From 12f54e0b9773c9c34654f684b3acfabdecf6cfe9 Mon Sep 17 00:00:00 2001 From: Donald Pinckney Date: Fri, 5 Feb 2016 01:50:25 -0800 Subject: [PATCH 0001/1679] Write initial structs for Graph --- Graph/Graph.playground/Contents.swift | 21 ++++++++++++++++++++ Graph/Graph.playground/contents.xcplayground | 4 ++++ Graph/Graph.playground/timeline.xctimeline | 6 ++++++ Graph/README.markdown | 6 ++++++ 4 files changed, 37 insertions(+) create mode 100644 Graph/Graph.playground/Contents.swift create mode 100644 Graph/Graph.playground/contents.xcplayground create mode 100644 Graph/Graph.playground/timeline.xctimeline create mode 100644 Graph/README.markdown diff --git a/Graph/Graph.playground/Contents.swift b/Graph/Graph.playground/Contents.swift new file mode 100644 index 000000000..c1b1dccbb --- /dev/null +++ b/Graph/Graph.playground/Contents.swift @@ -0,0 +1,21 @@ +public struct GraphEdge { + let from: GraphVertex + let to: GraphVertex + let weight: Int +} + +public struct GraphVertex { + public var data: T + private var edges: [GraphEdge] // This is a simple adjacency list, rather than matrix + + public mutating func connectTo(destinationVertex: GraphVertex, withWeight weight: Int = 0) { + edges.append(GraphEdge(from: self, to: destinationVertex, weight: weight)) + } + + public mutating func connectBetween(inout otherVertex: GraphVertex, withWeight weight: Int = 0) { + edges.append(GraphEdge(from: self, to: otherVertex, weight: weight)) + otherVertex.edges.append(GraphEdge(from: otherVertex, to: self, weight: weight)) + } +} + + diff --git a/Graph/Graph.playground/contents.xcplayground b/Graph/Graph.playground/contents.xcplayground new file mode 100644 index 000000000..5da2641c9 --- /dev/null +++ b/Graph/Graph.playground/contents.xcplayground @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Graph/Graph.playground/timeline.xctimeline b/Graph/Graph.playground/timeline.xctimeline new file mode 100644 index 000000000..bf468afec --- /dev/null +++ b/Graph/Graph.playground/timeline.xctimeline @@ -0,0 +1,6 @@ + + + + + diff --git a/Graph/README.markdown b/Graph/README.markdown new file mode 100644 index 000000000..30327f474 --- /dev/null +++ b/Graph/README.markdown @@ -0,0 +1,6 @@ +# Graph + +YAY Graphs! +TODO: Write stuff here. + +*Written by Donald Pinckney* From 7d1fbb8e28a4d107dbdd4e455332904c9d54ddc0 Mon Sep 17 00:00:00 2001 From: Donald Pinckney Date: Fri, 5 Feb 2016 01:58:00 -0800 Subject: [PATCH 0002/1679] Reformatted code to match style guide --- Graph/Graph.playground/Contents.swift | 49 +++++++++++++++++++-------- 1 file changed, 35 insertions(+), 14 deletions(-) diff --git a/Graph/Graph.playground/Contents.swift b/Graph/Graph.playground/Contents.swift index c1b1dccbb..1aa1d1444 100644 --- a/Graph/Graph.playground/Contents.swift +++ b/Graph/Graph.playground/Contents.swift @@ -1,21 +1,42 @@ public struct GraphEdge { - let from: GraphVertex - let to: GraphVertex - let weight: Int + let from: GraphVertex + let to: GraphVertex + let weight: Int } public struct GraphVertex { - public var data: T - private var edges: [GraphEdge] // This is a simple adjacency list, rather than matrix - - public mutating func connectTo(destinationVertex: GraphVertex, withWeight weight: Int = 0) { - edges.append(GraphEdge(from: self, to: destinationVertex, weight: weight)) - } - - public mutating func connectBetween(inout otherVertex: GraphVertex, withWeight weight: Int = 0) { - edges.append(GraphEdge(from: self, to: otherVertex, weight: weight)) - otherVertex.edges.append(GraphEdge(from: otherVertex, to: self, weight: weight)) - } + public var data: T + private var edges: [GraphEdge] = [] // This is a simple adjacency list, rather than matrix + + public init(data: T) { + self.data = data + } + + // Creates a directed edge self -----> dest + public mutating func connectTo(destinationVertex: GraphVertex, withWeight weight: Int = 0) { + edges.append(GraphEdge(from: self, to: destinationVertex, weight: weight)) + } + + // Creates an undirected edge by making 2 directed edges: self ----> other, and other ----> self + public mutating func connectBetween(inout otherVertex: GraphVertex, withWeight weight: Int = 0) { + edges.append(GraphEdge(from: self, to: otherVertex, weight: weight)) + otherVertex.edges.append(GraphEdge(from: otherVertex, to: self, weight: weight)) + } } + + +var v1 = GraphVertex(data: 1) +var v2 = GraphVertex(data: 2) +var v3 = GraphVertex(data: 3) +var v4 = GraphVertex(data: 4) + +// v1 ---> v2 ---> v3 ---> v4 +// ^ | +// | V +// -----------<------------| +v1.connectTo(v2) +v2.connectTo(v3) +v3.connectTo(v4) +v4.connectTo(v1) From 10154dc6e05c1c4586c6600708ce6ba69e22518f Mon Sep 17 00:00:00 2001 From: Donald Pinckney Date: Fri, 5 Feb 2016 02:39:45 -0800 Subject: [PATCH 0003/1679] Add adjacency matrix implementation --- .../Contents.swift | 0 .../contents.xcplayground | 0 .../timeline.xctimeline | 0 .../Contents.swift | 59 +++++++++++++++++++ .../contents.xcplayground | 4 ++ .../timeline.xctimeline | 6 ++ 6 files changed, 69 insertions(+) rename Graph/{Graph.playground => Graph Adjacency List.playground}/Contents.swift (100%) rename Graph/{Graph.playground => Graph Adjacency List.playground}/contents.xcplayground (100%) rename Graph/{Graph.playground => Graph Adjacency List.playground}/timeline.xctimeline (100%) create mode 100644 Graph/Graph Adjacency Matrix.playground/Contents.swift create mode 100644 Graph/Graph Adjacency Matrix.playground/contents.xcplayground create mode 100644 Graph/Graph Adjacency Matrix.playground/timeline.xctimeline diff --git a/Graph/Graph.playground/Contents.swift b/Graph/Graph Adjacency List.playground/Contents.swift similarity index 100% rename from Graph/Graph.playground/Contents.swift rename to Graph/Graph Adjacency List.playground/Contents.swift diff --git a/Graph/Graph.playground/contents.xcplayground b/Graph/Graph Adjacency List.playground/contents.xcplayground similarity index 100% rename from Graph/Graph.playground/contents.xcplayground rename to Graph/Graph Adjacency List.playground/contents.xcplayground diff --git a/Graph/Graph.playground/timeline.xctimeline b/Graph/Graph Adjacency List.playground/timeline.xctimeline similarity index 100% rename from Graph/Graph.playground/timeline.xctimeline rename to Graph/Graph Adjacency List.playground/timeline.xctimeline diff --git a/Graph/Graph Adjacency Matrix.playground/Contents.swift b/Graph/Graph Adjacency Matrix.playground/Contents.swift new file mode 100644 index 000000000..2d634e0c0 --- /dev/null +++ b/Graph/Graph Adjacency Matrix.playground/Contents.swift @@ -0,0 +1,59 @@ + + +public struct GraphVertex { + public var data: T + let uniqueID: Int +} + +public struct Graph { + + private var adjacencyMatrix: [[Int?]] = [] // row-major + + public init() { } // Silence default constructor + + public mutating func createVertex(data: T) -> GraphVertex { + let vertex = GraphVertex(data: data, uniqueID: adjacencyMatrix.count) + + // Expand each existing row to the right one column + for i in 0.. dest. Represented by M[source][dest] = weight + public mutating func connect(sourceVertex: GraphVertex, toDestinationVertex: GraphVertex, withWeight weight: Int = 0) { + adjacencyMatrix[sourceVertex.uniqueID][toDestinationVertex.uniqueID] = weight + } + + // Creates an undirected edge by making 2 directed edges: some ----> other, and other ----> some + public mutating func connect(someVertex: GraphVertex, withVertex: GraphVertex, withWeight weight: Int = 0) { + adjacencyMatrix[someVertex.uniqueID][withVertex.uniqueID] = weight + adjacencyMatrix[withVertex.uniqueID][someVertex.uniqueID] = weight + + } +} + + + + +var graph = Graph() +let v1 = graph.createVertex(1) +let v2 = graph.createVertex(2) +let v3 = graph.createVertex(3) +let v4 = graph.createVertex(4) + +// v1 ---> v2 ---> v3 ---> v4 +// ^ | +// | V +// -----------<------------| + +graph.connect(v1, toDestinationVertex: v2) +graph.connect(v2, toDestinationVertex: v3) +graph.connect(v3, toDestinationVertex: v4) +graph.connect(v4, toDestinationVertex: v1) diff --git a/Graph/Graph Adjacency Matrix.playground/contents.xcplayground b/Graph/Graph Adjacency Matrix.playground/contents.xcplayground new file mode 100644 index 000000000..5da2641c9 --- /dev/null +++ b/Graph/Graph Adjacency Matrix.playground/contents.xcplayground @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Graph/Graph Adjacency Matrix.playground/timeline.xctimeline b/Graph/Graph Adjacency Matrix.playground/timeline.xctimeline new file mode 100644 index 000000000..bf468afec --- /dev/null +++ b/Graph/Graph Adjacency Matrix.playground/timeline.xctimeline @@ -0,0 +1,6 @@ + + + + + From ebc45083d18197c3826cd72fa9bd07e0bec1b32c Mon Sep 17 00:00:00 2001 From: Donald Pinckney Date: Fri, 5 Feb 2016 21:43:28 -0800 Subject: [PATCH 0004/1679] Combine playgrounds into 1 playground with pages --- .../contents.xcplayground | 4 -- .../Contents.swift | 29 ++++++-- .../timeline.xctimeline | 0 .../Contents.swift | 71 +++++++++++++++++++ .../timeline.xctimeline | 6 ++ Graph/Graph.playground/contents.xcplayground | 7 ++ 6 files changed, 106 insertions(+), 11 deletions(-) delete mode 100644 Graph/Graph Adjacency List.playground/contents.xcplayground rename Graph/{Graph Adjacency List.playground => Graph.playground/Pages/Adjacency List.xcplaygroundpage}/Contents.swift (58%) rename Graph/{Graph Adjacency List.playground => Graph.playground/Pages/Adjacency List.xcplaygroundpage}/timeline.xctimeline (100%) create mode 100644 Graph/Graph.playground/Pages/Adjacency Matrix.xcplaygroundpage/Contents.swift create mode 100644 Graph/Graph.playground/Pages/Adjacency Matrix.xcplaygroundpage/timeline.xctimeline create mode 100644 Graph/Graph.playground/contents.xcplayground diff --git a/Graph/Graph Adjacency List.playground/contents.xcplayground b/Graph/Graph Adjacency List.playground/contents.xcplayground deleted file mode 100644 index 5da2641c9..000000000 --- a/Graph/Graph Adjacency List.playground/contents.xcplayground +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/Graph/Graph Adjacency List.playground/Contents.swift b/Graph/Graph.playground/Pages/Adjacency List.xcplaygroundpage/Contents.swift similarity index 58% rename from Graph/Graph Adjacency List.playground/Contents.swift rename to Graph/Graph.playground/Pages/Adjacency List.xcplaygroundpage/Contents.swift index 1aa1d1444..17c0514ea 100644 --- a/Graph/Graph Adjacency List.playground/Contents.swift +++ b/Graph/Graph.playground/Pages/Adjacency List.xcplaygroundpage/Contents.swift @@ -1,24 +1,34 @@ +/* + +A graph implementation, using an adjacency list. + +In an adjacency list implementation, each vertex stores an array of edges, indicating to which vertices it has an edge (note the directionality). The edge stores the source and destination vertices, as well as a weight. + +Connected vertices in this implementation is O(1). + +*/ + public struct GraphEdge { - let from: GraphVertex - let to: GraphVertex - let weight: Int + public let from: GraphVertex + public let to: GraphVertex + public let weight: Double } public struct GraphVertex { public var data: T - private var edges: [GraphEdge] = [] // This is a simple adjacency list, rather than matrix + public private(set) var edges: [GraphEdge] = [] // This is a simple adjacency list, rather than matrix public init(data: T) { self.data = data } // Creates a directed edge self -----> dest - public mutating func connectTo(destinationVertex: GraphVertex, withWeight weight: Int = 0) { + public mutating func connectTo(destinationVertex: GraphVertex, withWeight weight: Double = 0) { edges.append(GraphEdge(from: self, to: destinationVertex, weight: weight)) } // Creates an undirected edge by making 2 directed edges: self ----> other, and other ----> self - public mutating func connectBetween(inout otherVertex: GraphVertex, withWeight weight: Int = 0) { + public mutating func connectBetween(inout otherVertex: GraphVertex, withWeight weight: Double = 0) { edges.append(GraphEdge(from: self, to: otherVertex, weight: weight)) otherVertex.edges.append(GraphEdge(from: otherVertex, to: self, weight: weight)) } @@ -26,17 +36,22 @@ public struct GraphVertex { - +// Create 4 separate vertices var v1 = GraphVertex(data: 1) var v2 = GraphVertex(data: 2) var v3 = GraphVertex(data: 3) var v4 = GraphVertex(data: 4) +// Setup a cycle like so: // v1 ---> v2 ---> v3 ---> v4 // ^ | // | V // -----------<------------| + v1.connectTo(v2) v2.connectTo(v3) v3.connectTo(v4) v4.connectTo(v1) + + +//: [Next](@next) diff --git a/Graph/Graph Adjacency List.playground/timeline.xctimeline b/Graph/Graph.playground/Pages/Adjacency List.xcplaygroundpage/timeline.xctimeline similarity index 100% rename from Graph/Graph Adjacency List.playground/timeline.xctimeline rename to Graph/Graph.playground/Pages/Adjacency List.xcplaygroundpage/timeline.xctimeline diff --git a/Graph/Graph.playground/Pages/Adjacency Matrix.xcplaygroundpage/Contents.swift b/Graph/Graph.playground/Pages/Adjacency Matrix.xcplaygroundpage/Contents.swift new file mode 100644 index 000000000..4fffc4d40 --- /dev/null +++ b/Graph/Graph.playground/Pages/Adjacency Matrix.xcplaygroundpage/Contents.swift @@ -0,0 +1,71 @@ +//: [Previous](@previous) +/* + +A graph implementation, using an adjacency matrix. + +In an adjacency matrix implementation, each vertex is associated with an index from 0.. { + public var data: T + private let uniqueID: Int +} + +public struct Graph { + + // nil entries are used to mark that two vertices are NOT connected. + private var adjacencyMatrix: [[Double?]] = [] + + public init() { } + + public mutating func createVertex(data: T) -> GraphVertex { + let vertex = GraphVertex(data: data, uniqueID: adjacencyMatrix.count) + + // Expand each existing row to the right one column + for i in 0.. dest. Represented by M[source][dest] = weight + public mutating func connect(sourceVertex: GraphVertex, toDestinationVertex: GraphVertex, withWeight weight: Double = 0) { + adjacencyMatrix[sourceVertex.uniqueID][toDestinationVertex.uniqueID] = weight + } + + // Creates an undirected edge by making 2 directed edges: some ----> other, and other ----> some + public mutating func connect(someVertex: GraphVertex, withVertex: GraphVertex, withWeight weight: Double = 0) { + adjacencyMatrix[someVertex.uniqueID][withVertex.uniqueID] = weight + adjacencyMatrix[withVertex.uniqueID][someVertex.uniqueID] = weight + + } +} + + + +// Create 4 separate vertices +var graph = Graph() +let v1 = graph.createVertex(1) +let v2 = graph.createVertex(2) +let v3 = graph.createVertex(3) +let v4 = graph.createVertex(4) + +// Setup a cycle like so: +// v1 ---> v2 ---> v3 ---> v4 +// ^ | +// | V +// -----------<------------| + +graph.connect(v1, toDestinationVertex: v2) +graph.connect(v2, toDestinationVertex: v3) +graph.connect(v3, toDestinationVertex: v4) +graph.connect(v4, toDestinationVertex: v1) diff --git a/Graph/Graph.playground/Pages/Adjacency Matrix.xcplaygroundpage/timeline.xctimeline b/Graph/Graph.playground/Pages/Adjacency Matrix.xcplaygroundpage/timeline.xctimeline new file mode 100644 index 000000000..bf468afec --- /dev/null +++ b/Graph/Graph.playground/Pages/Adjacency Matrix.xcplaygroundpage/timeline.xctimeline @@ -0,0 +1,6 @@ + + + + + diff --git a/Graph/Graph.playground/contents.xcplayground b/Graph/Graph.playground/contents.xcplayground new file mode 100644 index 000000000..32b5a98b9 --- /dev/null +++ b/Graph/Graph.playground/contents.xcplayground @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file From 743b2f640d79e8c602e7dbc7dd1330b10f36cd4f Mon Sep 17 00:00:00 2001 From: Artur Antonov Date: Tue, 9 Feb 2016 21:14:11 +0300 Subject: [PATCH 0005/1679] Add Union-Find data structure implementation --- UnionFindDS/README.markdown | 3 + .../UnioinFindDS.playground/Contents.swift | 106 ++++++++++++++++++ .../contents.xcplayground | 4 + .../timeline.xctimeline | 6 + UnionFindDS/UnionFindDS.swift | 51 +++++++++ 5 files changed, 170 insertions(+) create mode 100644 UnionFindDS/README.markdown create mode 100644 UnionFindDS/UnioinFindDS.playground/Contents.swift create mode 100644 UnionFindDS/UnioinFindDS.playground/contents.xcplayground create mode 100644 UnionFindDS/UnioinFindDS.playground/timeline.xctimeline create mode 100644 UnionFindDS/UnionFindDS.swift diff --git a/UnionFindDS/README.markdown b/UnionFindDS/README.markdown new file mode 100644 index 000000000..5ae638efc --- /dev/null +++ b/UnionFindDS/README.markdown @@ -0,0 +1,3 @@ +# Union Find Data Structure + +TODO diff --git a/UnionFindDS/UnioinFindDS.playground/Contents.swift b/UnionFindDS/UnioinFindDS.playground/Contents.swift new file mode 100644 index 000000000..cb59acdbc --- /dev/null +++ b/UnionFindDS/UnioinFindDS.playground/Contents.swift @@ -0,0 +1,106 @@ +//: Playground - noun: a place where people can play + +public class UnionFindDS { + + private var index = [T:Int]() + private var parent = [Int]() + private var size = [Int]() + + + public func addSetWithElement(element: T) { + index[element] = parent.count + parent.append(parent.count) + size.append(1) + } + + private func findSetByIndexOfElement(index: Int) -> Int { + if parent[index] == index { + return index + } else { + parent[index] = findSetByIndexOfElement(parent[index]) + return parent[index] + } + } + + public func findSetOfElement(element: T) -> Int { + let indexOfElement = index[element]! + return findSetByIndexOfElement(indexOfElement) + } + + public func unionSetsWithElement(firstElement: T, andSecondElement secondElement: T) { + let firstSet = findSetOfElement(firstElement) + let secondSet = findSetOfElement(secondElement) + if (firstSet != secondSet) { + if (size[firstSet] < size[secondSet]) { + parent[firstSet] = secondSet; + size[secondSet] += size[firstSet] + } else { + parent[secondSet] = firstSet; + size[firstSet] += size[secondSet] + } + } + } +} + + +let dsu = UnionFindDS() + +for i in 1...10 { + dsu.addSetWithElement(i) +} +// now our dsu contains 10 independent sets + +// let's divide our numbers into two sets by divisibility by 2 +for i in 3...10 { + if i % 2 == 0 { + dsu.unionSetsWithElement(2, andSecondElement: i) + } else { + dsu.unionSetsWithElement(1, andSecondElement: i) + } +} + +// check our division +print(dsu.findSetOfElement(2) == dsu.findSetOfElement(4)) +print(dsu.findSetOfElement(4) == dsu.findSetOfElement(6)) +print(dsu.findSetOfElement(6) == dsu.findSetOfElement(8)) +print(dsu.findSetOfElement(8) == dsu.findSetOfElement(10)) + +print(dsu.findSetOfElement(1) == dsu.findSetOfElement(3)) +print(dsu.findSetOfElement(3) == dsu.findSetOfElement(5)) +print(dsu.findSetOfElement(5) == dsu.findSetOfElement(7)) +print(dsu.findSetOfElement(7) == dsu.findSetOfElement(9)) + +print(dsu.findSetOfElement(8) == dsu.findSetOfElement(9)) +print(dsu.findSetOfElement(4) == dsu.findSetOfElement(3)) + + +let dsuForStrings = UnionFindDS() +let words = ["all", "border", "boy", "afternoon", "amazing", "awesome", "best"] + +dsuForStrings.addSetWithElement("a") +dsuForStrings.addSetWithElement("b") + +// In that example we divide strings by its first letter +for word in words { + dsuForStrings.addSetWithElement(word) + if word.hasPrefix("a") { + dsuForStrings.unionSetsWithElement("a", andSecondElement: word) + } else if word.hasPrefix("b") { + dsuForStrings.unionSetsWithElement("b", andSecondElement: word) + } +} + +print(dsuForStrings.findSetOfElement("a") == dsuForStrings.findSetOfElement("all")) +print(dsuForStrings.findSetOfElement("all") == dsuForStrings.findSetOfElement("awesome")) +print(dsuForStrings.findSetOfElement("amazing") == dsuForStrings.findSetOfElement("afternoon")) + +print(dsuForStrings.findSetOfElement("b") == dsuForStrings.findSetOfElement("boy")) +print(dsuForStrings.findSetOfElement("best") == dsuForStrings.findSetOfElement("boy")) +print(dsuForStrings.findSetOfElement("border") == dsuForStrings.findSetOfElement("best")) + +print(dsuForStrings.findSetOfElement("amazing") == dsuForStrings.findSetOfElement("boy")) +print(dsuForStrings.findSetOfElement("all") == dsuForStrings.findSetOfElement("border")) + + + + diff --git a/UnionFindDS/UnioinFindDS.playground/contents.xcplayground b/UnionFindDS/UnioinFindDS.playground/contents.xcplayground new file mode 100644 index 000000000..06828af92 --- /dev/null +++ b/UnionFindDS/UnioinFindDS.playground/contents.xcplayground @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/UnionFindDS/UnioinFindDS.playground/timeline.xctimeline b/UnionFindDS/UnioinFindDS.playground/timeline.xctimeline new file mode 100644 index 000000000..bf468afec --- /dev/null +++ b/UnionFindDS/UnioinFindDS.playground/timeline.xctimeline @@ -0,0 +1,6 @@ + + + + + diff --git a/UnionFindDS/UnionFindDS.swift b/UnionFindDS/UnionFindDS.swift new file mode 100644 index 000000000..0e3a982f2 --- /dev/null +++ b/UnionFindDS/UnionFindDS.swift @@ -0,0 +1,51 @@ +/* + Union-Find Data Structure + + Performance: + adding new set is almost O(1) + finding set of element is almost O(1) + union sets is almost O(1) +*/ + + +public class UnionFindDS { + + private var index = [T:Int]() + private var parent = [Int]() + private var size = [Int]() + + + public func addSetWithElement(element: T) { + index[element] = parent.count + parent.append(parent.count) + size.append(1) + } + + private func findSetByIndexOfElement(index: Int) -> Int { + if parent[index] == index { + return index + } else { + parent[index] = findSetByIndexOfElement(parent[index]) + return parent[index] + } + } + + public func findSetOfElement(element: T) -> Int { + let indexOfElement = index[element]! + return findSetByIndexOfElement(indexOfElement) + } + + public func unionSetsWithElement(firstElement: T, andSecondElement secondElement: T) { + let firstSet = findSetOfElement(firstElement) + let secondSet = findSetOfElement(secondElement) + if (firstSet != secondSet) { + if (size[firstSet] < size[secondSet]) { + parent[firstSet] = secondSet; + size[secondSet] += size[firstSet] + } else { + parent[secondSet] = firstSet; + size[firstSet] += size[secondSet] + } + } + } +} \ No newline at end of file From 5d262b9eef21eca8c58bdac34205804d8f350ffb Mon Sep 17 00:00:00 2001 From: Artur Antonov Date: Wed, 10 Feb 2016 23:51:01 +0300 Subject: [PATCH 0006/1679] Rename UnionFindDS to UnionFind and make it struct --- {UnionFindDS => UnionFind}/README.markdown | 0 .../UnioinFind.playground}/Contents.swift | 14 +++++++------- .../UnioinFind.playground}/contents.xcplayground | 0 .../UnioinFind.playground}/timeline.xctimeline | 0 .../UnionFindDS.swift => UnionFind/UnionFind.swift | 10 +++++----- 5 files changed, 12 insertions(+), 12 deletions(-) rename {UnionFindDS => UnionFind}/README.markdown (100%) rename {UnionFindDS/UnioinFindDS.playground => UnionFind/UnioinFind.playground}/Contents.swift (88%) rename {UnionFindDS/UnioinFindDS.playground => UnionFind/UnioinFind.playground}/contents.xcplayground (100%) rename {UnionFindDS/UnioinFindDS.playground => UnionFind/UnioinFind.playground}/timeline.xctimeline (100%) rename UnionFindDS/UnionFindDS.swift => UnionFind/UnionFind.swift (75%) diff --git a/UnionFindDS/README.markdown b/UnionFind/README.markdown similarity index 100% rename from UnionFindDS/README.markdown rename to UnionFind/README.markdown diff --git a/UnionFindDS/UnioinFindDS.playground/Contents.swift b/UnionFind/UnioinFind.playground/Contents.swift similarity index 88% rename from UnionFindDS/UnioinFindDS.playground/Contents.swift rename to UnionFind/UnioinFind.playground/Contents.swift index cb59acdbc..2b2a68aea 100644 --- a/UnionFindDS/UnioinFindDS.playground/Contents.swift +++ b/UnionFind/UnioinFind.playground/Contents.swift @@ -1,19 +1,19 @@ //: Playground - noun: a place where people can play -public class UnionFindDS { +public struct UnionFind { private var index = [T:Int]() private var parent = [Int]() private var size = [Int]() - public func addSetWithElement(element: T) { + public mutating func addSetWithElement(element: T) { index[element] = parent.count parent.append(parent.count) size.append(1) } - private func findSetByIndexOfElement(index: Int) -> Int { + private mutating func findSetByIndexOfElement(index: Int) -> Int { if parent[index] == index { return index } else { @@ -22,12 +22,12 @@ public class UnionFindDS { } } - public func findSetOfElement(element: T) -> Int { + public mutating func findSetOfElement(element: T) -> Int { let indexOfElement = index[element]! return findSetByIndexOfElement(indexOfElement) } - public func unionSetsWithElement(firstElement: T, andSecondElement secondElement: T) { + public mutating func unionSetsWithElement(firstElement: T, andSecondElement secondElement: T) { let firstSet = findSetOfElement(firstElement) let secondSet = findSetOfElement(secondElement) if (firstSet != secondSet) { @@ -43,7 +43,7 @@ public class UnionFindDS { } -let dsu = UnionFindDS() +var dsu = UnionFind() for i in 1...10 { dsu.addSetWithElement(i) @@ -74,7 +74,7 @@ print(dsu.findSetOfElement(8) == dsu.findSetOfElement(9)) print(dsu.findSetOfElement(4) == dsu.findSetOfElement(3)) -let dsuForStrings = UnionFindDS() +var dsuForStrings = UnionFind() let words = ["all", "border", "boy", "afternoon", "amazing", "awesome", "best"] dsuForStrings.addSetWithElement("a") diff --git a/UnionFindDS/UnioinFindDS.playground/contents.xcplayground b/UnionFind/UnioinFind.playground/contents.xcplayground similarity index 100% rename from UnionFindDS/UnioinFindDS.playground/contents.xcplayground rename to UnionFind/UnioinFind.playground/contents.xcplayground diff --git a/UnionFindDS/UnioinFindDS.playground/timeline.xctimeline b/UnionFind/UnioinFind.playground/timeline.xctimeline similarity index 100% rename from UnionFindDS/UnioinFindDS.playground/timeline.xctimeline rename to UnionFind/UnioinFind.playground/timeline.xctimeline diff --git a/UnionFindDS/UnionFindDS.swift b/UnionFind/UnionFind.swift similarity index 75% rename from UnionFindDS/UnionFindDS.swift rename to UnionFind/UnionFind.swift index 0e3a982f2..617d20951 100644 --- a/UnionFindDS/UnionFindDS.swift +++ b/UnionFind/UnionFind.swift @@ -8,20 +8,20 @@ */ -public class UnionFindDS { +public struct UnionFind { private var index = [T:Int]() private var parent = [Int]() private var size = [Int]() - public func addSetWithElement(element: T) { + public mutating func addSetWithElement(element: T) { index[element] = parent.count parent.append(parent.count) size.append(1) } - private func findSetByIndexOfElement(index: Int) -> Int { + private mutating func findSetByIndexOfElement(index: Int) -> Int { if parent[index] == index { return index } else { @@ -30,12 +30,12 @@ public class UnionFindDS { } } - public func findSetOfElement(element: T) -> Int { + public mutating func findSetOfElement(element: T) -> Int { let indexOfElement = index[element]! return findSetByIndexOfElement(indexOfElement) } - public func unionSetsWithElement(firstElement: T, andSecondElement secondElement: T) { + public mutating func unionSetsWithElement(firstElement: T, andSecondElement secondElement: T) { let firstSet = findSetOfElement(firstElement) let secondSet = findSetOfElement(secondElement) if (firstSet != secondSet) { From 1ff10bc01972bc57f3313f2d721b7212e965c6f8 Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Thu, 11 Feb 2016 13:06:09 +1300 Subject: [PATCH 0007/1679] Adding placeholder readme for BFS --- Breadth-First Search/README.markdown | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 Breadth-First Search/README.markdown diff --git a/Breadth-First Search/README.markdown b/Breadth-First Search/README.markdown new file mode 100644 index 000000000..c1d74ec99 --- /dev/null +++ b/Breadth-First Search/README.markdown @@ -0,0 +1,3 @@ +# Breadth-First Search + +TODO From b3bb50a9ae6b18058aa9cc0045c0967fb9f3d423 Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Thu, 11 Feb 2016 13:07:36 +1300 Subject: [PATCH 0008/1679] Linking to BFS from main readme --- README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.markdown b/README.markdown index 1b5ff2a85..719b1bb7c 100644 --- a/README.markdown +++ b/README.markdown @@ -157,7 +157,7 @@ Most of the time using just the built-in `Array`, `Dictionary`, and `Set` types ### Graphs - Graph -- Breadth-First Search (BFS) +- [Breadth-First Search (BFS)](Breadth-First Search/) - Depth-First Search (DFS) - Shortest Path - Minimum Spanning Tree From 1ce7af4778c5ff36036f1fd54d27bca8ae51f721 Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Thu, 11 Feb 2016 22:08:39 +1300 Subject: [PATCH 0009/1679] Added titles in readme and added draft BFS playground --- .../Contents.swift | 113 ++++++++++++++++++ .../contents.xcplayground | 4 + .../timeline.xctimeline | 6 + Breadth-First Search/Images/Animated_BFS.gif | Bin 0 -> 33276 bytes Breadth-First Search/README.markdown | 20 +++- 5 files changed, 142 insertions(+), 1 deletion(-) create mode 100644 Breadth-First Search/BreadthFirstSearch.playground/Contents.swift create mode 100644 Breadth-First Search/BreadthFirstSearch.playground/contents.xcplayground create mode 100644 Breadth-First Search/BreadthFirstSearch.playground/timeline.xctimeline create mode 100644 Breadth-First Search/Images/Animated_BFS.gif diff --git a/Breadth-First Search/BreadthFirstSearch.playground/Contents.swift b/Breadth-First Search/BreadthFirstSearch.playground/Contents.swift new file mode 100644 index 000000000..706cb2b97 --- /dev/null +++ b/Breadth-First Search/BreadthFirstSearch.playground/Contents.swift @@ -0,0 +1,113 @@ +public class Graph { + private var canvas: Array + + init() { + canvas = Array() + } + + func addNode(key: String) -> Node { + let childNode: Node = Node(key: key) + canvas.append(childNode) + return childNode + } + + func addEdge(source: Node, neighbor: Node) { + let newEdge = Edge(neighbor: neighbor) + newEdge.neighbor = neighbor + source.neighbors.append(newEdge) + } +} + +public class Node { + var key: String + var neighbors: Array + + init(key: String) { + self.key = key + self.neighbors = Array() + } +} + +public class Edge { + var neighbor: Node + init(neighbor: Node) { + self.neighbor = neighbor + } +} + +public class Queue { + private var top: QueueNode! = QueueNode() + + func enQueue(key: T) { + if (top == nil) { + top = QueueNode() + } + + if (top.key == nil) { + top.key = key; + return + } + + let childToUse: QueueNode = QueueNode() + var current: QueueNode = top + while (current.next != nil) { + current = current.next! + } + + childToUse.key = key; + current.next = childToUse; + } + + func deQueue() -> QueueNode { + let itemToDeQueue = top + top = itemToDeQueue.next + return itemToDeQueue + } + + var isEmpty: Bool { + get { return top == nil } + } +} + +class QueueNode { + var key: T? + var next: QueueNode? +} + +func breadthFirstSearch(graph: Graph, root: Node) { + + let q = Queue() + q.enQueue(root) + print(root.key) + + while !q.isEmpty { + let current = q.deQueue() + for edge in current.key!.neighbors { + let neighbor = edge.neighbor + q.enQueue(neighbor) + + print(neighbor.key) + } + } +} + +let graph = Graph() + +let nodeA = graph.addNode("a") +let nodeB = graph.addNode("b") +let nodeC = graph.addNode("c") +let nodeD = graph.addNode("d") +let nodeE = graph.addNode("e") +let nodeF = graph.addNode("f") +let nodeG = graph.addNode("g") +let nodeH = graph.addNode("h") + +graph.addEdge(nodeA, neighbor: nodeB) +graph.addEdge(nodeA, neighbor: nodeC) +graph.addEdge(nodeB, neighbor: nodeD) +graph.addEdge(nodeB, neighbor: nodeE) +graph.addEdge(nodeC, neighbor: nodeF) +graph.addEdge(nodeC, neighbor: nodeG) +graph.addEdge(nodeE, neighbor: nodeH) + +breadthFirstSearch(graph, root: nodeA) diff --git a/Breadth-First Search/BreadthFirstSearch.playground/contents.xcplayground b/Breadth-First Search/BreadthFirstSearch.playground/contents.xcplayground new file mode 100644 index 000000000..5da2641c9 --- /dev/null +++ b/Breadth-First Search/BreadthFirstSearch.playground/contents.xcplayground @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Breadth-First Search/BreadthFirstSearch.playground/timeline.xctimeline b/Breadth-First Search/BreadthFirstSearch.playground/timeline.xctimeline new file mode 100644 index 000000000..bf468afec --- /dev/null +++ b/Breadth-First Search/BreadthFirstSearch.playground/timeline.xctimeline @@ -0,0 +1,6 @@ + + + + + diff --git a/Breadth-First Search/Images/Animated_BFS.gif b/Breadth-First Search/Images/Animated_BFS.gif new file mode 100644 index 0000000000000000000000000000000000000000..d8fe07cbc40a0a19534b597e123bf803de42f205 GIT binary patch literal 33276 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 VN-uB@0x#iI)bv$Ep$#Yh{{eHl({ca+ literal 0 HcmV?d00001 diff --git a/Breadth-First Search/README.markdown b/Breadth-First Search/README.markdown index c1d74ec99..7f5a314e0 100644 --- a/Breadth-First Search/README.markdown +++ b/Breadth-First Search/README.markdown @@ -1,3 +1,21 @@ # Breadth-First Search -TODO +Breadth-first search (BFS) is an algorithm for traversing or searching tree or graph data structures. It starts at the tree root and explores the neighbor nodes first, before moving to the next level neighbors. + +## Animated example + +![Animated example of a breadth-first search](Images/Animated_BFS.gif) + +## The code + +```swift +func breadthFirstSearch() { + +} +``` + +## See also + +[Breadth-first search on Wikipedia](https://en.wikipedia.org/wiki/Breadth-first_search) + +*Written by [Chris Pilcher](https://github.com/chris-pilcher)* From d49eb998a664dcc060084bf1d92086efd0d3465a Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Thu, 11 Feb 2016 22:47:00 +1300 Subject: [PATCH 0010/1679] Renaming variables in BFS playground --- .../Contents.swift | 83 ++++++++++--------- Breadth-First Search/README.markdown | 2 +- 2 files changed, 43 insertions(+), 42 deletions(-) diff --git a/Breadth-First Search/BreadthFirstSearch.playground/Contents.swift b/Breadth-First Search/BreadthFirstSearch.playground/Contents.swift index 706cb2b97..a6318d8c9 100644 --- a/Breadth-First Search/BreadthFirstSearch.playground/Contents.swift +++ b/Breadth-First Search/BreadthFirstSearch.playground/Contents.swift @@ -1,67 +1,68 @@ -public class Graph { - private var canvas: Array +class Graph { + private var nodes = [Node]() - init() { - canvas = Array() - } - - func addNode(key: String) -> Node { - let childNode: Node = Node(key: key) - canvas.append(childNode) - return childNode + func addNode(label: String) -> Node { + let node = Node(label: label) + nodes.append(node) + return node } func addEdge(source: Node, neighbor: Node) { - let newEdge = Edge(neighbor: neighbor) - newEdge.neighbor = neighbor - source.neighbors.append(newEdge) + let edge = Edge(neighbor: neighbor) + edge.neighbor = neighbor + source.neighbors.append(edge) } } -public class Node { - var key: String - var neighbors: Array +class Node { + private var label: String + private var neighbors: [Edge] - init(key: String) { - self.key = key - self.neighbors = Array() + init(label: String) { + self.label = label + neighbors = [] } } -public class Edge { - var neighbor: Node +class Edge { + private var neighbor: Node + init(neighbor: Node) { self.neighbor = neighbor } } -public class Queue { - private var top: QueueNode! = QueueNode() +class Queue { + private var top: QueueNode! - func enQueue(key: T) { + func enqueue(item: T) { if (top == nil) { top = QueueNode() } - if (top.key == nil) { - top.key = key; + if (top.item == nil) { + top.item = item; return } - let childToUse: QueueNode = QueueNode() + let childToUse = QueueNode() var current: QueueNode = top - while (current.next != nil) { + while current.next != nil { current = current.next! } - childToUse.key = key; + childToUse.item = item; current.next = childToUse; } - func deQueue() -> QueueNode { - let itemToDeQueue = top - top = itemToDeQueue.next - return itemToDeQueue + func dequeue() -> QueueNode? { + guard !isEmpty else { + return nil + } + + let itemToDequeue = top + top = itemToDequeue.next + return itemToDequeue } var isEmpty: Bool { @@ -70,23 +71,23 @@ public class Queue { } class QueueNode { - var key: T? + var item: T? var next: QueueNode? } func breadthFirstSearch(graph: Graph, root: Node) { + print("Performing breadth-first search on '\(root.label)'") let q = Queue() - q.enQueue(root) - print(root.key) + q.enqueue(root) while !q.isEmpty { - let current = q.deQueue() - for edge in current.key!.neighbors { - let neighbor = edge.neighbor - q.enQueue(neighbor) + let current = q.dequeue() + for edge in current!.item!.neighbors { + let neighborNode = edge.neighbor + q.enqueue(neighborNode) - print(neighbor.key) + print(neighborNode.label) } } } diff --git a/Breadth-First Search/README.markdown b/Breadth-First Search/README.markdown index 7f5a314e0..b1278df8b 100644 --- a/Breadth-First Search/README.markdown +++ b/Breadth-First Search/README.markdown @@ -1,6 +1,6 @@ # Breadth-First Search -Breadth-first search (BFS) is an algorithm for traversing or searching tree or graph data structures. It starts at the tree root and explores the neighbor nodes first, before moving to the next level neighbors. +Breadth-first search (BFS) is an algorithm for traversing or searching tree or graph data structures. It starts at the tree root and explores the neighbor nodes first, before moving to the next level neighbors. ## Animated example From 55d329deddfb6a4ec491edaf54905794e98fbe40 Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Thu, 11 Feb 2016 23:26:02 +1300 Subject: [PATCH 0011/1679] Adding code to readme --- Breadth-First Search/README.markdown | 145 ++++++++++++++++++++++++++- 1 file changed, 144 insertions(+), 1 deletion(-) diff --git a/Breadth-First Search/README.markdown b/Breadth-First Search/README.markdown index b1278df8b..bbb7fa376 100644 --- a/Breadth-First Search/README.markdown +++ b/Breadth-First Search/README.markdown @@ -8,14 +8,157 @@ Breadth-first search (BFS) is an algorithm for traversing or searching tree or g ## The code +Before we can code the breadth-first search algorithm we need to: +* Create an implementation of the graph +* Create an implementation of a queue + +### Graph implementation + +A graph is made up of nodes and edges. In the [animated example](#animated-example) the nodes are represented as circles and the edges are represented as lines. + +Implementation of a node: +```swift +class Node { + private var label: String + private var neighbors: [Edge] + + init(label: String) { + self.label = label + neighbors = [] + } +} +``` + +Implementation of an edge: ```swift -func breadthFirstSearch() { +class Edge { + private var neighbor: Node + init(neighbor: Node) { + self.neighbor = neighbor + } } ``` +Implementation of a graph: +```swift +class Graph { + private var nodes = [Node]() + + func addNode(label: String) -> Node { + let node = Node(label: label) + nodes.append(node) + return node + } + + func addEdge(source: Node, neighbor: Node) { + let edge = Edge(neighbor: neighbor) + edge.neighbor = neighbor + source.neighbors.append(edge) + } +} +``` + +### Queue implementation + +Implementation of simple queue: + +```swift +class Queue { + private var top: QueueNode! + + func enqueue(item: T) { + if (top == nil) { + top = QueueNode() + } + + if (top.item == nil) { + top.item = item; + return + } + + let childToUse = QueueNode() + var current: QueueNode = top + while current.next != nil { + current = current.next! + } + + childToUse.item = item; + current.next = childToUse; + } + + func dequeue() -> QueueNode? { + guard !isEmpty else { + return nil + } + + let itemToDequeue = top + top = itemToDequeue.next + return itemToDequeue + } + + var isEmpty: Bool { + get { return top == nil } + } +} + +class QueueNode { + var item: T? + var next: QueueNode? +} +``` + +### Breadth-first search algorithm + +Simple implementation of breadth-first search using queues: +```swift +func breadthFirstSearch(graph: Graph, root: Node) { + print("Performing breadth-first search on '\(root.label)'") + + let q = Queue() + q.enqueue(root) + + while !q.isEmpty { + let current = q.dequeue() + for edge in current!.item!.neighbors { + let neighborNode = edge.neighbor + q.enqueue(neighborNode) + + print(neighborNode.label) + } + } +} +``` + +Put this code in a playground and test it like so: +```swift +let graph = Graph() // Representing the graph from the animated example + +let nodeA = graph.addNode("a") +let nodeB = graph.addNode("b") +let nodeC = graph.addNode("c") +let nodeD = graph.addNode("d") +let nodeE = graph.addNode("e") +let nodeF = graph.addNode("f") +let nodeG = graph.addNode("g") +let nodeH = graph.addNode("h") + +graph.addEdge(nodeA, neighbor: nodeB) +graph.addEdge(nodeA, neighbor: nodeC) +graph.addEdge(nodeB, neighbor: nodeD) +graph.addEdge(nodeB, neighbor: nodeE) +graph.addEdge(nodeC, neighbor: nodeF) +graph.addEdge(nodeC, neighbor: nodeG) +graph.addEdge(nodeE, neighbor: nodeH) + +breadthFirstSearch(graph, root: nodeA) // This will output: Performing breadth-first search on 'a', b, c, d, e, f, g, h + +``` + ## See also [Breadth-first search on Wikipedia](https://en.wikipedia.org/wiki/Breadth-first_search) +[Queues](http://waynewbishop.com/swift/stacks-queues) & [Graphs](http://waynewbishop.com/swift/graphs) by Wayne Bishop + *Written by [Chris Pilcher](https://github.com/chris-pilcher)* From 475024e409f01bb6c657849955c09c59731e7992 Mon Sep 17 00:00:00 2001 From: Artur Antonov Date: Thu, 11 Feb 2016 17:00:39 +0300 Subject: [PATCH 0012/1679] Make some methods safer, rename the directory to Union-Find --- {UnionFind => Union-Find}/README.markdown | 0 .../UnioinFind.playground/Contents.swift | 27 ++++++++++--------- .../contents.xcplayground | 0 .../UnioinFind.playground/timeline.xctimeline | 0 {UnionFind => Union-Find}/UnionFind.swift | 27 ++++++++++--------- 5 files changed, 30 insertions(+), 24 deletions(-) rename {UnionFind => Union-Find}/README.markdown (100%) rename {UnionFind => Union-Find}/UnioinFind.playground/Contents.swift (83%) rename {UnionFind => Union-Find}/UnioinFind.playground/contents.xcplayground (100%) rename {UnionFind => Union-Find}/UnioinFind.playground/timeline.xctimeline (100%) rename {UnionFind => Union-Find}/UnionFind.swift (58%) diff --git a/UnionFind/README.markdown b/Union-Find/README.markdown similarity index 100% rename from UnionFind/README.markdown rename to Union-Find/README.markdown diff --git a/UnionFind/UnioinFind.playground/Contents.swift b/Union-Find/UnioinFind.playground/Contents.swift similarity index 83% rename from UnionFind/UnioinFind.playground/Contents.swift rename to Union-Find/UnioinFind.playground/Contents.swift index 2b2a68aea..d7cd8fd19 100644 --- a/UnionFind/UnioinFind.playground/Contents.swift +++ b/Union-Find/UnioinFind.playground/Contents.swift @@ -22,21 +22,24 @@ public struct UnionFind { } } - public mutating func findSetOfElement(element: T) -> Int { - let indexOfElement = index[element]! - return findSetByIndexOfElement(indexOfElement) + public mutating func findSetOfElement(element: T) -> Int? { + if let indexOfElement = index[element] { + return findSetByIndexOfElement(indexOfElement) + } else { + return nil + } } public mutating func unionSetsWithElement(firstElement: T, andSecondElement secondElement: T) { - let firstSet = findSetOfElement(firstElement) - let secondSet = findSetOfElement(secondElement) - if (firstSet != secondSet) { - if (size[firstSet] < size[secondSet]) { - parent[firstSet] = secondSet; - size[secondSet] += size[firstSet] - } else { - parent[secondSet] = firstSet; - size[firstSet] += size[secondSet] + if let firstSet = findSetOfElement(firstElement), secondSet = findSetOfElement(secondElement) { + if (firstSet != secondSet) { + if (size[firstSet] < size[secondSet]) { + parent[firstSet] = secondSet; + size[secondSet] += size[firstSet] + } else { + parent[secondSet] = firstSet; + size[firstSet] += size[secondSet] + } } } } diff --git a/UnionFind/UnioinFind.playground/contents.xcplayground b/Union-Find/UnioinFind.playground/contents.xcplayground similarity index 100% rename from UnionFind/UnioinFind.playground/contents.xcplayground rename to Union-Find/UnioinFind.playground/contents.xcplayground diff --git a/UnionFind/UnioinFind.playground/timeline.xctimeline b/Union-Find/UnioinFind.playground/timeline.xctimeline similarity index 100% rename from UnionFind/UnioinFind.playground/timeline.xctimeline rename to Union-Find/UnioinFind.playground/timeline.xctimeline diff --git a/UnionFind/UnionFind.swift b/Union-Find/UnionFind.swift similarity index 58% rename from UnionFind/UnionFind.swift rename to Union-Find/UnionFind.swift index 617d20951..193dd1d87 100644 --- a/UnionFind/UnionFind.swift +++ b/Union-Find/UnionFind.swift @@ -30,21 +30,24 @@ public struct UnionFind { } } - public mutating func findSetOfElement(element: T) -> Int { - let indexOfElement = index[element]! - return findSetByIndexOfElement(indexOfElement) + public mutating func findSetOfElement(element: T) -> Int? { + if let indexOfElement = index[element] { + return findSetByIndexOfElement(indexOfElement) + } else { + return nil + } } public mutating func unionSetsWithElement(firstElement: T, andSecondElement secondElement: T) { - let firstSet = findSetOfElement(firstElement) - let secondSet = findSetOfElement(secondElement) - if (firstSet != secondSet) { - if (size[firstSet] < size[secondSet]) { - parent[firstSet] = secondSet; - size[secondSet] += size[firstSet] - } else { - parent[secondSet] = firstSet; - size[firstSet] += size[secondSet] + if let firstSet = findSetOfElement(firstElement), secondSet = findSetOfElement(secondElement) { + if (firstSet != secondSet) { + if (size[firstSet] < size[secondSet]) { + parent[firstSet] = secondSet; + size[secondSet] += size[firstSet] + } else { + parent[secondSet] = firstSet; + size[firstSet] += size[secondSet] + } } } } From 4419a0d67f1cb54d4ad639fe32d3474bd066e61d Mon Sep 17 00:00:00 2001 From: Artur Antonov Date: Fri, 12 Feb 2016 19:01:03 +0300 Subject: [PATCH 0013/1679] Simplify method names --- .../UnioinFind.playground/Contents.swift | 85 +++++++++++-------- Union-Find/UnionFind.swift | 30 ++++--- 2 files changed, 67 insertions(+), 48 deletions(-) diff --git a/Union-Find/UnioinFind.playground/Contents.swift b/Union-Find/UnioinFind.playground/Contents.swift index d7cd8fd19..fe53241b9 100644 --- a/Union-Find/UnioinFind.playground/Contents.swift +++ b/Union-Find/UnioinFind.playground/Contents.swift @@ -7,102 +7,113 @@ public struct UnionFind { private var size = [Int]() - public mutating func addSetWithElement(element: T) { + public mutating func addSetWith(element: T) { index[element] = parent.count parent.append(parent.count) size.append(1) } - private mutating func findSetByIndexOfElement(index: Int) -> Int { + private mutating func setByIndex(index: Int) -> Int { if parent[index] == index { return index } else { - parent[index] = findSetByIndexOfElement(parent[index]) + parent[index] = setByIndex(parent[index]) return parent[index] } } - public mutating func findSetOfElement(element: T) -> Int? { + public mutating func setOf(element: T) -> Int? { if let indexOfElement = index[element] { - return findSetByIndexOfElement(indexOfElement) + return setByIndex(indexOfElement) } else { return nil } } - public mutating func unionSetsWithElement(firstElement: T, andSecondElement secondElement: T) { - if let firstSet = findSetOfElement(firstElement), secondSet = findSetOfElement(secondElement) { - if (firstSet != secondSet) { - if (size[firstSet] < size[secondSet]) { - parent[firstSet] = secondSet; + public mutating func unionSetsContaining(firstElement: T, and secondElement: T) { + if let firstSet = setOf(firstElement), secondSet = setOf(secondElement) { + if firstSet != secondSet { + if size[firstSet] < size[secondSet] { + parent[firstSet] = secondSet size[secondSet] += size[firstSet] } else { - parent[secondSet] = firstSet; + parent[secondSet] = firstSet size[firstSet] += size[secondSet] } } } } + + public mutating func inSameSet(firstElement: T, and secondElement: T) -> Bool { + if let firstSet = setOf(firstElement), secondSet = setOf(secondElement) { + return firstSet == secondSet + } else { + return false + } + } } var dsu = UnionFind() for i in 1...10 { - dsu.addSetWithElement(i) + dsu.addSetWith(i) } // now our dsu contains 10 independent sets // let's divide our numbers into two sets by divisibility by 2 for i in 3...10 { if i % 2 == 0 { - dsu.unionSetsWithElement(2, andSecondElement: i) + dsu.unionSetsContaining(2, and: i) } else { - dsu.unionSetsWithElement(1, andSecondElement: i) + dsu.unionSetsContaining(1, and: i) } } // check our division -print(dsu.findSetOfElement(2) == dsu.findSetOfElement(4)) -print(dsu.findSetOfElement(4) == dsu.findSetOfElement(6)) -print(dsu.findSetOfElement(6) == dsu.findSetOfElement(8)) -print(dsu.findSetOfElement(8) == dsu.findSetOfElement(10)) +print(dsu.inSameSet(2, and: 4)) +print(dsu.inSameSet(4, and: 6)) +print(dsu.inSameSet(6, and: 8)) +print(dsu.inSameSet(8, and: 10)) + + +print(dsu.inSameSet(1, and: 3)) +print(dsu.inSameSet(3, and: 5)) +print(dsu.inSameSet(5, and: 7)) +print(dsu.inSameSet(7, and: 9)) + -print(dsu.findSetOfElement(1) == dsu.findSetOfElement(3)) -print(dsu.findSetOfElement(3) == dsu.findSetOfElement(5)) -print(dsu.findSetOfElement(5) == dsu.findSetOfElement(7)) -print(dsu.findSetOfElement(7) == dsu.findSetOfElement(9)) +print(dsu.inSameSet(7, and: 4)) +print(dsu.inSameSet(3, and: 6)) -print(dsu.findSetOfElement(8) == dsu.findSetOfElement(9)) -print(dsu.findSetOfElement(4) == dsu.findSetOfElement(3)) var dsuForStrings = UnionFind() let words = ["all", "border", "boy", "afternoon", "amazing", "awesome", "best"] -dsuForStrings.addSetWithElement("a") -dsuForStrings.addSetWithElement("b") +dsuForStrings.addSetWith("a") +dsuForStrings.addSetWith("b") // In that example we divide strings by its first letter for word in words { - dsuForStrings.addSetWithElement(word) + dsuForStrings.addSetWith(word) if word.hasPrefix("a") { - dsuForStrings.unionSetsWithElement("a", andSecondElement: word) + dsuForStrings.unionSetsContaining("a", and: word) } else if word.hasPrefix("b") { - dsuForStrings.unionSetsWithElement("b", andSecondElement: word) + dsuForStrings.unionSetsContaining("b", and: word) } } -print(dsuForStrings.findSetOfElement("a") == dsuForStrings.findSetOfElement("all")) -print(dsuForStrings.findSetOfElement("all") == dsuForStrings.findSetOfElement("awesome")) -print(dsuForStrings.findSetOfElement("amazing") == dsuForStrings.findSetOfElement("afternoon")) +print(dsuForStrings.inSameSet("a", and: "all")) +print(dsuForStrings.inSameSet("all", and: "awesome")) +print(dsuForStrings.inSameSet("amazing", and: "afternoon")) -print(dsuForStrings.findSetOfElement("b") == dsuForStrings.findSetOfElement("boy")) -print(dsuForStrings.findSetOfElement("best") == dsuForStrings.findSetOfElement("boy")) -print(dsuForStrings.findSetOfElement("border") == dsuForStrings.findSetOfElement("best")) +print(dsuForStrings.inSameSet("b", and: "boy")) +print(dsuForStrings.inSameSet("best", and: "boy")) +print(dsuForStrings.inSameSet("border", and: "best")) -print(dsuForStrings.findSetOfElement("amazing") == dsuForStrings.findSetOfElement("boy")) -print(dsuForStrings.findSetOfElement("all") == dsuForStrings.findSetOfElement("border")) +print(dsuForStrings.inSameSet("amazing", and: "boy")) +print(dsuForStrings.inSameSet("all", and: "border")) diff --git a/Union-Find/UnionFind.swift b/Union-Find/UnionFind.swift index 193dd1d87..88583cb9a 100644 --- a/Union-Find/UnionFind.swift +++ b/Union-Find/UnionFind.swift @@ -15,40 +15,48 @@ public struct UnionFind { private var size = [Int]() - public mutating func addSetWithElement(element: T) { + public mutating func addSetWith(element: T) { index[element] = parent.count parent.append(parent.count) size.append(1) } - private mutating func findSetByIndexOfElement(index: Int) -> Int { + private mutating func setByIndex(index: Int) -> Int { if parent[index] == index { return index } else { - parent[index] = findSetByIndexOfElement(parent[index]) + parent[index] = setByIndex(parent[index]) return parent[index] } } - public mutating func findSetOfElement(element: T) -> Int? { + public mutating func setOf(element: T) -> Int? { if let indexOfElement = index[element] { - return findSetByIndexOfElement(indexOfElement) + return setByIndex(indexOfElement) } else { return nil } } - public mutating func unionSetsWithElement(firstElement: T, andSecondElement secondElement: T) { - if let firstSet = findSetOfElement(firstElement), secondSet = findSetOfElement(secondElement) { - if (firstSet != secondSet) { - if (size[firstSet] < size[secondSet]) { - parent[firstSet] = secondSet; + public mutating func unionSetsContaining(firstElement: T, and secondElement: T) { + if let firstSet = setOf(firstElement), secondSet = setOf(secondElement) { + if firstSet != secondSet { + if size[firstSet] < size[secondSet] { + parent[firstSet] = secondSet size[secondSet] += size[firstSet] } else { - parent[secondSet] = firstSet; + parent[secondSet] = firstSet size[firstSet] += size[secondSet] } } } } + + public mutating func inSameSet(firstElement: T, and secondElement: T) -> Bool { + if let firstSet = setOf(firstElement), secondSet = setOf(secondElement) { + return firstSet == secondSet + } else { + return false + } + } } \ No newline at end of file From 8ce99ee123232357f01bc8cc99bfac546b9eb0ab Mon Sep 17 00:00:00 2001 From: Artur Antonov Date: Fri, 12 Feb 2016 22:27:57 +0300 Subject: [PATCH 0014/1679] Add description with illustrations --- Union-Find/Images/AfterFind.png | Bin 0 -> 10347 bytes Union-Find/Images/AfterUnion.png | Bin 0 -> 26331 bytes Union-Find/Images/BeforeFind.png | Bin 0 -> 11685 bytes Union-Find/Images/BeforeUnion.png | Bin 0 -> 22581 bytes Union-Find/README.markdown | 152 +++++++++++++++++++++++++++++- 5 files changed, 150 insertions(+), 2 deletions(-) create mode 100644 Union-Find/Images/AfterFind.png create mode 100644 Union-Find/Images/AfterUnion.png create mode 100644 Union-Find/Images/BeforeFind.png create mode 100644 Union-Find/Images/BeforeUnion.png diff --git a/Union-Find/Images/AfterFind.png b/Union-Find/Images/AfterFind.png new file mode 100644 index 0000000000000000000000000000000000000000..6405f8e6da1e34121728073a1e4681df8ed4f74e GIT binary patch literal 10347 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 literal 0 HcmV?d00001 diff --git a/Union-Find/Images/AfterUnion.png b/Union-Find/Images/AfterUnion.png new file mode 100644 index 0000000000000000000000000000000000000000..aa75eefd882b0945d694acda6dadfdd11649a04c GIT binary patch literal 26331 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 literal 0 HcmV?d00001 diff --git a/Union-Find/Images/BeforeFind.png b/Union-Find/Images/BeforeFind.png new file mode 100644 index 0000000000000000000000000000000000000000..e0cdd224f857034e3cd4ae10188bcdee5f16e1f5 GIT binary patch literal 11685 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 Z=+m90swqBLd)aplke61Gs+BMa{$IT&LmmJC literal 0 HcmV?d00001 diff --git a/Union-Find/Images/BeforeUnion.png b/Union-Find/Images/BeforeUnion.png new file mode 100644 index 0000000000000000000000000000000000000000..42b3309aa8f8d4f4c6d423ab935a5f1ffd0e3407 GIT binary patch literal 22581 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 TAv!m8z_-+tv=uAimaqQ@eKZPO literal 0 HcmV?d00001 diff --git a/Union-Find/README.markdown b/Union-Find/README.markdown index 5ae638efc..a0d80dd1a 100644 --- a/Union-Find/README.markdown +++ b/Union-Find/README.markdown @@ -1,3 +1,151 @@ -# Union Find Data Structure +# Union-Find data structure -TODO +Union-Find data structure (also known as disjoint-set data structure) is data structure that can keep track of a set of elements partitioned into a number of disjoint (non-overlapping) subsets. It supports three basic operations: + 1. Find(**A**): Determine which subset an element **A** is in + 2. Union(**A**, **B**): Join two subsets that contain **A** and **B** into a single subset + 3. AddSet(**A**): Add a new subset containing just that element **A** + +The most common application of this data structure is keeping track of the connected components of an undirected graph. It is also used for implementing efficient version of Kruskal's algorithm to find the minimum spanning tree of a graph. + +## Implementation + +Union-Find can be implemented in many ways but we'll look at the most efficient. + +Every Union-Find data structure is just value of type `UnionFind` + +```swift +public struct UnionFind { + private var index = [T:Int]() + private var parent = [Int]() + private var size = [Int]() +} +``` + +Our Union-Find data structure is actually a forest where each subset represented by a [tree](../Tree/). For our purposes we only need to keep parent of each node. To do this we use array `parent` where `parent[i]` is index of parent of node with number **i**. In a that forest, the unique number of each subset is the index of value of root of that subset's tree. + +So let's look at the implementation of basic operations: + +### Add set + +```swift +public mutating func addSetWith(element: T) { + index[element] = parent.count // 1 + parent.append(parent.count) //2 + size.append(1) // 3 +} +``` + +1. We save index of new element in `index` dictionary because we need `parent` array only containing values in range 0.. Int { + if parent[index] == index { // 1 + return index + } else { + parent[index] = setByIndex(parent[index]) // 2 + return parent[index] // 3 + } +} + +public mutating func setOf(element: T) -> Int? { + if let indexOfElement = index[element] { + return setByIndex(indexOfElement) + } else { + return nil + } +} +``` + +`setOf(element: T)` is a helper method to get index corresponding to `element` and if it exists we return value of actual method `setByIndex(index: Int)` + +1. First, we check if current index represent a node that is root. That means we find number that represent the set of element we search for. + +2. Otherwise we recursively call our method on parent of current node. And then we do **very important thing**: we cache index of root node, so when we call this method again it will executed faster because of cached indexes. Without that optimization method's complexity is **O(n)** but now in combination with the size optimization (we'll look at that in Union section) it is almost **O(1)**. + +3. We return our cached root as result. + +Here's illustration of what I mean + +Before first call `setOf(4)`: + +![BeforeFind](Images/BeforeFind.png) + +After: + +![AfterFind](Images/AfterFind.png) + +Indexes of elements are marked in red. + + +### Union + +```swift +public mutating func unionSetsContaining(firstElement: T, and secondElement: T) { + if let firstSet = setOf(firstElement), secondSet = setOf(secondElement) { // 1 + if firstSet != secondSet { // 2 + if size[firstSet] < size[secondSet] { // 3 + parent[firstSet] = secondSet // 4 + size[secondSet] += size[firstSet] // 5 + } else { + parent[secondSet] = firstSet + size[firstSet] += size[secondSet] + } + } + } +} +``` + +1. We find sets of each element. + +2. Check that sets are not equal because if they are it makes no sense to union them. + +3. This is where our size optimization comes in. We want to keep trees as small as possible so we always attach the smaller tree to the root of the larger tree. To determine small tree we compare trees by its sizes. + +4. Here we attach the smaller tree to the root of the larger tree. + +5. We keep sizes of trees in actual states so we update size of larger tree. + +Union with optimizations also takes almost **O(1)** time. + +As always, some illustrations for better understanding + +Before calling `unionSetsContaining(4, and: 7)`: + +![BeforeUnion](Images/BeforeUnion.png) + +After: + +![AfterUnion](Images/AfterUnion.png) + +Note that during union caching optimization was performed because of calling `setOf` in the beginning of method. + + + +There are also helper method to just check that two elements is in the same set: + +```swift +public mutating func inSameSet(firstElement: T, and secondElement: T) -> Bool { + if let firstSet = setOf(firstElement), secondSet = setOf(secondElement) { + return firstSet == secondSet + } else { + return false + } +} +``` + + +See the playground for more examples of how to use this handy data structure. + + +## See also + +[Union-Find at wikipedia](https://en.wikipedia.org/wiki/Disjoint-set_data_structure) + +*Written for Swift Algorithm Club by [Artur Antonov](https://github.com/goingreen)* From 58392bcb5e804953b7b2da3370eb921f1b4f6f37 Mon Sep 17 00:00:00 2001 From: Matthijs Hollemans Date: Fri, 12 Feb 2016 21:17:22 +0100 Subject: [PATCH 0015/1679] Add run-length encoding --- README.markdown | 2 +- Run-Length Encoding/README.markdown | 139 ++++ .../RLE Tests/RLE.xcodeproj/project.pbxproj | 394 ++++++++++ .../RLE Tests/RLE/AppDelegate.swift | 27 + .../AppIcon.appiconset/Contents.json | 58 ++ .../RLE Tests/RLE/Base.lproj/MainMenu.xib | 680 ++++++++++++++++++ Run-Length Encoding/RLE Tests/RLE/Info.plist | 34 + Run-Length Encoding/RLE Tests/RLE/RLE.swift | 70 ++ .../RLE Tests/RLETests/Info.plist | 24 + .../RLE Tests/RLETests/RLETests.swift | 111 +++ .../RLE.playground/Contents.swift | 82 +++ .../RLE.playground/contents.xcplayground | 4 + .../RLE.playground/timeline.xctimeline | 6 + Run-Length Encoding/RLE.swift | 60 ++ 14 files changed, 1690 insertions(+), 1 deletion(-) create mode 100644 Run-Length Encoding/README.markdown create mode 100644 Run-Length Encoding/RLE Tests/RLE.xcodeproj/project.pbxproj create mode 100644 Run-Length Encoding/RLE Tests/RLE/AppDelegate.swift create mode 100644 Run-Length Encoding/RLE Tests/RLE/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 Run-Length Encoding/RLE Tests/RLE/Base.lproj/MainMenu.xib create mode 100644 Run-Length Encoding/RLE Tests/RLE/Info.plist create mode 100644 Run-Length Encoding/RLE Tests/RLE/RLE.swift create mode 100644 Run-Length Encoding/RLE Tests/RLETests/Info.plist create mode 100644 Run-Length Encoding/RLE Tests/RLETests/RLETests.swift create mode 100644 Run-Length Encoding/RLE.playground/Contents.swift create mode 100644 Run-Length Encoding/RLE.playground/contents.xcplayground create mode 100644 Run-Length Encoding/RLE.playground/timeline.xctimeline create mode 100644 Run-Length Encoding/RLE.swift diff --git a/README.markdown b/README.markdown index 1b5ff2a85..eb2bda765 100644 --- a/README.markdown +++ b/README.markdown @@ -79,7 +79,7 @@ Bad sorting algorithms (don't use these!): ### Compression -- Run-Length Encoding (RLE) +- [Run-Length Encoding (RLE)](Run-Length Encoding) - Huffman Encoding ### Miscellaneous diff --git a/Run-Length Encoding/README.markdown b/Run-Length Encoding/README.markdown new file mode 100644 index 000000000..0f6041885 --- /dev/null +++ b/Run-Length Encoding/README.markdown @@ -0,0 +1,139 @@ +# Run-Length Encoding (RLE) + +RLE is probably the simplest way to do compression. Let's say you have data that looks like this: + + aaaaabbbcdeeeeeeef... + +then RLE encodes it as follows: + + 5a3b1c1d7e1f... + +Instead of repeating bytes, you first write how often that byte occurs and then the byte's actual value. If the data has a lot of "byte runs", that is lots of repeating bytes, then RLE can save quite a bit of space. It works quite well on images. + +There are many different ways you can implement RLE. Here's an extension of `NSData` that does a version of RLE inspired by the old [PCX image file format](https://en.wikipedia.org/wiki/PCX). + +The rules are these: + +- Each byte run, i.e. when a certain byte value occurs more than once in a row, is compressed using two bytes: the first byte records the number of repetitions, the second records the actual value. The first byte is stored as: `191 + count`. This means encoded byte runs can never be more than 64 bytes long. + +- A single byte in the range 0 - 191 is not compressed and is copied without change. + +- A single byte in the range 192 - 255 is represented by two bytes: first the byte 192 (meaning a run of 1 byte), followed by the actual value. + +Here is the compression code. It returns a new `NSData` object containing the run-length encoded bytes: + +```swift +extension NSData { + public func compressRLE() -> NSData { + let data = NSMutableData() + if length > 0 { + var ptr = UnsafePointer(bytes) + let end = ptr + length + + while ptr < end { // 1 + var count = 0 + var byte = ptr.memory + var next = byte + + while next == byte && ptr < end && count < 64 { // 2 + ptr = ptr.advancedBy(1) + next = ptr.memory + count += 1 + } + + if count > 1 || byte >= 192 { // 3 + var size = 191 + UInt8(count) + data.appendBytes(&size, length: 1) + data.appendBytes(&byte, length: 1) + } else { // 4 + data.appendBytes(&byte, length: 1) + } + } + } + return data + } +} +``` + +How it works: + +1. We use an `UnsafePointer` to step through the bytes of the original `NSData` object. + +2. At this point we've read the current byte value into the `byte` variable. If the next byte is the same, then we keep reading until we find a byte value that is different, or we reach the end of the data. We also stop if the run is 64 bytes because that's the maximum we can encode. + +3. Here, we have to decide how to encode the bytes we just read. The first possibility is that we've read a run of 2 or more bytes (up to 64). In that case we write out two bytes: the length of the run followed by the byte value. But it's also possible we've read a single byte with a value >= 192. That will also be encoded with two bytes. + +4. The third possibility is that we've read a single byte < 192. That simply gets copied to the output verbatim. + +You can test it like this in a playground: + +```swift +let originalString = "aaaaabbbcdeeeeeeef" +let utf8 = originalString.dataUsingEncoding(NSUTF8StringEncoding)! +let compressed = utf8.compressRLE() +``` + +The compressed `NSData` object should be ``. Let's decode that by hand to see what has happened: + + c4 This is 196 in decimal. It means the next byte appears 5 times. + 61 The data byte "a". + c2 The next byte appears 3 times. + 62 The data byte "b". + 63 The data byte "c". Because this is < 192, it's a single data byte. + 64 The data byte "d". Also appears just once. + c6 The next byte will appear 7 times. + 65 The data byte "e". + 66 The data byte "f". Appears just once. + +So that's 9 bytes encoded versus 18 original. That's a savings of 50%. Of course, this was only a simple test case... If you get unlucky and there are no byte runs at all in your original data, then this method will actually make the encoded data twice as large! So it really depends on the input data. + +Here is the decompression code: + +```swift + public func decompressRLE() -> NSData { + let data = NSMutableData() + if length > 0 { + var ptr = UnsafePointer(bytes) + let end = ptr + length + + while ptr < end { + var byte = ptr.memory // 1 + ptr = ptr.advancedBy(1) + + if byte < 192 { // 2 + data.appendBytes(&byte, length: 1) + + } else if ptr < end { // 3 + var value = ptr.memory + ptr = ptr.advancedBy(1) + + for _ in 0 ..< byte - 191 { + data.appendBytes(&value, length: 1) + } + } + } + } + return data + } +``` + +1. Again this uses an `UnsafePointer` to read the `NSData`. Here we read the next byte; this is either a single value less than 192, or the start of a byte run. + +2. If it's a single value, then it's just a matter of copying it to the output. + +3. But if the byte is the start of a run, we have to first read the actual data value and then write it out repeatedly. + +To turn the compressed data back into the original, you'd do: + +```swift +let decompressed = compressed.decompressRLE() +let restoredString = String(data: decompressed, encoding: NSUTF8StringEncoding) +``` + +And now `originalString == restoredString` must be true! + +Footnote: The original PCX implementation is slightly different. There, a byte value of 192 (0xC0) means that the following byte will be repeated 0 times. This also limits the maximum run size to 63 bytes. Because it makes no sense to store bytes that don't occur, in my implementation 192 means the next byte appears once, and the maximum run length is 64 bytes. + +This was probably a trade-off when they designed the PCX format way back when. If you look at it in binary, the upper two bits indicate whether a byte is compressed. (If both bits are set then the byte value is 192 or more.) To get the run length you can simply do `byte & 0x3F`, giving you a value in the range 0 to 63. + +*Written for Swift Algorithm Club by Matthijs Hollemans* diff --git a/Run-Length Encoding/RLE Tests/RLE.xcodeproj/project.pbxproj b/Run-Length Encoding/RLE Tests/RLE.xcodeproj/project.pbxproj new file mode 100644 index 000000000..394f2c196 --- /dev/null +++ b/Run-Length Encoding/RLE Tests/RLE.xcodeproj/project.pbxproj @@ -0,0 +1,394 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 7B1BFA9B1C6E5CD70051C9A4 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B1BFA9A1C6E5CD70051C9A4 /* AppDelegate.swift */; }; + 7B1BFA9D1C6E5CD70051C9A4 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7B1BFA9C1C6E5CD70051C9A4 /* Assets.xcassets */; }; + 7B1BFAA01C6E5CD70051C9A4 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7B1BFA9E1C6E5CD70051C9A4 /* MainMenu.xib */; }; + 7B1BFAAB1C6E5CD70051C9A4 /* RLETests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B1BFAAA1C6E5CD70051C9A4 /* RLETests.swift */; }; + 7B1BFAB61C6E5D000051C9A4 /* RLE.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B1BFAB51C6E5D000051C9A4 /* RLE.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 7B1BFAA71C6E5CD70051C9A4 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 7B1BFA8F1C6E5CD70051C9A4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 7B1BFA961C6E5CD70051C9A4; + remoteInfo = RLE; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 7B1BFA971C6E5CD70051C9A4 /* RLE.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = RLE.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 7B1BFA9A1C6E5CD70051C9A4 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 7B1BFA9C1C6E5CD70051C9A4 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 7B1BFA9F1C6E5CD70051C9A4 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; + 7B1BFAA11C6E5CD70051C9A4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 7B1BFAA61C6E5CD70051C9A4 /* RLETests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RLETests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 7B1BFAAA1C6E5CD70051C9A4 /* RLETests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RLETests.swift; sourceTree = ""; }; + 7B1BFAAC1C6E5CD70051C9A4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 7B1BFAB51C6E5D000051C9A4 /* RLE.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RLE.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 7B1BFA941C6E5CD70051C9A4 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 7B1BFAA31C6E5CD70051C9A4 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 7B1BFA8E1C6E5CD70051C9A4 = { + isa = PBXGroup; + children = ( + 7B1BFA991C6E5CD70051C9A4 /* RLE */, + 7B1BFAA91C6E5CD70051C9A4 /* RLETests */, + 7B1BFA981C6E5CD70051C9A4 /* Products */, + ); + sourceTree = ""; + }; + 7B1BFA981C6E5CD70051C9A4 /* Products */ = { + isa = PBXGroup; + children = ( + 7B1BFA971C6E5CD70051C9A4 /* RLE.app */, + 7B1BFAA61C6E5CD70051C9A4 /* RLETests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 7B1BFA991C6E5CD70051C9A4 /* RLE */ = { + isa = PBXGroup; + children = ( + 7B1BFA9A1C6E5CD70051C9A4 /* AppDelegate.swift */, + 7B1BFA9C1C6E5CD70051C9A4 /* Assets.xcassets */, + 7B1BFAA11C6E5CD70051C9A4 /* Info.plist */, + 7B1BFA9E1C6E5CD70051C9A4 /* MainMenu.xib */, + 7B1BFAB51C6E5D000051C9A4 /* RLE.swift */, + ); + path = RLE; + sourceTree = ""; + }; + 7B1BFAA91C6E5CD70051C9A4 /* RLETests */ = { + isa = PBXGroup; + children = ( + 7B1BFAAA1C6E5CD70051C9A4 /* RLETests.swift */, + 7B1BFAAC1C6E5CD70051C9A4 /* Info.plist */, + ); + path = RLETests; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 7B1BFA961C6E5CD70051C9A4 /* RLE */ = { + isa = PBXNativeTarget; + buildConfigurationList = 7B1BFAAF1C6E5CD70051C9A4 /* Build configuration list for PBXNativeTarget "RLE" */; + buildPhases = ( + 7B1BFA931C6E5CD70051C9A4 /* Sources */, + 7B1BFA941C6E5CD70051C9A4 /* Frameworks */, + 7B1BFA951C6E5CD70051C9A4 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = RLE; + productName = RLE; + productReference = 7B1BFA971C6E5CD70051C9A4 /* RLE.app */; + productType = "com.apple.product-type.application"; + }; + 7B1BFAA51C6E5CD70051C9A4 /* RLETests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 7B1BFAB21C6E5CD70051C9A4 /* Build configuration list for PBXNativeTarget "RLETests" */; + buildPhases = ( + 7B1BFAA21C6E5CD70051C9A4 /* Sources */, + 7B1BFAA31C6E5CD70051C9A4 /* Frameworks */, + 7B1BFAA41C6E5CD70051C9A4 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 7B1BFAA81C6E5CD70051C9A4 /* PBXTargetDependency */, + ); + name = RLETests; + productName = RLETests; + productReference = 7B1BFAA61C6E5CD70051C9A4 /* RLETests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 7B1BFA8F1C6E5CD70051C9A4 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0720; + LastUpgradeCheck = 0720; + ORGANIZATIONNAME = "Swift Algorithm Club"; + TargetAttributes = { + 7B1BFA961C6E5CD70051C9A4 = { + CreatedOnToolsVersion = 7.2; + }; + 7B1BFAA51C6E5CD70051C9A4 = { + CreatedOnToolsVersion = 7.2; + TestTargetID = 7B1BFA961C6E5CD70051C9A4; + }; + }; + }; + buildConfigurationList = 7B1BFA921C6E5CD70051C9A4 /* Build configuration list for PBXProject "RLE" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 7B1BFA8E1C6E5CD70051C9A4; + productRefGroup = 7B1BFA981C6E5CD70051C9A4 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 7B1BFA961C6E5CD70051C9A4 /* RLE */, + 7B1BFAA51C6E5CD70051C9A4 /* RLETests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 7B1BFA951C6E5CD70051C9A4 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 7B1BFA9D1C6E5CD70051C9A4 /* Assets.xcassets in Resources */, + 7B1BFAA01C6E5CD70051C9A4 /* MainMenu.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 7B1BFAA41C6E5CD70051C9A4 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 7B1BFA931C6E5CD70051C9A4 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 7B1BFA9B1C6E5CD70051C9A4 /* AppDelegate.swift in Sources */, + 7B1BFAB61C6E5D000051C9A4 /* RLE.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 7B1BFAA21C6E5CD70051C9A4 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 7B1BFAAB1C6E5CD70051C9A4 /* RLETests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 7B1BFAA81C6E5CD70051C9A4 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 7B1BFA961C6E5CD70051C9A4 /* RLE */; + targetProxy = 7B1BFAA71C6E5CD70051C9A4 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 7B1BFA9E1C6E5CD70051C9A4 /* MainMenu.xib */ = { + isa = PBXVariantGroup; + children = ( + 7B1BFA9F1C6E5CD70051C9A4 /* Base */, + ); + name = MainMenu.xib; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 7B1BFAAD1C6E5CD70051C9A4 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 7B1BFAAE1C6E5CD70051C9A4 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + }; + name = Release; + }; + 7B1BFAB01C6E5CD70051C9A4 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = RLE/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.RLE; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 7B1BFAB11C6E5CD70051C9A4 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = RLE/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.RLE; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + 7B1BFAB31C6E5CD70051C9A4 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = RLETests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.RLETests; + PRODUCT_NAME = "$(TARGET_NAME)"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/RLE.app/Contents/MacOS/RLE"; + }; + name = Debug; + }; + 7B1BFAB41C6E5CD70051C9A4 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = RLETests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.RLETests; + PRODUCT_NAME = "$(TARGET_NAME)"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/RLE.app/Contents/MacOS/RLE"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 7B1BFA921C6E5CD70051C9A4 /* Build configuration list for PBXProject "RLE" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7B1BFAAD1C6E5CD70051C9A4 /* Debug */, + 7B1BFAAE1C6E5CD70051C9A4 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 7B1BFAAF1C6E5CD70051C9A4 /* Build configuration list for PBXNativeTarget "RLE" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7B1BFAB01C6E5CD70051C9A4 /* Debug */, + 7B1BFAB11C6E5CD70051C9A4 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 7B1BFAB21C6E5CD70051C9A4 /* Build configuration list for PBXNativeTarget "RLETests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7B1BFAB31C6E5CD70051C9A4 /* Debug */, + 7B1BFAB41C6E5CD70051C9A4 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 7B1BFA8F1C6E5CD70051C9A4 /* Project object */; +} diff --git a/Run-Length Encoding/RLE Tests/RLE/AppDelegate.swift b/Run-Length Encoding/RLE Tests/RLE/AppDelegate.swift new file mode 100644 index 000000000..4ae9f8243 --- /dev/null +++ b/Run-Length Encoding/RLE Tests/RLE/AppDelegate.swift @@ -0,0 +1,27 @@ +// +// AppDelegate.swift +// RLE +// +// Created by Matthijs Hollemans on 12-02-16. +// Copyright © 2016 Swift Algorithm Club. All rights reserved. +// + +import Cocoa + +@NSApplicationMain +class AppDelegate: NSObject, NSApplicationDelegate { + + @IBOutlet weak var window: NSWindow! + + + func applicationDidFinishLaunching(aNotification: NSNotification) { + // Insert code here to initialize your application + } + + func applicationWillTerminate(aNotification: NSNotification) { + // Insert code here to tear down your application + } + + +} + diff --git a/Run-Length Encoding/RLE Tests/RLE/Assets.xcassets/AppIcon.appiconset/Contents.json b/Run-Length Encoding/RLE Tests/RLE/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 000000000..2db2b1c7c --- /dev/null +++ b/Run-Length Encoding/RLE Tests/RLE/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,58 @@ +{ + "images" : [ + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Run-Length Encoding/RLE Tests/RLE/Base.lproj/MainMenu.xib b/Run-Length Encoding/RLE Tests/RLE/Base.lproj/MainMenu.xib new file mode 100644 index 000000000..6f60cc595 --- /dev/null +++ b/Run-Length Encoding/RLE Tests/RLE/Base.lproj/MainMenu.xib @@ -0,0 +1,680 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Default + + + + + + + Left to Right + + + + + + + Right to Left + + + + + + + + + + + Default + + + + + + + Left to Right + + + + + + + Right to Left + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Run-Length Encoding/RLE Tests/RLE/Info.plist b/Run-Length Encoding/RLE Tests/RLE/Info.plist new file mode 100644 index 000000000..0dca3caa8 --- /dev/null +++ b/Run-Length Encoding/RLE Tests/RLE/Info.plist @@ -0,0 +1,34 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + Copyright © 2016 Swift Algorithm Club. All rights reserved. + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/Run-Length Encoding/RLE Tests/RLE/RLE.swift b/Run-Length Encoding/RLE Tests/RLE/RLE.swift new file mode 100644 index 000000000..f26299cf1 --- /dev/null +++ b/Run-Length Encoding/RLE Tests/RLE/RLE.swift @@ -0,0 +1,70 @@ +import Foundation + +extension NSData { + /* + Compresses the NSData using run-length encoding. + */ + public func compressRLE() -> NSData { + let data = NSMutableData() + if length > 0 { + var ptr = UnsafePointer(bytes) + let end = ptr + length + + while ptr < end { + var count = 0 + var byte = ptr.memory + var next = byte + + // Is the next byte the same? Keep reading until we find a different + // value, or we reach the end of the data, or the run is 64 bytes. + while next == byte && ptr < end && count < 64 { + ptr = ptr.advancedBy(1) + next = ptr.memory + count += 1 + } + + if count > 1 || byte >= 192 { // byte run of up to 64 repeats + var size = 191 + UInt8(count) + data.appendBytes(&size, length: 1) + data.appendBytes(&byte, length: 1) + } else { // single byte between 0 and 192 + data.appendBytes(&byte, length: 1) + } + } + } + return data + } + + /* + Converts a run-length encoded NSData back to the original. + */ + public func decompressRLE() -> NSData { + let data = NSMutableData() + if length > 0 { + var ptr = UnsafePointer(bytes) + let end = ptr + length + + while ptr < end { + // Read the next byte. This is either a single value less than 192, + // or the start of a byte run. + var byte = ptr.memory + ptr = ptr.advancedBy(1) + + if byte < 192 { // single value + data.appendBytes(&byte, length: 1) + + } else if ptr < end { // byte run + // Read the actual data value. + var value = ptr.memory + ptr = ptr.advancedBy(1) + + // And write it out repeatedly. + for _ in 0 ..< byte - 191 { + data.appendBytes(&value, length: 1) + } + } + } + } + return data + } +} diff --git a/Run-Length Encoding/RLE Tests/RLETests/Info.plist b/Run-Length Encoding/RLE Tests/RLETests/Info.plist new file mode 100644 index 000000000..ba72822e8 --- /dev/null +++ b/Run-Length Encoding/RLE Tests/RLETests/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/Run-Length Encoding/RLE Tests/RLETests/RLETests.swift b/Run-Length Encoding/RLE Tests/RLETests/RLETests.swift new file mode 100644 index 000000000..99616a8c2 --- /dev/null +++ b/Run-Length Encoding/RLE Tests/RLETests/RLETests.swift @@ -0,0 +1,111 @@ +import XCTest +@testable import RLE + +class RLETests: XCTestCase { + private var showExtraOutput = false + + private func dumpData(data: NSData) { + if showExtraOutput { + var ptr = UnsafePointer(data.bytes) + for _ in 0.. NSData { + let data = NSMutableData() + if length > 0 { + var ptr = UnsafePointer(bytes) + let end = ptr + length + + while ptr < end { + var count = 0 + var byte = ptr.memory + var next = byte + + // Is the next byte the same? Keep reading until we find a different + // value, or we reach the end of the data, or the run is 64 bytes. + while next == byte && ptr < end && count < 64 { + ptr = ptr.advancedBy(1) + next = ptr.memory + count += 1 + } + + if count > 1 || byte >= 192 { // byte run of up to 64 repeats + var size = 191 + UInt8(count) + data.appendBytes(&size, length: 1) + data.appendBytes(&byte, length: 1) + } else { // single byte between 0 and 192 + data.appendBytes(&byte, length: 1) + } + } + } + return data + } + + /* + Converts a run-length encoded NSData back to the original. + */ + public func decompressRLE() -> NSData { + let data = NSMutableData() + if length > 0 { + var ptr = UnsafePointer(bytes) + let end = ptr + length + + while ptr < end { + // Read the next byte. This is either a single value less than 192, + // or the start of a byte run. + var byte = ptr.memory + ptr = ptr.advancedBy(1) + + if byte < 192 { // single value + data.appendBytes(&byte, length: 1) + + } else if ptr < end { // byte run + // Read the actual data value. + var value = ptr.memory + ptr = ptr.advancedBy(1) + + // And write it out repeatedly. + for _ in 0 ..< byte - 191 { + data.appendBytes(&value, length: 1) + } + } + } + } + return data + } +} + + + +let originalString = "aaaaabbbcdeeeeeeef" +let utf8 = originalString.dataUsingEncoding(NSUTF8StringEncoding)! +let compressed = utf8.compressRLE() + +let decompressed = compressed.decompressRLE() +let restoredString = String(data: decompressed, encoding: NSUTF8StringEncoding) +originalString == restoredString diff --git a/Run-Length Encoding/RLE.playground/contents.xcplayground b/Run-Length Encoding/RLE.playground/contents.xcplayground new file mode 100644 index 000000000..06828af92 --- /dev/null +++ b/Run-Length Encoding/RLE.playground/contents.xcplayground @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Run-Length Encoding/RLE.playground/timeline.xctimeline b/Run-Length Encoding/RLE.playground/timeline.xctimeline new file mode 100644 index 000000000..bf468afec --- /dev/null +++ b/Run-Length Encoding/RLE.playground/timeline.xctimeline @@ -0,0 +1,6 @@ + + + + + diff --git a/Run-Length Encoding/RLE.swift b/Run-Length Encoding/RLE.swift new file mode 100644 index 000000000..ee25af997 --- /dev/null +++ b/Run-Length Encoding/RLE.swift @@ -0,0 +1,60 @@ +import Foundation + +extension NSData { + /* + Helper method that reads the next run of bytes. Returns the size of the + run (between 1 and 64), the byte value, and the updated read pointer. + */ + private func readRun(start start: UnsafePointer, end: UnsafePointer) -> (Int, UInt8, UnsafePointer) { + var ptr = start + var count = 0 + + // Read the current byte. + let previous = ptr.memory + var current = previous + + // Is the next byte the same? Then keep reading until we find another + // byte, or we reach the end of the data, or the run is 64 bytes. + while current == previous && ptr < end && count < 64 { + ptr = ptr.advancedBy(1) + current = ptr.memory + count += 1 + } + + return (count, previous, ptr) + } + + /* + Compresses the NSData using run-length encoding. + */ + public func compressRLE() -> NSData { + let data = NSMutableData() + if length > 0 { + var ptr = UnsafePointer(bytes) + let end = ptr + length + + while ptr < end { + var (count, byte, out) = readRun(start: ptr, end: end) + + if count == 0 { // end-of-file + out = end + } else if count > 1 || byte >= 192 { // byte run, up to 64 repeats + var pair: [UInt8] = [191 + UInt8(count), byte] + data.appendBytes(&pair, length: 2) + } else { // single byte between 0 and 192 + data.appendBytes(&byte, length: 1) + } + ptr = out + } + } + return data + } + + + /* + Converts a run-length encoded NSData back to the original. + */ + public func decompressRLE() -> NSData { + return NSData() + } +} From 0cfd81d52c09aa01def16a835f3617ad0645f514 Mon Sep 17 00:00:00 2001 From: Artur Antonov Date: Sat, 13 Feb 2016 00:10:22 +0300 Subject: [PATCH 0016/1679] Fix images with union --- Union-Find/Images/AfterUnion.png | Bin 26331 -> 26672 bytes Union-Find/Images/BeforeUnion.png | Bin 22581 -> 22881 bytes Union-Find/README.markdown | 6 +++--- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Union-Find/Images/AfterUnion.png b/Union-Find/Images/AfterUnion.png index aa75eefd882b0945d694acda6dadfdd11649a04c..10c1f2d7eacdd8c650ea908a24dfa74b8fa602b6 100644 GIT binary patch literal 26672 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 delta 26004 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 diff --git a/Union-Find/Images/BeforeUnion.png b/Union-Find/Images/BeforeUnion.png index 42b3309aa8f8d4f4c6d423ab935a5f1ffd0e3407..13890ccb0090248bb8a2adcf040c75e5fd21130f 100644 GIT binary patch literal 22881 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 TAv!m8z_-+tv=uAimaqQ@eKZPO diff --git a/Union-Find/README.markdown b/Union-Find/README.markdown index a0d80dd1a..0ea8907e2 100644 --- a/Union-Find/README.markdown +++ b/Union-Find/README.markdown @@ -67,7 +67,7 @@ public mutating func setOf(element: T) -> Int? { 1. First, we check if current index represent a node that is root. That means we find number that represent the set of element we search for. -2. Otherwise we recursively call our method on parent of current node. And then we do **very important thing**: we cache index of root node, so when we call this method again it will executed faster because of cached indexes. Without that optimization method's complexity is **O(n)** but now in combination with the size optimization (we'll look at that in Union section) it is almost **O(1)**. +2. Otherwise we recursively call our method on parent of current node. And then we do **very important thing**: we cache index of root node, so when we call this method again it will executed faster because of cached indexes. Without that optimization method's complexity is **O(n)** but now in combination with the size optimization (I'll cover that in Union section) it is almost **O(1)**. 3. We return our cached root as result. @@ -116,7 +116,7 @@ Union with optimizations also takes almost **O(1)** time. As always, some illustrations for better understanding -Before calling `unionSetsContaining(4, and: 7)`: +Before calling `unionSetsContaining(4, and: 3)`: ![BeforeUnion](Images/BeforeUnion.png) @@ -128,7 +128,7 @@ Note that during union caching optimization was performed because of calling `se -There are also helper method to just check that two elements is in the same set: +There is also helper method to just check that two elements is in the same set: ```swift public mutating func inSameSet(firstElement: T, and secondElement: T) -> Bool { From 3b1b11c59c8dfcf5231fb842c61bc249de7b927e Mon Sep 17 00:00:00 2001 From: Matthijs Hollemans Date: Sat, 13 Feb 2016 14:14:37 +0100 Subject: [PATCH 0017/1679] Add the Monty Hall problem --- .../MontyHall.playground/Contents.swift | 53 +++++++++++++ .../contents.xcplayground | 4 + .../MontyHall.playground/timeline.xctimeline | 6 ++ Monty Hall Problem/README.markdown | 74 +++++++++++++++++++ README.markdown | 1 + 5 files changed, 138 insertions(+) create mode 100644 Monty Hall Problem/MontyHall.playground/Contents.swift create mode 100644 Monty Hall Problem/MontyHall.playground/contents.xcplayground create mode 100644 Monty Hall Problem/MontyHall.playground/timeline.xctimeline create mode 100644 Monty Hall Problem/README.markdown diff --git a/Monty Hall Problem/MontyHall.playground/Contents.swift b/Monty Hall Problem/MontyHall.playground/Contents.swift new file mode 100644 index 000000000..930dad714 --- /dev/null +++ b/Monty Hall Problem/MontyHall.playground/Contents.swift @@ -0,0 +1,53 @@ +//: Playground - noun: a place where people can play + +import Foundation + +func random(n: Int) -> Int { + return Int(arc4random_uniform(UInt32(n))) +} + +let numberOfDoors = 3 + +var rounds = 0 +var winOriginalChoice = 0 +var winChangedMind = 0 + +func playRound() { + // The door with the prize. + let prizeDoor = random(numberOfDoors) + + // The door the player chooses. + let chooseDoor = random(numberOfDoors) + + // The door that Monty opens. This must be empty and not the one the player chose. + var openDoor = -1 + repeat { + openDoor = random(numberOfDoors) + } while openDoor == prizeDoor || openDoor == chooseDoor + + // What happens when the player changes his mind and picks the other door. + var changeMind = -1 + repeat { + changeMind = random(numberOfDoors) + } while changeMind == openDoor || changeMind == chooseDoor + + // Figure out which choice was the winner. + if chooseDoor == prizeDoor { + winOriginalChoice += 1 + } + if changeMind == prizeDoor { + winChangedMind += 1 + } + + rounds += 1 +} + +// Run the simulation a large number of times. +for i in 1...5000 { + playRound() +} + +let stubbornPct = Double(winOriginalChoice)/Double(rounds) +let changedMindPct = Double(winChangedMind)/Double(rounds) + +print(String(format: "Played %d rounds, stubborn: %g%% vs changed mind: %g%%", rounds, stubbornPct, changedMindPct)) diff --git a/Monty Hall Problem/MontyHall.playground/contents.xcplayground b/Monty Hall Problem/MontyHall.playground/contents.xcplayground new file mode 100644 index 000000000..06828af92 --- /dev/null +++ b/Monty Hall Problem/MontyHall.playground/contents.xcplayground @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Monty Hall Problem/MontyHall.playground/timeline.xctimeline b/Monty Hall Problem/MontyHall.playground/timeline.xctimeline new file mode 100644 index 000000000..bf468afec --- /dev/null +++ b/Monty Hall Problem/MontyHall.playground/timeline.xctimeline @@ -0,0 +1,6 @@ + + + + + diff --git a/Monty Hall Problem/README.markdown b/Monty Hall Problem/README.markdown new file mode 100644 index 000000000..701299d63 --- /dev/null +++ b/Monty Hall Problem/README.markdown @@ -0,0 +1,74 @@ +# The Monty Hall Problem + +Congrats! You've reached the final round of the popular [Monty Hall game show](https://en.wikipedia.org/wiki/Let%27s_Make_a_Deal). Monty, the show host, gives you the choice between 3 doors. Behind one of the doors is a prize (a new car? a trip to Hawaii? a microwave oven?), the other two are empty. + +After you make your choice, Monty decides to make things a bit more interesting and opens one of the two doors that you didn't pick. Of course, the one he opens is empty. There are now two doors left, behind one of which is the coveted prize. + +Now Monty gives you the opportunity to change your mind. Should you stick with your original choice, should you pick the other door, or doesn't it matter? + +You'd think that changing your answer wouldn't improve your chances... but it does! + +This is a very nonintuitive result. Maybe you have trouble believing this is true. Don't worry, when this problem was first proposed many mathematicians didn't believe it either, so you're in good company. + +There's a simple way to verify this claim: we can write a program to test it out! We should be able to show who wins more often by playing the game a large number of times. + +Here's the code (see the [playground](MontyHall.playground/Contents.swift) for the full thing). First, we randomly choose the door that has the prize: + +```swift + let prizeDoor = random(3) +``` + +We also randomly pick the choice of the player: + +```swift + let chooseDoor = random(3) +``` + +Next, Monty opens one of the empty doors. Obviously, he won't choose the door that the player chose or the one with the prize. + +```swift + var openDoor = -1 + repeat { + openDoor = random(numberOfDoors) + } while openDoor == prizeDoor || openDoor == chooseDoor +``` + +There are only two closed doors left, one of which has the prize. What happens when the player changes his mind and picks the other door? + +```swift + var changeMind = -1 + repeat { + changeMind = random(3) + } while changeMind == openDoor || changeMind == chooseDoor +``` + +Now we see which choice was the right one: + +```swift + if chooseDoor == prizeDoor { + winOriginalChoice += 1 + } + if changeMind == prizeDoor { + winChangedMind += 1 + } +``` + +If the prize is behind the player's original door choice, we increment `winOriginalChoice`. If the prize is behind the other door, then the player would have won if he changed his mind, and so we increment `winChangedMind`. + +And that's all there is to it. + +If you run the above code 1000 times or so, you'll find that the probability of choosing the prize without changing your mind is about 33%. But if you *do* change your mind, the probability of winning is 67% -- that is twice as large! + +Try it out in the playground if you still don't believe it. ;-) + +Here's why: When you first make a choice, your chances of picking the prize are 1 out of 3, or 33% + +After Monty opens one of the doors, this gives you new information. However, it doesn't change the probability of your original choice being the winner. That chance remains 33% because you made that choice when you didn't know yet what was behind this open door. + +Since probabilities always need to add up to 100%, the chance that the prize is behind the other door is now 100 - 33 = 67%. So, as strange as it may sound, you're better of switching doors! + +This is hard to wrap your head around, but easily shown using a simulation that runs a significant number of times. Probability is weird. + +[Monty Hall Problem on Wikipedia](https://en.wikipedia.org/wiki/Monty_Hall_problem) + +*Written for Swift Algorithm Club by Matthijs Hollemans* diff --git a/README.markdown b/README.markdown index eb2bda765..5eba20eb5 100644 --- a/README.markdown +++ b/README.markdown @@ -169,6 +169,7 @@ A lot of software developer interview questions consist of algorithmic puzzles. - [Two-Sum Problem](Two-Sum Problem/) - [Fizz Buzz](Fizz Buzz/) +- [Monty Hall Problem](Monty Hall Problem/) ## Learn more! From a424764784a35fd5880a320098ebc2706ef17b71 Mon Sep 17 00:00:00 2001 From: Matthijs Hollemans Date: Sat, 13 Feb 2016 14:15:39 +0100 Subject: [PATCH 0018/1679] Small readme fix --- Monty Hall Problem/README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Monty Hall Problem/README.markdown b/Monty Hall Problem/README.markdown index 701299d63..f227a9b29 100644 --- a/Monty Hall Problem/README.markdown +++ b/Monty Hall Problem/README.markdown @@ -29,7 +29,7 @@ Next, Monty opens one of the empty doors. Obviously, he won't choose the door th ```swift var openDoor = -1 repeat { - openDoor = random(numberOfDoors) + openDoor = random(3) } while openDoor == prizeDoor || openDoor == chooseDoor ``` From d9313352c34b456ac02f230c8af6b4b55098123e Mon Sep 17 00:00:00 2001 From: Matthijs Hollemans Date: Sat, 13 Feb 2016 15:41:48 +0100 Subject: [PATCH 0019/1679] Tweaks to union-find --- README.markdown | 2 +- Union-Find/README.markdown | 177 +++++++++++------- .../Contents.swift | 6 +- .../contents.xcplayground | 0 .../timeline.xctimeline | 0 Union-Find/UnionFind.swift | 7 +- 6 files changed, 116 insertions(+), 76 deletions(-) rename Union-Find/{UnioinFind.playground => UnionFind.playground}/Contents.swift (98%) rename Union-Find/{UnioinFind.playground => UnionFind.playground}/contents.xcplayground (100%) rename Union-Find/{UnioinFind.playground => UnionFind.playground}/timeline.xctimeline (100%) diff --git a/README.markdown b/README.markdown index 5eba20eb5..a81f8a7ce 100644 --- a/README.markdown +++ b/README.markdown @@ -43,7 +43,7 @@ If you're new to algorithms and data structures, here are a few good ones to sta - [Select Minimum / Maximum](Select Minimum Maximum). Find the minimum/maximum value in an array. - [k-th Largest Element](Kth Largest Element/). Find the *k*th largest element in an array, such as the median. - [Selection Sampling](Selection Sampling/). Randomly choose a bunch of items from a collection. -- Union-Find +- [Union-Find](Union-Find/). Keeps track of disjoint sets and lets you quickly merge them. ### String Search diff --git a/Union-Find/README.markdown b/Union-Find/README.markdown index 0ea8907e2..66937cf69 100644 --- a/Union-Find/README.markdown +++ b/Union-Find/README.markdown @@ -1,59 +1,88 @@ -# Union-Find data structure +# Union-Find -Union-Find data structure (also known as disjoint-set data structure) is data structure that can keep track of a set of elements partitioned into a number of disjoint (non-overlapping) subsets. It supports three basic operations: - 1. Find(**A**): Determine which subset an element **A** is in - 2. Union(**A**, **B**): Join two subsets that contain **A** and **B** into a single subset - 3. AddSet(**A**): Add a new subset containing just that element **A** +Union-Find is a data structure that can keep track of a set of elements partitioned into a number of disjoint (non-overlapping) subsets. It is also known as disjoint-set data structure. -The most common application of this data structure is keeping track of the connected components of an undirected graph. It is also used for implementing efficient version of Kruskal's algorithm to find the minimum spanning tree of a graph. +What do we mean by this? For example, the Union-Find data structure could be keeping track of the following sets: + + [ a, b, f, k ] + [ e ] + [ g, d, c ] + [ i, j ] + +These sets are disjoint because they have no members in common. + +Union-Find supports three basic operations: + +1. **Find(A)**: Determine which subset an element **A** is in. For example, `find(d)` would return the subset `[ g, d, c ]`. + +2. **Union(A, B)**: Join two subsets that contain **A** and **B** into a single subset. For example, `union(d, j)` would combine `[ g, d, c ]` and `[ i, j ]` into the larger set `[ g, d, c, i, j ]`. + +3. **AddSet(A)**: Add a new subset containing just that element **A**. For example, `addSet(h)` would add a new set `[ h ]`. + +The most common application of this data structure is keeping track of the connected components of an undirected [graph](../Graph/). It is also used for implementing an efficient version of Kruskal's algorithm to find the minimum spanning tree of a graph. ## Implementation Union-Find can be implemented in many ways but we'll look at the most efficient. -Every Union-Find data structure is just value of type `UnionFind` - ```swift public struct UnionFind { - private var index = [T:Int]() + private var index = [T: Int]() private var parent = [Int]() private var size = [Int]() } ``` -Our Union-Find data structure is actually a forest where each subset represented by a [tree](../Tree/). For our purposes we only need to keep parent of each node. To do this we use array `parent` where `parent[i]` is index of parent of node with number **i**. In a that forest, the unique number of each subset is the index of value of root of that subset's tree. +Our Union-Find data structure is actually a forest where each subset is represented by a [tree](../Tree/). + +For our purposes we only need to keep track of the parent of each tree node, not the node's children. To do this we use the array `parent` so that `parent[i]` is the index of node `i`'s parent. -So let's look at the implementation of basic operations: +Example: If `parent` looks like this, -### Add set + parent [ 1, 1, 1, 0, 2, 0, 6, 6, 6 ] + i 0 1 2 3 4 5 6 7 8 + +then the tree structure looks like: + + 1 6 + / \ / \ + 0 2 7 8 + / \ / + 3 5 4 + +There are two trees in this forest, each of which corresponds to one set of elements. (Note: due to the limitations of ASCII art the trees are shown here as binary trees but that is not necessarily the case.) + +We give each subset a unique number to identify it. That number is the index of the root node of that subset's tree. In the example, node `1` is the root of the first tree and `6` is the root of the second tree. + +Note that the `parent[]` of a root node points to itself. So `parent[1] = 1` and `parent[6] = 6`. That's how we can tell something is a root node. + +So in this example we have two subsets, the first with the label `1` and the second with the label `6`. The **Find** operation actually returns the set's label, not its contents. + +## Add set + +Let's look at the implementation of these basic operations, starting with adding a new set. ```swift public mutating func addSetWith(element: T) { index[element] = parent.count // 1 - parent.append(parent.count) //2 - size.append(1) // 3 + parent.append(parent.count) // 2 + size.append(1) // 3 } ``` -1. We save index of new element in `index` dictionary because we need `parent` array only containing values in range 0.. Int { - if parent[index] == index { // 1 - return index - } else { - parent[index] = setByIndex(parent[index]) // 2 - return parent[index] // 3 - } -} +Often we want to determine whether we already have a set that contains a given element. That's what the **Find** operation does. In our `UnionFind` data structure it is called `setOf()`: +```swift public mutating func setOf(element: T) -> Int? { if let indexOfElement = index[element] { return setByIndex(indexOfElement) @@ -63,36 +92,66 @@ public mutating func setOf(element: T) -> Int? { } ``` -`setOf(element: T)` is a helper method to get index corresponding to `element` and if it exists we return value of actual method `setByIndex(index: Int)` +This looks up the element's index in the `index` dictionary and then uses a helper method to find the set that this element belongs to: + +```swift +private mutating func setByIndex(index: Int) -> Int { + if parent[index] == index { // 1 + return index + } else { + parent[index] = setByIndex(parent[index]) // 2 + return parent[index] // 3 + } +} +``` + +Because we're dealing with a tree structure, this is a recursive method. -1. First, we check if current index represent a node that is root. That means we find number that represent the set of element we search for. +Recall that each set is represented by a tree and that the index of the root node serves as the number that identifies the set. We're going to find the root node of the tree that the element we're searching for belongs to, and return its index. -2. Otherwise we recursively call our method on parent of current node. And then we do **very important thing**: we cache index of root node, so when we call this method again it will executed faster because of cached indexes. Without that optimization method's complexity is **O(n)** but now in combination with the size optimization (I'll cover that in Union section) it is almost **O(1)**. +1. First, we check if the given index represents a root node (i.e. a node whose `parent` points back to the node itself). If so, we're done. -3. We return our cached root as result. +2. Otherwise we recursively call this method on the parent of the current node. And then we do a **very important thing**: we overwrite the parent of the current node with the index of root node, in effect reconnecting the node directly to the root of the tree. The next time we call this method, it will execute faster because the path to the root of the tree is now much shorter. Without that optimization, this method's complexity is **O(n)** but now in combination with the size optimization (covered in the Union section) it is almost **O(1)**. -Here's illustration of what I mean +3. We return the index of the root node as the result. -Before first call `setOf(4)`: +Here's illustration of what I mean. Let's say the tree looks like this: ![BeforeFind](Images/BeforeFind.png) -After: +We call `setOf(4)`. To find the root node we have to first go to node `2` and then to node `7`. (The indexes of the elements are marked in red.) + +During the call to `setOf(4)`, the tree is reorganized to look like this: ![AfterFind](Images/AfterFind.png) -Indexes of elements are marked in red. +Now if we need to call `setOf(4)` again, we no longer have to go through node `2` to get to the root. So as you use the Union-Find data structure, it optimizes itself. Pretty cool! +There is also a helper method to check that two elements are in the same set: -### Union +```swift +public mutating func inSameSet(firstElement: T, and secondElement: T) -> Bool { + if let firstSet = setOf(firstElement), secondSet = setOf(secondElement) { + return firstSet == secondSet + } else { + return false + } +} +``` + +Since this calls `setOf()` it also optimizes the tree. + +## Union + +The final operation is **Union**, which combines two sets into one larger set. ```swift public mutating func unionSetsContaining(firstElement: T, and secondElement: T) { if let firstSet = setOf(firstElement), secondSet = setOf(secondElement) { // 1 - if firstSet != secondSet { // 2 + if firstSet != secondSet { // 2 if size[firstSet] < size[secondSet] { // 3 - parent[firstSet] = secondSet // 4 - size[secondSet] += size[firstSet] // 5 + parent[firstSet] = secondSet // 4 + size[secondSet] += size[firstSet] // 5 } else { parent[secondSet] = firstSet size[firstSet] += size[secondSet] @@ -102,50 +161,34 @@ public mutating func unionSetsContaining(firstElement: T, and secondElement: T) } ``` -1. We find sets of each element. +Here is how it works: -2. Check that sets are not equal because if they are it makes no sense to union them. +1. We find the sets that each element belongs to. Remember that this gives us two integers: the indices of the root nodes in the `parent` array. -3. This is where our size optimization comes in. We want to keep trees as small as possible so we always attach the smaller tree to the root of the larger tree. To determine small tree we compare trees by its sizes. +2. Check that the sets are not equal because if they are it makes no sense to union them. -4. Here we attach the smaller tree to the root of the larger tree. - -5. We keep sizes of trees in actual states so we update size of larger tree. +3. This is where the size optimization comes in. We want to keep the trees as shallow as possible so we always attach the smaller tree to the root of the larger tree. To determine which is the smaller tree we compare trees by their sizes. -Union with optimizations also takes almost **O(1)** time. +4. Here we attach the smaller tree to the root of the larger tree. -As always, some illustrations for better understanding +5. Update the size of larger tree because it just had a bunch of nodes added to it. -Before calling `unionSetsContaining(4, and: 3)`: +An illustration may help to better understand this. Let's say we have these two sets, each with its own tree: ![BeforeUnion](Images/BeforeUnion.png) -After: +Now we call `unionSetsContaining(4, and: 3)`. The smaller tree is attached to the larger one: ![AfterUnion](Images/AfterUnion.png) -Note that during union caching optimization was performed because of calling `setOf` in the beginning of method. +Note that, because we call `setOf()` in the beginning of the method, the larger tree was also optimized in the process -- node `3` now hangs directly off the root. +Union with optimizations also takes almost **O(1)** time. - -There is also helper method to just check that two elements is in the same set: - -```swift -public mutating func inSameSet(firstElement: T, and secondElement: T) -> Bool { - if let firstSet = setOf(firstElement), secondSet = setOf(secondElement) { - return firstSet == secondSet - } else { - return false - } -} -``` - +## See also See the playground for more examples of how to use this handy data structure. - -## See also - -[Union-Find at wikipedia](https://en.wikipedia.org/wiki/Disjoint-set_data_structure) +[Union-Find at Wikipedia](https://en.wikipedia.org/wiki/Disjoint-set_data_structure) *Written for Swift Algorithm Club by [Artur Antonov](https://github.com/goingreen)* diff --git a/Union-Find/UnioinFind.playground/Contents.swift b/Union-Find/UnionFind.playground/Contents.swift similarity index 98% rename from Union-Find/UnioinFind.playground/Contents.swift rename to Union-Find/UnionFind.playground/Contents.swift index fe53241b9..dd57514cd 100644 --- a/Union-Find/UnioinFind.playground/Contents.swift +++ b/Union-Find/UnionFind.playground/Contents.swift @@ -1,12 +1,10 @@ //: Playground - noun: a place where people can play public struct UnionFind { - - private var index = [T:Int]() + private var index = [T: Int]() private var parent = [Int]() private var size = [Int]() - public mutating func addSetWith(element: T) { index[element] = parent.count parent.append(parent.count) @@ -54,6 +52,8 @@ public struct UnionFind { } + + var dsu = UnionFind() for i in 1...10 { diff --git a/Union-Find/UnioinFind.playground/contents.xcplayground b/Union-Find/UnionFind.playground/contents.xcplayground similarity index 100% rename from Union-Find/UnioinFind.playground/contents.xcplayground rename to Union-Find/UnionFind.playground/contents.xcplayground diff --git a/Union-Find/UnioinFind.playground/timeline.xctimeline b/Union-Find/UnionFind.playground/timeline.xctimeline similarity index 100% rename from Union-Find/UnioinFind.playground/timeline.xctimeline rename to Union-Find/UnionFind.playground/timeline.xctimeline diff --git a/Union-Find/UnionFind.swift b/Union-Find/UnionFind.swift index 88583cb9a..f1500e6c9 100644 --- a/Union-Find/UnionFind.swift +++ b/Union-Find/UnionFind.swift @@ -7,14 +7,11 @@ union sets is almost O(1) */ - public struct UnionFind { - - private var index = [T:Int]() + private var index = [T: Int]() private var parent = [Int]() private var size = [Int]() - public mutating func addSetWith(element: T) { index[element] = parent.count parent.append(parent.count) @@ -51,7 +48,7 @@ public struct UnionFind { } } } - + public mutating func inSameSet(firstElement: T, and secondElement: T) -> Bool { if let firstSet = setOf(firstElement), secondSet = setOf(secondElement) { return firstSet == secondSet From ef637c843fd296919153e7e9bcbda11005825f7c Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Mon, 15 Feb 2016 21:47:20 +1300 Subject: [PATCH 0020/1679] BFS. Manually stepping through animated example. Removed Queue and Graph from readme. --- .../Contents.swift | 51 +++---- Breadth-First Search/README.markdown | 138 ++++++------------ 2 files changed, 59 insertions(+), 130 deletions(-) diff --git a/Breadth-First Search/BreadthFirstSearch.playground/Contents.swift b/Breadth-First Search/BreadthFirstSearch.playground/Contents.swift index a6318d8c9..a9fabb1c9 100644 --- a/Breadth-First Search/BreadthFirstSearch.playground/Contents.swift +++ b/Breadth-First Search/BreadthFirstSearch.playground/Contents.swift @@ -32,58 +32,43 @@ class Edge { } } -class Queue { - private var top: QueueNode! +struct Queue { + var array = [T]() - func enqueue(item: T) { - if (top == nil) { - top = QueueNode() - } - - if (top.item == nil) { - top.item = item; - return - } + var isEmpty: Bool { + return array.isEmpty + } - let childToUse = QueueNode() - var current: QueueNode = top - while current.next != nil { - current = current.next! - } + var count: Int { + return array.count + } - childToUse.item = item; - current.next = childToUse; + mutating func enqueue(element: T) { + array.append(element) } - func dequeue() -> QueueNode? { - guard !isEmpty else { + mutating func dequeue() -> T? { + if isEmpty { return nil + } else { + return array.removeFirst() } - - let itemToDequeue = top - top = itemToDequeue.next - return itemToDequeue } - var isEmpty: Bool { - get { return top == nil } + func peek() -> T? { + return array.first } } -class QueueNode { - var item: T? - var next: QueueNode? -} - func breadthFirstSearch(graph: Graph, root: Node) { print("Performing breadth-first search on '\(root.label)'") - let q = Queue() + var q = Queue() q.enqueue(root) while !q.isEmpty { let current = q.dequeue() - for edge in current!.item!.neighbors { + for edge in current!.neighbors { let neighborNode = edge.neighbor q.enqueue(neighborNode) diff --git a/Breadth-First Search/README.markdown b/Breadth-First Search/README.markdown index bbb7fa376..21f2e8a97 100644 --- a/Breadth-First Search/README.markdown +++ b/Breadth-First Search/README.markdown @@ -6,111 +6,57 @@ Breadth-first search (BFS) is an algorithm for traversing or searching tree or g ![Animated example of a breadth-first search](Images/Animated_BFS.gif) -## The code - -Before we can code the breadth-first search algorithm we need to: -* Create an implementation of the graph -* Create an implementation of a queue - -### Graph implementation - -A graph is made up of nodes and edges. In the [animated example](#animated-example) the nodes are represented as circles and the edges are represented as lines. +Let's follow the animated example by using a [queue](../Queue/). -Implementation of a node: +Start with the root node ``a`` and add it to a queue. ```swift -class Node { - private var label: String - private var neighbors: [Edge] - - init(label: String) { - self.label = label - neighbors = [] - } -} +queue.enqueue(a) ``` - -Implementation of an edge: +The queue is now ``[ a ]``. Dequeue ``a`` and enqueue the neighbor nodes ``b`` and ``c``. ```swift -class Edge { - private var neighbor: Node - - init(neighbor: Node) { - self.neighbor = neighbor - } -} +queue.dequeue(a) +queue.enqueue(b) +queue.enqueue(c) ``` - -Implementation of a graph: +The queue is now ``[ b, c ]``. Dequeue ``b`` and enqueue the neighbor nodes ``d`` and ``e``. ```swift -class Graph { - private var nodes = [Node]() - - func addNode(label: String) -> Node { - let node = Node(label: label) - nodes.append(node) - return node - } - - func addEdge(source: Node, neighbor: Node) { - let edge = Edge(neighbor: neighbor) - edge.neighbor = neighbor - source.neighbors.append(edge) - } -} +queue.dequeue(b) +queue.enqueue(d) +queue.enqueue(e) ``` - -### Queue implementation - -Implementation of simple queue: - +The queue is now ``[ c, d, e ]``. Dequeue ``c`` and enqueue the neighbor nodes ``f`` and ``g``. ```swift -class Queue { - private var top: QueueNode! - - func enqueue(item: T) { - if (top == nil) { - top = QueueNode() - } - - if (top.item == nil) { - top.item = item; - return - } - - let childToUse = QueueNode() - var current: QueueNode = top - while current.next != nil { - current = current.next! - } - - childToUse.item = item; - current.next = childToUse; - } - - func dequeue() -> QueueNode? { - guard !isEmpty else { - return nil - } - - let itemToDequeue = top - top = itemToDequeue.next - return itemToDequeue - } - - var isEmpty: Bool { - get { return top == nil } - } -} - -class QueueNode { - var item: T? - var next: QueueNode? -} +queue.dequeue(c) +queue.enqueue(f) +queue.enqueue(g) ``` +The queue is now ``[ d, e, f, g ]``. Dequeue ``d`` which has no neighbor nodes. +```swift +queue.dequeue(d) +``` +The queue is now ``[ e, f, g ]``. Dequeue ``e`` which enqueue the single neighbor node ``h``. +```swift +queue.dequeue(e) +queue.enqueue(h) +``` +The queue is now ``[ f, g, h ]``. Dequeue ``f`` which has no neighbor nodes. +```swift +queue.dequeue(f) +``` +The queue is now ``[ g, h ]``. Dequeue ``g`` which has no neighbor nodes. +```swift +queue.dequeue(g) +``` +The queue is now ``[ h ]``. Dequeue ``h`` which has no neighbor nodes. +```swift +queue.dequeue(h) +``` +The queue is now empty which means all nodes have been explored. -### Breadth-first search algorithm +## The code + +Simple implementation of breadth-first search using a queue: -Simple implementation of breadth-first search using queues: ```swift func breadthFirstSearch(graph: Graph, root: Node) { print("Performing breadth-first search on '\(root.label)'") @@ -157,8 +103,6 @@ breadthFirstSearch(graph, root: nodeA) // This will output: Performing breadth-f ## See also -[Breadth-first search on Wikipedia](https://en.wikipedia.org/wiki/Breadth-first_search) - -[Queues](http://waynewbishop.com/swift/stacks-queues) & [Graphs](http://waynewbishop.com/swift/graphs) by Wayne Bishop +[Graphs](../Graph/), [Queues](../Queue/), [Breadth-first search on Wikipedia](https://en.wikipedia.org/wiki/Breadth-first_search). *Written by [Chris Pilcher](https://github.com/chris-pilcher)* From 0ca1a40a0d7e5fa3879693730c905881cad22012 Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Mon, 15 Feb 2016 21:55:32 +1300 Subject: [PATCH 0021/1679] BFS. Typo and adding ToDos for future sections. --- Breadth-First Search/README.markdown | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Breadth-First Search/README.markdown b/Breadth-First Search/README.markdown index 21f2e8a97..878605fdf 100644 --- a/Breadth-First Search/README.markdown +++ b/Breadth-First Search/README.markdown @@ -34,7 +34,7 @@ The queue is now ``[ d, e, f, g ]``. Dequeue ``d`` which has no neighbor nodes. ```swift queue.dequeue(d) ``` -The queue is now ``[ e, f, g ]``. Dequeue ``e`` which enqueue the single neighbor node ``h``. +The queue is now ``[ e, f, g ]``. Dequeue ``e`` and enqueue the single neighbor node ``h``. ```swift queue.dequeue(e) queue.enqueue(h) @@ -101,6 +101,14 @@ breadthFirstSearch(graph, root: nodeA) // This will output: Performing breadth-f ``` +## Applications + +**TODO**: list a few common Applications + +# Finding the shortest path + +**TODO**: step through example + ## See also [Graphs](../Graph/), [Queues](../Queue/), [Breadth-first search on Wikipedia](https://en.wikipedia.org/wiki/Breadth-first_search). From 1a96dc028b3c88226f504a5a58a9c7f41980993b Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Tue, 16 Feb 2016 21:08:28 +1300 Subject: [PATCH 0022/1679] BFS Making breadthFirstSearch function in the readme match the playground --- Breadth-First Search/README.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Breadth-First Search/README.markdown b/Breadth-First Search/README.markdown index 878605fdf..e49ced0a1 100644 --- a/Breadth-First Search/README.markdown +++ b/Breadth-First Search/README.markdown @@ -61,12 +61,12 @@ Simple implementation of breadth-first search using a queue: func breadthFirstSearch(graph: Graph, root: Node) { print("Performing breadth-first search on '\(root.label)'") - let q = Queue() + var q = Queue() q.enqueue(root) while !q.isEmpty { let current = q.dequeue() - for edge in current!.item!.neighbors { + for edge in current!.neighbors { let neighborNode = edge.neighbor q.enqueue(neighborNode) From 19e0fc7cf6be4444ee8793b0b6dca6924922c191 Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Tue, 16 Feb 2016 22:30:01 +1300 Subject: [PATCH 0023/1679] BFS. Fixing infinite loop when graph contains cycles (by recording seen nodes). Added draft shortest path algorithm. --- .../Contents.swift | 49 +++++++++++++++-- Breadth-First Search/README.markdown | 52 +++++++++++++++---- 2 files changed, 87 insertions(+), 14 deletions(-) diff --git a/Breadth-First Search/BreadthFirstSearch.playground/Contents.swift b/Breadth-First Search/BreadthFirstSearch.playground/Contents.swift index a9fabb1c9..545a78fd1 100644 --- a/Breadth-First Search/BreadthFirstSearch.playground/Contents.swift +++ b/Breadth-First Search/BreadthFirstSearch.playground/Contents.swift @@ -14,14 +14,30 @@ class Graph { } } -class Node { +class Node : CustomStringConvertible, Equatable { private var label: String private var neighbors: [Edge] + private var distance: Int? init(label: String) { self.label = label neighbors = [] } + + var description: String { + if let distance = distance { + return "Node(label: \(label), distance: \(distance))" + } + return "Node(label: \(label), distance: infnity)" + } + + var hasDistance: Bool { + return distance != nil + } +} + +func ==(lhs: Node, rhs: Node) -> Bool { + return lhs.label == rhs.label } class Edge { @@ -63,6 +79,25 @@ struct Queue { func breadthFirstSearch(graph: Graph, root: Node) { print("Performing breadth-first search on '\(root.label)'") + var seenNodes = [root] + var queue = Queue() + queue.enqueue(root) + + while !queue.isEmpty { + let current = queue.dequeue() + for edge in current!.neighbors { + let neighborNode = edge.neighbor + if !seenNodes.contains(neighborNode) { + queue.enqueue(neighborNode) + seenNodes.append(neighborNode) + print(neighborNode.label) + } + } + } +} + +func breadthFirstSearchShortestPath(graph: Graph, root: Node) { + root.distance = 0 var q = Queue() q.enqueue(root) @@ -70,13 +105,17 @@ func breadthFirstSearch(graph: Graph, root: Node) { let current = q.dequeue() for edge in current!.neighbors { let neighborNode = edge.neighbor - q.enqueue(neighborNode) - - print(neighborNode.label) + if !neighborNode.hasDistance { + q.enqueue(neighborNode) + neighborNode.distance = current!.distance! + 1 + } } } + + print(graph.nodes) } + let graph = Graph() let nodeA = graph.addNode("a") @@ -96,4 +135,6 @@ graph.addEdge(nodeC, neighbor: nodeF) graph.addEdge(nodeC, neighbor: nodeG) graph.addEdge(nodeE, neighbor: nodeH) + breadthFirstSearch(graph, root: nodeA) +breadthFirstSearchShortestPath(graph, root: nodeA) diff --git a/Breadth-First Search/README.markdown b/Breadth-First Search/README.markdown index e49ced0a1..dc7918ff5 100644 --- a/Breadth-First Search/README.markdown +++ b/Breadth-First Search/README.markdown @@ -61,16 +61,19 @@ Simple implementation of breadth-first search using a queue: func breadthFirstSearch(graph: Graph, root: Node) { print("Performing breadth-first search on '\(root.label)'") - var q = Queue() - q.enqueue(root) + var seenNodes = [root] + var queue = Queue() + queue.enqueue(root) - while !q.isEmpty { - let current = q.dequeue() + while !queue.isEmpty { + let current = queue.dequeue() for edge in current!.neighbors { let neighborNode = edge.neighbor - q.enqueue(neighborNode) - - print(neighborNode.label) + if !seenNodes.contains(neighborNode) { + queue.enqueue(neighborNode) + seenNodes.append(neighborNode) + print(neighborNode.label) + } } } } @@ -103,11 +106,40 @@ breadthFirstSearch(graph, root: nodeA) // This will output: Performing breadth-f ## Applications -**TODO**: list a few common Applications +Breadth-first search can be used to solve many problems, for example: + +* Computing the shortest path between a source node and each of the other nodes + * Only for unweighted graphs +* Calculating the minimum spanning tree on an unweighted graph + +## Shortest path example + +TODO: walkthrough + explanation + +```swift +func breadthFirstSearchShortestPath(graph: Graph, root: Node) { + root.distance = 0 + var q = Queue() + q.enqueue(root) + + while !q.isEmpty { + let current = q.dequeue() + for edge in current!.neighbors { + let neighborNode = edge.neighbor + if !neighborNode.hasDistance { + q.enqueue(neighborNode) + neighborNode.distance = current!.distance! + 1 + } + } + } + + print(graph.nodes) +} +``` -# Finding the shortest path +## Minimum spanning tree example -**TODO**: step through example +TODO ## See also From eb648b1fcd090abc811de217fbf005f2debec5c5 Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Tue, 16 Feb 2016 22:31:22 +1300 Subject: [PATCH 0024/1679] BFS fixing typo --- .../BreadthFirstSearch.playground/Contents.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Breadth-First Search/BreadthFirstSearch.playground/Contents.swift b/Breadth-First Search/BreadthFirstSearch.playground/Contents.swift index 545a78fd1..64134a85c 100644 --- a/Breadth-First Search/BreadthFirstSearch.playground/Contents.swift +++ b/Breadth-First Search/BreadthFirstSearch.playground/Contents.swift @@ -28,7 +28,7 @@ class Node : CustomStringConvertible, Equatable { if let distance = distance { return "Node(label: \(label), distance: \(distance))" } - return "Node(label: \(label), distance: infnity)" + return "Node(label: \(label), distance: infinity)" } var hasDistance: Bool { From 0a2649278aa8888f36feece509e9eb4b9b3a75f2 Mon Sep 17 00:00:00 2001 From: Matthijs Hollemans Date: Tue, 16 Feb 2016 19:20:13 +0100 Subject: [PATCH 0025/1679] Additional explanation on Monty Hall --- Monty Hall Problem/README.markdown | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Monty Hall Problem/README.markdown b/Monty Hall Problem/README.markdown index f227a9b29..81004410e 100644 --- a/Monty Hall Problem/README.markdown +++ b/Monty Hall Problem/README.markdown @@ -69,6 +69,20 @@ Since probabilities always need to add up to 100%, the chance that the prize is This is hard to wrap your head around, but easily shown using a simulation that runs a significant number of times. Probability is weird. +By the way, you can simplify the code to this: + +```swift + let prizeDoor = random(3) + let chooseDoor = random(3) + if chooseDoor == prizeDoor { + winOriginalChoice += 1 + } else { + winChangedMind += 1 + } +``` + +Now it's no longer a simulation but the logic is equivalent. You can clearly see that the `chooseDoor` only wins 1/3rd of the time -- because it's a random number between 1 and 3 -- so changing your mind must win the other 2/3rds of the time. + [Monty Hall Problem on Wikipedia](https://en.wikipedia.org/wiki/Monty_Hall_problem) *Written for Swift Algorithm Club by Matthijs Hollemans* From 771163764b33d1b0b757b71fdfa1d67147805371 Mon Sep 17 00:00:00 2001 From: Matthijs Hollemans Date: Wed, 17 Feb 2016 20:25:57 +0100 Subject: [PATCH 0026/1679] Put brute-force string search in its own folder --- .../BoyerMoore.playground/Contents.swift | 3 +- Boyer-Moore/README.markdown | 39 ++----------- .../Contents.swift | 32 +++++++++++ .../contents.xcplayground | 4 ++ .../timeline.xctimeline | 6 ++ .../BruteForceStringSearch.swift | 23 ++++++++ Brute-Force String Search/README.markdown | 56 +++++++++++++++++++ README.markdown | 1 + 8 files changed, 130 insertions(+), 34 deletions(-) create mode 100644 Brute-Force String Search/BruteForceStringSearch.playground/Contents.swift create mode 100644 Brute-Force String Search/BruteForceStringSearch.playground/contents.xcplayground create mode 100644 Brute-Force String Search/BruteForceStringSearch.playground/timeline.xctimeline create mode 100644 Brute-Force String Search/BruteForceStringSearch.swift create mode 100644 Brute-Force String Search/README.markdown diff --git a/Boyer-Moore/BoyerMoore.playground/Contents.swift b/Boyer-Moore/BoyerMoore.playground/Contents.swift index bba6e0fb6..926a76f93 100644 --- a/Boyer-Moore/BoyerMoore.playground/Contents.swift +++ b/Boyer-Moore/BoyerMoore.playground/Contents.swift @@ -39,11 +39,12 @@ extension String { } } + + // A few simple tests let s = "Hello, World" s.indexOf("World") // 7 -// Input: let animals = "🐶🐔🐷🐮🐱" animals.indexOf("🐮") // 6 diff --git a/Boyer-Moore/README.markdown b/Boyer-Moore/README.markdown index 7050442e2..dce0430f2 100644 --- a/Boyer-Moore/README.markdown +++ b/Boyer-Moore/README.markdown @@ -1,8 +1,8 @@ # Boyer-Moore String Search -How would you go about writing a string search algorithm in pure Swift if you were not allowed to import Foundation and could not use `NSString`'s `rangeOfString()` method? - -The goal is to implement an `indexOf(pattern: String)` extension on `String` that returns the `String.Index` of the first occurrence of the search pattern, or `nil` if the pattern could not be found inside the string. +Goal: Write a string search algorithm in pure Swift without importing Foundation or using `NSString`'s `rangeOfString()` method. + +In other words, implement an `indexOf(pattern: String)` extension on `String` that returns the `String.Index` of the first occurrence of the search pattern, or `nil` if the pattern could not be found inside the string. For example: @@ -22,36 +22,9 @@ animals.indexOf("🐮") 6 ``` -Note: The index of the cow is 6, not 3 as you might expect, because the string uses more storage per character for emoji. The actual value of the `String.Index` is not so important, just that it points at the right character in the string. - -First, a brute-force solution: - -```swift -extension String { - func indexOf(pattern: String) -> String.Index? { - for i in self.startIndex ..< self.endIndex { - var j = i - var found = true - for p in pattern.startIndex ..< pattern.endIndex { - if j == self.endIndex || self[j] != pattern[p] { - found = false - break - } else { - j = j.successor() - } - } - if found { - return i - } - } - return nil - } -} -``` - -This looks at each character in the source string in turn. If the character equals the first character of the search pattern, then the inner loop checks whether the rest of the pattern matches. If no match is found, the outer loop continues where it left off. This repeats until a complete match is found or the end of the source string is reached. +> **Note:** The index of the cow is 6, not 3 as you might expect, because the string uses more storage per character for emoji. The actual value of the `String.Index` is not so important, just that it points at the right character in the string. -The brute-force approach works OK, but it's not very efficient (or pretty). As it turns out, you don't need to look at *every* character from the source string -- you can often skip ahead multiple characters. +The [brute-force approach](../Brute-Force Search Search/) works OK, but it's not very efficient, especially on large chunks of text. As it turns out, you don't need to look at *every* character from the source string -- you can often skip ahead multiple characters. That skip-ahead algorithm is called [Boyer-Moore](https://en.wikipedia.org/wiki/Boyer–Moore_string_search_algorithm) and it has been around for a long time. It is considered the benchmark for all string search algorithms. @@ -164,4 +137,4 @@ A caveat: If the search pattern consists of only a few characters, it's faster t Credits: This code is based on the article ["Faster String Searches" by Costas Menico](http://www.drdobbs.com/database/faster-string-searches/184408171) from Dr Dobb's magazine, July 1989 -- Yes, 1989! Sometimes it's useful to keep those old magazines around. -*Written by Matthijs Hollemans* +*Written for Swift Algorithm Club by Matthijs Hollemans* diff --git a/Brute-Force String Search/BruteForceStringSearch.playground/Contents.swift b/Brute-Force String Search/BruteForceStringSearch.playground/Contents.swift new file mode 100644 index 000000000..57f2b2090 --- /dev/null +++ b/Brute-Force String Search/BruteForceStringSearch.playground/Contents.swift @@ -0,0 +1,32 @@ +//: Playground - noun: a place where people can play + +extension String { + func indexOf(pattern: String) -> String.Index? { + for i in self.startIndex ..< self.endIndex { + var j = i + var found = true + for p in pattern.startIndex ..< pattern.endIndex { + if j == self.endIndex || self[j] != pattern[p] { + found = false + break + } else { + j = j.successor() + } + } + if found { + return i + } + } + return nil + } +} + + + +// A few simple tests + +let s = "Hello, World" +s.indexOf("World") // 7 + +let animals = "🐶🐔🐷🐮🐱" +animals.indexOf("🐮") // 6 diff --git a/Brute-Force String Search/BruteForceStringSearch.playground/contents.xcplayground b/Brute-Force String Search/BruteForceStringSearch.playground/contents.xcplayground new file mode 100644 index 000000000..06828af92 --- /dev/null +++ b/Brute-Force String Search/BruteForceStringSearch.playground/contents.xcplayground @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Brute-Force String Search/BruteForceStringSearch.playground/timeline.xctimeline b/Brute-Force String Search/BruteForceStringSearch.playground/timeline.xctimeline new file mode 100644 index 000000000..bf468afec --- /dev/null +++ b/Brute-Force String Search/BruteForceStringSearch.playground/timeline.xctimeline @@ -0,0 +1,6 @@ + + + + + diff --git a/Brute-Force String Search/BruteForceStringSearch.swift b/Brute-Force String Search/BruteForceStringSearch.swift new file mode 100644 index 000000000..431677a4a --- /dev/null +++ b/Brute-Force String Search/BruteForceStringSearch.swift @@ -0,0 +1,23 @@ +/* + Brute-force string search +*/ +extension String { + func indexOf(pattern: String) -> String.Index? { + for i in self.startIndex ..< self.endIndex { + var j = i + var found = true + for p in pattern.startIndex ..< pattern.endIndex { + if j == self.endIndex || self[j] != pattern[p] { + found = false + break + } else { + j = j.successor() + } + } + if found { + return i + } + } + return nil + } +} diff --git a/Brute-Force String Search/README.markdown b/Brute-Force String Search/README.markdown new file mode 100644 index 000000000..748be872f --- /dev/null +++ b/Brute-Force String Search/README.markdown @@ -0,0 +1,56 @@ +# Brute-Force String Search + +How would you go about writing a string search algorithm in pure Swift if you were not allowed to import Foundation and could not use `NSString`'s `rangeOfString()` method? + +The goal is to implement an `indexOf(pattern: String)` extension on `String` that returns the `String.Index` of the first occurrence of the search pattern, or `nil` if the pattern could not be found inside the string. + +For example: + +```swift +// Input: +let s = "Hello, World" +s.indexOf("World") + +// Output: + 7 + +// Input: +let animals = "🐶🐔🐷🐮🐱" +animals.indexOf("🐮") + +// Output: + 6 +``` + +> **Note:** The index of the cow is 6, not 3 as you might expect, because the string uses more storage per character for emoji. The actual value of the `String.Index` is not so important, just that it points at the right character in the string. + +Here is a brute-force solution: + +```swift +extension String { + func indexOf(pattern: String) -> String.Index? { + for i in self.startIndex ..< self.endIndex { + var j = i + var found = true + for p in pattern.startIndex ..< pattern.endIndex { + if j == self.endIndex || self[j] != pattern[p] { + found = false + break + } else { + j = j.successor() + } + } + if found { + return i + } + } + return nil + } +} +``` + +This looks at each character in the source string in turn. If the character equals the first character of the search pattern, then the inner loop checks whether the rest of the pattern matches. If no match is found, the outer loop continues where it left off. This repeats until a complete match is found or the end of the source string is reached. + +The brute-force approach works OK, but it's not very efficient (or pretty). It should work fine on small strings, though. For a smarter algorithm that works better with large chunks of text, check out [Boyer-Moore](../Boyer-Moore/) string search. + +*Written for Swift Algorithm Club by Matthijs Hollemans* diff --git a/README.markdown b/README.markdown index a81f8a7ce..db22ae68f 100644 --- a/README.markdown +++ b/README.markdown @@ -47,6 +47,7 @@ If you're new to algorithms and data structures, here are a few good ones to sta ### String Search +- [Brute-Force String Search](Brute-Force String Search/). A naive method. - [Boyer-Moore](Boyer-Moore/). A fast method to search for substrings. It skips ahead based on a look-up table, to avoid looking at every character in the text. - Rabin-Karp From b8cc255cd22886ddfa686bc8cc9c375da8493395 Mon Sep 17 00:00:00 2001 From: barbaramartina Date: Thu, 18 Feb 2016 17:44:37 +0100 Subject: [PATCH 0027/1679] Adding project and test target for Array2D data structure --- .../array2Dtest.xcodeproj/project.pbxproj | 409 ++++++++++++++++++ .../array2Dtest/array2Dtest/AppDelegate.swift | 46 ++ .../AppIcon.appiconset/Contents.json | 68 +++ .../Base.lproj/LaunchScreen.storyboard | 27 ++ .../array2Dtest/Base.lproj/Main.storyboard | 25 ++ Array2D/array2Dtest/array2Dtest/Info.plist | 47 ++ .../array2Dtest/ViewController.swift | 25 ++ .../array2Dtest/array2DtestTests/Info.plist | 24 + .../array2DtestTests/array2DtestTests.swift | 88 ++++ 9 files changed, 759 insertions(+) create mode 100644 Array2D/array2Dtest/array2Dtest.xcodeproj/project.pbxproj create mode 100644 Array2D/array2Dtest/array2Dtest/AppDelegate.swift create mode 100644 Array2D/array2Dtest/array2Dtest/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 Array2D/array2Dtest/array2Dtest/Base.lproj/LaunchScreen.storyboard create mode 100644 Array2D/array2Dtest/array2Dtest/Base.lproj/Main.storyboard create mode 100644 Array2D/array2Dtest/array2Dtest/Info.plist create mode 100644 Array2D/array2Dtest/array2Dtest/ViewController.swift create mode 100644 Array2D/array2Dtest/array2DtestTests/Info.plist create mode 100644 Array2D/array2Dtest/array2DtestTests/array2DtestTests.swift diff --git a/Array2D/array2Dtest/array2Dtest.xcodeproj/project.pbxproj b/Array2D/array2Dtest/array2Dtest.xcodeproj/project.pbxproj new file mode 100644 index 000000000..b1dae1cd7 --- /dev/null +++ b/Array2D/array2Dtest/array2Dtest.xcodeproj/project.pbxproj @@ -0,0 +1,409 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 766116121C7625C600358E02 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 766116111C7625C600358E02 /* AppDelegate.swift */; }; + 766116141C7625C600358E02 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 766116131C7625C600358E02 /* ViewController.swift */; }; + 766116171C7625C600358E02 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 766116151C7625C600358E02 /* Main.storyboard */; }; + 766116191C7625C700358E02 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 766116181C7625C700358E02 /* Assets.xcassets */; }; + 7661161C1C7625C700358E02 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7661161A1C7625C700358E02 /* LaunchScreen.storyboard */; }; + 766116271C7625C700358E02 /* array2DtestTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 766116261C7625C700358E02 /* array2DtestTests.swift */; }; + 766116321C76261600358E02 /* Array2D.swift in Sources */ = {isa = PBXBuildFile; fileRef = 766116311C76261600358E02 /* Array2D.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 766116231C7625C700358E02 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 766116061C7625C600358E02 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 7661160D1C7625C600358E02; + remoteInfo = array2Dtest; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 7661160E1C7625C600358E02 /* array2Dtest.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = array2Dtest.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 766116111C7625C600358E02 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 766116131C7625C600358E02 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; + 766116161C7625C600358E02 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 766116181C7625C700358E02 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 7661161B1C7625C700358E02 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 7661161D1C7625C700358E02 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 766116221C7625C700358E02 /* array2DtestTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = array2DtestTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 766116261C7625C700358E02 /* array2DtestTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = array2DtestTests.swift; sourceTree = ""; }; + 766116281C7625C700358E02 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 766116311C76261600358E02 /* Array2D.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Array2D.swift; path = ../../Array2D.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 7661160B1C7625C600358E02 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 7661161F1C7625C700358E02 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 766116051C7625C600358E02 = { + isa = PBXGroup; + children = ( + 766116101C7625C600358E02 /* array2Dtest */, + 766116251C7625C700358E02 /* array2DtestTests */, + 7661160F1C7625C600358E02 /* Products */, + ); + sourceTree = ""; + }; + 7661160F1C7625C600358E02 /* Products */ = { + isa = PBXGroup; + children = ( + 7661160E1C7625C600358E02 /* array2Dtest.app */, + 766116221C7625C700358E02 /* array2DtestTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 766116101C7625C600358E02 /* array2Dtest */ = { + isa = PBXGroup; + children = ( + 766116311C76261600358E02 /* Array2D.swift */, + 766116111C7625C600358E02 /* AppDelegate.swift */, + 766116131C7625C600358E02 /* ViewController.swift */, + 766116151C7625C600358E02 /* Main.storyboard */, + 766116181C7625C700358E02 /* Assets.xcassets */, + 7661161A1C7625C700358E02 /* LaunchScreen.storyboard */, + 7661161D1C7625C700358E02 /* Info.plist */, + ); + path = array2Dtest; + sourceTree = ""; + }; + 766116251C7625C700358E02 /* array2DtestTests */ = { + isa = PBXGroup; + children = ( + 766116261C7625C700358E02 /* array2DtestTests.swift */, + 766116281C7625C700358E02 /* Info.plist */, + ); + path = array2DtestTests; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 7661160D1C7625C600358E02 /* array2Dtest */ = { + isa = PBXNativeTarget; + buildConfigurationList = 7661162B1C7625C700358E02 /* Build configuration list for PBXNativeTarget "array2Dtest" */; + buildPhases = ( + 7661160A1C7625C600358E02 /* Sources */, + 7661160B1C7625C600358E02 /* Frameworks */, + 7661160C1C7625C600358E02 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = array2Dtest; + productName = array2Dtest; + productReference = 7661160E1C7625C600358E02 /* array2Dtest.app */; + productType = "com.apple.product-type.application"; + }; + 766116211C7625C700358E02 /* array2DtestTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 7661162E1C7625C700358E02 /* Build configuration list for PBXNativeTarget "array2DtestTests" */; + buildPhases = ( + 7661161E1C7625C700358E02 /* Sources */, + 7661161F1C7625C700358E02 /* Frameworks */, + 766116201C7625C700358E02 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 766116241C7625C700358E02 /* PBXTargetDependency */, + ); + name = array2DtestTests; + productName = array2DtestTests; + productReference = 766116221C7625C700358E02 /* array2DtestTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 766116061C7625C600358E02 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0720; + LastUpgradeCheck = 0720; + ORGANIZATIONNAME = "Swift Algorithm Club"; + TargetAttributes = { + 7661160D1C7625C600358E02 = { + CreatedOnToolsVersion = 7.2.1; + DevelopmentTeam = 6V43LV5QCY; + }; + 766116211C7625C700358E02 = { + CreatedOnToolsVersion = 7.2.1; + DevelopmentTeam = 6V43LV5QCY; + TestTargetID = 7661160D1C7625C600358E02; + }; + }; + }; + buildConfigurationList = 766116091C7625C600358E02 /* Build configuration list for PBXProject "array2Dtest" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 766116051C7625C600358E02; + productRefGroup = 7661160F1C7625C600358E02 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 7661160D1C7625C600358E02 /* array2Dtest */, + 766116211C7625C700358E02 /* array2DtestTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 7661160C1C7625C600358E02 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 7661161C1C7625C700358E02 /* LaunchScreen.storyboard in Resources */, + 766116191C7625C700358E02 /* Assets.xcassets in Resources */, + 766116171C7625C600358E02 /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 766116201C7625C700358E02 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 7661160A1C7625C600358E02 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 766116141C7625C600358E02 /* ViewController.swift in Sources */, + 766116321C76261600358E02 /* Array2D.swift in Sources */, + 766116121C7625C600358E02 /* AppDelegate.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 7661161E1C7625C700358E02 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 766116271C7625C700358E02 /* array2DtestTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 766116241C7625C700358E02 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 7661160D1C7625C600358E02 /* array2Dtest */; + targetProxy = 766116231C7625C700358E02 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 766116151C7625C600358E02 /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 766116161C7625C600358E02 /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 7661161A1C7625C700358E02 /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 7661161B1C7625C700358E02 /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 766116291C7625C700358E02 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.2; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 7661162A1C7625C700358E02 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.2; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 7661162C1C7625C700358E02 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = array2Dtest/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.sac.array2Dtest; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 7661162D1C7625C700358E02 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = array2Dtest/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.sac.array2Dtest; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + 7661162F1C7625C700358E02 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + INFOPLIST_FILE = array2DtestTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.sac.array2DtestTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/array2Dtest.app/array2Dtest"; + }; + name = Debug; + }; + 766116301C7625C700358E02 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + INFOPLIST_FILE = array2DtestTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.sac.array2DtestTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/array2Dtest.app/array2Dtest"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 766116091C7625C600358E02 /* Build configuration list for PBXProject "array2Dtest" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 766116291C7625C700358E02 /* Debug */, + 7661162A1C7625C700358E02 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 7661162B1C7625C700358E02 /* Build configuration list for PBXNativeTarget "array2Dtest" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7661162C1C7625C700358E02 /* Debug */, + 7661162D1C7625C700358E02 /* Release */, + ); + defaultConfigurationIsVisible = 0; + }; + 7661162E1C7625C700358E02 /* Build configuration list for PBXNativeTarget "array2DtestTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7661162F1C7625C700358E02 /* Debug */, + 766116301C7625C700358E02 /* Release */, + ); + defaultConfigurationIsVisible = 0; + }; +/* End XCConfigurationList section */ + }; + rootObject = 766116061C7625C600358E02 /* Project object */; +} diff --git a/Array2D/array2Dtest/array2Dtest/AppDelegate.swift b/Array2D/array2Dtest/array2Dtest/AppDelegate.swift new file mode 100644 index 000000000..7d1c32f11 --- /dev/null +++ b/Array2D/array2Dtest/array2Dtest/AppDelegate.swift @@ -0,0 +1,46 @@ +// +// AppDelegate.swift +// array2Dtest +// +// Created by Barbara Rodeker on 2/18/16. +// Copyright © 2016 Swift Algorithm Club. All rights reserved. +// + +import UIKit + +@UIApplicationMain +class AppDelegate: UIResponder, UIApplicationDelegate { + + var window: UIWindow? + + + func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { + // Override point for customization after application launch. + return true + } + + func applicationWillResignActive(application: UIApplication) { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. + } + + func applicationDidEnterBackground(application: UIApplication) { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. + } + + func applicationWillEnterForeground(application: UIApplication) { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. + } + + func applicationDidBecomeActive(application: UIApplication) { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. + } + + func applicationWillTerminate(application: UIApplication) { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. + } + + +} + diff --git a/Array2D/array2Dtest/array2Dtest/Assets.xcassets/AppIcon.appiconset/Contents.json b/Array2D/array2Dtest/array2Dtest/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 000000000..36d2c80d8 --- /dev/null +++ b/Array2D/array2Dtest/array2Dtest/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,68 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Array2D/array2Dtest/array2Dtest/Base.lproj/LaunchScreen.storyboard b/Array2D/array2Dtest/array2Dtest/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 000000000..2e721e183 --- /dev/null +++ b/Array2D/array2Dtest/array2Dtest/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Array2D/array2Dtest/array2Dtest/Base.lproj/Main.storyboard b/Array2D/array2Dtest/array2Dtest/Base.lproj/Main.storyboard new file mode 100644 index 000000000..3a2a49bad --- /dev/null +++ b/Array2D/array2Dtest/array2Dtest/Base.lproj/Main.storyboard @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Array2D/array2Dtest/array2Dtest/Info.plist b/Array2D/array2Dtest/array2Dtest/Info.plist new file mode 100644 index 000000000..40c6215d9 --- /dev/null +++ b/Array2D/array2Dtest/array2Dtest/Info.plist @@ -0,0 +1,47 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/Array2D/array2Dtest/array2Dtest/ViewController.swift b/Array2D/array2Dtest/array2Dtest/ViewController.swift new file mode 100644 index 000000000..669b79b89 --- /dev/null +++ b/Array2D/array2Dtest/array2Dtest/ViewController.swift @@ -0,0 +1,25 @@ +// +// ViewController.swift +// array2Dtest +// +// Created by Barbara Rodeker on 2/18/16. +// Copyright © 2016 Swift Algorithm Club. All rights reserved. +// + +import UIKit + +class ViewController: UIViewController { + + override func viewDidLoad() { + super.viewDidLoad() + // Do any additional setup after loading the view, typically from a nib. + } + + override func didReceiveMemoryWarning() { + super.didReceiveMemoryWarning() + // Dispose of any resources that can be recreated. + } + + +} + diff --git a/Array2D/array2Dtest/array2DtestTests/Info.plist b/Array2D/array2Dtest/array2DtestTests/Info.plist new file mode 100644 index 000000000..ba72822e8 --- /dev/null +++ b/Array2D/array2Dtest/array2DtestTests/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/Array2D/array2Dtest/array2DtestTests/array2DtestTests.swift b/Array2D/array2Dtest/array2DtestTests/array2DtestTests.swift new file mode 100644 index 000000000..0292449b4 --- /dev/null +++ b/Array2D/array2Dtest/array2DtestTests/array2DtestTests.swift @@ -0,0 +1,88 @@ +// +// Array2DTest.swift +// algorithmclub +// +// Created by Barbara Rodeker on 2/16/16. +// Copyright © 2016 Swift Algorithm Club. All rights reserved. +// + +import XCTest +@testable import array2Dtest + +class Array2DTest: XCTestCase { + + override func setUp() { + super.setUp() + } + + override func tearDown() { + super.tearDown() + } + + func testIntegerArrayWithPositiveRowsAndColumns() { + let array = Array2D(columns: 3, rows: 2, initialValue: 0) + XCTAssert(array.columns == 3, "Column count setup worked") + XCTAssert(array.rows == 2, "Rows count setup worked") + XCTAssert(array[2,2] == 0, "Integer array: Initialization value properly read") + } + + func testStringArrayWithPositiveRowsAndColumns() { + let array = Array2D(columns: 3, rows: 2, initialValue: "empty") + XCTAssert(array.columns == 3, "Column count setup worked") + XCTAssert(array.rows == 2, "Rows count setup worked") + XCTAssert(array[2,2] == "empty", "String array: Initialization value properly read") + } + + func testCustomClassArrayWithPositiveRowsAndColumns() { + let array = Array2D(columns: 3, rows: 2, initialValue: TestElement(identifier: "pepe")) + XCTAssert(array.columns == 3, "Column count setup worked") + XCTAssert(array.rows == 2, "Rows count setup worked") + XCTAssert(array[2,2] == TestElement(identifier: "pepe"), "Custom Class array: Initialization value properly read") + } + + func testArrayWithNegativeColumns() { + let array = Array2D(columns: -1,rows: 2,initialValue: 0) + XCTAssertNil(array) + } + + func testAccessingWrongIndex() { + let array = Array2D(columns: 2, rows: 4, initialValue: 5) + XCTAssertNil(array[20,20], "Array in 20,20 is not a valid index") + } + + func testPerformanceOnSmallArray() { + self.measureBlock { + self.printArrayWith(columns: 2, rows: 2, inititalValue: 1) + } + } + + func testPerformanceOnLargeArray() { + self.measureBlock { + self.printArrayWith(columns: 2000000, rows: 2000000, inititalValue: 1) + } + } + + private func printArrayWith(columns columns: Int, rows: Int, inititalValue: Int){ + let array = Array2D(columns: columns, rows: rows, initialValue: 4) + for r in 0.. Bool { + return lhs.identifier == rhs.identifier +} + From 905dd1a6cf93724336ba26d3d3e8a6e36f446a25 Mon Sep 17 00:00:00 2001 From: Donald Pinckney Date: Thu, 18 Feb 2016 11:41:24 -0800 Subject: [PATCH 0028/1679] Fix formatting, implement methods to lookup edges. --- .../Contents.swift | 59 ----------- .../contents.xcplayground | 4 - .../timeline.xctimeline | 6 -- .../Contents.swift | 51 +++++++--- .../Contents.swift | 97 +++++++++++-------- 5 files changed, 97 insertions(+), 120 deletions(-) delete mode 100644 Graph/Graph Adjacency Matrix.playground/Contents.swift delete mode 100644 Graph/Graph Adjacency Matrix.playground/contents.xcplayground delete mode 100644 Graph/Graph Adjacency Matrix.playground/timeline.xctimeline diff --git a/Graph/Graph Adjacency Matrix.playground/Contents.swift b/Graph/Graph Adjacency Matrix.playground/Contents.swift deleted file mode 100644 index 2d634e0c0..000000000 --- a/Graph/Graph Adjacency Matrix.playground/Contents.swift +++ /dev/null @@ -1,59 +0,0 @@ - - -public struct GraphVertex { - public var data: T - let uniqueID: Int -} - -public struct Graph { - - private var adjacencyMatrix: [[Int?]] = [] // row-major - - public init() { } // Silence default constructor - - public mutating func createVertex(data: T) -> GraphVertex { - let vertex = GraphVertex(data: data, uniqueID: adjacencyMatrix.count) - - // Expand each existing row to the right one column - for i in 0.. dest. Represented by M[source][dest] = weight - public mutating func connect(sourceVertex: GraphVertex, toDestinationVertex: GraphVertex, withWeight weight: Int = 0) { - adjacencyMatrix[sourceVertex.uniqueID][toDestinationVertex.uniqueID] = weight - } - - // Creates an undirected edge by making 2 directed edges: some ----> other, and other ----> some - public mutating func connect(someVertex: GraphVertex, withVertex: GraphVertex, withWeight weight: Int = 0) { - adjacencyMatrix[someVertex.uniqueID][withVertex.uniqueID] = weight - adjacencyMatrix[withVertex.uniqueID][someVertex.uniqueID] = weight - - } -} - - - - -var graph = Graph() -let v1 = graph.createVertex(1) -let v2 = graph.createVertex(2) -let v3 = graph.createVertex(3) -let v4 = graph.createVertex(4) - -// v1 ---> v2 ---> v3 ---> v4 -// ^ | -// | V -// -----------<------------| - -graph.connect(v1, toDestinationVertex: v2) -graph.connect(v2, toDestinationVertex: v3) -graph.connect(v3, toDestinationVertex: v4) -graph.connect(v4, toDestinationVertex: v1) diff --git a/Graph/Graph Adjacency Matrix.playground/contents.xcplayground b/Graph/Graph Adjacency Matrix.playground/contents.xcplayground deleted file mode 100644 index 5da2641c9..000000000 --- a/Graph/Graph Adjacency Matrix.playground/contents.xcplayground +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/Graph/Graph Adjacency Matrix.playground/timeline.xctimeline b/Graph/Graph Adjacency Matrix.playground/timeline.xctimeline deleted file mode 100644 index bf468afec..000000000 --- a/Graph/Graph Adjacency Matrix.playground/timeline.xctimeline +++ /dev/null @@ -1,6 +0,0 @@ - - - - - diff --git a/Graph/Graph.playground/Pages/Adjacency List.xcplaygroundpage/Contents.swift b/Graph/Graph.playground/Pages/Adjacency List.xcplaygroundpage/Contents.swift index 17c0514ea..3f7ea7e9a 100644 --- a/Graph/Graph.playground/Pages/Adjacency List.xcplaygroundpage/Contents.swift +++ b/Graph/Graph.playground/Pages/Adjacency List.xcplaygroundpage/Contents.swift @@ -4,34 +4,51 @@ A graph implementation, using an adjacency list. In an adjacency list implementation, each vertex stores an array of edges, indicating to which vertices it has an edge (note the directionality). The edge stores the source and destination vertices, as well as a weight. -Connected vertices in this implementation is O(1). +Connecting vertices in this implementation is O(1). */ +var uniqueIDCounter: Int = 0 + public struct GraphEdge { public let from: GraphVertex public let to: GraphVertex public let weight: Double } + public struct GraphVertex { public var data: T - public private(set) var edges: [GraphEdge] = [] // This is a simple adjacency list, rather than matrix + public private(set) var edges: [GraphEdge] = [] // This is an adjacency list, rather than matrix + + private let uniqueID: Int public init(data: T) { self.data = data + uniqueID = uniqueIDCounter + uniqueIDCounter += 1 } // Creates a directed edge self -----> dest - public mutating func connectTo(destinationVertex: GraphVertex, withWeight weight: Double = 0) { + public mutating func connectTo(destinationVertex: GraphVertex, withWeight weight: Double = 1.0) { edges.append(GraphEdge(from: self, to: destinationVertex, weight: weight)) } // Creates an undirected edge by making 2 directed edges: self ----> other, and other ----> self - public mutating func connectBetween(inout otherVertex: GraphVertex, withWeight weight: Double = 0) { + public mutating func connectBetween(inout otherVertex: GraphVertex, withWeight weight: Double = 1.0) { edges.append(GraphEdge(from: self, to: otherVertex, weight: weight)) otherVertex.edges.append(GraphEdge(from: otherVertex, to: self, weight: weight)) } + + public func edgeTo(otherVertex: GraphVertex) -> GraphEdge? { + for e in edges { + if e.to.uniqueID == otherVertex.uniqueID { + return e + } + } + + return nil + } } @@ -43,15 +60,25 @@ var v3 = GraphVertex(data: 3) var v4 = GraphVertex(data: 4) // Setup a cycle like so: -// v1 ---> v2 ---> v3 ---> v4 -// ^ | -// | V -// -----------<------------| +// v1 ---(1)---> v2 ---(1)---> v3 ---(4.5)---> v4 +// ^ | +// | V +// ---------<-----------<---------(2.8)----<----| + +v1.connectTo(v2, withWeight: 1.0) +v2.connectTo(v3, withWeight: 1.0) +v3.connectTo(v4, withWeight: 4.5) +v4.connectTo(v1, withWeight: 2.8) + +// Returns the weight of the edge from v1 to v2 (1.0) +v1.edgeTo(v2)?.weight -v1.connectTo(v2) -v2.connectTo(v3) -v3.connectTo(v4) -v4.connectTo(v1) +// Returns the weight of the edge from v1 to v3 (nil, since there is not an edge) +v1.edgeTo(v3)?.weight +// Returns the weight of the edge from v3 to v4 (4.5) +v3.edgeTo(v4)?.weight +// Returns the weight of the edge from v4 to v1 (2.8) +v4.edgeTo(v1)?.weight //: [Next](@next) diff --git a/Graph/Graph.playground/Pages/Adjacency Matrix.xcplaygroundpage/Contents.swift b/Graph/Graph.playground/Pages/Adjacency Matrix.xcplaygroundpage/Contents.swift index 4fffc4d40..5cff241fb 100644 --- a/Graph/Graph.playground/Pages/Adjacency Matrix.xcplaygroundpage/Contents.swift +++ b/Graph/Graph.playground/Pages/Adjacency Matrix.xcplaygroundpage/Contents.swift @@ -11,43 +11,49 @@ Connecting vertices os O(1). */ public struct GraphVertex { - public var data: T - private let uniqueID: Int + public var data: T + private let uniqueID: Int } public struct Graph { + + // nil entries are used to mark that two vertices are NOT connected. + // If adjacencyMatrix[i][j] is not nil, then there is an edge from vertex i to vertex j. + private var adjacencyMatrix: [[Double?]] = [] + + public init() { } + + public mutating func createVertex(data: T) -> GraphVertex { + let vertex = GraphVertex(data: data, uniqueID: adjacencyMatrix.count) - // nil entries are used to mark that two vertices are NOT connected. - private var adjacencyMatrix: [[Double?]] = [] - - public init() { } - - public mutating func createVertex(data: T) -> GraphVertex { - let vertex = GraphVertex(data: data, uniqueID: adjacencyMatrix.count) - - // Expand each existing row to the right one column - for i in 0.. dest. Represented by M[source][dest] = weight - public mutating func connect(sourceVertex: GraphVertex, toDestinationVertex: GraphVertex, withWeight weight: Double = 0) { - adjacencyMatrix[sourceVertex.uniqueID][toDestinationVertex.uniqueID] = weight - } + // Add one new row at the bottom + let newRow = [Double?](count: adjacencyMatrix.count + 1, repeatedValue: nil) + adjacencyMatrix.append(newRow) - // Creates an undirected edge by making 2 directed edges: some ----> other, and other ----> some - public mutating func connect(someVertex: GraphVertex, withVertex: GraphVertex, withWeight weight: Double = 0) { - adjacencyMatrix[someVertex.uniqueID][withVertex.uniqueID] = weight - adjacencyMatrix[withVertex.uniqueID][someVertex.uniqueID] = weight - - } + return vertex + } + + // Creates a directed edge source -----> dest. Represented by M[source][dest] = weight + public mutating func connect(sourceVertex: GraphVertex, toDestinationVertex: GraphVertex, withWeight weight: Double = 0) { + adjacencyMatrix[sourceVertex.uniqueID][toDestinationVertex.uniqueID] = weight + } + + // Creates an undirected edge by making 2 directed edges: some ----> other, and other ----> some + public mutating func connect(someVertex: GraphVertex, symmetricallyWithVertex withVertex: GraphVertex, withWeight weight: Double = 0) { + adjacencyMatrix[someVertex.uniqueID][withVertex.uniqueID] = weight + adjacencyMatrix[withVertex.uniqueID][someVertex.uniqueID] = weight + + } + + public func weightFrom(sourceVertex: GraphVertex, toDestinationVertex: GraphVertex) -> Double? { + return adjacencyMatrix[sourceVertex.uniqueID][toDestinationVertex.uniqueID] + } + } @@ -60,12 +66,25 @@ let v3 = graph.createVertex(3) let v4 = graph.createVertex(4) // Setup a cycle like so: -// v1 ---> v2 ---> v3 ---> v4 -// ^ | -// | V -// -----------<------------| - -graph.connect(v1, toDestinationVertex: v2) -graph.connect(v2, toDestinationVertex: v3) -graph.connect(v3, toDestinationVertex: v4) -graph.connect(v4, toDestinationVertex: v1) +// v1 ---(1)---> v2 ---(1)---> v3 ---(4.5)---> v4 +// ^ | +// | V +// ---------<-----------<---------(2.8)----<----| + +graph.connect(v1, toDestinationVertex: v2, withWeight: 1.0) +graph.connect(v2, toDestinationVertex: v3, withWeight: 1.0) +graph.connect(v3, toDestinationVertex: v4, withWeight: 4.5) +graph.connect(v4, toDestinationVertex: v1, withWeight: 2.8) + +// Returns the weight of the edge from v1 to v2 (1.0) +graph.weightFrom(v1, toDestinationVertex: v2) + +// Returns the weight of the edge from v1 to v3 (nil, since there is not an edge) +graph.weightFrom(v1, toDestinationVertex: v3) + +// Returns the weight of the edge from v3 to v4 (4.5) +graph.weightFrom(v3, toDestinationVertex: v4) + +// Returns the weight of the edge from v4 to v1 (2.8) +graph.weightFrom(v4, toDestinationVertex: v1) + From 8008a24c7a6a631191dcc57191456a9084658867 Mon Sep 17 00:00:00 2001 From: Robert Thompson Date: Thu, 18 Feb 2016 17:46:11 -0500 Subject: [PATCH 0029/1679] Initial commit --- Treap/Treap.swift | 160 ++++ Treap/Treap/Treap.xcodeproj/project.pbxproj | 400 ++++++++++ Treap/Treap/Treap/AppDelegate.swift | 27 + .../AppIcon.appiconset/Contents.json | 58 ++ Treap/Treap/Treap/Base.lproj/MainMenu.xib | 681 ++++++++++++++++++ Treap/Treap/Treap/Info.plist | 34 + Treap/Treap/TreapTests/Info.plist | 24 + Treap/Treap/TreapTests/TreapTests.swift | 57 ++ Treap/TreapCollectionType.swift | 81 +++ Treap/TreapMergeSplit.swift | 113 +++ 10 files changed, 1635 insertions(+) create mode 100644 Treap/Treap.swift create mode 100644 Treap/Treap/Treap.xcodeproj/project.pbxproj create mode 100644 Treap/Treap/Treap/AppDelegate.swift create mode 100644 Treap/Treap/Treap/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 Treap/Treap/Treap/Base.lproj/MainMenu.xib create mode 100644 Treap/Treap/Treap/Info.plist create mode 100644 Treap/Treap/TreapTests/Info.plist create mode 100644 Treap/Treap/TreapTests/TreapTests.swift create mode 100644 Treap/TreapCollectionType.swift create mode 100644 Treap/TreapMergeSplit.swift diff --git a/Treap/Treap.swift b/Treap/Treap.swift new file mode 100644 index 000000000..108eec913 --- /dev/null +++ b/Treap/Treap.swift @@ -0,0 +1,160 @@ +// +// Treap.swift +// TreapExample +// +// Created by Robert Thompson on 7/27/15. +// Copyright © 2015 Robert Thompson. All rights reserved. +// + +import Foundation + +public indirect enum Treap { + case Empty + case Node(key: Key, val: Element, p: Int, left: Treap, right: Treap) + + public init() { + self = .Empty + } + + internal func get(key: Key) -> Element? { + switch self { + case .Empty: + return nil + case let .Node(treeKey, val, _, _, _) where treeKey == key: + return val + case let .Node(treeKey, _, _, left, _) where key < treeKey: + return left.get(key) + case let .Node(treeKey, _, _, _, right) where key > treeKey: + return right.get(key) + default: + return nil + } + } + + public func contains(key: Key) -> Bool { + switch self { + case .Empty: + return false + case let .Node(treeKey, _, _, _, _) where treeKey == key: + return true + case let .Node(treeKey, _, _, left, _) where key < treeKey: + return left.contains(key) + case let .Node(treeKey, _, _, _, right) where key > treeKey: + return right.contains(key) + default: + return false + } + } + + public var depth: Int { + get { + switch self { + case .Empty: + return 0 + case let .Node(_, _, _, left, .Empty): + return 1 + left.depth + case let .Node(_, _, _, .Empty, right): + return 1 + right.depth + case let .Node(_, _, _, left, right): + let leftDepth = left.depth + let rightDepth = right.depth + return 1 + max(leftDepth, rightDepth) + } + + } + } + + public var count: Int { + get { + return Treap.countHelper(self) + } + } + + private static func countHelper(treap: Treap) -> Int + { + if case let .Node(_, _, _, left, right) = treap + { + return countHelper(left) + 1 + countHelper(right) + } + + return 0 + } +} + +internal func leftRotate(tree: Treap) -> Treap { + if case let .Node(key, val, p, .Node(leftKey, leftVal, leftP, leftLeft, leftRight), right) = tree { + return .Node(key: leftKey, val: leftVal, p: leftP, left: leftLeft, right: Treap.Node(key: key, val: val, p: p, left: leftRight, right: right)) + } + else + { + return .Empty + } +} + +internal func rightRotate(tree: Treap) -> Treap { + if case let .Node(key, val, p, left, .Node(rightKey, rightVal, rightP, rightLeft, rightRight)) = tree { + return .Node(key: rightKey, val: rightVal, p: rightP, left: Treap.Node(key: key, val: val, p: p, left: left, right: rightLeft), right: rightRight) + } + else + { + return .Empty + } +} + +public extension Treap { + internal func set(key: Key, val: Element, p: Int = Int(arc4random())) -> Treap { + switch self { + case .Empty: + return .Node(key: key, val: val, p: p, left: .Empty, right: .Empty) + case let .Node(nodeKey, nodeVal, nodeP, left, right) where key != nodeKey: + return insertAndBalance(nodeKey, nodeVal, nodeP, left, right, key, val, p) + case let .Node(nodeKey, _, nodeP, left, right) where key == nodeKey: + return .Node(key: key, val: val, p: nodeP, left: left, right: right) + default: // should never happen + return .Empty + } + + } + + private func insertAndBalance(nodeKey: Key, _ nodeVal: Element, _ nodeP: Int, _ left: Treap, _ right: Treap, _ key: Key, _ val: Element, _ p: Int) -> Treap { + let newChild: Treap + let newNode: Treap + let rotate: (Treap) -> Treap + if key < nodeKey { + newChild = left.set(key, val: val, p: p) + newNode = .Node(key: nodeKey, val: nodeVal, p: nodeP, left: newChild, right: right) + rotate = leftRotate + } + else if key > nodeKey { + newChild = right.set(key, val: val, p: p) + newNode = .Node(key: nodeKey, val: nodeVal, p: nodeP, left: left, right: newChild) + rotate = rightRotate + } + else { + // It should be impossible to reach here + newChild = .Empty + newNode = .Empty + return newNode + } + + if case let .Node(_, _, newChildP, _, _) = newChild where newChildP < nodeP { + return rotate(newNode) + } + else { + return newNode + } + } + + internal func delete(key: Key) throws -> Treap { + switch self { + case .Empty: + throw NSError(domain: "com.wta.treap.errorDomain", code: -1, userInfo: nil) + case let .Node(nodeKey, val, p, left, right) where key < nodeKey: + return try Treap.Node(key: nodeKey, val: val, p: p, left: left.delete(key), right: right) + case let .Node(nodeKey, val, p, left, right) where key > nodeKey: + return try Treap.Node(key: nodeKey, val: val, p: p, left: left, right: right.delete(key)) + case let .Node(_, _, _, left, right): + return merge(left, right: right) + } + } +} diff --git a/Treap/Treap/Treap.xcodeproj/project.pbxproj b/Treap/Treap/Treap.xcodeproj/project.pbxproj new file mode 100644 index 000000000..319a22f37 --- /dev/null +++ b/Treap/Treap/Treap.xcodeproj/project.pbxproj @@ -0,0 +1,400 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + E1E34DC71C7670240023AF4D /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1E34DC61C7670240023AF4D /* AppDelegate.swift */; }; + E1E34DC91C7670240023AF4D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E1E34DC81C7670240023AF4D /* Assets.xcassets */; }; + E1E34DCC1C7670240023AF4D /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = E1E34DCA1C7670240023AF4D /* MainMenu.xib */; }; + E1E34DD71C7670250023AF4D /* TreapTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1E34DD61C7670250023AF4D /* TreapTests.swift */; }; + E1E34DE31C7670350023AF4D /* Treap.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1E34DE11C7670350023AF4D /* Treap.swift */; }; + E1E34DE41C7670350023AF4D /* TreapMergeSplit.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1E34DE21C7670350023AF4D /* TreapMergeSplit.swift */; }; + E1E34DEA1C7671200023AF4D /* TreapCollectionType.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1E34DE91C7671200023AF4D /* TreapCollectionType.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + E1E34DD31C7670250023AF4D /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = E1E34DBB1C7670240023AF4D /* Project object */; + proxyType = 1; + remoteGlobalIDString = E1E34DC21C7670240023AF4D; + remoteInfo = Treap; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + E1E34DC31C7670240023AF4D /* Treap.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Treap.app; sourceTree = BUILT_PRODUCTS_DIR; }; + E1E34DC61C7670240023AF4D /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + E1E34DC81C7670240023AF4D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + E1E34DCB1C7670240023AF4D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; + E1E34DCD1C7670240023AF4D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + E1E34DD21C7670250023AF4D /* TreapTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TreapTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + E1E34DD61C7670250023AF4D /* TreapTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TreapTests.swift; sourceTree = ""; }; + E1E34DD81C7670250023AF4D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + E1E34DE11C7670350023AF4D /* Treap.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Treap.swift; path = ../../Treap.swift; sourceTree = ""; }; + E1E34DE21C7670350023AF4D /* TreapMergeSplit.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = TreapMergeSplit.swift; path = ../../TreapMergeSplit.swift; sourceTree = ""; }; + E1E34DE91C7671200023AF4D /* TreapCollectionType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = TreapCollectionType.swift; path = ../../TreapCollectionType.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + E1E34DC01C7670240023AF4D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E1E34DCF1C7670250023AF4D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + E1E34DBA1C7670240023AF4D = { + isa = PBXGroup; + children = ( + E1E34DC51C7670240023AF4D /* Treap */, + E1E34DD51C7670250023AF4D /* TreapTests */, + E1E34DC41C7670240023AF4D /* Products */, + ); + sourceTree = ""; + }; + E1E34DC41C7670240023AF4D /* Products */ = { + isa = PBXGroup; + children = ( + E1E34DC31C7670240023AF4D /* Treap.app */, + E1E34DD21C7670250023AF4D /* TreapTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + E1E34DC51C7670240023AF4D /* Treap */ = { + isa = PBXGroup; + children = ( + E1E34DC61C7670240023AF4D /* AppDelegate.swift */, + E1E34DC81C7670240023AF4D /* Assets.xcassets */, + E1E34DCA1C7670240023AF4D /* MainMenu.xib */, + E1E34DE11C7670350023AF4D /* Treap.swift */, + E1E34DE21C7670350023AF4D /* TreapMergeSplit.swift */, + E1E34DE91C7671200023AF4D /* TreapCollectionType.swift */, + E1E34DCD1C7670240023AF4D /* Info.plist */, + ); + path = Treap; + sourceTree = ""; + }; + E1E34DD51C7670250023AF4D /* TreapTests */ = { + isa = PBXGroup; + children = ( + E1E34DD61C7670250023AF4D /* TreapTests.swift */, + E1E34DD81C7670250023AF4D /* Info.plist */, + ); + path = TreapTests; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + E1E34DC21C7670240023AF4D /* Treap */ = { + isa = PBXNativeTarget; + buildConfigurationList = E1E34DDB1C7670250023AF4D /* Build configuration list for PBXNativeTarget "Treap" */; + buildPhases = ( + E1E34DBF1C7670240023AF4D /* Sources */, + E1E34DC01C7670240023AF4D /* Frameworks */, + E1E34DC11C7670240023AF4D /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Treap; + productName = Treap; + productReference = E1E34DC31C7670240023AF4D /* Treap.app */; + productType = "com.apple.product-type.application"; + }; + E1E34DD11C7670250023AF4D /* TreapTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = E1E34DDE1C7670250023AF4D /* Build configuration list for PBXNativeTarget "TreapTests" */; + buildPhases = ( + E1E34DCE1C7670250023AF4D /* Sources */, + E1E34DCF1C7670250023AF4D /* Frameworks */, + E1E34DD01C7670250023AF4D /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + E1E34DD41C7670250023AF4D /* PBXTargetDependency */, + ); + name = TreapTests; + productName = TreapTests; + productReference = E1E34DD21C7670250023AF4D /* TreapTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + E1E34DBB1C7670240023AF4D /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0720; + LastUpgradeCheck = 0720; + ORGANIZATIONNAME = "WillowTree, Inc."; + TargetAttributes = { + E1E34DC21C7670240023AF4D = { + CreatedOnToolsVersion = 7.2.1; + }; + E1E34DD11C7670250023AF4D = { + CreatedOnToolsVersion = 7.2.1; + TestTargetID = E1E34DC21C7670240023AF4D; + }; + }; + }; + buildConfigurationList = E1E34DBE1C7670240023AF4D /* Build configuration list for PBXProject "Treap" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = E1E34DBA1C7670240023AF4D; + productRefGroup = E1E34DC41C7670240023AF4D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + E1E34DC21C7670240023AF4D /* Treap */, + E1E34DD11C7670250023AF4D /* TreapTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + E1E34DC11C7670240023AF4D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + E1E34DC91C7670240023AF4D /* Assets.xcassets in Resources */, + E1E34DCC1C7670240023AF4D /* MainMenu.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E1E34DD01C7670250023AF4D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + E1E34DBF1C7670240023AF4D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + E1E34DEA1C7671200023AF4D /* TreapCollectionType.swift in Sources */, + E1E34DE31C7670350023AF4D /* Treap.swift in Sources */, + E1E34DC71C7670240023AF4D /* AppDelegate.swift in Sources */, + E1E34DE41C7670350023AF4D /* TreapMergeSplit.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E1E34DCE1C7670250023AF4D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + E1E34DD71C7670250023AF4D /* TreapTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + E1E34DD41C7670250023AF4D /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = E1E34DC21C7670240023AF4D /* Treap */; + targetProxy = E1E34DD31C7670250023AF4D /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + E1E34DCA1C7670240023AF4D /* MainMenu.xib */ = { + isa = PBXVariantGroup; + children = ( + E1E34DCB1C7670240023AF4D /* Base */, + ); + name = MainMenu.xib; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + E1E34DD91C7670250023AF4D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + E1E34DDA1C7670250023AF4D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + }; + name = Release; + }; + E1E34DDC1C7670250023AF4D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Treap/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.willowtree.Treap; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + E1E34DDD1C7670250023AF4D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Treap/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.willowtree.Treap; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + E1E34DDF1C7670250023AF4D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = TreapTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.willowtree.TreapTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Treap.app/Contents/MacOS/Treap"; + }; + name = Debug; + }; + E1E34DE01C7670250023AF4D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = TreapTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.willowtree.TreapTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Treap.app/Contents/MacOS/Treap"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + E1E34DBE1C7670240023AF4D /* Build configuration list for PBXProject "Treap" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + E1E34DD91C7670250023AF4D /* Debug */, + E1E34DDA1C7670250023AF4D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + E1E34DDB1C7670250023AF4D /* Build configuration list for PBXNativeTarget "Treap" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + E1E34DDC1C7670250023AF4D /* Debug */, + E1E34DDD1C7670250023AF4D /* Release */, + ); + defaultConfigurationIsVisible = 0; + }; + E1E34DDE1C7670250023AF4D /* Build configuration list for PBXNativeTarget "TreapTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + E1E34DDF1C7670250023AF4D /* Debug */, + E1E34DE01C7670250023AF4D /* Release */, + ); + defaultConfigurationIsVisible = 0; + }; +/* End XCConfigurationList section */ + }; + rootObject = E1E34DBB1C7670240023AF4D /* Project object */; +} diff --git a/Treap/Treap/Treap/AppDelegate.swift b/Treap/Treap/Treap/AppDelegate.swift new file mode 100644 index 000000000..a156c1cb4 --- /dev/null +++ b/Treap/Treap/Treap/AppDelegate.swift @@ -0,0 +1,27 @@ +// +// AppDelegate.swift +// Treap +// +// Created by Robert Thompson on 2/18/16. +// Copyright © 2016 WillowTree, Inc. All rights reserved. +// + +import Cocoa + +@NSApplicationMain +class AppDelegate: NSObject, NSApplicationDelegate { + + @IBOutlet weak var window: NSWindow! + + + func applicationDidFinishLaunching(aNotification: NSNotification) { + // Insert code here to initialize your application + } + + func applicationWillTerminate(aNotification: NSNotification) { + // Insert code here to tear down your application + } + + +} + diff --git a/Treap/Treap/Treap/Assets.xcassets/AppIcon.appiconset/Contents.json b/Treap/Treap/Treap/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 000000000..2db2b1c7c --- /dev/null +++ b/Treap/Treap/Treap/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,58 @@ +{ + "images" : [ + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Treap/Treap/Treap/Base.lproj/MainMenu.xib b/Treap/Treap/Treap/Base.lproj/MainMenu.xib new file mode 100644 index 000000000..8955ad822 --- /dev/null +++ b/Treap/Treap/Treap/Base.lproj/MainMenu.xib @@ -0,0 +1,681 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Default + + + + + + + Left to Right + + + + + + + Right to Left + + + + + + + + + + + Default + + + + + + + Left to Right + + + + + + + Right to Left + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Treap/Treap/Treap/Info.plist b/Treap/Treap/Treap/Info.plist new file mode 100644 index 000000000..63294f2da --- /dev/null +++ b/Treap/Treap/Treap/Info.plist @@ -0,0 +1,34 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + Copyright © 2016 WillowTree, Inc. All rights reserved. + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/Treap/Treap/TreapTests/Info.plist b/Treap/Treap/TreapTests/Info.plist new file mode 100644 index 000000000..ba72822e8 --- /dev/null +++ b/Treap/Treap/TreapTests/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/Treap/Treap/TreapTests/TreapTests.swift b/Treap/Treap/TreapTests/TreapTests.swift new file mode 100644 index 000000000..06421ad78 --- /dev/null +++ b/Treap/Treap/TreapTests/TreapTests.swift @@ -0,0 +1,57 @@ +// +// TreapTests.swift +// TreapTests +// +// Created by Robert Thompson on 2/18/16. +// Copyright © 2016 WillowTree, Inc. All rights reserved. +// + +import XCTest +@testable import Treap + +class TreapTests: XCTestCase { + + override func setUp() { + super.setUp() + // Put setup code here. This method is called before the invocation of each test method in the class. + } + + override func tearDown() { + // Put teardown code here. This method is called after the invocation of each test method in the class. + super.tearDown() + } + + func testSanity() { + var treap = Treap.Empty + treap = treap.set(5, val: "a").set(7, val: "b") + XCTAssert(treap.get(5) == "a") + XCTAssert(treap.get(7) == "b") + treap = treap.set(2, val: "c") + XCTAssert(treap.get(2) == "c") + treap = treap.set(2, val: "d") + XCTAssert(treap.get(2) == "d") + treap = try! treap.delete(5) + XCTAssert(!treap.contains(5)) + XCTAssert(treap.contains(7)) + } + + func testFairlyBalanced() { + var treap = Treap.Empty + for i in 0..<1000 { + treap = treap.set(i, val: nil) + } + let depth = treap.depth + XCTAssert(depth < 30, "treap.depth was \(depth)") + } + + func testFairlyBalancedCollection() { + var treap = Treap() + for i in 0..<1000 + { + treap[i] = Optional.None + } + let depth = treap.depth + XCTAssert(depth > 0 && depth < 30) + } + +} diff --git a/Treap/TreapCollectionType.swift b/Treap/TreapCollectionType.swift new file mode 100644 index 000000000..9753b6207 --- /dev/null +++ b/Treap/TreapCollectionType.swift @@ -0,0 +1,81 @@ +// +// TreapCollectionType.swift +// Treap +// +// Created by Robert Thompson on 2/18/16. +// Copyright © 2016 WillowTree, Inc. All rights reserved. +// + +import Foundation + +extension Treap: CollectionType { + public typealias Index = TreapIndex + + public subscript(index: TreapIndex) -> Element { + get { + guard let result = self.get(index.keys[index.keyIndex]) else { + fatalError("Invalid index!") + } + + return result + } + + mutating set { + let key = index.keys[index.keyIndex] + self = self.set(key, val: newValue) + } + } + + public subscript(key: Key) -> Element? { + get { + return self.get(key) + } + + mutating set { + guard let value = newValue else { + let _ = try? self.delete(key) + return + } + + self = self.set(key, val: value) + } + } + + public var startIndex: TreapIndex { + return TreapIndex(keys: keys, keyIndex: 0) + } + + public var endIndex: TreapIndex { + let keys = self.keys + return TreapIndex(keys: keys, keyIndex: keys.count) + } + + private var keys: [Key] { + var results: [Key] = [] + if case let .Node(key, _, _, left, right) = self { + results.appendContentsOf(left.keys) + results.append(key) + results.appendContentsOf(right.keys) + } + + return results + } +} + +public struct TreapIndex: ForwardIndexType { + private let keys: [Key] + private let keyIndex: Int + + public func successor() -> TreapIndex { + return TreapIndex(keys: keys, keyIndex: keyIndex + 1) + } + + private init(keys: [Key] = [], keyIndex: Int = 0) { + self.keys = keys + self.keyIndex = keyIndex + } +} + +public func ==(lhs: TreapIndex, rhs: TreapIndex) -> Bool { + return lhs.keys == rhs.keys && lhs.keyIndex == rhs.keyIndex +} diff --git a/Treap/TreapMergeSplit.swift b/Treap/TreapMergeSplit.swift new file mode 100644 index 000000000..eed6d3d94 --- /dev/null +++ b/Treap/TreapMergeSplit.swift @@ -0,0 +1,113 @@ +// +// TreapMergeSplit.swift +// TreapExample +// +// Created by Robert Thompson on 7/27/15. +// Copyright © 2015 Robert Thompson. All rights reserved. +// + +import Foundation +public extension Treap { + internal func split(key: Key) -> (left: Treap, right: Treap) + { + var current = self + let val: Element + if let newVal = self.get(key) + { + current = try! current.delete(key) + val = newVal + } + else if case let .Node(_, newVal, _, _, _) = self + { + val = newVal + } + else + { + fatalError("No values in treap") + } + + switch self { + case .Node: + if case let .Node(_, _, _, left, right) = current.set(key, val: val, p: -1) + { + return (left: left, right: right) + } + else + { + return (left: .Empty, right: .Empty) + } + default: + return (left: .Empty, right: .Empty) + } + } + + internal var leastKey: Key? { + switch self { + case .Empty: + return nil + case let .Node(key, _, _, .Empty, _): + return key + case let .Node(_, _, _, left, _): + return left.leastKey + } + } + + internal var mostKey: Key? { + switch self { + case .Empty: + return nil + case let .Node(key, _, _, _, .Empty): + return key + case let .Node(_, _, _, _, right): + return right.mostKey + } + } +} + +internal func merge(left: Treap, right: Treap) -> Treap { + switch (left, right) { + case (.Empty, _): + return right + case (_, .Empty): + return left + + case let (.Node(leftKey, leftVal, leftP, leftLeft, leftRight), .Node(rightKey, rightVal, rightP, rightLeft, rightRight)): + if leftP < rightP { + return .Node(key: leftKey, val: leftVal, p: leftP, left: leftLeft, right: merge(leftRight, right: right)) + } + else + { + return .Node(key: rightKey, val: rightVal, p: rightP, left: merge(rightLeft, right: left), right: rightRight) + } + default: + break + } + return .Empty +} + +extension Treap: CustomStringConvertible +{ + public var description: String { + get { + return Treap.descHelper(self, indent: 0) + } + } + + private static func descHelper(treap: Treap, indent: Int) -> String + { + if case let .Node(key, value, priority, left, right) = treap { + var result = "" + let tabs = String(count: indent, repeatedValue: Character("\t")) + + result += descHelper(left, indent: indent + 1) + result += "\n" + tabs + "\(key), \(value), \(priority)\n" + result += descHelper(right, indent: indent + 1) + + return result + } + else + { + return "" + } + } +} \ No newline at end of file From 0598dc1d9105322489522d79d67a64574e8538fc Mon Sep 17 00:00:00 2001 From: Robert Thompson Date: Thu, 18 Feb 2016 17:59:35 -0500 Subject: [PATCH 0030/1679] May as well be BidirectionalIndexType --- Treap/TreapCollectionType.swift | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Treap/TreapCollectionType.swift b/Treap/TreapCollectionType.swift index 9753b6207..a4f37c0b7 100644 --- a/Treap/TreapCollectionType.swift +++ b/Treap/TreapCollectionType.swift @@ -62,7 +62,7 @@ extension Treap: CollectionType { } } -public struct TreapIndex: ForwardIndexType { +public struct TreapIndex: BidirectionalIndexType { private let keys: [Key] private let keyIndex: Int @@ -70,6 +70,10 @@ public struct TreapIndex: ForwardIndexType { return TreapIndex(keys: keys, keyIndex: keyIndex + 1) } + public func predecessor() -> TreapIndex { + return TreapIndex(keys: keys, keyIndex: keyIndex - 1) + } + private init(keys: [Key] = [], keyIndex: Int = 0) { self.keys = keys self.keyIndex = keyIndex From d88f10e94866e1cd6088d6236fcadbf379b51603 Mon Sep 17 00:00:00 2001 From: Robert Thompson Date: Thu, 18 Feb 2016 18:01:22 -0500 Subject: [PATCH 0031/1679] Honestly it's MutableCollectionType --- Treap/TreapCollectionType.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Treap/TreapCollectionType.swift b/Treap/TreapCollectionType.swift index a4f37c0b7..f624bf265 100644 --- a/Treap/TreapCollectionType.swift +++ b/Treap/TreapCollectionType.swift @@ -8,7 +8,7 @@ import Foundation -extension Treap: CollectionType { +extension Treap: MutableCollectionType { public typealias Index = TreapIndex public subscript(index: TreapIndex) -> Element { From f907963c4ec7eb795a550ec0d35aeecccf66edb0 Mon Sep 17 00:00:00 2001 From: barbaramartina Date: Fri, 19 Feb 2016 11:09:03 +0100 Subject: [PATCH 0032/1679] Reducing the number of columns and rows for testing big arrays 2D --- .../array2DtestTests/array2DtestTests.swift | 34 +++++++------------ 1 file changed, 13 insertions(+), 21 deletions(-) diff --git a/Array2D/array2Dtest/array2DtestTests/array2DtestTests.swift b/Array2D/array2Dtest/array2DtestTests/array2DtestTests.swift index 0292449b4..926819e45 100644 --- a/Array2D/array2Dtest/array2DtestTests/array2DtestTests.swift +++ b/Array2D/array2Dtest/array2DtestTests/array2DtestTests.swift @@ -21,33 +21,26 @@ class Array2DTest: XCTestCase { func testIntegerArrayWithPositiveRowsAndColumns() { let array = Array2D(columns: 3, rows: 2, initialValue: 0) - XCTAssert(array.columns == 3, "Column count setup worked") - XCTAssert(array.rows == 2, "Rows count setup worked") - XCTAssert(array[2,2] == 0, "Integer array: Initialization value properly read") + + XCTAssertEqual(array.columns, 3, "Column count setup failed") + XCTAssertEqual(array.rows, 2, "Rows count setup failed") + XCTAssertEqual(array[2,1], 0, "Integer array: Initialization value is wrong") } func testStringArrayWithPositiveRowsAndColumns() { let array = Array2D(columns: 3, rows: 2, initialValue: "empty") - XCTAssert(array.columns == 3, "Column count setup worked") - XCTAssert(array.rows == 2, "Rows count setup worked") - XCTAssert(array[2,2] == "empty", "String array: Initialization value properly read") + + XCTAssertEqual(array.columns, 3, "Column count setup failed") + XCTAssertEqual(array.rows, 2, "Rows count setup failed") + XCTAssertEqual(array[2,1], "empty", "String array: Initialization value is wrong") } func testCustomClassArrayWithPositiveRowsAndColumns() { let array = Array2D(columns: 3, rows: 2, initialValue: TestElement(identifier: "pepe")) - XCTAssert(array.columns == 3, "Column count setup worked") - XCTAssert(array.rows == 2, "Rows count setup worked") - XCTAssert(array[2,2] == TestElement(identifier: "pepe"), "Custom Class array: Initialization value properly read") - } - - func testArrayWithNegativeColumns() { - let array = Array2D(columns: -1,rows: 2,initialValue: 0) - XCTAssertNil(array) - } - - func testAccessingWrongIndex() { - let array = Array2D(columns: 2, rows: 4, initialValue: 5) - XCTAssertNil(array[20,20], "Array in 20,20 is not a valid index") + + XCTAssertEqual(array.columns, 3, "Column count setup failed") + XCTAssertEqual(array.rows, 2, "Rows count setup failed") + XCTAssertEqual(array[2,1], TestElement(identifier: "pepe"), "Custom Class array: Initialization value is wrong") } func testPerformanceOnSmallArray() { @@ -58,7 +51,7 @@ class Array2DTest: XCTestCase { func testPerformanceOnLargeArray() { self.measureBlock { - self.printArrayWith(columns: 2000000, rows: 2000000, inititalValue: 1) + self.printArrayWith(columns: 2000, rows: 2000, inititalValue: 1) } } @@ -79,7 +72,6 @@ class TestElement : Equatable { init(identifier: String) { self.identifier = identifier } - } func == (lhs: TestElement, rhs: TestElement) -> Bool { From 77152547da2314c0a03937eaf41cc8d16963c1ef Mon Sep 17 00:00:00 2001 From: barbaramartina Date: Fri, 19 Feb 2016 14:00:58 +0100 Subject: [PATCH 0033/1679] Tests for AVLTree --- .../AVLTreeTests.xcodeproj/project.pbxproj | 415 ++++++++++++++++++ .../AVLTreeTests/AppDelegate.swift | 46 ++ .../AppIcon.appiconset/Contents.json | 68 +++ .../Base.lproj/LaunchScreen.storyboard | 27 ++ .../AVLTreeTests/Base.lproj/Main.storyboard | 25 ++ .../AVLTreeTests/AVLTreeTests/Info.plist | 47 ++ .../AVLTreeTests/ViewController.swift | 25 ++ .../AVLTreeTestsTests/AVLTreeTestsTests.swift | 82 ++++ .../AVLTreeTests/AVLTreeTestsTests/Info.plist | 24 + .../AVLTreeTestsTests/TreeNodeTest.swift | 86 ++++ 10 files changed, 845 insertions(+) create mode 100644 AVLtreeTest/AVLTreeTests/AVLTreeTests.xcodeproj/project.pbxproj create mode 100644 AVLtreeTest/AVLTreeTests/AVLTreeTests/AppDelegate.swift create mode 100644 AVLtreeTest/AVLTreeTests/AVLTreeTests/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 AVLtreeTest/AVLTreeTests/AVLTreeTests/Base.lproj/LaunchScreen.storyboard create mode 100644 AVLtreeTest/AVLTreeTests/AVLTreeTests/Base.lproj/Main.storyboard create mode 100644 AVLtreeTest/AVLTreeTests/AVLTreeTests/Info.plist create mode 100644 AVLtreeTest/AVLTreeTests/AVLTreeTests/ViewController.swift create mode 100644 AVLtreeTest/AVLTreeTests/AVLTreeTestsTests/AVLTreeTestsTests.swift create mode 100644 AVLtreeTest/AVLTreeTests/AVLTreeTestsTests/Info.plist create mode 100644 AVLtreeTest/AVLTreeTests/AVLTreeTestsTests/TreeNodeTest.swift diff --git a/AVLtreeTest/AVLTreeTests/AVLTreeTests.xcodeproj/project.pbxproj b/AVLtreeTest/AVLTreeTests/AVLTreeTests.xcodeproj/project.pbxproj new file mode 100644 index 000000000..45e5ceb17 --- /dev/null +++ b/AVLtreeTest/AVLTreeTests/AVLTreeTests.xcodeproj/project.pbxproj @@ -0,0 +1,415 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 763F28681C77228700AABA94 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 763F28671C77228700AABA94 /* AppDelegate.swift */; }; + 763F286A1C77228700AABA94 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 763F28691C77228700AABA94 /* ViewController.swift */; }; + 763F286D1C77228700AABA94 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 763F286B1C77228700AABA94 /* Main.storyboard */; }; + 763F286F1C77228700AABA94 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 763F286E1C77228700AABA94 /* Assets.xcassets */; }; + 763F28721C77228700AABA94 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 763F28701C77228700AABA94 /* LaunchScreen.storyboard */; }; + 763F287D1C77228700AABA94 /* AVLTreeTestsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 763F287C1C77228700AABA94 /* AVLTreeTestsTests.swift */; }; + 763F28881C77229D00AABA94 /* AVLTree.swift in Sources */ = {isa = PBXBuildFile; fileRef = 763F28871C77229D00AABA94 /* AVLTree.swift */; }; + 763F288B1C77254000AABA94 /* TreeNodeTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 763F288A1C77254000AABA94 /* TreeNodeTest.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 763F28791C77228700AABA94 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 763F285C1C77228600AABA94 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 763F28631C77228600AABA94; + remoteInfo = AVLTreeTests; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 763F28641C77228700AABA94 /* AVLTreeTests.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AVLTreeTests.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 763F28671C77228700AABA94 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 763F28691C77228700AABA94 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; + 763F286C1C77228700AABA94 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 763F286E1C77228700AABA94 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 763F28711C77228700AABA94 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 763F28731C77228700AABA94 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 763F28781C77228700AABA94 /* AVLTreeTestsTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AVLTreeTestsTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 763F287C1C77228700AABA94 /* AVLTreeTestsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AVLTreeTestsTests.swift; sourceTree = ""; }; + 763F287E1C77228700AABA94 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 763F28871C77229D00AABA94 /* AVLTree.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = AVLTree.swift; path = "../../../AVL Tree/AVLTree.swift"; sourceTree = ""; }; + 763F28891C7722B700AABA94 /* AVLTree.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; name = AVLTree.playground; path = "../../../AVL Tree/AVLTree.playground"; sourceTree = ""; }; + 763F288A1C77254000AABA94 /* TreeNodeTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TreeNodeTest.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 763F28611C77228600AABA94 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 763F28751C77228700AABA94 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 763F285B1C77228600AABA94 = { + isa = PBXGroup; + children = ( + 763F28661C77228700AABA94 /* AVLTreeTests */, + 763F287B1C77228700AABA94 /* AVLTreeTestsTests */, + 763F28651C77228700AABA94 /* Products */, + ); + sourceTree = ""; + }; + 763F28651C77228700AABA94 /* Products */ = { + isa = PBXGroup; + children = ( + 763F28641C77228700AABA94 /* AVLTreeTests.app */, + 763F28781C77228700AABA94 /* AVLTreeTestsTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 763F28661C77228700AABA94 /* AVLTreeTests */ = { + isa = PBXGroup; + children = ( + 763F28891C7722B700AABA94 /* AVLTree.playground */, + 763F28871C77229D00AABA94 /* AVLTree.swift */, + 763F28671C77228700AABA94 /* AppDelegate.swift */, + 763F28691C77228700AABA94 /* ViewController.swift */, + 763F286B1C77228700AABA94 /* Main.storyboard */, + 763F286E1C77228700AABA94 /* Assets.xcassets */, + 763F28701C77228700AABA94 /* LaunchScreen.storyboard */, + 763F28731C77228700AABA94 /* Info.plist */, + ); + path = AVLTreeTests; + sourceTree = ""; + }; + 763F287B1C77228700AABA94 /* AVLTreeTestsTests */ = { + isa = PBXGroup; + children = ( + 763F287C1C77228700AABA94 /* AVLTreeTestsTests.swift */, + 763F288A1C77254000AABA94 /* TreeNodeTest.swift */, + 763F287E1C77228700AABA94 /* Info.plist */, + ); + path = AVLTreeTestsTests; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 763F28631C77228600AABA94 /* AVLTreeTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 763F28811C77228700AABA94 /* Build configuration list for PBXNativeTarget "AVLTreeTests" */; + buildPhases = ( + 763F28601C77228600AABA94 /* Sources */, + 763F28611C77228600AABA94 /* Frameworks */, + 763F28621C77228600AABA94 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = AVLTreeTests; + productName = AVLTreeTests; + productReference = 763F28641C77228700AABA94 /* AVLTreeTests.app */; + productType = "com.apple.product-type.application"; + }; + 763F28771C77228700AABA94 /* AVLTreeTestsTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 763F28841C77228700AABA94 /* Build configuration list for PBXNativeTarget "AVLTreeTestsTests" */; + buildPhases = ( + 763F28741C77228700AABA94 /* Sources */, + 763F28751C77228700AABA94 /* Frameworks */, + 763F28761C77228700AABA94 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 763F287A1C77228700AABA94 /* PBXTargetDependency */, + ); + name = AVLTreeTestsTests; + productName = AVLTreeTestsTests; + productReference = 763F28781C77228700AABA94 /* AVLTreeTestsTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 763F285C1C77228600AABA94 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0720; + LastUpgradeCheck = 0720; + ORGANIZATIONNAME = "Swift Algorithm Club"; + TargetAttributes = { + 763F28631C77228600AABA94 = { + CreatedOnToolsVersion = 7.2.1; + DevelopmentTeam = 6V43LV5QCY; + }; + 763F28771C77228700AABA94 = { + CreatedOnToolsVersion = 7.2.1; + DevelopmentTeam = 6V43LV5QCY; + TestTargetID = 763F28631C77228600AABA94; + }; + }; + }; + buildConfigurationList = 763F285F1C77228600AABA94 /* Build configuration list for PBXProject "AVLTreeTests" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 763F285B1C77228600AABA94; + productRefGroup = 763F28651C77228700AABA94 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 763F28631C77228600AABA94 /* AVLTreeTests */, + 763F28771C77228700AABA94 /* AVLTreeTestsTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 763F28621C77228600AABA94 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 763F28721C77228700AABA94 /* LaunchScreen.storyboard in Resources */, + 763F286F1C77228700AABA94 /* Assets.xcassets in Resources */, + 763F286D1C77228700AABA94 /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 763F28761C77228700AABA94 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 763F28601C77228600AABA94 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 763F28881C77229D00AABA94 /* AVLTree.swift in Sources */, + 763F286A1C77228700AABA94 /* ViewController.swift in Sources */, + 763F28681C77228700AABA94 /* AppDelegate.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 763F28741C77228700AABA94 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 763F287D1C77228700AABA94 /* AVLTreeTestsTests.swift in Sources */, + 763F288B1C77254000AABA94 /* TreeNodeTest.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 763F287A1C77228700AABA94 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 763F28631C77228600AABA94 /* AVLTreeTests */; + targetProxy = 763F28791C77228700AABA94 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 763F286B1C77228700AABA94 /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 763F286C1C77228700AABA94 /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 763F28701C77228700AABA94 /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 763F28711C77228700AABA94 /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 763F287F1C77228700AABA94 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.2; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 763F28801C77228700AABA94 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.2; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 763F28821C77228700AABA94 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = AVLTreeTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.sac.AVLTreeTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 763F28831C77228700AABA94 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = AVLTreeTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.sac.AVLTreeTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + 763F28851C77228700AABA94 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + INFOPLIST_FILE = AVLTreeTestsTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.sac.AVLTreeTestsTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/AVLTreeTests.app/AVLTreeTests"; + }; + name = Debug; + }; + 763F28861C77228700AABA94 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + INFOPLIST_FILE = AVLTreeTestsTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.sac.AVLTreeTestsTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/AVLTreeTests.app/AVLTreeTests"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 763F285F1C77228600AABA94 /* Build configuration list for PBXProject "AVLTreeTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 763F287F1C77228700AABA94 /* Debug */, + 763F28801C77228700AABA94 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 763F28811C77228700AABA94 /* Build configuration list for PBXNativeTarget "AVLTreeTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 763F28821C77228700AABA94 /* Debug */, + 763F28831C77228700AABA94 /* Release */, + ); + defaultConfigurationIsVisible = 0; + }; + 763F28841C77228700AABA94 /* Build configuration list for PBXNativeTarget "AVLTreeTestsTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 763F28851C77228700AABA94 /* Debug */, + 763F28861C77228700AABA94 /* Release */, + ); + defaultConfigurationIsVisible = 0; + }; +/* End XCConfigurationList section */ + }; + rootObject = 763F285C1C77228600AABA94 /* Project object */; +} diff --git a/AVLtreeTest/AVLTreeTests/AVLTreeTests/AppDelegate.swift b/AVLtreeTest/AVLTreeTests/AVLTreeTests/AppDelegate.swift new file mode 100644 index 000000000..ac29ab4db --- /dev/null +++ b/AVLtreeTest/AVLTreeTests/AVLTreeTests/AppDelegate.swift @@ -0,0 +1,46 @@ +// +// AppDelegate.swift +// AVLTreeTests +// +// Created by Barbara Rodeker on 2/19/16. +// Copyright © 2016 Swift Algorithm Club. All rights reserved. +// + +import UIKit + +@UIApplicationMain +class AppDelegate: UIResponder, UIApplicationDelegate { + + var window: UIWindow? + + + func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { + // Override point for customization after application launch. + return true + } + + func applicationWillResignActive(application: UIApplication) { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. + } + + func applicationDidEnterBackground(application: UIApplication) { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. + } + + func applicationWillEnterForeground(application: UIApplication) { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. + } + + func applicationDidBecomeActive(application: UIApplication) { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. + } + + func applicationWillTerminate(application: UIApplication) { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. + } + + +} + diff --git a/AVLtreeTest/AVLTreeTests/AVLTreeTests/Assets.xcassets/AppIcon.appiconset/Contents.json b/AVLtreeTest/AVLTreeTests/AVLTreeTests/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 000000000..36d2c80d8 --- /dev/null +++ b/AVLtreeTest/AVLTreeTests/AVLTreeTests/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,68 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/AVLtreeTest/AVLTreeTests/AVLTreeTests/Base.lproj/LaunchScreen.storyboard b/AVLtreeTest/AVLTreeTests/AVLTreeTests/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 000000000..2e721e183 --- /dev/null +++ b/AVLtreeTest/AVLTreeTests/AVLTreeTests/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/AVLtreeTest/AVLTreeTests/AVLTreeTests/Base.lproj/Main.storyboard b/AVLtreeTest/AVLTreeTests/AVLTreeTests/Base.lproj/Main.storyboard new file mode 100644 index 000000000..3a2a49bad --- /dev/null +++ b/AVLtreeTest/AVLTreeTests/AVLTreeTests/Base.lproj/Main.storyboard @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/AVLtreeTest/AVLTreeTests/AVLTreeTests/Info.plist b/AVLtreeTest/AVLTreeTests/AVLTreeTests/Info.plist new file mode 100644 index 000000000..40c6215d9 --- /dev/null +++ b/AVLtreeTest/AVLTreeTests/AVLTreeTests/Info.plist @@ -0,0 +1,47 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/AVLtreeTest/AVLTreeTests/AVLTreeTests/ViewController.swift b/AVLtreeTest/AVLTreeTests/AVLTreeTests/ViewController.swift new file mode 100644 index 000000000..88030d517 --- /dev/null +++ b/AVLtreeTest/AVLTreeTests/AVLTreeTests/ViewController.swift @@ -0,0 +1,25 @@ +// +// ViewController.swift +// AVLTreeTests +// +// Created by Barbara Rodeker on 2/19/16. +// Copyright © 2016 Swift Algorithm Club. All rights reserved. +// + +import UIKit + +class ViewController: UIViewController { + + override func viewDidLoad() { + super.viewDidLoad() + // Do any additional setup after loading the view, typically from a nib. + } + + override func didReceiveMemoryWarning() { + super.didReceiveMemoryWarning() + // Dispose of any resources that can be recreated. + } + + +} + diff --git a/AVLtreeTest/AVLTreeTests/AVLTreeTestsTests/AVLTreeTestsTests.swift b/AVLtreeTest/AVLTreeTests/AVLTreeTestsTests/AVLTreeTestsTests.swift new file mode 100644 index 000000000..01ac0b5e5 --- /dev/null +++ b/AVLtreeTest/AVLTreeTests/AVLTreeTestsTests/AVLTreeTestsTests.swift @@ -0,0 +1,82 @@ +// +// AVLTreeTestsTests.swift +// AVLTreeTestsTests +// +// Created by Barbara Rodeker on 2/19/16. +// Copyright © 2016 Swift Algorithm Club. All rights reserved. +// + +import XCTest +@testable import AVLTreeTests + +class AVLTreeTestsTests: XCTestCase { + + var tree : AVLTree? + + override func setUp() { + super.setUp() + + tree = AVLTree() + tree?.insert(1, "A") + tree?.insert(2, "B") + tree?.insert(3, "C") + tree?.insert(4, "D") + } + + override func tearDown() { + // Put teardown code here. This method is called after the invocation of each test method in the class. + super.tearDown() + } + + func testEmptyInitialization() { + let tree = AVLTree() + + XCTAssertEqual(tree.size, 0) + XCTAssertNil(tree.root) + } + + func testNotEmptyInitialization() { + XCTAssertNotNil(self.tree?.root) + XCTAssertNotEqual(self.tree!.size, 0) + } + + func testInsertDuplicated() { + self.tree?.insert(1, "A") + XCTAssertEqual(self.tree?.size, 5, "Duplicated elements should be allowed") + } + + func testSingleInsertionPerformance() { + self.measureBlock { + self.tree?.insert(5, "E") + } + } + + func testMultipleInsertionsPerformance() { + self.measureBlock { + self.tree?.autopopulateWithNodes(50) + } + } + + func testSearchExistentOnSmallTreePerformance() { + self.measureBlock { + self.tree?.search(2) + } + } + + func testSearchExistentElementOnLargeTreePerformance() { + self.measureBlock { + self.tree?.autopopulateWithNodes(500) + self.tree?.search(400) + } + } + +} + +extension AVLTree where Key : SignedIntegerType { + func autopopulateWithNodes(count : Int) { + var k : Key = 1 + for _ in 0...count { + self.insert(k++) + } + } +} diff --git a/AVLtreeTest/AVLTreeTests/AVLTreeTestsTests/Info.plist b/AVLtreeTest/AVLTreeTests/AVLTreeTestsTests/Info.plist new file mode 100644 index 000000000..ba72822e8 --- /dev/null +++ b/AVLtreeTest/AVLTreeTests/AVLTreeTestsTests/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/AVLtreeTest/AVLTreeTests/AVLTreeTestsTests/TreeNodeTest.swift b/AVLtreeTest/AVLTreeTests/AVLTreeTestsTests/TreeNodeTest.swift new file mode 100644 index 000000000..802277ea9 --- /dev/null +++ b/AVLtreeTest/AVLTreeTests/AVLTreeTestsTests/TreeNodeTest.swift @@ -0,0 +1,86 @@ +// +// TreeNodeTest.swift +// AVLTreeTests +// +// Created by Barbara Rodeker on 2/19/16. +// Copyright © 2016 Swift Algorithm Club. All rights reserved. +// + +import XCTest +@testable import AVLTreeTests + + +class TreeNodeTest: XCTestCase { + + var root : TreeNode? + var left : TreeNode? + var right : TreeNode? + + override func setUp() { + super.setUp() + + left = TreeNode(key: "Name", payload: "Left") + right = TreeNode(key: "Name", payload: "Right") + root = TreeNode(key: "Name", payload: "Root", leftChild: left, rightChild: right, parent: nil) + } + + override func tearDown() { + // Put teardown code here. This method is called after the invocation of each test method in the class. + super.tearDown() + } + + + func testSingleNodeCreationNOPayload() { + let treeNode = TreeNode(key: "Building") + XCTAssertNil(treeNode.payload, "Payload for this case should be nil") + } + + func testSingleNodeCreationWithPayload() { + XCTAssertNotNil(self.root!, "Payload for this case should not be nil") + } + + func testIsRoot() { + XCTAssertTrue(self.root!.isRoot) + } + + func testNotIsLeaf() { + XCTAssertFalse(self.root!.isLeaf, "root node is not leaf") + } + + func testNotIsLeftChild() { + XCTAssertFalse(self.root!.isLeftChild, "root node is not left child") + } + + func testNotIsRightChild() { + XCTAssertFalse(self.root!.isRightChild, "root node is not right child") + } + + func testIsLeftChild() { + XCTAssertTrue(self.left!.isLeftChild) + } + + func testIsRightChild() { + XCTAssertTrue(self.right!.isRightChild) + } + + func isLeaf() { + XCTAssertTrue(self.left!.isLeaf) + } + + func testHasAnyChild() { + XCTAssertTrue(self.root!.hasAnyChild) + } + + func testNotHasAnyChild() { + XCTAssertFalse(self.left!.hasAnyChild) + } + + func testHasBothChildren() { + XCTAssertTrue(self.root!.hasBothChildren) + } + + func testNotHasBothChildren() { + XCTAssertFalse(self.left!.hasBothChildren) + } + +} From 3f7090e4f251349f500b800f3390edab43b2069f Mon Sep 17 00:00:00 2001 From: barbaramartina Date: Fri, 19 Feb 2016 14:15:23 +0100 Subject: [PATCH 0034/1679] Setting a parent reference when a child is added to a node. Making parent reference weak --- AVL Tree/AVLTree.swift | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/AVL Tree/AVLTree.swift b/AVL Tree/AVLTree.swift index 12befbe92..d05cd94bf 100644 --- a/AVL Tree/AVLTree.swift +++ b/AVL Tree/AVLTree.swift @@ -28,14 +28,16 @@ public class TreeNode { private var key: Key private var leftChild: Node? private var rightChild: Node? - private var parent: Node? + weak private var parent: Node? private var balance = 0 public init(key: Key, payload: Payload?, leftChild: Node?, rightChild: Node?, parent: Node?) { self.key = key self.payload = payload self.leftChild = leftChild + self.leftChild?.parent = self self.rightChild = rightChild + self.rightChild?.parent = self self.parent = parent } From 3aee5c4bb82acd7cdf123af523ff0eaef4516446 Mon Sep 17 00:00:00 2001 From: barbaramartina Date: Fri, 19 Feb 2016 14:21:27 +0100 Subject: [PATCH 0035/1679] Moving AVL test inside its main algortihms folder, commiting shared project data --- .../AVLTreeTests.xcodeproj/project.pbxproj | 0 .../AVLTreeTests/AppDelegate.swift | 0 .../AppIcon.appiconset/Contents.json | 0 .../Base.lproj/LaunchScreen.storyboard | 0 .../AVLTreeTests/Base.lproj/Main.storyboard | 0 .../AVLTreeTests/AVLTreeTests/Info.plist | 0 .../AVLTreeTests/ViewController.swift | 0 .../AVLTreeTestsTests/AVLTreeTestsTests.swift | 0 .../AVLTreeTests/AVLTreeTestsTests/Info.plist | 0 .../AVLTreeTestsTests/TreeNodeTest.swift | 0 ...B9780967-0BD8-4A91-8657-A96EFB81859F.plist | 22 ++++++++++ .../Info.plist | 40 +++++++++++++++++++ 12 files changed, 62 insertions(+) rename {AVLtreeTest => AVL Tree}/AVLTreeTests/AVLTreeTests.xcodeproj/project.pbxproj (100%) rename {AVLtreeTest => AVL Tree}/AVLTreeTests/AVLTreeTests/AppDelegate.swift (100%) rename {AVLtreeTest => AVL Tree}/AVLTreeTests/AVLTreeTests/Assets.xcassets/AppIcon.appiconset/Contents.json (100%) rename {AVLtreeTest => AVL Tree}/AVLTreeTests/AVLTreeTests/Base.lproj/LaunchScreen.storyboard (100%) rename {AVLtreeTest => AVL Tree}/AVLTreeTests/AVLTreeTests/Base.lproj/Main.storyboard (100%) rename {AVLtreeTest => AVL Tree}/AVLTreeTests/AVLTreeTests/Info.plist (100%) rename {AVLtreeTest => AVL Tree}/AVLTreeTests/AVLTreeTests/ViewController.swift (100%) rename {AVLtreeTest => AVL Tree}/AVLTreeTests/AVLTreeTestsTests/AVLTreeTestsTests.swift (100%) rename {AVLtreeTest => AVL Tree}/AVLTreeTests/AVLTreeTestsTests/Info.plist (100%) rename {AVLtreeTest => AVL Tree}/AVLTreeTests/AVLTreeTestsTests/TreeNodeTest.swift (100%) create mode 100644 Array2D/array2Dtest/array2Dtest.xcodeproj/xcshareddata/xcbaselines/766116211C7625C700358E02.xcbaseline/B9780967-0BD8-4A91-8657-A96EFB81859F.plist create mode 100644 Array2D/array2Dtest/array2Dtest.xcodeproj/xcshareddata/xcbaselines/766116211C7625C700358E02.xcbaseline/Info.plist diff --git a/AVLtreeTest/AVLTreeTests/AVLTreeTests.xcodeproj/project.pbxproj b/AVL Tree/AVLTreeTests/AVLTreeTests.xcodeproj/project.pbxproj similarity index 100% rename from AVLtreeTest/AVLTreeTests/AVLTreeTests.xcodeproj/project.pbxproj rename to AVL Tree/AVLTreeTests/AVLTreeTests.xcodeproj/project.pbxproj diff --git a/AVLtreeTest/AVLTreeTests/AVLTreeTests/AppDelegate.swift b/AVL Tree/AVLTreeTests/AVLTreeTests/AppDelegate.swift similarity index 100% rename from AVLtreeTest/AVLTreeTests/AVLTreeTests/AppDelegate.swift rename to AVL Tree/AVLTreeTests/AVLTreeTests/AppDelegate.swift diff --git a/AVLtreeTest/AVLTreeTests/AVLTreeTests/Assets.xcassets/AppIcon.appiconset/Contents.json b/AVL Tree/AVLTreeTests/AVLTreeTests/Assets.xcassets/AppIcon.appiconset/Contents.json similarity index 100% rename from AVLtreeTest/AVLTreeTests/AVLTreeTests/Assets.xcassets/AppIcon.appiconset/Contents.json rename to AVL Tree/AVLTreeTests/AVLTreeTests/Assets.xcassets/AppIcon.appiconset/Contents.json diff --git a/AVLtreeTest/AVLTreeTests/AVLTreeTests/Base.lproj/LaunchScreen.storyboard b/AVL Tree/AVLTreeTests/AVLTreeTests/Base.lproj/LaunchScreen.storyboard similarity index 100% rename from AVLtreeTest/AVLTreeTests/AVLTreeTests/Base.lproj/LaunchScreen.storyboard rename to AVL Tree/AVLTreeTests/AVLTreeTests/Base.lproj/LaunchScreen.storyboard diff --git a/AVLtreeTest/AVLTreeTests/AVLTreeTests/Base.lproj/Main.storyboard b/AVL Tree/AVLTreeTests/AVLTreeTests/Base.lproj/Main.storyboard similarity index 100% rename from AVLtreeTest/AVLTreeTests/AVLTreeTests/Base.lproj/Main.storyboard rename to AVL Tree/AVLTreeTests/AVLTreeTests/Base.lproj/Main.storyboard diff --git a/AVLtreeTest/AVLTreeTests/AVLTreeTests/Info.plist b/AVL Tree/AVLTreeTests/AVLTreeTests/Info.plist similarity index 100% rename from AVLtreeTest/AVLTreeTests/AVLTreeTests/Info.plist rename to AVL Tree/AVLTreeTests/AVLTreeTests/Info.plist diff --git a/AVLtreeTest/AVLTreeTests/AVLTreeTests/ViewController.swift b/AVL Tree/AVLTreeTests/AVLTreeTests/ViewController.swift similarity index 100% rename from AVLtreeTest/AVLTreeTests/AVLTreeTests/ViewController.swift rename to AVL Tree/AVLTreeTests/AVLTreeTests/ViewController.swift diff --git a/AVLtreeTest/AVLTreeTests/AVLTreeTestsTests/AVLTreeTestsTests.swift b/AVL Tree/AVLTreeTests/AVLTreeTestsTests/AVLTreeTestsTests.swift similarity index 100% rename from AVLtreeTest/AVLTreeTests/AVLTreeTestsTests/AVLTreeTestsTests.swift rename to AVL Tree/AVLTreeTests/AVLTreeTestsTests/AVLTreeTestsTests.swift diff --git a/AVLtreeTest/AVLTreeTests/AVLTreeTestsTests/Info.plist b/AVL Tree/AVLTreeTests/AVLTreeTestsTests/Info.plist similarity index 100% rename from AVLtreeTest/AVLTreeTests/AVLTreeTestsTests/Info.plist rename to AVL Tree/AVLTreeTests/AVLTreeTestsTests/Info.plist diff --git a/AVLtreeTest/AVLTreeTests/AVLTreeTestsTests/TreeNodeTest.swift b/AVL Tree/AVLTreeTests/AVLTreeTestsTests/TreeNodeTest.swift similarity index 100% rename from AVLtreeTest/AVLTreeTests/AVLTreeTestsTests/TreeNodeTest.swift rename to AVL Tree/AVLTreeTests/AVLTreeTestsTests/TreeNodeTest.swift diff --git a/Array2D/array2Dtest/array2Dtest.xcodeproj/xcshareddata/xcbaselines/766116211C7625C700358E02.xcbaseline/B9780967-0BD8-4A91-8657-A96EFB81859F.plist b/Array2D/array2Dtest/array2Dtest.xcodeproj/xcshareddata/xcbaselines/766116211C7625C700358E02.xcbaseline/B9780967-0BD8-4A91-8657-A96EFB81859F.plist new file mode 100644 index 000000000..124dc73bc --- /dev/null +++ b/Array2D/array2Dtest/array2Dtest.xcodeproj/xcshareddata/xcbaselines/766116211C7625C700358E02.xcbaseline/B9780967-0BD8-4A91-8657-A96EFB81859F.plist @@ -0,0 +1,22 @@ + + + + + classNames + + Array2DTest + + testPerformanceOnSmallArray() + + com.apple.XCTPerformanceMetric_WallClockTime + + baselineAverage + 0.377 + baselineIntegrationDisplayName + Local Baseline + + + + + + diff --git a/Array2D/array2Dtest/array2Dtest.xcodeproj/xcshareddata/xcbaselines/766116211C7625C700358E02.xcbaseline/Info.plist b/Array2D/array2Dtest/array2Dtest.xcodeproj/xcshareddata/xcbaselines/766116211C7625C700358E02.xcbaseline/Info.plist new file mode 100644 index 000000000..a0e45b60a --- /dev/null +++ b/Array2D/array2Dtest/array2Dtest.xcodeproj/xcshareddata/xcbaselines/766116211C7625C700358E02.xcbaseline/Info.plist @@ -0,0 +1,40 @@ + + + + + runDestinationsByUUID + + B9780967-0BD8-4A91-8657-A96EFB81859F + + localComputer + + busSpeedInMHz + 100 + cpuCount + 1 + cpuKind + Intel Core i5 + cpuSpeedInMHz + 2500 + logicalCPUCoresPerPackage + 4 + modelCode + Macmini6,1 + physicalCPUCoresPerPackage + 2 + platformIdentifier + com.apple.platform.macosx + + targetArchitecture + x86_64 + targetDevice + + modelCode + iPhone8,2 + platformIdentifier + com.apple.platform.iphonesimulator + + + + + From f75c9e814624d24d6b792f695101e9dd02e58250 Mon Sep 17 00:00:00 2001 From: Matthijs Hollemans Date: Fri, 19 Feb 2016 16:29:46 +0100 Subject: [PATCH 0036/1679] Add link to rosettacode.org --- Big-O Notation.markdown | 2 +- README.markdown | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Big-O Notation.markdown b/Big-O Notation.markdown index 20c0d9dea..8cb988168 100644 --- a/Big-O Notation.markdown +++ b/Big-O Notation.markdown @@ -14,7 +14,7 @@ Big-O | Name | Description **O(n log n)** | "linearithmic" | **Decent performance.** This is slightly worse than linear but not too bad. Example: the fastest general-purpose sorting algorithms. **O(n^2)** | quadratic | **Kinda slow.** If you have 100 items, this does 100^2 = 10,000 units of work. Doubling the number of items makes it four times slower (because 2 squared equals 4). Example: algorithms using nested loops, such as insertion sort. **O(n^3)** | cubic | **Poor performance.** If you have 100 items, this does 100^3 = 1,000,000 units of work. Doubling the input size makes it eight times slower. Example: matrix multiplication. -**O(2^n)** | exponential | **Very poor performance.** You want to avoid these kinds of algorithms, but sometimes you have no choice. Example: traveling salesperson problem. +**O(2^n)** | exponential | **Very poor performance.** You want to avoid these kinds of algorithms, but sometimes you have no choice. Adding just one bit to the input doubles the running time. Example: traveling salesperson problem. **O(n!)** | factorial | **Intolerably slow.** It literally takes a million years to do anything. Often you don't need math to figure out what the Big-O of an algorithm is but you can simply use your intuition. If your code uses a single loop that looks at all **n** elements of your input, the algorithm is **O(n)**. If the code has two nested loops, it is **O(n^2)**. Three nested loops gives **O(n^3)**, and so on. diff --git a/README.markdown b/README.markdown index db22ae68f..8a08a7575 100644 --- a/README.markdown +++ b/README.markdown @@ -188,9 +188,10 @@ The following books are available for free online: - [Algorithms + Data Structures = Programs](http://www.ethoberon.ethz.ch/WirthPubl/AD.pdf) by Wirth - Algorithms and Data Structures: The Basic Toolbox by Mehlhorn and Sanders -Friends of the club: +Other algorithm repositories: - [EKAlgorithms](https://github.com/EvgenyKarkan/EKAlgorithms). A great collection of algorithms in Objective-C. +- [Rosetta Code](http://rosettacode.org). Implementations in pretty much any language you can think of. ## License From 56a7ec75ea1cf313ffa365e344a4d76749d52256 Mon Sep 17 00:00:00 2001 From: Matthijs Hollemans Date: Fri, 19 Feb 2016 16:51:49 +0100 Subject: [PATCH 0037/1679] Small tweaks to folder names for tests --- .../AVLTreeTests.xcodeproj/project.pbxproj | 0 .../AVLTreeTests/AppDelegate.swift | 0 .../Assets.xcassets/AppIcon.appiconset/Contents.json | 0 .../AVLTreeTests/Base.lproj/LaunchScreen.storyboard | 0 .../AVLTreeTests/Base.lproj/Main.storyboard | 0 .../AVLTreeTests/Info.plist | 0 .../AVLTreeTests/ViewController.swift | 0 .../AVLTreeTestsTests/AVLTreeTestsTests.swift | 0 .../AVLTreeTestsTests/Info.plist | 0 .../AVLTreeTestsTests/TreeNodeTest.swift | 0 .../array2Dtest.xcodeproj/project.pbxproj | 0 .../B9780967-0BD8-4A91-8657-A96EFB81859F.plist | 0 .../766116211C7625C700358E02.xcbaseline/Info.plist | 0 .../array2Dtest/AppDelegate.swift | 0 .../Assets.xcassets/AppIcon.appiconset/Contents.json | 0 .../array2Dtest/Base.lproj/LaunchScreen.storyboard | 0 .../array2Dtest/Base.lproj/Main.storyboard | 0 .../array2Dtest/Info.plist | 0 .../array2Dtest/ViewController.swift | 0 .../array2DtestTests/Info.plist | 0 .../array2DtestTests/array2DtestTests.swift | 10 +++++----- 21 files changed, 5 insertions(+), 5 deletions(-) rename AVL Tree/{AVLTreeTests => AVLTree Tests}/AVLTreeTests.xcodeproj/project.pbxproj (100%) rename AVL Tree/{AVLTreeTests => AVLTree Tests}/AVLTreeTests/AppDelegate.swift (100%) rename AVL Tree/{AVLTreeTests => AVLTree Tests}/AVLTreeTests/Assets.xcassets/AppIcon.appiconset/Contents.json (100%) rename AVL Tree/{AVLTreeTests => AVLTree Tests}/AVLTreeTests/Base.lproj/LaunchScreen.storyboard (100%) rename AVL Tree/{AVLTreeTests => AVLTree Tests}/AVLTreeTests/Base.lproj/Main.storyboard (100%) rename AVL Tree/{AVLTreeTests => AVLTree Tests}/AVLTreeTests/Info.plist (100%) rename AVL Tree/{AVLTreeTests => AVLTree Tests}/AVLTreeTests/ViewController.swift (100%) rename AVL Tree/{AVLTreeTests => AVLTree Tests}/AVLTreeTestsTests/AVLTreeTestsTests.swift (100%) rename AVL Tree/{AVLTreeTests => AVLTree Tests}/AVLTreeTestsTests/Info.plist (100%) rename AVL Tree/{AVLTreeTests => AVLTree Tests}/AVLTreeTestsTests/TreeNodeTest.swift (100%) rename Array2D/{array2Dtest => Array2D Tests}/array2Dtest.xcodeproj/project.pbxproj (100%) rename Array2D/{array2Dtest => Array2D Tests}/array2Dtest.xcodeproj/xcshareddata/xcbaselines/766116211C7625C700358E02.xcbaseline/B9780967-0BD8-4A91-8657-A96EFB81859F.plist (100%) rename Array2D/{array2Dtest => Array2D Tests}/array2Dtest.xcodeproj/xcshareddata/xcbaselines/766116211C7625C700358E02.xcbaseline/Info.plist (100%) rename Array2D/{array2Dtest => Array2D Tests}/array2Dtest/AppDelegate.swift (100%) rename Array2D/{array2Dtest => Array2D Tests}/array2Dtest/Assets.xcassets/AppIcon.appiconset/Contents.json (100%) rename Array2D/{array2Dtest => Array2D Tests}/array2Dtest/Base.lproj/LaunchScreen.storyboard (100%) rename Array2D/{array2Dtest => Array2D Tests}/array2Dtest/Base.lproj/Main.storyboard (100%) rename Array2D/{array2Dtest => Array2D Tests}/array2Dtest/Info.plist (100%) rename Array2D/{array2Dtest => Array2D Tests}/array2Dtest/ViewController.swift (100%) rename Array2D/{array2Dtest => Array2D Tests}/array2DtestTests/Info.plist (100%) rename Array2D/{array2Dtest => Array2D Tests}/array2DtestTests/array2DtestTests.swift (93%) diff --git a/AVL Tree/AVLTreeTests/AVLTreeTests.xcodeproj/project.pbxproj b/AVL Tree/AVLTree Tests/AVLTreeTests.xcodeproj/project.pbxproj similarity index 100% rename from AVL Tree/AVLTreeTests/AVLTreeTests.xcodeproj/project.pbxproj rename to AVL Tree/AVLTree Tests/AVLTreeTests.xcodeproj/project.pbxproj diff --git a/AVL Tree/AVLTreeTests/AVLTreeTests/AppDelegate.swift b/AVL Tree/AVLTree Tests/AVLTreeTests/AppDelegate.swift similarity index 100% rename from AVL Tree/AVLTreeTests/AVLTreeTests/AppDelegate.swift rename to AVL Tree/AVLTree Tests/AVLTreeTests/AppDelegate.swift diff --git a/AVL Tree/AVLTreeTests/AVLTreeTests/Assets.xcassets/AppIcon.appiconset/Contents.json b/AVL Tree/AVLTree Tests/AVLTreeTests/Assets.xcassets/AppIcon.appiconset/Contents.json similarity index 100% rename from AVL Tree/AVLTreeTests/AVLTreeTests/Assets.xcassets/AppIcon.appiconset/Contents.json rename to AVL Tree/AVLTree Tests/AVLTreeTests/Assets.xcassets/AppIcon.appiconset/Contents.json diff --git a/AVL Tree/AVLTreeTests/AVLTreeTests/Base.lproj/LaunchScreen.storyboard b/AVL Tree/AVLTree Tests/AVLTreeTests/Base.lproj/LaunchScreen.storyboard similarity index 100% rename from AVL Tree/AVLTreeTests/AVLTreeTests/Base.lproj/LaunchScreen.storyboard rename to AVL Tree/AVLTree Tests/AVLTreeTests/Base.lproj/LaunchScreen.storyboard diff --git a/AVL Tree/AVLTreeTests/AVLTreeTests/Base.lproj/Main.storyboard b/AVL Tree/AVLTree Tests/AVLTreeTests/Base.lproj/Main.storyboard similarity index 100% rename from AVL Tree/AVLTreeTests/AVLTreeTests/Base.lproj/Main.storyboard rename to AVL Tree/AVLTree Tests/AVLTreeTests/Base.lproj/Main.storyboard diff --git a/AVL Tree/AVLTreeTests/AVLTreeTests/Info.plist b/AVL Tree/AVLTree Tests/AVLTreeTests/Info.plist similarity index 100% rename from AVL Tree/AVLTreeTests/AVLTreeTests/Info.plist rename to AVL Tree/AVLTree Tests/AVLTreeTests/Info.plist diff --git a/AVL Tree/AVLTreeTests/AVLTreeTests/ViewController.swift b/AVL Tree/AVLTree Tests/AVLTreeTests/ViewController.swift similarity index 100% rename from AVL Tree/AVLTreeTests/AVLTreeTests/ViewController.swift rename to AVL Tree/AVLTree Tests/AVLTreeTests/ViewController.swift diff --git a/AVL Tree/AVLTreeTests/AVLTreeTestsTests/AVLTreeTestsTests.swift b/AVL Tree/AVLTree Tests/AVLTreeTestsTests/AVLTreeTestsTests.swift similarity index 100% rename from AVL Tree/AVLTreeTests/AVLTreeTestsTests/AVLTreeTestsTests.swift rename to AVL Tree/AVLTree Tests/AVLTreeTestsTests/AVLTreeTestsTests.swift diff --git a/AVL Tree/AVLTreeTests/AVLTreeTestsTests/Info.plist b/AVL Tree/AVLTree Tests/AVLTreeTestsTests/Info.plist similarity index 100% rename from AVL Tree/AVLTreeTests/AVLTreeTestsTests/Info.plist rename to AVL Tree/AVLTree Tests/AVLTreeTestsTests/Info.plist diff --git a/AVL Tree/AVLTreeTests/AVLTreeTestsTests/TreeNodeTest.swift b/AVL Tree/AVLTree Tests/AVLTreeTestsTests/TreeNodeTest.swift similarity index 100% rename from AVL Tree/AVLTreeTests/AVLTreeTestsTests/TreeNodeTest.swift rename to AVL Tree/AVLTree Tests/AVLTreeTestsTests/TreeNodeTest.swift diff --git a/Array2D/array2Dtest/array2Dtest.xcodeproj/project.pbxproj b/Array2D/Array2D Tests/array2Dtest.xcodeproj/project.pbxproj similarity index 100% rename from Array2D/array2Dtest/array2Dtest.xcodeproj/project.pbxproj rename to Array2D/Array2D Tests/array2Dtest.xcodeproj/project.pbxproj diff --git a/Array2D/array2Dtest/array2Dtest.xcodeproj/xcshareddata/xcbaselines/766116211C7625C700358E02.xcbaseline/B9780967-0BD8-4A91-8657-A96EFB81859F.plist b/Array2D/Array2D Tests/array2Dtest.xcodeproj/xcshareddata/xcbaselines/766116211C7625C700358E02.xcbaseline/B9780967-0BD8-4A91-8657-A96EFB81859F.plist similarity index 100% rename from Array2D/array2Dtest/array2Dtest.xcodeproj/xcshareddata/xcbaselines/766116211C7625C700358E02.xcbaseline/B9780967-0BD8-4A91-8657-A96EFB81859F.plist rename to Array2D/Array2D Tests/array2Dtest.xcodeproj/xcshareddata/xcbaselines/766116211C7625C700358E02.xcbaseline/B9780967-0BD8-4A91-8657-A96EFB81859F.plist diff --git a/Array2D/array2Dtest/array2Dtest.xcodeproj/xcshareddata/xcbaselines/766116211C7625C700358E02.xcbaseline/Info.plist b/Array2D/Array2D Tests/array2Dtest.xcodeproj/xcshareddata/xcbaselines/766116211C7625C700358E02.xcbaseline/Info.plist similarity index 100% rename from Array2D/array2Dtest/array2Dtest.xcodeproj/xcshareddata/xcbaselines/766116211C7625C700358E02.xcbaseline/Info.plist rename to Array2D/Array2D Tests/array2Dtest.xcodeproj/xcshareddata/xcbaselines/766116211C7625C700358E02.xcbaseline/Info.plist diff --git a/Array2D/array2Dtest/array2Dtest/AppDelegate.swift b/Array2D/Array2D Tests/array2Dtest/AppDelegate.swift similarity index 100% rename from Array2D/array2Dtest/array2Dtest/AppDelegate.swift rename to Array2D/Array2D Tests/array2Dtest/AppDelegate.swift diff --git a/Array2D/array2Dtest/array2Dtest/Assets.xcassets/AppIcon.appiconset/Contents.json b/Array2D/Array2D Tests/array2Dtest/Assets.xcassets/AppIcon.appiconset/Contents.json similarity index 100% rename from Array2D/array2Dtest/array2Dtest/Assets.xcassets/AppIcon.appiconset/Contents.json rename to Array2D/Array2D Tests/array2Dtest/Assets.xcassets/AppIcon.appiconset/Contents.json diff --git a/Array2D/array2Dtest/array2Dtest/Base.lproj/LaunchScreen.storyboard b/Array2D/Array2D Tests/array2Dtest/Base.lproj/LaunchScreen.storyboard similarity index 100% rename from Array2D/array2Dtest/array2Dtest/Base.lproj/LaunchScreen.storyboard rename to Array2D/Array2D Tests/array2Dtest/Base.lproj/LaunchScreen.storyboard diff --git a/Array2D/array2Dtest/array2Dtest/Base.lproj/Main.storyboard b/Array2D/Array2D Tests/array2Dtest/Base.lproj/Main.storyboard similarity index 100% rename from Array2D/array2Dtest/array2Dtest/Base.lproj/Main.storyboard rename to Array2D/Array2D Tests/array2Dtest/Base.lproj/Main.storyboard diff --git a/Array2D/array2Dtest/array2Dtest/Info.plist b/Array2D/Array2D Tests/array2Dtest/Info.plist similarity index 100% rename from Array2D/array2Dtest/array2Dtest/Info.plist rename to Array2D/Array2D Tests/array2Dtest/Info.plist diff --git a/Array2D/array2Dtest/array2Dtest/ViewController.swift b/Array2D/Array2D Tests/array2Dtest/ViewController.swift similarity index 100% rename from Array2D/array2Dtest/array2Dtest/ViewController.swift rename to Array2D/Array2D Tests/array2Dtest/ViewController.swift diff --git a/Array2D/array2Dtest/array2DtestTests/Info.plist b/Array2D/Array2D Tests/array2DtestTests/Info.plist similarity index 100% rename from Array2D/array2Dtest/array2DtestTests/Info.plist rename to Array2D/Array2D Tests/array2DtestTests/Info.plist diff --git a/Array2D/array2Dtest/array2DtestTests/array2DtestTests.swift b/Array2D/Array2D Tests/array2DtestTests/array2DtestTests.swift similarity index 93% rename from Array2D/array2Dtest/array2DtestTests/array2DtestTests.swift rename to Array2D/Array2D Tests/array2DtestTests/array2DtestTests.swift index 926819e45..234d0f9b4 100644 --- a/Array2D/array2Dtest/array2DtestTests/array2DtestTests.swift +++ b/Array2D/Array2D Tests/array2DtestTests/array2DtestTests.swift @@ -49,11 +49,11 @@ class Array2DTest: XCTestCase { } } - func testPerformanceOnLargeArray() { - self.measureBlock { - self.printArrayWith(columns: 2000, rows: 2000, inititalValue: 1) - } - } +// func testPerformanceOnLargeArray() { +// self.measureBlock { +// self.printArrayWith(columns: 2000, rows: 2000, inititalValue: 1) +// } +// } private func printArrayWith(columns columns: Int, rows: Int, inititalValue: Int){ let array = Array2D(columns: columns, rows: rows, initialValue: 4) From 3ed00a3d2dd102b0e68cef456920c7f83416d5b1 Mon Sep 17 00:00:00 2001 From: Robert Thompson Date: Fri, 19 Feb 2016 11:02:24 -0500 Subject: [PATCH 0038/1679] Fix license --- Treap/Treap.swift | 20 ++++++++++++++++++-- Treap/Treap/Treap/AppDelegate.swift | 19 ++++++++++++++++++- Treap/Treap/TreapTests/TreapTests.swift | 20 ++++++++++++++++++-- Treap/TreapCollectionType.swift | 20 ++++++++++++++++++-- Treap/TreapMergeSplit.swift | 20 ++++++++++++++++++-- 5 files changed, 90 insertions(+), 9 deletions(-) diff --git a/Treap/Treap.swift b/Treap/Treap.swift index 108eec913..5413a17c2 100644 --- a/Treap/Treap.swift +++ b/Treap/Treap.swift @@ -3,8 +3,24 @@ // TreapExample // // Created by Robert Thompson on 7/27/15. -// Copyright © 2015 Robert Thompson. All rights reserved. -// +// Copyright © 2016 Robert Thompson +/* Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE.*/ import Foundation diff --git a/Treap/Treap/Treap/AppDelegate.swift b/Treap/Treap/Treap/AppDelegate.swift index a156c1cb4..1813d840b 100644 --- a/Treap/Treap/Treap/AppDelegate.swift +++ b/Treap/Treap/Treap/AppDelegate.swift @@ -3,7 +3,24 @@ // Treap // // Created by Robert Thompson on 2/18/16. -// Copyright © 2016 WillowTree, Inc. All rights reserved. +// Copyright © 2016 Robert Thompson +/* Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE.*/ // import Cocoa diff --git a/Treap/Treap/TreapTests/TreapTests.swift b/Treap/Treap/TreapTests/TreapTests.swift index 06421ad78..496e2f940 100644 --- a/Treap/Treap/TreapTests/TreapTests.swift +++ b/Treap/Treap/TreapTests/TreapTests.swift @@ -3,8 +3,24 @@ // TreapTests // // Created by Robert Thompson on 2/18/16. -// Copyright © 2016 WillowTree, Inc. All rights reserved. -// +// Copyright © 2016 Robert Thompson +/* Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE.*/ import XCTest @testable import Treap diff --git a/Treap/TreapCollectionType.swift b/Treap/TreapCollectionType.swift index f624bf265..36d02eaac 100644 --- a/Treap/TreapCollectionType.swift +++ b/Treap/TreapCollectionType.swift @@ -3,8 +3,24 @@ // Treap // // Created by Robert Thompson on 2/18/16. -// Copyright © 2016 WillowTree, Inc. All rights reserved. -// +// Copyright © 2016 Robert Thompson +/* Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE.*/ import Foundation diff --git a/Treap/TreapMergeSplit.swift b/Treap/TreapMergeSplit.swift index eed6d3d94..51929893b 100644 --- a/Treap/TreapMergeSplit.swift +++ b/Treap/TreapMergeSplit.swift @@ -3,8 +3,24 @@ // TreapExample // // Created by Robert Thompson on 7/27/15. -// Copyright © 2015 Robert Thompson. All rights reserved. -// +// Copyright © 2016 Robert Thompson +/* Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE.*/ import Foundation public extension Treap { From 063f3fe99b93fd76f243e0fb1cff982ea1ccf47e Mon Sep 17 00:00:00 2001 From: Robert Thompson Date: Fri, 19 Feb 2016 11:05:56 -0500 Subject: [PATCH 0039/1679] Add SequenceType conformance to Stack As per issue #10 --- Stack/Stack.swift | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Stack/Stack.swift b/Stack/Stack.swift index 8186a70de..96c1ff284 100644 --- a/Stack/Stack.swift +++ b/Stack/Stack.swift @@ -30,3 +30,13 @@ public struct Stack { return array.last } } + +extension Stack: SequenceType { + public func generate() -> AnyGenerator { + var curr = self + return anyGenerator { + _ -> T? in + return curr.pop() + } + } +} From 464077afd297dbc8f57bb0779fb466a8d99a2086 Mon Sep 17 00:00:00 2001 From: Matthijs Hollemans Date: Fri, 19 Feb 2016 20:49:46 +0100 Subject: [PATCH 0040/1679] Unit tests no longer use host application --- .../AVLTreeTests.xcodeproj/project.pbxproj | 415 ----------- .../AVLTreeTests/AppDelegate.swift | 46 -- .../AppIcon.appiconset/Contents.json | 68 -- .../Base.lproj/LaunchScreen.storyboard | 27 - .../AVLTreeTests/Base.lproj/Main.storyboard | 25 - .../AVLTree Tests/AVLTreeTests/Info.plist | 47 -- .../AVLTreeTests/ViewController.swift | 25 - .../AVLTreeTestsTests/AVLTreeTestsTests.swift | 82 --- AVL Tree/Tests/AVLTreeTests.swift | 80 +++ .../AVLTreeTestsTests => Tests}/Info.plist | 0 .../Tests/Tests.xcodeproj/project.pbxproj | 265 +++++++ .../TreeNodeTests.swift} | 4 +- .../array2Dtest.xcodeproj/project.pbxproj | 409 ----------- ...B9780967-0BD8-4A91-8657-A96EFB81859F.plist | 22 - .../Info.plist | 40 -- .../array2Dtest/AppDelegate.swift | 46 -- .../AppIcon.appiconset/Contents.json | 68 -- .../Base.lproj/LaunchScreen.storyboard | 27 - .../array2Dtest/Base.lproj/Main.storyboard | 25 - Array2D/Array2D Tests/array2Dtest/Info.plist | 47 -- .../array2Dtest/ViewController.swift | 25 - .../array2DtestTests/array2DtestTests.swift | 80 --- Array2D/Tests/Array2DTests.swift | 78 ++ .../array2DtestTests => Tests}/Info.plist | 0 Array2D/Tests/Tests.xcodeproj/project.pbxproj | 261 +++++++ .../project.pbxproj | 394 ---------- .../BinarySearchTree/AppDelegate.swift | 27 - .../AppIcon.appiconset/Contents.json | 58 -- .../BinarySearchTree/Base.lproj/MainMenu.xib | 680 ------------------ .../BinarySearchTree/Info.plist | 34 - .../BinarySearchTreeTests.swift | 1 - .../Info.plist | 0 .../Tests/Tests.xcodeproj/project.pbxproj | 261 +++++++ .../BinarySearch.xcodeproj/project.pbxproj | 394 ---------- .../BinarySearch/AppDelegate.swift | 27 - .../AppIcon.appiconset/Contents.json | 58 -- .../BinarySearch/Base.lproj/MainMenu.xib | 680 ------------------ .../BinarySearch/Info.plist | 34 - .../BinarySearchTests.swift | 1 - .../BinarySearchTests => Tests}/Info.plist | 0 .../Tests/Tests.xcodeproj/project.pbxproj | 261 +++++++ .../HeapSort.xcodeproj/project.pbxproj | 398 ---------- .../HeapSort Tests/HeapSort/AppDelegate.swift | 27 - .../AppIcon.appiconset/Contents.json | 58 -- .../HeapSort/Base.lproj/MainMenu.xib | 680 ------------------ Heap Sort/HeapSort Tests/HeapSort/Info.plist | 34 - .../HeapSortTests.swift | 9 - .../HeapSortTests => Tests}/Info.plist | 0 .../Tests/Tests.xcodeproj/project.pbxproj | 265 +++++++ .../Heap Tests/Heap.xcodeproj/project.pbxproj | 394 ---------- Heap/Heap Tests/Heap/AppDelegate.swift | 15 - .../AppIcon.appiconset/Contents.json | 58 -- Heap/Heap Tests/Heap/Base.lproj/MainMenu.xib | 680 ------------------ Heap/Heap Tests/Heap/Info.plist | 34 - .../HeapTests => Tests}/HeapTests.swift | 1 - .../HeapTests => Tests}/Info.plist | 0 Heap/Tests/Tests.xcodeproj/project.pbxproj | 261 +++++++ .../InsertionSort.xcodeproj/project.pbxproj | 398 ---------- .../InsertionSort/AppDelegate.swift | 27 - .../AppIcon.appiconset/Contents.json | 58 -- .../InsertionSort/Base.lproj/MainMenu.xib | 680 ------------------ .../InsertionSort/Info.plist | 34 - .../InsertionSortTests => Tests}/Info.plist | 0 .../InsertionSortTests.swift | 1 - .../Tests/Tests.xcodeproj/project.pbxproj | 265 +++++++ .../LinkedList.xcodeproj/project.pbxproj | 394 ---------- .../LinkedList/AppDelegate.swift | 27 - .../AppIcon.appiconset/Contents.json | 58 -- .../LinkedList/Base.lproj/MainMenu.xib | 680 ------------------ .../LinkedList Tests/LinkedList/Info.plist | 34 - .../LinkedListTests => Tests}/Info.plist | 0 .../LinkedListTests.swift | 1 - .../Tests/Tests.xcodeproj/project.pbxproj | 261 +++++++ .../PriorityQueue.xcodeproj/project.pbxproj | 398 ---------- .../PriorityQueue/AppDelegate.swift | 27 - .../AppIcon.appiconset/Contents.json | 58 -- .../PriorityQueue/Base.lproj/MainMenu.xib | 680 ------------------ .../PriorityQueue/Info.plist | 34 - .../PriorityQueueTests => Tests}/Info.plist | 0 .../PriorityQueueTests.swift | 1 - .../Tests/Tests.xcodeproj/project.pbxproj | 265 +++++++ .../Queue.xcodeproj/project.pbxproj | 394 ---------- Queue/Queue Tests/Queue/AppDelegate.swift | 27 - .../AppIcon.appiconset/Contents.json | 58 -- .../Queue Tests/Queue/Base.lproj/MainMenu.xib | 680 ------------------ Queue/Queue Tests/Queue/Info.plist | 34 - .../QueueTests => Tests}/Info.plist | 0 .../QueueTests => Tests}/QueueTests.swift | 1 - Queue/Tests/Tests.xcodeproj/project.pbxproj | 261 +++++++ .../Quicksort.xcodeproj/project.pbxproj | 398 ---------- .../Quicksort/AppDelegate.swift | 27 - .../AppIcon.appiconset/Contents.json | 58 -- .../Quicksort/Base.lproj/MainMenu.xib | 680 ------------------ .../Quicksort Tests/Quicksort/Info.plist | 34 - .../QuicksortTests => Tests}/Info.plist | 0 .../QuicksortTests.swift | 1 - .../SortingTestHelpers.swift | 0 .../Tests/Tests.xcodeproj/project.pbxproj | 265 +++++++ .../RLE Tests/RLE.xcodeproj/project.pbxproj | 394 ---------- .../RLE Tests/RLE/AppDelegate.swift | 27 - .../AppIcon.appiconset/Contents.json | 58 -- .../RLE Tests/RLE/Base.lproj/MainMenu.xib | 680 ------------------ Run-Length Encoding/RLE Tests/RLE/Info.plist | 34 - Run-Length Encoding/RLE Tests/RLE/RLE.swift | 70 -- Run-Length Encoding/RLE.swift | 76 +- .../{RLE Tests/RLETests => Tests}/Info.plist | 0 .../RLETests => Tests}/RLETests.swift | 1 - .../Tests/Tests.xcodeproj/project.pbxproj | 261 +++++++ .../MinimumMaximumPairs.swift | 3 +- .../project.pbxproj | 393 ---------- .../SelectMinimumMaximum/AppDelegate.swift | 16 - .../SelectMinimumMaximum/Info.plist | 32 - .../Info.plist | 0 .../MaximumTests.swift | 1 - .../MinimumMaximumPairsTests.swift} | 3 +- .../MinimumTests.swift | 1 - .../TestHelper.swift | 0 .../Tests/Tests.xcodeproj/project.pbxproj | 281 ++++++++ .../SelectionSort.xcodeproj/project.pbxproj | 398 ---------- .../SelectionSort/AppDelegate.swift | 27 - .../AppIcon.appiconset/Contents.json | 58 -- .../SelectionSort/Base.lproj/MainMenu.xib | 680 ------------------ .../SelectionSort/Info.plist | 34 - .../SelectionSortTests => Tests}/Info.plist | 0 .../SelectionSortTests.swift | 1 - .../Tests/Tests.xcodeproj/project.pbxproj | 265 +++++++ .../ShellSort.xcodeproj/project.pbxproj | 398 ---------- .../ShellSort/AppDelegate.swift | 27 - .../AppIcon.appiconset/Contents.json | 58 -- .../ShellSort/Base.lproj/MainMenu.xib | 680 ------------------ .../ShellSort Tests/ShellSort/Info.plist | 34 - .../ShellSortTests => Tests}/Info.plist | 0 .../ShellSortTests.swift | 1 - .../Tests/Tests.xcodeproj/project.pbxproj | 265 +++++++ .../Stack.xcodeproj/project.pbxproj | 394 ---------- Stack/Stack Tests/Stack/AppDelegate.swift | 27 - .../AppIcon.appiconset/Contents.json | 58 -- .../Stack Tests/Stack/Base.lproj/MainMenu.xib | 680 ------------------ Stack/Stack Tests/Stack/Info.plist | 34 - .../StackTests => Tests}/Info.plist | 0 .../StackTests => Tests}/StackTests.swift | 1 - Stack/Tests/Tests.xcodeproj/project.pbxproj | 261 +++++++ 142 files changed, 4428 insertions(+), 17619 deletions(-) delete mode 100644 AVL Tree/AVLTree Tests/AVLTreeTests.xcodeproj/project.pbxproj delete mode 100644 AVL Tree/AVLTree Tests/AVLTreeTests/AppDelegate.swift delete mode 100644 AVL Tree/AVLTree Tests/AVLTreeTests/Assets.xcassets/AppIcon.appiconset/Contents.json delete mode 100644 AVL Tree/AVLTree Tests/AVLTreeTests/Base.lproj/LaunchScreen.storyboard delete mode 100644 AVL Tree/AVLTree Tests/AVLTreeTests/Base.lproj/Main.storyboard delete mode 100644 AVL Tree/AVLTree Tests/AVLTreeTests/Info.plist delete mode 100644 AVL Tree/AVLTree Tests/AVLTreeTests/ViewController.swift delete mode 100644 AVL Tree/AVLTree Tests/AVLTreeTestsTests/AVLTreeTestsTests.swift create mode 100644 AVL Tree/Tests/AVLTreeTests.swift rename AVL Tree/{AVLTree Tests/AVLTreeTestsTests => Tests}/Info.plist (100%) create mode 100644 AVL Tree/Tests/Tests.xcodeproj/project.pbxproj rename AVL Tree/{AVLTree Tests/AVLTreeTestsTests/TreeNodeTest.swift => Tests/TreeNodeTests.swift} (97%) delete mode 100644 Array2D/Array2D Tests/array2Dtest.xcodeproj/project.pbxproj delete mode 100644 Array2D/Array2D Tests/array2Dtest.xcodeproj/xcshareddata/xcbaselines/766116211C7625C700358E02.xcbaseline/B9780967-0BD8-4A91-8657-A96EFB81859F.plist delete mode 100644 Array2D/Array2D Tests/array2Dtest.xcodeproj/xcshareddata/xcbaselines/766116211C7625C700358E02.xcbaseline/Info.plist delete mode 100644 Array2D/Array2D Tests/array2Dtest/AppDelegate.swift delete mode 100644 Array2D/Array2D Tests/array2Dtest/Assets.xcassets/AppIcon.appiconset/Contents.json delete mode 100644 Array2D/Array2D Tests/array2Dtest/Base.lproj/LaunchScreen.storyboard delete mode 100644 Array2D/Array2D Tests/array2Dtest/Base.lproj/Main.storyboard delete mode 100644 Array2D/Array2D Tests/array2Dtest/Info.plist delete mode 100644 Array2D/Array2D Tests/array2Dtest/ViewController.swift delete mode 100644 Array2D/Array2D Tests/array2DtestTests/array2DtestTests.swift create mode 100644 Array2D/Tests/Array2DTests.swift rename Array2D/{Array2D Tests/array2DtestTests => Tests}/Info.plist (100%) create mode 100644 Array2D/Tests/Tests.xcodeproj/project.pbxproj delete mode 100644 Binary Search Tree/Solution 1/BinarySearchTree Tests/BinarySearchTree.xcodeproj/project.pbxproj delete mode 100644 Binary Search Tree/Solution 1/BinarySearchTree Tests/BinarySearchTree/AppDelegate.swift delete mode 100644 Binary Search Tree/Solution 1/BinarySearchTree Tests/BinarySearchTree/Assets.xcassets/AppIcon.appiconset/Contents.json delete mode 100644 Binary Search Tree/Solution 1/BinarySearchTree Tests/BinarySearchTree/Base.lproj/MainMenu.xib delete mode 100644 Binary Search Tree/Solution 1/BinarySearchTree Tests/BinarySearchTree/Info.plist rename Binary Search Tree/Solution 1/{BinarySearchTree Tests/BinarySearchTreeTests => Tests}/BinarySearchTreeTests.swift (99%) rename Binary Search Tree/Solution 1/{BinarySearchTree Tests/BinarySearchTreeTests => Tests}/Info.plist (100%) create mode 100644 Binary Search Tree/Solution 1/Tests/Tests.xcodeproj/project.pbxproj delete mode 100644 Binary Search/BinarySearch Tests/BinarySearch.xcodeproj/project.pbxproj delete mode 100644 Binary Search/BinarySearch Tests/BinarySearch/AppDelegate.swift delete mode 100644 Binary Search/BinarySearch Tests/BinarySearch/Assets.xcassets/AppIcon.appiconset/Contents.json delete mode 100644 Binary Search/BinarySearch Tests/BinarySearch/Base.lproj/MainMenu.xib delete mode 100644 Binary Search/BinarySearch Tests/BinarySearch/Info.plist rename Binary Search/{BinarySearch Tests/BinarySearchTests => Tests}/BinarySearchTests.swift (97%) rename Binary Search/{BinarySearch Tests/BinarySearchTests => Tests}/Info.plist (100%) create mode 100644 Binary Search/Tests/Tests.xcodeproj/project.pbxproj delete mode 100644 Heap Sort/HeapSort Tests/HeapSort.xcodeproj/project.pbxproj delete mode 100644 Heap Sort/HeapSort Tests/HeapSort/AppDelegate.swift delete mode 100644 Heap Sort/HeapSort Tests/HeapSort/Assets.xcassets/AppIcon.appiconset/Contents.json delete mode 100644 Heap Sort/HeapSort Tests/HeapSort/Base.lproj/MainMenu.xib delete mode 100644 Heap Sort/HeapSort Tests/HeapSort/Info.plist rename Heap Sort/{HeapSort Tests/HeapSortTests => Tests}/HeapSortTests.swift (81%) rename Heap Sort/{HeapSort Tests/HeapSortTests => Tests}/Info.plist (100%) create mode 100644 Heap Sort/Tests/Tests.xcodeproj/project.pbxproj delete mode 100644 Heap/Heap Tests/Heap.xcodeproj/project.pbxproj delete mode 100644 Heap/Heap Tests/Heap/AppDelegate.swift delete mode 100644 Heap/Heap Tests/Heap/Assets.xcassets/AppIcon.appiconset/Contents.json delete mode 100644 Heap/Heap Tests/Heap/Base.lproj/MainMenu.xib delete mode 100644 Heap/Heap Tests/Heap/Info.plist rename Heap/{Heap Tests/HeapTests => Tests}/HeapTests.swift (99%) rename Heap/{Heap Tests/HeapTests => Tests}/Info.plist (100%) create mode 100644 Heap/Tests/Tests.xcodeproj/project.pbxproj delete mode 100644 Insertion Sort/InsertionSort Tests/InsertionSort.xcodeproj/project.pbxproj delete mode 100644 Insertion Sort/InsertionSort Tests/InsertionSort/AppDelegate.swift delete mode 100644 Insertion Sort/InsertionSort Tests/InsertionSort/Assets.xcassets/AppIcon.appiconset/Contents.json delete mode 100644 Insertion Sort/InsertionSort Tests/InsertionSort/Base.lproj/MainMenu.xib delete mode 100644 Insertion Sort/InsertionSort Tests/InsertionSort/Info.plist rename Insertion Sort/{InsertionSort Tests/InsertionSortTests => Tests}/Info.plist (100%) rename Insertion Sort/{InsertionSort Tests/InsertionSortTests => Tests}/InsertionSortTests.swift (80%) create mode 100644 Insertion Sort/Tests/Tests.xcodeproj/project.pbxproj delete mode 100644 Linked List/LinkedList Tests/LinkedList.xcodeproj/project.pbxproj delete mode 100644 Linked List/LinkedList Tests/LinkedList/AppDelegate.swift delete mode 100644 Linked List/LinkedList Tests/LinkedList/Assets.xcassets/AppIcon.appiconset/Contents.json delete mode 100644 Linked List/LinkedList Tests/LinkedList/Base.lproj/MainMenu.xib delete mode 100644 Linked List/LinkedList Tests/LinkedList/Info.plist rename Linked List/{LinkedList Tests/LinkedListTests => Tests}/Info.plist (100%) rename Linked List/{LinkedList Tests/LinkedListTests => Tests}/LinkedListTests.swift (99%) create mode 100644 Linked List/Tests/Tests.xcodeproj/project.pbxproj delete mode 100644 Priority Queue/PriorityQueue Tests/PriorityQueue.xcodeproj/project.pbxproj delete mode 100644 Priority Queue/PriorityQueue Tests/PriorityQueue/AppDelegate.swift delete mode 100644 Priority Queue/PriorityQueue Tests/PriorityQueue/Assets.xcassets/AppIcon.appiconset/Contents.json delete mode 100644 Priority Queue/PriorityQueue Tests/PriorityQueue/Base.lproj/MainMenu.xib delete mode 100644 Priority Queue/PriorityQueue Tests/PriorityQueue/Info.plist rename Priority Queue/{PriorityQueue Tests/PriorityQueueTests => Tests}/Info.plist (100%) rename Priority Queue/{PriorityQueue Tests/PriorityQueueTests => Tests}/PriorityQueueTests.swift (98%) create mode 100644 Priority Queue/Tests/Tests.xcodeproj/project.pbxproj delete mode 100644 Queue/Queue Tests/Queue.xcodeproj/project.pbxproj delete mode 100644 Queue/Queue Tests/Queue/AppDelegate.swift delete mode 100644 Queue/Queue Tests/Queue/Assets.xcassets/AppIcon.appiconset/Contents.json delete mode 100644 Queue/Queue Tests/Queue/Base.lproj/MainMenu.xib delete mode 100644 Queue/Queue Tests/Queue/Info.plist rename Queue/{Queue Tests/QueueTests => Tests}/Info.plist (100%) rename Queue/{Queue Tests/QueueTests => Tests}/QueueTests.swift (98%) create mode 100644 Queue/Tests/Tests.xcodeproj/project.pbxproj delete mode 100644 Quicksort/Quicksort Tests/Quicksort.xcodeproj/project.pbxproj delete mode 100644 Quicksort/Quicksort Tests/Quicksort/AppDelegate.swift delete mode 100644 Quicksort/Quicksort Tests/Quicksort/Assets.xcassets/AppIcon.appiconset/Contents.json delete mode 100644 Quicksort/Quicksort Tests/Quicksort/Base.lproj/MainMenu.xib delete mode 100644 Quicksort/Quicksort Tests/Quicksort/Info.plist rename Quicksort/{Quicksort Tests/QuicksortTests => Tests}/Info.plist (100%) rename Quicksort/{Quicksort Tests/QuicksortTests => Tests}/QuicksortTests.swift (96%) rename Quicksort/{Quicksort Tests/QuicksortTests => Tests}/SortingTestHelpers.swift (100%) create mode 100644 Quicksort/Tests/Tests.xcodeproj/project.pbxproj delete mode 100644 Run-Length Encoding/RLE Tests/RLE.xcodeproj/project.pbxproj delete mode 100644 Run-Length Encoding/RLE Tests/RLE/AppDelegate.swift delete mode 100644 Run-Length Encoding/RLE Tests/RLE/Assets.xcassets/AppIcon.appiconset/Contents.json delete mode 100644 Run-Length Encoding/RLE Tests/RLE/Base.lproj/MainMenu.xib delete mode 100644 Run-Length Encoding/RLE Tests/RLE/Info.plist delete mode 100644 Run-Length Encoding/RLE Tests/RLE/RLE.swift rename Run-Length Encoding/{RLE Tests/RLETests => Tests}/Info.plist (100%) rename Run-Length Encoding/{RLE Tests/RLETests => Tests}/RLETests.swift (99%) create mode 100644 Run-Length Encoding/Tests/Tests.xcodeproj/project.pbxproj delete mode 100644 Select Minimum Maximum/SelectMinimumMaximum Tests/SelectMinimumMaximum.xcodeproj/project.pbxproj delete mode 100644 Select Minimum Maximum/SelectMinimumMaximum Tests/SelectMinimumMaximum/AppDelegate.swift delete mode 100644 Select Minimum Maximum/SelectMinimumMaximum Tests/SelectMinimumMaximum/Info.plist rename Select Minimum Maximum/{SelectMinimumMaximum Tests/SelectMinimumMaximumTests => Tests}/Info.plist (100%) rename Select Minimum Maximum/{SelectMinimumMaximum Tests/SelectMinimumMaximumTests => Tests}/MaximumTests.swift (96%) rename Select Minimum Maximum/{SelectMinimumMaximum Tests/SelectMinimumMaximumTests/SelectMinimumMaximumTests.swift => Tests/MinimumMaximumPairsTests.swift} (95%) rename Select Minimum Maximum/{SelectMinimumMaximum Tests/SelectMinimumMaximumTests => Tests}/MinimumTests.swift (96%) rename Select Minimum Maximum/{SelectMinimumMaximum Tests/SelectMinimumMaximumTests => Tests}/TestHelper.swift (100%) create mode 100644 Select Minimum Maximum/Tests/Tests.xcodeproj/project.pbxproj delete mode 100644 Selection Sort/SelectionSort Tests/SelectionSort.xcodeproj/project.pbxproj delete mode 100644 Selection Sort/SelectionSort Tests/SelectionSort/AppDelegate.swift delete mode 100644 Selection Sort/SelectionSort Tests/SelectionSort/Assets.xcassets/AppIcon.appiconset/Contents.json delete mode 100644 Selection Sort/SelectionSort Tests/SelectionSort/Base.lproj/MainMenu.xib delete mode 100644 Selection Sort/SelectionSort Tests/SelectionSort/Info.plist rename Selection Sort/{SelectionSort Tests/SelectionSortTests => Tests}/Info.plist (100%) rename Selection Sort/{SelectionSort Tests/SelectionSortTests => Tests}/SelectionSortTests.swift (80%) create mode 100644 Selection Sort/Tests/Tests.xcodeproj/project.pbxproj delete mode 100644 Shell Sort/ShellSort Tests/ShellSort.xcodeproj/project.pbxproj delete mode 100644 Shell Sort/ShellSort Tests/ShellSort/AppDelegate.swift delete mode 100644 Shell Sort/ShellSort Tests/ShellSort/Assets.xcassets/AppIcon.appiconset/Contents.json delete mode 100644 Shell Sort/ShellSort Tests/ShellSort/Base.lproj/MainMenu.xib delete mode 100644 Shell Sort/ShellSort Tests/ShellSort/Info.plist rename Shell Sort/{ShellSort Tests/ShellSortTests => Tests}/Info.plist (100%) rename Shell Sort/{ShellSort Tests/ShellSortTests => Tests}/ShellSortTests.swift (87%) create mode 100644 Shell Sort/Tests/Tests.xcodeproj/project.pbxproj delete mode 100644 Stack/Stack Tests/Stack.xcodeproj/project.pbxproj delete mode 100644 Stack/Stack Tests/Stack/AppDelegate.swift delete mode 100644 Stack/Stack Tests/Stack/Assets.xcassets/AppIcon.appiconset/Contents.json delete mode 100644 Stack/Stack Tests/Stack/Base.lproj/MainMenu.xib delete mode 100644 Stack/Stack Tests/Stack/Info.plist rename Stack/{Stack Tests/StackTests => Tests}/Info.plist (100%) rename Stack/{Stack Tests/StackTests => Tests}/StackTests.swift (98%) create mode 100644 Stack/Tests/Tests.xcodeproj/project.pbxproj diff --git a/AVL Tree/AVLTree Tests/AVLTreeTests.xcodeproj/project.pbxproj b/AVL Tree/AVLTree Tests/AVLTreeTests.xcodeproj/project.pbxproj deleted file mode 100644 index 45e5ceb17..000000000 --- a/AVL Tree/AVLTree Tests/AVLTreeTests.xcodeproj/project.pbxproj +++ /dev/null @@ -1,415 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 763F28681C77228700AABA94 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 763F28671C77228700AABA94 /* AppDelegate.swift */; }; - 763F286A1C77228700AABA94 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 763F28691C77228700AABA94 /* ViewController.swift */; }; - 763F286D1C77228700AABA94 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 763F286B1C77228700AABA94 /* Main.storyboard */; }; - 763F286F1C77228700AABA94 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 763F286E1C77228700AABA94 /* Assets.xcassets */; }; - 763F28721C77228700AABA94 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 763F28701C77228700AABA94 /* LaunchScreen.storyboard */; }; - 763F287D1C77228700AABA94 /* AVLTreeTestsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 763F287C1C77228700AABA94 /* AVLTreeTestsTests.swift */; }; - 763F28881C77229D00AABA94 /* AVLTree.swift in Sources */ = {isa = PBXBuildFile; fileRef = 763F28871C77229D00AABA94 /* AVLTree.swift */; }; - 763F288B1C77254000AABA94 /* TreeNodeTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 763F288A1C77254000AABA94 /* TreeNodeTest.swift */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 763F28791C77228700AABA94 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 763F285C1C77228600AABA94 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 763F28631C77228600AABA94; - remoteInfo = AVLTreeTests; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXFileReference section */ - 763F28641C77228700AABA94 /* AVLTreeTests.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AVLTreeTests.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 763F28671C77228700AABA94 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 763F28691C77228700AABA94 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; - 763F286C1C77228700AABA94 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 763F286E1C77228700AABA94 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - 763F28711C77228700AABA94 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; - 763F28731C77228700AABA94 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 763F28781C77228700AABA94 /* AVLTreeTestsTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AVLTreeTestsTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 763F287C1C77228700AABA94 /* AVLTreeTestsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AVLTreeTestsTests.swift; sourceTree = ""; }; - 763F287E1C77228700AABA94 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 763F28871C77229D00AABA94 /* AVLTree.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = AVLTree.swift; path = "../../../AVL Tree/AVLTree.swift"; sourceTree = ""; }; - 763F28891C7722B700AABA94 /* AVLTree.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; name = AVLTree.playground; path = "../../../AVL Tree/AVLTree.playground"; sourceTree = ""; }; - 763F288A1C77254000AABA94 /* TreeNodeTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TreeNodeTest.swift; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 763F28611C77228600AABA94 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 763F28751C77228700AABA94 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 763F285B1C77228600AABA94 = { - isa = PBXGroup; - children = ( - 763F28661C77228700AABA94 /* AVLTreeTests */, - 763F287B1C77228700AABA94 /* AVLTreeTestsTests */, - 763F28651C77228700AABA94 /* Products */, - ); - sourceTree = ""; - }; - 763F28651C77228700AABA94 /* Products */ = { - isa = PBXGroup; - children = ( - 763F28641C77228700AABA94 /* AVLTreeTests.app */, - 763F28781C77228700AABA94 /* AVLTreeTestsTests.xctest */, - ); - name = Products; - sourceTree = ""; - }; - 763F28661C77228700AABA94 /* AVLTreeTests */ = { - isa = PBXGroup; - children = ( - 763F28891C7722B700AABA94 /* AVLTree.playground */, - 763F28871C77229D00AABA94 /* AVLTree.swift */, - 763F28671C77228700AABA94 /* AppDelegate.swift */, - 763F28691C77228700AABA94 /* ViewController.swift */, - 763F286B1C77228700AABA94 /* Main.storyboard */, - 763F286E1C77228700AABA94 /* Assets.xcassets */, - 763F28701C77228700AABA94 /* LaunchScreen.storyboard */, - 763F28731C77228700AABA94 /* Info.plist */, - ); - path = AVLTreeTests; - sourceTree = ""; - }; - 763F287B1C77228700AABA94 /* AVLTreeTestsTests */ = { - isa = PBXGroup; - children = ( - 763F287C1C77228700AABA94 /* AVLTreeTestsTests.swift */, - 763F288A1C77254000AABA94 /* TreeNodeTest.swift */, - 763F287E1C77228700AABA94 /* Info.plist */, - ); - path = AVLTreeTestsTests; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 763F28631C77228600AABA94 /* AVLTreeTests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 763F28811C77228700AABA94 /* Build configuration list for PBXNativeTarget "AVLTreeTests" */; - buildPhases = ( - 763F28601C77228600AABA94 /* Sources */, - 763F28611C77228600AABA94 /* Frameworks */, - 763F28621C77228600AABA94 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = AVLTreeTests; - productName = AVLTreeTests; - productReference = 763F28641C77228700AABA94 /* AVLTreeTests.app */; - productType = "com.apple.product-type.application"; - }; - 763F28771C77228700AABA94 /* AVLTreeTestsTests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 763F28841C77228700AABA94 /* Build configuration list for PBXNativeTarget "AVLTreeTestsTests" */; - buildPhases = ( - 763F28741C77228700AABA94 /* Sources */, - 763F28751C77228700AABA94 /* Frameworks */, - 763F28761C77228700AABA94 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - 763F287A1C77228700AABA94 /* PBXTargetDependency */, - ); - name = AVLTreeTestsTests; - productName = AVLTreeTestsTests; - productReference = 763F28781C77228700AABA94 /* AVLTreeTestsTests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 763F285C1C77228600AABA94 /* Project object */ = { - isa = PBXProject; - attributes = { - LastSwiftUpdateCheck = 0720; - LastUpgradeCheck = 0720; - ORGANIZATIONNAME = "Swift Algorithm Club"; - TargetAttributes = { - 763F28631C77228600AABA94 = { - CreatedOnToolsVersion = 7.2.1; - DevelopmentTeam = 6V43LV5QCY; - }; - 763F28771C77228700AABA94 = { - CreatedOnToolsVersion = 7.2.1; - DevelopmentTeam = 6V43LV5QCY; - TestTargetID = 763F28631C77228600AABA94; - }; - }; - }; - buildConfigurationList = 763F285F1C77228600AABA94 /* Build configuration list for PBXProject "AVLTreeTests" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 763F285B1C77228600AABA94; - productRefGroup = 763F28651C77228700AABA94 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 763F28631C77228600AABA94 /* AVLTreeTests */, - 763F28771C77228700AABA94 /* AVLTreeTestsTests */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 763F28621C77228600AABA94 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 763F28721C77228700AABA94 /* LaunchScreen.storyboard in Resources */, - 763F286F1C77228700AABA94 /* Assets.xcassets in Resources */, - 763F286D1C77228700AABA94 /* Main.storyboard in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 763F28761C77228700AABA94 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 763F28601C77228600AABA94 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 763F28881C77229D00AABA94 /* AVLTree.swift in Sources */, - 763F286A1C77228700AABA94 /* ViewController.swift in Sources */, - 763F28681C77228700AABA94 /* AppDelegate.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 763F28741C77228700AABA94 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 763F287D1C77228700AABA94 /* AVLTreeTestsTests.swift in Sources */, - 763F288B1C77254000AABA94 /* TreeNodeTest.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 763F287A1C77228700AABA94 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 763F28631C77228600AABA94 /* AVLTreeTests */; - targetProxy = 763F28791C77228700AABA94 /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin PBXVariantGroup section */ - 763F286B1C77228700AABA94 /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 763F286C1C77228700AABA94 /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 763F28701C77228700AABA94 /* LaunchScreen.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 763F28711C77228700AABA94 /* Base */, - ); - name = LaunchScreen.storyboard; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 763F287F1C77228700AABA94 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.2; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 763F28801C77228700AABA94 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.2; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 763F28821C77228700AABA94 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = AVLTreeTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.sac.AVLTreeTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 763F28831C77228700AABA94 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = AVLTreeTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.sac.AVLTreeTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - 763F28851C77228700AABA94 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - INFOPLIST_FILE = AVLTreeTestsTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.sac.AVLTreeTestsTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/AVLTreeTests.app/AVLTreeTests"; - }; - name = Debug; - }; - 763F28861C77228700AABA94 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - INFOPLIST_FILE = AVLTreeTestsTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.sac.AVLTreeTestsTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/AVLTreeTests.app/AVLTreeTests"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 763F285F1C77228600AABA94 /* Build configuration list for PBXProject "AVLTreeTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 763F287F1C77228700AABA94 /* Debug */, - 763F28801C77228700AABA94 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 763F28811C77228700AABA94 /* Build configuration list for PBXNativeTarget "AVLTreeTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 763F28821C77228700AABA94 /* Debug */, - 763F28831C77228700AABA94 /* Release */, - ); - defaultConfigurationIsVisible = 0; - }; - 763F28841C77228700AABA94 /* Build configuration list for PBXNativeTarget "AVLTreeTestsTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 763F28851C77228700AABA94 /* Debug */, - 763F28861C77228700AABA94 /* Release */, - ); - defaultConfigurationIsVisible = 0; - }; -/* End XCConfigurationList section */ - }; - rootObject = 763F285C1C77228600AABA94 /* Project object */; -} diff --git a/AVL Tree/AVLTree Tests/AVLTreeTests/AppDelegate.swift b/AVL Tree/AVLTree Tests/AVLTreeTests/AppDelegate.swift deleted file mode 100644 index ac29ab4db..000000000 --- a/AVL Tree/AVLTree Tests/AVLTreeTests/AppDelegate.swift +++ /dev/null @@ -1,46 +0,0 @@ -// -// AppDelegate.swift -// AVLTreeTests -// -// Created by Barbara Rodeker on 2/19/16. -// Copyright © 2016 Swift Algorithm Club. All rights reserved. -// - -import UIKit - -@UIApplicationMain -class AppDelegate: UIResponder, UIApplicationDelegate { - - var window: UIWindow? - - - func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { - // Override point for customization after application launch. - return true - } - - func applicationWillResignActive(application: UIApplication) { - // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. - // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. - } - - func applicationDidEnterBackground(application: UIApplication) { - // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. - // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. - } - - func applicationWillEnterForeground(application: UIApplication) { - // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. - } - - func applicationDidBecomeActive(application: UIApplication) { - // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. - } - - func applicationWillTerminate(application: UIApplication) { - // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. - } - - -} - diff --git a/AVL Tree/AVLTree Tests/AVLTreeTests/Assets.xcassets/AppIcon.appiconset/Contents.json b/AVL Tree/AVLTree Tests/AVLTreeTests/Assets.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index 36d2c80d8..000000000 --- a/AVL Tree/AVLTree Tests/AVLTreeTests/Assets.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,68 +0,0 @@ -{ - "images" : [ - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "60x60", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "60x60", - "scale" : "3x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "76x76", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "76x76", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/AVL Tree/AVLTree Tests/AVLTreeTests/Base.lproj/LaunchScreen.storyboard b/AVL Tree/AVLTree Tests/AVLTreeTests/Base.lproj/LaunchScreen.storyboard deleted file mode 100644 index 2e721e183..000000000 --- a/AVL Tree/AVLTree Tests/AVLTreeTests/Base.lproj/LaunchScreen.storyboard +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/AVL Tree/AVLTree Tests/AVLTreeTests/Base.lproj/Main.storyboard b/AVL Tree/AVLTree Tests/AVLTreeTests/Base.lproj/Main.storyboard deleted file mode 100644 index 3a2a49bad..000000000 --- a/AVL Tree/AVLTree Tests/AVLTreeTests/Base.lproj/Main.storyboard +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/AVL Tree/AVLTree Tests/AVLTreeTests/Info.plist b/AVL Tree/AVLTree Tests/AVLTreeTests/Info.plist deleted file mode 100644 index 40c6215d9..000000000 --- a/AVL Tree/AVLTree Tests/AVLTreeTests/Info.plist +++ /dev/null @@ -1,47 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - LSRequiresIPhoneOS - - UILaunchStoryboardName - LaunchScreen - UIMainStoryboardFile - Main - UIRequiredDeviceCapabilities - - armv7 - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - - diff --git a/AVL Tree/AVLTree Tests/AVLTreeTests/ViewController.swift b/AVL Tree/AVLTree Tests/AVLTreeTests/ViewController.swift deleted file mode 100644 index 88030d517..000000000 --- a/AVL Tree/AVLTree Tests/AVLTreeTests/ViewController.swift +++ /dev/null @@ -1,25 +0,0 @@ -// -// ViewController.swift -// AVLTreeTests -// -// Created by Barbara Rodeker on 2/19/16. -// Copyright © 2016 Swift Algorithm Club. All rights reserved. -// - -import UIKit - -class ViewController: UIViewController { - - override func viewDidLoad() { - super.viewDidLoad() - // Do any additional setup after loading the view, typically from a nib. - } - - override func didReceiveMemoryWarning() { - super.didReceiveMemoryWarning() - // Dispose of any resources that can be recreated. - } - - -} - diff --git a/AVL Tree/AVLTree Tests/AVLTreeTestsTests/AVLTreeTestsTests.swift b/AVL Tree/AVLTree Tests/AVLTreeTestsTests/AVLTreeTestsTests.swift deleted file mode 100644 index 01ac0b5e5..000000000 --- a/AVL Tree/AVLTree Tests/AVLTreeTestsTests/AVLTreeTestsTests.swift +++ /dev/null @@ -1,82 +0,0 @@ -// -// AVLTreeTestsTests.swift -// AVLTreeTestsTests -// -// Created by Barbara Rodeker on 2/19/16. -// Copyright © 2016 Swift Algorithm Club. All rights reserved. -// - -import XCTest -@testable import AVLTreeTests - -class AVLTreeTestsTests: XCTestCase { - - var tree : AVLTree? - - override func setUp() { - super.setUp() - - tree = AVLTree() - tree?.insert(1, "A") - tree?.insert(2, "B") - tree?.insert(3, "C") - tree?.insert(4, "D") - } - - override func tearDown() { - // Put teardown code here. This method is called after the invocation of each test method in the class. - super.tearDown() - } - - func testEmptyInitialization() { - let tree = AVLTree() - - XCTAssertEqual(tree.size, 0) - XCTAssertNil(tree.root) - } - - func testNotEmptyInitialization() { - XCTAssertNotNil(self.tree?.root) - XCTAssertNotEqual(self.tree!.size, 0) - } - - func testInsertDuplicated() { - self.tree?.insert(1, "A") - XCTAssertEqual(self.tree?.size, 5, "Duplicated elements should be allowed") - } - - func testSingleInsertionPerformance() { - self.measureBlock { - self.tree?.insert(5, "E") - } - } - - func testMultipleInsertionsPerformance() { - self.measureBlock { - self.tree?.autopopulateWithNodes(50) - } - } - - func testSearchExistentOnSmallTreePerformance() { - self.measureBlock { - self.tree?.search(2) - } - } - - func testSearchExistentElementOnLargeTreePerformance() { - self.measureBlock { - self.tree?.autopopulateWithNodes(500) - self.tree?.search(400) - } - } - -} - -extension AVLTree where Key : SignedIntegerType { - func autopopulateWithNodes(count : Int) { - var k : Key = 1 - for _ in 0...count { - self.insert(k++) - } - } -} diff --git a/AVL Tree/Tests/AVLTreeTests.swift b/AVL Tree/Tests/AVLTreeTests.swift new file mode 100644 index 000000000..f079603cf --- /dev/null +++ b/AVL Tree/Tests/AVLTreeTests.swift @@ -0,0 +1,80 @@ +// +// AVLTreeTestsTests.swift +// AVLTreeTestsTests +// +// Created by Barbara Rodeker on 2/19/16. +// Copyright © 2016 Swift Algorithm Club. All rights reserved. +// + +import XCTest + +class AVLTreeTests: XCTestCase { + + var tree : AVLTree? + + override func setUp() { + super.setUp() + + tree = AVLTree() + tree?.insert(1, "A") + tree?.insert(2, "B") + tree?.insert(3, "C") + tree?.insert(4, "D") + } + + override func tearDown() { + // Put teardown code here. This method is called after the invocation of each test method in the class. + super.tearDown() + } + + func testEmptyInitialization() { + let tree = AVLTree() + + XCTAssertEqual(tree.size, 0) + XCTAssertNil(tree.root) + } + + func testNotEmptyInitialization() { + XCTAssertNotNil(self.tree?.root) + XCTAssertNotEqual(self.tree!.size, 0) + } + + func testInsertDuplicated() { + self.tree?.insert(1, "A") + XCTAssertEqual(self.tree?.size, 5, "Duplicated elements should be allowed") + } + + func testSingleInsertionPerformance() { + self.measureBlock { + self.tree?.insert(5, "E") + } + } + + func testMultipleInsertionsPerformance() { + self.measureBlock { + self.tree?.autopopulateWithNodes(50) + } + } + + func testSearchExistentOnSmallTreePerformance() { + self.measureBlock { + self.tree?.search(2) + } + } + + func testSearchExistentElementOnLargeTreePerformance() { + self.measureBlock { + self.tree?.autopopulateWithNodes(500) + self.tree?.search(400) + } + } +} + +extension AVLTree where Key : SignedIntegerType { + func autopopulateWithNodes(count : Int) { + var k : Key = 1 + for _ in 0...count { + self.insert(k++) + } + } +} diff --git a/AVL Tree/AVLTree Tests/AVLTreeTestsTests/Info.plist b/AVL Tree/Tests/Info.plist similarity index 100% rename from AVL Tree/AVLTree Tests/AVLTreeTestsTests/Info.plist rename to AVL Tree/Tests/Info.plist diff --git a/AVL Tree/Tests/Tests.xcodeproj/project.pbxproj b/AVL Tree/Tests/Tests.xcodeproj/project.pbxproj new file mode 100644 index 000000000..dfaf44e8d --- /dev/null +++ b/AVL Tree/Tests/Tests.xcodeproj/project.pbxproj @@ -0,0 +1,265 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 7B80C3C91C77A112003CECC7 /* TreeNodeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C3C71C77A112003CECC7 /* TreeNodeTests.swift */; }; + 7B80C3CA1C77A112003CECC7 /* AVLTreeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C3C81C77A112003CECC7 /* AVLTreeTests.swift */; }; + 7B80C3CC1C77A120003CECC7 /* AVLTree.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C3CB1C77A120003CECC7 /* AVLTree.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 7B2BBC801C779D720067B71D /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 7B2BBC941C779E7B0067B71D /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; + 7B80C3C71C77A112003CECC7 /* TreeNodeTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TreeNodeTests.swift; sourceTree = SOURCE_ROOT; }; + 7B80C3C81C77A112003CECC7 /* AVLTreeTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AVLTreeTests.swift; sourceTree = SOURCE_ROOT; }; + 7B80C3CB1C77A120003CECC7 /* AVLTree.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = AVLTree.swift; path = ../AVLTree.swift; sourceTree = SOURCE_ROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 7B2BBC7D1C779D720067B71D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 7B2BBC681C779D710067B71D = { + isa = PBXGroup; + children = ( + 7B2BBC831C779D720067B71D /* Tests */, + 7B2BBC721C779D710067B71D /* Products */, + ); + sourceTree = ""; + }; + 7B2BBC721C779D710067B71D /* Products */ = { + isa = PBXGroup; + children = ( + 7B2BBC801C779D720067B71D /* Tests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 7B2BBC831C779D720067B71D /* Tests */ = { + isa = PBXGroup; + children = ( + 7B80C3CB1C77A120003CECC7 /* AVLTree.swift */, + 7B80C3C81C77A112003CECC7 /* AVLTreeTests.swift */, + 7B80C3C71C77A112003CECC7 /* TreeNodeTests.swift */, + 7B2BBC941C779E7B0067B71D /* Info.plist */, + ); + name = Tests; + path = TestsTests; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 7B2BBC7F1C779D720067B71D /* Tests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */; + buildPhases = ( + 7B2BBC7C1C779D720067B71D /* Sources */, + 7B2BBC7D1C779D720067B71D /* Frameworks */, + 7B2BBC7E1C779D720067B71D /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Tests; + productName = TestsTests; + productReference = 7B2BBC801C779D720067B71D /* Tests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 7B2BBC691C779D710067B71D /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0720; + LastUpgradeCheck = 0720; + ORGANIZATIONNAME = "Swift Algorithm Club"; + TargetAttributes = { + 7B2BBC7F1C779D720067B71D = { + CreatedOnToolsVersion = 7.2; + }; + }; + }; + buildConfigurationList = 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 7B2BBC681C779D710067B71D; + productRefGroup = 7B2BBC721C779D710067B71D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 7B2BBC7F1C779D720067B71D /* Tests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 7B2BBC7E1C779D720067B71D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 7B2BBC7C1C779D720067B71D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 7B80C3CC1C77A120003CECC7 /* AVLTree.swift in Sources */, + 7B80C3C91C77A112003CECC7 /* TreeNodeTests.swift in Sources */, + 7B80C3CA1C77A112003CECC7 /* AVLTreeTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 7B2BBC871C779D720067B71D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 7B2BBC881C779D720067B71D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + }; + name = Release; + }; + 7B2BBC8D1C779D720067B71D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 7B2BBC8E1C779D720067B71D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7B2BBC871C779D720067B71D /* Debug */, + 7B2BBC881C779D720067B71D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7B2BBC8D1C779D720067B71D /* Debug */, + 7B2BBC8E1C779D720067B71D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 7B2BBC691C779D710067B71D /* Project object */; +} diff --git a/AVL Tree/AVLTree Tests/AVLTreeTestsTests/TreeNodeTest.swift b/AVL Tree/Tests/TreeNodeTests.swift similarity index 97% rename from AVL Tree/AVLTree Tests/AVLTreeTestsTests/TreeNodeTest.swift rename to AVL Tree/Tests/TreeNodeTests.swift index 802277ea9..d55c4e5e2 100644 --- a/AVL Tree/AVLTree Tests/AVLTreeTestsTests/TreeNodeTest.swift +++ b/AVL Tree/Tests/TreeNodeTests.swift @@ -7,10 +7,8 @@ // import XCTest -@testable import AVLTreeTests - -class TreeNodeTest: XCTestCase { +class TreeNodeTests: XCTestCase { var root : TreeNode? var left : TreeNode? diff --git a/Array2D/Array2D Tests/array2Dtest.xcodeproj/project.pbxproj b/Array2D/Array2D Tests/array2Dtest.xcodeproj/project.pbxproj deleted file mode 100644 index b1dae1cd7..000000000 --- a/Array2D/Array2D Tests/array2Dtest.xcodeproj/project.pbxproj +++ /dev/null @@ -1,409 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 766116121C7625C600358E02 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 766116111C7625C600358E02 /* AppDelegate.swift */; }; - 766116141C7625C600358E02 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 766116131C7625C600358E02 /* ViewController.swift */; }; - 766116171C7625C600358E02 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 766116151C7625C600358E02 /* Main.storyboard */; }; - 766116191C7625C700358E02 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 766116181C7625C700358E02 /* Assets.xcassets */; }; - 7661161C1C7625C700358E02 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7661161A1C7625C700358E02 /* LaunchScreen.storyboard */; }; - 766116271C7625C700358E02 /* array2DtestTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 766116261C7625C700358E02 /* array2DtestTests.swift */; }; - 766116321C76261600358E02 /* Array2D.swift in Sources */ = {isa = PBXBuildFile; fileRef = 766116311C76261600358E02 /* Array2D.swift */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 766116231C7625C700358E02 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 766116061C7625C600358E02 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 7661160D1C7625C600358E02; - remoteInfo = array2Dtest; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXFileReference section */ - 7661160E1C7625C600358E02 /* array2Dtest.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = array2Dtest.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 766116111C7625C600358E02 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 766116131C7625C600358E02 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; - 766116161C7625C600358E02 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 766116181C7625C700358E02 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - 7661161B1C7625C700358E02 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; - 7661161D1C7625C700358E02 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 766116221C7625C700358E02 /* array2DtestTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = array2DtestTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 766116261C7625C700358E02 /* array2DtestTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = array2DtestTests.swift; sourceTree = ""; }; - 766116281C7625C700358E02 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 766116311C76261600358E02 /* Array2D.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Array2D.swift; path = ../../Array2D.swift; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 7661160B1C7625C600358E02 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 7661161F1C7625C700358E02 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 766116051C7625C600358E02 = { - isa = PBXGroup; - children = ( - 766116101C7625C600358E02 /* array2Dtest */, - 766116251C7625C700358E02 /* array2DtestTests */, - 7661160F1C7625C600358E02 /* Products */, - ); - sourceTree = ""; - }; - 7661160F1C7625C600358E02 /* Products */ = { - isa = PBXGroup; - children = ( - 7661160E1C7625C600358E02 /* array2Dtest.app */, - 766116221C7625C700358E02 /* array2DtestTests.xctest */, - ); - name = Products; - sourceTree = ""; - }; - 766116101C7625C600358E02 /* array2Dtest */ = { - isa = PBXGroup; - children = ( - 766116311C76261600358E02 /* Array2D.swift */, - 766116111C7625C600358E02 /* AppDelegate.swift */, - 766116131C7625C600358E02 /* ViewController.swift */, - 766116151C7625C600358E02 /* Main.storyboard */, - 766116181C7625C700358E02 /* Assets.xcassets */, - 7661161A1C7625C700358E02 /* LaunchScreen.storyboard */, - 7661161D1C7625C700358E02 /* Info.plist */, - ); - path = array2Dtest; - sourceTree = ""; - }; - 766116251C7625C700358E02 /* array2DtestTests */ = { - isa = PBXGroup; - children = ( - 766116261C7625C700358E02 /* array2DtestTests.swift */, - 766116281C7625C700358E02 /* Info.plist */, - ); - path = array2DtestTests; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 7661160D1C7625C600358E02 /* array2Dtest */ = { - isa = PBXNativeTarget; - buildConfigurationList = 7661162B1C7625C700358E02 /* Build configuration list for PBXNativeTarget "array2Dtest" */; - buildPhases = ( - 7661160A1C7625C600358E02 /* Sources */, - 7661160B1C7625C600358E02 /* Frameworks */, - 7661160C1C7625C600358E02 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = array2Dtest; - productName = array2Dtest; - productReference = 7661160E1C7625C600358E02 /* array2Dtest.app */; - productType = "com.apple.product-type.application"; - }; - 766116211C7625C700358E02 /* array2DtestTests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 7661162E1C7625C700358E02 /* Build configuration list for PBXNativeTarget "array2DtestTests" */; - buildPhases = ( - 7661161E1C7625C700358E02 /* Sources */, - 7661161F1C7625C700358E02 /* Frameworks */, - 766116201C7625C700358E02 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - 766116241C7625C700358E02 /* PBXTargetDependency */, - ); - name = array2DtestTests; - productName = array2DtestTests; - productReference = 766116221C7625C700358E02 /* array2DtestTests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 766116061C7625C600358E02 /* Project object */ = { - isa = PBXProject; - attributes = { - LastSwiftUpdateCheck = 0720; - LastUpgradeCheck = 0720; - ORGANIZATIONNAME = "Swift Algorithm Club"; - TargetAttributes = { - 7661160D1C7625C600358E02 = { - CreatedOnToolsVersion = 7.2.1; - DevelopmentTeam = 6V43LV5QCY; - }; - 766116211C7625C700358E02 = { - CreatedOnToolsVersion = 7.2.1; - DevelopmentTeam = 6V43LV5QCY; - TestTargetID = 7661160D1C7625C600358E02; - }; - }; - }; - buildConfigurationList = 766116091C7625C600358E02 /* Build configuration list for PBXProject "array2Dtest" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 766116051C7625C600358E02; - productRefGroup = 7661160F1C7625C600358E02 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 7661160D1C7625C600358E02 /* array2Dtest */, - 766116211C7625C700358E02 /* array2DtestTests */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 7661160C1C7625C600358E02 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 7661161C1C7625C700358E02 /* LaunchScreen.storyboard in Resources */, - 766116191C7625C700358E02 /* Assets.xcassets in Resources */, - 766116171C7625C600358E02 /* Main.storyboard in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 766116201C7625C700358E02 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 7661160A1C7625C600358E02 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 766116141C7625C600358E02 /* ViewController.swift in Sources */, - 766116321C76261600358E02 /* Array2D.swift in Sources */, - 766116121C7625C600358E02 /* AppDelegate.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 7661161E1C7625C700358E02 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 766116271C7625C700358E02 /* array2DtestTests.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 766116241C7625C700358E02 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 7661160D1C7625C600358E02 /* array2Dtest */; - targetProxy = 766116231C7625C700358E02 /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin PBXVariantGroup section */ - 766116151C7625C600358E02 /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 766116161C7625C600358E02 /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 7661161A1C7625C700358E02 /* LaunchScreen.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 7661161B1C7625C700358E02 /* Base */, - ); - name = LaunchScreen.storyboard; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 766116291C7625C700358E02 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.2; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 7661162A1C7625C700358E02 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.2; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 7661162C1C7625C700358E02 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = array2Dtest/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.sac.array2Dtest; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 7661162D1C7625C700358E02 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = array2Dtest/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.sac.array2Dtest; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - 7661162F1C7625C700358E02 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - INFOPLIST_FILE = array2DtestTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.sac.array2DtestTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/array2Dtest.app/array2Dtest"; - }; - name = Debug; - }; - 766116301C7625C700358E02 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - INFOPLIST_FILE = array2DtestTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.sac.array2DtestTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/array2Dtest.app/array2Dtest"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 766116091C7625C600358E02 /* Build configuration list for PBXProject "array2Dtest" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 766116291C7625C700358E02 /* Debug */, - 7661162A1C7625C700358E02 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 7661162B1C7625C700358E02 /* Build configuration list for PBXNativeTarget "array2Dtest" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 7661162C1C7625C700358E02 /* Debug */, - 7661162D1C7625C700358E02 /* Release */, - ); - defaultConfigurationIsVisible = 0; - }; - 7661162E1C7625C700358E02 /* Build configuration list for PBXNativeTarget "array2DtestTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 7661162F1C7625C700358E02 /* Debug */, - 766116301C7625C700358E02 /* Release */, - ); - defaultConfigurationIsVisible = 0; - }; -/* End XCConfigurationList section */ - }; - rootObject = 766116061C7625C600358E02 /* Project object */; -} diff --git a/Array2D/Array2D Tests/array2Dtest.xcodeproj/xcshareddata/xcbaselines/766116211C7625C700358E02.xcbaseline/B9780967-0BD8-4A91-8657-A96EFB81859F.plist b/Array2D/Array2D Tests/array2Dtest.xcodeproj/xcshareddata/xcbaselines/766116211C7625C700358E02.xcbaseline/B9780967-0BD8-4A91-8657-A96EFB81859F.plist deleted file mode 100644 index 124dc73bc..000000000 --- a/Array2D/Array2D Tests/array2Dtest.xcodeproj/xcshareddata/xcbaselines/766116211C7625C700358E02.xcbaseline/B9780967-0BD8-4A91-8657-A96EFB81859F.plist +++ /dev/null @@ -1,22 +0,0 @@ - - - - - classNames - - Array2DTest - - testPerformanceOnSmallArray() - - com.apple.XCTPerformanceMetric_WallClockTime - - baselineAverage - 0.377 - baselineIntegrationDisplayName - Local Baseline - - - - - - diff --git a/Array2D/Array2D Tests/array2Dtest.xcodeproj/xcshareddata/xcbaselines/766116211C7625C700358E02.xcbaseline/Info.plist b/Array2D/Array2D Tests/array2Dtest.xcodeproj/xcshareddata/xcbaselines/766116211C7625C700358E02.xcbaseline/Info.plist deleted file mode 100644 index a0e45b60a..000000000 --- a/Array2D/Array2D Tests/array2Dtest.xcodeproj/xcshareddata/xcbaselines/766116211C7625C700358E02.xcbaseline/Info.plist +++ /dev/null @@ -1,40 +0,0 @@ - - - - - runDestinationsByUUID - - B9780967-0BD8-4A91-8657-A96EFB81859F - - localComputer - - busSpeedInMHz - 100 - cpuCount - 1 - cpuKind - Intel Core i5 - cpuSpeedInMHz - 2500 - logicalCPUCoresPerPackage - 4 - modelCode - Macmini6,1 - physicalCPUCoresPerPackage - 2 - platformIdentifier - com.apple.platform.macosx - - targetArchitecture - x86_64 - targetDevice - - modelCode - iPhone8,2 - platformIdentifier - com.apple.platform.iphonesimulator - - - - - diff --git a/Array2D/Array2D Tests/array2Dtest/AppDelegate.swift b/Array2D/Array2D Tests/array2Dtest/AppDelegate.swift deleted file mode 100644 index 7d1c32f11..000000000 --- a/Array2D/Array2D Tests/array2Dtest/AppDelegate.swift +++ /dev/null @@ -1,46 +0,0 @@ -// -// AppDelegate.swift -// array2Dtest -// -// Created by Barbara Rodeker on 2/18/16. -// Copyright © 2016 Swift Algorithm Club. All rights reserved. -// - -import UIKit - -@UIApplicationMain -class AppDelegate: UIResponder, UIApplicationDelegate { - - var window: UIWindow? - - - func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { - // Override point for customization after application launch. - return true - } - - func applicationWillResignActive(application: UIApplication) { - // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. - // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. - } - - func applicationDidEnterBackground(application: UIApplication) { - // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. - // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. - } - - func applicationWillEnterForeground(application: UIApplication) { - // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. - } - - func applicationDidBecomeActive(application: UIApplication) { - // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. - } - - func applicationWillTerminate(application: UIApplication) { - // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. - } - - -} - diff --git a/Array2D/Array2D Tests/array2Dtest/Assets.xcassets/AppIcon.appiconset/Contents.json b/Array2D/Array2D Tests/array2Dtest/Assets.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index 36d2c80d8..000000000 --- a/Array2D/Array2D Tests/array2Dtest/Assets.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,68 +0,0 @@ -{ - "images" : [ - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "60x60", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "60x60", - "scale" : "3x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "76x76", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "76x76", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/Array2D/Array2D Tests/array2Dtest/Base.lproj/LaunchScreen.storyboard b/Array2D/Array2D Tests/array2Dtest/Base.lproj/LaunchScreen.storyboard deleted file mode 100644 index 2e721e183..000000000 --- a/Array2D/Array2D Tests/array2Dtest/Base.lproj/LaunchScreen.storyboard +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Array2D/Array2D Tests/array2Dtest/Base.lproj/Main.storyboard b/Array2D/Array2D Tests/array2Dtest/Base.lproj/Main.storyboard deleted file mode 100644 index 3a2a49bad..000000000 --- a/Array2D/Array2D Tests/array2Dtest/Base.lproj/Main.storyboard +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Array2D/Array2D Tests/array2Dtest/Info.plist b/Array2D/Array2D Tests/array2Dtest/Info.plist deleted file mode 100644 index 40c6215d9..000000000 --- a/Array2D/Array2D Tests/array2Dtest/Info.plist +++ /dev/null @@ -1,47 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - LSRequiresIPhoneOS - - UILaunchStoryboardName - LaunchScreen - UIMainStoryboardFile - Main - UIRequiredDeviceCapabilities - - armv7 - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - - diff --git a/Array2D/Array2D Tests/array2Dtest/ViewController.swift b/Array2D/Array2D Tests/array2Dtest/ViewController.swift deleted file mode 100644 index 669b79b89..000000000 --- a/Array2D/Array2D Tests/array2Dtest/ViewController.swift +++ /dev/null @@ -1,25 +0,0 @@ -// -// ViewController.swift -// array2Dtest -// -// Created by Barbara Rodeker on 2/18/16. -// Copyright © 2016 Swift Algorithm Club. All rights reserved. -// - -import UIKit - -class ViewController: UIViewController { - - override func viewDidLoad() { - super.viewDidLoad() - // Do any additional setup after loading the view, typically from a nib. - } - - override func didReceiveMemoryWarning() { - super.didReceiveMemoryWarning() - // Dispose of any resources that can be recreated. - } - - -} - diff --git a/Array2D/Array2D Tests/array2DtestTests/array2DtestTests.swift b/Array2D/Array2D Tests/array2DtestTests/array2DtestTests.swift deleted file mode 100644 index 234d0f9b4..000000000 --- a/Array2D/Array2D Tests/array2DtestTests/array2DtestTests.swift +++ /dev/null @@ -1,80 +0,0 @@ -// -// Array2DTest.swift -// algorithmclub -// -// Created by Barbara Rodeker on 2/16/16. -// Copyright © 2016 Swift Algorithm Club. All rights reserved. -// - -import XCTest -@testable import array2Dtest - -class Array2DTest: XCTestCase { - - override func setUp() { - super.setUp() - } - - override func tearDown() { - super.tearDown() - } - - func testIntegerArrayWithPositiveRowsAndColumns() { - let array = Array2D(columns: 3, rows: 2, initialValue: 0) - - XCTAssertEqual(array.columns, 3, "Column count setup failed") - XCTAssertEqual(array.rows, 2, "Rows count setup failed") - XCTAssertEqual(array[2,1], 0, "Integer array: Initialization value is wrong") - } - - func testStringArrayWithPositiveRowsAndColumns() { - let array = Array2D(columns: 3, rows: 2, initialValue: "empty") - - XCTAssertEqual(array.columns, 3, "Column count setup failed") - XCTAssertEqual(array.rows, 2, "Rows count setup failed") - XCTAssertEqual(array[2,1], "empty", "String array: Initialization value is wrong") - } - - func testCustomClassArrayWithPositiveRowsAndColumns() { - let array = Array2D(columns: 3, rows: 2, initialValue: TestElement(identifier: "pepe")) - - XCTAssertEqual(array.columns, 3, "Column count setup failed") - XCTAssertEqual(array.rows, 2, "Rows count setup failed") - XCTAssertEqual(array[2,1], TestElement(identifier: "pepe"), "Custom Class array: Initialization value is wrong") - } - - func testPerformanceOnSmallArray() { - self.measureBlock { - self.printArrayWith(columns: 2, rows: 2, inititalValue: 1) - } - } - -// func testPerformanceOnLargeArray() { -// self.measureBlock { -// self.printArrayWith(columns: 2000, rows: 2000, inititalValue: 1) -// } -// } - - private func printArrayWith(columns columns: Int, rows: Int, inititalValue: Int){ - let array = Array2D(columns: columns, rows: rows, initialValue: 4) - for r in 0.. Bool { - return lhs.identifier == rhs.identifier -} - diff --git a/Array2D/Tests/Array2DTests.swift b/Array2D/Tests/Array2DTests.swift new file mode 100644 index 000000000..3383b5eb3 --- /dev/null +++ b/Array2D/Tests/Array2DTests.swift @@ -0,0 +1,78 @@ +// +// Array2DTest.swift +// algorithmclub +// +// Created by Barbara Rodeker on 2/16/16. +// Copyright © 2016 Swift Algorithm Club. All rights reserved. +// + +import XCTest + +class Array2DTest: XCTestCase { + + override func setUp() { + super.setUp() + } + + override func tearDown() { + super.tearDown() + } + + func testIntegerArrayWithPositiveRowsAndColumns() { + let array = Array2D(columns: 3, rows: 2, initialValue: 0) + + XCTAssertEqual(array.columns, 3, "Column count setup failed") + XCTAssertEqual(array.rows, 2, "Rows count setup failed") + XCTAssertEqual(array[2,1], 0, "Integer array: Initialization value is wrong") + } + + func testStringArrayWithPositiveRowsAndColumns() { + let array = Array2D(columns: 3, rows: 2, initialValue: "empty") + + XCTAssertEqual(array.columns, 3, "Column count setup failed") + XCTAssertEqual(array.rows, 2, "Rows count setup failed") + XCTAssertEqual(array[2,1], "empty", "String array: Initialization value is wrong") + } + + func testCustomClassArrayWithPositiveRowsAndColumns() { + let array = Array2D(columns: 3, rows: 2, initialValue: TestElement(identifier: "pepe")) + + XCTAssertEqual(array.columns, 3, "Column count setup failed") + XCTAssertEqual(array.rows, 2, "Rows count setup failed") + XCTAssertEqual(array[2,1], TestElement(identifier: "pepe"), "Custom Class array: Initialization value is wrong") + } + + func testPerformanceOnSmallArray() { + self.measureBlock { + self.printArrayWith(columns: 2, rows: 2, inititalValue: 1) + } + } + + // func testPerformanceOnLargeArray() { + // self.measureBlock { + // self.printArrayWith(columns: 2000, rows: 2000, inititalValue: 1) + // } + // } + + private func printArrayWith(columns columns: Int, rows: Int, inititalValue: Int){ + let array = Array2D(columns: columns, rows: rows, initialValue: 4) + for r in 0.. Bool { + return lhs.identifier == rhs.identifier +} diff --git a/Array2D/Array2D Tests/array2DtestTests/Info.plist b/Array2D/Tests/Info.plist similarity index 100% rename from Array2D/Array2D Tests/array2DtestTests/Info.plist rename to Array2D/Tests/Info.plist diff --git a/Array2D/Tests/Tests.xcodeproj/project.pbxproj b/Array2D/Tests/Tests.xcodeproj/project.pbxproj new file mode 100644 index 000000000..8618e7530 --- /dev/null +++ b/Array2D/Tests/Tests.xcodeproj/project.pbxproj @@ -0,0 +1,261 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 7B2BBC901C779DAC0067B71D /* Array2DTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B2BBC8F1C779DAC0067B71D /* Array2DTests.swift */; }; + 7B2BBC991C77A04F0067B71D /* Array2D.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B2BBC981C77A04F0067B71D /* Array2D.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 7B2BBC801C779D720067B71D /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 7B2BBC8F1C779DAC0067B71D /* Array2DTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Array2DTests.swift; sourceTree = SOURCE_ROOT; }; + 7B2BBC941C779E7B0067B71D /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; + 7B2BBC981C77A04F0067B71D /* Array2D.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Array2D.swift; path = ../Array2D.swift; sourceTree = SOURCE_ROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 7B2BBC7D1C779D720067B71D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 7B2BBC681C779D710067B71D = { + isa = PBXGroup; + children = ( + 7B2BBC831C779D720067B71D /* Tests */, + 7B2BBC721C779D710067B71D /* Products */, + ); + sourceTree = ""; + }; + 7B2BBC721C779D710067B71D /* Products */ = { + isa = PBXGroup; + children = ( + 7B2BBC801C779D720067B71D /* Tests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 7B2BBC831C779D720067B71D /* Tests */ = { + isa = PBXGroup; + children = ( + 7B2BBC981C77A04F0067B71D /* Array2D.swift */, + 7B2BBC8F1C779DAC0067B71D /* Array2DTests.swift */, + 7B2BBC941C779E7B0067B71D /* Info.plist */, + ); + name = Tests; + path = TestsTests; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 7B2BBC7F1C779D720067B71D /* Tests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */; + buildPhases = ( + 7B2BBC7C1C779D720067B71D /* Sources */, + 7B2BBC7D1C779D720067B71D /* Frameworks */, + 7B2BBC7E1C779D720067B71D /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Tests; + productName = TestsTests; + productReference = 7B2BBC801C779D720067B71D /* Tests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 7B2BBC691C779D710067B71D /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0720; + LastUpgradeCheck = 0720; + ORGANIZATIONNAME = "Swift Algorithm Club"; + TargetAttributes = { + 7B2BBC7F1C779D720067B71D = { + CreatedOnToolsVersion = 7.2; + }; + }; + }; + buildConfigurationList = 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 7B2BBC681C779D710067B71D; + productRefGroup = 7B2BBC721C779D710067B71D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 7B2BBC7F1C779D720067B71D /* Tests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 7B2BBC7E1C779D720067B71D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 7B2BBC7C1C779D720067B71D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 7B2BBC901C779DAC0067B71D /* Array2DTests.swift in Sources */, + 7B2BBC991C77A04F0067B71D /* Array2D.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 7B2BBC871C779D720067B71D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 7B2BBC881C779D720067B71D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + }; + name = Release; + }; + 7B2BBC8D1C779D720067B71D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 7B2BBC8E1C779D720067B71D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7B2BBC871C779D720067B71D /* Debug */, + 7B2BBC881C779D720067B71D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7B2BBC8D1C779D720067B71D /* Debug */, + 7B2BBC8E1C779D720067B71D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 7B2BBC691C779D710067B71D /* Project object */; +} diff --git a/Binary Search Tree/Solution 1/BinarySearchTree Tests/BinarySearchTree.xcodeproj/project.pbxproj b/Binary Search Tree/Solution 1/BinarySearchTree Tests/BinarySearchTree.xcodeproj/project.pbxproj deleted file mode 100644 index d4ed37459..000000000 --- a/Binary Search Tree/Solution 1/BinarySearchTree Tests/BinarySearchTree.xcodeproj/project.pbxproj +++ /dev/null @@ -1,394 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 7B1BF9F11C678D630051C9A4 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B1BF9F01C678D630051C9A4 /* AppDelegate.swift */; }; - 7B1BF9F31C678D630051C9A4 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7B1BF9F21C678D630051C9A4 /* Assets.xcassets */; }; - 7B1BF9F61C678D630051C9A4 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7B1BF9F41C678D630051C9A4 /* MainMenu.xib */; }; - 7B1BFA011C678D630051C9A4 /* BinarySearchTreeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B1BFA001C678D630051C9A4 /* BinarySearchTreeTests.swift */; }; - 7B1BFA0C1C678D820051C9A4 /* BinarySearchTree.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B1BFA0B1C678D820051C9A4 /* BinarySearchTree.swift */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 7B1BF9FD1C678D630051C9A4 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 7B1BF9E51C678D630051C9A4 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 7B1BF9EC1C678D630051C9A4; - remoteInfo = BinarySearchTree; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXFileReference section */ - 7B1BF9ED1C678D630051C9A4 /* BinarySearchTree.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = BinarySearchTree.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 7B1BF9F01C678D630051C9A4 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 7B1BF9F21C678D630051C9A4 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - 7B1BF9F51C678D630051C9A4 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; - 7B1BF9F71C678D630051C9A4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 7B1BF9FC1C678D630051C9A4 /* BinarySearchTreeTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = BinarySearchTreeTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 7B1BFA001C678D630051C9A4 /* BinarySearchTreeTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BinarySearchTreeTests.swift; sourceTree = ""; }; - 7B1BFA021C678D630051C9A4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 7B1BFA0B1C678D820051C9A4 /* BinarySearchTree.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BinarySearchTree.swift; path = ../../BinarySearchTree.swift; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 7B1BF9EA1C678D630051C9A4 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 7B1BF9F91C678D630051C9A4 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 7B1BF9E41C678D630051C9A4 = { - isa = PBXGroup; - children = ( - 7B1BF9EF1C678D630051C9A4 /* BinarySearchTree */, - 7B1BF9FF1C678D630051C9A4 /* BinarySearchTreeTests */, - 7B1BF9EE1C678D630051C9A4 /* Products */, - ); - sourceTree = ""; - }; - 7B1BF9EE1C678D630051C9A4 /* Products */ = { - isa = PBXGroup; - children = ( - 7B1BF9ED1C678D630051C9A4 /* BinarySearchTree.app */, - 7B1BF9FC1C678D630051C9A4 /* BinarySearchTreeTests.xctest */, - ); - name = Products; - sourceTree = ""; - }; - 7B1BF9EF1C678D630051C9A4 /* BinarySearchTree */ = { - isa = PBXGroup; - children = ( - 7B1BF9F01C678D630051C9A4 /* AppDelegate.swift */, - 7B1BF9F21C678D630051C9A4 /* Assets.xcassets */, - 7B1BFA0B1C678D820051C9A4 /* BinarySearchTree.swift */, - 7B1BF9F71C678D630051C9A4 /* Info.plist */, - 7B1BF9F41C678D630051C9A4 /* MainMenu.xib */, - ); - path = BinarySearchTree; - sourceTree = ""; - }; - 7B1BF9FF1C678D630051C9A4 /* BinarySearchTreeTests */ = { - isa = PBXGroup; - children = ( - 7B1BFA001C678D630051C9A4 /* BinarySearchTreeTests.swift */, - 7B1BFA021C678D630051C9A4 /* Info.plist */, - ); - path = BinarySearchTreeTests; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 7B1BF9EC1C678D630051C9A4 /* BinarySearchTree */ = { - isa = PBXNativeTarget; - buildConfigurationList = 7B1BFA051C678D630051C9A4 /* Build configuration list for PBXNativeTarget "BinarySearchTree" */; - buildPhases = ( - 7B1BF9E91C678D630051C9A4 /* Sources */, - 7B1BF9EA1C678D630051C9A4 /* Frameworks */, - 7B1BF9EB1C678D630051C9A4 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = BinarySearchTree; - productName = BinarySearchTree; - productReference = 7B1BF9ED1C678D630051C9A4 /* BinarySearchTree.app */; - productType = "com.apple.product-type.application"; - }; - 7B1BF9FB1C678D630051C9A4 /* BinarySearchTreeTests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 7B1BFA081C678D630051C9A4 /* Build configuration list for PBXNativeTarget "BinarySearchTreeTests" */; - buildPhases = ( - 7B1BF9F81C678D630051C9A4 /* Sources */, - 7B1BF9F91C678D630051C9A4 /* Frameworks */, - 7B1BF9FA1C678D630051C9A4 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - 7B1BF9FE1C678D630051C9A4 /* PBXTargetDependency */, - ); - name = BinarySearchTreeTests; - productName = BinarySearchTreeTests; - productReference = 7B1BF9FC1C678D630051C9A4 /* BinarySearchTreeTests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 7B1BF9E51C678D630051C9A4 /* Project object */ = { - isa = PBXProject; - attributes = { - LastSwiftUpdateCheck = 0720; - LastUpgradeCheck = 0720; - ORGANIZATIONNAME = "Swift Algorithm Club"; - TargetAttributes = { - 7B1BF9EC1C678D630051C9A4 = { - CreatedOnToolsVersion = 7.2; - }; - 7B1BF9FB1C678D630051C9A4 = { - CreatedOnToolsVersion = 7.2; - TestTargetID = 7B1BF9EC1C678D630051C9A4; - }; - }; - }; - buildConfigurationList = 7B1BF9E81C678D630051C9A4 /* Build configuration list for PBXProject "BinarySearchTree" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 7B1BF9E41C678D630051C9A4; - productRefGroup = 7B1BF9EE1C678D630051C9A4 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 7B1BF9EC1C678D630051C9A4 /* BinarySearchTree */, - 7B1BF9FB1C678D630051C9A4 /* BinarySearchTreeTests */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 7B1BF9EB1C678D630051C9A4 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 7B1BF9F31C678D630051C9A4 /* Assets.xcassets in Resources */, - 7B1BF9F61C678D630051C9A4 /* MainMenu.xib in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 7B1BF9FA1C678D630051C9A4 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 7B1BF9E91C678D630051C9A4 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 7B1BFA0C1C678D820051C9A4 /* BinarySearchTree.swift in Sources */, - 7B1BF9F11C678D630051C9A4 /* AppDelegate.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 7B1BF9F81C678D630051C9A4 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 7B1BFA011C678D630051C9A4 /* BinarySearchTreeTests.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 7B1BF9FE1C678D630051C9A4 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 7B1BF9EC1C678D630051C9A4 /* BinarySearchTree */; - targetProxy = 7B1BF9FD1C678D630051C9A4 /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin PBXVariantGroup section */ - 7B1BF9F41C678D630051C9A4 /* MainMenu.xib */ = { - isa = PBXVariantGroup; - children = ( - 7B1BF9F51C678D630051C9A4 /* Base */, - ); - name = MainMenu.xib; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 7B1BFA031C678D630051C9A4 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "-"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.11; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = macosx; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - }; - name = Debug; - }; - 7B1BFA041C678D630051C9A4 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "-"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.11; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = macosx; - }; - name = Release; - }; - 7B1BFA061C678D630051C9A4 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = BinarySearchTree/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.BinarySearchTree; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 7B1BFA071C678D630051C9A4 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = BinarySearchTree/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.BinarySearchTree; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - 7B1BFA091C678D630051C9A4 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = BinarySearchTreeTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.BinarySearchTreeTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/BinarySearchTree.app/Contents/MacOS/BinarySearchTree"; - }; - name = Debug; - }; - 7B1BFA0A1C678D630051C9A4 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = BinarySearchTreeTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.BinarySearchTreeTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/BinarySearchTree.app/Contents/MacOS/BinarySearchTree"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 7B1BF9E81C678D630051C9A4 /* Build configuration list for PBXProject "BinarySearchTree" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 7B1BFA031C678D630051C9A4 /* Debug */, - 7B1BFA041C678D630051C9A4 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 7B1BFA051C678D630051C9A4 /* Build configuration list for PBXNativeTarget "BinarySearchTree" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 7B1BFA061C678D630051C9A4 /* Debug */, - 7B1BFA071C678D630051C9A4 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 7B1BFA081C678D630051C9A4 /* Build configuration list for PBXNativeTarget "BinarySearchTreeTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 7B1BFA091C678D630051C9A4 /* Debug */, - 7B1BFA0A1C678D630051C9A4 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 7B1BF9E51C678D630051C9A4 /* Project object */; -} diff --git a/Binary Search Tree/Solution 1/BinarySearchTree Tests/BinarySearchTree/AppDelegate.swift b/Binary Search Tree/Solution 1/BinarySearchTree Tests/BinarySearchTree/AppDelegate.swift deleted file mode 100644 index d80dd0269..000000000 --- a/Binary Search Tree/Solution 1/BinarySearchTree Tests/BinarySearchTree/AppDelegate.swift +++ /dev/null @@ -1,27 +0,0 @@ -// -// AppDelegate.swift -// BinarySearchTree -// -// Created by Matthijs Hollemans on 07-02-16. -// Copyright © 2016 Swift Algorithm Club. All rights reserved. -// - -import Cocoa - -@NSApplicationMain -class AppDelegate: NSObject, NSApplicationDelegate { - - @IBOutlet weak var window: NSWindow! - - - func applicationDidFinishLaunching(aNotification: NSNotification) { - // Insert code here to initialize your application - } - - func applicationWillTerminate(aNotification: NSNotification) { - // Insert code here to tear down your application - } - - -} - diff --git a/Binary Search Tree/Solution 1/BinarySearchTree Tests/BinarySearchTree/Assets.xcassets/AppIcon.appiconset/Contents.json b/Binary Search Tree/Solution 1/BinarySearchTree Tests/BinarySearchTree/Assets.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index 2db2b1c7c..000000000 --- a/Binary Search Tree/Solution 1/BinarySearchTree Tests/BinarySearchTree/Assets.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "images" : [ - { - "idiom" : "mac", - "size" : "16x16", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "16x16", - "scale" : "2x" - }, - { - "idiom" : "mac", - "size" : "32x32", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "32x32", - "scale" : "2x" - }, - { - "idiom" : "mac", - "size" : "128x128", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "128x128", - "scale" : "2x" - }, - { - "idiom" : "mac", - "size" : "256x256", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "256x256", - "scale" : "2x" - }, - { - "idiom" : "mac", - "size" : "512x512", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "512x512", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/Binary Search Tree/Solution 1/BinarySearchTree Tests/BinarySearchTree/Base.lproj/MainMenu.xib b/Binary Search Tree/Solution 1/BinarySearchTree Tests/BinarySearchTree/Base.lproj/MainMenu.xib deleted file mode 100644 index f7be413dc..000000000 --- a/Binary Search Tree/Solution 1/BinarySearchTree Tests/BinarySearchTree/Base.lproj/MainMenu.xib +++ /dev/null @@ -1,680 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Default - - - - - - - Left to Right - - - - - - - Right to Left - - - - - - - - - - - Default - - - - - - - Left to Right - - - - - - - Right to Left - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Binary Search Tree/Solution 1/BinarySearchTree Tests/BinarySearchTree/Info.plist b/Binary Search Tree/Solution 1/BinarySearchTree Tests/BinarySearchTree/Info.plist deleted file mode 100644 index 0dca3caa8..000000000 --- a/Binary Search Tree/Solution 1/BinarySearchTree Tests/BinarySearchTree/Info.plist +++ /dev/null @@ -1,34 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIconFile - - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - LSMinimumSystemVersion - $(MACOSX_DEPLOYMENT_TARGET) - NSHumanReadableCopyright - Copyright © 2016 Swift Algorithm Club. All rights reserved. - NSMainNibFile - MainMenu - NSPrincipalClass - NSApplication - - diff --git a/Binary Search Tree/Solution 1/BinarySearchTree Tests/BinarySearchTreeTests/BinarySearchTreeTests.swift b/Binary Search Tree/Solution 1/Tests/BinarySearchTreeTests.swift similarity index 99% rename from Binary Search Tree/Solution 1/BinarySearchTree Tests/BinarySearchTreeTests/BinarySearchTreeTests.swift rename to Binary Search Tree/Solution 1/Tests/BinarySearchTreeTests.swift index a23c3de5f..bafcd8003 100755 --- a/Binary Search Tree/Solution 1/BinarySearchTree Tests/BinarySearchTreeTests/BinarySearchTreeTests.swift +++ b/Binary Search Tree/Solution 1/Tests/BinarySearchTreeTests.swift @@ -1,6 +1,5 @@ import Foundation import XCTest -@testable import BinarySearchTree class BinarySearchTreeTest: XCTestCase { func testRootNode() { diff --git a/Binary Search Tree/Solution 1/BinarySearchTree Tests/BinarySearchTreeTests/Info.plist b/Binary Search Tree/Solution 1/Tests/Info.plist similarity index 100% rename from Binary Search Tree/Solution 1/BinarySearchTree Tests/BinarySearchTreeTests/Info.plist rename to Binary Search Tree/Solution 1/Tests/Info.plist diff --git a/Binary Search Tree/Solution 1/Tests/Tests.xcodeproj/project.pbxproj b/Binary Search Tree/Solution 1/Tests/Tests.xcodeproj/project.pbxproj new file mode 100644 index 000000000..c1d6c8029 --- /dev/null +++ b/Binary Search Tree/Solution 1/Tests/Tests.xcodeproj/project.pbxproj @@ -0,0 +1,261 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 7B80C3D81C77A313003CECC7 /* BinarySearchTree.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C3D71C77A313003CECC7 /* BinarySearchTree.swift */; }; + 7B80C3DA1C77A323003CECC7 /* BinarySearchTreeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C3D91C77A323003CECC7 /* BinarySearchTreeTests.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 7B2BBC801C779D720067B71D /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 7B2BBC941C779E7B0067B71D /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; + 7B80C3D71C77A313003CECC7 /* BinarySearchTree.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BinarySearchTree.swift; path = ../BinarySearchTree.swift; sourceTree = SOURCE_ROOT; }; + 7B80C3D91C77A323003CECC7 /* BinarySearchTreeTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BinarySearchTreeTests.swift; sourceTree = SOURCE_ROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 7B2BBC7D1C779D720067B71D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 7B2BBC681C779D710067B71D = { + isa = PBXGroup; + children = ( + 7B2BBC831C779D720067B71D /* Tests */, + 7B2BBC721C779D710067B71D /* Products */, + ); + sourceTree = ""; + }; + 7B2BBC721C779D710067B71D /* Products */ = { + isa = PBXGroup; + children = ( + 7B2BBC801C779D720067B71D /* Tests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 7B2BBC831C779D720067B71D /* Tests */ = { + isa = PBXGroup; + children = ( + 7B80C3D71C77A313003CECC7 /* BinarySearchTree.swift */, + 7B80C3D91C77A323003CECC7 /* BinarySearchTreeTests.swift */, + 7B2BBC941C779E7B0067B71D /* Info.plist */, + ); + name = Tests; + path = TestsTests; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 7B2BBC7F1C779D720067B71D /* Tests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */; + buildPhases = ( + 7B2BBC7C1C779D720067B71D /* Sources */, + 7B2BBC7D1C779D720067B71D /* Frameworks */, + 7B2BBC7E1C779D720067B71D /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Tests; + productName = TestsTests; + productReference = 7B2BBC801C779D720067B71D /* Tests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 7B2BBC691C779D710067B71D /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0720; + LastUpgradeCheck = 0720; + ORGANIZATIONNAME = "Swift Algorithm Club"; + TargetAttributes = { + 7B2BBC7F1C779D720067B71D = { + CreatedOnToolsVersion = 7.2; + }; + }; + }; + buildConfigurationList = 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 7B2BBC681C779D710067B71D; + productRefGroup = 7B2BBC721C779D710067B71D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 7B2BBC7F1C779D720067B71D /* Tests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 7B2BBC7E1C779D720067B71D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 7B2BBC7C1C779D720067B71D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 7B80C3DA1C77A323003CECC7 /* BinarySearchTreeTests.swift in Sources */, + 7B80C3D81C77A313003CECC7 /* BinarySearchTree.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 7B2BBC871C779D720067B71D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 7B2BBC881C779D720067B71D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + }; + name = Release; + }; + 7B2BBC8D1C779D720067B71D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 7B2BBC8E1C779D720067B71D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7B2BBC871C779D720067B71D /* Debug */, + 7B2BBC881C779D720067B71D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7B2BBC8D1C779D720067B71D /* Debug */, + 7B2BBC8E1C779D720067B71D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 7B2BBC691C779D710067B71D /* Project object */; +} diff --git a/Binary Search/BinarySearch Tests/BinarySearch.xcodeproj/project.pbxproj b/Binary Search/BinarySearch Tests/BinarySearch.xcodeproj/project.pbxproj deleted file mode 100644 index b5493845f..000000000 --- a/Binary Search/BinarySearch Tests/BinarySearch.xcodeproj/project.pbxproj +++ /dev/null @@ -1,394 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 7B18DFF11C5BF66F005A2B8E /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B18DFF01C5BF66F005A2B8E /* AppDelegate.swift */; }; - 7B18DFF31C5BF66F005A2B8E /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7B18DFF21C5BF66F005A2B8E /* Assets.xcassets */; }; - 7B18DFF61C5BF66F005A2B8E /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7B18DFF41C5BF66F005A2B8E /* MainMenu.xib */; }; - 7B18E0011C5BF66F005A2B8E /* BinarySearchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B18E0001C5BF66F005A2B8E /* BinarySearchTests.swift */; }; - 7B18E00C1C5BF6B2005A2B8E /* BinarySearch.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B18E00B1C5BF6B2005A2B8E /* BinarySearch.swift */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 7B18DFFD1C5BF66F005A2B8E /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 7B18DFE51C5BF66F005A2B8E /* Project object */; - proxyType = 1; - remoteGlobalIDString = 7B18DFEC1C5BF66F005A2B8E; - remoteInfo = BinarySearch; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXFileReference section */ - 7B18DFED1C5BF66F005A2B8E /* BinarySearch.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = BinarySearch.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 7B18DFF01C5BF66F005A2B8E /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 7B18DFF21C5BF66F005A2B8E /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - 7B18DFF51C5BF66F005A2B8E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; - 7B18DFF71C5BF66F005A2B8E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 7B18DFFC1C5BF66F005A2B8E /* BinarySearchTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = BinarySearchTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 7B18E0001C5BF66F005A2B8E /* BinarySearchTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BinarySearchTests.swift; sourceTree = ""; }; - 7B18E0021C5BF66F005A2B8E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 7B18E00B1C5BF6B2005A2B8E /* BinarySearch.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BinarySearch.swift; path = ../../BinarySearch.swift; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 7B18DFEA1C5BF66F005A2B8E /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 7B18DFF91C5BF66F005A2B8E /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 7B18DFE41C5BF66F005A2B8E = { - isa = PBXGroup; - children = ( - 7B18DFEF1C5BF66F005A2B8E /* BinarySearch */, - 7B18DFFF1C5BF66F005A2B8E /* BinarySearchTests */, - 7B18DFEE1C5BF66F005A2B8E /* Products */, - ); - sourceTree = ""; - }; - 7B18DFEE1C5BF66F005A2B8E /* Products */ = { - isa = PBXGroup; - children = ( - 7B18DFED1C5BF66F005A2B8E /* BinarySearch.app */, - 7B18DFFC1C5BF66F005A2B8E /* BinarySearchTests.xctest */, - ); - name = Products; - sourceTree = ""; - }; - 7B18DFEF1C5BF66F005A2B8E /* BinarySearch */ = { - isa = PBXGroup; - children = ( - 7B18DFF01C5BF66F005A2B8E /* AppDelegate.swift */, - 7B18DFF21C5BF66F005A2B8E /* Assets.xcassets */, - 7B18E00B1C5BF6B2005A2B8E /* BinarySearch.swift */, - 7B18DFF71C5BF66F005A2B8E /* Info.plist */, - 7B18DFF41C5BF66F005A2B8E /* MainMenu.xib */, - ); - path = BinarySearch; - sourceTree = ""; - }; - 7B18DFFF1C5BF66F005A2B8E /* BinarySearchTests */ = { - isa = PBXGroup; - children = ( - 7B18E0001C5BF66F005A2B8E /* BinarySearchTests.swift */, - 7B18E0021C5BF66F005A2B8E /* Info.plist */, - ); - path = BinarySearchTests; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 7B18DFEC1C5BF66F005A2B8E /* BinarySearch */ = { - isa = PBXNativeTarget; - buildConfigurationList = 7B18E0051C5BF66F005A2B8E /* Build configuration list for PBXNativeTarget "BinarySearch" */; - buildPhases = ( - 7B18DFE91C5BF66F005A2B8E /* Sources */, - 7B18DFEA1C5BF66F005A2B8E /* Frameworks */, - 7B18DFEB1C5BF66F005A2B8E /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = BinarySearch; - productName = BinarySearch; - productReference = 7B18DFED1C5BF66F005A2B8E /* BinarySearch.app */; - productType = "com.apple.product-type.application"; - }; - 7B18DFFB1C5BF66F005A2B8E /* BinarySearchTests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 7B18E0081C5BF66F005A2B8E /* Build configuration list for PBXNativeTarget "BinarySearchTests" */; - buildPhases = ( - 7B18DFF81C5BF66F005A2B8E /* Sources */, - 7B18DFF91C5BF66F005A2B8E /* Frameworks */, - 7B18DFFA1C5BF66F005A2B8E /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - 7B18DFFE1C5BF66F005A2B8E /* PBXTargetDependency */, - ); - name = BinarySearchTests; - productName = BinarySearchTests; - productReference = 7B18DFFC1C5BF66F005A2B8E /* BinarySearchTests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 7B18DFE51C5BF66F005A2B8E /* Project object */ = { - isa = PBXProject; - attributes = { - LastSwiftUpdateCheck = 0720; - LastUpgradeCheck = 0720; - ORGANIZATIONNAME = "Swift Algorithm Club"; - TargetAttributes = { - 7B18DFEC1C5BF66F005A2B8E = { - CreatedOnToolsVersion = 7.2; - }; - 7B18DFFB1C5BF66F005A2B8E = { - CreatedOnToolsVersion = 7.2; - TestTargetID = 7B18DFEC1C5BF66F005A2B8E; - }; - }; - }; - buildConfigurationList = 7B18DFE81C5BF66F005A2B8E /* Build configuration list for PBXProject "BinarySearch" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 7B18DFE41C5BF66F005A2B8E; - productRefGroup = 7B18DFEE1C5BF66F005A2B8E /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 7B18DFEC1C5BF66F005A2B8E /* BinarySearch */, - 7B18DFFB1C5BF66F005A2B8E /* BinarySearchTests */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 7B18DFEB1C5BF66F005A2B8E /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 7B18DFF31C5BF66F005A2B8E /* Assets.xcassets in Resources */, - 7B18DFF61C5BF66F005A2B8E /* MainMenu.xib in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 7B18DFFA1C5BF66F005A2B8E /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 7B18DFE91C5BF66F005A2B8E /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 7B18E00C1C5BF6B2005A2B8E /* BinarySearch.swift in Sources */, - 7B18DFF11C5BF66F005A2B8E /* AppDelegate.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 7B18DFF81C5BF66F005A2B8E /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 7B18E0011C5BF66F005A2B8E /* BinarySearchTests.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 7B18DFFE1C5BF66F005A2B8E /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 7B18DFEC1C5BF66F005A2B8E /* BinarySearch */; - targetProxy = 7B18DFFD1C5BF66F005A2B8E /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin PBXVariantGroup section */ - 7B18DFF41C5BF66F005A2B8E /* MainMenu.xib */ = { - isa = PBXVariantGroup; - children = ( - 7B18DFF51C5BF66F005A2B8E /* Base */, - ); - name = MainMenu.xib; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 7B18E0031C5BF66F005A2B8E /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "-"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.11; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = macosx; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - }; - name = Debug; - }; - 7B18E0041C5BF66F005A2B8E /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "-"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.11; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = macosx; - }; - name = Release; - }; - 7B18E0061C5BF66F005A2B8E /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = BinarySearch/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.BinarySearch; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 7B18E0071C5BF66F005A2B8E /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = BinarySearch/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.BinarySearch; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - 7B18E0091C5BF66F005A2B8E /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = BinarySearchTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.BinarySearchTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/BinarySearch.app/Contents/MacOS/BinarySearch"; - }; - name = Debug; - }; - 7B18E00A1C5BF66F005A2B8E /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = BinarySearchTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.BinarySearchTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/BinarySearch.app/Contents/MacOS/BinarySearch"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 7B18DFE81C5BF66F005A2B8E /* Build configuration list for PBXProject "BinarySearch" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 7B18E0031C5BF66F005A2B8E /* Debug */, - 7B18E0041C5BF66F005A2B8E /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 7B18E0051C5BF66F005A2B8E /* Build configuration list for PBXNativeTarget "BinarySearch" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 7B18E0061C5BF66F005A2B8E /* Debug */, - 7B18E0071C5BF66F005A2B8E /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 7B18E0081C5BF66F005A2B8E /* Build configuration list for PBXNativeTarget "BinarySearchTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 7B18E0091C5BF66F005A2B8E /* Debug */, - 7B18E00A1C5BF66F005A2B8E /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 7B18DFE51C5BF66F005A2B8E /* Project object */; -} diff --git a/Binary Search/BinarySearch Tests/BinarySearch/AppDelegate.swift b/Binary Search/BinarySearch Tests/BinarySearch/AppDelegate.swift deleted file mode 100644 index f3db7bc62..000000000 --- a/Binary Search/BinarySearch Tests/BinarySearch/AppDelegate.swift +++ /dev/null @@ -1,27 +0,0 @@ -// -// AppDelegate.swift -// BinarySearch -// -// Created by Matthijs Hollemans on 29-01-16. -// Copyright © 2016 Swift Algorithm Club. All rights reserved. -// - -import Cocoa - -@NSApplicationMain -class AppDelegate: NSObject, NSApplicationDelegate { - - @IBOutlet weak var window: NSWindow! - - - func applicationDidFinishLaunching(aNotification: NSNotification) { - // Insert code here to initialize your application - } - - func applicationWillTerminate(aNotification: NSNotification) { - // Insert code here to tear down your application - } - - -} - diff --git a/Binary Search/BinarySearch Tests/BinarySearch/Assets.xcassets/AppIcon.appiconset/Contents.json b/Binary Search/BinarySearch Tests/BinarySearch/Assets.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index 2db2b1c7c..000000000 --- a/Binary Search/BinarySearch Tests/BinarySearch/Assets.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "images" : [ - { - "idiom" : "mac", - "size" : "16x16", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "16x16", - "scale" : "2x" - }, - { - "idiom" : "mac", - "size" : "32x32", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "32x32", - "scale" : "2x" - }, - { - "idiom" : "mac", - "size" : "128x128", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "128x128", - "scale" : "2x" - }, - { - "idiom" : "mac", - "size" : "256x256", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "256x256", - "scale" : "2x" - }, - { - "idiom" : "mac", - "size" : "512x512", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "512x512", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/Binary Search/BinarySearch Tests/BinarySearch/Base.lproj/MainMenu.xib b/Binary Search/BinarySearch Tests/BinarySearch/Base.lproj/MainMenu.xib deleted file mode 100644 index ee7982efd..000000000 --- a/Binary Search/BinarySearch Tests/BinarySearch/Base.lproj/MainMenu.xib +++ /dev/null @@ -1,680 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Default - - - - - - - Left to Right - - - - - - - Right to Left - - - - - - - - - - - Default - - - - - - - Left to Right - - - - - - - Right to Left - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Binary Search/BinarySearch Tests/BinarySearch/Info.plist b/Binary Search/BinarySearch Tests/BinarySearch/Info.plist deleted file mode 100644 index 0dca3caa8..000000000 --- a/Binary Search/BinarySearch Tests/BinarySearch/Info.plist +++ /dev/null @@ -1,34 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIconFile - - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - LSMinimumSystemVersion - $(MACOSX_DEPLOYMENT_TARGET) - NSHumanReadableCopyright - Copyright © 2016 Swift Algorithm Club. All rights reserved. - NSMainNibFile - MainMenu - NSPrincipalClass - NSApplication - - diff --git a/Binary Search/BinarySearch Tests/BinarySearchTests/BinarySearchTests.swift b/Binary Search/Tests/BinarySearchTests.swift similarity index 97% rename from Binary Search/BinarySearch Tests/BinarySearchTests/BinarySearchTests.swift rename to Binary Search/Tests/BinarySearchTests.swift index d626e475d..35ad9559b 100755 --- a/Binary Search/BinarySearch Tests/BinarySearchTests/BinarySearchTests.swift +++ b/Binary Search/Tests/BinarySearchTests.swift @@ -1,6 +1,5 @@ import Foundation import XCTest -@testable import BinarySearch class BinarySearchTest: XCTestCase { var searchList = [Int]() diff --git a/Binary Search/BinarySearch Tests/BinarySearchTests/Info.plist b/Binary Search/Tests/Info.plist similarity index 100% rename from Binary Search/BinarySearch Tests/BinarySearchTests/Info.plist rename to Binary Search/Tests/Info.plist diff --git a/Binary Search/Tests/Tests.xcodeproj/project.pbxproj b/Binary Search/Tests/Tests.xcodeproj/project.pbxproj new file mode 100644 index 000000000..9ed1ab1a8 --- /dev/null +++ b/Binary Search/Tests/Tests.xcodeproj/project.pbxproj @@ -0,0 +1,261 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 7B80C3CE1C77A256003CECC7 /* BinarySearchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C3CD1C77A256003CECC7 /* BinarySearchTests.swift */; }; + 7B80C3D01C77A263003CECC7 /* BinarySearch.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C3CF1C77A263003CECC7 /* BinarySearch.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 7B2BBC801C779D720067B71D /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 7B2BBC941C779E7B0067B71D /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; + 7B80C3CD1C77A256003CECC7 /* BinarySearchTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BinarySearchTests.swift; sourceTree = SOURCE_ROOT; }; + 7B80C3CF1C77A263003CECC7 /* BinarySearch.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BinarySearch.swift; path = ../BinarySearch.swift; sourceTree = SOURCE_ROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 7B2BBC7D1C779D720067B71D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 7B2BBC681C779D710067B71D = { + isa = PBXGroup; + children = ( + 7B2BBC831C779D720067B71D /* Tests */, + 7B2BBC721C779D710067B71D /* Products */, + ); + sourceTree = ""; + }; + 7B2BBC721C779D710067B71D /* Products */ = { + isa = PBXGroup; + children = ( + 7B2BBC801C779D720067B71D /* Tests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 7B2BBC831C779D720067B71D /* Tests */ = { + isa = PBXGroup; + children = ( + 7B80C3CF1C77A263003CECC7 /* BinarySearch.swift */, + 7B80C3CD1C77A256003CECC7 /* BinarySearchTests.swift */, + 7B2BBC941C779E7B0067B71D /* Info.plist */, + ); + name = Tests; + path = TestsTests; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 7B2BBC7F1C779D720067B71D /* Tests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */; + buildPhases = ( + 7B2BBC7C1C779D720067B71D /* Sources */, + 7B2BBC7D1C779D720067B71D /* Frameworks */, + 7B2BBC7E1C779D720067B71D /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Tests; + productName = TestsTests; + productReference = 7B2BBC801C779D720067B71D /* Tests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 7B2BBC691C779D710067B71D /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0720; + LastUpgradeCheck = 0720; + ORGANIZATIONNAME = "Swift Algorithm Club"; + TargetAttributes = { + 7B2BBC7F1C779D720067B71D = { + CreatedOnToolsVersion = 7.2; + }; + }; + }; + buildConfigurationList = 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 7B2BBC681C779D710067B71D; + productRefGroup = 7B2BBC721C779D710067B71D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 7B2BBC7F1C779D720067B71D /* Tests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 7B2BBC7E1C779D720067B71D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 7B2BBC7C1C779D720067B71D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 7B80C3D01C77A263003CECC7 /* BinarySearch.swift in Sources */, + 7B80C3CE1C77A256003CECC7 /* BinarySearchTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 7B2BBC871C779D720067B71D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 7B2BBC881C779D720067B71D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + }; + name = Release; + }; + 7B2BBC8D1C779D720067B71D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 7B2BBC8E1C779D720067B71D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7B2BBC871C779D720067B71D /* Debug */, + 7B2BBC881C779D720067B71D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7B2BBC8D1C779D720067B71D /* Debug */, + 7B2BBC8E1C779D720067B71D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 7B2BBC691C779D710067B71D /* Project object */; +} diff --git a/Heap Sort/HeapSort Tests/HeapSort.xcodeproj/project.pbxproj b/Heap Sort/HeapSort Tests/HeapSort.xcodeproj/project.pbxproj deleted file mode 100644 index f6da3b7db..000000000 --- a/Heap Sort/HeapSort Tests/HeapSort.xcodeproj/project.pbxproj +++ /dev/null @@ -1,398 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 7B1BFA451C69158D0051C9A4 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B1BFA441C69158D0051C9A4 /* AppDelegate.swift */; }; - 7B1BFA471C69158D0051C9A4 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7B1BFA461C69158D0051C9A4 /* Assets.xcassets */; }; - 7B1BFA4A1C69158D0051C9A4 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7B1BFA481C69158D0051C9A4 /* MainMenu.xib */; }; - 7B1BFA551C69158D0051C9A4 /* HeapSortTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B1BFA541C69158D0051C9A4 /* HeapSortTests.swift */; }; - 7B1BFA601C69159D0051C9A4 /* HeapSort.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B1BFA5F1C69159D0051C9A4 /* HeapSort.swift */; }; - 7B1BFA621C6915A70051C9A4 /* Heap.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B1BFA611C6915A70051C9A4 /* Heap.swift */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 7B1BFA511C69158D0051C9A4 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 7B1BFA391C69158D0051C9A4 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 7B1BFA401C69158D0051C9A4; - remoteInfo = HeapSort; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXFileReference section */ - 7B1BFA411C69158D0051C9A4 /* HeapSort.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = HeapSort.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 7B1BFA441C69158D0051C9A4 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 7B1BFA461C69158D0051C9A4 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - 7B1BFA491C69158D0051C9A4 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; - 7B1BFA4B1C69158D0051C9A4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 7B1BFA501C69158D0051C9A4 /* HeapSortTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = HeapSortTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 7B1BFA541C69158D0051C9A4 /* HeapSortTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeapSortTests.swift; sourceTree = ""; }; - 7B1BFA561C69158D0051C9A4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 7B1BFA5F1C69159D0051C9A4 /* HeapSort.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = HeapSort.swift; path = ../../HeapSort.swift; sourceTree = ""; }; - 7B1BFA611C6915A70051C9A4 /* Heap.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Heap.swift; path = ../../../Heap/Heap.swift; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 7B1BFA3E1C69158D0051C9A4 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 7B1BFA4D1C69158D0051C9A4 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 7B1BFA381C69158D0051C9A4 = { - isa = PBXGroup; - children = ( - 7B1BFA431C69158D0051C9A4 /* HeapSort */, - 7B1BFA531C69158D0051C9A4 /* HeapSortTests */, - 7B1BFA421C69158D0051C9A4 /* Products */, - ); - sourceTree = ""; - }; - 7B1BFA421C69158D0051C9A4 /* Products */ = { - isa = PBXGroup; - children = ( - 7B1BFA411C69158D0051C9A4 /* HeapSort.app */, - 7B1BFA501C69158D0051C9A4 /* HeapSortTests.xctest */, - ); - name = Products; - sourceTree = ""; - }; - 7B1BFA431C69158D0051C9A4 /* HeapSort */ = { - isa = PBXGroup; - children = ( - 7B1BFA441C69158D0051C9A4 /* AppDelegate.swift */, - 7B1BFA461C69158D0051C9A4 /* Assets.xcassets */, - 7B1BFA611C6915A70051C9A4 /* Heap.swift */, - 7B1BFA5F1C69159D0051C9A4 /* HeapSort.swift */, - 7B1BFA4B1C69158D0051C9A4 /* Info.plist */, - 7B1BFA481C69158D0051C9A4 /* MainMenu.xib */, - ); - path = HeapSort; - sourceTree = ""; - }; - 7B1BFA531C69158D0051C9A4 /* HeapSortTests */ = { - isa = PBXGroup; - children = ( - 7B1BFA541C69158D0051C9A4 /* HeapSortTests.swift */, - 7B1BFA561C69158D0051C9A4 /* Info.plist */, - ); - path = HeapSortTests; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 7B1BFA401C69158D0051C9A4 /* HeapSort */ = { - isa = PBXNativeTarget; - buildConfigurationList = 7B1BFA591C69158D0051C9A4 /* Build configuration list for PBXNativeTarget "HeapSort" */; - buildPhases = ( - 7B1BFA3D1C69158D0051C9A4 /* Sources */, - 7B1BFA3E1C69158D0051C9A4 /* Frameworks */, - 7B1BFA3F1C69158D0051C9A4 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = HeapSort; - productName = HeapSort; - productReference = 7B1BFA411C69158D0051C9A4 /* HeapSort.app */; - productType = "com.apple.product-type.application"; - }; - 7B1BFA4F1C69158D0051C9A4 /* HeapSortTests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 7B1BFA5C1C69158D0051C9A4 /* Build configuration list for PBXNativeTarget "HeapSortTests" */; - buildPhases = ( - 7B1BFA4C1C69158D0051C9A4 /* Sources */, - 7B1BFA4D1C69158D0051C9A4 /* Frameworks */, - 7B1BFA4E1C69158D0051C9A4 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - 7B1BFA521C69158D0051C9A4 /* PBXTargetDependency */, - ); - name = HeapSortTests; - productName = HeapSortTests; - productReference = 7B1BFA501C69158D0051C9A4 /* HeapSortTests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 7B1BFA391C69158D0051C9A4 /* Project object */ = { - isa = PBXProject; - attributes = { - LastSwiftUpdateCheck = 0720; - LastUpgradeCheck = 0720; - ORGANIZATIONNAME = "Swift Algorithm Club"; - TargetAttributes = { - 7B1BFA401C69158D0051C9A4 = { - CreatedOnToolsVersion = 7.2; - }; - 7B1BFA4F1C69158D0051C9A4 = { - CreatedOnToolsVersion = 7.2; - TestTargetID = 7B1BFA401C69158D0051C9A4; - }; - }; - }; - buildConfigurationList = 7B1BFA3C1C69158D0051C9A4 /* Build configuration list for PBXProject "HeapSort" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 7B1BFA381C69158D0051C9A4; - productRefGroup = 7B1BFA421C69158D0051C9A4 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 7B1BFA401C69158D0051C9A4 /* HeapSort */, - 7B1BFA4F1C69158D0051C9A4 /* HeapSortTests */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 7B1BFA3F1C69158D0051C9A4 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 7B1BFA471C69158D0051C9A4 /* Assets.xcassets in Resources */, - 7B1BFA4A1C69158D0051C9A4 /* MainMenu.xib in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 7B1BFA4E1C69158D0051C9A4 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 7B1BFA3D1C69158D0051C9A4 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 7B1BFA621C6915A70051C9A4 /* Heap.swift in Sources */, - 7B1BFA451C69158D0051C9A4 /* AppDelegate.swift in Sources */, - 7B1BFA601C69159D0051C9A4 /* HeapSort.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 7B1BFA4C1C69158D0051C9A4 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 7B1BFA551C69158D0051C9A4 /* HeapSortTests.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 7B1BFA521C69158D0051C9A4 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 7B1BFA401C69158D0051C9A4 /* HeapSort */; - targetProxy = 7B1BFA511C69158D0051C9A4 /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin PBXVariantGroup section */ - 7B1BFA481C69158D0051C9A4 /* MainMenu.xib */ = { - isa = PBXVariantGroup; - children = ( - 7B1BFA491C69158D0051C9A4 /* Base */, - ); - name = MainMenu.xib; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 7B1BFA571C69158D0051C9A4 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "-"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.11; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = macosx; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - }; - name = Debug; - }; - 7B1BFA581C69158D0051C9A4 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "-"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.11; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = macosx; - }; - name = Release; - }; - 7B1BFA5A1C69158D0051C9A4 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = HeapSort/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.HeapSort; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 7B1BFA5B1C69158D0051C9A4 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = HeapSort/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.HeapSort; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - 7B1BFA5D1C69158D0051C9A4 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = HeapSortTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.HeapSortTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/HeapSort.app/Contents/MacOS/HeapSort"; - }; - name = Debug; - }; - 7B1BFA5E1C69158D0051C9A4 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = HeapSortTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.HeapSortTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/HeapSort.app/Contents/MacOS/HeapSort"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 7B1BFA3C1C69158D0051C9A4 /* Build configuration list for PBXProject "HeapSort" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 7B1BFA571C69158D0051C9A4 /* Debug */, - 7B1BFA581C69158D0051C9A4 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 7B1BFA591C69158D0051C9A4 /* Build configuration list for PBXNativeTarget "HeapSort" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 7B1BFA5A1C69158D0051C9A4 /* Debug */, - 7B1BFA5B1C69158D0051C9A4 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 7B1BFA5C1C69158D0051C9A4 /* Build configuration list for PBXNativeTarget "HeapSortTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 7B1BFA5D1C69158D0051C9A4 /* Debug */, - 7B1BFA5E1C69158D0051C9A4 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 7B1BFA391C69158D0051C9A4 /* Project object */; -} diff --git a/Heap Sort/HeapSort Tests/HeapSort/AppDelegate.swift b/Heap Sort/HeapSort Tests/HeapSort/AppDelegate.swift deleted file mode 100644 index 08b4b6f47..000000000 --- a/Heap Sort/HeapSort Tests/HeapSort/AppDelegate.swift +++ /dev/null @@ -1,27 +0,0 @@ -// -// AppDelegate.swift -// HeapSort -// -// Created by Matthijs Hollemans on 08-02-16. -// Copyright © 2016 Swift Algorithm Club. All rights reserved. -// - -import Cocoa - -@NSApplicationMain -class AppDelegate: NSObject, NSApplicationDelegate { - - @IBOutlet weak var window: NSWindow! - - - func applicationDidFinishLaunching(aNotification: NSNotification) { - // Insert code here to initialize your application - } - - func applicationWillTerminate(aNotification: NSNotification) { - // Insert code here to tear down your application - } - - -} - diff --git a/Heap Sort/HeapSort Tests/HeapSort/Assets.xcassets/AppIcon.appiconset/Contents.json b/Heap Sort/HeapSort Tests/HeapSort/Assets.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index 2db2b1c7c..000000000 --- a/Heap Sort/HeapSort Tests/HeapSort/Assets.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "images" : [ - { - "idiom" : "mac", - "size" : "16x16", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "16x16", - "scale" : "2x" - }, - { - "idiom" : "mac", - "size" : "32x32", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "32x32", - "scale" : "2x" - }, - { - "idiom" : "mac", - "size" : "128x128", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "128x128", - "scale" : "2x" - }, - { - "idiom" : "mac", - "size" : "256x256", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "256x256", - "scale" : "2x" - }, - { - "idiom" : "mac", - "size" : "512x512", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "512x512", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/Heap Sort/HeapSort Tests/HeapSort/Base.lproj/MainMenu.xib b/Heap Sort/HeapSort Tests/HeapSort/Base.lproj/MainMenu.xib deleted file mode 100644 index cb25f88b2..000000000 --- a/Heap Sort/HeapSort Tests/HeapSort/Base.lproj/MainMenu.xib +++ /dev/null @@ -1,680 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Default - - - - - - - Left to Right - - - - - - - Right to Left - - - - - - - - - - - Default - - - - - - - Left to Right - - - - - - - Right to Left - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Heap Sort/HeapSort Tests/HeapSort/Info.plist b/Heap Sort/HeapSort Tests/HeapSort/Info.plist deleted file mode 100644 index 0dca3caa8..000000000 --- a/Heap Sort/HeapSort Tests/HeapSort/Info.plist +++ /dev/null @@ -1,34 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIconFile - - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - LSMinimumSystemVersion - $(MACOSX_DEPLOYMENT_TARGET) - NSHumanReadableCopyright - Copyright © 2016 Swift Algorithm Club. All rights reserved. - NSMainNibFile - MainMenu - NSPrincipalClass - NSApplication - - diff --git a/Heap Sort/HeapSort Tests/HeapSortTests/HeapSortTests.swift b/Heap Sort/Tests/HeapSortTests.swift similarity index 81% rename from Heap Sort/HeapSort Tests/HeapSortTests/HeapSortTests.swift rename to Heap Sort/Tests/HeapSortTests.swift index 70304fea7..e5e847a74 100644 --- a/Heap Sort/HeapSort Tests/HeapSortTests/HeapSortTests.swift +++ b/Heap Sort/Tests/HeapSortTests.swift @@ -1,13 +1,4 @@ -// -// HeapSortTests.swift -// HeapSortTests -// -// Created by Matthijs Hollemans on 08-02-16. -// Copyright © 2016 Swift Algorithm Club. All rights reserved. -// - import XCTest -@testable import HeapSort class HeapSortTests: XCTestCase { func testSort() { diff --git a/Heap Sort/HeapSort Tests/HeapSortTests/Info.plist b/Heap Sort/Tests/Info.plist similarity index 100% rename from Heap Sort/HeapSort Tests/HeapSortTests/Info.plist rename to Heap Sort/Tests/Info.plist diff --git a/Heap Sort/Tests/Tests.xcodeproj/project.pbxproj b/Heap Sort/Tests/Tests.xcodeproj/project.pbxproj new file mode 100644 index 000000000..454222c49 --- /dev/null +++ b/Heap Sort/Tests/Tests.xcodeproj/project.pbxproj @@ -0,0 +1,265 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 7B80C3E01C77A3DB003CECC7 /* Heap.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C3DF1C77A3DB003CECC7 /* Heap.swift */; }; + 7B80C3E21C77A3E5003CECC7 /* HeapSort.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C3E11C77A3E5003CECC7 /* HeapSort.swift */; }; + 7B80C3E41C77A3EB003CECC7 /* HeapSortTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C3E31C77A3EB003CECC7 /* HeapSortTests.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 7B2BBC801C779D720067B71D /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 7B2BBC941C779E7B0067B71D /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; + 7B80C3DF1C77A3DB003CECC7 /* Heap.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Heap.swift; path = ../../Heap/Heap.swift; sourceTree = SOURCE_ROOT; }; + 7B80C3E11C77A3E5003CECC7 /* HeapSort.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = HeapSort.swift; path = ../HeapSort.swift; sourceTree = SOURCE_ROOT; }; + 7B80C3E31C77A3EB003CECC7 /* HeapSortTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HeapSortTests.swift; sourceTree = SOURCE_ROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 7B2BBC7D1C779D720067B71D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 7B2BBC681C779D710067B71D = { + isa = PBXGroup; + children = ( + 7B2BBC831C779D720067B71D /* Tests */, + 7B2BBC721C779D710067B71D /* Products */, + ); + sourceTree = ""; + }; + 7B2BBC721C779D710067B71D /* Products */ = { + isa = PBXGroup; + children = ( + 7B2BBC801C779D720067B71D /* Tests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 7B2BBC831C779D720067B71D /* Tests */ = { + isa = PBXGroup; + children = ( + 7B80C3DF1C77A3DB003CECC7 /* Heap.swift */, + 7B80C3E11C77A3E5003CECC7 /* HeapSort.swift */, + 7B80C3E31C77A3EB003CECC7 /* HeapSortTests.swift */, + 7B2BBC941C779E7B0067B71D /* Info.plist */, + ); + name = Tests; + path = TestsTests; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 7B2BBC7F1C779D720067B71D /* Tests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */; + buildPhases = ( + 7B2BBC7C1C779D720067B71D /* Sources */, + 7B2BBC7D1C779D720067B71D /* Frameworks */, + 7B2BBC7E1C779D720067B71D /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Tests; + productName = TestsTests; + productReference = 7B2BBC801C779D720067B71D /* Tests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 7B2BBC691C779D710067B71D /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0720; + LastUpgradeCheck = 0720; + ORGANIZATIONNAME = "Swift Algorithm Club"; + TargetAttributes = { + 7B2BBC7F1C779D720067B71D = { + CreatedOnToolsVersion = 7.2; + }; + }; + }; + buildConfigurationList = 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 7B2BBC681C779D710067B71D; + productRefGroup = 7B2BBC721C779D710067B71D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 7B2BBC7F1C779D720067B71D /* Tests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 7B2BBC7E1C779D720067B71D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 7B2BBC7C1C779D720067B71D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 7B80C3E01C77A3DB003CECC7 /* Heap.swift in Sources */, + 7B80C3E41C77A3EB003CECC7 /* HeapSortTests.swift in Sources */, + 7B80C3E21C77A3E5003CECC7 /* HeapSort.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 7B2BBC871C779D720067B71D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 7B2BBC881C779D720067B71D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + }; + name = Release; + }; + 7B2BBC8D1C779D720067B71D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 7B2BBC8E1C779D720067B71D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7B2BBC871C779D720067B71D /* Debug */, + 7B2BBC881C779D720067B71D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7B2BBC8D1C779D720067B71D /* Debug */, + 7B2BBC8E1C779D720067B71D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 7B2BBC691C779D710067B71D /* Project object */; +} diff --git a/Heap/Heap Tests/Heap.xcodeproj/project.pbxproj b/Heap/Heap Tests/Heap.xcodeproj/project.pbxproj deleted file mode 100644 index c0fd77f65..000000000 --- a/Heap/Heap Tests/Heap.xcodeproj/project.pbxproj +++ /dev/null @@ -1,394 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 7B18DF9F1C5BF41B005A2B8E /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B18DF9E1C5BF41B005A2B8E /* AppDelegate.swift */; }; - 7B18DFA11C5BF41B005A2B8E /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7B18DFA01C5BF41B005A2B8E /* Assets.xcassets */; }; - 7B18DFA41C5BF41B005A2B8E /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7B18DFA21C5BF41B005A2B8E /* MainMenu.xib */; }; - 7B18DFAF1C5BF41B005A2B8E /* HeapTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B18DFAE1C5BF41B005A2B8E /* HeapTests.swift */; }; - 7B18DFBA1C5BF465005A2B8E /* Heap.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B18DFB91C5BF465005A2B8E /* Heap.swift */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 7B18DFAB1C5BF41B005A2B8E /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 7B18DF931C5BF41B005A2B8E /* Project object */; - proxyType = 1; - remoteGlobalIDString = 7B18DF9A1C5BF41B005A2B8E; - remoteInfo = Heap; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXFileReference section */ - 7B18DF9B1C5BF41B005A2B8E /* Heap.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Heap.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 7B18DF9E1C5BF41B005A2B8E /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 7B18DFA01C5BF41B005A2B8E /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - 7B18DFA31C5BF41B005A2B8E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; - 7B18DFA51C5BF41B005A2B8E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 7B18DFAA1C5BF41B005A2B8E /* HeapTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = HeapTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 7B18DFAE1C5BF41B005A2B8E /* HeapTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeapTests.swift; sourceTree = ""; }; - 7B18DFB01C5BF41B005A2B8E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 7B18DFB91C5BF465005A2B8E /* Heap.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Heap.swift; path = ../../Heap.swift; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 7B18DF981C5BF41B005A2B8E /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 7B18DFA71C5BF41B005A2B8E /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 7B18DF921C5BF41B005A2B8E = { - isa = PBXGroup; - children = ( - 7B18DF9D1C5BF41B005A2B8E /* Heap */, - 7B18DFAD1C5BF41B005A2B8E /* HeapTests */, - 7B18DF9C1C5BF41B005A2B8E /* Products */, - ); - sourceTree = ""; - }; - 7B18DF9C1C5BF41B005A2B8E /* Products */ = { - isa = PBXGroup; - children = ( - 7B18DF9B1C5BF41B005A2B8E /* Heap.app */, - 7B18DFAA1C5BF41B005A2B8E /* HeapTests.xctest */, - ); - name = Products; - sourceTree = ""; - }; - 7B18DF9D1C5BF41B005A2B8E /* Heap */ = { - isa = PBXGroup; - children = ( - 7B18DF9E1C5BF41B005A2B8E /* AppDelegate.swift */, - 7B18DFA01C5BF41B005A2B8E /* Assets.xcassets */, - 7B18DFB91C5BF465005A2B8E /* Heap.swift */, - 7B18DFA51C5BF41B005A2B8E /* Info.plist */, - 7B18DFA21C5BF41B005A2B8E /* MainMenu.xib */, - ); - path = Heap; - sourceTree = ""; - }; - 7B18DFAD1C5BF41B005A2B8E /* HeapTests */ = { - isa = PBXGroup; - children = ( - 7B18DFAE1C5BF41B005A2B8E /* HeapTests.swift */, - 7B18DFB01C5BF41B005A2B8E /* Info.plist */, - ); - path = HeapTests; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 7B18DF9A1C5BF41B005A2B8E /* Heap */ = { - isa = PBXNativeTarget; - buildConfigurationList = 7B18DFB31C5BF41B005A2B8E /* Build configuration list for PBXNativeTarget "Heap" */; - buildPhases = ( - 7B18DF971C5BF41B005A2B8E /* Sources */, - 7B18DF981C5BF41B005A2B8E /* Frameworks */, - 7B18DF991C5BF41B005A2B8E /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = Heap; - productName = Heap; - productReference = 7B18DF9B1C5BF41B005A2B8E /* Heap.app */; - productType = "com.apple.product-type.application"; - }; - 7B18DFA91C5BF41B005A2B8E /* HeapTests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 7B18DFB61C5BF41B005A2B8E /* Build configuration list for PBXNativeTarget "HeapTests" */; - buildPhases = ( - 7B18DFA61C5BF41B005A2B8E /* Sources */, - 7B18DFA71C5BF41B005A2B8E /* Frameworks */, - 7B18DFA81C5BF41B005A2B8E /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - 7B18DFAC1C5BF41B005A2B8E /* PBXTargetDependency */, - ); - name = HeapTests; - productName = HeapTests; - productReference = 7B18DFAA1C5BF41B005A2B8E /* HeapTests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 7B18DF931C5BF41B005A2B8E /* Project object */ = { - isa = PBXProject; - attributes = { - LastSwiftUpdateCheck = 0720; - LastUpgradeCheck = 0720; - ORGANIZATIONNAME = "Swift Algorithm Club"; - TargetAttributes = { - 7B18DF9A1C5BF41B005A2B8E = { - CreatedOnToolsVersion = 7.2; - }; - 7B18DFA91C5BF41B005A2B8E = { - CreatedOnToolsVersion = 7.2; - TestTargetID = 7B18DF9A1C5BF41B005A2B8E; - }; - }; - }; - buildConfigurationList = 7B18DF961C5BF41B005A2B8E /* Build configuration list for PBXProject "Heap" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 7B18DF921C5BF41B005A2B8E; - productRefGroup = 7B18DF9C1C5BF41B005A2B8E /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 7B18DF9A1C5BF41B005A2B8E /* Heap */, - 7B18DFA91C5BF41B005A2B8E /* HeapTests */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 7B18DF991C5BF41B005A2B8E /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 7B18DFA11C5BF41B005A2B8E /* Assets.xcassets in Resources */, - 7B18DFA41C5BF41B005A2B8E /* MainMenu.xib in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 7B18DFA81C5BF41B005A2B8E /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 7B18DF971C5BF41B005A2B8E /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 7B18DF9F1C5BF41B005A2B8E /* AppDelegate.swift in Sources */, - 7B18DFBA1C5BF465005A2B8E /* Heap.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 7B18DFA61C5BF41B005A2B8E /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 7B18DFAF1C5BF41B005A2B8E /* HeapTests.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 7B18DFAC1C5BF41B005A2B8E /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 7B18DF9A1C5BF41B005A2B8E /* Heap */; - targetProxy = 7B18DFAB1C5BF41B005A2B8E /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin PBXVariantGroup section */ - 7B18DFA21C5BF41B005A2B8E /* MainMenu.xib */ = { - isa = PBXVariantGroup; - children = ( - 7B18DFA31C5BF41B005A2B8E /* Base */, - ); - name = MainMenu.xib; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 7B18DFB11C5BF41B005A2B8E /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "-"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.11; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = macosx; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - }; - name = Debug; - }; - 7B18DFB21C5BF41B005A2B8E /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "-"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.11; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = macosx; - }; - name = Release; - }; - 7B18DFB41C5BF41B005A2B8E /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = Heap/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Heap; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 7B18DFB51C5BF41B005A2B8E /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = Heap/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Heap; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - 7B18DFB71C5BF41B005A2B8E /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = HeapTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.HeapTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Heap.app/Contents/MacOS/Heap"; - }; - name = Debug; - }; - 7B18DFB81C5BF41B005A2B8E /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = HeapTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.HeapTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Heap.app/Contents/MacOS/Heap"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 7B18DF961C5BF41B005A2B8E /* Build configuration list for PBXProject "Heap" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 7B18DFB11C5BF41B005A2B8E /* Debug */, - 7B18DFB21C5BF41B005A2B8E /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 7B18DFB31C5BF41B005A2B8E /* Build configuration list for PBXNativeTarget "Heap" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 7B18DFB41C5BF41B005A2B8E /* Debug */, - 7B18DFB51C5BF41B005A2B8E /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 7B18DFB61C5BF41B005A2B8E /* Build configuration list for PBXNativeTarget "HeapTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 7B18DFB71C5BF41B005A2B8E /* Debug */, - 7B18DFB81C5BF41B005A2B8E /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 7B18DF931C5BF41B005A2B8E /* Project object */; -} diff --git a/Heap/Heap Tests/Heap/AppDelegate.swift b/Heap/Heap Tests/Heap/AppDelegate.swift deleted file mode 100644 index 954fc0c35..000000000 --- a/Heap/Heap Tests/Heap/AppDelegate.swift +++ /dev/null @@ -1,15 +0,0 @@ -import Cocoa - -@NSApplicationMain -class AppDelegate: NSObject, NSApplicationDelegate { - - @IBOutlet weak var window: NSWindow! - - func applicationDidFinishLaunching(aNotification: NSNotification) { - // Insert code here to initialize your application - } - - func applicationWillTerminate(aNotification: NSNotification) { - // Insert code here to tear down your application - } -} diff --git a/Heap/Heap Tests/Heap/Assets.xcassets/AppIcon.appiconset/Contents.json b/Heap/Heap Tests/Heap/Assets.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index 2db2b1c7c..000000000 --- a/Heap/Heap Tests/Heap/Assets.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "images" : [ - { - "idiom" : "mac", - "size" : "16x16", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "16x16", - "scale" : "2x" - }, - { - "idiom" : "mac", - "size" : "32x32", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "32x32", - "scale" : "2x" - }, - { - "idiom" : "mac", - "size" : "128x128", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "128x128", - "scale" : "2x" - }, - { - "idiom" : "mac", - "size" : "256x256", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "256x256", - "scale" : "2x" - }, - { - "idiom" : "mac", - "size" : "512x512", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "512x512", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/Heap/Heap Tests/Heap/Base.lproj/MainMenu.xib b/Heap/Heap Tests/Heap/Base.lproj/MainMenu.xib deleted file mode 100644 index e6d67c02a..000000000 --- a/Heap/Heap Tests/Heap/Base.lproj/MainMenu.xib +++ /dev/null @@ -1,680 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Default - - - - - - - Left to Right - - - - - - - Right to Left - - - - - - - - - - - Default - - - - - - - Left to Right - - - - - - - Right to Left - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Heap/Heap Tests/Heap/Info.plist b/Heap/Heap Tests/Heap/Info.plist deleted file mode 100644 index 0dca3caa8..000000000 --- a/Heap/Heap Tests/Heap/Info.plist +++ /dev/null @@ -1,34 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIconFile - - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - LSMinimumSystemVersion - $(MACOSX_DEPLOYMENT_TARGET) - NSHumanReadableCopyright - Copyright © 2016 Swift Algorithm Club. All rights reserved. - NSMainNibFile - MainMenu - NSPrincipalClass - NSApplication - - diff --git a/Heap/Heap Tests/HeapTests/HeapTests.swift b/Heap/Tests/HeapTests.swift similarity index 99% rename from Heap/Heap Tests/HeapTests/HeapTests.swift rename to Heap/Tests/HeapTests.swift index 653cf6af9..b038687ad 100644 --- a/Heap/Heap Tests/HeapTests/HeapTests.swift +++ b/Heap/Tests/HeapTests.swift @@ -4,7 +4,6 @@ // import XCTest -@testable import Heap class HeapTests: XCTestCase { diff --git a/Heap/Heap Tests/HeapTests/Info.plist b/Heap/Tests/Info.plist similarity index 100% rename from Heap/Heap Tests/HeapTests/Info.plist rename to Heap/Tests/Info.plist diff --git a/Heap/Tests/Tests.xcodeproj/project.pbxproj b/Heap/Tests/Tests.xcodeproj/project.pbxproj new file mode 100644 index 000000000..a2302e38b --- /dev/null +++ b/Heap/Tests/Tests.xcodeproj/project.pbxproj @@ -0,0 +1,261 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 7B80C3DC1C77A38C003CECC7 /* HeapTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C3DB1C77A38C003CECC7 /* HeapTests.swift */; }; + 7B80C3DE1C77A393003CECC7 /* Heap.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C3DD1C77A393003CECC7 /* Heap.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 7B2BBC801C779D720067B71D /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 7B2BBC941C779E7B0067B71D /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; + 7B80C3DB1C77A38C003CECC7 /* HeapTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HeapTests.swift; sourceTree = SOURCE_ROOT; }; + 7B80C3DD1C77A393003CECC7 /* Heap.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Heap.swift; path = ../Heap.swift; sourceTree = SOURCE_ROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 7B2BBC7D1C779D720067B71D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 7B2BBC681C779D710067B71D = { + isa = PBXGroup; + children = ( + 7B2BBC831C779D720067B71D /* Tests */, + 7B2BBC721C779D710067B71D /* Products */, + ); + sourceTree = ""; + }; + 7B2BBC721C779D710067B71D /* Products */ = { + isa = PBXGroup; + children = ( + 7B2BBC801C779D720067B71D /* Tests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 7B2BBC831C779D720067B71D /* Tests */ = { + isa = PBXGroup; + children = ( + 7B80C3DD1C77A393003CECC7 /* Heap.swift */, + 7B80C3DB1C77A38C003CECC7 /* HeapTests.swift */, + 7B2BBC941C779E7B0067B71D /* Info.plist */, + ); + name = Tests; + path = TestsTests; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 7B2BBC7F1C779D720067B71D /* Tests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */; + buildPhases = ( + 7B2BBC7C1C779D720067B71D /* Sources */, + 7B2BBC7D1C779D720067B71D /* Frameworks */, + 7B2BBC7E1C779D720067B71D /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Tests; + productName = TestsTests; + productReference = 7B2BBC801C779D720067B71D /* Tests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 7B2BBC691C779D710067B71D /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0720; + LastUpgradeCheck = 0720; + ORGANIZATIONNAME = "Swift Algorithm Club"; + TargetAttributes = { + 7B2BBC7F1C779D720067B71D = { + CreatedOnToolsVersion = 7.2; + }; + }; + }; + buildConfigurationList = 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 7B2BBC681C779D710067B71D; + productRefGroup = 7B2BBC721C779D710067B71D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 7B2BBC7F1C779D720067B71D /* Tests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 7B2BBC7E1C779D720067B71D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 7B2BBC7C1C779D720067B71D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 7B80C3DC1C77A38C003CECC7 /* HeapTests.swift in Sources */, + 7B80C3DE1C77A393003CECC7 /* Heap.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 7B2BBC871C779D720067B71D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 7B2BBC881C779D720067B71D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + }; + name = Release; + }; + 7B2BBC8D1C779D720067B71D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 7B2BBC8E1C779D720067B71D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7B2BBC871C779D720067B71D /* Debug */, + 7B2BBC881C779D720067B71D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7B2BBC8D1C779D720067B71D /* Debug */, + 7B2BBC8E1C779D720067B71D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 7B2BBC691C779D710067B71D /* Project object */; +} diff --git a/Insertion Sort/InsertionSort Tests/InsertionSort.xcodeproj/project.pbxproj b/Insertion Sort/InsertionSort Tests/InsertionSort.xcodeproj/project.pbxproj deleted file mode 100644 index 1eed2d04e..000000000 --- a/Insertion Sort/InsertionSort Tests/InsertionSort.xcodeproj/project.pbxproj +++ /dev/null @@ -1,398 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 7B18E0971C5BFA2E005A2B8E /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B18E0961C5BFA2E005A2B8E /* AppDelegate.swift */; }; - 7B18E0991C5BFA2E005A2B8E /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7B18E0981C5BFA2E005A2B8E /* Assets.xcassets */; }; - 7B18E09C1C5BFA2E005A2B8E /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7B18E09A1C5BFA2E005A2B8E /* MainMenu.xib */; }; - 7B18E0A71C5BFA2E005A2B8E /* InsertionSortTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B18E0A61C5BFA2E005A2B8E /* InsertionSortTests.swift */; }; - 7B18E0B21C5BFA4B005A2B8E /* SortingTestHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B18E0B11C5BFA4B005A2B8E /* SortingTestHelpers.swift */; }; - 7B18E0B41C5BFA5F005A2B8E /* InsertionSort.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B18E0B31C5BFA5F005A2B8E /* InsertionSort.swift */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 7B18E0A31C5BFA2E005A2B8E /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 7B18E08B1C5BFA2E005A2B8E /* Project object */; - proxyType = 1; - remoteGlobalIDString = 7B18E0921C5BFA2E005A2B8E; - remoteInfo = InsertionSort; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXFileReference section */ - 7B18E0931C5BFA2E005A2B8E /* InsertionSort.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = InsertionSort.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 7B18E0961C5BFA2E005A2B8E /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 7B18E0981C5BFA2E005A2B8E /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - 7B18E09B1C5BFA2E005A2B8E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; - 7B18E09D1C5BFA2E005A2B8E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 7B18E0A21C5BFA2E005A2B8E /* InsertionSortTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = InsertionSortTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 7B18E0A61C5BFA2E005A2B8E /* InsertionSortTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InsertionSortTests.swift; sourceTree = ""; }; - 7B18E0A81C5BFA2E005A2B8E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 7B18E0B11C5BFA4B005A2B8E /* SortingTestHelpers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SortingTestHelpers.swift; path = "../../../Quicksort/Quicksort Tests/QuicksortTests/SortingTestHelpers.swift"; sourceTree = ""; }; - 7B18E0B31C5BFA5F005A2B8E /* InsertionSort.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = InsertionSort.swift; path = ../../InsertionSort.swift; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 7B18E0901C5BFA2E005A2B8E /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 7B18E09F1C5BFA2E005A2B8E /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 7B18E08A1C5BFA2E005A2B8E = { - isa = PBXGroup; - children = ( - 7B18E0951C5BFA2E005A2B8E /* InsertionSort */, - 7B18E0A51C5BFA2E005A2B8E /* InsertionSortTests */, - 7B18E0941C5BFA2E005A2B8E /* Products */, - ); - sourceTree = ""; - }; - 7B18E0941C5BFA2E005A2B8E /* Products */ = { - isa = PBXGroup; - children = ( - 7B18E0931C5BFA2E005A2B8E /* InsertionSort.app */, - 7B18E0A21C5BFA2E005A2B8E /* InsertionSortTests.xctest */, - ); - name = Products; - sourceTree = ""; - }; - 7B18E0951C5BFA2E005A2B8E /* InsertionSort */ = { - isa = PBXGroup; - children = ( - 7B18E0961C5BFA2E005A2B8E /* AppDelegate.swift */, - 7B18E0981C5BFA2E005A2B8E /* Assets.xcassets */, - 7B18E09D1C5BFA2E005A2B8E /* Info.plist */, - 7B18E0B31C5BFA5F005A2B8E /* InsertionSort.swift */, - 7B18E09A1C5BFA2E005A2B8E /* MainMenu.xib */, - ); - path = InsertionSort; - sourceTree = ""; - }; - 7B18E0A51C5BFA2E005A2B8E /* InsertionSortTests */ = { - isa = PBXGroup; - children = ( - 7B18E0A81C5BFA2E005A2B8E /* Info.plist */, - 7B18E0A61C5BFA2E005A2B8E /* InsertionSortTests.swift */, - 7B18E0B11C5BFA4B005A2B8E /* SortingTestHelpers.swift */, - ); - path = InsertionSortTests; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 7B18E0921C5BFA2E005A2B8E /* InsertionSort */ = { - isa = PBXNativeTarget; - buildConfigurationList = 7B18E0AB1C5BFA2E005A2B8E /* Build configuration list for PBXNativeTarget "InsertionSort" */; - buildPhases = ( - 7B18E08F1C5BFA2E005A2B8E /* Sources */, - 7B18E0901C5BFA2E005A2B8E /* Frameworks */, - 7B18E0911C5BFA2E005A2B8E /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = InsertionSort; - productName = InsertionSort; - productReference = 7B18E0931C5BFA2E005A2B8E /* InsertionSort.app */; - productType = "com.apple.product-type.application"; - }; - 7B18E0A11C5BFA2E005A2B8E /* InsertionSortTests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 7B18E0AE1C5BFA2E005A2B8E /* Build configuration list for PBXNativeTarget "InsertionSortTests" */; - buildPhases = ( - 7B18E09E1C5BFA2E005A2B8E /* Sources */, - 7B18E09F1C5BFA2E005A2B8E /* Frameworks */, - 7B18E0A01C5BFA2E005A2B8E /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - 7B18E0A41C5BFA2E005A2B8E /* PBXTargetDependency */, - ); - name = InsertionSortTests; - productName = InsertionSortTests; - productReference = 7B18E0A21C5BFA2E005A2B8E /* InsertionSortTests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 7B18E08B1C5BFA2E005A2B8E /* Project object */ = { - isa = PBXProject; - attributes = { - LastSwiftUpdateCheck = 0720; - LastUpgradeCheck = 0720; - ORGANIZATIONNAME = "Swift Algorithm Club"; - TargetAttributes = { - 7B18E0921C5BFA2E005A2B8E = { - CreatedOnToolsVersion = 7.2; - }; - 7B18E0A11C5BFA2E005A2B8E = { - CreatedOnToolsVersion = 7.2; - TestTargetID = 7B18E0921C5BFA2E005A2B8E; - }; - }; - }; - buildConfigurationList = 7B18E08E1C5BFA2E005A2B8E /* Build configuration list for PBXProject "InsertionSort" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 7B18E08A1C5BFA2E005A2B8E; - productRefGroup = 7B18E0941C5BFA2E005A2B8E /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 7B18E0921C5BFA2E005A2B8E /* InsertionSort */, - 7B18E0A11C5BFA2E005A2B8E /* InsertionSortTests */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 7B18E0911C5BFA2E005A2B8E /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 7B18E0991C5BFA2E005A2B8E /* Assets.xcassets in Resources */, - 7B18E09C1C5BFA2E005A2B8E /* MainMenu.xib in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 7B18E0A01C5BFA2E005A2B8E /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 7B18E08F1C5BFA2E005A2B8E /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 7B18E0971C5BFA2E005A2B8E /* AppDelegate.swift in Sources */, - 7B18E0B41C5BFA5F005A2B8E /* InsertionSort.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 7B18E09E1C5BFA2E005A2B8E /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 7B18E0B21C5BFA4B005A2B8E /* SortingTestHelpers.swift in Sources */, - 7B18E0A71C5BFA2E005A2B8E /* InsertionSortTests.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 7B18E0A41C5BFA2E005A2B8E /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 7B18E0921C5BFA2E005A2B8E /* InsertionSort */; - targetProxy = 7B18E0A31C5BFA2E005A2B8E /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin PBXVariantGroup section */ - 7B18E09A1C5BFA2E005A2B8E /* MainMenu.xib */ = { - isa = PBXVariantGroup; - children = ( - 7B18E09B1C5BFA2E005A2B8E /* Base */, - ); - name = MainMenu.xib; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 7B18E0A91C5BFA2E005A2B8E /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "-"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.11; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = macosx; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - }; - name = Debug; - }; - 7B18E0AA1C5BFA2E005A2B8E /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "-"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.11; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = macosx; - }; - name = Release; - }; - 7B18E0AC1C5BFA2E005A2B8E /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = InsertionSort/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.InsertionSort; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 7B18E0AD1C5BFA2E005A2B8E /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = InsertionSort/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.InsertionSort; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - 7B18E0AF1C5BFA2E005A2B8E /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = InsertionSortTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.InsertionSortTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/InsertionSort.app/Contents/MacOS/InsertionSort"; - }; - name = Debug; - }; - 7B18E0B01C5BFA2E005A2B8E /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = InsertionSortTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.InsertionSortTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/InsertionSort.app/Contents/MacOS/InsertionSort"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 7B18E08E1C5BFA2E005A2B8E /* Build configuration list for PBXProject "InsertionSort" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 7B18E0A91C5BFA2E005A2B8E /* Debug */, - 7B18E0AA1C5BFA2E005A2B8E /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 7B18E0AB1C5BFA2E005A2B8E /* Build configuration list for PBXNativeTarget "InsertionSort" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 7B18E0AC1C5BFA2E005A2B8E /* Debug */, - 7B18E0AD1C5BFA2E005A2B8E /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 7B18E0AE1C5BFA2E005A2B8E /* Build configuration list for PBXNativeTarget "InsertionSortTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 7B18E0AF1C5BFA2E005A2B8E /* Debug */, - 7B18E0B01C5BFA2E005A2B8E /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 7B18E08B1C5BFA2E005A2B8E /* Project object */; -} diff --git a/Insertion Sort/InsertionSort Tests/InsertionSort/AppDelegate.swift b/Insertion Sort/InsertionSort Tests/InsertionSort/AppDelegate.swift deleted file mode 100644 index 7e8ee6125..000000000 --- a/Insertion Sort/InsertionSort Tests/InsertionSort/AppDelegate.swift +++ /dev/null @@ -1,27 +0,0 @@ -// -// AppDelegate.swift -// InsertionSort -// -// Created by Matthijs Hollemans on 29-01-16. -// Copyright © 2016 Swift Algorithm Club. All rights reserved. -// - -import Cocoa - -@NSApplicationMain -class AppDelegate: NSObject, NSApplicationDelegate { - - @IBOutlet weak var window: NSWindow! - - - func applicationDidFinishLaunching(aNotification: NSNotification) { - // Insert code here to initialize your application - } - - func applicationWillTerminate(aNotification: NSNotification) { - // Insert code here to tear down your application - } - - -} - diff --git a/Insertion Sort/InsertionSort Tests/InsertionSort/Assets.xcassets/AppIcon.appiconset/Contents.json b/Insertion Sort/InsertionSort Tests/InsertionSort/Assets.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index 2db2b1c7c..000000000 --- a/Insertion Sort/InsertionSort Tests/InsertionSort/Assets.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "images" : [ - { - "idiom" : "mac", - "size" : "16x16", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "16x16", - "scale" : "2x" - }, - { - "idiom" : "mac", - "size" : "32x32", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "32x32", - "scale" : "2x" - }, - { - "idiom" : "mac", - "size" : "128x128", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "128x128", - "scale" : "2x" - }, - { - "idiom" : "mac", - "size" : "256x256", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "256x256", - "scale" : "2x" - }, - { - "idiom" : "mac", - "size" : "512x512", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "512x512", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/Insertion Sort/InsertionSort Tests/InsertionSort/Base.lproj/MainMenu.xib b/Insertion Sort/InsertionSort Tests/InsertionSort/Base.lproj/MainMenu.xib deleted file mode 100644 index c08abf93b..000000000 --- a/Insertion Sort/InsertionSort Tests/InsertionSort/Base.lproj/MainMenu.xib +++ /dev/null @@ -1,680 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Default - - - - - - - Left to Right - - - - - - - Right to Left - - - - - - - - - - - Default - - - - - - - Left to Right - - - - - - - Right to Left - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Insertion Sort/InsertionSort Tests/InsertionSort/Info.plist b/Insertion Sort/InsertionSort Tests/InsertionSort/Info.plist deleted file mode 100644 index 0dca3caa8..000000000 --- a/Insertion Sort/InsertionSort Tests/InsertionSort/Info.plist +++ /dev/null @@ -1,34 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIconFile - - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - LSMinimumSystemVersion - $(MACOSX_DEPLOYMENT_TARGET) - NSHumanReadableCopyright - Copyright © 2016 Swift Algorithm Club. All rights reserved. - NSMainNibFile - MainMenu - NSPrincipalClass - NSApplication - - diff --git a/Insertion Sort/InsertionSort Tests/InsertionSortTests/Info.plist b/Insertion Sort/Tests/Info.plist similarity index 100% rename from Insertion Sort/InsertionSort Tests/InsertionSortTests/Info.plist rename to Insertion Sort/Tests/Info.plist diff --git a/Insertion Sort/InsertionSort Tests/InsertionSortTests/InsertionSortTests.swift b/Insertion Sort/Tests/InsertionSortTests.swift similarity index 80% rename from Insertion Sort/InsertionSort Tests/InsertionSortTests/InsertionSortTests.swift rename to Insertion Sort/Tests/InsertionSortTests.swift index 351ee6157..49f5eda9a 100644 --- a/Insertion Sort/InsertionSort Tests/InsertionSortTests/InsertionSortTests.swift +++ b/Insertion Sort/Tests/InsertionSortTests.swift @@ -1,5 +1,4 @@ import XCTest -@testable import InsertionSort class InsertionSortTests: XCTestCase { func testInsertionSort() { diff --git a/Insertion Sort/Tests/Tests.xcodeproj/project.pbxproj b/Insertion Sort/Tests/Tests.xcodeproj/project.pbxproj new file mode 100644 index 000000000..f8c23899c --- /dev/null +++ b/Insertion Sort/Tests/Tests.xcodeproj/project.pbxproj @@ -0,0 +1,265 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 7B80C3EA1C77A4D0003CECC7 /* SortingTestHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C3E81C77A4D0003CECC7 /* SortingTestHelpers.swift */; }; + 7B80C3EC1C77A536003CECC7 /* InsertionSortTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C3EB1C77A536003CECC7 /* InsertionSortTests.swift */; }; + 7B80C3EE1C77A53E003CECC7 /* InsertionSort.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C3ED1C77A53E003CECC7 /* InsertionSort.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 7B2BBC801C779D720067B71D /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 7B2BBC941C779E7B0067B71D /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; + 7B80C3E81C77A4D0003CECC7 /* SortingTestHelpers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SortingTestHelpers.swift; path = ../../Quicksort/Tests/SortingTestHelpers.swift; sourceTree = SOURCE_ROOT; }; + 7B80C3EB1C77A536003CECC7 /* InsertionSortTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InsertionSortTests.swift; sourceTree = SOURCE_ROOT; }; + 7B80C3ED1C77A53E003CECC7 /* InsertionSort.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = InsertionSort.swift; path = ../InsertionSort.swift; sourceTree = SOURCE_ROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 7B2BBC7D1C779D720067B71D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 7B2BBC681C779D710067B71D = { + isa = PBXGroup; + children = ( + 7B2BBC831C779D720067B71D /* Tests */, + 7B2BBC721C779D710067B71D /* Products */, + ); + sourceTree = ""; + }; + 7B2BBC721C779D710067B71D /* Products */ = { + isa = PBXGroup; + children = ( + 7B2BBC801C779D720067B71D /* Tests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 7B2BBC831C779D720067B71D /* Tests */ = { + isa = PBXGroup; + children = ( + 7B80C3ED1C77A53E003CECC7 /* InsertionSort.swift */, + 7B80C3EB1C77A536003CECC7 /* InsertionSortTests.swift */, + 7B80C3E81C77A4D0003CECC7 /* SortingTestHelpers.swift */, + 7B2BBC941C779E7B0067B71D /* Info.plist */, + ); + name = Tests; + path = TestsTests; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 7B2BBC7F1C779D720067B71D /* Tests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */; + buildPhases = ( + 7B2BBC7C1C779D720067B71D /* Sources */, + 7B2BBC7D1C779D720067B71D /* Frameworks */, + 7B2BBC7E1C779D720067B71D /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Tests; + productName = TestsTests; + productReference = 7B2BBC801C779D720067B71D /* Tests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 7B2BBC691C779D710067B71D /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0720; + LastUpgradeCheck = 0720; + ORGANIZATIONNAME = "Swift Algorithm Club"; + TargetAttributes = { + 7B2BBC7F1C779D720067B71D = { + CreatedOnToolsVersion = 7.2; + }; + }; + }; + buildConfigurationList = 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 7B2BBC681C779D710067B71D; + productRefGroup = 7B2BBC721C779D710067B71D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 7B2BBC7F1C779D720067B71D /* Tests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 7B2BBC7E1C779D720067B71D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 7B2BBC7C1C779D720067B71D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 7B80C3EA1C77A4D0003CECC7 /* SortingTestHelpers.swift in Sources */, + 7B80C3EE1C77A53E003CECC7 /* InsertionSort.swift in Sources */, + 7B80C3EC1C77A536003CECC7 /* InsertionSortTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 7B2BBC871C779D720067B71D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 7B2BBC881C779D720067B71D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + }; + name = Release; + }; + 7B2BBC8D1C779D720067B71D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 7B2BBC8E1C779D720067B71D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7B2BBC871C779D720067B71D /* Debug */, + 7B2BBC881C779D720067B71D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7B2BBC8D1C779D720067B71D /* Debug */, + 7B2BBC8E1C779D720067B71D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 7B2BBC691C779D710067B71D /* Project object */; +} diff --git a/Linked List/LinkedList Tests/LinkedList.xcodeproj/project.pbxproj b/Linked List/LinkedList Tests/LinkedList.xcodeproj/project.pbxproj deleted file mode 100644 index 20817809d..000000000 --- a/Linked List/LinkedList Tests/LinkedList.xcodeproj/project.pbxproj +++ /dev/null @@ -1,394 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 7B1BF9C81C6288D40051C9A4 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B1BF9C71C6288D40051C9A4 /* AppDelegate.swift */; }; - 7B1BF9CA1C6288D40051C9A4 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7B1BF9C91C6288D40051C9A4 /* Assets.xcassets */; }; - 7B1BF9CD1C6288D40051C9A4 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7B1BF9CB1C6288D40051C9A4 /* MainMenu.xib */; }; - 7B1BF9D81C6288D40051C9A4 /* LinkedListTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B1BF9D71C6288D40051C9A4 /* LinkedListTests.swift */; }; - 7B1BF9E31C62897B0051C9A4 /* LinkedList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B1BF9E21C62897B0051C9A4 /* LinkedList.swift */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 7B1BF9D41C6288D40051C9A4 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 7B1BF9BC1C6288D40051C9A4 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 7B1BF9C31C6288D40051C9A4; - remoteInfo = LinkedList; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXFileReference section */ - 7B1BF9C41C6288D40051C9A4 /* LinkedList.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = LinkedList.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 7B1BF9C71C6288D40051C9A4 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 7B1BF9C91C6288D40051C9A4 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - 7B1BF9CC1C6288D40051C9A4 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; - 7B1BF9CE1C6288D40051C9A4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 7B1BF9D31C6288D40051C9A4 /* LinkedListTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = LinkedListTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 7B1BF9D71C6288D40051C9A4 /* LinkedListTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkedListTests.swift; sourceTree = ""; }; - 7B1BF9D91C6288D40051C9A4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 7B1BF9E21C62897B0051C9A4 /* LinkedList.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = LinkedList.swift; path = ../../LinkedList.swift; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 7B1BF9C11C6288D40051C9A4 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 7B1BF9D01C6288D40051C9A4 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 7B1BF9BB1C6288D40051C9A4 = { - isa = PBXGroup; - children = ( - 7B1BF9C61C6288D40051C9A4 /* LinkedList */, - 7B1BF9D61C6288D40051C9A4 /* LinkedListTests */, - 7B1BF9C51C6288D40051C9A4 /* Products */, - ); - sourceTree = ""; - }; - 7B1BF9C51C6288D40051C9A4 /* Products */ = { - isa = PBXGroup; - children = ( - 7B1BF9C41C6288D40051C9A4 /* LinkedList.app */, - 7B1BF9D31C6288D40051C9A4 /* LinkedListTests.xctest */, - ); - name = Products; - sourceTree = ""; - }; - 7B1BF9C61C6288D40051C9A4 /* LinkedList */ = { - isa = PBXGroup; - children = ( - 7B1BF9C71C6288D40051C9A4 /* AppDelegate.swift */, - 7B1BF9C91C6288D40051C9A4 /* Assets.xcassets */, - 7B1BF9CE1C6288D40051C9A4 /* Info.plist */, - 7B1BF9E21C62897B0051C9A4 /* LinkedList.swift */, - 7B1BF9CB1C6288D40051C9A4 /* MainMenu.xib */, - ); - path = LinkedList; - sourceTree = ""; - }; - 7B1BF9D61C6288D40051C9A4 /* LinkedListTests */ = { - isa = PBXGroup; - children = ( - 7B1BF9D71C6288D40051C9A4 /* LinkedListTests.swift */, - 7B1BF9D91C6288D40051C9A4 /* Info.plist */, - ); - path = LinkedListTests; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 7B1BF9C31C6288D40051C9A4 /* LinkedList */ = { - isa = PBXNativeTarget; - buildConfigurationList = 7B1BF9DC1C6288D40051C9A4 /* Build configuration list for PBXNativeTarget "LinkedList" */; - buildPhases = ( - 7B1BF9C01C6288D40051C9A4 /* Sources */, - 7B1BF9C11C6288D40051C9A4 /* Frameworks */, - 7B1BF9C21C6288D40051C9A4 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = LinkedList; - productName = LinkedList; - productReference = 7B1BF9C41C6288D40051C9A4 /* LinkedList.app */; - productType = "com.apple.product-type.application"; - }; - 7B1BF9D21C6288D40051C9A4 /* LinkedListTests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 7B1BF9DF1C6288D40051C9A4 /* Build configuration list for PBXNativeTarget "LinkedListTests" */; - buildPhases = ( - 7B1BF9CF1C6288D40051C9A4 /* Sources */, - 7B1BF9D01C6288D40051C9A4 /* Frameworks */, - 7B1BF9D11C6288D40051C9A4 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - 7B1BF9D51C6288D40051C9A4 /* PBXTargetDependency */, - ); - name = LinkedListTests; - productName = LinkedListTests; - productReference = 7B1BF9D31C6288D40051C9A4 /* LinkedListTests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 7B1BF9BC1C6288D40051C9A4 /* Project object */ = { - isa = PBXProject; - attributes = { - LastSwiftUpdateCheck = 0720; - LastUpgradeCheck = 0720; - ORGANIZATIONNAME = "Swift Algorithm Club"; - TargetAttributes = { - 7B1BF9C31C6288D40051C9A4 = { - CreatedOnToolsVersion = 7.2; - }; - 7B1BF9D21C6288D40051C9A4 = { - CreatedOnToolsVersion = 7.2; - TestTargetID = 7B1BF9C31C6288D40051C9A4; - }; - }; - }; - buildConfigurationList = 7B1BF9BF1C6288D40051C9A4 /* Build configuration list for PBXProject "LinkedList" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 7B1BF9BB1C6288D40051C9A4; - productRefGroup = 7B1BF9C51C6288D40051C9A4 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 7B1BF9C31C6288D40051C9A4 /* LinkedList */, - 7B1BF9D21C6288D40051C9A4 /* LinkedListTests */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 7B1BF9C21C6288D40051C9A4 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 7B1BF9CA1C6288D40051C9A4 /* Assets.xcassets in Resources */, - 7B1BF9CD1C6288D40051C9A4 /* MainMenu.xib in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 7B1BF9D11C6288D40051C9A4 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 7B1BF9C01C6288D40051C9A4 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 7B1BF9E31C62897B0051C9A4 /* LinkedList.swift in Sources */, - 7B1BF9C81C6288D40051C9A4 /* AppDelegate.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 7B1BF9CF1C6288D40051C9A4 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 7B1BF9D81C6288D40051C9A4 /* LinkedListTests.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 7B1BF9D51C6288D40051C9A4 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 7B1BF9C31C6288D40051C9A4 /* LinkedList */; - targetProxy = 7B1BF9D41C6288D40051C9A4 /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin PBXVariantGroup section */ - 7B1BF9CB1C6288D40051C9A4 /* MainMenu.xib */ = { - isa = PBXVariantGroup; - children = ( - 7B1BF9CC1C6288D40051C9A4 /* Base */, - ); - name = MainMenu.xib; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 7B1BF9DA1C6288D40051C9A4 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "-"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.11; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = macosx; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - }; - name = Debug; - }; - 7B1BF9DB1C6288D40051C9A4 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "-"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.11; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = macosx; - }; - name = Release; - }; - 7B1BF9DD1C6288D40051C9A4 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = LinkedList/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.LinkedList; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 7B1BF9DE1C6288D40051C9A4 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = LinkedList/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.LinkedList; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - 7B1BF9E01C6288D40051C9A4 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = LinkedListTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.LinkedListTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/LinkedList.app/Contents/MacOS/LinkedList"; - }; - name = Debug; - }; - 7B1BF9E11C6288D40051C9A4 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = LinkedListTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.LinkedListTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/LinkedList.app/Contents/MacOS/LinkedList"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 7B1BF9BF1C6288D40051C9A4 /* Build configuration list for PBXProject "LinkedList" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 7B1BF9DA1C6288D40051C9A4 /* Debug */, - 7B1BF9DB1C6288D40051C9A4 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 7B1BF9DC1C6288D40051C9A4 /* Build configuration list for PBXNativeTarget "LinkedList" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 7B1BF9DD1C6288D40051C9A4 /* Debug */, - 7B1BF9DE1C6288D40051C9A4 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 7B1BF9DF1C6288D40051C9A4 /* Build configuration list for PBXNativeTarget "LinkedListTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 7B1BF9E01C6288D40051C9A4 /* Debug */, - 7B1BF9E11C6288D40051C9A4 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 7B1BF9BC1C6288D40051C9A4 /* Project object */; -} diff --git a/Linked List/LinkedList Tests/LinkedList/AppDelegate.swift b/Linked List/LinkedList Tests/LinkedList/AppDelegate.swift deleted file mode 100644 index f83b01f35..000000000 --- a/Linked List/LinkedList Tests/LinkedList/AppDelegate.swift +++ /dev/null @@ -1,27 +0,0 @@ -// -// AppDelegate.swift -// LinkedList -// -// Created by Matthijs Hollemans on 03-02-16. -// Copyright © 2016 Swift Algorithm Club. All rights reserved. -// - -import Cocoa - -@NSApplicationMain -class AppDelegate: NSObject, NSApplicationDelegate { - - @IBOutlet weak var window: NSWindow! - - - func applicationDidFinishLaunching(aNotification: NSNotification) { - // Insert code here to initialize your application - } - - func applicationWillTerminate(aNotification: NSNotification) { - // Insert code here to tear down your application - } - - -} - diff --git a/Linked List/LinkedList Tests/LinkedList/Assets.xcassets/AppIcon.appiconset/Contents.json b/Linked List/LinkedList Tests/LinkedList/Assets.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index 2db2b1c7c..000000000 --- a/Linked List/LinkedList Tests/LinkedList/Assets.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "images" : [ - { - "idiom" : "mac", - "size" : "16x16", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "16x16", - "scale" : "2x" - }, - { - "idiom" : "mac", - "size" : "32x32", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "32x32", - "scale" : "2x" - }, - { - "idiom" : "mac", - "size" : "128x128", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "128x128", - "scale" : "2x" - }, - { - "idiom" : "mac", - "size" : "256x256", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "256x256", - "scale" : "2x" - }, - { - "idiom" : "mac", - "size" : "512x512", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "512x512", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/Linked List/LinkedList Tests/LinkedList/Base.lproj/MainMenu.xib b/Linked List/LinkedList Tests/LinkedList/Base.lproj/MainMenu.xib deleted file mode 100644 index 32e8f7bae..000000000 --- a/Linked List/LinkedList Tests/LinkedList/Base.lproj/MainMenu.xib +++ /dev/null @@ -1,680 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Default - - - - - - - Left to Right - - - - - - - Right to Left - - - - - - - - - - - Default - - - - - - - Left to Right - - - - - - - Right to Left - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Linked List/LinkedList Tests/LinkedList/Info.plist b/Linked List/LinkedList Tests/LinkedList/Info.plist deleted file mode 100644 index 0dca3caa8..000000000 --- a/Linked List/LinkedList Tests/LinkedList/Info.plist +++ /dev/null @@ -1,34 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIconFile - - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - LSMinimumSystemVersion - $(MACOSX_DEPLOYMENT_TARGET) - NSHumanReadableCopyright - Copyright © 2016 Swift Algorithm Club. All rights reserved. - NSMainNibFile - MainMenu - NSPrincipalClass - NSApplication - - diff --git a/Linked List/LinkedList Tests/LinkedListTests/Info.plist b/Linked List/Tests/Info.plist similarity index 100% rename from Linked List/LinkedList Tests/LinkedListTests/Info.plist rename to Linked List/Tests/Info.plist diff --git a/Linked List/LinkedList Tests/LinkedListTests/LinkedListTests.swift b/Linked List/Tests/LinkedListTests.swift similarity index 99% rename from Linked List/LinkedList Tests/LinkedListTests/LinkedListTests.swift rename to Linked List/Tests/LinkedListTests.swift index 80241114c..4bdc0adae 100755 --- a/Linked List/LinkedList Tests/LinkedListTests/LinkedListTests.swift +++ b/Linked List/Tests/LinkedListTests.swift @@ -1,5 +1,4 @@ import XCTest -@testable import LinkedList class LinkedListTest: XCTestCase { let numbers = [8, 2, 10, 9, 7, 5] diff --git a/Linked List/Tests/Tests.xcodeproj/project.pbxproj b/Linked List/Tests/Tests.xcodeproj/project.pbxproj new file mode 100644 index 000000000..7c6a2020a --- /dev/null +++ b/Linked List/Tests/Tests.xcodeproj/project.pbxproj @@ -0,0 +1,261 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 7B80C3F81C77A618003CECC7 /* LinkedList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C3F71C77A618003CECC7 /* LinkedList.swift */; }; + 7B80C3FA1C77A61E003CECC7 /* LinkedListTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C3F91C77A61E003CECC7 /* LinkedListTests.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 7B2BBC801C779D720067B71D /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 7B2BBC941C779E7B0067B71D /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; + 7B80C3F71C77A618003CECC7 /* LinkedList.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = LinkedList.swift; path = ../LinkedList.swift; sourceTree = SOURCE_ROOT; }; + 7B80C3F91C77A61E003CECC7 /* LinkedListTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LinkedListTests.swift; sourceTree = SOURCE_ROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 7B2BBC7D1C779D720067B71D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 7B2BBC681C779D710067B71D = { + isa = PBXGroup; + children = ( + 7B2BBC831C779D720067B71D /* Tests */, + 7B2BBC721C779D710067B71D /* Products */, + ); + sourceTree = ""; + }; + 7B2BBC721C779D710067B71D /* Products */ = { + isa = PBXGroup; + children = ( + 7B2BBC801C779D720067B71D /* Tests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 7B2BBC831C779D720067B71D /* Tests */ = { + isa = PBXGroup; + children = ( + 7B80C3F71C77A618003CECC7 /* LinkedList.swift */, + 7B80C3F91C77A61E003CECC7 /* LinkedListTests.swift */, + 7B2BBC941C779E7B0067B71D /* Info.plist */, + ); + name = Tests; + path = TestsTests; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 7B2BBC7F1C779D720067B71D /* Tests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */; + buildPhases = ( + 7B2BBC7C1C779D720067B71D /* Sources */, + 7B2BBC7D1C779D720067B71D /* Frameworks */, + 7B2BBC7E1C779D720067B71D /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Tests; + productName = TestsTests; + productReference = 7B2BBC801C779D720067B71D /* Tests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 7B2BBC691C779D710067B71D /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0720; + LastUpgradeCheck = 0720; + ORGANIZATIONNAME = "Swift Algorithm Club"; + TargetAttributes = { + 7B2BBC7F1C779D720067B71D = { + CreatedOnToolsVersion = 7.2; + }; + }; + }; + buildConfigurationList = 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 7B2BBC681C779D710067B71D; + productRefGroup = 7B2BBC721C779D710067B71D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 7B2BBC7F1C779D720067B71D /* Tests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 7B2BBC7E1C779D720067B71D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 7B2BBC7C1C779D720067B71D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 7B80C3F81C77A618003CECC7 /* LinkedList.swift in Sources */, + 7B80C3FA1C77A61E003CECC7 /* LinkedListTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 7B2BBC871C779D720067B71D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 7B2BBC881C779D720067B71D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + }; + name = Release; + }; + 7B2BBC8D1C779D720067B71D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 7B2BBC8E1C779D720067B71D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7B2BBC871C779D720067B71D /* Debug */, + 7B2BBC881C779D720067B71D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7B2BBC8D1C779D720067B71D /* Debug */, + 7B2BBC8E1C779D720067B71D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 7B2BBC691C779D710067B71D /* Project object */; +} diff --git a/Priority Queue/PriorityQueue Tests/PriorityQueue.xcodeproj/project.pbxproj b/Priority Queue/PriorityQueue Tests/PriorityQueue.xcodeproj/project.pbxproj deleted file mode 100644 index d855143a1..000000000 --- a/Priority Queue/PriorityQueue Tests/PriorityQueue.xcodeproj/project.pbxproj +++ /dev/null @@ -1,398 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 7B1BFA1A1C6914970051C9A4 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B1BFA191C6914970051C9A4 /* AppDelegate.swift */; }; - 7B1BFA1C1C6914970051C9A4 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7B1BFA1B1C6914970051C9A4 /* Assets.xcassets */; }; - 7B1BFA1F1C6914970051C9A4 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7B1BFA1D1C6914970051C9A4 /* MainMenu.xib */; }; - 7B1BFA2A1C6914970051C9A4 /* PriorityQueueTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B1BFA291C6914970051C9A4 /* PriorityQueueTests.swift */; }; - 7B1BFA351C6914B60051C9A4 /* PriorityQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B1BFA341C6914B60051C9A4 /* PriorityQueue.swift */; }; - 7B1BFA371C6914C20051C9A4 /* Heap.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B1BFA361C6914C20051C9A4 /* Heap.swift */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 7B1BFA261C6914970051C9A4 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 7B1BFA0E1C6914970051C9A4 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 7B1BFA151C6914970051C9A4; - remoteInfo = PriorityQueue; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXFileReference section */ - 7B1BFA161C6914970051C9A4 /* PriorityQueue.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = PriorityQueue.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 7B1BFA191C6914970051C9A4 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 7B1BFA1B1C6914970051C9A4 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - 7B1BFA1E1C6914970051C9A4 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; - 7B1BFA201C6914970051C9A4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 7B1BFA251C6914970051C9A4 /* PriorityQueueTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = PriorityQueueTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 7B1BFA291C6914970051C9A4 /* PriorityQueueTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PriorityQueueTests.swift; sourceTree = ""; }; - 7B1BFA2B1C6914970051C9A4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 7B1BFA341C6914B60051C9A4 /* PriorityQueue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = PriorityQueue.swift; path = ../../PriorityQueue.swift; sourceTree = ""; }; - 7B1BFA361C6914C20051C9A4 /* Heap.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Heap.swift; path = ../../../Heap/Heap.swift; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 7B1BFA131C6914970051C9A4 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 7B1BFA221C6914970051C9A4 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 7B1BFA0D1C6914970051C9A4 = { - isa = PBXGroup; - children = ( - 7B1BFA181C6914970051C9A4 /* PriorityQueue */, - 7B1BFA281C6914970051C9A4 /* PriorityQueueTests */, - 7B1BFA171C6914970051C9A4 /* Products */, - ); - sourceTree = ""; - }; - 7B1BFA171C6914970051C9A4 /* Products */ = { - isa = PBXGroup; - children = ( - 7B1BFA161C6914970051C9A4 /* PriorityQueue.app */, - 7B1BFA251C6914970051C9A4 /* PriorityQueueTests.xctest */, - ); - name = Products; - sourceTree = ""; - }; - 7B1BFA181C6914970051C9A4 /* PriorityQueue */ = { - isa = PBXGroup; - children = ( - 7B1BFA191C6914970051C9A4 /* AppDelegate.swift */, - 7B1BFA1B1C6914970051C9A4 /* Assets.xcassets */, - 7B1BFA361C6914C20051C9A4 /* Heap.swift */, - 7B1BFA201C6914970051C9A4 /* Info.plist */, - 7B1BFA1D1C6914970051C9A4 /* MainMenu.xib */, - 7B1BFA341C6914B60051C9A4 /* PriorityQueue.swift */, - ); - path = PriorityQueue; - sourceTree = ""; - }; - 7B1BFA281C6914970051C9A4 /* PriorityQueueTests */ = { - isa = PBXGroup; - children = ( - 7B1BFA291C6914970051C9A4 /* PriorityQueueTests.swift */, - 7B1BFA2B1C6914970051C9A4 /* Info.plist */, - ); - path = PriorityQueueTests; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 7B1BFA151C6914970051C9A4 /* PriorityQueue */ = { - isa = PBXNativeTarget; - buildConfigurationList = 7B1BFA2E1C6914970051C9A4 /* Build configuration list for PBXNativeTarget "PriorityQueue" */; - buildPhases = ( - 7B1BFA121C6914970051C9A4 /* Sources */, - 7B1BFA131C6914970051C9A4 /* Frameworks */, - 7B1BFA141C6914970051C9A4 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = PriorityQueue; - productName = PriorityQueue; - productReference = 7B1BFA161C6914970051C9A4 /* PriorityQueue.app */; - productType = "com.apple.product-type.application"; - }; - 7B1BFA241C6914970051C9A4 /* PriorityQueueTests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 7B1BFA311C6914970051C9A4 /* Build configuration list for PBXNativeTarget "PriorityQueueTests" */; - buildPhases = ( - 7B1BFA211C6914970051C9A4 /* Sources */, - 7B1BFA221C6914970051C9A4 /* Frameworks */, - 7B1BFA231C6914970051C9A4 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - 7B1BFA271C6914970051C9A4 /* PBXTargetDependency */, - ); - name = PriorityQueueTests; - productName = PriorityQueueTests; - productReference = 7B1BFA251C6914970051C9A4 /* PriorityQueueTests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 7B1BFA0E1C6914970051C9A4 /* Project object */ = { - isa = PBXProject; - attributes = { - LastSwiftUpdateCheck = 0720; - LastUpgradeCheck = 0720; - ORGANIZATIONNAME = "Swift Algorithm Club"; - TargetAttributes = { - 7B1BFA151C6914970051C9A4 = { - CreatedOnToolsVersion = 7.2; - }; - 7B1BFA241C6914970051C9A4 = { - CreatedOnToolsVersion = 7.2; - TestTargetID = 7B1BFA151C6914970051C9A4; - }; - }; - }; - buildConfigurationList = 7B1BFA111C6914970051C9A4 /* Build configuration list for PBXProject "PriorityQueue" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 7B1BFA0D1C6914970051C9A4; - productRefGroup = 7B1BFA171C6914970051C9A4 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 7B1BFA151C6914970051C9A4 /* PriorityQueue */, - 7B1BFA241C6914970051C9A4 /* PriorityQueueTests */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 7B1BFA141C6914970051C9A4 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 7B1BFA1C1C6914970051C9A4 /* Assets.xcassets in Resources */, - 7B1BFA1F1C6914970051C9A4 /* MainMenu.xib in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 7B1BFA231C6914970051C9A4 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 7B1BFA121C6914970051C9A4 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 7B1BFA371C6914C20051C9A4 /* Heap.swift in Sources */, - 7B1BFA1A1C6914970051C9A4 /* AppDelegate.swift in Sources */, - 7B1BFA351C6914B60051C9A4 /* PriorityQueue.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 7B1BFA211C6914970051C9A4 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 7B1BFA2A1C6914970051C9A4 /* PriorityQueueTests.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 7B1BFA271C6914970051C9A4 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 7B1BFA151C6914970051C9A4 /* PriorityQueue */; - targetProxy = 7B1BFA261C6914970051C9A4 /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin PBXVariantGroup section */ - 7B1BFA1D1C6914970051C9A4 /* MainMenu.xib */ = { - isa = PBXVariantGroup; - children = ( - 7B1BFA1E1C6914970051C9A4 /* Base */, - ); - name = MainMenu.xib; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 7B1BFA2C1C6914970051C9A4 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "-"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.11; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = macosx; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - }; - name = Debug; - }; - 7B1BFA2D1C6914970051C9A4 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "-"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.11; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = macosx; - }; - name = Release; - }; - 7B1BFA2F1C6914970051C9A4 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = PriorityQueue/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.PriorityQueue; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 7B1BFA301C6914970051C9A4 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = PriorityQueue/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.PriorityQueue; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - 7B1BFA321C6914970051C9A4 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = PriorityQueueTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.PriorityQueueTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/PriorityQueue.app/Contents/MacOS/PriorityQueue"; - }; - name = Debug; - }; - 7B1BFA331C6914970051C9A4 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = PriorityQueueTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.PriorityQueueTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/PriorityQueue.app/Contents/MacOS/PriorityQueue"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 7B1BFA111C6914970051C9A4 /* Build configuration list for PBXProject "PriorityQueue" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 7B1BFA2C1C6914970051C9A4 /* Debug */, - 7B1BFA2D1C6914970051C9A4 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 7B1BFA2E1C6914970051C9A4 /* Build configuration list for PBXNativeTarget "PriorityQueue" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 7B1BFA2F1C6914970051C9A4 /* Debug */, - 7B1BFA301C6914970051C9A4 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 7B1BFA311C6914970051C9A4 /* Build configuration list for PBXNativeTarget "PriorityQueueTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 7B1BFA321C6914970051C9A4 /* Debug */, - 7B1BFA331C6914970051C9A4 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 7B1BFA0E1C6914970051C9A4 /* Project object */; -} diff --git a/Priority Queue/PriorityQueue Tests/PriorityQueue/AppDelegate.swift b/Priority Queue/PriorityQueue Tests/PriorityQueue/AppDelegate.swift deleted file mode 100644 index 0154bd5eb..000000000 --- a/Priority Queue/PriorityQueue Tests/PriorityQueue/AppDelegate.swift +++ /dev/null @@ -1,27 +0,0 @@ -// -// AppDelegate.swift -// PriorityQueue -// -// Created by Matthijs Hollemans on 08-02-16. -// Copyright © 2016 Swift Algorithm Club. All rights reserved. -// - -import Cocoa - -@NSApplicationMain -class AppDelegate: NSObject, NSApplicationDelegate { - - @IBOutlet weak var window: NSWindow! - - - func applicationDidFinishLaunching(aNotification: NSNotification) { - // Insert code here to initialize your application - } - - func applicationWillTerminate(aNotification: NSNotification) { - // Insert code here to tear down your application - } - - -} - diff --git a/Priority Queue/PriorityQueue Tests/PriorityQueue/Assets.xcassets/AppIcon.appiconset/Contents.json b/Priority Queue/PriorityQueue Tests/PriorityQueue/Assets.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index 2db2b1c7c..000000000 --- a/Priority Queue/PriorityQueue Tests/PriorityQueue/Assets.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "images" : [ - { - "idiom" : "mac", - "size" : "16x16", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "16x16", - "scale" : "2x" - }, - { - "idiom" : "mac", - "size" : "32x32", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "32x32", - "scale" : "2x" - }, - { - "idiom" : "mac", - "size" : "128x128", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "128x128", - "scale" : "2x" - }, - { - "idiom" : "mac", - "size" : "256x256", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "256x256", - "scale" : "2x" - }, - { - "idiom" : "mac", - "size" : "512x512", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "512x512", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/Priority Queue/PriorityQueue Tests/PriorityQueue/Base.lproj/MainMenu.xib b/Priority Queue/PriorityQueue Tests/PriorityQueue/Base.lproj/MainMenu.xib deleted file mode 100644 index b36de4331..000000000 --- a/Priority Queue/PriorityQueue Tests/PriorityQueue/Base.lproj/MainMenu.xib +++ /dev/null @@ -1,680 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Default - - - - - - - Left to Right - - - - - - - Right to Left - - - - - - - - - - - Default - - - - - - - Left to Right - - - - - - - Right to Left - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Priority Queue/PriorityQueue Tests/PriorityQueue/Info.plist b/Priority Queue/PriorityQueue Tests/PriorityQueue/Info.plist deleted file mode 100644 index 0dca3caa8..000000000 --- a/Priority Queue/PriorityQueue Tests/PriorityQueue/Info.plist +++ /dev/null @@ -1,34 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIconFile - - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - LSMinimumSystemVersion - $(MACOSX_DEPLOYMENT_TARGET) - NSHumanReadableCopyright - Copyright © 2016 Swift Algorithm Club. All rights reserved. - NSMainNibFile - MainMenu - NSPrincipalClass - NSApplication - - diff --git a/Priority Queue/PriorityQueue Tests/PriorityQueueTests/Info.plist b/Priority Queue/Tests/Info.plist similarity index 100% rename from Priority Queue/PriorityQueue Tests/PriorityQueueTests/Info.plist rename to Priority Queue/Tests/Info.plist diff --git a/Priority Queue/PriorityQueue Tests/PriorityQueueTests/PriorityQueueTests.swift b/Priority Queue/Tests/PriorityQueueTests.swift similarity index 98% rename from Priority Queue/PriorityQueue Tests/PriorityQueueTests/PriorityQueueTests.swift rename to Priority Queue/Tests/PriorityQueueTests.swift index e0fc1bd28..56536310d 100755 --- a/Priority Queue/PriorityQueue Tests/PriorityQueueTests/PriorityQueueTests.swift +++ b/Priority Queue/Tests/PriorityQueueTests.swift @@ -1,6 +1,5 @@ import Foundation import XCTest -@testable import PriorityQueue private struct Message { let text: String diff --git a/Priority Queue/Tests/Tests.xcodeproj/project.pbxproj b/Priority Queue/Tests/Tests.xcodeproj/project.pbxproj new file mode 100644 index 000000000..5c6a20355 --- /dev/null +++ b/Priority Queue/Tests/Tests.xcodeproj/project.pbxproj @@ -0,0 +1,265 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 7B80C3FC1C77A658003CECC7 /* PriorityQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C3FB1C77A658003CECC7 /* PriorityQueue.swift */; }; + 7B80C3FE1C77A65E003CECC7 /* PriorityQueueTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C3FD1C77A65E003CECC7 /* PriorityQueueTests.swift */; }; + 7B80C4001C77A67B003CECC7 /* Heap.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C3FF1C77A67B003CECC7 /* Heap.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 7B2BBC801C779D720067B71D /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 7B2BBC941C779E7B0067B71D /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; + 7B80C3FB1C77A658003CECC7 /* PriorityQueue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = PriorityQueue.swift; path = ../PriorityQueue.swift; sourceTree = SOURCE_ROOT; }; + 7B80C3FD1C77A65E003CECC7 /* PriorityQueueTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PriorityQueueTests.swift; sourceTree = SOURCE_ROOT; }; + 7B80C3FF1C77A67B003CECC7 /* Heap.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Heap.swift; path = ../../Heap/Heap.swift; sourceTree = SOURCE_ROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 7B2BBC7D1C779D720067B71D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 7B2BBC681C779D710067B71D = { + isa = PBXGroup; + children = ( + 7B2BBC831C779D720067B71D /* Tests */, + 7B2BBC721C779D710067B71D /* Products */, + ); + sourceTree = ""; + }; + 7B2BBC721C779D710067B71D /* Products */ = { + isa = PBXGroup; + children = ( + 7B2BBC801C779D720067B71D /* Tests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 7B2BBC831C779D720067B71D /* Tests */ = { + isa = PBXGroup; + children = ( + 7B80C3FF1C77A67B003CECC7 /* Heap.swift */, + 7B80C3FB1C77A658003CECC7 /* PriorityQueue.swift */, + 7B80C3FD1C77A65E003CECC7 /* PriorityQueueTests.swift */, + 7B2BBC941C779E7B0067B71D /* Info.plist */, + ); + name = Tests; + path = TestsTests; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 7B2BBC7F1C779D720067B71D /* Tests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */; + buildPhases = ( + 7B2BBC7C1C779D720067B71D /* Sources */, + 7B2BBC7D1C779D720067B71D /* Frameworks */, + 7B2BBC7E1C779D720067B71D /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Tests; + productName = TestsTests; + productReference = 7B2BBC801C779D720067B71D /* Tests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 7B2BBC691C779D710067B71D /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0720; + LastUpgradeCheck = 0720; + ORGANIZATIONNAME = "Swift Algorithm Club"; + TargetAttributes = { + 7B2BBC7F1C779D720067B71D = { + CreatedOnToolsVersion = 7.2; + }; + }; + }; + buildConfigurationList = 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 7B2BBC681C779D710067B71D; + productRefGroup = 7B2BBC721C779D710067B71D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 7B2BBC7F1C779D720067B71D /* Tests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 7B2BBC7E1C779D720067B71D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 7B2BBC7C1C779D720067B71D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 7B80C4001C77A67B003CECC7 /* Heap.swift in Sources */, + 7B80C3FE1C77A65E003CECC7 /* PriorityQueueTests.swift in Sources */, + 7B80C3FC1C77A658003CECC7 /* PriorityQueue.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 7B2BBC871C779D720067B71D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 7B2BBC881C779D720067B71D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + }; + name = Release; + }; + 7B2BBC8D1C779D720067B71D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 7B2BBC8E1C779D720067B71D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7B2BBC871C779D720067B71D /* Debug */, + 7B2BBC881C779D720067B71D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7B2BBC8D1C779D720067B71D /* Debug */, + 7B2BBC8E1C779D720067B71D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 7B2BBC691C779D710067B71D /* Project object */; +} diff --git a/Queue/Queue Tests/Queue.xcodeproj/project.pbxproj b/Queue/Queue Tests/Queue.xcodeproj/project.pbxproj deleted file mode 100644 index 5e2275234..000000000 --- a/Queue/Queue Tests/Queue.xcodeproj/project.pbxproj +++ /dev/null @@ -1,394 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 7B18E01A1C5BF7A1005A2B8E /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B18E0191C5BF7A1005A2B8E /* AppDelegate.swift */; }; - 7B18E01C1C5BF7A1005A2B8E /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7B18E01B1C5BF7A1005A2B8E /* Assets.xcassets */; }; - 7B18E01F1C5BF7A1005A2B8E /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7B18E01D1C5BF7A1005A2B8E /* MainMenu.xib */; }; - 7B18E02A1C5BF7A1005A2B8E /* QueueTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B18E0291C5BF7A1005A2B8E /* QueueTests.swift */; }; - 7B18E0351C5BF7C2005A2B8E /* Queue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B18E0341C5BF7C2005A2B8E /* Queue.swift */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 7B18E0261C5BF7A1005A2B8E /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 7B18E00E1C5BF7A1005A2B8E /* Project object */; - proxyType = 1; - remoteGlobalIDString = 7B18E0151C5BF7A1005A2B8E; - remoteInfo = Queue; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXFileReference section */ - 7B18E0161C5BF7A1005A2B8E /* Queue.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Queue.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 7B18E0191C5BF7A1005A2B8E /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 7B18E01B1C5BF7A1005A2B8E /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - 7B18E01E1C5BF7A1005A2B8E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; - 7B18E0201C5BF7A1005A2B8E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 7B18E0251C5BF7A1005A2B8E /* QueueTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = QueueTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 7B18E0291C5BF7A1005A2B8E /* QueueTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QueueTests.swift; sourceTree = ""; }; - 7B18E02B1C5BF7A1005A2B8E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 7B18E0341C5BF7C2005A2B8E /* Queue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Queue.swift; path = ../../Queue.swift; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 7B18E0131C5BF7A1005A2B8E /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 7B18E0221C5BF7A1005A2B8E /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 7B18E00D1C5BF7A1005A2B8E = { - isa = PBXGroup; - children = ( - 7B18E0181C5BF7A1005A2B8E /* Queue */, - 7B18E0281C5BF7A1005A2B8E /* QueueTests */, - 7B18E0171C5BF7A1005A2B8E /* Products */, - ); - sourceTree = ""; - }; - 7B18E0171C5BF7A1005A2B8E /* Products */ = { - isa = PBXGroup; - children = ( - 7B18E0161C5BF7A1005A2B8E /* Queue.app */, - 7B18E0251C5BF7A1005A2B8E /* QueueTests.xctest */, - ); - name = Products; - sourceTree = ""; - }; - 7B18E0181C5BF7A1005A2B8E /* Queue */ = { - isa = PBXGroup; - children = ( - 7B18E0191C5BF7A1005A2B8E /* AppDelegate.swift */, - 7B18E01B1C5BF7A1005A2B8E /* Assets.xcassets */, - 7B18E0201C5BF7A1005A2B8E /* Info.plist */, - 7B18E01D1C5BF7A1005A2B8E /* MainMenu.xib */, - 7B18E0341C5BF7C2005A2B8E /* Queue.swift */, - ); - path = Queue; - sourceTree = ""; - }; - 7B18E0281C5BF7A1005A2B8E /* QueueTests */ = { - isa = PBXGroup; - children = ( - 7B18E0291C5BF7A1005A2B8E /* QueueTests.swift */, - 7B18E02B1C5BF7A1005A2B8E /* Info.plist */, - ); - path = QueueTests; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 7B18E0151C5BF7A1005A2B8E /* Queue */ = { - isa = PBXNativeTarget; - buildConfigurationList = 7B18E02E1C5BF7A1005A2B8E /* Build configuration list for PBXNativeTarget "Queue" */; - buildPhases = ( - 7B18E0121C5BF7A1005A2B8E /* Sources */, - 7B18E0131C5BF7A1005A2B8E /* Frameworks */, - 7B18E0141C5BF7A1005A2B8E /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = Queue; - productName = Queue; - productReference = 7B18E0161C5BF7A1005A2B8E /* Queue.app */; - productType = "com.apple.product-type.application"; - }; - 7B18E0241C5BF7A1005A2B8E /* QueueTests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 7B18E0311C5BF7A1005A2B8E /* Build configuration list for PBXNativeTarget "QueueTests" */; - buildPhases = ( - 7B18E0211C5BF7A1005A2B8E /* Sources */, - 7B18E0221C5BF7A1005A2B8E /* Frameworks */, - 7B18E0231C5BF7A1005A2B8E /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - 7B18E0271C5BF7A1005A2B8E /* PBXTargetDependency */, - ); - name = QueueTests; - productName = QueueTests; - productReference = 7B18E0251C5BF7A1005A2B8E /* QueueTests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 7B18E00E1C5BF7A1005A2B8E /* Project object */ = { - isa = PBXProject; - attributes = { - LastSwiftUpdateCheck = 0720; - LastUpgradeCheck = 0720; - ORGANIZATIONNAME = "Swift Algorithm Club"; - TargetAttributes = { - 7B18E0151C5BF7A1005A2B8E = { - CreatedOnToolsVersion = 7.2; - }; - 7B18E0241C5BF7A1005A2B8E = { - CreatedOnToolsVersion = 7.2; - TestTargetID = 7B18E0151C5BF7A1005A2B8E; - }; - }; - }; - buildConfigurationList = 7B18E0111C5BF7A1005A2B8E /* Build configuration list for PBXProject "Queue" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 7B18E00D1C5BF7A1005A2B8E; - productRefGroup = 7B18E0171C5BF7A1005A2B8E /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 7B18E0151C5BF7A1005A2B8E /* Queue */, - 7B18E0241C5BF7A1005A2B8E /* QueueTests */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 7B18E0141C5BF7A1005A2B8E /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 7B18E01C1C5BF7A1005A2B8E /* Assets.xcassets in Resources */, - 7B18E01F1C5BF7A1005A2B8E /* MainMenu.xib in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 7B18E0231C5BF7A1005A2B8E /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 7B18E0121C5BF7A1005A2B8E /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 7B18E01A1C5BF7A1005A2B8E /* AppDelegate.swift in Sources */, - 7B18E0351C5BF7C2005A2B8E /* Queue.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 7B18E0211C5BF7A1005A2B8E /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 7B18E02A1C5BF7A1005A2B8E /* QueueTests.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 7B18E0271C5BF7A1005A2B8E /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 7B18E0151C5BF7A1005A2B8E /* Queue */; - targetProxy = 7B18E0261C5BF7A1005A2B8E /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin PBXVariantGroup section */ - 7B18E01D1C5BF7A1005A2B8E /* MainMenu.xib */ = { - isa = PBXVariantGroup; - children = ( - 7B18E01E1C5BF7A1005A2B8E /* Base */, - ); - name = MainMenu.xib; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 7B18E02C1C5BF7A1005A2B8E /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "-"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.11; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = macosx; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - }; - name = Debug; - }; - 7B18E02D1C5BF7A1005A2B8E /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "-"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.11; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = macosx; - }; - name = Release; - }; - 7B18E02F1C5BF7A1005A2B8E /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = Queue/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Queue; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 7B18E0301C5BF7A1005A2B8E /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = Queue/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Queue; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - 7B18E0321C5BF7A1005A2B8E /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = QueueTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.QueueTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Queue.app/Contents/MacOS/Queue"; - }; - name = Debug; - }; - 7B18E0331C5BF7A1005A2B8E /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = QueueTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.QueueTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Queue.app/Contents/MacOS/Queue"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 7B18E0111C5BF7A1005A2B8E /* Build configuration list for PBXProject "Queue" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 7B18E02C1C5BF7A1005A2B8E /* Debug */, - 7B18E02D1C5BF7A1005A2B8E /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 7B18E02E1C5BF7A1005A2B8E /* Build configuration list for PBXNativeTarget "Queue" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 7B18E02F1C5BF7A1005A2B8E /* Debug */, - 7B18E0301C5BF7A1005A2B8E /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 7B18E0311C5BF7A1005A2B8E /* Build configuration list for PBXNativeTarget "QueueTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 7B18E0321C5BF7A1005A2B8E /* Debug */, - 7B18E0331C5BF7A1005A2B8E /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 7B18E00E1C5BF7A1005A2B8E /* Project object */; -} diff --git a/Queue/Queue Tests/Queue/AppDelegate.swift b/Queue/Queue Tests/Queue/AppDelegate.swift deleted file mode 100644 index 307e0984f..000000000 --- a/Queue/Queue Tests/Queue/AppDelegate.swift +++ /dev/null @@ -1,27 +0,0 @@ -// -// AppDelegate.swift -// Queue -// -// Created by Matthijs Hollemans on 29-01-16. -// Copyright © 2016 Swift Algorithm Club. All rights reserved. -// - -import Cocoa - -@NSApplicationMain -class AppDelegate: NSObject, NSApplicationDelegate { - - @IBOutlet weak var window: NSWindow! - - - func applicationDidFinishLaunching(aNotification: NSNotification) { - // Insert code here to initialize your application - } - - func applicationWillTerminate(aNotification: NSNotification) { - // Insert code here to tear down your application - } - - -} - diff --git a/Queue/Queue Tests/Queue/Assets.xcassets/AppIcon.appiconset/Contents.json b/Queue/Queue Tests/Queue/Assets.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index 2db2b1c7c..000000000 --- a/Queue/Queue Tests/Queue/Assets.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "images" : [ - { - "idiom" : "mac", - "size" : "16x16", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "16x16", - "scale" : "2x" - }, - { - "idiom" : "mac", - "size" : "32x32", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "32x32", - "scale" : "2x" - }, - { - "idiom" : "mac", - "size" : "128x128", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "128x128", - "scale" : "2x" - }, - { - "idiom" : "mac", - "size" : "256x256", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "256x256", - "scale" : "2x" - }, - { - "idiom" : "mac", - "size" : "512x512", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "512x512", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/Queue/Queue Tests/Queue/Base.lproj/MainMenu.xib b/Queue/Queue Tests/Queue/Base.lproj/MainMenu.xib deleted file mode 100644 index fbacc16b3..000000000 --- a/Queue/Queue Tests/Queue/Base.lproj/MainMenu.xib +++ /dev/null @@ -1,680 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Default - - - - - - - Left to Right - - - - - - - Right to Left - - - - - - - - - - - Default - - - - - - - Left to Right - - - - - - - Right to Left - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Queue/Queue Tests/Queue/Info.plist b/Queue/Queue Tests/Queue/Info.plist deleted file mode 100644 index 0dca3caa8..000000000 --- a/Queue/Queue Tests/Queue/Info.plist +++ /dev/null @@ -1,34 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIconFile - - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - LSMinimumSystemVersion - $(MACOSX_DEPLOYMENT_TARGET) - NSHumanReadableCopyright - Copyright © 2016 Swift Algorithm Club. All rights reserved. - NSMainNibFile - MainMenu - NSPrincipalClass - NSApplication - - diff --git a/Queue/Queue Tests/QueueTests/Info.plist b/Queue/Tests/Info.plist similarity index 100% rename from Queue/Queue Tests/QueueTests/Info.plist rename to Queue/Tests/Info.plist diff --git a/Queue/Queue Tests/QueueTests/QueueTests.swift b/Queue/Tests/QueueTests.swift similarity index 98% rename from Queue/Queue Tests/QueueTests/QueueTests.swift rename to Queue/Tests/QueueTests.swift index 1ffea7468..7406f8d35 100755 --- a/Queue/Queue Tests/QueueTests/QueueTests.swift +++ b/Queue/Tests/QueueTests.swift @@ -1,6 +1,5 @@ import Foundation import XCTest -@testable import Queue class QueueTest: XCTestCase { func testEmpty() { diff --git a/Queue/Tests/Tests.xcodeproj/project.pbxproj b/Queue/Tests/Tests.xcodeproj/project.pbxproj new file mode 100644 index 000000000..83e3fc523 --- /dev/null +++ b/Queue/Tests/Tests.xcodeproj/project.pbxproj @@ -0,0 +1,261 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 7B80C4021C77A6BF003CECC7 /* Queue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C4011C77A6BF003CECC7 /* Queue.swift */; }; + 7B80C4041C77A6C5003CECC7 /* QueueTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C4031C77A6C5003CECC7 /* QueueTests.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 7B2BBC801C779D720067B71D /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 7B2BBC941C779E7B0067B71D /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; + 7B80C4011C77A6BF003CECC7 /* Queue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Queue.swift; path = ../Queue.swift; sourceTree = SOURCE_ROOT; }; + 7B80C4031C77A6C5003CECC7 /* QueueTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QueueTests.swift; sourceTree = SOURCE_ROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 7B2BBC7D1C779D720067B71D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 7B2BBC681C779D710067B71D = { + isa = PBXGroup; + children = ( + 7B2BBC831C779D720067B71D /* Tests */, + 7B2BBC721C779D710067B71D /* Products */, + ); + sourceTree = ""; + }; + 7B2BBC721C779D710067B71D /* Products */ = { + isa = PBXGroup; + children = ( + 7B2BBC801C779D720067B71D /* Tests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 7B2BBC831C779D720067B71D /* Tests */ = { + isa = PBXGroup; + children = ( + 7B80C4011C77A6BF003CECC7 /* Queue.swift */, + 7B80C4031C77A6C5003CECC7 /* QueueTests.swift */, + 7B2BBC941C779E7B0067B71D /* Info.plist */, + ); + name = Tests; + path = TestsTests; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 7B2BBC7F1C779D720067B71D /* Tests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */; + buildPhases = ( + 7B2BBC7C1C779D720067B71D /* Sources */, + 7B2BBC7D1C779D720067B71D /* Frameworks */, + 7B2BBC7E1C779D720067B71D /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Tests; + productName = TestsTests; + productReference = 7B2BBC801C779D720067B71D /* Tests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 7B2BBC691C779D710067B71D /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0720; + LastUpgradeCheck = 0720; + ORGANIZATIONNAME = "Swift Algorithm Club"; + TargetAttributes = { + 7B2BBC7F1C779D720067B71D = { + CreatedOnToolsVersion = 7.2; + }; + }; + }; + buildConfigurationList = 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 7B2BBC681C779D710067B71D; + productRefGroup = 7B2BBC721C779D710067B71D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 7B2BBC7F1C779D720067B71D /* Tests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 7B2BBC7E1C779D720067B71D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 7B2BBC7C1C779D720067B71D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 7B80C4021C77A6BF003CECC7 /* Queue.swift in Sources */, + 7B80C4041C77A6C5003CECC7 /* QueueTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 7B2BBC871C779D720067B71D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 7B2BBC881C779D720067B71D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + }; + name = Release; + }; + 7B2BBC8D1C779D720067B71D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 7B2BBC8E1C779D720067B71D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7B2BBC871C779D720067B71D /* Debug */, + 7B2BBC881C779D720067B71D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7B2BBC8D1C779D720067B71D /* Debug */, + 7B2BBC8E1C779D720067B71D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 7B2BBC691C779D710067B71D /* Project object */; +} diff --git a/Quicksort/Quicksort Tests/Quicksort.xcodeproj/project.pbxproj b/Quicksort/Quicksort Tests/Quicksort.xcodeproj/project.pbxproj deleted file mode 100644 index 9737ad3b4..000000000 --- a/Quicksort/Quicksort Tests/Quicksort.xcodeproj/project.pbxproj +++ /dev/null @@ -1,398 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 7B18E06C1C5BF86E005A2B8E /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B18E06B1C5BF86E005A2B8E /* AppDelegate.swift */; }; - 7B18E06E1C5BF86E005A2B8E /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7B18E06D1C5BF86E005A2B8E /* Assets.xcassets */; }; - 7B18E0711C5BF86E005A2B8E /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7B18E06F1C5BF86E005A2B8E /* MainMenu.xib */; }; - 7B18E07C1C5BF86E005A2B8E /* QuicksortTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B18E07B1C5BF86E005A2B8E /* QuicksortTests.swift */; }; - 7B18E0871C5BF8F3005A2B8E /* Quicksort.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B18E0861C5BF8F3005A2B8E /* Quicksort.swift */; }; - 7B18E0891C5BF92B005A2B8E /* SortingTestHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B18E0881C5BF92B005A2B8E /* SortingTestHelpers.swift */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 7B18E0781C5BF86E005A2B8E /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 7B18E0601C5BF86E005A2B8E /* Project object */; - proxyType = 1; - remoteGlobalIDString = 7B18E0671C5BF86E005A2B8E; - remoteInfo = Quicksort; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXFileReference section */ - 7B18E0681C5BF86E005A2B8E /* Quicksort.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Quicksort.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 7B18E06B1C5BF86E005A2B8E /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 7B18E06D1C5BF86E005A2B8E /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - 7B18E0701C5BF86E005A2B8E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; - 7B18E0721C5BF86E005A2B8E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 7B18E0771C5BF86E005A2B8E /* QuicksortTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = QuicksortTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 7B18E07B1C5BF86E005A2B8E /* QuicksortTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuicksortTests.swift; sourceTree = ""; }; - 7B18E07D1C5BF86E005A2B8E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 7B18E0861C5BF8F3005A2B8E /* Quicksort.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Quicksort.swift; path = ../../Quicksort.swift; sourceTree = ""; }; - 7B18E0881C5BF92B005A2B8E /* SortingTestHelpers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SortingTestHelpers.swift; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 7B18E0651C5BF86E005A2B8E /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 7B18E0741C5BF86E005A2B8E /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 7B18E05F1C5BF86E005A2B8E = { - isa = PBXGroup; - children = ( - 7B18E06A1C5BF86E005A2B8E /* Quicksort */, - 7B18E07A1C5BF86E005A2B8E /* QuicksortTests */, - 7B18E0691C5BF86E005A2B8E /* Products */, - ); - sourceTree = ""; - }; - 7B18E0691C5BF86E005A2B8E /* Products */ = { - isa = PBXGroup; - children = ( - 7B18E0681C5BF86E005A2B8E /* Quicksort.app */, - 7B18E0771C5BF86E005A2B8E /* QuicksortTests.xctest */, - ); - name = Products; - sourceTree = ""; - }; - 7B18E06A1C5BF86E005A2B8E /* Quicksort */ = { - isa = PBXGroup; - children = ( - 7B18E06B1C5BF86E005A2B8E /* AppDelegate.swift */, - 7B18E06D1C5BF86E005A2B8E /* Assets.xcassets */, - 7B18E0721C5BF86E005A2B8E /* Info.plist */, - 7B18E06F1C5BF86E005A2B8E /* MainMenu.xib */, - 7B18E0861C5BF8F3005A2B8E /* Quicksort.swift */, - ); - path = Quicksort; - sourceTree = ""; - }; - 7B18E07A1C5BF86E005A2B8E /* QuicksortTests */ = { - isa = PBXGroup; - children = ( - 7B18E07D1C5BF86E005A2B8E /* Info.plist */, - 7B18E07B1C5BF86E005A2B8E /* QuicksortTests.swift */, - 7B18E0881C5BF92B005A2B8E /* SortingTestHelpers.swift */, - ); - path = QuicksortTests; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 7B18E0671C5BF86E005A2B8E /* Quicksort */ = { - isa = PBXNativeTarget; - buildConfigurationList = 7B18E0801C5BF86E005A2B8E /* Build configuration list for PBXNativeTarget "Quicksort" */; - buildPhases = ( - 7B18E0641C5BF86E005A2B8E /* Sources */, - 7B18E0651C5BF86E005A2B8E /* Frameworks */, - 7B18E0661C5BF86E005A2B8E /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = Quicksort; - productName = Quicksort; - productReference = 7B18E0681C5BF86E005A2B8E /* Quicksort.app */; - productType = "com.apple.product-type.application"; - }; - 7B18E0761C5BF86E005A2B8E /* QuicksortTests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 7B18E0831C5BF86E005A2B8E /* Build configuration list for PBXNativeTarget "QuicksortTests" */; - buildPhases = ( - 7B18E0731C5BF86E005A2B8E /* Sources */, - 7B18E0741C5BF86E005A2B8E /* Frameworks */, - 7B18E0751C5BF86E005A2B8E /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - 7B18E0791C5BF86E005A2B8E /* PBXTargetDependency */, - ); - name = QuicksortTests; - productName = QuicksortTests; - productReference = 7B18E0771C5BF86E005A2B8E /* QuicksortTests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 7B18E0601C5BF86E005A2B8E /* Project object */ = { - isa = PBXProject; - attributes = { - LastSwiftUpdateCheck = 0720; - LastUpgradeCheck = 0720; - ORGANIZATIONNAME = "Swift Algorithm Club"; - TargetAttributes = { - 7B18E0671C5BF86E005A2B8E = { - CreatedOnToolsVersion = 7.2; - }; - 7B18E0761C5BF86E005A2B8E = { - CreatedOnToolsVersion = 7.2; - TestTargetID = 7B18E0671C5BF86E005A2B8E; - }; - }; - }; - buildConfigurationList = 7B18E0631C5BF86E005A2B8E /* Build configuration list for PBXProject "Quicksort" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 7B18E05F1C5BF86E005A2B8E; - productRefGroup = 7B18E0691C5BF86E005A2B8E /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 7B18E0671C5BF86E005A2B8E /* Quicksort */, - 7B18E0761C5BF86E005A2B8E /* QuicksortTests */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 7B18E0661C5BF86E005A2B8E /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 7B18E06E1C5BF86E005A2B8E /* Assets.xcassets in Resources */, - 7B18E0711C5BF86E005A2B8E /* MainMenu.xib in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 7B18E0751C5BF86E005A2B8E /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 7B18E0641C5BF86E005A2B8E /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 7B18E06C1C5BF86E005A2B8E /* AppDelegate.swift in Sources */, - 7B18E0871C5BF8F3005A2B8E /* Quicksort.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 7B18E0731C5BF86E005A2B8E /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 7B18E0891C5BF92B005A2B8E /* SortingTestHelpers.swift in Sources */, - 7B18E07C1C5BF86E005A2B8E /* QuicksortTests.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 7B18E0791C5BF86E005A2B8E /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 7B18E0671C5BF86E005A2B8E /* Quicksort */; - targetProxy = 7B18E0781C5BF86E005A2B8E /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin PBXVariantGroup section */ - 7B18E06F1C5BF86E005A2B8E /* MainMenu.xib */ = { - isa = PBXVariantGroup; - children = ( - 7B18E0701C5BF86E005A2B8E /* Base */, - ); - name = MainMenu.xib; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 7B18E07E1C5BF86E005A2B8E /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "-"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.11; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = macosx; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - }; - name = Debug; - }; - 7B18E07F1C5BF86E005A2B8E /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "-"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.11; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = macosx; - }; - name = Release; - }; - 7B18E0811C5BF86E005A2B8E /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = Quicksort/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Quicksort; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 7B18E0821C5BF86E005A2B8E /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = Quicksort/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Quicksort; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - 7B18E0841C5BF86E005A2B8E /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = QuicksortTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.QuicksortTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Quicksort.app/Contents/MacOS/Quicksort"; - }; - name = Debug; - }; - 7B18E0851C5BF86E005A2B8E /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = QuicksortTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.QuicksortTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Quicksort.app/Contents/MacOS/Quicksort"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 7B18E0631C5BF86E005A2B8E /* Build configuration list for PBXProject "Quicksort" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 7B18E07E1C5BF86E005A2B8E /* Debug */, - 7B18E07F1C5BF86E005A2B8E /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 7B18E0801C5BF86E005A2B8E /* Build configuration list for PBXNativeTarget "Quicksort" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 7B18E0811C5BF86E005A2B8E /* Debug */, - 7B18E0821C5BF86E005A2B8E /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 7B18E0831C5BF86E005A2B8E /* Build configuration list for PBXNativeTarget "QuicksortTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 7B18E0841C5BF86E005A2B8E /* Debug */, - 7B18E0851C5BF86E005A2B8E /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 7B18E0601C5BF86E005A2B8E /* Project object */; -} diff --git a/Quicksort/Quicksort Tests/Quicksort/AppDelegate.swift b/Quicksort/Quicksort Tests/Quicksort/AppDelegate.swift deleted file mode 100644 index 633208e7b..000000000 --- a/Quicksort/Quicksort Tests/Quicksort/AppDelegate.swift +++ /dev/null @@ -1,27 +0,0 @@ -// -// AppDelegate.swift -// Quicksort -// -// Created by Matthijs Hollemans on 29-01-16. -// Copyright © 2016 Swift Algorithm Club. All rights reserved. -// - -import Cocoa - -@NSApplicationMain -class AppDelegate: NSObject, NSApplicationDelegate { - - @IBOutlet weak var window: NSWindow! - - - func applicationDidFinishLaunching(aNotification: NSNotification) { - // Insert code here to initialize your application - } - - func applicationWillTerminate(aNotification: NSNotification) { - // Insert code here to tear down your application - } - - -} - diff --git a/Quicksort/Quicksort Tests/Quicksort/Assets.xcassets/AppIcon.appiconset/Contents.json b/Quicksort/Quicksort Tests/Quicksort/Assets.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index 2db2b1c7c..000000000 --- a/Quicksort/Quicksort Tests/Quicksort/Assets.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "images" : [ - { - "idiom" : "mac", - "size" : "16x16", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "16x16", - "scale" : "2x" - }, - { - "idiom" : "mac", - "size" : "32x32", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "32x32", - "scale" : "2x" - }, - { - "idiom" : "mac", - "size" : "128x128", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "128x128", - "scale" : "2x" - }, - { - "idiom" : "mac", - "size" : "256x256", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "256x256", - "scale" : "2x" - }, - { - "idiom" : "mac", - "size" : "512x512", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "512x512", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/Quicksort/Quicksort Tests/Quicksort/Base.lproj/MainMenu.xib b/Quicksort/Quicksort Tests/Quicksort/Base.lproj/MainMenu.xib deleted file mode 100644 index 41a33b27a..000000000 --- a/Quicksort/Quicksort Tests/Quicksort/Base.lproj/MainMenu.xib +++ /dev/null @@ -1,680 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Default - - - - - - - Left to Right - - - - - - - Right to Left - - - - - - - - - - - Default - - - - - - - Left to Right - - - - - - - Right to Left - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Quicksort/Quicksort Tests/Quicksort/Info.plist b/Quicksort/Quicksort Tests/Quicksort/Info.plist deleted file mode 100644 index 0dca3caa8..000000000 --- a/Quicksort/Quicksort Tests/Quicksort/Info.plist +++ /dev/null @@ -1,34 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIconFile - - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - LSMinimumSystemVersion - $(MACOSX_DEPLOYMENT_TARGET) - NSHumanReadableCopyright - Copyright © 2016 Swift Algorithm Club. All rights reserved. - NSMainNibFile - MainMenu - NSPrincipalClass - NSApplication - - diff --git a/Quicksort/Quicksort Tests/QuicksortTests/Info.plist b/Quicksort/Tests/Info.plist similarity index 100% rename from Quicksort/Quicksort Tests/QuicksortTests/Info.plist rename to Quicksort/Tests/Info.plist diff --git a/Quicksort/Quicksort Tests/QuicksortTests/QuicksortTests.swift b/Quicksort/Tests/QuicksortTests.swift similarity index 96% rename from Quicksort/Quicksort Tests/QuicksortTests/QuicksortTests.swift rename to Quicksort/Tests/QuicksortTests.swift index 215991e98..ef95f1095 100644 --- a/Quicksort/Quicksort Tests/QuicksortTests/QuicksortTests.swift +++ b/Quicksort/Tests/QuicksortTests.swift @@ -1,5 +1,4 @@ import XCTest -@testable import Quicksort class QuicksortTests: XCTestCase { func testQuicksort() { diff --git a/Quicksort/Quicksort Tests/QuicksortTests/SortingTestHelpers.swift b/Quicksort/Tests/SortingTestHelpers.swift similarity index 100% rename from Quicksort/Quicksort Tests/QuicksortTests/SortingTestHelpers.swift rename to Quicksort/Tests/SortingTestHelpers.swift diff --git a/Quicksort/Tests/Tests.xcodeproj/project.pbxproj b/Quicksort/Tests/Tests.xcodeproj/project.pbxproj new file mode 100644 index 000000000..8aecb59f8 --- /dev/null +++ b/Quicksort/Tests/Tests.xcodeproj/project.pbxproj @@ -0,0 +1,265 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 7B80C3E61C77A4CA003CECC7 /* Quicksort.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C3E51C77A4CA003CECC7 /* Quicksort.swift */; }; + 7B80C3E91C77A4D0003CECC7 /* QuicksortTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C3E71C77A4D0003CECC7 /* QuicksortTests.swift */; }; + 7B80C3EA1C77A4D0003CECC7 /* SortingTestHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C3E81C77A4D0003CECC7 /* SortingTestHelpers.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 7B2BBC801C779D720067B71D /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 7B2BBC941C779E7B0067B71D /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; + 7B80C3E51C77A4CA003CECC7 /* Quicksort.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Quicksort.swift; path = ../Quicksort.swift; sourceTree = SOURCE_ROOT; }; + 7B80C3E71C77A4D0003CECC7 /* QuicksortTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QuicksortTests.swift; sourceTree = SOURCE_ROOT; }; + 7B80C3E81C77A4D0003CECC7 /* SortingTestHelpers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SortingTestHelpers.swift; sourceTree = SOURCE_ROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 7B2BBC7D1C779D720067B71D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 7B2BBC681C779D710067B71D = { + isa = PBXGroup; + children = ( + 7B2BBC831C779D720067B71D /* Tests */, + 7B2BBC721C779D710067B71D /* Products */, + ); + sourceTree = ""; + }; + 7B2BBC721C779D710067B71D /* Products */ = { + isa = PBXGroup; + children = ( + 7B2BBC801C779D720067B71D /* Tests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 7B2BBC831C779D720067B71D /* Tests */ = { + isa = PBXGroup; + children = ( + 7B80C3E51C77A4CA003CECC7 /* Quicksort.swift */, + 7B80C3E71C77A4D0003CECC7 /* QuicksortTests.swift */, + 7B80C3E81C77A4D0003CECC7 /* SortingTestHelpers.swift */, + 7B2BBC941C779E7B0067B71D /* Info.plist */, + ); + name = Tests; + path = TestsTests; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 7B2BBC7F1C779D720067B71D /* Tests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */; + buildPhases = ( + 7B2BBC7C1C779D720067B71D /* Sources */, + 7B2BBC7D1C779D720067B71D /* Frameworks */, + 7B2BBC7E1C779D720067B71D /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Tests; + productName = TestsTests; + productReference = 7B2BBC801C779D720067B71D /* Tests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 7B2BBC691C779D710067B71D /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0720; + LastUpgradeCheck = 0720; + ORGANIZATIONNAME = "Swift Algorithm Club"; + TargetAttributes = { + 7B2BBC7F1C779D720067B71D = { + CreatedOnToolsVersion = 7.2; + }; + }; + }; + buildConfigurationList = 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 7B2BBC681C779D710067B71D; + productRefGroup = 7B2BBC721C779D710067B71D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 7B2BBC7F1C779D720067B71D /* Tests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 7B2BBC7E1C779D720067B71D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 7B2BBC7C1C779D720067B71D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 7B80C3EA1C77A4D0003CECC7 /* SortingTestHelpers.swift in Sources */, + 7B80C3E61C77A4CA003CECC7 /* Quicksort.swift in Sources */, + 7B80C3E91C77A4D0003CECC7 /* QuicksortTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 7B2BBC871C779D720067B71D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 7B2BBC881C779D720067B71D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + }; + name = Release; + }; + 7B2BBC8D1C779D720067B71D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 7B2BBC8E1C779D720067B71D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7B2BBC871C779D720067B71D /* Debug */, + 7B2BBC881C779D720067B71D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7B2BBC8D1C779D720067B71D /* Debug */, + 7B2BBC8E1C779D720067B71D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 7B2BBC691C779D710067B71D /* Project object */; +} diff --git a/Run-Length Encoding/RLE Tests/RLE.xcodeproj/project.pbxproj b/Run-Length Encoding/RLE Tests/RLE.xcodeproj/project.pbxproj deleted file mode 100644 index 394f2c196..000000000 --- a/Run-Length Encoding/RLE Tests/RLE.xcodeproj/project.pbxproj +++ /dev/null @@ -1,394 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 7B1BFA9B1C6E5CD70051C9A4 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B1BFA9A1C6E5CD70051C9A4 /* AppDelegate.swift */; }; - 7B1BFA9D1C6E5CD70051C9A4 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7B1BFA9C1C6E5CD70051C9A4 /* Assets.xcassets */; }; - 7B1BFAA01C6E5CD70051C9A4 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7B1BFA9E1C6E5CD70051C9A4 /* MainMenu.xib */; }; - 7B1BFAAB1C6E5CD70051C9A4 /* RLETests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B1BFAAA1C6E5CD70051C9A4 /* RLETests.swift */; }; - 7B1BFAB61C6E5D000051C9A4 /* RLE.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B1BFAB51C6E5D000051C9A4 /* RLE.swift */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 7B1BFAA71C6E5CD70051C9A4 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 7B1BFA8F1C6E5CD70051C9A4 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 7B1BFA961C6E5CD70051C9A4; - remoteInfo = RLE; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXFileReference section */ - 7B1BFA971C6E5CD70051C9A4 /* RLE.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = RLE.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 7B1BFA9A1C6E5CD70051C9A4 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 7B1BFA9C1C6E5CD70051C9A4 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - 7B1BFA9F1C6E5CD70051C9A4 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; - 7B1BFAA11C6E5CD70051C9A4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 7B1BFAA61C6E5CD70051C9A4 /* RLETests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RLETests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 7B1BFAAA1C6E5CD70051C9A4 /* RLETests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RLETests.swift; sourceTree = ""; }; - 7B1BFAAC1C6E5CD70051C9A4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 7B1BFAB51C6E5D000051C9A4 /* RLE.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RLE.swift; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 7B1BFA941C6E5CD70051C9A4 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 7B1BFAA31C6E5CD70051C9A4 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 7B1BFA8E1C6E5CD70051C9A4 = { - isa = PBXGroup; - children = ( - 7B1BFA991C6E5CD70051C9A4 /* RLE */, - 7B1BFAA91C6E5CD70051C9A4 /* RLETests */, - 7B1BFA981C6E5CD70051C9A4 /* Products */, - ); - sourceTree = ""; - }; - 7B1BFA981C6E5CD70051C9A4 /* Products */ = { - isa = PBXGroup; - children = ( - 7B1BFA971C6E5CD70051C9A4 /* RLE.app */, - 7B1BFAA61C6E5CD70051C9A4 /* RLETests.xctest */, - ); - name = Products; - sourceTree = ""; - }; - 7B1BFA991C6E5CD70051C9A4 /* RLE */ = { - isa = PBXGroup; - children = ( - 7B1BFA9A1C6E5CD70051C9A4 /* AppDelegate.swift */, - 7B1BFA9C1C6E5CD70051C9A4 /* Assets.xcassets */, - 7B1BFAA11C6E5CD70051C9A4 /* Info.plist */, - 7B1BFA9E1C6E5CD70051C9A4 /* MainMenu.xib */, - 7B1BFAB51C6E5D000051C9A4 /* RLE.swift */, - ); - path = RLE; - sourceTree = ""; - }; - 7B1BFAA91C6E5CD70051C9A4 /* RLETests */ = { - isa = PBXGroup; - children = ( - 7B1BFAAA1C6E5CD70051C9A4 /* RLETests.swift */, - 7B1BFAAC1C6E5CD70051C9A4 /* Info.plist */, - ); - path = RLETests; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 7B1BFA961C6E5CD70051C9A4 /* RLE */ = { - isa = PBXNativeTarget; - buildConfigurationList = 7B1BFAAF1C6E5CD70051C9A4 /* Build configuration list for PBXNativeTarget "RLE" */; - buildPhases = ( - 7B1BFA931C6E5CD70051C9A4 /* Sources */, - 7B1BFA941C6E5CD70051C9A4 /* Frameworks */, - 7B1BFA951C6E5CD70051C9A4 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = RLE; - productName = RLE; - productReference = 7B1BFA971C6E5CD70051C9A4 /* RLE.app */; - productType = "com.apple.product-type.application"; - }; - 7B1BFAA51C6E5CD70051C9A4 /* RLETests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 7B1BFAB21C6E5CD70051C9A4 /* Build configuration list for PBXNativeTarget "RLETests" */; - buildPhases = ( - 7B1BFAA21C6E5CD70051C9A4 /* Sources */, - 7B1BFAA31C6E5CD70051C9A4 /* Frameworks */, - 7B1BFAA41C6E5CD70051C9A4 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - 7B1BFAA81C6E5CD70051C9A4 /* PBXTargetDependency */, - ); - name = RLETests; - productName = RLETests; - productReference = 7B1BFAA61C6E5CD70051C9A4 /* RLETests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 7B1BFA8F1C6E5CD70051C9A4 /* Project object */ = { - isa = PBXProject; - attributes = { - LastSwiftUpdateCheck = 0720; - LastUpgradeCheck = 0720; - ORGANIZATIONNAME = "Swift Algorithm Club"; - TargetAttributes = { - 7B1BFA961C6E5CD70051C9A4 = { - CreatedOnToolsVersion = 7.2; - }; - 7B1BFAA51C6E5CD70051C9A4 = { - CreatedOnToolsVersion = 7.2; - TestTargetID = 7B1BFA961C6E5CD70051C9A4; - }; - }; - }; - buildConfigurationList = 7B1BFA921C6E5CD70051C9A4 /* Build configuration list for PBXProject "RLE" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 7B1BFA8E1C6E5CD70051C9A4; - productRefGroup = 7B1BFA981C6E5CD70051C9A4 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 7B1BFA961C6E5CD70051C9A4 /* RLE */, - 7B1BFAA51C6E5CD70051C9A4 /* RLETests */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 7B1BFA951C6E5CD70051C9A4 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 7B1BFA9D1C6E5CD70051C9A4 /* Assets.xcassets in Resources */, - 7B1BFAA01C6E5CD70051C9A4 /* MainMenu.xib in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 7B1BFAA41C6E5CD70051C9A4 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 7B1BFA931C6E5CD70051C9A4 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 7B1BFA9B1C6E5CD70051C9A4 /* AppDelegate.swift in Sources */, - 7B1BFAB61C6E5D000051C9A4 /* RLE.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 7B1BFAA21C6E5CD70051C9A4 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 7B1BFAAB1C6E5CD70051C9A4 /* RLETests.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 7B1BFAA81C6E5CD70051C9A4 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 7B1BFA961C6E5CD70051C9A4 /* RLE */; - targetProxy = 7B1BFAA71C6E5CD70051C9A4 /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin PBXVariantGroup section */ - 7B1BFA9E1C6E5CD70051C9A4 /* MainMenu.xib */ = { - isa = PBXVariantGroup; - children = ( - 7B1BFA9F1C6E5CD70051C9A4 /* Base */, - ); - name = MainMenu.xib; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 7B1BFAAD1C6E5CD70051C9A4 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "-"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.11; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = macosx; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - }; - name = Debug; - }; - 7B1BFAAE1C6E5CD70051C9A4 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "-"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.11; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = macosx; - }; - name = Release; - }; - 7B1BFAB01C6E5CD70051C9A4 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = RLE/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.RLE; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 7B1BFAB11C6E5CD70051C9A4 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = RLE/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.RLE; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - 7B1BFAB31C6E5CD70051C9A4 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = RLETests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.RLETests; - PRODUCT_NAME = "$(TARGET_NAME)"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/RLE.app/Contents/MacOS/RLE"; - }; - name = Debug; - }; - 7B1BFAB41C6E5CD70051C9A4 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = RLETests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.RLETests; - PRODUCT_NAME = "$(TARGET_NAME)"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/RLE.app/Contents/MacOS/RLE"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 7B1BFA921C6E5CD70051C9A4 /* Build configuration list for PBXProject "RLE" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 7B1BFAAD1C6E5CD70051C9A4 /* Debug */, - 7B1BFAAE1C6E5CD70051C9A4 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 7B1BFAAF1C6E5CD70051C9A4 /* Build configuration list for PBXNativeTarget "RLE" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 7B1BFAB01C6E5CD70051C9A4 /* Debug */, - 7B1BFAB11C6E5CD70051C9A4 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 7B1BFAB21C6E5CD70051C9A4 /* Build configuration list for PBXNativeTarget "RLETests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 7B1BFAB31C6E5CD70051C9A4 /* Debug */, - 7B1BFAB41C6E5CD70051C9A4 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 7B1BFA8F1C6E5CD70051C9A4 /* Project object */; -} diff --git a/Run-Length Encoding/RLE Tests/RLE/AppDelegate.swift b/Run-Length Encoding/RLE Tests/RLE/AppDelegate.swift deleted file mode 100644 index 4ae9f8243..000000000 --- a/Run-Length Encoding/RLE Tests/RLE/AppDelegate.swift +++ /dev/null @@ -1,27 +0,0 @@ -// -// AppDelegate.swift -// RLE -// -// Created by Matthijs Hollemans on 12-02-16. -// Copyright © 2016 Swift Algorithm Club. All rights reserved. -// - -import Cocoa - -@NSApplicationMain -class AppDelegate: NSObject, NSApplicationDelegate { - - @IBOutlet weak var window: NSWindow! - - - func applicationDidFinishLaunching(aNotification: NSNotification) { - // Insert code here to initialize your application - } - - func applicationWillTerminate(aNotification: NSNotification) { - // Insert code here to tear down your application - } - - -} - diff --git a/Run-Length Encoding/RLE Tests/RLE/Assets.xcassets/AppIcon.appiconset/Contents.json b/Run-Length Encoding/RLE Tests/RLE/Assets.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index 2db2b1c7c..000000000 --- a/Run-Length Encoding/RLE Tests/RLE/Assets.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "images" : [ - { - "idiom" : "mac", - "size" : "16x16", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "16x16", - "scale" : "2x" - }, - { - "idiom" : "mac", - "size" : "32x32", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "32x32", - "scale" : "2x" - }, - { - "idiom" : "mac", - "size" : "128x128", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "128x128", - "scale" : "2x" - }, - { - "idiom" : "mac", - "size" : "256x256", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "256x256", - "scale" : "2x" - }, - { - "idiom" : "mac", - "size" : "512x512", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "512x512", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/Run-Length Encoding/RLE Tests/RLE/Base.lproj/MainMenu.xib b/Run-Length Encoding/RLE Tests/RLE/Base.lproj/MainMenu.xib deleted file mode 100644 index 6f60cc595..000000000 --- a/Run-Length Encoding/RLE Tests/RLE/Base.lproj/MainMenu.xib +++ /dev/null @@ -1,680 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Default - - - - - - - Left to Right - - - - - - - Right to Left - - - - - - - - - - - Default - - - - - - - Left to Right - - - - - - - Right to Left - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Run-Length Encoding/RLE Tests/RLE/Info.plist b/Run-Length Encoding/RLE Tests/RLE/Info.plist deleted file mode 100644 index 0dca3caa8..000000000 --- a/Run-Length Encoding/RLE Tests/RLE/Info.plist +++ /dev/null @@ -1,34 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIconFile - - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - LSMinimumSystemVersion - $(MACOSX_DEPLOYMENT_TARGET) - NSHumanReadableCopyright - Copyright © 2016 Swift Algorithm Club. All rights reserved. - NSMainNibFile - MainMenu - NSPrincipalClass - NSApplication - - diff --git a/Run-Length Encoding/RLE Tests/RLE/RLE.swift b/Run-Length Encoding/RLE Tests/RLE/RLE.swift deleted file mode 100644 index f26299cf1..000000000 --- a/Run-Length Encoding/RLE Tests/RLE/RLE.swift +++ /dev/null @@ -1,70 +0,0 @@ -import Foundation - -extension NSData { - /* - Compresses the NSData using run-length encoding. - */ - public func compressRLE() -> NSData { - let data = NSMutableData() - if length > 0 { - var ptr = UnsafePointer(bytes) - let end = ptr + length - - while ptr < end { - var count = 0 - var byte = ptr.memory - var next = byte - - // Is the next byte the same? Keep reading until we find a different - // value, or we reach the end of the data, or the run is 64 bytes. - while next == byte && ptr < end && count < 64 { - ptr = ptr.advancedBy(1) - next = ptr.memory - count += 1 - } - - if count > 1 || byte >= 192 { // byte run of up to 64 repeats - var size = 191 + UInt8(count) - data.appendBytes(&size, length: 1) - data.appendBytes(&byte, length: 1) - } else { // single byte between 0 and 192 - data.appendBytes(&byte, length: 1) - } - } - } - return data - } - - /* - Converts a run-length encoded NSData back to the original. - */ - public func decompressRLE() -> NSData { - let data = NSMutableData() - if length > 0 { - var ptr = UnsafePointer(bytes) - let end = ptr + length - - while ptr < end { - // Read the next byte. This is either a single value less than 192, - // or the start of a byte run. - var byte = ptr.memory - ptr = ptr.advancedBy(1) - - if byte < 192 { // single value - data.appendBytes(&byte, length: 1) - - } else if ptr < end { // byte run - // Read the actual data value. - var value = ptr.memory - ptr = ptr.advancedBy(1) - - // And write it out repeatedly. - for _ in 0 ..< byte - 191 { - data.appendBytes(&value, length: 1) - } - } - } - } - return data - } -} diff --git a/Run-Length Encoding/RLE.swift b/Run-Length Encoding/RLE.swift index ee25af997..f26299cf1 100644 --- a/Run-Length Encoding/RLE.swift +++ b/Run-Length Encoding/RLE.swift @@ -1,29 +1,6 @@ import Foundation extension NSData { - /* - Helper method that reads the next run of bytes. Returns the size of the - run (between 1 and 64), the byte value, and the updated read pointer. - */ - private func readRun(start start: UnsafePointer, end: UnsafePointer) -> (Int, UInt8, UnsafePointer) { - var ptr = start - var count = 0 - - // Read the current byte. - let previous = ptr.memory - var current = previous - - // Is the next byte the same? Then keep reading until we find another - // byte, or we reach the end of the data, or the run is 64 bytes. - while current == previous && ptr < end && count < 64 { - ptr = ptr.advancedBy(1) - current = ptr.memory - count += 1 - } - - return (count, previous, ptr) - } - /* Compresses the NSData using run-length encoding. */ @@ -34,27 +11,60 @@ extension NSData { let end = ptr + length while ptr < end { - var (count, byte, out) = readRun(start: ptr, end: end) + var count = 0 + var byte = ptr.memory + var next = byte + + // Is the next byte the same? Keep reading until we find a different + // value, or we reach the end of the data, or the run is 64 bytes. + while next == byte && ptr < end && count < 64 { + ptr = ptr.advancedBy(1) + next = ptr.memory + count += 1 + } - if count == 0 { // end-of-file - out = end - } else if count > 1 || byte >= 192 { // byte run, up to 64 repeats - var pair: [UInt8] = [191 + UInt8(count), byte] - data.appendBytes(&pair, length: 2) - } else { // single byte between 0 and 192 + if count > 1 || byte >= 192 { // byte run of up to 64 repeats + var size = 191 + UInt8(count) + data.appendBytes(&size, length: 1) + data.appendBytes(&byte, length: 1) + } else { // single byte between 0 and 192 data.appendBytes(&byte, length: 1) } - ptr = out } } return data } - /* Converts a run-length encoded NSData back to the original. */ public func decompressRLE() -> NSData { - return NSData() + let data = NSMutableData() + if length > 0 { + var ptr = UnsafePointer(bytes) + let end = ptr + length + + while ptr < end { + // Read the next byte. This is either a single value less than 192, + // or the start of a byte run. + var byte = ptr.memory + ptr = ptr.advancedBy(1) + + if byte < 192 { // single value + data.appendBytes(&byte, length: 1) + + } else if ptr < end { // byte run + // Read the actual data value. + var value = ptr.memory + ptr = ptr.advancedBy(1) + + // And write it out repeatedly. + for _ in 0 ..< byte - 191 { + data.appendBytes(&value, length: 1) + } + } + } + } + return data } } diff --git a/Run-Length Encoding/RLE Tests/RLETests/Info.plist b/Run-Length Encoding/Tests/Info.plist similarity index 100% rename from Run-Length Encoding/RLE Tests/RLETests/Info.plist rename to Run-Length Encoding/Tests/Info.plist diff --git a/Run-Length Encoding/RLE Tests/RLETests/RLETests.swift b/Run-Length Encoding/Tests/RLETests.swift similarity index 99% rename from Run-Length Encoding/RLE Tests/RLETests/RLETests.swift rename to Run-Length Encoding/Tests/RLETests.swift index 99616a8c2..a55f74fdc 100644 --- a/Run-Length Encoding/RLE Tests/RLETests/RLETests.swift +++ b/Run-Length Encoding/Tests/RLETests.swift @@ -1,5 +1,4 @@ import XCTest -@testable import RLE class RLETests: XCTestCase { private var showExtraOutput = false diff --git a/Run-Length Encoding/Tests/Tests.xcodeproj/project.pbxproj b/Run-Length Encoding/Tests/Tests.xcodeproj/project.pbxproj new file mode 100644 index 000000000..aae67b064 --- /dev/null +++ b/Run-Length Encoding/Tests/Tests.xcodeproj/project.pbxproj @@ -0,0 +1,261 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 7B80C4181C77A7F3003CECC7 /* RLE.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C4171C77A7F3003CECC7 /* RLE.swift */; }; + 7B80C41A1C77A7FA003CECC7 /* RLETests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C4191C77A7FA003CECC7 /* RLETests.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 7B2BBC801C779D720067B71D /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 7B2BBC941C779E7B0067B71D /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; + 7B80C4171C77A7F3003CECC7 /* RLE.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = RLE.swift; path = ../RLE.swift; sourceTree = SOURCE_ROOT; }; + 7B80C4191C77A7FA003CECC7 /* RLETests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RLETests.swift; sourceTree = SOURCE_ROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 7B2BBC7D1C779D720067B71D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 7B2BBC681C779D710067B71D = { + isa = PBXGroup; + children = ( + 7B2BBC831C779D720067B71D /* Tests */, + 7B2BBC721C779D710067B71D /* Products */, + ); + sourceTree = ""; + }; + 7B2BBC721C779D710067B71D /* Products */ = { + isa = PBXGroup; + children = ( + 7B2BBC801C779D720067B71D /* Tests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 7B2BBC831C779D720067B71D /* Tests */ = { + isa = PBXGroup; + children = ( + 7B80C4171C77A7F3003CECC7 /* RLE.swift */, + 7B80C4191C77A7FA003CECC7 /* RLETests.swift */, + 7B2BBC941C779E7B0067B71D /* Info.plist */, + ); + name = Tests; + path = TestsTests; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 7B2BBC7F1C779D720067B71D /* Tests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */; + buildPhases = ( + 7B2BBC7C1C779D720067B71D /* Sources */, + 7B2BBC7D1C779D720067B71D /* Frameworks */, + 7B2BBC7E1C779D720067B71D /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Tests; + productName = TestsTests; + productReference = 7B2BBC801C779D720067B71D /* Tests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 7B2BBC691C779D710067B71D /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0720; + LastUpgradeCheck = 0720; + ORGANIZATIONNAME = "Swift Algorithm Club"; + TargetAttributes = { + 7B2BBC7F1C779D720067B71D = { + CreatedOnToolsVersion = 7.2; + }; + }; + }; + buildConfigurationList = 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 7B2BBC681C779D710067B71D; + productRefGroup = 7B2BBC721C779D710067B71D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 7B2BBC7F1C779D720067B71D /* Tests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 7B2BBC7E1C779D720067B71D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 7B2BBC7C1C779D720067B71D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 7B80C4181C77A7F3003CECC7 /* RLE.swift in Sources */, + 7B80C41A1C77A7FA003CECC7 /* RLETests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 7B2BBC871C779D720067B71D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 7B2BBC881C779D720067B71D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + }; + name = Release; + }; + 7B2BBC8D1C779D720067B71D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 7B2BBC8E1C779D720067B71D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7B2BBC871C779D720067B71D /* Debug */, + 7B2BBC881C779D720067B71D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7B2BBC8D1C779D720067B71D /* Debug */, + 7B2BBC8E1C779D720067B71D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 7B2BBC691C779D710067B71D /* Project object */; +} diff --git a/Select Minimum Maximum/MinimumMaximumPairs.swift b/Select Minimum Maximum/MinimumMaximumPairs.swift index 537210058..5798e1f32 100644 --- a/Select Minimum Maximum/MinimumMaximumPairs.swift +++ b/Select Minimum Maximum/MinimumMaximumPairs.swift @@ -2,8 +2,7 @@ Finds the maximum and minimum value in an array in O(n) time. */ -func minimumMaximum(var array: [T]) -> (minimum: T, maximum: T)? -{ +func minimumMaximum(var array: [T]) -> (minimum: T, maximum: T)? { guard !array.isEmpty else { return nil } diff --git a/Select Minimum Maximum/SelectMinimumMaximum Tests/SelectMinimumMaximum.xcodeproj/project.pbxproj b/Select Minimum Maximum/SelectMinimumMaximum Tests/SelectMinimumMaximum.xcodeproj/project.pbxproj deleted file mode 100644 index dc319937a..000000000 --- a/Select Minimum Maximum/SelectMinimumMaximum Tests/SelectMinimumMaximum.xcodeproj/project.pbxproj +++ /dev/null @@ -1,393 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 7B18E0971C5BFA2E005A2B8E /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B18E0961C5BFA2E005A2B8E /* AppDelegate.swift */; }; - 7B18E0A71C5BFA2E005A2B8E /* SelectMinimumMaximumTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B18E0A61C5BFA2E005A2B8E /* SelectMinimumMaximumTests.swift */; }; - 838A4FB41C64AED00092AA8F /* TestHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 838A4FB31C64AED00092AA8F /* TestHelper.swift */; }; - 83F3255D1C64A0E700EB0421 /* Maximum.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83F3255A1C64A0E700EB0421 /* Maximum.swift */; }; - 83F3255E1C64A0E700EB0421 /* Minimum.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83F3255B1C64A0E700EB0421 /* Minimum.swift */; }; - 83F3255F1C64A0E700EB0421 /* MinimumMaximumPairs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83F3255C1C64A0E700EB0421 /* MinimumMaximumPairs.swift */; }; - 83F325611C64A3E000EB0421 /* MinimumTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83F325601C64A3E000EB0421 /* MinimumTests.swift */; }; - 83F325631C64A4D400EB0421 /* MaximumTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83F325621C64A4D400EB0421 /* MaximumTests.swift */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 7B18E0A31C5BFA2E005A2B8E /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 7B18E08B1C5BFA2E005A2B8E /* Project object */; - proxyType = 1; - remoteGlobalIDString = 7B18E0921C5BFA2E005A2B8E; - remoteInfo = SelectMinimumMaximum; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXFileReference section */ - 7B18E0931C5BFA2E005A2B8E /* SelectMinimumMaximum.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SelectMinimumMaximum.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 7B18E0961C5BFA2E005A2B8E /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 7B18E09D1C5BFA2E005A2B8E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 7B18E0A21C5BFA2E005A2B8E /* SelectMinimumMaximumTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SelectMinimumMaximumTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 7B18E0A61C5BFA2E005A2B8E /* SelectMinimumMaximumTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SelectMinimumMaximumTests.swift; sourceTree = ""; }; - 7B18E0A81C5BFA2E005A2B8E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 838A4FB31C64AED00092AA8F /* TestHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestHelper.swift; sourceTree = ""; }; - 83F3255A1C64A0E700EB0421 /* Maximum.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Maximum.swift; path = ../../Maximum.swift; sourceTree = ""; }; - 83F3255B1C64A0E700EB0421 /* Minimum.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Minimum.swift; path = ../../Minimum.swift; sourceTree = ""; }; - 83F3255C1C64A0E700EB0421 /* MinimumMaximumPairs.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MinimumMaximumPairs.swift; path = ../../MinimumMaximumPairs.swift; sourceTree = ""; }; - 83F325601C64A3E000EB0421 /* MinimumTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MinimumTests.swift; sourceTree = ""; }; - 83F325621C64A4D400EB0421 /* MaximumTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MaximumTests.swift; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 7B18E0901C5BFA2E005A2B8E /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 7B18E09F1C5BFA2E005A2B8E /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 7B18E08A1C5BFA2E005A2B8E = { - isa = PBXGroup; - children = ( - 7B18E0951C5BFA2E005A2B8E /* SelectMinimumMaximum */, - 7B18E0A51C5BFA2E005A2B8E /* SelectMinimumMaximumTests */, - 7B18E0941C5BFA2E005A2B8E /* Products */, - ); - sourceTree = ""; - }; - 7B18E0941C5BFA2E005A2B8E /* Products */ = { - isa = PBXGroup; - children = ( - 7B18E0931C5BFA2E005A2B8E /* SelectMinimumMaximum.app */, - 7B18E0A21C5BFA2E005A2B8E /* SelectMinimumMaximumTests.xctest */, - ); - name = Products; - sourceTree = ""; - }; - 7B18E0951C5BFA2E005A2B8E /* SelectMinimumMaximum */ = { - isa = PBXGroup; - children = ( - 7B18E0961C5BFA2E005A2B8E /* AppDelegate.swift */, - 83F3255A1C64A0E700EB0421 /* Maximum.swift */, - 83F3255B1C64A0E700EB0421 /* Minimum.swift */, - 83F3255C1C64A0E700EB0421 /* MinimumMaximumPairs.swift */, - 7B18E09D1C5BFA2E005A2B8E /* Info.plist */, - ); - path = SelectMinimumMaximum; - sourceTree = ""; - }; - 7B18E0A51C5BFA2E005A2B8E /* SelectMinimumMaximumTests */ = { - isa = PBXGroup; - children = ( - 7B18E0A81C5BFA2E005A2B8E /* Info.plist */, - 7B18E0A61C5BFA2E005A2B8E /* SelectMinimumMaximumTests.swift */, - 83F325601C64A3E000EB0421 /* MinimumTests.swift */, - 83F325621C64A4D400EB0421 /* MaximumTests.swift */, - 838A4FB31C64AED00092AA8F /* TestHelper.swift */, - ); - path = SelectMinimumMaximumTests; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 7B18E0921C5BFA2E005A2B8E /* SelectMinimumMaximum */ = { - isa = PBXNativeTarget; - buildConfigurationList = 7B18E0AB1C5BFA2E005A2B8E /* Build configuration list for PBXNativeTarget "SelectMinimumMaximum" */; - buildPhases = ( - 7B18E08F1C5BFA2E005A2B8E /* Sources */, - 7B18E0901C5BFA2E005A2B8E /* Frameworks */, - 7B18E0911C5BFA2E005A2B8E /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = SelectMinimumMaximum; - productName = SelectMinimumMaximum; - productReference = 7B18E0931C5BFA2E005A2B8E /* SelectMinimumMaximum.app */; - productType = "com.apple.product-type.application"; - }; - 7B18E0A11C5BFA2E005A2B8E /* SelectMinimumMaximumTests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 7B18E0AE1C5BFA2E005A2B8E /* Build configuration list for PBXNativeTarget "SelectMinimumMaximumTests" */; - buildPhases = ( - 7B18E09E1C5BFA2E005A2B8E /* Sources */, - 7B18E09F1C5BFA2E005A2B8E /* Frameworks */, - 7B18E0A01C5BFA2E005A2B8E /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - 7B18E0A41C5BFA2E005A2B8E /* PBXTargetDependency */, - ); - name = SelectMinimumMaximumTests; - productName = SelectMinimumMaximumTests; - productReference = 7B18E0A21C5BFA2E005A2B8E /* SelectMinimumMaximumTests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 7B18E08B1C5BFA2E005A2B8E /* Project object */ = { - isa = PBXProject; - attributes = { - LastSwiftUpdateCheck = 0720; - LastUpgradeCheck = 0720; - ORGANIZATIONNAME = "Swift Algorithm Club"; - TargetAttributes = { - 7B18E0921C5BFA2E005A2B8E = { - CreatedOnToolsVersion = 7.2; - }; - 7B18E0A11C5BFA2E005A2B8E = { - CreatedOnToolsVersion = 7.2; - TestTargetID = 7B18E0921C5BFA2E005A2B8E; - }; - }; - }; - buildConfigurationList = 7B18E08E1C5BFA2E005A2B8E /* Build configuration list for PBXProject "SelectMinimumMaximum" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 7B18E08A1C5BFA2E005A2B8E; - productRefGroup = 7B18E0941C5BFA2E005A2B8E /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 7B18E0921C5BFA2E005A2B8E /* SelectMinimumMaximum */, - 7B18E0A11C5BFA2E005A2B8E /* SelectMinimumMaximumTests */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 7B18E0911C5BFA2E005A2B8E /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 7B18E0A01C5BFA2E005A2B8E /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 7B18E08F1C5BFA2E005A2B8E /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 83F3255E1C64A0E700EB0421 /* Minimum.swift in Sources */, - 83F3255F1C64A0E700EB0421 /* MinimumMaximumPairs.swift in Sources */, - 83F3255D1C64A0E700EB0421 /* Maximum.swift in Sources */, - 7B18E0971C5BFA2E005A2B8E /* AppDelegate.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 7B18E09E1C5BFA2E005A2B8E /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 83F325611C64A3E000EB0421 /* MinimumTests.swift in Sources */, - 83F325631C64A4D400EB0421 /* MaximumTests.swift in Sources */, - 7B18E0A71C5BFA2E005A2B8E /* SelectMinimumMaximumTests.swift in Sources */, - 838A4FB41C64AED00092AA8F /* TestHelper.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 7B18E0A41C5BFA2E005A2B8E /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 7B18E0921C5BFA2E005A2B8E /* SelectMinimumMaximum */; - targetProxy = 7B18E0A31C5BFA2E005A2B8E /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin XCBuildConfiguration section */ - 7B18E0A91C5BFA2E005A2B8E /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "-"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.11; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = macosx; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - }; - name = Debug; - }; - 7B18E0AA1C5BFA2E005A2B8E /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "-"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.11; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = macosx; - }; - name = Release; - }; - 7B18E0AC1C5BFA2E005A2B8E /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = SelectMinimumMaximum/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.SelectMinimumMaximum; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 7B18E0AD1C5BFA2E005A2B8E /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = SelectMinimumMaximum/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.SelectMinimumMaximum; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - 7B18E0AF1C5BFA2E005A2B8E /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = SelectMinimumMaximumTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.SelectMinimumMaximumTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/SelectMinimumMaximum.app/Contents/MacOS/SelectMinimumMaximum"; - }; - name = Debug; - }; - 7B18E0B01C5BFA2E005A2B8E /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = SelectMinimumMaximumTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.SelectMinimumMaximumTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/SelectMinimumMaximum.app/Contents/MacOS/SelectMinimumMaximum"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 7B18E08E1C5BFA2E005A2B8E /* Build configuration list for PBXProject "SelectMinimumMaximum" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 7B18E0A91C5BFA2E005A2B8E /* Debug */, - 7B18E0AA1C5BFA2E005A2B8E /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 7B18E0AB1C5BFA2E005A2B8E /* Build configuration list for PBXNativeTarget "SelectMinimumMaximum" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 7B18E0AC1C5BFA2E005A2B8E /* Debug */, - 7B18E0AD1C5BFA2E005A2B8E /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 7B18E0AE1C5BFA2E005A2B8E /* Build configuration list for PBXNativeTarget "SelectMinimumMaximumTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 7B18E0AF1C5BFA2E005A2B8E /* Debug */, - 7B18E0B01C5BFA2E005A2B8E /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 7B18E08B1C5BFA2E005A2B8E /* Project object */; -} diff --git a/Select Minimum Maximum/SelectMinimumMaximum Tests/SelectMinimumMaximum/AppDelegate.swift b/Select Minimum Maximum/SelectMinimumMaximum Tests/SelectMinimumMaximum/AppDelegate.swift deleted file mode 100644 index 9c4f92293..000000000 --- a/Select Minimum Maximum/SelectMinimumMaximum Tests/SelectMinimumMaximum/AppDelegate.swift +++ /dev/null @@ -1,16 +0,0 @@ -import Cocoa - -@NSApplicationMain -class AppDelegate: NSObject, NSApplicationDelegate { - - @IBOutlet weak var window: NSWindow! - - func applicationDidFinishLaunching(aNotification: NSNotification) { - // Insert code here to initialize your application - } - - func applicationWillTerminate(aNotification: NSNotification) { - // Insert code here to tear down your application - } - -} diff --git a/Select Minimum Maximum/SelectMinimumMaximum Tests/SelectMinimumMaximum/Info.plist b/Select Minimum Maximum/SelectMinimumMaximum Tests/SelectMinimumMaximum/Info.plist deleted file mode 100644 index ec6d36e96..000000000 --- a/Select Minimum Maximum/SelectMinimumMaximum Tests/SelectMinimumMaximum/Info.plist +++ /dev/null @@ -1,32 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIconFile - - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - LSMinimumSystemVersion - $(MACOSX_DEPLOYMENT_TARGET) - NSHumanReadableCopyright - Copyright © 2016 Swift Algorithm Club. All rights reserved. - NSPrincipalClass - NSApplication - - diff --git a/Select Minimum Maximum/SelectMinimumMaximum Tests/SelectMinimumMaximumTests/Info.plist b/Select Minimum Maximum/Tests/Info.plist similarity index 100% rename from Select Minimum Maximum/SelectMinimumMaximum Tests/SelectMinimumMaximumTests/Info.plist rename to Select Minimum Maximum/Tests/Info.plist diff --git a/Select Minimum Maximum/SelectMinimumMaximum Tests/SelectMinimumMaximumTests/MaximumTests.swift b/Select Minimum Maximum/Tests/MaximumTests.swift similarity index 96% rename from Select Minimum Maximum/SelectMinimumMaximum Tests/SelectMinimumMaximumTests/MaximumTests.swift rename to Select Minimum Maximum/Tests/MaximumTests.swift index bd58187fc..38bcf483b 100644 --- a/Select Minimum Maximum/SelectMinimumMaximum Tests/SelectMinimumMaximumTests/MaximumTests.swift +++ b/Select Minimum Maximum/Tests/MaximumTests.swift @@ -1,5 +1,4 @@ import XCTest -@testable import SelectMinimumMaximum class MaximumTests: XCTestCase { diff --git a/Select Minimum Maximum/SelectMinimumMaximum Tests/SelectMinimumMaximumTests/SelectMinimumMaximumTests.swift b/Select Minimum Maximum/Tests/MinimumMaximumPairsTests.swift similarity index 95% rename from Select Minimum Maximum/SelectMinimumMaximum Tests/SelectMinimumMaximumTests/SelectMinimumMaximumTests.swift rename to Select Minimum Maximum/Tests/MinimumMaximumPairsTests.swift index 330f0e902..6cde21021 100644 --- a/Select Minimum Maximum/SelectMinimumMaximum Tests/SelectMinimumMaximumTests/SelectMinimumMaximumTests.swift +++ b/Select Minimum Maximum/Tests/MinimumMaximumPairsTests.swift @@ -1,7 +1,6 @@ import XCTest -@testable import SelectMinimumMaximum -class SelectMinimumMaximumTests: XCTestCase { +class MinimumMaximumPairsTests: XCTestCase { func testMinimumAndMaximumGivenAListContainingOneElement() { let array = [ 8 ] diff --git a/Select Minimum Maximum/SelectMinimumMaximum Tests/SelectMinimumMaximumTests/MinimumTests.swift b/Select Minimum Maximum/Tests/MinimumTests.swift similarity index 96% rename from Select Minimum Maximum/SelectMinimumMaximum Tests/SelectMinimumMaximumTests/MinimumTests.swift rename to Select Minimum Maximum/Tests/MinimumTests.swift index 235673320..ed4fbe1f0 100644 --- a/Select Minimum Maximum/SelectMinimumMaximum Tests/SelectMinimumMaximumTests/MinimumTests.swift +++ b/Select Minimum Maximum/Tests/MinimumTests.swift @@ -1,5 +1,4 @@ import XCTest -@testable import SelectMinimumMaximum class MinimumTests: XCTestCase { diff --git a/Select Minimum Maximum/SelectMinimumMaximum Tests/SelectMinimumMaximumTests/TestHelper.swift b/Select Minimum Maximum/Tests/TestHelper.swift similarity index 100% rename from Select Minimum Maximum/SelectMinimumMaximum Tests/SelectMinimumMaximumTests/TestHelper.swift rename to Select Minimum Maximum/Tests/TestHelper.swift diff --git a/Select Minimum Maximum/Tests/Tests.xcodeproj/project.pbxproj b/Select Minimum Maximum/Tests/Tests.xcodeproj/project.pbxproj new file mode 100644 index 000000000..e2857d2b7 --- /dev/null +++ b/Select Minimum Maximum/Tests/Tests.xcodeproj/project.pbxproj @@ -0,0 +1,281 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 7B80C40C1C77A768003CECC7 /* Maximum.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C4091C77A768003CECC7 /* Maximum.swift */; }; + 7B80C40D1C77A768003CECC7 /* Minimum.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C40A1C77A768003CECC7 /* Minimum.swift */; }; + 7B80C40E1C77A768003CECC7 /* MinimumMaximumPairs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C40B1C77A768003CECC7 /* MinimumMaximumPairs.swift */; }; + 7B80C4131C77A770003CECC7 /* MaximumTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C40F1C77A770003CECC7 /* MaximumTests.swift */; }; + 7B80C4141C77A770003CECC7 /* MinimumTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C4101C77A770003CECC7 /* MinimumTests.swift */; }; + 7B80C4151C77A770003CECC7 /* MinimumMaximumPairsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C4111C77A770003CECC7 /* MinimumMaximumPairsTests.swift */; }; + 7B80C4161C77A770003CECC7 /* TestHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C4121C77A770003CECC7 /* TestHelper.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 7B2BBC801C779D720067B71D /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 7B2BBC941C779E7B0067B71D /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; + 7B80C4091C77A768003CECC7 /* Maximum.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Maximum.swift; path = ../Maximum.swift; sourceTree = SOURCE_ROOT; }; + 7B80C40A1C77A768003CECC7 /* Minimum.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Minimum.swift; path = ../Minimum.swift; sourceTree = SOURCE_ROOT; }; + 7B80C40B1C77A768003CECC7 /* MinimumMaximumPairs.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MinimumMaximumPairs.swift; path = ../MinimumMaximumPairs.swift; sourceTree = SOURCE_ROOT; }; + 7B80C40F1C77A770003CECC7 /* MaximumTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MaximumTests.swift; sourceTree = SOURCE_ROOT; }; + 7B80C4101C77A770003CECC7 /* MinimumTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MinimumTests.swift; sourceTree = SOURCE_ROOT; }; + 7B80C4111C77A770003CECC7 /* MinimumMaximumPairsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MinimumMaximumPairsTests.swift; sourceTree = SOURCE_ROOT; }; + 7B80C4121C77A770003CECC7 /* TestHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestHelper.swift; sourceTree = SOURCE_ROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 7B2BBC7D1C779D720067B71D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 7B2BBC681C779D710067B71D = { + isa = PBXGroup; + children = ( + 7B2BBC831C779D720067B71D /* Tests */, + 7B2BBC721C779D710067B71D /* Products */, + ); + sourceTree = ""; + }; + 7B2BBC721C779D710067B71D /* Products */ = { + isa = PBXGroup; + children = ( + 7B2BBC801C779D720067B71D /* Tests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 7B2BBC831C779D720067B71D /* Tests */ = { + isa = PBXGroup; + children = ( + 7B2BBC941C779E7B0067B71D /* Info.plist */, + 7B80C4091C77A768003CECC7 /* Maximum.swift */, + 7B80C40F1C77A770003CECC7 /* MaximumTests.swift */, + 7B80C40A1C77A768003CECC7 /* Minimum.swift */, + 7B80C4101C77A770003CECC7 /* MinimumTests.swift */, + 7B80C40B1C77A768003CECC7 /* MinimumMaximumPairs.swift */, + 7B80C4111C77A770003CECC7 /* MinimumMaximumPairsTests.swift */, + 7B80C4121C77A770003CECC7 /* TestHelper.swift */, + ); + name = Tests; + path = TestsTests; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 7B2BBC7F1C779D720067B71D /* Tests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */; + buildPhases = ( + 7B2BBC7C1C779D720067B71D /* Sources */, + 7B2BBC7D1C779D720067B71D /* Frameworks */, + 7B2BBC7E1C779D720067B71D /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Tests; + productName = TestsTests; + productReference = 7B2BBC801C779D720067B71D /* Tests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 7B2BBC691C779D710067B71D /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0720; + LastUpgradeCheck = 0720; + ORGANIZATIONNAME = "Swift Algorithm Club"; + TargetAttributes = { + 7B2BBC7F1C779D720067B71D = { + CreatedOnToolsVersion = 7.2; + }; + }; + }; + buildConfigurationList = 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 7B2BBC681C779D710067B71D; + productRefGroup = 7B2BBC721C779D710067B71D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 7B2BBC7F1C779D720067B71D /* Tests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 7B2BBC7E1C779D720067B71D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 7B2BBC7C1C779D720067B71D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 7B80C40D1C77A768003CECC7 /* Minimum.swift in Sources */, + 7B80C40E1C77A768003CECC7 /* MinimumMaximumPairs.swift in Sources */, + 7B80C4141C77A770003CECC7 /* MinimumTests.swift in Sources */, + 7B80C40C1C77A768003CECC7 /* Maximum.swift in Sources */, + 7B80C4131C77A770003CECC7 /* MaximumTests.swift in Sources */, + 7B80C4161C77A770003CECC7 /* TestHelper.swift in Sources */, + 7B80C4151C77A770003CECC7 /* MinimumMaximumPairsTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 7B2BBC871C779D720067B71D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 7B2BBC881C779D720067B71D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + }; + name = Release; + }; + 7B2BBC8D1C779D720067B71D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 7B2BBC8E1C779D720067B71D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7B2BBC871C779D720067B71D /* Debug */, + 7B2BBC881C779D720067B71D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7B2BBC8D1C779D720067B71D /* Debug */, + 7B2BBC8E1C779D720067B71D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 7B2BBC691C779D710067B71D /* Project object */; +} diff --git a/Selection Sort/SelectionSort Tests/SelectionSort.xcodeproj/project.pbxproj b/Selection Sort/SelectionSort Tests/SelectionSort.xcodeproj/project.pbxproj deleted file mode 100644 index 25bfba716..000000000 --- a/Selection Sort/SelectionSort Tests/SelectionSort.xcodeproj/project.pbxproj +++ /dev/null @@ -1,398 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 7B18E0C21C5BFB2D005A2B8E /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B18E0C11C5BFB2D005A2B8E /* AppDelegate.swift */; }; - 7B18E0C41C5BFB2D005A2B8E /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7B18E0C31C5BFB2D005A2B8E /* Assets.xcassets */; }; - 7B18E0C71C5BFB2D005A2B8E /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7B18E0C51C5BFB2D005A2B8E /* MainMenu.xib */; }; - 7B18E0D21C5BFB2D005A2B8E /* SelectionSortTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B18E0D11C5BFB2D005A2B8E /* SelectionSortTests.swift */; }; - 7B18E0DD1C5BFB40005A2B8E /* SelectionSort.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B18E0DC1C5BFB40005A2B8E /* SelectionSort.swift */; }; - 7B18E0DF1C5BFB55005A2B8E /* SortingTestHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B18E0DE1C5BFB55005A2B8E /* SortingTestHelpers.swift */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 7B18E0CE1C5BFB2D005A2B8E /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 7B18E0B61C5BFB2D005A2B8E /* Project object */; - proxyType = 1; - remoteGlobalIDString = 7B18E0BD1C5BFB2D005A2B8E; - remoteInfo = SelectionSort; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXFileReference section */ - 7B18E0BE1C5BFB2D005A2B8E /* SelectionSort.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SelectionSort.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 7B18E0C11C5BFB2D005A2B8E /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 7B18E0C31C5BFB2D005A2B8E /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - 7B18E0C61C5BFB2D005A2B8E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; - 7B18E0C81C5BFB2D005A2B8E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 7B18E0CD1C5BFB2D005A2B8E /* SelectionSortTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SelectionSortTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 7B18E0D11C5BFB2D005A2B8E /* SelectionSortTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SelectionSortTests.swift; sourceTree = ""; }; - 7B18E0D31C5BFB2D005A2B8E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 7B18E0DC1C5BFB40005A2B8E /* SelectionSort.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SelectionSort.swift; path = ../../SelectionSort.swift; sourceTree = ""; }; - 7B18E0DE1C5BFB55005A2B8E /* SortingTestHelpers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SortingTestHelpers.swift; path = "../../../Quicksort/Quicksort Tests/QuicksortTests/SortingTestHelpers.swift"; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 7B18E0BB1C5BFB2D005A2B8E /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 7B18E0CA1C5BFB2D005A2B8E /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 7B18E0B51C5BFB2D005A2B8E = { - isa = PBXGroup; - children = ( - 7B18E0C01C5BFB2D005A2B8E /* SelectionSort */, - 7B18E0D01C5BFB2D005A2B8E /* SelectionSortTests */, - 7B18E0BF1C5BFB2D005A2B8E /* Products */, - ); - sourceTree = ""; - }; - 7B18E0BF1C5BFB2D005A2B8E /* Products */ = { - isa = PBXGroup; - children = ( - 7B18E0BE1C5BFB2D005A2B8E /* SelectionSort.app */, - 7B18E0CD1C5BFB2D005A2B8E /* SelectionSortTests.xctest */, - ); - name = Products; - sourceTree = ""; - }; - 7B18E0C01C5BFB2D005A2B8E /* SelectionSort */ = { - isa = PBXGroup; - children = ( - 7B18E0C11C5BFB2D005A2B8E /* AppDelegate.swift */, - 7B18E0C31C5BFB2D005A2B8E /* Assets.xcassets */, - 7B18E0C81C5BFB2D005A2B8E /* Info.plist */, - 7B18E0C51C5BFB2D005A2B8E /* MainMenu.xib */, - 7B18E0DC1C5BFB40005A2B8E /* SelectionSort.swift */, - ); - path = SelectionSort; - sourceTree = ""; - }; - 7B18E0D01C5BFB2D005A2B8E /* SelectionSortTests */ = { - isa = PBXGroup; - children = ( - 7B18E0D31C5BFB2D005A2B8E /* Info.plist */, - 7B18E0D11C5BFB2D005A2B8E /* SelectionSortTests.swift */, - 7B18E0DE1C5BFB55005A2B8E /* SortingTestHelpers.swift */, - ); - path = SelectionSortTests; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 7B18E0BD1C5BFB2D005A2B8E /* SelectionSort */ = { - isa = PBXNativeTarget; - buildConfigurationList = 7B18E0D61C5BFB2D005A2B8E /* Build configuration list for PBXNativeTarget "SelectionSort" */; - buildPhases = ( - 7B18E0BA1C5BFB2D005A2B8E /* Sources */, - 7B18E0BB1C5BFB2D005A2B8E /* Frameworks */, - 7B18E0BC1C5BFB2D005A2B8E /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = SelectionSort; - productName = SelectionSort; - productReference = 7B18E0BE1C5BFB2D005A2B8E /* SelectionSort.app */; - productType = "com.apple.product-type.application"; - }; - 7B18E0CC1C5BFB2D005A2B8E /* SelectionSortTests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 7B18E0D91C5BFB2D005A2B8E /* Build configuration list for PBXNativeTarget "SelectionSortTests" */; - buildPhases = ( - 7B18E0C91C5BFB2D005A2B8E /* Sources */, - 7B18E0CA1C5BFB2D005A2B8E /* Frameworks */, - 7B18E0CB1C5BFB2D005A2B8E /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - 7B18E0CF1C5BFB2D005A2B8E /* PBXTargetDependency */, - ); - name = SelectionSortTests; - productName = SelectionSortTests; - productReference = 7B18E0CD1C5BFB2D005A2B8E /* SelectionSortTests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 7B18E0B61C5BFB2D005A2B8E /* Project object */ = { - isa = PBXProject; - attributes = { - LastSwiftUpdateCheck = 0720; - LastUpgradeCheck = 0720; - ORGANIZATIONNAME = "Swift Algorithm Club"; - TargetAttributes = { - 7B18E0BD1C5BFB2D005A2B8E = { - CreatedOnToolsVersion = 7.2; - }; - 7B18E0CC1C5BFB2D005A2B8E = { - CreatedOnToolsVersion = 7.2; - TestTargetID = 7B18E0BD1C5BFB2D005A2B8E; - }; - }; - }; - buildConfigurationList = 7B18E0B91C5BFB2D005A2B8E /* Build configuration list for PBXProject "SelectionSort" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 7B18E0B51C5BFB2D005A2B8E; - productRefGroup = 7B18E0BF1C5BFB2D005A2B8E /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 7B18E0BD1C5BFB2D005A2B8E /* SelectionSort */, - 7B18E0CC1C5BFB2D005A2B8E /* SelectionSortTests */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 7B18E0BC1C5BFB2D005A2B8E /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 7B18E0C41C5BFB2D005A2B8E /* Assets.xcassets in Resources */, - 7B18E0C71C5BFB2D005A2B8E /* MainMenu.xib in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 7B18E0CB1C5BFB2D005A2B8E /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 7B18E0BA1C5BFB2D005A2B8E /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 7B18E0DD1C5BFB40005A2B8E /* SelectionSort.swift in Sources */, - 7B18E0C21C5BFB2D005A2B8E /* AppDelegate.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 7B18E0C91C5BFB2D005A2B8E /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 7B18E0DF1C5BFB55005A2B8E /* SortingTestHelpers.swift in Sources */, - 7B18E0D21C5BFB2D005A2B8E /* SelectionSortTests.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 7B18E0CF1C5BFB2D005A2B8E /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 7B18E0BD1C5BFB2D005A2B8E /* SelectionSort */; - targetProxy = 7B18E0CE1C5BFB2D005A2B8E /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin PBXVariantGroup section */ - 7B18E0C51C5BFB2D005A2B8E /* MainMenu.xib */ = { - isa = PBXVariantGroup; - children = ( - 7B18E0C61C5BFB2D005A2B8E /* Base */, - ); - name = MainMenu.xib; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 7B18E0D41C5BFB2D005A2B8E /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "-"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.11; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = macosx; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - }; - name = Debug; - }; - 7B18E0D51C5BFB2D005A2B8E /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "-"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.11; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = macosx; - }; - name = Release; - }; - 7B18E0D71C5BFB2D005A2B8E /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = SelectionSort/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.SelectionSort; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 7B18E0D81C5BFB2D005A2B8E /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = SelectionSort/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.SelectionSort; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - 7B18E0DA1C5BFB2D005A2B8E /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = SelectionSortTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.SelectionSortTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/SelectionSort.app/Contents/MacOS/SelectionSort"; - }; - name = Debug; - }; - 7B18E0DB1C5BFB2D005A2B8E /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = SelectionSortTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.SelectionSortTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/SelectionSort.app/Contents/MacOS/SelectionSort"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 7B18E0B91C5BFB2D005A2B8E /* Build configuration list for PBXProject "SelectionSort" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 7B18E0D41C5BFB2D005A2B8E /* Debug */, - 7B18E0D51C5BFB2D005A2B8E /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 7B18E0D61C5BFB2D005A2B8E /* Build configuration list for PBXNativeTarget "SelectionSort" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 7B18E0D71C5BFB2D005A2B8E /* Debug */, - 7B18E0D81C5BFB2D005A2B8E /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 7B18E0D91C5BFB2D005A2B8E /* Build configuration list for PBXNativeTarget "SelectionSortTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 7B18E0DA1C5BFB2D005A2B8E /* Debug */, - 7B18E0DB1C5BFB2D005A2B8E /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 7B18E0B61C5BFB2D005A2B8E /* Project object */; -} diff --git a/Selection Sort/SelectionSort Tests/SelectionSort/AppDelegate.swift b/Selection Sort/SelectionSort Tests/SelectionSort/AppDelegate.swift deleted file mode 100644 index 79cd1a92a..000000000 --- a/Selection Sort/SelectionSort Tests/SelectionSort/AppDelegate.swift +++ /dev/null @@ -1,27 +0,0 @@ -// -// AppDelegate.swift -// SelectionSort -// -// Created by Matthijs Hollemans on 29-01-16. -// Copyright © 2016 Swift Algorithm Club. All rights reserved. -// - -import Cocoa - -@NSApplicationMain -class AppDelegate: NSObject, NSApplicationDelegate { - - @IBOutlet weak var window: NSWindow! - - - func applicationDidFinishLaunching(aNotification: NSNotification) { - // Insert code here to initialize your application - } - - func applicationWillTerminate(aNotification: NSNotification) { - // Insert code here to tear down your application - } - - -} - diff --git a/Selection Sort/SelectionSort Tests/SelectionSort/Assets.xcassets/AppIcon.appiconset/Contents.json b/Selection Sort/SelectionSort Tests/SelectionSort/Assets.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index 2db2b1c7c..000000000 --- a/Selection Sort/SelectionSort Tests/SelectionSort/Assets.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "images" : [ - { - "idiom" : "mac", - "size" : "16x16", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "16x16", - "scale" : "2x" - }, - { - "idiom" : "mac", - "size" : "32x32", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "32x32", - "scale" : "2x" - }, - { - "idiom" : "mac", - "size" : "128x128", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "128x128", - "scale" : "2x" - }, - { - "idiom" : "mac", - "size" : "256x256", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "256x256", - "scale" : "2x" - }, - { - "idiom" : "mac", - "size" : "512x512", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "512x512", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/Selection Sort/SelectionSort Tests/SelectionSort/Base.lproj/MainMenu.xib b/Selection Sort/SelectionSort Tests/SelectionSort/Base.lproj/MainMenu.xib deleted file mode 100644 index 47b389b06..000000000 --- a/Selection Sort/SelectionSort Tests/SelectionSort/Base.lproj/MainMenu.xib +++ /dev/null @@ -1,680 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Default - - - - - - - Left to Right - - - - - - - Right to Left - - - - - - - - - - - Default - - - - - - - Left to Right - - - - - - - Right to Left - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Selection Sort/SelectionSort Tests/SelectionSort/Info.plist b/Selection Sort/SelectionSort Tests/SelectionSort/Info.plist deleted file mode 100644 index 0dca3caa8..000000000 --- a/Selection Sort/SelectionSort Tests/SelectionSort/Info.plist +++ /dev/null @@ -1,34 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIconFile - - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - LSMinimumSystemVersion - $(MACOSX_DEPLOYMENT_TARGET) - NSHumanReadableCopyright - Copyright © 2016 Swift Algorithm Club. All rights reserved. - NSMainNibFile - MainMenu - NSPrincipalClass - NSApplication - - diff --git a/Selection Sort/SelectionSort Tests/SelectionSortTests/Info.plist b/Selection Sort/Tests/Info.plist similarity index 100% rename from Selection Sort/SelectionSort Tests/SelectionSortTests/Info.plist rename to Selection Sort/Tests/Info.plist diff --git a/Selection Sort/SelectionSort Tests/SelectionSortTests/SelectionSortTests.swift b/Selection Sort/Tests/SelectionSortTests.swift similarity index 80% rename from Selection Sort/SelectionSort Tests/SelectionSortTests/SelectionSortTests.swift rename to Selection Sort/Tests/SelectionSortTests.swift index 917332cae..3e26122b0 100644 --- a/Selection Sort/SelectionSort Tests/SelectionSortTests/SelectionSortTests.swift +++ b/Selection Sort/Tests/SelectionSortTests.swift @@ -1,5 +1,4 @@ import XCTest -@testable import SelectionSort class SelectionSortTests: XCTestCase { func testSelectionSort() { diff --git a/Selection Sort/Tests/Tests.xcodeproj/project.pbxproj b/Selection Sort/Tests/Tests.xcodeproj/project.pbxproj new file mode 100644 index 000000000..11aefac3c --- /dev/null +++ b/Selection Sort/Tests/Tests.xcodeproj/project.pbxproj @@ -0,0 +1,265 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 7B80C3EA1C77A4D0003CECC7 /* SortingTestHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C3E81C77A4D0003CECC7 /* SortingTestHelpers.swift */; }; + 7B80C3F01C77A590003CECC7 /* SelectionSortTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C3EF1C77A590003CECC7 /* SelectionSortTests.swift */; }; + 7B80C3F21C77A598003CECC7 /* SelectionSort.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C3F11C77A598003CECC7 /* SelectionSort.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 7B2BBC801C779D720067B71D /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 7B2BBC941C779E7B0067B71D /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; + 7B80C3E81C77A4D0003CECC7 /* SortingTestHelpers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SortingTestHelpers.swift; path = ../../Quicksort/Tests/SortingTestHelpers.swift; sourceTree = SOURCE_ROOT; }; + 7B80C3EF1C77A590003CECC7 /* SelectionSortTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SelectionSortTests.swift; sourceTree = SOURCE_ROOT; }; + 7B80C3F11C77A598003CECC7 /* SelectionSort.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SelectionSort.swift; path = ../SelectionSort.swift; sourceTree = SOURCE_ROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 7B2BBC7D1C779D720067B71D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 7B2BBC681C779D710067B71D = { + isa = PBXGroup; + children = ( + 7B2BBC831C779D720067B71D /* Tests */, + 7B2BBC721C779D710067B71D /* Products */, + ); + sourceTree = ""; + }; + 7B2BBC721C779D710067B71D /* Products */ = { + isa = PBXGroup; + children = ( + 7B2BBC801C779D720067B71D /* Tests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 7B2BBC831C779D720067B71D /* Tests */ = { + isa = PBXGroup; + children = ( + 7B80C3F11C77A598003CECC7 /* SelectionSort.swift */, + 7B80C3EF1C77A590003CECC7 /* SelectionSortTests.swift */, + 7B80C3E81C77A4D0003CECC7 /* SortingTestHelpers.swift */, + 7B2BBC941C779E7B0067B71D /* Info.plist */, + ); + name = Tests; + path = TestsTests; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 7B2BBC7F1C779D720067B71D /* Tests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */; + buildPhases = ( + 7B2BBC7C1C779D720067B71D /* Sources */, + 7B2BBC7D1C779D720067B71D /* Frameworks */, + 7B2BBC7E1C779D720067B71D /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Tests; + productName = TestsTests; + productReference = 7B2BBC801C779D720067B71D /* Tests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 7B2BBC691C779D710067B71D /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0720; + LastUpgradeCheck = 0720; + ORGANIZATIONNAME = "Swift Algorithm Club"; + TargetAttributes = { + 7B2BBC7F1C779D720067B71D = { + CreatedOnToolsVersion = 7.2; + }; + }; + }; + buildConfigurationList = 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 7B2BBC681C779D710067B71D; + productRefGroup = 7B2BBC721C779D710067B71D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 7B2BBC7F1C779D720067B71D /* Tests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 7B2BBC7E1C779D720067B71D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 7B2BBC7C1C779D720067B71D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 7B80C3F01C77A590003CECC7 /* SelectionSortTests.swift in Sources */, + 7B80C3EA1C77A4D0003CECC7 /* SortingTestHelpers.swift in Sources */, + 7B80C3F21C77A598003CECC7 /* SelectionSort.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 7B2BBC871C779D720067B71D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 7B2BBC881C779D720067B71D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + }; + name = Release; + }; + 7B2BBC8D1C779D720067B71D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 7B2BBC8E1C779D720067B71D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7B2BBC871C779D720067B71D /* Debug */, + 7B2BBC881C779D720067B71D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7B2BBC8D1C779D720067B71D /* Debug */, + 7B2BBC8E1C779D720067B71D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 7B2BBC691C779D710067B71D /* Project object */; +} diff --git a/Shell Sort/ShellSort Tests/ShellSort.xcodeproj/project.pbxproj b/Shell Sort/ShellSort Tests/ShellSort.xcodeproj/project.pbxproj deleted file mode 100644 index c012a7cff..000000000 --- a/Shell Sort/ShellSort Tests/ShellSort.xcodeproj/project.pbxproj +++ /dev/null @@ -1,398 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 7B1BFA701C6A40370051C9A4 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B1BFA6F1C6A40370051C9A4 /* AppDelegate.swift */; }; - 7B1BFA721C6A40370051C9A4 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7B1BFA711C6A40370051C9A4 /* Assets.xcassets */; }; - 7B1BFA751C6A40380051C9A4 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7B1BFA731C6A40380051C9A4 /* MainMenu.xib */; }; - 7B1BFA801C6A40380051C9A4 /* ShellSortTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B1BFA7F1C6A40380051C9A4 /* ShellSortTests.swift */; }; - 7B1BFA8B1C6A40560051C9A4 /* ShellSort.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B1BFA8A1C6A40560051C9A4 /* ShellSort.swift */; }; - 7B1BFA8D1C6A40820051C9A4 /* SortingTestHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B1BFA8C1C6A40820051C9A4 /* SortingTestHelpers.swift */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 7B1BFA7C1C6A40380051C9A4 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 7B1BFA641C6A40370051C9A4 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 7B1BFA6B1C6A40370051C9A4; - remoteInfo = ShellSort; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXFileReference section */ - 7B1BFA6C1C6A40370051C9A4 /* ShellSort.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ShellSort.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 7B1BFA6F1C6A40370051C9A4 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 7B1BFA711C6A40370051C9A4 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - 7B1BFA741C6A40380051C9A4 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; - 7B1BFA761C6A40380051C9A4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 7B1BFA7B1C6A40380051C9A4 /* ShellSortTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ShellSortTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 7B1BFA7F1C6A40380051C9A4 /* ShellSortTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShellSortTests.swift; sourceTree = ""; }; - 7B1BFA811C6A40380051C9A4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 7B1BFA8A1C6A40560051C9A4 /* ShellSort.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ShellSort.swift; path = ../../ShellSort.swift; sourceTree = ""; }; - 7B1BFA8C1C6A40820051C9A4 /* SortingTestHelpers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SortingTestHelpers.swift; path = "../../../Quicksort/Quicksort Tests/QuicksortTests/SortingTestHelpers.swift"; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 7B1BFA691C6A40370051C9A4 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 7B1BFA781C6A40380051C9A4 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 7B1BFA631C6A40370051C9A4 = { - isa = PBXGroup; - children = ( - 7B1BFA6E1C6A40370051C9A4 /* ShellSort */, - 7B1BFA7E1C6A40380051C9A4 /* ShellSortTests */, - 7B1BFA6D1C6A40370051C9A4 /* Products */, - ); - sourceTree = ""; - }; - 7B1BFA6D1C6A40370051C9A4 /* Products */ = { - isa = PBXGroup; - children = ( - 7B1BFA6C1C6A40370051C9A4 /* ShellSort.app */, - 7B1BFA7B1C6A40380051C9A4 /* ShellSortTests.xctest */, - ); - name = Products; - sourceTree = ""; - }; - 7B1BFA6E1C6A40370051C9A4 /* ShellSort */ = { - isa = PBXGroup; - children = ( - 7B1BFA6F1C6A40370051C9A4 /* AppDelegate.swift */, - 7B1BFA711C6A40370051C9A4 /* Assets.xcassets */, - 7B1BFA761C6A40380051C9A4 /* Info.plist */, - 7B1BFA731C6A40380051C9A4 /* MainMenu.xib */, - 7B1BFA8A1C6A40560051C9A4 /* ShellSort.swift */, - ); - path = ShellSort; - sourceTree = ""; - }; - 7B1BFA7E1C6A40380051C9A4 /* ShellSortTests */ = { - isa = PBXGroup; - children = ( - 7B1BFA811C6A40380051C9A4 /* Info.plist */, - 7B1BFA7F1C6A40380051C9A4 /* ShellSortTests.swift */, - 7B1BFA8C1C6A40820051C9A4 /* SortingTestHelpers.swift */, - ); - path = ShellSortTests; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 7B1BFA6B1C6A40370051C9A4 /* ShellSort */ = { - isa = PBXNativeTarget; - buildConfigurationList = 7B1BFA841C6A40380051C9A4 /* Build configuration list for PBXNativeTarget "ShellSort" */; - buildPhases = ( - 7B1BFA681C6A40370051C9A4 /* Sources */, - 7B1BFA691C6A40370051C9A4 /* Frameworks */, - 7B1BFA6A1C6A40370051C9A4 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = ShellSort; - productName = ShellSort; - productReference = 7B1BFA6C1C6A40370051C9A4 /* ShellSort.app */; - productType = "com.apple.product-type.application"; - }; - 7B1BFA7A1C6A40380051C9A4 /* ShellSortTests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 7B1BFA871C6A40380051C9A4 /* Build configuration list for PBXNativeTarget "ShellSortTests" */; - buildPhases = ( - 7B1BFA771C6A40380051C9A4 /* Sources */, - 7B1BFA781C6A40380051C9A4 /* Frameworks */, - 7B1BFA791C6A40380051C9A4 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - 7B1BFA7D1C6A40380051C9A4 /* PBXTargetDependency */, - ); - name = ShellSortTests; - productName = ShellSortTests; - productReference = 7B1BFA7B1C6A40380051C9A4 /* ShellSortTests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 7B1BFA641C6A40370051C9A4 /* Project object */ = { - isa = PBXProject; - attributes = { - LastSwiftUpdateCheck = 0720; - LastUpgradeCheck = 0720; - ORGANIZATIONNAME = "Swift Algorithm Club"; - TargetAttributes = { - 7B1BFA6B1C6A40370051C9A4 = { - CreatedOnToolsVersion = 7.2; - }; - 7B1BFA7A1C6A40380051C9A4 = { - CreatedOnToolsVersion = 7.2; - TestTargetID = 7B1BFA6B1C6A40370051C9A4; - }; - }; - }; - buildConfigurationList = 7B1BFA671C6A40370051C9A4 /* Build configuration list for PBXProject "ShellSort" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 7B1BFA631C6A40370051C9A4; - productRefGroup = 7B1BFA6D1C6A40370051C9A4 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 7B1BFA6B1C6A40370051C9A4 /* ShellSort */, - 7B1BFA7A1C6A40380051C9A4 /* ShellSortTests */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 7B1BFA6A1C6A40370051C9A4 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 7B1BFA721C6A40370051C9A4 /* Assets.xcassets in Resources */, - 7B1BFA751C6A40380051C9A4 /* MainMenu.xib in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 7B1BFA791C6A40380051C9A4 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 7B1BFA681C6A40370051C9A4 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 7B1BFA8B1C6A40560051C9A4 /* ShellSort.swift in Sources */, - 7B1BFA701C6A40370051C9A4 /* AppDelegate.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 7B1BFA771C6A40380051C9A4 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 7B1BFA8D1C6A40820051C9A4 /* SortingTestHelpers.swift in Sources */, - 7B1BFA801C6A40380051C9A4 /* ShellSortTests.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 7B1BFA7D1C6A40380051C9A4 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 7B1BFA6B1C6A40370051C9A4 /* ShellSort */; - targetProxy = 7B1BFA7C1C6A40380051C9A4 /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin PBXVariantGroup section */ - 7B1BFA731C6A40380051C9A4 /* MainMenu.xib */ = { - isa = PBXVariantGroup; - children = ( - 7B1BFA741C6A40380051C9A4 /* Base */, - ); - name = MainMenu.xib; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 7B1BFA821C6A40380051C9A4 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "-"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.11; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = macosx; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - }; - name = Debug; - }; - 7B1BFA831C6A40380051C9A4 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "-"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.11; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = macosx; - }; - name = Release; - }; - 7B1BFA851C6A40380051C9A4 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = ShellSort/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.ShellSort; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 7B1BFA861C6A40380051C9A4 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = ShellSort/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.ShellSort; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - 7B1BFA881C6A40380051C9A4 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = ShellSortTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.ShellSortTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/ShellSort.app/Contents/MacOS/ShellSort"; - }; - name = Debug; - }; - 7B1BFA891C6A40380051C9A4 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = ShellSortTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.ShellSortTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/ShellSort.app/Contents/MacOS/ShellSort"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 7B1BFA671C6A40370051C9A4 /* Build configuration list for PBXProject "ShellSort" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 7B1BFA821C6A40380051C9A4 /* Debug */, - 7B1BFA831C6A40380051C9A4 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 7B1BFA841C6A40380051C9A4 /* Build configuration list for PBXNativeTarget "ShellSort" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 7B1BFA851C6A40380051C9A4 /* Debug */, - 7B1BFA861C6A40380051C9A4 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 7B1BFA871C6A40380051C9A4 /* Build configuration list for PBXNativeTarget "ShellSortTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 7B1BFA881C6A40380051C9A4 /* Debug */, - 7B1BFA891C6A40380051C9A4 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 7B1BFA641C6A40370051C9A4 /* Project object */; -} diff --git a/Shell Sort/ShellSort Tests/ShellSort/AppDelegate.swift b/Shell Sort/ShellSort Tests/ShellSort/AppDelegate.swift deleted file mode 100644 index 8e8d28d24..000000000 --- a/Shell Sort/ShellSort Tests/ShellSort/AppDelegate.swift +++ /dev/null @@ -1,27 +0,0 @@ -// -// AppDelegate.swift -// ShellSort -// -// Created by Matthijs Hollemans on 09-02-16. -// Copyright © 2016 Swift Algorithm Club. All rights reserved. -// - -import Cocoa - -@NSApplicationMain -class AppDelegate: NSObject, NSApplicationDelegate { - - @IBOutlet weak var window: NSWindow! - - - func applicationDidFinishLaunching(aNotification: NSNotification) { - // Insert code here to initialize your application - } - - func applicationWillTerminate(aNotification: NSNotification) { - // Insert code here to tear down your application - } - - -} - diff --git a/Shell Sort/ShellSort Tests/ShellSort/Assets.xcassets/AppIcon.appiconset/Contents.json b/Shell Sort/ShellSort Tests/ShellSort/Assets.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index 2db2b1c7c..000000000 --- a/Shell Sort/ShellSort Tests/ShellSort/Assets.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "images" : [ - { - "idiom" : "mac", - "size" : "16x16", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "16x16", - "scale" : "2x" - }, - { - "idiom" : "mac", - "size" : "32x32", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "32x32", - "scale" : "2x" - }, - { - "idiom" : "mac", - "size" : "128x128", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "128x128", - "scale" : "2x" - }, - { - "idiom" : "mac", - "size" : "256x256", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "256x256", - "scale" : "2x" - }, - { - "idiom" : "mac", - "size" : "512x512", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "512x512", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/Shell Sort/ShellSort Tests/ShellSort/Base.lproj/MainMenu.xib b/Shell Sort/ShellSort Tests/ShellSort/Base.lproj/MainMenu.xib deleted file mode 100644 index 22614e1d7..000000000 --- a/Shell Sort/ShellSort Tests/ShellSort/Base.lproj/MainMenu.xib +++ /dev/null @@ -1,680 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Default - - - - - - - Left to Right - - - - - - - Right to Left - - - - - - - - - - - Default - - - - - - - Left to Right - - - - - - - Right to Left - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Shell Sort/ShellSort Tests/ShellSort/Info.plist b/Shell Sort/ShellSort Tests/ShellSort/Info.plist deleted file mode 100644 index 0dca3caa8..000000000 --- a/Shell Sort/ShellSort Tests/ShellSort/Info.plist +++ /dev/null @@ -1,34 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIconFile - - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - LSMinimumSystemVersion - $(MACOSX_DEPLOYMENT_TARGET) - NSHumanReadableCopyright - Copyright © 2016 Swift Algorithm Club. All rights reserved. - NSMainNibFile - MainMenu - NSPrincipalClass - NSApplication - - diff --git a/Shell Sort/ShellSort Tests/ShellSortTests/Info.plist b/Shell Sort/Tests/Info.plist similarity index 100% rename from Shell Sort/ShellSort Tests/ShellSortTests/Info.plist rename to Shell Sort/Tests/Info.plist diff --git a/Shell Sort/ShellSort Tests/ShellSortTests/ShellSortTests.swift b/Shell Sort/Tests/ShellSortTests.swift similarity index 87% rename from Shell Sort/ShellSort Tests/ShellSortTests/ShellSortTests.swift rename to Shell Sort/Tests/ShellSortTests.swift index 780ce1d3b..f9404b781 100644 --- a/Shell Sort/ShellSort Tests/ShellSortTests/ShellSortTests.swift +++ b/Shell Sort/Tests/ShellSortTests.swift @@ -1,5 +1,4 @@ import XCTest -@testable import ShellSort class ShellSortTests: XCTestCase { func testShellSort() { diff --git a/Shell Sort/Tests/Tests.xcodeproj/project.pbxproj b/Shell Sort/Tests/Tests.xcodeproj/project.pbxproj new file mode 100644 index 000000000..9f7f4391e --- /dev/null +++ b/Shell Sort/Tests/Tests.xcodeproj/project.pbxproj @@ -0,0 +1,265 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 7B80C3EA1C77A4D0003CECC7 /* SortingTestHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C3E81C77A4D0003CECC7 /* SortingTestHelpers.swift */; }; + 7B80C3F41C77A5D3003CECC7 /* ShellSort.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C3F31C77A5D3003CECC7 /* ShellSort.swift */; }; + 7B80C3F61C77A5D9003CECC7 /* ShellSortTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C3F51C77A5D9003CECC7 /* ShellSortTests.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 7B2BBC801C779D720067B71D /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 7B2BBC941C779E7B0067B71D /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; + 7B80C3E81C77A4D0003CECC7 /* SortingTestHelpers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SortingTestHelpers.swift; path = ../../Quicksort/Tests/SortingTestHelpers.swift; sourceTree = SOURCE_ROOT; }; + 7B80C3F31C77A5D3003CECC7 /* ShellSort.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ShellSort.swift; path = ../ShellSort.swift; sourceTree = SOURCE_ROOT; }; + 7B80C3F51C77A5D9003CECC7 /* ShellSortTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ShellSortTests.swift; sourceTree = SOURCE_ROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 7B2BBC7D1C779D720067B71D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 7B2BBC681C779D710067B71D = { + isa = PBXGroup; + children = ( + 7B2BBC831C779D720067B71D /* Tests */, + 7B2BBC721C779D710067B71D /* Products */, + ); + sourceTree = ""; + }; + 7B2BBC721C779D710067B71D /* Products */ = { + isa = PBXGroup; + children = ( + 7B2BBC801C779D720067B71D /* Tests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 7B2BBC831C779D720067B71D /* Tests */ = { + isa = PBXGroup; + children = ( + 7B80C3F31C77A5D3003CECC7 /* ShellSort.swift */, + 7B80C3F51C77A5D9003CECC7 /* ShellSortTests.swift */, + 7B80C3E81C77A4D0003CECC7 /* SortingTestHelpers.swift */, + 7B2BBC941C779E7B0067B71D /* Info.plist */, + ); + name = Tests; + path = TestsTests; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 7B2BBC7F1C779D720067B71D /* Tests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */; + buildPhases = ( + 7B2BBC7C1C779D720067B71D /* Sources */, + 7B2BBC7D1C779D720067B71D /* Frameworks */, + 7B2BBC7E1C779D720067B71D /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Tests; + productName = TestsTests; + productReference = 7B2BBC801C779D720067B71D /* Tests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 7B2BBC691C779D710067B71D /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0720; + LastUpgradeCheck = 0720; + ORGANIZATIONNAME = "Swift Algorithm Club"; + TargetAttributes = { + 7B2BBC7F1C779D720067B71D = { + CreatedOnToolsVersion = 7.2; + }; + }; + }; + buildConfigurationList = 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 7B2BBC681C779D710067B71D; + productRefGroup = 7B2BBC721C779D710067B71D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 7B2BBC7F1C779D720067B71D /* Tests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 7B2BBC7E1C779D720067B71D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 7B2BBC7C1C779D720067B71D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 7B80C3F61C77A5D9003CECC7 /* ShellSortTests.swift in Sources */, + 7B80C3EA1C77A4D0003CECC7 /* SortingTestHelpers.swift in Sources */, + 7B80C3F41C77A5D3003CECC7 /* ShellSort.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 7B2BBC871C779D720067B71D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 7B2BBC881C779D720067B71D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + }; + name = Release; + }; + 7B2BBC8D1C779D720067B71D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 7B2BBC8E1C779D720067B71D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7B2BBC871C779D720067B71D /* Debug */, + 7B2BBC881C779D720067B71D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7B2BBC8D1C779D720067B71D /* Debug */, + 7B2BBC8E1C779D720067B71D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 7B2BBC691C779D710067B71D /* Project object */; +} diff --git a/Stack/Stack Tests/Stack.xcodeproj/project.pbxproj b/Stack/Stack Tests/Stack.xcodeproj/project.pbxproj deleted file mode 100644 index bfa645c10..000000000 --- a/Stack/Stack Tests/Stack.xcodeproj/project.pbxproj +++ /dev/null @@ -1,394 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 7B18E0431C5BF7F1005A2B8E /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B18E0421C5BF7F1005A2B8E /* AppDelegate.swift */; }; - 7B18E0451C5BF7F1005A2B8E /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7B18E0441C5BF7F1005A2B8E /* Assets.xcassets */; }; - 7B18E0481C5BF7F1005A2B8E /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7B18E0461C5BF7F1005A2B8E /* MainMenu.xib */; }; - 7B18E0531C5BF7F1005A2B8E /* StackTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B18E0521C5BF7F1005A2B8E /* StackTests.swift */; }; - 7B18E05E1C5BF80C005A2B8E /* Stack.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B18E05D1C5BF80C005A2B8E /* Stack.swift */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 7B18E04F1C5BF7F1005A2B8E /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 7B18E0371C5BF7F1005A2B8E /* Project object */; - proxyType = 1; - remoteGlobalIDString = 7B18E03E1C5BF7F1005A2B8E; - remoteInfo = Stack; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXFileReference section */ - 7B18E03F1C5BF7F1005A2B8E /* Stack.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Stack.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 7B18E0421C5BF7F1005A2B8E /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 7B18E0441C5BF7F1005A2B8E /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - 7B18E0471C5BF7F1005A2B8E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; - 7B18E0491C5BF7F1005A2B8E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 7B18E04E1C5BF7F1005A2B8E /* StackTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = StackTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 7B18E0521C5BF7F1005A2B8E /* StackTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StackTests.swift; sourceTree = ""; }; - 7B18E0541C5BF7F1005A2B8E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 7B18E05D1C5BF80C005A2B8E /* Stack.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Stack.swift; path = ../../Stack.swift; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 7B18E03C1C5BF7F1005A2B8E /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 7B18E04B1C5BF7F1005A2B8E /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 7B18E0361C5BF7F1005A2B8E = { - isa = PBXGroup; - children = ( - 7B18E0411C5BF7F1005A2B8E /* Stack */, - 7B18E0511C5BF7F1005A2B8E /* StackTests */, - 7B18E0401C5BF7F1005A2B8E /* Products */, - ); - sourceTree = ""; - }; - 7B18E0401C5BF7F1005A2B8E /* Products */ = { - isa = PBXGroup; - children = ( - 7B18E03F1C5BF7F1005A2B8E /* Stack.app */, - 7B18E04E1C5BF7F1005A2B8E /* StackTests.xctest */, - ); - name = Products; - sourceTree = ""; - }; - 7B18E0411C5BF7F1005A2B8E /* Stack */ = { - isa = PBXGroup; - children = ( - 7B18E0421C5BF7F1005A2B8E /* AppDelegate.swift */, - 7B18E0441C5BF7F1005A2B8E /* Assets.xcassets */, - 7B18E0491C5BF7F1005A2B8E /* Info.plist */, - 7B18E0461C5BF7F1005A2B8E /* MainMenu.xib */, - 7B18E05D1C5BF80C005A2B8E /* Stack.swift */, - ); - path = Stack; - sourceTree = ""; - }; - 7B18E0511C5BF7F1005A2B8E /* StackTests */ = { - isa = PBXGroup; - children = ( - 7B18E0521C5BF7F1005A2B8E /* StackTests.swift */, - 7B18E0541C5BF7F1005A2B8E /* Info.plist */, - ); - path = StackTests; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 7B18E03E1C5BF7F1005A2B8E /* Stack */ = { - isa = PBXNativeTarget; - buildConfigurationList = 7B18E0571C5BF7F1005A2B8E /* Build configuration list for PBXNativeTarget "Stack" */; - buildPhases = ( - 7B18E03B1C5BF7F1005A2B8E /* Sources */, - 7B18E03C1C5BF7F1005A2B8E /* Frameworks */, - 7B18E03D1C5BF7F1005A2B8E /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = Stack; - productName = Stack; - productReference = 7B18E03F1C5BF7F1005A2B8E /* Stack.app */; - productType = "com.apple.product-type.application"; - }; - 7B18E04D1C5BF7F1005A2B8E /* StackTests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 7B18E05A1C5BF7F1005A2B8E /* Build configuration list for PBXNativeTarget "StackTests" */; - buildPhases = ( - 7B18E04A1C5BF7F1005A2B8E /* Sources */, - 7B18E04B1C5BF7F1005A2B8E /* Frameworks */, - 7B18E04C1C5BF7F1005A2B8E /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - 7B18E0501C5BF7F1005A2B8E /* PBXTargetDependency */, - ); - name = StackTests; - productName = StackTests; - productReference = 7B18E04E1C5BF7F1005A2B8E /* StackTests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 7B18E0371C5BF7F1005A2B8E /* Project object */ = { - isa = PBXProject; - attributes = { - LastSwiftUpdateCheck = 0720; - LastUpgradeCheck = 0720; - ORGANIZATIONNAME = "Swift Algorithm Club"; - TargetAttributes = { - 7B18E03E1C5BF7F1005A2B8E = { - CreatedOnToolsVersion = 7.2; - }; - 7B18E04D1C5BF7F1005A2B8E = { - CreatedOnToolsVersion = 7.2; - TestTargetID = 7B18E03E1C5BF7F1005A2B8E; - }; - }; - }; - buildConfigurationList = 7B18E03A1C5BF7F1005A2B8E /* Build configuration list for PBXProject "Stack" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 7B18E0361C5BF7F1005A2B8E; - productRefGroup = 7B18E0401C5BF7F1005A2B8E /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 7B18E03E1C5BF7F1005A2B8E /* Stack */, - 7B18E04D1C5BF7F1005A2B8E /* StackTests */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 7B18E03D1C5BF7F1005A2B8E /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 7B18E0451C5BF7F1005A2B8E /* Assets.xcassets in Resources */, - 7B18E0481C5BF7F1005A2B8E /* MainMenu.xib in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 7B18E04C1C5BF7F1005A2B8E /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 7B18E03B1C5BF7F1005A2B8E /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 7B18E05E1C5BF80C005A2B8E /* Stack.swift in Sources */, - 7B18E0431C5BF7F1005A2B8E /* AppDelegate.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 7B18E04A1C5BF7F1005A2B8E /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 7B18E0531C5BF7F1005A2B8E /* StackTests.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 7B18E0501C5BF7F1005A2B8E /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 7B18E03E1C5BF7F1005A2B8E /* Stack */; - targetProxy = 7B18E04F1C5BF7F1005A2B8E /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin PBXVariantGroup section */ - 7B18E0461C5BF7F1005A2B8E /* MainMenu.xib */ = { - isa = PBXVariantGroup; - children = ( - 7B18E0471C5BF7F1005A2B8E /* Base */, - ); - name = MainMenu.xib; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 7B18E0551C5BF7F1005A2B8E /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "-"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.11; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = macosx; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - }; - name = Debug; - }; - 7B18E0561C5BF7F1005A2B8E /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "-"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.11; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = macosx; - }; - name = Release; - }; - 7B18E0581C5BF7F1005A2B8E /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = Stack/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Stack; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 7B18E0591C5BF7F1005A2B8E /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = Stack/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Stack; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - 7B18E05B1C5BF7F1005A2B8E /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = StackTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.StackTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Stack.app/Contents/MacOS/Stack"; - }; - name = Debug; - }; - 7B18E05C1C5BF7F1005A2B8E /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = StackTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.StackTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Stack.app/Contents/MacOS/Stack"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 7B18E03A1C5BF7F1005A2B8E /* Build configuration list for PBXProject "Stack" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 7B18E0551C5BF7F1005A2B8E /* Debug */, - 7B18E0561C5BF7F1005A2B8E /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 7B18E0571C5BF7F1005A2B8E /* Build configuration list for PBXNativeTarget "Stack" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 7B18E0581C5BF7F1005A2B8E /* Debug */, - 7B18E0591C5BF7F1005A2B8E /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 7B18E05A1C5BF7F1005A2B8E /* Build configuration list for PBXNativeTarget "StackTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 7B18E05B1C5BF7F1005A2B8E /* Debug */, - 7B18E05C1C5BF7F1005A2B8E /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 7B18E0371C5BF7F1005A2B8E /* Project object */; -} diff --git a/Stack/Stack Tests/Stack/AppDelegate.swift b/Stack/Stack Tests/Stack/AppDelegate.swift deleted file mode 100644 index 5daa0ee2d..000000000 --- a/Stack/Stack Tests/Stack/AppDelegate.swift +++ /dev/null @@ -1,27 +0,0 @@ -// -// AppDelegate.swift -// Stack -// -// Created by Matthijs Hollemans on 29-01-16. -// Copyright © 2016 Swift Algorithm Club. All rights reserved. -// - -import Cocoa - -@NSApplicationMain -class AppDelegate: NSObject, NSApplicationDelegate { - - @IBOutlet weak var window: NSWindow! - - - func applicationDidFinishLaunching(aNotification: NSNotification) { - // Insert code here to initialize your application - } - - func applicationWillTerminate(aNotification: NSNotification) { - // Insert code here to tear down your application - } - - -} - diff --git a/Stack/Stack Tests/Stack/Assets.xcassets/AppIcon.appiconset/Contents.json b/Stack/Stack Tests/Stack/Assets.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index 2db2b1c7c..000000000 --- a/Stack/Stack Tests/Stack/Assets.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "images" : [ - { - "idiom" : "mac", - "size" : "16x16", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "16x16", - "scale" : "2x" - }, - { - "idiom" : "mac", - "size" : "32x32", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "32x32", - "scale" : "2x" - }, - { - "idiom" : "mac", - "size" : "128x128", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "128x128", - "scale" : "2x" - }, - { - "idiom" : "mac", - "size" : "256x256", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "256x256", - "scale" : "2x" - }, - { - "idiom" : "mac", - "size" : "512x512", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "512x512", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/Stack/Stack Tests/Stack/Base.lproj/MainMenu.xib b/Stack/Stack Tests/Stack/Base.lproj/MainMenu.xib deleted file mode 100644 index d2e0528b5..000000000 --- a/Stack/Stack Tests/Stack/Base.lproj/MainMenu.xib +++ /dev/null @@ -1,680 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Default - - - - - - - Left to Right - - - - - - - Right to Left - - - - - - - - - - - Default - - - - - - - Left to Right - - - - - - - Right to Left - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Stack/Stack Tests/Stack/Info.plist b/Stack/Stack Tests/Stack/Info.plist deleted file mode 100644 index 0dca3caa8..000000000 --- a/Stack/Stack Tests/Stack/Info.plist +++ /dev/null @@ -1,34 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIconFile - - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - LSMinimumSystemVersion - $(MACOSX_DEPLOYMENT_TARGET) - NSHumanReadableCopyright - Copyright © 2016 Swift Algorithm Club. All rights reserved. - NSMainNibFile - MainMenu - NSPrincipalClass - NSApplication - - diff --git a/Stack/Stack Tests/StackTests/Info.plist b/Stack/Tests/Info.plist similarity index 100% rename from Stack/Stack Tests/StackTests/Info.plist rename to Stack/Tests/Info.plist diff --git a/Stack/Stack Tests/StackTests/StackTests.swift b/Stack/Tests/StackTests.swift similarity index 98% rename from Stack/Stack Tests/StackTests/StackTests.swift rename to Stack/Tests/StackTests.swift index 13aa77479..62e26b0fa 100755 --- a/Stack/Stack Tests/StackTests/StackTests.swift +++ b/Stack/Tests/StackTests.swift @@ -1,6 +1,5 @@ import Foundation import XCTest -@testable import Stack class StackTest: XCTestCase { func testEmpty() { diff --git a/Stack/Tests/Tests.xcodeproj/project.pbxproj b/Stack/Tests/Tests.xcodeproj/project.pbxproj new file mode 100644 index 000000000..a36d7c51d --- /dev/null +++ b/Stack/Tests/Tests.xcodeproj/project.pbxproj @@ -0,0 +1,261 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 7B80C4061C77A70A003CECC7 /* Stack.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C4051C77A70A003CECC7 /* Stack.swift */; }; + 7B80C4081C77A711003CECC7 /* StackTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C4071C77A711003CECC7 /* StackTests.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 7B2BBC801C779D720067B71D /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 7B2BBC941C779E7B0067B71D /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; + 7B80C4051C77A70A003CECC7 /* Stack.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Stack.swift; path = ../Stack.swift; sourceTree = SOURCE_ROOT; }; + 7B80C4071C77A711003CECC7 /* StackTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StackTests.swift; sourceTree = SOURCE_ROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 7B2BBC7D1C779D720067B71D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 7B2BBC681C779D710067B71D = { + isa = PBXGroup; + children = ( + 7B2BBC831C779D720067B71D /* Tests */, + 7B2BBC721C779D710067B71D /* Products */, + ); + sourceTree = ""; + }; + 7B2BBC721C779D710067B71D /* Products */ = { + isa = PBXGroup; + children = ( + 7B2BBC801C779D720067B71D /* Tests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 7B2BBC831C779D720067B71D /* Tests */ = { + isa = PBXGroup; + children = ( + 7B80C4051C77A70A003CECC7 /* Stack.swift */, + 7B80C4071C77A711003CECC7 /* StackTests.swift */, + 7B2BBC941C779E7B0067B71D /* Info.plist */, + ); + name = Tests; + path = TestsTests; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 7B2BBC7F1C779D720067B71D /* Tests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */; + buildPhases = ( + 7B2BBC7C1C779D720067B71D /* Sources */, + 7B2BBC7D1C779D720067B71D /* Frameworks */, + 7B2BBC7E1C779D720067B71D /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Tests; + productName = TestsTests; + productReference = 7B2BBC801C779D720067B71D /* Tests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 7B2BBC691C779D710067B71D /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0720; + LastUpgradeCheck = 0720; + ORGANIZATIONNAME = "Swift Algorithm Club"; + TargetAttributes = { + 7B2BBC7F1C779D720067B71D = { + CreatedOnToolsVersion = 7.2; + }; + }; + }; + buildConfigurationList = 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 7B2BBC681C779D710067B71D; + productRefGroup = 7B2BBC721C779D710067B71D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 7B2BBC7F1C779D720067B71D /* Tests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 7B2BBC7E1C779D720067B71D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 7B2BBC7C1C779D720067B71D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 7B80C4081C77A711003CECC7 /* StackTests.swift in Sources */, + 7B80C4061C77A70A003CECC7 /* Stack.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 7B2BBC871C779D720067B71D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 7B2BBC881C779D720067B71D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + }; + name = Release; + }; + 7B2BBC8D1C779D720067B71D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 7B2BBC8E1C779D720067B71D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7B2BBC871C779D720067B71D /* Debug */, + 7B2BBC881C779D720067B71D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7B2BBC8D1C779D720067B71D /* Debug */, + 7B2BBC8E1C779D720067B71D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 7B2BBC691C779D710067B71D /* Project object */; +} From c5b3ac93c05d3684d6e1e467ba5b5bdb5f7689c3 Mon Sep 17 00:00:00 2001 From: Matthijs Hollemans Date: Tue, 23 Feb 2016 22:22:24 +0100 Subject: [PATCH 0041/1679] Add Huffman coding --- .../Huffman.playground/Contents.swift | 23 + .../Huffman.playground/Sources/Heap.swift | 223 ++++++++++ .../Huffman.playground/Sources/Huffman.swift | 191 ++++++++ .../Sources/NSData+Bits.swift | 50 +++ .../Sources/PriorityQueue.swift | 58 +++ .../Huffman.playground/contents.xcplayground | 4 + .../Huffman.playground/timeline.xctimeline | 6 + Huffman Coding/Huffman.swift | 191 ++++++++ Huffman Coding/Images/BuildTree.gif | Bin 0 -> 24647 bytes Huffman Coding/Images/BuildTree.graffle | Bin 0 -> 13580 bytes Huffman Coding/Images/BuildTree.psd | Bin 0 -> 2619878 bytes Huffman Coding/Images/Compression.graffle | Bin 0 -> 4299 bytes Huffman Coding/Images/Compression.png | Bin 0 -> 54972 bytes Huffman Coding/Images/Decompression.graffle | Bin 0 -> 3944 bytes Huffman Coding/Images/Decompression.png | Bin 0 -> 47499 bytes Huffman Coding/Images/Tree.graffle | Bin 0 -> 3963 bytes Huffman Coding/Images/Tree.png | Bin 0 -> 38273 bytes Huffman Coding/NSData+Bits.swift | 50 +++ Huffman Coding/README.markdown | 417 ++++++++++++++++++ Priority Queue/README.markdown | 2 +- README.markdown | 7 +- 21 files changed, 1219 insertions(+), 3 deletions(-) create mode 100644 Huffman Coding/Huffman.playground/Contents.swift create mode 100644 Huffman Coding/Huffman.playground/Sources/Heap.swift create mode 100644 Huffman Coding/Huffman.playground/Sources/Huffman.swift create mode 100644 Huffman Coding/Huffman.playground/Sources/NSData+Bits.swift create mode 100644 Huffman Coding/Huffman.playground/Sources/PriorityQueue.swift create mode 100644 Huffman Coding/Huffman.playground/contents.xcplayground create mode 100644 Huffman Coding/Huffman.playground/timeline.xctimeline create mode 100644 Huffman Coding/Huffman.swift create mode 100644 Huffman Coding/Images/BuildTree.gif create mode 100644 Huffman Coding/Images/BuildTree.graffle create mode 100644 Huffman Coding/Images/BuildTree.psd create mode 100644 Huffman Coding/Images/Compression.graffle create mode 100644 Huffman Coding/Images/Compression.png create mode 100644 Huffman Coding/Images/Decompression.graffle create mode 100644 Huffman Coding/Images/Decompression.png create mode 100644 Huffman Coding/Images/Tree.graffle create mode 100644 Huffman Coding/Images/Tree.png create mode 100644 Huffman Coding/NSData+Bits.swift create mode 100644 Huffman Coding/README.markdown diff --git a/Huffman Coding/Huffman.playground/Contents.swift b/Huffman Coding/Huffman.playground/Contents.swift new file mode 100644 index 000000000..99170fa91 --- /dev/null +++ b/Huffman Coding/Huffman.playground/Contents.swift @@ -0,0 +1,23 @@ +//: Playground - noun: a place where people can play + +import Foundation + +let s1 = "so much words wow many compression" +if let originalData = s1.dataUsingEncoding(NSUTF8StringEncoding) { + print(originalData.length) + + let huffman1 = Huffman() + let compressedData = huffman1.compressData(originalData) + print(compressedData.length) + + let frequencyTable = huffman1.frequencyTable() + //print(frequencyTable) + + let huffman2 = Huffman() + let decompressedData = huffman2.decompressData(compressedData, frequencyTable: frequencyTable) + print(decompressedData.length) + + let s2 = String(data: decompressedData, encoding: NSUTF8StringEncoding)! + print(s2) + assert(s1 == s2) +} diff --git a/Huffman Coding/Huffman.playground/Sources/Heap.swift b/Huffman Coding/Huffman.playground/Sources/Heap.swift new file mode 100644 index 000000000..3293f75bb --- /dev/null +++ b/Huffman Coding/Huffman.playground/Sources/Heap.swift @@ -0,0 +1,223 @@ +// +// Heap.swift +// Written for the Swift Algorithm Club by Kevin Randrup and Matthijs Hollemans +// + +public struct Heap { + /** The array that stores the heap's nodes. */ + var elements = [T]() + + /** Determines whether this is a max-heap (>) or min-heap (<). */ + private var isOrderedBefore: (T, T) -> Bool + + /** + * Creates an empty heap. + * The sort function determines whether this is a min-heap or max-heap. + * For integers, > makes a max-heap, < makes a min-heap. + */ + public init(sort: (T, T) -> Bool) { + self.isOrderedBefore = sort + } + + /** + * Creates a heap from an array. The order of the array does not matter; + * the elements are inserted into the heap in the order determined by the + * sort function. + */ + public init(array: [T], sort: (T, T) -> Bool) { + self.isOrderedBefore = sort + buildHeap(array) + } + + /* + // This version has O(n log n) performance. + private mutating func buildHeap(array: [T]) { + elements.reserveCapacity(array.count) + for value in array { + insert(value) + } + } + */ + + /** + * Converts an array to a max-heap or min-heap in a bottom-up manner. + * Performance: This runs pretty much in O(n). + */ + private mutating func buildHeap(array: [T]) { + elements = array + for i in (elements.count/2 - 1).stride(through: 0, by: -1) { + shiftDown(index: i, heapSize: elements.count) + } + } + + public var isEmpty: Bool { + return elements.isEmpty + } + + public var count: Int { + return elements.count + } + + /** + * Returns the index of the parent of the element at index i. + * The element at index 0 is the root of the tree and has no parent. + */ + @inline(__always) func indexOfParent(i: Int) -> Int { + return (i - 1) / 2 + } + + /** + * Returns the index of the left child of the element at index i. + * Note that this index can be greater than the heap size, in which case + * there is no left child. + */ + @inline(__always) func indexOfLeftChild(i: Int) -> Int { + return 2*i + 1 + } + + /** + * Returns the index of the right child of the element at index i. + * Note that this index can be greater than the heap size, in which case + * there is no right child. + */ + @inline(__always) func indexOfRightChild(i: Int) -> Int { + return 2*i + 2 + } + + /** + * Returns the maximum value in the heap (for a max-heap) or the minimum + * value (for a min-heap). + */ + public func peek() -> T? { + return elements.first + } + + /** + * Adds a new value to the heap. This reorders the heap so that the max-heap + * or min-heap property still holds. Performance: O(log n). + */ + public mutating func insert(value: T) { + elements.append(value) + shiftUp(index: elements.count - 1) + } + + public mutating func insert(sequence: S) { + for value in sequence { + insert(value) + } + } + + /** + * Allows you to change an element. In a max-heap, the new element should be + * larger than the old one; in a min-heap it should be smaller. + */ + public mutating func replace(index i: Int, value: T) { + assert(isOrderedBefore(value, elements[i])) + elements[i] = value + shiftUp(index: i) + } + + /** + * Removes the root node from the heap. For a max-heap, this is the maximum + * value; for a min-heap it is the minimum value. Performance: O(log n). + */ + public mutating func remove() -> T? { + if elements.isEmpty { + return nil + } else if elements.count == 1 { + return elements.removeLast() + } else { + // Use the last node to replace the first one, then fix the heap by + // shifting this new first node into its proper position. + let value = elements[0] + elements[0] = elements.removeLast() + shiftDown() + return value + } + } + + /** + * Removes an arbitrary node from the heap. Performance: O(log n). You need + * to know the node's index, which may actually take O(n) steps to find. + */ + public mutating func removeAtIndex(i: Int) -> T? { + let size = elements.count - 1 + if i != size { + swap(&elements[i], &elements[size]) + shiftDown(index: i, heapSize: size) + shiftUp(index: i) + } + return elements.removeLast() + } + + /** + * Takes a child node and looks at its parents; if a parent is not larger + * (max-heap) or not smaller (min-heap) than the child, we exchange them. + */ + mutating func shiftUp(index index: Int) { + var childIndex = index + let child = elements[childIndex] + var parentIndex = indexOfParent(childIndex) + + while childIndex > 0 && isOrderedBefore(child, elements[parentIndex]) { + elements[childIndex] = elements[parentIndex] + childIndex = parentIndex + parentIndex = indexOfParent(childIndex) + } + + elements[childIndex] = child + } + + mutating func shiftDown() { + shiftDown(index: 0, heapSize: elements.count) + } + + /** + * Looks at a parent node and makes sure it is still larger (max-heap) or + * smaller (min-heap) than its childeren. + */ + mutating func shiftDown(index index: Int, heapSize: Int) { + var parentIndex = index + + while true { + let leftChildIndex = indexOfLeftChild(parentIndex) + let rightChildIndex = leftChildIndex + 1 + + // Figure out which comes first if we order them by the sort function: + // the parent, the left child, or the right child. If the parent comes + // first, we're done. If not, that element is out-of-place and we make + // it "float down" the tree until the heap property is restored. + var first = parentIndex + if leftChildIndex < heapSize && isOrderedBefore(elements[leftChildIndex], elements[first]) { + first = leftChildIndex + } + if rightChildIndex < heapSize && isOrderedBefore(elements[rightChildIndex], elements[first]) { + first = rightChildIndex + } + if first == parentIndex { return } + + swap(&elements[parentIndex], &elements[first]) + parentIndex = first + } + } +} + +// MARK: - Searching + +extension Heap where T: Equatable { + /** + * Searches the heap for the given element. Performance: O(n). + */ + public func indexOf(element: T) -> Int? { + return indexOf(element, 0) + } + + private func indexOf(element: T, _ i: Int) -> Int? { + if i >= count { return nil } + if isOrderedBefore(element, elements[i]) { return nil } + if element == elements[i] { return i } + if let j = indexOf(element, indexOfLeftChild(i)) { return j } + if let j = indexOf(element, indexOfRightChild(i)) { return j } + return nil + } +} diff --git a/Huffman Coding/Huffman.playground/Sources/Huffman.swift b/Huffman Coding/Huffman.playground/Sources/Huffman.swift new file mode 100644 index 000000000..0b6da03af --- /dev/null +++ b/Huffman Coding/Huffman.playground/Sources/Huffman.swift @@ -0,0 +1,191 @@ +import Foundation + +/* + Basic implementation of Huffman encoding. It encodes bytes that occur often + with a smaller number of bits than bytes that occur less frequently. + + Based on Al Stevens' C Programming column from Dr.Dobb's Magazine, February + 1991 and October 1992. + + Note: This code is not optimized for speed but explanation. +*/ +public class Huffman { + /* Tree nodes don't use pointers to refer to each other, but simple integer + indices. That allows us to use structs for the nodes. */ + typealias NodeIndex = Int + + /* A node in the compression tree. Leaf nodes represent the actual bytes that + are present in the input data. The count of an intermediary node is the sum + of the counts of all nodes below it. The root node's count is the number of + bytes in the original, uncompressed input data. */ + struct Node { + var count = 0 + var index: NodeIndex = -1 + var parent: NodeIndex = -1 + var left: NodeIndex = -1 + var right: NodeIndex = -1 + } + + /* The tree structure. The first 256 entries are for the leaf nodes (not all + of those may be used, depending on the input). We add additional nodes as + we build the tree. */ + var tree = [Node](count: 256, repeatedValue: Node()) + + /* This is the last node we add to the tree. */ + var root: NodeIndex = -1 + + /* The frequency table describes how often a byte occurs in the input data. + You need it to decompress the Huffman-encoded data. The frequency table + should be serialized along with the compressed data. */ + public struct Freq { + var byte: UInt8 = 0 + var count = 0 + } + + public init() { } +} + +extension Huffman { + /* To compress a block of data, first we need to count how often each byte + occurs. These counts are stored in the first 256 nodes in the tree, i.e. + the leaf nodes. The frequency table used by decompression is derived from + this. */ + private func countByteFrequency(data: NSData) { + var ptr = UnsafePointer(data.bytes) + for _ in 0.. [Freq] { + var a = [Freq]() + for i in 0..<256 where tree[i].count > 0 { + a.append(Freq(byte: UInt8(i), count: tree[i].count)) + } + return a + } +} + +extension Huffman { + /* Builds a Huffman tree from a frequency table. */ + private func buildTree() { + // Create a min-priority queue and enqueue all used nodes. + var queue = PriorityQueue(sort: { $0.count < $1.count }) + for node in tree where node.count > 0 { + queue.enqueue(node) + } + + while queue.count > 1 { + // Find the two nodes with the smallest frequencies that do not have + // a parent node yet. + let node1 = queue.dequeue()! + let node2 = queue.dequeue()! + + // Create a new intermediate node. + var parentNode = Node() + parentNode.count = node1.count + node2.count + parentNode.left = node1.index + parentNode.right = node2.index + parentNode.index = tree.count + tree.append(parentNode) + + // Link the two nodes into their new parent node. + tree[node1.index].parent = parentNode.index + tree[node2.index].parent = parentNode.index + + // Put the intermediate node back into the queue. + queue.enqueue(parentNode) + } + + // The final remaining node in the queue becomes the root of the tree. + let rootNode = queue.dequeue()! + root = rootNode.index + } +} + +extension Huffman { + /* Compresses the contents of an NSData object. */ + public func compressData(data: NSData) -> NSData { + countByteFrequency(data) + buildTree() + + let writer = BitWriter() + var ptr = UnsafePointer(data.bytes) + for _ in 0.. NSData { + restoreTree(frequencyTable) + + let reader = BitReader(data: data) + let outData = NSMutableData() + let byteCount = tree[root].count + + var i = 0 + while i < byteCount { + var b = findLeafNode(reader: reader, nodeIndex: root) + outData.appendBytes(&b, length: 1) + i += 1 + } + return outData + } + + /* Walks the tree from the root down to the leaf node. At every node, read the + next bit and use that to determine whether to step to the left or right. + When we get to the leaf node, we simply return its index, which is equal to + the original byte value. */ + private func findLeafNode(reader reader: BitReader, nodeIndex: Int) -> UInt8 { + var h = nodeIndex + while tree[h].right != -1 { + if reader.readBit() { + h = tree[h].left + } else { + h = tree[h].right + } + } + return UInt8(h) + } +} diff --git a/Huffman Coding/Huffman.playground/Sources/NSData+Bits.swift b/Huffman Coding/Huffman.playground/Sources/NSData+Bits.swift new file mode 100644 index 000000000..beb669dd1 --- /dev/null +++ b/Huffman Coding/Huffman.playground/Sources/NSData+Bits.swift @@ -0,0 +1,50 @@ +import Foundation + +/* Helper class for writing bits to an NSData object. */ +public class BitWriter { + public var data = NSMutableData() + var outByte: UInt8 = 0 + var outCount = 0 + + public func writeBit(bit: Bool) { + if outCount == 8 { + data.appendBytes(&outByte, length: 1) + outCount = 0 + } + outByte = (outByte << 1) | (bit ? 1 : 0) + outCount += 1 + } + + public func flush() { + if outCount > 0 { + if outCount < 8 { + let diff = UInt8(8 - outCount) + outByte <<= diff + } + data.appendBytes(&outByte, length: 1) + } + } +} + +/* Helper class for reading bits from an NSData object. */ +public class BitReader { + var ptr: UnsafePointer + var inByte: UInt8 = 0 + var inCount = 8 + + public init(data: NSData) { + ptr = UnsafePointer(data.bytes) + } + + public func readBit() -> Bool { + if inCount == 8 { + inByte = ptr.memory // load the next byte + inCount = 0 + ptr = ptr.successor() + } + let bit = inByte & 0x80 // read the next bit + inByte <<= 1 + inCount += 1 + return bit == 0 ? false : true + } +} diff --git a/Huffman Coding/Huffman.playground/Sources/PriorityQueue.swift b/Huffman Coding/Huffman.playground/Sources/PriorityQueue.swift new file mode 100644 index 000000000..7a7cee34b --- /dev/null +++ b/Huffman Coding/Huffman.playground/Sources/PriorityQueue.swift @@ -0,0 +1,58 @@ +/* + Priority Queue, a queue where the most "important" items are at the front of + the queue. + + The heap is a natural data structure for a priority queue, so this object + simply wraps the Heap struct. + + All operations are O(lg n). + + Just like a heap can be a max-heap or min-heap, the queue can be a max-priority + queue (largest element first) or a min-priority queue (smallest element first). +*/ +public struct PriorityQueue { + private var heap: Heap + + /* + To create a max-priority queue, supply a > sort function. For a min-priority + queue, use <. + */ + public init(sort: (T, T) -> Bool) { + heap = Heap(sort: sort) + } + + public var isEmpty: Bool { + return heap.isEmpty + } + + public var count: Int { + return heap.count + } + + public func peek() -> T? { + return heap.peek() + } + + public mutating func enqueue(element: T) { + heap.insert(element) + } + + public mutating func dequeue() -> T? { + return heap.remove() + } + + /* + Allows you to change the priority of an element. In a max-priority queue, + the new priority should be larger than the old one; in a min-priority queue + it should be smaller. + */ + public mutating func changePriority(index i: Int, value: T) { + return heap.replace(index: i, value: value) + } +} + +extension PriorityQueue where T: Equatable { + public func indexOf(element: T) -> Int? { + return heap.indexOf(element) + } +} diff --git a/Huffman Coding/Huffman.playground/contents.xcplayground b/Huffman Coding/Huffman.playground/contents.xcplayground new file mode 100644 index 000000000..06828af92 --- /dev/null +++ b/Huffman Coding/Huffman.playground/contents.xcplayground @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Huffman Coding/Huffman.playground/timeline.xctimeline b/Huffman Coding/Huffman.playground/timeline.xctimeline new file mode 100644 index 000000000..bf468afec --- /dev/null +++ b/Huffman Coding/Huffman.playground/timeline.xctimeline @@ -0,0 +1,6 @@ + + + + + diff --git a/Huffman Coding/Huffman.swift b/Huffman Coding/Huffman.swift new file mode 100644 index 000000000..0b6da03af --- /dev/null +++ b/Huffman Coding/Huffman.swift @@ -0,0 +1,191 @@ +import Foundation + +/* + Basic implementation of Huffman encoding. It encodes bytes that occur often + with a smaller number of bits than bytes that occur less frequently. + + Based on Al Stevens' C Programming column from Dr.Dobb's Magazine, February + 1991 and October 1992. + + Note: This code is not optimized for speed but explanation. +*/ +public class Huffman { + /* Tree nodes don't use pointers to refer to each other, but simple integer + indices. That allows us to use structs for the nodes. */ + typealias NodeIndex = Int + + /* A node in the compression tree. Leaf nodes represent the actual bytes that + are present in the input data. The count of an intermediary node is the sum + of the counts of all nodes below it. The root node's count is the number of + bytes in the original, uncompressed input data. */ + struct Node { + var count = 0 + var index: NodeIndex = -1 + var parent: NodeIndex = -1 + var left: NodeIndex = -1 + var right: NodeIndex = -1 + } + + /* The tree structure. The first 256 entries are for the leaf nodes (not all + of those may be used, depending on the input). We add additional nodes as + we build the tree. */ + var tree = [Node](count: 256, repeatedValue: Node()) + + /* This is the last node we add to the tree. */ + var root: NodeIndex = -1 + + /* The frequency table describes how often a byte occurs in the input data. + You need it to decompress the Huffman-encoded data. The frequency table + should be serialized along with the compressed data. */ + public struct Freq { + var byte: UInt8 = 0 + var count = 0 + } + + public init() { } +} + +extension Huffman { + /* To compress a block of data, first we need to count how often each byte + occurs. These counts are stored in the first 256 nodes in the tree, i.e. + the leaf nodes. The frequency table used by decompression is derived from + this. */ + private func countByteFrequency(data: NSData) { + var ptr = UnsafePointer(data.bytes) + for _ in 0.. [Freq] { + var a = [Freq]() + for i in 0..<256 where tree[i].count > 0 { + a.append(Freq(byte: UInt8(i), count: tree[i].count)) + } + return a + } +} + +extension Huffman { + /* Builds a Huffman tree from a frequency table. */ + private func buildTree() { + // Create a min-priority queue and enqueue all used nodes. + var queue = PriorityQueue(sort: { $0.count < $1.count }) + for node in tree where node.count > 0 { + queue.enqueue(node) + } + + while queue.count > 1 { + // Find the two nodes with the smallest frequencies that do not have + // a parent node yet. + let node1 = queue.dequeue()! + let node2 = queue.dequeue()! + + // Create a new intermediate node. + var parentNode = Node() + parentNode.count = node1.count + node2.count + parentNode.left = node1.index + parentNode.right = node2.index + parentNode.index = tree.count + tree.append(parentNode) + + // Link the two nodes into their new parent node. + tree[node1.index].parent = parentNode.index + tree[node2.index].parent = parentNode.index + + // Put the intermediate node back into the queue. + queue.enqueue(parentNode) + } + + // The final remaining node in the queue becomes the root of the tree. + let rootNode = queue.dequeue()! + root = rootNode.index + } +} + +extension Huffman { + /* Compresses the contents of an NSData object. */ + public func compressData(data: NSData) -> NSData { + countByteFrequency(data) + buildTree() + + let writer = BitWriter() + var ptr = UnsafePointer(data.bytes) + for _ in 0.. NSData { + restoreTree(frequencyTable) + + let reader = BitReader(data: data) + let outData = NSMutableData() + let byteCount = tree[root].count + + var i = 0 + while i < byteCount { + var b = findLeafNode(reader: reader, nodeIndex: root) + outData.appendBytes(&b, length: 1) + i += 1 + } + return outData + } + + /* Walks the tree from the root down to the leaf node. At every node, read the + next bit and use that to determine whether to step to the left or right. + When we get to the leaf node, we simply return its index, which is equal to + the original byte value. */ + private func findLeafNode(reader reader: BitReader, nodeIndex: Int) -> UInt8 { + var h = nodeIndex + while tree[h].right != -1 { + if reader.readBit() { + h = tree[h].left + } else { + h = tree[h].right + } + } + return UInt8(h) + } +} diff --git a/Huffman Coding/Images/BuildTree.gif b/Huffman Coding/Images/BuildTree.gif new file mode 100644 index 0000000000000000000000000000000000000000..ddfce5c9bd630123123e7ed8dfd2f01c24c237d3 GIT binary patch literal 24647 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 Tzg5Y0$;fpYp2!Zqf${$UK!FH( literal 0 HcmV?d00001 diff --git a/Huffman Coding/Images/BuildTree.psd b/Huffman Coding/Images/BuildTree.psd new file mode 100644 index 0000000000000000000000000000000000000000..f3145aa4463be47848f47e9a3b4369b77bff661a GIT binary patch literal 2619878 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�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
F{EDc=(dYbzNOGB4{p60&6($FQK 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 r;~j~nKoH_cZp0GyxCXcp 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

RSBxmsG%ax_>9C&1x-NM4ne;)F0Fz@q0-J6sbq# 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

AGkKRGrhE{TM`B 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 literal 0 HcmV?d00001 diff --git a/Huffman Coding/Images/Decompression.graffle b/Huffman Coding/Images/Decompression.graffle new file mode 100644 index 0000000000000000000000000000000000000000..dcfd906bd6ef89260d00cfa4684e336fc26a8843 GIT binary patch literal 3944 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 VKgnm;lX~0R`adK(7}1}L0RUps#7+PJ literal 0 HcmV?d00001 diff --git a/Huffman Coding/Images/Tree.png b/Huffman Coding/Images/Tree.png new file mode 100644 index 0000000000000000000000000000000000000000..a90b11986ea4fb24d03289b2e4f50647d061ac96 GIT binary patch literal 38273 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 Y>Py{c3|I^@@Zi@?HC@$GWsAW71ty-qCjbBd literal 0 HcmV?d00001 diff --git a/Huffman Coding/NSData+Bits.swift b/Huffman Coding/NSData+Bits.swift new file mode 100644 index 000000000..beb669dd1 --- /dev/null +++ b/Huffman Coding/NSData+Bits.swift @@ -0,0 +1,50 @@ +import Foundation + +/* Helper class for writing bits to an NSData object. */ +public class BitWriter { + public var data = NSMutableData() + var outByte: UInt8 = 0 + var outCount = 0 + + public func writeBit(bit: Bool) { + if outCount == 8 { + data.appendBytes(&outByte, length: 1) + outCount = 0 + } + outByte = (outByte << 1) | (bit ? 1 : 0) + outCount += 1 + } + + public func flush() { + if outCount > 0 { + if outCount < 8 { + let diff = UInt8(8 - outCount) + outByte <<= diff + } + data.appendBytes(&outByte, length: 1) + } + } +} + +/* Helper class for reading bits from an NSData object. */ +public class BitReader { + var ptr: UnsafePointer + var inByte: UInt8 = 0 + var inCount = 8 + + public init(data: NSData) { + ptr = UnsafePointer(data.bytes) + } + + public func readBit() -> Bool { + if inCount == 8 { + inByte = ptr.memory // load the next byte + inCount = 0 + ptr = ptr.successor() + } + let bit = inByte & 0x80 // read the next bit + inByte <<= 1 + inCount += 1 + return bit == 0 ? false : true + } +} diff --git a/Huffman Coding/README.markdown b/Huffman Coding/README.markdown new file mode 100644 index 000000000..56623d60f --- /dev/null +++ b/Huffman Coding/README.markdown @@ -0,0 +1,417 @@ +# Huffman Coding + +The idea: Encode objects that occur often with a smaller number of bits than objects that occur less frequently. + +Although you can encode any type of objects with this scheme, it's most common to compress a stream of bytes. Let's say you have the following text, where each character is one byte: + + so much words wow many compression + +If you count how often each byte appears, you can clearly see that some bytes occur more than others: + + space: 5 u: 1 + o: 5 h: 1 + s: 4 d: 1 + m: 3 a: 1 + w: 3 y: 1 + c: 2 p: 1 + r: 2 e: 1 + n: 2 i: 1 + +We can assign bit strings to each of these bytes. The more common a byte is, the fewer bits we assign to it. We might get something like this: + + space: 5 010 u: 1 11001 + o: 5 000 h: 1 10001 + s: 4 101 d: 1 11010 + m: 3 111 a: 1 11011 + w: 3 0010 y: 1 01111 + c: 2 0011 p: 1 11000 + r: 2 1001 e: 1 01110 + n: 2 0110 i: 1 10000 + +Now if we replace the original bytes with these bit strings, the compressed output becomes: + + 101 000 010 111 11001 0011 10001 010 0010 000 1001 11010 101 + s o _ m u c h _ w o r d s + + 010 0010 000 0010 010 111 11011 0110 01111 010 0011 000 111 + _ w o w _ m a n y _ c o m + + 11000 1001 01110 101 101 10000 000 0110 0 + p r e s s i o n + +The extra 0-bit at the end is there to make a full number of bytes. We were able to compress the original 34 bytes into merely 16 bytes, a space savings of over 50%! + +But hold on... to be able to decode these bits we need to have the original frequency table. That table needs to be transmitted or saved along with the compressed data, otherwise the decoder doesn't know how to interpret the bits. Because of the overhead of this frequency table, it doesn't really pay to use Huffman encoding on very small inputs. + +## How it works + +When compressing a stream of bytes, the algorithm first creates a frequency table that counts how often each byte occurs. Based on this table it creates a binary tree that describes the bit strings for each of the input bytes. + +For our example, the tree looks like this: + +![The compression tree](Images/Tree.png) + +Note that the tree has 16 leaf nodes (the grey ones), one for each byte value from the input. Each leaf node also shows the count of how often it occurs. The other nodes are "intermediate" nodes. The number shown in these nodes is the sum of the counts of their child nodes. The count of the root node is therefore the total number of bytes in the input. + +The edges between the nodes either say "1" or "0". These correspond to the bit-encodings of the leaf nodes. Notice how each left branch is always 1 and each right branch is always 0. + +Compression is then a matter of looping through the input bytes, and for each byte traverse the tree from the root node to that byte's leaf node. Every time we take a left branch, we emit a 1-bit. When we take a right branch, we emit a 0-bit. + +For example, to go from the root node to `c`, we go right (`0`), right again (`0`), left (`1`), and left again (`1`). So the Huffman code for `c` is `0011`. + +Decompression works in exactly the opposite way. It reads the compressed bits one-by-one and traverses the tree until we get to a leaf node. The value of that leaf node is the uncompressed byte. For example, if the bits are `11010`, we start at the root and go left, left again, right, left, and a final right to end up at `d`. + +## The code + +Before we get to the actual Huffman coding scheme, it's useful to have some helper code that can write individual bits to an `NSData` object. The smallest piece of data that `NSData` understands is the byte. But we're dealing in bits, so we need to translate between the two. + +```swift +public class BitWriter { + public var data = NSMutableData() + var outByte: UInt8 = 0 + var outCount = 0 + + public func writeBit(bit: Bool) { + if outCount == 8 { + data.appendBytes(&outByte, length: 1) + outCount = 0 + } + outByte = (outByte << 1) | (bit ? 1 : 0) + outCount += 1 + } + + public func flush() { + if outCount > 0 { + if outCount < 8 { + let diff = UInt8(8 - outCount) + outByte <<= diff + } + data.appendBytes(&outByte, length: 1) + } + } +} +``` + +To add a bit to the `NSData` you call `writeBit()`. This simply stuffs each new bit into the `outByte` variable. Once you've written 8 bits, `outByte` gets added to the `NSData` object for real. + +The `flush()` method is used for outputting the very last byte. There is no guarantee that the number of compressed bits is a nice round multiple of 8, in which case there may be some spare bits at the end. If so, `flush()` adds a few 0-bits to make sure that we write a full byte. + +We'll use a similar helper object for reading individual bits from `NSData`: + +```swift +public class BitReader { + var ptr: UnsafePointer + var inByte: UInt8 = 0 + var inCount = 8 + + public init(data: NSData) { + ptr = UnsafePointer(data.bytes) + } + + public func readBit() -> Bool { + if inCount == 8 { + inByte = ptr.memory // load the next byte + inCount = 0 + ptr = ptr.successor() + } + let bit = inByte & 0x80 // read the next bit + inByte <<= 1 + inCount += 1 + return bit == 0 ? false : true + } +} +``` + +This works in a similar fashion. We read one whole byte from the `NSData` object and put it in `inByte`. Then `readBit()` returns the individual bits from that byte. Once `readBit()` has been called 8 times, we read the next byte from the `NSData`. + +> **Note:** It's no big deal if you're unfamiliar with this sort of bit manipulation. Just know that these two helper objects make it simple for us to write and read bits and not worry about all the messy stuff of making sure they end up in the right place. + +## The frequency table + +The first step in Huffman compression is to read the entire input stream and build a frequency table. This table contains a list of all 256 possible byte values and how often each of these bytes occurs in the input data. + +We could store this frequency information in a dictionary or an array, but since we're going to need to build a tree anyway, we might as well store the frequency table as the leaves of the tree. + +Here are the definitions we need: + +```swift +class Huffman { + typealias NodeIndex = Int + + struct Node { + var count = 0 + var index: NodeIndex = -1 + var parent: NodeIndex = -1 + var left: NodeIndex = -1 + var right: NodeIndex = -1 + } + + var tree = [Node](count: 256, repeatedValue: Node()) + + var root: NodeIndex = -1 +} +``` + +The tree structure is stored in the `tree` array and will be made up of `Node` objects. Since this is a [binary tree](../Binary Tree/), each node needs two children, `left` and `right`, and a reference back to its `parent` node. Unlike a typical binary tree, however, these nodes don't to use pointers to refer to each other but simple integer indices in the `tree` array. (We also store the array `index` of the node itself; the reason for this will become clear later.) + +Note that `tree` currently has room for 256 entries. These are for the leaf nodes because there are 256 possible byte values. Of course, not all of those may end up being used, depending on the input data. Later, we'll add more nodes as we build up the actual tree. For the moment there isn't a tree yet, just 256 separate leaf nodes with no connections between them. All the node counts are 0. + +We use the following method to count how often each byte occurs in the input data: + +```swift + private func countByteFrequency(data: NSData) { + var ptr = UnsafePointer(data.bytes) + for _ in 0.. [Freq] { + var a = [Freq]() + for i in 0..<256 where tree[i].count > 0 { + a.append(Freq(byte: UInt8(i), count: tree[i].count)) + } + return a + } +``` + +The `frequencyTable()` method looks at those first 256 nodes from the tree but keeps only those that are actually used, without the `parent`, `left`, and `right` pointers. You would serialize the array it returns along with the compressed file so that it can be properly decompressed later. + +## The tree + +As a reminder, there is the compression tree for the example: + +![The compression tree](Images/Tree.png) + +The leaf nodes represent the actual bytes that are present in the input data. The intermediary nodes connect the leaves in such a way that the path from the root to a frequently-used byte value is shorter than the path to a less common byte value. As you can see, `m`, `s`, space, and `o` are the most common letters in our input data and therefore they are highest up in the tree. + +To build the tree, we do the following: + +1. Find the two nodes with the smallest counts that do not have a parent node yet. +2. Add a new parent node that links these two nodes together. +3. This repeats over and over until only one node with no parent remains. This becomes the root node of the tree. + +This is an ideal place to use a [priority queue](../Priority Queue/). A priority queue is a data structure that is optimized so that finding the minimum value is always very fast. Here, we repeatedly need to find the node with the smallest count. + +The function `buildTree()` then becomes: + +```swift + private func buildTree() { + var queue = PriorityQueue(sort: { $0.count < $1.count }) + for node in tree where node.count > 0 { + queue.enqueue(node) // 1 + } + + while queue.count > 1 { + let node1 = queue.dequeue()! // 2 + let node2 = queue.dequeue()! + + var parentNode = Node() // 3 + parentNode.count = node1.count + node2.count + parentNode.left = node1.index + parentNode.right = node2.index + parentNode.index = tree.count + tree.append(parentNode) + + tree[node1.index].parent = parentNode.index // 4 + tree[node2.index].parent = parentNode.index + + queue.enqueue(parentNode) // 5 + } + + let rootNode = queue.dequeue()! // 6 + root = rootNode.index + } +``` + +Here is how it works step-by-step: + +1. Create a priority queue and enqueue all the leaf nodes that have at least a count of 1. (If the count is 0, then this byte value did not appear in the input data.) The `PriorityQueue` object sorts the nodes by their count, so that the node with the lowest count is always the first one that gets dequeued. + +2. While there are at least two nodes left in the queue, remove the two nodes that are at the front of the queue. Since this is a min-priority queue, this gives us the two nodes with the smallest counts that do not have a parent node yet. + +3. Create a new intermediate node that connects `node1` and `node2`. The count of this new node is the sum of the counts of `node1` and `node2`. Because the nodes are connected using array indices instead of real pointers, we use `node1.index` and `node2.index` to find these nodes in the `tree` array. (This is why a `Node` needs to know its own index.) + +4. Link the two nodes into their new parent node. Now this new intermediate node has become part of the tree. + +5. Put the new intermediate node back into the queue. At this point we're done with `node1` and `node2`, but the `parentNode` stills need to be connected to other nodes in the tree. + +6. Repeat steps 2-5 until there is only one node left in the queue. This becomes the root node of the tree, and we're done. + +This is what the process looks like: + +![Building the tree](Images/BuildTree.gif) + +> **Note:** Instead of using a priority queue, you can iterate through the `tree` array to find the next two smallest nodes, but that makes the compressor quite slow, **O(n^2)**. Using the priority queue, the running time is only **O(n log n)** where **n** is the number of nodes. + +> **Note:** Due to the nature of binary trees, if we have *x* leaf nodes we can at most add *x - 1* additional nodes to the tree. Given that at most there will be 256 leaf nodes, the tree will never contain more than 511 nodes total. + +## Compression + +Now that we know how to build the compression tree from the frequency table, we can use it to compress the contents of an `NSData` object. Here is the code: + +``` + func compressData(data: NSData) -> NSData { + countByteFrequency(data) + buildTree() + + let writer = BitWriter() + var ptr = UnsafePointer(data.bytes) + + for _ in 0.. **Note:** Compression always requires two passes through the entire input data: first to build the frequency table, second to convert the bytes to their compressed bit sequences. + +The interesting stuff happens in `traverseTree()`. This is a recursive method: + +``` + private func traverseTree(writer writer: BitWriter, nodeIndex h: Int, childIndex child: Int) { + if tree[h].parent != -1 { + traverseTree(writer: writer, nodeIndex: tree[h].parent, childIndex: h) + } + if child != -1 { + if child == tree[h].left { + writer.writeBit(true) + } else if child == tree[h].right { + writer.writeBit(false) + } + } + } +``` + +When we call this method from `compressData()`, the `nodeIndex` parameter is the array index of the leaf node for the byte that we're about to encode. This method recursively walks the tree from a leaf node up to the root, and then back again. + +As we're going back from the root to the leaf node, we write a 1 bit or a 0 bit for every node we encounter. If a child is the left node, we emit a 1; if it's the right node, we emit a 0. + +In a picture: + +![How compression works](Images/Compression.png) + +Note that, even through the illustration of the tree shows a 0 or 1 for each edge between the nodes, the bit values 0 and 1 aren't actually stored in the tree! The rule is that we write a 1 bit if we take the left branch and a 0 bit if we take the right branch, so just knowing the direction we're going in is enough to determine what bit value to write. + +You use the `compressData()` method as follows: + +```swift +let s1 = "so much words wow many compression" +if let originalData = s1.dataUsingEncoding(NSUTF8StringEncoding) { + let huffman1 = Huffman() + let compressedData = huffman1.compressData(originalData) + print(compressedData.length) +} +``` + +## Decompression + +Decompression is pretty much compression in reverse. However, the compressed bits are useless to us without the frequency table. Earlier you saw the `frequencyTable()` method that returns an array of `Freq` objects. The idea is that if you were saving the compressed data into a file or sending it across the network, you'd also save that `[Freq]` array along with it. + +We first need some way to turn the `[Freq]` array back into a compression tree. Fortunately, this is pretty easy: + +```swift + private func restoreTree(frequencyTable: [Freq]) { + for freq in frequencyTable { + let i = Int(freq.byte) + tree[i].count = freq.count + tree[i].index = i + } + buildTree() + } +``` + +We convert the `Freq` objects into leaf nodes and then call `buildTree()` to do the rest. + +Here is the code for `decompressData()`, which takes an `NSData` object with Huffman-encoded bits and a frequency table, and returns the original data: + +```swift + func decompressData(data: NSData, frequencyTable: [Freq]) -> NSData { + restoreTree(frequencyTable) + + let reader = BitReader(data: data) + let outData = NSMutableData() + let byteCount = tree[root].count + + var i = 0 + while i < byteCount { + var b = findLeafNode(reader: reader, nodeIndex: root) + outData.appendBytes(&b, length: 1) + i += 1 + } + return outData + } +``` + +This also uses a helper method to traverse the tree: + +```swift + private func findLeafNode(reader reader: BitReader, nodeIndex: Int) -> UInt8 { + var h = nodeIndex + while tree[h].right != -1 { + if reader.readBit() { + h = tree[h].left + } else { + h = tree[h].right + } + } + return UInt8(h) + } +``` + +`findLeafNode()` walks the tree from the root down to the leaf node given by `nodeIndex`. At each intermediate node we read a new bit and then step to the left (bit is 1) or the right (bit is 0). When we get to the leaf node, we simply return its index, which is equal to the original byte value. + +In a picture: + +![How decompression works](Images/Decompression.png) + +Here's how you would use the decompression method: + +```swift + let frequencyTable = huffman1.frequencyTable() + + let huffman2 = Huffman() + let decompressedData = huffman2.decompressData(compressedData, frequencyTable: frequencyTable) + + let s2 = String(data: decompressedData, encoding: NSUTF8StringEncoding)! +``` + +First you get the frequency table from somewhere (in this case the `Huffman` object we used to encode the data) and then call `decompressData()`. The string that results should be equal to the one you compressed in the first place. + +You can see how this works in more detail in the Playground. + +## See also + +[Huffman coding at Wikipedia](https://en.wikipedia.org/wiki/Huffman_coding) + +The code is based on Al Stevens' C Programming column from Dr.Dobb's Magazine, February 1991 and October 1992. + +*Written for Swift Algorithm Club by Matthijs Hollemans* diff --git a/Priority Queue/README.markdown b/Priority Queue/README.markdown index c5e088520..0c04e7445 100644 --- a/Priority Queue/README.markdown +++ b/Priority Queue/README.markdown @@ -12,7 +12,7 @@ Examples of algorithms that can benefit from a priority queue: - Event-driven simulations. Each event is given a timestamp and you want events to be performed in order of their timestamps. The priority queue makes it easy to find the next event that needs to be simulated. - Dijkstra's algorithm for graph searching uses a priority queue to calculate the minimum cost. -- [Huffman encoding](../Huffman Encoding/) for data compression. This algorithm builds up a compression tree. It repeatedly needs to find the two nodes with the smallest frequencies that do not have a parent node yet. +- [Huffman coding](../Huffman Coding/) for data compression. This algorithm builds up a compression tree. It repeatedly needs to find the two nodes with the smallest frequencies that do not have a parent node yet. - A* pathfinding for artificial intelligence. - Lots of other places! diff --git a/README.markdown b/README.markdown index 8a08a7575..b924f88f1 100644 --- a/README.markdown +++ b/README.markdown @@ -80,8 +80,8 @@ Bad sorting algorithms (don't use these!): ### Compression -- [Run-Length Encoding (RLE)](Run-Length Encoding) -- Huffman Encoding +- [Run-Length Encoding (RLE)](Run-Length Encoding/). Store repeated values as a single byte and a count. +- [Huffman Coding](Huffman Coding/). Store more common elements using a smaller number of bits. ### Miscellaneous @@ -96,6 +96,9 @@ Bad sorting algorithms (don't use these!): ### Machine learning - k-Nearest Neighbors +- Linear Regression +- Logistic Regression +- Neural Networks - PageRank ## Data structures From b791185c165f2f6a12f0b44f744e316fe6d35b8f Mon Sep 17 00:00:00 2001 From: Matthijs Hollemans Date: Tue, 23 Feb 2016 22:24:36 +0100 Subject: [PATCH 0042/1679] Missing syntax highlighting --- Huffman Coding/README.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Huffman Coding/README.markdown b/Huffman Coding/README.markdown index 56623d60f..3f78aa203 100644 --- a/Huffman Coding/README.markdown +++ b/Huffman Coding/README.markdown @@ -268,7 +268,7 @@ This is what the process looks like: Now that we know how to build the compression tree from the frequency table, we can use it to compress the contents of an `NSData` object. Here is the code: -``` +```swift func compressData(data: NSData) -> NSData { countByteFrequency(data) buildTree() @@ -296,7 +296,7 @@ Then it loops through the entire input and for each byte calls `traverseTree()`. The interesting stuff happens in `traverseTree()`. This is a recursive method: -``` +```swift private func traverseTree(writer writer: BitWriter, nodeIndex h: Int, childIndex child: Int) { if tree[h].parent != -1 { traverseTree(writer: writer, nodeIndex: tree[h].parent, childIndex: h) From f5cc3cf5c055885ce2eb80fceffdf3f0f0cc833a Mon Sep 17 00:00:00 2001 From: Donald Pinckney Date: Tue, 23 Feb 2016 20:02:11 -0800 Subject: [PATCH 0043/1679] Write content for README --- .../Contents.swift | 11 +- .../Contents.swift | 19 +-- Graph/README.markdown | 142 +++++++++++++++++- 3 files changed, 152 insertions(+), 20 deletions(-) diff --git a/Graph/Graph.playground/Pages/Adjacency List.xcplaygroundpage/Contents.swift b/Graph/Graph.playground/Pages/Adjacency List.xcplaygroundpage/Contents.swift index 3f7ea7e9a..6c239f75d 100644 --- a/Graph/Graph.playground/Pages/Adjacency List.xcplaygroundpage/Contents.swift +++ b/Graph/Graph.playground/Pages/Adjacency List.xcplaygroundpage/Contents.swift @@ -4,8 +4,6 @@ A graph implementation, using an adjacency list. In an adjacency list implementation, each vertex stores an array of edges, indicating to which vertices it has an edge (note the directionality). The edge stores the source and destination vertices, as well as a weight. -Connecting vertices in this implementation is O(1). - */ var uniqueIDCounter: Int = 0 @@ -19,7 +17,7 @@ public struct GraphEdge { public struct GraphVertex { public var data: T - public private(set) var edges: [GraphEdge] = [] // This is an adjacency list, rather than matrix + private var edges: [GraphEdge] = [] // This is an adjacency list, rather than matrix private let uniqueID: Int @@ -35,11 +33,12 @@ public struct GraphVertex { } // Creates an undirected edge by making 2 directed edges: self ----> other, and other ----> self - public mutating func connectBetween(inout otherVertex: GraphVertex, withWeight weight: Double = 1.0) { - edges.append(GraphEdge(from: self, to: otherVertex, weight: weight)) - otherVertex.edges.append(GraphEdge(from: otherVertex, to: self, weight: weight)) + public mutating func connectBetween(inout otherVertex: GraphVertex, withWeight weight: Double = 1.0) { + connectTo(otherVertex, withWeight: weight) + otherVertex.connectTo(self, withWeight: weight) } + // Queries for an edge from self -----> otherVertex public func edgeTo(otherVertex: GraphVertex) -> GraphEdge? { for e in edges { if e.to.uniqueID == otherVertex.uniqueID { diff --git a/Graph/Graph.playground/Pages/Adjacency Matrix.xcplaygroundpage/Contents.swift b/Graph/Graph.playground/Pages/Adjacency Matrix.xcplaygroundpage/Contents.swift index 5cff241fb..c8c5fdf8c 100644 --- a/Graph/Graph.playground/Pages/Adjacency Matrix.xcplaygroundpage/Contents.swift +++ b/Graph/Graph.playground/Pages/Adjacency Matrix.xcplaygroundpage/Contents.swift @@ -5,14 +5,11 @@ A graph implementation, using an adjacency matrix. In an adjacency matrix implementation, each vertex is associated with an index from 0.. { public var data: T - private let uniqueID: Int + private let index: Int } public struct Graph { @@ -21,10 +18,9 @@ public struct Graph { // If adjacencyMatrix[i][j] is not nil, then there is an edge from vertex i to vertex j. private var adjacencyMatrix: [[Double?]] = [] - public init() { } - + // Possibly O(n^2) because of the resizing of the matrix public mutating func createVertex(data: T) -> GraphVertex { - let vertex = GraphVertex(data: data, uniqueID: adjacencyMatrix.count) + let vertex = GraphVertex(data: data, index: adjacencyMatrix.count) // Expand each existing row to the right one column for i in 0.. { // Creates a directed edge source -----> dest. Represented by M[source][dest] = weight public mutating func connect(sourceVertex: GraphVertex, toDestinationVertex: GraphVertex, withWeight weight: Double = 0) { - adjacencyMatrix[sourceVertex.uniqueID][toDestinationVertex.uniqueID] = weight + adjacencyMatrix[sourceVertex.index][toDestinationVertex.index] = weight } // Creates an undirected edge by making 2 directed edges: some ----> other, and other ----> some public mutating func connect(someVertex: GraphVertex, symmetricallyWithVertex withVertex: GraphVertex, withWeight weight: Double = 0) { - adjacencyMatrix[someVertex.uniqueID][withVertex.uniqueID] = weight - adjacencyMatrix[withVertex.uniqueID][someVertex.uniqueID] = weight - + adjacencyMatrix[someVertex.index][withVertex.index] = weight + adjacencyMatrix[withVertex.index][someVertex.index] = weight } public func weightFrom(sourceVertex: GraphVertex, toDestinationVertex: GraphVertex) -> Double? { - return adjacencyMatrix[sourceVertex.uniqueID][toDestinationVertex.uniqueID] + return adjacencyMatrix[sourceVertex.index][toDestinationVertex.index] } } diff --git a/Graph/README.markdown b/Graph/README.markdown index 30327f474..42b71b6b2 100644 --- a/Graph/README.markdown +++ b/Graph/README.markdown @@ -1,6 +1,144 @@ # Graph -YAY Graphs! -TODO: Write stuff here. +A graph is a set of *vertices* paired with a set of *edges*. Each vertex has a set of associated edges, which connect to other vertices. +For example, a graph can represent a social network. Each person is a vertex, and people that know each other are connected with edges. + +// TODO: Insert image here + +## Weighted and Directed Edges +Edges can optionally be *weighted*, where an arbitrary weight is assigned to each edge. Consider an example of a graph representing airplane flights. Cities can be represented as vertices, and flights as edges. Then an edge weight could represent flight time. + +In addition, edges can optionally be *directed*. A directed edge from vertex A to vertex B connects *A to B*, but **not** *B to A*. Continuing from the flight path example, a directed edge from San Francisco, CA to Juneau, AK would indicate that there is a flight from San Francisco to Juneau, but not from Juneau to San Francisco. + +// TODO: Insert image here + +## Representing Graphs in Code +There are two main strategies for representing graphs: + +1. Adjacency List +2. Adjacency Matrix + +### Adjacency List +In an adjacency list implementation, each vertex stores a list of edges that originate from the vertex. For example, if vertex A has an edge to vertices B, C, and D, then vertex A would have a list of 3 edges. + +### Adjacency Matrix +In an adjacency matrix implementation, a matrix with rows and columns representing vertices stores a weight to indicate if vertices are connected, and by what weight. For example, if there is a directed edge of weight 5.6 from vertex A to vertex B, then the entry with row for vertex A, column for vertex B would have value 5.6: +``` + matrix[index(A)][index(B)] == 5.6 +``` + +### Comparing Graph Representations +Let *V* be the number of vertices in the graph, and *E* the number of edges. Then we have: + +| Operation | Adjacency List | Adjacency Matrix | +|-----------------|----------------|------------------| +| Storage Space | O(V + E) | O(V^2) | +| Add Vertex | O(1) | O(V^2) | +| Add Edge | O(1) | O(1) | +| Check Adjacency | O(V) | O(1) | + +Note that the time to check adjacency for an adjacency list is **O(V)**, because at worst a vertex is connected to *every* other vertex. So, in the case of a *sparse* graph, in which each vertex is connected to a handfull of other vertices, an Adjacency List is preferred. If the graph is *dense*, that is, vertices are connected to most of the other vertices, then an Adjacency Matrix is preferred. + +## The Code +Below we have implementations of both Adjacency List and Adjacency Matrix graph representations. + +In both cases, we also let the vertex store arbitrary data with a generic parameter. +### Adjacency List +First, we have the data structures for edges and vertices: + +```swift +var uniqueIDCounter: Int = 0 + +public struct GraphEdge { + public let from: GraphVertex + public let to: GraphVertex + public let weight: Double +} + +public struct GraphVertex { + public var data: T + private var edges: [GraphEdge] = [] + + private let uniqueID: Int + + public init(data: T) { + self.data = data + uniqueID = uniqueIDCounter + uniqueIDCounter += 1 + } +} +``` +Note that each vertex has a unique identifier, which we use to compare equality later. + +Now, lets see how to connect vertices: + +```swift +// Creates a directed edge self -----> dest +public mutating func connectTo(destinationVertex: GraphVertex, withWeight weight: Double = 1.0) { + edges.append(GraphEdge(from: self, to: destinationVertex, weight: weight)) +} +``` +And then we can check for an edge between vertices: + +```swift +// Queries for an edge from self -----> otherVertex +public func edgeTo(otherVertex: GraphVertex) -> GraphEdge? { + for e in edges { + if e.to.uniqueID == otherVertex.uniqueID { + return e + } + } + return nil +} +``` + +### Adjacency Matrix +Fundamentally, we will store a `[[Double?]]` which is the adjacency matrix. An entry of `nil` indicates no edge, while any other value indicates an edge of the given weight. To index into the matrix using vertices, we give each `GraphVertex` a unique integer index: + +```swift +public struct GraphVertex { + public var data: T + private let index: Int +} +``` + +Then the `Graph` struct keeps track of the matrix. To create a new vertex, the graph must resize the matrix: + +```swift +public struct Graph { + + // nil entries are used to mark that two vertices are NOT connected. + // If adjacencyMatrix[i][j] is not nil, then there is an edge from vertex i to vertex j. + private var adjacencyMatrix: [[Double?]] = [] + + // O(n^2) because of the resizing of the matrix + public mutating func createVertex(data: T) -> GraphVertex { + let vertex = GraphVertex(data: data, index: adjacencyMatrix.count) + + // Expand each existing row to the right one column + for i in 0.. dest. Represented by M[source][dest] = weight +public mutating func connect(sourceVertex: GraphVertex, toDestinationVertex: GraphVertex, withWeight weight: Double = 0) { + adjacencyMatrix[sourceVertex.index][toDestinationVertex.index] = weight +} + +public func weightFrom(sourceVertex: GraphVertex, toDestinationVertex: GraphVertex) -> Double? { + return adjacencyMatrix[sourceVertex.index][toDestinationVertex.index] +} +``` *Written by Donald Pinckney* From d29704db2c2bc82628220641fef23f0c168c764b Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Wed, 24 Feb 2016 21:12:50 +1300 Subject: [PATCH 0044/1679] BFS Shortest path example in readme. Unwrapping in a single place. --- .../Contents.swift | 30 ++++----- Breadth-First Search/README.markdown | 67 ++++++++++++++----- 2 files changed, 66 insertions(+), 31 deletions(-) diff --git a/Breadth-First Search/BreadthFirstSearch.playground/Contents.swift b/Breadth-First Search/BreadthFirstSearch.playground/Contents.swift index 64134a85c..328bccaa9 100644 --- a/Breadth-First Search/BreadthFirstSearch.playground/Contents.swift +++ b/Breadth-First Search/BreadthFirstSearch.playground/Contents.swift @@ -76,12 +76,12 @@ struct Queue { } } -func breadthFirstSearch(graph: Graph, root: Node) { - print("Performing breadth-first search on '\(root.label)'") +func breadthFirstSearch(graph: Graph, source: Node) { + print("Performing breadth-first search on '\(source.label)'") - var seenNodes = [root] + var seenNodes = [source] var queue = Queue() - queue.enqueue(root) + queue.enqueue(source) while !queue.isEmpty { let current = queue.dequeue() @@ -96,18 +96,18 @@ func breadthFirstSearch(graph: Graph, root: Node) { } } -func breadthFirstSearchShortestPath(graph: Graph, root: Node) { - root.distance = 0 - var q = Queue() - q.enqueue(root) +func breadthFirstSearchShortestPath(graph: Graph, source: Node) { + var queue = Queue() + queue.enqueue(source) + source.distance = 0 - while !q.isEmpty { - let current = q.dequeue() - for edge in current!.neighbors { + while !queue.isEmpty { + let current = queue.dequeue()! + for edge in current.neighbors { let neighborNode = edge.neighbor if !neighborNode.hasDistance { - q.enqueue(neighborNode) - neighborNode.distance = current!.distance! + 1 + queue.enqueue(neighborNode) + neighborNode.distance = current.distance! + 1 } } } @@ -136,5 +136,5 @@ graph.addEdge(nodeC, neighbor: nodeG) graph.addEdge(nodeE, neighbor: nodeH) -breadthFirstSearch(graph, root: nodeA) -breadthFirstSearchShortestPath(graph, root: nodeA) +breadthFirstSearch(graph, source: nodeA) +breadthFirstSearchShortestPath(graph, source: nodeA) diff --git a/Breadth-First Search/README.markdown b/Breadth-First Search/README.markdown index dc7918ff5..bf2236dd5 100644 --- a/Breadth-First Search/README.markdown +++ b/Breadth-First Search/README.markdown @@ -8,7 +8,7 @@ Breadth-first search (BFS) is an algorithm for traversing or searching tree or g Let's follow the animated example by using a [queue](../Queue/). -Start with the root node ``a`` and add it to a queue. +Start with the source node ``a`` and add it to a queue. ```swift queue.enqueue(a) ``` @@ -58,12 +58,12 @@ The queue is now empty which means all nodes have been explored. Simple implementation of breadth-first search using a queue: ```swift -func breadthFirstSearch(graph: Graph, root: Node) { - print("Performing breadth-first search on '\(root.label)'") +func breadthFirstSearch(graph: Graph, source: Node) { + print("Performing breadth-first search on '\(source.label)'") - var seenNodes = [root] + var seenNodes = [source] var queue = Queue() - queue.enqueue(root) + queue.enqueue(source) while !queue.isEmpty { let current = queue.dequeue() @@ -100,7 +100,7 @@ graph.addEdge(nodeC, neighbor: nodeF) graph.addEdge(nodeC, neighbor: nodeG) graph.addEdge(nodeE, neighbor: nodeH) -breadthFirstSearch(graph, root: nodeA) // This will output: Performing breadth-first search on 'a', b, c, d, e, f, g, h +breadthFirstSearch(graph, source: nodeA) // This will output: Performing breadth-first search on 'a', b, c, d, e, f, g, h ``` @@ -114,21 +114,46 @@ Breadth-first search can be used to solve many problems, for example: ## Shortest path example -TODO: walkthrough + explanation +Bread breadth-first can be used to compute the shortest path between a source node and each of the other nodes because it explores all of the neighbor nodes before moving to the next level neighbors. Let's follow the animated example and calculate the shortest path to all the other nodes: +Start with the source node ``a`` and add it to a queue with a distance of ``0``. ```swift -func breadthFirstSearchShortestPath(graph: Graph, root: Node) { - root.distance = 0 - var q = Queue() - q.enqueue(root) +queue.enqueue(a) +a.distance = 0 +``` +The queue is now ``[ a ]``. Dequeue ``a`` and enqueue the neighbor nodes ``b`` and ``c`` with a distance of ``1``. +```swift +queue.dequeue(a) +queue.enqueue(b) +b.distance = a.distance + 1 // result: 1 +queue.enqueue(c) +c.distance = a.distance + 1 // result: 1 +``` +The queue is now ``[ b, c ]``. Dequeue ``b`` and enqueue the neighbor nodes ``d`` and ``e`` with a distance of ``2``. +```swift +queue.dequeue(b) +queue.enqueue(d) +d.distance = b.distance + 1 // result: 2 +queue.enqueue(e) +e.distance = b.distance + 1 // result: 2 +``` - while !q.isEmpty { - let current = q.dequeue() - for edge in current!.neighbors { +Continue until the queue is empty to calculate the shortest path to all other nodes. + +Here's the code: +```swift +func breadthFirstSearchShortestPath(graph: Graph, source: Node) { + var queue = Queue() + queue.enqueue(source) + source.distance = 0 + + while !queue.isEmpty { + let current = queue.dequeue()! + for edge in current.neighbors { let neighborNode = edge.neighbor if !neighborNode.hasDistance { - q.enqueue(neighborNode) - neighborNode.distance = current!.distance! + 1 + queue.enqueue(neighborNode) + neighborNode.distance = current.distance! + 1 } } } @@ -137,6 +162,16 @@ func breadthFirstSearchShortestPath(graph: Graph, root: Node) { } ``` +Put this code in a playground and test it like so: +```swift +breadthFirstSearchShortestPath(graph, source: nodeA) + +// This will output: +// Node(label: a, distance: 0), Node(label: b, distance: 1), Node(label: c, distance: 1), +// Node(label: d, distance: 2), Node(label: e, distance: 2), Node(label: f, distance: 2), +// Node(label: g, distance: 2), Node(label: h, distance: 3) +``` + ## Minimum spanning tree example TODO From 81ba37568fadf5c1a40de9bb27fd9b6fdb035027 Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Wed, 24 Feb 2016 23:09:50 +1300 Subject: [PATCH 0045/1679] BFS adding image for minimum spanning tree --- .../Images/MinimumSpanningTree.sketch | Bin 0 -> 81920 bytes .../Images/Minimum_Spanning_Tree.png | Bin 0 -> 24095 bytes Breadth-First Search/README.markdown | 15 ++++++++++----- 3 files changed, 10 insertions(+), 5 deletions(-) create mode 100644 Breadth-First Search/Images/MinimumSpanningTree.sketch create mode 100644 Breadth-First Search/Images/Minimum_Spanning_Tree.png diff --git a/Breadth-First Search/Images/MinimumSpanningTree.sketch b/Breadth-First Search/Images/MinimumSpanningTree.sketch new file mode 100644 index 0000000000000000000000000000000000000000..882fbc9d67149f0cb77baf6570f0b77e5c91304b GIT binary patch literal 81920 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 b^%vj0K=uOW$j=6h?|66A_0_6XY$E>)qWk5k literal 0 HcmV?d00001 diff --git a/Breadth-First Search/README.markdown b/Breadth-First Search/README.markdown index bf2236dd5..e4b1db44d 100644 --- a/Breadth-First Search/README.markdown +++ b/Breadth-First Search/README.markdown @@ -1,6 +1,6 @@ # Breadth-First Search -Breadth-first search (BFS) is an algorithm for traversing or searching tree or graph data structures. It starts at the tree root and explores the neighbor nodes first, before moving to the next level neighbors. +Breadth-first search (BFS) is an algorithm for traversing or searching [tree](../Tree/) or [graph](../Graph/) data structures. It starts at the tree source and explores the neighbor nodes first, before moving to the next level neighbors. ## Animated example @@ -101,7 +101,6 @@ graph.addEdge(nodeC, neighbor: nodeG) graph.addEdge(nodeE, neighbor: nodeH) breadthFirstSearch(graph, source: nodeA) // This will output: Performing breadth-first search on 'a', b, c, d, e, f, g, h - ``` ## Applications @@ -114,7 +113,7 @@ Breadth-first search can be used to solve many problems, for example: ## Shortest path example -Bread breadth-first can be used to compute the shortest path between a source node and each of the other nodes because it explores all of the neighbor nodes before moving to the next level neighbors. Let's follow the animated example and calculate the shortest path to all the other nodes: +Breadth-first search can be used to compute the [shortest path](../Shortest Path/) between a source node and each of the other nodes because it explores all of the neighbor nodes before moving to the next level neighbors. Let's follow the animated example and calculate the shortest path to all the other nodes: Start with the source node ``a`` and add it to a queue with a distance of ``0``. ```swift @@ -174,10 +173,16 @@ breadthFirstSearchShortestPath(graph, source: nodeA) ## Minimum spanning tree example -TODO +Breadth-first search can be used to calculate the [minimum spanning tree](../Minimum Spanning Tree/) on an unweighted graph. + +![Minimum spanning tree](Images/Minimum_Spanning_Tree.png) + +The minimum spanning tree is represented by the bold edges. + +TODO: explain steps to generate minimum spanning tree ## See also -[Graphs](../Graph/), [Queues](../Queue/), [Breadth-first search on Wikipedia](https://en.wikipedia.org/wiki/Breadth-first_search). +[Graph](../Graph/), [Tree](../Tree/), [Queues](../Queue/), [Shortest Path](../Shortest Path/), [Breadth-first search on Wikipedia](https://en.wikipedia.org/wiki/Breadth-first_search), [Minimum spanning tree on Wikipedia](https://en.wikipedia.org/wiki/Minimum_spanning_tree). *Written by [Chris Pilcher](https://github.com/chris-pilcher)* From ba8326641ad8a3abb548e5beb081fe35252fb139 Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Wed, 24 Feb 2016 23:14:45 +1300 Subject: [PATCH 0046/1679] BFS unwrapping in a single place --- .../BreadthFirstSearch.playground/Contents.swift | 4 ++-- Breadth-First Search/README.markdown | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Breadth-First Search/BreadthFirstSearch.playground/Contents.swift b/Breadth-First Search/BreadthFirstSearch.playground/Contents.swift index 328bccaa9..640a0e045 100644 --- a/Breadth-First Search/BreadthFirstSearch.playground/Contents.swift +++ b/Breadth-First Search/BreadthFirstSearch.playground/Contents.swift @@ -84,8 +84,8 @@ func breadthFirstSearch(graph: Graph, source: Node) { queue.enqueue(source) while !queue.isEmpty { - let current = queue.dequeue() - for edge in current!.neighbors { + let current = queue.dequeue()! + for edge in current.neighbors { let neighborNode = edge.neighbor if !seenNodes.contains(neighborNode) { queue.enqueue(neighborNode) diff --git a/Breadth-First Search/README.markdown b/Breadth-First Search/README.markdown index e4b1db44d..96be1d4b4 100644 --- a/Breadth-First Search/README.markdown +++ b/Breadth-First Search/README.markdown @@ -66,8 +66,8 @@ func breadthFirstSearch(graph: Graph, source: Node) { queue.enqueue(source) while !queue.isEmpty { - let current = queue.dequeue() - for edge in current!.neighbors { + let current = queue.dequeue()! + for edge in current.neighbors { let neighborNode = edge.neighbor if !seenNodes.contains(neighborNode) { queue.enqueue(neighborNode) From 7b420565d6e9595c78c980426ffadaec80fb61f0 Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Wed, 24 Feb 2016 23:21:05 +1300 Subject: [PATCH 0047/1679] BFS updating minimum spanning tree --- .../Images/MinimumSpanningTree.sketch | Bin 81920 -> 81920 bytes .../Images/Minimum_Spanning_Tree.png | Bin 24095 -> 23928 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/Breadth-First Search/Images/MinimumSpanningTree.sketch b/Breadth-First Search/Images/MinimumSpanningTree.sketch index 882fbc9d67149f0cb77baf6570f0b77e5c91304b..93a5b808cdca5702194429d6334f9f58eda147dd 100644 GIT binary patch literal 81920 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 T*AjtB9dc7$7xhlnD(rs%aZzvT literal 24095 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 b^%vj0K=uOW$j=6h?|66A_0_6XY$E>)qWk5k From b91edfddfb9ff565c0f6bd725a7388d66accc568 Mon Sep 17 00:00:00 2001 From: Kauserali Hafizji Date: Thu, 25 Feb 2016 19:16:18 +0530 Subject: [PATCH 0048/1679] Shunting yard algorithm --- .../Shunting Yard.playground/Contents.swift | 229 +++++++++++++++++ .../Sources/Stack.swift | 43 ++++ .../contents.xcplayground | 4 + .../timeline.xctimeline | 6 + Shunting Yard/ShuntingYardAlgorithm.swift | 233 ++++++++++++++++++ Shunting Yard/Stack.swift | 43 ++++ 6 files changed, 558 insertions(+) create mode 100644 Shunting Yard/Shunting Yard.playground/Contents.swift create mode 100644 Shunting Yard/Shunting Yard.playground/Sources/Stack.swift create mode 100644 Shunting Yard/Shunting Yard.playground/contents.xcplayground create mode 100644 Shunting Yard/Shunting Yard.playground/timeline.xctimeline create mode 100644 Shunting Yard/ShuntingYardAlgorithm.swift create mode 100644 Shunting Yard/Stack.swift diff --git a/Shunting Yard/Shunting Yard.playground/Contents.swift b/Shunting Yard/Shunting Yard.playground/Contents.swift new file mode 100644 index 000000000..e0bf80bcf --- /dev/null +++ b/Shunting Yard/Shunting Yard.playground/Contents.swift @@ -0,0 +1,229 @@ +//: Playground - noun: a place where people can play + +import Foundation + +internal enum OperatorAssociativity { + case LeftAssociative + case RightAssociative +} + +internal enum OperatorType: CustomStringConvertible { + case Add + case Subtract + case Divide + case Multiply + case Percent + case Exponent + + var description: String { + switch self { + case Add: + return "+" + case Subtract: + return "-" + case Divide: + return "/" + case Multiply: + return "*" + case Percent: + return "%" + case Exponent: + return "^" + } + } +} + +internal struct OperatorToken: CustomStringConvertible { + + var operatorType: OperatorType + + init(operatorType: OperatorType) { + self.operatorType = operatorType + } + + var precedance: Int { + switch operatorType { + case .Add, .Subtract: + return 0 + case .Divide, .Multiply, .Percent: + return 5; + case .Exponent: + return 10 + } + } + + var associativity: OperatorAssociativity { + switch operatorType { + case .Add, .Subtract, .Divide, .Multiply, .Percent: + return .LeftAssociative; + case .Exponent: + return .RightAssociative + } + } + + var description: String { + return operatorType.description + } +} + +func <=(left: OperatorToken, right: OperatorToken) -> Bool { + if left.precedance <= right.precedance { + return true + } + return false +} + +func <(left: OperatorToken, right: OperatorToken) -> Bool { + if left.precedance < right.precedance { + return true + } + return false +} + +internal enum TokenType: CustomStringConvertible { + case OpenBracket + case CloseBracket + case Operator(OperatorToken) + case Operand(Double) + + var description: String { + switch self { + case OpenBracket: + return "(" + case CloseBracket: + return ")" + case Operator(let operatorToken): + return operatorToken.description + case Operand(let value): + return "\(value)" + } + } +} + +internal struct Token: CustomStringConvertible { + + var tokenType: TokenType + + init(tokenType: TokenType) { + self.tokenType = tokenType + } + + init(operand: Double) { + tokenType = .Operand(operand) + } + + init(operatorType: OperatorType) { + tokenType = .Operator(OperatorToken(operatorType: operatorType)) + } + + var isOpenBracket: Bool { + switch tokenType { + case .OpenBracket: + return true + default: + return false + } + } + + var isOperator: Bool { + switch tokenType { + case .Operator(_): + return true + default: + return false + } + } + + var operatorToken: OperatorToken? { + switch tokenType { + case .Operator(let operatorToken): + return operatorToken + default: + return nil + } + } + + var description: String { + return tokenType.description + } +} + +public struct Expression { + var expression = Array() + + init() { + expression.append(Token(operand: 3)) + expression.append(Token(operatorType: OperatorType.Add)) + expression.append(Token(operand: 4)) + expression.append(Token(operatorType: OperatorType.Multiply)) + expression.append(Token(operand: 2)) + expression.append(Token(operatorType: OperatorType.Divide)) + expression.append(Token(tokenType: TokenType.OpenBracket)) + expression.append(Token(operand: 1)) + expression.append(Token(operatorType: OperatorType.Subtract)) + expression.append(Token(operand: 5)) + expression.append(Token(tokenType: TokenType.CloseBracket)) + expression.append(Token(operatorType: OperatorType.Exponent)) + expression.append(Token(operand: 2)) + expression.append(Token(operatorType: OperatorType.Exponent)) + expression.append(Token(operand: 3)) + } + + public func reversePolishNotation() -> String { + + var tokenStack = Stack() + var reversePolishNotation = [Token]() + + for token in expression { + switch token.tokenType { + case .Operand(_): + reversePolishNotation.append(token) + break + case .OpenBracket: + tokenStack.push(token) + break + case .CloseBracket: + while tokenStack.count > 0 { + if let tempToken = tokenStack.pop() where !tempToken.isOpenBracket { + reversePolishNotation.append(tempToken) + } else { + break + } + } + break + case .Operator(let operatorToken): + + for tempToken in tokenStack.generate() { + if !tempToken.isOperator { + break + } + + if let tempOperatorToken = tempToken.operatorToken { + + if operatorToken.associativity == .LeftAssociative && operatorToken <= tempOperatorToken + || operatorToken.associativity == .RightAssociative && operatorToken < tempOperatorToken { + + reversePolishNotation.append(tokenStack.pop()!) + } else { + break + } + } + } + + tokenStack.push(token) + break + + } + } + + while tokenStack.count > 0 { + reversePolishNotation.append(tokenStack.pop()!) + } + + return reversePolishNotation.map({token in + return token.description + }).joinWithSeparator(", ") + } +} + +print(Expression().reversePolishNotation()) diff --git a/Shunting Yard/Shunting Yard.playground/Sources/Stack.swift b/Shunting Yard/Shunting Yard.playground/Sources/Stack.swift new file mode 100644 index 000000000..93feb2ca1 --- /dev/null +++ b/Shunting Yard/Shunting Yard.playground/Sources/Stack.swift @@ -0,0 +1,43 @@ +import Foundation + +public struct Stack { + private var array = [T]() + + public init() { + array = [] + } + + public var isEmpty: Bool { + return array.isEmpty + } + + public var count: Int { + return array.count + } + + public mutating func push(element: T) { + array.append(element) + } + + public mutating func pop() -> T? { + if isEmpty { + return nil + } else { + return array.removeLast() + } + } + + public func peek() -> T? { + return array.last + } +} + +extension Stack: SequenceType { + public func generate() -> AnyGenerator { + var curr = self + return anyGenerator { + _ -> T? in + return curr.pop() + } + } +} \ No newline at end of file diff --git a/Shunting Yard/Shunting Yard.playground/contents.xcplayground b/Shunting Yard/Shunting Yard.playground/contents.xcplayground new file mode 100644 index 000000000..5da2641c9 --- /dev/null +++ b/Shunting Yard/Shunting Yard.playground/contents.xcplayground @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Shunting Yard/Shunting Yard.playground/timeline.xctimeline b/Shunting Yard/Shunting Yard.playground/timeline.xctimeline new file mode 100644 index 000000000..bf468afec --- /dev/null +++ b/Shunting Yard/Shunting Yard.playground/timeline.xctimeline @@ -0,0 +1,6 @@ + + + + + diff --git a/Shunting Yard/ShuntingYardAlgorithm.swift b/Shunting Yard/ShuntingYardAlgorithm.swift new file mode 100644 index 000000000..980fc88ef --- /dev/null +++ b/Shunting Yard/ShuntingYardAlgorithm.swift @@ -0,0 +1,233 @@ +// +// ShuntingYardAlgorithm.swift +// +// +// Created by Ali Hafizji on 2016-02-25. +// +// + +import Foundation + +internal enum OperatorAssociativity { + case LeftAssociative + case RightAssociative +} + +internal enum OperatorType: CustomStringConvertible { + case Add + case Subtract + case Divide + case Multiply + case Percent + case Exponent + + var description: String { + switch self { + case Add: + return "+" + case Subtract: + return "-" + case Divide: + return "/" + case Multiply: + return "*" + case Percent: + return "%" + case Exponent: + return "^" + } + } +} + +internal struct OperatorToken: CustomStringConvertible { + + var operatorType: OperatorType + + init(operatorType: OperatorType) { + self.operatorType = operatorType + } + + var precedance: Int { + switch operatorType { + case .Add, .Subtract: + return 0 + case .Divide, .Multiply, .Percent: + return 5; + case .Exponent: + return 10 + } + } + + var associativity: OperatorAssociativity { + switch operatorType { + case .Add, .Subtract, .Divide, .Multiply, .Percent: + return .LeftAssociative; + case .Exponent: + return .RightAssociative + } + } + + var description: String { + return operatorType.description + } +} + +func <=(left: OperatorToken, right: OperatorToken) -> Bool { + if left.precedance <= right.precedance { + return true + } + return false +} + +func <(left: OperatorToken, right: OperatorToken) -> Bool { + if left.precedance < right.precedance { + return true + } + return false +} + +internal enum TokenType: CustomStringConvertible { + case OpenBracket + case CloseBracket + case Operator(OperatorToken) + case Operand(Double) + + var description: String { + switch self { + case OpenBracket: + return "(" + case CloseBracket: + return ")" + case Operator(let operatorToken): + return operatorToken.description + case Operand(let value): + return "\(value)" + } + } +} + +internal struct Token: CustomStringConvertible { + + var tokenType: TokenType + + init(tokenType: TokenType) { + self.tokenType = tokenType + } + + init(operand: Double) { + tokenType = .Operand(operand) + } + + init(operatorType: OperatorType) { + tokenType = .Operator(OperatorToken(operatorType: operatorType)) + } + + var isOpenBracket: Bool { + switch tokenType { + case .OpenBracket: + return true + default: + return false + } + } + + var isOperator: Bool { + switch tokenType { + case .Operator(_): + return true + default: + return false + } + } + + var operatorToken: OperatorToken? { + switch tokenType { + case .Operator(let operatorToken): + return operatorToken + default: + return nil + } + } + + var description: String { + return tokenType.description + } +} + +public struct Expression { + var expression = Array() + + init() { + expression.append(Token(operand: 3)) + expression.append(Token(operatorType: OperatorType.Add)) + expression.append(Token(operand: 4)) + expression.append(Token(operatorType: OperatorType.Multiply)) + expression.append(Token(operand: 2)) + expression.append(Token(operatorType: OperatorType.Divide)) + expression.append(Token(tokenType: TokenType.OpenBracket)) + expression.append(Token(operand: 1)) + expression.append(Token(operatorType: OperatorType.Subtract)) + expression.append(Token(operand: 5)) + expression.append(Token(tokenType: TokenType.CloseBracket)) + expression.append(Token(operatorType: OperatorType.Exponent)) + expression.append(Token(operand: 2)) + expression.append(Token(operatorType: OperatorType.Exponent)) + expression.append(Token(operand: 3)) + } + + public func reversePolishNotation() -> String { + + var tokenStack = Stack() + var reversePolishNotation = [Token]() + + for token in expression { + switch token.tokenType { + case .Operand(_): + reversePolishNotation.append(token) + break + case .OpenBracket: + tokenStack.push(token) + break + case .CloseBracket: + while tokenStack.count > 0 { + if let tempToken = tokenStack.pop() where !tempToken.isOpenBracket { + reversePolishNotation.append(tempToken) + } else { + break + } + } + break + case .Operator(let operatorToken): + + for tempToken in tokenStack.generate() { + if !tempToken.isOperator { + break + } + + if let tempOperatorToken = tempToken.operatorToken { + + if operatorToken.associativity == .LeftAssociative && operatorToken <= tempOperatorToken + || operatorToken.associativity == .RightAssociative && operatorToken < tempOperatorToken { + + reversePolishNotation.append(tokenStack.pop()!) + } else { + break + } + } + } + + tokenStack.push(token) + break + + } + } + + while tokenStack.count > 0 { + reversePolishNotation.append(tokenStack.pop()!) + } + + return reversePolishNotation.map({token in + return token.description + }).joinWithSeparator(", ") + } +} \ No newline at end of file diff --git a/Shunting Yard/Stack.swift b/Shunting Yard/Stack.swift new file mode 100644 index 000000000..93feb2ca1 --- /dev/null +++ b/Shunting Yard/Stack.swift @@ -0,0 +1,43 @@ +import Foundation + +public struct Stack { + private var array = [T]() + + public init() { + array = [] + } + + public var isEmpty: Bool { + return array.isEmpty + } + + public var count: Int { + return array.count + } + + public mutating func push(element: T) { + array.append(element) + } + + public mutating func pop() -> T? { + if isEmpty { + return nil + } else { + return array.removeLast() + } + } + + public func peek() -> T? { + return array.last + } +} + +extension Stack: SequenceType { + public func generate() -> AnyGenerator { + var curr = self + return anyGenerator { + _ -> T? in + return curr.pop() + } + } +} \ No newline at end of file From 23d433573dfa6272cc05b8b631ec6417ff720a1a Mon Sep 17 00:00:00 2001 From: John Gill Date: Thu, 25 Feb 2016 13:46:48 -0800 Subject: [PATCH 0049/1679] Initial fileset --- K-Means/K-Means.playground/Contents.swift | 116 ++++++++++++++++++ .../K-Means.playground/contents.xcplayground | 4 + .../K-Means.playground/timeline.xctimeline | 6 + K-Means/README.md | 0 4 files changed, 126 insertions(+) create mode 100644 K-Means/K-Means.playground/Contents.swift create mode 100644 K-Means/K-Means.playground/contents.xcplayground create mode 100644 K-Means/K-Means.playground/timeline.xctimeline create mode 100644 K-Means/README.md diff --git a/K-Means/K-Means.playground/Contents.swift b/K-Means/K-Means.playground/Contents.swift new file mode 100644 index 000000000..a3071733e --- /dev/null +++ b/K-Means/K-Means.playground/Contents.swift @@ -0,0 +1,116 @@ +// +// K-Means.swift +// +// Created by John Gill on 2/25/16. + +import Foundation + +// Need a container to easily hold 2 Dimensional Vector2Ds +class Vector2D: CustomStringConvertible { + var x:Float = 0.0 // x-Coordinate of Vector2D + var y:Float = 0.0 // y-Coordinate of Vector2D + + init(x: Float, y: Float) { + self.x = x + self.y = y + } + + var description: String { + return "Vector2D (\(self.x), \(self.y))" + } +} + +// Ability to use std operators on Vector2D object +func +(left: Vector2D, right: Vector2D) -> Vector2D { + return Vector2D(x: left.x + right.x, y: left.y + right.y) +} +func +=(inout left: Vector2D, right: Vector2D) { + left = left + right +} +func /(left:Vector2D, right: Float) -> Vector2D { + return Vector2D(x: left.x / right, y: left.y / right) +} +func /=(inout left: Vector2D, right: Float) { + left = left / right +} + +// TODO: Explain/Replace/Cleanup +extension Array { + var shuffle: [Element] { + var elements = self + for index in indices { + let anotherIndex = Int(arc4random_uniform(UInt32(elements.count - index))) + index + anotherIndex != index ? swap(&elements[index], &elements[anotherIndex]) : () + } + return elements + } + func choose(n: Int) -> [Element] { + return Array(shuffle.prefix(n)) + } +} + +// Calculates the Euclidean distance between two Vector2Ds +func euclidean(v1:Vector2D, v2:Vector2D) -> Float { + return sqrt(pow((v1.x - v2.x), 2.0) + pow((v1.y - v2.y), 2.0)) +} + +// Get the INDEX of nearest Center to X +func nearestCenter(x: Vector2D, Centers: [Vector2D]) -> Int { + var nearestDist = FLT_MAX + var minIndex:Int = 0; + // Calculate the distance from Vector2D X to all the centers + for (idx, c) in Centers.enumerate() { + let dist = euclidean(x, v2: c) + if dist < nearestDist { + minIndex = idx + nearestDist = dist + } + } + return minIndex +} + +func kNN(numCenters: Int, convergeDist: Float, points: [Vector2D]) -> [Vector2D] { + var centerMoveDist:Float = 0.0 + + // 1. Choose k Random Vector2Ds as the initial centers + var kCenters:[Vector2D] = points.choose(numCenters) + + // do following steps until convergence + repeat { + var cnts = [Float](count: numCenters, repeatedValue: 0.0) + var nCenters = [Vector2D](count:numCenters, repeatedValue: Vector2D(x:0, y:0)) + // 2. Assign Vector2Ds to centers + // a. Determine which center each Vector2D is closest to + // b. Record how many Vector2Ds are assigned to each center + for p in points { + let c = nearestCenter(p, Centers: kCenters) + cnts[c]++ + nCenters[c] += p + } + // 3. Calculate a new centers + for idx in 0.. convergeDist) + return kCenters +} +var points = [Vector2D]() +let lim = 50 +for _ in 0.. + + + \ No newline at end of file diff --git a/K-Means/K-Means.playground/timeline.xctimeline b/K-Means/K-Means.playground/timeline.xctimeline new file mode 100644 index 000000000..bf468afec --- /dev/null +++ b/K-Means/K-Means.playground/timeline.xctimeline @@ -0,0 +1,6 @@ + + + + + diff --git a/K-Means/README.md b/K-Means/README.md new file mode 100644 index 000000000..e69de29bb From 973db8d50f2f1840a17d1a7fd52d879563a90dc9 Mon Sep 17 00:00:00 2001 From: John Gill Date: Thu, 25 Feb 2016 15:16:57 -0800 Subject: [PATCH 0050/1679] Change 2D vector to ND vector --- K-Means/K-Means.playground/Contents.swift | 82 +++++++++++-------- .../K-Means.playground/contents.xcplayground | 2 +- 2 files changed, 49 insertions(+), 35 deletions(-) diff --git a/K-Means/K-Means.playground/Contents.swift b/K-Means/K-Means.playground/Contents.swift index a3071733e..d1d6a05fd 100644 --- a/K-Means/K-Means.playground/Contents.swift +++ b/K-Means/K-Means.playground/Contents.swift @@ -5,32 +5,40 @@ import Foundation -// Need a container to easily hold 2 Dimensional Vector2Ds -class Vector2D: CustomStringConvertible { - var x:Float = 0.0 // x-Coordinate of Vector2D - var y:Float = 0.0 // y-Coordinate of Vector2D +// Need a container to easily hold N Dimensional Vectors +class VectorND: CustomStringConvertible { + private var length:Int = 0 + private var data:[Float] = [Float]() - init(x: Float, y: Float) { - self.x = x - self.y = y + init(d:[Float]) { + self.data = d + self.length = d.count } - var description: String { - return "Vector2D (\(self.x), \(self.y))" - } + var description: String { return "VectorND (\(self.data)" } + func getData() -> [Float] { return data } + func getLength() -> Int { return length } } -// Ability to use std operators on Vector2D object -func +(left: Vector2D, right: Vector2D) -> Vector2D { - return Vector2D(x: left.x + right.x, y: left.y + right.y) +// Ability to use std operators on VectorND object +func +(left: VectorND, right: VectorND) -> VectorND { + var results = [Float](count: left.getLength(), repeatedValue: 0.0) + for idx in 0.. Vector2D { - return Vector2D(x: left.x / right, y: left.y / right) +func /(left:VectorND, right: Float) -> VectorND { + var results = [Float](count: left.getLength(), repeatedValue: 0.0) + for (idx, value) in left.getData().enumerate() { + results[idx] = value / right + } + return VectorND(d: results) } -func /=(inout left: Vector2D, right: Float) { +func /=(inout left: VectorND, right: Float) { left = left / right } @@ -49,16 +57,20 @@ extension Array { } } -// Calculates the Euclidean distance between two Vector2Ds -func euclidean(v1:Vector2D, v2:Vector2D) -> Float { - return sqrt(pow((v1.x - v2.x), 2.0) + pow((v1.y - v2.y), 2.0)) +// Calculates the Euclidean distance between two VectorNDs +func euclidean(v1:VectorND, v2:VectorND) -> Float { + var result:Float = 0.0 + for idx in 0.. Int { +func nearestCenter(x: VectorND, Centers: [VectorND]) -> Int { var nearestDist = FLT_MAX var minIndex:Int = 0; - // Calculate the distance from Vector2D X to all the centers + // Calculate the distance from VectorND X to all the centers for (idx, c) in Centers.enumerate() { let dist = euclidean(x, v2: c) if dist < nearestDist { @@ -69,19 +81,20 @@ func nearestCenter(x: Vector2D, Centers: [Vector2D]) -> Int { return minIndex } -func kNN(numCenters: Int, convergeDist: Float, points: [Vector2D]) -> [Vector2D] { +func kNN(numCenters: Int, convergeDist: Float, points: [VectorND]) -> [VectorND] { var centerMoveDist:Float = 0.0 + let zeros = [Float](count: points[0].getLength(), repeatedValue: 0.0) - // 1. Choose k Random Vector2Ds as the initial centers - var kCenters:[Vector2D] = points.choose(numCenters) + // 1. Choose k Random VectorNDs as the initial centers + var kCenters:[VectorND] = points.choose(numCenters) // do following steps until convergence repeat { var cnts = [Float](count: numCenters, repeatedValue: 0.0) - var nCenters = [Vector2D](count:numCenters, repeatedValue: Vector2D(x:0, y:0)) - // 2. Assign Vector2Ds to centers - // a. Determine which center each Vector2D is closest to - // b. Record how many Vector2Ds are assigned to each center + var nCenters = [VectorND](count:numCenters, repeatedValue: VectorND(d:zeros)) + // 2. Assign VectorNDs to centers + // a. Determine which center each VectorND is closest to + // b. Record how many VectorNDs are assigned to each center for p in points { let c = nearestCenter(p, Centers: kCenters) cnts[c]++ @@ -102,15 +115,16 @@ func kNN(numCenters: Int, convergeDist: Float, points: [Vector2D]) -> [Vector2D] } while(centerMoveDist > convergeDist) return kCenters } -var points = [Vector2D]() -let lim = 50 + +var points = [VectorND]() +let lim = 10 for _ in 0.. - + \ No newline at end of file From 07f47e2f2acb62cdeeaeee8816a0d2e4b365b103 Mon Sep 17 00:00:00 2001 From: John Gill Date: Thu, 25 Feb 2016 20:45:12 -0800 Subject: [PATCH 0051/1679] Update to follow Swift Style Guide --- K-Means/K-Means.playground/Contents.swift | 100 ++++++++++-------- .../K-Means.playground/timeline.xctimeline | 35 ++++++ 2 files changed, 90 insertions(+), 45 deletions(-) diff --git a/K-Means/K-Means.playground/Contents.swift b/K-Means/K-Means.playground/Contents.swift index d1d6a05fd..9f35e5863 100644 --- a/K-Means/K-Means.playground/Contents.swift +++ b/K-Means/K-Means.playground/Contents.swift @@ -7,22 +7,22 @@ import Foundation // Need a container to easily hold N Dimensional Vectors class VectorND: CustomStringConvertible { - private var length:Int = 0 - private var data:[Float] = [Float]() + private var length = 0 + private var data = [Double]() - init(d:[Float]) { - self.data = d - self.length = d.count + init(d:[Double]) { + data = d + length = d.count } - var description: String { return "VectorND (\(self.data)" } - func getData() -> [Float] { return data } + var description: String { return "VectorND (\(data)" } + func getData() -> [Double] { return data } func getLength() -> Int { return length } } -// Ability to use std operators on VectorND object +// MARK: VectorND Operators func +(left: VectorND, right: VectorND) -> VectorND { - var results = [Float](count: left.getLength(), repeatedValue: 0.0) + var results = [Double](count: left.getLength(), repeatedValue: 0.0) for idx in 0.. VectorND { func +=(inout left: VectorND, right: VectorND) { left = left + right } -func /(left:VectorND, right: Float) -> VectorND { - var results = [Float](count: left.getLength(), repeatedValue: 0.0) +func /(left:VectorND, right: Double) -> VectorND { + var results = [Double](count: left.getLength(), repeatedValue: 0.0) for (idx, value) in left.getData().enumerate() { results[idx] = value / right } return VectorND(d: results) } -func /=(inout left: VectorND, right: Float) { +func /=(inout left: VectorND, right: Double) { left = left / right } -// TODO: Explain/Replace/Cleanup -extension Array { - var shuffle: [Element] { - var elements = self - for index in indices { - let anotherIndex = Int(arc4random_uniform(UInt32(elements.count - index))) + index - anotherIndex != index ? swap(&elements[index], &elements[anotherIndex]) : () - } - return elements +// MARK: Assist Functions +// Pick a k random elements from samples +func reservoirSample(samples:[VectorND], k:Int) -> [VectorND] { + var result = [VectorND]() + + // Fill the result array with first k elements + for i in 0.. [Element] { - return Array(shuffle.prefix(n)) + // randomly replace elements from remaining ones + for i in (k+1).. Float { - var result:Float = 0.0 +func euclidean(v1:VectorND, v2:VectorND) -> Double { + var result = 0.0 for idx in 0.. Float { // Get the INDEX of nearest Center to X func nearestCenter(x: VectorND, Centers: [VectorND]) -> Int { - var nearestDist = FLT_MAX - var minIndex:Int = 0; - // Calculate the distance from VectorND X to all the centers + var nearestDist = DBL_MAX + var minIndex = 0; + for (idx, c) in Centers.enumerate() { let dist = euclidean(x, v2: c) if dist < nearestDist { @@ -81,50 +85,56 @@ func nearestCenter(x: VectorND, Centers: [VectorND]) -> Int { return minIndex } -func kNN(numCenters: Int, convergeDist: Float, points: [VectorND]) -> [VectorND] { - var centerMoveDist:Float = 0.0 - let zeros = [Float](count: points[0].getLength(), repeatedValue: 0.0) +// MARK: Main Function +func kMeans(numCenters: Int, convergeDist: Double, points: [VectorND]) -> [VectorND] { + var centerMoveDist = 0.0 + let zeros = [Double](count: points[0].getLength(), repeatedValue: 0.0) // 1. Choose k Random VectorNDs as the initial centers - var kCenters:[VectorND] = points.choose(numCenters) + var kCenters = reservoirSample(points, k: numCenters) // do following steps until convergence repeat { - var cnts = [Float](count: numCenters, repeatedValue: 0.0) - var nCenters = [VectorND](count:numCenters, repeatedValue: VectorND(d:zeros)) + var cnts = [Double](count: numCenters, repeatedValue: 0.0) + var newCenters = [VectorND](count:numCenters, repeatedValue: VectorND(d:zeros)) // 2. Assign VectorNDs to centers // a. Determine which center each VectorND is closest to // b. Record how many VectorNDs are assigned to each center for p in points { let c = nearestCenter(p, Centers: kCenters) cnts[c]++ - nCenters[c] += p + newCenters[c] += p } // 3. Calculate a new centers for idx in 0.. convergeDist) return kCenters } +// MARK: Sample Data var points = [VectorND]() -let lim = 10 -for _ in 0.. + + + + + + + + + + + + + + From 49687da9e865fed62d190409e1ed1c44fb42af58 Mon Sep 17 00:00:00 2001 From: John Gill Date: Thu, 25 Feb 2016 22:22:37 -0800 Subject: [PATCH 0052/1679] add k-Means algorithm --- README.markdown | 1 + 1 file changed, 1 insertion(+) diff --git a/README.markdown b/README.markdown index b924f88f1..1af54642d 100644 --- a/README.markdown +++ b/README.markdown @@ -95,6 +95,7 @@ Bad sorting algorithms (don't use these!): ### Machine learning +- [k-Means](K-Means/). Unsupervised classifier that partitions data into k clusters. - k-Nearest Neighbors - Linear Regression - Logistic Regression From 5dd6948bf82d1bc2442d90e38a4ea277b45cc3f5 Mon Sep 17 00:00:00 2001 From: John Gill Date: Thu, 25 Feb 2016 22:29:14 -0800 Subject: [PATCH 0053/1679] Move Contents into own source file --- K-Means/KMeans.swift | 139 +++++++++++++++++++++++++++++++++++++++++++ K-Means/README.md | 3 + 2 files changed, 142 insertions(+) create mode 100644 K-Means/KMeans.swift diff --git a/K-Means/KMeans.swift b/K-Means/KMeans.swift new file mode 100644 index 000000000..05e973ba0 --- /dev/null +++ b/K-Means/KMeans.swift @@ -0,0 +1,139 @@ +// +// KMeans.swift +// +// Created by John Gill on 2/25/16. + +import Foundation + +// Need a container to easily hold N Dimensional Vectors +class VectorND: CustomStringConvertible { + private var length = 0 + private var data = [Double]() + + init(d:[Double]) { + data = d + length = d.count + } + + var description: String { return "VectorND (\(data)" } + func getData() -> [Double] { return data } + func getLength() -> Int { return length } +} + +// MARK: VectorND Operators +func +(left: VectorND, right: VectorND) -> VectorND { + var results = [Double](count: left.getLength(), repeatedValue: 0.0) + for idx in 0.. VectorND { + var results = [Double](count: left.getLength(), repeatedValue: 0.0) + for (idx, value) in left.getData().enumerate() { + results[idx] = value / right + } + return VectorND(d: results) +} +func /=(inout left: VectorND, right: Double) { + left = left / right +} + +// MARK: Assist Functions +// Pick a k random elements from samples +func reservoirSample(samples:[VectorND], k:Int) -> [VectorND] { + var result = [VectorND]() + + // Fill the result array with first k elements + for i in 0.. Double { + var result = 0.0 + for idx in 0.. Int { + var nearestDist = DBL_MAX + var minIndex = 0; + + for (idx, c) in Centers.enumerate() { + let dist = euclidean(x, v2: c) + if dist < nearestDist { + minIndex = idx + nearestDist = dist + } + } + return minIndex +} + +// MARK: Main Function +func kMeans(numCenters: Int, convergeDist: Double, points: [VectorND]) -> [VectorND] { + var centerMoveDist = 0.0 + let zeros = [Double](count: points[0].getLength(), repeatedValue: 0.0) + + // 1. Choose k Random VectorNDs as the initial centers + var kCenters = reservoirSample(points, k: numCenters) + + // do following steps until convergence + repeat { + var cnts = [Double](count: numCenters, repeatedValue: 0.0) + var newCenters = [VectorND](count:numCenters, repeatedValue: VectorND(d:zeros)) + // 2. Assign VectorNDs to centers + // a. Determine which center each VectorND is closest to + // b. Record how many VectorNDs are assigned to each center + for p in points { + let c = nearestCenter(p, Centers: kCenters) + cnts[c]++ + newCenters[c] += p + } + // 3. Calculate a new centers + for idx in 0.. convergeDist) + return kCenters +} + +// MARK: Sample Data +var points = [VectorND]() +let numPoints = 10 +let numDimmensions = 5 +for _ in 0.. Date: Fri, 26 Feb 2016 19:03:18 +0530 Subject: [PATCH 0054/1679] Updated code style --- .../Shunting Yard.playground/Contents.swift | 412 +++++++++--------- Shunting Yard/ShuntingYardAlgorithm.swift | 412 +++++++++--------- 2 files changed, 420 insertions(+), 404 deletions(-) diff --git a/Shunting Yard/Shunting Yard.playground/Contents.swift b/Shunting Yard/Shunting Yard.playground/Contents.swift index e0bf80bcf..f70f36c5a 100644 --- a/Shunting Yard/Shunting Yard.playground/Contents.swift +++ b/Shunting Yard/Shunting Yard.playground/Contents.swift @@ -3,227 +3,235 @@ import Foundation internal enum OperatorAssociativity { - case LeftAssociative - case RightAssociative + case LeftAssociative + case RightAssociative } -internal enum OperatorType: CustomStringConvertible { - case Add - case Subtract - case Divide - case Multiply - case Percent - case Exponent - - var description: String { - switch self { - case Add: - return "+" - case Subtract: - return "-" - case Divide: - return "/" - case Multiply: - return "*" - case Percent: - return "%" - case Exponent: - return "^" - } - } +public enum OperatorType: CustomStringConvertible { + case Add + case Subtract + case Divide + case Multiply + case Percent + case Exponent + + public var description: String { + switch self { + case Add: + return "+" + case Subtract: + return "-" + case Divide: + return "/" + case Multiply: + return "*" + case Percent: + return "%" + case Exponent: + return "^" + } + } } -internal struct OperatorToken: CustomStringConvertible { - - var operatorType: OperatorType - - init(operatorType: OperatorType) { - self.operatorType = operatorType - } - - var precedance: Int { - switch operatorType { - case .Add, .Subtract: - return 0 - case .Divide, .Multiply, .Percent: - return 5; - case .Exponent: - return 10 - } - } - - var associativity: OperatorAssociativity { - switch operatorType { - case .Add, .Subtract, .Divide, .Multiply, .Percent: - return .LeftAssociative; - case .Exponent: - return .RightAssociative - } - } - - var description: String { - return operatorType.description - } +public enum TokenType: CustomStringConvertible { + case OpenBracket + case CloseBracket + case Operator(OperatorToken) + case Operand(Double) + + public var description: String { + switch self { + case OpenBracket: + return "(" + case CloseBracket: + return ")" + case Operator(let operatorToken): + return operatorToken.description + case Operand(let value): + return "\(value)" + } + } +} + +public struct OperatorToken: CustomStringConvertible { + + var operatorType: OperatorType + + init(operatorType: OperatorType) { + self.operatorType = operatorType + } + + var precedance: Int { + switch operatorType { + case .Add, .Subtract: + return 0 + case .Divide, .Multiply, .Percent: + return 5; + case .Exponent: + return 10 + } + } + + var associativity: OperatorAssociativity { + switch operatorType { + case .Add, .Subtract, .Divide, .Multiply, .Percent: + return .LeftAssociative; + case .Exponent: + return .RightAssociative + } + } + + public var description: String { + return operatorType.description + } } func <=(left: OperatorToken, right: OperatorToken) -> Bool { - if left.precedance <= right.precedance { - return true - } - return false + if left.precedance <= right.precedance { + return true + } + return false } func <(left: OperatorToken, right: OperatorToken) -> Bool { - if left.precedance < right.precedance { - return true - } - return false + if left.precedance < right.precedance { + return true + } + return false } -internal enum TokenType: CustomStringConvertible { - case OpenBracket - case CloseBracket - case Operator(OperatorToken) - case Operand(Double) - - var description: String { - switch self { - case OpenBracket: - return "(" - case CloseBracket: - return ")" - case Operator(let operatorToken): - return operatorToken.description - case Operand(let value): - return "\(value)" - } - } +public struct Token: CustomStringConvertible { + + var tokenType: TokenType + + init(tokenType: TokenType) { + self.tokenType = tokenType + } + + init(operand: Double) { + tokenType = .Operand(operand) + } + + init(operatorType: OperatorType) { + tokenType = .Operator(OperatorToken(operatorType: operatorType)) + } + + var isOpenBracket: Bool { + switch tokenType { + case .OpenBracket: + return true + default: + return false + } + } + + var isOperator: Bool { + switch tokenType { + case .Operator(_): + return true + default: + return false + } + } + + var operatorToken: OperatorToken? { + switch tokenType { + case .Operator(let operatorToken): + return operatorToken + default: + return nil + } + } + + public var description: String { + return tokenType.description + } } -internal struct Token: CustomStringConvertible { - - var tokenType: TokenType - - init(tokenType: TokenType) { - self.tokenType = tokenType - } - - init(operand: Double) { - tokenType = .Operand(operand) - } - - init(operatorType: OperatorType) { - tokenType = .Operator(OperatorToken(operatorType: operatorType)) - } - - var isOpenBracket: Bool { - switch tokenType { - case .OpenBracket: - return true - default: - return false - } - } - - var isOperator: Bool { - switch tokenType { - case .Operator(_): - return true - default: - return false - } - } - - var operatorToken: OperatorToken? { - switch tokenType { - case .Operator(let operatorToken): - return operatorToken - default: - return nil - } - } - - var description: String { - return tokenType.description - } +public class InfixExpressionBuilder { + + private var expression = Array() + + public func addOperator(operatorType: OperatorType) -> InfixExpressionBuilder { + expression.append(Token(operatorType: operatorType)) + return self + } + + public func addOperand(operand: Double) -> InfixExpressionBuilder { + expression.append(Token(operand: operand)) + return self + } + + public func addOpenBracket() -> InfixExpressionBuilder { + expression.append(Token(tokenType: .OpenBracket)) + return self + } + + public func addCloseBracket() -> InfixExpressionBuilder { + expression.append(Token(tokenType: .CloseBracket)) + return self + } + + public func build() -> Array { + // Maybe do some validation here + return expression + } } -public struct Expression { - var expression = Array() - - init() { - expression.append(Token(operand: 3)) - expression.append(Token(operatorType: OperatorType.Add)) - expression.append(Token(operand: 4)) - expression.append(Token(operatorType: OperatorType.Multiply)) - expression.append(Token(operand: 2)) - expression.append(Token(operatorType: OperatorType.Divide)) - expression.append(Token(tokenType: TokenType.OpenBracket)) - expression.append(Token(operand: 1)) - expression.append(Token(operatorType: OperatorType.Subtract)) - expression.append(Token(operand: 5)) - expression.append(Token(tokenType: TokenType.CloseBracket)) - expression.append(Token(operatorType: OperatorType.Exponent)) - expression.append(Token(operand: 2)) - expression.append(Token(operatorType: OperatorType.Exponent)) - expression.append(Token(operand: 3)) - } - - public func reversePolishNotation() -> String { - - var tokenStack = Stack() - var reversePolishNotation = [Token]() - - for token in expression { - switch token.tokenType { - case .Operand(_): - reversePolishNotation.append(token) - break - case .OpenBracket: - tokenStack.push(token) - break - case .CloseBracket: - while tokenStack.count > 0 { - if let tempToken = tokenStack.pop() where !tempToken.isOpenBracket { - reversePolishNotation.append(tempToken) - } else { - break - } - } - break - case .Operator(let operatorToken): - - for tempToken in tokenStack.generate() { - if !tempToken.isOperator { - break - } +// This returns the result of the shunting yard algorithm +public func reversePolishNotation(expression: Array) -> String { + + var tokenStack = Stack() + var reversePolishNotation = [Token]() + + for token in expression { + switch token.tokenType { + case .Operand(_): + reversePolishNotation.append(token) + break + case .OpenBracket: + tokenStack.push(token) + break + case .CloseBracket: + while tokenStack.count > 0 { + if let tempToken = tokenStack.pop() where !tempToken.isOpenBracket { + reversePolishNotation.append(tempToken) + } else { + break + } + } + break + case .Operator(let operatorToken): + + for tempToken in tokenStack.generate() { + if !tempToken.isOperator { + break + } + + if let tempOperatorToken = tempToken.operatorToken { + + if operatorToken.associativity == .LeftAssociative && operatorToken <= tempOperatorToken + || operatorToken.associativity == .RightAssociative && operatorToken < tempOperatorToken { - if let tempOperatorToken = tempToken.operatorToken { - - if operatorToken.associativity == .LeftAssociative && operatorToken <= tempOperatorToken - || operatorToken.associativity == .RightAssociative && operatorToken < tempOperatorToken { - - reversePolishNotation.append(tokenStack.pop()!) - } else { - break - } - } - } - - tokenStack.push(token) - break - + reversePolishNotation.append(tokenStack.pop()!) + } else { + break } + } } - while tokenStack.count > 0 { - reversePolishNotation.append(tokenStack.pop()!) - } - - return reversePolishNotation.map({token in - return token.description - }).joinWithSeparator(", ") - } + tokenStack.push(token) + break + } + } + + while tokenStack.count > 0 { + reversePolishNotation.append(tokenStack.pop()!) + } + + return reversePolishNotation.map({token in + return token.description + }).joinWithSeparator(" ") } -print(Expression().reversePolishNotation()) +print(reversePolishNotation(InfixExpressionBuilder().addOperand(3).addOperator(.Add).addOperand(4).addOperator(.Multiply).addOperand(2).addOperator(.Divide).addOpenBracket().addOperand(1).addOperator(.Subtract).addOperand(5).addCloseBracket().addOperator(.Exponent).addOperand(2).addOperator(.Exponent).addOperand(3).build())) diff --git a/Shunting Yard/ShuntingYardAlgorithm.swift b/Shunting Yard/ShuntingYardAlgorithm.swift index 980fc88ef..dbaba475c 100644 --- a/Shunting Yard/ShuntingYardAlgorithm.swift +++ b/Shunting Yard/ShuntingYardAlgorithm.swift @@ -9,225 +9,233 @@ import Foundation internal enum OperatorAssociativity { - case LeftAssociative - case RightAssociative + case LeftAssociative + case RightAssociative } -internal enum OperatorType: CustomStringConvertible { - case Add - case Subtract - case Divide - case Multiply - case Percent - case Exponent - - var description: String { - switch self { - case Add: - return "+" - case Subtract: - return "-" - case Divide: - return "/" - case Multiply: - return "*" - case Percent: - return "%" - case Exponent: - return "^" - } - } +public enum OperatorType: CustomStringConvertible { + case Add + case Subtract + case Divide + case Multiply + case Percent + case Exponent + + public var description: String { + switch self { + case Add: + return "+" + case Subtract: + return "-" + case Divide: + return "/" + case Multiply: + return "*" + case Percent: + return "%" + case Exponent: + return "^" + } + } } -internal struct OperatorToken: CustomStringConvertible { - - var operatorType: OperatorType - - init(operatorType: OperatorType) { - self.operatorType = operatorType - } - - var precedance: Int { - switch operatorType { - case .Add, .Subtract: - return 0 - case .Divide, .Multiply, .Percent: - return 5; - case .Exponent: - return 10 - } - } - - var associativity: OperatorAssociativity { - switch operatorType { - case .Add, .Subtract, .Divide, .Multiply, .Percent: - return .LeftAssociative; - case .Exponent: - return .RightAssociative - } - } - - var description: String { - return operatorType.description - } +public enum TokenType: CustomStringConvertible { + case OpenBracket + case CloseBracket + case Operator(OperatorToken) + case Operand(Double) + + public var description: String { + switch self { + case OpenBracket: + return "(" + case CloseBracket: + return ")" + case Operator(let operatorToken): + return operatorToken.description + case Operand(let value): + return "\(value)" + } + } +} + +public struct OperatorToken: CustomStringConvertible { + + var operatorType: OperatorType + + init(operatorType: OperatorType) { + self.operatorType = operatorType + } + + var precedance: Int { + switch operatorType { + case .Add, .Subtract: + return 0 + case .Divide, .Multiply, .Percent: + return 5; + case .Exponent: + return 10 + } + } + + var associativity: OperatorAssociativity { + switch operatorType { + case .Add, .Subtract, .Divide, .Multiply, .Percent: + return .LeftAssociative; + case .Exponent: + return .RightAssociative + } + } + + public var description: String { + return operatorType.description + } } func <=(left: OperatorToken, right: OperatorToken) -> Bool { - if left.precedance <= right.precedance { - return true - } - return false + if left.precedance <= right.precedance { + return true + } + return false } func <(left: OperatorToken, right: OperatorToken) -> Bool { - if left.precedance < right.precedance { - return true - } - return false + if left.precedance < right.precedance { + return true + } + return false } -internal enum TokenType: CustomStringConvertible { - case OpenBracket - case CloseBracket - case Operator(OperatorToken) - case Operand(Double) - - var description: String { - switch self { - case OpenBracket: - return "(" - case CloseBracket: - return ")" - case Operator(let operatorToken): - return operatorToken.description - case Operand(let value): - return "\(value)" - } - } +public struct Token: CustomStringConvertible { + + var tokenType: TokenType + + init(tokenType: TokenType) { + self.tokenType = tokenType + } + + init(operand: Double) { + tokenType = .Operand(operand) + } + + init(operatorType: OperatorType) { + tokenType = .Operator(OperatorToken(operatorType: operatorType)) + } + + var isOpenBracket: Bool { + switch tokenType { + case .OpenBracket: + return true + default: + return false + } + } + + var isOperator: Bool { + switch tokenType { + case .Operator(_): + return true + default: + return false + } + } + + var operatorToken: OperatorToken? { + switch tokenType { + case .Operator(let operatorToken): + return operatorToken + default: + return nil + } + } + + public var description: String { + return tokenType.description + } } -internal struct Token: CustomStringConvertible { - - var tokenType: TokenType - - init(tokenType: TokenType) { - self.tokenType = tokenType - } - - init(operand: Double) { - tokenType = .Operand(operand) - } - - init(operatorType: OperatorType) { - tokenType = .Operator(OperatorToken(operatorType: operatorType)) - } - - var isOpenBracket: Bool { - switch tokenType { - case .OpenBracket: - return true - default: - return false - } - } - - var isOperator: Bool { - switch tokenType { - case .Operator(_): - return true - default: - return false - } - } - - var operatorToken: OperatorToken? { - switch tokenType { - case .Operator(let operatorToken): - return operatorToken - default: - return nil - } - } - - var description: String { - return tokenType.description - } +public class InfixExpressionBuilder { + + private var expression = Array() + + public func addOperator(operatorType: OperatorType) -> InfixExpressionBuilder { + expression.append(Token(operatorType: operatorType)) + return self + } + + public func addOperand(operand: Double) -> InfixExpressionBuilder { + expression.append(Token(operand: operand)) + return self + } + + public func addOpenBracket() -> InfixExpressionBuilder { + expression.append(Token(tokenType: .OpenBracket)) + return self + } + + public func addCloseBracket() -> InfixExpressionBuilder { + expression.append(Token(tokenType: .CloseBracket)) + return self + } + + public func build() -> Array { + // Maybe do some validation here + return expression + } } -public struct Expression { - var expression = Array() - - init() { - expression.append(Token(operand: 3)) - expression.append(Token(operatorType: OperatorType.Add)) - expression.append(Token(operand: 4)) - expression.append(Token(operatorType: OperatorType.Multiply)) - expression.append(Token(operand: 2)) - expression.append(Token(operatorType: OperatorType.Divide)) - expression.append(Token(tokenType: TokenType.OpenBracket)) - expression.append(Token(operand: 1)) - expression.append(Token(operatorType: OperatorType.Subtract)) - expression.append(Token(operand: 5)) - expression.append(Token(tokenType: TokenType.CloseBracket)) - expression.append(Token(operatorType: OperatorType.Exponent)) - expression.append(Token(operand: 2)) - expression.append(Token(operatorType: OperatorType.Exponent)) - expression.append(Token(operand: 3)) - } - - public func reversePolishNotation() -> String { - - var tokenStack = Stack() - var reversePolishNotation = [Token]() - - for token in expression { - switch token.tokenType { - case .Operand(_): - reversePolishNotation.append(token) - break - case .OpenBracket: - tokenStack.push(token) - break - case .CloseBracket: - while tokenStack.count > 0 { - if let tempToken = tokenStack.pop() where !tempToken.isOpenBracket { - reversePolishNotation.append(tempToken) - } else { - break - } - } - break - case .Operator(let operatorToken): - - for tempToken in tokenStack.generate() { - if !tempToken.isOperator { - break - } - - if let tempOperatorToken = tempToken.operatorToken { - - if operatorToken.associativity == .LeftAssociative && operatorToken <= tempOperatorToken - || operatorToken.associativity == .RightAssociative && operatorToken < tempOperatorToken { - - reversePolishNotation.append(tokenStack.pop()!) - } else { - break - } - } - } - - tokenStack.push(token) - break - - } +// This returns the result of the shunting yard algorithm +public func reversePolishNotation(expression: Array) -> String { + + var tokenStack = Stack() + var reversePolishNotation = [Token]() + + for token in expression { + switch token.tokenType { + case .Operand(_): + reversePolishNotation.append(token) + break + case .OpenBracket: + tokenStack.push(token) + break + case .CloseBracket: + while tokenStack.count > 0 { + if let tempToken = tokenStack.pop() where !tempToken.isOpenBracket { + reversePolishNotation.append(tempToken) + } else { + break } - - while tokenStack.count > 0 { - reversePolishNotation.append(tokenStack.pop()!) + } + break + case .Operator(let operatorToken): + + for tempToken in tokenStack.generate() { + if !tempToken.isOperator { + break } - return reversePolishNotation.map({token in - return token.description - }).joinWithSeparator(", ") - } + if let tempOperatorToken = tempToken.operatorToken { + + if operatorToken.associativity == .LeftAssociative && operatorToken <= tempOperatorToken + || operatorToken.associativity == .RightAssociative && operatorToken < tempOperatorToken { + + reversePolishNotation.append(tokenStack.pop()!) + } else { + break + } + } + } + + tokenStack.push(token) + break + } + } + + while tokenStack.count > 0 { + reversePolishNotation.append(tokenStack.pop()!) + } + + return reversePolishNotation.map({token in + return token.description + }).joinWithSeparator(" ") } \ No newline at end of file From 6943444ba42894d3dec642acda215a3256da6ef9 Mon Sep 17 00:00:00 2001 From: Matthijs Hollemans Date: Sat, 27 Feb 2016 17:12:46 +0100 Subject: [PATCH 0055/1679] Add recursive implementation of GCD --- GCD/GCD.playground/Contents.swift | 19 +++++++++++--- GCD/GCD.swift | 12 +++++++++ GCD/README.markdown | 43 +++++++++++++++++++------------ 3 files changed, 54 insertions(+), 20 deletions(-) diff --git a/GCD/GCD.playground/Contents.swift b/GCD/GCD.playground/Contents.swift index ab18c9a05..387d5de94 100644 --- a/GCD/GCD.playground/Contents.swift +++ b/GCD/GCD.playground/Contents.swift @@ -1,5 +1,17 @@ //: Playground - noun: a place where people can play +// Recursive version +func gcd(a: Int, _ b: Int) -> Int { + let r = a % b + if r != 0 { + return gcd(b, r) + } else { + return b + } +} + +/* +// Iterative version func gcd(m: Int, _ n: Int) -> Int { var a = 0 var b = max(m, n) @@ -12,14 +24,15 @@ func gcd(m: Int, _ n: Int) -> Int { } return b } +*/ func lcm(m: Int, _ n: Int) -> Int { return m*n / gcd(m, n) } -gcd(39, 52) // 13 -gcd(36, 228) // 12 -gcd(3819, 51357) // 57 +gcd(52, 39) // 13 +gcd(228, 36) // 12 +gcd(51357, 3819) // 57 gcd(841, 299) // 1 lcm(2, 3) // 6 diff --git a/GCD/GCD.swift b/GCD/GCD.swift index 222f8284e..dc473ccd4 100644 --- a/GCD/GCD.swift +++ b/GCD/GCD.swift @@ -14,6 +14,18 @@ func gcd(m: Int, _ n: Int) -> Int { return b } +/* +// Recursive version +func gcd(a: Int, _ b: Int) -> Int { + let r = a % b + if r != 0 { + return gcd(b, r) + } else { + return b + } +} +*/ + /* Returns the least common multiple of two numbers. */ diff --git a/GCD/README.markdown b/GCD/README.markdown index 63cd9afa4..a7fe799d9 100644 --- a/GCD/README.markdown +++ b/GCD/README.markdown @@ -17,34 +17,26 @@ where `a % b` calculates the remainder of `a` divided by `b`. Here is an implementation of this idea in Swift: ```swift -func gcd(m: Int, _ n: Int) -> Int { - var a = 0 - var b = max(m, n) - var r = min(m, n) - - while r != 0 { - a = b - b = r - r = a % b +func gcd(a: Int, _ b: Int) -> Int { + let r = a % b + if r != 0 { + return gcd(b, r) + } else { + return b } - return b } ``` Put it in a playground and try it out with these examples: ```swift -gcd(39, 52) // 13 -gcd(36, 228) // 12 -gcd(3819, 51357) // 57 +gcd(52, 39) // 13 +gcd(228, 36) // 12 +gcd(51357, 3819) // 57 ``` Let's step through the third example: - gcd(3819, 51357) - -It's convenient to have the larger number first, so we swap them. That's what the `max()` and `min()` are for at the top of the function. We now have: - gcd(51357, 3819) According to Euclid's rule, this is equivalent to: @@ -73,6 +65,23 @@ By the way, it's also possible that two numbers have a GCD of 1. They are said t gcd(841, 299) // 1 ``` +Here is a slightly different implementation of Euclid's algorithm. Unlike the first version this doesn't use recursion but only a basic `while` loop. The `max()` and `min()` at the top of the function make sure we always divide the larger number by the smaller one. + +```swift +func gcd(m: Int, _ n: Int) -> Int { + var a = 0 + var b = max(m, n) + var r = min(m, n) + + while r != 0 { + a = b + b = r + r = a % b + } + return b +} +``` + ## Least Common Multiple An idea related to the GCD is the *least common multiple* or LCM. From ae60a894e2b3d8438043672819b04f0e912f56d3 Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Sun, 28 Feb 2016 21:59:39 +1300 Subject: [PATCH 0056/1679] BFS adding readme documentation for calculating minimum spanning tree --- Breadth-First Search/README.markdown | 148 ++++++++++++++++++++++++++- 1 file changed, 145 insertions(+), 3 deletions(-) diff --git a/Breadth-First Search/README.markdown b/Breadth-First Search/README.markdown index 96be1d4b4..41ef739b8 100644 --- a/Breadth-First Search/README.markdown +++ b/Breadth-First Search/README.markdown @@ -175,14 +175,156 @@ breadthFirstSearchShortestPath(graph, source: nodeA) Breadth-first search can be used to calculate the [minimum spanning tree](../Minimum Spanning Tree/) on an unweighted graph. +Let's calculate the minimum spanning tree for the following graph: + ![Minimum spanning tree](Images/Minimum_Spanning_Tree.png) -The minimum spanning tree is represented by the bold edges. +*Note: the minimum spanning tree is represented by the bold edges.* + +Start with the source node ``a`` and add it to a queue and mark it as visited. +```swift +queue.enqueue(a) +a.visited = true +``` +The queue is now ``[ a ]``. Dequeue ``a`` and enqueue the neighbor nodes ``b`` and ``h`` and mark them as visited. +```swift +queue.dequeue(a) +queue.enqueue(b) +b.visited = true +queue.enqueue(h) +h.visited = true +``` +The queue is now ``[ b, h ]``. Dequeue ``b`` and enqueue the neighbor node ``c`` mark it as visited. Remove the edge between ``b`` to ``h`` because ``h`` has already been visited. +```swift +queue.dequeue(b) +queue.enqueue(c) +c.visited = true +b.removeEdgeTo(h) +``` +The queue is now ``[ h, c ]``. Dequeue ``h`` and enqueue the neighbor nodes ``g`` and ``i`` and mark them as visited. +```swift +queue.dequeue(h) +queue.enqueue(g) +g.visited = true +queue.enqueue(i) +i.visited = true +``` +The queue is now ``[ c, g, i ]``. Dequeue ``c`` and enqueue the neighbor nodes ``d`` and ``f`` and mark them as visited. Remove the edge between ``c`` to ``i`` because ``i`` has already been visited. +```swift +queue.dequeue(c) +queue.enqueue(d) +d.visited = true +queue.enqueue(f) +f.visited = true +c.removeEdgeTo(i) +``` +The queue is now ``[ g, i, d, f ]``. Dequeue ``g`` and remove the edges between ``g`` to ``f`` and ``g`` to ``i`` because ``f`` and ``i`` have already been visited. +```swift +queue.dequeue(g) +g.removeEdgeTo(f) +g.removeEdgeTo(i) +``` +The queue is now ``[ i, d, f ]``. Dequeue ``i``. +```swift +queue.dequeue(i) +``` +The queue is now ``[ d, f ]``. Dequeue ``d`` and enqueue the neighbor node ``e`` mark it as visited. Remove the edge between ``d`` to ``f`` because ``f`` has already been visited. +```swift +queue.dequeue(d) +queue.enqueue(e) +e.visited = true +d.removeEdgeTo(f) +``` +The queue is now ``[ f, e ]``. Dequeue ``f``. Remove the edge between ``f`` to ``e`` because ``e`` has already been visited. +```swift +queue.dequeue(f) +f.removeEdgeTo(e) +``` +The queue is now ``[ e ]``. Dequeue ``e``. +```swift +queue.dequeue(e) +``` +The queue is now empty which means the minimum spanning tree has been computed. + +Here's the code: +```swift +func breadthFirstSearchMinimumSpanningTree(graph: Graph, source: Node) -> Graph { + let minimumSpanningTree = graph.duplicate() + + var queue = Queue() + let sourceInMinimumSpanningTree = minimumSpanningTree.findNodeWithLabel(source.label) + queue.enqueue(sourceInMinimumSpanningTree) + sourceInMinimumSpanningTree.visited = true + + while !queue.isEmpty { + let current = queue.dequeue()! + for edge in current.neighbors { + let neighborNode = edge.neighbor + if !neighborNode.visited { + neighborNode.visited = true + queue.enqueue(neighborNode) + } else { + current.remove(edge) + } + } + } + + return minimumSpanningTree +} +``` +Put this code in a playground and test it like so: +```swift +let graph = Graph() -TODO: explain steps to generate minimum spanning tree +let nodeA = graph.addNode("a") +let nodeB = graph.addNode("b") +let nodeC = graph.addNode("c") +let nodeD = graph.addNode("d") +let nodeE = graph.addNode("e") +let nodeF = graph.addNode("f") +let nodeG = graph.addNode("g") +let nodeH = graph.addNode("h") +let nodeI = graph.addNode("i") +graph.addEdge(nodeA, neighbor: nodeB) +graph.addEdge(nodeA, neighbor: nodeH) +graph.addEdge(nodeB, neighbor: nodeA) +graph.addEdge(nodeB, neighbor: nodeC) +graph.addEdge(nodeB, neighbor: nodeH) +graph.addEdge(nodeC, neighbor: nodeB) +graph.addEdge(nodeC, neighbor: nodeD) +graph.addEdge(nodeC, neighbor: nodeF) +graph.addEdge(nodeC, neighbor: nodeI) +graph.addEdge(nodeD, neighbor: nodeC) +graph.addEdge(nodeD, neighbor: nodeE) +graph.addEdge(nodeD, neighbor: nodeF) +graph.addEdge(nodeE, neighbor: nodeD) +graph.addEdge(nodeE, neighbor: nodeF) +graph.addEdge(nodeF, neighbor: nodeC) +graph.addEdge(nodeF, neighbor: nodeD) +graph.addEdge(nodeF, neighbor: nodeE) +graph.addEdge(nodeF, neighbor: nodeG) +graph.addEdge(nodeG, neighbor: nodeF) +graph.addEdge(nodeG, neighbor: nodeH) +graph.addEdge(nodeG, neighbor: nodeI) +graph.addEdge(nodeH, neighbor: nodeA) +graph.addEdge(nodeH, neighbor: nodeB) +graph.addEdge(nodeH, neighbor: nodeG) +graph.addEdge(nodeH, neighbor: nodeI) +graph.addEdge(nodeI, neighbor: nodeC) +graph.addEdge(nodeI, neighbor: nodeG) +graph.addEdge(nodeI, neighbor: nodeH) + +let minimumSpanningTree = breadthFirstSearchMinimumSpanningTree(graph, source: nodeA) + +print(minimumSpanningTree) // [node: a edges: ["b", "h"]] + // [node: b edges: ["c"]] + // [node: c edges: ["d", "f"]] + // [node: d edges: ["e"]] + // [node: h edges: ["g", "i"]] +``` ## See also -[Graph](../Graph/), [Tree](../Tree/), [Queues](../Queue/), [Shortest Path](../Shortest Path/), [Breadth-first search on Wikipedia](https://en.wikipedia.org/wiki/Breadth-first_search), [Minimum spanning tree on Wikipedia](https://en.wikipedia.org/wiki/Minimum_spanning_tree). +[Graph](../Graph/), [Tree](../Tree/), [Queues](../Queue/), [Shortest Path](../Shortest Path/), [Minimum Spanning Tree](../Minimum Spanning Tree/). *Written by [Chris Pilcher](https://github.com/chris-pilcher)* From a1f6cac6d83372d44bb49e68a9cb68460dc55694 Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Sun, 28 Feb 2016 22:50:28 +1300 Subject: [PATCH 0057/1679] BFS adding pages to playground. Including minimum spanning tree example. --- .../Contents.swift | 140 ------------------ .../Contents.swift | 71 +++++++++ .../timeline.xctimeline | 0 .../Contents.swift | 43 ++++++ .../timeline.xctimeline | 6 + .../Contents.swift | 45 ++++++ .../timeline.xctimeline | 6 + .../Resources/Animated_BFS.gif | Bin 0 -> 33276 bytes .../Resources/Minimum_Spanning_Tree.png | Bin 0 -> 23928 bytes .../Sources/Edge.swift | 7 + .../Sources/Graph.swift | 52 +++++++ .../Sources/Node.swift | 32 ++++ .../Sources/Queue.swift | 31 ++++ .../contents.xcplayground | 8 +- Breadth-First Search/README.markdown | 6 +- 15 files changed, 302 insertions(+), 145 deletions(-) delete mode 100644 Breadth-First Search/BreadthFirstSearch.playground/Contents.swift create mode 100644 Breadth-First Search/BreadthFirstSearch.playground/Pages/Minimum spanning tree example.xcplaygroundpage/Contents.swift rename Breadth-First Search/BreadthFirstSearch.playground/{ => Pages/Minimum spanning tree example.xcplaygroundpage}/timeline.xctimeline (100%) create mode 100644 Breadth-First Search/BreadthFirstSearch.playground/Pages/Shortest path example.xcplaygroundpage/Contents.swift create mode 100644 Breadth-First Search/BreadthFirstSearch.playground/Pages/Shortest path example.xcplaygroundpage/timeline.xctimeline create mode 100644 Breadth-First Search/BreadthFirstSearch.playground/Pages/Simple example.xcplaygroundpage/Contents.swift create mode 100644 Breadth-First Search/BreadthFirstSearch.playground/Pages/Simple example.xcplaygroundpage/timeline.xctimeline create mode 100644 Breadth-First Search/BreadthFirstSearch.playground/Resources/Animated_BFS.gif create mode 100644 Breadth-First Search/BreadthFirstSearch.playground/Resources/Minimum_Spanning_Tree.png create mode 100644 Breadth-First Search/BreadthFirstSearch.playground/Sources/Edge.swift create mode 100644 Breadth-First Search/BreadthFirstSearch.playground/Sources/Graph.swift create mode 100644 Breadth-First Search/BreadthFirstSearch.playground/Sources/Node.swift create mode 100644 Breadth-First Search/BreadthFirstSearch.playground/Sources/Queue.swift diff --git a/Breadth-First Search/BreadthFirstSearch.playground/Contents.swift b/Breadth-First Search/BreadthFirstSearch.playground/Contents.swift deleted file mode 100644 index 640a0e045..000000000 --- a/Breadth-First Search/BreadthFirstSearch.playground/Contents.swift +++ /dev/null @@ -1,140 +0,0 @@ -class Graph { - private var nodes = [Node]() - - func addNode(label: String) -> Node { - let node = Node(label: label) - nodes.append(node) - return node - } - - func addEdge(source: Node, neighbor: Node) { - let edge = Edge(neighbor: neighbor) - edge.neighbor = neighbor - source.neighbors.append(edge) - } -} - -class Node : CustomStringConvertible, Equatable { - private var label: String - private var neighbors: [Edge] - private var distance: Int? - - init(label: String) { - self.label = label - neighbors = [] - } - - var description: String { - if let distance = distance { - return "Node(label: \(label), distance: \(distance))" - } - return "Node(label: \(label), distance: infinity)" - } - - var hasDistance: Bool { - return distance != nil - } -} - -func ==(lhs: Node, rhs: Node) -> Bool { - return lhs.label == rhs.label -} - -class Edge { - private var neighbor: Node - - init(neighbor: Node) { - self.neighbor = neighbor - } -} - -struct Queue { - var array = [T]() - - var isEmpty: Bool { - return array.isEmpty - } - - var count: Int { - return array.count - } - - mutating func enqueue(element: T) { - array.append(element) - } - - mutating func dequeue() -> T? { - if isEmpty { - return nil - } else { - return array.removeFirst() - } - } - - func peek() -> T? { - return array.first - } -} - -func breadthFirstSearch(graph: Graph, source: Node) { - print("Performing breadth-first search on '\(source.label)'") - - var seenNodes = [source] - var queue = Queue() - queue.enqueue(source) - - while !queue.isEmpty { - let current = queue.dequeue()! - for edge in current.neighbors { - let neighborNode = edge.neighbor - if !seenNodes.contains(neighborNode) { - queue.enqueue(neighborNode) - seenNodes.append(neighborNode) - print(neighborNode.label) - } - } - } -} - -func breadthFirstSearchShortestPath(graph: Graph, source: Node) { - var queue = Queue() - queue.enqueue(source) - source.distance = 0 - - while !queue.isEmpty { - let current = queue.dequeue()! - for edge in current.neighbors { - let neighborNode = edge.neighbor - if !neighborNode.hasDistance { - queue.enqueue(neighborNode) - neighborNode.distance = current.distance! + 1 - } - } - } - - print(graph.nodes) -} - - -let graph = Graph() - -let nodeA = graph.addNode("a") -let nodeB = graph.addNode("b") -let nodeC = graph.addNode("c") -let nodeD = graph.addNode("d") -let nodeE = graph.addNode("e") -let nodeF = graph.addNode("f") -let nodeG = graph.addNode("g") -let nodeH = graph.addNode("h") - -graph.addEdge(nodeA, neighbor: nodeB) -graph.addEdge(nodeA, neighbor: nodeC) -graph.addEdge(nodeB, neighbor: nodeD) -graph.addEdge(nodeB, neighbor: nodeE) -graph.addEdge(nodeC, neighbor: nodeF) -graph.addEdge(nodeC, neighbor: nodeG) -graph.addEdge(nodeE, neighbor: nodeH) - - -breadthFirstSearch(graph, source: nodeA) -breadthFirstSearchShortestPath(graph, source: nodeA) diff --git a/Breadth-First Search/BreadthFirstSearch.playground/Pages/Minimum spanning tree example.xcplaygroundpage/Contents.swift b/Breadth-First Search/BreadthFirstSearch.playground/Pages/Minimum spanning tree example.xcplaygroundpage/Contents.swift new file mode 100644 index 000000000..181d566d4 --- /dev/null +++ b/Breadth-First Search/BreadthFirstSearch.playground/Pages/Minimum spanning tree example.xcplaygroundpage/Contents.swift @@ -0,0 +1,71 @@ +func breadthFirstSearchMinimumSpanningTree(graph: Graph, source: Node) -> Graph { + let minimumSpanningTree = graph.duplicate() + + var queue = Queue() + let sourceInMinimumSpanningTree = minimumSpanningTree.findNodeWithLabel(source.label) + queue.enqueue(sourceInMinimumSpanningTree) + sourceInMinimumSpanningTree.visited = true + + while !queue.isEmpty { + let current = queue.dequeue()! + for edge in current.neighbors { + let neighborNode = edge.neighbor + if !neighborNode.visited { + neighborNode.visited = true + queue.enqueue(neighborNode) + } else { + current.remove(edge) + } + } + } + + return minimumSpanningTree +} + +/*: +![Animated example of a breadth-first search](Minimum_Spanning_Tree.png) +*/ + +let graph = Graph() + +let nodeA = graph.addNode("a") +let nodeB = graph.addNode("b") +let nodeC = graph.addNode("c") +let nodeD = graph.addNode("d") +let nodeE = graph.addNode("e") +let nodeF = graph.addNode("f") +let nodeG = graph.addNode("g") +let nodeH = graph.addNode("h") +let nodeI = graph.addNode("i") + +graph.addEdge(nodeA, neighbor: nodeB) +graph.addEdge(nodeA, neighbor: nodeH) +graph.addEdge(nodeB, neighbor: nodeA) +graph.addEdge(nodeB, neighbor: nodeC) +graph.addEdge(nodeB, neighbor: nodeH) +graph.addEdge(nodeC, neighbor: nodeB) +graph.addEdge(nodeC, neighbor: nodeD) +graph.addEdge(nodeC, neighbor: nodeF) +graph.addEdge(nodeC, neighbor: nodeI) +graph.addEdge(nodeD, neighbor: nodeC) +graph.addEdge(nodeD, neighbor: nodeE) +graph.addEdge(nodeD, neighbor: nodeF) +graph.addEdge(nodeE, neighbor: nodeD) +graph.addEdge(nodeE, neighbor: nodeF) +graph.addEdge(nodeF, neighbor: nodeC) +graph.addEdge(nodeF, neighbor: nodeD) +graph.addEdge(nodeF, neighbor: nodeE) +graph.addEdge(nodeF, neighbor: nodeG) +graph.addEdge(nodeG, neighbor: nodeF) +graph.addEdge(nodeG, neighbor: nodeH) +graph.addEdge(nodeG, neighbor: nodeI) +graph.addEdge(nodeH, neighbor: nodeA) +graph.addEdge(nodeH, neighbor: nodeB) +graph.addEdge(nodeH, neighbor: nodeG) +graph.addEdge(nodeH, neighbor: nodeI) +graph.addEdge(nodeI, neighbor: nodeC) +graph.addEdge(nodeI, neighbor: nodeG) +graph.addEdge(nodeI, neighbor: nodeH) + +let minimumSpanningTree = breadthFirstSearchMinimumSpanningTree(graph, source: nodeA) +print(minimumSpanningTree) diff --git a/Breadth-First Search/BreadthFirstSearch.playground/timeline.xctimeline b/Breadth-First Search/BreadthFirstSearch.playground/Pages/Minimum spanning tree example.xcplaygroundpage/timeline.xctimeline similarity index 100% rename from Breadth-First Search/BreadthFirstSearch.playground/timeline.xctimeline rename to Breadth-First Search/BreadthFirstSearch.playground/Pages/Minimum spanning tree example.xcplaygroundpage/timeline.xctimeline diff --git a/Breadth-First Search/BreadthFirstSearch.playground/Pages/Shortest path example.xcplaygroundpage/Contents.swift b/Breadth-First Search/BreadthFirstSearch.playground/Pages/Shortest path example.xcplaygroundpage/Contents.swift new file mode 100644 index 000000000..175821efc --- /dev/null +++ b/Breadth-First Search/BreadthFirstSearch.playground/Pages/Shortest path example.xcplaygroundpage/Contents.swift @@ -0,0 +1,43 @@ +func breadthFirstSearchShortestPath(graph: Graph, source: Node) { + var queue = Queue() + queue.enqueue(source) + source.distance = 0 + + while !queue.isEmpty { + let current = queue.dequeue()! + for edge in current.neighbors { + let neighborNode = edge.neighbor + if !neighborNode.hasDistance { + queue.enqueue(neighborNode) + neighborNode.distance = current.distance! + 1 + } + } + } + + print(graph.nodes) +} + +/*: +![Animated example of a breadth-first search](Animated_BFS.gif) +*/ + +let graph = Graph() + +let nodeA = graph.addNode("a") +let nodeB = graph.addNode("b") +let nodeC = graph.addNode("c") +let nodeD = graph.addNode("d") +let nodeE = graph.addNode("e") +let nodeF = graph.addNode("f") +let nodeG = graph.addNode("g") +let nodeH = graph.addNode("h") + +graph.addEdge(nodeA, neighbor: nodeB) +graph.addEdge(nodeA, neighbor: nodeC) +graph.addEdge(nodeB, neighbor: nodeD) +graph.addEdge(nodeB, neighbor: nodeE) +graph.addEdge(nodeC, neighbor: nodeF) +graph.addEdge(nodeC, neighbor: nodeG) +graph.addEdge(nodeE, neighbor: nodeH) + +breadthFirstSearchShortestPath(graph, source: nodeA) diff --git a/Breadth-First Search/BreadthFirstSearch.playground/Pages/Shortest path example.xcplaygroundpage/timeline.xctimeline b/Breadth-First Search/BreadthFirstSearch.playground/Pages/Shortest path example.xcplaygroundpage/timeline.xctimeline new file mode 100644 index 000000000..bf468afec --- /dev/null +++ b/Breadth-First Search/BreadthFirstSearch.playground/Pages/Shortest path example.xcplaygroundpage/timeline.xctimeline @@ -0,0 +1,6 @@ + + + + + diff --git a/Breadth-First Search/BreadthFirstSearch.playground/Pages/Simple example.xcplaygroundpage/Contents.swift b/Breadth-First Search/BreadthFirstSearch.playground/Pages/Simple example.xcplaygroundpage/Contents.swift new file mode 100644 index 000000000..b2ac225ab --- /dev/null +++ b/Breadth-First Search/BreadthFirstSearch.playground/Pages/Simple example.xcplaygroundpage/Contents.swift @@ -0,0 +1,45 @@ +func breadthFirstSearch(graph: Graph, source: Node) { + var seenNodes = [source] + var queue = Queue() + queue.enqueue(source) + + print(source.label) + + while !queue.isEmpty { + let current = queue.dequeue()! + for edge in current.neighbors { + let neighborNode = edge.neighbor + if !seenNodes.contains(neighborNode) { + queue.enqueue(neighborNode) + seenNodes.append(neighborNode) + print(neighborNode.label) + } + } + } +} + +/*: +![Animated example of a breadth-first search](Animated_BFS.gif) +*/ + +let graph = Graph() + +let nodeA = graph.addNode("a") +let nodeB = graph.addNode("b") +let nodeC = graph.addNode("c") +let nodeD = graph.addNode("d") +let nodeE = graph.addNode("e") +let nodeF = graph.addNode("f") +let nodeG = graph.addNode("g") +let nodeH = graph.addNode("h") + +graph.addEdge(nodeA, neighbor: nodeB) +graph.addEdge(nodeA, neighbor: nodeC) +graph.addEdge(nodeB, neighbor: nodeD) +graph.addEdge(nodeB, neighbor: nodeE) +graph.addEdge(nodeC, neighbor: nodeF) +graph.addEdge(nodeC, neighbor: nodeG) +graph.addEdge(nodeE, neighbor: nodeH) + + +breadthFirstSearch(graph, source: nodeA) diff --git a/Breadth-First Search/BreadthFirstSearch.playground/Pages/Simple example.xcplaygroundpage/timeline.xctimeline b/Breadth-First Search/BreadthFirstSearch.playground/Pages/Simple example.xcplaygroundpage/timeline.xctimeline new file mode 100644 index 000000000..bf468afec --- /dev/null +++ b/Breadth-First Search/BreadthFirstSearch.playground/Pages/Simple example.xcplaygroundpage/timeline.xctimeline @@ -0,0 +1,6 @@ + + + + + diff --git a/Breadth-First Search/BreadthFirstSearch.playground/Resources/Animated_BFS.gif b/Breadth-First Search/BreadthFirstSearch.playground/Resources/Animated_BFS.gif new file mode 100644 index 0000000000000000000000000000000000000000..d8fe07cbc40a0a19534b597e123bf803de42f205 GIT binary patch literal 33276 zcmbr_cTiJp!|(g7wX#wngb*O~gc@21)lf}nBBDk_iXa9=MMaDX2#A`5-UCt`fPnq}AVgY5Lnhg!A_ zCwc6bx1|IhTYh5nXxg>6nHLq(^pF)zTE`qC;jd9sv~U- z^p192sMXRuAI{L!x;T_)rZccr$87laCVPTatQDc<&ZCt^COi|v@n_Kv1WTTk`i;rA zTzj&^LWU{Te6a)h&AXoqED0a#>ckQnhi&;n{yBOyApmJ*%Sxd0`NMc@GG%?pgm3=^ zQyMOTBI_?K#+uAopF=%RScEfTNcg6p=<43UU|w6>^MKjB?W}BEA+di!LB4NpXS#%2 zT!^;Vjf0zH%WJf7?4atR`0V_ukeGBib8GvE4$Y}fF*cc7s7C9me_Uh=p)_np^)s6K z2XfU`PvI76P5?-C%P@L)M|=lXjbxk?MC*3a)Yb?}Y~%KUIcOcbFu8&zin&(9$!bs4 zNAX75RzwyYG51H09*%HW*QfS1Mprx0;l1SE*ZW$O#$MM8u6}k_4$R2aWm-K?%q^U_ z8b{oMKfQdUXSzS$ci^+~S;NwATtn}<=~J~*sr;e$9HQ}2;+ek|o#tC#dq0P;Gcw3Z z;YLs7?kA63+QzefygE*ieX(S!DvkX8KxUWLGEq6bPTpMZkr~mCGKiF-VWK~q z17{`7uh(^uC}qgZH<|!4V!5mjwISfJKi(vP$U&PY4&23=B@%_G&FeV%jRqykm2A5b zIR~kirQE-lk;Usn3uy@=w2+m!#K^eo&K!l?d3Oh7ELt9%c5`hDeye z$tc-?Z7#!wxIxE^&3lQTC9?14dhBoy1H^O27=ut-4ivzg2KfmNqE?Xge>NboLtB;{$hU4Ty|iQz z@p%B2V4h@%)5L6qaTJa@rzP?z^II{+t{ukV#=rQZasEk{aO&m}s~S;D-}_?DIbmw= z1WoE~n=LKmE7G;B)9-a;86{D_YiXu(KNmZQ5q+?E*N-Xquh6F5C{z04ewZjmcgb*g?o6O=&ViXAUiO}QE@W$!HY8+L->qBnm%T5O6 z35fzlTJ>ua)bURU^c!KwKOg<^ZoIkLPaRVI(uJrv_FPJ$GIQAsRgFz0XzB=Ia>*UI zUM?Kd?oSS8$H69_Lvg0>D zCFLYyOr7FHfeD1!7FGb`vapaVrhW0^`{~$J5P4Zww9c5-ICaX4`O*VgvxD76=7GW@ zhol4gCt0=j;Z3=9;%8dZ1qPnMKzZWGDzY>($SD>OdxRyBG1ip1J|9Z91g+AhM9tTb zY2pg1vZ)8z!!0B7()__mT?==3(Vjbb(Sk{uOGa+!kwI~-nz`*^#not!JDc{KL-rlK zYdah6;5%IgnH};4t7bd#O)&>chWf?&sE_3j$OBF%xz{%;oNC6@2IxIKfguG<*lvcp z_(BG(nI_LkAkwhj-5iF??neCt4sPTnOm53tusu;wgTU1K^zr6KD@-t-5Nsg!CHRk@ zLOWc-MtO)6h;W~>jXkfc1s0GC*icZQaGvXdC{wur>Y6dub_0H&PTSFb++Sq0q@$0B@mrjG!^ z&=}NfnXqYj4onlX;XSBa-5k@S$Ks7X9tzHx3b=L1fD5n4=ZkPbREBH|2TP`5=#$5x zb4z{O0t0d%&JV-(+%=i!&AqvpkI+3fq8+^;VC*lBsr`)&xoZwGMQRd~$5Fh!R+6^p zJPt^GfUj;n&a)-9n41vW4r>Jq1biHAYxxde97(#s&_+-$TP1jzC_>yjO&T&D8+pwmw%qjAuN>EV^06>t_6Xwp3d| z(>?T}JF&Cmd_VzV%NcZDuOr8Kabh2q^-GdTue%t?q0X7&}-O2W~*$AD+rzSmq(ASk=JX44iyxvfGV=IWxz z=}a6$o-?aX5x`o?t%r}6Aa%scv09k22O*u$%)_o@X?z#5=wyz?91arVvp1Jhcbm5H zfWFm2q$Pq~nyR4CR|)p!3q-JV;VRQ~gq9)kCc&I~H7j70WGQ`3OOgOoBH7<10tuO! z&kr7u?a5a%rs>CHLu9q*s=o+#z-Kqj;|ZZax#(wZ6f{q9LO1?lj?Slcyg7y9dndIN zHC+QfM%_eCPp!JM(FLi?Kc?CBd=;fi0@fxEA!T@Iqhrr9ZRtljT`+FWnF5bweLU&n zlS8JP8p7g=6B!WSx7(M(MLO{|KAE z$m<4ez`N_c;0<>+roHokwNqqiVUcfc+Gp9=OfFi|i|pHQi0GB%ci?rDgD*bbson}x zqqTKyZc>+~K=f4l9=Uf4YU_;<>{|AFfzhPbb#fo{EG*-}dib&IQR{!|!`z zD)B)dce0NDLM~cf`Mg!qVti17e4Vd9JZWk0bR}|{0Hq7?6$0GQtOjaSFfJ1ig9s#+ zP?NG%hpw(&C%ml`7|!60XM|l+q3JZ97Ab0Fi|BN`O}EHgBxKZy7VBo`$we;dSgZ7G zS5~$M1?@hXy@i*}rsR0Ba=wItV|{u$a)hK$@7#oWU=XU3X(>HGvE}EMbbzN#0lU7G zC2by7JY5qhSTg~x*#_t&8t$#wCMjU}-Ou#hR{9~%ZEzbB zdjJ^k&ND~gQvx)q3(BxH5vmiB4HeXt1Ak+RdQM_C@Qv&hi?yk^*NNr+3UGEeI$df( z7(<&1ig1OPwN$K`7+fnBYmZeJXTTiQq5Z!O@Bcoj=c+iuVzK7Vo%=^5ix)3eaU?1# zO2v^?t5*Ht$i|HuRUAo8O;vGZ*REYEj^yR#6&Dw)II?^9ZWTxB>gxU{9JzV(=KsQx z7cXA?UvlJsAdQ2eHvg7}#eqoE@~mcHc%GfM>3>PXfUHi|H=&6u#3uU1WP{}VJ$s|= z4K#HPE2y-VL)4ZE!)*rk4JV{r3vJzUaofS3LuU`0=#niu`Um{&DYa+151+esriWHU zIX*bjK*E+EzIpam>p0B>OS(6iXQnZB{c-Q(S0)-}&p&Lk$LrsGb@g@kc#A&%?hEXv zexdK-tbYimVe^Covi#^+yCJ5{Q^tJ!{?(C6@W4D0uVe2+`P8wxN(&qK z;;IAz0`;w=2LABf;n^Y-%P&P{#*6bo*<{)*o9GwjXIuM)5tURnI_DoB7O$skLj_vL z#&lA~^UdBqBYD@Ul(k2jT2Qm(`P$8AcM^koALAk4+)ZWK26>qL6Id z>qdmlcvD;wf)FNuqIS zpZu|e+1Tl2C`*4%Q?Bus76sWdQ4&{Ze;#3~y|rUH6i+@%f$=&Lt7i6(WpRo!;^%qP zA|r6P866pxIO#=Clr)nK8P>OoBTMM3U9HyNR#cDp59LgiQvo4B{=*iT971=JAB+PM^*FT_)4>r?9j7BY`l! zs>&u8r=N~Erq#ZVePAymo#&uq!RkLoa^RXaX-}sq|E?r^F_Xx)OetMUk159L(3U9H zV3W3V^ds-vRP-aY)^eW7LeI)&=a-it`uhBP5#_p8F1&YT#?mwXc+>0cgD6ubtslk9 z;!jmtHfJI6a0~X5yB+@h2VE;Bb8DepWY$JNFI~aVVsM$Kh#PjUK;q1+&P}}5)$)GMK=Po0J-9yx(utnH*jf%9{VRf|&Nc8iuoBkLg6X+8zXcNr4 zwWyBzv3ka}!d+9Jc^rw=7YHqD7rs0W|Gmgx;-YJrq-}}Q6vx6d69ye3q|wR_Uu5)3 zz0Kd2v`A#~g((u%Yvt!BX02%=v0U3BU2V8Q)(z?u!oFoZ}`Z7=jr<7a~2`_F~y zid$B<07FSE8^px$kR9h5Iv7lubrk~AC+29yutoUET%jk98o*K@)UwzxW2lL+wN6yY zmOxLh`X2I7=pK8^&$pRDpbYui>MiAq9Fzj|p(ZdaHRj=qZf74OU&g7uS zDMN4de3676J(C+%4uNi4v}gq_=9({?+?sAmI+kCh0F-hy62Ul_A7Q zOMh%`=+&SKX~{t|JZAyDtsqdWI&+PnAyYx>j)PF=l&*gHvx-Mc$2!K}%*=w|r1sPRlMt>}OT*BhS`h&~sr*VG&}4e(`_&Rs`?+ak5$PP$E%KvBFJ^Q_&N8@PC% zV@kBt0v}uv+0u#I+%E_ zRm29h6^4fb`NBtcHsmy%>c{@A>8m^QIXl?CA8SJuKAb+*W}!d?^HsT-|bE%WmkdJ4a zmJ)}qy-H5#v0ufhB3OYS;gi}gD@#eS$pE1t|{X2yF!;{{v+G|24)oinL zN!k^hzF)^s_pN0*74X(s(m!}#^dccP!+c0~tz3LUUEGVc{*Hj4%PZ{~6z9fsg&1nQ{{h&1$Tv}&j8(`~Iu{w4}a|IFO8+Pr7nMvo1ZnBulFT?M3FC|;Bz7iPDt|$hOqhF z1$*QLWr>&~N?~O|epL`=cY5I#MByF`x?!}?Xc=f23UtX4JOK0aQnZAHq7y*^6Zmof zw2^{c^kSP?xx=weRC}AHl^AgA0w1i7)s+Ab&J_OyKfhp9($xwPlzo1m|)VmYo)) zjQ&u7wBvguH@lX8UFAnFpz}85FGZ}%Eqg!$KAkQ$m+Qnp9!7jb={>}y?qWOXddxh8 zW>5vHHm7V9)X7+hk^_4ywyEB?eiR_T^6hOE#uu&tZYL}Irx3c<_~(JU1BlxoYot9F zxLaH1AdBDq6`_B4_a!3k(pTh@YJl2P^q2!Cy@+{VQ1$f`Kw*ROTGZRGRnMkZuylzS zYo;p$5#FWD3U`MYs>ewJKv!84Hy_W>0CcFJ_u<_(0x(k#G~=V_h#l+n>O}MZdjP4D z1saXULe0LS6A1-z`)SZkVd0fT3T9LTie^)J3BkOy1Kf%yL)?kb2yy9z`z9y z7O1Ec8X6iF7N&|fv9Yl#Ev;R_1v6D=Vw0sHmx_ zsjshZY-~Jm;6O`Diz?n6J9g~k$&+W!oayfFzHs4!OeRyso8jT%>({TVv~>Ue{YQ@; zsp8Gkr%xv*CskT{^X83Gsr+}mLCwnc|9_{Jd(XFc)W0dQJolHfeK87jCCvB&n^eys zeKw1-bLM(jQD8)INogrevGT~Rs*drtR0ql$_5tda-ZjlFTxUIS-;qW==YuDt{&o2F zQ~U5u9cP=Vdrx011*qo+bDS}<;S$X8OE(j|HLu=9XnNfm<=I{skpZ@2PosTEkMC*; zCtfY{(HMpZ8ftenUcUayor4|58tPizC5_7F$%o4_WSEd{Y5ekRBiPJlUF{oA5#A0% zZ@21rrb!saCDjRlC?|sPQc_c#%uov52s`pd@u3!7&&ud-Kl}=q^>1)mNmmTd@54*j zo0BMPvP_`P5}Urg9iO-mX86yq&h*Ox4_!slF`HMlN6}a@Tq0Ajw;2Ip!uXn>kFM}D zNi2{{v)>{u-9UuCe$zYyy9!t;?0}&zj+v&mHCZv z#=f1sv23|a%1Cy4X??aQfBS7;0{{KZFX2SfBD>3+P!;yCDiBQ>7Ai& zZ%zlK|ElQkPm7shg4m>Q8te)*h*E-Ll{3D%kAK6%Js{q>6Pd z(Ro+b;?3(6E3>_&R8iyc7iU|WnG&Wbeo42Ce&Vc1f1O%Ytj$x5ZeqlnliN>ofuaxz zS9oO5*Wd_Vw?s}=H|mxgJ8hT3)zzA1rSKKqw@%B2S>HcPIJoxC_I9ihb-h2@aumN2 zr#G_haoer%o_F1}L7Bf=-Wt#216hZbuhh^}9NB;;h`E2Cv`CR5(f@q^u?ba&x{{41 z&U+<-j0+_F&DMXv>_>mcJsm(#%x(v9jwfIBZM%O@!fEeGeknug`SbZ5j0FBWO^-zJ z)(-PTz6fPo(hl@aJeG29In9+FhAflb9KjoeROS#2LXK^KjR$3hqvw*D?WtZV>@#?c z5{WMy<@ZR0cKxNuM&H!g3m`2eiqpp(e*SFirPuvqjj?Z*Y*aHJ?;1p#v#)_D-75Ci zMpbm%!gnZ;*xzPO;Y71Z3*?CYlVy!JTQNpOQv;~dSI0MEO<2I$=cXSEU%VO`lX4Wp zyN-b9_0CNYTBo?d9?x}62Lp#r8VvkZ=Y1Q5ZE{YWtNj(kx`Ltk;osxU#cWTqiD(UGL-Jg$#e^`b=-@^IiWLvY8>Ntr%lz~M>q9?#O=j!y1uG|TCi`Q!qJYOIyv;EH z)~Vo}mg-dMjN$FbLO|Y!dGpO8h4>h`NbeyRHdDwx`q0t({BnqKvPpeIH>jCHg&Y?2 z-KCF;bSReSXi^{gP@T|ap<@cOj;foYup))Lhk|}gV19-jF;TK%-+r-%M=H{!`#sv0 zb=6?@sWOlv7${xx5YYGb*Vd~-adHbd-zxc+T`sr7JAbaSU<~B=>LivHhM8N$Bgz8b zZH_O<>c^4YhB*vQd0q;^yooOf=6=AIO)fHNmK+Jlti(#XZtAT-GJ+BNHR;sYyjdtFvr zoaqs9O;^`MvMgy`QSkcY)zvS%R=e!BhPQ$6z9`uXkC%Ga7fcN9iNvh6I>ovPJ=Wjc7w!r~?#JdHqK?kz7EeIU*y>hl%NU%0WMD5(zSiZ+>@b|X z20EaZYC(zdz<8lRw5N2PCi{pgZBdD&OV12)zKc9>ZpM#yS!*0H9bt@99W5xrFn2+# zW`STWb7p?dX+gIAx5Y<{W(3Ouh+g)|!eR$@b(pstAO+n+M%%2?`4p*ZjJX;S3Iph) z9v~@cxM9h(P%TUjTzM-9CaykE|Sv_1OJE{VW& z3_tstsT+D(Xaw#g|FWKl$8=@d7pEyiWIh{q;>D68BSqRN;q^=+fPH6~>t4r(o#k(d z=>j{gpZ9StOyGQ#Ewb;342kF!sRzkCg{LY|w$r+)`GQ$UyNf4WB<0{@6)P+!1+Xo% zUF+)hC+kkLVN|LwAzTLb1Paj(LBMA9Er0#g?+dY3G?6p8j{pY_iazs#99hS+zRq48 zDdynJ$C01cJjc1pmp&zb625n8Lg~ueNb;N~)(R>__6G3{hv3u4USJ)&5f6^bppN?? z4sZAMtKpni5{J&<<}f?8Qiv_~Zar9UA}1u$cD4B%0W^EB9~XppPM}lpOiG|u@>H(= zWINWJE7aX013m?(TtK;rG>iw34ni8dG_XH+Nk+Dg0jFtRcOTZv7B0iZp$&#QNr7B1 zRr$H5^;A}SlDNiF+=F$e3fDDop;^MT+YR1OA4-r1Y1!$aY3$)j+P)kk|Fy$z%8$YT zX1r#}Hds>%G-;c^HW4d^0*Ct4c#>)JDw()pAO({k1D4H+LtBK4)O{5>dXvnD+*yS5 zz0(u27w=9GwV0Ht6vpC(JIxbiWwmS&J0Ob=ksdp-PyHGJ*@G%wBf_|My(W5;(OXB#l3Sz zed#NyfYy(*4=yJAs+mg|^g3Q)QuK^Q8m}cl^I`acX#i~)gPhu-;4Uf~V3 zFCWpz6wf-#*^s|sCwUKXOES{SQy7pl+lM72=jiXe|NLci-JZRQrF6M+a87tX!9)DW zGTalM$2)nynN7LLM@YlPz|%UubL)m$$l@30-j&B3ZRr{8gCE<}LWo~1$9c%@w^mN< zmq40>J(v|^=bYxV)7lCVN=uUy8dqzOTbd2=EEzkaQQ3TBU<)*|9K_u@1V6|>59_ga zl@ZXCVB4Uq4e^RCrqhTE z2hjgyZY<~PwozX#ka2J^ykzsyWwOKf$aGpYj=zv5%W?EIq|_WmC;C7 zI#mWb@hD%27*9zYRpS2qL8d(tG`Jt{#f0pXK$)57SZiFuDO8Xga%MVP$-y61YqJl6 zOP0;Ge->WS3C?_mCDouU7fgO0VEQRMW;!dJ2iXu~Lzh`g%$A)$2+l^pf1Lr>yMi=j zo*5Uk5k%{?AsL{li(o0^PWGcure4fl)Gd*lHo~TwqNcX^qjl>0XNpFtMV&Kh9kY?em)OPKL23uPi%%95 zUFgQQQ%Y`1iU((KXVOa!@=C6LO8O6hS{X$`gXeh_AFO{r8~JWj`WaiL>P zbB&rURG0#J6?hp%SU(9&E^3obSjKyrRQ^Z`AS!kh{_{xT}1tEB$PE zj4L0UoF@))+qEllg`GTCZFrl$q>GyDZvrc?s?+PHY1Rh9Axq0y@;U3SV`OEG%c~8<+oHSch?V0 zCD#oISPfuCy*+v;)O@556A+~Un6@o75j_+`rofYLuiKHKAk_paoy2I<16RP?tu^^; z7_n@~m{%~)$_V(j%YvD2mEnBi$|_@V^%iTS&7GBzOt!V47U>RINtZ8`LypSI+#clG zPjxSAq1{)&6725hr>q_M(09=6({78Uk@en6(1H(I^1!2G5y!^%SaCrCx4tj~nxhmt z2_P09YF)Qirq{5Di2QH*l8RR_3}dla6|aayqKa2~dV0pj#wuP}Sy}zzm7}AhDnqGw z<>TYy>+7rHm1-Lo5)!gx$&x?3`ctCTuV24u)26LkxBe+nDqD#}B9*OF!?==?60unP zXBhX#RtFCrJaXiSY8cni(V-f~scd!e;>EtczAIO*{M%L|BO`x?aT600e{A*k?c0wZ zKYsoCb!KMf&oEBam;O(@dYarFsdnY&?_&cxq)FC)BE?5&BxtR1+3Dt z@^V<$GC9AdHrmTV9S}F}2h=UR>QqZMXUe|)M;k$1r{7C9PYe99p8fddt_ufE+RqM@ z0Vb*?n-ga6Mj6I&_|7Iz&6^Jpnk{$7SK9QC4gfZfpGSLZJ$*pRe(`RZx5f=nMXU!J zZ~y+mb;I7kvLczA?S<+)G5e+yofwkZ4io6aqMFHw0 z26MxqxRwQ`&T4IDY1I4I_8P7sJma67nk_5wnCm@y`(!H~=6GB1mvl|5t3#C_Me;Q8 z?jf&8>b=8~OQ+ixZpz_O6?+gcjUZa_8k$#(12KZ_WS(F^hc)_2yK-QlgsA7DnyYd6 zc|?0(;^T7<0*XyNbu`?YYTiFIGN&^#I{KZWuPjUv&%EkcTdujM{wQzx*+g}%?={z1 zx6jgX`rMF_wtqgPlJ&bX%Dsf1MafTfb}VQTn!0`1Mqk5S*Z2L~IV01CxtjK4nLWDY z?MJ^P6SlsxmJQc#?E|lE{(L7%GQG&c`)9)7sosl=7i8%C_<5u9FP$H7WRbdMN?(Jp z^{CQUxApcF9_@5PE1aqoJK?)Fc6OQxuG72fDABbG(~Z~ldLx50T*svo1n*JexbEq; zw(KG|IdQDiDsagF)-p(jfYhlHnOH4SDnw`Oh=b7792tN%N)&L=M(jf0l!u>L{^3SP zT}nV|HzHo!tCuH28COa7tYQr6S>Y`NVh+|mC_P@oCWx!!28Hn^$ll$==U7IsB(cF^ zXt?cwgM>Avg)Qx_+YXLMDYnWhFpx`x^)V!K*F6yNEV$bCc4dB$~!vZ8DMYWML zt&_Gjv^2hY-Q0AX*PdybXk!aFyKVM`n`d7op6LC6YlKZhSlM-*ZvBE~3&&-`?3;N8 zjC6w_T?Jv5l<;~O9w6L?&=z9cvEB(^11mK;k9RoLhH~vHLOm-*9bhs6zxqOt1%G!R zw6U?-<<;V;2H3KQH{lRITXY_~AGfaAaIV4O3t!*z%UQOO#6IA)-R*4ji1%wdoJF1D z{f(A1UQ?FUwpRsvtjFYRG@S0H-%e9%p=JsQgwizWWOrkVs8Sr&&fn?YbB5r=HYfBGx`zUF1RdD;oMz+aK|wP!nibo;{HcC-gZ}m+Rc!L|H*S($nTjD*3Sttp zP(6XSvPipYM-#{%V|$j0LMxW?4z7;*7QC=%i)VF$n*D}#1@nVBH59ZfDq6 zYbDP64v!ylJomC}o5;Cp1+&%t4ffXREu8)1iYf2+^u=q!Pa4csTdUg{g;_cKQIbzx zrIF08VqmMViB)?v=lwF zv_xx^i&AKv{0>H4Z#@t~1T{+}kO5H`I%f)OSs^UXM`uUUVfXngx^a+IAE!2049X%Mlsh&D2?yCdqm#S_N*=5(=4T&vE8hA=M8>fd+BTDl(YP6&dKGEd#)cQ|=qJPoW<}xuY&o~w`x)MsFIq7_V#lq1?e-Q#_A-FEe50rK z_tr!KznI%Ih3`yR`1kZzo8ZR1v=FM(XW756*|Mfm}u(QU{^CllG>A%#~!0 z4ze}&cMFlKaH6C5o1DhK6gSL<$dml@vk@W!brkJ3B*J@q=2`2A4(tLymJA69iANh3q2^qFDhvUj<^WZ$}!ZQ*Zn5 z`!N0rgtkc>61lUlyZ%Z$ArgVg9(!EvdAVM#I~wC6W7lol^SpCo`4~m{g~*o)4KDJ) z@-Ka8!*|(nW(`QgbPnv3jMQxShB9J(!+R+O+6e;Cs#fdQa zE(FQQcPIPv-|oN#U`Io z5Qr?SZMWcRIX64PfrF%m`{L>-&~?=7-U=M<3|SKNiCM_*Phq^M0Wg3f-W{FSQHw8!z4@Zzc_rI!gf z@%%~jVVW1(fa0hbD-(`y&3a`}UWGQ)(CV_BbNy;GfNt53?4ZW`ec3zBj$#ga z7eusrD$-(}T^KOQ>&LvYPx&&u0oE4Vh48`e_Y;g{>k3kUxAW+xidjJB97Gd)&tJ>> zG~v^7hG$C!V*^v2+`=NsTfMpAuO1*>#h@K=s}BOQ5=4gcAsaC`Y=tEHgO(36aLshp zN^8asb`|)LU4(Zkg;vb;1p=rzb!Q+m)=HAGSPZF3j(@tQ4NG)N0v@vvHs;&dv%_e- zEUs8PDtud-)v`UyY{L=07BUbxgLIRFF6pc06Cn!;=&VefqXf;Rpkq4HT?(2D0Gc?j zmE_!gierVCyYN0}Apoe=+fCOf^9mv%VdVuN+7J#Pmf*v&(c^PS7f8`F(Y#J zt_d?I7N^d@PY$YB5O%)Wb3y9bf+5(GZ|2E_$f;)4iSVN~)8bQRPb1++>1M7HGY^^B zCK>d$4VuG*=G-aU-T~@PTl|nFejn2KIa>a=pd7JI^A}6}oGV5RtAq98*@E?IW9s;C z;&%cu=^LILRnbMPpd1zxdMb2OW48K=Z@phVXS& z;Z(DRYRGs5nq|pAOWBI$!}A%^9D4VXj)3UZQ84O0xGtmUY)$n>Y`Px1wv7*%Mb(x+ z0D>&H8%y(3zd6Mw!i9acsJn)Y-B9%qWGT%nc*!tgiro1?ZXq&{R39XPXv%6W8OZ1~ z+IP4PNL1a@@T3jviEHU=|;EU3_HYa|N+Wz0108EdqVc#h;DJ*D1dtmK+E!3)^iZPjalpI?$@%X_h5v~@O-;@JMBksL z=HTG)2YssT;eVn})znlMqEzUMjEq!eHI@6;tXZSF5T$b8=FOW`?%Te7`ycoHxe)bl z_wCuU=a2gi9XizB-u|EN`_t4^?i(5!`qR`@?i(8$Q#G~!o%{YLO^xqSZ+GSXzpgJ? zK|;en=+jSg^!bgxKUM8t=%ZNu3w^(<+P~0e>HQmhE_%Pw2k1HfM&BO%vF_jIJAaVc z-qT+OP%m7`bH)r@FT*$u-QMJ_dE>sye5&h9wtWx!0o(CORaR5nCuKi>tIBHERpvW$ zL*vc6@2aeJ9cygYFjHgOSGohU?@gktM3#fMJ?c2BLSLov`#f*%W+5!xu0o%Ar!Y#W zPGZ`vI{h1cE@~|X|3aV98r*CCNvqlN-{@1^K53=)8-3|Zy69#9LZ1|vclVI@a_YSv zNv;Zgn+v#9*?*z$hgtq_^byV7cnDb6U4^~_&meV8eYYeP`lKjLhQA7Zx_QN>UOM>q zLSOr5r@Vr>F<|qh)u$bdoriyZ-n!Vt+|4Xw`jEOA5vP?SnrAh zZM1-G{Nf7-M}jmzbe|&+wst4J9XBf1ys`fcoz~;wekFW4_v?jY`D<)t!&|pM{Z_R3 z^X=r8f1z*HncwKM{f)k1&`9?;`gSe1TdT0PlgZ)rpX?(GGLCF?+?P|^E9=*NG+Uk5 zWH=zCJ;~>NlKE+PkMf}+uNgkHk*8!971Aeo*@ae>lw5Us0~LVOTm%A8-9;vV4YR}# zbXn%>0I|BcKv1C;!uKukuGX_)!<#eh7;0Is8#J_;egKLzb2ntc0zU5!nuhcWf%l@mf`@zbx$Pv! z&7Rr^C%^H8cMVxjozM6iqz{Cj^kHu%c_JI`PL;jc1=5w9^VLHgf0MZ`m5m z7Q}!h;7?$`)KKfbv_+%J*a>k!Ch?se^Y|_o?eU!?E=Q46a~p^-!vN4s882POvljuO z&o5Q5q5ieZ6&9Xta(dqBZDs!1wK6Gf^!~{)(U(WI8w$TJ2;1eoYiv&6c?-v^6FJ}U zr~kh2EnjjA`Olm3UxPpL3xKXKx;`_bx3G4y{j^UHkh2+60!#|==i~z!c=P(MB?tv* z9ohG}9wqv7-DTCu2HTCe}lHU;~#jG6m*RUFnkz1m=cFA8s? zMP^Y3KE5R4eC=?WyXr2QncmKw6BVx+QQ$={^DkQJl7l!U_AlmD6dH{C>S}%nVCux@ z#djU>xmtHg)1xA9y&c+M_C`>FeOg?}c-<<4*E5%G6ps3t?nG{_#kR9F_8+j{*+;2mEf)wO_|u&LdHVGH3AP&Q;-2@G|3@7iK5<&C&VXD ziIUT_V8KiFoT=Tg$#piYrxakq6*tn(vSCx=b)3yMSpO&wG9(Id<71+Y$9YJjApvd; zx64Y&+iyQDiwl+B*qL^6za6Cy%@lxoLnYX&Y8;HJR#65e=~Q)VHJ^td$#Bh{Ma))= z?<^10EeUHe{ih8dL==^Qhs_ARUxFC|5O z>12BMVTK+c4eEGxlDF%_;c(Ig~x*4>St?l**ObXLYOo?+IN`^lev3;&?R8s z)f%a`;87=C9Ncx)4aJZlj)>XW>Vx-t4yzxI{uP;QffAADu>IDa{;JDNwh(pJQ$+NdbIP_GafvS%KIvq` zls4JCCc8V@IXtY_G{UjI0X&vA10DM;OZ{;TAzRZ8O{w?chGHVL>jX$o(Pym5%yeXmHJL~5*Wn-DdWG^S>_1}S;Ben)9kj$zjK&Uri8 zhhOgzPE&JPvQU0ObF5Z{XNJ z?9RO&Ao|VTL1V;e;&|p5Np%pV6>NKtT7fi5Y3ZGcV2RX`rC40O%SSe+C^$Na=Q zqZYkiZ=_|eE`7Tu&zt(r^pgx4U~G9Wu#K@yD0zRlbmf*Nfe06}^TKT-fV`YNe(G!8 zxnS0`M{(Bj*4>6L*YE!u?{BM5_o^AnyR~N9{zam02TG%j^c-=^)uo5ZBJMceXvdLO zKAijL(bR=fIu6vZJ$gFwm6`pzglpXUueUCnrsXDMgL&V~lsp&{&f)DS`#cty+7%&> za9zFj*}(;|r$SRc5SZMhboOi#vl=u*fU%q5s#B3Q_jZ{c1be%{JKK<+GSET{;RToPg>1yr6o>X^;83e%T|8qKV{KL{A{ z!0o7pa3FRzh`~oTB@}?JOY!cFUvJ%Mpz@_!+4N^ zC1@nbH4ra~z<@RgBRdN0E{!we=4IvQnK1K^_h2t6@?E2a3kyr^rI zUMx*7e#9$2JEYz_T6~9DEGtmE$SS!)ExA03AF3-k$t_VewVs)hPAPc7s`QYe1Ssw$hi z1e$GwT)4R=L?|x3JX~pNco5oD`@30g&Jm+NgLEF0!9x15A#hDODGKQ@0qU+pmOFVG z)pPXuVpcA2JF>Die|@B?wMh#xFCi25@<=hot_SHP21Dy0!!gK;m*PGjX%Vq2O9;3f zMmq4<_(eII^1{5CfV}|v(hV&hs|pZ6AsL&s5Zre!kQcoX;F1C{bL@9!bC7~MN~Dhr zphs0ch^x^e&fQQSdN;S)SFmxDHPTa&N#_B(gP`R6T7Su|&^D-eNc7OZZu)b2EF0>+ zQs<|7DnP7E3-R(8Ha$V`p?dMt>~S>AV&@tTS32{-Y!>WAgkGcfJb1CznYriJ z#2!2Tp7cU!XAN(T+{#-y|Hc`x3%j@R>%Z!oxS{o4*3}HqoVR3fKJ3ni<_I9OTxi6- z;daly@x%XThy5?{?cdwRKMwQo@K8C7&1U~QzWs67^5x6_I81dD>_7Y4|Jz}zZKJBc z{o7%x{`S9f*njr7|9gksbQ*JSHT$n^qq|zZUz2!_%PU8p&DlA*Du(I7h?3H>GS#?o zV_tPl^lyfh?`!-$ZmexNsA5<{WBWc8!wz+H`q$%+o@vA%IN94mJ<{E$S~s4*oa>C~ zzgCKIx*|{Z*1UdCwQjuqkY_8q-v`=0dZuF7U-w9&$u}y7T>}Y3wR;+`-+ogu>>Acc zXHnP!zTbY1m8ZU)8N08)XuVpRVMALB+AB^YEHaTJ81pWomM2Aq^Rkg@S8Fz6hAT1Z z&~%QG;9lpN{JK7mk@4YYrn8F{YjnOniuLQewFt{oGb&m&AZSLQl4Knz>&kTkH!~6) zkE~y2XiCPkS+Y3=qS(8$Lr+B_1o*@drZ5HnPjBZL)l}NB>s`_lLI^DsG4#+wkJN-N zMFS!tq6S1nM2(7oD7cf*L5&4OMU5R4HDW_WO#l@YH5L$iP*g-6BQ|u#%-QJ7oO#Rl zey6N+e)21e{bR3vJ@seH-9N~)c z7NuC&+PI2twzu3jUcE{1%h0kcUHaxt@`Cunrd9eAvt?O<23Q@IeU56uSHG$^kDTN0 zNY|NhE<8@i-mRDuFte(EQmTBxwl$XsFZg*IDq@SK&2nfpX8oQMrMdbk zEsu@wYuDEGGe?T_{^BqM&R{)en=t|^(ygjEeS)WzHW6ts$^MVrjSB~(W(a&ik*H&> z(Qkd|EXRvGfUz&Bx26XiQ}d#g^`FG$Ngp*K$yb>g9+_S|*g>M#%)SN~R!q4-HVl}( z3ZOS5)60Ad)S0oE5^j&dxC)it1gL<2uOv_|qb1($deupO$-NJdm*4ko-!7$UcIvbG zi0I2a^(0d#bu|fqB_5*C!2KR##e86xKexF?pvK@@edu8QvxACPjv_1SEn(Ja&&?BxE(op@he~HVIW}gg1eiKVemFZv=BvmqV&)rH!rgT;4w#cIQ9XR z`KloBVVetn0&w==P3%+6q5THd1MBybj*$eU=&?(IFjH-GB~b9qrJ)3pXi3%U21ChNq_uFCX{>rV%3(nu-c5nDq8z3P!M6vi5RGY6 zzJKj0e*%4uk#o;kzVH-j zi-&x76xq7dBK1FS+@}5duDG=83GnRh82HdTU>Ux@u@eK`Bu%=5H$GF}?k0|}{>s>8c($*U zy*hMNhItsEJ*&Q$rC79z<2B1Dzj2lS)A-ee53Su6Gu?t+m3VP7IFCle^9T^`sUXAb zW<`_*C3;<|LRsjl_9w9c$UyT5F90NmYO=^@%x>e8nm`>yP;1M2{C;;-G`*RQG3`<~ z1+$^&w&SbbKLaT<1melXGMK@Bkv2mS$?8tSkP03-#@Zu9Rswc-@e4|lR79;1U|k7w zIMZko3@d<{POS}wE4UIvbqvOlv5zxdB{r;)!6tkqWi<|MyWYl*VaJjN93~pos9^?I zM9IqQLL=A2ZkhtO`4t8wIgBM+L{6u{356ebu?K$wSK}YRrB#WgVuRgQqr@e@;q*}L zW|K8Ha^_I{>eFhB6^-Yx1A%GWk7i^67>ahwmK;*=y6~)NcxQC9VF`jgdS@&-L%(eLLm>hTo#Vke6cnwHl=WPIl$j&IKk`OEJJr`1ovEjU;Cz!^Z zH|@n(%eL$1Aj!w~_Z)WTiuhl@O5!d=gH_YpiOwo!2ld0A#8n~^i`Hc=N1*ASoHM4< zXsk{&N#W0*S^ZK>sV5O9zMhP&i!L$CQ8%@C=a4wk9xJpIn5DB|<`fy&YPSPFw&LJo zWlEb-7FX_%C{933vE4@jY~S}P_inZ}#(o8Yc{;{zV!RxDOycd?U-Twr3L<*8L!G;o zqj(`c0<>7A#SVRXP3CG&*{A?a%X}Wm&*{mUD!~u7GBp<@)B)9@gX6t9fH*t%q?IX` zS9;eJrWYVY3#KUhkqKnD+z4x`eoF|UJ^Uz6Jm}cCP;aql{6^4FbQkV;$;WE23xPIGn&~7yeS*9^prp` zpIqt!vmu>CHMGReHp@rDu^wa=?nluo%>0QCi$V+>RAf_@Ptaj;PeWxO-r%ZpS~3>{ zsE{oi-9_3xyF8;g=%_@l&?Acul zfYJch%_IU^TcvzmVS#v~Kqa2>r3X8fGk}ks->1hx?w1vzyV=XLr+qn&p~|@gLEIHx zg`uFGiQxTIAXWWE@8+Q>TmnrpZXW^}Gr?1Fh_~&C3|?_9k1%ZWz#s!TX(@BBb&}u3 zJ>QgCq~#H2!9rxZP^8E0 zKQ`-gVRNATj)hD;FZc*IQ+Ly%mN{m}>=~j5+cjc6TH%S}IOXM{86|XlTl641i zr#l2mv>Nr5SZ!dUt^b1Smke>X;ozxoUx+4rPAXjL)cpFOn7%@Q4GV6kCdp2fxeG8N z?lz6L^rj~Elh&DKS5UsW)Iy=gm}x*ex#=YD*ekaok3FDiZSiAUEzDAYz`iIfXL7JN zWWt4#ZSkH6WXIJFv$6?p2Z*(h-af3C6iPb2z(N&mAzz@`02NHe`pBRcoeM1FpovO6 z27nwj=Do()aa_rlJD>%U8`cMoMa140u)eooFDdLfESaK!{Q(mgYvQk-k)nbpcfr1V zIFVqoP+&E=0tJ}T$&JQLj2~0P%PFAE8z~cxELz+}U65Rk&UOo;sEb<5^Xl`88+D2p z6%W`IB@CUyf{IImimEJ1WnV>`rb5ah*KjH~M3vVu$m{AWcgrgqvWVM8D$DqlI|)@t za@F37s*R0RWq-m_M`TGyBy>X?52tihO%}pzHTaX3a+o!KLb0U=beAnXorQH>47tkS zAhedKg6xrqtMy~t5XgsF8lsrcUt4{bkp^E_6|Q1A%4+)S1Fy{%GlW&ISb1m4v7YE# zuV7V>2D~~4Tk(E%3=?)xV9;`+dISy>LPsyI3D+#VaMG9|UGuvkL})6uQZGSS2&E-; zE39v_7NsQ`QL4{|%r$9`u~5Rvnh$*#!^?pvDFq6rn2*Qw?pUX<4sv;g31mWWWmN#% z@Z0))2LVWlTIxO(;|Qb?n_y|YI7$JnpR&PUx)g<_k|`U)H7f@iG4=6+BnOl08*ArY z+?YOnF2=nbiX~#lp{Oih|B8cl6-yG(uA)FXtEtve0C@`QBBkh`kdva$yb{i@oZ%~V zoiPHPnp3y*-b6P(WG{fEmC2`!H`(zacc8wy$=_E9b7%=1`KH26n|6-d{NL9Vf3Cqy zO-<3dqLr1^eTH)6eAUXJZj1Ce)pQHWtz3>ZdycZ7iZ|FqD{3cLur!`zK;L zb?Vf=Z7lvpOfO%)eD&%Tx(54uWAT3>x$0j$ZWCqI?LU*NKkABqORi94`u~(%(I~xt zC0Apd8{~EBi{~U0^1K8Q0&%HfFXIh2DxMgSshgN8;K@wRjS`dK2Qgi(|AUxbm5r(R zK}_wV#AI!uosgtk@aEyy5aq;)#2NpNn06c-x@BfXC&*D^B1rxqCS-LpL}751;nd>= zr2`snXi1rlnIj))=7o{fcFNb0~O)OumD0cyDFQ40&Vo=kRK~fN1WE)T4M} zcWg4tHt^2H$`vu$GC`n0I7&>c+nKL^5Yzma%Q|i83mv=@6|TRyUU=)^lH{3xX;$a3 zy??CDwi&CB81_88S{f1fJilPUwj;FQv2P=)-cIg58f+JE_1o8DtLN-+Hw!-aE#=|M znGU`Us&Mqgx`0Gx=k|9HG!9u&y0+4NrQ}=Vvnn!YYTt0%vrI370^^&dgb3X=p9C;9 zP&U}1^SwwZ$#V%RljyL5GSdxwWI{29!d3wg33GWgx#HFu2dPy`ybS%dZO4Q3cl8StTU>^K*J;8bSHt=6{lz}&A5TnoiS=34{q7ZSE=5BIY+7NH9ST( zr+#SvhFpw#qn>n_)IBtI|5*#oJ$;wvJzE zcBA@4WzaG8UYZ}uNq=Nm47X8sQgMv@2{(A}^*JhJ*o1I+km?v^n*MH=y;5z<&Z)zE zdF(_e&c2?Kprr@wmIf8S-q$O$b+12+`8ITtrlmhyvR(W6Zs6~C4imwE&R;hxfb&g zJ2K*{&AguKoatNV7QJ>w`UXh1i$M1jFDjkZ`ZP%UaO9%t-kVi94c4SH>`<>f-s%CF zwLwAD1%E&HHKK>Rj0q0qc8fu27m~*K)_Q@8+GfVdr@S)wij7#O#7ht*2N&N;wW4nb z=mH&Lh*)!l3~S7Oj9~yEiSZ6*BO;&ZW2Nd-O!(q1V0go&07e#_tdxMnAVsWB27u`{ z5Pg1{6@q@&VC^)3=Qsq+w9pBSs)5Et2sZTUJ)7t(6p>b&l$vZn^k3w3zCMwQCRehV zR(uh8#Y=I~w+UG5K`t(l4JSFKt@`y1H;pf!xboY2EZPUf@oDg0TV<}{p#D@J+I4$X znx2{s;C&*orl{Y|CX45KSbHy^|5WZCS2jva+*YSPg`2~Ci%v}@HjB%+Wx6M*s`z+|;0$X3!F$7AAJ0OU3>KmTQTzF%rf~bnV-+S&3mO%p>Gc~7XxLhM< zz<2M_+rc~YdyY#C=YL3&fhVnY;4P95&H|_1zj-cU$y^Dy=LaS!plPpD^n=t>di}l} zzFy=&@{w!rjFkeI$KPG%ZuEahiCsWoRqV5;@Ta+(oFuq%vJdaPh%rTg)*2L(7zQ)8 zMXx9NjwsSaSJk)HAt_<}Ehr{I^Ahh``9ClPO7>!OM`};4K0AjHp-NS3s{xFq%+H9B8h7D7;xNZpeR z8)TRrhKH)Rww*EI)EeS6030TJmdQuva)8ZjBe_TqQM4QsDwbEvBs%8fT6dwCbn$e$ zTlT(j)M(A!oFiUg`spT|8X< zZ|TR^slk*52XUVZF%~(9!gj$7L9_<(KiYf5oN2YH987_7Ww$!i?|E@$)p7b$YF;0!rFMWqvALHUzSM=Uypree3T+gN*#|!e?%SN2d0_rlQNv;nGfgoxmlNscxf2 zeX%}0do7wfUA?9Q${1VTZrsa+jdUE(S(3%18W~2f=J?bpLXc11fw@LQ+Q#;??aZr9 zz$l+n`?5+HgyT=9K6<(HnjaLZmEp!ly*@aN59*soU|y9r6Zr==F6y`f%bFs3T-BK6 zm)h03$DRqFdC%i8g|_mfBWQYRlqw9Y5eT?n&VR*Fj+X zrXldoh2J)R&v|v@@GH=&cPFgBunc_h0u%pD+g z)d05(5OGU?C$wp{Sl1DIfRI5VxiXZ*w&?{f+Yb#qw+*30383qqkD486%H^A-Rjo&# z0){)qI;2nfP>G^{VwaK_9i%z>vIV<)WwJr8RIC@K*dGs>E+3x8}1U&npR@e zhOx_JaX0U{gbC0<_MbsJndvRN0B7bTQ-Kz8jOU|F}UP-vRSDVZ#_4w6murXy2SqtVl7%A_uxPQa%QmZB+BI%_49 zH-7gdy=`~O-fGH(QKLGHUzz23ES-Y-@-9?|kxX4aQht_JA?A>alPd}b^D6qv@0_fV zG*+x0saV^pQ^KjN<5$*Y5z6Z;TSkeAR6kO=h*q_81h+f6YL>97ku!c(Yt^hD&}7Gi zGU~wj+K6fv8ZpUA53#UlH*zHivE-wf+QkBilMrG`!7%{*rKftbGe> zB~!9rU09eo8#0rXJsLzuR?x?&H3&L(ldXxN!4AgrB2Pl(6Iqd8!1kBYFg0wB&NePV zbVS;9X&GCcX?ic)oWIsBFPAEv=txX;R)dMGDvl!H(DO-D8E7a4fvIb1lpw9I+EW_1 z?E1`qf^lHYh?hNA3Zhbq^?w=C(I~HO0id@ z*^kFKXwnqNp>s<_zV`yk*49PHVYpU0dwdpKSl2dKMVq>IS<_yx>ai3=4LHxdQBXg-Sa&mw(zaSvne69kPKr znuc?i8+w;*P5N)=Vn3UM|HNN^H3$DGvHFX@{L`Cbdi3c3raAbJHjaNvtj3M%IQ~ei{LsYehmPZ46D!7##45m! z+}t`ES)D~At5fZ0WOeQm8d-I8qmfnDO*FC^Z4U1Gm*$}O&*mWQZ_PoJzy42~g8(`g z`&)A`aI`u25}k|r|GVa3lVY?vxbSby!R1|8EI4+`kHm_6Am@Wt)&ECgB|{Ud3L~qE zp&m4`T5C~NF5{mmn7@W@u(3@Lzv*qYQC!}Jk^7@_u}z!g=v=IEmA+-Iii^(0s!aK# z&B5WN8%F11Z7$&_|7Z^WT5!gobziICXLHc7t|E2oL-M7`N%?M<;G>4>XJ;kn(gTW) znK`sh;=QvlA(^J!zq`FQ;Od+2XK5#YBvu{7>CU5xl|ogjYu$B{X?cA2i3_8N)jeZ> zt(2QmwupeL&F_f%uo;2qc`nsqSlywcEQ*h*c6cg)GXhp*S?T|czX(703%M)dTSF1vqq1l?U(9hmhvq3HHRmFi$3ojVJy4}P3?4P2=f9G>uPua6Yu4wG~Beq)V*?U<+`#}~jPcb#nV;6Rp(OqEedf>l zpl13X=tV%$i>=_E_*oxRPDJa27w53I4)`~!v&v4Bw}naS6pE?$?xXd=FHd}@RgT1D zoc~_@$QLZOb+0*G@+DL!fq;H*64URpWZJH9rF2J*3?`;$E)h*LM)4Eq)Og zE});RBqs`ESlu$rmPR`u5ifF1v&=hs#ux}m(|1NqBCbLno+5#a-?(o3lBy&GA)rAQ zFgH@Z9$R;@2FL+6PpFqzDbfIH&H|FR#++j%3UaKlg>9Jely#SGuJ$|ZZcpG51c1s? z4PY>5%OH++av5FbJO&@79Nw&u7;s$2NY^(Q6sX0t2G?b7!pD*RS8mGMWyMw;@E7Qt zxW?8NFz2%9zvMYmP?x@UE5h00E~@fT;_MhAa@GErUGz`Q=7DInP<>pl%b7*e?5FpA zc09?mTySEinL)bHwgvKT4C%2=8D|O`3%HZV*DGJn=<&8!Gjk4`ZV9=bxBu8Ul%6=s zh#REjqtv=aSCt~PR1OmgoB->rke)*qLHnGzMziUu0yrW+pf99$H*Y--#Sgr0g-o@Tcn`4$nmOU-)qQc*_NIK!$}BO{an4bm8k#&*wDNT0ny6y@{*q8 zn7saWR|2rWdf<2oE$hPxk;{J41g_X{(7167{{dyj6%t&4fL1J_CyVB4{xOz8Q6mJd zrgw7Uo8k$EWmo|)H4Sk_If*N|vU$3)N&uVk6~v&10BWKa&Spj_HVpB0T=J>zQ?^Mo zlbIIrTMW^UmEvll)|tl?q(!NfxFpZS>p?dln*uJm{pf!OJm_J~YQ~VC_{!(IieP7Uf}ihxf**5=D?u&NQga1xl~zG-T)Ow(X=CFD zDeX^6+(CVcud#Z+kdTf%cx|VPF=X(FWz92}d`cqNW-ah5UzBObI3V+$fd%Q~O6FKT zaGo9;q7$TkvAP8ETf>8tK0QYv=Fc3Fp#eOnJH0yB{*SC}@Ufa8Qmus>eAxiQ3 zVG97aJGYZ58x4rvcL-j9W_SAYWZ`xaxGNBvS^VwpH#@g&vBf<6$EXsEfzBjc!8HA# z+PkOScO;&O?wM{c6YqR{cOX1yUREIOki~A^~~vCPgM;Q`N_79}!Qt(zuv!xmc4LX4CPrZ>LV?iglX>k0Se&BpbgP zTn&?!qUMoLcT(838;BVsW%YyS;N#h8RF;~HkCk03c-)J%qk$1qHSbEU16Vt>ZC_zv zgZnrM`?YNA8pOs1V4Q2%6NOcXW~`vdWF!sj`$XR#Ee(?>7?ShPPk&0_Yn z#e@XwJtgxv7+*eWOU&F}n-=;U8o#G3zW{Uh^U~a;`CWJOBvBYY8A!>mIMEw#CkHD| zmIbLnJD^f9Wv0j$8aQ4to{P`CP|o!(i9ng^$wt1?Y+3#l|n6IS&Zn~XBfWAxibQ@wU@imMth<%6b*N+BcfeQ)7B4s60K z$mnBG+0!_4rYl*=WwsUby5KRItSy8@Dj%{0z~0iNkmt}?d5vEe+ALUnqM+s}3^FyK z9(&FcMvcAH`z!~8su`(~iCwM!vj&A13mC+y7=QU1$?TdZQ8Oc!qC8ygM}RGWn%s-! z*PlT}@oOX0@K_mmeD7K+F~wM#;)r&ypQmlknisVZVxC%MEre#xo_VTgs;jL0K=S&^ z@=@q%!_EEJIto22&`W!yKcI&XInXwQ8Nx17$irGO$4N6Uaa^_=7mD9hbY;Ni9v+%) z5050*MMz-|e7w{G#hjl~ZCrHJq^Q^tReo_?A#{wnMJg+6~pPv~e0E$g8o zLUc5hmzVdi=<`#S@mKWpPot@Si#|U`Q$NuMjh;{u;XlbT{_mrwAMEqrM^B6&qbZbq z{xoGUf0#0us42tqhbhAYHDv_;Wy)|GHDx%Vri>u^AEu0;QBwx(4^xIOYRd3S<}7ki zj+!#wv_{q_Fl47ge~hM3Q^x3M>Zd8AeaDZ{6noyqpQEWp>&#J8#+Xd%Ka8eE(dXZe zrkWH#Oc^Np{AtSg6)q=}pr95KTY!$HlI{(C-_h~MXo@>JnsWJbG!epmfWzg@%nQ#_0eUAsC{X?fw!zdp7yKl8E-`!@~0bro-ZpWch6onY>7bq}tWssF}d&hh3JXcVTY9+Mz z=4Y>HcZS3OJcr%^Z0WkE%659bKmn3ap9R-8YJlAoVa`_Y&UZ2u50-0blYT+b2Z`~d zrlRQ6M;}EW(XMLVt<}|Tqv!*n=%WbxnK}^}Tgb5bGm1XfM$zYY&QVa`><9YzqUdw> zl)CuST(h zPK`6v=yFQv)PwOTIJk{!>-@GGbdZiNr@G>@h`>9J1Y>dgnDTL=N+F89n`^~Wr;z$# zii1J`!C;~`YDhQi5_XC1?w}einmVDcZI@<;5~_MOQ;E^{QUe;g5P&IFbB=V7*+Pv! zmg>b_fpcr)U#6az_bQZplhu!=PPs{WpDhzj|i+`i)NwU7KSuvR`1HR0u&{pC^y_dHGW4+FQ3se=ISgXb;=P1cR zkrMKN%s{(QX~d?HU@y$~z1)x+2(8q>Mu0yFE6=vkO6_e*;K<~T;}2-t$jFn@PK^K%D}tZHi5G+`tq4CUtlT;$GuuZf$b7 zb&Y5C5m9#PECcPe{s=FloyZKGzyZfoJf@5q|? zs2yXU^<4CaUWRcsJ@Nh^Z*sph^fGr#_EC3|NLdE)< zA2M)_>n}&|FU7kfAfeb7Bt+>J7-xZ$J2+jFn((}lr?*KnWYE-*G@PxvWT;9HAY>59 za>kK)D4YzZS830%!$nHR#F!1D7sc3sL!-{_=K!SUO&E*aibX?AV4zW2Tj@^1oDG9Ed1&j< zCLMEoWb2j#Y~~o&9W_K+ic{}KR25|%piZ2a@MgRNma&2OTlRwon`yo?Zt9Rc2-6ZU zGDn+kWJ%i)x_ItAc*J2K=TP(({X*oZpa(KQ|Uh@x&oO$FlV77LU1di0^Az{}$yErT6{)m;=*wfZ%B% zs@N705%D(8GaQ-&swZ0w0K3tH3Y0~}qb%}taRf*gBu{V5Av({yfJsGw^XIN?Hpz+r zDCltoCdn8-_?*K2gGCw-db0SQ<{xtyWRyjiLs|+x?3Z-sF(`~Mds0VXM8@@GGV2*p zNyb?DW!mO&3b_IROjQd!&+Wl1_ud7wM98Acn-cCC&1dM2T=X{Bi<$2Ij7{b97Ea?K z`seC?5QraBkpA#QyVbl+ID!n(Ir{WuG{M!$LLtV&f*CPUuI}b4F|DiK5YK3)Cj3^Z zmyf{2r5Eva?1Pz11jFRacRh9-b6#f_WLI!#;o8sOu1bZ)o%vY!`mYi?N3xZ?S3|Gb zle)cSXGiy9XB$ZUVj{OX^2@hQAWQ`Weect^<%CcxVjXn7l_1993zXKuIK zZRLPxyfT3H%$shoUl|vbxNqsr#?n=C%&uQjaX?DH0Y}ygum%ka<=2JXm$A2!UQH{0 zL;}Oq_me6>T<_Z|e9neaXGUXN1e4&RkzuE2LFJg)DCe%#y*z zPvc;NdW8kgYTa6NBWNfyYY2kYNzwc1tS2+E4#-?Xv_D{w2t+4%+^RiS8Eq&7V19z) zj2HvzYh~Q?o4Vq4v!oIO?20GjhDD^dc8R%C6yejZcj+klsr+1q%YIUA8R|>g~!?yEbFGHU&FRe#a`oTq(NrJ+ju~wfBt%2Xn`n~Mt?QInQMo=e~DSnL4#8?r) z1?uAE?hn;iG03|%MJ6`nod0S+g5KRG?|zz(9x(t)!d?^j#h7=$K6$4lg=s*8`upFk zb49~v-xX=joUgmITuBT8B*%9>A^5VCg!{j1-%Zi|?d?m*N(jBoUm2}JpAq!^B%;M@ zk?vW!-I)mLHZbA)Q3^!BND+z=R^`PgM%W`F9W3tNHNjSz zQYgA_B}x_63h+T>=F6@O6eA z{}Wdb2!y``=l>L`xVpOj-N5&sx#DM~4UJS#uK0N!)L)SbDmeeE()O2x@8<}prKRQP z?X+m5g5FO1_ekYmC4B$;mA2>qC}a57O52|XzW*p=_D@<(1RN7qts?tWqkNS2n&Q8;2Jl-}~VU_b=vn$EOa9u`f=zrFiwnrw_l}5*U?} z*}n7DtDQa*2B#&!7hdml$mWhqd-nNiUwrnjd6gmg29G;jpp6OE7v2oKLub8D+r2;L z2Sfy{Y}ti*_WFgzw7EKu&0qCQD%tqX$do+%>DGeXBQwGSS7clml`+iwA!GPy;2Y(N zo2Y^B2UkeBVD2zj83`?%rAoz{(qcVoLTAi(NBbpGu zbv}xa?V3tj<8D|nh#^%*J0gSzaU{HP9jek>7poRdJa8k{n5kQTYlwhrqKia_)@13c zN!wdOCN_1_Xed`OV^FSmcsKMfuIN0h2(seUUw+R%Fv=C9kxFw1=J;u*0&u;~mfPj} z$nQs=GRx)e_tY_{LS+opA0r?|lqcaMZhLU&hS3p_BBlm5HaY^I=tM_AlhuRi(qqqF zcu+@2Kx}t<^MhEtgEK#=O-+6Iccie@o1{Qx46(6TciorbqX$g|sElFhgDzl0o$t}x zz?+8{eBu<=VE6$@j%#&0h_Cn@Mt*fG8fnDcavzm32+SRga|3Q;JaVR^ zNYT)I9sCflgh}&ngmHEq-Ms~ z&=C-O=MNc!?P!`(6j&$1=*Ob>i=K^9pv#TK<_lCeg#vtMz)^8ECTPuVRL0O)b|P|D z2`XbyPo?+F9Gg$RzwmdN?PE8+pw9z;$QUrXy`J@F_1}$!LXQpIz47Gxi2ru&z}?{Y zJUjxvu>i@f78pBP@o)3mza4s}z*E^I{S8xp-7O6c-K{Ipo{7V5S1ChQ&`NL*uM)<$ zI)8ML`dj97lg6{Sp`A=ItFxOjw~_0VA$9Q|*g-z53EhW@uPAS|G^#3CkIEP%ZVixr zOU1$x(}3_YA>_O^%sDv z9@blrc_s^UQ@fi433%l5%r2*I?yL89Dcj2AJoW}DE$O0N;-j zQLWLC#Z(UnJgCMxCTAF|U`yyiaVm%?hEDL!?z-p$TWO_na_)KKR^r4jByNhIJy!L| z!5ma0M%$SZ3gM6mPOW$}BsnFF+PPwKD~LaLnKbUKVqus9B&eFGSh*}K8Zf`rz~eky zWrwYtbm^&(h&>n;I|c%Hw(9}E8ryJSxM45lh1RF`^xNA+@2)MoN9?d7qj`3^oI!eo z@V1Nv$YQz5!1e2VSn{|j3ngMon~x!wWl!|%YB+T4MaiM1uR$a4c4}v@V+)#sc)@kI zq-gZPaRICvH((ok*BzLxv%`ux7|Rp{7I$pJ>(U49HVT%rm@F2G?6NsdHR|ZS@`<6#|AEP z5*XY_2XN~ardp?cIOF0(dj=SGpD?`Q_;&789%x8I;1S!hc`uDyQggX5hOdxJjh|-A zsyEaXfT$?!uq}|E?o3lwPF)1tezxpH zcKa@c*#-jFj^rkf*z046HEEulKxCQgC-CmjV^fGeKq8+&6G!;>^QFBPcAl$I(v$C- zfGY03nOmT{r4oQa$TP4o6vZ2Ffc#3!w`M-7;&?tFc__H8)B6Df!sceDL3?-fCK_Ir z2=CID;CTzObE#>HC42yWX;DiUQts{UM*#WIHB9zS1?DqwONw*?l-*oxa&O4|6(4uk z!c7n>N*QnvfemCbXkr!p>VaHa*Fi3prBJLlP`fgD3Jj|r4DqkBGSvwz3BZz zV`T(tpknQ+_HDa-N09Jwjo@nL(7MRN)ngZ|{MG*{`sfW>ej)Dge|$=L@vL>&yW)vB zHT-+^8U4rRMZs;4;tm!lH=cTbixDsow|3-m(bAqHNY%`hBwq#hW4Sw^>-_t#<5eyPAqB8(*OTiZ^LkD` zK93ojg=Alno!@lew+g^O(L>m~5&>*Mt?bmyf|4rxm@!PkSnKp(En!e34Ow-sPQ;uI0Sz0?;xF zllR;cVgs;o_N5b&V4-`W=kzcRhK$%&>naqcH>h2de}|~^0EL^1hR=N3su2v02+(_M{<0TbP5%KESXDllhIu( VN-uB@0x#iI)bv$Ep$#Yh{{eHl({ca+ literal 0 HcmV?d00001 diff --git a/Breadth-First Search/BreadthFirstSearch.playground/Resources/Minimum_Spanning_Tree.png b/Breadth-First Search/BreadthFirstSearch.playground/Resources/Minimum_Spanning_Tree.png new file mode 100644 index 0000000000000000000000000000000000000000..bce73cc8eaf8a1dd24c8f96269bd2ac127414cf9 GIT binary patch literal 23928 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 T*AjtB9dc7$7xhlnD(rs%aZzvT literal 0 HcmV?d00001 diff --git a/Breadth-First Search/BreadthFirstSearch.playground/Sources/Edge.swift b/Breadth-First Search/BreadthFirstSearch.playground/Sources/Edge.swift new file mode 100644 index 000000000..8f2128ac5 --- /dev/null +++ b/Breadth-First Search/BreadthFirstSearch.playground/Sources/Edge.swift @@ -0,0 +1,7 @@ +public class Edge { + public var neighbor: Node + + public init(neighbor: Node) { + self.neighbor = neighbor + } +} diff --git a/Breadth-First Search/BreadthFirstSearch.playground/Sources/Graph.swift b/Breadth-First Search/BreadthFirstSearch.playground/Sources/Graph.swift new file mode 100644 index 000000000..6792ebf7b --- /dev/null +++ b/Breadth-First Search/BreadthFirstSearch.playground/Sources/Graph.swift @@ -0,0 +1,52 @@ +public class Graph : CustomStringConvertible { + public private(set) var nodes: [Node] + + public init() { + self.nodes = [] + } + + public func addNode(label: String) -> Node { + let node = Node(label: label) + nodes.append(node) + return node + } + + public func addEdge(source: Node, neighbor: Node) { + let edge = Edge(neighbor: neighbor) + edge.neighbor = neighbor + source.neighbors.append(edge) + } + + public var description: String { + var description = "" + + for node in nodes { + if !node.neighbors.isEmpty { + description += "[node: \(node.label) edges: \(node.neighbors.map{ $0.neighbor.label})]" + } + } + return description + } + + public func findNodeWithLabel(label: String) -> Node { + return nodes.filter{ $0.label == label }.first! + } + + public func duplicate() -> Graph { + let duplicated = Graph() + + for node in nodes { + duplicated.addNode(node.label) + } + + for node in nodes { + for edge in node.neighbors { + let source = duplicated.findNodeWithLabel(node.label) + let neighbour = duplicated.findNodeWithLabel(edge.neighbor.label) + duplicated.addEdge(source, neighbor: neighbour) + } + } + + return duplicated + } +} diff --git a/Breadth-First Search/BreadthFirstSearch.playground/Sources/Node.swift b/Breadth-First Search/BreadthFirstSearch.playground/Sources/Node.swift new file mode 100644 index 000000000..4c261ffca --- /dev/null +++ b/Breadth-First Search/BreadthFirstSearch.playground/Sources/Node.swift @@ -0,0 +1,32 @@ +public class Node : CustomStringConvertible, Equatable { + public var neighbors: [Edge] + + public private(set) var label: String + public var distance: Int? + public var visited: Bool + + public init(label: String) { + self.label = label + neighbors = [] + visited = false + } + + public var description: String { + if let distance = distance { + return "Node(label: \(label), distance: \(distance))" + } + return "Node(label: \(label), distance: infinity)" + } + + public var hasDistance: Bool { + return distance != nil + } + + public func remove(edge: Edge) { + neighbors.removeAtIndex(neighbors.indexOf{ $0 === edge }!) + } +} + +public func ==(lhs: Node, rhs: Node) -> Bool { + return lhs.label == rhs.label +} diff --git a/Breadth-First Search/BreadthFirstSearch.playground/Sources/Queue.swift b/Breadth-First Search/BreadthFirstSearch.playground/Sources/Queue.swift new file mode 100644 index 000000000..bf462bbdd --- /dev/null +++ b/Breadth-First Search/BreadthFirstSearch.playground/Sources/Queue.swift @@ -0,0 +1,31 @@ +public struct Queue { + private var array: [T] + + public init() { + array = [] + } + + public var isEmpty: Bool { + return array.isEmpty + } + + public var count: Int { + return array.count + } + + public mutating func enqueue(element: T) { + array.append(element) + } + + public mutating func dequeue() -> T? { + if isEmpty { + return nil + } else { + return array.removeFirst() + } + } + + public func peek() -> T? { + return array.first + } +} diff --git a/Breadth-First Search/BreadthFirstSearch.playground/contents.xcplayground b/Breadth-First Search/BreadthFirstSearch.playground/contents.xcplayground index 5da2641c9..fc13b7766 100644 --- a/Breadth-First Search/BreadthFirstSearch.playground/contents.xcplayground +++ b/Breadth-First Search/BreadthFirstSearch.playground/contents.xcplayground @@ -1,4 +1,8 @@ - - + + + + + + \ No newline at end of file diff --git a/Breadth-First Search/README.markdown b/Breadth-First Search/README.markdown index 41ef739b8..d71cca15c 100644 --- a/Breadth-First Search/README.markdown +++ b/Breadth-First Search/README.markdown @@ -59,12 +59,12 @@ Simple implementation of breadth-first search using a queue: ```swift func breadthFirstSearch(graph: Graph, source: Node) { - print("Performing breadth-first search on '\(source.label)'") - var seenNodes = [source] var queue = Queue() queue.enqueue(source) + print(source.label) + while !queue.isEmpty { let current = queue.dequeue()! for edge in current.neighbors { @@ -100,7 +100,7 @@ graph.addEdge(nodeC, neighbor: nodeF) graph.addEdge(nodeC, neighbor: nodeG) graph.addEdge(nodeE, neighbor: nodeH) -breadthFirstSearch(graph, source: nodeA) // This will output: Performing breadth-first search on 'a', b, c, d, e, f, g, h +breadthFirstSearch(graph, source: nodeA) // This will output: a, b, c, d, e, f, g, h ``` ## Applications From 0ad6cca09442b693d39b62f3e309a95e14e7c8fd Mon Sep 17 00:00:00 2001 From: Jeroen Houtzager Date: Sun, 28 Feb 2016 11:39:49 +0100 Subject: [PATCH 0058/1679] Add B-tree paragraph placeholder, --- B Tree/README.markdown | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 B Tree/README.markdown diff --git a/B Tree/README.markdown b/B Tree/README.markdown new file mode 100644 index 000000000..a96d59be2 --- /dev/null +++ b/B Tree/README.markdown @@ -0,0 +1,8 @@ +# B Tree + +Under Construction. + +See also [Wikipedia](https://en.wikipedia.org/wiki/B-tree). + +*Written by Jeroen Houtzager* + From ab15e38562c8607382bddcaa16a41460ad69054a Mon Sep 17 00:00:00 2001 From: Matthijs Hollemans Date: Sun, 28 Feb 2016 12:38:05 +0100 Subject: [PATCH 0059/1679] Add optimized version of Queue --- Queue/Queue-Optimized.swift | 47 ++++++ Queue/{Queue.swift => Queue-Simple.swift} | 10 +- Queue/Queue.playground/Contents.swift | 21 +-- Queue/README.markdown | 187 +++++++++++++++++++++- 4 files changed, 245 insertions(+), 20 deletions(-) create mode 100644 Queue/Queue-Optimized.swift rename Queue/{Queue.swift => Queue-Simple.swift} (96%) diff --git a/Queue/Queue-Optimized.swift b/Queue/Queue-Optimized.swift new file mode 100644 index 000000000..efc573442 --- /dev/null +++ b/Queue/Queue-Optimized.swift @@ -0,0 +1,47 @@ +/* + First-in first-out queue (FIFO) + + New elements are added to the end of the queue. Dequeuing pulls elements from + the front of the queue. + + Enqueuing and dequeuing are O(1) operations. +*/ +public struct Queue { + private var array = [T?]() + private var head = 0 + + public var isEmpty: Bool { + return count == 0 + } + + public var count: Int { + return array.count - head + } + + public mutating func enqueue(element: T) { + array.append(element) + } + + public mutating func dequeue() -> T? { + guard head < array.count, let element = array[head] else { return nil } + + array[head] = nil + head += 1 + + let percentage = Double(head)/Double(array.count) + if array.count > 50 && percentage > 0.25 { + array.removeFirst(head) + head = 0 + } + + return element + } + + public func peek() -> T? { + if isEmpty { + return nil + } else { + return array[head] + } + } +} diff --git a/Queue/Queue.swift b/Queue/Queue-Simple.swift similarity index 96% rename from Queue/Queue.swift rename to Queue/Queue-Simple.swift index 70830df7a..6d3c197ee 100644 --- a/Queue/Queue.swift +++ b/Queue/Queue-Simple.swift @@ -8,16 +8,16 @@ implemented with a linked list, then both would be O(1). */ public struct Queue { - var array = [T]() - - public var isEmpty: Bool { - return array.isEmpty - } + private var array = [T]() public var count: Int { return array.count } + public var isEmpty: Bool { + return array.isEmpty + } + public mutating func enqueue(element: T) { array.append(element) } diff --git a/Queue/Queue.playground/Contents.swift b/Queue/Queue.playground/Contents.swift index 8289c46ac..da556d156 100644 --- a/Queue/Queue.playground/Contents.swift +++ b/Queue/Queue.playground/Contents.swift @@ -13,32 +13,35 @@ public struct Queue { private var array = [T]() - - public var count: Int { - return array.count - } - + public var isEmpty: Bool { return array.isEmpty } - + + public var count: Int { + return array.count + } + public mutating func enqueue(element: T) { array.append(element) } - + public mutating func dequeue() -> T? { - if count == 0 { + if isEmpty { return nil } else { return array.removeFirst() } } - + public func peek() -> T? { return array.first } } + + + // Create a queue and put some elements on it already. var queueOfNames = Queue(array: ["Carl", "Lisa", "Stephanie", "Jeff", "Wade"]) diff --git a/Queue/README.markdown b/Queue/README.markdown index 7b90daa9a..70a6a76eb 100644 --- a/Queue/README.markdown +++ b/Queue/README.markdown @@ -40,12 +40,14 @@ This returns `3`, the next dequeue returns `57`, and so on. If the queue is empt > **Note:** A queue is not always the best choice. If the order in which the items are added and removed from the list isn't important, you might as well use a [stack](../Stack/) instead of a queue. Stacks are simpler and faster. +## The code + Here is a very simplistic implementation of a queue in Swift. It's just a wrapper around an array that lets you enqueue, dequeue, and peek at the front-most item: ```swift public struct Queue { - var array = [T]() - + private var array = [T]() + public var isEmpty: Bool { return array.isEmpty } @@ -53,7 +55,7 @@ public struct Queue { public var count: Int { return array.count } - + public mutating func enqueue(element: T) { array.append(element) } @@ -76,10 +78,183 @@ This queue works just fine but it is not optimal. Enqueuing is an **O(1)** operation because adding to the end of an array always takes the same amount of time, regardless of the size of the array. So that's great. -However, to dequeue we remove the element from the beginning of the array. This is an **O(n)** operation because it requires all remaining array elements to be shifted in memory. +You might be wondering why appending items to an array is **O(1)**, or a constant-time operation. That is so because an array in Swift always has some empty space at the end. If we do the following: + +```swift +var queue = Queue() +queue.enqueue("Ada") +queue.enqueue("Steve") +queue.enqueue("Tim") +``` + +then the array might actually look like this: + + [ "Ada", "Steve", "Tim", xxx, xxx, xxx ] + +where `xxx` is memory that is reserved but not filled in yet. Adding a new element to the array overwrites the next unused spot: + + [ "Ada", "Steve", "Tim", "Grace", xxx, xxx ] + +This is simply matter of copying memory from one place to another, a constant-time operation. + +Of course, there are only a limited number of such unused spots at the end of the array. When the last `xxx` gets used and you want to add another item, the array needs to resize to make more room. Resizing includes allocating new memory and copying all the existing data over to the new array. This is an **O(n)** process, so relatively slow. But since it happens only every so often, the time for appending a new element to the end of the array is still **O(1)** on average, or **O(1)** "amortized". + +The story for dequeueing is slightly different. To dequeue we remove the element from the *beginning* of the array, not the end. This is always an **O(n)** operation because it requires all remaining array elements to be shifted in memory. + +In our example, dequeuing the first element `"Ada"` copies `"Steve"` in the place of `"Ada"`, `"Tim"` in the place of `"Steve"`, and `"Grace"` in the place of `"Tim"`: + + before [ "Ada", "Steve", "Tim", "Grace", xxx, xxx ] + / / / + / / / + / / / + / / / + after [ "Steve", "Tim", "Grace", xxx, xxx, xxx ] + +Moving all these elements in memory is always an **O(n)** operation. So with our simple implementation of a queue, enqueuing is efficient but dequeueing leaves something to be desired... + +## A more efficient queue + +To make dequeuing more efficient, we can use the same trick of reserving some extra free space, but this time do it at the front of the array. We're going to have to write this code ourselves as the built-in Swift array doesn't support this out of the box. + +The idea is this: whenever we dequeue an item, we don't shift the contents of the array to the front (slow) but mark the item's position in the array as empty (fast). After dequeuing `"Ada"`, the array is: + + [ xxx, "Steve", "Tim", "Grace", xxx, xxx ] + +After dequeuing `"Steve"`, the array is: + + [ xxx, xxx, "Tim", "Grace", xxx, xxx ] + +These empty spots at the front never get reused for anything, so they're wasting space. Every so often you can trim the array by moving the remaining elements to the front again: + + [ "Tim", "Grace", xxx, xxx, xxx, xxx ] + +This trimming procedure involves shifting memory so it's an **O(n)** operation. But because it only happens once in a while, dequeuing is now **O(1)** on average. + +Here is how you could implement this version of `Queue`: + +```swift +public struct Queue { + private var array = [T?]() + private var head = 0 + + public var isEmpty: Bool { + return count == 0 + } + + public var count: Int { + return array.count - head + } + + public mutating func enqueue(element: T) { + array.append(element) + } + + public mutating func dequeue() -> T? { + guard head < array.count, let element = array[head] else { return nil } + + array[head] = nil + head += 1 + + let percentage = Double(head)/Double(array.count) + if head > 20 && percentage > 0.25 { + array.removeFirst(head) + head = 0 + } + + return element + } + + public func peek() -> T? { + if isEmpty { + return nil + } else { + return array[head] + } + } +} +``` + +The array now stores objects of type `T?` instead of just `T` because we need some way to mark array elements as being empty. The `head` variable is the index in the array of the front-most object. + +Most of the new functionality sits in `dequeue()`. When we dequeue an item, we first set `array[head]` to `nil` to remove the object from the array. Then we increment `head` because now the next item has become the front one. + +We go from this: + + [ "Ada", "Steve", "Tim", "Grace", xxx, xxx ] + head + +to this: + + [ xxx, "Steve", "Tim", "Grace", xxx, xxx ] + head + +It's like some weird supermarket where the people in the checkout lane don't shuffle forward towards the cash register, but the cash register moves up the queue. + +Of course, if we never remove those empty spots at the front then the array will keep growing as we enqueue and dequeue elements. To periodically trim down the array, we do the following: + +```swift + let percentage = Double(head)/Double(array.count) + if array.count > 50 && percentage > 0.25 { + array.removeFirst(head) + head = 0 + } +``` + +This calculates the percentage of empty spots at the beginning as a ratio of the total array size. If more than 25% of the array is unused, we chop off that wasted space. However, if the array is small we don't want to resize it all the time, so there must be at least 50 elements in the array before we try to trim it. + +> **Note:** I just pulled these numbers out of thin air -- you may need to tweak them based on the behavior of your app in a production environment. + +To test this in a playground, do: + +```swift +var q = Queue() +q.array // [] empty array + +q.enqueue("Ada") +q.enqueue("Steve") +q.enqueue("Tim") +q.array // [{Some "Ada"}, {Some "Steve"}, {Some "Tim"}] +q.count // 3 + +q.dequeue() // "Ada" +q.array // [nil, {Some "Steve"}, {Some "Tim"}] +q.count // 2 + +q.dequeue() // "Steve" +q.array // [nil, nil, {Some "Tim"}] +q.count // 1 + +q.enqueue("Grace") +q.array // [nil, nil, {Some "Tim"}, {Some "Grace"}] +q.count // 2 +``` + +To test the trimming behavior, replace the line + +```swift + if array.count > 50 && percentage > 0.25 { +``` + +with: + +```swift + if head > 2 { +``` + +Now if you dequeue another object, the array will look as follows: + +```swift +q.dequeue() // "Tim" +q.array // [{Some "Grace"}] +q.count // 1 +``` + +The `nil` objects at the front have been removed and the array is no longer wasting space. This new version of `Queue` isn't much more complicated than the first one but dequeuing is now also an **O(1)** operation, just because we were a bit smarter about how we used the array. + +## See also -More efficient implementations would use a linked list, a [circular buffer](../Ring Buffer/), or a [heap](../Heap/). (I might add an example of this later.) +There are many other ways to create a queue. Alternative implementations use a [linked list](../Linked List/), a [circular buffer](../Ring Buffer/), or a [heap](../Heap/). Variations on this theme are [deque](../Deque/), a double-ended queue where you can enqueue and dequeue at both ends, and [priority queue](../Priority Queue/), a sorted queue where the "most important" item is always at the front. -*Written by Matthijs Hollemans* +*Written for Swift Algorithm Club by Matthijs Hollemans* From 16e4285f85663d27bf2b786f89d799d10a3299ac Mon Sep 17 00:00:00 2001 From: Matthijs Hollemans Date: Sun, 28 Feb 2016 15:28:44 +0100 Subject: [PATCH 0060/1679] Add optimized version of Deque --- Deque/Deque-Optimized.swift | 77 ++++++++ Deque/{Deque.swift => Deque-Simple.swift} | 0 Deque/README.markdown | 229 +++++++++++++++++++++- 3 files changed, 304 insertions(+), 2 deletions(-) create mode 100644 Deque/Deque-Optimized.swift rename Deque/{Deque.swift => Deque-Simple.swift} (100%) diff --git a/Deque/Deque-Optimized.swift b/Deque/Deque-Optimized.swift new file mode 100644 index 000000000..e78942543 --- /dev/null +++ b/Deque/Deque-Optimized.swift @@ -0,0 +1,77 @@ +/* + Deque (pronounced "deck"), a double-ended queue + + All enqueuing and dequeuing operations are O(1). +*/ +public struct Deque { + private var array: [T?] + private var head: Int + private var capacity: Int + + public init(capacity: Int = 10) { + self.capacity = max(capacity, 1) + array = .init(count: capacity, repeatedValue: nil) + head = capacity + } + + public var isEmpty: Bool { + return count == 0 + } + + public var count: Int { + return array.count - head + } + + public mutating func enqueue(element: T) { + array.append(element) + } + + public mutating func enqueueFront(element: T) { + if head == 0 { + capacity *= 2 + let emptySpace = [T?](count: capacity, repeatedValue: nil) + array.insertContentsOf(emptySpace, at: 0) + head = capacity + } + + head -= 1 + array[head] = element + } + + public mutating func dequeue() -> T? { + guard head < array.count, let element = array[head] else { return nil } + + array[head] = nil + head += 1 + + if capacity > 10 && head >= capacity*2 { + array.removeFirst(capacity) + head -= capacity + } + return element + } + + public mutating func dequeueBack() -> T? { + if isEmpty { + return nil + } else { + return array.removeLast() + } + } + + public func peekFront() -> T? { + if isEmpty { + return nil + } else { + return array[head] + } + } + + public func peekBack() -> T? { + if isEmpty { + return nil + } else { + return array.last! + } + } +} diff --git a/Deque/Deque.swift b/Deque/Deque-Simple.swift similarity index 100% rename from Deque/Deque.swift rename to Deque/Deque-Simple.swift diff --git a/Deque/README.markdown b/Deque/README.markdown index 8ccaf8361..a4889f546 100644 --- a/Deque/README.markdown +++ b/Deque/README.markdown @@ -2,7 +2,7 @@ A double-ended queue. For some reason this is pronounced as "deck". -A regular [queue](../Queue/) adds new elements to the back and dequeues from the front. The deque also allows enqueuing at the front and dequeuing from the back, and peeking at both ends. +A regular [queue](../Queue/) adds new elements to the back and removes from the front. The deque also allows enqueuing at the front and dequeuing from the back, and peeking at both ends. Here is a very basic implementation of a deque in Swift: @@ -71,7 +71,232 @@ deque.dequeue() // 5 ``` This particular implementation of `Deque` is simple but not very efficient. Several operations are **O(n)**, notably `enqueueFront()` and `dequeue()`. I've included it only to show the principle of what a deque does. + +## A more efficient version + +The reason that `dequeue()` and `enqueueFront()` are **O(n)** is that they work on the front of the array. If you remove an element at the front of an array, what happens is that all the remaining elements need to be shifted in memory. + +Let's say the deque's array contains the following items: + + [ 1, 2, 3, 4 ] + +Then `dequeue()` will remove `1` from the array and the elements `2`, `3`, and `4`, are shifted one position to the front: + + [ 2, 3, 4 ] + +This is an **O(n)** operation because all array elements need to be moved by one position in the computer's memory. + +Likewise, inserting an element at the front of the array is expensive because it requires that all other elements must be shifted one position to the back. So `enqueueFront(5)` will change the array to be: + + [ 5, 2, 3, 4 ] + +First, the elements `2`, `3`, and `4`, are move up by one position in the computer's memory, and then the new element `5` is inserted at the position where `2` used to be. + +Why is this not an issue at for `enqueue()` and `dequeueBack()`? Well, these operations are performed at the end of the array. The way resizable arrays are implemented in Swift is by reserving a certain amount of free space at the back. + +Our initial array `[ 1, 2, 3, 4]` actually looks like this in memory: + + [ 1, 2, 3, 4, x, x, x ] + +where the `x`s denote additional positions in the array that are not being used yet. Calling `enqueue(6)` simply copies the new item into the next unused spot: + + [ 1, 2, 3, 4, 6, x, x ] + +And `dequeueBack()` uses `array.removeLast()` to read that item and decrement `array.count` by one. There is no shifting of memory involved here. So operations at the back of the array are fast, **O(1)**. + +It is possible the array runs out of free spots at the back. In that case, Swift will allocate a new, larger array and copy over all the data. This is an **O(n)** operation but because it only happens once in a while, adding new elements at the end of an array is still **O(1)** on average. + +Of course, we can use this same trick at the *beginning* of the array. That will make our deque efficient too for operations at the front of the queue. Our array will look like this: + + [ x, x, x, 1, 2, 3, 4, x, x, x ] + +There is now a chunk of free space at the start of the array, which allows adding or removing elements at the front of the queue to be **O(1)** as well. + +Here is the new version of `Deque`: + +```swift +public struct Deque { + private var array: [T?] + private var head: Int + private var capacity: Int + + public init(capacity: Int = 10) { + self.capacity = max(capacity, 1) + array = .init(count: capacity, repeatedValue: nil) + head = capacity + } + + public var isEmpty: Bool { + return count == 0 + } + + public var count: Int { + return array.count - head + } + + public mutating func enqueue(element: T) { + array.append(element) + } -A more efficient implementation would use a [doubly linked list](../Linked List/), a [circular buffer](../Ring Buffer/), or two [stacks](../Stack/) facing opposite directions. + public mutating func enqueueFront(element: T) { + // this is explained below + } + + public mutating func dequeue() -> T? { + // this is explained below + } + + public mutating func dequeueBack() -> T? { + if isEmpty { + return nil + } else { + return array.removeLast() + } + } + + public func peekFront() -> T? { + if isEmpty { + return nil + } else { + return array[head] + } + } + + public func peekBack() -> T? { + if isEmpty { + return nil + } else { + return array.last! + } + } +} +``` + +It still largely looks the same -- `enqueue()` and `dequeueBack()` haven't changed -- but there are also a few important differences. The array now stores objects of type `T?` instead of just `T` because we need some way to mark array elements as being empty. + +The `init` method allocates a new array that contains a certain number of `nil` values. This is the free room we have to work with at the beginning of the array. By default this creates 10 empty spots. + +The `head` variable is the index in the array of the front-most object. Since the queue is currently empty, `head` points at an index beyond the end of the array. + + [ x, x, x, x, x, x, x, x, x, x ] + | + head + +To enqueue an object at the front, we move `head` one position to the left and then copy the new object into the array at index `head`. For example, `enqueueFront(5)` gives: + + [ x, x, x, x, x, x, x, x, x, 5 ] + | + head + +Followed by `enqueueFront(7)`: + + [ x, x, x, x, x, x, x, x, 7, 5 ] + | + head + +And so on... the `head` keeps moving to the left and always points at the first item in the queue. `enqueueFront()` is now **O(1)** because it only involves copying a value into the array, a constant-time operation. + +Here is the code: + +```swift + public mutating func enqueueFront(element: T) { + head -= 1 + array[head] = element + } +``` + +Appending to the back of the queue has not changed (it's the exact same code as before). For example, `enqueue(1)` gives: + + [ x, x, x, x, x, x, x, x, 7, 5, 1, x, x, x, x, x, x, x, x, x ] + | + head + +Notice how the array has resized itself. There was no room to add the `1`, so Swift decided to make the array larger and add a number of empty spots to the end. If you enqueue another object, it gets added to the next empty spot in the back. For example, `enqueue(2)`: + + [ x, x, x, x, x, x, x, x, 7, 5, 1, 2, x, x, x, x, x, x, x, x ] + | + head + +> **Note:** You won't see those empty spots at the back when you `print(deque.array)`. This is because Swift hides them from you. Only the ones at the front of the array show up. + +The `dequeue()` method does the opposite of `enqueueFront()`, it reads the value at `head`, sets the array element back to `nil`, and then moves `head` one position to the right: + +```swift + public mutating func dequeue() -> T? { + guard head < array.count, let element = array[head] else { return nil } + + array[head] = nil + head += 1 + + return element + } +``` + +There is one tiny problem... If you enqueue a lot of objects at the front, you're going to run out of empty spots at the front at some point. When this happens at the back of the array, Swift automatically resizes it. But at the front of the array we have to handle this ourselves with some extra logic in `enqueueFront()`: + +```swift + public mutating func enqueueFront(element: T) { + if head == 0 { + capacity *= 2 + let emptySpace = [T?](count: capacity, repeatedValue: nil) + array.insertContentsOf(emptySpace, at: 0) + head = capacity + } + + head -= 1 + array[head] = element + } +``` + +If `head` equals 0, there is no room left at the front. When that happens, we add a whole bunch of new `nil` elements to the array. This is an **O(n)** operation but since this cost gets divided over all the `enqueueFront()`s, each individual call to `enqueueFront()` is still **O(1)** on average. + +> **Note:** We also multiply the capacity by 2 each time this happens, so if your queue grows bigger and bigger, the resizing happens less often. This is also what Swift arrays automatically do at the back. + +We have to do something similar for `dequeue()`. If you mostly enqueue a lot of elements at the back and mostly dequeue from the front, then you may end up with an array that looks like this: + + [ x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, 1, 2, 3 ] + | + head + +Those empty spots at the front only get used when you use `enqueueFront()`. But if enqueuing objects at the front happens only rarely, this leaves a lot of wasted space. So let's add some code to `dequeue()` to clean this up: + +```swift + public mutating func dequeue() -> T? { + guard head < array.count, let element = array[head] else { return nil } + + array[head] = nil + head += 1 + + if capacity > 10 && head >= capacity*2 { + array.removeFirst(capacity) + head -= capacity + } + return element + } +``` + +Recall that `capacity` is the original number of empty places at the front of the queue. If the `head` has advanced more to the right than twice the capacity, then it's time to trim off half of these empty spots. + +For example, this: + + [ x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, 1, 2, 3 ] + | | + capacity head + +becomes this after trimming: + + [ x, x, x, x, x, x, x, x, x, 1, 2, 3 ] + | + head + +This way we can strike a balance between fast enqueuing and dequeuing at the front and keeping the memory requirements reasonable. + +> **Note:** We don't perform this trimming on very small arrays. It's not worth it for saving just a few bytes of memory. + +## See also + +Other ways to implement deque are by using a [doubly linked list](../Linked List/), a [circular buffer](../Ring Buffer/), or two [stacks](../Stack/) facing opposite directions. + +[A fully-featured deque implementation in Swift](https://github.com/lorentey/Deque) *Written for Swift Algorithm Club by Matthijs Hollemans* From fcedd45411e7e5c7ee0a68ec9c25103b2a8a994c Mon Sep 17 00:00:00 2001 From: Matthijs Hollemans Date: Sun, 28 Feb 2016 16:55:03 +0100 Subject: [PATCH 0061/1679] Also reduce capacity on dequeue --- Deque/Deque-Optimized.swift | 6 ++++-- Deque/README.markdown | 25 ++++++++++++++----------- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/Deque/Deque-Optimized.swift b/Deque/Deque-Optimized.swift index e78942543..3b0d724dd 100644 --- a/Deque/Deque-Optimized.swift +++ b/Deque/Deque-Optimized.swift @@ -45,8 +45,10 @@ public struct Deque { head += 1 if capacity > 10 && head >= capacity*2 { - array.removeFirst(capacity) - head -= capacity + let amountToRemove = capacity + capacity/2 + array.removeFirst(amountToRemove) + head -= amountToRemove + capacity /= 2 } return element } diff --git a/Deque/README.markdown b/Deque/README.markdown index a4889f546..87b5d2791 100644 --- a/Deque/README.markdown +++ b/Deque/README.markdown @@ -254,11 +254,11 @@ If `head` equals 0, there is no room left at the front. When that happens, we ad We have to do something similar for `dequeue()`. If you mostly enqueue a lot of elements at the back and mostly dequeue from the front, then you may end up with an array that looks like this: - [ x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, 1, 2, 3 ] + [ x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, 1, 2, 3 ] | head -Those empty spots at the front only get used when you use `enqueueFront()`. But if enqueuing objects at the front happens only rarely, this leaves a lot of wasted space. So let's add some code to `dequeue()` to clean this up: +Those empty spots at the front only get used when you call `enqueueFront()`. But if enqueuing objects at the front happens only rarely, this leaves a lot of wasted space. So let's add some code to `dequeue()` to clean this up: ```swift public mutating func dequeue() -> T? { @@ -268,26 +268,29 @@ Those empty spots at the front only get used when you use `enqueueFront()`. But head += 1 if capacity > 10 && head >= capacity*2 { - array.removeFirst(capacity) - head -= capacity + let amountToRemove = capacity + capacity/2 + array.removeFirst(amountToRemove) + head -= amountToRemove + capacity /= 2 } return element } ``` -Recall that `capacity` is the original number of empty places at the front of the queue. If the `head` has advanced more to the right than twice the capacity, then it's time to trim off half of these empty spots. +Recall that `capacity` is the original number of empty places at the front of the queue. If the `head` has advanced more to the right than twice the capacity, then it's time to trim off a bunch of these empty spots. We reduce it to about 25%. For example, this: - [ x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, 1, 2, 3 ] - | | - capacity head + [ x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, 1, 2, 3 ] + | | + capacity head becomes this after trimming: - [ x, x, x, x, x, x, x, x, x, 1, 2, 3 ] - | - head + [ x, x, x, x, x, 1, 2, 3 ] + | + head + capacity This way we can strike a balance between fast enqueuing and dequeuing at the front and keeping the memory requirements reasonable. From 111469cd4f6ba87793fe4bf444d92db3b1ac946c Mon Sep 17 00:00:00 2001 From: Matthijs Hollemans Date: Sun, 28 Feb 2016 17:58:36 +0100 Subject: [PATCH 0062/1679] Fix path to file in test project --- Queue/Tests/Tests.xcodeproj/project.pbxproj | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Queue/Tests/Tests.xcodeproj/project.pbxproj b/Queue/Tests/Tests.xcodeproj/project.pbxproj index 83e3fc523..ac23063a5 100644 --- a/Queue/Tests/Tests.xcodeproj/project.pbxproj +++ b/Queue/Tests/Tests.xcodeproj/project.pbxproj @@ -7,14 +7,14 @@ objects = { /* Begin PBXBuildFile section */ - 7B80C4021C77A6BF003CECC7 /* Queue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C4011C77A6BF003CECC7 /* Queue.swift */; }; + 7B80C4021C77A6BF003CECC7 /* Queue-Optimized.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C4011C77A6BF003CECC7 /* Queue-Optimized.swift */; }; 7B80C4041C77A6C5003CECC7 /* QueueTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C4031C77A6C5003CECC7 /* QueueTests.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ 7B2BBC801C779D720067B71D /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 7B2BBC941C779E7B0067B71D /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; - 7B80C4011C77A6BF003CECC7 /* Queue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Queue.swift; path = ../Queue.swift; sourceTree = SOURCE_ROOT; }; + 7B80C4011C77A6BF003CECC7 /* Queue-Optimized.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "Queue-Optimized.swift"; path = "../Queue-Optimized.swift"; sourceTree = SOURCE_ROOT; }; 7B80C4031C77A6C5003CECC7 /* QueueTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QueueTests.swift; sourceTree = SOURCE_ROOT; }; /* End PBXFileReference section */ @@ -48,7 +48,7 @@ 7B2BBC831C779D720067B71D /* Tests */ = { isa = PBXGroup; children = ( - 7B80C4011C77A6BF003CECC7 /* Queue.swift */, + 7B80C4011C77A6BF003CECC7 /* Queue-Optimized.swift */, 7B80C4031C77A6C5003CECC7 /* QueueTests.swift */, 7B2BBC941C779E7B0067B71D /* Info.plist */, ); @@ -124,7 +124,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 7B80C4021C77A6BF003CECC7 /* Queue.swift in Sources */, + 7B80C4021C77A6BF003CECC7 /* Queue-Optimized.swift in Sources */, 7B80C4041C77A6C5003CECC7 /* QueueTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; From 084b7566db311dfe111bb1590a6364c1c5808505 Mon Sep 17 00:00:00 2001 From: John Gill Date: Sun, 28 Feb 2016 14:41:43 -0800 Subject: [PATCH 0063/1679] Write README for K-Means Algorithm --- K-Means/Images/k_means_bad1.png | Bin 0 -> 16294 bytes K-Means/Images/k_means_bad2.png | Bin 0 -> 15826 bytes K-Means/Images/k_means_good.png | Bin 0 -> 15983 bytes K-Means/README.md | 82 +++++++++++++++++++++++++++++++- README.markdown | 5 +- 5 files changed, 85 insertions(+), 2 deletions(-) create mode 100644 K-Means/Images/k_means_bad1.png create mode 100644 K-Means/Images/k_means_bad2.png create mode 100644 K-Means/Images/k_means_good.png diff --git a/K-Means/Images/k_means_bad1.png b/K-Means/Images/k_means_bad1.png new file mode 100644 index 0000000000000000000000000000000000000000..55df0e7eedb8e60921a9c84c2ea0718fc77e3e99 GIT binary patch literal 16294 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 Lcu+3?B=mm)Oq!bc literal 0 HcmV?d00001 diff --git a/K-Means/Images/k_means_good.png b/K-Means/Images/k_means_good.png new file mode 100644 index 0000000000000000000000000000000000000000..01760758b5e5f2735579b8206e95b04c99cd3f20 GIT binary patch literal 15983 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 [VectorND] { + var centerMoveDist = 0.0 + let zeros = [Double](count: points[0].getLength(), repeatedValue: 0.0) + + var kCenters = reservoirSample(points, k: numCenters) + + repeat { + var cnts = [Double](count: numCenters, repeatedValue: 0.0) + var newCenters = [VectorND](count:numCenters, repeatedValue: VectorND(d:zeros)) + for p in points { + let c = nearestCenter(p, Centers: kCenters) + cnts[c]++ + newCenters[c] += p + } + for idx in 0.. convergeDist) + return kCenters +} +``` + +## Example +These examples are contrived to show the exact nature of K-Means and finding clusters. These clusters are very easily identified by human eyes, we see there is one in the lower left corner, one in the upper right corner and maybe one in the middle. + +In all these examples the stars represent the *centroids* and the squares are the points. + +##### Good clusters +This first example shows K-Means finding all three clusters: +![Good Clustering](Images/k_means_good.png) + +The selection of initial centroids found that lower left (indicated by red) and did pretty good on the center and upper left clusters. + +#### Bad Clustering +The next two examples highlight the unpredictability of k-Means and how not always does it find the best clustering. +![Bad Clustering 1](Images/k_means_bad1.png) +As you can see in this one the initial *centroids* were all a little two close and the 'blue' didn't quite get to a good place. By adjusting the convergence distance should be able to get it better. + +![Bad Clustering 1](Images/k_means_bad2.png) +This one the blue cluster never really could separate from the red cluster and as such sort of got stuck down there. + +## Performance +The first thing to recognize is that k-Means is classified as an NP-Hard type of problem. The selection of the initial *centroids* has a big effect on how the resulting clusters may end up. This means that trying to find an exact solution is not likely - even in 2 dimensional space. + +As seem from the steps above the complexity really isn't that bad - it is often considered to be on the order of O(kndi), where **k** is the number of *centroids*, **n** is the number of **d** dimensional vectors and **i** is the number of iterations for convergence. + +The amount of data has a big linear effect on the running time of k-means, but tuning how far you want the *centroids* to converge can have a big impact how many iterations will be done - **k** should be relatively small compared to the number of vectors. + +Often times as more data is added certain points may lie in the boundary between two *centroids* and as such those centroids would continue to bounce back and forth and the **convergence** distance would need to be tuned to prevent that. + +## See Also +See also [Wikipedia](https://en.wikipedia.org/wiki/K-means_clustering) + +*Written by John Gill* diff --git a/README.markdown b/README.markdown index 1af54642d..ebff0be73 100644 --- a/README.markdown +++ b/README.markdown @@ -95,13 +95,16 @@ Bad sorting algorithms (don't use these!): ### Machine learning -- [k-Means](K-Means/). Unsupervised classifier that partitions data into k clusters. +##### Supervised learning - k-Nearest Neighbors - Linear Regression - Logistic Regression - Neural Networks - PageRank +##### Clustering +- [k-Means](K-Means/). Unsupervised classifier that partitions data into k clusters. + ## Data structures The choice of data structure for a particular task depends on a few things. From ebcf1f4155afe2d57fd1967f60456bbbfeb70232 Mon Sep 17 00:00:00 2001 From: John Gill Date: Sun, 28 Feb 2016 14:44:04 -0800 Subject: [PATCH 0064/1679] Modify main README to add k-Means --- README.markdown | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/README.markdown b/README.markdown index ebff0be73..1f77f12a7 100644 --- a/README.markdown +++ b/README.markdown @@ -94,17 +94,13 @@ Bad sorting algorithms (don't use these!): - Statistics ### Machine learning - -##### Supervised learning +- [k-Means](K-Means/). Unsupervised classifier that partitions data into k clusters. - k-Nearest Neighbors - Linear Regression - Logistic Regression - Neural Networks - PageRank -##### Clustering -- [k-Means](K-Means/). Unsupervised classifier that partitions data into k clusters. - ## Data structures The choice of data structure for a particular task depends on a few things. From 87d798d949d2807bdb4d2a679d1155cb455bcc9f Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Mon, 29 Feb 2016 22:02:39 +1300 Subject: [PATCH 0065/1679] Changed simple example to used node.visited flag instead of storing separate "seenNodes" list --- .../Pages/Simple example.xcplaygroundpage/Contents.swift | 5 ++--- Breadth-First Search/README.markdown | 5 ++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/Breadth-First Search/BreadthFirstSearch.playground/Pages/Simple example.xcplaygroundpage/Contents.swift b/Breadth-First Search/BreadthFirstSearch.playground/Pages/Simple example.xcplaygroundpage/Contents.swift index b2ac225ab..7cb9122e3 100644 --- a/Breadth-First Search/BreadthFirstSearch.playground/Pages/Simple example.xcplaygroundpage/Contents.swift +++ b/Breadth-First Search/BreadthFirstSearch.playground/Pages/Simple example.xcplaygroundpage/Contents.swift @@ -1,5 +1,4 @@ func breadthFirstSearch(graph: Graph, source: Node) { - var seenNodes = [source] var queue = Queue() queue.enqueue(source) @@ -9,9 +8,9 @@ func breadthFirstSearch(graph: Graph, source: Node) { let current = queue.dequeue()! for edge in current.neighbors { let neighborNode = edge.neighbor - if !seenNodes.contains(neighborNode) { + if !neighborNode.visited { queue.enqueue(neighborNode) - seenNodes.append(neighborNode) + neighborNode.visited = true print(neighborNode.label) } } diff --git a/Breadth-First Search/README.markdown b/Breadth-First Search/README.markdown index d71cca15c..eea81bfd0 100644 --- a/Breadth-First Search/README.markdown +++ b/Breadth-First Search/README.markdown @@ -59,7 +59,6 @@ Simple implementation of breadth-first search using a queue: ```swift func breadthFirstSearch(graph: Graph, source: Node) { - var seenNodes = [source] var queue = Queue() queue.enqueue(source) @@ -69,9 +68,9 @@ func breadthFirstSearch(graph: Graph, source: Node) { let current = queue.dequeue()! for edge in current.neighbors { let neighborNode = edge.neighbor - if !seenNodes.contains(neighborNode) { + if !neighborNode.visited { queue.enqueue(neighborNode) - seenNodes.append(neighborNode) + neighborNode.visited = true print(neighborNode.label) } } From 32ac84bcaf4d444d70c2a06562aaef1acec83f21 Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Mon, 29 Feb 2016 22:28:07 +1300 Subject: [PATCH 0066/1679] BFS Added test project with implementation files. --- Breadth-First Search/BreadthFirstSearch.swift | 18 ++ ...readthFirstSearchMinimumSpanningTree.swift | 23 ++ .../BreadthFirstSearchShortestPath.swift | 18 ++ Breadth-First Search/Edge.swift | 7 + Breadth-First Search/Graph.swift | 52 ++++ Breadth-First Search/Node.swift | 32 ++ Breadth-First Search/Queue.swift | 31 ++ .../Tests/BreadthFirstSearchTests.swift | 8 + Breadth-First Search/Tests/Info.plist | 24 ++ .../Tests/Tests.xcodeproj/project.pbxproj | 288 ++++++++++++++++++ 10 files changed, 501 insertions(+) create mode 100644 Breadth-First Search/BreadthFirstSearch.swift create mode 100644 Breadth-First Search/BreadthFirstSearchMinimumSpanningTree.swift create mode 100644 Breadth-First Search/BreadthFirstSearchShortestPath.swift create mode 100644 Breadth-First Search/Edge.swift create mode 100644 Breadth-First Search/Graph.swift create mode 100644 Breadth-First Search/Node.swift create mode 100644 Breadth-First Search/Queue.swift create mode 100755 Breadth-First Search/Tests/BreadthFirstSearchTests.swift create mode 100644 Breadth-First Search/Tests/Info.plist create mode 100644 Breadth-First Search/Tests/Tests.xcodeproj/project.pbxproj diff --git a/Breadth-First Search/BreadthFirstSearch.swift b/Breadth-First Search/BreadthFirstSearch.swift new file mode 100644 index 000000000..d58c2367c --- /dev/null +++ b/Breadth-First Search/BreadthFirstSearch.swift @@ -0,0 +1,18 @@ +func breadthFirstSearch(graph: Graph, source: Node) { + var queue = Queue() + queue.enqueue(source) + + print(source.label) + + while !queue.isEmpty { + let current = queue.dequeue()! + for edge in current.neighbors { + let neighborNode = edge.neighbor + if !neighborNode.visited { + queue.enqueue(neighborNode) + neighborNode.visited = true + print(neighborNode.label) + } + } + } +} diff --git a/Breadth-First Search/BreadthFirstSearchMinimumSpanningTree.swift b/Breadth-First Search/BreadthFirstSearchMinimumSpanningTree.swift new file mode 100644 index 000000000..9329a0d3c --- /dev/null +++ b/Breadth-First Search/BreadthFirstSearchMinimumSpanningTree.swift @@ -0,0 +1,23 @@ +func breadthFirstSearchMinimumSpanningTree(graph: Graph, source: Node) -> Graph { + let minimumSpanningTree = graph.duplicate() + + var queue = Queue() + let sourceInMinimumSpanningTree = minimumSpanningTree.findNodeWithLabel(source.label) + queue.enqueue(sourceInMinimumSpanningTree) + sourceInMinimumSpanningTree.visited = true + + while !queue.isEmpty { + let current = queue.dequeue()! + for edge in current.neighbors { + let neighborNode = edge.neighbor + if !neighborNode.visited { + neighborNode.visited = true + queue.enqueue(neighborNode) + } else { + current.remove(edge) + } + } + } + + return minimumSpanningTree +} diff --git a/Breadth-First Search/BreadthFirstSearchShortestPath.swift b/Breadth-First Search/BreadthFirstSearchShortestPath.swift new file mode 100644 index 000000000..cb251cf0e --- /dev/null +++ b/Breadth-First Search/BreadthFirstSearchShortestPath.swift @@ -0,0 +1,18 @@ +func breadthFirstSearchShortestPath(graph: Graph, source: Node) { + var queue = Queue() + queue.enqueue(source) + source.distance = 0 + + while !queue.isEmpty { + let current = queue.dequeue()! + for edge in current.neighbors { + let neighborNode = edge.neighbor + if !neighborNode.hasDistance { + queue.enqueue(neighborNode) + neighborNode.distance = current.distance! + 1 + } + } + } + + print(graph.nodes) +} diff --git a/Breadth-First Search/Edge.swift b/Breadth-First Search/Edge.swift new file mode 100644 index 000000000..8f2128ac5 --- /dev/null +++ b/Breadth-First Search/Edge.swift @@ -0,0 +1,7 @@ +public class Edge { + public var neighbor: Node + + public init(neighbor: Node) { + self.neighbor = neighbor + } +} diff --git a/Breadth-First Search/Graph.swift b/Breadth-First Search/Graph.swift new file mode 100644 index 000000000..6792ebf7b --- /dev/null +++ b/Breadth-First Search/Graph.swift @@ -0,0 +1,52 @@ +public class Graph : CustomStringConvertible { + public private(set) var nodes: [Node] + + public init() { + self.nodes = [] + } + + public func addNode(label: String) -> Node { + let node = Node(label: label) + nodes.append(node) + return node + } + + public func addEdge(source: Node, neighbor: Node) { + let edge = Edge(neighbor: neighbor) + edge.neighbor = neighbor + source.neighbors.append(edge) + } + + public var description: String { + var description = "" + + for node in nodes { + if !node.neighbors.isEmpty { + description += "[node: \(node.label) edges: \(node.neighbors.map{ $0.neighbor.label})]" + } + } + return description + } + + public func findNodeWithLabel(label: String) -> Node { + return nodes.filter{ $0.label == label }.first! + } + + public func duplicate() -> Graph { + let duplicated = Graph() + + for node in nodes { + duplicated.addNode(node.label) + } + + for node in nodes { + for edge in node.neighbors { + let source = duplicated.findNodeWithLabel(node.label) + let neighbour = duplicated.findNodeWithLabel(edge.neighbor.label) + duplicated.addEdge(source, neighbor: neighbour) + } + } + + return duplicated + } +} diff --git a/Breadth-First Search/Node.swift b/Breadth-First Search/Node.swift new file mode 100644 index 000000000..4c261ffca --- /dev/null +++ b/Breadth-First Search/Node.swift @@ -0,0 +1,32 @@ +public class Node : CustomStringConvertible, Equatable { + public var neighbors: [Edge] + + public private(set) var label: String + public var distance: Int? + public var visited: Bool + + public init(label: String) { + self.label = label + neighbors = [] + visited = false + } + + public var description: String { + if let distance = distance { + return "Node(label: \(label), distance: \(distance))" + } + return "Node(label: \(label), distance: infinity)" + } + + public var hasDistance: Bool { + return distance != nil + } + + public func remove(edge: Edge) { + neighbors.removeAtIndex(neighbors.indexOf{ $0 === edge }!) + } +} + +public func ==(lhs: Node, rhs: Node) -> Bool { + return lhs.label == rhs.label +} diff --git a/Breadth-First Search/Queue.swift b/Breadth-First Search/Queue.swift new file mode 100644 index 000000000..bf462bbdd --- /dev/null +++ b/Breadth-First Search/Queue.swift @@ -0,0 +1,31 @@ +public struct Queue { + private var array: [T] + + public init() { + array = [] + } + + public var isEmpty: Bool { + return array.isEmpty + } + + public var count: Int { + return array.count + } + + public mutating func enqueue(element: T) { + array.append(element) + } + + public mutating func dequeue() -> T? { + if isEmpty { + return nil + } else { + return array.removeFirst() + } + } + + public func peek() -> T? { + return array.first + } +} diff --git a/Breadth-First Search/Tests/BreadthFirstSearchTests.swift b/Breadth-First Search/Tests/BreadthFirstSearchTests.swift new file mode 100755 index 000000000..c68d369dc --- /dev/null +++ b/Breadth-First Search/Tests/BreadthFirstSearchTests.swift @@ -0,0 +1,8 @@ +import Foundation +import XCTest + +class QueueTest: XCTestCase { + func testFail() { + XCTAssertFalse(true) + } +} diff --git a/Breadth-First Search/Tests/Info.plist b/Breadth-First Search/Tests/Info.plist new file mode 100644 index 000000000..ba72822e8 --- /dev/null +++ b/Breadth-First Search/Tests/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/Breadth-First Search/Tests/Tests.xcodeproj/project.pbxproj b/Breadth-First Search/Tests/Tests.xcodeproj/project.pbxproj new file mode 100644 index 000000000..9d32cfdaa --- /dev/null +++ b/Breadth-First Search/Tests/Tests.xcodeproj/project.pbxproj @@ -0,0 +1,288 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 83F9C9681C84437C00B3A87F /* BreadthFirstSearch.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83F9C9651C84437C00B3A87F /* BreadthFirstSearch.swift */; }; + 83F9C9691C84437C00B3A87F /* BreadthFirstSearchMinimumSpanningTree.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83F9C9661C84437C00B3A87F /* BreadthFirstSearchMinimumSpanningTree.swift */; }; + 83F9C96A1C84437C00B3A87F /* BreadthFirstSearchShortestPath.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83F9C9671C84437C00B3A87F /* BreadthFirstSearchShortestPath.swift */; }; + 83F9C96C1C8443E800B3A87F /* BreadthFirstSearchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83F9C96B1C8443E800B3A87F /* BreadthFirstSearchTests.swift */; }; + 83F9C9711C84449D00B3A87F /* Edge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83F9C96D1C84449D00B3A87F /* Edge.swift */; }; + 83F9C9721C84449D00B3A87F /* Graph.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83F9C96E1C84449D00B3A87F /* Graph.swift */; }; + 83F9C9731C84449D00B3A87F /* Node.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83F9C96F1C84449D00B3A87F /* Node.swift */; }; + 83F9C9741C84449D00B3A87F /* Queue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83F9C9701C84449D00B3A87F /* Queue.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 7B2BBC801C779D720067B71D /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 7B2BBC941C779E7B0067B71D /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; + 83F9C9651C84437C00B3A87F /* BreadthFirstSearch.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BreadthFirstSearch.swift; path = ../BreadthFirstSearch.swift; sourceTree = SOURCE_ROOT; }; + 83F9C9661C84437C00B3A87F /* BreadthFirstSearchMinimumSpanningTree.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BreadthFirstSearchMinimumSpanningTree.swift; path = ../BreadthFirstSearchMinimumSpanningTree.swift; sourceTree = SOURCE_ROOT; }; + 83F9C9671C84437C00B3A87F /* BreadthFirstSearchShortestPath.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BreadthFirstSearchShortestPath.swift; path = ../BreadthFirstSearchShortestPath.swift; sourceTree = SOURCE_ROOT; }; + 83F9C96B1C8443E800B3A87F /* BreadthFirstSearchTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BreadthFirstSearchTests.swift; sourceTree = SOURCE_ROOT; }; + 83F9C96D1C84449D00B3A87F /* Edge.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Edge.swift; path = ../Edge.swift; sourceTree = SOURCE_ROOT; }; + 83F9C96E1C84449D00B3A87F /* Graph.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Graph.swift; path = ../Graph.swift; sourceTree = SOURCE_ROOT; }; + 83F9C96F1C84449D00B3A87F /* Node.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Node.swift; path = ../Node.swift; sourceTree = SOURCE_ROOT; }; + 83F9C9701C84449D00B3A87F /* Queue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Queue.swift; path = ../Queue.swift; sourceTree = SOURCE_ROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 7B2BBC7D1C779D720067B71D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 7B2BBC681C779D710067B71D = { + isa = PBXGroup; + children = ( + 7B2BBC831C779D720067B71D /* Tests */, + 7B2BBC721C779D710067B71D /* Products */, + ); + sourceTree = ""; + }; + 7B2BBC721C779D710067B71D /* Products */ = { + isa = PBXGroup; + children = ( + 7B2BBC801C779D720067B71D /* Tests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 7B2BBC831C779D720067B71D /* Tests */ = { + isa = PBXGroup; + children = ( + 83F9C96D1C84449D00B3A87F /* Edge.swift */, + 83F9C96E1C84449D00B3A87F /* Graph.swift */, + 83F9C96F1C84449D00B3A87F /* Node.swift */, + 83F9C9701C84449D00B3A87F /* Queue.swift */, + 83F9C96B1C8443E800B3A87F /* BreadthFirstSearchTests.swift */, + 83F9C9651C84437C00B3A87F /* BreadthFirstSearch.swift */, + 83F9C9661C84437C00B3A87F /* BreadthFirstSearchMinimumSpanningTree.swift */, + 83F9C9671C84437C00B3A87F /* BreadthFirstSearchShortestPath.swift */, + 7B2BBC941C779E7B0067B71D /* Info.plist */, + ); + name = Tests; + path = TestsTests; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 7B2BBC7F1C779D720067B71D /* Tests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */; + buildPhases = ( + 7B2BBC7C1C779D720067B71D /* Sources */, + 7B2BBC7D1C779D720067B71D /* Frameworks */, + 7B2BBC7E1C779D720067B71D /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Tests; + productName = TestsTests; + productReference = 7B2BBC801C779D720067B71D /* Tests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 7B2BBC691C779D710067B71D /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0720; + LastUpgradeCheck = 0720; + ORGANIZATIONNAME = "Swift Algorithm Club"; + TargetAttributes = { + 7B2BBC7F1C779D720067B71D = { + CreatedOnToolsVersion = 7.2; + }; + }; + }; + buildConfigurationList = 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 7B2BBC681C779D710067B71D; + productRefGroup = 7B2BBC721C779D710067B71D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 7B2BBC7F1C779D720067B71D /* Tests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 7B2BBC7E1C779D720067B71D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 7B2BBC7C1C779D720067B71D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 83F9C9721C84449D00B3A87F /* Graph.swift in Sources */, + 83F9C9691C84437C00B3A87F /* BreadthFirstSearchMinimumSpanningTree.swift in Sources */, + 83F9C9681C84437C00B3A87F /* BreadthFirstSearch.swift in Sources */, + 83F9C9741C84449D00B3A87F /* Queue.swift in Sources */, + 83F9C96A1C84437C00B3A87F /* BreadthFirstSearchShortestPath.swift in Sources */, + 83F9C9711C84449D00B3A87F /* Edge.swift in Sources */, + 83F9C96C1C8443E800B3A87F /* BreadthFirstSearchTests.swift in Sources */, + 83F9C9731C84449D00B3A87F /* Node.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 7B2BBC871C779D720067B71D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 7B2BBC881C779D720067B71D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + }; + name = Release; + }; + 7B2BBC8D1C779D720067B71D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 7B2BBC8E1C779D720067B71D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7B2BBC871C779D720067B71D /* Debug */, + 7B2BBC881C779D720067B71D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7B2BBC8D1C779D720067B71D /* Debug */, + 7B2BBC8E1C779D720067B71D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 7B2BBC691C779D710067B71D /* Project object */; +} From aa8e35292dd7b1bd10694cfb54adbb0a74c94cc8 Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Mon, 29 Feb 2016 22:53:59 +1300 Subject: [PATCH 0067/1679] BFS Changed simple example to return array instead of printing explored nodes to allow for testing. Added tests for simple example. --- .../Contents.swift | 13 ++- Breadth-First Search/BreadthFirstSearch.swift | 12 ++- Breadth-First Search/README.markdown | 13 ++- .../Tests/BreadthFirstSearchTests.swift | 81 ++++++++++++++++++- 4 files changed, 105 insertions(+), 14 deletions(-) diff --git a/Breadth-First Search/BreadthFirstSearch.playground/Pages/Simple example.xcplaygroundpage/Contents.swift b/Breadth-First Search/BreadthFirstSearch.playground/Pages/Simple example.xcplaygroundpage/Contents.swift index 7cb9122e3..44a6a284e 100644 --- a/Breadth-First Search/BreadthFirstSearch.playground/Pages/Simple example.xcplaygroundpage/Contents.swift +++ b/Breadth-First Search/BreadthFirstSearch.playground/Pages/Simple example.xcplaygroundpage/Contents.swift @@ -1,8 +1,9 @@ -func breadthFirstSearch(graph: Graph, source: Node) { +func breadthFirstSearch(graph: Graph, source: Node) -> [String] { var queue = Queue() queue.enqueue(source) - print(source.label) + var nodesExplored = [source.label] + source.visited = true while !queue.isEmpty { let current = queue.dequeue()! @@ -11,10 +12,13 @@ func breadthFirstSearch(graph: Graph, source: Node) { if !neighborNode.visited { queue.enqueue(neighborNode) neighborNode.visited = true - print(neighborNode.label) + + nodesExplored.append(neighborNode.label) } } } + + return nodesExplored } /*: @@ -41,4 +45,5 @@ graph.addEdge(nodeC, neighbor: nodeG) graph.addEdge(nodeE, neighbor: nodeH) -breadthFirstSearch(graph, source: nodeA) +let nodesExplored = breadthFirstSearch(graph, source: nodeA) +print(nodesExplored) diff --git a/Breadth-First Search/BreadthFirstSearch.swift b/Breadth-First Search/BreadthFirstSearch.swift index d58c2367c..eb9fe30a6 100644 --- a/Breadth-First Search/BreadthFirstSearch.swift +++ b/Breadth-First Search/BreadthFirstSearch.swift @@ -1,9 +1,10 @@ -func breadthFirstSearch(graph: Graph, source: Node) { +func breadthFirstSearch(graph: Graph, source: Node) -> [String] { var queue = Queue() queue.enqueue(source) - print(source.label) - + var nodesExplored = [source.label] + source.visited = true + while !queue.isEmpty { let current = queue.dequeue()! for edge in current.neighbors { @@ -11,8 +12,11 @@ func breadthFirstSearch(graph: Graph, source: Node) { if !neighborNode.visited { queue.enqueue(neighborNode) neighborNode.visited = true - print(neighborNode.label) + + nodesExplored.append(neighborNode.label) } } } + + return nodesExplored } diff --git a/Breadth-First Search/README.markdown b/Breadth-First Search/README.markdown index eea81bfd0..9971cd081 100644 --- a/Breadth-First Search/README.markdown +++ b/Breadth-First Search/README.markdown @@ -58,11 +58,12 @@ The queue is now empty which means all nodes have been explored. Simple implementation of breadth-first search using a queue: ```swift -func breadthFirstSearch(graph: Graph, source: Node) { +func breadthFirstSearch(graph: Graph, source: Node) -> [String] { var queue = Queue() queue.enqueue(source) - print(source.label) + var nodesExplored = [source.label] + source.visited = true while !queue.isEmpty { let current = queue.dequeue()! @@ -71,10 +72,13 @@ func breadthFirstSearch(graph: Graph, source: Node) { if !neighborNode.visited { queue.enqueue(neighborNode) neighborNode.visited = true - print(neighborNode.label) + + nodesExplored.append(neighborNode.label) } } } + + return nodesExplored } ``` @@ -99,7 +103,8 @@ graph.addEdge(nodeC, neighbor: nodeF) graph.addEdge(nodeC, neighbor: nodeG) graph.addEdge(nodeE, neighbor: nodeH) -breadthFirstSearch(graph, source: nodeA) // This will output: a, b, c, d, e, f, g, h +let nodesExplored = breadthFirstSearch(graph, source: nodeA) +print(nodesExplored) // This will output: ["a", "b", "c", "d", "e", "f", "g", "h"] ``` ## Applications diff --git a/Breadth-First Search/Tests/BreadthFirstSearchTests.swift b/Breadth-First Search/Tests/BreadthFirstSearchTests.swift index c68d369dc..86487d8b7 100755 --- a/Breadth-First Search/Tests/BreadthFirstSearchTests.swift +++ b/Breadth-First Search/Tests/BreadthFirstSearchTests.swift @@ -2,7 +2,84 @@ import Foundation import XCTest class QueueTest: XCTestCase { - func testFail() { - XCTAssertFalse(true) + + func testExploringTree() { + let tree = Graph() + let nodeA = tree.addNode("a") + let nodeB = tree.addNode("b") + let nodeC = tree.addNode("c") + let nodeD = tree.addNode("d") + let nodeE = tree.addNode("e") + let nodeF = tree.addNode("f") + let nodeG = tree.addNode("g") + let nodeH = tree.addNode("h") + tree.addEdge(nodeA, neighbor: nodeB) + tree.addEdge(nodeA, neighbor: nodeC) + tree.addEdge(nodeB, neighbor: nodeD) + tree.addEdge(nodeB, neighbor: nodeE) + tree.addEdge(nodeC, neighbor: nodeF) + tree.addEdge(nodeC, neighbor: nodeG) + tree.addEdge(nodeE, neighbor: nodeH) + + let nodesExplored = breadthFirstSearch(tree, source: nodeA) + + XCTAssertEqual(nodesExplored, ["a", "b", "c", "d", "e", "f", "g", "h"]) + } + + func testExploringGraph() { + let graph = Graph() + + let nodeA = graph.addNode("a") + let nodeB = graph.addNode("b") + let nodeC = graph.addNode("c") + let nodeD = graph.addNode("d") + let nodeE = graph.addNode("e") + let nodeF = graph.addNode("f") + let nodeG = graph.addNode("g") + let nodeH = graph.addNode("h") + let nodeI = graph.addNode("i") + + graph.addEdge(nodeA, neighbor: nodeB) + graph.addEdge(nodeA, neighbor: nodeH) + graph.addEdge(nodeB, neighbor: nodeA) + graph.addEdge(nodeB, neighbor: nodeC) + graph.addEdge(nodeB, neighbor: nodeH) + graph.addEdge(nodeC, neighbor: nodeB) + graph.addEdge(nodeC, neighbor: nodeD) + graph.addEdge(nodeC, neighbor: nodeF) + graph.addEdge(nodeC, neighbor: nodeI) + graph.addEdge(nodeD, neighbor: nodeC) + graph.addEdge(nodeD, neighbor: nodeE) + graph.addEdge(nodeD, neighbor: nodeF) + graph.addEdge(nodeE, neighbor: nodeD) + graph.addEdge(nodeE, neighbor: nodeF) + graph.addEdge(nodeF, neighbor: nodeC) + graph.addEdge(nodeF, neighbor: nodeD) + graph.addEdge(nodeF, neighbor: nodeE) + graph.addEdge(nodeF, neighbor: nodeG) + graph.addEdge(nodeG, neighbor: nodeF) + graph.addEdge(nodeG, neighbor: nodeH) + graph.addEdge(nodeG, neighbor: nodeI) + graph.addEdge(nodeH, neighbor: nodeA) + graph.addEdge(nodeH, neighbor: nodeB) + graph.addEdge(nodeH, neighbor: nodeG) + graph.addEdge(nodeH, neighbor: nodeI) + graph.addEdge(nodeI, neighbor: nodeC) + graph.addEdge(nodeI, neighbor: nodeG) + graph.addEdge(nodeI, neighbor: nodeH) + + let nodesExplored = breadthFirstSearch(graph, source: nodeA) + + XCTAssertEqual(nodesExplored, ["a", "b", "h", "c", "g", "i", "d", "f", "e"]) + + } + + func testExploringGraphWithASingleNode() { + let graph = Graph() + let node = graph.addNode("a") + + let nodesExplored = breadthFirstSearch(graph, source: node) + + XCTAssertEqual(nodesExplored, ["a"]) } } From edf5673f3b3a528b1d3005bd67c959acf674343e Mon Sep 17 00:00:00 2001 From: Kauserali Hafizji Date: Mon, 29 Feb 2016 15:58:01 +0530 Subject: [PATCH 0068/1679] Algorithm explanation --- Shunting Yard/README.markdown | 108 ++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 Shunting Yard/README.markdown diff --git a/Shunting Yard/README.markdown b/Shunting Yard/README.markdown new file mode 100644 index 000000000..92555de9a --- /dev/null +++ b/Shunting Yard/README.markdown @@ -0,0 +1,108 @@ +# Shunting Yard Algorithm + +Any mathematical expression that we write is expressed in a notation known as Infix Notation. + +For example: + +A + B * C + +In the above expression the operator is placed between operands hence the expression is said to be in Infix form. +If you think about it any expression that you write on a piece of paper will always be in infix form. This is what we humans understand. + +Now, think about the way the above expression is evaluated, you would first multiply B and C then add the result to A. This is because multiplication has +higher precedence than addition. We humans can easily understand the precedence of operators, but a machine needs to be given instructions about each operator. If you were to +write an algorithm than parsed and evaluated the infix notation you'll soon realize that it's a tedious process. You'd have to parse the expression +multiple times to know what operation to perform first. As the number of operators increase so does the complexity. + +## Postfix notations / Reverse Polish Notation + +An expression when represented in postfix form will not have any brackets and neither will you have to worry about scanning for operator precedence. This makes it easy for the computer to evaluate +expressions since the order in which the operator need to be applied is fixed. + +For example: + +**A B C * +** + +The above is the postfix representation of the example in the previous section. The operators come after the corresponding operands. + +### Evaluating a postfix expression + +A stack is used to evaluate a postfix expression. Here is the pseudocode: + +1. read postfix expression token by token +2. if the token is an operand, push it + into the stack +3. if the token is a binary operator, +3.1 pop the two top most operands + from the stack +3.2 apply the binary operator with the + two operands +3.3 push the result into the stack +4. finally, the value of the whole postfix + expression remains in the stack + +Using the above psuedocode the evaluation on the stack would be as follows: + +| Expression | Stack | +| ------------- | --------| +| A B C * + | | +| B C * + | A | +| C * + | A, B | +| * + | A, B, C | +| + | A, D | +| | E | + +Where **D = B * C** and **E = A + D.** + +As seen above a postfix operation is relatively easy to evaluate as the order in which the operators need to be applied is predecided. + +## Shunting yard algorithm + +The Shunting yard algorithm was invented by Edsger Dijkstra to convert an infix expression to postfix. Many calculators use this algorithm to convert the expression being entered to postfix form. + +Here is the psedocode of the algorithm: + +1. For all the input tokens + 1. Read the next token + 2. If token is an operator (x) + 1. While there is an operator (y) at the top of the operators stack and either (x) is left-associative and its precedence is less or equal to that of (y), or (x) is right-associative and its precedence is less than (y) + 1. Pop (y) from the stack + 2. Add (y) output buffer + 2. Push (x) on the stack + 3. Else If token is left parenthesis, then push it on the stack + 4. Else If token is a right parenthesis + 1. Until the top token (from the stack) is left parenthesis, pop from the stack to the output buffer + 2. Also pop the left parenthesis but don’t include it in the output buffer + 7. Else add token to output buffer +2. While there are still operator tokens in the stack, pop them to output + +### How does it work + +Let's take a small example and see how the psuedocode works. + +**4 + 4 * 2 / ( 1 - 5 )** + +| Operator | Precedence | Associativity | +| ---------| -------------| ----------------| +| ^ | 10 | Right | +| * | 5 | Left | +| / | 5 | Left | +| + | 0 | Left | +| - | 0 | Left | + +The above table describes the precedence and the associativity for each operator. The same values are used in the algorithm. + +| Token | Action | Output | Operator stack | +|-------|---------------------------------------------|-------------------|----------------| +| 3 | Add token to output | 4 | | +| + | Push token to stack | 4 | + | +| 4 | Add token to output | 4 4 | + | +| * | Push token to stack | 4 4 | * + | +| 2 | Add token to output | 4 4 2 | * + | +| / | * Pop stack to output * Push token to stack | 4 4 2 * | / + | +| ( | Push token to stack | 4 4 2 * | ( / + | +| 1 | Add token to output | 4 4 2 * 1 | ( / + | +| - | Push token to stack | 4 4 2 * 1 | - ( / + | +| 5 | Add token to output | 4 4 2 * 1 5 | - ( / + | +| ) | * Pop stack to output * Pop stack | 4 4 2 * 1 5 - | / + | +| end | Pop entire stack to output | 4 4 2 * 1 5 - / + | | \ No newline at end of file From abba1fa41d862d7e759a4d2865df97d0c6e5f880 Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Mon, 29 Feb 2016 23:28:50 +1300 Subject: [PATCH 0069/1679] BFS Added tests for minimum spanning tree. --- .../Sources/Edge.swift | 6 +- .../Sources/Graph.swift | 6 +- .../Sources/Node.swift | 4 +- Breadth-First Search/Edge.swift | 6 +- Breadth-First Search/Graph.swift | 6 +- Breadth-First Search/Node.swift | 2 +- ...hFirstSearchMinimumSpanningTreeTests.swift | 107 ++++++++++++++++++ .../Tests/BreadthFirstSearchTests.swift | 4 +- .../Tests/Tests.xcodeproj/project.pbxproj | 4 + 9 files changed, 136 insertions(+), 9 deletions(-) create mode 100644 Breadth-First Search/Tests/BreadthFirstSearchMinimumSpanningTreeTests.swift diff --git a/Breadth-First Search/BreadthFirstSearch.playground/Sources/Edge.swift b/Breadth-First Search/BreadthFirstSearch.playground/Sources/Edge.swift index 8f2128ac5..3937a2cc7 100644 --- a/Breadth-First Search/BreadthFirstSearch.playground/Sources/Edge.swift +++ b/Breadth-First Search/BreadthFirstSearch.playground/Sources/Edge.swift @@ -1,7 +1,11 @@ -public class Edge { +public class Edge : Equatable { public var neighbor: Node public init(neighbor: Node) { self.neighbor = neighbor } } + +public func ==(lhs: Edge, rhs: Edge) -> Bool { + return lhs.neighbor == rhs.neighbor +} diff --git a/Breadth-First Search/BreadthFirstSearch.playground/Sources/Graph.swift b/Breadth-First Search/BreadthFirstSearch.playground/Sources/Graph.swift index 6792ebf7b..181af9e85 100644 --- a/Breadth-First Search/BreadthFirstSearch.playground/Sources/Graph.swift +++ b/Breadth-First Search/BreadthFirstSearch.playground/Sources/Graph.swift @@ -1,4 +1,4 @@ -public class Graph : CustomStringConvertible { +public class Graph : CustomStringConvertible, Equatable { public private(set) var nodes: [Node] public init() { @@ -50,3 +50,7 @@ public class Graph : CustomStringConvertible { return duplicated } } + +public func ==(lhs: Graph, rhs: Graph) -> Bool { + return lhs.nodes == rhs.nodes +} diff --git a/Breadth-First Search/BreadthFirstSearch.playground/Sources/Node.swift b/Breadth-First Search/BreadthFirstSearch.playground/Sources/Node.swift index 4c261ffca..9d8435ffa 100644 --- a/Breadth-First Search/BreadthFirstSearch.playground/Sources/Node.swift +++ b/Breadth-First Search/BreadthFirstSearch.playground/Sources/Node.swift @@ -1,6 +1,6 @@ public class Node : CustomStringConvertible, Equatable { public var neighbors: [Edge] - + public private(set) var label: String public var distance: Int? public var visited: Bool @@ -28,5 +28,5 @@ public class Node : CustomStringConvertible, Equatable { } public func ==(lhs: Node, rhs: Node) -> Bool { - return lhs.label == rhs.label + return lhs.label == rhs.label && lhs.neighbors == rhs.neighbors } diff --git a/Breadth-First Search/Edge.swift b/Breadth-First Search/Edge.swift index 8f2128ac5..3937a2cc7 100644 --- a/Breadth-First Search/Edge.swift +++ b/Breadth-First Search/Edge.swift @@ -1,7 +1,11 @@ -public class Edge { +public class Edge : Equatable { public var neighbor: Node public init(neighbor: Node) { self.neighbor = neighbor } } + +public func ==(lhs: Edge, rhs: Edge) -> Bool { + return lhs.neighbor == rhs.neighbor +} diff --git a/Breadth-First Search/Graph.swift b/Breadth-First Search/Graph.swift index 6792ebf7b..181af9e85 100644 --- a/Breadth-First Search/Graph.swift +++ b/Breadth-First Search/Graph.swift @@ -1,4 +1,4 @@ -public class Graph : CustomStringConvertible { +public class Graph : CustomStringConvertible, Equatable { public private(set) var nodes: [Node] public init() { @@ -50,3 +50,7 @@ public class Graph : CustomStringConvertible { return duplicated } } + +public func ==(lhs: Graph, rhs: Graph) -> Bool { + return lhs.nodes == rhs.nodes +} diff --git a/Breadth-First Search/Node.swift b/Breadth-First Search/Node.swift index 4c261ffca..000fd78f6 100644 --- a/Breadth-First Search/Node.swift +++ b/Breadth-First Search/Node.swift @@ -28,5 +28,5 @@ public class Node : CustomStringConvertible, Equatable { } public func ==(lhs: Node, rhs: Node) -> Bool { - return lhs.label == rhs.label + return lhs.label == rhs.label && lhs.neighbors == rhs.neighbors } diff --git a/Breadth-First Search/Tests/BreadthFirstSearchMinimumSpanningTreeTests.swift b/Breadth-First Search/Tests/BreadthFirstSearchMinimumSpanningTreeTests.swift new file mode 100644 index 000000000..527387062 --- /dev/null +++ b/Breadth-First Search/Tests/BreadthFirstSearchMinimumSpanningTreeTests.swift @@ -0,0 +1,107 @@ +import XCTest + +class BreadthFirstSearchMinimumSpanningTreeTests: XCTestCase { + + func testMinimumSpanningTreeReturnsSameTreeWhenGivenTree() { + let tree = Graph() + let nodeA = tree.addNode("a") + let nodeB = tree.addNode("b") + let nodeC = tree.addNode("c") + let nodeD = tree.addNode("d") + let nodeE = tree.addNode("e") + let nodeF = tree.addNode("f") + let nodeG = tree.addNode("g") + let nodeH = tree.addNode("h") + tree.addEdge(nodeA, neighbor: nodeB) + tree.addEdge(nodeA, neighbor: nodeC) + tree.addEdge(nodeB, neighbor: nodeD) + tree.addEdge(nodeB, neighbor: nodeE) + tree.addEdge(nodeC, neighbor: nodeF) + tree.addEdge(nodeC, neighbor: nodeG) + tree.addEdge(nodeE, neighbor: nodeH) + + let minimumSpanningTree = breadthFirstSearchMinimumSpanningTree(tree, source: nodeA) + + XCTAssertEqual(minimumSpanningTree, tree) + } + + func testMinimumSpanningTreeReturnsMinimumSpanningTreeWhenGivenGraph() { + let graphAndSourceNode = createGraph() + let expectedMinimumSpanningTree = createMinimumSpanningTree() + + let actualMinimumSpanningTree = breadthFirstSearchMinimumSpanningTree(graphAndSourceNode.graph, + source: graphAndSourceNode.source) + + XCTAssertEqual(actualMinimumSpanningTree, expectedMinimumSpanningTree) + } + + func createGraph() -> (graph: Graph, source: Node) { + let graph = Graph() + + let nodeA = graph.addNode("a") + let nodeB = graph.addNode("b") + let nodeC = graph.addNode("c") + let nodeD = graph.addNode("d") + let nodeE = graph.addNode("e") + let nodeF = graph.addNode("f") + let nodeG = graph.addNode("g") + let nodeH = graph.addNode("h") + let nodeI = graph.addNode("i") + + graph.addEdge(nodeA, neighbor: nodeB) + graph.addEdge(nodeA, neighbor: nodeH) + graph.addEdge(nodeB, neighbor: nodeA) + graph.addEdge(nodeB, neighbor: nodeC) + graph.addEdge(nodeB, neighbor: nodeH) + graph.addEdge(nodeC, neighbor: nodeB) + graph.addEdge(nodeC, neighbor: nodeD) + graph.addEdge(nodeC, neighbor: nodeF) + graph.addEdge(nodeC, neighbor: nodeI) + graph.addEdge(nodeD, neighbor: nodeC) + graph.addEdge(nodeD, neighbor: nodeE) + graph.addEdge(nodeD, neighbor: nodeF) + graph.addEdge(nodeE, neighbor: nodeD) + graph.addEdge(nodeE, neighbor: nodeF) + graph.addEdge(nodeF, neighbor: nodeC) + graph.addEdge(nodeF, neighbor: nodeD) + graph.addEdge(nodeF, neighbor: nodeE) + graph.addEdge(nodeF, neighbor: nodeG) + graph.addEdge(nodeG, neighbor: nodeF) + graph.addEdge(nodeG, neighbor: nodeH) + graph.addEdge(nodeG, neighbor: nodeI) + graph.addEdge(nodeH, neighbor: nodeA) + graph.addEdge(nodeH, neighbor: nodeB) + graph.addEdge(nodeH, neighbor: nodeG) + graph.addEdge(nodeH, neighbor: nodeI) + graph.addEdge(nodeI, neighbor: nodeC) + graph.addEdge(nodeI, neighbor: nodeG) + graph.addEdge(nodeI, neighbor: nodeH) + + return (graph, nodeA) + } + + func createMinimumSpanningTree() -> Graph { + let minimumSpanningTree = Graph() + + let nodeA = minimumSpanningTree.addNode("a") + let nodeB = minimumSpanningTree.addNode("b") + let nodeC = minimumSpanningTree.addNode("c") + let nodeD = minimumSpanningTree.addNode("d") + let nodeE = minimumSpanningTree.addNode("e") + let nodeF = minimumSpanningTree.addNode("f") + let nodeG = minimumSpanningTree.addNode("g") + let nodeH = minimumSpanningTree.addNode("h") + let nodeI = minimumSpanningTree.addNode("i") + + minimumSpanningTree.addEdge(nodeA, neighbor: nodeB) + minimumSpanningTree.addEdge(nodeA, neighbor: nodeH) + minimumSpanningTree.addEdge(nodeB, neighbor: nodeC) + minimumSpanningTree.addEdge(nodeH, neighbor: nodeG) + minimumSpanningTree.addEdge(nodeH, neighbor: nodeI) + minimumSpanningTree.addEdge(nodeC, neighbor: nodeD) + minimumSpanningTree.addEdge(nodeC, neighbor: nodeF) + minimumSpanningTree.addEdge(nodeD, neighbor: nodeE) + + return minimumSpanningTree + } +} diff --git a/Breadth-First Search/Tests/BreadthFirstSearchTests.swift b/Breadth-First Search/Tests/BreadthFirstSearchTests.swift index 86487d8b7..6c0d382d9 100755 --- a/Breadth-First Search/Tests/BreadthFirstSearchTests.swift +++ b/Breadth-First Search/Tests/BreadthFirstSearchTests.swift @@ -1,7 +1,6 @@ -import Foundation import XCTest -class QueueTest: XCTestCase { +class BreadthFirstSearchTests: XCTestCase { func testExploringTree() { let tree = Graph() @@ -83,3 +82,4 @@ class QueueTest: XCTestCase { XCTAssertEqual(nodesExplored, ["a"]) } } + diff --git a/Breadth-First Search/Tests/Tests.xcodeproj/project.pbxproj b/Breadth-First Search/Tests/Tests.xcodeproj/project.pbxproj index 9d32cfdaa..b0e34b310 100644 --- a/Breadth-First Search/Tests/Tests.xcodeproj/project.pbxproj +++ b/Breadth-First Search/Tests/Tests.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 83AACB421C844CED00DDAFC7 /* BreadthFirstSearchMinimumSpanningTreeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83AACB411C844CED00DDAFC7 /* BreadthFirstSearchMinimumSpanningTreeTests.swift */; }; 83F9C9681C84437C00B3A87F /* BreadthFirstSearch.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83F9C9651C84437C00B3A87F /* BreadthFirstSearch.swift */; }; 83F9C9691C84437C00B3A87F /* BreadthFirstSearchMinimumSpanningTree.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83F9C9661C84437C00B3A87F /* BreadthFirstSearchMinimumSpanningTree.swift */; }; 83F9C96A1C84437C00B3A87F /* BreadthFirstSearchShortestPath.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83F9C9671C84437C00B3A87F /* BreadthFirstSearchShortestPath.swift */; }; @@ -20,6 +21,7 @@ /* Begin PBXFileReference section */ 7B2BBC801C779D720067B71D /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 7B2BBC941C779E7B0067B71D /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; + 83AACB411C844CED00DDAFC7 /* BreadthFirstSearchMinimumSpanningTreeTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BreadthFirstSearchMinimumSpanningTreeTests.swift; sourceTree = SOURCE_ROOT; }; 83F9C9651C84437C00B3A87F /* BreadthFirstSearch.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BreadthFirstSearch.swift; path = ../BreadthFirstSearch.swift; sourceTree = SOURCE_ROOT; }; 83F9C9661C84437C00B3A87F /* BreadthFirstSearchMinimumSpanningTree.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BreadthFirstSearchMinimumSpanningTree.swift; path = ../BreadthFirstSearchMinimumSpanningTree.swift; sourceTree = SOURCE_ROOT; }; 83F9C9671C84437C00B3A87F /* BreadthFirstSearchShortestPath.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BreadthFirstSearchShortestPath.swift; path = ../BreadthFirstSearchShortestPath.swift; sourceTree = SOURCE_ROOT; }; @@ -69,6 +71,7 @@ 83F9C9661C84437C00B3A87F /* BreadthFirstSearchMinimumSpanningTree.swift */, 83F9C9671C84437C00B3A87F /* BreadthFirstSearchShortestPath.swift */, 7B2BBC941C779E7B0067B71D /* Info.plist */, + 83AACB411C844CED00DDAFC7 /* BreadthFirstSearchMinimumSpanningTreeTests.swift */, ); name = Tests; path = TestsTests; @@ -142,6 +145,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 83AACB421C844CED00DDAFC7 /* BreadthFirstSearchMinimumSpanningTreeTests.swift in Sources */, 83F9C9721C84449D00B3A87F /* Graph.swift in Sources */, 83F9C9691C84437C00B3A87F /* BreadthFirstSearchMinimumSpanningTree.swift in Sources */, 83F9C9681C84437C00B3A87F /* BreadthFirstSearch.swift in Sources */, From ea0df5b52394bd63d8d4b1440a4f39816a12ae4a Mon Sep 17 00:00:00 2001 From: Kauserali Hafizji Date: Mon, 29 Feb 2016 16:07:54 +0530 Subject: [PATCH 0070/1679] Fixed some typos --- Shunting Yard/README.markdown | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/Shunting Yard/README.markdown b/Shunting Yard/README.markdown index 92555de9a..3668888b2 100644 --- a/Shunting Yard/README.markdown +++ b/Shunting Yard/README.markdown @@ -4,14 +4,14 @@ Any mathematical expression that we write is expressed in a notation known as In For example: -A + B * C +**A + B * C** In the above expression the operator is placed between operands hence the expression is said to be in Infix form. If you think about it any expression that you write on a piece of paper will always be in infix form. This is what we humans understand. Now, think about the way the above expression is evaluated, you would first multiply B and C then add the result to A. This is because multiplication has higher precedence than addition. We humans can easily understand the precedence of operators, but a machine needs to be given instructions about each operator. If you were to -write an algorithm than parsed and evaluated the infix notation you'll soon realize that it's a tedious process. You'd have to parse the expression +write an algorithm that parsed and evaluated the infix notation you will realize that it's a tedious process. You'd have to parse the expression multiple times to know what operation to perform first. As the number of operators increase so does the complexity. ## Postfix notations / Reverse Polish Notation @@ -29,16 +29,13 @@ The above is the postfix representation of the example in the previous section. A stack is used to evaluate a postfix expression. Here is the pseudocode: -1. read postfix expression token by token -2. if the token is an operand, push it - into the stack -3. if the token is a binary operator, -3.1 pop the two top most operands - from the stack -3.2 apply the binary operator with the - two operands -3.3 push the result into the stack -4. finally, the value of the whole postfix +1. Read postfix expression token by token +2. If the token is an operand, push it into the stack +3. If the token is a binary operator, + 1. Pop the two top most operands from the stack + 2. Apply the binary operator with thetwo operands + 3. Push the result into the stack +4. Finally, the value of the whole postfix expression remains in the stack Using the above psuedocode the evaluation on the stack would be as follows: @@ -105,4 +102,11 @@ The above table describes the precedence and the associativity for each operator | - | Push token to stack | 4 4 2 * 1 | - ( / + | | 5 | Add token to output | 4 4 2 * 1 5 | - ( / + | | ) | * Pop stack to output * Pop stack | 4 4 2 * 1 5 - | / + | -| end | Pop entire stack to output | 4 4 2 * 1 5 - / + | | \ No newline at end of file +| end | Pop entire stack to output | 4 4 2 * 1 5 - / + | | + + +# See Also + +[Shunting yard algorithm on Wikipedia](https://en.wikipedia.org/wiki/Shunting-yard_algorithm) + +*Written for the Swift Algorithm Club by [Ali Hafizji](http://www.github.com/aliHafizji)* \ No newline at end of file From b6ab5205d84ed700e6fcd191cb71f1d0f005468a Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Mon, 29 Feb 2016 23:46:07 +1300 Subject: [PATCH 0071/1679] BFS Added tests for shortest path --- .../Contents.swift | 15 ++-- .../BreadthFirstSearchShortestPath.swift | 11 ++- Breadth-First Search/README.markdown | 14 +-- .../BreadthFirstSearchShortestPathTests.swift | 89 +++++++++++++++++++ .../Tests/Tests.xcodeproj/project.pbxproj | 10 ++- 5 files changed, 121 insertions(+), 18 deletions(-) create mode 100644 Breadth-First Search/Tests/BreadthFirstSearchShortestPathTests.swift diff --git a/Breadth-First Search/BreadthFirstSearch.playground/Pages/Shortest path example.xcplaygroundpage/Contents.swift b/Breadth-First Search/BreadthFirstSearch.playground/Pages/Shortest path example.xcplaygroundpage/Contents.swift index 175821efc..28cdc6093 100644 --- a/Breadth-First Search/BreadthFirstSearch.playground/Pages/Shortest path example.xcplaygroundpage/Contents.swift +++ b/Breadth-First Search/BreadthFirstSearch.playground/Pages/Shortest path example.xcplaygroundpage/Contents.swift @@ -1,7 +1,10 @@ -func breadthFirstSearchShortestPath(graph: Graph, source: Node) { +func breadthFirstSearchShortestPath(graph: Graph, source: Node) -> Graph { + let shortestPathGraph = graph.duplicate() + var queue = Queue() - queue.enqueue(source) - source.distance = 0 + let sourceInShortestPathsGraph = shortestPathGraph.findNodeWithLabel(source.label) + queue.enqueue(sourceInShortestPathsGraph) + sourceInShortestPathsGraph.distance = 0 while !queue.isEmpty { let current = queue.dequeue()! @@ -14,9 +17,8 @@ func breadthFirstSearchShortestPath(graph: Graph, source: Node) { } } - print(graph.nodes) + return shortestPathGraph } - /*: ![Animated example of a breadth-first search](Animated_BFS.gif) */ @@ -40,4 +42,5 @@ graph.addEdge(nodeC, neighbor: nodeF) graph.addEdge(nodeC, neighbor: nodeG) graph.addEdge(nodeE, neighbor: nodeH) -breadthFirstSearchShortestPath(graph, source: nodeA) +let shortestPathGraph = breadthFirstSearchShortestPath(graph, source: nodeA) +print(shortestPathGraph.nodes) diff --git a/Breadth-First Search/BreadthFirstSearchShortestPath.swift b/Breadth-First Search/BreadthFirstSearchShortestPath.swift index cb251cf0e..2e5a9c1d0 100644 --- a/Breadth-First Search/BreadthFirstSearchShortestPath.swift +++ b/Breadth-First Search/BreadthFirstSearchShortestPath.swift @@ -1,7 +1,10 @@ -func breadthFirstSearchShortestPath(graph: Graph, source: Node) { +func breadthFirstSearchShortestPath(graph: Graph, source: Node) -> Graph { + let shortestPathGraph = graph.duplicate() + var queue = Queue() - queue.enqueue(source) - source.distance = 0 + let sourceInShortestPathsGraph = shortestPathGraph.findNodeWithLabel(source.label) + queue.enqueue(sourceInShortestPathsGraph) + sourceInShortestPathsGraph.distance = 0 while !queue.isEmpty { let current = queue.dequeue()! @@ -14,5 +17,5 @@ func breadthFirstSearchShortestPath(graph: Graph, source: Node) { } } - print(graph.nodes) + return shortestPathGraph } diff --git a/Breadth-First Search/README.markdown b/Breadth-First Search/README.markdown index 9971cd081..8d3266d39 100644 --- a/Breadth-First Search/README.markdown +++ b/Breadth-First Search/README.markdown @@ -145,10 +145,13 @@ Continue until the queue is empty to calculate the shortest path to all other no Here's the code: ```swift -func breadthFirstSearchShortestPath(graph: Graph, source: Node) { +func breadthFirstSearchShortestPath(graph: Graph, source: Node) -> Graph { + let shortestPathGraph = graph.duplicate() + var queue = Queue() - queue.enqueue(source) - source.distance = 0 + let sourceInShortestPathsGraph = shortestPathGraph.findNodeWithLabel(source.label) + queue.enqueue(sourceInShortestPathsGraph) + sourceInShortestPathsGraph.distance = 0 while !queue.isEmpty { let current = queue.dequeue()! @@ -161,13 +164,14 @@ func breadthFirstSearchShortestPath(graph: Graph, source: Node) { } } - print(graph.nodes) + return shortestPathGraph } ``` Put this code in a playground and test it like so: ```swift -breadthFirstSearchShortestPath(graph, source: nodeA) +let shortestPathGraph = breadthFirstSearchShortestPath(graph, source: nodeA) +print(shortestPathGraph.nodes) // This will output: // Node(label: a, distance: 0), Node(label: b, distance: 1), Node(label: c, distance: 1), diff --git a/Breadth-First Search/Tests/BreadthFirstSearchShortestPathTests.swift b/Breadth-First Search/Tests/BreadthFirstSearchShortestPathTests.swift new file mode 100644 index 000000000..b13fac2d1 --- /dev/null +++ b/Breadth-First Search/Tests/BreadthFirstSearchShortestPathTests.swift @@ -0,0 +1,89 @@ +import XCTest + +class BreadthFirstSearchShortestPathTests: XCTestCase { + + func testShortestPathWhenGivenTree() { + let tree = Graph() + let nodeA = tree.addNode("a") + let nodeB = tree.addNode("b") + let nodeC = tree.addNode("c") + let nodeD = tree.addNode("d") + let nodeE = tree.addNode("e") + let nodeF = tree.addNode("f") + let nodeG = tree.addNode("g") + let nodeH = tree.addNode("h") + tree.addEdge(nodeA, neighbor: nodeB) + tree.addEdge(nodeA, neighbor: nodeC) + tree.addEdge(nodeB, neighbor: nodeD) + tree.addEdge(nodeB, neighbor: nodeE) + tree.addEdge(nodeC, neighbor: nodeF) + tree.addEdge(nodeC, neighbor: nodeG) + tree.addEdge(nodeE, neighbor: nodeH) + + let shortestPaths = breadthFirstSearchShortestPath(tree, source: nodeA) + + XCTAssertEqual(shortestPaths.findNodeWithLabel(nodeA.label).distance, 0) + XCTAssertEqual(shortestPaths.findNodeWithLabel(nodeB.label).distance, 1) + XCTAssertEqual(shortestPaths.findNodeWithLabel(nodeC.label).distance, 1) + XCTAssertEqual(shortestPaths.findNodeWithLabel(nodeD.label).distance, 2) + XCTAssertEqual(shortestPaths.findNodeWithLabel(nodeE.label).distance, 2) + XCTAssertEqual(shortestPaths.findNodeWithLabel(nodeF.label).distance, 2) + XCTAssertEqual(shortestPaths.findNodeWithLabel(nodeG.label).distance, 2) + XCTAssertEqual(shortestPaths.findNodeWithLabel(nodeH.label).distance, 3) + } + + func testShortestPathWhenGivenGraph() { + let graph = Graph() + + let nodeA = graph.addNode("a") + let nodeB = graph.addNode("b") + let nodeC = graph.addNode("c") + let nodeD = graph.addNode("d") + let nodeE = graph.addNode("e") + let nodeF = graph.addNode("f") + let nodeG = graph.addNode("g") + let nodeH = graph.addNode("h") + let nodeI = graph.addNode("i") + + graph.addEdge(nodeA, neighbor: nodeB) + graph.addEdge(nodeA, neighbor: nodeH) + graph.addEdge(nodeB, neighbor: nodeA) + graph.addEdge(nodeB, neighbor: nodeC) + graph.addEdge(nodeB, neighbor: nodeH) + graph.addEdge(nodeC, neighbor: nodeB) + graph.addEdge(nodeC, neighbor: nodeD) + graph.addEdge(nodeC, neighbor: nodeF) + graph.addEdge(nodeC, neighbor: nodeI) + graph.addEdge(nodeD, neighbor: nodeC) + graph.addEdge(nodeD, neighbor: nodeE) + graph.addEdge(nodeD, neighbor: nodeF) + graph.addEdge(nodeE, neighbor: nodeD) + graph.addEdge(nodeE, neighbor: nodeF) + graph.addEdge(nodeF, neighbor: nodeC) + graph.addEdge(nodeF, neighbor: nodeD) + graph.addEdge(nodeF, neighbor: nodeE) + graph.addEdge(nodeF, neighbor: nodeG) + graph.addEdge(nodeG, neighbor: nodeF) + graph.addEdge(nodeG, neighbor: nodeH) + graph.addEdge(nodeG, neighbor: nodeI) + graph.addEdge(nodeH, neighbor: nodeA) + graph.addEdge(nodeH, neighbor: nodeB) + graph.addEdge(nodeH, neighbor: nodeG) + graph.addEdge(nodeH, neighbor: nodeI) + graph.addEdge(nodeI, neighbor: nodeC) + graph.addEdge(nodeI, neighbor: nodeG) + graph.addEdge(nodeI, neighbor: nodeH) + + let shortestPaths = breadthFirstSearchShortestPath(graph, source: nodeA) + + XCTAssertEqual(shortestPaths.findNodeWithLabel(nodeA.label).distance, 0) + XCTAssertEqual(shortestPaths.findNodeWithLabel(nodeB.label).distance, 1) + XCTAssertEqual(shortestPaths.findNodeWithLabel(nodeC.label).distance, 2) + XCTAssertEqual(shortestPaths.findNodeWithLabel(nodeD.label).distance, 3) + XCTAssertEqual(shortestPaths.findNodeWithLabel(nodeE.label).distance, 4) + XCTAssertEqual(shortestPaths.findNodeWithLabel(nodeF.label).distance, 3) + XCTAssertEqual(shortestPaths.findNodeWithLabel(nodeG.label).distance, 2) + XCTAssertEqual(shortestPaths.findNodeWithLabel(nodeH.label).distance, 1) + XCTAssertEqual(shortestPaths.findNodeWithLabel(nodeI.label).distance, 2) + } +} \ No newline at end of file diff --git a/Breadth-First Search/Tests/Tests.xcodeproj/project.pbxproj b/Breadth-First Search/Tests/Tests.xcodeproj/project.pbxproj index b0e34b310..8946ba1a6 100644 --- a/Breadth-First Search/Tests/Tests.xcodeproj/project.pbxproj +++ b/Breadth-First Search/Tests/Tests.xcodeproj/project.pbxproj @@ -8,6 +8,7 @@ /* Begin PBXBuildFile section */ 83AACB421C844CED00DDAFC7 /* BreadthFirstSearchMinimumSpanningTreeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83AACB411C844CED00DDAFC7 /* BreadthFirstSearchMinimumSpanningTreeTests.swift */; }; + 83AACB441C8456D200DDAFC7 /* BreadthFirstSearchShortestPathTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83AACB431C8456D200DDAFC7 /* BreadthFirstSearchShortestPathTests.swift */; }; 83F9C9681C84437C00B3A87F /* BreadthFirstSearch.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83F9C9651C84437C00B3A87F /* BreadthFirstSearch.swift */; }; 83F9C9691C84437C00B3A87F /* BreadthFirstSearchMinimumSpanningTree.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83F9C9661C84437C00B3A87F /* BreadthFirstSearchMinimumSpanningTree.swift */; }; 83F9C96A1C84437C00B3A87F /* BreadthFirstSearchShortestPath.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83F9C9671C84437C00B3A87F /* BreadthFirstSearchShortestPath.swift */; }; @@ -22,6 +23,7 @@ 7B2BBC801C779D720067B71D /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 7B2BBC941C779E7B0067B71D /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; 83AACB411C844CED00DDAFC7 /* BreadthFirstSearchMinimumSpanningTreeTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BreadthFirstSearchMinimumSpanningTreeTests.swift; sourceTree = SOURCE_ROOT; }; + 83AACB431C8456D200DDAFC7 /* BreadthFirstSearchShortestPathTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BreadthFirstSearchShortestPathTests.swift; sourceTree = SOURCE_ROOT; }; 83F9C9651C84437C00B3A87F /* BreadthFirstSearch.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BreadthFirstSearch.swift; path = ../BreadthFirstSearch.swift; sourceTree = SOURCE_ROOT; }; 83F9C9661C84437C00B3A87F /* BreadthFirstSearchMinimumSpanningTree.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BreadthFirstSearchMinimumSpanningTree.swift; path = ../BreadthFirstSearchMinimumSpanningTree.swift; sourceTree = SOURCE_ROOT; }; 83F9C9671C84437C00B3A87F /* BreadthFirstSearchShortestPath.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BreadthFirstSearchShortestPath.swift; path = ../BreadthFirstSearchShortestPath.swift; sourceTree = SOURCE_ROOT; }; @@ -66,12 +68,13 @@ 83F9C96E1C84449D00B3A87F /* Graph.swift */, 83F9C96F1C84449D00B3A87F /* Node.swift */, 83F9C9701C84449D00B3A87F /* Queue.swift */, - 83F9C96B1C8443E800B3A87F /* BreadthFirstSearchTests.swift */, 83F9C9651C84437C00B3A87F /* BreadthFirstSearch.swift */, - 83F9C9661C84437C00B3A87F /* BreadthFirstSearchMinimumSpanningTree.swift */, 83F9C9671C84437C00B3A87F /* BreadthFirstSearchShortestPath.swift */, - 7B2BBC941C779E7B0067B71D /* Info.plist */, + 83F9C9661C84437C00B3A87F /* BreadthFirstSearchMinimumSpanningTree.swift */, + 83F9C96B1C8443E800B3A87F /* BreadthFirstSearchTests.swift */, + 83AACB431C8456D200DDAFC7 /* BreadthFirstSearchShortestPathTests.swift */, 83AACB411C844CED00DDAFC7 /* BreadthFirstSearchMinimumSpanningTreeTests.swift */, + 7B2BBC941C779E7B0067B71D /* Info.plist */, ); name = Tests; path = TestsTests; @@ -145,6 +148,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 83AACB441C8456D200DDAFC7 /* BreadthFirstSearchShortestPathTests.swift in Sources */, 83AACB421C844CED00DDAFC7 /* BreadthFirstSearchMinimumSpanningTreeTests.swift in Sources */, 83F9C9721C84449D00B3A87F /* Graph.swift in Sources */, 83F9C9691C84437C00B3A87F /* BreadthFirstSearchMinimumSpanningTree.swift in Sources */, From fa073ec9da6ec25430e99759d98af316f7aea7d1 Mon Sep 17 00:00:00 2001 From: Matthijs Hollemans Date: Mon, 29 Feb 2016 19:08:04 +0100 Subject: [PATCH 0072/1679] Small tweaks to text --- .../Contents.swift | 1 - Breadth-First Search/BreadthFirstSearch.swift | 1 - Breadth-First Search/README.markdown | 145 ++++++++++++------ 3 files changed, 99 insertions(+), 48 deletions(-) diff --git a/Breadth-First Search/BreadthFirstSearch.playground/Pages/Simple example.xcplaygroundpage/Contents.swift b/Breadth-First Search/BreadthFirstSearch.playground/Pages/Simple example.xcplaygroundpage/Contents.swift index 44a6a284e..ed655b591 100644 --- a/Breadth-First Search/BreadthFirstSearch.playground/Pages/Simple example.xcplaygroundpage/Contents.swift +++ b/Breadth-First Search/BreadthFirstSearch.playground/Pages/Simple example.xcplaygroundpage/Contents.swift @@ -12,7 +12,6 @@ func breadthFirstSearch(graph: Graph, source: Node) -> [String] { if !neighborNode.visited { queue.enqueue(neighborNode) neighborNode.visited = true - nodesExplored.append(neighborNode.label) } } diff --git a/Breadth-First Search/BreadthFirstSearch.swift b/Breadth-First Search/BreadthFirstSearch.swift index eb9fe30a6..31bb1c594 100644 --- a/Breadth-First Search/BreadthFirstSearch.swift +++ b/Breadth-First Search/BreadthFirstSearch.swift @@ -12,7 +12,6 @@ func breadthFirstSearch(graph: Graph, source: Node) -> [String] { if !neighborNode.visited { queue.enqueue(neighborNode) neighborNode.visited = true - nodesExplored.append(neighborNode.label) } } diff --git a/Breadth-First Search/README.markdown b/Breadth-First Search/README.markdown index 8d3266d39..584b37c1d 100644 --- a/Breadth-First Search/README.markdown +++ b/Breadth-First Search/README.markdown @@ -1,6 +1,6 @@ # Breadth-First Search -Breadth-first search (BFS) is an algorithm for traversing or searching [tree](../Tree/) or [graph](../Graph/) data structures. It starts at the tree source and explores the neighbor nodes first, before moving to the next level neighbors. +Breadth-first search (BFS) is an algorithm for traversing or searching [tree](../Tree/) or [graph](../Graph/) data structures. It starts at the tree source and explores the immediate neighbor nodes first, before moving to the next level neighbors. ## Animated example @@ -9,49 +9,67 @@ Breadth-first search (BFS) is an algorithm for traversing or searching [tree](.. Let's follow the animated example by using a [queue](../Queue/). Start with the source node ``a`` and add it to a queue. + ```swift queue.enqueue(a) ``` -The queue is now ``[ a ]``. Dequeue ``a`` and enqueue the neighbor nodes ``b`` and ``c``. + +The queue is now ``[ a ]``. Dequeue ``a`` and enqueue its two neighbor nodes ``b`` and ``c``. + ```swift -queue.dequeue(a) +queue.dequeue() // a queue.enqueue(b) queue.enqueue(c) ``` -The queue is now ``[ b, c ]``. Dequeue ``b`` and enqueue the neighbor nodes ``d`` and ``e``. + +The queue is now ``[ b, c ]``. Dequeue ``b`` and enqueue `b`'s neighbor nodes ``d`` and ``e``. + ```swift -queue.dequeue(b) +queue.dequeue() // b queue.enqueue(d) queue.enqueue(e) ``` -The queue is now ``[ c, d, e ]``. Dequeue ``c`` and enqueue the neighbor nodes ``f`` and ``g``. + +The queue is now ``[ c, d, e ]``. Dequeue ``c`` and enqueue `c`'s neighbor nodes ``f`` and ``g``. + ```swift -queue.dequeue(c) +queue.dequeue() // c queue.enqueue(f) queue.enqueue(g) ``` + The queue is now ``[ d, e, f, g ]``. Dequeue ``d`` which has no neighbor nodes. + ```swift -queue.dequeue(d) +queue.dequeue() // d ``` -The queue is now ``[ e, f, g ]``. Dequeue ``e`` and enqueue the single neighbor node ``h``. + +The queue is now ``[ e, f, g ]``. Dequeue ``e`` and enqueue its single neighbor node ``h``. + ```swift -queue.dequeue(e) +queue.dequeue() // e queue.enqueue(h) ``` + The queue is now ``[ f, g, h ]``. Dequeue ``f`` which has no neighbor nodes. + ```swift -queue.dequeue(f) +queue.dequeue() // f ``` + The queue is now ``[ g, h ]``. Dequeue ``g`` which has no neighbor nodes. + ```swift -queue.dequeue(g) +queue.dequeue() // g ``` + The queue is now ``[ h ]``. Dequeue ``h`` which has no neighbor nodes. + ```swift -queue.dequeue(h) +queue.dequeue() // h ``` -The queue is now empty which means all nodes have been explored. + +The queue is now empty, meaning that all nodes have been explored. The order in which the nodes were explored is `a`, `b`, `c`, `d`, `e`, `f`, `g`, `h`. ## The code @@ -72,7 +90,6 @@ func breadthFirstSearch(graph: Graph, source: Node) -> [String] { if !neighborNode.visited { queue.enqueue(neighborNode) neighborNode.visited = true - nodesExplored.append(neighborNode.label) } } @@ -83,8 +100,9 @@ func breadthFirstSearch(graph: Graph, source: Node) -> [String] { ``` Put this code in a playground and test it like so: + ```swift -let graph = Graph() // Representing the graph from the animated example +let graph = Graph() // Representing the graph from the animated example let nodeA = graph.addNode("a") let nodeB = graph.addNode("b") @@ -104,46 +122,53 @@ graph.addEdge(nodeC, neighbor: nodeG) graph.addEdge(nodeE, neighbor: nodeH) let nodesExplored = breadthFirstSearch(graph, source: nodeA) -print(nodesExplored) // This will output: ["a", "b", "c", "d", "e", "f", "g", "h"] +print(nodesExplored) ``` +This will output: `["a", "b", "c", "d", "e", "f", "g", "h"]` + ## Applications Breadth-first search can be used to solve many problems, for example: -* Computing the shortest path between a source node and each of the other nodes - * Only for unweighted graphs +* Computing the shortest path between a source node and each of the other nodes (only for unweighted graphs) * Calculating the minimum spanning tree on an unweighted graph ## Shortest path example -Breadth-first search can be used to compute the [shortest path](../Shortest Path/) between a source node and each of the other nodes because it explores all of the neighbor nodes before moving to the next level neighbors. Let's follow the animated example and calculate the shortest path to all the other nodes: +Breadth-first search can be used to compute the [shortest path](../Shortest Path/) between a source node and each of the other nodes in the tree or graph, because it explores all of the immediate neighbor nodes first before moving to the next level neighbors. + +Let's follow the animated example and calculate the shortest path to all the other nodes. Start with the source node ``a`` and add it to a queue with a distance of ``0``. -Start with the source node ``a`` and add it to a queue with a distance of ``0``. ```swift queue.enqueue(a) a.distance = 0 ``` -The queue is now ``[ a ]``. Dequeue ``a`` and enqueue the neighbor nodes ``b`` and ``c`` with a distance of ``1``. + +The queue is now ``[ a ]``. Dequeue ``a`` and enqueue its two neighbor nodes ``b`` and ``c`` with a distance of ``1``. + ```swift -queue.dequeue(a) +queue.dequeue() // a queue.enqueue(b) -b.distance = a.distance + 1 // result: 1 +b.distance = a.distance + 1 // result: 1 queue.enqueue(c) -c.distance = a.distance + 1 // result: 1 +c.distance = a.distance + 1 // result: 1 ``` -The queue is now ``[ b, c ]``. Dequeue ``b`` and enqueue the neighbor nodes ``d`` and ``e`` with a distance of ``2``. + +The queue is now ``[ b, c ]``. Dequeue ``b`` and enqueue `b`'s neighbor nodes ``d`` and ``e`` with a distance of ``2``. + ```swift -queue.dequeue(b) +queue.dequeue() // b queue.enqueue(d) -d.distance = b.distance + 1 // result: 2 +d.distance = b.distance + 1 // result: 2 queue.enqueue(e) -e.distance = b.distance + 1 // result: 2 +e.distance = b.distance + 1 // result: 2 ``` Continue until the queue is empty to calculate the shortest path to all other nodes. Here's the code: + ```swift func breadthFirstSearchShortestPath(graph: Graph, source: Node) -> Graph { let shortestPathGraph = graph.duplicate() @@ -169,19 +194,21 @@ func breadthFirstSearchShortestPath(graph: Graph, source: Node) -> Graph { ``` Put this code in a playground and test it like so: + ```swift let shortestPathGraph = breadthFirstSearchShortestPath(graph, source: nodeA) print(shortestPathGraph.nodes) - -// This will output: -// Node(label: a, distance: 0), Node(label: b, distance: 1), Node(label: c, distance: 1), -// Node(label: d, distance: 2), Node(label: e, distance: 2), Node(label: f, distance: 2), -// Node(label: g, distance: 2), Node(label: h, distance: 3) ``` +This will output: + + Node(label: a, distance: 0), Node(label: b, distance: 1), Node(label: c, distance: 1), + Node(label: d, distance: 2), Node(label: e, distance: 2), Node(label: f, distance: 2), + Node(label: g, distance: 2), Node(label: h, distance: 3) + ## Minimum spanning tree example -Breadth-first search can be used to calculate the [minimum spanning tree](../Minimum Spanning Tree/) on an unweighted graph. +Breadth-first search can be used to calculate the [minimum spanning tree](../Minimum Spanning Tree/) on an unweighted graph. A minimum spanning tree describes a path that contains the smallest number of edges that are needed to visit every node in the graph. Let's calculate the minimum spanning tree for the following graph: @@ -190,71 +217,92 @@ Let's calculate the minimum spanning tree for the following graph: *Note: the minimum spanning tree is represented by the bold edges.* Start with the source node ``a`` and add it to a queue and mark it as visited. + ```swift queue.enqueue(a) a.visited = true ``` -The queue is now ``[ a ]``. Dequeue ``a`` and enqueue the neighbor nodes ``b`` and ``h`` and mark them as visited. + +The queue is now ``[ a ]``. Dequeue ``a`` and enqueue its immediate neighbor nodes ``b`` and ``h`` and mark them as visited. + ```swift -queue.dequeue(a) +queue.dequeue() // a queue.enqueue(b) b.visited = true queue.enqueue(h) h.visited = true ``` + The queue is now ``[ b, h ]``. Dequeue ``b`` and enqueue the neighbor node ``c`` mark it as visited. Remove the edge between ``b`` to ``h`` because ``h`` has already been visited. + ```swift -queue.dequeue(b) +queue.dequeue() // b queue.enqueue(c) c.visited = true b.removeEdgeTo(h) ``` + The queue is now ``[ h, c ]``. Dequeue ``h`` and enqueue the neighbor nodes ``g`` and ``i`` and mark them as visited. + ```swift -queue.dequeue(h) +queue.dequeue() // h queue.enqueue(g) g.visited = true queue.enqueue(i) i.visited = true ``` + The queue is now ``[ c, g, i ]``. Dequeue ``c`` and enqueue the neighbor nodes ``d`` and ``f`` and mark them as visited. Remove the edge between ``c`` to ``i`` because ``i`` has already been visited. + ```swift -queue.dequeue(c) +queue.dequeue() // c queue.enqueue(d) d.visited = true queue.enqueue(f) f.visited = true c.removeEdgeTo(i) ``` + The queue is now ``[ g, i, d, f ]``. Dequeue ``g`` and remove the edges between ``g`` to ``f`` and ``g`` to ``i`` because ``f`` and ``i`` have already been visited. + ```swift -queue.dequeue(g) +queue.dequeue() // g g.removeEdgeTo(f) g.removeEdgeTo(i) ``` + The queue is now ``[ i, d, f ]``. Dequeue ``i``. + ```swift -queue.dequeue(i) +queue.dequeue() // i ``` + The queue is now ``[ d, f ]``. Dequeue ``d`` and enqueue the neighbor node ``e`` mark it as visited. Remove the edge between ``d`` to ``f`` because ``f`` has already been visited. + ```swift -queue.dequeue(d) +queue.dequeue() // d queue.enqueue(e) e.visited = true d.removeEdgeTo(f) ``` + The queue is now ``[ f, e ]``. Dequeue ``f``. Remove the edge between ``f`` to ``e`` because ``e`` has already been visited. + ```swift -queue.dequeue(f) +queue.dequeue() // f f.removeEdgeTo(e) ``` + The queue is now ``[ e ]``. Dequeue ``e``. + ```swift -queue.dequeue(e) +queue.dequeue() // e ``` -The queue is now empty which means the minimum spanning tree has been computed. + +The queue is now empty, which means the minimum spanning tree has been computed. Here's the code: + ```swift func breadthFirstSearchMinimumSpanningTree(graph: Graph, source: Node) -> Graph { let minimumSpanningTree = graph.duplicate() @@ -280,7 +328,11 @@ func breadthFirstSearchMinimumSpanningTree(graph: Graph, source: Node) -> Graph return minimumSpanningTree } ``` + +This function returns a new `Graph` object that describes just the minimum spanning tree. In the figure, that would be the graph containing just the bold edges. + Put this code in a playground and test it like so: + ```swift let graph = Graph() @@ -331,6 +383,7 @@ print(minimumSpanningTree) // [node: a edges: ["b", "h"]] // [node: d edges: ["e"]] // [node: h edges: ["g", "i"]] ``` + ## See also [Graph](../Graph/), [Tree](../Tree/), [Queues](../Queue/), [Shortest Path](../Shortest Path/), [Minimum Spanning Tree](../Minimum Spanning Tree/). From d81b544453c8221d77300cddaf00325975958258 Mon Sep 17 00:00:00 2001 From: Matthijs Hollemans Date: Mon, 29 Feb 2016 19:34:11 +0100 Subject: [PATCH 0073/1679] Small tweaks to the text and code Don't need to have a duplicate copy of Stack in this folder --- README.markdown | 1 + Shunting Yard/README.markdown | 55 +++--- .../Contents.swift | 67 +++---- .../Sources/Stack.swift | 0 .../contents.xcplayground | 0 .../timeline.xctimeline | 0 ...YardAlgorithm.swift => ShuntingYard.swift} | 170 ++++++++---------- Shunting Yard/Stack.swift | 43 ----- 8 files changed, 128 insertions(+), 208 deletions(-) rename Shunting Yard/{Shunting Yard.playground => ShuntingYard.playground}/Contents.swift (77%) rename Shunting Yard/{Shunting Yard.playground => ShuntingYard.playground}/Sources/Stack.swift (100%) rename Shunting Yard/{Shunting Yard.playground => ShuntingYard.playground}/contents.xcplayground (100%) rename Shunting Yard/{Shunting Yard.playground => ShuntingYard.playground}/timeline.xctimeline (100%) rename Shunting Yard/{ShuntingYardAlgorithm.swift => ShuntingYard.swift} (54%) delete mode 100644 Shunting Yard/Stack.swift diff --git a/README.markdown b/README.markdown index 650ad2f57..579e7c182 100644 --- a/README.markdown +++ b/README.markdown @@ -91,6 +91,7 @@ Bad sorting algorithms (don't use these!): - [Greatest Common Divisor (GCD)](GCD/). Special bonus: the least common multiple. - [Permutations and Combinations](Combinatorics/). Get your combinatorics on! +- [Shunting Yard Algorithm](Shunting Yard/). Convert infix expressions to postfix. - Statistics ### Machine learning diff --git a/Shunting Yard/README.markdown b/Shunting Yard/README.markdown index 3668888b2..6d9332629 100644 --- a/Shunting Yard/README.markdown +++ b/Shunting Yard/README.markdown @@ -1,29 +1,24 @@ # Shunting Yard Algorithm -Any mathematical expression that we write is expressed in a notation known as Infix Notation. +Any mathematical expression that we write is expressed in a notation known as *infix notation*. For example: **A + B * C** -In the above expression the operator is placed between operands hence the expression is said to be in Infix form. -If you think about it any expression that you write on a piece of paper will always be in infix form. This is what we humans understand. +In the above expression the operator is placed between operands, hence the expression is said to be in *infix* form. If you think about it, any expression that you write on a piece of paper will always be in infix form. This is what we humans understand. -Now, think about the way the above expression is evaluated, you would first multiply B and C then add the result to A. This is because multiplication has -higher precedence than addition. We humans can easily understand the precedence of operators, but a machine needs to be given instructions about each operator. If you were to -write an algorithm that parsed and evaluated the infix notation you will realize that it's a tedious process. You'd have to parse the expression -multiple times to know what operation to perform first. As the number of operators increase so does the complexity. +When the above expression is evaluated, you would first multiply **B** and **C**, and then add the result to **A**. This is because multiplication has higher precedence than addition. We humans can easily understand the precedence of operators, but a machine needs to be given instructions about each operator. -## Postfix notations / Reverse Polish Notation +If you were to write an algorithm that parsed and evaluated the infix notation you will realize that it's a tedious process. You'd have to parse the expression multiple times to know what operation to perform first. As the number of operators increase so does the complexity. -An expression when represented in postfix form will not have any brackets and neither will you have to worry about scanning for operator precedence. This makes it easy for the computer to evaluate -expressions since the order in which the operator need to be applied is fixed. +## Postfix notations / Reverse Polish Notation -For example: +In postfix notation, also known as Reverse Polish Notation or RPN, the operators come after the corresponding operands. Here is the postfix representation of the example from the previous section: **A B C * +** -The above is the postfix representation of the example in the previous section. The operators come after the corresponding operands. +An expression when represented in postfix form will not have any brackets and neither will you have to worry about scanning for operator precedence. This makes it easy for the computer to evaluate expressions, since the order in which the operators need to be applied is fixed. ### Evaluating a postfix expression @@ -33,12 +28,11 @@ A stack is used to evaluate a postfix expression. Here is the pseudocode: 2. If the token is an operand, push it into the stack 3. If the token is a binary operator, 1. Pop the two top most operands from the stack - 2. Apply the binary operator with thetwo operands + 2. Apply the binary operator to the two operands 3. Push the result into the stack -4. Finally, the value of the whole postfix - expression remains in the stack +4. Finally, the value of the whole postfix expression remains in the stack -Using the above psuedocode the evaluation on the stack would be as follows: +Using the above pseudocode, the evaluation on the stack would be as follows: | Expression | Stack | | ------------- | --------| @@ -51,23 +45,23 @@ Using the above psuedocode the evaluation on the stack would be as follows: Where **D = B * C** and **E = A + D.** -As seen above a postfix operation is relatively easy to evaluate as the order in which the operators need to be applied is predecided. +As seen above, a postfix operation is relatively easy to evaluate as the order in which the operators need to be applied is pre-decided. -## Shunting yard algorithm +## Dijkstra's shunting yard algorithm -The Shunting yard algorithm was invented by Edsger Dijkstra to convert an infix expression to postfix. Many calculators use this algorithm to convert the expression being entered to postfix form. +The shunting yard algorithm was invented by Edsger Dijkstra to convert an infix expression to postfix. Many calculators use this algorithm to convert the expression being entered to postfix form. Here is the psedocode of the algorithm: -1. For all the input tokens +1. For all the input tokens: 1. Read the next token 2. If token is an operator (x) 1. While there is an operator (y) at the top of the operators stack and either (x) is left-associative and its precedence is less or equal to that of (y), or (x) is right-associative and its precedence is less than (y) 1. Pop (y) from the stack 2. Add (y) output buffer 2. Push (x) on the stack - 3. Else If token is left parenthesis, then push it on the stack - 4. Else If token is a right parenthesis + 3. Else if token is left parenthesis, then push it on the stack + 4. Else if token is a right parenthesis 1. Until the top token (from the stack) is left parenthesis, pop from the stack to the output buffer 2. Also pop the left parenthesis but don’t include it in the output buffer 7. Else add token to output buffer @@ -75,10 +69,12 @@ Here is the psedocode of the algorithm: ### How does it work -Let's take a small example and see how the psuedocode works. +Let's take a small example and see how the pseudocode works. **4 + 4 * 2 / ( 1 - 5 )** +The following table describes the precedence and the associativity for each operator. The same values are used in the algorithm. + | Operator | Precedence | Associativity | | ---------| -------------| ----------------| | ^ | 10 | Right | @@ -87,25 +83,28 @@ Let's take a small example and see how the psuedocode works. | + | 0 | Left | | - | 0 | Left | -The above table describes the precedence and the associativity for each operator. The same values are used in the algorithm. +Here we go: | Token | Action | Output | Operator stack | |-------|---------------------------------------------|-------------------|----------------| -| 3 | Add token to output | 4 | | +| 4 | Add token to output | 4 | | | + | Push token to stack | 4 | + | | 4 | Add token to output | 4 4 | + | | * | Push token to stack | 4 4 | * + | | 2 | Add token to output | 4 4 2 | * + | -| / | * Pop stack to output * Push token to stack | 4 4 2 * | / + | +| / | Pop stack to output, Push token to stack | 4 4 2 * | / + | | ( | Push token to stack | 4 4 2 * | ( / + | | 1 | Add token to output | 4 4 2 * 1 | ( / + | | - | Push token to stack | 4 4 2 * 1 | - ( / + | | 5 | Add token to output | 4 4 2 * 1 5 | - ( / + | -| ) | * Pop stack to output * Pop stack | 4 4 2 * 1 5 - | / + | +| ) | Pop stack to output, Pop stack | 4 4 2 * 1 5 - | / + | | end | Pop entire stack to output | 4 4 2 * 1 5 - / + | | +We end up with the postfix expression: + +** 4 4 2 * 1 5 - / + ** -# See Also +# See also [Shunting yard algorithm on Wikipedia](https://en.wikipedia.org/wiki/Shunting-yard_algorithm) diff --git a/Shunting Yard/Shunting Yard.playground/Contents.swift b/Shunting Yard/ShuntingYard.playground/Contents.swift similarity index 77% rename from Shunting Yard/Shunting Yard.playground/Contents.swift rename to Shunting Yard/ShuntingYard.playground/Contents.swift index f70f36c5a..52b952d1f 100644 --- a/Shunting Yard/Shunting Yard.playground/Contents.swift +++ b/Shunting Yard/ShuntingYard.playground/Contents.swift @@ -1,7 +1,5 @@ //: Playground - noun: a place where people can play -import Foundation - internal enum OperatorAssociativity { case LeftAssociative case RightAssociative @@ -54,19 +52,18 @@ public enum TokenType: CustomStringConvertible { } public struct OperatorToken: CustomStringConvertible { - - var operatorType: OperatorType + let operatorType: OperatorType init(operatorType: OperatorType) { self.operatorType = operatorType } - var precedance: Int { + var precedence: Int { switch operatorType { case .Add, .Subtract: return 0 case .Divide, .Multiply, .Percent: - return 5; + return 5 case .Exponent: return 10 } @@ -87,22 +84,15 @@ public struct OperatorToken: CustomStringConvertible { } func <=(left: OperatorToken, right: OperatorToken) -> Bool { - if left.precedance <= right.precedance { - return true - } - return false + return left.precedence <= right.precedence } func <(left: OperatorToken, right: OperatorToken) -> Bool { - if left.precedance < right.precedance { - return true - } - return false + return left.precedence < right.precedence } public struct Token: CustomStringConvertible { - - var tokenType: TokenType + let tokenType: TokenType init(tokenType: TokenType) { self.tokenType = tokenType @@ -136,9 +126,9 @@ public struct Token: CustomStringConvertible { var operatorToken: OperatorToken? { switch tokenType { - case .Operator(let operatorToken): + case .Operator(let operatorToken): return operatorToken - default: + default: return nil } } @@ -149,8 +139,7 @@ public struct Token: CustomStringConvertible { } public class InfixExpressionBuilder { - - private var expression = Array() + private var expression = [Token]() public func addOperator(operatorType: OperatorType) -> InfixExpressionBuilder { expression.append(Token(operatorType: operatorType)) @@ -172,15 +161,15 @@ public class InfixExpressionBuilder { return self } - public func build() -> Array { + public func build() -> [Token] { // Maybe do some validation here return expression } } // This returns the result of the shunting yard algorithm -public func reversePolishNotation(expression: Array) -> String { - +public func reversePolishNotation(expression: [Token]) -> String { + var tokenStack = Stack() var reversePolishNotation = [Token]() @@ -188,40 +177,31 @@ public func reversePolishNotation(expression: Array) -> String { switch token.tokenType { case .Operand(_): reversePolishNotation.append(token) - break + case .OpenBracket: tokenStack.push(token) - break + case .CloseBracket: - while tokenStack.count > 0 { - if let tempToken = tokenStack.pop() where !tempToken.isOpenBracket { - reversePolishNotation.append(tempToken) - } else { - break - } + while tokenStack.count > 0, let tempToken = tokenStack.pop() where !tempToken.isOpenBracket { + reversePolishNotation.append(tempToken) } - break + case .Operator(let operatorToken): - for tempToken in tokenStack.generate() { if !tempToken.isOperator { break } if let tempOperatorToken = tempToken.operatorToken { - if operatorToken.associativity == .LeftAssociative && operatorToken <= tempOperatorToken || operatorToken.associativity == .RightAssociative && operatorToken < tempOperatorToken { - reversePolishNotation.append(tokenStack.pop()!) } else { break } } } - tokenStack.push(token) - break } } @@ -229,9 +209,14 @@ public func reversePolishNotation(expression: Array) -> String { reversePolishNotation.append(tokenStack.pop()!) } - return reversePolishNotation.map({token in - return token.description - }).joinWithSeparator(" ") + return reversePolishNotation.map({token in token.description}).joinWithSeparator(" ") } -print(reversePolishNotation(InfixExpressionBuilder().addOperand(3).addOperator(.Add).addOperand(4).addOperator(.Multiply).addOperand(2).addOperator(.Divide).addOpenBracket().addOperand(1).addOperator(.Subtract).addOperand(5).addCloseBracket().addOperator(.Exponent).addOperand(2).addOperator(.Exponent).addOperand(3).build())) + +// Simple demo + +let expr = InfixExpressionBuilder().addOperand(3).addOperator(.Add).addOperand(4).addOperator(.Multiply).addOperand(2).addOperator(.Divide).addOpenBracket().addOperand(1).addOperator(.Subtract).addOperand(5).addCloseBracket().addOperator(.Exponent).addOperand(2).addOperator(.Exponent).addOperand(3).build() + +print(expr.description) +print(reversePolishNotation(expr)) + diff --git a/Shunting Yard/Shunting Yard.playground/Sources/Stack.swift b/Shunting Yard/ShuntingYard.playground/Sources/Stack.swift similarity index 100% rename from Shunting Yard/Shunting Yard.playground/Sources/Stack.swift rename to Shunting Yard/ShuntingYard.playground/Sources/Stack.swift diff --git a/Shunting Yard/Shunting Yard.playground/contents.xcplayground b/Shunting Yard/ShuntingYard.playground/contents.xcplayground similarity index 100% rename from Shunting Yard/Shunting Yard.playground/contents.xcplayground rename to Shunting Yard/ShuntingYard.playground/contents.xcplayground diff --git a/Shunting Yard/Shunting Yard.playground/timeline.xctimeline b/Shunting Yard/ShuntingYard.playground/timeline.xctimeline similarity index 100% rename from Shunting Yard/Shunting Yard.playground/timeline.xctimeline rename to Shunting Yard/ShuntingYard.playground/timeline.xctimeline diff --git a/Shunting Yard/ShuntingYardAlgorithm.swift b/Shunting Yard/ShuntingYard.swift similarity index 54% rename from Shunting Yard/ShuntingYardAlgorithm.swift rename to Shunting Yard/ShuntingYard.swift index dbaba475c..1da67990d 100644 --- a/Shunting Yard/ShuntingYardAlgorithm.swift +++ b/Shunting Yard/ShuntingYard.swift @@ -6,8 +6,6 @@ // // -import Foundation - internal enum OperatorAssociativity { case LeftAssociative case RightAssociative @@ -23,18 +21,18 @@ public enum OperatorType: CustomStringConvertible { public var description: String { switch self { - case Add: - return "+" - case Subtract: - return "-" - case Divide: - return "/" - case Multiply: - return "*" - case Percent: - return "%" - case Exponent: - return "^" + case Add: + return "+" + case Subtract: + return "-" + case Divide: + return "/" + case Multiply: + return "*" + case Percent: + return "%" + case Exponent: + return "^" } } } @@ -47,43 +45,42 @@ public enum TokenType: CustomStringConvertible { public var description: String { switch self { - case OpenBracket: - return "(" - case CloseBracket: - return ")" - case Operator(let operatorToken): - return operatorToken.description - case Operand(let value): - return "\(value)" + case OpenBracket: + return "(" + case CloseBracket: + return ")" + case Operator(let operatorToken): + return operatorToken.description + case Operand(let value): + return "\(value)" } } } public struct OperatorToken: CustomStringConvertible { - - var operatorType: OperatorType + let operatorType: OperatorType init(operatorType: OperatorType) { self.operatorType = operatorType } - var precedance: Int { + var precedence: Int { switch operatorType { - case .Add, .Subtract: - return 0 - case .Divide, .Multiply, .Percent: - return 5; - case .Exponent: - return 10 + case .Add, .Subtract: + return 0 + case .Divide, .Multiply, .Percent: + return 5 + case .Exponent: + return 10 } } var associativity: OperatorAssociativity { switch operatorType { - case .Add, .Subtract, .Divide, .Multiply, .Percent: - return .LeftAssociative; - case .Exponent: - return .RightAssociative + case .Add, .Subtract, .Divide, .Multiply, .Percent: + return .LeftAssociative; + case .Exponent: + return .RightAssociative } } @@ -93,22 +90,15 @@ public struct OperatorToken: CustomStringConvertible { } func <=(left: OperatorToken, right: OperatorToken) -> Bool { - if left.precedance <= right.precedance { - return true - } - return false + return left.precedence <= right.precedence } func <(left: OperatorToken, right: OperatorToken) -> Bool { - if left.precedance < right.precedance { - return true - } - return false + return left.precedence < right.precedence } public struct Token: CustomStringConvertible { - - var tokenType: TokenType + let tokenType: TokenType init(tokenType: TokenType) { self.tokenType = tokenType @@ -124,28 +114,28 @@ public struct Token: CustomStringConvertible { var isOpenBracket: Bool { switch tokenType { - case .OpenBracket: - return true - default: - return false + case .OpenBracket: + return true + default: + return false } } var isOperator: Bool { switch tokenType { - case .Operator(_): - return true - default: - return false + case .Operator(_): + return true + default: + return false } } var operatorToken: OperatorToken? { switch tokenType { - case .Operator(let operatorToken): - return operatorToken - default: - return nil + case .Operator(let operatorToken): + return operatorToken + default: + return nil } } @@ -155,8 +145,7 @@ public struct Token: CustomStringConvertible { } public class InfixExpressionBuilder { - - private var expression = Array() + private var expression = [Token]() public func addOperator(operatorType: OperatorType) -> InfixExpressionBuilder { expression.append(Token(operatorType: operatorType)) @@ -178,56 +167,47 @@ public class InfixExpressionBuilder { return self } - public func build() -> Array { + public func build() -> [Token] { // Maybe do some validation here return expression } } // This returns the result of the shunting yard algorithm -public func reversePolishNotation(expression: Array) -> String { - +public func reversePolishNotation(expression: [Token]) -> String { + var tokenStack = Stack() var reversePolishNotation = [Token]() for token in expression { switch token.tokenType { - case .Operand(_): - reversePolishNotation.append(token) - break - case .OpenBracket: - tokenStack.push(token) - break - case .CloseBracket: - while tokenStack.count > 0 { - if let tempToken = tokenStack.pop() where !tempToken.isOpenBracket { + case .Operand(_): + reversePolishNotation.append(token) + + case .OpenBracket: + tokenStack.push(token) + + case .CloseBracket: + while tokenStack.count > 0, let tempToken = tokenStack.pop() where !tempToken.isOpenBracket { reversePolishNotation.append(tempToken) - } else { - break } - } - break - case .Operator(let operatorToken): - - for tempToken in tokenStack.generate() { - if !tempToken.isOperator { - break - } - - if let tempOperatorToken = tempToken.operatorToken { + + case .Operator(let operatorToken): + for tempToken in tokenStack.generate() { + if !tempToken.isOperator { + break + } - if operatorToken.associativity == .LeftAssociative && operatorToken <= tempOperatorToken - || operatorToken.associativity == .RightAssociative && operatorToken < tempOperatorToken { - + if let tempOperatorToken = tempToken.operatorToken { + if operatorToken.associativity == .LeftAssociative && operatorToken <= tempOperatorToken + || operatorToken.associativity == .RightAssociative && operatorToken < tempOperatorToken { reversePolishNotation.append(tokenStack.pop()!) - } else { - break + } else { + break + } } } - } - - tokenStack.push(token) - break + tokenStack.push(token) } } @@ -235,7 +215,5 @@ public func reversePolishNotation(expression: Array) -> String { reversePolishNotation.append(tokenStack.pop()!) } - return reversePolishNotation.map({token in - return token.description - }).joinWithSeparator(" ") -} \ No newline at end of file + return reversePolishNotation.map({token in token.description}).joinWithSeparator(" ") +} diff --git a/Shunting Yard/Stack.swift b/Shunting Yard/Stack.swift deleted file mode 100644 index 93feb2ca1..000000000 --- a/Shunting Yard/Stack.swift +++ /dev/null @@ -1,43 +0,0 @@ -import Foundation - -public struct Stack { - private var array = [T]() - - public init() { - array = [] - } - - public var isEmpty: Bool { - return array.isEmpty - } - - public var count: Int { - return array.count - } - - public mutating func push(element: T) { - array.append(element) - } - - public mutating func pop() -> T? { - if isEmpty { - return nil - } else { - return array.removeLast() - } - } - - public func peek() -> T? { - return array.last - } -} - -extension Stack: SequenceType { - public func generate() -> AnyGenerator { - var curr = self - return anyGenerator { - _ -> T? in - return curr.pop() - } - } -} \ No newline at end of file From 5721ee725ddf5aede392b844e4ad8bc8168a448c Mon Sep 17 00:00:00 2001 From: Matthijs Hollemans Date: Mon, 29 Feb 2016 19:35:53 +0100 Subject: [PATCH 0074/1679] Fix bold text --- Shunting Yard/README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Shunting Yard/README.markdown b/Shunting Yard/README.markdown index 6d9332629..d4d7c3e22 100644 --- a/Shunting Yard/README.markdown +++ b/Shunting Yard/README.markdown @@ -102,7 +102,7 @@ Here we go: We end up with the postfix expression: -** 4 4 2 * 1 5 - / + ** +**4 4 2 * 1 5 - / +** # See also From 35a8ed4c18a6978063306596d8443350a424becf Mon Sep 17 00:00:00 2001 From: jamil Date: Mon, 29 Feb 2016 22:00:48 -0500 Subject: [PATCH 0075/1679] Add code for Bloom Filter, tests --- Bloom Filter/BloomFilter.swift | 58 ++++++++++++++ .../BloomFilterTests/BloomFilterTests.swift | 78 +++++++++++++++++++ Bloom Filter/BloomFilterTests/Info.plist | 24 ++++++ 3 files changed, 160 insertions(+) create mode 100644 Bloom Filter/BloomFilter.swift create mode 100644 Bloom Filter/BloomFilterTests/BloomFilterTests.swift create mode 100644 Bloom Filter/BloomFilterTests/Info.plist diff --git a/Bloom Filter/BloomFilter.swift b/Bloom Filter/BloomFilter.swift new file mode 100644 index 000000000..6f5232b0d --- /dev/null +++ b/Bloom Filter/BloomFilter.swift @@ -0,0 +1,58 @@ +import Foundation + +public class BloomFilter { + private(set) private var arr: [Bool] + private(set) private var hashFunctions: [T -> Int] + + public init(size: Int = 1024, hashFunctions: [T -> Int]) { + self.arr = Array(count: size, repeatedValue: false) + self.hashFunctions = hashFunctions + } + + private func computeHashes(value: T) -> [Int] { + return hashFunctions.map() { hashFunc in + abs(hashFunc(value) % self.arr.count) + } + } + + public func insert(toInsert: T) { + let hashValues: [Int] = self.computeHashes(toInsert) + + for hashValue in hashValues { + self.arr[hashValue] = true + } + } + + public func insert(values: [T]) { + for value in values { + self.insert(value) + } + } + + public func query(value: T) -> Bool { + let hashValues = self.computeHashes(value) + + // Map hashes to indices in the Bloom filter + let results = hashValues.map() { hashValue in + self.arr[hashValue] + } + + // All values must be 'true' for the query to return true + + // This does NOT imply that the value is in the Bloom filter, + // only that it may be. If the query returns false, however, + // you can be certain that the value was not added. + + let exists = results.reduce(true, combine: { $0 && $1 }) + + return exists + } + + public func isEmpty() -> Bool { + // Reduce list; as soon as the reduction hits a 'true' value, the && condition will fail + return arr.reduce(true) { prev, next in + prev && !next + } + } + +} \ No newline at end of file diff --git a/Bloom Filter/BloomFilterTests/BloomFilterTests.swift b/Bloom Filter/BloomFilterTests/BloomFilterTests.swift new file mode 100644 index 000000000..bb11f80aa --- /dev/null +++ b/Bloom Filter/BloomFilterTests/BloomFilterTests.swift @@ -0,0 +1,78 @@ +import XCTest +import BloomFilter + +/* Two hash functions, adapted from + http://www.cse.yorku.ca/~oz/hash.html */ + + +func djb2(x: String) -> Int { + var hash = 5381 + + for char in x.characters { + hash = ((hash << 5) &+ hash) &+ char.hashValue + } + + return Int(hash) +} + +func sdbm(x: String) -> Int { + var hash = 0 + + for char in x.characters { + hash = char.hashValue &+ (hash << 6) &+ (hash << 16) &- hash; + } + + return Int(hash) +} + + +class BloomFilterTests: XCTestCase { + + func testSingleHashFunction() { + let bloom = BloomFilter(hashFunctions: [djb2]) + + bloom.insert("Hello world!") + + let result_good = bloom.query("Hello world!") + let result_bad = bloom.query("Hello world") + + XCTAssertTrue(result_good) + XCTAssertFalse(result_bad) + } + + func testEmptyFilter() { + let bloom = BloomFilter(hashFunctions: [djb2]) + + let empty = bloom.isEmpty() + + XCTAssertTrue(empty) + } + + func testMultipleHashFunctions() { + let bloom = BloomFilter(hashFunctions: [djb2, sdbm]) + + bloom.insert("Hello world!") + + let result_good = bloom.query("Hello world!") + let result_bad = bloom.query("Hello world") + + XCTAssertTrue(result_good) + XCTAssertFalse(result_bad) + } + + func testFalsePositive() { + let bloom = BloomFilter(size: 5, hashFunctions: [djb2, sdbm]) + + bloom.insert(["hello", "elloh", "llohe", "lohel", "ohell"]) + + print("Inserted") + + let query = bloom.query("This wasn't inserted!") + + // This is true even though we did not insert the value in the Bloom filter; + // the Bloom filter is capable of producing false positives but NOT + // false negatives. + + XCTAssertTrue(query) + } +} diff --git a/Bloom Filter/BloomFilterTests/Info.plist b/Bloom Filter/BloomFilterTests/Info.plist new file mode 100644 index 000000000..ba72822e8 --- /dev/null +++ b/Bloom Filter/BloomFilterTests/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + From 20d3c0e45ce932116fdef8241e4c7bc04e02e161 Mon Sep 17 00:00:00 2001 From: John Gill Date: Mon, 29 Feb 2016 18:34:09 -0800 Subject: [PATCH 0076/1679] Move kMeans from playground to project --- K-Means/K-Means.playground/Contents.swift | 140 ---------- .../K-Means.playground/contents.xcplayground | 4 - .../K-Means.playground/timeline.xctimeline | 41 --- K-Means/KMeans.swift | 168 ++++------- K-Means/README.md | 4 +- K-Means/Tests/Info.plist | 24 ++ K-Means/Tests/KMeansTests.swift | 65 +++++ K-Means/Tests/Tests.xcodeproj/project.pbxproj | 261 ++++++++++++++++++ K-Means/Tests/Vector.swift | 76 +++++ 9 files changed, 482 insertions(+), 301 deletions(-) delete mode 100644 K-Means/K-Means.playground/Contents.swift delete mode 100644 K-Means/K-Means.playground/contents.xcplayground delete mode 100644 K-Means/K-Means.playground/timeline.xctimeline create mode 100644 K-Means/Tests/Info.plist create mode 100644 K-Means/Tests/KMeansTests.swift create mode 100644 K-Means/Tests/Tests.xcodeproj/project.pbxproj create mode 100644 K-Means/Tests/Vector.swift diff --git a/K-Means/K-Means.playground/Contents.swift b/K-Means/K-Means.playground/Contents.swift deleted file mode 100644 index 9f35e5863..000000000 --- a/K-Means/K-Means.playground/Contents.swift +++ /dev/null @@ -1,140 +0,0 @@ -// -// K-Means.swift -// -// Created by John Gill on 2/25/16. - -import Foundation - -// Need a container to easily hold N Dimensional Vectors -class VectorND: CustomStringConvertible { - private var length = 0 - private var data = [Double]() - - init(d:[Double]) { - data = d - length = d.count - } - - var description: String { return "VectorND (\(data)" } - func getData() -> [Double] { return data } - func getLength() -> Int { return length } -} - -// MARK: VectorND Operators -func +(left: VectorND, right: VectorND) -> VectorND { - var results = [Double](count: left.getLength(), repeatedValue: 0.0) - for idx in 0.. VectorND { - var results = [Double](count: left.getLength(), repeatedValue: 0.0) - for (idx, value) in left.getData().enumerate() { - results[idx] = value / right - } - return VectorND(d: results) -} -func /=(inout left: VectorND, right: Double) { - left = left / right -} - -// MARK: Assist Functions -// Pick a k random elements from samples -func reservoirSample(samples:[VectorND], k:Int) -> [VectorND] { - var result = [VectorND]() - - // Fill the result array with first k elements - for i in 0.. Double { - var result = 0.0 - for idx in 0.. Int { - var nearestDist = DBL_MAX - var minIndex = 0; - - for (idx, c) in Centers.enumerate() { - let dist = euclidean(x, v2: c) - if dist < nearestDist { - minIndex = idx - nearestDist = dist - } - } - return minIndex -} - -// MARK: Main Function -func kMeans(numCenters: Int, convergeDist: Double, points: [VectorND]) -> [VectorND] { - var centerMoveDist = 0.0 - let zeros = [Double](count: points[0].getLength(), repeatedValue: 0.0) - - // 1. Choose k Random VectorNDs as the initial centers - var kCenters = reservoirSample(points, k: numCenters) - - // do following steps until convergence - repeat { - var cnts = [Double](count: numCenters, repeatedValue: 0.0) - var newCenters = [VectorND](count:numCenters, repeatedValue: VectorND(d:zeros)) - // 2. Assign VectorNDs to centers - // a. Determine which center each VectorND is closest to - // b. Record how many VectorNDs are assigned to each center - for p in points { - let c = nearestCenter(p, Centers: kCenters) - cnts[c]++ - newCenters[c] += p - } - // 3. Calculate a new centers - for idx in 0.. convergeDist) - return kCenters -} - -// MARK: Sample Data -var points = [VectorND]() -let numPoints = 10 -let numDimmensions = 5 -for _ in 0.. - - - \ No newline at end of file diff --git a/K-Means/K-Means.playground/timeline.xctimeline b/K-Means/K-Means.playground/timeline.xctimeline deleted file mode 100644 index 850856b0b..000000000 --- a/K-Means/K-Means.playground/timeline.xctimeline +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/K-Means/KMeans.swift b/K-Means/KMeans.swift index 05e973ba0..9a3193bfe 100644 --- a/K-Means/KMeans.swift +++ b/K-Means/KMeans.swift @@ -5,55 +5,71 @@ import Foundation -// Need a container to easily hold N Dimensional Vectors -class VectorND: CustomStringConvertible { - private var length = 0 - private var data = [Double]() - - init(d:[Double]) { - data = d - length = d.count +class KMeans { + var numCenters:Int + var convergeDist:Double + + init(numCenters:Int, convergeDist:Double) { + self.numCenters = numCenters + self.convergeDist = convergeDist } - - var description: String { return "VectorND (\(data)" } - func getData() -> [Double] { return data } - func getLength() -> Int { return length } -} - -// MARK: VectorND Operators -func +(left: VectorND, right: VectorND) -> VectorND { - var results = [Double](count: left.getLength(), repeatedValue: 0.0) - for idx in 0.. Int { + var nearestDist = DBL_MAX + var minIndex = 0; + + for (idx, c) in Centers.enumerate() { + let dist = x.distTo(c) + if dist < nearestDist { + minIndex = idx + nearestDist = dist + } + } + return minIndex } - return VectorND(d: results) -} -func +=(inout left: VectorND, right: VectorND) { - left = left + right -} -func /(left:VectorND, right: Double) -> VectorND { - var results = [Double](count: left.getLength(), repeatedValue: 0.0) - for (idx, value) in left.getData().enumerate() { - results[idx] = value / right + + func findCenters(points: [Vector]) -> [Vector] { + var centerMoveDist = 0.0 + let zeros = [Double](count: points[0].length, repeatedValue: 0.0) + + var kCenters = reservoirSample(points, k: numCenters) + + repeat { + var cnts = [Double](count: numCenters, repeatedValue: 0.0) + var newCenters = [Vector](count:numCenters, repeatedValue: Vector(d:zeros)) + + for p in points { + let c = nearestCenter(p, Centers: kCenters) + cnts[c]++ + newCenters[c] += p + } + + for idx in 0.. convergeDist) + return kCenters } - return VectorND(d: results) -} -func /=(inout left: VectorND, right: Double) { - left = left / right } -// MARK: Assist Functions -// Pick a k random elements from samples -func reservoirSample(samples:[VectorND], k:Int) -> [VectorND] { - var result = [VectorND]() +// Pick k random elements from samples +func reservoirSample(samples:[T], k:Int) -> [T] { + var result = [T]() // Fill the result array with first k elements for i in 0.. [VectorND] { return result } -// Calculates the Euclidean distance between two VectorNDs -func euclidean(v1:VectorND, v2:VectorND) -> Double { - var result = 0.0 - for idx in 0.. Int { - var nearestDist = DBL_MAX - var minIndex = 0; - - for (idx, c) in Centers.enumerate() { - let dist = euclidean(x, v2: c) - if dist < nearestDist { - minIndex = idx - nearestDist = dist - } - } - return minIndex -} - -// MARK: Main Function -func kMeans(numCenters: Int, convergeDist: Double, points: [VectorND]) -> [VectorND] { - var centerMoveDist = 0.0 - let zeros = [Double](count: points[0].getLength(), repeatedValue: 0.0) - - // 1. Choose k Random VectorNDs as the initial centers - var kCenters = reservoirSample(points, k: numCenters) - - // do following steps until convergence - repeat { - var cnts = [Double](count: numCenters, repeatedValue: 0.0) - var newCenters = [VectorND](count:numCenters, repeatedValue: VectorND(d:zeros)) - // 2. Assign VectorNDs to centers - // a. Determine which center each VectorND is closest to - // b. Record how many VectorNDs are assigned to each center - for p in points { - let c = nearestCenter(p, Centers: kCenters) - cnts[c]++ - newCenters[c] += p - } - // 3. Calculate a new centers - for idx in 0.. convergeDist) - return kCenters -} - -// MARK: Sample Data -var points = [VectorND]() -let numPoints = 10 -let numDimmensions = 5 -for _ in 0.. [VectorND] { +func kMeans(numCenters: Int, convergeDist: Double, points: [Vector]) -> [Vector] { var centerMoveDist = 0.0 let zeros = [Double](count: points[0].getLength(), repeatedValue: 0.0) @@ -30,7 +30,7 @@ func kMeans(numCenters: Int, convergeDist: Double, points: [VectorND]) -> [Vecto repeat { var cnts = [Double](count: numCenters, repeatedValue: 0.0) - var newCenters = [VectorND](count:numCenters, repeatedValue: VectorND(d:zeros)) + var newCenters = [Vector](count:numCenters, repeatedValue: Vector(d:zeros)) for p in points { let c = nearestCenter(p, Centers: kCenters) cnts[c]++ diff --git a/K-Means/Tests/Info.plist b/K-Means/Tests/Info.plist new file mode 100644 index 000000000..ba72822e8 --- /dev/null +++ b/K-Means/Tests/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/K-Means/Tests/KMeansTests.swift b/K-Means/Tests/KMeansTests.swift new file mode 100644 index 000000000..436cab4fe --- /dev/null +++ b/K-Means/Tests/KMeansTests.swift @@ -0,0 +1,65 @@ +// +// Tests.swift +// Tests +// +// Created by John Gill on 2/29/16. +// +// + +import Foundation +import XCTest + +class KMeansTests: XCTestCase { + var points = [Vector]() + + func genPoints(numPoints:Int, numDimmensions:Int) { + for _ in 0.. Double { + var result = 0.0 + for idx in 0.. Bool { + for idx in 0.. Vector { + var results = [Double]() + for idx in 0.. Vector { + var results = [Double]() + for idx in 0.. Vector { + var results = [Double](count: left.length, repeatedValue: 0.0) + for (idx, value) in left.data.enumerate() { + results[idx] = value / right + } + return Vector(d: results) +} + +func /=(inout left: Vector, right: Double) { + left = left / right +} \ No newline at end of file From 79810762a3186def99297986bedeb14b61e1d009 Mon Sep 17 00:00:00 2001 From: John Gill Date: Thu, 25 Feb 2016 13:46:48 -0800 Subject: [PATCH 0077/1679] Initial fileset --- K-Means/K-Means.playground/Contents.swift | 116 ++++++++++++++++++ .../K-Means.playground/contents.xcplayground | 4 + .../K-Means.playground/timeline.xctimeline | 6 + K-Means/README.md | 0 4 files changed, 126 insertions(+) create mode 100644 K-Means/K-Means.playground/Contents.swift create mode 100644 K-Means/K-Means.playground/contents.xcplayground create mode 100644 K-Means/K-Means.playground/timeline.xctimeline create mode 100644 K-Means/README.md diff --git a/K-Means/K-Means.playground/Contents.swift b/K-Means/K-Means.playground/Contents.swift new file mode 100644 index 000000000..a3071733e --- /dev/null +++ b/K-Means/K-Means.playground/Contents.swift @@ -0,0 +1,116 @@ +// +// K-Means.swift +// +// Created by John Gill on 2/25/16. + +import Foundation + +// Need a container to easily hold 2 Dimensional Vector2Ds +class Vector2D: CustomStringConvertible { + var x:Float = 0.0 // x-Coordinate of Vector2D + var y:Float = 0.0 // y-Coordinate of Vector2D + + init(x: Float, y: Float) { + self.x = x + self.y = y + } + + var description: String { + return "Vector2D (\(self.x), \(self.y))" + } +} + +// Ability to use std operators on Vector2D object +func +(left: Vector2D, right: Vector2D) -> Vector2D { + return Vector2D(x: left.x + right.x, y: left.y + right.y) +} +func +=(inout left: Vector2D, right: Vector2D) { + left = left + right +} +func /(left:Vector2D, right: Float) -> Vector2D { + return Vector2D(x: left.x / right, y: left.y / right) +} +func /=(inout left: Vector2D, right: Float) { + left = left / right +} + +// TODO: Explain/Replace/Cleanup +extension Array { + var shuffle: [Element] { + var elements = self + for index in indices { + let anotherIndex = Int(arc4random_uniform(UInt32(elements.count - index))) + index + anotherIndex != index ? swap(&elements[index], &elements[anotherIndex]) : () + } + return elements + } + func choose(n: Int) -> [Element] { + return Array(shuffle.prefix(n)) + } +} + +// Calculates the Euclidean distance between two Vector2Ds +func euclidean(v1:Vector2D, v2:Vector2D) -> Float { + return sqrt(pow((v1.x - v2.x), 2.0) + pow((v1.y - v2.y), 2.0)) +} + +// Get the INDEX of nearest Center to X +func nearestCenter(x: Vector2D, Centers: [Vector2D]) -> Int { + var nearestDist = FLT_MAX + var minIndex:Int = 0; + // Calculate the distance from Vector2D X to all the centers + for (idx, c) in Centers.enumerate() { + let dist = euclidean(x, v2: c) + if dist < nearestDist { + minIndex = idx + nearestDist = dist + } + } + return minIndex +} + +func kNN(numCenters: Int, convergeDist: Float, points: [Vector2D]) -> [Vector2D] { + var centerMoveDist:Float = 0.0 + + // 1. Choose k Random Vector2Ds as the initial centers + var kCenters:[Vector2D] = points.choose(numCenters) + + // do following steps until convergence + repeat { + var cnts = [Float](count: numCenters, repeatedValue: 0.0) + var nCenters = [Vector2D](count:numCenters, repeatedValue: Vector2D(x:0, y:0)) + // 2. Assign Vector2Ds to centers + // a. Determine which center each Vector2D is closest to + // b. Record how many Vector2Ds are assigned to each center + for p in points { + let c = nearestCenter(p, Centers: kCenters) + cnts[c]++ + nCenters[c] += p + } + // 3. Calculate a new centers + for idx in 0.. convergeDist) + return kCenters +} +var points = [Vector2D]() +let lim = 50 +for _ in 0.. + + + \ No newline at end of file diff --git a/K-Means/K-Means.playground/timeline.xctimeline b/K-Means/K-Means.playground/timeline.xctimeline new file mode 100644 index 000000000..bf468afec --- /dev/null +++ b/K-Means/K-Means.playground/timeline.xctimeline @@ -0,0 +1,6 @@ + + + + + diff --git a/K-Means/README.md b/K-Means/README.md new file mode 100644 index 000000000..e69de29bb From 62d152001463ee53a5987441f078d66c2ff0f564 Mon Sep 17 00:00:00 2001 From: John Gill Date: Thu, 25 Feb 2016 15:16:57 -0800 Subject: [PATCH 0078/1679] Change 2D vector to ND vector --- K-Means/K-Means.playground/Contents.swift | 82 +++++++++++-------- .../K-Means.playground/contents.xcplayground | 2 +- 2 files changed, 49 insertions(+), 35 deletions(-) diff --git a/K-Means/K-Means.playground/Contents.swift b/K-Means/K-Means.playground/Contents.swift index a3071733e..d1d6a05fd 100644 --- a/K-Means/K-Means.playground/Contents.swift +++ b/K-Means/K-Means.playground/Contents.swift @@ -5,32 +5,40 @@ import Foundation -// Need a container to easily hold 2 Dimensional Vector2Ds -class Vector2D: CustomStringConvertible { - var x:Float = 0.0 // x-Coordinate of Vector2D - var y:Float = 0.0 // y-Coordinate of Vector2D +// Need a container to easily hold N Dimensional Vectors +class VectorND: CustomStringConvertible { + private var length:Int = 0 + private var data:[Float] = [Float]() - init(x: Float, y: Float) { - self.x = x - self.y = y + init(d:[Float]) { + self.data = d + self.length = d.count } - var description: String { - return "Vector2D (\(self.x), \(self.y))" - } + var description: String { return "VectorND (\(self.data)" } + func getData() -> [Float] { return data } + func getLength() -> Int { return length } } -// Ability to use std operators on Vector2D object -func +(left: Vector2D, right: Vector2D) -> Vector2D { - return Vector2D(x: left.x + right.x, y: left.y + right.y) +// Ability to use std operators on VectorND object +func +(left: VectorND, right: VectorND) -> VectorND { + var results = [Float](count: left.getLength(), repeatedValue: 0.0) + for idx in 0.. Vector2D { - return Vector2D(x: left.x / right, y: left.y / right) +func /(left:VectorND, right: Float) -> VectorND { + var results = [Float](count: left.getLength(), repeatedValue: 0.0) + for (idx, value) in left.getData().enumerate() { + results[idx] = value / right + } + return VectorND(d: results) } -func /=(inout left: Vector2D, right: Float) { +func /=(inout left: VectorND, right: Float) { left = left / right } @@ -49,16 +57,20 @@ extension Array { } } -// Calculates the Euclidean distance between two Vector2Ds -func euclidean(v1:Vector2D, v2:Vector2D) -> Float { - return sqrt(pow((v1.x - v2.x), 2.0) + pow((v1.y - v2.y), 2.0)) +// Calculates the Euclidean distance between two VectorNDs +func euclidean(v1:VectorND, v2:VectorND) -> Float { + var result:Float = 0.0 + for idx in 0.. Int { +func nearestCenter(x: VectorND, Centers: [VectorND]) -> Int { var nearestDist = FLT_MAX var minIndex:Int = 0; - // Calculate the distance from Vector2D X to all the centers + // Calculate the distance from VectorND X to all the centers for (idx, c) in Centers.enumerate() { let dist = euclidean(x, v2: c) if dist < nearestDist { @@ -69,19 +81,20 @@ func nearestCenter(x: Vector2D, Centers: [Vector2D]) -> Int { return minIndex } -func kNN(numCenters: Int, convergeDist: Float, points: [Vector2D]) -> [Vector2D] { +func kNN(numCenters: Int, convergeDist: Float, points: [VectorND]) -> [VectorND] { var centerMoveDist:Float = 0.0 + let zeros = [Float](count: points[0].getLength(), repeatedValue: 0.0) - // 1. Choose k Random Vector2Ds as the initial centers - var kCenters:[Vector2D] = points.choose(numCenters) + // 1. Choose k Random VectorNDs as the initial centers + var kCenters:[VectorND] = points.choose(numCenters) // do following steps until convergence repeat { var cnts = [Float](count: numCenters, repeatedValue: 0.0) - var nCenters = [Vector2D](count:numCenters, repeatedValue: Vector2D(x:0, y:0)) - // 2. Assign Vector2Ds to centers - // a. Determine which center each Vector2D is closest to - // b. Record how many Vector2Ds are assigned to each center + var nCenters = [VectorND](count:numCenters, repeatedValue: VectorND(d:zeros)) + // 2. Assign VectorNDs to centers + // a. Determine which center each VectorND is closest to + // b. Record how many VectorNDs are assigned to each center for p in points { let c = nearestCenter(p, Centers: kCenters) cnts[c]++ @@ -102,15 +115,16 @@ func kNN(numCenters: Int, convergeDist: Float, points: [Vector2D]) -> [Vector2D] } while(centerMoveDist > convergeDist) return kCenters } -var points = [Vector2D]() -let lim = 50 + +var points = [VectorND]() +let lim = 10 for _ in 0.. - + \ No newline at end of file From 12f5a241b69190d47f8697cbb1d4bfaca7390605 Mon Sep 17 00:00:00 2001 From: John Gill Date: Thu, 25 Feb 2016 20:45:12 -0800 Subject: [PATCH 0079/1679] Update to follow Swift Style Guide --- K-Means/K-Means.playground/Contents.swift | 100 ++++++++++-------- .../K-Means.playground/timeline.xctimeline | 35 ++++++ 2 files changed, 90 insertions(+), 45 deletions(-) diff --git a/K-Means/K-Means.playground/Contents.swift b/K-Means/K-Means.playground/Contents.swift index d1d6a05fd..9f35e5863 100644 --- a/K-Means/K-Means.playground/Contents.swift +++ b/K-Means/K-Means.playground/Contents.swift @@ -7,22 +7,22 @@ import Foundation // Need a container to easily hold N Dimensional Vectors class VectorND: CustomStringConvertible { - private var length:Int = 0 - private var data:[Float] = [Float]() + private var length = 0 + private var data = [Double]() - init(d:[Float]) { - self.data = d - self.length = d.count + init(d:[Double]) { + data = d + length = d.count } - var description: String { return "VectorND (\(self.data)" } - func getData() -> [Float] { return data } + var description: String { return "VectorND (\(data)" } + func getData() -> [Double] { return data } func getLength() -> Int { return length } } -// Ability to use std operators on VectorND object +// MARK: VectorND Operators func +(left: VectorND, right: VectorND) -> VectorND { - var results = [Float](count: left.getLength(), repeatedValue: 0.0) + var results = [Double](count: left.getLength(), repeatedValue: 0.0) for idx in 0.. VectorND { func +=(inout left: VectorND, right: VectorND) { left = left + right } -func /(left:VectorND, right: Float) -> VectorND { - var results = [Float](count: left.getLength(), repeatedValue: 0.0) +func /(left:VectorND, right: Double) -> VectorND { + var results = [Double](count: left.getLength(), repeatedValue: 0.0) for (idx, value) in left.getData().enumerate() { results[idx] = value / right } return VectorND(d: results) } -func /=(inout left: VectorND, right: Float) { +func /=(inout left: VectorND, right: Double) { left = left / right } -// TODO: Explain/Replace/Cleanup -extension Array { - var shuffle: [Element] { - var elements = self - for index in indices { - let anotherIndex = Int(arc4random_uniform(UInt32(elements.count - index))) + index - anotherIndex != index ? swap(&elements[index], &elements[anotherIndex]) : () - } - return elements +// MARK: Assist Functions +// Pick a k random elements from samples +func reservoirSample(samples:[VectorND], k:Int) -> [VectorND] { + var result = [VectorND]() + + // Fill the result array with first k elements + for i in 0.. [Element] { - return Array(shuffle.prefix(n)) + // randomly replace elements from remaining ones + for i in (k+1).. Float { - var result:Float = 0.0 +func euclidean(v1:VectorND, v2:VectorND) -> Double { + var result = 0.0 for idx in 0.. Float { // Get the INDEX of nearest Center to X func nearestCenter(x: VectorND, Centers: [VectorND]) -> Int { - var nearestDist = FLT_MAX - var minIndex:Int = 0; - // Calculate the distance from VectorND X to all the centers + var nearestDist = DBL_MAX + var minIndex = 0; + for (idx, c) in Centers.enumerate() { let dist = euclidean(x, v2: c) if dist < nearestDist { @@ -81,50 +85,56 @@ func nearestCenter(x: VectorND, Centers: [VectorND]) -> Int { return minIndex } -func kNN(numCenters: Int, convergeDist: Float, points: [VectorND]) -> [VectorND] { - var centerMoveDist:Float = 0.0 - let zeros = [Float](count: points[0].getLength(), repeatedValue: 0.0) +// MARK: Main Function +func kMeans(numCenters: Int, convergeDist: Double, points: [VectorND]) -> [VectorND] { + var centerMoveDist = 0.0 + let zeros = [Double](count: points[0].getLength(), repeatedValue: 0.0) // 1. Choose k Random VectorNDs as the initial centers - var kCenters:[VectorND] = points.choose(numCenters) + var kCenters = reservoirSample(points, k: numCenters) // do following steps until convergence repeat { - var cnts = [Float](count: numCenters, repeatedValue: 0.0) - var nCenters = [VectorND](count:numCenters, repeatedValue: VectorND(d:zeros)) + var cnts = [Double](count: numCenters, repeatedValue: 0.0) + var newCenters = [VectorND](count:numCenters, repeatedValue: VectorND(d:zeros)) // 2. Assign VectorNDs to centers // a. Determine which center each VectorND is closest to // b. Record how many VectorNDs are assigned to each center for p in points { let c = nearestCenter(p, Centers: kCenters) cnts[c]++ - nCenters[c] += p + newCenters[c] += p } // 3. Calculate a new centers for idx in 0.. convergeDist) return kCenters } +// MARK: Sample Data var points = [VectorND]() -let lim = 10 -for _ in 0.. + + + + + + + + + + + + + + From 1e25e02e96ba5cd26feda8f655f3854c69b820b7 Mon Sep 17 00:00:00 2001 From: John Gill Date: Thu, 25 Feb 2016 22:29:14 -0800 Subject: [PATCH 0080/1679] Move Contents into own source file --- K-Means/KMeans.swift | 139 +++++++++++++++++++++++++++++++++++++++++++ K-Means/README.md | 3 + 2 files changed, 142 insertions(+) create mode 100644 K-Means/KMeans.swift diff --git a/K-Means/KMeans.swift b/K-Means/KMeans.swift new file mode 100644 index 000000000..05e973ba0 --- /dev/null +++ b/K-Means/KMeans.swift @@ -0,0 +1,139 @@ +// +// KMeans.swift +// +// Created by John Gill on 2/25/16. + +import Foundation + +// Need a container to easily hold N Dimensional Vectors +class VectorND: CustomStringConvertible { + private var length = 0 + private var data = [Double]() + + init(d:[Double]) { + data = d + length = d.count + } + + var description: String { return "VectorND (\(data)" } + func getData() -> [Double] { return data } + func getLength() -> Int { return length } +} + +// MARK: VectorND Operators +func +(left: VectorND, right: VectorND) -> VectorND { + var results = [Double](count: left.getLength(), repeatedValue: 0.0) + for idx in 0.. VectorND { + var results = [Double](count: left.getLength(), repeatedValue: 0.0) + for (idx, value) in left.getData().enumerate() { + results[idx] = value / right + } + return VectorND(d: results) +} +func /=(inout left: VectorND, right: Double) { + left = left / right +} + +// MARK: Assist Functions +// Pick a k random elements from samples +func reservoirSample(samples:[VectorND], k:Int) -> [VectorND] { + var result = [VectorND]() + + // Fill the result array with first k elements + for i in 0.. Double { + var result = 0.0 + for idx in 0.. Int { + var nearestDist = DBL_MAX + var minIndex = 0; + + for (idx, c) in Centers.enumerate() { + let dist = euclidean(x, v2: c) + if dist < nearestDist { + minIndex = idx + nearestDist = dist + } + } + return minIndex +} + +// MARK: Main Function +func kMeans(numCenters: Int, convergeDist: Double, points: [VectorND]) -> [VectorND] { + var centerMoveDist = 0.0 + let zeros = [Double](count: points[0].getLength(), repeatedValue: 0.0) + + // 1. Choose k Random VectorNDs as the initial centers + var kCenters = reservoirSample(points, k: numCenters) + + // do following steps until convergence + repeat { + var cnts = [Double](count: numCenters, repeatedValue: 0.0) + var newCenters = [VectorND](count:numCenters, repeatedValue: VectorND(d:zeros)) + // 2. Assign VectorNDs to centers + // a. Determine which center each VectorND is closest to + // b. Record how many VectorNDs are assigned to each center + for p in points { + let c = nearestCenter(p, Centers: kCenters) + cnts[c]++ + newCenters[c] += p + } + // 3. Calculate a new centers + for idx in 0.. convergeDist) + return kCenters +} + +// MARK: Sample Data +var points = [VectorND]() +let numPoints = 10 +let numDimmensions = 5 +for _ in 0.. Date: Thu, 25 Feb 2016 22:22:37 -0800 Subject: [PATCH 0081/1679] add k-Means algorithm --- README.markdown | 1 + 1 file changed, 1 insertion(+) diff --git a/README.markdown b/README.markdown index 579e7c182..f19944aa3 100644 --- a/README.markdown +++ b/README.markdown @@ -96,6 +96,7 @@ Bad sorting algorithms (don't use these!): ### Machine learning +- [k-Means](K-Means/). Unsupervised classifier that partitions data into k clusters. - k-Nearest Neighbors - Linear Regression - Logistic Regression From a52aa68cdc8ea9d21d35dee3cad5768ef4322fd9 Mon Sep 17 00:00:00 2001 From: John Gill Date: Sun, 28 Feb 2016 14:41:43 -0800 Subject: [PATCH 0082/1679] Write README for K-Means Algorithm --- K-Means/Images/k_means_bad1.png | Bin 0 -> 16294 bytes K-Means/Images/k_means_bad2.png | Bin 0 -> 15826 bytes K-Means/Images/k_means_good.png | Bin 0 -> 15983 bytes K-Means/README.md | 82 +++++++++++++++++++++++++++++++- README.markdown | 5 +- 5 files changed, 85 insertions(+), 2 deletions(-) create mode 100644 K-Means/Images/k_means_bad1.png create mode 100644 K-Means/Images/k_means_bad2.png create mode 100644 K-Means/Images/k_means_good.png diff --git a/K-Means/Images/k_means_bad1.png b/K-Means/Images/k_means_bad1.png new file mode 100644 index 0000000000000000000000000000000000000000..55df0e7eedb8e60921a9c84c2ea0718fc77e3e99 GIT binary patch literal 16294 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 Lcu+3?B=mm)Oq!bc literal 0 HcmV?d00001 diff --git a/K-Means/Images/k_means_good.png b/K-Means/Images/k_means_good.png new file mode 100644 index 0000000000000000000000000000000000000000..01760758b5e5f2735579b8206e95b04c99cd3f20 GIT binary patch literal 15983 zcmeIZbySq!_dg0FNS7iYIf#^$2#7RDcS(23&@l{MqJ)4V9n#%MGn9&;bTDL2-SI zg0gOmg2JDGfzp zO~CGUw)QUk?m`cKjo=5q--tOLfPW2v+6X<+R#X9tJ2+c_dDywxA3qSr27|$Z&gPc< zY7$a^-wymG^uP)Vb>!#ZaC38GcjIDraDK_b$;ZdX@%RbHlP7Gz2sRfFd#H&!o4pI& zUz7YZkA#JbnKQ%@3UROp-^^=b>fj0$dhp=pLI3{zr6&|(`JX4*yZpT@V1XPrS2#G? zA9MUWH*l-qjg(*9!Oqdy!o>xcUzk(y*T_F)|9Q?|o z>$5-Ap{|M}1?sb0eJ@f9)iv&5p`sCrqWu5zfh}QN#IoXxuBQ1mRFo5&Fsn^_!`6is zi!kfW3%!_XGW3uE)8a!AVmY>Sni0uUsv7#C}{6NxgNNbb8^IP)&Wu8iIH438l{j^mYqn=NdkV`2lL(5@ZEBizVK$#WyhHnZSStzdMK@j?IilRp zRAGHf_$B;HTx~^8Dr)_(Pug}6#J+rQ;(nCEOHLLvIkbDmjj7MZ&(KsV5eS2^w2bfan@4@1cp4diVbZsfx4DW~ze9=}=&q?`DY9#=XV zW#5U*i8Y#XWXc(n}X{cm@-XeW+a1294R_&b`W36 zUeoa9UB}jV!fVkyv`K6-8{-HCoz`>2iA_U`vUA#~-4JHYJxRg2m7iC^@fL&wbc7Kx z%!%5d)mJ*lrl2!T?s$ZgpkRXtNhy$Fuqj7u2B{zi9eWR5s5#A&_cjCSHf=60!5$i7%q;cb4nB#?zkoFv+H!n{bv#_iP^Ci)cQ6h3g@zIAJHtKPnRhW{ZNwhs6m zXOb=rY}4jDGP?=0|JgK-QW#CsMl*q%ctvtPdcVW8u@-2n`z?LLTQ@mV)=R&pY4e86 z+BUq=gvL?4f{xKoe(SFROBi~-rzmv`G_a%m8N>nq3FEEe)iIu43EHmvQtGSAJ48^Q zLFZB5CWGltOPEK-)6Z_dT5~=Gvx1dXDAN5pm0<&V`jV83L0kwGz5Lkc^+Ym6A?o3i zpH9*3SAX8N+14&=+DCle=b;1@EP%@DC6%X}>UglXWV1F9k(;>?44YAHy`Mpf_T?-N zX|91evi2u#rp0S5wD!ZL38l_~=!Cx)0{DF|^A#kGe4F>$W@s7~0BkbKL@nE#CU!#C9 z!T$fJACYfF_wHdAR3harzdi#=vPQBCd(VNTeDcvd=K@hU*TvaXZlgWHAJ0c}$r4PW z3y+_BYexJb{hx{dHT3`2rU((^v$nQ|uB5oFpKX+lRY8WTplgFFwbo;$21x>LrM^3X zG!KJoz+c4ZF~p6|BobK+C7;AhAzI$V<-WOh)8PwMPC4 z4G1&gb7$<}2WdG3TsBKewomYGY1ccd!8fFGLY^|0=km2PhTf|DC%~p9 z;FHj;VV!21sgmWtgcek&kqc^j?tF3F?_;Qq;^wMfu*0t#s(W03hiXGss{QFX9v)sO zUsq=*x9j=~JSzUG2>QzNT`qeL2;NsX9R3Zow6ug2b&Fz9`j}vFdn=(R`ymne+I$vO z{i3a=Dfi2&-Cp;vXlth{^fupgDpKBWtsc#aoXkvIx11`jF^YUBEDHR{dOdp~1wWbZ zU7q&zFs-V_QpeW&3`@bF1UKyl4Ud!A%4@_<`)aI@aeTCMX)s5)##gz#j7)3Gr}9pP zsy#c+TYes%YyFrSBcMbt=L22N;YMJ|C-Js`TR9p2fR#%JJ!=4;> zFy`zowEk%FpiVT6VF~U@IT^(Y7&G*;Q*Q0AfIz)?lSwoySUz+FWh_A!OpH=+i;5Qm z{T)ECwz>M1B=R85X0=+31QC(Os2M*$_11ppYN>geYcj*D#n+-A(Ti2=LQF%SJD=?6+B-3qfgy_Efu8&bKgeTtB zr9|A5I5eR@RVx_LdgQ@*Y>4*g(W9ixD*1T!((@#NB_g%;wX?!4;jT}N->FA=gMi&) zhpp`nkF+xI=NcgnxV~_@Zm-NpKp@AP`ySQiQP9l0?sP;mc9Ex#u2y9fO%*Su%)sqv7IoLp`*ZZy1TxFj}e-EaFMnbPnd&~~@x^j*i85_5h+Vi*a?ELI%ee@m0 z+)rOdtHZqt>(ZDh_?Bf^$~_O)CA8EUOs(+5Z5{?C*1+*+<>Odo1w)pN-J~691kSp} zI)@1aFpAb?;=Wl)4{I~fK6Xew=<|~k4?;Tz1yN>(o@Y_Jiy{{l%f&0tIh{X*4Cv=a z5eUO`oS(lpS+W}~DYrso+p=Qz)(Omysv{z(@*$-BR$Z$;o57>4hB9u?DkBSdEpqbUwHFC-qyat1 ze3$m{`xUn{y?6tsKH&}L#2Y4AF)iny6r-V{9X*;eWG-BIA5Tu6edf8A9i4rSjNU{? zJVYZ5F`T2hj#Ls6awj!4NHO1*XjmdqnwK!*ia`kwH9oRk`--zPbI#`0$l`O_HRw8a zTGHx;e_5KQ9gln`fb6#^Yl^cXn+%GJjfD(m%km$Mo6*f86}Ejt8;!+K-TN{a?-3oF zhSPAc8M2aQeTh3-rBzI0_t`WXaNy%4_n}gGwTgb5Aa2H|wt$i(>*y6STG>8{WQ2^9 zJXUbyQ1UZ*pwGG7$cQ3+VR6jWAxFninQEQ_ryNalzD;h(Sc~uF8F1vy^4;PYMvHaS zzdf+!2dvb1Nmi;pB}ir^;_V^zbuN*WLE9+!tFxv9GkQT-Rn83%)mThH$LXbfzehM-3g{z_9|ee z0kzQ@f8ujC-?w9Py8Pl@_h6v$g|~S6GxXcIk#IMM<}FxQd!18H-sw?9dxis#n#2;{ zLO9oOi=W>ZLBlkaKWrdhHH+Ki>+1)1jMa&D^yYd6fWs(VA!Q=@hTF9eimdmIPaLFG zQ2-GLlL?08zEm!-(OOHg$qv06ChKn}`Pm4yLGGkqTumd^oYVSzAnob}IamAa6TOaU zzFf`F^F-Ybk7>0)z`0ROeoBwz-5e>>D%Bi9dUGAN+Pg{B>-dxPM6lH75|vkeEYg%c zs#5bJ&*TUtJIrBVk{$-ZjH27}1;z?}jzZzwiW`hl$*g27_5mpZIeyoA^?hz zgOa4OM~mWjK$sFN#sn$#E7Xvm&({j_UXfjX#&|_mt))$@JKt%NF+#S~6DFEl$?T!y zF~#z;(_~7jo5%%FX!&0EGSA&|FQ2V@_l`c_rwGE2P4%1EF1q{8s`AmId^q}MVKdL| zH17%s9RWX6h-yP${}`Ybus~h27#1~Pfp;MpNt#Lv4@ir3`7D$Fu zIVzWKPUNK(5*^FOuLZzk4QonMi#VrHe-V!WV7Dc`D_jmT{efe z81^~d6J-%L1Wa#7I8WJ6mt2T{CfAk95O1thfhgRao!gZetZf!?j%PL{G4$4G>@lLwIYK{rZj8TM*{qe+*}UcY$f zILiJw4jHKqyl&dE+^h+wrSdFi$>xtjOFPTSIqU0l{zK#;M=D{F&tJg$PcsP6Pp8DW zHm4)cE5Qw%BAXK7L2Poq!kGG=1<>s#FTp;+hcPu0wuzZa;@!zS=yQxt@D@AETjVtKpvU1hr?oPF z_3iojwt5c{(_FHp)Yiw=QG$0sE(org5)-R}ft0K1HDs^Pz!5)fj>rD;R>y2bm8%fo zI%$`bo??E}OV1F4{|qt?Hq*1_?JhH9yFBgtX;;f5T=Emr0n0qv35N{5+P-*?0`el& zZqTe~*LxDQiAq|7Q!Tv^9NTZ(=_XcFkWXi| zEwU_HLA4`ehEv2@Fd4gJitC>QKbO)JmALUMRZUZi(bhLMl6zj_eTy4P>gn(0sIIOq ziId?i8BtIG_9khVSYQeLo0Lmj79F$4JUX|WrfP)r9jWz<2{vtriF!K z?I)NM5f}eAig);Kmo~*LkS7y$0NnN$odO+|=5$0S&$gIjq%x+CA5~2Ba=KdY$2(8q zz)O-T0UmOagiKhUoTt-15p%ivq^dOME<;t5ZH-Hv0OvFtjiSrcNwCQDK?)}t;Sbiw zzKz3q%IdcU@I5dH;@ZPI8Wp_!Ot-len?_nkIW6S8T-K&9rd`JQMB47(r>pM80wmqk-|eMeS-AC3YX>TmZ8ou zUiewV9CNNy8iH;V<@y9W-{h-+#AmHvymboPpk{@Taj2(%_POaucP%sQYnKQQqbavW z;BFmeu^yv=Z~Z|xmzekfwUWzc)Sq@K2Fz9GiO5DS_sy#aUb(y!62q$kKB6puJ^C&= z7r~qT-cR3ijlP3Cj3moMm|_4PJ=HqD8Asq%yT;+i+;n|eKhQ;-1=xE*u@s#>lG#{r zf|Wct^#xj6h>|~9L~kk&U1S6bXHvwSeJ~-AMv=LukjVUjjZr{t?4k?h<9@fseg8<3 zK4bMiTO9i@8rZ*`w&m7;-LKEL==NX3fO|_~jBfog9}19(UEtra4sTdh)aj`F8mpYl zXdTckr2oE|2CdVZ3C-eHz_3d5Z*sh9KF@xGlXJSCFB zZg%a8YZC{IBP~>MZ};Ah8}lvbt=Q@?qCG)ZV64D(Q6&#Hu_kde6oAQSXdsuJ+>Yy9 zISeYL$RDTs^X5}YGD=Mav=w7YfJMWl{Cgh}Sp@@zT?*jd5;fNZ6#L8=aE~P$iOAU~ zjXpb!j$=P8fX1NzO{Zfk`m+ST(KL(U1kUTnHCniXYDRv|eB#bK|&_A0_{Ha3FPbh6o}Va9u3ae@&bBeBNA=1AFN z;#fay@({d9nDLbN+>?d020dpLvXC;~293Cm=KL0_#coqj4y(kzh zV5BG~^zIEvcDttXDh4j7d3azZt}ursJH#~~@f2h}FD#3{I+0!*R^P93)(jMVhaOj= zm%HHS)(9KjeqkV11!2n+nofq2P zLt{pJrRGcXE$3@%3hTp(V;{{SrPR2*YBygVnA*vpe2&*P-qB?ZM+&bp|7v>gih%;3 z}~;w9k8B@BjLzCPzIF)E)HhyKKzn$i1PF3^l9x=?fumLL-t&D@ z2Ln`3S~oX?Qw2NMorn#kIuw9j%O7tb>D^X*+h|K@PkGx+hfB$IKc@P?WD=wCK-8EY zea0px^(z6d1-rANh2xv^T}ucl)=|OoiU)hUL3#2MU5KjNcqtD14||pSUAub1K&*8(AEz(LrVOWXy%WvAjERkdSe0e;ytUco zhxwnkaYSq$!Jo&SOFI@x~?cpXfz?7vpz5@8M zO*^a>UrT{<3j0X7YqaMve$B$wd7xMF#Uth%v2-(#TZ&u!?IW^$Lj$h@JssZ5mAdQU zQ?tHpZA&6ni(_uT-7rPY$=Wh*8%;EHlUU3}nYk}v)Guc3eMTBG-5yAl@t-}S;+?Of zEMdE_?Gw_1?|cPIc^yVgXTXv5j2DOBguX-F0vc9I>Nd)=H9<$O)f%?@?Ne(p28jn1 z4>}?WU}IAyECmLfRk!Jwn?57qilj7aq(8P_m~sc!HqdL29(IvyXGzxzccqzdmNDq@ z@-(>Z`QKWcA1=!D&;V*GMe9G{k6|>?uIfdF`GY^2=_(C-^X{_=Bg`=FXg%CCCuVK} zqTo#1alw>zEqyA3Eu(YLF*VZ5X(-NN59x2o`1DJ{n0KYi_vlz)2$uZEb|A7xa4 zr?8@wdfAusHzxW!>^T5ZPxX7m0H*(KI1s+uO>St8KcxRN@xO`2|JD?<);&dmkn4=R3&uy*};Z zJ^U_`nxSQQKWA`I3gNXqan?$6w3`hjzJ-d0Y^p6Vu_7Nqp6vGuIEkU48lhP>KXw6_ z-%j(0Z;5?<2RZIBw*oRr>$Xm(j<|90=!mk|?PYy|6!9QixIMgJ44qVPPVTOLG5NC{ z1GmE+6Jkul46vyY2pm>U_ktUq%y7&R78lrBL0=;7(CsaWFHo#x_5>ik*73{ip z$5^{{Cy2uTm%62VN92dAlj1qZH2RGS*k$P0xtd^Sfam~@zTeL4rxx_0yA*?2rMZ7}ggjw;nvgD(V>~n7Vu4lsogS`v%)u zoL)AYUiN-p{5zqinXk%qkwD4|F8R!|VKflFVwqq1Nhv4K!={4dMM)E#hw#dshHT+^r{hQXO#3#L2vjf?e z43M599$l>__Ov2PgB0R9NKOix`K~**x#z2BM!l{f;N4@sB}xGbgegKcQeX;z|Dm8? z76bDG{#vefaCQAP58Xcm%rAH{1C)^uavw4M$?y{1WV^qd_+J<%o5;$_w*Pq9NBKzh z`OQLpqyYmibSfGCUXzvhXKG_kn+aAQ7bNdt|6cGNf+{OBBHv#$Ghq}8K{ggvlgk*|~mceNBeutvtNp<)og_<1C&{>qsFIzaGC5Rgd^R{nDgHaT2hU z_-%RtwC5xM4AJMqy`QxCcMJexvOxoML_J<4XD~`lr?p==t@#2%9z?ZZ&J5_5jsT9z zlw$iowv1#6u&bWB!_g~jKf7=zZEB-t#ad%A>;@6^KliuKVG{*<6R^zT!^lv4#Bav* zDIK$oXkFTf-w2_VUY)2-8wt3?fAPLl$hk>(j{u+)@$ScL5@PCrZ+7gBdh@iuKqmkH z7G&n=L7=W*|BvEadUtXZv8dQn`|11~`FI9u%_sKL&oneN?uiy8zg@L|F(l8?lwEBz zR_J$qMJ@od-TT6#$i*2Xii*Q((C~tQ-Ae`0316cN_LjKiiOZB<0?)6&lX7;cM1@q@~qBp!L7@SvDQ%F$Gfv9WRV_`*gf2RP)@E{;j{m&wE9OqbvNWcF9& zM@G~va-bs`gNI}1TADO+65(emI9n{Ow>U)7!>-*wZAu;=3AfS;1+UgC3+2t+YnqBz zm2lCk7kRvJ%M*f-pVX;UM|3toCOd|pORrhz9(|ZCqL%_n0??d>r9?gGVXM~m>17Qg zx`@YVbf~)`Z;QiFv5EW1HD&3Do)+U(?+a)_|JKS(sSAPdSZ$`KYU;0J$y&5BAWfrT zXIDawAo_^+RM-tU%^LsC_i4j=z5DLG1VHGU;Yrvq*^iggo_$pXp*<(8TQAcpfS2;` z&Tl3Kk=u>ei}7A=V>(qYjl4o_sl8D!YEt_5o>#kcn71l%HEzwEOrAR_1DC)V;)!=ON@aFM( zEMD0|&jsSnnh6ab8#0FL-WOw9U02A+Nk+gW%9mLS#HK~DhUhBEpMG-75^zJlfI#-w zYqp=JycVTIE5?zvE_5g!gRi?5L^o2qtvC$l$nQUhtABT`SNk-rofi#T!&qK%pNp#c zuzIp?=yIM^rlN(Djp7xIXW(k|MwNgd1H6j6MFj;;T3NbCJ#|0iR9$TK(o@?K3&zPA zPwN?7tL;Ha?iPfZl>uk;FTC`y;rrw23r+iTVPjDfM6?FeObpjGXob@I-J>o8qi)1s zpz64(%tN*$vyd?g6P6 zetdE3(e@zJHuB;=(Cd}tk9fzqD|FYQWvl=)7$RF>)I?qDg z_dn~tv%Z@3ew6b&WtKexP9GF{mvKFW?%faPwbhrEL36_e>O5Bc=@MD}!W<2o6`FYM ztMYPKgsTak36#$=*zfzv&R^wR#aHvcjaY{^J?JN9_cNEEUcnuO!_7%9Cyt$N7t8h4pVGn69@NhFtNWOQpabIMsyxqy zI=!s+e4`IPzadyO=_v*UTwsoG?}ySUD_r<)>s6OgH|~f3SdYkB+ zL@F;+PWuxG*8KX;W(l3yOIh8)icTZEddWGWxyjHVe8 z0YV_7v#Izh_nvv7+57*A*gqmfb?htXwQd563rK#Hb)bmCa6~!ntYBt*FG$#T{5y}w zqPZ)}#%O)G4*9=v9$X?Sn^e$fEP#g{{Z<}46ecF5%Ji1(a@B`sWZUSXsZ+kIy6bX7 zZBSC#Xt%1JfP7n)M~6uAx%fyw z$4rw|-B$QUV}li$R4o|7f6v_gasJZ;_6C*d@}?@YorD z^m*JrgHb@TsPI?@`V$GTBzP$2C`KoflI^X1&h5rh&y+K*qp^2zD(mr)^i%^cskL6X z&>gUpP$BNySEA%VY5}Z^a7X4>%sa@BVtOkAN(8k>-yu<4=)ddm_Gbpr+hmfX@(@i8 zfP}=jQbao{H)BhNTRSuVBv(b70hO2aJ|6yC9r~poHE?JS%GH>F;@59oSdk9E3p*uw z>GQkL-#_>!DJ~{{3lxigyRfJSE{kY|!};wdt7HLe!#B~}-Y(VDgtQwO9$tLt_e2tW z1e&Uq2P%Q=nl2yK$=9o_haTCLxo*$`%=nrmh(M@#UbG-s15ymTof zt)>s0*4@NK5NFdR8OzF+nBNTN&S&F+Vr%=mSgCh0hCV#Qim8>(?`|tlM1~Ap4V`U# ziKoHk@p~c;9tAbPWYf++a=Vv9=K{VoAEdZ_MJ$S3WI#lO9Mh-2*w>v#Q-GAf9NT=; zHFn9qN0n*yVMK~rba2>KVNqGL?$LcIew#@hUBf1Qjt0NW>6YV|M(Lrx8qv(yWew|)w9>v{eR34l81(ozLc*SJFOYD9Vt)49U7f1 z@meloEgSAE(zG@vIIi`7Eh>QimR)KasMdXBe7F%{R#2>v#4QVy?gF<{E@w-nbhEfz zMGQ3VZRRz&ZrCDOja~zMFgJ%5{#c1#-r(S9Q3ZRh$wRm7;-K~0Y%bTVcF^n5OeBOEZHYU!?FCDHeD^%^@LvpHM0e8E^^X&fh=$-?_uk+>)!C@# zBwb;R;8@Ds!Y>-+T$Tz}r_n^9PbAOItk$B_aACHiifu5*QOR8S{o4l8c%5=x(3N_( zPI!Ta#tVAkGQo8@DxP6i3;JKRu9vCIDNaGdS;0VcpHXYOK5uKO;$xPPg~+9MXWvLu zvDX8st$i;>UuC+p*Y1wV7CH%d0j~gChAe>SocD1A&A3X2MaD%_4qk;KkNZ z>OJEPI$FX^e}R&LM{oQ@hL9TC$Ab|_W~IyX<9HsjRwbCjf&h}bK+err!2AcHThR-6 z4~|#KBB^u$P|XsW82#9mZwN&QmV|Wz9A|5AaC5zby$9DoEEIs8{N|B*7+3)NPHYjb zt2OurhrX6$1gQDKj2wSJ+Jf%s*7zn$ZE?w&ojJYYF`vooEM+nqPE|QujE)kZ9(j%B zjM4COtlpKQI+%Y_=sS$(!)s9tbf8rSKB|ty7ZlKTClLqF0RLR+-_ng(56G;Fnnl3r&*$#vwps<)qx?BA2@Sv zXsGy8>rf@hl(hW&`t=gWU>Aox1`TTpEJ;6-qyc;Cy}t`XE(@$8N&K>Hf;bgvh0A+V#MDXdX_&6Sp~! ztJ9Ss(eM+}Ty4#?wcX}a+ZIyJ!ai>)_*RYail!m^1dhMonYwZalhia2RG(UpE6sfL zDn0l?Cl(%8@A75#Ebd^WtmYF~L<&raYFdT&{p@V+bq`mcOm($dt^MHj#ruO#@2mg1 z4glzNi-mH_6(ze#2a&A>!-J`|l+)>@QmM_&8H42OLk_&^c$a9xAD={X{X2H8D|>{` z+D-P*8`(9FA5MLm(D+6~ccfs77N8F#Kz2W__R|KL^JJ!Kd3&rFou1mqcpg|KwUdGP zfB-w?4^+K#`uv(t6>^aF95&p8IC=Frv(68IH{8^?;`mZA;>vS5u_DfQxE{#&=JUcZoJcC9^=lqNUM&sCYJY|YhUuFd zm~0F<`j0NtiOD2>!kdNP0x)V463Z~bk!}I?E;)TZrKe)KZ5wl6zC<2_K0QYxw4!&s z*exj|oNW5SMiE{@Vh#e;-?MV+d{E2M_4HV+_HM)6pghlP%IQa5%W!7=Y^JhUK)G7drS(VxHx87#`@FE(F?cW=Zj>F-J6S zQRkxGdUZR~Rh>dW({nChl+krET4eu$zoN51^Z`>K>Fm%L>U?b^E7VGo68(LI1NVuLt(c^@l=tQ>LEANr72z zGM{K35b!jkYkn)@$&riMOC_KIm79wTD_|NRr0Ngp-O%`1fY$|~glWbtnKAz&1IDe$ zgKKunnjb|_Q$gQ+YR@nzSe>1{OY&A#0qE5Wn)IE=TB}N1?{F?CL_$LT8FWwSdT>4E&|&~^#(2Mylp|1C3p-Gl;r8|30d1AjJT*J@IjR)9s-f1S z0rIR0QpfG95#XoLJYw7T~-1eS>uRzMe%s>eTdh&BH zg7<;qKAz8xgjnCg zz#qP091y(XFgU+uPf`xO{dXNLt@s~BUxnc3H@!I9Gfe_1y!VOIZs3j32h3}rBSPhw zWq6f|_>M17ZOrb7&JnrhYg828;$GYRzSN7`aY+<;Q`hE*FD(43hrxF*LUf=lUx;?x z(7eS?&+)U4&i%%g9o`nKyj}#BCY5VU6%?}bTHQ-}K7?p+zO50Pj`C+_SI(;Gu<6oj z7SPp`Udkrba$&JHY13NZCGZ7kyB^eYkcFB4FjRFJHyLcXy4MJ2_*fk&PXutE1C9E8 z-rrN!%2|R(A6J=cosI&z4^Z+AQbR||=!B85O%6R)C^f66a*qN~jU8}y1ErFwz`7N; zr|I6mcGGn3B7yXN1RHhDj+zO;zf)H_0F`trdE=waIsg8x?K>U#q6Qp^{ZUP=!$*ln zaB_KA=E#iM*;kw|ZdcL(DT*`gsc`)190b3oH5>a9f(W5O7`bsVQ^i!1ylJvn|%zh8M+SGvT%`|YtaBLUhxha<9H ztuIwEf+sA8!-u(X3+V8M%u5t_9fOrObcOBp9sSJQZD<+M=2;vkETXnHqVOcb2Fm<| z8n=9A&$B|=8(>DXkD_5ikyz0?+b^9bM&YH8_LqBxZkRIL@yAqN zo1a3x2wDr#8}6KLR`$USIlF*PM-Ig#Zsy(lnpcbJK%>W*iC1Q1G@0VG!%51v42ve( zF@>S4hNFYAHieymtV1*3s+{L%)WO;ow!MZy&#sQ?8{S{fhXn?If30(V zgp#!F%Uj2La=9Jfymzmjh0dfjpz-YuR9r4`(v}#twZ;XyNWvMDu=M7{ehx2&>m)L`d`$;3?N-FXaQOR ze;*wg3n*8dknkt<@INa5CvgP2_G7Xq8Vw-1oLB*-#6YP}_!(iA@G!_?N6eq>FoT5Y z7AO(O*SeoxprO*Bc}J+y*aD*8jr>Om [VectorND] { + var centerMoveDist = 0.0 + let zeros = [Double](count: points[0].getLength(), repeatedValue: 0.0) + + var kCenters = reservoirSample(points, k: numCenters) + + repeat { + var cnts = [Double](count: numCenters, repeatedValue: 0.0) + var newCenters = [VectorND](count:numCenters, repeatedValue: VectorND(d:zeros)) + for p in points { + let c = nearestCenter(p, Centers: kCenters) + cnts[c]++ + newCenters[c] += p + } + for idx in 0.. convergeDist) + return kCenters +} +``` + +## Example +These examples are contrived to show the exact nature of K-Means and finding clusters. These clusters are very easily identified by human eyes, we see there is one in the lower left corner, one in the upper right corner and maybe one in the middle. + +In all these examples the stars represent the *centroids* and the squares are the points. + +##### Good clusters +This first example shows K-Means finding all three clusters: +![Good Clustering](Images/k_means_good.png) + +The selection of initial centroids found that lower left (indicated by red) and did pretty good on the center and upper left clusters. + +#### Bad Clustering +The next two examples highlight the unpredictability of k-Means and how not always does it find the best clustering. +![Bad Clustering 1](Images/k_means_bad1.png) +As you can see in this one the initial *centroids* were all a little two close and the 'blue' didn't quite get to a good place. By adjusting the convergence distance should be able to get it better. + +![Bad Clustering 1](Images/k_means_bad2.png) +This one the blue cluster never really could separate from the red cluster and as such sort of got stuck down there. + +## Performance +The first thing to recognize is that k-Means is classified as an NP-Hard type of problem. The selection of the initial *centroids* has a big effect on how the resulting clusters may end up. This means that trying to find an exact solution is not likely - even in 2 dimensional space. + +As seem from the steps above the complexity really isn't that bad - it is often considered to be on the order of O(kndi), where **k** is the number of *centroids*, **n** is the number of **d** dimensional vectors and **i** is the number of iterations for convergence. + +The amount of data has a big linear effect on the running time of k-means, but tuning how far you want the *centroids* to converge can have a big impact how many iterations will be done - **k** should be relatively small compared to the number of vectors. + +Often times as more data is added certain points may lie in the boundary between two *centroids* and as such those centroids would continue to bounce back and forth and the **convergence** distance would need to be tuned to prevent that. + +## See Also +See also [Wikipedia](https://en.wikipedia.org/wiki/K-means_clustering) + +*Written by John Gill* diff --git a/README.markdown b/README.markdown index f19944aa3..241099e98 100644 --- a/README.markdown +++ b/README.markdown @@ -96,13 +96,16 @@ Bad sorting algorithms (don't use these!): ### Machine learning -- [k-Means](K-Means/). Unsupervised classifier that partitions data into k clusters. +##### Supervised learning - k-Nearest Neighbors - Linear Regression - Logistic Regression - Neural Networks - PageRank +##### Clustering +- [k-Means](K-Means/). Unsupervised classifier that partitions data into k clusters. + ## Data structures The choice of data structure for a particular task depends on a few things. From 3c228e980e363119ad5e7ed472f0cff5576c947d Mon Sep 17 00:00:00 2001 From: John Gill Date: Sun, 28 Feb 2016 14:44:04 -0800 Subject: [PATCH 0083/1679] Modify main README to add k-Means --- README.markdown | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/README.markdown b/README.markdown index 241099e98..984bb1bfd 100644 --- a/README.markdown +++ b/README.markdown @@ -95,17 +95,13 @@ Bad sorting algorithms (don't use these!): - Statistics ### Machine learning - -##### Supervised learning +- [k-Means](K-Means/). Unsupervised classifier that partitions data into k clusters. - k-Nearest Neighbors - Linear Regression - Logistic Regression - Neural Networks - PageRank -##### Clustering -- [k-Means](K-Means/). Unsupervised classifier that partitions data into k clusters. - ## Data structures The choice of data structure for a particular task depends on a few things. From 824e88fd7ff2d0308f022702688a8f6f4383b4f5 Mon Sep 17 00:00:00 2001 From: John Gill Date: Mon, 29 Feb 2016 18:34:09 -0800 Subject: [PATCH 0084/1679] Move kMeans from playground to project --- K-Means/K-Means.playground/Contents.swift | 140 ---------- .../K-Means.playground/contents.xcplayground | 4 - .../K-Means.playground/timeline.xctimeline | 41 --- K-Means/KMeans.swift | 168 ++++------- K-Means/README.md | 4 +- K-Means/Tests/Info.plist | 24 ++ K-Means/Tests/KMeansTests.swift | 65 +++++ K-Means/Tests/Tests.xcodeproj/project.pbxproj | 261 ++++++++++++++++++ K-Means/Tests/Vector.swift | 76 +++++ 9 files changed, 482 insertions(+), 301 deletions(-) delete mode 100644 K-Means/K-Means.playground/Contents.swift delete mode 100644 K-Means/K-Means.playground/contents.xcplayground delete mode 100644 K-Means/K-Means.playground/timeline.xctimeline create mode 100644 K-Means/Tests/Info.plist create mode 100644 K-Means/Tests/KMeansTests.swift create mode 100644 K-Means/Tests/Tests.xcodeproj/project.pbxproj create mode 100644 K-Means/Tests/Vector.swift diff --git a/K-Means/K-Means.playground/Contents.swift b/K-Means/K-Means.playground/Contents.swift deleted file mode 100644 index 9f35e5863..000000000 --- a/K-Means/K-Means.playground/Contents.swift +++ /dev/null @@ -1,140 +0,0 @@ -// -// K-Means.swift -// -// Created by John Gill on 2/25/16. - -import Foundation - -// Need a container to easily hold N Dimensional Vectors -class VectorND: CustomStringConvertible { - private var length = 0 - private var data = [Double]() - - init(d:[Double]) { - data = d - length = d.count - } - - var description: String { return "VectorND (\(data)" } - func getData() -> [Double] { return data } - func getLength() -> Int { return length } -} - -// MARK: VectorND Operators -func +(left: VectorND, right: VectorND) -> VectorND { - var results = [Double](count: left.getLength(), repeatedValue: 0.0) - for idx in 0.. VectorND { - var results = [Double](count: left.getLength(), repeatedValue: 0.0) - for (idx, value) in left.getData().enumerate() { - results[idx] = value / right - } - return VectorND(d: results) -} -func /=(inout left: VectorND, right: Double) { - left = left / right -} - -// MARK: Assist Functions -// Pick a k random elements from samples -func reservoirSample(samples:[VectorND], k:Int) -> [VectorND] { - var result = [VectorND]() - - // Fill the result array with first k elements - for i in 0.. Double { - var result = 0.0 - for idx in 0.. Int { - var nearestDist = DBL_MAX - var minIndex = 0; - - for (idx, c) in Centers.enumerate() { - let dist = euclidean(x, v2: c) - if dist < nearestDist { - minIndex = idx - nearestDist = dist - } - } - return minIndex -} - -// MARK: Main Function -func kMeans(numCenters: Int, convergeDist: Double, points: [VectorND]) -> [VectorND] { - var centerMoveDist = 0.0 - let zeros = [Double](count: points[0].getLength(), repeatedValue: 0.0) - - // 1. Choose k Random VectorNDs as the initial centers - var kCenters = reservoirSample(points, k: numCenters) - - // do following steps until convergence - repeat { - var cnts = [Double](count: numCenters, repeatedValue: 0.0) - var newCenters = [VectorND](count:numCenters, repeatedValue: VectorND(d:zeros)) - // 2. Assign VectorNDs to centers - // a. Determine which center each VectorND is closest to - // b. Record how many VectorNDs are assigned to each center - for p in points { - let c = nearestCenter(p, Centers: kCenters) - cnts[c]++ - newCenters[c] += p - } - // 3. Calculate a new centers - for idx in 0.. convergeDist) - return kCenters -} - -// MARK: Sample Data -var points = [VectorND]() -let numPoints = 10 -let numDimmensions = 5 -for _ in 0.. - - - \ No newline at end of file diff --git a/K-Means/K-Means.playground/timeline.xctimeline b/K-Means/K-Means.playground/timeline.xctimeline deleted file mode 100644 index 850856b0b..000000000 --- a/K-Means/K-Means.playground/timeline.xctimeline +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/K-Means/KMeans.swift b/K-Means/KMeans.swift index 05e973ba0..9a3193bfe 100644 --- a/K-Means/KMeans.swift +++ b/K-Means/KMeans.swift @@ -5,55 +5,71 @@ import Foundation -// Need a container to easily hold N Dimensional Vectors -class VectorND: CustomStringConvertible { - private var length = 0 - private var data = [Double]() - - init(d:[Double]) { - data = d - length = d.count +class KMeans { + var numCenters:Int + var convergeDist:Double + + init(numCenters:Int, convergeDist:Double) { + self.numCenters = numCenters + self.convergeDist = convergeDist } - - var description: String { return "VectorND (\(data)" } - func getData() -> [Double] { return data } - func getLength() -> Int { return length } -} - -// MARK: VectorND Operators -func +(left: VectorND, right: VectorND) -> VectorND { - var results = [Double](count: left.getLength(), repeatedValue: 0.0) - for idx in 0.. Int { + var nearestDist = DBL_MAX + var minIndex = 0; + + for (idx, c) in Centers.enumerate() { + let dist = x.distTo(c) + if dist < nearestDist { + minIndex = idx + nearestDist = dist + } + } + return minIndex } - return VectorND(d: results) -} -func +=(inout left: VectorND, right: VectorND) { - left = left + right -} -func /(left:VectorND, right: Double) -> VectorND { - var results = [Double](count: left.getLength(), repeatedValue: 0.0) - for (idx, value) in left.getData().enumerate() { - results[idx] = value / right + + func findCenters(points: [Vector]) -> [Vector] { + var centerMoveDist = 0.0 + let zeros = [Double](count: points[0].length, repeatedValue: 0.0) + + var kCenters = reservoirSample(points, k: numCenters) + + repeat { + var cnts = [Double](count: numCenters, repeatedValue: 0.0) + var newCenters = [Vector](count:numCenters, repeatedValue: Vector(d:zeros)) + + for p in points { + let c = nearestCenter(p, Centers: kCenters) + cnts[c]++ + newCenters[c] += p + } + + for idx in 0.. convergeDist) + return kCenters } - return VectorND(d: results) -} -func /=(inout left: VectorND, right: Double) { - left = left / right } -// MARK: Assist Functions -// Pick a k random elements from samples -func reservoirSample(samples:[VectorND], k:Int) -> [VectorND] { - var result = [VectorND]() +// Pick k random elements from samples +func reservoirSample(samples:[T], k:Int) -> [T] { + var result = [T]() // Fill the result array with first k elements for i in 0.. [VectorND] { return result } -// Calculates the Euclidean distance between two VectorNDs -func euclidean(v1:VectorND, v2:VectorND) -> Double { - var result = 0.0 - for idx in 0.. Int { - var nearestDist = DBL_MAX - var minIndex = 0; - - for (idx, c) in Centers.enumerate() { - let dist = euclidean(x, v2: c) - if dist < nearestDist { - minIndex = idx - nearestDist = dist - } - } - return minIndex -} - -// MARK: Main Function -func kMeans(numCenters: Int, convergeDist: Double, points: [VectorND]) -> [VectorND] { - var centerMoveDist = 0.0 - let zeros = [Double](count: points[0].getLength(), repeatedValue: 0.0) - - // 1. Choose k Random VectorNDs as the initial centers - var kCenters = reservoirSample(points, k: numCenters) - - // do following steps until convergence - repeat { - var cnts = [Double](count: numCenters, repeatedValue: 0.0) - var newCenters = [VectorND](count:numCenters, repeatedValue: VectorND(d:zeros)) - // 2. Assign VectorNDs to centers - // a. Determine which center each VectorND is closest to - // b. Record how many VectorNDs are assigned to each center - for p in points { - let c = nearestCenter(p, Centers: kCenters) - cnts[c]++ - newCenters[c] += p - } - // 3. Calculate a new centers - for idx in 0.. convergeDist) - return kCenters -} - -// MARK: Sample Data -var points = [VectorND]() -let numPoints = 10 -let numDimmensions = 5 -for _ in 0.. [VectorND] { +func kMeans(numCenters: Int, convergeDist: Double, points: [Vector]) -> [Vector] { var centerMoveDist = 0.0 let zeros = [Double](count: points[0].getLength(), repeatedValue: 0.0) @@ -30,7 +30,7 @@ func kMeans(numCenters: Int, convergeDist: Double, points: [VectorND]) -> [Vecto repeat { var cnts = [Double](count: numCenters, repeatedValue: 0.0) - var newCenters = [VectorND](count:numCenters, repeatedValue: VectorND(d:zeros)) + var newCenters = [Vector](count:numCenters, repeatedValue: Vector(d:zeros)) for p in points { let c = nearestCenter(p, Centers: kCenters) cnts[c]++ diff --git a/K-Means/Tests/Info.plist b/K-Means/Tests/Info.plist new file mode 100644 index 000000000..ba72822e8 --- /dev/null +++ b/K-Means/Tests/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/K-Means/Tests/KMeansTests.swift b/K-Means/Tests/KMeansTests.swift new file mode 100644 index 000000000..436cab4fe --- /dev/null +++ b/K-Means/Tests/KMeansTests.swift @@ -0,0 +1,65 @@ +// +// Tests.swift +// Tests +// +// Created by John Gill on 2/29/16. +// +// + +import Foundation +import XCTest + +class KMeansTests: XCTestCase { + var points = [Vector]() + + func genPoints(numPoints:Int, numDimmensions:Int) { + for _ in 0.. Double { + var result = 0.0 + for idx in 0.. Bool { + for idx in 0.. Vector { + var results = [Double]() + for idx in 0.. Vector { + var results = [Double]() + for idx in 0.. Vector { + var results = [Double](count: left.length, repeatedValue: 0.0) + for (idx, value) in left.data.enumerate() { + results[idx] = value / right + } + return Vector(d: results) +} + +func /=(inout left: Vector, right: Double) { + left = left / right +} \ No newline at end of file From 6cc2f29f6b2c30cc6f59e70e2ea1d59e1a9749ae Mon Sep 17 00:00:00 2001 From: jamil Date: Mon, 29 Feb 2016 22:21:10 -0500 Subject: [PATCH 0085/1679] Add README --- Bloom Filter/README.markdown | 58 ++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 Bloom Filter/README.markdown diff --git a/Bloom Filter/README.markdown b/Bloom Filter/README.markdown new file mode 100644 index 000000000..f50877138 --- /dev/null +++ b/Bloom Filter/README.markdown @@ -0,0 +1,58 @@ +# Binary Tree + +## Introduction + +A Bloom Filter is a space-efficient data structure to check for an element in a set, that guarantees that there are no false negatives on queries. In other words, a query to a Bloom filter either returns "false", meaning the element is definitely not in the set, or "true", meaning that the element could be in the set. At first, this may not seem too useful. However, it's important in applications like cache filtering and data synchronization. + +An advantage of the Bloom Filter over a hash table is that the former maintains constant memory usage and constant-time insert and search. For a large number of elements in a set, the performance difference between a hash table and a Bloom Filter is significant, and it is a viable option if you do not need the guarantee of no false positives. + +## Implementation + +A Bloom Filter is essentially a fixed-length bit vector. To insert an element in the filter, it is hashed with *m* different hash functions, which map to indices in the array. The bits at these indices are set to `1`, or `true`, when an element is inserted. + +Querying, similarly, is accomplished by hashing the expected value, and checking to see if all of the bits at the indices are `true`. If even one of the bits is not `true`, the element could not have been inserted - and the query returns `false`. If all the bits are `true`, the query returns likewise. If there are "collisions", the query may erroneously return `true` even though the element was not inserted - bringing about the issue with false positives mentioned earlier. + +Deletion is not possible with a Bloom Filter, since any one bit might have been set by multiple elements inserted. Once you add an element, it's in there for good. + +## The Code + +The code is extremely straightforward, as you can imagine. The internal bit array is set to a fixed length on initialization, which cannot be mutated once it is initialized. Several hash functions should be specified at initialization, which will depend on the types you're using. You can see some examples in the tests - the djb2 and sdbm hash functions for strings. + +```swift +public init(size: Int = 1024, hashFunctions: [T -> Int]) { + self.arr = Array(count: size, repeatedValue: false) + self.hashFunctions = hashFunctions +} +``` + +Insertion just flips the required bits to `true`: + +```swift +public func insert(toInsert: T) { + let hashValues: [Int] = self.computeHashes(toInsert) + + for hashValue in hashValues { + self.arr[hashValue] = true + } +} +``` + +And querying checks to make sure the bits at the hashed values are `true`: + +```swift +public func query(value: T) -> Bool { + let hashValues = self.computeHashes(value) + + let results = hashValues.map() { hashValue in + self.arr[hashValue] + } + + let exists = results.reduce(true, combine: { $0 && $1 }) + + return exists +} +``` + +If you're coming from another imperative language, you might notice the unusual syntax in the `exists` constant assignment. Swift makes use of functional paradigms when it makes code more consise and readable, and in this case, `reduce` is a much more consise way to check if all the required bits are `true` than a `for` loop. + +*Written for Swift Algorithm Club by Jamil Dhanani* From 7faca17d67592f8c072ac5615d040e8807a9e9d5 Mon Sep 17 00:00:00 2001 From: jamil Date: Mon, 29 Feb 2016 22:21:40 -0500 Subject: [PATCH 0086/1679] Remove Info.plist in Test directory --- Bloom Filter/BloomFilterTests/Info.plist | 24 ------------------------ 1 file changed, 24 deletions(-) delete mode 100644 Bloom Filter/BloomFilterTests/Info.plist diff --git a/Bloom Filter/BloomFilterTests/Info.plist b/Bloom Filter/BloomFilterTests/Info.plist deleted file mode 100644 index ba72822e8..000000000 --- a/Bloom Filter/BloomFilterTests/Info.plist +++ /dev/null @@ -1,24 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - BNDL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - - From cf97f25bfb3a615671e12d0fdbab82d8d2d5fd19 Mon Sep 17 00:00:00 2001 From: Jamil Dhanani Date: Mon, 29 Feb 2016 22:31:31 -0500 Subject: [PATCH 0087/1679] Fix typos in README --- Bloom Filter/README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Bloom Filter/README.markdown b/Bloom Filter/README.markdown index f50877138..f06bef5bd 100644 --- a/Bloom Filter/README.markdown +++ b/Bloom Filter/README.markdown @@ -1,4 +1,4 @@ -# Binary Tree +# Bloom Filter ## Introduction From 11e3d64c90fa5369a1898d9dee9ef73f7b73871f Mon Sep 17 00:00:00 2001 From: jamil Date: Mon, 29 Feb 2016 22:39:20 -0500 Subject: [PATCH 0088/1679] Add Bloom Filter to README --- README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.markdown b/README.markdown index 579e7c182..c53232982 100644 --- a/README.markdown +++ b/README.markdown @@ -154,7 +154,7 @@ Most of the time using just the built-in `Array`, `Dictionary`, and `Set` types ### Sets -- Bloom Filter +- [Bloom Filter](Bloom Filter/). A constant-memory data structure that probabilistically tests whether an element is in a set. - [Hash Set](Hash Set/). A set implemented using a hash table. - Multiset - Ordered Set From a070fb29613b36acf50e14795f348af93d457f7b Mon Sep 17 00:00:00 2001 From: John Gill Date: Sun, 28 Feb 2016 18:01:20 -0800 Subject: [PATCH 0089/1679] Initital implementation of Bounded Priority Queue --- .../BoundedPriorityQueue.swift | 105 +++++++ .../Tests/BoundedPriorityQueueTests.swift | 115 ++++++++ Bounded Priority Queue/Tests/Info.plist | 24 ++ .../Tests/Tests.xcodeproj/project.pbxproj | 260 ++++++++++++++++++ .../Contents.swift | 47 ++++ .../contents.xcplayground | 4 + .../timeline.xctimeline | 31 +++ K-Nearest Neighbors/README.md | 7 + 8 files changed, 593 insertions(+) create mode 100644 Bounded Priority Queue/BoundedPriorityQueue.swift create mode 100644 Bounded Priority Queue/Tests/BoundedPriorityQueueTests.swift create mode 100644 Bounded Priority Queue/Tests/Info.plist create mode 100644 Bounded Priority Queue/Tests/Tests.xcodeproj/project.pbxproj create mode 100644 K-Nearest Neighbors/K-Nearest Neighbors.playground/Contents.swift create mode 100644 K-Nearest Neighbors/K-Nearest Neighbors.playground/contents.xcplayground create mode 100644 K-Nearest Neighbors/K-Nearest Neighbors.playground/timeline.xctimeline create mode 100644 K-Nearest Neighbors/README.md diff --git a/Bounded Priority Queue/BoundedPriorityQueue.swift b/Bounded Priority Queue/BoundedPriorityQueue.swift new file mode 100644 index 000000000..f5f3a2221 --- /dev/null +++ b/Bounded Priority Queue/BoundedPriorityQueue.swift @@ -0,0 +1,105 @@ +// +// BoundedPriorityQueue.swift +// Tests +// +// Created by John Gill on 2/28/16. +// Copyright © 2016 Swift Algorithm Club. All rights reserved. +// + +import Foundation + +public class LinkedListNode { + var value: T + var next: LinkedListNode? + var previous: LinkedListNode? + + public init(value: T) { + self.value = value + self.next = nil + self.previous = nil + } +} + +public class BoundedPriorityQueue { + public typealias Node = LinkedListNode + private var head: Node? + private var isLessThan:(T, T) -> Bool + private var curNumElements:Int + private var maxNumElements: Int + + public init(sort: (T, T) -> Bool, maxElements:Int) { + isLessThan = sort + head = nil + maxNumElements = maxElements + curNumElements = 0 + } + + public var isEmpty: Bool { + return curNumElements == 0 + } + + public var count: Int { + return curNumElements + } + + public func peek() -> T? { + if curNumElements > 0 { + return head!.value + } + return nil + } + + public func enqueue(value: T) { + let newNode = Node(value: value) + + if head == nil { + head = newNode + } else { + var node = head + if curNumElements == maxNumElements && !isLessThan(newNode.value, node!.value) { + return + } + + while node!.next != nil && isLessThan(newNode.value, node!.value) { node = node!.next } + + if isLessThan(newNode.value, node!.value) { + newNode.next = node!.next + newNode.previous = node + + if(newNode.next != nil) { /* TAIL */ + newNode.next!.previous = newNode + } + node!.next = newNode + } else { + newNode.previous = node!.previous + newNode.next = node + if(node!.previous == nil) { /* HEAD */ + head = newNode + } else { + node!.previous!.next = newNode + } + node!.previous = newNode + } + if(curNumElements == maxNumElements) { dequeue() } + } + curNumElements++ + } + + public func dequeue() -> T? { + if curNumElements > 0 { + let retVal = head!.value + + if curNumElements == 1 { + head = nil + } + else { + head = head!.next + head!.previous = nil + } + + curNumElements-- + return retVal + } + return nil + } +} \ No newline at end of file diff --git a/Bounded Priority Queue/Tests/BoundedPriorityQueueTests.swift b/Bounded Priority Queue/Tests/BoundedPriorityQueueTests.swift new file mode 100644 index 000000000..4b68b0bab --- /dev/null +++ b/Bounded Priority Queue/Tests/BoundedPriorityQueueTests.swift @@ -0,0 +1,115 @@ +// +// BoundedPriorityQueueTests.swift +// Tests +// +// Created by John Gill on 2/28/16. +// Copyright © 2016 Swift Algorithm Club. All rights reserved. +// + +import Foundation +import XCTest + +private struct Message { + let name: String + let priority: Int +} + +private func < (m1: Message, m2: Message) -> Bool { + return m1.priority < m2.priority +} + +class BoundedPriorityQueueTest: XCTestCase { + func testEmpty() { + let queue = BoundedPriorityQueue(sort: <, maxElements: 5) + XCTAssertTrue(queue.isEmpty) + XCTAssertEqual(queue.count, 0) + XCTAssertNil(queue.dequeue()) + } + + func testOneElement() { + let queue = BoundedPriorityQueue(sort: <, maxElements: 5) + + queue.enqueue(Message(name: "hello", priority: 100)) + XCTAssertFalse(queue.isEmpty) + XCTAssertEqual(queue.count, 1) + + let result = queue.dequeue() + XCTAssertEqual(result!.priority, 100) + XCTAssertTrue(queue.isEmpty) + XCTAssertEqual(queue.count, 0) + } + + func testMaxElements() { + let queue = BoundedPriorityQueue(sort: <, maxElements: 5) + XCTAssertTrue(queue.isEmpty) + + queue.enqueue(Message(name: "john", priority: 100)) + XCTAssertEqual(queue.count, 1) + XCTAssertEqual(queue.peek()?.priority, 100) + + queue.enqueue(Message(name: "james", priority: 200)) + XCTAssertEqual(queue.count, 2) + XCTAssertEqual(queue.peek()?.priority, 200) + + queue.enqueue(Message(name: "mark", priority: 300)) + XCTAssertEqual(queue.count, 3) + XCTAssertEqual(queue.peek()?.priority, 300) + + queue.enqueue(Message(name: "ken", priority: 400)) + XCTAssertEqual(queue.count, 4) + XCTAssertEqual(queue.peek()?.priority, 400) + + queue.enqueue(Message(name: "thomas", priority: 500)) + XCTAssertEqual(queue.count, 5) + XCTAssertEqual(queue.peek()?.priority, 500) + + queue.enqueue(Message(name: "melanie", priority: 550)) + XCTAssertEqual(queue.count, 5) + XCTAssertEqual(queue.peek()?.priority, 500) + + queue.enqueue(Message(name: "lily", priority: 450)) + XCTAssertEqual(queue.count, 5) + XCTAssertEqual(queue.peek()?.priority, 450) + + queue.enqueue(Message(name: "fred", priority: 350)) + XCTAssertEqual(queue.count, 5) + XCTAssertEqual(queue.peek()?.priority, 400) + + queue.enqueue(Message(name: "rachel", priority: 50)) + XCTAssertEqual(queue.count, 5) + XCTAssertEqual(queue.peek()?.priority, 350) + + var result = queue.dequeue() + XCTAssertEqual(result!.priority, 350) + XCTAssertEqual(queue.count, 4) + + result = queue.dequeue() + XCTAssertEqual(result!.priority, 300) + XCTAssertEqual(queue.count, 3) + + result = queue.dequeue() + XCTAssertEqual(result!.priority, 200) + XCTAssertEqual(queue.count, 2) + + queue.enqueue(Message(name: "ryan", priority: 150)) + XCTAssertEqual(queue.count, 3) + XCTAssertEqual(queue.peek()?.priority, 150) + + result = queue.dequeue() + XCTAssertEqual(result!.priority, 150) + XCTAssertEqual(queue.count, 2) + + result = queue.dequeue() + XCTAssertEqual(result!.priority, 100) + XCTAssertEqual(queue.count, 1) + + result = queue.dequeue() + XCTAssertEqual(result!.priority, 50) + XCTAssertEqual(queue.count, 0) + + result = queue.dequeue() + XCTAssertNil(result) + XCTAssertEqual(queue.count, 0) + XCTAssertTrue(queue.isEmpty) + } +} \ No newline at end of file diff --git a/Bounded Priority Queue/Tests/Info.plist b/Bounded Priority Queue/Tests/Info.plist new file mode 100644 index 000000000..ba72822e8 --- /dev/null +++ b/Bounded Priority Queue/Tests/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/Bounded Priority Queue/Tests/Tests.xcodeproj/project.pbxproj b/Bounded Priority Queue/Tests/Tests.xcodeproj/project.pbxproj new file mode 100644 index 000000000..2920474ae --- /dev/null +++ b/Bounded Priority Queue/Tests/Tests.xcodeproj/project.pbxproj @@ -0,0 +1,260 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + B810B5B11C83E3B200450324 /* BoundedPriorityQueueTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B810B5B01C83E3B200450324 /* BoundedPriorityQueueTests.swift */; }; + B8F635A81C83E4270060805E /* BoundedPriorityQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8F635A71C83E4270060805E /* BoundedPriorityQueue.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + B80004B31C83E342001FE2D7 /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + B80004B81C83E342001FE2D7 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; + B810B5B01C83E3B200450324 /* BoundedPriorityQueueTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BoundedPriorityQueueTests.swift; path = ../BoundedPriorityQueueTests.swift; sourceTree = ""; }; + B8F635A71C83E4270060805E /* BoundedPriorityQueue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BoundedPriorityQueue.swift; path = ../../BoundedPriorityQueue.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + B80004B01C83E342001FE2D7 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + B80004A81C83E324001FE2D7 = { + isa = PBXGroup; + children = ( + B80004B51C83E342001FE2D7 /* Tests */, + B80004B41C83E342001FE2D7 /* Products */, + ); + sourceTree = ""; + }; + B80004B41C83E342001FE2D7 /* Products */ = { + isa = PBXGroup; + children = ( + B80004B31C83E342001FE2D7 /* Tests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + B80004B51C83E342001FE2D7 /* Tests */ = { + isa = PBXGroup; + children = ( + B8F635A71C83E4270060805E /* BoundedPriorityQueue.swift */, + B810B5B01C83E3B200450324 /* BoundedPriorityQueueTests.swift */, + B80004B81C83E342001FE2D7 /* Info.plist */, + ); + path = Tests; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + B80004B21C83E342001FE2D7 /* Tests */ = { + isa = PBXNativeTarget; + buildConfigurationList = B80004B91C83E342001FE2D7 /* Build configuration list for PBXNativeTarget "Tests" */; + buildPhases = ( + B80004AF1C83E342001FE2D7 /* Sources */, + B80004B11C83E342001FE2D7 /* Resources */, + B80004B01C83E342001FE2D7 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Tests; + productName = Tests; + productReference = B80004B31C83E342001FE2D7 /* Tests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + B80004A91C83E324001FE2D7 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0720; + LastUpgradeCheck = 0720; + TargetAttributes = { + B80004B21C83E342001FE2D7 = { + CreatedOnToolsVersion = 7.2.1; + }; + }; + }; + buildConfigurationList = B80004AC1C83E324001FE2D7 /* Build configuration list for PBXProject "Tests" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = B80004A81C83E324001FE2D7; + productRefGroup = B80004B41C83E342001FE2D7 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + B80004B21C83E342001FE2D7 /* Tests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + B80004B11C83E342001FE2D7 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + B80004AF1C83E342001FE2D7 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + B810B5B11C83E3B200450324 /* BoundedPriorityQueueTests.swift in Sources */, + B8F635A81C83E4270060805E /* BoundedPriorityQueue.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + B80004AD1C83E324001FE2D7 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + }; + name = Debug; + }; + B80004AE1C83E324001FE2D7 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + }; + name = Release; + }; + B80004BA1C83E342001FE2D7 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + INFOPLIST_FILE = Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_BUNDLE_IDENTIFIER = com.alvahouse322.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + SWIFT_OBJC_BRIDGING_HEADER = ""; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + B80004BB1C83E342001FE2D7 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + INFOPLIST_FILE = Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_BUNDLE_IDENTIFIER = com.alvahouse322.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + SWIFT_OBJC_BRIDGING_HEADER = ""; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + B80004AC1C83E324001FE2D7 /* Build configuration list for PBXProject "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + B80004AD1C83E324001FE2D7 /* Debug */, + B80004AE1C83E324001FE2D7 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + B80004B91C83E342001FE2D7 /* Build configuration list for PBXNativeTarget "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + B80004BA1C83E342001FE2D7 /* Debug */, + B80004BB1C83E342001FE2D7 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = B80004A91C83E324001FE2D7 /* Project object */; +} diff --git a/K-Nearest Neighbors/K-Nearest Neighbors.playground/Contents.swift b/K-Nearest Neighbors/K-Nearest Neighbors.playground/Contents.swift new file mode 100644 index 000000000..a4dd21dd0 --- /dev/null +++ b/K-Nearest Neighbors/K-Nearest Neighbors.playground/Contents.swift @@ -0,0 +1,47 @@ +// +// K-NearestNeighbors.swift +// +// Created by John Gill on 2/23/16. +import Foundation + +// Container to easily hold N Dimensional Vectors +class VectorND: CustomStringConvertible { + private var length = 0 + private var data = [Double]() + + init(d:[Double]) { + data = d + length = d.count + } + + var description: String { return "VectorND (\(data)" } + func getData() -> [Double] { return data } + func getLength() -> Int { return length } + + // Calculates the Euclidean distance from + // this point to another VectorND + func getDist(v:VectorND) -> Double { + var result = 0.0 + for idx in 0.. [Int] { + + return [] + } +} \ No newline at end of file diff --git a/K-Nearest Neighbors/K-Nearest Neighbors.playground/contents.xcplayground b/K-Nearest Neighbors/K-Nearest Neighbors.playground/contents.xcplayground new file mode 100644 index 000000000..9f9eecc96 --- /dev/null +++ b/K-Nearest Neighbors/K-Nearest Neighbors.playground/contents.xcplayground @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/K-Nearest Neighbors/K-Nearest Neighbors.playground/timeline.xctimeline b/K-Nearest Neighbors/K-Nearest Neighbors.playground/timeline.xctimeline new file mode 100644 index 000000000..4dca8e784 --- /dev/null +++ b/K-Nearest Neighbors/K-Nearest Neighbors.playground/timeline.xctimeline @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + diff --git a/K-Nearest Neighbors/README.md b/K-Nearest Neighbors/README.md new file mode 100644 index 000000000..9e22c4a02 --- /dev/null +++ b/K-Nearest Neighbors/README.md @@ -0,0 +1,7 @@ +# k-Nearest Neighbors + +Goal: Label Data into Clusters by k Nearest other points + +Machine Learning algorithms are two pass: + 1. Train the algorithm on a set of Data + 2. Predict new labels for data based on training From f0d833a5a718ea23b381ce22cc658ae63dec19c8 Mon Sep 17 00:00:00 2001 From: Matthijs Hollemans Date: Tue, 1 Mar 2016 19:59:35 +0100 Subject: [PATCH 0090/1679] Tweak text and code style Add examples to description Add playground Add test project --- .../BloomFilter.playground/Contents.swift | 86 ++++++ .../contents.xcplayground | 4 + .../timeline.xctimeline | 6 + Bloom Filter/BloomFilter.swift | 90 +++--- Bloom Filter/README.markdown | 93 +++++-- .../BloomFilterTests.swift | 2 - Bloom Filter/Tests/Info.plist | 24 ++ .../Tests/Tests.xcodeproj/project.pbxproj | 261 ++++++++++++++++++ 8 files changed, 488 insertions(+), 78 deletions(-) create mode 100644 Bloom Filter/BloomFilter.playground/Contents.swift create mode 100644 Bloom Filter/BloomFilter.playground/contents.xcplayground create mode 100644 Bloom Filter/BloomFilter.playground/timeline.xctimeline rename Bloom Filter/{BloomFilterTests => Tests}/BloomFilterTests.swift (98%) create mode 100644 Bloom Filter/Tests/Info.plist create mode 100644 Bloom Filter/Tests/Tests.xcodeproj/project.pbxproj diff --git a/Bloom Filter/BloomFilter.playground/Contents.swift b/Bloom Filter/BloomFilter.playground/Contents.swift new file mode 100644 index 000000000..0727ea439 --- /dev/null +++ b/Bloom Filter/BloomFilter.playground/Contents.swift @@ -0,0 +1,86 @@ +//: Playground - noun: a place where people can play + +public class BloomFilter { + private var array: [Bool] + private var hashFunctions: [T -> Int] + + public init(size: Int = 1024, hashFunctions: [T -> Int]) { + self.array = .init(count: size, repeatedValue: false) + self.hashFunctions = hashFunctions + } + + private func computeHashes(value: T) -> [Int] { + return hashFunctions.map() { hashFunc in abs(hashFunc(value) % array.count) } + } + + public func insert(element: T) { + for hashValue in computeHashes(element) { + array[hashValue] = true + } + } + + public func insert(values: [T]) { + for value in values { + insert(value) + } + } + + public func query(value: T) -> Bool { + let hashValues = computeHashes(value) + + // Map hashes to indices in the Bloom Filter + let results = hashValues.map() { hashValue in array[hashValue] } + + // All values must be 'true' for the query to return true + + // This does NOT imply that the value is in the Bloom filter, + // only that it may be. If the query returns false, however, + // you can be certain that the value was not added. + + let exists = results.reduce(true, combine: { $0 && $1 }) + return exists + } + + public func isEmpty() -> Bool { + // As soon as the reduction hits a 'true' value, the && condition will fail. + return array.reduce(true) { prev, next in prev && !next } + } +} + + + +/* Two hash functions, adapted from http://www.cse.yorku.ca/~oz/hash.html */ + +func djb2(x: String) -> Int { + var hash = 5381 + for char in x.characters { + hash = ((hash << 5) &+ hash) &+ char.hashValue + } + return Int(hash) +} + +func sdbm(x: String) -> Int { + var hash = 0 + for char in x.characters { + hash = char.hashValue &+ (hash << 6) &+ (hash << 16) &- hash + } + return Int(hash) +} + + + +/* A simple test */ + +let bloom = BloomFilter(size: 17, hashFunctions: [djb2, sdbm]) + +bloom.insert("Hello world!") +print(bloom.array) + +bloom.query("Hello world!") // true +bloom.query("Hello WORLD") // false + +bloom.insert("Bloom Filterz") +print(bloom.array) + +bloom.query("Bloom Filterz") // true +bloom.query("Hello WORLD") // true diff --git a/Bloom Filter/BloomFilter.playground/contents.xcplayground b/Bloom Filter/BloomFilter.playground/contents.xcplayground new file mode 100644 index 000000000..06828af92 --- /dev/null +++ b/Bloom Filter/BloomFilter.playground/contents.xcplayground @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Bloom Filter/BloomFilter.playground/timeline.xctimeline b/Bloom Filter/BloomFilter.playground/timeline.xctimeline new file mode 100644 index 000000000..bf468afec --- /dev/null +++ b/Bloom Filter/BloomFilter.playground/timeline.xctimeline @@ -0,0 +1,6 @@ + + + + + diff --git a/Bloom Filter/BloomFilter.swift b/Bloom Filter/BloomFilter.swift index 6f5232b0d..83787ee7b 100644 --- a/Bloom Filter/BloomFilter.swift +++ b/Bloom Filter/BloomFilter.swift @@ -1,58 +1,46 @@ -import Foundation - public class BloomFilter { - private(set) private var arr: [Bool] - private(set) private var hashFunctions: [T -> Int] - - public init(size: Int = 1024, hashFunctions: [T -> Int]) { - self.arr = Array(count: size, repeatedValue: false) - self.hashFunctions = hashFunctions + private var array: [Bool] + private var hashFunctions: [T -> Int] + + public init(size: Int = 1024, hashFunctions: [T -> Int]) { + self.array = .init(count: size, repeatedValue: false) + self.hashFunctions = hashFunctions + } + + private func computeHashes(value: T) -> [Int] { + return hashFunctions.map() { hashFunc in abs(hashFunc(value) % array.count) } + } + + public func insert(element: T) { + for hashValue in computeHashes(element) { + array[hashValue] = true } - - private func computeHashes(value: T) -> [Int] { - return hashFunctions.map() { hashFunc in - abs(hashFunc(value) % self.arr.count) - } + } + + public func insert(values: [T]) { + for value in values { + insert(value) } + } + + public func query(value: T) -> Bool { + let hashValues = computeHashes(value) - public func insert(toInsert: T) { - let hashValues: [Int] = self.computeHashes(toInsert) - - for hashValue in hashValues { - self.arr[hashValue] = true - } - } + // Map hashes to indices in the Bloom Filter + let results = hashValues.map() { hashValue in array[hashValue] } - public func insert(values: [T]) { - for value in values { - self.insert(value) - } - } + // All values must be 'true' for the query to return true - public func query(value: T) -> Bool { - let hashValues = self.computeHashes(value) - - // Map hashes to indices in the Bloom filter - let results = hashValues.map() { hashValue in - self.arr[hashValue] - } - - // All values must be 'true' for the query to return true - - // This does NOT imply that the value is in the Bloom filter, - // only that it may be. If the query returns false, however, - // you can be certain that the value was not added. - - let exists = results.reduce(true, combine: { $0 && $1 }) - - return exists - } - - public func isEmpty() -> Bool { - // Reduce list; as soon as the reduction hits a 'true' value, the && condition will fail - return arr.reduce(true) { prev, next in - prev && !next - } - } + // This does NOT imply that the value is in the Bloom filter, + // only that it may be. If the query returns false, however, + // you can be certain that the value was not added. -} \ No newline at end of file + let exists = results.reduce(true, combine: { $0 && $1 }) + return exists + } + + public func isEmpty() -> Bool { + // As soon as the reduction hits a 'true' value, the && condition will fail. + return array.reduce(true) { prev, next in prev && !next } + } +} diff --git a/Bloom Filter/README.markdown b/Bloom Filter/README.markdown index f06bef5bd..c0c06400b 100644 --- a/Bloom Filter/README.markdown +++ b/Bloom Filter/README.markdown @@ -2,38 +2,86 @@ ## Introduction -A Bloom Filter is a space-efficient data structure to check for an element in a set, that guarantees that there are no false negatives on queries. In other words, a query to a Bloom filter either returns "false", meaning the element is definitely not in the set, or "true", meaning that the element could be in the set. At first, this may not seem too useful. However, it's important in applications like cache filtering and data synchronization. +A Bloom Filter is a space-efficient data structure that tells you whether or not an element is present in a set. -An advantage of the Bloom Filter over a hash table is that the former maintains constant memory usage and constant-time insert and search. For a large number of elements in a set, the performance difference between a hash table and a Bloom Filter is significant, and it is a viable option if you do not need the guarantee of no false positives. +This is a probabilistic data structure: a query to a Bloom filter either returns `false`, meaning the element is definitely not in the set, or `true`, meaning that the element *might* be in the set. -## Implementation +There is a small probability of false positives, where the element isn't actually in the set even though the query returned `true`. But there will never any false negatives: you're guaranteed that if the query returns `false`, then the element really isn't in the set. -A Bloom Filter is essentially a fixed-length bit vector. To insert an element in the filter, it is hashed with *m* different hash functions, which map to indices in the array. The bits at these indices are set to `1`, or `true`, when an element is inserted. +So a Bloom Filter tells you, "definitely not" or "probably yes". -Querying, similarly, is accomplished by hashing the expected value, and checking to see if all of the bits at the indices are `true`. If even one of the bits is not `true`, the element could not have been inserted - and the query returns `false`. If all the bits are `true`, the query returns likewise. If there are "collisions", the query may erroneously return `true` even though the element was not inserted - bringing about the issue with false positives mentioned earlier. +At first, this may not seem too useful. However, it's important in applications like cache filtering and data synchronization. + +An advantage of the Bloom Filter over a hash table is that the former maintains constant memory usage and constant-time insert and search. For sets with a large number of elements, the performance difference between a hash table and a Bloom Filter is significant, and it is a viable option if you do not need the guarantee of no false positives. + +> **Note:** Unlike a hash table, the Bloom Filter does not store the actual objects. It just remembers what objects you’ve seen (with a degree of uncertainty) and which ones you haven’t. + +## How it works + +A Bloom Filter is essentially a fixed-length [bit vector](../Bit Set/), an array of bits. When we insert objects, we set some of these bits to `1`, and when we query for objects we check if certain bits are `0` or `1`. Both operations use hash functions. + +To insert an element in the filter, the element is hashed with several different hash functions. Each hash function returns a value that we map to an index in the array. We set the bits at these indices to `1` or true. + +For example, let's say this is our array of bits. We have 17 bits and initially they are all `0` or false: + + [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ] + +Now we want to insert the string `"Hello world!"` into the Bloom Filter. We apply two hash functions to this string. The first one gives the value 1999532104120917762. We map this hash value to an index into our array by taking the modulo of the array length: `1999532104120917762 % 17 = 4`. This means we set the bit at index 4 to `1` or true: + + [ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ] + +Then we hash the original string again but this time with a different hash function. It gives the hash value 9211818684948223801. Modulo 17 that is 12, and we set the bit at index 12 to `1` as well: + + [ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 ] + +These two bits are enough to tell the Bloom Filter that it now contains the string `"Hello world!"`. + +Querying, similarly, is accomplished by first hashing the expected value, which gives several array indices, and then checking to see if all of the bits at those indices are `true`. If even one of the bits is not `true`, the element could not have been inserted and the query returns `false`. If all the bits are `true`, the query returns likewise. + +For example, if we query for the string `"Hello WORLD"`, then the first hash function returns 5383892684077141175, which modulo 17 is 12. That bit is `1`. But the second hash function gives 5625257205398334446, which maps to array index 9. That bit is `0`. This means the string `"Hello WORLD"` is not in the filter and the query returns `false`. + +The fact that the first hash function mapped to a `1` bit is a coincidence (it has nothing to do with the fact that both strings start with `"Hello "`). Too many such coincidences can lead to "collisions". If there are collisions, the query may erroneously return `true` even though the element was not inserted -- bringing about the issue with false positives mentioned earlier. + +Let's say we insert some other element, `"Bloom Filterz"`, which sets bits 7 and 9. Now the array looks like this: + + [ 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0 ] + +If you query for `"Hello WORLD"` again, the filter sees that bit 12 is true and bit 9 is now true as well. It reports that `"Hello WORLD"` is indeed present in the set, even though it isn't... because we never inserted that particular string. It's a false positive. This example shows why a Bloom Filter will never say, "definitely yes", only "probably yes". + +You can fix such issues by using an array with more bits and using additional hash functions. Of course, the more hash functions you use the slower the Bloom Filter will be. So you have to strike a balance. Deletion is not possible with a Bloom Filter, since any one bit might have been set by multiple elements inserted. Once you add an element, it's in there for good. -## The Code +Performance of a Bloom Filter is **O(k)** where **k** is the number of hashing functions. + +## The code -The code is extremely straightforward, as you can imagine. The internal bit array is set to a fixed length on initialization, which cannot be mutated once it is initialized. Several hash functions should be specified at initialization, which will depend on the types you're using. You can see some examples in the tests - the djb2 and sdbm hash functions for strings. +The code is quite straightforward. The internal bit array is set to a fixed length on initialization, which cannot be mutated once it is initialized. ```swift public init(size: Int = 1024, hashFunctions: [T -> Int]) { - self.arr = Array(count: size, repeatedValue: false) - self.hashFunctions = hashFunctions + self.array = .init(count: size, repeatedValue: false) + self.hashFunctions = hashFunctions } ``` +Several hash functions should be specified at initialization. Which hash functions you use will depend on the datatypes of the elements you'll be adding to the set. You can see some examples in the playground and the tests -- the `djb2` and `sdbm` hash functions for strings. + Insertion just flips the required bits to `true`: ```swift -public func insert(toInsert: T) { - let hashValues: [Int] = self.computeHashes(toInsert) +public func insert(element: T) { + for hashValue in computeHashes(element) { + array[hashValue] = true + } +} +``` - for hashValue in hashValues { - self.arr[hashValue] = true - } +This uses the `computeHashes()` function, which loops through the specified `hashFunctions` and returns an array of indices: + +```swift +private func computeHashes(value: T) -> [Int] { + return hashFunctions.map() { hashFunc in abs(hashFunc(value) % array.count) } } ``` @@ -41,18 +89,13 @@ And querying checks to make sure the bits at the hashed values are `true`: ```swift public func query(value: T) -> Bool { - let hashValues = self.computeHashes(value) - - let results = hashValues.map() { hashValue in - self.arr[hashValue] - } - - let exists = results.reduce(true, combine: { $0 && $1 }) - - return exists + let hashValues = computeHashes(value) + let results = hashValues.map() { hashValue in array[hashValue] } + let exists = results.reduce(true, combine: { $0 && $1 }) + return exists } ``` -If you're coming from another imperative language, you might notice the unusual syntax in the `exists` constant assignment. Swift makes use of functional paradigms when it makes code more consise and readable, and in this case, `reduce` is a much more consise way to check if all the required bits are `true` than a `for` loop. +If you're coming from another imperative language, you might notice the unusual syntax in the `exists` assignment. Swift makes use of functional paradigms when it makes code more consise and readable, and in this case, `reduce` is a much more consise way to check if all the required bits are `true` than a `for` loop. -*Written for Swift Algorithm Club by Jamil Dhanani* +*Written for Swift Algorithm Club by Jamil Dhanani. Edited by Matthijs Hollemans.* diff --git a/Bloom Filter/BloomFilterTests/BloomFilterTests.swift b/Bloom Filter/Tests/BloomFilterTests.swift similarity index 98% rename from Bloom Filter/BloomFilterTests/BloomFilterTests.swift rename to Bloom Filter/Tests/BloomFilterTests.swift index bb11f80aa..1248e0150 100644 --- a/Bloom Filter/BloomFilterTests/BloomFilterTests.swift +++ b/Bloom Filter/Tests/BloomFilterTests.swift @@ -1,10 +1,8 @@ import XCTest -import BloomFilter /* Two hash functions, adapted from http://www.cse.yorku.ca/~oz/hash.html */ - func djb2(x: String) -> Int { var hash = 5381 diff --git a/Bloom Filter/Tests/Info.plist b/Bloom Filter/Tests/Info.plist new file mode 100644 index 000000000..ba72822e8 --- /dev/null +++ b/Bloom Filter/Tests/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/Bloom Filter/Tests/Tests.xcodeproj/project.pbxproj b/Bloom Filter/Tests/Tests.xcodeproj/project.pbxproj new file mode 100644 index 000000000..d413110c9 --- /dev/null +++ b/Bloom Filter/Tests/Tests.xcodeproj/project.pbxproj @@ -0,0 +1,261 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 7B80C3D01C77A263003CECC7 /* BloomFilter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C3CF1C77A263003CECC7 /* BloomFilter.swift */; }; + 7B95D1E41C861DAA00760793 /* BloomFilterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B95D1E31C861DAA00760793 /* BloomFilterTests.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 7B2BBC801C779D720067B71D /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 7B2BBC941C779E7B0067B71D /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; + 7B80C3CF1C77A263003CECC7 /* BloomFilter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BloomFilter.swift; path = ../BloomFilter.swift; sourceTree = SOURCE_ROOT; }; + 7B95D1E31C861DAA00760793 /* BloomFilterTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BloomFilterTests.swift; sourceTree = SOURCE_ROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 7B2BBC7D1C779D720067B71D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 7B2BBC681C779D710067B71D = { + isa = PBXGroup; + children = ( + 7B2BBC831C779D720067B71D /* Tests */, + 7B2BBC721C779D710067B71D /* Products */, + ); + sourceTree = ""; + }; + 7B2BBC721C779D710067B71D /* Products */ = { + isa = PBXGroup; + children = ( + 7B2BBC801C779D720067B71D /* Tests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 7B2BBC831C779D720067B71D /* Tests */ = { + isa = PBXGroup; + children = ( + 7B80C3CF1C77A263003CECC7 /* BloomFilter.swift */, + 7B95D1E31C861DAA00760793 /* BloomFilterTests.swift */, + 7B2BBC941C779E7B0067B71D /* Info.plist */, + ); + name = Tests; + path = TestsTests; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 7B2BBC7F1C779D720067B71D /* Tests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */; + buildPhases = ( + 7B2BBC7C1C779D720067B71D /* Sources */, + 7B2BBC7D1C779D720067B71D /* Frameworks */, + 7B2BBC7E1C779D720067B71D /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Tests; + productName = TestsTests; + productReference = 7B2BBC801C779D720067B71D /* Tests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 7B2BBC691C779D710067B71D /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0720; + LastUpgradeCheck = 0720; + ORGANIZATIONNAME = "Swift Algorithm Club"; + TargetAttributes = { + 7B2BBC7F1C779D720067B71D = { + CreatedOnToolsVersion = 7.2; + }; + }; + }; + buildConfigurationList = 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 7B2BBC681C779D710067B71D; + productRefGroup = 7B2BBC721C779D710067B71D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 7B2BBC7F1C779D720067B71D /* Tests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 7B2BBC7E1C779D720067B71D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 7B2BBC7C1C779D720067B71D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 7B80C3D01C77A263003CECC7 /* BloomFilter.swift in Sources */, + 7B95D1E41C861DAA00760793 /* BloomFilterTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 7B2BBC871C779D720067B71D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 7B2BBC881C779D720067B71D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + }; + name = Release; + }; + 7B2BBC8D1C779D720067B71D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 7B2BBC8E1C779D720067B71D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7B2BBC871C779D720067B71D /* Debug */, + 7B2BBC881C779D720067B71D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7B2BBC8D1C779D720067B71D /* Debug */, + 7B2BBC8E1C779D720067B71D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 7B2BBC691C779D710067B71D /* Project object */; +} From c2fe941be578faaefdb3e83de2b68ff51599a7ea Mon Sep 17 00:00:00 2001 From: Paulo Tanaka Date: Tue, 1 Mar 2016 15:16:56 -0800 Subject: [PATCH 0091/1679] Adding simple depth first search example --- .../Contents.swift | 38 +++ .../timeline.xctimeline | 6 + .../Resources/Animated_BFS.gif | Bin 0 -> 33276 bytes .../Resources/Minimum_Spanning_Tree.png | Bin 0 -> 23928 bytes .../Sources/Edge.swift | 11 + .../Sources/Graph.swift | 56 ++++ .../Sources/Node.swift | 32 ++ .../contents.xcplayground | 2 + Depth-First Search/DepthFirstSearch.swift | 15 + Depth-First Search/Edge.swift | 11 + Depth-First Search/Graph.swift | 56 ++++ Depth-First Search/Images/Animated_BFS.gif | Bin 0 -> 33276 bytes .../Images/MinimumSpanningTree.sketch | Bin 0 -> 81920 bytes .../Images/Minimum_Spanning_Tree.png | Bin 0 -> 23928 bytes Depth-First Search/Node.swift | 32 ++ Depth-First Search/README.markdown | 61 ++++ .../Tests/DepthFirstSearchTests.swift | 84 ++++++ Depth-First Search/Tests/Info.plist | 24 ++ .../Tests/Tests.xcodeproj/project.pbxproj | 276 ++++++++++++++++++ 19 files changed, 704 insertions(+) create mode 100644 Depth-First Search/DepthFirstSearch.playground/Pages/Simple Example.xcplaygroundpage/Contents.swift create mode 100644 Depth-First Search/DepthFirstSearch.playground/Pages/Simple Example.xcplaygroundpage/timeline.xctimeline create mode 100644 Depth-First Search/DepthFirstSearch.playground/Resources/Animated_BFS.gif create mode 100644 Depth-First Search/DepthFirstSearch.playground/Resources/Minimum_Spanning_Tree.png create mode 100644 Depth-First Search/DepthFirstSearch.playground/Sources/Edge.swift create mode 100644 Depth-First Search/DepthFirstSearch.playground/Sources/Graph.swift create mode 100644 Depth-First Search/DepthFirstSearch.playground/Sources/Node.swift create mode 100644 Depth-First Search/DepthFirstSearch.playground/contents.xcplayground create mode 100644 Depth-First Search/DepthFirstSearch.swift create mode 100644 Depth-First Search/Edge.swift create mode 100644 Depth-First Search/Graph.swift create mode 100644 Depth-First Search/Images/Animated_BFS.gif create mode 100644 Depth-First Search/Images/MinimumSpanningTree.sketch create mode 100644 Depth-First Search/Images/Minimum_Spanning_Tree.png create mode 100644 Depth-First Search/Node.swift create mode 100644 Depth-First Search/README.markdown create mode 100755 Depth-First Search/Tests/DepthFirstSearchTests.swift create mode 100644 Depth-First Search/Tests/Info.plist create mode 100644 Depth-First Search/Tests/Tests.xcodeproj/project.pbxproj diff --git a/Depth-First Search/DepthFirstSearch.playground/Pages/Simple Example.xcplaygroundpage/Contents.swift b/Depth-First Search/DepthFirstSearch.playground/Pages/Simple Example.xcplaygroundpage/Contents.swift new file mode 100644 index 000000000..e18e7cc58 --- /dev/null +++ b/Depth-First Search/DepthFirstSearch.playground/Pages/Simple Example.xcplaygroundpage/Contents.swift @@ -0,0 +1,38 @@ +func depthFirstSearch(graph: Graph, source: Node) -> [String] { + var nodesExplored: [String] = [source.label] + source.visited = true + + // Iterate through all neighbors, and for each one visit all of its neighbors + for edge in source.neighbors { + let neighbor: Node = edge.neighbor + + if (!neighbor.visited) { + nodesExplored += depthFirstSearch(graph, source: neighbor) + } + } + return nodesExplored +} + + +let graph = Graph() + +let nodeA = graph.addNode("a") +let nodeB = graph.addNode("b") +let nodeC = graph.addNode("c") +let nodeD = graph.addNode("d") +let nodeE = graph.addNode("e") +let nodeF = graph.addNode("f") +let nodeG = graph.addNode("g") +let nodeH = graph.addNode("h") + +graph.addEdge(nodeA, neighbor: nodeB) +graph.addEdge(nodeA, neighbor: nodeC) +graph.addEdge(nodeB, neighbor: nodeD) +graph.addEdge(nodeB, neighbor: nodeE) +graph.addEdge(nodeC, neighbor: nodeF) +graph.addEdge(nodeC, neighbor: nodeG) +graph.addEdge(nodeE, neighbor: nodeH) + + +let nodesExplored = depthFirstSearch(graph, source: nodeA) +print(nodesExplored) \ No newline at end of file diff --git a/Depth-First Search/DepthFirstSearch.playground/Pages/Simple Example.xcplaygroundpage/timeline.xctimeline b/Depth-First Search/DepthFirstSearch.playground/Pages/Simple Example.xcplaygroundpage/timeline.xctimeline new file mode 100644 index 000000000..bf468afec --- /dev/null +++ b/Depth-First Search/DepthFirstSearch.playground/Pages/Simple Example.xcplaygroundpage/timeline.xctimeline @@ -0,0 +1,6 @@ + + + + + diff --git a/Depth-First Search/DepthFirstSearch.playground/Resources/Animated_BFS.gif b/Depth-First Search/DepthFirstSearch.playground/Resources/Animated_BFS.gif new file mode 100644 index 0000000000000000000000000000000000000000..d8fe07cbc40a0a19534b597e123bf803de42f205 GIT binary patch literal 33276 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 VN-uB@0x#iI)bv$Ep$#Yh{{eHl({ca+ literal 0 HcmV?d00001 diff --git a/Depth-First Search/DepthFirstSearch.playground/Resources/Minimum_Spanning_Tree.png b/Depth-First Search/DepthFirstSearch.playground/Resources/Minimum_Spanning_Tree.png new file mode 100644 index 0000000000000000000000000000000000000000..bce73cc8eaf8a1dd24c8f96269bd2ac127414cf9 GIT binary patch literal 23928 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 T*AjtB9dc7$7xhlnD(rs%aZzvT literal 0 HcmV?d00001 diff --git a/Depth-First Search/DepthFirstSearch.playground/Sources/Edge.swift b/Depth-First Search/DepthFirstSearch.playground/Sources/Edge.swift new file mode 100644 index 000000000..3937a2cc7 --- /dev/null +++ b/Depth-First Search/DepthFirstSearch.playground/Sources/Edge.swift @@ -0,0 +1,11 @@ +public class Edge : Equatable { + public var neighbor: Node + + public init(neighbor: Node) { + self.neighbor = neighbor + } +} + +public func ==(lhs: Edge, rhs: Edge) -> Bool { + return lhs.neighbor == rhs.neighbor +} diff --git a/Depth-First Search/DepthFirstSearch.playground/Sources/Graph.swift b/Depth-First Search/DepthFirstSearch.playground/Sources/Graph.swift new file mode 100644 index 000000000..181af9e85 --- /dev/null +++ b/Depth-First Search/DepthFirstSearch.playground/Sources/Graph.swift @@ -0,0 +1,56 @@ +public class Graph : CustomStringConvertible, Equatable { + public private(set) var nodes: [Node] + + public init() { + self.nodes = [] + } + + public func addNode(label: String) -> Node { + let node = Node(label: label) + nodes.append(node) + return node + } + + public func addEdge(source: Node, neighbor: Node) { + let edge = Edge(neighbor: neighbor) + edge.neighbor = neighbor + source.neighbors.append(edge) + } + + public var description: String { + var description = "" + + for node in nodes { + if !node.neighbors.isEmpty { + description += "[node: \(node.label) edges: \(node.neighbors.map{ $0.neighbor.label})]" + } + } + return description + } + + public func findNodeWithLabel(label: String) -> Node { + return nodes.filter{ $0.label == label }.first! + } + + public func duplicate() -> Graph { + let duplicated = Graph() + + for node in nodes { + duplicated.addNode(node.label) + } + + for node in nodes { + for edge in node.neighbors { + let source = duplicated.findNodeWithLabel(node.label) + let neighbour = duplicated.findNodeWithLabel(edge.neighbor.label) + duplicated.addEdge(source, neighbor: neighbour) + } + } + + return duplicated + } +} + +public func ==(lhs: Graph, rhs: Graph) -> Bool { + return lhs.nodes == rhs.nodes +} diff --git a/Depth-First Search/DepthFirstSearch.playground/Sources/Node.swift b/Depth-First Search/DepthFirstSearch.playground/Sources/Node.swift new file mode 100644 index 000000000..9d8435ffa --- /dev/null +++ b/Depth-First Search/DepthFirstSearch.playground/Sources/Node.swift @@ -0,0 +1,32 @@ +public class Node : CustomStringConvertible, Equatable { + public var neighbors: [Edge] + + public private(set) var label: String + public var distance: Int? + public var visited: Bool + + public init(label: String) { + self.label = label + neighbors = [] + visited = false + } + + public var description: String { + if let distance = distance { + return "Node(label: \(label), distance: \(distance))" + } + return "Node(label: \(label), distance: infinity)" + } + + public var hasDistance: Bool { + return distance != nil + } + + public func remove(edge: Edge) { + neighbors.removeAtIndex(neighbors.indexOf{ $0 === edge }!) + } +} + +public func ==(lhs: Node, rhs: Node) -> Bool { + return lhs.label == rhs.label && lhs.neighbors == rhs.neighbors +} diff --git a/Depth-First Search/DepthFirstSearch.playground/contents.xcplayground b/Depth-First Search/DepthFirstSearch.playground/contents.xcplayground new file mode 100644 index 000000000..5ed29117b --- /dev/null +++ b/Depth-First Search/DepthFirstSearch.playground/contents.xcplayground @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/Depth-First Search/DepthFirstSearch.swift b/Depth-First Search/DepthFirstSearch.swift new file mode 100644 index 000000000..79e835f3e --- /dev/null +++ b/Depth-First Search/DepthFirstSearch.swift @@ -0,0 +1,15 @@ +func depthFirstSearch(graph: Graph, source: Node) -> [String] { + var nodesExplored: [String] = [source.label] + source.visited = true + + // Iterate through all neighbors, and for each one visit all of its neighbors + for edge in source.neighbors { + let neighbor: Node = edge.neighbor + + if (!neighbor.visited) { + nodesExplored += depthFirstSearch(graph, source: neighbor) + } + } + + return nodesExplored +} diff --git a/Depth-First Search/Edge.swift b/Depth-First Search/Edge.swift new file mode 100644 index 000000000..3937a2cc7 --- /dev/null +++ b/Depth-First Search/Edge.swift @@ -0,0 +1,11 @@ +public class Edge : Equatable { + public var neighbor: Node + + public init(neighbor: Node) { + self.neighbor = neighbor + } +} + +public func ==(lhs: Edge, rhs: Edge) -> Bool { + return lhs.neighbor == rhs.neighbor +} diff --git a/Depth-First Search/Graph.swift b/Depth-First Search/Graph.swift new file mode 100644 index 000000000..181af9e85 --- /dev/null +++ b/Depth-First Search/Graph.swift @@ -0,0 +1,56 @@ +public class Graph : CustomStringConvertible, Equatable { + public private(set) var nodes: [Node] + + public init() { + self.nodes = [] + } + + public func addNode(label: String) -> Node { + let node = Node(label: label) + nodes.append(node) + return node + } + + public func addEdge(source: Node, neighbor: Node) { + let edge = Edge(neighbor: neighbor) + edge.neighbor = neighbor + source.neighbors.append(edge) + } + + public var description: String { + var description = "" + + for node in nodes { + if !node.neighbors.isEmpty { + description += "[node: \(node.label) edges: \(node.neighbors.map{ $0.neighbor.label})]" + } + } + return description + } + + public func findNodeWithLabel(label: String) -> Node { + return nodes.filter{ $0.label == label }.first! + } + + public func duplicate() -> Graph { + let duplicated = Graph() + + for node in nodes { + duplicated.addNode(node.label) + } + + for node in nodes { + for edge in node.neighbors { + let source = duplicated.findNodeWithLabel(node.label) + let neighbour = duplicated.findNodeWithLabel(edge.neighbor.label) + duplicated.addEdge(source, neighbor: neighbour) + } + } + + return duplicated + } +} + +public func ==(lhs: Graph, rhs: Graph) -> Bool { + return lhs.nodes == rhs.nodes +} diff --git a/Depth-First Search/Images/Animated_BFS.gif b/Depth-First Search/Images/Animated_BFS.gif new file mode 100644 index 0000000000000000000000000000000000000000..d8fe07cbc40a0a19534b597e123bf803de42f205 GIT binary patch literal 33276 zcmbr_cTiJp!|(g7wX#wngb*O~gc@21)lf}nBBDk_iXa9=MMaDX2#A`5-UCt`fPnq}AVgY5Lnhg!A_ zCwc6bx1|IhTYh5nXxg>6nHLq(^pF)zTE`qC;jd9sv~U- z^p192sMXRuAI{L!x;T_)rZccr$87laCVPTatQDc<&ZCt^COi|v@n_Kv1WTTk`i;rA zTzj&^LWU{Te6a)h&AXoqED0a#>ckQnhi&;n{yBOyApmJ*%Sxd0`NMc@GG%?pgm3=^ zQyMOTBI_?K#+uAopF=%RScEfTNcg6p=<43UU|w6>^MKjB?W}BEA+di!LB4NpXS#%2 zT!^;Vjf0zH%WJf7?4atR`0V_ukeGBib8GvE4$Y}fF*cc7s7C9me_Uh=p)_np^)s6K z2XfU`PvI76P5?-C%P@L)M|=lXjbxk?MC*3a)Yb?}Y~%KUIcOcbFu8&zin&(9$!bs4 zNAX75RzwyYG51H09*%HW*QfS1Mprx0;l1SE*ZW$O#$MM8u6}k_4$R2aWm-K?%q^U_ z8b{oMKfQdUXSzS$ci^+~S;NwATtn}<=~J~*sr;e$9HQ}2;+ek|o#tC#dq0P;Gcw3Z z;YLs7?kA63+QzefygE*ieX(S!DvkX8KxUWLGEq6bPTpMZkr~mCGKiF-VWK~q z17{`7uh(^uC}qgZH<|!4V!5mjwISfJKi(vP$U&PY4&23=B@%_G&FeV%jRqykm2A5b zIR~kirQE-lk;Usn3uy@=w2+m!#K^eo&K!l?d3Oh7ELt9%c5`hDeye z$tc-?Z7#!wxIxE^&3lQTC9?14dhBoy1H^O27=ut-4ivzg2KfmNqE?Xge>NboLtB;{$hU4Ty|iQz z@p%B2V4h@%)5L6qaTJa@rzP?z^II{+t{ukV#=rQZasEk{aO&m}s~S;D-}_?DIbmw= z1WoE~n=LKmE7G;B)9-a;86{D_YiXu(KNmZQ5q+?E*N-Xquh6F5C{z04ewZjmcgb*g?o6O=&ViXAUiO}QE@W$!HY8+L->qBnm%T5O6 z35fzlTJ>ua)bURU^c!KwKOg<^ZoIkLPaRVI(uJrv_FPJ$GIQAsRgFz0XzB=Ia>*UI zUM?Kd?oSS8$H69_Lvg0>D zCFLYyOr7FHfeD1!7FGb`vapaVrhW0^`{~$J5P4Zww9c5-ICaX4`O*VgvxD76=7GW@ zhol4gCt0=j;Z3=9;%8dZ1qPnMKzZWGDzY>($SD>OdxRyBG1ip1J|9Z91g+AhM9tTb zY2pg1vZ)8z!!0B7()__mT?==3(Vjbb(Sk{uOGa+!kwI~-nz`*^#not!JDc{KL-rlK zYdah6;5%IgnH};4t7bd#O)&>chWf?&sE_3j$OBF%xz{%;oNC6@2IxIKfguG<*lvcp z_(BG(nI_LkAkwhj-5iF??neCt4sPTnOm53tusu;wgTU1K^zr6KD@-t-5Nsg!CHRk@ zLOWc-MtO)6h;W~>jXkfc1s0GC*icZQaGvXdC{wur>Y6dub_0H&PTSFb++Sq0q@$0B@mrjG!^ z&=}NfnXqYj4onlX;XSBa-5k@S$Ks7X9tzHx3b=L1fD5n4=ZkPbREBH|2TP`5=#$5x zb4z{O0t0d%&JV-(+%=i!&AqvpkI+3fq8+^;VC*lBsr`)&xoZwGMQRd~$5Fh!R+6^p zJPt^GfUj;n&a)-9n41vW4r>Jq1biHAYxxde97(#s&_+-$TP1jzC_>yjO&T&D8+pwmw%qjAuN>EV^06>t_6Xwp3d| z(>?T}JF&Cmd_VzV%NcZDuOr8Kabh2q^-GdTue%t?q0X7&}-O2W~*$AD+rzSmq(ASk=JX44iyxvfGV=IWxz z=}a6$o-?aX5x`o?t%r}6Aa%scv09k22O*u$%)_o@X?z#5=wyz?91arVvp1Jhcbm5H zfWFm2q$Pq~nyR4CR|)p!3q-JV;VRQ~gq9)kCc&I~H7j70WGQ`3OOgOoBH7<10tuO! z&kr7u?a5a%rs>CHLu9q*s=o+#z-Kqj;|ZZax#(wZ6f{q9LO1?lj?Slcyg7y9dndIN zHC+QfM%_eCPp!JM(FLi?Kc?CBd=;fi0@fxEA!T@Iqhrr9ZRtljT`+FWnF5bweLU&n zlS8JP8p7g=6B!WSx7(M(MLO{|KAE z$m<4ez`N_c;0<>+roHokwNqqiVUcfc+Gp9=OfFi|i|pHQi0GB%ci?rDgD*bbson}x zqqTKyZc>+~K=f4l9=Uf4YU_;<>{|AFfzhPbb#fo{EG*-}dib&IQR{!|!`z zD)B)dce0NDLM~cf`Mg!qVti17e4Vd9JZWk0bR}|{0Hq7?6$0GQtOjaSFfJ1ig9s#+ zP?NG%hpw(&C%ml`7|!60XM|l+q3JZ97Ab0Fi|BN`O}EHgBxKZy7VBo`$we;dSgZ7G zS5~$M1?@hXy@i*}rsR0Ba=wItV|{u$a)hK$@7#oWU=XU3X(>HGvE}EMbbzN#0lU7G zC2by7JY5qhSTg~x*#_t&8t$#wCMjU}-Ou#hR{9~%ZEzbB zdjJ^k&ND~gQvx)q3(BxH5vmiB4HeXt1Ak+RdQM_C@Qv&hi?yk^*NNr+3UGEeI$df( z7(<&1ig1OPwN$K`7+fnBYmZeJXTTiQq5Z!O@Bcoj=c+iuVzK7Vo%=^5ix)3eaU?1# zO2v^?t5*Ht$i|HuRUAo8O;vGZ*REYEj^yR#6&Dw)II?^9ZWTxB>gxU{9JzV(=KsQx z7cXA?UvlJsAdQ2eHvg7}#eqoE@~mcHc%GfM>3>PXfUHi|H=&6u#3uU1WP{}VJ$s|= z4K#HPE2y-VL)4ZE!)*rk4JV{r3vJzUaofS3LuU`0=#niu`Um{&DYa+151+esriWHU zIX*bjK*E+EzIpam>p0B>OS(6iXQnZB{c-Q(S0)-}&p&Lk$LrsGb@g@kc#A&%?hEXv zexdK-tbYimVe^Covi#^+yCJ5{Q^tJ!{?(C6@W4D0uVe2+`P8wxN(&qK z;;IAz0`;w=2LABf;n^Y-%P&P{#*6bo*<{)*o9GwjXIuM)5tURnI_DoB7O$skLj_vL z#&lA~^UdBqBYD@Ul(k2jT2Qm(`P$8AcM^koALAk4+)ZWK26>qL6Id z>qdmlcvD;wf)FNuqIS zpZu|e+1Tl2C`*4%Q?Bus76sWdQ4&{Ze;#3~y|rUH6i+@%f$=&Lt7i6(WpRo!;^%qP zA|r6P866pxIO#=Clr)nK8P>OoBTMM3U9HyNR#cDp59LgiQvo4B{=*iT971=JAB+PM^*FT_)4>r?9j7BY`l! zs>&u8r=N~Erq#ZVePAymo#&uq!RkLoa^RXaX-}sq|E?r^F_Xx)OetMUk159L(3U9H zV3W3V^ds-vRP-aY)^eW7LeI)&=a-it`uhBP5#_p8F1&YT#?mwXc+>0cgD6ubtslk9 z;!jmtHfJI6a0~X5yB+@h2VE;Bb8DepWY$JNFI~aVVsM$Kh#PjUK;q1+&P}}5)$)GMK=Po0J-9yx(utnH*jf%9{VRf|&Nc8iuoBkLg6X+8zXcNr4 zwWyBzv3ka}!d+9Jc^rw=7YHqD7rs0W|Gmgx;-YJrq-}}Q6vx6d69ye3q|wR_Uu5)3 zz0Kd2v`A#~g((u%Yvt!BX02%=v0U3BU2V8Q)(z?u!oFoZ}`Z7=jr<7a~2`_F~y zid$B<07FSE8^px$kR9h5Iv7lubrk~AC+29yutoUET%jk98o*K@)UwzxW2lL+wN6yY zmOxLh`X2I7=pK8^&$pRDpbYui>MiAq9Fzj|p(ZdaHRj=qZf74OU&g7uS zDMN4de3676J(C+%4uNi4v}gq_=9({?+?sAmI+kCh0F-hy62Ul_A7Q zOMh%`=+&SKX~{t|JZAyDtsqdWI&+PnAyYx>j)PF=l&*gHvx-Mc$2!K}%*=w|r1sPRlMt>}OT*BhS`h&~sr*VG&}4e(`_&Rs`?+ak5$PP$E%KvBFJ^Q_&N8@PC% zV@kBt0v}uv+0u#I+%E_ zRm29h6^4fb`NBtcHsmy%>c{@A>8m^QIXl?CA8SJuKAb+*W}!d?^HsT-|bE%WmkdJ4a zmJ)}qy-H5#v0ufhB3OYS;gi}gD@#eS$pE1t|{X2yF!;{{v+G|24)oinL zN!k^hzF)^s_pN0*74X(s(m!}#^dccP!+c0~tz3LUUEGVc{*Hj4%PZ{~6z9fsg&1nQ{{h&1$Tv}&j8(`~Iu{w4}a|IFO8+Pr7nMvo1ZnBulFT?M3FC|;Bz7iPDt|$hOqhF z1$*QLWr>&~N?~O|epL`=cY5I#MByF`x?!}?Xc=f23UtX4JOK0aQnZAHq7y*^6Zmof zw2^{c^kSP?xx=weRC}AHl^AgA0w1i7)s+Ab&J_OyKfhp9($xwPlzo1m|)VmYo)) zjQ&u7wBvguH@lX8UFAnFpz}85FGZ}%Eqg!$KAkQ$m+Qnp9!7jb={>}y?qWOXddxh8 zW>5vHHm7V9)X7+hk^_4ywyEB?eiR_T^6hOE#uu&tZYL}Irx3c<_~(JU1BlxoYot9F zxLaH1AdBDq6`_B4_a!3k(pTh@YJl2P^q2!Cy@+{VQ1$f`Kw*ROTGZRGRnMkZuylzS zYo;p$5#FWD3U`MYs>ewJKv!84Hy_W>0CcFJ_u<_(0x(k#G~=V_h#l+n>O}MZdjP4D z1saXULe0LS6A1-z`)SZkVd0fT3T9LTie^)J3BkOy1Kf%yL)?kb2yy9z`z9y z7O1Ec8X6iF7N&|fv9Yl#Ev;R_1v6D=Vw0sHmx_ zsjshZY-~Jm;6O`Diz?n6J9g~k$&+W!oayfFzHs4!OeRyso8jT%>({TVv~>Ue{YQ@; zsp8Gkr%xv*CskT{^X83Gsr+}mLCwnc|9_{Jd(XFc)W0dQJolHfeK87jCCvB&n^eys zeKw1-bLM(jQD8)INogrevGT~Rs*drtR0ql$_5tda-ZjlFTxUIS-;qW==YuDt{&o2F zQ~U5u9cP=Vdrx011*qo+bDS}<;S$X8OE(j|HLu=9XnNfm<=I{skpZ@2PosTEkMC*; zCtfY{(HMpZ8ftenUcUayor4|58tPizC5_7F$%o4_WSEd{Y5ekRBiPJlUF{oA5#A0% zZ@21rrb!saCDjRlC?|sPQc_c#%uov52s`pd@u3!7&&ud-Kl}=q^>1)mNmmTd@54*j zo0BMPvP_`P5}Urg9iO-mX86yq&h*Ox4_!slF`HMlN6}a@Tq0Ajw;2Ip!uXn>kFM}D zNi2{{v)>{u-9UuCe$zYyy9!t;?0}&zj+v&mHCZv z#=f1sv23|a%1Cy4X??aQfBS7;0{{KZFX2SfBD>3+P!;yCDiBQ>7Ai& zZ%zlK|ElQkPm7shg4m>Q8te)*h*E-Ll{3D%kAK6%Js{q>6Pd z(Ro+b;?3(6E3>_&R8iyc7iU|WnG&Wbeo42Ce&Vc1f1O%Ytj$x5ZeqlnliN>ofuaxz zS9oO5*Wd_Vw?s}=H|mxgJ8hT3)zzA1rSKKqw@%B2S>HcPIJoxC_I9ihb-h2@aumN2 zr#G_haoer%o_F1}L7Bf=-Wt#216hZbuhh^}9NB;;h`E2Cv`CR5(f@q^u?ba&x{{41 z&U+<-j0+_F&DMXv>_>mcJsm(#%x(v9jwfIBZM%O@!fEeGeknug`SbZ5j0FBWO^-zJ z)(-PTz6fPo(hl@aJeG29In9+FhAflb9KjoeROS#2LXK^KjR$3hqvw*D?WtZV>@#?c z5{WMy<@ZR0cKxNuM&H!g3m`2eiqpp(e*SFirPuvqjj?Z*Y*aHJ?;1p#v#)_D-75Ci zMpbm%!gnZ;*xzPO;Y71Z3*?CYlVy!JTQNpOQv;~dSI0MEO<2I$=cXSEU%VO`lX4Wp zyN-b9_0CNYTBo?d9?x}62Lp#r8VvkZ=Y1Q5ZE{YWtNj(kx`Ltk;osxU#cWTqiD(UGL-Jg$#e^`b=-@^IiWLvY8>Ntr%lz~M>q9?#O=j!y1uG|TCi`Q!qJYOIyv;EH z)~Vo}mg-dMjN$FbLO|Y!dGpO8h4>h`NbeyRHdDwx`q0t({BnqKvPpeIH>jCHg&Y?2 z-KCF;bSReSXi^{gP@T|ap<@cOj;foYup))Lhk|}gV19-jF;TK%-+r-%M=H{!`#sv0 zb=6?@sWOlv7${xx5YYGb*Vd~-adHbd-zxc+T`sr7JAbaSU<~B=>LivHhM8N$Bgz8b zZH_O<>c^4YhB*vQd0q;^yooOf=6=AIO)fHNmK+Jlti(#XZtAT-GJ+BNHR;sYyjdtFvr zoaqs9O;^`MvMgy`QSkcY)zvS%R=e!BhPQ$6z9`uXkC%Ga7fcN9iNvh6I>ovPJ=Wjc7w!r~?#JdHqK?kz7EeIU*y>hl%NU%0WMD5(zSiZ+>@b|X z20EaZYC(zdz<8lRw5N2PCi{pgZBdD&OV12)zKc9>ZpM#yS!*0H9bt@99W5xrFn2+# zW`STWb7p?dX+gIAx5Y<{W(3Ouh+g)|!eR$@b(pstAO+n+M%%2?`4p*ZjJX;S3Iph) z9v~@cxM9h(P%TUjTzM-9CaykE|Sv_1OJE{VW& z3_tstsT+D(Xaw#g|FWKl$8=@d7pEyiWIh{q;>D68BSqRN;q^=+fPH6~>t4r(o#k(d z=>j{gpZ9StOyGQ#Ewb;342kF!sRzkCg{LY|w$r+)`GQ$UyNf4WB<0{@6)P+!1+Xo% zUF+)hC+kkLVN|LwAzTLb1Paj(LBMA9Er0#g?+dY3G?6p8j{pY_iazs#99hS+zRq48 zDdynJ$C01cJjc1pmp&zb625n8Lg~ueNb;N~)(R>__6G3{hv3u4USJ)&5f6^bppN?? z4sZAMtKpni5{J&<<}f?8Qiv_~Zar9UA}1u$cD4B%0W^EB9~XppPM}lpOiG|u@>H(= zWINWJE7aX013m?(TtK;rG>iw34ni8dG_XH+Nk+Dg0jFtRcOTZv7B0iZp$&#QNr7B1 zRr$H5^;A}SlDNiF+=F$e3fDDop;^MT+YR1OA4-r1Y1!$aY3$)j+P)kk|Fy$z%8$YT zX1r#}Hds>%G-;c^HW4d^0*Ct4c#>)JDw()pAO({k1D4H+LtBK4)O{5>dXvnD+*yS5 zz0(u27w=9GwV0Ht6vpC(JIxbiWwmS&J0Ob=ksdp-PyHGJ*@G%wBf_|My(W5;(OXB#l3Sz zed#NyfYy(*4=yJAs+mg|^g3Q)QuK^Q8m}cl^I`acX#i~)gPhu-;4Uf~V3 zFCWpz6wf-#*^s|sCwUKXOES{SQy7pl+lM72=jiXe|NLci-JZRQrF6M+a87tX!9)DW zGTalM$2)nynN7LLM@YlPz|%UubL)m$$l@30-j&B3ZRr{8gCE<}LWo~1$9c%@w^mN< zmq40>J(v|^=bYxV)7lCVN=uUy8dqzOTbd2=EEzkaQQ3TBU<)*|9K_u@1V6|>59_ga zl@ZXCVB4Uq4e^RCrqhTE z2hjgyZY<~PwozX#ka2J^ykzsyWwOKf$aGpYj=zv5%W?EIq|_WmC;C7 zI#mWb@hD%27*9zYRpS2qL8d(tG`Jt{#f0pXK$)57SZiFuDO8Xga%MVP$-y61YqJl6 zOP0;Ge->WS3C?_mCDouU7fgO0VEQRMW;!dJ2iXu~Lzh`g%$A)$2+l^pf1Lr>yMi=j zo*5Uk5k%{?AsL{li(o0^PWGcure4fl)Gd*lHo~TwqNcX^qjl>0XNpFtMV&Kh9kY?em)OPKL23uPi%%95 zUFgQQQ%Y`1iU((KXVOa!@=C6LO8O6hS{X$`gXeh_AFO{r8~JWj`WaiL>P zbB&rURG0#J6?hp%SU(9&E^3obSjKyrRQ^Z`AS!kh{_{xT}1tEB$PE zj4L0UoF@))+qEllg`GTCZFrl$q>GyDZvrc?s?+PHY1Rh9Axq0y@;U3SV`OEG%c~8<+oHSch?V0 zCD#oISPfuCy*+v;)O@556A+~Un6@o75j_+`rofYLuiKHKAk_paoy2I<16RP?tu^^; z7_n@~m{%~)$_V(j%YvD2mEnBi$|_@V^%iTS&7GBzOt!V47U>RINtZ8`LypSI+#clG zPjxSAq1{)&6725hr>q_M(09=6({78Uk@en6(1H(I^1!2G5y!^%SaCrCx4tj~nxhmt z2_P09YF)Qirq{5Di2QH*l8RR_3}dla6|aayqKa2~dV0pj#wuP}Sy}zzm7}AhDnqGw z<>TYy>+7rHm1-Lo5)!gx$&x?3`ctCTuV24u)26LkxBe+nDqD#}B9*OF!?==?60unP zXBhX#RtFCrJaXiSY8cni(V-f~scd!e;>EtczAIO*{M%L|BO`x?aT600e{A*k?c0wZ zKYsoCb!KMf&oEBam;O(@dYarFsdnY&?_&cxq)FC)BE?5&BxtR1+3Dt z@^V<$GC9AdHrmTV9S}F}2h=UR>QqZMXUe|)M;k$1r{7C9PYe99p8fddt_ufE+RqM@ z0Vb*?n-ga6Mj6I&_|7Iz&6^Jpnk{$7SK9QC4gfZfpGSLZJ$*pRe(`RZx5f=nMXU!J zZ~y+mb;I7kvLczA?S<+)G5e+yofwkZ4io6aqMFHw0 z26MxqxRwQ`&T4IDY1I4I_8P7sJma67nk_5wnCm@y`(!H~=6GB1mvl|5t3#C_Me;Q8 z?jf&8>b=8~OQ+ixZpz_O6?+gcjUZa_8k$#(12KZ_WS(F^hc)_2yK-QlgsA7DnyYd6 zc|?0(;^T7<0*XyNbu`?YYTiFIGN&^#I{KZWuPjUv&%EkcTdujM{wQzx*+g}%?={z1 zx6jgX`rMF_wtqgPlJ&bX%Dsf1MafTfb}VQTn!0`1Mqk5S*Z2L~IV01CxtjK4nLWDY z?MJ^P6SlsxmJQc#?E|lE{(L7%GQG&c`)9)7sosl=7i8%C_<5u9FP$H7WRbdMN?(Jp z^{CQUxApcF9_@5PE1aqoJK?)Fc6OQxuG72fDABbG(~Z~ldLx50T*svo1n*JexbEq; zw(KG|IdQDiDsagF)-p(jfYhlHnOH4SDnw`Oh=b7792tN%N)&L=M(jf0l!u>L{^3SP zT}nV|HzHo!tCuH28COa7tYQr6S>Y`NVh+|mC_P@oCWx!!28Hn^$ll$==U7IsB(cF^ zXt?cwgM>Avg)Qx_+YXLMDYnWhFpx`x^)V!K*F6yNEV$bCc4dB$~!vZ8DMYWML zt&_Gjv^2hY-Q0AX*PdybXk!aFyKVM`n`d7op6LC6YlKZhSlM-*ZvBE~3&&-`?3;N8 zjC6w_T?Jv5l<;~O9w6L?&=z9cvEB(^11mK;k9RoLhH~vHLOm-*9bhs6zxqOt1%G!R zw6U?-<<;V;2H3KQH{lRITXY_~AGfaAaIV4O3t!*z%UQOO#6IA)-R*4ji1%wdoJF1D z{f(A1UQ?FUwpRsvtjFYRG@S0H-%e9%p=JsQgwizWWOrkVs8Sr&&fn?YbB5r=HYfBGx`zUF1RdD;oMz+aK|wP!nibo;{HcC-gZ}m+Rc!L|H*S($nTjD*3Sttp zP(6XSvPipYM-#{%V|$j0LMxW?4z7;*7QC=%i)VF$n*D}#1@nVBH59ZfDq6 zYbDP64v!ylJomC}o5;Cp1+&%t4ffXREu8)1iYf2+^u=q!Pa4csTdUg{g;_cKQIbzx zrIF08VqmMViB)?v=lwF zv_xx^i&AKv{0>H4Z#@t~1T{+}kO5H`I%f)OSs^UXM`uUUVfXngx^a+IAE!2049X%Mlsh&D2?yCdqm#S_N*=5(=4T&vE8hA=M8>fd+BTDl(YP6&dKGEd#)cQ|=qJPoW<}xuY&o~w`x)MsFIq7_V#lq1?e-Q#_A-FEe50rK z_tr!KznI%Ih3`yR`1kZzo8ZR1v=FM(XW756*|Mfm}u(QU{^CllG>A%#~!0 z4ze}&cMFlKaH6C5o1DhK6gSL<$dml@vk@W!brkJ3B*J@q=2`2A4(tLymJA69iANh3q2^qFDhvUj<^WZ$}!ZQ*Zn5 z`!N0rgtkc>61lUlyZ%Z$ArgVg9(!EvdAVM#I~wC6W7lol^SpCo`4~m{g~*o)4KDJ) z@-Ka8!*|(nW(`QgbPnv3jMQxShB9J(!+R+O+6e;Cs#fdQa zE(FQQcPIPv-|oN#U`Io z5Qr?SZMWcRIX64PfrF%m`{L>-&~?=7-U=M<3|SKNiCM_*Phq^M0Wg3f-W{FSQHw8!z4@Zzc_rI!gf z@%%~jVVW1(fa0hbD-(`y&3a`}UWGQ)(CV_BbNy;GfNt53?4ZW`ec3zBj$#ga z7eusrD$-(}T^KOQ>&LvYPx&&u0oE4Vh48`e_Y;g{>k3kUxAW+xidjJB97Gd)&tJ>> zG~v^7hG$C!V*^v2+`=NsTfMpAuO1*>#h@K=s}BOQ5=4gcAsaC`Y=tEHgO(36aLshp zN^8asb`|)LU4(Zkg;vb;1p=rzb!Q+m)=HAGSPZF3j(@tQ4NG)N0v@vvHs;&dv%_e- zEUs8PDtud-)v`UyY{L=07BUbxgLIRFF6pc06Cn!;=&VefqXf;Rpkq4HT?(2D0Gc?j zmE_!gierVCyYN0}Apoe=+fCOf^9mv%VdVuN+7J#Pmf*v&(c^PS7f8`F(Y#J zt_d?I7N^d@PY$YB5O%)Wb3y9bf+5(GZ|2E_$f;)4iSVN~)8bQRPb1++>1M7HGY^^B zCK>d$4VuG*=G-aU-T~@PTl|nFejn2KIa>a=pd7JI^A}6}oGV5RtAq98*@E?IW9s;C z;&%cu=^LILRnbMPpd1zxdMb2OW48K=Z@phVXS& z;Z(DRYRGs5nq|pAOWBI$!}A%^9D4VXj)3UZQ84O0xGtmUY)$n>Y`Px1wv7*%Mb(x+ z0D>&H8%y(3zd6Mw!i9acsJn)Y-B9%qWGT%nc*!tgiro1?ZXq&{R39XPXv%6W8OZ1~ z+IP4PNL1a@@T3jviEHU=|;EU3_HYa|N+Wz0108EdqVc#h;DJ*D1dtmK+E!3)^iZPjalpI?$@%X_h5v~@O-;@JMBksL z=HTG)2YssT;eVn})znlMqEzUMjEq!eHI@6;tXZSF5T$b8=FOW`?%Te7`ycoHxe)bl z_wCuU=a2gi9XizB-u|EN`_t4^?i(5!`qR`@?i(8$Q#G~!o%{YLO^xqSZ+GSXzpgJ? zK|;en=+jSg^!bgxKUM8t=%ZNu3w^(<+P~0e>HQmhE_%Pw2k1HfM&BO%vF_jIJAaVc z-qT+OP%m7`bH)r@FT*$u-QMJ_dE>sye5&h9wtWx!0o(CORaR5nCuKi>tIBHERpvW$ zL*vc6@2aeJ9cygYFjHgOSGohU?@gktM3#fMJ?c2BLSLov`#f*%W+5!xu0o%Ar!Y#W zPGZ`vI{h1cE@~|X|3aV98r*CCNvqlN-{@1^K53=)8-3|Zy69#9LZ1|vclVI@a_YSv zNv;Zgn+v#9*?*z$hgtq_^byV7cnDb6U4^~_&meV8eYYeP`lKjLhQA7Zx_QN>UOM>q zLSOr5r@Vr>F<|qh)u$bdoriyZ-n!Vt+|4Xw`jEOA5vP?SnrAh zZM1-G{Nf7-M}jmzbe|&+wst4J9XBf1ys`fcoz~;wekFW4_v?jY`D<)t!&|pM{Z_R3 z^X=r8f1z*HncwKM{f)k1&`9?;`gSe1TdT0PlgZ)rpX?(GGLCF?+?P|^E9=*NG+Uk5 zWH=zCJ;~>NlKE+PkMf}+uNgkHk*8!971Aeo*@ae>lw5Us0~LVOTm%A8-9;vV4YR}# zbXn%>0I|BcKv1C;!uKukuGX_)!<#eh7;0Is8#J_;egKLzb2ntc0zU5!nuhcWf%l@mf`@zbx$Pv! z&7Rr^C%^H8cMVxjozM6iqz{Cj^kHu%c_JI`PL;jc1=5w9^VLHgf0MZ`m5m z7Q}!h;7?$`)KKfbv_+%J*a>k!Ch?se^Y|_o?eU!?E=Q46a~p^-!vN4s882POvljuO z&o5Q5q5ieZ6&9Xta(dqBZDs!1wK6Gf^!~{)(U(WI8w$TJ2;1eoYiv&6c?-v^6FJ}U zr~kh2EnjjA`Olm3UxPpL3xKXKx;`_bx3G4y{j^UHkh2+60!#|==i~z!c=P(MB?tv* z9ohG}9wqv7-DTCu2HTCe}lHU;~#jG6m*RUFnkz1m=cFA8s? zMP^Y3KE5R4eC=?WyXr2QncmKw6BVx+QQ$={^DkQJl7l!U_AlmD6dH{C>S}%nVCux@ z#djU>xmtHg)1xA9y&c+M_C`>FeOg?}c-<<4*E5%G6ps3t?nG{_#kR9F_8+j{*+;2mEf)wO_|u&LdHVGH3AP&Q;-2@G|3@7iK5<&C&VXD ziIUT_V8KiFoT=Tg$#piYrxakq6*tn(vSCx=b)3yMSpO&wG9(Id<71+Y$9YJjApvd; zx64Y&+iyQDiwl+B*qL^6za6Cy%@lxoLnYX&Y8;HJR#65e=~Q)VHJ^td$#Bh{Ma))= z?<^10EeUHe{ih8dL==^Qhs_ARUxFC|5O z>12BMVTK+c4eEGxlDF%_;c(Ig~x*4>St?l**ObXLYOo?+IN`^lev3;&?R8s z)f%a`;87=C9Ncx)4aJZlj)>XW>Vx-t4yzxI{uP;QffAADu>IDa{;JDNwh(pJQ$+NdbIP_GafvS%KIvq` zls4JCCc8V@IXtY_G{UjI0X&vA10DM;OZ{;TAzRZ8O{w?chGHVL>jX$o(Pym5%yeXmHJL~5*Wn-DdWG^S>_1}S;Ben)9kj$zjK&Uri8 zhhOgzPE&JPvQU0ObF5Z{XNJ z?9RO&Ao|VTL1V;e;&|p5Np%pV6>NKtT7fi5Y3ZGcV2RX`rC40O%SSe+C^$Na=Q zqZYkiZ=_|eE`7Tu&zt(r^pgx4U~G9Wu#K@yD0zRlbmf*Nfe06}^TKT-fV`YNe(G!8 zxnS0`M{(Bj*4>6L*YE!u?{BM5_o^AnyR~N9{zam02TG%j^c-=^)uo5ZBJMceXvdLO zKAijL(bR=fIu6vZJ$gFwm6`pzglpXUueUCnrsXDMgL&V~lsp&{&f)DS`#cty+7%&> za9zFj*}(;|r$SRc5SZMhboOi#vl=u*fU%q5s#B3Q_jZ{c1be%{JKK<+GSET{;RToPg>1yr6o>X^;83e%T|8qKV{KL{A{ z!0o7pa3FRzh`~oTB@}?JOY!cFUvJ%Mpz@_!+4N^ zC1@nbH4ra~z<@RgBRdN0E{!we=4IvQnK1K^_h2t6@?E2a3kyr^rI zUMx*7e#9$2JEYz_T6~9DEGtmE$SS!)ExA03AF3-k$t_VewVs)hPAPc7s`QYe1Ssw$hi z1e$GwT)4R=L?|x3JX~pNco5oD`@30g&Jm+NgLEF0!9x15A#hDODGKQ@0qU+pmOFVG z)pPXuVpcA2JF>Die|@B?wMh#xFCi25@<=hot_SHP21Dy0!!gK;m*PGjX%Vq2O9;3f zMmq4<_(eII^1{5CfV}|v(hV&hs|pZ6AsL&s5Zre!kQcoX;F1C{bL@9!bC7~MN~Dhr zphs0ch^x^e&fQQSdN;S)SFmxDHPTa&N#_B(gP`R6T7Su|&^D-eNc7OZZu)b2EF0>+ zQs<|7DnP7E3-R(8Ha$V`p?dMt>~S>AV&@tTS32{-Y!>WAgkGcfJb1CznYriJ z#2!2Tp7cU!XAN(T+{#-y|Hc`x3%j@R>%Z!oxS{o4*3}HqoVR3fKJ3ni<_I9OTxi6- z;daly@x%XThy5?{?cdwRKMwQo@K8C7&1U~QzWs67^5x6_I81dD>_7Y4|Jz}zZKJBc z{o7%x{`S9f*njr7|9gksbQ*JSHT$n^qq|zZUz2!_%PU8p&DlA*Du(I7h?3H>GS#?o zV_tPl^lyfh?`!-$ZmexNsA5<{WBWc8!wz+H`q$%+o@vA%IN94mJ<{E$S~s4*oa>C~ zzgCKIx*|{Z*1UdCwQjuqkY_8q-v`=0dZuF7U-w9&$u}y7T>}Y3wR;+`-+ogu>>Acc zXHnP!zTbY1m8ZU)8N08)XuVpRVMALB+AB^YEHaTJ81pWomM2Aq^Rkg@S8Fz6hAT1Z z&~%QG;9lpN{JK7mk@4YYrn8F{YjnOniuLQewFt{oGb&m&AZSLQl4Knz>&kTkH!~6) zkE~y2XiCPkS+Y3=qS(8$Lr+B_1o*@drZ5HnPjBZL)l}NB>s`_lLI^DsG4#+wkJN-N zMFS!tq6S1nM2(7oD7cf*L5&4OMU5R4HDW_WO#l@YH5L$iP*g-6BQ|u#%-QJ7oO#Rl zey6N+e)21e{bR3vJ@seH-9N~)c z7NuC&+PI2twzu3jUcE{1%h0kcUHaxt@`Cunrd9eAvt?O<23Q@IeU56uSHG$^kDTN0 zNY|NhE<8@i-mRDuFte(EQmTBxwl$XsFZg*IDq@SK&2nfpX8oQMrMdbk zEsu@wYuDEGGe?T_{^BqM&R{)en=t|^(ygjEeS)WzHW6ts$^MVrjSB~(W(a&ik*H&> z(Qkd|EXRvGfUz&Bx26XiQ}d#g^`FG$Ngp*K$yb>g9+_S|*g>M#%)SN~R!q4-HVl}( z3ZOS5)60Ad)S0oE5^j&dxC)it1gL<2uOv_|qb1($deupO$-NJdm*4ko-!7$UcIvbG zi0I2a^(0d#bu|fqB_5*C!2KR##e86xKexF?pvK@@edu8QvxACPjv_1SEn(Ja&&?BxE(op@he~HVIW}gg1eiKVemFZv=BvmqV&)rH!rgT;4w#cIQ9XR z`KloBVVetn0&w==P3%+6q5THd1MBybj*$eU=&?(IFjH-GB~b9qrJ)3pXi3%U21ChNq_uFCX{>rV%3(nu-c5nDq8z3P!M6vi5RGY6 zzJKj0e*%4uk#o;kzVH-j zi-&x76xq7dBK1FS+@}5duDG=83GnRh82HdTU>Ux@u@eK`Bu%=5H$GF}?k0|}{>s>8c($*U zy*hMNhItsEJ*&Q$rC79z<2B1Dzj2lS)A-ee53Su6Gu?t+m3VP7IFCle^9T^`sUXAb zW<`_*C3;<|LRsjl_9w9c$UyT5F90NmYO=^@%x>e8nm`>yP;1M2{C;;-G`*RQG3`<~ z1+$^&w&SbbKLaT<1melXGMK@Bkv2mS$?8tSkP03-#@Zu9Rswc-@e4|lR79;1U|k7w zIMZko3@d<{POS}wE4UIvbqvOlv5zxdB{r;)!6tkqWi<|MyWYl*VaJjN93~pos9^?I zM9IqQLL=A2ZkhtO`4t8wIgBM+L{6u{356ebu?K$wSK}YRrB#WgVuRgQqr@e@;q*}L zW|K8Ha^_I{>eFhB6^-Yx1A%GWk7i^67>ahwmK;*=y6~)NcxQC9VF`jgdS@&-L%(eLLm>hTo#Vke6cnwHl=WPIl$j&IKk`OEJJr`1ovEjU;Cz!^Z zH|@n(%eL$1Aj!w~_Z)WTiuhl@O5!d=gH_YpiOwo!2ld0A#8n~^i`Hc=N1*ASoHM4< zXsk{&N#W0*S^ZK>sV5O9zMhP&i!L$CQ8%@C=a4wk9xJpIn5DB|<`fy&YPSPFw&LJo zWlEb-7FX_%C{933vE4@jY~S}P_inZ}#(o8Yc{;{zV!RxDOycd?U-Twr3L<*8L!G;o zqj(`c0<>7A#SVRXP3CG&*{A?a%X}Wm&*{mUD!~u7GBp<@)B)9@gX6t9fH*t%q?IX` zS9;eJrWYVY3#KUhkqKnD+z4x`eoF|UJ^Uz6Jm}cCP;aql{6^4FbQkV;$;WE23xPIGn&~7yeS*9^prp` zpIqt!vmu>CHMGReHp@rDu^wa=?nluo%>0QCi$V+>RAf_@Ptaj;PeWxO-r%ZpS~3>{ zsE{oi-9_3xyF8;g=%_@l&?Acul zfYJch%_IU^TcvzmVS#v~Kqa2>r3X8fGk}ks->1hx?w1vzyV=XLr+qn&p~|@gLEIHx zg`uFGiQxTIAXWWE@8+Q>TmnrpZXW^}Gr?1Fh_~&C3|?_9k1%ZWz#s!TX(@BBb&}u3 zJ>QgCq~#H2!9rxZP^8E0 zKQ`-gVRNATj)hD;FZc*IQ+Ly%mN{m}>=~j5+cjc6TH%S}IOXM{86|XlTl641i zr#l2mv>Nr5SZ!dUt^b1Smke>X;ozxoUx+4rPAXjL)cpFOn7%@Q4GV6kCdp2fxeG8N z?lz6L^rj~Elh&DKS5UsW)Iy=gm}x*ex#=YD*ekaok3FDiZSiAUEzDAYz`iIfXL7JN zWWt4#ZSkH6WXIJFv$6?p2Z*(h-af3C6iPb2z(N&mAzz@`02NHe`pBRcoeM1FpovO6 z27nwj=Do()aa_rlJD>%U8`cMoMa140u)eooFDdLfESaK!{Q(mgYvQk-k)nbpcfr1V zIFVqoP+&E=0tJ}T$&JQLj2~0P%PFAE8z~cxELz+}U65Rk&UOo;sEb<5^Xl`88+D2p z6%W`IB@CUyf{IImimEJ1WnV>`rb5ah*KjH~M3vVu$m{AWcgrgqvWVM8D$DqlI|)@t za@F37s*R0RWq-m_M`TGyBy>X?52tihO%}pzHTaX3a+o!KLb0U=beAnXorQH>47tkS zAhedKg6xrqtMy~t5XgsF8lsrcUt4{bkp^E_6|Q1A%4+)S1Fy{%GlW&ISb1m4v7YE# zuV7V>2D~~4Tk(E%3=?)xV9;`+dISy>LPsyI3D+#VaMG9|UGuvkL})6uQZGSS2&E-; zE39v_7NsQ`QL4{|%r$9`u~5Rvnh$*#!^?pvDFq6rn2*Qw?pUX<4sv;g31mWWWmN#% z@Z0))2LVWlTIxO(;|Qb?n_y|YI7$JnpR&PUx)g<_k|`U)H7f@iG4=6+BnOl08*ArY z+?YOnF2=nbiX~#lp{Oih|B8cl6-yG(uA)FXtEtve0C@`QBBkh`kdva$yb{i@oZ%~V zoiPHPnp3y*-b6P(WG{fEmC2`!H`(zacc8wy$=_E9b7%=1`KH26n|6-d{NL9Vf3Cqy zO-<3dqLr1^eTH)6eAUXJZj1Ce)pQHWtz3>ZdycZ7iZ|FqD{3cLur!`zK;L zb?Vf=Z7lvpOfO%)eD&%Tx(54uWAT3>x$0j$ZWCqI?LU*NKkABqORi94`u~(%(I~xt zC0Apd8{~EBi{~U0^1K8Q0&%HfFXIh2DxMgSshgN8;K@wRjS`dK2Qgi(|AUxbm5r(R zK}_wV#AI!uosgtk@aEyy5aq;)#2NpNn06c-x@BfXC&*D^B1rxqCS-LpL}751;nd>= zr2`snXi1rlnIj))=7o{fcFNb0~O)OumD0cyDFQ40&Vo=kRK~fN1WE)T4M} zcWg4tHt^2H$`vu$GC`n0I7&>c+nKL^5Yzma%Q|i83mv=@6|TRyUU=)^lH{3xX;$a3 zy??CDwi&CB81_88S{f1fJilPUwj;FQv2P=)-cIg58f+JE_1o8DtLN-+Hw!-aE#=|M znGU`Us&Mqgx`0Gx=k|9HG!9u&y0+4NrQ}=Vvnn!YYTt0%vrI370^^&dgb3X=p9C;9 zP&U}1^SwwZ$#V%RljyL5GSdxwWI{29!d3wg33GWgx#HFu2dPy`ybS%dZO4Q3cl8StTU>^K*J;8bSHt=6{lz}&A5TnoiS=34{q7ZSE=5BIY+7NH9ST( zr+#SvhFpw#qn>n_)IBtI|5*#oJ$;wvJzE zcBA@4WzaG8UYZ}uNq=Nm47X8sQgMv@2{(A}^*JhJ*o1I+km?v^n*MH=y;5z<&Z)zE zdF(_e&c2?Kprr@wmIf8S-q$O$b+12+`8ITtrlmhyvR(W6Zs6~C4imwE&R;hxfb&g zJ2K*{&AguKoatNV7QJ>w`UXh1i$M1jFDjkZ`ZP%UaO9%t-kVi94c4SH>`<>f-s%CF zwLwAD1%E&HHKK>Rj0q0qc8fu27m~*K)_Q@8+GfVdr@S)wij7#O#7ht*2N&N;wW4nb z=mH&Lh*)!l3~S7Oj9~yEiSZ6*BO;&ZW2Nd-O!(q1V0go&07e#_tdxMnAVsWB27u`{ z5Pg1{6@q@&VC^)3=Qsq+w9pBSs)5Et2sZTUJ)7t(6p>b&l$vZn^k3w3zCMwQCRehV zR(uh8#Y=I~w+UG5K`t(l4JSFKt@`y1H;pf!xboY2EZPUf@oDg0TV<}{p#D@J+I4$X znx2{s;C&*orl{Y|CX45KSbHy^|5WZCS2jva+*YSPg`2~Ci%v}@HjB%+Wx6M*s`z+|;0$X3!F$7AAJ0OU3>KmTQTzF%rf~bnV-+S&3mO%p>Gc~7XxLhM< zz<2M_+rc~YdyY#C=YL3&fhVnY;4P95&H|_1zj-cU$y^Dy=LaS!plPpD^n=t>di}l} zzFy=&@{w!rjFkeI$KPG%ZuEahiCsWoRqV5;@Ta+(oFuq%vJdaPh%rTg)*2L(7zQ)8 zMXx9NjwsSaSJk)HAt_<}Ehr{I^Ahh``9ClPO7>!OM`};4K0AjHp-NS3s{xFq%+H9B8h7D7;xNZpeR z8)TRrhKH)Rww*EI)EeS6030TJmdQuva)8ZjBe_TqQM4QsDwbEvBs%8fT6dwCbn$e$ zTlT(j)M(A!oFiUg`spT|8X< zZ|TR^slk*52XUVZF%~(9!gj$7L9_<(KiYf5oN2YH987_7Ww$!i?|E@$)p7b$YF;0!rFMWqvALHUzSM=Uypree3T+gN*#|!e?%SN2d0_rlQNv;nGfgoxmlNscxf2 zeX%}0do7wfUA?9Q${1VTZrsa+jdUE(S(3%18W~2f=J?bpLXc11fw@LQ+Q#;??aZr9 zz$l+n`?5+HgyT=9K6<(HnjaLZmEp!ly*@aN59*soU|y9r6Zr==F6y`f%bFs3T-BK6 zm)h03$DRqFdC%i8g|_mfBWQYRlqw9Y5eT?n&VR*Fj+X zrXldoh2J)R&v|v@@GH=&cPFgBunc_h0u%pD+g z)d05(5OGU?C$wp{Sl1DIfRI5VxiXZ*w&?{f+Yb#qw+*30383qqkD486%H^A-Rjo&# z0){)qI;2nfP>G^{VwaK_9i%z>vIV<)WwJr8RIC@K*dGs>E+3x8}1U&npR@e zhOx_JaX0U{gbC0<_MbsJndvRN0B7bTQ-Kz8jOU|F}UP-vRSDVZ#_4w6murXy2SqtVl7%A_uxPQa%QmZB+BI%_49 zH-7gdy=`~O-fGH(QKLGHUzz23ES-Y-@-9?|kxX4aQht_JA?A>alPd}b^D6qv@0_fV zG*+x0saV^pQ^KjN<5$*Y5z6Z;TSkeAR6kO=h*q_81h+f6YL>97ku!c(Yt^hD&}7Gi zGU~wj+K6fv8ZpUA53#UlH*zHivE-wf+QkBilMrG`!7%{*rKftbGe> zB~!9rU09eo8#0rXJsLzuR?x?&H3&L(ldXxN!4AgrB2Pl(6Iqd8!1kBYFg0wB&NePV zbVS;9X&GCcX?ic)oWIsBFPAEv=txX;R)dMGDvl!H(DO-D8E7a4fvIb1lpw9I+EW_1 z?E1`qf^lHYh?hNA3Zhbq^?w=C(I~HO0id@ z*^kFKXwnqNp>s<_zV`yk*49PHVYpU0dwdpKSl2dKMVq>IS<_yx>ai3=4LHxdQBXg-Sa&mw(zaSvne69kPKr znuc?i8+w;*P5N)=Vn3UM|HNN^H3$DGvHFX@{L`Cbdi3c3raAbJHjaNvtj3M%IQ~ei{LsYehmPZ46D!7##45m! z+}t`ES)D~At5fZ0WOeQm8d-I8qmfnDO*FC^Z4U1Gm*$}O&*mWQZ_PoJzy42~g8(`g z`&)A`aI`u25}k|r|GVa3lVY?vxbSby!R1|8EI4+`kHm_6Am@Wt)&ECgB|{Ud3L~qE zp&m4`T5C~NF5{mmn7@W@u(3@Lzv*qYQC!}Jk^7@_u}z!g=v=IEmA+-Iii^(0s!aK# z&B5WN8%F11Z7$&_|7Z^WT5!gobziICXLHc7t|E2oL-M7`N%?M<;G>4>XJ;kn(gTW) znK`sh;=QvlA(^J!zq`FQ;Od+2XK5#YBvu{7>CU5xl|ogjYu$B{X?cA2i3_8N)jeZ> zt(2QmwupeL&F_f%uo;2qc`nsqSlywcEQ*h*c6cg)GXhp*S?T|czX(703%M)dTSF1vqq1l?U(9hmhvq3HHRmFi$3ojVJy4}P3?4P2=f9G>uPua6Yu4wG~Beq)V*?U<+`#}~jPcb#nV;6Rp(OqEedf>l zpl13X=tV%$i>=_E_*oxRPDJa27w53I4)`~!v&v4Bw}naS6pE?$?xXd=FHd}@RgT1D zoc~_@$QLZOb+0*G@+DL!fq;H*64URpWZJH9rF2J*3?`;$E)h*LM)4Eq)Og zE});RBqs`ESlu$rmPR`u5ifF1v&=hs#ux}m(|1NqBCbLno+5#a-?(o3lBy&GA)rAQ zFgH@Z9$R;@2FL+6PpFqzDbfIH&H|FR#++j%3UaKlg>9Jely#SGuJ$|ZZcpG51c1s? z4PY>5%OH++av5FbJO&@79Nw&u7;s$2NY^(Q6sX0t2G?b7!pD*RS8mGMWyMw;@E7Qt zxW?8NFz2%9zvMYmP?x@UE5h00E~@fT;_MhAa@GErUGz`Q=7DInP<>pl%b7*e?5FpA zc09?mTySEinL)bHwgvKT4C%2=8D|O`3%HZV*DGJn=<&8!Gjk4`ZV9=bxBu8Ul%6=s zh#REjqtv=aSCt~PR1OmgoB->rke)*qLHnGzMziUu0yrW+pf99$H*Y--#Sgr0g-o@Tcn`4$nmOU-)qQc*_NIK!$}BO{an4bm8k#&*wDNT0ny6y@{*q8 zn7saWR|2rWdf<2oE$hPxk;{J41g_X{(7167{{dyj6%t&4fL1J_CyVB4{xOz8Q6mJd zrgw7Uo8k$EWmo|)H4Sk_If*N|vU$3)N&uVk6~v&10BWKa&Spj_HVpB0T=J>zQ?^Mo zlbIIrTMW^UmEvll)|tl?q(!NfxFpZS>p?dln*uJm{pf!OJm_J~YQ~VC_{!(IieP7Uf}ihxf**5=D?u&NQga1xl~zG-T)Ow(X=CFD zDeX^6+(CVcud#Z+kdTf%cx|VPF=X(FWz92}d`cqNW-ah5UzBObI3V+$fd%Q~O6FKT zaGo9;q7$TkvAP8ETf>8tK0QYv=Fc3Fp#eOnJH0yB{*SC}@Ufa8Qmus>eAxiQ3 zVG97aJGYZ58x4rvcL-j9W_SAYWZ`xaxGNBvS^VwpH#@g&vBf<6$EXsEfzBjc!8HA# z+PkOScO;&O?wM{c6YqR{cOX1yUREIOki~A^~~vCPgM;Q`N_79}!Qt(zuv!xmc4LX4CPrZ>LV?iglX>k0Se&BpbgP zTn&?!qUMoLcT(838;BVsW%YyS;N#h8RF;~HkCk03c-)J%qk$1qHSbEU16Vt>ZC_zv zgZnrM`?YNA8pOs1V4Q2%6NOcXW~`vdWF!sj`$XR#Ee(?>7?ShPPk&0_Yn z#e@XwJtgxv7+*eWOU&F}n-=;U8o#G3zW{Uh^U~a;`CWJOBvBYY8A!>mIMEw#CkHD| zmIbLnJD^f9Wv0j$8aQ4to{P`CP|o!(i9ng^$wt1?Y+3#l|n6IS&Zn~XBfWAxibQ@wU@imMth<%6b*N+BcfeQ)7B4s60K z$mnBG+0!_4rYl*=WwsUby5KRItSy8@Dj%{0z~0iNkmt}?d5vEe+ALUnqM+s}3^FyK z9(&FcMvcAH`z!~8su`(~iCwM!vj&A13mC+y7=QU1$?TdZQ8Oc!qC8ygM}RGWn%s-! z*PlT}@oOX0@K_mmeD7K+F~wM#;)r&ypQmlknisVZVxC%MEre#xo_VTgs;jL0K=S&^ z@=@q%!_EEJIto22&`W!yKcI&XInXwQ8Nx17$irGO$4N6Uaa^_=7mD9hbY;Ni9v+%) z5050*MMz-|e7w{G#hjl~ZCrHJq^Q^tReo_?A#{wnMJg+6~pPv~e0E$g8o zLUc5hmzVdi=<`#S@mKWpPot@Si#|U`Q$NuMjh;{u;XlbT{_mrwAMEqrM^B6&qbZbq z{xoGUf0#0us42tqhbhAYHDv_;Wy)|GHDx%Vri>u^AEu0;QBwx(4^xIOYRd3S<}7ki zj+!#wv_{q_Fl47ge~hM3Q^x3M>Zd8AeaDZ{6noyqpQEWp>&#J8#+Xd%Ka8eE(dXZe zrkWH#Oc^Np{AtSg6)q=}pr95KTY!$HlI{(C-_h~MXo@>JnsWJbG!epmfWzg@%nQ#_0eUAsC{X?fw!zdp7yKl8E-`!@~0bro-ZpWch6onY>7bq}tWssF}d&hh3JXcVTY9+Mz z=4Y>HcZS3OJcr%^Z0WkE%659bKmn3ap9R-8YJlAoVa`_Y&UZ2u50-0blYT+b2Z`~d zrlRQ6M;}EW(XMLVt<}|Tqv!*n=%WbxnK}^}Tgb5bGm1XfM$zYY&QVa`><9YzqUdw> zl)CuST(h zPK`6v=yFQv)PwOTIJk{!>-@GGbdZiNr@G>@h`>9J1Y>dgnDTL=N+F89n`^~Wr;z$# zii1J`!C;~`YDhQi5_XC1?w}einmVDcZI@<;5~_MOQ;E^{QUe;g5P&IFbB=V7*+Pv! zmg>b_fpcr)U#6az_bQZplhu!=PPs{WpDhzj|i+`i)NwU7KSuvR`1HR0u&{pC^y_dHGW4+FQ3se=ISgXb;=P1cR zkrMKN%s{(QX~d?HU@y$~z1)x+2(8q>Mu0yFE6=vkO6_e*;K<~T;}2-t$jFn@PK^K%D}tZHi5G+`tq4CUtlT;$GuuZf$b7 zb&Y5C5m9#PECcPe{s=FloyZKGzyZfoJf@5q|? zs2yXU^<4CaUWRcsJ@Nh^Z*sph^fGr#_EC3|NLdE)< zA2M)_>n}&|FU7kfAfeb7Bt+>J7-xZ$J2+jFn((}lr?*KnWYE-*G@PxvWT;9HAY>59 za>kK)D4YzZS830%!$nHR#F!1D7sc3sL!-{_=K!SUO&E*aibX?AV4zW2Tj@^1oDG9Ed1&j< zCLMEoWb2j#Y~~o&9W_K+ic{}KR25|%piZ2a@MgRNma&2OTlRwon`yo?Zt9Rc2-6ZU zGDn+kWJ%i)x_ItAc*J2K=TP(({X*oZpa(KQ|Uh@x&oO$FlV77LU1di0^Az{}$yErT6{)m;=*wfZ%B% zs@N705%D(8GaQ-&swZ0w0K3tH3Y0~}qb%}taRf*gBu{V5Av({yfJsGw^XIN?Hpz+r zDCltoCdn8-_?*K2gGCw-db0SQ<{xtyWRyjiLs|+x?3Z-sF(`~Mds0VXM8@@GGV2*p zNyb?DW!mO&3b_IROjQd!&+Wl1_ud7wM98Acn-cCC&1dM2T=X{Bi<$2Ij7{b97Ea?K z`seC?5QraBkpA#QyVbl+ID!n(Ir{WuG{M!$LLtV&f*CPUuI}b4F|DiK5YK3)Cj3^Z zmyf{2r5Eva?1Pz11jFRacRh9-b6#f_WLI!#;o8sOu1bZ)o%vY!`mYi?N3xZ?S3|Gb zle)cSXGiy9XB$ZUVj{OX^2@hQAWQ`Weect^<%CcxVjXn7l_1993zXKuIK zZRLPxyfT3H%$shoUl|vbxNqsr#?n=C%&uQjaX?DH0Y}ygum%ka<=2JXm$A2!UQH{0 zL;}Oq_me6>T<_Z|e9neaXGUXN1e4&RkzuE2LFJg)DCe%#y*z zPvc;NdW8kgYTa6NBWNfyYY2kYNzwc1tS2+E4#-?Xv_D{w2t+4%+^RiS8Eq&7V19z) zj2HvzYh~Q?o4Vq4v!oIO?20GjhDD^dc8R%C6yejZcj+klsr+1q%YIUA8R|>g~!?yEbFGHU&FRe#a`oTq(NrJ+ju~wfBt%2Xn`n~Mt?QInQMo=e~DSnL4#8?r) z1?uAE?hn;iG03|%MJ6`nod0S+g5KRG?|zz(9x(t)!d?^j#h7=$K6$4lg=s*8`upFk zb49~v-xX=joUgmITuBT8B*%9>A^5VCg!{j1-%Zi|?d?m*N(jBoUm2}JpAq!^B%;M@ zk?vW!-I)mLHZbA)Q3^!BND+z=R^`PgM%W`F9W3tNHNjSz zQYgA_B}x_63h+T>=F6@O6eA z{}Wdb2!y``=l>L`xVpOj-N5&sx#DM~4UJS#uK0N!)L)SbDmeeE()O2x@8<}prKRQP z?X+m5g5FO1_ekYmC4B$;mA2>qC}a57O52|XzW*p=_D@<(1RN7qts?tWqkNS2n&Q8;2Jl-}~VU_b=vn$EOa9u`f=zrFiwnrw_l}5*U?} z*}n7DtDQa*2B#&!7hdml$mWhqd-nNiUwrnjd6gmg29G;jpp6OE7v2oKLub8D+r2;L z2Sfy{Y}ti*_WFgzw7EKu&0qCQD%tqX$do+%>DGeXBQwGSS7clml`+iwA!GPy;2Y(N zo2Y^B2UkeBVD2zj83`?%rAoz{(qcVoLTAi(NBbpGu zbv}xa?V3tj<8D|nh#^%*J0gSzaU{HP9jek>7poRdJa8k{n5kQTYlwhrqKia_)@13c zN!wdOCN_1_Xed`OV^FSmcsKMfuIN0h2(seUUw+R%Fv=C9kxFw1=J;u*0&u;~mfPj} z$nQs=GRx)e_tY_{LS+opA0r?|lqcaMZhLU&hS3p_BBlm5HaY^I=tM_AlhuRi(qqqF zcu+@2Kx}t<^MhEtgEK#=O-+6Iccie@o1{Qx46(6TciorbqX$g|sElFhgDzl0o$t}x zz?+8{eBu<=VE6$@j%#&0h_Cn@Mt*fG8fnDcavzm32+SRga|3Q;JaVR^ zNYT)I9sCflgh}&ngmHEq-Ms~ z&=C-O=MNc!?P!`(6j&$1=*Ob>i=K^9pv#TK<_lCeg#vtMz)^8ECTPuVRL0O)b|P|D z2`XbyPo?+F9Gg$RzwmdN?PE8+pw9z;$QUrXy`J@F_1}$!LXQpIz47Gxi2ru&z}?{Y zJUjxvu>i@f78pBP@o)3mza4s}z*E^I{S8xp-7O6c-K{Ipo{7V5S1ChQ&`NL*uM)<$ zI)8ML`dj97lg6{Sp`A=ItFxOjw~_0VA$9Q|*g-z53EhW@uPAS|G^#3CkIEP%ZVixr zOU1$x(}3_YA>_O^%sDv z9@blrc_s^UQ@fi433%l5%r2*I?yL89Dcj2AJoW}DE$O0N;-j zQLWLC#Z(UnJgCMxCTAF|U`yyiaVm%?hEDL!?z-p$TWO_na_)KKR^r4jByNhIJy!L| z!5ma0M%$SZ3gM6mPOW$}BsnFF+PPwKD~LaLnKbUKVqus9B&eFGSh*}K8Zf`rz~eky zWrwYtbm^&(h&>n;I|c%Hw(9}E8ryJSxM45lh1RF`^xNA+@2)MoN9?d7qj`3^oI!eo z@V1Nv$YQz5!1e2VSn{|j3ngMon~x!wWl!|%YB+T4MaiM1uR$a4c4}v@V+)#sc)@kI zq-gZPaRICvH((ok*BzLxv%`ux7|Rp{7I$pJ>(U49HVT%rm@F2G?6NsdHR|ZS@`<6#|AEP z5*XY_2XN~ardp?cIOF0(dj=SGpD?`Q_;&789%x8I;1S!hc`uDyQggX5hOdxJjh|-A zsyEaXfT$?!uq}|E?o3lwPF)1tezxpH zcKa@c*#-jFj^rkf*z046HEEulKxCQgC-CmjV^fGeKq8+&6G!;>^QFBPcAl$I(v$C- zfGY03nOmT{r4oQa$TP4o6vZ2Ffc#3!w`M-7;&?tFc__H8)B6Df!sceDL3?-fCK_Ir z2=CID;CTzObE#>HC42yWX;DiUQts{UM*#WIHB9zS1?DqwONw*?l-*oxa&O4|6(4uk z!c7n>N*QnvfemCbXkr!p>VaHa*Fi3prBJLlP`fgD3Jj|r4DqkBGSvwz3BZz zV`T(tpknQ+_HDa-N09Jwjo@nL(7MRN)ngZ|{MG*{`sfW>ej)Dge|$=L@vL>&yW)vB zHT-+^8U4rRMZs;4;tm!lH=cTbixDsow|3-m(bAqHNY%`hBwq#hW4Sw^>-_t#<5eyPAqB8(*OTiZ^LkD` zK93ojg=Alno!@lew+g^O(L>m~5&>*Mt?bmyf|4rxm@!PkSnKp(En!e34Ow-sPQ;uI0Sz0?;xF zllR;cVgs;o_N5b&V4-`W=kzcRhK$%&>naqcH>h2de}|~^0EL^1hR=N3su2v02+(_M{<0TbP5%KESXDllhIu( VN-uB@0x#iI)bv$Ep$#Yh{{eHl({ca+ literal 0 HcmV?d00001 diff --git a/Depth-First Search/Images/MinimumSpanningTree.sketch b/Depth-First Search/Images/MinimumSpanningTree.sketch new file mode 100644 index 0000000000000000000000000000000000000000..93a5b808cdca5702194429d6334f9f58eda147dd GIT binary patch literal 81920 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 T*AjtB9dc7$7xhlnD(rs%aZzvT literal 0 HcmV?d00001 diff --git a/Depth-First Search/Node.swift b/Depth-First Search/Node.swift new file mode 100644 index 000000000..000fd78f6 --- /dev/null +++ b/Depth-First Search/Node.swift @@ -0,0 +1,32 @@ +public class Node : CustomStringConvertible, Equatable { + public var neighbors: [Edge] + + public private(set) var label: String + public var distance: Int? + public var visited: Bool + + public init(label: String) { + self.label = label + neighbors = [] + visited = false + } + + public var description: String { + if let distance = distance { + return "Node(label: \(label), distance: \(distance))" + } + return "Node(label: \(label), distance: infinity)" + } + + public var hasDistance: Bool { + return distance != nil + } + + public func remove(edge: Edge) { + neighbors.removeAtIndex(neighbors.indexOf{ $0 === edge }!) + } +} + +public func ==(lhs: Node, rhs: Node) -> Bool { + return lhs.label == rhs.label && lhs.neighbors == rhs.neighbors +} diff --git a/Depth-First Search/README.markdown b/Depth-First Search/README.markdown new file mode 100644 index 000000000..da5fd1b0b --- /dev/null +++ b/Depth-First Search/README.markdown @@ -0,0 +1,61 @@ +# Depth-First Search + +Depth-first search (DFS) is an algorithm for traversing or searching [tree](../Tree/) or [graph](../Graph/) data structures. It starts at the tree source and explores as far as possible along each branch before backtracking. + +## The code + +Simple implementation of breadth-first search using a queue: + +```swift +func depthFirstSearch(graph: Graph, source: Node) -> [String] { + var nodesExplored: [String] = [source.label] + source.visited = true + + // Iterate through all neighbors, and for each one visit all of its neighbors + for edge in source.neighbors { + let neighbor: Node = edge.neighbor + + if (!neighbor.visited) { + nodesExplored += depthFirstSearch(graph, source: neighbor) + } + } + return nodesExplored +} +``` + +Put this code in a playground and test it like so: + +```swift +let graph = Graph() // Representing the graph from the animated example + +let nodeA = graph.addNode("a") +let nodeB = graph.addNode("b") +let nodeC = graph.addNode("c") +let nodeD = graph.addNode("d") +let nodeE = graph.addNode("e") +let nodeF = graph.addNode("f") +let nodeG = graph.addNode("g") +let nodeH = graph.addNode("h") + +graph.addEdge(nodeA, neighbor: nodeB) +graph.addEdge(nodeA, neighbor: nodeC) +graph.addEdge(nodeB, neighbor: nodeD) +graph.addEdge(nodeB, neighbor: nodeE) +graph.addEdge(nodeC, neighbor: nodeF) +graph.addEdge(nodeC, neighbor: nodeG) +graph.addEdge(nodeE, neighbor: nodeH) + +let nodesExplored = depthFirstSearch(graph, source: nodeA) +print(nodesExplored) +``` + +This will output: `["a", "b", "d", "e", "h", "c", "f", "g"]` + +## Applications + +Depth-first search can be used to solve many problems, for example: + +* Finding connected components of a sparse graph +* Topological sorting of nodes in a graph +* Finding bridges of a graph (see: [Bridges](https://en.wikipedia.org/wiki/Bridge_(graph_theory)#Bridge-finding_algorithm)) +* Among others diff --git a/Depth-First Search/Tests/DepthFirstSearchTests.swift b/Depth-First Search/Tests/DepthFirstSearchTests.swift new file mode 100755 index 000000000..aacc8efcf --- /dev/null +++ b/Depth-First Search/Tests/DepthFirstSearchTests.swift @@ -0,0 +1,84 @@ +import XCTest + +class DepthFirstSearchTests: XCTestCase { + + func testExploringTree() { + let tree = Graph() + let nodeA = tree.addNode("a") + let nodeB = tree.addNode("b") + let nodeC = tree.addNode("c") + let nodeD = tree.addNode("d") + let nodeE = tree.addNode("e") + let nodeF = tree.addNode("f") + let nodeG = tree.addNode("g") + let nodeH = tree.addNode("h") + tree.addEdge(nodeA, neighbor: nodeB) + tree.addEdge(nodeA, neighbor: nodeC) + tree.addEdge(nodeB, neighbor: nodeD) + tree.addEdge(nodeB, neighbor: nodeE) + tree.addEdge(nodeC, neighbor: nodeF) + tree.addEdge(nodeC, neighbor: nodeG) + tree.addEdge(nodeE, neighbor: nodeH) + + let nodesExplored = depthFirstSearch(tree, source: nodeA) + + XCTAssertEqual(nodesExplored, ["a", "b", "d", "e", "h", "c", "f", "g"]) + } + + func testExploringGraph() { + let graph = Graph() + + let nodeA = graph.addNode("a") + let nodeB = graph.addNode("b") + let nodeC = graph.addNode("c") + let nodeD = graph.addNode("d") + let nodeE = graph.addNode("e") + let nodeF = graph.addNode("f") + let nodeG = graph.addNode("g") + let nodeH = graph.addNode("h") + let nodeI = graph.addNode("i") + + graph.addEdge(nodeA, neighbor: nodeB) + graph.addEdge(nodeA, neighbor: nodeH) + graph.addEdge(nodeB, neighbor: nodeA) + graph.addEdge(nodeB, neighbor: nodeC) + graph.addEdge(nodeB, neighbor: nodeH) + graph.addEdge(nodeC, neighbor: nodeB) + graph.addEdge(nodeC, neighbor: nodeD) + graph.addEdge(nodeC, neighbor: nodeF) + graph.addEdge(nodeC, neighbor: nodeI) + graph.addEdge(nodeD, neighbor: nodeC) + graph.addEdge(nodeD, neighbor: nodeE) + graph.addEdge(nodeD, neighbor: nodeF) + graph.addEdge(nodeE, neighbor: nodeD) + graph.addEdge(nodeE, neighbor: nodeF) + graph.addEdge(nodeF, neighbor: nodeC) + graph.addEdge(nodeF, neighbor: nodeD) + graph.addEdge(nodeF, neighbor: nodeE) + graph.addEdge(nodeF, neighbor: nodeG) + graph.addEdge(nodeG, neighbor: nodeF) + graph.addEdge(nodeG, neighbor: nodeH) + graph.addEdge(nodeG, neighbor: nodeI) + graph.addEdge(nodeH, neighbor: nodeA) + graph.addEdge(nodeH, neighbor: nodeB) + graph.addEdge(nodeH, neighbor: nodeG) + graph.addEdge(nodeH, neighbor: nodeI) + graph.addEdge(nodeI, neighbor: nodeC) + graph.addEdge(nodeI, neighbor: nodeG) + graph.addEdge(nodeI, neighbor: nodeH) + + let nodesExplored = depthFirstSearch(graph, source: nodeA) + + XCTAssertEqual(nodesExplored, ["a", "b", "c", "d", "e", "f", "g", "h", "i"]) + + } + + func testExploringGraphWithASingleNode() { + let graph = Graph() + let node = graph.addNode("a") + + let nodesExplored = depthFirstSearch(graph, source: node) + + XCTAssertEqual(nodesExplored, ["a"]) + } +} \ No newline at end of file diff --git a/Depth-First Search/Tests/Info.plist b/Depth-First Search/Tests/Info.plist new file mode 100644 index 000000000..ba72822e8 --- /dev/null +++ b/Depth-First Search/Tests/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/Depth-First Search/Tests/Tests.xcodeproj/project.pbxproj b/Depth-First Search/Tests/Tests.xcodeproj/project.pbxproj new file mode 100644 index 000000000..e3c46e3cc --- /dev/null +++ b/Depth-First Search/Tests/Tests.xcodeproj/project.pbxproj @@ -0,0 +1,276 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 83F9C96C1C8443E800B3A87F /* DepthFirstSearchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83F9C96B1C8443E800B3A87F /* DepthFirstSearchTests.swift */; }; + 83F9C9711C84449D00B3A87F /* Edge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83F9C96D1C84449D00B3A87F /* Edge.swift */; }; + 83F9C9721C84449D00B3A87F /* Graph.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83F9C96E1C84449D00B3A87F /* Graph.swift */; }; + 83F9C9731C84449D00B3A87F /* Node.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83F9C96F1C84449D00B3A87F /* Node.swift */; }; + FFC6E11E1C8656D10046BA79 /* DepthFirstSearch.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFC6E11D1C8656D10046BA79 /* DepthFirstSearch.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 7B2BBC801C779D720067B71D /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 7B2BBC941C779E7B0067B71D /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; + 83F9C96B1C8443E800B3A87F /* DepthFirstSearchTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DepthFirstSearchTests.swift; sourceTree = SOURCE_ROOT; }; + 83F9C96D1C84449D00B3A87F /* Edge.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Edge.swift; path = ../Edge.swift; sourceTree = SOURCE_ROOT; }; + 83F9C96E1C84449D00B3A87F /* Graph.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Graph.swift; path = ../Graph.swift; sourceTree = SOURCE_ROOT; }; + 83F9C96F1C84449D00B3A87F /* Node.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Node.swift; path = ../Node.swift; sourceTree = SOURCE_ROOT; }; + FFC6E11D1C8656D10046BA79 /* DepthFirstSearch.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = DepthFirstSearch.swift; path = ../DepthFirstSearch.swift; sourceTree = SOURCE_ROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 7B2BBC7D1C779D720067B71D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 7B2BBC681C779D710067B71D = { + isa = PBXGroup; + children = ( + 7B2BBC831C779D720067B71D /* Tests */, + 7B2BBC721C779D710067B71D /* Products */, + ); + sourceTree = ""; + }; + 7B2BBC721C779D710067B71D /* Products */ = { + isa = PBXGroup; + children = ( + 7B2BBC801C779D720067B71D /* Tests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 7B2BBC831C779D720067B71D /* Tests */ = { + isa = PBXGroup; + children = ( + 83F9C96D1C84449D00B3A87F /* Edge.swift */, + 83F9C96E1C84449D00B3A87F /* Graph.swift */, + 83F9C96F1C84449D00B3A87F /* Node.swift */, + 83F9C96B1C8443E800B3A87F /* DepthFirstSearchTests.swift */, + FFC6E11D1C8656D10046BA79 /* DepthFirstSearch.swift */, + 7B2BBC941C779E7B0067B71D /* Info.plist */, + ); + name = Tests; + path = TestsTests; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 7B2BBC7F1C779D720067B71D /* Tests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */; + buildPhases = ( + 7B2BBC7C1C779D720067B71D /* Sources */, + 7B2BBC7D1C779D720067B71D /* Frameworks */, + 7B2BBC7E1C779D720067B71D /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Tests; + productName = TestsTests; + productReference = 7B2BBC801C779D720067B71D /* Tests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 7B2BBC691C779D710067B71D /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0720; + LastUpgradeCheck = 0720; + ORGANIZATIONNAME = "Swift Algorithm Club"; + TargetAttributes = { + 7B2BBC7F1C779D720067B71D = { + CreatedOnToolsVersion = 7.2; + }; + }; + }; + buildConfigurationList = 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 7B2BBC681C779D710067B71D; + productRefGroup = 7B2BBC721C779D710067B71D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 7B2BBC7F1C779D720067B71D /* Tests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 7B2BBC7E1C779D720067B71D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 7B2BBC7C1C779D720067B71D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 83F9C9721C84449D00B3A87F /* Graph.swift in Sources */, + 83F9C9711C84449D00B3A87F /* Edge.swift in Sources */, + FFC6E11E1C8656D10046BA79 /* DepthFirstSearch.swift in Sources */, + 83F9C96C1C8443E800B3A87F /* DepthFirstSearchTests.swift in Sources */, + 83F9C9731C84449D00B3A87F /* Node.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 7B2BBC871C779D720067B71D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 7B2BBC881C779D720067B71D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + }; + name = Release; + }; + 7B2BBC8D1C779D720067B71D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 7B2BBC8E1C779D720067B71D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7B2BBC871C779D720067B71D /* Debug */, + 7B2BBC881C779D720067B71D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7B2BBC8D1C779D720067B71D /* Debug */, + 7B2BBC8E1C779D720067B71D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 7B2BBC691C779D710067B71D /* Project object */; +} From 17aa1a043d7a634424a9d9a48a8ebe744ae9e0e1 Mon Sep 17 00:00:00 2001 From: Paulo Tanaka Date: Tue, 1 Mar 2016 15:18:38 -0800 Subject: [PATCH 0092/1679] Removing dfs images --- .../Resources/Animated_BFS.gif | Bin 33276 -> 0 bytes .../Resources/Minimum_Spanning_Tree.png | Bin 23928 -> 0 bytes 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 Depth-First Search/DepthFirstSearch.playground/Resources/Animated_BFS.gif delete mode 100644 Depth-First Search/DepthFirstSearch.playground/Resources/Minimum_Spanning_Tree.png diff --git a/Depth-First Search/DepthFirstSearch.playground/Resources/Animated_BFS.gif b/Depth-First Search/DepthFirstSearch.playground/Resources/Animated_BFS.gif deleted file mode 100644 index d8fe07cbc40a0a19534b597e123bf803de42f205..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 33276 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 VN-uB@0x#iI)bv$Ep$#Yh{{eHl({ca+ diff --git a/Depth-First Search/DepthFirstSearch.playground/Resources/Minimum_Spanning_Tree.png b/Depth-First Search/DepthFirstSearch.playground/Resources/Minimum_Spanning_Tree.png deleted file mode 100644 index bce73cc8eaf8a1dd24c8f96269bd2ac127414cf9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23928 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 T*AjtB9dc7$7xhlnD(rs%aZzvT From e98fe5c64dcd5b6d58340a360a3dec8805d22599 Mon Sep 17 00:00:00 2001 From: Paulo Tanaka Date: Tue, 1 Mar 2016 15:22:47 -0800 Subject: [PATCH 0093/1679] Removing README images --- Depth-First Search/Images/Animated_BFS.gif | Bin 33276 -> 0 bytes .../Images/MinimumSpanningTree.sketch | Bin 81920 -> 0 bytes .../Images/Minimum_Spanning_Tree.png | Bin 23928 -> 0 bytes 3 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 Depth-First Search/Images/Animated_BFS.gif delete mode 100644 Depth-First Search/Images/MinimumSpanningTree.sketch delete mode 100644 Depth-First Search/Images/Minimum_Spanning_Tree.png diff --git a/Depth-First Search/Images/Animated_BFS.gif b/Depth-First Search/Images/Animated_BFS.gif deleted file mode 100644 index d8fe07cbc40a0a19534b597e123bf803de42f205..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 33276 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 VN-uB@0x#iI)bv$Ep$#Yh{{eHl({ca+ diff --git a/Depth-First Search/Images/MinimumSpanningTree.sketch b/Depth-First Search/Images/MinimumSpanningTree.sketch deleted file mode 100644 index 93a5b808cdca5702194429d6334f9f58eda147dd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 81920 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 T*AjtB9dc7$7xhlnD(rs%aZzvT From 4c25b90064d28033c3ced696cd6445ede8524a78 Mon Sep 17 00:00:00 2001 From: John Gill Date: Tue, 1 Mar 2016 22:14:35 -0800 Subject: [PATCH 0094/1679] Write BPQ README.md --- Bounded Priority Queue/README.md | 80 ++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 Bounded Priority Queue/README.md diff --git a/Bounded Priority Queue/README.md b/Bounded Priority Queue/README.md new file mode 100644 index 000000000..2d19ecba9 --- /dev/null +++ b/Bounded Priority Queue/README.md @@ -0,0 +1,80 @@ +# Bounded Priority queue + +A bounded priority queue is similar to a regular [priority queue](../Priority Queue), except that there is a fixed upper bound on the number of elements that can be stored. Whenever a new element is added to the queue, if the queue is at capacity, the element with the highest priority value is ejected from the queue. + +## Example +Supposed we have a bounded-priority-queue with maximum size 5 that has the following values and priorities: +``` +Value: [A, B, C, D, E] +Priority: [0.1, 0.25, 1.33, 3.2, 4.6] +``` +Suppose that we want to insert the element `F` with priority `0.4` into this bounded priority queue. Because this bounded-priority-queue has maximum size five, this will insert the element `F`, but then evict the lowest-priority element (`E`), yielding the updated queue: +``` +Value: [A, B, F, C, D] +Priority: [0.1, 0.25, 0.4, 1.33, 3.2] +``` +Now suppose that we wish to insert the element G with priority 4.0 into this BPQ. Because G's priority value is greater than the maximum-priority element in the BPQ, upon inserting G it will immediately be evicted. In other words, inserting an element into a BPQ with priority greater than the maximum-priority element of the BPQ has no effect. + +## Implementation +While a [heap](../Heap) may be a really simple implementation for a priority queue, an sorted [linked list](../Linked List) allows for `O(k)` insertion and `O(1)` deletion. Where `k` is the bounding number of elements. +```swift +public func enqueue(value: T) { + let newNode = Node(value: value) + + if head == nil { + head = newNode + } else { + var node = head + if curNumElements == maxNumElements && !(newNode.value < node!.value) { + return + } + + while (node!.next != nil) && (newNode.value < node!.value) { node = node!.next } + + if newNode.value < node!.value { + newNode.next = node!.next + newNode.previous = node + + if(newNode.next != nil) { /* TAIL */ + newNode.next!.previous = newNode + } + node!.next = newNode + } else { + newNode.previous = node!.previous + newNode.next = node + if(node!.previous == nil) { /* HEAD */ + head = newNode + } else { + node!.previous!.next = newNode + } + node!.previous = newNode + } + if(curNumElements == maxNumElements) { dequeue() } + } + curNumElements += 1 +} +``` +The `enqueue(_:)` method checks if the queue already has the maximum number of elements. If the new value is greater than the `head` value then don't insert it. If the new value is less than `head` search through the list to find the proper insertion location and update the pointers. + +Lastly if the queue has reached the maximum number of elements `dequeue()` the highest priority one. + +By keeping the element with the highest priority as the head it allows for a simple update of the `head` variable in a `dequeue()`: +```swift +public func dequeue() -> T? { + if curNumElements > 0 { + let retVal = head!.value + + if curNumElements == 1 { + head = nil + } + else { + head = head!.next + head!.previous = nil + } + + curNumElements -= 1 + return retVal + } + return nil +} +``` From 3467142bca114217f8393bcf19c5d99b80d81b62 Mon Sep 17 00:00:00 2001 From: John Gill Date: Tue, 1 Mar 2016 22:17:51 -0800 Subject: [PATCH 0095/1679] Apply type constraint Comparable --- .../BoundedPriorityQueue.swift | 44 ++++++------- .../Tests/BoundedPriorityQueueTests.swift | 62 ++++++++++--------- .../Tests/Tests.xcodeproj/project.pbxproj | 4 +- 3 files changed, 56 insertions(+), 54 deletions(-) diff --git a/Bounded Priority Queue/BoundedPriorityQueue.swift b/Bounded Priority Queue/BoundedPriorityQueue.swift index f5f3a2221..91b6d30b6 100644 --- a/Bounded Priority Queue/BoundedPriorityQueue.swift +++ b/Bounded Priority Queue/BoundedPriorityQueue.swift @@ -1,18 +1,16 @@ // // BoundedPriorityQueue.swift -// Tests // // Created by John Gill on 2/28/16. -// Copyright © 2016 Swift Algorithm Club. All rights reserved. // import Foundation -public class LinkedListNode { +public class LinkedListNode { var value: T var next: LinkedListNode? var previous: LinkedListNode? - + public init(value: T) { self.value = value self.next = nil @@ -20,52 +18,50 @@ public class LinkedListNode { } } -public class BoundedPriorityQueue { +public class BoundedPriorityQueue { public typealias Node = LinkedListNode private var head: Node? - private var isLessThan:(T, T) -> Bool private var curNumElements:Int private var maxNumElements: Int - - public init(sort: (T, T) -> Bool, maxElements:Int) { - isLessThan = sort + + public init(maxElements:Int) { head = nil maxNumElements = maxElements curNumElements = 0 } - + public var isEmpty: Bool { return curNumElements == 0 } - + public var count: Int { return curNumElements } - + public func peek() -> T? { if curNumElements > 0 { return head!.value } return nil } - + public func enqueue(value: T) { let newNode = Node(value: value) - + if head == nil { head = newNode } else { var node = head - if curNumElements == maxNumElements && !isLessThan(newNode.value, node!.value) { + if curNumElements == maxNumElements && newNode.value > node!.value { return } - while node!.next != nil && isLessThan(newNode.value, node!.value) { node = node!.next } - - if isLessThan(newNode.value, node!.value) { + while (node!.next != nil) && (newNode.value < node!.value) { node = node!.next } + + if newNode.value < node!.value { newNode.next = node!.next newNode.previous = node - + if(newNode.next != nil) { /* TAIL */ newNode.next!.previous = newNode } @@ -82,13 +78,13 @@ public class BoundedPriorityQueue { } if(curNumElements == maxNumElements) { dequeue() } } - curNumElements++ + curNumElements += 1 } - + public func dequeue() -> T? { if curNumElements > 0 { let retVal = head!.value - + if curNumElements == 1 { head = nil } @@ -97,9 +93,9 @@ public class BoundedPriorityQueue { head!.previous = nil } - curNumElements-- + curNumElements -= 1 return retVal } return nil } -} \ No newline at end of file +} diff --git a/Bounded Priority Queue/Tests/BoundedPriorityQueueTests.swift b/Bounded Priority Queue/Tests/BoundedPriorityQueueTests.swift index 4b68b0bab..772999e84 100644 --- a/Bounded Priority Queue/Tests/BoundedPriorityQueueTests.swift +++ b/Bounded Priority Queue/Tests/BoundedPriorityQueueTests.swift @@ -1,60 +1,66 @@ // // BoundedPriorityQueueTests.swift -// Tests // // Created by John Gill on 2/28/16. -// Copyright © 2016 Swift Algorithm Club. All rights reserved. // import Foundation import XCTest -private struct Message { +private struct Message: Comparable { let name: String let priority: Int } -private func < (m1: Message, m2: Message) -> Bool { +private func ==(m1: Message, m2: Message) -> Bool { + return m1.priority == m2.priority +} + +private func <(m1: Message, m2: Message) -> Bool { return m1.priority < m2.priority } +private func >(m1: Message, m2: Message) -> Bool { + return m1.priority > m2.priority +} + class BoundedPriorityQueueTest: XCTestCase { func testEmpty() { - let queue = BoundedPriorityQueue(sort: <, maxElements: 5) + let queue = BoundedPriorityQueue(maxElements: 5) XCTAssertTrue(queue.isEmpty) XCTAssertEqual(queue.count, 0) XCTAssertNil(queue.dequeue()) } - + func testOneElement() { - let queue = BoundedPriorityQueue(sort: <, maxElements: 5) - + let queue = BoundedPriorityQueue(maxElements: 5) + queue.enqueue(Message(name: "hello", priority: 100)) XCTAssertFalse(queue.isEmpty) XCTAssertEqual(queue.count, 1) - + let result = queue.dequeue() XCTAssertEqual(result!.priority, 100) XCTAssertTrue(queue.isEmpty) XCTAssertEqual(queue.count, 0) } - + func testMaxElements() { - let queue = BoundedPriorityQueue(sort: <, maxElements: 5) + let queue = BoundedPriorityQueue(maxElements: 5) XCTAssertTrue(queue.isEmpty) - + queue.enqueue(Message(name: "john", priority: 100)) XCTAssertEqual(queue.count, 1) XCTAssertEqual(queue.peek()?.priority, 100) - + queue.enqueue(Message(name: "james", priority: 200)) XCTAssertEqual(queue.count, 2) XCTAssertEqual(queue.peek()?.priority, 200) - + queue.enqueue(Message(name: "mark", priority: 300)) XCTAssertEqual(queue.count, 3) XCTAssertEqual(queue.peek()?.priority, 300) - + queue.enqueue(Message(name: "ken", priority: 400)) XCTAssertEqual(queue.count, 4) XCTAssertEqual(queue.peek()?.priority, 400) @@ -62,54 +68,54 @@ class BoundedPriorityQueueTest: XCTestCase { queue.enqueue(Message(name: "thomas", priority: 500)) XCTAssertEqual(queue.count, 5) XCTAssertEqual(queue.peek()?.priority, 500) - + queue.enqueue(Message(name: "melanie", priority: 550)) XCTAssertEqual(queue.count, 5) XCTAssertEqual(queue.peek()?.priority, 500) - + queue.enqueue(Message(name: "lily", priority: 450)) XCTAssertEqual(queue.count, 5) XCTAssertEqual(queue.peek()?.priority, 450) - + queue.enqueue(Message(name: "fred", priority: 350)) XCTAssertEqual(queue.count, 5) XCTAssertEqual(queue.peek()?.priority, 400) - + queue.enqueue(Message(name: "rachel", priority: 50)) XCTAssertEqual(queue.count, 5) XCTAssertEqual(queue.peek()?.priority, 350) - + var result = queue.dequeue() XCTAssertEqual(result!.priority, 350) XCTAssertEqual(queue.count, 4) - + result = queue.dequeue() XCTAssertEqual(result!.priority, 300) XCTAssertEqual(queue.count, 3) - + result = queue.dequeue() XCTAssertEqual(result!.priority, 200) XCTAssertEqual(queue.count, 2) - + queue.enqueue(Message(name: "ryan", priority: 150)) XCTAssertEqual(queue.count, 3) XCTAssertEqual(queue.peek()?.priority, 150) - + result = queue.dequeue() XCTAssertEqual(result!.priority, 150) XCTAssertEqual(queue.count, 2) - + result = queue.dequeue() XCTAssertEqual(result!.priority, 100) XCTAssertEqual(queue.count, 1) - + result = queue.dequeue() XCTAssertEqual(result!.priority, 50) XCTAssertEqual(queue.count, 0) - + result = queue.dequeue() XCTAssertNil(result) XCTAssertEqual(queue.count, 0) XCTAssertTrue(queue.isEmpty) } -} \ No newline at end of file +} diff --git a/Bounded Priority Queue/Tests/Tests.xcodeproj/project.pbxproj b/Bounded Priority Queue/Tests/Tests.xcodeproj/project.pbxproj index 2920474ae..6fd5c0b46 100644 --- a/Bounded Priority Queue/Tests/Tests.xcodeproj/project.pbxproj +++ b/Bounded Priority Queue/Tests/Tests.xcodeproj/project.pbxproj @@ -14,8 +14,8 @@ /* Begin PBXFileReference section */ B80004B31C83E342001FE2D7 /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; B80004B81C83E342001FE2D7 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; - B810B5B01C83E3B200450324 /* BoundedPriorityQueueTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BoundedPriorityQueueTests.swift; path = ../BoundedPriorityQueueTests.swift; sourceTree = ""; }; - B8F635A71C83E4270060805E /* BoundedPriorityQueue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BoundedPriorityQueue.swift; path = ../../BoundedPriorityQueue.swift; sourceTree = ""; }; + B810B5B01C83E3B200450324 /* BoundedPriorityQueueTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BoundedPriorityQueueTests.swift; sourceTree = SOURCE_ROOT; }; + B8F635A71C83E4270060805E /* BoundedPriorityQueue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BoundedPriorityQueue.swift; path = ../BoundedPriorityQueue.swift; sourceTree = SOURCE_ROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ From 591f711dc832cd1d8b091a2c6830d4cb5ffb6e84 Mon Sep 17 00:00:00 2001 From: John Gill Date: Tue, 1 Mar 2016 22:42:47 -0800 Subject: [PATCH 0096/1679] BPQ Update main README.markdown --- README.markdown | 1 + 1 file changed, 1 insertion(+) diff --git a/README.markdown b/README.markdown index 03bd2601b..e3f85f910 100644 --- a/README.markdown +++ b/README.markdown @@ -125,6 +125,7 @@ Most of the time using just the built-in `Array`, `Dictionary`, and `Set` types - [Queue](Queue/). First-in, first-out! - [Deque](Deque/). A double-ended queue. - [Priority Queue](Priority Queue). A queue where the most important element is always at the front. +- [Bounded Priority Queue](Bounded Priority Queue). A queue that is bounded to have a limited number of elements. - [Ring Buffer](Ring Buffer/). Also known as a circular buffer. An array of a certain size that conceptually wraps around back to the beginning. ### Lists From 671926fe755d3b727a25be505d67c156c1aa993e Mon Sep 17 00:00:00 2001 From: John Gill Date: Tue, 1 Mar 2016 22:51:20 -0800 Subject: [PATCH 0097/1679] BPQ Remove kNN code from branch --- .../Contents.swift | 47 ------------------- .../contents.xcplayground | 4 -- .../timeline.xctimeline | 31 ------------ K-Nearest Neighbors/README.md | 7 --- 4 files changed, 89 deletions(-) delete mode 100644 K-Nearest Neighbors/K-Nearest Neighbors.playground/Contents.swift delete mode 100644 K-Nearest Neighbors/K-Nearest Neighbors.playground/contents.xcplayground delete mode 100644 K-Nearest Neighbors/K-Nearest Neighbors.playground/timeline.xctimeline delete mode 100644 K-Nearest Neighbors/README.md diff --git a/K-Nearest Neighbors/K-Nearest Neighbors.playground/Contents.swift b/K-Nearest Neighbors/K-Nearest Neighbors.playground/Contents.swift deleted file mode 100644 index a4dd21dd0..000000000 --- a/K-Nearest Neighbors/K-Nearest Neighbors.playground/Contents.swift +++ /dev/null @@ -1,47 +0,0 @@ -// -// K-NearestNeighbors.swift -// -// Created by John Gill on 2/23/16. -import Foundation - -// Container to easily hold N Dimensional Vectors -class VectorND: CustomStringConvertible { - private var length = 0 - private var data = [Double]() - - init(d:[Double]) { - data = d - length = d.count - } - - var description: String { return "VectorND (\(data)" } - func getData() -> [Double] { return data } - func getLength() -> Int { return length } - - // Calculates the Euclidean distance from - // this point to another VectorND - func getDist(v:VectorND) -> Double { - var result = 0.0 - for idx in 0.. [Int] { - - return [] - } -} \ No newline at end of file diff --git a/K-Nearest Neighbors/K-Nearest Neighbors.playground/contents.xcplayground b/K-Nearest Neighbors/K-Nearest Neighbors.playground/contents.xcplayground deleted file mode 100644 index 9f9eecc96..000000000 --- a/K-Nearest Neighbors/K-Nearest Neighbors.playground/contents.xcplayground +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/K-Nearest Neighbors/K-Nearest Neighbors.playground/timeline.xctimeline b/K-Nearest Neighbors/K-Nearest Neighbors.playground/timeline.xctimeline deleted file mode 100644 index 4dca8e784..000000000 --- a/K-Nearest Neighbors/K-Nearest Neighbors.playground/timeline.xctimeline +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/K-Nearest Neighbors/README.md b/K-Nearest Neighbors/README.md deleted file mode 100644 index 9e22c4a02..000000000 --- a/K-Nearest Neighbors/README.md +++ /dev/null @@ -1,7 +0,0 @@ -# k-Nearest Neighbors - -Goal: Label Data into Clusters by k Nearest other points - -Machine Learning algorithms are two pass: - 1. Train the algorithm on a set of Data - 2. Predict new labels for data based on training From bf6680591a58b3cb5bdd9b30db815091d33e1d78 Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Wed, 2 Mar 2016 22:21:06 +1300 Subject: [PATCH 0098/1679] Travis-CI - Adding several test projects --- travis.yml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 travis.yml diff --git a/travis.yml b/travis.yml new file mode 100644 index 000000000..7882690d3 --- /dev/null +++ b/travis.yml @@ -0,0 +1,6 @@ +osx_image: xcode7.2 + +script: +- xcodebuild test -project ./AVL\ Tree/Tests/Tests.xcodeproj -scheme Tests +- xcodebuild test -project ./Array2D/Tests/Tests.xcodeproj -scheme Tests +- xcodebuild test -project ./Binary\ Search/Tests/Tests.xcodeproj -scheme Tests From 914ca49c2f81c91049b197abb45cba910965040e Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Wed, 2 Mar 2016 22:25:33 +1300 Subject: [PATCH 0099/1679] Travis: Renaming travis file --- travis.yml => .travis.yml | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename travis.yml => .travis.yml (100%) diff --git a/travis.yml b/.travis.yml similarity index 100% rename from travis.yml rename to .travis.yml From 59dee733d4c3d54776b0394be396fba30b97f4e3 Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Wed, 2 Mar 2016 22:28:32 +1300 Subject: [PATCH 0100/1679] Travis: adding language --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 7882690d3..87fcc6438 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,3 +1,4 @@ +language: objective-c osx_image: xcode7.2 script: From a2ec9dda5c1112083df30a7f327d2b546548e004 Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Wed, 2 Mar 2016 22:32:18 +1300 Subject: [PATCH 0101/1679] Building before running tests --- .travis.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 87fcc6438..591f2cbdc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,6 +2,7 @@ language: objective-c osx_image: xcode7.2 script: +- xcodebuild build -project ./AVL\ Tree/Tests/Tests.xcodeproj - xcodebuild test -project ./AVL\ Tree/Tests/Tests.xcodeproj -scheme Tests -- xcodebuild test -project ./Array2D/Tests/Tests.xcodeproj -scheme Tests -- xcodebuild test -project ./Binary\ Search/Tests/Tests.xcodeproj -scheme Tests +#- xcodebuild test -project ./Array2D/Tests/Tests.xcodeproj -scheme Tests +#- xcodebuild test -project ./Binary\ Search/Tests/Tests.xcodeproj -scheme Tests From ce6e7b4f4f3ebbe266ee68e3df1b4c36a45058b0 Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Wed, 2 Mar 2016 22:50:29 +1300 Subject: [PATCH 0102/1679] Travis: making test scheme shared --- .travis.yml | 23 ++++++-- .../xcshareddata/xcschemes/Tests.xcscheme | 56 +++++++++++++++++++ 2 files changed, 75 insertions(+), 4 deletions(-) create mode 100644 Heap/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme diff --git a/.travis.yml b/.travis.yml index 591f2cbdc..d1a498cd6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,22 @@ language: objective-c osx_image: xcode7.2 script: -- xcodebuild build -project ./AVL\ Tree/Tests/Tests.xcodeproj -- xcodebuild test -project ./AVL\ Tree/Tests/Tests.xcodeproj -scheme Tests -#- xcodebuild test -project ./Array2D/Tests/Tests.xcodeproj -scheme Tests -#- xcodebuild test -project ./Binary\ Search/Tests/Tests.xcodeproj -scheme Tests + +- xcodebuild test -project ./Heap/Tests/Tests.xcodeproj -scheme Tests +# - xcodebuild build -project ./AVL\ Tree/Tests/Tests.xcodeproj +# - xcodebuild test -project ./AVL\ Tree/Tests/Tests.xcodeproj -scheme Tests + +# - xcodebuild build -project ./Array2D/Tests/Tests.xcodeproj +# - xcodebuild test -project ./Array2D/Tests/Tests.xcodeproj -scheme Tests + +# - xcodebuild build -project ./Binary\ Search/Tests/Tests.xcodeproj +# - xcodebuild test -project ./Binary\ Search/Tests/Tests.xcodeproj -scheme Tests + +# - xcodebuild build -project ./Binary\ Search/Tests/Tests.xcodeproj +# - xcodebuild test -project ./Binary\ Search/Tests/Tests.xcodeproj -scheme Tests + + + + +# - xcodebuild build -project ./Heap/Tests/Tests.xcodeproj +# - xcodebuild test -project ./Heap/Tests/Tests.xcodeproj -scheme Tests diff --git a/Heap/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Heap/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme new file mode 100644 index 000000000..74dd9450b --- /dev/null +++ b/Heap/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + From 2e7e1e8a87c30db59d3a2c2a937e67a2b5aa2ee2 Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Wed, 2 Mar 2016 23:12:53 +1300 Subject: [PATCH 0103/1679] Including all files. Changing all schemes to "shared" --- .travis.yml | 35 ++++++------ .../xcshareddata/xcschemes/Tests.xcscheme | 56 +++++++++++++++++++ .../xcshareddata/xcschemes/Tests.xcscheme | 56 +++++++++++++++++++ .../xcshareddata/xcschemes/Tests.xcscheme | 56 +++++++++++++++++++ .../xcshareddata/xcschemes/Tests.xcscheme | 56 +++++++++++++++++++ .../xcshareddata/xcschemes/Tests.xcscheme | 56 +++++++++++++++++++ .../xcshareddata/xcschemes/Tests.xcscheme | 56 +++++++++++++++++++ .../xcshareddata/xcschemes/Tests.xcscheme | 56 +++++++++++++++++++ .../xcshareddata/xcschemes/Tests.xcscheme | 56 +++++++++++++++++++ .../xcshareddata/xcschemes/Tests.xcscheme | 56 +++++++++++++++++++ .../xcshareddata/xcschemes/Tests.xcscheme | 56 +++++++++++++++++++ .../xcshareddata/xcschemes/Tests.xcscheme | 56 +++++++++++++++++++ .../xcshareddata/xcschemes/Tests.xcscheme | 56 +++++++++++++++++++ .../xcshareddata/xcschemes/Tests.xcscheme | 56 +++++++++++++++++++ .../xcshareddata/xcschemes/Tests.xcscheme | 56 +++++++++++++++++++ .../xcshareddata/xcschemes/Tests.xcscheme | 56 +++++++++++++++++++ .../xcshareddata/xcschemes/Tests.xcscheme | 56 +++++++++++++++++++ .../xcshareddata/xcschemes/Tests.xcscheme | 56 +++++++++++++++++++ .../xcshareddata/xcschemes/Tests.xcscheme | 56 +++++++++++++++++++ 19 files changed, 1026 insertions(+), 17 deletions(-) create mode 100644 AVL Tree/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme create mode 100644 Array2D/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme create mode 100644 Binary Search Tree/Solution 1/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme create mode 100644 Binary Search/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme create mode 100644 Bloom Filter/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme create mode 100644 Breadth-First Search/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme create mode 100644 Heap Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme create mode 100644 Insertion Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme create mode 100644 K-Means/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme create mode 100644 Linked List/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme create mode 100644 Priority Queue/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme create mode 100644 Queue/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme create mode 100644 Quicksort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme create mode 100644 Run-Length Encoding/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme create mode 100644 Select Minimum Maximum/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme create mode 100644 Selection Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme create mode 100644 Shell Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme create mode 100644 Stack/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme diff --git a/.travis.yml b/.travis.yml index d1a498cd6..9a4806998 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,21 +3,22 @@ osx_image: xcode7.2 script: +- xcodebuild test -project ./Array2D/Tests/Tests.xcodeproj -scheme Tests +- xcodebuild test -project ./AVL\ Tree/Tests/Tests.xcodeproj -scheme Tests +- xcodebuild test -project ./Binary\ Search/Tests/Tests.xcodeproj -scheme Tests +- xcodebuild test -project ./Binary\ Search\ Tree/Solution\ 1/Tests/Tests.xcodeproj -scheme Tests +- xcodebuild test -project ./Bloom\ Filter/Tests/Tests.xcodeproj -scheme Tests +- xcodebuild test -project ./Breadth-First\ Search/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Heap/Tests/Tests.xcodeproj -scheme Tests -# - xcodebuild build -project ./AVL\ Tree/Tests/Tests.xcodeproj -# - xcodebuild test -project ./AVL\ Tree/Tests/Tests.xcodeproj -scheme Tests - -# - xcodebuild build -project ./Array2D/Tests/Tests.xcodeproj -# - xcodebuild test -project ./Array2D/Tests/Tests.xcodeproj -scheme Tests - -# - xcodebuild build -project ./Binary\ Search/Tests/Tests.xcodeproj -# - xcodebuild test -project ./Binary\ Search/Tests/Tests.xcodeproj -scheme Tests - -# - xcodebuild build -project ./Binary\ Search/Tests/Tests.xcodeproj -# - xcodebuild test -project ./Binary\ Search/Tests/Tests.xcodeproj -scheme Tests - - - - -# - xcodebuild build -project ./Heap/Tests/Tests.xcodeproj -# - xcodebuild test -project ./Heap/Tests/Tests.xcodeproj -scheme Tests +- xcodebuild test -project ./Heap\ Sort/Tests/Tests.xcodeproj -scheme Tests +- xcodebuild test -project ./Insertion\ Sort/Tests/Tests.xcodeproj -scheme Tests +- xcodebuild test -project ./K-Means/Tests/Tests.xcodeproj -scheme Tests +- xcodebuild test -project ./Linked\ List/Tests/Tests.xcodeproj -scheme Tests +- xcodebuild test -project ./Priority\ Queue/Tests/Tests.xcodeproj -scheme Tests +- xcodebuild test -project ./Queue/Tests/Tests.xcodeproj -scheme Tests +- xcodebuild test -project ./Quicksort/Tests/Tests.xcodeproj -scheme Tests +- xcodebuild test -project ./Run-Length\ Encoding/Tests/Tests.xcodeproj -scheme Tests +- xcodebuild test -project ./Select\ Minimum\ Maximum/Tests/Tests.xcodeproj -scheme Tests +- xcodebuild test -project ./Selection\ Sort/Tests/Tests.xcodeproj -scheme Tests +- xcodebuild test -project ./Shell\ Sort/Tests/Tests.xcodeproj -scheme Tests +- xcodebuild test -project ./Stack/Tests/Tests.xcodeproj -scheme Tests diff --git a/AVL Tree/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/AVL Tree/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme new file mode 100644 index 000000000..74dd9450b --- /dev/null +++ b/AVL Tree/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Array2D/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Array2D/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme new file mode 100644 index 000000000..74dd9450b --- /dev/null +++ b/Array2D/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Binary Search Tree/Solution 1/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Binary Search Tree/Solution 1/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme new file mode 100644 index 000000000..74dd9450b --- /dev/null +++ b/Binary Search Tree/Solution 1/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Binary Search/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Binary Search/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme new file mode 100644 index 000000000..74dd9450b --- /dev/null +++ b/Binary Search/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Bloom Filter/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Bloom Filter/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme new file mode 100644 index 000000000..74dd9450b --- /dev/null +++ b/Bloom Filter/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Breadth-First Search/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Breadth-First Search/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme new file mode 100644 index 000000000..74dd9450b --- /dev/null +++ b/Breadth-First Search/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Heap Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Heap Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme new file mode 100644 index 000000000..74dd9450b --- /dev/null +++ b/Heap Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Insertion Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Insertion Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme new file mode 100644 index 000000000..74dd9450b --- /dev/null +++ b/Insertion Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/K-Means/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/K-Means/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme new file mode 100644 index 000000000..54b00dc9a --- /dev/null +++ b/K-Means/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Linked List/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Linked List/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme new file mode 100644 index 000000000..74dd9450b --- /dev/null +++ b/Linked List/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Priority Queue/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Priority Queue/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme new file mode 100644 index 000000000..74dd9450b --- /dev/null +++ b/Priority Queue/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Queue/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Queue/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme new file mode 100644 index 000000000..74dd9450b --- /dev/null +++ b/Queue/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Quicksort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Quicksort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme new file mode 100644 index 000000000..74dd9450b --- /dev/null +++ b/Quicksort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Run-Length Encoding/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Run-Length Encoding/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme new file mode 100644 index 000000000..74dd9450b --- /dev/null +++ b/Run-Length Encoding/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Select Minimum Maximum/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Select Minimum Maximum/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme new file mode 100644 index 000000000..74dd9450b --- /dev/null +++ b/Select Minimum Maximum/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Selection Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Selection Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme new file mode 100644 index 000000000..74dd9450b --- /dev/null +++ b/Selection Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Shell Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Shell Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme new file mode 100644 index 000000000..74dd9450b --- /dev/null +++ b/Shell Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Stack/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Stack/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme new file mode 100644 index 000000000..74dd9450b --- /dev/null +++ b/Stack/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + From 6f8badd5247fdcb248e4d0e6a65b9fb9d18d8403 Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Wed, 2 Mar 2016 23:43:41 +1300 Subject: [PATCH 0104/1679] Travis: adding contribution guidelines for Travis-CI test projects --- How to Contribute.markdown | 11 +++++++++-- Images/scheme-settings-for-travis.png | Bin 0 -> 70387 bytes README.markdown | 2 ++ 3 files changed, 11 insertions(+), 2 deletions(-) create mode 100644 Images/scheme-settings-for-travis.png diff --git a/How to Contribute.markdown b/How to Contribute.markdown index 0069c57ba..215539ae2 100644 --- a/How to Contribute.markdown +++ b/How to Contribute.markdown @@ -6,9 +6,9 @@ Want to help out with the Swift Algorithm Club? Great! Take a look at the [list](README.markdown). Any algorithms or data structures that don't have a link yet are up for grabs. -New algorithms and data structures are always welcome (even if they aren't on the list). +New algorithms and data structures are always welcome (even if they aren't on the list). -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. +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. Unit tests. Fixes for typos. No contribution is too small. :-) @@ -21,6 +21,13 @@ To keep this a high quality repo, please follow this process when submitting you 3. Write an explanation of how the algorithm works. Include **plenty of examples** for readers to follow along. Pictures are good. Take a look at [the explanation of quicksort](Quicksort/) to get an idea. 4. Include your name in the explanation, something like *Written by Your Name* at the end of the document. If you wrote it, you deserve the credit and fame. 5. Add a playground and/or unit tests. + - Add unit test projects to `.travis.yml` so they will be run on [Travis-CI](https://travis-ci.org/hollance/swift-algorithm-club) + - `- xcodebuild test -project ./Algorithm/Tests/Tests.xcodeproj -scheme Tests` + - Configure scheme to run on Travis-CI + - Open `Product` -> `Scheme` -> `Manage Schemes ...` + - Uncheck `Autocreate schemes` + - Check `Shared` + - [Screenshot of scheme settings](/images/scheme-settings-for-travis.png) Just so you know, I will probably edit your text and code for grammar etc, just to ensure a certain level of polish. diff --git a/Images/scheme-settings-for-travis.png b/Images/scheme-settings-for-travis.png new file mode 100644 index 0000000000000000000000000000000000000000..2ada94839502790ef5ea2123279857c0454e9aa2 GIT binary patch literal 70387 zcmeEtby!=^(lC?)1q!sqic=`1I4xG(p}1?X7I$|DMGB=9D+P*MaR?eDNRR@>o#5^g z+!7K#e)qm|?|bk2|M$mxp68si+1;5rJG(nGJ2Q#WP*Whpr^3g;z#vq7FRO)tfsMex zz%qD*b6=AYX^e}3@tDd^Mn*$XMutJd-No9@(Fz0OeN>V@u7P$Rc@{wH5gz9gOx9dM zDgUG;Y|LGArk9w~crTvl9PH$UI#3Ykd6LO?fH7){zq}@wZ8sJCQe0jhjZMww@*M*L zXI~as7W6@92yG7r4`()|VoHu>F+Z`)Q^K%3ISWq+5g)t`mwl!9_{k@%w>%h+qBGf# zW4}DY){sX+2buw+RQ+Dcisiwvclw%Jt{$@(3{Ri1c(~6RKB33OfLRiR`(Zp0&RH_| z&XNpWmM&)te~8KOo%x+^1o-7U!-$Fkfw6?PCrC`m!Wx549SqW!C#g3FI?olPFsk{p zyVhk|s6P^WQ$=G{KVQQ$G@O0HuJuAd70so#xBT%{T(@PlR&NytMM*r$w<%O*df~2? z<_=KvRxaOTr%PUy1V>KEJ;JN(&mW=$^FOq98!VBZWy&9%$k8d-b9Y>g%SydrxC-X0>N-}X2zvO!ReDgSOT4s2@kTJmj41K|;JPFc?-=Y?S1g zJdKb*MuouWhpA7QE@#x7t<8Ux56>hl+!kvtgG3wKExp?5ifUge{JFL`dg%9b?5*=V zBIywBV=NVhP)SxYQmk7Bd;|u(BWSQ+-kQ@a6~}lbd1YU02M-QYePH;}<`UnVnaDExq-{2|N!rxj zh;D)!n9ww6EwXwyZy*~PY?@@yt+fL|<8O%c&9%dVlVcl6; z6vFYxU*IQk@+U@(2h*Xd=F~ITm!bHs&uOr|a-L>jQ?!$fVmgN+U7gNDDaq~lYY-&iLK(h2WhVk$~&Jr!q^-eOWtcxEY9LpU3z!w6+$NvQq9 z{EMV1+LI~hkHZGZ*IXSPvMKqPv8ZC+y_krcv7N_!WJ6K}qgFfio&-j*bkYuEwL4_z zuh`_xa>AasZ@j@Nj5Pc>{F9qJmiZ&=&nJK{WEKSmLV7X$?LI-YBo?R{g^Vu~Zm*p2 zU^Y+a!fH=w0$;S@FGuLFfPD#ov`0O-$CVGMq@vBGT$vw|tl^b}&xSKfvwo0ReYh&R zAkrG{Bg>c|#rHzEqcv4hg=Lrt#0Y1YeviXsXDvdA1s{VJ_TdMmFvv|ei$>+Wdz zmb@;q{k2o^PPC=?zd-+LzhQsb4`Mbm zEg(o*>y6%t{%SFY_H3EET0vy&7~xKvr$7*E5Ist?RX?fNK98zA4P=z(ZvZy&l2nx& zGUe2BiZx1|W95H?W$~Ohlrr@j|F`^afN$#Sb-jLZ>#+bKkiRjk@oH~4g$M)7s#cJ>Q0tgOl#{xL9b>XZutKIs2iB zxw5H3{^E*!+G5VprP3g^X0yoL^@2oDt>$)}S~iynOeUqMS@Y@}oL+^$P>?sV>GNzS z&FI89!8pn8;g|!AdR%ZUZj5`faxBn}9s`f=^I z7YTp`2==ZTu3NGRT9)s&u2IcZ4I6R*cmV31QV$75(o8-rGB*1+>tB*z8Y43=eQ0)w zv}uw>_(THTJl#o!^+Ya(D217YoO~dM<$E-%E&Vrn1RdSIRtd`a0}A>IFi}`OD7eWG zV%13N86e(g`OIg$O;HSvfOA}l!9NlgDtzyCCax~ZVi~AiIIB(xq3Csh!gyVHk35fL zmbin;gTlpG0+)~w1lO_CY1i!o)K}CTO83^{w&6wsf0Xz=VKM&mN1l%|C}v1yAK~K} zQFw|Ni2S5ArWECwwL1;%<9sn0UmWlBB2H#V=5sEg_9$y&k>k%(hQZh0==CUwI>WjI z!zI4)ME!}nc4Bk0|2 zst;*pbfvS;WHQ>hTCEoF(eUs}0XLsxv=1l$pg@P&&78&){$zIIj- zq{#XGq4JpuyXyY-&1wCKX#sA*ky3E>(=0azi+8+SwXdQxl74u7uk0LIX|UY49O;9T z8a(>?aE%6*p(=#c`D7Js{L)9>IVg)wbgwQ-MNT3Lawc{s%cd!lhXAR0&)V0sqVdZWDM!+mU8W%Htj$M3@#W0>3k`2`n|v2k^H%}a~EDe3*r zi_b18J)BMkg{_V!HCfpYf=k)7UOyvWG=%GqZ z+PZf-A|T;%);Jy25nZhf`>g!y8SmVu=fK5RAx1r6Pl`h*XLDh1x(n$ z+>7AU8pArn7G_UnlwMbbLj!Orx&F{PRo!sNyW)_&0lM5VI|iO`u({wmG+}NQKioQO zt7UOjcWQF;+cjNVx@}dz>V`X@x^GhYQE5o!%V42)2?o%Ya@!Km(sI#aFIQDEBj(aQ z5k8bg?+0kt#Z>ZCfcgSbY9aZ$_Lhy`XR#>LE(jjZ;gc!8?bm zLd`f^W7*IBv~LTiA%X;Ii1NCT=ZS^IN0dYo%RNB!{twU|0rd z%BRtj&r@wrba8Xm>k_hjK_D3FV%$XOU3;cCSRv9-v`oIdy5I*CJcE}7++0P#xq*_t z8n+s|A9k546gHvhC{reH((JvjE2XUW{wW>jqvfk8YO{GuG@c!uNo7&z2v-ygK^V_}Rw zTbadNT7QjSgG|wRGMlOSwLQ4AMkGyVrEl{S1;(3b%txPXeq>frN~wHq-MFSb#MTgL zt`=ZyV)d@CG0^diei8Vb4wz4fQG)r2yK{9lm$s|R>{6=62h+AcVG;RKI^5=V@q05_ zqkYv5*0mHGd)VC(nR8qMyFV=8xxP2_z`!79{_Dn6)OvZ0fq|K2r(@u0psFHl;o`*g z!P4cU6_>A*>wRww3{hX<`=XPT=LZH~Cr4)wVP7%Ezx5ElFaK4|&B*Y#E}jlzj0UP2 z3^Fe6Rt)@Hd|W(?;`j^<45IFq*1}q{^8W#T|4WR~*3;8fn48 zkPtV|Tkf}SIq!RLdiXhee(>dV_F(!ulK;dbYvp0#Zs+Q0=i8>;2$CXq2)gyMY;bP!9R@X@9g?p?LEK5@kP1+i}&LA zSgF_~_tQaRC#$Y=|9xsMt?$+|wkNwVO(2Imbp zx)A6MaGJ(LUo&VKOBQ?tJ;HzR(K7DIi}07ncS9MxHd~I0Y7Fr!+vmEx+k=;b0k1v` zU-@nMjf>xGBr>gi#(40E;nTl=#Aq?ZLoC}VVC{#cFx9xucx;}h_ zXd?Re@PD=2{(kTf6?46z>G{79x$kt30q6fP{2w3wb0PlUdieWZ`Tv0rRGy>3Inr}& z5~?CZzwFcv(};8nN?J~L)Ql!xY3cPm1rLko-EJvNa&3P}v!PoQFr@xhY4Tof<#@HL zw6yg5*@R!g{Z%78!1$LCoJ?#_U{YA%EGjBuXJV2W9_cx@kCzJGTxCMIszd676AHhd zdJ38xsI8+nL<29n!OY}r*R?yqkfBhFZ87t}M*K~QbTp5N-44F`yISN;L zh%%6sk^@8}e>$Y&1>~=7&cqkFA8F*R*!KzI!?$*RH33)Jbes z4gV1)Y5ljR*7C+AdK5b{S-Qh~O**c1xNJ4Eo;$a7ZlXoNlAX9uI3 zkij+(tAS+uu{^o3il0szQg>1KH?0F-s+JR1SpEeqjWQ<7iVu3Z-U$G9fWZx%)0|%X zjYqZZmxuFUk8L%<1D^+X5!d!S_lSsYS`%evjuekc{)OGKpFd5Q#F0FCdP+~AS|4)H zqKxO5+y_4BWDyetU!8u~BSfb7jlSd1JNV+oOA$)78MB#^uj0r=%oCx1`Kn1H^N}nu zcSz8?{qkD-Rw9DG%^RO+2(kEe`ysHxYk!&$B>fk-|rxDL|SR!1F-rLH` zDnZKr8He6}T#FQGO>OO>c+&Ta&pv9vq+w?gst--m)HYK8suLI(T(6HmIL+6q`uX{J z&XTx(cy>QR+iwrl%Fv6=K4n43OC@!QHjBaO4X@5HG#1%-zxo6iB`G=>f`zN2rL~rq zX_XrQYvI`BSJ$t7#ZRlZc7w}au!u|Ka0Zt_w6jrU1Uq_ocuckUoi&op@k^A46w&IP z4K^AE{u{MCsg#qKC!H?nqIa~^N^Pl63>JPwF8w#Xhn)eMSqeB3^E#Zsic(uy->$6+ywkF0-;>knLjaGCqF0@r_~yesB4v%JTBb=~jjFtzIP9 z$*f>r!PId8%@NR^FLC6T0u8ncP;`4`=-0l;J-MO?4P@%tXH%z--H|JH-hU?oOy zN#hE>NNv1%h)0ZA=1_wbj;sUD?x_of+!lvwd-~58Iuk~ny^}REGRo`%vTXREkLosj z>?Z}`9I)Fw?gjjCSrnU>$VC;7m*~PLZuYMc|FW|P4cqY$5{MlpGIDZ(jgMLaf6ZNp z5q`NrwX|5k<;$J83!}ytGRXdkj}m%rZq*2H`_ff2rwZ$#w7y-yvY(LD-B?RT&a$7b zuI}ziN0|Rj@YPN>U|_1+qPKCV-qBw+bshf8e-w{`$3WwbMnODXxm#u8RHT~Z-;@g zIkx6l69<-pVvgx@Tsl}pnAKk3m=olKLCUY_w^$)0tjBS|w=y;vZa7lG2Z}!%+M+Vr z&MeH*1)Rox@I{LCBgvf|(D{Vd77a%a(f8}{B0Fhsgk4;_!Fll`g90Rqi{6bqRLCwG zBY}@Q!OU{GX7Q|HoB88YQ~^u;?w8XZosL6Lu$f7Hr?4Wn62H$lzrU+o6z7;aH1+Na z&ekiFnat`Ba4{;OO)Dhtm|-Htt!BPIOlP^xp+AhAb^))z z5xYJkB|5%`S68-M^UYH&F#a_3`l>xSQ2IsvK?^ZnVCtaw?Z6>oNrwHfJzzhInb#|p z@b%xt=zp35Pb61<E*aFP-tc(yVi~fOAT$>p;CSvYK zub)y(TLyg``l>Hl8r>^lto_0Xm}||IUD9dccKD-W`Wgtc{p0GWgC1A%e7M|)fXxW`u}Vmbo^mUXW^ZgT6CfHKXY=l! zPnZldG?_MtDGF$A$7SX$Q=VT@oQdnDaGk_qO}*M#h8*`oPM54g-Wvas;7SM8rqdzg z`NdG5(4vb$*~l-C;uYDVqv`X9&_ndWZGwu;~3+>d%A;K7hL*HrO~hCgLEH8UoHYOSUz z7yG$`Ul)y94}?^Mu5a2gjf>>u5~nt8n@?Zt5dWO+wJfnV9F-U%KsZr!6>*L->7T!c z)aDiS07j2=THilJiIYe{U7qqMaqQe}B&sjuNK6Rdm5$^r@3!^gAw+!OG`d{ds;W}K zMsv=nle7ecgxWEkZw%@p8gdq@7or|J^lL&G)kMuTj&(G9>A#%I%nQxm5~$*-+<0L2 ziZ>L!0mJn8C#ye%gn9Hy82Wn>@!qYQx_sisV(}(Be7xHBCvEG8ZIe{&ZzyR@i{&UI z{_O~Rz|-E!JFDA`->KLDH^78HXR1fpntVNnVafb3Jw*wJ@T(U*Qo&+oJ10`m2_Kk@ zacHh3jVDeGXS~mal?^ETsd;oW#@+#_n*EMe%r66ezq!|&R#?Z zvmh~CwqFOvUi|}##m|~mjEs`R?+$orRp#>zVavauvj!Ob&3eJNT~qcS$jI!+r8DPx z^*Mgg&wzZQr|k!ZQ8fxoKN1&}4uvl!XBUlF7F-S@0|Y9@0_cHx+(bfU*?9t)&AWr9 zi&LUv5cdwe2??ZS3Y!yFg^0JNn*8Vb;5vB+L3oW9ammo`w!`S`7*h1$$6+RzZK-)V z$ewAUfBKL;XtKiVVx9UOd9#FRB{;od&x8G^HYoW}ZNjj1Sfk7u$fDuJU*^#C@i6p= zHd`GAnu@gEFv@Z-74|yJHC;UWq1i=32^Pa0M(2g1t$3%33_le+C-;E|RvVX6QZ>RZ|W-s$(HSoxe) zY?M`606@a9Vg7QjWUQ-T+l&ajnDy2L+>@EwsGT{U+0DjU>w-?U@w7{C6ui5(V$;!Ec9WiZm+^+U5pzaCbhroEYh6ny{5 zJgPj;qKanWI#5usD6^oM*sv%-O!yU>N9xyx1JAQ>#sj=Yd?h+35FefMRU*L=TbRQa ze1g0yLp!U0?FvRG&T5yUWU!^-tUu|weq4RjVv9r3c>hJm9HY~m5u-A1xpC9p+&a5( zt@6PMY^WTxdD_2y$1!oM*u{V1cV%femuCfGRMbWhdboHXU3{i1K+onQQ|ZaMezN13$la}^$l(0wkLCL4;d&N=XPHAQ(^_X=T8S)S9rn#c z8EvR`HFwDNw3VLHn!8%_iqvop-$2 zhIr=vF!tIXQ?{8slHvH^T5-KAD+T48nqa%xVgYTGnT#IYF11ixy7&8hbyq(uHf<#! zy>ierw8s)jDIWj$i~Ld~g&OH#fhFO>$_3WUK2%qokF5s|KAl4V9D}x}IzgWsFBXL^ z?&$B;N>7Z?j+sSR_R!j#&Ad8?e6oYy3l9CHh8CYGx|F^2Jyy$Hd@Eda zMJ`@r0k*zHaw5_J4y!?XsKJRwvs-xys-*#>B;{q~_1=eu#!c$0=-txWu9qn0;~z3h zSJ{)H^q1Z#l_iccF6bCIrP)uOb5x6M2>j+G$baHQ`Irh>YX~``&UG(HsT3--o=Reu z(qyDRyf;!*Q;+vGur)R&j%AnR(oQx;ygu}n&j=}9(7dBQ4ns$uH%p+R$rs%s$zN7c z`6EfvE;Gg5k{)}B2_D^@P*Fd;w%AwOi}b&(?}FScXMGXL3U#0xUH1X1c5{oBmZ2^5 z76SYFMP1Txz{+vy+eQm^FpHJ6uN;;U&^kAEu01LwcbJYo@=ty0Kf7pRLnOlp5Eaaq z1`bh&mrHK~BlJ}J#{DRk;dFK*`_}g8jn0P(PK$p?jbI|qS#P8&D;xQxU?Ox!d*@qkZkT6jNKb1`1hyt7BHbNjf)*aF;JRYWB{m(0N+4 znLO0wptezD@C zu-EsnmoIQl1$7zG`EWIWwx4v#~{{lA*owb*K zm4K!kjzOsXw6b9Ig+ZYCX`$%1BE8U-zG1hOs~$4|#CgsmE%0-2ta3Enl%Kx%0oOPT zLXb`}VPbHS7vOnvn7h2XvkV>83sYwz%&vYP_igXl!lGOHs~vUeMT0Q(`MD~@XT^Zi zHFm%V#_hXG#1FVA=4#?3{YaE4ssN>$;M^qHp+|)M{!rbF zOC3065Z@SO*|JX z!<3mb+SWq+()fO5jt{^JE%jjT%p9`UU9B!Csgy->TL0}$#pZn1Or=~2KtcS3rp}IT zipNU%E-q@7Q1^`K65$C-hfqy=Ll+6~&)qaN`3oR=XL?H|-XZW}dxw+6*@5#RIC_G? z3tU;~I{3HK*nh44y_ch-p=i!C7Q5fSHGKUSEe81g3`oRmJDhEemsZpC&%X?R8&Jo> z{4fskdB&lw_p2HOQlZg;qy_N@T+mz$crX31A9gZ>O{V0x@v-n6IlMT^{wTeqHI#Yo zrRoOAWienr)y%bS71zdU{TeD+MPvAqXSG4Aa`Q4$eX3NU2d5MLY=|njt&q9z8f9Wq zAxFQ!E?A>7R<74etIriY5>==-Cpom<5|UQ2pM|ZyR7%JBj5GDNw#LhYKXC8|)mcGj zR4w0GgloHT*Uguubd$2OLnE(BS{F6i5$%dAhgDy7g5JdNIW<-g&@l>5J3Yo8k1DrF zbsWkRU^tEciJ7qO!Cdrq>qw81jt=;-89umhD;^|m}qNPvgOr$9{gE#EC)lvBm_ z!+`OX>0^>$8xDV^c^aUi;^DSjllU1 z>c2O~yWr~g9s9KMU2ob|5W$^`rfH5ta`BU8oC%Y+ENyWp%K;j3SINlns~so^s&%(n z=O~Us`ooEr^&MD9hinVCRAoX?@XZPSQ+Sga-U5s)F?)0ZlFtKh%|df)4|J3pBeqYCH1QI`sI zuy>_A@gC@vmDM!AvP}aZbEjr=w{RCaHX|iA#c`G+0DYs-V5sbRlzqkytd&e0ZqQjU zja9UK@-e{7bw~^mcSNXbvyUitzZ0kk+=7L;2Pu!V3Mpm|wmMsbxl;g*FYgqU=N;As zjmasY9}Y(7V8mSeWqOnfI&ChA=w%m{eKbWmSxYO#>?+)P`B^Dn$-a;I=?aDxxM}MR3>{ z)QoSD?uz?Bnp(vtiLj758~Mt#u%=FjOjYR|StcLOMpB+0FE@gI-{cGvo3(!mPh*<- z4rBc@rF~d}dV^X734M)Dww)VlVAsNZ!kgoA0Lic5zh2ZQ)S4f}ck*+oE?gEEGxIr@ zVM`NdoZJ)US^?{AO%(2zzG#*9lW%m0-#Og2>y(LeSctFvk!e^+IAF7j0NfsdJ8~N8 zc326dZNj;W+tLK~CA{qJK-1VNpYQ28%q4lNtTyRO)V;roeFRnmr5hd&kS$q_(=)Tv zgWu3dSAb*)Hto*Cn>~k)G52P>A@9E8!$_R0qv1jh;aMlvn=#WCweab9x~9_Ctkb7Z z71$whfCAT$fz~fgHTsjN;offwo+#$lL*e4l2(pnqB8Nrz=0Uy<$LP5xTC&DVOx+FX zWz>JSN=GQftIxd8(MZ3ZT{QZF%zo}5fDd9up?hFlB(WUOYVAv5v&<@h)7|*zNFj6J z*E2DDGFReA;!B8K?RnQ2R?e_XAs_;cA369vu5i_I>4cn%gt5?xP`vWo35kAyi5-v|K@zQ{(J5NAIp#mb}l9f?KJEP=Se6?=CaF5m$*6O$DI90sVm4ZbVSHB~L}!m2gDBwqOXtVlUk z|L!&48tgn`2+jRr;jR9e-h7IzjzD$q9( z=+!af`X0sEYMVq{@gRBlwg?_z1ehQy-V|E*+7^^CA)2~3^sF9bQ4>M{%5-gPdnI3X zFc$p2GfcKlj!`|l0=S-$`0wH7DiIW^j6vD;?k*}Qja;uj510ShPo#iP=}MUGv_b8* zKAPN3jn0s1k_*7Qzenb0pSq45J`9lF8X7I^5p#wGWb2id1^tp#`DZUduSU)bY*Z3p ztE}CjL&QG?!S&!e{4^ud()70vU4*h{;XM zS-Sk>JNqMQywWCJR9-$j2hbnYc}2=jw+=rz>sxIXb*IXIu+gslP&50gj=Xckh+uVw zRKy>N1~LKkckKzzEAem@ac*L9(`=4qDGh7 zBHWh4X-mB;cfWx5=vo!!qq`7iKVhjmzIv_Y&a#V`1d0;ZKN!^M3~l{3+h1`jm=TG& zLjZ>6KM!U#$ReP<=ARZk);!XJ!@Q23d5Qmus@31cDSE|rjISpx>%;FwN~eiDbWjf( zJjq5>1?fAdmgO?F6p=iuds$iMP|FbLB(Ez?E0@Y~-qtI9q+!)J<-eG9{RQIhh|brh zgIUvRIN#CRpBg{|GBET9E$>b1A09=zuOCP0yxuTD#p^AIFxHqJi{5-_6?3XO2NE`I z?vA>94{=u~Uv+Fh&!F7jQXButx;nFDbW~Y0jU1j`Fwc&A94zkDVIOn&6p_geuu;GI zmbzC?<#&%xx9-~`msyAbm4k_skiOMe`^a;=! zcgxR~#D(>J>xjPdCJ^9n%_7g7xn*6VH z;rDSI*MSMwN<8#bB`ocWm}SeP#3dSf9<@h$sw6JPtfIsuQ-#dUi9*sFT|CB2{cB^(nxmL%hhjHmnGKrd?ZF&Cwb2ymB{$eUiaBJY z_KJ0TxPXd(Bl(XXkzO4$5h8!YEe}6cBP6r}janus>U1mCeJ30#5V$8Q_V!ZcUVa?y zhGuo~Ll*7Dpqd~l5JTbdxsH?K%$l%8mOgrkKv(LlO=7KCKcWXxw8(-v~ zF}cWZV~hEdq{1T9CC;gPTSEId?3DQBX17K6w=B2K@xs2-@xqm3VM9jkp~U<(Ce%Z` zE?(?;GRvI&ajp62krVg3iP=B97Ne*on`XFS^TE9hvYT?TBU1CdQP)6M-u#n@w}kfp%w-7u&DOaVIo+{k)oD3PD<>ir;dVnN+^D~QBG z=8r2rDU$=4fK})}#wtFwS5w%&lM3eXBsj;T7vIPfc(fIN%<%K?zSnD$Jemn|6yAdc z^XTjAb`e*#2b}(`oA#~F=DZ1glI{CW+;6!>pFXDG^qQQsLy>Gz9*Mrw&3*A;4G<0p ztym)j)Oi7_#kprI#mo-ID4LbQKD|amL0eXW$KRHNziV9nOlH5dC26gk9Ok6Ay>M{Z z*-SC5KjzobBnAHh&zV&@x;G9`Q2+2NCtRQb@ufK>(Y=W|&DV?Z*N#5>;MC`&f)^0l zwF`dr1VTUMS84|hxrt(Dc$Qt3&z5My>roM%&Khz;dx{`}k#%uTu5@hgvWr2CeB^=L zjGD2E%P+Z#YOl%5WT~HmWD{?lTc6>gz!JS>73wI51@Q}1j#-D&w?8DZK&yNAZY_W7 zz%qX)DqzEhg>*qr38t$R2N_}5QU3^=2}SSlOcSxW#G|du9cUlZXHO9J6L7!d9FVCr zAGl7Fwy}xXOD=KFs&&>ePx~d;)*QF8(zFUhcuZU(v9NnZ3s%at7t8ddf*A%YoBj%$)q`*>!!xcR-5fogK{;Y#JY=RXBrC$F(apQ>wTls;bC~ZJ78@Tum{Ep~Ej^ zUqBbRV*OM8pS_(0k}`ORd}MUPYnO9d>f!MKtNr$`Hn+foFwTNSx$n5)OXQ`MkBfmQ z^V#q97(U*lB#mv(LEi-N&cnLrxvSjZN%919-vzU z5WO6HI8@3VBOz$ObvHp;#HQ@D5C-EvD{9zJb-gTE-6IeY!#874KlVr!FILmf7u+jHUxE4@iJ2kA z?=oM}z8icM*R#z1Rp{CL&H?`&2+Q*s)00nx)*`>}SVRnp&3U-@k+(^aJ;i=JJFo`F zoN0Om9D71gx~*_y>n~13Scw19E|t-!&{!d3c9P-xEjtjH&9(Q_%6ZI!xRGF%XMIt` zQv-mUEwRW#3k86r{ro-um?Zj*s<0-rYt7id%9!4yZ#|1J4YJEMO>5>b?%5%8_P1;U z(T~1DAl{$QyaSwLUD$@LEQR*&gR_W%dK6)4m-{1?0r&rWSkdVAN_;NLvmLrCXgUFc zwxdiutP4KUFOW|B4^csC`&=s6Q=b|v)Mgj`)l-h5vfGtsCYtb3YlUuuiq{zjgz#aW zW{`V8`XvwtOMm|?0DN&{LTTW0{!LEcodbo-Zdx!-Jq3MTq#kjys-GBti&=wx1E78Y z=UEo|ll)A|%*XxS+mDs>XU9fY}9?e3(|8b-Kvq`pryyr5Wepb?)(bf5xsG&ues_m^GtkFbKh}{G=!)VeR zEE}Z@-4;;k_B#K$*aq7c`c0xMTcz#2kWes-QRdQCH5hcx zHUkUP*~$1tj4HPJ$cB}-#cUukhW7czkY z_!Pp7=we0cW$7o`c8DL>0bG$Z^EM5#=}OmzI-a{q(c=YvLm#|2yH!NSfa7JJCa)=lfG+&Ke6Z@y6jVGkG zPwtgWah>;VmjXqpUse3-E*3y zj-7o6JFL9?H>J}1&diO0oXDNZ4i2z8_Eokyq()Zm$VuxniktVyk<1ehyB06m6YKbW z@J+&7oMx|GyLGX_ILf0JtI5*z(`$h*2@zOWj70~U6F{spZG1#rp$c9qn=Yi*fS#_JMw22=} zzzfiBrzV$0%!;fM;L-*CPQ?CRTu9?6D4}a_;mnLVP`h){wg8%LkI#3Lq(XVne9X;Zx z-HH>OVQ9$>F^W_Js@*$oS-o`&jsW=zz*>!hA)-=bx5RkEhyykMbC()&l%|yk3TecH zB;RCy4e-Cg3|fu1=F>ha+=Zi;8!#;^;~q0mOZ+LHa1Y43h&&=(qds5}XRak3Ad4h9 zlbY%XyBx{;k(xZw+@CL6h`g`5@j4BLj3LT6Erf?=MG@p z`iEgan`RdY?-=KxIm&PPRLDQk5D!UqAK^<0Tp}7*38j%f&DvvrT?*vP;VIoeWiY%W ze?a(RhuhSWbHF8dPAtPd%#(nRsiOkiV|w1viVuz>j%Zi~3AFT}>9oKfY#Gc4n>Cg7 z77B_ldzsn!_HIvBr~5ll{?x=Mj+&0}%E!d74zN*d)m#$yQC+GG-L4Aicm+>u$63dV zDG$2I12FQ(VtHiGvX~mY3qRy73juCIUtI)YshY7Nt4 z78PD~^Gjli#YXkc$%q)d&nYKJ^$w0CcV@PLmD(D@=_2%>l3exEazHX!6t18*#cS}H zx9N3@oY6Tz(g9Ty=Yh2H!2y6z=z4H^10EffTY~9Y?vCbCObY3k;FIr)^MQGcd`kQV#a$4W*Nmx|k--chb3U;s`3pZdDwx=}q74#+`JP<}$h4G**XPuOP> zdwXN!ydxq|)xJA%*_3+V^1Wl`#7RXexVr~x{|5{uqE&1hpyoFCCeku;AMJ)NP$1qd zd>7sRgUNYYO*o2B+F7rjxC4nmw}?0P>x6-a4TAe-Hj$l|vQojW?F+rhbLQZXuQ)7| zXk>VFS4aczC_LZ)7J;ex;;bWv;Jm`&h(N+AzKD|GE}LtRP*+dq{={bDJH_1<=?;M- z_a`8A%GTGd6J$zB$?EhKQMsN*SS-V1GWy>4kwtp#`dpH`95WM2F#}gb2!ERAi7Nhy zvE?GJs!ucVT-yvC3F4~BS%~XywidEYJ+_E;47g}OZ2b~ib(fD^7)xRoXm=sBF8RU! zAkmz0hE{ETCkwTu6jO={dq-@)?v8&?8Uk+6PIPTsUP6sXSz^2zCNxZSx6r3rO`yjSN)19^PRdV6!+M86-vo7@!n?wqbH1Ja^BX+TyogPZw34Y#EBC}ISs z26b>&;b+{7411JGoEWbmqe00{VubxiTOC7(j%K9>2vdpt)pF3HOf;XLY%xB=hK}9p ziciHRh}r=lvm%MH&-JAI^&_JGUDg!)*d#am#&1C^gOl0LoH{%U943PLX7s$w-)%(e z13yPJMFn`y`kRW$j4X*Lbug7Lyfu?iP+a$jRb;KV?~bjB75OB!+_-2S zzb8CS4&vPNK$R|up}0ZH&1O+Rc0wArqUAnb*u612L8_UAJ z<5)jXj55lKGZdIP;@j4Wh79Lb=Kc`1pK~z>o{Nj|OVq_?nO(ibZvNKajCfJe=o8*h zdpsgJ>aw`aVf04Gn3bZ|U~=Aa^PAD1r5SKQvdU%$Bi_g~gUfr2DzHUkO z@L!bwDt1D#c6@g~;CF`uBsj6_n-p89;cqmcO0Vym&Bug4@qd) z9u89ap9SwByZm1VZAbc}qq6s0ob{Q9X#%=E7uRtPB^q*qq#8$3mX^nZ1WkSk45>{B zZD(xZAUYUev$9J$M-Hb~1WB-iFXBPl&rIYlCz4)>%2@$2sDgsx7${M_mcqa~*SguK>@0GZ{ng&33$Z3_;nf`KLSr&=?YMA2B^B z`J~}^I7lP@Ap&@PQCr~TaBSuFt z1nXV|^2~Tn|6y;@gf`xM1cSvR1X|w!NNhxp0uS0gcD2=bP2&d*P97U0Kg!ir&h=vsA_s{J=0mICB;vz`6hkO!&<~jKY4eZUwOTselb%ib!(;_q}`Q-F>DRW zI*kW$9^_(qx89;wk%#^#rv+`(ts@y4SK?q{`o69`NG1!r@n4E4j_6b@$N#nVF&_53 z>T+4pPVag|8DL-K@cLMF==Mfd>?ku&(nruV>e-!&>F~_vIht$z_bgC4 zf*`21y>kRBolnF-d_a!gsAllNt-0JMlU3@iQu7VcVAy5dh;>>o1OI{c-nax`?3eM>29EfM4^z;kQvFLa8^@9W# zx)W+W*I;CKLh6ZJb`+_G_gNk|KmRMz{kPP)*o5{dB1E)x3@mAN>ox)ITq+{qAQzAh z&I_6~c{REyUjSy{ssc%u0$}MjQg{1jE*hY#B_O;GKm5fi{=>WV9dxVUAXI^gWx6V| z6VK@My5ei!W3bg&7?oQ0)f5lznb$)mgl5jBQ# z{h?NgOkpFh@Rjo$_MpmjcXL0d3XIXFiKjfph3->v!H3~X3F7=Mb#BD~W;+&{gG zUbQ%{)3;gY__2}{ShYf!W~ol(t1#o!$x-%_K)>^IL#-A1Wz5g#hMkq9N>$nGH&3O4 zpB;Xtep^?$U?)P4nrreX8a|ve?t;!4siyH&Pj8(J$W|uIH8YWC>Feq3ZQd>BHwe;e z%+~{h5*iAURpWL}=~kVc#Os}%KzLpb>z=r$x4&L!nymTmKMcmfZJo+#25+pEZJak` zd%KopWs2+aGFBvXIb@1!@xtjVPi^4i&=D{TuK&C+ugt#hyq8gNCE&7-?m7t!jJsv* z))x(|hBKqqma_NADyJG7FdfLm;5K)leFbt^1aI6RzWO_?T(0yRfT};E_%FElxv(l^ z9k~a4BT{2jC3iR4=TYu*=bYdd^-7%ED8~$aEgsBc*v2B05wn`85lB zi)|Jcbl2>n>*$+Cv!r3`p>Ho>{ywo|Tc4ww+IL>85nc(|ftWSB+#PaP?#veno>@0Z z?0;M#)(A?7;pbVTbzo@Jl<*vxP`4hL5Nz(9T)9vDrsV&y^)_g`Of{?wusP%0di>jS z5$Rbx&hf6c9n?$ha-+7eGC2I!3ry^sZTHW5#1>o4anyygtQRm~-=Ivh-v%?9iv6nk zhlIwwDh|#%QZe2bN}gNLUvE1tmdH1B$SzWq2i6Nd@M*BSE2p8|QjqzMTiGUlGK226U=8svzTEdSJC$gH|(nfQO~y=Pd{ z&DK6@$A+jhk*1;|O{7apL_}1Oh)4@13M$PI=}3TxDAFS$MWqSSdkH}x1f?mxw*V1B z4JDM2Kths#@X_aepS}P4!})g3b@mr8FOiw~tv2`EYu1`o--?XtC*tzsD9CI1SJ~xx z3Aws#QgURSKo*hr`Sx)18RNpyI> z(@{oiqJCGnqZ0`9jI9fj+To+x%doa`sx zQ=~s7(*M2?y4KMD=~I^TqNIe;ZG^--r;YQ7Mo_DAftqLg138Za>G1TmlmiOY#!;Ek_#-+9c5#3A-+}N3( zRdmehqoS%#X1Qv5V>5TAewCMSQLzs)tE}uQRLv`EedThKsbFd4JE{JQ6pWk55#M7c z69%r&80S`-pd`Kgk^=`_eMs|lwKz{JM209J)t=YgQwO*1?f9^Enpn;b`^54e z8viiul=5BT%Cm(~2_uVwJoik`VX8vrgU63O3x=m@5j&kq(@VPVitm5Ac9v;e1hXTjCO4+6exgTD=>$J#x7 zTz_=s|tcNQ+%4RD`*<0>sm?9JC* zM1IY?bqjmP-29ctjkBolZKeeZ_gyrx#3sV*L8}4zF9Yrl_D`+FO`B0pYAAeVnv_?B zlln}>=UY;Mkz9~xT()tpiSwYy$ivvFAwQgPHa$CJH~D9Y zzSzH)_k`>*U}s&sTvi3x6x#BmW9%tiGq}taXZ|WF^37$ktH_99vNcb&H^ziN%#ydB zOrgKu^L#v7xgwE!IaRp-pf4d(9z%VPx{GdpX=I?P)ApeO{TXKGm%*j6SoFc}yu@YE z|I5Tm`;U?bcGN#%D>WtR0Q+*U+qeFuTRk6yL#kf7eA_4~kymA1QbTg6jxGtcwam=} zrKI$3e^fU1^z^jU^M~PPCQauSly%XvFpGalh;G;9$Y$=)V#TdhyY=or^>me8!fWd0 zEX5_-6`C(FOwnO~m7_^6+I$hDns>+`_wM8Cqe((p=oiHg{$XOje`_`>nC$E*R+X%j%s(VZ3 z7NMx0W(j9;6G@hZ5U&4Yo}d8E&IE&*+pH%!D7PAXW>FTf2rca#f$yr zP+V`m1=?0QX`#5p>5>-K?TWbCg7_rRB#sxS^^Z)-HW&ic9(a|o6x^XYBSaGO|Eo^z zYJiecf5qrG^%ykgVqeM&e~y`JuNW`4I2XG=Yy5+9-!79A+QqI-9Io`p#ie4M1`5QR zv|P5!jcVic@2^d_xq``F#NL}SV8!aC`zI|sNtU7p$qdn@n*$Wt?t6EW3bc*a-TEF5 zZD7CL=E@zF&~?8)U+4JNAbD$Dtj**f7pmBz*jPPy&)C?3PFXBjiXMF)T*PXD%RHTA z7jIwQoA3soUDVdrW?bdD_%7PYU@kl`W zuMz+8M?jFw&%@0Y*471Vjn1ug0KK%uW-vX&tnX1`xAfBD0)qVZNeJ)S?`yuN8vDZ_ zmyvP%V`WTfW|B`1xctdn4G08+z2Vuz;9M=cbK&32@$%4~gd%Ke>Nnx|fdiX~4l@d} z_tb_W;|SZfa5C*VRb}V^SwTTz^eNk4S`wYJPGbrBo%j=l%FW^bC}+dZF~9!l1+e|e z5hk?`4J6d0*RFHczl?$tRQs&Ec@x`Hf;~<7Au4sfQ&j33{NEPzHx@q`wL=Rbre@B= z`)@}6M?L{&J6|x(j*b0aqQP%F>O9X~Y-yCxo%`YX2l?;rjB zJ4dCi{Qu5W0`>`#S?h%e=(X_wZ2v!7&MYs&5LH^jl3IvBHDR88|H)HQJ{@9jj;n{C z$BxT{>MwoXDP&uU#OiT!=KjWs|2Xfuf#_<0x zW6+hkV{CZ((PK$M7P|g_H5oFv&PF&q9qi5Mcu|i0;*eEpw>*89O<`+>s$nRbuo?^SU?qY{TYZ~5Gt8Zsp3m^csHH4R?p4?mIDAL3k$bmYqW14_lCuRNO* zS!7n<gshL9 z1hZMmm^k6?aq{_QXP+`iTuYfxmyMqzwY@zTSF30I2BiJ|%|6y|+!>H^rC|(2rda3< z8^@kXZ~1PB1nhSAY~uTBe6I!?VeR7-_O4GSF8s2txZW+V5)sqhA7Rh5J4JWj?Xh^l zOnHOagCIP@V5OFu#KiQ>1&r0)FD#q)JDgNYP2K{EO-X{c-YUl&BXcMbGUthc*mNRr z-1i=-&hq#6Z*R713e0Lep3gNF2&R`ww~)Dv_bzG0q!%6*$mp>UhIS^=x=a_$()dk> z`5#MZv-EVc2!_+ERs98>f`Yg5bPzSDS`E_y^J_;C*mDihO_a@)>+L0;`0Nv+@714kSTcG z>_Owt{P;m0+9@drgJa#K$>fs{Hnc<&OkJ`VE|cmdXFV!BL`GTX*GX|p(?fq`5|=*u zehis;3OHW1{HGI*;t7ze zRBO`2m6}RT%f_KJO8~w;bE^+9-~0mhzL*M#%ZB)8H0P0ux*3$2MiH3vhtaF~;CobP z)~$57rxQzS-ahYUnhjQ<=cIu1G4vxpJjW-EyUr@Swu@umD$JKA9Wg&_94An1=F-BH; z)!-#y&ZX+#EJMI`i95yGdJxO(POm}BLtTfsgJzk2@803zS^GTKE%IMQR`F4zMeej} z>g$+ikJc@irn^ZwQkA~sYsVZOo8X=DgssjwVkpcb^zTWM759S;+?Jvjt@9j4I3LGQ zNTaz70~KHieRyFH71bUz3dh}|TB{E7zVRXrxAwQZaRWWXsqug>X1-D|(IR6CN+npv zba+;$e|JnYlsaoXHEdC0`em> zs7sAjTx}WiGE!Tw_$i+_s`d`GXZK1A+u|R;il{TcOPsd7UGgDEC)XtOnzD;U{uCxW z-;_=d8OEo1H@LVqV8$)w)NzfR(5UIw*kl|4c%pFTss)teC)ba;t( zK-O%i09oeP$5G-(< zlHZML1jh;DQ#v{XwSfA~_&Zur6EgH5e4VBDZt3j zG%j}FNXCd_K23>UF0PoW+{7rRfMihz_f#?87905&Ep!z78|T~hX&XpwElbUpF;8~M zE~mHd<1k-1d}IPMva;jIklGl>U4HsEugJAmh3;v57vcEDz`VG=yOe_ichwMPTPF91 z`t6A4{FAfk(8Tlu{VOU6OLiQ!$Vg2OLrENswHxX=q-8Nh?o6+1KSHfC8CWxXIAd$1 zbY4bjxuo!i$ly~*7joz|;85aPJnZw5^o&oDzvpgSP4`)aR@$32>~btr56b$axeEES z)wJ&N*A7-bDeqVWHg>yYkSmwj=jW4h&d*$u8a)mbuYO(3M>c-+$RB|g5LP6wy7hfq zQi7nCHEXh8DMif5->GZ=;e{rWKUH>lY+LgUdD zs>~;0A1ZhDj7GW-yi4A1nqU6uo&ffZ+8vD{@Aai5Bvf5(Jgpek2WYziQxrYgU2*3=B*3GB8Esi*gvaGGZT^=cI+q37$B|bX2+5@T@xI zz7H7)l)vRYSB~;w9mR<17vnD3ntRzdcMsO$ zu1|D}qCxYs^P;a&C5}V4`4b?gybf1}-pxnQJp?N*lKG2TYV|w}YK#<&n%0Ut+h5bI z%F=7(H#8E*8ddSe!^KQ!zNM&|(NHF5=Q+kznSs=rvv$cDhb}H;_LsvmjYpkezDFGd zViQGuCTg?IFXB+vEqF6h5>6V|AG}#NtOB36|IT@UE!rqHk6(cJy;^#Q(Q?84Q~tIgCqwbqqZC1Z3FYCzI#)b z%oD6E_yac=ak<)b_N{N+@ZxnDn?=;#loXvVaWDNaOt; zM%R5_xH7SCU<~=P%+M{r!Owq2p|7g;>QAxqX_s)1s^s@`sUmC2v> zv$kxrzXX0i)e7wJ8URhm~Nl$Nr?VY}u z6TUT8>3iRl+BO{%MjngQZnn2g<~-uZ2PW1tR6Otpd1d?!KPJf53b2QMl9CGlJnFP_ z(^Vw}<`(M_(^HC)@phj{8`zt+5E5da7L3X3o^*AB+TnLH5Kl{>?Dq*$8{IFI%T|#p zAfC`G@rKH$^zXYxLHB}-_7=V#UIG@~JpY?|OffvTL6x>{DZFk0?KVJ##CHg8{|xZm-28#lib$ zN-#h9`>yOrj)D2D99a-*C{FvnPsUSZrOe}EG1D{g?OsktKQ7)8&|3f^&9hbTcQCrF zwW~j34OckFh%b1H`Sx&Xa=vv8)7J;hn)7qa?u=COad?!)5%H7z)u(gKf8lrN^+4+R z?6HUyaEa@`i%3?Jyb`G>3X{;=Nj(P}r0y_9^Xdr55Kgs~^ z^s~&4ac~~lCvfSkxf2{a-I4nsocu@O_v0-uM9j#0MOx&2lS ziT()Lj0!E}tSR}n590FKwc}*!wr^KQlKgX~6A6ap#g4-&KAzv~ekJr~`UOzeTGmjOFv zQcTN7M0Oi{duFL?&6Ixk3!1VEl$E{rF`k1`J`^7Y8xo883g?Dd^oOUIQ00|I(Vu;h z-Swirm(7_|G3ws3lX3LPUrMPyP9E6vI1L&XYfqn!0HYmVi_&KN8^C?ZA|m@+S#M*P zTdq#Fyc8wV15+9}zJ5Bsi3{Hv4|yW4ZO8e=QnOUqscV9oCm8R`DY$OzcXVlZCht>P zZ)u2%Y-LCBhe*msN8wkMyEknJyw@tHv$NmTSbg(26UjaS-~MR8t`Mqu;*+aeb7jEQ zdeUcE`3*S}()Gsu*yBIP46$RED+}Ofs9XV=d(yZ@u;QU3py6G8qnW*$v$8#neWY0i zC~;aK1oBn>TFr9~Qp_2u{oSIsUvc16k2CwmuHHoKTl(ZU2%TE)ef|Vlyb^YEQ$)vFYu1h4B6_B$ft5?r+(&{jcM)(#V*7!t>E4d|TD&0*#$7C3J8br$H<60i~QxS7^ z>I=DUWWq|+;$Cc4|Iu1;u(-{eX3cw?^c7^--xm0N7hJiZ*NODH@t*$Wq({pDv8Si3 z9}_qj+4zkep06 zA1INY#&U*#B(w$7zCcl&iqr0sy!Jzh3x^CJHhhme0G!3syAH~*Y8T&}AGf`hQ&NNG z3!;rV+J0sHd>W?&@5ee?F&9doV&f_uqWdinnZh(ksv9(Zc@^5vF=Syed3ey}`dT8b z_WIoSIpsTb2e+Ey&OB0E;`SgzOLSrJfeJh~4fxe#-Hr?C#b}=NH@nr*T2|=YF14P5 z2Z}-!-Ftt=yX+W=Xk;|eU!U$09lSTw_lV`PcVhP+%;vr;U3qr6WI4rY69XN|$U3qX z_}VB#Ne|MM$&vf6=UGb4W2zUEp*_*m9X$#%@k)NX0FXRhB7Tsz8+3o#eIs-qRnuxH zKzGtB-#ka9d;#gB0r(ZMziYZp$hL;CgMcG~%e04oEk*5*a-Z7lX{J6g>C%ne_o)0% zp+DyMjG`y0Xtn{JmwBkAMx8tm?51A%>b85wQH_Hn>kDkR9=FcOpohF88SYZO-y#y2 zZ?UZW^-NVy)XJ$qD#%4I(Ngp%yZ8!lfTnqAo&*?KkC0chADo(z1P}{5X{L~VnqNOy zVqTF`uuHaDpZL|aFKHdTG3?_t^A)UHs0hzH^HT|Z<_b}HLtZd^;KLhSt|LhoT(Pwq zCP#m7%V2W3(HUGvlBQ*j0%wC&X1rN>xv&@jxcJWL(AbkthX#59*N&;}n6G0Q&)4DS zG_j9l1x3FK>riLgb&G5oj3n_W^Z8KfF!0hBwY7!zk_UW|4q?on>vwPr_#?uf7PyKw z0kxQLH^_k9;6Sgc_?x${x$=9#c`}F4W^0Wv4~_vpy8`F@zTECL`=qReKnS|!q`4_f zVs`EH`v{10d^%IxTI;PBCEHVO{Y~~~z~WgSNrf&otw1ndyRS%;RJ0MY4Sd+4Ufduh zZ)5Qeh}Y!hLtBu^f_W}K1oxA#L_7I`8rto`54~-gNUaiXX>I9-`J<8P;|g-v^U6|&tzUDv?=z}p3OW7F3w7V~-ns>1g=tKx=d z%8QyJbMIMKT8I{GW~#r5ue!cu-mi=3P(z>cqA^#mZ+eywWauK+=Y~wob9&p6_#TUS zZKQ}Q@4+~;S64kh$HUhfx2BvAc~R36oGabU0t7YGcL!}CcoM#319yoG-PY9a?HhpK z{VMa8^W})$9fZe|#B}X+O7AyfAFVgryVz7#5S?NwH52ASWM8G+oPFAVh1b19Wx#cD zsKyY6DgBy%+T>@KH%T<;8sffDGQXc@?_<`I*4m%T*!JXIW85D(qnaI4wc%mwOBN)@xSrN_Yqs{36PFKp|J3t@1~My0 z>iWnHBQnygKlBT?)P1T**ut2YyI|C(Bbo<$=gAbuE=40_-YH25<{eTsT0)+ccUr8s zr|sq25xYH+jaB@iBOiO&?lVmfnWdKvPioMC&n)!t4C#B_dCEj!7E-OextpnJvEHGA zH~JiR?FF-TNJB1q4@10B6NNEZ?8Ak{y{7*xbnc5i={+~_PShc9lIwHqtX{}k3wBWC zT**o`?~|Rz#+8O)aTrl%+B`q`v9-kaN1}LssTFXpuN?w6$yYxj3h@pLK8AmKlR4#3Z7eG(SbW8P27| zDmzA^PPR$Rb?r+t)V}v5ye~NDg5lGb4@5>-V7LfexsHI8=Gj>IzJM8^Zp7<9-?4Mop8X4+ zyKr6ob2NPtV6)EU2~14U^Rwm`l(POYGLSL~pZLa2ov~DVt-H zL9H*HqrG>D1_*I;%>fo?!R1ho5d@X1drHZpZo$3KlR?}V4+MttTU1u6dE6G2CnmaV z-Q>2_XY9zdTI(;orGod~cttLNEnBubZz4Bl=%TV%jT6z%gYeaHv8q^~j~a__U{Jg% zi_S&R1=S2LH+*0Ao{=NieuE#GJGdD(EDRJ8mXU4XLa>#ij^=j~0uVbdQz{P3ee4~x zrLS_cj&m^;8A;?XIjLEZvx!u8ace`drg&<^TKkPPA|l4M9OC?)i>)BG@a`jznXQQ; z8?=$YfzJMHzv^*1GK?w=1T>Nr@<0#E#o;)Kb<-eE1?MlqeY91D6&M$g*GZ*+7lZb* zX4afV0$PfIl*>Lfea=0Lob^5LU$i=P0^oet*M8#kRFIEB?L5v9>Tsj6%1K*ZB&wz} z{tork_2N4?qG;17&|6ulwXxwfuvd`Gzg9AQ2RCR?4EVjUpNpqESG$`x#%-mH=xNCe z0eQ(W&G8EN)~kt{Bn*;)jOP&#w-Ut51nn#ogr=fxI(#36Gg}Fcvq>_~J<1v@ z2l^Xml=j($h46seb+(hUU2@fcn9*;k>hfRGP)f=fg3Z_M;MaPJP5|83ip{+qVqmyO zo`Wh@-)j7A%Q9`>I%5Uvt{*0y1USt2cbE6C7t0CLC%P0LnjMxY)Wd(l4Gs^F5f|AC zZWUvjF56FXcr-Y``do>kH6fLJT==f$xF6-AtC;+ zKl{t;ZtdN}cwha3seftemo5Fv07p;V$!1?8iZ<;`K9G^{&%u8Uz@AQ$_bAzJ^&m~* z>pSj$Tfz2!x{|(&J%P0r;(Wa8Ul#kXvt-?4-?aE4HQTYr$lzap_ScXx2lvwyp6zA4 zzu){-6`XR0!MybjR3B7*Y&nCrHD{>R2@Eo4%35!1)mCj4I? z*|Y!uLBJ@Id55hiS716kveVeGw9{bRsvqtT-f59F+CO=mh&sgWx!8ABkZcF3lU8-t>Iu?$qpTi6Aaf5&9w;vT3Qm z_P4eM0XtR4D5{t~;}^_UF?L|vGoQH?#ji#vL<}Blfei9!@6$P~KV#m2Rau+WpYd$K zMhG7h$GBZ#vmk*J3=$6oD`3=e{P%cc1-lXx6IUj}WE(|+TaAya%oL^IHmuc#j1zJx zGDiffB>=I*uSo!R{RJ$GDQADjG1%vC%XwmaB@%6%gzjTkU{8;4+m6yZe*6yWO-!Ws z!@i6YBV`24hM);U+w z;X^dn7?Goj^vYwUH#dK!K1^2EZa!#ZOO9S|_*#UAMoh6` z3uVb;nH?FM*!}Ad^xt8&y&fhsP9@6uF1K@SR;d`jWX$8vu-{j>1W=Oj`}kAqkMS2Z z?dQ=#SXfwSFvvYFeT9wnF-;`VIE~d@^5$I#bEl5p(<__z=3DXRlqFWa_UncW_stn} zvhQg%m1+?PVEp-@S3N-Pacg{u9kvL8++1JQ`pdTh5-*%;!iB_F-Dhh`{~_C9&9pc3 z(gg`2abh3FCbQHS5p`h1i~cbImj$h3Dh7hxMI2*)^s;}UeV2~nFHdA?>e zcrzNj4p9BTosct|e`GbNy{9se$-clWSyRc>blH6QV5LD6?Y!9ol^hP=eYZE+hnktf zicrcWfIw*`_p=o8#_N~w-jM39>BaTTwA0R?2!ESu!#OhtvRYqN40!K1-fAd zK>f0M$=a<=$z}G_>!p>~y&T($4G`vkLs+aBwJ83a0yMJvrB}clEke%Gtgb#B-4J56 z0_)5uuULMUvC$^>x=|&r5Sb1Xs2Dnt>!fl`gDjwh*jIS>_g-6zvrYlbVx1XXD|XyL zjmZT!v{)Gc^tcRAm+>yujrF`Y7dsULsaMH}3}XcKy%@2{W2N?dKmA(hIJ+={kAhu9 z?9Rb`?Vni+10gnEY@o|Rve%p=Unz(iql?k^+X`!Fj;%?W>L&SMV`smG!Q$el)yjNZqzkfD1=tZE^bwkcNQ8j6Z}r0M-YXSt=;)bIKE1~x z=(fs4^UfMab4&jQnU&^Bzlj7{KZ*9s-67xF*#%>N={Uu7Tf>#e26UpWFFg?>GP^aW38gW6Q2vxFftdDhj}uEHLFJ!N(;*xH}PO$=kG2)mQbc1D#XBV16dJ%kEQaQXgx!)%SY66sZ)HY37jyKbWJ z+(@7DH;RuA#v)agdqWW47s$NFHAXqP~_~m&BUrSuVM@ECT3#3#w zJ@Rr(tc;Y`LQ&n3utEf5erjITZMvRaR{^O3OuaK|t_;}il$hNd;=jHB)LP53gDb{= z8@KWsPX{`9^_R| z09x>tA{|1FB2Nm^7fL(Y1q#_V=6PvrWM@FXnHt>2(vrOP-p5>{dU@o#!y|qyVZa&= z^_@}2OQ8KawK!sISCIk=8NOJbb)su4GY;ba#h2BE^jDm2PpoqDC$%Wie#Pjjs^>y5 zs@e-SG9a8|BLk-k_%7hlhBumYPKPiZEE*Orpqgbl4`j~v#Uq-W~YvvOX();}BMKW*Ix}Kskl;}#yz=7! zy)lRq?8hY}n08X_DyqPo7gVt2P)!Ce)*MVbq9GmW+Y#kb8%$GD@jpWP6VH?aXeq1? zi01hMz=Nl)@XJbO-D%&KomTv*xjR=v>NpxV6wh|Zsyqp`>-T6xBgVRnj7-wsU`x%U zHIqGNYrUt_AsI!88$1u}ZRsT!TKw&?eNm`JqH*Ch$McOfws+O#lvv;a4St{*^IClX zN8`_Rr?k1})F;LH!WHLEst&(>gjn7Oc&2tv~O=3;aCSB}P;q6s`4WQV(a z(DBTPY&*nQU&g5T^$4}gks8ypv)EF9c%C^*t=sFW+!J!VOgX3ujT=pp8E$?p%BVRp zz`8XLK-7PjF{uwlkcN}L((40W3yY9cT`kGbgXpGVo^P;VNCUn#flmd%?&PT*A*ob@2?PBkh3D@TDy>gCUU+i_MKc?Gjd`*LGX@=wl2-?|7 zm9e$ffdu)lM*BHdpWfbCF{W(j1{a32f!oUQU%-t@lg_1`RvjF>kN z65`h!u?||_9VSA1q{1Yp&99#$d`wOEGtyWgX2iR9)>bgHc~Z;0+GNKaAqU+vXoa^= z9*>h@8Mgwr`YvxR*R_npiKLwURq=L#CTUFOv3?gwN*2kMXlwcM{7T)8r!`~cUx$%u0EA6naP%C$4 zeVCDnz}YE#<~T&?#$60YLM-Qhc4Hu;9XfCd=q}uIjnDJikTO;p)kcRNRB5UfEC_j@ z>9q)=CBBau-m-9bMBU6A#ld`&)I1!YAxl4LzmC9oOg?2g1-t&fia>2o;MSQ*&etr! z%#UBrU26Q|BmzDzx>3*T$9I!T49%qF*}F>n|17kFfpkTJmaeFK3J+!?K`A!X*J?;J(Us~OthRu?)p{F*OX&^M) z1Y>D|hYji?@k~+nqP{;r5o^stB4laHnW5muWa|NuLk1#3ZiphlMId?TGBGQyx&3UF z~v zDZxz;-H>{5s(Il<+#O3;!tF0n*~R4IS8_Gu%|nfeo8S0r?ul}+us60-tR8Wlt)=?$m5m(t z(os@*<8VY^a}oA(6wa=*QSo6%@Z~4iuT#TI%oQh>E?_nI$dJO>bprv#Eai8gx(pi< zC(X3Uqb>8A7cgylZjJEa5RgwdL(Uz{zJufCyZEhw+`q*APPKR;d&p2Q-3@w>03seB z%t%+rw9`9XPa--XTvXO!omd*)5`+dmjD|mpvizzbQ{YAOP zdi^jZ=KECn*6(8}1+X3Q-$FzL4~cU{c5J0+zM_m~`*pdTwP_C6J;6%qx_&i%7?zepxCdF)LQ~JG^K4FoEIpB7SDqQO zS4UIaINjj`c2Ww#4FsjVicH$zkfY~~=_Oj2j=gnmggclkBj)Pn9!ex;_i37pdRZlS zYAx2!ZZ)(J-b(mIZ_UKYgy^*RixfX_*Jq6^%mM~-EMCR^=28OgvavsFOLk09#Xm*j zvF4i>%wC@nw8NF^C~MD*fdK=@&@Wsb^>OEqgvzF;u)Od}r>-9nIa-)bUlA$AKi?oB zGspeAc|SWu-4LVm$aGYk-peQzu@5U0TD>L&Uns7Up2a({gNc@p%cTy;Q&UUV#;7Tm z#m%TChvf!$P|nf?W)2%OI_M4z$F6H3*75{x=5#WtltvQx>jw`0MvivU$!>8!!y;)v z!%pEZUNFM@s={!Eo|w;5X*C#2G{P^CsZ>0hz*XM|>f_7CXD)e^=T)5Zc#@5JEe53q zl#TX&iv%<&N0cI1i>0Zkb*sV+Wsd^XQMj-}_LF$%LVBu62=?lM*=9(%&Z?&e9GOpDJ;n_tw^HtSF=@8L~d5aB}| zs^|FLiC;3Z{VI&$vlAM{fAg51^BH>kg30akf>~*8XtidV$z5PnX;5*#a7RAATbgjbTHb`#JD=>6(t zpAT50w-6O2gAXs(k-Ik*b@up5mTX3G!lz@|pNGzg9`Tnr4cjZ{4!bXcI| zkPn%pvxu%dg{kR2c%jlk zuCy8st$&ogyZH;J@SV_g>f$4yQiK<_NVyy_%3MD{GnEZXdF+vQD( zYmH4KxUhAv!cr2m6)S^^rdPS6JUpc7W5~1<&xy6R;!Q4^)UKREH1W(7#E&n2L3O7CEET=k7A{f)e$0s?mWS+5w-x#ROJf0EORI!RE3 zyRva=i`g?jfpqpeM-f(43pyfL-f$XTsq)2ZAH#_dD{)Db5K>0d!{P;L@ zFJo~o?A3}DMA|)HHKRjK+yF4Q5kKhb{_H&}4Cy5A|C_bGXDAIZu!jLRq(k+zdAMZX zyI8bJ54kMO^$Av>w(Ud}#lcLn+nX-DvZB+`K;#r_J`E3b*+hHTma!eEP+ee9-{lZD zu?YY*7hretR_AkP2ZM_G-Z{64YETltQRD*7&(T5)QJiGAWO2gIx+ujZ21RW%vNZsc zp7msqg)e5Y9F2ZwiZN!}5wCTPVEcpPqfH~r5&4C{(KvW)_e4YNZ5KacA`2m`e(A^@ zaU9aIz8Z8}PLi{7Kaf0TK(;SswI9SQ2=hrtJU zF$D4e6kVf>@UuWC8?UQ7SQ9b8wF)haHtC5if@XD7Zt^j;Q`3h`1wH&FRyNJvl>5#r zv(U0L`KIKr^D1m>w_)oNJ7XCksM07n7i44`1PjIjU{8d~S)BkqYmWiF6*RIej-Bz> z%-wfHf4~YxI6VuZE~wf02u1m1LsyEKF~QVCen^5`y0dRjzxQ;PXgw7R2aUi9`Bo}F z7OR3bRb;~iqJ3n`3V@q)ZrY_aVLJ04>?R;sDq~~Jixgo&TAabX%ytm!d-V~SHe7TP z_P-^byuR>q182n1fVi#2dakI}@lH{wBm4D{@Ol4{V?8}@H1R&?Bl?pY$7QFXw^(|z zJz+anIIzm6GBV`o92p06iXg2rA}VZpCwapfzBP5MszeuI75|a)0O^eFbXz|d+0nmjHgEOtkqM6}P5+{-UxL)Z*>WMfH0jE(?Pzp9_(CHW6 z)M0Z`R(mkf%3`w}FM0kx3to`$Sx2WAA*_f)zz6#9t-f%V;*K}qcvferjNBRw68S*v zI&|QT=IF-}^+2Zk9Cbm_9pu96n!xRqSD_Z!uJ(Smf8O628Ox@Fhhn&z@=e<#EUKKZ z@NtTtTo(sgh#W$}6HzmiepE5-)eK?0$~pAQA)ls0MAG9Lzc_N_U-^N-k9&!M%=f^= zqiBEoI|=mB$TL`E7+&QRvu99iWx*+1m$f^)%HQ-k#D`Y`@qPvts@*fVg>~C_zJW*@ z;Ym)ubg5>QaPQ+|ybmoU-XEeXt>$V@M`fF^C;xlDb% zq^g^rhg0R~k{tteb6uOt?(eb7!t!!k)*+hL&&Sn}jc@!DQMw`_da@Wr1Hk5FKJ-GY zEJOrC>yDeK=LUth$YOnSQIEHSXYH8SHnkOr`XBaG+zKmqozp3PaJ_s#-9qI_aO?mC z*)yhasb-@q&~|;eJf6yxOK4CDiqWPhDk(wTz9%iA3P+EwblL^EV@DN|&`(zl*^e)Q z6~zE99{K34gpZ=ZL(xaFl1JAn&sk|1YJ9jJ9=tR!KHL)#6$XF?1|7+tABV)Ii{?&L zx*3EGW7@jo_RqbXoh{fqAIMYFk7+k}%%g_SK0Gkq-#AeSQNC4*YDg z2QZVPK0$QQRf+Wm{m!&p*w!Qnpn00ftP7m5rS|$vLHxQ?yirOMxl(F`2=|Umd5ml~ z18mA1rh{h~8w@rhUm@H3Igq0fVPWknaa41@axTkCfSjq!?ket|>(p{xAC!3aA_;AD zi?p#hS6=R+z4b(W7U`{M?q8iNqv6z5QZf53$kV|krN_TD>9S07ja;@{YxirT&SW(* zjNR?J627l~^4Uu5+xK0tLsh7A;Nc#h4?&H=1#k<^4@-NOS5~ce%yC2DAWQ%L3L7pO zpuZqkX8eePGur& zZFw>c8#udY@G|~@rw8d_4}3$%eM4O~UUQ0C2W_!a5@QAI&1Ky)gS%qF=Q$mKq3&hm zcSuKs*jbM>sB6Yv#A-BBh3^7QE;4Kq{8sWGwUPJEy(EOY7>f3*bbxu#5cgXHYL&^v z7fg2vG6UTaS!`7bCi6%M-&8TeXes2TZ+qq=805ywrYqBO*vtv!wPPa5I7KA&5vS*6+D4x$sW zW`4)005?zrUCxXbQW;r`xa?=?rSj3n6)s)n3~tR^&$x*`TOsA)Ggo7i!VG=x9*B3} zJwfOu%~Jr*>;@iY)!r`V0N2UyW<~e4gxEx!A0L7;WM|u+pgI-P*AUKTvw?ukA0SHh zO3*K&#`+gg!|wY1hs6ds%{6*YO!fXq*XVJKA6hTZ&zDio7(3hGc8tugd1qgy%VyZv zIUL;{G~?JL!s9|H!^qB(+(KXnlvStkmsAWir-i$ixib@VJk!LoxS}e~VDx~tA1J+S zq}SZEL6o%wtFNLsg~lN$X%$n$hiqJ^MYJCNdfT|ni2Zr);FNSkr=(U5a zfySl^!`ps7Ch1B|#$n9M{2xO#~+*E zVZ*;L>+dswm70pRR-Pq%pP}b@i5FV|k18OCR$GpocgSv6#CY?pRn{>lzQp6#HLt8l zE^Xy&xtP#Wf5zI1AgMJ}jNyo2jy3Fxrb1uZLIoykNAQCo!c4#rUpl2lh zu0VDdkx~fjOzy8-jlDd+pa-WwSIL`l)acAc^$){@FXA<#_z!M61H8MkQ5GsSh)Vra zOIs85@fP%bDePci95#U#7Z#Z}Wx+=nZG{aHR6rkUEZb#m^_5(9X0!qA_|InYxhn&4 z$Fl=ORD6knEa6@-)yh)H5|{8RM6BWf4;E?SmwJcDPpdB zc0AB&#*DMH1+5cUR-px3DZE@P>0DiRi&p*G*KR^F?cs%BE&Uw9G z_t$e?&+<7wd1mYR+_Ub(gQvg`N7z6Cn~9xh)1|dk1Zq14;%W@KPA*f*eY#x4(Q?@s z*Cw<&Jsh6Ud2+~tSymoCfo!;Q{B+36{^C~S+_UIiU_apZj!u6S=r7JM4p5i{!LT9j zO>5+YT(9wnw;!x`nP^n2dN6d;?E^h-An(JB=~$vFF(3+9&0eT^Z1Y0|BlTe+4@suB zCWvGp;2Rv#c)aDtHCSegb9=i9d}uOli0i;Nx`Pr0^*{ zyqJ2V3q#3@E-kut02}ObDSl_S!+^lUeIV-&SDduE*P?W%<^0vBs)z9yd4yL*-#Y(Jco%9md7Bs%bp!-JEmg&bxys|KK1Ra2d#P zzS-!_lW88m`$&2Lx`S&Y^@F3!3-mMSHQ1TU8d*jkuh zdm2qXM7!-CKIho@90A*iqH=Jl0fBD(`-SRRX5sE(J`*I*&hpH;eGrg$Pd18VEB8FB zH#c>v8}f8-TNd_gOFAa>dLD70+&4%(aGQmv$PWznENe)8a-^&Eb>%K!f4A>ZSVoR> zFn6@@NO2V7gph%^w!Z5wBppii@S_k+E)NSrR#YGfh<$7bvE{+F^Rc^9{o+TpYc=ARhL^9{czZ zIX!oj=4E@W)wQqTPhZdeKN+4A-^ay)!!;UYEz)diBCU}(b*SrPmxgYN6fSA#nYtE{ z3GW?tx<|e%!aA%?6bZ>#LbV~{c*oGt>7d7<3$L`BS0q4X0>Nu1!gmeF@-*J5@jZ8| z1g9bv4-3@g76$<+#WT!nP{@5FnJ7lRSaQYI@W=Q@hxFg!-YqhWG81*ePz%dKcvdP6 z9%8Dk#|Dqy3znPnpWPr*?Fs4|2VFg82YUN%Y!!I7KU6Uc{f*pOTUK_-w|U@#cmIup ziu%f`%GpXPJx0Hgdz0gMK(Ey{ZqFlCX3+2-`G|1ee7CMn9CSn7!RrafHOoSidr?T{ zd*n%t%VKG0kZ2c+CKoczYR&;azd3qbRt9olPR1fY_>E`|0-coRG?O=r$3$^>7fy)} zhGZ2g=Dn?8My#rTj2XONat!DtmMxy)hcdH*-2xHGb{tgDwo&eLn1sWFam_ ze}!~-(C<{0iOZma>)zP_hpt$az!$Obb&ni&xz3PP^Yqg#{W{u4P#hk1r1ui2WHeyy z);*=cuR}{8o?FEGG;`H0tM=UPzZ&6378~K@h{Z;@F3&&ap4ds)+nz=lJEk8f=R1)izDg#?;I2^!^e?iiC9m3Hub^4Yg$ zG5ajR?AbnNo~vV5Rg>MD46xICJj--xzG&4^0EJxRH!wz~aQ8#6g`7LL)$Doj@q7kn zaFEtULwO|1JTx_oBQQ}iyi(gV(9P4CT3OrRndU?$ga@Ik_+vdzFn!V(4CiyQqNT6c zv)NG0A4Cvm-DCE>E3wQMpM->5d=hQoNj}7XnjZ&_3d(-_EsKaTFY#rY@W#RNV#u7C zbvscpM?Fny0yOTSrF#lx6Shb+v(FUS!c@Y6lBrH3)|2mQET(-@*#5br4Rw zx_NT)4}VQm0FVJN2j2g~$8gd!+NUK%QQ*;$-;o- z&-_igH8UKNzT@N_ZHYF1AkM`~`Q}N-ufP8z(s3vaS-0~0;~T7hQ5^`%fsn6RiFVr&IF2G=eqhP8$5zO*?CVO*>cq>!zLUMfaA30Zet@ zZQ5B9#$R@`B#eKO#wE@8D0^Jej3v$Zd#AyN;b_TBmds=+&-iQZy_9qJzBPYK_hS&NpYPWY z(HipQr2+h6=C(9h{Gb!||5zAh>bHvAYs}n%9bb*FZ|mBq&Cc|f(42^(lP&3c1L`j# zK1i+q=Pq|=E+$*8@GYFIi?4NXy%_Nzb(bG*;inbvRv|1BEF4F%WPBpD&4S%>99nYY zWBq^M7^iLDHfiwNCIE3`yRdNbsbd3@q`nzgq#w7qYABOmP47t%fQdre>RC71DFgzc=Tf?JU|?W$GCR><54`_< zKjMD`00fbU0)TO7^OJ7@D36x4aI_(g_QyuMSPNzB+#T#pF{zOto>NVxzh{5O}zoQPLzkGo7H35PCVlokV-BTXbDwd)XpLo`~UO_jx8l z4(8Jpzvw{@FJCU*;gaVFAdPxQ$HT+JS-|5M77}G5VBd~^zH_lh{f2ROAxJJD(G(HE zb+O}IFjYLlAI%0yFU$^p#XTp)5emF4*>_mOObpn}%q$w~_ip|6XXovzw{4Q@@uYSi z;QgHAQsiAwsY5zyB&1k8S4C>r3{%r}D!i^+SpGm+V1MW5M<$%M`!O1oud=IIjjEbT z(yrlQb@oJS933hb8lrhKri&}1WnyMxNt>DO2s@MScTv^yJrmBy*M8v)C|U7;8l87d zf)vhwx2uiD$ij%GaK#+9sl*0YP*tumj-$A{suH1zQf%#t&E1Vc5JkODs`2$QPhh12>CY{m75A`fQx8=N zjIxAB)3Gw)%^3Qtvsg4*e9*=PG~$)5)EQYEJwC-`7G05qIA`H&X5p*|rLZ%lJ^Jry z={}Lkd4Mz`ZO7JA+a^I%hW*q6w<;5N)-|X4C?!i3k~->i7(iN+aH{0I@j7$<7!=r| zpZ)Zy?ucB*r!)?eK@+TZR7D5v?d`)@aWJ)x5^T?tlgPHc^!i29s+uixm2h&Q@l##7 z;4<%bTfRQNK45e^fK&Od;5XL;?eYmQvBJdS=vfC7SJ^BAi!L!fx#{%9S36GnnJliK zIb2p%5ic9vOpHYl*crIzl45#2r)W68PS#IDO-B+Ovt*@r*jy%@28 zWnFBN*MVfuc)T?*!MG6S~8W5H7wnBdK_o(lGnM=9-=7$(ibL%KAQPqrJ{v#Z#VnEAp9R15H zBtm%3)eEq+2mTxE=$_rXkD-H^i#~R7TO>Jb!pL5a^)JrmN5I+qkfV4YQl_Y!6h61; z5{<|fMwOM7KKo~90CV@$xH#7@|5qzT&sF4_Y&y26;M}LMc)*7SwYY#j68zs!bw=-N zYq|5!o_d=(iC-IiyO|nDal?)97`+8?WUP#h972-f8OPm&`p>ZnQ8l^%*O{ZZ_l2c+ z#;9-*Z}_E#OPSIl$TUP5h(EYsArQG*1@+pN8y4N)kzExJO)imvT|4R_>C)<%0|ueT zk7ikhC)rd4%?^}H7MeYU3*$JJG|^Ht*|eXphLx~z=jfSe|Mbx5ytJWcr7vP{b|+uH zht<1dn7l?rx_swhT);Lt4^M}@DvQCZA*SkDz-KL5TyfQxN3%?|%@5@dVsq5)d)Hip(y zgbCCiBiHbOSl8t8jCi5rLHTUi;OJ$Ab+K`~DtG4CWtc7Vkczm-&O_S9J`16H1!Ts! zyKL`_oRx@GtD1S<9Ls&j>+zY}wz>*v^DnwRi)dM`LqaB2E^bn4g^b2(dc3}+gUfaS zRu<_ukv)Y(nmRLfapfKmTm!Pir^AHJums?-!Hdp4)!5f@mOVE&SI!&o^;Hsvw*_Px zd8mImu{j2?Z5nJEOt!|Jb+~PR`2|33r=pz|b`d_AVG)g$MpW*VkUi(=XE6)L0RY>V zot5v*-(+wf+GE7*abS!S+`9*lRO2A9oY(SLW#=#5z;^b1{gz)0YF76a2aP}FeAx{H z+NI)f&l}B2?DzPx^IX(hML^r4UatMjZvWEl3lQLCMuw5T)`yny!JC&pz9hPjDynz7 zv7|OjCiBJM_`mBeB7hue)ykC*h(zduZzfROZ(ZdX{UYgm6^t7WkFO$R>OJOumSfTM zZj{s#2m}|))Dkt}8&d@YJ?$yXL0CCGIT@S2q3mV%&(>I=U%=sTe!;Xtw^S#LtZpCZ z+q#VF`;&Y-Dk!KIvzWRT6(Ef-eVJ0eGssDQF3~mF{;Jps)i59{d=+vp z;fc=j96Y~%&ImnvFJu_mqA|K$_J;&mKy%J-lCzI^r{V%ER&;Kub$!Z$srqPU_V3xo4^S5tep z819f>QknEzYZyn`f3FDopvu6*4N*Tm7ZEJ3)g7Iz$u)*s_HnGS>jZ4_^({soyqSI) zGQls(>gEfeZ}hIldInu3)A}qgj<~w9e7X>als&UFW{e=%flCe!tE3^ZnQG5g3)AK*`{%a) zrX*(LQe!xV?|IceNQQnhxDmtH%YVJs5OMzD4eah<_@y!OxAJ4(iN_web(j)w;$ycu z1xY=QSou2i5&Z(|wG+ehbz)fF)Az8m12`N@0JJvf(FI$U4IX|2EWOXWA^~b)x?2@| z+=KYRb>2xb;>q$|BHDm}95c~Sy+w7OwEGeE0!k;mU`IEXe-igH2yYN^pYa6K9^d>_ z-!Xqn>}F=AgJMsVukT}Qd!l3#j6gEFV*^b7l;jE2 z1>DY@U^sA^z#`;gfQiz0#c$0f4~XDU@u0)*;gRPt?MD@fKwae_lL#Ya=go8m_I+ZP zM-NAE85EK?^zKG`^x@SU21F20PHhsikA`NkWs;CtqawBF!jys~tFq3Gtx zhnTI0LEjdqngve3S_frlNK((*+NwP)>(YZ=b3pU34`_x0Tk(;VrGI|n4=@MenN6@Q0!q>^lN@zu*;23|9abd*(_qIXl zeQ%bg0;_=XjfkO<7T&s_e>CA9(R{8(R#}cX`4Bk_M)ievfY0$w7v^gojKzWAkRu*% zd+_z5Qek06<^~(k9%5PcBfS3gG|-gBz*I|cBTQ`r+uTG_QeM$32=fH0>PD^Pzg^8g z+2@n>P1bT9XzIo)x`wnaCzLL&er!p-Rusb=-e55J6cThd`MHP?+rwBjT4*DpIq`X< z3}2g|pQyiw!I5oO9Y${y#=2sOmX;xO=fGqNVkNxQS32;z$bPMeX%7(*r9fYztp9=c z&nu*;(ZUBcxcT4j~v zx;Y#K&abG$52`8+hlLMSJqHiuLX9)S`??+k92vl80K&qv*SvW9o{;(lIYE=LLa~3gWfh!7*qBpa z(p8Dqa{*=jYEAS`U*WUaMRePs(&EuWC{$9RA%M=$TZQqtkuvLaeF5Z7q|Dr*U2dfh z5Ls;rIB!$=)4>zk72Ynn!k_2KG+asmg9g&Xv=q zFDd+ht;zMJTnac#e2}}wof_S0mRgxBc7pz0t#j>AZXUAbxLEm$z%|l1sGXRHL(|%P3%6E(Z5T*#{=FM>pl$`+r#VSz zWG(-XWmQ7_r#7OsXd|4Oieg{*WM+D~C35T9`mFNOQ&jw;ObHAd;`Q*lrH30S7=#XWXspd_!rWBoT(qht-&g26{;u*zz5YW9E^wY}yv`h&fz4 zP>RU_!v&HST+fBo~~m(^qU3rwBs+|3DInjT1$z12%g&&s!!NACH> z?p0LKs++we2v};UY)~XWpp?xR(8(0$XN;2L{IB+Sv*zy+3+Nr?)6=e+iEUk(8lB=H z&W({FvHZy;hiwL`;nUX?5-qhdJ8@UB-UngGDrbNKbC+F7)ThINyH?v)NwqP){xc_3 zE4_Z-bi1*9YX7Y7AJ6yK6s7T`Lv4b&r{+F2LWE#eWXf+-1RG3)4G$8^NOb$zYq^hT z)l3nWRmg}5O~C^OYCnBVvy-ySpAZ@zHqYz8vn2}Vw1-iHo|GwXg}iJ8f@!4}QVJ!M zJcAYuGbKY%kcUs^dr84iYBJ70*4aHx3Ty$dagpy8Y#QmoGiI} z3t$RZd$X&zY?nW*{6ZXP!u*Fx(D?QmczE*(rX1Q63e1NzavA}ut!+Wm>p6)Nnm|9U z;pa~?uNQ(ffJ*ehvNoDC|NM^LT>{}hE7W$ZKwvY;MIlefU3VuV-rs0*xQKmv4T(z#ct-EUSVfn3~ItgLM})) zIKaS@|{eZc86u*NtH5#DKHOZx#q5y?#56Iq2tH0w0bl{=Fkh6~e&-J>Sz+ z=71#c$FThG4L#UvEmtSB76#M1x|Dml4gJ*F#H#3M;;SrU z#;vr}#JwQu1hG-*FLQt7p-JE+1<`W*-1lsj1aX@DI(2B?;S{Pj>O@yOOv?U=$T z;()>lhcutB{q*C9qZNliA>70@msWHLdY6PiZJ-h>Opk-&D0>%*Ng8QTlO$`jk@_;enK+J8W? zYNFF{%zJ9T0*j4j0P@I%UtB45GeposI*gl+>?I?Ja^W!xwRai$`JRl9#BQSq6ejUbrDNs+>Z4wq+V z`y(~YX(cguQl(8OZ5+B)>bhE!2hOiiE$h4#VtJt`b#SbGQZg6cGh*Bd1=EV#Ps!3-c_5!An~olp#0fH0_MDA9u`>N9MpVP z-rfyfucWUY3*?p1T@~9)*_hZ?)~5A&K_5K$qXU+NB7YfWZ6Azd50EV`&>Km>RZ&oIu#8Lxt~67>c<~Q+GFw)oDs4|**)AB zo{oWtz@u9zDo~pP+B!9>5vKf zC8p7Z=*}Ms9~gb;RZ6n*f@$h7 z!aYIqj{Tl|=mtdoc1&5hjl6r$LHTiU!!2$9K5;yN$xyxN{8_jA@h^)uFOdwT8dax+ zK+4uDIuxDnHl%7GV&z21-VVY=!nc&Zo$+ogE9_|&Y=tzt z{W{^o^OaH?^%~ewb?FVT%RsO6*lFB+f{LUnOOvPW zs5%M3BejN}eZ%d?gFKG|92r$>|0g88kFOgw0hQk@DGDjBa~O08%ZRbvGIKAJZ>eHT zN%0FlhA3J0ZCBPlaaKmpok&6KD#YYfC)mxzvok^bTw2ZiOkp1w!r;|1PDl}}80-ZD z0(|!*af(ud6mg^KUaf@@f{!DrC#E}M=3dQ~|A_O%cPBi>45%_I12~o1W*EW41k>%@ z1@e8_8W|)jCZZ25=ao+qAFkwaNoYbJ46VZ4Nbzmp3q?=tqbU7vszPOQfx^_@Z{+Zh zqZyTtbO6$t9zvNuj8LtEz#n~mkNEp_S?pP*7F$Z~Ep>jJrqYP}wmZkm$bNerjuoPN`ykTmzn}k(fVy^_2PC_u^R`P(LB&*n!Q; zq*)Z;g4{|x_)>miMvkJqt4R#6In+)Kr5}y^q&XSUy9p?$*|NPWq*ZjQu-~7=H)nY{ z#Pl>izfZm^9akrz>ZvnEeNW|`AZ}v}Q@yG|yZV`trKqJ=bqgKVu9`*O&wA*+P2Y^! zQs{gmltbk_oeOT}sxFiz!8*6l)&3ko@kyuXT#~Wk{n|h_voR>9XYIr7p>3zy9T{iB z&V_!%B=`C~E+S_nM^AvXyYLIlO2@WK0YH_OBztht~d0@o~}r89Y?qEN7(+?G_@uu8c*NCWTQ zqpD4Jm%n-nJ=agQn>E`L-Yq@`OXt+c%F(Hw*sXH;pIzo2WR7r@fu;#y{ujtwyakyk z(4JuS=<_UYBaps_UVxAIn>EVm^$Dg(GAE?6cs@a%tK_LJOxZZz;98o-$TMn27V?tXZfqU= znr*nHMEDhMHV0v(XX-;u#;yZk02prYXNZ^Ibb&+gv;;%XLyUKH=$L94KKea4`<&+L zyKGxAr%WL8)|s(~EciO`t%ih?R%6=*s9&3TsZf=9I@u8*h|`w+zAf2*@;7%zx_G=~ zC7MG`1z33$<5OURjv^e*eU?R|Tw1FrhpbPu902KxPavdw;jCMwObbXT+P->B8`s}h z6z+hKVvkTwe^qDtDp6{TuJj-2{B>Kv#6dN|t@|eWj5r742ng$!Z>$oD6~$+;Uc0Tr z*US~m%26kO@d{O$^!Ki*ty7Byx%a7pDzJUm^bOPA#uQdHa!mjh__Ffpn&!2`C6DO8 zFSfO0n6nnUXCk(w?NQNOkChMxM<=R4TecPv30HWW-GAniYSFfFP&eZ~G-kj*rv9dV zmXj{f_fn3-@N);Co9a?1l!Qw#xKN6!SLa)N$A~fG*@)QYlardBxqGgYU)){g*@43r z4)2W3tE%6yW}S**f;O}xVlUaH^{R~Kp3%%s<^|=>mf>^d=Il7{wLsrfWw-LDo??09DIomYgrCQ> zs1(>>N1Pxb>U61H_rySFpCDIVg;kmdH{8(>KCE+$_;w^hz~4dZid6UdMa@!sgt)&R?%EtUK*F?YY^U=CO zoUzU%aY6yWt63HRe{xQkMgR!5Z|lo+KWP!1sZs_`>ZUvZb96A=FFMqoQLG!b@6D?< zYl&^WBjEK!`6^EiqWH-@Y+T+ZyL$loXIb&=wNKLZzQPq3+p+bz6C_TqBC|S6gLk)T zAy@9Zzp4AmG^DU5LCq_gl(g_`)WIGNjnh>vCkC<<LZO5gz#j_2o^Jt%G{Up#gZ1C~R51#hg4^!PzopKAqe?-^O zo4rbv)IFJ;o*p=;uNIDnH>VgNUZdTGN=;OZrsisx-;On2jOfwrw7wc8r2 z5u?k0FakhhJw~dvWyatuSqJ^JmrbP^umrS33c>B?!0GPUvB&CK9{@exRX=A2R}Ym1 zpH!1yamzM35H+jgs&3h|Z|nMpEP^F7u>Fs^q<|);@Zo2c)T~f8e^*@jScX!=*XTVk zn>RV@L~KgH!Z96RO5yiB#30rI�m7mjNhMO7x#TWkutD6m3%Nr-zy3vMrH^WSvZG zScR?hy3}HKR(`#g&)X53bLJAra}nx1{HUVZ4B8qwwfN zj6X1k%i$%VPmog$vz5z2t(Yb?ZQ9Z{b`*+jn-exWjz}J3?2_*p+;5^Kz54s*Pinju zK?ctN8aM&#`ztfY5e zD-F&9obzG(b>ysxw4=hBn0d=@Pe1*%^RT>Z-?l{2O>>WtQ08mF6xR*e3Nac@cvRxa z73su3!|Iy&e!nbjQ|jJx;WK#J6H}ieW7ahCTqaC=|C+A zOvvexA(s+|HkiuCgy$87?Ap>_+F?#)Z2Oi6okW)8x1>M+2kb|VS2xf38rV0iGC?)gQZC$j`5|5MIj-ZK z)kYk%np85h{kK=~m)qsa{C~6OeP7>)*6;Z@YaUs)PwqMd`l6 Date: Wed, 2 Mar 2016 15:07:35 +0100 Subject: [PATCH 0105/1679] More test cases for AVLTree --- AVL Tree/Tests/AVLTreeTests.swift | 48 +++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/AVL Tree/Tests/AVLTreeTests.swift b/AVL Tree/Tests/AVLTreeTests.swift index f079603cf..5fd0b9a2a 100644 --- a/AVL Tree/Tests/AVLTreeTests.swift +++ b/AVL Tree/Tests/AVLTreeTests.swift @@ -7,6 +7,7 @@ // import XCTest +@testable import testAVL class AVLTreeTests: XCTestCase { @@ -68,6 +69,53 @@ class AVLTreeTests: XCTestCase { self.tree?.search(400) } } + + func testMinimumOnPopulatedTree() { + self.tree?.autopopulateWithNodes(500) + let min = self.tree?.root?.minimum() + XCTAssertNotNil(min, "Minimum function not working") + } + + func testMinimumOnSingleTreeNode() { + let treeNode = TreeNode(key: 1, payload: "A") + let min = treeNode.minimum() + + XCTAssertNotNil(min, "Minimum on single node should be returned") + XCTAssertEqual(min?.payload,treeNode.payload) + } + + func testSuccessorOfRoot() { + self.tree?.autopopulateWithNodes(10) + let successor = self.tree?.root?.successor() + XCTAssertNotNil(successor, "Succesor of root, non-empty tree, not found") + } + + func testSuccessorOfMinimum() { + self.tree?.autopopulateWithNodes(10) + + let minimum = self.tree?.root?.minimum() + XCTAssertNotNil(minimum, "Minimum should exist here") + + let successor = minimum!.successor() + XCTAssertNotNil(successor, "Succesor of minimum, non-empty tree, not found") + } + + func testSuccessorSingleNode() { + let singleNode = TreeNode(key: 1, payload: "A") + let successor = singleNode.successor() + XCTAssertNil(successor, "Empty node should not have succesor") + } + + func testDeleteExistentKey() { + self.tree?.delete(1) + XCTAssertNil(self.tree?.search(1), "Key should not exist anymore") + } + + func testDeleteNOTExistentKey() { + self.tree?.delete(1056) + XCTAssertNil(self.tree?.search(1056), "Key should not exist") + } + } extension AVLTree where Key : SignedIntegerType { From 73ca46e31c7aa964edb3e952847310debf712c3c Mon Sep 17 00:00:00 2001 From: barbaramartina Date: Wed, 2 Mar 2016 15:09:36 +0100 Subject: [PATCH 0106/1679] Removing testable from local app --- AVL Tree/Tests/AVLTreeTests.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/AVL Tree/Tests/AVLTreeTests.swift b/AVL Tree/Tests/AVLTreeTests.swift index 5fd0b9a2a..d631c7688 100644 --- a/AVL Tree/Tests/AVLTreeTests.swift +++ b/AVL Tree/Tests/AVLTreeTests.swift @@ -7,7 +7,6 @@ // import XCTest -@testable import testAVL class AVLTreeTests: XCTestCase { From 7868b032f7d89f33a8bf7310dc96698b232b355a Mon Sep 17 00:00:00 2001 From: Matthijs Hollemans Date: Thu, 3 Mar 2016 17:51:19 +0100 Subject: [PATCH 0107/1679] Tons of tiny text tweaks --- AVL Tree/README.markdown | 10 +-- Algorithm Design.markdown | 6 +- Array2D/README.markdown | 12 +++- Binary Search Tree/README.markdown | 46 +++++++------- .../Sources/BinarySearchTree.swift | 2 +- .../Solution 1/BinarySearchTree.swift | 2 +- Binary Search/README.markdown | 22 +++---- Binary Tree/README.markdown | 8 +-- Bit Set/README.markdown | 24 +++---- Bloom Filter/README.markdown | 14 +++-- Boyer-Moore/README.markdown | 8 +-- Breadth-First Search/README.markdown | 8 +-- Combinatorics/README.markdown | 38 +++++------ Count Occurrences/README.markdown | 12 ++-- Deque/README.markdown | 24 +++---- Fixed Size Array/README.markdown | 12 ++-- Fizz Buzz/README.markdown | 41 +++++++----- GCD/README.markdown | 12 ++-- Hash Set/README.markdown | 6 +- Hash Table/README.markdown | 32 +++++----- Heap Sort/README.markdown | 8 +-- Heap/README.markdown | 44 ++++++------- Huffman Coding/Images/BuildTree.gif | Bin 24647 -> 18044 bytes Huffman Coding/Images/BuildTree.psd | Bin 2619878 -> 2611102 bytes Huffman Coding/Images/Compression.graffle | Bin 4299 -> 4300 bytes Huffman Coding/Images/Compression.png | Bin 54972 -> 54850 bytes Huffman Coding/Images/Decompression.graffle | Bin 3944 -> 3946 bytes Huffman Coding/Images/Decompression.png | Bin 47499 -> 47379 bytes Huffman Coding/README.markdown | 20 +++--- Insertion Sort/README.markdown | 26 ++++---- Kth Largest Element/README.markdown | 30 ++++----- .../kthLargest.playground/Contents.swift | 11 ++-- Kth Largest Element/kthLargest.swift | 17 ++--- Linear Search/README.markdown | 20 +++--- Linked List/README.markdown | 22 ++++--- Merge Sort/README.markdown | 28 ++++----- Monty Hall Problem/README.markdown | 4 +- Ordered Array/README.markdown | 6 +- Queue/README.markdown | 8 ++- Quicksort/README.markdown | 14 ++--- README.markdown | 12 ++-- Ring Buffer/README.markdown | 10 +-- Run-Length Encoding/README.markdown | 2 +- Segment Tree/README.markdown | 26 +++++--- Select Minimum Maximum/README.markdown | 59 +++++++++--------- Selection Sampling/README.markdown | 6 +- Selection Sort/README.markdown | 32 +++++----- Shell Sort/README.markdown | 40 ++++++------ Shuffle/README.markdown | 2 +- Shunting Yard/README.markdown | 42 ++++++------- Stack/README.markdown | 4 +- Tree/README.markdown | 10 +-- Tree/Tree.playground/Contents.swift | 5 +- Tree/Tree.swift | 2 +- Two-Sum Problem/README.markdown | 6 +- Union-Find/README.markdown | 6 +- 56 files changed, 454 insertions(+), 407 deletions(-) diff --git a/AVL Tree/README.markdown b/AVL Tree/README.markdown index 9e3a2cdc6..744d9a272 100644 --- a/AVL Tree/README.markdown +++ b/AVL Tree/README.markdown @@ -8,7 +8,7 @@ This is an example of an unbalanced tree: ![Unbalanced tree](Images/Unbalanced.png) -All the children are in the left branch and none are in the right. This is essentially the same as a [linked list](../Linked List/) and as a result, searching takes **O(n)** time instead of the much faster **O(log n)** that you'd expect from a binary search tree. +All the children are in the left branch and none are in the right. This is essentially the same as a [linked list](../Linked List/). As a result, searching takes **O(n)** time instead of the much faster **O(log n)** that you'd expect from a binary search tree. A balanced version of that tree would look like this: @@ -16,7 +16,7 @@ A balanced version of that tree would look like this: One way to make the binary search tree balanced is to insert the nodes in a totally random order. But that doesn't guarantee success, nor is it always practical. -The other solution is to use a *self-balancing* binary tree. This type of data structure adjusts the tree to keep it balanced after you insert or delete nodes. The height of such a tree is guaranteed to be *log(n)* where *n* is the number nodes. On a balanced tree all insert, remove, and search operations take **O(log n)** time. That means fast. ;-) +The other solution is to use a *self-balancing* binary tree. This type of data structure adjusts the tree to keep it balanced after you insert or delete nodes. The height of such a tree is guaranteed to be *log(n)* where *n* is the number nodes. On a balanced tree all insert, remove, and search operations take only **O(log n)** time. That means fast. ;-) ## Introducing the AVL tree @@ -32,7 +32,7 @@ As mentioned, in an AVL tree a node is balanced if its left and right subtree ha ![Balanced trees](Images/BalanceOK.png) -But these are trees that are unbalanced, because the height of the left subtree is too large compared to the right subtree: +But the following are trees that are unbalanced, because the height of the left subtree is too large compared to the right subtree: ![Unbalanced trees](Images/BalanceNotOK.png) @@ -52,7 +52,7 @@ Insertion never needs more than 2 rotations. Removal might require up to *log(n) ## The code -Most of the code in [AVLTree.swift](AVLTree.swift) is just regular [binary search tree](../Binary Search Tree/) stuff. You'll find this in any implementation of a binary search tree. For example, searching the tree is exactly the same. The only things that an AVL tree does slightly differently is inserting and deleting the nodes. +Most of the code in [AVLTree.swift](AVLTree.swift) is just regular [binary search tree](../Binary Search Tree/) stuff. You'll find this in any implementation of a binary search tree. For example, searching the tree is exactly the same. The only things that an AVL tree does slightly differently are inserting and deleting the nodes. > **Note:** If you're a bit fuzzy on the regular operations of a binary search tree, I suggest you [catch up on those first](../Binary Search Tree/). It will make the rest of the AVL tree easier to understand. @@ -66,6 +66,6 @@ The interesting bits are in the following methods: [AVL tree on Wikipedia](https://en.wikipedia.org/wiki/AVL_tree) -AVL tree was the first self-balancing binary tree. These days, the [red-black tree](../Red-Black Tree/) seems to be more common. +AVL tree was the first self-balancing binary tree. These days, the [red-black tree](../Red-Black Tree/) seems to be more popular. *Written for Swift Algorithm Club by Mike Taghavi and Matthijs Hollemans* diff --git a/Algorithm Design.markdown b/Algorithm Design.markdown index d9376f82e..23f8ad70e 100644 --- a/Algorithm Design.markdown +++ b/Algorithm Design.markdown @@ -4,9 +4,9 @@ What to do when you're faced with a new problem and you need to find an algorith ### Is it similar to another problem? -One thing I like about [The Algorithm Design Manual](http://www.algorist.com) by Steven Skiena is that it includes a catalog of problems and solutions you can try. +If you can frame your problem in terms of another, more general problem, then you might be able to use an existing algorithm. Why reinvent the wheel? -If you can frame your problem in terms of another, more general problem, then you might be able to use an existing algorithm. +One thing I like about [The Algorithm Design Manual](http://www.algorist.com) by Steven Skiena is that it includes a catalog of problems and solutions you can try. (See also his [algorithm repository](http://www3.cs.stonybrook.edu/~algorith/).) ### It's OK to start with brute force @@ -14,7 +14,7 @@ Naive, brute force solutions are often too slow for practical use but they're a Once you have a brute force implementation you can use that to verify that any improvements you come up with are correct. -And if you only work with small datasets, then a brute force approach may actually be good enough on its own. +And if you only work with small datasets, then a brute force approach may actually be good enough on its own. Don't fall into the trap of premature optimization! ### Divide and conquer diff --git a/Array2D/README.markdown b/Array2D/README.markdown index 32cde4d67..e73d453a6 100644 --- a/Array2D/README.markdown +++ b/Array2D/README.markdown @@ -1,6 +1,6 @@ # Array2D -In C and Objective-C you can write this, +In C and Objective-C you can write the following line, int cookies[9][7]; @@ -61,7 +61,7 @@ var threeDimensions = dim(2, dim(3, dim(4, 0))) The downside of using multi-dimensional arrays in this fashion -- actually, multiple nested arrays -- is that it's easy to lose track of what dimension represents what. -So instead let's create our own type that acts like a 2-D array and that is more convenient to use. Here it is: +So instead let's create our own type that acts like a 2-D array and that is more convenient to use. Here it is, short and sweet: ```swift public struct Array2D { @@ -100,8 +100,14 @@ Thanks to the `subscript` function, you can do the following to retrieve an obje let myCookie = cookies[column, row] ``` +Or change it: + +```swift +cookies[column, row] = newCookie +``` + Internally, `Array2D` uses a single one-dimensional array to store the data. The index of an object in that array is given by `(row x numberOfColumns) + column`. But as a user of `Array2D` you don't have to worry about that; you only have to think in terms of "column" and "row", and let `Array2D` figure out the details for you. That's the advantage of wrapping primitive types into a wrapper class or struct. And that's all there is to it. -*Written by Matthijs Hollemans* +*Written for Swift Algorithm Club by Matthijs Hollemans* diff --git a/Binary Search Tree/README.markdown b/Binary Search Tree/README.markdown index f08cc0ad1..25d56803b 100644 --- a/Binary Search Tree/README.markdown +++ b/Binary Search Tree/README.markdown @@ -1,12 +1,12 @@ # Binary Search Tree (BST) -A binary search tree is a special kind of [binary tree](../Binary Tree/) (a tree in which a node only has two children) that performs insertions and deletions such that the tree is always sorted. +A binary search tree is a special kind of [binary tree](../Binary Tree/) (a tree in which each node has at most two children) that performs insertions and deletions such that the tree is always sorted. If you don't know what a tree is or what it is for, then [read this first](../Tree/). ## "Always sorted" property -This is an example of a valid binary search tree: +Here is an example of a valid binary search tree: ![A binary search tree](Images/Tree1.png) @@ -33,7 +33,7 @@ There is always only one possible place where the new element can be inserted in > **Note:** The *height* of a node is the number of steps it takes to go from that node to its lowest leaf. The height of the entire tree is the distance from the root to the lowest leaf. Many of the operations on a binary search tree are expressed in terms of the tree's height. -By following this simple rule -- smaller values on the left, larger values on the right -- we keep the tree sorted in a way that whenever we query it, we can quickly check if a value is in the tree. +By following this simple rule -- smaller values on the left, larger values on the right -- we keep the tree sorted in a way such that whenever we query it, we can quickly check if a value is in the tree. ## Searching the tree @@ -49,7 +49,7 @@ If we were looking for the value `5` in the example, it would go as follows: ![Searching the tree](Images/Searching.png) -Thanks to the structure of the tree, searching is really fast. It runs in **O(h)** time. If you have a tree with a million nodes, it only takes about 20 steps to find anything in this tree. (The idea is very similar to [binary search](../Binary Search) in an array.) +Thanks to the structure of the tree, searching is really fast. It runs in **O(h)** time. If you have a well-balanced tree with a million nodes, it only takes about 20 steps to find anything in this tree. (The idea is very similar to [binary search](../Binary Search) in an array.) ## Traversing the tree @@ -57,7 +57,7 @@ Sometimes you don't want to look at just a single node, but at all of them. There are three ways to traverse a binary tree: -1. *In-order* (or *depth-first*): first look at the left child node, then at the node itself, and finally at the right child. +1. *In-order* (or *depth-first*): first look at the left child of a node, then at the node itself, and finally at its right child. 2. *Pre-order*: first look at a node, then its left and right children. 3. *Post-order*: first look at the left and right children and process the node itself last. @@ -148,9 +148,9 @@ Here's how you'd use it: let tree = BinarySearchTree(value: 7) ``` -The `count` property determines how many nodes are in the subtree described by this node. This doesn't just count the node's immediate children but also their children and their children's children, and so on. If this is the root node, then it counts how many nodes are in the entire tree. Initially, `count = 0`. +The `count` property determines how many nodes are in the subtree described by this node. This doesn't just count the node's immediate children but also their children and their children's children, and so on. If this particular object is the root node, then it counts how many nodes are in the entire tree. Initially, `count = 0`. -> **Note:** Because `left`, `right`, and `parent` are optionals, we can make good use of Swift's optional chaining (`?`) and nil-coalescing operators (`??`). You could also write this sort of thing with `if let` but that takes up more space. +> **Note:** Because `left`, `right`, and `parent` are optionals, we can make good use of Swift's optional chaining (`?`) and nil-coalescing operators (`??`). You could also write this sort of thing with `if let` but that is less concise. ### Inserting nodes @@ -182,7 +182,7 @@ A tree node by itself is pretty useless, so here is how you would add new nodes Like so many other tree operations, insertion is easiest to implement with recursion. We compare the new value to the values of the existing nodes and decide whether to add it to the left branch or the right branch. -If there is no more left or right child to look at, we create a new `BinarySearchTree` object for the new node and connect it to the tree by setting its `parent` property. +If there is no more left or right child to look at, we create a `BinarySearchTree` object for the new node and connect it to the tree by setting its `parent` property. > **Note:** Because the whole point of a binary search tree is to have smaller nodes on the left and larger ones on the right, you should always insert elements at the root, to make to sure this remains a valid binary tree! @@ -197,7 +197,7 @@ tree.insert(9) tree.insert(1) ``` -> **Note:** For reasons that will become clear later, you should insert the numbers in a somewhat random order. If you insert them in sorted order, then the tree won't have the right shape. +> **Note:** For reasons that will become clear later, you should insert the numbers in a somewhat random order. If you insert them in sorted order, the tree won't have the right shape. For convenience, let's add an init method that calls `insert()` for all the elements in an array: @@ -243,11 +243,11 @@ When you do a `print(tree)`, you should get something like this: ((1) <- 2 -> (5)) <- 7 -> ((9) <- 10) -With some imagination, you should see now that this indeed corresponds to the following tree: +The root node is in the middle. With some imagination, you should see that this indeed corresponds to the following tree: ![The tree](Images/Tree2.png) -By the way, you may be wondering what happens when you insert duplicate items? We always insert those kinds of items in the right branch. Try it out! +By the way, you may be wondering what happens when you insert duplicate items? We always insert those in the right branch. Try it out! ### Searching @@ -269,7 +269,7 @@ Here is the implementation of `search()`: I hope the logic is clear: this starts at the current node (usually the root) and compares the values. If the search value is less than the node's value, we continue searching in the left branch; if the search value is greater, we dive into the right branch. -Of course, if there are no more nodes to look at -- when `left` or `right` is nil -- then we return nil to indicate the search value is not in the tree. +Of course, if there are no more nodes to look at -- when `left` or `right` is nil -- then we return `nil` to indicate the search value is not in the tree. > **Note:** In Swift that's very conveniently done with optional chaining; when you write `left?.search(value)` it automatically returns nil if `left` is nil. There's no need to explicitly check for this with an `if` statement. @@ -299,7 +299,7 @@ Here's how to test searching: tree.search(5) tree.search(2) tree.search(7) -tree.search(6) // nil +tree.search(6) // nil ``` The first three lines all return the corresponding `BinaryTreeNode` object. The last line returns `nil` because there is no node with value `6`. @@ -426,7 +426,7 @@ We won't need it for deleting, but for completeness' sake, here is the opposite } ``` -It returns the rightmost descendent of this node. We find it by following `right` pointers until we get to the end. In the above example, the rightmost descendent of node `2` is `5`. The maximum value in the entire tree is `11`, because that is the rightmost descendent of the root node `7`. +It returns the rightmost descendent of the node. We find it by following `right` pointers until we get to the end. In the above example, the rightmost descendent of node `2` is `5`. The maximum value in the entire tree is `11`, because that is the rightmost descendent of the root node `7`. Finally, we can write the code the remove a node from the tree: @@ -460,8 +460,6 @@ It doesn't look so scary after all. ;-) Here is what it does: The only tricky situation here is `// 1`. Rather than deleting the current node, we give it the successor's value and remove the successor node instead. -> **Note:** What would happen if you deleted the root node? Specifically, how would you know which node becomes the new root node? It turns out you don't have to worry about that because the root never actually gets deleted. We simply give it a new value. - Try it out: ```swift @@ -482,6 +480,8 @@ But after `remove()` you get: As you can see, node `5` has taken the place of `2`. In fact, if you do `print(node2)` you'll see that it now has the value `5`. We didn't actually remove the `node2` object, we just gave it a new value. +> **Note:** What would happen if you deleted the root node? Specifically, how would you know which node becomes the new root node? It turns out you don't have to worry about that because the root never actually gets deleted. We simply give it a new value. + Like most binary search tree operations, removing a node runs in **O(h)** time, where **h** is the height of the tree. ### Depth and height @@ -516,7 +516,7 @@ You can also calculate the *depth* of a node, which is the distance to the root. var edges = 0 while case let parent? = node.parent { node = parent - ++edges + edges += 1 } return edges } @@ -624,6 +624,8 @@ We've implemented the binary tree node as a class but you can also use an enum. The difference is reference semantics versus value semantics. Making a change to the class-based tree will update that same instance in memory. But the enum-based tree is immutable -- any insertions or deletions will give you an entirely new copy of the tree. Which one is best totally depends on what you want to use it for. +Here's how you'd make a binary search tree using an enum: + ```swift public enum BinarySearchTree { case Empty @@ -638,9 +640,9 @@ The enum has three cases: - `Leaf` for a leaf node that has no children. - `Node` for a node that has one or two children. This is marked `indirect` so that it can hold `BinarySearchTree` values. Without `indirect` you can't make recursive enums. -> **Note:** The nodes in this binary tree don't have a reference to their parent node. That will make certain operations slightly more cumbersome to implement. +> **Note:** The nodes in this binary tree don't have a reference to their parent node. It's not a major impediment but it will make certain operations slightly more cumbersome to implement. -A usual, we'll implement most functionality recursively. We'll treat each case slightly differently. For example, this is how you could calculate the number of nodes in the tree and the height of the tree: +A usual, we'll implement most functionality recursively. We'll treat each case of the enum slightly differently. For example, this is how you could calculate the number of nodes in the tree and the height of the tree: ```swift public var count: Int { @@ -696,7 +698,7 @@ tree = tree.insert(9) tree = tree.insert(1) ``` -Notice that each time you insert something, you get back a completely new tree. That's why you need to assign the result back to the `tree` variable. +Notice that each time you insert something, you get back a completely new tree object. That's why you need to assign the result back to the `tree` variable. Here is the all-important search function: @@ -748,13 +750,13 @@ When you do `print(tree)` it will look something like this: ((1 <- 2 -> 5) <- 7 -> (9 <- 10 -> .)) -The root node is in the middle. A dot means there is no child at that position. +The root node is in the middle; a dot means there is no child at that position. ## When the tree becomes unbalanced... A binary search tree is *balanced* when its left and right subtrees contain roughly the same number of nodes. In that case, the height of the tree is *log(n)*, where *n* is the number of nodes. That's the ideal situation. -However, if one branch is significantly longer than the other, searching becomes very slow. We need to check way more values than we'd ideally have to. In the worst case, the height of the tree can become *n*. Such a tree acts more like a [linked list](../Linked List/) than a binary search tree, with performance degrading to **O(n)**. Not good! +However, if one branch is significantly longer than the other, searching becomes very slow. We end up checking way more values than we'd ideally have to. In the worst case, the height of the tree can become *n*. Such a tree acts more like a [linked list](../Linked List/) than a binary search tree, with performance degrading to **O(n)**. Not good! One way to make the binary search tree balanced is to insert the nodes in a totally random order. On average that should balance out the tree quite nicely. But it doesn't guarantee success, nor is it always practical. diff --git a/Binary Search Tree/Solution 1/BinarySearchTree.playground/Sources/BinarySearchTree.swift b/Binary Search Tree/Solution 1/BinarySearchTree.playground/Sources/BinarySearchTree.swift index f509195f9..7ef0280cf 100644 --- a/Binary Search Tree/Solution 1/BinarySearchTree.playground/Sources/BinarySearchTree.swift +++ b/Binary Search Tree/Solution 1/BinarySearchTree.playground/Sources/BinarySearchTree.swift @@ -212,7 +212,7 @@ extension BinarySearchTree { var edges = 0 while case let parent? = node.parent { node = parent - ++edges + edges += 1 } return edges } diff --git a/Binary Search Tree/Solution 1/BinarySearchTree.swift b/Binary Search Tree/Solution 1/BinarySearchTree.swift index f509195f9..7ef0280cf 100644 --- a/Binary Search Tree/Solution 1/BinarySearchTree.swift +++ b/Binary Search Tree/Solution 1/BinarySearchTree.swift @@ -212,7 +212,7 @@ extension BinarySearchTree { var edges = 0 while case let parent? = node.parent { node = parent - ++edges + edges += 1 } return edges } diff --git a/Binary Search/README.markdown b/Binary Search/README.markdown index 792b15c4a..8c5d8f0f1 100644 --- a/Binary Search/README.markdown +++ b/Binary Search/README.markdown @@ -31,7 +31,7 @@ And you'd use it like this: linearSearch(numbers, 43) // returns 15 ``` -So what's the problem? `linearSearch()` loops through the entire array from the beginning until it finds the element you're looking for. In the worst case, the value isn't in the array and all that work is done for nothing. +So what's the problem? `linearSearch()` loops through the entire array from the beginning, until it finds the element you're looking for. In the worst case, the value isn't even in the array and all that work is done for nothing. On average, the linear search algorithm needs to look at half the values in the array. If your array is large enough, this starts to become very slow! @@ -41,12 +41,12 @@ The classic way to speed this up is to use a *binary search*. The trick is to ke For an array of size `n`, the performance is not **O(n)** as with linear search but only **O(log n)**. To put that in perspective, binary search on an array with 1,000,000 elements only takes about 20 steps to find what you're looking for, because `log_2(1,000,000) = 19.9`. And for an array with a billion elements it only takes 30 steps. (Then again, when was the last time you used an array with a billion items?) -Sounds great, but there is one downside to using binary search: the array must be sorted. In practice, this usually isn't a problem. +Sounds great, but there is a downside to using binary search: the array must be sorted. In practice, this usually isn't a problem. Here's how binary search works: - Split the array in half and determine whether the thing you're looking for, known as the *search key*, is in the left half or in the right half. -- How do you determine in which half the search key is? This is why you sorted the array first, so you can do a simple less-than or greater-than comparison. +- How do you determine in which half the search key is? This is why you sorted the array first, so you can do a simple `<` or `>` comparison. - If the search key is in the left half, you repeat the process there: split the left half into two even smaller pieces and look in which piece the search key must lie. (Likewise for when it's the right half.) - This repeats until the search key is found. If the array cannot be split up any further, you must regrettably conclude that the search key is not present in the array. @@ -92,11 +92,9 @@ binarySearch(numbers, key: 43, range: 0 ..< numbers.count) // gives 13 Note that the `numbers` array is sorted. The binary search algorithm does not work otherwise! -I said that binary search works by splitting the array in half, but we don't actually create two new arrays. Instead, we keep track of these splits using a Swift `Range` object. +I said that binary search works by splitting the array in half, but we don't actually create two new arrays. Instead, we keep track of these splits using a Swift `Range` object. Initially, this range covers the entire array, `0 ..< numbers.count`. As we split the array, the range becomes smaller and smaller. -Initially, this range covers the entire array, `0 ..< numbers.count`. As we split the array, the range becomes smaller and smaller. - -> **Note:** One thing to be aware of is that `range.endIndex` always points one beyond the last element. In the example, the range is `0..<19` because there are 19 numbers in the array, and so `range.startIndex = 0` and `range.endIndex = 19`. But in our array the last element is at index 18, since we start counting from 0. Just keep this in mind when working with ranges: the `endIndex` is always one more than the index of the last element. +> **Note:** One thing to be aware of is that `range.endIndex` always points one beyond the last element. In the example, the range is `0..<19` because there are 19 numbers in the array, and so `range.startIndex = 0` and `range.endIndex = 19`. But in our array the last element is at index 18, not 19, since we start counting from 0. Just keep this in mind when working with ranges: the `endIndex` is always one more than the index of the last element. ## Stepping through the example @@ -133,7 +131,7 @@ Now binary search will determine which half to use. The relevant section from th } ``` -In this case, `a[midIndex] = 29`. That's less than the search key, so we can safely conclude that the search key will never be in the left half of the array, since that only contains numbers smaller than `29`. Hence, the search key must be in the right half somewhere (or not in the array at all). +In this case, `a[midIndex] = 29`. That's less than the search key, so we can safely conclude that the search key will never be in the left half of the array. After all, the left half only contains numbers smaller than `29`. Hence, the search key must be in the right half somewhere (or not in the array at all). Now we can simply repeat the binary search, but on the array interval from `midIndex + 1` to `range.endIndex`: @@ -167,13 +165,13 @@ Again, the search key is greater, so split once more and take the right side: [ x, x, x, x, x, x, x, x, x, x | x, x | x | 43 | x, x, x, x, x ] * -And now we're done. The search key equals the array element we're looking at, so we've finally found what we were looking for. Number `43` is at array index `13`. w00t! +And now we're done. The search key equals the array element we're looking at, so we've finally found what we were searching for: number `43` is at array index `13`. w00t! It may have seemed like a lot of work, but in reality it only took four steps to find the search key in the array, which sounds about right because `log_2(19) = 4.23`. With a linear search, it would have taken 14 steps. -What would happen if we were to look for `42` instead of `43`? In that case, we can't split up the array any further.The `range.endIndex` becomes smaller than `range.startIndex` and that tells the algorithm the search key is not in the array and it returns `nil`. +What would happen if we were to search for `42` instead of `43`? In that case, we can't split up the array any further. The `range.endIndex` becomes smaller than `range.startIndex`. That tells the algorithm the search key is not in the array and it returns `nil`. -> **Note:** Many implementations of binary search calculate `midIndex = (start + end) / 2`. This contains a subtle bug that only appears with very large arrays, because `start + end` may overflow the maximum number an integer can hold. This situation is unlikely to happen on a 64-bit CPU, but it definitely can on 32-bit machines. +> **Note:** Many implementations of binary search calculate `midIndex = (startIndex + endIndex) / 2`. This contains a subtle bug that only appears with very large arrays, because `startIndex + endIndex` may overflow the maximum number an integer can hold. This situation is unlikely to happen on a 64-bit CPU, but it definitely can on 32-bit machines. ## Iterative vs recursive @@ -214,4 +212,4 @@ Is it a problem that the array must be sorted first? It depends. Keep in mind th See also [Wikipedia](https://en.wikipedia.org/wiki/Binary_search_algorithm). -*Written by Matthijs Hollemans* +*Written for Swift Algorithm Club by Matthijs Hollemans* diff --git a/Binary Tree/README.markdown b/Binary Tree/README.markdown index ed829ec0c..24498b035 100644 --- a/Binary Tree/README.markdown +++ b/Binary Tree/README.markdown @@ -4,7 +4,7 @@ A binary tree is a [tree](../Tree/) where each node has 0, 1, or 2 children. Thi ![A binary tree](Images/BinaryTree.png) -The child nodes are usually called the "left" child and the "right" child. If a node doesn't have any children, it's called a *leaf* node. The *root* is the node at the very top of the tree (programmers like their trees upside down). +The child nodes are usually called the *left* child and the *right* child. If a node doesn't have any children, it's called a *leaf* node. The *root* is the node at the very top of the tree (programmers like their trees upside down). Often nodes will have a link back to their parent but this is not strictly necessary. @@ -104,9 +104,9 @@ On the tree from the example, `tree.count` should be 12. Something you often need to do with trees is traverse them, i.e. look at all the nodes in some order. There are three ways to traverse a binary tree: -1. *In-order* (or *depth-first*): first look at the left child node, then at the node itself, and finally at the right child. -2. *Pre-order*: first look at a node, then its left and right children. -3. *Post-order*: first look at the left and right children and process the node last. +1. *In-order* (or *depth-first*): first look at the left child of a node, then at the node itself, and finally at its right child. +2. *Pre-order*: first look at a node, then at its left and right children. +3. *Post-order*: first look at the left and right children and process the node itself last. Here is how you'd implement that: diff --git a/Bit Set/README.markdown b/Bit Set/README.markdown index 380463d33..85d55e06e 100644 --- a/Bit Set/README.markdown +++ b/Bit Set/README.markdown @@ -10,7 +10,7 @@ Since manipulating individual bits is a little tricky, you can use `BitSet` to h ## The code -A bit set is simply a wrapper around an array. The array doesn't store individual bits but larger integers that we call the "words". The `BitSet` maps the bits to the right word. +A bit set is simply a wrapper around an array. The array doesn't store individual bits but larger integers called the "words". The main job of `BitSet` is to map the bits to the right word. ```swift public struct BitSet { @@ -38,9 +38,9 @@ If you write, var bits = BitSet(size: 140) ``` -then the `BitSet` allocates an array of three words. Each word holds 64 bits and therefore three words can hold 192 bits. We only use 140 of those bits so we're wasting a bit of space (but of course we can never use less than a whole word.) +then the `BitSet` allocates an array of three words. Each word has 64 bits and therefore three words can hold 192 bits. We only use 140 of those bits so we're wasting a bit of space (but of course we can never use less than a whole word). -> **Note:** The first entry in the `words` array is the least-significant word, so these words are stored in little endian order. +> **Note:** The first entry in the `words` array is the least-significant word, so these words are stored in little endian order in the array. ## Looking up the bits @@ -56,9 +56,9 @@ Most of the operations on `BitSet` take the index of the bit as a parameter, so } ``` -The `indexOf()` function returns the array index of the word, as well as a "mask" that shows where the bit sits inside that word. +The `indexOf()` function returns the array index of the word, as well as a "mask" that shows exactly where the bit sits inside that word. -For example, `indexOf(2)` returns the tuple `(0, 4)` because bit 2 is in the first word (index 0). The mask is 4. In binary that looks like: +For example, `indexOf(2)` returns the tuple `(0, 4)` because bit 2 is in the first word (index 0). The mask is 4. In binary the mask looks like the following: 0010000000000000000000000000000000000000000000000000000000000000 @@ -94,7 +94,7 @@ Clearing the bit -- i.e. changing it to 0 -- is just as easy: } ``` -Instead of a bitwise OR we now do a bitwise AND with the inverse of the mask. So if the mask was `00100000...0`, then the inverse is `11011111...1`. All the bits are 1, except for the bit we want to set to 0. Due to the way `&` works, this leaves all other bits alone and only changes that one to 0. +Instead of a bitwise OR we now do a bitwise AND with the inverse of the mask. So if the mask was `00100000...0`, then the inverse is `11011111...1`. All the bits are 1, except for the bit we want to set to 0. Due to the way `&` works, this leaves all other bits alone and only changes that single bit to 0. To see if a bit is set we also use the bitwise AND but without inverting: @@ -185,7 +185,7 @@ But this is incorrect... Since we don't use most of the last word, we should lea Instead of 192 one-bits we now have only 140 one-bits. The fact that the last word may not be completely filled up means that we always have to treat this last word specially. -Setting those "leftover" bits to 0 is what the `clearUnusedBits()` helper function does. If the size is not a multiple of `N` (i.e. 64), then we have to clear out the bits that we're not using. If we don't do this, bitwise operations between two differently sized `BitSet`s will go wrong (an example follows). +Setting those "leftover" bits to 0 is what the `clearUnusedBits()` helper function does. If the `BitSet`'s size is not a multiple of `N` (i.e. 64), then we have to clear out the bits that we're not using. If we don't do this, bitwise operations between two differently sized `BitSet`s will go wrong (an example follows). This uses some advanced bit manipulation, so pay close attention: @@ -209,7 +209,7 @@ Here's what it does, step-by-step: 1) `diff` is the number of "leftover" bits. In the above example that is 52 because `3*64 - 140 = 52`. -2) Create a mask that is all 0's. Except the highest bit that's still valid is a 1. In our example, that would be: +2) Create a mask that is all 0's, except the highest bit that's still valid is a 1. In our example, that would be: 0000000000010000000000000000000000000000000000000000000000000000 @@ -230,7 +230,7 @@ An example of where this is important is when you combine two `BitSet`s of diffe 10001111 size=4 00100011 size=8 -The first one only uses the first 4 bits; the second one uses 8 bits. The first one should really be `10000000` but let's pretend we forgot to clear out those 1's. Then a bitwise or between the two results in: +The first one only uses the first 4 bits; the second one uses 8 bits. The first one should really be `10000000` but let's pretend we forgot to clear out those 1's at the end. Then a bitwise OR between the two results in: 10001111 00100011 @@ -299,7 +299,7 @@ To count the number of bits that are set to 1 we could scan through the entire a } ``` -When you write `x & ~(x - 1)`, it gives you a new value with a single bit set. This is the lowest bit that is one. For example take this 8-bit value (again, I'm showing this with the least significant bit on the left): +When you write `x & ~(x - 1)`, it gives you a new value with only a single bit set. This is the lowest bit that is one. For example take this 8-bit value (again, I'm showing this with the least significant bit on the left): 00101101 @@ -325,7 +325,9 @@ The only value they have in common is the lowest (or least significant) 1-bit. T -------- XOR 00001101 -We keep repeating this until the value consists of all zeros. The time complexity is **O(s)** where **s** is the number of 1-bits. +This is the original value but with the lowest 1-bit removed. + +We keep repeating this process until the value consists of all zeros. The time complexity is **O(s)** where **s** is the number of 1-bits. ## See also diff --git a/Bloom Filter/README.markdown b/Bloom Filter/README.markdown index c0c06400b..3e37ee50b 100644 --- a/Bloom Filter/README.markdown +++ b/Bloom Filter/README.markdown @@ -16,11 +16,11 @@ An advantage of the Bloom Filter over a hash table is that the former maintains > **Note:** Unlike a hash table, the Bloom Filter does not store the actual objects. It just remembers what objects you’ve seen (with a degree of uncertainty) and which ones you haven’t. -## How it works +## Inserting objects into the set A Bloom Filter is essentially a fixed-length [bit vector](../Bit Set/), an array of bits. When we insert objects, we set some of these bits to `1`, and when we query for objects we check if certain bits are `0` or `1`. Both operations use hash functions. -To insert an element in the filter, the element is hashed with several different hash functions. Each hash function returns a value that we map to an index in the array. We set the bits at these indices to `1` or true. +To insert an element in the filter, the element is hashed with several different hash functions. Each hash function returns a value that we map to an index in the array. We then set the bits at these indices to `1` or true. For example, let's say this is our array of bits. We have 17 bits and initially they are all `0` or false: @@ -34,9 +34,11 @@ Then we hash the original string again but this time with a different hash funct [ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 ] -These two bits are enough to tell the Bloom Filter that it now contains the string `"Hello world!"`. +These two 1-bits are enough to tell the Bloom Filter that it now contains the string `"Hello world!"`. Of course, it doesn't contain the actual string, so you can't ask the Bloom Filter, "give me a list of all the objects you contain". All it has is a bunch of ones and zeros. -Querying, similarly, is accomplished by first hashing the expected value, which gives several array indices, and then checking to see if all of the bits at those indices are `true`. If even one of the bits is not `true`, the element could not have been inserted and the query returns `false`. If all the bits are `true`, the query returns likewise. +## Querying the set + +Querying, similarly to inserting, is accomplished by first hashing the expected value, which gives several array indices, and then checking to see if all of the bits at those indices are `1`. If even one of the bits is not `1`, the element could not have been inserted and the query returns `false`. If all the bits are `1`, the query returns `true`. For example, if we query for the string `"Hello WORLD"`, then the first hash function returns 5383892684077141175, which modulo 17 is 12. That bit is `1`. But the second hash function gives 5625257205398334446, which maps to array index 9. That bit is `0`. This means the string `"Hello WORLD"` is not in the filter and the query returns `false`. @@ -50,7 +52,7 @@ If you query for `"Hello WORLD"` again, the filter sees that bit 12 is true and You can fix such issues by using an array with more bits and using additional hash functions. Of course, the more hash functions you use the slower the Bloom Filter will be. So you have to strike a balance. -Deletion is not possible with a Bloom Filter, since any one bit might have been set by multiple elements inserted. Once you add an element, it's in there for good. +Deletion is not possible with a Bloom Filter, since any one bit might belong to multiple elements. Once you add an element, it's in there for good. Performance of a Bloom Filter is **O(k)** where **k** is the number of hashing functions. @@ -96,6 +98,6 @@ public func query(value: T) -> Bool { } ``` -If you're coming from another imperative language, you might notice the unusual syntax in the `exists` assignment. Swift makes use of functional paradigms when it makes code more consise and readable, and in this case, `reduce` is a much more consise way to check if all the required bits are `true` than a `for` loop. +If you're coming from another imperative language, you might notice the unusual syntax in the `exists` assignment. Swift makes use of functional paradigms when it makes code more consise and readable, and in this case `reduce` is a much more consise way to check if all the required bits are `true` than a `for` loop. *Written for Swift Algorithm Club by Jamil Dhanani. Edited by Matthijs Hollemans.* diff --git a/Boyer-Moore/README.markdown b/Boyer-Moore/README.markdown index dce0430f2..73a7943a2 100644 --- a/Boyer-Moore/README.markdown +++ b/Boyer-Moore/README.markdown @@ -2,7 +2,7 @@ Goal: Write a string search algorithm in pure Swift without importing Foundation or using `NSString`'s `rangeOfString()` method. -In other words, implement an `indexOf(pattern: String)` extension on `String` that returns the `String.Index` of the first occurrence of the search pattern, or `nil` if the pattern could not be found inside the string. +In other words, we want to implement an `indexOf(pattern: String)` extension on `String` that returns the `String.Index` of the first occurrence of the search pattern, or `nil` if the pattern could not be found inside the string. For example: @@ -24,9 +24,9 @@ animals.indexOf("🐮") > **Note:** The index of the cow is 6, not 3 as you might expect, because the string uses more storage per character for emoji. The actual value of the `String.Index` is not so important, just that it points at the right character in the string. -The [brute-force approach](../Brute-Force Search Search/) works OK, but it's not very efficient, especially on large chunks of text. As it turns out, you don't need to look at *every* character from the source string -- you can often skip ahead multiple characters. +The [brute-force approach](../Brute-Force String Search/) works OK, but it's not very efficient, especially on large chunks of text. As it turns out, you don't need to look at *every* character from the source string -- you can often skip ahead multiple characters. -That skip-ahead algorithm is called [Boyer-Moore](https://en.wikipedia.org/wiki/Boyer–Moore_string_search_algorithm) and it has been around for a long time. It is considered the benchmark for all string search algorithms. +The skip-ahead algorithm is called [Boyer-Moore](https://en.wikipedia.org/wiki/Boyer–Moore_string_search_algorithm) and it has been around for a long time. It is considered the benchmark for all string search algorithms. Here's how you could write it in Swift: @@ -133,7 +133,7 @@ The amount to skip ahead at any given time is determined by the "skip table", wh The closer a character is to the end of the pattern, the smaller the skip amount. If a character appears more than once in the pattern, the one nearest to the end of the pattern determines the skip value for that character. -A caveat: If the search pattern consists of only a few characters, it's faster to do a brute-force search. There's a trade-off between the time it takes to build the skip table and doing brute-force for short patterns. +> **Note:** If the search pattern consists of only a few characters, it's faster to do a brute-force search. There's a trade-off between the time it takes to build the skip table and doing brute-force for short patterns. Credits: This code is based on the article ["Faster String Searches" by Costas Menico](http://www.drdobbs.com/database/faster-string-searches/184408171) from Dr Dobb's magazine, July 1989 -- Yes, 1989! Sometimes it's useful to keep those old magazines around. diff --git a/Breadth-First Search/README.markdown b/Breadth-First Search/README.markdown index 584b37c1d..e75d2b913 100644 --- a/Breadth-First Search/README.markdown +++ b/Breadth-First Search/README.markdown @@ -1,6 +1,6 @@ # Breadth-First Search -Breadth-first search (BFS) is an algorithm for traversing or searching [tree](../Tree/) or [graph](../Graph/) data structures. It starts at the tree source and explores the immediate neighbor nodes first, before moving to the next level neighbors. +Breadth-first search (BFS) is an algorithm for traversing or searching [tree](../Tree/) or [graph](../Graph/) data structures. It starts at a source node and explores the immediate neighbor nodes first, before moving to the next level neighbors. ## Animated example @@ -129,10 +129,10 @@ This will output: `["a", "b", "c", "d", "e", "f", "g", "h"]` ## Applications -Breadth-first search can be used to solve many problems, for example: +Breadth-first search can be used to solve many problems. A small selection: -* Computing the shortest path between a source node and each of the other nodes (only for unweighted graphs) -* Calculating the minimum spanning tree on an unweighted graph +* Computing the shortest path between a source node and each of the other nodes (only for unweighted graphs). +* Calculating the minimum spanning tree on an unweighted graph. ## Shortest path example diff --git a/Combinatorics/README.markdown b/Combinatorics/README.markdown index d491aab28..2d7a6ac83 100644 --- a/Combinatorics/README.markdown +++ b/Combinatorics/README.markdown @@ -10,20 +10,20 @@ This is another permutation: For a collection of `n` objects, there are `n!` possible permutations, where `!` is the "factorial" function. So for our collection of five letters, the total number of permutations you can make is: - 5! = 5 x 4 x 3 x 2 x 1 = 120 + 5! = 5 * 4 * 3 * 2 * 1 = 120 -A collection of six items has `6! = 720` permutations. For ten items, it is `10! = 3.628.800`. That adds up quick! +A collection of six items has `6! = 720` permutations. For ten items, it is `10! = 3,628,800`. That adds up quick! Where does this `n!` come from? The logic is as follows: we have a collection of five letters that we want to put in some order. To do this, you need to pick up these letters one-by-one. Initially, you have the choice of five letters: `a, b, c, d, e`. That gives 5 possibilities. -After picking the first letter, you only have four letters left to choose from. That gives `5 x 4 = 20` possibilities: +After picking the first letter, you only have four letters left to choose from. That gives `5 * 4 = 20` possibilities: a+b b+a c+a d+a e+a a+c b+c c+b d+b e+b a+d b+d c+d d+c e+c a+e b+e c+e d+e e+d -After picking the second letter, there are only three letters left to choose from. And so on... When you get to the last letter, you don't have any choice because there is only one letter left. That's why the total number of possibilities is `5 x 4 x 3 x 2 x 1`. +After picking the second letter, there are only three letters left to choose from. And so on... When you get to the last letter, you don't have any choice because there is only one letter left. That's why the total number of possibilities is `5 * 4 * 3 * 2 * 1`. To calculate the factorial in Swift: @@ -47,7 +47,7 @@ factorial(5) // returns 120 Note that `factorial(20)` is the largest number you can calculate with this function, or you'll get integer overflow. -Let's say that from that collection of five letters you want to choose only 3 elements. How many possible ways can you do this? Well, that works the same way as before, except that you stop after the third letter. So now the number of possibilities is `5 x 4 x 3 = 60`. +Let's say that from that collection of five letters you want to choose only 3 elements. How many possible ways can you do this? Well, that works the same way as before, except that you stop after the third letter. So now the number of possibilities is `5 * 4 * 3 = 60`. The formula for this is: @@ -83,11 +83,13 @@ permutations(9, 4) // returns 3024 This function takes advantage of the following algebra fact: - 9 x 8 x 7 x 6 x 5 x 4 x 3 x 2 x 1 - P(9, 4) = --------------------------------- = 9 x 8 x 7 x 6 = 3024 - 5 x 4 x 3 x 2 x 1 + 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2 * 1 + P(9, 4) = --------------------------------- = 9 * 8 * 7 * 6 = 3024 + 5 * 4 * 3 * 2 * 1 -The denominator cancels out part of the numerator, so there's no need to perform a division and you're not dealing with intermediate results that are potentially too large. However, there are still limits to what you can calculate; for example the number of groups of size 15 that you can make from a collection of 30 objects -- i.e. `P(30, 15)` -- is ginormous and breaks Swift. Huh, you wouldn't think it would be so large but combinatorics is funny that way. +The denominator cancels out part of the numerator, so there's no need to perform a division and you're not dealing with intermediate results that are potentially too large. + +However, there are still limits to what you can calculate; for example the number of groups of size 15 that you can make from a collection of 30 objects -- i.e. `P(30, 15)` -- is ginormous and breaks Swift. Huh, you wouldn't think it would be so large but combinatorics is funny that way. ## Generating the permutations @@ -211,7 +213,7 @@ Of course, the larger your array is, the more swaps it performs and the deeper t If the above is still not entirely clear, then I suggest you give it a go in the playground. That's what playgrounds are great for. :-) -For fun, here is an alternative algorithm, by Sedgewick: +For fun, here is an alternative algorithm, by Robert Sedgewick: ```swift func permuteSedgewick(a: [Int], _ n: Int, inout _ pos: Int) { @@ -259,7 +261,7 @@ Try to figure out for yourself how this algorithm works! ## Combinations -A combination is like a permutation where the order does not matter. So the following are six different permutations of the letters `k` `l` `m` but they all count as the same combination: +A combination is like a permutation where the order does not matter. The following are six different permutations of the letters `k` `l` `m` but they all count as the same combination: k, l, m k, m, l m, l, k l, m, k l, k, m m, k, l @@ -276,15 +278,15 @@ The formula for `C(n, k)` is: n! P(n, k) C(n, k) = ------------- = -------- - (n - k)! x k! k! + (n - k)! * k! k! As you can see, you can derive it from the formula for `P(n, k)`. There are always more permutations than combinations. You divide the number of permutations by `k!` because a total of `k!` of these permutations give the same combination. -Above I showed that the number of permutations of `k` `l` `m` is 6 but, if you pick only two of those letters, the number of combinations is 3. If we use the formula we should get the same answer. We want to calculate `C(3, 2)` because we choose 2 letters out of a collection of 3. +Above I showed that the number of permutations of `k` `l` `m` is 6, but if you pick only two of those letters the number of combinations is 3. If we use the formula we should get the same answer. We want to calculate `C(3, 2)` because we choose 2 letters out of a collection of 3. - 3 x 2 x 1 6 + 3 * 2 * 1 6 C(3, 2) = --------- = --- = 3 - 1! x 2! 2 + 1! * 2! 2 Here's a simple function to calculate `C(n, k)`: @@ -300,7 +302,7 @@ Use it like this: combinations(28, 5) // prints 98280 ``` -Because this uses the `permutations()` and `factorial()` functions under the hood, you're still limited by how large these numbers can get. For example, `combinations(30, 15)` is "only" `155.117.520` but because the intermediate results don't fit into a 64-bit integer, you can't calculate it with the given function. +Because this uses the `permutations()` and `factorial()` functions under the hood, you're still limited by how large these numbers can get. For example, `combinations(30, 15)` is "only" `155,117,520` but because the intermediate results don't fit into a 64-bit integer, you can't calculate it with the given function. Here is an algorithm that uses dynamic programming to overcome the need for calculating factorials. It is based on Pascal's triangle: @@ -312,7 +314,7 @@ Here is an algorithm that uses dynamic programming to overcome the need for calc 5: 1 5 10 10 5 1 6: 1 6 15 20 15 6 1 -Each number in the next row is made up by adding two numbers from the previous row. For example, in row 6, the number 15 is made by adding the 5 and 10 from row 5. These numbers are called the binomial coefficients and as it happens they are the same as `C(n, k)`. +Each number in the next row is made up by adding two numbers from the previous row. For example in row 6, the number 15 is made by adding the 5 and 10 from row 5. These numbers are called the binomial coefficients and as it happens they are the same as `C(n, k)`. For example, for row 6: @@ -360,6 +362,6 @@ You may wonder what the point is in calculating these permutations and combinati ## References -Wirth's and Sedgewick's permutation algorithms and the code for counting permutations and combinations is based on the Algorithm Alley column from Dr.Dobb's Magazine, June 1993. The dynamic programming binomial coefficient algorithm is from The Algorithm Design Manual by Skiena. +Wirth's and Sedgewick's permutation algorithms and the code for counting permutations and combinations are based on the Algorithm Alley column from Dr.Dobb's Magazine, June 1993. The dynamic programming binomial coefficient algorithm is from The Algorithm Design Manual by Skiena. *Written for Swift Algorithm Club by Matthijs Hollemans* diff --git a/Count Occurrences/README.markdown b/Count Occurrences/README.markdown index d22609025..be8c2061e 100644 --- a/Count Occurrences/README.markdown +++ b/Count Occurrences/README.markdown @@ -2,7 +2,7 @@ Goal: Count how often a certain value appears in an array. -The obvious way to do this is with a [linear search](../Linear Search/) from the beginning of the array until the end, keeping count of how often you come across the value. This is an **O(n)** algorithm. +The obvious way to do this is with a [linear search](../Linear Search/) from the beginning of the array until the end, keeping count of how often you come across the value. That is an **O(n)** algorithm. However, if the array is sorted you can do it much faster, in **O(log n)** time, by using a modification of [binary search](../Binary Search/). @@ -10,7 +10,7 @@ Let's say we have the following array: [ 0, 1, 1, 3, 3, 3, 3, 6, 8, 10, 11, 11 ] -If we want to know how often the value `3` occurs, we can do a binary search for `3`. That could give us any of these four indices: +If we want to know how often the value `3` occurs, we can do a regular binary search for `3`. That could give us any of these four indices: [ 0, 1, 1, 3, 3, 3, 3, 6, 8, 10, 11, 11 ] * * * * @@ -55,7 +55,7 @@ func countOccurrencesOfKey(key: Int, inArray a: [Int]) -> Int { } ``` -Notice that the helper functions `leftBoundary()` and `rightBoundary()` are very similar to the binary search algorithm. The big difference is that they don't stop when they find the search key, but keep going. +Notice that the helper functions `leftBoundary()` and `rightBoundary()` are very similar to the [binary search](../Binary Search/) algorithm. The big difference is that they don't stop when they find the search key, but keep going. To test this algorithm, copy the code to a playground and then do: @@ -65,7 +65,7 @@ let a = [ 0, 1, 1, 3, 3, 3, 3, 6, 8, 10, 11, 11 ] countOccurrencesOfKey(3, inArray: a) // returns 4 ``` -Remember: If you use your own array, make sure it is sorted first! +> **Remember:** If you use your own array, make sure it is sorted first! Let's walk through the example. The array is: @@ -111,10 +111,10 @@ Now let's start over and try to find the right boundary. This is very similar, s The right boundary is at index 7. The difference between the two boundaries is 7 - 3 = 4, so the number `3` occurs four times in this array. -Each binary search took 4 steps, so in total this algorithm took 8 steps. Not a big gain on an array of only 12 items, but the bigger the array, the more efficient this algorithm becomes. For a sorted array with 1,000,000 items, it only takes 2x20 = 40 steps to count the number of occurrences for any particular value. +Each binary search took 4 steps, so in total this algorithm took 8 steps. Not a big gain on an array of only 12 items, but the bigger the array, the more efficient this algorithm becomes. For a sorted array with 1,000,000 items, it only takes 2 x 20 = 40 steps to count the number of occurrences for any particular value. By the way, if the value you're looking for is not in the array, then `rightBoundary()` and `leftBoundary()` return the same value and so the difference between them is 0. This is an example of how you can modify the basic binary search to solve other algorithmic problems as well. Of course, it does require that the array is sorted. -*Written by Matthijs Hollemans* +*Written for Swift Algorithm Club by Matthijs Hollemans* diff --git a/Deque/README.markdown b/Deque/README.markdown index 87b5d2791..3329adca0 100644 --- a/Deque/README.markdown +++ b/Deque/README.markdown @@ -2,7 +2,7 @@ A double-ended queue. For some reason this is pronounced as "deck". -A regular [queue](../Queue/) adds new elements to the back and removes from the front. The deque also allows enqueuing at the front and dequeuing from the back, and peeking at both ends. +A regular [queue](../Queue/) adds elements to the back and removes from the front. The deque also allows enqueuing at the front and dequeuing from the back, and peeking at both ends. Here is a very basic implementation of a deque in Swift: @@ -52,7 +52,7 @@ public struct Deque { } ``` -This uses an array internally. Enqueuing and dequeuing is simply a matter of adding and removing items from the front or back of the array. +This uses an array internally. Enqueuing and dequeuing are simply a matter of adding and removing items from the front or back of the array. An example of how to use it in a playground: @@ -90,7 +90,7 @@ Likewise, inserting an element at the front of the array is expensive because it [ 5, 2, 3, 4 ] -First, the elements `2`, `3`, and `4`, are move up by one position in the computer's memory, and then the new element `5` is inserted at the position where `2` used to be. +First, the elements `2`, `3`, and `4` are moved up by one position in the computer's memory, and then the new element `5` is inserted at the position where `2` used to be. Why is this not an issue at for `enqueue()` and `dequeueBack()`? Well, these operations are performed at the end of the array. The way resizable arrays are implemented in Swift is by reserving a certain amount of free space at the back. @@ -102,7 +102,7 @@ where the `x`s denote additional positions in the array that are not being used [ 1, 2, 3, 4, 6, x, x ] -And `dequeueBack()` uses `array.removeLast()` to read that item and decrement `array.count` by one. There is no shifting of memory involved here. So operations at the back of the array are fast, **O(1)**. +The `dequeueBack()` function uses `array.removeLast()` to delete that item. This does not shrink the array's memory but only decrements `array.count` by one. There are no expensive memory copies involved here. So operations at the back of the array are fast, **O(1)**. It is possible the array runs out of free spots at the back. In that case, Swift will allocate a new, larger array and copy over all the data. This is an **O(n)** operation but because it only happens once in a while, adding new elements at the end of an array is still **O(1)** on average. @@ -110,7 +110,7 @@ Of course, we can use this same trick at the *beginning* of the array. That will [ x, x, x, 1, 2, 3, 4, x, x, x ] -There is now a chunk of free space at the start of the array, which allows adding or removing elements at the front of the queue to be **O(1)** as well. +There is now also a chunk of free space at the start of the array, which allows adding or removing elements at the front of the queue to be **O(1)** as well. Here is the new version of `Deque`: @@ -217,7 +217,7 @@ Notice how the array has resized itself. There was no room to add the `1`, so Sw | head -> **Note:** You won't see those empty spots at the back when you `print(deque.array)`. This is because Swift hides them from you. Only the ones at the front of the array show up. +> **Note:** You won't see those empty spots at the back of the array when you `print(deque.array)`. This is because Swift hides them from you. Only the ones at the front of the array show up. The `dequeue()` method does the opposite of `enqueueFront()`, it reads the value at `head`, sets the array element back to `nil`, and then moves `head` one position to the right: @@ -232,7 +232,7 @@ The `dequeue()` method does the opposite of `enqueueFront()`, it reads the value } ``` -There is one tiny problem... If you enqueue a lot of objects at the front, you're going to run out of empty spots at the front at some point. When this happens at the back of the array, Swift automatically resizes it. But at the front of the array we have to handle this ourselves with some extra logic in `enqueueFront()`: +There is one tiny problem... If you enqueue a lot of objects at the front, you're going to run out of empty spots at the front at some point. When this happens at the back of the array, Swift automatically resizes it. But at the front of the array we have to handle this situation ourselves, with some extra logic in `enqueueFront()`: ```swift public mutating func enqueueFront(element: T) { @@ -252,11 +252,11 @@ If `head` equals 0, there is no room left at the front. When that happens, we ad > **Note:** We also multiply the capacity by 2 each time this happens, so if your queue grows bigger and bigger, the resizing happens less often. This is also what Swift arrays automatically do at the back. -We have to do something similar for `dequeue()`. If you mostly enqueue a lot of elements at the back and mostly dequeue from the front, then you may end up with an array that looks like this: +We have to do something similar for `dequeue()`. If you mostly enqueue a lot of elements at the back and mostly dequeue from the front, then you may end up with an array that looks as follows: [ x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, 1, 2, 3 ] - | - head + | + head Those empty spots at the front only get used when you call `enqueueFront()`. But if enqueuing objects at the front happens only rarely, this leaves a lot of wasted space. So let's add some code to `dequeue()` to clean this up: @@ -285,7 +285,7 @@ For example, this: | | capacity head -becomes this after trimming: +becomes after trimming: [ x, x, x, x, x, 1, 2, 3 ] | @@ -294,7 +294,7 @@ becomes this after trimming: This way we can strike a balance between fast enqueuing and dequeuing at the front and keeping the memory requirements reasonable. -> **Note:** We don't perform this trimming on very small arrays. It's not worth it for saving just a few bytes of memory. +> **Note:** We don't perform trimming on very small arrays. It's not worth it for saving just a few bytes of memory. ## See also diff --git a/Fixed Size Array/README.markdown b/Fixed Size Array/README.markdown index ec72852a8..8a87f077c 100644 --- a/Fixed Size Array/README.markdown +++ b/Fixed Size Array/README.markdown @@ -2,7 +2,7 @@ Early programming languages didn't have very fancy arrays. You'd create the array with a specific size and from that moment on it would never grow or shrink. Even the standard arrays in C and Objective-C are still of this type. -When you define an array like this, +When you define an array like so, int myArray[10]; @@ -14,7 +14,7 @@ That's your array. It will always be this size. If you need to fit more than 10 To get an array that grows when it gets full you need to use a [dynamic array](https://en.wikipedia.org/wiki/Dynamic_array) object such as `NSMutableArray` in Objective-C or `std::vector` in C++, or a language like Swift whose arrays increase their capacity as needed. -A big downside of the old-style arrays is that they need to be big enough or you run out of space. But if they are too big you're wasting memory. And you need to be careful about security flaws and crashes due to buffer overflows. In summary, fixed-size arrays are not flexible and they leave no room for error. +A major downside of the old-style arrays is that they need to be big enough or you run out of space. But if they are too big you're wasting memory. And you need to be careful about security flaws and crashes due to buffer overflows. In summary, fixed-size arrays are not flexible and they leave no room for error. That said, **I like fixed-size arrays** because they are simple, fast, and predictable. @@ -38,7 +38,7 @@ These two operations have complexity **O(1)**, meaning the time it takes to perf For an array that can grow, appending is more involved: if the array is full, new memory must be allocated and the old contents copied over to the new memory buffer. On average, appending is still an **O(1)** operation, but what goes on under the hood is less predictable. -The expensive operations are inserting and deleting. When you insert an element somewhere that's not at the end, it requires moving up the remainder of the array by one position. That involves a relatively costly memory copy operation: +The expensive operations are inserting and deleting. When you insert an element somewhere that's not at the end, it requires moving up the remainder of the array by one position. That involves a relatively costly memory copy operation. For example, inserting the value `7` in the middle of the array: ![Insert requires a memory copy](Images/insert.png) @@ -48,7 +48,7 @@ Deleting requires a copy the other way around: ![Delete also requires a memory copy](Images/delete.png) -This, by the way, is also true for `NSMutableArray` or Swift arrays. Inserting and deleting are **O(n)** operations -- the larger the array is the more time it takes. +This, by the way, is also true for `NSMutableArray` or Swift arrays. Inserting and deleting are **O(n)** operations -- the larger the array the more time it takes. Fixed-size arrays are a good solution when: @@ -87,7 +87,7 @@ This copies the last element on top of the element you want to remove, and then This is why the array is not sorted. To avoid an expensive copy of a potentially large portion of the array we copy just one element, but that does change the order of the elements. -There are now two copies of element "6" in the array, but what was previously the last element is no longer part of the active array. It's just junk data -- the next time you append an new element, this old version of "6" will be overwritten. +There are now two copies of element `6` in the array, but what was previously the last element is no longer part of the active array. It's just junk data -- the next time you append an new element, this old version of `6` will be overwritten. Under these two constraints -- a limit on the number of elements and an unsorted array -- fixed-size arrays are still perfectly suitable for use in modern software. @@ -138,4 +138,4 @@ var a = FixedSizeArray(maxSize: 10, defaultValue: 0) Note that `removeAtIndex()` overwrites the last element with this `defaultValue` to clean up the "junk" object that gets left behind. Normally it wouldn't matter to leave that duplicate object in the array, but if it's a class or a struct it may have strong references to other objects and it's good boyscout practice to zero those out. -*Written by Matthijs Hollemans* +*Written for Swift Algorithm Club by Matthijs Hollemans* diff --git a/Fizz Buzz/README.markdown b/Fizz Buzz/README.markdown index 066cbe2de..0ce1e2c42 100644 --- a/Fizz Buzz/README.markdown +++ b/Fizz Buzz/README.markdown @@ -18,38 +18,40 @@ The modulus operator returns the remainder after an integer division. Here is an | Division | Division Result | Modulus | Modulus Result | | ------------- | -------------------------- | --------------- | ---------------:| -| 1 `/` 3 | `0` with a remainder of 3 | 1 `%` 3 | `3` | -| 5 `/` 3 | `1` with a remainder of 2 | 5 `%` 3 | `2` | -| 16 `/` 3 | `5` with a remainder of 1 | 16 `%` 3 | `1` | +| 1 / 3 | 0 with a remainder of 3 | 1 % 3 | 3 | +| 5 / 3 | 1 with a remainder of 2 | 5 % 3 | 2 | +| 16 / 3 | 5 with a remainder of 1 | 16 % 3 | 1 | A common approach to determine if a number is even or odd is to use the modulus operator: | Modulus | Result | Swift Code | Swift Code Result | Comment | | ------------- | ---------------:| ------------------------------- | -----------------:| --------------------------------------------- | -| 6 `%` 2 | 0 | `let isEven = number % 2 == 0` | `true` | If a number is divisible by 2 it is `even` | -| 5 `%` 2 | 1 | `let isOdd = number % 2 != 0` | `true` | If a number is not divisible by 2 it is `odd` | +| 6 % 2 | 0 | `let isEven = (number % 2 == 0)` | `true` | If a number is divisible by 2 it is *even* | +| 5 % 2 | 1 | `let isOdd = (number % 2 != 0)` | `true` | If a number is not divisible by 2 it is *odd* | -Now we can use the modulus operator `%` to solve fizz buzz. +## Solving fizz buzz + +Now we can use the modulus operator `%` to solve fizz buzz. Finding numbers divisible by three: | Modulus | Modulus Result | Swift Code | Swift Code Result | | ------- | --------------:| ------------- |------------------:| -| 1 `%` 3 | `1` | `1 % 3 == 0` | `false` | -| 2 `%` 3 | `2` | `2 % 3 == 0` | `false` | -| 3 `%` 3 | `0` | `3 % 3 == 0` | `true` | -| 4 `%` 3 | `1` | `4 % 3 == 0` | `false` | +| 1 % 3 | 1 | `1 % 3 == 0` | `false` | +| 2 % 3 | 2 | `2 % 3 == 0` | `false` | +| 3 % 3 | 0 | `3 % 3 == 0` | `true` | +| 4 % 3 | 1 | `4 % 3 == 0` | `false` | Finding numbers divisible by five: | Modulus | Modulus Result | Swift Code | Swift Code Result | | ------- | --------------:| ------------- |------------------:| -| 1 `%` 5 | `1` | `1 % 5 == 0` | `false` | -| 2 `%` 5 | `2` | `2 % 5 == 0` | `false` | -| 3 `%` 5 | `3` | `3 % 5 == 0` | `false` | -| 4 `%` 5 | `4` | `4 % 5 == 0` | `false` | -| 5 `%` 5 | `0` | `5 % 5 == 0` | `true` | -| 6 `%` 5 | `1` | `6 % 5 == 0` | `false` | +| 1 % 5 | 1 | `1 % 5 == 0` | `false` | +| 2 % 5 | 2 | `2 % 5 == 0` | `false` | +| 3 % 5 | 3 | `3 % 5 == 0` | `false` | +| 4 % 5 | 4 | `4 % 5 == 0` | `false` | +| 5 % 5 | 0 | `5 % 5 == 0` | `true` | +| 6 % 5 | 1 | `6 % 5 == 0` | `false` | ## The code @@ -80,8 +82,13 @@ func fizzBuzz(numberOfTurns: Int) { Put this code in a playground and test it like so: ```swift -fizzBuzz(15) // This will output 1, 2, Fizz, 4, Buzz, Fizz, 7, 8, Fizz, Buzz, 11, Fizz, 13, 14, Fizz Buzz +fizzBuzz(15) ``` + +This will output: + + 1, 2, Fizz, 4, Buzz, Fizz, 7, 8, Fizz, Buzz, 11, Fizz, 13, 14, Fizz Buzz + ## See also [Fizz buzz on Wikipedia](https://en.wikipedia.org/wiki/Fizz_buzz) diff --git a/GCD/README.markdown b/GCD/README.markdown index a7fe799d9..1d20fb9cb 100644 --- a/GCD/README.markdown +++ b/GCD/README.markdown @@ -30,16 +30,16 @@ func gcd(a: Int, _ b: Int) -> Int { Put it in a playground and try it out with these examples: ```swift -gcd(52, 39) // 13 -gcd(228, 36) // 12 -gcd(51357, 3819) // 57 +gcd(52, 39) // 13 +gcd(228, 36) // 12 +gcd(51357, 3819) // 57 ``` Let's step through the third example: gcd(51357, 3819) -According to Euclid's rule, this is equivalent to: +According to Euclid's rule, this is equivalent to, gcd(3819, 51357 % 3819) = gcd(3819, 1710) @@ -65,7 +65,7 @@ By the way, it's also possible that two numbers have a GCD of 1. They are said t gcd(841, 299) // 1 ``` -Here is a slightly different implementation of Euclid's algorithm. Unlike the first version this doesn't use recursion but only a basic `while` loop. The `max()` and `min()` at the top of the function make sure we always divide the larger number by the smaller one. +Here is a slightly different implementation of Euclid's algorithm. Unlike the first version this doesn't use recursion but only a basic `while` loop. ```swift func gcd(m: Int, _ n: Int) -> Int { @@ -82,6 +82,8 @@ func gcd(m: Int, _ n: Int) -> Int { } ``` +The `max()` and `min()` at the top of the function make sure we always divide the larger number by the smaller one. + ## Least Common Multiple An idea related to the GCD is the *least common multiple* or LCM. diff --git a/Hash Set/README.markdown b/Hash Set/README.markdown index 8dcc891d3..c6616fb42 100644 --- a/Hash Set/README.markdown +++ b/Hash Set/README.markdown @@ -11,7 +11,7 @@ If the following were arrays, they'd all be different. However, they all represe [1, 2, 2, 3, 1] ``` -(Because each element can appear only once, it doesn't matter how often you write it down -- only one of them counts.) +Because each element can appear only once, it doesn't matter how often you write the element down -- only one of them counts. > **Note:** I often prefer to use sets over arrays when I have a collection of objects but don't care what order they are in. Using a set communicates to the programmer that the order of the elements is unimportant. If you're using an array, then you can't assume the same thing. @@ -135,7 +135,7 @@ let union = setA.union(setB) union.allElements() // [5, 6, 2, 3, 1, 4] ``` -As you can see, the union of the two sets contains all of the elements now. The values `3` and `4` appear only once, even though they were in both sets. +As you can see, the union of the two sets contains all of the elements now. The values `3` and `4` still appear only once, even though they were in both sets. The *intersection* of two sets contains only the elements that they have in common. Here is the code: @@ -192,7 +192,7 @@ difference2.allElements() // [5, 6] If you look at the [documentation](http://swiftdoc.org/v2.1/type/Set/) for Swift's own `Set`, you'll notice it has tons more functionality. An obvious extension would be to make `HashSet` conform to `SequenceType` so that you can iterate it with a `for`...`in` loop. -Another thing you could do is replace the `Dictionary` with an actual [hash table](../Hash Table), but one that just stores the keys and doesn't associate them with anything. +Another thing you could do is replace the `Dictionary` with an actual [hash table](../Hash Table), but one that just stores the keys and doesn't associate them with anything. So you wouldn't need the `Bool` values anymore. If you often need to look up whether an element belongs to a set and perform unions, then the [union-find](../Union-Find/) data structure may be more suitable. It uses a tree structure instead of a dictionary to make the find and union operations very efficient. diff --git a/Hash Table/README.markdown b/Hash Table/README.markdown index 5afecabba..02a2c9578 100644 --- a/Hash Table/README.markdown +++ b/Hash Table/README.markdown @@ -4,11 +4,11 @@ A hash table allows you to store and retrieve objects by a "key". Also called dictionary, map, associative array. There are other ways to implement these, such as with a tree or even a plain array, but hash table is the most common. -This should explain why Swift's built-in `Dictionary` type requires that keys conform to the `Hashable` protocol: internally it uses a hash table. +This should explain why Swift's built-in `Dictionary` type requires that keys conform to the `Hashable` protocol: internally it uses a hash table, just like the one you'll learn about here. -## How a hash table works +## How it works -At its most basic, a hash table is nothing more than an array. Initially, this array is empty. When you put a value into the hash table, it uses the key to calculate an index in the array, like so: +At its most basic, a hash table is nothing more than an array. Initially, this array is empty. When you put a value into the hash table under a certain key, it uses that key to calculate an index in the array, like so: ```swift hashTable["firstName"] = "Steve" @@ -68,11 +68,11 @@ Using hashes in this manner is what makes the dictionary so efficient: to find a ## Avoiding collisions -There is one problem: because we take the modulo of the hash value with the size of the array, it can happen than two or more keys get assigned the same array index. This is called a collision. +There is one problem: because we take the modulo of the hash value with the size of the array, it can happen that two or more keys get assigned the same array index. This is called a collision. One way to avoid collisions is to have a very large array. That reduces the likelihood of two keys mapping to the same index. Another trick is to use a prime number for the array size. However, collisions are bound to occur so you need some way to handle them. -Because our table is so small it's easy to show a collision. For example, the array index for the key `"lastName"` is also 3. +Because our table is so small it's easy to show a collision. For example, the array index for the key `"lastName"` is also 3. That's a problem, as we don't want to overwrite the value that's already at this array index. There are a few ways to handle collisions. A common one is to use chaining. The array now looks as follows: @@ -91,7 +91,7 @@ There are a few ways to handle collisions. A common one is to use chaining. The +-----+ ``` -Keys are not stored directly in the array. Instead, each element in the array is really a list of key/value pairs. The array elements are usually called the *buckets* and the lists are called the *chains*. So here we have 5 buckets and two of these buckets have chains. The other three buckets are empty. +With chaining, keys and their values are not stored directly in the array. Instead, each array element is really a list of zero or more key/value pairs. The array elements are usually called the *buckets* and the lists are called the *chains*. So here we have 5 buckets and two of these buckets have chains. The other three buckets are empty. If we now write the following to retrieve an item from the hash table, @@ -99,13 +99,13 @@ If we now write the following to retrieve an item from the hash table, let x = hashTable["lastName"] ``` -then this first hashes the key `"lastName"` to calculate the array index, which is 3. Bucket 3 has a chain, so we step through that list to find the item with the key `"lastName"`. That is done by comparing the keys, so here that involves a string comparison. The hash table sees that this key belongs to the last item in the chain and returns the corresponding value, `"Jobs"`. +then this first hashes the key `"lastName"` to calculate the array index, which is 3. Bucket 3 has a chain, so we step through that list to find the value with the key `"lastName"`. That is done by comparing the keys, so here that involves a string comparison. The hash table sees that this key belongs to the last item in the chain and returns the corresponding value, `"Jobs"`. -Common ways to implement this chaining mechanism are to use a linked list or another array. Technically speaking the order of the items in the chain doesn't matter, so you also can think of it as a set instead of a list. (Now you can also imagine where the term "bucket" comes from.) +Common ways to implement this chaining mechanism are to use a linked list or another array. Technically speaking the order of the items in the chain doesn't matter, so you also can think of it as a set instead of a list. (Now you can also imagine where the term "bucket" comes from; we just dump all the objects together into the bucket.) -It's important that chains do not become too long or looking up items in the hash table becomes really slow. Ideally, we would have no chains at all but in practice it is impossible to avoid collisions. But you can improve the odds by giving the hash table enough buckets and by using high-quality hash functions. +It's important that chains do not become too long or looking up items in the hash table becomes really slow. Ideally, we would have no chains at all but in practice it is impossible to avoid collisions. You can improve the odds by giving the hash table enough buckets and by using high-quality hash functions. -> **Note:** An alternative to chaining is "open addressing". The idea is this: if an array index is already taken, we put the element in an unused bucket. Of course, this approach has its own upsides and downsides. +> **Note:** An alternative to chaining is "open addressing". The idea is this: if an array index is already taken, we put the element in the next unused bucket. Of course, this approach has its own upsides and downsides. ## The code @@ -129,9 +129,9 @@ public struct HashTable { } ``` -The `HashTable` is a generic container and the two generic types are named `Key` (which must be `Hashable`) and `Value`. We also define two other types: `Element` is a key/value pair for use in a chain and `Bucket` is an array of such `Element`s. +The `HashTable` is a generic container and the two generic types are named `Key` (which must be `Hashable`) and `Value`. We also define two other types: `Element` is a key/value pair for use in a chain and `Bucket` is an array of such `Elements`. -The main array is named `buckets`. It has a fixed size, the so-called capacity, provided bythe `init(capacity)` method. We're also keeping track of how many items have been added to the hash table using the `count` variable. +The main array is named `buckets`. It has a fixed size, the so-called capacity, provided by the `init(capacity)` method. We're also keeping track of how many items have been added to the hash table using the `count` variable. An example of how to create a new hash table object: @@ -197,9 +197,9 @@ This calls three helper functions to do the actual work. Let's take a look at `v } ``` -First it calls `indexForKey()` to convert the key into an array index. That gives us the bucket, but if there were collisions this bucket may be used by more than one key. So `valueForKey()` loops through the chain from that bucket and compares the keys one-by-one. If found, it returns the corresponding value, otherwise it returns `nil`. +First it calls `indexForKey()` to convert the key into an array index. That gives us the bucket number, but if there were collisions this bucket may be used by more than one key. So `valueForKey()` loops through the chain from that bucket and compares the keys one-by-one. If found, it returns the corresponding value, otherwise it returns `nil`. -The code to insert or update an existing element lives in `updateValue(forKey)`. It's a little bit more complicated: +The code to insert a new element or update an existing element lives in `updateValue(forKey)`. It's a little bit more complicated: ```swift public mutating func updateValue(value: Value, forKey key: Key) -> Value? { @@ -243,7 +243,7 @@ Removing is similar in that again it loops through the chain: } ``` -And these are the basic functions of the hash table. They all work the same way: convert the key into an array index using its hash value, then loop through the chain for that bucket and perform the desired operation. +These are the basic functions of the hash table. They all work the same way: convert the key into an array index using its hash value, find the bucket, then loop through that bucket's chain and perform the desired operation. Try this stuff out in a playground. It should work just like a standard Swift `Dictionary`. @@ -255,7 +255,7 @@ The *load factor* of a hash table is the percentage of the capacity that is curr If the hash table is too small and the chains are long, the load factor can become greater than 1. That's not a good idea. -If the load factor becomes too high, say > 75%, you can resize the hash table. Adding the code for this is left as an exercise for the reader. Keep in mind that making the buckets array larger will change the array indices that the keys map to! +If the load factor becomes too high, say > 75%, you can resize the hash table. Adding the code for this is left as an exercise for the reader. Keep in mind that making the buckets array larger will change the array indices that the keys map to! To account for this, you'll have to insert all the elements again after resizing the array. ## Where to go from here? diff --git a/Heap Sort/README.markdown b/Heap Sort/README.markdown index 84f978931..3d8b0f394 100644 --- a/Heap Sort/README.markdown +++ b/Heap Sort/README.markdown @@ -18,16 +18,16 @@ The heap's internal array is then: [ 25, 13, 20, 8, 7, 17, 2, 5, 4 ] -That's hardly what you'd call sorted! But now the sorting process starts: we swap the first element (index *0*) with the last one (index *n-1*) to get: +That's hardly what you'd call sorted! But now the sorting process starts: we swap the first element (index *0*) with the last one at index *n-1*, to get: [ 4, 13, 20, 8, 7, 17, 2, 5, 25 ] * * -Now the new root node, `4`, will be smaller than its children, so we fix up the max-heap up to element to *n-2* using the *shift down* or "heapify" procedure. After repairing the heap, the new root is now the second-largest item in the array: +Now the new root node, `4`, will be smaller than its children, so we fix up the max-heap up to element *n-2* using the *shift down* or "heapify" procedure. After repairing the heap, the new root is now the second-largest item in the array: [20, 13, 17, 8, 7, 4, 2, 5 | 25] -Important: When we fix the heap, we ignore the last item. That now contains the array's maximum value, so it is in its final sorted place already. The `|` bar indicates where the sorted portion of the array begins. We'll leave that part of the array alone from now on. +Important: When we fix the heap, we ignore the last item at index *n-1*. That now contains the array's maximum value, so it is in its final sorted place already. The `|` bar indicates where the sorted portion of the array begins. We'll leave that part of the array alone from now on. Again, we swap the first element with the last one (this time at index *n-2*): @@ -67,7 +67,7 @@ let a1 = h1.sort() Because we need a max-heap to sort from low-to-high, you need to give `Heap` the reverse of the sort function. To sort `<`, the `Heap` object must be created with `>` as the sort function. In other words, sorting from low-to-high creates a max-heap and turns it into a min-heap. -We can write a helper function for that: +We can write a handy helper function for that: ```swift public func heapsort(a: [T], _ sort: (T, T) -> Bool) -> [T] { diff --git a/Heap/README.markdown b/Heap/README.markdown index a51f97636..fb5092fe3 100644 --- a/Heap/README.markdown +++ b/Heap/README.markdown @@ -13,7 +13,7 @@ Common uses for heap: There are two kinds of heaps: a *max-heap* and a *min-heap*. They are identical, except that the order in which they store the tree nodes is opposite. -In a max-heap, parent nodes must always have a greater value than each one of their children. For a min-heap it's the other way around: every parent node has a smaller value than its child nodes. This is called the "heap property" and it is true for every single node in the tree. +In a max-heap, parent nodes must always have a greater value than each of their children. For a min-heap it's the other way around: every parent node has a smaller value than its child nodes. This is called the "heap property" and it is true for every single node in the tree. An example: @@ -21,19 +21,19 @@ An example: This is a max-heap because every parent node is greater than its children. `(10)` is greater than `(7)` and `(2)`. `(7)` is greater than `(5)` and `(1)`. -As a result of this heap property, a max-heap always stores its largest item at the root of the tree. For a min-heap, the root is always the smallest item in the tree. That is very useful because heaps are often used as a [priority queue](../Priority Queue/) where you want to quickly access the most important element. +As a result of this heap property, a max-heap always stores its largest item at the root of the tree. For a min-heap, the root is always the smallest item in the tree. That is very useful because heaps are often used as a [priority queue](../Priority Queue/) where you want to quickly access the "most important" element. -Note that you can't really say anything else about the sort order of the heap. For example, in a max-heap the maximum element is always at index 0 but the minimum element isn’t necessarily the last one -- the only guarantee you have is that it is one of the leaf nodes, but not which one. +> **Note:** You can't really say anything else about the sort order of the heap. For example, in a max-heap the maximum element is always at index 0 but the minimum element isn’t necessarily the last one -- the only guarantee you have is that it is one of the leaf nodes, but not which one. ## How does heap compare to regular trees? -A heap isn't really intended to be a replacement for a binary search tree. But there are many similarities between the two and also some differences. Here are some of the bigger differences: +A heap isn't intended to be a replacement for a binary search tree. But there are many similarities between the two and also some differences. Here are some of the bigger differences: **Order of the nodes.** In a [binary search tree (BST)](../Binary Search Tree/), the left child must always be smaller than its parent and the right child must be greater. This is not true for a heap. In max-heap both children must be smaller; in a min-heap they both must be greater. **Memory.** Traditional trees take up more memory than just the data they store. You need to allocate additional storage for the node objects and pointers to the left/right child nodes. A heap only uses a plain array for storage and uses no pointers. -**Balancing.** A binary search tree must be balanced so that most operations have **O(log n)** performance. You can either insert and delete your data in a random order or use something like an [AVL tree](../AVL Tree/) or [red-black tree](../Red-Black Tree/). But with heaps we don't actually need the entire tree to be sorted. We just want the heap property to be fulfilled, so balancing isn't an issue. Because of the way the heap is structured, heaps can guarantee **O(log n)** performance. +**Balancing.** A binary search tree must be "balanced" so that most operations have **O(log n)** performance. You can either insert and delete your data in a random order or use something like an [AVL tree](../AVL Tree/) or [red-black tree](../Red-Black Tree/). But with heaps we don't actually need the entire tree to be sorted. We just want the heap property to be fulfilled, and so balancing isn't an issue. Because of the way the heap is structured, heaps can guarantee **O(log n)** performance. **Searching.** Searching a binary tree is really fast -- that's its whole purpose. In a heap, searching is slow. The purpose of a heap is to always put the largest (or smallest) node at the front, and to allow relatively fast inserts and deletes. Searching isn't a top priority. @@ -77,17 +77,15 @@ Recall that in a max-heap, the parent's value is always greater than (or equal t array[parent(i)] >= array[i] ``` -Verify that this heap property holds for the array for the example heap. +Verify that this heap property holds for the array from the example heap. As you can see, these equations let us find the parent or child index for any node without the need for pointers. True, it's slightly more complicated than just dereferencing a pointer but that's the tradeoff: we save memory space but pay with extra computations. Fortunately, the computations are fast and only take **O(1)** time. -It's important to understand this relationship between array index and position in the tree. Here's a slightly larger heap: +It's important to understand this relationship between array index and position in the tree. Here's a slightly larger heap, this tree has 15 nodes divided over four levels: ![Large heap](Images/LargeHeap.png) -This tree has 15 nodes divided over four levels. Note that the numbers in this picture aren't the values of the nodes but the array indices that store the nodes! - -Those array indices correspond to the different levels of the tree like this: +The numbers in this picture aren't the values of the nodes but the array indices that store the nodes! Those array indices correspond to the different levels of the tree like this: ![The heap array](Images/Array.png) @@ -119,7 +117,7 @@ The heap property holds for each node because a parent is always smaller than it In case you are curious, here are a few more formulas that describe certain properties of a heap. You don't need to know these by heart but they come in handy sometimes. Feel free to skip this section! -The *height* of a tree is defined as the number of steps it takes to go from the root node to the lowest leaf node (or more formally: the maximum number of edges between the nodes). A heap of height *h* has *h + 1* levels. +The *height* of a tree is defined as the number of steps it takes to go from the root node to the lowest leaf node. Or more formally: the height is the maximum number of edges between the nodes. A heap of height *h* has *h + 1* levels. This heap has height 3 and therefore has 4 levels: @@ -143,9 +141,9 @@ There are two primitive operations necessary to make sure the heap is a valid ma - `shiftUp()`: If the element is greater (max-heap) or smaller (min-heap) than its parent, it needs to be swapped with the parent. This makes it move up the tree. -- `shiftDown()`. If the element is smaller (max-heap) or greater (min-heap) than its children, it needs to move down the tree. This is also called "heapify". +- `shiftDown()`. If the element is smaller (max-heap) or greater (min-heap) than its children, it needs to move down the tree. This operation is also called "heapify". -Shifting is a recursive procedure that takes **O(log n)** time. +Shifting up or down is a recursive procedure that takes **O(log n)** time. The other operations are built on these primitives. They are: @@ -155,7 +153,7 @@ The other operations are built on these primitives. They are: - `removeAtIndex(index)`: Just like `remove()` except it lets you remove any item from the heap, not just the root. This calls both `shiftDown()`, in case the new element is out-of-order with its children, and `shiftUp()`, in case the element is out-of-order with its parents. -- `replace(index, value)`: Assigns a smaller (min-heap) or larger (max-heap) value to a node. Because this invalidates the heap property, this uses `shiftUp()` to patch things up. (Also called "decrease key" and "increase key".) +- `replace(index, value)`: Assigns a smaller (min-heap) or larger (max-heap) value to a node. Because this invalidates the heap property, it uses `shiftUp()` to patch things up. (Also called "decrease key" and "increase key".) All of the above take time **O(log n)** because shifting up or down is the most expensive thing they do. There are also a few operations that take more time: @@ -205,7 +203,7 @@ The time required for shifting up is proportional to the height of the tree so i ## Removing the root -Let's remove 10 from this tree: +Let's remove `(10)` from this tree: ![The heap before removal](Images/Heap1.png) @@ -217,7 +215,7 @@ When inserting, we put the new value at the end of the array. Here, we'll do the ![The last node goes to the root](Images/Remove2.png) -Let's look at how to **shift-down** `(1)`. To maintain the heap property for this max-heap, we want to the highest number of top. We have 2 candidates for swapping places with: `(7)` and `(2)`. We choose the highest number between these three nodes to be on top. This is `(7)`, so swapping `(1)` and `(7)` gives us the following tree. +Let's look at how to **shift-down** `(1)`. To maintain the heap property for this max-heap, we want to the highest number of top. We have two candidates for swapping places with: `(7)` and `(2)`. We choose the highest number between these three nodes to be on top. That is `(7)`, so swapping `(1)` and `(7)` gives us the following tree. ![The last node goes to the root](Images/Remove3.png) @@ -249,7 +247,7 @@ As you know, removing an element could potentially invalidate the max-heap or mi The last element is the one that we'll return; we'll call `removeLast()` to remove it from the heap. The `(1)` is now out-of-order because it's smaller than its child, `(5)`, but sits higher in the tree. We call `shiftDown()` to repair this. -However, it may also happen that the new element must be shifted up. Consider what happens if you remove `(5)` from the following heap: +However, shifting down is not the only situation we need to handle -- it may also happen that the new element must be shifted up. Consider what happens if you remove `(5)` from the following heap: ![We need to shift up](Images/Remove5.png) @@ -271,7 +269,7 @@ In code it would look like this: We simply call `insert()` for each of the values in the array. Simple enough, but not very efficient. This takes **O(n log n)** time in total because there are **n** elements and each insertion takes **log n** time. -If you didn't skip the math section, you'd have seen that for any heap the elements at array indices *n/2* to *n-1* are the leaves of the tree. We can simply skip those leaves. We only have to process the other nodes, since they are parents with one or more children and therefore may be in the wrong order. +If you didn't gloss over the math section, you'd have seen that for any heap the elements at array indices *n/2* to *n-1* are the leaves of the tree. We can simply skip those leaves. We only have to process the other nodes, since they are parents with one or more children and therefore may be in the wrong order. In code: @@ -288,7 +286,7 @@ Here, `elements` is the heap's own array. We walk backwards through this array, ## Searching the heap -Heaps aren't made for fast searches, but if you want to remove an arbitrary item using `removeAtIndex()` or change the value of an item with `replace()`, then you need to obtain the index of that item somehow. Searching is one way to do this but it's kind of slow. +Heaps aren't made for fast searches, but if you want to remove an arbitrary element using `removeAtIndex()` or change the value of an element with `replace()`, then you need to obtain the index of that element somehow. Searching is one way to do this but it's kind of slow. In a [binary search tree](../Binary Search Tree/) you can depend on the order of the nodes to guarantee a fast search. A heap orders its nodes differently and so a binary search won't work. You'll potentially have to look at every node in the tree. @@ -298,15 +296,13 @@ Let's take our example heap again: If we want to search for the index of node `(1)`, we could just step through the array `[ 10, 7, 2, 5, 1 ]` with a linear search. -But even though the heap property wasn't conceived with searching in mind, we can still take advantage of it. Because we know that in a max-heap a parent node is always larger than its children. - -Let's say we want to see if the heap contains the value `8` (it doesn't). We start at the root `(10)`. This is obviously not what we're looking for, so we recursively look at its left and right child. +But even though the heap property wasn't conceived with searching in mind, we can still take advantage of it. We know that in a max-heap a parent node is always larger than its children, so we can ignore those children (and their children, and so on...) if the parent is already smaller than the value we're looking for. -The left child is `(7)`. That is also not what we want, but since this is a max-heap, we know there's no point in looking at the children of `(7)`. They will always be smaller than `7` and are therefore never equal to `8`. Likewise for the right child, `(2)`. +Let's say we want to see if the heap contains the value `8` (it doesn't). We start at the root `(10)`. This is obviously not what we're looking for, so we recursively look at its left and right child. The left child is `(7)`. That is also not what we want, but since this is a max-heap, we know there's no point in looking at the children of `(7)`. They will always be smaller than `7` and are therefore never equal to `8`. Likewise for the right child, `(2)`. Despite this small optimization, searching is still an **O(n)** operation. -> **Note:** There is away to turn this into **O(1)** by keeping an additional dictionary that maps node values to indices. This may be worth doing if you often need to call `replace()` to change the "priority" of objects in a [priority queue](../Priority Queue/) that's built on a heap. +> **Note:** There is away to turn lookups into a **O(1)** operation by keeping an additional dictionary that maps node values to indices. This may be worth doing if you often need to call `replace()` to change the "priority" of objects in a [priority queue](../Priority Queue/) that's built on a heap. ## The code diff --git a/Huffman Coding/Images/BuildTree.gif b/Huffman Coding/Images/BuildTree.gif index ddfce5c9bd630123123e7ed8dfd2f01c24c237d3..6f5e51523b4a112fcd0bd0a09376034a6374bcb0 100644 GIT binary patch delta 5296 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 delta 7418 zcmds*4Nwzj8pn47i9$#T9>fjur6f>WW%5DztQIYWg1~ubTR|-lKok%H7?dgyXy^Di zbr{}*w4%Zxqn$euWYs{=mRLM{Jxf8PYORO1c0g$nR7NeWc<=5)vSi3Q&PbVS;6K^y z`|R$U-}B^o-{(2lREzfCuSF{s`k(V#85U`2i4ZSaCo~qZSRf8{Vj&3pN60ZTImYko z8q5Fa^G~hVs@!8u?2f48%5fApvF5U+{sG={u$AR+{DkAIG!{$Z3%0X8@DTPfHg)U< z1Y94UY^hAXRwfG|uft=w|B&-7?vc;1Mvy1u3m;$pGK#XmOFW(?VDcEl{XB zs33TF13`AcL-xBkKbUP%81nf~ja_9|J@vc(<1G02vj?rIU)^>7_n7Bcd%vjR3sGfw zbl6KVKi@g4-kRn()Ni%(JzWPfhv^vu!3Ajv*Z1$)`=j%!$a6UA@Ct`+F+9XMecj-`bpB8t|Bc$TQ{x%^^`gpJ&=Y#GFi*I9zD>~O^P~B7 zJ7bsC)U@A!XE^qg_ObG_jh`M3%x!6j9pTojZN^v|n2Dae33G z^XuDAKXfgP8cbEcQ?_~Zd!MLZ{lX%oEkdyRWKrh_)vd3+uesaS{&n`^w2ccilB7Q> z551}AIkPeH>KVQDmc?PEmMeN)R&J||)^kcXYy41;la2gtq@PpP6BZsOs$7GohRsEJ zvH+Rf%@75J;VcKxzTN>;$GwhPfNOCV?JS^o35O$yC-zswH8>sU;{#ZnFF|*i1T0B7 zEMQ-OV=N*>x2ET8BP|iO2E-4Dah_6&3fRP{aFZ;iRqacDe#c`OtY|)(=8I5N_xNw<;#MiN5pCJMO>YfsaER$qz5C_LQs3*0^Z$Z z|CC4j*ch%iKFz}(27V_oFgc}zH+Oi!2gZWygDW|>Jh0C?4xG`sfn`}j(4FkW;>AM} z0pP_=4FdKL@H$fxy9p9tPD)N?jyF*C@IcU@1L#gs|E63tGsNXgcC2MY)_D%7IK7O5 zQv_BV7x4TQ3Llw5;k{I$I$d`*D|u>DIU5$~EpFVYE_w+v3u z#&J>M@6QW=r+dMN(F;C|UZDAC(hFa)Kua0MnM-(p$TocpnFhaIzWgbP@Bb&~n&g&$ z(i!`bjB$Oc6^oWRh`i#<$d^VR^2IDcaFrp6@2_G?;`q*L)8&j@7-xPtoBZ(z@QTqT zDBu^DGyi~|acMKb+)c;qXBM*`BW9WtD9o4YAZ99ad;N_mf8e}&Q_L{%5#+bQ><%hM zv55skfHx8oMaYq5+h_jJiJqC-5ktZos1>haGCe%sotrWLM$rh%C1wcAVXbYh z<|YW!_)~;$+%*#Rzh{mx+3Q(we-`7ooTRL3o}@gJD_tC&wA3tVDFbN*-47J$+{Z@J zU5^<_A0MAZ(ydwzissHxno!Zv%FLpbF`}h`C(&wctWd}{iCo~c$yO+YYqn9R3$;dP zk#0X3$8O2ka|JxLzT;}>l;vhA(;9FlTQ#D{rul%PTyKv$p*)aKCDo4Dqb&?=VcmZn zW{vSQePPoY{#h%!$-XeRiq4g4eNJsp5EY%Aq3uaiVekq zngcZ#$_mOFiVI}}#e;eQ$`*JL!%P!3Q6sQFMBln}}hY5|lJlrxlzj_>B` zk%%3zPu~&}46ARJi0JA1`pBt(fjwQv>S0%bZeNaD?|v+0aEcjh{TdpPj@tNFMD{vO zulunSETP=g&d?&Busga}9F>4&OQ+ZwDrDlZ)csUW;s;q+Nt21)#L`FD>EeAC{ka4y zcQG}gayDrq>GT*W)5h%;bFjw6rgp}u>FW3kS&dlQo+&2qTT{yd71U87KVHVbO9mmRD?QM->-FyIY?u49Ua5XC`)XDoK;ypf1RL dAJC2si@B2ksG8e&lb{iCMUKwxZO;PD{{WtD)|&tT diff --git a/Huffman Coding/Images/Compression.graffle b/Huffman Coding/Images/Compression.graffle index 81920ac70587bc3bac22df5ec0451d6afe321f02..e69912012836df1e0a32835cd86f8845ede3e7dd 100644 GIT binary patch delta 4299 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 delta 4298 zcmV;*5H;`2A=sh70e*bdo8J}f1a0CCh zC%A>47}D>hIfG*1cHp_` zS*MD;JWl1u{YtW3oQSofdrzj4<2EM;Rh7Y~^l0XAa{M@S?$TzZ4SRi_ZI0^ENmq>D zrEiix9LSGBaJ#^mICA{Y&fq+Bdu}=!#+@1WW%g30CED&+S&+~4d7)I`4R8HJ&+Ykz zR^eiQt77SP-|46-Ci0>;v8sDZ7goIPd8_!m-t zh1Tgxf^fS0D<_I>+`k9LY2bPC*6|0^1&`f9-*fKU9mgx29UHE1{ATEv>0&QjPhQ;j z3q>3?Ii_Xf0eKvBhPTp>rswUX3rV35M+13(pwUt?&+{WQKOrXVIdgqkG9ktn$yejq zdlRS=XUk5`k(rizTn!9j=4N8{Flh;aFc*aH8hfHe2_x7t`NPz>PpeM4QMKTue;riM zC@oPkp-!duSw@P5Q|*aoaAsud@8ZFx`*$?zvhyz~aVni|brUk+$e;t$96JhiW=my% zt}>n~r9~FH02mRmYfvPrE`hDD5H+niU7qJ#;l~bcoNjQJ{lTd~IpeAzm+g^qdKT+` zF2A}m%vC;KTYgDLtrz4)GPNWkSJ}g(0f1T<*%qQUA+wl{hbqW;a(p=3vq{-A*>gJgxq{b@H^}#v20#{6 z`7xXyjH4nKj_Xyn36-_vgWHX6a?%Ouvp+sNKc=RNKH;*{kBF-2mwDGLB8jjM+zMW#?DG6W|DN+(tMGym4?e$*y6Ns`<%(S`-nJ zGHND#q}-<4tUOj0J&s`)8e7PYOBm2I{dR|93cqck-QZL;1d z4OrTMNQlz>7(@!H*oUpE`AJ)h+KkgUQiJW5;1&dHN*Rg2ON%T7sv%edjQlAXS)E8y z$;hePxlHn$8WSxAE{buB+3BAUI-^ctb%Z=TlmN6Gy6qdMFT0i4ec?ub7xGI~Ece$* zyF}W{UWc*hTRDg!SCF2|)9Kk$n1WZOS3Q|LtnA|V79J*HdDZcpvF5O&9O~8#sFwp6 zl|_T*F!5T=!!;4{htjrA-G#ZEAIej0$RAB-++`SD<4eaMxbeSEzo&Esa@h$wfuj#G z#F7t#;g$MK8QS@Fd94P2cXZ`lUZcxv-&L=j8z&sd2pJP?;I$meUoTbFQv$D~?*)5r zWpC&?;ja&>vW}hys}Qj{BQi#Wy@i4+7CBqsemkcYQ+QEcn zA_J>V8?hUSi9Y6lWSv`UO}s8fnACdo;YeTvFk-v(2)hm=P+dlFo6St?DrX2V0vNGA zMp!G%8xTybaRkR{0#s+;h!wh0*5>Y5!qZVM8!jZfpqqm(E$ikeFf6WHcV@AVkKC~1 zmH3i?D9sb)aXDI+@S`A-9MEs{0rjd~DY5?~`ofbS2P}UWI^Im546zcQjQKEcAFaia z$4$LtTNWU%N#t2;N8UU?aBV1AoY@H5!e*3M6j_TyX_1m)jgl2m0`vp=w*>uH8TjAs zTwWpLa)+*P5io7CYv3ed?C~rDn;GU?elg&n|301s|L;wWf7Ey^i!g4ET8#P9Nc`E{ zg`|eNP^^FNMtO@sNCDi1jk*i*3f+a4U|>5pZaWjOoxyen+Zk-<Jz=cwjs?YCLlS`FOK? zh}Ox+LIsal`Z4k3GN~lbL_dJ*dD4Py#5iK1wj4#OxkowR8z{ zeUuRT4j`ZePy#5iLAnI1LkY32r-M{b1Rw#BSRW+#3S;^h^W+(A5YA~noWmg%62dtU z&iVdu4qau08#8^|@1si(f8=>ioB<0VzX$SrmdO9MR|-9bAi1+~=ut@Sgyc?uKfr(a zMd6x zF$>}(&BaL=Y^OM{hw3DGbF@B6a3O#aK#2{f#0>jM5Cry9)AkdC9TmZT0{dy1&;eSd z(@5y;v>^tsBD7AmH7BtdZh?y1` z$Y3BhWgt^2~}8La|jrK>>vkV1$qHM2&n`8fPR0A zhtwgKGHgmEXn=k%NYr2ayAa902=){WT&7e(lJ?&*nwLHSA+b zYum@==5JQOR7)-62<&69j~lX&33z|e=1~IGp#)hYC6EA003|k@60^K$0;vH^f6zYZ ztFq8ASZH9OfrYk77TQJ`V#tsqLkzFd9fvLJ2g37bb;luqJ-{Ad5AL|--EsHpSOwIt zfS^p%s{nyOG|&&|w?rTsLJ)HtE4a?y!leG=oDrF`-2t*KNYMl5Vx!JQu}XjEB0`Vx z7N;$F2qO`oA;Ci!;USDaAcOBGQ=Dq)O}wt&Wa`bZh}oJCrj5m@-Ib z1;waI#i%;!0+bl_P@SzK2ws05C6FLM382J=Q({)$CKiyl*|_}#d7F^833epdku~x* z-F4(`BF119XnGaEHmm}$3cxA=tHAQBz|C4#0SiI)e&efv1+f&MAJA`|+56SZvlGre zF66BvAGaac(Z{RuQmuO;(-s(;rbW2DFpjve1TmQ@giWw*n~UOT`xSp&NI%{z_@iv{ zG1@exH-sJJ77P*838v%P!SwPpg8p0t+5&+!#L=GYCdmD$d}E43X9QoWI+sRZmt?VWutzq&Gy(I_0|y^&jW58zCX?F(hq z$noKtzFR%}FYdF;Y<4u}$6^h4?`rO3tl=0Ie6D9W9r|%Se}rx~i<-%KM!HCFH_#%J zlZ}7zUnlMCZ%%)teWyRT2o{h}TNAfo=yv7cEa-falY*twCnNpd9k^HNl&v^TJeb}% zJvo`0<>q(NrMF7(NGZrsI@!txMJ)dRQuZ%`cE`!IVlvW_QRdvsFg^1GIa4c?{^7+1 zYKj}NRoME1Qa@8*hD4I+Qlf?ya`52Hihy>%j47!>*6 z7>jn4nj5@w{bP5KHhr{KS?SD4W!q9I4Nl|+{*-tQP_euhH}k~rso7s>OE-uLjq#-u z1)3FS((h&F^7sS!8{r1uY#_7t<(

f_9n9#={b7JG>75o!?p6rrb-82{2eS2$N(QD**) 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 An*aa+ delta 3940 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 OfFIGv-@DP1lKndv_T6kS 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 **Note:** Instead of using a priority queue, you can iterate through the `tree` array to find the next two smallest nodes, but that makes the compressor quite slow, **O(n^2)**. Using the priority queue, the running time is only **O(n log n)** where **n** is the number of nodes. +> **Note:** Instead of using a priority queue, you can repeatedly iterate through the `tree` array to find the next two smallest nodes, but that makes the compressor quite slow, **O(n^2)**. Using the priority queue, the running time is only **O(n log n)** where **n** is the number of nodes. -> **Note:** Due to the nature of binary trees, if we have *x* leaf nodes we can at most add *x - 1* additional nodes to the tree. Given that at most there will be 256 leaf nodes, the tree will never contain more than 511 nodes total. +> **Fun fact:** Due to the nature of binary trees, if we have *x* leaf nodes we can at most add *x - 1* additional nodes to the tree. Given that at most there will be 256 leaf nodes, the tree will never contain more than 511 nodes total. ## Compression @@ -319,7 +319,7 @@ In a picture: ![How compression works](Images/Compression.png) -Note that, even through the illustration of the tree shows a 0 or 1 for each edge between the nodes, the bit values 0 and 1 aren't actually stored in the tree! The rule is that we write a 1 bit if we take the left branch and a 0 bit if we take the right branch, so just knowing the direction we're going in is enough to determine what bit value to write. +Even though the illustration of the tree shows a 0 or 1 for each edge between the nodes, the bit values 0 and 1 aren't actually stored in the tree! The rule is that we write a 1 bit if we take the left branch and a 0 bit if we take the right branch, so just knowing the direction we're going in is enough to determine what bit value to write. You use the `compressData()` method as follows: @@ -412,6 +412,6 @@ You can see how this works in more detail in the Playground. [Huffman coding at Wikipedia](https://en.wikipedia.org/wiki/Huffman_coding) -The code is based on Al Stevens' C Programming column from Dr.Dobb's Magazine, February 1991 and October 1992. +The code is loosely based on Al Stevens' C Programming column from Dr.Dobb's Magazine, February 1991 and October 1992. *Written for Swift Algorithm Club by Matthijs Hollemans* diff --git a/Insertion Sort/README.markdown b/Insertion Sort/README.markdown index ea39f5dad..b67541669 100644 --- a/Insertion Sort/README.markdown +++ b/Insertion Sort/README.markdown @@ -13,7 +13,7 @@ You are given an array of numbers and need to put them in the right order. The i That's why this is called an "insertion" sort, because you take a number from the pile and insert it in the array in its proper sorted position. -### An example +## An example Let's say the numbers to sort are `[ 8, 3, 5, 4, 6 ]`. This is our unsorted pile. @@ -25,7 +25,7 @@ Pick the next number from the pile, `5`, and insert it into the sorted array. It Repeat this process until the pile is empty. -### In-place sort +## In-place sort The above explanation makes it seem like you need two arrays: one for the unsorted pile and one that contains the numbers in sorted order. @@ -54,7 +54,7 @@ This is how the content of the array changes during the sort: In each step, the `|` bar moves up one position. As you can see, the beginning of the array up to the `|` is always sorted. The pile shrinks by one and the sorted portion grows by one, until the pile is empty and there are no more unsorted numbers left. -### How to insert +## How to insert At each step you pick the top-most number from the unsorted pile and insert it into the sorted portion of the array. You must put that number in the proper place so that the beginning of the array remains sorted. How does that work? @@ -85,9 +85,9 @@ Again, look at the previous element. Is `3` greater than `4`? No, it is not. Tha This was a description of the inner loop of the insertion sort algorithm, which you'll see in the next section. It inserts the number from the top of the pile into the sorted portion by swapping numbers. -### The code +## The code -Here is a simple implementation of insertion sort in Swift: +Here is an implementation of insertion sort in Swift: ```swift func insertionSort(array: [Int]) -> [Int] { @@ -118,9 +118,9 @@ Here is how the code works. 3. The inner loop looks at the element at position `x`. This is the number at the top of the pile, and it may be smaller than any of the previous elements. The inner loop steps backwards through the sorted array; every time it finds a previous number that is larger, it swaps them. When the inner loop completes, the beginning of the array is sorted again, and the sorted portion has grown by one element. -Note: The outer loop starts at index 1, not 0. Moving the very first element from the pile to the sorted portion doesn't actually change anything, so we might as well skip it. +> **Note:** The outer loop starts at index 1, not 0. Moving the very first element from the pile to the sorted portion doesn't actually change anything, so we might as well skip it. -### No more swaps +## No more swaps The above version of insertion sort works fine, but it can be made a tiny bit faster by removing the call to `swap()`. @@ -168,7 +168,7 @@ func insertionSort(array: [Int]) -> [Int] { The line at `//1` is what shifts up the previous elements by one position. At the end of the inner loop, `y` is the destination index for the new number in the sorted portion, and the line at `//2` copies this number into place. -### Making it generic +## Making it generic It would be nice to sort other things than just numbers. We can make the datatype of the array generic and use a user-supplied function (or closure) to perform the less-than comparison. This only requires two changes to the code. @@ -188,7 +188,7 @@ The only other change is in the inner loop, which now becomes: while y > 0 && isOrderedBefore(temp, a[y - 1]) { ``` -Instead of writing `temp < a[y - 1]`, we now call the `isOrderedBefore()` function. It does the exact same thing, except we can now compare any kind of object, not just numbers. +Instead of writing `temp < a[y - 1]`, we call the `isOrderedBefore()` function. It does the exact same thing, except we can now compare any kind of object, not just numbers. To test this in a playground, do: @@ -218,7 +218,7 @@ The closure tells `insertionSort()` to sort on the `priority` property of the ob Insertion sort is a *stable* sort. A sort is stable when elements that have identical sort keys remain in the same relative order after sorting. This is not important for simple values such as numbers or strings, but it is important when sorting more complex objects. In the example above, if two objects have the same `priority`, regardless of the values of their other properties, those two objects don't get swapped around. -### Performance +## Performance Insertion sort is really fast if the array is already sorted. That sounds obvious, but this is not true for all search algorithms. In practice, a lot of data will already be largely -- if not entirely -- sorted and insertion sort works quite well in that case. @@ -228,8 +228,8 @@ Insertion sort is actually very fast for sorting small arrays. Some standard lib I did a quick test comparing our `insertionSort()` with Swift's built-in `sort()`. On arrays of about 100 items or so, the difference in speed is tiny. However, as your input becomes larger, **O(n^2)** quickly starts to perform a lot worse than **O(n log n)** and insertion sort just can't keep up. -### See also +## See also -See also [Wikipedia](https://en.wikipedia.org/wiki/Insertion_sort). +[Insertion sort on Wikipedia](https://en.wikipedia.org/wiki/Insertion_sort) -*Written by Matthijs Hollemans* +*Written for Swift Algorithm Club by Matthijs Hollemans* diff --git a/Kth Largest Element/README.markdown b/Kth Largest Element/README.markdown index 04d10ad99..d50d691a1 100644 --- a/Kth Largest Element/README.markdown +++ b/Kth Largest Element/README.markdown @@ -6,21 +6,21 @@ For example, the 1-st largest element is the maximum value that occurs in the ar ## The naive solution -The following solution is semi-naive. Its time complexity is **O(n log n)** since it first sorts the array, and uses an additional **O(n)** space. Better solutions using heaps exist that run in **O(n)** time. +The following solution is semi-naive. Its time complexity is **O(n log n)** since it first sorts the array, and therefore also uses additional **O(n)** space. ```swift func kthLargest(a: [Int], k: Int) -> Int? { let len = a.count - - if k <= 0 || k > len || len < 1 { return nil } - - let sorted = a.sort() - - return sorted[len - k] + if k > 0 && k <= len { + let sorted = a.sort() + return sorted[len - k] + } else { + return nil + } } ``` -The `kthLargest()` function takes two parameters: the array `a` consisting of integers, and `k`. It returns the k-th largest element. +The `kthLargest()` function takes two parameters: the array `a` consisting of integers, and `k`. It returns the *k*-th largest element. Let's take a look at an example and run through the algorithm to see how it works. Given `k = 4` and the array: @@ -48,9 +48,9 @@ There is a clever algorithm that combines the ideas of [binary search](../Binary Recall that binary search splits the array in half over and over again, to quickly narrow in on the value you're searching for. That's what we'll do here too. -Quicksort also splits up arrays. It uses partitioning to move all smaller values to the left of the pivot and all greater values to the right. After partitioning around a certain pivot, that pivot will already be in its final, sorted position. We can use that to our advantage here. +Quicksort also splits up arrays. It uses partitioning to move all smaller values to the left of the pivot and all greater values to the right. After partitioning around a certain pivot, that pivot value will already be in its final, sorted position. We can use that to our advantage here. -We choose a random pivot, partition the array around that pivot, and then act like a binary search and only continue in the left or right partition. This repeats until we've found a pivot that happens to end up in the *k*-th position. +Here's how it works: We choose a random pivot, partition the array around that pivot, then act like a binary search and only continue in the left or right partition. This repeats until we've found a pivot that happens to end up in the *k*-th position. Let's look at the original example again. We're looking for the 4-th largest element in this array: @@ -58,12 +58,12 @@ Let's look at the original example again. We're looking for the 4-th largest ele The algorithm is a bit easier to follow if we look for the k-th *smallest* item instead, so let's take `k = 4` and look for the 4-th smallest element. -Note that we don't have to sort the array first. We pick a random pivot, let's say `11` and partition the array around that. We might end up with something like this: +Note that we don't have to sort the array first. We pick one of the elements at random to be the pivot, let's say `11`, and partition the array around that. We might end up with something like this: [ 7, 9, -1, 0, 6, 11, 92, 23 ] <------ smaller larger --> -As you can see, all values smaller than `11` are on the left; all values larger are on the right. The pivot value is now in its final place. The index of the pivot is 5, so the 4-th smallest element must be in the left partition somewhere. We can ignore the rest of the array from now on: +As you can see, all values smaller than `11` are on the left; all values larger are on the right. The pivot value `11` is now in its final place. The index of the pivot is 5, so the 4-th smallest element must be in the left partition somewhere. We can ignore the rest of the array from now on: [ 7, 9, -1, 0, 6, x, x, x ] @@ -126,15 +126,15 @@ public func randomizedSelect(array: [T], order k: Int) -> T { } ``` -To keep things readable, it splits up the functionality into three inner functions: +To keep things readable, the functionality is split into three inner functions: - `randomPivot()` picks a random number and puts it at the end of the current partition (this is a requirement of the Lomuto partitioning scheme, see the discussion on [quicksort](../Quicksort/) for more details). - `randomizedPartition()` is Lomuto's partitioning scheme from quicksort. When this completes, the randomly chosen pivot is in its final sorted position in the array. It returns the array index of the pivot. -- `randomizedSelect()` does all the hard work. It first calls the partitioning function and then decides what to do next. If the index of the pivot is equal to the k-th number we're looking for, we're done. If `k` is less than the pivot index, it must be in the left partition and we'll recursively try again there. Likewise for when the k-th number must be in the right partition. +- `randomizedSelect()` does all the hard work. It first calls the partitioning function and then decides what to do next. If the index of the pivot is equal to the *k*-th number we're looking for, we're done. If `k` is less than the pivot index, it must be in the left partition and we'll recursively try again there. Likewise for when the *k*-th number must be in the right partition. -Pretty cool, huh? +Pretty cool, huh? Normally quicksort is an **O(n log n)** algorithm, but because we only partition smaller and smaller slices of the array, the running time of `randomizedSelect()` works out to **O(n)**. > **Note:** This function calculates the *k*-th smallest item in the array, where *k* starts at 0. If you want the *k*-th largest item, call it with `a.count - k`. diff --git a/Kth Largest Element/kthLargest.playground/Contents.swift b/Kth Largest Element/kthLargest.playground/Contents.swift index 9cac62f4e..7f97bb271 100644 --- a/Kth Largest Element/kthLargest.playground/Contents.swift +++ b/Kth Largest Element/kthLargest.playground/Contents.swift @@ -2,13 +2,14 @@ func kthLargest(a: [Int], k: Int) -> Int? { let len = a.count - if k <= 0 || k > len || len < 1 { return nil } - - let sorted = a.sort() - return sorted[len - k] + if k > 0 && k <= len { + let sorted = a.sort() + return sorted[len - k] + } else { + return nil + } } - let a = [5, 1, 3, 2, 7, 6, 4] kthLargest(a, k: 0) diff --git a/Kth Largest Element/kthLargest.swift b/Kth Largest Element/kthLargest.swift index 69c03b76f..5bf781932 100644 --- a/Kth Largest Element/kthLargest.swift +++ b/Kth Largest Element/kthLargest.swift @@ -1,17 +1,20 @@ import Foundation /* - * Returns the k-th largest value inside of an array a. - * This is an O(n log n) solution since we sort the array. - */ + Returns the k-th largest value inside of an array a. + This is an O(n log n) solution since we sort the array. +*/ func kthLargest(a: [Int], k: Int) -> Int? { let len = a.count - if k <= 0 || k > len || len < 1 { return nil } - - let sorted = a.sort() - return sorted[len - k] + if k > 0 && k <= len { + let sorted = a.sort() + return sorted[len - k] + } else { + return nil + } } + // MARK: - Randomized selection /* Returns a random integer in the range min...max, inclusive. */ diff --git a/Linear Search/README.markdown b/Linear Search/README.markdown index 178a1dd09..115dd7ee2 100644 --- a/Linear Search/README.markdown +++ b/Linear Search/README.markdown @@ -2,15 +2,17 @@ Goal: Find a particular value in an array. -We have an array of generic objects and we iterate over all the objects by comparing each one to the object we're looking for. If the two objects are equal, we stop and we return the index of the object in the array. If not, we continue to look for the next object as long as we have objects in the array. +We have an array of generic objects. With linear search, we iterate over all the objects in the array and compare each one to the object we're looking for. If the two objects are equal, we stop and return the current array index. If not, we continue to look for the next object as long as we have objects in the array. -### An example +## An example Let's say we have an array of numbers `[5, 2, 4, 7]` and we want to check if the array contains the number `2`. -We start by comparing the first number in the array, `5` with the number we're looking for, `2`. They are obviously not the same number and so we continue by taking the second element in the array. We compare the number `2` to our number `2` and we notice that they are the same. We stop our iteration and we return `1`, which is the index of the number `2` in the array. +We start by comparing the first number in the array, `5`, to the number we're looking for, `2`. They are obviously not the same, and so we continue to the next array element. -### The code +We compare the number `2` from the array to our number `2` and notice they are equal. Now we can stop our iteration and return 1, which is the index of the number `2` in the array. + +## The code Here is a simple implementation of linear search in Swift: @@ -30,14 +32,14 @@ let array = [5, 2, 4, 7] linearSearch(array, 2) // This will return 1 ``` -### Performance +## Performance -Linear search runs at **O(n)**. It compares the object we are looking for with each object in the array and so the time it takes is proportional to the array length. +Linear search runs at **O(n)**. It compares the object we are looking for with each object in the array and so the time it takes is proportional to the array length. In the worst case, we need to look at all the elements in the array. -The best-case performance is **O(1)** but this case is rare because the object we're looking for has to be positioned at the start of the array to be immediately found. +The best-case performance is **O(1)** but this case is rare because the object we're looking for has to be positioned at the start of the array to be immediately found. You might get lucky, but most of the time you won't. On average, linear search needs to look at half the objects in the array. -### See also +## See also -See also [Wikipedia](https://en.wikipedia.org/wiki/Linear_search). +[Linear search on Wikipedia](https://en.wikipedia.org/wiki/Linear_search) *Written by [Patrick Balestra](http://www.github.com/BalestraPatrick)* diff --git a/Linked List/README.markdown b/Linked List/README.markdown index 0ce6c57fa..d37749acd 100644 --- a/Linked List/README.markdown +++ b/Linked List/README.markdown @@ -1,6 +1,6 @@ # Linked List -A linked list is a sequence of data items, just like an array. But where an array allocates a big block of memory and then divides this into different parts to store the objects, the elements in a linked list are totally separate objects in memory and are connected through links: +A linked list is a sequence of data items, just like an array. But where an array allocates a big block of memory to store the objects, the elements in a linked list are totally separate objects in memory and are connected through links: +--------+ +--------+ +--------+ +--------+ | | | | | | | | @@ -38,15 +38,17 @@ This means that when you're dealing with a linked list, you should insert new it ## Singly vs doubly linked lists -A singly linked list uses less memory than a doubly linked list because it doesn't need to store all those `previous` pointers. +A singly linked list uses a little less memory than a doubly linked list because it doesn't need to store all those `previous` pointers. -But if you have a node and you need to find its previous node, you're screwed. You have to start back at the head of the list and iterate through the entire list until you get to the right node. +But if you have a node and you need to find its previous node, you're screwed. You have to start at the head of the list and iterate through the entire list until you get to the right node. For many tasks, a doubly linked list makes things easier. ## Why use a linked list? -An example of where to use a linked list is when you need a [queue](../Queue/). With an array, removing elements from the front of the queue is slow because it needs to shift down all the other elements in memory. But with a linked list it's just a matter of changing `head` to point to the second element. Much faster. +A typical example of where to use a linked list is when you need a [queue](../Queue/). With an array, removing elements from the front of the queue is slow because it needs to shift down all the other elements in memory. But with a linked list it's just a matter of changing `head` to point to the second element. Much faster. + +But to be honest, you hardly ever need to write your own linked list these days. Still, it's useful to understand how they work; the principle of linking objects together is also used with [trees](../Tree/) and [graphs](../Graph/). ## The code @@ -86,7 +88,7 @@ public class LinkedList { } ``` -Ideally, I'd like to put the `LinkedListNode` class inside `LinkedList` but Swift 2 doesn't allow generic types to have nested types. Instead we're using a typealias so inside `LinkedList` we can write the shorter `Node` instead of `LinkedListNode`. +Ideally, I'd like to put the `LinkedListNode` class inside `LinkedList` but Swift currently doesn't allow generic types to have nested types. Instead we're using a typealias so inside `LinkedList` we can write the shorter `Node` instead of `LinkedListNode`. This linked list only has a `head` pointer, not a tail. Adding a tail pointer is left as an exercise for the reader. (I'll point out which functions would be different if we also had a tail pointer.) @@ -329,13 +331,13 @@ Now that we have this helper function, we can write the method for inserting nod } ``` -Some notes about this method: +Some remarks about this method: 1. First, we need to find where to insert this node. After calling the helper method, `prev` points to the previous node and `next` is the node currently at the given index. We'll insert the new node in between these two. Note that `prev` can be nil (index is 0), `next` can be nil (index equals size of the list), or both can be nil if the list is empty. 2. Create the new node and connect the `previous` and `next` pointers. Because the local `prev` and `next` variables are optionals and may be nil, so we use optional chaining here. -3. If the new node is being inserted at the front of the list, we need to update the `head` pointer. Note: If the list had a tail pointer, you'd also need to update that pointer here if `next == nil`, because that means the last element has changed. +3. If the new node is being inserted at the front of the list, we need to update the `head` pointer. (Note: If the list had a tail pointer, you'd also need to update that pointer here if `next == nil`, because that means the last element has changed.) Try it out: @@ -419,7 +421,7 @@ list.removeAtIndex(0) // "Swift" list.count // 0 ``` -> **Note:** For a singly linked list, it's slightly more complicated. You can't just use `last` to find the end of the list because you also need a reference to the second-to-last node. You'd need to use the `nodesBeforeAndAfter()` helper method instead. If you're using a tail pointer, then `removeLast()` is really quick, but you do need to remember to make `tail` point to the previous node. +> **Note:** For a singly linked list, removing the last node is slightly more complicated. You can't just use `last` to find the end of the list because you also need a reference to the second-to-last node. Instead, use the `nodesBeforeAndAfter()` helper method. If the list has a tail pointer, then `removeLast()` is really quick, but you do need to remember to make `tail` point to the previous node. There's a few other fun things we can do with our `LinkedList` class. It's handy to have some sort of readable debug output: @@ -520,7 +522,7 @@ Exercise for the reader: These implementations of `map()` and `filter()` aren't ## An alternative approach -The version of `LinkedList` you've seen so far uses nodes that are classes and therefore use reference semantics. Nothing wrong with that, but that does make them a bit more heavyweight than Swift's other collections such as `Array` and `Dictionary`. +The version of `LinkedList` you've seen so far uses nodes that are classes and therefore have reference semantics. Nothing wrong with that, but that does make them a bit more heavyweight than Swift's other collections such as `Array` and `Dictionary`. It is possible to implement a linked list with value semantics using an enum. That would look somewhat like this: @@ -541,6 +543,6 @@ Linked lists are flexible but many operations are **O(n)**. When performing operations on a linked list, you always need to be careful to update the relevant `next` and `previous` pointers, and possibly also the `head` and `tail` pointers. If you mess this up, your list will no longer be correct and your program will likely crash at some point. Be careful! -When processing lists, you can often use recursion: process the first element and then recursively call the operation on the rest of the list. You’re done when there is no next element. This is why linked lists are the foundation of functional programming languages such as LISP. +When processing lists, you can often use recursion: process the first element and then recursively call the function again on the rest of the list. You’re done when there is no next element. This is why linked lists are the foundation of functional programming languages such as LISP. *Written for Swift Algorithm Club by Matthijs Hollemans* diff --git a/Merge Sort/README.markdown b/Merge Sort/README.markdown index 190f76a34..023e18b32 100644 --- a/Merge Sort/README.markdown +++ b/Merge Sort/README.markdown @@ -4,28 +4,28 @@ Goal: Sort an array from low to high (or high to low) Invented in 1945 by John von Neumann, merge sort is a fairly efficient sorting algorithm with a best, worst, and average time complexity of **O(n log n)**. -The idea behind merge sort is to **divide and conquer**. To divide a big problem into smaller problems and solving many small problems instead of solving a big one. I think of merge sort as **split first** and **merge after**. +The idea behind merge sort is to **divide and conquer**: to divide a big problem into smaller problems and solving many small problems instead of solving a big one. I think of merge sort as **split first** and **merge after**. Assume you're given an array of *n* numbers and you need to put them in the right order. The merge sort algorithm works as follows: - Put the numbers in a pile. The pile is unsorted. - Split the pile into 2. Now you have **two unsorted piles** of numbers. -- Keep splitting the resulting piles until you can't anymore. In the end, you will have *n* piles with 1 number in each pile. -- Begin to **merge** the piles together by sequentially pairing a pile with another pile. During each merge, you want to sort the contents in order. +- Keep splitting the resulting piles until you can't split anymore. In the end, you will have *n* piles with 1 number in each pile. +- Begin to **merge** the piles together by sequentially pairing a pile with another pile. During each merge, you put the contents in sorted order. This is fairly easy because each individual pile is already sorted. ## An example ### Splitting -Let's say the numbers to sort are `[2, 1, 5, 4, 9]`. This is your unsorted pile. Our goal is to keep splitting the pile until you can't anymore. +Let's say the numbers to sort are `[2, 1, 5, 4, 9]`. This is your unsorted pile. The goal is to keep splitting the pile until you can't split anymore. -Split the array into two halves: `[2, 1,]` and `[5, 4, 9]`. Can you keep splitting them? Yes you can! +First, split the array into two halves: `[2, 1,]` and `[5, 4, 9]`. Can you keep splitting them? Yes you can! Focus on the left pile. `[2, 1]` will split into `[2]` and `[1]`. Can you keep splitting them? No. Time to check the other pile. -`[5, 4, 9]` splits to `[5]` and `[4, 9]`. Unsurprisingly, `[5]` can't split into anymore, but `[4, 9]` splits into `[4]` and `[9]`. +`[5, 4, 9]` splits to `[5]` and `[4, 9]`. Unsurprisingly, `[5]` can't be split anymore, but `[4, 9]` splits into `[4]` and `[9]`. -The splitting process ends with the following piles: `[2]` `[1]` `[5]` `[4]` `[9]` +The splitting process ends with the following piles: `[2]` `[1]` `[5]` `[4]` `[9]`. Notice that each pile consists of just one element. ### Merging @@ -35,7 +35,7 @@ Given the piles `[2]` `[1]` `[5]` `[4]` `[9]`, the first pass will result in `[1 The next pass will merge `[1, 2]` and `[4, 5]` together. This results in `[1, 2, 4, 5]`, with the `[9]` left out again since it's the odd one out. -Since you're left with only two piles, `[9]` finally gets its chance to merge, resulting in the sorted array `[1, 2, 4, 5, 9]`. +You're left with only two piles and `[9]` finally gets its chance to merge, resulting in the sorted array `[1, 2, 4, 5, 9]`. ## Top-down implementation @@ -61,9 +61,9 @@ A step-by-step explanation of how the code works: 2. Find the middle index. -3. Using the middle index from the previous step, recursively split the left side of the resulting arrays. +3. Using the middle index from the previous step, recursively split the left side of the array. -4. Using the middle index, recursively split the right side of the resulting arrays. +4. Also recursively split the right side of the array. 5. Finally, merge all the values together, making sure that it's always sorted. @@ -119,7 +119,7 @@ This method may look scary but it is quite straightforward: 4. If control exits from the previous while loop, it means that either `leftPile` or `rightPile` has its contents completely merged into the `orderedPile`. At this point, you no longer need to do comparisons. Just append the rest of the contents of the other array until there's no more to append. -As an example of how `merge()` works, suppose that we have the following piles: `leftPile = [1, 7, 8]` and `rightPile = [3, 6, 9]`. Note that each of these piles is individually sorted already. These are merged into one larger sorted pile in the following steps: +As an example of how `merge()` works, suppose that we have the following piles: `leftPile = [1, 7, 8]` and `rightPile = [3, 6, 9]`. Note that each of these piles is individually sorted already -- that is always true with merge sort. These are merged into one larger sorted pile in the following steps: leftPile rightPile orderedPile [ 1, 7, 8 ] [ 3, 6, 9 ] [ ] @@ -218,7 +218,7 @@ Notable points: 1. Merge sort needs a temporary working array because you can't merge the left and right piles and at the same time overwrite their contents. But allocating a new array for each merge is wasteful. Therefore, we're using two working arrays and we'll switch between them using the value of `d`, which is either 0 or 1. The array `z[d]` is used for reading, `z[1 - d]` is used for writing. This is called *double-buffering*. -2. Conceptually, the bottom-up version works the same way as the top-down version. First, it merges small piles of 1 element each, then it merges piles of 2 elements each, then piles of 4 elements each, and so on. The size of the pile is given by `width`. Initially, this is `1` but at the end of each loop iteration we multiply it by 2. So this outer loop determines the size of the piles being merged. And in each step, the subarrays to merge become larger. +2. Conceptually, the bottom-up version works the same way as the top-down version. First, it merges small piles of 1 element each, then it merges piles of 2 elements each, then piles of 4 elements each, and so on. The size of the pile is given by `width`. Initially, `width` is `1` but at the end of each loop iteration we multiply it by 2. So this outer loop determines the size of the piles being merged. And in each step, the subarrays to merge become larger. 3. The inner loop steps through the piles and merges each pair of piles into a larger one. The result is written in the array given by `z[1 - d]`. @@ -237,7 +237,7 @@ mergeSortBottomUp(array, <) // [1, 2, 4, 5, 9] ## Performance -The speed of merge sort is dependent on the size of the array it needs to sort. +The speed of merge sort is dependent on the size of the array it needs to sort. The larger the array, the more work it needs to do. Whether or not the initial array is sorted already doesn't affect the speed of merge sort since you'll be doing the same amount splits and comparisons regardless of the initial order of the elements. @@ -249,6 +249,6 @@ Most implementations of merge sort produce a **stable** sort. This means that ar ## See also -See also [Wikipedia](https://en.wikipedia.org/wiki/Merge_sort) +[Merge sort on Wikipedia](https://en.wikipedia.org/wiki/Merge_sort) *Written by Kelvin Lau. Additions by Matthijs Hollemans.* diff --git a/Monty Hall Problem/README.markdown b/Monty Hall Problem/README.markdown index 81004410e..f096a3a7a 100644 --- a/Monty Hall Problem/README.markdown +++ b/Monty Hall Problem/README.markdown @@ -8,7 +8,7 @@ Now Monty gives you the opportunity to change your mind. Should you stick with y You'd think that changing your answer wouldn't improve your chances... but it does! -This is a very nonintuitive result. Maybe you have trouble believing this is true. Don't worry, when this problem was first proposed many mathematicians didn't believe it either, so you're in good company. +This is a very nonintuitive result. Maybe you have trouble believing this is true. Don't worry, when this problem was first proposed many professional mathematicians didn't believe it either, so you're in good company. There's a simple way to verify this claim: we can write a program to test it out! We should be able to show who wins more often by playing the game a large number of times. @@ -65,7 +65,7 @@ Here's why: When you first make a choice, your chances of picking the prize are After Monty opens one of the doors, this gives you new information. However, it doesn't change the probability of your original choice being the winner. That chance remains 33% because you made that choice when you didn't know yet what was behind this open door. -Since probabilities always need to add up to 100%, the chance that the prize is behind the other door is now 100 - 33 = 67%. So, as strange as it may sound, you're better of switching doors! +Since probabilities always need to add up to 100%, the chance that the prize is behind the other door is now 100 - 33 = 67%. So, as strange as it may sound, you're better off switching doors! This is hard to wrap your head around, but easily shown using a simulation that runs a significant number of times. Probability is weird. diff --git a/Ordered Array/README.markdown b/Ordered Array/README.markdown index d258024d3..f64e55057 100644 --- a/Ordered Array/README.markdown +++ b/Ordered Array/README.markdown @@ -63,7 +63,7 @@ What remains is the `insert()` function. Here is an initial stab at it: } ``` -The helper function `findInsertionPoint()` simply loops through the entire array, looking for the right place to insert the new element. +The helper function `findInsertionPoint()` simply iterates through the entire array, looking for the right place to insert the new element. > **Note:** Quite conveniently, `array.insert(... atIndex: array.count)` adds the new object to the end of the array, so if no suitable insertion point was found we can simply return `array.count` as the index. @@ -83,7 +83,7 @@ a // [-2, -1, 1, 3, 4, 5, 7, 9, 10] The array's contents will always be sorted from low to high, now matter what. -Unfortunately, the current `findInsertionPoint()` function is a bit slow. In the worst case, it needs to scan through the entire array in order to insert the new element. We can speed this up by using a [binary search](../Binary Search) to find the insertion point. +Unfortunately, the current `findInsertionPoint()` function is a bit slow. In the worst case, it needs to scan through the entire array. We can speed this up by using a [binary search](../Binary Search) to find the insertion point. Here is the new version: @@ -106,6 +106,6 @@ Here is the new version: The big difference with a regular binary search is that this doesn't return `nil` when the value can't be found, but the array index where the element would have been. That's where we insert the new object. -Note that using binary search doesn't change the worst-case running time complexity of `insert()`. The binary search itself takes only **O(log n)** time, but inserting a new object in the middle of an array still involves shifting all remaining elements to the right in memory. So overall, the time complexity is still **O(n)**. But in practice this new version definitely is a lot faster, especially on large arrays. +Note that using binary search doesn't change the worst-case running time complexity of `insert()`. The binary search itself takes only **O(log n)** time, but inserting a new object in the middle of an array still involves shifting all remaining elements in memory. So overall, the time complexity is still **O(n)**. But in practice this new version definitely is a lot faster, especially on large arrays. *Written for Swift Algorithm Club by Matthijs Hollemans* diff --git a/Queue/README.markdown b/Queue/README.markdown index 70a6a76eb..7cf4bd484 100644 --- a/Queue/README.markdown +++ b/Queue/README.markdown @@ -97,7 +97,9 @@ where `xxx` is memory that is reserved but not filled in yet. Adding a new eleme This is simply matter of copying memory from one place to another, a constant-time operation. -Of course, there are only a limited number of such unused spots at the end of the array. When the last `xxx` gets used and you want to add another item, the array needs to resize to make more room. Resizing includes allocating new memory and copying all the existing data over to the new array. This is an **O(n)** process, so relatively slow. But since it happens only every so often, the time for appending a new element to the end of the array is still **O(1)** on average, or **O(1)** "amortized". +Of course, there are only a limited number of such unused spots at the end of the array. When the last `xxx` gets used and you want to add another item, the array needs to resize to make more room. + +Resizing includes allocating new memory and copying all the existing data over to the new array. This is an **O(n)** process, so it's relatively slow. But since it happens only every so often, the time for appending a new element to the end of the array is still **O(1)** on average, or **O(1)** "amortized". The story for dequeueing is slightly different. To dequeue we remove the element from the *beginning* of the array, not the end. This is always an **O(n)** operation because it requires all remaining array elements to be shifted in memory. @@ -116,7 +118,7 @@ Moving all these elements in memory is always an **O(n)** operation. So with our To make dequeuing more efficient, we can use the same trick of reserving some extra free space, but this time do it at the front of the array. We're going to have to write this code ourselves as the built-in Swift array doesn't support this out of the box. -The idea is this: whenever we dequeue an item, we don't shift the contents of the array to the front (slow) but mark the item's position in the array as empty (fast). After dequeuing `"Ada"`, the array is: +The idea is as follows: whenever we dequeue an item, we don't shift the contents of the array to the front (slow) but mark the item's position in the array as empty (fast). After dequeuing `"Ada"`, the array is: [ xxx, "Steve", "Tim", "Grace", xxx, xxx ] @@ -229,7 +231,7 @@ q.array // [nil, nil, {Some "Tim"}, {Some "Grace"}] q.count // 2 ``` -To test the trimming behavior, replace the line +To test the trimming behavior, replace the line, ```swift if array.count > 50 && percentage > 0.25 { diff --git a/Quicksort/README.markdown b/Quicksort/README.markdown index eda50aff5..b8a908985 100644 --- a/Quicksort/README.markdown +++ b/Quicksort/README.markdown @@ -31,7 +31,7 @@ Here's how it works. When given an array, `quicksort()` splits it up into three All the elements less than the pivot go into a new array called `less`. All the elements equal to the pivot go into the `equal` array. And you guessed it, all elements greater than the pivot go into the third array, `greater`. This is why the generic type `T` must be `Comparable`, so we can compare the elements with `<`, `==`, and `>`. -Once we have these three arrays, `quicksort()` recursively sorts the `less` array and the `right` array, then glues those sorted subarrays back together to get the final result. +Once we have these three arrays, `quicksort()` recursively sorts the `less` array and the `right` array, then glues those sorted subarrays back together with the `equal` array to get the final result. ## An example @@ -160,16 +160,16 @@ Note that `list` needs to be a `var` because `partitionLomuto()` directly change The `low` and `high` parameters are necessary because when this is used inside quicksort, you don't always want to (re)partition the entire array, only a limited range that becomes smaller and smaller. -Previously we used the middle array element as the pivot but it's important to realize that the Lomuto algorithm always uses the *last* element, `a[high]`. Because we've been pivoting around `8` all this time, I swapped the positions of `8` and `26` in the example so that `8` is at the end of the array and is used as the pivot value here too. +Previously we used the middle array element as the pivot but it's important to realize that the Lomuto algorithm always uses the *last* element, `a[high]`, for the pivot. Because we've been pivoting around `8` all this time, I swapped the positions of `8` and `26` in the example so that `8` is at the end of the array and is used as the pivot value here too. After partitioning, the array looks like this: [ 0, 3, 2, 1, 5, 8, -1, 8, 9, 10, 14, 26, 27 ] * -The variable `p` contains the return value of the call to `partitionLomuto()` and is 7. This is the index of the pivot element in the new array (marked with a star). +The variable `p` contains the return value of the call to `partitionLomuto()` and is 7. This is the index of the pivot element in the new array (marked with a star). -The left partition goes from 0 to `p-1` and is `[ 0, 3, 2, 1, 5, 8, -1 ]`. The right partition goes from `p+1` to the end, and is `[ 9, 10, 14, 26, 27 ]` (the fact that this is already sorted is a coincidence). +The left partition goes from 0 to `p-1` and is `[ 0, 3, 2, 1, 5, 8, -1 ]`. The right partition goes from `p+1` to the end, and is `[ 9, 10, 14, 26, 27 ]` (the fact that the right partition is already sorted is a coincidence). You may notice something interesting... The value `8` occurs more than once in the array. One of those `8`s did not end up neatly in the middle but somewhere in the left partition. That's a small downside of the Lomuto algorithm as it makes quicksort slower if there are a lot of duplicate elements. @@ -372,7 +372,7 @@ You might think this means we should always choose the middle element rather tha Now the middle element is `1` and that gives the same lousy results as in the previous example. -Ideally, the pivot is the *median* element of the array that you're partitioning. Of course, you won't know what the median is until after you've sorted the array, so this is a bit of a chicken-and-egg problem. However, there are some tricks to choose good, if not ideal, pivots. +Ideally, the pivot is the *median* element of the array that you're partitioning, i.e. the element that sits in the middle of the sorted array. Of course, you won't know what the median is until after you've sorted the array, so this is a bit of a chicken-and-egg problem. However, there are some tricks to choose good, if not ideal, pivots. One trick is "median-of-three", where you find the median of the first, middle, and last element in this subarray. In theory that often gives a good approximation of the true median. @@ -478,6 +478,6 @@ Using Dutch flag partitioning makes for a more efficient quicksort if the array ## See also -See also [Wikipedia](https://en.wikipedia.org/wiki/Quicksort). +[Quicksort on Wikipedia](https://en.wikipedia.org/wiki/Quicksort) -*Written by Matthijs Hollemans* +*Written for Swift Algorithm Club by Matthijs Hollemans* diff --git a/README.markdown b/README.markdown index 03bd2601b..c389f219b 100644 --- a/README.markdown +++ b/README.markdown @@ -8,7 +8,9 @@ The goal of this project is to **explain how algorithms work**. The focus is on All code is compatible with **Xcode 7.2** and **Swift 2.1**. We'll keep this updated with the latest version of Swift. -This is a work in progress. More algorithms will be added soon. :-) +This is a work in progress. More algorithms will be added soon. :-) + +:heart_eyes: **Suggestions and contributions are welcome!** :heart_eyes: ## Important links @@ -20,7 +22,7 @@ This is a work in progress. More algorithms will be added soon. :-) [Algorithm design techniques](Algorithm Design.markdown). How do you create your own algorithms? -[How to contribute](How to Contribute.markdown). Report an issue to leave feedback, or submit a pull request. **Suggestions and contributions are welcome!** +[How to contribute](How to Contribute.markdown). Report an issue to leave feedback, or submit a pull request. ## Where to start? @@ -41,7 +43,7 @@ If you're new to algorithms and data structures, here are a few good ones to sta - [Binary Search](Binary Search/). Quickly find elements in a sorted array. - [Count Occurrences](Count Occurrences/). Count how often a value appears in an array. - [Select Minimum / Maximum](Select Minimum Maximum). Find the minimum/maximum value in an array. -- [k-th Largest Element](Kth Largest Element/). Find the *k*th largest element in an array, such as the median. +- [k-th Largest Element](Kth Largest Element/). Find the *k*-th largest element in an array, such as the median. - [Selection Sampling](Selection Sampling/). Randomly choose a bunch of items from a collection. - [Union-Find](Union-Find/). Keeps track of disjoint sets and lets you quickly merge them. @@ -108,7 +110,7 @@ The choice of data structure for a particular task depends on a few things. First, there is the shape of your data and the kinds of operations that you'll need to perform on it. If you want to look up objects by a key you need some kind of dictionary; if your data is hierarchical in nature you want a tree structure of some sort; if your data is sequential you want a stack or queue. -Second, it matters what particular operations you'll be performing most, as certain data structures are optimized for certain actions. For example, if you often need to find the most important object in a queue, then a heap or priority queue is more optimal than a plain array. +Second, it matters what particular operations you'll be performing most, as certain data structures are optimized for certain actions. For example, if you often need to find the most important object in a collection, then a heap or priority queue is more optimal than a plain array. Most of the time using just the built-in `Array`, `Dictionary`, and `Set` types is sufficient, but sometimes you may want something more fancy... @@ -136,7 +138,7 @@ Most of the time using just the built-in `Array`, `Dictionary`, and `Set` types - [Tree](Tree/). A general-purpose tree structure. - [Binary Tree](Binary Tree/). A tree where each node has at most two children. -- [Binary Search Tree (BST)](Binary Search Tree/). A binary tree with the special requirement that elements are inserted in a specific way, allowing for faster queries, like when using a [binary search](Binary Search/) algorithm. +- [Binary Search Tree (BST)](Binary Search Tree/). A binary tree that orders its nodes in a way that allows for fast queries. - [AVL Tree](AVL Tree/). A binary search tree that balances itself using rotations. - Red-Black Tree - Splay Tree diff --git a/Ring Buffer/README.markdown b/Ring Buffer/README.markdown index 72fb08ebd..70e0ad108 100644 --- a/Ring Buffer/README.markdown +++ b/Ring Buffer/README.markdown @@ -41,7 +41,7 @@ Now the app decides it's time to write again and enqueues two more data items, ` [ 123, 456, 789, 666, 333 ] r ---> w -Whoops, the write pointer has reached the end of the array, so there is no more room. What now? Well, this is why it's a circular buffer: we wrap the write pointer back to the beginning and write the remaining data: +Whoops, the write pointer has reached the end of the array, so there is no more room for object `555`. What now? Well, this is why it's a circular buffer: we wrap the write pointer back to the beginning and write the remaining data: [ 555, 456, 789, 666, 333 ] ---> w r @@ -113,7 +113,7 @@ public struct RingBuffer { The `RingBuffer` object has an array for the actual storage of the data, and `readIndex` and `writeIndex` variables for the "pointers" into the array. The `write()` function puts the new element into the array at the `writeIndex`, and the `read()` function returns the element at the `readIndex`. -But hold up, you say, how does this wrapping around work? There are several ways to accomplish this and I chose a slightly controversial one. In this implementation, the `writeIndex` and `readIndex` always increment and never actually wrap around. Instead, we do this to find the actual index into the array: +But hold up, you say, how does this wrapping around work? There are several ways to accomplish this and I chose a slightly controversial one. In this implementation, the `writeIndex` and `readIndex` always increment and never actually wrap around. Instead, we do the following to find the actual index into the array: ```swift array[writeIndex % array.count] @@ -125,7 +125,7 @@ and: array[readIndex % array.count] ``` -In other words, we take the modulo (or the remainder) of the read and write index divided by the size of the underlying array. +In other words, we take the modulo (or the remainder) of the read index and write index divided by the size of the underlying array. The reason this is a bit controversial is that `writeIndex` and `readIndex` always increment, so in theory these values could become too large to fit into an integer and the app will crash. However, a quick back-of-the-napkin calculation should take away those fears. @@ -158,8 +158,8 @@ You've seen that a ring buffer can make a more optimal queue but it also has a d A ring buffer is also very useful for when a producer of data writes into the array at a different rate than the consumer of the data reads it. This happens often with file or network I/O. Ring buffers are also the preferred way of communicating between high priority threads (such as an audio rendering callback) and other, slower, parts of the system. -The implementation given here is not thread safe. It only serves as an example of how a ring buffer works. That said, it should be fairly straightforward to make it thread-safe for a single reader and single writer by using `OSAtomicIncrement64()` to change the read and write pointers. +The implementation given here is not thread-safe. It only serves as an example of how a ring buffer works. That said, it should be fairly straightforward to make it thread-safe for a single reader and single writer by using `OSAtomicIncrement64()` to change the read and write pointers. A cool trick to make a really fast ring buffer is to use the operating system's virtual memory system to map the same buffer onto different memory pages. Crazy stuff but worth looking into if you need to use a ring buffer in a high performance environment. -*Written by Matthijs Hollemans* +*Written for Swift Algorithm Club by Matthijs Hollemans* diff --git a/Run-Length Encoding/README.markdown b/Run-Length Encoding/README.markdown index 0f6041885..8371b1227 100644 --- a/Run-Length Encoding/README.markdown +++ b/Run-Length Encoding/README.markdown @@ -8,7 +8,7 @@ then RLE encodes it as follows: 5a3b1c1d7e1f... -Instead of repeating bytes, you first write how often that byte occurs and then the byte's actual value. If the data has a lot of "byte runs", that is lots of repeating bytes, then RLE can save quite a bit of space. It works quite well on images. +Instead of repeating bytes, you first write how often that byte occurs and then the byte's actual value. So `5a` means `aaaaa`. If the data has a lot of "byte runs", that is lots of repeating bytes, then RLE can save quite a bit of space. It works quite well on images. There are many different ways you can implement RLE. Here's an extension of `NSData` that does a version of RLE inspired by the old [PCX image file format](https://en.wikipedia.org/wiki/PCX). diff --git a/Segment Tree/README.markdown b/Segment Tree/README.markdown index fb9b6aaa1..0bb6d8da5 100644 --- a/Segment Tree/README.markdown +++ b/Segment Tree/README.markdown @@ -4,11 +4,23 @@ I'm pleased to present to you Segment Tree. It's actually one of my favorite dat Let's suppose that you have an array **a** of some type and some associative function **f**. For example, the function can be sum, multiplication, min, max, [gcd](../GCD/), and so on. -Your task is: +Your task is to: - answer a query for an interval given by **l** and **r**, i.e. perform `f(a[l], a[l+1], ..., a[r-1], a[r])` - support replacing an item at some index `a[index] = newItem` +For example, if we have an array of numbers: + +```swift +var a = [ 20, 3, -1, 101, 14, 29, 5, 61, 99 ] +``` + +We want to query this array on the interval from 3 to 7 for the function "sum". That means we do the following: + + 101 + 14 + 29 + 5 + 61 = 210 + +because `101` is at index 3 in the array and `61` is at index 7. So we pass all the numbers between `101` and `61` to the sum function, which adds them all up. If we had used the "min" function, the result would have been `5` because that's the smallest number in the interval from 3 to 7. + Here's naive approach if our array's type is `Int` and **f** is just the sum of two integers: ```swift @@ -21,7 +33,7 @@ func query(array: [Int], l: Int, r: Int) -> Int { } ``` -The running time of this algorithm is **O(n)** in the worst case, that is when **l = 0, r = n-1**. And if we have **m** queries to answer we get **O(m*n)** complexity. +The running time of this algorithm is **O(n)** in the worst case, that is when **l = 0, r = n-1** (where **n** is the number of elements in the array). And if we have **m** queries to answer we get **O(m*n)** complexity. If we have an array with 100,000 items (**n = 10^5**) and we have to do 100 queries (**m = 100**), then our algorithm will do **10^7** units of work. Ouch, that doesn't sound very good. Let's look at how we can improve it. @@ -48,7 +60,7 @@ Each node has the following data: - `leftBound` and `rightBound` describe an interval - `leftChild` and `rightChild` are pointers to child nodes -- `value` is actually the application of the function `f(a[leftBound], a[leftBound+1], ..., a[rightBound-1], a[rightBound])` +- `value` is the result of applying the function `f(a[leftBound], a[leftBound+1], ..., a[rightBound-1], a[rightBound])` If our array is `[1, 2, 3, 4]` and the function `f = a + b`, the segment tree looks like this: @@ -80,11 +92,11 @@ public init(array: [T], leftBound: Int, rightBound: Int, function: (T, T) -> T) } ``` -Notice that this is a recursive method! You give it an array, such as `[1, 2, 3, 4]` and it creates the root node of the tree and all the child nodes as well. +Notice that this is a recursive method. You give it an array such as `[1, 2, 3, 4]` and it builds up the entire tree, from the root node to all the child nodes. -1. The recursion terminates if `leftBound` and `rightBound` are equal. That means this `SegmentTree` instance will represent a leaf node. For the input array `[1, 2, 3, 4]`, it will create four such leaf nodes: `1`, `2`, `3`, and `4`. We just fill in the `value` property with the number from the array. +1. The recursion terminates if `leftBound` and `rightBound` are equal. Such a `SegmentTree` instance represents a leaf node. For the input array `[1, 2, 3, 4]`, this process will create four such leaf nodes: `1`, `2`, `3`, and `4`. We just fill in the `value` property with the number from the array. -2. However, if `rightBound` is still greater than `leftBound`, we create two child nodes. We divide the current segment into two equal (if length is even) segments. +2. However, if `rightBound` is still greater than `leftBound`, we create two child nodes. We divide the current segment into two equal segments (at least, if the length is even; if it's odd, one segment will be slightly larger). 3. Recursively build child nodes for those two segments. The left child node covers the interval **[leftBound, middle]** and the right child node covers **[middle+1, rightBound]**. @@ -143,7 +155,7 @@ Again, this is a recursive method. It checks four different possibilities. ![mixedSegment](Images/MixedSegment.png) -For example, this is how you could test it out in a playground: +This is how you can test it out in a playground: ```swift let array = [1, 2, 3, 4] diff --git a/Select Minimum Maximum/README.markdown b/Select Minimum Maximum/README.markdown index 5d7c11731..5e006f50e 100644 --- a/Select Minimum Maximum/README.markdown +++ b/Select Minimum Maximum/README.markdown @@ -2,23 +2,23 @@ Goal: Find the minimum/maximum object in an unsorted array. -### Maximum or minimum +## Maximum or minimum We have an array of generic objects and we iterate over all the objects keeping track of the minimum/maximum element so far. -#### An example +### An example Let's say the we want to find the maximum value in the unsorted list `[ 8, 3, 9, 4, 6 ]`. Pick the first number, `8`, and store it as the maximum element so far. -Pick the next number from the list, `3`, and compare it to the current maximum `8`. `3` is less than `8` so the maximum `8` does not change. +Pick the next number from the list, `3`, and compare it to the current maximum. `3` is less than `8` so the maximum `8` does not change. -Pick the next number from the list, `9`, and compare it to the current maximum `8`. `9` is greater than `8` so we store `9` as the maximum. +Pick the next number from the list, `9`, and compare it to the current maximum. `9` is greater than `8` so we store `9` as the maximum. Repeat this process until the all elements in the list have been processed. -#### The code +### The code Here is a simple implementation in Swift: @@ -52,35 +52,44 @@ Put this code in a playground and test it like so: ```swift let array = [ 8, 3, 9, 4, 6 ] -minimum(array) // This will return 3 -maximum(array) // This will return 9 +minimum(array) // This will return 3 +maximum(array) // This will return 9 ``` -### Maximum and minimum +### In the Swift standard library + +The Swift library already contains an extension to `SequenceType` that returns the minimum/maximum element in a sequence. + +```swift +let array = [ 8, 3, 9, 4, 6 ] +array.minElement() // This will return 3 +array.maxElement() // This will return 9 +``` + +## Maximum and minimum To find both the maximum and minimum values contained in array while minimizing the number of comparisons we can compare the items in pairs. -#### An example +### An example -Let's say the we want to find the minimum and maximum value in the unsorted list `[ 8, 3, 9, 4, 6 ]`. +Let's say the we want to find the minimum and maximum value in the unsorted list `[ 8, 3, 9, 6, 4 ]`. Pick the first number, `8`, and store it as the minimum and maximum element so far. -Because we have an odd number of items we remove `8` from the list which leaves the pairs `[ 3, 9 ]` and `[ 4, 6 ]`. +Because we have an odd number of items we remove `8` from the list which leaves the pairs `[ 3, 9 ]` and `[ 6, 4 ]`. -Pick the next pair of numbers from the list, `[ 3, 9 ]`, `3` is less than `9` so we compare `3` to the current minimum `8` and `9` to the current maximum `8`. `3` is less than `8` so the new minimum is `3`. `9` is greater than `8` so the new maximum is `9`. +Pick the next pair of numbers from the list, `[ 3, 9 ]`. Of these two numbers, `3` is the smaller one, so we compare `3` to the current minimum `8`, and we compare `9` to the current maximum `8`. `3` is less than `8` so the new minimum is `3`. `9` is greater than `8` so the new maximum is `9`. -Pick the next pair of numbers from the list, `[ 4, 6 ]`, `4` is less than `6` so we compare `4` to the current minimum `3` and `6` to the current maximum `9`. `4` is greater than `3` so the minimum does not change. `6` is less than `9` so the maximum does not change. +Pick the next pair of numbers from the list, `[ 6, 4 ]`. Here, `4` is the smaller one, so we compare `4` to the current minimum `3`, and we compare `6` to the current maximum `9`. `4` is greater than `3` so the minimum does not change. `6` is less than `9` so the maximum does not change. The result is a minimum of `3` and a maximum of `9`. -#### The code +### The code Here is a simple implementation in Swift: ```swift -func minimumMaximum(var array: [T]) -> (minimum: T, maximum: T)? -{ +func minimumMaximum(var array: [T]) -> (minimum: T, maximum: T)? { guard !array.isEmpty else { return nil } @@ -95,7 +104,6 @@ func minimumMaximum(var array: [T]) -> (minimum: T, maximum: T)? while !array.isEmpty { let pair = (array.removeFirst(), array.removeFirst()) - if pair.0 > pair.1 { if pair.0 > maximum { maximum = pair.0 @@ -120,26 +128,15 @@ func minimumMaximum(var array: [T]) -> (minimum: T, maximum: T)? Put this code in a playground and test it like so: ```swift - let result = minimumMaximum(array)! -result.minimum // This will return 3 -result.maximum // This will return 9 +result.minimum // This will return 3 +result.maximum // This will return 9 ``` By picking elements in pairs and comparing their maximum and minimum with the running minimum and maximum we reduce the number of comparisons to 3 for every 2 elements. -### Performance +## Performance These algorithms run at **O(n)**. Each object in the array is compared with the running minimum/maximum so the time it takes is proportional to the array length. -### Swift library - -The Swift library already contains an extension to `SequenceType` that returns the minimum/maximum element in a sequence. - -```swift -let array = [ 8, 3, 9, 4, 6 ] -array.minElement() // This will return 3 -array.maxElement() // This will return 9 -``` - *Written by [Chris Pilcher](https://github.com/chris-pilcher)* diff --git a/Selection Sampling/README.markdown b/Selection Sampling/README.markdown index 174b3a3da..a02c17b79 100644 --- a/Selection Sampling/README.markdown +++ b/Selection Sampling/README.markdown @@ -19,7 +19,7 @@ func select(from a: [T], count k: Int) -> [T] { } ``` -As often happens with these [kinds of algorithms](../Shuffle/), it divides the array into two regions. The first region is the selected items; the second region is all the remaining items. +As often happens with these [kinds of algorithms](../Shuffle/), it divides the array into two regions. The first region contains the selected items; the second region is all the remaining items. Here's an example. Let's say the array is: @@ -115,7 +115,7 @@ Only one item left to select but there are still 4 candidates to look at. Suppos 4 * 0.718 = 2.872 -For this element to be selected the number has to be less than 1, since there is only 1 element left to be picked. It isn't, so we skip `"d"`. Only three possibilities left -- will we make it? +For this element to be selected the number has to be less than 1, as there is only 1 element left to be picked. It isn't, so we skip `"d"`. Only three possibilities left -- will we make it before we run out of elements? The random number is 0.346. The formula gives: @@ -135,7 +135,7 @@ Let's say our final random number is 0.999 (remember, it can never be 1.0 or hig And so the last element will always be chosen if we didn't have a big enough selection yet. The final selection is `[ "b", "c", "g" ]`. Notice that the elements are still in their original order, because we examined the array from left to right. -Maybe you're not convinced yet... What if we always got 0.999 as the random value, would that still select 3 items? Well, let's do the math: +Maybe you're not convinced yet... What if we always got 0.999 as the random value (the maximum possible), would that still select 3 items? Well, let's do the math: 7 * 0.999 = 6.993 is this less than 3? no 6 * 0.999 = 5.994 is this less than 3? no diff --git a/Selection Sort/README.markdown b/Selection Sort/README.markdown index 57b1d09f5..6eb019ab1 100644 --- a/Selection Sort/README.markdown +++ b/Selection Sort/README.markdown @@ -2,7 +2,7 @@ Goal: Sort an array from low to high (or high to low). -You are given an array of numbers and need to put them in the right order. The selection sort algorithm divides the array into two parts: the beginning of the array is sorted, while the rest of the array consists of the numbers that still need to be sorted. +You are given an array of numbers and need to put them in the right order. The selection sort algorithm divides the array into two parts: the beginning of the array is sorted, while the rest of the array consists of the numbers that still remain to be sorted. [ ...sorted numbers... | ...unsorted numbers... ] @@ -17,11 +17,11 @@ It works as follows: - Swap it with the number at index 1. Now the sorted portion contains two numbers and extends from index 0 to index 1. - Go to index 2. - Find the lowest number in the rest of the array, starting from index 2, and swap it with the one at index 2. Now the array is sorted from index 0 to 2; this range contains the three lowest numbers in the array. -- And so on, until no numbers remain to be sorted. +- And so on... until no numbers remain to be sorted. It's called a "selection" sort, because at every step you search through the rest of the array to select the next lowest number. -### An example +## An example Let's say the numbers to sort are `[ 5, 8, 3, 4, 6 ]`. We also keep track of where the sorted portion of the array ends, denoted by the `|` symbol. @@ -48,11 +48,13 @@ With every step, the `|` bar moves one position to the right. We again look thro [ 3, 4, 5 | 8, 6 ] * -This process repeats until the array is sorted. Note that everything to the left of the `|` bar is always in sorted order and always contains the lowest numbers in the array. +This process repeats until the array is sorted. Note that everything to the left of the `|` bar is always in sorted order and always contains the lowest numbers in the array. Finally, we end up with: -As you can see, selection sort is an *in-place* sort because everything happens in the same array; no additional memory is necessary. You can also implement this as a *stable* sort so that identical elements do not get swapped around relative to each other (note that the version below isn't stable). + [ 3, 4, 5, 6, 8 |] -### The code +As you can see, selection sort is an *in-place* sort because everything happens in the same array; no additional memory is necessary. You can also implement this as a *stable* sort so that identical elements do not get swapped around relative to each other (note that the version given below isn't stable). + +## The code Here is an implementation of selection sort in Swift: @@ -90,7 +92,7 @@ A step-by-step explanation of how the code works: 1. If the array is empty or only contains a single element, then there's not much point to sorting it. -2. Make a copy of the array. This is necessary because we cannot modify the contents of the `array` parameter directly. Like Swift's own `sort()`, the `selectionSort()` function will return a sorted *copy* of the original array. +2. Make a copy of the array. This is necessary because we cannot modify the contents of the `array` parameter directly in Swift. Like Swift's own `sort()`, the `selectionSort()` function will return a sorted *copy* of the original array. 3. There are two loops inside this function. The outer loop looks at each of the elements in the array in turn; this is what moves the `|` bar forward. @@ -98,18 +100,20 @@ A step-by-step explanation of how the code works: 5. Swap the lowest number with the current array index. The `if` check is necessary because you can't `swap()` an element with itself in Swift. -In summary: For each element of the array, it swaps positions with the lowest value from the rest of the array. As a result, the array gets sorted from the left to the right. (You can also do it right-to-left, in which case you always look for the largest number in the array. Give that a try!) +In summary: For each element of the array, selection sort swaps positions with the lowest value from the rest of the array. As a result, the array gets sorted from the left to the right. (You can also do it right-to-left, in which case you always look for the largest number in the array. Give that a try!) -Note: The outer loop ends at index `a.count - 2`. The very last element will automatically always be in the correct position because at that point there are no other smaller elements left. +> **Note:** The outer loop ends at index `a.count - 2`. The very last element will automatically always be in the correct position because at that point there are no other smaller elements left. The source file [SelectionSort.swift](SelectionSort.swift) has a version of this function that uses generics, so you can also use it to sort strings and other types. -### Performance +## Performance + +Selection sort is easy to understand but it performs quite badly, **O(n^2)**. It's worse than [insertion sort](../Insertion Sort/) but better than [bubble sort](../Bubble Sort/). The killer is finding the lowest element in the rest of the array. This takes up a lot of time, especially since the inner loop will be performed over and over. -Selection sort is easy to understand but it performs quite badly, **O(n^2)**. It's worse than insertion sort but better than bubble sort. The killer is finding the lowest element in the rest of the array. This takes up a lot of time, especially since the inner loop will be performed over and over. +[Heap sort](../Heap Sort/) uses the same principle as selection sort but has a really fast method for finding the minimum value in the rest of the array. Its performance is **O(n log n)**. -### See also +## See also -See also [Wikipedia](https://en.wikipedia.org/wiki/Selection_sort). +[Selection sort on Wikipedia](https://en.wikipedia.org/wiki/Selection_sort) -*Written by Matthijs Hollemans* +*Written for Swift Algorithm Club by Matthijs Hollemans* diff --git a/Shell Sort/README.markdown b/Shell Sort/README.markdown index 8870ffea6..6cb682035 100644 --- a/Shell Sort/README.markdown +++ b/Shell Sort/README.markdown @@ -1,6 +1,6 @@ # Shell Sort -Shell sort is based on [insertion sort](../Insertion%20Sort/) as a general way to improve its performance, by breaking the original list into smaller sublists which can then be individually sorted using insertion sort. +Shell sort is based on [insertion sort](../Insertion%20Sort/) as a general way to improve its performance, by breaking the original list into smaller sublists which are then individually sorted using insertion sort. [There is a nice video created at Sapientia University](https://www.youtube.com/watch?v=CmPA7zE8mx0) which shows the process as a Hungarian folk dance. @@ -12,7 +12,7 @@ The distance between elements is known as the *gap*. If the elements being compa The idea is that by moving the elements over large gaps, the array becomes partially sorted quite quickly. This makes later passes faster because they don't have to swap so many items anymore. -Once a pass has been completed, the gap is made smaller and a new pass starts. This repeats until the gap is 1, at which point the algorithm functions just like insertion sort. But since the data is already fairly well sorted by then, the final pass can be very quick. +Once a pass has been completed, the gap is made smaller and a new pass starts. This repeats until the gap has size 1, at which point the algorithm functions just like insertion sort. But since the data is already fairly well sorted by then, the final pass can be very quick. ## An example @@ -26,36 +26,36 @@ This is the gap size. We create `n` sublists. In each sublist, the items are spaced apart by a gap of size `n`. In our example, we need to make four of these sublists. The sublists are sorted by the `insertionSort()` function. -That probably didn't make a whole lot of sense, so let's look at what happens. +That may not have made a whole lot of sense, so let's take a closer look at what happens. The first pass is as follows. We have `n = 4`, so we make four sublists: - list 0: [ 64, xx, xx, xx, 72, xx, xx, xx, 4 ] - list 1: [ xx, 20, xx, xx, xx, 10, xx, xx, xx ] - list 2: [ xx, xx, 50, xx, xx, xx, 23, xx, xx ] - list 3: [ xx, xx, xx, 33, xx, xx, xx, -1, xx ] + sublist 0: [ 64, xx, xx, xx, 72, xx, xx, xx, 4 ] + sublist 1: [ xx, 20, xx, xx, xx, 10, xx, xx, xx ] + sublist 2: [ xx, xx, 50, xx, xx, xx, 23, xx, xx ] + sublist 3: [ xx, xx, xx, 33, xx, xx, xx, -1, xx ] -As you can see, each list contains only every 4th item from the original array. The items that are not in a sublist are marked with `xx`. So the first list is `[ 64, 72, 4]` and the second is `[ 20, 10 ]`, and so on. The reason we use this "gap" is so that we don't have to actually make new arrays. Instead, we interleave them in the original array. +As you can see, each sublist contains only every 4th item from the original array. The items that are not in a sublist are marked with `xx`. So the first sublist is `[ 64, 72, 4 ]` and the second is `[ 20, 10 ]`, and so on. The reason we use this "gap" is so that we don't have to actually make new arrays. Instead, we interleave them in the original array. We now call `insertionSort()` once on each sublist. -This particular version of [insertion sort](../Insertion Sort/) sorts from the back to the front. Each item in the sublist is compared against the others. If they're in the wrong order, the value is swapped and travels all the way down until we reach the start of the list. +This particular version of [insertion sort](../Insertion Sort/) sorts from the back to the front. Each item in the sublist is compared against the others. If they're in the wrong order, the value is swapped and travels all the way down until we reach the start of the sublist. -So for list 0, we swap `4` with `72`, then swap `4` with `64`. After sorting, this sublist looks like: +So for sublist 0, we swap `4` with `72`, then swap `4` with `64`. After sorting, this sublist looks like: - list 0: [ 4, xx, xx, xx, 64, xx, xx, xx, 72 ] + sublist 0: [ 4, xx, xx, xx, 64, xx, xx, xx, 72 ] The other three sublists after sorting: - list 1: [ xx, 10, xx, xx, xx, 20, xx, xx, xx ] - list 2: [ xx, xx, 23, xx, xx, xx, 50, xx, xx ] - list 3: [ xx, xx, xx, -1, xx, xx, xx, 33, xx ] + sublist 1: [ xx, 10, xx, xx, xx, 20, xx, xx, xx ] + sublist 2: [ xx, xx, 23, xx, xx, xx, 50, xx, xx ] + sublist 3: [ xx, xx, xx, -1, xx, xx, xx, 33, xx ] The total array looks like this now: [ 4, 10, 23, -1, 64, 20, 50, 33, 72 ] -It's not sorted yet but it's more sorted than before. This completes the first pass. +It's not entirely sorted yet but it's more sorted than before. This completes the first pass. In the second pass, we divide the gap size by two: @@ -63,13 +63,13 @@ In the second pass, we divide the gap size by two: That means we now create only two sublists: - list 0: [ 4, xx, 23, xx, 64, xx, 50, xx, 72 ] - list 1: [ xx, 10, xx, -1, xx, 20, xx, 33, xx ] + sublist 0: [ 4, xx, 23, xx, 64, xx, 50, xx, 72 ] + sublist 1: [ xx, 10, xx, -1, xx, 20, xx, 33, xx ] Each sublist contains every 2nd item. Again, we call `insertionSort()` to sort these sublists. The result is: - list 0: [ 4, xx, 23, xx, 50, xx, 64, xx, 72 ] - list 1: [ xx, -1, xx, 10, xx, 20, xx, 33, xx ] + sublist 0: [ 4, xx, 23, xx, 50, xx, 64, xx, 72 ] + sublist 1: [ xx, -1, xx, 10, xx, 20, xx, 33, xx ] Note that in each list only two elements were out of place. So the insertion sort is really fast. That's because we already sorted the array a little in the first pass. @@ -85,7 +85,7 @@ A gap size of 1 means we only have a single sublist, the array itself, and once [ -1, 4, 10, 20, 23, 33, 50, 64, 72 ] -The performance of shell sort is **O(n^2)** or **O(n log n)** if you get lucky. This algorithm produces an unstable sort; it may change the relative order of elements with equal values. +The performance of shell sort is **O(n^2)** in most cases or **O(n log n)** if you get lucky. This algorithm produces an unstable sort; it may change the relative order of elements with equal values. ## The gap sequence diff --git a/Shuffle/README.markdown b/Shuffle/README.markdown index 6cbb23016..e0be6c1e4 100644 --- a/Shuffle/README.markdown +++ b/Shuffle/README.markdown @@ -29,7 +29,7 @@ list.shuffle() list.shuffle() ``` -You should see three different arrangements -- or permutations to use math-speak -- of the objects in the array. +You should see three different arrangements -- or [permutations](../Combinatorics/) to use math-speak -- of the objects in the array. This shuffle works *in place*, it modifies the contents of the original array. The algorithm works by creating a new array, `temp`, that is initially empty. Then we randomly choose an element from the original array and append it to `temp`, until the original array is empty. Finally, the temporary array is copied back into the original one. diff --git a/Shunting Yard/README.markdown b/Shunting Yard/README.markdown index d4d7c3e22..d2e568d39 100644 --- a/Shunting Yard/README.markdown +++ b/Shunting Yard/README.markdown @@ -1,38 +1,40 @@ # Shunting Yard Algorithm -Any mathematical expression that we write is expressed in a notation known as *infix notation*. - -For example: +Any mathematics we write is expressed in a notation known as *infix notation*. For example: **A + B * C** -In the above expression the operator is placed between operands, hence the expression is said to be in *infix* form. If you think about it, any expression that you write on a piece of paper will always be in infix form. This is what we humans understand. +The operator is placed in between the operands, hence the expression is said to be in *infix* form. If you think about it, any expression that you write on a piece of paper will always be in infix form. This is what we humans understand. + +Multiplication has higher precedence than addition, so when the above expression is evaluated you would first multiply **B** and **C**, and then add the result to **A**. We humans can easily understand the precedence of operators, but a machine needs to be given instructions about each operator. + +To change the order of evaluation, we can use parentheses: -When the above expression is evaluated, you would first multiply **B** and **C**, and then add the result to **A**. This is because multiplication has higher precedence than addition. We humans can easily understand the precedence of operators, but a machine needs to be given instructions about each operator. +**(A + B) * C** -If you were to write an algorithm that parsed and evaluated the infix notation you will realize that it's a tedious process. You'd have to parse the expression multiple times to know what operation to perform first. As the number of operators increase so does the complexity. +Now **A** is first added to **B** and then the sum is multiplied by **C**. -## Postfix notations / Reverse Polish Notation +If you were to write an algorithm that parsed and evaluated expressions in infix notation you will realize that it's a tedious process. You'd have to parse the expression multiple times to know what operation to perform first. As the number of operators increase so does the complexity. + +## Postfix notation In postfix notation, also known as Reverse Polish Notation or RPN, the operators come after the corresponding operands. Here is the postfix representation of the example from the previous section: **A B C * +** -An expression when represented in postfix form will not have any brackets and neither will you have to worry about scanning for operator precedence. This makes it easy for the computer to evaluate expressions, since the order in which the operators need to be applied is fixed. - -### Evaluating a postfix expression +An expression in postfix form will not have any parentheses and neither will you have to worry about scanning for operator precedence. This makes it easy for the computer to evaluate expressions, since the order in which the operators need to be applied is fixed. -A stack is used to evaluate a postfix expression. Here is the pseudocode: +Evaluating a postfix expression is easily done using a stack. Here is the pseudocode: -1. Read postfix expression token by token -2. If the token is an operand, push it into the stack +1. Read the postfix expression token by token +2. If the token is an operand, push it onto the stack 3. If the token is a binary operator, - 1. Pop the two top most operands from the stack + 1. Pop the two topmost operands from the stack 2. Apply the binary operator to the two operands - 3. Push the result into the stack + 3. Push the result back onto the stack 4. Finally, the value of the whole postfix expression remains in the stack -Using the above pseudocode, the evaluation on the stack would be as follows: +Using the above pseudocode, the evaluation of **A B C * +** would be as follows: | Expression | Stack | | ------------- | --------| @@ -47,7 +49,7 @@ Where **D = B * C** and **E = A + D.** As seen above, a postfix operation is relatively easy to evaluate as the order in which the operators need to be applied is pre-decided. -## Dijkstra's shunting yard algorithm +## Converting infix to postfix The shunting yard algorithm was invented by Edsger Dijkstra to convert an infix expression to postfix. Many calculators use this algorithm to convert the expression being entered to postfix form. @@ -65,11 +67,9 @@ Here is the psedocode of the algorithm: 1. Until the top token (from the stack) is left parenthesis, pop from the stack to the output buffer 2. Also pop the left parenthesis but don’t include it in the output buffer 7. Else add token to output buffer -2. While there are still operator tokens in the stack, pop them to output - -### How does it work +2. Pop any remaining operator tokens from the stack to the output -Let's take a small example and see how the pseudocode works. +Let's take a small example and see how the pseudocode works. Here is the infix expression to convert: **4 + 4 * 2 / ( 1 - 5 )** diff --git a/Stack/README.markdown b/Stack/README.markdown index fbc2512e4..6e832b69b 100644 --- a/Stack/README.markdown +++ b/Stack/README.markdown @@ -72,6 +72,6 @@ public struct Stack { Notice that a push puts the new element at the end of the array, not the beginning. Inserting at the beginning of an array is expensive, an **O(n)** operation, because it requires all existing array elements to be shifted in memory. Adding at the end is **O(1)**; it always takes the same amount of time, regardless of the size of the array. -Fun fact about stacks: each time you call a function or a method, the return address is placed on a stack by the CPU. When the function ends, the CPU uses that return address to jump back to the caller. That's why if you call too many functions -- for example in a recursive function that never ends -- you get a so-called "stack overflow" as the CPU stack is out of space. +Fun fact about stacks: Each time you call a function or a method, the CPU places the return address on a stack. When the function ends, the CPU uses that return address to jump back to the caller. That's why if you call too many functions -- for example in a recursive function that never ends -- you get a so-called "stack overflow" as the CPU stack has run out of space. -*Written by Matthijs Hollemans* +*Written for Swift Algorithm Club by Matthijs Hollemans* diff --git a/Tree/README.markdown b/Tree/README.markdown index 98d1bec12..52a46c597 100644 --- a/Tree/README.markdown +++ b/Tree/README.markdown @@ -1,10 +1,10 @@ -# Tree +# Trees A tree represents hierarchical relationships between objects. This is a tree: ![A tree](Images/Tree.png) -A tree consists of nodes. +A tree consists of nodes, and these nodes are linked to one another. Nodes have links to their children and usually to their parent as well. The children are the nodes below a given node; the parent is the node above. A node always has just one parent but can have multiple children. @@ -16,7 +16,7 @@ The pointers in a tree do not form cycles. This is not a tree: ![Not a tree](Images/Cycles.png) -Such a structure is called a [graph](../Graph/). A tree is really a very simple form of a graph. (In a similar vein, a [linked list](../Linked List) is a simple version of a tree. Think about it!) +Such a structure is called a [graph](../Graph/). A tree is really a very simple form of a graph. (In a similar vein, a [linked list](../Linked List/) is a simple version of a tree. Think about it!) This article talks about a general-purpose tree. That's a tree without any kind of restrictions on how many children each node may have, or on the order of the nodes in the tree. @@ -33,7 +33,7 @@ public class TreeNode { self.value = value } - func addChild(node: TreeNode) { + public func addChild(node: TreeNode) { children.append(node) node.parent = self } @@ -165,4 +165,6 @@ Then we can describe the tree with the following array: Each entry in the array is a pointer to its parent node. The item at index 3, `tea`, has the value 1 because its parent is `hot`. The root node points to `-1` because it has no parent. You can only traverse such trees from a node back to the root but not the other way around. +By the way, sometimes you see algorithms using the term *forest*. Unsurprisingly, that is the name given to a collection of separate tree objects. For an example of this, see [union-find](../Union-Find/). + *Written for Swift Algorithm Club by Matthijs Hollemans* diff --git a/Tree/Tree.playground/Contents.swift b/Tree/Tree.playground/Contents.swift index c4e8959f5..966870bdf 100644 --- a/Tree/Tree.playground/Contents.swift +++ b/Tree/Tree.playground/Contents.swift @@ -10,7 +10,7 @@ public class TreeNode { self.value = value } - func addChild(node: TreeNode) { + public func addChild(node: TreeNode) { children.append(node) node.parent = self } @@ -26,6 +26,9 @@ extension TreeNode: CustomStringConvertible { } } + + + let tree = TreeNode(value: "beverages") let hotNode = TreeNode(value: "hot") diff --git a/Tree/Tree.swift b/Tree/Tree.swift index e77045339..5c027141c 100644 --- a/Tree/Tree.swift +++ b/Tree/Tree.swift @@ -8,7 +8,7 @@ public class TreeNode { self.value = value } - func addChild(node: TreeNode) { + public func addChild(node: TreeNode) { children.append(node) node.parent = self } diff --git a/Two-Sum Problem/README.markdown b/Two-Sum Problem/README.markdown index 0c010954a..e2e15d4c0 100644 --- a/Two-Sum Problem/README.markdown +++ b/Two-Sum Problem/README.markdown @@ -8,7 +8,7 @@ There are a variety of solutions to this problem (some better than others). The This solution uses a dictionary to store differences between each element in the array and the sum `k` that we're looking for. The dictionary also stores the indices of each element. -With this approach, each key in the dictionary corresponds to a new target value. If one of the following numbers from the array is equal to one of the dictionary's keys, then we know there exist two numbers that sum to `k`. +With this approach, each key in the dictionary corresponds to a new target value. If one of the successive numbers from the array is equal to one of the dictionary's keys, then we know there exist two numbers that sum to `k`. ```swift func twoSumProblem(a: [Int], k: Int) -> ((Int, Int))? { @@ -38,7 +38,7 @@ Let's find out if there exist two entries whose sum is equal to 10. Initially, our dictionary is empty. We begin looping through each element: -- **i = 0**: Is `0` in the dictionary? No. We add the difference between the target `k` and the current number to the dictionary. The difference is `10 - 7 = 3`, so the dictionary key is `3`. The value for that key is the current index, `0`. The dictionary now looks like this: +- **i = 0**: Is `7` in the dictionary? No. We add the difference between the target `k` and the current number to the dictionary. The difference is `10 - 7 = 3`, so the dictionary key is `3`. The value for that key is the current index, `0`. The dictionary now looks like this: ```swift [ 3: 0 ] @@ -148,4 +148,4 @@ It's possible, of course, that there are no values for `a[i] + a[j]` that sum to I'm quite enamored by this little algorithm. It shows that with some basic preprocessing on the input data -- sorting it from low to high -- you can turn a tricky problem into a very simple and beautiful algorithm. -*Written by Matthijs Hollemans and Daniel Speiser* +*Written for Swift Algorithm Club by Matthijs Hollemans and Daniel Speiser* diff --git a/Union-Find/README.markdown b/Union-Find/README.markdown index 66937cf69..1d674e965 100644 --- a/Union-Find/README.markdown +++ b/Union-Find/README.markdown @@ -54,10 +54,10 @@ There are two trees in this forest, each of which corresponds to one set of elem We give each subset a unique number to identify it. That number is the index of the root node of that subset's tree. In the example, node `1` is the root of the first tree and `6` is the root of the second tree. -Note that the `parent[]` of a root node points to itself. So `parent[1] = 1` and `parent[6] = 6`. That's how we can tell something is a root node. - So in this example we have two subsets, the first with the label `1` and the second with the label `6`. The **Find** operation actually returns the set's label, not its contents. +Note that the `parent[]` of a root node points to itself. So `parent[1] = 1` and `parent[6] = 6`. That's how we can tell something is a root node. + ## Add set Let's look at the implementation of these basic operations, starting with adding a new set. @@ -181,7 +181,7 @@ Now we call `unionSetsContaining(4, and: 3)`. The smaller tree is attached to th ![AfterUnion](Images/AfterUnion.png) -Note that, because we call `setOf()` in the beginning of the method, the larger tree was also optimized in the process -- node `3` now hangs directly off the root. +Note that, because we call `setOf()` at the start of the method, the larger tree was also optimized in the process -- node `3` now hangs directly off the root. Union with optimizations also takes almost **O(1)** time. From 04966b1ef55ef4dc573f939553ae08eaf54bf823 Mon Sep 17 00:00:00 2001 From: Matthijs Hollemans Date: Thu, 3 Mar 2016 19:08:49 +0100 Subject: [PATCH 0108/1679] Clean up Travis-CI instructions --- How to Contribute.markdown | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/How to Contribute.markdown b/How to Contribute.markdown index 215539ae2..aa2cf3dea 100644 --- a/How to Contribute.markdown +++ b/How to Contribute.markdown @@ -21,16 +21,24 @@ To keep this a high quality repo, please follow this process when submitting you 3. Write an explanation of how the algorithm works. Include **plenty of examples** for readers to follow along. Pictures are good. Take a look at [the explanation of quicksort](Quicksort/) to get an idea. 4. Include your name in the explanation, something like *Written by Your Name* at the end of the document. If you wrote it, you deserve the credit and fame. 5. Add a playground and/or unit tests. - - Add unit test projects to `.travis.yml` so they will be run on [Travis-CI](https://travis-ci.org/hollance/swift-algorithm-club) - - `- xcodebuild test -project ./Algorithm/Tests/Tests.xcodeproj -scheme Tests` - - Configure scheme to run on Travis-CI - - Open `Product` -> `Scheme` -> `Manage Schemes ...` - - Uncheck `Autocreate schemes` - - Check `Shared` - - [Screenshot of scheme settings](/images/scheme-settings-for-travis.png) Just so you know, I will probably edit your text and code for grammar etc, just to ensure a certain level of polish. +For the unit tests: + +- Add the unit test project to `.travis.yml` so they it be run on [Travis-CI](https://travis-ci.org/hollance/swift-algorithm-club). Add a line to `.travis.yml` like this: + +``` +- xcodebuild test -project ./Algorithm/Tests/Tests.xcodeproj -scheme Tests +``` + +- Configure the Test project's scheme to run on Travis-CI: + - Open **Product -> Scheme -> Manage Schemes...** + - Uncheck **Autocreate schemes** + - Check **Shared** + +![Screenshot of scheme settings](Images/scheme-settings-for-travis.png) + ## Want to chat? This isn't just a repo with a bunch of code... If you want to learn more about how an algorithm works or want to discuss better ways of solving problems, then open a [Github issue](https://github.com/hollance/swift-algorithm-club/issues) and we'll talk! From dda4729089a1666a0cea756a5221152c46d513fe Mon Sep 17 00:00:00 2001 From: Matthijs Hollemans Date: Thu, 3 Mar 2016 19:38:25 +0100 Subject: [PATCH 0109/1679] Add Travis-CI build status badge --- README.markdown | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.markdown b/README.markdown index d17b87072..7cb2fbca4 100644 --- a/README.markdown +++ b/README.markdown @@ -1,5 +1,7 @@ # Welcome to the Swift Algorithm Club! +[![Build Status](https://travis-ci.org/hollance/swift-algorithm-club.svg?branch=master)](https://travis-ci.org/hollance/swift-algorithm-club) + Here you'll find implementations of popular algorithms and data structures in everyone's favorite new language Swift, with detailed explanations of how they work. If you're a computer science student who needs to learn this stuff for exams -- or if you're a self-taught programmer who wants to brush up on the theory behind your craft -- you've come to the right place! From 2e27f222b1e327859753dc3363319bc95ffa97a6 Mon Sep 17 00:00:00 2001 From: Matthijs Hollemans Date: Thu, 3 Mar 2016 19:46:58 +0100 Subject: [PATCH 0110/1679] Clean up of Bounded Priority Queue --- .../BoundedPriorityQueue.swift | 155 +++++++++--------- Bounded Priority Queue/README.markdown | 131 +++++++++++++++ Bounded Priority Queue/README.md | 80 --------- 3 files changed, 207 insertions(+), 159 deletions(-) create mode 100644 Bounded Priority Queue/README.markdown delete mode 100644 Bounded Priority Queue/README.md diff --git a/Bounded Priority Queue/BoundedPriorityQueue.swift b/Bounded Priority Queue/BoundedPriorityQueue.swift index 91b6d30b6..abee9e526 100644 --- a/Bounded Priority Queue/BoundedPriorityQueue.swift +++ b/Bounded Priority Queue/BoundedPriorityQueue.swift @@ -4,98 +4,95 @@ // Created by John Gill on 2/28/16. // -import Foundation - public class LinkedListNode { - var value: T - var next: LinkedListNode? - var previous: LinkedListNode? - - public init(value: T) { - self.value = value - self.next = nil - self.previous = nil - } + var value: T + var next: LinkedListNode? + var previous: LinkedListNode? + + public init(value: T) { + self.value = value + self.next = nil + self.previous = nil + } } public class BoundedPriorityQueue { - public typealias Node = LinkedListNode - private var head: Node? - private var curNumElements:Int - private var maxNumElements: Int - - public init(maxElements:Int) { - head = nil - maxNumElements = maxElements - curNumElements = 0 - } - - public var isEmpty: Bool { - return curNumElements == 0 - } - - public var count: Int { - return curNumElements - } + private typealias Node = LinkedListNode - public func peek() -> T? { - if curNumElements > 0 { - return head!.value - } - return nil - } + private(set) public var count = 0 + private var head: Node? + private var maxElements: Int - public func enqueue(value: T) { - let newNode = Node(value: value) + public init(maxElements: Int) { + self.maxElements = maxElements + } - if head == nil { - head = newNode - } else { - var node = head - if curNumElements == maxNumElements && newNode.value > node!.value { - return - } + public var isEmpty: Bool { + return count == 0 + } - while (node!.next != nil) && (newNode.value < node!.value) { node = node!.next } + public func peek() -> T? { + return head?.value + } - if newNode.value < node!.value { - newNode.next = node!.next - newNode.previous = node + public func enqueue(value: T) { + let newNode = Node(value: value) - if(newNode.next != nil) { /* TAIL */ - newNode.next!.previous = newNode - } - node!.next = newNode - } else { - newNode.previous = node!.previous - newNode.next = node - if(node!.previous == nil) { /* HEAD */ - head = newNode - } else { - node!.previous!.next = newNode - } - node!.previous = newNode - } - if(curNumElements == maxNumElements) { dequeue() } - } - curNumElements += 1 + if head == nil { + head = newNode + count = 1 + return } - public func dequeue() -> T? { - if curNumElements > 0 { - let retVal = head!.value + var node = head + if count == maxElements && newNode.value > node!.value { + return + } + + while (node!.next != nil) && (newNode.value < node!.value) { + node = node!.next + } + + if newNode.value < node!.value { + newNode.next = node!.next + newNode.previous = node + + if newNode.next != nil { /* TAIL */ + newNode.next!.previous = newNode + } + node!.next = newNode + } else { + newNode.previous = node!.previous + newNode.next = node + if node!.previous == nil { /* HEAD */ + head = newNode + } else { + node!.previous!.next = newNode + } + node!.previous = newNode + } - if curNumElements == 1 { - head = nil - } - else { - head = head!.next - head!.previous = nil - } + if count == maxElements { + dequeue() + } + count += 1 + } + + public func dequeue() -> T? { + if count == 0 { + return nil + } - curNumElements -= 1 - return retVal - } - return nil + let retVal = head!.value + + if count == 1 { + head = nil + } else { + head = head!.next + head!.previous = nil } + + count -= 1 + return retVal + } } diff --git a/Bounded Priority Queue/README.markdown b/Bounded Priority Queue/README.markdown new file mode 100644 index 000000000..b62d87678 --- /dev/null +++ b/Bounded Priority Queue/README.markdown @@ -0,0 +1,131 @@ +# Bounded Priority queue + +A bounded priority queue is similar to a regular [priority queue](../Priority Queue/), except that there is a fixed upper bound on the number of elements that can be stored. When a new element is added to the queue while the queue is at capacity, the element with the highest priority value is ejected from the queue. + +## Example + +Suppose we have a bounded-priority-queue with maximum size 5 that has the following values and priorities: + +``` +Value: [ A, B, C, D, E ] +Priority: [ 0.1, 0.25, 1.33, 3.2, 4.6 ] +``` + +Here, we consider the object with the lowest priority value to be the most important (so this is a *min-priority* queue). The larger the priority value, the less we care about the object. So `A` is more important than `B`, `B` is more important than `C`, and so on. + +Now we want to insert the element `F` with priority `0.4` into this bounded priority queue. Because the queue has maximum size 5, this will insert the element `F` but then evict the lowest-priority element (`E`), yielding the updated queue: + +``` +Value: [ A, B, F, C, D ] +Priority: [ 0.1, 0.25, 0.4, 1.33, 3.2 ] +``` + +`F` is inserted between `B` and `C` because of its priority value. It's less important than `B` but more important than `C`. + +Suppose that we wish to insert the element `G` with priority 4.0 into this BPQ. Because `G`'s priority value is greater than the maximum-priority element in the queue, upon inserting `G` it will immediately be evicted. In other words, inserting an element into a BPQ with priority greater than the maximum-priority element of the BPQ has no effect. + +## Implementation + +While a [heap](../Heap/) may be a really simple implementation for a priority queue, a sorted [linked list](../Linked List/) allows for **O(k)** insertion and **O(1)** deletion, where **k** is the bounding number of elements. + +Here's how you could implement it in Swift: + +```swift +public class BoundedPriorityQueue { + private typealias Node = LinkedListNode + + private(set) public var count = 0 + private var head: Node? + private var maxElements: Int + + public init(maxElements: Int) { + self.maxElements = maxElements + } + + public var isEmpty: Bool { + return count == 0 + } + + public func peek() -> T? { + return head?.value + } +``` + +The `BoundedPriorityQueue` class contains a doubly linked list of `LinkedListNode` objects. Nothing special here yet. The fun stuff happens in the `enqueue()` method: + +```swift + public func enqueue(value: T) { + let newNode = Node(value: value) + + if head == nil { + head = newNode + count = 1 + return + } + + var node = head + if count == maxElements && newNode.value > node!.value { + return + } + + while (node!.next != nil) && (newNode.value < node!.value) { + node = node!.next + } + + if newNode.value < node!.value { + newNode.next = node!.next + newNode.previous = node + + if newNode.next != nil { /* TAIL */ + newNode.next!.previous = newNode + } + node!.next = newNode + } else { + newNode.previous = node!.previous + newNode.next = node + if node!.previous == nil { /* HEAD */ + head = newNode + } else { + node!.previous!.next = newNode + } + node!.previous = newNode + } + + if count == maxElements { + dequeue() + } + count += 1 + } +``` + +We first check if the queue already has the maximum number of elements. If so, and the new priority value is greater than the `head` element's priority value, then there is no room for this new element and we return without inserting it. + +If the new value is acceptable, then we search through the list to find the proper insertion location and update the `next` and `previous` pointers. + +Lastly, if the queue has now reached the maximum number of elements, then we `dequeue()` the one with the largest priority value. + +By keeping the most important element at the front of the list, it makes dequeueing very easy: + +```swift + public func dequeue() -> T? { + if count == 0 { + return nil + } + + let retVal = head!.value + + if count == 1 { + head = nil + } else { + head = head!.next + head!.previous = nil + } + + count -= 1 + return retVal + } +``` + +This simply removes the `head` element from the list and returns it. + +*Written for Swift Algorithm Club by John Gill and Matthijs Hollemans* diff --git a/Bounded Priority Queue/README.md b/Bounded Priority Queue/README.md deleted file mode 100644 index 2d19ecba9..000000000 --- a/Bounded Priority Queue/README.md +++ /dev/null @@ -1,80 +0,0 @@ -# Bounded Priority queue - -A bounded priority queue is similar to a regular [priority queue](../Priority Queue), except that there is a fixed upper bound on the number of elements that can be stored. Whenever a new element is added to the queue, if the queue is at capacity, the element with the highest priority value is ejected from the queue. - -## Example -Supposed we have a bounded-priority-queue with maximum size 5 that has the following values and priorities: -``` -Value: [A, B, C, D, E] -Priority: [0.1, 0.25, 1.33, 3.2, 4.6] -``` -Suppose that we want to insert the element `F` with priority `0.4` into this bounded priority queue. Because this bounded-priority-queue has maximum size five, this will insert the element `F`, but then evict the lowest-priority element (`E`), yielding the updated queue: -``` -Value: [A, B, F, C, D] -Priority: [0.1, 0.25, 0.4, 1.33, 3.2] -``` -Now suppose that we wish to insert the element G with priority 4.0 into this BPQ. Because G's priority value is greater than the maximum-priority element in the BPQ, upon inserting G it will immediately be evicted. In other words, inserting an element into a BPQ with priority greater than the maximum-priority element of the BPQ has no effect. - -## Implementation -While a [heap](../Heap) may be a really simple implementation for a priority queue, an sorted [linked list](../Linked List) allows for `O(k)` insertion and `O(1)` deletion. Where `k` is the bounding number of elements. -```swift -public func enqueue(value: T) { - let newNode = Node(value: value) - - if head == nil { - head = newNode - } else { - var node = head - if curNumElements == maxNumElements && !(newNode.value < node!.value) { - return - } - - while (node!.next != nil) && (newNode.value < node!.value) { node = node!.next } - - if newNode.value < node!.value { - newNode.next = node!.next - newNode.previous = node - - if(newNode.next != nil) { /* TAIL */ - newNode.next!.previous = newNode - } - node!.next = newNode - } else { - newNode.previous = node!.previous - newNode.next = node - if(node!.previous == nil) { /* HEAD */ - head = newNode - } else { - node!.previous!.next = newNode - } - node!.previous = newNode - } - if(curNumElements == maxNumElements) { dequeue() } - } - curNumElements += 1 -} -``` -The `enqueue(_:)` method checks if the queue already has the maximum number of elements. If the new value is greater than the `head` value then don't insert it. If the new value is less than `head` search through the list to find the proper insertion location and update the pointers. - -Lastly if the queue has reached the maximum number of elements `dequeue()` the highest priority one. - -By keeping the element with the highest priority as the head it allows for a simple update of the `head` variable in a `dequeue()`: -```swift -public func dequeue() -> T? { - if curNumElements > 0 { - let retVal = head!.value - - if curNumElements == 1 { - head = nil - } - else { - head = head!.next - head!.previous = nil - } - - curNumElements -= 1 - return retVal - } - return nil -} -``` From a72a812e41df0b0294116fb0d1dacee88b8fc4b2 Mon Sep 17 00:00:00 2001 From: Matthijs Hollemans Date: Thu, 3 Mar 2016 19:57:11 +0100 Subject: [PATCH 0111/1679] Quickie cleanup of depth-first search. Needs more work. --- .../Contents.swift | 12 ++++------ Depth-First Search/DepthFirstSearch.swift | 10 +++----- Depth-First Search/README.markdown | 23 +++++++++++-------- README.markdown | 2 +- 4 files changed, 22 insertions(+), 25 deletions(-) diff --git a/Depth-First Search/DepthFirstSearch.playground/Pages/Simple Example.xcplaygroundpage/Contents.swift b/Depth-First Search/DepthFirstSearch.playground/Pages/Simple Example.xcplaygroundpage/Contents.swift index e18e7cc58..cc4bd7dd3 100644 --- a/Depth-First Search/DepthFirstSearch.playground/Pages/Simple Example.xcplaygroundpage/Contents.swift +++ b/Depth-First Search/DepthFirstSearch.playground/Pages/Simple Example.xcplaygroundpage/Contents.swift @@ -1,19 +1,17 @@ func depthFirstSearch(graph: Graph, source: Node) -> [String] { - var nodesExplored: [String] = [source.label] + var nodesExplored = [source.label] source.visited = true - // Iterate through all neighbors, and for each one visit all of its neighbors for edge in source.neighbors { - let neighbor: Node = edge.neighbor - - if (!neighbor.visited) { - nodesExplored += depthFirstSearch(graph, source: neighbor) + if !edge.neighbor.visited { + nodesExplored += depthFirstSearch(graph, source: edge.neighbor) } } return nodesExplored } + let graph = Graph() let nodeA = graph.addNode("a") @@ -35,4 +33,4 @@ graph.addEdge(nodeE, neighbor: nodeH) let nodesExplored = depthFirstSearch(graph, source: nodeA) -print(nodesExplored) \ No newline at end of file +print(nodesExplored) diff --git a/Depth-First Search/DepthFirstSearch.swift b/Depth-First Search/DepthFirstSearch.swift index 79e835f3e..4393ac864 100644 --- a/Depth-First Search/DepthFirstSearch.swift +++ b/Depth-First Search/DepthFirstSearch.swift @@ -1,15 +1,11 @@ func depthFirstSearch(graph: Graph, source: Node) -> [String] { - var nodesExplored: [String] = [source.label] + var nodesExplored = [source.label] source.visited = true - // Iterate through all neighbors, and for each one visit all of its neighbors for edge in source.neighbors { - let neighbor: Node = edge.neighbor - - if (!neighbor.visited) { - nodesExplored += depthFirstSearch(graph, source: neighbor) + if !edge.neighbor.visited { + nodesExplored += depthFirstSearch(graph, source: edge.neighbor) } } - return nodesExplored } diff --git a/Depth-First Search/README.markdown b/Depth-First Search/README.markdown index da5fd1b0b..322635d7a 100644 --- a/Depth-First Search/README.markdown +++ b/Depth-First Search/README.markdown @@ -1,32 +1,33 @@ # Depth-First Search -Depth-first search (DFS) is an algorithm for traversing or searching [tree](../Tree/) or [graph](../Graph/) data structures. It starts at the tree source and explores as far as possible along each branch before backtracking. +Depth-first search (DFS) is an algorithm for traversing or searching [tree](../Tree/) or [graph](../Graph/) data structures. It starts at a source node and explores as far as possible along each branch before backtracking. + +[TODO: this is a work-in-progress] ## The code -Simple implementation of breadth-first search using a queue: +Simple recursive implementation of depth-first search: ```swift func depthFirstSearch(graph: Graph, source: Node) -> [String] { - var nodesExplored: [String] = [source.label] + var nodesExplored = [source.label] source.visited = true - // Iterate through all neighbors, and for each one visit all of its neighbors for edge in source.neighbors { - let neighbor: Node = edge.neighbor - - if (!neighbor.visited) { - nodesExplored += depthFirstSearch(graph, source: neighbor) + if !edge.neighbor.visited { + nodesExplored += depthFirstSearch(graph, source: edge.neighbor) } } return nodesExplored } ``` +Where a [breadth-first search](../Breadth-First Search/) visits all immediate neighbors first, a depth-first search tries to go as deep down the tree or graph as it can. + Put this code in a playground and test it like so: ```swift -let graph = Graph() // Representing the graph from the animated example +let graph = Graph() let nodeA = graph.addNode("a") let nodeB = graph.addNode("b") @@ -58,4 +59,6 @@ Depth-first search can be used to solve many problems, for example: * Finding connected components of a sparse graph * Topological sorting of nodes in a graph * Finding bridges of a graph (see: [Bridges](https://en.wikipedia.org/wiki/Bridge_(graph_theory)#Bridge-finding_algorithm)) -* Among others +* And lots of others! + +*Written for Swift Algorithm Club by Paulo Tanaka* diff --git a/README.markdown b/README.markdown index 7cb2fbca4..b7d878e7e 100644 --- a/README.markdown +++ b/README.markdown @@ -168,7 +168,7 @@ Most of the time using just the built-in `Array`, `Dictionary`, and `Set` types - Graph - [Breadth-First Search (BFS)](Breadth-First Search/) -- Depth-First Search (DFS) +- [Depth-First Search (DFS)](Depth-First Search/) - Shortest Path - Minimum Spanning Tree - All Paths From b311d34025a7779a31cee29f040bde24bb0bbcc5 Mon Sep 17 00:00:00 2001 From: Matthijs Hollemans Date: Thu, 3 Mar 2016 20:16:02 +0100 Subject: [PATCH 0112/1679] Clean up of k-Means Clustering. --- K-Means/KMeans.swift | 123 +++++++++--------- K-Means/README.markdown | 101 ++++++++++++++ K-Means/README.md | 83 ------------ K-Means/Tests/Tests.xcodeproj/project.pbxproj | 5 +- README.markdown | 3 +- 5 files changed, 168 insertions(+), 147 deletions(-) create mode 100644 K-Means/README.markdown delete mode 100644 K-Means/README.md diff --git a/K-Means/KMeans.swift b/K-Means/KMeans.swift index 9a3193bfe..9073b7b46 100644 --- a/K-Means/KMeans.swift +++ b/K-Means/KMeans.swift @@ -6,74 +6,75 @@ import Foundation class KMeans { - var numCenters:Int - var convergeDist:Double - - init(numCenters:Int, convergeDist:Double) { - self.numCenters = numCenters - self.convergeDist = convergeDist + let numCenters: Int + let convergeDist: Double + + init(numCenters: Int, convergeDist: Double) { + self.numCenters = numCenters + self.convergeDist = convergeDist + } + + private func nearestCenter(x: Vector, centers: [Vector]) -> Int { + var nearestDist = DBL_MAX + var minIndex = 0 + + for (idx, c) in centers.enumerate() { + let dist = x.distTo(c) + if dist < nearestDist { + minIndex = idx + nearestDist = dist + } } + return minIndex + } + + func findCenters(points: [Vector]) -> [Vector] { + var centerMoveDist = 0.0 + let zeros = [Double](count: points[0].length, repeatedValue: 0.0) - private func nearestCenter(x: Vector, Centers: [Vector]) -> Int { - var nearestDist = DBL_MAX - var minIndex = 0; - - for (idx, c) in Centers.enumerate() { - let dist = x.distTo(c) - if dist < nearestDist { - minIndex = idx - nearestDist = dist - } - } - return minIndex - } + var kCenters = reservoirSample(points, k: numCenters) - func findCenters(points: [Vector]) -> [Vector] { - var centerMoveDist = 0.0 - let zeros = [Double](count: points[0].length, repeatedValue: 0.0) - - var kCenters = reservoirSample(points, k: numCenters) - - repeat { - var cnts = [Double](count: numCenters, repeatedValue: 0.0) - var newCenters = [Vector](count:numCenters, repeatedValue: Vector(d:zeros)) - - for p in points { - let c = nearestCenter(p, Centers: kCenters) - cnts[c]++ - newCenters[c] += p - } - - for idx in 0.. convergeDist) - return kCenters - } + repeat { + var cnts = [Double](count: numCenters, repeatedValue: 0.0) + var newCenters = [Vector](count:numCenters, repeatedValue: Vector(d:zeros)) + + for p in points { + let c = nearestCenter(p, centers: kCenters) + cnts[c] += 1 + newCenters[c] += p + } + + for idx in 0.. convergeDist + + return kCenters + } } // Pick k random elements from samples func reservoirSample(samples:[T], k:Int) -> [T] { - var result = [T]() - - // Fill the result array with first k elements - for i in 0.. [Vector] { + var centerMoveDist = 0.0 + let zeros = [Double](count: points[0].length, repeatedValue: 0.0) + + var kCenters = reservoirSample(points, k: numCenters) + + repeat { + var cnts = [Double](count: numCenters, repeatedValue: 0.0) + var newCenters = [Vector](count:numCenters, repeatedValue: Vector(d:zeros)) + + for p in points { + let c = nearestCenter(p, centers: kCenters) + cnts[c] += 1 + newCenters[c] += p + } + + for idx in 0.. convergeDist + + return kCenters +} +``` + +## Example + +These examples are contrived to show the exact nature of k-Means and finding clusters. These clusters are very easily identified by human eyes: we see there is one in the lower left corner, one in the upper right corner, and maybe one in the middle. + +In all these examples the squares represent the data points and the stars represent the *centroids*. + +##### Good clusters + +This first example shows k-Means finding all three clusters: + +![Good Clustering](Images/k_means_good.png) + +The selection of initial centroids found the lower left cluster (indicated by red) and did pretty good on the center and upper left clusters. + +#### Bad Clustering + +The next two examples highlight the unpredictability of k-Means and how it not always finds the best clustering. + +![Bad Clustering 1](Images/k_means_bad1.png) + +As you can see in this one, the initial *centroids* were all a little too close and the 'blue' didn't quite get to a good place. By adjusting the convergence distance we should be able to get it better. + +![Bad Clustering 1](Images/k_means_bad2.png) + +In this example, the blue cluster never really could separate from the red cluster and as such sort of got stuck down there. + +## Performance + +The first thing to recognize is that k-Means is classified as an NP-Hard type of problem. The selection of the initial *centroids* has a big effect on how the resulting clusters may end up. This means that trying to find an exact solution is not likely -- even in 2 dimensional space. + +As seen from the steps above the complexity really isn't that bad -- it is often considered to be on the order of **O(kndi)**, where **k** is the number of *centroids*, **n** is the number of **d**-dimensional vectors, and **i** is the number of iterations for convergence. + +The amount of data has a big linear effect on the running time of k-Means, but tuning how far you want the *centroids* to converge can have a big impact how many iterations will be done. As a general rule, **k** should be relatively small compared to the number of vectors. + +Often times as more data is added certain points may lie in the boundary between two *centroids* and as such those centroids would continue to bounce back and forth and the **convergence** distance would need to be tuned to prevent that. + +## See Also + +[K-Means Clustering on Wikipedia](https://en.wikipedia.org/wiki/K-means_clustering) + +*Written by John Gill* diff --git a/K-Means/README.md b/K-Means/README.md deleted file mode 100644 index e1314a825..000000000 --- a/K-Means/README.md +++ /dev/null @@ -1,83 +0,0 @@ -# K-Means - -Goal: Partition data into k clusters based on nearest means - -The idea behind K-Means is to try and take data that has no formal classification to it and determine if there are any natural clusters within the data. - -K-Means assumes that there are **k-centers** within the data. The data that is then closest to these *centroids* become classified or grouped together. K-Means doesn't tell you what the classifier is for that particular data group, but it assists in trying to find what clusters potentially exist. - -## Algorithm -The k-means algorithm is really quite simple at it's core: -1. Choose k random points to be the initial centers -2. Repeat the following two steps until the *centroid* reach convergence - 1. Assign each point to it's nearest *centroid* - 2. Update the *centroid* to the mean of it's nearest points - -Convergence is said to be reached when all of the *centroids* have not changed. - -This brings about a few of the parameters that are required for k-means: -- **k** - This is the number of *centroids* to attempt to locate -- **convergence distance** - This is minimum distance that the centers are allowed to moved after a particular update step. -- **distance function** - There are a number of distance functions that can be used, but mostly commonly the euclidean distance function is adequate. But often can lead to convergence not being reached in higher dimensionally. - -This is what the algorithm would look like in swift -```swift -func kMeans(numCenters: Int, convergeDist: Double, points: [Vector]) -> [Vector] { - var centerMoveDist = 0.0 - let zeros = [Double](count: points[0].getLength(), repeatedValue: 0.0) - - var kCenters = reservoirSample(points, k: numCenters) - - repeat { - var cnts = [Double](count: numCenters, repeatedValue: 0.0) - var newCenters = [Vector](count:numCenters, repeatedValue: Vector(d:zeros)) - for p in points { - let c = nearestCenter(p, Centers: kCenters) - cnts[c]++ - newCenters[c] += p - } - for idx in 0.. convergeDist) - return kCenters -} -``` - -## Example -These examples are contrived to show the exact nature of K-Means and finding clusters. These clusters are very easily identified by human eyes, we see there is one in the lower left corner, one in the upper right corner and maybe one in the middle. - -In all these examples the stars represent the *centroids* and the squares are the points. - -##### Good clusters -This first example shows K-Means finding all three clusters: -![Good Clustering](Images/k_means_good.png) - -The selection of initial centroids found that lower left (indicated by red) and did pretty good on the center and upper left clusters. - -#### Bad Clustering -The next two examples highlight the unpredictability of k-Means and how not always does it find the best clustering. -![Bad Clustering 1](Images/k_means_bad1.png) -As you can see in this one the initial *centroids* were all a little two close and the 'blue' didn't quite get to a good place. By adjusting the convergence distance should be able to get it better. - -![Bad Clustering 1](Images/k_means_bad2.png) -This one the blue cluster never really could separate from the red cluster and as such sort of got stuck down there. - -## Performance -The first thing to recognize is that k-Means is classified as an NP-Hard type of problem. The selection of the initial *centroids* has a big effect on how the resulting clusters may end up. This means that trying to find an exact solution is not likely - even in 2 dimensional space. - -As seem from the steps above the complexity really isn't that bad - it is often considered to be on the order of O(kndi), where **k** is the number of *centroids*, **n** is the number of **d** dimensional vectors and **i** is the number of iterations for convergence. - -The amount of data has a big linear effect on the running time of k-means, but tuning how far you want the *centroids* to converge can have a big impact how many iterations will be done - **k** should be relatively small compared to the number of vectors. - -Often times as more data is added certain points may lie in the boundary between two *centroids* and as such those centroids would continue to bounce back and forth and the **convergence** distance would need to be tuned to prevent that. - -## See Also -See also [Wikipedia](https://en.wikipedia.org/wiki/K-means_clustering) - -*Written by John Gill* diff --git a/K-Means/Tests/Tests.xcodeproj/project.pbxproj b/K-Means/Tests/Tests.xcodeproj/project.pbxproj index 55f861d02..c70acba0d 100644 --- a/K-Means/Tests/Tests.xcodeproj/project.pbxproj +++ b/K-Means/Tests/Tests.xcodeproj/project.pbxproj @@ -16,8 +16,8 @@ B80894DB1C852CFA0018730E /* KMeans.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = KMeans.swift; path = ../KMeans.swift; sourceTree = SOURCE_ROOT; }; B80894E01C852D100018730E /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; B80894E31C852D100018730E /* KMeansTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KMeansTests.swift; sourceTree = SOURCE_ROOT; }; - B80894E51C852D100018730E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = ../Info.plist; sourceTree = ""; }; - B80894E91C852DA00018730E /* Vector.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Vector.swift; path = ../Vector.swift; sourceTree = ""; }; + B80894E51C852D100018730E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; + B80894E91C852DA00018730E /* Vector.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Vector.swift; sourceTree = SOURCE_ROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -254,6 +254,7 @@ B80894E81C852D100018730E /* Release */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; diff --git a/README.markdown b/README.markdown index b7d878e7e..49f93c562 100644 --- a/README.markdown +++ b/README.markdown @@ -99,7 +99,8 @@ Bad sorting algorithms (don't use these!): - Statistics ### Machine learning -- [k-Means](K-Means/). Unsupervised classifier that partitions data into k clusters. + +- [k-Means Clustering](K-Means/). Unsupervised classifier that partitions data into *k* clusters. - k-Nearest Neighbors - Linear Regression - Logistic Regression From ef35bf044802f963c85a038e94ac26b7a806ff12 Mon Sep 17 00:00:00 2001 From: Matthijs Hollemans Date: Thu, 3 Mar 2016 20:27:38 +0100 Subject: [PATCH 0113/1679] Small edits to graph explanation --- Graph/README.markdown | 40 ++++++++++++++++++++++++---------------- README.markdown | 2 +- 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/Graph/README.markdown b/Graph/README.markdown index 42b71b6b2..75ac34abd 100644 --- a/Graph/README.markdown +++ b/Graph/README.markdown @@ -1,34 +1,37 @@ # Graph -A graph is a set of *vertices* paired with a set of *edges*. Each vertex has a set of associated edges, which connect to other vertices. +[TODO: this is a work-in-progress] -For example, a graph can represent a social network. Each person is a vertex, and people that know each other are connected with edges. +A graph is a set of *vertices* paired with a set of *edges*. Each vertex has a number of associated edges, which connect the vertex to other vertices. + +For example, a graph can represent a social network. Each person is a vertex, and people who know each other are connected by edges. // TODO: Insert image here +> **Note:** Vertices are sometimes also called "nodes" and edges are also called "links". + ## Weighted and Directed Edges -Edges can optionally be *weighted*, where an arbitrary weight is assigned to each edge. Consider an example of a graph representing airplane flights. Cities can be represented as vertices, and flights as edges. Then an edge weight could represent flight time. + +Edges can optionally be *weighted*, where an arbitrary weight -- a positive or negative numeric value -- is assigned to each edge. Consider an example of a graph representing airplane flights. Cities can be represented as vertices, and flights as edges. Then an edge weight could represent flight time or the cost of the trip. In addition, edges can optionally be *directed*. A directed edge from vertex A to vertex B connects *A to B*, but **not** *B to A*. Continuing from the flight path example, a directed edge from San Francisco, CA to Juneau, AK would indicate that there is a flight from San Francisco to Juneau, but not from Juneau to San Francisco. // TODO: Insert image here ## Representing Graphs in Code + There are two main strategies for representing graphs: -1. Adjacency List -2. Adjacency Matrix +**Adjacency List.** In an adjacency list implementation, each vertex stores a list of edges that originate from the vertex. For example, if vertex A has an edge to vertices B, C, and D, then vertex A would have a list of 3 edges. -### Adjacency List -In an adjacency list implementation, each vertex stores a list of edges that originate from the vertex. For example, if vertex A has an edge to vertices B, C, and D, then vertex A would have a list of 3 edges. +**Adjacency Matrix.** In an adjacency matrix implementation, a matrix with rows and columns representing vertices stores a weight to indicate if vertices are connected, and by what weight. For example, if there is a directed edge of weight 5.6 from vertex A to vertex B, then the entry with row for vertex A, column for vertex B would have value 5.6: -### Adjacency Matrix -In an adjacency matrix implementation, a matrix with rows and columns representing vertices stores a weight to indicate if vertices are connected, and by what weight. For example, if there is a directed edge of weight 5.6 from vertex A to vertex B, then the entry with row for vertex A, column for vertex B would have value 5.6: ``` - matrix[index(A)][index(B)] == 5.6 +matrix[index(A)][index(B)] == 5.6 ``` ### Comparing Graph Representations + Let *V* be the number of vertices in the graph, and *E* the number of edges. Then we have: | Operation | Adjacency List | Adjacency Matrix | @@ -38,17 +41,20 @@ Let *V* be the number of vertices in the graph, and *E* the number of edges. Th | Add Edge | O(1) | O(1) | | Check Adjacency | O(V) | O(1) | -Note that the time to check adjacency for an adjacency list is **O(V)**, because at worst a vertex is connected to *every* other vertex. So, in the case of a *sparse* graph, in which each vertex is connected to a handfull of other vertices, an Adjacency List is preferred. If the graph is *dense*, that is, vertices are connected to most of the other vertices, then an Adjacency Matrix is preferred. +Note that the time to check adjacency for an adjacency list is **O(V)**, because at worst a vertex is connected to *every* other vertex. + +In the case of a *sparse* graph, where each vertex is connected to only a handful of other vertices, an Adjacency List is preferred. If the graph is *dense*, where each vertex is connected to most of the other vertices, then an Adjacency Matrix is preferred. ## The Code -Below we have implementations of both Adjacency List and Adjacency Matrix graph representations. -In both cases, we also let the vertex store arbitrary data with a generic parameter. +Below we have implementations of both Adjacency List and Adjacency Matrix graph representations. In both cases, we also let the vertex store arbitrary data with a generic parameter. + ### Adjacency List + First, we have the data structures for edges and vertices: ```swift -var uniqueIDCounter: Int = 0 +var uniqueIDCounter = 0 public struct GraphEdge { public let from: GraphVertex @@ -69,6 +75,7 @@ public struct GraphVertex { } } ``` + Note that each vertex has a unique identifier, which we use to compare equality later. Now, lets see how to connect vertices: @@ -76,7 +83,7 @@ Now, lets see how to connect vertices: ```swift // Creates a directed edge self -----> dest public mutating func connectTo(destinationVertex: GraphVertex, withWeight weight: Double = 1.0) { - edges.append(GraphEdge(from: self, to: destinationVertex, weight: weight)) + edges.append(GraphEdge(from: self, to: destinationVertex, weight: weight)) } ``` And then we can check for an edge between vertices: @@ -94,7 +101,8 @@ public func edgeTo(otherVertex: GraphVertex) -> GraphEdge? { ``` ### Adjacency Matrix -Fundamentally, we will store a `[[Double?]]` which is the adjacency matrix. An entry of `nil` indicates no edge, while any other value indicates an edge of the given weight. To index into the matrix using vertices, we give each `GraphVertex` a unique integer index: + +Fundamentally, we will store a `[[Double?]]` array, which is the adjacency matrix. An entry of `nil` indicates no edge, while any other value indicates an edge of the given weight. To index into the matrix using vertices, we give each `GraphVertex` a unique integer index: ```swift public struct GraphVertex { diff --git a/README.markdown b/README.markdown index 49f93c562..85173ab6e 100644 --- a/README.markdown +++ b/README.markdown @@ -167,7 +167,7 @@ Most of the time using just the built-in `Array`, `Dictionary`, and `Set` types ### Graphs -- Graph +- [Graph](Graph/) - [Breadth-First Search (BFS)](Breadth-First Search/) - [Depth-First Search (DFS)](Depth-First Search/) - Shortest Path From 6a00819508c354c92ec334ed563aedd54049dba4 Mon Sep 17 00:00:00 2001 From: Matthijs Hollemans Date: Thu, 3 Mar 2016 20:30:11 +0100 Subject: [PATCH 0114/1679] Add :construction: emoji to articles that need work --- README.markdown | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/README.markdown b/README.markdown index 85173ab6e..2cab9e1b4 100644 --- a/README.markdown +++ b/README.markdown @@ -100,7 +100,7 @@ Bad sorting algorithms (don't use these!): ### Machine learning -- [k-Means Clustering](K-Means/). Unsupervised classifier that partitions data into *k* clusters. +- [k-Means Clustering](K-Means/). Unsupervised classifier that partitions data into *k* clusters. :construction: - k-Nearest Neighbors - Linear Regression - Logistic Regression @@ -130,7 +130,7 @@ Most of the time using just the built-in `Array`, `Dictionary`, and `Set` types - [Queue](Queue/). First-in, first-out! - [Deque](Deque/). A double-ended queue. - [Priority Queue](Priority Queue). A queue where the most important element is always at the front. -- [Bounded Priority Queue](Bounded Priority Queue). A queue that is bounded to have a limited number of elements. +- [Bounded Priority Queue](Bounded Priority Queue). A queue that is bounded to have a limited number of elements. :construction: - [Ring Buffer](Ring Buffer/). Also known as a circular buffer. An array of a certain size that conceptually wraps around back to the beginning. ### Lists @@ -143,7 +143,7 @@ Most of the time using just the built-in `Array`, `Dictionary`, and `Set` types - [Tree](Tree/). A general-purpose tree structure. - [Binary Tree](Binary Tree/). A tree where each node has at most two children. - [Binary Search Tree (BST)](Binary Search Tree/). A binary tree that orders its nodes in a way that allows for fast queries. -- [AVL Tree](AVL Tree/). A binary search tree that balances itself using rotations. +- [AVL Tree](AVL Tree/). A binary search tree that balances itself using rotations. :construction: - Red-Black Tree - Splay Tree - Threaded Binary Tree @@ -152,6 +152,7 @@ Most of the time using just the built-in `Array`, `Dictionary`, and `Set` types - [Heap](Heap/). A binary tree stored in an array, so it doesn't use pointers. Makes a great priority queue. - Fibonacci Heap - Trie +- [B-Tree](B Tree/) :construction: ### Hashing @@ -167,9 +168,9 @@ Most of the time using just the built-in `Array`, `Dictionary`, and `Set` types ### Graphs -- [Graph](Graph/) +- [Graph](Graph/) :construction: - [Breadth-First Search (BFS)](Breadth-First Search/) -- [Depth-First Search (DFS)](Depth-First Search/) +- [Depth-First Search (DFS)](Depth-First Search/) :construction: - Shortest Path - Minimum Spanning Tree - All Paths From 8f6e5b66d7f677587104a095c70c60f77775d0f3 Mon Sep 17 00:00:00 2001 From: Matthijs Hollemans Date: Thu, 3 Mar 2016 20:32:28 +0100 Subject: [PATCH 0115/1679] Didn't realize we already had a Travis build badge on the main page --- README.markdown | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/README.markdown b/README.markdown index 2cab9e1b4..ff2902bc7 100644 --- a/README.markdown +++ b/README.markdown @@ -1,7 +1,5 @@ # Welcome to the Swift Algorithm Club! -[![Build Status](https://travis-ci.org/hollance/swift-algorithm-club.svg?branch=master)](https://travis-ci.org/hollance/swift-algorithm-club) - Here you'll find implementations of popular algorithms and data structures in everyone's favorite new language Swift, with detailed explanations of how they work. If you're a computer science student who needs to learn this stuff for exams -- or if you're a self-taught programmer who wants to brush up on the theory behind your craft -- you've come to the right place! @@ -208,4 +206,4 @@ Other algorithm repositories: All content is licensed under the terms of the MIT open source license. -[![Build Status](https://travis-ci.org/hollance/swift-algorithm-club.svg)](https://travis-ci.org/hollance/swift-algorithm-club) +[![Build Status](https://travis-ci.org/hollance/swift-algorithm-club.svg?branch=master)](https://travis-ci.org/hollance/swift-algorithm-club) From f15eb772912658394dffcd39827e778b60028002 Mon Sep 17 00:00:00 2001 From: Matthijs Hollemans Date: Thu, 3 Mar 2016 20:33:18 +0100 Subject: [PATCH 0116/1679] Add note about construction badge --- How to Contribute.markdown | 2 ++ 1 file changed, 2 insertions(+) diff --git a/How to Contribute.markdown b/How to Contribute.markdown index aa2cf3dea..385d712e0 100644 --- a/How to Contribute.markdown +++ b/How to Contribute.markdown @@ -6,6 +6,8 @@ Want to help out with the Swift Algorithm Club? Great! Take a look at the [list](README.markdown). Any algorithms or data structures that don't have a link yet are up for grabs. +Things marked with :construction: need work. + New algorithms and data structures are always welcome (even if they aren't on the list). 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. From 0903d54de48c6c803f72d434ccf09016a246d207 Mon Sep 17 00:00:00 2001 From: Kauserali Hafizji Date: Fri, 4 Mar 2016 02:15:53 +0530 Subject: [PATCH 0117/1679] Initial playground --- Topological Sort/Topological Sort.playground/Contents.swift | 5 +++++ .../Topological Sort.playground/contents.xcplayground | 4 ++++ 2 files changed, 9 insertions(+) create mode 100644 Topological Sort/Topological Sort.playground/Contents.swift create mode 100644 Topological Sort/Topological Sort.playground/contents.xcplayground diff --git a/Topological Sort/Topological Sort.playground/Contents.swift b/Topological Sort/Topological Sort.playground/Contents.swift new file mode 100644 index 000000000..c9a67424b --- /dev/null +++ b/Topological Sort/Topological Sort.playground/Contents.swift @@ -0,0 +1,5 @@ +//: Playground - noun: a place where people can play + +import UIKit + +var str = "Hello, playground" diff --git a/Topological Sort/Topological Sort.playground/contents.xcplayground b/Topological Sort/Topological Sort.playground/contents.xcplayground new file mode 100644 index 000000000..5da2641c9 --- /dev/null +++ b/Topological Sort/Topological Sort.playground/contents.xcplayground @@ -0,0 +1,4 @@ + + + + \ No newline at end of file From ecd1ee3a4ba71d2c5baf2c93c9c6f13a5822a734 Mon Sep 17 00:00:00 2001 From: Matthijs Hollemans Date: Fri, 4 Mar 2016 19:24:11 +0100 Subject: [PATCH 0118/1679] Improve graph --- Graph/AdjacencyList.swift | 39 +++ Graph/AdjacencyMatrix.swift | 43 +++ .../Contents.swift | 74 ++--- .../Contents.swift | 76 +++--- Graph/Images/AdjacencyList.graffle | Bin 0 -> 2581 bytes Graph/Images/AdjacencyList.png | Bin 0 -> 18147 bytes Graph/Images/AdjacencyMatrix.graffle | Bin 0 -> 3223 bytes Graph/Images/AdjacencyMatrix.png | Bin 0 -> 21209 bytes Graph/Images/ChordMap.graffle | Bin 0 -> 2244 bytes Graph/Images/ChordMap.png | Bin 0 -> 17202 bytes Graph/Images/CoreData.graffle | Bin 0 -> 2092 bytes Graph/Images/CoreData.png | Bin 0 -> 5632 bytes Graph/Images/DAG.graffle | Bin 0 -> 2018 bytes Graph/Images/DAG.png | Bin 0 -> 9119 bytes Graph/Images/Demo1.graffle | Bin 0 -> 2172 bytes Graph/Images/Demo1.png | Bin 0 -> 9314 bytes Graph/Images/Flights.graffle | Bin 0 -> 2566 bytes Graph/Images/Flights.png | Bin 0 -> 34735 bytes Graph/Images/FlightsDirected.graffle | Bin 0 -> 2268 bytes Graph/Images/FlightsDirected.png | Bin 0 -> 32004 bytes Graph/Images/Graph.graffle | Bin 0 -> 2160 bytes Graph/Images/Graph.png | Bin 0 -> 14516 bytes Graph/Images/SocialNetwork.graffle | Bin 0 -> 2416 bytes Graph/Images/SocialNetwork.png | Bin 0 -> 31918 bytes Graph/Images/StateMachine.graffle | Bin 0 -> 2517 bytes Graph/Images/StateMachine.png | Bin 0 -> 24128 bytes Graph/Images/Tasks.graffle | Bin 0 -> 2361 bytes Graph/Images/Tasks.png | Bin 0 -> 14987 bytes Graph/Images/TreeAndList.graffle | Bin 0 -> 2648 bytes Graph/Images/TreeAndList.png | Bin 0 -> 19198 bytes Graph/README.markdown | 254 +++++++++++++----- README.markdown | 2 +- 32 files changed, 355 insertions(+), 133 deletions(-) create mode 100644 Graph/AdjacencyList.swift create mode 100644 Graph/AdjacencyMatrix.swift create mode 100644 Graph/Images/AdjacencyList.graffle create mode 100644 Graph/Images/AdjacencyList.png create mode 100644 Graph/Images/AdjacencyMatrix.graffle create mode 100644 Graph/Images/AdjacencyMatrix.png create mode 100644 Graph/Images/ChordMap.graffle create mode 100644 Graph/Images/ChordMap.png create mode 100644 Graph/Images/CoreData.graffle create mode 100644 Graph/Images/CoreData.png create mode 100644 Graph/Images/DAG.graffle create mode 100644 Graph/Images/DAG.png create mode 100644 Graph/Images/Demo1.graffle create mode 100644 Graph/Images/Demo1.png create mode 100644 Graph/Images/Flights.graffle create mode 100644 Graph/Images/Flights.png create mode 100644 Graph/Images/FlightsDirected.graffle create mode 100644 Graph/Images/FlightsDirected.png create mode 100644 Graph/Images/Graph.graffle create mode 100644 Graph/Images/Graph.png create mode 100644 Graph/Images/SocialNetwork.graffle create mode 100644 Graph/Images/SocialNetwork.png create mode 100644 Graph/Images/StateMachine.graffle create mode 100644 Graph/Images/StateMachine.png create mode 100644 Graph/Images/Tasks.graffle create mode 100644 Graph/Images/Tasks.png create mode 100644 Graph/Images/TreeAndList.graffle create mode 100644 Graph/Images/TreeAndList.png diff --git a/Graph/AdjacencyList.swift b/Graph/AdjacencyList.swift new file mode 100644 index 000000000..3a8bc3006 --- /dev/null +++ b/Graph/AdjacencyList.swift @@ -0,0 +1,39 @@ +private var uniqueIDCounter = 0 + +public struct Edge { + public let from: Vertex + public let to: Vertex + public let weight: Double +} + +public struct Vertex { + public var data: T + public let uniqueID: Int + + private(set) public var edges: [Edge] = [] // the adjacency list + + public init(data: T) { + self.data = data + uniqueID = uniqueIDCounter + uniqueIDCounter += 1 + } + + // Creates the directed edge: self -----> dest + public mutating func connectTo(destinationVertex: Vertex, withWeight weight: Double = 0) { + edges.append(Edge(from: self, to: destinationVertex, weight: weight)) + } + + // Creates an undirected edge by making two directed edges: self ----> other, and other ----> self + public mutating func connectBetween(inout otherVertex: Vertex, withWeight weight: Double = 0) { + connectTo(otherVertex, withWeight: weight) + otherVertex.connectTo(self, withWeight: weight) + } + + // Does this vertex have an edge -----> otherVertex? + public func edgeTo(otherVertex: Vertex) -> Edge? { + for e in edges where e.to.uniqueID == otherVertex.uniqueID { + return e + } + return nil + } +} diff --git a/Graph/AdjacencyMatrix.swift b/Graph/AdjacencyMatrix.swift new file mode 100644 index 000000000..85a16d94f --- /dev/null +++ b/Graph/AdjacencyMatrix.swift @@ -0,0 +1,43 @@ +public struct Vertex { + public var data: T + private let index: Int +} + +public struct Graph { + // If adjacencyMatrix[i][j] is not nil, then there is an edge from + // vertex i to vertex j. + private var adjacencyMatrix: [[Double?]] = [] + + // Adds a new vertex to the matrix. + // Performance: possibly O(n^2) because of the resizing of the matrix. + public mutating func createVertex(data: T) -> Vertex { + let vertex = Vertex(data: data, index: adjacencyMatrix.count) + + // Expand each existing row to the right one column. + for i in 0.. dest. + public mutating func connect(sourceVertex: Vertex, to destinationVertex: Vertex, withWeight weight: Double = 0) { + adjacencyMatrix[sourceVertex.index][destinationVertex.index] = weight + } + + // Creates an undirected edge by making 2 directed edges: + // some ----> other, and other ----> some. + public mutating func connect(someVertex: Vertex, symmetricallyWithVertex withVertex: Vertex, withWeight weight: Double = 0) { + adjacencyMatrix[someVertex.index][withVertex.index] = weight + adjacencyMatrix[withVertex.index][someVertex.index] = weight + } + + public func weightFrom(sourceVertex: Vertex, toDestinationVertex: Vertex) -> Double? { + return adjacencyMatrix[sourceVertex.index][toDestinationVertex.index] + } +} diff --git a/Graph/Graph.playground/Pages/Adjacency List.xcplaygroundpage/Contents.swift b/Graph/Graph.playground/Pages/Adjacency List.xcplaygroundpage/Contents.swift index 6c239f75d..f3c89b112 100644 --- a/Graph/Graph.playground/Pages/Adjacency List.xcplaygroundpage/Contents.swift +++ b/Graph/Graph.playground/Pages/Adjacency List.xcplaygroundpage/Contents.swift @@ -1,64 +1,65 @@ -/* +//: # Graph using an adjacency list +//: +//: In an adjacency list implementation of a graph, each vertex stores an +//: array of edges, indicating to which other vertices it has an edge. +//: (Note the directionality: we only record "to" edges, not "from" edges.) -A graph implementation, using an adjacency list. +private var uniqueIDCounter = 0 -In an adjacency list implementation, each vertex stores an array of edges, indicating to which vertices it has an edge (note the directionality). The edge stores the source and destination vertices, as well as a weight. - -*/ - -var uniqueIDCounter: Int = 0 - -public struct GraphEdge { - public let from: GraphVertex - public let to: GraphVertex +public struct Edge { + public let from: Vertex + public let to: Vertex public let weight: Double } - -public struct GraphVertex { +public struct Vertex { public var data: T - private var edges: [GraphEdge] = [] // This is an adjacency list, rather than matrix + public let uniqueID: Int - private let uniqueID: Int + private(set) public var edges: [Edge] = [] // the adjacency list public init(data: T) { self.data = data uniqueID = uniqueIDCounter uniqueIDCounter += 1 } - - // Creates a directed edge self -----> dest - public mutating func connectTo(destinationVertex: GraphVertex, withWeight weight: Double = 1.0) { - edges.append(GraphEdge(from: self, to: destinationVertex, weight: weight)) + + // Creates the directed edge: self -----> dest + public mutating func connectTo(destinationVertex: Vertex, withWeight weight: Double = 0) { + edges.append(Edge(from: self, to: destinationVertex, weight: weight)) } - // Creates an undirected edge by making 2 directed edges: self ----> other, and other ----> self - public mutating func connectBetween(inout otherVertex: GraphVertex, withWeight weight: Double = 1.0) { + // Creates an undirected edge by making two directed edges: self ----> other, and other ----> self + public mutating func connectBetween(inout otherVertex: Vertex, withWeight weight: Double = 0) { connectTo(otherVertex, withWeight: weight) otherVertex.connectTo(self, withWeight: weight) } - // Queries for an edge from self -----> otherVertex - public func edgeTo(otherVertex: GraphVertex) -> GraphEdge? { - for e in edges { - if e.to.uniqueID == otherVertex.uniqueID { - return e - } + // Does this vertex have an edge -----> otherVertex? + public func edgeTo(otherVertex: Vertex) -> Edge? { + for e in edges where e.to.uniqueID == otherVertex.uniqueID { + return e } - return nil } } -// Create 4 separate vertices -var v1 = GraphVertex(data: 1) -var v2 = GraphVertex(data: 2) -var v3 = GraphVertex(data: 3) -var v4 = GraphVertex(data: 4) +//: ### Demo + +// Create the vertices +var v1 = Vertex(data: 1) +var v2 = Vertex(data: 2) +var v3 = Vertex(data: 3) +var v4 = Vertex(data: 4) +var v5 = Vertex(data: 5) -// Setup a cycle like so: +// Set up a cycle like so: +// v5 +// ^ +// | (3.2) +// | // v1 ---(1)---> v2 ---(1)---> v3 ---(4.5)---> v4 // ^ | // | V @@ -68,6 +69,8 @@ v1.connectTo(v2, withWeight: 1.0) v2.connectTo(v3, withWeight: 1.0) v3.connectTo(v4, withWeight: 4.5) v4.connectTo(v1, withWeight: 2.8) +v2.connectTo(v5, withWeight: 3.2) + // Returns the weight of the edge from v1 to v2 (1.0) v1.edgeTo(v2)?.weight @@ -80,4 +83,5 @@ v3.edgeTo(v4)?.weight // Returns the weight of the edge from v4 to v1 (2.8) v4.edgeTo(v1)?.weight -//: [Next](@next) + +//: [Next: Adjacency Matrix](@next) diff --git a/Graph/Graph.playground/Pages/Adjacency Matrix.xcplaygroundpage/Contents.swift b/Graph/Graph.playground/Pages/Adjacency Matrix.xcplaygroundpage/Contents.swift index c8c5fdf8c..8d9fb5080 100644 --- a/Graph/Graph.playground/Pages/Adjacency Matrix.xcplaygroundpage/Contents.swift +++ b/Graph/Graph.playground/Pages/Adjacency Matrix.xcplaygroundpage/Contents.swift @@ -1,75 +1,87 @@ -//: [Previous](@previous) -/* +//: [Previous: Adjacency List](@previous) -A graph implementation, using an adjacency matrix. +//: # Graph using an adjacency matrix +//: +//: In an adjacency matrix implementation, each vertex is given an index +//: from `0.. { +public struct Vertex { public var data: T private let index: Int } public struct Graph { - - // nil entries are used to mark that two vertices are NOT connected. - // If adjacencyMatrix[i][j] is not nil, then there is an edge from vertex i to vertex j. + // If adjacencyMatrix[i][j] is not nil, then there is an edge from + // vertex i to vertex j. private var adjacencyMatrix: [[Double?]] = [] - // Possibly O(n^2) because of the resizing of the matrix - public mutating func createVertex(data: T) -> GraphVertex { - let vertex = GraphVertex(data: data, index: adjacencyMatrix.count) + // Adds a new vertex to the matrix. + // Performance: possibly O(n^2) because of the resizing of the matrix. + public mutating func createVertex(data: T) -> Vertex { + let vertex = Vertex(data: data, index: adjacencyMatrix.count) - // Expand each existing row to the right one column + // Expand each existing row to the right one column. for i in 0.. dest. Represented by M[source][dest] = weight - public mutating func connect(sourceVertex: GraphVertex, toDestinationVertex: GraphVertex, withWeight weight: Double = 0) { - adjacencyMatrix[sourceVertex.index][toDestinationVertex.index] = weight + // Creates a directed edge source -----> dest. + public mutating func connect(sourceVertex: Vertex, to destinationVertex: Vertex, withWeight weight: Double = 0) { + adjacencyMatrix[sourceVertex.index][destinationVertex.index] = weight } - // Creates an undirected edge by making 2 directed edges: some ----> other, and other ----> some - public mutating func connect(someVertex: GraphVertex, symmetricallyWithVertex withVertex: GraphVertex, withWeight weight: Double = 0) { + // Creates an undirected edge by making 2 directed edges: + // some ----> other, and other ----> some. + public mutating func connect(someVertex: Vertex, symmetricallyWithVertex withVertex: Vertex, withWeight weight: Double = 0) { adjacencyMatrix[someVertex.index][withVertex.index] = weight adjacencyMatrix[withVertex.index][someVertex.index] = weight } - - public func weightFrom(sourceVertex: GraphVertex, toDestinationVertex: GraphVertex) -> Double? { + + public func weightFrom(sourceVertex: Vertex, toDestinationVertex: Vertex) -> Double? { return adjacencyMatrix[sourceVertex.index][toDestinationVertex.index] } - } -// Create 4 separate vertices +//: ### Demo + +// Create the vertices var graph = Graph() let v1 = graph.createVertex(1) let v2 = graph.createVertex(2) let v3 = graph.createVertex(3) let v4 = graph.createVertex(4) +let v5 = graph.createVertex(5) -// Setup a cycle like so: +// Set up a cycle like so: +// v5 +// ^ +// | (3.2) +// | // v1 ---(1)---> v2 ---(1)---> v3 ---(4.5)---> v4 // ^ | // | V // ---------<-----------<---------(2.8)----<----| -graph.connect(v1, toDestinationVertex: v2, withWeight: 1.0) -graph.connect(v2, toDestinationVertex: v3, withWeight: 1.0) -graph.connect(v3, toDestinationVertex: v4, withWeight: 4.5) -graph.connect(v4, toDestinationVertex: v1, withWeight: 2.8) +graph.connect(v1, to: v2, withWeight: 1.0) +graph.connect(v2, to: v3, withWeight: 1.0) +graph.connect(v3, to: v4, withWeight: 4.5) +graph.connect(v4, to: v1, withWeight: 2.8) +graph.connect(v2, to: v5, withWeight: 3.2) // Returns the weight of the edge from v1 to v2 (1.0) graph.weightFrom(v1, toDestinationVertex: v2) @@ -83,3 +95,5 @@ graph.weightFrom(v3, toDestinationVertex: v4) // Returns the weight of the edge from v4 to v1 (2.8) graph.weightFrom(v4, toDestinationVertex: v1) +print(graph.adjacencyMatrix) + diff --git a/Graph/Images/AdjacencyList.graffle b/Graph/Images/AdjacencyList.graffle new file mode 100644 index 0000000000000000000000000000000000000000..62132edca0b49ac8e6e8471d6a3ae129f6c5dd22 GIT binary patch literal 2581 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 literal 0 HcmV?d00001 diff --git a/Graph/Images/AdjacencyMatrix.graffle b/Graph/Images/AdjacencyMatrix.graffle new file mode 100644 index 0000000000000000000000000000000000000000..644bbfea42ac4d8f0b23b9bcc5db9c8ce4175578 GIT binary patch literal 3223 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 CCI7$x literal 0 HcmV?d00001 diff --git a/Graph/Images/ChordMap.graffle b/Graph/Images/ChordMap.graffle new file mode 100644 index 0000000000000000000000000000000000000000..5f83ffd7603ce6658c37d9b59fe854ed58d149e6 GIT binary patch literal 2244 zcmV;#2s`&5iwFP!000030PS3DQ`@)}{=EDOU%p;QEXQ_|E@dYqDbVF@Nq}u9Gdsdo z5-pD9%1Q%e`0rP;6TitOAtmhg)_lNrbk5Py(eoTjwxzw_?kA4&6;U4(_x(1gsM`v1 zEn;JL^nUxQ|6#YW{oDT5-hVph?f$2WuHre^XUfIZ!O3x3+1{;ITb}2jYPHkvC>JNk zy}rV2RIA;yZDo7RnD?$)oy}$yD5NSDnFv9@dO?YYD0?{J#&)?v#b)+4uO_sfa)+yT8@+; zrBIywvgb3(o4n6GtdNO|N0dyx$~iwfq;NQNkXbo}7Pr)6grdFbTs)x(%x1+%6zo+O z#zQBjjI`{(r#_1+XLO3Hi}C|#-HA$Fn^)+Ku@#BUTR#^Q68@qrs{HX$-BHx19pw>d zhPI;spw^zAQf>;3wgY`xxknrv*P2l|?!@woxN6A|hhjbU;GkG?;d5BXO_IB~G*KLu zcPO02ZpDtBohRMl5sgBzIEzoh82aclA(Is_(T46<=$}(O!Z8{a!3<)V?8;c9hrc07 zJ`rV(>UpXRF>*BLwYY7ZS8h5Vx5ku4FQ) z6qDV|C<%!R!hcEzE(&lWC)FBS#n@4rs$MakGHuSt)SG5jCeEL^DMo6sKZZ7$C0iW} zB;kV;!ZJG0R!Y4{)bQi9{)KKFF z+iaYY4&a%DY02pyfz$fBoHjI5@Uda2#hf-YKFF*CP;&a;&FNQWDo|fc)yyO@F-tU5 zouf=^h?%0!!J->aPcm%_sNNex57~ue&!vRqeE>gUNVea`)N+t)_#Z*5)OF~d75k7b zjRQWQYzPK?0)>NrmNyb}#eqdE0!5Lo>fwbyz2(<6UEO*d40%pux6WXw4u&q~M{5kJ zkC>`NY4HqA(XUTj)*=p}T=>@kMYd)bgAql@6(_gO6!9aM8hDV}19oqiD*q3F797lm zIB1$492%-P)M|l9tr>{udLY6vqlVhzV1huztaA}z7gHCqDTU79izR+wcr<3n9YTvw zEY+>8pcQ^iQwG*hRXUTWWmEdq!OWfI39+uf8JL?TmP;&0SZ=*KmQB-qGc21WmP;&0 zSnj?imUW}a^RlMC8J3L_%O#d0EPr@SC~LJHrD?p~5JNAaTtYd5a{IMM7>$PZW>Bt` zP%fbyLHV%$Vl4k;PaO4io;cPv`NUDzjo?i~y?ia)ExL})1`LA?^ z_2R!H8<6?TN05LRNN1b^u|Xwh&vwPx4fi}Eu#$@zdMs73*@_yxaYvV5lNLfLDK zW=lnjK*T*DQ&tS4mWwBerSb)B3`8wVEpm$8PGSZ5BFi^o;>5B&|ge+5~=(PHMD^$rMQWO52=VzZ3oC}LrH=n%-# zyq=%yAkE=84}~=x5sJSN7dqT;>}HTBS7Z@er0JZB4qEJ+ee}`!bOTiM=YjM2_=vRh zKMwvl?sdnl@%fc%fZLmojx}oYYy12Pd>-E(T{|sa-tHRxzV`9U=bJONb$rup^}cYK z5BJWjefYflCuqpNCp;ppJZJv`dWfbnZ;tu!kZa$CyAEQ(J!NS%snKm-H9>h!C66Wm zl_vjd=ye@vKyB*s8uXk>1^Or|7eDt;Vwe(Cfk8RCUwj7n%uj_NEf!{M1xE zo>fKVms2OcFG~Wvi*Dhv;`D?l@wr1z>pAUu4!k`=g5Q~ukY;2@PV;;7B^ssDR}={V z^h%vipA7@>=`#<9shNu_IULD-tmJQKB9Uw8Or>5aoaN^brQi#laI~9xq!A}2DS^bt SU<0@Pt^WZ$pI3cXP5=NbH&ML+ literal 0 HcmV?d00001 diff --git a/Graph/Images/ChordMap.png b/Graph/Images/ChordMap.png new file mode 100644 index 0000000000000000000000000000000000000000..d3f9932b6111c50f5a51d0d4de21a49771db3650 GIT binary patch literal 17202 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 literal 0 HcmV?d00001 diff --git a/Graph/Images/CoreData.graffle b/Graph/Images/CoreData.graffle new file mode 100644 index 0000000000000000000000000000000000000000..caa78ecad345f9198f30c44c2d07220f2b2f239d GIT binary patch literal 2092 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 literal 0 HcmV?d00001 diff --git a/Graph/Images/Demo1.graffle b/Graph/Images/Demo1.graffle new file mode 100644 index 0000000000000000000000000000000000000000..dba0fb600bc10e89133764ff59b74144cf2d330f GIT binary patch literal 2172 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 literal 0 HcmV?d00001 diff --git a/Graph/Images/Flights.graffle b/Graph/Images/Flights.graffle new file mode 100644 index 0000000000000000000000000000000000000000..4b0da692742dd3c3876d73ba725ced7df5a97ea8 GIT binary patch literal 2566 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 literal 0 HcmV?d00001 diff --git a/Graph/Images/Flights.png b/Graph/Images/Flights.png new file mode 100644 index 0000000000000000000000000000000000000000..6e8eb2cdbf59a26eb90a244a8322822db1790348 GIT binary patch literal 34735 zcmZ_01yof*`#nr^>3iw!lJ4#9|sq$ z1UfY}wU~>Am58RC!hdfEpTucx+}xZ*I62?Hf6wurm&4J;nv+{tSeTQGhm(hg9h6{q z^>T1C^<;N&rTd>s{#QM6magV5Z=KxUIyz84)oW_z=t+}#;o23i5+0FE+cM?4Rz5D;a#Q(Rhmo9HD!BhX|Ztnly{eNHkZ+S7!rw9MP z2I7B4`9D{|FiW6|asKZqlR&T8;8}u$lY�lYZq1f0*aBO7QdXF<^kQPA*-O1(v2s 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 literal 0 HcmV?d00001 diff --git a/Graph/Images/FlightsDirected.graffle b/Graph/Images/FlightsDirected.graffle new file mode 100644 index 0000000000000000000000000000000000000000..79e7632b951b8ad103ca62701d04729ad68c0aa6 GIT binary patch literal 2268 zcmV<22qX6&iwFP!000030PS2`bK| z=_+w{wz<78x(Tc&+!5c} z*y2Zf?+zc)^HI~{_&aLDXT;8ljh+rG@>|h}2}c9Oj=*7MemYkXePau9Ve&4p94bM^ zpgehZ=yE28d?Y+9(-FY~M!j+QN}PRSu-|u(S-yalu+-s{p~K2dJf^9djdC^Ca9Eie z51jBgZQ6f&E)P5B%tMuV`!Td0Wv9dz9gc_C3dLrlpNUBccit9u{_+A!3YeCZ7qx0M zN{R|<=5(5HQ);vv=w_8W)WK1&DV6h+NPa%AT6~HFu?~NBP$W6`IcO9n>0{IyYYy5^ z7@S0IMUGuw#oZAz8cxOhEIJA1&_!P<9j$?h79`)Hd&TeoM`)N&razbQrHnK>_y@|! z$L2hvMICQMnhqY2j8|&bD_^=ZhL$i9$}{T&y&bZ5+d}cjS0#j#B30h z@N?3qi}5Taa^QT1obQN>NR+TS<4+7%@;iU2<>+Q>9!GzmafYD1*o7EvW5lf`h?_AP zR|<7>Bc&uIuBrGcK5^j$$6}IMtCkeQtWQ(powsZCdP%7oV47liWGg4MWJc-^p-m_8 z(MAIK;bl>LiO)xV;L6&TtI%XD;Xr6#z}-Rf=6FYuZh}G4%EuReCf!B@Xgw!H`_OUy z9V8U$LhLMb2jn>+HP&$=j+GQ_q>0xe(OiVY*x64_RaM=9tD3$kSM#|TwbxCfq?oE! zaCJ9aUE$8(#M)ZH+HJ5_+tv>IuV*bNxLWM6JLRgnDOVfDPtMgM8(s*-M#0tP6I9=X zs$f&9`c%|4V-ZywHLawm_2S0$r`}*yP_TBx6l4i&)yAf*t%BvO%}jUF1L)T)vf*PWE3~B#Rgma?6hizj7?Z;Y>Tz3TGjsDJ8ba~_ASYpdc!yNif^qU zfK;uS{%gL5KwV9nPP5Ei!1m4%j*-2P@A<6Ad)nz6%Gz&XW;rNp_;0~=X6?`uU+hD& zHJb4r<9)RUiHrRYYdlc3s@AipMWJjmfDv4{-h;T-4Y2pp>x;0+ADmtv^!fygqcw!g zMI0z$WV}Qk`eiC)E$UDvgn#KVWNX!GZ@>^D^5ntskT?pd-WW2w$DgVu5TB~5`3JKu z51MB9hdPi4UH3)whA(0mzKF>GL7*)Urs|8BH6bGHVn!hM7<78yEcpe;gCR$x4=qj^ z*xU0*;p&>wv-&`}psqzH(^W5JzY@_}y}m<4g96b7qC-SqLx$Zq1a!Toixgegb_eK2 zf#(9xA)ecm*p$2>pc?>`6oKU30lHoQx&U+t=q?^Tc#qtBLr80?Dbi@LLrB*ONEeU} zA$>;4K>1C4ydkDduhuPnkZi=dwfGk>xQ=D%%fUBx`1>D>CYZP&?_lT z0kB8-hQL-q9qjm552HYKf$R|3&5_Fyv*G9sK`nBR9b;NAFkN6e#B>J|lB0{6bJ;njoYT<-WU*>Z@wYMNruzFBu0f7oZAoiFz)Kz|%NU(e5I)A;@P_w&x_usOWC1y%Lo z{dgpAI|Qarf6@SR=Zv8^S7_}m!Nrmf763XkwZ_nxE#Z=XDL;Tf^nxSecXvjRY zk^GP9oK7YBZjdZGhjJ+KPgwpNnHz0${kwF$4fDwe?k~g@K{9kK$R=(Ow6BQsygH`b z(8;=0*M#U=CD;7u-^Dx|{({T^qcS9C23zD{=fZ-ZBo3AWW0Fl+ASL)sp z{LMqrebbWB-@53OaLkrX`(1wenB64qF%h>+i$i(KV@%A1Ka<(If*@O0@bqa6i6Gnm zf+p1Y?3`u^cG9j&+&YWg@^9>p#!q@9cM8@kU&U4OGKT_ll qin~BJHyY%;B$>mHcRAMczKX}9Ox%c$e&Nugz5fGRayj_VQ~&@T;A-#y literal 0 HcmV?d00001 diff --git a/Graph/Images/FlightsDirected.png b/Graph/Images/FlightsDirected.png new file mode 100644 index 0000000000000000000000000000000000000000..6cd6eca06cd6fb8b266908c4d3d9ac41965c5b30 GIT binary patch literal 32004 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 literal 0 HcmV?d00001 diff --git a/Graph/Images/Graph.graffle b/Graph/Images/Graph.graffle new file mode 100644 index 0000000000000000000000000000000000000000..d329bb433001546f4efda46fda8042798a592d4a GIT binary patch literal 2160 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 oBMS@0U}tl0YdLR;&t; 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 literal 0 HcmV?d00001 diff --git a/Graph/Images/SocialNetwork.png b/Graph/Images/SocialNetwork.png new file mode 100644 index 0000000000000000000000000000000000000000..5927937d263da1ebb7e2e36db7232d4220d2d68e GIT binary patch literal 31918 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 M4{XW56_8b9bz?U+v!7&F*v1m zEy8fjnGWp@>7;SFq{auJbt3=jvRVH+YmEN!M+A;u6%_<7eb6D`MW;EEMz7FlJLVw< zgUJ#e1)xClgG1CeWBY6Y@MG`olzj#hXj9t`Y0zdldrM=Ar4QBZbJNFp9Pp9UFMybY z)GjVSEiAwIK9og>+IArnEQYo)7_KQFUcU216BQ*_%DxwuSt>}vJK=pKmG=gKl>qnZ zS+wzRFqC)PGo2xH@=r41IEHGcN>d4%)R~4KmeUBJw|W^Gy%*41Vl*nuk(h*_>AKSF;s@-{#@CES zf8`HN*1}#P4;(gLJ*%EKyN?57;o|GKhW7eAv+&@_#ZD6?3AO_Vm3wKF3SQg*H&xM1 z?cf7{L!X$HGzYB+-j+P)Uxv})#Jqqa1UwpZAU4t;$k_1%-O@~9dLt z9kx0r6Z-Z>W}AbVsQd*8Y7qq_M626ra?o?K+b>Xf|7PO-QxeO@x(c-!q0-)Z>0bV_a08AHF9qUDd&jWbLpP^P&)PEi?WELtFMq4JI8yY#PX6Sy zBqS@$F_NvKKr+t#pQPeQGG0j{P9U&!r@P@8e>*-@a5*o8fWP)z#Ms z0{ke_ZayJ?VBi2J@_XVh0P!|$+$Fr!QCO)3LFvia<_ICQh10L=3Pf1ZOFjYY+V}V; zxLT1mx*VF36lmKIAaV(oATT~1ND|oPn2$Rv%=jLc{19ts$Vi?}+NaXD(pcc%B6>XF z?56IEZTD}UTm027De_^fZrBJ={T1VD6XY`#$VV`NX{g$nJ)I95He-KPJZ659g3_5t z;yHmkxDKVw)v zm5;R>)vq`W;WuEbQCU=vmE0|z0jZI?jo2_TH~mR{x57@PP(C&AcDD~*5BwZ>jG3iB z+`N>LNX%90Fj9lOx7`-a>S2EEeDaz`y!hcN!$@Y5voTuwLGo6Sbgh4#Ww)=!i}A5A z5NHBHFl6*ejAFU3B?X^RM(AOTLow8)D7pdqyeTLOWevzLt+tD{S(9qw1}uSjG2gA} z=O6V+8Yk0F4>|@vxvcL)T=x;W&egm%a0Ay?pUj7KrIuV1Vw&Q+@w6aEkW#9niFbH_ z+yF>&jlceO&x+l%=Rh$9z5HL#V*d#hE7@DCDwL8uCt69Srd+8YxKf_C4Ckh=%gkz2 z`Z|DvD?INPC0YipN#x*#7lt2Wn7U@ZLR4e}Ebdz%hp~oNne;R=)Tmt0qRv7!ijE_P>(I7hjtkp{Bp*5zPpklG{cPuj zC?fLXP~TJl&EbUmFq`!_P45sucGA1|p^;Z|76LomDSD0DJ9WqYeVy$nFM0M(24knU-WH#RA-=U0 zjI?2zEYEj8^19+_iwE%GQW+W;df(QY8@iBZ1?ZsM3}SEcjKQwzzEyOxk=ggh`(+b` z^(<{Di&&J1$`X?0K3NrGm$V1VZJO5fx)T_u3H8pJ#7=-khL9%)(R@UdBwYlN{J{}P z8H(0?8|3T~jw^(-)aBMNKy4>IRgHz^aWw{05}UFYQiUVOEkc{A3P>%zZ5<-;@!caO z?CF03SYwNV`E9$!AF z#A$N6=dBgdkxI(&TmAxG;k!29TWcYdGz^_j;>%@sccJXC)#`==kRstAMLf@`o@7fz z+Dj6CdA6C0pRG>{%Jg4&lm1s>w1tB~7nVTPISr}Olf9?N$RZN`R}TQgN+evz=M?t~ zUy@tk@FN*_Lq_$O1s914rwQij!0w5p164%1wc`lN3Uvm7{=nqYDs$j>h90{E7gseKL(Iu2}}PS-^C= zB1_=86^M;n-Yy-^BGZ{Q{EcwN)U>SJVTyUBBJlp}5`z3s3XA0pv>P`)u;(bwP$Ykt zx2B9WBgG3T0@R=AnN`Mf_JT3ox>up8GNzWKiPW7j%1?DHsL z@IKrd`ZTR$yO@8ukVly^g&~ZKdUC>kr$2YJU_`?jjN${vNtNS$SEFNfBOapcEI);XwH^is?YL zXrhb~pEvn6gN2nWS#j;wBO&!Azk6o4@;Ay)0H&Rzw5#$Unxa*!v+Yj2zg&LIt0+c} z)Ymi*oOv3-;5vdm#jc%=c2jNNh6#|DG(58Z-2OTK`yxyrFI`9t*^>Ic(d|c4-C?#1 z;%@FV%ruh>98-_aI4eD-Do+$7{A%^)b!md&?Kl3gs+Wna`tDUtDNy40eF|@bgovQu z@TRVW6R*;p_cqLEl}(%QaP4njA}7%=$*#sX?A5*giqDPFfHTG)i{}LsZ6zM0kXx!C zez*750TLe=D;jozZ@PK}e1l|DcAQITWe9@kgb9wZtLF}0rJT1JO0pra-czx5X=RTPTdWV|H> z!29b_z}20SxgPNdNgONcPK?pFWyib~~4$m-XJn!Q~0yGz4N4@G1cGy+6z zM*&(Oc zY!kc{4}y`Lp$ix#DUZ2{qWsD+9@RA4Bik7tf8Iim1g;%Wn1j0NvRE*>RY3)x4!CBJ zr8ey%@Rbq6ze!4mpQ7iU_@{y~J6#knkeQR$wVX_Bws&6wK?s-21>C9|TozrpVxwwJ1&uT9?9iKb_f=*z85%P~5>6sB`nj!~R{UhfkV`MD9k}IK+5Y1v6@vB;OPKpI5{;!(O};Da;mEvyt*wD^kvcmi z^|&yM@Jx2vgBn1=R~BYM)Yc`u-O;vS#AI8Sx|Jm`C8bqt6q*;DK!KB@OE zP;z5@yqQKbK^#jZO?Q4o&!o;q1Ym|{ z{}EKRLMS{UhB|SOTq}3C^Czxa2GB;ZB-^bHni;R^h`nTfDGplrzFLKcq)@tKruYWP zvt-1H(bx789x~U~1jJ6x zOLbU=lGfpj@+n~s6GY@iq7$7CI~Z=oBveiC_;w5!1&pC2TapV4KseEK3j1J;acQXF zVozCc4AgQJz~U|1{CzCNhFs1`+pYVXlP*IYk<8qJN=D3ez$wgp^-Pf8!>bJ5i#!_}39I<)8Os>RK-<8=m|!60xB0q!ugM3sD^Xpd7FHtLL> zSdcu=LaxpSoNT%(Aq}lv{$Wl^o1`T*fB#FeVuUA1D71=8UC!PN0kZ%lj|MG62;Vbd zgFsJc{)GC*DM`?_Y-zpJ6LueJG^~ zae6^==Q=}Z3chY5JuLP8)FU^_{3aIq7s+=EY`67ZlM#G_0;3KAxsZ9`q(|!wpj+$Z zn;t7kL9K}mDGY!*E>CL=B)3_ zbd#DtgTG1pj;`DxcGFWX#)zfLmyYy|TV_~H6x~gMWzm_G(OQOF^vn~Zbbg!8PK3(l5Q7ivqPm&{;Pq6B z=}bm<3mS}5DIIwuyqiyx0{|fg2o=)ui52A#89-;+4>GHUX|O8YM$j5AvBpYMbRUul z*V1eWH02W(jZ}~&Ia;}5wtIO`r-e{<#0Im00-6c*^p>nTtLAKFJ-+%yk54o~STsm- zQUoPTmv~h3YZ{&KrndiMAK|CkNd2*KxDk(}px9m#ruxF+;$}*)&bW?e2V))Iy?fR& zgJe1tOCGa`zwU(R*vtv2PtqX+Dkjy4!wVEzJJ~FHYSFXUBI4ZbY_fG4N&eI7CYrIU z)H>h&)-`*yFZzGz|4eR6HUQ$LB6)hlpD5TOObPfH4>Eg8F@M(2oMH5ir=OFCsr)wF zbtVDPf+Q<+zI=%goIV27EHocd`7bFz?6hhFzBv06JZZMdVBHvk`)9eh!XExOd6up^ zHd1EcaqLYbt2~M)fN%kVM~CK{`37ARnoV=-dEh;^;S`s0G)6m*iE*Xu8H> zKqf^;q~eM4UXl2%yJN_RO&d@@70r5yb0aY8RA7@)TNi$H=zepLr=8;*v;MK$p=6Gg zuPT6v|MaQL8H1B7!hz%zbP+IdT7q7`-hEJu7i-MZXpp*W6t;kq&DrI=0)X@=t*6G| zgak>mNMVR??*LHE21EviIbZh(?uZJ+Qw#->O-M?d6NrZnS3hN2J}3FXh>d%n%yRDn zAa#P|FXV~YSn!6oZ5^hm6YrT?$n@H58VEJy-3hksuj}d@EdAYp&u1U|Dc-=&DOYw{ z9gvKC=v9uF0F1| zwH8@pswFZfT=WfNXAq`d2V;#N5-QOA`nC4%9R`F?Z9PEDeHr)buNT?DR`Pg|m)0d+ zde9i;BP8+te@`>t&NywlV|QmswraoS%kp-$4-@aLcjf%-SGN@B=;JGl-lV3k75c5R z+e~5M)a(fCQ=9eGs17Sm&F47R7JtuaPEBRFw)0-wfnU%NvYo431=21aQo)?^4Bf1alIU*G4{bg*S4Og(NeGoIJb)0rmB!5RS0?07&qII)OplC)u+f{1pIqMIkCVG~j)= zTY^f%$oKdu-x<1}$@c{RtHhztTe%a?upJQ+xXj?}{mC~1s+h^^Jh7=%$4c@HRI}AO zA3!-aVufZBJ@q7|fxGCfb%&$wv;}Vinu@)oj~Q?eWapDu({mv{|3sHE?_jKsZ?Y@! z=zC0)NJK{)AFsNIT8;#ca_TaFiOdMSXEFM2!|8IN$ft?$+=4j>2?$a%h~`OqQ3x#) zMc=OtNk|LRP4&z0qTSMY_IxrolKe`#Cc5v^zh!%%>p!U7M&DuvTeb>lIq_D`hJxFI7Zvh4LwAloocsp+}Nv8Ap#^R5CF7*G7?=)@Tq z?zbYsHz_upZ}e2nPCvO+$UtwwT9_Z{f@)h3-2?l335ZoZ1m0~!LBgAn4RV9j5uODu z7rGbJb-d1P8%HSoJZ6VN2lst28*_&WpVJke7>!O0|83P^70&P5zWkUT0nx3jg#OfH z0a_g{Nj>9{W9PGN4ion+1<^t_sVlIh!f&ct{TycPoPdz>K${91)eHHE$}&&f@8%h4 z!@};v=`TO1zL37JuhhB$3nD$nFJ6H3j$y(B(Nu z(!TS=o9lDI?F7@p8o7H9%_O*{U^IM`)?G)L^%%i!UUVb(!{wV58%~&D*djBM%GXhT zF>cQM2FOG7<3l^V;}HO^p`>}d)Mz2jJu1pplZW1v^Dbv zNc?&wwpRcXuU{Fa% zt9R37X7KU6lqxyylQMc2PcCy3_$PXF;x`!@BtA$_`jBrwB5E+s>sWeL07=}_5S?82uV9yXTL3{6sVVc)g8m`_V zv|RVa5~{B6Px5QE;s;g#)?dT0&vS(-Pa$Kx=v+=J$`0Dm`iB;CBtNY3BKpv^A|KPy z6ZDbN9U1~hx6gcy6q5qTa0LO@E?cx(5knhaBkeUdBrE1m+=Ok|g92#e5!0;~&OP^6 zy@pqxJ=h!9I7rLbDi9*k)E_79h|PhWD;&53#9t{Zui2O)s+E))ibb4s;0RN5gj5TN;%fbgi-M zNXmzd9hfl(`l+=+sxSQNbvxxI^GcdJR&?WZ+LSc}s0Tj;FvQjYX|c~Rarm%S^^S@$ zZw=G4!NfS(_OTwqj%Wc1LE^Cn0~z`#Af!yf ztEZuQtrn_%#bPP$D_t+jtRwI>djn7M+SX7FX0;{#>n%b$x1X$P5;8 z>!ut2`K3-Okxy}~*#fEo{zCV_qKJ{fdJx?Jk63DBpo;a^Fc{(amv3`j<42#2jt~VB zXU%V;tb-1}q&&(rVi;Lah=@G(+fd6bT`Kd+?zO9(XvPi>B>TzLCqtfIT_cQ7HuwCg zI&Q$Rz_e5%`sXA^?kP|ccm=$&zT=3jQI-G~@oc=#ncETpgM;9daz+lz#(2=co^B@~ z?R02Kn=beWjRD8i`uN%M;Z~U`=`Rw3prDS#JQ-W(cWxsMD#5OyGF`o3U+Cfq3H!Cq zx{s)Zo&qXUyhUAFfO`0KA}W zWzHR^mspzzXj*#<51F8eyHaoSi~-T);W*#T_()!QY$$D+f!ghN3)tdzh1|9=B*8x7 zX|k6Trc`#g5zxpK4&3qwh^E{>usW8Z3BK@5VnPSXP zt3^;KAnSDmX~1Up5!hlTwCZY8olVDbaM?`3C{wd2clnyX(%762m`6EfBQ?>;jdSMD zZs!ya!LA|8>}77`pBc{#1V{4T&MevyEy|LN-k6)%4|OU3R=U6=XJd^}qFBW~%$GtL zWD%stp}FtDG5i$z$Bl{Q!=ji{r;1n{uvUI$aV(5rMrmg(cAozT$Y=#mrbq;(LI*Z( z8r!}$PkBbEugCuJYEu^{{pHZTfugCfj;eXh>3_3(?hc4!$`$&aYl70CD>~Bn-=02w z0$|M>eyt6lUX>UU7fYv-J2@M3NjA7eC1~OU=aNy6S1&mhxVb94i%N0PKc-djNYwwP zMNkHDcy%t;tm~xus?m>nrRTZMO6w2B!R(U#MQSrHlx=6%UzCnRj=Z4WUrP9Ob(8m@ z8&NJ>f8s4%rJ%tnRvSQpIVo1Y$A&yaAI0n{R}pWR5GZ9y7886s{m_zBKL<^GkAYh^ z=tI-{_qOYKp{}$im&DnU6mo&9z1_Y;JA=biA*u@FZvtC>lJw7W-aqx1Ztc^hLzh)* zerpNS^7Z5m{{&WzB13Gi@1(MmF1JlC%`g9eC9xNKJB2laqw&^rN5Cpx`EX*+7Ngl)Y|G~IWlKsO z>I_@(lIoQCr&=S)+>>4vcEU7!LwQkRL)h|4g7;7h*VT!*8O}C8>rb=J_zKljyOMxh{55YJ+zPTP#fqShLK=zVTuk4*ia*d0fkGXY{AQlCW8`01~{FO0Uo%Xs!2t{G3IswOkUQ{U<_AM}V2c_*ed z_Lwbi(x741Pt+CmJBj$V2XP&2SB&?%3<=QHdSLt0QpJ)Z%j`Pt%*XDO(PX*v!F=|J zUJrvJV4dL4YO~*S3o99uiLMB!{W1K5H(JS@<_aJ#Pz4D+Z-Pg@lmE72r38xkLwfEj z11g>4EMr@1Bx4x?>Cs$Gd-mnkbd%eLc)ysHDR~PH3lC{}2KhBC$HqR1iF;Oo8svKUBHef3 zeBm!LZ~ZEceL=>ZFwwT`n-q@q z3C5IF)2bA@Ks!EqsKZqwH64p&DBHyHsKCRtlgl43fHR9uV{~rCAF_5+CBu9e_vt6=u?KUxQp6HhkGf`yIQqIgAklP_zU}C0-Byv}>M`ND4yUN3uZ#i?hk=q2n{8bn+qv z1sz^tE8s;;Gxzt>VCWL zgQ8w=qpJNGAa7PK>7E0V%oJO{)jU&B%NyJ?u;hql3y9b9Wg8t>kD8YmqMUwU{wh_D zp&)GA!oCKmfNVJR5Y@WVAG-dd)MdBcYR#7s-)rJE#H!4V_U%K*yCfKrO&Rl?Iv%eGo&QDb7#BlV~q9JJ{eVJWgCtZ^APK|&Zy&bNpj(~`qP8_6QrN0Zq zWVV(tA**FsoQZk1SwVn|?3nftwFpXo$XBIJT%#Xic!f)g6sVpEmP@V@2~iCIuRUKc z2_CP!()MMEz0kM-fi!}duw$DXtQ`#)OkNq}!R2w)@R(-pS&W@*Yu!-L(1?>Eg~4?_ zGIDy41&Ja_a;#NTjir$KEeZP*P7L}f5fjHXfh81yi)Rthmj%o{>3sh@waj*C7WV?H zKj5e9bFyP7KUis05I`uFzciL5nJma>OHSl)v-F+Uze&)Oxwd&o(hx&<+uE(8TaHwe zARL|FGa$C$a~RI2s*zRFDhHtQr2-H6ZeU!_Nk7!HMyr^CM5mh=SttmxYFdxl&Ud55 zey(J$aSfmU+)MidudR}6r8yin$MzE&U2LmY>UaPuj@S)~T2k=kce3-5)AMDPug${W zQy+nN$461bVK@4O0S1D0g?xB$)g)Xji^2-Sj44`v%^}ANYfBYx{yPkxGJj%cA=S5Lt6-U!qI++>$BN7UUAH5qIv>@+73NOk}K@ zOlLEzB3N?LFzvigA69J`)hN6uN8D_k%27kDJ80x{Ai6kmG52d`Z&~SQcBx`ZF0^`y z*32oi{LJ3%UL}bOeEtCOMouR;hNIe<-&G^0v~9z?O1mi$g#Qu$CJp>x>ka)cm`M?I zkufAj>irZ=u){m$1X2a`-_N6Ma_&}mEXP$HO>7u!%F_Hi4yGk0Gxl)izQExXX;Mh# zV$4x8!!B7FY%Nd|2R(9`iU##V-$o(OuJn4Y;L;L&*gx+7?9>zEg=vMp%0?H$RQ_y7Cjh;;u9`6QRb4z|cwU1h9k z-MSOyZVoo%;1H+d?F>cfXY_Ua{#tjf83>&r=iF{X6Bd$al_Vj#};@5ycXO~_)VlMaF zI>jVF?LbVJ3~0=%5FDLPOG~-*l~2{7awC_h9@dafojKw2SO9VAj)=Pa+ssDK#fV|W z034YftPpE4aguNj@mUji`0LWbt{ssr#%CjE%Vf_S1{^IA-iSs5b6Jf~iwv>XZkcBM z+CvXlxzslQvn!|N*l`^%-6*lgCIM%fLr4T^eaHe4rj=wVT?dbI;~5a+E6hvKx2SR5 z*L+PWcDB}Og%Ine!CcnKiOedexQo7Wt-qDh|AUr0-hQ=N@62gDyA7|?=FMwgw(cEX zN_ypHyc37rP;E~!mc@dkb*C;TXgkK|H3HX=j$$L(e%3hlx?`&RkF%`R5@9wfP*pUv za+wB@=mHY+JvTXxT7*#(48><#?UsbC!)*yiSubO(8hrjT6GPxYN3=T__ub|){g5?D z-q-GvYq>&Ej}@*mb80=Cq_~CKMGw48oe=d2?POoRwX?Ml@^I+9TcDDHzdLifJhg?e zOvVRhH*6p(@&Lx7!`V%@D=mnnasCx{0yx{E)1vjmqYIt4L%U`6K7^=zXw^fj_=`iB zBa?`R8OjdK}rJg6hj=7pk{-5>sS-=7&JE*u=1=Ox&jqj7tKsJ^Hw zD_cODATbr|QUCY{f`1!8jmGx#`#}*FgYVT^%Q{Rm3M?C78$K({_7z{~C?XP7EE$yj zoI}lc_ZJ+rTa+ADr;D|?R;MNB5qY*6SX7Ac>yvXCD7BzcrWq(Z_nL0m>}zAQHlE{r zpyLy22)NHPw!3#5?xWC@Bp46F^(_lRL!zs=fP6f8k{`07tn|t806p&=d8@hJ?(p{H z@>)iB08=us^`*Aowu(g>at%1SS4`6+e?Sdo6)^zS37n%JaiOC9v0IPAALV>)QVhAU zh*?a)t+Ljow$Lk%sU>C>v6}XT4~AC!1T1<}uljB8;0=FHJ75Rrf!-a(-v?{#{e}vj z1Ws0=f1#)@8w5^v)bhL^OS`MQu9cb{O;2z#tY@3yq9_shc4rM@*pWIOfDt}|=qQOF z8cbT<97dwj9RAgwh`J^D$PIXZQb%y+pZXSF&+3H;5yWOTkm+@hfrcut9<{m}BqgeH zXvQ)!SQ#o)5Do8~`#`f4N|xi|0)kcy5t9l}{PshcK;>~U2LG5#R zh!C{%Ehqwm&&n|m!ZYaGgSm$t-1F}^pNENaJE?Z{lAJ4J3 zsC^UpWmh=8zaG2ywu^BPZ@Nrn?q*1K5`{yH6WX2j=Kc?5L?m!XH2#Rdm)Pt`SOE&Z z?oCcaq;06Iug#d$Y?@TrQ0;WOIn!XSKvcxS|5S*ly1Ytwk>rP~DreE`o1(yzX@O4g z*4$gm&XQQJ$EN?ktBF5;ARs*EpZ^y?TJLI8<<}i%DhdPNe`-J4p&AOW5qZ?F5n%X_ zPUU~){#I50W_25n%+a#^reFqpK(bDG1zmAb&9V^&4f55NlC{qD_7%ADoO6yf&!{l zy^m!LQ;V7ktvX48@8pv-3&W2y(kP5T^RFUVimNf(4#k=@?Jt(mF@opF7;m@DQG)Ln z|BVEb)66paiRQ{CE)=rp(rB=m zKnj$?zu;BX3LSDn33|5n2H7vG5KNx0{eR%*d|1P|y)-naM z*T{{>4S1dK<)X4USl?X$nnY&2uEaS7;z%;iFg`4Yp}E2T+p}607@vx!ofAuyDyfRd z7{C`Yv{*1vJ}=^BOa6}GMqM{AVolA^qjJzQBWr*_C6`C_`+^!{iYPC;)10ASRd+Pq zVSQ(pG1aF+JgUo?)@pxai4v5teA6*cf@qd zzmtVl4Nr;V_5e_Vlvr8L?^QU)as;ss2b61tUfGz7ecaYH9tsGTqB{GQNXxhV=o_ zR>+)_E!Oo7IL{w<^Di!v9yYJxif*3DUCNEN^qr)z5+vR)7l$qgp;p8X3_X2X2U7f9TW?IWQn@KEv zB#i?Cp5zwf3D;o^S$VkRkG3N+`GA4Ih`^OwDum7IbE;^^hxt?1@1LuwHvvUNTa%3P zV>SWnOG^c8o_ogfJk6dh^FU(0mYkPQxyIk@;MX=qOo7#F3a3)pNi}N(tGG|<`$9?1 zQ9ZB&#+9>%_3ZA4%)EA2n^gvMsm-_;Fn|BT6CKg z=YRoC_rPC+U2dGXjD&X2<(UbeMYkc)ZUK!e&2FxY#w9fn1MSCcn&;9b6yf4(lP*8e z=&DQ7+I))7^z|@-$`*{C7K8G-@{-iDTkccX9TQ>S; z`B91Q7u@sHm^SZ*_ouYlH6zoz9oZe~&YncVpZX$)REE?q&ba>-!TdR@4e6!Rz7b(Z zoBvcB&)!mF;*xHj3cSLtTTxncG27#zxyt?R3IDT8$v~2nGd|AUZB7r^-f2^6MhPQU zqY2&Sh6nr~+iuL<8(v9Ar9X|jYyzN#ClEJwz0>TB*cC9{LX0gH@-uKFsnk4RjA*QF zd-VK$9r#AU*gf@YH{mbR9-~wF=mVple3}h!B%YiwOrEJfJl<`2a!Rl}{@6>8UK`P2 z9xD+#VQtNXcoKV;+gF|5$yGyn&+2sS$l83}SerzA6(D0XpiHv4GC}m`sHC>{FA6n= z!VBfyH$b1D>>czm`aO7kMm;vQq~vg-I}2mBF(x4v=ci|#@3A!8+2mOF9BcF73k;qu zNLJ7!Sh5jyv_i(92rIx&{1-t#!M(!>ow>))Sfe5T&0@htVG_1b#!q+CFfAMM#@|nu!y?8-XZ1EW98Rx#CI(Pmo%RaZLhg1OFIIjPNh7UWB9eTdr|s>hnb!MrbDw)=xCc9N+Hc<0t>(VdicM9}R{fH-VnUsIbQN0ai;qHs}-FAaS%RQME75 zngn7}WgQwDs5omcQx7bxM9K{!8#VCEiYbfqd3+a5S0{y}46bsiYJuYMrr)`U?o0{) zjn=*ZiS7;`2JGn8QMNV7FSM<9_}Q;KTQHvZn_ky)V?FnQ)`S}`hf@oZhnpj*qk|8> z`piQU(cWy3c_E`6vD+kj=`D~TEg0g#3~((hIkbM)>EoM$*!azzfeq)n!6)c0Kb{mz zV5A}t&{-sJnl4ma>X^_iLVH04 zkKRe7Nc>X#llWFQ1=fe^)kKDMxTBbUX_YRf=5DMbF8TUS70n&L^ejCdQobN2$<<3ca&8kOJ;5jZ9N%}H{j$}Bfh{H+gsU2C5^NDhJ z!aW{W+kpLfhJcdsLX3l}AOqzoz8)q72U=g`F_`-FMuAx44IrhwT7S2YH<&5+mer=` zG_nah6I;-?tf57`vc15m_g0IB*SDKi4*|xID%eIj6;~?1z9Bkt4+1A~`2+9q9{H)& z-NgkKod?TNS&poeLxS?Ue} zn(g3^tjI>aeLjUnLne%v_>wkq%|)ts`JfIteClD#&rQ>2m?C85=dX{a%%T!zT_wP2 zCT{VZ=}Dq`Xr^5$DiVGCUCO9Qjr0JkR&&tXx(OH=_kVyH z)Xpd4*q~}d{R-&-RVL`AhOKv2ifB3S*2~8L7qL|g>OuG^4bQacJ_E{g)!}9s;ihWCL{4mmo}p zdH=NeFR^N0Ip{Gh3%1i!U74i6Ln?V&p%C#DIGyF0n*4DG7>G!-nSXB<|d;+X1>}&iy@Q%KsiZpqzxr<4akdJ^^rOJwf*n=>_yiJD|hMZL_&M> zsdL0}$v1}XKsVqkJqa8bBt%J$VgDW*{*{QUyJPV}BL#q#X!MEc+huSKsn}^N5X_0G zTaPs@T1FT=$M}ULX^wcP-DRByHI6$0z^XUU!{=aPQMbh>hp29OJ($DiYBvU(?)~pC zup}PmPQFAz}pOzTL-&o%JtpFmCLLhTQGsBlHYg$y}(%sY_Oz_#Qf?Vp75K@ zg7O}|skfnti)9`rMxWp%$M}#Z@!y(Go%1CCjod{rEZUdUw!IAfzCXPeXG?(!gfaoD zn8e)`Y+nQ}^C(5agD(6w&0{eVN8ptzOO1!V1|!C|{pVooyZhWg0wxF068{}6GPJh` zF@ndOryS3MZs#qah1oWoqEv84b9e7>4T@BGdVNFXHIY}r9?%zWyJ;jg2P&)1wZ=rZ z=}#eCE`O~ykVyj~rL)h0UQT8t#37g3EFb*B$*oY=h^hYDx)i8o%r-PsDIGB;7<*m^ zY+yZ}@DicuBSiwEN9G9+#Lm0%W8)$$6JvTjXB|~!RDo}p)c?0=y;d_af+?@I<%U#G zE9F|Y*J_h^EXOqWG>jjPT3b?dKOo1)x zc=M4FX+$(gS#^Odth~mm*wn<_@Y;dP5ra+|3yjN_J#}2wz)Y)Cdh@jLr|!426NzYx8%3HhQiS&);g?Zuy{YB*K2e$!9EhfO zh@%0bPRqHW$uub0XZm&oe0b%^7CY{7tya8=M%A33ZtV8?Fr;a76e6{J5&|M1I2XI-Hvo&iC}P*>_LeV9ILn8XyJnYOv~?rP zIqSq=`9j#F-C~JM`Y}_otN;*`;OHg%RciE&{Q^Id!ouTPIeuM@ezyCGKVlvV_yTI1 zHX-JmQ(WpCk|-31`T0#1PD8nd$3wfqovOavKT9I+2JsSp?f|x2oJunQya_Fd+h10_ zBh4P!0-kPBr*FxTrwvXCmj_wE^54b5o5QUi&s!i&pxD9xWJOpt8R}PfINFn=&+-BQ zdRTI_TjZwb0RUXKUcJXxNR}`nvQ#wg8hE98>yt;eFY5D*`PRhtZu_?&MCW;TZ?2i6 za>q#5gkqv(hFh4dVNrl=U_BLhIrIiFcs?NLe)axqGe$}_BvPgV7zKsxsyn$BP-Mzn zQr-(4!79Tguxg(?!!rrwPohQs3EThz(+DUBTm$F3h*8H6HTf88AK?8LH}D{K9VGk` z;u-g>_JS0n){L7jH9Cm6%*8{rFE@P#jA&Hw=Cl(Oy$*PsN7c{y5IHB3-=XUS%ZQ{9 zINryg>7mKS<0R;J1Q~xnB?{QhO1@!%Z^AEYMZ94s?nQtAmKxv*ZmK@Dw#G3#m{n`U zoSDh1sPujqU%P8s_AYP?JB3Bo*NA|xeyr(4uOw)azyVWX1T`0b0!LYrlGJIcoG^S3 zK2QR)Z@OW$B`ujRZ@NCF%y^!IWpxIN5pPfAi(<{3Hv1D3P1PxRx7VN7RV`M$bucmY z_Ta_-5Am1#q3_&}v@jz*kQ?1K_wPZ_-x2kLJytShWbX1C7c2BSKm?*S6BX$`JHzz& z4*$R(KlfSashB2^`iM*@#Wo(xg5>8FFi78tlRaXD+8|AV-J|x%oyVesp0`?UZ zcV;|HvLDftS%sqS7+q&Zu*H;CztNl)*O8X8N7aN+1cCMFs|bd?Zwa`04KzKX-*VJG z2yne00MFKh=Lto@yA8HPDCPh=et)1vc3SD^doE&sDC*N#BqU?SQFT z&@#{-qE$|vH=_!dVC#z4NBT7`1fNebgUH_V>F=dza~S3v+4B~{YCCcJ2c|!E)3@+QPu7=eo|83&M^B*s zCsO|{z2e$V2!5aq*N-+gTVy=Ubh4Bh(VeOIL8kAf>}}KLN@}LXaeCG;n2x^9(Yp*d zoYXGIlHWRpYcwa*%sVm2D2Xy@xQ)B2p8+-F1m2eFZqkHNr#| zFS>qfa$jJVSeLVDijdnuvZy>)i{fyrO|W?AWJP};9novb7cLs+lC+vRI}gK@{2TLwB2%va{g#9g*QgIs$!#` zZY+s&(k+eoA+6sS{~g(a5Fmj+uL&S+PQi3t^4z7X(Mq5U*A=@bg?KtbyxrL^EfLE& z%>In^Vz{x-_-ngoWqVjMXA)c|h!-UU3T^`c`+nEmHy+MZ^aFyOv);0Q#hwmK84O19 zwhQ3YfgKj|q@@WU=JNgRYg8N*5!`&Z8^3kwapks>A;73R}$<>Fu1 z($9pg`Pp%upO2-{q0h|=Am^Gb?s|8Zu^tZLxJt~G)BOQ zBESnK7}yXk#3ldLUk}+-)jN3Wflp_9|61*c51z!KSWbXUej>w4o-11xeW(b6 zFxLv|gP^LQ^>6D}u$5#LGm5v8@E3JW2-A`V<{OQS#t@WB0_wH``3yX?**Dr$T9zQl zE)TDddY8!0M%hIHkQaIcMU$&Ud#S#I ztlhx$djE0}^pA?{VHBRoVGFklOz*{Jr?w6Aq-Xb@@fa9=KaRf*vgG{&)hfFM^65X} zPybKzomRHp9I_u;ZwjnsF0g14p{d>w{4QsihUv#;Sl+!t&d zs7~PY@F`;VRcm1CO3u1-#zx>C|rt0#6rjDp$W$S z25(hKY$qjAU~qZk3T!6Yv%>Lq6J1#)tCsqylE*!9XIJqli`cdSk&rIH93B5jf3W zGW(w+UKlw}T6(`aU@>Da-z}H(GA98FXG^e}n1EW@Dip5qZFsO)YdEU1oTKhSfiHgh zaIo4JxemY6^pUeg^o|YSecv850CSDg0~Tz_@};XT{f5)%KY_N%M(AxzE7_9ADB)+* z$aN|0otWSvx+8zS(?RM)I+&L_LW7=rHC8IST4AV>>uPYEnSCIA6yIDb*Cb=0G`Eiw_;z^;kZJp8v|Tapz6Os#HFH-Pibak^k2wn_sp zHdtr;TT3Y~3i#=ravnSsWLhrk>}puk;irK@7ZU;Z&)5D@sZx;gH+1TX;dHL~I!(TufU zV9;!-|BgEh+LtgUdHL+i{)1p~CO8Wjr^5-S&{T)ANAltzzrFmxvPQgJk7%DG>C{^I zN%t2W7z1*wz#3>0@Fd9h38c$E1YPHDVlduITfTfEby!gLC1qi|JPku*@OW_UgUmLF zFAKp}7Z4=Z)fip(E`-A;LlZ)+*^PNzaw6{50rm>7L!|if?()W)3=dAJ`wH z-2vZS=5zA0b)g~b;OpIUnAglj$_yCrV*Spb5mQ3GsAEa`4i@F!;^CyB|GcK0>Mp>w zL%?0Y(P!=elnXvGsB4f)IHVRNg^3j5!T{|AleAjRhaLYvh{2dy5GOq_Vn!XO`RuqZ znMP5dl@b#nI&xQ46$nZ*a6f{wxSH5`=xf%-&F6Ek{+h2~xhfOOJ9R=6kan$MU2FlP z$S@_iXwi5|>k#4l31b3%@jKX4NV&@2mv?M}k-*)FE<%S&W(90lNx=4RU`%UE7+^dz z^_}>wrLMwgV$lM?et0`yr6u)s5OpR&+&D6{VDs2p_8PR2HnIq*oI)XI;N4$@wPEzc?Owd8I>(JSI@e zMC}45<5Cfxpj2&39vaV*DH^k(Ag{zKE5M6!{O`w?nk_-f6pI@JA3ZsmVr-GY%x29> zmBF6EaG2Hso@s!H!?CfXk2C12{0<1ys*fIzRNP%QDvJ$96~C&^_ZMdE+rwHBXk`$N zDC$WN;Pm7U1ye(H3jXnip8N|!l-WOoblXzC2F4x_L-rmGLoaTHPkCuE-}iyFFojv; z$E3&x2FL!FKJ#Wo_OimCWON`}+=nyP~TYSVW!}g*Aaz(p?)pD(Lg2Vcq znn?cbURi&!*x0oBlpt~7;XsBuj0&x9)L(9<<=DVnKmT4oD;gG>9)>8bSliG;6Pm79 z30AZ!)u7iX-QLfHR!^e-lf;20cvs1CaC|@uv)Ql!%|6CoH@9hwli5v}(|(n3e)pL< zBA{%C0|By$Cvxie1>oJR{rZ;+wev^qM0WREW@GL4427}c= zwH4A5&UE%tE6$H*7i)N;vLXzVP@G1c;aE{_sVYjy(1du5lG(c9d&0e!izA^JD)-43 zAjUIMMmY2D!_tJy#2#i^xNR6YA%zv5YwCMUcSK(KmB!SvgqR?W1*9OE96hODN<{v@ z!^kG_;DmOxLSgCshY#JMWne?^h{ z(qn!f)&rOZ3#D=*FJaRo{I;j7zET@GD08}Nw9bEjpCIC$i&$!Nebz_}jagh<;jz}U z2}=!E42DVw);+2wj<&!ci6XGT*qa>qUO=#6f<+8`Q(%;A0mg&?#@$R*XoL9|kDPwu(Q>iv*j^$iy4LUs`QX2E6 zuhvk#IM{s&FzA~#1kaY8Oj0EAsth|E6nb8b5fDkYIk960t|Q$dyvwFnolV?UI^2}4 zc5yVaTuHZ2sUKwme=;cFIG%$IO0eYa`vPRYZ_`=+9$bgdH5lEOyKCOXa#XUuCvJ>B8 z*cm7N99jL=q4uP8L*NU;h@1+aYz7@W_F&zltXxFlGbj!QR!gReW$$Xzvb->9M3}GI zvmo)B3aZOXQ6GV~j-r{+tuY*}$u^?*1`BK{wcEeka{_E47&5HRPj4?CNbLo>d1o(o!L@(S>0 z{|(LRLo}pwq-nxIin_Kf1HVdu0mxImdBv>hQOlW=<{hHN?7y)1~Yk@?DvtcIus(O zvm9}{SHO+J+8cXYvo%} zbuaPVxriBkMOaGSvypw>=kN)YDf_7D3;fd0PchH%u?018BJYsSblbh^&sXI5uI-Ly z7=p3slq5`)VpKbudHA^DP=FPYw^XaOIq4Q^8rRiN>q;`}8{#p$ZHkCmD zoD6R-NvlP(fl5}!V2@&jAf}WD=BN0GP)gLVUsy9*j`p$(nImx-uWhBHBq;%|iF1G& z#aL3wCVZrM?=8nRtv>+gu^{UgSc2%)0mYA~2qttuvK?Mjs*Plm`XmG3mj2G_!7>)jukfCPV@M*}B zAwGOBLY!>>5h*mhnyvt3Mm41TGQ?!Urd{7VobAmW6G%P`7sMT??*$K?Z6Z}*t8I$$ ztwH5y(VcReWkSGQS_fWo;+PpmP+Gy{lZaK+q?)Xm4?50^_L~sky#LdHP&rMZv0jE2 zus?K7yWeDSSr2M2O_@aowSZDCkVH}Py_rHJ3zxZo;tPhN@VS(r{iHztu0mIJulHgW zY=@TMyB%c#-<0j;BJ#T2$h1o&I6KH*;By?K?Pn8IZ$XZsr|_hzhzJ?Y1=Oz_umf0` znPedYh_K`6l5LzQCM`p5H@+w2#j~ePQ+J}8!oD)79hA83ON%S_IPjUV`U_w^2*n48z=9$r)>f1$4=p`XiNvQ2UVl``$ zhY8RV8KDDNoj`i0mKEzIQRY_p7{Z3fEmq&Ljm+*9YCQ9{NKMot+CDjb0AW@~^5ShHtp6OlG0rn@6_4w|tY4*=3*BE`Hdu_`YWLEP*$d=731T}efXGz&oJnk z;0Kxvb%*=xSlFb~sJRYWR9CitWo!h+k_mdI2M2TCUP={_{rV!dBTX1%jh5d;m)1la zk?KnPuU>ntGpZc>>MrCnUl&rl-xp8#hmEtfPh+hxYo-=or<--NzSrYOJ{5ZH-Z&U_A$%OH*kF z;8e_&zBms~=(Eh>zeBNXn<8V;*pGPk^i8;)kQh2<00Qrazo?iX?QxW`fnm12h{5Xp zCEW@bH5FXh20L;C=Ia&0rQt;@es?;hU^kzyw;fV0G$f>g1= z+y9{GU}>n-(Qifm$|30IuqG%8TMKiMm*V@{v1=Fr57ed1?TrP!(8LQ$J8J{X#lgli zo7WEfB^D-}$m@d|E7*?((~>_ewIzA3>%St!vV`-d+`YXwcIUk+zk5oZw7wt2R%Y(p zP5rO1zo(wf#2=u$Na0pDm%wXLfDfCA-_)Y zA32YUaf;Gd26{K7UGFouPPxpJE*g5R1EV0D?E?UizxHlrA)h!Cn{#q(D}Aa6vI>M! zBdv!-Ku9Bn)Yq6EvP+N7hy`t_E`ggRJiaaw`xaJ(giKweno!(r|21M;VXQF=P ziMy`o&Ss~@gG{p&C7chH{$+xe0%rRNxOJb>_|axfiQs&bXWFuv>s!P18kBSEN1mD9 z+6aF@njzRGPZ=W(0_AZ!O#WX>FCe0XdGF*151_WP?R*Im7n+!kBls)dNz}cO{n7Mt z&$Sg_l#s&2F_f(@ZSqU)LAHA!_Pyw&+qq95Xt&Xi7|=mFwEXdh;|y7!mEW=FS%hYr z625GeYUAmywj!LD{+OElCsTjH8KK^PMLsq+_*`Rm}SnXL=n~Jz9XiQ8u zYbw^R3C=62^+|?|S-G#ZBH%GZx~r{W091;)*&ZIV)EuW*_qg_;wH>Dy?J7E(XpUpy z?CK!}n zX8C;o^s|^;G!ZJ+a3RxbzKY%=u%>ds70y}}R^=7`InXVd6ssb60Z1&)(jHT1G zJtub{R)!Cb5Tg=LPE4+(;p1o5AA}J3PM#bn(Y&cj zDk1N`m8(}IvZnFP zM+?c1gnAOBnL&h%-!azlA4OL0>=v2x?aa|Xnq%G%vN`6a=W3M4Vc(6>fW#p=5>wq3 zO)Ug7nQR@0R}fe}fh^qP$C<`tG-|uaT%f;NHEx8@{O&w7r*fX`g<$^Hg+6t;CS*tV z%MTT+IrkYZd-?YHBm3w+ntb1)3&H@B01iD=R&A%AJyVc^VDTD5&J z71ZE@C3L!fVt%Wfa_wkvwrxs}VYbW^=Se+3Up3&aZLmm3RHmu+Svj1)(=7E+7956j z0B2m@UzoBKm+WxVI}0>=|77$`*PoE3%eR&0Gbye6`O$lAPB*#Q|M8m3YKCnMg`dL)nHCM<1ryc ziO(prt&15txx+&(^J*Ps&pd&+)&i7Ya6=u#=Co|NSMVHx@!@IG`u)61?<}a3KooR_ ziKE?GsG#hg4Cws=5oT-X)HWqb3Z>lb24=7$cjQIzT*r^HXsWBhnn7zR$6hb^Rsc98 z;K2Ff$@Y8#M+!0oQgn19h118Uzu+O{E`cZ^!)4sT!8k~alZ%eFO)0?fJ8P#ca!B;b zWqn2ZfZU4Tgj`qRpq_5VWN|vq)SzGu3iHt5+_ zHd(%`FzKpl*al^eXzoOcpw|}ez$@0iftg(Q#%L0k*+jV%yr&A0m7<9H`b1!cUK-ak z?)>S_<@Kq9vrM@6Ic!%`FE#be(#9hx-Za-6ttryqcIz5u==HXOMRmCvTe+}kd?K}J za1+RrpSjfG-dy=dY{_wc%942nX^MyBa;-6#)k@ru5dBj)4{hwm)zX3PRHW@it-*$a z0!q9j%5llXIs8R4PJ%Z;%1L<0al|G-fDL;0Nn;7;LD|oV&5f}ZacT7lu+nRMk+bd_ zW{banl?HkG{07~%nD58UF6>hpB=ue4@E^BCxk8s5o2>A{^gX1ZRR`!1T94}~t={8+ zqoKdLV?=!fRQKAB?bwK^d%)mNNnp9qa!U0@vP-58^;yu==1w!JC_WzmQ}@b=W@lUG zFs%kDfpPsOoEiQyjEdUbCJHV3wo;1O&nzIU5P(R0G}&jdNZ?1UeV?d$NS-ITnlx5Ml=%KFU_`tLDBpfMVuDjJC}VG~GUhSJ># zgieP|CE;XEky~>X4W@7QwZ32t^L6^y@Vt4%L5RIK0vmL=I`ed4wfRd>tsI8RZM|to zsy3+I8#{3YRSnfl?PV*=uvtGvQ0(qxXtRj*U@sdJIlj$TaNzo@iTwhyEBrt`3nza2 z$@)wshWoQy{4n9Wdb1qca?@+=!~mcP5C-La)49u38%U)dyzhSg!!P<+U0T>vxM(r- zC@YYPzoV{Sfgp!Bh{fY_@6uM8=Vh-`%!rwn&sRRo zDtV%*rWsWR+=z>}ln=a!wo7d}j-Y!0qAs9dO!pE;ib!BeN4qy)&OKQ;UeMeK%CfB{ zuN0ikMj*wXRh%DYFN>+gxxOqVS$zEf%$PGRgOv%hMD{on<&8Yl7qh2Y4T(wIZqgbT z3;r$uAYj1A#na1^l%~Ss{U>dNu>@q;VT|I2R63?J^`u|qxiXa46-VGPdef|Z|6wM^ zRi(6UoZl8`@2-lU3c=o3>kEF&K`CEDP17f_oB&V)uEbYdS2&Tu+89?WULRJTlbL$}2;jh55KVa75ac+J@R{~9 zjhx||b2F$nmEAIV^Z^tvJ!W(hoQoGb)2kz}wA7i@VV489=Rd*gLa&$Pq(3MSsk@a# zrw|S&qt_v(&!)H(fW20qHq#M^M1iAFEDr=QUsWkWYir+ius15Z;}o6H*wC?8{{Mmyy!zSL3%E7jP2@Fx;yFb9yPszL&|zEygkQ4e*}e6F}m4{=4=V;o`Lx3SmKD zWSfgHbQ!`u{TAJwuWMVD?k}%LH-5;{zSjIJk_ci00XUJ?4@CBgKzY|UJ>Ph8tUXtZ zi%R`AyB-Tgz_~ ztF60odOQG9v?R^dLPk}!xL29KE)@F8d@g|Cd$2AEic7D9-o?1gH6=)>%Gd`$a$-d} zW5qH+s*KdX?7PBEQJKT%#)Jac5LGci?xA0wGFTL=MlH)?FJymmbL4)#oiUfks-}~@ zqV-oJHx&&eMoBYurg%^3j-J>la%9YTvphg2G#$gY6)*J;5mY+E12`fR>|_V zf!KU?xUOz=1oWt?SJFAb-A_ZFx79xS3MA;+Q@}(87TLOzmUS>NKdVl8;6As7xO0H% z3i5=pfY`8lNvgzLa&kU-1KhVC(k`0ce_nH)I7+SW`2zDgdU>Cxo>mR-Qd_ zxFxaow0!RblJVeR(#6TEm9@?@aD_}u9Z{VmM<8;kSF7`@nh`{%lLvldbdoP7p^y?d+%K#y%x1y%Rg$jm8Kw&N6U`OG< z5iS9|r%r>^(?6)#fSME}*%iJ6Rr2Hh=zc%Zt%rj`X*RSmBi7h9FdDG+LGqzC{Wj;v zFHI(d>n-n(kFIP`pluDehc_=1z2FGJhcFP`At^&nDzQB3NTsQX{$SDa3h#v?m`sr( z8RP)=_fPCpgOB0=-vY~Rj9!$@+B01}1hT|xHE z4YBB01p4yq4f@7%QK%$?-1cs6RyQJWv z`HGS^*ZGPvt^9wUvLqNdy68*I^B@lpn>#+&%xMF0T(xPnyd1ZoS?ZjR>mO58H>z<>^VQ ztq2+Q`qBBevOVB@^tN7~OeQrbscIe@O2V*y8L$xw`1Di=+Z7BopZnWlnpk>99kJKP z9^c=3vv-H4`wfrdujmv`QE)g**_4ye~AYu_49%fQ?7B3$gYgfW00;R_zRWLQ;#f0PWQu$y1!F<<`v9z+QbO zJXT`NS;PNp9P;_(JQ$<;Z2SOvcXCqdiwQ>q?9Is@kN%NNQiQXy`Q+cfgB=At>?q$= z({Ohb71-9pLq<)>(IhY|GPfAP$*eh+lf#65W>+n3;+U+(rvxRGGo9l>A(GuCqp9I| z{4ju%M6E=z^NX}P!lH9i%+`{X*oGnc%-C=RpJ+n*6^0i9?&HK8X2y(cnLd>XM+<*L z1^SfD3tWthhqOU(pBA)Ii&{n0tr7Huh&g?LAlcWgy?V4VBNZFcqYoi3D5L?^+6DS9 zFcj5ztLbkwSNS&(zk+sB2n+K3XOQy&{wq|D86jv0X_#j`#Nmj*Y0HD8FuST?s=QO= zBG2|76V#rL3M^27BTpMSgnS)abPljskC^|4| znxkvBp&6!O>4q&KW~*`}3$HSKB>)@15h_F2%qqN%?s<{#(^0F0ny^Wc^a_QMXXdF> z@J-=2<9VeBE?~5W2}wgV87{~0A`qugJc|wk=%){9t+I2GXFamhtCBHy_HsI8M-vz8 z1iYtq1h{bY=Z*TRW@;Uec?`-S0~ql}IPQvV-2hwPJ3U4@?~+arbb1tvr8j^OCQgO-RY9sb zj)0=6N>p0zrlS&6sH{-ACRBD2AycI{CgfFsX;|itBL3ox)Y@=ls&0kM3Ylv{=3p!m zYNao3VnZdQ;;t`z6@*&0AyDbsHN$Zo%P}n5(QH?b0INBh4p^rGYz5dC04!(IS3#?* z>N|>NNAR>Z9-VfD&I+AtLT4XwWgsYC1(v1@b`;exqN^sbHyxK&h06+;Yr-YRLb}2N zrOU+1>!4FNYo?`%J5kNBB8WPh{)|X9D~MJQT@yqpQvwu@7!8rq3)nEubYBpv3qW>? zDOwCMVYU<6V~fv{q$oK{bF1c@Awo>5iYNC)g*91AdaSS&kNX%wf3XT_tR`U9b6CxZ zEC;wz0`N;FcBKtBFK4Bk(gm^x>41ma@y^C|3zUo}RqEA($?HO1o`psbWE7aoe=p)3 znhmEXN_aE%%H+(aPy8eGDe6OSnj!5$5=QmTRt3Ii8t5tTftR}Sm4mYaUv=eM48Ep-R=~(g{-^0R*R@U8wSa0HrUm4) zR!i>FT-P*J*U}xZ&^vc!^<-DI1%2{!oG0=)c_mrw>#{<+#M3u8vKY^ZEbdDM7E4p5 zwcSPI<@}o!cn;7vjDn2t*%uqD1t;)}LXw1Y`mOqm+vF0vRifCEpelJ+If5$h|KAS~ z&QGQNPdsh@Cj@{h^H_RI`HZTpqs#XstoUO!!`M-5ZG8pVQYSBc-AKwQif`h;BPGSy zSMk$-Qn50sQ1W|`B8q=i)uM&v$c3gE(ZT_8q3aQe?nWer5s{c6A`#qjVW|;`CF`70 zE)FQ<;{cMCs-7*1dp*U2oZ^KatvvTr6rty@b8D+|>&mU?ZhZuK{5ts>eL4!&v)9{x ziBFrAPgg!Y_vuRlr)zX)q1rFbJdDbnD|eo|^BH23b!QyEG&<{*J6G+-;{O2!`Gk$|O7vL(2^H@aA)*MNGuWqy{|J335YZYS#B8D+`wa=RlmO zyKn_siP6Q#Id2^>&e`w`2C2qK=|{jb(LKT-&*J)V-B7a_PU28J!!Zl+H%1{5dSjaN zyy8S2^JSPWndqRwzxl@>$){Ttpg#}D=aXaBF#b6BGGIz#U`sZI1{8RbvKKm ze;e~+_>0@HWzvtBV<_^~NDbL9EKb_uUV$s*Y!S0e0U-6z5At49{AG-i`=uw2{yIcQ zRDKxugxPP()5qdP;uceJtF$3<*uoDKTlgK_k02Fb`)_Pw6y_YTKBs&i zWWrO@^~Ki39jO+5Yo`G#+R%-XK7=yQ&s15H%KCi#YD`kq_dJ0(MP0aT_!j%=EGlWV zRC4qJb}a(C$4KHkmkDWRK684!HeaEBCVb5;v8(Adkog(%RTne!s*7v8aeo}ws=2_{ zRLgJ;$1nw{Dk5r4vmMd@b4#q4Zgn`%*<8!b&XLnxGTlINKN*(Bmy%j<3F6+Y fG~Yat&J?Tw;_GihB literal 0 HcmV?d00001 diff --git a/Graph/Images/StateMachine.png b/Graph/Images/StateMachine.png new file mode 100644 index 0000000000000000000000000000000000000000..82ef5c8e4d51ad1aa5f40441289743db8489d213 GIT binary patch literal 24128 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 literal 0 HcmV?d00001 diff --git a/Graph/Images/Tasks.graffle b/Graph/Images/Tasks.graffle new file mode 100644 index 0000000000000000000000000000000000000000..e64c331c6d521852ec8dae73ca7864b344db955a GIT binary patch literal 2361 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 literal 0 HcmV?d00001 diff --git a/Graph/Images/Tasks.png b/Graph/Images/Tasks.png new file mode 100644 index 0000000000000000000000000000000000000000..a3f62ba9e5b50148589c23cf023047320dbac57b GIT binary patch literal 14987 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 LQM^*r_{;wSZS8MQ literal 0 HcmV?d00001 diff --git a/Graph/Images/TreeAndList.graffle b/Graph/Images/TreeAndList.graffle new file mode 100644 index 0000000000000000000000000000000000000000..dc2a180aded364938e928938bc31e0695f5c0dd4 GIT binary patch literal 2648 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 Gga7~^!9zX( literal 0 HcmV?d00001 diff --git a/Graph/Images/TreeAndList.png b/Graph/Images/TreeAndList.png new file mode 100644 index 0000000000000000000000000000000000000000..14004c9c66d99468f2edb5ef46ffd6db7f908a01 GIT binary patch literal 19198 zcmeFZWmJ`I_dQB%X^?JYvuUJDx*Mds84tOhJnt|5 z=Zy39d^(PS;=Qkqb+0+sTsvA-Sr!wG6b%jz4pUxEN*xXkehd82q9A}LS}hJC;2(H5 zby*4c`9bC&@E=rXIXyQxICQ+nA9%Q|9AZ%5$16=;ciopt0v1jVtY(%@=2ooU4$h!7 z9GsB10Ql9x%H0g=?O^ZdCg3d$`=^8e`2F!Q8w~nS5qCRbnC?qesHBst6_kgSo0T0V zf(C^`gf~y}#=+0e&&JNl#>vS7O0c;3 zIJ%p8vpBj@|J%rawIgNaX5sqE+5MH1BlNLdGjk^ocVQUpv7`U~^Y1v_Us?Z8PmXT? znHHEJ+v6u}9IWhY|J^pID)jhNK+?&<+11L;4YV)9BlJ(n|Kr*J^z(0dRa+-_C$I{x zuPo#p-K|_fWp}g3(TQ;Wr}qDQiT`_BDz2}rz^wnN&GDbw|NGg0$_ueQPW*o@#J{Wj z&r`6>B4|Qv|Gi}*Xw@5>KjGlS;N+#mHND{va(z~x{dV4{?fVr|=Dt0k9B-b| zeiaE#@`kMQnxV%$cyL?1?oXhovl%yT4{Uv(t~Mb{?gG(zxZbN;3Ap&#;;}ceVK-ap z@Z-~u{QFb-Q*Ul{c@{95)hIC``tlvS{;{c?Cdh zppxI_x-}#ohV-M-$e<3pOBoFNJ9gB;8-jp}nGpCgx|dl!3qF^B*Q|!$X_?i5zx@uI zZALOU`pMnm&{`)RCocn87c!GJvD>#r)_%C2ZQmZr zyS_yRtA|1ma;c&_IctU)Y!Y~7wcZmg8G&)s=;J-aSZe6;L(4xaoHqY20oXKjgy@Xw z!YUTw4`(j-w^#qJbc<8vuUxNZdwZkVFK)J>Po97s!3mL40xib0?#5%Vwf@QvdPer8 z(Y(Es)v(EVw$iAk>{diC5EabM8j`~KIJ-mdFbc=>IJl7s_~zLvlc4Sh%t$N>v;o-| zbWjQ%K|T}oYa}okG_&Z`{<~R`K)$yqL4b)NePyUSl9*aw7ZnezgtHWs5l{QH z-r}N{p~kc`lp{q(3J1(v2O^RC*niDM_AAKpiNUqk*7^Q?k=@68!M0;bu&MX4VvkMl zJ)CFEJa8CW;7oVnZt&3Avy{Jy20OwBOG-t3e!Wn06H1ro(nm7gKi=!%Gjwod(&u>>8h!N?&ydptB?qGZ9a)^w?%M*7y_pP7k=wtL`CI7ty5GDx z=xKV1*U7{f8BofolcK;7^;;!d)d*SiQ{ntxEIA`q<}NGT%e20l{*X*9d%iQ-Evv@} z19#FG$F$4X@1P!R(}}Rz73txR&*`(i!jrLW=a6*d^@GJm(W}k3Hu(YP9U+K8mutvR zY0>dJ{st_(D$NB)T*`9GQ&z<)To)|eE!9MsS`j+iw~324ty}L5n6y4^R=w_3FRUU6 zIhKiV8*pg+IRoxB*!NbKjXrQ8yW{nfdvE@#i)+)gE{>D<}v$ zhA!cMP|127RF@K2AGl#+x*`oESIpNtMTtrcY^|s2>8wV&jt{pdhWr4m|{As!)RX* zhu``B+1~66+ld0R?g*aO-x)MMU_f@fa>{2b4El4w-TudDl%_s^#o+g+^+LVcW<1Z{ z(qMk54xEZNA!13WWD!D0DwDGd)xD;p*5O~Z@Am7)Cx$=kR4uo7JRhP+8{I|huS1AQ%FVF#(vxY|2WC>^V*w%G`Vy~&MGScT|O^{P4$Sd~H!jcT9K zdA*VOoE{uE&w{bHU7=!A*h!<$AA}=1ueY?F0ZgcC@(BFKK}+Qxb{ zJlwxcc`S+@a8TFJu1of8X4cT{<*5i+i9%Y-$(W!Wu(*v*CP!oE^Wo}B*m9%@=1-57 zERspef6{j6{H(W|{r%%}QIn5N6#pUx>mUKd6%M=|mIXL`!|K2Kn~!<+%ep=ZF_aM7 zr+VhgWq@Sog;TL@pRnA7r&tN5K|=&ee+o!90;N+w@P7?@xPPpp0P1YQpyx>=0YrG< zqk{ixh+ItU)FVPUF1vHV$dJS4>jrgms8}HmwqKONMenrf0i8<-LPp)gQDPAG1>7Hd zP{M*1l&A&s%WY_1x35-ye(FR*tN2bzZzGpw+uo~yMh9Dt5KPKtr%H;roMN+qCUe^! zmDgNc`q`5ZOKRw~K>b6CRkd>3{Y5*6jhi@5{}%1sz@Lz0lTa}j=y>2y3rjT8-U?60 zIbr~4k&Gz?ObZuG>tU~9leGL{7O9keI)_C^T%eQsRj8ObHiJK~{PZ$&6A&JZnQ@Vu zeIu`*T2;oa6Tb&ZEk@=Ik@RcKdvT~`QdtZd6w;XV@T8dtA-GW;7Ky^=BV6O(u77_v z2{`-F;ILR*Lc1B5iSVIwA#m3mp9qt>r)x)sIhF8qBnop<>IhzgNHVU)asW-FRlQRkhz=*YrQj zCSW*r4~Xx|;&oUkmVevi&hd@RwQj12Db0NBaH>QxUnHP<)-9w;0p~pqwFkxv}Z>a@}ZtZ6>` zdtu+xj=#T~61HD9c^|C<2jMzJk@eL|TR<}Gp=Ru@2rz#lS5B>GGhi+0&6_Nx<+=rL zz`2mJ%T8}Y78iM5k)-e>Bp9W~bA(>fq|UkRV%cx9%VFUQN4;|ktGJ-({pE&1qay{s zD@~7iwK8(5g}}D`vIBTrWHyEs`i(kB9v@kU+(jciL}}Uw)H$-X!s-y`DtI>D_Gj26DRgqE79W{J^S6w%ENN4)v$Jj{?%nf zS6u*b9OumDGf&lo@?(Q!#T>+C{hsr$g>x4l;doj!|8>P>`eEh{aW)~7Q zuiXko(Af{2lUIr3`A%3@da6m|HEr;fd2C%U3V9O0Y%65Mi=ToA}H50ogk*(=kI^!k;!T0 z&Jx4ZCRG14m6#KM(_)Shre20ZV>QyRV>0_mEB58$YVPS?RlDO{^;)WiGU^zU3Lna` z&(!3U5?)Ag+|}i8J61}lDq&zU-G}>UyiUvhOD_FK_oq5SPZd#*edcz3mN)+`mcWDi zE2~TrUUsT096j0qKS|!0fN1mN)7O$3=)ZHpjLH@C+Gg-cqUFUAf8n@9OoJdFm|!g~ zB6=g7Z;%UC-7a9X-Z-A@1)XY6yP1^Gcr+fpap2Wf=TrG>JZN(Xh*aE_ z?w*}9us3@(=5A+&i6Tv_q3FQdTx#*KqqHiCg0fjaSFocVz>&JOi$I_JoX!2Ji|5#o zMGk7;3*R%8bD6v}%o_E_ljS9~A2ci~q%y$YGh%F&Lb2T- z>s1cxZEYXInyJ#^{K`xZ7q$4s!$wKdIy3toZrUGWuP&qNywM4nJ8;it44izV^NJqg zZlGVWTq2|`haDj1l@2K`E3A^66YnJHtT8Oh;)%TR7e zMQ5Fa?=N&GrH6R-cddIkoy`f_ZaWEsMdRi0QXG39SJw|a!VkEua7?b~nb#d0el(^c zgscY#Cvs56&qYtpc7(v53Ao#yY>%!4-W(tzV_|zFY83a0t2-vGsVadNx-zhjL?-@6 z$+FM*Z~t}|iL+n4u3@sP^MJ-7{gUjL%EPYT8cO3zc3Swt7|6Fha~Op~tvZ8dgSRBRnvmHb5Q%kWX&Dlwhw zD8F_B06?@w_TVL_RjQoZ_Hcg_mnxAI+Hrez(j0s+%+{_X?{yokHN^2#$Ja?$BFJ z31(1?5rsy~#Lvi(j3t%UQ$eNlhU8N%FVj|vU&}`2*TWRHJoi@UZfGzX0_w!9G106{ zomF(j)Ey3R+AwlzCl|_VkI2+;lx%^6-H{-+bXMQqTR*9+XTEr|n1!1OTIy{@{?(5B z%)5grOz07@2_U%4&fXKw%G_8*A8=y9v}Yn{$n&WRJ5m`n3?Xlsf$J(4DOP^wkpvnt z)iW3L^w&=1Nm)&Z{yK2HHOwFOn<0Y+?H}k@Gczj=8p^hccKCB+&uAx!+s&ArM^I|- zH!BwdT}==J*5)s0#Z}MTKvv8%t)2>1c|OOgpD}x2TYG*}4`7TXoT#ccthOdz{W08Z zlm!5YJ&<9Pt{VmAm^qlG_R6B4AOoY3mC3wl2uvtFnkIYthGf_SxMbw(Mdk6z967ar zzMUw$3~6VUNl>E%iz%JeSAq`vAujhDln)u>iu+BBc10#p?J+ZSN)3Egv7ERNP3)+m zwwbR@ys87gXg!6}>L=OwtSDW2a4h;0v`ET9JDdCnF5hQ;!D1u-I=~ei8(P>Q&8bCY z;q>_ZT_`_h%3mBxjZiZ^YsOrOiGS=IO%Y`Ea@Ls^Q+eL0?dk)cl}%2iL=p?6sdg2h zdD>#ZAfK^!#Q!PpeBuzDi(=*A4oVw7lPb1%^c|j2O7eXIPXs~v7_=5nA5AIGJQQX47;klS;eN~IsS!W(g1wJ^lAJ~@-f)+S!)*a59) zAy_o=_0(JzBj{NRRJBa?{pZS-Pk?H<-I@>Q{9azJl{59p795R|=9Zo@cre=}KC99Z ztSb^^2)N~qK@WlV)@m7DUMm4!mOmbjhuORr0%{ zhW$bFqk4YOJ^u|7SbvUB7G!I6<06Xygxw1)$&DL)0dxS4+`91-_CAhs1*$(2975|f$;G<|%jBfV6Z!tMfaHPXoQAWo_AHD$#Y*_DXw8_4xCQA`6 zVL3J(7|092=IbAy5`ojy6OD(-9QwUPmk@KV9ZdG_8s~=_@Q_m_aAA@MKfesi8L?1e8oS`nV6Os~49g|0T4NUQtYh36g zQuH<$3Y#7jPs0wA~y^QoH~Dj@lWQYf>kW zO094UJdl+}CrZCgTL-S^-;v+Nn1&wgZVe2>8M`JKbh7++Hor9wkM$GxQ1yi>kf7}f+!Z9xK=BRJA5dn8Oqj6^a z?}#8xageR#ScRF>TG5YIwA1gWyVD$-RR)b?x$26Ck7P%M!He%p?3yXcsWz^!nHq*b{>emi18p*H(BCX#n31j#_l-8cbvKkY0O|YVIQaNSNZL(1j z;Kej^QSBVGWy&3X#9kI`_B#Lcn5}WvW{zFU(7_rumi7&@Bz|4>?O5Sm+3#K|Ym&f| z(H9na>TFwS$L|ar-(Lk6=wh3OT;zH!s}<`|ZCHm@8hw4n=PVXZOv=Df{Ox?fF6LB% z4n-Fysym}`$RYqs+Qi}kyxdrD{L6Vh3f1*}+e}gHGO!Z8*{>^6Ot+>~ktTi{(F z6Jfxka7q6`9Nq*F6o3r_P8`1;^^w&ae>GiC>6KyaL(6EIxE#&`1`lvOKXhhh^x;U#;Fq#?Hc0$V z^B-<)x)FQqTolv@v5e8t0+wOeksN=p+5!VcwV%2DSP^<**=rfnI%VWY*}TKEMCOmr z9rG8>%q^wDY=xX0z3^i*;V_3HNAh~xkAM~?Te^76;~B_nIF)`A+FTyaLyd3kT2U0Q z7|@Zc?A&CvQ!-9addx;_AbJlznT#4As>ShpxDwg)&aZ3Y`Ro&~Uv_0h+bLk%u#w}= zF>Yh->p&u1%W!X5*&Fya8R^x?>8jOPlQWa7r{?e}<3@U!@x?G#I~?Ut&Ij78fMGyk zTCd0m&#H9}PNaSL>fi4(Wx>wcoeE)3y=C~8Q2BCQPA6r%hjNvK ziB{b7KPl%Y;EwPB=bnOP%cSKu{xp9U%JUAL;>MIUl~G1wW9u0y%5h-$!k#Yqr>4QK z!oy#Du!&xY-8Q#C8rA5XD$5|&tt*)()1G)uG zios6c&f%RYsnRpsO^LDCb9Td@lPzTJ>_FQLKv~t5vY2$!IL%nIJN8I0Om=q=%howH$WZ@OZaFqxtZZ z!A3-e?y%LHB>D!U?IIR+n)}B?@wuQ_&jc?Vxm_nMhHI*$KW;fac`g@DgnZq(RBc3> zDIMw)qol-{u%A5+Psv@|mGB;iHOQKwMQK*7kfjAly+b5ry+#^}Wnuh;eDpd?POOEn z_wVGHbh#SSOhD(0^^t^09tBl-(iIr#S|Q$DXE??^;Wk~vc35AC<#B2xx#T}p)km*e z0LP$z`+>i@Kd^{(8ciK%S^r5w9QT)mY%{JDMqDUyNHIaQ(LfTKHY+5rHbMAYmnB!O zq-{+CDc-0r+EWDu#ifl3+@h+`X6t}a<68j2HJLn1J0~ju7MG4C^q|)m>1BzNCTv@a zIo%!L3y?~En!_=Lnosxx`q1<-K-8a*frG@xbx(A=u>E+nZJvjAuXZtjL%8^L@SFK?3fDvRt<4ov`x? z!u{;M$X^P(&13jwr3Ae^T$i?pv{D#r4|ft!p~jXiA%l_W9QB%yD0v}Zt4k=i|~!rAOuu= z!Q`ij%6kosgbN8>XP@*|gcIT?lyerOzk^UXJ*)8~1X>{y-CKl2n&YoL$Ddf3FescikmnhN55qin!qsY=vpMhkiy zan}OEDR7~g>-Qa_hdo|DZm7CQ^Zf!d|cIAIbQjK@$AfB`+{D=#?zk^L2O z6iFG_B>$Gquv`C==12D#5*UfAY$s!BPUzT_U4v(Nau~6#fOfrq-NwYaoFvSPsrFaj zdRDg8Eq_VLMhsPQ4Xea=|oILOK=#KF0 z*8*eAuR=Zp=XTDMyJdp-$6CLz{TzFPR`Pq`W$s$8Y6ROYI=}kmTa+sJXPO|{{Sp6x zoiSok@A@&T8SI+#!s%HARzraEl_{Z1D#{C7$7tF)lt90-JOPj2>`y0W6JQa^1GV^0 zTy1dP9cQ@I7*uba%_V6d9~!YSP+gq(0JMtgr-;Bv5V|54x7*nCy5224$?FclZYttVm!O!fDm=+dps_G6i#%+z%}-S^`5i^(I}Nv5 z8k5#U^f%Kf7FUf++lOd&2JyDxiAlNe{%2z{JC4PlbgG_BysAC&wOjz|a%OGLN5HM-l0{)|tWWux|q zW)hOZyzZlcbb3OA7BG4t_&RG?rGg-PTq#h*!^MGDW0UF$Jn!A5jJ*8F^|-f!RY#~I zgQO#1p!HEU;Rlh)+1VV4?&gp~6L|LRl>uT+0O{_5d(@ zM3D7pv8HSNUSjiA347>Lb*NNy41F6+%M+(#i}I4mQUX9C0p zmw`f`lWn&4+uC>9Aky0*wc1DKv}uZ;x9|^rgDMS`3V1mZUpFS8c$YxjK&zKXk1vZO z*npy0X_%R@pD1)JXHSdY34xb}NPM3?be#3PibAJKnDf-7q2)tZPoN-|T*F3&bWP1N zInJJ+592N-L>EJ3#g=NqEEvewgT-{O^#e*LV?z1N4JMOp;!&am8)VqSwHmNdq)nc; z7%eWwAritX_u?!j#Qjgb+E_7$YyF=G3(MXd(Q_Qh_$(;Zq^q7B>*uf5=#(HKJ2;^B z4OawlJUtWLET2oZ=Bch+Jbxlw0t^yB;I*IgXUEW?ATZ!y@L&P!dBU7-O>fOO=)hJy zxT$SDq2h_W8LlwG^;x}6qn%%NFO7M>l)5{Wa~CRo_0T)-y_UcDB5JS#6B9p=uMLgb z>Hm##6FS~{%%H(x1HR9|{79qbFsp0B3$*cRJJ9@p4zgXXTRNK>F0b^{z zURAbXGIl@4;k z&6HsipLN)}M5ej#ag*r`9KL_73ixWYNX78D zvpML__gV3!%7X*^w^0;$@{>_;jip`(3tCGxJQ7*m<+|c|LHAeO*jA%%4f>xnO!hb< zh;^f=JsbL@?!P}joV%Ky?KD{Us6p>&vgYKh-NtV_Jq!P{@&Gd_>YrW(AA6;kGPD}V zW%63~q2C)|=B<9zv^bsp4!S++2TlP9rCm>}h)Rq9S!sVLD@s`Zno>Y%5_HFNZYR?& z&={8r;MdU#VE+J6)1bbo192c>_Z@7WV^Gnz!wWdQHkK(;2%&o$4l}oChw@5Dg&?a$DoQ_y~m#R^?LKKJiC=P;jU_z*=n=yx5@(1MPYh4%%&y4>De$Z zf=5K^pnu|{9xS{!fNWoYe-SS>l<{!B=tP2{M}G3@`ugjiHiK%@&ZTBIe#ee94j>$W zDb%^|PVqJQ1Gx7nPWa|?l2NlW14J;dGaJ8p{mBD51V8}{qhlI)UL9|V$8=;A7j;#q z0c4Byvhztm)aF;wb?v_(u$&Y%Q*VfHD`e!dl)BSd49)@T{JqMg9fZ&c zo@>V`T>`TB@0d3*`T&1NzOGa<Vi^E4d&c{-&>8X*hU+y}c?EPkMx%X{yh34Z=b5 zM}OvOHUP9=kNEZu2@Q`DrN@1wu5Iix5mmk*XR=7P?vpE(Or){bPY2^>5+rB$Ac1ZMGF+t<#4zdx2{>!>S2o^xd@Q9?vk_Y z&e#0{gu=|IJe_KKi+5mB&G(7HZhq~J&huY zOURfUD*Sm2eZD`g3gZkj(`f>?q3x(|BteOVqXG;qV6NH>n07k_-`c=XvWh04c>oCB zk6@50%zJ;XhN(x~Hi~tk+0Dki28JiWc+^`ohbEo(KBbrNO4Wd6#0Wd;BxAgw>S}CD z5NEMQ@nm05NgtoJ;hCRyU+P+SWSxwgp0=Q?Sg)J7iL1^$c_W#Cdl~%|)ppirRh{`q z9tF5bQcY5_Bh$33CT%&w?o}3a6phu>8`1uA6@>S@*ily*UemJ~Cjcm2fQ2iy%T^S~ zf9Fr}a5}BR%6-l}bDVDEnK`SDl&@AK^E2q-&NJ^w#b>{!U-xb8#0e9VbOZ)T=nr74 z34Ghi*yRKMb|N$NFmlHdvaFL0ub>NtYn6$D&dOdAZnL8F1dWvbn9W#3wUZFSPTy{} zIjR>4y7%`YwL1hf6}!w$-eyMK&Dq`s*fay5zK6^^$%K|`UP`qj;3+Sv6aIPe(;e@* z)r!4K3o#%q|E%NS$I&0-a2tLCVjdg|k%|W%#bV&ftf8)2*!^G#{rOg`+dGlLwS%nq zWj60+4#QMw(pqY0OTVwOO|fO~6+HqTD^@#Ekc2wu;7CWvh>_bP8758o!Z9ZSY9UY= z=zU)!oteyO06CHpF|d_ujV3-ByUu!gV3X$)5pIxV+;b6Im)+!C#@-1}_#kAz#niKF zJI1$x@omM~S5X$b(S0e?<&tNt`TAY_I(tZ(6V`d?H$e{Dx#=Go3h$T)VyPvn7@Yn{UWdIf7)4o_%*a-m5wq8|qKQR?FMQoeLg#(F^BQ0Ms1P%7=c7b88u@3le)V)y z(yJakpLk4s?Yzfuq}R;s7vm`sSQ43^xfIe@)&c2}f_zegkeyeMGcdZ)p%DUDh)x5_Z7>4cyN%&2oqp9ezB35oe(f2NP0< zDYCTG+SU{1ge1V1Dl+N5N=EZpEtKCXw{Tqe65Ub#|6EmLY6cNxv`{Cr zwZPb*niw16XFdA<9%d;&(V;@|xE*UxHa7NZ^RV#!bX6-177f=--_b;+Gts)T6t@iFwt-gQyWhC3FZN6NOD~)tR zto!p;QKATJND12vV6=$Dy5&ZEWDWj90x71UF7cWRMD5KYZ~NqnNkYa#ph}4Iu?cv2 z6Wx1M6?BJgV!fh^9Rj&n)KC%D3P-eaF0@z470?Rjqrk+Wih77X5~dJenu;ZO-Y0GH zMg|Q=T;Os{rY)XPoJy+zORfuTQnn~udqTeGWn-VLvWs#>LV^J9>#H-KUxvW5?nI_M zjhr3J6`afivN8>}u_LRT2Y*lY%9_{b{ckqRL3dc5uBsyudjQ17@0W?qWS+Dsk zFE#0y1pMHbrA;>d1j*EIa(<5ArSefkc)-W{f4@N|9H3 zdR~8)@4|_U|IXf(6Y^(_{Z?w_%fbqS)2aMO6ir5ZF<5%I}(*m3v`_^bixykd~uU$VQ$mSf#fB^3=Rg7 zI@0)Vb&k~%cyBy6TH=dd_VlHGRFv6sL4JvC!}2)q|T{}70c=O z7cWrb(5%Vop5G{bs|<^I#-XTzRlHglOv&LH2lQWVFFT{@^UAuW!~0b4K(K}Sm^_aO z(m?0mmX?=}JVs-PADx`b@)dHxp>JR&f;SrkFj3=5px|MEZ7UFlOj-I%R3vO-Pz!B3 z|Ma`sO269a><$qezVe^O%^XhcIa-T zMwZS+d8s`}6n=#u`On0AL^2i^$Akew@(}L?A1!c>^~ByYsxsJO#`P*KP$%$()<2W^ z)r}>HaTfCKBe1#7#Y$Ksux0oit9Rq%az%Z>hXfMcOe+uITup8?#lELjx_%?_*Y$eO z&C({!;9@9_9}q%*)lZeY_{aC+a1^&w>eOc!p#^B~K`GoWfB?nUPl1?HRn=$Oa~d)ljN^f{&E^L_4q@ zbaMIxYDa};Do+CrB=)CXqnRs%xW`9DmqB%LI5)hT&3yl3c>#06pSr)O6lI~i{E5NC zN^u_!Ufor>-RF`-BAGXAh$L9i*+2s4e(9CJ-ZcZ^e>)1kP8YKvn zqRm#^6d}dv2xgBmJo`7($Nl!g<~=BFRr9?s6^oNP4_VPAb)O_&6sj7Gr2ui-=91gE zhto4iQuDN2B^3J^kVtlS^CH?1_LgtQ3HM*Xb1*G##@v+p>oJ#aYMT+8@j zWOg8M`oz-1G+dnx^mMlVv4^E;e!)22Y@m-6%gwK{xQV*J9D{=|O1_6eeh`xYXae7N z?R6NY&o7LTzD2>p=#G3^iU!IRO9pe@ecN=lSCKV+NzW~0hQ3u|+bfkvEeX_)mZ}e> zuy|{`uRG*W^BXmcc~472b-tN#HMTu9bt3Zt=sAVTWO$t=Dgp@(P&wkjav=+&GoEYJ z(N0TEYWC%xmgE}F*<0ToWyZ1X^r9Fg#O(@!IsgX>))XP>K|`7tw0&wm&|tBik}`R) zVEiw}RNzL5YD+-+g|L=cae#>}*+B8uo$7!zbKVz41t5R&IzZZE5ZQgVF@D)D(fQ=$)W1OgN%5>`*8q4F;bJwoS^6{DC87An_T<8J#$3T}U3-l4#3;2EbSN~4|Yg}-Nb zwEV$i=QBqy_Ox_m-b!7$pJX_pdX9-7P(gBT?_=C<}UzZ=$IPcbEVU&y%5Qx`6{olwyhEY?%N$ZOUHMg86tZ{i{l z8M&*00Q+TjuMBO6C}j5YV{{l0yvtv`*y`4S#+e_ae5eSYeFrfKY1Ad4JPm#^o+s=# z=geTxU=L(z%7O=9@K>J3Tkio1+X3jG0mmrw8EC?XzP5TEECBi&YwopY3u;qLnIV<6 z)fo`zyA}~=uYNhI?#3#L2jmrWdkEJMQ$+%asS#tZ7S2#2BZ%_eEP*{ zMFfsny%?pE8f0=Pjb`xxk(MnREhDM~Tz#FxBCqv2(7XeBkHwepGYTp6nhrnCjd%qF z^}Rt}0mwFagsRWA%Ln`)1qiQW8AFg{tsb*WfY=g)fM=gf1<0vDNd6@~6;hDmJLYD) zSyoF^*C~f3kKqq^oTfcF0DaHZSZJg+=^Uv}1HDV{gkk+_Ez;P+_ccH?FYARU2l7Sc zuEkvZtn5l;dFuLqmM9WQy6!gvl;-QzZSTYw+yEk*$EOWA8oWpU~-O*9w-{^=#q zxXN$l+Eq5w#aTgHd0tJ?cs}U805bciUh5c)Q&?N$DZ^6`Q_khILR+38CRZQ$9ux?O zghY|+9e^EMJP(F+cpdW?tw=U)V>k3f;>IZEhpm8`w;CaVtBoGeO7A>OW_4nYA1285M_}K5$ebP(ey7aTDdSY|J z&+BK6htc`M#RB`V;oBTbUuO5gA})M^%3}YIK6#Cv&QadBMq2YUpirXpJFf*CAC?0y zjO@#S`kL8y!iZP3Tgdf?mJZ29Kog$d&>ax=s;ZolXmD7FbCU)(J>32h7W@Pngg7jmdp)^G4MIBc7PkgPFjO5r4jGT!mP{Myosxw z{9F2R(^7nBU9&YxkT!PckdQ|hHGfm-=%J3dN;#(#DjJ(X?TO}~60T|JbL+-8ke4m@b4{9g&Sq@V3o z_9z4?l`!vaF7ic#+JqHp!&&Gwd0%UW&lQ-}ha;V8_6+4{@%9R{%$K24;rtkqy(7`U zz_#LEDC5GABe|)wJkd0YyR9N(Gak`X z@jSoPJDjiV{Vi%Y!yMEbuRcc`Jl+^f%PR6FER(|`q6K4I_`(o~&gbLQ+00AI0Z-Oz zX8zJWNJi+*=|OxC7RI)Iuxk}rN*C&$- zOpNpS?lkgU*!p?Dc!{RrDNl`N2GSh2<{M?%X~1uR93is-W!crdgb#gZg+MiaXnEND zX17BTo-AB2GkJIn$za4E`Wd^l=slm3X<9-@R)T3%WYUaO)wsP70=}~kOIfbSwORL0 z7f1AH1k}MShid^x1O<=rGZFj@$7RL3({?tC_REoG=9&Pv0bO?1Ytlwy!U1ve@3u^b zwh_Dh7IhS;&Mw`Fks9m?%`wqAc^%XS90id4zBlVV7COnz)Fiz}G+}9vTw3J}=$Uah zFAxDo3_iV7-3(h+)P5NVs>r|XCnVtl2{|LyL%nCQai0L+&%d8INU@4e$H~q7uH{sZqFs zcsv}FC&}3N79^%}%>@Q-9H=R|3VLl5@0(318T~%KsAs^J=d9ORMI1TUN0Y&+Fy=em z3p3M~@;X=17|fbl3_o9C4AUXgE)5P?HL5C>`DNJ8*V0;eM7_c3Ze05@L|K5noRyOH zD=HFm0}c6gn@`vaLO2`|KFYNM5Z+m<9|>qPJkM{=^Ec)6B2W_P zCRrk=2wvpU-jX>sNB=cMAdPNXY-KTy(c!&JQwfdC1J}A)_mw*A-ZmOpqP-u!W9KV# z9?$Qr=r77Hhd13+VAS0!=aRqfv!qUu2#j9YC^Jgf%uNRrL&JvbdrrwGQtbzj@DQ>s zQ{N)NbRSuiVD+nDRWpJ&bn9l4Z&5dKrA+IX@529XtN0ACBKVd@h~5>2ih+ z;67=WG7V}lu&s!gKDAwT_mUy=>9Lq6ZI$yVlxgEnRz76ouVvnz%SkeF-%8OKIR&mj z7faAmaF41d4RVK2P!SSRwPb_YjEpqGn*XRgl*y411sIhm5U|Mjn!kGHw_kG~Dn*TG z#-OR{R=U8jmGn7AFoA6mKB`r(+I3?xRkBisLiRv2q}3;yNv6GD)9?ne^jga z5%mU7IhAKYP|iu=w3}|7bs9b0Suqk0@11RWXCmD(YyXRUT8ow#gb)4FCSgQoiBWfi z#ln1_U2-}bgE%6)_;31azC$@x2_t=aHO?X$y*t!GKZ`QyPBIcZqgWAChloK`+r}r5 z%YW(%U7H~WgMr!zlKdj)miD$Y*yN8zG0mij2>e@u@oUn5k1}l=^ioIAHwl%v|BRBG z5OKM#o8V8WN`nCR9zS|4EumdOAl7c53UH)aRNEU_1_*gR+av_*?%al*hqNaMsTT!_#= zVZ?fiFF$oB#U3jBGFRZoMH7U4EY5jSyoCv-oESJa(H_U$m)-sjS1HXUVeURg@naJ9 zs-x(Pig;lVdqva;-l1Iv+tuB- zta4=Rrf@}LcArTW-ANGqSQt)mpdF?3@0AI z#a#S*bemPSFzzJ&qj67eN~|VI#voRkU?xxcN04r!`n~cgEea*;=l$hY!S3Fn={pkh z^-Z%ZXL`30T7A44Ut~w(-OR?h3VR0wky}&$m08xwAk1&(81P z1gIrW5aLa#0DXX%>9O8??xD*(x|dK9qKLLAtx8V0BiC+vW9*j7M~idPi}_;dFQBz< zG*TItM)G^`#E^Q??V3d6boM|-G|}dPLV>$x!@42@XOzuY&MUP24fqh8Y{73@LkLfT zi47c>PA8}T%L6G;upk*XMC!TAVd{~1D-EgUs2#Ev`BZLw*%zL22D5>}lK4Md6m2~3 zGI~m$C-dCJEv={*jYWPy|F9qjZ`zoF~$rD{&7<8N|q26gH?I;DH5I7AwC{8 z$ittb#7W%J*LEUDQ)m^N_MWOdHMRy`z4M!_=X&ouai>7iAyNu;JWU@OydlzI`$J$` zr0@BDbi3?iq4dGJOYXCDW$gZ(R|9r}SqB#xzwIW(#ZA*QxNH*4N~}1m*-XlHIfMo$ zQp$LF{aL^L?E;vBfX#R*;ln%peWdc|lLMLyAe7|Ko&-Njx&2Hy=Hh9}-%qArRc7fB ztK8et=Os4X;3erJ9m|p%Oz*^y93QAP7Ga z-v9|j{&H|Yvk>XgF(HG6lIjE(kzn$~Bk-thEFsILkk5XzUgQ=jNO$?({b`J*N5N`9 zjIFk`yoT^C!4RoYbV-Kxi8+*lCx&p<8|4oM3svDr%LuXzy)2R~^x^MSX*`D1QVYfG zPwS7~BH;LxC6DU1onyfHG=`8F^*v9*R!heG?(HdCSYmz<>iNMfGurm`_7ibdkS8j= z^nJ&q17sXTAHKpd27-SGd^}3ez=OWU=Qn8}y8;EFITA1{OM4oxk{>fz=>TcsR%cS8 z1rqg=`~Zp{YZXZ&1o`MGD5Gl=V0yIsZ>FB zqv*rcI1=%U4UsqgpdlZz9>_`W2J-FK^w~Ui+V3U8+pd2ECVPKYWCO1haMv zUv|TuiVW1wD%cBA3b^k8P4(_l^9lH(1jpj0kv1T;-38rN>D5^SJf0VL{YvnKUkoFz z9?%cC0IdL^Fu3Dr7~X*N+LWC#)_wmt{K?tfq@#S}TFXJ8nkHaWF9vaZA$&Gta^s!D zbd$hl;MRk0#1P!hurT&N>IK6FYV87*d=Y?lAJy7_nl`YC6w;X=IOXNVp--{J@+(c+ z^CAjKevM?hfpihh-WIPv#vtMb5CXu!JWs+vrc{YWsq!34jT9yDr8ZkeM6`zRpga0$S%VXcz6&*S~ZgV+8F!pNmpw-b_2 z-#93HIT$`4Ai%pZqgzm-e80K2 zRdkC>r%>3ucjp(azx(mxOyFQyWV7u21RKz<%qFMl{#pVo zpV%17e)n5E;@D%lA?Vxd>-o>m%{953`t9#S{(6fy8xF6rQ+y+@7qP)X)}X_%IiQQx zG!3+Sb6d{MBH$#-E13l%wQo7~_>X`_JG!49?G}FzY)LJZ;LhFG30$XOlz50`-|`Qi zAAdb(cT6&U&cjJl54qFr@K{@jL?V*qD+&{igdh;EshJ%kFZAemUC>OIQ4EKOocI1l*u=@WTFr2a|sRr(F$Q zyaL7D7X5wyKIg;!;3uDyYgk_N1DDsy16RWUms0z#JgchR8U*rULmW#?n*6%PA9sz? z4f}trnDR*G%t32bzBMcN76A`s5H$p@wF8}~Va?I;*UEZ__gY|WslZX;3OuJL{74J9 jnr(ao8p|I*xd;Cl`>OBut4~k1U;qM7S3j3^P6 **Note:** Vertices are sometimes also called "nodes" and edges are also called "links". -## Weighted and Directed Edges +For example, a graph can represent a social network. Each person is a vertex, and people who know each other are connected by edges. A somewhat historically inaccurate example: -Edges can optionally be *weighted*, where an arbitrary weight -- a positive or negative numeric value -- is assigned to each edge. Consider an example of a graph representing airplane flights. Cities can be represented as vertices, and flights as edges. Then an edge weight could represent flight time or the cost of the trip. +![Social network](Images/SocialNetwork.png) -In addition, edges can optionally be *directed*. A directed edge from vertex A to vertex B connects *A to B*, but **not** *B to A*. Continuing from the flight path example, a directed edge from San Francisco, CA to Juneau, AK would indicate that there is a flight from San Francisco to Juneau, but not from Juneau to San Francisco. +Graphs come in all kinds of shapes and sizes. The edges can have a *weight*, where a positive or negative numeric value is assigned to each edge. Consider an example of a graph representing airplane flights. Cities can be vertices, and flights can be edges. Then an edge weight could describe flight time or the price of a ticket. -// TODO: Insert image here +![Airplane flights](Images/Flights.png) -## Representing Graphs in Code +With this hypothetical airline, flying from San Francisco to Moscow is cheapest by going through New York. -There are two main strategies for representing graphs: +Edges can also be *directed*. So far the edges you've seen have been undirected, so if Ada knows Charles, then Charles also knows Ada. A directed edge, on the other hand, implies a one-way relationship. A directed edge from vertex X to vertex Y connects X to Y, but *not* Y to X. -**Adjacency List.** In an adjacency list implementation, each vertex stores a list of edges that originate from the vertex. For example, if vertex A has an edge to vertices B, C, and D, then vertex A would have a list of 3 edges. +Continuing from the flights example, a directed edge from San Francisco to Juneau in Alaska would indicate that there is a flight from San Francisco to Juneau, but not from Juneau to San Francisco (I suppose that means you're walking back!). -**Adjacency Matrix.** In an adjacency matrix implementation, a matrix with rows and columns representing vertices stores a weight to indicate if vertices are connected, and by what weight. For example, if there is a directed edge of weight 5.6 from vertex A to vertex B, then the entry with row for vertex A, column for vertex B would have value 5.6: +![One-way flights](Images/FlightsDirected.png) -``` -matrix[index(A)][index(B)] == 5.6 -``` +The following are also graphs: + +![Tree and linked list](Images/TreeAndList.png) + +On the left is a [tree](../Tree/) structure, on the right a [linked list](../Linked List/). Both can be considered graphs, but in a simpler form. After all, they have vertices (nodes) and edges (links). + +The very first graph I showed you contained *cycles*, where you can start off at a vertex, follow a path, and come back to the original vertex. A tree is a graph without such cycles. + +Another very common type of graph is the *directed acyclic graph* or DAG: + +![DAG](Images/DAG.png) + +Like a tree this does not have any cycles in it (no matter where you start, there is no path back to the starting vertex), but unlike a tree the edges are directional and the shape doesn't necessarily form a hierarchy. + +## Why use graphs? + +Maybe you're shrugging your shoulders and thinking, what's the big deal? Well, it turns out that graphs are an extremely useful data structure. + +If you have some programming problem where you can represent some of your data as vertices and some of it as edges between those vertices, then you can draw your problem as a graph and use well-known graph algorithms such as [breadth-first search](../Breadth-First Search/) or [depth-first search](../Depth-First Search) to find a solution. + +For example, let's say you have a list of tasks where some tasks have to wait on others before they can begin. You can model this using an acyclic directed graph: + +![Tasks as a graph](Images/Tasks.png) + +Each vertex represents a task. Here, an edge between two vertices means that the source task must be completed before the destination task can start. So task C cannot start before B and D are finished, and B nor D can start before A is finished. + +Now that the problem is expressed using a graph, you can use a depth-first search to perform a [topological sort](../Topological Sort/). This will put the tasks in an optimal order so that you minimize the time spent waiting for tasks to complete. (One possible order here is A, B, D, E, C, F, G, H, I, J, K.) + +Whenever you're faced with a tough programming problem, ask yourself, "how can I express this problem using a graph?" Graphs are all about representing relationships between your data. The trick is in how you define "relationship". + +If you're a musician you might appreciate this graph: + +![Chord map](Images/ChordMap.png) + +The vertices are chords from the C major scale. The edges -- the relationships between the chords -- represent how [likely one chord is to follow another](http://mugglinworks.com/chordmaps/genmap.htm). This is a directed graph, so the direction of the arrows shows how you can go from one chord to the next. It's also a weighted graph, where the weight of the edges -- portrayed here by line thickness -- shows a strong relationship between two chords. As you can see, a G7-chord is very likely to be followed by a C chord, and much less likely by a Am chord. -### Comparing Graph Representations +You're probably already using graphs without even knowing it. Your data model is also a graph (from Apple's Core Data documentation): + +![Core Data model](https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/CoreDataVersioning/Art/recipe_version2.0.jpg) + +Another common graph that's used by programmers is the state machine, where edges depict the conditions for transitioning between states. Here is a state machine that models my cat: + +![State machine](Images/StateMachine.png) + +Graphs are awesome. Facebook made a fortune from them. If you're going to learn any data structure, it should be the graph, and the vast collection of standard graph algorithms. + +## Vertices and edges, oh my! + +In theory, a graph is just a bunch of vertex objects and a bunch of edge objects. But how do you describe these in code? + +There are two main strategies: + +**Adjacency List.** In an adjacency list implementation, each vertex stores a list of edges that originate from the vertex. For example, if vertex A has an edge to vertices B, C, and D, then vertex A would have a list containing 3 edges. + +![Adjacency list](Images/AdjacencyList.png) + +The adjacency list describes outgoing edges. A has an edge to B but B does not have an edge back to A, so A does not appear in B's adjacency list. + +**Adjacency Matrix.** In an adjacency matrix implementation, a matrix with rows and columns representing vertices stores a weight to indicate if vertices are connected, and by what weight. For example, if there is a directed edge of weight 5.6 from vertex A to vertex B, then the entry with row for vertex A, column for vertex B would have value 5.6: + +![Adjacency matrix](Images/AdjacencyMatrix.png) + +So which one should you use? Most of the time, the adjacency list is the right approach. What follows is a more detailed comparison between the two. Let *V* be the number of vertices in the graph, and *E* the number of edges. Then we have: @@ -41,98 +97,132 @@ Let *V* be the number of vertices in the graph, and *E* the number of edges. Th | Add Edge | O(1) | O(1) | | Check Adjacency | O(V) | O(1) | -Note that the time to check adjacency for an adjacency list is **O(V)**, because at worst a vertex is connected to *every* other vertex. +"Checking adjacency" means that we try to determine that a given vertex is an immediate neighbor of another vertex. The time to check adjacency for an adjacency list is **O(V)**, because at worst a vertex is connected to *every* other vertex. -In the case of a *sparse* graph, where each vertex is connected to only a handful of other vertices, an Adjacency List is preferred. If the graph is *dense*, where each vertex is connected to most of the other vertices, then an Adjacency Matrix is preferred. +In the case of a *sparse* graph, where each vertex is connected to only a handful of other vertices, an adjacency list is the best way to store the edges. If the graph is *dense*, where each vertex is connected to most of the other vertices, then a matrix is preferred. -## The Code +We'll show you sample implementations of both adjacency list and adjacency matrix. -Below we have implementations of both Adjacency List and Adjacency Matrix graph representations. In both cases, we also let the vertex store arbitrary data with a generic parameter. +## The code: adjacency list -### Adjacency List - -First, we have the data structures for edges and vertices: +The adjacency list for each vertex consists of `Edge` objects: ```swift -var uniqueIDCounter = 0 - -public struct GraphEdge { - public let from: GraphVertex - public let to: GraphVertex +public struct Edge { + public let from: Vertex + public let to: Vertex public let weight: Double } +``` + +This struct describes the "from" and "to" vertices and a weight value. Note that an `Edge` object is always directed, a one-way connection (shown as arrows in the illustrations above). If you want the connection to go both ways, you also need to add an `Edge` object to the adjacency list of the destination vertex. + +The `Vertex` looks like this: + +```swift +private var uniqueIDCounter = 0 -public struct GraphVertex { +public struct Vertex { public var data: T - private var edges: [GraphEdge] = [] + public let uniqueID: Int - private let uniqueID: Int + private(set) public var edges: [Edge] = [] public init(data: T) { self.data = data uniqueID = uniqueIDCounter uniqueIDCounter += 1 } -} ``` -Note that each vertex has a unique identifier, which we use to compare equality later. +It stores arbitrary data with a generic type `T`. The vertex also has a unique identifier, which we use to compare equality later. The `edges` array is the adjacency list. -Now, lets see how to connect vertices: +To connect two vertices using a directed edge: ```swift -// Creates a directed edge self -----> dest -public mutating func connectTo(destinationVertex: GraphVertex, withWeight weight: Double = 1.0) { - edges.append(GraphEdge(from: self, to: destinationVertex, weight: weight)) -} + public mutating func connectTo(destinationVertex: Vertex, withWeight weight: Double = 0) { + edges.append(Edge(from: self, to: destinationVertex, weight: weight)) + } +``` + +As mentioned, to create an undirected edge you need to make two directed edges: + +``` + public mutating func connectBetween(inout otherVertex: Vertex, withWeight weight: Double = 0) { + connectTo(otherVertex, withWeight: weight) + otherVertex.connectTo(self, withWeight: weight) + } ``` -And then we can check for an edge between vertices: + +There is also a method for checking adjacency, i.e. to determine if there is an edge between two vertices: ```swift -// Queries for an edge from self -----> otherVertex -public func edgeTo(otherVertex: GraphVertex) -> GraphEdge? { - for e in edges { - if e.to.uniqueID == otherVertex.uniqueID { + public func edgeTo(otherVertex: Vertex) -> Edge? { + for e in edges where e.to.uniqueID == otherVertex.uniqueID { return e } - } - return nil + return nil + } +``` + +Here's an example of a very simple graph: + +![Demo](Images/Demo1.png) + +This is how you'd create it using `Vertex` objects: + +```swift +var v1 = Vertex(data: 1) +var v2 = Vertex(data: 2) +var v3 = Vertex(data: 3) +var v4 = Vertex(data: 4) +var v5 = Vertex(data: 5) + +v1.connectTo(v2, withWeight: 1.0) +v2.connectTo(v3, withWeight: 1.0) +v3.connectTo(v4, withWeight: 4.5) +v4.connectTo(v1, withWeight: 2.8) +v2.connectTo(v5, withWeight: 3.2) +``` + +> **Note:** There are many, many ways to implement graphs. The code given here is just one possible implementation. You probably want to tailor the graph code for each individual problem you're trying to solve. For instance, your edges may not need a `weight` property, or you may not have the need to distinguish between directed and undirected edges. + +## The code: adjacency matrix + +We'll keep track of the adjacency matrix in a two-dimensional `[[Double?]]` array. An entry of `nil` indicates no edge, while any other value indicates an edge of the given weight. + +```swift +public struct Graph { + private var adjacencyMatrix: [[Double?]] = [] } ``` -### Adjacency Matrix +If `adjacencyMatrix[i][j]` is not nil, then there is an edge from vertex `i` to vertex `j`. -Fundamentally, we will store a `[[Double?]]` array, which is the adjacency matrix. An entry of `nil` indicates no edge, while any other value indicates an edge of the given weight. To index into the matrix using vertices, we give each `GraphVertex` a unique integer index: +To index into the matrix using vertices, we give each `Vertex` a unique integer index: ```swift -public struct GraphVertex { +public struct Vertex { public var data: T private let index: Int } ``` -Then the `Graph` struct keeps track of the matrix. To create a new vertex, the graph must resize the matrix: +To create a new vertex, the graph must resize the matrix: ```swift -public struct Graph { - - // nil entries are used to mark that two vertices are NOT connected. - // If adjacencyMatrix[i][j] is not nil, then there is an edge from vertex i to vertex j. - private var adjacencyMatrix: [[Double?]] = [] - - // O(n^2) because of the resizing of the matrix - public mutating func createVertex(data: T) -> GraphVertex { - let vertex = GraphVertex(data: data, index: adjacencyMatrix.count) + public mutating func createVertex(data: T) -> Vertex { + let vertex = Vertex(data: data, index: adjacencyMatrix.count) - // Expand each existing row to the right one column + // Expand each existing row to the right one column. for i in 0.. { Once we have the matrix properly configured, adding edges and querying for edges are simple indexing operations into the matrix: ```swift -// Creates a directed edge source -----> dest. Represented by M[source][dest] = weight -public mutating func connect(sourceVertex: GraphVertex, toDestinationVertex: GraphVertex, withWeight weight: Double = 0) { - adjacencyMatrix[sourceVertex.index][toDestinationVertex.index] = weight +public mutating func connect(sourceVertex: Vertex, to destinationVertex: Vertex, withWeight weight: Double = 0) { + adjacencyMatrix[sourceVertex.index][destinationVertex.index] = weight } public func weightFrom(sourceVertex: GraphVertex, toDestinationVertex: GraphVertex) -> Double? { return adjacencyMatrix[sourceVertex.index][toDestinationVertex.index] } ``` -*Written by Donald Pinckney* + +You use these objects as follows: + +```swift +var graph = Graph() +let v1 = graph.createVertex(1) +let v2 = graph.createVertex(2) +let v3 = graph.createVertex(3) +let v4 = graph.createVertex(4) +let v5 = graph.createVertex(5) + +graph.connect(v1, to: v2, withWeight: 1.0) +graph.connect(v2, to: v3, withWeight: 1.0) +graph.connect(v3, to: v4, withWeight: 4.5) +graph.connect(v4, to: v1, withWeight: 2.8) +graph.connect(v2, to: v5, withWeight: 3.2) +``` + +Then the adjacency matrix looks like this: + + [[nil, 1.0, nil, nil, nil] v1 + [nil, nil, 1.0, nil, 3.2] v2 + [nil, nil, nil, 4.5, nil] v3 + [2.8, nil, nil, nil, nil] v4 + [nil, nil, nil, nil, nil]] v5 + + v1 v2 v3 v4 v5 + + +## See also + +This article described what a graph is and how you can implement the basic data structure. But we have many more articles on practical uses for graphs, so check those out too! + +*Written by Donald Pinckney and Matthijs Hollemans* diff --git a/README.markdown b/README.markdown index ff2902bc7..ac2dbf9a9 100644 --- a/README.markdown +++ b/README.markdown @@ -166,7 +166,7 @@ Most of the time using just the built-in `Array`, `Dictionary`, and `Set` types ### Graphs -- [Graph](Graph/) :construction: +- [Graph](Graph/) - [Breadth-First Search (BFS)](Breadth-First Search/) - [Depth-First Search (DFS)](Depth-First Search/) :construction: - Shortest Path From 05b9ef2725f27298fe3a07ab4ebe30a571fce57a Mon Sep 17 00:00:00 2001 From: Kauserali Hafizji Date: Sat, 5 Mar 2016 02:18:25 +0530 Subject: [PATCH 0119/1679] Adding DFS --- .../Contents.swift | 25 ++++++++- .../Sources/Graph.swift | 56 +++++++++++++++++++ .../Sources/Stack.swift | 39 +++++++++++++ .../timeline.xctimeline | 6 ++ 4 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 Topological Sort/Topological Sort.playground/Sources/Graph.swift create mode 100644 Topological Sort/Topological Sort.playground/Sources/Stack.swift create mode 100644 Topological Sort/Topological Sort.playground/timeline.xctimeline diff --git a/Topological Sort/Topological Sort.playground/Contents.swift b/Topological Sort/Topological Sort.playground/Contents.swift index c9a67424b..4b9680f38 100644 --- a/Topological Sort/Topological Sort.playground/Contents.swift +++ b/Topological Sort/Topological Sort.playground/Contents.swift @@ -2,4 +2,27 @@ import UIKit -var str = "Hello, playground" +let graph = Graph() + +let node5 = graph.addNode("5") +let node7 = graph.addNode("7") +let node3 = graph.addNode("3") +let node11 = graph.addNode("11") +let node8 = graph.addNode("8") +let node2 = graph.addNode("2") +let node9 = graph.addNode("9") +let node10 = graph.addNode("10") + +graph.addEdge(fromNode: node5, toNode: node11) +graph.addEdge(fromNode: node7, toNode: node11) +graph.addEdge(fromNode: node7, toNode: node8) +graph.addEdge(fromNode: node3, toNode: node8) +graph.addEdge(fromNode: node3, toNode: node10) +graph.addEdge(fromNode: node11, toNode: node2) +graph.addEdge(fromNode: node11, toNode: node9) +graph.addEdge(fromNode: node11, toNode: node10) +graph.addEdge(fromNode: node8, toNode: node9) + +print(graph.description, terminator: "") + +graph.depthFirstSearch("5") \ No newline at end of file diff --git a/Topological Sort/Topological Sort.playground/Sources/Graph.swift b/Topological Sort/Topological Sort.playground/Sources/Graph.swift new file mode 100644 index 000000000..748591d28 --- /dev/null +++ b/Topological Sort/Topological Sort.playground/Sources/Graph.swift @@ -0,0 +1,56 @@ + +public class Graph: CustomStringConvertible { + + private var adjacencyLists: [String : [String]] + + public init() { + adjacencyLists = [String : [String]]() + } + + public func addNode(value: String) -> String { + adjacencyLists[value] = [] + return value + } + + public func addEdge(fromNode from: String, toNode to: String) -> Bool { + adjacencyLists[from]?.append(to) + return adjacencyLists[from] != nil ? true : false + } + + public var description: String { + return adjacencyLists.description + } + + private func adjacencyList(forValue: String) -> [String]? { + for (key, adjacencyList) in adjacencyLists { + if key == forValue { + return adjacencyList + } + } + return nil + } +} + +extension Graph { + + public func depthFirstSearch(source: String) -> [String] { + var result = [String]() + var stack = Stack() + + result.append(source) + stack.push(source) + + while !stack.isEmpty { + if let element = stack.pop(), temp = adjacencyList(element) { + for node in temp { + stack.push(node) + result.append(node) + } + } + } + + return result + } +} + + diff --git a/Topological Sort/Topological Sort.playground/Sources/Stack.swift b/Topological Sort/Topological Sort.playground/Sources/Stack.swift new file mode 100644 index 000000000..7099e5f55 --- /dev/null +++ b/Topological Sort/Topological Sort.playground/Sources/Stack.swift @@ -0,0 +1,39 @@ +import Foundation + +public struct Stack { + private var array = [T]() + + public var isEmpty: Bool { + return array.isEmpty + } + + public var count: Int { + return array.count + } + + public mutating func push(element: T) { + array.append(element) + } + + public mutating func pop() -> T? { + if isEmpty { + return nil + } else { + return array.removeLast() + } + } + + public func peek() -> T? { + return array.last + } +} + +extension Stack: SequenceType { + public func generate() -> AnyGenerator { + var curr = self + return anyGenerator { + _ -> T? in + return curr.pop() + } + } +} \ No newline at end of file diff --git a/Topological Sort/Topological Sort.playground/timeline.xctimeline b/Topological Sort/Topological Sort.playground/timeline.xctimeline new file mode 100644 index 000000000..bf468afec --- /dev/null +++ b/Topological Sort/Topological Sort.playground/timeline.xctimeline @@ -0,0 +1,6 @@ + + + + + From 8ec5ab149791003b76de95670c05d5c8db9b7f3a Mon Sep 17 00:00:00 2001 From: TheCmar7 Date: Fri, 4 Mar 2016 13:04:16 -0800 Subject: [PATCH 0120/1679] I added a playground for the 2D array --- Array2D/Array2D.playground/Contents.swift | 73 +++++++++++++++++++ .../Array2D.playground/contents.xcplayground | 4 + .../Array2D.playground/timeline.xctimeline | 6 ++ 3 files changed, 83 insertions(+) create mode 100644 Array2D/Array2D.playground/Contents.swift create mode 100644 Array2D/Array2D.playground/contents.xcplayground create mode 100644 Array2D/Array2D.playground/timeline.xctimeline diff --git a/Array2D/Array2D.playground/Contents.swift b/Array2D/Array2D.playground/Contents.swift new file mode 100644 index 000000000..995804ab0 --- /dev/null +++ b/Array2D/Array2D.playground/Contents.swift @@ -0,0 +1,73 @@ +/* +Two-dimensional array with a fixed number of rows and columns. +This is mostly handy for games that are played on a grid, such as chess. +Performance is always O(1). +*/ +public struct Array2D { + public let columns: Int + public let rows: Int + private var array: [T] + + public init(columns: Int, rows: Int, initialValue: T) { + self.columns = columns + self.rows = rows + array = .init(count: rows*columns, repeatedValue: initialValue) + } + + public subscript(column: Int, row: Int) -> T { + get { + return array[row*columns + column] + } + set { + array[row*columns + column] = newValue + } + } + +} + +// initialization +var Array2DNumbers = Array2D(columns: 3, rows: 5, initialValue: 0) + +// makes an array of rows * columns elements all filled with zero +print(Array2DNumbers.array) + +//setting numbers +Array2DNumbers[0, 0] = 1 +Array2DNumbers[1, 0] = 2 + +Array2DNumbers[0, 1] = 3 +Array2DNumbers[1, 1] = 4 + +Array2DNumbers[0, 2] = 5 +Array2DNumbers[1, 2] = 6 + +Array2DNumbers[0, 3] = 7 +Array2DNumbers[1, 3] = 8 +Array2DNumbers[2, 3] = 9 + +// now the numbers are set in the array +print(Array2DNumbers.array) + +// printint out the 2D array with a reference around the grid [x, y] +print(" ", terminator: "") +for k in 0.. + + + \ No newline at end of file diff --git a/Array2D/Array2D.playground/timeline.xctimeline b/Array2D/Array2D.playground/timeline.xctimeline new file mode 100644 index 000000000..bf468afec --- /dev/null +++ b/Array2D/Array2D.playground/timeline.xctimeline @@ -0,0 +1,6 @@ + + + + + From b65ac551776deb704cadb051c0d9d0dae45d0fa8 Mon Sep 17 00:00:00 2001 From: TheCmar7 Date: Fri, 4 Mar 2016 13:07:37 -0800 Subject: [PATCH 0121/1679] I took off the grid around the printing out of the 2dArray I thought it might confuse people more than it helps --- Array2D/Array2D.playground/Contents.swift | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/Array2D/Array2D.playground/Contents.swift b/Array2D/Array2D.playground/Contents.swift index 995804ab0..3f72db3bd 100644 --- a/Array2D/Array2D.playground/Contents.swift +++ b/Array2D/Array2D.playground/Contents.swift @@ -31,7 +31,7 @@ var Array2DNumbers = Array2D(columns: 3, rows: 5, initialValue: 0) // makes an array of rows * columns elements all filled with zero print(Array2DNumbers.array) -//setting numbers +// setting numbers using subscript [x, y] Array2DNumbers[0, 0] = 1 Array2DNumbers[1, 0] = 2 @@ -48,17 +48,9 @@ Array2DNumbers[2, 3] = 9 // now the numbers are set in the array print(Array2DNumbers.array) -// printint out the 2D array with a reference around the grid [x, y] -print(" ", terminator: "") -for k in 0.. Date: Sat, 5 Mar 2016 10:10:56 +0100 Subject: [PATCH 0122/1679] Rename variable to matrix --- Array2D/Array2D.playground/Contents.swift | 85 +++++++++++------------ 1 file changed, 42 insertions(+), 43 deletions(-) diff --git a/Array2D/Array2D.playground/Contents.swift b/Array2D/Array2D.playground/Contents.swift index 3f72db3bd..f73ba8b13 100644 --- a/Array2D/Array2D.playground/Contents.swift +++ b/Array2D/Array2D.playground/Contents.swift @@ -1,65 +1,64 @@ /* -Two-dimensional array with a fixed number of rows and columns. -This is mostly handy for games that are played on a grid, such as chess. -Performance is always O(1). + Two-dimensional array with a fixed number of rows and columns. + This is mostly handy for games that are played on a grid, such as chess. + Performance is always O(1). */ public struct Array2D { - public let columns: Int - public let rows: Int - private var array: [T] - - public init(columns: Int, rows: Int, initialValue: T) { - self.columns = columns - self.rows = rows - array = .init(count: rows*columns, repeatedValue: initialValue) + public let columns: Int + public let rows: Int + private var array: [T] + + public init(columns: Int, rows: Int, initialValue: T) { + self.columns = columns + self.rows = rows + array = .init(count: rows*columns, repeatedValue: initialValue) + } + + public subscript(column: Int, row: Int) -> T { + get { + return array[row*columns + column] } - - public subscript(column: Int, row: Int) -> T { - get { - return array[row*columns + column] - } - set { - array[row*columns + column] = newValue - } + set { + array[row*columns + column] = newValue } - + } } + + // initialization -var Array2DNumbers = Array2D(columns: 3, rows: 5, initialValue: 0) +var matrix = Array2D(columns: 3, rows: 5, initialValue: 0) // makes an array of rows * columns elements all filled with zero -print(Array2DNumbers.array) +print(matrix.array) // setting numbers using subscript [x, y] -Array2DNumbers[0, 0] = 1 -Array2DNumbers[1, 0] = 2 +matrix[0, 0] = 1 +matrix[1, 0] = 2 -Array2DNumbers[0, 1] = 3 -Array2DNumbers[1, 1] = 4 +matrix[0, 1] = 3 +matrix[1, 1] = 4 -Array2DNumbers[0, 2] = 5 -Array2DNumbers[1, 2] = 6 +matrix[0, 2] = 5 +matrix[1, 2] = 6 -Array2DNumbers[0, 3] = 7 -Array2DNumbers[1, 3] = 8 -Array2DNumbers[2, 3] = 9 +matrix[0, 3] = 7 +matrix[1, 3] = 8 +matrix[2, 3] = 9 // now the numbers are set in the array -print(Array2DNumbers.array) +print(matrix.array) // print out the 2D array with a reference around the grid -for i in 0.. Date: Mon, 7 Mar 2016 14:32:50 +0530 Subject: [PATCH 0123/1679] Adding tests and completed topological sort --- .../Contents.swift | 3 +- .../Sources/Graph.swift | 83 ++++-- .../TopologicalSort.xcodeproj/project.pbxproj | 260 ++++++++++++++++++ .../TopologicalSort/Graph.swift | 93 +++++++ .../TopologicalSort/Info.plist | 24 ++ .../TopologicalSort/Stack.swift | 39 +++ .../TopologicalSort/TopologicalSort.swift | 42 +++ 7 files changed, 518 insertions(+), 26 deletions(-) create mode 100644 Topological Sort/TopologicalSort/TopologicalSort.xcodeproj/project.pbxproj create mode 100644 Topological Sort/TopologicalSort/TopologicalSort/Graph.swift create mode 100644 Topological Sort/TopologicalSort/TopologicalSort/Info.plist create mode 100644 Topological Sort/TopologicalSort/TopologicalSort/Stack.swift create mode 100644 Topological Sort/TopologicalSort/TopologicalSort/TopologicalSort.swift diff --git a/Topological Sort/Topological Sort.playground/Contents.swift b/Topological Sort/Topological Sort.playground/Contents.swift index 4b9680f38..2d6af7e4f 100644 --- a/Topological Sort/Topological Sort.playground/Contents.swift +++ b/Topological Sort/Topological Sort.playground/Contents.swift @@ -23,6 +23,5 @@ graph.addEdge(fromNode: node11, toNode: node9) graph.addEdge(fromNode: node11, toNode: node10) graph.addEdge(fromNode: node8, toNode: node9) -print(graph.description, terminator: "") -graph.depthFirstSearch("5") \ No newline at end of file +graph.topologicalSort() diff --git a/Topological Sort/Topological Sort.playground/Sources/Graph.swift b/Topological Sort/Topological Sort.playground/Sources/Graph.swift index 748591d28..5cf228d65 100644 --- a/Topological Sort/Topological Sort.playground/Sources/Graph.swift +++ b/Topological Sort/Topological Sort.playground/Sources/Graph.swift @@ -1,18 +1,19 @@ - public class Graph: CustomStringConvertible { - private var adjacencyLists: [String : [String]] - + public typealias Node = String + + private var adjacencyLists: [Node : [Node]] + public init() { - adjacencyLists = [String : [String]]() + adjacencyLists = [Node : [Node]]() } - public func addNode(value: String) -> String { + public func addNode(value: Node) -> Node { adjacencyLists[value] = [] return value } - public func addEdge(fromNode from: String, toNode to: String) -> Bool { + public func addEdge(fromNode from: Node, toNode to: Node) -> Bool { adjacencyLists[from]?.append(to) return adjacencyLists[from] != nil ? true : false } @@ -21,9 +22,9 @@ public class Graph: CustomStringConvertible { return adjacencyLists.description } - private func adjacencyList(forValue: String) -> [String]? { + private func adjacencyList(forNode node: Node) -> [Node]? { for (key, adjacencyList) in adjacencyLists { - if key == forValue { + if key == node { return adjacencyList } } @@ -32,25 +33,59 @@ public class Graph: CustomStringConvertible { } extension Graph { - - public func depthFirstSearch(source: String) -> [String] { - var result = [String]() - var stack = Stack() - - result.append(source) - stack.push(source) - - while !stack.isEmpty { - if let element = stack.pop(), temp = adjacencyList(element) { - for node in temp { - stack.push(node) - result.append(node) + + typealias InDegree = Int + private func calculateInDegreeOfNodes() -> [Node : InDegree] { + + var inDegrees = [Node : InDegree]() + + for (node, _) in adjacencyLists { + inDegrees[node] = 0 + } + + for (_, adjacencyList) in adjacencyLists { + for nodeInList in adjacencyList { + inDegrees[nodeInList] = (inDegrees[nodeInList] ?? 0) + 1 + } + } + return inDegrees + } + + private func depthFirstSearch(source: Node, inout visited: [Node : Bool]) -> [Node] { + var result = [source] + visited[source] = true + + if let adjacencyList = adjacencyList(forNode: source) { + for nodeInAdjacencyList in adjacencyList { + if !(visited[nodeInAdjacencyList] ?? false) { + result += (depthFirstSearch(nodeInAdjacencyList, visited: &visited)) } } } return result } -} - - + + public func topologicalSort() -> [Node] { + + let startNodes = calculateInDegreeOfNodes().filter({(_, indegree) in + return indegree == 0 + }).map({(node, indegree) in + return node + }) + + var visited = [Node : Bool]() + + for (node, _) in adjacencyLists { + visited[node] = false + } + + var result = [Node]() + + for startNode in startNodes { + result += depthFirstSearch(startNode, visited: &visited) + } + + return result + } +} \ No newline at end of file diff --git a/Topological Sort/TopologicalSort/TopologicalSort.xcodeproj/project.pbxproj b/Topological Sort/TopologicalSort/TopologicalSort.xcodeproj/project.pbxproj new file mode 100644 index 000000000..2d0ec1b6b --- /dev/null +++ b/Topological Sort/TopologicalSort/TopologicalSort.xcodeproj/project.pbxproj @@ -0,0 +1,260 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 61FB15B41C8D70B7000CEA54 /* TopologicalSort.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61FB15B31C8D70B7000CEA54 /* TopologicalSort.swift */; }; + 61FB15BB1C8D70D7000CEA54 /* Graph.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61FB15B91C8D70D7000CEA54 /* Graph.swift */; }; + 61FB15BC1C8D70D7000CEA54 /* Stack.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61FB15BA1C8D70D7000CEA54 /* Stack.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 61FB15B01C8D70B7000CEA54 /* TopologicalSort.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TopologicalSort.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 61FB15B31C8D70B7000CEA54 /* TopologicalSort.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TopologicalSort.swift; sourceTree = ""; }; + 61FB15B51C8D70B7000CEA54 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 61FB15B91C8D70D7000CEA54 /* Graph.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Graph.swift; sourceTree = ""; }; + 61FB15BA1C8D70D7000CEA54 /* Stack.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Stack.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 61FB15AD1C8D70B7000CEA54 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 61FB15A51C8D709E000CEA54 = { + isa = PBXGroup; + children = ( + 61FB15B21C8D70B7000CEA54 /* TopologicalSort */, + 61FB15B11C8D70B7000CEA54 /* Products */, + ); + sourceTree = ""; + }; + 61FB15B11C8D70B7000CEA54 /* Products */ = { + isa = PBXGroup; + children = ( + 61FB15B01C8D70B7000CEA54 /* TopologicalSort.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 61FB15B21C8D70B7000CEA54 /* TopologicalSort */ = { + isa = PBXGroup; + children = ( + 61FB15B91C8D70D7000CEA54 /* Graph.swift */, + 61FB15BA1C8D70D7000CEA54 /* Stack.swift */, + 61FB15B31C8D70B7000CEA54 /* TopologicalSort.swift */, + 61FB15B51C8D70B7000CEA54 /* Info.plist */, + ); + path = TopologicalSort; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 61FB15AF1C8D70B7000CEA54 /* TopologicalSort */ = { + isa = PBXNativeTarget; + buildConfigurationList = 61FB15B61C8D70B7000CEA54 /* Build configuration list for PBXNativeTarget "TopologicalSort" */; + buildPhases = ( + 61FB15AC1C8D70B7000CEA54 /* Sources */, + 61FB15AD1C8D70B7000CEA54 /* Frameworks */, + 61FB15AE1C8D70B7000CEA54 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = TopologicalSort; + productName = TopologicalSort; + productReference = 61FB15B01C8D70B7000CEA54 /* TopologicalSort.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 61FB15A61C8D709E000CEA54 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0720; + LastUpgradeCheck = 0720; + TargetAttributes = { + 61FB15AF1C8D70B7000CEA54 = { + CreatedOnToolsVersion = 7.2.1; + }; + }; + }; + buildConfigurationList = 61FB15A91C8D709E000CEA54 /* Build configuration list for PBXProject "TopologicalSort" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 61FB15A51C8D709E000CEA54; + productRefGroup = 61FB15B11C8D70B7000CEA54 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 61FB15AF1C8D70B7000CEA54 /* TopologicalSort */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 61FB15AE1C8D70B7000CEA54 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 61FB15AC1C8D70B7000CEA54 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 61FB15BB1C8D70D7000CEA54 /* Graph.swift in Sources */, + 61FB15BC1C8D70D7000CEA54 /* Stack.swift in Sources */, + 61FB15B41C8D70B7000CEA54 /* TopologicalSort.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 61FB15AA1C8D709E000CEA54 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + }; + name = Debug; + }; + 61FB15AB1C8D709E000CEA54 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + }; + name = Release; + }; + 61FB15B71C8D70B7000CEA54 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + INFOPLIST_FILE = TopologicalSort/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 9.2; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_BUNDLE_IDENTIFIER = com.alihafizji.TopologicalSort; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 61FB15B81C8D70B7000CEA54 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + INFOPLIST_FILE = TopologicalSort/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 9.2; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_BUNDLE_IDENTIFIER = com.alihafizji.TopologicalSort; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 61FB15A91C8D709E000CEA54 /* Build configuration list for PBXProject "TopologicalSort" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 61FB15AA1C8D709E000CEA54 /* Debug */, + 61FB15AB1C8D709E000CEA54 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 61FB15B61C8D70B7000CEA54 /* Build configuration list for PBXNativeTarget "TopologicalSort" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 61FB15B71C8D70B7000CEA54 /* Debug */, + 61FB15B81C8D70B7000CEA54 /* Release */, + ); + defaultConfigurationIsVisible = 0; + }; +/* End XCConfigurationList section */ + }; + rootObject = 61FB15A61C8D709E000CEA54 /* Project object */; +} diff --git a/Topological Sort/TopologicalSort/TopologicalSort/Graph.swift b/Topological Sort/TopologicalSort/TopologicalSort/Graph.swift new file mode 100644 index 000000000..f30f30241 --- /dev/null +++ b/Topological Sort/TopologicalSort/TopologicalSort/Graph.swift @@ -0,0 +1,93 @@ + +public class Graph: CustomStringConvertible { + + public typealias Node = String + + private var adjacencyLists: [Node : [Node]] + + public init() { + adjacencyLists = [Node : [Node]]() + } + + public func addNode(value: Node) -> Node { + adjacencyLists[value] = [] + return value + } + + public func addEdge(fromNode from: Node, toNode to: Node) -> Bool { + adjacencyLists[from]?.append(to) + return adjacencyLists[from] != nil ? true : false + } + + public var description: String { + return adjacencyLists.description + } + + private func adjacencyList(forNode node: Node) -> [Node]? { + for (key, adjacencyList) in adjacencyLists { + if key == node { + return adjacencyList + } + } + return nil + } +} + +extension Graph { + + typealias InDegree = Int + private func calculateInDegreeOfNodes() -> [Node : InDegree] { + + var inDegrees = [Node : InDegree]() + + for (node, _) in adjacencyLists { + inDegrees[node] = 0 + } + + for (_, adjacencyList) in adjacencyLists { + for nodeInList in adjacencyList { + inDegrees[nodeInList] = (inDegrees[nodeInList] ?? 0) + 1 + } + } + return inDegrees + } + + private func depthFirstSearch(source: Node, inout visited: [Node : Bool]) -> [Node] { + var result = [source] + visited[source] = true + + if let adjacencyList = adjacencyList(forNode: source) { + for nodeInAdjacencyList in adjacencyList { + if !(visited[nodeInAdjacencyList] ?? false) { + result += (depthFirstSearch(nodeInAdjacencyList, visited: &visited)) + } + } + } + + return result + } + + public func topologicalSort() -> [Node] { + + let startNodes = calculateInDegreeOfNodes().filter({(_, indegree) in + return indegree == 0 + }).map({(node, indegree) in + return node + }) + + var visited = [Node : Bool]() + + for (node, _) in adjacencyLists { + visited[node] = false + } + + var result = [Node]() + + for startNode in startNodes { + result += depthFirstSearch(startNode, visited: &visited) + } + + return result + } +} + diff --git a/Topological Sort/TopologicalSort/TopologicalSort/Info.plist b/Topological Sort/TopologicalSort/TopologicalSort/Info.plist new file mode 100644 index 000000000..ba72822e8 --- /dev/null +++ b/Topological Sort/TopologicalSort/TopologicalSort/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/Topological Sort/TopologicalSort/TopologicalSort/Stack.swift b/Topological Sort/TopologicalSort/TopologicalSort/Stack.swift new file mode 100644 index 000000000..7099e5f55 --- /dev/null +++ b/Topological Sort/TopologicalSort/TopologicalSort/Stack.swift @@ -0,0 +1,39 @@ +import Foundation + +public struct Stack { + private var array = [T]() + + public var isEmpty: Bool { + return array.isEmpty + } + + public var count: Int { + return array.count + } + + public mutating func push(element: T) { + array.append(element) + } + + public mutating func pop() -> T? { + if isEmpty { + return nil + } else { + return array.removeLast() + } + } + + public func peek() -> T? { + return array.last + } +} + +extension Stack: SequenceType { + public func generate() -> AnyGenerator { + var curr = self + return anyGenerator { + _ -> T? in + return curr.pop() + } + } +} \ No newline at end of file diff --git a/Topological Sort/TopologicalSort/TopologicalSort/TopologicalSort.swift b/Topological Sort/TopologicalSort/TopologicalSort/TopologicalSort.swift new file mode 100644 index 000000000..97436c5d0 --- /dev/null +++ b/Topological Sort/TopologicalSort/TopologicalSort/TopologicalSort.swift @@ -0,0 +1,42 @@ +// +// TopologicalSort.swift +// TopologicalSort +// +// Created by Kauserali on 07/03/16. +// +// + +import XCTest + +class TopologicalSort: XCTestCase { + + var graph: Graph! + + override func setUp() { + super.setUp() + graph = Graph() + + let node5 = graph.addNode("5") + let node7 = graph.addNode("7") + let node3 = graph.addNode("3") + let node11 = graph.addNode("11") + let node8 = graph.addNode("8") + let node2 = graph.addNode("2") + let node9 = graph.addNode("9") + let node10 = graph.addNode("10") + + graph.addEdge(fromNode: node5, toNode: node11) + graph.addEdge(fromNode: node7, toNode: node11) + graph.addEdge(fromNode: node7, toNode: node8) + graph.addEdge(fromNode: node3, toNode: node8) + graph.addEdge(fromNode: node3, toNode: node10) + graph.addEdge(fromNode: node11, toNode: node2) + graph.addEdge(fromNode: node11, toNode: node9) + graph.addEdge(fromNode: node11, toNode: node10) + graph.addEdge(fromNode: node8, toNode: node9) + } + + func testTopologicalSort() { + XCTAssertEqual(graph.topologicalSort(), ["3", "8", "9", "10", "7", "11", "2", "5"]) + } +} From 4a512ea97a12d598a56a7b5badce6c7dfa8e59b7 Mon Sep 17 00:00:00 2001 From: Kauserali Hafizji Date: Mon, 7 Mar 2016 15:49:37 +0530 Subject: [PATCH 0124/1679] Adding readme --- Topological Sort/Images/algorithm_example.png | Bin 0 -> 187544 bytes Topological Sort/Images/graph_example.png | Bin 0 -> 114041 bytes Topological Sort/README.markdown | 50 ++++++++++++++++++ 3 files changed, 50 insertions(+) create mode 100644 Topological Sort/Images/algorithm_example.png create mode 100644 Topological Sort/Images/graph_example.png create mode 100644 Topological Sort/README.markdown diff --git a/Topological Sort/Images/algorithm_example.png b/Topological Sort/Images/algorithm_example.png new file mode 100644 index 0000000000000000000000000000000000000000..b86b2bc391cf42d0d48042dc5d693187fa3dc91d GIT binary patch literal 187544 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

LC}f4Aau+dni%PMJ3m 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 z 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 literal 0 HcmV?d00001 diff --git a/Topological Sort/Images/graph_example.png b/Topological Sort/Images/graph_example.png new file mode 100644 index 0000000000000000000000000000000000000000..22b8271d4effeba1062fb2f22c29259ad0b0a141 GIT binary patch literal 114041 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�jn9rfnW)8Hau_>k!(Oje3< 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 Date: Mon, 7 Mar 2016 15:52:42 +0530 Subject: [PATCH 0125/1679] Update README.markdown --- Topological Sort/README.markdown | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Topological Sort/README.markdown b/Topological Sort/README.markdown index 12fcd5fc1..fb0b2360c 100644 --- a/Topological Sort/README.markdown +++ b/Topological Sort/README.markdown @@ -8,7 +8,7 @@ Let's consider that you want to learn all the algorithms present in the swift-al For e.g. To learn the depth first search algorithm you need to know how a graph is represented. Similarly, to understand how to calculate the length of a binary tree you need to know details of how a tree is traversed. If we were to represent these in the form of a graph it would be as follows: -//add image +![Example](Images/algorithm_example.png) If we consider each algorithm to be a node in the graph you'll see dependancies among them i.e. to learn something you might have to know something else first. This is exactly what topological sort is used for, it will sort things out such that you know what to learn first. @@ -34,17 +34,23 @@ The last step of the sort is to maintain a list of all the nodes that have alrea Consider the following graph: +![Graph Example](Images/graph_example.png) + *Step 1* Nodes with 0 in-degree: **5, 7, 3** *Step 2* Depth first search for each without remembering nodes that have already been visited: +``` Node 3: 3, 8, 9, 10 Node 7: 7, 11, 2, 8, 9 Node 5: 5, 11, 2, 9, 10 +``` *Step 3* Remember nodes already visited in each DFS. +``` Node 3: 3, 8, 9, 10 Node 7: 7, 11, 2 Node 5: 5 +``` The final sorted order is a concatenation of the above three traversals: **3, 8, 9, 10, 7, 11, 2, 5** From 5e228b437577a0a92ee0797ff0091f666ee84a1f Mon Sep 17 00:00:00 2001 From: Kauserali Date: Mon, 7 Mar 2016 15:57:34 +0530 Subject: [PATCH 0126/1679] Update README.markdown --- Topological Sort/README.markdown | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Topological Sort/README.markdown b/Topological Sort/README.markdown index fb0b2360c..4bc7508c8 100644 --- a/Topological Sort/README.markdown +++ b/Topological Sort/README.markdown @@ -20,15 +20,15 @@ The in-degree of a node is the number of incoming edges to that node. All nodes If you think about it in the context of the previous example these nodes represent algorithms that don't need anything else to be learnt, hence the sort starts with them. -### Step 2: Use depth first search for traversal +### Step 2: Depth first search for traversal -Depth first search is an algorithm that is used to traverse a graph. This algorithm traverses all the child nodes recursively and uses backtracking to find other edges. +Depth first search is an algorithm that is used to traverse a graph. This algorithm traverses all the child nodes recursively and uses backtracking. -To know more about this algorithm please take a look at the explanation here. +To know more about this algorithm please take a look at the explanation [here](https://github.com/hollance/swift-algorithm-club/tree/master/Depth-First%20Search). ### Step 3: Remember all visited nodes -The last step of the sort is to maintain a list of all the nodes that have already been visited. +The last step of the sort is to maintain a list of all the nodes that have been visited. This is to avoid visiting the same node twice. ## Example From 99907cfc303dde2f4fbd8602b34be7a042be62db Mon Sep 17 00:00:00 2001 From: Matthijs Hollemans Date: Tue, 8 Mar 2016 20:02:25 +0100 Subject: [PATCH 0127/1679] Additions to topological sort --- README.markdown | 2 +- Topological Sort/Graph.swift | 32 ++ Topological Sort/Images/GraphResult.graffle | Bin 0 -> 2251 bytes Topological Sort/Images/GraphResult.png | Bin 0 -> 8911 bytes .../Images/TopologicalSort.graffle | Bin 0 -> 2833 bytes Topological Sort/Images/TopologicalSort.png | Bin 0 -> 24083 bytes Topological Sort/README.markdown | 44 ++- .../TopologicalSort => }/Stack.swift | 12 - .../TopologicalSort => Tests}/Info.plist | 0 .../Tests/Tests.xcodeproj/project.pbxproj | 273 ++++++++++++++++++ .../xcshareddata/xcschemes/Tests.xcscheme | 56 ++++ .../TopologicalSortTests.swift} | 2 + .../Contents.swift | 5 + .../Sources/Graph.swift | 63 +--- .../Sources/Stack.swift | 12 - .../Sources/TopologicalSort1.swift} | 44 +-- .../Sources/TopologicalSort2.swift | 41 +++ .../TopologicalSort.xcodeproj/project.pbxproj | 260 ----------------- Topological Sort/TopologicalSort1.swift | 55 ++++ Topological Sort/TopologicalSort2.swift | 41 +++ 20 files changed, 542 insertions(+), 400 deletions(-) create mode 100644 Topological Sort/Graph.swift create mode 100644 Topological Sort/Images/GraphResult.graffle create mode 100644 Topological Sort/Images/GraphResult.png create mode 100644 Topological Sort/Images/TopologicalSort.graffle create mode 100644 Topological Sort/Images/TopologicalSort.png rename Topological Sort/{TopologicalSort/TopologicalSort => }/Stack.swift (68%) rename Topological Sort/{TopologicalSort/TopologicalSort => Tests}/Info.plist (100%) create mode 100644 Topological Sort/Tests/Tests.xcodeproj/project.pbxproj create mode 100644 Topological Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme rename Topological Sort/{TopologicalSort/TopologicalSort/TopologicalSort.swift => Tests/TopologicalSortTests.swift} (92%) rename Topological Sort/{TopologicalSort/TopologicalSort/Graph.swift => Topological Sort.playground/Sources/TopologicalSort1.swift} (61%) create mode 100644 Topological Sort/Topological Sort.playground/Sources/TopologicalSort2.swift delete mode 100644 Topological Sort/TopologicalSort/TopologicalSort.xcodeproj/project.pbxproj create mode 100644 Topological Sort/TopologicalSort1.swift create mode 100644 Topological Sort/TopologicalSort2.swift diff --git a/README.markdown b/README.markdown index ac2dbf9a9..1465626f5 100644 --- a/README.markdown +++ b/README.markdown @@ -74,7 +74,7 @@ Special-purpose sorts: - Bucket Sort - Counting Sort - Radix Sort -- Topological Sort +- [Topological Sort](Topological Sort/) Bad sorting algorithms (don't use these!): diff --git a/Topological Sort/Graph.swift b/Topological Sort/Graph.swift new file mode 100644 index 000000000..49f4db96a --- /dev/null +++ b/Topological Sort/Graph.swift @@ -0,0 +1,32 @@ +public class Graph: CustomStringConvertible { + public typealias Node = String + + private(set) public var adjacencyLists: [Node : [Node]] + + public init() { + adjacencyLists = [Node : [Node]]() + } + + public func addNode(value: Node) -> Node { + adjacencyLists[value] = [] + return value + } + + public func addEdge(fromNode from: Node, toNode to: Node) -> Bool { + adjacencyLists[from]?.append(to) + return adjacencyLists[from] != nil ? true : false + } + + public var description: String { + return adjacencyLists.description + } + + public func adjacencyList(forNode node: Node) -> [Node]? { + for (key, adjacencyList) in adjacencyLists { + if key == node { + return adjacencyList + } + } + return nil + } +} diff --git a/Topological Sort/Images/GraphResult.graffle b/Topological Sort/Images/GraphResult.graffle new file mode 100644 index 0000000000000000000000000000000000000000..aed8664e9a74664cfe1a9b60cb27de83b8b4b1b4 GIT binary patch literal 2251 zcmV;+2sHN}iwFP!000030PS3DQ`@YP1g;p8jcLs!_}r7pf)Z^>^(BcU9Ru)hJ;TZ`R=is+j-hzpaak>ywk`96|6 zZ`K3ui&NeZ9yZy8l9A75)8?Vr`{1MD(8FePA34HOk24>yw{FE#n$T=Fja0*WYhgTc zV#Zm={bv^NxO48$aBI=NiJS}BDRo7M(=l;kvD>r16_XOdqAl+H`Wmb$;ATy^hKAl= zQy{R+o12WAQlsmkps3tq9!Yx5sqAhg@{72t=@3U^J$~ikL~`MC)F@1{i=;Kx9JO!x zXr8#0ICgNDc1J`s4#i?G*@0B|H=EFoM@F>Z6)bucO82J75hh}JA0ux=GuK<;&O%fiNJMWTUT{bS&};y$0c-`@ zZ^fUcD!&5pDR?K1Fh8%qk2oKbe*$HPc^;l18srtXNHF!#RnI|Qp?9bds=QO=Ca?CM zc({KxEvO)o9C_IgkXy`|O)%y8yp2Ps7Gih{ zM@)2_){Xl}rDem0Yf8h=GpU$rx0+U4ZJV}btSM?!Gohy1P&ICHxKB(+VH6(h(jlwP zC@E2rP&?TBin-vzoI7C#r;shb3&AGidyBes{zV!)7`fFhq=+L$9cG3)3MSJ^$spS~ zB`L8~_-$KVQ#8x248LZVv=`!?CAY$v24m#1dHQSn*v}YW zTv*CD8hOyML?jMcXC8I zhtwSL$~gjp?~f#)t_u!;RY(;JDFeW^p@|uUK270vYXc$e+&Y?hcUgm~>Jf zJ##EwLMH8|Y1ZlV9jB9Cr_(e1VgsLRA@&-6v3bqu^zgM)?g5F^6A};rx#~8<$0RgK zqq#>U?###D7)`NTnUUqV1tqu*4HfNoiSKy0X!w7DUSa6)C9n1&+nPjt;PW9IAR3VH zpEDgn)ldfxa~P6MI?$toV0JE!H65&64~Bxc__;S2g29jyv317C4=@Kx%v}d~hJU*e zvJUf@FNA*^_}EnqV=(eDrgG=pn_;mPQiCb--2uNeOd$S4sD>NUmK#;o!;KB(M$sIgpQImUAP388FQFTC*6Ybe)Hj-hNnC6vJn zFZ{F`$~BZ@C~G(OSC?f<_&)f=P2Y9NR_67_Y#vCFLVew*?Ovg*u1C={=(8o{vn6gH zX2iw89&;|Ro3EnEASfk$N&<3TtkcSM6W&TVLL(d$s;sm^k=5=*2zEtg^W+h*JL=m0 zzOa6iK4(+1lzcXUgo_td z8Bt82eKew&KSVwd8POYK%yVFlk-pDdGQ2HEzQ1@=)81-&dGTgs2tT5F^MG-@{5c)^ z1XG@ga(N~2LRw&EY2%V`HpM_)1WU-u9IeirgWe|NoK5zTpDOB2-xpq(9(oM%Y+m2) z>oA+c2@gd*>@c5vV-$J9Z$fj(D|X~CSJHGzN1Gk~&E5IveL8~x|F!9T-rZpx{m;!m zcYE98&iL>I81Ve;qvwpe;@CYrfuG0cJEvYpw0F0Seqa6g<@4DA= zKDKV@P=!D~17NkYw=_yRmFPRh^4$cuBqe@?;Xju1q30a`KAS#=`7DEn193>Pq>hT& z#4$$hA@#2A=ageMU$!`3h%Qx`AF_X+@FM+1uMo&gKO&8Zn5%|v$XfSk(iXkvVu?9h zs4S-dh&uRzx+j!;nc-xubjR7B1bCZr;@=ha)AH$K@gi|Xs8}XdQ+aph`yvuyB#W<~ z0L9l&Y+p_h70LE@6k;6Y0N9Ep-}@PQiWj4r{9VO14LQxvJbIN> zJ;d$DGcQ#ckrxmnbdK(8J|k{=5*3FMl$^ZCx}Jy5cd$(F+(bw<@)M`qOY<=vW!NhY zgl@rR_&NglJ`))Z%hH?T*wE~faHLvYTP1n&ro?(Y+08tn ZmT*#mKay?uo|%o6e*t^LGxYvO0060>Tbcj> literal 0 HcmV?d00001 diff --git a/Topological Sort/Images/GraphResult.png b/Topological Sort/Images/GraphResult.png new file mode 100644 index 0000000000000000000000000000000000000000..86355f8af8f96b2ec5a550d1507479fc97c81d55 GIT binary patch literal 8911 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 literal 0 HcmV?d00001 diff --git a/Topological Sort/Images/TopologicalSort.png b/Topological Sort/Images/TopologicalSort.png new file mode 100644 index 0000000000000000000000000000000000000000..dbfdd41762c5561750b138b1e14699365827c643 GIT binary patch literal 24083 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 literal 0 HcmV?d00001 diff --git a/Topological Sort/README.markdown b/Topological Sort/README.markdown index 4bc7508c8..045f910b6 100644 --- a/Topological Sort/README.markdown +++ b/Topological Sort/README.markdown @@ -2,31 +2,39 @@ Topological sort is an algorithm aimed at ordering a directed graph such that for each directed edge *uv* from vertex *u* to vertex *v*, *u* comes before *v*. +In other words, a topological sort places the vertices of a directed acyclic graph on a line so that all directed edges go from left to right. + +The graph in the following example has two possible topological sorts: + +![Example](Images/TopologicalSort.png) + ## Where is this used? -Let's consider that you want to learn all the algorithms present in the swift-algorithm-club, this might seem daunting at first but we can use topological sort to get things organized. +Let's consider that you want to learn all the algorithms present in the Swift Algorithm Club. This might seem daunting at first but we can use topological sort to get things organized. -For e.g. To learn the depth first search algorithm you need to know how a graph is represented. Similarly, to understand how to calculate the length of a binary tree you need to know details of how a tree is traversed. If we were to represent these in the form of a graph it would be as follows: +For example, to learn the [depth-first search](../Depth-First Search/) algorithm you need to know how a [graph](../Graph/) is represented. Similarly, to understand how to calculate the length of a [binary tree](../Binary Tree/) you need to know details of how a [tree is traversed](../Tree/). + +If we were to represent these objectives in the form of a graph it would be as follows: ![Example](Images/algorithm_example.png) -If we consider each algorithm to be a node in the graph you'll see dependancies among them i.e. to learn something you might have to know something else first. This is exactly what topological sort is used for, it will sort things out such that you know what to learn first. +If we consider each algorithm to be a node in the graph you'll see dependancies among them, i.e. to learn something you might have to know something else first. This is exactly what topological sort is used for -- it will sort things out such that you know what to learn first. ## How does it work? -### Step 1: Find all nodes that have in-degree of 0 +**Step 1: Find all nodes that have in-degree of 0** -The in-degree of a node is the number of incoming edges to that node. All nodes that have no incoming edges have an in-degree of 0. These nodes are the starting points for the sort. +The *in-degree* of a node is the number of incoming edges to that node. Nodes that have no incoming edges have an in-degree of 0. These nodes are the starting points for the sort. -If you think about it in the context of the previous example these nodes represent algorithms that don't need anything else to be learnt, hence the sort starts with them. +If you think about it in the context of the previous example, these nodes represent algorithms that don't have any prerequisites; you don't need to learn anything else first, hence the sort starts with them. -### Step 2: Depth first search for traversal +**Step 2: Depth-first search for traversal** -Depth first search is an algorithm that is used to traverse a graph. This algorithm traverses all the child nodes recursively and uses backtracking. +Depth-first search is an algorithm that is used to traverse a graph. This algorithm traverses all the child nodes recursively and uses backtracking. -To know more about this algorithm please take a look at the explanation [here](https://github.com/hollance/swift-algorithm-club/tree/master/Depth-First%20Search). +To find out more about depth-first search, please take a look at the [detailed explanation](../Depth-First%20Search/). -### Step 3: Remember all visited nodes +**Step 3: Remember all visited nodes** The last step of the sort is to maintain a list of all the nodes that have been visited. This is to avoid visiting the same node twice. @@ -36,8 +44,9 @@ Consider the following graph: ![Graph Example](Images/graph_example.png) -*Step 1* Nodes with 0 in-degree: **5, 7, 3** -*Step 2* Depth first search for each without remembering nodes that have already been visited: +**Step 1:** The nodes with 0 in-degree are: **5, 7, 3** + +**Step 2:** Depth-first search for each starting node, without remembering nodes that have already been visited: ``` Node 3: 3, 8, 9, 10 @@ -45,7 +54,7 @@ Node 7: 7, 11, 2, 8, 9 Node 5: 5, 11, 2, 9, 10 ``` -*Step 3* Remember nodes already visited in each DFS. +**Step 3:** Remember nodes already visited in each DFS: ``` Node 3: 3, 8, 9, 10 @@ -54,3 +63,12 @@ Node 5: 5 ``` The final sorted order is a concatenation of the above three traversals: **3, 8, 9, 10, 7, 11, 2, 5** + +The result of the topological sort looks like this: + +![Result of the sort](Images/GraphResult.png) + +TODO: I don't think this is correct! There should be no arrows going from right to left! (A valid topological order would be 3, 7, 5, 10, 8, 11, 9, 2 -- or 3, 7, 5, 8, 11, 2, 9, 10.) + + +*Written for Swift Algorithm Club by Ali Hafizji* diff --git a/Topological Sort/TopologicalSort/TopologicalSort/Stack.swift b/Topological Sort/Stack.swift similarity index 68% rename from Topological Sort/TopologicalSort/TopologicalSort/Stack.swift rename to Topological Sort/Stack.swift index 7099e5f55..7f4aadc8b 100644 --- a/Topological Sort/TopologicalSort/TopologicalSort/Stack.swift +++ b/Topological Sort/Stack.swift @@ -1,5 +1,3 @@ -import Foundation - public struct Stack { private var array = [T]() @@ -27,13 +25,3 @@ public struct Stack { return array.last } } - -extension Stack: SequenceType { - public func generate() -> AnyGenerator { - var curr = self - return anyGenerator { - _ -> T? in - return curr.pop() - } - } -} \ No newline at end of file diff --git a/Topological Sort/TopologicalSort/TopologicalSort/Info.plist b/Topological Sort/Tests/Info.plist similarity index 100% rename from Topological Sort/TopologicalSort/TopologicalSort/Info.plist rename to Topological Sort/Tests/Info.plist diff --git a/Topological Sort/Tests/Tests.xcodeproj/project.pbxproj b/Topological Sort/Tests/Tests.xcodeproj/project.pbxproj new file mode 100644 index 000000000..cb32961df --- /dev/null +++ b/Topological Sort/Tests/Tests.xcodeproj/project.pbxproj @@ -0,0 +1,273 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 7B3471BB1C8F50CF008381CD /* TopologicalSortTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B3471BA1C8F50CF008381CD /* TopologicalSortTests.swift */; }; + 7B3471BF1C8F50DD008381CD /* Graph.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B3471BC1C8F50DD008381CD /* Graph.swift */; }; + 7B3471C01C8F50DD008381CD /* Stack.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B3471BD1C8F50DD008381CD /* Stack.swift */; }; + 7B3471C11C8F50DD008381CD /* TopologicalSort1.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B3471BE1C8F50DD008381CD /* TopologicalSort1.swift */; }; + 7B3471C31C8F5348008381CD /* TopologicalSort2.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B3471C21C8F5348008381CD /* TopologicalSort2.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 7B2BBC801C779D720067B71D /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 7B2BBC941C779E7B0067B71D /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; + 7B3471BA1C8F50CF008381CD /* TopologicalSortTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TopologicalSortTests.swift; sourceTree = SOURCE_ROOT; }; + 7B3471BC1C8F50DD008381CD /* Graph.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Graph.swift; path = ../Graph.swift; sourceTree = SOURCE_ROOT; }; + 7B3471BD1C8F50DD008381CD /* Stack.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Stack.swift; path = ../Stack.swift; sourceTree = SOURCE_ROOT; }; + 7B3471BE1C8F50DD008381CD /* TopologicalSort1.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = TopologicalSort1.swift; path = ../TopologicalSort1.swift; sourceTree = SOURCE_ROOT; }; + 7B3471C21C8F5348008381CD /* TopologicalSort2.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = TopologicalSort2.swift; path = ../TopologicalSort2.swift; sourceTree = SOURCE_ROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 7B2BBC7D1C779D720067B71D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 7B2BBC681C779D710067B71D = { + isa = PBXGroup; + children = ( + 7B2BBC831C779D720067B71D /* Tests */, + 7B2BBC721C779D710067B71D /* Products */, + ); + sourceTree = ""; + }; + 7B2BBC721C779D710067B71D /* Products */ = { + isa = PBXGroup; + children = ( + 7B2BBC801C779D720067B71D /* Tests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 7B2BBC831C779D720067B71D /* Tests */ = { + isa = PBXGroup; + children = ( + 7B3471BC1C8F50DD008381CD /* Graph.swift */, + 7B3471BD1C8F50DD008381CD /* Stack.swift */, + 7B3471BE1C8F50DD008381CD /* TopologicalSort1.swift */, + 7B3471C21C8F5348008381CD /* TopologicalSort2.swift */, + 7B3471BA1C8F50CF008381CD /* TopologicalSortTests.swift */, + 7B2BBC941C779E7B0067B71D /* Info.plist */, + ); + name = Tests; + path = TestsTests; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 7B2BBC7F1C779D720067B71D /* Tests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */; + buildPhases = ( + 7B2BBC7C1C779D720067B71D /* Sources */, + 7B2BBC7D1C779D720067B71D /* Frameworks */, + 7B2BBC7E1C779D720067B71D /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Tests; + productName = TestsTests; + productReference = 7B2BBC801C779D720067B71D /* Tests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 7B2BBC691C779D710067B71D /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0720; + LastUpgradeCheck = 0720; + ORGANIZATIONNAME = "Swift Algorithm Club"; + TargetAttributes = { + 7B2BBC7F1C779D720067B71D = { + CreatedOnToolsVersion = 7.2; + }; + }; + }; + buildConfigurationList = 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 7B2BBC681C779D710067B71D; + productRefGroup = 7B2BBC721C779D710067B71D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 7B2BBC7F1C779D720067B71D /* Tests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 7B2BBC7E1C779D720067B71D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 7B2BBC7C1C779D720067B71D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 7B3471C31C8F5348008381CD /* TopologicalSort2.swift in Sources */, + 7B3471BF1C8F50DD008381CD /* Graph.swift in Sources */, + 7B3471C01C8F50DD008381CD /* Stack.swift in Sources */, + 7B3471BB1C8F50CF008381CD /* TopologicalSortTests.swift in Sources */, + 7B3471C11C8F50DD008381CD /* TopologicalSort1.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 7B2BBC871C779D720067B71D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 7B2BBC881C779D720067B71D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + }; + name = Release; + }; + 7B2BBC8D1C779D720067B71D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 7B2BBC8E1C779D720067B71D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7B2BBC871C779D720067B71D /* Debug */, + 7B2BBC881C779D720067B71D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7B2BBC8D1C779D720067B71D /* Debug */, + 7B2BBC8E1C779D720067B71D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 7B2BBC691C779D710067B71D /* Project object */; +} diff --git a/Topological Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Topological Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme new file mode 100644 index 000000000..74dd9450b --- /dev/null +++ b/Topological Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Topological Sort/TopologicalSort/TopologicalSort/TopologicalSort.swift b/Topological Sort/Tests/TopologicalSortTests.swift similarity index 92% rename from Topological Sort/TopologicalSort/TopologicalSort/TopologicalSort.swift rename to Topological Sort/Tests/TopologicalSortTests.swift index 97436c5d0..41e7a854f 100644 --- a/Topological Sort/TopologicalSort/TopologicalSort/TopologicalSort.swift +++ b/Topological Sort/Tests/TopologicalSortTests.swift @@ -38,5 +38,7 @@ class TopologicalSort: XCTestCase { func testTopologicalSort() { XCTAssertEqual(graph.topologicalSort(), ["3", "8", "9", "10", "7", "11", "2", "5"]) + + XCTAssertEqual(graph.topologicalSort2(), ["3", "7", "5", "8", "11", "2", "9", "10"]) } } diff --git a/Topological Sort/Topological Sort.playground/Contents.swift b/Topological Sort/Topological Sort.playground/Contents.swift index 2d6af7e4f..d1a92abbc 100644 --- a/Topological Sort/Topological Sort.playground/Contents.swift +++ b/Topological Sort/Topological Sort.playground/Contents.swift @@ -24,4 +24,9 @@ graph.addEdge(fromNode: node11, toNode: node10) graph.addEdge(fromNode: node8, toNode: node9) + +// using depth-first search graph.topologicalSort() + +// alternative method +graph.topologicalSort2() diff --git a/Topological Sort/Topological Sort.playground/Sources/Graph.swift b/Topological Sort/Topological Sort.playground/Sources/Graph.swift index 5cf228d65..fca7485e8 100644 --- a/Topological Sort/Topological Sort.playground/Sources/Graph.swift +++ b/Topological Sort/Topological Sort.playground/Sources/Graph.swift @@ -1,8 +1,7 @@ public class Graph: CustomStringConvertible { - public typealias Node = String - private var adjacencyLists: [Node : [Node]] + private(set) public var adjacencyLists: [Node : [Node]] public init() { adjacencyLists = [Node : [Node]]() @@ -22,7 +21,7 @@ public class Graph: CustomStringConvertible { return adjacencyLists.description } - private func adjacencyList(forNode node: Node) -> [Node]? { + public func adjacencyList(forNode node: Node) -> [Node]? { for (key, adjacencyList) in adjacencyLists { if key == node { return adjacencyList @@ -31,61 +30,3 @@ public class Graph: CustomStringConvertible { return nil } } - -extension Graph { - - typealias InDegree = Int - private func calculateInDegreeOfNodes() -> [Node : InDegree] { - - var inDegrees = [Node : InDegree]() - - for (node, _) in adjacencyLists { - inDegrees[node] = 0 - } - - for (_, adjacencyList) in adjacencyLists { - for nodeInList in adjacencyList { - inDegrees[nodeInList] = (inDegrees[nodeInList] ?? 0) + 1 - } - } - return inDegrees - } - - private func depthFirstSearch(source: Node, inout visited: [Node : Bool]) -> [Node] { - var result = [source] - visited[source] = true - - if let adjacencyList = adjacencyList(forNode: source) { - for nodeInAdjacencyList in adjacencyList { - if !(visited[nodeInAdjacencyList] ?? false) { - result += (depthFirstSearch(nodeInAdjacencyList, visited: &visited)) - } - } - } - - return result - } - - public func topologicalSort() -> [Node] { - - let startNodes = calculateInDegreeOfNodes().filter({(_, indegree) in - return indegree == 0 - }).map({(node, indegree) in - return node - }) - - var visited = [Node : Bool]() - - for (node, _) in adjacencyLists { - visited[node] = false - } - - var result = [Node]() - - for startNode in startNodes { - result += depthFirstSearch(startNode, visited: &visited) - } - - return result - } -} \ No newline at end of file diff --git a/Topological Sort/Topological Sort.playground/Sources/Stack.swift b/Topological Sort/Topological Sort.playground/Sources/Stack.swift index 7099e5f55..7f4aadc8b 100644 --- a/Topological Sort/Topological Sort.playground/Sources/Stack.swift +++ b/Topological Sort/Topological Sort.playground/Sources/Stack.swift @@ -1,5 +1,3 @@ -import Foundation - public struct Stack { private var array = [T]() @@ -27,13 +25,3 @@ public struct Stack { return array.last } } - -extension Stack: SequenceType { - public func generate() -> AnyGenerator { - var curr = self - return anyGenerator { - _ -> T? in - return curr.pop() - } - } -} \ No newline at end of file diff --git a/Topological Sort/TopologicalSort/TopologicalSort/Graph.swift b/Topological Sort/Topological Sort.playground/Sources/TopologicalSort1.swift similarity index 61% rename from Topological Sort/TopologicalSort/TopologicalSort/Graph.swift rename to Topological Sort/Topological Sort.playground/Sources/TopologicalSort1.swift index f30f30241..011c4164b 100644 --- a/Topological Sort/TopologicalSort/TopologicalSort/Graph.swift +++ b/Topological Sort/Topological Sort.playground/Sources/TopologicalSort1.swift @@ -1,43 +1,7 @@ - -public class Graph: CustomStringConvertible { - - public typealias Node = String - - private var adjacencyLists: [Node : [Node]] - - public init() { - adjacencyLists = [Node : [Node]]() - } - - public func addNode(value: Node) -> Node { - adjacencyLists[value] = [] - return value - } - - public func addEdge(fromNode from: Node, toNode to: Node) -> Bool { - adjacencyLists[from]?.append(to) - return adjacencyLists[from] != nil ? true : false - } - - public var description: String { - return adjacencyLists.description - } - - private func adjacencyList(forNode node: Node) -> [Node]? { - for (key, adjacencyList) in adjacencyLists { - if key == node { - return adjacencyList - } - } - return nil - } -} - extension Graph { - typealias InDegree = Int - private func calculateInDegreeOfNodes() -> [Node : InDegree] { - + + func calculateInDegreeOfNodes() -> [Node : InDegree] { var inDegrees = [Node : InDegree]() for (node, _) in adjacencyLists { @@ -63,7 +27,6 @@ extension Graph { } } } - return result } @@ -74,7 +37,7 @@ extension Graph { }).map({(node, indegree) in return node }) - + var visited = [Node : Bool]() for (node, _) in adjacencyLists { @@ -90,4 +53,3 @@ extension Graph { return result } } - diff --git a/Topological Sort/Topological Sort.playground/Sources/TopologicalSort2.swift b/Topological Sort/Topological Sort.playground/Sources/TopologicalSort2.swift new file mode 100644 index 000000000..468e098df --- /dev/null +++ b/Topological Sort/Topological Sort.playground/Sources/TopologicalSort2.swift @@ -0,0 +1,41 @@ +extension Graph { + /* Topological sort that does not use a depth-first search. */ + public func topologicalSort2() -> [Node] { + var nodes = calculateInDegreeOfNodes() + + // Find vertices with no predecessors and puts them into a new list. + // These are the "leaders". The leaders array eventually becomes the + // topologically sorted list. + var leaders = nodes.filter({ _, indegree in + return indegree == 0 + }).map({ node, indegree in + return node + }) + + // "Remove" each of the leaders. We do this by decrementing the in-degree + // of the nodes they point to. As soon as such a node has itself no more + // predecessors, it is added to the leaders array. This repeats until there + // are no more vertices left. + var l = 0 + while l < leaders.count { + if let edges = adjacencyList(forNode: leaders[l]) { + for neighbor in edges { + if let count = nodes[neighbor] { + nodes[neighbor] = count - 1 + if count == 1 { // this leader was the last predecessor + leaders.append(neighbor) // so neighbor is now a leader itself + } + } + } + } + l += 1 + } + + // Was there a cycle in the graph? + if leaders.count != nodes.count { + print("Error: graphs with cycles are not allowed") + } + + return leaders + } +} diff --git a/Topological Sort/TopologicalSort/TopologicalSort.xcodeproj/project.pbxproj b/Topological Sort/TopologicalSort/TopologicalSort.xcodeproj/project.pbxproj deleted file mode 100644 index 2d0ec1b6b..000000000 --- a/Topological Sort/TopologicalSort/TopologicalSort.xcodeproj/project.pbxproj +++ /dev/null @@ -1,260 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 61FB15B41C8D70B7000CEA54 /* TopologicalSort.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61FB15B31C8D70B7000CEA54 /* TopologicalSort.swift */; }; - 61FB15BB1C8D70D7000CEA54 /* Graph.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61FB15B91C8D70D7000CEA54 /* Graph.swift */; }; - 61FB15BC1C8D70D7000CEA54 /* Stack.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61FB15BA1C8D70D7000CEA54 /* Stack.swift */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - 61FB15B01C8D70B7000CEA54 /* TopologicalSort.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TopologicalSort.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 61FB15B31C8D70B7000CEA54 /* TopologicalSort.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TopologicalSort.swift; sourceTree = ""; }; - 61FB15B51C8D70B7000CEA54 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 61FB15B91C8D70D7000CEA54 /* Graph.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Graph.swift; sourceTree = ""; }; - 61FB15BA1C8D70D7000CEA54 /* Stack.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Stack.swift; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 61FB15AD1C8D70B7000CEA54 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 61FB15A51C8D709E000CEA54 = { - isa = PBXGroup; - children = ( - 61FB15B21C8D70B7000CEA54 /* TopologicalSort */, - 61FB15B11C8D70B7000CEA54 /* Products */, - ); - sourceTree = ""; - }; - 61FB15B11C8D70B7000CEA54 /* Products */ = { - isa = PBXGroup; - children = ( - 61FB15B01C8D70B7000CEA54 /* TopologicalSort.xctest */, - ); - name = Products; - sourceTree = ""; - }; - 61FB15B21C8D70B7000CEA54 /* TopologicalSort */ = { - isa = PBXGroup; - children = ( - 61FB15B91C8D70D7000CEA54 /* Graph.swift */, - 61FB15BA1C8D70D7000CEA54 /* Stack.swift */, - 61FB15B31C8D70B7000CEA54 /* TopologicalSort.swift */, - 61FB15B51C8D70B7000CEA54 /* Info.plist */, - ); - path = TopologicalSort; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 61FB15AF1C8D70B7000CEA54 /* TopologicalSort */ = { - isa = PBXNativeTarget; - buildConfigurationList = 61FB15B61C8D70B7000CEA54 /* Build configuration list for PBXNativeTarget "TopologicalSort" */; - buildPhases = ( - 61FB15AC1C8D70B7000CEA54 /* Sources */, - 61FB15AD1C8D70B7000CEA54 /* Frameworks */, - 61FB15AE1C8D70B7000CEA54 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = TopologicalSort; - productName = TopologicalSort; - productReference = 61FB15B01C8D70B7000CEA54 /* TopologicalSort.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 61FB15A61C8D709E000CEA54 /* Project object */ = { - isa = PBXProject; - attributes = { - LastSwiftUpdateCheck = 0720; - LastUpgradeCheck = 0720; - TargetAttributes = { - 61FB15AF1C8D70B7000CEA54 = { - CreatedOnToolsVersion = 7.2.1; - }; - }; - }; - buildConfigurationList = 61FB15A91C8D709E000CEA54 /* Build configuration list for PBXProject "TopologicalSort" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - ); - mainGroup = 61FB15A51C8D709E000CEA54; - productRefGroup = 61FB15B11C8D70B7000CEA54 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 61FB15AF1C8D70B7000CEA54 /* TopologicalSort */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 61FB15AE1C8D70B7000CEA54 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 61FB15AC1C8D70B7000CEA54 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 61FB15BB1C8D70D7000CEA54 /* Graph.swift in Sources */, - 61FB15BC1C8D70D7000CEA54 /* Stack.swift in Sources */, - 61FB15B41C8D70B7000CEA54 /* TopologicalSort.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin XCBuildConfiguration section */ - 61FB15AA1C8D709E000CEA54 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - }; - name = Debug; - }; - 61FB15AB1C8D709E000CEA54 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - }; - name = Release; - }; - 61FB15B71C8D70B7000CEA54 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - INFOPLIST_FILE = TopologicalSort/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 9.2; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - PRODUCT_BUNDLE_IDENTIFIER = com.alihafizji.TopologicalSort; - PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = iphoneos; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - }; - name = Debug; - }; - 61FB15B81C8D70B7000CEA54 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - INFOPLIST_FILE = TopologicalSort/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 9.2; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MTL_ENABLE_DEBUG_INFO = NO; - PRODUCT_BUNDLE_IDENTIFIER = com.alihafizji.TopologicalSort; - PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = iphoneos; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 61FB15A91C8D709E000CEA54 /* Build configuration list for PBXProject "TopologicalSort" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 61FB15AA1C8D709E000CEA54 /* Debug */, - 61FB15AB1C8D709E000CEA54 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 61FB15B61C8D70B7000CEA54 /* Build configuration list for PBXNativeTarget "TopologicalSort" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 61FB15B71C8D70B7000CEA54 /* Debug */, - 61FB15B81C8D70B7000CEA54 /* Release */, - ); - defaultConfigurationIsVisible = 0; - }; -/* End XCConfigurationList section */ - }; - rootObject = 61FB15A61C8D709E000CEA54 /* Project object */; -} diff --git a/Topological Sort/TopologicalSort1.swift b/Topological Sort/TopologicalSort1.swift new file mode 100644 index 000000000..500b8ca11 --- /dev/null +++ b/Topological Sort/TopologicalSort1.swift @@ -0,0 +1,55 @@ +extension Graph { + typealias InDegree = Int + + func calculateInDegreeOfNodes() -> [Node : InDegree] { + var inDegrees = [Node : InDegree]() + + for (node, _) in adjacencyLists { + inDegrees[node] = 0 + } + + for (_, adjacencyList) in adjacencyLists { + for nodeInList in adjacencyList { + inDegrees[nodeInList] = (inDegrees[nodeInList] ?? 0) + 1 + } + } + return inDegrees + } + + private func depthFirstSearch(source: Node, inout visited: [Node : Bool]) -> [Node] { + var result = [source] + visited[source] = true + + if let adjacencyList = adjacencyList(forNode: source) { + for nodeInAdjacencyList in adjacencyList { + if !(visited[nodeInAdjacencyList] ?? false) { + result += (depthFirstSearch(nodeInAdjacencyList, visited: &visited)) + } + } + } + return result + } + + public func topologicalSort() -> [Node] { + + let startNodes = calculateInDegreeOfNodes().filter({(_, indegree) in + return indegree == 0 + }).map({(node, indegree) in + return node + }) + + var visited = [Node : Bool]() + + for (node, _) in adjacencyLists { + visited[node] = false + } + + var result = [Node]() + + for startNode in startNodes { + result += depthFirstSearch(startNode, visited: &visited) + } + + return result + } +} diff --git a/Topological Sort/TopologicalSort2.swift b/Topological Sort/TopologicalSort2.swift new file mode 100644 index 000000000..468e098df --- /dev/null +++ b/Topological Sort/TopologicalSort2.swift @@ -0,0 +1,41 @@ +extension Graph { + /* Topological sort that does not use a depth-first search. */ + public func topologicalSort2() -> [Node] { + var nodes = calculateInDegreeOfNodes() + + // Find vertices with no predecessors and puts them into a new list. + // These are the "leaders". The leaders array eventually becomes the + // topologically sorted list. + var leaders = nodes.filter({ _, indegree in + return indegree == 0 + }).map({ node, indegree in + return node + }) + + // "Remove" each of the leaders. We do this by decrementing the in-degree + // of the nodes they point to. As soon as such a node has itself no more + // predecessors, it is added to the leaders array. This repeats until there + // are no more vertices left. + var l = 0 + while l < leaders.count { + if let edges = adjacencyList(forNode: leaders[l]) { + for neighbor in edges { + if let count = nodes[neighbor] { + nodes[neighbor] = count - 1 + if count == 1 { // this leader was the last predecessor + leaders.append(neighbor) // so neighbor is now a leader itself + } + } + } + } + l += 1 + } + + // Was there a cycle in the graph? + if leaders.count != nodes.count { + print("Error: graphs with cycles are not allowed") + } + + return leaders + } +} From 87802ee1f878ef854ac52059fac97289e16a163f Mon Sep 17 00:00:00 2001 From: Matthijs Hollemans Date: Wed, 9 Mar 2016 14:28:41 +0100 Subject: [PATCH 0128/1679] Put Edge and Node into Graph.swift It's only supporting code so it shouldn't draw too much attention to itself. --- .../Contents.swift | 4 ++ .../Contents.swift | 7 +++ .../Contents.swift | 5 ++ .../Sources/Graph.swift | 1 - Breadth-First Search/Edge.swift | 11 ---- Breadth-First Search/Graph.swift | 52 ++++++++++++++++++- Breadth-First Search/Node.swift | 32 ------------ .../Tests/Tests.xcodeproj/project.pbxproj | 18 ++----- .../Sources/Graph.swift | 1 - Depth-First Search/Edge.swift | 11 ---- Depth-First Search/Graph.swift | 52 ++++++++++++++++++- Depth-First Search/Node.swift | 32 ------------ .../Tests/Tests.xcodeproj/project.pbxproj | 8 --- 13 files changed, 123 insertions(+), 111 deletions(-) delete mode 100644 Breadth-First Search/Edge.swift delete mode 100644 Breadth-First Search/Node.swift delete mode 100644 Depth-First Search/Edge.swift delete mode 100644 Depth-First Search/Node.swift diff --git a/Breadth-First Search/BreadthFirstSearch.playground/Pages/Minimum spanning tree example.xcplaygroundpage/Contents.swift b/Breadth-First Search/BreadthFirstSearch.playground/Pages/Minimum spanning tree example.xcplaygroundpage/Contents.swift index 181d566d4..c0868c653 100644 --- a/Breadth-First Search/BreadthFirstSearch.playground/Pages/Minimum spanning tree example.xcplaygroundpage/Contents.swift +++ b/Breadth-First Search/BreadthFirstSearch.playground/Pages/Minimum spanning tree example.xcplaygroundpage/Contents.swift @@ -1,3 +1,7 @@ +//: [Previous](@previous) + +//: # Minimum Spanning Tree Example + func breadthFirstSearchMinimumSpanningTree(graph: Graph, source: Node) -> Graph { let minimumSpanningTree = graph.duplicate() diff --git a/Breadth-First Search/BreadthFirstSearch.playground/Pages/Shortest path example.xcplaygroundpage/Contents.swift b/Breadth-First Search/BreadthFirstSearch.playground/Pages/Shortest path example.xcplaygroundpage/Contents.swift index 28cdc6093..be35cc684 100644 --- a/Breadth-First Search/BreadthFirstSearch.playground/Pages/Shortest path example.xcplaygroundpage/Contents.swift +++ b/Breadth-First Search/BreadthFirstSearch.playground/Pages/Shortest path example.xcplaygroundpage/Contents.swift @@ -1,3 +1,7 @@ +//: [Previous](@previous) + +//: # Shortest Path Example + func breadthFirstSearchShortestPath(graph: Graph, source: Node) -> Graph { let shortestPathGraph = graph.duplicate() @@ -44,3 +48,6 @@ graph.addEdge(nodeE, neighbor: nodeH) let shortestPathGraph = breadthFirstSearchShortestPath(graph, source: nodeA) print(shortestPathGraph.nodes) + +//: [Next: Minimum Spanning Tree Example](@next) + diff --git a/Breadth-First Search/BreadthFirstSearch.playground/Pages/Simple example.xcplaygroundpage/Contents.swift b/Breadth-First Search/BreadthFirstSearch.playground/Pages/Simple example.xcplaygroundpage/Contents.swift index ed655b591..8cd7df2f5 100644 --- a/Breadth-First Search/BreadthFirstSearch.playground/Pages/Simple example.xcplaygroundpage/Contents.swift +++ b/Breadth-First Search/BreadthFirstSearch.playground/Pages/Simple example.xcplaygroundpage/Contents.swift @@ -1,3 +1,5 @@ +//: # Breadth-First Search + func breadthFirstSearch(graph: Graph, source: Node) -> [String] { var queue = Queue() queue.enqueue(source) @@ -46,3 +48,6 @@ graph.addEdge(nodeE, neighbor: nodeH) let nodesExplored = breadthFirstSearch(graph, source: nodeA) print(nodesExplored) + +//: [Next: Shortest Path Example](@next) + diff --git a/Breadth-First Search/BreadthFirstSearch.playground/Sources/Graph.swift b/Breadth-First Search/BreadthFirstSearch.playground/Sources/Graph.swift index 181af9e85..e89d4ac97 100644 --- a/Breadth-First Search/BreadthFirstSearch.playground/Sources/Graph.swift +++ b/Breadth-First Search/BreadthFirstSearch.playground/Sources/Graph.swift @@ -13,7 +13,6 @@ public class Graph : CustomStringConvertible, Equatable { public func addEdge(source: Node, neighbor: Node) { let edge = Edge(neighbor: neighbor) - edge.neighbor = neighbor source.neighbors.append(edge) } diff --git a/Breadth-First Search/Edge.swift b/Breadth-First Search/Edge.swift deleted file mode 100644 index 3937a2cc7..000000000 --- a/Breadth-First Search/Edge.swift +++ /dev/null @@ -1,11 +0,0 @@ -public class Edge : Equatable { - public var neighbor: Node - - public init(neighbor: Node) { - self.neighbor = neighbor - } -} - -public func ==(lhs: Edge, rhs: Edge) -> Bool { - return lhs.neighbor == rhs.neighbor -} diff --git a/Breadth-First Search/Graph.swift b/Breadth-First Search/Graph.swift index 181af9e85..6f69ee800 100644 --- a/Breadth-First Search/Graph.swift +++ b/Breadth-First Search/Graph.swift @@ -1,3 +1,54 @@ +// MARK: - Edge + +public class Edge : Equatable { + public var neighbor: Node + + public init(neighbor: Node) { + self.neighbor = neighbor + } +} + +public func ==(lhs: Edge, rhs: Edge) -> Bool { + return lhs.neighbor == rhs.neighbor +} + +// MARK: - Node + +public class Node : CustomStringConvertible, Equatable { + public var neighbors: [Edge] + + public private(set) var label: String + public var distance: Int? + public var visited: Bool + + public init(label: String) { + self.label = label + neighbors = [] + visited = false + } + + public var description: String { + if let distance = distance { + return "Node(label: \(label), distance: \(distance))" + } + return "Node(label: \(label), distance: infinity)" + } + + public var hasDistance: Bool { + return distance != nil + } + + public func remove(edge: Edge) { + neighbors.removeAtIndex(neighbors.indexOf{ $0 === edge }!) + } +} + +public func ==(lhs: Node, rhs: Node) -> Bool { + return lhs.label == rhs.label && lhs.neighbors == rhs.neighbors +} + +// MARK: - Graph + public class Graph : CustomStringConvertible, Equatable { public private(set) var nodes: [Node] @@ -13,7 +64,6 @@ public class Graph : CustomStringConvertible, Equatable { public func addEdge(source: Node, neighbor: Node) { let edge = Edge(neighbor: neighbor) - edge.neighbor = neighbor source.neighbors.append(edge) } diff --git a/Breadth-First Search/Node.swift b/Breadth-First Search/Node.swift deleted file mode 100644 index 000fd78f6..000000000 --- a/Breadth-First Search/Node.swift +++ /dev/null @@ -1,32 +0,0 @@ -public class Node : CustomStringConvertible, Equatable { - public var neighbors: [Edge] - - public private(set) var label: String - public var distance: Int? - public var visited: Bool - - public init(label: String) { - self.label = label - neighbors = [] - visited = false - } - - public var description: String { - if let distance = distance { - return "Node(label: \(label), distance: \(distance))" - } - return "Node(label: \(label), distance: infinity)" - } - - public var hasDistance: Bool { - return distance != nil - } - - public func remove(edge: Edge) { - neighbors.removeAtIndex(neighbors.indexOf{ $0 === edge }!) - } -} - -public func ==(lhs: Node, rhs: Node) -> Bool { - return lhs.label == rhs.label && lhs.neighbors == rhs.neighbors -} diff --git a/Breadth-First Search/Tests/Tests.xcodeproj/project.pbxproj b/Breadth-First Search/Tests/Tests.xcodeproj/project.pbxproj index 8946ba1a6..061e1be44 100644 --- a/Breadth-First Search/Tests/Tests.xcodeproj/project.pbxproj +++ b/Breadth-First Search/Tests/Tests.xcodeproj/project.pbxproj @@ -13,9 +13,7 @@ 83F9C9691C84437C00B3A87F /* BreadthFirstSearchMinimumSpanningTree.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83F9C9661C84437C00B3A87F /* BreadthFirstSearchMinimumSpanningTree.swift */; }; 83F9C96A1C84437C00B3A87F /* BreadthFirstSearchShortestPath.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83F9C9671C84437C00B3A87F /* BreadthFirstSearchShortestPath.swift */; }; 83F9C96C1C8443E800B3A87F /* BreadthFirstSearchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83F9C96B1C8443E800B3A87F /* BreadthFirstSearchTests.swift */; }; - 83F9C9711C84449D00B3A87F /* Edge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83F9C96D1C84449D00B3A87F /* Edge.swift */; }; 83F9C9721C84449D00B3A87F /* Graph.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83F9C96E1C84449D00B3A87F /* Graph.swift */; }; - 83F9C9731C84449D00B3A87F /* Node.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83F9C96F1C84449D00B3A87F /* Node.swift */; }; 83F9C9741C84449D00B3A87F /* Queue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83F9C9701C84449D00B3A87F /* Queue.swift */; }; /* End PBXBuildFile section */ @@ -28,9 +26,7 @@ 83F9C9661C84437C00B3A87F /* BreadthFirstSearchMinimumSpanningTree.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BreadthFirstSearchMinimumSpanningTree.swift; path = ../BreadthFirstSearchMinimumSpanningTree.swift; sourceTree = SOURCE_ROOT; }; 83F9C9671C84437C00B3A87F /* BreadthFirstSearchShortestPath.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BreadthFirstSearchShortestPath.swift; path = ../BreadthFirstSearchShortestPath.swift; sourceTree = SOURCE_ROOT; }; 83F9C96B1C8443E800B3A87F /* BreadthFirstSearchTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BreadthFirstSearchTests.swift; sourceTree = SOURCE_ROOT; }; - 83F9C96D1C84449D00B3A87F /* Edge.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Edge.swift; path = ../Edge.swift; sourceTree = SOURCE_ROOT; }; 83F9C96E1C84449D00B3A87F /* Graph.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Graph.swift; path = ../Graph.swift; sourceTree = SOURCE_ROOT; }; - 83F9C96F1C84449D00B3A87F /* Node.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Node.swift; path = ../Node.swift; sourceTree = SOURCE_ROOT; }; 83F9C9701C84449D00B3A87F /* Queue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Queue.swift; path = ../Queue.swift; sourceTree = SOURCE_ROOT; }; /* End PBXFileReference section */ @@ -64,16 +60,14 @@ 7B2BBC831C779D720067B71D /* Tests */ = { isa = PBXGroup; children = ( - 83F9C96D1C84449D00B3A87F /* Edge.swift */, - 83F9C96E1C84449D00B3A87F /* Graph.swift */, - 83F9C96F1C84449D00B3A87F /* Node.swift */, - 83F9C9701C84449D00B3A87F /* Queue.swift */, 83F9C9651C84437C00B3A87F /* BreadthFirstSearch.swift */, - 83F9C9671C84437C00B3A87F /* BreadthFirstSearchShortestPath.swift */, - 83F9C9661C84437C00B3A87F /* BreadthFirstSearchMinimumSpanningTree.swift */, 83F9C96B1C8443E800B3A87F /* BreadthFirstSearchTests.swift */, - 83AACB431C8456D200DDAFC7 /* BreadthFirstSearchShortestPathTests.swift */, + 83F9C9661C84437C00B3A87F /* BreadthFirstSearchMinimumSpanningTree.swift */, 83AACB411C844CED00DDAFC7 /* BreadthFirstSearchMinimumSpanningTreeTests.swift */, + 83F9C9671C84437C00B3A87F /* BreadthFirstSearchShortestPath.swift */, + 83AACB431C8456D200DDAFC7 /* BreadthFirstSearchShortestPathTests.swift */, + 83F9C96E1C84449D00B3A87F /* Graph.swift */, + 83F9C9701C84449D00B3A87F /* Queue.swift */, 7B2BBC941C779E7B0067B71D /* Info.plist */, ); name = Tests; @@ -155,9 +149,7 @@ 83F9C9681C84437C00B3A87F /* BreadthFirstSearch.swift in Sources */, 83F9C9741C84449D00B3A87F /* Queue.swift in Sources */, 83F9C96A1C84437C00B3A87F /* BreadthFirstSearchShortestPath.swift in Sources */, - 83F9C9711C84449D00B3A87F /* Edge.swift in Sources */, 83F9C96C1C8443E800B3A87F /* BreadthFirstSearchTests.swift in Sources */, - 83F9C9731C84449D00B3A87F /* Node.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Depth-First Search/DepthFirstSearch.playground/Sources/Graph.swift b/Depth-First Search/DepthFirstSearch.playground/Sources/Graph.swift index 181af9e85..e89d4ac97 100644 --- a/Depth-First Search/DepthFirstSearch.playground/Sources/Graph.swift +++ b/Depth-First Search/DepthFirstSearch.playground/Sources/Graph.swift @@ -13,7 +13,6 @@ public class Graph : CustomStringConvertible, Equatable { public func addEdge(source: Node, neighbor: Node) { let edge = Edge(neighbor: neighbor) - edge.neighbor = neighbor source.neighbors.append(edge) } diff --git a/Depth-First Search/Edge.swift b/Depth-First Search/Edge.swift deleted file mode 100644 index 3937a2cc7..000000000 --- a/Depth-First Search/Edge.swift +++ /dev/null @@ -1,11 +0,0 @@ -public class Edge : Equatable { - public var neighbor: Node - - public init(neighbor: Node) { - self.neighbor = neighbor - } -} - -public func ==(lhs: Edge, rhs: Edge) -> Bool { - return lhs.neighbor == rhs.neighbor -} diff --git a/Depth-First Search/Graph.swift b/Depth-First Search/Graph.swift index 181af9e85..6f69ee800 100644 --- a/Depth-First Search/Graph.swift +++ b/Depth-First Search/Graph.swift @@ -1,3 +1,54 @@ +// MARK: - Edge + +public class Edge : Equatable { + public var neighbor: Node + + public init(neighbor: Node) { + self.neighbor = neighbor + } +} + +public func ==(lhs: Edge, rhs: Edge) -> Bool { + return lhs.neighbor == rhs.neighbor +} + +// MARK: - Node + +public class Node : CustomStringConvertible, Equatable { + public var neighbors: [Edge] + + public private(set) var label: String + public var distance: Int? + public var visited: Bool + + public init(label: String) { + self.label = label + neighbors = [] + visited = false + } + + public var description: String { + if let distance = distance { + return "Node(label: \(label), distance: \(distance))" + } + return "Node(label: \(label), distance: infinity)" + } + + public var hasDistance: Bool { + return distance != nil + } + + public func remove(edge: Edge) { + neighbors.removeAtIndex(neighbors.indexOf{ $0 === edge }!) + } +} + +public func ==(lhs: Node, rhs: Node) -> Bool { + return lhs.label == rhs.label && lhs.neighbors == rhs.neighbors +} + +// MARK: - Graph + public class Graph : CustomStringConvertible, Equatable { public private(set) var nodes: [Node] @@ -13,7 +64,6 @@ public class Graph : CustomStringConvertible, Equatable { public func addEdge(source: Node, neighbor: Node) { let edge = Edge(neighbor: neighbor) - edge.neighbor = neighbor source.neighbors.append(edge) } diff --git a/Depth-First Search/Node.swift b/Depth-First Search/Node.swift deleted file mode 100644 index 000fd78f6..000000000 --- a/Depth-First Search/Node.swift +++ /dev/null @@ -1,32 +0,0 @@ -public class Node : CustomStringConvertible, Equatable { - public var neighbors: [Edge] - - public private(set) var label: String - public var distance: Int? - public var visited: Bool - - public init(label: String) { - self.label = label - neighbors = [] - visited = false - } - - public var description: String { - if let distance = distance { - return "Node(label: \(label), distance: \(distance))" - } - return "Node(label: \(label), distance: infinity)" - } - - public var hasDistance: Bool { - return distance != nil - } - - public func remove(edge: Edge) { - neighbors.removeAtIndex(neighbors.indexOf{ $0 === edge }!) - } -} - -public func ==(lhs: Node, rhs: Node) -> Bool { - return lhs.label == rhs.label && lhs.neighbors == rhs.neighbors -} diff --git a/Depth-First Search/Tests/Tests.xcodeproj/project.pbxproj b/Depth-First Search/Tests/Tests.xcodeproj/project.pbxproj index e3c46e3cc..39c15ce79 100644 --- a/Depth-First Search/Tests/Tests.xcodeproj/project.pbxproj +++ b/Depth-First Search/Tests/Tests.xcodeproj/project.pbxproj @@ -8,9 +8,7 @@ /* Begin PBXBuildFile section */ 83F9C96C1C8443E800B3A87F /* DepthFirstSearchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83F9C96B1C8443E800B3A87F /* DepthFirstSearchTests.swift */; }; - 83F9C9711C84449D00B3A87F /* Edge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83F9C96D1C84449D00B3A87F /* Edge.swift */; }; 83F9C9721C84449D00B3A87F /* Graph.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83F9C96E1C84449D00B3A87F /* Graph.swift */; }; - 83F9C9731C84449D00B3A87F /* Node.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83F9C96F1C84449D00B3A87F /* Node.swift */; }; FFC6E11E1C8656D10046BA79 /* DepthFirstSearch.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFC6E11D1C8656D10046BA79 /* DepthFirstSearch.swift */; }; /* End PBXBuildFile section */ @@ -18,9 +16,7 @@ 7B2BBC801C779D720067B71D /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 7B2BBC941C779E7B0067B71D /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; 83F9C96B1C8443E800B3A87F /* DepthFirstSearchTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DepthFirstSearchTests.swift; sourceTree = SOURCE_ROOT; }; - 83F9C96D1C84449D00B3A87F /* Edge.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Edge.swift; path = ../Edge.swift; sourceTree = SOURCE_ROOT; }; 83F9C96E1C84449D00B3A87F /* Graph.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Graph.swift; path = ../Graph.swift; sourceTree = SOURCE_ROOT; }; - 83F9C96F1C84449D00B3A87F /* Node.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Node.swift; path = ../Node.swift; sourceTree = SOURCE_ROOT; }; FFC6E11D1C8656D10046BA79 /* DepthFirstSearch.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = DepthFirstSearch.swift; path = ../DepthFirstSearch.swift; sourceTree = SOURCE_ROOT; }; /* End PBXFileReference section */ @@ -54,9 +50,7 @@ 7B2BBC831C779D720067B71D /* Tests */ = { isa = PBXGroup; children = ( - 83F9C96D1C84449D00B3A87F /* Edge.swift */, 83F9C96E1C84449D00B3A87F /* Graph.swift */, - 83F9C96F1C84449D00B3A87F /* Node.swift */, 83F9C96B1C8443E800B3A87F /* DepthFirstSearchTests.swift */, FFC6E11D1C8656D10046BA79 /* DepthFirstSearch.swift */, 7B2BBC941C779E7B0067B71D /* Info.plist */, @@ -134,10 +128,8 @@ buildActionMask = 2147483647; files = ( 83F9C9721C84449D00B3A87F /* Graph.swift in Sources */, - 83F9C9711C84449D00B3A87F /* Edge.swift in Sources */, FFC6E11E1C8656D10046BA79 /* DepthFirstSearch.swift in Sources */, 83F9C96C1C8443E800B3A87F /* DepthFirstSearchTests.swift in Sources */, - 83F9C9731C84449D00B3A87F /* Node.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; From 619e604e0086cdc4a4752eb7bdac163c776f3b74 Mon Sep 17 00:00:00 2001 From: Matthijs Hollemans Date: Wed, 9 Mar 2016 14:32:20 +0100 Subject: [PATCH 0129/1679] Add link to @lorentey's repos --- README.markdown | 1 + 1 file changed, 1 insertion(+) diff --git a/README.markdown b/README.markdown index 1465626f5..833d12a54 100644 --- a/README.markdown +++ b/README.markdown @@ -200,6 +200,7 @@ The following books are available for free online: Other algorithm repositories: - [EKAlgorithms](https://github.com/EvgenyKarkan/EKAlgorithms). A great collection of algorithms in Objective-C. +- [@lorentey](https://github.com/lorentey/). Production-quality Swift implementations of common algorithms and data structures. - [Rosetta Code](http://rosettacode.org). Implementations in pretty much any language you can think of. ## License From a6ddf98faa0d68865b6edf0d70308a16055efa4e Mon Sep 17 00:00:00 2001 From: Matthijs Hollemans Date: Sat, 12 Mar 2016 14:25:21 +0100 Subject: [PATCH 0130/1679] Add explanation of alternative algorithm + more tests --- README.markdown | 2 +- Topological Sort/README.markdown | 15 +++- .../Tests/TopologicalSortTests.swift | 73 ++++++++++++++----- 3 files changed, 71 insertions(+), 19 deletions(-) diff --git a/README.markdown b/README.markdown index 833d12a54..92dfa013f 100644 --- a/README.markdown +++ b/README.markdown @@ -74,7 +74,7 @@ Special-purpose sorts: - Bucket Sort - Counting Sort - Radix Sort -- [Topological Sort](Topological Sort/) +- [Topological Sort](Topological Sort/) :construction: Bad sorting algorithms (don't use these!): diff --git a/Topological Sort/README.markdown b/Topological Sort/README.markdown index 045f910b6..58985c908 100644 --- a/Topological Sort/README.markdown +++ b/Topological Sort/README.markdown @@ -70,5 +70,18 @@ The result of the topological sort looks like this: TODO: I don't think this is correct! There should be no arrows going from right to left! (A valid topological order would be 3, 7, 5, 10, 8, 11, 9, 2 -- or 3, 7, 5, 8, 11, 2, 9, 10.) +## Alternative algorithm -*Written for Swift Algorithm Club by Ali Hafizji* +Even though depth-first search is the typical way to perform a topological sort, there is another algorithm that also does the job. + +1. Find out what the in-degree is of every vertex. +2. Put all the vertices that have no predecessors in a new array called `leaders`. These vertices have in-degree 0 and therefore do not depend on any other vertices. +3. Go through this list of leaders and remove them one-by-one from the graph. We don't actually modify the graph, we just decrement the in-degree of the vertices they point to. That has the same effect. +4. Look at the (former) immediate neighbor vertices of each leader. If any of them now have an in-degree of 0, then they no longer have any predecessors themselves. We'll add those vertices to the `leaders` array too. +5. This repeats until there are no more vertices left to look at. At this point, the `leaders` array contains all the vertices in sorted order. + +This is an **O(n + m)** algorithm where **n** is the number of vertices and **m** is the number of edges. You can see the implementation in [TopologicalSort2.swift](TopologicalSort2.swift). + +I first read about this algorithm in the Algorithm Alley column in Dr. Dobb's Magazine from May 1993. + +*Written for Swift Algorithm Club by Ali Hafizji and Matthijs Hollemans* diff --git a/Topological Sort/Tests/TopologicalSortTests.swift b/Topological Sort/Tests/TopologicalSortTests.swift index 41e7a854f..4d4178cfb 100644 --- a/Topological Sort/Tests/TopologicalSortTests.swift +++ b/Topological Sort/Tests/TopologicalSortTests.swift @@ -1,20 +1,25 @@ -// -// TopologicalSort.swift -// TopologicalSort -// -// Created by Kauserali on 07/03/16. -// -// - +import Foundation import XCTest +extension Graph { + public func loadEdgeList(lines: [String]) { + for line in lines { + let items = line.componentsSeparatedByString(" ").filter { s in !s.isEmpty } + if adjacencyList(forNode: items[0]) == nil { + addNode(items[0]) + } + if adjacencyList(forNode: items[1]) == nil { + addNode(items[1]) + } + addEdge(fromNode: items[0], toNode: items[1]) + } + } +} + class TopologicalSort: XCTestCase { - var graph: Graph! - - override func setUp() { - super.setUp() - graph = Graph() + func testTopologicalSort() { + let graph = Graph() let node5 = graph.addNode("5") let node7 = graph.addNode("7") @@ -34,11 +39,45 @@ class TopologicalSort: XCTestCase { graph.addEdge(fromNode: node11, toNode: node9) graph.addEdge(fromNode: node11, toNode: node10) graph.addEdge(fromNode: node8, toNode: node9) - } - - func testTopologicalSort() { - XCTAssertEqual(graph.topologicalSort(), ["3", "8", "9", "10", "7", "11", "2", "5"]) + XCTAssertEqual(graph.topologicalSort(), ["3", "8", "9", "10", "7", "11", "2", "5"]) XCTAssertEqual(graph.topologicalSort2(), ["3", "7", "5", "8", "11", "2", "9", "10"]) } + + func testTopologicalSortEdgeLists() { + let p1 = ["A B", "A C", "B C", "B D", "C E", "C F", "E D", "F E", "G A", "G F"] + let a1 = ["G", "A", "B", "C", "F", "E", "D"] // TODO + let s1 = ["G", "A", "B", "C", "F", "E", "D"] + + let p2 = ["B C", "C D", "C G", "B F", "D G", "G E", "F G", "F G"] + let a2 = ["B", "C", "F", "D", "G", "E"] // TODO + let s2 = ["B", "C", "F", "D", "G", "E"] + + let p3 = ["S V", "S W", "V T", "W T"] + let a3 = ["S", "V", "W", "T"] // TODO + let s3 = ["S", "V", "W", "T"] + + let p4 = ["5 11", "7 11", "7 8", "3 8", "3 10", "11 2", "11 9", "11 10", "8 9"] + let a4 = ["3", "8", "9", "10", "7", "11", "2", "5"] + let s4 = ["3", "7", "5", "8", "11", "2", "9", "10"] + + let data = [ + (p1, a1, s1), + (p2, a2, s2), + (p3, a3, s3), + (p4, a4, s4), + ] + + for d in data { + let graph = Graph() + graph.loadEdgeList(d.0) + + // TODO: this fails the tests + //let sorted1 = graph.topologicalSort() + //XCTAssertEqual(sorted1, d.1) + + let sorted2 = graph.topologicalSort2() + XCTAssertEqual(sorted2, d.2) + } + } } From 6a7d25873f9adde1e844e3ad95ae412dd408683a Mon Sep 17 00:00:00 2001 From: Pedro Vereza Date: Wed, 9 Mar 2016 09:45:32 -0300 Subject: [PATCH 0131/1679] Adds playground for Longest Common Subsequence --- .../Contents.swift | 62 +++++++++++++++++++ .../contents.xcplayground | 4 ++ .../timeline.xctimeline | 6 ++ 3 files changed, 72 insertions(+) create mode 100644 Longest Common Subsequence/LongestCommonSubsequence.playground/Contents.swift create mode 100644 Longest Common Subsequence/LongestCommonSubsequence.playground/contents.xcplayground create mode 100644 Longest Common Subsequence/LongestCommonSubsequence.playground/timeline.xctimeline diff --git a/Longest Common Subsequence/LongestCommonSubsequence.playground/Contents.swift b/Longest Common Subsequence/LongestCommonSubsequence.playground/Contents.swift new file mode 100644 index 000000000..8f49b45fb --- /dev/null +++ b/Longest Common Subsequence/LongestCommonSubsequence.playground/Contents.swift @@ -0,0 +1,62 @@ +extension String { + func longestCommonSubsequence(other:String) -> String { + + func lcsLength(other: String) -> [[Int]] { + var matrix = [[Int]](count:self.characters.count+1, repeatedValue:[Int](count:other.characters.count+1, repeatedValue:0)) + + for (i, selfChar) in self.characters.enumerate() { + for (j, otherChar) in other.characters.enumerate() { + if (otherChar == selfChar) { + matrix[i+1][j+1] = (matrix[i][j]) + 1 + } + else { + matrix[i+1][j+1] = max(matrix[i][j+1], matrix[i+1][j]) + } + } + } + + return matrix; + } + + func backtrack(matrix: [[Int]]) -> String { + var i = self.characters.count + var j = other.characters.count + var charInSequence = self.endIndex + + var lcs = String() + + while (i >= 1 && j >= 1) { + if (matrix[i][j] == matrix[i][j - 1]) { + j = j - 1 + } + else if (matrix[i][j] == matrix[i - 1][j]) { + i = i - 1 + charInSequence = charInSequence.predecessor() + } + else { + i = i - 1 + j = j - 1 + charInSequence = charInSequence.predecessor() + + lcs.append(self[charInSequence]) + } + } + + return String(lcs.characters.reverse()); + } + + return backtrack(lcsLength(other)) + } +} + +// Examples + +let a = "ABCBX" +let b = "ABDCAB" +let c = "KLMK" + +a.longestCommonSubsequence(c) //"" +a.longestCommonSubsequence("") //"" +a.longestCommonSubsequence(b) //"ABCB" +b.longestCommonSubsequence(a) //"ABCB" +a.longestCommonSubsequence(a) // "ABCBX" diff --git a/Longest Common Subsequence/LongestCommonSubsequence.playground/contents.xcplayground b/Longest Common Subsequence/LongestCommonSubsequence.playground/contents.xcplayground new file mode 100644 index 000000000..5da2641c9 --- /dev/null +++ b/Longest Common Subsequence/LongestCommonSubsequence.playground/contents.xcplayground @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Longest Common Subsequence/LongestCommonSubsequence.playground/timeline.xctimeline b/Longest Common Subsequence/LongestCommonSubsequence.playground/timeline.xctimeline new file mode 100644 index 000000000..bf468afec --- /dev/null +++ b/Longest Common Subsequence/LongestCommonSubsequence.playground/timeline.xctimeline @@ -0,0 +1,6 @@ + + + + + From 308d8e040a41817929509d9b73d593742a901c55 Mon Sep 17 00:00:00 2001 From: Pedro Vereza Date: Wed, 9 Mar 2016 21:20:16 -0300 Subject: [PATCH 0132/1679] Adds code with comments --- .../LongestCommonSubsequence.swift | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 Longest Common Subsequence/LongestCommonSubsequence.swift diff --git a/Longest Common Subsequence/LongestCommonSubsequence.swift b/Longest Common Subsequence/LongestCommonSubsequence.swift new file mode 100644 index 000000000..a6225bb74 --- /dev/null +++ b/Longest Common Subsequence/LongestCommonSubsequence.swift @@ -0,0 +1,68 @@ +extension String { + func longestCommonSubsequence(other:String) -> String { + + // Computes the length of the lcs using dynamic programming + // Output is a matrix of size (n+1)x(m+1), where matrix[x][y] indicates the length + // of lcs between substring (0, x-1) of self and substring (0, y-1) of other. + func lcsLength(other: String) -> [[Int]] { + + //Matrix of size (n+1)x(m+1), algorithm needs first row and first column to be filled with 0 + var matrix = [[Int]](count:self.characters.count+1, repeatedValue:[Int](count:other.characters.count+1, repeatedValue:0)) + + for (i, selfChar) in self.characters.enumerate() { + for (j, otherChar) in other.characters.enumerate() { + if (otherChar == selfChar) { + //Common char found, add 1 to highest lcs found so far + matrix[i+1][j+1] = (matrix[i][j]) + 1 + } + else { + //Not a match, propagates highest lcs length found so far + matrix[i+1][j+1] = max(matrix[i][j+1], matrix[i+1][j]) + } + } + } + + //Due to propagation, lcs length is at matrix[n][m] + return matrix; + } + + //Backtracks from matrix[n][m] to matrix[1][1] looking for chars that are common to both strings + func backtrack(matrix: [[Int]]) -> String { + var i = self.characters.count + var j = other.characters.count + + //charInSequence is in sync with i so we can get self[i] + var charInSequence = self.endIndex + + var lcs = String() + + while (i >= 1 && j >= 1) { + //Indicates propagation without change, i.e. no new char was added to lcs + if (matrix[i][j] == matrix[i][j - 1]) { + j = j - 1 + } + //Indicates propagation without change, i.e. no new char was added to lcs + else if (matrix[i][j] == matrix[i - 1][j]) { + i = i - 1 + //As i was subtracted, move back charInSequence + charInSequence = charInSequence.predecessor() + } + //Value on the left and above are different than current cell. This means 1 was added to lcs length (line 16) + else { + i = i - 1 + j = j - 1 + charInSequence = charInSequence.predecessor() + + lcs.append(self[charInSequence]) + } + } + + //Due to backtrack, chars were added in reverse order: reverse it back. + //Append and reverse is faster than inserting at index 0 + return String(lcs.characters.reverse()); + } + + //Combine dynamic programming approach with backtrack to find the lcs + return backtrack(lcsLength(other)) + } +} \ No newline at end of file From 1a075f3a636d96977c7719d4ec7d5a918cbb3782 Mon Sep 17 00:00:00 2001 From: Pedro Vereza Date: Sat, 12 Mar 2016 17:27:14 -0300 Subject: [PATCH 0133/1679] Adds tests for LCS --- .../Tests/LongestCommonSubsquenceTests.swift | 32 +++ .../Tests/Tests.xcodeproj/project.pbxproj | 257 ++++++++++++++++++ .../xcshareddata/xcschemes/Tests.xcscheme | 90 ++++++ .../Tests/Tests/Info.plist | 24 ++ 4 files changed, 403 insertions(+) create mode 100644 Longest Common Subsequence/Tests/LongestCommonSubsquenceTests.swift create mode 100644 Longest Common Subsequence/Tests/Tests.xcodeproj/project.pbxproj create mode 100644 Longest Common Subsequence/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme create mode 100644 Longest Common Subsequence/Tests/Tests/Info.plist diff --git a/Longest Common Subsequence/Tests/LongestCommonSubsquenceTests.swift b/Longest Common Subsequence/Tests/LongestCommonSubsquenceTests.swift new file mode 100644 index 000000000..75859ca1a --- /dev/null +++ b/Longest Common Subsequence/Tests/LongestCommonSubsquenceTests.swift @@ -0,0 +1,32 @@ +import Foundation +import XCTest + +class LongestCommonSubsquenceTests: XCTestCase { + + func testLCSwithSelfIsSelf() { + let a = "ABCDE" + + XCTAssertEqual(a, a.longestCommonSubsequence(a)) + } + + func testLCSWithEmptyStringIsEmptyString() { + let a = "ABCDE" + + XCTAssertEqual("", a.longestCommonSubsequence("")) + } + + func testLCSIsEmptyWhenNoCharMatches() { + let a = "ABCDE" + let b = "WXYZ" + + XCTAssertEqual("", a.longestCommonSubsequence(b)) + } + + func testLCSIsNotCommutative() { + let a = "ABCDEF" + let b = "XAWDMVBEKD" + + XCTAssertEqual("ADE", a.longestCommonSubsequence(b)) + XCTAssertEqual("ABD", b.longestCommonSubsequence(a)) + } +} diff --git a/Longest Common Subsequence/Tests/Tests.xcodeproj/project.pbxproj b/Longest Common Subsequence/Tests/Tests.xcodeproj/project.pbxproj new file mode 100644 index 000000000..39422654f --- /dev/null +++ b/Longest Common Subsequence/Tests/Tests.xcodeproj/project.pbxproj @@ -0,0 +1,257 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 4716C7AF1C93751E00F6C1C0 /* LongestCommonSubsquenceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4716C7891C936E0E00F6C1C0 /* LongestCommonSubsquenceTests.swift */; }; + 4716C7B01C93751E00F6C1C0 /* LongestCommonSubsequence.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4716C7881C936DDD00F6C1C0 /* LongestCommonSubsequence.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 4716C7881C936DDD00F6C1C0 /* LongestCommonSubsequence.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = LongestCommonSubsequence.swift; path = ../../LongestCommonSubsequence.swift; sourceTree = ""; }; + 4716C7891C936E0E00F6C1C0 /* LongestCommonSubsquenceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = LongestCommonSubsquenceTests.swift; path = ../LongestCommonSubsquenceTests.swift; sourceTree = ""; }; + 4716C7A71C93750500F6C1C0 /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 4716C7AB1C93750500F6C1C0 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 4716C7A41C93750500F6C1C0 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 4716C7811C936DCB00F6C1C0 = { + isa = PBXGroup; + children = ( + 4716C7A81C93750500F6C1C0 /* Tests */, + 4716C78F1C93746D00F6C1C0 /* Products */, + ); + sourceTree = ""; + }; + 4716C78F1C93746D00F6C1C0 /* Products */ = { + isa = PBXGroup; + children = ( + 4716C7A71C93750500F6C1C0 /* Tests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 4716C7A81C93750500F6C1C0 /* Tests */ = { + isa = PBXGroup; + children = ( + 4716C7891C936E0E00F6C1C0 /* LongestCommonSubsquenceTests.swift */, + 4716C7881C936DDD00F6C1C0 /* LongestCommonSubsequence.swift */, + 4716C7AB1C93750500F6C1C0 /* Info.plist */, + ); + path = Tests; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 4716C7A61C93750500F6C1C0 /* Tests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4716C7AC1C93750500F6C1C0 /* Build configuration list for PBXNativeTarget "Tests" */; + buildPhases = ( + 4716C7A31C93750500F6C1C0 /* Sources */, + 4716C7A41C93750500F6C1C0 /* Frameworks */, + 4716C7A51C93750500F6C1C0 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Tests; + productName = Tests; + productReference = 4716C7A71C93750500F6C1C0 /* Tests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 4716C7821C936DCB00F6C1C0 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0720; + LastUpgradeCheck = 0720; + TargetAttributes = { + 4716C7A61C93750500F6C1C0 = { + CreatedOnToolsVersion = 7.2.1; + }; + }; + }; + buildConfigurationList = 4716C7851C936DCB00F6C1C0 /* Build configuration list for PBXProject "Tests" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 4716C7811C936DCB00F6C1C0; + productRefGroup = 4716C78F1C93746D00F6C1C0 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 4716C7A61C93750500F6C1C0 /* Tests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 4716C7A51C93750500F6C1C0 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 4716C7A31C93750500F6C1C0 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4716C7AF1C93751E00F6C1C0 /* LongestCommonSubsquenceTests.swift in Sources */, + 4716C7B01C93751E00F6C1C0 /* LongestCommonSubsequence.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 4716C7861C936DCB00F6C1C0 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + }; + name = Debug; + }; + 4716C7871C936DCB00F6C1C0 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + }; + name = Release; + }; + 4716C7AD1C93750500F6C1C0 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + INFOPLIST_FILE = Tests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.10; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_BUNDLE_IDENTIFIER = me.pedrovereza.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 4716C7AE1C93750500F6C1C0 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + INFOPLIST_FILE = Tests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.10; + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_BUNDLE_IDENTIFIER = me.pedrovereza.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 4716C7851C936DCB00F6C1C0 /* Build configuration list for PBXProject "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4716C7861C936DCB00F6C1C0 /* Debug */, + 4716C7871C936DCB00F6C1C0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4716C7AC1C93750500F6C1C0 /* Build configuration list for PBXNativeTarget "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4716C7AD1C93750500F6C1C0 /* Debug */, + 4716C7AE1C93750500F6C1C0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + }; +/* End XCConfigurationList section */ + }; + rootObject = 4716C7821C936DCB00F6C1C0 /* Project object */; +} diff --git a/Longest Common Subsequence/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Longest Common Subsequence/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme new file mode 100644 index 000000000..19caeb2ad --- /dev/null +++ b/Longest Common Subsequence/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -0,0 +1,90 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Longest Common Subsequence/Tests/Tests/Info.plist b/Longest Common Subsequence/Tests/Tests/Info.plist new file mode 100644 index 000000000..ba72822e8 --- /dev/null +++ b/Longest Common Subsequence/Tests/Tests/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + From 6832500b62dba4676c2beffd3451f00827acd033 Mon Sep 17 00:00:00 2001 From: Pedro Vereza Date: Sat, 12 Mar 2016 17:47:51 -0300 Subject: [PATCH 0134/1679] Adds README for LCS --- Longest Common Subsequence/README.markdown | 211 +++++++++++++++++++++ 1 file changed, 211 insertions(+) create mode 100644 Longest Common Subsequence/README.markdown diff --git a/Longest Common Subsequence/README.markdown b/Longest Common Subsequence/README.markdown new file mode 100644 index 000000000..719135a54 --- /dev/null +++ b/Longest Common Subsequence/README.markdown @@ -0,0 +1,211 @@ +# Longest Common Subsequence + + +The Longest Common Subsequence (LCS) of two strings is the longest sequence of characters that appear in the same order in both strings. Should not be confused with the Longest Common Substring problem, where characters **must** be a substring of both strings (i.e they have to be immediate neighbours). + +One way to find what's the LCS of two strings `a` and `b` is using Dynamic Programming and a backtracking strategy. During the explanation, remember that `n` is the length of `a` and `m` the length of `b`. + +## Length of LCS - Dynamic Programming + +Dynamic programming is used to determine the length of LCS between all combinations of substrings of `a` and `b`. + + +```swift + // Computes the length of the lcs using dynamic programming + // Output is a matrix of size (n+1)x(m+1), where matrix[x][y] indicates the length + // of lcs between substring (0, x-1) of self and substring (0, y-1) of other. + func lcsLength(other: String) -> [[Int]] { + + //Matrix of size (n+1)x(m+1), algorithm needs first row and first line to be filled with 0 + var matrix = [[Int]](count:self.characters.count+1, repeatedValue:[Int](count:other.characters.count+1, repeatedValue:0)) + + for (i, selfChar) in self.characters.enumerate() { + for (j, otherChar) in other.characters.enumerate() { + if (otherChar == selfChar) { + //Common char found, add 1 to highest lcs found so far + matrix[i+1][j+1] = (matrix[i][j]) + 1 + } + else { + //Not a match, propagates highest lcs length found so far + matrix[i+1][j+1] = max(matrix[i][j+1], matrix[i+1][j]) + } + } + } + + //Due to propagation, lcs length is at matrix[n][m] + return matrix; + } +``` + +Given strings `"ABCBX"` and `"ABDCAB"` the output matrix of `lcsLength` is the following: + +*First row and column added for easier understanding, actual matrix starts on zeros* + +``` +| | Ø | A | B | D | C | A | B | +| Ø | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| A | 0 | 1 | 1 | 1 | 1 | 1 | 1 | +| B | 0 | 1 | 2 | 2 | 2 | 2 | 2 | +| C | 0 | 1 | 2 | 2 | 3 | 3 | 3 | +| B | 0 | 1 | 2 | 2 | 3 | 3 | 4 | +| X | 0 | 1 | 2 | 2 | 3 | 3 | 4 | +``` + +The content of the matrix indicates that position `(i, j)` contains the length of the LCS between substring `(0, i - 1)` of `a` and substring `(0, j - 1)` of `b`. + +Example: `(2, 3)` says that the LCS for `"AB"` and `"ABD"` is 2 + + +## Actual LCS - Backtrack + +Having the length of every combination makes it possible to determine *which* characters are part of the LCS itself by using a backtracking strategy. + +Backtrack starts at matrix[n + 1][m + 1] and *walks* up and left (in this priority) looking for changes that do not indicate a simple propagation. If the number on the left and above are different than the number in the current cell, no propagation happened, it means that `(i, j)` indicates a common char between `a` and `b`, so char at `a[i - 1]` and `b[j - 1]` are part of the LCS and should be stored in the returned value (`self[i - 1]` was used in the code but could be `other[j - 1]`). + +``` +| | Ø| A| B| D| C| A| B| +| Ø | 0| 0| 0| 0| 0| 0| 0| +| A | 0|↖ 1| 1| 1| 1| 1| 1| +| B | 0| 1|↖ 2|← 2| 2| 2| 2| +| C | 0| 1| 2| 2|↖ 3|← 3| 3| +| B | 0| 1| 2| 2| 3| 3|↖ 4| +| X | 0| 1| 2| 2| 3| 3|↑ 4| +``` +Each `↖` move indicates a character (in row/column header) that is part of the LCS. + +One thing to notice is, as it's running backwards, the LCS is built in reverse order. Before returning, the result is reversed to reflect the actual LCS. + + + +```swift + //Backtracks from matrix[n][m] to matrix[1][1] looking for chars that are common to both strings + func backtrack(matrix: [[Int]]) -> String { + var i = self.characters.count + var j = other.characters.count + + //charInSequence is in sync with i so we can get self[i] + var charInSequence = self.endIndex + + var lcs = String() + + while (i >= 1 && j >= 1) { + //Indicates propagation without change, i.e. no new char was added to lcs + if (matrix[i][j] == matrix[i][j - 1]) { + j = j - 1 + } + //Indicates propagation without change, i.e. no new char was added to lcs + else if (matrix[i][j] == matrix[i - 1][j]) { + i = i - 1 + //As i was subtracted, move back charInSequence + charInSequence = charInSequence.predecessor() + } + //Value on the left and above are different than current cell. This means 1 was added to lcs length (line 16) + else { + i = i - 1 + j = j - 1 + charInSequence = charInSequence.predecessor() + + lcs.append(self[charInSequence]) + } + } + + //Due to backtrack, chars were added in reverse order: reverse it back. + //Append and reverse is faster than inserting at index 0 + return String(lcs.characters.reverse()); + } + +``` + + + + +## Putting it all together + + +```swift +extension String { + func longestCommonSubsequence(other:String) -> String { + + // Computes the same of the lcs using dynamic programming + // Output is a matrix of size (n+1)x(m+1), where matrix[x][y] indicates the length + // of lcs between substring (0, x-1) of self and substring (0, y-1) of other. + func lcsLength(other: String) -> [[Int]] { + + //Matrix of size (n+1)x(m+1), algorithm needs first row and first line to be filled with 0 + var matrix = [[Int]](count:self.characters.count+1, repeatedValue:[Int](count:other.characters.count+1, repeatedValue:0)) + + for (i, selfChar) in self.characters.enumerate() { + for (j, otherChar) in other.characters.enumerate() { + if (otherChar == selfChar) { + //Common char found, add 1 to highest lcs found so far + matrix[i+1][j+1] = (matrix[i][j]) + 1 + } + else { + //Not a match, propagates highest lcs length found so far + matrix[i+1][j+1] = max(matrix[i][j+1], matrix[i+1][j]) + } + } + } + + //Due to propagation, lcs length is at matrix[n][m] + return matrix; + } + + //Backtracks from matrix[n][m] to matrix[1][1] looking for chars that are common to both strings + func backtrack(matrix: [[Int]]) -> String { + var i = self.characters.count + var j = other.characters.count + + //charInSequence is in sync with i so we can get self[i] + var charInSequence = self.endIndex + + var lcs = String() + + while (i >= 1 && j >= 1) { + //Indicates propagation without change, i.e. no new char was added to lcs + if (matrix[i][j] == matrix[i][j - 1]) { + j = j - 1 + } + //Indicates propagation without change, i.e. no new char was added to lcs + else if (matrix[i][j] == matrix[i - 1][j]) { + i = i - 1 + //As i was subtracted, move back charInSequence + charInSequence = charInSequence.predecessor() + } + //Value on the left and above are different than current cell. This means 1 was added to lcs length (line 16) + else { + i = i - 1 + j = j - 1 + charInSequence = charInSequence.predecessor() + + lcs.append(self[charInSequence]) + } + } + + //Due to backtrack, chars were added in reverse order: reverse it back. + //Append and reverse is faster than inserting at index 0 + return String(lcs.characters.reverse()); + } + + //Combine dynamic programming approach with backtrack to find the lcs + return backtrack(lcsLength(other)) + } +} +``` + +**Examples:** + +```swift +let a = "ABCBX" +let b = "ABDCAB" +let c = "KLMK" + +a.longestCommonSubsequence(c) //"" +a.longestCommonSubsequence("") //"" +a.longestCommonSubsequence(b) //"ABCB" +b.longestCommonSubsequence(a) //"ABCB" +a.longestCommonSubsequence(a) // "ABCBX" +``` + + +*Written for Swift Algorithm Club by Pedro Vereza* \ No newline at end of file From a5440104ba5008b3105f0f0208bad28b84e95c8e Mon Sep 17 00:00:00 2001 From: Pedro Vereza Date: Sat, 12 Mar 2016 17:49:32 -0300 Subject: [PATCH 0135/1679] Adds LCS tests on travis --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 9a4806998..3a2bcb7b2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -22,3 +22,4 @@ script: - xcodebuild test -project ./Selection\ Sort/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Shell\ Sort/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Stack/Tests/Tests.xcodeproj -scheme Tests +- xcodebuild test -project ./Longest\ Common\ Subsequence/Tests/Tests.xcodeproj -scheme Tests From d344becbfbfb054269148cc23261306c337c246a Mon Sep 17 00:00:00 2001 From: Matteo Piombo Date: Sun, 13 Mar 2016 10:15:58 +0100 Subject: [PATCH 0136/1679] Introduce Associated Labels to centroids. This could help showing how to use KMeans as a classifier. Some changes to KMeans properties and function. Updated Tests accordingly. Demo the usage of labels in one small test. --- K-Means/KMeans.swift | 58 ++++++++++++------- K-Means/Tests/KMeansTests.swift | 45 ++++++++------ K-Means/Tests/Tests.xcodeproj/project.pbxproj | 2 +- 3 files changed, 67 insertions(+), 38 deletions(-) diff --git a/K-Means/KMeans.swift b/K-Means/KMeans.swift index 9073b7b46..245a93b4a 100644 --- a/K-Means/KMeans.swift +++ b/K-Means/KMeans.swift @@ -5,21 +5,24 @@ import Foundation -class KMeans { +class KMeans { let numCenters: Int - let convergeDist: Double + let labels: Array

LC}f4Aau+dni%PMJ3m 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 z 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 diff --git a/Topological Sort/Images/graph_example.png b/Topological Sort/Images/graph_example.png deleted file mode 100644 index 22b8271d4effeba1062fb2f22c29259ad0b0a141..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 114041 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�jn9rfnW)8Hau_>k!(Oje3< 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 **Note:** This is not the only possible topological sort for this graph. For example, other valid solutions are **3, 7, 5, 10, 8, 11, 9, 2** and **3, 7, 5, 8, 11, 2, 9, 10**. Any order where all the arrows are going from left to right will do. + +## The code + +Here is how you could implement topological sort in Swift (see also [TopologicalSort1.swift](TopologicalSort1.swift)): + +```swift +extension Graph { + public func topologicalSort() -> [Node] { + // 1 + let startNodes = calculateInDegreeOfNodes().filter({ _, indegree in + return indegree == 0 + }).map({ node, indegree in + return node + }) + + // 2 + var visited = [Node : Bool]() + for (node, _) in adjacencyLists { + visited[node] = false + } + + // 3 + var result = [Node]() + for startNode in startNodes { + result = depthFirstSearch(startNode, visited: &visited) + result + } + + // 4 + return result + } +} +``` + +Some remarks: + +1. Find the in-degree of each vertex and put all the vertices with in-degree 0 in the `startNodes` array. In this graph implementation, vertices are called "nodes". Both terms are used interchangeably by people who write graph code. + +2. The `visited` array keeps track of whether we've already seen a vertex during the depth-first search. Initially, we set all elements to `false`. + +3. For each of the vertices in the `startNodes` array, perform a depth-first search. This returns an array of `Node` objects. We prepend that array to our own `result` array. + +4. The `result` array contains all the vertices in topologically sorted order. -## Alternative algorithm +## Alternative method (Kahn's algorithm) Even though depth-first search is the typical way to perform a topological sort, there is another algorithm that also does the job. @@ -82,6 +138,6 @@ Even though depth-first search is the typical way to perform a topological sort, This is an **O(n + m)** algorithm where **n** is the number of vertices and **m** is the number of edges. You can see the implementation in [TopologicalSort2.swift](TopologicalSort2.swift). -I first read about this algorithm in the Algorithm Alley column in Dr. Dobb's Magazine from May 1993. +Source: I first read about this alternative algorithm in the Algorithm Alley column in Dr. Dobb's Magazine from May 1993. *Written for Swift Algorithm Club by Ali Hafizji and Matthijs Hollemans* diff --git a/Topological Sort/Stack.swift b/Topological Sort/Stack.swift deleted file mode 100644 index 7f4aadc8b..000000000 --- a/Topological Sort/Stack.swift +++ /dev/null @@ -1,27 +0,0 @@ -public struct Stack { - private var array = [T]() - - public var isEmpty: Bool { - return array.isEmpty - } - - public var count: Int { - return array.count - } - - public mutating func push(element: T) { - array.append(element) - } - - public mutating func pop() -> T? { - if isEmpty { - return nil - } else { - return array.removeLast() - } - } - - public func peek() -> T? { - return array.last - } -} diff --git a/Topological Sort/Tests/Tests.xcodeproj/project.pbxproj b/Topological Sort/Tests/Tests.xcodeproj/project.pbxproj index cb32961df..83c59dbab 100644 --- a/Topological Sort/Tests/Tests.xcodeproj/project.pbxproj +++ b/Topological Sort/Tests/Tests.xcodeproj/project.pbxproj @@ -9,9 +9,9 @@ /* Begin PBXBuildFile section */ 7B3471BB1C8F50CF008381CD /* TopologicalSortTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B3471BA1C8F50CF008381CD /* TopologicalSortTests.swift */; }; 7B3471BF1C8F50DD008381CD /* Graph.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B3471BC1C8F50DD008381CD /* Graph.swift */; }; - 7B3471C01C8F50DD008381CD /* Stack.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B3471BD1C8F50DD008381CD /* Stack.swift */; }; 7B3471C11C8F50DD008381CD /* TopologicalSort1.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B3471BE1C8F50DD008381CD /* TopologicalSort1.swift */; }; 7B3471C31C8F5348008381CD /* TopologicalSort2.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B3471C21C8F5348008381CD /* TopologicalSort2.swift */; }; + 7BE143491C9C6A93001BC747 /* TopologicalSort3.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BE143481C9C6A93001BC747 /* TopologicalSort3.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -19,9 +19,9 @@ 7B2BBC941C779E7B0067B71D /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; 7B3471BA1C8F50CF008381CD /* TopologicalSortTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TopologicalSortTests.swift; sourceTree = SOURCE_ROOT; }; 7B3471BC1C8F50DD008381CD /* Graph.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Graph.swift; path = ../Graph.swift; sourceTree = SOURCE_ROOT; }; - 7B3471BD1C8F50DD008381CD /* Stack.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Stack.swift; path = ../Stack.swift; sourceTree = SOURCE_ROOT; }; 7B3471BE1C8F50DD008381CD /* TopologicalSort1.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = TopologicalSort1.swift; path = ../TopologicalSort1.swift; sourceTree = SOURCE_ROOT; }; 7B3471C21C8F5348008381CD /* TopologicalSort2.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = TopologicalSort2.swift; path = ../TopologicalSort2.swift; sourceTree = SOURCE_ROOT; }; + 7BE143481C9C6A93001BC747 /* TopologicalSort3.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = TopologicalSort3.swift; path = ../TopologicalSort3.swift; sourceTree = SOURCE_ROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -55,9 +55,9 @@ isa = PBXGroup; children = ( 7B3471BC1C8F50DD008381CD /* Graph.swift */, - 7B3471BD1C8F50DD008381CD /* Stack.swift */, 7B3471BE1C8F50DD008381CD /* TopologicalSort1.swift */, 7B3471C21C8F5348008381CD /* TopologicalSort2.swift */, + 7BE143481C9C6A93001BC747 /* TopologicalSort3.swift */, 7B3471BA1C8F50CF008381CD /* TopologicalSortTests.swift */, 7B2BBC941C779E7B0067B71D /* Info.plist */, ); @@ -135,9 +135,9 @@ files = ( 7B3471C31C8F5348008381CD /* TopologicalSort2.swift in Sources */, 7B3471BF1C8F50DD008381CD /* Graph.swift in Sources */, - 7B3471C01C8F50DD008381CD /* Stack.swift in Sources */, 7B3471BB1C8F50CF008381CD /* TopologicalSortTests.swift in Sources */, 7B3471C11C8F50DD008381CD /* TopologicalSort1.swift in Sources */, + 7BE143491C9C6A93001BC747 /* TopologicalSort3.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Topological Sort/Tests/TopologicalSortTests.swift b/Topological Sort/Tests/TopologicalSortTests.swift index 4d4178cfb..bc4dd7f60 100644 --- a/Topological Sort/Tests/TopologicalSortTests.swift +++ b/Topological Sort/Tests/TopologicalSortTests.swift @@ -40,44 +40,51 @@ class TopologicalSort: XCTestCase { graph.addEdge(fromNode: node11, toNode: node10) graph.addEdge(fromNode: node8, toNode: node9) - XCTAssertEqual(graph.topologicalSort(), ["3", "8", "9", "10", "7", "11", "2", "5"]) - XCTAssertEqual(graph.topologicalSort2(), ["3", "7", "5", "8", "11", "2", "9", "10"]) + XCTAssertEqual(graph.topologicalSort(), ["5", "7", "11", "2", "3", "8", "9", "10"]) + XCTAssertEqual(graph.topologicalSortKahn(), ["3", "7", "5", "8", "11", "2", "9", "10"]) + XCTAssertEqual(graph.topologicalSortAlternative(), ["5", "7", "3", "8", "11", "10", "9", "2"]) } func testTopologicalSortEdgeLists() { let p1 = ["A B", "A C", "B C", "B D", "C E", "C F", "E D", "F E", "G A", "G F"] - let a1 = ["G", "A", "B", "C", "F", "E", "D"] // TODO - let s1 = ["G", "A", "B", "C", "F", "E", "D"] + let s1 = ["G", "A", "B", "C", "E", "D", "F"] + let a1 = ["G", "A", "B", "C", "F", "E", "D"] + let k1 = ["G", "A", "B", "C", "F", "E", "D"] let p2 = ["B C", "C D", "C G", "B F", "D G", "G E", "F G", "F G"] - let a2 = ["B", "C", "F", "D", "G", "E"] // TODO - let s2 = ["B", "C", "F", "D", "G", "E"] + let s2 = ["B", "C", "D", "G", "E", "F"] + let a2 = ["B", "C", "F", "D", "G", "E"] + let k2 = ["B", "F", "C", "D", "G", "E"] let p3 = ["S V", "S W", "V T", "W T"] - let a3 = ["S", "V", "W", "T"] // TODO let s3 = ["S", "V", "W", "T"] + let a3 = ["S", "V", "W", "T"] + let k3 = ["S", "V", "W", "T"] let p4 = ["5 11", "7 11", "7 8", "3 8", "3 10", "11 2", "11 9", "11 10", "8 9"] - let a4 = ["3", "8", "9", "10", "7", "11", "2", "5"] - let s4 = ["3", "7", "5", "8", "11", "2", "9", "10"] + let s4 = ["5", "7", "11", "2", "3", "8", "9", "10"] + let a4 = ["3", "7", "5", "8", "11", "2", "9", "10"] + let k4 = ["5", "7", "3", "8", "11", "10", "9", "2"] let data = [ - (p1, a1, s1), - (p2, a2, s2), - (p3, a3, s3), - (p4, a4, s4), + (p1, s1, a1, k1), + (p2, s2, a2, k2), + (p3, s3, a3, k3), + (p4, s4, a4, k4), ] for d in data { let graph = Graph() graph.loadEdgeList(d.0) - // TODO: this fails the tests - //let sorted1 = graph.topologicalSort() - //XCTAssertEqual(sorted1, d.1) + let sorted1 = graph.topologicalSort() + XCTAssertEqual(sorted1, d.1) - let sorted2 = graph.topologicalSort2() + let sorted2 = graph.topologicalSortKahn() XCTAssertEqual(sorted2, d.2) + + let sorted3 = graph.topologicalSortAlternative() + XCTAssertEqual(sorted3, d.3) } } } diff --git a/Topological Sort/Topological Sort.playground/Contents.swift b/Topological Sort/Topological Sort.playground/Contents.swift index d1a92abbc..d0ebe550d 100644 --- a/Topological Sort/Topological Sort.playground/Contents.swift +++ b/Topological Sort/Topological Sort.playground/Contents.swift @@ -28,5 +28,8 @@ graph.addEdge(fromNode: node8, toNode: node9) // using depth-first search graph.topologicalSort() -// alternative method -graph.topologicalSort2() +// also using depth-first search +graph.topologicalSortAlternative() + +// Kahn's algorithm +graph.topologicalSortKahn() diff --git a/Topological Sort/Topological Sort.playground/Sources/Graph.swift b/Topological Sort/Topological Sort.playground/Sources/Graph.swift index fca7485e8..7fbadb6ce 100644 --- a/Topological Sort/Topological Sort.playground/Sources/Graph.swift +++ b/Topological Sort/Topological Sort.playground/Sources/Graph.swift @@ -30,3 +30,22 @@ public class Graph: CustomStringConvertible { return nil } } + +extension Graph { + typealias InDegree = Int + + func calculateInDegreeOfNodes() -> [Node : InDegree] { + var inDegrees = [Node : InDegree]() + + for (node, _) in adjacencyLists { + inDegrees[node] = 0 + } + + for (_, adjacencyList) in adjacencyLists { + for nodeInList in adjacencyList { + inDegrees[nodeInList] = (inDegrees[nodeInList] ?? 0) + 1 + } + } + return inDegrees + } +} diff --git a/Topological Sort/Topological Sort.playground/Sources/Stack.swift b/Topological Sort/Topological Sort.playground/Sources/Stack.swift deleted file mode 100644 index 7f4aadc8b..000000000 --- a/Topological Sort/Topological Sort.playground/Sources/Stack.swift +++ /dev/null @@ -1,27 +0,0 @@ -public struct Stack { - private var array = [T]() - - public var isEmpty: Bool { - return array.isEmpty - } - - public var count: Int { - return array.count - } - - public mutating func push(element: T) { - array.append(element) - } - - public mutating func pop() -> T? { - if isEmpty { - return nil - } else { - return array.removeLast() - } - } - - public func peek() -> T? { - return array.last - } -} diff --git a/Topological Sort/Topological Sort.playground/Sources/TopologicalSort1.swift b/Topological Sort/Topological Sort.playground/Sources/TopologicalSort1.swift index 011c4164b..a6051a4bf 100644 --- a/Topological Sort/Topological Sort.playground/Sources/TopologicalSort1.swift +++ b/Topological Sort/Topological Sort.playground/Sources/TopologicalSort1.swift @@ -1,53 +1,35 @@ extension Graph { - typealias InDegree = Int - - func calculateInDegreeOfNodes() -> [Node : InDegree] { - var inDegrees = [Node : InDegree]() - - for (node, _) in adjacencyLists { - inDegrees[node] = 0 - } - - for (_, adjacencyList) in adjacencyLists { - for nodeInList in adjacencyList { - inDegrees[nodeInList] = (inDegrees[nodeInList] ?? 0) + 1 - } - } - return inDegrees - } - private func depthFirstSearch(source: Node, inout visited: [Node : Bool]) -> [Node] { var result = [source] visited[source] = true if let adjacencyList = adjacencyList(forNode: source) { for nodeInAdjacencyList in adjacencyList { - if !(visited[nodeInAdjacencyList] ?? false) { - result += (depthFirstSearch(nodeInAdjacencyList, visited: &visited)) + if let seen = visited[nodeInAdjacencyList] where !seen { + result += depthFirstSearch(nodeInAdjacencyList, visited: &visited) } } } return result } + /* Topological sort using depth-first search. */ public func topologicalSort() -> [Node] { - let startNodes = calculateInDegreeOfNodes().filter({(_, indegree) in + let startNodes = calculateInDegreeOfNodes().filter({ _, indegree in return indegree == 0 - }).map({(node, indegree) in + }).map({ node, indegree in return node }) var visited = [Node : Bool]() - for (node, _) in adjacencyLists { visited[node] = false } var result = [Node]() - for startNode in startNodes { - result += depthFirstSearch(startNode, visited: &visited) + result = depthFirstSearch(startNode, visited: &visited) + result } return result diff --git a/Topological Sort/Topological Sort.playground/Sources/TopologicalSort2.swift b/Topological Sort/Topological Sort.playground/Sources/TopologicalSort2.swift index 468e098df..f4c1cdd6f 100644 --- a/Topological Sort/Topological Sort.playground/Sources/TopologicalSort2.swift +++ b/Topological Sort/Topological Sort.playground/Sources/TopologicalSort2.swift @@ -1,6 +1,6 @@ extension Graph { - /* Topological sort that does not use a depth-first search. */ - public func topologicalSort2() -> [Node] { + /* Topological sort using Kahn's algorithm. */ + public func topologicalSortKahn() -> [Node] { var nodes = calculateInDegreeOfNodes() // Find vertices with no predecessors and puts them into a new list. diff --git a/Topological Sort/Topological Sort.playground/Sources/TopologicalSort3.swift b/Topological Sort/Topological Sort.playground/Sources/TopologicalSort3.swift new file mode 100644 index 000000000..24a6189fa --- /dev/null +++ b/Topological Sort/Topological Sort.playground/Sources/TopologicalSort3.swift @@ -0,0 +1,35 @@ +/* + An alternative implementation of topological sort using depth-first search. + This does not start at vertices with in-degree 0 but simply at the first one + it finds. It uses a stack to build up the sorted list, but in reverse order. +*/ +extension Graph { + public func topologicalSortAlternative() -> [Node] { + var stack = [Node]() + + var visited = [Node: Bool]() + for (node, _) in adjacencyLists { + visited[node] = false + } + + func depthFirstSearch(source: Node) { + if let adjacencyList = adjacencyList(forNode: source) { + for neighbor in adjacencyList { + if let seen = visited[neighbor] where !seen { + depthFirstSearch(neighbor) + } + } + } + stack.append(source) + visited[source] = true + } + + for (node, _) in visited { + if let seen = visited[node] where !seen { + depthFirstSearch(node) + } + } + + return stack.reverse() + } +} diff --git a/Topological Sort/TopologicalSort1.swift b/Topological Sort/TopologicalSort1.swift index 500b8ca11..a6051a4bf 100644 --- a/Topological Sort/TopologicalSort1.swift +++ b/Topological Sort/TopologicalSort1.swift @@ -1,55 +1,37 @@ extension Graph { - typealias InDegree = Int - - func calculateInDegreeOfNodes() -> [Node : InDegree] { - var inDegrees = [Node : InDegree]() - - for (node, _) in adjacencyLists { - inDegrees[node] = 0 - } - - for (_, adjacencyList) in adjacencyLists { - for nodeInList in adjacencyList { - inDegrees[nodeInList] = (inDegrees[nodeInList] ?? 0) + 1 - } - } - return inDegrees - } - private func depthFirstSearch(source: Node, inout visited: [Node : Bool]) -> [Node] { var result = [source] visited[source] = true if let adjacencyList = adjacencyList(forNode: source) { for nodeInAdjacencyList in adjacencyList { - if !(visited[nodeInAdjacencyList] ?? false) { - result += (depthFirstSearch(nodeInAdjacencyList, visited: &visited)) + if let seen = visited[nodeInAdjacencyList] where !seen { + result += depthFirstSearch(nodeInAdjacencyList, visited: &visited) } } } return result } + /* Topological sort using depth-first search. */ public func topologicalSort() -> [Node] { - let startNodes = calculateInDegreeOfNodes().filter({(_, indegree) in + let startNodes = calculateInDegreeOfNodes().filter({ _, indegree in return indegree == 0 - }).map({(node, indegree) in + }).map({ node, indegree in return node }) var visited = [Node : Bool]() - for (node, _) in adjacencyLists { visited[node] = false } var result = [Node]() - for startNode in startNodes { - result += depthFirstSearch(startNode, visited: &visited) + result = depthFirstSearch(startNode, visited: &visited) + result } - + return result } } diff --git a/Topological Sort/TopologicalSort2.swift b/Topological Sort/TopologicalSort2.swift index 468e098df..f4c1cdd6f 100644 --- a/Topological Sort/TopologicalSort2.swift +++ b/Topological Sort/TopologicalSort2.swift @@ -1,6 +1,6 @@ extension Graph { - /* Topological sort that does not use a depth-first search. */ - public func topologicalSort2() -> [Node] { + /* Topological sort using Kahn's algorithm. */ + public func topologicalSortKahn() -> [Node] { var nodes = calculateInDegreeOfNodes() // Find vertices with no predecessors and puts them into a new list. diff --git a/Topological Sort/TopologicalSort3.swift b/Topological Sort/TopologicalSort3.swift new file mode 100644 index 000000000..24a6189fa --- /dev/null +++ b/Topological Sort/TopologicalSort3.swift @@ -0,0 +1,35 @@ +/* + An alternative implementation of topological sort using depth-first search. + This does not start at vertices with in-degree 0 but simply at the first one + it finds. It uses a stack to build up the sorted list, but in reverse order. +*/ +extension Graph { + public func topologicalSortAlternative() -> [Node] { + var stack = [Node]() + + var visited = [Node: Bool]() + for (node, _) in adjacencyLists { + visited[node] = false + } + + func depthFirstSearch(source: Node) { + if let adjacencyList = adjacencyList(forNode: source) { + for neighbor in adjacencyList { + if let seen = visited[neighbor] where !seen { + depthFirstSearch(neighbor) + } + } + } + stack.append(source) + visited[source] = true + } + + for (node, _) in visited { + if let seen = visited[node] where !seen { + depthFirstSearch(node) + } + } + + return stack.reverse() + } +} From 160522b4528cd4a536ed1e593f0c862903f17377 Mon Sep 17 00:00:00 2001 From: Matthijs Hollemans Date: Fri, 18 Mar 2016 19:35:11 +0100 Subject: [PATCH 0162/1679] Fix error in depth-first search Results were added in the wrong order inside the DFS too. Unit tests now use a function to check whether the result is a valid topological sort. --- Topological Sort/README.markdown | 16 ++++--- .../Tests/TopologicalSortTests.swift | 44 ++++++++----------- .../Sources/TopologicalSort1.swift | 11 ++--- Topological Sort/TopologicalSort1.swift | 9 ++-- 4 files changed, 38 insertions(+), 42 deletions(-) diff --git a/Topological Sort/README.markdown b/Topological Sort/README.markdown index c92072539..4429a0754 100644 --- a/Topological Sort/README.markdown +++ b/Topological Sort/README.markdown @@ -28,7 +28,7 @@ If we were to represent these objectives in the form of a graph it would look as ![Example](Images/Algorithms.png) -If we consider each algorithm to be a vertex in the graph you can clearly see the dependencies between them. To learn something you might have to know something else first. This is exactly what topological sort is used for -- it will sort things out such that you know what to do first. +If we consider each algorithm to be a vertex in the graph you can clearly see the dependencies between them. To learn something you might have to know something else first. This is exactly what topological sort is used for -- it will sort things out so that you know what to do first. ## How does it work? @@ -36,7 +36,7 @@ If we consider each algorithm to be a vertex in the graph you can clearly see th The *in-degree* of a vertex is the number of edges pointing at that vertex. Vertices with no incoming edges have an in-degree of 0. These vertices are the starting points for the topological sort. -In the context of the previous example, these vertices represent algorithms that don't have any prerequisites; you don't need to learn anything else first, hence the sort starts with them. +In the context of the previous example, these starting vertices represent algorithms and data structures that don't have any prerequisites; you don't need to learn anything else first, hence the sort starts with them. **Step 2: Traverse the graph with depth-first search** @@ -63,7 +63,7 @@ Consider the following graph: **Step 2:** Perform depth-first search for each starting vertex, without remembering vertices that have already been visited: ``` -Vertex 3: 3, 8, 9, 10 +Vertex 3: 3, 10, 8, 9 Vertex 7: 7, 11, 2, 8, 9 Vertex 5: 5, 11, 2, 9, 10 ``` @@ -71,12 +71,12 @@ Vertex 5: 5, 11, 2, 9, 10 **Step 3:** Filter out the vertices already visited in each previous search: ``` -Vertex 3: 3, 8, 9, 10 +Vertex 3: 3, 10, 8, 9 Vertex 7: 7, 11, 2 Vertex 5: 5 ``` -**Step 4:** Combine the results of these three depth-first searches. The final sorted order is **5, 7, 11, 2, 3, 8, 9, 10**. (Important: we need to add the results of each subsequent search to the *front* of the list.) +**Step 4:** Combine the results of these three depth-first searches. The final sorted order is **5, 7, 11, 2, 3, 10, 8, 9**. (Important: we need to add the results of each subsequent search to the *front* of the sorted list.) The result of the topological sort looks like this: @@ -122,11 +122,13 @@ Some remarks: 2. The `visited` array keeps track of whether we've already seen a vertex during the depth-first search. Initially, we set all elements to `false`. -3. For each of the vertices in the `startNodes` array, perform a depth-first search. This returns an array of `Node` objects. We prepend that array to our own `result` array. +3. For each of the vertices in the `startNodes` array, perform a depth-first search. This returns an array of sorted `Node` objects. We prepend that array to our own `result` array. 4. The `result` array contains all the vertices in topologically sorted order. -## Alternative method (Kahn's algorithm) +> **Note:** For a slightly different implementation of topological sort using depth-first search, see [TopologicalSort3.swift](TopologicalSort3.swift). This uses a stack and does not require you to find all vertices with in-degree 0 first. + +## Kahn's algorithm Even though depth-first search is the typical way to perform a topological sort, there is another algorithm that also does the job. diff --git a/Topological Sort/Tests/TopologicalSortTests.swift b/Topological Sort/Tests/TopologicalSortTests.swift index bc4dd7f60..441422703 100644 --- a/Topological Sort/Tests/TopologicalSortTests.swift +++ b/Topological Sort/Tests/TopologicalSortTests.swift @@ -18,6 +18,18 @@ extension Graph { class TopologicalSort: XCTestCase { + // The topological sort is valid if a node does not have any of its + // predecessors in its adjacency list. + func checkIsValidTopologicalSort(graph: Graph, _ a: [Graph.Node]) { + for i in (a.count - 1).stride(to: 0, by: -1) { + if let neighbors = graph.adjacencyList(forNode: a[i]) { + for j in (i - 1).stride(through: 0, by: -1) { + XCTAssertFalse(neighbors.contains(a[j]), "\(a) is not a valid topological sort") + } + } + } + } + func testTopologicalSort() { let graph = Graph() @@ -40,51 +52,31 @@ class TopologicalSort: XCTestCase { graph.addEdge(fromNode: node11, toNode: node10) graph.addEdge(fromNode: node8, toNode: node9) - XCTAssertEqual(graph.topologicalSort(), ["5", "7", "11", "2", "3", "8", "9", "10"]) + XCTAssertEqual(graph.topologicalSort(), ["5", "7", "11", "2", "3", "10", "8", "9"]) XCTAssertEqual(graph.topologicalSortKahn(), ["3", "7", "5", "8", "11", "2", "9", "10"]) XCTAssertEqual(graph.topologicalSortAlternative(), ["5", "7", "3", "8", "11", "10", "9", "2"]) } func testTopologicalSortEdgeLists() { let p1 = ["A B", "A C", "B C", "B D", "C E", "C F", "E D", "F E", "G A", "G F"] - let s1 = ["G", "A", "B", "C", "E", "D", "F"] - let a1 = ["G", "A", "B", "C", "F", "E", "D"] - let k1 = ["G", "A", "B", "C", "F", "E", "D"] - let p2 = ["B C", "C D", "C G", "B F", "D G", "G E", "F G", "F G"] - let s2 = ["B", "C", "D", "G", "E", "F"] - let a2 = ["B", "C", "F", "D", "G", "E"] - let k2 = ["B", "F", "C", "D", "G", "E"] - let p3 = ["S V", "S W", "V T", "W T"] - let s3 = ["S", "V", "W", "T"] - let a3 = ["S", "V", "W", "T"] - let k3 = ["S", "V", "W", "T"] - let p4 = ["5 11", "7 11", "7 8", "3 8", "3 10", "11 2", "11 9", "11 10", "8 9"] - let s4 = ["5", "7", "11", "2", "3", "8", "9", "10"] - let a4 = ["3", "7", "5", "8", "11", "2", "9", "10"] - let k4 = ["5", "7", "3", "8", "11", "10", "9", "2"] - let data = [ - (p1, s1, a1, k1), - (p2, s2, a2, k2), - (p3, s3, a3, k3), - (p4, s4, a4, k4), - ] + let data = [ p1, p2, p3, p4 ] for d in data { let graph = Graph() - graph.loadEdgeList(d.0) + graph.loadEdgeList(d) let sorted1 = graph.topologicalSort() - XCTAssertEqual(sorted1, d.1) + checkIsValidTopologicalSort(graph, sorted1) let sorted2 = graph.topologicalSortKahn() - XCTAssertEqual(sorted2, d.2) + checkIsValidTopologicalSort(graph, sorted2) let sorted3 = graph.topologicalSortAlternative() - XCTAssertEqual(sorted3, d.3) + checkIsValidTopologicalSort(graph, sorted3) } } } diff --git a/Topological Sort/Topological Sort.playground/Sources/TopologicalSort1.swift b/Topological Sort/Topological Sort.playground/Sources/TopologicalSort1.swift index a6051a4bf..a7be2803c 100644 --- a/Topological Sort/Topological Sort.playground/Sources/TopologicalSort1.swift +++ b/Topological Sort/Topological Sort.playground/Sources/TopologicalSort1.swift @@ -1,18 +1,19 @@ extension Graph { private func depthFirstSearch(source: Node, inout visited: [Node : Bool]) -> [Node] { - var result = [source] - visited[source] = true + var result = [Node]() if let adjacencyList = adjacencyList(forNode: source) { for nodeInAdjacencyList in adjacencyList { if let seen = visited[nodeInAdjacencyList] where !seen { - result += depthFirstSearch(nodeInAdjacencyList, visited: &visited) + result = depthFirstSearch(nodeInAdjacencyList, visited: &visited) + result } } } - return result + + visited[source] = true + return [source] + result } - + /* Topological sort using depth-first search. */ public func topologicalSort() -> [Node] { diff --git a/Topological Sort/TopologicalSort1.swift b/Topological Sort/TopologicalSort1.swift index a6051a4bf..e134bf9ce 100644 --- a/Topological Sort/TopologicalSort1.swift +++ b/Topological Sort/TopologicalSort1.swift @@ -1,16 +1,17 @@ extension Graph { private func depthFirstSearch(source: Node, inout visited: [Node : Bool]) -> [Node] { - var result = [source] - visited[source] = true + var result = [Node]() if let adjacencyList = adjacencyList(forNode: source) { for nodeInAdjacencyList in adjacencyList { if let seen = visited[nodeInAdjacencyList] where !seen { - result += depthFirstSearch(nodeInAdjacencyList, visited: &visited) + result = depthFirstSearch(nodeInAdjacencyList, visited: &visited) + result } } } - return result + + visited[source] = true + return [source] + result } /* Topological sort using depth-first search. */ From 784023d3269b2a4e88bb994a6badd89b4ed46c4f Mon Sep 17 00:00:00 2001 From: Matthijs Hollemans Date: Fri, 18 Mar 2016 19:49:07 +0100 Subject: [PATCH 0163/1679] Tweak graph images and text --- Graph/Images/DAG.graffle | Bin 2018 -> 2033 bytes Graph/Images/DAG.png | Bin 9119 -> 17463 bytes Graph/Images/Flights.png | Bin 34735 -> 42005 bytes Graph/Images/FlightsDirected.png | Bin 32004 -> 38653 bytes Graph/Images/SocialNetwork.graffle | Bin 2416 -> 2419 bytes Graph/Images/SocialNetwork.png | Bin 31918 -> 36342 bytes Graph/README.markdown | 12 ++++++------ 7 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Graph/Images/DAG.graffle b/Graph/Images/DAG.graffle index af6a84ab09879a7a314d339b827746f6393968f0..68cb09554fc31c95169b268ff3b3688848e585e4 100644 GIT binary patch delta 2016 zcmV<62Os$25AhF>Cx2gd6k7ppjO5y)B+cZ%uVe$h$R>mox(#MB6NAo8N9Q}b*glQ- zw_`{84m}?c{BBPv$$JvS7O@c?zS}z=eAut;y+3%}_@mu#4ZfUqB-cScl}^tOd)=0_ zw_h$dUDtu-a(mF0PJ3N*ATb%`a_3}E+8a^ozAcxh(`gBCs(+G2#+=YEpL)cF9=+=^ zVf&1sWK(;OsR^Yg%wfOU$f5_YUo~#v-9gi$=sWCzJLq+>4R0G|{wr%ln8G3S4&+98 zemQ4hx{(Da6L}FzUN8aA1N`Du!>1nW@&U83M8+5mJu-1ieRlQH1J~CMG)l+7VvNH5o%p)4*N0P!)VQ3uK?? zmJFaLBQptzg*`olVFn;(ogkQY@iobhXHJn3&PUMs4k=4T37Iqe#Nvwo77R7--E7R` z(I0XgL15>b5QA+DxJClFg2*^i1oku&r#L0-r+>KP77mW(B*QQmD%1oh;_cO{&e|(l zUVBYpKvXsTA(aIpT^XrI@Pt1CHkrn~5fNmkpS=7N_g8je6J_&JYI>B77t-|Du#= z6w8+loL$JzTD>fRYH>EPyQ`N<0o9)mRi*x{S#`-qOY=b)i~Y2Y;%S zO&u&{KQvQ7wK!NRpt>GZ^=HkhOP*hQ@lY)mz`2oFEugxlgO)*6+t{;anNTif)nWl$ zKsDb%%b=>R3stRJdmO68UUes-s{O?0!s`5CFjXuY{uB8mn%D)F}CSteHXo~ z8S-|$ti2pBr>Z@C^pG7t4M-MoFh^wSa}uEx!kdc{6}By=N%X0C|y#5x1WG^4dNG%2*a*S|0Ruo}=oK%Z8^bxHIUEl=;CQ{^bNlwu_ftejVL|C-N zCR8v6^P&^{Fs%pikd6ces(&1Q)Ot-;HC5G93IqNp7)YnYMJv%K0mMwa$wPz)pkpw^ zkUoXpXNWLI5YkjIFCzVz*ywszx@K9O52Yq4wYOUJtz5~j^AQSyYZUr8Ar!9Or@n_E zrU@@+7mb-yvzS>~I8Qi-Y@lxZ6=*p|^O1969ui8)_!xMx`Y-YG%73}&Yli@u#P#f2 zSCSZx@=&PZhYvLMu!I zeOzvS4_?#fxQC~eWqE z3OF#q<|en@TJ{LXI);Xn$Y^FN+i|+QOP>E3DZ9 zX1)Xf*n&^wJ;&(V1V+pFCA~lQVFy#>Epz)t_VQ7jBrXwVEBO3W-kNwG^F-iDu~L~V zRx0bx7nEh delta 2001 zcmV;?2QK*W58@AyCx2dc6k7o`MsjUYns)NvSF!Du<@TU0o%XusKw>h=<<7~Tv^S#EeO)e3r_&PPRDUIlj5(oSKJ|zTJ$lz; z!uAX58T{1&?p@Pi%Bvm z@nEAoBad+^Mt{9ji8VCJbK#*86H1!)=ZQ}j%BeSj<$3!dux`0hY%_)K2w4lVS?_0L zoWh^CEtLQGA-|I3`&ZHrrJ~ngNs3%G?(Y+3a*mb*e398C4vMszN|}%_F89us`R(aK7w^z2=UVV$AHoi`s_n~lqHI1&P0vdhu#nH-;J|rv zTv5cEKv)zR@xYi-_uvp%cL~xP;P}A|6A`h%jsq|e9ZGVbXDkDNoZKGBS$1=dRqT$3 zUwC1G0RxO8AC$~rktSvSXJ?@*%ldVfXV?H!E#J7l&8674U_aYnHo*}%;R`AN%> zB~UGHHay?uNTq=4&xfi~f6}bFWaqH+P%UQF`~{v|V0B#&Edy(9Q``J(Fca(0z3#e`as>Y_Co$WkSi&?dJ(6ug9YwJL@vZ)(O*>AxVP=76M zEEP~)532f;X4NGxr0qOZiv@6QBvuQkuIZpnL6i&?c;02ffrchEAZs_Q~k ztJWTdYOz;+mQdAx;)`B&{&ttD7+ZVMOHuxy7rpZRR;@GqX{x?GzsWn{x8TLXZThXg zJ8o0t+Sc4w+X=T-WPQ7CtL{#6+kfVyVC)V^x9PUZ?tpZgZqs+dZJHr(*KOKw?6y>0 zfcGA<i>*?)mw)0_BK!vr zf%A@wahEPWz}rv27-rl?;A$jABtKNBq&hj@T1mivZ|@7o_|sp@IS&pIwdYzi9QJ+X5wugB18ZkgCU0WG4wt|ggJtc zrh<79>Bq!IH?tZiD^!H2z1EEEiV&e7xJF5c6GGwYed>D%Vw&)Bc6pIGHH(>*h4X}S z$Oh`xUxAimG#@!9<{_b!jE{jAs}vHy5jGcn;}AfTxSn0>N)p3S9)Aio91#zFCm1-) zZiG{jCn~at&C_&-qQfTrZXbPcK3ys@{P)ng>K>7%{_*f**X)d%qyD*EQLZmPIM%Sm zzT5qC-}=`d+>%n#XUT&ER%oA z=6^4dc{9X^|1#xcuz&AB8q6sVs!80R%~BJzXDIn$C`zf$J~h3nE2<*b*-DXZPVOI2 z%A@ZL@`6V&0}_A2@SmaKXrtplAnqo_Co_035Pb}J>d0A5oIzmsv2*uuPB|mfRV)55 z(v`~n1lfOpsF?o3x7k&rf`|3S^VgO~pUXJ_~}N>2a)4OZgY diff --git a/Graph/Images/DAG.png b/Graph/Images/DAG.png index 480f2e0a599852ff9196daa0c958cd43c951e67a..c26924ca91c96b151db3808eaede259daab27336 100644 GIT binary patch literal 17463 zcmb`vby!vH*EI?oP(V;p1f-=)NkKZL5u{5H1SF+HN)ZG>R7$#}q>=6rkdhRnL%~gl zo02+n`#kUOec$gp=fC51amn6$t+m&h_dVx5#+c(KOjBKv5T6Pk0|SFl>8_j>1_r_h z0|V0^7Xj}imeCKwf0(XXiZU3*U$3vg3q0q$2Cf(wmq^h+m>7x4*WiF}w)gej^wm^F zA38bkm|HqoSn+r{IK$Bx7-C+c@T-HBn>oFggT14xsFyh7-y=lfcl6u5jP!pGakCR= z)K}A_mvwTnq8H>5;JL{tflp6QFXm$TNK{Ks;osBYl{lk~o13#JFR!PkCyysTkCTfv z?=2A#5#F18ynKAza0Iujx1*c67q_D;(?1vauj|NJxjuBUb#}9La->IJ*WAL%-A$a4 z5&cE~`S;I#y4gPZ?{9K+{r9op0eR7%@ZRFN$@`yc!>MBEcSU8L9GqROTwUS%5`toX zkNjWn{rC6$bG)XFlbaJn!NvBWlB1iI3!Lm`j=nnyzJJgD|32dXyq1QGtra}=-?MN1 zd-nf)@89Fac+n63KLYVjl>fd9VV1xb^C>BW=l8!fD-nJ5!vg(3RTYriVtkX`#?M}!36py^7 zlQfN>z^2E*#FfH8IFhh!<~*^N#Xt}RVqnv6V_~*&r(vN#Aqos!!^W*HX3F_{Abh+K zHvosA&uei<1RISLkNo>G(7D(8-wVu(Vzw2ny|n%JrBuxl|36D z5Ym=-g=WoX1<@rV>UWABfBX0=#p_#%nPj=D>gH{qgu=^B(&={*xoa9;mj zhI8pEmvN2r*~wA1N_??tqYu~T)rX~i#~wIy4pUV$VqT@Pp_kz|hq)%dFcRjr(bJYa zoJIsIP2Z9CGLsr~9IH_FInu`Imm>y*EDzRJ15`Y;oIG)o)fYgE4-htHB;~D`9-ns zL=L0T-=g&nZtz$7L41@x0@^KbTeGEX6{N+2SLqg{$l*TxJ`*3zIowG&(7U zI3K#*50=uzEp26DQ_fz<-G75x{kC@WE6r1AtOtuS`Sz2{t0Dzq0@pKblo7~Sk}JXt zL?npdsW-TkbA%fu-%{zgpM*CfM|~4wp9n6*NUx_;q+#O91z|*Yn`;|*zpQxUb#k~< zWK`{u?=%@Tm8+2!C3*HfS$iKZE8Z_eKTwJu_hubou&V9tgruZ`(TL3s!`e(aN@cZd z!2#PE`Jo%wgPeHRcx37AA#�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 literal 9119 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 diff --git a/Graph/Images/Flights.png b/Graph/Images/Flights.png index 6e8eb2cdbf59a26eb90a244a8322822db1790348..879dc131f7633f498affe1ce905feb0f051f2e1a 100644 GIT binary patch literal 42005 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 literal 34735 zcmZ_01yof*`#nr^>3iw!lJ4#9|sq$ z1UfY}wU~>Am58RC!hdfEpTucx+}xZ*I62?Hf6wurm&4J;nv+{tSeTQGhm(hg9h6{q z^>T1C^<;N&rTd>s{#QM6magV5Z=KxUIyz84)oW_z=t+}#;o23i5+0FE+cM?4Rz5D;a#Q(Rhmo9HD!BhX|Ztnly{eNHkZ+S7!rw9MP z2I7B4`9D{|FiW6|asKZqlR&T8;8}u$lY�lYZq1f0*aBO7QdXF<^kQPA*-O1(v2s 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 diff --git a/Graph/Images/FlightsDirected.png b/Graph/Images/FlightsDirected.png index 6cd6eca06cd6fb8b266908c4d3d9ac41965c5b30..5a677e7c0c5cefbe6449eb1abeae3c94a890e3dd 100644 GIT binary patch literal 38653 zcmZ_01yq$$w>1oSgd=(A?w0ODH;6Pycc*lBBMs6a-5}jaNOuS*Dv}Bah=i0Ne*5^| zd%yerWBiWcP#>OW=h|z{HP_t6X{ae;p_8E_At7NYJ(1HwLV5s4LP9QwqJSqJE5sw< z4`fd*MH!@qIg0P#ACKIg7ZW>8q-USh+suw6J!ywBhu7 z?grjQLK5>60e^jN<7GkP_uSdVQ^Zf4?%x|C;O~gXTy!-5Uh#4gr_)!}ppkX;u%Qv) zg^>?M~CR>e}4UEoL&yL z|F&;Obhm>?J8CtN(7++6?DHuzKw@l-_C^|_meji)DQUqV3a-<$u>v;W)Af8N)y zclB}wtKi{arR3se;{iVQvOtVZg7?3^{{MgD|J#u%eHpL~fF$MuYcpt^pw(t_|U*0lnkK&r7ZS^IcaGzHfd~ zZ~P3N6Td2$_b+mn-1C&!nHaeLeF!y?k%B^zX=xx)VK5lVu`Esg?Grrt|L0*SJ&l6u z&i{UmQ(h`DPgzvK`qBS|nE%{gOg#%A+{T0L4E$qt#7S*Yc%Uk`s?8TdOG^){E%bB1T^_hgS_eZj!r``)*G z&1f-2eEy<%2?VS|5&lDum`}1V(rwN&wAFAQ?1l4eS>laWcXxS~rj2d4SdOCS@a(MfQgp0;#i*PWMXMYuCD@0$XUAT+ z+~TlQ+1URZeK(~?P2%S3*|%xXv+y5A5lXs?hCLXpZ1<8=cD3JerPe04@!NEE>tvno zYqGP~10O52)mZhLimkBBaeiNXFl(JTCAM|{(&Nos=tq};{p;ClLqg<2tBh(ogat}v zK?ga4FF)GVzp5_~^*y$3uGJ`sX!aPY5cZcqx&nh7@30s~eX{LV_B8YH!tj*;K~0tI zN0<#1j$*lNEP}N9H`wdiu+1L#4z|r^E8v;$sgkXcnEE$?tKa-#l*8?>C3V^smoGgR z2P?8edwA&bF<>F2Wy4-^6y!GhdGHPjzB7;8oKF@zdy-xJ)<3%WYL`o7ggu|V(5@(0 zP_d4)M8moZ9ht|m;UJlQbKZ8o@XzIE*VfZoojM}?F11%8#};#z;iKDKUf%XY_*-u6LO_;v>2;AZCg@nZ9>nF|J37M*X-fp zq16{~QK_2$zR`^OH9WsoyV+C@oG!KiEQMH(&0pV_a8;W}jDt=`oguF>W{h5-9L~+; z^4ZPgyghC*Xth<%Joxp4ESgT4M8mOw(CI7=d?pohK@SbT6&<~jwLBiJqxzh7+o=rJ#y4l^F<>#h zWlZ;}RB=T=zix>RgEc)wZnMHId0X0C6`kU+*450h(p9W6gKfWiuu}KA&0(p>+lhVB zSSsVm1QM_YUL=u_xx%0`B`;RazF%6l#kV>O@5Z5Z7grmhp?BA(ezXTmRqDX>m$TxvEOWe?JpLbUmkxUZ?8iO09@L3=cigraXsuT zeEV;G*V_ri#%{Q(xj^MKAKFg%{g5r0`^L9^UkwTkhe6gs zzqdaJ{>HO4bnWIji8(^4-;p`FxNrR$e1PMIId#*>-HfX3n@y)MdwKu%+I=FG7A}AI zxs!{B|9RuQHlZ7yNYJ%g;z8Qp^u(aH3A1H%SRb@0n_SSD1pCj&Y5yVmygs+P&R?Jl zDmU2c<`C4IpxuG$>&t8sfxup(5A750j{9$2-l%;xO1D$q=nE7|WM^k*`A)Lj`h{gE zIxG_kGa#ueYn>B093ywlxcZp29jS}-rUfqK3nm)X({|$c9S%)2(dAlHsvt=5zJrWm46a%Kqn9Khq);l*)F-qqIaxku%@ z=HBsab4g}AnNpcMa<4Fu({=rg#PiZTM&JikApO4&>VTv2K3*d&vf$zSE)7A+7krM= z8U6qbb?vbr3P};e1aZOzrLe<02KLOZquqDlKt@gWTwqNY$I02#sL3{(_SqZmR%^@x zw_}YI{^N6JSsFP0H0}`MWW%Z-kPwz+C_MAtbG*=0?b7K5;~z}DUX*am z$~zMRr>~v@ZKRz-%+Kxb{hv4|2b*qWw!`;Eu8ivh$rBIWy9nq(A;jSzK5pTuynpaL zF$^4GGrz6q>nfEhSl^)xWTe{QBP*mt^n8Xd_pvTfo|J)6r^~2PelBjOEZmhIx8bxb zMM7pizuIPci#w^zRF zarBHvY+74jMY@o~lgNeej8f7?g=j)F$jXJXpnQ}K-It(*K-;kowacHRd7(F7egR-vCPPJDY)!KZYI7x#GPF4vw$`4%$s* zNI!4|H|Kk?@ps}Jq}P>tdICoJ`u~jNxGt;YwkI%xvLfRVuj=AKKvl z^#M`upGPcanNO>5x%i)bm5#<{)11Rs#gEzu{YyC;oFk}4E{r)k1_Jk*?qaU3Fbol% z@vLe!%M=`lDn0;r=*EGP&aBRqQ5C35^#LUlZt=mym(q^iav4u?=9{qhF9%h$Ee}}M z1hPBX(!6ym0-rg5yg!z{7VHvgWu&knyGpyGAUH!eTBXJ|8*#V+4lhpDo1x!%gDT9D|(c*A8Xxw z(w{W2Mcp=~B66S4D(t_`WYaqfZ)ztZJSIU{ad^Pnh=hgme87;Y&|a;CdtX1=+7ukn2oaP!3 z+ezf3v-z8)5&eEdD3%Ll>DyH1bk`nNug3VBzr}&s#lPlWGUZ1rVguYEcUnZmyK1e0i>B-LF#)ZMa_qhR{9dOBm+Z zn;Lt*Wf?8JkJhtlr?q5a#|}-J0igUb8n)0z5T7!qOXB-_16h$uE0$|A(goqSjw@g* zn30~G>1*C36h6YlUnAM$z!nu7lEZXXt@YY*KzP}uU^l^|(t6hEFBMIt(H?$2_|q>P zJ(7GrRGcBsD+#i#kmuUgQ`tIMT%tnE#b7yPNOk*EKm-e4)UI+xW#Xdk_d zbUTJmam1m^4xL_IQXG+GI*BBIL!ImpuwgVqU&C}HD*4Ii#8T*dztD5kE5!bYLi@h8 zk@m3xSl4Q(wa>T2r&{`@{v%2~H3^ArGhe^TL>8C%$Gj#)g&13Wi|QYuUy9Sx7px08 z6Mska;W0O#X)@@dC+wAObzX!(G?OuUiCEfvY#z3p06~hjY0J$Hfz1{@{}b+DDZ9BL z-hZ(BSQ;r^y+Ff5ZI9~Z5X)O#^R1z1hM@}at2NJT(*V{h5+ag9_!CU54c~W4%(SJ$ z_DJ)JWA9((s42`?nkp^CX^|k;{E_?CppZmX(^uEI7K4~&0E7dwCTQv9pz1!EF~l27 zDmVp;32^3Z>=Ea3fAZ>7ZO?~Bt_XI*ib4U`Z8ZI|8MXFNu5F1M9`<0zJi{jIdSW5Y zQ$R&pIh*rKlZC8Lw?#(Tb__Y67i8d(oy;_Q4 zQt6oR?pOQ{c&?=JZS|S9AxljZ^F81QDl!rUV_ZhSU9H5uTkYFdewD$S;b;^MLNx~{C zt8N{Vpwpp3OB0u8GtrtbWR`3*%BTyQA)<2G!u{CU>xF=z5;1G3@b-r72`vj&MT;?%aEKHa+V+w^saB6J*ft4s*q? z4WpzgVfO29gw;ab!qZq$@M?&E%9j|EH8x$SW-0HyE-zqVl+m}Qs<;0bZ|1$Cla`XP zt%*2f@7t*=}>g;Y#+UH!~vaPM{yH_rz9Eo@+xQg zI_2)=;iX;TlPpP?_PIjP5|rN{~$ zz|Uj2z%O&H3blNmfitc%BDD)=d08P}xv9DsE%(B5)Tciz~U5J!`xhM#)4h7;&$fhfo5{{|x(IVzsbt26Y z9gcbuufGr(AyJhy&Rdnm(ny=OE_*^|NK}{+F8oK^QtAfZ)y>oHOoh&+QEA9&*TOS* z(UMXwC14edkMwmv3Ny;_N58f#Hx1QoWV$N&hN*z{C3)e)i-?HtNX+>PbnkfI+`~Ly zk@$dgLGkeY>%gnyB!A?erDeJ`T8x-9P#Frt2nYT3N>y?{ff;Dmgj9y5v!Sf#C-;=L zM$f%D4x@w2S0?Mkm0KW-CG};_D`o+;1 z_G=yIv!FgCseJ&0v#?PE7A@|p9@RW;ahZB=Pa?joGxzDY7rvOi2Pewia4cyfHRC+9 z-`YQ5C^ht9cU1Yz&$w2%$zl#_vcFvk3ICFMMO=0dqP(hc-oJD&=~V(VIR#FsklQpz zr`xW*m8vNxg0@o3LS#;p@7}B>m6|~HV~`AW_mlV?mtP22oNkY1Wga$0z}skf3GYZR zEqMFR^fqET6%>oMUg+PGe;|Rbz*O-cNr{}5oOrDH@4fQfmW`6nwc1`#>>)-_qcFqx z2^Ra`mp?x1jTe{fY<`zjT+qgVimdiD^z z`SIA!kVKU23_Q?lbAMw6SIzx%@qD!jx%2s|{^lGOPT!?oH5q94J zCceSeI(4!vDLxn*A_uk?+rcMMPoEqAr5vVU(~Jx3MKFTAYQNp-gQa#-JN-L>dP-cb z(aEDo#r?eEXVNol^`e@!P=dgN$YX8%s4!(%m<_3@4?6`pa`ctln6y3#wCs-Y=h=f1@Ol7Zgx9kNpaO331@Bg+|+Ce z;-LoGUm&Qm*FO4}_^genFrT}&b@-sz2FeYm;-lNU-0D0 zpxEu;ZOh~+Z>GB{7kmPwPGoF*fEjoHH9PevVOJQpcq}I!v2J)jmJjK6DLp^utWS&? zxTH33slONi8O`vIlGpj%K7sYDITAts*F*XjAR^dp@sTKwgwzPBxS}H}8qTs|KaP96 z4--uo&jjiETW#}*m8)Ohv!~^jNZK_NuorPVRuzT(w&-t07eeneH=4h#HRo|$KU8b` zDER!-NP*Cw_*A`j+ez}r*_=| zT-lD7W^$02keFN(*b9C5mQ?{3N6$cseUn;?E!i3&8Po1mx7|F|d-eB9M3YCcT)Ju_ zuAm;p#(HP-Co0zJIe+KKS`!baR{6x%pRDe(vGQ`W9_|!j(}$1apb1O z+Ws+~xCTXvz8qVw(SDSaNa(oT$X4~QQ)I{jZQy=MEE&H&x6^y}WYJkN+^W%LOzzh2 z3eYYr;Otxuaj)J*@?kHjlJ&H$_Ox0sCRYWr64`)`A(+S!Wt)ONt4$Vwje4}QFj%IM zK*WK98k2X355{~`PETn+=1}#DX!ioG@g<--dyjh#Py7#&kZWZSH9r^zvX~7f1w3_A z*$+By&c{w3^Mj=>n(?3tb^-zPhuETO0}Wm*W!mu)g34d^7Sz(w?qhaB+} zaU@w56`luIJk4|yBe+Pziw>Jc#H%xG4`Tm<5Cy!bI@+O0{D;xeyk|99|C|6e4HESw zD8wjYWejN!+GLyTB4L5?tcHUWM^xkDd2Xe+v_8h-UlvgIvv7o6K9K}C7lwjOGx$65 zyja+C*KH&hxPb*Scd>+1ZTtA+=&)E|7P}>LQ(`qFoy6?=+!@%$KKOdqTd~yln~^xq zNqNMEHQ+VSiY6|N=~B5;`in4ULy5GcFyteKvR%DWn42WZ$1m!oEM7P$tN1Y2sq)xw zjUeL(E?V1|6(1jgaZ{xsFXDUw*Mu7qwyBmQf=fhd*~C3Tqf~1MEsqOhaCAT+ssG^q z<2lP$OPOe|=R;ACo-9MtiP;I34S|DLiyyQ~5g$W6n__Ep{@7CCj`?(E78H4UGEEm5 zA)o?)*Iv(~m8=2ToQICd_*q@nvqUsK@4H$L#7gGi&;QTxvFT61q!8pCyP`rLMdTTN zs~2mv@EUIIoFRlDD}ndi}fdNK|C(QX^>@}IS*Z?YOs2261= zS0JFwMUC5Q@liVHfKS);d!Ts@N+as~>M{fw>;}9rEM0m813-#WUFi)t&Ik<7&4neK z@;D0GR8GL-C=*NfrEHUJ^J7arj7AtU4Lvlc)`7IfBoiIk2-tuv+Z$=tH^5hoIMYHr zG|1|GfTP?bgJ7<-iT-@EBtQ@cqcvwlpmDren(TJKfq{V!Tz+!$Ki|dT#dbtEaWy)c z6@KPLT@zAius(@{$HPzAo>eb&x$i8NDc&|ccYFz6YLG)(;YVpU3%*$4rE#-E%>a)DmcG}7{X`XF|8uRo zb*=VcdGCq}?WP!tmZ~R}=Sq$=q7_)shAu~^WB(6B0Trk<8FEdfO%K|$fhFifO5V~7 zv~r1V9gHW6b-9RI&{u(3r8b>xWmu}*EF=2y!n76^qbm}9c^>v-d6Fd{wg*v1!WMgnHuRb=!K-uSR*OT6d z-^KO+JREy%2#VZeN#uLCS+(K71+2z~y{Y^d`}(PmBnmH+TPU@EzKrfFaQ?$}nJk(^ zpE+-(7LDYYtKV81U_ z&4ZkfFlRpWRUOeIJKKkd|E?R?i7iy(0qpus<~L{GB%HGI=)t~GA}j{`nNB4!!m*8-o-@qG7`6BQ z?9WeXVJ4?3MH~`zusg!hZ3m}_%A?qVQa^38bR;S;EK#3&SHtocFmQ8W(3!1p`Qrt! zgE@msU-rbe4I-L7>#|acMeB!r)Eexa zjuQKF0@6_Z1h82K2~|(eu>e1LQ_0r14C~f8*K&>1r8SpCj7@T^_H7+lh;zqz|5q;H zX8}0zA++YSV8L5qDumzo5HY1*R(y#9{7gkJPJ`B*6$K!P{_S|S%by#rS&vuv@zK9P z!=Hc`V%r{s`{YJAHJOt9 z8Jbj(SATZt{Q-P2whreUCTpz@m|H$>4zJA=DA38U2?LzOTmnY%3hr)c--B@8+^~hk zDuoC(7zvN%NaMi0h~J61o(4S~Xt)VEyeRaZlsX=S@i?7Jv(P_;hiUJkrOa_t+(JNwGHLh)XiXmp~LV#}y7NyJf_54o_fizng;m=*Z2 z=DQJ0RbgfgnuTG6<49Z&!mrqYrw8yrVYQmmq-U^sbgI$o-?m#{)TC{4Lhb?Q10tC* zAlisc{Vdq0CL(VcefCH$|K0;X{>L+|$oubpDh8uXvYuBh9)?l{1~5$LJTp+Nx!W&G zft6!XOHe3qw3t>v!!vLPi*vY8Dj)mdT<=Amkei{MC!~r8`t)P6$nF@D3Qe=>Wuy_0 zR@*>)bjWbRx%#iSK^YNqR+o;-5+!Vk`eP6@ya6i z;SIBpo6(#K70rI3jKQN(DP*4{J&?q|SZMGA^g%qK=vEYdV!mJbelCK%RiRt6h6@hl zbf^r13a|zD$jk+6wPRKiv?;NSa5y$>nxs>X=4-+r`g|t6A~q_C3Q4kX((B(m;}o)% ztG0zWkj6Uzuf8%!ZanOV24P&&xt+?>+_hl{U0NX(jgVTsv&^Cm9P}BVycykVRZ3^dGb1HMGOf>eg#hMBTqvOfH@oB{HFWavIgwe& zn61%%i33WnN_HCN;puOud)}U(3UiMjgX%7aaaYr+@TMyeo4k0E@BRyfz&98X%1A{3 z!|1Y`^#^@yu>q-P}qlpu)D4~-CjH@vJSyj6Zy{I7i{EI<<`OfB=3eLhj_*~bC|g3q0d>t z=T%i%>l@2uIv&mVKB)6r7p}Nv!^Po;Y%a6H#d-G4M)HnNGg{TWe&e7_Nag=E4U&qW z58TUe%ReV1JS9far76C#c^LnASQr9-!LZI|2D$ejatOf%nwA|3+-4`4CcCrbd?D8{ zK0Y%DC&abctmQh6L?8iK$GsUg2&d+H8fC3;pR?}){Zw}Ee3EhE zXfL~S`KS-=*74b-42=MUe?V(k)zt8 z2cYlU&PBR;0XfJmCh{y-k$3ga{NZq>&)yQ~^%X~f-HyxETixgABUt-CX7YtnVv0GI z-uQd25v=;MFeuDkozq!i0Ty5j5KC`>4TCBMPjWNn1PSYVokRc(TnA>qe%(Er=5k%B zCA?gJPuTb}N~#oUAHo=)an}6+S&$GR4O&W0u)6GNvgd4TR3UoYX0tkcE^jVD7c=%q~vkE4N1Ip!p7Sll-NDbL?2bGg_1U##fyk@J-X=Ta_>x#6ng+&rfX*_Fpdc7l)NDw5sx| z1J)wKcC&Z0jm9j8yf)n(ma8=pgg#IanI?MzM&YEcaOOp8C-8a14H+K;c9Mh&J?Dh8 z_+=CG7`bax=`|XxWmCeg-L?3#N z^k7Dyl6?+Bm16w+zChn(N@EvLs(xA!D**^Uzu?2ADjYS1ckE_~hIvQ_7xZql37zhh zHb2+Rc;aXW3zVYKBuK~FTDiNB%njtVOOfi9hdP=>^%$R47+EYP*MGM-A*LZ%g zTmy=s{5?)1pOnUz0Z0oT7JxA#WTfh1r;s!YpfXT8N|tI9cA*Bbh=+{m?0M{(sBc1YFMikqAVpr>}y9=G4)A@cly zL#SXEC=oMSZi4cJ@pkS4W1mdUVpU-Px_2K4w3f+NxdIDz;4EZpGMkn*<~1+RYu_M zC4l#gj;M_2;rhT9M`gxTKHTw^xD8{iFRpgti{uXQhNpa@hYC=ITw7FL(x-^Mtp8F+ z(q5hVn1>3*@22;#p*Pia=eK}q|DYs2|5E^5g;5_i3`Wu-;mJ##vq_ip58y$jj-3Gu zFE5>IJ_}A})#Z=VMTPwr2AHA3l*vVWziLR@HTb=X1W@#gz)4PVSMd8(?};XXMy`69 z4HO7eLM{b+Z(Py(uXvHdcJ;K1okAENW>e;d0x_&uY)P2+FqY7&X8+%*ptDKl=BPiQ z3WE1H=IQO{(BZ)`BHV1OvhX;3W+sUt=khTO`QZY03XKluk47%t53N|ZQrXG)fKlnS zEPz%Ma@udwDog-i4u&g41Jm$ht8^ zBONPGq+BX!xw3i|gB^L=-77Gl6~p<8_;fVIaU6jEu&q#$Z;%s{JADg6jK&V{!}oG| zjb-z48d`+|&&8U_{Qwj4Sht=9t|b*l)2~n1bipuTg5G#Y7)oD!lWF_cF{I*=IeMe# zngPHtKnk7&ajc-ApSD;OcVZ7L(dvP(pD)TK3Y zfemd^|Ju27LbTJ;2z0l%fJk7-^K9XIJP?P3Ob)=v(*=1x#`j4i?fMfef6O2tc^1g< z0g9G8*O$jH6~n$T`;c@Ek6L-3xgKI|&;fU^^uaO20L6+f`e?oH79bC59!oiN&bN51 zl5qdkzWE%U2U$WP>7&)7zd^~?GQdQ}LNBU3!^5~#r{4U$c-uu$^M zh1d@9NT$IU6`fkQ@d3&dSO4<1*)>_JMSw((x!`+h4dq~>hoBNBn z)%*Rw-YLU_afx(k!}{hy8L-cOk**H?neaNW)#MNZwl}7TH1#Xe#CKj7=>g8_6o?aFsb7A;|;4bE8 z5KOkYT6lwiv@&kbm)&mr+zH?$7Vn^ww`j?WyOHtwy`V5?XCdpBI}Me?`ZUCw{y1K^ z7aZ|&(`G?FKOl->NG?<5aeR+*-1+V#-Ly*Wm9^2u8cl^;m$3f?wgGM>s!-5mG+TysDz{C4*n7y?gw9cVF~NtJtK_m^ASi(MV7LfePB$Sy@hWl6)9K+?_r&%q9f29eijE{b-Y|^V(3L#zTgWFU|3NJ!zih zmN>6nY#H?21X2-vd--iP|HDvBHA^Bsnv;Qddk!0o0L*`b&G7x1Q#}x%}8emxlGcszP z%Q4#~KFMkgx;bOi5w8+{;ie8y*$xLvXREXjh1OsmCY4wh5RH-8<)U9iqGDMxORJc{ zW!@-RK(e2BQ|NClk$&CgCq%6Nixt2~}<1D>s@oDfjYV2#tRR0;PK*(>lQ`2*4-%V$4Bop&T| z_ADb#iRyl|e=wcq!6&K#(4`U`g?X^^RG4RbQjUWN8L5@BTfCL*gMgl~`$Ku2`A+AL z5$woBNnc1TT0HjVlAx)In&+~DyhA|f->lWNE$feN#-xE|LRqbxor1fm9Ql|*(fLHY z31cjcr8k>kH~R|sN74|N2|>Y{pWL{ zGY|W%Rh}2f@I)Rl@lKy5-8`grrgA^4h$UPopT_ICCS|8?K3d%>1W;`Sh{`>$=GIZa zlNpi8FnGcvUt|Q3T1^DsU_`s=9TBY(p6CMiMbeh24}Ve~Y**;dlpu_PvPu zW$>7c!gp4>!EPMwgjZ;hBmx4-Aux&}3lbAGb%1Kut#1l3Vxclv<9v ze`U;VRF6?0PZzX{yFoQVt9jm7Jtmn2DIg+9M!)^X;A_`FU1f7wx)3Gof_PWH) z;~-X#-5I4D7BVt1((lfjSf_*!E}F-wc34sPocD1547oNZgq;peOa3gKO+27omtB=7 zAxE9E7)XjrcHUj67#Hpf2KrML^sHo_0mqfc$B1g|g?5Dg+-gq>ki&PAahgxe2#$&Q zZB@MnDs-c*i=eHsu{M=l-ndT4J!&ClE-CR9b?`4-bP<)uK-?M%7uphw?o-rqs?)_c;b)w4AMCr?^%Ay2Sf50hh zIcw#ZX(p)hrTr}6A0 z7vyazYNy8h1OZ?w!b>Mv6-_5`BD`2#r+J3)Tz@r&kHd|uJ_ky6+9L%{`)Y;7@mk#(A|l$X^9 z=#UPF4d=VI*HYC{Zavi0H_xGa8Y~WkeFWQKGVGNVGzVGPZrYZ}_xx zo>I`#h7ZHS1KZYS6mxrcc8RHNiKv%Va8u7YByYZ^Zzb}{zmz;^_ZbLb-3)9lS2o)uV4uvTdPzg3UR}w4OYlpX z18gq=aA!=b!CLHgq?0|iqq<>VFsT_L4=wLXATe~rhwwLKk1d^hx5B%&yONa9CBB-* zM4)JiblAJc%WvfFsEzC{2nPJx2l9_*dABRuAN7=ijm^>WzsN zf!hc{%(@;*xQRXwl~J8k0XA>lgPGTbttR$~zSGXAylLYuO-!dO<6xcP8kaK9XvycL za3h(LZMG#kCOmPEl#80_5`Mv`>h+Q1StcNPCZP;3e*j}C=aTLX` zo^(iI)2%j_an4|W>{|Hp6*FKs2FrkG)HaM~vNB>Gs|CqwqQpD$B++;49Sa(Vb-w^b zD>pJ0KBQHDPRXDX>#sk6*g@dxO`>94=+l|f`kt-3>=hba2a(^2(TVT=DumI8W_6S| zZ4TnP#66Jfc*-qK@we>fWEx$BB?G#%#)VbYyjiv;nTMswn`|*Kn z3az1pt~D*9jiN*dlhjUR->a3Juhktr?vh;lVIxGvBr(pM6E{wA*X~2~GS&+J<>7vH z=~C*^BPKgER=+AfrIn;O?ZsxzOmK! zNh+omPOnd^&4Vv_+i`80AI8t@SU;`58O0m9VJF6?7{)$-vaIy!jVW>LCVMcqK6{Eo z$HPX76Qh!GT>IDD22X^p=9_EH+ZE%YA5t({_47Unos1(08@>4hs&ZS=#QVmp0)p~E z1Pk0&)8SsT>`CfKhRXo&RtQgoO?JEQC=@c?v+^Xgd_{G6iNk0M<58AvD^`Y%$b^~j zZqwyt>XTYloYT?cm>|mr+1Oge$sLcX^SYrsR95*%dZPp~mBHdGPT&uROlbEK^1>CX zTWORrg2@CVF(5MS3(j#HR{Z1ltfzNV-)SKvC(e?obbL&$45Hs|GHoWatfiu2%1K`% zJ+;!JX?UT{&Q7LX=#R^s!k2k9MT+nMbS+C2WJnAnwCRhY5Vmju zV?_P{7v`IPPq)B|-mIi8lHNtkl=fEIHGvkCXCW9`_e&{w|sq zSw?`?@(~K$hqu0fomDm3j}p*8PJtTd(}rU7%CfGIOgUp)ISH+&=unj+3CeG|aAPu? zcui&GRr9`x9;D>^g_x`pfj`OPLE(S!^IE?XSK!@+0}dwoPxXxrZH{~VP|2fOb2uzH zT`>hu8tIfFuef9my|kZEf#Wgz(>olL>sl!sp+Cjle_8qcBsH$yat(j+-AFQv*=#rE zNR9)Ew~GBse~{^78ajL%)j;)SCUGu}E7Fw?56vxx=J1+lQcyn%=0;?He-)9mpITa4 zZg9$J$s+kPc;bDuZec2|(W&Zu6Ac>5`%`g~$rLu(uNH)|ia|lhcw2gw4>k9Qk~gHw z6|Bx_@%P=Jc>k00}3z(zNVJgjAR?p19s>e!XL1JZUBW zd-*VP_G`istej@}{jHSmB5W{P2p>=KdqLn+0S+>mr?)sDOa2>9Uq_v1Wq#+b z**u|CZH&$MLcsG5+%Xzu6O|~%50b}ghlFc&{G|^wb6wNIhq$f3@ke2lK+*qYJ{NiJ zL`NI1oRE@PNQPh?CGY?@lm54H_=4HUM6^2vZ zxhG2YY)tAFJB{*Sy&7C_&oCj75nxzf!&lcU6)1lDm`Ivz4kgtU zzfXTy9$JoIeV(oH50nmVzZ?OVS>M;`xdJ&F7S@~wf2_!x_Zpgs=j4~`uaSwuf`hZa`zL9Vu>E;(z5d!_Qd0GgnA zuF}|Bu<#IrNbGEa9_Z2lDf)Mkx#-Bl@ik+LIKBn>0toTo(qhj+El|iA8udTL2g{RZ zwx0LU`OC+ykh{}yaDB~nv2;{Zk@6eI@1^oA%G(#X^zj6&5qG5^ZFR_EQs7WUy7)Z+ zZ3;&aypQ5B%ie>_(|H0;_qQ`uzASjEIo!x-OMtHW0pN2`tvY$Ftqm2J%xvRK$`Au9 z(BC{*!~iO;WuP&i=IouhdM8jG2P#6G3J=!Y+C1ij_ZS}O|2ncGKqvUa zPi!!v{c0?RV`^SaRjGvWafJY~1E@1zNrp<~%k$&BY-#t2ky+VRhMWrbmH+qu1;9TL z^zrq*%QBFfUDMH+3{MmTe$?;RiCG{H1)SSvilAW9!Z5a=6v!!v9zO@`w-M&9oZuFp zkT(PXDY<~-GN4up=z5}C`1e;qmJhgi@!;RT`U0=;lzRbRp_QZhK&>xN1T12WRh1B5 zIFdVuaH#nyU?0R{?2opzn?h$GTc-zdbF(T1;0|G_e8Pf!q`dOqV!jp$9>=sCmeHq> zoB~WsPISbjRbjecrKq35-TvIz>zAe=1pxY2v<-v40B;N-6qdHE7cjZnJOgrh5Y%AxcmOusM~{)mv0TleXH-$qC80D z5%dPzfhMWUASdJveBfFQKXQUo?pZ@G?x2&%fm0Cfbv~Dwgald;L6`BiBIUWxPQsvB zgbk?}BXu;mwk;Y{Mi6NhW^?IN8aT{1RFS5frCsk{}$izwge znFT+j9*Yh}vW5+g>od8nPZUnlkbOV`B*o~@v6`yF_-IHk%TdGM=PAcgVYjeBC(J6o z!W^^X2kHbisK~ljf|JIHpFy=U8Yk*T9)3E4PYI{BX`G9lyrv@weZ)FV{MMZM)S?jg zGn~gUmoz#2b!NAsb441xqGd-Cmz)bGOAgfxI$l!uTd!|?4-Qd#Q9G@T*XX^irZejw z4}z+9{PExZ;9FS7j)WITZ9aEA2U4b=u$PDue94*xp!lo^*Sp-Ujv7jc4#Po)*xDEo z^2_224HWapO=}omZt%}J+uIlxBR3dA-37MZDg?J56c~LLk5X@(f{34Hu%rpOn)XAD zl^hmnST{Wf6_J?|xllGxIQuc~zuUw+%fO4~=@Z@nM{TWdV8?5&OqzmFE z!YVxp6BBvFF?{HGB}_Dbm~a2DHnhs-%>+dD+1w1fMln))IzIl6W!dm-iEONfE+ZLD z=nY(xl~^ct&qIQM22jZ8pY2q&ml(b!FT2*^?PdCrF$npI#vlvfl_hA3Bmhe5=t1m@lIn?jd&^;D(*;Tkn#tdZSsU=m8|BXC?`fyi($(2P)x-ng577%jy5H^wm*O?%&tUIKY5_L#NUy9n#X>A(Dc0Go&C$NOww!NSBJV7&Ou-EgA7-M{Wy&M?pOiGB9jd!Ls(%^eZIyRO&I{EH>{bJAHobS7lO%9Hs! z?IKyDurX4?Ou;|aoW*GN@PSFaMr7}));M`g#2lF}4KhZR!07nolSr z=lZF-zU3bJGDjNCJYR#BL#t0>N7e4T zDwtXi51evhGXxstM89l_QwM`Si6G6oZWhIoSkbI2s(#!}m;rK+WKP`LSC{p4bHmS+ zy;D>-$XD}3(}lguO~gV;r}c4i7cF*aq&&*{=1*yQAW=Rqm%a#KS<7ahuk z;E`VlDL3fN?FYr`Qa`)HdGH~?=lX+AgpQa+QTIF|V$@MEos-+FF~LKULNEezIk$5^ zcy}&FZ-A47&L@ck0vQIHDH7!iJ8R;LZ_pvHsTowdsPMf9{pm z?5G*_=q&kcZd|Po&}MOek|L^TKpw&Y$`ZQdWYZaqUfhff>8A3O%(?jMY8%~9D#cN2 zKMT6`>McF`*2~5A_#8FK1~B7!fCK|b=Kimacv(vf0f%zjU>#}wNy|~Ah6%xcCI)W= z@d~)qo(oUk~!{}RG0bC!97~(ig)H0udscx`A?^NRx4f3B_^pkNQ z@L89IJ3OI_r$wXaF;g`agcr?#=2n9z32It16}B8by=of!SFyGBrys8ZyovkqLnC$$ z&7LKR+$$3pB`59e*k8)9v`#iVr ziB!CO3`ANaUTdU`#q<^uq)WER`p=7bFE$xn{f!!TFNz>?BdDv+XT#1-m8%KyYsaHl z5dI$7=LqCufuqB*6=;PXB~6sku;ctt*tcSCZ&)}&Fi)z0haVgmviJjSo;>cDp8xEg zw9+9i-my+~Q`Vy{psU?D`o0A8a@qx7u;dt@J@mgZ&58GeCH))S`3y)0Zs_2i4wElb z$OR5C>3AKHIeM(mtpAd0Hh36*@EpL|hMF(1_eTYnj*CrhfY(YY(_uHjk;L13*M!xJmno5*euxoog)E2PVF?cSH?#s=d}A3xk@l zNte1H-#iL0&w)+})S%UJ_4N0w&?jUF5Ll3>^Qt~<*PEn7hOn_YA?1z9)r;0=Ot-hd z`pbS@%__ag+T=k;t#Qo_N@S^8G#fYI)c2kKm6G!c?{0A{hT+v}3R{tNCbrgcT}k10 zLAgpDkg`}7z;}-#=k~joXrP)aq4Cn$C1hTgb<2i*EFP4n+uO5ND>nc!e^x;wG{wP^Wu_0saS!k#t4HsGb; zu5E4SpcO`~B=kZd0J$IkGg|q}uPjJa40EHkE4Fenuu_ccGy4aZD(+H|QJ#5*9%Kdb zznr%C-KdHKU7PT=2AZ_uM|D(Us=bPMg{F~xXC4(;F@y9$UR8Q~mmj&0qxl7YJ+{Ua ze19v^1btYN){dyNNNEfwIE&uHd9~GX$)8?veWqkT6aMUvfIrEZB-v)>zyb2$v2`#> z3>inX`fpG-hi(y2x(;#$k1&i=s$%Ss5=JiK1bs6z1l zE#&Qhq(F+Z{gEj<&J{(YIyTvrtFt^SV>k#rm-?<*$DOnKY0sT~RxUf}z9jxx*@!*7Q3B zl`NTer_drV;eU{p{2SpGct!Evx}PpVdB~}mhC9yPCd6;0da^DqltL^44`GuRXoC*P zUUQhE7c)U%`k&ZOL-O^Rm8I*D32^SJJP3JPoJXl{nesKnMPEZZ=%`hNgi*JV8r|DC zhu;;khHW(@>obr0rb|r$BPZID-|CFhdTiNTp?I&(oINWH1(jEe>m<|WFvvUKDo9m8 z76$<$J}W?lw=){$4|34B$2yB0J~p6F@tSX#hg;I|h1=h|0cgYp4p6UCkeyGuX58eU zav?_~CqDW$+WpBh24fLAUg62hT^7*Nq_>aA?kx)qID-U@F4c~08l(=pG3bBbe)A_N zp0fen+9}>N-t*JD;tN$lKA-8qNCD7~peQd8w4&xg3b0Dd>)2#VC3 z*Ze=IE6aI)*q2VNqbqQw%*vn(gy4XMdb30UXm5wmyu&ETSa%6fg9bPH3vYN1@cq($ zA6EV?o5y0XQlPkf{vzC)8{CLb4wvmtz~Yx7vI6x2yfE*^U@yf0`Z~sUHK8B! z{n{f;Coop=H1v^1dsb(82bGwqbyx3+I%895otqL>D|Un#=1}5irk> z0?`tK)U)F_r=TRgKr&A^fiZB~LMn(3**S&vgXQ+|BHe4L7%UM&VOjy~y8r$9dh367 zTiYb~cl04C>0EHuP_9hSJ^)bz)U}k6iP~my?QdAv8?4ZlX}!t3rBEuXg-W%qfRgfA(a5Vzq7^ZwZV0LRky3vcC$gEINfyGJoZAPOcM)W#IhCHY=m8G)3u%!~5* z8|?poGvXv|g??}&i78m{Iu*?f77!}xLK~rIWD&%adiEXH)2Wcza7?8R4*K!0&zvq) zTD8|2m#c0cPs`z6gX*sOIR*98^B$w>T`>cm2ei=KIeDs`|3$~H+E>L}p6C-XUT zt}srjgYvoue{Vij{O{Jw!Rp`7Z&AD3fSnX5gN1gl>&H*i_uX#}yqGMJrRFF6MUq!8 zsLJMq?yZK3HlxrZn+D{%gwL&=Uw~cb41a+3T>TrB3ZK*AmFr;%=ND_lp-RPFrWA1&;!<~;rc|2G~_gHc6<%D!^TfK5`W88tVhk5^&;nA8st?qh4M4M zj84g@pI!}592Jgt=g$|IpU5me53DsIv+o0-!Ug`m`uv7panaQ1{rAuC9%ej|BJFwy z;#}?kL9#bj?^Ls`i9Vr?sZ5}_xcjbyu)}VB2KoL+GgB$_2aU`1tn5goxtB316E=H8YQwbGZIAF34OLS9g={j8*?S!D)(D8psCf+)cB*p8mIv#eH)X2l zT*RZ{bMq5<{K7&KoiDpB`f1_h8=;$@9lW=BOMc?3iwRs0Po`jVMPdpHEFGe zqj}hIO8C8h$nrqu72J6e{{qgD^RjdstFDXR7|kJbK?@?uaBvo~ zu*Qh`FeS!ZBtm#}GDy9>C7DWddmUH~sRWZ!zceN=E-=vH10&$*q#|2@PRWJ$>JRX~ zfllmA!Jp{HJ=j)TRU~UH^wQ|h4v)xc8bEQ4dLnKm+$r2>sloUq)~PaX;PEOnphC51 zw*I;PrI3gkT!W0mTqD^}G#etGI@zUd`-!?zo#zqhYPWtQ*7@V}{|woEj1(j02dkIP zJvq~}>yD5ut-ArTj!>RgmmIEXF`R2%0*f(Q2}jt;OW1a%)w+xd)DzVHAK^lA-)h?+ z5+f12OIDNB(^)QJ)#41=Yk}*H6ZR4AOD6SWLF`DTMB#m!?9Kl}abvrK)mF)_#^b6L z34%TlUKc_6`z64{3reS0@K>-16{S%&`d20#`IAWqvV(Bve6IiIW}f9Lu&;O#(wh?5 zi=1k-vatl0{z+0ih_P-DMZ%9L-LBzN2O1oil4GhG?KBKtGe7V>GbHwxfO~@eQqsA} zJkr2*ZVH_>9;H9qoR-qIrK&=tAuK&|CeL=8$l-y!FT2+F0m|xP-v5kji+Nv8x~Nwk zeeWY?b+{QFPQh@o;s|3drj@}W%qek6HdK-O!|7eZ^B|ov11AxPjHTSCl$X7a*aAOF zq^te@UQ$#0`{WPfI}}OCi{PTc}7Xx{(WmQ zc1OLw5w04j0M#nr{BQ6Qdc|!_uZ@Q zid4|%<0eA}tN!3GT-iXLu@DADoagy#9feju*aFe+EUpyc^ZSbMAz}4z2dl&CpV?|& zM%Ln$r?ZH~0%!@~K1{fvtaT_3ln(7L=%t7}gOzqEyZm1DqsNk%DH;893SCUb_)DHZaPUZf~=fOab#nFCN-lPZuARrN+@6_Bkl>Z_be%WltpK?lO zP9{xW`B)TBGdQYlG!U=P*v?vfg)P-shQva7sV(c~5suXdQ#k zlI+`@*`{MM{Ek5I5uhwr-d&HZ(cYNawo6x2$_%*wo+r6@lAzY^RcBipJDDv)oe3}e zlU%Fcx56^!HVYVSkA#COF1KDhn3SYTua^ToUvfTBj zyHXUnyGH2)RX9>tS8(C(-}3kH-KV`ZdklQ#72lOmaE5}ZFj%@;xWX3}B2+sAfm&cG zwpGtB(3zIeFaIS;VMZWi{PbjLr&>$i)E4l!aI7;Y-E9cAnKGt>;#4G$-wbs4VxfbI zVC4aR_xyoHy#W;?$=nBMd2 zNfD>_0N|=ZYm(cbuBMn}A!17OKyGimgRt1Tz}MB!>m(FZ$G}|_23jmCD$+efX4bx@ zIIlsm`ba(Av~P2TvA=dkg(XI!dG)4dJ!VBp6(?DO2hZj{mdLHk9YV}!>2PR{_!4MmLG{fR5`%m2DTI$sC2*5 z3Yeos{S&=(JYodYH>Uaz7G&Bm`X6by!8rKR)E4g^Y@KJ73#tRdC|^6@Sm(7n+WXiz zPl)w=o6VVc&E-!wOS;%_zQRfRv>l~XK#%DKHyLCu&`{RD4x0nJ_4oPfdZ6KIJMc$+>&DYQP> z5T&w7_yoX|bJk3+Z}kYg>Sp2Z7M@8`_{6^pj88Qg*DrvYmF(bZLoi$n@PZrfkoOn1 z`F-q$jJ~e;YrXk@L7Mt&_0~g^EvSIC(imdQ(%>Q<>bIWZZvd_)?pUWbuB^-Jmkb$G zsb;toMeNeoW@{l$Av*CZHK}-f-%B&e=m_!1`(D0qb>9ac#G~s^M+CAO@mZBR4E`Et zfA&N&M4)CJ+u@Q0dTNw&BkLH~7kd)A@ze?_EDBoXrL}>?r*<#%2LV)JXrnPZutH_I zC4H9jEUN+Ki+!WEiv-FA1oEF@r~2mi7I{NC2u&NG8q4s3db7o~$L*i~dn);I_$Eh^ ze}pWU42Fy#fMg=qYiI^wKZ8&xBMU^2R?hKx0#R{MKI9dsm>+^DeySf}&U;YxIX?py z@>O;Q$sx1ft3Eb24zO8Dg&vbn`t5ZMl|MPW-H3&2{#H?^WG&?{r#mH=0zQFzaA634 zTu01J4(9M$NutE2=vMm4p6In>$6J3>Zt^f#r^KCDdV}B5`j!z~e z-e!ftRSvZ&xn5m*lJARTXgz_ z1Hj^zO=FGu=LlyeTMAqD1?G<$8>P9ku#Vr2F#dt-staNQUWMa_(61U}cwtyB{CkESGXT z(La>Tm`hg=eTKc;{M!xh(L-l)rLV zFXNi1(jJDK&C9eg-}JjDqB&XqkE&n`GZj-$G+g+`-K@NFfS)R&5aE-}p-~$7$HP{U zk-mibvw=2GmM3<7l%7I|fo$cmRV!{@z`PFAt|lWSMUHkK0hRcK_e!qgsd|E2%||GM z@R=H)n{H|~yAtX7y63T=dE={`Hbm*JVKAQG`nzN!8PbPr$TT(*-jI*$%l*EY7V`Cj z&!)=ycvz!}cK*+iq09OBKa$1Nh@MY#GWmeIU<);dcy!JcO)g5zbO!>@6^^IW>YSK^ z{Y`%lQXAps1>s@(!LEYS(l=rP?fSZW2G~2T4kB`_WY>vhm&W>~*=P!ue|j!+q@Mi5vf1(GSGnJ28&f)MtM;H3 zegB`fZSfZjaSO7WJ0t8A#0QV2en~qFDdehEw786yhOQ^q**WESj0nkay?#SLm+oE2 z3m_&H^lO^@=E(H-YC*u}XH*2h8ig-W#|)%}7$Hy}b4dpV{1alTCP1*!kLl5*kaI9BAlla>lhCwTmX$z}va9 z#D8$y{Zj*YLGh`-J9}X_ziwKwkR8A9B%S58?I=oRn@13-UPRUKw}9^LnQB^0mq6BS zcr((<8&j$y08~)3(i%EilYbfkSSZ#Ah!G(>jfaNFuenRsJAvM50gWT2kP0*(5%Zsv zdlsP1)&$%=c#Clg78|0-`&?9#6uAVKwXI&)S*^TZpAjT7fBlypaq5V9I@-DL#3s?k zFhYH8XdeP!`(>A+zVBXFMdJ<-Jm+F(Au5!woIa1A2??~S1ICj@bAYE@GJPP+SYN@WX#T7p*ahDc4e41I4}^!dqK3bh-x1iWr1vr&K<_0RT^A}T0j z5)NZp2m}<*!(ASugPL@}a>Ti)(Z7&eUF8it$QA&Lu8esIVe~V4mM8}ABK9jF8&B-Z zVvM3JE&8`$P;xl4^weId-*=r!;9Gr>fpj*SO=BSbJ!oRYKgC|n;rd$R&Qh~-iz$&` zjXn-M&sMYJcs^Gww3>}X&HU%vn_GWiR}$R|*>rAlNth7q>&)#;cmXx|+V?4H-6JsePmebWe{_y!W`iDNR)!#eRQ@zh{1D4c)xU=gGo@HqUBJHfb&U^}5=Mz|kRP zvBf2IG~YjV!yuMdVo{u>rnb^EK~q83J1$i91s#LBnFn9fuP^TlsNVu|NY&FL?Cbmr zMMC`NkBLl)XO87B7xBbfx`Cq+c-0cjlmjVOe}nl{Qbs~;luW6)T&w7HD*ZFMVo3coH&JPTCc3b2%Y?_V74G-c1&KS?_GzV8d2E2ZTl zi~djj8O~qBza>6J0jT9F`g4pcI@{tLz6JBN)k^y;)7;L}NeRm%vC)h;N-KH%1#G7< z0%PR+LD#PvzlkJ<*z~`bslKTm6jokxa7h^oSM{VLIR0!Q6^26l+sf>r zsP1+<0L23!hd5Nt@f0(ZV5?AqF`>O!mKA4Ct-Bf8ABX1~+ypjZdOE>wzyu?bq&Lna z)w78Xb|Q-Ui9dN?hy@1P-1@Q{|92Ih%-TH8% z!Q#pCCp7f^swCKVIU^u)yYHcYig}rG3`FpTfXM0v_$VRy&8FS+-jDIIHGWi9>H3i1 zF`vX-I-{dRgj;C#yCtCJ>P#xH0K*RXpkQK-(+q2{F=hV=OdS5o09-tt$3F|gFG)f( zevPk|DbYjaL*>=y1o+~UO~xx~DJ{UqTU3H&{N42Vvl;mwC`nocKg>Caur&crG47ba zI=PlQ1$=l=#w;Py_9F>M6v{W>K$+IH-!k4LF#>fA?}%Z(w(aaqG3Cd9AeKIL(Kw~G zR4_W^^E>=ieD5nhF2iNI9A1M$g9ni1(%%^aq&CRr^ykvAW8lFhgz@k$mwQ_k`%Wkz zkp3(7VV`IPzu}w~{pOz7NONvcbm4G8tAf zN&BvV42*++$-44RJOFVzwHTlS0vl0#OYm3$k1bt)pxc1~g6Djnxk)6nkE~ynev(L# z5I7#@l<0d@UO&X>zR6kbjESl9ozO30lvcSCnYJuqImBicJASi-(++Ba8vx~2-frVl z;Gspu8hOHQDp}|^autxolxfnkCie?gL{!=U9Pk(qUx#N=2du7_s*T~BGMsiELN9xc zC4w2K{Xu$Rqf!ME$eBW*`d13sWh-ZlI|R*qCs^EHe!6y89rtz38rp$i!$ZuPJr8j4 zT^U%e5KReX{?^$EEEDM|BmKwMkO&dAIg$-pvcbX6K%ThyT4!XE1`#2QGS%GJOodd` z;3rO8a_h->Bh@Y2A3(!ziXtXIM?}`Ecuy%Wyq{@%>tRHLY`0{l_`phG`F|p3=XY+g z{>*{8|1AwHeYpzcZ#i=MtP+X_QCw26k%w=3a&`Cpw!1p-7@QDg%sH?m5ie-nh8 zmhO9j1NNv1kDTW4U%qYQJHG!o%+`p!Y|}!?h_W*hG#){VqT~sF?nEM@4{)uYX@98z zBnyI?!(*xC)AP@zdjj@@JlQXFP%)MpSuu%oE7vwev$yy%G1{bvx1yfgCF?qff&ZZC z(-hGfGxTZR@647Zrui=Gos+RrMR`^~I`@!y8MfXob;-#rxA%N7Ef( zC@#1~+nCElS2VVNUD~y%e>UTG5smiqZm7A9Yf_$%+DgmzSdB8J!- z5lb3C`Sdy;Fd8N%uALS9)lXLwS?4caO^e=RkdhI-asVk5E(iWcVh*Y;dakeC78vPS z7-}!^*bI?JFa!kT25(3ZNZdNPe0U}j!+t@c2NgkpjZIEx(6^jBh~Z_Ha3vF%-|s*2 z(c3I??qM`Zy#_v;AS3KbVSM|lkpEsjK2D9tKzWl$fxqs4!n5Y*{#$Uw-iZjal z!XnDQ%El*90zm*Z?*{4!1FFW?Jm$1?k1@zXa{q0y$kR}Z;9T#5G_~AI5J#qm8BwSl zT22ulv-diY5Vid?;5-fE`*mT?P zm^Ry@v{=~xXVz=}v=BX#UPKb_TcScxqzlGaEG50gMb%r9^O)XHF{GuX&2g^C2)Xpi zAw>0be#}gh(?eHfMhB)becXrc&)RX)dB%Hv7y78m({dsu1o>l5CPhK6#ggIRm~b7L zM%2kBoD!blg8UXuLEmk?K*1qrJh|B#*$FTWz|*xeDQ$_L@m9#n(0#hFwF}eSWlOCC{~CL zrOZ}$=Mm*7;cHwyA;Q^DN?#!!VQzXPx+Lz4jYZnH3KaRfJ{kC^u9@_$6MHw8`Ks(`tV5V6DuV8FW|Jwtr8oz{)^ zKovFPI48rifk7mm$Gf&WXX7UW)3^j}lHHJ%vHbx+y0JWxj?`#g!S7cY>J0n4rKAW} zPSL1;5vMg&x2ixOaMia)sW<_F5d3lNy4|PDtvXs&Hh+|<^W0)4-tftUo@69;D-2@^4EtqK_L7BLJ{yo4e~ObU@coM-c!P%F|`NzHokpP#NmdS z#nr^+#A3MWSW(nbx+)fP+rX!dG{&4kN)WN8fvH;cAHEo8-I78Rl^6R?V~`?dBz@P>1xl%s@b%4wcA6AXb_Z6Zj)W(yH4daJyg0y#F059i!i-A{3mY;g z8b8{hGj{a8KcRHil%*IGT3Rw#`q^$JK=aP!d}ax=Q5b8ZYGQ9*0eZ$G%20eq2`U0$ zKAXo=9-0|l)QtXg1h(akSN&_ZuRXwENsyyrp6XNKP=Wyq69QuX&MHJBcPwtoNa1J@ z(o1Ml!yH-9fN^U|=CxLc6q`uEN%h+1Yz|GtX-KQ~`l0}(P6+1_2(TnjG0z?Bnn!Y= z%iL4-D7xik42`&YzM&Ck>{+PFp=o7k(jWHq6&0UFH&trvPs?&@7KsETv+wh}Jpd8g zYZXn)`9hbVgOw$$E0476P26@Zrim7@h+J87q)zW}-B3d$$*2782)|AvNy4 zwkwF_y4BfCG|3-n!uGil#@#fXYq}R%;?5b34++78mC86MUsgii`)DtBCR_7R$=DJ# zJ^8FG0ijDK-}y`+AnZR(pr5_lp{hMy}Ls&oFd_A0y1K}*vj}&IV*ONS;VU@Mb50=lSCu>oIA3kf|%-m zDqLk$29sQn`>88_`X69>AIO$E^}fwS93$~oA@_t_#(Lm?Ive#s5wjYyH=qYHU}2ui zpH5r*z=z;G$FVeuQKTrn&4pr7#uYkc^yzTPU#8PBzgpF@MX*(Vt&HO?rz73lDfR#9 zNwZ#0^X?vcUlvo%lW&wH9)=%f8Dwm6o}8B~a7b($8V||nbj#_^tN8o~v_b^Xzm)oN zlT1Hez!J@8YXX^x^BP1rQJUOobs7Id)1RYz?gqL=l7-fwM8+hVID)J0H(M5AB@CQ; z30$_x8yP{y%Y`Cq$>&7+{B_mZ5|XK}pkOvtQm#QJq|ITe5RY3a4{;on-v^)>D`yo< zu(y7=25C%MT1{|(BfPtd1yTK&q-XLaFraSP9NKeidcWO3WU|DwzIMfsge7*pRL$0! zCFxijpYR@D3(~1~P&YuIj^Vnjk#d=5i9(pTS6OG9a_|c#X5yGoInPA_Dg?bxgUr`G zlXZ02w}3;O${T6WBkd1?n-oTw$>#ph_NWyVzXAurkS*pHvXiG^&I{N`}{B}vQ8K(I=XDt-m54_ zanJ3J>ka1k@rwC#=}t|souu39K(w^TzBIJ)=FYEGH;cGg@xkkOFl8nl9?NXgIRqXH zmwd8$VN{&*7#f$ejJ>%EoiHGeYi%=bq^aY;Y4e&uYl~U+W78`k zQ;PamXLOGbbvGG4>kGgH5#zFGi8Ab6(a=L2G$__>@CB=s05@Gfv_xd=dyg1Q3XMtG zFGkUIa&T&X#fLL6a$Nb|%s2RhvX5Zv?ZZsN;yECl6ctmL#xxPvzBb?Fea5vZUagCDfcinj zKK(Vt^mXt8C;y|M1BlSaD|Mwdsn0&*NaLC+mgwq)%moDRfqxgN;= z5`6l7SO$bcO5@)HS8sg&8z!>JE&h2iW4DKBKfh+PHKoZuF?1xqhB6c8t{N^o7vem(A0)m)vTte?uHb1~QJWNn&yydxNw z>adme zDH&Y_1M$ii0J-m*3a8b>DI-(8W~6Cf*OqwccG5b#$$zii8ew;Ud_^Qg>OehFqigcT zh#^W=rH(i{wm7iMa+Ny(9v;Ph{86Rx5@#vwT1aMT2d%gI@|+?E8}bsnvJ0i4=jj&a zi#icUX4=@s0FK@d&}wLHSVRd^DY^Dk{nzxUv)rT6v2Z z4_9aBLp3EBe)D%q3pqzid3ZJE@nb=%bIk>b_aRLxyh{l;mvIP20^Tg8=gnUA53+C5 z$81t1UC(>Kaf!DCs|q9ja^AZ|{?n@w7o=ZoA9-(af?G4K7oFw?Vd2XiKFsA*r|nm@efl6pvmBVr1=wEG<1o^%0-XRp$}R4Z7dis?wdadgX?bx9%@(W6 zf!>FhP6^HqndY!~lrd@pa3m-o{ON5|2tUnJ1Y%Tq;5?R#>utUZ+-F{k~8yUfzB$NG*2L`yEtgi^&x*HkQZTfx{Sy)IdvF448sehw8 zWiXIm4O`mG5d;5AV2aXe|ab7A< z1v;Ixv$KAkYecLD6Y^?=Y#&S#?FR zM1?7|qe_DBMsxD9w@}(qA}F;<5Gz+ipV-~rsh%6w8zoSf;qP%eX~YdzbTMT7M zDAO0|uD?#*^-oA)h;#K9?iuy zS4ei097lsAWc^0mx8Ar1(wI;PX{BDu8yOPYO?hA(g5nDuyTBOIxgJ6v7A1&Cd|2Xt z`*K?<({hw7$MjALT1Gwkv$TT6=r;qq4NT3(@DG?$P}&(%x7(~{FDk_>icBVzs!3N8 zB=LCP?xm&kGTH>|D7WuKwW}d%HaB+Uf7=!~18|d_T+~v1{rpLuA3N@`kJ(FpittjD zE&tN)21gbeq0m;>+FvO`(n$SWN%R*+*%-zF_Rk?DI1SWMEZoLqe1i^bSxp#A|Wt4n5Cp zoVjy5?gbFAU9fj+_P~>Rf%(cl_`H$?r`G>1&Q+pM?kXR}F_}4zr`0NxR^;}ZM3$Mn zE1angt+ERkgTaXc?2VOyFA-B6M^ZK!Qbv0)Ttg0su#7oW_!w}2LH}$#sx)j z+1`SOJxY`w+Ryg)z0Vr+G=-4|)O_W}PGyDHL>rnBy8QmT^)Hozp8iN;Pp^oCZUwUp z*1`Ce7?qo$cELT(LEjXoU$#hL|Fjnp3aG^z2j(`YzX#)T=;Rrw?V;ZEkV(oApJo4d zv6AV(SDW{a3yicy^VM1p`D1e6m)sQJr?%-0q|)hEz3-3rwWB<~%_X^B)95)l;~k{J z+KM=bONeBG2>*n9*NzemMx&`bVas+;+RO<2fN+AX_}FETcubzH{(O#Gybakz;#&XK zn(W^_M<*$pBdcjWB~$*BCF#YJK;IF`ENU+L>pI!q8^E031noq9N2A+doqdbCu%id; zi3O4xnGOqX92KH29H|!VC<*|h_XQn+R-^nuXY5F8o!&sKBDYONcQyXd3qk5&JZogR z#sT~qX4?fkxw!z|pO&usxCc?7st&b|05WP@BI1WCx6!KYq$M(A_?%v^6|Z+g!ouUd zt%^F4S`xhE7%j!YJvtW%Ej0Pn2Z3L1?Jwf<|I)l4&LQB&W|DB#-?Vwbf#fhwQl5z` z_P7Od@x>RQDvm$LA0QO^oQ1@`pFVx87ML)nyH-|KIqvb@rU$Q_bI}9$S79~l_C6o5 z?~*Zy_WK6nY_)o-4s;mO|Al&ubyH8;Fs^cruo4mgh!4(<^;t;>1k1*pl4#G zz{{I>stj#2U-*R(sO8wTmr8xi_}_ET0&dvfR_9%cj*up_$A;X_f`$D@dYtAN0FcVX z(EKK67G5f>;nSpLqpV)g=cur3gTPLk!Y8Vl@eGPEH~}N{>ay4J74!McYRW!PmAv$& zMo>max2jIExxRFnc@a-QKvS=yu40a{Z-g1Hm7(C%$h6(?C(Z42lQ8?vR#;H*%%KlS zH1US#oG&o=&>1QB(?3KHQexw)?uRA&862{?YhL12{(aT61ou?O$Cy=7^)SycZV4`E z(i@T5VHU$4gIXKEPM)a_oWFpOjw^n^ll{4lHRwIaJ%y4y1_ zam^mXpcEMax6mk7FXsVNuQ_B2qQBQ7`s`!L$PmxsiwP<8h#RPdgE7$wpmaEcANxDIo z8cm7K_Qgj0<-(vl+xa<}PQ~-J(2{ zLOeycYbR~0Za!2DgkWwFsI}F+i+W13cA1*v8Oa8iwP2c(=rpCXZoCskBTLBQO>H?- zhwlXsCE6}t2ywp}7Pi2~a1y#fcbw3YL=lJqjs@Uu~9h8c9ri8S5%K7}I8(ig1cYW4{U4IHMcAtO(QHN-h{(_Y2CHvp&>>V;c{p?Q9 z2A=%YDGa383o8^6y-j&Dv9z`AqKL=CD@#*lQpio{C;D~>V!irE3vn{R_t8nw52AbG zi|^p~B>^Uh6PKpbnZ?XPCqvRn@Hl+5CR&7;kSt3bhI3@z3%ma$8J{9So_1OE57}>* zJnGWUq2lolwb9#|-}#-iT|@J!u_`KvpI3C>Fe^DwUHN@^Ub|#;SBMf@9359Y8#mvL z=87R;{*ymH+0yHOm(UO?OcHVDJ<2`}Mp#p7DZxmI%SwzE!uvjY`GP7Bv%N>$Iq&Z2 zTuC+3*4;`G%XI$(yP9QwBql)~3Oxx4iP5E)W+84hQ@~>MNGb?1;!ih2Rp5VyXonRA z)>Y(QK})Yj%=Vcc_$IIZ^W5z3eIP9@U0_-+^DWm7ovexKBL1vZv2%KQ3c7~e#+}ns{H6UYtP@0Zc$?62+mG!wl%%~kfuT*Qc;JbV3qOFkZqxQBdv=e zsQ!ZYEJVD4DJh1{{DRl6nkqm7MyyVwPQHQecM}55BjPtvUURVz(b{#tJ=!HLDEYWy zhfzFnwZc87Hh%z!rbzzSKjJq&HzP&BskkDDbpFfYN>H81EwGiGKqxoJeiWpN3_rhl zFq*e#_-k2MIDD=W@db)Nk*A zeg-e^MU0=o2Kr{k*8v0-_ey zSO##V?c3q-#;lbpW)a0T=h!+e57+K%E{tAp_GGG%`O7bph3g{-p7XZZX@LO&5T2;~ zPlD=ixI{|p2!Gx;BC1w{Qib0@33$TZhajCgKFcwpAO4hwln4?jR-ya^0c0e1bTrR2rkhQ?drFg{<9#ZwSTA=-h~0D zJoiQpKB!s5)O+qlBQ+&j0G@eSJ z?iEC~^_omaOqHqRiPj3_Wqw=G6waT$uCJIt$*E~P)4S6>*Nv{qg7r+Hut zu~8(js&9Rf41iDJz~7Eqm%^%CVpK_Zp2%7E^P{NMb5wX1sMNR z3kyH|D^P~x!fFBRiTdj~QBQYzI52$hU}LNe4Kz{eY?Mf}jQL#Tvu9Ch*ddxkE8zzG zsR*N}469rMFBrO>7{VCDn1ZAp;0QnnFI)N6FWR{isFiax;q3wNph}R2rB$Lui`ACw*j#vO@29ERD6`3Q zbpP3Eh|OHy6ZA`9Ax+6r?!2us;L#^9pC5Uu=^f)J(%-g!v*=NrwWWpicc@nR#A3jq z&Fp03%uS?fR!J%o$8=4G|DoqsN}WVo{489*=bz|WhL=88V0md5Ao*RC;H4P!rO1yA=vEd~Yu$L_! zkC4Nm&SS=;p^)vL{cBHm9d&3v;Gn~zxz0NMfCG029_R;q&U9mxdaoO*&L9k;&Dk~_ z)9*(cpMJpVGDEzEz!M;Yps|`7+}g;ije|pWVr;Bmw0_f*glg8On+;ngqFJw!5)HRS zCK^9iF+-QLDbMqsvk$k~GEl*zSL-?Ga$7nRFNRoxdi(~A;jL<`(Nyo{M5Ry;Z)Q_^ zF~G0j!1*KhUFn$Et9p z@#3^6m*x1m5rxm(r|t z5F54>i4D5T=>S39g=l_ERA>Tjq8(#SF(Tn%(?H{{R(A1tC08@+q3*N!LSEmqBuo&~i=Gg%dB!)|u zJ19)7Vam?hCw!&N#<|mz9NJr-q0gbN(Ue{M@L|+Wb-_$O%rOA#Fo>;;UNFE|(qB%q ze?Wi;K8K4Rs@IXh^b^0qqP&#Hm7K8i?s*St@!!w)es9{J=4Q! z&}B1q`kyjP(yM4eUN!k z?dYig@Z}6em$qUl6(9$nl8jVr?R}cX!TXBP@149T*AkaSmcOchSGm^cq3_3ERXEz+ zF|2w?v(6Z8+{Ir_Uz2~nfS@OX_RCbitwUtS?giWdSAuySZ|8gj%MZ=xrY*U~yFp;o zcoqMHf|;4QX8#$-T<1amU1+KA_uJ0J!{XnOhn>iVtY^nUOeocz9qW&l(^#GX>x89= z(hGE5NhD)TM4xS!y27Qyi_HZ!?EF7KhJdefqm|(w+bUDK>o7snOZHLo+DPzKyfCe; zO)^Ab+DAXPX%=2aE8?!Svb_nojVGck`AccNRgx;p(w%`Bc1?ijfD4mbPvTtJG3iQ*o`tPd!t?ki ztQvJT9z?&Wm?L=5bCF-f{AQR*sM*rdq%(unJg4lde8^IsvL{AHBAG(+9p6)Rj2~8gk?|xSrrf=0wyXTLLC_jg|an~QN#);)Coe_B7(?3 zjmT~hIv`C01C_E{YDXP}unK6X2qIQcXoZ^4@5X5}Z}Knq<=y-4Io~oNt`_j{SXxI=<5h-dOubtHmw1<{A3X--d4t}<`3xqc6_c$rj-?>hJMD=P4!q!%e@y@EJc zRovhPbyxR-(f)XguHGj}f6#^PdsoB(P!f-)xi#cv@%rEw&ZVTdT@W5Wi19Z6$(^6F4=IVd+T zyd7yQyvM+6_ zhu1>(C+FwIJ^`ojrio$2G3N_wBC^qTd-E6#;D!O6bJ0!!`)BrsAt0CiKk zq>*PnOE!Lb7V{bUg;A~_x!n#WKx+UWVrI~f!UY-w-s&&wc{gxk|Kc?(h?k-xRO~;~ zKj<{lxX#A;BvPSxyl|9nC}qXArr)Mh3ptOQcd|zY1_s(}g-7$!DDf!uokAZaBx1&^ z4iE)8vOUH1b=ZWvNFZQcnqh?<5v@dEHU4eCJ+iw8`s3b>EO>^BPy-?Q8wf&;Txe%F zsM)fb6MNq44^LqG} zDW^i!Hx8sCsj^C0r3P z03R+51I&{o=)?mUK{-$(*qR|uX%5@c@ZZneli+o}jj4AC_^|!)T}D9t*hNmu|07B8 zLTxT>8a_;{x%^5&{QMwB<$H-7ZCfALIDx!P`VqW<1W5) z{&W6&$GDDxuwUL-?}}&5XU_Q$t)ZrXi}e@_2?+`JxuTpF5)xz-2?^N+3IRu`yXIQJ zH)MA$1sUX-!6!lB1E!0jfjbfsHqpZuGE!zXIXGd$_JzKOzN(6dxw9jOsfDwdC5Mlr z3pg7INz6wC{OD-uVM^=c=-}io;v)|K&lw`%=ZC|baN7Tz;$bfi*H_h`m34Nrq~+(} ziD=2m|M%tKlQ`VQ!^1^{lhfPVo5P!z!`aQ6lUrC=n3Ic#lZWRi zIOD0iuak$V&r>IN`v1Dg|GAHxrMtPCt&4}PvlH#ZeND}rJw3$X@P`Ne&%gg_r-!Z8 z|31md{l8xeyddYpZ#cO*xH$jk-r!QPhod60&WTb4{;I032HTQpC{eK_(@AJht zA71?b>WKg9<^LQ7-7JA6#`!-(CV^GE!n1&cB!%=`PWpup@@|gzqOSRUe^6TFK&gg& z8FBhsEIOsnv|)Qz5J#-UlBES7y!h-PKH@&_m+hYS z@5_D5*A2h@omVRXuQx;vPTq^&{F^eqFG+;KATm-=C^8)_>b#tZf*`xz!vFb<2!>ry zAQRwKp@3h458%vBPgFUfSCRU-|GD5l$KaGNQU3Re9cYwG3trvh|Glf6P$T+(UHtHv zDFT-5H`sQx6sQ8ue{Q~={d{K}czNu_d71q7ZrRm%w;ZSlsSJXPz2?8VmHMUvjGND9>Mi#~ z2^q{wa=hGJZeV!V38xc!#sPPi8wQyq+BtI4;GOO~RMFNxG(FLd7nKjDO58vR(QiJD_0jLs;7j zFm;#-q(VkSe^wea{CTtUG_7jAbp$1FBgfmT{=L|?Sq0xvm})fc_OyAT<9v(jw-}O> zQmuDaP%wWtn9b*!9FuVN?Z)5s(**hdE>`soaryE{!M^v{{Al?bul2~y#Y$qL@Onn7 zng}Lc$%m(VNHPKC4OI zo`TQqe~Vu}EUKrdy49~Phj@QJG5*qF&|nqC#r?~rf^lm5*`=uW{`}?1Mo+4m_`erJ zO0VpdNZMnAp^>~7cc95Deer((CiE!yY+Pn-OH3)2R6hTisCQYCIb&scaecPu%Q$Nq zN!76v`;rtQLu-#Zsw(zxT$@7BX_YQuIhq-LK`}PuP~dz_nbXw9ZNGJ6+2tKSysgt7 zEb`+VWQUFtmG{RtCqD(9|726l5s8la_b1)FF-nw=e;nR0@4Jx`iK}!Rdi4wp&R5#t zzy0Qk;t?p&=DlPE>PN-RXlI6LPt5xhzRgyG|Dk5LkhZI2WH93&1*dgD&4QPDBF#M~ zTHQAS&Ssc>yG-tn`zV}igORIaeeUh>qf30m(RgO#XB6) z8y>df>d4fgdN$l0ga8mPIrqdX@co1WP z((pZ3+;6f>yWcp+y;YF&%LV)~sSv5t6Art=vJc@D;An&@u=~T1a1F6So>7_Yzc5O7=q7TRe`3K?xyW@9(Zj^j>LJz5Jxi z(OPsUEpr=2T*l$L(l2vXoaGe5gLn5n86i%vqzF}BPF?9wl)T<;I2yrv&#tumt5`G^ z|L{Yigow>3?PbZwFr}~9$a*j?^_eEeIV1n0Z`FLTQYC^fc$7j(^KMaj--K_3J(W^Z zw>lOfYS|LYX3>u11JJ@Zzn+odl5+(I2fq(3bpu<45CW+$Ma($*ioVGd_KgukoU;~( zLSTq4PA9$xY#$b=EV_lMOsX=PN+yeO90T>RlukV(U&bG?9h`yluKhXgBf?=A_)MAY z=btt45mIR|pTjPUXv_I3!)6v-kzxHM$__|!a+b@WZOpbcCk(cvm?$D(AY|-ne$cv+ zyQQp9iE5xnYufTd-eLYRh~k9EGAl{i)D>u)qDw!TmM9+{wv_zkVj0`mi)$>0a7j_} z_M#|B3-#da^w|l!bW83|b^FM;biT*3zsr2RrLqd6i|2}LHunh39-onM@O8A1(@4_q zN8%h?lThi1NODW3)-}=&TNNF$S1!m$GDCF~f92rPVzOTh1lja*K#%m&25@jLitI6aqJ`i~r}Ni(GA+jk7C`U*|I%S=jxhBCJDl%INO1;_ z*d4bZw@&g^RHr}3>G@Y3!lbZ_{ZwXkuNusWCt!huBM}JreiGWu53A%AiINWH^K^(S z?KU6TF?J>Z9U3NyITXdbV%i%h<1fP>wGew8x(fApm+@uQ6kbG&*QQ?!e;xe8*k>s` z`(XyQ4v*mshUXFVxHt!0uD#aa}xrNz~cbm2!`22&qy$GnX7K})(kx!V@ac4@!;AQ0@M z-dkgq+v8=Uco2liq|*2G;VeN4Ei;`@V3U8r*4Q0O&_;Le!A?H(^>RInujm0|?bCI> z?)$uMa@$cMWqbi^hwNbBjnbNX3%jijj91b6G9sC5^V~c(CTX7p7$@hfTMXMoJf?u+ z`=;2=uQfcl#&}m-x8B6@+7Ipt58GGcDwBfUM}cQE)};)1k~c0w(qJFMd>kc;^LKFe z8*SQ)r1|Z%jo_&qJSvf-M=40JrsKPx4U|h+g@CrEI^j}lSLi-158V=Um`<9ae+RGs zjYSp4#=5FjAN|{xE=dy7At|(j6-)gVpGsEk61;V0<2CC4k5Y@n zjK$%)G>dDSa;8tm5FMHIQ$ocoMTAA9r@ z$KZry70;*u=3ION*(FD7`8J(7&CZ3s@jB{f6al?YYU@gZ=+*hb{UCE5%rVZq4^5hm z9N$p4!D`s4eNVuPdbP%VV`Po_)kd55fm3rKn3iOR1r?ef&?l{?^Oo#;3`xiEAeS1s zq%-2#xMmUgWG$tyX!2-jyOZtUEy>^CapslF{rURsfQnK1?NE{KKBFHuyL=S)#Ue99 zj8~I1A3>bvE7hYIKD5Zp3xb*JGIM|)j-`W}^KqJ^{9n>>^5KL%_CX6($Ratr2o}cNtB>sqk!L; zL%T6`d!){vWRwPaVXbsFS5)K~m!i<*@z|vO7mT4N6cDZEXR#(E!xrgX258&1iv)}E zeJ?6ZdZZ{q(J?L=Q=(JVB_7pb$RVb<=zST@DcN4PAx_hJ-wwVB&qm23*d1a~*@aou zy$Tg#Fz_uI`TcwcZKzB{M_uA!eaPTrhA_C5Azht2cjQl7vfbZl-eZE{K!VJhB`8C* zys>Yepe<4!x%NGYX2k$dwr1=gf4TL%qb#G+mMsVp3hmDt`#qW^ZX-uNnNa@ax>ieKlkB@pzvOj2@O@Q4~$k z4R@bv8J6%lg_1^Z98(+Fr@r=7M*A3~jZK5p+m{(94Bnkg9bArOBy=zX)RrGDQ~o^u z7S#IYi*|zMeK;ypTVPTCQlN?7Dz(fu^-O<-i(v2lmv~%iBE)3-@#sfb<)Vdky2rK& zSc0=@*^uAKZ|*3RzbCiJ7+`AlwE8N3+dtbJP1h~c3Xd2~$&6#0Z)>SdA*OZw4Z}O; zasOHJbjt{tN3_vtA+xIYGt-L(5H5UzPPZpwVG{b`*T}ft&;pgZte6!RYyU}}U86W- zqX@l^Py4bcC|J26tEG9Q6`>?a2zuOc$JxfNboRbPv0;AUTQTbq%F;d^z1QEU2!B(0 zEs709*CA7J+fFB`q^K0wO_YE3J8vRerxsmH(^hOC%o}-HqGtJqV12Vx+1GgR6p~H^ zAR{xX3nAS)?w=yz*Lye5pu)QjVd%BL8y!S>Z1HuTpfaYW7^M3GB(WNrY9uNgbm zrARtsL!>$N`S;9Xn?T8xEwxe&1SN}fJbk+k%?8M9Bnp$^_H^z~x@05qsA3vjw#Gh+ zZB=Ci*mz;yhqu23$;Zm?R)bHiuE8X40EAtb=AYlJ+9rmC$Orqyd$9HSz(-MBYfe@@ z;RAGC_zU(j{2Rd_=DZn&!tX#D({A@jZEcq}$@OMD*+NQUccI&nio5S{sV90ga))&( zQaPP1d_}at4Jzr7mL_M)48c#R>C5<#v^8I>nkAov-<>ggUHPznU&#cE)yZu$7&I#X z!}$Et-!ut1^*P1HTz(>>#Vr}Y1O;-fbd%I-t6Q<_FPA~&k&~3U(MUxi^)376tPwR? zW1Ls?sipSBN*3FvjBZW{q;~m-P+p@qTa0Rf_qXSpX8E+!7Dvw89!{-Zyj`BXywBDU zOp1j+P&YTzU@jQQD(%qO&o;l{-sSjSRlABly-7x*(>+l00}@-l4+e}`nqLEN6^%n* z(S5+Ke}c$|e2litjA?;jnQaH_NKHrLJnH_6z>*&ic^n>;_hy@Q`7ob@k(kztf-8|p zH50~=5$9C%^-g5pE=m^mHb1A1!q;M^hVNT+h5N~{;BUChJHBWC9;V_5UGN%e@rR2~ zt~;$%xHGLrWQ9y-1;^`FH_q6%VEu%X63X4l--h69 zCaSVRqpymheq}w2e^2u58pX^sj-k>odZfsN;ze9Dc0CO5LZB;}*Zye$>+*S*fD1Y4 zoFe{PB`C5WL8oc%A_5gpA$i+MG_Zz(g!h+P^i!+7q`(7LhHGX_g~{Iug0r=zJwBU8 zftPCpeyF13?N@?{czcXFA3X+H0#XsaqSI# zhW|Cj9PHG7clx_j6Z)qF$@ohiwc8an(rB)QWzrBo}p43+e$ti+4NuZx~P!o%b-Q z@sKg1AY8Y`AbfSOq;?RP;#w=ps^iDQp8tt6T;O4GE<^1TgUg-srZb6nY9<@@ro3VpnX~7YKEy z6eX;Y61vIroHSS>Pis%Qtn?zl>t{k`)-iK*m4wBVILfI}zgX}xTuKo} zs}3Q6JQs-{AzPP@lV0IExL-15juZ>aZ4ga1hBOtNvfSl;A{HlJQbblWk~ICz2hc+9 zUq+=gso9XGa0gb27lPHsU+;4EXqHP;h+}S{vAhctzQdn6NFjH!!QOQHu3iks$~1u& zO9(bA?c;*>N3M8!RWF}GFq#-qDLQTrXPMHg?@3>9h!ZXipna;WrptQljn^%e^2KdV zN?1`cBS{M`#A%ER1HnfM2z4S+r#@RXO z&*&y0O)0u&`WB%fBaLu7x@$b+P6Jed$0A!YF&SeP%U!#`g*(v~N5bWn)~dAP#vIUN z7m2RQM6^-o6kjTIDy+QTyJWP8NE()FLgkP`YQ9{3-&GV_k5+wEqLveeFOfloIj8`( zL$;dY5tEbQSmZwM-fLwazxOonrxJ$T^8Qiqu;OvlthD(RjRKesx`U zqupVqe*RE6Bj*mVjni&fc9#Me(;-^SG($Wsc@;0p3eVA7TBCj6A=VfYcB}h!<9(gg!moE%>{_WA&PvCDCV!c@;HETPjdNtO zI?RAdJ!FK~=w1KY>Awq;gi@^+Z0s{Tn8@Yls`-T#fSqDB7I7YnF zA5-gFy$}9q{%AD$jz-BfpsC{N<653vKR=12L33 z*LVFreS#2tr9wvoY7r7V_S+g+S1PufOQYVTuPaxEVG)ei(|i=oW{@ztz>q81a|5ro zh}6YgR|k@7aqZ-9V}!%QR7=_DOcX#QNRYQl9A@gi3-#Uy)JOoJgbQ47_iXsNz&0{Q z7wpRNtE=7nAR!gX_EMWtvy_i^E9v(^D?NaUqF%^tDf&il9s6fL*(c|F?ah)fDhEg8 zS3dw!C}cD?lKM?l+CCApTB9?h9JNg3Gpg_G^K zxUNWCZPK4nnc+n^)ILrCv6~fE3Kk*YALEE#sXXGT8V6y0z37evf(NI?j0`imYGw<) z+yxue+1=4w+4VHgg5=GaK%;)Z4ySSGIpTd|&j{xPpE<#E00th{UCcI1)NS8YCFr()y^BY`m5C z_n#iLB^0oh?6p_5TD$Ty+CBxsTSckRfjYpXR2ww(Mc%%62WGYlMMyuj9}Yje2=NCa zQ)?SQ+v2^?n%^(k#(xAk*20`YFj1)iX1Eq=9t3dX4>i#}#P_$QA3D|s_9R#>uB4#| zf{<`*G7dnd0qTT5O!l)3>2qiI-;o4X@vO)YEXQ1=w5aU1lMzwhAHslnpyx5d)duvX z|4L2UHXC8_Vk;9LLMntHN$F!}@O5b`Hb;v|U)&?06tpH@6;(fEppPLLPB_$J8TvhD z6xF7cG1~u0G;&<-BR)9vCs5J&EQYw?YkvUfxs%pJMet>l1FIAwm>CR~52W4r@i*l) z0J~&Hmfqo&(SV_C2@B?4Xt_E5u~2682`l9EA=~O_nP&upB3=6{o_-FYbUfWA1^Ziw{;2 z%$9%gZ!H0!>;38Qt?we9+ez#xr&y+s)B513@C0xI{0q{JfIk7=*WoDZ+t$NwY*#&l zcCRXHagCmbdqh6mqeqKh7?A&wyh0KAq(pDSOg8AqVf{5}?Ul1^}`}s!sjl5?$(Ra5 zL;|+GdI^%YI^Z}$gQVrZuWYspUxV(?mu)0J zlPac2&bi9Rd4-^7;nmp;WP74eK%nO*LyP~=Vho?QMkz3k#L&%7{tva3Az3`0Lf@eS z9`xTEXwvFpT~IBH#WqX2-F%SRGKnEG^t8X@ce#I)P=n!GLf%BS(*lj-GuXD{duSZr zhIrHm(k19}B}w&9tRI>}l@lqj0czy;P8Nyps}FI&Huf_gU#W-bNk5Q}h|=&X@?>a5 z9-b!RP8FIQz#8ZIX!Ck`Met(k)I_KPd@t%6T z%J6(K3_q94H1xi`oEj@6iWamkO2s21g0-8Vc*eu^3E69pU#DBYr>bA?m{F9!1juR# z2HI&QRF?J?0Gz`q|BEI;#M@x%vM#sQ95lwgL-O%7D;+kT3w*`fb7L zMLUQ*_wtJi-hZD04J2J%vzX#OLg5|_9e~+Rm2?`BS%4Y2&HEhYTYll^Xwo30q?!{c`@tPfD}=MOhf0h|OYW2q2M3d1Po^po-lDEvzRkJ&3gn&>_Tc zdsb{UPLidO0=@&5b;xDuiYu`z48w3ceV{WxBmx<?49 zwN~rqeomJQBh5K|3Q2jG+x`pO;cJKgPD|ZQrA^UB7-=09HA3DtK!~kSxL|-fAL7fW3%C>gz};BP6r-BiWZC) zw3qL)E)~rBegnGHsxXTJshMoG+XMApaipI*@ww8f|{L;J)|}jS7NBa)#AA z^ym6`9TtL)v#VOS<+@P0Mu- zA|CL^TcW3y5keR;8GhZ}-{*te!dy zkF2eX4JEqM`Ri?;*VWG1Pdw4xPA5A79o^Wxe)`tzJZom80Qx5i%}xu@A9X+wUg|ji zc81>t1HzTVK87sMw0|qjP^4d&ajW))EdY~Xp)`0l?>5aj=|@t!bRxHO9u7zHB1=iX zj-!V7MEL_{sJi+R=x(VhCdaFTxR3dws5_IXx&6CezND-j8qP?CahK`pQ(SzYfx%hp)cRlih5!0X++CRCtg{34HHYrz zbN!FEPnG8_-6b<7@?_RJaz5OvN(_Yr5S6%b@OfiTz*VX>KSaPqFnktJTX!nu?T33R z9`Kj=*>ukYzj23;>l4{Tv17%mOIptC(|}0s%2%y!KyR$%eoOjyv&=WV;ZHj)R!7Fn zd(`zF%$-lGb`hb6@(MA|+pCO82cRdt@&eB4%Bx&RLN8ycOm&Iu z6=c{iz~p_|?&au&8H)>p4aJ+@gT*?j8Wpq%R5Ep&4In=kj#cYcy~Ltkk+*(fJq{bq zOq`7)bLdbUFd^Ul=x;(HcEPS&Y15?rr2x(86jcPGDUgkh)$P?5c>Cth^0eB_Pdd00 zpIwbMfNc>8<^&gO?~I`z9rm#Vj3+-{O7WY;lCB1wu$f$)07-QjZgUmp|B-gDBKeR$ zpP%MV_{<5>A#pU@hu8N7xC5S3pX{1UROl(ZS$baL^MQA+4D+qJ_0SGwfcpnYIHgnm z;|merYIABykQ=ca(nV5sv#s_82VdKn*qClodt*0a;YY6|O6F$7)i0e-P@lPX(_6%@&?28gna3;|2P zEP(=pc7gFl0a@-M_~M8$jcMWtfSEQcS5qz=z_=kR)ul`jEmO3p!DjYdiTB zQC+0Z1df}^5r7G`+1oDZK+FQ%0`!lcFoYeRAPT*|4u>`cn{5J-nQpxQaw88v=X-%8 zpgg3odl)kY#DTy)E#Bxj_jV{%n)uvO2v<=Q8hHia(Q81ekegWhq{oEggPu7YE(?-J zFph#PM^y#e=ntOwsm8s>&{3|*5=L2f;=8288LY%-LX>$4NH3!91<%pF1^}XtQ)Kyx zFLALrB6`3Op|vrR^Z8f`yYoBLne5Ygk7zS>V%#DrKruJJ)g>1`*-wE)<=4s|;v!!J zrMlP=YWK?iLVH7*)t_Rh!n%HV(Q2dZ?-s$Ni?t6i*l^O8k(4_-U|cBr80>)N3f*>h zg4zt*4{tQNjTwdi@j6`Wg8r=TIQ~BNQMu$PO);dGedSwv6egLmziUKa5uDQWC6aAl zXiPFQNA6_vyqhv`ql~5DZT%#F4W>&E*cEfM6O8D-u`=|GWm>~Ot-pRbj9T5Y6hV<7 zx-X={`r590V}ek(_pmAi1;eWF9of?1B|>CIJh%RZph;(N)DH1sT>n?>DFgVSP;|}q zF%1}cE49XTD&wr)&E8il-PoKAhlwlc7^N~o;(e68+EO)Xy3(B81o`iWKUY*n&pEZn zH>UasTC!Y!|6E7=s?}=vaTFQTlZ$?gg0I`=li+3hrHc7!P!uKZmv_d2&`l>BA*afn zgTse&@)uY>im1wj6_(@N2iYbrgW)cKLnVq@2b2!k92c)5rH(}bSY!B?k|-i2+g^64 zjqB!zzcLe%88(726+%>TVr=Vhv1Q|qFed|ls|pra)T#B+M7i{u6E^X-M3@);q)LfS zc#?a3_dNC87-xu_l)c1KqwO#=f^jZYUx_e57>>vKK1|jHZ&{nj zk?tEKoRYN@vqwG273W!9KIvRko|=OY*E&c9FqVVH-Y>%Q`SZ;78`rgiQwP;i=X>!< zyOW1qnwiBV~#v#Q!4;=}aEiV$0Qbg>QI|x)2={PKjxXIru#EFM(I#vshBP zM~T=yCM%s6v8uh{Z8{$@Kqr@=y|$NlDmRFgR1i%$tAzO;hh~HZB(Ff*de!1$+RgLd z_kj4*{n02q8~+`>HU+qG6RWb=Ej?#~#WkK(Jey(bP_1?QT)m0Bz$?~N5n1C1a^nW; zpAx{LAuBm1hT#L;ByJQ;m2wDrx+kVW(S{Fc|4hDg*bs(n=d8NKC2C^L5GSVebEAve z)lO3(RCCND*!Dz)f`EC7OR>-0TJ5@QoPJD!W&Qf#_%i_{ldphv(0)OZlLruwd`jB# zw^#-1f!6r6jF|bNzy2qxH*0XpqYT6<&enI}(+c-s?>QRElgta35kVU31AYuxtynM{AAaL3j5vgaYIlxhdQBn2u@V)@Yr z2z4V={LNv?e`u}s)~}z+JHO3p_#LZuF;G!_l#8n(?-D76c^tX*uo(^ZgymPmXEsmY-VCR& zI)}?L&A!3X8Cu@*U*E)b_U+M}8V@)CeBn1Dya9Bj+4|@auVGRCw?GXxDN}OvSOj~y z}X%Z*z7q;g@%iNfQ@Bi&g9RTavdwi>& z2wdHvw_yBRwM*1qU4wv|{PiwL7O%|cvq%3uI+paH*>U6W>cV1I&hXe`=gYs zrSY^T_?6EfezvIbKq&eQb0G6quR5czilFx7c&DL9Da~fG^ zyQ07A$%!sdZa-rDg+b?8f)ghZZm-)dA)9UkUs4y@l124lfvDlb^KTApn!bl8GqkN?$fmRw48Y?e&PluZNVHE0!RIL6S?}L zJLMrnrSLjf0}lPWKbKqs9U8%bct_#UfOVbQ)8rNX`VQ54e^>F1@Dy*MKOr!u2KIu` zu5V5c=4JgfW96*mJ*EsVqTHc`k`+0%A@`h)0!vlOpOKn-HAfDxwJFk_Zd^1M!>hUV|9jA(lxwF8L{o zI)i*&w>`++(ZIYxg)3+#ZnxeOe+0lu)~sTqqSUJxQvvnuXDpD}VFAZk7j!n+AQc^d zV4VE5JEiy9lSGMTKl>sDMgTd^XpC1B@;U7M%bSR<=-evVs$NOzxyX*{!%?5t=YiRS zr{b?Kyt0wo$c$H_DNGRv`PLN5&Ve~cnJedL&{{FG1+p3hd?Pa!FHG=Ut={d zOznD>0FsjLwKIJ+gT$)t&qrvSdJyYjT4k#^Wq&y>z6_@f7k%JDLVT{&e9Iplku0zB zo(By*xbh(ag(=Yc)o#xKpIy}o`5vtxN*NHr&^! zz8RkL-ELS^2=+&gz~PWCr&O-&k28MQE`z*4nhtWVpzj9Qe*?7I?L}FPq)->(<;{!~t~Ur8s9uZY);*9} zO*ALh%J8$@e3Tbr0*5h>dmWx2o#`T6293HJUY=ZfFztOhs-QCbl~K`Dvw8p2_Vk<^ z?bWT|Oy)-Gv)$JcP)A0k9bnSGnApG zEqHY3!0X%pDJoL4-lQ<{Rzj5R7(Xsj$mD0EofU7L?#<7slHPtmP&Q%}&s8#dhKBZlEjE+e8 zT%?t2Ow^X=N?j0s+l^ps2%zhcCP-yBZ?rt9N(cx?dSAo4rQT#Okt*WOo;qlkXgt>X zDSc1peT}b^?={ssM_E(0#AMhQe|uCR*9Y0jSX`dJm|5lrGFI7#%xZm6&AbMwgXQ0E zZa}ux<(N_HKbFAsq$;&b2I;KR{q*BIBP`u!>={EFAumHO?+lry>LyAB0O_9=y*#m{ zQ_@A6vqT6`tOH0gTInt*h~3gcrv0p zHdWgsxYf!UA~-UsiTE4*n#j&urQlZyLuz=e3&P*gC9?M3tRUJz zejqaQ_V7@p=Xb~){k5`Zco0Z%)wu;g!KXi8raHMu?vddEP76ue?1p(6c zK83cJbn?2lifE%&UBD@%qYUGt94~L zw(AS#=M0A;QANHqoJ_79>$kowX5vcwDa54mrjOmW>lUL?h?q@?r6;xDjn^PQ1D#>D z4DuzU!3|@|gJ>Q#1`dDSlQL$$sg&H%!(t|Pw;1W?-N}&b!y5#*7$#dZ&qx-{-=#r}cnP}*0;0JA%&#V|iuj%Ln5%q6A79d#XQ}j|kF%5at{NNW+Xv6|2t?&8Wh^wd zmNG0sPhVLt`0An?;tQh?_2mq=wILZv`5VI{2wH1^w;Xx*OItQS$Sz-=7;t6|adc9J zIV2A#Y3~s5R6I%gn3ReChzH^9G9V}Tw3}eScBJHY5j%qrM)GB{*Q&PqVl|@z@6z1h zRfJJASz6~mW2%uy$W^{om)T_M+t^1x$i;lP)?LZHrp*J2zpzn$t$&vyf=8t3reRT9 zMz#d)AGa2a0Yp-R25>{fz^hHSzqttst2ul2HS;CI#% z2KTIyuXI1{X;%bNKHsuH$#7W z{~Lb_rs{%>!0|sbiRhXq_~zZP{Du)RUki;S`aBwR7ho{dGz1u$5>QOZC^n|;sJvRo zOea1}0gQu?6tq43(b{CYMV5O&{ZI$p9IYCDe;a{eQ?zaOKu>H$WK}E0B5my}qW-*- zP4F@Dq@}UtJPHc=7E4AX*NK=J=)X`$^xV6@&Zn+NdoY(H(BZL1n9SKprqz`YPmUF< zL$o}J0Fl4IL#t4p%!T=?FTKoU08DQDOH@C>jt2rioL`i!mBBZ;XOu3=&i;>#X1)|Z z*S|2aWI9IKl~Ie%SQiFaroxS1a%M>UL3cM;By3WmNibBIMd_<`P)<=GPUmd~yr7wU zwlYS&QECMdIgDWR3?RkJ@8Q8ImJih1jr1ee-MW6bB%YG4o!sMT1czZ$oR~JCv?~F} zS!}LmpoXAl6w|yVIB5fka_yoInjC{ZAgBS+EiKIzeT>f_$MwN)o)Fl)@HlE*==V3= z*1lhsL~cJ12Fxh_s0CVeh1~95{Vp=nZmc=fSS)|#}iUtuD03Fv?O*b9!!sO ztgbI|{%sL09ZtkuSM!Pu44zr&E`ge;0aeJ!VgpDReaG~2v4n!M?vfzQAk+0gZ{{15 zS1wu_j6>A?lB)E58}LwugAur?fDjsXFy5^I&9$JWqaimDxqkJNQr^q+H_ewBMO>mn zz0;>BN<5sb-O0kb$sCy63f6T$IND99yT(wl-!e6ZnNVLl-?yB0Yy?WZ?tcCK9B3`* z|Cq8mmc$h=HDWo8zhuv)i=sYbZ43(&`xKX)YlVCF7wRxwi%gLDck<@zb?H4M8fli) ztS2KBm0T3XZ;;=A?aJGjNV#LCRiGE=dk~OJHH15cMI1_m$v}>~| zgbV>yD%oPbJid`YVnF;=09GNE-W1Ea<6#Ve&e?BbM9Zd5HO`A+0CRO`)My zs3`0blnx7R|3LlJ2N{WCE1x(zzVTO04hH-27f5Yjj>F?5&k4<>ut0V+!<^?2hA5o~ zN4^9hRSm7By=_=`r$SVp&_ke3b(6-Q?9yjWFRZ3M8Es5o3H4Rv#gEUvNd2r!_fbmD zy6N}c+;+`Hh~XTo6O#{0#_P-lLb^v!N|IvS2=FAUCG$?BEtP~?!7~Wg&|))G_8Cxs zWm}eb2p8r40`S?D&+t=&ai&5~9%(G5B(yhh2^^z}SXO|9+>kzlxYf zvFnZ>FObE+QT#l1$AF@=AsZG9&t2Tcsj2ve++tAL8Ap!#ax~3{RptBi8sUx!6?u3JNW$WdiX9i zAshs()u#36uNdYLYwrE63$hb5uTZC-4O37ZIK*|2Vt)zP_XqK6o^iwfrzSfGpqQp> zO@_qaA&gv5>hVCVzgTE<%rb6Vb^(^-6Y(hIl(s z;>t$XfbB*A_D=!YOJ8e#!)W*%4+^`VDHS#{KvPWLd>8_c2bqf~82$-Aek19j z5&(l-J{UJIFfI#LYKbfT0Csk`hDM79vLo& z^cR`^AO0>4@18Q}XJYytnKNleOyqYDHZja;Dcx8h@7?J-?n%2Azigl7=n!&zbZ_9f z;5RbrMa|+eg`iUgT%FQo%Ftfbs9_4fv-FWq6iv zGiH1$+Y94zK%wXN7r*Ef8`S`UWA_*f1_b|<)g?Bg8os(%b@bNINt%P|$sI8-?3Mxz zHEN!QSA{Pu5_s2u`_v3nr_jNkpb|&Y>z}OYIzMe9pdaz95a--xwC_|ETtGa>Qi418 z?D=xP`Sge!6>ypn>Q4$RH@P2^qEg>p{j;B{&Kb%>;SJxmAw(_GdJa)ZQ&R|W_6!f85b&clctAjlw4Z2JMtLS2MhS|dY?3DGKJKxTSe zLjO%*S6jq-BpZm@gz}ldMRX!U3JH`#5^#8yMwiaA`oa2Vu20oQfIK9EFbp&RFo1wCynKcSN{NfbY;l@DQc*Eg%5+3XDM*4{5`fI{$Nyv)nEs!~W??~*YhW!v*ntY$xh4BeV0>anJ(dGy zZ|X>4-mTLS0V5h^`8o(+lb=VRVs$oXtPTcTL+R{#OcMR8gQ>T_8UM*aEgp(UnxfF! zJErAtZVKqXuBIqMUC}r6Tiq=Ek#h(@XXFDa5wS^|9Y-VbK>`{=2}}BAgO`u?kFYMD zm{(y4Wx2&%UMX!N)=LW2q%0ZQGvC1P4cGUOs z6DjICZMsmQD5M{5peh(_sg+tEW5OoN+2|GpfUlq>zSjC*tm7)a_&$)YWpe^yiDb20%wSwRRp(xR0eCV^78i(`!g>=SwX%ihC z320}SL42v+ahco{R)`ERwJFg3;?OWOqZom_1_CWH``4Re<@>wapsOurYj!C5MRRk=NCx73Cwqrm81iE7+wY5km6L8;f6d>xi-`y9BKar zVy*KHUq!_WeW=faHz#sY^l#&I#7V}io!EoSD!f6Nfx+b0^jm}&@`rX5bjZVt+@AkE zFZTV!hFUKtWyEFxSzlQ;qd?2Z252#9>JCU?w6BFO8?i*-Ard>Ev_q*b9wMtIa{W-=9n1Np)Ap_ZOEjm~!A)Xtv#B(lqKPv5I!U93{XX0h=d2z1D6a?rKw-Qn}BiYc_z?R&KA4Ez!HdM6Ms&SLkii4kAls)`Oh2W zR`i8u2A?(}!O{-A@b&mK9ih<4?D%%q$$PeZgG#OU2aMs*C0imoIofx}>dgBI z=;d1`L)l0nmvFGNa)yR~HFEfHm|;BzPo{AOHI-+#K)g`S%EdHeTX_NjTjK(#DUTtk zm<5x!Ut}@_c1ZbPk1C;U#{=s&QqNR5Rb?lJz1n6pzYA2xFfMtS*6G>bH}~L)F2a>- zPr#ZATkGf66oHb{+aQ9~A9{08&SD(5E6JAf6#==|B90ygqc zG?&pn5OY9=VFD`6f`EDC16qjujyY<~Rg3fXEHFjQU64`U-EEY9NSFm6TG3A3h3g{n zt7yfaa8%^D$i76H`{h_p;J=Q1OP9=3g|P6F<&L8QPpHwrVOR}=%|Vw@ou_LX=K zygT^wS#n z`_!6DCjlz)#Sa4V*OhV(Jn+NPb%5+ZP02Hoax;0%|R z8sq&!unF z;d2DatL>F;Kqp_=g76}EgeJm{iWL>?AcO_=5>SnHvhWU7nHg0 z*7@Y2rW1Mda~nA&s$$9UZo^Ob-n4B=&L;ov8K_yuRy&{g%>{7aQvVFe+~G>)>J)RO z0<&sn?@sam)7G2EL;1b`j+$r@OVZ+{cOcVZ3 z8#;E-8%*~UdU+V>_r&WG;vOrg`;6V3Ff>%4ZNTu!v8i}?I?q5GE%Zo%zOx{1W*s`Uuw&~m6cIa< zu(p|KXTPTTtwKUo`WL)}po_e_CoxauJtMivn*(t-FYI}V&wNj;TD%4yCt>k`5@B)! zWPh;ZEkDQXurNyDe0zXIX1lpr6Lp{0n@VHCoc-Uwm<#i)xfim--+VH6{LQPHq}2hSJZW3HeVsrU=w^Lcpe;rzS8y`%+ETTrd^`V+&Vnf=m6^WA0}3Ot znJ;rKhZIFiqp>y+tooLxz(`w9x~-3C>-*r6IVm_r{Rh@rS|I|rp16W$tC8DdCj;%n z{#X9nJ(en*R8W#5qVkIws#1&@oQxV zi>N0D>y?Gr@Tte0DX`f-)tW$ku8i0ZUNBVw*VX+K3x%3rwGj@g8y;ocPB5SyT=vRk z*8ZaU1$wsVQorXc3fEw%EkKLwU8yk5}~Mph}px$fZHWPOtVa@82{peNY+~j=QVJfpo-+ zqQ{HFZJyq;!WVdDvJ3y^r5M{AbET`8F9!Z9{{XD94k&m|+?By)+QJXqareeHiS_$VG8;x!yr4_@d`qC2_tC)vXW}}53+Z6Zq_Xy6m8E-=JQnLi;@pYd_!8(P~AjQZJ6FBh8Vn#}lrFUFW?& zks#vzNFj0$R0Du`T^*3EBj#V=t%0iQvin6=(88yGi*M5@c;P!aAz==a)37)7$?2d_ zJt*S3K3crWeE;g=Tr)|HWV!M5diV?vqHqobr9hhNO_77_A|@N}o@_riT5W$u0Gu^Q>yJ@H13W@Bnp(kl=Bp%-TSZ$&x;h+jaomC6GV7XcTL;|=G zUcF-$P;CU=x}?>?l(_0|s6a-?0vdm7oi8mmWMncRi0T+otVZ|+ph?-`p@ zp{QKIg@E5JZF#fi_1!q}T04UTRaW->%`?*us^=t#1LCs8Hfh)dHY1WQsH2~KFYVaB zv@)1W{InTq@!tj(L(Lf&KErzBScO+6S<83Q6J?FPnG~q5anfDDypS*b^(28@$9g{tD73+Pt!zz5fc_sDzA|>Z$IBp-X52b+)JtZ4-M> z_DM806!J9;c$_&eDNWxnO6Dcg4~WU;`AZDfEgPuk=kixE`vjt0Wjjwv+LhtG z_o=*o;U>jm{q{UOv*Ex$pAGIi0=?j)65unLw{<6WwMvKfgQF1T`SPsq;{#;!6v!ST zx9+A0r4U4J1*$8+$gxE6PDpR6On~q=|Jy%!G^QIa`MewKwua5;?RKqQU4XMv_4a!R z2{;ahY?fk+hqJG*_*vx~d(mrL#xz}b(ZUy_)b|&Xld{2H3ppA@)nOXwK=a6ilpM*nT(az_$I-o=U_BR|C%Dvba`f^8opX~*3i$BUSBHR@5`$`JEQhTS1aSz%stJ}-v#C&2&-14b&I>bCGWWKve-r6sSFCsMZu=v- z%*p1&#pEvtexLQd+oGIJpw05Jqy!Tk^k+P? ze*O*?adkr!J(uf{b*b$)Sei}#zqb?#w-nqXN3>(Vz6j-Wum{1oCHy7vy_qpI{(6ig?(N6@5 z-|83aj%el6E=MWaROl7(4D=^fX)`vVo-X`Duuh$5)QzQku2}p4wpmNMQWksK!(gW( zW45o-CFkE2F`RKBA0xegv9m9NO(I`V|KHP6Iv|eIHv0h~Ow4uwPD;#|r6=!YlpXO4 zFR*z;3bI2FVR*PXC6FI(7FM3KYOm*V9e!I(~Afrofm17U=o!&jS zdK%aDI^^3;q9>qT3^#_pEoB@zQE5H&Z7SV)`AfB;y<2%utB%M7ouLL?(&rr|;0v0a zgEo2*Gn5pOLxXRCM*sBVLp{M5d>T3;kTYi$WC55LM;gbUWICwIQ9JIPzwt*wWJ}J$CPNly{gnANXrcIf#pgqVlzjW8vJF% z*!q(JZ&CWvW2TE&e=lWPaC?^> z|5ju5&p)=@eZ$VUR`(VGX&J98g?YglJZT^0s(A121IMgQ2$cprgdC0-sw&L|e5 zdUX!5Dn+LC=IK+H1>>??GZjo@hXcy?ejwNgUZH26o$#A1y6*y;8HTnL+VA3>Bel1s zPLCc<+!Es7_*&5-tb6%~;lt~lt$O*aGXddE=4UmPju2uixv`JEG6RQS`2!WcnpsWm z_5IzcsuUxo6h9KfaqaemQH1&)G_IudXdkTj)w?`?o~_0@BQTSq(c1EBw+t&fK_+6a zmY^wrBh)<`KU6&EBZz)stEM=O)GSFUaP_RU-cuK}rxG=d>}6CGU-H4rG8E zgMxZ%=es~AeWi3CF+sI|qJRJV>N%&N&1~Af{Yb||CZw>4!?CHAuA~iNJ0R}eT;uOf z#W2)@7kplP+Fz7Q6ZbnM$|2;cZjR`J=Amrco>9W>1`pK5og#v$3wN6)+qF1U(Ru>n z+#A590*k~ljM}NJCT)0rzH?CZPJq&~>79Xk#&E@i;b~vQKN`Jt`IZCrA(Da8JUv{r zaWm{;>mdEfzn-! z<=iZYig*OE6A}q^M>^(noSxJ2@|<9Lg&5L3 zu9Q@39VOQ=g}k0@$vk*=^Jj9yQ>P1Ro_G8vapd2MC_NiShS%!=e#XN&<%~LgMY`vfn&vX;%GW_$KLaM3cQ8} z?#+M2&087o{ICN@3HIaHpdO*@v}j{A=YvD0={%hq+K)@Y1oimDO3PxnPV5A=Y#w&_ z-tT-wv@u62P`K&pqeaegcIAS>sXz>6%2c&BV64p2t}CI$(6Mgyv>9j)x{gEp+g=Z9 z=20F6wM*Z`ILaW@uP_lH%K`AZfvdc~={*2a`Yak^25x_|l%ajn(0|JGH-S*Z&;x7W zsdC4lc!*;YX-7*8jDM@kWeU0x%o59nGE47=W<=T2Q7JOh_8%yJS%`Jt?mI!J0iF!t zqz%}2z$+jm%Jrv0GlYg(RzS_t=02?<_H`W1sldmEDcmylu15KxDvuqj9*$K_qjD5@ z@3I+cyD7|UlvwR%_N~K~NX|`ZFj@R2a(H}X;g$NeKlFwu$MaJ)Qp4Kj)P+}-bO{6E z99h=gbtqzX;O5N`XdEJeD^$Eh^O>+Aq+-|2iveBJ8D8`WgA5;DwB7OVVas3_jSG=+ zs3Ex)1HNAl9X1raN@>a~VK>~RJDpab!qER_EH?x7c2aYYpCCvX6}x_1jAlcPSG%iIBw z{~1v2S|R*K`!l{W%HF?%kxU#7d13(s4?!QNIS{+N`fU4`}Yj6~A&a~M=-^{5#G zbu59%Kz|&1m7MQqzEbs2TaN;b^#(YD3Bz09sQ+6O>(8d(rXa(WWap+({jJub|MB`C zh>Bs}pATyHXojB25|e*z=ocu=)?K04{A4;~qZK)*_Oqe*ls)Z3h|8RaJU>#hSz%TruTG+^GE%P$hv-b8aAF~f*hNtk%n3q6xQ^AKvg@Qg0|*T#taKv_CTXk+3c z1R>2(Y2BF4xox;dMgVONL8GbR)rkYet{!&!*9}|c<7hl2U;e!v9rIW5`mJLU(eKtP zr$axs)Y)l!KU}5?wS9RpI2}L2Q77`5u6WhO0`@VC{O@}9c9=uFO@X&SWjA*>$ zKpL-j>+-wp#WkE=pNUbf@!DYdN~cJ_k{89Nb$xFgrpDw?Mu`b{T>b$-qsSA?(WV*z zGzmywI}eI({6{Q+cF=wntfn8Qy%uqZ^HUP2FoHVDv{!VF6gb4(s+NbnCUTjYk0uLG z=I+~|q{a6hM>kedU33!Ny)^(X8=>N>Sr zix&G9fjy65A>H#@oJNkPBwTrkp7a=9PAn4c~$?k`{!f+w=FTphH_e( z0H*aVX4rdnTmiR2W{JHW*sGZMVZ?F)zPfY$eL`rz>|vYDgpVS!??TO%Sa?~`sC`|N?< zT_b+`Naj6#OYs;t1w947Sr+POO7Kv!e#Hl7r|>@ZK)4kLpUd+a2;LcrwG_yMAB_@U zqA*m{b}0JOp$jxkpwFDB6G+q){st6Mq6MZ$Mg-xRgJI!>pQK~685SfqH(|zDa^@A@ z9|3{%WXIH#M`?8Jji*#yq|2LrI?PJOXx9Y(5cwcco#J@0$)8$};HX+sTbk3-XN@xNqPTz}HFMUPFw0zOTWVEA6cDLF@U)LpPH7l))vc5X0}bL{4;B9;c6Q>t$AR zz9WmsQ@s#V+@TDu4MCVF*Yn9Asz>z=m+<8~5k8KO`j5v`UE7Ad+`o`Hv~N_iJ~m=) z5y;jHE9Yx7Y@oYn;mC!_>L+vWVtkG(`W6FC%Mk9471F#+;K;hb94~({zKxI>|A%$1 zv$&?w7~|@CSAgxpDRP_LEnoA#NRMB!20n>vlAo)jy9`Y+;W1SAIA`yz?<|<8jXlFu zil!eYx4y$%JQ`6B&JDpD2{#ZsM^R^lYyX_^sDDS{YGdNk*}U_;jMV;P;JXYG2eHppO{pjO&b|3lX;La)rx z=J-+}*@$Ih7D^(OXP2jNOh_1SxxSkMqt2i6iZ_ty5s-4gOFa#U!AjZOwSSRJq0FE( zHvj|(0wFLPZs#vY>tp@eqt9dBC>%JPd9Tqai54XAw&F!xsy!Jr*UARJhxe_{G$`km zSKpC#bW^ZQ<@K=GCON!gVj;2dsq=my`{JWU@fyh4$Y0LY&1_h?dsxn}v7FZb;g1!x z0d_+S(KRSfBlSQ%^4cvH+FL0#Hi^%vn%61Gt>RTA&39A!^P5VSS4W;cxXO5oads1o zTbcYfJz=rWAV2h6eokL_HlCn|bcx)x@ihX+`e>85OhKkOE{co4fxjR$jz74>9DwtD zJ*-uGG{4u_vs0^H7r_#@sgdd(BYu}-1Z5hmEHS{F+8`KopTam*U%T|#innbAw)}6q zN6`sF%tA&;YIiEVW<`&sAYSon@+~Jt@HPeAI$alqtZu|np*&61>6rQBf}?#dWX;u* z89zE*V%~OJ_|=tndA>yd?p<0Y?)f|CU%cQ~IS)gBr9e$u>Mo3Y&OHSKDW^x1ioK<1Lx*WRbeAgM|I}Vly)oODQ%I=4N-Dmbb8deqQoT3Qz z;ExC4=DiO5;$tQaw-JA-C86JpB4S<&DkSjE$kcCODP)^5K zVs_4(l^i(?^<<_nSpZ31952fief69jH&2H!P(Yltm0$amB>W!YRcL!s5>W;WZn0?) zB@G^X3hh4ciVW`NXW_A(v6neV-(5Q~Q48EqGaaZ3ZW~a&^m~w+5Hc@!qAaynkKEg; z$k}n_q1lgfk*k8|%0#+9`OZlioO$S6B!+&)GFDEvk?{l8MBsTtd;(@u8DYXe z-^|95r;K+>vMR-M9^OqwU6XEqe1TxT z>AtYTm|2FwYGbactkj)xegbO)2a=tGWp<#7>&~3Rl#~X9rK66OJ1farN@J0yv8}g; z&iLFn_(?T(6eK^Ur%vm1VHE;q>LKnKGRvzKKkrsxHgSj~h91}v;!k-#cpybGk$=64 z_Zy_BA#svrH+D2CKboPFDUjFqIh}`$I}NoiO;>aLmaJmSxgd!F33Ao=JDS~TYM(B@ z2a+M)!~xmsuL2Q~)sLOQ+e5va`S0A#%>RF0M$gl79w9$nO#~I0ionvg` zy1cCKJ0YFjhh@SDMco{>%M;lp?A z4bi?X^v+bTR+9EIe892KRlyQ7v`ewAyg(bz2WxHkl01hduDCOtec_;j2qf3ujGuyB zxvIpAu>1bAt!m8VOYr>u03?2xUV7?<^o$eH*+{+L86w0{<;Auon-ZWn3~q_fb}SBj zO$Mqxx|5v+aYB6?(^bGu!?dGYHh}hZGHB5ok+B;dJGzuPsqUgeb>d$WK2aZVz#cP(Ix$ z^enpW&T$P8F*(pd8K*eJGE-CLZkyt%|LTu5g3R%@{hfY>v(Xkjhuvy%Yu&G}d`(sq z_e#fiW<`IxM0bVG=Ftt^EA2;63Sf2Z4xdd7tkIPgxWsjc*KPaGqDQmOs}bxO5$*q$ ziZk#@J!1n?$v7wNkIer?Okq*K({cKk_*s}MT7Fhp$-NeYwva?;2V!@rTLN8lXB>?U zZQH&xzu47D*mzp$P`j~@WnymbC8S#r$kVUTr=c5c^1*Sw{e1?SWuPM zr$qMMYyTM+-UAp}?->6LhFYNm)Avwfs3UTC`%EMDYkXYb2!wSDkDE}iF~7i!KetaA z!A#*31g#7YAss3mhd?&sCIu=aAvb*&&V9%w+dPt~g)|7xe*24Y!I$~1>)DJ2r}DFd zBMdh!I>y_cYY8*R z=M?^^_h9(nqmUR_iz?7rc1Bg<0y148SE@F za!DLFe~Ui+95nn%iHH3X#)r>ZtnY_Z!v~Ag{!W2>JU8#moL8{J3AIW6N)QNWjpTXj zn9rq{8$|(YqT6ZPKD~Lu%9N5l#7YU7RU`GQf4xYDTN_`d^Dvj z$+rE>v3p~HasGpHK1DvNOHy-%GW`G)S7^!LMKAm9`!^9yT@; z)MIl)ZtB6eZu@)j&ey)Z!lja8eHiK1prcA&C;H9f2v}yaYn=L{-L?1h*H{c*Det7n z%07@nsai1wCwWJJmt+g1!;xk^qRd05G znjkA1{mv@;Sj#XF^P-@TW$?n~j$y3CacsJ}G{_xV|2`KwIY;jc1qi% z)YJTTAjV2(zFi{~uDO|r#xP41pgf7{yaKcMB{{{{@1j^#4g)wAzd|e80_P4CoZbJp z;?Im>ixV-#yJz1L6UCzp3Rh0A%FLGxC87eE(pTBCPX)XKGyb2-M81$D-h}!>khCOh zFWuD()@M2KQ3yjrO(IS~mM281aqj>V*)6GhIV z@i8$o>~Z$qc!ng@RX*b+lCf5@rj;==%-bWN0c5(c(WZv!#rtbMtVK!O)HgL_E-LE2 zoNVv&zv>NzL1?hEDC_0F!Y+DVI?|<8^&)H#>ATeTy1!tv;u;7ANAf~8W+o>t964IH zBSk{V3{Av$_8Jh0HU5lARN-jh@Flj+DyYZYannN$vOlDjt|m7K3fRZov&d7G{a-p2 zwH{W!-K{%GiYm=#p@0LyIv{?!kKXs-XZd#ZFcb33cq$a>P)eO_7+;@X3d|qzqf6&t zXERQE$#*GuwNj4ZC?alN-#dzrJN55BwFFnuNI3gt{ZiW-!STnPyKHCbItmwCA(5P{ z;2}OKkWYg!-+K;0$Jia?+oH2}3b{@Jn`r!HP{7m!nCW@rrwyzAcy1UzrZ|E1d*GG} zj1Mj^vLYe&@g%fdQPk>RxL7$(7Yk{J(#va2^qo1v@H76BAoo|uxJN}t;pchDmE9I0 zH0=E?0I7gCzog-BM;jmxu3Vda)bjr|8e$Rzx#as#`Kyow`8O`3wRN@6s3oVM21Uj1 z8EdgA-s3kRX5gOh^kL?opq`%bZ;kxwX|$)Lb#Bn;U;6YKT%U2i2yx* zTnAeClC1EO*69BHIfgB)v$V*?CWo-1T)8dgI>Kd>?0G)2@>S*$cC+aZa91vLr`yZA z_69cPMc8iFq#HK0LSWOTOWXHY&QscBmafS+00kzCBtGM<%c4Xs4zn%qznkcYi*kfC zrcv-4p)P#pYw@2{YTw>WmYAdN&OxbuvUTyFZR9hdTXTi;RZf0+3`C;Cm=7R(FGElF zMC(Tl#%wL5#}PY?i3b&ptTUX*nhsC`;BxWudPw@6yywT=nkjMt=g?1F93SEM7ySYn z#_HFy$OSe@B)PKAG{+@}{@e^RYwI@6RP;n_nnvrNTXEkto~hOXCc7NSWTiY8F|SrU zb(8C;p2}WrsA10|B9@j-aWMAc*C=LZqFB}d_FF+EMxuZ_H~)4>k*rfC0%UvI&$B^i z90;OC7 zcu4aYpfog^#sQlU+~oF|16aOAw$zQaxklD%Cl;W7&gM_HW+PcSNIR255dO}+&33-3;ov+~X_#f+Z{%sNO9-9ZXg$}cP1 zj_%}L;iEJ_Z<(*6R{bYfmtu!UszlSY*t4%U`shbBCSWMqf4tHtf3Xj$2#e?5uUsXO zND@17xGtzG%_j-|bKagrFAUf9rQQ^^g zkgTgGw1V>_`DL=Rpt~4ek%+9|BcU$NroMV{^Peu&_Y9b@59WK}nk#+I&{9z4p05t> zz0Y8wcfqJ%tv3-Vd}vno?>8GL?sSH4{^s;TE+moM#I#V~VlcO|NTj7&hswdQm0X|7 zbZjTLh2M->aA^;#9d0v6D|{QSZ9cvM{k5OTp4;iM#4xzC1;tT5+`JJ|LEsoW+Z(4i z54PL>K1`x>qmPYlK>Y%Fhyfrl@fCjSYftj7_3X<~eyjBou=b1)&o>IzvlrkJGlurN zOw^(Oo1gghoo*#775a!BhM^r5di$hniq{YJ!1$WM`5Jgb?ZGD*9R==ky2HA3-0gC3 zkjgSRk5cz-phI8)N<2uEST4-IeB{=pmfF2*HI-tK!*-uu>1{6Mz}`a%%H z$nhX>Mp&rHRP^I6p1`;Zxr#1)(HDA;%t-c31#KdPI43R|W{K1l1+9H3UB;kpLTyQ`{1^SI2#jSe-$d zzYzq=HH^+8_}cMn3=QMbpiDtyJ#m{El+!{)Mm@doSA;WDfzo%oO%rgNzn<=^2n;wF zA-*JGP|66*?UomMwM=^Jb6dpD^o+1MM!Z=*NTPgAq8Kz7{U1Xo2%%|WYbNMGq=kOc z2ylsj8mX>4l{{qnj6H*H$K9@!l&4|sk!vU8_RdqnL=SIC;Kl#Q?K`9pJ2P&%9+L7H zmSx9KMbzI`C#pnKd4Z>?yYdg1fd!j?87JhbhF4p$QE8_^s|@_a6e#)4a!>$>VcSo+ zwtmQmu9y$E3G~neElw~~EiT7-izoBHUEmj+LG{OW&b1h%aP2@LFay<10u)Y+lRQz%meg{PqMeJVRh3{_t zh0N>OL%B|5LYDSZrNrbmS#k@YP83$yK%G72ai$!u^6`n?5(j9E zRpn>@m>?edEOPT{SK{~)_5Lg=Wr!Cn-3Gal>v8wL0`)ZQ`IzgRk50{BEoY(Ufd_bg z`2JNm+OV|+19nlGTA@SDV})y%wL2(6)gVS<@8yoz-vKfk@DU-;0a)1TZyuO!v~?3xsZDQ zZ#O4hXZ{PTR}9gdsNMuoTJ_&1FdMPBP3VQ*d=5DUP6KNVaGhQFSpKQBqM0!l>sOwn z7Xn#wWZhUJxwjYlvt%8Ag3HJ#j!>ke4F;P4pozWU9FR2bSmWoL?1PpC;)-@QRedeDcaUN+c zUmz+{<@S)PKpcCUYdmWPS1Hbi6*f}(Ur4>-5Sv%=;5thU9DHnugWvmbYmb;s7RHRA z>e~VCfW5-VLA?|wgG;}Wb3L)-9v#I9?KzSO#mSd~WB3v+nd&NjSFH~k_!w@|Nk5o~&Q47FA7+&Q0kL4*Y zG&D@VuFinI+e{5(FcIlSqK#peO3@PqL1j-%+;%5_tmRioUndUeCph-@!&wiKFTui) zN*39&+dBFqCf%w2pAvU|0H{;>gFMtd+dB$~&%bDEAQQ7>>XS#UU~lIN=?;GE}~;h8SAddl*%2;^SJmuP&f z<3yf0kQ}&gaM`d02)5CY4GR#~v=XiR<0)i<*J|GXjUAeL`Lszw@-R$!j204fFAb2_ zi3v?>54}$;%kj0hEk!v5zBlNI*?sl_e0mfJdRLxa(Qfia@OR!Wj{PfOtYJ$&{mIV& zSWaG~7@0&(qyT6bSENIYuWp3G!Er_%I#PU>s_%V*+l1%DB%OrE1f7q2xwKgw*dmhE zQYH-DMr@CA!vez1sR>cX*iF=CuhIQ2piAhli1Tj3>CmqRzfp z_>wZ+IH}j=AUrEM;7GyW&{xwrui&`N7ZU}p#D(+vB~DL)hpVY!R9L_x_vw6SuPp%;EmcT)WAWTazodHuEX589)HN;ijT{^u%9ZJQIm-gA0tcVeySq zz%#({wUG22v%3o7)4{x^uPOW0)Z2ZZ0y~(Ae=yUV%Ll|#tBgRRU$cq>4x@|gT}=px zpSUkZl2A3gjKN-@;1B<9TnqhvPm?n-DB{$!dAty@tLu}RU_Pf1@{lTMN91x4N0FrZ9~Sd3 z1?{iu>k3u_ANpaPWQ5qC3=OF18&4B0w4bIYW-cB4*z}jabM>C6NL(uo0+~v`sm@7_ zbUISNXME+FK`5WK?NI3*qP3uT1v2!_r>jln(J2J%e2H9Pl?yjEFsva|Lk)@9lU5K; zQ{j5v->AaRY?FTYI`+hkOWF_TW@o3qg*>wKedQqS_4ysgqe&Moc+V>z4S9HvEkQou z$DhCEPj|Mr3lT4#oL-xD{3@Pv5t>R@%#qUB6?r^+B|1_&e4iOoA|9PeV3B zVm9x$hP?UU<#=SMaMbsO?ZD@q*W?9z+U4XA=bxM#8e0j|a)G}tE4>fbsBQ7hks{11 zNKFu^sLwL3>S^Z8^9q{+trr7JuJJwUe9*yOj*LN(s3fmpfOu zcufdTm=82I8bKp5f$6Q+TRuLC)P7jHM=H6$Hi?p5yR6BJ{^xmgH{`3QQbSjAyi)p< zt7k!=`a$N<{2NTzO{(ZcspJS00u^RO=n($8>(Hlf_jkzq@n|X$|44vu#UbsamX~eX z`?bsJg8yc?J@oyS^Bl+avy~+!zYiTM=-lUu?yzVYYQRUqSTc%SZ5%VBF;pKZ6TZ4F znrn6*iRWZod&MK$oiM)A-P4nZj~DM7DP+F%C%8c{%_wr^^XJcp8r>7#VvErm3zj_$ z7`BC9F5ACBkD+aiSl|Gd_-AzmD>Nk`2X|f x`O1~9+5f#0g@t38Tis|<^#AY5gw}hlXGJV%U0?e?jiG{nCI;rjay{3W{|B$1$KL<| diff --git a/Graph/Images/SocialNetwork.graffle b/Graph/Images/SocialNetwork.graffle index 05abc83bbfaa10691970641a33862765d4841538..83baf8fd3211d3d9e4b23a9d580d50c489dcf700 100644 GIT binary patch literal 2419 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 diff --git a/Graph/Images/SocialNetwork.png b/Graph/Images/SocialNetwork.png index 5927937d263da1ebb7e2e36db7232d4220d2d68e..ca5f662aee5513bf5fe43a7ca1af007063781d18 100644 GIT binary patch literal 36342 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�&-u8f6KJ=bupcSnkCmR4+obK(7yc9~+duFSBF9xGhW8pY(JHtGrE!$Nr|; z!;+H->V()W=qYp0I|?ZKGI+W&O%vcRmaM#46to=Oo?{%tbE4Y*@N1dyLFl!o+iqD; zS!f1#Es)|guV0yMMHBs(>pb+nRKar#i8)TNlI2 z1np>PK6Mg)wJGKhy0xzx7^`qnio=qXay+kHk4nl8@W%u_mA+meLO-jn%YVDAx^rdC z@Em4sQ)s~glH^$+i9a%rT?0>0x6M5|u?#&hJm5QyjKu?`DxWDIgoUU=%{}2tXgr)W z%pz07gl~;IfZjFkUORR_vq+7MS`utpQ@3tHQ|2g)1fjfvxvXxEP)xD1W-ikaWS-?W zsly)`!N+SDwP&KpzQ!z;^j*hTzb6CQ_gI=wfZO&DwOqy>aCi|MTw`x&{1;MIy2Bcr zO%ho+F0y-)URSC}8jHrPD?)|dDn84-W zh&}cWg>Zee#DG}OF>l(%VPFq$t7W5Bd^u^k&u$UiptEzoBoIX>T?5OzdoVEM(?gFd z@_@oK@}YhQ#FkW1Z-@FE(8(Ob?Z(|}tz~m+kzx`$p>Luj9B^{v!R?dfyohrt&+#Oa zG16gNa1qjiw?FV1(Q3I*6%+&$L?k?RFbQyU(1NnG6u0w;6jr0QVLNF<4ExbbcUj4P zkm<;-<GGj#Z1NxM36|ACjJr4bo>)+1UR0ns95POGYP`W*gcQK%*w-a z&@i|fk!3cMMoegh;}j>^!Al#w7I*u$!{dH6_8($GFsXz(ix)qC1@?qsNlWVUiXB*8 za26%XQhiNih(K)}TM)Mq1Vhn~6l^lV!xQ@5A2{x`CbKfkLUUldqpS3o@aS*Kj?p%7 z7vkIMQ}KXJDaOdwMAc7?yJ{PWMy-LT;EqfpM4au7a(T57?S?;Ns&$BHqV@%3EqkS| zOcsI|4x38U|9ypd#jXIq*joKJW?7LigNRRK1*ob7mNQWF^`y!7!++|di zCRfGCW~o*8chOjnx4Au(^&^35Y_o7xItk-EX*=` zn)n?9=_|K1bbJ|~HH`o$uf?QRVRc^}N2l~ZzM|*Wm)Y!#8}FjMrZQfRu~*()D4a-%_{LTM-0Ycx=&)MpID4E{p)Z?4)Mkn1wrJlR1Uuyk4y9eYef?qKLKo zn`h!v5i3`kR*5*fp10MEP1ByH$)7Gjr|y7{QIS+|Mza3(8`AC7Rys#JL=anFi{R@K z#|7vuT)nkGNVtO@<-0PikQVW?#96KHJ^k04__pwSc&p}B6+6Wb`v_}z*Uw{jHzN`~ zdFyZ{JUF+`SZ(rfeqhf^ zXuD|K*wvCRQaXRFU|$Z~lG~I4Eg3^abl}?+m00zYLbGRLy?Z^qQv}vYXxtw`_wdUo zZ|nq3R@KP}#c#BU3Au)WW&cWQ$=(wop_YB%)aAqe7zEz$Kfw2JQ_k#seeq#wxr_k~ zpt!lq_PS`d$&^s2Z?W)LkO<)7C#7U}Us!T@qjpccezLluBG++>EVhn=TK|qw`LMTw zhT=W25{wu=&{sqKqW1P1vL$G2*j1;uJla*V;MRv6(#gfSLZ-`Ie}Ve6QRn_%+Bypg z+~kPj(EG;=j?Gd;BB#b9qGR&TL>nNSZEY9uO)W#$G$icmv-jiglaNWs%tp|CtnJVo zYMvz!4k=I&x00c}Marke(IBX5BX_R2*y)U9Eo_{MR;$6ammBBye|}$`vGITxXqa6x3LDoVpK3 zw}zl1OMXEcjFWgv1rq3YPj9oomL=YP)`1P&<2fQc>*ZSeHI=L+5ltXXwFh&F-JZ7*F12AV0 zw5DPA2$@^#-~M^rDVO&0!gL54A&3-;iYJdu$Npp?7rWoXqEmVUYdT}ityYs@blUlUXdZoX; z8s+TGz$Vk|>#B~DO-;8R7?Pb@p>zCcKTefYx zWxKsk?;lV->b|f0T<3hQ5ODqwu-i`JGF6i|Dl^SJ3)PYpGa;OD{>4lZ?L$GFbuw4N zfS~=<(-s;IDT-Es#GqWbFgX5j={{;)5TBWvKzC5*>@g4Zj^kV+UD%HHNja2`u}khW zEEkCQH+dpDC;t&QDNG5*CM5b9qDdu^p!>fN$>HGHi;22F6#{DR#&PC63rFJraH#Sd zRE~p%mDZ)33|X2xy>QUL$^4K+4(bsH5Di;dvjIn^AkKCG#0=%SB z;x(V!iC6Cy`Kkq0@qJiAHHg;3;b7Kw)4lnKE`hcP|6#ELp*VZbgt-`&Zyg1QN0n0N zCyqwNY%J98mU!@p%~d)y^fN%AE)^tuE_&0{MU7(a2U@7?KsNfrO+VeKBSo0?n3oFhm%joTb^Lpsnhh|E+!SECB>Al(Q07N z;jL&gN^3RD*kT$U%1J&74K9nELI{1j`%0#a@W?TZI}eTwc%cHp%#s;1s*BeyO9^ zPy4oHT~Ohvj5LN?zW((_W;BheP51%gp|QG>SHowZf;|G7<)>LQg%-k)++ZEGEgDxk zmzy$$(;L@wA58QEEzhndQl(HMcmtOV=Ubvhzh$NU0Gn}bq;jnW{FS*OBUmRW_K?8y zL(w_tcr?x=Zu`q31;VQO`Mmr`A<6eUWTg2TP|XUa;5`tpp%U8RSRUqm&Mf^_o9+^# zW0H3^d6w}!0sXfU+;ZGLTtSe1+#>(Y-*mTl`d`49scWEv|EaBk@04Gh1>r3uihv>0 zIE@QqU_wOwEa_~ImK8dawzA+WUQ0l&IM(dI!x@$KbaV! z&;4j$g?4)ymlCdwZy+xezw4a75wbB>4NY$uO zKCX1~4fY9aKqIG~1+Kf-wec&NUTtuV*Kq@9pDd9I;+I4gse#W>aXXK?RLM|S2a_P> zN4I^sixclk_fVeh3kMb6_t(b%DoLen^@P4O}rL!1hF zp|B@uU;;C#_8f4xn!aQlP}9N|ce{HvJUr+B^O6Hu>&wv?@HG#-qcZci#Xa*09>#Qw zQ2QgHZ)^Kr$&kJ>p~nMpO!?1D(q7l5ms{L-L?!(DPVx0v;-nqYTzv|eEFkLE=c<}g z!e~EJ>l5n)aSTL84t)AI(^dZowo^(^pFi3x+6U!|V+O5W2AM1qlhf>Ag-MM@-_8Bf zxya+d?r_Fqhq6apkZUCwd`0j-Nw_aw-%dr~(?)C!3&*9!(RvpXL*C}~08-L-E|TY6 zmuLc_sHVS6QzlJpXm&%kw~KS6{#m_XMoKnj7MmH^mWJcKK3$LKt}F%ZEvBvU9^jcE z8H9CqfPW1kwl3>#>~;%)X}}h9Roe{z4gvF&;~>pS|>T!9azyoRLcNDn!r*t zkg=skL>5iMq$5}Ue)iP~0jLg_+O#AdmExhFM)>0<1)CX(|kuSj_2>XaN%oakNdHZB~jJG*rVd7$#;fw}p z%$I~88oWqqd3F--RRB7p+<(}CTGEhZ7-q{8hM+n{@fpG_xuAy>dC?{?T3&2cLe}Zc zL}fhJ{0Yy7Zx{G_OK*u|wedN7r}un4(PsZU5H#j}9m$;eMS8vT@=D#qY;4EvC{F&{#I zqGYw}c|{0``NXyd7+%e6OPA4@hI?C`C1z~2|0s{{Zx+d=AdL`R-kI*SmB||XJ)1Qa zMM0u5;e&Hkwppg9kFFUZEd=!2W^tKkb1Tqo2M>(~Xky!OTCu_zd(-N8DA5 zuqpJ9G*g|HQ!MAnOS}wKY$mh|CCFFMQ8yq;^c}fJV)E5f<}ncuu^L#J3#R0fV|u0a zPKjGEq0fF_ZAE9zfJpm{ODUG{UK&YPzl(Atc#JL%+%c&aY#s090|cDRdpY z5bjDEnFwYUqv2K?@$nG|>e=p<)kA>S@eiP>%zOR$t7$V`X{Qo$6`ClqA18)vbXNUR z*w$wsSZq~SZ1efjHb`inn3$Ttz}p;EW(R1P#k02|lVk(FRy~~IyR#6$=B<1LajiYt zpvCauT?zOaYS^q`K<;j#fjtv?HC4(&mSH5WBfs}D^hH$BCC#-0SRUz^yEZ;F)Nw5= zFR@#pmziHV9=j2?r#PIk!{sGrdss)X!a)WtH1k>-zMR(5|EKVjx`=Ou7Zuq$Q$|Q0 zw2P)aB%M{QduBDH46$ZGspnaA$>U0UtR?WsWOgcC!8iW;IuPiPkgyi)CD!ejfLq8c zp4?P>kDXuoZJOg-Q$wz-KMlUM+V%*4sPN$4Y?0vGRbK%Fd5PooF}%j^nQii$)#~9a zp7}9D_?v%+C=y9xrNM+U1UBD{=CrPrqo_YNYktlJ80uFi!kUPZoJM|CQThN8KXorf zd57aTDi%yqbh^=%Lf~_JbYvA%!^uNBP3`{WFtC*W#6%}OGAJR^P{AzK8aR!v8#n(4 zPE%)W@3^GaO#&c5#y@WqF`@;AzR9V60ZE6MDw$-#Lqv1lLD*_Z{7IFb z6=oJ=j7s{~y30WSQbgl)VYgm-ybSTROOAT$DF_~*Kp*KqpY=J`dYy67FP5nPgq0~-od6o$aQ*pVV4@W!P+{j-}9L(Akt&ID3d=0ePo8SzYoXfXozj zsFI&zz8*1-gO6^kyF?R?BQ%2D501JXvENu}%!t#0__=Pi4|e-{r3ts@6$4XCYi+Y? zQR2m7eGrUA)q*T6a5}+4rl`r}gWO4#yl-cbb4hP6U%8NfyA%sQZ2P8ozJJ^%Q|Y&E}z6cG6#ODG(9EMt&F3m#j;*o{$r`GwnI;1PS+U?&v;nRDz*6 z^4}T4{>fo}>l17lD;~Zrhld3YEB5wv<*gqIl{2#CyO4V3gC2x7(%Hs1&@H67IAh6`MPi+g+4zXWg81q}Aoxe-_ct?eG~RKZ`ar`UorV-9 zR(ZIsec@o!aAo*;t^?eI?vU?Plo+%gcZQ_FUhFc4!7?5V>f)w>Y^6z1qz*yTa)sU& z-y`y71Vd#Pt9akrL$E#d4ORSFk*`3cUmTrMO?DLE$f+drDV zwfOrU4CE+yX&zqme}+vtAELuIaMr{DicWBdm1iU98OXjXGz^dz>1;G}9uvaPxnPOL zW@>cUlB~t79UfZHT;OBfoubFgJkRol(?l8*)2UW2=|5pT#U43Ekz4xW#A!>Ft8I3= z#Z{Tf!(^Im77C3ZSF)dz@)l{;o&71mO9D_6?JBI>b>;9XCns01a% z!T&`vsLBq^y#wsH=z< zh;4?wn`NsZ?qHL}iPrHjGXf9ZszJQE!xqtkgl$bdJr6TOU4)$E*M>$XfI1v!o5qb~ zfJEpvqKsDZu?M*pPJe?PxiL76u)Yf?kCpBSuRr@!+IePaEcgYz5KSctqP%xcDb3m9 z$LzAEhmb^o9nq@%dAWE+%~acNFcmZ{Jb~lWL3so_GCyaX?Z3t<@_jgcsXgGF<)s-3 z@e^wAsuOc&sGmQu)|mj^9gBv(wr8ywdRo70o-9SQH=S%sBu&2h->n##lo)mkUssYT z#a{Pq(fq;zSBV{w6#NDff8UnLh5%qM^&q|$#_w!azVFr^=SDp*?%Vq>2%@jG<*y+T zNoU`(7(I0G$iNHI^w%OB67IGa4a@<0^&XLN+LX)8-S_?p)8L-)ba_Q%TUPY9-|Q#0 zHvDAgWK+Es!lzxe=5@(T6`Wp_u>K9<7Yul(!1aM@Wfx6=HF{Xp{%Z%%-(u8l#Iy7o1 z#hO3R&-rg1y3BcKHqXHou65+Ez!Xn2x}gZq*1Gc)qhT3TjW}xPC!awqkNKeQW;4$= z*s2qemW0-bee&B4S1xNqBPCSzI4NxxngIIfS)z(Ll;rZPN%s+L(V$`c%ZXG3V^k0D z;{)5zjCIiwzbo2Az4l_ba{wISzR0$;HtKG||FqBgJxK1zVw@51LK?ohLhHw@d&(HmEYT%IQ^KzkB^&=WP`b8nED#s0J zqvabnW6aftK~9+3t~}*_4g{mT70A1(cD8DUNw#_&sq;)XWF&r1I~{)|lV7@QEF-S= zW56}2BmNn?ZFXGiIsA(U;Y438g{rd3lp7sjO0hgli;Y%DiL3+BXHy0*083`}E)j>> zr%|ZS)tT2`?EvEvov+t2Bf~-)mGu_^D@Pvcj|y(hLm`TZpIz0BN|~p)VJ0hTy&soJ zVcNe1Wo-bSh0K4(lAI8Q=lGDLN?0nD&fEhGmd@4qH4lSSG!;>S}CkUV=+FNKjb z&McpU;{4L;|j;&Y_|r`S$-{@9uZ zZG5d~zA|QSAPP&?XFNDfw2P2><|zNuT%*17j&J6Qfw&Mae5J~? z+06!UAdS&?>l@loujhaKybHUWfY~T_DJ~?U8HREA-s2U zO7#OinV6Ljsn31JoV($#V>xyTyh3ccd4^29&d9KJ-!?rn^L~=fEBk-X<9w%;bBhY1 zg&zQA4Lyy?&Y91!vK*!IgQfi7_W+740( zvR<}sUOc=tG>cI=8vwMkaC|{Scj7`D6e5~|=XgC?ZjE?LahOH( z#}J;coImgu9s#&wG2sya;EXW*qzd}Fs`!`?hRXIO1n#g8)6=Q4_WcC77pFK0K-b}D zoP8>(>=5A19WHe~G^QC;8bCcP_{q~Wl%MAlYUk3A-aOnZ3^h3d7%Pwao*&W5_0svt z5nSyCceF8Pb(Wh%?(2EE;WzvO{|VohDPr+nU$9iHKVJ2rsG8A7e7pM(;BrC;=e21* z!gz1K-&g-+uX-fp-A4FlagN|s!h0{y znjWvaCFIuQKjX->!)lDC+3(e?A%HYg!oBX$r|-5RL1Uuh((k4|2rT&rUf!ShUm3Me zA6!Wx85w;9m-nzXhai(9I_MRk9L`h+{o?o22`RI+OwjUEYb95W$gCGe9~O8y{xI z1;U!T{k&vP6OXu$)>qluG0l2r_boc>dYB%CBa6SaoEXW4d}!&#i1_h3qp6eZvF@ve zxx{0+j>dq~jw%*|5*n8#~5eL?7)11^iXEB<>*evQ@9U^e8Y63Csz0xqja&%bJ8;uYq204C@8iX_AS~osuM}^I#=!uK9P*bk)WvrvJXJmSti9c6_Q^EU6j;;bcTT9LP`VDDT=Kw2Ny0>QnA9oVIvPiuMYy zx{@nX;80%cwr5@J1Rm*^LkI+hX%5kT-NpyNiev5%5&lho;bu$Lexk1ftt}sbe?>-Q z%t$Hlt%%VZ_28M0>gQA)v(-SJ0b4Q@bcp3x@ziPHxd*)_BBp2_Z7n6q;ckC^M?bn; zu#O*8j~+Fb>Cp{n3-BeS!RgF>GP<42N)(PupJu*)`xwM%QJ zinp)1xQ-fwGiXxhN7Vqhhd_Oph9h20|25=+QQughe=j2*Q|q$&Z`|Q{(7yxbpJ-?l z=g?7?Kz6+jNIB9%ucu=1E~S^8Wu2yf?dgptYS^OsO4Vq47?(suHPQB?KGFOe_0o55 zMx?aiiZttTIQEaK-NkjjsGVvSviOou?onPtN9UNTxA#+7(Mg`un7{LQFdRlW_)HhY z#4Aw+SF4gGD31_f`57QAAj;?hhAM;_`lI(%k2LaGO+Ckff?q;yf6FUIySdX)Z1HW~ z9$VuI0e){V`7Z%Bo$?G+_13CZxDT6u19-29R$a7z%uup{4nzHUSHmCmA9!y-!J>L0 zLFYI5TqI!yWut~WoB*mg`O&CcCwM!~4x1+LN~vjv66(S$X5-@&x-I;4SjY`mvSj`U zCC@g@xv15LO}MZT(^9^;xDM;-ca)Dy5i9ub?bfO$t@QnnTSLa{_cR;NL6R!Zi%c)c zMw48f$0)R2An z*p6`Ddn5IT7x3vJ;TesB_-J7_-2bectW3$V^Ei0E&CdJfUv%nw@`P^Y65}tMkngvSZ?Dc-a^%ei6Ao1k-teoWMqZsOjEqCzD@6eeb z!vz76+&Hh?==-UM&>Bg|;kLiP&+{J!x_}*Z2*ZHZqN)Y^M4YG`2!qwuAc~$L_mdXG z7#Y&;RBG3w+f6L=vP=zCRCi|3r;me7T;EYR)fwUIsuEaoQ=rq1YCom z9JXXYj6hO@C*WFkYyFh$5PU#@3+ME8B3)4cov#M}F1Y3s zzeMWy79(2)9_Y6Z5}0@AQ27X4H9~eMyOy0$lT+!;g$%+ezgZPagQyIoq|&sx>;8Ge z`r=je*ny>04K^*5ccCJ~CE(;Y$nb4p=CWSho`lw=$zCazNEF_My$;3EZ#;RXA1Szv zlSk*M)SNUO(OPtKqOVx80m-Q~9XeD*)>*}1S`L;yCUWo-S|=IJQ%J21W9VM(v%O{ zlX)@}jYC(&fbjs&06|&e!$I8=>se%^*9dm?B**_?#=pC2kjVYCn~AhRL}gBu>*G$_ zZ{cE3;s>XSC6+24Gm2Wj(3pR~CZ^5_tcC@=E*YMge@i6G)eb19dD%Fs*FSZ5+@WKT zLULH?hbHb@5TJ(K8G6XwVir_~|IG8{uoAd@2 z_Dm8SG_S(F+E79Nnht=-aw`!RPK1prF}`!vO^pPqx*Z#WI6L!;*|CpxwbYyqYNC->VIW!NaAYTHac z{bHSjAacpG^M{|-#4OK4=h$P&1f6vdx-xB5V7}dK=qsk_U|zx@J>5KO@KOK4`d)% zpD(1bjr3v8CG*U>jp!pGTtY8%NafhM5`37Olrb~7{jNbip|EG0>Yv7k#8Z8Ac5>vX zW#9zj2xkdw?zXHt-&9MH{iTeknKk(NR8++J~q)8z8wOx z;H;Sz6E_~-+(${U&Mm{JD70P27 z!`khRC}B-)v=XEP(P-g%1~y+j39l&p6-$gBab6;q7s z;89}kFQg0R8NT13&~qU`pR~T=h+Y?i<)|0}R^UG5p1#ZH%ZdhC{TV$4@Foq94@JMjy`G#}K<-58x{1zso?DNa z&zVwnKWO@_LL|rx3;QFF8^RHGD5(bZAjL6to9RE2bls!qi+nChLI)*1*lH1lKn zk|PzOG~8$T z2hBG+y}tw@{^xT%f~&chFW)EedgvRgOTgJ{2Yi7;z&LY zAi&tI)bC*%(!Xl1LP7C2e2&J*a!7U(JR$rq%5M*GJp;HaF}aU)X+NH+zc?BQN(zNx zDUzb)Ab7~ll9T@;8Hey78Ild1iLBjAHX?Ng^h`LIY5oki&thEbC1k zP({BiWdRS$e3YOUgrn0{v3No>_J4 zA$}Q0;;(s!4pFPF7ow$dg?iV!HCu!8JOp|~*FKo+2TnU1Ju5_)!f9!p!}xZNscKJ$ zKYpZf^E1Zm5J(TSqq18`q+b#*zV3pL{T*ld+aSSh#dAkz4|Yp;%az@l61{FS0<_^! zV)W*MEW7L_;qXT)h@c?gZC|d6%~w7Uq>XSX=c&gE0F|$#hRs1FH-#|G!=;F+L#o|iNcieOe=(Wx*37#o#bUw%=T~34+Xp~BL*`DE%pt#3HV$*` z6_Mg^$R(9DKvuT^z)(=X+&n^`*4MwYM~gM_NetX?_T4 z3h0oM7ZQ+AWn}&*L!I4!!tgexoYk1w#(%=j3-@73MoBioHJh_OdIEKw=vbDOTx^Ma z7Meg^k5&mxwYW;DU?QVN9I|sB@W*$5(vkXIKvOYpl*n%}Z56-7dSM!h&l4g-gba!Q ziJ;SS#O1Gsfo?N<$MpI&*;r(|qL2eMo}GrfRHWbs3uT#IuwB*Mi)GxL zXk2#}!*Xg-a?<>LXnT$Z_3?9P$^~=L{mRVu2yJ2K0pXwW9rg~J!E(vAH_R=b6l@T)UNm2OUjS^*wO_U(S5OyVdQ-G=|mv|Az@*c=A*NM3*Lt?T7VodD9)dooN~hA1eA z@*&S(@dQw2FruX{P4Au{UMD(Ub-p!AHh29&@;aE-mEiI}Tvwar6n9Xg2nXNHKDIG0Cr# zfY3Hf3G5XAj=8I2-UFg~Z$~626Qqk}jt;~C>}lUrYOpAU8CQYMI-t(AVS*9+RW6G? zv-&&KNn%~m(qdsHtz|oacr?yt^)npsVzLY=9Z~c|eQ$W2LhDgMc)N6Ba$Uiip|Cu7$GBV35;bVjhxk2_BF@9kB*&lNx{Vu~veQ6q`@2a&2xW>5!C0gAfhGrur z^A)9EtpMJzX@}ETHQ2qey=79kW zIymK_!iuzwaPio|@ptPXJhco9#Sxq~?EC1OqExZ~!7g3mPi4FQv>ZKR3YaZc>t5je zg&!{jwELuIMa|N=(-;54P->`i%{`h9nZTAa zV~{9Z`v;{k>3I1e?8|n<3alx5176#%TF}Wc>F-(pJFxgE~PF zHhDsrr37Egdr#6{1q1D+WSO`>H|C$gQgff?)>FS-61rp*%;d3N8QNF0^9W3lv7X5y zSES2XC^Qy6VI{R4q`mduIPa|Ka3Zt2S{nSF&RrbF0cJv{6e<&c)6ob~BS+7X*Q}7@p_hKAWL_gIY zfv(lqNe+bvvy}re$+e-nG248M_(Q(PnSLl~#&HRFW{U(k(QEp%D-;q@ZncEVH$ZV&?sk!qP3 zLV7jxU$uJZtttBArCJ5uOFTWnB++cwWW;h}6!?kqDFhZU)NkhaNy*Mn3jD}s#7f6Pf(hm6XslO^prf?9nxc+)!i5M|Q z$OS}l#1@x&Ly_6P2q9G#9}7LnVe0b1SYi?j>EV5#+QAU-MDs-Z@Dl7pJbu!i!rzwA zfFZ0P_tYx9$ZIg2^iwKQN;;buk(0_V(OPv9qRq08uuE)Auyg4W4sMPHf$yh}Qbc;C zccJ-opuogWb{s7m*?y9WxonH^iNzF*BSM;@M2unn8Z6}ROK$5^HbR_!4&7SP`N8;+ zpKv&qUyfT}PH{usaGnRk@my!Ao%6muRlcYP#Yrj6nUEgG6rlX{iY~H&D{3J*{+2!>XY?cLzknEAn`3NUp=jN0hZ|w+m zJ`~Cn+I+lXV#XYp_{#*20Gf;wo__>O5(XgOSl;d&lG+mUSDrACs1yo!nu-x^A6@4yN||+m{wHepG&-b`HhvcSq@e&G*n zj4yu^xdJhv5c+k4EegXo^t7j4mPI;El|4Bob4-Xf!~(EoKo|kV#59Q@d!l8j0+_V8 z*TFcJ{-Lp70eKDURdZtc!-@ha$>B;vW!q1^8Xh+-yNM4yx3GQxjHOK3MolnhTlIPp zkrtcb+~Eqn0B*5a{+LON&Fg+)xp@R3jv50gN!{&ddkesN+l%p;&0^W`(6AHP)e2F; zxQx_R8anXU++kvIxdfE>5#^iP9>)&z-My+nQL!8-xj()djy^Q3FGlx&M;vE!zo{0t zOx1VO9wdjt#W<_lc>`FythC5zGw+XE|H)DPR8J^%?)u(Vj+@2NDqb2#hS3QI-(~A< zr~~SC4f&L&g5IP4i6lR(TvaK9_D1Qe)y8JI!()rHKn4^0Z3aM7KXQD25yzv}QHCXs zH3YeS7cxXa_l_nqX;P>hKdsb^D1W@<=f^^|-vQ*|AH6hhoL$pbf5pl_9hsIneUmB) zobzyqY;k{7sP^v$=;0)9DA;NE)Yx*bINVLsX!dHPU_h@rX8BgdJ23P;PN3*){thar zHKt3P0{?u#a-;lM{c%46Ct{y%@5y(g`y|1kc0k z5`kK_`yi7_vU{4Wl?d(}Kc^>CzZUd`Eh$BjpcPqvvd z%?gCeD!KM0kf**b_Cj655ZKfNXj=$vO3E#8`i3H>@S{~Yg{3X4003&uj;fn{$akfu5a_Qf!=D_5F#p5{R6&~VY&e=#-RZu}2eGZKPh!0Q~n zXWX9gYm%*$;yYt-f+a_3Ql((4?->MwVF|VYjodj}!X0$(1DuCGJ030c3^=sBN|sS{ z*MZnK)EryPnxgZ9cmC{sgL$2Iw^f2HbnzV#GkL6bx}A0_U1na=UsVH1?Z8WIVj>BmZZWDk3A+V&VO$sA25TYWU3=9iTR&h% z?jqGe0Zi(6Per81h!!D$7|gMTYb-?4DWp&)qb}=?fm=9_EFaX^FG_L7$h2FFYPER0 zNSwxNBb5gu?|-?`8ZGbQ$K&si-E2;r7nCKI$C_}oe?O4OggdMpYDbjZ$DR+0=%1uO zuv<=j=NjN_64DySI=m$vf4+Bw&KO$ObDFExrxmyDsq%$icH`D!OooVYn$?f*(mp^%jff}kiL;%7B=pE*c?nJeU{Y<^?pmMlcX zG15O!&eo0N9d}@bbsK+P?Izg>^}>^0n}}KxBKlb&u-d^F|vr$u?owa2Bp9$PXE&tiRUaHbY!B zCYSnE`7jVUR=aqhNEhffRZJX6_J#}wu4dHBo8$21frcL7_K+on z*v@#})HM;KLqXg|s;Cs^yr^^!NH|L z5pSXNxfb+^e?n)8y)F1$l0CId5z>a^#7H9ndddYneWiaI(u#V<&`J>8bWdO({sc4G z3Y5=4;a@7dDQd+~I~N1XbMSiUk^R1A*?7-a#KzWh%I-Z0i{H!Sf(W)OzkL}dDorxO z!EtH6gxGmuyya;@`Fba*A#*GYiJhPI-7?PbV!)5Irx_SfnJGWrV?L7TQiBs2EzWA5 z=T}cs@1PlYfG)GI_860iTj1cd-x09LtfOpf-Nnj@Jf&=}JF#PmRbUro`EbZ6J(q9m zKr>+PsKs#B(wy!FtilJ66(okS8zk3ej;jeJ((tXp-`#!|s=0?4#^(WwwNho5!E4Y# z21fAmmlGt*8PAf`b<-3KXyax`lUzVBel>+S8NehT90@>^w2S}iK)QCPX6gJ!j2|Dd zlvgED{tP}Gh+gVSjdMB(Gxwi2e}{D$ycKOc6LI~?e^q*N45Zax;Z;WAGG-lb-**y2 zhMzAy_%*M^64mEH1Jk+{(ThAE0ve>;XsltlW{cMe?L&vG@5@JVxTVA)#7@1}j<}>? zl*+mvNQD`4lPn3pvlTW~I}c=S;mIfkf5Da4M&!dkf3PTgVx?TzP1qdg`tcAd+8tBW+7=qkly}0m1RL&C`_~9u2cn*7Ao&V7VD*Y{38V_3fz(Qf` z0b=|-;UJD<>Yt4dS&5XgH33Vwx6yeg2H||IOyq5RS(uhhVjKH{ToBrUlwRQ-WqFSiD^S!yTemzgensk9(P4%a>iU| z1nGEPP>Ag8J@U)t&p$)db^U-ZM%%c4)AxEQIZoRPMwGL4GAT`=fT;`KP6SF5H)<+l zR_r~+f$GnSieMUjw;;b%;WbBKsP?rt*Y6*YXt(*lrn!*K&gOjZ=aEjif7`1K!>#yr zPi>BWLHv)bjiH2sx*)@ZusIm;*0lvQ7e$lSiYcbC1kf@63VevcNXbWF-AksTB*eM~ zL=!3^@?M6aLa*+ofx$t+DM}Yi2nzXDi?I#@(%IcY-dKqtJ~;58SF&bkaEQ$^cs%38 z(UcmUv#bH~3V~jR8DHtMJ{>gGpo90?{tpbq{e)wt6TzH$Xvk408PcK~pWp1pO-VnM z73?eh1HOBmP(s_6Q6kVtXPtJqFtwNK$mngYm<{PYB*be9Im0w4`S0~5RT%Rrw@F5) za3gD4>mVlX*wr-4covKkeV2`cV2p(z3vi8dr6{k15wr5KmIjPZf)o%#yN+uqE;;CS zN9PD)DACbhZV>DL-qUe?x?KFtBJH5{LpV<&)iaS5>S1&Cmu~{r*3GmiJmoO*FgRfZ zH=n$Q#YVx_+){Pzcq2H+2bkoCHHt%+h)DeDIGU#3vaHo)Oj;SB#>_W8CHTdkA+Gl{ z%+o!|LGzP>k9wvFw!PlUInV#>FXcfMTKOz*9w=(j(E2BHG5sNZpzANLcwZz414*H= zBIXn%xbr13T_^)fbGK0)$>7_R`@vzLlnc-RCy0du2#t{IV$)(YiQ9eje0rhm;>A1u z?tHB|v@7Fv%lU8CZGp2G+KPdSdk{=&^?$0ouus7bdcgRDJ_D{~4LmA{8>g_=iy8B8q6sfAUa(ZFLti&zVidrscq%RJ(7)TQ1_fPvh;{#1 z`aN(O3qm_7G2Ob^K(g2iplF9{{N^HB`fFo(Ih@tBW8LQ-LvFm?XUSx^E>ocj3lv5B zA;F4G6959H2TBq;?XNjrCB)6GuM_GdxTqD9+W5uwWGHdA)k>ZqD@%9mrma5pP4u9! zp||DQuA{#hv%@sVw&7gEym899i}QS?Ein!U14GD{5f@c+4qRF#e3R|_5z|??<3}8k zk%1qcPA!#0=vw5`r3z&##vj6s5VIGyPtO*>W7^3PUp3C|)WoIm zlt6j1Sh$AXb-O!&;4J*W(Yku5;QU2sP?m~5G*wI5hrI9liqhbEZ!pFL1M?n1tLGkv z19>wvG_)@aWsipwa&9Xhwg&YreB_m=4?=YI%vYp=g~`bOZQzUXFs=|+(zq>=>HDd$ z<6e?Xn6GlQd260q4r>nK(hq%??`N4Wa5&;VXQB&=>5lKo6$P=ao|3f&TdhYHi5M} z%Q_Y=+D9{V6n*{2=lRC8v##t1tM`LVomG7jp^c-PS1-iQ%b~++6h02b2kBL_u-J^W zfH)Xc!Ke$_PAe|mRu|@@NH1IS^<0S}37^X_&7(H-fHd19>ixtaC0!R!ZA4NNNxx3r z(P414tIt>q_r&$f{g300-@lPbcv84?EaY|NZ#xuQJ!B}Z_D2#O%iAsWY~jJl;wYi| zr?qt^o{m6SjBeJ(%8gnLX#kMI2$da=EA-o$R#}9g*Ijs)j@#F3w}fJeC&e=Uqsi=c z`z@hSvw9<$N*hE~_!riU#I7 z6<6kO89kT^Tfmoy+mCN4vSjaLEWd?_kz+uBa-o2`LGM0x;)f`t z&fAkSI}5(fUB!{8*VWan-M)rXHS9+OyZPR1N2D%|!~9)OtMK+>qkY%`EqGue=~l1F z1`n%7x$}PkSO=&0GF3vUPePp#N}!+uLh&+G7PyVZo0^)YOqnug&KwGNCooNh*V58r z)R7bDPF)BAA&_1K#L($oyM#u*bm>wGY9>|@)6R;NXhf(`yr65uptugF;s%GL;Z$UU zDRxH9PJ9228#mx%h?eRll<7t*6U{657==nmo!d^HJPBuGydsi;-1WhO2f2ulCB`~c z%&^x{zIyQBfo;&y35wVB)vsSaNA0UwAs_@YgMccQWM(N{O$4Fki4!LxXaT*s>Z3%v zR2M;E(7t)<)G4fCN^x<8?P}hItxdcYLKO4o&p&(iEJNkpLaj-o_K1a@r(cN;jX)u) zS=0@sgcvM1Spl zuxE__IX9vTy2WU=10bvnZ7W_96panNbLURPC{6fxq1Gf0bMCYyyRCj@b#*o3l}J)< z-@culZ=|Me`>~(kSBIPN!^hsT8WaLTAd?7)p)eQ(yYq^VBXXHep5v^vYqZ1(@1cX3&1hfxb9v{8?2Lae+{rdG7 z(_6Q0wZ`b5x8pcNZjxrOl}C*lMR*t6#<{JMC%u3F{^`@F6K2)FfBzjjc3_es`E2iL zZf-_O68UGeCZTY&CTWUfEkeOd4S3hCT?-d3#DJ#q34DLz#0lG4j3)%CG4cZk4q)8J z*sPio0zx3$2uOW0+v^+i?67e$QhW94g-f|hUC5aG?r07NHBRYD6t@bsCOg{b^q&Sl zeE7hm9BmJiFh*P(Y2`$sb?R6zgn$qb0%Z{pLzjg|Zx$ecmz!K+!>=wO#V&WU48H=}_qTX@r*s+TjFXBa5uwVhxPuHqxv_e1#c#D7- z+S{c`>%b_$dGzQ}6fdX*g4h(g6ltAFSK~%OiID(b4X3gr|ySJZ1)u@Dk z5J)uwV(3&apYMZz_wF6~7LXZ5I$<)7^ctGvHzPrP?%cUsw{DSa##~VK2*i```*Wu8 z34x3vAcoH9!g@BX`}gm|ZC9>bp>_wwx6$E16w-KR9wnR0{N;q>=g*%=WOCp|$1?u@{X2PI-@bigJJ}qxMuAep`>-S`10k;=g*&^TZk6M<%Fy!HjE7)o4?Ei)oOSe zx}|am2fPlQS65fV%KT*`dC;IiBI9%{xkf1jf=56M9sDC80EB=L5CTHLO9Z43?d7s) zP(nZm2mv7wJOX0q;2!}2AOwVf5D)@hA|QtLa#=JeAs_^VfDi~C0Woy&kAMIW0zyCt z2mvn<5JP*pEE<#$5CTF#2n3IS7&`bzKmZ5@Obi*{8tMe;PdBYMiQd`YT|0cPogQWL?r6qY(~V+z{bEtA^=N7 zM8xN8YR;o9Ch?!{z&CypOIKG%9!5qF4-W?jL^ zN)q%_nA(b3I0YFdk&8{nBXYh}B_R$W!Zkc!2boL^SseWvBSEL+#)JF-{Xh5o>~8V@)BVr<7h&Mf zw;_M>K3)%P>N@WW!U-~2%tk*yZhpLNnuyc#_Q<>n~$l_kt%f+wVI9~tfxjg&U74y^DUl+}D3cS6taU~F-qQXREw@QZb z!d2lQC0@XQo^OF(`-}lkotJ(NcbExNF$TU@1ARz>f4hh9J^r3GP32Az&Danzl>+Zg zFo#Pxb^#NJ>+t((m^7YmI|S_@FW^0w0WWzlnNm^Uq`W9j;Q1&NQ`=H54Q~t{99D?v zbsFM3o~SBrVAGVqi_hlEMnzff^EOhz&sEwHyZfrzj+0*-ceM)|25%jwwK|SH5H7fs zJc!_faDmeWL#O^j);{7}8$OroZcBQ=1dV1`mF!~+;b(zvL41^f8 zJ8#$!B0>Te5jhOBzU3x?=6gA7`W)!fVV>ZUu1oB2lC%CGlK;Qp&z`+-jK#`_e5$U5 z&@lpl0Z4uj48gvL3VmI`>V6!cZ(R<$YV9T%ys0FO>a?x9uYE7l0N=Q8Z9D&cGij0Qb@1`l{n55$Q{)Gj&HSgiVa9SHg1<-pIWEiV zdVfCs7z%imB$|Z+b*??guproW^V7xs@oC^uLQ+TQQC!eKTafqIHTz$7$?_a9V$Tv= zRR(V-I2PGgz|dpDAVxgMsLX(Day&%#sM zLZi=ylp?Ymp{Im#EGoP=q9W6TM# zzyM-o)Mo?D{%=J22Mv#^h?Z4_Z?m$Do!6tZyYmZ z0GNXNsuktoLXhuXqGaa%$B^K=6JXj~lxZ5JAI($aNLw%qZN3A`*>zMHebIhMkh4Ws^qVG+ecg4A{XALf{duWdA^iRv*u8vfwoUAI2V~~* z9Ou9`@$U_RA$&WM1orzNVE2ixWzi1xJ&-lEjaV7xnN|@~W@%aneT46h{!g1OliZX| zfi02)N9qqGlTe^F$k6y57%WcyXULvU`#%I9dyo#=&SV+dL-L=me{{>SZn#YG8~B{J z09(9z!LhIkQ_po~Z%xZQ!wgsh`-P+!!H?IQc)@qiAg@^V#eC)HDeDC;e#Pzg&rJ}B zX zlb!xZ>8hJa-YFbRbI?1&k4H)8YovfjQD-63%I_I?S=cYFyQ^vMa$n~PG<2QB_3fnP zf9QK3d!N<}t?AiR)pgRG=S@xsp0Dy={4{wvZ~Fn}{;vm$vd`?Dv8s#Qbi>XS8#;y$ zv_Lfel|Bx_JsN~M$)H`D=PDRU;3wcm5=%!cmh?P2-|pA)yiY2$EOJuQQ;6Rl07DKz zQ;;eh;~#&MJDQDrSobh6;Qj!tc{5{(FyQai-IBqjHWZE1H)ZbPj~l@cmuULde7m`M z46A#L)3$)Ddxs*!0H*Wix!T52nlZ+1zK^yvZohdV7?>Qi)|qol!1s7JUpiFRLV-(F zyq;)DHvkeT?-@>!r?$9}74P!EZL1^Oa$ZG8uW?w<0yaCvgwELhrn zJ>bL}QBizT97=w)@cst`A$gzD@3XGIx99?Gu#$cSxU$5F*a*dUUHW zAWSsP4~jy)$ge)*+>b&;6w3L-H1TzMHW}RIN>t@k{QD16V?ViI-fXY@c(~mpA;WPL zXc+zjBq6#F188V8S~a0Li_Ov883 zVqK3hZUVcH-KIKvzZg}MO5XAY*RDBHAm_fUz4Y4_U2&^ z9WDA?cD9-H=lvAlk3ngUb!(t%tTgl8r!|m%=5%#7)cpmn(nz^=_zBkkmd2?&ODld< zhS-TtGYiy~2^2XIF;RTZNir_}*jWt73I%n)!$Esu~KYRZ{}5JrwcU*+LxvW1fAyPJL_%$krAz&(*l?E0S<*^AVSE0wJVWSQ~3h zKRTBzT|_=5(beuA(NPV!PVHt>Ti2LV)a z4H)?@7K0{j(kJgzoz2ScYK4s|afz8Fw3Idr2?q|CkMem6Q)uO;?NMVeSlDaqtj;12 zITXfEl?@DOGCx$$Ki$wBXXBKZ(~_MvpJMp%JxH$7MC%l=E3nbPdy)7lIC;`mFhEUV zs%$mneXPW2=Hw%1sZ~nz%P1l-e8rktdSPkt+~&W9Ff)(5`vS3X@m_|Bm3I@sUL?J< zHzXb0F`*s>2lvFTID;xqS!^cz_SMm$M>?Ic#Vk-wt!d_|?pd2(_(Vkxp&V}cRzGL> z`~|n_6d{moyt2)v!_x1pVQ6QO1R zU4hTn=A}XBLDk>y_if!1PWC_b8RPE*|D==tYkhmz3>YVl*oOjbfd+B{+9R(W3!dnc0u zBRsEG#C`=xewWuN?x?>B5M1A5WVQj)5!_Inh!5vZpgNClcT9n`C!kYU2g=q37EP!|f;0?Qa3DGj?bKU7bX?UMbk^VXnrQ`%HJW3$|;N#093 zsE#;7yFV~vGstHZU5Y+Q&L^mGfi!LA0qEKVztSxB}ia2V^{hptpr_s z9tg>m&qcfB$NSx6&->uF9FP6@pEZGhkWr3QL`=X2*SjBgqKodu_XYbQQmidgzaR-b z8bY9|{uA%kt!y7KeHIluOKP0Zt+d)Ne}BdauOje1D(JjlJxx(jC=fmD&=0!>f*1rj z9P7_=pS(}#)*gqQ0|ih3`Ghcjmz@u&Qz6KmUR22pPx*X5I2cf^`z+M2c^CF?82~%D z1X4r@=v;>$q z%szna9r;F4sn(%u63ZT8eQ`1%k^f?S}nGl|)AbMl<)Tl^YTQ1c`kkY}(luu}k*Pt&p2syvbs=eUa0 zcbySeY4`j)7`EEgJK4T$%1(YyJipkAiAu6S%;_o9UC!U~xD zPj-oL!koWs0FDbOXHWSoRgH>cftihGf@!Zux>9u?r8Q>+zu70jmP8&dp(w3$(PD>2Fd^m7Q0FTjD{(!v)rou`#2;NBC_Pe8E9}A>d@7;|663Z0NnZ79mTpE17epN!Vu}{PD(Xx%`FJ*Qvkl~NNxN8fPe@W?gyK3 z2{5~^Q~VFv0Q)6X%ZAC$0`0n3Ks^opr4V(KsO|TQjBjuZ>XJJ27wX@dO1`59{eEwE zOKq#xv>dD~)gqqvJZi7~gc799Xl2evBeFkninw?$gg3A#?#zLK5btqs392)m5jcnC^5xuL}T+ z%N-|~19^de98r#{Md7OdfsZlbU5Hf)bX2y@Q>gb>GLjttrb6{pjOg-=xS^)NZ`iNG zXbO1Em-#Y*)H&pmlQfs-Y?sNWl_~$y>N~8ie-O;)C7Jqi=C&y59dDzb-p5B%l&?*) zBFiCTrt9t8LAIPe|7Qd!7^I9KythEgWB2=A-MgLl^lkBdGpxa}Qd}(Z=3X*^hs#!y zRcS`pD2W5tlMvCk3vh`&;cx6c=_eoSQ0L3>#4CUXcA*^QixPVLb<)rOBtM=Bh#2Hh5^y_L zt*iVFSo5T(TwRC|!fd7`wS3x}1RhCzlXmwEdY5rNWav;hw@_K87Nf>pw#a2AN(oom zMx4$AsfYuf=kYBwice1FY~N^Y7R#>kk4Ks_v@ M4{XW56_8b9bz?U+v!7&F*v1m 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 **Note:** There are many, many ways to implement graphs. The code given here is just one possible implementation. You probably want to tailor the graph code for each individual problem you're trying to solve. For instance, your edges may not need a `weight` property, or you may not have the need to distinguish between directed and undirected edges. +> **Note:** There are many, many ways to implement graphs. The code given here is just one possible implementation. You probably want to tailor the graph code to each individual problem you're trying to solve. For instance, your edges may not need a `weight` property, or you may not have the need to distinguish between directed and undirected edges. ## The code: adjacency matrix From efe956a55dc7e3dfa84d3cf4586fd250b0f98933 Mon Sep 17 00:00:00 2001 From: Matthijs Hollemans Date: Fri, 18 Mar 2016 21:01:54 +0100 Subject: [PATCH 0164/1679] Replace animation with my own The original was apparently taken from Wikipedia and I don't know if we had the rights to it. Besides, it was ugly. --- .../Contents.swift | 5 +- .../Contents.swift | 8 +- .../Contents.swift | 12 +-- .../Resources/Animated_BFS.gif | Bin 33276 -> 0 bytes Breadth-First Search/BreadthFirstSearch.swift | 3 +- ...readthFirstSearchMinimumSpanningTree.swift | 3 +- .../BreadthFirstSearchShortestPath.swift | 3 +- .../Images/AnimatedExample.gif | Bin 0 -> 9713 bytes .../Images/AnimatedExample.graffle | Bin 0 -> 4912 bytes .../Images/AnimatedExample.psd | Bin 0 -> 582072 bytes Breadth-First Search/Images/Animated_BFS.gif | Bin 33276 -> 0 bytes .../Images/TraversalTree.graffle | Bin 0 -> 2088 bytes Breadth-First Search/Images/TraversalTree.png | Bin 0 -> 9817 bytes Breadth-First Search/README.markdown | 91 ++++++++++-------- .../Tests/BreadthFirstSearchTests.swift | 4 +- 15 files changed, 69 insertions(+), 60 deletions(-) delete mode 100644 Breadth-First Search/BreadthFirstSearch.playground/Resources/Animated_BFS.gif create mode 100644 Breadth-First Search/Images/AnimatedExample.gif create mode 100644 Breadth-First Search/Images/AnimatedExample.graffle create mode 100644 Breadth-First Search/Images/AnimatedExample.psd delete mode 100644 Breadth-First Search/Images/Animated_BFS.gif create mode 100644 Breadth-First Search/Images/TraversalTree.graffle create mode 100644 Breadth-First Search/Images/TraversalTree.png diff --git a/Breadth-First Search/BreadthFirstSearch.playground/Pages/Minimum spanning tree example.xcplaygroundpage/Contents.swift b/Breadth-First Search/BreadthFirstSearch.playground/Pages/Minimum spanning tree example.xcplaygroundpage/Contents.swift index c0868c653..006ce1873 100644 --- a/Breadth-First Search/BreadthFirstSearch.playground/Pages/Minimum spanning tree example.xcplaygroundpage/Contents.swift +++ b/Breadth-First Search/BreadthFirstSearch.playground/Pages/Minimum spanning tree example.xcplaygroundpage/Contents.swift @@ -10,8 +10,7 @@ func breadthFirstSearchMinimumSpanningTree(graph: Graph, source: Node) -> Graph queue.enqueue(sourceInMinimumSpanningTree) sourceInMinimumSpanningTree.visited = true - while !queue.isEmpty { - let current = queue.dequeue()! + while let current = queue.dequeue() { for edge in current.neighbors { let neighborNode = edge.neighbor if !neighborNode.visited { @@ -26,10 +25,12 @@ func breadthFirstSearchMinimumSpanningTree(graph: Graph, source: Node) -> Graph return minimumSpanningTree } + /*: ![Animated example of a breadth-first search](Minimum_Spanning_Tree.png) */ + let graph = Graph() let nodeA = graph.addNode("a") diff --git a/Breadth-First Search/BreadthFirstSearch.playground/Pages/Shortest path example.xcplaygroundpage/Contents.swift b/Breadth-First Search/BreadthFirstSearch.playground/Pages/Shortest path example.xcplaygroundpage/Contents.swift index be35cc684..2a9c1676f 100644 --- a/Breadth-First Search/BreadthFirstSearch.playground/Pages/Shortest path example.xcplaygroundpage/Contents.swift +++ b/Breadth-First Search/BreadthFirstSearch.playground/Pages/Shortest path example.xcplaygroundpage/Contents.swift @@ -10,8 +10,7 @@ func breadthFirstSearchShortestPath(graph: Graph, source: Node) -> Graph { queue.enqueue(sourceInShortestPathsGraph) sourceInShortestPathsGraph.distance = 0 - while !queue.isEmpty { - let current = queue.dequeue()! + while let current = queue.dequeue() { for edge in current.neighbors { let neighborNode = edge.neighbor if !neighborNode.hasDistance { @@ -23,9 +22,8 @@ func breadthFirstSearchShortestPath(graph: Graph, source: Node) -> Graph { return shortestPathGraph } -/*: -![Animated example of a breadth-first search](Animated_BFS.gif) -*/ + + let graph = Graph() diff --git a/Breadth-First Search/BreadthFirstSearch.playground/Pages/Simple example.xcplaygroundpage/Contents.swift b/Breadth-First Search/BreadthFirstSearch.playground/Pages/Simple example.xcplaygroundpage/Contents.swift index 8cd7df2f5..c761d9e99 100644 --- a/Breadth-First Search/BreadthFirstSearch.playground/Pages/Simple example.xcplaygroundpage/Contents.swift +++ b/Breadth-First Search/BreadthFirstSearch.playground/Pages/Simple example.xcplaygroundpage/Contents.swift @@ -7,9 +7,8 @@ func breadthFirstSearch(graph: Graph, source: Node) -> [String] { var nodesExplored = [source.label] source.visited = true - while !queue.isEmpty { - let current = queue.dequeue()! - for edge in current.neighbors { + while let node = queue.dequeue() { + for edge in node.neighbors { let neighborNode = edge.neighbor if !neighborNode.visited { queue.enqueue(neighborNode) @@ -22,9 +21,7 @@ func breadthFirstSearch(graph: Graph, source: Node) -> [String] { return nodesExplored } -/*: -![Animated example of a breadth-first search](Animated_BFS.gif) -*/ + let graph = Graph() @@ -44,10 +41,11 @@ graph.addEdge(nodeB, neighbor: nodeE) graph.addEdge(nodeC, neighbor: nodeF) graph.addEdge(nodeC, neighbor: nodeG) graph.addEdge(nodeE, neighbor: nodeH) +graph.addEdge(nodeE, neighbor: nodeF) +graph.addEdge(nodeF, neighbor: nodeG) let nodesExplored = breadthFirstSearch(graph, source: nodeA) print(nodesExplored) //: [Next: Shortest Path Example](@next) - diff --git a/Breadth-First Search/BreadthFirstSearch.playground/Resources/Animated_BFS.gif b/Breadth-First Search/BreadthFirstSearch.playground/Resources/Animated_BFS.gif deleted file mode 100644 index d8fe07cbc40a0a19534b597e123bf803de42f205..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 33276 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 VN-uB@0x#iI)bv$Ep$#Yh{{eHl({ca+ diff --git a/Breadth-First Search/BreadthFirstSearch.swift b/Breadth-First Search/BreadthFirstSearch.swift index 31bb1c594..296bf42ed 100644 --- a/Breadth-First Search/BreadthFirstSearch.swift +++ b/Breadth-First Search/BreadthFirstSearch.swift @@ -5,8 +5,7 @@ func breadthFirstSearch(graph: Graph, source: Node) -> [String] { var nodesExplored = [source.label] source.visited = true - while !queue.isEmpty { - let current = queue.dequeue()! + while let current = queue.dequeue() { for edge in current.neighbors { let neighborNode = edge.neighbor if !neighborNode.visited { diff --git a/Breadth-First Search/BreadthFirstSearchMinimumSpanningTree.swift b/Breadth-First Search/BreadthFirstSearchMinimumSpanningTree.swift index 9329a0d3c..92d370878 100644 --- a/Breadth-First Search/BreadthFirstSearchMinimumSpanningTree.swift +++ b/Breadth-First Search/BreadthFirstSearchMinimumSpanningTree.swift @@ -6,8 +6,7 @@ func breadthFirstSearchMinimumSpanningTree(graph: Graph, source: Node) -> Graph queue.enqueue(sourceInMinimumSpanningTree) sourceInMinimumSpanningTree.visited = true - while !queue.isEmpty { - let current = queue.dequeue()! + while let current = queue.dequeue() { for edge in current.neighbors { let neighborNode = edge.neighbor if !neighborNode.visited { diff --git a/Breadth-First Search/BreadthFirstSearchShortestPath.swift b/Breadth-First Search/BreadthFirstSearchShortestPath.swift index 2e5a9c1d0..13ed0c080 100644 --- a/Breadth-First Search/BreadthFirstSearchShortestPath.swift +++ b/Breadth-First Search/BreadthFirstSearchShortestPath.swift @@ -6,8 +6,7 @@ func breadthFirstSearchShortestPath(graph: Graph, source: Node) -> Graph { queue.enqueue(sourceInShortestPathsGraph) sourceInShortestPathsGraph.distance = 0 - while !queue.isEmpty { - let current = queue.dequeue()! + while let current = queue.dequeue() { for edge in current.neighbors { let neighborNode = edge.neighbor if !neighborNode.hasDistance { diff --git a/Breadth-First Search/Images/AnimatedExample.gif b/Breadth-First Search/Images/AnimatedExample.gif new file mode 100644 index 0000000000000000000000000000000000000000..8f57028c78a2e0ddc4e8684462d8f40e0c5990d4 GIT binary patch literal 9713 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 literal 0 HcmV?d00001 diff --git a/Breadth-First Search/Images/AnimatedExample.psd b/Breadth-First Search/Images/AnimatedExample.psd new file mode 100644 index 0000000000000000000000000000000000000000..836fb92474d5111756178c14557ab60fc8481274 GIT binary patch literal 582072 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

JrD}hpt4IQs9(o0$t1jGgX?#UDlz^8mSVhS z*qeH7tX#kT2lMbMGx^YYDeUY2F#-ri6Xd^q5>bxvD=oc5Xq3@e|Y| z?AudC*uwK=|zDT}Phb3$7eLMv893xXkC5dz)XLwMFqkAdN%3U-nD#8yMfu z^7E5OXV6;$h+81q-w6%u#{nNH(|Nlnx>zLb(N|Iku1HAqY z0XqQyBf3+z!}A#C@Tr}a=-J!J=c|VKQ8_JmZ{~w)1}-cb<0Ze-yZRIf^yK^aug1-> zqB@`UEtJzjEDCUd>SvClMLQG_EK-Cq{?!+?C-1xkw^{f1xWU`X_wi8uZhGxyXf?OA z2vvR5RgKxul2H$vyoVpPG&7@rDhfkTD?67F67j$$Zu4xWXfyOq9Y#>}aug$JLCX?1ig*v`7bU1?9I8sswOyBcG1$ z)g*_mnHeV+%1%R8w2NFt^+XS~X3fs=M2j5!`HVsZk4)BG^YYXZpbJDp^ zl(r5~Ywm6c_uWCC|AkMO2i3&2>v~4O$|O%DUghxzs)0?~iTc-L)u;p2;6Ie7jR^}( zHiXbqZH%a7HktIqTG=lU&};+i&lM8!kd;@U^v(IBG1r`RhKfgz(;E1@!GOImDclSZ*o{G5R^yj&P57TXd2daSEG7g^3~RASHJe>cmp}b)R!OD^_*c&^^X!&y8fd1aR!g# zR2b|$ensP<3>G&HjA$l8QSr{lD>=~iCgnb(iR}a(kgdN(LlwrLNaL<}2s5(amy<@J zvr5%{+w1KjpG>d{X}IfiTll?>`{k(V22D5ZP$+}o?J8gS>DR5HXcTK?rQGRjP9~BD zY7_gn*Y*4s5pLP3{#6Y>;?!MXEUeR9#y^e8%3-Vwp!MDU_WtQD(j(SQ?Y>J&h+*=} zA19#RJ@Zt?$eM9Xc23VgnCEWG_L)et`Tl$41NcT`v*`Y~A30r)?w&0*ur$#|@}av71t7~?$&8~Z zn4|lNgJiP%S&D;xo+}+I>|5;njkunXGGq#zh5{Sy#gL+3ji`^6hQ#KjbhU{gR$*)>iLX=ATu3u=67EoQ@8g*rx25wW+=0&h_BS_7)Nx%ob978gIL_r1|? zy&8C&XnAdp9QYZG49Fr6~Q@W(z$*8B1@7>XKhPekhK zt~lT_2(rpu{`UTS20j)(wl9m;`CPGSuA8xMd{9Ma{MV@6@4A{7STmEP<>^|*i@M=O z|H2NT|G*AR@e%=0jDu->;$PUI9A#7f?ct4YB-jCt#|;0#4!A28{D(a`9@7x)P$JcQ z+6k(AYrTn5J0Q>7+kF{jw!)|^M5eL>zCG^7Z$KjaT@n;Xs-Nk5-Y4dG|NIAbAXSO1 z$)6O)0r^&|@xAw?oy<#q4T_e;>gZb?yb_a|H5F5Yium!^2CcUn|7?ujy(8}?1~OW7 zk{Dw&%w7-9ErAC0n2)UxKf7jJQfqyAd7dLC;7z6bGwnnrLs5Ks z5dpy7$WR{#9^GHC!A| zpGMJVOs3%}IY;Z@-trfA`1ZR<@N6_nsLJ_MmiPr$f7l-RC&Cz1 z*T{n6qI2Gav%gL}&Wlag)2$wHcr7i(OWPkqKUE}QQ_Z_97em_a!~G(fp87@_S)AeM zFylun(TTF_Ux0#%EcX?{rkb!FZO@44!YQ0V2=2`fabLY z)&ZsYsZPKG0IvS%2{@{x@QGpyOv;oI-T$%82=c*) z$VV8qx863er=5LqBiDNl+_yykAsuuYTG^bX2oEjnl{r+7XPUfbC5)bWIzx5P7q

%^z zQ{;1EQ4vCTv%+Ty^DtfDfASnGo@9?-XyDn8g(SOz@Agh*{O{BW)h>;?3K5_F1sznv zmPh#xA@-ySD+~?DI<4M46sPI`$n5^)L5Gg5apP$k zZ0MS6)~W$)Qk?H{ntuQGFxE*xS)4fer16CTrJJZW0p&hT)ptxm#3v}nqqgr36*)o?-(`K zMu1LeAR}teqk($Ub~Kyp{-YtL;9Hyc>?a=nCDB!B<$p;By?;oDlL@vLn5F-c4if1Y z66v6|<93p}*RnC%F57!$l{{hhzDjipxf@kufsH0oPyRBGfHdc!HMV}s=`aUe*avR< zxP{5XLYuK9k^@RIVi`uqGO;vy^!fbw7&5tqRz>K(DX6(jJ->TT|3w}2{y`n!jNLf- z5Ry5U+rs`q9Uel>3#fw)pbi2~CBjc}p!Qn~HP*V5o12B}Lix{7<%yyHz~8-C+rq!N zp?JrdEj*Na+di#9?i~dg zJ&*s-Fere>)iMr_>UWQQ={ku#6o*;m>>e}9756GCpn1hlSQib2gABxbvd*j8)txkT zsAyymz2p0YHC4UGrDZOc7R4yd1C#D!MH-FpJBaZ^`5EMH3R^m2n+vhese}(eVO;-z zvG<`@d)Qp4l_|&F_UXjw0Uc=Dx4%I?wa?97h%R$a6PR?zWIWymVN7&R<8`k~8B% z>XWW<(TOeJ1CT_lYDzr5&Jz@?BJPjSumi2=25u6_)j_*y)@ZLm<5dL29tijOmI$>T zPAbilNZRA4qy76V}syc38q)g?pF^t1u==ED)HNh zk-L&pc=y`Jbn0-z57PiZtu$-f2eY|WVbjNVqj1X(|ATh$g(e^zm&xzd*?ybHN>*n~ zT_pu$CV0GJsqW!K5rC3?0W=a~G;8@aXxgDC!JMMIVnuqMH<5ct81Mru&CcXc>-{Zp zG?)uaiCl=wePUNn;S>Vu;bOBy9V#PKGBu{fE5A1AM}r&LYhxCojYWg$lHmc#d{SpZ z3M7VARR_=AcKus;dWk_603`(9>KcinG%CpBng-yP(U z>}&g03x>}^?h&b^fiVA@{;CXvfnu-QNe>6TSncc6WC8+~!jVx)OQBC)Goxfyyoc%U zF%hkPLay^}$Ga<;8B+QAm|lC5@_AvBeUsY^BE+DehD4Ig=o|DcrmO7pzf8_gJQx=#L<=<0l!tON~TqirKYoy=mryMXE@u;OKXz`k&9?~eZ zXoW7z6ab2|rN8D6(+KW7bSHIjc~ZuCo(;okpU4 zi6er*P$ z-;1+m_ypw_jKC^CUs0tef_vL@-n-76yFoDHgkXOB>%1~mvhPoQtdR=eP}&COcZ51rFh^|{ewGTYp3o|V%xX~;n$}sFpM%{!5v$U6}_uDS<-yBKseB0^U5ev1V7Xz4{g^9g|_f^DTc#^9>LV}>mJ*))FMlFL+4^NIZ>%!z7N4Po-R$qxCj5@9UvWS z2qtwYj?K4Z8wl9rZ=9of2dMD?{EB#iTS5uE!a4YrP5` zQvycooJ&}d)t$7eph29_P`TV3{iX-4^mEX=<9q(pd5?K}!@(N|hvjnLJY}$P`rr0n zz46u11$eZ0K2u?!COcxolxPCH1C*R*|CM)GNAnJNw^a_%{jq^aA{ZK;LrRiAtcWn1 zu*{;o!EnDf1hZZnTQ4#O_8iO3*g!l|b_ORkA!0mLlQs|5=TFCIyh7+OUq_l7>t5kgn$1#2xm9B&e6O>_bq1jYOoDTSAFDkFlARnbXcRX zlrohsgHd(sAgly;toXUso?xbv_(4yzjc*mnowABF4K;B@Fo*sucSgxn=oDQx zTfLo*Y72qezXH&}!_R+!2L*8e z9?G)+e}M-S01qMg#j39*^Yym~$?X55okgheUF0*IURL_nMIPQ04#kig)Hw7^z7yk$FKt{0*3jaX>9zf$x*Sq=;@DPOt9^BEu18Cx*OnK_`3Fi0# zaKMh-N4l^h6I6)`SaQSBZwN6klrOFXNUb8l>$V0Y&_G5!f(~@uFjsE9*SD!-|LD?q zPgR)`QZB0jhQF2^%|5=D&m;L^tQma%aVs&5m!6J}Y>PoSpJB3s&t0^Gy?SY{<6SG>{4!GB!^C|7)c|6`&#z#m zzlO#g1gOG;chLbgKyA=Tcqtc`Q@UO4I3ZG@IS^Xi-dTKm@KER~v1gaDXr8|`s3jx^ zm2vrhV6r}e?Cj^1T~b$ab~E^_kO5__9O<-kp0M8>ckS6|TypS_l>d5iIISh~=jPIh zCg)#hH4|6%m;cuLDP7=$rTg>X86L7wiiJW!P)!v#^fx-97hfLS!i=$ z=LDHx)7*RJ6L`~mM>#pjKNEcZmq6x4{D}KT87ZFFGkTNX-%s>4k@F-jl}_iH%N{{` z35mLWSa^tL6!WD*CUG2P_LNB7d^{GpceLjkvV>0Dv6fDhr5)Ll{#2KB_=pKoR*R0V zF@ID_Um=6;v=-}!=9yZMdxS{uiYogzfnt@Wn8Tw6TayOA)*$*lOChNo1VtPO<$v=ORnVj_yx>mumw8{fdG7V?}k$#o#bNZ&t536`dm_0g~bhU zANzrk%lV(*-Mssy>;;CLgG=v21A3#3)JpI!TPJGY(T@&QttX4>uyQ3DNxxL{3T??a z^T_Sv71C$bf>-d_-^8gBIk0M}9)bKYOc0GbT&vaA)#E6zJZdC9LR=JIvo}ds=yPr7 z9YU2x$Kfx-^aC@EO|Nn22xyG#Ehj{Z-iPycGhNtjkXOsJUt7>E3%itck-T6rnkNL5a1Ksx%FuflOuRTJ%kfx4HiAmDX< zZ@Rf6>TM{FHb-Asp}I02C96OEc6fZm&i3nsIsemNen7KlsuuhI{q_O zu~w`*ctnZ`T-}mfUku&#M|p?^{%GN`7a86fMQx%6td!Kx!5ou;_=+MEc1ai>Y0Nv1 z$m&oPIkO(SRuDWuPhz9RA-+eUL63texlciSROp&E3qWgc|` zBnZwy6!WT@X-_0s&lZU1m{>sHNCfsGpphmb0XeTRqAC}>*=0d$_kZ_~k9i+HX)Hc_ z@uc>DCLRPR{zu-y=Kp|q5c^;84*cE!<{kdcJN$3(4!lqQlXrMWIy)O-p#4e5M2J$j zhBZCXR7F~+mz7CPUY;*n&Fm79Mr=5xXdz*9vbJhZ*!yZiZFy~mAcnHYd~KCre%AF@ z42;plm<5-}PICG3zK9*XIsAUH_+#n(KN1wgZ*O)jh(Fp!Yhg;_u_J@9*Aja~+FYBd zc#upC06j3^mHn1R$uo4LY!L^QPnyk8^3vqmKZ79MBmid^xncC%xefjqcm5)Rh%oq^ zI019K_Q$LT5h21vx(fro#R)3|Ub@BS%60ht)i7xkCl0904yBd?S|H`P>*(V))*VSG zjVjcuZZa+32(Dfy+pO6yO!0&6AqbNKVaqMm$eKg@|Ns8fh;E2w3V*qZ-eiqx%ue=( z=pTG)t#^4}11IM#7_>tdw2(}?BuaW8t~bfy{@pm}^G-mFs5`_f+5CiDU$-fh>$D!j zjK5TY5qN;kr2|{$3$W_|AEQ)|>)mgRW7FMID9O4{n1Jaer?scj2G|7nZ0P)f6b4Ta zg;N;{fmRd5S2+XFZgO5|skXYoN`hFx9!7qA@mzl07wCw~_%x9`H`kN(koxDKbF&l$ zUC!f41q#gJ8g8Zp2}E^haZSh!3LR?*-5v?|)d95UY&zk*#=beUV#f)NAkoK|ag-Iw z0k>40C?M0o!hMh|aADu+Q>!~AjG7^0UL2-A9P)~MS5($D!h*OhIp_6i4#7YB6{Mb# z^P1C4os(tCFoK1RGZYZUGIMTXcC!_a^H4$rUrEx>MqtW5;GGIZ7be~L+}JYE$l{QP z^g*jA?D^x9uP<`o4t}3eGt;f#TL(RdEjEqox1ttf?pUht42x+DZd{oLGCsKo@0UTDsj|B;PLrugVUGmx|sE3 zuP$EvRp@a>HUt?~UYA|L_G$j?ywfm@0W{|j^MFtQli*X?GvYWH4>?MIsnFg>>A_uDLwI&QQyAAOT7~6s8Q(AL}p?& z>G4jg4GLg~bDVl?b3K<+s4Mt&d-66>T@1XCcTXd=sMK|>Jw3C_S@0Kk`_$kTT(z1D;bQO2pL};J%^`Q;;WR_RSyR%Ih4M3dF}zgc?=ot! zu^h?58W;O~w-EcBG1x3x(&T);8|AagayBm*UP!YEY*DsT-VT7pyd28 z7>2L%l6@bB80`w?Wy#!=YXuY-JdhuWXvK9a@zzlB?d=kpKqnUuYpJdtdRZ53B@k9F zUBdb8kKDot$Wy|91#$NF05#FLv_1Z{RhFry16?i}39mBz=osAcQI+tZxsaq4*SkDu zk!R`slTaWZ4u(c~Z(546ziIbYWgse3k@oM&^l3Ol_Xp>zik?YCdj|A3CGMn4NeTp7 z@o_#dg^QhL$_wb4=iWex6SM60VP6}0v*I>CeYn7kBi|#1hzq$895Z|dO4MJ_Y7(h` zW)%=ibM^&J4xB_9G3ir&@Y;7mExP@>fV;k+1WZ6@o>c04|>{ z=+GE;h<>;of>mb18Yuamr||q?G2A9c5DoJoOnRtsKbNs z?{EG8_J%m7ue6jq1^@RAncWr|L{jtnPS6Tj7D%aA&L{l|W|Cd-hT}XS((I$S^I)-4 ze1+2>CkF-1FCmC?fKg>gVE3O>7xP%&?(+t>`tPtdy!`BaZb&WSIuE@j*iiQ$z^1(8 z8kwVO&>z#JO}5z7#Dd=;VYbNf=ssWCa9!8y4;8e;^D9v~*Ip{{*3@Bwnj(SZ5=Pp#15I2}!|9O!fD zXur1eHR%o#cIdu@Fkht+O~y7%o=2E(=v9!%`9CtPbK2`~zI zF@?(FA~Vlw)=SnPuZv`|phz?Gz}co=nXsrwUF)5qQ1(%Cn)l}Ymb9DKk!45PR&##{r3I?`oO^QmFPxCc5V$CJnd&sbRr;I|9+jbbEMPs`FkcjN^xB^yaARI+83Djamdyu zkhl+)U$TCVrNS&7lWP0;A!q38Nari)#1lNL*sJ16}7f!QT03T(}`+;QTIFsGqz z=}ndKh!K79Qem>*8tGzFkGn)#X&5SM*vU^;BWbB_d5=3a-5>nDjE2APyNJg2iL2a> z=tcB0bv7?uy_r`*;8<$Dny6~^=?hawiP=gV*#nxeN&-qOgC}Ef41mL!P@+u;7qtpj zLR@bfBtJ0p-8nHd4p1V0=YgrfYYvjtUB$>x*aFQ`e#g7n^rR6j)_rOtebg86!BVE~ zq!j`@*WbYq67NPULm$aB#};_z|5$igyM9$mu~TdpWMKjidf5_nQn@V!va2h@%CIP9 zB<`=U7TxrPPU&Lc-;0%)QFWZ>U+w}(3l2^SJ{MDN0vWw2_Hx()1zPuU%s_w0`2HS$ z;KPRx|5<<%aKsn1qtgV<=SxRwu>pb=@DTle+M5 zI%XDTev{#JJ->iVS{`%N4p3#dYps29kkVzpcY$i6=bPY&Y}&HF@eRrzNmw}^w10b1 zc;&oFY%i6WUi=`IeV~(9zJn_?Q-kzioE<~!@CCTsWV7|zg;q1=olJt@Ts2C;y$h+K8?a>{<{GH zgu3&MK{f90;E8g%XUrNeuqQX*)ampo|42rJwH@LhfBk3kb2%WX&Rnf&_!2J`G5l4Y zLheI*aIdrd!*p6@uLToE9K#R~CsFlRiwL&(H{zQ#pJZ+S2;?7wT`Hgm&sCzJ_bPxf zp;CeqO^}XzPpC2D&b(5{=Ll*+=R9yy83(PIy30deaob0XS;R2 z4~iAOWhx;@?Y(C=1f=spV>s}`-YEwERr0n`LGLER`CRegH{y4P7VYPivvl@!bxq?i z@bIYUg_P~5(~p`lYo-p{Z@@`@d@xJ;XAqej@}=XsOV+ERhM=YxW;58|&;fzVKC>2DVs@8l~Ys0?aV)wwu!Sh zy)Izebb~Up;d73=yJ6NftB!vT_BJ}|e?Nl|3XIR+e@ckkijrX?^@r(roldxM92AB3 zuL#>#C|6@TsOH$kP5$T>U^qD$E#wPe10W-5TKQgy3v00meMH{e_W8Ek69LZ0pv`&TKdVeEFY_?F zt8hQB5sr1gmLM?x=q)l-r|$}*kQkAKZJw#sW3yoy@JW(#eEmn0hNc&r*Bo7O?bT~okE>@v&G_u zk*0qQ=dS0!_`6k9_=JcMK6ewWdDk_W8-j>Bg>WbsH)8a;|DxH*^193Prm{@ za(!Xqy=k4z>Ff`wA<~ViRwA)76Y=U4b;W$(4W}`6!%9P0PKDfCzWc0c zW{Fm%L~$WpDffTUYW)3BnH8(*4Ufndp(()BA@#t%A&Ls~X3<>VVcxSpZi-eWM5Lw9 zLHE@HHv+8e?IHJJ3ExCol(gcTl;~ly4hMnMIodVTa|-*X)oV?vC=WU}FrfT{*r17hJk{wygiJ@m#J+EjZfJ%V6^;u+^q(`V7n|zIZ*bWMazRju&<)WF zrWFk@u`xX-|I6`JHDhB_;z}7TYrb$qik0{3(Ks@vjNoS2#nWU4hw&ls!4Oy#3Yow? zTDg7!+250sHuP;HPgDemlfq(qoxOyNl(peSq|m|?$tj*FIC@QE_zq*n zHw<#pmq6@7P68uye(ObN7w(0Y4Y!TA@k75XZp@HVW z^F2V#vzoXt^3^lTg?Hu4Vv_nXJ_^Ko&v0c?D_B$+T81Y`xCr6^&@0)8 zq?ZZKhrvnlJxl#Pr}@9W&{xiQO2uz2|1BYJM?IPJkN#tkt8vNIV!rk|NFwE&OM%}q zNNnUIaXO&PVo$ovsbPp? z`4K)%#6_R|WIWeBHoAvObiQlgpDY2I;Fci);~M)v!-LGk39$p{Wlc>@u=}VkD4oUP zX-7l!-~F_1%lEMU8hUpx*6Od-K(!b>i3l7}eG>MIiSv^em42M}Hyt``(rm@~bL}mm z{daN%{JCAL(Oi%`*i8!y@dk~uI=Mh%j_kM~x!&X05b>{x{6_rEo0yxWb@@=v zW^OXT&WPPj7WpO zJV0)1n&5*A^WrO=?wOxO*1C>YW4;-knmPqHzI%`f92E55%_ zNl&4+xd z*=d~X{Th*D#W-QHCv3TZ^W15d-_E4Lr|~FE)F0EoLZj|jKR=q?%Sw~sCAk}zMYuXx zHF_=gKIlqV^4-h+?ExN|4xrSQOXMbtPQa(T0 zu9R*o;Z@0ELU>CaLJak@n?EAw&L^30(b-Jm<@L+%%O4aU;3*UNG`V31IhX{KXp0%3 z-rUzx3~o@ONF1<7hH3k3Odj|(muOd6HQi>$8&-^i3T}qaBZ}8VMI9^QS5gl()rBF2 z%j4i^vRd4?mk}E=H61@BkV=E^X>c7Jgvopjt!xn-VYJk({POov8K`TLeyuB!pBwo_ zSP0pvn;5RSvPla)^!q&i`(g$AFFfOo@tMl|;ol40ye+aqX@r}D^wsmJTaFcctR)oc z!y>+2>NjjlRL?h?OkPtDyCm5i{zGfPfbpw9*1f%wvq9bf8Ez{kEXw;-He7UMz9R1; zFpIf0MTfAb+z+_l3nD&`K&IL*xM2QP|7ML0_Rw)j6u*Ytp%#qF91pi{d9^A({xylR zG7!8eaU?Y6Pb~hPz7HiiB2D2`?`t`044R3aSly)c5L5RyRS?gea1#xdZmYbhLPw9- zp^{`2_6vwHXtcOo%i{VRxlI~uVem0%JA0!Hc~kD;EHUYivz8!R zo8$;yyz9ZJe=0|K3!K$bgG-Sq2-XUmN#dT996qL8yH}@Ml?R(|9U#x7Q3xx(E~=fo zLbiD-{odhWGl4atJpLp=^Qn!R=);}%?V4E@_Aae|4l%a8{>dvY!K2XlZMuYt3>l{i zb5NvFP@aYq@X=(^MIRfe1UY{iEfy?%bwYGqgm8`Ve6rfa%F!+SRM*fyM;-o&`@`~* zTzcP@D<-%8TY_I{cO?DnhBXe#8Z5z_L*Y?c;ODsG z)u{Pf!Hn$qrX^Y22M+j#9D*vAuu+%jl!JIglW)dajo|j7HVK~NsypQzlH6_;sdnAQ z2)Fp-!>ig}sTmt+dJ6l-9iEOKF+m-uuf+Vln;cSa?j4>TlePzEcmIJOI)z95!Uw*u z0z-*}kGj0?A~q2&6cwexI6JLho*f^8d$710&L}%lgv8P;(rQ1sj&QTWOOBqly)PmR z^>!x=HSlR*c}|lX&p1m9SIhl|J$JV3Aoy6XUJp{)&(4yI&b!!g;6C%n#{N>ETY%m0 zcClybrf|&%HFiAXr|~86l-QnZh8e3oDF)V2L0U+4M7?ozOqRndnWvYDZZ(6B69TE& zqWN5y)t@&?*>_(Y9YCITh2?bYW@q+k5E~zfMp3X^VXJ}3D#}=5y;$_EGru_)dJHV0 z?Ul=lo>?o#*GyY!Ajj{m z^C$|LyVH1y2b}xJ-F4f#>>0=%<#w82MV{z>dIaeL+t<9!{iQvNM@nX-#l+_-INXst zc=q9MY!zA=s2KIX5}XPIlD>HyGZH1y5EQk&lrMV}LX0EF)pxlpdEhqE_0f8QMa#v| zb&0SqhOP~@hU9#bJfWP|D5&}wUKUj7*b^x~y;LhYD+x19cYSmA7VR*HleVmAm>D6DbElHzMHAI6;Udw4P8p(jnft2f4w(2VM(CJ8`h^iI~Qk6^+-Gkc7S`yJm?8`vu(osrk*Fwu$uwEVl&>__+CKRPxsRkwa2 znB}fn$m|n6i?3FF_EdUu-DagPOe9O{;|)B@Av{9=3@U7;xB9HF<-oL_?GNq^`mnp) zdov^&LG|}h zT*wy(8l9_f4XCLa>jr+@*XtM&7G{#TlUH|S&Ge{#AzW7LzZG2W6LFGj@Kb_o>}#$6 z^;Y~qiP{#?tyg?uWJ=Uxq2!zN&LfRL>!Bm*PSkKA3RD&AGc&OMO5Z8snNk(g$)>}M zrxK37_jbVD3Fb9oSIXB7>G^~Y5u8wT<=|w#D4RsQ<4{{e)%nX`zguS++_6Ex))4f( zn{to5EZD8n&!8O?9BDU8`T+c9;M(tuqh@N^-V{ zB7eC=b`6Xb7WT?#xJb;jc*y*kVN8pUR!m-c$KIM9d9fr+2%mO?xLp8l)Kfi4vDz0$ z9P}GkU$T^(2Bot1MNpa&9U;_IiWq{%l+b6zApx5W0+EIwolb_RG)DTBf#;hq`$EQs zK$7yMa4e$qqY&AxDT8(7B4K7!7Ww0Aj*bOEYxY)hq`0*^M))A!Q@jlDlI5N1_-j8K%bRdl#Qv$9l%1a7xg^0dS)JZi`1*bv3 zJl$7oF867cjo>iimHGiN_0&J`gg>xMk^EiM@5YJ*Dr_T#BCOXaft~%85$PgJEqTN1 z@1*CQe^FwmowEBti{zZPy0UV6v8yAv(?qRMGJk=}j=>K)*Jyj`@Ak^4$=E>kob<0V z=WP&dH3V^VJ)Sh+qF?!Hyir*UHx`8XVjH(CczB(v6?<9vK6TDW&uesDbk8`&g@`Xa zf-6dwdf)#kV&>Ip5F_G6-d&89!-vbss8&Ddb}W~d<~{~}gXjG}@3Oe_^>`nUSv516 zVaDE1BVlj#1No5`G<$sAPS_s=4#K;`l_2KxwEA2MQktN=dhsPGd)hp)$Z|0WhLXZg zQ??+ufxbtMXVog9v44+P8QWbphdFeE&y+|rvqSG!wOLytW#F}&>&%^(K_nvBREWA7 zTCM%GS{C9|z>&43a}D?qJw__bCrlp92#joKF+2eS*Nz|UmDI#)qdX{LO7sH*ZjY-M zb^_!6!@rgNdlD|)8+jw0UOh=;eJ@5ju^%5Ebhp=c47E_*| z#Lw`AhsNNa7dHbQnwv!x#4=x~;k&v|YlsqUwm}D*m27MO32FxGoDRRV+fiZO>6Zf6 ztsC^&`+HMryd&qcm$~2|5^tlm&b*V}XH95ygZ@>%GwBXq+V?1UU+&70?JL|wKZTz> z-=Z7l^E9LB`Gq2%*{_4-L!79z+l67L=~Nc??UIz{Nj`xXG_W(IqgZlN3kdaw6~On7lJ@{T{pP->557URT4`f#S=jKd31alNgv(cws-h?3&%{sXolG@H5e;VX;{voRL4bV#vW$^^ufnn;tYtRpq$|Z*MHoK*@>ESAAxD-|Z7!z=RcL^VX9k1_a5=CHW5g84+M!xF&uVIK z5Cb6s$+4_++{>(C5bQUjfFvKKsn&(m(uv{U@aW9?DKxdGV#cOA;FjF=7-3Z}!D{mT zWtT*BrFL*Q#RGgk8uzKq`BJnMrEeB)HzIy~>Hs4^dPrylWg4gK^9QXf;qC41*m&c2 zblln3L6?u^V(819A^im0b1tp5Rv0%q65X-NAdBuq{xd}P<%vaI;wnJ}rCO7l^pLJZ zRAe$JW6}HZ-PkKoEziw}vxolRoXCP>vUZNnAPGkaGU~hNVZcI7f%85QDk_e5HaEOm zYek>vRkm3QLy1`F{a=V2y$^p;_A&|6!5>JdD-YFgxnHWkrFex=jUzn2O7(?gzQGnB znLTuxz-d=hgH{N(ziqb_+{~MgPLS+&0Io=Z=h35ud!nAky3yiXNy!aCY{^w>PoHp{ z*-Q*d?9}zoqtJEY7b4f(n6hns+g!;_j)|1MS7R{X2srxSp#J5CdFOHW-wR$H^SW@h zOC_WvsvAy1xFQaAI-|Fb=ASObw@Cx14!h!K0*SBrNtzN-3g!o~Fk`*ht#xqdtLaph zOzS*LdGDyz#Pw{{#7+e0^0PtZ{eu9TO%OQL(;$FZI7#RqbC znS3`@jne*1g=zF;Vy8>1Rci5)=ZU7|iS3*aWl_EE2=6`UfQr0TQ_y$Fm3+x@HKmUm zwX$a3XG&=+#vG|dIQlf$5GZO=)EY# z=KGp+CSnTp+Le(q6^KBqOgL#&08CqtK$xh%Slh{5qA!5sr$o-j*FGa)ort@lslmcv ze)z34PZG)z;_1P3sX)oglPorjSIPDkM6~i2lEYQ4ILYPVB#(!os){35%UxTzmWCMl z_#WhiM54hmh6PqvLZMvm{sDI#p4MO$y=!jJ^W#^^J`md2-dTBj@Jsk=qG#94eb|JW zPv(!4pOf`p@_RlDwNgJCo=+MXxs6+yJ7}8;# zK%@3$;$O51V#{s)V)Q0^@}vCyS3gh;mZx&K+D#1u@HXTmIg|F!2P7WEA*0`KBce2l65hj{Zwi`J9_MV9dR`9*g10v=LS}G zh<++DJvY+%n&PEmrkgm%>?u*Y?=VNO+xwSTLX;c%`lk3wJE}~Zai2O;Mk&Gba~4fR z%Q(IkE%CGSV06cH{XJ+L>4JAf%lw2OiW+}PNZcrtBqGTr<%@6zdr5u_EKpLXUyCSv zWn*y4p&lTBkwTNM-mk^yx=en0=s{?PnGV1Rc3Em&Qt{XiR-f?MjV7;|uKQ>Nq{znC zf~N#J4@2V*DcLM%iTqjSFmLOzbDLLzv^u%7nrgi^M=q0-XzX<+YLexxC(sBx*}8dr z?{Zkg!7W-*takf@n zSBW5)?+BV@R*mN_+|-TstVqN3(zIK``2-&A5IGG!tPhI)uZ3tyf73cj8RJ#xu>CO(|4F6b{_)X%^{{cAZZsF}?0rfjApt>zf=C@dslPt->63X= zWlEXqb45tRh)L3Y#cK8CFI2wHti|eL*9jwX(vLy7%}jiSnMl^jU8X)XmAQpDDco#X z02q+BpdfHr@Kj!A`+#2FMqm=Gp6gpE3?_ETmww2%^V0m5A-vA?VebK?nGmPQrKAuh z=&D*4`*Gl!4>`D`XJdk}iyf&4>JN@FDzP{yQJ?e0;6nuLb2?Ra+XPkxOe%zNk0$Yk#gGV5=E=BMkf~LW|YSI9=3)}2^EK% z<*H8o6#foi$fn<0a|es}i)a3S%KVSaw;Sgk`yZY7z5jk-a`Qg0rda-<0+we;LV1tc zR?a$t_Lu0G9u0Y50od^Y4SC%C56Gh-=rI<2X@eTPk{#_vW1#l6Mf}1Cw8S~sEq!e>@|LY@dC78y668u6qt&;^=G2s zHR5?4bN3Mg^E%-rIDdh-!@_4J477~^b-O@+(*?q0;q31#2fQxKX+NR`L;#F{Hq8+} z0I-v28$DM{77bM4bp|}j+n(F1=P>=s_1(yToF~jD?|}z}e@gE@K*Z{D0^{T^;Mbv5 z4jcO0pU@14b!w+6iA`6vaB9L9#69ZaxqX%EK*GYIEbcrQ0}JG0Q+4@p9LJ}XNFIRT z@cWCMZT}SxQQj7WK_pm5SdP6B`*MWL&qb&|#AZ*b2tX z26ZkdBI5|J$w;xJh?2uPS#KHN_HKyoiR(<64%%}F@(=A9&~v%1`FduqVJiHgDpN8G zM#Kb$AvX8PNE)|EpLZ&_JNnR_r`n>!AR&S|{zAx^eOfkdP3Mk;(|#j^3|h= zgA?G94M)vM)Q6rik6Q@MTDLr3E#y!ui43BL`y23;mE&h=Uce}of{-vO4_Lci5LXSC-B53ME25)W_&=5G` zA5@|f_MlW=TjKE4u=F3Kc@NJ;M3T6>zhP+YWLkdgdTgjUy12^S7otZ0`cni>;r0DR>C(bTe$d?#O6^~vtj92R<0%o zQ8~qylGqua^S8){(b#gYY@?-@(T4)JVnZ|-0@lTDy2L{)m;n%)SxQ1}5D{v8ak6PNNM9Of#P}` z&^MN5YhQRNvIesmltO&WDPhztPJ{o1D)5Ou22ojdkYaC&pqkM$V4V-QW@G*n49UJL zJg?10J{=}sJpuq-&lQf2_7{J4`w3_~B^}=}^dUXcX_ROU9%W-oc8hg&!60v^%HD;M z+M;Ry4z0mwEdWD$TJ^xB-RoO07F}d1R)Jk)b&w~2 zmXjOrWXmRdQ=xz?8?1%`%eK**#iE5BdRe=joX|v0sX^+7l%UnF*lMa!5Y4b!>}fk4au}D3(py50v-BrmJatL zI;HYOR1kJ6Jm+4B;vv{GIN*Oxw_dMsg5TeOh3xL7Z}sRC9#AST{{5~0-`)^my-y;- z6N15D=ks@Sh(H!iX~cZb1I4FLYI&?U^27&iyms+>$->9ejp^0AJM6DS6y>WsEOpRn z1W!=(6z=>CzTm*x50;ZRgKwY~hGlj4PBj=w!B*Vi^{uZP*o(SGM(?@N-ZM~!ji>V$ zL98~w{}#|Q+j?J1unFG`lrTrIia`2{C$#@Qw%p_De9oam&L=Q)M1BZu!&?`J(}BnR z^shjK0H(Pgn+ri;ze)FG#~o}_AAbM%urvn<66BT6^Sc0e-l=;8u&MLs_FqIwG&%z4 zI{Y`Z)xk^RFZf_|!%Kgx#@xv&gXsfkfpmHlX)~yqKvP@`R}Jd~nXo0)gOHZB0-;-g z%$n=GR%gBZ03=vW```-=&K6GdNB?F2CpVXKTudB6KK_!LXa?a=ZQwP_+3bH3H-rzX zM<;kMpNKyEPDlw33_%EtIy;AK_i!vW-mXJp@5YLXt!S>A-GsX)>e!B~1EIPS(`FB6 z4Zy`{DgDX*^sTB*7^U7tlXaj+v_A<111SCBP%v&1OGXw??mS3_gfV)68=u2Jo zN5vKs-OfKHV;;)!`uYMU0|{P%@QcylB0&xx?SC!U5rNSO8ag}doqOMkI(3aHukl+C zfEk29%*$K!544&y#;9KwZ&)wUQ(N>^-tOaIx^yq?n%)I_E0@bmXF+2E5Ia{_ejSs zMaMm16Yl4aNm*SbnD(pruva;@p?o#ZA~oIYBq7LO87u7+P@P5Ln*k3=*D}>{uHZO| z#xj-(vGiYG>bwT9&7ae4JTz>xtT|HqVW+t6Z@fPrYjARB6z>Gk%t?Q-Beu_LS!><7 zUcu=VopYP0^{`PFR^}99HRs3NRKe!sE`Om**a-rrjc*5fx`cyvoXO7L<%7`vCL_4lBO!ps3Y|Y-yTQbAtS1TLvBMwJxNR}w<3&h6mt^r{!cH$_?cupPd5iR^`k>XY-a)TKrPeZV!8js8kK zd7pirw4Ez|aUAFsZ`0O)$hN|MTFMM-@vRmS)z??Iqps&Nv?^1k6k!a%UiQ>ElRb9jSfx3?}5n)`;(G#zNE&YI|3j-5XWC5p(;R^H!< zxOz9;(s!Qm--U2Pv}E(;0}K2$^{cGZR7_|Ve6<`yB*r57ZJ5G1z0Fn#yTD%4P=ju7 zU$!OqGv4NnO?bXTgCB9*j(HP|)v&Mng9suk;$_{HsJL03bXw|W@P`Gt<)dCqidfKp zki3ct1MvAp^r+qErzsY52I(gi>^3im!Fh2YgT|7!|D00%=t3MV3OVtq_op!TVZ@?T zhmq`>_H*@uqd8*}=?9;P^J2O>T3hSAo@|wu3e>Hp9{?HWnfhYH%HvRJ-eh7aUJQ4Ns+)!Ni8N=Iw<>H~0&=j`+#@<^-MftvOzqEsN zNDKl)cZY=1-Q7qC2m*qDf(1h(-5~>#3aAK(h=S6R(nyF(mq;rhwa@u}|G(d}*0c6r zYwxx8%jexJ17_~~p6fcV^E^JsF^r4*DqC_PY*i>Y=Ron`qQY{|=dQ@`tZ-pj6Y^}e z5%#B&Pe7l~5;PMUbPpolW@PB+_m*P!q0Ct5(l5G`i*a~N)%yK0AIVCBZH@moSQF~A zhQIM{ILnY-`}nA8^O!qN>9E~-j=s0)yf$^r-0n8D_I*%`vuug)_pplU@jpCNx{;yJ zR)fwNX^=S4jK}xMKg^lG;1|AXeV_d9z?x`Ue8AU7E>wO}rUF+zTguJ7yQ9Qf+Rfy8 z>BU314mp3i!Eqd93VkK*P`>28c>LAWw&NU-{e|NZtBQ0X&@=eFrnwSXj@Cj{)rv!Q z7gmRvqbA9uom0-Q2B_qD1&j|K5MFZz>KH&{;}_K~q{idt0^bHMJATwlG@LUFr!kNT&6^k#@?Cs3{zer#F*H7SAHt_Mn)D=PWD`hx z@P?feeOn?EnWY7VHSY*J`e|iVmRqRk_-l{Y>z|cs=ekaXWg)(n7+)F*<34ATL6woG zS%Y33fAjQg_|-hCt=2fjem+Oi<Q2MyRkj@Xu_X+r;KF;kx$&;+03q(^m7!5>C(g>m@_;l}? zA|b#0cB>>scF+YnNu`kxLM6d7D{%F76*O7#%)7B|*4Yv`^pp>fKJ9g=LaPwmu2`aqxS?FlpnfttOMOw?3JcrePqv zn4U^(5@K3B)BfCQB;=8$(}VwVM=!A4(e{Uj%IUxzp?KYFh;G%&1j@X|!am(t?kLOa zWYYM4r$-6Y-HZXqq00r#n+4Bo-2V>HNH>Ug$WvqwgpDl8cyM}R|I6W~QtH3lk+zAI z)a^H&cqYouKLY_G2jK*$+@XnoqXJX$)rMHRL=Jwq)*EYwRm=!tB#iMEGKH}A^rfJ= zvi?~{QPF)|N?(iynB!uoo>5sh<6M0lquzCR$$7?Ffc#m?IhG)R#$YHE3={6vn;*Y~ z(L8ndb*h`)N^NV8(SVE>=sB$_c&G`mY2Q=5a3rEVCI0-mxd2;-c|N$pWLRF!amIp2 zasLI6(!Z=@{QFxxN)a?v(8WSdA84@4&2T>y(F+6e2p%ISL<7MtpYIm3#qI9V zR$4G*w5_gGCrvMW;ADK%t)k(>#Vwg-X!NRa=RB4?GIZZH|FuJK@GITW@#_dc2P3&` z`7_WB@p_&c{WqxO>=TpEMexSKDpMZ)>NN!XH1(UReOh)05AVG%$CCy7S?zVt`?(3I zuj6{qhKypZW!QU4W+-0MlVHO}DC%A{ld}VQq!oZXE67$_0qfBswz8c?V$LBvIU#2s z3&8Qg1u}dG&?Aoyx+-v#42?gdGBG!Im1R~Oqv2KDt4X``j*gN!fl(q#tOttu)aS2y z1W^rba41+l{*D>=S&LK-)!8s)pL@(Rh1VLJrV;bB!|QhYbQpgn-aqV7&$DiUE?|!y z0(*2G*rPB^36?#Ak@%PAmPur6+M`+Jgm#TVw@~3f@JPBWpVE%hin1GNA2YUFEz?>l zt;|-8LV*BHS6+?O@3GQT6kUna*pp^sTZT1rFq}M0t0wgeV$WJv4esJ~Pf=Js6=Hq3 zM`gf44@#?FZ+~3n&hbu)XXn5kO(9K=_|+QXSCE_ z#yIRb5zKaefuOn{k2g)4U%!ZW@Z3dNzlA4f$JY&z&@SkQE#rode~$MPS)epL9P@SAuIqUOHVdZf(;7pr06qg&?jPgL#HHH|9g zC2PPm6VbC{5z&ihm3gP=HBc}?84ShIRhT|tYw+W1Y3@dZ z03VHF;Un0TtN=dh1^B3&IB?C{a1R&W?X}druqqC2J|R6*zOqX{9*j&%ya5^5H3Dme zhS?}4(ytlr|G-C*RK5mCr`y@QBT>)s40Z()o^Ieijw9SdRijA!ZPiQ!>#cVLt`y*Y zRpfdy6_PgTu&V<^X7P))R2IW*hm$o+*!1Srgil==zp2GI`3$LH*&_lhdj#i;Km#P- zrey0!8#?t>nyT8E->A#J|F&8NBP}*75E?k2QGL_LoMg$hV zg7sWnS#Okay;Ysw-X(RSPICRM5!jnP}Tt=Lk{S;R_1-HWf`KYf^cAa%kjno`Gtp$~&#dH{%|9WcFM2S6|OJgzjO z&+5U5D+{G1S)C{Cb&1BdFI%8>V|?Y2wnv*j&01&pFMFhO>`|`| zut(4w_yEWgcBlS_J?cMBiPPjn{j)UIECYLVry8AI5=#_FNO%Szo-LK2-Fh(--2I9+ z-Hv31hPD|0G-h%Cye_-nO>U%F4zNdb2!MvYg1Z8djPiE`=O@8HjOHzoc_+W>clq3Q|Jpx^u=Acq~~#6oT32pAM(f{_^?!aB$d3U zBta+bCf@OEr$+?e<#?2C*xo$p2bJe-Vc5wL@~04ISr_7cXH=oz3xn)>B1=ozw4(!A zy=>8zL7_f1$2|`M{(DP&yi~TylNk@c$U%aSMBlT+-Va1x@@(Q{3Qq-fmu_Y@`96D9 zV7N%Ulz-lgJW{xi*yRhJuyswuFF~)&KbH@Li0{H?4(cG5Bag?>M-x|W(a-vqJc9N0 z2*{&?(XdyD&XB~g^BX)s9&zb9RCvb|OdJjZEDT+{OIEv@ag z3e_Zu#;Nbw!Qjl&&dN4iVI=Hfu`lD6rtwvo&CwiqUM7@i)#iR*gDyD%X?S@%!f7Ej zc1_1w4*lXu(Dy+rk6VRL|6M)h5TXuXG>*d4j2yoh@%r`SFuOR>8nl*EC(%vPP$p$= zoSRKkUkF7= zvl1l~jGLdG$XmB1%Ir8%QNl@6R^qPnJN|zMkK|$Fc*Lc*fYYXb&8wprHBMyVh?~-} zx`Z{KsPwa^8O+0$C#=B-PUGp?dMG39(Z_2S$#DN9jy}fDA-i`s8BSQjITA%aeFJ--WPZHbQZ)A6y7;|*NR;fm;r!6ZoP3f{%3L6Py zcVhC6lx~Y@s7@&LScD_-%&`Fjm1PcAmDd_clEW@AA^5q4!>dR*rot#s(v8Xf;ja%? zN}LLs9B&r5pAC9Q`wIPb0lHC z7FqWD>Zo`Bf=4zXn6E4Q+qeD!kHGU#{@uhcFNT1eYuYglS3e3S?V=YW*UGQsVa0$7 zSD=CWTTq!%z1a;foOCrar~Y<+ zqsG$P=5N#rRQ>}Vd42?XgXZ!Z`1SrveQf^$kCtY_DeipM#ft^-=;y!S5eF7LDycWO zTKE?{8g~}E3N7hR-@zqqAK0mD{|h|w1n`I;k9a(NgUZBSomY8=Kt|mO1le8^=k00; zrZmv+UcTsv`6Q4SE)23lmogHAZ;l&DTvP_E;(aRO20vf~nQPzH|D3`-QSyB{01}-x zT8)>(8OJXGrpqb6({d!@?I!u^vIZTa+`upH5_5y~h{d%3N(gRkD;VN zdny4z_`(*>ozNSewOmNzawH?>T!0q$Qb|cNtw{AEu{+8xKPjI(4@X%QYVbSI#F;su zGP9*r=Y3gG!M|IzizGZps2C)RM4THiqxNR60vw|CZIvBU43!$9NQSHbxXRHHOegm= zjvIw-s7_@m9_muyCe}2hOSspjs?MghHS6x|*UFgEIh!7ZVCygLR zx7bp9l=JHmsBoj76IDLB7_3&}(i-Lb8dR>TU5W!F94?&l3Y-@kEIhuwp*G>G)*A8j z3@E9e=N0r6V1vwwG1+B|>cU5uQd25QMq?tWmIozOnzC6rH0g&Y&BMul(*;`7i9W+) z5~*ePDz?CTY5G(U#Z)+OdAASSo(Oi>rkW*9n8f{L+)9wPEGi5A&J7u=2f?@Q6_Y$t zs-qLXc2)4RkuFw2?yRe^&!VW)-x>Roh+jqzZ?YP#H Hgod5i-yw>(6EjbtV<(7N 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

?vpU~Z>c{);16yV^MX4X0LEZ0dm2%HO+ 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 literal 0 HcmV?d00001 diff --git a/Breadth-First Search/Images/Animated_BFS.gif b/Breadth-First Search/Images/Animated_BFS.gif deleted file mode 100644 index d8fe07cbc40a0a19534b597e123bf803de42f205..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 33276 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 VN-uB@0x#iI)bv$Ep$#Yh{{eHl({ca+ diff --git a/Breadth-First Search/Images/TraversalTree.graffle b/Breadth-First Search/Images/TraversalTree.graffle new file mode 100644 index 0000000000000000000000000000000000000000..3de9f1a688bb80a02088b426d1b202be94cf7af7 GIT binary patch literal 2088 zcmV+@2-o)?iwFP!000030PS0CbK1BT{@nZu-+bK${0?+!b_kF_mxOE}$!&+39mN)) z#z?L#O41Jh{Yp0Y9YVNi+MP8Yu(2K;9ZBaoM;1EuKOSa|^c7MM5&Zs8DanTt#1^p; zp1eQ29-bam5C1qmsQ;(cZw^0Rwk6j=9+NJwPkP;^ba+%QH(b|&<#KD-k}iAQ!BFBd z%H{UOp>#N9%zalbFBXdu5U7$xW&-GyFDY>$Wsf~B?1)z=*~~uV%>>dD>hPyFve@y# zoBBO`JZ@MFeT6;n2x%AF@S$E7PkAB23{D_Dmh0v9?YatY8(DyHkvDgBccK#Mse z4g2%lV`1xz&S807egdp}(JHoii|!OzA#BzC6-*$!by?W@_wVvsNnXB{zAJ`adn+k& z#au2EdWsrN2YA`a1LB~l)l`*kE5fe_R*jEw02{DJ2S&)X&Osp;N$#W4SaDF^qF@oJ z6)ASnkE_E+G#rZcU33$Sp$9(^GTXr@ngD+VUZ0`~ip*g>nEqJCr!uNBK;K{n9~<*b zE#k~)xZ$7)&S<4%werye7g$_Gh^G)Z$C_C$`!{PS{~=7e1z1KQRaVR+Svyjyl2Uu8 zYwr|I`c3AajCMi@q3QbPfUzn1>`5KsIB*8Am#)}Cp6h_efd!mQ>xzW1^j;E|bhT6D zz~Q5tsRB4T(pcXhTf~~rAZBUehC`@k#&BiGp71R>L{C~~k`SRjJ%nKnAy%Crn04`( zY_?~C$T8;*biP8yT~R{jia#;C63_gp7QI`|dEEMg8XXAi%__ub8z-)wU~WccyjE1n zNL3PuOTr(;M=l)Um{ZcLCZ|QMx=eLAEH^mQ)QY@J(L9os<6AOa^`^iki+Fbwb(HBcR zU}!RB5RZYy1DSkq;P=AQRB2?5WvR7%Y6bCcj|l2M5kcEGA{eTg-rCfRHLZBi@t$cjC(aF4A0>^-tA z{{Wg*?yRcvtC@1OFy+FOLsLF^K~pviVajs#)l9ikm~vstp(!_B(3DO6mA$fAm~vst zp(!_C(v+1~K4N4Prd*hEXv(KAY0A}Ce(lo=Q!Y$7H0879)5q--ISpqN+3_8{WU9ho zN*11gWD*WOwg;I!g8>GvHzYgYlV|?V=E#O#k68E6P9G~zSWpaogFJMXJ-D7~#^0v8 z1QY0Gj-6|nQ|H|o2R1pg8KgTL^#2n=cSw@Q=fmBsV7p7CxOh(6CpN`cRAeC~}T)D|YmM zy(L_YwuB?>0CH0JX%s2AT#{3G$5*qBCkSVCu?fp4gGFkE*bwhQJYmyJ1F9T+)LKMc&o_pzbDS8Zih7VzfS(@4%*Ykw0|ud%H8b;$C@n6I46W4E$`#?TNCC`;-4`6S7JT% zBjB0Sp=wm2c$A;C!6$Ex4JC9HMlq<5>HCvHGcS=?Cz5fugtosXcDih0( zpvH`^Red!?@?WrM3o?IqShM++#S#Eu3qG^%HAY|NFnU+o()()Q0!t^))_bo=uNKmY)V0rv6$ literal 0 HcmV?d00001 diff --git a/Breadth-First Search/Images/TraversalTree.png b/Breadth-First Search/Images/TraversalTree.png new file mode 100644 index 0000000000000000000000000000000000000000..4029285d7083aef47fef6661e5133ce0426594b3 GIT binary patch literal 9817 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 Vf$?4S)BlRW$xEw9RZ18K{1-29r literal 0 HcmV?d00001 diff --git a/Breadth-First Search/README.markdown b/Breadth-First Search/README.markdown index e75d2b913..70127db5a 100644 --- a/Breadth-First Search/README.markdown +++ b/Breadth-First Search/README.markdown @@ -4,72 +4,86 @@ Breadth-first search (BFS) is an algorithm for traversing or searching [tree](.. ## Animated example -![Animated example of a breadth-first search](Images/Animated_BFS.gif) +Here's how breadth-first search works on a graph: -Let's follow the animated example by using a [queue](../Queue/). +![Animated example of a breadth-first search](Images/AnimatedExample.gif) -Start with the source node ``a`` and add it to a queue. +When we visit a node, we color it black. We also put its neighbor nodes into a [queue](../Queue/). In the animation the nodes that are enqueued but not visited yet are shown in gray. + +Let's follow the animated example. We start with the source node `A` and add it to a queue. In the animation this is shown as node `A` becoming gray. ```swift -queue.enqueue(a) +queue.enqueue(A) ``` -The queue is now ``[ a ]``. Dequeue ``a`` and enqueue its two neighbor nodes ``b`` and ``c``. +The queue is now `[ A ]`. The idea is that, as long as there are nodes in the queue, we visit the node that's at the front of the queue, and enqueue its immediate neighbor nodes if they have not been visited yet. + +To start traversing the graph, we pull the first node off the queue, `A`, and color it black. Then we enqueue its two neighbor nodes `B` and `C`. This colors them gray. ```swift -queue.dequeue() // a -queue.enqueue(b) -queue.enqueue(c) +queue.dequeue() // A +queue.enqueue(B) +queue.enqueue(C) ``` -The queue is now ``[ b, c ]``. Dequeue ``b`` and enqueue `b`'s neighbor nodes ``d`` and ``e``. +The queue is now `[ B, C ]`. We dequeue `B`, and enqueue `B`'s neighbor nodes `D` and `E`. ```swift -queue.dequeue() // b -queue.enqueue(d) -queue.enqueue(e) +queue.dequeue() // B +queue.enqueue(D) +queue.enqueue(E) ``` -The queue is now ``[ c, d, e ]``. Dequeue ``c`` and enqueue `c`'s neighbor nodes ``f`` and ``g``. +The queue is now `[ C, D, E ]`. Dequeue `C`, and enqueue `C`'s neighbor nodes `F` and `G`. ```swift -queue.dequeue() // c -queue.enqueue(f) -queue.enqueue(g) +queue.dequeue() // C +queue.enqueue(F) +queue.enqueue(G) ``` -The queue is now ``[ d, e, f, g ]``. Dequeue ``d`` which has no neighbor nodes. +The queue is now `[ D, E, F, G ]`. Dequeue `D`, which has no neighbor nodes. ```swift -queue.dequeue() // d +queue.dequeue() // D ``` -The queue is now ``[ e, f, g ]``. Dequeue ``e`` and enqueue its single neighbor node ``h``. +The queue is now `[ E, F, G ]`. Dequeue `E` and enqueue its single neighbor node `H`. Note that `B` is also a neighbor for `E` but we've already visited `B`, so we're not adding it to the queue again. ```swift -queue.dequeue() // e -queue.enqueue(h) +queue.dequeue() // E +queue.enqueue(H) ``` -The queue is now ``[ f, g, h ]``. Dequeue ``f`` which has no neighbor nodes. +The queue is now `[ F, G, H ]`. Dequeue `F`, which has no unvisited neighbor nodes. ```swift -queue.dequeue() // f +queue.dequeue() // F ``` -The queue is now ``[ g, h ]``. Dequeue ``g`` which has no neighbor nodes. +The queue is now `[ G, H ]`. Dequeue `G`, which has no unvisited neighbor nodes. ```swift -queue.dequeue() // g +queue.dequeue() // G ``` -The queue is now ``[ h ]``. Dequeue ``h`` which has no neighbor nodes. +The queue is now `[ H ]`. Dequeue `H`, which has no unvisited neighbor nodes. ```swift -queue.dequeue() // h +queue.dequeue() // H ``` -The queue is now empty, meaning that all nodes have been explored. The order in which the nodes were explored is `a`, `b`, `c`, `d`, `e`, `f`, `g`, `h`. +The queue is now empty, meaning that all nodes have been explored. The order in which the nodes were explored is `A`, `B`, `C`, `D`, `E`, `F`, `G`, `H`. + +We can show this as a tree: + +![The BFS tree](Images/TraversalTree.png) + +The parent of a node is the one that "discovered" that node. The root of the tree is the node you started the breadth-first search from. + +For an unweighted graph, this tree defines a shortest path from the starting node to every other node in the tree. So breadth-first search is one way to find the shortest path between two nodes in a graph. + +Breadth-first search can be used on directed and undirected graphs. ## The code @@ -83,9 +97,8 @@ func breadthFirstSearch(graph: Graph, source: Node) -> [String] { var nodesExplored = [source.label] source.visited = true - while !queue.isEmpty { - let current = queue.dequeue()! - for edge in current.neighbors { + while let node = queue.dequeue() { + for edge in node.neighbors { let neighborNode = edge.neighbor if !neighborNode.visited { queue.enqueue(neighborNode) @@ -99,10 +112,12 @@ func breadthFirstSearch(graph: Graph, source: Node) -> [String] { } ``` +While there are nodes in the queue, we visit the first one and then enqueue its immediate neighbors if they haven't been visited yet. + Put this code in a playground and test it like so: ```swift -let graph = Graph() // Representing the graph from the animated example +let graph = Graph() let nodeA = graph.addNode("a") let nodeB = graph.addNode("b") @@ -120,6 +135,8 @@ graph.addEdge(nodeB, neighbor: nodeE) graph.addEdge(nodeC, neighbor: nodeF) graph.addEdge(nodeC, neighbor: nodeG) graph.addEdge(nodeE, neighbor: nodeH) +graph.addEdge(nodeE, neighbor: nodeF) +graph.addEdge(nodeF, neighbor: nodeG) let nodesExplored = breadthFirstSearch(graph, source: nodeA) print(nodesExplored) @@ -178,8 +195,7 @@ func breadthFirstSearchShortestPath(graph: Graph, source: Node) -> Graph { queue.enqueue(sourceInShortestPathsGraph) sourceInShortestPathsGraph.distance = 0 - while !queue.isEmpty { - let current = queue.dequeue()! + while let current = queue.dequeue() { for edge in current.neighbors { let neighborNode = edge.neighbor if !neighborNode.hasDistance { @@ -312,8 +328,7 @@ func breadthFirstSearchMinimumSpanningTree(graph: Graph, source: Node) -> Graph queue.enqueue(sourceInMinimumSpanningTree) sourceInMinimumSpanningTree.visited = true - while !queue.isEmpty { - let current = queue.dequeue()! + while let current = queue.dequeue() { for edge in current.neighbors { let neighborNode = edge.neighbor if !neighborNode.visited { @@ -386,6 +401,6 @@ print(minimumSpanningTree) // [node: a edges: ["b", "h"]] ## See also -[Graph](../Graph/), [Tree](../Tree/), [Queues](../Queue/), [Shortest Path](../Shortest Path/), [Minimum Spanning Tree](../Minimum Spanning Tree/). +[Graph](../Graph/), [Tree](../Tree/), [Queue](../Queue/), [Shortest Path](../Shortest Path/), [Minimum Spanning Tree](../Minimum Spanning Tree/). -*Written by [Chris Pilcher](https://github.com/chris-pilcher)* +*Written by [Chris Pilcher](https://github.com/chris-pilcher) and Matthijs Hollemans* diff --git a/Breadth-First Search/Tests/BreadthFirstSearchTests.swift b/Breadth-First Search/Tests/BreadthFirstSearchTests.swift index 6c0d382d9..b5e3adac6 100755 --- a/Breadth-First Search/Tests/BreadthFirstSearchTests.swift +++ b/Breadth-First Search/Tests/BreadthFirstSearchTests.swift @@ -4,6 +4,7 @@ class BreadthFirstSearchTests: XCTestCase { func testExploringTree() { let tree = Graph() + let nodeA = tree.addNode("a") let nodeB = tree.addNode("b") let nodeC = tree.addNode("c") @@ -12,6 +13,7 @@ class BreadthFirstSearchTests: XCTestCase { let nodeF = tree.addNode("f") let nodeG = tree.addNode("g") let nodeH = tree.addNode("h") + tree.addEdge(nodeA, neighbor: nodeB) tree.addEdge(nodeA, neighbor: nodeC) tree.addEdge(nodeB, neighbor: nodeD) @@ -70,7 +72,6 @@ class BreadthFirstSearchTests: XCTestCase { let nodesExplored = breadthFirstSearch(graph, source: nodeA) XCTAssertEqual(nodesExplored, ["a", "b", "h", "c", "g", "i", "d", "f", "e"]) - } func testExploringGraphWithASingleNode() { @@ -82,4 +83,3 @@ class BreadthFirstSearchTests: XCTestCase { XCTAssertEqual(nodesExplored, ["a"]) } } - From 1f5c20ed74d614b3e5a4afab01a4df4b831081f4 Mon Sep 17 00:00:00 2001 From: Matthijs Hollemans Date: Fri, 18 Mar 2016 22:30:58 +0100 Subject: [PATCH 0165/1679] Extract shortest path and minimum spanning tree from breadth-first search --- .../Contents.swift | 4 - .../contents.xcplayground | 8 +- Breadth-First Search/README.markdown | 258 +---------------- Breadth-First Search/{ => Tests}/Graph.swift | 0 Breadth-First Search/{ => Tests}/Queue.swift | 0 .../Tests/Tests.xcodeproj/project.pbxproj | 20 +- Minimum Spanning Tree/Images/Graph.png | Bin 0 -> 20362 bytes Minimum Spanning Tree/Images/Graph.sketch | Bin 0 -> 81920 bytes .../Images/MinimumSpanningTree.png | Bin .../Images/MinimumSpanningTree.sketch | Bin Minimum Spanning Tree/Images/Tree.graffle | Bin 0 -> 2146 bytes Minimum Spanning Tree/Images/Tree.png | Bin 0 -> 11733 bytes .../Contents.swift | 6 +- .../timeline.xctimeline | 0 .../Resources}/Minimum_Spanning_Tree.png | Bin .../Sources/Edge.swift | 11 + .../Sources/Graph.swift | 55 ++++ .../Sources/Node.swift | 32 +++ .../Sources/Queue.swift | 31 ++ .../contents.xcplayground | 2 + .../MinimumSpanningTree.swift | 0 Minimum Spanning Tree/README.markdown | 190 ++++++++++++ Minimum Spanning Tree/Tests/Graph.swift | 106 +++++++ Minimum Spanning Tree/Tests/Info.plist | 24 ++ .../Tests/MinimumSpanningTreeTests.swift | 2 +- Minimum Spanning Tree/Tests/Queue.swift | 31 ++ .../Tests/Tests.xcodeproj/project.pbxproj | 272 ++++++++++++++++++ .../xcshareddata/xcschemes/Tests.xcscheme | 56 ++++ README.markdown | 4 +- Shortest Path/Images/Graph.graffle | Bin 0 -> 2127 bytes Shortest Path/Images/Graph.png | Bin 0 -> 12819 bytes Shortest Path/README.markdown | 106 +++++++ .../Contents.swift | 7 - .../timeline.xctimeline | 0 .../Sources/Edge.swift | 11 + .../Sources/Graph.swift | 55 ++++ .../Sources/Node.swift | 32 +++ .../Sources/Queue.swift | 31 ++ .../contents.xcplayground | 2 + .../ShortestPath.swift | 0 Shortest Path/Tests/Graph.swift | 106 +++++++ Shortest Path/Tests/Info.plist | 24 ++ Shortest Path/Tests/Queue.swift | 31 ++ .../Tests/ShortestPathTests.swift | 2 +- .../Tests/Tests.xcodeproj/project.pbxproj | 272 ++++++++++++++++++ .../xcshareddata/xcschemes/Tests.xcscheme | 56 ++++ 46 files changed, 1547 insertions(+), 300 deletions(-) rename Breadth-First Search/{ => Tests}/Graph.swift (100%) rename Breadth-First Search/{ => Tests}/Queue.swift (100%) create mode 100644 Minimum Spanning Tree/Images/Graph.png create mode 100644 Minimum Spanning Tree/Images/Graph.sketch rename Breadth-First Search/BreadthFirstSearch.playground/Resources/Minimum_Spanning_Tree.png => Minimum Spanning Tree/Images/MinimumSpanningTree.png (100%) rename {Breadth-First Search => Minimum Spanning Tree}/Images/MinimumSpanningTree.sketch (100%) create mode 100644 Minimum Spanning Tree/Images/Tree.graffle create mode 100644 Minimum Spanning Tree/Images/Tree.png rename {Breadth-First Search/BreadthFirstSearch.playground => Minimum Spanning Tree/MinimumSpanningTree.playground}/Pages/Minimum spanning tree example.xcplaygroundpage/Contents.swift (93%) rename {Breadth-First Search/BreadthFirstSearch.playground => Minimum Spanning Tree/MinimumSpanningTree.playground}/Pages/Minimum spanning tree example.xcplaygroundpage/timeline.xctimeline (100%) rename {Breadth-First Search/Images => Minimum Spanning Tree/MinimumSpanningTree.playground/Resources}/Minimum_Spanning_Tree.png (100%) create mode 100644 Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/Edge.swift create mode 100644 Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/Graph.swift create mode 100644 Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/Node.swift create mode 100644 Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/Queue.swift create mode 100644 Minimum Spanning Tree/MinimumSpanningTree.playground/contents.xcplayground rename Breadth-First Search/BreadthFirstSearchMinimumSpanningTree.swift => Minimum Spanning Tree/MinimumSpanningTree.swift (100%) create mode 100644 Minimum Spanning Tree/README.markdown create mode 100644 Minimum Spanning Tree/Tests/Graph.swift create mode 100644 Minimum Spanning Tree/Tests/Info.plist rename Breadth-First Search/Tests/BreadthFirstSearchMinimumSpanningTreeTests.swift => Minimum Spanning Tree/Tests/MinimumSpanningTreeTests.swift (98%) create mode 100644 Minimum Spanning Tree/Tests/Queue.swift create mode 100644 Minimum Spanning Tree/Tests/Tests.xcodeproj/project.pbxproj create mode 100644 Minimum Spanning Tree/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme create mode 100644 Shortest Path/Images/Graph.graffle create mode 100644 Shortest Path/Images/Graph.png create mode 100644 Shortest Path/README.markdown rename {Breadth-First Search/BreadthFirstSearch.playground => Shortest Path/ShortestPath.playground}/Pages/Shortest path example.xcplaygroundpage/Contents.swift (92%) rename {Breadth-First Search/BreadthFirstSearch.playground => Shortest Path/ShortestPath.playground}/Pages/Shortest path example.xcplaygroundpage/timeline.xctimeline (100%) create mode 100644 Shortest Path/ShortestPath.playground/Sources/Edge.swift create mode 100644 Shortest Path/ShortestPath.playground/Sources/Graph.swift create mode 100644 Shortest Path/ShortestPath.playground/Sources/Node.swift create mode 100644 Shortest Path/ShortestPath.playground/Sources/Queue.swift create mode 100644 Shortest Path/ShortestPath.playground/contents.xcplayground rename Breadth-First Search/BreadthFirstSearchShortestPath.swift => Shortest Path/ShortestPath.swift (100%) create mode 100644 Shortest Path/Tests/Graph.swift create mode 100644 Shortest Path/Tests/Info.plist create mode 100644 Shortest Path/Tests/Queue.swift rename Breadth-First Search/Tests/BreadthFirstSearchShortestPathTests.swift => Shortest Path/Tests/ShortestPathTests.swift (98%) create mode 100644 Shortest Path/Tests/Tests.xcodeproj/project.pbxproj create mode 100644 Shortest Path/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme diff --git a/Breadth-First Search/BreadthFirstSearch.playground/Pages/Simple example.xcplaygroundpage/Contents.swift b/Breadth-First Search/BreadthFirstSearch.playground/Pages/Simple example.xcplaygroundpage/Contents.swift index c761d9e99..93aa6b337 100644 --- a/Breadth-First Search/BreadthFirstSearch.playground/Pages/Simple example.xcplaygroundpage/Contents.swift +++ b/Breadth-First Search/BreadthFirstSearch.playground/Pages/Simple example.xcplaygroundpage/Contents.swift @@ -1,5 +1,3 @@ -//: # Breadth-First Search - func breadthFirstSearch(graph: Graph, source: Node) -> [String] { var queue = Queue() queue.enqueue(source) @@ -47,5 +45,3 @@ graph.addEdge(nodeF, neighbor: nodeG) let nodesExplored = breadthFirstSearch(graph, source: nodeA) print(nodesExplored) - -//: [Next: Shortest Path Example](@next) diff --git a/Breadth-First Search/BreadthFirstSearch.playground/contents.xcplayground b/Breadth-First Search/BreadthFirstSearch.playground/contents.xcplayground index fc13b7766..513c2e7e9 100644 --- a/Breadth-First Search/BreadthFirstSearch.playground/contents.xcplayground +++ b/Breadth-First Search/BreadthFirstSearch.playground/contents.xcplayground @@ -1,8 +1,2 @@ - - - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/Breadth-First Search/README.markdown b/Breadth-First Search/README.markdown index 70127db5a..4eb77b0ac 100644 --- a/Breadth-First Search/README.markdown +++ b/Breadth-First Search/README.markdown @@ -144,263 +144,11 @@ print(nodesExplored) This will output: `["a", "b", "c", "d", "e", "f", "g", "h"]` -## Applications +## What is BFS good for? Breadth-first search can be used to solve many problems. A small selection: -* Computing the shortest path between a source node and each of the other nodes (only for unweighted graphs). -* Calculating the minimum spanning tree on an unweighted graph. - -## Shortest path example - -Breadth-first search can be used to compute the [shortest path](../Shortest Path/) between a source node and each of the other nodes in the tree or graph, because it explores all of the immediate neighbor nodes first before moving to the next level neighbors. - -Let's follow the animated example and calculate the shortest path to all the other nodes. Start with the source node ``a`` and add it to a queue with a distance of ``0``. - -```swift -queue.enqueue(a) -a.distance = 0 -``` - -The queue is now ``[ a ]``. Dequeue ``a`` and enqueue its two neighbor nodes ``b`` and ``c`` with a distance of ``1``. - -```swift -queue.dequeue() // a -queue.enqueue(b) -b.distance = a.distance + 1 // result: 1 -queue.enqueue(c) -c.distance = a.distance + 1 // result: 1 -``` - -The queue is now ``[ b, c ]``. Dequeue ``b`` and enqueue `b`'s neighbor nodes ``d`` and ``e`` with a distance of ``2``. - -```swift -queue.dequeue() // b -queue.enqueue(d) -d.distance = b.distance + 1 // result: 2 -queue.enqueue(e) -e.distance = b.distance + 1 // result: 2 -``` - -Continue until the queue is empty to calculate the shortest path to all other nodes. - -Here's the code: - -```swift -func breadthFirstSearchShortestPath(graph: Graph, source: Node) -> Graph { - let shortestPathGraph = graph.duplicate() - - var queue = Queue() - let sourceInShortestPathsGraph = shortestPathGraph.findNodeWithLabel(source.label) - queue.enqueue(sourceInShortestPathsGraph) - sourceInShortestPathsGraph.distance = 0 - - while let current = queue.dequeue() { - for edge in current.neighbors { - let neighborNode = edge.neighbor - if !neighborNode.hasDistance { - queue.enqueue(neighborNode) - neighborNode.distance = current.distance! + 1 - } - } - } - - return shortestPathGraph -} -``` - -Put this code in a playground and test it like so: - -```swift -let shortestPathGraph = breadthFirstSearchShortestPath(graph, source: nodeA) -print(shortestPathGraph.nodes) -``` - -This will output: - - Node(label: a, distance: 0), Node(label: b, distance: 1), Node(label: c, distance: 1), - Node(label: d, distance: 2), Node(label: e, distance: 2), Node(label: f, distance: 2), - Node(label: g, distance: 2), Node(label: h, distance: 3) - -## Minimum spanning tree example - -Breadth-first search can be used to calculate the [minimum spanning tree](../Minimum Spanning Tree/) on an unweighted graph. A minimum spanning tree describes a path that contains the smallest number of edges that are needed to visit every node in the graph. - -Let's calculate the minimum spanning tree for the following graph: - -![Minimum spanning tree](Images/Minimum_Spanning_Tree.png) - -*Note: the minimum spanning tree is represented by the bold edges.* - -Start with the source node ``a`` and add it to a queue and mark it as visited. - -```swift -queue.enqueue(a) -a.visited = true -``` - -The queue is now ``[ a ]``. Dequeue ``a`` and enqueue its immediate neighbor nodes ``b`` and ``h`` and mark them as visited. - -```swift -queue.dequeue() // a -queue.enqueue(b) -b.visited = true -queue.enqueue(h) -h.visited = true -``` - -The queue is now ``[ b, h ]``. Dequeue ``b`` and enqueue the neighbor node ``c`` mark it as visited. Remove the edge between ``b`` to ``h`` because ``h`` has already been visited. - -```swift -queue.dequeue() // b -queue.enqueue(c) -c.visited = true -b.removeEdgeTo(h) -``` - -The queue is now ``[ h, c ]``. Dequeue ``h`` and enqueue the neighbor nodes ``g`` and ``i`` and mark them as visited. - -```swift -queue.dequeue() // h -queue.enqueue(g) -g.visited = true -queue.enqueue(i) -i.visited = true -``` - -The queue is now ``[ c, g, i ]``. Dequeue ``c`` and enqueue the neighbor nodes ``d`` and ``f`` and mark them as visited. Remove the edge between ``c`` to ``i`` because ``i`` has already been visited. - -```swift -queue.dequeue() // c -queue.enqueue(d) -d.visited = true -queue.enqueue(f) -f.visited = true -c.removeEdgeTo(i) -``` - -The queue is now ``[ g, i, d, f ]``. Dequeue ``g`` and remove the edges between ``g`` to ``f`` and ``g`` to ``i`` because ``f`` and ``i`` have already been visited. - -```swift -queue.dequeue() // g -g.removeEdgeTo(f) -g.removeEdgeTo(i) -``` - -The queue is now ``[ i, d, f ]``. Dequeue ``i``. - -```swift -queue.dequeue() // i -``` - -The queue is now ``[ d, f ]``. Dequeue ``d`` and enqueue the neighbor node ``e`` mark it as visited. Remove the edge between ``d`` to ``f`` because ``f`` has already been visited. - -```swift -queue.dequeue() // d -queue.enqueue(e) -e.visited = true -d.removeEdgeTo(f) -``` - -The queue is now ``[ f, e ]``. Dequeue ``f``. Remove the edge between ``f`` to ``e`` because ``e`` has already been visited. - -```swift -queue.dequeue() // f -f.removeEdgeTo(e) -``` - -The queue is now ``[ e ]``. Dequeue ``e``. - -```swift -queue.dequeue() // e -``` - -The queue is now empty, which means the minimum spanning tree has been computed. - -Here's the code: - -```swift -func breadthFirstSearchMinimumSpanningTree(graph: Graph, source: Node) -> Graph { - let minimumSpanningTree = graph.duplicate() - - var queue = Queue() - let sourceInMinimumSpanningTree = minimumSpanningTree.findNodeWithLabel(source.label) - queue.enqueue(sourceInMinimumSpanningTree) - sourceInMinimumSpanningTree.visited = true - - while let current = queue.dequeue() { - for edge in current.neighbors { - let neighborNode = edge.neighbor - if !neighborNode.visited { - neighborNode.visited = true - queue.enqueue(neighborNode) - } else { - current.remove(edge) - } - } - } - - return minimumSpanningTree -} -``` - -This function returns a new `Graph` object that describes just the minimum spanning tree. In the figure, that would be the graph containing just the bold edges. - -Put this code in a playground and test it like so: - -```swift -let graph = Graph() - -let nodeA = graph.addNode("a") -let nodeB = graph.addNode("b") -let nodeC = graph.addNode("c") -let nodeD = graph.addNode("d") -let nodeE = graph.addNode("e") -let nodeF = graph.addNode("f") -let nodeG = graph.addNode("g") -let nodeH = graph.addNode("h") -let nodeI = graph.addNode("i") - -graph.addEdge(nodeA, neighbor: nodeB) -graph.addEdge(nodeA, neighbor: nodeH) -graph.addEdge(nodeB, neighbor: nodeA) -graph.addEdge(nodeB, neighbor: nodeC) -graph.addEdge(nodeB, neighbor: nodeH) -graph.addEdge(nodeC, neighbor: nodeB) -graph.addEdge(nodeC, neighbor: nodeD) -graph.addEdge(nodeC, neighbor: nodeF) -graph.addEdge(nodeC, neighbor: nodeI) -graph.addEdge(nodeD, neighbor: nodeC) -graph.addEdge(nodeD, neighbor: nodeE) -graph.addEdge(nodeD, neighbor: nodeF) -graph.addEdge(nodeE, neighbor: nodeD) -graph.addEdge(nodeE, neighbor: nodeF) -graph.addEdge(nodeF, neighbor: nodeC) -graph.addEdge(nodeF, neighbor: nodeD) -graph.addEdge(nodeF, neighbor: nodeE) -graph.addEdge(nodeF, neighbor: nodeG) -graph.addEdge(nodeG, neighbor: nodeF) -graph.addEdge(nodeG, neighbor: nodeH) -graph.addEdge(nodeG, neighbor: nodeI) -graph.addEdge(nodeH, neighbor: nodeA) -graph.addEdge(nodeH, neighbor: nodeB) -graph.addEdge(nodeH, neighbor: nodeG) -graph.addEdge(nodeH, neighbor: nodeI) -graph.addEdge(nodeI, neighbor: nodeC) -graph.addEdge(nodeI, neighbor: nodeG) -graph.addEdge(nodeI, neighbor: nodeH) - -let minimumSpanningTree = breadthFirstSearchMinimumSpanningTree(graph, source: nodeA) - -print(minimumSpanningTree) // [node: a edges: ["b", "h"]] - // [node: b edges: ["c"]] - // [node: c edges: ["d", "f"]] - // [node: d edges: ["e"]] - // [node: h edges: ["g", "i"]] -``` - -## See also - -[Graph](../Graph/), [Tree](../Tree/), [Queue](../Queue/), [Shortest Path](../Shortest Path/), [Minimum Spanning Tree](../Minimum Spanning Tree/). +* Computing the [shortest path](../Shortest Path/) between a source node and each of the other nodes (only for unweighted graphs). +* Calculating the [minimum spanning tree](../Minimum Spanning Tree/) on an unweighted graph. *Written by [Chris Pilcher](https://github.com/chris-pilcher) and Matthijs Hollemans* diff --git a/Breadth-First Search/Graph.swift b/Breadth-First Search/Tests/Graph.swift similarity index 100% rename from Breadth-First Search/Graph.swift rename to Breadth-First Search/Tests/Graph.swift diff --git a/Breadth-First Search/Queue.swift b/Breadth-First Search/Tests/Queue.swift similarity index 100% rename from Breadth-First Search/Queue.swift rename to Breadth-First Search/Tests/Queue.swift diff --git a/Breadth-First Search/Tests/Tests.xcodeproj/project.pbxproj b/Breadth-First Search/Tests/Tests.xcodeproj/project.pbxproj index 061e1be44..33be43391 100644 --- a/Breadth-First Search/Tests/Tests.xcodeproj/project.pbxproj +++ b/Breadth-First Search/Tests/Tests.xcodeproj/project.pbxproj @@ -7,11 +7,7 @@ objects = { /* Begin PBXBuildFile section */ - 83AACB421C844CED00DDAFC7 /* BreadthFirstSearchMinimumSpanningTreeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83AACB411C844CED00DDAFC7 /* BreadthFirstSearchMinimumSpanningTreeTests.swift */; }; - 83AACB441C8456D200DDAFC7 /* BreadthFirstSearchShortestPathTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83AACB431C8456D200DDAFC7 /* BreadthFirstSearchShortestPathTests.swift */; }; 83F9C9681C84437C00B3A87F /* BreadthFirstSearch.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83F9C9651C84437C00B3A87F /* BreadthFirstSearch.swift */; }; - 83F9C9691C84437C00B3A87F /* BreadthFirstSearchMinimumSpanningTree.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83F9C9661C84437C00B3A87F /* BreadthFirstSearchMinimumSpanningTree.swift */; }; - 83F9C96A1C84437C00B3A87F /* BreadthFirstSearchShortestPath.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83F9C9671C84437C00B3A87F /* BreadthFirstSearchShortestPath.swift */; }; 83F9C96C1C8443E800B3A87F /* BreadthFirstSearchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83F9C96B1C8443E800B3A87F /* BreadthFirstSearchTests.swift */; }; 83F9C9721C84449D00B3A87F /* Graph.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83F9C96E1C84449D00B3A87F /* Graph.swift */; }; 83F9C9741C84449D00B3A87F /* Queue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83F9C9701C84449D00B3A87F /* Queue.swift */; }; @@ -20,14 +16,10 @@ /* Begin PBXFileReference section */ 7B2BBC801C779D720067B71D /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 7B2BBC941C779E7B0067B71D /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; - 83AACB411C844CED00DDAFC7 /* BreadthFirstSearchMinimumSpanningTreeTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BreadthFirstSearchMinimumSpanningTreeTests.swift; sourceTree = SOURCE_ROOT; }; - 83AACB431C8456D200DDAFC7 /* BreadthFirstSearchShortestPathTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BreadthFirstSearchShortestPathTests.swift; sourceTree = SOURCE_ROOT; }; 83F9C9651C84437C00B3A87F /* BreadthFirstSearch.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BreadthFirstSearch.swift; path = ../BreadthFirstSearch.swift; sourceTree = SOURCE_ROOT; }; - 83F9C9661C84437C00B3A87F /* BreadthFirstSearchMinimumSpanningTree.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BreadthFirstSearchMinimumSpanningTree.swift; path = ../BreadthFirstSearchMinimumSpanningTree.swift; sourceTree = SOURCE_ROOT; }; - 83F9C9671C84437C00B3A87F /* BreadthFirstSearchShortestPath.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BreadthFirstSearchShortestPath.swift; path = ../BreadthFirstSearchShortestPath.swift; sourceTree = SOURCE_ROOT; }; 83F9C96B1C8443E800B3A87F /* BreadthFirstSearchTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BreadthFirstSearchTests.swift; sourceTree = SOURCE_ROOT; }; - 83F9C96E1C84449D00B3A87F /* Graph.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Graph.swift; path = ../Graph.swift; sourceTree = SOURCE_ROOT; }; - 83F9C9701C84449D00B3A87F /* Queue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Queue.swift; path = ../Queue.swift; sourceTree = SOURCE_ROOT; }; + 83F9C96E1C84449D00B3A87F /* Graph.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Graph.swift; sourceTree = SOURCE_ROOT; }; + 83F9C9701C84449D00B3A87F /* Queue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Queue.swift; sourceTree = SOURCE_ROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -62,10 +54,6 @@ children = ( 83F9C9651C84437C00B3A87F /* BreadthFirstSearch.swift */, 83F9C96B1C8443E800B3A87F /* BreadthFirstSearchTests.swift */, - 83F9C9661C84437C00B3A87F /* BreadthFirstSearchMinimumSpanningTree.swift */, - 83AACB411C844CED00DDAFC7 /* BreadthFirstSearchMinimumSpanningTreeTests.swift */, - 83F9C9671C84437C00B3A87F /* BreadthFirstSearchShortestPath.swift */, - 83AACB431C8456D200DDAFC7 /* BreadthFirstSearchShortestPathTests.swift */, 83F9C96E1C84449D00B3A87F /* Graph.swift */, 83F9C9701C84449D00B3A87F /* Queue.swift */, 7B2BBC941C779E7B0067B71D /* Info.plist */, @@ -142,13 +130,9 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 83AACB441C8456D200DDAFC7 /* BreadthFirstSearchShortestPathTests.swift in Sources */, - 83AACB421C844CED00DDAFC7 /* BreadthFirstSearchMinimumSpanningTreeTests.swift in Sources */, 83F9C9721C84449D00B3A87F /* Graph.swift in Sources */, - 83F9C9691C84437C00B3A87F /* BreadthFirstSearchMinimumSpanningTree.swift in Sources */, 83F9C9681C84437C00B3A87F /* BreadthFirstSearch.swift in Sources */, 83F9C9741C84449D00B3A87F /* Queue.swift in Sources */, - 83F9C96A1C84437C00B3A87F /* BreadthFirstSearchShortestPath.swift in Sources */, 83F9C96C1C8443E800B3A87F /* BreadthFirstSearchTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/Minimum Spanning Tree/Images/Graph.png b/Minimum Spanning Tree/Images/Graph.png new file mode 100644 index 0000000000000000000000000000000000000000..e850728981f55b94119e60f56d70b44dfef83b4c GIT binary patch literal 20362 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 literal 0 HcmV?d00001 diff --git a/Minimum Spanning Tree/Images/Graph.sketch b/Minimum Spanning Tree/Images/Graph.sketch new file mode 100644 index 0000000000000000000000000000000000000000..e73e423795724845d22db114d85deb6a51e32185 GIT binary patch literal 81920 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 literal 0 HcmV?d00001 diff --git a/Breadth-First Search/BreadthFirstSearch.playground/Pages/Minimum spanning tree example.xcplaygroundpage/Contents.swift b/Minimum Spanning Tree/MinimumSpanningTree.playground/Pages/Minimum spanning tree example.xcplaygroundpage/Contents.swift similarity index 93% rename from Breadth-First Search/BreadthFirstSearch.playground/Pages/Minimum spanning tree example.xcplaygroundpage/Contents.swift rename to Minimum Spanning Tree/MinimumSpanningTree.playground/Pages/Minimum spanning tree example.xcplaygroundpage/Contents.swift index 006ce1873..088da1d11 100644 --- a/Breadth-First Search/BreadthFirstSearch.playground/Pages/Minimum spanning tree example.xcplaygroundpage/Contents.swift +++ b/Minimum Spanning Tree/MinimumSpanningTree.playground/Pages/Minimum spanning tree example.xcplaygroundpage/Contents.swift @@ -1,7 +1,3 @@ -//: [Previous](@previous) - -//: # Minimum Spanning Tree Example - func breadthFirstSearchMinimumSpanningTree(graph: Graph, source: Node) -> Graph { let minimumSpanningTree = graph.duplicate() @@ -27,7 +23,7 @@ func breadthFirstSearchMinimumSpanningTree(graph: Graph, source: Node) -> Graph /*: -![Animated example of a breadth-first search](Minimum_Spanning_Tree.png) +![Graph](Minimum_Spanning_Tree.png) */ diff --git a/Breadth-First Search/BreadthFirstSearch.playground/Pages/Minimum spanning tree example.xcplaygroundpage/timeline.xctimeline b/Minimum Spanning Tree/MinimumSpanningTree.playground/Pages/Minimum spanning tree example.xcplaygroundpage/timeline.xctimeline similarity index 100% rename from Breadth-First Search/BreadthFirstSearch.playground/Pages/Minimum spanning tree example.xcplaygroundpage/timeline.xctimeline rename to Minimum Spanning Tree/MinimumSpanningTree.playground/Pages/Minimum spanning tree example.xcplaygroundpage/timeline.xctimeline diff --git a/Breadth-First Search/Images/Minimum_Spanning_Tree.png b/Minimum Spanning Tree/MinimumSpanningTree.playground/Resources/Minimum_Spanning_Tree.png similarity index 100% rename from Breadth-First Search/Images/Minimum_Spanning_Tree.png rename to Minimum Spanning Tree/MinimumSpanningTree.playground/Resources/Minimum_Spanning_Tree.png diff --git a/Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/Edge.swift b/Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/Edge.swift new file mode 100644 index 000000000..3937a2cc7 --- /dev/null +++ b/Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/Edge.swift @@ -0,0 +1,11 @@ +public class Edge : Equatable { + public var neighbor: Node + + public init(neighbor: Node) { + self.neighbor = neighbor + } +} + +public func ==(lhs: Edge, rhs: Edge) -> Bool { + return lhs.neighbor == rhs.neighbor +} diff --git a/Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/Graph.swift b/Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/Graph.swift new file mode 100644 index 000000000..e89d4ac97 --- /dev/null +++ b/Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/Graph.swift @@ -0,0 +1,55 @@ +public class Graph : CustomStringConvertible, Equatable { + public private(set) var nodes: [Node] + + public init() { + self.nodes = [] + } + + public func addNode(label: String) -> Node { + let node = Node(label: label) + nodes.append(node) + return node + } + + public func addEdge(source: Node, neighbor: Node) { + let edge = Edge(neighbor: neighbor) + source.neighbors.append(edge) + } + + public var description: String { + var description = "" + + for node in nodes { + if !node.neighbors.isEmpty { + description += "[node: \(node.label) edges: \(node.neighbors.map{ $0.neighbor.label})]" + } + } + return description + } + + public func findNodeWithLabel(label: String) -> Node { + return nodes.filter{ $0.label == label }.first! + } + + public func duplicate() -> Graph { + let duplicated = Graph() + + for node in nodes { + duplicated.addNode(node.label) + } + + for node in nodes { + for edge in node.neighbors { + let source = duplicated.findNodeWithLabel(node.label) + let neighbour = duplicated.findNodeWithLabel(edge.neighbor.label) + duplicated.addEdge(source, neighbor: neighbour) + } + } + + return duplicated + } +} + +public func ==(lhs: Graph, rhs: Graph) -> Bool { + return lhs.nodes == rhs.nodes +} diff --git a/Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/Node.swift b/Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/Node.swift new file mode 100644 index 000000000..9d8435ffa --- /dev/null +++ b/Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/Node.swift @@ -0,0 +1,32 @@ +public class Node : CustomStringConvertible, Equatable { + public var neighbors: [Edge] + + public private(set) var label: String + public var distance: Int? + public var visited: Bool + + public init(label: String) { + self.label = label + neighbors = [] + visited = false + } + + public var description: String { + if let distance = distance { + return "Node(label: \(label), distance: \(distance))" + } + return "Node(label: \(label), distance: infinity)" + } + + public var hasDistance: Bool { + return distance != nil + } + + public func remove(edge: Edge) { + neighbors.removeAtIndex(neighbors.indexOf{ $0 === edge }!) + } +} + +public func ==(lhs: Node, rhs: Node) -> Bool { + return lhs.label == rhs.label && lhs.neighbors == rhs.neighbors +} diff --git a/Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/Queue.swift b/Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/Queue.swift new file mode 100644 index 000000000..bf462bbdd --- /dev/null +++ b/Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/Queue.swift @@ -0,0 +1,31 @@ +public struct Queue { + private var array: [T] + + public init() { + array = [] + } + + public var isEmpty: Bool { + return array.isEmpty + } + + public var count: Int { + return array.count + } + + public mutating func enqueue(element: T) { + array.append(element) + } + + public mutating func dequeue() -> T? { + if isEmpty { + return nil + } else { + return array.removeFirst() + } + } + + public func peek() -> T? { + return array.first + } +} diff --git a/Minimum Spanning Tree/MinimumSpanningTree.playground/contents.xcplayground b/Minimum Spanning Tree/MinimumSpanningTree.playground/contents.xcplayground new file mode 100644 index 000000000..5ed29117b --- /dev/null +++ b/Minimum Spanning Tree/MinimumSpanningTree.playground/contents.xcplayground @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/Breadth-First Search/BreadthFirstSearchMinimumSpanningTree.swift b/Minimum Spanning Tree/MinimumSpanningTree.swift similarity index 100% rename from Breadth-First Search/BreadthFirstSearchMinimumSpanningTree.swift rename to Minimum Spanning Tree/MinimumSpanningTree.swift diff --git a/Minimum Spanning Tree/README.markdown b/Minimum Spanning Tree/README.markdown new file mode 100644 index 000000000..5d988eee6 --- /dev/null +++ b/Minimum Spanning Tree/README.markdown @@ -0,0 +1,190 @@ +# Minimum Spanning Tree + +A minimum spanning tree describes a path that contains the smallest number of edges that are needed to visit every node in the graph. + +Take a look at the following graph: + +![Graph](Images/Graph.png) + +If we start from node `a` and want to visit every other node, then what is the most efficient path to do that? We can calculate this with the minimum spanning tree algorithm. + +Here is the minimum spanning tree for the graph. It is represented by the bold edges: + +![Minimum spanning tree](Images/MinimumSpanningTree.png) + +Drawn as a more conventional tree it looks like this: + +![An actual tree](Images/Tree.png) + +To calculate the minimum spanning tree on an unweighted graph, we can use the [breadth-first search](../Breadth-First Search/) algorithm. Breadth-first search starts at a source node and traverses the graph by exploring the immediate neighbor nodes first, before moving to the next level neighbors. If we tweak this algorithm by selectively removing edges, then it can convert the graph into the minimum spanning tree. + +Let's step through the example. We start with the source node `a`, add it to a queue and mark it as visited. + +```swift +queue.enqueue(a) +a.visited = true +``` + +The queue is now `[ a ]`. As is usual with breadth-first search, we dequeue the node at the front of the queue, `a`, and enqueue its immediate neighbor nodes `b` and `h`. We mark them as visited too. + +```swift +queue.dequeue() // a +queue.enqueue(b) +b.visited = true +queue.enqueue(h) +h.visited = true +``` + +The queue is now `[ b, h ]`. Dequeue `b` and enqueue the neighbor node `c`. Mark it as visited. Remove the edge from `b` to `h` because `h` has already been visited. + +```swift +queue.dequeue() // b +queue.enqueue(c) +c.visited = true +b.removeEdgeTo(h) +``` + +The queue is now `[ h, c ]`. Dequeue `h` and enqueue the neighbor nodes `g` and `i`, and mark them as visited. + +```swift +queue.dequeue() // h +queue.enqueue(g) +g.visited = true +queue.enqueue(i) +i.visited = true +``` + +The queue is now `[ c, g, i ]`. Dequeue `c` and enqueue the neighbor nodes `d` and `f`, and mark them as visited. Remove the edge between `c` and `i` because `i` has already been visited. + +```swift +queue.dequeue() // c +queue.enqueue(d) +d.visited = true +queue.enqueue(f) +f.visited = true +c.removeEdgeTo(i) +``` + +The queue is now `[ g, i, d, f ]`. Dequeue `g`. All of its neighbors have been discovered already, so there is nothing to enqueue. Remove the edges from `g` to `f`, as well as `g` to `i`, because `f` and `i` have already been discovered. + +```swift +queue.dequeue() // g +g.removeEdgeTo(f) +g.removeEdgeTo(i) +``` + +The queue is now `[ i, d, f ]`. Dequeue `i`. Nothing else to do for this node. + +```swift +queue.dequeue() // i +``` + +The queue is now `[ d, f ]`. Dequeue `d` and enqueue the neighbor node `e`. Mark it as visited. Remove the edge from `d` to `f` because `f` has already been visited. + +```swift +queue.dequeue() // d +queue.enqueue(e) +e.visited = true +d.removeEdgeTo(f) +``` + +The queue is now `[ f, e ]`. Dequeue `f`. Remove the edge between `f` and `e` because `e` has already been visited. + +```swift +queue.dequeue() // f +f.removeEdgeTo(e) +``` + +The queue is now `[ e ]`. Dequeue `e`. + +```swift +queue.dequeue() // e +``` + +The queue is empty, which means the minimum spanning tree has been computed. + +Here's the code: + +```swift +func breadthFirstSearchMinimumSpanningTree(graph: Graph, source: Node) -> Graph { + let minimumSpanningTree = graph.duplicate() + + var queue = Queue() + let sourceInMinimumSpanningTree = minimumSpanningTree.findNodeWithLabel(source.label) + queue.enqueue(sourceInMinimumSpanningTree) + sourceInMinimumSpanningTree.visited = true + + while let current = queue.dequeue() { + for edge in current.neighbors { + let neighborNode = edge.neighbor + if !neighborNode.visited { + neighborNode.visited = true + queue.enqueue(neighborNode) + } else { + current.remove(edge) + } + } + } + + return minimumSpanningTree +} +``` + +This function returns a new `Graph` object that describes just the minimum spanning tree. In the figure, that would be the graph containing just the bold edges. + +Put this code in a playground and test it like so: + +```swift +let graph = Graph() + +let nodeA = graph.addNode("a") +let nodeB = graph.addNode("b") +let nodeC = graph.addNode("c") +let nodeD = graph.addNode("d") +let nodeE = graph.addNode("e") +let nodeF = graph.addNode("f") +let nodeG = graph.addNode("g") +let nodeH = graph.addNode("h") +let nodeI = graph.addNode("i") + +graph.addEdge(nodeA, neighbor: nodeB) +graph.addEdge(nodeA, neighbor: nodeH) +graph.addEdge(nodeB, neighbor: nodeA) +graph.addEdge(nodeB, neighbor: nodeC) +graph.addEdge(nodeB, neighbor: nodeH) +graph.addEdge(nodeC, neighbor: nodeB) +graph.addEdge(nodeC, neighbor: nodeD) +graph.addEdge(nodeC, neighbor: nodeF) +graph.addEdge(nodeC, neighbor: nodeI) +graph.addEdge(nodeD, neighbor: nodeC) +graph.addEdge(nodeD, neighbor: nodeE) +graph.addEdge(nodeD, neighbor: nodeF) +graph.addEdge(nodeE, neighbor: nodeD) +graph.addEdge(nodeE, neighbor: nodeF) +graph.addEdge(nodeF, neighbor: nodeC) +graph.addEdge(nodeF, neighbor: nodeD) +graph.addEdge(nodeF, neighbor: nodeE) +graph.addEdge(nodeF, neighbor: nodeG) +graph.addEdge(nodeG, neighbor: nodeF) +graph.addEdge(nodeG, neighbor: nodeH) +graph.addEdge(nodeG, neighbor: nodeI) +graph.addEdge(nodeH, neighbor: nodeA) +graph.addEdge(nodeH, neighbor: nodeB) +graph.addEdge(nodeH, neighbor: nodeG) +graph.addEdge(nodeH, neighbor: nodeI) +graph.addEdge(nodeI, neighbor: nodeC) +graph.addEdge(nodeI, neighbor: nodeG) +graph.addEdge(nodeI, neighbor: nodeH) + +let minimumSpanningTree = breadthFirstSearchMinimumSpanningTree(graph, source: nodeA) + +print(minimumSpanningTree) // [node: a edges: ["b", "h"]] + // [node: b edges: ["c"]] + // [node: c edges: ["d", "f"]] + // [node: d edges: ["e"]] + // [node: h edges: ["g", "i"]] +``` + +> **Note:** On an unweighed graph, any spanning tree is always a minimal spanning tree. This means you can also use a [depth-first search](../Depth-First Search) to find the minimum spanning tree. + +*Written by [Chris Pilcher](https://github.com/chris-pilcher) and Matthijs Hollemans* diff --git a/Minimum Spanning Tree/Tests/Graph.swift b/Minimum Spanning Tree/Tests/Graph.swift new file mode 100644 index 000000000..6f69ee800 --- /dev/null +++ b/Minimum Spanning Tree/Tests/Graph.swift @@ -0,0 +1,106 @@ +// MARK: - Edge + +public class Edge : Equatable { + public var neighbor: Node + + public init(neighbor: Node) { + self.neighbor = neighbor + } +} + +public func ==(lhs: Edge, rhs: Edge) -> Bool { + return lhs.neighbor == rhs.neighbor +} + +// MARK: - Node + +public class Node : CustomStringConvertible, Equatable { + public var neighbors: [Edge] + + public private(set) var label: String + public var distance: Int? + public var visited: Bool + + public init(label: String) { + self.label = label + neighbors = [] + visited = false + } + + public var description: String { + if let distance = distance { + return "Node(label: \(label), distance: \(distance))" + } + return "Node(label: \(label), distance: infinity)" + } + + public var hasDistance: Bool { + return distance != nil + } + + public func remove(edge: Edge) { + neighbors.removeAtIndex(neighbors.indexOf{ $0 === edge }!) + } +} + +public func ==(lhs: Node, rhs: Node) -> Bool { + return lhs.label == rhs.label && lhs.neighbors == rhs.neighbors +} + +// MARK: - Graph + +public class Graph : CustomStringConvertible, Equatable { + public private(set) var nodes: [Node] + + public init() { + self.nodes = [] + } + + public func addNode(label: String) -> Node { + let node = Node(label: label) + nodes.append(node) + return node + } + + public func addEdge(source: Node, neighbor: Node) { + let edge = Edge(neighbor: neighbor) + source.neighbors.append(edge) + } + + public var description: String { + var description = "" + + for node in nodes { + if !node.neighbors.isEmpty { + description += "[node: \(node.label) edges: \(node.neighbors.map{ $0.neighbor.label})]" + } + } + return description + } + + public func findNodeWithLabel(label: String) -> Node { + return nodes.filter{ $0.label == label }.first! + } + + public func duplicate() -> Graph { + let duplicated = Graph() + + for node in nodes { + duplicated.addNode(node.label) + } + + for node in nodes { + for edge in node.neighbors { + let source = duplicated.findNodeWithLabel(node.label) + let neighbour = duplicated.findNodeWithLabel(edge.neighbor.label) + duplicated.addEdge(source, neighbor: neighbour) + } + } + + return duplicated + } +} + +public func ==(lhs: Graph, rhs: Graph) -> Bool { + return lhs.nodes == rhs.nodes +} diff --git a/Minimum Spanning Tree/Tests/Info.plist b/Minimum Spanning Tree/Tests/Info.plist new file mode 100644 index 000000000..ba72822e8 --- /dev/null +++ b/Minimum Spanning Tree/Tests/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/Breadth-First Search/Tests/BreadthFirstSearchMinimumSpanningTreeTests.swift b/Minimum Spanning Tree/Tests/MinimumSpanningTreeTests.swift similarity index 98% rename from Breadth-First Search/Tests/BreadthFirstSearchMinimumSpanningTreeTests.swift rename to Minimum Spanning Tree/Tests/MinimumSpanningTreeTests.swift index 527387062..af8da4e5a 100644 --- a/Breadth-First Search/Tests/BreadthFirstSearchMinimumSpanningTreeTests.swift +++ b/Minimum Spanning Tree/Tests/MinimumSpanningTreeTests.swift @@ -1,6 +1,6 @@ import XCTest -class BreadthFirstSearchMinimumSpanningTreeTests: XCTestCase { +class MinimumSpanningTreeTests: XCTestCase { func testMinimumSpanningTreeReturnsSameTreeWhenGivenTree() { let tree = Graph() diff --git a/Minimum Spanning Tree/Tests/Queue.swift b/Minimum Spanning Tree/Tests/Queue.swift new file mode 100644 index 000000000..bf462bbdd --- /dev/null +++ b/Minimum Spanning Tree/Tests/Queue.swift @@ -0,0 +1,31 @@ +public struct Queue { + private var array: [T] + + public init() { + array = [] + } + + public var isEmpty: Bool { + return array.isEmpty + } + + public var count: Int { + return array.count + } + + public mutating func enqueue(element: T) { + array.append(element) + } + + public mutating func dequeue() -> T? { + if isEmpty { + return nil + } else { + return array.removeFirst() + } + } + + public func peek() -> T? { + return array.first + } +} diff --git a/Minimum Spanning Tree/Tests/Tests.xcodeproj/project.pbxproj b/Minimum Spanning Tree/Tests/Tests.xcodeproj/project.pbxproj new file mode 100644 index 000000000..659c7e9f2 --- /dev/null +++ b/Minimum Spanning Tree/Tests/Tests.xcodeproj/project.pbxproj @@ -0,0 +1,272 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 83AACB421C844CED00DDAFC7 /* MinimumSpanningTreeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83AACB411C844CED00DDAFC7 /* MinimumSpanningTreeTests.swift */; }; + 83F9C9691C84437C00B3A87F /* MinimumSpanningTree.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83F9C9661C84437C00B3A87F /* MinimumSpanningTree.swift */; }; + 83F9C9721C84449D00B3A87F /* Graph.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83F9C96E1C84449D00B3A87F /* Graph.swift */; }; + 83F9C9741C84449D00B3A87F /* Queue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83F9C9701C84449D00B3A87F /* Queue.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 7B2BBC801C779D720067B71D /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 7B2BBC941C779E7B0067B71D /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; + 83AACB411C844CED00DDAFC7 /* MinimumSpanningTreeTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MinimumSpanningTreeTests.swift; sourceTree = SOURCE_ROOT; }; + 83F9C9661C84437C00B3A87F /* MinimumSpanningTree.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MinimumSpanningTree.swift; path = ../MinimumSpanningTree.swift; sourceTree = SOURCE_ROOT; }; + 83F9C96E1C84449D00B3A87F /* Graph.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Graph.swift; sourceTree = SOURCE_ROOT; }; + 83F9C9701C84449D00B3A87F /* Queue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Queue.swift; sourceTree = SOURCE_ROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 7B2BBC7D1C779D720067B71D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 7B2BBC681C779D710067B71D = { + isa = PBXGroup; + children = ( + 7B2BBC831C779D720067B71D /* Tests */, + 7B2BBC721C779D710067B71D /* Products */, + ); + sourceTree = ""; + }; + 7B2BBC721C779D710067B71D /* Products */ = { + isa = PBXGroup; + children = ( + 7B2BBC801C779D720067B71D /* Tests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 7B2BBC831C779D720067B71D /* Tests */ = { + isa = PBXGroup; + children = ( + 83F9C9661C84437C00B3A87F /* MinimumSpanningTree.swift */, + 83AACB411C844CED00DDAFC7 /* MinimumSpanningTreeTests.swift */, + 83F9C96E1C84449D00B3A87F /* Graph.swift */, + 83F9C9701C84449D00B3A87F /* Queue.swift */, + 7B2BBC941C779E7B0067B71D /* Info.plist */, + ); + name = Tests; + path = TestsTests; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 7B2BBC7F1C779D720067B71D /* Tests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */; + buildPhases = ( + 7B2BBC7C1C779D720067B71D /* Sources */, + 7B2BBC7D1C779D720067B71D /* Frameworks */, + 7B2BBC7E1C779D720067B71D /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Tests; + productName = TestsTests; + productReference = 7B2BBC801C779D720067B71D /* Tests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 7B2BBC691C779D710067B71D /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0720; + LastUpgradeCheck = 0720; + ORGANIZATIONNAME = "Swift Algorithm Club"; + TargetAttributes = { + 7B2BBC7F1C779D720067B71D = { + CreatedOnToolsVersion = 7.2; + }; + }; + }; + buildConfigurationList = 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 7B2BBC681C779D710067B71D; + productRefGroup = 7B2BBC721C779D710067B71D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 7B2BBC7F1C779D720067B71D /* Tests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 7B2BBC7E1C779D720067B71D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 7B2BBC7C1C779D720067B71D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 83AACB421C844CED00DDAFC7 /* MinimumSpanningTreeTests.swift in Sources */, + 83F9C9721C84449D00B3A87F /* Graph.swift in Sources */, + 83F9C9691C84437C00B3A87F /* MinimumSpanningTree.swift in Sources */, + 83F9C9741C84449D00B3A87F /* Queue.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 7B2BBC871C779D720067B71D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 7B2BBC881C779D720067B71D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + }; + name = Release; + }; + 7B2BBC8D1C779D720067B71D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 7B2BBC8E1C779D720067B71D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7B2BBC871C779D720067B71D /* Debug */, + 7B2BBC881C779D720067B71D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7B2BBC8D1C779D720067B71D /* Debug */, + 7B2BBC8E1C779D720067B71D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 7B2BBC691C779D710067B71D /* Project object */; +} diff --git a/Minimum Spanning Tree/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Minimum Spanning Tree/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme new file mode 100644 index 000000000..74dd9450b --- /dev/null +++ b/Minimum Spanning Tree/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/README.markdown b/README.markdown index d086ca298..c3e3e43ea 100644 --- a/README.markdown +++ b/README.markdown @@ -170,8 +170,8 @@ Most of the time using just the built-in `Array`, `Dictionary`, and `Set` types - [Graph](Graph/) - [Breadth-First Search (BFS)](Breadth-First Search/) - [Depth-First Search (DFS)](Depth-First Search/) :construction: -- Shortest Path -- Minimum Spanning Tree +- [Shortest Path](Shortest Path/) +- [Minimum Spanning Tree](Minimum Spanning Tree/) - All Paths ## Puzzles diff --git a/Shortest Path/Images/Graph.graffle b/Shortest Path/Images/Graph.graffle new file mode 100644 index 0000000000000000000000000000000000000000..432495e6206ff4ec8b9aa5aadf776ffdf9632e2e GIT binary patch literal 2127 zcmV-V2(b4biwFP!000030PS3DSK_)B{yhGQUcX+2zEQx#coqT*b5T5kdS@1E-4)va zIhLf8hC#>0f4@l!eFu@F9%r5MftKdU&Q7wQz0-!>+V2ljTlxX1iwOR_uN35c31X92 z2#-JSUk^?XEBn76@74a*>@@~oFI$phBbP~+*C*XhL)t$q7VC~HXiAsePJbYA z8O37jVqe;yFy)pW z&1IB#`Iu{1AXALSl+2t$kDr}UFdEs=D4YY6OX@R1VXe4?M`|iYwV=q6l3H;k-PdBq zNZtB#=CYu5MrW|NDn9|{y=WC%yhUe%%mB9R{t_k-?y4+k{pm?QkmSXI^i+|R1Idup z#UiGqz&C8*rmOaejlwn)RXWWOzZzCGI>J7z&mL_UB3BywgipD53hSgAdBN?5@utp#KgeiP5;;A~s zo=tJxMq`}PNlEMEq5BRnxrhKyA+V1%qgM1zR#5&!m~#`blsc-c7>BZUs8l4SdL$c1 ziZ1yLI|PB`saYL3HsBO+Qhcu6ks=5v58#A29JFc*s0bP31R88Bo4`Hr^tqb zM<-PUaAG8}o;fy&Ih#VvlB5lWP)&{D(u`ft2O%x!4@fQ-ALn9L=6B331?c~dQVx195+?fW&_5LoL~h>$i)TRq0xl+0+Yuu>^e zNgyr>zZ4z0V1y$MNmWY+lB(&8M2A=9ifUw(hfXuov!uG}PJl(`(e8$TZ11wpy+p?& z+i#_1i)pA+8dD&UFUQ6EHM(#N%*Pmf1Z>v}0|96NkiD(g=qx5CRET-0kyO^%NaQTu zN+KXdB9bCk_zWwCh)NotY|U6K(u`We!u|v}&|1sGY-80kjMWpAmft|sv|(EC-(qj6 znS&2(y$;4aScE^8fy1e%^9C3HW?(E@6 z9*!{LM{@$G3z;kh9_s?m;BO0#HHl3q2mdyt&{9jK;g~{*#mSvLgZ#)*LkCc6$R0|D z%)b>y^$tcw98^{J4i#A(G|hu(RS%-;9;76D5MEmx48?;OWeyQ?5ygPbD6og$O>u#t z@q|G<0wxb+^4^};3s+O6p*fPJ=Hj{a!#_PDsJlc2ZRdzkt{zB=p{|PvUU@~y1HwlN z2-Q~%2&y3#%G&$I12vBac{~W>K|7BJJ92#!$CS6aLC6jlc|7>lZV>)qBr5GfB6(L5 z=~Y3Z(%LnZRyA@GeK-$j#N2`auR)L5*fRY zNO{u-3pt5?`3DQn?A9o{{%+ef)qJ-m->nIDYg#Yft=VA8a`}D#iBic;IXC6NluusM zly!~UuljyoxtyDFZpwiv*I&_;wQ}WsP1(pzIXC6NlpC*Y%I~>WF6E}2n{r^vr>|(r zdb#ZH)4Z1{Yq=@srW}~^+2Z-6uUKB)8AVp~iC#Qiu0J7jS3pu}Z(m#eRJL0m1IHbZ zE%5Qov$GkppxY(pJ+zYPO)(3Kpl^_i?$QZViDtaVRF_~3-BkKhI{T?J<-i7KHiLAF zgtPxZ=nP0ajVpMX9;2JN$*-NDR;MDY;)Y;zpdW2@@;b0zOn1PywNHR2I`mZ-)=ADdgr!P?|z+!+rr7`yu-i%gNkum0_j47H@;x56EGu~_=mie)5 z{ovgiVfod}4#RQ^z-Q8Hn?j;LGQ#uNG&B7PRr1I1;;V( z^^&)HL|=WeT5u*>5s(|eZ~NR#SCH{PfDCec%8;IQDe8z)P9r>euY5V)`#(L>Tq21^ F007*?7SR9z literal 0 HcmV?d00001 diff --git a/Shortest Path/Images/Graph.png b/Shortest Path/Images/Graph.png new file mode 100644 index 0000000000000000000000000000000000000000..6f3a345859919335b930915a0df58c3b66c0a65f GIT binary patch literal 12819 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 literal 0 HcmV?d00001 diff --git a/Shortest Path/README.markdown b/Shortest Path/README.markdown new file mode 100644 index 000000000..b3fb1692d --- /dev/null +++ b/Shortest Path/README.markdown @@ -0,0 +1,106 @@ +# Shortest Path + +Goal: find the shortest route to go from one node to another in a graph. + +Suppose we have to following graph: + +![Example graph](Images/Graph.png) + +We may want to find out what the shortest way is to get from node `A` to node `F`. + +If the [graph is unweighed](../Graph/), then finding the shortest path is easy: we can use the breadth-first search algorithm. For a weighted graph, we can use Dijkstra's algorithm. + +## Unweighted graph: breadth-first search + +[Breadth-first search](../Breadth-First Search/) is a method for traversing a tree or graph data structure. It starts at a source node and explores the immediate neighbor nodes first, before moving to the next level neighbors. As a convenient side effect, it automatically computes the shortest path between a source node and each of the other nodes in the tree or graph. + +The result of the breadth-first search can be represented with a tree: + +![The BFS tree](../Breadth-First Search/Images/TraversalTree.png) + +The root of the tree is the node you started the breadth-first search from. To find the distance from node `A` to any other node, we simply count the number of edges in the tree. And so we find that the shortest path between `A` and `F` is 2. The tree not only tells you how long that path is, but also how to actually get from `A` to `F` (or any of the other nodes). + +Let's put breadth-first search into practice and calculate the shortest path from `A` to all the other nodes. We start with the source node `A` and add it to a queue with a distance of `0`. + +```swift +queue.enqueue(A) +A.distance = 0 +``` + +The queue is now `[ A ]`. We dequeue `A` and enqueue its two immediate neighbor nodes `B` and `C` with a distance of `1`. + +```swift +queue.dequeue() // A +queue.enqueue(B) +B.distance = A.distance + 1 // result: 1 +queue.enqueue(C) +C.distance = A.distance + 1 // result: 1 +``` + +The queue is now `[ B, C ]`. Dequeue `B` and enqueue `B`'s neighbor nodes `D` and `E` with a distance of `2`. + +```swift +queue.dequeue() // B +queue.enqueue(D) +D.distance = B.distance + 1 // result: 2 +queue.enqueue(E) +E.distance = B.distance + 1 // result: 2 +``` + +The queue is now `[ C, D, E ]`. Dequeue `C` and enqueue `C`'s neighbor nodes `F` and `G`, also with a distance of `2`. + +```swift +queue.dequeue() // C +queue.enqueue(F) +F.distance = C.distance + 1 // result: 2 +queue.enqueue(G) +G.distance = C.distance + 1 // result: 2 +``` + +This continues until the queue is empty and we've visited all the nodes. Each time we discover a new node, it gets the `distance` of its parent plus 1. As you can see, this is exactly what the [breadth-first search](../Breadth-First Search/) algorithm does, except that we now also keep track of the distance travelled. + +Here's the code: + +```swift +func breadthFirstSearchShortestPath(graph: Graph, source: Node) -> Graph { + let shortestPathGraph = graph.duplicate() + + var queue = Queue() + let sourceInShortestPathsGraph = shortestPathGraph.findNodeWithLabel(source.label) + queue.enqueue(sourceInShortestPathsGraph) + sourceInShortestPathsGraph.distance = 0 + + while let current = queue.dequeue() { + for edge in current.neighbors { + let neighborNode = edge.neighbor + if !neighborNode.hasDistance { + queue.enqueue(neighborNode) + neighborNode.distance = current.distance! + 1 + } + } + } + + return shortestPathGraph +} +``` + +Put this code in a playground and test it like so: + +```swift +let shortestPathGraph = breadthFirstSearchShortestPath(graph, source: nodeA) +print(shortestPathGraph.nodes) +``` + +This will output: + + Node(label: a, distance: 0), Node(label: b, distance: 1), Node(label: c, distance: 1), + Node(label: d, distance: 2), Node(label: e, distance: 2), Node(label: f, distance: 2), + Node(label: g, distance: 2), Node(label: h, distance: 3) + +> **Note:** This version of `breadthFirstSearchShortestPath()` does not actually produce the tree, it only computes the distances. See [minimum spanning tree](../Minimum Spanning Tree/) on how you can convert the graph into a tree by removing edges. + +## Weighted graph: Dijkstra's algorithm + +[Coming soon] + +*Written by [Chris Pilcher](https://github.com/chris-pilcher) and Matthijs Hollemans* diff --git a/Breadth-First Search/BreadthFirstSearch.playground/Pages/Shortest path example.xcplaygroundpage/Contents.swift b/Shortest Path/ShortestPath.playground/Pages/Shortest path example.xcplaygroundpage/Contents.swift similarity index 92% rename from Breadth-First Search/BreadthFirstSearch.playground/Pages/Shortest path example.xcplaygroundpage/Contents.swift rename to Shortest Path/ShortestPath.playground/Pages/Shortest path example.xcplaygroundpage/Contents.swift index 2a9c1676f..cfc582c49 100644 --- a/Breadth-First Search/BreadthFirstSearch.playground/Pages/Shortest path example.xcplaygroundpage/Contents.swift +++ b/Shortest Path/ShortestPath.playground/Pages/Shortest path example.xcplaygroundpage/Contents.swift @@ -1,7 +1,3 @@ -//: [Previous](@previous) - -//: # Shortest Path Example - func breadthFirstSearchShortestPath(graph: Graph, source: Node) -> Graph { let shortestPathGraph = graph.duplicate() @@ -46,6 +42,3 @@ graph.addEdge(nodeE, neighbor: nodeH) let shortestPathGraph = breadthFirstSearchShortestPath(graph, source: nodeA) print(shortestPathGraph.nodes) - -//: [Next: Minimum Spanning Tree Example](@next) - diff --git a/Breadth-First Search/BreadthFirstSearch.playground/Pages/Shortest path example.xcplaygroundpage/timeline.xctimeline b/Shortest Path/ShortestPath.playground/Pages/Shortest path example.xcplaygroundpage/timeline.xctimeline similarity index 100% rename from Breadth-First Search/BreadthFirstSearch.playground/Pages/Shortest path example.xcplaygroundpage/timeline.xctimeline rename to Shortest Path/ShortestPath.playground/Pages/Shortest path example.xcplaygroundpage/timeline.xctimeline diff --git a/Shortest Path/ShortestPath.playground/Sources/Edge.swift b/Shortest Path/ShortestPath.playground/Sources/Edge.swift new file mode 100644 index 000000000..3937a2cc7 --- /dev/null +++ b/Shortest Path/ShortestPath.playground/Sources/Edge.swift @@ -0,0 +1,11 @@ +public class Edge : Equatable { + public var neighbor: Node + + public init(neighbor: Node) { + self.neighbor = neighbor + } +} + +public func ==(lhs: Edge, rhs: Edge) -> Bool { + return lhs.neighbor == rhs.neighbor +} diff --git a/Shortest Path/ShortestPath.playground/Sources/Graph.swift b/Shortest Path/ShortestPath.playground/Sources/Graph.swift new file mode 100644 index 000000000..e89d4ac97 --- /dev/null +++ b/Shortest Path/ShortestPath.playground/Sources/Graph.swift @@ -0,0 +1,55 @@ +public class Graph : CustomStringConvertible, Equatable { + public private(set) var nodes: [Node] + + public init() { + self.nodes = [] + } + + public func addNode(label: String) -> Node { + let node = Node(label: label) + nodes.append(node) + return node + } + + public func addEdge(source: Node, neighbor: Node) { + let edge = Edge(neighbor: neighbor) + source.neighbors.append(edge) + } + + public var description: String { + var description = "" + + for node in nodes { + if !node.neighbors.isEmpty { + description += "[node: \(node.label) edges: \(node.neighbors.map{ $0.neighbor.label})]" + } + } + return description + } + + public func findNodeWithLabel(label: String) -> Node { + return nodes.filter{ $0.label == label }.first! + } + + public func duplicate() -> Graph { + let duplicated = Graph() + + for node in nodes { + duplicated.addNode(node.label) + } + + for node in nodes { + for edge in node.neighbors { + let source = duplicated.findNodeWithLabel(node.label) + let neighbour = duplicated.findNodeWithLabel(edge.neighbor.label) + duplicated.addEdge(source, neighbor: neighbour) + } + } + + return duplicated + } +} + +public func ==(lhs: Graph, rhs: Graph) -> Bool { + return lhs.nodes == rhs.nodes +} diff --git a/Shortest Path/ShortestPath.playground/Sources/Node.swift b/Shortest Path/ShortestPath.playground/Sources/Node.swift new file mode 100644 index 000000000..9d8435ffa --- /dev/null +++ b/Shortest Path/ShortestPath.playground/Sources/Node.swift @@ -0,0 +1,32 @@ +public class Node : CustomStringConvertible, Equatable { + public var neighbors: [Edge] + + public private(set) var label: String + public var distance: Int? + public var visited: Bool + + public init(label: String) { + self.label = label + neighbors = [] + visited = false + } + + public var description: String { + if let distance = distance { + return "Node(label: \(label), distance: \(distance))" + } + return "Node(label: \(label), distance: infinity)" + } + + public var hasDistance: Bool { + return distance != nil + } + + public func remove(edge: Edge) { + neighbors.removeAtIndex(neighbors.indexOf{ $0 === edge }!) + } +} + +public func ==(lhs: Node, rhs: Node) -> Bool { + return lhs.label == rhs.label && lhs.neighbors == rhs.neighbors +} diff --git a/Shortest Path/ShortestPath.playground/Sources/Queue.swift b/Shortest Path/ShortestPath.playground/Sources/Queue.swift new file mode 100644 index 000000000..bf462bbdd --- /dev/null +++ b/Shortest Path/ShortestPath.playground/Sources/Queue.swift @@ -0,0 +1,31 @@ +public struct Queue { + private var array: [T] + + public init() { + array = [] + } + + public var isEmpty: Bool { + return array.isEmpty + } + + public var count: Int { + return array.count + } + + public mutating func enqueue(element: T) { + array.append(element) + } + + public mutating func dequeue() -> T? { + if isEmpty { + return nil + } else { + return array.removeFirst() + } + } + + public func peek() -> T? { + return array.first + } +} diff --git a/Shortest Path/ShortestPath.playground/contents.xcplayground b/Shortest Path/ShortestPath.playground/contents.xcplayground new file mode 100644 index 000000000..513c2e7e9 --- /dev/null +++ b/Shortest Path/ShortestPath.playground/contents.xcplayground @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/Breadth-First Search/BreadthFirstSearchShortestPath.swift b/Shortest Path/ShortestPath.swift similarity index 100% rename from Breadth-First Search/BreadthFirstSearchShortestPath.swift rename to Shortest Path/ShortestPath.swift diff --git a/Shortest Path/Tests/Graph.swift b/Shortest Path/Tests/Graph.swift new file mode 100644 index 000000000..6f69ee800 --- /dev/null +++ b/Shortest Path/Tests/Graph.swift @@ -0,0 +1,106 @@ +// MARK: - Edge + +public class Edge : Equatable { + public var neighbor: Node + + public init(neighbor: Node) { + self.neighbor = neighbor + } +} + +public func ==(lhs: Edge, rhs: Edge) -> Bool { + return lhs.neighbor == rhs.neighbor +} + +// MARK: - Node + +public class Node : CustomStringConvertible, Equatable { + public var neighbors: [Edge] + + public private(set) var label: String + public var distance: Int? + public var visited: Bool + + public init(label: String) { + self.label = label + neighbors = [] + visited = false + } + + public var description: String { + if let distance = distance { + return "Node(label: \(label), distance: \(distance))" + } + return "Node(label: \(label), distance: infinity)" + } + + public var hasDistance: Bool { + return distance != nil + } + + public func remove(edge: Edge) { + neighbors.removeAtIndex(neighbors.indexOf{ $0 === edge }!) + } +} + +public func ==(lhs: Node, rhs: Node) -> Bool { + return lhs.label == rhs.label && lhs.neighbors == rhs.neighbors +} + +// MARK: - Graph + +public class Graph : CustomStringConvertible, Equatable { + public private(set) var nodes: [Node] + + public init() { + self.nodes = [] + } + + public func addNode(label: String) -> Node { + let node = Node(label: label) + nodes.append(node) + return node + } + + public func addEdge(source: Node, neighbor: Node) { + let edge = Edge(neighbor: neighbor) + source.neighbors.append(edge) + } + + public var description: String { + var description = "" + + for node in nodes { + if !node.neighbors.isEmpty { + description += "[node: \(node.label) edges: \(node.neighbors.map{ $0.neighbor.label})]" + } + } + return description + } + + public func findNodeWithLabel(label: String) -> Node { + return nodes.filter{ $0.label == label }.first! + } + + public func duplicate() -> Graph { + let duplicated = Graph() + + for node in nodes { + duplicated.addNode(node.label) + } + + for node in nodes { + for edge in node.neighbors { + let source = duplicated.findNodeWithLabel(node.label) + let neighbour = duplicated.findNodeWithLabel(edge.neighbor.label) + duplicated.addEdge(source, neighbor: neighbour) + } + } + + return duplicated + } +} + +public func ==(lhs: Graph, rhs: Graph) -> Bool { + return lhs.nodes == rhs.nodes +} diff --git a/Shortest Path/Tests/Info.plist b/Shortest Path/Tests/Info.plist new file mode 100644 index 000000000..ba72822e8 --- /dev/null +++ b/Shortest Path/Tests/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/Shortest Path/Tests/Queue.swift b/Shortest Path/Tests/Queue.swift new file mode 100644 index 000000000..bf462bbdd --- /dev/null +++ b/Shortest Path/Tests/Queue.swift @@ -0,0 +1,31 @@ +public struct Queue { + private var array: [T] + + public init() { + array = [] + } + + public var isEmpty: Bool { + return array.isEmpty + } + + public var count: Int { + return array.count + } + + public mutating func enqueue(element: T) { + array.append(element) + } + + public mutating func dequeue() -> T? { + if isEmpty { + return nil + } else { + return array.removeFirst() + } + } + + public func peek() -> T? { + return array.first + } +} diff --git a/Breadth-First Search/Tests/BreadthFirstSearchShortestPathTests.swift b/Shortest Path/Tests/ShortestPathTests.swift similarity index 98% rename from Breadth-First Search/Tests/BreadthFirstSearchShortestPathTests.swift rename to Shortest Path/Tests/ShortestPathTests.swift index b13fac2d1..17c9264a1 100644 --- a/Breadth-First Search/Tests/BreadthFirstSearchShortestPathTests.swift +++ b/Shortest Path/Tests/ShortestPathTests.swift @@ -1,6 +1,6 @@ import XCTest -class BreadthFirstSearchShortestPathTests: XCTestCase { +class ShortestPathTests: XCTestCase { func testShortestPathWhenGivenTree() { let tree = Graph() diff --git a/Shortest Path/Tests/Tests.xcodeproj/project.pbxproj b/Shortest Path/Tests/Tests.xcodeproj/project.pbxproj new file mode 100644 index 000000000..35aeffa54 --- /dev/null +++ b/Shortest Path/Tests/Tests.xcodeproj/project.pbxproj @@ -0,0 +1,272 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 83AACB441C8456D200DDAFC7 /* ShortestPathTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83AACB431C8456D200DDAFC7 /* ShortestPathTests.swift */; }; + 83F9C96A1C84437C00B3A87F /* ShortestPath.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83F9C9671C84437C00B3A87F /* ShortestPath.swift */; }; + 83F9C9721C84449D00B3A87F /* Graph.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83F9C96E1C84449D00B3A87F /* Graph.swift */; }; + 83F9C9741C84449D00B3A87F /* Queue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83F9C9701C84449D00B3A87F /* Queue.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 7B2BBC801C779D720067B71D /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 7B2BBC941C779E7B0067B71D /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; + 83AACB431C8456D200DDAFC7 /* ShortestPathTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ShortestPathTests.swift; sourceTree = SOURCE_ROOT; }; + 83F9C9671C84437C00B3A87F /* ShortestPath.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ShortestPath.swift; path = ../ShortestPath.swift; sourceTree = SOURCE_ROOT; }; + 83F9C96E1C84449D00B3A87F /* Graph.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Graph.swift; sourceTree = SOURCE_ROOT; }; + 83F9C9701C84449D00B3A87F /* Queue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Queue.swift; sourceTree = SOURCE_ROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 7B2BBC7D1C779D720067B71D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 7B2BBC681C779D710067B71D = { + isa = PBXGroup; + children = ( + 7B2BBC831C779D720067B71D /* Tests */, + 7B2BBC721C779D710067B71D /* Products */, + ); + sourceTree = ""; + }; + 7B2BBC721C779D710067B71D /* Products */ = { + isa = PBXGroup; + children = ( + 7B2BBC801C779D720067B71D /* Tests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 7B2BBC831C779D720067B71D /* Tests */ = { + isa = PBXGroup; + children = ( + 83F9C9671C84437C00B3A87F /* ShortestPath.swift */, + 83AACB431C8456D200DDAFC7 /* ShortestPathTests.swift */, + 83F9C96E1C84449D00B3A87F /* Graph.swift */, + 83F9C9701C84449D00B3A87F /* Queue.swift */, + 7B2BBC941C779E7B0067B71D /* Info.plist */, + ); + name = Tests; + path = TestsTests; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 7B2BBC7F1C779D720067B71D /* Tests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */; + buildPhases = ( + 7B2BBC7C1C779D720067B71D /* Sources */, + 7B2BBC7D1C779D720067B71D /* Frameworks */, + 7B2BBC7E1C779D720067B71D /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Tests; + productName = TestsTests; + productReference = 7B2BBC801C779D720067B71D /* Tests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 7B2BBC691C779D710067B71D /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0720; + LastUpgradeCheck = 0720; + ORGANIZATIONNAME = "Swift Algorithm Club"; + TargetAttributes = { + 7B2BBC7F1C779D720067B71D = { + CreatedOnToolsVersion = 7.2; + }; + }; + }; + buildConfigurationList = 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 7B2BBC681C779D710067B71D; + productRefGroup = 7B2BBC721C779D710067B71D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 7B2BBC7F1C779D720067B71D /* Tests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 7B2BBC7E1C779D720067B71D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 7B2BBC7C1C779D720067B71D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 83AACB441C8456D200DDAFC7 /* ShortestPathTests.swift in Sources */, + 83F9C9721C84449D00B3A87F /* Graph.swift in Sources */, + 83F9C9741C84449D00B3A87F /* Queue.swift in Sources */, + 83F9C96A1C84437C00B3A87F /* ShortestPath.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 7B2BBC871C779D720067B71D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 7B2BBC881C779D720067B71D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + }; + name = Release; + }; + 7B2BBC8D1C779D720067B71D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 7B2BBC8E1C779D720067B71D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7B2BBC871C779D720067B71D /* Debug */, + 7B2BBC881C779D720067B71D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7B2BBC8D1C779D720067B71D /* Debug */, + 7B2BBC8E1C779D720067B71D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 7B2BBC691C779D710067B71D /* Project object */; +} diff --git a/Shortest Path/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Shortest Path/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme new file mode 100644 index 000000000..74dd9450b --- /dev/null +++ b/Shortest Path/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + From 21ce7ad2fe0943bad1e7eb91b8b72c8d4c876ca7 Mon Sep 17 00:00:00 2001 From: Matthew Wo <9029537@gmail.com> Date: Fri, 18 Mar 2016 19:12:34 -0700 Subject: [PATCH 0166/1679] added more test cases to test the validity of the AVL Tree --- .../AVLTree.playground/Sources/AVLTree.swift | 6 +- AVL Tree/AVLTree.swift | 6 +- AVL Tree/Tests/AVLTreeTests.swift | 97 +++++++++++++++---- 3 files changed, 87 insertions(+), 22 deletions(-) diff --git a/AVL Tree/AVLTree.playground/Sources/AVLTree.swift b/AVL Tree/AVLTree.playground/Sources/AVLTree.swift index 91df1ed9e..580a51e8e 100644 --- a/AVL Tree/AVLTree.playground/Sources/AVLTree.swift +++ b/AVL Tree/AVLTree.playground/Sources/AVLTree.swift @@ -26,8 +26,8 @@ public class TreeNode { public var payload: Payload? private var key: Key - private var leftChild: Node? - private var rightChild: Node? + internal var leftChild: Node? + internal var rightChild: Node? private var height: Int weak private var parent: Node? @@ -343,6 +343,8 @@ extension AVLTree { } else if node.isRightChild { parent.rightChild = nil } + + balance(parent) } else { // at root root = nil diff --git a/AVL Tree/AVLTree.swift b/AVL Tree/AVLTree.swift index 91df1ed9e..580a51e8e 100644 --- a/AVL Tree/AVLTree.swift +++ b/AVL Tree/AVLTree.swift @@ -26,8 +26,8 @@ public class TreeNode { public var payload: Payload? private var key: Key - private var leftChild: Node? - private var rightChild: Node? + internal var leftChild: Node? + internal var rightChild: Node? private var height: Int weak private var parent: Node? @@ -343,6 +343,8 @@ extension AVLTree { } else if node.isRightChild { parent.rightChild = nil } + + balance(parent) } else { // at root root = nil diff --git a/AVL Tree/Tests/AVLTreeTests.swift b/AVL Tree/Tests/AVLTreeTests.swift index 6ec9b5f65..51e1211c3 100644 --- a/AVL Tree/Tests/AVLTreeTests.swift +++ b/AVL Tree/Tests/AVLTreeTests.swift @@ -11,39 +11,61 @@ import XCTest class AVLTreeTests: XCTestCase { var tree : AVLTree? - + override func setUp() { super.setUp() tree = AVLTree() - tree?.insert(1, "A") - tree?.insert(2, "B") - tree?.insert(3, "C") - tree?.insert(4, "D") } override func tearDown() { // Put teardown code here. This method is called after the invocation of each test method in the class. super.tearDown() } - + + func testAVLTreeBalancedAutoPopulate() { + self.tree?.autopopulateWithNodes(10) + + do { + try self.tree?.inOrderCheckBalanced(self.tree?.root) + } catch _ { + XCTFail("Tree is not balanced after autopopulate") + } + } + + func testAVLTreeBalancedInsert() { + self.tree?.autopopulateWithNodes(5) + + for i in 6...10 { + self.tree?.insert(i) + do { + try self.tree?.inOrderCheckBalanced(self.tree?.root) + } catch _ { + XCTFail("Tree is not balanced after inserting " + String(i)) + } + } + } + + func testAVLTreeBalancedDelete() { + self.tree?.autopopulateWithNodes(5) + + for i in 1...6 { + self.tree?.delete(i) + do { + try self.tree?.inOrderCheckBalanced(self.tree?.root) + } catch _ { + XCTFail("Tree is not balanced after deleting " + String(i)) + } + } + } + func testEmptyInitialization() { let tree = AVLTree() XCTAssertEqual(tree.size, 0) XCTAssertNil(tree.root) } - - func testNotEmptyInitialization() { - XCTAssertNotNil(self.tree?.root) - XCTAssertNotEqual(self.tree!.size, 0) - } - - func testInsertDuplicated() { - self.tree?.insert(1, "A") - XCTAssertEqual(self.tree?.size, 5, "Duplicated elements should be allowed") - } - + func testSingleInsertionPerformance() { self.measureBlock { self.tree?.insert(5, "E") @@ -92,6 +114,14 @@ class AVLTreeTests: XCTestCase { self.tree?.delete(1056) XCTAssertNil(self.tree?.search(1056), "Key should not exist") } + + func testInsertSize() { + let tree = AVLTree() + for i in 0...5 { + tree.insert(i, "") + XCTAssertEqual(tree.size, i + 1, "Insert didn't update size correctly!") + } + } func testDelete() { let permutations = [ @@ -109,9 +139,12 @@ class AVLTreeTests: XCTestCase { tree.insert(3, "three") tree.insert(4, "two") tree.insert(5, "one") - + + var count = tree.size for i in p { tree.delete(i) + count -= 1 + XCTAssertEqual(tree.size, count, "Delete didn't update size correctly!") } } } @@ -126,3 +159,31 @@ extension AVLTree where Key : SignedIntegerType { } } } + +enum AVLTreeError: ErrorType { + case NotBalanced +} + +extension AVLTree where Key : SignedIntegerType { + func height(node: Node?) -> Int { + if let node = node { + let lHeight = height(node.leftChild) + let rHeight = height(node.rightChild) + + return max(lHeight, rHeight) + 1 + } + return 0 + } + + func inOrderCheckBalanced(node: Node?) throws { + if let node = node { + guard abs(height(node.leftChild) - height(node.rightChild)) <= 1 else { + throw AVLTreeError.NotBalanced + } + try inOrderCheckBalanced(node.leftChild) + try inOrderCheckBalanced(node.rightChild) + } + } +} + + From 243f9257410f85debc7a1d15699a02c4b89e755f Mon Sep 17 00:00:00 2001 From: Matthijs Hollemans Date: Sat, 19 Mar 2016 12:04:40 +0100 Subject: [PATCH 0167/1679] Improve explanation of DFS --- Breadth-First Search/README.markdown | 4 +-- .../Contents.swift | 3 +- Depth-First Search/Images/AnimatedExample.gif | Bin 0 -> 17042 bytes .../Images/AnimatedExample.graffle | Bin 0 -> 6537 bytes Depth-First Search/Images/AnimatedExample.psd | Bin 0 -> 1059655 bytes .../Images/TraversalTree.graffle | Bin 0 -> 2118 bytes Depth-First Search/Images/TraversalTree.png | Bin 0 -> 11619 bytes Depth-First Search/README.markdown | 30 +++++++++++++++--- .../Tests/DepthFirstSearchTests.swift | 5 +-- Depth-First Search/{ => Tests}/Graph.swift | 0 .../Tests/Tests.xcodeproj/project.pbxproj | 2 +- 11 files changed, 33 insertions(+), 11 deletions(-) create mode 100644 Depth-First Search/Images/AnimatedExample.gif create mode 100644 Depth-First Search/Images/AnimatedExample.graffle create mode 100644 Depth-First Search/Images/AnimatedExample.psd create mode 100644 Depth-First Search/Images/TraversalTree.graffle create mode 100644 Depth-First Search/Images/TraversalTree.png rename Depth-First Search/{ => Tests}/Graph.swift (100%) diff --git a/Breadth-First Search/README.markdown b/Breadth-First Search/README.markdown index 4eb77b0ac..12e906532 100644 --- a/Breadth-First Search/README.markdown +++ b/Breadth-First Search/README.markdown @@ -2,6 +2,8 @@ Breadth-first search (BFS) is an algorithm for traversing or searching [tree](../Tree/) or [graph](../Graph/) data structures. It starts at a source node and explores the immediate neighbor nodes first, before moving to the next level neighbors. +Breadth-first search can be used on both directed and undirected graphs. + ## Animated example Here's how breadth-first search works on a graph: @@ -83,8 +85,6 @@ The parent of a node is the one that "discovered" that node. The root of the tre For an unweighted graph, this tree defines a shortest path from the starting node to every other node in the tree. So breadth-first search is one way to find the shortest path between two nodes in a graph. -Breadth-first search can be used on directed and undirected graphs. - ## The code Simple implementation of breadth-first search using a queue: diff --git a/Depth-First Search/DepthFirstSearch.playground/Pages/Simple Example.xcplaygroundpage/Contents.swift b/Depth-First Search/DepthFirstSearch.playground/Pages/Simple Example.xcplaygroundpage/Contents.swift index cc4bd7dd3..770712bfb 100644 --- a/Depth-First Search/DepthFirstSearch.playground/Pages/Simple Example.xcplaygroundpage/Contents.swift +++ b/Depth-First Search/DepthFirstSearch.playground/Pages/Simple Example.xcplaygroundpage/Contents.swift @@ -30,7 +30,8 @@ graph.addEdge(nodeB, neighbor: nodeE) graph.addEdge(nodeC, neighbor: nodeF) graph.addEdge(nodeC, neighbor: nodeG) graph.addEdge(nodeE, neighbor: nodeH) - +graph.addEdge(nodeE, neighbor: nodeF) +graph.addEdge(nodeF, neighbor: nodeG) let nodesExplored = depthFirstSearch(graph, source: nodeA) print(nodesExplored) diff --git a/Depth-First Search/Images/AnimatedExample.gif b/Depth-First Search/Images/AnimatedExample.gif new file mode 100644 index 0000000000000000000000000000000000000000..6769f5b5969eea8429a5d8213932ecd5336fbb6d GIT binary patch literal 17042 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 literal 0 HcmV?d00001 diff --git a/Depth-First Search/Images/AnimatedExample.graffle b/Depth-First Search/Images/AnimatedExample.graffle new file mode 100644 index 0000000000000000000000000000000000000000..fb91dd9ca4a90021b9b6782d8c1d764b92a59823 GIT binary patch literal 6537 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%0DD#AkoBP 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 literal 0 HcmV?d00001 diff --git a/Depth-First Search/Images/TraversalTree.graffle b/Depth-First Search/Images/TraversalTree.graffle new file mode 100644 index 0000000000000000000000000000000000000000..d40812e4a8a0fac33c92bbda313e059f170fe879 GIT binary patch literal 2118 zcmV-M2)XwkiwFP!000030PS2`bKby2z8>bI1O&S|f& z2pQ#a`+Qf~9dkbYST4`!^AeP(l1(QP=#?)Rog&5`IzrgK=umRFvn$jD(i7&0Uma}o zgPjlcJM?hSusQyYI`9FpQ{tfedRhJ|8ZqH$gxCS7mzSr@E%Taw1uP|rwrB03wW%jYSl_Ah_%$qOX-0X zGfo@MUo($~+But{^0NI9+ILbbafHU{7~3IiG5iHgBD`f=sQvK~>?z=BPkB^Lqqe80 zpkh5eCG39k=9g~(^iCEI#!GOIDqx|gNq{M(&nI1h@^K>YpgkFZ!tKJ z%!&*<@5ap$9t~ZwJc~{OAA0C3rIQVUq6x`&=ye$$;V2xI&h&j5pUS955C1?Je9Y&W zUeujUNW;Y=lCet7TIHjAQ)mkjA)X=V9_UuR?4K;5;zEXW3-XLX8c?l$pzo_SVbn*n z`cVhUzk&E!t*t9y!JCa9EXuNixascBCsmPfL3QcGr}-WWP`9v^K4$WJe; z@=M$w`H3qlTh2m*v4jDke2^3$^yr`wv>y`iA#^?eP7s3n5WAa-jn86gLZz6O#)z>h zMq+3G*CaAuLn7LZyNH0jV-a(bu zkjVH)B+A@rQX~?ffEt65}O zdy4p4#i9xj4@DKdTCnJ6Vo|MN(JLLajzsEv-HP%_R*>jdyA`FjjADC6R#hxEDw@A< zq>IVcQ+q~hN!T01DRNfQFh5v9PO$odvhtgl*)GZo{;A`wNf|-x5;}O6RN?1|YAj!@ zjSF{eXs2H1HV3`H*Fx9(sF z21A0y(H=wQAr6!<9iF2Z`t3hp4_@KB#r_#m_p_Z_`PWX z@vW+wf3T|ZplODGr~-M=bswVFe28KA5EJ+i(OVuY)rVLjM18rK5y)o@x`S`F{DI@q zm?JWTHm3~i?D(VbbWIu9L!dODp4&Zq0aFa|Y%9LD#*|t?l!7Q*BFgbw5=E8U5fy7| zM5z`;DTuNqq8z;;QA`7DmnfBjCHPP&L95uY*iHTLjr zwoD_X#@{WwfFtB(iY)X@jm7Ci0GlFjaKtt!YxxgC(>_fWi-enM!LFMu=<=Q|*N_9x zrh;^tkZeDPlbodCt5MV}{6bvvEIu`L0rncB`LobfK_o1oGrl^E8U#;b6+J7)=tFIh z0qGegtyrPUa%Vc0N+N6z2~zk)Ln$~YffU~L&1{nqCRtk?$}`3gSx6-J1Wiz z!$mpb2DMwYk6Jaqb}JBsUQxVtPC43qOkIW%;R!G27XmKPB4#!gE)&k7n5a8%1FYoe zYUZ5x4k_n!at2wfrZ4{L!&3CnrI06iy*M}2B!{Cs6lgf14F8}6y25TuQjwQcWK&0` z=^RCe4gSM9`RsnVQ33k%(EWOPLL0^(hku;*+T+H!dj(AO_U5x|kDB7z>0YT{$G0cf zZbP&;+h)J7eg5|K<{UImZ`zICH-S02cjwLH_2zfbkpC0+$h5Lf{)Jenu|($05g#0K zh~0BPUOd-=3r7(Nfh?O?;|G#ZWaB$Tu!4wd5O@IZ9>pT_RbVjB+UP zD@^~TTo1kH{P*efJ;Wz7xIYnHf@JDgv6{F<(CHHQ;rX0$N#~o^<_hRWg}HwA?_-`# ze?bLtV)+sDn25EiZ-y*&4Hj)do%;rBHovo60zhJ;7xuj(_}dIcPhx9Ef90Vz;h3#+ z`*r^EF?*A^!9+ZStxo058Dqi|z9+NQ=O9~s-oBqgBFOgNz{SW*1zeRIn=jEQk-j2NR4d|1-_T1HQ#zwkF-qp1V(Qf#XT*!`mkLwr wB;*>32S6`3DdfDEm_w5fInu+mZsH}(C?#dmM|AZ6&BVdZ-?#fFV*Nq@0Ki8FhyVZp literal 0 HcmV?d00001 diff --git a/Depth-First Search/Images/TraversalTree.png b/Depth-First Search/Images/TraversalTree.png new file mode 100644 index 0000000000000000000000000000000000000000..bff2070dd99e50d6918daae66457857ab997fced GIT binary patch literal 11619 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 literal 0 HcmV?d00001 diff --git a/Depth-First Search/README.markdown b/Depth-First Search/README.markdown index 322635d7a..a44ae8163 100644 --- a/Depth-First Search/README.markdown +++ b/Depth-First Search/README.markdown @@ -2,7 +2,25 @@ Depth-first search (DFS) is an algorithm for traversing or searching [tree](../Tree/) or [graph](../Graph/) data structures. It starts at a source node and explores as far as possible along each branch before backtracking. -[TODO: this is a work-in-progress] +Depth-first search can be used on both directed and undirected graphs. + +## Animated example + +Here's how depth-first search works on a graph: + +![Animated example](Images/AnimatedExample.gif) + +Let's say we start the search from node `A`. In depth-first search we look at the starting node's first neighbor and visit that. In the example that is node `B`. Then we look at node `B`'s first neighbor and visit it. This is node `D`. Since `D` doesn't have any unvisited neighbors of its own, we backtrack to node `B` and go to its other neighbor `E`. And so on, until we've visited all the nodes in the graph. + +Each time we visit the first neighbor and keep going until there's nowhere left to go, and then we backtrack to a point where there are again nodes to visit. When we've backtracked all the way to node `A`, the search is complete. + +For the example, the nodes were visited in the order `A`, `B`, `D`, `E`, `H`, `F`, `G`, `C`. + +The depth-first search process can also be visualized as a tree: + +![Traversal tree](Images/TraversalTree.png) + +The parent of a node is the one that "discovered" that node. The root of the tree is the node you started the depth-first search from. Whenever there's a branch, that's where we backtracked. ## The code @@ -45,20 +63,22 @@ graph.addEdge(nodeB, neighbor: nodeE) graph.addEdge(nodeC, neighbor: nodeF) graph.addEdge(nodeC, neighbor: nodeG) graph.addEdge(nodeE, neighbor: nodeH) +graph.addEdge(nodeE, neighbor: nodeF) +graph.addEdge(nodeF, neighbor: nodeG) let nodesExplored = depthFirstSearch(graph, source: nodeA) print(nodesExplored) ``` -This will output: `["a", "b", "d", "e", "h", "c", "f", "g"]` +This will output: `["a", "b", "d", "e", "h", "f", "g", "c"]` -## Applications +## What is DFS good for? Depth-first search can be used to solve many problems, for example: * Finding connected components of a sparse graph -* Topological sorting of nodes in a graph +* [Topological sorting](../Topological Sort/) of nodes in a graph * Finding bridges of a graph (see: [Bridges](https://en.wikipedia.org/wiki/Bridge_(graph_theory)#Bridge-finding_algorithm)) * And lots of others! -*Written for Swift Algorithm Club by Paulo Tanaka* +*Written for Swift Algorithm Club by Paulo Tanaka and Matthijs Hollemans* diff --git a/Depth-First Search/Tests/DepthFirstSearchTests.swift b/Depth-First Search/Tests/DepthFirstSearchTests.swift index aacc8efcf..2cb2556ce 100755 --- a/Depth-First Search/Tests/DepthFirstSearchTests.swift +++ b/Depth-First Search/Tests/DepthFirstSearchTests.swift @@ -4,6 +4,7 @@ class DepthFirstSearchTests: XCTestCase { func testExploringTree() { let tree = Graph() + let nodeA = tree.addNode("a") let nodeB = tree.addNode("b") let nodeC = tree.addNode("c") @@ -12,6 +13,7 @@ class DepthFirstSearchTests: XCTestCase { let nodeF = tree.addNode("f") let nodeG = tree.addNode("g") let nodeH = tree.addNode("h") + tree.addEdge(nodeA, neighbor: nodeB) tree.addEdge(nodeA, neighbor: nodeC) tree.addEdge(nodeB, neighbor: nodeD) @@ -70,7 +72,6 @@ class DepthFirstSearchTests: XCTestCase { let nodesExplored = depthFirstSearch(graph, source: nodeA) XCTAssertEqual(nodesExplored, ["a", "b", "c", "d", "e", "f", "g", "h", "i"]) - } func testExploringGraphWithASingleNode() { @@ -81,4 +82,4 @@ class DepthFirstSearchTests: XCTestCase { XCTAssertEqual(nodesExplored, ["a"]) } -} \ No newline at end of file +} diff --git a/Depth-First Search/Graph.swift b/Depth-First Search/Tests/Graph.swift similarity index 100% rename from Depth-First Search/Graph.swift rename to Depth-First Search/Tests/Graph.swift diff --git a/Depth-First Search/Tests/Tests.xcodeproj/project.pbxproj b/Depth-First Search/Tests/Tests.xcodeproj/project.pbxproj index 39c15ce79..9e2872f88 100644 --- a/Depth-First Search/Tests/Tests.xcodeproj/project.pbxproj +++ b/Depth-First Search/Tests/Tests.xcodeproj/project.pbxproj @@ -16,7 +16,7 @@ 7B2BBC801C779D720067B71D /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 7B2BBC941C779E7B0067B71D /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; 83F9C96B1C8443E800B3A87F /* DepthFirstSearchTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DepthFirstSearchTests.swift; sourceTree = SOURCE_ROOT; }; - 83F9C96E1C84449D00B3A87F /* Graph.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Graph.swift; path = ../Graph.swift; sourceTree = SOURCE_ROOT; }; + 83F9C96E1C84449D00B3A87F /* Graph.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Graph.swift; sourceTree = SOURCE_ROOT; }; FFC6E11D1C8656D10046BA79 /* DepthFirstSearch.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = DepthFirstSearch.swift; path = ../DepthFirstSearch.swift; sourceTree = SOURCE_ROOT; }; /* End PBXFileReference section */ From 13e69562bac29edd716871254ec0816407ddc344 Mon Sep 17 00:00:00 2001 From: Matthijs Hollemans Date: Sat, 19 Mar 2016 12:11:33 +0100 Subject: [PATCH 0168/1679] Shortest path and minimum spanning tree are for unweighted graphs only --- .../Images/Graph.png | Bin .../Images/Graph.sketch | Bin .../Images/MinimumSpanningTree.png | Bin .../Images/MinimumSpanningTree.sketch | Bin .../Images/Tree.graffle | Bin .../Images/Tree.png | Bin .../Contents.swift | 0 .../timeline.xctimeline | 0 .../Resources/Minimum_Spanning_Tree.png | Bin .../Sources/Edge.swift | 0 .../Sources/Graph.swift | 0 .../Sources/Node.swift | 0 .../Sources/Queue.swift | 0 .../contents.xcplayground | 0 .../MinimumSpanningTree.swift | 0 .../README.markdown | 2 +- .../Tests/Graph.swift | 0 .../Tests/Info.plist | 0 .../Tests/MinimumSpanningTreeTests.swift | 0 .../Tests/Queue.swift | 0 .../Tests/Tests.xcodeproj/project.pbxproj | 0 .../xcshareddata/xcschemes/Tests.xcscheme | 0 README.markdown | 6 +++--- .../Images/Graph.graffle | Bin .../Images/Graph.png | Bin .../README.markdown | 6 +----- .../Contents.swift | 0 .../timeline.xctimeline | 0 .../ShortestPath.playground/Sources/Edge.swift | 0 .../ShortestPath.playground/Sources/Graph.swift | 0 .../ShortestPath.playground/Sources/Node.swift | 0 .../ShortestPath.playground/Sources/Queue.swift | 0 .../ShortestPath.playground/contents.xcplayground | 0 .../ShortestPath.swift | 0 .../Tests/Graph.swift | 0 .../Tests/Info.plist | 0 .../Tests/Queue.swift | 0 .../Tests/ShortestPathTests.swift | 0 .../Tests/Tests.xcodeproj/project.pbxproj | 0 .../xcshareddata/xcschemes/Tests.xcscheme | 0 40 files changed, 5 insertions(+), 9 deletions(-) rename {Minimum Spanning Tree => Minimum Spanning Tree (Unweighted)}/Images/Graph.png (100%) rename {Minimum Spanning Tree => Minimum Spanning Tree (Unweighted)}/Images/Graph.sketch (100%) rename {Minimum Spanning Tree => Minimum Spanning Tree (Unweighted)}/Images/MinimumSpanningTree.png (100%) rename {Minimum Spanning Tree => Minimum Spanning Tree (Unweighted)}/Images/MinimumSpanningTree.sketch (100%) rename {Minimum Spanning Tree => Minimum Spanning Tree (Unweighted)}/Images/Tree.graffle (100%) rename {Minimum Spanning Tree => Minimum Spanning Tree (Unweighted)}/Images/Tree.png (100%) rename {Minimum Spanning Tree => Minimum Spanning Tree (Unweighted)}/MinimumSpanningTree.playground/Pages/Minimum spanning tree example.xcplaygroundpage/Contents.swift (100%) rename {Minimum Spanning Tree => Minimum Spanning Tree (Unweighted)}/MinimumSpanningTree.playground/Pages/Minimum spanning tree example.xcplaygroundpage/timeline.xctimeline (100%) rename {Minimum Spanning Tree => Minimum Spanning Tree (Unweighted)}/MinimumSpanningTree.playground/Resources/Minimum_Spanning_Tree.png (100%) rename {Minimum Spanning Tree => Minimum Spanning Tree (Unweighted)}/MinimumSpanningTree.playground/Sources/Edge.swift (100%) rename {Minimum Spanning Tree => Minimum Spanning Tree (Unweighted)}/MinimumSpanningTree.playground/Sources/Graph.swift (100%) rename {Minimum Spanning Tree => Minimum Spanning Tree (Unweighted)}/MinimumSpanningTree.playground/Sources/Node.swift (100%) rename {Minimum Spanning Tree => Minimum Spanning Tree (Unweighted)}/MinimumSpanningTree.playground/Sources/Queue.swift (100%) rename {Minimum Spanning Tree => Minimum Spanning Tree (Unweighted)}/MinimumSpanningTree.playground/contents.xcplayground (100%) rename {Minimum Spanning Tree => Minimum Spanning Tree (Unweighted)}/MinimumSpanningTree.swift (100%) rename {Minimum Spanning Tree => Minimum Spanning Tree (Unweighted)}/README.markdown (99%) rename {Minimum Spanning Tree => Minimum Spanning Tree (Unweighted)}/Tests/Graph.swift (100%) rename {Minimum Spanning Tree => Minimum Spanning Tree (Unweighted)}/Tests/Info.plist (100%) rename {Minimum Spanning Tree => Minimum Spanning Tree (Unweighted)}/Tests/MinimumSpanningTreeTests.swift (100%) rename {Minimum Spanning Tree => Minimum Spanning Tree (Unweighted)}/Tests/Queue.swift (100%) rename {Minimum Spanning Tree => Minimum Spanning Tree (Unweighted)}/Tests/Tests.xcodeproj/project.pbxproj (100%) rename {Minimum Spanning Tree => Minimum Spanning Tree (Unweighted)}/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme (100%) rename {Shortest Path => Shortest Path (Unweighted)}/Images/Graph.graffle (100%) rename {Shortest Path => Shortest Path (Unweighted)}/Images/Graph.png (100%) rename {Shortest Path => Shortest Path (Unweighted)}/README.markdown (98%) rename {Shortest Path => Shortest Path (Unweighted)}/ShortestPath.playground/Pages/Shortest path example.xcplaygroundpage/Contents.swift (100%) rename {Shortest Path => Shortest Path (Unweighted)}/ShortestPath.playground/Pages/Shortest path example.xcplaygroundpage/timeline.xctimeline (100%) rename {Shortest Path => Shortest Path (Unweighted)}/ShortestPath.playground/Sources/Edge.swift (100%) rename {Shortest Path => Shortest Path (Unweighted)}/ShortestPath.playground/Sources/Graph.swift (100%) rename {Shortest Path => Shortest Path (Unweighted)}/ShortestPath.playground/Sources/Node.swift (100%) rename {Shortest Path => Shortest Path (Unweighted)}/ShortestPath.playground/Sources/Queue.swift (100%) rename {Shortest Path => Shortest Path (Unweighted)}/ShortestPath.playground/contents.xcplayground (100%) rename {Shortest Path => Shortest Path (Unweighted)}/ShortestPath.swift (100%) rename {Shortest Path => Shortest Path (Unweighted)}/Tests/Graph.swift (100%) rename {Shortest Path => Shortest Path (Unweighted)}/Tests/Info.plist (100%) rename {Shortest Path => Shortest Path (Unweighted)}/Tests/Queue.swift (100%) rename {Shortest Path => Shortest Path (Unweighted)}/Tests/ShortestPathTests.swift (100%) rename {Shortest Path => Shortest Path (Unweighted)}/Tests/Tests.xcodeproj/project.pbxproj (100%) rename {Shortest Path => Shortest Path (Unweighted)}/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme (100%) diff --git a/Minimum Spanning Tree/Images/Graph.png b/Minimum Spanning Tree (Unweighted)/Images/Graph.png similarity index 100% rename from Minimum Spanning Tree/Images/Graph.png rename to Minimum Spanning Tree (Unweighted)/Images/Graph.png diff --git a/Minimum Spanning Tree/Images/Graph.sketch b/Minimum Spanning Tree (Unweighted)/Images/Graph.sketch similarity index 100% rename from Minimum Spanning Tree/Images/Graph.sketch rename to Minimum Spanning Tree (Unweighted)/Images/Graph.sketch diff --git a/Minimum Spanning Tree/Images/MinimumSpanningTree.png b/Minimum Spanning Tree (Unweighted)/Images/MinimumSpanningTree.png similarity index 100% rename from Minimum Spanning Tree/Images/MinimumSpanningTree.png rename to Minimum Spanning Tree (Unweighted)/Images/MinimumSpanningTree.png diff --git a/Minimum Spanning Tree/Images/MinimumSpanningTree.sketch b/Minimum Spanning Tree (Unweighted)/Images/MinimumSpanningTree.sketch similarity index 100% rename from Minimum Spanning Tree/Images/MinimumSpanningTree.sketch rename to Minimum Spanning Tree (Unweighted)/Images/MinimumSpanningTree.sketch diff --git a/Minimum Spanning Tree/Images/Tree.graffle b/Minimum Spanning Tree (Unweighted)/Images/Tree.graffle similarity index 100% rename from Minimum Spanning Tree/Images/Tree.graffle rename to Minimum Spanning Tree (Unweighted)/Images/Tree.graffle diff --git a/Minimum Spanning Tree/Images/Tree.png b/Minimum Spanning Tree (Unweighted)/Images/Tree.png similarity index 100% rename from Minimum Spanning Tree/Images/Tree.png rename to Minimum Spanning Tree (Unweighted)/Images/Tree.png diff --git a/Minimum Spanning Tree/MinimumSpanningTree.playground/Pages/Minimum spanning tree example.xcplaygroundpage/Contents.swift b/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Pages/Minimum spanning tree example.xcplaygroundpage/Contents.swift similarity index 100% rename from Minimum Spanning Tree/MinimumSpanningTree.playground/Pages/Minimum spanning tree example.xcplaygroundpage/Contents.swift rename to Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Pages/Minimum spanning tree example.xcplaygroundpage/Contents.swift diff --git a/Minimum Spanning Tree/MinimumSpanningTree.playground/Pages/Minimum spanning tree example.xcplaygroundpage/timeline.xctimeline b/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Pages/Minimum spanning tree example.xcplaygroundpage/timeline.xctimeline similarity index 100% rename from Minimum Spanning Tree/MinimumSpanningTree.playground/Pages/Minimum spanning tree example.xcplaygroundpage/timeline.xctimeline rename to Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Pages/Minimum spanning tree example.xcplaygroundpage/timeline.xctimeline diff --git a/Minimum Spanning Tree/MinimumSpanningTree.playground/Resources/Minimum_Spanning_Tree.png b/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Resources/Minimum_Spanning_Tree.png similarity index 100% rename from Minimum Spanning Tree/MinimumSpanningTree.playground/Resources/Minimum_Spanning_Tree.png rename to Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Resources/Minimum_Spanning_Tree.png diff --git a/Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/Edge.swift b/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Sources/Edge.swift similarity index 100% rename from Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/Edge.swift rename to Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Sources/Edge.swift diff --git a/Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/Graph.swift b/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Sources/Graph.swift similarity index 100% rename from Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/Graph.swift rename to Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Sources/Graph.swift diff --git a/Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/Node.swift b/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Sources/Node.swift similarity index 100% rename from Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/Node.swift rename to Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Sources/Node.swift diff --git a/Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/Queue.swift b/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Sources/Queue.swift similarity index 100% rename from Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/Queue.swift rename to Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Sources/Queue.swift diff --git a/Minimum Spanning Tree/MinimumSpanningTree.playground/contents.xcplayground b/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/contents.xcplayground similarity index 100% rename from Minimum Spanning Tree/MinimumSpanningTree.playground/contents.xcplayground rename to Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/contents.xcplayground diff --git a/Minimum Spanning Tree/MinimumSpanningTree.swift b/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.swift similarity index 100% rename from Minimum Spanning Tree/MinimumSpanningTree.swift rename to Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.swift diff --git a/Minimum Spanning Tree/README.markdown b/Minimum Spanning Tree (Unweighted)/README.markdown similarity index 99% rename from Minimum Spanning Tree/README.markdown rename to Minimum Spanning Tree (Unweighted)/README.markdown index 5d988eee6..cfd29c987 100644 --- a/Minimum Spanning Tree/README.markdown +++ b/Minimum Spanning Tree (Unweighted)/README.markdown @@ -1,4 +1,4 @@ -# Minimum Spanning Tree +# Minimum Spanning Tree (Unweighted Graph) A minimum spanning tree describes a path that contains the smallest number of edges that are needed to visit every node in the graph. diff --git a/Minimum Spanning Tree/Tests/Graph.swift b/Minimum Spanning Tree (Unweighted)/Tests/Graph.swift similarity index 100% rename from Minimum Spanning Tree/Tests/Graph.swift rename to Minimum Spanning Tree (Unweighted)/Tests/Graph.swift diff --git a/Minimum Spanning Tree/Tests/Info.plist b/Minimum Spanning Tree (Unweighted)/Tests/Info.plist similarity index 100% rename from Minimum Spanning Tree/Tests/Info.plist rename to Minimum Spanning Tree (Unweighted)/Tests/Info.plist diff --git a/Minimum Spanning Tree/Tests/MinimumSpanningTreeTests.swift b/Minimum Spanning Tree (Unweighted)/Tests/MinimumSpanningTreeTests.swift similarity index 100% rename from Minimum Spanning Tree/Tests/MinimumSpanningTreeTests.swift rename to Minimum Spanning Tree (Unweighted)/Tests/MinimumSpanningTreeTests.swift diff --git a/Minimum Spanning Tree/Tests/Queue.swift b/Minimum Spanning Tree (Unweighted)/Tests/Queue.swift similarity index 100% rename from Minimum Spanning Tree/Tests/Queue.swift rename to Minimum Spanning Tree (Unweighted)/Tests/Queue.swift diff --git a/Minimum Spanning Tree/Tests/Tests.xcodeproj/project.pbxproj b/Minimum Spanning Tree (Unweighted)/Tests/Tests.xcodeproj/project.pbxproj similarity index 100% rename from Minimum Spanning Tree/Tests/Tests.xcodeproj/project.pbxproj rename to Minimum Spanning Tree (Unweighted)/Tests/Tests.xcodeproj/project.pbxproj diff --git a/Minimum Spanning Tree/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Minimum Spanning Tree (Unweighted)/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme similarity index 100% rename from Minimum Spanning Tree/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme rename to Minimum Spanning Tree (Unweighted)/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme diff --git a/README.markdown b/README.markdown index c3e3e43ea..7c776225c 100644 --- a/README.markdown +++ b/README.markdown @@ -169,9 +169,9 @@ Most of the time using just the built-in `Array`, `Dictionary`, and `Set` types - [Graph](Graph/) - [Breadth-First Search (BFS)](Breadth-First Search/) -- [Depth-First Search (DFS)](Depth-First Search/) :construction: -- [Shortest Path](Shortest Path/) -- [Minimum Spanning Tree](Minimum Spanning Tree/) +- [Depth-First Search (DFS)](Depth-First Search/) +- [Shortest Path](Shortest Path %28Unweighted%29/) on an unweighted tree +- [Minimum Spanning Tree](Minimum Spanning Tree %28Unweighted%29/) on an unweighted tree - All Paths ## Puzzles diff --git a/Shortest Path/Images/Graph.graffle b/Shortest Path (Unweighted)/Images/Graph.graffle similarity index 100% rename from Shortest Path/Images/Graph.graffle rename to Shortest Path (Unweighted)/Images/Graph.graffle diff --git a/Shortest Path/Images/Graph.png b/Shortest Path (Unweighted)/Images/Graph.png similarity index 100% rename from Shortest Path/Images/Graph.png rename to Shortest Path (Unweighted)/Images/Graph.png diff --git a/Shortest Path/README.markdown b/Shortest Path (Unweighted)/README.markdown similarity index 98% rename from Shortest Path/README.markdown rename to Shortest Path (Unweighted)/README.markdown index b3fb1692d..64ae52a80 100644 --- a/Shortest Path/README.markdown +++ b/Shortest Path (Unweighted)/README.markdown @@ -1,4 +1,4 @@ -# Shortest Path +# Shortest Path (Unweighted Graph) Goal: find the shortest route to go from one node to another in a graph. @@ -99,8 +99,4 @@ This will output: > **Note:** This version of `breadthFirstSearchShortestPath()` does not actually produce the tree, it only computes the distances. See [minimum spanning tree](../Minimum Spanning Tree/) on how you can convert the graph into a tree by removing edges. -## Weighted graph: Dijkstra's algorithm - -[Coming soon] - *Written by [Chris Pilcher](https://github.com/chris-pilcher) and Matthijs Hollemans* diff --git a/Shortest Path/ShortestPath.playground/Pages/Shortest path example.xcplaygroundpage/Contents.swift b/Shortest Path (Unweighted)/ShortestPath.playground/Pages/Shortest path example.xcplaygroundpage/Contents.swift similarity index 100% rename from Shortest Path/ShortestPath.playground/Pages/Shortest path example.xcplaygroundpage/Contents.swift rename to Shortest Path (Unweighted)/ShortestPath.playground/Pages/Shortest path example.xcplaygroundpage/Contents.swift diff --git a/Shortest Path/ShortestPath.playground/Pages/Shortest path example.xcplaygroundpage/timeline.xctimeline b/Shortest Path (Unweighted)/ShortestPath.playground/Pages/Shortest path example.xcplaygroundpage/timeline.xctimeline similarity index 100% rename from Shortest Path/ShortestPath.playground/Pages/Shortest path example.xcplaygroundpage/timeline.xctimeline rename to Shortest Path (Unweighted)/ShortestPath.playground/Pages/Shortest path example.xcplaygroundpage/timeline.xctimeline diff --git a/Shortest Path/ShortestPath.playground/Sources/Edge.swift b/Shortest Path (Unweighted)/ShortestPath.playground/Sources/Edge.swift similarity index 100% rename from Shortest Path/ShortestPath.playground/Sources/Edge.swift rename to Shortest Path (Unweighted)/ShortestPath.playground/Sources/Edge.swift diff --git a/Shortest Path/ShortestPath.playground/Sources/Graph.swift b/Shortest Path (Unweighted)/ShortestPath.playground/Sources/Graph.swift similarity index 100% rename from Shortest Path/ShortestPath.playground/Sources/Graph.swift rename to Shortest Path (Unweighted)/ShortestPath.playground/Sources/Graph.swift diff --git a/Shortest Path/ShortestPath.playground/Sources/Node.swift b/Shortest Path (Unweighted)/ShortestPath.playground/Sources/Node.swift similarity index 100% rename from Shortest Path/ShortestPath.playground/Sources/Node.swift rename to Shortest Path (Unweighted)/ShortestPath.playground/Sources/Node.swift diff --git a/Shortest Path/ShortestPath.playground/Sources/Queue.swift b/Shortest Path (Unweighted)/ShortestPath.playground/Sources/Queue.swift similarity index 100% rename from Shortest Path/ShortestPath.playground/Sources/Queue.swift rename to Shortest Path (Unweighted)/ShortestPath.playground/Sources/Queue.swift diff --git a/Shortest Path/ShortestPath.playground/contents.xcplayground b/Shortest Path (Unweighted)/ShortestPath.playground/contents.xcplayground similarity index 100% rename from Shortest Path/ShortestPath.playground/contents.xcplayground rename to Shortest Path (Unweighted)/ShortestPath.playground/contents.xcplayground diff --git a/Shortest Path/ShortestPath.swift b/Shortest Path (Unweighted)/ShortestPath.swift similarity index 100% rename from Shortest Path/ShortestPath.swift rename to Shortest Path (Unweighted)/ShortestPath.swift diff --git a/Shortest Path/Tests/Graph.swift b/Shortest Path (Unweighted)/Tests/Graph.swift similarity index 100% rename from Shortest Path/Tests/Graph.swift rename to Shortest Path (Unweighted)/Tests/Graph.swift diff --git a/Shortest Path/Tests/Info.plist b/Shortest Path (Unweighted)/Tests/Info.plist similarity index 100% rename from Shortest Path/Tests/Info.plist rename to Shortest Path (Unweighted)/Tests/Info.plist diff --git a/Shortest Path/Tests/Queue.swift b/Shortest Path (Unweighted)/Tests/Queue.swift similarity index 100% rename from Shortest Path/Tests/Queue.swift rename to Shortest Path (Unweighted)/Tests/Queue.swift diff --git a/Shortest Path/Tests/ShortestPathTests.swift b/Shortest Path (Unweighted)/Tests/ShortestPathTests.swift similarity index 100% rename from Shortest Path/Tests/ShortestPathTests.swift rename to Shortest Path (Unweighted)/Tests/ShortestPathTests.swift diff --git a/Shortest Path/Tests/Tests.xcodeproj/project.pbxproj b/Shortest Path (Unweighted)/Tests/Tests.xcodeproj/project.pbxproj similarity index 100% rename from Shortest Path/Tests/Tests.xcodeproj/project.pbxproj rename to Shortest Path (Unweighted)/Tests/Tests.xcodeproj/project.pbxproj diff --git a/Shortest Path/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Shortest Path (Unweighted)/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme similarity index 100% rename from Shortest Path/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme rename to Shortest Path (Unweighted)/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme From e3c921b85589aa524c244b576cca4f44d0564f8a Mon Sep 17 00:00:00 2001 From: Matthijs Hollemans Date: Sat, 19 Mar 2016 14:57:12 +0100 Subject: [PATCH 0169/1679] Tweaks to K-Means code, text, and images Vector is a struct instead of a class. --- K-Means/Images/k_means_bad1.png | Bin 16294 -> 11976 bytes K-Means/Images/k_means_bad2.png | Bin 15826 -> 11127 bytes K-Means/Images/k_means_good.png | Bin 15983 -> 11887 bytes K-Means/KMeans.swift | 65 ++++---- K-Means/README.markdown | 149 +++++++++++------- K-Means/Tests/KMeansTests.swift | 104 ++++++------ K-Means/Tests/Tests.xcodeproj/project.pbxproj | 2 +- K-Means/Tests/Vector.swift | 94 +++++------ README.markdown | 2 +- 9 files changed, 217 insertions(+), 199 deletions(-) diff --git a/K-Means/Images/k_means_bad1.png b/K-Means/Images/k_means_bad1.png index 55df0e7eedb8e60921a9c84c2ea0718fc77e3e99..07cb656b6e38ad76bb0d7b7a78cc12694c4f7373 100644 GIT binary patch literal 11976 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 literal 16294 zcmeIZXFyX=_bv(uNRci@5QtRi9fVMVAl1-2(t8U?3C&PMDbl-u6sZEzt8}F(AibA> z2uKY`N9x`9d+&SR+;i`T|2^mb?eHNaE3;>2&z^bKv!1mQp`oToL_kY`fq_A!tR%06 zfpIGgc)yB=3%vdie`y5#!?u%!%3@$t#S&gv-~gXNR!Uk>3=BUu42+;x7#L@ODQF!7 z!;2pSW78Z1L*gw42DRI}CQV5U49p1!9Rp7T=u-(RR~KFjYgbDfULO}X;0g>3NgoN| zt&5GP1<1$68RjA3BgOQ$g#_^a#>~eA`rE|QNs7q;ssWO7b+-YD@Cx(tGf5MGKp;tX zYg-8|d4+#n4t$bgviJ0Kli=g?_V(uW7UFevx8oBK7Z>N_7vvKZ;0goX^lM@1>g6fL#B?*zzyJQ3r>BGM{}>78@vqwgZjkTh z8$JPEe!hSA4O}XDW0jC|b#ZgI@$dlpmllxx+Y-(8KgRi|y}G-D4KUN2`TV>6f7U$lLGk9$jAVop_aZ1RpYmV`*`R%L>?&BEl^r6s)*4yl94(m<)wlfudV~&GtI45u}&V~nwko} zSPMHlyY|&T$f1FNqHQG>Y*GjY=KuZ|rF+39<%MDSPhE;1Vr{TPq6*Ej$9|5JgA}w& z+dsIR;gjZVOs#Ru{S+zxRkU4tdH3W|MToKB*VXIS#JtQY2r;pP+6;Je@2qb`h7w+W zI^?a@Ay>JOsrQ(v7&6t7UJgMv%}zQ=GvI|f56PHpatO;R zU%LRM$}2@4N{Pi2gW`OHrhFU%gYPtafM0j>m?lj86iKZ4X;MyeJ~}f7P5rb16N`4E zzz^1;#50Zx*p~QN1WS)Ep?};;X3s)eNHYL;Iq!h7e=44a%D9bL!D!dn$gzq!fp6-h zPd{bgHuqY3R%f(r7LFn1ALk5URkd<-nh^WX>uj)r4_haoDb7PnWiY=*XuaJR+-JV9 zYT?gN#-6>h-dNOpsXU>J@4{gL|;=|+}YK`rS5_^hV8`<>&fyHB~?9n|= zLQvMzyq){7Urd{~H(>5YQ}Ovl34Xp@lu`B}JP|cdZ>tVG|2W9B)uDGep9<1?u@}`W zfFBIU7pCSH?V!D{{{U)oR*z2&%?0OB*$yTE8o!wmZ!M55~hy>Qx(!T}iV7Mm6Y*74V^A?odOjr9 zH8AH;S#^OD9zV4XF#@TEwlZ?mo=Vma!d1z|mhL>18Io>oRblg3-Cq!)S+`K3*$~`fY*D;ak)H#k) zHG1&?dh$g>EZQrv?3_c)usS-jpl3@lRpGi}-#JJ8A?*EtnAfKLyyN-6ESUnGJpnJoH{rK@0EapU1R9n;M@Vy+HNb3RLLfozsLSX;Iy~d z`Hq_7!PL|CL0A?2$lL}S-P5aY z(7oQiN5TQJ^DUXCXKyoL?uqm+_g4xlnl~PZ)rlIKORg4XH}=K^%sLdVH5T*uerkv( z#RJyBavV}KKkl%Y=Q6x)WMi!G7^I8yg(~l)F@|QRP`$aBNf-RukC~MH=BV!eqW)Ao z3>E!VRddYiNzq=hM5^RM?K9MRl!S0?kbQqSx=tn5tu|K6=Ok)ij4DLIs+nD8kf|D~?E0FC`VG;U7&EX<^eYG_{wom$RQOdttlI4N;;+J~dF$JcmGD487+C+y zF9Ud8uP^lieiRe2Hd1W$E}a%&HXcM z^(wTLfW!e-++wj0glH@DBM~D+F8c=u6`I?_OTY-}1Rdde$)b(-g52C~okFsk32m8W z0V_@ZLJlw5ctPq|cZd-$iww}*DM$&hhK$pV8pc5fc1`+s|GdNcpdD(a!P;J=0>~e|Mo?GtdY9E?=E%myR&Jd zFhdw|=E-ByG(M&`F*)ft_)h%n&rl#kT2|nd?~EWh7GCYsocvmOikv8mNoV6ctH8jI5|q_ zy3pp`%y#WiO#tK6$TmK=|Mey<>(}Bl+k4QDKiXUmUN_^@Q87X~a6?P=EA+g)ysXQ% zx1FJx61taXN8pZTqpMLm*Omu#qPf0 z($~`p%v#hg4f<^Fe%(YxyY}NgPa$w8s9jHgB2hc{K1=xGc1>W;+}dJ!bzgPU#jezv zsfpi8LDmXmHogEY-~?%~OPor)rYlIs!oV^*P#0*va<^}{(PiDlrs*&;kxdO@Tf$(t zAAYQdie9k`yk%=Dsa?e2SHk}1tKH+M9w&ZA++dT{X5mx)kUE>86eSPAr1z$;TWgQc z>Nb;*y@_mDSHl~Ae=bvXHBHER`DDOm2NmfRd47zm%2#`7EN?Vp?)MN1EW(0M7W^w< z=Jsh5&y6xmx#xc-1hg)zaFmFAr49dZW>J_dcq5`8$YQ(p`-r*YcK*jkJls6XHPlsq&+bcaVMa-_ZD z%)j}7^%nN1toid^OWjF%5)A`?C!|c|d+&ypEyIJgkD1zH{IySA6i2p2YNYzxKSj~p z7iI6-DkJ~a-|tizpr@Cze{ev@?KG5_o6Cfn>(@+$T3A>hC57-n!?h4ocviJw&9U)P z&PB+v@#G{p7_s7baMR23*4E)F^c#sL<@SN!2g0|28AJlmSPI zmU|f=3y+0rJ!KJ^JaH5vXWXA97E{`_3!53uozKPPvbD4IPY(?FP9bUG_7>yy6Bp`7 z2j7KkiV|#XZTr;zaP#s`YAX7A)4cfE6;X}(fk?uoZ(v};p(u0mnBYJSdsL|-hI~PK z-~{>;4@&hH%KBdxKMEAJDfv>TTX!Pa#3^WW#cafq6Ly(XgBk?V$6)`0uN*^XRm zP&?IQ5q0_crh7fVlWk+V?W^D9_G0D{n9`d1A-j+wyvZm#SNd$9y>0tn7loeCloKkN zOoJ3EXg!jNd8MaoY_E5|+egjj46B{j_e=9i{A3#1cje71EHC=$SNLnir&T%FYisg} z8fzVMs3?D}Y;LNlbf2jB+56{cOj^C_vJ9`Hw!>cmPTMakMybnQ@k4?gDfU&>CZkbhfb5Fu zdjwe>J=m1(T$YHd6TUKi)X|;!ruBOpFP~*?%*!-V{OR55Y1X^Pa>9y-5|8aj!2azu zv$J#aQ_=xYkIC;5&zxS&Xr}tYrL30ySl?*khD9g)#B@jp%VSc2?&F4GZr&;R8H*vX z84E688rH(JtS!*`7#1Xh6=69(XQFvk8>xkcwwTzn934L@GlN>_(Qq6u1n?XDhfFU2 z3C;iI#&O8OlLI*RERTk!=KG_qDaD=G=?2%uZ&KuQnH={(K|yv{;NzX)mqdi)tQCGBYT{C%t&V!j#j`>J16Sc%$Y;djgEIUtwT~R+5~)2OHrFlJ zbOBBZ){=ue4t#t1{XHSuZ@A&`#kZ!dehz&}9Pz=H?oN*#@IY}&=E}X~h|MeY;-*3) zT@hUguiwRfo4G|v$!W>J68$a3k^wex)I7_$=QG1J%vFcaPwM)<2-i@gsc3&QrcYHLgsr5gBC8wq; z;)c_SIuBp`IT)jRJ;_W83RcZ(k)Jzu9*fzh=Pcu%P<1jL&8EH-hlu2J;^jAV;KZ8b zm{2w|2^i@aQbi0=FZv6#YT8R-VUksT&H98G?UzY5ZM-tNf%Xg>B8 zPVe36Y8%y+aEp)MOG-GClaji!_QNr-qzPNvmk|?9fmPPGx{{6cdj7EzOp{$EjE2sA zPoJeNn{Dd*YNRQQh1Z2$pX3tXZT+He@cZOuS?Mx0j$_tmi<~CrOU|)V+Rk_H?jP+g z%3Ol%1+XwFE4Nas1vk|n@BpWIT{`cUk#Wguh#&s+1~R0X2sXSP6?KPx;`{?{zYoBE zuJ8`Iw~H^fFK}P$>*_n`RA>^V;B4UE@Dc^u$<^(eA-z}zDeI6gA3t&v-4m3z`Wge3 z!%vTb@Z&JF{ji{a_M*~R<85kkQE^_;<^|c>?V9Rwf?(mhZ+-W^eR=;^({GKBxam-SBJcEE1g@x|L)g_~XW=1ni(oN`w-I95nc?*;o& zAL~6YvdnhUHhYmvMH55VFN+j0}=A$XMh)E00X=M z2{Z;6O#Y2n$K}J*hu8~<6O%H7s>e7uIJ9E0cLaolQZD++$`K1M4hEF6@)TqB7TXX~ z1KHn6@oIvQ62C@RV>i1`OviJ6$~FbeA8o!{L-AOfo}Y?H{XV|c*FQKWlHI5v*Gxhr z#Ni^>p&bltz5ySn&|iVVX3Tyu!}_u3jw~rH+}6kGGk(s!R`LE72-ImsabW6|sja#x z-YcV=>LxAk)__zh*s~7;h_CDY*{9Wj*OPQPsOit1@ZidhoIm@y#r{I7xZ%T+9#s~c zHLdmPY|C%yHMNeRVe$9x-@jozpRIN18yY&nw(ATfYT9i(XZm9t3J8Bq7yJEQzdzsh zPY8U$77?%@cIB15_9^-G5Pe)pci?Wp?#AHtLNUN-z76=?_M*>kxL%y=8`@)2K&h^Y z2Z}4&=-TYCy}!r#oo9SYzrB1(D%4+1A<9opB@~nN?f&<>QdNf$N>T8>oqVga`+2_F zYre;;2l3sp>ybk3G`%uh%v|n6bx)?awb}gZEZ?e4+C4(-BK_S{j3xJ-DLJ%C7l)JKy)ov6IOU6N6BKP*bFZzk*o znVJJ6)$3M6dO9r%*{mN)#q-9jz~sPVZLq9=QLtKey`QgrzFg8*2y25$!$iBx*tC_k z`g4_Ns(z{yvfS%zuCLu!!8}Brj>f3O>sp0NMdWgEOsYRS3V7-rg`?2w&l#weDr>Pp zQ=Mw1>&w&jERpkOzJLba>&;n56!&7WOv};jp?!8{>@VDvjn-9HmrL!;x8$6PTz0QM zZDt$QAfoLCu15N0N+L)4(p6lLHM+5Ui20g}jQ;S?79NjV7C3`TN=k6I<}j-Es&Tn$ z_m!VK=?>Ucs&#HpHUPG6Nl9@6>d5(>^KOxTacy<2tez-j-lVGevtSk|2x5sD`2?I! zoh>LNSXVUKOyhEY_t^V0{AU~~B*zzX?)lgw1yqt2pVc^gzK4CTif+#0ZhK4KuY335 zNzUoN!0szbHg;2Hed)=`1@Glrn-|vKTE#@XQ=wh18&h$)hmVP!PF?AQ!A_h-Bc3T- zUys<6wE4|ZRfGz7=l5NQa^>#$s?~wEf_kz4AaGKJdH8esF^I(N!?$$=RjIP!jvLcg zRv7`>TxOpxKJ=eNju0xC4);AXpbtL0`>5nZb91)X35g*97BWV>IkPu7vB(O3Cv)*) z6`0bdh0Qzh!>2b)hPhnaSuK3ZnAKbnKRfX1&o`3MX|K>kcJ;{|*$|^-MGr1MgGxw6 z%f8AAUijsYf$1tMDew@uZCifL;%ocPf#lTvvw6&7qZaz^jN^IX0Yfmmd-TZe&{b>9 zjz_KCKoxW1m|14I|3agpxS{yj$ScN;1ZKWH?(5U2@DV^p>SU_?zqKy+IFgRe%sTrzxZlJ;c4j147)JxdA+C2)nPe z@2FTNKm{NH2i)p{k1;TJv9}jq-vo?(n<~44tnApNzn_{<(?tBt;&;FWXDBw2kwYccgd)A4N@Atjo&P z0nr}-@sT_PC}siL*>WOiC&1pxycyr0)VCJhIjNYuq?-zSXL|Xw)Is18i-O#NCb5g0 zii)b|AyTn4|D!ywr0(+7%wR?lpPxjnON^^QE{%;F4PTce)^n@~EVdn+cDsA`&ycq; zITqVqP+jL5q}@y7tl-t}ZBQAnskDPQPE}2S6u^_I^Q~kC4NjS7iwkDHhQ9Himjc&n>!ZVLWXb_LiD zF60K!sts;6-x)tqKWl^QZjYAlo4E9`bG!chW?|r$0QcdIvv+;7_PSO|F6Mqcl2>Qf zlM!2YN>8y|;A44l%r^m$T`U(>JZQ#4+@AghDkt-1*$aSi*br8PTr51;ll^ z?h)pW2Tj<>{5BEEe9qTN>B87~nK{s*_jNgq-|GPP4fS+?Cy;3a^K0(~-y*=NZf+)K zW|nPLw41(u{o1SlZ3F>J(}`-3bK{W3%fUxmLv|Z~CWcB&M9=OG4Gm5~i{|qyvVR|8 zJKc62*&pZ^`E}i6uRf90)JM5`*WrLDBRMrwzac8^1BO7lU-qk!lc>or(S*!ql4ZxQ z#b2Lw7G38=#x_1;r4`z}^p#j1vU_-CFAqfTM%M#J9GchG`Uy19dY|+Dtw7_zvbolB zUgpS=HC}`o1#y~21NS$fSU%rp+S!>UqkZc$&yNw8-%J%ZGo2Rj-Rlsg#=yy~9o6$x zv~YM|-xMfveuWw)rc9!$Wx5@xkF2s%1VW=1Jll9bk5O~W)B>@PJ_7EU+I&F$iLR8L zoTFP*OFN!+;E#@VpIyv|E}+vcB+|JH( z#FBbpO@YUxB)M&c6p#I$}2n}}3HX^@TXlp2i?;FSP zTWKq;LWi)EM=#p>(g576W~N}l{sQ9P&atQ-^5iy*irEz5JQn^P%j_Q$^-lb**+|dC?-YY%4@lMSkw!;ZbffON`P`!G+S`fR!H ztV2<;x2&s4x>qr8UyG6yp}!*_=x{7+YG~vf41(3+oDQa@rYn2%9z&~1qe&aGoU`vb zTG!@FWxGRkl8jlv1&1qgYLogg=PDkqgx|M1n@GlZijcW#GnqheubNMCb>Iw$3Ki9~8=B@8(-xkz9!=*rnK`N;xd)XL6&w9p0F!!& zqYSiNRVUpoYw;b<1!yBj zezsT=?T9u;)V*w-{#gS^!1Z!p;R^BOgq8HrZSuo{W-hp50CXC@a%Wu-v_1hfkU1}y zK>0Up{oV=Vl3|xwlHk_)g0k19(-n1mVL56V6m2vch>d~Qh#^4xn>g3cfe*+uUn*h* z1rY)YrWzNKPm!h+nmi7=2XK|d_fPMk@ft`64iG4|gnVE?L;JWp0NVFz6y8Da;>Qi$ zS&-EsL8CiLp+Nj-{ZJbhtqW2&pbN}hPzie0gGCNtL4rvfx6rx(?jxi#$eVOR4lN0h z@Br{5_xh58(R>c}GoXtOaQNl}w8*rV)ZFdu9h*LMJqn8#=;8;x{1KWf3bqDV*V9lz z8+0y)Neytno8?4bBSFA#vB{+gqIVHQ2xK9AZvPjS`D4grxk+jBPLpZ_5}si@kX`_Q zY|up9CMa$JYlt^cuQNdC=`9#z4xMSEtgc9xy7lVUVd3n_wr$&dTduw_eNBMZGPDk4Z5rm`R-?ndtYnuGl-2_9LCs?{=2Ou zA3sJV#RF)*)ETz*l8|@3Qn0tt0mxn{`2aaDXuE)T1!-RIbC^aS7h_AVG6{4vt3)b( z6-OK=T@;>Pm@V4+*-uhA27vDSYdV~(#Ww02`$c^EhBk)zvs8Iv*?u+U;HxGbM+N&$ zm8j4{E-9yPu4d-K}l)p zR$o}b$_MR^t1{NWsdKu*q1EE zQe^PWCmUDblQ0!DErImT+u1sh_&2>{Vt z_eT$ftBwWiy&zIXwf^8&p*Bp#k^bQwATXqA+!)VbdhXyf-7)<0s3#HTd`8rg;29j+ zJhd6Q=2z$!nLmh{sZp$GJx*6qRTXib<_EMdmf}@ygVq~B+A=#r#LyfS6G|`qsoL>f zWGel5)yXq^Btp;1kQ_UFgauS& zPPXgpqe#O0LIV)qn;gIE(#|663F?{d>#E(&yF=VL(omaw3!5D0>Fv8?lic_2*Xzcd zyjB1bqfq_PxHy0`K0q0yQ_}tuOTFJPrA1F=)|vn(bq?jjj*bkp05ZJaQ29TNZ(xn| zzi~B!w})$4l!<2QT{2R5O-caGHJVmLrMtUZnR6z?($UGO&Ur@AWwusX%I|RaTRbzf z%O0DzyKF}wCUsW2xc26_^4Y~&L6+2Ig|?I9jr!BheHJ+hGb^<^r!N%>%bH1VsNuy5 zruJDT+W51!TAw{isjrj?zTMVG#A#rvTYh`dSA$MfY%@QY-Qmjv3fh)I3T!PC^POkC zg$u2D0_mx#Mm)2+ZCvDeb0@GVAcN!Jd|g#MfsyT$F(Us5c1LrrOLe2UF+X2k$o9L2 zuC6Zj1K>#On<46&ymzw%9}Y>Me@x*v%5f4?F+REeQ6{^GovyAqhYTvm_^Yz8vc*5eLIGMo4n>u5e${iT99S0SWQGHI$6We=RJ_)tE~Zudf~ zUzBfbp|5o_X-s)cJ)_*gs_2jQ`=C^nD8RRp>+ELv=eq`I&o+xSB_93mEckPfx0h~y z)WK67yd-e#9W{wEVvn3^`6wync_k+i*!3s4)QOZc>7jynSuLg1!KfJBR4#eKMqspbKyLC0Qe5haKWcO!~B}t78&$FeYZc4@fSl()!VX7>V!6#?A z|ES~@kjrrBPN9s?6x+#wtn6hB1!`|=oT$8gadEeD`SIeZf+u*hZBwDXh)Z8#sAsRn zw2WgeW^=B?O?`p^h*(QMmOP!h8n|3~P-g(3Kx8qu(tN{UqcvSfPybI-;`wdU2D*nr zH5RFJ9>!{qL3gm`8pNDm)2}SHd|Ijo$;{Q;WdPzWt1wJo!m(sxtgx|KxH z%l7d4C8hT>6J!23%{{|v-BGL=4K~FI+q9jhXU454-yxmmhg`ZH#df1O(g*j7b8^}Y z{x*o&3Vaq)Vhf~80j+s+ZYI-T@i7P+%dSb)9_9DLpxP--O-AaN`!p7gcuzkOTk!7t zeS~`ldvc=gH4=183sj}02bshO1hgQ;oDB}}DQKlh_JwX{z#3fua9?5HZ!6Q<48|ZJ z%Z8&=r5hu23LbE88R9%f_q<5SrMp|q4&=eElL15g-YualQB&omr)It zpqIg~y@y5)?SaylN-{ikw6tWf=UssA#k8trpqmu{ib@y!`z~4!N{WET*_ht?|I_hr zjUR+&ancvVop*W(FtH^mJ`~6Ewi(P;b=GkAKJ3Dpc>tq>{)@H-6W{gO;&GS}+=$&_ z7|WDUUdyCz4Tg&@@=9oAek8O1)Dd{a-1?{Ra6K;p`90ug*Lu>(c;=vSmWWfRPEK(w zuGloOL)h3yfF3mo*!M3Ymz>D+=+&NL%2ETVpWXM`>dCf4DbD=%itGf01+1$1AtcA` zuyFvdEyow7Ka?fMJbG-@q|@iQMlgGjB~_qXnm?F%Sw>fITMk%U!AEx#7BwO<2v`W- zV(2D*wg{34DLG|^M4c@&m^s=M2%87hx@73+vbLU;2*aLT(0(tf0rJFwyQwKE$Yw?F z1%sAy6D}g!mB7{yvi#WO-4Cbk3!bFf$1#n#$HdQRwSHNZyS04xccGYawn zNBZiK1phlxC?_YAf*f*&K_rGbj6pU5dWubsg5qm%iM!L}4CZiN;gRNDHHz_i9oQBt zk~o~eIJi{%hFn{4hsJaP`L=xx<++QRD+nQea|Md-wu6;lALZhH26SG4sDzA&jWY$^ zD1nd(Yq$UCPMZ^phZ3Y<%-QXScgh@hgQ(-#Z8Kq?!YlZx(mDQpFFv3t(M}z z7dQTSX@9lY^bVlChME-2?q+w zfex_(PeaCAn}r>d#w)UG&4Y`e0SC}x*G2ndz3+$V}(zfN7E|vBmCm*@yc2WrSJNZ~MK1MGhd72kn`zubawi{=J}Jk0g2NeM@?JhFo~sCm{}|8Y#Xd`>kE9CCu6QRg4(km%0?mnj*O8}w+>coDZZ5;u*wo;SFt4sGD^`|I* z`b0!l7LG70qigFB!k&E?SNqxGc>~NZV1MP?`##!+h8hVWZ9cX1{J~?F;Sg))#R!Vj z<_qUkyD~?|YR|I`4-vNa;cPN5Gx=d^GLK!F-xn3$_Yw35qEZ8Hy55B*vS)CUe%_ma7MRJ??@B>D*ENB}` zE>sELD3#)DC2Fs+ZP?66B5r-Xb;recV<|frJ{5mQ%M9cY(h1wiSnBNzbx6**azC0l z>p*-Nk~lV4U0d@nJWU&V_5p^3J8q6EiufHqrlcmBMaE^XL!~d zmmk}A(|VYjsH~IiDbLl;e|HkqWQ+3nu{k*-=59ICwFh2lH(j_p9Q>N*l4J@B0zBx( zc1^*T$DfGa%`a$dRDG2UsoDw(JfQo8au@dZznB@4yo7BTngB&B5Q1rrf_k1hZBt+y zRjkXA`0DANt84`{<;h0Ps^hqYM%#5+uVByfM!)Jk-%2~CteHW~&HW1KE)HuRMdC)8 z79pFxn^p5g8+Yq)cEb41np6wY9doBx6V0Zv$uq;~b41|=Q3`_xwH`V#lGSp&$2A{O zI$F&!!*75Ms~21wr3p?R=N+$;Vz=t?{MH>*s;{WdS{DM^Hgnl3N<2w}81;NGF_#H! zoA-i_PFIa!=6+?o4Q?G*yVal?;}XV+A6!qs@@Aw^L5=>TyQZve4S~mE2-56e`9yG= zGloVgj<}-WHQ>^zkWZPl4T5N(OM`iv4i5n2O@tdc7~zd6{Tm%`Tr}tjpg$Gbf7NtB zGk2&04%^f*ff_AvjLQX_yLRpJ2T?Thj{=~ofls8D5Z&i%25;v~`2*UiQF}mZGZ|c; zh*4VdxaON|h3JtSND>Qv@Hy2qK}`m6Ejlx_d40J%y1zOaPBwbaZrU|OfTxn}WmB<bi>AA1cvtaEI@eY2^jOqL~{9Xfn-N7aqqB2lV;-rpO) zjoZa+OADV;B)TIsm)-vs* zY;BZJ=9x{NKj}R335Ag3q|bKmo=c7Q_4j-A^EAlgh6=>qKUqB>pyt1|y)(mtEnxr} zX*H8*{5EO5xF^tLqk3rn;~3>0OhbP`L{EzhpBec)P49EEQ&!RkmEjO#m0iC_8 zaodEx-QowN0orLN;*%!6cko(%>6rr{jdJ?rJ0RsK;(PA$BK=BrOz1PWA9f+Vr?N$x zd~1?2<|;k?VIeAjLUYPxzSm?OVXesYGf`@>ia7xPMxzM}LV220F*O~Cw7r;Ha-1_E z$CAbuzK{5$6CvLX-;ZD5fp=Uasw{USdB7m0F8zW3ywW3YQB@c_^miEjM3EW zjfs_gQE@jrn3Jqs?ZWA1M*G;mzQ?znO@x{Wx`dTx(k`4H{$81QbE6%x{r<*0LSI=Q z9nCsd81R$g+|}5s;vgJCj*SI=RGarod;a}#mXyB&Zn&ty#l@OTMQ&~`OQi-j7M?uz z_FdRqP;!z|`(>GRQFKp2cP;``YP)iM1m7F#wjy3s+WpE$9`pz6IFE|`9q6Ap(`$<= z+W36bw~H*nL~efl82v_uTdp}Za zEdK!uQnwFseuOL%Bwz>=ec*sa5Ur{%sS*n$icO=6vGH_vDu3}>+HZU~=GS6ipl9V< zb1$j~!|_;M_E< zF{HDaa?Q5A0mEO)1!~Q>SpmYrkG+3TFofWh;IE~rt8pVoa&pqt6;L@m1XNfea3&k` zjb!`Epab{S;&t1~4#mfQ-pBxaqURnCv{)SM=C{6>U1|B9m~6cBIKI|QPjVuqBu>OA zN)9a+bBHX$iXg7@H-elCF4vA8|JmCi1sLOlb@_BsMq~<^NBO6C@sS^YBbis7tWZ{=O4B&XRjQPdxbd@(+G8n$C0fk1Nd!e|GHYZd8 zb;N6h?Zou33&>QKvcftI4Gr)0@(v+&Jb~J#&C!BL>X}5vbbOX3B{2y0!Zj!w!Es;o z>1>n8nb0Y`^E`s0p#5^7#y0zT=wU@*FN)^P)t7*ioe@SSF5cshc!Da-H>@XCIzb^O z3BH@MO<06v9Do@=-)&tuY(idrfep5LIvi4~p%@}UaFrve6z)Z1uO^ZJSr|Y z^Lcf(Js&V8FPNDOp5c@xbv*ik-UQI3wFOPT33|^slwy{y;lai zH-1KKR5FJF)wkA)e?(muKDx}+`;Ox5WK>h}J_F?7sN}u!%cuN*>uuf&u}e7C@P(&1 zW1oB>%t9s4f6`8u0;iYRxOPv&cUDtTf9rB6-->XZz2=9rd}#}6s*SJ5Hk@OAS1GE3`KVX8_4hx>`9JtP9@ zJ&ffmB8Y1;UkX4q+mMlpw}7n2sZy{706cd&gAfmiA~WX zyu%iifeqTyQCy@V<==;+=4k?^?}6pG#4_Z6dECou@y5okyHTj$tB-@hT8#=XKcwT& znkxKYdpZ?LSm^qqvpI#)?}KnaOHwxDz?d2jqX?%TBG0=Zjsk0mvTCNP~Gb% zZEGg}v0yb?$;K;T*T{)6wZyZdgYrA>D*nL=&7dvGmiDY(8Rr`iK`>WewIv2>^;4Qm{P@m#h~uUdSrM0xGMCNuPvu*{}F@W?#q~ zwMzK4E_qEo;RD#=5}b1*(_2BERcf1mBk)>(b8;Z>doLRbdsI*Xkh8cIrYceg#TCzf zQlH4APiLvW%q%>PG*hZ*XSn6q;6niT#BSfW-^MQ$jR*uq^;qqN-g4=n!@aSVP-m z9Uh>OpW%-{=FB$2027V;;I#wR-zNe*@@VKyEe*@s(5teSUURTnEuhGY= z0mxPct0fK^F$3@kNDC}}ttCYp&t4CZ_-f=oq9x?;UYP;b)AP4f=q02B1pJSjQ^G0H z(`mnN(rJN=V~^3s%P|Cq-~f3Q7TQgd1_0KjT`MD?hWS4xEzAW7MTSgz=o!HO#zlrG zP(VMrSc*rIDTxIaT6VeKwjAGO$hpV?9Fyz@{$?;xUuY>@MW{-K2mE@>O8BAlIC|a_ oeWqv&g0{Z@#dbh#{OR>ksq3-QfX&R!Pvn)KsL7Wxw}J)g(Sdr z(^^L#qp$Wz!VHb%GbPdRxgqTVZV*UP#?9W;%+>6XopjvoEg)JJPH1OGGhpE?IZ0jFOUOG~ zm}1b5I%u@r-?ONJKx5EO2(&$$ytW7%mzt@WHHuWh{TGLtnuIdS31f;fvrtx$;sDy< zv$i$|<`Z^bKu-8RR2U|5ANVgOA}=NmmE~6u78e%0FCzXouL9c48EJvS{LO3r@4N#4 zl9!|mNPD1X1q(-O7YlQkBO1x}*Ptb={|i~fp-?eFF%c1{FjVNjmgN_(`M;Kh|6j@i z0fd2&mi9j^_1{&1{*a3QP+Z{UAF6MG0`%PxP;6*l;0y?KXGvK>R>y7R$M^*=@Z53J zI`MYgOZ%Gv0oNYNzK(a~CO78dqI!jYEP3UvcAD;SjPB@XJYCj6cJy5qKT4LqyLX{H z{^aB#ew1vYj+_Ax|6qH#HY?M$7G!tn8AXJ-$bRKv?AqEHE2|`{>Ia)~wnl-0f#jsU z*av49A|n+vz<<4SQT_D>CT)5UC`9hB2b7)kNKO}!QPvcybr8r&Ioknxs|hj(v*9wa zOx@a)T3{9ez3t+vr*t0^z3#?gM`6(P#PgNEP%`{rG7bV`LRj5(^u#IQlYwz(ik zZ^`DZrlN(=7}IUT23=dRXEc+B@+Rfi&HFT0dPMQ2r4U?P&a`a#;U1JdBmCSqi;*?( z$)QHDcjD{nunsrduN_RrML{JP!RAb}BRiUz98)SIYJugi*mAsSh49noG(7`9^M#L^ zm^zc=fR1MzY{dvMJw5|JuiJhNL0!sMQMds0R3FioPZyqT^?dc9W7oAX~Kao!qzVRjK2b7{r)0>^n&e!ZOrheez9%m(hkcaE;2=zJb62$dhI!u=#%(Jq`8QyHtb`~I zs;l3Sx9AAWgJn@M+PEvNtu2pC+*>F=8O-~NTIKkdb>Qba^koGj+YhERGsph#S9pr* zy~skg@%$WKrzb}4>eKhMCfK*VYLXvqAA4%|36}h2k^#0e(?R^jktp<_>O1dlIU@yBl$#fpI9L!*Gtq{MrQ>W znE=xbMqyvywo>-P>*ZkczIQ8{o7E-;4W1hl`VNdnhSDgZtIzHmEf)`uK7-R)Lx?FG z`jhpn-tniFIl}R)qpGGSNcEbi5IAkLcXhY$?scogQ?EagEM7t|Cxc*@f}nnqc5w<& zz3rK5UIb4D{czr3`2uRrbQ;8=CKt${)7-;mG#xr#ug326MR(pzDNPWkw*xcO@0xzJd#UXozr?f_qn*NQQN8 zVUXs=+LL>C+dZ2-Ws#pDep)S|Xfv-mej@r(MocxQ_R?nUX82Xf(@E~JW$H^0VF?jE zHG8^m_k9|YmPq<)zID+=I(%>bRzv9(K-~as=ETjPKk;%WYQ>^xROh5X{$_oCmiGG$ zFZp6Z=}Exi$7BpXnAy@K0ZC@#FO>27L`!OKZV1e`rXTjbX6*nr zdVk$xO)kVBi8grB{x#MgsQv3pC)V+Ri^SRY{1;9=)I3jmP3Ag7di5P zrl#dvy{gVVP=;Yvs+hLTsqXaKII*(1gMLDq)Ppqg$yfZ=$BRjQchl2&39QF+$FW7T z+}x#Z2N0vFi_dVI_cUQDp^LFo6!{d304lV6*MTidH)XMMJ z&dPN`8id0w#WnW_*Q)x?vD&04G{JXihxPD>_L&Z1rb!eI9%f=NsU&OZFVAm)xkzE{p zdT4hjIXYq1dvKxgY|5R~-pPR)=nMtf(EBgrRG$HgP3H{(;Cqj{&)F0Rj%arP3A=n| z>d>2~Ek|B0NH+stNK`91pbMz3cbYF5e!RoTO=TMT>eZ`1^5o^^A7{XsN7GI6jH^CL zg)8>s4P$~R$!V9~aP5v(J0!q%s+4uKS_XBWcD=Sy0XjuoV=;1kNys;Df{uLX>7^8u zOS`QZX6?lW3gfsQeQyZs715)AIB~PmE{dMvilIf)yHB(wi<31q3z0o<-_mwvCG_<4 zEDwFbAqm9(?3j$7LXGK+^$iXE8S1P|EazuKC+I#k9UL_{m4C1zrn^5v;8zTd%|<=% zReyITQg!4!9-E-)e$5~S$nwI@e&BWgD;6_V^P(qhJeX2FT2}XHv;;|a^{Tdb%9O$RK8-@xcEXPY>i$a9)$w7U%zC-i zj>UtmBq8Sp&ye#pgIu=I=xb3AVK1omo^9SaxVvvy9ID)#UsCGkvN+T-#x)}oC!>pT z^Bx~Yy<&nDu$;Y{Kefnf%Umkyj4y9=?F&;Lj1~`F)!`l64zonX;Q}(n!mMT5OIGOG z+7L^&RNPc#x|SfuTR0HoSsP7QSFUo{AV{vL)g*Lu?RUTa(uMeb(f1PSr!zm z+%=N-WVEJRv}H1+VwCeMzojnb;v=s0 z%I3b){3B)wjMDJ%aAG~bxcHMvuT2^n3NeM4aK86%^wkUS?0PEW0w$1LpM)T?8{ao} z@&5c7Vz@%RsB(l$QiFXsYGhv z(IXutrSo4QX-WD_ziIAHR{^m@3Nr zW&!DKiz)xp6+rqUnrr+I9UL4IpYsa|=_o5JOPn5UT3@SW7cqLE7_vkEvY#8{8?@Ui%CtQ0PmdA7M0Mp?2;7@#+DC8|ih~NQc^0f`?=(jJMKQ?3n zyXFKSWeqnz2R#|sAx;v@${rmbY$sf$B0>-N7DTQyLi?L}nhENZB0Lft2Cp?Qm`7sk zP1~JSZ{sd#u7`x$DZpB|Zrm1xsK#AJJ&wpE^zjRP(_}1mochFdM*kxjKu&HB&P-$E zH3I+lY}pH{;e6AVmYwlgkm^0T;LEHf-Ur;=+y`3(b*YB6@d|7EWb*d$o!fcts#P*& zk9Y5RC{Y#)+WCeDR#f*07Y41QcQql9BOWAU;a^WKRps@`!`mzLW}VLq&#h<$UqCO*e7J9@%GwEK`NeOjT0tEn_OEYQl{ z+FXwS=QkEuvt-k6)8zkBnhf~KY>lb|Jbxi8DCZ7U)oVtY9|&m$fEfwhWN(k&k@ zbBsBZufrE0(EwxSgK5%JnE??izHnx>j;; zdz>f{QKze+k(`rr?|5$}yhP2n&i|}p2KvLo=0aD-^b633s*l?Ahg5Q1=WUzcPE2l@ z07j#>vZ9iw^^;ni-BM!X325eZe>B6scBL0gQ|3*E_pxfX%9nXzZoDo--KigltDF zJuWEjac5hgB^fh~wRZ)K#h)`dEh~*S+AOy;)~4?sV!?s=&Ps{<{livC z$kD9|%+hypi=tQVsBdIqUzA(}F!S!DP(nnEvS<-7C6aynvOFJrICB=lT`D8KQIdCm zI$6@PJN}LrC|tM3YeC>YP@|p~m+f6YV&B*}Q3L%a+sx2NnQPNTOQlg3pGY~&MqWLJVvI*$~Jki>P5Jm1BgO=3j*%^6N1@2RHpROQRS z0{NAl__TE+Czx|?LWfNiC<=8cQKEf>L#|gtiy!S-5kZ%L!W__5{)HO z3HGO+B@<8q0u-vgDXb%okz`gtze4EW)`jH$)>+rLDhrW6gps|~1j6jhu=j%67-CLO zq9PDhgBa7e&iEP3r}d+i%Bp|WNGTuPJgXrA9#gqqSC9io-CR|UU>ek%&g3M4k9FH} zDi`-HZIxHL)6K`fYj_5pmk)Zpr?s^ZD%Q0q+EUj7eB+#U+MD0_d=$D)e(G_zdAvi? zoSi$ZsPH(Ey$W%U2Yl?ent=4Ou)pkMrt${$rt@}=>A{af(eQn=%|QtEFGpN}O2Ecf zvspM0M0-=tDCMAN@;Z~_bXBnn^c*QMQ1k~C^bMFiO|FgwE;d$zWwyCLjTM*?ov3=E z+++1#6JS>XAhLPUL9q3m9O%5Gldtit_xI?7B-e_Cp1sMEF6$e9SaLQT9Srd8W#=Q9 zH`A_Jx2#SsMO5c4jZU|vi7kyI3x5*)&12COz+&S0or*H9M3)f?~qBn!i36W>s#ScDk- z0}nT3C`y{npfD_&T4)?e^7gv~4Ks_jE%b_;lhntn84~vs?@x+mUIW6_=5Lm|(Z;^V z&S@DLo+2VM-@juHS4(*$B_$Ek4Xsf;{nnNlxV)Il`nm7~iJr2#KtR=AcD|99S;30N zDqAu?i(S}4wU#-&tCwr=pBFr`Sc>q#Oi*ZLZhv}sU_W)Id?)7w!^eofqMMfcI9PO4 z*?l0?E6aA&#Cl1X5PBfMb@8KT-o#Upx;V|Ym{Ko%q8cRGsRa@Cj4DfYVrkmj)M9I3 zlQ=M1bxJ3+i9Xo!|4316zDhZPHE3vM&+bprd?2xVjgi+I#~4x%YL6G!=F!d3@bRf$ za7G|9%UxDKS9>2ycvLt2t$o@P)7MP8T(^&2-ZtJ4WA13Z=XUsGJTy(s#GP8Mfmf<; zlwwUIN7nEc^%Z~#vD`LUGV zst@BJhow?XBb1TR2gXY?ft*GVnzD!w3zqQ&so@z@Bj@>N+@b!o!ehoY{@wW@*wh3dv>>nlSW4HxFVw92`Ol+N&##eL&-hz;F!#RVaJAAD2E&KyRO!`(8+C)AMatDr4|?Ggc3y-lT~^Eos>E zDrmF<9_-UNy(Z=?7aBv#$FR^J67e}mO4m&1hMSErkyLF!#ovF7nQK8byt~82_waMiEdYQdB{`Dm8308y zpceXtTZ#VNVvy>HOPAU-GCtg7q6DBPb2X4dk?Mt3%CpON9s+0y#6nE*ngFblfa+HY z1@!+v0dfYhGJua2bNH0#KF`=6HLMAl857ubjge@v(qGzx3pO+CioFM;#r?Amvh*Dns<{2}77X ztR<78vg|~LNnqwScc~c8cj-8lW$D0^DHyrDM&~wCW09Pf{L{~t@<~GE>6*!`Fdr!nE|Qe znq0SN5=9r!iRNwG?oo4(+?^CIj9-2}e_%l54=Sf3T0g-*gA`+qOD^J!Kp6-Y7S1T? zy{kR1g2>`IBui#(dGhe}*L(TEfjeb^$@b zV$6~jv$U5!-k=zW$NmV@G9sC}NHfoGaH*Z+GplXGdH0c&OCgpqyxez(OD8}DR%f`R7v}90d8TOPfW~3CIx45{N9D7<{FNZg((DmG1d;Iii z{7A9w!v4L7VP9;Dw@!k!5+r)_*|lc&l4Fm7__V6h?BE^MaW&TtoGx^hLQ z(3k&#{AqzeIfO@TFv-1`57nC>jR(bW)4!><{}>ZkqymI$+_3@{AsZVTl6ejF^+Gm% zT*AN~VArvXf<+$NHbCs;F+T|o95nXiO)xa(s%$LK=CKqoNZhARHI9kCQED3#`QaM4 z&_qK&x!V;IT>^=A%(*h%`wC?yykC&9WGG-DSb6#a)3AN3X;p>|DtbO-xT~{EbN0HG z%ApH$$KoDOA|a`>DyI4tPPjqFjzGW*sXxR@dqu2tLjC($?!@|qmfR$8X2>6z&_tJ7_a(pi( zvOHS>#v1RG#Kot<`C;y>f-K@kWV$a{h_&tp`xZE0eorlB*P%HlZgG?y! zHr~AzgGRd2&-R3$_u1c{3s+aaoVbn9jom$;Qgfp``ct>%Jd>PLtHqVgF)TGbP(Iy< z99#sV4-B78P)`l_gSC<=af?)|2$oxlA2_ejq*`vrl17ueXEE$BxOF*pm^fJJI*iY- zMAFeS!6rHO%Ekx2Jw~ciMcFN9$W$fy@F3M zJy40=F{hW7Cu(G3c0>HPZr*fDjB5h&u~m;!&Y!_AB)vm1>K+}GEu`7{UJ)uxqV3l= zxomK^F}Bt~o^TUcg{+W!>IKCG?JXj0DF~1VVkM8!5GTU2My)~jU{cK~6=4E1#AvtD zP%rBB-B_7dS%vWV91q)NIcFz-^mfu_bfQUFZgJ{BXX_qsjrS9K^5|;AEd2nNncV%~ zUFIwQqugrDo${sV z4%Fs`de`?^`DsUYmKzeDfa40d_N45}o94`@mwzzg3pfLTZ1zZvZw;{Z?k><6$1Quu zA2CVM#A6$R(|8RZ>GQ0p);{pwlm^{htCh80(dCw@aZFE2SnWVq-bMmsMHuTtm#pMu z$8>aowLolyykUdOV=XXXGT@{v|801DW=4|Fh(TiMki>CcpU%?dn$2prpJcoSMXwUi z-hKYPO{>bI_lcGA^mMQ5#HA8 zJr)d3(lH#IRg7UF@1^%%iBOVTypf#n3GU<4wV8NIRV+~CSz1M0@2r@xi^akeluY?OyAkt&e;DL`jXfbu@mFai}RIUucILI1GoK|n7q{07Z3085Sx!rw3F6W&>pO; zV&5(e6t5sW*=S9ow2zPmj>`n$2dK4c+*L<5`@WOaFH3@vcdNLtZ{FzoWUa7LQBmpC z_#A7;*&{NycEC$(lhKC@_0z5zwB#=k?z;Ok*T2P&U^)_qyt8^kPjiM2$+@_*-WP1t z3QjaFp<_;W>8-kV9p(1ZcQC;@zK7b_Eh5ZHF6va7OZ?=3=a}79yKS#v(vJ= z{_x$cyEwvf{!iyY6}_W^*{^3q;nH!?moChQlhQi@kHIC$z$9Q9d4-7vj$^Ir>fYtP z2ghGdEm8UUH7v->qdLRtS|12X1OkDMfnk9gj5On`WX2Tk?)ML>COz7f_H{21@;D=f zjTjo#P(`OzJx|-!iR@%fBdE*lFMSZCI2Zmtop}LX8$UuLV9=ALqFNKRvli7!^l%(J zIQw2r+v{Y7s1-MG4*`VTrnwELHeVv&v2QQ(H75R9f=b?PyXFuhjI$#jEz+aQuPDDuqtQ z)iH=X1scbukapqZ)6cxiF;(nA;!UyLpnluw!NxAieL8=q`CbvftA#D$0~Gy4w+E<1 zugD!TD7zn<;I1kWCtiGrZ|Qa1Brsg*J(bQtf(kB7=?`U50k|c6F2jYw{OZHTFEi)* z+4j&v6hq8Zd~Ye6xfstjBb@KMvR4sBZ$ZLa#b%GQuJMKYt1;5VR)nL*%O6*`5_KOv z!j2SKYj2&U$QN*ugLO!@A1N3V!iVgm(MTn9*`d0xf`R%{ zb7q7H5ILlv;zVz<>ZQZf<4KF?)(Y_9?Ku zqAD8B=Oc9lC#pAq?CWpmVU&HBR=Pr(q&7Zm#ZX#buf4Fbk-FHaH6Q!kA;LHcb_s{n z@DBV$cmuYyvRY}mlLXjOD1e|s=FPOiwgXre`MF?!sraT+>%vH#&SFKw5+z=Pe9#N5 zt}Bee=hk-R*B^WG!KvlWPy8OjvLE1x)sS&7`QdfT(HIK0%uiT}6IZIjf&xiJO4at% z?StlboLg*DXFPYKWPD8SA}Pc;aGq_fHNG-HQ5-klwDQ8{``1tTKF0^24NFn4wV@p> z3Afc^yAA!W7NPY{_DYZlU9<-b?+jygvfk0oX6 zL5$E`}_N`GQQO!c0*J9QVjrL zdiX5Rie+i^)l0>XmZ(T|MMl9}jz*?Fa{>;mNVTkGI%c7&x9@V=S^{2p{$>`GnqK5> z4+w93YkOsCd@2V`W9x)GNm$uB?#-`AWlU1_=8K;2fZDWsfX#(8ROwYIAdxwUyCX~k zbRS&u*J)gc(J1Cy9VXAKG)=5q6|!W#=|$o(FjZFWoT5)ZTbfcuSxczoR@|e7!8c|m zj}O?FrX4bNj0G**yO;a3qvGOL+?lUjNx5(KEfZLoEeZXP32eCFM;$KlzE+Ab=gwOL zx~rcGuBY7Zxo6LY>rd!8^2)B4Z15<^p54p2S14!kf`U;>7IwL{Lc6$Ez{Vv92907G zZXNk*Y~?ifdgLiscVr1?cFMJVgO53D*1!9V=Ui))BDEaxfOpcVkGA%;puy7F=@&08 zsO4rt%P{0q0a(lkdV07>X|4_%PieYFOuy;}5*S(SRT&$SG^TH8 z=Au=CjXLN2zy^I`f&QcqocP}U1Iq0y%imcDDBr5MgaMZH-a&V8-{IFl_w8hS9C zXT!}Ta-X6bi1|xu%L7s8#`Il|qV&4S9)cK|Wm1l6Xjo8$xSPe1ookvNseNgJ%%C%G zdzwr>&ti?c#}8`0-D+}Pi@FM$M~?L*wKAGMmA?MrrzIOq`F0ss1zJeEflE}@dtN(Jdtr47R>F8!y zSyx;SCF{HDL}){UZj{e%&lgwKLX)=>N5;!zjRwS=$RJ}IUczx|3$dHb{u!6euo0n| z>n~j80(Md>BI*=wT5sK3k3lP8FEOW`eULiOyF^=ip&7_?06Fo#4Y@COeKKgze+Kr! zq#pS%P7O~1gE_@tchowezpj1!=R;bOxA;Hnh5oMz7tkI17?x?rG6Y?1-EV3c~xXF(dO4!>@w{PSIu;?`4YevkvN&YKVw>=ubo846d(m3!v@Z~4?f{r~^~ literal 15826 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 Lcu+3?B=mm)Oq!bc diff --git a/K-Means/Images/k_means_good.png b/K-Means/Images/k_means_good.png index 01760758b5e5f2735579b8206e95b04c99cd3f20..bb6a996a8bc81cd507d70306fb2ce96c08cf044b 100644 GIT binary patch literal 11887 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 literal 15983 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 { let numCenters: Int - let labels: ArrayaHI-7pa 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 Character { + func char() -> String { return self.character! } - func changeChar(c: Character) -> Void { + func changeChar(c: String) -> Void { self.character = c } - + //For Testing purposes func getParent() -> Node { return parent! @@ -38,8 +38,13 @@ public class Node { } } +public class Trie { + var root: Node = Node(c: "") + +} + print("tests") var x: Node = Node(c: "c") From eb0d9f222517ccc42b655d01862bd573218811ea Mon Sep 17 00:00:00 2001 From: Thukor Date: Wed, 13 Apr 2016 11:53:40 -0400 Subject: [PATCH 0249/1679] Updated Node class to be a bit cleaner and not as redundant. Started on Trie Class. --- Trie/trie | Bin 22390 -> 23362 bytes Trie/trie.swift | 21 ++++++++++++++++++--- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/Trie/trie b/Trie/trie index a9f6e269f8158efc047108ddee0b7535ad80ea52..9459e471d729d947cf78e2e3b199647501c58738 100755 GIT binary patch literal 23362 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 Void { self.isAWord = false } + + func isRoot() -> Bool { + return self.character == "" + } } public class Trie { - var root: Node = Node(c: "") + var root: Node + var nodes: [Node] + init() { + self.root = Node(c: "") + self.nodes = [] + self.nodes.append(self.root) + } + func insertWord(w: String) -> Void { + + } + } print("tests") From 5e0ca14f8126d0c673f9925491c848e7c58144b1 Mon Sep 17 00:00:00 2001 From: barbaramartina Date: Thu, 14 Apr 2016 13:52:28 +0200 Subject: [PATCH 0250/1679] Fix for: Tests target not found (was failing due to renaming operation failure). Adding OSX like target. Using the null identity for signing --- .../Tests/Tests.xcodeproj/project.pbxproj | 134 +++++++++--------- .../xcshareddata/xcschemes/Tests.xcscheme | 6 +- 2 files changed, 71 insertions(+), 69 deletions(-) diff --git a/Bucket Sort/Tests/Tests.xcodeproj/project.pbxproj b/Bucket Sort/Tests/Tests.xcodeproj/project.pbxproj index 8608af8d2..9a42afa4b 100644 --- a/Bucket Sort/Tests/Tests.xcodeproj/project.pbxproj +++ b/Bucket Sort/Tests/Tests.xcodeproj/project.pbxproj @@ -7,19 +7,19 @@ objects = { /* Begin PBXBuildFile section */ - 768206991CBCEA94008B2B5A /* Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 768206971CBCEA94008B2B5A /* Tests.swift */; }; - 7682069F1CBCEC82008B2B5A /* BucketSort.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7682069E1CBCEC82008B2B5A /* BucketSort.swift */; }; + 76E90BEB1CBFB317009E04FE /* Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76E90BEA1CBFB317009E04FE /* Tests.swift */; }; + 76E90BED1CBFB322009E04FE /* BucketSort.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76E90BEC1CBFB322009E04FE /* BucketSort.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ - 768206961CBCEA94008B2B5A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; - 768206971CBCEA94008B2B5A /* Tests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Tests.swift; sourceTree = SOURCE_ROOT; }; - 7682069D1CBCEC47008B2B5A /* Tests.temp_caseinsensitive_rename.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; name = Tests.temp_caseinsensitive_rename.xctest; path = "/Users/barbararodeker/Desktop/Projects/SwiftAlgorithms/swift-algorithm-club/Bucket Sort/Tests/build/Debug-iphoneos/Tests.temp_caseinsensitive_rename.xctest"; sourceTree = ""; }; - 7682069E1CBCEC82008B2B5A /* BucketSort.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = BucketSort.swift; path = ../BucketSort.swift; sourceTree = SOURCE_ROOT; }; + 76E90BEA1CBFB317009E04FE /* Tests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Tests.swift; sourceTree = SOURCE_ROOT; }; + 76E90BEC1CBFB322009E04FE /* BucketSort.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BucketSort.swift; path = ../BucketSort.swift; sourceTree = SOURCE_ROOT; }; + 7B2BBC801C779D720067B71D /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 7B2BBC941C779E7B0067B71D /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ - 76CC7DB31CB41D07003398A8 /* Frameworks */ = { + 7B2BBC7D1C779D720067B71D /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( @@ -29,62 +29,69 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 76CC7D991CB41D03003398A8 = { + 7B2BBC681C779D710067B71D = { isa = PBXGroup; children = ( - 76CC7DB91CB41D07003398A8 /* Tests */, + 7B2BBC831C779D720067B71D /* Tests */, + 7B2BBC721C779D710067B71D /* Products */, ); sourceTree = ""; }; - 76CC7DB91CB41D07003398A8 /* Tests */ = { + 7B2BBC721C779D710067B71D /* Products */ = { isa = PBXGroup; children = ( - 768206971CBCEA94008B2B5A /* Tests.swift */, - 7682069E1CBCEC82008B2B5A /* BucketSort.swift */, - 768206961CBCEA94008B2B5A /* Info.plist */, + 7B2BBC801C779D720067B71D /* Tests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 7B2BBC831C779D720067B71D /* Tests */ = { + isa = PBXGroup; + children = ( + 76E90BEA1CBFB317009E04FE /* Tests.swift */, + 76E90BEC1CBFB322009E04FE /* BucketSort.swift */, + 7B2BBC941C779E7B0067B71D /* Info.plist */, ); name = Tests; - path = TestTests; + path = TestsTests; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ - 76CC7DB51CB41D07003398A8 /* Tests */ = { + 7B2BBC7F1C779D720067B71D /* Tests */ = { isa = PBXNativeTarget; - buildConfigurationList = 76CC7DC21CB41D07003398A8 /* Build configuration list for PBXNativeTarget "Tests" */; + buildConfigurationList = 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */; buildPhases = ( - 76CC7DB21CB41D07003398A8 /* Sources */, - 76CC7DB31CB41D07003398A8 /* Frameworks */, - 76CC7DB41CB41D07003398A8 /* Resources */, + 7B2BBC7C1C779D720067B71D /* Sources */, + 7B2BBC7D1C779D720067B71D /* Frameworks */, + 7B2BBC7E1C779D720067B71D /* Resources */, ); buildRules = ( ); dependencies = ( ); name = Tests; - productName = TestTests; - productReference = 7682069D1CBCEC47008B2B5A /* Tests.temp_caseinsensitive_rename.xctest */; + productName = TestsTests; + productReference = 7B2BBC801C779D720067B71D /* Tests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ - 76CC7D9A1CB41D03003398A8 /* Project object */ = { + 7B2BBC691C779D710067B71D /* Project object */ = { isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0730; - LastUpgradeCheck = 0730; - ORGANIZATIONNAME = "Barbara M. Rodeker"; + LastUpgradeCheck = 0720; + ORGANIZATIONNAME = "Swift Algorithm Club"; TargetAttributes = { - 76CC7DB51CB41D07003398A8 = { - CreatedOnToolsVersion = 7.3; - DevelopmentTeam = 6V43LV5QCY; - TestTargetID = 76CC7DA11CB41D03003398A8; + 7B2BBC7F1C779D720067B71D = { + CreatedOnToolsVersion = 7.2; }; }; }; - buildConfigurationList = 76CC7D9D1CB41D03003398A8 /* Build configuration list for PBXProject "Tests" */; + buildConfigurationList = 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; @@ -92,18 +99,18 @@ en, Base, ); - mainGroup = 76CC7D991CB41D03003398A8; - productRefGroup = 76CC7D991CB41D03003398A8; + mainGroup = 7B2BBC681C779D710067B71D; + productRefGroup = 7B2BBC721C779D710067B71D /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( - 76CC7DB51CB41D07003398A8 /* Tests */, + 7B2BBC7F1C779D720067B71D /* Tests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ - 76CC7DB41CB41D07003398A8 /* Resources */ = { + 7B2BBC7E1C779D720067B71D /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( @@ -113,23 +120,22 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ - 76CC7DB21CB41D07003398A8 /* Sources */ = { + 7B2BBC7C1C779D720067B71D /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 768206991CBCEA94008B2B5A /* Tests.swift in Sources */, - 7682069F1CBCEC82008B2B5A /* BucketSort.swift in Sources */, + 76E90BEB1CBFB317009E04FE /* Tests.swift in Sources */, + 76E90BED1CBFB322009E04FE /* BucketSort.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ - 76CC7DBD1CB41D07003398A8 /* Debug */ = { + 7B2BBC871C779D720067B71D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; @@ -143,7 +149,7 @@ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; @@ -162,19 +168,18 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.3; + MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; + SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; }; name = Debug; }; - 76CC7DBE1CB41D07003398A8 /* Release */ = { + 7B2BBC881C779D720067B71D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; @@ -188,7 +193,7 @@ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; @@ -201,62 +206,59 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.3; + MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - VALIDATE_PRODUCT = YES; + SDKROOT = macosx; }; name = Release; }; - 76CC7DC31CB41D07003398A8 /* Debug */ = { + 7B2BBC8D1C779D720067B71D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - BUNDLE_LOADER = ""; CLANG_ENABLE_MODULES = YES; + COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.algorithmsclub.Tests; - PRODUCT_NAME = Tests.temp_caseinsensitive_rename; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Test.app/Test"; }; name = Debug; }; - 76CC7DC41CB41D07003398A8 /* Release */ = { + 7B2BBC8E1C779D720067B71D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - BUNDLE_LOADER = ""; CLANG_ENABLE_MODULES = YES; + COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.algorithmsclub.Tests; - PRODUCT_NAME = Tests.temp_caseinsensitive_rename; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Test.app/Test"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - 76CC7D9D1CB41D03003398A8 /* Build configuration list for PBXProject "Tests" */ = { + 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( - 76CC7DBD1CB41D07003398A8 /* Debug */, - 76CC7DBE1CB41D07003398A8 /* Release */, + 7B2BBC871C779D720067B71D /* Debug */, + 7B2BBC881C779D720067B71D /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 76CC7DC21CB41D07003398A8 /* Build configuration list for PBXNativeTarget "Tests" */ = { + 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( - 76CC7DC31CB41D07003398A8 /* Debug */, - 76CC7DC41CB41D07003398A8 /* Release */, + 7B2BBC8D1C779D720067B71D /* Debug */, + 7B2BBC8E1C779D720067B71D /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; - rootObject = 76CC7D9A1CB41D03003398A8 /* Project object */; + rootObject = 7B2BBC691C779D710067B71D /* Project object */; } diff --git a/Bucket Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Bucket Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme index 574e1d2ea..74dd9450b 100644 --- a/Bucket Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme +++ b/Bucket Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -1,6 +1,6 @@ From 5873dd5a50fadf0e674143acb3d8bd0b5b8c4d66 Mon Sep 17 00:00:00 2001 From: Barbara Martina Rodeker Date: Thu, 14 Apr 2016 14:11:45 +0200 Subject: [PATCH 0251/1679] Adding time performance & alternatives. --- Bucket Sort/README.markdown | 80 +++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/Bucket Sort/README.markdown b/Bucket Sort/README.markdown index 5c785993e..576937359 100644 --- a/Bucket Sort/README.markdown +++ b/Bucket Sort/README.markdown @@ -12,6 +12,18 @@ A more complete definition could be > Bucket sort, or bin sort, is a sorting algorithm that works by distributing the elements of an array into a number of buckets. Each bucket is then sorted individually, either using a different sorting algorithm, or by recursively applying the bucket sorting algorithm. It is a distribution sort, and is a cousin of radix sort in the most to least significant digit flavour. Bucket sort is a generalization of pigeonhole sort. Bucket sort can be implemented with comparisons and therefore can also be considered a comparison sort algorithm. The computational complexity estimates involve the number of buckets. [1](https://en.wikipedia.org/wiki/Bucket_sort) +## Performance + +Performance for execution time: + +| Case | Performance | +|:-------------: |:---------------:| +| Worst | O(n^2) | +| Best | Omega(n + k) | +| Average | Theta(n + k) | + +Where **n** = #elements and **k** = #buckets + ## Pseudocode @@ -117,5 +129,73 @@ The algorithm is designed to sort integers, so all the elements to be sorted sho func distribute(element: T, inout buckets: [Bucket]) } +### Custom Sorter and Distributor + +The current implementation make use of the following implementations for *Sorter* and *Distributor*. + +*Sorter* + + public struct InsertionSorter: Sorter { + + public init() {} + + public func sort(items: [T]) -> [T] { + var results = items + for i in 0 ..< results.count { + var j = i + while ( j > 0 && results[j-1] > results[j]) { + + let auxiliar = results[j-1] + results[j-1] = results[j] + results[j] = auxiliar + + j -= 1 + } + } + return results + } + } + +*Distributor* + + /* + * An example of a simple distribution function that send every elements to + * the bucket representing the range in which it fits.An + * + * If the range of values to sort is 0..<49 i.e, there could be 5 buckets of capacity = 10 + * So every element will be classified by the ranges: + * + * - 0 ..< 10 + * - 10 ..< 20 + * - 20 ..< 30 + * - 30 ..< 40 + * - 40 ..< 50 + * + * By following the formula: element / capacity = #ofBucket + */ + public struct RangeDistributor: Distributor { + + public init() {} + + public func distribute(element: T, inout buckets: [Bucket]) { + let value = element.toInt() + let bucketCapacity = buckets.first!.capacity + + let bucketIndex = value / bucketCapacity + buckets[bucketIndex].add(element) + } + } + +### Make your own version + +By reusing this code and implementing your own *Sorter* and *Distributor* you can experiment with different versions. + +## Other variations of Bucket Sort + +The following are some of the variation to the General Bucket Sort implemented here: +- [Proxmap Sort](https://en.wikipedia.org/wiki/Bucket_sort#ProxmapSort) +- [Histogram Sort](https://en.wikipedia.org/wiki/Bucket_sort#Histogram_sort) +- [Postman Sort](https://en.wikipedia.org/wiki/Bucket_sort#Postman.27s_sort) +- [Shuffle Sort](https://en.wikipedia.org/wiki/Bucket_sort#Shuffle_sort) From 36962170d25c437f19c3b2070b705b2e32905097 Mon Sep 17 00:00:00 2001 From: Steven Scally Date: Thu, 14 Apr 2016 10:20:06 -0400 Subject: [PATCH 0252/1679] Update README.markdown --- Radix-Tree/README.markdown | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Radix-Tree/README.markdown b/Radix-Tree/README.markdown index 6e4542f6d..de11425d7 100644 --- a/Radix-Tree/README.markdown +++ b/Radix-Tree/README.markdown @@ -1 +1,2 @@ -Radix Tree README +# Radix Tree +--- From e1ac122d9a90ba79dbf3bdf8ee3a0f58c72ce650 Mon Sep 17 00:00:00 2001 From: Steven Scally Date: Thu, 14 Apr 2016 10:25:38 -0400 Subject: [PATCH 0253/1679] Update README.markdown --- Radix-Tree/README.markdown | 1 + 1 file changed, 1 insertion(+) diff --git a/Radix-Tree/README.markdown b/Radix-Tree/README.markdown index de11425d7..99f4502b9 100644 --- a/Radix-Tree/README.markdown +++ b/Radix-Tree/README.markdown @@ -1,2 +1,3 @@ # Radix Tree --- +A radix tree (or radix trie, compact prefix tree) is a space-optimized tree used for constructing associative arrays that are usually expressed as strings. Edges in radix trees store strings. If you started at the root of the tree and traversed down to any node that has no children, concatenating the edges in order of traversal would result in a stored word. An example can be seen (here)[https://en.wikipedia.org/wiki/Radix_tree#/media/File:Patricia_trie.svg] From 5fffd6913884e44f57cfd66d6d55085a34aa50fa Mon Sep 17 00:00:00 2001 From: Steven Scally Date: Thu, 14 Apr 2016 10:26:12 -0400 Subject: [PATCH 0254/1679] Update README.markdown --- Radix-Tree/README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Radix-Tree/README.markdown b/Radix-Tree/README.markdown index 99f4502b9..9ce08dff4 100644 --- a/Radix-Tree/README.markdown +++ b/Radix-Tree/README.markdown @@ -1,3 +1,3 @@ # Radix Tree --- -A radix tree (or radix trie, compact prefix tree) is a space-optimized tree used for constructing associative arrays that are usually expressed as strings. Edges in radix trees store strings. If you started at the root of the tree and traversed down to any node that has no children, concatenating the edges in order of traversal would result in a stored word. An example can be seen (here)[https://en.wikipedia.org/wiki/Radix_tree#/media/File:Patricia_trie.svg] +A radix tree (or radix trie, compact prefix tree) is a space-optimized tree used for constructing associative arrays that are usually expressed as strings. Edges in radix trees store strings. If you started at the root of the tree and traversed down to any node that has no children, concatenating the edges in order of traversal would result in a stored word. An example can be seen [here](https://en.wikipedia.org/wiki/Radix_tree#/media/File:Patricia_trie.svg). From adb8a6b4262a59ec76f0534d7974b298ca77ddbd Mon Sep 17 00:00:00 2001 From: Steven Scally Date: Thu, 14 Apr 2016 10:27:15 -0400 Subject: [PATCH 0255/1679] Update README.markdown --- Radix-Tree/README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Radix-Tree/README.markdown b/Radix-Tree/README.markdown index 9ce08dff4..a52c8f8ab 100644 --- a/Radix-Tree/README.markdown +++ b/Radix-Tree/README.markdown @@ -1,3 +1,3 @@ # Radix Tree ---- +-- A radix tree (or radix trie, compact prefix tree) is a space-optimized tree used for constructing associative arrays that are usually expressed as strings. Edges in radix trees store strings. If you started at the root of the tree and traversed down to any node that has no children, concatenating the edges in order of traversal would result in a stored word. An example can be seen [here](https://en.wikipedia.org/wiki/Radix_tree#/media/File:Patricia_trie.svg). From 2b28ee4ba2cfaff1dc127eee6c969edb32ec0467 Mon Sep 17 00:00:00 2001 From: Steven Scally Date: Thu, 14 Apr 2016 10:27:24 -0400 Subject: [PATCH 0256/1679] Update README.markdown --- Radix-Tree/README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Radix-Tree/README.markdown b/Radix-Tree/README.markdown index a52c8f8ab..e3de0a161 100644 --- a/Radix-Tree/README.markdown +++ b/Radix-Tree/README.markdown @@ -1,3 +1,3 @@ # Radix Tree --- +- A radix tree (or radix trie, compact prefix tree) is a space-optimized tree used for constructing associative arrays that are usually expressed as strings. Edges in radix trees store strings. If you started at the root of the tree and traversed down to any node that has no children, concatenating the edges in order of traversal would result in a stored word. An example can be seen [here](https://en.wikipedia.org/wiki/Radix_tree#/media/File:Patricia_trie.svg). From 180ce9e06161ddecc1dc5e860b67f2ada249b645 Mon Sep 17 00:00:00 2001 From: Steven Scally Date: Thu, 14 Apr 2016 10:27:31 -0400 Subject: [PATCH 0257/1679] Update README.markdown --- Radix-Tree/README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Radix-Tree/README.markdown b/Radix-Tree/README.markdown index e3de0a161..7f803e215 100644 --- a/Radix-Tree/README.markdown +++ b/Radix-Tree/README.markdown @@ -1,3 +1,3 @@ # Radix Tree -- + A radix tree (or radix trie, compact prefix tree) is a space-optimized tree used for constructing associative arrays that are usually expressed as strings. Edges in radix trees store strings. If you started at the root of the tree and traversed down to any node that has no children, concatenating the edges in order of traversal would result in a stored word. An example can be seen [here](https://en.wikipedia.org/wiki/Radix_tree#/media/File:Patricia_trie.svg). From 831b27ad870da93d1789716701d5c5d7d64ede7e Mon Sep 17 00:00:00 2001 From: Steven Scally Date: Thu, 14 Apr 2016 10:31:34 -0400 Subject: [PATCH 0258/1679] Update README.markdown --- Radix-Tree/README.markdown | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Radix-Tree/README.markdown b/Radix-Tree/README.markdown index 7f803e215..0d9a10125 100644 --- a/Radix-Tree/README.markdown +++ b/Radix-Tree/README.markdown @@ -1,3 +1,7 @@ # Radix Tree A radix tree (or radix trie, compact prefix tree) is a space-optimized tree used for constructing associative arrays that are usually expressed as strings. Edges in radix trees store strings. If you started at the root of the tree and traversed down to any node that has no children, concatenating the edges in order of traversal would result in a stored word. An example can be seen [here](https://en.wikipedia.org/wiki/Radix_tree#/media/File:Patricia_trie.svg). + +## Operations + +Typical operations on a radix tree include lookup, insertion, deletion, find predecessor, find successor, and find all strings with common prefix. The running time of lookup, insertion, and deletion is O(k) where k is the length of the key. This is different from most trees because these operations usually run in O(logn) time where n is the number of nodes in the tree. From 3b30576efb6e49be0ca9c90894387f7056a87fba Mon Sep 17 00:00:00 2001 From: Steven Scally Date: Thu, 14 Apr 2016 12:02:59 -0400 Subject: [PATCH 0259/1679] Update README.markdown --- Radix-Tree/README.markdown | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Radix-Tree/README.markdown b/Radix-Tree/README.markdown index 0d9a10125..733f5ec0c 100644 --- a/Radix-Tree/README.markdown +++ b/Radix-Tree/README.markdown @@ -5,3 +5,7 @@ A radix tree (or radix trie, compact prefix tree) is a space-optimized tree used ## Operations Typical operations on a radix tree include lookup, insertion, deletion, find predecessor, find successor, and find all strings with common prefix. The running time of lookup, insertion, and deletion is O(k) where k is the length of the key. This is different from most trees because these operations usually run in O(logn) time where n is the number of nodes in the tree. + +## See Also + +[Radix Tree - Wikipedia](https://en.wikipedia.org/wiki/Radix_tree) From da404ce3e973d6a8e41e1ae9b40f1ee685a03b95 Mon Sep 17 00:00:00 2001 From: Steven Scally Date: Thu, 14 Apr 2016 12:11:23 -0400 Subject: [PATCH 0260/1679] Update README.markdown --- Radix-Tree/README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Radix-Tree/README.markdown b/Radix-Tree/README.markdown index 733f5ec0c..1b41d1a93 100644 --- a/Radix-Tree/README.markdown +++ b/Radix-Tree/README.markdown @@ -1,6 +1,6 @@ # Radix Tree -A radix tree (or radix trie, compact prefix tree) is a space-optimized tree used for constructing associative arrays that are usually expressed as strings. Edges in radix trees store strings. If you started at the root of the tree and traversed down to any node that has no children, concatenating the edges in order of traversal would result in a stored word. An example can be seen [here](https://en.wikipedia.org/wiki/Radix_tree#/media/File:Patricia_trie.svg). +A radix tree is a tree where a node can have any number of children. Each edge leading from a node to a child has a label (usually a string). A radix tree is often used to store strings or IP addresses and by traversing from the root to any leaf in the tree, (by concatenating all the labels of edges along the way) you can find any string. This is a radix tree: ## Operations From 8a6f269288593b24d5e726e557c7f487595aeb3c Mon Sep 17 00:00:00 2001 From: Steven Scally Date: Thu, 14 Apr 2016 12:11:43 -0400 Subject: [PATCH 0261/1679] Create test.md --- Radix-Tree/Images/test.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 Radix-Tree/Images/test.md diff --git a/Radix-Tree/Images/test.md b/Radix-Tree/Images/test.md new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/Radix-Tree/Images/test.md @@ -0,0 +1 @@ + From 49543eac600925e4a1a34a0aeb11225d82d6d10b Mon Sep 17 00:00:00 2001 From: Steven Scally Date: Thu, 14 Apr 2016 12:12:38 -0400 Subject: [PATCH 0262/1679] Uploaded radixtree.png --- Radix-Tree/Images/radixtree.png | Bin 0 -> 24072 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 Radix-Tree/Images/radixtree.png diff --git a/Radix-Tree/Images/radixtree.png b/Radix-Tree/Images/radixtree.png new file mode 100644 index 0000000000000000000000000000000000000000..7c78dd8c1fb27b6ba1c157bc62f39cad39499731 GIT binary patch literal 24072 zcmZsj1yEFB+xM4l>COeD1!<7(?rv$2?k?$GN>WNvrBhmRK}tZnySwu{JkPu{-^}}t zgBzSZd+xgK>;L;-hiFx084OesR1gS+Atx)T4g$eIfamwfh`|4erPz|d1EQINj3nsg z^sFLM7XWXnb6?n*^)Vp5Dd?!18TZ@JILNG(<dC3qxsabkFt9tPRC8V5AG3_oKkGleo z(}d*?XzS!R)n1z>iGF(;_yMvT9~$ye4uAC!wA4 z%&YgZ&V#HKYrz{Fo&gS(i!I)jh96uJ(&*hJyixu

_np+ZzqrorX1`yQRh>ZS#$TKPo; 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 literal 0 HcmV?d00001 From e9f4bf40d83cff0302a5258343ca96232aaa0b4e Mon Sep 17 00:00:00 2001 From: Steven Scally Date: Thu, 14 Apr 2016 12:12:53 -0400 Subject: [PATCH 0263/1679] Delete test.md --- Radix-Tree/Images/test.md | 1 - 1 file changed, 1 deletion(-) delete mode 100644 Radix-Tree/Images/test.md diff --git a/Radix-Tree/Images/test.md b/Radix-Tree/Images/test.md deleted file mode 100644 index 8b1378917..000000000 --- a/Radix-Tree/Images/test.md +++ /dev/null @@ -1 +0,0 @@ - From be4e1a9180aa6c1a6be294249550a1b4589ea584 Mon Sep 17 00:00:00 2001 From: Steven Scally Date: Thu, 14 Apr 2016 12:13:56 -0400 Subject: [PATCH 0264/1679] Update README.markdown --- Radix-Tree/README.markdown | 1 + 1 file changed, 1 insertion(+) diff --git a/Radix-Tree/README.markdown b/Radix-Tree/README.markdown index 1b41d1a93..db6dfe7b8 100644 --- a/Radix-Tree/README.markdown +++ b/Radix-Tree/README.markdown @@ -1,6 +1,7 @@ # Radix Tree A radix tree is a tree where a node can have any number of children. Each edge leading from a node to a child has a label (usually a string). A radix tree is often used to store strings or IP addresses and by traversing from the root to any leaf in the tree, (by concatenating all the labels of edges along the way) you can find any string. This is a radix tree: +![](/Images/radixtree.png) ## Operations From 2e16592b4c3cf2f183bf293cad6fd4183e43aba4 Mon Sep 17 00:00:00 2001 From: Steven Scally Date: Thu, 14 Apr 2016 12:14:33 -0400 Subject: [PATCH 0265/1679] Update README.markdown --- Radix-Tree/README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Radix-Tree/README.markdown b/Radix-Tree/README.markdown index db6dfe7b8..eecbeb6f3 100644 --- a/Radix-Tree/README.markdown +++ b/Radix-Tree/README.markdown @@ -1,7 +1,7 @@ # Radix Tree A radix tree is a tree where a node can have any number of children. Each edge leading from a node to a child has a label (usually a string). A radix tree is often used to store strings or IP addresses and by traversing from the root to any leaf in the tree, (by concatenating all the labels of edges along the way) you can find any string. This is a radix tree: -![](/Images/radixtree.png) +![](/Radix-Tree/Images/radixtree.png) ## Operations From d74c1aa5f440424af52160d69d9744be42da15bb Mon Sep 17 00:00:00 2001 From: Luisa Herrmann Date: Fri, 15 Apr 2016 16:49:25 +0200 Subject: [PATCH 0266/1679] Add minimum edit distance for strings --- .../MinimumEditDistance.swift | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 Minimum Edit Distance/MinimumEditDistance.swift diff --git a/Minimum Edit Distance/MinimumEditDistance.swift b/Minimum Edit Distance/MinimumEditDistance.swift new file mode 100644 index 000000000..b03c76f8c --- /dev/null +++ b/Minimum Edit Distance/MinimumEditDistance.swift @@ -0,0 +1,27 @@ +extension String { + + public func minimumEditDistance(other: String) -> Int { + let m = self.characters.count + let n = other.characters.count + var matrix = [[Int]](count: m+1, repeatedValue: [Int](count: n+1, repeatedValue: 0)) + + for index in 1...m { + matrix[index][0]=index + } + for index in 1...n { + matrix[0][index]=index + } + + for (i, selfChar) in self.characters.enumerate() { + for (j, otherChar) in other.characters.enumerate() { + if otherChar == selfChar { + matrix[i+1][j+1] = matrix[i][j] + } else { + matrix[i+1][j+1] = min(matrix[i][j]+1, matrix[i+1][j]+1, matrix[i][j+1]+1) + } + + } + } + return matrix[m][n] + } +} From f3da019e1f12018c5a0eeb3e36733601ab60ee3a Mon Sep 17 00:00:00 2001 From: Luisa Herrmann Date: Sun, 17 Apr 2016 16:11:30 +0200 Subject: [PATCH 0267/1679] added README.markdown and some comments in the code --- .../MinimumEditDistance.swift | 7 ++ Minimum Edit Distance/README.markdown | 65 +++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 Minimum Edit Distance/README.markdown diff --git a/Minimum Edit Distance/MinimumEditDistance.swift b/Minimum Edit Distance/MinimumEditDistance.swift index b03c76f8c..8008e03ba 100644 --- a/Minimum Edit Distance/MinimumEditDistance.swift +++ b/Minimum Edit Distance/MinimumEditDistance.swift @@ -5,18 +5,25 @@ extension String { let n = other.characters.count var matrix = [[Int]](count: m+1, repeatedValue: [Int](count: n+1, repeatedValue: 0)) + + // initialize matrix for index in 1...m { + // the distance of any first string to an empty second string matrix[index][0]=index } for index in 1...n { + // the distance of any second string to an empty first string matrix[0][index]=index } + // compute Levenshtein distance for (i, selfChar) in self.characters.enumerate() { for (j, otherChar) in other.characters.enumerate() { if otherChar == selfChar { + // substitution of equal symbols with cost 0 matrix[i+1][j+1] = matrix[i][j] } else { + // minimum of the cost of insertion, deletion, or substitution added to the already computed costs in the corresponding cells matrix[i+1][j+1] = min(matrix[i][j]+1, matrix[i+1][j]+1, matrix[i][j+1]+1) } diff --git a/Minimum Edit Distance/README.markdown b/Minimum Edit Distance/README.markdown new file mode 100644 index 000000000..d72e0dbda --- /dev/null +++ b/Minimum Edit Distance/README.markdown @@ -0,0 +1,65 @@ +# Minimum Edit Distance + +The minimum edit distance is a possibility to measure the similarity of two strings *w* and *u* by counting costs of operations which are necessary to transform *w* into *u* (or vice versa). + +### Algorithm using Levenshtein distance + +A common distance measure is given by the *Levenshtein distance*, which allows the following three transformation operations: + +* **Inseration** (*ε→x*) of a single symbol *x* with **cost 1**, +* **Deletion** (*x→ε*) of a single symbol *x* with **cost 1**, and +* **Substitution** (*x→y*) of two single symbols *x, y* with **cost 1** if *x≠y* and with **cost 0** otherwise. + +When transforming a string by a sequence of operations, the costs of the single operations are added to obtain the (minimal) edit distance. For example, the string *Door* can be transformed by the operations *o→l*, *r→l*, *ε→s* to the string *Dolls*, which results in a minimum edit distance of 3. + +To avoid exponential time complexity, the minimum edit distance of two strings in the usual is computed using *dynamic programming*. For this in a matrix + +```swift +var matrix = [[Int]](count: m+1, repeatedValue: [Int](count: n+1, repeatedValue: 0)) +``` + +already computed minimal edit distances of prefixes of *w* and *u* (of length *m* and *n*, respectively) are used to fill the matrix. In a first step the matrix is initialized by filling the first row and the first column as follows: + +```swift +// initialize matrix +for index in 1...m { + // the distance of any prefix of the first string to an empty second string + matrix[index][0]=index +} +for index in 1...n { + // the distance of any prefix of the second string to an empty first string + matrix[0][index]=index +} +``` +Then in each cell the minimum of the cost of insertion, deletion, or substitution added to the already computed costs in the corresponding cells is chosen. In this way the matrix is filled iteratively: + +```swift +// compute Levenshtein distance +for (i, selfChar) in self.characters.enumerate() { + for (j, otherChar) in other.characters.enumerate() { + if otherChar == selfChar { + // substitution of equal symbols with cost 0 + matrix[i+1][j+1] = matrix[i][j] + } else { + // minimum of the cost of insertion, deletion, or substitution added + // to the already computed costs in the corresponing cells + matrix[i+1][j+1] = min(matrix[i][j]+1, matrix[i+1][j]+1, matrix[i][j+1]+1) + } + + } +} +``` + +After applying this algorithm, the minimal edit distance can be read from the rightmost bottom cell and is returned. + +```swift +return matrix[m][n] +``` + +This algorithm has a time complexity of Θ(*mn*). + +### Other distance measures + +**todo** + +*Written for Swift Algorithm Club by Luisa Herrmann* \ No newline at end of file From 11d7e8a46cbd3b9037593506ad7e55172eff7479 Mon Sep 17 00:00:00 2001 From: Steven Scally Date: Thu, 21 Apr 2016 18:17:26 -0400 Subject: [PATCH 0268/1679] Testing two approaches to a RadixTree --- Radix-Tree/EdgeTree.swift | 149 +++++++++++++++++++++++++++++++++++++ Radix-Tree/RadixTree.swift | 123 ++++++++++++++++++++++++++++++ 2 files changed, 272 insertions(+) create mode 100644 Radix-Tree/EdgeTree.swift create mode 100644 Radix-Tree/RadixTree.swift diff --git a/Radix-Tree/EdgeTree.swift b/Radix-Tree/EdgeTree.swift new file mode 100644 index 000000000..06a8b0b7a --- /dev/null +++ b/Radix-Tree/EdgeTree.swift @@ -0,0 +1,149 @@ +class Root { + + var children: [Edge] + + init() { + children = [Edge]() + } + +} + +class Edge: Root { + + var parent: Edge? + var label: String + + init(_ label: String) { + self.label = label + super.init() + } + +} + +class EdgeTree { + + var root: Root + + init() { + root = Root() + } + + func insert(_ str: String) -> Bool { + + //Account for a blank input + if str == "" { + return true + } + + //Account for an empty tree + if root.children.count == 0 { + root.children.append( Edge(str) ) + return true + } + + var searchStr = str + var currEdge = root + + while (true) { + + var i = 0 + + for e in currEdge.children { + + //Get the shared + var shared = sharedPrefix(searchStr, e.label) + var index = shared.startIndex + + //The search string is equal to the shared string + //so the string already exists in the tree + if searchStr == shared { + return false + } + + //The child's label is a prefix of the search string + else if e.label.hasPrefix(shared) { + + for _ in 1...shared.characters.count { + index = index.successor() + } + + //Substring the search string so that the prefix is removed + searchStr = searchStr.substringFromIndex(index) + + //Set currNode to e + currEdge = e + break + + } + + + //The child's label and the search string share a prefix + else if shared.characters.count > 0 { + + //Cut the prefix off from both the search string and label + var labelIndex = e.label.characters.startIndex + + for _ in 1...shared.characters.count { + index = index.successor() + labelIndex = labelIndex.successor() + } + + searchStr = searchStr.substringFromIndex(index) + e.label = e.label.substringFromIndex(labelIndex) + + //Create a new edge whose label is the shared string + //its parent is currEdge.parent and add a child with + //label = searchStr + //Also add it to the parent's children + let newEdge = Edge(shared) + newEdge.children.append( Edge(searchStr) ) + newEdge.parent = e.parent + currEdge.children.append(newEdge) + + //Remove this edge from the parent's child list + currEdge.children.remove(at: i) + + //Set this edge's parent to the prefix node + e.parent = newEdge.parent + return true + + } + + //They don't share a prefix (go to next child) + i += 1 + + } + + //No children share a prefix, so create a new child + currEdge.children.append( Edge(searchStr) ) + return true + } + } +} + +//Returns the prefix that is shared between the two input strings +//i.e. sharedPrefix("court", "coral") -> "co" +func sharedPrefix(_ str1: String, _ str2: String) -> String { + + var temp = "" + + var c1 = str1.characters.startIndex + var c2 = str2.characters.startIndex + + for _ in 0...min(str1.characters.count-1, str2.characters.count-1) { + + if str1[c1] == str2[c2] { + temp.append( str1[c1] ) + c1 = c1.successor() + c2 = c2.successor() + } + + else { + return temp + } + + } + + return temp + +} \ No newline at end of file diff --git a/Radix-Tree/RadixTree.swift b/Radix-Tree/RadixTree.swift new file mode 100644 index 000000000..27dfbd8dc --- /dev/null +++ b/Radix-Tree/RadixTree.swift @@ -0,0 +1,123 @@ +import Foundation + + +public class RadixNode { + public var parent: RadixNode? + public var children = [(childNode: RadixNode, childEdgeLabel: String)]() + + public init() { + + } + + public init(value: String) { + self.children.append((childNode: RadixNode(), childEdgeLabel: value)) + } + + public func addChild(_ node: RadixNode, _ label: String) { + children.append((node, label)) + node.parent = self + } + + public func getChildren() -> [(childNode: RadixNode, childEdgeLabel: String)] { + return children + } + + public func getChildAt(i: Int) -> (RadixNode, String)? { + if i >= children.count { + return nil + } + return children[i] + } + + public func getParent() -> RadixNode? { + return parent + } + + public func isLeaf() -> Bool { + return children.count == 0 + } +} + +public class RadixTree { + public var root: RadixNode + + //Construct an "empty" RadixTree with a single node + public init() { + root = RadixNode() + } + + public init(value: String) { + self.root = RadixNode(value: value) + } + + public func find(str: String, node: RadixNode?) -> Bool { + var currNode: RadixNode + var search = str + if (node == nil) { + currNode = self.root + } + else { + currNode = node! + } + if (str == "") { + return true + } + else { + for n in 0...currNode.children.count-1 { + if (str.hasPrefix(currNode.children[n].childEdgeLabel)) { + let elementsFound = currNode.children[n].childEdgeLabel.characters.count + search = search.substringFromIndex(search.startIndex.advanced(by: elementsFound)) + currNode = currNode.children[n].childNode + find(str: search, node: currNode) + } + } + } + return false + } + + public func insert(str: String, node: RadixNode?) -> Bool { + var search = str + var currNode: RadixNode + if (node == nil) { + currNode = self.root + } + else { + currNode = node! + } + //Case 0: str == "" (it is already in the tree) + // -> return false + if (str == "") { + return false + } + else { + for c in currNode.children { + + //Temp is the string of the prefix that the label and the + // search string have in common. + //let temp = currNode.children[c].childEdgeLabel.sharePrefix(str) + + //Case 3: currNode has a child that shares some prefix with str + // -> little bit more complicated + //if temp == 0 { + + //Remove the shared characters from both the search string and + // label + //currNode.children[c].childEdgeLabel.substringFromIndex(temp.count) + //str.substringFromIndex(temp.count) + + + //} + + + //Case 1: currNode has no children that share a prefix with str + // -> create a new child for currNode + + + //Case 2: currNode has a child whose label is a prefix of str + // -> recurse down + + } + } + return false + } +} \ No newline at end of file From 27d92a6848e7aa06daeea7d18e6ef488a8c0856e Mon Sep 17 00:00:00 2001 From: Keita Ito Date: Thu, 21 Apr 2016 17:59:29 -0700 Subject: [PATCH 0269/1679] Fix code snippet --- Graph/README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Graph/README.markdown b/Graph/README.markdown index b76fae732..8e88f80eb 100644 --- a/Graph/README.markdown +++ b/Graph/README.markdown @@ -234,7 +234,7 @@ public mutating func connect(sourceVertex: Vertex, to destinationVertex: Vert adjacencyMatrix[sourceVertex.index][destinationVertex.index] = weight } -public func weightFrom(sourceVertex: GraphVertex, toDestinationVertex: GraphVertex) -> Double? { +public func weightFrom(sourceVertex: Vertex, toDestinationVertex: Vertex) -> Double? { return adjacencyMatrix[sourceVertex.index][toDestinationVertex.index] } ``` From 6894b2e7a0d09f97dc3a6e2636e52a16ed58d15e Mon Sep 17 00:00:00 2001 From: Keita Ito Date: Thu, 21 Apr 2016 18:04:19 -0700 Subject: [PATCH 0270/1679] Fix typo --- Boyer-Moore/README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Boyer-Moore/README.markdown b/Boyer-Moore/README.markdown index a8f2c9f7a..ad1d3bc73 100644 --- a/Boyer-Moore/README.markdown +++ b/Boyer-Moore/README.markdown @@ -143,7 +143,7 @@ See also: [a detailed analysis](http://www.inf.fh-flensburg.de/lang/algorithmen/ A variation on the above algorithm is the [Boyer-Moore-Horspool algorithm](https://en.wikipedia.org/wiki/Boyer%E2%80%93Moore%E2%80%93Horspool_algorithm). -Like the regular Boyer-Moore algorithm, it uses the `skipTable` to skip ahead a number of characters. The difference is in how we check partial matches. In the above version, it a partial match is found but it's not a complete match, we skip ahead by just one character. In this revised version, we also use the skip table in that situation. +Like the regular Boyer-Moore algorithm, it uses the `skipTable` to skip ahead a number of characters. The difference is in how we check partial matches. In the above version, if a partial match is found but it's not a complete match, we skip ahead by just one character. In this revised version, we also use the skip table in that situation. Here's an implementation of the Boyer-Moore-Horspool algorithm: From d18b61132b81ac02ff23c39a2e11648b16a17dd5 Mon Sep 17 00:00:00 2001 From: Keita Ito Date: Thu, 21 Apr 2016 18:23:21 -0700 Subject: [PATCH 0271/1679] Fix code snippet by adding forced unwrapping --- Linked List/README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Linked List/README.markdown b/Linked List/README.markdown index 24360e2b5..e78735350 100644 --- a/Linked List/README.markdown +++ b/Linked List/README.markdown @@ -408,7 +408,7 @@ If you don't have a reference to the node, you can use `removeLast()` or `remove public func removeAtIndex(index: Int) -> T { let node = nodeAtIndex(index) assert(node != nil) - return removeNode(node) + return removeNode(node!) } ``` From 2eb7e9f144b0b099be48149da4524925453ee4e2 Mon Sep 17 00:00:00 2001 From: Jayson Tung Date: Sat, 23 Apr 2016 15:27:13 -0400 Subject: [PATCH 0272/1679] Begin converting BinarySearchTree.swift to ThreadedBinaryTree.swift --- Threaded Binary Tree/ThreadedBinaryTree.swift | 380 ++++++++++++++++++ 1 file changed, 380 insertions(+) create mode 100644 Threaded Binary Tree/ThreadedBinaryTree.swift diff --git a/Threaded Binary Tree/ThreadedBinaryTree.swift b/Threaded Binary Tree/ThreadedBinaryTree.swift new file mode 100644 index 000000000..f83dd4592 --- /dev/null +++ b/Threaded Binary Tree/ThreadedBinaryTree.swift @@ -0,0 +1,380 @@ +/* + A threaded binary tree based on this club's binary search tree implementation. + + Each node stores a value and two children. The left child contains a smaller + value; the right a larger (or equal) value. + + Any nodes that lack either a left or right child instead keep track of their + in-order predecessor and/or successor. + + This tree allows duplicate elements. + + This tree does not automatically balance itself. To make sure it is balanced, + you should insert new values in randomized order, not in sorted order. +*/ +public class ThreadedBinaryTree { + private(set) public var value: T + private(set) public var parent: ThreadedBinaryTree? + private(set) public var left: ThreadedBinaryTree? + private(set) public var right: ThreadedBinaryTree? + + public init(value: T) { + self.value = value + } + + public convenience init(array: [T]) { + precondition(array.count > 0) + self.init(value: array.first!) + for v in array.dropFirst() { + insert(v, parent: self) + } + } + + public var isRoot: Bool { + return parent == nil + } + + public var isLeaf: Bool { + return left == nil && right == nil + } + + public var isLeftChild: Bool { + return parent?.left === self + } + + public var isRightChild: Bool { + return parent?.right === self + } + + public var hasLeftChild: Bool { + return left != nil + } + + public var hasRightChild: Bool { + return right != nil + } + + public var hasAnyChild: Bool { + return hasLeftChild || hasRightChild + } + + public var hasBothChildren: Bool { + return hasLeftChild && hasRightChild + } + + /* How many nodes are in this subtree. Performance: O(n). */ + public var count: Int { + return (left?.count ?? 0) + 1 + (right?.count ?? 0) + } +} + +// MARK: - Adding items + +extension ThreadedBinaryTree { + /* + Inserts a new element into the tree. You should only insert elements + at the root, to make to sure this remains a valid binary tree! + Performance: runs in O(h) time, where h is the height of the tree. + */ + public func insert(value: T) { + insert(value, parent: self) + } + + private func insert(value: T, parent: ThreadedBinaryTree) { + if value < self.value { + if let left = left { + left.insert(value, parent: left) + } else { + left = ThreadedBinaryTree(value: value) + left?.parent = parent + } + } else { + if let right = right { + right.insert(value, parent: right) + } else { + right = ThreadedBinaryTree(value: value) + right?.parent = parent + } + } + } +} + +// MARK: - Deleting items + +extension ThreadedBinaryTree { + /* + Deletes a node from the tree. + + Returns the node that has replaced this removed one (or nil if this was a + leaf node). That is primarily useful for when you delete the root node, in + which case the tree gets a new root. + + Performance: runs in O(h) time, where h is the height of the tree. + */ + public func remove() -> ThreadedBinaryTree? { + let replacement: ThreadedBinaryTree? + + if let left = left { + if let right = right { + replacement = removeNodeWithTwoChildren(left, right) + } else { + // This node only has a left child. The left child replaces the node. + replacement = left + } + } else if let right = right { + // This node only has a right child. The right child replaces the node. + replacement = right + } else { + // This node has no children. We just disconnect it from its parent. + replacement = nil + } + + reconnectParentToNode(replacement) + + // The current node is no longer part of the tree, so clean it up. + parent = nil + left = nil + right = nil + + return replacement + } + + private func removeNodeWithTwoChildren(left: ThreadedBinaryTree, _ right: BinarySearchTree) -> BinarySearchTree { + // This node has two children. It must be replaced by the smallest + // child that is larger than this node's value, which is the leftmost + // descendent of the right child. + let successor = right.minimum() + + // If this in-order successor has a right child of its own (it cannot + // have a left child by definition), then that must take its place. + successor.remove() + + // Connect our left child with the new node. + successor.left = left + left.parent = successor + + // Connect our right child with the new node. If the right child does + // not have any left children of its own, then the in-order successor + // *is* the right child. + if right !== successor { + successor.right = right + right.parent = successor + } else { + successor.right = nil + } + + // And finally, connect the successor node to our parent. + return successor + } + + private func reconnectParentToNode(node: ThreadedBinaryTree?) { + if let parent = parent { + if isLeftChild { + parent.left = node + } else { + parent.right = node + } + } + node?.parent = parent + } +} + +// MARK: - Searching + +extension ThreadedBinaryTree { + /* + Finds the "highest" node with the specified value. + Performance: runs in O(h) time, where h is the height of the tree. + */ + public func search(value: T) -> ThreadedBinaryTree? { + var node: ThreadedBinaryTree? = self + while case let n? = node { + if value < n.value { + node = n.left + } else if value > n.value { + node = n.right + } else { + return node + } + } + return nil + } + + /* + // Recursive version of search + public func search(value: T) -> ThreadedBinaryTree? { + if value < self.value { + return left?.search(value) + } else if value > self.value { + return right?.search(value) + } else { + return self // found it! + } + } + */ + + public func contains(value: T) -> Bool { + return search(value) != nil + } + + /* + Returns the leftmost descendent. O(h) time. + */ + public func minimum() -> ThreadedBinaryTree { + var node = self + while case let next? = node.left { + node = next + } + return node + } + + /* + Returns the rightmost descendent. O(h) time. + */ + public func maximum() -> ThreadedBinaryTree { + var node = self + while case let next? = node.right { + node = next + } + return node + } + + /* + Calculates the depth of this node, i.e. the distance to the root. + Takes O(h) time. + */ + public func depth() -> Int { + var node = self + var edges = 0 + while case let parent? = node.parent { + node = parent + edges += 1 + } + return edges + } + + /* + Calculates the height of this node, i.e. the distance to the lowest leaf. + Since this looks at all children of this node, performance is O(n). + */ + public func height() -> Int { + if isLeaf { + return 0 + } else { + return 1 + max(left?.height() ?? 0, right?.height() ?? 0) + } + } + + /* + Finds the node whose value precedes our value in sorted order. + */ + public func predecessor() -> ThreadedBinaryTree? { + if let left = left { + return left.maximum() + } else { + var node = self + while case let parent? = node.parent { + if parent.value < value { return parent } + node = parent + } + return nil + } + } + + /* + Finds the node whose value succeeds our value in sorted order. + */ + public func successor() -> ThreadedBinaryTree? { + if let right = right { + return right.minimum() + } else { + var node = self + while case let parent? = node.parent { + if parent.value > value { return parent } + node = parent + } + return nil + } + } +} + +// MARK: - Traversal + +extension ThreadedBinaryTree { + public func traverseInOrder(@noescape process: T -> Void) { + left?.traverseInOrder(process) + process(value) + right?.traverseInOrder(process) + } + + public func traversePreOrder(@noescape process: T -> Void) { + process(value) + left?.traversePreOrder(process) + right?.traversePreOrder(process) + } + + public func traversePostOrder(@noescape process: T -> Void) { + left?.traversePostOrder(process) + right?.traversePostOrder(process) + process(value) + } + + /* + Performs an in-order traversal and collects the results in an array. + */ + public func map(@noescape formula: T -> T) -> [T] { + var a = [T]() + if let left = left { a += left.map(formula) } + a.append(formula(value)) + if let right = right { a += right.map(formula) } + return a + } +} + +/* + Is this binary tree a valid binary search tree? +*/ +extension ThreadedBinaryTree { + public func isBST(minValue minValue: T, maxValue: T) -> Bool { + if value < minValue || value > maxValue { return false } + let leftBST = left?.isBST(minValue: minValue, maxValue: value) ?? true + let rightBST = right?.isBST(minValue: value, maxValue: maxValue) ?? true + return leftBST && rightBST + } +} + +// MARK: - Debugging + +extension ThreadedBinaryTree: CustomStringConvertible { + public var description: String { + var s = "" + if let left = left { + s += "(\(left.description)) <- " + } + s += "\(value)" + if let right = right { + s += " -> (\(right.description))" + } + return s + } +} + +extension ThreadedBinaryTree: CustomDebugStringConvertible { + public var debugDescription: String { + var s = "value: \(value)" + if let parent = parent { + s += ", parent: \(parent.value)" + } + if let left = left { + s += ", left = [" + left.debugDescription + "]" + } + if let right = right { + s += ", right = [" + right.debugDescription + "]" + } + return s + } + + public func toArray() -> [T] { + return map { $0 } + } +} From 6065c25c9257c9c8aa9ec0cfa42429034791c70a Mon Sep 17 00:00:00 2001 From: scalls Date: Tue, 26 Apr 2016 13:57:32 -0400 Subject: [PATCH 0273/1679] Removed Adjacency List directory and EdgeTree.swift class in Radix Tree directory --- Adjacency-List/README.markdown | 1 - "Adjacency\\ List" | 1 - Radix-Tree/EdgeTree.swift | 149 --------------------------------- 3 files changed, 151 deletions(-) delete mode 100644 Adjacency-List/README.markdown delete mode 100644 "Adjacency\\ List" delete mode 100644 Radix-Tree/EdgeTree.swift diff --git a/Adjacency-List/README.markdown b/Adjacency-List/README.markdown deleted file mode 100644 index aebd1a631..000000000 --- a/Adjacency-List/README.markdown +++ /dev/null @@ -1 +0,0 @@ -Adjacency List README diff --git "a/Adjacency\\ List" "b/Adjacency\\ List" deleted file mode 100644 index 8b1378917..000000000 --- "a/Adjacency\\ List" +++ /dev/null @@ -1 +0,0 @@ - diff --git a/Radix-Tree/EdgeTree.swift b/Radix-Tree/EdgeTree.swift deleted file mode 100644 index 06a8b0b7a..000000000 --- a/Radix-Tree/EdgeTree.swift +++ /dev/null @@ -1,149 +0,0 @@ -class Root { - - var children: [Edge] - - init() { - children = [Edge]() - } - -} - -class Edge: Root { - - var parent: Edge? - var label: String - - init(_ label: String) { - self.label = label - super.init() - } - -} - -class EdgeTree { - - var root: Root - - init() { - root = Root() - } - - func insert(_ str: String) -> Bool { - - //Account for a blank input - if str == "" { - return true - } - - //Account for an empty tree - if root.children.count == 0 { - root.children.append( Edge(str) ) - return true - } - - var searchStr = str - var currEdge = root - - while (true) { - - var i = 0 - - for e in currEdge.children { - - //Get the shared - var shared = sharedPrefix(searchStr, e.label) - var index = shared.startIndex - - //The search string is equal to the shared string - //so the string already exists in the tree - if searchStr == shared { - return false - } - - //The child's label is a prefix of the search string - else if e.label.hasPrefix(shared) { - - for _ in 1...shared.characters.count { - index = index.successor() - } - - //Substring the search string so that the prefix is removed - searchStr = searchStr.substringFromIndex(index) - - //Set currNode to e - currEdge = e - break - - } - - - //The child's label and the search string share a prefix - else if shared.characters.count > 0 { - - //Cut the prefix off from both the search string and label - var labelIndex = e.label.characters.startIndex - - for _ in 1...shared.characters.count { - index = index.successor() - labelIndex = labelIndex.successor() - } - - searchStr = searchStr.substringFromIndex(index) - e.label = e.label.substringFromIndex(labelIndex) - - //Create a new edge whose label is the shared string - //its parent is currEdge.parent and add a child with - //label = searchStr - //Also add it to the parent's children - let newEdge = Edge(shared) - newEdge.children.append( Edge(searchStr) ) - newEdge.parent = e.parent - currEdge.children.append(newEdge) - - //Remove this edge from the parent's child list - currEdge.children.remove(at: i) - - //Set this edge's parent to the prefix node - e.parent = newEdge.parent - return true - - } - - //They don't share a prefix (go to next child) - i += 1 - - } - - //No children share a prefix, so create a new child - currEdge.children.append( Edge(searchStr) ) - return true - } - } -} - -//Returns the prefix that is shared between the two input strings -//i.e. sharedPrefix("court", "coral") -> "co" -func sharedPrefix(_ str1: String, _ str2: String) -> String { - - var temp = "" - - var c1 = str1.characters.startIndex - var c2 = str2.characters.startIndex - - for _ in 0...min(str1.characters.count-1, str2.characters.count-1) { - - if str1[c1] == str2[c2] { - temp.append( str1[c1] ) - c1 = c1.successor() - c2 = c2.successor() - } - - else { - return temp - } - - } - - return temp - -} \ No newline at end of file From 6d5d92a2c423aab6c11f8b0ca12bcf4326e9b155 Mon Sep 17 00:00:00 2001 From: scalls Date: Tue, 26 Apr 2016 13:58:52 -0400 Subject: [PATCH 0274/1679] Removed Adjacency List from README.markdown --- README.markdown | 1 - 1 file changed, 1 deletion(-) diff --git a/README.markdown b/README.markdown index 9a536bb63..2f883c287 100644 --- a/README.markdown +++ b/README.markdown @@ -174,7 +174,6 @@ Most of the time using just the built-in `Array`, `Dictionary`, and `Set` types - [Shortest Path](Shortest Path %28Unweighted%29/) on an unweighted tree - [Minimum Spanning Tree](Minimum Spanning Tree %28Unweighted%29/) on an unweighted tree - All Paths -- [Adjacency List](Adjacency-List/) :construction: ## Puzzles From 32c558b8f4fb8bb964d1fcdf3aff40a045afb447 Mon Sep 17 00:00:00 2001 From: scalls Date: Tue, 26 Apr 2016 14:03:47 -0400 Subject: [PATCH 0275/1679] Added main.swift to the Radix-Tree directory and updated RadixTree.swift class --- Radix-Tree/main.swift | 63 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 Radix-Tree/main.swift diff --git a/Radix-Tree/main.swift b/Radix-Tree/main.swift new file mode 100644 index 000000000..cad669697 --- /dev/null +++ b/Radix-Tree/main.swift @@ -0,0 +1,63 @@ +var radix = RadixTree() +var radix2 = RadixTree() +var radixWiki = RadixTree() + +print("-------------------------------------------------") +radix.printTree() +print("--------------------------------------------------") +radix.insert( "courting" ) +radix.printTree() +print("-------------------------------------------------") +radix.insert( "coral" ) +radix.printTree() +print("--------------------------------------------------") +radix.insert( "courted" ) +radix.printTree() +print("---------------------------------------------------") +print( radix.insert( "corals") ) +radix.printTree() + +print( radixWiki.insert("romanus") ) +print( radixWiki.insert("rubicundus") ) +print( radixWiki.insert("rubicon") ) +print( radixWiki.insert("romane") ) +print( radixWiki.insert("ruber") ) +print( radixWiki.insert("rubens") ) +print( radixWiki.insert("romulus") ) +radixWiki.insert("start") +radixWiki.insert("shoot") +radixWiki.insert("shit") +radixWiki.insert("starch") +radixWiki.insert("steven") + +radixWiki.insert("compute") +radixWiki.insert("compatible") +radixWiki.insert("construction") +radixWiki.insert("coral") +radixWiki.insert("crude") +radixWiki.insert("chalk") +radixWiki.insert("chime") +radixWiki.insert("courting") +radixWiki.insert("courted") + +print("PRINT TEST-------------------------------") +radixWiki.printTree() + +// let h = radix.height() +// let h2 = radix2.height() +// let hwiki = radixWiki.height() +// print("Height of tree: \(h)") +// print("height of second tree: \(h2)") +// print("Height of wikipedia tree: \(hwiki)") + +// print(radixWiki.root.level()) +// print(radixWiki.root.children[0].level()) +// print(radixWiki.root.children[0].children[0].level()) +// print(radixWiki.root.children[0].children[0].children[0].level()) + +// print("\t\t\t\t\t\ttest") +// print("PRINT TEST-------------------------------") +// radixWiki.printTree() + +// print("PRINT TEST-------------------------------") +// radix.printTree() \ No newline at end of file From cf7c08731baf2e7e8f7678a800427bb78cc84840 Mon Sep 17 00:00:00 2001 From: scalls Date: Tue, 26 Apr 2016 14:19:06 -0400 Subject: [PATCH 0276/1679] Updated RadixTree.swift and main.swift --- Radix-Tree/RadixTree.swift | 278 +++++++++++++++++++++++++------------ Radix-Tree/main.swift | 32 +++-- 2 files changed, 208 insertions(+), 102 deletions(-) diff --git a/Radix-Tree/RadixTree.swift b/Radix-Tree/RadixTree.swift index 27dfbd8dc..b58dee309 100644 --- a/Radix-Tree/RadixTree.swift +++ b/Radix-Tree/RadixTree.swift @@ -1,123 +1,227 @@ import Foundation +class Root { -public class RadixNode { - public var parent: RadixNode? - public var children = [(childNode: RadixNode, childEdgeLabel: String)]() + var children: [Edge] - public init() { - - } - - public init(value: String) { - self.children.append((childNode: RadixNode(), childEdgeLabel: value)) - } - - public func addChild(_ node: RadixNode, _ label: String) { - children.append((node, label)) - node.parent = self - } - - public func getChildren() -> [(childNode: RadixNode, childEdgeLabel: String)] { - return children + init() { + children = [Edge]() } - public func getChildAt(i: Int) -> (RadixNode, String)? { - if i >= children.count { - return nil + func height() -> Int { + if children.count == 0 { + return 1 + } + else { + var max = 1 + for c in children { + if c.height() > max { + max = c.height() + } + } + return 1 + max } - return children[i] } - public func getParent() -> RadixNode? { - return parent + func level() -> Int { + return 0 } - public func isLeaf() -> Bool { - return children.count == 0 + func printRoot() { + //print("children: \(children.count)") + //print("split at: \(children.count/2-1)") + if (children.count > 1) { + for c in 0...children.count/2-1 { + children[c].printEdge() + print("|") + } + } + else if children.count > 0 { + children[0].printEdge() + } + print("ROOT") + //print("second half starts at: \(children.count/2)") + if children.count > 1 { + for c in children.count/2...children.count-1 { + children[c].printEdge() + print("|") + } + } + print() } } -public class RadixTree { - public var root: RadixNode +class Edge: Root { - //Construct an "empty" RadixTree with a single node - public init() { - root = RadixNode() - } + var parent: Root? + var label: String - public init(value: String) { - self.root = RadixNode(value: value) + init(_ label: String) { //Edge(label: "label") + self.label = label + super.init() } - public func find(str: String, node: RadixNode?) -> Bool { - var currNode: RadixNode - var search = str - if (node == nil) { - currNode = self.root + override + func level() -> Int { + if parent != nil { + return 1 + parent!.level() } else { - currNode = node! - } - if (str == "") { - return true - } - else { - for n in 0...currNode.children.count-1 { - if (str.hasPrefix(currNode.children[n].childEdgeLabel)) { - let elementsFound = currNode.children[n].childEdgeLabel.characters.count - search = search.substringFromIndex(search.startIndex.advanced(by: elementsFound)) - currNode = currNode.children[n].childNode - find(str: search, node: currNode) - } - } + return 1 } - return false } - public func insert(str: String, node: RadixNode?) -> Bool { - var search = str - var currNode: RadixNode - if (node == nil) { - currNode = self.root + func printEdge() { + if children.count > 1 { + for c in 0...children.count/2-1 { + children[c].printEdge() + } } - else { - currNode = node! + else if children.count > 0 { + children[0].printEdge() + } + for x in 1...level() { + if x == level() { + print("|------>", terminator: "") + } + else if x == 1 { + print("| ", terminator: "") + } + else if x == level()-1 { + print("| ", terminator: "") + } + else { + print("| ", terminator: "") + } } - //Case 0: str == "" (it is already in the tree) - // -> return false - if (str == "") { - return false + print(label) + if children.count == 0 { + for _ in 1...level() { + print("| ", terminator: "") + } + print() } - else { - for c in currNode.children { - - //Temp is the string of the prefix that the label and the - // search string have in common. - //let temp = currNode.children[c].childEdgeLabel.sharePrefix(str) - - //Case 3: currNode has a child that shares some prefix with str - // -> little bit more complicated - //if temp == 0 { + if children.count > 1 { + for c in children.count/2...children.count-1 { + children[c].printEdge() + } + } + } +} - //Remove the shared characters from both the search string and - // label - //currNode.children[c].childEdgeLabel.substringFromIndex(temp.count) - //str.substringFromIndex(temp.count) +class RadixTree { + var root: Root - //} - + init() { + root = Root() + } - //Case 1: currNode has no children that share a prefix with str - // -> create a new child for currNode + func height() -> Int { + return root.height() - 1 + } + func insert(_ str: String) -> Bool { + //Account for a blank input + if str == "" { + return true + } + //Account for an empty tree + if root.children.count == 0 { + root.children.append( Edge(str) ) + return true + } + var searchStr = str + var currEdge = root + while (true) { + var found = false + var i = 0 + if currEdge.children.count == 0 { + let newEdge = Edge(searchStr) + currEdge.children.append(newEdge) + newEdge.parent = currEdge + } + for e in currEdge.children { + //Get the shared + var shared = sharedPrefix(searchStr, e.label) + var index = shared.startIndex + //The search string is equal to the shared string + //so the string already exists in the tree + if searchStr == shared { + return false + } + else if shared == e.label { + currEdge = e + var tempIndex = searchStr.startIndex + for _ in 1...shared.characters.count { + tempIndex = tempIndex.successor() + } + searchStr = searchStr.substringFromIndex(tempIndex) + found = true + break + } + //The child's label and the search string share a prefix + else if shared.characters.count > 0 { + //Cut the prefix off from both the search string and label + var labelIndex = e.label.characters.startIndex + //Create index objects and move them to after the shared prefix + for _ in 1...shared.characters.count { + index = index.successor() + labelIndex = labelIndex.successor() + } + //Substring both the search string and the label from the shared prefix + searchStr = searchStr.substringFromIndex(index) + e.label = e.label.substringFromIndex(labelIndex) + //Create 2 new edges and update parent/children values + let newEdge = Edge(e.label) + e.label = shared + for ec in e.children { + newEdge.children.append(ec) + } + newEdge.parent = e + e.children.removeAll() + for nec in newEdge.children { + nec.parent = newEdge + } + e.children.append(newEdge) + let newEdge2 = Edge(searchStr) + newEdge2.parent = e + e.children.append(newEdge2) + return true + } + //They don't share a prefix (go to next child) + i += 1 + } + if (!found) { + //No children share a prefix, so create a new child + let newEdge = Edge(searchStr) + currEdge.children.append(newEdge) + newEdge.parent = currEdge + return true + } + } + } - //Case 2: currNode has a child whose label is a prefix of str - // -> recurse down + func printTree() { + root.printRoot() + } +} - } +//Returns the prefix that is shared between the two input strings +//i.e. sharedPrefix("court", "coral") -> "co" +func sharedPrefix(_ str1: String, _ str2: String) -> String { + var temp = "" + var c1 = str1.characters.startIndex + var c2 = str2.characters.startIndex + for _ in 0...min(str1.characters.count-1, str2.characters.count-1) { + if str1[c1] == str2[c2] { + temp.append( str1[c1] ) + c1 = c1.successor() + c2 = c2.successor() + } + else { + return temp } - return false } + return temp } \ No newline at end of file diff --git a/Radix-Tree/main.swift b/Radix-Tree/main.swift index cad669697..148766834 100644 --- a/Radix-Tree/main.swift +++ b/Radix-Tree/main.swift @@ -40,24 +40,26 @@ radixWiki.insert("chime") radixWiki.insert("courting") radixWiki.insert("courted") +radixWiki.insert("rubicunduses") + print("PRINT TEST-------------------------------") radixWiki.printTree() -// let h = radix.height() -// let h2 = radix2.height() -// let hwiki = radixWiki.height() -// print("Height of tree: \(h)") -// print("height of second tree: \(h2)") -// print("Height of wikipedia tree: \(hwiki)") +let h = radix.height() +let h2 = radix2.height() +let hwiki = radixWiki.height() +print("Height of tree: \(h)") +print("height of second tree: \(h2)") +print("Height of wikipedia tree: \(hwiki)") -// print(radixWiki.root.level()) -// print(radixWiki.root.children[0].level()) -// print(radixWiki.root.children[0].children[0].level()) -// print(radixWiki.root.children[0].children[0].children[0].level()) +print(radixWiki.root.level()) +print(radixWiki.root.children[0].level()) +print(radixWiki.root.children[0].children[0].level()) +print(radixWiki.root.children[0].children[0].children[0].level()) -// print("\t\t\t\t\t\ttest") -// print("PRINT TEST-------------------------------") -// radixWiki.printTree() +print("\t\t\t\t\t\ttest") +print("PRINT TEST-------------------------------") +radixWiki.printTree() -// print("PRINT TEST-------------------------------") -// radix.printTree() \ No newline at end of file +print("PRINT TEST-------------------------------") +radix.printTree() \ No newline at end of file From 7b1a04510509eef72185d81a8f78d263b13a92b4 Mon Sep 17 00:00:00 2001 From: scalls Date: Tue, 26 Apr 2016 15:02:46 -0400 Subject: [PATCH 0277/1679] Added find() to RadixTree class --- Radix-Tree/RadixTree.swift | 62 ++++++++++++++++++++++++++++++++++++-- Radix-Tree/main.swift | 53 +++++++------------------------- 2 files changed, 70 insertions(+), 45 deletions(-) diff --git a/Radix-Tree/RadixTree.swift b/Radix-Tree/RadixTree.swift index b58dee309..39448fa27 100644 --- a/Radix-Tree/RadixTree.swift +++ b/Radix-Tree/RadixTree.swift @@ -124,7 +124,7 @@ class RadixTree { func insert(_ str: String) -> Bool { //Account for a blank input if str == "" { - return true + return false } //Account for an empty tree if root.children.count == 0 { @@ -135,7 +135,6 @@ class RadixTree { var currEdge = root while (true) { var found = false - var i = 0 if currEdge.children.count == 0 { let newEdge = Edge(searchStr) currEdge.children.append(newEdge) @@ -190,7 +189,6 @@ class RadixTree { return true } //They don't share a prefix (go to next child) - i += 1 } if (!found) { //No children share a prefix, so create a new child @@ -202,6 +200,64 @@ class RadixTree { } } + func find(_ str: String) -> Bool { + //A radix tree always contains the empty string + if str == "" { + return true + } + //If there are no children then the string cannot be in the tree + else if root.children.count == 0 { + return false + } + var searchStr = str + var currEdge = root + while (true) { + var found = false + for c in currEdge.children { + //First check if the search string and the child's label are equal + // if so the string is in the tree, return true + if searchStr == c.label { + return true + } + //If that is not true, find the shared string b/t the search string + // and the label + var shared = sharedPrefix(searchStr, c.label) + //If the shared string is equal to the label, update the curent node + // and run it back + if shared == c.label { + currEdge = c + var tempIndex = searchStr.startIndex + for _ in 1...shared.characters.count { + tempIndex = tempIndex.successor() + } + searchStr = searchStr.substringFromIndex(tempIndex) + found = true + break + } + //If the shared string is empty, go to the next children + else if shared.characters.count == 0 { + continue + } + //If the search string and the child's label only share some characters, + // the string is not in the tree, return false + else if shared[shared.startIndex] == c.label[c.label.startIndex] && + shared.characters.count < c.label.characters.count { + return false + } + } + if !found { + return false + } + } + //Start at the root + //If a child's label is a prefix of the search string + // Cut the prefix off of the search string and + // start looking through that child's children + //If a child's label == searchStr, return true + + //If none of the children's labels are a prefix of the search string + } + func printTree() { root.printRoot() } diff --git a/Radix-Tree/main.swift b/Radix-Tree/main.swift index 148766834..b53ffb9ec 100644 --- a/Radix-Tree/main.swift +++ b/Radix-Tree/main.swift @@ -1,29 +1,13 @@ var radix = RadixTree() -var radix2 = RadixTree() var radixWiki = RadixTree() -print("-------------------------------------------------") -radix.printTree() -print("--------------------------------------------------") -radix.insert( "courting" ) -radix.printTree() -print("-------------------------------------------------") -radix.insert( "coral" ) -radix.printTree() -print("--------------------------------------------------") -radix.insert( "courted" ) -radix.printTree() -print("---------------------------------------------------") -print( radix.insert( "corals") ) -radix.printTree() - -print( radixWiki.insert("romanus") ) -print( radixWiki.insert("rubicundus") ) -print( radixWiki.insert("rubicon") ) -print( radixWiki.insert("romane") ) -print( radixWiki.insert("ruber") ) -print( radixWiki.insert("rubens") ) -print( radixWiki.insert("romulus") ) +radixWiki.insert("romanus") +radixWiki.insert("rubicundus") +radixWiki.insert("rubicon") +radixWiki.insert("romane") +radixWiki.insert("ruber") +radixWiki.insert("rubens") +radixWiki.insert("romulus") radixWiki.insert("start") radixWiki.insert("shoot") radixWiki.insert("shit") @@ -42,24 +26,9 @@ radixWiki.insert("courted") radixWiki.insert("rubicunduses") -print("PRINT TEST-------------------------------") -radixWiki.printTree() - -let h = radix.height() -let h2 = radix2.height() -let hwiki = radixWiki.height() -print("Height of tree: \(h)") -print("height of second tree: \(h2)") -print("Height of wikipedia tree: \(hwiki)") - -print(radixWiki.root.level()) -print(radixWiki.root.children[0].level()) -print(radixWiki.root.children[0].children[0].level()) -print(radixWiki.root.children[0].children[0].children[0].level()) - -print("\t\t\t\t\t\ttest") -print("PRINT TEST-------------------------------") radixWiki.printTree() -print("PRINT TEST-------------------------------") -radix.printTree() \ No newline at end of file +print("FIND TESTS") +print(radixWiki.find("courts")) +print(radixWiki.find("rubicunduses")) +print(radixWiki.find("")) \ No newline at end of file From 7386c4d80ec7597b28708fe4ac5ec44dbb5f2e36 Mon Sep 17 00:00:00 2001 From: scalls Date: Tue, 26 Apr 2016 15:21:34 -0400 Subject: [PATCH 0278/1679] Updated RadixTree's README.markdown --- Radix-Tree/README.markdown | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Radix-Tree/README.markdown b/Radix-Tree/README.markdown index eecbeb6f3..9c126760e 100644 --- a/Radix-Tree/README.markdown +++ b/Radix-Tree/README.markdown @@ -3,10 +3,22 @@ A radix tree is a tree where a node can have any number of children. Each edge leading from a node to a child has a label (usually a string). A radix tree is often used to store strings or IP addresses and by traversing from the root to any leaf in the tree, (by concatenating all the labels of edges along the way) you can find any string. This is a radix tree: ![](/Radix-Tree/Images/radixtree.png) +## Implemenation + +The RadixTree class itself has one member variable, root, of type Root. The Root is the top of every RadixTree. Every node that is added, removed, looked up, etc. is a child, a child of a child, etc. of that root. The rest of the tree is represented as an Edge, which inherits Root. The different between Edge and Root is that Edges have a label (of type String) and a parent (of type Root?) member variables. This approach is a little different from the conventional way of creating Tree data structures but is easier to wrap your head around (see the picture above). + ## Operations Typical operations on a radix tree include lookup, insertion, deletion, find predecessor, find successor, and find all strings with common prefix. The running time of lookup, insertion, and deletion is O(k) where k is the length of the key. This is different from most trees because these operations usually run in O(logn) time where n is the number of nodes in the tree. +### Find + +The find function returns true if the String you are searching for is in the tree and false if it is not. Every RadixTree contains at the very least one String ("") so find("") will always return true. A String is considered "in the tree" if the String you are searching for is a concatenation of Edge labels while traversing downwards or a prefix of that concatenation. For example, if you look at the example tree above, find("roma") will return true because it is a prefix of the traversal "r"->"om"->"an". On the other hand, find("romans") will return false. + +### Insert + +The insert function returns true if the String you are trying to insert was successfully inserted into the RadixTree and false if the String is already in the tree. Similarly to find(""), insert("") will always return false because an empty RadixTree contains "" by default. + ## See Also [Radix Tree - Wikipedia](https://en.wikipedia.org/wiki/Radix_tree) From f11d617fe9641f5bb425c0dd810621c22aa8d184 Mon Sep 17 00:00:00 2001 From: scalls Date: Tue, 26 Apr 2016 15:22:41 -0400 Subject: [PATCH 0279/1679] Updated RadixTree's README.markdown --- Radix-Tree/README.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Radix-Tree/README.markdown b/Radix-Tree/README.markdown index 9c126760e..918c8324c 100644 --- a/Radix-Tree/README.markdown +++ b/Radix-Tree/README.markdown @@ -11,11 +11,11 @@ The RadixTree class itself has one member variable, root, of type Root. The Root Typical operations on a radix tree include lookup, insertion, deletion, find predecessor, find successor, and find all strings with common prefix. The running time of lookup, insertion, and deletion is O(k) where k is the length of the key. This is different from most trees because these operations usually run in O(logn) time where n is the number of nodes in the tree. -### Find +### Find(_ str: String) -> Bool The find function returns true if the String you are searching for is in the tree and false if it is not. Every RadixTree contains at the very least one String ("") so find("") will always return true. A String is considered "in the tree" if the String you are searching for is a concatenation of Edge labels while traversing downwards or a prefix of that concatenation. For example, if you look at the example tree above, find("roma") will return true because it is a prefix of the traversal "r"->"om"->"an". On the other hand, find("romans") will return false. -### Insert +### Insert(_ str: String) -> Bool The insert function returns true if the String you are trying to insert was successfully inserted into the RadixTree and false if the String is already in the tree. Similarly to find(""), insert("") will always return false because an empty RadixTree contains "" by default. From c648c8fc4be6224b57a76715260d8dcf59c8aa3b Mon Sep 17 00:00:00 2001 From: scalls Date: Tue, 26 Apr 2016 15:30:51 -0400 Subject: [PATCH 0280/1679] Added more to RadixTree's README --- Radix-Tree/README.markdown | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/Radix-Tree/README.markdown b/Radix-Tree/README.markdown index 918c8324c..129d0add4 100644 --- a/Radix-Tree/README.markdown +++ b/Radix-Tree/README.markdown @@ -11,14 +11,35 @@ The RadixTree class itself has one member variable, root, of type Root. The Root Typical operations on a radix tree include lookup, insertion, deletion, find predecessor, find successor, and find all strings with common prefix. The running time of lookup, insertion, and deletion is O(k) where k is the length of the key. This is different from most trees because these operations usually run in O(logn) time where n is the number of nodes in the tree. -### Find(_ str: String) -> Bool +### RadixTree.find(_ str: String) -> Bool The find function returns true if the String you are searching for is in the tree and false if it is not. Every RadixTree contains at the very least one String ("") so find("") will always return true. A String is considered "in the tree" if the String you are searching for is a concatenation of Edge labels while traversing downwards or a prefix of that concatenation. For example, if you look at the example tree above, find("roma") will return true because it is a prefix of the traversal "r"->"om"->"an". On the other hand, find("romans") will return false. -### Insert(_ str: String) -> Bool +### RadixTree.insert(_ str: String) -> Bool The insert function returns true if the String you are trying to insert was successfully inserted into the RadixTree and false if the String is already in the tree. Similarly to find(""), insert("") will always return false because an empty RadixTree contains "" by default. +### RadixTree.remove(_ str: String) -> Bool + +THIS IS NOT IMPLEMENTED YET + +### Root.level() -> Int + +The level function returns how far down in the tree the Root or Edge in question is. A Root object will always return 0. A child of the Root will return 1, a child of a child of the root will return 2, etc. + +### RadixTree.height() -> Int + +The height function returns an Int equal to the highest level in the Tree. An empty tree will return 0. + +### RadixTree.printTree() + +The printTree function was used to visualize the tree itself. This function is a little buggy and not perfect yet but gets the job done thus far. + +### sharedPrefix(_ str1: String, _ str2: String) -> + +The sharedPrefix function is a non-member function in the RadixTree.swift file. It takes in two String objects and returns the shared prefix between them. For example, +sharedPrefix("apples", "oranges") will return "" and sharedPrefix("court", "coral") will return "co". This function is used in the implementation of the find, insert, and remove functions. + ## See Also [Radix Tree - Wikipedia](https://en.wikipedia.org/wiki/Radix_tree) From a6d58ec2cdf4f11ffe7ac6260c4c26d25583e77c Mon Sep 17 00:00:00 2001 From: scalls Date: Tue, 26 Apr 2016 15:31:34 -0400 Subject: [PATCH 0281/1679] Fixed typo in RadixTree's README --- Radix-Tree/README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Radix-Tree/README.markdown b/Radix-Tree/README.markdown index 129d0add4..ef405bcb0 100644 --- a/Radix-Tree/README.markdown +++ b/Radix-Tree/README.markdown @@ -35,7 +35,7 @@ The height function returns an Int equal to the highest level in the Tree. An em The printTree function was used to visualize the tree itself. This function is a little buggy and not perfect yet but gets the job done thus far. -### sharedPrefix(_ str1: String, _ str2: String) -> +### sharedPrefix(_ str1: String, _ str2: String) -> String The sharedPrefix function is a non-member function in the RadixTree.swift file. It takes in two String objects and returns the shared prefix between them. For example, sharedPrefix("apples", "oranges") will return "" and sharedPrefix("court", "coral") will return "co". This function is used in the implementation of the find, insert, and remove functions. From 42e259f0a8cae284cda4826e3e0f7211ccdd696f Mon Sep 17 00:00:00 2001 From: scalls Date: Tue, 26 Apr 2016 17:21:39 -0400 Subject: [PATCH 0282/1679] Added remove() to the RadixTree class --- Radix-Tree/RadixTree.swift | 73 ++++++++++++++++++++++++++++++++++---- Radix-Tree/main.swift | 22 ++++++++++-- 2 files changed, 86 insertions(+), 9 deletions(-) diff --git a/Radix-Tree/RadixTree.swift b/Radix-Tree/RadixTree.swift index 39448fa27..994a38dbe 100644 --- a/Radix-Tree/RadixTree.swift +++ b/Radix-Tree/RadixTree.swift @@ -71,6 +71,18 @@ class Edge: Root { } } + func erase() { + print("Testing erase on: \(label)") + self.parent = nil + if children.count > 0 { + for _ in 0...children.count-1 { + children[0].erase() + children.remove(at: 0) + } + } + print("Removed: \(label)") + } + func printEdge() { if children.count > 1 { for c in 0...children.count/2-1 { @@ -238,6 +250,10 @@ class RadixTree { else if shared.characters.count == 0 { continue } + //If the shared string matches the search string, return true + else if shared == searchStr { + return true + } //If the search string and the child's label only share some characters, // the string is not in the tree, return false else if shared[shared.startIndex] == c.label[c.label.startIndex] && @@ -249,13 +265,58 @@ class RadixTree { return false } } - //Start at the root - //If a child's label is a prefix of the search string - // Cut the prefix off of the search string and - // start looking through that child's children - //If a child's label == searchStr, return true + } - //If none of the children's labels are a prefix of the search string + func remove(_ str: String) -> Bool { + print("Tryna remove: \(str)") + //You cannot remove the empty string from the tree + if str == "" { + return false + } + //If the tree is empty, you cannot remove anything + else if root.children.count == 0 { + return false + } + var searchStr = str + var currEdge = root + while (true) { + var found = false + print("Search string: \(searchStr)") + //If currEdge has no children, then the searchStr is not in the tree + if currEdge.children.count == 0 { + return false + } + for c in 0...currEdge.children.count-1 { + //If the child's label matches the search string, remove that child + // and everything below it in the tree + print("Looking at: \(currEdge.children[c].label)") + if currEdge.children[c].label == searchStr { + print("MATCH FOUND") + currEdge.children[c].erase() + print("ERASED WORKED") + currEdge.children.remove(at: c) + print("EDGE LABEL MATCH REMOVE") + return true + } + //Find the shared string + var shared = sharedPrefix(searchStr, currEdge.children[c].label) + //If the shared string is equal to the child's string, go down a level + if shared == currEdge.children[c].label { + currEdge = currEdge.children[c] + var tempIndex = searchStr.startIndex + for _ in 1...shared.characters.count { + tempIndex = tempIndex.successor() + } + searchStr = searchStr.substringFromIndex(tempIndex) + found = true + break + } + } + //If there is no match, then the searchStr is not in the tree + if !found { + return false + } + } } func printTree() { diff --git a/Radix-Tree/main.swift b/Radix-Tree/main.swift index b53ffb9ec..6cffe1c20 100644 --- a/Radix-Tree/main.swift +++ b/Radix-Tree/main.swift @@ -29,6 +29,22 @@ radixWiki.insert("rubicunduses") radixWiki.printTree() print("FIND TESTS") -print(radixWiki.find("courts")) -print(radixWiki.find("rubicunduses")) -print(radixWiki.find("")) \ No newline at end of file +print(radixWiki.find("courts")) // false +print(radixWiki.find("r")) // true +print(radixWiki.find("ro")) // true +print(radixWiki.find("rom")) // true +print(radixWiki.find("roma")) // true +print(radixWiki.find("roman")) // true +print(radixWiki.find("romane")) // true +print(radixWiki.find("romans")) // false +print(radixWiki.find("steve")) // true + +print("REMOVE TESTS") + +print(radixWiki.remove("c")) +radixWiki.printTree() + +print(radixWiki.remove("rub")) +radixWiki.printTree() + +print(radixWiki.remove("stevenson")) \ No newline at end of file From ad134fdbaf12919e8d349131ac422b29a9632a0e Mon Sep 17 00:00:00 2001 From: Thukor Date: Thu, 28 Apr 2016 10:44:22 -0400 Subject: [PATCH 0283/1679] Added debugged Insert and Find --- Trie/trie | Bin 23362 -> 38270 bytes Trie/trie.swift | 58 +++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 52 insertions(+), 6 deletions(-) diff --git a/Trie/trie b/Trie/trie index 9459e471d729d947cf78e2e3b199647501c58738..327aac89484ab9a8360ca3e5e09e046d904d095d 100755 GIT binary patch literal 38270 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 literal 23362 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 (key: String, found: Bool) { + var currentNode = self.root - func insertWord(w: String) -> Void { + for c in key.characters { + if currentNode.children[String(c)] == nil { + return(key, false) + } + currentNode = currentNode.children[String(c)]! + } + + return(key, currentNode.isValidWord()) + } + + func insert(w: String) -> (word: String, inserted: Bool) { + + var currentNode = self.root + var length = w.characters.count + + for c in w.characters { + if currentNode.children[String(c)] != nil { + currentNode = currentNode.children[String(c)]! + length -= 1 + } + } + + if length == 0 { + if(currentNode.isValidWord()) { + return (w, false) + } + currentNode.isWord() + return (w, true) + } + + let choppedWord = String(w.characters.suffix(length)) + + print(choppedWord) + for c in choppedWord.characters { + currentNode.children[String(c)] = Node(c: String(c)) + currentNode = currentNode.children[String(c)]! + } + + currentNode.isWord() + return (w, true) } } print("tests") -var x: Node = Node(c: "c") +/*var x: Node = Node(c: "c") print(x.char()) print(x.isValidWord()) x.isWord() -print(x.isValidWord()) +print(x.isValidWord())*/ + + +var T: Trie = Trie() +print(T.insert("Hello")) +print(T.find("Hello")) From 05e402ae68971dce2297f6c77d601d49567c9441 Mon Sep 17 00:00:00 2001 From: Thukor Date: Thu, 28 Apr 2016 11:09:48 -0400 Subject: [PATCH 0284/1679] got rid of debugging statements --- Trie/trie.swift | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/Trie/trie.swift b/Trie/trie.swift index 50a2b544a..b8beb0293 100644 --- a/Trie/trie.swift +++ b/Trie/trie.swift @@ -46,6 +46,8 @@ public class Node { public class Trie { var root = Node(c: "") var nodes: [Node] + var wordList: [String] + var wordCount = 0 init() { self.root = Node(c: "") @@ -84,21 +86,29 @@ public class Trie { } currentNode.isWord() + wordList.append(w) + wordCount += 1 return (w, true) } let choppedWord = String(w.characters.suffix(length)) - print(choppedWord) for c in choppedWord.characters { currentNode.children[String(c)] = Node(c: String(c)) currentNode = currentNode.children[String(c)]! } currentNode.isWord() + wordList.append(w) + wordCount += 1 return (w, true) } + func remove(w: String) { + + + } + } print("tests") From 9dd86baa52481c578449c0b0774c8cc706fb8a4e Mon Sep 17 00:00:00 2001 From: Thukor Date: Thu, 28 Apr 2016 11:53:12 -0400 Subject: [PATCH 0285/1679] Added a few functions for usage, working on remove --- Trie/trie | Bin 38270 -> 43930 bytes Trie/trie.swift | 30 +++++++++++++++++++++++++++++- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/Trie/trie b/Trie/trie index 327aac89484ab9a8360ca3e5e09e046d904d095d..c4dc38f8f44778777f5a4f81f5e8b56679323a28 100755 GIT binary patch literal 43930 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 literal 38270 zcmeHwdw5&bmG7|=gDE&RkhF#*jR2<&k2tci6Q|T5`IQrpgNd9+3#p{ovMq3IMUO3k`rQ%|Sq7&F9Xz2xD=GdYpc2g+gDeu>TX}z9q5V1R>o>puUuVK9_}r#+h6srUh}O3KmP1d%5&n6bWpweCoaj;<~zpZ_(qY42=Cvb7xeIgnZ6b%CZ-wG)^)1cOA8yD& zAJ0Mmc8>nDGKW8($zkUUIsEpk9Q77F|ybLel$!T%QQ%;tx`z@BXOKbpf%PY(JQbM)K4N4-k4 z#ad~b7naRlhnc=a>udAQ5|O%->5H^J884{JgGgMUovRgI$`j*UmL939PsZ3bxX@!a=4dm=Sd z2b2_En<^(~8I^AT&Zxhq&96#ma{E^Mfzdq=F5^laH&2amQkx!s)=_BLgBc&@?B zmft5L(NE6K2y&2x=FZo5AguB@yJv=nSo?w7Jy*28qZM`Z#7IPV zr_jRw29Pc);M+TjrLxbRbtAAMW6W^=f5wdckl^-y2;hCp|H?~b4^6bOqBOFl~} zT<7ochXQR%T}95Et54&ywXDS#=?&e!4)tHd?HcImOp#-r-LV=^W4C{YzbA70mYCb_ zStBtI99q*!R$#nxl`A|k>fq$bxtgka{ILkL?X;*=9t!!p{l2hYR-#w*)>d~%RoD~u zwBsL75EV6^4!EwnF%;?zHDk#7I{i(pD6Y~S@kIh{?nns6yFK_9^@zdN;tqt-x$2^U z?ns~qUESa556O{K-`lgxABqIfH^Z`I>c>u+gHVqxB#R>5fzBR(yA)N!dP@s;Zgv=V z?p*#0S6rR)rV?)EZqtnB#I)iLkk6=NwN_SmwhKc=O{AT5!J6%RB7QgK!n)mS0%51S ze*OBoKm`VoTiVT|{l@LLVt@+E-Ijqz6J2wQ+b6(I23gw(IjN!h-n%4Ejg@v!Lm*6^ zXy54T>GZQ>xHmM0TjmVb&g!<_XisE|9J4hLYT_i93Sq*9%2ZJsb;6+~|nbdQJ9GE~?>3s^Z%ah0B6s5jEv*4yoA>+R|2 z4eg*M46^~n6q?6RQz+t$?crHcPrJ6Nt9OTgRa+OPOau=-t60^p%2m;Dh&BfVjudtW zv~{lab@iUg^2+k+v}o!72Z9@bj4Kbj3f6zyIc5_~(TfA;&~C-=K%>j<@iN410q;XF zf{z*t9ieaPa#-jeNl`UTx6q3%^cD;KLJNJXg}%r__gd&5wa~jP^p9ESK@0sN3q59` zFSXG7EOeWN-fy9oS?B{6`f>~XfQ5dQg+64Vue8t)S?J{!`mlw*%0eHp&?_wTF$?`_ z3;l$JzS=?`x6s#E=qD}owHEq>h5jiE-L%j@ZJ|$D=+|24(-!)57P{{9GKSj)ZJCAM zwLLq%)GO%J2T4X|J zEc6Kr{c;Q4w9v1x(5Ec)D=qYC3*By^YqFnHzpb>;3oUf(T2W%5*I4*VEp+QRwOQ!3 z7XB3$y2C=(_q|%ECklSlWYhHcSfs$bEFY8hzQ+q6voIk!Q~eBBW|sdPpT)}@ND-M$jDMGK8gi3Ej6X;?4YkPu#{ZshT7D+` z7{8D3vk4C}{x^iv5S;WfzMpU!dXp`T{}ti16iqr9znyRzf|GW}Lxj`No3t^0E8#Tc zCQBIKPB;y89lL&XbznE}Z;wFQPUqCnw$w@EcA0eEUy2%#C^9iS+ zIq6{hFO9%yNKV=r|0Cfv6en$r|ABB?5+_R-e}Qlsl9L+a&k{~k^W@Y!RR3oPw-G+U z_)iF@p*lIv_))?yC43Bc#cS)0r$46~FX;PTnrdlXe|*e~9U=YrktvzyYsg_HUfRzQQzG5C}qt|6ff%|+6ZBa|H$+_ z@ax7={m37#)APplr>CP3euNnH_%o3=x9P?)A^(Du@2kyQXVbLk`I{hV-U&mt9V_@x zxG?XH$Ed&S`)XSpV2FG?Wx~QukM?7C4E!_W+a^B`k>X|AWLQ8_a}BX5Bd>QvAIw;Hk6pZMghn?0KNg;Xzn*} zAwpvB5Eu`*63rlP>T?-CaV0kO>qat$O1O-t*BfKV>(di)BIw5aGIJr6o8Q4Og7s!6 zpz{a9?C14l(Q!1nZseKQkp)Ja#;I-$b^)0G%B<8q8;s|jKRBBcztIy(%GC{Lsrgy5 zC|R_RbR<|vH}dtwIq;8e{0Zu4n8UWMr0%u-GX{uY zBxyb{7qj}kC(-gQ#S^ETnQ=YQcv4R^Pw0tF=KgI{dSaAS7;&968A+NyP>&jb{s-3J z)7-$`6BZ?sf(->qPMwm(ts8pDewOHaF|U7XskxcVHsULULYjA=zLYdR@fV~MqwKQ8 zVPb%lf?=?PFyp8z!K{!dWWtZRd6JZiS`&?1D1A5LvQS1-OfhHDBz4=FxwZElMN>8~I;wa#IkuXbO^$ zP4Uw|6EQx*d4t0Yl7|3HC*>qY*=32t#DJy{41+_2aZ?a03_8FB*%XwErXU(O#qXi1 zVobm5ahe5g-u75WM|ttGyWt59QxztteXn};$ ztX`rgVz!3;Ei2$)@U;LZreG<`IpH!KwquSJn)B4rJO~a$*P-Y+m?aLG+fWnp09IQ) zQTy<R}M3(&)&{ zO)aQAh|MQ}j_==e5)xqq9VL8~MAT@%Ax(^^zi@c=^Pj4FN$r1UDT6_!uK@1k~7=B`s* zt7)^DtJgS%(n_rDOXcZ_z5{U8%y|Ei{${cV94UKvkrNFx&FwQi^OYfTGPBKT&k_tD zZq01WS=v9yIXL=;3Q@07VZHNbVielhGmb*I;$_A8F`s{u*i$-1ZoU z5$HAA!_>8nCm*JcZTy7#_1}RvSO2x?2K@bJeczFiQ|ng1#=St{X7tu*5gH%%$4bnn z$gl*OG!e6#M`w{5^RPguU3iRSjt@KOPi#OlZN`vq!c?$fh4a)Aa>g|EClqL+F!*lM zNmS;SJp8B3JKy92siz~W5PkV1CJ#Uw$iWiF{=L6+^!+~1(H|>iyY@Y97d6Z*-@)y3 zBP6$!H0)nj>O3`uvelG;>Y?n0{>JCI+-dVHQSOwQxp?A=f-6{p5io%X3$3K0JwyY5I*ElM3f)$-GAAq9$jn5y-i=K-yp4dBWCP+1p6^=K>csyEy`E(jBrB#ek zuZIdWnV7A(LYeh}Bfns$Rx)pXL$*nJe-|wnoieZCe45Gbw6l+lCcCU3q~D=jIhOjU zd})vU1K3l;_WbmZr?=-@oX_^uNPB9`U2G)m*^$GZn)hSR{&kp%WPDBaar94@<@Gm# z*dgbGqmK8Z59_4^b(=DaF)d@fj$MLw`myn(2>dWBnyaZ&m{yEmP{U!kn|ISZova-M zt7T{-3mw;4ViwF1aP!2D?8KfDX4wuF7Nyn1G%u49NTcIUm_H+2s6*d(LI#T$=JUpr zrv5sWO~bSq!=)K;69(qdQpk;i;e`36Jk$frB?2Mjjhla(B3&4T+%L1OZ%~icp$)-@ zZTLu=SI!ZZnNN!~60>gR`j{-(_9;wS3A&@wXvjw|(vt-@tp#o0SP9m-Ybo2{*?{^4 zG-Sjp=!LEkWA%ZL6kg95esV ze{rqetjVkuHCOuj<=o=j?A+vRrTf5>)Mbt7=0u@xj8bgsqHY=&q3Pimpp?r<_A!AtC`G}t%+rmAvO<^9T82pXmNJZ}xKP$mX464f z;W8p+c0KU`+X6z3%ebS=;WFCGbXS5cA&wSTg6*TstrpGRRDlg;T^4$fN{qRT`^)+; zs$7XdD%54%TSm7nF5_Ss-ANKW!0@56AwaXAS|PEw-@J|!!ZGqDFfpiezd78(fbS@A z8{q|p`?xL!gF(tO8VAsR2QVoNVW~NU0X~eCc*KQB&_z*v68XvG3T8zxb6C{;sQKV) zR65^FHtdhvk>9XCSpneedwoW%>G2q<(a;~?4G=AutikTvenv1OVFr4tKfa5-pX>rK z|Mpd^k(_;M{7_zG0WFlHq`~|G=MZo4_oo!`RxW>(L|q8_j6p9_xFg!iAl?GtoEhkY zqaZVne6-5uXaqjbh796ikZtH6&?A^(-zVfqMZ z*!v3khCGnzn|jiRjTG}!A~9xGh{U+L0*Q*Te)MuVhQ)2BxTnOpu|pkZgB1)0Z2kJ}+hQ5|GTd{{RD$Y{1iq*Q~AcTgqbFEUohd3`V&mD_W-zDXJ-h_%wEC zW?P52;49kKGs7g9slybQP?ek#!X^pt;+yfJui3eEyZ~sOlgvP^ zLp*35DhI7&#)OSrEY%OaS@6cENo3zB0d>prGBzwSZds;5O21|KB5M@lJipS`q&YT8 zx^Z8eh!alJs(BBW$0eA3xqa(L*5n@Ub7+;lND z&S;{B=6sO>FH&meE8}8d5JP|bDSVoLmWs?NP9(?335n5R20ZWYXGXM#=rW@=$}$G+ z0R3_5Is5q&We^FTW(I60F~&W)KmH^elB7*p$c`{LJWK|}M7iTamPopRyHCk;6N2_Z zA$3#9epZ8M&Ph}B36i+$aa!YUcHZLL=KP$~!{KtqdbrumTONsmAJVuLG01`9c${5P z`{$L^T^fh5h&@Tk#G-#;P(1~J!TwJSif(7H=<^Jg&MzmD~)DpGzS8`*W z$Dn8_gGEgYmOjNSOHTs064iglp!O((<@11H$b4MWptdm#8U5sov(_a9X%YZWu!u53|E! zWgDFWhG31B9|UU@9H2ZAWHk0;?ij!vf`EB0ni+ZrXV|Otq#> z(sy1Y1L8ELBUq#P62aP!0W87V7%GHd?NI;(Yp-B3-OorWSog-p6;-Dr$<6u4BmCpCn(LvP4Z|l=Usjif6d#t5hC>UN8tZ z1(8C9yBNg10JCl)F1TqcfLSXH4GKev4^k47I$|PEs7m&+7ve1>?4TRlM3L{4?4~OK z;HEBSAU6>Y+(hM2)Kn*I={qHJqNbxDrAJLItWk(l(2Skz zxK4(BX@b;q;6ykFPHrxe3o+Mm8uQ=GiQ)lld&C{!>L0ugpT&J0=W3Yum;}KS!q=Id zwE!9>kCE=g-UH^JM0q3Te^O%K-V<7J{G+K>m6qATZNBzAiNq;Q&zFqjsep<|{qa@A zbO>7ZbCQGk4QN>%zA=Yc82jZ^KN+C6kna+_RKw-Oh5+40>W$G-27@J}Ia!R)$#>47 zx=~k?Mroj$TZK`SRz{t~T!mse`y#HLFkz)KVLpi8%|lg$0Z9kj!AvMw7!Vf*B-wyL zHsB66Als_*;%}(*>h?19qD1Y#0U$*99D}0k7%b{%u=KY82oa7lR(%75S}e>ESiY3O z%4-48tkd)mF;Nf`*p$FND=?F=q}UrU;u8WJz|01@lguf^4auS&wNdO07h>&93bsL( zMW9SV)CUir;1ssT;vzLT#)P93LkrC`y<%Y+0VVA>*iiWP6cfb4M1}Ff1hrHSrM;;l5P|SAg_VL_Lg^Sq z9K2d#)uNq**$Cuc1Ta z4|LxlIMu8`5BMQQjmA&S53!|#LkyA!0L&p4EqeV@YTWA)z>g9c?KL2H`-v&>A5>PH z((t#?LU#Z{5$*j;DLjw(0`VI0J|P}skPMQRx1J;MQC5uk8YHZ%f?=?WFn*Rwte7vo zOpwn~DHr7vji04{o$VQALlTFFICqe%^ZIkdSsl6r)k)Mo2Y?=bkU`O528({fU}+}+ zdVG+v>a`4NKg(eG*BPv=0zg%^vi^bv0&5{G$-61Y(*;%|`nZERg#dQsm^j$SAlXj< zQy{Y>SGMaHW*i!`e^i*&!2IE#uo zO`IjnmT}gu=cvM?RB!VNPV)u~I*@~1!5cHQq%k(S6@WIy81N<(Mo*CPQs2F3nIUX& zD}%#c2BW-vCca;S!5#wsG$*?$O&}JEfWCegF{whI55q}i} zApYv+%`!q#@z(-Eu!RC(cK?dj7Rt6PX{5p2$T`F-;x8uFQu)Tb zbi*X#cb*y-&%@#q$dOw-EdK6EDlJ3jBnsk=Bp!AoNyxmH7MbMX67oP&Y}h0Q$znZ$ zFC2}Y)YC}lx}FfEUQB2$AU1juJjyM&A3o*a#uz<7^7o;9;p5B} z?MvlYTJ$y+XHgL<4v=L=vY$b`4`4P_qyo_HF#z)d5=_QVkm-pe@j*&rQpdQ+6RMIY zMJ0nIyof59C|bRgC%G9sYeA?u#talH5)bBRDu+VFj|m&O*slxs3SO}fwr_L-k}6cZ z8#@{q8*E<#DLqtN&Kl)58a=@1BC9;Vpkg^rB%I^KE4e%_!CXcTOj7r?hT+_^=Ob&f zjw2@CBRAh*U86BHmHB(6m$%lutope5`oB|YaYlJ-ZL7$DHz_sq6&Z99gLzP>(@{}# zgavuoGVhV9&3#C`{{Rd_pKVTZgqGmg5dP;tO+=af@hxmtQfDyeU~ssGj4I~BlU{1K z#2}HxMw{T_jW!`g8*QXUZM1DA34EOh?PA$zD?V2}Pkj}GrXcWf^a}NWuf}|V?{{lo zxfs+$(c26b{fGd4u?|lp@xT(#FU?zjPG%HbNzxgQ>l(!KXp_IsV8dLI_T2Gl2+HlU z^!+ky_95Du))O}Z&=(o#D>75&`P>ZjKrmKn&KHRMB1snc#1~ix%O5x2`Wd-QJxI)W z-lobEytqG~GJhoar|4@Fczg>Rf+gkv)s(&i@FhxEpVxn&=l`WtIrHW;%TnKW5f!KB z|D4ay+Yxc021Zkt}{J->lJ|DNE{SBHGxc$YKM~dTLMU#ziyB#0l@1Yzs zUwsAz;;}OYBJ{Nje6^7OT@ME`&;TX^#}wdHU9zQG%hX)qeU zEs#GY$ir{TBK~kBtnKa%wc7$cVf-rA-;O%?@l#msHvb-52Y#*z0{{Bf=BJqqfZ-ynX8>TmB>l0AWL+wQJFx8D}+*&V{~;qg0No3F>Fe(P-8 z8C-$9`A^Qw97MWd91$vD6}sOOfUTIvUnM%0 zw)3!cN$c)afUQ{HU4Y*M>;^1D0C5js1K>k|5x^$^4+6dlScRbWJcNnufL8%N4(I}G zcoy=2F9F^IxbQj116Bb(0T=;%74RV7dGjF$copD$+%~!Zs{p$J8vySCYz2G>@NU2- z2>u%KfK|^!z5sFvw5kYV^}PkK3h)lV2;lvI2Lb;T@Fl?i09^RrGc#`kRsk--@*DyD zG~hwNTL^y}@_>(H9=#v13Q_e-fD5I+^KRd$<;6fr@R6eC~k^J5Gvt#ADi3nNp4}u&-{&#ZZKTdS?7f+7-mq2$Q ze@Bk|`RHc@$X}KtpWaPF`Jc#<-+=rff_1>>nKM}8Udy~xkyp9Yz~HivvW^68!@m;Sqv zKX4lT2W5UP{f{Gm_%!-oLjD-?vB#OUf6YfvC3*fGWETIGA%EyJ`WvMD8#(m1BYyz% zQFWGl^2y!Ew>>*EGml~^ResC9v+p@8S@7lge~nx*9%+6$fz|qd)33mC@X>hsIrxU& z%-x^fME)@HSCe9;htjx6e&Kxd7vwJ|LYDk0V!){Xa*(1NldC*!L##r;z`REcp$fEyTQQ`_s&fpYrP#l>BvmJ@BCi{zo3LoTa zc@kIe4K0$mdN1fj5?AjfU#$2gyja56EnZI1eGgqyz4q3-Grfc#$afIX5X$q_caDQ0 zwp#c)neSlu5&qP)KS~AovJzjV5-yTZ0lujt#Oq~}x<}AuhT4~*TSB@%CV)1!$iXQ^ zw_PZ3W%rO&#P_=3ROMrPi0h+CemvJ=T(!%T#6uSdeO$OJMpMpOA31giR7|mas#@T@rp#!mmpB z4-$S~!ebKtLc-rkcuK;v7R&M_{Dg$7C2W##vxFTIvQsP{-ZG)bLON|y^;pCPG#T*8tj z2e`10BB58pAqj_-Kdumb_DTU&JxWO!*Sh-pPuW&%+KxA8Mr~E)HRV++E2E56+*wgo zZm%k@xLnZZvR1CFSSxu2Po;)8E$-QYH}e8ULIQTF6yCq-4+XXIp5BPR+*!ANWyIGh zvCf`oIlZN{ePy6sD<`ZAubI@!+xPT9pMa5&$ieGX!+4i%8sb47Uia!F0htPRN3?Q& zp>ufzZ;92)`L)L7p)OKRn}wm}J%Namq%u8MC*pbh5ZK@NSCv!%i+yn0eAZ|mJbZ^jkv z^FRGu3sEyt=}QqBgXY*0aEdc z;#2T8*a1|eLu!lUGl+UzZlC|5BAfGCE6_3~`Sj06XGYSMcr~Y??Zk1Q@&6o_B zR6IoT6!T^JkLpK0A^Yf3@nGRa0#|XKz(iRpP0+xfRo*VwRlAgTsESD;HNPo%Z-%@& z?dzscX+NENW0hBN&w!NgV{Nk^nesRdh{ukyU&XQNoF<#>SgG+PRjGb- zMMn8{kC!>@9>F*+`4v#*E4V5{UfmCAULj$p%2_TYr(jKnyxr$zZo5winK|T@%4?BN zx>Ws3+q|4r+QvYrQRE!PRFY5^;$`s zo`>^j)cCh%&cjn}HLla?ORXrUX?)GsUZ2U#pmi`WOT8#e$k&Rrp~a3gk#b2N&!9Uc zJ#*h~3+Q>4+xa6zr|-Bf;Y7eN;2Q~WvkaunSZh7kn^TZ7W|x~ zd$)U8#Rz|j@t;l4E6jg^wqm10atiQgrf2UD+4K~k{JbpvVFBB9;hcWBOwu#!TgiIn z_7fd+85*bA=?49LL<0Kt4yLPlKAeO99?4%S<0ZvUZ!gWJ|Gz-LB!7vvqRpG8zYy!| z1?WF&f1!+XHEp$|tNjQ?r~9I8`uBjI?L4Nw9Q^lzPW7G2sP7LYeMJU+g7sj&y2Qa2 z-X!h(3+T2itE`pu4WN@fYJO93;x@^z_DKdLe+=|X^D*vp z2UF@K{T|jM5exXH)T8z-_`5pDe>4aGQ%o<`4rTb^kCHx|K`(~EWdB$O{VGY1Wzcm= z@6Vvqp_SR%H=2X~Ak&L9dfzc!{2e^N@38)lrS^Fol!@z6qUSHxYJ6VC)dziNkz$d| z%ar;D${d`<-$6raTGG`%TA36qMZ8Y!-gl{kDKZSyYCtFdoXn{27SO33?UxIF8TM;I zsYmV4En{uCpJlp4Ea2;sU+p7aBJ;kLgMS=!vZpV@o>z15+YkU#y@ppfSTlc@3#rwT zuJ*t9yIG*OF@5ej9$-4FNc-3adN%+6Z4Ul#GC#&khW$Uv!7t9^E7n>v`17%OlC8g8 z3wkztKA(gCt2y}TygZus^foWow@}vl#T@(;pk^!gGSI1?j5jz~!_87pBl9oOwzheh zqV#V|y#6 z&DQ2+Zl&iQ(0QI*?qK@Y`BT##QuK`Y;h&iBZVmhJOyS9?4_@W1!Q#(V`0t4KnYiQja%7&wqnXaa87g zL?H|-L44lV=9L-*C<2|@Yam0<3eb5S{G@{!mEY)cb*3#x> zYN5>gHRxndX1|@3`ul7S=6p@^&%-7c*`uC=g(dwmNmtLcFpcn43p&-y%&6Bb%rBWN zphxMKe)h|}J9F?4fKL6>-sWXaRj+S=o~=JWB=xK3P%3VGQtGM6(DQ=iSI@PUb1B#> z&!NAfgvwp41-A=()cuZw>BZVeh9A64mr5<56LjitC096@s^ZemOFa`AdhV0_!3x3u zU8(DYr1xDe=q^eBHS3Xx1^fLC@yTjXC&xa_~n$w^_tplfEM} zzA5SIxvFZfo)ow5g>?3qUQc9)r;QHk4QuK^UJJ?NY47!j6BRw} zIB+qHXRa{~&p2^*DSpjYzIyE%oF>f=#m~D^l*s%v97K~5sO=DdZ z*%4etk91eIS60~9Y%iztahp4=KQOf5{3An;r)i_JxzW?Op@9x&<;u!*!)G=)o7dNa z$S2G4V_?|So=%YG2(EM8Sm$(kZft6DH@13Oopr88btI`ggmg=9lf{tmYVngqoCu4f zP!(&|(;a68$>P=GSCt)ZcWV{>%F^wwQNOcvZ~tItEy5?R9LlUF@2F8fpQIy7E$2Oh!&Fp6_$`8ZgseE3X$S$`u`wg-AV z(Xb!ACsXf6{JIl*#UZXfm}v1L*?QWumX#sYHQGoED#7QdrXMk#*7qtZ0^!X#FS%XT zh)YiQSw?l|WLj-b&kWPKvZOeRR;#DshRg%4Kfo!*e9$NA+arA@$8>wR*VEAdaShss)fo!K-y&d_i8&~2PhOJ{l0a7^!cWJzZg{c>0JOftpy9>!T`#>f$)L7vK; z-g_FL6DP)=`TXznHrkQaM(^`*R_!H4aD47Sui$2za|&*@vz60& zc4u0}GLFS1JJoU8nR7&z+3Euyq)cZ5f8aBnMPt8*Q`gUQ$h>RLByH*H+*MD1D)rnG z+`}1%1^doaLbEGvRL&j=efrbfXS+C$q3kpKdp?dEgN|J>_aO1PH6*wEzd00scKlJD zs?hn{Y09`7uS9UWtNEn}V)fp|FGHwkrAb3fW@*bsc?!CK72E&QGgHKAX>%d^qni6gN6q55uLIE-LlEk@mbUzirx+2$bUX6c?- ze&-If>h*LWI>eh>vU-?us1+>M(b#NtcUI#dcX;akbzZBPG^nz#SUWOTYpksG9h<|m zkrYm0pY76A->i|8>TOg~c#cj>mC{3{R18CkQBJyN=QK_#MsAJbri#v%Z}vxg6u(xI z_b84Op>DdKGX|?3YY5DDI~kT#Q8Z0GB-0t`QHAmX)n;uVyrDOe7C-yLSOhAn>U+Dp z@q!n8wU=tJJGPb&xA)U7NN?ve-9n_t9kU*%E|Af!M7#04d*k+7QFjb{ zKDoXv9OWBLOOVsxXFje%mbId}#f_uuQ&r&pmUWJ$v81L%swl5>vLlkzoH%t$OU^+X zu2|jF8`|v)weuLJW($*n7Ii>pU68%~Vfs#zLO0DcY*sYu0D?%?jxl$V;imUx@f&J4 zC$tP#RJ#2;qyC;Y9!pfEjPS8@Z8*9;+!hK1BTX@kuAQ`BfKV@+u8e-o+ITXVQ!bC9 zX1Z5e-`eb%-Cu!2X?La7x1H}{tfMLC0LkdLzAUz1^O+ z-ky%$&<-CODXi|&#o*x}$U}F74#zsz`nq~gWqDrNXyRvYOqRNM&r{fNO3f$fZWa0k2E zqh4{fA<$iqoitx45Ej#>*gCK(IZc4c4Ysy%XA~=iYBB2&MDfksDO=qgRq(Q>9shX6 tt*G(vYr7ihtzFIjaM;)BZ)(M0taL|wkwBX}62i;4u#e(#M`@Sj{{qgX79Rir diff --git a/Trie/trie.swift b/Trie/trie.swift index b8beb0293..4aa54d41f 100644 --- a/Trie/trie.swift +++ b/Trie/trie.swift @@ -53,6 +53,7 @@ public class Trie { self.root = Node(c: "") self.nodes = [] self.nodes.append(self.root) + self.wordList = [] } func find(key: String) -> (key: String, found: Bool) { @@ -104,11 +105,38 @@ public class Trie { return (w, true) } - func remove(w: String) { + func remove(w: String) -> (word: String, removed: Bool){ + var currentNode = self.root + + for c in w.characters { + if(currentNode.children[String(c)]) == nil{ + return (w, false) + } + + currentNode = currentNode.children[String(c)]! + + } + return (w, false) + + } + + func isEmpty() -> Bool { + return wordCount == 0 + } + + func count() -> Int { + return wordCount + } + + func getWords() -> [String] { + return wordList } + func contains(w: String) -> Bool { + return find(w).found + } } print("tests") From 2e12fbea4c2bc384a1689e3a6d6967615d6fe063 Mon Sep 17 00:00:00 2001 From: Thukor Date: Thu, 28 Apr 2016 14:17:25 -0400 Subject: [PATCH 0286/1679] Tweaked somethings --- Trie/trie | Bin 43930 -> 44196 bytes Trie/trie.swift | 12 ++++++++++++ 2 files changed, 12 insertions(+) diff --git a/Trie/trie b/Trie/trie index c4dc38f8f44778777f5a4f81f5e8b56679323a28..8160f90759b17a39108b47fd5e0fce35dd7a9ea0 100755 GIT binary patch delta 6060 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 delta 5662 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 a$0t!voy*f*mmla^ceG@b=f-QN Bool{ + return self.children.count == 0 + } //For Testing purposes func getParent() -> Node { return parent! @@ -137,6 +140,15 @@ public class Trie { func contains(w: String) -> Bool { return find(w).found } + + func isPrefix(w: String) -> Bool { + return true + } + + func findPrefix(w: String) -> (key: String, found: Bool) { + return (w, true) + } + } print("tests") From b879d555f81c8f918926263be83dd2a737e6ce65 Mon Sep 17 00:00:00 2001 From: Jayson Tung Date: Thu, 28 Apr 2016 14:49:31 -0400 Subject: [PATCH 0287/1679] Remove Fibonacci Heap --- Fibonacci Heap/README.markdown | 9 --------- README.markdown | 2 +- 2 files changed, 1 insertion(+), 10 deletions(-) delete mode 100644 Fibonacci Heap/README.markdown diff --git a/Fibonacci Heap/README.markdown b/Fibonacci Heap/README.markdown deleted file mode 100644 index c973701b2..000000000 --- a/Fibonacci Heap/README.markdown +++ /dev/null @@ -1,9 +0,0 @@ -# Fibonacci Heap - -Under construction. - -## See also - -[Fibonacci Heap on Wikipedia](https://en.wikipedia.org/wiki/Fibonacci_heap). - -*Written for the Swift Algorithm Club by Jayson Tung* diff --git a/README.markdown b/README.markdown index fa6e263bc..a6b492154 100644 --- a/README.markdown +++ b/README.markdown @@ -149,7 +149,7 @@ Most of the time using just the built-in `Array`, `Dictionary`, and `Set` types - [Segment Tree](Segment Tree/). Can quickly compute a function over a portion of an array. - kd-Tree - [Heap](Heap/). A binary tree stored in an array, so it doesn't use pointers. Makes a great priority queue. -- [Fibonacci Heap](Fibonacci\ Heap/) :construction: +- Fibonacci Heap - [Trie](Trie/) :construction: - [B-Tree](B Tree/) :construction: From 07f3856c0795d4369e7b15aa7dd2b6d59997712e Mon Sep 17 00:00:00 2001 From: Thukor Date: Thu, 28 Apr 2016 17:43:10 -0400 Subject: [PATCH 0288/1679] Bunch of stuff --- Trie/trie | Bin 44196 -> 50574 bytes Trie/trie.swift | 154 +++++++++++++++++++++++++++++------------------- 2 files changed, 94 insertions(+), 60 deletions(-) diff --git a/Trie/trie b/Trie/trie index 8160f90759b17a39108b47fd5e0fce35dd7a9ea0..a92296a75854658e2faea8776b4fa06b93878428 100755 GIT binary patch literal 50574 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 diff --git a/Trie/trie.swift b/Trie/trie.swift index b3cc9c381..d0b156933 100644 --- a/Trie/trie.swift +++ b/Trie/trie.swift @@ -1,13 +1,15 @@ public class Node { - var character: String? - var parent: Node? - var children: [String:Node] - var isAWord: Bool + private var character: String? + private var parent: Node? + private var children: [String:Node] + private var isAWord: Bool - init(c: String){ + + init(c: String?, p: Node?){ self.character = c self.children = [String:Node]() self.isAWord = false + self.parent = p } //Easier getter function, probably will make it more swift like @@ -15,7 +17,7 @@ public class Node { return self.character! } - func changeChar(c: String) -> Void { + func update(c: String?) -> Void { self.character = c } @@ -27,6 +29,13 @@ public class Node { return parent! } + func setParent(node: Node) -> Void { + self.parent = node + } + + func getChildAt(s: String) -> Node { + return self.children[s]! + } //Is this node marked as the end of a word? func isValidWord() -> Bool{ return self.isAWord @@ -44,18 +53,24 @@ public class Node { func isRoot() -> Bool { return self.character == "" } + + func numChildren() -> Int { + return self.children.count + } + + func getChildren() -> [String: Node] { + return self.children + } + } public class Trie { - var root = Node(c: "") - var nodes: [Node] - var wordList: [String] - var wordCount = 0 + private var root: Node + private var wordList: [String] + private var wordCount = 0 init() { - self.root = Node(c: "") - self.nodes = [] - self.nodes.append(self.root) + self.root = Node(c: "", p: nil) self.wordList = [] } @@ -72,33 +87,47 @@ public class Trie { return(key, currentNode.isValidWord()) } + func isEmpty() -> Bool { + return wordCount == 0 + } + + func count() -> Int { + return wordCount + } + + func getWords() -> [String] { + return wordList + } + + func contains(w: String) -> Bool { + return find(w.lowercaseString).found + } + + func isPrefix(w: String) -> Bool { + return true + } + func insert(w: String) -> (word: String, inserted: Bool) { + let word = w.lowercaseString var currentNode = self.root - var length = w.characters.count + var length = word.characters.count + + if self.contains(word) { + return (w, false) + } - for c in w.characters { + for c in word.characters { if currentNode.children[String(c)] != nil { currentNode = currentNode.children[String(c)]! length -= 1 } } - if length == 0 { - if(currentNode.isValidWord()) { - return (w, false) - } - - currentNode.isWord() - wordList.append(w) - wordCount += 1 - return (w, true) - } - - let choppedWord = String(w.characters.suffix(length)) + let remainingChars = String(word.characters.suffix(length)) - for c in choppedWord.characters { - currentNode.children[String(c)] = Node(c: String(c)) + for c in remainingChars.characters { + currentNode.children[String(c)] = Node(c: String(c), p: currentNode) currentNode = currentNode.children[String(c)]! } @@ -109,45 +138,40 @@ public class Trie { } func remove(w: String) -> (word: String, removed: Bool){ - var currentNode = self.root - for c in w.characters { - if(currentNode.children[String(c)]) == nil{ - return (w, false) - } - - currentNode = currentNode.children[String(c)]! + let word = w.lowercaseString + var currentNode = self.root + if(!self.contains(w)) { + return (w, false) } - return (w, false) - - - } - - func isEmpty() -> Bool { - return wordCount == 0 - } + for c in word.characters { + if currentNode.children[String(c)] != nil { + currentNode = currentNode.children[String(c)]! + } + } + var x = currentNode.char() + while currentNode.getParent().numChildren() == 1 { + currentNode = currentNode.getParent() + currentNode.children[x] = nil + x = currentNode.char() + } - func count() -> Int { - return wordCount - } + wordCount -= 1 - func getWords() -> [String] { - return wordList - } + var index = 0 + for item in wordList{ + if item == w { + wordList.removeAtIndex(index) + } + index += 1 + } - func contains(w: String) -> Bool { - return find(w).found + return (w, true) } - func isPrefix(w: String) -> Bool { - return true - } - func findPrefix(w: String) -> (key: String, found: Bool) { - return (w, true) - } } @@ -161,5 +185,15 @@ print(x.isValidWord())*/ var T: Trie = Trie() -print(T.insert("Hello")) -print(T.find("Hello")) +T.insert("Hello") +T.insert("Hey") +T.insert("YOLO") +T.insert("Him") +assert(T.count() == 4, "Count function failed") +assert(T.contains("Hey") == true) +assert(T.contains("Hello")==true) +print("trying remove") +T.remove("Him") +assert(T.count() == 3) +assert(T.contains("Him") == false, "Test failed") +assert(T.wordList.count == 3) From 3c985848500329311061a23df494c60e5baadf8c Mon Sep 17 00:00:00 2001 From: Thukor Date: Thu, 28 Apr 2016 17:44:31 -0400 Subject: [PATCH 0289/1679] Remove Counting Sort --- Counting-Sort/ReadMe.md | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 Counting-Sort/ReadMe.md diff --git a/Counting-Sort/ReadMe.md b/Counting-Sort/ReadMe.md deleted file mode 100644 index 30b7fbb98..000000000 --- a/Counting-Sort/ReadMe.md +++ /dev/null @@ -1,7 +0,0 @@ -# Counting Sort - -Under Construction. - -See also [Wikipedia](https://en.wikipedia.org/wiki/Counting_Sort). - -*Written for the Swift Algorithm Club by Christian Encarnacion* From 1d87ed163902d5c0b553a212ac7cbd072a5712f8 Mon Sep 17 00:00:00 2001 From: Thukor Date: Thu, 28 Apr 2016 17:48:36 -0400 Subject: [PATCH 0290/1679] Fixed Order of Deletion for Remove function in Trie class --- Trie/trie | Bin 50574 -> 50582 bytes Trie/trie.swift | 3 ++- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Trie/trie b/Trie/trie index a92296a75854658e2faea8776b4fa06b93878428..35d8d33f32d84a74c13e27100c3a12585bf2c19a 100755 GIT binary patch delta 12659 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 b=K`_$nzWW#FXs(ydFIgTVJ(jxxyJrK70)1o delta 12294 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 diff --git a/Trie/trie.swift b/Trie/trie.swift index d0b156933..bba82b357 100644 --- a/Trie/trie.swift +++ b/Trie/trie.swift @@ -29,7 +29,7 @@ public class Node { return parent! } - func setParent(node: Node) -> Void { + func setParent(node: Node?) -> Void { self.parent = node } @@ -154,6 +154,7 @@ public class Trie { var x = currentNode.char() while currentNode.getParent().numChildren() == 1 { currentNode = currentNode.getParent() + currentNode.children[x]!.setParent(nil) currentNode.children[x] = nil x = currentNode.char() } From f985b1bd2f2c5035e79420d4d392b4144f5c3b18 Mon Sep 17 00:00:00 2001 From: Thukor Date: Thu, 28 Apr 2016 17:55:20 -0400 Subject: [PATCH 0291/1679] Made some conditions more swift like --- Trie/trie | Bin 50582 -> 50497 bytes Trie/trie.swift | 16 ++++++++-------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Trie/trie b/Trie/trie index 35d8d33f32d84a74c13e27100c3a12585bf2c19a..9f97126c25ecb61209501230e7efeddd6f236300 100755 GIT binary patch delta 16863 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 delta 17515 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 lY+^~fd|GNkgkCe1M{6d@i{{lw9xwQZQ diff --git a/Trie/trie.swift b/Trie/trie.swift index bba82b357..4a06a30ae 100644 --- a/Trie/trie.swift +++ b/Trie/trie.swift @@ -118,8 +118,8 @@ public class Trie { } for c in word.characters { - if currentNode.children[String(c)] != nil { - currentNode = currentNode.children[String(c)]! + if let child = currentNode.children[String(c)] { + currentNode = child length -= 1 } } @@ -147,16 +147,16 @@ public class Trie { } for c in word.characters { - if currentNode.children[String(c)] != nil { - currentNode = currentNode.children[String(c)]! + if let child = currentNode.children[String(c)] { + currentNode = child } } - var x = currentNode.char() + var character = currentNode.char() while currentNode.getParent().numChildren() == 1 { currentNode = currentNode.getParent() - currentNode.children[x]!.setParent(nil) - currentNode.children[x] = nil - x = currentNode.char() + currentNode.children[character]!.setParent(nil) + currentNode.children[character] = nil + character = currentNode.char() } wordCount -= 1 From 0c2f57d8f41f1e9400785a8584997d62a52463dd Mon Sep 17 00:00:00 2001 From: Barbara Martina Rodeker Date: Fri, 29 Apr 2016 12:55:35 +0200 Subject: [PATCH 0292/1679] Update: example step by step and descr changes --- Bucket Sort/README.markdown | 68 ++++++++++++++++++++++++++++++++----- 1 file changed, 60 insertions(+), 8 deletions(-) diff --git a/Bucket Sort/README.markdown b/Bucket Sort/README.markdown index 576937359..398f76e34 100644 --- a/Bucket Sort/README.markdown +++ b/Bucket Sort/README.markdown @@ -1,20 +1,16 @@ # Bucket Sort -## Definition [Bucket Sort or Bin Sort](https://en.wikipedia.org/wiki/Bucket_sort) is a distributed sorting algorithm, which sort elements from an array by performing these steps: -1) Distribute the elements into buckets or bin. +1) Distribute the elements into buckets or bins. 2) Sort each bucket individually. 3) Merge the buckets in order to produce a sort array as results. -A more complete definition could be -> -Bucket sort, or bin sort, is a sorting algorithm that works by distributing the elements of an array into a number of buckets. Each bucket is then sorted individually, either using a different sorting algorithm, or by recursively applying the bucket sorting algorithm. It is a distribution sort, and is a cousin of radix sort in the most to least significant digit flavour. Bucket sort is a generalization of pigeonhole sort. Bucket sort can be implemented with comparisons and therefore can also be considered a comparison sort algorithm. The computational complexity estimates involve the number of buckets. [1](https://en.wikipedia.org/wiki/Bucket_sort) +See the algorithm in action [here](https://www.cs.usfca.edu/~galles/visualization/BucketSort.html) and [here](http://www.algostructure.com/sorting/bucketsort.php). -## Performance -Performance for execution time: +The performance for execution time is: | Case | Performance | |:-------------: |:---------------:| @@ -24,10 +20,13 @@ Performance for execution time: Where **n** = #elements and **k** = #buckets +On the **best case** the algorithm distributes the elements uniformily between buckets, a few elements are placed on each bucket and sorting the buckets is *O(1)*. Rearranging the elements is one more run through the initial list. +On the **worst case** the elements are sent all to the same bucket, making the process takes *O(n^2)*. + ## Pseudocode -A [pseudocode](https://en.wikipedia.org/wiki/Bucket_sort#Pseudocode) of the algorithm is as follows: +A [pseudocode](https://en.wikipedia.org/wiki/Bucket_sort#Pseudocode) of the algorithm can be as follows: function bucketSort(array, n) is buckets ← new array of n empty lists @@ -48,6 +47,59 @@ A [pseudocode](https://en.wikipedia.org/wiki/Bucket_sort#Pseudocode) of the algo ![sorting each bucket and merge](https://upload.wikimedia.org/wikipedia/commons/3/39/Bucket_sort_2.png) +##An example + +### Input + +Suppose we have the following list of elements: `[2, 56, 4, 77, 26, 98, 55]`. +And we define 10 buckets will be used. To determine the capacity of each bucket we need to know the `maximum element value`, in this case `98`. + +So the buckets are: +* `bucket 1`: from 0 to 9 +* `bucket 2`: from 10 to 19 +* `bucket 3`: from 20 to 29 +* and so on. + +### Distribution + +Now we need to choose a distribution function. + +`bucketNumber = ( elementValue / totalNumberOfBuckets) + 1` + +Such that applying that function we distribute all the elements in the buckets. +In our example it is like following: + +1. Apply the distribution function to `2`. `bucketNumber = (2 / 10) + 1 = 1` +2. Apply the distribution function to `56`. `bucketNumber = (56 / 10) + 1 = 6` +3. Apply the distribution function to `4`. `bucketNumber = (4 / 10) + 1 = 1` +4. Apply the distribution function to `77`. `bucketNumber = (77 / 10) + 1 = 8` +5. Apply the distribution function to `26`. `bucketNumber = (26 / 10) + 1 = 3` +6. Apply the distribution function to `98`. `bucketNumber = (98 / 10) + 1 = 10` +7. Apply the distribution function to `55`. `bucketNumber = (55 / 10) + 1 = 6` + +Our buckets will be filled now: + +**1** : `[2, 4]` +**2** : `[]` +**3** : `[26]` +**4** : `[]` +**5** : `[]` +**6** : `[55, 56]` +**7** : `[]` +**8** : `[77]` +**9** : `[]` +**10** : `[98]` + +We can choose to insert the elements in every bucket in order, or sort every bucket after distributing all the elements. + +### Put the elements back in the list + +Finally we go through all the buckets and put the elements back in the list: + + `[2, 4, 26, 55, 56, 77, 98]` + + + ##Swift implementation ###Classes From 3ead1ddc4923b8e7965690ccf4287a55275272c9 Mon Sep 17 00:00:00 2001 From: axptwig Date: Fri, 29 Apr 2016 11:33:09 -0400 Subject: [PATCH 0293/1679] Update RBTree.swift --- Red Black Trees/RBTree.swift | 225 ++++++++++++++++++++++++----------- 1 file changed, 153 insertions(+), 72 deletions(-) diff --git a/Red Black Trees/RBTree.swift b/Red Black Trees/RBTree.swift index 12f97b21f..33c165b4e 100644 --- a/Red Black Trees/RBTree.swift +++ b/Red Black Trees/RBTree.swift @@ -1,86 +1,167 @@ -public class RBTNode { - var color: Int? - var left: RBTNode? - var right: RBTNode? - var parent: RBTNode? - var data: Int - init(data: Int) { - self.data = data - self.left = nil - self.right = nil - self.parent = nil - self.color = nil - } - - public var isLeaf: Bool { - return left == nil && right == nil +public class RBTNode{ + private(set) public var color: Bool + private(set) public var left: RBTNode! + private(set) public var right: RBTNode! + private(set) public var parent: RBTNode! + private(set) public var data: Int + init(){ + self.data = -1 + self.color = true + self.left = nil + self.right = nil + self.parent = nil } - - public var isLeftChild: Bool { - return parent?.left === self - } - - public var isRightChild: Bool { - return parent?.right === self - } - - public var hasLeftChild: Bool { - return left != nil - } - - public var hasRightChild: Bool { - return right != nil - } - - public var hasAnyChild: Bool { - return hasLeftChild || hasRightChild - } - - public var hasBothChildren: Bool { - return hasLeftChild && hasRightChild + init(rootData: Int){ + self.data = rootData + self.color = true + self.left = nil + self.right = nil + self.parent = nil } } +public class RBTree { -extension RBTNode { - public func insert(value: Int) { - insert(value, parent: self) - } - private func insert(value: Int, parent: RBTNode) { - if value < self.data { - if let left = left { - left.insert(value, parent: left) - } else { - left = RBTNode(data: value) - left?.parent = parent + private(set) public var root: RBTNode? + init(rootData: Int) { + root = RBTNode(rootData: rootData) + } + init(){ + root = nil + } + public func depth()->Int{ + let n = depth(root!) + return n + } + private func depth(rooty:RBTNode?)->Int{ + if(rooty == nil){ + return 0 } - } else { - if let right = right { - right.insert(value, parent: right) - } else { - right = RBTNode(data: value) - right?.parent = parent + else{ + return 1+(max(depth(root!.left),depth(root!.right))) + } + } + + public func inOrder(){ + inOrder(root) + } + private func inOrder(root: RBTNode?){ + if(root == nil){ + print("nil") + return } + inOrder(root!.left) + print("Data: \(root!.data) Color: \(root!.color)") + inOrder(root!.right) } + + private func leftRotate(x: RBTNode) { + let newRoot = x.right + x.right = newRoot.left + if (newRoot.left !== nil) { + newRoot.left.parent = x + } + newRoot.parent = x.parent + if(x.parent === nil) { + root = newRoot + } else if (x === x.parent.left) { + x.parent.left = newRoot + } else { + x.parent.right = newRoot + } + newRoot.left = x + x.parent = newRoot } + private func rightRotate(x: RBTNode) { + let newRoot = x.left + x.left = newRoot.right + if newRoot.right !== nil { + newRoot.right.parent = x + } + newRoot.parent = x.parent + if x.parent === nil { + root = newRoot + } else if x === x.parent.right { + x.parent.right = newRoot + } else { + x.parent.left = newRoot + } + newRoot.right = x + x.parent = newRoot } -extension RBTNode{ - public func inOrder(root: RBTNode?){ - if(root == nil){ - return + + + private func insertFixup(){} + public func insert(value: Int) { + insert(value, parent: root!) + //insertFixUp() } - inOrder(root!.left) - print(root!.data) - inOrder(root!.right) - } + private func insert(value: Int, parent: RBTNode) { + if value < parent.data { + if let left = parent.left { + insert(value, parent: left) + } else { + parent.left = RBTNode(rootData: value) + parent.left?.parent = parent + } + } else { + if let right = parent.right { + insert(value, parent: right) + } else { + parent.right = RBTNode(rootData: value) + parent.right?.parent = parent + } + } + } + public func find(data: Int)->RBTNode?{ + return find(root!,data: data) + } + private func find(root: RBTNode, data: Int)->RBTNode?{ + if data == root.data{ + return root + } + if root.data != data && root.right == nil && root.left == nil { + return nil + } + else if data > root.data{ + return find(root.right, data: data) + } + else if data < root.data{ + return find(root.left, data: data) + } + else{ + return nil + } + } } -var me = RBTNode(data: 5) -var me2 = RBTNode(data: 6) +var tree = RBTree(rootData: 8) +tree.insert(9) +tree.insert(6) +tree.insert(5) +tree.insert(4) +tree.insert(3) +tree.inOrder() +print("_________________________") +let x = tree.root! +print("root: \(tree.root!.data)") +tree.rightRotate(x) +print("root: \(tree.root!.data)") +tree.inOrder() + +let t = tree.find(234) +if t == nil{ + print("ASDASD") +} +//how you access certain elements +//let root = tree.root!.left! +//if(root.parent === nil){ +// print("niggs") +//} +//else{ +// print(root.parent.data) +//} -me.insert(4) -me.insert(3) -me.insert(2) -me.insert(1) -me.insert(0) -me.inOrder(me) //stupid way to call this +//print(tree.root!.data) +//print(tree.root!.right!.data) +//print(tree.root!.left!.data) From c59f47500f12138a8e688e9022407e7fed2f54bd Mon Sep 17 00:00:00 2001 From: scalls Date: Fri, 29 Apr 2016 12:05:38 -0400 Subject: [PATCH 0294/1679] Removed debug prints --- Radix-Tree/RadixTree.swift | 17 +++++------------ Radix-Tree/main.swift | 5 ++++- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/Radix-Tree/RadixTree.swift b/Radix-Tree/RadixTree.swift index 994a38dbe..89c3cb7ef 100644 --- a/Radix-Tree/RadixTree.swift +++ b/Radix-Tree/RadixTree.swift @@ -28,8 +28,6 @@ class Root { } func printRoot() { - //print("children: \(children.count)") - //print("split at: \(children.count/2-1)") if (children.count > 1) { for c in 0...children.count/2-1 { children[c].printEdge() @@ -40,7 +38,6 @@ class Root { children[0].printEdge() } print("ROOT") - //print("second half starts at: \(children.count/2)") if children.count > 1 { for c in children.count/2...children.count-1 { children[c].printEdge() @@ -72,7 +69,6 @@ class Edge: Root { } func erase() { - print("Testing erase on: \(label)") self.parent = nil if children.count > 0 { for _ in 0...children.count-1 { @@ -80,7 +76,6 @@ class Edge: Root { children.remove(at: 0) } } - print("Removed: \(label)") } func printEdge() { @@ -268,10 +263,13 @@ class RadixTree { } func remove(_ str: String) -> Bool { - print("Tryna remove: \(str)") //You cannot remove the empty string from the tree if str == "" { - return false + for c in root.children { + c.erase() + root.children.remove(at: 0) + } + return true } //If the tree is empty, you cannot remove anything else if root.children.count == 0 { @@ -281,7 +279,6 @@ class RadixTree { var currEdge = root while (true) { var found = false - print("Search string: \(searchStr)") //If currEdge has no children, then the searchStr is not in the tree if currEdge.children.count == 0 { return false @@ -289,13 +286,9 @@ class RadixTree { for c in 0...currEdge.children.count-1 { //If the child's label matches the search string, remove that child // and everything below it in the tree - print("Looking at: \(currEdge.children[c].label)") if currEdge.children[c].label == searchStr { - print("MATCH FOUND") currEdge.children[c].erase() - print("ERASED WORKED") currEdge.children.remove(at: c) - print("EDGE LABEL MATCH REMOVE") return true } //Find the shared string diff --git a/Radix-Tree/main.swift b/Radix-Tree/main.swift index 6cffe1c20..ba1528046 100644 --- a/Radix-Tree/main.swift +++ b/Radix-Tree/main.swift @@ -47,4 +47,7 @@ radixWiki.printTree() print(radixWiki.remove("rub")) radixWiki.printTree() -print(radixWiki.remove("stevenson")) \ No newline at end of file +print(radixWiki.remove("stevenson")) + +print(radixWiki.remove("")) +radixWiki.printTree() \ No newline at end of file From 927cbf64ee2183982a6c7ad826f8c500eaed9e53 Mon Sep 17 00:00:00 2001 From: scalls Date: Fri, 29 Apr 2016 12:09:24 -0400 Subject: [PATCH 0295/1679] Added documentation for RadixTree.remove() --- Radix-Tree/README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Radix-Tree/README.markdown b/Radix-Tree/README.markdown index ef405bcb0..e187c806b 100644 --- a/Radix-Tree/README.markdown +++ b/Radix-Tree/README.markdown @@ -21,7 +21,7 @@ The insert function returns true if the String you are trying to insert was succ ### RadixTree.remove(_ str: String) -> Bool -THIS IS NOT IMPLEMENTED YET +The remove function returns true if the String is removed and false if the String is not in the tree. When a string is removed, any other Strings that have a prefix of the removed String are removed as well. For example, remove("rom") will also remove "roman", "rome", and "romulus" if those Strings are in the tree as well. Calling remove("") will remove all Strings in the tree. ### Root.level() -> Int From efe4d94c263fbc3f0d1295ab06cd783918f13101 Mon Sep 17 00:00:00 2001 From: scalls Date: Fri, 29 Apr 2016 12:16:27 -0400 Subject: [PATCH 0296/1679] Added credit to wikipedia for the image --- Radix-Tree/README.markdown | 1 + 1 file changed, 1 insertion(+) diff --git a/Radix-Tree/README.markdown b/Radix-Tree/README.markdown index e187c806b..ce1dde6b7 100644 --- a/Radix-Tree/README.markdown +++ b/Radix-Tree/README.markdown @@ -2,6 +2,7 @@ A radix tree is a tree where a node can have any number of children. Each edge leading from a node to a child has a label (usually a string). A radix tree is often used to store strings or IP addresses and by traversing from the root to any leaf in the tree, (by concatenating all the labels of edges along the way) you can find any string. This is a radix tree: ![](/Radix-Tree/Images/radixtree.png) +(Image from en.wikipedia.org) ## Implemenation From bcf9ade4ff49f467513cd67fdf08a218270fe454 Mon Sep 17 00:00:00 2001 From: scalls Date: Fri, 29 Apr 2016 12:54:16 -0400 Subject: [PATCH 0297/1679] Added more inline comments --- Radix-Tree/RadixTree.swift | 69 +++++++++++++++++++++++++++----------- Radix-Tree/main.swift | 2 ++ 2 files changed, 52 insertions(+), 19 deletions(-) diff --git a/Radix-Tree/RadixTree.swift b/Radix-Tree/RadixTree.swift index 89c3cb7ef..93ca95495 100644 --- a/Radix-Tree/RadixTree.swift +++ b/Radix-Tree/RadixTree.swift @@ -1,5 +1,6 @@ import Foundation +//The root is the top of the Radix Tree class Root { var children: [Edge] @@ -8,10 +9,14 @@ class Root { children = [Edge]() } + //The height functions returns the length (in number of edges) of the longest + // traversal down the tree func height() -> Int { + //Base case: no children: the tree has a height of 1 if children.count == 0 { return 1 } + //Recursion: find the max height of a root's child and return 1 + that max else { var max = 1 for c in children { @@ -23,11 +28,16 @@ class Root { } } + //The level function returns how far down in the tree a Root/Edge is + //A root's level is always 0 func level() -> Int { return 0 } + //printRoot is a recursive function that prints the tree for debugging/ + // visualization purposes func printRoot() { + //Print the first half of the children if (children.count > 1) { for c in 0...children.count/2-1 { children[c].printEdge() @@ -37,7 +47,9 @@ class Root { else if children.count > 0 { children[0].printEdge() } + //Then print the root print("ROOT") + //Print the second half of the children if children.count > 1 { for c in children.count/2...children.count-1 { children[c].printEdge() @@ -48,6 +60,7 @@ class Root { } } +//Edges are what actually store the Strings in the tree class Edge: Root { var parent: Root? @@ -58,19 +71,25 @@ class Edge: Root { super.init() } + //The Edge class overrides root's level function override func level() -> Int { + //Recurse up the tree incrementing level by one until the root is reached if parent != nil { return 1 + parent!.level() } + //If an edge has no parent, it's level is one + // NOTE: THIS SHOULD NEVER HAPPEN AS THE ROOT IS ALWAYS THE TOP OF THE TREE else { return 1 } } + //Erase erases a specific edge (and all edges below it in the tree) func erase() { self.parent = nil if children.count > 0 { + //For each child, erase it, then remove it from the children array for _ in 0...children.count-1 { children[0].erase() children.remove(at: 0) @@ -78,7 +97,10 @@ class Edge: Root { } } + //printEdge is used in printRoot to print the tree + // It follows a similar structure to printRoot func printEdge() { + //Print the first half of the edge's children if children.count > 1 { for c in 0...children.count/2-1 { children[c].printEdge() @@ -87,21 +109,17 @@ class Edge: Root { else if children.count > 0 { children[0].printEdge() } + //Tab over once up to the edge's level for x in 1...level() { if x == level() { print("|------>", terminator: "") } - else if x == 1 { - print("| ", terminator: "") - } - else if x == level()-1 { - print("| ", terminator: "") - } else { print("| ", terminator: "") } } print(label) + //Print the second half of the edge's children if children.count == 0 { for _ in 1...level() { print("| ", terminator: "") @@ -124,38 +142,47 @@ class RadixTree { root = Root() } + //Returns the height of the tree by calling the root's height function func height() -> Int { return root.height() - 1 } + //Inserts a string into the tree func insert(_ str: String) -> Bool { //Account for a blank input + // The empty string is already in the tree if str == "" { return false } - //Account for an empty tree - if root.children.count == 0 { - root.children.append( Edge(str) ) - return true - } + //searchStr is the parameter of the function + // it will be substringed as the function traverses down the tree var searchStr = str + //currEdge is the current Edge (or Root) in question var currEdge = root while (true) { var found = false + //If the current Edge has no children then the remaining searchStr is + // created as a child if currEdge.children.count == 0 { let newEdge = Edge(searchStr) currEdge.children.append(newEdge) newEdge.parent = currEdge + return true } + //Loop through all of the children for e in currEdge.children { - //Get the shared + //Get the shared prefix betweeen the child in question and the + // search string var shared = sharedPrefix(searchStr, e.label) var index = shared.startIndex - //The search string is equal to the shared string - //so the string already exists in the tree + //If the search string is equal to the shared string, + // the string already exists in the tree if searchStr == shared { return false } + //If the child's label is equal to the shared string, you have to + // traverse another level down the tree, so substring the search + // string, break the loop, and run it back else if shared == e.label { currEdge = e var tempIndex = searchStr.startIndex @@ -166,16 +193,18 @@ class RadixTree { found = true break } - //The child's label and the search string share a prefix + //If the child's label and the search string share a partial prefix, + // then both the label and the search string need to be substringed + // and a new branch needs to be created else if shared.characters.count > 0 { - //Cut the prefix off from both the search string and label var labelIndex = e.label.characters.startIndex //Create index objects and move them to after the shared prefix for _ in 1...shared.characters.count { index = index.successor() labelIndex = labelIndex.successor() } - //Substring both the search string and the label from the shared prefix + //Substring both the search string and the label from the + // shared prefix searchStr = searchStr.substringFromIndex(index) e.label = e.label.substringFromIndex(labelIndex) //Create 2 new edges and update parent/children values @@ -195,10 +224,10 @@ class RadixTree { e.children.append(newEdge2) return true } - //They don't share a prefix (go to next child) + //If they don't share a prefix, go to next child } + //If none of the children share a prefix, you have to create a new child if (!found) { - //No children share a prefix, so create a new child let newEdge = Edge(searchStr) currEdge.children.append(newEdge) newEdge.parent = currEdge @@ -207,6 +236,7 @@ class RadixTree { } } + //Tells you if a string is in the tree func find(_ str: String) -> Bool { //A radix tree always contains the empty string if str == "" { @@ -216,6 +246,7 @@ class RadixTree { else if root.children.count == 0 { return false } + //searchStr and currEdge have the same functionality as insert() var searchStr = str var currEdge = root while (true) { diff --git a/Radix-Tree/main.swift b/Radix-Tree/main.swift index ba1528046..6495e5e1b 100644 --- a/Radix-Tree/main.swift +++ b/Radix-Tree/main.swift @@ -13,6 +13,8 @@ radixWiki.insert("shoot") radixWiki.insert("shit") radixWiki.insert("starch") radixWiki.insert("steven") +radixWiki.insert("shart") +radixWiki.insert("shard") radixWiki.insert("compute") radixWiki.insert("compatible") From 2f209a30b81c657210b3d05090836678f014a837 Mon Sep 17 00:00:00 2001 From: scalls Date: Fri, 29 Apr 2016 13:01:48 -0400 Subject: [PATCH 0298/1679] Added more inline comments --- Radix-Tree/RadixTree.swift | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/Radix-Tree/RadixTree.swift b/Radix-Tree/RadixTree.swift index 93ca95495..6f1f8fa57 100644 --- a/Radix-Tree/RadixTree.swift +++ b/Radix-Tree/RadixTree.swift @@ -251,6 +251,7 @@ class RadixTree { var currEdge = root while (true) { var found = false + //Loop through currEdge's children for c in currEdge.children { //First check if the search string and the child's label are equal // if so the string is in the tree, return true @@ -260,8 +261,8 @@ class RadixTree { //If that is not true, find the shared string b/t the search string // and the label var shared = sharedPrefix(searchStr, c.label) - //If the shared string is equal to the label, update the curent node - // and run it back + //If the shared string is equal to the label, update the curent node, + // break the loop, and run it back if shared == c.label { currEdge = c var tempIndex = searchStr.startIndex @@ -272,7 +273,7 @@ class RadixTree { found = true break } - //If the shared string is empty, go to the next children + //If the shared string is empty, go to the next child else if shared.characters.count == 0 { continue } @@ -287,14 +288,16 @@ class RadixTree { return false } } + //If nothing was found, return false if !found { return false } } } + //Removes a string from the tree func remove(_ str: String) -> Bool { - //You cannot remove the empty string from the tree + //Removing the empty string removes everything in the tree if str == "" { for c in root.children { c.erase() @@ -306,6 +309,7 @@ class RadixTree { else if root.children.count == 0 { return false } + //searchStr and currEdge have the same functionality as in insert() and find() var searchStr = str var currEdge = root while (true) { @@ -314,6 +318,7 @@ class RadixTree { if currEdge.children.count == 0 { return false } + //Loop through the children for c in 0...currEdge.children.count-1 { //If the child's label matches the search string, remove that child // and everything below it in the tree @@ -343,6 +348,7 @@ class RadixTree { } } + //Prints the tree by calling the root's print function func printTree() { root.printRoot() } From 7fc446a8c1527b298c5e1f00bb5bec91b29454cb Mon Sep 17 00:00:00 2001 From: Thukor Date: Fri, 29 Apr 2016 15:06:27 -0400 Subject: [PATCH 0299/1679] Implemented print Trie, but encountered insert bug --- Trie/trie | Bin 50497 -> 55843 bytes Trie/trie.swift | 106 +++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 101 insertions(+), 5 deletions(-) diff --git a/Trie/trie b/Trie/trie index 9f97126c25ecb61209501230e7efeddd6f236300..352d06dbbdcbd17995b5c5478ae75c2b2d1272d1 100755 GIT binary patch literal 55843 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 literal 50497 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 diff --git a/Trie/trie.swift b/Trie/trie.swift index 4a06a30ae..12800315b 100644 --- a/Trie/trie.swift +++ b/Trie/trie.swift @@ -62,6 +62,28 @@ public class Node { return self.children } + func printNode(var indent: String, leaf: Bool) -> Void { + + print(indent, terminator: "") + if(leaf) { + print("\\-", terminator: "") + indent += " " + } + else { + print("|-", terminator: "") + indent += "| " + } + + print(self.char()) + + var i = 0 + for (_, node) in self.children { + node.printNode(indent, leaf: i == self.getChildren().count-1) + i+=1 + } + + } + } public class Trie { @@ -103,8 +125,26 @@ public class Trie { return find(w.lowercaseString).found } - func isPrefix(w: String) -> Bool { - return true + func isPrefix(w: String) -> (node: Node?, found: Bool) { + var currentNode = self.root + + let word = w.lowercaseString + if !self.contains(w) { + return (nil,false) + } + + for c in word.characters { + if let child = currentNode.children[String(c)] { + print("I make it here") + currentNode = child + } + } + + if currentNode.getChildren().count > 0 { + return (currentNode, true) + } + + return (nil, false) } func insert(w: String) -> (word: String, inserted: Bool) { @@ -118,7 +158,9 @@ public class Trie { } for c in word.characters { + print(c) if let child = currentNode.children[String(c)] { + print(child.char()) currentNode = child length -= 1 } @@ -172,7 +214,51 @@ public class Trie { return (w, true) } + private func getChildrenWithPrefix(node: Node, var word: String, var words: [String]) -> [String] { + + if node.isLeaf() { + word += node.char() + words.append(word) + + } + + for (child, n) in node.getChildren() { + word += child + getChildrenWithPrefix(n, word: word, words: words) + } + + return words + } + + func findPrefix(p: String) -> [String] { + if self.isPrefix(p).found { + print("here") + return getChildrenWithPrefix(self.isPrefix(p).node!, word: "", words: []) + } + + return [] + } + + + private func removeAllHelper(node: Node, w: String) { + + if(node.getChildren().count == 0) { + + } + + + + } + + + func removeAll(w: String) { + + } + + func printTrie() { + self.root.printNode("", leaf: true) + } } @@ -186,15 +272,25 @@ print(x.isValidWord())*/ var T: Trie = Trie() -T.insert("Hello") +/*T.insert("Hello") T.insert("Hey") T.insert("YOLO") T.insert("Him") assert(T.count() == 4, "Count function failed") assert(T.contains("Hey") == true) -assert(T.contains("Hello")==true) +assert(T.contains("Hello") == true) print("trying remove") T.remove("Him") assert(T.count() == 3) assert(T.contains("Him") == false, "Test failed") -assert(T.wordList.count == 3) +assert(T.wordList.count == 3)*/ + + +//T.insert("Hello") +//T.insert("Hi") +T.insert("Hey") +//T.insert("Hallo") +T.insert("Henry") +T.printTrie() +//assert(T.contains("He") == true) +//print(T.findPrefix("H")) From 16ee33f94944cc68b0b459fee9f0a2b165d79339 Mon Sep 17 00:00:00 2001 From: Thukor Date: Fri, 29 Apr 2016 16:30:55 -0400 Subject: [PATCH 0300/1679] Fixed a bug in the insert function --- Trie/trie | Bin 55843 -> 55991 bytes Trie/trie.swift | 17 +++++++++-------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/Trie/trie b/Trie/trie index 352d06dbbdcbd17995b5c5478ae75c2b2d1272d1..640d11ed4f90f1f725c18d7ff50bfca6d283926d 100755 GIT binary patch delta 17037 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 D_CSGv delta 16946 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 b!iH60br(<6bg|s|sL)Tx*M0r&2i^Y%q`|q7 diff --git a/Trie/trie.swift b/Trie/trie.swift index 12800315b..0ea606908 100644 --- a/Trie/trie.swift +++ b/Trie/trie.swift @@ -157,17 +157,18 @@ public class Trie { return (w, false) } - for c in word.characters { - print(c) - if let child = currentNode.children[String(c)] { - print(child.char()) - currentNode = child - length -= 1 - } + var index = 0 + var c = Array(word.characters)[index] + + while let child = currentNode.children[String(c)] { + currentNode = child + length -= 1 + index += 1 + c = Array(word.characters)[index] } let remainingChars = String(word.characters.suffix(length)) - + print(remainingChars) for c in remainingChars.characters { currentNode.children[String(c)] = Node(c: String(c), p: currentNode) currentNode = currentNode.children[String(c)]! From bd7398bfed9491c075af79217adf799322cdfd95 Mon Sep 17 00:00:00 2001 From: Thukor Date: Fri, 29 Apr 2016 18:02:34 -0400 Subject: [PATCH 0301/1679] Fixed a bug where Remove was removing one node less than it should have. --- Trie/trie | Bin 55991 -> 60243 bytes Trie/trie.swift | 37 ++++++++++++++++++++++++------------- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/Trie/trie b/Trie/trie index 640d11ed4f90f1f725c18d7ff50bfca6d283926d..bb9ae602fe57355dc14252eafd3f27d85b53f7b5 100755 GIT binary patch literal 60243 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 CXuo6t delta 21044 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 (word: String, removed: Bool){ let word = w.lowercaseString - var currentNode = self.root if(!self.contains(w)) { return (w, false) } + var currentNode = self.root for c in word.characters { - if let child = currentNode.children[String(c)] { - currentNode = child - } + currentNode = currentNode.getChildAt(String(c)) } - var character = currentNode.char() - while currentNode.getParent().numChildren() == 1 { - currentNode = currentNode.getParent() - currentNode.children[character]!.setParent(nil) - currentNode.children[character] = nil - character = currentNode.char() + + if currentNode.numChildren() > 0 { + currentNode.isNotWord() + } else { + var character = currentNode.char() + while(currentNode.numChildren() < 1) { + currentNode = currentNode.getParent() + print(currentNode.char()) + currentNode.children[character]!.setParent(nil) + currentNode.children[character]!.update(nil) + currentNode.children[character] = nil + character = currentNode.char() + + } } wordCount -= 1 @@ -288,10 +294,15 @@ assert(T.wordList.count == 3)*/ //T.insert("Hello") -//T.insert("Hi") +T.insert("Hi") T.insert("Hey") //T.insert("Hallo") T.insert("Henry") T.printTrie() -//assert(T.contains("He") == true) -//print(T.findPrefix("H")) +assert(T.contains("Henry") == true) +T.remove("Henry") +assert(T.contains("Henry") == false) +//assert(T.count() == 4) +assert(T.isPrefix("Hen").found == false) +T.printTrie() +print(T.findPrefix("H")) From 8fe2ec240dfc325f64ad8cb0b0561c4bcab47dda Mon Sep 17 00:00:00 2001 From: Thukor Date: Fri, 29 Apr 2016 18:04:48 -0400 Subject: [PATCH 0302/1679] Removed some debugging print statements --- Trie/trie.swift | 2 -- 1 file changed, 2 deletions(-) diff --git a/Trie/trie.swift b/Trie/trie.swift index f4e9913d5..6faf2e655 100644 --- a/Trie/trie.swift +++ b/Trie/trie.swift @@ -135,7 +135,6 @@ public class Trie { for c in word.characters { if let child = currentNode.children[String(c)] { - print("I make it here") currentNode = child } } @@ -199,7 +198,6 @@ public class Trie { var character = currentNode.char() while(currentNode.numChildren() < 1) { currentNode = currentNode.getParent() - print(currentNode.char()) currentNode.children[character]!.setParent(nil) currentNode.children[character]!.update(nil) currentNode.children[character] = nil From aa32c46b5aa44f95f1e11b6c9556e71663180444 Mon Sep 17 00:00:00 2001 From: Thukor Date: Mon, 2 May 2016 11:47:08 -0400 Subject: [PATCH 0303/1679] Added a merge function, still debugging findPrefix --- Trie/trie | Bin 60243 -> 61374 bytes Trie/trie.swift | 96 ++++++++++++++++++++++++++++++------------------ 2 files changed, 60 insertions(+), 36 deletions(-) diff --git a/Trie/trie b/Trie/trie index bb9ae602fe57355dc14252eafd3f27d85b53f7b5..6df0edeec95fbb06b251185dd4af79c852fd0a9e 100755 GIT binary patch literal 61374 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 literal 60243 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 CXuo6t diff --git a/Trie/trie.swift b/Trie/trie.swift index 6faf2e655..4169bd208 100644 --- a/Trie/trie.swift +++ b/Trie/trie.swift @@ -62,6 +62,7 @@ public class Node { return self.children } + func printNode(var indent: String, leaf: Bool) -> Void { print(indent, terminator: "") @@ -96,17 +97,36 @@ public class Trie { self.wordList = [] } - func find(key: String) -> (key: String, found: Bool) { + init(wordList: Set) { + + self.root = Node(c: "", p: nil) + self.wordList = [] + + for word in wordList { + let op = self.insert(word) + if(op.inserted){ + self.wordList.append(word) + } + } + } + + func merge(other: Trie) -> Trie{ + let newWorldList = Set(self.getWords() + other.getWords()) + + return Trie(wordList: newWorldList) + } + + func find(key: String) -> (node: Node?, found: Bool) { var currentNode = self.root for c in key.characters { if currentNode.children[String(c)] == nil { - return(key, false) + return(nil, false) } currentNode = currentNode.children[String(c)]! } - return(key, currentNode.isValidWord()) + return(currentNode, currentNode.isValidWord()) } func isEmpty() -> Bool { @@ -125,21 +145,20 @@ public class Trie { return find(w.lowercaseString).found } - func isPrefix(w: String) -> (node: Node?, found: Bool) { - var currentNode = self.root + func isPrefix(p: String) -> (node: Node?, found: Bool) { + let prefixP = p.lowercaseString - let word = w.lowercaseString - if !self.contains(w) { - return (nil,false) - } + var currentNode = self.root - for c in word.characters { - if let child = currentNode.children[String(c)] { - currentNode = child + for c in prefixP.characters { + if currentNode.children[String(c)] == nil{ + return (nil, false) } + + currentNode = currentNode.children[String(c)]! } - if currentNode.getChildren().count > 0 { + if currentNode.numChildren() > 0 { return (currentNode, true) } @@ -167,7 +186,6 @@ public class Trie { } let remainingChars = String(word.characters.suffix(length)) - print(remainingChars) for c in remainingChars.characters { currentNode.children[String(c)] = Node(c: String(c), p: currentNode) currentNode = currentNode.children[String(c)]! @@ -196,7 +214,7 @@ public class Trie { currentNode.isNotWord() } else { var character = currentNode.char() - while(currentNode.numChildren() < 1) { + while(currentNode.numChildren() == 0) { currentNode = currentNode.getParent() currentNode.children[character]!.setParent(nil) currentNode.children[character]!.update(nil) @@ -221,25 +239,32 @@ public class Trie { private func getChildrenWithPrefix(node: Node, var word: String, var words: [String]) -> [String] { - if node.isLeaf() { - word += node.char() + print(word) + if node.isLeaf() && node.isValidWord() { words.append(word) + print(words) - } + } else { - for (child, n) in node.getChildren() { - word += child - getChildrenWithPrefix(n, word: word, words: words) + for (child, n) in node.getChildren(){ + print(child) + word += child + getChildrenWithPrefix(n, word: word, words: words) + } } return words } func findPrefix(p: String) -> [String] { + print("Entered") + + + //var (node, pFound: Bool) = self.isPrefix(p) if self.isPrefix(p).found { - print("here") - return getChildrenWithPrefix(self.isPrefix(p).node!, word: "", words: []) + print("I found the prefix!") + return getChildrenWithPrefix(self.isPrefix(p).node!, word: p.lowercaseString, words: []) } return [] @@ -277,6 +302,16 @@ print(x.isValidWord())*/ var T: Trie = Trie() +T.insert("Hello") +T.insert("Hi") +T.insert("Hey") +T.insert("Hallo") +T.insert("Henry") +var U: Trie = Trie(wordList: Set(["Hey", "HO", "hello", "yolo"])) +var V: Trie = T.merge(U) +T.printTrie() +U.printTrie() +V.printTrie() /*T.insert("Hello") T.insert("Hey") T.insert("YOLO") @@ -290,17 +325,6 @@ assert(T.count() == 3) assert(T.contains("Him") == false, "Test failed") assert(T.wordList.count == 3)*/ - -//T.insert("Hello") -T.insert("Hi") -T.insert("Hey") -//T.insert("Hallo") -T.insert("Henry") -T.printTrie() -assert(T.contains("Henry") == true) -T.remove("Henry") -assert(T.contains("Henry") == false) -//assert(T.count() == 4) -assert(T.isPrefix("Hen").found == false) T.printTrie() -print(T.findPrefix("H")) +print(T.find("")) +//print(T.findPrefix("H")) From 3a7f20d1f9dc0a8c208e9630740aca16cf0d77c0 Mon Sep 17 00:00:00 2001 From: Matthijs Hollemans Date: Mon, 2 May 2016 20:10:08 +0200 Subject: [PATCH 0304/1679] Small tweaks to the text --- Bucket Sort/BucketSort.swift | 2 +- Bucket Sort/README.markdown | 252 ++++++++++++++++++----------------- README.markdown | 2 +- 3 files changed, 131 insertions(+), 125 deletions(-) diff --git a/Bucket Sort/BucketSort.swift b/Bucket Sort/BucketSort.swift index 0c75ce40a..c28eb0284 100644 --- a/Bucket Sort/BucketSort.swift +++ b/Bucket Sort/BucketSort.swift @@ -28,7 +28,7 @@ import Foundation /** - Perform buckets srot algorithm on the given input elements. + Performs bucket sort algorithm on the given input elements. [Bucket Sort Algorithm Reference](https://en.wikipedia.org/wiki/Bucket_sort) - Parameter elements: Array of Sortable elements diff --git a/Bucket Sort/README.markdown b/Bucket Sort/README.markdown index 398f76e34..f6e318c1f 100644 --- a/Bucket Sort/README.markdown +++ b/Bucket Sort/README.markdown @@ -1,15 +1,13 @@ # Bucket Sort -[Bucket Sort or Bin Sort](https://en.wikipedia.org/wiki/Bucket_sort) is a distributed sorting algorithm, which sort elements from an array by performing these steps: +Bucket Sort, also known as Bin Sort, is a distributed sorting algorithm, which sort elements from an array by performing these steps: 1) Distribute the elements into buckets or bins. 2) Sort each bucket individually. -3) Merge the buckets in order to produce a sort array as results. - +3) Merge the buckets in order to produce a sorted array as the result. See the algorithm in action [here](https://www.cs.usfca.edu/~galles/visualization/BucketSort.html) and [here](http://www.algostructure.com/sorting/bucketsort.php). - The performance for execution time is: | Case | Performance | @@ -18,11 +16,11 @@ The performance for execution time is: | Best | Omega(n + k) | | Average | Theta(n + k) | -Where **n** = #elements and **k** = #buckets +Where **n** = the number of elements and **k** is the number of buckets. -On the **best case** the algorithm distributes the elements uniformily between buckets, a few elements are placed on each bucket and sorting the buckets is *O(1)*. Rearranging the elements is one more run through the initial list. -On the **worst case** the elements are sent all to the same bucket, making the process takes *O(n^2)*. +In the *best case*, the algorithm distributes the elements uniformily between buckets, a few elements are placed on each bucket and sorting the buckets is **O(1)**. Rearranging the elements is one more run through the initial list. +In the *worst case*, the elements are sent all to the same bucket, making the process take **O(n^2)**. ## Pseudocode @@ -39,22 +37,22 @@ A [pseudocode](https://en.wikipedia.org/wiki/Bucket_sort#Pseudocode) of the algo ## Graphically explained -###Distribute elements in buckets +1) Distribute elements in buckets: ![distribution step](https://upload.wikimedia.org/wikipedia/commons/6/61/Bucket_sort_1.png) -###Sorting inside every bucket and merging +2) Sorting inside every bucket and merging: ![sorting each bucket and merge](https://upload.wikimedia.org/wikipedia/commons/3/39/Bucket_sort_2.png) -##An example +## An example ### Input -Suppose we have the following list of elements: `[2, 56, 4, 77, 26, 98, 55]`. -And we define 10 buckets will be used. To determine the capacity of each bucket we need to know the `maximum element value`, in this case `98`. +Suppose we have the following list of elements: `[2, 56, 4, 77, 26, 98, 55]`. Let's use 10 buckets. To determine the capacity of each bucket we need to know the *maximum element value*, in this case `98`. So the buckets are: + * `bucket 1`: from 0 to 9 * `bucket 2`: from 10 to 19 * `bucket 3`: from 20 to 29 @@ -64,10 +62,11 @@ So the buckets are: Now we need to choose a distribution function. -`bucketNumber = ( elementValue / totalNumberOfBuckets) + 1` +`bucketNumber = (elementValue / totalNumberOfBuckets) + 1` -Such that applying that function we distribute all the elements in the buckets. -In our example it is like following: +Such that by applying that function we distribute all the elements in the buckets. + +In our example it is like the following: 1. Apply the distribution function to `2`. `bucketNumber = (2 / 10) + 1 = 1` 2. Apply the distribution function to `56`. `bucketNumber = (56 / 10) + 1 = 6` @@ -99,87 +98,95 @@ Finally we go through all the buckets and put the elements back in the list: `[2, 4, 26, 55, 56, 77, 98]` +## Swift implementation -##Swift implementation +Here is a diagram that shows the functions, data structures and protocols for our bucker sort implementation: -###Classes +![classes](Docs/BucketSort.png) -![classes](https://github.com/barbaramartina/swift-algorithm-club/blob/BucketSort/Bucket%20Sort/Docs/BucketSort.png) +#### Main function -###Code +`bucketSort()` is a generic function that can apply the algorithm to any element of type `T`, as long as `T` is `Sortable`. -Bucket Sort implementation use the following functions, data structures and protocols: +```swift +public func bucketSort(elements: [T], + distributor: Distributor, + sorter: Sorter, + buckets: [Bucket]) -> [T] { + precondition(allPositiveNumbers(elements)) + precondition(enoughSpaceInBuckets(buckets, elements: elements)) -####Main function + var bucketsCopy = buckets + for elem in elements { + distributor.distribute(elem, buckets: &bucketsCopy) + } -`bucketSort` is a generic function that can apply the algorithm to any element of type T, as long as T is Sortable. + var results = [T]() - public func bucketSort(elements: [T], distributor: Distributor,sorter: Sorter, buckets: [Bucket]) -> [T] { - precondition(allPositiveNumbers(elements)) - precondition(enoughSpaceInBuckets(buckets, elements: elements)) - - var bucketsCopy = buckets - for elem in elements { - distributor.distribute(elem, buckets: &bucketsCopy) - } - - var results = [T]() - - for bucket in bucketsCopy { - results += bucket.sort(sorter) - } - - return results - } + for bucket in bucketsCopy { + results += bucket.sort(sorter) + } + return results +} +``` -####Bucket +#### Bucket - public struct Bucket { - var elements: [T] - let capacity: Int - - public init(capacity: Int) { - self.capacity = capacity - elements = [T]() - } - - public mutating func add(item: T) { - if (elements.count < capacity) { - elements.append(item) - } - } - - public func sort(algorithm: Sorter) -> [T] { - return algorithm.sort(elements) - } - } +```swift +public struct Bucket { + var elements: [T] + let capacity: Int -####Sortable + public init(capacity: Int) { + self.capacity = capacity + elements = [T]() + } - public protocol Sortable: IntConvertible, Comparable { - } + public mutating func add(item: T) { + if (elements.count < capacity) { + elements.append(item) + } + } -####IntConvertible + public func sort(algorithm: Sorter) -> [T] { + return algorithm.sort(elements) + } +} +``` -The algorithm is designed to sort integers, so all the elements to be sorted should be mapped to an integer value. +#### Sortable + +```swift +public protocol Sortable: IntConvertible, Comparable { +} +``` - public protocol IntConvertible { - func toInt() -> Int - } +#### IntConvertible + +The algorithm is designed to sort integers, so all the elements to be sorted should be mapped to an integer value. +```swift +public protocol IntConvertible { + func toInt() -> Int +} +``` -####Sorter +#### Sorter - public protocol Sorter { - func sort(items: [T]) -> [T] - } +```swift +public protocol Sorter { + func sort(items: [T]) -> [T] +} +``` -####Distributor +#### Distributor - public protocol Distributor { - func distribute(element: T, inout buckets: [Bucket]) - } +```swift +public protocol Distributor { + func distribute(element: T, inout buckets: [Bucket]) +} +``` ### Custom Sorter and Distributor @@ -187,56 +194,54 @@ The current implementation make use of the following implementations for *Sorter *Sorter* - public struct InsertionSorter: Sorter { - - public init() {} - - public func sort(items: [T]) -> [T] { - var results = items - for i in 0 ..< results.count { - var j = i - while ( j > 0 && results[j-1] > results[j]) { - - let auxiliar = results[j-1] - results[j-1] = results[j] - results[j] = auxiliar - - j -= 1 - } - } - return results - } - } +```swift +public struct InsertionSorter: Sorter { + public func sort(items: [T]) -> [T] { + var results = items + for i in 0 ..< results.count { + var j = i + while ( j > 0 && results[j-1] > results[j]) { + + let auxiliar = results[j-1] + results[j-1] = results[j] + results[j] = auxiliar + + j -= 1 + } + } + return results + } +} +``` *Distributor* - /* - * An example of a simple distribution function that send every elements to - * the bucket representing the range in which it fits.An - * - * If the range of values to sort is 0..<49 i.e, there could be 5 buckets of capacity = 10 - * So every element will be classified by the ranges: - * - * - 0 ..< 10 - * - 10 ..< 20 - * - 20 ..< 30 - * - 30 ..< 40 - * - 40 ..< 50 - * - * By following the formula: element / capacity = #ofBucket - */ - public struct RangeDistributor: Distributor { - - public init() {} - - public func distribute(element: T, inout buckets: [Bucket]) { - let value = element.toInt() - let bucketCapacity = buckets.first!.capacity - - let bucketIndex = value / bucketCapacity - buckets[bucketIndex].add(element) - } - } +```swift +/* + * An example of a simple distribution function that send every elements to + * the bucket representing the range in which it fits. + * + * If the range of values to sort is 0..<49 i.e, there could be 5 buckets of capacity = 10 + * So every element will be classified by the ranges: + * + * - 0 ..< 10 + * - 10 ..< 20 + * - 20 ..< 30 + * - 30 ..< 40 + * - 40 ..< 50 + * + * By following the formula: element / capacity = #ofBucket + */ +public struct RangeDistributor: Distributor { + public func distribute(element: T, inout buckets: [Bucket]) { + let value = element.toInt() + let bucketCapacity = buckets.first!.capacity + + let bucketIndex = value / bucketCapacity + buckets[bucketIndex].add(element) + } +} +``` ### Make your own version @@ -244,10 +249,11 @@ By reusing this code and implementing your own *Sorter* and *Distributor* you ca ## Other variations of Bucket Sort -The following are some of the variation to the General Bucket Sort implemented here: +The following are some of the variation to the general [Bucket Sort](https://en.wikipedia.org/wiki/Bucket_sort) implemented here: - [Proxmap Sort](https://en.wikipedia.org/wiki/Bucket_sort#ProxmapSort) - [Histogram Sort](https://en.wikipedia.org/wiki/Bucket_sort#Histogram_sort) - [Postman Sort](https://en.wikipedia.org/wiki/Bucket_sort#Postman.27s_sort) - [Shuffle Sort](https://en.wikipedia.org/wiki/Bucket_sort#Shuffle_sort) +*Written for Swift Algorithm Club by Barbara Rodeker. Images from Wikipedia.* diff --git a/README.markdown b/README.markdown index abbc39cc5..bbc10fb8d 100644 --- a/README.markdown +++ b/README.markdown @@ -72,7 +72,7 @@ Fast sorts: Special-purpose sorts: -- Bucket Sort +- [Bucket Sort](Bucket Sort/) :construction: - [Counting Sort](Counting Sort/) - Radix Sort - [Topological Sort](Topological Sort/) From 6ec2d66c80eea2b583fc06e770b8f34a74c42308 Mon Sep 17 00:00:00 2001 From: Thukor Date: Mon, 2 May 2016 14:39:40 -0400 Subject: [PATCH 0305/1679] Finished Remove all, fixed a duplication error in constructor --- Trie/trie | Bin 61374 -> 65115 bytes Trie/trie.swift | 49 +++++++++++++++++++++++------------------------- 2 files changed, 23 insertions(+), 26 deletions(-) diff --git a/Trie/trie b/Trie/trie index 6df0edeec95fbb06b251185dd4af79c852fd0a9e..f4fc8cdf7379094f875f742142542a09096220b0 100755 GIT binary patch literal 65115 zcmeFaeL$SWwLktOCWZ;gMHE~HoLR!%!0kW}RFp!s4(}ln$U7=!)t1|!;Re%1@uV3h9_x$Hnj6yg?yCry*^o*aDy%{onFS+PYa<(D+pEpBXRY6~q66|7jiV)>Fl^OB`fZ}KPY+ABAb+_3eSjWA_C4gbiR z=^s7(WApC=7ti_J@n^mC*!Tao=rq)1%_<)y-(d_rpc>JwAr-KgBj zDfq|GF;emG1pid@d!c|-^iQDkr^5dL<)*@Wp!ih$PlIAp;lBrbDn36;qleF@q5pIm zdD_$H|J!Nkmq2f+YIwsoHYD*q|w_*nsSGshgAGW)3n!;H2UdEGmhR) zQ|=pS_*AADM_&g%m7HIOoT>0Hr0Ji&G;)%M3;&Xzi_-Ly3)ASi7X2ZWJX2}v_3Je4 z*qlcH*FwNl?e$z5IrGxgcQg&XH%)te5Avtd+iK`JRefX7 zLn`{Or5TTPY2>*8d|ddK{B)<$!#io({n|AAbJEoJ(KLL1l*YbYk*42%GEM(1LWNw( zl|pYJ)vo=l^MJ!!`8r_<1f)6{G3NrsVSoNc)GS0~giTks2w zSQ7pv=rhY$V7Rq^XlJ?)fm4hVjR}{>MhQGg^GW7^iu8wh#@;&;=?(Z>fn5#TgKL^w z{cy7k-xb&UHu!fm1cLt7HH|fafIndP)>W1J>in%5T~)rOvAM}#RkN+pZ}@yWb~ZQp z0>PTrpwFjBQxjHIRqn{I@ZqT{4J=*ht7&X(uB{3BH#RjiH3S=K8XIo(*A=z4*4)t6 zTDp2y)!NFMkZ*MhcrxAaRh4h5tjt@sroN`NrWVp|YVhv@c5}r{bRci}n&!qve{Ha# zxvA=g7S^HaQ`fH#tgL8luJs23d3nCJra;Yhe^Kj>>(^Gc;Qvj5FWoeC3WjcdcFDz|4B8%z4XN{X3hl_ZJ04pzW0n zAtq4X;s#McP3sK>JN!-lR;YV>m5)_fHJ!9pr8KvOu4C=DL*0h-316!}Skus?BXxdh zG3gZRn$X~=70Pj{HQ!g$x}$beARn4swiJm_%1o(|3cUrEE?wPF*U+jOsiskoww56L zvPyq2S!if8I4!MD3l?Z>-c_uGqdZjbQop}#LnyGSj?+3xI^(s{}&kT*duGx@Dyn^*c&^Rm0GY1>fe^GUwx-Wj@aGmxv|`dwMl=-=sY z3i?{NUxx%4j^Mqy0%L(gGqB9Pp{8kve}liJv8L8fEzcZu9P{Ys?|aOv{X3MvjV=(hD1!cEq(1^6d&0__Qi++#ITO`=%9B=}YLL zm3h7p$1j_6Ca2|1{!ma_;yMRQ8SfR94S~EBrOmCoYFg_O2Ew$qllvTPjvgleTyrW} z9Swwju|1f#w1y_QtN|9brcoMNH@$5V8vQi^zgBj$vH|E)I~;v>+5n}pG7dddu}e|| zRh8S92Ydlv9sZNPl2_o{j^=JGX>Dz8Er-Rf+2Jp(lCB=C2{zPL23yfeFrdE5HlH$@ zR3e7*>b8c)U_%oukbj52Ro7!pbJO+y)?kC!YE=Tn$nf9Ly?}4Qw+GXw3SHw68a zmf-Rg!sA7=_Bw;18|+pdM(RFYRZ%p5yKc|~Q70@n#h*%^@%H4!neMKb7oEBl?{z+ns>I;v^E6P6iTBhGviXXuec#VP1MQw7sap<6~h*^(*~K` zq*+Q!0u?jt<&ON?=C-EbW^FbLz)z+V89agf7PM`U2D=9C!m5BDQq%;STQU2)(JOa0 zG^vA5m6`LWbSY7GUQ3(XhtBzrEHQ@3=FqgMiyN>TH~V1EV77ed100K?v_=$?PTQjC z!Jw^>)6;NTg6Y{SrF)dfN2an=7K8nc)11ToN)U(h-}F32k?g*0yIIn8g~hbnBP=Q_ z0|nliKs~!NGp;LrKi#j$%^v$c^W-s)=rXZNm{F4}LgzeKS9{S#+yGrcUwvmhw4=7x z7ho)p_*#Yc`54yT_)hw6OT=m{^|iD%2b*h~8-2CSP1~DWchY-<#iiSB`23t&;mU6d zOrx6Wj7#d9cls}>t%nVOf8KP7u)2QfC2fIL?$fF`LfEJ^)|RbXy~ek6$e2Y#IcA9LWZaNvg> z_)j?SBM$s}2Y%Fn=N^mwj5+WdY$TxNz*jl&6ArvOxlxIe4*VtuegDJN5}SqJB@Vpt zoz(d3eud|lV;=i)Iq=TWpXn{Gd9e8X##-9QQo@3H}JPtgzxZ;o3frsIUKNSu< zwzA^S76(2vjx~&G2i|!ARqw#hchI*u@L3Lg$bon6hqXKK&i$|s2cBnY_S5CSFR+n- zJr4Zo4t%cz&oesv>2u)Ew2^@Q4*b~;{GbDGpWQM!=D;s<&<{KCA9CPF9C()lKkC49 zPt|_L9QcpeNI=Vh&voD@9Qcnq@RJVwMGm~7`#JmV#SVOi1Mha=vmE%P4t%x)@0@^L z4*W_7eXavv;J~{b_*D*kfdl_B2j1hrf82rhI`Ee|@D&dHY6pIc17GaGS3B@)9r$_& zzRZDdap21x_>cpCr32sYz&q_;hXY^fpzm_vH#_j&J+EhYBXfWDMVH|X$AWXM*I;eD zdk$qhrHH2T|A?fi3*N-<{Bt}AF<#Ha@v$j97yOQKny&E?iNDM^P1bl!;x8~xQ#IZ% z@gFlz6E)r|@n;yvF10brv2X|l$vCH^hOX{yF6Bz`aB zG*ROoiGP)Gx-R2xiQmEaNsPNB-pM#k*Lar1KhHQ#*0>?@8yTO^_{86VxS*ABnyB$H ziC@b&P1E>@#J4ei3ga<}e~R%_8Sj_)2F7Wc#(O1x1>-bH<6RP8%{Wcbc)P?u#yDN3 z@fL|MWt=8yyjtQHGEP%8ULo=G7^f>W?veOejMF5IyCr@K<1|I%E{UJOI8D%amc(Z> zPSZ1PNc=BR#OZ>KPyCJb|0Clr#>XW7JI2ptd_>|eGkzZ9F^Rvx`1y?YOZ>--)8!iP zmH0D^({zn@N&Fz=biKygCH@%WG-2Z{68|>iG+pD>68{$CG+E;n62F&mx@hAbiGP)G znyzuT#P4AIV#Zw(?_`{=+jy45KhHR)?r}rnH!^++;}h>pP38T5o%!6Sz2?i_J+Dku zRINJ_Yrn%|c#j;&5^yBz0*_(sf}Y;oKK~pTgu#{jtBsA`#XQ&W?wOqDHGjKn_SUBc z!A}O^iAx4h2lJTMb0I$Z#n=LlF3GhK%HF|T>VYYuSidCh07*Z(>- zRWwL*Pz-!z?hioYjYL&)hV|c2sW)19;ZDOS8swlaHV-Ruunm!|c}2F@?Dm3PG3srG zIf$*FL-XFq0I^>4Sg*M$!)sodWqpolGh86(ZVqp+8O>#eFvRdihL{=oNKh7uDuQkf z`!e&HvPd^ckt16W&#g0KAY!UF5+=@T&dISJM;X>(j5n!gI16}d7o*Y442%@7Im;WF zh<@Mz&D8d1r|RV9D*7*ztkB=AOHa?LR!%&5T}MuimnlMvD6o?ZRoH;bc>=5MzW{61CdR8*e{ljgEqKuO9y?>#Yg_nsaoDUqL zkRU;n5#|_^9J_m!D2gV`6cME#q6p3$8fJEgvR;Y8sI^9kQkNu3jA>^mQ69NAMFWu_ zL6kw}*r-HlSE4AIFjGX7E{GyHbEu!$A<7|Uh)C2Ll+1IVk0ffPkBo178+6garKvBxZ-YjIZ7Ag8` zgkBGYBzjLaGPsZ-ml423WS&EcL=RRKPZDfgVKQ zG7%uUMYI)GAllBVY>+V>4l#U}3b!zPA?8wVB>%NATWi7H0A-Q64@xZa=w2d+m>;Hs zSuuj^88e>-g85-q6ymfTuUVXvVO{tZsbC8S#CCk`46u)8id~E@_#w@sIooMMs=>r+ zW2Wfbhm`ds${RV^8@Z#8MuUU=u-AMGc5(|-%y0$s6fsX^h+!0_@`Onsy+Yz<*h|Wf zKxay+Xnz#5UKPVMubE*LP^Hn#Re~K*wQSAyMvhlD&Ld>q1p=aOGCX{gWri7Mhc%B( z-99Xm4hhN(=aQ;l1Pn{YNR%j+_89Y;VV6X^vjs%6NFVz%*$qi~kpU8*lPQAk493iZ zP&!FzM+Nb;GU7~yJj96+Kgu$qb9Z#G`Jg>*A}28$Stlsj8MbBTN*o1C@?Vjh7xUh7 zh*RL!r#K&0!fCGeMvn7F)@PJO)@BuVuFv)!DH%nL;R%$CX=o81E}6gtv3s;EvT>{| zveoL`I^i{M%qlZCWS5zra<%_vR>!Auk!eISMRt!M)m?P-0H&0-;WD!%<~27Cdd-r4 zuUXz#+)@6`w&TGrW>tx9N(Q|VZUx7aU&g zLDKGF>%}*zCl(xXdm|f%y=H~m`ngad^@j*_mVXoSYdN2=<=k_q{_3qyb%{T*=ks4Z$wj;wY0AZq)F^*TJ`qQ{D$onrInMUQbEP;CB~2JIj@M=@ujnjj~Hq~#VM z*pyEcca}d=)cz8xT|NobjIu_Tu|w=RRIwGl&|YdBt`_{8J+D`L(T-?O^zzLvPv@>& z&(Xus)JEi@Q02p(jJw>uF9nuiBzH!;2*2I?`cRg26K^I(yA!1|I>7PxL?H6~=dLDlBQeiYJY z`K09C6V~>4BOoPG-iJC>vrZnnJ|3-KR0rL2ZFbSo7^^dhUInft7TApyca;2Esx)aG z3&x!#zwVpWb|R#W?4GpV{G(KIBC&rVpY*RW-M=Pv|N3=e|AK0E4-4yI>+u<^|9uAL zE3DU^L!RmWfwuTu0k}+BpMfCOt5`pwV{UFo$BZn<5U?ASIbdBZaxz>pVXY^hNXZ0N zvh(kZfn(Ozr?$(pB&oe!;O_?i3F}0~09pZ)J-a83Hq~JJx6NoUqc*w0ex(YeB&w|} z>+v@z0|Y;)G-yE#*Npy_CB>mJtcXqjc?qC-A~(BH3Ggg+Tf24jte_pBK2*(QeG%`! zCQZjL(8lPGZ8Cl=w{XO$h+I{m()z81#6>w;HiCX5Ac@=1-F71*Tut_~U0A+)BbnCC zGWY!pfH%ti{R>d{A!q+OXnvcLsNZ^CiYY-lgm!4KwPuC}p9Ctg%ik?rSX-^ZUh9Sl zt-*F-46CwBmC%cNqnooq6WX(LEqab#|4<)?*Lr4wEUq8K4QKpa#`_>D(N7&<04q~F zXpR4Y@(?ZKy${J8?;w@&{!M$lW0e0}wPBRx#jvOmf8Y8LtD=lJv|B!M7?T7#@RxS8 zA7_RLXu+awG3$Jg7IhqewfcsxW?X*AJ3St*hBVgCvHyVauvYjin7oPX)Oc7Z!s_vG zxo8sOK}JGqekZEhq2)MQ#6A~oF4|PIv8bvN3%>$5gdM|=&Jr{AG#p;s`z^`=?e2Qvm(oSoO#V~J7~c!BtRT7tA;6&p)NsjT}2w(ZHt6k1dkQo z^Pns4+{Zc;9erw6+uZTzQCnHVVw$;#6^Ir-@@d0(l!n`UR+Iss@afNDc$llRQEWZ( zn$JLtY6PrYRh_$#r6lj^V)NM|oh3}V1P}Qc>#x5T`L`eij4A{~y<~F_QzAoTsT_UM zKz^Z#h$kn`&6%pW52LsuQ5|MV)&2gJ9HMNp!`7cbHU3ja#WtvHqg!WGY~sdv#XKld zDpo*=)(gMFA!JFa80nHKcAl!38!4z*u7IeEY=&Q#ijk$N7->*3p^0cu5Dnu|#jQed zMUPSU@roTL2VJqVP!GGYZf1^1;U%a5{3!OeUKSFWkEY3%;<~c{rfweuH>5J+HIMU} zn=`!T`YdY+`C=8XNDTo|aRZmXMm|HrBr-q(bSOp8JptEI`J&=Pno&y-+81Rid{N@0 zxvpgyM@lFGL{Nhz;w_N*BRU2uD}=JFKb^$n1$8%|Dv`_u1knLYBzg<(Jqh9KTJMNl zvOvc+%LLOS-ID?axPbtfx#a+1vjnKkj)>X>iR_adkjOr_r0IPU*)=JP-0v0SgDeSS zeH5U~`~$QzB8cd)fbN)pfk8u&)QeYwqik*g%JXp>_fHhXAavs7fft z;R=)s#VG!2$%f@M=s3Pq8cRd0Ud2XLtVP8r0@6Y%MoD0S+o@?4>_AXSRMLeYr2;_@ zf|LxwUIZx}f|%^Wln}vw>mImo-l*Ejigw4ODKOz;CH9PUzp8;CBSRyi|L7<{ac6i8 zps0NU#)UpuxJCF4)eDGL1Hj^JfPqC>jHwlWwjeNcBe1qIR}XEG94IkbA)#)sfB_GH zRXom|bjzc?Qu@hiu~vY@sXMaB%?!Iq`PCCxRQ`#(TmTE6xSn8$DRig)+aens4d;^n zFTz>E-l^fD`CTw4VHZ-0JHqDx%x~YNglADGo=M(S!}ISvh;B+r=YRJZu%z_pg%lRs zg;|V2brGoq@YRwWCBA6tIjPB1425wEFayZqj_%_C=C_}u3L_4!g8GUkttydnh-@q` z!sF$l1>Kp{`X4KE=@bL1r|fRWN~r^@q#i8Jda*d`FEd~C9(e8YqK;pA!!M%XN!eeF za^Dvw%n~p#CSYh3pbUdSKy+9@cTB*(L4e|pfkyz^R=j3(h8a3K(l;x(obL4y`C9iX zRg;f(mkKkV)rs(HC)rdtNy_dKE5N`lhd3W!U35*+)}l`r`QY`OIRC^M{*cAp@<)sC zgUO03CR*?#*2DjU&ET~DusP{9-}de~kacuzF1o4mAn59}Wui6U@Px9gKY#-wlU(~* zFHc7bte>d}Jqp7#I2YAcj2a_u?fRy9oU4^h77{jGM;g226!i+G9mNN2UbcEqtp~+au-Ii1+xjys<-E1Z6 z6G~L4|0e#Tv>?_O7fE{3vf{&{SL9x#q=Dz>@SnYV4!Zvdc`${6!BGdk=Su$)bVdbK`M{Vxts2EmU8eye{v4q_qjQ@?p)}P_D z$U*`8g50hs%Ca{626?ehXl{&IcZrfDA=_&X&*(2$4^Y>aK%hr+@slvl|DBmJ-iv7L zM3>3qF*^6bHky5&NTEh0lWk{uqjTR50JkTWg{_G%G8rcuT+v~?LvhaaGuH=P8}!f= zA1QS~08r~)_yNv=R{k8IqJ>|^5wt@?;>ugcv!cYr^c!fb#dDcRs z^q_`GJ|yJg8)53omgzx!BM{_DY{(4&=d?gTw@1J}ucYm(kl4T$0eVXwUWM$iZS2Je z?n66aS}7kaL$j8dTZg^o){!#V?AkqM{U?mMH(K81jdqLY#`U|n6GvZSEd~6_smR0?}eJK;-6Z6mOi>ZHkDctyKd?*%L%svQ-@BcgajqU3=Y zS>=~?nrtACG2ib+Fj>P{FCjcmwV;c@lftfIWMd!Jp@Zo4F-)x^m|Dlm&1cr(@Uo=i zC*@&m+sP>cJeYPcgVZ4bLoEUZ>H#pNRtt!30VwX+w;4c9q6|4E(GEndtx6s;u&z>J z=Ceu=mPu5oR;m` z=ee_5(fRBFcCI&4n7xyoa_;Q}Sdl&VYwBR`3)eBK2AVxw6ZbbDPc`yAN~YTH;$s4 zVqcGYgPeG{SNN>8_*Ww1WlBc0E?i>0*O;(>%KDx=E#G7t>pS=v$}{&KDf6)PlH&Cj z4$XJ3Z*=Zl@=CH#$2S3|?9;2lBb|Mc_KVE@7ZTa}FR<=a`Z`90$~=ieMHUP(Wmzi&s zaUake2tlP~=FzeU&uGPLmzjSli}-sm!fDIP%$Ld{4=O5Ix|N$&nJLbAIg-qabHJ#p z%nasWOQ#KtgE=_87*JV*Iq($4RVUtsFc*Ie=Q{9igvI;uC0?U;??T=wU1aza!Uyg#QaF||iURq^|CdJ|Lo7&Y(A z=@+;^XHb$U%Kn^~gyW^ML5UtwB+$tIoKY2qQugPJNm%P*e~zW1wp0^|sdOVDvn>_R zvK%$aU=&huMM&0MXDS8l&v6Ov?wnjeuX%TlTj1WD0>TK^(B|G84{0L%l)moH;cMmI z$UZe=-Z5_#~p7||_&lqIC&?GlI91>T+0rC|@CwdZ+cj^tO> zyHMbQxd7<0r%PaAk&(>s*z9R z_dz+3FZ}CvksX73L5#sj{=WmDZre~P*zb!3EVxF%q6Mt!`>@|TM_IeMUl&`%?Tl3R z+i8D>#r~|zqStA=bnr>_cE`Y=*pp~Kfb|@CN5Tw4Bv>fr0Y(&2M6y^yXH36I(ZkZTy&P}&6*Vms_2%vPNe!8pboha-mTMY(d>!rJ_Etg0nh{K0v$ zsS*N#RVXQ>o&Vhl^hiO5r2L_JU~ycJc3_95mx*a=ivYPmf!6mTX1)D0iYw&S-@p$Y zDGS0vUll5kj%g0rDors`*T-;cjf~uK-y!p!TItdo0O06nkenxJ1Eit$0ocKCkBym5 zRKkiRpHrn9ssxo&E{t)Vh-+=6{{-l9Zae$62JaEM9EJ9lU4+hVs^RF5<;Y*IX#^dL z${}ma+t%4C5VKBEff4I?1oC1X=<@pZ#!xO8bwodc-|_RrKJZK&N|Zfy>*=4OHKJ13 zb2#{Smhupjr0E>ZF|PER4R+Jbk%btVBSU~}tfM(5;l^0kf(Jw)xz)t1QQ1*Na~LYm z7(x6Vh^1nRk=hV9!xLn5kDRV&p0Z7vDaUTOQ5Kygs4&CcNC9X^6fKm=(A4d8 zG@yDCbcBC|U+ec;TI&@F$azJlB%$%7n}pd-I^`F9hysTgKu7plVIPf=(S53HhC90@ z;g&<3dlF_)sF3p~cN^3a=vQ@UG&P0x%nye}yuwF)Y{`;dOer@r7+J7GKz=^}=8_r# znP&-DaJGO&KLCJV+a|I6(+S`~V|Ct#Yr;*^r1iw-vf;W+TAw9r?y)B9pSgHL zEYeP25^|tjxn){zSr3j-5DdkibH^~kgXxlqsga@%4p3b1_@9oAuUZ8^CQI%YA<$X! zDp)6!@0|ZFj&FOqj}Ed2u45VYtbTLWI_XxN^~I3tdxm-gLN*VqMSGw73kFwiSN zoebYAq9=L=^CUg<3tQPZ3$i{y1uDu}W;2E5%+U)-w&p_4u zpmp<)*tOo>GpI&2;2HP;;2EqG&w!D*XYgr8a3}^~6+TPj!(@kNKn~XVl0sTF6$$dw zQodZ7oSurjpaDOR0GX80`fl?0^$%IBkXye2KTJh3DPwm~<kNH@z=o`H*{zrhmKoNW13>61dJU4p2@(3{m=Nh=SP z6VIRxp209EVLY^FKsDH&K{mpA&K8}VAjM!pnWX|TYf`F>eeXZ0`u8A*^&5n>mp~4f zJ+c5gqVw@Pz9+#;Fi8JzKS0YwrC^7bASHG%DV)?aPpPt)ce-gf8>4Atsy5|F9Zka- z&MF2EC`XF&GHX;#*AY34N1jnI!i1zbjH#Gn6tx&LWg@gb`+L%5zWzyRntcFhnh_zO zm!KxgZk9cMIRodY|o2q66V}|^BT-SU<;3yZ$$Ky34orTMmcXYoOm2{!tRZ!b zC4|2zRf_hI(<0#{_W?S)CE=DsoB|zg$jtkL&iS&3Ygw5Qy~6e_%q1QPVMgvQkPt5h zxe-EN%@u^4ky~#JQ>Xz!MeKPsTj<#CSwh;Kp>h}imhWli2$M#yxP=J!QHY6j3(*xM zGWAvW?rN$|?Z#RCM@g0W(M{;nkp3%)5}QMQmQI#*)( zF9>Dfi4wcu8iMG9Tr{Fk9&BUeRY+_|ottxZRY&KXU4_DoszY?nolJsacnq#)SLVX( z%7b+pKfL6Dke*$Ml%1UEbvHvU=Yl(|co!!wxaG{9i)?HM-ml86lLfaDQcbI>BsHzt zMI}wEdZo?nt1fg-ZlTFaJJQW!IosYy}bm=V%5!PnhBe_+d#T3GrIlvnYuV+r?D`nGZ4+?G|q%{sNar^;NIxJ-sNUjMHJa3LU_v#3aSQUJU_X z&RT+6mE^sMH;K@%SFxa|eyIy5X}mhp14_#)f(%LcV$p+m9G!CQ2?MF0xA3=O_t0J) zburf;zt6Ht`a8=9JD$;#Ww-+=9nmk~S5KKlSVutG875Zw7J{6uG)`XA6Ici_496A$ z;d-Xwzze|IBgG9#(O;mz@m&W}A&>SZGzY!wpcvV^4qM3RF&^n--%#oMmm5SW8KP58 zV5EUgStcj2yOnN4ge(awmqr#@;R;X%v!HPXpiVEqYjelBQ41tvaXarp#Cq}&naecA zxJ*-zDLoG3@{qdDQ-G9??v?nR-+ui`!igvlqw|-?yi*5+E}AQJ9}&6=MMo6qVyQb^ z1xtrIrRR3n3y8Kzub#X7D(Jy{NnY2>oX<#PK`#LM;<=1PF&j#6%wruiG~{y9^W7(ry6tRQfz){1uIziBLIv!kATcG1uXcy zfJJ`-zykP?#Pah66kaCag16Q)-{M@7z^Kbxb#q%)Y(mAVRLqjM?6kKM9#b)KwP4bP zQf1fvkg2XFs<$37xX|EHMb<5Ou?4|QbQ}hTC4?(tVHN6*34)3iB4rIQeE7PhnmQQ5 z)X^^pP8|%^!G(LR<#B2Ssw$W7V@Cj`-$Qvp_! zXbDa|+@xhW_EJn0fjNU^;7qBTDq%RpIielbk#huhXQ$_kC-m;@eQL7MvjmSu`h{+< z%o5l;R#m<`CkC{2?m?7_$pAyy@~g0NY6p}z+f6stdXXvd9RV}i2XU+w2beYgk}IWK z3<98A+#n#cQ^1191uVK40No;AV)_4DPRhb_Bz8fIfW>bBiEhzLB}C>vrD8pdMfF>d z;Vu8iB-$aWkPUs< z=^lxxvjMoah~W}SzW})o1HHDW`7$JcXDhr!v%9MdJ5pt4c`x?l`_Lpp6_qRTYFl3Q zi^>!Th`LGs)~`h*(ia^a(f4L^5z|&tvTsPmGfJMAfYc_H z3t7}|e>Os#Lj{C00IXAxA6DEFTPi3>p<+=@J|Ss3mnJCkeK8eph~=Z4&&yUET_;@kj-8=DH>gAS-8Nvp(fC``;i}QO--PG50aZXV2~Tk zCl3wHp$P#|3&8pqFQcJT%W>iWQF4!)oxeiH=)ee3(QZk>zPrc*8!g^B$mD(y>uddRh~@EG!q5owKZx=> z!)(apF7f4fila+BE7>LMw9hmQMi46|Ak3GksU&h=FSS!8RWfT--QkWzNrgNelsgjD z9J*9YF_QHkTD*^pZvAi4Wxlme3}YVvYTHh7*^eO&+L~q3XR04!bVx+_rBbk>RaeaS z4D}+Xz36Yec*dfC5U9jO|6RgS-%#h`ua{D_JkD~&n_?V}!id$Vs>~9sYN{|Q%5`k1 z$lxeJ()bkHDYCoWS}B>ZrL#l@^rF8#h*q@1usWzpZI5}-MTrf#25eU}8*YeK9R z6+e0m1w`c?W6*ja6Lh}i?<{qwKw|3c6})aBF?mnMUh?iajF)C*dyPW_-M@et&4CV- zf(C8}fFeRH^P4XSONMztF49dJ>*U9XRfKlm*11}cuKPBF5H42zV%z9(YC7 zF&xh2MC>Rzi~qsCO)~avwIbUSb3x#2&{1IUWRNC+tRt;1@6=(>{4TU!v|5;iw+I-h z0Pu7Stp}LjzDK#vl7s_Ap}ecfz%{`1y`=zbN}S17tYB z(d!NF7j2=4Ji+O%kP!EaSW%1u(Xc5Rwhnxk0;%1l$YtKh_eS)%kxcT=hB}c^eOZ8O6zw&_`W(Xw_|}WFIHHcQbKrw{XktK5&88F1X`H#w~y5U-Ur_#tjO!C|Ojl-=cP7A}2SsMkT~eEftb2D>W&S2(32^pjIXfVKQge zSDRWg2;^>(P$g|@f#(QFiFG;mw)TlE@IK+X+LuYNOi<-t!@VteJ%#S?7C5@9)SKkU zNEImSl$)?l;R3~Ri-e`6^JGiWq0-|pNI9yg56u7MN^3B}wr!hv< z`!{iy^}C|kXdi%;xnJaG*c(}eF*O#a*A}rCN!lWkv-RS4Xv)Y#`7MGxopQw&T@m38 z?J%!cUg58IqrN3Y%Bdz;FrTRSTdL<5p)Z@OvoUPCz@9@-cCoC_qau2g1Jy2~bcY1U{*?8`w}n7b zA_J0wi$Em61cO0|wxuEA-FObsKMKDA7UKLy(~IPS1)Jhut@v*NuwHst_;(P68<+s# zs0g|%7?aO?kQAoED+v8cB~zhZ;$$1}3@O@i=-@$$l_&Ct8MZ&{p-(Rag(U~6&X&9q zmeY%md7Y;hZjx9cXqaJ}(Ij*XKs)R!>oIo zKcNPbbP-NLgZJ85bj)r^;9HBi1R3 zk?fvC%Gjo3YbR}ywhhG?#UZWr0T`XG2vgYf2&$WMEInt zh@w@W1=us>MNWGOI=*Pe5;Xrq$xF~vm3EjfzNeo-!G8AuOI8~s@;cEdyC=?PS%T`R zviL9$^S#|6$#Ym~h0LtS9J<3y^)TV#8`-PjjR*2W*RZK6R#>nWlA2L_w-&Tp*9|FLVa1!&GdP$5l zP&><{+M86pM1+@>aEexaU0{#gQnc0Hx^RZtp9Cs#<$t%*jw~hZBlA%T7Wfa8932{@ zDDW^v4h&f{rnEl_ylDT3+<(wPOJfhqjYllex=Dv|I|hJp%k<(-eSe}`c;kqVX>e8n z)c2C)_8%77(w-vBQ3|8)VE#_Rdh6;6FObx#{dZzzdnmqhrZe{-U9Za-L=KS{r|eQ=*3^T`$H_cB>UX^_3<3ADfDypW>6eUr>; zmjY&N?dBXLWkj|;jbQMO#3)mtteVHPeBFyIEjmJ7EN=C}W54(t_-HyvCO?i zK;~ZrEVx?0qGA9na~FZKEGqB3mcgh{a(qnmZMG7cZHUETMLQvgze7BWp~(G;B0Ppz zxjBXtF~Q?9l_18EQ)RgnXD^L>iED_YT$|zurjajj4N-a`TnIB8!#Ihl!n+Yz-C`Y! z^ENJVy>jTnQR~*_Y{&y#wu<@j=hsiji=>@cI z6-CSYDb|Hb>7oN{Mu{ry4?|X?*(?}7nx`%FQ=)QLRr~^ZlkbP$08+n73zNaj>Tm|D zw|>N?U(6jE5$Okp1%zV&aB@GRd}qe2+wT`%1+WlSScN4IUQK2myg(x$)mrOVkc-p& zOVo~|kFx3wmOU}f zw{8)g$Pj|RIKK-Q%EBE;!2JvS&Tr2YT?z^*N(Dor*|o?yzMMs?*IBF;!b#A+xFf1qjQQ<`&v(Y|IMK_qV#U7_&FFq6T6eVQy@7$}h-;K;6HB7BeKXl-3cx z6|zF@ApzYj0tV^MymnWLXDDt6ulUbf$WWy2X3s z9&*wBPQGM{sYMaU>oRI;sZbJoL`FTe(BtGlkR(hke^c_Xn)Yg8Sd9un@x`Lck!H;W zU8e-)+SIk+p$LvxzY}5fcbW>IGq*73l}Lu-Z%L3IJJ{rQM7S~75nh5{u7C+qCq=cG zRQG_&UJVP?3!Pym$iQBx3`G|S>nTBWs82ZP`|0Z1y*@O?sFpN!c5LeN;UO0@e?~?f zzE+2eU?jr%iGFYAxn9^S=^OY|x3xwzrOq^@dE3xG=$B_nE_FVFb4c?11#&_|8BDQX z!^yDTAXdG!gZ7+|F(bEct+)P_gz9Ts5%I3EX`~3`CawA!x21B70+gBhYusbR!Tpsa zwC7@|V!TdG=v1ZMs998(zAO7EYmD~_m!P9YGGAN_fMZ@EmV->}$Xef5HBi|9M?RZ1 zA|lIqulj6OOc44!SGl_8Kp&78e7yqXNU{w3bQ0UwAsP0yOKcz{V5mjF{q+D=wW@?- ztiN=muHowIpYf};)oOlVY0#3MErwN0EwlC6qwP2LNSgSKl!ksInn6j#k3HBQ$m&6m zl7XNXK}v^UAA*z+!G7!77y@ZNo7JRipgPj90Cm|KJ2Hr2RviPFo>lebE}0Y2$tt9f z0WSb1SDvleJ4iw4a)lRMjMg{hOK^%-pQwmsx8{ExqQNsH7aYL}vn+JfEfNaBTIo-1 zVTa^Y(yDvBC^%Or)IHua_c6OZ3>$DG1=dOt$l-;uRxXtzi^=vzQZ{k$|0D^$d%egb z7t5@`KBVyzcX<6=$mHUfmdLt5swbyJ*pstLNz5;K@`JqgHAXcLnQ{=ramgLOMM9|V zU!SbPR9<}2Qp8v{gBZ2oq=2Cs0&FO>s~325U;HP(x;4S= zNVuQ^{Q&st7S9^h2SXT=YX|D9TjXn9tRyBM%ca81 zXPt(yd@w|)j%5tigL9-D$CKoxuTfFE2QBMv35;03mVnrF>n9RcS5t2}#A(+tHz&Oh zcFXIuS9)5;l)QUF4({;LU$botv-7AmKyJ~(+LQ3}R*w`TzYqwsMVz@~(U9m3^r$6x*|6CBQ znic&QsbM=hGg~hz#bzjERRwY8{UUcu{15w*Yars&8!&2zXYO5p1QB_D%&85>z z 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 delta 24066 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 diff --git a/Trie/trie.swift b/Trie/trie.swift index 4169bd208..e377bdbbf 100644 --- a/Trie/trie.swift +++ b/Trie/trie.swift @@ -104,16 +104,12 @@ public class Trie { for word in wordList { let op = self.insert(word) - if(op.inserted){ - self.wordList.append(word) - } } } func merge(other: Trie) -> Trie{ - let newWorldList = Set(self.getWords() + other.getWords()) - - return Trie(wordList: newWorldList) + let newWordList = Set(self.getWords() + other.getWords()) + return Trie(wordList: newWordList) } func find(key: String) -> (node: Node?, found: Bool) { @@ -198,7 +194,6 @@ public class Trie { } func remove(w: String) -> (word: String, removed: Bool){ - let word = w.lowercaseString if(!self.contains(w)) { @@ -210,17 +205,23 @@ public class Trie { currentNode = currentNode.getChildAt(String(c)) } + print("I make it here " + w) if currentNode.numChildren() > 0 { + //print("Hello?") currentNode.isNotWord() } else { var character = currentNode.char() - while(currentNode.numChildren() == 0) { + var i = 0 + while(currentNode.numChildren() == 0 && !currentNode.isRoot()) { + print("Do I die here?") + print(currentNode.getParent().char()) + i+=1 currentNode = currentNode.getParent() currentNode.children[character]!.setParent(nil) currentNode.children[character]!.update(nil) currentNode.children[character] = nil character = currentNode.char() - + print(i) } } @@ -267,25 +268,18 @@ public class Trie { return getChildrenWithPrefix(self.isPrefix(p).node!, word: p.lowercaseString, words: []) } - return [] + return ["HE"] } - private func removeAllHelper(node: Node, w: String) { - - if(node.getChildren().count == 0) { - + func removeAll() -> Void { + for word in wordList { + self.remove(word) } - - - + self.root.update(nil) } - func removeAll(w: String) { - - } - func printTrie() { self.root.printNode("", leaf: true) } @@ -309,9 +303,12 @@ T.insert("Hallo") T.insert("Henry") var U: Trie = Trie(wordList: Set(["Hey", "HO", "hello", "yolo"])) var V: Trie = T.merge(U) -T.printTrie() -U.printTrie() -V.printTrie() +//T.printTrie() +//U.printTrie() +//V.printTrie() +print(V.getWords()) +V.removeAll() +//V.printTrie() /*T.insert("Hello") T.insert("Hey") T.insert("YOLO") @@ -325,6 +322,6 @@ assert(T.count() == 3) assert(T.contains("Him") == false, "Test failed") assert(T.wordList.count == 3)*/ -T.printTrie() -print(T.find("")) +//T.printTrie() +//print(T.find("")) //print(T.findPrefix("H")) From 8d0a20cfb142dadc359086f7ea18094100cfa7be Mon Sep 17 00:00:00 2001 From: Thukor Date: Mon, 2 May 2016 14:44:16 -0400 Subject: [PATCH 0306/1679] Got rid of unnecessary debugging print statements and variable declarations. --- Trie/trie.swift | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/Trie/trie.swift b/Trie/trie.swift index e377bdbbf..4758e10fd 100644 --- a/Trie/trie.swift +++ b/Trie/trie.swift @@ -103,7 +103,7 @@ public class Trie { self.wordList = [] for word in wordList { - let op = self.insert(word) + self.insert(word) } } @@ -205,23 +205,17 @@ public class Trie { currentNode = currentNode.getChildAt(String(c)) } - print("I make it here " + w) if currentNode.numChildren() > 0 { - //print("Hello?") currentNode.isNotWord() } else { var character = currentNode.char() - var i = 0 while(currentNode.numChildren() == 0 && !currentNode.isRoot()) { - print("Do I die here?") print(currentNode.getParent().char()) - i+=1 currentNode = currentNode.getParent() currentNode.children[character]!.setParent(nil) currentNode.children[character]!.update(nil) currentNode.children[character] = nil character = currentNode.char() - print(i) } } From 006e74db51e5618e90e81fe3d9a917a3be1f3fa7 Mon Sep 17 00:00:00 2001 From: Jayson Tung Date: Mon, 2 May 2016 19:13:37 -0400 Subject: [PATCH 0307/1679] Add first draft of Threaded Binary Tree, with some images --- Threaded Binary Tree/Images/AddOne.png | Bin 0 -> 15851 bytes Threaded Binary Tree/Images/AddTwo.png | Bin 0 -> 17141 bytes Threaded Binary Tree/Images/Base.png | Bin 0 -> 11907 bytes Threaded Binary Tree/Images/DelOne.png | Bin 0 -> 17173 bytes Threaded Binary Tree/Images/DelThree.png | Bin 0 -> 11596 bytes Threaded Binary Tree/Images/DelTwo.png | Bin 0 -> 13594 bytes Threaded Binary Tree/Images/Full.png | Bin 0 -> 12426 bytes Threaded Binary Tree/Images/Partial.png | Bin 0 -> 11218 bytes Threaded Binary Tree/README.markdown | 54 +- Threaded Binary Tree/ThreadedBinaryTree.swift | 171 +++++- .../ThreadedBinaryTreeBackup.swift | 543 ++++++++++++++++++ 11 files changed, 738 insertions(+), 30 deletions(-) create mode 100644 Threaded Binary Tree/Images/AddOne.png create mode 100644 Threaded Binary Tree/Images/AddTwo.png create mode 100644 Threaded Binary Tree/Images/Base.png create mode 100644 Threaded Binary Tree/Images/DelOne.png create mode 100644 Threaded Binary Tree/Images/DelThree.png create mode 100644 Threaded Binary Tree/Images/DelTwo.png create mode 100644 Threaded Binary Tree/Images/Full.png create mode 100644 Threaded Binary Tree/Images/Partial.png create mode 100644 Threaded Binary Tree/ThreadedBinaryTreeBackup.swift diff --git a/Threaded Binary Tree/Images/AddOne.png b/Threaded Binary Tree/Images/AddOne.png new file mode 100644 index 0000000000000000000000000000000000000000..12509733c9c6222e8442fe5306aa69bb5a78df21 GIT binary patch literal 15851 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 W%(T_=6(FpJK$PV*UX;qc3j05ib&Z$+ literal 0 HcmV?d00001 diff --git a/Threaded Binary Tree/Images/Base.png b/Threaded Binary Tree/Images/Base.png new file mode 100644 index 0000000000000000000000000000000000000000..da25b476385513c28ffdd6426fb68370aedfa07d GIT binary patch literal 11907 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 JGA--K{{i}^eE8YF+1aht&{8f{a zfGuQiJ!!$e^DeSVI^^W!xLNow@R7zU6VTUNm z$>?}atTrP*Fj;+EKen}Gj)q1J*KC`MU&28>u07xw&u>RX-VJJ)A}KV}r?sJYnl_O; z^m~M=H*c+Q9&%Tmzus0RTzn;KNW!Xq8JZN~tuG)R6t`FqG^T^lpyqo;TUhEXTOocw z&B3%%mDzq*{3BZj%$4XFrqO}#@*LuKD{9SvX`ycB?k=q=&iJGD{ZR9fL(6VpJed~W zLKnaQpx|wR2LgEvKlh(EZ!rFTZ3yHI3hegpZHEr*kN(fj|BlG$59NVmwTtxB*FQ?M zcoc=PKRb!tSEsbDE+vf6N^RZ7L#aMtN{o;yZ-O#c93|%E^p`tVWr*7SQ>+Vr{(LH3 z&almRu*Biq*sa|Q*8^xjtw!n1$fcysalJlQz~Y?WDgvN{^K!ux>o$;|zXJ{M+1?4`3Slk?`; zbl^AlB5Z_XIU}Q^^?0ur=aMXd?KOx_yi=kD?#AD;cX;t^?q@~A%DDk7NHFF$j8mH2 zEmMO;1dgSw!h<;!Uze4YH`Crr$O(buEtQPNyHYDJ!DFYsle-R&7 z!@ApDAtf!X&UBvS01Y`v?+}fLg^rFTe@zcSQoJd5sQ)*?$T)!Cs1kF{nqNPd|xcY-7PdTlWB=_x7MXw7rL z;{4@C-7?6IdpKY${J>OyX+v|-aYw#s%$)8}H^tWhvh_LUPiEQC?Y( zrA}56P~oM>J-c!eFyMw^d_eNr>@{@88$mvgAif zfiGXCSU&jZIxD+(?l7Zpz~@Q|nfv`9nu>dOoNqtbUmw_0U3cmvS}h`(U&my1$cPXq=Qi*G%M?YpXE<0u?@4Y8{Icg$aSSUhp6MMZAp*Feq{t`e5ojw zq<>yf4c+&blO7uTAW^(}+_tzN5ax03mk0CR8xgaKGT_d6m^`DQ>@TFCVQoH1tasAL|-~1D6TcvJa&dnH~>hTz| zyQ;>Fu8#S`w$~%jv!thR8KHg={#(Ckr!&VNSA*Xap9+y3mj-Kxp>%Y4SMJupxGOlLf}-N`ZbRuZjW#%; zOym(2Mo7)Y-o7{x!@$HOe71h%jv(F?B$R#ICdU(_B5Dzxc$S-wx#9*yR{hp}*uK#{ zhRb{&a64TmtgQ<)t~|hs2!B+SJdf;j%1`Es>oPfA(tGmc$@f{ZAQ~+)cIzSAhX#q4 zI0D%96Lq=i@*AHQ4Nq*Z?MM}A73h?W@^@!X9atDR^g-S@zC{JR(Jauh_D%1eOF`a@ zRJa*Zpu_v3RT3jKVC_22H0S)NaPbB8SvYx3mLkL!(Jl~Q^1MXhR8C&AY2%t*^>h3b zfA@1u+eHq&!ouI`XBH!vXfePonc7o&D{0(5k>;z=`)uyDC2_UT=ciNP0Eu+2pm*7I z*?)nTgRm&*>M~j+b^^Xz04x+rP)xX%z%5EcPXI%U7cZ5X6bT>sYbog=E9;r zUxyH7r&BgJI9hK>Q4JfVXIHc^%95=Vg!MXHX!i#iW~Lw>*Zuglg7 zblnvtokn&Z>bI*x@B`f33;GeYl_CqHHrDAB+l!s?Qb4 zjo*7`J8x*RkXADzpPTt-#)}q&y36g7R zHEY?jaGA!e5*1wB)#?Tpi83n{ztim6F3|$I|6ta1eK$Wf{x4b z;GQHpa{Z^Vq+>dtUmzi*&{olCC?qF5mMAKTrc$ZfpZ2*N{Iz+1TICe$Hh*@3R1Mt( zn!(=p`MPP?M)&EXh>X+X!+oms)%XZy9y$t;G~mTwX;*hXG9D2v9!RtIJG<>Fj61lT zMEY9syxVB6VG_^cgX(6x`I2>W;wStI-<i;uT@x<8*U`No140&Zpx}Le1dru* zG|_p3o#T(m6;`9Yl+kFGPQZEFOE(ZsgGL-JLTxQDVPRZjT58&(0$;nxjqLB>x%NQp29Ja#*_O>xjdCHkR zkZ+SBBKf0lXLtYD-JTM&(C~sc;m6!ofB%QlWg#KhdFTZPvlPo)F&erLle$0VjeE0M z!w;!{*0lPsZ}=!WY#$aY$G%Fj%r7rUx6dKC_E+R`tca+~maSFr4ew;HB?FiFb)VAQ+WMWP++qXkxA*xOtP)RMVgtm91v)=! z5DiMf_Pik3`fR8yoUNZoC8sddp3myb)h`BqN{kRiux!0iR42X!4G+12t3l`GWuh~u zlJjmxcLv5@y?*hPfhgr|#z-#OFkk8DO9o`XYf4F=ZXS#f4_|xu-Ux_AvYjR5 z>rcz|KaEGtIgclN{(jfj`h>VzAt_%w%Bhqc0m;?6lzwgE(iXhURy-=M>y@i9oGUIR zZ?^j;ovU#YCl75{yz(8+3m{6h9Hwll$AFG_Ju|*BN;P0f;+0kLWti=d( zU%uNjzg>gym{WYxg(Q2tC{XuVHqBDTZDXiO^!1<3^^-r94>&&Q@VcE+wV&f%JxAct zUn_IdRv6+<^F7RMd3#RwY3&i3$`b|BdQ0s)v|**hrscmG-RxFOrg8T|Td#2+Q%&_^VG*eeIXsM> z|B#-PBd#m+PwU5zA8+c_7-peOJI``oj_wL}@;n=NZSTdUlf}F1^$I7MrVPeSxSH&o z!et3%g5b%GI%k#zoBXVsnhDClByQQ?)Eu2^_QC4v1#h>AC7nb^M$Sfj=&>}ur2V0f zZJKOrY%Dp?CV<^KC8UOHR!%eCSGsT8w?Jp<==!!Ogeda9ACvY_EhqHR6IDzxn)@&m z6|fuEH@|4w3yPAu5*5QgRJd&7Q%+irnU%ad!~pj16=_d7KPz2;Ua&j6I6Z#lpfh zpceA{!uLcoUO5+(NBB+8r&lyg4Mq}{*-Z*lGa9Pg3fRdPYDRyKA07&CZ)d4V8#kVE zhimcOkk{l(P&Q5@m1WB>jTij_qv9>p%LsDGt z$3Bkjo_pqd;~DSulncXCB`Pw<|M9|g&h@^tCbbSzDeCC^D*f1B;Fc5l4aqqYEglk4 zmNMmhjoIyi-p&4hd&H1i_2t(DPn$NGWN0>43>s$#T0o&E=aWA%ce*3nvuC6__Cc_MV@oh2?^W%iQk364Tvt|S6D09 zM|!?}lM`WFU0p?pcE9AGnRl)S)z!%G(Z**g8k2*s^xodyy%{h#Qp#g(^2-;<#Iw@$ z%XX^weM)|b_kQ{EWpZ+o?ff(f)q09+_1kQxKfiNzl5%C^J=F)n*R!iRrEO%=8|PLQ z14ToX*$%#tS-(eS8MvQbouog%oA-7WPWS`&KgP|Vpg!&ixx+>Rp?~|oXscqGnV1YM zW(vy69ACfQSQyCRNMl}6yl`F(8^sEpputixiHZ<+K}D0qPCj5wHxDs+zqFqrLHN3T zPo0lzRclv=Cg{}zuk9X3+<41)mOb{4gyi%ZZ4 ze#4rR!wll1PABHhO({4r!r*y&<@R=;GV&Ci(KO%C=plF<7tt*AH4J2Q2&Rx(@hF>= zvX-MIN93`g?Dvrp!`9PP#~D|wS{6m}XSTW9OA(jRCTWkL<|Fjm{%vdwl>S}$7RPsA>@7S6);LM#_Fyy`0 z%$-82)z63BptNB|e!IguaCo}JZh5p{@#X{6{LK(k1}@+<;*>I8DcPlnK6+IDyO(rF zQ1RtKD~)aT@18v8dgEri$$w`>c`?HY&{L>2Hv8fZd$;#>$Yy z?8A#3expV>*cO3mv=zNR;bG1t$hrda8#bA2FoW|f*xY+d92$zxv#BZ#vM`9k$98ch zbSsR#O5rL=7NX1np&Fy(iAp+yXnGa&K$hAq6NI{$EUftABl7Pe_;)ABzHaS^pRLsg z&+pq8#d5F36SFJUwA&}SDDh>Hz6UFuAV%!;xWvI!itI~_o}tn;zCSjzH=SDA;x^B_ zcHMF@R*3R;Mjuw5R)z+IRNjOJeWTXmqwyMq@u-_I+PGg%laG!fT}yWqu8BFau@XoA z{&pe^=Z6xF`u0}Ovo*Vzzc=yt^TNbP9BSSR+a5ZMyL;?0ExIuvDVX;iQbk_kJ}MGv zVIZ%mRWQ_$p%8^%Xei}Yu719%V+(>jZg8#l8LlnlnyzEv4RP)ns{V?5}V zoNCxQ+0S^+2QxHzJ{f<||3wiNlB@gcRuulvwwJDM&Okn2w?K`wCY`+QFaQ?}5?$(z zBrzA1Vzmn5BMwi%SsQa*h^IsekKf<&zJ-b+H=dNLyzp}}oek|1NX%HBD!=VLGxJ6B zfn;!%a*b%lybO;wdt><+|xLb{h#a*3{0c_}Ccw!A1iKW?tb zvRlL{o4jI$Y07T!JUJ*sdHU)fxz6C2cHXLd73qeQ^CSYR((Es97nO3994`mj(V&%diXAOH{(2p_MjCar`Z19L%~*`U)A(^ddSE; zn=m<&z4{*~AU{d8K;ZVC<2_Neh*XPl52;cLZ${g{t;8Xw8OHS)FQ(hb8fbS)j9Ti= z!^%@hM<2W)etQPV8|31@HJ3#2EBr~AOD~c{i_o)hHQWl%eg!}liK&{~EH^{$Q{GNj zw|a21tWg`TuHKNr8`^v2MdiUHJPP)DrohoX@5#3U$HcP_zg=LLa8<1zjswc)k;u*@ zuv&aCKl}JmJ)I&!9UYeBr@L^IzjVJrj!;m0;@|NJwK$g%EAaqw)Z*xC*W}R|l}9u9(Zhw?&{WZCM33ukoA{DmpP<0n!S5s|yDz-rQP-k7a|Wz&BdU6A z@43TWTwD?@>V4*Pc<02UmR06A;LT>hY)~+--&=4c|L;Z7_7hEW*E}*{UfIk0dA+@T z8R;3Jhb2t9x&Sg2>7ll$qr_OJC`A8s@sq(s_&r@H(2F5_Z9|J8|Cke$h?B2RsZzgD z3o!d0orGO8mfB8eo!KY)&1vfYYPfysE1l6}c^XIP+V&Mq1sUL5{kXR%@2{yud?WBZ zj)Y&Kz7GrEwl-B-9q)l3r@?KaXa>3Tr(4i?>EA zSv+$2GyFDsda;(`2slTucDH}V==CvsEH^R;abFont2_b9^2Jy#@63;^*#U z^mUruSBmu&7gdVYPXu>gV)ElGF`Sj}h3pLZoyCg3-;2N+-&!RXyDRMrK1|hyH=O3B z&Jax~mhTNKw$PPa%YiDLhVgZWm{$3tr6$4x!0=@cO~^Tz%n7T1`(e&Z9Ix(wb35(F zUe1C(o{|ciK2M*}lrTR-5n}q8Z+ReuX=lhny;U6Bx-AOZXN|O8s3V*7|_OfC_f5b-XXVXIIZD+1PKrHissu2v1Awqj>dTwNe(du{U) z)Xe~XiG$$yNLi7=6$+Jv5x2`uYg>9!W7vlqP_)$Hg2tgypRYqL7!(pM)}?vQuFC9H zZFTHU^k`on2QlY(FLQbE@()Zzr-{!@Aa$0pYefGYd7|VZb7wgi=ZMtKP&C12=AnQ% zTIKHxfeP9{pPzStt?>fWU$5yt?{I&=(xpYmD1^KDW>tm?Pq559f})X_wW&8| z%u_m3{Q)`q@^hs|nUZgR!g4=9UPz_TCZ+3D#c+{0*4B2^ye!S%Q2YD%`Nl(^yT|LE zuZbe8ZnSoUL`$DdM8MVtaI%n&zj

QVGgl=`SNZXXbyhju{p! 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 literal 0 HcmV?d00001 diff --git a/Threaded Binary Tree/Images/DelThree.png b/Threaded Binary Tree/Images/DelThree.png new file mode 100644 index 0000000000000000000000000000000000000000..a1acdc85defe49d0fc70ead50c4725f6d277d6a2 GIT binary patch literal 11596 zcmZvCcT`hP)NMdeL`qaZq$8*Zks?)k??n)hAW;zMO{(-xq(~8@Na#qAE<}1a^aufw z8W0eW5~>kU>KlLGTkrkzWl>h{y~)fycjlaZ_TDiM^fhRyS*Rfp2(6Z;su2W2_6Gba zQjvorzqrR^!M}5!%38)$R8)iogL&{4>ZNAp_0Y}M>!p>44dkJ{x0jcVhjsYyMF@lo zqNS>2>^r@g9rBvZ?%m2<-EHDUYYQ7ywiW#cW752AS5_T|Z(;ZfO1C*tJRh7GFd`dK zm1#^vQ#@~K)(4g>D2eBh zc-NcWeq^auR+k~$;i<1yvm8evVbo;I1TmNRfWh__qCMwyoFu<}5cFNQo^TTaNrFl& zFhL-Ba4`Qta)=`4#U%)27zTla+LD2z4U`awJvgt3`FC^%+`AY!|LEBuX>h$u!bRR;99nn?fVM=l*Ropc2tbx%JfeGlSY?wdw;qFabrg z3^crILT{8eGP-~dR|CVHOCUo`h|^$&U+WjEP`%+T8L?Mv>_{Da&-mdsnn8qziDT5CtEY9zTlZDxah4HGJm?%?Wg=@|4b{JHSInrRE%El(_>J&=; z9g|RtU`0t$(M73*Qt&$eMCl-?eacw^HRvoMqo9yjq8{qc#9TW5gpZ+Vw$dRppDD+g zkj8r_rT-Jb#kiqEy5k|WU`!?PZ(z=%)Py&7{IU|%Vq#fJFc(j3NdoJwbh0xWw8a?nt7ZNA2-8WNbe8aJWXncV zKr$%>dCbJHEMv^^9Q780SCzRQTQYv=jJWgykv{%$+#>4g^|o!DLPGg!o4hQZ6=_ANLp%72fgwz- zGkTMW@;6X^&b5B`HRKoUg?#@# zJ<-=i_fAzXO!UF9?zLLFivexdPin-EnvuhvfQxg~fgRM}zzVP+QX zQi8I9>y7^W`SZt}5-@TBddfN3w^`B#zLkAD)HdwX=$cn-_p>Z~lFih!YRzU8xjmDn zxYy#v=>fSR&E#)HK@d-_R%YY~Yhd?vf8=jxaL4bjjf!2ZzRZm$vGsOZQ0KuNdc9}o zDR7dg0WpPl{m<{oyxcUTC)k}!yQ|AiZf`mbx3Hl3kg<$9icPzgU60WDvZ=9w4KP!tn&Qzp_SzphIXtyKI>+jJ15e(E zfn0pvIs~8ay7gVJ&Sno|+^vVJEcZCMgbxoJ&g3oQ8Xs3gVZ?`!-FT&;P z*oJqKa&9wmC}SY!kz~S+PG_fVfA=0O1-<%m6^Fy!PT-g+hP7z*!Oxs6@YlhHV9|(@ z8&)+Nz~W^uz0Z9A+gD2)&lW0sDKdeJ3Wn=x z8N7t(i+>^p@nhnOE%1`gmO8=(&24*0Yu12llx1M`Lss_v3e(y7VTiQ~G~4;^-MjY_ zuHr{=witUO>Lj}`l6~gSCRf>dsrM_$_|N}VGFfZ^3Z`guGlRolkLM?zk2&zVp;K}^-A+sV=LHxM!J`sf`Na zNd@<%Hx1?-Ye6Pkl=>u4Qd&Ba1<|A!hV9&j;R>v)!PY-hL0Xxm)xrce3NbL8@R!na zV~*mbD63phC&GA@^iYi!ThAO;mt`{1QE#?=b0%b(7Nwj9uDh7eIZN!m|M%3T5>zyv zr)n=7B`^6sDKg@Y{0J*^F#l+-RY5~!%g#|OF}@M0nfwV|32sJ{a?my

KL~pKDz` zDq_VCG4ZOuQ5HYyolU2vQ}i|To|uAy!G%&1iR9}u3`-J}#TVZF4Q`dOB+&+5!1whc zn^tn>;LrJ(#6>BPLnqGbFmwx482ROBBv$fKQcucrL_7YK*b zmrLkfcGjZj z1}0^Wp{6SDBu zjBcfHN9yY8a*f5(e;e#@w|FjeCG)vqfmSUaCxBeQ=U_z94YhQ>C+7KCF38yyM6Oue2cQeYK?0e-K9?B10zvOj8Q9MOmD(9Yt^Z| zMTKdu)}gFAc%6((OzYj^dBHW@{nWx^ET)*l6j-SRO43ceRQ!rPvCMvk=G-kfk8Z8M z^>Z*Em1IWCQt@(ILjxw8gRR-t5PeF#SyY8q91 ze?+Cjppp7qPfu_2duxEBBY%gn6W`$aO?X+_&jS_+hz_JF&hf1)(mT1lKPIMm|GPS- zG+jTZ#cA6mWyHT$P_1ypk{P+;NAX-tYy8_c;|kM4p^JEuV=aqG<-)^?d@-<0Dn>OU z`P2DgeUrEsr0Bdw-)a|)*g{`!wz{mBmiap_OC_Kk#DqV1jLap-vUXqTrb;e%A=K@C zb4<bxLYiQsyu!vgLI}ivOLycG{#6?^sVLGui+%IR@{g=?*IDRWIvDC;gh* zYv0aUp}nsZc?yrwZ4Yoo`nJ&r`!7*(FBNMfbdk>25nK`$KdOr4Q#3xxAU5s!XYXs0 zb6aKF%ICV(6XMl*>QJBC>jFy;@XR-~l3fS|e5Iw*qN1YH?3iA83(gmxHrtOeh~$KXs*Z|Tmq#91$8>xC+PbVcsfe~sl9QV2TU z8!f)-^||$C>OY!jLi}rmx5mr!egPY3dYFKgX!Gxh`2Qc2ctuPHwjw=%9XzF2?WCQm>q%-|o zhyev64B8OxqW80x6-N}{hZ zD;L}qspQ*VcO~ewv@{dlFRYvY;KKxwYJ@hA=s%D8dA=NucKH0TiR=R^Z0O0&zQK?B zIUb|0D(8N`N>2&q4(FPzLzEbc>ETvDR(QQI`7z|Sm9XWnEc}YN9$0f|2UlO2KMg@+ zXOA|Wj+fGQebqsNoOKPzdBn$HYiD=)lXVdshP#1h$(ov)`iC0zn`hA||MQiV^H9nP&y82#So{4nCR82=wZbQGpGTq z1(KgT$6FCHrrOoD+P2S`VUdFRd4rkNaX&OeZPhkEq3MvTlD}e;;{s0OIVaUF%m3N! zt=kNgH<+aXC^CqZMl1Qd?{2qytF+$e2lHi;pA`2MiwJtGvINHi$#YoY#RXgD$YRF> zj*xkjbzoRHR|Z-u8ycldhB0tzt0%8Iq%4P9nf3MXv=+FYC)D*~2ZgB~J;f}}5UUao z#4F7Us8sg&O-)V7>3v_*VnHRZd%)+LqcKZ!r_oUf3d+!!j8DtDv_r#_CRIa*ZjVNq z+g+vCd}ex)d9StsU{o?OF=TKd=$jn&*Oc>WZ8t8cD{E>$kCSlf0lSvU46`bEb^AJ2 zxMr%{1`dkW#mzxz-=y%_@;NXI9=Y_Hc2!Vim7nsbYVUaJh2fV+P3RnaL?7sE`ZiyO zWI=cA;$wtj+Dwo$-X1g->1c-=%pc=!9K);8PpU@aTVObCe_|PT=Wmh57ctNBA1HQG zi2w1`OL#vz_yRuEx<4JK5VCG@MPmM9m9RlJbW%;EEpu$m%gClurx<0W_}zC+jmWum zgcUU?{(GyhCTj@6Ag)Jf3ko3rm!*oj;44jn-l7a~-Jcq-pI@2{OoRT?mfoNv4!6fW zEA_vCRe)qFoqxK>?q=n#xLM|%)N&7da zMiLv(s-x?|hs$w<^ohV(!wV`ErdR|EZ_Kb5?SU1PCH_2CSQcM3b;F%d=Tc;J@#V$L zT8V^3=h>!IXpQ3_t+((CHp%btlGwD<`k}1O>_+4H5!y0i6GUqC2ss^7*j@z7G3BVV z-B4EkEu@L-c}J!wl+_FSUatXGp|(F}Yjf87FS74k0zI&g^6%4|F?u%;6WQ6>ddP_| zX!4-#)s;#w#7kG#N(ECd#CGHL9%r7a=tlqEgqWAD#NQ7Mewdb@4ZJ_0{PkCM7PP@z zStyiFR!E;W!o&od!92_Gb?w&BhK^+DjY#M3Eq>r-Ym2rJj4Pm$#P(cyWpXK_vUTm} zwUASWtuKeeH)D&8VgwCk-G5M={O#&e{c&tz{9Faz%hVJ4kfGb#cJ2pUbgTU~D4|Fc zx0$|z-^S{bzstpmi>5T6kB?=s!r;snJ??qxL#J96tZ+<;T{R3D>n>B_$>GbHPW)q4uNb=Iu5acsg_(a`XMCn@U;( z$H&Lr^-*mv&ykG@)>s?FSWE={d}k+r z(1>sSH6Rd~1Ta$YhBfD+Uryz=4V-DO+)6C2Mbz^fzO2&oILvMK{mDd3$(@-ZTu(8v z3GHy$=0@0e3nrl+7VBUBhpqNow}ZBktgf0aKNK!IUKYHSbL;;xB)RGx-65nf`arIf z{_^tj=NPyWbiRlB=Ja>*y;5R}rTkFP`e*|y5lfQA)#&KxAg!L?d*@Wun&vnzP}Sl= ztf=2Veci*4tEquqi|fwls<2}A^z?Kxja@|9A=dR+-D_soyu1*_H@e*|sx-7iSkw%X z+r|Uuo?2ME&(Gu2E-?=Gr9Apw5z?@2GI7!s5(0hc(AQAwf*Kk^q1T$WzJ4_la#b^A z+vHOk{bY-|p618(emc0s_=jI`WQtI$w?qM-1WSD9Bj@`GqxNE}heH2I7PHOTu#!og z!56K^zjq4*mPZXZun1}%*8m+fuNI5d!DT}RHA9*;EcR=;dg0|9uFA8e)%|d`-dght zt3zMVDFnGcsI>gMiKTB1J`~$h(R3&JJt-S2pjFmjtcT%D`BNhun7q?899)0NCJvd1 z&|J0bWyX{I2WlOsv{P^H_qVIlIhlxR<+B$6)S#T<_d*#wb>l%jP>Anc!Ri}=rF5XcVm)vZR0MEWg%iaH<9{s{hhILqmnLR-I=V_oD~t8h?C%e zIRm}X%GK*5&yF#3CqoV2uXed;i^u6}b&WErJ%wkeY`A*;T&<^95UcczjwUQQq^tZxF*#!lGGy~DLp5OwD-Tk8Hl(tK{lbDb7WVwKaDqoSg?6(Wandi-?k{9R)R zg|gpFiyn1>Qh!YR+|G_UO3G;vr-@i>pgJs6uYMI}#SGAHnhmX|9ANdVGBN~|*`&22 z%--ZQ%z{!`VjOGvI4}BFIX5TktnZB>p|bC(KGNCGH}lyI(t>|2K0?^h1ilAzojY)< zHCKJaGF865qq6mfRqF%og-gY+mMTQ;?Bz}wSI%x8DnskFD(o&RBP}=;Uk&We4acwe zB`gX{uqDTol%UqnHrJgh{Yv+r{=-B|PpE!KlvraGJvQb!T0%CGZfrgSVEh*LSF*=y z2It1&ON8WLY@vg>1d9Dho&0f8^To9`OZlADYAa#)fc?oZL`pMVPQ$!irMn`NkG}1_ zcVCwDmE>ggOf8)qBtN7yF*}}lU!1_L=mVBdG4oVQ*%@{>&LsQs~dZuZ5t` zUru^`_+KS_B9LC~SN}W_4Sxnpyy0qM5})^*!&}a&Pekk-2golXBmM?SQ(2IJ@nm`6vb7#TaT0 z&B_H;_WIue?2akzBi}IgzwX37Ykk70rMAI-YxyMgT&dS7W)ksPzvhQv?oBS{)vewz zlJe0m?+`B?WBpcskmy14=mC2*-E0egf?uNtJ}jtt=*)6L%%HD^sKMUXRC!f-_2=uw zG`qd5nn&wNX#F2a(wtu>MlWppNtj*p%?yzJWL_a`n+LkFNB@?r_VD>{WL=xA347%l z8s{XRW|$(nO41sloTucr)!0F5Q*RlN{_39w!vO}{s;xlT*6j8t=Z!hZX0Of73-lY* zEgtF9vO0!ug}*m(o-|ik1PzLhPtXgVEcI&L>7bY6pN~RBymzqMM7Ok)Z1tVCta#$V zii_*MG5gR*)@dgaIx1FWj8S%6_uY?dbMv=#g*&s2E$1ad&(=1(L`1~*c0-(x1*&(H zkE(Y$8K1;?};}mVw8VipEeyWo=s|Yl^`$IU%PGgY6%f_nU#$}0gXVFSym`|s zf|WZ*&fOkgX)u(N(YAf@=;LPtWvXPIWAcA%G?!)c_SWhU)S^)+N`$<360`%I?Juz#pmA>^-HNM-kg0H@{5 z6WJTaMPLjl>$phJQ;5)af%wOIqY@ir%yrtr$%WH(6@1h#pJnEw?`1?$R#v{{L`->* z+7Md{^4DgThU5m?5GiB`7K!;7KA&Q={4wXY^l69W*jtM0_3(~S+-tX>esYsXs+#{9HxSo3PLCBNW55jl>t zE&GVRpd(|&iEdKh04p}d{)npG`{x&-t+S)t;8RZ#=NBx-GnM<&ExW2QaM6T!U$45U zLhC<0#C@11BU>j^=}0;u7QyPQ2fzy@M{dZ z%?k&2Xes^)IBK~@FW?}T6<$4jdHcI~_uQew*4*s0kXcvQHEY&|pc& z(np0>3g7<#u%c-}c=ZpUJe@f^&^Qz0Ti=&^NaUa5b?bW(tB zv@;DCBR=Bu{NeW{pYQ|aQj(ZtVdQ1k=1>1ycy*2CCi#we_QOdME zvsJ}lFhVUmpC{T+z10j?-}h+#$6h~9V|33|7xsAKoed_M6L8|K+_w}^b-DdS!N1-A zFwCuWZ`z4a16S_br=Q))VRhX&88{jf?KQ}Px)Efi8&1C1$&;|0r#mupe~0>0Zo|_m zjQLxiI%M9$d3;&CFXHr4P-;yVJ!dDI+-pEdtZd#o{3+QUv;88oI}ZBG_4HV39)PyU zB*`a%yBqB-zun|L1I|ugCkERhp}#_A=0X{pCmglYV7sOYIiDJ=A>*P!8#Q41 z*4hnES|w+1s<`i{crsjdV+)(va{Sx0Bj8Gv|i4d-zlxZLX-TjqCf8Ngc(_TBhSRvR`SSv1EX)ve@}l@)l}vQ*{E zyl2(SDpg!!m)x7z6=Ar0G@=|tv7YDYKE3Ytl1_S~pC3T+BzsnSLxv*-g`6jyBaTd0 z@XS3fg6XWRc+u;q-fcgQY%-v%j()PtmCimujD~8^Q(u*BeN@2rY{Z7`M;&2vzjsrL zma;EHEffdkUs1 zyTSFRZxsiB8>iaym4{bSF8V!5=7pzKc`X3q3@E9yu7w77G#|_;W0JdsLjK}rn_ns% zt`>6s?b9IttEdD8{LZTGGwJ+*OT`ie1z~7ovA^0Y?2~V&?aumm5@A9@3cvbzl!7cV zQ(g#3K{-rkhVsMGZ`7v#B-q@++(Fwx_I*!VKofu_Ov&b3GVfhM!LRC^cUsC~3mPip zD!xK~mCrj!pa2)Z9oYi<#uIiPr0RtC+`+lyjxO5AJMrXHW;&b@2+hntFF+qgS+{2O zj8G+ikA_#%w?EJs*={+8;}pX79uaW@xg8b18lV2VbO=3me^)4*Dsj zpLwYW2&>dL`>A=xj7(CkGCUez?~p?>#hsJ);@twR2cL?w#OJX{)W8VN5_+S$1e)oY z8H-<;Pk_*A1PJT?{_hIs3~E=^Awb5FI~W(!Q!})`&H=GEP5QrNwT$<=aXmo}{H-uW zWo7~z{>DEMiy#3*11(-6=ef)DrxMe$Y+1jWiRVa(yV8EYcmb(pS$b0|nJ*R)v^TLg z{oiFsQVf@OSi*fA97>8!%Yus>%tIf(l1l{vzRC1Zn!igvk<0m>*$4~&w`ZBtW3vBl zie|!_xaU8K)3dLi@iNyX3$+F09gvkO;IjC#QfV2PxLRK@g=DhY4D`SOFeC_c4wEam zNZs#Azb`5pAqcc<#;p%`2aMwu8~j`4dk#D|)PP#5UIhnCLe2iBmpI<{v2OJ(HbqR& z1$bIXw->A`!PaaT1|>s@&~n?>fIjjp{xowulNMW@yl9kc~IFeB3N*2A)~Bw6w$_(B2Szz63G zndo2vwSL;IKdE)uAZ8RU?`CUW&=PEI@t5MGFX0ltZ}#k~8C z+(lYh3YbC$W5cD4-}p0)E(LFvjq%szP!5;#Jz%&=SE)bUE!If8h?wYRBL}?g+r_R< zBURQO6#8A)nCz!37wniqZHojKamyZs*W1Jhouo z6*x`IQToMLcMDzF8830rN%PT@g;p=zw7DVg`DD=6Q`VFOuAz>z5L`J5*40;sQaFmV z{&{ODO$o_Vqv8gV?*KDcO7#Q~*D<{H*zYF{PX~UCbH#OD1uj#8%#Vn*0cxJC=Q6||H$?Z8wpycA#*k8_ECOj;{ zI#Mwy=1@}MNrZYgA*MJWhMe-|_@z}6KiHAkoBIEc;RX5(K3>Wgov@g9jSq6Qfig-t z->BrZPnp1|7^7Ogqj%?U&?s8rbT?7%euOO_@7;qLuUE&-8*av-!uFXoMj4XPK4h>J6-44PY5M4}iJfk3S?k$bXXH}N#2mDp6B ze7DzqI0vdqFIyDy`QRkutu3IB%*+4{djJeR6Iq;4iZC0%p4h+znd12PL4cZ|05C?5 zR4P@wG>@*WHtDOy`WO^N2&LHsr1B8z){L_qGUY~FxTscBV%hawAcNAHTgvP z|12#9l9no6G>5$@*ezf6P10=Cd{jZL6g5IxIo6tgJj4mpaI2b(S*gA_Nx2>Q$^5P= zU8rsR`CfMbjWy?X#OZHSk(-nW)2;h)mw{(@@YmpAkBSi zTplOC*S$6BS|1^ogm&2TXMb}}o%|U7rhw=#pSvP8If|JkkjovvNfcRt@MOY`vz#bfbvkiGJebl}^et5P3zto>jazqJ0rIp2{k55B1K z!P6?uCjP<4Lz_!co}nzqe-wjO!kQO=JS|>6;!3%C)W)j?suSQSMhmas%^`E#aaT%y z-@)p3_|IaXVs}xanIGs=qhigoTVK9>5sp8kjv`M}KWA?W%Ol1|oapL}vh~LF+v1Gt zoC)J%E?BKJVw1hnIbk=cI`0!^{mGFvT)dy&ny&KXr3i@Gg(Wz5fdim|z2fx)AN(sr z@kQonhp))1z6}s-tUFe0u(9#JiOJ&l3_zGBCM!RGN__Oxz)XqJoTIRRSM21tYib0j1KPr1>&?B0X?o>CKs(T#-Oo>Wy!i3@U666D?l8q+ zWjO55DZtaL1K$0fQ6KvW{a3r5g7W-|Z4|VKF$K&k5}PnwY=M-o`@q48vqao8keuSJ z$dx5?qCJzxn!oB7i{`bzt;_9w%^hmnEkd>{>&9Frsi%G=AKr>#Un&4BWU(Jeh9%Cl zq}yGTI-=vuqU+pH>-|Vf3^y@}x_b$f$$U6luQ+N@KqnSyUtE8_vd!RrQ<=LN z5Y?J{fqo(BxWe_WCjYKYL5B@as;*JZSB$xF+v# zO4pQCN&VzBQIH|doo=eca#5t7PSp*%&qzDi&NoBJK!IQ<)Y;kEvc&gbcF(_O1PlFqRM6*s}ZL(C>g#5 zoMXqUS7bk$wmyIU+-+;<7+7V@4~2ne%}Ikbdz$z`-OvA0xqH+ zc6Doktc1AM z&!Cu-dgGrlQOoeHH;V$W*EBS&O6ix66Gss3rY;Qs;4H!H673bmYt9UK()igqX<-0l zs--uzir%zp^z%wuIia>-BP|DwA^AAx`=gB>xP>M#^sX3X|xzwBA zeSHBK3Y{s;lkv~*ZTiT3GjDJqfMQSBELf%Mx%h3q5FnK4DBww$AnpnKEBtADS~WrX zE4!&n-$`yw33Dv`HT+OP8dsBvru@^Ni5@YuD>4exW9Ya*PhK~au6^^@5S=7e^Yw~f zQ|0Itz$BZGzNLo*?r>#%PAM(T)_(;Bh6@<3`jcqaBy&wz@IV%5B#Tq zDohc);Cm}+LLm?cW zjm-)7VH!_gwR!sR3&e6cyU#Dq9wqgMkAtGL+?#GBCfoR)p4dw=VXJA_4dJOQ0o~_x zxA3eumf|IeM~ij8KcTEEbcWm+=F2Z%RZm&qvmy~Pq3E_6qTJnR#Ijdb0T-gAn-NEYc3vJ0Pk#Nn z4CRbL!!a#Yf>+FOb{c7%nrW*iDjbSwoWID;Sg9Q=i7JS#CSUax6mXfn_rU4%WKw#` zsTpU7>U@q7Q_>g}VRE)xzDW>iKebVfdwp3ULWO*AYGCf_rp`Z|Q78-s z8-G&sl4?=H&CwA;Kx&3hizC4rX9tOjcv|Kv=3+k4BLB6v!c|P$kVZ*^ilA4ht4%>R z0*bq8NM}extwf+$H0neoFPWoviy)HfrfLl}7GDXEGos7c+``?x+K!=sE1_WRxTpz^ zspT82WlB`rKat^M#1k?ltZ+DOYi(^cLOLQ=Hj2`!HktZWIZ~DKaq3LFnj>x+*b>sH z#`iDLsAiR{qeFzqo+9q68tw&H8qx^K;TRE)#d2z1TwDx1Ga40f=gHSd8x!Hr(m6aj z(oQ2##!&m@9Lj`K;Ku!5PMrZaYf?o{UMC zh^~zMviWQy2O93pWGaxUU3{~G7>^CsWfZx#y)8!8E22B+zcGc@9rY1m}V zQrI9U)D89ni`*N3Whnbha8zJ8KSlU62b*i$OZG$zX!@_TG60qSCC~3*CJb-Y_ zD@C-jM?Y4C62{Pk_$j9-qnvGFd~}|reqioFm_ZX{&dP^y_r^gd6&Q+9+!R}dPK-M` zG3@wAJS7Bd8;VYY}A+f8t^6}W;esKc-)PpjfN=a5m z-CuR*7jlaUv#v9ymd5$kSCjO2t>R==7{e~onulbNh0slQQIe=#g0NnJ@M(c zq8bxbzKpr}42bpX#FX@xFn`7MEFc+$fj+ExeAGdz9K&2L%N=`wUaq z{gI8KgR8HCrh_G^altr>nkhUPI~YCNS?f4mV!b*ZKNo6W4c=0PG)M;zjdU_x50J!x zw`*0<9l_+O48zlPeeJl0vYn-r3lPcdQ;JSZw!uZvg#iW1*K_V()OYB7fnPSBu zX4}nwoIYsZD-;zN2rl+G0uNjO1f)@s=s+5_4l(l#yLUJ*Q8=8Co-bcs+A&1()YZeK z858f{Bvv)Fef^)WG}GW1MN;c$=4iO|mk09rY_N#Z5s@6N;zwCJ9tgb67C8xtcY3Ay z8q5&{R1&-x)c5MM+#86J+sXZVu2QZS_-rV=?+R%}C{(&uace7P?h!8r9UL6Yo1TC| zeJ}<~?xPZ8nG>RF6CWR6&iZp#S47n&qC|0n2t+F0ULl?BovTZK>%f!nuoE#Gfe)RX zHimD9Lso?U^IH$S=ah*ymr8pryaHE0^sTpcc8(t1s)yg%gmR&B@{rE@ohoC z`RcjUu*iG`uTQ=jzwAfJ^QCJMD5h|l^Q2o|92y~2(l`~Vv^%(R^qw~RoZ*2a@_|_5 z^mx~i_3BOatNz5vjB}W1ODg9;;_la4KFfvMulmS(%?$fI@B_fm7l9k3czHcvc@X|k zXu7}ieC=-O%Ia|OeI%5GT_vrEQVJRZlU*@T%Pw zxTS%IbJ(Rr@D3|>DI9$ip3VF2ajFsWQ!Sr$;(~-;#`0+|Q?Jl7^Uv5CDkZ+bD&HHR z>F3xewgBNNN&=E!X17|rVtOg%V+@uN(mS(WGY6Z;1eSS7lyi;QCr>)v(WbqJr)8$B zr)8ZVuan^W5+}rc6RzA<$)w)R&`pJm<;X}}L`mJ0>p^RT(EK|ncLE+!0zua313ew? zKG#!Y*b`a1dhpl_pVERE@-b$_<{bSeE*Y&X`D`o6^W$P zKy|UNYb^qho==}*I5h*(sUY`DoTSXZZfdy31#8fe5JHTj2c+M;@RW=?`A2DWQLvg9 zD(1gWALlLExC7BY6eh#>#&(1LBTATc#&eJ+{o3E7qoa546SGyz)m+_M??As2yxhVM z*S?tDX+5=CN|vi_SXvyoNNx@_uH~aAA?y`e+zYt>Ceo0Cv6fF7(>)$ZK$XW8e`U!< zV|#;LqRoZz1#8%v)#!(g0BwgW)8CgZlh$D;t4Ej1pGh%vdO7!Zjv4(&b=|@X;h3ga z?%{nfF{K_75Ma>NO^XR9Cnvh^#lSLF|J)Z@rj=Ht!5Ky6?BWvL#Ut@HFYwghw8MCR ze^P7iP@$AcNk1&uV<{F6$xoz5%N~88msR!LLAZ)pfTmz^;-|LD7Pg2o_P&6Oj>!b&cK zb0w_%F!q$Q#Xyh4|K} z_ITLmpK2`I+KwAQ8#s%iy1uF>F=vH%PRa_u_$(DG-|n_6ZM`w}H|1+)7fG)W_#qOi zMbo#v?PeK7a!hL^$zWC~k3x|nIZ`!>jix@@^`7l?Qbwj9fytJU7r0@R(6Qp;Z=6=+(9|kaDr)!Y^ro3zK(4s1 zFx{(z!^5E8KWLPAVhq&P`*p=<#`X+-b`)&KH3Fp`qa{092w4^PS{}?$tDObFSMw%E znY-^^Ofa^K-kPdfA)kt8@L*u`6%( zD;u}-zv1K`a7A@*5!ku8>7{XU**gkkPgS`hR_5o~_{dsG1k@$`{(KZ%hE(GAd$v^7 z@$n`+ad#K|*3f!t@=}F^!p+xfi%CHuhln2F~DXhj&T`#yUD zYM#&X2s~E`%_G<#HKTj{DoL5* z!_KD7T(A`LLg(G(PhLnzg?EeSYNw6SR0|+VM0KO#(ROcnG;o-o+4&uUr~*dS*rsjy zMxL{DZv>}ivC%+nMSu*2?;u5wkdD}U-`!$D-U!7%Lp|Nx%Rkg8TyQ30;FvT{`$xBv zma;>;a8ghcMURu_?aR4|vLu84y*&NncPa0F@#n$&@5dkELVUz*BW(RiI&_^u(gNx) ziE3Rp+L&&$N{e2O-d%b+ zGSMGjfZXM{A9)y!&&*VEk-Q#}a;)--5n@XyC~+cC^zrxawLCioxOYm-AW4%}uH~kh zW97UT0Td~sE!neS$&z?^jtzfh>0?+or_rFA$Emp&z@&Bi@dMmX(vy*==I?Ss!Afpo zT4?FssaKQif#tO?JYL7_4PTW`Fx(B9{$OuDGc)5cZTm`tRx^zXHh#UzY<~L=_iT~L zouJai{&_M@Y7u?zLU;QrQ^iE*t(eu|<(Azfz*TefMYJ=q*DG*GcPdz=mwsbmlt159 zhQOp^t1V|k?=loM3+WnD#XPBjl#+{if|5i09m0r(U-sjw5duVe7`@9i?e@-q z?SB41e^53Qq56=r75`~$h-6Rx%FqUpQF~(Fk@4Nl- zWzyr+WMpFcBrBAYQ$Z|gfVV*gMoLfae540cm(!CM*Bm?8v$eI@+1?I*)4N6HG0mm{ zQwThWzffmo?RZ;IeKI}6ZnGi{kW#t+R`}-8P4>Ab_82r9N4RTZ*0?BT)jJF*-+Y7eFi6v5`)wcrwf5{*`?%KY4w5oEAv{gM_FW=>`Zbe z&RQpz87|eW3+{1p=!?-^Gdy0SR=5z9|CDKRnUsk&J%cqGbYF10g(&l`<-X|Jq8DAJ zw>V3FbxcpevY{Fh$^qe!!Q9|Z@H)iL$u{YynC@|g!9^QDU*z#cjk~7t6H~Iq*5YU+ zZo?ju35$zQwjG8}ikO^Wo~qvmbCXi;WCKj+2t8aELiam-G$aRLa%?~iX;k|&Bl6Ai z#hwHSU1lCt9XA?(EnIfUjq)PsLhh1eKH8PZ8+vZaXFnfkZAeq*<#7+??EK9k7ZJKX zl8|rGFi!LKZg%GNJwl(z|5|8UNJpW{^Tf=!XjBXdEFz&feLY(hCu5X*tj^&{lrCT% zvO9^6H$j<0L(I}Rg;ZtDL7mR)cBdYGcD%RLY)Qd0rhxjsxVF^0BPhTYLpPgSnLsa~ zehf$7`AR+UsaiiLPOrmPX|%p-b5Q#>D%?@+2gqJ;1_)ZraM@`R)$GmPT2eN|`;T0CL=-+wWzjR#R?JSf&xQuYqoDtDAq+w1b67)FddH-FPQvTeQ^QIy# zP4j%zk!$O}$zXsyPJSI?x2{gl_$RF>DSsk<1x#gR8JBibxDe)vz0(2I!PfS6E&|ab z@9yH_(jvuIQJLhQ?$Ol1GFUrAd(JBT$mwDcf?}glOsA9+QX4}jV%c|+Mj)B~a{+@Z z$uoFyX40IRJPAGfZETRM)9R~)@PN~QPP(Hax-M0y#}1UdzV}cZnzhXZC>!!CoP0@t>gF&FaDCJJkS6j11rMptYJLx^crKOAd7XnpN7Y?qqq+ z3x~jozrBx*?hLe6W`%y_Q5CDt|Ei9lRisaSFCM!1H8B$|x%Xb29gWIUUUyHt8WdjY z3?%jHI=#)zd`~ltbAVK^%>!LhyVDr9+30cqxSNQTNj@x_bD*k9;3Y~a2Jl)omw&G= z3jcO5;whC?wqN|zw`|_4<-gPDI;Em6?ly(z4NKG*|Mcn8bwtYVj|;wZLX?y^9k)e+ zA7;9@AJ8c|j+W@kA9qut-RD?x>juA*@Xs6@V9@xr{sU-iYAQ7h2FHBHPYw^er|H^$ zym(?<8g_Zu`H)Px`jBel|^ z@d;8Y?EIL&G27g-PrWK+tubCjAy)zh^KQ13%X7y=k|^;q{FiA1WR{aus>VEZ<;wk* zs-*)h-BGRLo7+5tLa*5%e1l3Pb#l`fOgAL|z`|;hG&YKt)yfm`?2+cEPu~NQSfvKM zSo^8`eD+?Ujq}DhJ2GJ?dxMe~??No)m`Q|0pU~TObpW9O|h|+}~J`VelMH;6u66&o%OL0XK8|5%j z!$;aU$Ohra(UU$N09bo+CZXWhOG;b?jdQUqo#%B^D=9pKwQXbEy+RCe-OZ+Jt@P}IPDIdeF18gkrc-F!|5bMN-2xISB3OF zdFZZWIavFohC%5|@iAJI0lSpfbaaQQKa#u4T@fYs?K8E~z_Xu&(BHKc&mP57dHFrh z?W>^Q3|aoV2A0M6&d8WbHN5<|7X#dc{$^SG~-)QWBy>rz^NIOv09yb z^@fw!B}zNM;qUGhKaE)i;b6>=yQkacY+q}GmH9Q%_Ts4$k@!DffB!pic8HQ4>0DO~ zsQVZbLB%IgL5|b895{=H)BBG#b4CI*lddIsMgc$;OT|u=XpuisjNb8fmpgtAP7AdX zk;ghYQG3c3&U_;q%;7l!aTH{F8{lF{)UJP(h(vaFmLy13$df=J!sE&%k^ashcG_V}Qy}!X=eVA0XH%k%;1$gC0G^&cB ze#J(Cpi6)t`2NQ(`KX*IBjvc#-dtw5RrdC(8&q}FXXyq1W=oaRanrTxX;KY4?j@AV`9pYJRHA%KhIrUK46n){Z5I-V0zfAC{WUEwRYWEGB7$kfzb3VnVlsSWl# zZ8_uE!UtpMromNbknW@=khmDH7tPQu^sR@>N6%H(hA*|6^0NpVc#0e{L zsuE<)egD3kMQW_<$Wh7ksJ##?>vgHHpy21Q3SAK^amafb{YmKC@86bR3W?ja3c0jW z=+|YtZg)2H|H;j5uWs`{Jo5`68g2D=egAPsAwOlVF?#Iq@KKZ$_Qf2ax({7jN{#Fh z&qWxmY?foa`?N+kwk-oUv4w?aet%^xlRv66Gbgm0{=U0Op=tsc`?mUxfAP0KNQ~SX zChoM#Hu696x!hLpMEdJ-|NQbBcH~kR9K({dL>TBJqB?}ljMJ^Ym=GD#xj$-TNUJ-_ zH%LK2QH6P%WcgW4E?7Mu+?1! z;)I}Eaq=ZPN9R13+9du;=bJTW9wK;uK(?qf%mw4ek=mtR6{P&$VJ?REU8v@T38RhM zygD|%;=X@_bS_qD8y}e`o>qq4UZ0ZIn+vn`@pou#4AV~g^Z0J^{deV$kAz=0E=fq6 zwmVXg>V(XzW88)}QH9jBNp}G^EPn2HvgyYXZH);KsSm)a^R+((iA`7N_g>uMOU zW}09$W@Yba9Z*tHb_~85ke?#h5d!SnwxwB5mEWIITR8HFhcHfI5A>ydTs(YqMN1g~ zm?m%QjrR^~{TC~Z4pv{GRhgNN6;YMjC+DnFo<}!tH#TMPq-q@78r!t!PKMt!=ScnF zG#%+4dU9tqV5o+OF1uL}QKCHiEcE{}m78;lE?nF9l1{K`Phw;9?#I*4ywkY!>BjHu zYc~qHZO&Rm()gje&X{M*z+C{@;|p_RttZW)4cW7>6kM4#+=(nJM-d8o*Ya5m3ogk? zu+%HVsX}7Acl7`80H$d+Xyzc`rFjOqx76>nut6amB=m1>28zzVH9`unSBO(niQeEt zGft;(#(gdmDgyR-axpkYfbJDLB@$;BLzl?|gPF4G@trFs74J1jj#u1pB!B$bomO?P zNhs9*JZHSuc#EvJqNAj%wnBK5dpp8H9ojQAkac^1y_846<%Hjw71Hw)eMQs_5=s=C zBf@(5i*j4RTfI_ziP@&0FW7y?=w!h40kT0jiFR!7Z`$)C%={Yk9)ze{n5@w0aj}v4 zy)S>5)F5Fl=bY<`XRex_v%>ut(1Qa@8%FCSvvReQ!h?(aVDNe9neG& zUpNfsR1K4=ezk>C4 zHZa*Y?Zo)5(?zXwXmy_r<`PWp$<$c%d#bj=j884?8I_+aL!4sTGd?=f{lnDpJR)!^ zM`r^cQ0;z`+yz`cy$al%j>SFX zv$#xf1JmVpbW^30=yJCxmjb`U@ZUjq0AlhD9Dlmvi0+h`&Kb_WmioR=tpp0s%)^s$ z^1JV#?_sc83G;7z2nbwn{Z<;K?}R&ViZ%)_X!%o`L;=-KGmStI+R2rwLGVoX!8@Z^ z{V;;MF)g)&c^TFVx}vY*WW8NE`S&!vlqL8Ed)m{V)|g>iG=;R!&eM7J*I7-j=vy}V z*|T&e1lmuQK_-{$tTsZ@Tx+YEX-wzOG}CtfDDk8}-qt_X&bQ7tLS`fKSg*?6S;VdJ zky55Ub?1F6nR8Ll6ISbmWJoy5B+bJrpZ&P8? zR~HDk{B*C5Lsdsb+}JEI+GIyg4RDJ|Ur>#Ve!4rfFVpYoE2jP78pt-c zK$UWT%nZZ$)R#cV#aa#i7b$LbDIE|FXm_UmJ(^_?9-8j=x08nYz6K_IHQ z_)=1yqfa1q3UUu0*1$37_;}({IU%}Nv27eannVm_0t%!jF;)!<>=9uYOG~OA`k6QS za+0#L7k}R9OC7I>=n8W&f5D3`;PTDQpFwG)J;R`l)jWQ?v*VHlX$ADrntmG|w(%Oc zSKWEpVr(be?|JLit)^Zz$jsWVzc1amH4Y99>e>syY8eoG2ufqV8e)>Y$fqSvYK1?1 zq_8icunRv>D*#9p<3`s~rj@b$AC~(3ybYvCH7X!H9Y+rJ0diq5{H5uTvNj+-6sh!> zcg+tlOZ~|&#)f*t{5=NlWkPo@(zFFUKPrHQ4W!-g2_s9NT^bJZ#+y+iXpKJJ9zA%g z#bP5MEJ+rUsysAl1)@=X-8l~ps7avtPEvHQL}S78CzLJny8AK8m_6dFx~zQm;|t3l z?#c{iv5r+J1a@+9>vcL;0*&gy(NXVT8^;=Wu&pf{kV#<w6UlLXj(x1CJ@_}O`w?EpJLnRlAcL?5XNNKPPOJ2Z^05l~6_ zqpZQ@w1J{>X?dN|XAEjoF(cb(VoEezz3>Ns{u_)@B~F0q%ZK#}`I!J_E{*ed$~Rd@ z1fA-`Hv>%#CtXI`e^_M5tJzX^ilzW%FfucP z-TOl=*G7;Qn?Z~O;_IWVe}6*^R1JG9Nmz}LJuei4P7+0QOGnp1>&hT-TouC#D9`R9 zF4Ecj>OKUI!~?->H7Uz$fYT!Y>)1MeplNhnMNMka=D+wk$8<QBL%cf1-P8kAmbt znMx&~fu}z4^kRcs$B?GqlmF?!54lT__AHj^|DMPwmDxY`U%(LS&#A1LE(=Go9g8Y+ zYo?Vrp-^$3#`sODg@lAaMq-$rR={KMBT%$8M~fZ`b-FM@@{{3L|9Cp1%gZeaN$O)a zmw+Pa9TY<9+AsyiM?d_aYTSQ(L}aMel~e=Ppn!{5JyFuoR?r=-hhqi{-rd`kvEif3 z=csS)v4g>Ut&UviS^7Nz7I)YHx_ykCv*6|u;rw$~gLk7UJ7Sg}=9k-&SNf<2`!KbH+sGe7RgF~}v@WYYg)4xZbd6+`_slFd1Qs( z(kvhtjb*~xWOOnhpsCT`MTLBWc2%n+?ois8dk()tm{;kCN{#F4)nHYELul;9-oqDmtw%)= zCGTBOeIi4SA_$gVwtAY}+|!O!a|WMv>6>M9AKhrth9JnEX|n zk<Y}%pHI_Bh|2Zv%fu3zyn~^=V>YA@+jks8 zcrghyGKwp~&OMEAhA=wX-W))J;Ft`p;;y70K*R-*4oKaTSNc>+z?&0sRO`EG5@XQ7 z>nfF_2Du%FO95OFk={3gj>iI+LeKYDuRLu98*)p6v~A7B-W9`yg@u1jqv7vMBqbym z{_^v66KtUHh;&DPIMyF-9pfbZ0Q9*#9fkFNL+j?%gD5r~9UZ80AC4@3D&$g`C!HsA zu$$WeIFX_ta?%mmI8T2U2 z^6x&S+%e7~Gi8}?#IjiDLfjo6tJT0+e|1$zY%?Jj$%&tRLP3-PArOQMxK2VYe`*WP ze6&;E#rmCoBHpA|f80xC;uArBN6g2^2ar|myFH}1n(fM=X51Q}_Utx)vlw_e*?D=u z-}w7xNb3+2qx{>;2_OVdoKmV9{*zTgz9_Hm2=em!Id}L;`(Hix)(Q{YuH$6c{%gkz zQ!rZ+yZ~C{=i_U;x;*Qy$F!FG@Z0Ny`%Z>W$aw{N|iXpYjBm+%)8<6&9C z>Ises4r!Ff@$SNK=(hKG9sykbtLJFb+a$4IhSn!Sz|r+#nH1PT;?y6H*5~KvgJg%J zHQrj%T(UUK6Hu=80X+#7yq}}TDi%&-}~?djg63z z{NKhs-W4qX5TeA98sT-Q=K4xEVZVC=jq7TWVSh11a!<3z!Sh8Z zpRzSFTZ7Xq1^+SoncS^>3V6lYoV$=H%#616_por?b{mtnBem_uSa>T3 zr)G%}cM9sGHf=86?%y0IbGj;i;QN`n)CF>1Q;9i^YG(aBaL52^>T~xhV{>SX0SGe! zn37SaMtHCQNZr~icu42_WW8K8B)O7#b_`^_^F#xQf(?A6{qbbIP1JbvNkKsTXFQ=w zC;+yTH`5txkW5$72q+<8h##FIl^c;K;3e50X`IYg1vc1l*ZO4lU1bpWdWCE)Y;_fg z%hW+QO77=Qc%(aurM(wtr!!i_#lw;;-P&}`J)4HDPu!4?S&{%oMl?!+4^RgyCXZ*)O(zfD4gxWyyIqt!jq_>EyUvGg_U1KauQ>;9 zOjhcB|3<(==XMWMm4@kAijQ|OeJ2kC>`h^4TeReSOC!1=7ml04Bky2wO;|n> zmU9dXt@Dx(=PJaW@3ZNAs{hZ|;a#NS-4)M!@M@CA*2m66qR*T%9_S*W&XozHX=uU? z+{c?aqUNt2Xx%x_2CfO<6`QbcB9U`sk>A%<*Kh^AO?Y^?R8HKDuR@g_MltK3zH#N+ zkpr|Z@ZR-vW_W<>W@vBnJboXEg9hi##7w^Vr-V@<&UZS{3ORi^Xsaj`3h!DG-{aU{ZU(? zM)9z(dbA`U8)X`7{hT7P@v3!j!e4DYkeVR>J5lRBFrDRTRBNUgSa6V!r?eUKoQRYMhJt4=;&-eYy5( zl??ky?8EN@#qSf?%5si)7hys|rbr+lv>e|BtU{t4?X^e%I87)DcukIXhJ zH<7eIlGzBPcwv*0$hQS>45=cOkCn~lH?FW$DRZ=VgZ?k%!@nPYO>G~`EC zT>u?6mr%Fd@-;qs<}O^F;{-Wes|_C4QU34d?2XC~}PB{C{GxZZqpV$)i16t|vCR)&ap2ciww5HGX}a zj*o_yX6bn?4_m9el)-$#K9fe&(a+Rko3|eVMd+?+^!bAbkPR!hGXu+6=?200c9 zSV{{~RbNV^1HV?|)V7#^!dT|rgaSBbHQ^a^ zJ@)IPCW&@4mnqd?YHG~%Of5f-VfvLs>J0(JhU4v_^s{OfcM`qavNB_X`n>EQJMH>S!Ku9x;}LE3F|+HRZrovQ9^ zyZ@8TN+LhMpeI0X5YEy8iL)Q>Yg^?k$`Gf?c@sGDe5+P~^->`7{o=&eWiM~tk|rmM zpi-&Bc23#*Gk*I+7iT*6(^-v!G~8V=b8|LG=m({Xa|QqIpy@N<3lG2bWuDa{iZax^ zCT9ika?KKc<{6nsmhQNi-12H}rUMEqg`B`F-UOr7fz(8CoIO`Oik!myufU}s zFDbp`{(CW$3+b` z?{M!gfg;20+uZ3|+CR%m(EK>wu@wH`moXelWd=ZuJhqA=?NZx^ENTgJK^s+<||q;($x4!lax}wVSwW`^OfVFb5C$ z_i?3({BN4Zzh;}|@Z{s#c-Pi~>`1*xXy8WX0nH=< zb~)MRtYL2+IAd9_1~S9{`tE_OQpY(n^uz+Eh{vO1?E?~;z&S8q^tfsIqZmVo!(Wds zUuVsqR-(^$;jNrJF%ASpJXBJ#^r0lNJ!u|nbgu|GfsrDbbHI$xB>17A{HeySFA4>A z5WpJPj?sPeNG=iqa?-~wBu2DG*9hmR^O@&Yq1QnsWU^oK8RFO>1<27`gSE~>3?7(8 zBySAWV6FD79gar&@SpvYd)yIxgROqpo`zR))(mnc^ENEs&RusdK$;w7oX{&a3g0CP zkDvncbI&m9?DUjMDOu((pbVS58nmQx+-B1!aPaQ9{QliQ6F+A1cq!I78PIE{G|QV; zd%{=ompR(pr%y5RGq)o+^ws?c9T9QC{PRwHovs!aHc@O*mYS6JK6IU|nx_qLhPAYP zGXY3tZ%q7ZQ4k=BdQ_l$=Y=0D{JmB&Ni3dGn;SlK%Okl?n|vDJdvO{u4 zzqF&z^7Dmp07kJvWQKdqI}(4<9npU_0q#9k17Nuw-e>CX zu7|RrXcSRV(Qph3<&1caD1l=DgE$yYv=e$4?41D{UZVXnY)F4)lsF|Vb)mt|j_IO zcoQ@D;LimP>*v5>MjagLgTTR)3=TinX=!M_;_3hI3j<$S^=Yo?LV9lBz8xX*GN0uM z^$V!yPy;fVY=bqxKn*Z*>?6ksVlcIlxcpBNcS|OI2b}YxAGpgQbhSPCWXvy5B_GI( zeSg7T$yjZcUjeqsA2%ur5O-NNLULjbzEf5kWd{E3VyT16_1tZpTk#2=6OZbxDlG;- zCYO-EmHce5zW86BcUX*h3UI`Z6?!m&STLk4!yYe)7Pr*EeN*4X8vXRb@>NR|Sci|R z`|Im6RR>^_;Ri5G4Q6E$J>->%NJqiH1i}ZZ+;AGo%2y4%{r&k6A;26rvb7F>{4nFu zEkvXj_RU-XtIYT|5iG~kT>R{lt53Q4)#nG+(K1VHN9}JwJr6n%E)Fb z=}9`ey1LUdh$dV&;xVU$owZR&h|F_z`D##5&|#<@*0+?A`d-Q4IS+-5fW3WKA}QdU zdLtus&0gmPRY!ot=wIaH2TVV)eV+}?MM?8t;UQxu&e#8 zm`(>KgBYWnDV*x@KT#Z?DGyu;;@C%>_O%YR6mP+49P#f0PPfgF`XbZ6AvrB))z$0U z4u5=EoXmKAsNP~Y?@hg1S7du`W<4vE_@%5IzQu%Km86d3>EdLF3ErxOJZUDE$nYSU zHq2=_XcIKDswDk)5BQjlFb#n*rYlC)nECYl8`?<@a ztgfM9C=hU@?sMi$qg1MZ--vBWtVF- z8<=&)4;h#}58;o|J&R`iD)6R>xhr~U@56@=_pSeojh#G2riPP%vFY^$0y~p#*_HJb z2{@{{h%Zg6jhSjA_>B7H&RmJW=q*=T38_>kM%H*LCS2?P>C70v$`+bL1DqrJ7IyoW z=fn9$21GjNiU=A93ADg+kxy1ZW_im?+Lv8HrJZdcy2=?(b`9U<33}cA&Gtw{7 zNL2%jqlO<9_U^uth>daB3T*lPI*zro60^b|^SrYrR|>duzgBu7K^-?^qT&Tn6y#{U z8E2+UGp0@>^($c37eD6m-A!Rry3+{b^W@1Bs9-}mn;jQ0w>=l~jX;b;6MlF@ewygV zAJa;@5Km8C2Ub|}(J$enb}B3+4KS{)ttlmJs*~I zXN62DUyX5)V9~Cg8dNM}_`1zcd+%9?MQEt{Wlc60r${!P6_^u-{6YLqdpjg#u<_b|z>wl%KuQk7^EtkPK27%)NY}K2qcj zJk9;?d@*Qx91@1yipMb zp^#BiiH8p9&#ji#&7O}sz|S4p{1EO(BdO1Kg$lOVa+R<@WnMow595!CztveK)hX8@ zm#O?n<07f;Si@lDo7cg}@xh2in2N6PZzU9b3OZC)Ru+6VfDYLE=?CoU^^75ExLFN; zEY>{4XbK(gt=b*$)6FLBAlJ#1?4`URPT)}QBGI{54NOoAa_oF2?ed(&%W)_EUT!Qm zLQiR>ay_Mer))nqXy>YYHd!p|^6*LBtFigIp?(8ZDp?@GABJkK4)W5xT-W+9VV)tn z3dH<6A99#B8oEJyG>K={dLwpX$Afl8{h=kuTTsF5CEq4|S7Jo^;IvUyD*I8|i`R1O zAU7CPPq~c~Yyj7YyqJe~$K2POBUj7RX3E!$NPZQM`m5%F+p(8piO3yusV`@X4%ZF; zz${_{92@qh&up75Mgdk>T3Xt?GyOzTQj(DKGC%c^zevp#t&$TX>N&_AE>M@x7m<** zXWe;+{r#~H{F;=hk!+2S{py^}T z^18u*qI(&3way(cNG?sx@2!%Wo($jVZ}VM6iLf+i(#J2=+)xv_0KzY*kY|1y(|3PBDS^+zH9#PYQWqBFo1>S#WVfpt z_Z-+f?NTpGebCp}*9uU&p1B1#jo-?#k2x^|!~AC2CfpwY%Vg);pr47Tj+8g}8k-R? zp%-2t%HCO4CXMy=_xBgp47L878;V56FYOVD#0a}0F&GYqV`gS1HE$00_4RdkcmMfw zu^(MQtg zknQu75-{#{x7kRp78c{sTB#E3>gCvR5}9wtiv>VA@3yLyl@*{hRZ@H(zyGsrK0cy= zPrzM68)VLcX9G8oXe9w^0oE7mJMhqT4^IlkdS#MA$xZN@w&G$h2zJ#su$~s44nW}X zsqf%EE$(}+X&$LYxV2~5FBDY4dAS%)?mA?UzrP~;O|b;;9;m?_Svlc}LdIkpqbE6> z0}OY}#S_BE(0(d&e79_FUs}62OVz*sNUQtNeW?KuTMqo%B|ly7rP0e=Odx=u`C?>| zUdYl)(o3$<7ru?%PDwd!$-{=Hs}J&24{SMy>;{Y!31?^3OD_aqKq8eCPm{=FWh~Y# z$;vsbPOQ7OkzT z1*oE;BE5qZmyE12m#F`&5gc<-vNkhDDd9bZ{%-O-MML_tt3rm}aR3Oq)GMEEn-3Js z>t_h{c-fz>54vX@*kW5frJww5Qw@if{P+1HtQfmGq0Fz3TkEZAuC9($P~~OzC7VW3 z-v{s)(xbI!z*~vLRh5o}9c>=Y4)N|L6zutmg#vDv);My z81X<$*H>S}Oe4`#dGK_XYI=Vz)R{T*N~ld8u1x#$0{oko8icc?lwqJsZA35mi%#G1u8xOQ>>qpqL-*`mg=skXY5A$ zMTh`PgINU@TezMmWJdb^TyK}xsTgv?K!?mqcwgu z*FaBNedI#{>hJc?#!&@Tkj*eo%n0H7pf|{Q->EjRwwA77A-nXX+cPC%CHu7-FCgKkIzO zzmJrNU7u;V$?_`S<=;|G^L_3pHjg`=Q+1bG1&jD>TWrOnQVW&$HpO5r&ChPV$?X+M zGvSmP*zb}J)w(py9Iq$6vUmAyx;|HrSFfrOpgDZ#DS_j>^P8T4#<87GAhfi!^x+1* zGQB<*AaRrLvK%fj+^RRL(Za0(^qY2ahWM=!iF>VFrvYnLSZ=f}nP3rB^q5uC(3qW` zo}QXYf-5IH@~O=fwJtzh^^|tW5Hi33w{#xK9?PjHEzLD-lgeFhT?X4XH-(;rx$3!S>|avf?f^LsZB#>SFX8*43z3-9d;*N>JokN3=5|GnF&FfJSCFPL!E zs(ZO!Lh%8yD%6vAWW&u6XwI#DDUvM5zVcjTj!aO}P*KVEPby!nlDg2HBi)!tNFCk^ zzn+V8eXemT&SUI)`8^c80Y@~P^A(HDcdwHi_&4dzs6~@v8`p0C*Ewv*xy+2MFx-9Y zJjdfnrf!f3*7Z8rwetEgcK&+fF4w^`ik$d*wS+wn8Ox~klA!eDvR*Pz&leFES;*Dc ze#kWDBp9Y~8ht8U{Df$Fp|t$tt&dF3^M-G?W66kw124Q>YI*=s5OoW&WkKIHF8a*RG!*DFm2Qk4=Avl#Lr#3;T9 zQ7q9vHfGGtFp0|iMm{{=%Q@bov>gWl=oVN;-~WogcIHX-)a!hS1j3AJ)JMdX*x&p6 zjY|P8=5)DM;r$TQLlm#BaqGqyfA&(y99QRPm6Q}mxI3+U>fp=#mpm0U;b$y=^0R?6 z$;yMHzIb2!c{R?QFsPX+ukH}^W=mb2Ge1)m!>Dw!vi+^#xj7u}nnAToXw*^w21?%9 zky-m_r{(Wqfg&i?T5@o_$-@;tU(V(rWR*MG&ORft&6Z8M1!mtqR$X6a!)pWYX@3yq zuuKU}@<&MxbbSJMk!`1QRc=j)!&gP(M=1__S-8S;>aKBB^QPvJabon_FgPW~Jm@g0Q>$ z+Lq(W(FgI_l;diI1aCg9)W zQ7o2ob}GU>u7_1$PTYZi+)IF+?j!wxVCZgF>+wUo3sKx~lanSJ19Mf`mPb3&2Nffm z!CiW(7B6Z>rFqLeS{sZkBk9d;E=0XC&{e}vYCMBvU+KR>9oYjp)$rEhN(mCOrj^5H>$m_4xbw$ivIoT|Y+n+rH7JgMf;;;7=S)k;hs1jAgu{C!b@n zck5>~mq*)=It4R=58L4&8;<2uyIqOEze`- z5}@{~R8QM*3GTYKN_;Z~?trRQ(gP@)2Qaq1jjj{}l<$S?E4buxde{qYRlK9|0My6YD^#rm`PTWeZC@pI)?n>li z&T7@AFGiBVFu7i!*~3x9-Uj&+d#Z%Hf9H2Z?_n!cNbr2x>jrAmC%0EC!2f@J<%X zJDYeII=88&eWwoBWf@%TtL^9SKT>*fkPhF0k8GG9*laFDd>E5pp-Uh<%jSv@!6 zfK^N&bbEYvt$mhl_xQD$jK3y7`%e(!^+9rc>4jbpKHV`T#EpR#>4ARjZ?NQ1jKp?e z$U)&&$cU0sJ*BTQi77dIsa^g*gI={%mi+;^sIyG=lJtP%t{)0M_PE4>e~AR!FH9ld ze|OW|0ww;)v_1%U_qoC7d`ol=4@figF_c3I_67MA%kX)DEjq*qCT6_tL#$Y?s>T1 zktVfLX|3vt>UzH$*FBX!dI9m*Cl!*Gx^%-Xmeb=bS27B2VQQ*tTfQDDt+&e zxVE0{p8M!(_a9-tFGC~#t(!vHy>)GeNVE6m6lQ1pcj-y$_oC3UlI6uIH>+r!z1oYEboRPLQUjowe<^KHROK%-=A8cSG z`2u&?+URqwmeJwutf#@vw&Ad1$j|DK*-ZANROY+sg&S&iLl{Xd?#zlmt7J-y!woP1 z3vG(>p>*2N{#HrM{SBI&gl~_wU6s4v4k*!?cR@E6lq!FUuxe;e6-eJQ5B~1^qYb7C4AYTXk4( za*Eyct@G})%@$KMImmBb7B9c4-78*Pd8eGwLLEqJp8DyqAa#GECz_WlT6U&)+W;3g zEom>3Z1?=&A+M7kr_xa4#+AVm@dg{-XkA~r2j|gM8!;b^yio@~LF_>VA8uot@awA; zZ5oMf7qPtkduD!wn1FZt>!zmf98ThtbSy0_1nQy+h|VkHRUB`N{Q?(aZF@{JvKa6v znHuM1kBVRG*A1HToiDe%jD2wRn(!C13akgd(bs|G5x6jYD6I`1v!v1y4HJsr~sD5Zx&aWrQ zqU}4Q?qgNHoZZl-+eUd(4Yj(pwRN{kQI2vLs+&wdDxF$#p%8d$NmPNZo5fP;IrTst zmVm8g;~&51d%WJMo3R4tx){+{I&^k(tG`Yvj#K6nCmLCV_@gvTH@mvKtAxRVIED_{ zR+!i7mWqr@i$u+&_AHxT1IXH9J0kbGRFeYsbB-EGh;&F#Ee<(zVpJON3NDRJ=rzH3 zsR7G$qios z9I`d$NOw_-TP17wR0W817T ze$%~^)DTJ$k^|5#&3I=~KboLKttYj-%`r4JwLrbUelOqa5RP~vC{uu-PW#RxO>!Zk z2$KZtGjY+7)a})*zk2x+Nl0qO}qZboIY%C1{)N%^cVLm?xdNWp|mDqBmpOM z7nt^w@vo5R9~U2X!F*#h8qZVw6M>A&%LTKy`YTIP^Cq{FWJBPb(vAZcDGm0x*nAiM zTSb`m6<#nt-Ss1>_Xb}q1UuxcAD*<*3T6P?>?rLzfQ5&QIO~DK_-Xe#MlCr5?+uTT z&BdWE9O{2qG-_olHebS=WD4Y*>S}s0je!xhwA_XDOQ{~F9tmh(28T4Jlq9~3eih3x zT-3`9SG;9(dAeftpD2g*oYH2B)Y6?fOwOu_aR1dLKUHkA?q&~P4e+&j4-Zh@HyVow z)HN=jUA-{ybey$Ocdn-NDR}_II?ysOH6{3O<6$`Ic7#4v?LL~w5!yli!7Pw_)N{W(kxX{BRL;3Bpdx9&U?RKg00I* zs|1ciBSXU@a@et=9d7(NKg(Mx;)o35I8XOwZh|Vuyy-W;ON7iIK^+WqkUfIx0iMsE zDIH&Ct*4Cq1Vus$3T`?d+|Nc|VBFW^SYO`stz|6_2cIAYq^?O1Ev&DY;N-6-;-{uQ zV^YpkI^vP`DY^_erf~z&m!lOq#oFjdUawulDNrKlMA^ zCds`{kJTj1h8uSYcK;7X@^Ry$MS)Dq3-|X%bryI|x%P*`Y9n=)(y6~YFp_Ye=o<6i zP;eu2vxwr)k(oe+y_yh``$GxEKV^e`$g|7kW|FhJ9$vP?NDW~#t>T?7lJep5h zwivx%eYifwl)bd@@Czq3GVd(zw%Rpj%&Qd_KZU?A690fU0YPdnfcYB(78OK=3;G@0 zf=4&Ak!qN(n|03rj22ze6$}<`w#Q9cV}S&yr0Z5wnRgFei#*$d0n|j{cIWU&^SUih z*QxE))=}3QLyvfLPWNOZ;w}poYZ&v zSQ14!JF+d%+!HF8rCDbok$4SOJ(U>>$3TTRUv&Aip(QK>`y@-o4@lat9o+(`xU-rv`XX9Th|c##_qPG)wXQ0 z6Y-0eA}`5tq!gLkhHOuC%qm>txz<}{J-B(7`tXd)wO>+;ZE}+ zn}A}bC)@I!=+{PWA@RuQ>WsG20wa&GSSZ!uh@vf3t34j0i;! zP2o4y>}DIdE1LiHbA|qm48Gl()lesXp;mj!%ydHdc(=!Huirejt+aggO00b3iausg z{eFzQWC;%8rpl*(U$0BY;pfY@dGGA6B5@=#X{OL|`-G zOKu-4A-q%Ti3eGUDgn6W{XZr8XpJj+Jh~}m^KpJ2K-|UUVd&1GqufhA;7UK=8_D#- z6@nThDeRaMUHnK=sD{I=4i~ag@czz5qk+)5bK_e5*Vae|cNu{x-oGlY53&rR^h;JS zXjMMG@W=Zbbchr}3ZhO6NF;gdKwfov5`GbODnnqDir8wYLe+OMH6r3t<52wEoWG4C zwGTzMl>3d?tEGVKB~w#mttDf_Q>-sgGC+;S%}OiRYH~*{fv`p*<&j}0HrHH|>z80v>ko#z<0W|U2MUG11Q+j*{ z+FTQWVQ1;!t3J-~LPWmAV*UH;hTr?EW{7@89%uM7VKrow(KKr_ocnZsT zqplKpOP5)|Y_U?XK&ewh)nJS@Vw6N)O1qOL25XxuDk=w+&4MPWk@B^%@%cbAYy4#KP!o2l@oTc!f`$$qI!p9l>gI|SH-iDj z9>91i)uCjQMOdC?FDc2aMp<$*Kzaac%zC|fY7*6_{MoFe>%a}r1+dMq<5Ed3w5^a` zOu7O~4s0b_4#i6!wPX*Hpc256C&#TcDn26e8mEb1uTPgFZRoKLMqSv52wc z5g-$d(jSmESa^n#;N8XKoVaxld9flJz7(eOm|JgZ4m8FDjm zJ0Uqu62;hSZRe_ccAkY}1izXt4)n2Cl{eoNs)T5N#^H>e4!#%d$7Qi}dv?~yIG zO92{jA$xp4`a_$9X8zs{1g{?Yj#h38Qc-)~poIuAZCzDq<+ps*b>L`O_G7|%$sUK` z)=e_42X*A);%hx-z~wS(k=}mf>?MJi_MJx>~~B=u)?{x+ihgf7F7! zsJ?lF)h6wx$ItwC$k7+2|IXDuG{cR@tH!L#dpDf|Z;oziQve|~pF}($ShWV}R1%|e z?r<|KlI7gk@G|kpxYhNQZl9}?Ri7_NcwFqeKdk^eg_ZVlTmV1-_3Zy zq$01QL5Wm?^|ZG^+eH@K8DVfeYYr`tWo}PeS5C+X!$z!!^6V{h4DpP#iTM}~y{(|f zoq_!Cy9WL9x+`-`ON##-9UW!LYQOmTsn~K-RA*~?QTPX;v0Q}3#BlIAk_}KQ{IG`= zDCzu^-g)19z&3AbM|m#_JGGf^vM472^)B0BtR%v@+VUlwzPp1ytra@~DlEF;GE}iDF%3n8G7i>U|KyzdEjG}p3Rr& zy@qp>ehN5w+4f8#^#+`^o2t5ERj6X$x$PXQlQ*^Qf@{Z5t?hc&LDZTi*=2uh0q zp)nqyXqW=RVH&H7yGxnV2;P&yyniQ#P=XBa9H$pvjy*3_Xl;n=PPjrm7_eL=-bU91 z9&EK|glz;ddvR;LG2?Tw%3ea^hPN)A==21Tn4^Bk)zRWNGHp$16D}*i{A85aTzZ+@ zHl?m{s6Xf!vN~s`SVt;fMB=itvcNDikeieOn=y?gkcz?Uh9~k(t^FKZqS_rpgI7S<<8# zjk$5tRNlh7UbcV}2<3&fK)1gcECo8&4LvMJD{KUp2dlsrHt7@=22=H1+kZ4`bdHz8StgMj6ir@5z1LJW%6!2l_x> z-IgF_*zvNQZ0(jhm(`7qabRbP>|!8kaa(&`eT}3XsK;NZTeU+@C~LEb)-g`;>x|@C zp${sp#OL8ddQZtGV9A3BoZ5#VstO$;GV1x$GD!Y)#Uq2pj14}rufG%Mo2#|le7qd% zXa%0oGklA9T&8&Z8~>qkWAwfm9~`HY5Y#f;f$rkb{UY^53$3ofV$}O$Bzt4OQ`{(9 zEzoM=MT<0ovT@aCAmMw9htR3LcKYZMyg0Wuz!P3N$$c|vQ2>0a>qXB0dd(_t1AMJ0 z**%X#nV(~#h2^M++P7}PFNg9p;-17+64hQs3yk`PczDPfVAy0|eL-Rsh|lkQG|;ua z81-goXefT7X{d$b_ep;G#0z&q57&;7?GLFK*P$tNz$Nd+sek>BZRg`2bE-$0loP+L z?L;gumU)t1#C;*soeLcyeYE-FkV@3Rd6P;YqW?smy9<;#*BQRFXDC(djB~@C|ABYj z-8Gw79sHecl%wu@PJ>e%?PRX2D<&47XjI)ctdy{%FEv<+nFQTB8d{yB=tLpKgSEJ< z>|`9MHjPSWOdfsqzQbVZ+$v!E7$?(^?~27mbjqQmFwz1bO;0pBTg?=D!R$5;ekUaLpc_7oBIb3!#jiCiQ)&Yujhk zzH@l4q=@ij3e8ekOKjP^z#GLA;&?dY_vhd5q4g7)KY7mtwJC%bXQFncZT){I)s#wE*0#E3rs-U zXyX&IH3Q-w`^1*9P}3=9ti{A|=ZYS==}9~`uPw97%yxpBCPA_%{{wxfVR2v^Nn}Uc zJf;kG5kS$p1=~3S$Jsc-6_<$;lV?chKDBrZs`PS8p3LGM@fy7-4L~w zK%;x0a2IJc{YLCVyXmI*dFprWe^vHgH2AO4PS^OZxzGb!-1wuK^uh&q zKOFk@hq2*dD!QZk&<(+TAf!ri{9}*TZgmdwT{;c+ixIbRQguk6sdVhrI^EHssx-6! z8{}WOkAbe!?LTPCGO0h_53d^R@!;(&9|ypE-K^$&0{*{I{*MBwW8Cam6rq5UT>O5! z(aGHT&88*x$|Sm%`n;MeVseW(AHmhR=ZJj(Xn~8`7^q;HcHQ3-o@DF=mI%!wg65?t zQ0MNoewZxgW5dz;SFPgvRLprCdUuG^Ii@>rR63Y$=5RZAiO2TYe!{QD@ck|yE!TgE&StG+6WSK}(S#9*N6_j&%J zq5M~LrL>#XWn6Nytv_hk6FWPyiGp7Z25r|aC*L{n7kt|NKTmh^*F3t5g~p>6R1&U@ z+|@r9HwrCtZ9nP8hU-ATUIO?#&hG^NFnUxLxxdZ1 z-3cc6DHmDt8+6O({+H(@c+A;9`xOTE7Z38|G&*%ivCzQxmKh<2a2@^ P7inO+hC1ci_7VRJDe(vc literal 0 HcmV?d00001 diff --git a/Threaded Binary Tree/Images/Partial.png b/Threaded Binary Tree/Images/Partial.png new file mode 100644 index 0000000000000000000000000000000000000000..4436df2f44689f5fc699e2c139899e818ced4b85 GIT binary patch literal 11218 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 I#V5i44@=D^t^fc4 literal 0 HcmV?d00001 diff --git a/Threaded Binary Tree/README.markdown b/Threaded Binary Tree/README.markdown index d75809d7d..bc812ee6a 100644 --- a/Threaded Binary Tree/README.markdown +++ b/Threaded Binary Tree/README.markdown @@ -20,16 +20,18 @@ children last. In-order traversal of any binary tree generally goes as follows: +```swift +func traverse(n: Node?) { + if (n == nil) { return + } else { + traverse(n.left) + visit(n) + traverse(n.right) + } +} ``` -traverse(n): - if (n == NULL) return - else: - traverse(n->left) - visit n - traverse(n->right) -``` -Where `n` is a pointer to a node in the tree (or `NULL`), each node stores -pointers to its children as `left` and `right`, and "visiting" a node can mean +Where `n` is a a node in the tree (or `nil`), each node stores +its children as `left` and `right`, and "visiting" a node can mean performing any desired action on it. We would call this function by passing to it the root of the tree we wish to traverse. @@ -48,9 +50,9 @@ A threaded binary tree fixes this problem. An in-order traversal of a tree yields a linear ordering of the nodes. Thus each node has both a predecessor and a successor (except for the first and last nodes, which only have a successor or a predecessor respectively). In a -threaded binary tree, each left child pointer that would normally be `NULL` +threaded binary tree, each left child pointer that would normally be `nil` instead points to the node's predecessor (if it exists), and each right child -pointer that would normally be `NULL` instead points to the node's successor +pointer that would normally be `nil` instead points to the node's successor (if it exists). This is what separates threaded binary trees from standard binary trees. @@ -80,31 +82,31 @@ threaded binary tree is much more efficient than the recursive algorithm outlined above. We use these predecessor/successor attributes to great effect in this new algorithm (note that this is for a forward traversal): -``` +```swift traverse(root): - if (root == NULL) return + if (root == nil) return // Find the leftmost Node - Node *n = root - while (n->left != NULL): - n = n->left + Node n = root + while (n.left != nil): + n = n.left - while (n != NULL): + while (n != nil): visit n // If this Node is a thread Node, then go to its in-order successor - if (n->rightThread): - n = n->right + if (n.rightThread): + n = n.right // Else go to the leftmost Node in its right subtree else: - n = n->right - while (n->left != NULL): - n = n->left + n = n.right + while (n.left != nil): + n = n.left ``` Where: -- `root` is a pointer to the root of the tree (or `NULL`). -- Each node stores pointers to its children or predecessor/successor as `left` +- `root` is the root of the tree (or `nil`). +- Each node stores its children or predecessor/successor as `left` and `right`. - "Visiting" a node can mean performing any desired action on it. - The booleans `leftThread` and `rightThread` keep track of whether `left` and @@ -113,8 +115,8 @@ Where: - While `leftThread` is not used here, it would be used in a backwards traversal in a double threaded tree or a single threaded tree "pointing" the other direction. -- The first node in the traversal has `leftThread = true` and `left = NULL` -- The last node in the traversal has `rightThread = true` and `right = NULL` +- The first node in the traversal has `leftThread = true` and `left = nil` +- The last node in the traversal has `rightThread = true` and `right = nil` ## An example diff --git a/Threaded Binary Tree/ThreadedBinaryTree.swift b/Threaded Binary Tree/ThreadedBinaryTree.swift index f83dd4592..10f955580 100644 --- a/Threaded Binary Tree/ThreadedBinaryTree.swift +++ b/Threaded Binary Tree/ThreadedBinaryTree.swift @@ -1,5 +1,6 @@ /* - A threaded binary tree based on this club's binary search tree implementation. + A Threaded Binary Tree. + Based on this club's Binary Search Tree implementation. Each node stores a value and two children. The left child contains a smaller value; the right a larger (or equal) value. @@ -18,6 +19,10 @@ public class ThreadedBinaryTree { private(set) public var left: ThreadedBinaryTree? private(set) public var right: ThreadedBinaryTree? + //threaded + private(set) public var leftThread: ThreadedBinaryTree? + private(set) public var rightThread: ThreadedBinaryTree? + public init(value: T) { self.value = value } @@ -87,6 +92,10 @@ extension ThreadedBinaryTree { } else { left = ThreadedBinaryTree(value: value) left?.parent = parent + //threaded + left?.leftThread = leftThread + left?.rightThread = parent + leftThread = nil } } else { if let right = right { @@ -94,6 +103,10 @@ extension ThreadedBinaryTree { } else { right = ThreadedBinaryTree(value: value) right?.parent = parent + //threaded + right?.rightThread = rightThread + right?.leftThread = parent + rightThread = nil } } } @@ -103,7 +116,7 @@ extension ThreadedBinaryTree { extension ThreadedBinaryTree { /* - Deletes a node from the tree. + Deletes the "highest" node with the specified value. Returns the node that has replaced this removed one (or nil if this was a leaf node). That is primarily useful for when you delete the root node, in @@ -111,22 +124,45 @@ extension ThreadedBinaryTree { Performance: runs in O(h) time, where h is the height of the tree. */ + //threaded + public func remove(value: T) -> ThreadedBinaryTree? { + return search(value)?.remove() + } + + /* + Deletes "this" node from the tree. + */ public func remove() -> ThreadedBinaryTree? { let replacement: ThreadedBinaryTree? if let left = left { if let right = right { replacement = removeNodeWithTwoChildren(left, right) + //threaded + replacement?.leftThread = leftThread + replacement?.rightThread = rightThread + left.maximum().rightThread = replacement + right.minimum().leftThread = replacement } else { // This node only has a left child. The left child replaces the node. replacement = left + //threaded + left.maximum().rightThread = rightThread } } else if let right = right { // This node only has a right child. The right child replaces the node. replacement = right + //threaded + right.minimum().leftThread = leftThread } else { // This node has no children. We just disconnect it from its parent. replacement = nil + //threaded + if isLeftChild { + parent?.leftThread = leftThread + } else { + parent?.rightThread = rightThread + } } reconnectParentToNode(replacement) @@ -135,11 +171,14 @@ extension ThreadedBinaryTree { parent = nil left = nil right = nil + //threaded + leftThread = nil + rightThread = nil return replacement } - private func removeNodeWithTwoChildren(left: ThreadedBinaryTree, _ right: BinarySearchTree) -> BinarySearchTree { + private func removeNodeWithTwoChildren(left: ThreadedBinaryTree, _ right: ThreadedBinaryTree) -> ThreadedBinaryTree { // This node has two children. It must be replaced by the smallest // child that is larger than this node's value, which is the leftmost // descendent of the right child. @@ -272,12 +311,16 @@ extension ThreadedBinaryTree { if let left = left { return left.maximum() } else { + /* var node = self while case let parent? = node.parent { if parent.value < value { return parent } node = parent } return nil + */ + //threaded + return leftThread } } @@ -288,12 +331,16 @@ extension ThreadedBinaryTree { if let right = right { return right.minimum() } else { + /* var node = self while case let parent? = node.parent { if parent.value > value { return parent } node = parent } return nil + */ + //threaded + return rightThread } } } @@ -302,9 +349,22 @@ extension ThreadedBinaryTree { extension ThreadedBinaryTree { public func traverseInOrder(@noescape process: T -> Void) { + /* left?.traverseInOrder(process) process(value) right?.traverseInOrder(process) + */ + //threaded + var n: ThreadedBinaryTree + n = minimum() + while true { + process(n.value) + if let successor = n.successor() { + n = successor + } else { + break + } + } } public func traversePreOrder(@noescape process: T -> Void) { @@ -332,7 +392,7 @@ extension ThreadedBinaryTree { } /* - Is this binary tree a valid binary search tree? + Is this threaded binary tree a valid binary search tree? */ extension ThreadedBinaryTree { public func isBST(minValue minValue: T, maxValue: T) -> Bool { @@ -343,6 +403,35 @@ extension ThreadedBinaryTree { } } +/* + Is this binary tree properly threaded? + Either left or leftThread (but not both) must be nil (likewise for right). + The first and last nodes in the in-order traversal are exempt from this, + as the first has leftThread = nil, and the last has rightThread = nil. +*/ +//threaded +extension ThreadedBinaryTree { + public func isThreaded() -> Bool { + if self === minimum() { + if left != nil && leftThread != nil { + return false + } + } else if (left == nil && leftThread == nil) || (left != nil && leftThread != nil) { + return false + } + if self === maximum() { + if right != nil && rightThread != nil { + return false + } + } else if (right == nil && rightThread == nil) || (right != nil && rightThread != nil) { + return false + } + let leftThreaded = left?.isThreaded() ?? true + let rightThreaded = right?.isThreaded() ?? true + return leftThreaded && rightThreaded + } +} + // MARK: - Debugging extension ThreadedBinaryTree: CustomStringConvertible { @@ -371,6 +460,13 @@ extension ThreadedBinaryTree: CustomDebugStringConvertible { if let right = right { s += ", right = [" + right.debugDescription + "]" } + //threaded + if let leftThread = leftThread { + s += ", leftThread: \(leftThread.value)" + } + if let rightThread = rightThread { + s += ", rightThread: \(rightThread.value)" + } return s } @@ -378,3 +474,70 @@ extension ThreadedBinaryTree: CustomDebugStringConvertible { return map { $0 } } } + +/* + TESTS + I don't have an Apple computer, so I can't make a Playground or any of that + fancy stuff. Here's a simple demonstration of the ThreadedBinaryTree class. + It follows the illustrations in the README. +*/ + +// Simple little debug function to make testing output pretty +private func check(tree: ThreadedBinaryTree) { + print("Overview:") + print(tree) + print("Debug Info:") + print(tree.debugDescription) + print("In-Order Traversal:") + let myArray = tree.toArray() + for node in myArray { + print(node) + } + if tree.isThreaded() { + print("This threaded binary tree is VALID.") + } else { + print("This threaded binary tree is INVALID.") + } +} + + +print("\nFull Balanced Binary Tree with 7 Nodes") +let fullTree = ThreadedBinaryTree(value: 4) +fullTree.insert(2) +fullTree.insert(6) +fullTree.insert(1) +fullTree.insert(3) +fullTree.insert(5) +fullTree.insert(7) +check(fullTree) + + +print("\n\nUnbalanced Binary Tree with 5 Nodes") +let tree = ThreadedBinaryTree(array: [9, 5, 12, 2, 7]) +check(tree) + +print("\nInsert 10") +tree.insert(10) +check(tree) + +print("\nInsert 4") +tree.insert(4) +check(tree) + +print("\nRemove 13 (Not in the Tree)") +tree.remove(13) +check(tree) + +print("\nRemove 5") +tree.remove(5) +check(tree) + +print("\nRemove 7") +tree.remove(7) +check(tree) + +print("\nRemove 10") +tree.remove(10) +check(tree) + +print("\n\nDone with Tests!\n") diff --git a/Threaded Binary Tree/ThreadedBinaryTreeBackup.swift b/Threaded Binary Tree/ThreadedBinaryTreeBackup.swift new file mode 100644 index 000000000..10f955580 --- /dev/null +++ b/Threaded Binary Tree/ThreadedBinaryTreeBackup.swift @@ -0,0 +1,543 @@ +/* + A Threaded Binary Tree. + Based on this club's Binary Search Tree implementation. + + Each node stores a value and two children. The left child contains a smaller + value; the right a larger (or equal) value. + + Any nodes that lack either a left or right child instead keep track of their + in-order predecessor and/or successor. + + This tree allows duplicate elements. + + This tree does not automatically balance itself. To make sure it is balanced, + you should insert new values in randomized order, not in sorted order. +*/ +public class ThreadedBinaryTree { + private(set) public var value: T + private(set) public var parent: ThreadedBinaryTree? + private(set) public var left: ThreadedBinaryTree? + private(set) public var right: ThreadedBinaryTree? + + //threaded + private(set) public var leftThread: ThreadedBinaryTree? + private(set) public var rightThread: ThreadedBinaryTree? + + public init(value: T) { + self.value = value + } + + public convenience init(array: [T]) { + precondition(array.count > 0) + self.init(value: array.first!) + for v in array.dropFirst() { + insert(v, parent: self) + } + } + + public var isRoot: Bool { + return parent == nil + } + + public var isLeaf: Bool { + return left == nil && right == nil + } + + public var isLeftChild: Bool { + return parent?.left === self + } + + public var isRightChild: Bool { + return parent?.right === self + } + + public var hasLeftChild: Bool { + return left != nil + } + + public var hasRightChild: Bool { + return right != nil + } + + public var hasAnyChild: Bool { + return hasLeftChild || hasRightChild + } + + public var hasBothChildren: Bool { + return hasLeftChild && hasRightChild + } + + /* How many nodes are in this subtree. Performance: O(n). */ + public var count: Int { + return (left?.count ?? 0) + 1 + (right?.count ?? 0) + } +} + +// MARK: - Adding items + +extension ThreadedBinaryTree { + /* + Inserts a new element into the tree. You should only insert elements + at the root, to make to sure this remains a valid binary tree! + Performance: runs in O(h) time, where h is the height of the tree. + */ + public func insert(value: T) { + insert(value, parent: self) + } + + private func insert(value: T, parent: ThreadedBinaryTree) { + if value < self.value { + if let left = left { + left.insert(value, parent: left) + } else { + left = ThreadedBinaryTree(value: value) + left?.parent = parent + //threaded + left?.leftThread = leftThread + left?.rightThread = parent + leftThread = nil + } + } else { + if let right = right { + right.insert(value, parent: right) + } else { + right = ThreadedBinaryTree(value: value) + right?.parent = parent + //threaded + right?.rightThread = rightThread + right?.leftThread = parent + rightThread = nil + } + } + } +} + +// MARK: - Deleting items + +extension ThreadedBinaryTree { + /* + Deletes the "highest" node with the specified value. + + Returns the node that has replaced this removed one (or nil if this was a + leaf node). That is primarily useful for when you delete the root node, in + which case the tree gets a new root. + + Performance: runs in O(h) time, where h is the height of the tree. + */ + //threaded + public func remove(value: T) -> ThreadedBinaryTree? { + return search(value)?.remove() + } + + /* + Deletes "this" node from the tree. + */ + public func remove() -> ThreadedBinaryTree? { + let replacement: ThreadedBinaryTree? + + if let left = left { + if let right = right { + replacement = removeNodeWithTwoChildren(left, right) + //threaded + replacement?.leftThread = leftThread + replacement?.rightThread = rightThread + left.maximum().rightThread = replacement + right.minimum().leftThread = replacement + } else { + // This node only has a left child. The left child replaces the node. + replacement = left + //threaded + left.maximum().rightThread = rightThread + } + } else if let right = right { + // This node only has a right child. The right child replaces the node. + replacement = right + //threaded + right.minimum().leftThread = leftThread + } else { + // This node has no children. We just disconnect it from its parent. + replacement = nil + //threaded + if isLeftChild { + parent?.leftThread = leftThread + } else { + parent?.rightThread = rightThread + } + } + + reconnectParentToNode(replacement) + + // The current node is no longer part of the tree, so clean it up. + parent = nil + left = nil + right = nil + //threaded + leftThread = nil + rightThread = nil + + return replacement + } + + private func removeNodeWithTwoChildren(left: ThreadedBinaryTree, _ right: ThreadedBinaryTree) -> ThreadedBinaryTree { + // This node has two children. It must be replaced by the smallest + // child that is larger than this node's value, which is the leftmost + // descendent of the right child. + let successor = right.minimum() + + // If this in-order successor has a right child of its own (it cannot + // have a left child by definition), then that must take its place. + successor.remove() + + // Connect our left child with the new node. + successor.left = left + left.parent = successor + + // Connect our right child with the new node. If the right child does + // not have any left children of its own, then the in-order successor + // *is* the right child. + if right !== successor { + successor.right = right + right.parent = successor + } else { + successor.right = nil + } + + // And finally, connect the successor node to our parent. + return successor + } + + private func reconnectParentToNode(node: ThreadedBinaryTree?) { + if let parent = parent { + if isLeftChild { + parent.left = node + } else { + parent.right = node + } + } + node?.parent = parent + } +} + +// MARK: - Searching + +extension ThreadedBinaryTree { + /* + Finds the "highest" node with the specified value. + Performance: runs in O(h) time, where h is the height of the tree. + */ + public func search(value: T) -> ThreadedBinaryTree? { + var node: ThreadedBinaryTree? = self + while case let n? = node { + if value < n.value { + node = n.left + } else if value > n.value { + node = n.right + } else { + return node + } + } + return nil + } + + /* + // Recursive version of search + public func search(value: T) -> ThreadedBinaryTree? { + if value < self.value { + return left?.search(value) + } else if value > self.value { + return right?.search(value) + } else { + return self // found it! + } + } + */ + + public func contains(value: T) -> Bool { + return search(value) != nil + } + + /* + Returns the leftmost descendent. O(h) time. + */ + public func minimum() -> ThreadedBinaryTree { + var node = self + while case let next? = node.left { + node = next + } + return node + } + + /* + Returns the rightmost descendent. O(h) time. + */ + public func maximum() -> ThreadedBinaryTree { + var node = self + while case let next? = node.right { + node = next + } + return node + } + + /* + Calculates the depth of this node, i.e. the distance to the root. + Takes O(h) time. + */ + public func depth() -> Int { + var node = self + var edges = 0 + while case let parent? = node.parent { + node = parent + edges += 1 + } + return edges + } + + /* + Calculates the height of this node, i.e. the distance to the lowest leaf. + Since this looks at all children of this node, performance is O(n). + */ + public func height() -> Int { + if isLeaf { + return 0 + } else { + return 1 + max(left?.height() ?? 0, right?.height() ?? 0) + } + } + + /* + Finds the node whose value precedes our value in sorted order. + */ + public func predecessor() -> ThreadedBinaryTree? { + if let left = left { + return left.maximum() + } else { + /* + var node = self + while case let parent? = node.parent { + if parent.value < value { return parent } + node = parent + } + return nil + */ + //threaded + return leftThread + } + } + + /* + Finds the node whose value succeeds our value in sorted order. + */ + public func successor() -> ThreadedBinaryTree? { + if let right = right { + return right.minimum() + } else { + /* + var node = self + while case let parent? = node.parent { + if parent.value > value { return parent } + node = parent + } + return nil + */ + //threaded + return rightThread + } + } +} + +// MARK: - Traversal + +extension ThreadedBinaryTree { + public func traverseInOrder(@noescape process: T -> Void) { + /* + left?.traverseInOrder(process) + process(value) + right?.traverseInOrder(process) + */ + //threaded + var n: ThreadedBinaryTree + n = minimum() + while true { + process(n.value) + if let successor = n.successor() { + n = successor + } else { + break + } + } + } + + public func traversePreOrder(@noescape process: T -> Void) { + process(value) + left?.traversePreOrder(process) + right?.traversePreOrder(process) + } + + public func traversePostOrder(@noescape process: T -> Void) { + left?.traversePostOrder(process) + right?.traversePostOrder(process) + process(value) + } + + /* + Performs an in-order traversal and collects the results in an array. + */ + public func map(@noescape formula: T -> T) -> [T] { + var a = [T]() + if let left = left { a += left.map(formula) } + a.append(formula(value)) + if let right = right { a += right.map(formula) } + return a + } +} + +/* + Is this threaded binary tree a valid binary search tree? +*/ +extension ThreadedBinaryTree { + public func isBST(minValue minValue: T, maxValue: T) -> Bool { + if value < minValue || value > maxValue { return false } + let leftBST = left?.isBST(minValue: minValue, maxValue: value) ?? true + let rightBST = right?.isBST(minValue: value, maxValue: maxValue) ?? true + return leftBST && rightBST + } +} + +/* + Is this binary tree properly threaded? + Either left or leftThread (but not both) must be nil (likewise for right). + The first and last nodes in the in-order traversal are exempt from this, + as the first has leftThread = nil, and the last has rightThread = nil. +*/ +//threaded +extension ThreadedBinaryTree { + public func isThreaded() -> Bool { + if self === minimum() { + if left != nil && leftThread != nil { + return false + } + } else if (left == nil && leftThread == nil) || (left != nil && leftThread != nil) { + return false + } + if self === maximum() { + if right != nil && rightThread != nil { + return false + } + } else if (right == nil && rightThread == nil) || (right != nil && rightThread != nil) { + return false + } + let leftThreaded = left?.isThreaded() ?? true + let rightThreaded = right?.isThreaded() ?? true + return leftThreaded && rightThreaded + } +} + +// MARK: - Debugging + +extension ThreadedBinaryTree: CustomStringConvertible { + public var description: String { + var s = "" + if let left = left { + s += "(\(left.description)) <- " + } + s += "\(value)" + if let right = right { + s += " -> (\(right.description))" + } + return s + } +} + +extension ThreadedBinaryTree: CustomDebugStringConvertible { + public var debugDescription: String { + var s = "value: \(value)" + if let parent = parent { + s += ", parent: \(parent.value)" + } + if let left = left { + s += ", left = [" + left.debugDescription + "]" + } + if let right = right { + s += ", right = [" + right.debugDescription + "]" + } + //threaded + if let leftThread = leftThread { + s += ", leftThread: \(leftThread.value)" + } + if let rightThread = rightThread { + s += ", rightThread: \(rightThread.value)" + } + return s + } + + public func toArray() -> [T] { + return map { $0 } + } +} + +/* + TESTS + I don't have an Apple computer, so I can't make a Playground or any of that + fancy stuff. Here's a simple demonstration of the ThreadedBinaryTree class. + It follows the illustrations in the README. +*/ + +// Simple little debug function to make testing output pretty +private func check(tree: ThreadedBinaryTree) { + print("Overview:") + print(tree) + print("Debug Info:") + print(tree.debugDescription) + print("In-Order Traversal:") + let myArray = tree.toArray() + for node in myArray { + print(node) + } + if tree.isThreaded() { + print("This threaded binary tree is VALID.") + } else { + print("This threaded binary tree is INVALID.") + } +} + + +print("\nFull Balanced Binary Tree with 7 Nodes") +let fullTree = ThreadedBinaryTree(value: 4) +fullTree.insert(2) +fullTree.insert(6) +fullTree.insert(1) +fullTree.insert(3) +fullTree.insert(5) +fullTree.insert(7) +check(fullTree) + + +print("\n\nUnbalanced Binary Tree with 5 Nodes") +let tree = ThreadedBinaryTree(array: [9, 5, 12, 2, 7]) +check(tree) + +print("\nInsert 10") +tree.insert(10) +check(tree) + +print("\nInsert 4") +tree.insert(4) +check(tree) + +print("\nRemove 13 (Not in the Tree)") +tree.remove(13) +check(tree) + +print("\nRemove 5") +tree.remove(5) +check(tree) + +print("\nRemove 7") +tree.remove(7) +check(tree) + +print("\nRemove 10") +tree.remove(10) +check(tree) + +print("\n\nDone with Tests!\n") From ac9abb4ae8ed5589911630cd85d1f7588a7dd0d8 Mon Sep 17 00:00:00 2001 From: Jayson Tung Date: Mon, 2 May 2016 20:55:09 -0400 Subject: [PATCH 0308/1679] Touch up ThreadedBinaryTree and begin testing --- Threaded Binary Tree/README.markdown | 53 +++---- Threaded Binary Tree/ThreadedBinaryTree.swift | 132 +++++++++--------- 2 files changed, 92 insertions(+), 93 deletions(-) diff --git a/Threaded Binary Tree/README.markdown b/Threaded Binary Tree/README.markdown index bc812ee6a..d78030e4b 100644 --- a/Threaded Binary Tree/README.markdown +++ b/Threaded Binary Tree/README.markdown @@ -22,18 +22,18 @@ In-order traversal of any binary tree generally goes as follows: ```swift func traverse(n: Node?) { - if (n == nil) { return - } else { - traverse(n.left) - visit(n) - traverse(n.right) - } + if (n == nil) { return + } else { + traverse(n.left) + visit(n) + traverse(n.right) + } } ``` -Where `n` is a a node in the tree (or `nil`), each node stores -its children as `left` and `right`, and "visiting" a node can mean -performing any desired action on it. We would call this function by passing to -it the root of the tree we wish to traverse. +Where `n` is a a node in the tree (or `nil`), each node stores its children as +`left` and `right`, and "visiting" a node can mean performing any desired +action on it. We would call this function by passing to it the root of the +tree we wish to traverse. While simple and understandable, this algorithm uses stack space proportional to the height of the tree due to its recursive nature. If the tree has **n** @@ -83,26 +83,19 @@ outlined above. We use these predecessor/successor attributes to great effect in this new algorithm (note that this is for a forward traversal): ```swift -traverse(root): - if (root == nil) return - - // Find the leftmost Node - Node n = root - while (n.left != nil): - n = n.left - - while (n != nil): - visit n - - // If this Node is a thread Node, then go to its in-order successor - if (n.rightThread): - n = n.right - - // Else go to the leftmost Node in its right subtree - else: - n = n.right - while (n.left != nil): - n = n.left +func traverse(root: Node) { + var n: ThreadedBinaryTree + // Start at the leftmost Node + n = root.minimum() + while true { + visit(n) + if let successor = n.successor() { + n = successor + } else { + break + } + } +} ``` Where: - `root` is the root of the tree (or `nil`). diff --git a/Threaded Binary Tree/ThreadedBinaryTree.swift b/Threaded Binary Tree/ThreadedBinaryTree.swift index 10f955580..b1ae8d0bf 100644 --- a/Threaded Binary Tree/ThreadedBinaryTree.swift +++ b/Threaded Binary Tree/ThreadedBinaryTree.swift @@ -19,7 +19,7 @@ public class ThreadedBinaryTree { private(set) public var left: ThreadedBinaryTree? private(set) public var right: ThreadedBinaryTree? - //threaded + //THREADED private(set) public var leftThread: ThreadedBinaryTree? private(set) public var rightThread: ThreadedBinaryTree? @@ -92,7 +92,7 @@ extension ThreadedBinaryTree { } else { left = ThreadedBinaryTree(value: value) left?.parent = parent - //threaded + //THREADED left?.leftThread = leftThread left?.rightThread = parent leftThread = nil @@ -103,7 +103,7 @@ extension ThreadedBinaryTree { } else { right = ThreadedBinaryTree(value: value) right?.parent = parent - //threaded + //THREADED right?.rightThread = rightThread right?.leftThread = parent rightThread = nil @@ -124,7 +124,7 @@ extension ThreadedBinaryTree { Performance: runs in O(h) time, where h is the height of the tree. */ - //threaded + //THREADED public func remove(value: T) -> ThreadedBinaryTree? { return search(value)?.remove() } @@ -138,7 +138,7 @@ extension ThreadedBinaryTree { if let left = left { if let right = right { replacement = removeNodeWithTwoChildren(left, right) - //threaded + //THREADED replacement?.leftThread = leftThread replacement?.rightThread = rightThread left.maximum().rightThread = replacement @@ -146,18 +146,18 @@ extension ThreadedBinaryTree { } else { // This node only has a left child. The left child replaces the node. replacement = left - //threaded + //THREADED left.maximum().rightThread = rightThread } } else if let right = right { // This node only has a right child. The right child replaces the node. replacement = right - //threaded + //THREADED right.minimum().leftThread = leftThread } else { // This node has no children. We just disconnect it from its parent. replacement = nil - //threaded + //THREADED if isLeftChild { parent?.leftThread = leftThread } else { @@ -171,7 +171,7 @@ extension ThreadedBinaryTree { parent = nil left = nil right = nil - //threaded + //THREADED leftThread = nil rightThread = nil @@ -241,13 +241,14 @@ extension ThreadedBinaryTree { /* // Recursive version of search + // Educational but undesirable due to the overhead cost of recursion public func search(value: T) -> ThreadedBinaryTree? { if value < self.value { return left?.search(value) } else if value > self.value { return right?.search(value) } else { - return self // found it! + return self } } */ @@ -311,15 +312,7 @@ extension ThreadedBinaryTree { if let left = left { return left.maximum() } else { - /* - var node = self - while case let parent? = node.parent { - if parent.value < value { return parent } - node = parent - } - return nil - */ - //threaded + //THREADED return leftThread } } @@ -331,15 +324,7 @@ extension ThreadedBinaryTree { if let right = right { return right.minimum() } else { - /* - var node = self - while case let parent? = node.parent { - if parent.value > value { return parent } - node = parent - } - return nil - */ - //threaded + //THREADED return rightThread } } @@ -348,17 +333,12 @@ extension ThreadedBinaryTree { // MARK: - Traversal extension ThreadedBinaryTree { - public func traverseInOrder(@noescape process: T -> Void) { - /* - left?.traverseInOrder(process) - process(value) - right?.traverseInOrder(process) - */ - //threaded + //THREADED + public func traverseInOrderForward(@noescape visit: T -> Void) { var n: ThreadedBinaryTree n = minimum() while true { - process(n.value) + visit(n.value) if let successor = n.successor() { n = successor } else { @@ -366,17 +346,31 @@ extension ThreadedBinaryTree { } } } + + //THREADED + public func traverseInOrderBackward(@noescape visit: T -> Void) { + var n: ThreadedBinaryTree + n = maximum() + while true { + visit(n.value) + if let predecessor = n.predecessor() { + n = predecessor + } else { + break + } + } + } - public func traversePreOrder(@noescape process: T -> Void) { - process(value) - left?.traversePreOrder(process) - right?.traversePreOrder(process) + public func traversePreOrder(@noescape visit: T -> Void) { + visit(value) + left?.traversePreOrder(visit) + right?.traversePreOrder(visit) } - public func traversePostOrder(@noescape process: T -> Void) { - left?.traversePostOrder(process) - right?.traversePostOrder(process) - process(value) + public func traversePostOrder(@noescape visit: T -> Void) { + left?.traversePostOrder(visit) + right?.traversePostOrder(visit) + visit(value) } /* @@ -384,33 +378,41 @@ extension ThreadedBinaryTree { */ public func map(@noescape formula: T -> T) -> [T] { var a = [T]() - if let left = left { a += left.map(formula) } - a.append(formula(value)) - if let right = right { a += right.map(formula) } + //THREADED + var n: ThreadedBinaryTree + n = minimum() + while true { + a.append(formula(n.value)) + if let successor = n.successor() { + n = successor + } else { + break + } + } return a } } -/* - Is this threaded binary tree a valid binary search tree? -*/ +// MARK: - Verification + extension ThreadedBinaryTree { + /* + Is this threaded binary tree a valid binary search tree? + */ public func isBST(minValue minValue: T, maxValue: T) -> Bool { if value < minValue || value > maxValue { return false } let leftBST = left?.isBST(minValue: minValue, maxValue: value) ?? true let rightBST = right?.isBST(minValue: value, maxValue: maxValue) ?? true return leftBST && rightBST } -} -/* - Is this binary tree properly threaded? - Either left or leftThread (but not both) must be nil (likewise for right). - The first and last nodes in the in-order traversal are exempt from this, - as the first has leftThread = nil, and the last has rightThread = nil. -*/ -//threaded -extension ThreadedBinaryTree { + /* + Is this binary tree properly threaded? + Either left or leftThread (but not both) must be nil (likewise for right). + The first and last nodes in the in-order traversal are exempt from this, + as the first has leftThread = nil, and the last has rightThread = nil. + */ + //THREADED public func isThreaded() -> Bool { if self === minimum() { if left != nil && leftThread != nil { @@ -460,7 +462,7 @@ extension ThreadedBinaryTree: CustomDebugStringConvertible { if let right = right { s += ", right = [" + right.debugDescription + "]" } - //threaded + //THREADED if let leftThread = leftThread { s += ", leftThread: \(leftThread.value)" } @@ -479,12 +481,12 @@ extension ThreadedBinaryTree: CustomDebugStringConvertible { TESTS I don't have an Apple computer, so I can't make a Playground or any of that fancy stuff. Here's a simple demonstration of the ThreadedBinaryTree class. - It follows the illustrations in the README. + It follows the examples in the README. */ // Simple little debug function to make testing output pretty private func check(tree: ThreadedBinaryTree) { - print("Overview:") + print("\(tree.count) Total Nodes:"); print(tree) print("Debug Info:") print(tree.debugDescription) @@ -499,7 +501,11 @@ private func check(tree: ThreadedBinaryTree) { print("This threaded binary tree is INVALID.") } } - + + +print("\nTree with Single Node") +let emptyTree = ThreadedBinaryTree(value: 1) +check(emptyTree) print("\nFull Balanced Binary Tree with 7 Nodes") let fullTree = ThreadedBinaryTree(value: 4) From 0bf400802f7d5f824936529192254fee5c487439 Mon Sep 17 00:00:00 2001 From: Jayson Tung Date: Mon, 2 May 2016 22:46:36 -0400 Subject: [PATCH 0309/1679] Add traversal details to Threaded README --- Threaded Binary Tree/README.markdown | 114 +++++++++++++++++++++------ 1 file changed, 88 insertions(+), 26 deletions(-) diff --git a/Threaded Binary Tree/README.markdown b/Threaded Binary Tree/README.markdown index d78030e4b..ad8337f83 100644 --- a/Threaded Binary Tree/README.markdown +++ b/Threaded Binary Tree/README.markdown @@ -2,7 +2,7 @@ A threaded binary tree is a special kind of [binary tree](../Binary Tree/) (a tree in which each node has at most two children) that maintains a few extra -pointers to allow cheap and fast **in-order traversal** of the tree. +variables to allow cheap and fast **in-order traversal** of the tree. If you don't know what a tree is or what it is for, then [read this first](../Tree/). @@ -50,11 +50,10 @@ A threaded binary tree fixes this problem. An in-order traversal of a tree yields a linear ordering of the nodes. Thus each node has both a predecessor and a successor (except for the first and last nodes, which only have a successor or a predecessor respectively). In a -threaded binary tree, each left child pointer that would normally be `nil` -instead points to the node's predecessor (if it exists), and each right child -pointer that would normally be `nil` instead points to the node's successor -(if it exists). This is what separates threaded binary trees from standard -binary trees. +threaded binary tree, each left child that would normally be `nil` instead +stores the node's predecessor (if it exists), and each right child that would +normally be `nil` instead stores the node's successor (if it exists). This is +what separates threaded binary trees from standard binary trees. There are two types of threaded binary trees: single threaded and double threaded: @@ -75,20 +74,70 @@ has a right child but no left child, it will track its predecessor in place of its left child. +## Representation + +Before we go into detail about the methods that we can apply to threaded binary +trees, it might be a good idea to explain how we will be representing the tree. +The core of this data structure is the `ThreadedBinaryTree` +class. Each instance of this class represents a node with six member +variables: `value`, `parent`, `left`, `right`, `leftThread`, and +`rightThread`. Of all of these, only `value` is required. The other five are +Swift *optionals*. +- `value: T` is the value of this node (e.g. 1, 2, A, B, etc.) +- `parent: ThreadedBinaryTree?` is the parent of this node (if it exists) +- `left: ThreadedBinaryTree?` is the left child of this node (if it exists) +- `right: ThreadedBinaryTree?` is the right child of this node (if it exists) +- `leftThread: ThreadedBinaryTree?` is the in-order predecessor of this node +- `rightThread: ThreadedBinaryTree?` is the in-order successor of this node + +Now we are ready to go over some of the member functions in our +`ThreadedBinaryTree` class. + + ## Traversal algorithm +Let's start with the main reason we're using a threaded binary tree. It is now +very easy to find the in-order predecessor and the in-order successor of any +node in the tree. If the node has no left/right child, we can simply return +the node's leftThread/rightThread. Otherwise, it is trivial to move down the +tree and find the correct node. + +```swift + func predecessor() -> ThreadedBinaryTree? { + if let left = left { + return left.maximum() + } else { + return leftThread + } + } + + func successor() -> ThreadedBinaryTree? { + if let right = right { + return right.minimum() + } else { + return rightThread + } + } +``` +> Note: `maximum()` and `minimum()` are methods of `ThreadedBinaryTree` which +return the largest/smallest node in a given sub-tree. See [the +implementation](ThreadedBinaryTree.swift) for more detail. + +Because these are `ThreadedBinaryTree` methods, we can call +`node.predecessor()` or `node.successor()` to obtain the predecessor or +successor of any `node`, provided that `node` is a `ThreadedBinaryTree` object. + Because predecessors and/or successors are tracked, an in-order traversal of a threaded binary tree is much more efficient than the recursive algorithm outlined above. We use these predecessor/successor attributes to great effect -in this new algorithm (note that this is for a forward traversal): +in this new algorithm for both forward and backward traversals: ```swift -func traverse(root: Node) { +func traverseInOrderForward(visit: T -> Void) { var n: ThreadedBinaryTree - // Start at the leftmost Node - n = root.minimum() + n = minimum() while true { - visit(n) + visit(n.value) if let successor = n.successor() { n = successor } else { @@ -96,23 +145,35 @@ func traverse(root: Node) { } } } + +func traverseInOrderBackward(visit: T -> Void) { + var n: ThreadedBinaryTree + n = maximum() + while true { + visit(n.value) + if let predecessor = n.predecessor() { + n = predecessor + } else { + break + } + } +} ``` -Where: -- `root` is the root of the tree (or `nil`). -- Each node stores its children or predecessor/successor as `left` - and `right`. -- "Visiting" a node can mean performing any desired action on it. -- The booleans `leftThread` and `rightThread` keep track of whether `left` and - `right` point to a child or a predecessor/successor. - - They are `true` for predecessors/successors, and `false` for children. - - While `leftThread` is not used here, it would be used in a backwards - traversal in a double threaded tree or a single threaded tree "pointing" - the other direction. -- The first node in the traversal has `leftThread = true` and `left = nil` -- The last node in the traversal has `rightThread = true` and `right = nil` +Again, this a method of `ThreadedBinaryTree`, so we'd call it like +`node.traverseInorderForward(visitFunction)`. Note that we are able to specify +a function that executes on each node as they are visited. This function can +be anything you want, as long as it accepts `T` (the type of the values of the +nodes of the tree) and has no return value. + +## Insertion and deletion -## An example +The quick in-order traversal that a threaded binary trees gives us comes at a +small cost. Inserting/deleting nodes becomes more complicated, as we have to +continuously manage the `leftThread` and `rightThread` variables. It is best +to explain this with an example. Please note that this requires knowledge of +binary search trees, so make sure you have [read this first](../Binary Search +Tree/). ### Still under construction. @@ -121,4 +182,5 @@ Where: [Threaded Binary Tree on Wikipedia](https://en.wikipedia.org/wiki/Threaded_binary_tree). -*Written for the Swift Algorithm Club by Jayson Tung* +*Written for the Swift Algorithm Club by [Jayson +Tung](https://github.com/JFTung)* From 791456994bb225b1b83d5c3a14f3649e4cf5f4ec Mon Sep 17 00:00:00 2001 From: Jayson Tung Date: Mon, 2 May 2016 22:58:05 -0400 Subject: [PATCH 0310/1679] Fix README link and delete unnecessary backup --- Threaded Binary Tree/README.markdown | 16 +- .../ThreadedBinaryTreeBackup.swift | 543 ------------------ 2 files changed, 8 insertions(+), 551 deletions(-) delete mode 100644 Threaded Binary Tree/ThreadedBinaryTreeBackup.swift diff --git a/Threaded Binary Tree/README.markdown b/Threaded Binary Tree/README.markdown index ad8337f83..ba654ea07 100644 --- a/Threaded Binary Tree/README.markdown +++ b/Threaded Binary Tree/README.markdown @@ -4,8 +4,8 @@ A threaded binary tree is a special kind of [binary tree](../Binary Tree/) (a tree in which each node has at most two children) that maintains a few extra variables to allow cheap and fast **in-order traversal** of the tree. -If you don't know what a tree is or what it is for, then [read this -first](../Tree/). +If you don't know what a tree is or what it is for, then +[read this first](../Tree/). ## In-order traversal @@ -120,8 +120,8 @@ tree and find the correct node. } ``` > Note: `maximum()` and `minimum()` are methods of `ThreadedBinaryTree` which -return the largest/smallest node in a given sub-tree. See [the -implementation](ThreadedBinaryTree.swift) for more detail. +return the largest/smallest node in a given sub-tree. See +[the implementation](ThreadedBinaryTree.swift) for more detail. Because these are `ThreadedBinaryTree` methods, we can call `node.predecessor()` or `node.successor()` to obtain the predecessor or @@ -172,8 +172,8 @@ The quick in-order traversal that a threaded binary trees gives us comes at a small cost. Inserting/deleting nodes becomes more complicated, as we have to continuously manage the `leftThread` and `rightThread` variables. It is best to explain this with an example. Please note that this requires knowledge of -binary search trees, so make sure you have [read this first](../Binary Search -Tree/). +binary search trees, so make sure you have +[read this first](../Binary Search Tree/). ### Still under construction. @@ -182,5 +182,5 @@ Tree/). [Threaded Binary Tree on Wikipedia](https://en.wikipedia.org/wiki/Threaded_binary_tree). -*Written for the Swift Algorithm Club by [Jayson -Tung](https://github.com/JFTung)* +*Written for the Swift Algorithm Club by +[Jayson Tung](https://github.com/JFTung)* diff --git a/Threaded Binary Tree/ThreadedBinaryTreeBackup.swift b/Threaded Binary Tree/ThreadedBinaryTreeBackup.swift deleted file mode 100644 index 10f955580..000000000 --- a/Threaded Binary Tree/ThreadedBinaryTreeBackup.swift +++ /dev/null @@ -1,543 +0,0 @@ -/* - A Threaded Binary Tree. - Based on this club's Binary Search Tree implementation. - - Each node stores a value and two children. The left child contains a smaller - value; the right a larger (or equal) value. - - Any nodes that lack either a left or right child instead keep track of their - in-order predecessor and/or successor. - - This tree allows duplicate elements. - - This tree does not automatically balance itself. To make sure it is balanced, - you should insert new values in randomized order, not in sorted order. -*/ -public class ThreadedBinaryTree { - private(set) public var value: T - private(set) public var parent: ThreadedBinaryTree? - private(set) public var left: ThreadedBinaryTree? - private(set) public var right: ThreadedBinaryTree? - - //threaded - private(set) public var leftThread: ThreadedBinaryTree? - private(set) public var rightThread: ThreadedBinaryTree? - - public init(value: T) { - self.value = value - } - - public convenience init(array: [T]) { - precondition(array.count > 0) - self.init(value: array.first!) - for v in array.dropFirst() { - insert(v, parent: self) - } - } - - public var isRoot: Bool { - return parent == nil - } - - public var isLeaf: Bool { - return left == nil && right == nil - } - - public var isLeftChild: Bool { - return parent?.left === self - } - - public var isRightChild: Bool { - return parent?.right === self - } - - public var hasLeftChild: Bool { - return left != nil - } - - public var hasRightChild: Bool { - return right != nil - } - - public var hasAnyChild: Bool { - return hasLeftChild || hasRightChild - } - - public var hasBothChildren: Bool { - return hasLeftChild && hasRightChild - } - - /* How many nodes are in this subtree. Performance: O(n). */ - public var count: Int { - return (left?.count ?? 0) + 1 + (right?.count ?? 0) - } -} - -// MARK: - Adding items - -extension ThreadedBinaryTree { - /* - Inserts a new element into the tree. You should only insert elements - at the root, to make to sure this remains a valid binary tree! - Performance: runs in O(h) time, where h is the height of the tree. - */ - public func insert(value: T) { - insert(value, parent: self) - } - - private func insert(value: T, parent: ThreadedBinaryTree) { - if value < self.value { - if let left = left { - left.insert(value, parent: left) - } else { - left = ThreadedBinaryTree(value: value) - left?.parent = parent - //threaded - left?.leftThread = leftThread - left?.rightThread = parent - leftThread = nil - } - } else { - if let right = right { - right.insert(value, parent: right) - } else { - right = ThreadedBinaryTree(value: value) - right?.parent = parent - //threaded - right?.rightThread = rightThread - right?.leftThread = parent - rightThread = nil - } - } - } -} - -// MARK: - Deleting items - -extension ThreadedBinaryTree { - /* - Deletes the "highest" node with the specified value. - - Returns the node that has replaced this removed one (or nil if this was a - leaf node). That is primarily useful for when you delete the root node, in - which case the tree gets a new root. - - Performance: runs in O(h) time, where h is the height of the tree. - */ - //threaded - public func remove(value: T) -> ThreadedBinaryTree? { - return search(value)?.remove() - } - - /* - Deletes "this" node from the tree. - */ - public func remove() -> ThreadedBinaryTree? { - let replacement: ThreadedBinaryTree? - - if let left = left { - if let right = right { - replacement = removeNodeWithTwoChildren(left, right) - //threaded - replacement?.leftThread = leftThread - replacement?.rightThread = rightThread - left.maximum().rightThread = replacement - right.minimum().leftThread = replacement - } else { - // This node only has a left child. The left child replaces the node. - replacement = left - //threaded - left.maximum().rightThread = rightThread - } - } else if let right = right { - // This node only has a right child. The right child replaces the node. - replacement = right - //threaded - right.minimum().leftThread = leftThread - } else { - // This node has no children. We just disconnect it from its parent. - replacement = nil - //threaded - if isLeftChild { - parent?.leftThread = leftThread - } else { - parent?.rightThread = rightThread - } - } - - reconnectParentToNode(replacement) - - // The current node is no longer part of the tree, so clean it up. - parent = nil - left = nil - right = nil - //threaded - leftThread = nil - rightThread = nil - - return replacement - } - - private func removeNodeWithTwoChildren(left: ThreadedBinaryTree, _ right: ThreadedBinaryTree) -> ThreadedBinaryTree { - // This node has two children. It must be replaced by the smallest - // child that is larger than this node's value, which is the leftmost - // descendent of the right child. - let successor = right.minimum() - - // If this in-order successor has a right child of its own (it cannot - // have a left child by definition), then that must take its place. - successor.remove() - - // Connect our left child with the new node. - successor.left = left - left.parent = successor - - // Connect our right child with the new node. If the right child does - // not have any left children of its own, then the in-order successor - // *is* the right child. - if right !== successor { - successor.right = right - right.parent = successor - } else { - successor.right = nil - } - - // And finally, connect the successor node to our parent. - return successor - } - - private func reconnectParentToNode(node: ThreadedBinaryTree?) { - if let parent = parent { - if isLeftChild { - parent.left = node - } else { - parent.right = node - } - } - node?.parent = parent - } -} - -// MARK: - Searching - -extension ThreadedBinaryTree { - /* - Finds the "highest" node with the specified value. - Performance: runs in O(h) time, where h is the height of the tree. - */ - public func search(value: T) -> ThreadedBinaryTree? { - var node: ThreadedBinaryTree? = self - while case let n? = node { - if value < n.value { - node = n.left - } else if value > n.value { - node = n.right - } else { - return node - } - } - return nil - } - - /* - // Recursive version of search - public func search(value: T) -> ThreadedBinaryTree? { - if value < self.value { - return left?.search(value) - } else if value > self.value { - return right?.search(value) - } else { - return self // found it! - } - } - */ - - public func contains(value: T) -> Bool { - return search(value) != nil - } - - /* - Returns the leftmost descendent. O(h) time. - */ - public func minimum() -> ThreadedBinaryTree { - var node = self - while case let next? = node.left { - node = next - } - return node - } - - /* - Returns the rightmost descendent. O(h) time. - */ - public func maximum() -> ThreadedBinaryTree { - var node = self - while case let next? = node.right { - node = next - } - return node - } - - /* - Calculates the depth of this node, i.e. the distance to the root. - Takes O(h) time. - */ - public func depth() -> Int { - var node = self - var edges = 0 - while case let parent? = node.parent { - node = parent - edges += 1 - } - return edges - } - - /* - Calculates the height of this node, i.e. the distance to the lowest leaf. - Since this looks at all children of this node, performance is O(n). - */ - public func height() -> Int { - if isLeaf { - return 0 - } else { - return 1 + max(left?.height() ?? 0, right?.height() ?? 0) - } - } - - /* - Finds the node whose value precedes our value in sorted order. - */ - public func predecessor() -> ThreadedBinaryTree? { - if let left = left { - return left.maximum() - } else { - /* - var node = self - while case let parent? = node.parent { - if parent.value < value { return parent } - node = parent - } - return nil - */ - //threaded - return leftThread - } - } - - /* - Finds the node whose value succeeds our value in sorted order. - */ - public func successor() -> ThreadedBinaryTree? { - if let right = right { - return right.minimum() - } else { - /* - var node = self - while case let parent? = node.parent { - if parent.value > value { return parent } - node = parent - } - return nil - */ - //threaded - return rightThread - } - } -} - -// MARK: - Traversal - -extension ThreadedBinaryTree { - public func traverseInOrder(@noescape process: T -> Void) { - /* - left?.traverseInOrder(process) - process(value) - right?.traverseInOrder(process) - */ - //threaded - var n: ThreadedBinaryTree - n = minimum() - while true { - process(n.value) - if let successor = n.successor() { - n = successor - } else { - break - } - } - } - - public func traversePreOrder(@noescape process: T -> Void) { - process(value) - left?.traversePreOrder(process) - right?.traversePreOrder(process) - } - - public func traversePostOrder(@noescape process: T -> Void) { - left?.traversePostOrder(process) - right?.traversePostOrder(process) - process(value) - } - - /* - Performs an in-order traversal and collects the results in an array. - */ - public func map(@noescape formula: T -> T) -> [T] { - var a = [T]() - if let left = left { a += left.map(formula) } - a.append(formula(value)) - if let right = right { a += right.map(formula) } - return a - } -} - -/* - Is this threaded binary tree a valid binary search tree? -*/ -extension ThreadedBinaryTree { - public func isBST(minValue minValue: T, maxValue: T) -> Bool { - if value < minValue || value > maxValue { return false } - let leftBST = left?.isBST(minValue: minValue, maxValue: value) ?? true - let rightBST = right?.isBST(minValue: value, maxValue: maxValue) ?? true - return leftBST && rightBST - } -} - -/* - Is this binary tree properly threaded? - Either left or leftThread (but not both) must be nil (likewise for right). - The first and last nodes in the in-order traversal are exempt from this, - as the first has leftThread = nil, and the last has rightThread = nil. -*/ -//threaded -extension ThreadedBinaryTree { - public func isThreaded() -> Bool { - if self === minimum() { - if left != nil && leftThread != nil { - return false - } - } else if (left == nil && leftThread == nil) || (left != nil && leftThread != nil) { - return false - } - if self === maximum() { - if right != nil && rightThread != nil { - return false - } - } else if (right == nil && rightThread == nil) || (right != nil && rightThread != nil) { - return false - } - let leftThreaded = left?.isThreaded() ?? true - let rightThreaded = right?.isThreaded() ?? true - return leftThreaded && rightThreaded - } -} - -// MARK: - Debugging - -extension ThreadedBinaryTree: CustomStringConvertible { - public var description: String { - var s = "" - if let left = left { - s += "(\(left.description)) <- " - } - s += "\(value)" - if let right = right { - s += " -> (\(right.description))" - } - return s - } -} - -extension ThreadedBinaryTree: CustomDebugStringConvertible { - public var debugDescription: String { - var s = "value: \(value)" - if let parent = parent { - s += ", parent: \(parent.value)" - } - if let left = left { - s += ", left = [" + left.debugDescription + "]" - } - if let right = right { - s += ", right = [" + right.debugDescription + "]" - } - //threaded - if let leftThread = leftThread { - s += ", leftThread: \(leftThread.value)" - } - if let rightThread = rightThread { - s += ", rightThread: \(rightThread.value)" - } - return s - } - - public func toArray() -> [T] { - return map { $0 } - } -} - -/* - TESTS - I don't have an Apple computer, so I can't make a Playground or any of that - fancy stuff. Here's a simple demonstration of the ThreadedBinaryTree class. - It follows the illustrations in the README. -*/ - -// Simple little debug function to make testing output pretty -private func check(tree: ThreadedBinaryTree) { - print("Overview:") - print(tree) - print("Debug Info:") - print(tree.debugDescription) - print("In-Order Traversal:") - let myArray = tree.toArray() - for node in myArray { - print(node) - } - if tree.isThreaded() { - print("This threaded binary tree is VALID.") - } else { - print("This threaded binary tree is INVALID.") - } -} - - -print("\nFull Balanced Binary Tree with 7 Nodes") -let fullTree = ThreadedBinaryTree(value: 4) -fullTree.insert(2) -fullTree.insert(6) -fullTree.insert(1) -fullTree.insert(3) -fullTree.insert(5) -fullTree.insert(7) -check(fullTree) - - -print("\n\nUnbalanced Binary Tree with 5 Nodes") -let tree = ThreadedBinaryTree(array: [9, 5, 12, 2, 7]) -check(tree) - -print("\nInsert 10") -tree.insert(10) -check(tree) - -print("\nInsert 4") -tree.insert(4) -check(tree) - -print("\nRemove 13 (Not in the Tree)") -tree.remove(13) -check(tree) - -print("\nRemove 5") -tree.remove(5) -check(tree) - -print("\nRemove 7") -tree.remove(7) -check(tree) - -print("\nRemove 10") -tree.remove(10) -check(tree) - -print("\n\nDone with Tests!\n") From 75a94e38556a1de73cc3b4cf46c1d7115b365a97 Mon Sep 17 00:00:00 2001 From: Jayson Tung Date: Tue, 3 May 2016 12:28:09 -0400 Subject: [PATCH 0311/1679] Finish threaded bin. tree images --- Threaded Binary Tree/Images/DelOne.png | Bin 17173 -> 0 bytes Threaded Binary Tree/Images/DelThree.png | Bin 11596 -> 0 bytes Threaded Binary Tree/Images/DelTwo.png | Bin 13594 -> 0 bytes .../Images/{AddOne.png => Insert1.png} | Bin .../Images/{AddTwo.png => Insert2.png} | Bin Threaded Binary Tree/Images/Insert3.png | Bin 0 -> 20386 bytes Threaded Binary Tree/Images/Remove1.png | Bin 0 -> 17019 bytes Threaded Binary Tree/Images/Remove2.png | Bin 0 -> 14090 bytes Threaded Binary Tree/Images/Remove3.png | Bin 0 -> 12835 bytes Threaded Binary Tree/Images/Remove4.png | Bin 0 -> 11934 bytes Threaded Binary Tree/README.markdown | 53 ++++++++++++++++++ Threaded Binary Tree/ThreadedBinaryTree.swift | 50 ++++++++++------- 12 files changed, 84 insertions(+), 19 deletions(-) delete mode 100644 Threaded Binary Tree/Images/DelOne.png delete mode 100644 Threaded Binary Tree/Images/DelThree.png delete mode 100644 Threaded Binary Tree/Images/DelTwo.png rename Threaded Binary Tree/Images/{AddOne.png => Insert1.png} (100%) rename Threaded Binary Tree/Images/{AddTwo.png => Insert2.png} (100%) create mode 100644 Threaded Binary Tree/Images/Insert3.png create mode 100644 Threaded Binary Tree/Images/Remove1.png create mode 100644 Threaded Binary Tree/Images/Remove2.png create mode 100644 Threaded Binary Tree/Images/Remove3.png create mode 100644 Threaded Binary Tree/Images/Remove4.png diff --git a/Threaded Binary Tree/Images/DelOne.png b/Threaded Binary Tree/Images/DelOne.png deleted file mode 100644 index ded6abbe8cbad71af128c58c8e9eefd3189acece..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17173 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

QVGgl=`SNZXXbyhju{p! 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 diff --git a/Threaded Binary Tree/Images/DelThree.png b/Threaded Binary Tree/Images/DelThree.png deleted file mode 100644 index a1acdc85defe49d0fc70ead50c4725f6d277d6a2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11596 zcmZvCcT`hP)NMdeL`qaZq$8*Zks?)k??n)hAW;zMO{(-xq(~8@Na#qAE<}1a^aufw z8W0eW5~>kU>KlLGTkrkzWl>h{y~)fycjlaZ_TDiM^fhRyS*Rfp2(6Z;su2W2_6Gba zQjvorzqrR^!M}5!%38)$R8)iogL&{4>ZNAp_0Y}M>!p>44dkJ{x0jcVhjsYyMF@lo zqNS>2>^r@g9rBvZ?%m2<-EHDUYYQ7ywiW#cW752AS5_T|Z(;ZfO1C*tJRh7GFd`dK zm1#^vQ#@~K)(4g>D2eBh zc-NcWeq^auR+k~$;i<1yvm8evVbo;I1TmNRfWh__qCMwyoFu<}5cFNQo^TTaNrFl& zFhL-Ba4`Qta)=`4#U%)27zTla+LD2z4U`awJvgt3`FC^%+`AY!|LEBuX>h$u!bRR;99nn?fVM=l*Ropc2tbx%JfeGlSY?wdw;qFabrg z3^crILT{8eGP-~dR|CVHOCUo`h|^$&U+WjEP`%+T8L?Mv>_{Da&-mdsnn8qziDT5CtEY9zTlZDxah4HGJm?%?Wg=@|4b{JHSInrRE%El(_>J&=; z9g|RtU`0t$(M73*Qt&$eMCl-?eacw^HRvoMqo9yjq8{qc#9TW5gpZ+Vw$dRppDD+g zkj8r_rT-Jb#kiqEy5k|WU`!?PZ(z=%)Py&7{IU|%Vq#fJFc(j3NdoJwbh0xWw8a?nt7ZNA2-8WNbe8aJWXncV zKr$%>dCbJHEMv^^9Q780SCzRQTQYv=jJWgykv{%$+#>4g^|o!DLPGg!o4hQZ6=_ANLp%72fgwz- zGkTMW@;6X^&b5B`HRKoUg?#@# zJ<-=i_fAzXO!UF9?zLLFivexdPin-EnvuhvfQxg~fgRM}zzVP+QX zQi8I9>y7^W`SZt}5-@TBddfN3w^`B#zLkAD)HdwX=$cn-_p>Z~lFih!YRzU8xjmDn zxYy#v=>fSR&E#)HK@d-_R%YY~Yhd?vf8=jxaL4bjjf!2ZzRZm$vGsOZQ0KuNdc9}o zDR7dg0WpPl{m<{oyxcUTC)k}!yQ|AiZf`mbx3Hl3kg<$9icPzgU60WDvZ=9w4KP!tn&Qzp_SzphIXtyKI>+jJ15e(E zfn0pvIs~8ay7gVJ&Sno|+^vVJEcZCMgbxoJ&g3oQ8Xs3gVZ?`!-FT&;P z*oJqKa&9wmC}SY!kz~S+PG_fVfA=0O1-<%m6^Fy!PT-g+hP7z*!Oxs6@YlhHV9|(@ z8&)+Nz~W^uz0Z9A+gD2)&lW0sDKdeJ3Wn=x z8N7t(i+>^p@nhnOE%1`gmO8=(&24*0Yu12llx1M`Lss_v3e(y7VTiQ~G~4;^-MjY_ zuHr{=witUO>Lj}`l6~gSCRf>dsrM_$_|N}VGFfZ^3Z`guGlRolkLM?zk2&zVp;K}^-A+sV=LHxM!J`sf`Na zNd@<%Hx1?-Ye6Pkl=>u4Qd&Ba1<|A!hV9&j;R>v)!PY-hL0Xxm)xrce3NbL8@R!na zV~*mbD63phC&GA@^iYi!ThAO;mt`{1QE#?=b0%b(7Nwj9uDh7eIZN!m|M%3T5>zyv zr)n=7B`^6sDKg@Y{0J*^F#l+-RY5~!%g#|OF}@M0nfwV|32sJ{a?my

KL~pKDz` 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 E0$YzwjsO4v literal 0 HcmV?d00001 diff --git a/Threaded Binary Tree/Images/Remove1.png b/Threaded Binary Tree/Images/Remove1.png new file mode 100644 index 0000000000000000000000000000000000000000..0ca2f9c5073387b2a18f067136bd68c9c0ba8607 GIT binary patch literal 17019 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

t*(a?;_B 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 Q!FdopZDXx!&AXBR3$a9|sQ>@~ literal 0 HcmV?d00001 diff --git a/Threaded Binary Tree/Images/Remove2.png b/Threaded Binary Tree/Images/Remove2.png new file mode 100644 index 0000000000000000000000000000000000000000..31c4965948393169c4fbe023faebce6a5ad2de95 GIT binary patch literal 14090 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 literal 0 HcmV?d00001 diff --git a/Threaded Binary Tree/Images/Remove3.png b/Threaded Binary Tree/Images/Remove3.png new file mode 100644 index 0000000000000000000000000000000000000000..c20c6f1f74e7fc11922c53fd104d14e654ea88b2 GIT binary patch literal 12835 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 Z@!kKB-@0VS41+ZgB?UG4QrXv`{|f~qigW+~ literal 0 HcmV?d00001 diff --git a/Threaded Binary Tree/README.markdown b/Threaded Binary Tree/README.markdown index ba654ea07..91d7a9ecb 100644 --- a/Threaded Binary Tree/README.markdown +++ b/Threaded Binary Tree/README.markdown @@ -73,6 +73,26 @@ need to keep track of both. For example, in a double threaded tree, if a node has a right child but no left child, it will track its predecessor in place of its left child. +Here is a valid "full" threaded binary tree: + +![Full](/Images/Full.png) + +While the following threaded binary tree is not "full," it is still valid. The +structure of the tree does not matter as long as it follows the definition of a +binary search tree: + +![Partial](/Images/Partial.png) + +The solid lines denote the links between parents and children, while the dotted +lines denote the "threads." The important thing to note here is how the +children and thread edges interact with each other. Every node besides the +root has one entering edge (from its parent), and two leaving edges: one to the +left and one to the right. The left leaving edge goes to the node's left child +if it exists, and to its in-order predecessor if it does not. The right +leaving edge goes to the node's right child if it exists, and to its in-order +successor if it does not. The exceptions are the left-most node and the +right-most node, which do not have a predecessor or successor, respectively. + ## Representation @@ -175,6 +195,39 @@ to explain this with an example. Please note that this requires knowledge of binary search trees, so make sure you have [read this first](../Binary Search Tree/). +Base: + +![Base](/Images/Base.png) + +Insert1: + +![Insert1](/Images/Insert1.png) + +Insert2: + +![Insert2](/Images/Insert2.png) + +Insert3: + +![Insert3](/Images/Insert3.png) + +Remove1: + +![Remove1](/Images/Remove1.png) + +Remove2: + +![Remove2](/Images/Remove2.png) + +Remove3: + +![Remove3](/Images/Remove3.png) + +Remove4: + +![Remove4](/Images/Remove4.png) + + ### Still under construction. diff --git a/Threaded Binary Tree/ThreadedBinaryTree.swift b/Threaded Binary Tree/ThreadedBinaryTree.swift index b1ae8d0bf..c4fd2f4de 100644 --- a/Threaded Binary Tree/ThreadedBinaryTree.swift +++ b/Threaded Binary Tree/ThreadedBinaryTree.swift @@ -485,20 +485,24 @@ extension ThreadedBinaryTree: CustomDebugStringConvertible { */ // Simple little debug function to make testing output pretty -private func check(tree: ThreadedBinaryTree) { - print("\(tree.count) Total Nodes:"); - print(tree) - print("Debug Info:") - print(tree.debugDescription) - print("In-Order Traversal:") - let myArray = tree.toArray() - for node in myArray { - print(node) - } - if tree.isThreaded() { - print("This threaded binary tree is VALID.") +private func check(tree: ThreadedBinaryTree?) { + if let tree = tree { + print("\(tree.count) Total Nodes:"); + print(tree) + print("Debug Info:") + print(tree.debugDescription) + print("In-Order Traversal:") + let myArray = tree.toArray() + for node in myArray { + print(node) + } + if tree.isThreaded() { + print("This threaded binary tree is VALID.") + } else { + print("This threaded binary tree is INVALID.") + } } else { - print("This threaded binary tree is INVALID.") + print("This tree is nil.") } } @@ -530,20 +534,28 @@ print("\nInsert 4") tree.insert(4) check(tree) -print("\nRemove 13 (Not in the Tree)") -tree.remove(13) +print("\nInsert 15") +tree.insert(15) check(tree) -print("\nRemove 5") -tree.remove(5) +print("\nRemove 13 (Not in the Tree)") +tree.remove(13) check(tree) print("\nRemove 7") tree.remove(7) check(tree) -print("\nRemove 10") -tree.remove(10) +print("\nRemove 5") +tree.remove(5) check(tree) +print("\nRemove 9 (root)") +let newRoot = tree.remove(9) +check(newRoot) + +print("\nRemove 12") +newRoot?.remove(12) +check(newRoot) + print("\n\nDone with Tests!\n") From 74f9ad5ff5bd8c177ecacde6b8101be8478ed7db Mon Sep 17 00:00:00 2001 From: Jayson Tung Date: Tue, 3 May 2016 12:33:14 -0400 Subject: [PATCH 0312/1679] Fix broken README links --- Threaded Binary Tree/README.markdown | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Threaded Binary Tree/README.markdown b/Threaded Binary Tree/README.markdown index 91d7a9ecb..155404b66 100644 --- a/Threaded Binary Tree/README.markdown +++ b/Threaded Binary Tree/README.markdown @@ -75,13 +75,13 @@ its left child. Here is a valid "full" threaded binary tree: -![Full](/Images/Full.png) +![Full](Images/Full.png) While the following threaded binary tree is not "full," it is still valid. The structure of the tree does not matter as long as it follows the definition of a binary search tree: -![Partial](/Images/Partial.png) +![Partial](Images/Partial.png) The solid lines denote the links between parents and children, while the dotted lines denote the "threads." The important thing to note here is how the @@ -197,35 +197,35 @@ binary search trees, so make sure you have Base: -![Base](/Images/Base.png) +![Base](Images/Base.png) Insert1: -![Insert1](/Images/Insert1.png) +![Insert1](Images/Insert1.png) Insert2: -![Insert2](/Images/Insert2.png) +![Insert2](Images/Insert2.png) Insert3: -![Insert3](/Images/Insert3.png) +![Insert3](Images/Insert3.png) Remove1: -![Remove1](/Images/Remove1.png) +![Remove1](Images/Remove1.png) Remove2: -![Remove2](/Images/Remove2.png) +![Remove2](Images/Remove2.png) Remove3: -![Remove3](/Images/Remove3.png) +![Remove3](Images/Remove3.png) Remove4: -![Remove4](/Images/Remove4.png) +![Remove4](Images/Remove4.png) From ab7bafa62dec6878bdc23233f71acec7df29f966 Mon Sep 17 00:00:00 2001 From: Thukor Date: Tue, 3 May 2016 14:06:35 -0400 Subject: [PATCH 0313/1679] Scrapped current findPrefix() implementation --- Trie/trie | Bin 65115 -> 60968 bytes Trie/trie.swift | 30 ------------------------------ 2 files changed, 30 deletions(-) diff --git a/Trie/trie b/Trie/trie index f4fc8cdf7379094f875f742142542a09096220b0..08a387f2717bd69ad4f97d3c0f1a326f983d1bf4 100755 GIT binary patch delta 21081 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 delta 22384 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 diff --git a/Trie/trie.swift b/Trie/trie.swift index 4758e10fd..341f4c708 100644 --- a/Trie/trie.swift +++ b/Trie/trie.swift @@ -210,7 +210,6 @@ public class Trie { } else { var character = currentNode.char() while(currentNode.numChildren() == 0 && !currentNode.isRoot()) { - print(currentNode.getParent().char()) currentNode = currentNode.getParent() currentNode.children[character]!.setParent(nil) currentNode.children[character]!.update(nil) @@ -232,37 +231,8 @@ public class Trie { return (w, true) } - private func getChildrenWithPrefix(node: Node, var word: String, var words: [String]) -> [String] { - - print(word) - - if node.isLeaf() && node.isValidWord() { - words.append(word) - print(words) - - } else { - - for (child, n) in node.getChildren(){ - print(child) - word += child - getChildrenWithPrefix(n, word: word, words: words) - } - } - - return words - } - func findPrefix(p: String) -> [String] { - print("Entered") - - - //var (node, pFound: Bool) = self.isPrefix(p) - if self.isPrefix(p).found { - print("I found the prefix!") - return getChildrenWithPrefix(self.isPrefix(p).node!, word: p.lowercaseString, words: []) - } - return ["HE"] } From 461127f55a13eae90b68f602cab7f2cd0da2010e Mon Sep 17 00:00:00 2001 From: Thukor Date: Tue, 3 May 2016 14:51:14 -0400 Subject: [PATCH 0314/1679] Revamped directory structure to allow for importing of modules from implemented data structures --- Trie/.build/debug/Trie | Bin 0 -> 95508 bytes Trie/.build/debug/Trie.a | Bin 0 -> 125236 bytes Trie/.build/debug/Trie.o/Trie/Queue.d | 3 + Trie/.build/debug/Trie.o/Trie/Queue.swiftdeps | 316 +++++++++++ .../debug/Trie.o/Trie/Queue~partial.swiftdoc | Bin 0 -> 540 bytes .../Trie.o/Trie/Queue~partial.swiftmodule | Bin 0 -> 11788 bytes Trie/.build/debug/Trie.o/Trie/main.d | 3 + Trie/.build/debug/Trie.o/Trie/main.swiftdeps | 202 +++++++ .../debug/Trie.o/Trie/main~partial.swiftdoc | Bin 0 -> 540 bytes .../Trie.o/Trie/main~partial.swiftmodule | Bin 0 -> 31660 bytes .../.build/debug/Trie.o/Trie/master.swiftdeps | 7 + .../debug/Trie.o/Trie/output-file-map.json | 23 + Trie/.build/debug/Trie.o/Trie/trie.d | 3 + Trie/.build/debug/Trie.o/Trie/trie.swiftdeps | 504 +++++++++++++++++ .../debug/Trie.o/Trie/trie~partial.swiftdoc | Bin 0 -> 540 bytes .../Trie.o/Trie/trie~partial.swiftmodule | Bin 0 -> 53928 bytes Trie/.build/debug/Trie.o/build.db | Bin 0 -> 15360 bytes Trie/.build/debug/Trie.o/llbuild.yaml | 29 + .../.build/debug/Trie.o/sources/Queue.swift.o | Bin 0 -> 23440 bytes Trie/.build/debug/Trie.o/sources/main.swift.o | Bin 0 -> 13864 bytes Trie/.build/debug/Trie.o/sources/trie.swift.o | Bin 0 -> 94800 bytes Trie/.build/debug/Trie.swiftdoc | Bin 0 -> 540 bytes Trie/.build/debug/Trie.swiftmodule | Bin 0 -> 20724 bytes .../build.db | Bin 0 -> 7168 bytes .../llbuild.yaml | 29 + .../Queue.d | 3 + .../Queue.swiftdeps | 316 +++++++++++ .../master.swiftdeps | 6 + .../output-file-map.json | 17 + .../trie.d | 3 + .../trie.swiftdeps | 513 ++++++++++++++++++ Trie/Package.swift | 6 + Trie/Package.swift~ | 5 + Trie/sources/Queue.swift | 47 ++ Trie/sources/main.swift | 34 ++ Trie/{ => sources}/trie.swift | 44 +- 36 files changed, 2072 insertions(+), 41 deletions(-) create mode 100755 Trie/.build/debug/Trie create mode 100644 Trie/.build/debug/Trie.a create mode 100644 Trie/.build/debug/Trie.o/Trie/Queue.d create mode 100644 Trie/.build/debug/Trie.o/Trie/Queue.swiftdeps create mode 100644 Trie/.build/debug/Trie.o/Trie/Queue~partial.swiftdoc create mode 100644 Trie/.build/debug/Trie.o/Trie/Queue~partial.swiftmodule create mode 100644 Trie/.build/debug/Trie.o/Trie/main.d create mode 100644 Trie/.build/debug/Trie.o/Trie/main.swiftdeps create mode 100644 Trie/.build/debug/Trie.o/Trie/main~partial.swiftdoc create mode 100644 Trie/.build/debug/Trie.o/Trie/main~partial.swiftmodule create mode 100644 Trie/.build/debug/Trie.o/Trie/master.swiftdeps create mode 100644 Trie/.build/debug/Trie.o/Trie/output-file-map.json create mode 100644 Trie/.build/debug/Trie.o/Trie/trie.d create mode 100644 Trie/.build/debug/Trie.o/Trie/trie.swiftdeps create mode 100644 Trie/.build/debug/Trie.o/Trie/trie~partial.swiftdoc create mode 100644 Trie/.build/debug/Trie.o/Trie/trie~partial.swiftmodule create mode 100644 Trie/.build/debug/Trie.o/build.db create mode 100644 Trie/.build/debug/Trie.o/llbuild.yaml create mode 100644 Trie/.build/debug/Trie.o/sources/Queue.swift.o create mode 100644 Trie/.build/debug/Trie.o/sources/main.swift.o create mode 100644 Trie/.build/debug/Trie.o/sources/trie.swift.o create mode 100644 Trie/.build/debug/Trie.swiftdoc create mode 100644 Trie/.build/debug/Trie.swiftmodule create mode 100644 Trie/.build/debug/package_name_here_and_keep_quote_marks.o/build.db create mode 100644 Trie/.build/debug/package_name_here_and_keep_quote_marks.o/llbuild.yaml create mode 100644 Trie/.build/debug/package_name_here_and_keep_quote_marks.o/package_name_here_and_keep_quote_marks/Queue.d create mode 100644 Trie/.build/debug/package_name_here_and_keep_quote_marks.o/package_name_here_and_keep_quote_marks/Queue.swiftdeps create mode 100644 Trie/.build/debug/package_name_here_and_keep_quote_marks.o/package_name_here_and_keep_quote_marks/master.swiftdeps create mode 100644 Trie/.build/debug/package_name_here_and_keep_quote_marks.o/package_name_here_and_keep_quote_marks/output-file-map.json create mode 100644 Trie/.build/debug/package_name_here_and_keep_quote_marks.o/package_name_here_and_keep_quote_marks/trie.d create mode 100644 Trie/.build/debug/package_name_here_and_keep_quote_marks.o/package_name_here_and_keep_quote_marks/trie.swiftdeps create mode 100644 Trie/Package.swift create mode 100644 Trie/Package.swift~ create mode 100644 Trie/sources/Queue.swift create mode 100644 Trie/sources/main.swift rename Trie/{ => sources}/trie.swift (85%) diff --git a/Trie/.build/debug/Trie b/Trie/.build/debug/Trie new file mode 100755 index 0000000000000000000000000000000000000000..3635f7c44a43c8b6f0aeab91e0d200109e211888 GIT binary patch literal 95508 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 z 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" +- !private "Double" +- !private "&&" +- !private "+=" +depends-member: +- !private ["Ps16AbsoluteValuable", "init"] +- ["Sa", "Generator"] +- ["Sa", "Index"] +- ["Sa", "SubSequence"] +- ["Sa", "_Element"] +- !private ["Sa", "append"] +- !private ["Sa", "count"] +- !private ["Sa", "deinit"] +- ["Sa", "init"] +- !private ["Sa", "removeFirst"] +- !private ["Sa", "subscript"] +- ["Ps23ArrayLiteralConvertible", "Generator"] +- ["Ps23ArrayLiteralConvertible", "Index"] +- ["Ps23ArrayLiteralConvertible", "SubSequence"] +- ["Ps23ArrayLiteralConvertible", "_Element"] +- !private ["Ps23ArrayLiteralConvertible", "append"] +- !private ["Ps23ArrayLiteralConvertible", "count"] +- ["Ps23ArrayLiteralConvertible", "init"] +- !private ["Ps23ArrayLiteralConvertible", "removeFirst"] +- !private ["Ps23ArrayLiteralConvertible", "subscript"] +- ["Vs10ArraySlice", "Generator"] +- ["Vs10ArraySlice", "Index"] +- ["Ps22BidirectionalIndexType", "Distance"] +- ["Ps22BidirectionalIndexType", "IntegerLiteralType"] +- ["Ps21BitwiseOperationsType", "Distance"] +- ["Ps21BitwiseOperationsType", "IntegerLiteralType"] +- !private ["Sb", "_getBuiltinLogicValue"] +- !private ["Ps25BooleanLiteralConvertible", "_getBuiltinLogicValue"] +- !private ["Ps11BooleanType", "_getBuiltinLogicValue"] +- ["Ps11CVarArgType", "Distance"] +- ["Ps11CVarArgType", "IntegerLiteralType"] +- !private ["Ps11CVarArgType", "init"] +- ["Ps14CollectionType", "Generator"] +- ["Ps14CollectionType", "Index"] +- ["Ps14CollectionType", "SubSequence"] +- ["Ps14CollectionType", "_Element"] +- !private ["Ps14CollectionType", "append"] +- !private ["Ps14CollectionType", "count"] +- ["Ps14CollectionType", "init"] +- !private ["Ps14CollectionType", "removeFirst"] +- !private ["Ps14CollectionType", "subscript"] +- ["Ps10Comparable", "Distance"] +- ["Ps10Comparable", "IntegerLiteralType"] +- !private ["Ps10Comparable", "init"] +- ["Ps28CustomDebugStringConvertible", "Generator"] +- ["Ps28CustomDebugStringConvertible", "Index"] +- ["Ps28CustomDebugStringConvertible", "Some"] +- ["Ps28CustomDebugStringConvertible", "SubSequence"] +- ["Ps28CustomDebugStringConvertible", "_Element"] +- !private ["Ps28CustomDebugStringConvertible", "append"] +- !private ["Ps28CustomDebugStringConvertible", "count"] +- ["Ps28CustomDebugStringConvertible", "init"] +- !private ["Ps28CustomDebugStringConvertible", "removeFirst"] +- !private ["Ps28CustomDebugStringConvertible", "subscript"] +- ["Ps23CustomStringConvertible", "Distance"] +- ["Ps23CustomStringConvertible", "Generator"] +- ["Ps23CustomStringConvertible", "Index"] +- ["Ps23CustomStringConvertible", "IntegerLiteralType"] +- ["Ps23CustomStringConvertible", "SubSequence"] +- ["Ps23CustomStringConvertible", "_Element"] +- !private ["Ps23CustomStringConvertible", "_getBuiltinLogicValue"] +- !private ["Ps23CustomStringConvertible", "append"] +- !private ["Ps23CustomStringConvertible", "count"] +- ["Ps23CustomStringConvertible", "init"] +- !private ["Ps23CustomStringConvertible", "removeFirst"] +- !private ["Ps23CustomStringConvertible", "subscript"] +- !private ["Sd", "init"] +- ["Ps9Equatable", "Distance"] +- ["Ps9Equatable", "IntegerLiteralType"] +- !private ["Ps9Equatable", "_getBuiltinLogicValue"] +- !private ["Ps9Equatable", "init"] +- !private ["Ps23FloatLiteralConvertible", "init"] +- !private ["Ps17FloatingPointType", "init"] +- ["Ps16ForwardIndexType", "Distance"] +- ["Ps16ForwardIndexType", "IntegerLiteralType"] +- ["Ps13GeneratorType", "Element"] +- ["Ps8Hashable", "Distance"] +- ["Ps8Hashable", "IntegerLiteralType"] +- !private ["Ps8Hashable", "_getBuiltinLogicValue"] +- !private ["Ps8Hashable", "init"] +- ["Ps9Indexable", "Generator"] +- ["Ps9Indexable", "Index"] +- ["Ps9Indexable", "SubSequence"] +- ["Ps9Indexable", "_Element"] +- !private ["Ps9Indexable", "append"] +- !private ["Ps9Indexable", "count"] +- ["Ps9Indexable", "init"] +- !private ["Ps9Indexable", "removeFirst"] +- !private ["Ps9Indexable", "subscript"] +- ["Vs17IndexingGenerator", "Element"] +- ["Si", "Distance"] +- ["Si", "IntegerLiteralType"] +- ["Ps21IntegerArithmeticType", "Distance"] +- ["Ps21IntegerArithmeticType", "IntegerLiteralType"] +- ["Ps25IntegerLiteralConvertible", "Distance"] +- ["Ps25IntegerLiteralConvertible", "IntegerLiteralType"] +- !private ["Ps25IntegerLiteralConvertible", "init"] +- ["Ps11IntegerType", "Distance"] +- ["Ps11IntegerType", "IntegerLiteralType"] +- ["Ps14MirrorPathType", "Distance"] +- ["Ps14MirrorPathType", "IntegerLiteralType"] +- ["Ps21MutableCollectionType", "Generator"] +- ["Ps21MutableCollectionType", "Index"] +- ["Ps21MutableCollectionType", "SubSequence"] +- ["Ps21MutableCollectionType", "_Element"] +- !private ["Ps21MutableCollectionType", "append"] +- !private ["Ps21MutableCollectionType", "count"] +- ["Ps21MutableCollectionType", "init"] +- !private ["Ps21MutableCollectionType", "removeFirst"] +- !private ["Ps21MutableCollectionType", "subscript"] +- ["Ps16MutableIndexable", "Generator"] +- ["Ps16MutableIndexable", "Index"] +- ["Ps16MutableIndexable", "SubSequence"] +- ["Ps16MutableIndexable", "_Element"] +- !private ["Ps16MutableIndexable", "append"] +- !private ["Ps16MutableIndexable", "count"] +- ["Ps16MutableIndexable", "init"] +- !private ["Ps16MutableIndexable", "removeFirst"] +- !private ["Ps16MutableIndexable", "subscript"] +- ["Ps16MutableSliceable", "Generator"] +- ["Ps16MutableSliceable", "Index"] +- ["Ps16MutableSliceable", "SubSequence"] +- ["Ps16MutableSliceable", "_Element"] +- !private ["Ps16MutableSliceable", "append"] +- !private ["Ps16MutableSliceable", "count"] +- ["Ps16MutableSliceable", "init"] +- !private ["Ps16MutableSliceable", "removeFirst"] +- !private ["Ps16MutableSliceable", "subscript"] +- ["Ps21NilLiteralConvertible", "Some"] +- ["Sq", "Some"] +- ["V4Trie5Queue", "Bool"] +- !private ["V4Trie5Queue", "Double"] +- ["V4Trie5Queue", "Int"] +- ["V4Trie5Queue", "T"] +- !private ["V4Trie5Queue", "array"] +- ["V4Trie5Queue", "count"] +- ["V4Trie5Queue", "dequeue"] +- ["V4Trie5Queue", "enqueue"] +- !private ["V4Trie5Queue", "head"] +- ["V4Trie5Queue", "init"] +- ["V4Trie5Queue", "isEmpty"] +- ["V4Trie5Queue", "peek"] +- ["Ps21RandomAccessIndexType", "Distance"] +- ["Ps21RandomAccessIndexType", "IntegerLiteralType"] +- ["Ps30RangeReplaceableCollectionType", "Generator"] +- ["Ps30RangeReplaceableCollectionType", "Index"] +- ["Ps30RangeReplaceableCollectionType", "SubSequence"] +- ["Ps30RangeReplaceableCollectionType", "_Element"] +- !private ["Ps30RangeReplaceableCollectionType", "append"] +- !private ["Ps30RangeReplaceableCollectionType", "count"] +- ["Ps30RangeReplaceableCollectionType", "init"] +- !private ["Ps30RangeReplaceableCollectionType", "removeFirst"] +- !private ["Ps30RangeReplaceableCollectionType", "subscript"] +- ["Ps12SequenceType", "Element"] +- ["Ps12SequenceType", "Generator"] +- ["Ps12SequenceType", "Index"] +- ["Ps12SequenceType", "SubSequence"] +- ["Ps12SequenceType", "_Element"] +- !private ["Ps12SequenceType", "append"] +- !private ["Ps12SequenceType", "count"] +- ["Ps12SequenceType", "init"] +- !private ["Ps12SequenceType", "removeFirst"] +- !private ["Ps12SequenceType", "subscript"] +- ["Ps17SignedIntegerType", "Distance"] +- ["Ps17SignedIntegerType", "IntegerLiteralType"] +- ["Ps16SignedNumberType", "Distance"] +- ["Ps16SignedNumberType", "IntegerLiteralType"] +- !private ["Ps16SignedNumberType", "init"] +- !private ["Vs5Slice", "Generator"] +- !private ["Vs5Slice", "Index"] +- !private ["Vs5Slice", "SubSequence"] +- !private ["Vs5Slice", "_Element"] +- ["Ps10Strideable", "Distance"] +- ["Ps10Strideable", "IntegerLiteralType"] +- !private ["Ps10Strideable", "init"] +- ["Ps10_ArrayType", "Generator"] +- ["Ps10_ArrayType", "Index"] +- ["Ps10_ArrayType", "SubSequence"] +- ["Ps10_ArrayType", "_Element"] +- !private ["Ps10_ArrayType", "append"] +- !private ["Ps10_ArrayType", "count"] +- ["Ps10_ArrayType", "init"] +- !private ["Ps10_ArrayType", "removeFirst"] +- !private ["Ps10_ArrayType", "subscript"] +- !private ["Ps33_BuiltinBooleanLiteralConvertible", "_getBuiltinLogicValue"] +- !private ["Ps31_BuiltinFloatLiteralConvertible", "init"] +- ["Ps33_BuiltinIntegerLiteralConvertible", "Distance"] +- ["Ps33_BuiltinIntegerLiteralConvertible", "IntegerLiteralType"] +- !private ["Ps33_BuiltinIntegerLiteralConvertible", "init"] +- !private ["Ps19_CVarArgAlignedType", "init"] +- !private ["Ps22_CVarArgPassedAsDouble", "init"] +- ["Ps24_DestructorSafeContainer", "Generator"] +- ["Ps24_DestructorSafeContainer", "Index"] +- ["Ps24_DestructorSafeContainer", "SubSequence"] +- ["Ps24_DestructorSafeContainer", "_Element"] +- !private ["Ps24_DestructorSafeContainer", "append"] +- !private ["Ps24_DestructorSafeContainer", "count"] +- ["Ps24_DestructorSafeContainer", "init"] +- !private ["Ps24_DestructorSafeContainer", "removeFirst"] +- !private ["Ps24_DestructorSafeContainer", "subscript"] +- ["Ps14_Incrementable", "Distance"] +- ["Ps14_Incrementable", "IntegerLiteralType"] +- ["Ps22_IntegerArithmeticType", "Distance"] +- ["Ps22_IntegerArithmeticType", "IntegerLiteralType"] +- ["Ps12_IntegerType", "Distance"] +- ["Ps12_IntegerType", "IntegerLiteralType"] +- ["Ps22_RandomAccessAmbiguity", "Distance"] +- ["Ps22_RandomAccessAmbiguity", "IntegerLiteralType"] +- ["Ps12_Reflectable", "Distance"] +- ["Ps12_Reflectable", "Generator"] +- ["Ps12_Reflectable", "Index"] +- ["Ps12_Reflectable", "IntegerLiteralType"] +- ["Ps12_Reflectable", "Some"] +- ["Ps12_Reflectable", "SubSequence"] +- ["Ps12_Reflectable", "_Element"] +- !private ["Ps12_Reflectable", "_getBuiltinLogicValue"] +- !private ["Ps12_Reflectable", "append"] +- !private ["Ps12_Reflectable", "count"] +- ["Ps12_Reflectable", "init"] +- !private ["Ps12_Reflectable", "removeFirst"] +- !private ["Ps12_Reflectable", "subscript"] +- ["Ps18_SignedIntegerType", "Distance"] +- ["Ps18_SignedIntegerType", "IntegerLiteralType"] +depends-nominal: +- !private "Ps16AbsoluteValuable" +- "Sa" +- "Ps23ArrayLiteralConvertible" +- "Vs10ArraySlice" +- "Ps22BidirectionalIndexType" +- "Ps21BitwiseOperationsType" +- !private "Sb" +- !private "Ps25BooleanLiteralConvertible" +- !private "Ps11BooleanType" +- "Ps11CVarArgType" +- "Ps14CollectionType" +- "Ps10Comparable" +- "Ps28CustomDebugStringConvertible" +- "Ps23CustomStringConvertible" +- !private "Sd" +- "Ps9Equatable" +- !private "Ps23FloatLiteralConvertible" +- !private "Ps17FloatingPointType" +- "Ps16ForwardIndexType" +- "Ps13GeneratorType" +- "Ps8Hashable" +- "Ps9Indexable" +- "Vs17IndexingGenerator" +- "Si" +- "Ps21IntegerArithmeticType" +- "Ps25IntegerLiteralConvertible" +- "Ps11IntegerType" +- "Ps14MirrorPathType" +- "Ps21MutableCollectionType" +- "Ps16MutableIndexable" +- "Ps16MutableSliceable" +- "Ps21NilLiteralConvertible" +- "Sq" +- "V4Trie5Queue" +- "Ps21RandomAccessIndexType" +- "Ps30RangeReplaceableCollectionType" +- "Ps12SequenceType" +- "Ps17SignedIntegerType" +- "Ps16SignedNumberType" +- !private "Vs5Slice" +- "Ps10Strideable" +- "Ps10_ArrayType" +- !private "Ps33_BuiltinBooleanLiteralConvertible" +- !private "Ps31_BuiltinFloatLiteralConvertible" +- "Ps33_BuiltinIntegerLiteralConvertible" +- !private "Ps19_CVarArgAlignedType" +- !private "Ps22_CVarArgPassedAsDouble" +- "Ps24_DestructorSafeContainer" +- "Ps14_Incrementable" +- "Ps22_IntegerArithmeticType" +- "Ps12_IntegerType" +- "Ps22_RandomAccessAmbiguity" +- "Ps12_Reflectable" +- "Ps18_SignedIntegerType" +depends-dynamic-lookup: +depends-external: +- "/home/christian/swiftv2/usr/lib/swift/linux/x86_64/Swift.swiftmodule" +- "/home/christian/swiftv2/usr/lib/swift/shims/UnicodeShims.h" +- "/home/christian/swiftv2/usr/lib/swift/shims/SwiftStdint.h" +- "/home/christian/swiftv2/usr/lib/swift/shims/SwiftStddef.h" +- "/home/christian/swiftv2/usr/lib/swift/shims/LibcShims.h" +- "/home/christian/swiftv2/usr/lib/swift/shims/RuntimeStubs.h" +- "/home/christian/swiftv2/usr/lib/swift/shims/RuntimeShims.h" +- "/home/christian/swiftv2/usr/lib/swift/shims/RefCount.h" +- "/home/christian/swiftv2/usr/lib/swift/shims/HeapObject.h" +- "/home/christian/swiftv2/usr/lib/swift/shims/GlobalObjects.h" +- "/home/christian/swiftv2/usr/lib/swift/shims/FoundationShims.h" +- "/home/christian/swiftv2/usr/lib/swift/shims/CoreFoundationShims.h" +- "/home/christian/swiftv2/usr/lib/swift/shims/module.map" +interface-hash: "b268b101cc2bc2706939fa25905dab4d" diff --git a/Trie/.build/debug/Trie.o/Trie/Queue~partial.swiftdoc b/Trie/.build/debug/Trie.o/Trie/Queue~partial.swiftdoc new file mode 100644 index 0000000000000000000000000000000000000000..12942dedfe6852aa61b902224cde186d2adaaf6c GIT binary patch literal 540 zcmaDfX9YVW2LppD0|Ns)qlJ#c+7Dby0=U-%aP4>CT5rI$Ux91Q2d>2%xY!*xUFbQa zy@N^j#3Ahshx9v`wD%m+SaZl(Xp58P1t*OOP8vYc#=uE?50mBxdSs$%*Q9pSHW1%LeHSMEDy*( z2E-K>X7Oewx}|y9dHLmex;dG7r4_pAd8I%phE||K?m*gzO@POXg+Yf2BnSi!U~-gz Gg#ZA|lTWSy literal 0 HcmV?d00001 diff --git a/Trie/.build/debug/Trie.o/Trie/Queue~partial.swiftmodule b/Trie/.build/debug/Trie.o/Trie/Queue~partial.swiftmodule new file mode 100644 index 0000000000000000000000000000000000000000..267c48a56b4a095c3a6463ff17bcb74be262f696 GIT binary patch literal 11788 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 V6K8$N%$y_>dSt!-|1K+m{{~>CuYLdk literal 0 HcmV?d00001 diff --git a/Trie/.build/debug/Trie.o/Trie/main.d b/Trie/.build/debug/Trie.o/Trie/main.d new file mode 100644 index 000000000..73abc24e4 --- /dev/null +++ b/Trie/.build/debug/Trie.o/Trie/main.d @@ -0,0 +1,3 @@ +/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/sources/main.swift.o : /home/christian/Desktop/swift-algorithm-club/Trie/sources/main.swift /home/christian/Desktop/swift-algorithm-club/Trie/sources/trie.swift /home/christian/Desktop/swift-algorithm-club/Trie/sources/Queue.swift /home/christian/swiftv2/usr/lib/swift/linux/x86_64/Swift.swiftmodule /home/christian/swiftv2/usr/lib/swift/shims/UnicodeShims.h /home/christian/swiftv2/usr/lib/swift/shims/SwiftStdint.h /home/christian/swiftv2/usr/lib/swift/shims/SwiftStddef.h /home/christian/swiftv2/usr/lib/swift/shims/LibcShims.h /home/christian/swiftv2/usr/lib/swift/shims/RuntimeStubs.h /home/christian/swiftv2/usr/lib/swift/shims/RuntimeShims.h /home/christian/swiftv2/usr/lib/swift/shims/RefCount.h /home/christian/swiftv2/usr/lib/swift/shims/HeapObject.h /home/christian/swiftv2/usr/lib/swift/shims/GlobalObjects.h /home/christian/swiftv2/usr/lib/swift/shims/FoundationShims.h /home/christian/swiftv2/usr/lib/swift/shims/CoreFoundationShims.h /home/christian/swiftv2/usr/lib/swift/shims/module.map +/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/Trie/main~partial.swiftmodule : /home/christian/Desktop/swift-algorithm-club/Trie/sources/main.swift /home/christian/Desktop/swift-algorithm-club/Trie/sources/trie.swift /home/christian/Desktop/swift-algorithm-club/Trie/sources/Queue.swift /home/christian/swiftv2/usr/lib/swift/linux/x86_64/Swift.swiftmodule /home/christian/swiftv2/usr/lib/swift/shims/UnicodeShims.h /home/christian/swiftv2/usr/lib/swift/shims/SwiftStdint.h /home/christian/swiftv2/usr/lib/swift/shims/SwiftStddef.h /home/christian/swiftv2/usr/lib/swift/shims/LibcShims.h /home/christian/swiftv2/usr/lib/swift/shims/RuntimeStubs.h /home/christian/swiftv2/usr/lib/swift/shims/RuntimeShims.h /home/christian/swiftv2/usr/lib/swift/shims/RefCount.h /home/christian/swiftv2/usr/lib/swift/shims/HeapObject.h /home/christian/swiftv2/usr/lib/swift/shims/GlobalObjects.h /home/christian/swiftv2/usr/lib/swift/shims/FoundationShims.h /home/christian/swiftv2/usr/lib/swift/shims/CoreFoundationShims.h /home/christian/swiftv2/usr/lib/swift/shims/module.map +/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/Trie/main~partial.swiftdoc : /home/christian/Desktop/swift-algorithm-club/Trie/sources/main.swift /home/christian/Desktop/swift-algorithm-club/Trie/sources/trie.swift /home/christian/Desktop/swift-algorithm-club/Trie/sources/Queue.swift /home/christian/swiftv2/usr/lib/swift/linux/x86_64/Swift.swiftmodule /home/christian/swiftv2/usr/lib/swift/shims/UnicodeShims.h /home/christian/swiftv2/usr/lib/swift/shims/SwiftStdint.h /home/christian/swiftv2/usr/lib/swift/shims/SwiftStddef.h /home/christian/swiftv2/usr/lib/swift/shims/LibcShims.h /home/christian/swiftv2/usr/lib/swift/shims/RuntimeStubs.h /home/christian/swiftv2/usr/lib/swift/shims/RuntimeShims.h /home/christian/swiftv2/usr/lib/swift/shims/RefCount.h /home/christian/swiftv2/usr/lib/swift/shims/HeapObject.h /home/christian/swiftv2/usr/lib/swift/shims/GlobalObjects.h /home/christian/swiftv2/usr/lib/swift/shims/FoundationShims.h /home/christian/swiftv2/usr/lib/swift/shims/CoreFoundationShims.h /home/christian/swiftv2/usr/lib/swift/shims/module.map diff --git a/Trie/.build/debug/Trie.o/Trie/main.swiftdeps b/Trie/.build/debug/Trie.o/Trie/main.swiftdeps new file mode 100644 index 000000000..923f0f821 --- /dev/null +++ b/Trie/.build/debug/Trie.o/Trie/main.swiftdeps @@ -0,0 +1,202 @@ +### Swift dependencies file v0 ### +provides-top-level: +- "T" +- "U" +- "V" +provides-nominal: +provides-member: +depends-top-level: +- "StringLiteralType" +- "Set" +- "Array" +- "print" +- "Trie" +- "V" +- "T" +- "U" +depends-member: +- ["Ps9AnyObject", "getWords"] +- ["Ps9AnyObject", "init"] +- ["Ps9AnyObject", "insert"] +- ["Ps9AnyObject", "merge"] +- ["Ps9AnyObject", "removeAll"] +- ["Sa", "Element"] +- ["Sa", "Generator"] +- ["Sa", "Index"] +- ["Sa", "_Element"] +- ["Ps23ArrayLiteralConvertible", "Element"] +- ["Ps23ArrayLiteralConvertible", "Generator"] +- ["Ps23ArrayLiteralConvertible", "Index"] +- ["Ps23ArrayLiteralConvertible", "_Element"] +- ["Ps23ArrayLiteralConvertible", "init"] +- ["Ps22BidirectionalIndexType", "Distance"] +- ["Ps22BidirectionalIndexType", "IntegerLiteralType"] +- ["Ps21BitwiseOperationsType", "Distance"] +- ["Ps21BitwiseOperationsType", "IntegerLiteralType"] +- ["Ps11CVarArgType", "Distance"] +- ["Ps11CVarArgType", "IntegerLiteralType"] +- ["Ps14CollectionType", "Element"] +- ["Ps14CollectionType", "Generator"] +- ["Ps14CollectionType", "Index"] +- ["Ps14CollectionType", "_Element"] +- ["Ps14CollectionType", "init"] +- ["Ps10Comparable", "Distance"] +- ["Ps10Comparable", "IntegerLiteralType"] +- ["Ps28CustomDebugStringConvertible", "Element"] +- ["Ps28CustomDebugStringConvertible", "Generator"] +- ["Ps28CustomDebugStringConvertible", "Index"] +- ["Ps28CustomDebugStringConvertible", "_Element"] +- ["Ps28CustomDebugStringConvertible", "init"] +- ["Ps23CustomStringConvertible", "Distance"] +- ["Ps23CustomStringConvertible", "Element"] +- ["Ps23CustomStringConvertible", "Generator"] +- ["Ps23CustomStringConvertible", "Index"] +- ["Ps23CustomStringConvertible", "IntegerLiteralType"] +- ["Ps23CustomStringConvertible", "_Element"] +- ["Ps23CustomStringConvertible", "init"] +- ["Ps9Equatable", "Distance"] +- ["Ps9Equatable", "IntegerLiteralType"] +- ["Ps9Equatable", "init"] +- ["Ps16ForwardIndexType", "Distance"] +- ["Ps16ForwardIndexType", "IntegerLiteralType"] +- ["Ps13GeneratorType", "Element"] +- ["Ps8Hashable", "Distance"] +- ["Ps8Hashable", "IntegerLiteralType"] +- ["Ps8Hashable", "init"] +- ["Ps9Indexable", "Element"] +- ["Ps9Indexable", "Generator"] +- ["Ps9Indexable", "Index"] +- ["Ps9Indexable", "_Element"] +- ["Ps9Indexable", "init"] +- ["Vs17IndexingGenerator", "Element"] +- ["Si", "Distance"] +- ["Si", "IntegerLiteralType"] +- ["Si", "deinit"] +- ["Ps21IntegerArithmeticType", "Distance"] +- ["Ps21IntegerArithmeticType", "IntegerLiteralType"] +- ["Ps25IntegerLiteralConvertible", "Distance"] +- ["Ps25IntegerLiteralConvertible", "IntegerLiteralType"] +- ["Ps11IntegerType", "Distance"] +- ["Ps11IntegerType", "IntegerLiteralType"] +- ["Ps14MirrorPathType", "Distance"] +- ["Ps14MirrorPathType", "IntegerLiteralType"] +- ["Ps21MutableCollectionType", "Element"] +- ["Ps21MutableCollectionType", "Generator"] +- ["Ps21MutableCollectionType", "Index"] +- ["Ps21MutableCollectionType", "_Element"] +- ["Ps16MutableIndexable", "Element"] +- ["Ps16MutableIndexable", "Generator"] +- ["Ps16MutableIndexable", "Index"] +- ["Ps16MutableIndexable", "_Element"] +- ["Ps16MutableSliceable", "Element"] +- ["Ps16MutableSliceable", "Generator"] +- ["Ps16MutableSliceable", "Index"] +- ["Ps16MutableSliceable", "_Element"] +- ["Ps21RandomAccessIndexType", "Distance"] +- ["Ps21RandomAccessIndexType", "IntegerLiteralType"] +- ["Ps30RangeReplaceableCollectionType", "Element"] +- ["Ps30RangeReplaceableCollectionType", "Generator"] +- ["Ps30RangeReplaceableCollectionType", "Index"] +- ["Ps30RangeReplaceableCollectionType", "_Element"] +- ["Ps12SequenceType", "Element"] +- ["Ps12SequenceType", "Generator"] +- ["Ps12SequenceType", "Index"] +- ["Ps12SequenceType", "_Element"] +- ["Ps12SequenceType", "init"] +- ["Vs3Set", "init"] +- ["Ps17SignedIntegerType", "Distance"] +- ["Ps17SignedIntegerType", "IntegerLiteralType"] +- ["Ps16SignedNumberType", "Distance"] +- ["Ps16SignedNumberType", "IntegerLiteralType"] +- ["Ps10Strideable", "Distance"] +- ["Ps10Strideable", "IntegerLiteralType"] +- ["C4Trie4Trie", "getWords"] +- ["C4Trie4Trie", "init"] +- ["C4Trie4Trie", "insert"] +- ["C4Trie4Trie", "merge"] +- ["C4Trie4Trie", "removeAll"] +- ["Ps10_ArrayType", "Element"] +- ["Ps10_ArrayType", "Generator"] +- ["Ps10_ArrayType", "Index"] +- ["Ps10_ArrayType", "_Element"] +- ["Ps33_BuiltinIntegerLiteralConvertible", "Distance"] +- ["Ps33_BuiltinIntegerLiteralConvertible", "IntegerLiteralType"] +- ["Ps24_DestructorSafeContainer", "Element"] +- ["Ps24_DestructorSafeContainer", "Generator"] +- ["Ps24_DestructorSafeContainer", "Index"] +- ["Ps24_DestructorSafeContainer", "_Element"] +- ["Ps14_Incrementable", "Distance"] +- ["Ps14_Incrementable", "IntegerLiteralType"] +- ["Ps22_IntegerArithmeticType", "Distance"] +- ["Ps22_IntegerArithmeticType", "IntegerLiteralType"] +- ["Ps12_IntegerType", "Distance"] +- ["Ps12_IntegerType", "IntegerLiteralType"] +- ["Ps22_RandomAccessAmbiguity", "Distance"] +- ["Ps22_RandomAccessAmbiguity", "IntegerLiteralType"] +- ["Ps12_Reflectable", "Distance"] +- ["Ps12_Reflectable", "Element"] +- ["Ps12_Reflectable", "Generator"] +- ["Ps12_Reflectable", "Index"] +- ["Ps12_Reflectable", "IntegerLiteralType"] +- ["Ps12_Reflectable", "_Element"] +- ["Ps12_Reflectable", "init"] +- ["Ps18_SignedIntegerType", "Distance"] +- ["Ps18_SignedIntegerType", "IntegerLiteralType"] +depends-nominal: +- "Ps9AnyObject" +- "Sa" +- "Ps23ArrayLiteralConvertible" +- "Ps22BidirectionalIndexType" +- "Ps21BitwiseOperationsType" +- "Ps11CVarArgType" +- "Ps14CollectionType" +- "Ps10Comparable" +- "Ps28CustomDebugStringConvertible" +- "Ps23CustomStringConvertible" +- "Ps9Equatable" +- "Ps16ForwardIndexType" +- "Ps13GeneratorType" +- "Ps8Hashable" +- "Ps9Indexable" +- "Vs17IndexingGenerator" +- "Si" +- "Ps21IntegerArithmeticType" +- "Ps25IntegerLiteralConvertible" +- "Ps11IntegerType" +- "Ps14MirrorPathType" +- "Ps21MutableCollectionType" +- "Ps16MutableIndexable" +- "Ps16MutableSliceable" +- "Ps21RandomAccessIndexType" +- "Ps30RangeReplaceableCollectionType" +- "Ps12SequenceType" +- "Vs3Set" +- "Ps17SignedIntegerType" +- "Ps16SignedNumberType" +- "Ps10Strideable" +- "C4Trie4Trie" +- "Ps10_ArrayType" +- "Ps33_BuiltinIntegerLiteralConvertible" +- "Ps24_DestructorSafeContainer" +- "Ps14_Incrementable" +- "Ps22_IntegerArithmeticType" +- "Ps12_IntegerType" +- "Ps22_RandomAccessAmbiguity" +- "Ps12_Reflectable" +- "Ps18_SignedIntegerType" +depends-dynamic-lookup: +depends-external: +- "/home/christian/swiftv2/usr/lib/swift/linux/x86_64/Swift.swiftmodule" +- "/home/christian/swiftv2/usr/lib/swift/shims/UnicodeShims.h" +- "/home/christian/swiftv2/usr/lib/swift/shims/SwiftStdint.h" +- "/home/christian/swiftv2/usr/lib/swift/shims/SwiftStddef.h" +- "/home/christian/swiftv2/usr/lib/swift/shims/LibcShims.h" +- "/home/christian/swiftv2/usr/lib/swift/shims/RuntimeStubs.h" +- "/home/christian/swiftv2/usr/lib/swift/shims/RuntimeShims.h" +- "/home/christian/swiftv2/usr/lib/swift/shims/RefCount.h" +- "/home/christian/swiftv2/usr/lib/swift/shims/HeapObject.h" +- "/home/christian/swiftv2/usr/lib/swift/shims/GlobalObjects.h" +- "/home/christian/swiftv2/usr/lib/swift/shims/FoundationShims.h" +- "/home/christian/swiftv2/usr/lib/swift/shims/CoreFoundationShims.h" +- "/home/christian/swiftv2/usr/lib/swift/shims/module.map" +interface-hash: "80fed5d587327a0a97180685d884fa09" diff --git a/Trie/.build/debug/Trie.o/Trie/main~partial.swiftdoc b/Trie/.build/debug/Trie.o/Trie/main~partial.swiftdoc new file mode 100644 index 0000000000000000000000000000000000000000..12942dedfe6852aa61b902224cde186d2adaaf6c GIT binary patch literal 540 zcmaDfX9YVW2LppD0|Ns)qlJ#c+7Dby0=U-%aP4>CT5rI$Ux91Q2d>2%xY!*xUFbQa zy@N^j#3Ahshx9v`wD%m+SaZl(Xp58P1t*OOP8vYc#=uE?50mBxdSs$%*Q9pSHW1%LeHSMEDy*( z2E-K>X7Oewx}|y9dHLmex;dG7r4_pAd8I%phE||K?m*gzO@POXg+Yf2BnSi!U~-gz Gg#ZA|lTWSy literal 0 HcmV?d00001 diff --git a/Trie/.build/debug/Trie.o/Trie/main~partial.swiftmodule b/Trie/.build/debug/Trie.o/Trie/main~partial.swiftmodule new file mode 100644 index 0000000000000000000000000000000000000000..876e0ca6ba870dcbe4f14e6dff6cf29aedab8598 GIT binary patch literal 31660 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 literal 0 HcmV?d00001 diff --git a/Trie/.build/debug/Trie.o/Trie/master.swiftdeps b/Trie/.build/debug/Trie.o/Trie/master.swiftdeps new file mode 100644 index 000000000..5539f705b --- /dev/null +++ b/Trie/.build/debug/Trie.o/Trie/master.swiftdeps @@ -0,0 +1,7 @@ +version: "Swift version 2.2-dev (LLVM 3ebdbb2c7e, Clang f66c5bb67b, Swift 0ddf238ad7)" +options: "1cfa30eacd63a1262ef0618da5cf7605" +build_time: [515616404, 830067000] +inputs: + "/home/christian/Desktop/swift-algorithm-club/Trie/sources/main.swift": [515616359, 0] + "/home/christian/Desktop/swift-algorithm-club/Trie/sources/trie.swift": [515616400, 0] + "/home/christian/Desktop/swift-algorithm-club/Trie/sources/Queue.swift": [512710161, 0] diff --git a/Trie/.build/debug/Trie.o/Trie/output-file-map.json b/Trie/.build/debug/Trie.o/Trie/output-file-map.json new file mode 100644 index 000000000..be714f4c6 --- /dev/null +++ b/Trie/.build/debug/Trie.o/Trie/output-file-map.json @@ -0,0 +1,23 @@ +{ + "": { + "swift-dependencies": "/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/Trie/master.swiftdeps" + }, + "/home/christian/Desktop/swift-algorithm-club/Trie/sources/main.swift": { + "dependencies": "/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/Trie/main.d", + "object": "/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/sources/main.swift.o", + "swiftmodule": "/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/Trie/main~partial.swiftmodule", + "swift-dependencies": "/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/Trie/main.swiftdeps" + }, + "/home/christian/Desktop/swift-algorithm-club/Trie/sources/trie.swift": { + "dependencies": "/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/Trie/trie.d", + "object": "/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/sources/trie.swift.o", + "swiftmodule": "/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/Trie/trie~partial.swiftmodule", + "swift-dependencies": "/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/Trie/trie.swiftdeps" + }, + "/home/christian/Desktop/swift-algorithm-club/Trie/sources/Queue.swift": { + "dependencies": "/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/Trie/Queue.d", + "object": "/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/sources/Queue.swift.o", + "swiftmodule": "/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/Trie/Queue~partial.swiftmodule", + "swift-dependencies": "/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/Trie/Queue.swiftdeps" + } +} diff --git a/Trie/.build/debug/Trie.o/Trie/trie.d b/Trie/.build/debug/Trie.o/Trie/trie.d new file mode 100644 index 000000000..98996f58e --- /dev/null +++ b/Trie/.build/debug/Trie.o/Trie/trie.d @@ -0,0 +1,3 @@ +/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/sources/trie.swift.o : /home/christian/Desktop/swift-algorithm-club/Trie/sources/main.swift /home/christian/Desktop/swift-algorithm-club/Trie/sources/trie.swift /home/christian/Desktop/swift-algorithm-club/Trie/sources/Queue.swift /home/christian/swiftv2/usr/lib/swift/linux/x86_64/Swift.swiftmodule /home/christian/swiftv2/usr/lib/swift/shims/UnicodeShims.h /home/christian/swiftv2/usr/lib/swift/shims/SwiftStdint.h /home/christian/swiftv2/usr/lib/swift/shims/SwiftStddef.h /home/christian/swiftv2/usr/lib/swift/shims/LibcShims.h /home/christian/swiftv2/usr/lib/swift/shims/RuntimeStubs.h /home/christian/swiftv2/usr/lib/swift/shims/RuntimeShims.h /home/christian/swiftv2/usr/lib/swift/shims/RefCount.h /home/christian/swiftv2/usr/lib/swift/shims/HeapObject.h /home/christian/swiftv2/usr/lib/swift/shims/GlobalObjects.h /home/christian/swiftv2/usr/lib/swift/shims/FoundationShims.h /home/christian/swiftv2/usr/lib/swift/shims/CoreFoundationShims.h /home/christian/swiftv2/usr/lib/swift/shims/module.map +/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/Trie/trie~partial.swiftmodule : /home/christian/Desktop/swift-algorithm-club/Trie/sources/main.swift /home/christian/Desktop/swift-algorithm-club/Trie/sources/trie.swift /home/christian/Desktop/swift-algorithm-club/Trie/sources/Queue.swift /home/christian/swiftv2/usr/lib/swift/linux/x86_64/Swift.swiftmodule /home/christian/swiftv2/usr/lib/swift/shims/UnicodeShims.h /home/christian/swiftv2/usr/lib/swift/shims/SwiftStdint.h /home/christian/swiftv2/usr/lib/swift/shims/SwiftStddef.h /home/christian/swiftv2/usr/lib/swift/shims/LibcShims.h /home/christian/swiftv2/usr/lib/swift/shims/RuntimeStubs.h /home/christian/swiftv2/usr/lib/swift/shims/RuntimeShims.h /home/christian/swiftv2/usr/lib/swift/shims/RefCount.h /home/christian/swiftv2/usr/lib/swift/shims/HeapObject.h /home/christian/swiftv2/usr/lib/swift/shims/GlobalObjects.h /home/christian/swiftv2/usr/lib/swift/shims/FoundationShims.h /home/christian/swiftv2/usr/lib/swift/shims/CoreFoundationShims.h /home/christian/swiftv2/usr/lib/swift/shims/module.map +/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/Trie/trie~partial.swiftdoc : /home/christian/Desktop/swift-algorithm-club/Trie/sources/main.swift /home/christian/Desktop/swift-algorithm-club/Trie/sources/trie.swift /home/christian/Desktop/swift-algorithm-club/Trie/sources/Queue.swift /home/christian/swiftv2/usr/lib/swift/linux/x86_64/Swift.swiftmodule /home/christian/swiftv2/usr/lib/swift/shims/UnicodeShims.h /home/christian/swiftv2/usr/lib/swift/shims/SwiftStdint.h /home/christian/swiftv2/usr/lib/swift/shims/SwiftStddef.h /home/christian/swiftv2/usr/lib/swift/shims/LibcShims.h /home/christian/swiftv2/usr/lib/swift/shims/RuntimeStubs.h /home/christian/swiftv2/usr/lib/swift/shims/RuntimeShims.h /home/christian/swiftv2/usr/lib/swift/shims/RefCount.h /home/christian/swiftv2/usr/lib/swift/shims/HeapObject.h /home/christian/swiftv2/usr/lib/swift/shims/GlobalObjects.h /home/christian/swiftv2/usr/lib/swift/shims/FoundationShims.h /home/christian/swiftv2/usr/lib/swift/shims/CoreFoundationShims.h /home/christian/swiftv2/usr/lib/swift/shims/module.map diff --git a/Trie/.build/debug/Trie.o/Trie/trie.swiftdeps b/Trie/.build/debug/Trie.o/Trie/trie.swiftdeps new file mode 100644 index 000000000..35e802978 --- /dev/null +++ b/Trie/.build/debug/Trie.o/Trie/trie.swiftdeps @@ -0,0 +1,504 @@ +### Swift dependencies file v0 ### +provides-top-level: +- "Node" +- "Trie" +provides-nominal: +- "C4Trie4Node" +- "C4Trie4Trie" +provides-member: +- ["C4Trie4Node", ""] +- ["C4Trie4Trie", ""] +depends-top-level: +- "Int" +- !private "UnicodeScalarType" +- !private "Array" +- "Node" +- "Void" +- !private "==" +- "IntegerLiteralType" +- !private "+=" +- "Trie" +- "FloatLiteralType" +- "Set" +- !private "BooleanLiteralType" +- !private "-" +- "Bool" +- !private "print" +- !private "-=" +- "String" +- !private "&&" +- !private "!" +- !private "Queue" +- !private "+" +- !private "StringLiteralType" +- !private ">" +depends-member: +- !private ["Vs12AnyGenerator", "Element"] +- !private ["Ps9AnyObject", "Array"] +- !private ["Ps9AnyObject", "Node"] +- !private ["Ps9AnyObject", "Queue"] +- !private ["Ps9AnyObject", "Set"] +- !private ["Ps9AnyObject", "String"] +- !private ["Ps9AnyObject", "Trie"] +- !private ["Ps9AnyObject", "char"] +- !private ["Ps9AnyObject", "character"] +- !private ["Ps9AnyObject", "children"] +- !private ["Ps9AnyObject", "contains"] +- !private ["Ps9AnyObject", "find"] +- !private ["Ps9AnyObject", "getChildAt"] +- !private ["Ps9AnyObject", "getChildren"] +- !private ["Ps9AnyObject", "getParent"] +- !private ["Ps9AnyObject", "getWords"] +- !private ["Ps9AnyObject", "init"] +- !private ["Ps9AnyObject", "insert"] +- !private ["Ps9AnyObject", "isAWord"] +- !private ["Ps9AnyObject", "isNotWord"] +- !private ["Ps9AnyObject", "isRoot"] +- !private ["Ps9AnyObject", "isValidWord"] +- !private ["Ps9AnyObject", "isWord"] +- !private ["Ps9AnyObject", "numChildren"] +- !private ["Ps9AnyObject", "parent"] +- !private ["Ps9AnyObject", "print"] +- !private ["Ps9AnyObject", "printNode"] +- !private ["Ps9AnyObject", "remove"] +- !private ["Ps9AnyObject", "root"] +- !private ["Ps9AnyObject", "setParent"] +- !private ["Ps9AnyObject", "update"] +- !private ["Ps9AnyObject", "wordCount"] +- !private ["Ps9AnyObject", "wordList"] +- ["Ps9AnyObject", ""] +- !private ["Vs11AnySequence", "Generator"] +- !private ["Vs11AnySequence", "deinit"] +- !private ["Sa", "Element"] +- !private ["Sa", "Generator"] +- !private ["Sa", "Index"] +- !private ["Sa", "SubSequence"] +- !private ["Sa", "_Element"] +- !private ["Sa", "append"] +- !private ["Sa", "deinit"] +- !private ["Sa", "init"] +- !private ["Sa", "removeAtIndex"] +- !private ["Sa", "subscript"] +- !private ["Ps23ArrayLiteralConvertible", "Element"] +- !private ["Ps23ArrayLiteralConvertible", "Generator"] +- !private ["Ps23ArrayLiteralConvertible", "Index"] +- !private ["Ps23ArrayLiteralConvertible", "SubSequence"] +- !private ["Ps23ArrayLiteralConvertible", "_Element"] +- !private ["Ps23ArrayLiteralConvertible", "append"] +- !private ["Ps23ArrayLiteralConvertible", "init"] +- !private ["Ps23ArrayLiteralConvertible", "removeAtIndex"] +- !private ["Ps23ArrayLiteralConvertible", "subscript"] +- !private ["Vs10ArraySlice", "Generator"] +- !private ["Vs10ArraySlice", "Index"] +- !private ["Ps22BidirectionalIndexType", "Distance"] +- !private ["Ps22BidirectionalIndexType", "IntegerLiteralType"] +- !private ["Ps21BitwiseOperationsType", "Distance"] +- !private ["Ps21BitwiseOperationsType", "IntegerLiteralType"] +- !private ["Sb", "_getBuiltinLogicValue"] +- !private ["Ps25BooleanLiteralConvertible", "_getBuiltinLogicValue"] +- !private ["Ps11BooleanType", "_getBuiltinLogicValue"] +- !private ["Ps11CVarArgType", "Distance"] +- !private ["Ps11CVarArgType", "IntegerLiteralType"] +- !private ["VSS13CharacterView", "Generator"] +- !private ["VSS13CharacterView", "Index"] +- !private ["VSS13CharacterView", "SubSequence"] +- !private ["VSS13CharacterView", "_Element"] +- !private ["VSS13CharacterView", "count"] +- !private ["VSS13CharacterView", "deinit"] +- !private ["VSS13CharacterView", "suffix"] +- !private ["Ps14CollectionType", "Element"] +- !private ["Ps14CollectionType", "Generator"] +- !private ["Ps14CollectionType", "Index"] +- !private ["Ps14CollectionType", "SubSequence"] +- !private ["Ps14CollectionType", "_Element"] +- !private ["Ps14CollectionType", "append"] +- !private ["Ps14CollectionType", "count"] +- !private ["Ps14CollectionType", "init"] +- !private ["Ps14CollectionType", "removeAtIndex"] +- !private ["Ps14CollectionType", "subscript"] +- !private ["Ps14CollectionType", "suffix"] +- !private ["Ps10Comparable", "Distance"] +- !private ["Ps10Comparable", "IntegerLiteralType"] +- !private ["Ps10Comparable", "_DisabledRangeIndex"] +- !private ["Ps10Comparable", "characters"] +- !private ["Ps10Comparable", "init"] +- !private ["Ps10Comparable", "lowercaseString"] +- !private ["Ps28CustomDebugStringConvertible", "Element"] +- !private ["Ps28CustomDebugStringConvertible", "Generator"] +- !private ["Ps28CustomDebugStringConvertible", "Index"] +- ["Ps28CustomDebugStringConvertible", "Some"] +- !private ["Ps28CustomDebugStringConvertible", "SubSequence"] +- !private ["Ps28CustomDebugStringConvertible", "_Element"] +- !private ["Ps28CustomDebugStringConvertible", "append"] +- !private ["Ps28CustomDebugStringConvertible", "characters"] +- !private ["Ps28CustomDebugStringConvertible", "count"] +- !private ["Ps28CustomDebugStringConvertible", "init"] +- !private ["Ps28CustomDebugStringConvertible", "lowercaseString"] +- !private ["Ps28CustomDebugStringConvertible", "removeAtIndex"] +- !private ["Ps28CustomDebugStringConvertible", "subscript"] +- !private ["Ps23CustomStringConvertible", "Distance"] +- !private ["Ps23CustomStringConvertible", "Element"] +- !private ["Ps23CustomStringConvertible", "Generator"] +- !private ["Ps23CustomStringConvertible", "Index"] +- !private ["Ps23CustomStringConvertible", "IntegerLiteralType"] +- !private ["Ps23CustomStringConvertible", "SubSequence"] +- !private ["Ps23CustomStringConvertible", "_Element"] +- !private ["Ps23CustomStringConvertible", "_getBuiltinLogicValue"] +- !private ["Ps23CustomStringConvertible", "append"] +- !private ["Ps23CustomStringConvertible", "count"] +- !private ["Ps23CustomStringConvertible", "init"] +- !private ["Ps23CustomStringConvertible", "removeAtIndex"] +- !private ["Ps23CustomStringConvertible", "subscript"] +- !private ["Vs10Dictionary", "Generator"] +- !private ["Vs10Dictionary", "Index"] +- !private ["Vs10Dictionary", "SubSequence"] +- !private ["Vs10Dictionary", "_Element"] +- !private ["Vs10Dictionary", "count"] +- !private ["Vs10Dictionary", "deinit"] +- !private ["Vs10Dictionary", "init"] +- !private ["Vs10Dictionary", "subscript"] +- !private ["Vs19DictionaryGenerator", "Element"] +- !private ["Vs15DictionaryIndex", "Distance"] +- !private ["Vs15DictionaryIndex", "_DisabledRangeIndex"] +- !private ["Ps28DictionaryLiteralConvertible", "Generator"] +- !private ["Ps28DictionaryLiteralConvertible", "Index"] +- !private ["Ps28DictionaryLiteralConvertible", "SubSequence"] +- !private ["Ps28DictionaryLiteralConvertible", "_Element"] +- !private ["Ps28DictionaryLiteralConvertible", "count"] +- !private ["Ps28DictionaryLiteralConvertible", "init"] +- !private ["Ps28DictionaryLiteralConvertible", "subscript"] +- !private ["Ps9Equatable", "Distance"] +- !private ["Ps9Equatable", "Generator"] +- !private ["Ps9Equatable", "IntegerLiteralType"] +- !private ["Ps9Equatable", "_DisabledRangeIndex"] +- !private ["Ps9Equatable", "_getBuiltinLogicValue"] +- !private ["Ps9Equatable", "characters"] +- !private ["Ps9Equatable", "init"] +- !private ["Ps9Equatable", "lowercaseString"] +- !private ["Ps41ExtendedGraphemeClusterLiteralConvertible", "characters"] +- !private ["Ps41ExtendedGraphemeClusterLiteralConvertible", "init"] +- !private ["Ps41ExtendedGraphemeClusterLiteralConvertible", "lowercaseString"] +- !private ["Ps16ForwardIndexType", "Distance"] +- !private ["Ps16ForwardIndexType", "IntegerLiteralType"] +- !private ["Ps16ForwardIndexType", "_DisabledRangeIndex"] +- !private ["Ps13GeneratorType", "Element"] +- !private ["Ps8Hashable", "Distance"] +- !private ["Ps8Hashable", "Generator"] +- !private ["Ps8Hashable", "IntegerLiteralType"] +- !private ["Ps8Hashable", "_getBuiltinLogicValue"] +- !private ["Ps8Hashable", "characters"] +- !private ["Ps8Hashable", "init"] +- !private ["Ps8Hashable", "lowercaseString"] +- !private ["VVSS13CharacterView5Index", "Distance"] +- !private ["Ps9Indexable", "Element"] +- !private ["Ps9Indexable", "Generator"] +- !private ["Ps9Indexable", "Index"] +- !private ["Ps9Indexable", "SubSequence"] +- !private ["Ps9Indexable", "_Element"] +- !private ["Ps9Indexable", "append"] +- !private ["Ps9Indexable", "count"] +- !private ["Ps9Indexable", "init"] +- !private ["Ps9Indexable", "removeAtIndex"] +- !private ["Ps9Indexable", "subscript"] +- !private ["Ps9Indexable", "suffix"] +- !private ["Vs17IndexingGenerator", "Element"] +- !private ["Si", "Distance"] +- !private ["Si", "IntegerLiteralType"] +- !private ["Ps21IntegerArithmeticType", "Distance"] +- !private ["Ps21IntegerArithmeticType", "IntegerLiteralType"] +- !private ["Ps25IntegerLiteralConvertible", "Distance"] +- !private ["Ps25IntegerLiteralConvertible", "IntegerLiteralType"] +- !private ["Ps11IntegerType", "Distance"] +- !private ["Ps11IntegerType", "IntegerLiteralType"] +- !private ["Ps14MirrorPathType", "Distance"] +- !private ["Ps14MirrorPathType", "IntegerLiteralType"] +- !private ["Ps14MirrorPathType", "characters"] +- !private ["Ps14MirrorPathType", "init"] +- !private ["Ps14MirrorPathType", "lowercaseString"] +- !private ["Ps21MutableCollectionType", "Element"] +- !private ["Ps21MutableCollectionType", "Generator"] +- !private ["Ps21MutableCollectionType", "Index"] +- !private ["Ps21MutableCollectionType", "SubSequence"] +- !private ["Ps21MutableCollectionType", "_Element"] +- !private ["Ps21MutableCollectionType", "append"] +- !private ["Ps21MutableCollectionType", "init"] +- !private ["Ps21MutableCollectionType", "removeAtIndex"] +- !private ["Ps21MutableCollectionType", "subscript"] +- !private ["Ps16MutableIndexable", "Element"] +- !private ["Ps16MutableIndexable", "Generator"] +- !private ["Ps16MutableIndexable", "Index"] +- !private ["Ps16MutableIndexable", "SubSequence"] +- !private ["Ps16MutableIndexable", "_Element"] +- !private ["Ps16MutableIndexable", "append"] +- !private ["Ps16MutableIndexable", "init"] +- !private ["Ps16MutableIndexable", "removeAtIndex"] +- !private ["Ps16MutableIndexable", "subscript"] +- !private ["Ps16MutableSliceable", "Element"] +- !private ["Ps16MutableSliceable", "Generator"] +- !private ["Ps16MutableSliceable", "Index"] +- !private ["Ps16MutableSliceable", "SubSequence"] +- !private ["Ps16MutableSliceable", "_Element"] +- !private ["Ps16MutableSliceable", "append"] +- !private ["Ps16MutableSliceable", "init"] +- !private ["Ps16MutableSliceable", "removeAtIndex"] +- !private ["Ps16MutableSliceable", "subscript"] +- ["Ps21NilLiteralConvertible", "Some"] +- ["C4Trie4Node", "Bool"] +- ["C4Trie4Node", "Int"] +- ["C4Trie4Node", "Node"] +- ["C4Trie4Node", "String"] +- ["C4Trie4Node", "Void"] +- ["C4Trie4Node", "char"] +- !private ["C4Trie4Node", "character"] +- !private ["C4Trie4Node", "children"] +- ["C4Trie4Node", "deinit"] +- ["C4Trie4Node", "getChildAt"] +- ["C4Trie4Node", "getChildren"] +- ["C4Trie4Node", "getParent"] +- ["C4Trie4Node", "init"] +- !private ["C4Trie4Node", "isAWord"] +- ["C4Trie4Node", "isLeaf"] +- ["C4Trie4Node", "isNotWord"] +- ["C4Trie4Node", "isRoot"] +- ["C4Trie4Node", "isValidWord"] +- ["C4Trie4Node", "isWord"] +- ["C4Trie4Node", "numChildren"] +- !private ["C4Trie4Node", "parent"] +- !private ["C4Trie4Node", "print"] +- ["C4Trie4Node", "printNode"] +- ["C4Trie4Node", "setParent"] +- ["C4Trie4Node", "update"] +- ["Sq", "Some"] +- !private ["Sq", "deinit"] +- !private ["Ps16OutputStreamType", "characters"] +- !private ["Ps16OutputStreamType", "init"] +- !private ["Ps16OutputStreamType", "lowercaseString"] +- !private ["V4Trie5Queue", "init"] +- !private ["Ps21RandomAccessIndexType", "Distance"] +- !private ["Ps21RandomAccessIndexType", "IntegerLiteralType"] +- !private ["Ps30RangeReplaceableCollectionType", "Element"] +- !private ["Ps30RangeReplaceableCollectionType", "Generator"] +- !private ["Ps30RangeReplaceableCollectionType", "Index"] +- !private ["Ps30RangeReplaceableCollectionType", "SubSequence"] +- !private ["Ps30RangeReplaceableCollectionType", "_Element"] +- !private ["Ps30RangeReplaceableCollectionType", "append"] +- !private ["Ps30RangeReplaceableCollectionType", "count"] +- !private ["Ps30RangeReplaceableCollectionType", "init"] +- !private ["Ps30RangeReplaceableCollectionType", "removeAtIndex"] +- !private ["Ps30RangeReplaceableCollectionType", "subscript"] +- !private ["Ps30RangeReplaceableCollectionType", "suffix"] +- !private ["Ps12SequenceType", "Element"] +- !private ["Ps12SequenceType", "Generator"] +- !private ["Ps12SequenceType", "Index"] +- !private ["Ps12SequenceType", "SubSequence"] +- !private ["Ps12SequenceType", "_Element"] +- !private ["Ps12SequenceType", "append"] +- !private ["Ps12SequenceType", "count"] +- !private ["Ps12SequenceType", "init"] +- !private ["Ps12SequenceType", "removeAtIndex"] +- !private ["Ps12SequenceType", "subscript"] +- !private ["Ps12SequenceType", "suffix"] +- !private ["Vs3Set", "Generator"] +- !private ["Vs3Set", "init"] +- !private ["Vs12SetGenerator", "Element"] +- !private ["Ps17SignedIntegerType", "Distance"] +- !private ["Ps17SignedIntegerType", "IntegerLiteralType"] +- !private ["Ps16SignedNumberType", "Distance"] +- !private ["Ps16SignedNumberType", "IntegerLiteralType"] +- !private ["Vs5Slice", "Generator"] +- !private ["Vs5Slice", "Index"] +- !private ["Vs5Slice", "SubSequence"] +- !private ["Vs5Slice", "_Element"] +- !private ["Vs5Slice", "deinit"] +- !private ["Ps10Streamable", "characters"] +- !private ["Ps10Streamable", "init"] +- !private ["Ps10Streamable", "lowercaseString"] +- !private ["Ps10Strideable", "Distance"] +- !private ["Ps10Strideable", "IntegerLiteralType"] +- !private ["SS", "characters"] +- !private ["SS", "init"] +- !private ["SS", "lowercaseString"] +- !private ["Ps30StringInterpolationConvertible", "characters"] +- !private ["Ps30StringInterpolationConvertible", "init"] +- !private ["Ps30StringInterpolationConvertible", "lowercaseString"] +- !private ["Ps24StringLiteralConvertible", "characters"] +- !private ["Ps24StringLiteralConvertible", "init"] +- !private ["Ps24StringLiteralConvertible", "lowercaseString"] +- !private ["C4Trie4Trie", "Array"] +- ["C4Trie4Trie", "Bool"] +- ["C4Trie4Trie", "Int"] +- ["C4Trie4Trie", "Node"] +- !private ["C4Trie4Trie", "Queue"] +- ["C4Trie4Trie", "Set"] +- ["C4Trie4Trie", "String"] +- ["C4Trie4Trie", "Trie"] +- ["C4Trie4Trie", "contains"] +- ["C4Trie4Trie", "count"] +- ["C4Trie4Trie", "deinit"] +- ["C4Trie4Trie", "find"] +- ["C4Trie4Trie", "findPrefix"] +- ["C4Trie4Trie", "getWords"] +- ["C4Trie4Trie", "init"] +- ["C4Trie4Trie", "insert"] +- ["C4Trie4Trie", "isEmpty"] +- ["C4Trie4Trie", "isPrefix"] +- ["C4Trie4Trie", "merge"] +- ["C4Trie4Trie", "printTrie"] +- ["C4Trie4Trie", "remove"] +- ["C4Trie4Trie", "removeAll"] +- !private ["C4Trie4Trie", "root"] +- !private ["C4Trie4Trie", "wordCount"] +- !private ["C4Trie4Trie", "wordList"] +- !private ["Ps31UnicodeScalarLiteralConvertible", "characters"] +- !private ["Ps31UnicodeScalarLiteralConvertible", "init"] +- !private ["Ps31UnicodeScalarLiteralConvertible", "lowercaseString"] +- !private ["Ps10_ArrayType", "Element"] +- !private ["Ps10_ArrayType", "Generator"] +- !private ["Ps10_ArrayType", "Index"] +- !private ["Ps10_ArrayType", "SubSequence"] +- !private ["Ps10_ArrayType", "_Element"] +- !private ["Ps10_ArrayType", "append"] +- !private ["Ps10_ArrayType", "init"] +- !private ["Ps10_ArrayType", "removeAtIndex"] +- !private ["Ps10_ArrayType", "subscript"] +- !private ["Ps33_BuiltinBooleanLiteralConvertible", "_getBuiltinLogicValue"] +- !private ["Ps49_BuiltinExtendedGraphemeClusterLiteralConvertible", "characters"] +- !private ["Ps49_BuiltinExtendedGraphemeClusterLiteralConvertible", "init"] +- !private ["Ps49_BuiltinExtendedGraphemeClusterLiteralConvertible", "lowercaseString"] +- !private ["Ps33_BuiltinIntegerLiteralConvertible", "Distance"] +- !private ["Ps33_BuiltinIntegerLiteralConvertible", "IntegerLiteralType"] +- !private ["Ps32_BuiltinStringLiteralConvertible", "characters"] +- !private ["Ps32_BuiltinStringLiteralConvertible", "init"] +- !private ["Ps32_BuiltinStringLiteralConvertible", "lowercaseString"] +- !private ["Ps37_BuiltinUTF16StringLiteralConvertible", "characters"] +- !private ["Ps37_BuiltinUTF16StringLiteralConvertible", "init"] +- !private ["Ps37_BuiltinUTF16StringLiteralConvertible", "lowercaseString"] +- !private ["Ps39_BuiltinUnicodeScalarLiteralConvertible", "characters"] +- !private ["Ps39_BuiltinUnicodeScalarLiteralConvertible", "init"] +- !private ["Ps39_BuiltinUnicodeScalarLiteralConvertible", "lowercaseString"] +- !private ["Ps24_DestructorSafeContainer", "Element"] +- !private ["Ps24_DestructorSafeContainer", "Generator"] +- !private ["Ps24_DestructorSafeContainer", "Index"] +- !private ["Ps24_DestructorSafeContainer", "SubSequence"] +- !private ["Ps24_DestructorSafeContainer", "_Element"] +- !private ["Ps24_DestructorSafeContainer", "append"] +- !private ["Ps24_DestructorSafeContainer", "init"] +- !private ["Ps24_DestructorSafeContainer", "removeAtIndex"] +- !private ["Ps24_DestructorSafeContainer", "subscript"] +- !private ["Ps14_Incrementable", "Distance"] +- !private ["Ps14_Incrementable", "IntegerLiteralType"] +- !private ["Ps14_Incrementable", "_DisabledRangeIndex"] +- !private ["Ps22_IntegerArithmeticType", "Distance"] +- !private ["Ps22_IntegerArithmeticType", "IntegerLiteralType"] +- !private ["Ps12_IntegerType", "Distance"] +- !private ["Ps12_IntegerType", "IntegerLiteralType"] +- !private ["Vs26_OptionalNilComparisonType", "deinit"] +- !private ["Ps22_RandomAccessAmbiguity", "Distance"] +- !private ["Ps22_RandomAccessAmbiguity", "IntegerLiteralType"] +- !private ["Ps12_Reflectable", "Distance"] +- !private ["Ps12_Reflectable", "Element"] +- !private ["Ps12_Reflectable", "Generator"] +- !private ["Ps12_Reflectable", "Index"] +- !private ["Ps12_Reflectable", "IntegerLiteralType"] +- ["Ps12_Reflectable", "Some"] +- !private ["Ps12_Reflectable", "SubSequence"] +- !private ["Ps12_Reflectable", "_Element"] +- !private ["Ps12_Reflectable", "_getBuiltinLogicValue"] +- !private ["Ps12_Reflectable", "append"] +- !private ["Ps12_Reflectable", "characters"] +- !private ["Ps12_Reflectable", "count"] +- !private ["Ps12_Reflectable", "init"] +- !private ["Ps12_Reflectable", "lowercaseString"] +- !private ["Ps12_Reflectable", "removeAtIndex"] +- !private ["Ps12_Reflectable", "subscript"] +- !private ["Ps18_SignedIntegerType", "Distance"] +- !private ["Ps18_SignedIntegerType", "IntegerLiteralType"] +depends-nominal: +- !private "Vs12AnyGenerator" +- "Ps9AnyObject" +- !private "Vs11AnySequence" +- !private "Sa" +- !private "Ps23ArrayLiteralConvertible" +- !private "Vs10ArraySlice" +- !private "Ps22BidirectionalIndexType" +- !private "Ps21BitwiseOperationsType" +- !private "Sb" +- !private "Ps25BooleanLiteralConvertible" +- !private "Ps11BooleanType" +- !private "Ps11CVarArgType" +- !private "VSS13CharacterView" +- !private "Ps14CollectionType" +- !private "Ps10Comparable" +- "Ps28CustomDebugStringConvertible" +- !private "Ps23CustomStringConvertible" +- !private "Vs10Dictionary" +- !private "Vs19DictionaryGenerator" +- !private "Vs15DictionaryIndex" +- !private "Ps28DictionaryLiteralConvertible" +- !private "Ps9Equatable" +- !private "Ps41ExtendedGraphemeClusterLiteralConvertible" +- !private "Ps16ForwardIndexType" +- !private "Ps13GeneratorType" +- !private "Ps8Hashable" +- !private "VVSS13CharacterView5Index" +- !private "Ps9Indexable" +- !private "Vs17IndexingGenerator" +- !private "Si" +- !private "Ps21IntegerArithmeticType" +- !private "Ps25IntegerLiteralConvertible" +- !private "Ps11IntegerType" +- !private "Ps14MirrorPathType" +- !private "Ps21MutableCollectionType" +- !private "Ps16MutableIndexable" +- !private "Ps16MutableSliceable" +- "Ps21NilLiteralConvertible" +- "C4Trie4Node" +- "Sq" +- !private "Ps16OutputStreamType" +- !private "V4Trie5Queue" +- !private "Ps21RandomAccessIndexType" +- !private "Ps30RangeReplaceableCollectionType" +- !private "Ps12SequenceType" +- !private "Vs3Set" +- !private "Vs12SetGenerator" +- !private "Ps17SignedIntegerType" +- !private "Ps16SignedNumberType" +- !private "Vs5Slice" +- !private "Ps10Streamable" +- !private "Ps10Strideable" +- !private "SS" +- !private "Ps30StringInterpolationConvertible" +- !private "Ps24StringLiteralConvertible" +- "C4Trie4Trie" +- !private "Ps31UnicodeScalarLiteralConvertible" +- !private "Ps10_ArrayType" +- !private "Ps33_BuiltinBooleanLiteralConvertible" +- !private "Ps49_BuiltinExtendedGraphemeClusterLiteralConvertible" +- !private "Ps33_BuiltinIntegerLiteralConvertible" +- !private "Ps32_BuiltinStringLiteralConvertible" +- !private "Ps37_BuiltinUTF16StringLiteralConvertible" +- !private "Ps39_BuiltinUnicodeScalarLiteralConvertible" +- !private "Ps24_DestructorSafeContainer" +- !private "Ps14_Incrementable" +- !private "Ps22_IntegerArithmeticType" +- !private "Ps12_IntegerType" +- !private "Vs26_OptionalNilComparisonType" +- !private "Ps22_RandomAccessAmbiguity" +- "Ps12_Reflectable" +- !private "Ps18_SignedIntegerType" +depends-dynamic-lookup: +depends-external: +- "/home/christian/swiftv2/usr/lib/swift/linux/x86_64/Swift.swiftmodule" +- "/home/christian/swiftv2/usr/lib/swift/shims/UnicodeShims.h" +- "/home/christian/swiftv2/usr/lib/swift/shims/SwiftStdint.h" +- "/home/christian/swiftv2/usr/lib/swift/shims/SwiftStddef.h" +- "/home/christian/swiftv2/usr/lib/swift/shims/LibcShims.h" +- "/home/christian/swiftv2/usr/lib/swift/shims/RuntimeStubs.h" +- "/home/christian/swiftv2/usr/lib/swift/shims/RuntimeShims.h" +- "/home/christian/swiftv2/usr/lib/swift/shims/RefCount.h" +- "/home/christian/swiftv2/usr/lib/swift/shims/HeapObject.h" +- "/home/christian/swiftv2/usr/lib/swift/shims/GlobalObjects.h" +- "/home/christian/swiftv2/usr/lib/swift/shims/FoundationShims.h" +- "/home/christian/swiftv2/usr/lib/swift/shims/CoreFoundationShims.h" +- "/home/christian/swiftv2/usr/lib/swift/shims/module.map" +interface-hash: "fd9fdb3a4bd3dfc789eaf1430eb72c67" diff --git a/Trie/.build/debug/Trie.o/Trie/trie~partial.swiftdoc b/Trie/.build/debug/Trie.o/Trie/trie~partial.swiftdoc new file mode 100644 index 0000000000000000000000000000000000000000..12942dedfe6852aa61b902224cde186d2adaaf6c GIT binary patch literal 540 zcmaDfX9YVW2LppD0|Ns)qlJ#c+7Dby0=U-%aP4>CT5rI$Ux91Q2d>2%xY!*xUFbQa zy@N^j#3Ahshx9v`wD%m+SaZl(Xp58P1t*OOP8vYc#=uE?50mBxdSs$%*Q9pSHW1%LeHSMEDy*( z2E-K>X7Oewx}|y9dHLmex;dG7r4_pAd8I%phE||K?m*gzO@POXg+Yf2BnSi!U~-gz Gg#ZA|lTWSy literal 0 HcmV?d00001 diff --git a/Trie/.build/debug/Trie.o/Trie/trie~partial.swiftmodule b/Trie/.build/debug/Trie.o/Trie/trie~partial.swiftmodule new file mode 100644 index 0000000000000000000000000000000000000000..adcffc2d393f212f2788c24b04011d6603038431 GIT binary patch literal 53928 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 literal 0 HcmV?d00001 diff --git a/Trie/.build/debug/Trie.o/build.db b/Trie/.build/debug/Trie.o/build.db new file mode 100644 index 0000000000000000000000000000000000000000..0028fe224f5e646cb2855a04c20247cf4e075b37 GIT binary patch literal 15360 zcmeHNTWlN06`k2xk&;P8vTIj%qyTG2FWM4mIF0*=Ls_ONMX^d*BvnNS3Ym|UwKd6= zxx0E)Qk7L2pg@5l{wRvTK>d+?1xDNSqYc`kDT1P{QJ_G+`q3gS&>(FRp@D3J2JRFYp30RE~i$_Ny!+pZ}=*X7` zqf^4U@YH5Wql8Zw8jFTUh9l%JQ-)87hKIt@a3mCtQB_iIM(&l;KA$i-5`SuJA}&P7 zCP&WdpXJP}5?ok;T@}Co-BSoEaTE(&d|t*+Fv3>z^0%iX`VOYBG|TQ>ShD*wyn1)l$?) zd=sKi0RGlf9f3Lmy8{6?XaKMg^4^AV54F zG+x3dcMm=_EBNF(%;7UcKgVa#LNDaDp6UqH5qMA$7~3>#&uJd&C?5&T%2_dxn$1g! zDkX9OWkH%z=T8JQB_GI0N%}jW%t~1$5Y=+3loeyDmQ?(+)c=1*Bzlo?*%V&CsUuKF z;6X;fGsx==(2@5KXXIoeGnV|Cm{PI(KiUi%0Rqnf@En5Z>-2Lkn~d#u1O3oSQdz+T z%8j?9lXScdFqZs#F3lKkX8U+vM~Csq-|JL$NY0BxvX)C5JYI}U>1-A^MdPbE>I2M* zR>I@sWVeFwe=gVxU@N@BwQ}D^JX$x3?$XoR5!@+FPCKRI4mrj;=eN6p?u^B8i9+o;?V9lxar^Lh@ol?pVML$!0yll%Cx~lNRs5leC-k_FO z+`|+fd#oJfE8Q4!}1+6k*8=l**kotrxxv&RXkN-oK64lX4>Ckvz}dh zGx`y5f$IQVhu!dHPT;BoViAB$X%a4$&$AeGj$z46w5vU_jN1#>&Na*#zW&oSv z6nq7K$bE@h=YE44(GYqby+J;;YIrc~do5;d-k-y4>LELuT6u)G5D`yfS#7n*D$Eu& zi&8OJLMNUwqDu3{+fSy$xPg1^4J<8+QqLv#t|2U^$(bD6c54vJXmBQD%Z}+u1lODi zux@%zA-L+Swq;rR1cJ-XDi=0AHSqs*-$MN#zYK7jYvI~q1Gmb(4QG%KzJ^rv3yYI{ znr|=gddN-y?dWXIa681h0pyF?u^xECJFlD|Z9;Lag)48V2jo9U_)XoFp$WO-@^I&ZLk5*sbU@m;8(5f^0Et6aClW5IZ zW$V1!`2<>aR=Y4Yb~(qrn9}R6UI1m~dK_C{c&;Fj;2bFm&hsQV)2!fP18RZsCFA+u zGkftcHlj!WMN#c%Fa2)!NOJv}s+5dWRjWj$ zP>DPzS-NYkc3!A3HIyT${?I{rp&xvP8rS*}<%Rxn;>1CcUqrY~LRG{O=q< z3GPiU5B~_i1JBX6)XxqP7+i9J7TnQs_80+t>$f-9)8EP@dA-AnF3?WKiV^sOW^MCY znHU@nJo>=}H)vn)FdZ^TypW8N@sq)cTjck zF5ug2qq*~N+C&oy>|q@m_OK9|*)NxKu$=-0F;Bfa<`wpY<;~kE-g!M_ z{oew+0UU={;9J~2F2cRYz0CcDyTSb#1<^GageUOdyF7UiY+qtdN$wZvwmG;DLEl30 zDs2E$QP3HkW3JYX)piZ_jn#e?j8O4*!#N#QShZ3fu9hVTK~yOwB}kTP&(iE!^Tk;S d+!f)4I~)~?7>o;8L+DOxusZf#QD6;h{|BlQ@MQo1 literal 0 HcmV?d00001 diff --git a/Trie/.build/debug/Trie.o/llbuild.yaml b/Trie/.build/debug/Trie.o/llbuild.yaml new file mode 100644 index 000000000..8607eca74 --- /dev/null +++ b/Trie/.build/debug/Trie.o/llbuild.yaml @@ -0,0 +1,29 @@ +client: + name: swift-build + +tools: {} + +targets: + "": [] + Trie: [] + +commands: + : + tool: swift-compiler + executable: "/home/christian/swiftv2/usr/bin/swiftc" + inputs: ["/home/christian/Desktop/swift-algorithm-club/Trie/sources/main.swift","/home/christian/Desktop/swift-algorithm-club/Trie/sources/trie.swift","/home/christian/Desktop/swift-algorithm-club/Trie/sources/Queue.swift"] + outputs: ["","/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.swiftmodule","/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/sources/main.swift.o","/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/sources/trie.swift.o","/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/sources/Queue.swift.o"] + module-name: "Trie" + module-output-path: "/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.swiftmodule" + is-library: false + sources: ["/home/christian/Desktop/swift-algorithm-club/Trie/sources/main.swift","/home/christian/Desktop/swift-algorithm-club/Trie/sources/trie.swift","/home/christian/Desktop/swift-algorithm-club/Trie/sources/Queue.swift"] + objects: ["/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/sources/main.swift.o","/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/sources/trie.swift.o","/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/sources/Queue.swift.o"] + import-paths: ["/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug"] + temps-path: "/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/Trie" + other-args: ["-j8","-Onone","-g","-I","/usr/local/include"] + : + tool: shell + inputs: ["","/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/sources/main.swift.o","/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/sources/trie.swift.o","/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/sources/Queue.swift.o"] + outputs: ["","/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie"] + args: ["/home/christian/swiftv2/usr/bin/swiftc","-o","/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie","/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/sources/main.swift.o","/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/sources/trie.swift.o","/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/sources/Queue.swift.o","-g","-L/usr/local/lib"] + description: "Linking Executable: .build/debug/Trie" diff --git a/Trie/.build/debug/Trie.o/sources/Queue.swift.o b/Trie/.build/debug/Trie.o/sources/Queue.swift.o new file mode 100644 index 0000000000000000000000000000000000000000..efac8c7a3782cff0aaa917c7375533ce4bf89c97 GIT binary patch literal 23440 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 Q!TC}@zaK=s+18)`1zC`*`~Uy| literal 0 HcmV?d00001 diff --git a/Trie/.build/debug/Trie.o/sources/main.swift.o b/Trie/.build/debug/Trie.o/sources/main.swift.o new file mode 100644 index 0000000000000000000000000000000000000000..c44e7e0254fa8c98846d9e01de765def37b2da8c GIT binary patch literal 13864 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⪼Ocn4ui*GwL-Kh?;D~dtg1;wl#91A0i@1>kzFv{PUEmlm{?Cy1Hz~Nv=Wc<+ zuNwa@7yDwGuqQM2e+}uO$mdezFj)tV9F8LKC~vZR7>TbD7!H^-C{q5bylMXhC-I8{ z$671?Z9^k{8@p+ z4)TU9&x?w*GbH4{BXAjiDgOfpE}tX*+F|F1Vxld&;D6_0=bs(;q*y<1JM6qD>|b%n z%jePmaNyU3onJWYyd>=W${{bGcjbM!jDwtqZ2+jqxVUiuvP=L9bA=Ov%-3H&~X{0{{_?!f76~1y}RcGYXD;bye8;69@hcabCWy;K)}6(U#9CGHxIdRNF!3 z^a^xFWxSN_NEust!Ghv%mS{hhjwfbt9G_&KM~YHY5WPW7 z+U;#P!^k)cA{No#B=PxUd&~X%N(Fl5s2qvJD{Sw4xHNstxm%8b_0pR}d2<}>X{>`~ zgI+?xo^mV}3DfGD$>w=0KIyu@EIBFX8Qad7QJgksEqAdeZpi6y1eV5?sX3aN95`Mm zrK9xz6@>z48KH@V8wd*Y23>MXu^4&kip24P5apa0C5Qa9m}?`&f#eC(h|v@nIo_Ww z564C)CPuOmq7lPr={FROQ|OVv((%E%)<9jWzpm9+*Xq@#bA=?$G@5X6N`H}&vGM-! z`1ojKpucBuWO$@!uy?q>d!(m#aOYUpcsOnrjvD!%8`a8G@~NIW$Mvo5x<0&_p-!>h zIK8cvvR~D3TgH((Bh)Gtu)2{2A|dtuR9xO}`0xTJZb0STF65i02W}T=L&H?lHtIzZ79dT|6Mo;sK8ep80WaAkE=f5CvkuoMU)W z2&&HlkeB+XqkNx;gMSxm)qbQt{u5V=xZSbi5GDW^xT)p5aD;mzwK)AB6#7n{FA2d9 z9f5WFf1VsmO!f0)1hzqO%A)PWpeFU-b=YvqK2CrWgUa)5T=55vPDfLFn1Dv-e{mDn zm(N)^|G4**@ssC&g7lp>p?Od~kfWg#r|fIg=fof`^>-?|s5)i;masZm zxs(6q1~v)Oo)P@zJ~c2Dr+@S}^1r@;e@qFd|NkL_PMh#^;r|)G9zOqy&iTJ6^q+(= zrAYr0>LkTR{OKJpRt^h6#1AH=zKrW8m-(-Y7Xt8#lUf{2ZG(&d(+%Q>T<7$Ep7iOn Tq`V1XDn;?U1;1DlPW}G_(i+=w literal 0 HcmV?d00001 diff --git a/Trie/.build/debug/Trie.o/sources/trie.swift.o b/Trie/.build/debug/Trie.o/sources/trie.swift.o new file mode 100644 index 0000000000000000000000000000000000000000..dda3f017321c7fa1cf9e09b846f00ea0cc4bb14f GIT binary patch literal 94800 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 Gg#ZA|lTWSy literal 0 HcmV?d00001 diff --git a/Trie/.build/debug/Trie.swiftmodule b/Trie/.build/debug/Trie.swiftmodule new file mode 100644 index 0000000000000000000000000000000000000000..9c1463f850e9a3df6dac26495e6a4be9822ca2dd GIT binary patch literal 20724 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 CFj24o literal 0 HcmV?d00001 diff --git a/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/build.db b/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/build.db new file mode 100644 index 0000000000000000000000000000000000000000..1c00411e4402e025363b0e2c481337daff6a3f53 GIT binary patch literal 7168 zcmeHM%WvaE7@vn@Cqb}6VmB)EFb7sNQWGOsgg{H!KD;H}lF}rlo0H`x)6_JvgCAwl zBCT8`;J^h54u}i?0*4hyh{pkm8#lB^Zh%05fD00PV8+fQ?pCF4f-14isFuf*@A>;4 zV^3>qE2c-umhE&6k30?}03oJ-U|>Nbn1QUq?To zhuLH@{woBUl9DT&hXFLL7QN>99jZIj^*f%co2`A%sfDUGSJ%jTrM$MTk#c2GyGrh4 zAgh&qYh-4JzM2mfu#!_%xc7u-Y<6hK)S^AgR9a1wx(61dzOMS*{E8L{jMI~uki%>- zE9%;kR-GkG4XM?u<;v15d7)Z(8yO*GYACqr4cLLrU&E!^$3d(Z?zd13qYbpNcS{!s57*`>o$K zIzA=yE35OfWYaf0p3drO;AhkB_I!`FVvG6fP|2M=3xh^z7q^~YXrCQ?<#7GG)NxJQ zimB#Wor!;6vTd2K@c7hr#rF+pI0z$rmM1}Om387am5h4^powG!P<2>=r} zCkUK+1Y|kOFt`W&3b2W9;z!UQ=ri;d!te%MhSO~ME*k|5^=##0&uH!#ZK_*Fm+ITp zp}JwU^c_lj`pdrUQN3$8J8p?nXBLuDU%;@NPAa?LzG7~9%~F6QxTmBm>bBjbYIEB$ zUC%Tub&LU<5}`Ns6^Vk2A@mFr|*mG$+9zC0)Ir)k74LHuVbq*XuiD z7ZU6~ruwd?yBhMgeKO8W~2ZXp6&Akv2(TwNf(Za^n-edJK}ZuRtVs zVtrDiPw*Y}VkGp*eFY!B{ndj{-bktqfa_QRL5evjfZ6g2$KFrF4_BtM_VH7*?|t{t z14-2f5@OnOqveJupkb8xA$j~DTuMiVd^0^APJTNVJvV-t+2FHJ-$;jN>a3eEGp5Ef zBUZU@!$c_(iWXC)2-+qzLzWn)<`}jRPn@0tJFQHq=Vw1_3AaEE0&t_$ChNW!1 zpXA`jAHI$!|6zQC^>#)EI?wrpovkEVsQ6$TNIGKDPDhH8wzQJ?N7tjr^eA{nVOvdR Uv^pMdtBF] + package_name_here_and_keep_quote_marks: [] + +commands: + : + tool: swift-compiler + executable: "/home/christian/swiftv2/usr/bin/swiftc" + inputs: ["/home/christian/Desktop/swift-algorithm-club/Trie/sources/trie.swift","/home/christian/Desktop/swift-algorithm-club/Trie/sources/Queue.swift"] + outputs: ["","/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/package_name_here_and_keep_quote_marks.swiftmodule","/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/sources/trie.swift.o","/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/sources/Queue.swift.o"] + module-name: "package_name_here_and_keep_quote_marks" + module-output-path: "/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/package_name_here_and_keep_quote_marks.swiftmodule" + is-library: true + sources: ["/home/christian/Desktop/swift-algorithm-club/Trie/sources/trie.swift","/home/christian/Desktop/swift-algorithm-club/Trie/sources/Queue.swift"] + objects: ["/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/sources/trie.swift.o","/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/sources/Queue.swift.o"] + import-paths: ["/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug"] + temps-path: "/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/package_name_here_and_keep_quote_marks" + other-args: ["-j8","-Onone","-g","-enable-testing","-I","/usr/local/include"] + : + tool: shell + inputs: ["","/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/sources/trie.swift.o","/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/sources/Queue.swift.o"] + outputs: ["","/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/package_name_here_and_keep_quote_marks.a"] + args: ["/bin/sh","-c","rm -f '/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/package_name_here_and_keep_quote_marks.a'; ar cr '/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/package_name_here_and_keep_quote_marks.a' '/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/sources/trie.swift.o' '/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/sources/Queue.swift.o'"] + description: "Linking Library: .build/debug/package_name_here_and_keep_quote_marks.a" diff --git a/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/package_name_here_and_keep_quote_marks/Queue.d b/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/package_name_here_and_keep_quote_marks/Queue.d new file mode 100644 index 000000000..2b2aa612f --- /dev/null +++ b/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/package_name_here_and_keep_quote_marks/Queue.d @@ -0,0 +1,3 @@ +/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/sources/Queue.swift.o : /home/christian/Desktop/swift-algorithm-club/Trie/sources/trie.swift /home/christian/Desktop/swift-algorithm-club/Trie/sources/Queue.swift /home/christian/swiftv2/usr/lib/swift/linux/x86_64/Swift.swiftmodule /home/christian/swiftv2/usr/lib/swift/shims/UnicodeShims.h /home/christian/swiftv2/usr/lib/swift/shims/SwiftStdint.h /home/christian/swiftv2/usr/lib/swift/shims/SwiftStddef.h /home/christian/swiftv2/usr/lib/swift/shims/LibcShims.h /home/christian/swiftv2/usr/lib/swift/shims/RuntimeStubs.h /home/christian/swiftv2/usr/lib/swift/shims/RuntimeShims.h /home/christian/swiftv2/usr/lib/swift/shims/RefCount.h /home/christian/swiftv2/usr/lib/swift/shims/HeapObject.h /home/christian/swiftv2/usr/lib/swift/shims/GlobalObjects.h /home/christian/swiftv2/usr/lib/swift/shims/FoundationShims.h /home/christian/swiftv2/usr/lib/swift/shims/CoreFoundationShims.h /home/christian/swiftv2/usr/lib/swift/shims/module.map +/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/package_name_here_and_keep_quote_marks/Queue~partial.swiftmodule : /home/christian/Desktop/swift-algorithm-club/Trie/sources/trie.swift /home/christian/Desktop/swift-algorithm-club/Trie/sources/Queue.swift /home/christian/swiftv2/usr/lib/swift/linux/x86_64/Swift.swiftmodule /home/christian/swiftv2/usr/lib/swift/shims/UnicodeShims.h /home/christian/swiftv2/usr/lib/swift/shims/SwiftStdint.h /home/christian/swiftv2/usr/lib/swift/shims/SwiftStddef.h /home/christian/swiftv2/usr/lib/swift/shims/LibcShims.h /home/christian/swiftv2/usr/lib/swift/shims/RuntimeStubs.h /home/christian/swiftv2/usr/lib/swift/shims/RuntimeShims.h /home/christian/swiftv2/usr/lib/swift/shims/RefCount.h /home/christian/swiftv2/usr/lib/swift/shims/HeapObject.h /home/christian/swiftv2/usr/lib/swift/shims/GlobalObjects.h /home/christian/swiftv2/usr/lib/swift/shims/FoundationShims.h /home/christian/swiftv2/usr/lib/swift/shims/CoreFoundationShims.h /home/christian/swiftv2/usr/lib/swift/shims/module.map +/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/package_name_here_and_keep_quote_marks/Queue~partial.swiftdoc : /home/christian/Desktop/swift-algorithm-club/Trie/sources/trie.swift /home/christian/Desktop/swift-algorithm-club/Trie/sources/Queue.swift /home/christian/swiftv2/usr/lib/swift/linux/x86_64/Swift.swiftmodule /home/christian/swiftv2/usr/lib/swift/shims/UnicodeShims.h /home/christian/swiftv2/usr/lib/swift/shims/SwiftStdint.h /home/christian/swiftv2/usr/lib/swift/shims/SwiftStddef.h /home/christian/swiftv2/usr/lib/swift/shims/LibcShims.h /home/christian/swiftv2/usr/lib/swift/shims/RuntimeStubs.h /home/christian/swiftv2/usr/lib/swift/shims/RuntimeShims.h /home/christian/swiftv2/usr/lib/swift/shims/RefCount.h /home/christian/swiftv2/usr/lib/swift/shims/HeapObject.h /home/christian/swiftv2/usr/lib/swift/shims/GlobalObjects.h /home/christian/swiftv2/usr/lib/swift/shims/FoundationShims.h /home/christian/swiftv2/usr/lib/swift/shims/CoreFoundationShims.h /home/christian/swiftv2/usr/lib/swift/shims/module.map diff --git a/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/package_name_here_and_keep_quote_marks/Queue.swiftdeps b/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/package_name_here_and_keep_quote_marks/Queue.swiftdeps new file mode 100644 index 000000000..eaa595090 --- /dev/null +++ b/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/package_name_here_and_keep_quote_marks/Queue.swiftdeps @@ -0,0 +1,316 @@ +### Swift dependencies file v0 ### +provides-top-level: +- "Queue" +provides-nominal: +- "V38package_name_here_and_keep_quote_marks5Queue" +provides-member: +- ["V38package_name_here_and_keep_quote_marks5Queue", ""] +depends-top-level: +- "Queue" +- !private "/" +- !private "&&" +- !private "Double" +- !private "-" +- "Bool" +- "FloatLiteralType" +- "IntegerLiteralType" +- !private ">" +- !private "==" +- "Int" +- !private "<" +- !private "+=" +depends-member: +- !private ["Ps16AbsoluteValuable", "init"] +- ["Sa", "Generator"] +- ["Sa", "Index"] +- ["Sa", "SubSequence"] +- ["Sa", "_Element"] +- !private ["Sa", "append"] +- !private ["Sa", "count"] +- !private ["Sa", "deinit"] +- ["Sa", "init"] +- !private ["Sa", "removeFirst"] +- !private ["Sa", "subscript"] +- ["Ps23ArrayLiteralConvertible", "Generator"] +- ["Ps23ArrayLiteralConvertible", "Index"] +- ["Ps23ArrayLiteralConvertible", "SubSequence"] +- ["Ps23ArrayLiteralConvertible", "_Element"] +- !private ["Ps23ArrayLiteralConvertible", "append"] +- !private ["Ps23ArrayLiteralConvertible", "count"] +- ["Ps23ArrayLiteralConvertible", "init"] +- !private ["Ps23ArrayLiteralConvertible", "removeFirst"] +- !private ["Ps23ArrayLiteralConvertible", "subscript"] +- ["Vs10ArraySlice", "Generator"] +- ["Vs10ArraySlice", "Index"] +- ["Ps22BidirectionalIndexType", "Distance"] +- ["Ps22BidirectionalIndexType", "IntegerLiteralType"] +- ["Ps21BitwiseOperationsType", "Distance"] +- ["Ps21BitwiseOperationsType", "IntegerLiteralType"] +- !private ["Sb", "_getBuiltinLogicValue"] +- !private ["Ps25BooleanLiteralConvertible", "_getBuiltinLogicValue"] +- !private ["Ps11BooleanType", "_getBuiltinLogicValue"] +- ["Ps11CVarArgType", "Distance"] +- ["Ps11CVarArgType", "IntegerLiteralType"] +- !private ["Ps11CVarArgType", "init"] +- ["Ps14CollectionType", "Generator"] +- ["Ps14CollectionType", "Index"] +- ["Ps14CollectionType", "SubSequence"] +- ["Ps14CollectionType", "_Element"] +- !private ["Ps14CollectionType", "append"] +- !private ["Ps14CollectionType", "count"] +- ["Ps14CollectionType", "init"] +- !private ["Ps14CollectionType", "removeFirst"] +- !private ["Ps14CollectionType", "subscript"] +- ["Ps10Comparable", "Distance"] +- ["Ps10Comparable", "IntegerLiteralType"] +- !private ["Ps10Comparable", "init"] +- ["Ps28CustomDebugStringConvertible", "Generator"] +- ["Ps28CustomDebugStringConvertible", "Index"] +- ["Ps28CustomDebugStringConvertible", "Some"] +- ["Ps28CustomDebugStringConvertible", "SubSequence"] +- ["Ps28CustomDebugStringConvertible", "_Element"] +- !private ["Ps28CustomDebugStringConvertible", "append"] +- !private ["Ps28CustomDebugStringConvertible", "count"] +- ["Ps28CustomDebugStringConvertible", "init"] +- !private ["Ps28CustomDebugStringConvertible", "removeFirst"] +- !private ["Ps28CustomDebugStringConvertible", "subscript"] +- ["Ps23CustomStringConvertible", "Distance"] +- ["Ps23CustomStringConvertible", "Generator"] +- ["Ps23CustomStringConvertible", "Index"] +- ["Ps23CustomStringConvertible", "IntegerLiteralType"] +- ["Ps23CustomStringConvertible", "SubSequence"] +- ["Ps23CustomStringConvertible", "_Element"] +- !private ["Ps23CustomStringConvertible", "_getBuiltinLogicValue"] +- !private ["Ps23CustomStringConvertible", "append"] +- !private ["Ps23CustomStringConvertible", "count"] +- ["Ps23CustomStringConvertible", "init"] +- !private ["Ps23CustomStringConvertible", "removeFirst"] +- !private ["Ps23CustomStringConvertible", "subscript"] +- !private ["Sd", "init"] +- ["Ps9Equatable", "Distance"] +- ["Ps9Equatable", "IntegerLiteralType"] +- !private ["Ps9Equatable", "_getBuiltinLogicValue"] +- !private ["Ps9Equatable", "init"] +- !private ["Ps23FloatLiteralConvertible", "init"] +- !private ["Ps17FloatingPointType", "init"] +- ["Ps16ForwardIndexType", "Distance"] +- ["Ps16ForwardIndexType", "IntegerLiteralType"] +- ["Ps13GeneratorType", "Element"] +- ["Ps8Hashable", "Distance"] +- ["Ps8Hashable", "IntegerLiteralType"] +- !private ["Ps8Hashable", "_getBuiltinLogicValue"] +- !private ["Ps8Hashable", "init"] +- ["Ps9Indexable", "Generator"] +- ["Ps9Indexable", "Index"] +- ["Ps9Indexable", "SubSequence"] +- ["Ps9Indexable", "_Element"] +- !private ["Ps9Indexable", "append"] +- !private ["Ps9Indexable", "count"] +- ["Ps9Indexable", "init"] +- !private ["Ps9Indexable", "removeFirst"] +- !private ["Ps9Indexable", "subscript"] +- ["Vs17IndexingGenerator", "Element"] +- ["Si", "Distance"] +- ["Si", "IntegerLiteralType"] +- ["Ps21IntegerArithmeticType", "Distance"] +- ["Ps21IntegerArithmeticType", "IntegerLiteralType"] +- ["Ps25IntegerLiteralConvertible", "Distance"] +- ["Ps25IntegerLiteralConvertible", "IntegerLiteralType"] +- !private ["Ps25IntegerLiteralConvertible", "init"] +- ["Ps11IntegerType", "Distance"] +- ["Ps11IntegerType", "IntegerLiteralType"] +- ["Ps14MirrorPathType", "Distance"] +- ["Ps14MirrorPathType", "IntegerLiteralType"] +- ["Ps21MutableCollectionType", "Generator"] +- ["Ps21MutableCollectionType", "Index"] +- ["Ps21MutableCollectionType", "SubSequence"] +- ["Ps21MutableCollectionType", "_Element"] +- !private ["Ps21MutableCollectionType", "append"] +- !private ["Ps21MutableCollectionType", "count"] +- ["Ps21MutableCollectionType", "init"] +- !private ["Ps21MutableCollectionType", "removeFirst"] +- !private ["Ps21MutableCollectionType", "subscript"] +- ["Ps16MutableIndexable", "Generator"] +- ["Ps16MutableIndexable", "Index"] +- ["Ps16MutableIndexable", "SubSequence"] +- ["Ps16MutableIndexable", "_Element"] +- !private ["Ps16MutableIndexable", "append"] +- !private ["Ps16MutableIndexable", "count"] +- ["Ps16MutableIndexable", "init"] +- !private ["Ps16MutableIndexable", "removeFirst"] +- !private ["Ps16MutableIndexable", "subscript"] +- ["Ps16MutableSliceable", "Generator"] +- ["Ps16MutableSliceable", "Index"] +- ["Ps16MutableSliceable", "SubSequence"] +- ["Ps16MutableSliceable", "_Element"] +- !private ["Ps16MutableSliceable", "append"] +- !private ["Ps16MutableSliceable", "count"] +- ["Ps16MutableSliceable", "init"] +- !private ["Ps16MutableSliceable", "removeFirst"] +- !private ["Ps16MutableSliceable", "subscript"] +- ["Ps21NilLiteralConvertible", "Some"] +- ["Sq", "Some"] +- ["V38package_name_here_and_keep_quote_marks5Queue", "Bool"] +- !private ["V38package_name_here_and_keep_quote_marks5Queue", "Double"] +- ["V38package_name_here_and_keep_quote_marks5Queue", "Int"] +- ["V38package_name_here_and_keep_quote_marks5Queue", "T"] +- !private ["V38package_name_here_and_keep_quote_marks5Queue", "array"] +- ["V38package_name_here_and_keep_quote_marks5Queue", "count"] +- ["V38package_name_here_and_keep_quote_marks5Queue", "dequeue"] +- ["V38package_name_here_and_keep_quote_marks5Queue", "enqueue"] +- !private ["V38package_name_here_and_keep_quote_marks5Queue", "head"] +- ["V38package_name_here_and_keep_quote_marks5Queue", "init"] +- ["V38package_name_here_and_keep_quote_marks5Queue", "isEmpty"] +- ["V38package_name_here_and_keep_quote_marks5Queue", "peek"] +- ["Ps21RandomAccessIndexType", "Distance"] +- ["Ps21RandomAccessIndexType", "IntegerLiteralType"] +- ["Ps30RangeReplaceableCollectionType", "Generator"] +- ["Ps30RangeReplaceableCollectionType", "Index"] +- ["Ps30RangeReplaceableCollectionType", "SubSequence"] +- ["Ps30RangeReplaceableCollectionType", "_Element"] +- !private ["Ps30RangeReplaceableCollectionType", "append"] +- !private ["Ps30RangeReplaceableCollectionType", "count"] +- ["Ps30RangeReplaceableCollectionType", "init"] +- !private ["Ps30RangeReplaceableCollectionType", "removeFirst"] +- !private ["Ps30RangeReplaceableCollectionType", "subscript"] +- ["Ps12SequenceType", "Element"] +- ["Ps12SequenceType", "Generator"] +- ["Ps12SequenceType", "Index"] +- ["Ps12SequenceType", "SubSequence"] +- ["Ps12SequenceType", "_Element"] +- !private ["Ps12SequenceType", "append"] +- !private ["Ps12SequenceType", "count"] +- ["Ps12SequenceType", "init"] +- !private ["Ps12SequenceType", "removeFirst"] +- !private ["Ps12SequenceType", "subscript"] +- ["Ps17SignedIntegerType", "Distance"] +- ["Ps17SignedIntegerType", "IntegerLiteralType"] +- ["Ps16SignedNumberType", "Distance"] +- ["Ps16SignedNumberType", "IntegerLiteralType"] +- !private ["Ps16SignedNumberType", "init"] +- !private ["Vs5Slice", "Generator"] +- !private ["Vs5Slice", "Index"] +- !private ["Vs5Slice", "SubSequence"] +- !private ["Vs5Slice", "_Element"] +- ["Ps10Strideable", "Distance"] +- ["Ps10Strideable", "IntegerLiteralType"] +- !private ["Ps10Strideable", "init"] +- ["Ps10_ArrayType", "Generator"] +- ["Ps10_ArrayType", "Index"] +- ["Ps10_ArrayType", "SubSequence"] +- ["Ps10_ArrayType", "_Element"] +- !private ["Ps10_ArrayType", "append"] +- !private ["Ps10_ArrayType", "count"] +- ["Ps10_ArrayType", "init"] +- !private ["Ps10_ArrayType", "removeFirst"] +- !private ["Ps10_ArrayType", "subscript"] +- !private ["Ps33_BuiltinBooleanLiteralConvertible", "_getBuiltinLogicValue"] +- !private ["Ps31_BuiltinFloatLiteralConvertible", "init"] +- ["Ps33_BuiltinIntegerLiteralConvertible", "Distance"] +- ["Ps33_BuiltinIntegerLiteralConvertible", "IntegerLiteralType"] +- !private ["Ps33_BuiltinIntegerLiteralConvertible", "init"] +- !private ["Ps19_CVarArgAlignedType", "init"] +- !private ["Ps22_CVarArgPassedAsDouble", "init"] +- ["Ps24_DestructorSafeContainer", "Generator"] +- ["Ps24_DestructorSafeContainer", "Index"] +- ["Ps24_DestructorSafeContainer", "SubSequence"] +- ["Ps24_DestructorSafeContainer", "_Element"] +- !private ["Ps24_DestructorSafeContainer", "append"] +- !private ["Ps24_DestructorSafeContainer", "count"] +- ["Ps24_DestructorSafeContainer", "init"] +- !private ["Ps24_DestructorSafeContainer", "removeFirst"] +- !private ["Ps24_DestructorSafeContainer", "subscript"] +- ["Ps14_Incrementable", "Distance"] +- ["Ps14_Incrementable", "IntegerLiteralType"] +- ["Ps22_IntegerArithmeticType", "Distance"] +- ["Ps22_IntegerArithmeticType", "IntegerLiteralType"] +- ["Ps12_IntegerType", "Distance"] +- ["Ps12_IntegerType", "IntegerLiteralType"] +- ["Ps22_RandomAccessAmbiguity", "Distance"] +- ["Ps22_RandomAccessAmbiguity", "IntegerLiteralType"] +- ["Ps12_Reflectable", "Distance"] +- ["Ps12_Reflectable", "Generator"] +- ["Ps12_Reflectable", "Index"] +- ["Ps12_Reflectable", "IntegerLiteralType"] +- ["Ps12_Reflectable", "Some"] +- ["Ps12_Reflectable", "SubSequence"] +- ["Ps12_Reflectable", "_Element"] +- !private ["Ps12_Reflectable", "_getBuiltinLogicValue"] +- !private ["Ps12_Reflectable", "append"] +- !private ["Ps12_Reflectable", "count"] +- ["Ps12_Reflectable", "init"] +- !private ["Ps12_Reflectable", "removeFirst"] +- !private ["Ps12_Reflectable", "subscript"] +- ["Ps18_SignedIntegerType", "Distance"] +- ["Ps18_SignedIntegerType", "IntegerLiteralType"] +depends-nominal: +- !private "Ps16AbsoluteValuable" +- "Sa" +- "Ps23ArrayLiteralConvertible" +- "Vs10ArraySlice" +- "Ps22BidirectionalIndexType" +- "Ps21BitwiseOperationsType" +- !private "Sb" +- !private "Ps25BooleanLiteralConvertible" +- !private "Ps11BooleanType" +- "Ps11CVarArgType" +- "Ps14CollectionType" +- "Ps10Comparable" +- "Ps28CustomDebugStringConvertible" +- "Ps23CustomStringConvertible" +- !private "Sd" +- "Ps9Equatable" +- !private "Ps23FloatLiteralConvertible" +- !private "Ps17FloatingPointType" +- "Ps16ForwardIndexType" +- "Ps13GeneratorType" +- "Ps8Hashable" +- "Ps9Indexable" +- "Vs17IndexingGenerator" +- "Si" +- "Ps21IntegerArithmeticType" +- "Ps25IntegerLiteralConvertible" +- "Ps11IntegerType" +- "Ps14MirrorPathType" +- "Ps21MutableCollectionType" +- "Ps16MutableIndexable" +- "Ps16MutableSliceable" +- "Ps21NilLiteralConvertible" +- "Sq" +- "V38package_name_here_and_keep_quote_marks5Queue" +- "Ps21RandomAccessIndexType" +- "Ps30RangeReplaceableCollectionType" +- "Ps12SequenceType" +- "Ps17SignedIntegerType" +- "Ps16SignedNumberType" +- !private "Vs5Slice" +- "Ps10Strideable" +- "Ps10_ArrayType" +- !private "Ps33_BuiltinBooleanLiteralConvertible" +- !private "Ps31_BuiltinFloatLiteralConvertible" +- "Ps33_BuiltinIntegerLiteralConvertible" +- !private "Ps19_CVarArgAlignedType" +- !private "Ps22_CVarArgPassedAsDouble" +- "Ps24_DestructorSafeContainer" +- "Ps14_Incrementable" +- "Ps22_IntegerArithmeticType" +- "Ps12_IntegerType" +- "Ps22_RandomAccessAmbiguity" +- "Ps12_Reflectable" +- "Ps18_SignedIntegerType" +depends-dynamic-lookup: +depends-external: +- "/home/christian/swiftv2/usr/lib/swift/linux/x86_64/Swift.swiftmodule" +- "/home/christian/swiftv2/usr/lib/swift/shims/UnicodeShims.h" +- "/home/christian/swiftv2/usr/lib/swift/shims/SwiftStdint.h" +- "/home/christian/swiftv2/usr/lib/swift/shims/SwiftStddef.h" +- "/home/christian/swiftv2/usr/lib/swift/shims/LibcShims.h" +- "/home/christian/swiftv2/usr/lib/swift/shims/RuntimeStubs.h" +- "/home/christian/swiftv2/usr/lib/swift/shims/RuntimeShims.h" +- "/home/christian/swiftv2/usr/lib/swift/shims/RefCount.h" +- "/home/christian/swiftv2/usr/lib/swift/shims/HeapObject.h" +- "/home/christian/swiftv2/usr/lib/swift/shims/GlobalObjects.h" +- "/home/christian/swiftv2/usr/lib/swift/shims/FoundationShims.h" +- "/home/christian/swiftv2/usr/lib/swift/shims/CoreFoundationShims.h" +- "/home/christian/swiftv2/usr/lib/swift/shims/module.map" +interface-hash: "b268b101cc2bc2706939fa25905dab4d" diff --git a/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/package_name_here_and_keep_quote_marks/master.swiftdeps b/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/package_name_here_and_keep_quote_marks/master.swiftdeps new file mode 100644 index 000000000..d0814f65b --- /dev/null +++ b/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/package_name_here_and_keep_quote_marks/master.swiftdeps @@ -0,0 +1,6 @@ +version: "Swift version 2.2-dev (LLVM 3ebdbb2c7e, Clang f66c5bb67b, Swift 0ddf238ad7)" +options: "4b4cb3e8efe303c8a39bf9409934d3d3" +build_time: [515615518, 682291000] +inputs: + "/home/christian/Desktop/swift-algorithm-club/Trie/sources/trie.swift": !dirty [515615193, 0] + "/home/christian/Desktop/swift-algorithm-club/Trie/sources/Queue.swift": !dirty [512710161, 0] diff --git a/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/package_name_here_and_keep_quote_marks/output-file-map.json b/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/package_name_here_and_keep_quote_marks/output-file-map.json new file mode 100644 index 000000000..5b65a86c0 --- /dev/null +++ b/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/package_name_here_and_keep_quote_marks/output-file-map.json @@ -0,0 +1,17 @@ +{ + "": { + "swift-dependencies": "/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/package_name_here_and_keep_quote_marks/master.swiftdeps" + }, + "/home/christian/Desktop/swift-algorithm-club/Trie/sources/trie.swift": { + "dependencies": "/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/package_name_here_and_keep_quote_marks/trie.d", + "object": "/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/sources/trie.swift.o", + "swiftmodule": "/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/package_name_here_and_keep_quote_marks/trie~partial.swiftmodule", + "swift-dependencies": "/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/package_name_here_and_keep_quote_marks/trie.swiftdeps" + }, + "/home/christian/Desktop/swift-algorithm-club/Trie/sources/Queue.swift": { + "dependencies": "/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/package_name_here_and_keep_quote_marks/Queue.d", + "object": "/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/sources/Queue.swift.o", + "swiftmodule": "/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/package_name_here_and_keep_quote_marks/Queue~partial.swiftmodule", + "swift-dependencies": "/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/package_name_here_and_keep_quote_marks/Queue.swiftdeps" + } +} diff --git a/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/package_name_here_and_keep_quote_marks/trie.d b/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/package_name_here_and_keep_quote_marks/trie.d new file mode 100644 index 000000000..eefb6fd8d --- /dev/null +++ b/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/package_name_here_and_keep_quote_marks/trie.d @@ -0,0 +1,3 @@ +/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/sources/trie.swift.o : /home/christian/Desktop/swift-algorithm-club/Trie/sources/trie.swift /home/christian/Desktop/swift-algorithm-club/Trie/sources/Queue.swift /home/christian/swiftv2/usr/lib/swift/linux/x86_64/Swift.swiftmodule /home/christian/swiftv2/usr/lib/swift/shims/UnicodeShims.h /home/christian/swiftv2/usr/lib/swift/shims/SwiftStdint.h /home/christian/swiftv2/usr/lib/swift/shims/SwiftStddef.h /home/christian/swiftv2/usr/lib/swift/shims/LibcShims.h /home/christian/swiftv2/usr/lib/swift/shims/RuntimeStubs.h /home/christian/swiftv2/usr/lib/swift/shims/RuntimeShims.h /home/christian/swiftv2/usr/lib/swift/shims/RefCount.h /home/christian/swiftv2/usr/lib/swift/shims/HeapObject.h /home/christian/swiftv2/usr/lib/swift/shims/GlobalObjects.h /home/christian/swiftv2/usr/lib/swift/shims/FoundationShims.h /home/christian/swiftv2/usr/lib/swift/shims/CoreFoundationShims.h /home/christian/swiftv2/usr/lib/swift/shims/module.map +/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/package_name_here_and_keep_quote_marks/trie~partial.swiftmodule : /home/christian/Desktop/swift-algorithm-club/Trie/sources/trie.swift /home/christian/Desktop/swift-algorithm-club/Trie/sources/Queue.swift /home/christian/swiftv2/usr/lib/swift/linux/x86_64/Swift.swiftmodule /home/christian/swiftv2/usr/lib/swift/shims/UnicodeShims.h /home/christian/swiftv2/usr/lib/swift/shims/SwiftStdint.h /home/christian/swiftv2/usr/lib/swift/shims/SwiftStddef.h /home/christian/swiftv2/usr/lib/swift/shims/LibcShims.h /home/christian/swiftv2/usr/lib/swift/shims/RuntimeStubs.h /home/christian/swiftv2/usr/lib/swift/shims/RuntimeShims.h /home/christian/swiftv2/usr/lib/swift/shims/RefCount.h /home/christian/swiftv2/usr/lib/swift/shims/HeapObject.h /home/christian/swiftv2/usr/lib/swift/shims/GlobalObjects.h /home/christian/swiftv2/usr/lib/swift/shims/FoundationShims.h /home/christian/swiftv2/usr/lib/swift/shims/CoreFoundationShims.h /home/christian/swiftv2/usr/lib/swift/shims/module.map +/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/package_name_here_and_keep_quote_marks/trie~partial.swiftdoc : /home/christian/Desktop/swift-algorithm-club/Trie/sources/trie.swift /home/christian/Desktop/swift-algorithm-club/Trie/sources/Queue.swift /home/christian/swiftv2/usr/lib/swift/linux/x86_64/Swift.swiftmodule /home/christian/swiftv2/usr/lib/swift/shims/UnicodeShims.h /home/christian/swiftv2/usr/lib/swift/shims/SwiftStdint.h /home/christian/swiftv2/usr/lib/swift/shims/SwiftStddef.h /home/christian/swiftv2/usr/lib/swift/shims/LibcShims.h /home/christian/swiftv2/usr/lib/swift/shims/RuntimeStubs.h /home/christian/swiftv2/usr/lib/swift/shims/RuntimeShims.h /home/christian/swiftv2/usr/lib/swift/shims/RefCount.h /home/christian/swiftv2/usr/lib/swift/shims/HeapObject.h /home/christian/swiftv2/usr/lib/swift/shims/GlobalObjects.h /home/christian/swiftv2/usr/lib/swift/shims/FoundationShims.h /home/christian/swiftv2/usr/lib/swift/shims/CoreFoundationShims.h /home/christian/swiftv2/usr/lib/swift/shims/module.map diff --git a/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/package_name_here_and_keep_quote_marks/trie.swiftdeps b/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/package_name_here_and_keep_quote_marks/trie.swiftdeps new file mode 100644 index 000000000..39eba9f00 --- /dev/null +++ b/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/package_name_here_and_keep_quote_marks/trie.swiftdeps @@ -0,0 +1,513 @@ +### Swift dependencies file v0 ### +provides-top-level: +- "Node" +- "Trie" +- "T" +- "U" +- "V" +provides-nominal: +- "C38package_name_here_and_keep_quote_marks4Node" +- "C38package_name_here_and_keep_quote_marks4Trie" +provides-member: +- ["C38package_name_here_and_keep_quote_marks4Node", ""] +- ["C38package_name_here_and_keep_quote_marks4Trie", ""] +depends-top-level: +- "Trie" +- "print" +- "Bool" +- !private "-=" +- "StringLiteralType" +- !private ">" +- !private "&&" +- !private "Queue" +- "U" +- "Int" +- "V" +- !private "BooleanLiteralType" +- "Node" +- "FloatLiteralType" +- "Set" +- "Array" +- !private "+" +- !private "-" +- !private "UnicodeScalarType" +- "IntegerLiteralType" +- !private "==" +- "Void" +- !private "+=" +- "T" +- !private "!" +- "String" +depends-member: +- !private ["Vs12AnyGenerator", "Element"] +- !private ["Ps9AnyObject", "Array"] +- !private ["Ps9AnyObject", "Node"] +- !private ["Ps9AnyObject", "Queue"] +- !private ["Ps9AnyObject", "Set"] +- !private ["Ps9AnyObject", "String"] +- !private ["Ps9AnyObject", "Trie"] +- !private ["Ps9AnyObject", "char"] +- !private ["Ps9AnyObject", "character"] +- !private ["Ps9AnyObject", "children"] +- !private ["Ps9AnyObject", "contains"] +- !private ["Ps9AnyObject", "find"] +- !private ["Ps9AnyObject", "getChildAt"] +- !private ["Ps9AnyObject", "getChildren"] +- !private ["Ps9AnyObject", "getParent"] +- ["Ps9AnyObject", "getWords"] +- ["Ps9AnyObject", "init"] +- ["Ps9AnyObject", "insert"] +- !private ["Ps9AnyObject", "isAWord"] +- !private ["Ps9AnyObject", "isNotWord"] +- !private ["Ps9AnyObject", "isRoot"] +- !private ["Ps9AnyObject", "isValidWord"] +- !private ["Ps9AnyObject", "isWord"] +- ["Ps9AnyObject", "merge"] +- !private ["Ps9AnyObject", "numChildren"] +- !private ["Ps9AnyObject", "parent"] +- !private ["Ps9AnyObject", "print"] +- !private ["Ps9AnyObject", "printNode"] +- !private ["Ps9AnyObject", "remove"] +- ["Ps9AnyObject", "removeAll"] +- !private ["Ps9AnyObject", "root"] +- !private ["Ps9AnyObject", "setParent"] +- !private ["Ps9AnyObject", "update"] +- !private ["Ps9AnyObject", "wordCount"] +- !private ["Ps9AnyObject", "wordList"] +- ["Ps9AnyObject", ""] +- !private ["Vs11AnySequence", "Generator"] +- !private ["Vs11AnySequence", "deinit"] +- ["Sa", "Element"] +- ["Sa", "Generator"] +- ["Sa", "Index"] +- !private ["Sa", "SubSequence"] +- ["Sa", "_Element"] +- !private ["Sa", "append"] +- !private ["Sa", "deinit"] +- !private ["Sa", "init"] +- !private ["Sa", "removeAtIndex"] +- !private ["Sa", "subscript"] +- ["Ps23ArrayLiteralConvertible", "Element"] +- ["Ps23ArrayLiteralConvertible", "Generator"] +- ["Ps23ArrayLiteralConvertible", "Index"] +- !private ["Ps23ArrayLiteralConvertible", "SubSequence"] +- ["Ps23ArrayLiteralConvertible", "_Element"] +- !private ["Ps23ArrayLiteralConvertible", "append"] +- ["Ps23ArrayLiteralConvertible", "init"] +- !private ["Ps23ArrayLiteralConvertible", "removeAtIndex"] +- !private ["Ps23ArrayLiteralConvertible", "subscript"] +- !private ["Vs10ArraySlice", "Generator"] +- !private ["Vs10ArraySlice", "Index"] +- ["Ps22BidirectionalIndexType", "Distance"] +- ["Ps22BidirectionalIndexType", "IntegerLiteralType"] +- ["Ps21BitwiseOperationsType", "Distance"] +- ["Ps21BitwiseOperationsType", "IntegerLiteralType"] +- !private ["Sb", "_getBuiltinLogicValue"] +- !private ["Ps25BooleanLiteralConvertible", "_getBuiltinLogicValue"] +- !private ["Ps11BooleanType", "_getBuiltinLogicValue"] +- ["Ps11CVarArgType", "Distance"] +- ["Ps11CVarArgType", "IntegerLiteralType"] +- !private ["VSS13CharacterView", "Generator"] +- !private ["VSS13CharacterView", "Index"] +- !private ["VSS13CharacterView", "SubSequence"] +- !private ["VSS13CharacterView", "_Element"] +- !private ["VSS13CharacterView", "count"] +- !private ["VSS13CharacterView", "deinit"] +- !private ["VSS13CharacterView", "suffix"] +- ["Ps14CollectionType", "Element"] +- ["Ps14CollectionType", "Generator"] +- ["Ps14CollectionType", "Index"] +- !private ["Ps14CollectionType", "SubSequence"] +- ["Ps14CollectionType", "_Element"] +- !private ["Ps14CollectionType", "append"] +- !private ["Ps14CollectionType", "count"] +- ["Ps14CollectionType", "init"] +- !private ["Ps14CollectionType", "removeAtIndex"] +- !private ["Ps14CollectionType", "subscript"] +- !private ["Ps14CollectionType", "suffix"] +- ["Ps10Comparable", "Distance"] +- ["Ps10Comparable", "IntegerLiteralType"] +- !private ["Ps10Comparable", "_DisabledRangeIndex"] +- !private ["Ps10Comparable", "characters"] +- !private ["Ps10Comparable", "init"] +- !private ["Ps10Comparable", "lowercaseString"] +- ["Ps28CustomDebugStringConvertible", "Element"] +- ["Ps28CustomDebugStringConvertible", "Generator"] +- ["Ps28CustomDebugStringConvertible", "Index"] +- ["Ps28CustomDebugStringConvertible", "Some"] +- !private ["Ps28CustomDebugStringConvertible", "SubSequence"] +- ["Ps28CustomDebugStringConvertible", "_Element"] +- !private ["Ps28CustomDebugStringConvertible", "append"] +- !private ["Ps28CustomDebugStringConvertible", "characters"] +- !private ["Ps28CustomDebugStringConvertible", "count"] +- ["Ps28CustomDebugStringConvertible", "init"] +- !private ["Ps28CustomDebugStringConvertible", "lowercaseString"] +- !private ["Ps28CustomDebugStringConvertible", "removeAtIndex"] +- !private ["Ps28CustomDebugStringConvertible", "subscript"] +- ["Ps23CustomStringConvertible", "Distance"] +- ["Ps23CustomStringConvertible", "Element"] +- ["Ps23CustomStringConvertible", "Generator"] +- ["Ps23CustomStringConvertible", "Index"] +- ["Ps23CustomStringConvertible", "IntegerLiteralType"] +- !private ["Ps23CustomStringConvertible", "SubSequence"] +- ["Ps23CustomStringConvertible", "_Element"] +- !private ["Ps23CustomStringConvertible", "_getBuiltinLogicValue"] +- !private ["Ps23CustomStringConvertible", "append"] +- !private ["Ps23CustomStringConvertible", "count"] +- ["Ps23CustomStringConvertible", "init"] +- !private ["Ps23CustomStringConvertible", "removeAtIndex"] +- !private ["Ps23CustomStringConvertible", "subscript"] +- !private ["Vs10Dictionary", "Generator"] +- !private ["Vs10Dictionary", "Index"] +- !private ["Vs10Dictionary", "SubSequence"] +- !private ["Vs10Dictionary", "_Element"] +- !private ["Vs10Dictionary", "count"] +- !private ["Vs10Dictionary", "deinit"] +- !private ["Vs10Dictionary", "init"] +- !private ["Vs10Dictionary", "subscript"] +- !private ["Vs19DictionaryGenerator", "Element"] +- !private ["Vs15DictionaryIndex", "Distance"] +- !private ["Vs15DictionaryIndex", "_DisabledRangeIndex"] +- !private ["Ps28DictionaryLiteralConvertible", "Generator"] +- !private ["Ps28DictionaryLiteralConvertible", "Index"] +- !private ["Ps28DictionaryLiteralConvertible", "SubSequence"] +- !private ["Ps28DictionaryLiteralConvertible", "_Element"] +- !private ["Ps28DictionaryLiteralConvertible", "count"] +- !private ["Ps28DictionaryLiteralConvertible", "init"] +- !private ["Ps28DictionaryLiteralConvertible", "subscript"] +- ["Ps9Equatable", "Distance"] +- !private ["Ps9Equatable", "Generator"] +- ["Ps9Equatable", "IntegerLiteralType"] +- !private ["Ps9Equatable", "_DisabledRangeIndex"] +- !private ["Ps9Equatable", "_getBuiltinLogicValue"] +- !private ["Ps9Equatable", "characters"] +- ["Ps9Equatable", "init"] +- !private ["Ps9Equatable", "lowercaseString"] +- !private ["Ps41ExtendedGraphemeClusterLiteralConvertible", "characters"] +- !private ["Ps41ExtendedGraphemeClusterLiteralConvertible", "init"] +- !private ["Ps41ExtendedGraphemeClusterLiteralConvertible", "lowercaseString"] +- ["Ps16ForwardIndexType", "Distance"] +- ["Ps16ForwardIndexType", "IntegerLiteralType"] +- !private ["Ps16ForwardIndexType", "_DisabledRangeIndex"] +- ["Ps13GeneratorType", "Element"] +- ["Ps8Hashable", "Distance"] +- !private ["Ps8Hashable", "Generator"] +- ["Ps8Hashable", "IntegerLiteralType"] +- !private ["Ps8Hashable", "_getBuiltinLogicValue"] +- !private ["Ps8Hashable", "characters"] +- ["Ps8Hashable", "init"] +- !private ["Ps8Hashable", "lowercaseString"] +- !private ["VVSS13CharacterView5Index", "Distance"] +- ["Ps9Indexable", "Element"] +- ["Ps9Indexable", "Generator"] +- ["Ps9Indexable", "Index"] +- !private ["Ps9Indexable", "SubSequence"] +- ["Ps9Indexable", "_Element"] +- !private ["Ps9Indexable", "append"] +- !private ["Ps9Indexable", "count"] +- ["Ps9Indexable", "init"] +- !private ["Ps9Indexable", "removeAtIndex"] +- !private ["Ps9Indexable", "subscript"] +- !private ["Ps9Indexable", "suffix"] +- ["Vs17IndexingGenerator", "Element"] +- ["Si", "Distance"] +- ["Si", "IntegerLiteralType"] +- ["Si", "deinit"] +- ["Ps21IntegerArithmeticType", "Distance"] +- ["Ps21IntegerArithmeticType", "IntegerLiteralType"] +- ["Ps25IntegerLiteralConvertible", "Distance"] +- ["Ps25IntegerLiteralConvertible", "IntegerLiteralType"] +- ["Ps11IntegerType", "Distance"] +- ["Ps11IntegerType", "IntegerLiteralType"] +- ["Ps14MirrorPathType", "Distance"] +- ["Ps14MirrorPathType", "IntegerLiteralType"] +- !private ["Ps14MirrorPathType", "characters"] +- !private ["Ps14MirrorPathType", "init"] +- !private ["Ps14MirrorPathType", "lowercaseString"] +- ["Ps21MutableCollectionType", "Element"] +- ["Ps21MutableCollectionType", "Generator"] +- ["Ps21MutableCollectionType", "Index"] +- !private ["Ps21MutableCollectionType", "SubSequence"] +- ["Ps21MutableCollectionType", "_Element"] +- !private ["Ps21MutableCollectionType", "append"] +- !private ["Ps21MutableCollectionType", "init"] +- !private ["Ps21MutableCollectionType", "removeAtIndex"] +- !private ["Ps21MutableCollectionType", "subscript"] +- ["Ps16MutableIndexable", "Element"] +- ["Ps16MutableIndexable", "Generator"] +- ["Ps16MutableIndexable", "Index"] +- !private ["Ps16MutableIndexable", "SubSequence"] +- ["Ps16MutableIndexable", "_Element"] +- !private ["Ps16MutableIndexable", "append"] +- !private ["Ps16MutableIndexable", "init"] +- !private ["Ps16MutableIndexable", "removeAtIndex"] +- !private ["Ps16MutableIndexable", "subscript"] +- ["Ps16MutableSliceable", "Element"] +- ["Ps16MutableSliceable", "Generator"] +- ["Ps16MutableSliceable", "Index"] +- !private ["Ps16MutableSliceable", "SubSequence"] +- ["Ps16MutableSliceable", "_Element"] +- !private ["Ps16MutableSliceable", "append"] +- !private ["Ps16MutableSliceable", "init"] +- !private ["Ps16MutableSliceable", "removeAtIndex"] +- !private ["Ps16MutableSliceable", "subscript"] +- ["Ps21NilLiteralConvertible", "Some"] +- ["C38package_name_here_and_keep_quote_marks4Node", "Bool"] +- ["C38package_name_here_and_keep_quote_marks4Node", "Int"] +- ["C38package_name_here_and_keep_quote_marks4Node", "Node"] +- ["C38package_name_here_and_keep_quote_marks4Node", "String"] +- ["C38package_name_here_and_keep_quote_marks4Node", "Void"] +- ["C38package_name_here_and_keep_quote_marks4Node", "char"] +- !private ["C38package_name_here_and_keep_quote_marks4Node", "character"] +- !private ["C38package_name_here_and_keep_quote_marks4Node", "children"] +- ["C38package_name_here_and_keep_quote_marks4Node", "deinit"] +- ["C38package_name_here_and_keep_quote_marks4Node", "getChildAt"] +- ["C38package_name_here_and_keep_quote_marks4Node", "getChildren"] +- ["C38package_name_here_and_keep_quote_marks4Node", "getParent"] +- ["C38package_name_here_and_keep_quote_marks4Node", "init"] +- !private ["C38package_name_here_and_keep_quote_marks4Node", "isAWord"] +- ["C38package_name_here_and_keep_quote_marks4Node", "isLeaf"] +- ["C38package_name_here_and_keep_quote_marks4Node", "isNotWord"] +- ["C38package_name_here_and_keep_quote_marks4Node", "isRoot"] +- ["C38package_name_here_and_keep_quote_marks4Node", "isValidWord"] +- ["C38package_name_here_and_keep_quote_marks4Node", "isWord"] +- ["C38package_name_here_and_keep_quote_marks4Node", "numChildren"] +- !private ["C38package_name_here_and_keep_quote_marks4Node", "parent"] +- !private ["C38package_name_here_and_keep_quote_marks4Node", "print"] +- ["C38package_name_here_and_keep_quote_marks4Node", "printNode"] +- ["C38package_name_here_and_keep_quote_marks4Node", "setParent"] +- ["C38package_name_here_and_keep_quote_marks4Node", "update"] +- ["Sq", "Some"] +- !private ["Sq", "deinit"] +- !private ["Ps16OutputStreamType", "characters"] +- !private ["Ps16OutputStreamType", "init"] +- !private ["Ps16OutputStreamType", "lowercaseString"] +- !private ["V38package_name_here_and_keep_quote_marks5Queue", "init"] +- ["Ps21RandomAccessIndexType", "Distance"] +- ["Ps21RandomAccessIndexType", "IntegerLiteralType"] +- ["Ps30RangeReplaceableCollectionType", "Element"] +- ["Ps30RangeReplaceableCollectionType", "Generator"] +- ["Ps30RangeReplaceableCollectionType", "Index"] +- !private ["Ps30RangeReplaceableCollectionType", "SubSequence"] +- ["Ps30RangeReplaceableCollectionType", "_Element"] +- !private ["Ps30RangeReplaceableCollectionType", "append"] +- !private ["Ps30RangeReplaceableCollectionType", "count"] +- !private ["Ps30RangeReplaceableCollectionType", "init"] +- !private ["Ps30RangeReplaceableCollectionType", "removeAtIndex"] +- !private ["Ps30RangeReplaceableCollectionType", "subscript"] +- !private ["Ps30RangeReplaceableCollectionType", "suffix"] +- ["Ps12SequenceType", "Element"] +- ["Ps12SequenceType", "Generator"] +- ["Ps12SequenceType", "Index"] +- !private ["Ps12SequenceType", "SubSequence"] +- ["Ps12SequenceType", "_Element"] +- !private ["Ps12SequenceType", "append"] +- !private ["Ps12SequenceType", "count"] +- ["Ps12SequenceType", "init"] +- !private ["Ps12SequenceType", "removeAtIndex"] +- !private ["Ps12SequenceType", "subscript"] +- !private ["Ps12SequenceType", "suffix"] +- !private ["Vs3Set", "Generator"] +- ["Vs3Set", "init"] +- !private ["Vs12SetGenerator", "Element"] +- ["Ps17SignedIntegerType", "Distance"] +- ["Ps17SignedIntegerType", "IntegerLiteralType"] +- ["Ps16SignedNumberType", "Distance"] +- ["Ps16SignedNumberType", "IntegerLiteralType"] +- !private ["Vs5Slice", "Generator"] +- !private ["Vs5Slice", "Index"] +- !private ["Vs5Slice", "SubSequence"] +- !private ["Vs5Slice", "_Element"] +- !private ["Vs5Slice", "deinit"] +- !private ["Ps10Streamable", "characters"] +- !private ["Ps10Streamable", "init"] +- !private ["Ps10Streamable", "lowercaseString"] +- ["Ps10Strideable", "Distance"] +- ["Ps10Strideable", "IntegerLiteralType"] +- !private ["SS", "characters"] +- !private ["SS", "init"] +- !private ["SS", "lowercaseString"] +- !private ["Ps30StringInterpolationConvertible", "characters"] +- !private ["Ps30StringInterpolationConvertible", "init"] +- !private ["Ps30StringInterpolationConvertible", "lowercaseString"] +- !private ["Ps24StringLiteralConvertible", "characters"] +- !private ["Ps24StringLiteralConvertible", "init"] +- !private ["Ps24StringLiteralConvertible", "lowercaseString"] +- !private ["C38package_name_here_and_keep_quote_marks4Trie", "Array"] +- ["C38package_name_here_and_keep_quote_marks4Trie", "Bool"] +- ["C38package_name_here_and_keep_quote_marks4Trie", "Int"] +- ["C38package_name_here_and_keep_quote_marks4Trie", "Node"] +- !private ["C38package_name_here_and_keep_quote_marks4Trie", "Queue"] +- ["C38package_name_here_and_keep_quote_marks4Trie", "Set"] +- ["C38package_name_here_and_keep_quote_marks4Trie", "String"] +- ["C38package_name_here_and_keep_quote_marks4Trie", "Trie"] +- ["C38package_name_here_and_keep_quote_marks4Trie", "contains"] +- ["C38package_name_here_and_keep_quote_marks4Trie", "count"] +- ["C38package_name_here_and_keep_quote_marks4Trie", "deinit"] +- ["C38package_name_here_and_keep_quote_marks4Trie", "find"] +- ["C38package_name_here_and_keep_quote_marks4Trie", "findPrefix"] +- ["C38package_name_here_and_keep_quote_marks4Trie", "getWords"] +- ["C38package_name_here_and_keep_quote_marks4Trie", "init"] +- ["C38package_name_here_and_keep_quote_marks4Trie", "insert"] +- ["C38package_name_here_and_keep_quote_marks4Trie", "isEmpty"] +- ["C38package_name_here_and_keep_quote_marks4Trie", "isPrefix"] +- ["C38package_name_here_and_keep_quote_marks4Trie", "merge"] +- ["C38package_name_here_and_keep_quote_marks4Trie", "printTrie"] +- ["C38package_name_here_and_keep_quote_marks4Trie", "remove"] +- ["C38package_name_here_and_keep_quote_marks4Trie", "removeAll"] +- !private ["C38package_name_here_and_keep_quote_marks4Trie", "root"] +- !private ["C38package_name_here_and_keep_quote_marks4Trie", "wordCount"] +- !private ["C38package_name_here_and_keep_quote_marks4Trie", "wordList"] +- !private ["Ps31UnicodeScalarLiteralConvertible", "characters"] +- !private ["Ps31UnicodeScalarLiteralConvertible", "init"] +- !private ["Ps31UnicodeScalarLiteralConvertible", "lowercaseString"] +- ["Ps10_ArrayType", "Element"] +- ["Ps10_ArrayType", "Generator"] +- ["Ps10_ArrayType", "Index"] +- !private ["Ps10_ArrayType", "SubSequence"] +- ["Ps10_ArrayType", "_Element"] +- !private ["Ps10_ArrayType", "append"] +- !private ["Ps10_ArrayType", "init"] +- !private ["Ps10_ArrayType", "removeAtIndex"] +- !private ["Ps10_ArrayType", "subscript"] +- !private ["Ps33_BuiltinBooleanLiteralConvertible", "_getBuiltinLogicValue"] +- !private ["Ps49_BuiltinExtendedGraphemeClusterLiteralConvertible", "characters"] +- !private ["Ps49_BuiltinExtendedGraphemeClusterLiteralConvertible", "init"] +- !private ["Ps49_BuiltinExtendedGraphemeClusterLiteralConvertible", "lowercaseString"] +- ["Ps33_BuiltinIntegerLiteralConvertible", "Distance"] +- ["Ps33_BuiltinIntegerLiteralConvertible", "IntegerLiteralType"] +- !private ["Ps32_BuiltinStringLiteralConvertible", "characters"] +- !private ["Ps32_BuiltinStringLiteralConvertible", "init"] +- !private ["Ps32_BuiltinStringLiteralConvertible", "lowercaseString"] +- !private ["Ps37_BuiltinUTF16StringLiteralConvertible", "characters"] +- !private ["Ps37_BuiltinUTF16StringLiteralConvertible", "init"] +- !private ["Ps37_BuiltinUTF16StringLiteralConvertible", "lowercaseString"] +- !private ["Ps39_BuiltinUnicodeScalarLiteralConvertible", "characters"] +- !private ["Ps39_BuiltinUnicodeScalarLiteralConvertible", "init"] +- !private ["Ps39_BuiltinUnicodeScalarLiteralConvertible", "lowercaseString"] +- ["Ps24_DestructorSafeContainer", "Element"] +- ["Ps24_DestructorSafeContainer", "Generator"] +- ["Ps24_DestructorSafeContainer", "Index"] +- !private ["Ps24_DestructorSafeContainer", "SubSequence"] +- ["Ps24_DestructorSafeContainer", "_Element"] +- !private ["Ps24_DestructorSafeContainer", "append"] +- !private ["Ps24_DestructorSafeContainer", "init"] +- !private ["Ps24_DestructorSafeContainer", "removeAtIndex"] +- !private ["Ps24_DestructorSafeContainer", "subscript"] +- ["Ps14_Incrementable", "Distance"] +- ["Ps14_Incrementable", "IntegerLiteralType"] +- !private ["Ps14_Incrementable", "_DisabledRangeIndex"] +- ["Ps22_IntegerArithmeticType", "Distance"] +- ["Ps22_IntegerArithmeticType", "IntegerLiteralType"] +- ["Ps12_IntegerType", "Distance"] +- ["Ps12_IntegerType", "IntegerLiteralType"] +- !private ["Vs26_OptionalNilComparisonType", "deinit"] +- ["Ps22_RandomAccessAmbiguity", "Distance"] +- ["Ps22_RandomAccessAmbiguity", "IntegerLiteralType"] +- ["Ps12_Reflectable", "Distance"] +- ["Ps12_Reflectable", "Element"] +- ["Ps12_Reflectable", "Generator"] +- ["Ps12_Reflectable", "Index"] +- ["Ps12_Reflectable", "IntegerLiteralType"] +- ["Ps12_Reflectable", "Some"] +- !private ["Ps12_Reflectable", "SubSequence"] +- ["Ps12_Reflectable", "_Element"] +- !private ["Ps12_Reflectable", "_getBuiltinLogicValue"] +- !private ["Ps12_Reflectable", "append"] +- !private ["Ps12_Reflectable", "characters"] +- !private ["Ps12_Reflectable", "count"] +- ["Ps12_Reflectable", "init"] +- !private ["Ps12_Reflectable", "lowercaseString"] +- !private ["Ps12_Reflectable", "removeAtIndex"] +- !private ["Ps12_Reflectable", "subscript"] +- ["Ps18_SignedIntegerType", "Distance"] +- ["Ps18_SignedIntegerType", "IntegerLiteralType"] +depends-nominal: +- !private "Vs12AnyGenerator" +- "Ps9AnyObject" +- !private "Vs11AnySequence" +- "Sa" +- "Ps23ArrayLiteralConvertible" +- !private "Vs10ArraySlice" +- "Ps22BidirectionalIndexType" +- "Ps21BitwiseOperationsType" +- !private "Sb" +- !private "Ps25BooleanLiteralConvertible" +- !private "Ps11BooleanType" +- "Ps11CVarArgType" +- !private "VSS13CharacterView" +- "Ps14CollectionType" +- "Ps10Comparable" +- "Ps28CustomDebugStringConvertible" +- "Ps23CustomStringConvertible" +- !private "Vs10Dictionary" +- !private "Vs19DictionaryGenerator" +- !private "Vs15DictionaryIndex" +- !private "Ps28DictionaryLiteralConvertible" +- "Ps9Equatable" +- !private "Ps41ExtendedGraphemeClusterLiteralConvertible" +- "Ps16ForwardIndexType" +- "Ps13GeneratorType" +- "Ps8Hashable" +- !private "VVSS13CharacterView5Index" +- "Ps9Indexable" +- "Vs17IndexingGenerator" +- "Si" +- "Ps21IntegerArithmeticType" +- "Ps25IntegerLiteralConvertible" +- "Ps11IntegerType" +- "Ps14MirrorPathType" +- "Ps21MutableCollectionType" +- "Ps16MutableIndexable" +- "Ps16MutableSliceable" +- "Ps21NilLiteralConvertible" +- "C38package_name_here_and_keep_quote_marks4Node" +- "Sq" +- !private "Ps16OutputStreamType" +- !private "V38package_name_here_and_keep_quote_marks5Queue" +- "Ps21RandomAccessIndexType" +- "Ps30RangeReplaceableCollectionType" +- "Ps12SequenceType" +- "Vs3Set" +- !private "Vs12SetGenerator" +- "Ps17SignedIntegerType" +- "Ps16SignedNumberType" +- !private "Vs5Slice" +- !private "Ps10Streamable" +- "Ps10Strideable" +- !private "SS" +- !private "Ps30StringInterpolationConvertible" +- !private "Ps24StringLiteralConvertible" +- "C38package_name_here_and_keep_quote_marks4Trie" +- !private "Ps31UnicodeScalarLiteralConvertible" +- "Ps10_ArrayType" +- !private "Ps33_BuiltinBooleanLiteralConvertible" +- !private "Ps49_BuiltinExtendedGraphemeClusterLiteralConvertible" +- "Ps33_BuiltinIntegerLiteralConvertible" +- !private "Ps32_BuiltinStringLiteralConvertible" +- !private "Ps37_BuiltinUTF16StringLiteralConvertible" +- !private "Ps39_BuiltinUnicodeScalarLiteralConvertible" +- "Ps24_DestructorSafeContainer" +- "Ps14_Incrementable" +- "Ps22_IntegerArithmeticType" +- "Ps12_IntegerType" +- !private "Vs26_OptionalNilComparisonType" +- "Ps22_RandomAccessAmbiguity" +- "Ps12_Reflectable" +- "Ps18_SignedIntegerType" +depends-dynamic-lookup: +depends-external: +- "/home/christian/swiftv2/usr/lib/swift/linux/x86_64/Swift.swiftmodule" +- "/home/christian/swiftv2/usr/lib/swift/shims/UnicodeShims.h" +- "/home/christian/swiftv2/usr/lib/swift/shims/SwiftStdint.h" +- "/home/christian/swiftv2/usr/lib/swift/shims/SwiftStddef.h" +- "/home/christian/swiftv2/usr/lib/swift/shims/LibcShims.h" +- "/home/christian/swiftv2/usr/lib/swift/shims/RuntimeStubs.h" +- "/home/christian/swiftv2/usr/lib/swift/shims/RuntimeShims.h" +- "/home/christian/swiftv2/usr/lib/swift/shims/RefCount.h" +- "/home/christian/swiftv2/usr/lib/swift/shims/HeapObject.h" +- "/home/christian/swiftv2/usr/lib/swift/shims/GlobalObjects.h" +- "/home/christian/swiftv2/usr/lib/swift/shims/FoundationShims.h" +- "/home/christian/swiftv2/usr/lib/swift/shims/CoreFoundationShims.h" +- "/home/christian/swiftv2/usr/lib/swift/shims/module.map" +interface-hash: "f003b1876d32aa37e370054fb3e811bb" diff --git a/Trie/Package.swift b/Trie/Package.swift new file mode 100644 index 000000000..fc323a1ec --- /dev/null +++ b/Trie/Package.swift @@ -0,0 +1,6 @@ +import PackageDescription + +let package = Package( + name: "Trie", + targets: [] +) diff --git a/Trie/Package.swift~ b/Trie/Package.swift~ new file mode 100644 index 000000000..c9e5942b1 --- /dev/null +++ b/Trie/Package.swift~ @@ -0,0 +1,5 @@ +import PackageDescription + +let package = Package( + name: "package_name_here_and_keep_quote_marks" +) diff --git a/Trie/sources/Queue.swift b/Trie/sources/Queue.swift new file mode 100644 index 000000000..efc573442 --- /dev/null +++ b/Trie/sources/Queue.swift @@ -0,0 +1,47 @@ +/* + First-in first-out queue (FIFO) + + New elements are added to the end of the queue. Dequeuing pulls elements from + the front of the queue. + + Enqueuing and dequeuing are O(1) operations. +*/ +public struct Queue { + private var array = [T?]() + private var head = 0 + + public var isEmpty: Bool { + return count == 0 + } + + public var count: Int { + return array.count - head + } + + public mutating func enqueue(element: T) { + array.append(element) + } + + public mutating func dequeue() -> T? { + guard head < array.count, let element = array[head] else { return nil } + + array[head] = nil + head += 1 + + let percentage = Double(head)/Double(array.count) + if array.count > 50 && percentage > 0.25 { + array.removeFirst(head) + head = 0 + } + + return element + } + + public func peek() -> T? { + if isEmpty { + return nil + } else { + return array[head] + } + } +} diff --git a/Trie/sources/main.swift b/Trie/sources/main.swift new file mode 100644 index 000000000..e88bbc713 --- /dev/null +++ b/Trie/sources/main.swift @@ -0,0 +1,34 @@ + +print("tests") + + +var T: Trie = Trie() +T.insert("Hello") +T.insert("Hi") +T.insert("Hey") +T.insert("Hallo") +T.insert("Henry") +var U: Trie = Trie(wordList: Set(["Hey", "HO", "hello", "yolo"])) +var V: Trie = T.merge(U) +//T.printTrie() +//U.printTrie() +//V.printTrie() +print(V.getWords()) +V.removeAll() +//V.printTrie() +/*T.insert("Hello") +T.insert("Hey") +T.insert("YOLO") +T.insert("Him") +assert(T.count() == 4, "Count function failed") +assert(T.contains("Hey") == true) +assert(T.contains("Hello") == true) +print("trying remove") +T.remove("Him") +assert(T.count() == 3) +assert(T.contains("Him") == false, "Test failed") +assert(T.wordList.count == 3)*/ + +//T.printTrie() +//print(T.find("")) +//print(T.findPrefix("H")) diff --git a/Trie/trie.swift b/Trie/sources/trie.swift similarity index 85% rename from Trie/trie.swift rename to Trie/sources/trie.swift index 341f4c708..bf1b44156 100644 --- a/Trie/trie.swift +++ b/Trie/sources/trie.swift @@ -233,10 +233,12 @@ public class Trie { func findPrefix(p: String) -> [String] { + var q: Queue = Queue() + return [] } - func removeAll() -> Void { + func removeAll() { for word in wordList { self.remove(word) } @@ -249,43 +251,3 @@ public class Trie { } } - -print("tests") - -/*var x: Node = Node(c: "c") -print(x.char()) -print(x.isValidWord()) -x.isWord() -print(x.isValidWord())*/ - - -var T: Trie = Trie() -T.insert("Hello") -T.insert("Hi") -T.insert("Hey") -T.insert("Hallo") -T.insert("Henry") -var U: Trie = Trie(wordList: Set(["Hey", "HO", "hello", "yolo"])) -var V: Trie = T.merge(U) -//T.printTrie() -//U.printTrie() -//V.printTrie() -print(V.getWords()) -V.removeAll() -//V.printTrie() -/*T.insert("Hello") -T.insert("Hey") -T.insert("YOLO") -T.insert("Him") -assert(T.count() == 4, "Count function failed") -assert(T.contains("Hey") == true) -assert(T.contains("Hello") == true) -print("trying remove") -T.remove("Him") -assert(T.count() == 3) -assert(T.contains("Him") == false, "Test failed") -assert(T.wordList.count == 3)*/ - -//T.printTrie() -//print(T.find("")) -//print(T.findPrefix("H")) From 3d0bb6de0aa0bf87b933680407881d511cc9cbea Mon Sep 17 00:00:00 2001 From: Thukor Date: Tue, 3 May 2016 16:12:48 -0400 Subject: [PATCH 0315/1679] Finally got findPrefix() workinggit add .git add .! --- Trie/.build/debug/Trie | Bin 95508 -> 103286 bytes Trie/.build/debug/Trie.o/Trie/main.swiftdeps | 15 +++-- .../.build/debug/Trie.o/Trie/master.swiftdeps | 6 +- Trie/.build/debug/Trie.o/Trie/trie.swiftdeps | 62 +++++++++++++----- .../Trie.o/Trie/trie~partial.swiftmodule | Bin 53928 -> 66240 bytes Trie/.build/debug/Trie.o/build.db | Bin 15360 -> 15360 bytes Trie/.build/debug/Trie.o/sources/main.swift.o | Bin 13864 -> 14800 bytes Trie/.build/debug/Trie.o/sources/trie.swift.o | Bin 94800 -> 107904 bytes Trie/.build/debug/Trie.swiftmodule | Bin 20724 -> 21236 bytes Trie/sources/main.swift | 3 +- Trie/sources/trie.swift | 38 ++++++++++- 11 files changed, 94 insertions(+), 30 deletions(-) diff --git a/Trie/.build/debug/Trie b/Trie/.build/debug/Trie index 3635f7c44a43c8b6f0aeab91e0d200109e211888..188a7c4d0c444c157c71e7da34a6ba76d6069ca5 100755 GIT binary patch literal 103286 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ℑ6zsY!R%XN&BfGeX$d1EDcsFgvEeSHDCe7r~Qqc7 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 z zQ%W0kh&wxJi|m69l_zzdIbb7u%SttlD=k+=Qr&IrDLaC_^@x;1J^07#3fO157dLeJ iR}K%yhTHHY6}Dk$?O-278&-GACpPhXYjA`H*Z&8N!`eCk delta 34861 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 H(1-nh^FwF{ diff --git a/Trie/.build/debug/Trie.o/Trie/main.swiftdeps b/Trie/.build/debug/Trie.o/Trie/main.swiftdeps index 923f0f821..d126051a2 100644 --- a/Trie/.build/debug/Trie.o/Trie/main.swiftdeps +++ b/Trie/.build/debug/Trie.o/Trie/main.swiftdeps @@ -6,15 +6,17 @@ provides-top-level: provides-nominal: provides-member: depends-top-level: -- "StringLiteralType" -- "Set" -- "Array" -- "print" - "Trie" +- "U" +- "Array" - "V" +- "print" +- "StringLiteralType" - "T" -- "U" +- "Set" +- "UnicodeScalarType" depends-member: +- ["Ps9AnyObject", "findPrefix"] - ["Ps9AnyObject", "getWords"] - ["Ps9AnyObject", "init"] - ["Ps9AnyObject", "insert"] @@ -110,6 +112,7 @@ depends-member: - ["Ps16SignedNumberType", "IntegerLiteralType"] - ["Ps10Strideable", "Distance"] - ["Ps10Strideable", "IntegerLiteralType"] +- ["C4Trie4Trie", "findPrefix"] - ["C4Trie4Trie", "getWords"] - ["C4Trie4Trie", "init"] - ["C4Trie4Trie", "insert"] @@ -199,4 +202,4 @@ depends-external: - "/home/christian/swiftv2/usr/lib/swift/shims/FoundationShims.h" - "/home/christian/swiftv2/usr/lib/swift/shims/CoreFoundationShims.h" - "/home/christian/swiftv2/usr/lib/swift/shims/module.map" -interface-hash: "80fed5d587327a0a97180685d884fa09" +interface-hash: "57319b836b718d38040ac7809f4446f7" diff --git a/Trie/.build/debug/Trie.o/Trie/master.swiftdeps b/Trie/.build/debug/Trie.o/Trie/master.swiftdeps index 5539f705b..3f65c9e2b 100644 --- a/Trie/.build/debug/Trie.o/Trie/master.swiftdeps +++ b/Trie/.build/debug/Trie.o/Trie/master.swiftdeps @@ -1,7 +1,7 @@ version: "Swift version 2.2-dev (LLVM 3ebdbb2c7e, Clang f66c5bb67b, Swift 0ddf238ad7)" options: "1cfa30eacd63a1262ef0618da5cf7605" -build_time: [515616404, 830067000] +build_time: [515621198, 271577000] inputs: - "/home/christian/Desktop/swift-algorithm-club/Trie/sources/main.swift": [515616359, 0] - "/home/christian/Desktop/swift-algorithm-club/Trie/sources/trie.swift": [515616400, 0] + "/home/christian/Desktop/swift-algorithm-club/Trie/sources/main.swift": [515620938, 0] + "/home/christian/Desktop/swift-algorithm-club/Trie/sources/trie.swift": [515621195, 0] "/home/christian/Desktop/swift-algorithm-club/Trie/sources/Queue.swift": [512710161, 0] diff --git a/Trie/.build/debug/Trie.o/Trie/trie.swiftdeps b/Trie/.build/debug/Trie.o/Trie/trie.swiftdeps index 35e802978..6f65d2492 100644 --- a/Trie/.build/debug/Trie.o/Trie/trie.swiftdeps +++ b/Trie/.build/debug/Trie.o/Trie/trie.swiftdeps @@ -9,29 +9,30 @@ provides-member: - ["C4Trie4Node", ""] - ["C4Trie4Trie", ""] depends-top-level: -- "Int" +- !private "StringLiteralType" - !private "UnicodeScalarType" -- !private "Array" -- "Node" -- "Void" -- !private "==" -- "IntegerLiteralType" -- !private "+=" -- "Trie" -- "FloatLiteralType" -- "Set" -- !private "BooleanLiteralType" +- !private "&&" - !private "-" +- "String" +- !private "BooleanLiteralType" - "Bool" -- !private "print" - !private "-=" -- "String" -- !private "&&" +- "Trie" +- "FloatLiteralType" +- "Int" +- !private "+" +- "IntegerLiteralType" - !private "!" +- !private "+=" +- !private "print" +- !private "!==" +- "Set" +- "Node" +- "Void" +- !private "==" - !private "Queue" -- !private "+" -- !private "StringLiteralType" - !private ">" +- !private "Array" depends-member: - !private ["Vs12AnyGenerator", "Element"] - !private ["Ps9AnyObject", "Array"] @@ -53,6 +54,7 @@ depends-member: - !private ["Ps9AnyObject", "insert"] - !private ["Ps9AnyObject", "isAWord"] - !private ["Ps9AnyObject", "isNotWord"] +- !private ["Ps9AnyObject", "isPrefix"] - !private ["Ps9AnyObject", "isRoot"] - !private ["Ps9AnyObject", "isValidWord"] - !private ["Ps9AnyObject", "isWord"] @@ -64,6 +66,7 @@ depends-member: - !private ["Ps9AnyObject", "root"] - !private ["Ps9AnyObject", "setParent"] - !private ["Ps9AnyObject", "update"] +- !private ["Ps9AnyObject", "visited"] - !private ["Ps9AnyObject", "wordCount"] - !private ["Ps9AnyObject", "wordList"] - ["Ps9AnyObject", ""] @@ -92,6 +95,7 @@ depends-member: - !private ["Vs10ArraySlice", "Index"] - !private ["Ps22BidirectionalIndexType", "Distance"] - !private ["Ps22BidirectionalIndexType", "IntegerLiteralType"] +- !private ["Ps22BidirectionalIndexType", "_DisabledRangeIndex"] - !private ["Ps21BitwiseOperationsType", "Distance"] - !private ["Ps21BitwiseOperationsType", "IntegerLiteralType"] - !private ["Sb", "_getBuiltinLogicValue"] @@ -105,6 +109,7 @@ depends-member: - !private ["VSS13CharacterView", "_Element"] - !private ["VSS13CharacterView", "count"] - !private ["VSS13CharacterView", "deinit"] +- !private ["VSS13CharacterView", "reverse"] - !private ["VSS13CharacterView", "suffix"] - !private ["Ps14CollectionType", "Element"] - !private ["Ps14CollectionType", "Generator"] @@ -115,6 +120,7 @@ depends-member: - !private ["Ps14CollectionType", "count"] - !private ["Ps14CollectionType", "init"] - !private ["Ps14CollectionType", "removeAtIndex"] +- !private ["Ps14CollectionType", "reverse"] - !private ["Ps14CollectionType", "subscript"] - !private ["Ps14CollectionType", "suffix"] - !private ["Ps10Comparable", "Distance"] @@ -190,6 +196,8 @@ depends-member: - !private ["Ps8Hashable", "init"] - !private ["Ps8Hashable", "lowercaseString"] - !private ["VVSS13CharacterView5Index", "Distance"] +- !private ["VVSS13CharacterView5Index", "_DisabledRangeIndex"] +- !private ["VVSS13CharacterView5Index", "deinit"] - !private ["Ps9Indexable", "Element"] - !private ["Ps9Indexable", "Generator"] - !private ["Ps9Indexable", "Index"] @@ -199,6 +207,7 @@ depends-member: - !private ["Ps9Indexable", "count"] - !private ["Ps9Indexable", "init"] - !private ["Ps9Indexable", "removeAtIndex"] +- !private ["Ps9Indexable", "reverse"] - !private ["Ps9Indexable", "subscript"] - !private ["Ps9Indexable", "suffix"] - !private ["Vs17IndexingGenerator", "Element"] @@ -268,11 +277,14 @@ depends-member: - ["C4Trie4Node", "printNode"] - ["C4Trie4Node", "setParent"] - ["C4Trie4Node", "update"] +- !private ["C4Trie4Node", "visited"] - ["Sq", "Some"] - !private ["Sq", "deinit"] - !private ["Ps16OutputStreamType", "characters"] - !private ["Ps16OutputStreamType", "init"] - !private ["Ps16OutputStreamType", "lowercaseString"] +- !private ["V4Trie5Queue", "dequeue"] +- !private ["V4Trie5Queue", "enqueue"] - !private ["V4Trie5Queue", "init"] - !private ["Ps21RandomAccessIndexType", "Distance"] - !private ["Ps21RandomAccessIndexType", "IntegerLiteralType"] @@ -285,8 +297,15 @@ depends-member: - !private ["Ps30RangeReplaceableCollectionType", "count"] - !private ["Ps30RangeReplaceableCollectionType", "init"] - !private ["Ps30RangeReplaceableCollectionType", "removeAtIndex"] +- !private ["Ps30RangeReplaceableCollectionType", "reverse"] - !private ["Ps30RangeReplaceableCollectionType", "subscript"] - !private ["Ps30RangeReplaceableCollectionType", "suffix"] +- !private ["Vs17ReverseCollection", "Generator"] +- !private ["Vs17ReverseCollection", "Index"] +- !private ["Vs17ReverseCollection", "_Element"] +- !private ["Vs17ReverseCollection", "deinit"] +- !private ["Vs12ReverseIndex", "Distance"] +- !private ["Ps16ReverseIndexType", "Distance"] - !private ["Ps12SequenceType", "Element"] - !private ["Ps12SequenceType", "Generator"] - !private ["Ps12SequenceType", "Index"] @@ -296,6 +315,7 @@ depends-member: - !private ["Ps12SequenceType", "count"] - !private ["Ps12SequenceType", "init"] - !private ["Ps12SequenceType", "removeAtIndex"] +- !private ["Ps12SequenceType", "reverse"] - !private ["Ps12SequenceType", "subscript"] - !private ["Ps12SequenceType", "suffix"] - !private ["Vs3Set", "Generator"] @@ -402,6 +422,7 @@ depends-member: - !private ["Ps12_Reflectable", "IntegerLiteralType"] - ["Ps12_Reflectable", "Some"] - !private ["Ps12_Reflectable", "SubSequence"] +- !private ["Ps12_Reflectable", "_DisabledRangeIndex"] - !private ["Ps12_Reflectable", "_Element"] - !private ["Ps12_Reflectable", "_getBuiltinLogicValue"] - !private ["Ps12_Reflectable", "append"] @@ -411,6 +432,9 @@ depends-member: - !private ["Ps12_Reflectable", "lowercaseString"] - !private ["Ps12_Reflectable", "removeAtIndex"] - !private ["Ps12_Reflectable", "subscript"] +- !private ["Ps22_ReverseCollectionType", "Generator"] +- !private ["Ps22_ReverseCollectionType", "Index"] +- !private ["Ps22_ReverseCollectionType", "_Element"] - !private ["Ps18_SignedIntegerType", "Distance"] - !private ["Ps18_SignedIntegerType", "IntegerLiteralType"] depends-nominal: @@ -458,6 +482,9 @@ depends-nominal: - !private "V4Trie5Queue" - !private "Ps21RandomAccessIndexType" - !private "Ps30RangeReplaceableCollectionType" +- !private "Vs17ReverseCollection" +- !private "Vs12ReverseIndex" +- !private "Ps16ReverseIndexType" - !private "Ps12SequenceType" - !private "Vs3Set" - !private "Vs12SetGenerator" @@ -485,6 +512,7 @@ depends-nominal: - !private "Vs26_OptionalNilComparisonType" - !private "Ps22_RandomAccessAmbiguity" - "Ps12_Reflectable" +- !private "Ps22_ReverseCollectionType" - !private "Ps18_SignedIntegerType" depends-dynamic-lookup: depends-external: @@ -501,4 +529,4 @@ depends-external: - "/home/christian/swiftv2/usr/lib/swift/shims/FoundationShims.h" - "/home/christian/swiftv2/usr/lib/swift/shims/CoreFoundationShims.h" - "/home/christian/swiftv2/usr/lib/swift/shims/module.map" -interface-hash: "fd9fdb3a4bd3dfc789eaf1430eb72c67" +interface-hash: "eefc37d55a335afd501967035d9090a5" diff --git a/Trie/.build/debug/Trie.o/Trie/trie~partial.swiftmodule b/Trie/.build/debug/Trie.o/Trie/trie~partial.swiftmodule index adcffc2d393f212f2788c24b04011d6603038431..f9e33b421a684ed26ac2066848785167312f0845 100644 GIT binary patch delta 27847 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 WwBTau6vTqJXgn+S?j7@q^#1@l@l7=V delta 16548 zcmbtbd3+Q__J7^XK$1Zi5*UIabV5RgWWeE2Bce7TVmLFf2;o`=2^f#XfS^HGr-%rs zC?gHXDvJXGa;YN$jV@|~h(TG1cq|?(Bg+aZ>o1_YvR?c9zUrRLB;x+@`_<=D)m87k zdUqW?otXDKwrpw>P|-(8vmPRMX{vGRsq9dcC!u6o4@yZ{fu010`}-B5LPoeJd}7lrs?H#a zr4ng30lvRAnyn>k(1KLpp|e~R4OQ4OTcUpvDn(EOfPZ#z#sxa%(3<3}}XxqhR1eiSvlWkO)hEeRK}E={}@_RHO`M7&{jw- zrZN)cVq?}!PY52C#bZC0JQ9xOTm4ApMyn(EFfo>xP`7t23gmqevpMZq3GuZ z@q&Q0(hwr{4ws90EY-mCGKM&8iZULc zc#Mg+XN7EFgjRTW0$74E`<=92^{gv9xMYt8Xc&r0BcqPrVW^cb72?#&dPp0wE8#jSk7z<}+mKQR=oa>l2f?CN!_0LVT8rxcVdKcOXPUEO8xfp#) z;XN27VmqY%S`1iveF~bOO)AhQcY$$RX;wQg_j!TGpT;X|yq9n;X#dV)7&vj75%p=s zYvVGbi`S#gvN=fvpmM1s1e`XGRCOv00znURV+$dhy=P{6WvrVx z5hnpwrd*$i2p1a>Z`MsWF)Aqynh~|m>cVJtK{j`Osnaw&apD2HoXMK&)bkUDUCge% zoqH(K-9@&uD{QCiVoe>!^JN`E#kOPOLDKvjc0W(8;MkhnL)pWP`%-QbUOd*!$=0q^ z#Uv@M+4K9kdx4F|PVF*lwG-XLbP4wa4^G1+vaSQqJlqe}|X%%4x9Bj)>y{H;@!dGz+tX;f6URvy;xr6KTh!woOuAaG5b@L}4h8;p%;iNmyfV+$KY4p)Jz3 zMzF>xLE9xVR8b2i_f&FAo(YO@GX{fs<|WpQ{w9Z8Xf}xqH2@C-Dy7SX755{@nFiWM z+-|hHvr|@IdlWbMMkcZ2fM=zHmwt#dFlpD1vNUVgmtp?p!U<=A0wr!FCoPw_4+is~ zH8)URJ`dUynKsalxnRlHpq8CuO#2Bo8V_N0kpaarEobmJrS%nP>$&UB&?d$=_j(P~uLNiIK3>IudlA5{=1ATN-i) zhkQKA0vs^Cl373#+x>du24TThYn(d!ZN2=`KDb=tRB$ti{-r=GU8k2+$~OUE(tc|h zCu*Uj`zlau^b_PQ4e>@cdM|sEdEz1bc%ta2n$4e;K7h)F$wn_^BJSZHJq@i)AbEpf zGKNT`?E(u8;6ux$j$7~J2b)XXv-Xzo6Y{3!*bd}}Tp$3VE5>N4M!7LC+Y3a1k-mY$ z(5B>~L5au~iBP@9c+=<>VjK#aB%eaVS*FYW))rW@LJD60M!5u$p1Bf~#e8@C|GckY zy7jse`fu+m)f;{TLe9i$(G4w^>S{ad0Gn%p(A#bIHdH@n_xN!Q95)-j>9fe)I)Bj8 zgKgUnZ?lUp4k!ve^sn2WE;8=fbiI;ZV{S4O#chmv`a#8I9DlmIi_=n}uEkyNxyy)d zFRaPkDpaLo&F1Zn7D@+W`?H@ZZE7BVZiAwuoL^L`5&^bbW`f1YBGEueXblb_AygWn!PT{SymA$pmUN|*I_PRHwywWvfNf97geH6_=R7;8q zJyx9Qp;cv}5$n&;h7{I)6gvrZL z1t^W5Ub%Q&Z<~{&1AsnU5ry|sQ2U-i69(bVDl{ABU~+Unbmuqkx)Z=HU4ge4Gaa)d zkf1$;%+iMP1~Cj~ifm)%tNDfU@&rd(cCG<(bssb%P(7EUK@kLoe7Es)$a13S>4nCq z*E-z3*Ul?bQtY!cR!-u1DZ09b+Em)(me>zPE8cxkYzUhAiHF@AWhS6k_o>oLdo3dkQc3e9X~sxi^* z*5M7<@6JV%id=R_d(?$(4Z|FseH~!fjifHYm0K`x zKg}}`bmgeJ2_x*7VkalQ`;4@G*`e1#$rM7qSAK?6@?x|HM#bFI zk~;`Io;s#Q@HDgF4C%1Y0~p4F-~$M)K;@?w6_aCdXY!6hZp5caN$BR@+V za{%K$Ag;l)E6@-W1KJJLkEn#YknJA`ZW`ziz5rsvr*&r-x`hMLDhmyYK8|7>ufwb) zCf<7(gL%xVrV73F#ZXILSW-6i0V_V0b?*?M<&j>r6>{Y&at|E}a^BQMU;>0hLwu3v zQq6lMAG_MhLm0|KeEl3|3&-PrkL_Fd(9^w}m@UsL;>(52b}+`{QNb1}%ClinI(%kU zLzN)dQZxc3!sysK@%2P|D8wEaS`4VARDUQ{7XyoLAwm2i0XuQ{u0wV6IgnVB*5sRb zGG8?o9Yt()WDczP2<^_9Xx5)(Yj_={Y=W_tlR{oTr7d$(5kO8gC^QSL?Ikt`d}+~& z&W#@W9AoR6Qw;A!#-OPTb9_*w#|J-vWYf2D^8mP-*)}qTkGt-u!Vj@j;t5HQ??S(@ z9t{IER7!!yg2gU@6D5Sxf%u9Oz|*pFG_uaN@(h4>%-GG+%3Kb!l?s0cV>=aiEuCPg zP}-l0{G&yUJBJCfW;@3m@BoeA{KqrQCt(Wf@;V@V<RJ*Tti!m zEx}yHi7~wsG(qCy{0Cn*_*Q}JRg8oDs^AyH7@&oKRnS|*LoG33 zDh9nll4&T1F74q4w4ooslfFPR_In`lB=;gTMX1;lBG@v5Em?#y`B3YeQb5P?TJ3<` z(lMa@m=VLX5;>zo+(w0oL;1`|&jJIfG$ME&NP@t7dDYD0Tl8E$_xBy{it)V;bgMjQ z?qU@hq#durn0j~scc4MgIg5LVQan(DxcpziZ2Lpuos(=pADT<`E6;5ddutodJEs znh^>N#Y%QO2B#3HL=0emHUMrMXUSz0uYJpddmT+Z$nQ|zBoAVm-kt%L1N%VNWC!M8 zyds%3ggGB-)V2&DiY{N+R~qQE#T>JN0(hIYTVrg)E#idLNcC z&Z_eq{@532j?F@29s!D$=Rx`>1vtc{do_(e-K++JbAbz=?F4e$zw5A;EdP4H8;Zp( zy_~WXUN;eXu1VbNo!#V&>Yb{hj=(#YOw_Z640=Xj8o8Y@>lCRh_9o3F!52qbZG5fi10p)ce zL=5(ZD%l3B2sTab2$pAugK92+VfajX_Fmqj=8Z)2_hiv3M2lY+&A$P^cMy`6Ud>X@ zXJP)yApm}Y4w<3lI7hVQ`B)6eKI#sn!Sq&%G>guS7mUtGKoRG7VMirJX9@24fj6P7 z9i1f{ou@+#{q^ubt)`;8jDwJ0L<3XqV$W zwhmSPVL=0g+Ts3@0*z8Y#VNRm&#(f4{RC^i1vpyADZk0G61s+l{d7O-AaKi)XI>;5 zLs|+R#o&P=#FKqNy>22JxszHH%Rn*Mrl^Mg<`KDD_d+JL=>d(7JpegoDY{e&pf1(W zc&TibY#SSQs-3`+Lr7cBEDlQ+%w9t2NP4@iri=QoS+T4?q-k-*o&tBawg`ypzFeD2JA!A zQ?k&(B9dUiBzjJH6ArImh{OIy4i(_AOHPRI^UOkS44|=;c;iAW4m7f;1dH0{O5EN= zi8n9Ap{|ib6*%lMir;rP?zNWSgBP0iR^v2*X=XFQ?dJesy)~^yu&p!K%D^DTQA|!M zZYNf|mE~QqF!hj3bIm%?vO$=#6mP=1FEJ&END>&?DeyE>-%0^{!{F}|CJ4NqYm)!hfl z_H`p0z?9|-R5XoF9=6I~M&|^gQ|V%+R*B)EbNBpJ@~nA>!?QOLo`FD}{E)-*-=fn@ zG{4UMB05h4m>iu?;X)VIIc1@W4nDr?h#Sy{)%>|KhF!+gFbGbCF5+B1TE?(!C#1;S6=zIt%Wr8&mR{_DaQv5PYJZF-01$MP2;$uz4>q+7*Pq^V# z4os7jCs5;{oYAq_`>l4@|EN&Zm@I}h^tW`lEF{z>BmJ_j4wrxOGV15#$SSF=q-u!@z74lVDZr{QyYpt{TW1po9GFsSx&+ zh2;LmEEj>YQIDH3xCJ$#he*=Ha<7S~X^@!$odg*B)JpmtbWljSi(kP+rTy1P%|o zWlNLrPz0#BSFFvBU$&7QA`DE4ZI;+gKimkc0u8Yb3COp+EjXW%hrH9WR*7Bc5ctNEK;E8a z0+8?)Z)4+ECP=bu@fXLE`Yvck>W{k)fyahE&f;qSvYqho(`*b0PiEgDWha!ZA_*jyavyX;? zO6MDK^4AI63{PUB0~smLN@4*7ko}S8Xg(%Y?}M#Dc1+q15Vv6abG-aI%rT0@U_WcE zR~HrFfjx=Ro|AM;h7s>La!(>JylH<`3u0=~Av9U1KD*MqD&K?L ztl)H<`xZAxx%o&nx}O?itT^TE`W6KE_!m{*N8Fs?=1XqQ zar3?L!l?r9vObsuE4eJ?KIf!WdSj8_2S|F0l|L8M+;}?L!tj3m`P@2hNtY#Wcje>8UcTT%wE|4F8^FDldIUIgHbn3Hc&5wFfmwhW8^vY1xT$QVc&sR`v?GV!6 z&7s1()2V(yDydI8sC_^ceyB}n=TKEK+?}SF+6L1~{9>^f=NGeS{?V$O0se0wr zirDu@s{DK;)z8hNetR;={4|xiG&n?Il}fz_D6#By6!DbO>4)=3ugjnVCsS$kHx6-h zo=QItP-xFO@=q%z|E@eL|2TunzD}jkcMkeuzN)8Qt5Dk~DY~qb8bWn>wEyoJRQ_!$ zt^UCww%)6XTdq^I*PbNvWGS8hHjnClfN*CT{kDaZmLM^v4OGOb2u0=xC@{=R5&R0~#CV$r+ z6!NcbPZLVhXmq}leq5#Mi-##@$IYa7{|$LJ_Mk1Fw5Q0dG&X7C!WT| zb_`yx@~PIlOvRN*g@RE}X{;Ha9%~Z7cFH&XQMB4I2Pg?e!hxRXU(a60{5&GtY zYQ|I<1|SO1JKGh)=Nc3wkQC4XY_QV;BW@=hA{t(~-cbbnGPu zwVkZ$`|-tl&10nh1slV6xfI&<=VzOIiF8}|naM28dI+MVjJ%%J*psdOnWJqIdOF{hsr3p`GdD@Rb(`tJC% z)(jfCJ(d3PzJt)l9!ep^fXv#MitnAK)gV@%N@){Gn)j^36}f)!a!R)T;X2NlLKzSu%6RQT@sS3jVnRwLBF{ql@M^MbDR2 zp-on_RnJnx$Z=HmTmdaR-ho~{n?@hcb5hwWDt+}^g;qUB`bXoa?wbO7@23t__@6Yo zcA=Br-m8k7sfzi0lp+;n5RT_G;BKFr%@YHy!`q762(1Sk&b5Yt;PHJ&f6*`v3Yr9AfPoT;hds6Uu z4>=~eXvcF-8gopgTW(jh(if;<+(bH7)04E*9!j~(MY~^hiiO8jdixGV|DP90{5TQ6 zvh~7WOLV02g)aOSg#53MspkAjC2~V8MZJ@#&eMz5w(dw@E_TuDuRH0VpQ+SlmSTo$ zNgpwZ+&y}cuR}-b^N@@BA8=Cf-&C=CmLg8pl6Lnb{DE;VD%3hsZP-QI>YTLTq$)NIM>L(d7?*Nfg8(2-g`>7tr?r#O3B z71eW;;NX`jk~**`2>gbJ-9QxjXTK<)T@BU<%R#che`NPVcrAD zYz6-ui%ZOO++X>IdI@H?!5w}X?n3=>1<*j_QOJY{eI$lG@Ggjp@=36$0*g0+#_NlK zqQS}Fd>ItM>q;hW34UDWp27KjTp|6R;5;9gtC9{gW3NL0DVX8MZ7&l) zokD@kmL%G=ARRx8#bBbChIf$O0C&Qh2hd}oU!N8vo&fVBP`3gK^uz3naSgf%_m7R3 zJ_*yGgZ>}m!u>nwkJp4_@Q@E4^0mT0kYf6u6^h`F7?_LO;MFhr)YWQzIX8%p0 z;5i7N2f^21b{C)!g2O=L)+N4!@Sk86(7>{mmi11SOSe+T+*m4dkNh;;~PDRj%j^Q&OsWs2rcrZua3(V1Z#Y4Bzj z4SUxqUiv~cKSxSe0evmdp$PDSj&xv)iynH&mi{5_U zDgF)gVxa4Qo&oeOpeJDVGcI!d#VP*qm1=$fbOX@$0R1Y^Q!qOU;m4ffsxzwD{VpY# z`6r4#0(4z3nsKHa(|1DnhfeV!@OJ^P1HS?IqnLgRrtfyqE_x}tV=|R}*o*4iMgEF* zF8U*KT^5B};zHmcCyl(LeEN{C04lUg^-Iv0*|$s|lC}E|rI*rn24gfdH=`=qFYZv3 H_R9YP)vk3| diff --git a/Trie/.build/debug/Trie.o/build.db b/Trie/.build/debug/Trie.o/build.db index 0028fe224f5e646cb2855a04c20247cf4e075b37..1b9a387ff0a346fbfbed4bd7a4a3a64c8bb116ee 100644 GIT binary patch delta 1820 zcma)6Z%iCT6rY*5cL&$Io>!oN{5|$69LQ0?vsLhHdt7M?!PXM~!xadWt0IQd+JrVR z8%_LVSSNl{n<|Z(*bjscCa8_1UrdculM<6!tErNZ(8M-0^@E!FW_J$`Y@%;>-^_dS zoA-BiCeKWsnaWA^6GA-rZPooX)IW3VydzV!!2_be5^9MP{)Bt50!#4otXH`LAza!< z2y&NPCaGE*@)YewEIT8m}5RJ>kUns<9UZbbS< zF)fdN{qjyJtLj;;Ra~tcx2amD)+P>CmB6xdLg$CX<*Jm4W`B`Hk^8a|NR5A#7=hh* z=ZBz_l@!SdS+Q{6J!8t(tOQQn4`)bC0{5$ho4iO3;DQy->Vb)ZWZW+%PDHD-vs6_k z?I6AmmL)i0S-Eo2u4pJz^@9k#c-wG(I*o zT(0vHyQ=amty|m(`QXl4mZe9ns7{NGQQcj&%Y%eP;(1z^gYc-}nd#WABJuF)TrpDW z7Dpb>65;AXCqiFhUXr zF&Wcm$0nb-Vs2OZ;RGz<_rLn1s!no=Y#}j57RWpsXW8@xc8kO)&>0wmFLbV|^e=Kk zRs+XAIc}r|g=aERSrCoU-Du-BNtf&MME1@k7v!*rkyMy=r$N9H)-r5E!@dMqdNC}l zDR7eTQR5xM(gcmt(3W0>N2KR!Y)T2Eonj`?Py_*zXKZE1{~c}e4p}dkgLd>OJesg# zw3g8>ajUdJk$!bvuhc8tE50fVis2_R#OG!Eeef=E(-vU8%+JoVA0e0iMyF{%bi*g8 z{s6wz`8@?bBN3fH@0H1$9SzeS{6E1k)snw;_QUcAG=MN9JHFsy%`_& zaWtTuX~@x}d2)>ti21T&aVpzOuSym!<8}wVE_rvMg=WHD#5puC3`}XsfMsRSLsDlZKku;-+o> zG%Z_Q@BHE??el`5f@O3FLXmX^5h}_=)P52{<_BdA9L{QSPNahR!F%&wy2gRNN6tIv z+;dKT_jk{^^E2}^3*Jf>A;c|ym1d|5Tq~oC6?KLxYy~%kB)jl0yp5Z8C*8>mo#U>{|uy>#TQ(0L&H*Ytckl!cCRD=BLx)8(SkA6UN zA^qC@ieCp80T(+g__Bgjp%gm=+hRYOVab+pRu;aL%%3 z?=#eHggMK4)u*dn2xlZMQFkhxcp?9ME;_zV)#1?i#OZ8w+$j+2pc43-x~UgbI!CWT z8k=DSbNHdjZmOdSO8}pb9OtJa2ITlk^B&$73Gx>YIV6vQ(Us=GP>o1QbdO{vQmxs- zL^?MX%joE}U9mz^VZE}*Q(E>;z4fpGd44T2SXNW8p-%QItePi%QMr4**3uUcFkLW4 zXp)BLBK;P9a6=r$7@ov8a2Y?qkHlfcK{=){Easi;+_k#Yx&;vlY^V&_v;=0kVlyhb zVPrP0FctV@u)ASOcB}$D1bW~L+J~doE1ZP9WwJNnVUs-s36u38(%L0B(mbslkm zG5%%5RaKlUk??FP*E*fbWck(oO?wQdBte5gf=T)b&A>PC3Jk8W4ycXKYQ%jOV8n(; zUjBR?Om^^I!|0#Uh*vDx%vvxA5vy&gp|kn|KXM>|_1hF2yYq*Uqu&cV>-B)K6> z;88H)D_TQ`=mK4$@6&bq9ma4GV$crZ3k(kF2;NznCaKR@gA=PkXfBlZYLA$9uqN8q z>Cm4^rK96zK9^>Xw7e=r)7wLzZ0ji96r!sila;gO<0)OayIuLaUDM^Rq=3|0D9-Yz PP!m!u-VNFgQ;haM<9utL diff --git a/Trie/.build/debug/Trie.o/sources/main.swift.o b/Trie/.build/debug/Trie.o/sources/main.swift.o index c44e7e0254fa8c98846d9e01de765def37b2da8c..625ca7c5217d193b2ef840d5fe9a49e9ed441651 100644 GIT binary patch literal 14800 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 delta 4679 zcmZ`*eQaCR6@Smohtt?Jaa+H*ty9y6#!mCyq_M?FGZa;?ERYt#noa6RD_~s-N?NMX zO=K>Ac*@mz1Z1LPOi?DFTIf_LrY=;pOzRdTDphEMu#XBwiqxS=1Z}N%&b{|F z=UK{;lKbB8ch2ved+)i|Z|~+4k81JXSc_#B3WZ+rzAZ96 z`1GZLW;i9d(aNd#;$*(!%@e3{OXD|(SbpOaM%lQDV|f9!K6$<-Fw8VP*7N956o zSlh`EW{Z+KnMh?5moRx1;yQUy)*#F~Y{#_41zY?Dd4BtwG zc68nrAND!uDl-vNn6sVH8<8sn3ox@!OwlM{%gg`b4>XarL251#7O1Ss4Ov&yX;lI zES2+6y(-q9FIGOwlus&U<&z;sDvzVG#6<42SNXJ5o+jmor;C+eSys*sqLdO>ZW$s; zJU2p&laa8_H;1XAaYw_y~a!iBBqEU7am@ z>-q@S4I3@6rx&Vm9f{a@*US7Ln>E`V<&Cs)39K8ODJReqXWQ4BGw1 z;m3xChK-*L4-L-_t$xsNejm<{Y<`ZD9UxHxx2W3Xt zs$u^>;g{j>z}n;L8iXqsZd_fMvc>USWKr;5K|4(iJ z_Ec(y2D&E5=!cH*UR_5AfoL)#j_*;yXw;Wvs*or4eR5%U$ZJU zt6BHbdep<_H0$R5v4>qm*8NT)!tt=tgcYRq>DGCtU|-yVfkZ&AT8~C&bc~!ij3%rI z&ENgZde@`)dcxX6if`$Y`zIdDqCP3YAJXmgna0)3gAG=iat&&Bu_$Uu<6rYAe7>l& z-zxHVKLN}1*GlnTR%u*j$Jpy-2E5u(Emz}hty#-`;7WtqSM-$D?qP3g_Ir9I@Aj}w z+g0pan%(VT4`?>8*@r!BR^ zaY|k}dsoxBvf#1dM-Lu9*!+vk92kWj0DW!@Nx(iaHvT@L$cd?T?fFr5y_%-_dL>tjNOsha2Ai7R@^%DPo8PMT$ diff --git a/Trie/.build/debug/Trie.o/sources/trie.swift.o b/Trie/.build/debug/Trie.o/sources/trie.swift.o index dda3f017321c7fa1cf9e09b846f00ea0cc4bb14f..fc047f2cdfbf51fcca8f6f7dcddd0d202f73415f 100644 GIT binary patch literal 107904 zcmeFa3w%|@)i=Czjwb|A3BgOe6c36TFF=r6uwD`%c*LMlK=FbkKrpFDQb;tl0#SNu zPEJn^YFeIFY}#r~TeZ=e8f{afwUFL4eR`vpr!Q@73$>Tjr$u^`_y1orbIv+D=LE#3 z-|zdr_uaqW$?W;hnl)?IteIIed-l$j@`{CloE*5+D&|nn>)(+=O9d|VP6Oq# zNbJ{3B6t6OJFrN6R3v^?UPb(}`~_`S6-Hv^yCbp1dn#h(d&^tDS=RE)oCU4Rh9a@1 z!ANY`Kx9{W7a1Y!wqY;Bo#p*Gk@%*riuj7|NPI=_g0^M-k=UL26|oz@@`kYCb4?NQ zb&?*mok%Y(+y7z?cyC8>?cm>v;#(rIMDxLe2N$#^?m*Bq8no?uO{VhJNIa4si8qJa zDvKiVCeSwISHz>FuZWcvR>T*#SHvRW1#KP7Yf7yw+W!&?Nz?*~#QLhp^yo-jZiKI8 zez7TImISevEJ~T?mF%2XN}0DSIhuMT)EIH66R0kO@Gz|Sb>Y&sJBmv8??e@r zfm`_iIQEyeHoYJk8gyy|3>!=eK+VFRf)SMkO|N3Tso9;jD)vre-j~1=jwy z{yuElYfA~jAyI|Zhv^dWat(%6trnldql*F{<9@mCOaCDG8MvQT%m74zL>KAK5E*9IA%;SVY zEOs1Ss*~B)&R@T~f8Rp&7}h9a*#X$b9>lvNu^$;rYw85##*oF^Bk`-DYNoZDvJ&WY z@nxXL;29?|j0b}%cnl(As})G>yTT3^iDkWH5pQZm&i2bw4P#ltcF;n*q2S#|qTt<0 z1-CeL>~=R@_68&N-7mB58~_*^eWUNUT~9Xh%<0A(k3?TjwG6Tg|w{oMT~e4!=f6LykR5nJLxZCOGY1Cf1f{$A50N_j-{OS% zYHRcpxQWDi+9e)sl~_j$0;^p+8*V7Xgh@COi#8jgh9r?0gr|Qa_KGMs5|1(s)3PbW ztB5BI{|MZS9pq9GTb^&*AX;nKRY{Ooj=&b(XA0U0Mx+53p@~OH6Nw!)S?Dm;vkqmL zRXMB5&-Qs8s|vreIT@^6B4L5PPM} zW{HyS@|bsdtTONNSR{Wz?3+&hQlx-Ui3Ew_B%632Sw>=%pEQtPXyQ@QB;~ipSthE( zbgb+%!FJp!B{kN^#02s(B%7JCUbASryrK>@yTd8{88Q(?@+QnlJuE)FknBVeRN zCZNOssH7}gpq(u3Skkjw>hNYH-a|t0w`5UCK>1SJj=d7}3`x*;00D&c*mdKHJPA7T zCD>7jAQImZmRL`b1bxL4JX#{b6D$c1Z$E;H*q@-tUI7x_5_EJ)(9+9l{{ zm0(8;f=Fyfv&4EDBU*UI`g2UBpBISsA+SHDK2Ux!eRkVzd%|(|BzrIQd5)lL#ajwT`gJKy2Ntfi$ zi^OBaf};n=If>JW?JE@;6r3oLyN+TBdWsNOO=3ohCyZf@7rTmvk$CX_B65pG3saQo zK3N}AQf`@zM)OnjavwQ3P&Td|qe?UnDGOSoqY#X1xx>_fMWJ{mMdl8Sd+;S#Dw9Wu07lR>Xc9dGYm2 z%UXXPiT)G??~y_hyCvutl%Quog1&wP73dQZB)TQ&=#pSZCxQj7J)c0(H2Zb0Ey}z7 zgIzg|GwHAQk*|}OeB3?r$^GkGU@9u-;oto-=jt2FZYo<*c5~TEct>N$jZMw})~Ry~ zz!J;X42yOJXuXu!E12Jhu>Qg_WysLQ%xclD4~^fT{d@5*g!DPC{V*SL<;O|FF8svP zaQ<4-Up^3t{VlTf#r*x36`>axkDsnq(=p;@$D8fwOJ614Tx?~Qh^qh`YVmZmf4KGc zrI8qTHywz?ugs6cuf^(pAy)2J7MV?f@*%8U_oBc(C~P;K8Mt7titFb*a`^ahCZWHv zgHnmbUyBtHtI*>qEg4O#9Sx8#uWLRWgdQ`&l<^+oKIaH9mxG&!er zp)opZiD5v+J@j?Fjb+#zy?^J+?D!0+yw_ z%7=tH&Q-N+HSOluu(NzG#>r)dP!?Xh&{YQ_u`)YY#CD-ao5ht)D2&7gVCdLJN{xq* zM~Zr`2!#wEuhPaXfBU_|{WPwxxV9RQnRinw8nGp^YhhSw8|&-j>=f(Sjv$McqV1`) zKAFCDiECrj)gxXGdl}Or-Qi=6MBZJhh<#!SIvNnb6?*`xg)3&#q618eTav_}#Do&+-Yqd{y-56$Nc@F8%o^*fB_8{c z6|t|&kO{+hhZGi1urT;L+a*m_rUwV1=3d0DV*5xU_xr|)#^|ncyN7#mBTog^!=~AFWsomW#)A(;Rj*5T(0rLYUZM#2hH>}T#*cF`XduH{c z9PLalN^<|l%ug6BMb_tv&?dwCe4JB~Srj`DNA{QWe#mkxIbni>FhxwsxwwU8zIm{H zKw25QvGH=WMlt-JgC7wL`#cd@ZF5IxQ#M#;JFL5B4>k93>xXA>(cDIZ z@!Kj)_pFG&3qrt5C8$U=b<^zFlVWdH#G6ob566Ov*#3$*2b~TM5EZe%SHx>tU>NLd z6|rAb#Gf!!QFg+`vAq?s1bgLTB*o63ToISyr6Sfi89OdLhJE8?>?HRX291;9Z1ot{ zjg!N;m(C3OB83;@Uiv!l5`~vm#FkEukb5Oi>Vo&nD`GcIu8QDKZ6vl}as!fF!Ogfg z1wS*n1+`D|dS-H~iJIb{ncSY9$_FJNHbOizxidYri_zGFlldg7BKFK=F3dq~1bSw2 zzlpkn2P_pg5J1J|WTxFFYD9fz@*Wd4s(D7Xm_Y2r<6MWROFdwsPCPz?Q>l53LcDwl zpP5`}lAU;AfghS&gfJ3&XtFFAV;`7Y!Z_BkkS~I0spQ&WYVpwIh@|eI1k6-vh$$b5 zmoo~u%D@ziaIJ+K5K^LM8*h;~8bQK`Cb!#gJHmAHmfZ}u=WKg-0?!@d+}-95^{W`+ zTChn$wQ{orHDE<)33-MUm**J009w|4ya!b5hvGfMpjfmhMU{LECm=ST+27TgD&;@; z#-~Y<^zq4!BN;~}zds@C1wGz%H8t6qn9iSA+#PXqu#5^L4glDfz|4plaz#I9Nc=EE zF2f9Ip1ooS8p3RfvF;VCKDW4o(yJ@Y%$|E9S}0|Ue}Tyhm8cboU*ULRs>2DL&ur`-Jj4Zn z?M48+!#q(b04aE9`zq6f;<0?SDH zftxE5#@FT}${y07X;>y6R6;>{sZ4z-NfNT}iqdzJ9((c6Lxo6 zo=zZ7Hx-h6WYKG4hEbxQv6yVETSmU-=n?`pM?Z^>cd*RVbK^cGg4xZ6RLruqkHHZ< zLpIrIg7W;qN(JXUZl6b#n-+lfS%RdGpxu3S*kjGykg}cF*Uf6Voq=S-btSbKkMcee zFTteHX=tHL-W}ZL!SR6{B*3Fl{7p)0Z{*ntwu2>K;(*Z6OxmLS3qFLvp&d18jXums zOrELO{PI+ztwR#-ewp)@@>|mOC%OAD%;nfVE*gckJ2xf)mnwZ%*v%s1EL4oN^01UK z9y3_c1^2_cBV4dAhC4!w=lLESnBn=KVXhJuP*_C44Z-@*Jf6<5KN;T=jzkaQNQh7j z-@lAs7Dh_SU*rB$d`lr*O0xz;8QGqHLpi0OgJjN8;=})(NW6v10mu#6S%<}T7mEh? zLp<=2-6ojDK|C90r(V!nzN>YaT~Nk1?KbvTz7thT+pp99MhS*;SWh#DYii4>C^MNw;G;lg(`HY^PQrR0?O;By*1tVJ1V& z5XI~RetF!_>=4mr|F^g&W`!X$9cB%gzwn$(lkN!~mw#45MQ|?J26I-JvB7l3cRNNCr zFp4n=*0UQyTL&?5PxeTnbx%$ZlGK#kCXAGOLLR0wMM-Ps!z2hB&I6iqPdwpg#!oyk z#K;Nj*o(lLuaKMjM6{p8@dT+Lrj1z+113!dV&^^JCe1KPbTSr`88LIyv>d zQX*ZI)>QSxRbiYHin9k&9!k6WRvf}rX%VLO;j2B{Abv@+Nq`=CcW_(S_$7v3PCHmR z%*h8lFWx*Kb0y|8xYan?DyJYUiF@>{Ea+)WllGv5xSXvWw4c`(!eaNLUbI*c@D`31 zn94~CSM!t|exnt$sXb+(__RgI4YChNAjh~`qbnJ~goMD!&il3wNx1uE&Z*iL^6xk6 z`S(CB=U+^lvJ;23O_hw5a>5&?$zc~ggOA_&&?DAkp8sR^w?_bY-ixOIK+C815R0b( zj96xi3Z!Oglf@z|Q0S7gwK*+7JK=!=5O*3j+mmc?qC_B>t%V5BUWmYolSHv-SVT3e z)tHR@RyqHc+1ivAZKoW`&4gBwle2Y;+;O%R3OrsBfO9dEpsfZ3X0~Q7%+|F6kb+5e zwkGJCt+~igo2H|N_k#3YggzF`odawvKWfTcBfAJjNVAJzN;1>5E6O)b+wB8xg|@?( zxz8)x2Y84h1w1Ib2za7JzTA805~_#nR`TPrm26u=4prHEy8*)o{l;?Qc{u9B9c7Gy zY*(046#|#Fi%?p_qg(U~7$x0794Wy{b_K^!m91OdldG_^!~Sl>VMK!x^e`8@fdqY( z5_Cimv?eaY-+gP3g=o9V`ynAk94?QQR6oV=?N%kswgish8C&I+2dbGbL0<_ut%DdYZ_qKl1POi}~Qd$$I;jf)y2}l8LQKH5dNrF%ed8H=2e8f=2 zJPD#6(_+yB|40d$Dmvi~@R166cFUldupIW7m|zL=Fl?_kyZ19~$Qk6tf4x>!E%3%A_GNfcY~1+Ua38D6GO|c4J)4Zm{oz1Lo+~ zAW~X8Ud7*WEnP>`h@yl*j6Q(l>IYvGxmR}HpjA;@hi7JoJO*~t zKK6?UUUo@a-r5CiB++NG;RsYmx0HfYP*HQ2=n}x$p{Zq}Z!gQiFz%==S+o;?Gd*=5 zB|VN743)CfsOzXWm`65S3B zo-kw`k{63sW}?5*Qzdse4j46e9m@qkvm}Jb3<{i^ftwkGcbGvU0&oW59mfmK6?xo( z&gZ(WkgGN~b=)<%nETCm7`cPxkf^jGwvHRnPqYfKZgM49wTo3Pkg0>^xD9Ai1f~v_ zfhUw5REcarbE;^84mnk{B1}ykU$HySkC-{bP8NKuW;Pl=Ad?05#Z8qTn%s}<&I|^i zL3b~jj`z@WMAz<4roh=0J=+Hp_K*igIN7d{QeAZ1sG$dLh_Kc04`^(<>-q;}=(8dkyVN09)JZU;*(*DZG6W@dP;& zry-Cx8-F<)xr+8;nx17ev#nduSg->YlXX=e-(kdlNG!lLXA7!t@6CyRcfP-)l!~!y zapQGkQd|xYi~A}GI%-J*O`5sXY$Ppf!DbR3Ty1K{?%Q_k!gb;aL>HTcR0+Eo&sDxL z@8l{!3}#s67fFyf2Z37U4?zQ1<^Kr*R{7tSRX!u=nM}fz)rA47t%I1X^1Efcva9?* z3Q5l%1X9;FVWd|1je>VCxRIGW6EX#6~} zBr$tty~tvoZFJ*~HIX3NiNLf>qEFUsICgGQOe|r^+oh&9SAwg_owB;cB-caU=%tj( zvXTSeII~nGxkM$AtvhipP*zefBRW{MOf>5ySf8o1JsKUQCO86u1cpFO!1$L-hMw&# z4v!`!=xdcA(SpDf4vQxg?;#{-eiO`L6Qe>8UqGAylR4Uq^w$HgmqQHRqPh1--bA4h zu_2j1AqV?WGf9aHXBpMStp}N$Z(?p+9+!lDwJvTN>F`YgNgYzof;rO7hVb znulA;#lkeXyC6~7T_`dM&?D~-Zp#x#QRtn{dojS8`-FL`2T$W&xdj z7VjWA%(qZtX05z+XCb!}P!VRA@G0|7(98)A%Lvo z8^V!;J4?s4V@gXL_#2r-ha~9Pi=ec%@3#oXwQMy$w5*?C)fm`_6T9C|~K!l)9m!+@`d%vl>t-P1r6DBbLT06+{ z)=?zwZo6aA4Ue}^T0EYRrcSo;a?!M1Y9=Cx;R!eX;_)<7;t3%@Z<1I~r3A9NZH?{{ zxf8t-baYG5)0Gk=u}7#o2t{J!p*KTwHC1SGU7e5ZB_!iKbs7DG0p`GyH0%he-6OtL zF>Y+y^R!Io72R2IbABgnseyAhc&syY`0rQf{i)^2{V5(bK*umUQt}cDY~SoG_2o%3 zbAQT{JMK>%V0GlRy&>Fzmg^9h92H|)%bbJ)X|b?Q$YX+dkI>0cR_;ciyNN1e(uU@_ zlIgJ>qA={4CmG_QH;a$UD?QM&X@i7e7^Mvy9GrPj_9?E0QKTe^%PTY@m3w+Fj7%l4 zpDv=?EsDNwiOCB#t%=7F*;hMGmXoF+yf?vW^W~`RNVJw2+SnbO=Q+8~F#SYNBiNq@IR?zo9&?$jn4iO{4C2+R_QcWIkwwUXJK zo|9Xgo}=dqci5cBX|||a5SbG>?SiH~^1^z=lz)>P(lkZ$kY>EklzNw($T0=Vg6OW{ zM{!tMRX z$&1FKU*RJNw{k#WKqH@FH_fg8LM0o>rCc+yiqZOPR-(f%U$eUnwP!5 z=l4oBUx*C?_#JkCDU57ZQL-5q!9FPtTW`xZo<=fx-$yx8>YRltC+}TOyT>XJHnW%# z>&TNJ;i)_(#l1sn2;?175}=Ss8BTbRs=UQzL$6>h3YW3*S1@ZK>h zG!-V)8vU&!YLnZUfPMq0P5!n81j9fa+IJn!cchiS z8`MtWym#dj<4jH{COdbQO5Dytfs<~h-PubTge*&OtQR(fWoh4lVbU)_q8EWHQTW8& zo6y~;i{SZ;ts}z4LaYD%p3_*gnJ0wmCWo8vdFQPNTP3#nXyPfCjo(S z+*SGV+!q!1*b}zO>8>Mj+$FoS?aq``vU^BX$74fO^seY`2!=b+Ic1FP!qG?3|2zG580kPkc{anT1%1fj7S36Bz3)`i0l)IQU-cUp`(^ayl0SE%zi@zh*T5D zJ(-ASl|s{DxOWIE9Hcdc6q~f=CRQRD5|t9`iAc~_DuHb8*_!kT0bc)>6mH{^)KydH z-I~m1E=Iat&F~gE1|@GIEG5c@qOEIBC80!zq!`Z0HCYid$^6IMP8k0^zQc5|-OdQ6 z6tn$^6{smQKb09nm))F9ep$c}$*e#^&I(e}zCB!bV6b!b+{-z`tP49af*75fa|<{p z!bDjYzGByfdBRL~HsJ^!!0Hm~!Z#6&YZ)yAwn@SvL0N^ua62T6TNm2=dy#52$y;br zio)|Kj$(Mc1JG%*i%_CNQsN0u1hDHul0lQZ%I+s52S#(wcSagfQIMA$Z7Cr=Cvb2+m9_~aI-70)6J|A*2Z9Pj~x zIkIlvTe3DK?;$w*5*?V2<3RUSXfIT|7J+Tvgg^m}m9o>{K*3%_{{nCtV>)Qr0q<8{n>LKLV?v|L49~^9X0~~g> zc6=0|!eq1W>`eeLiV4Y*`;>t&I3~S>k?EB{!_v9~0ho`3e3?Sa9m16QE@%u&Y zxIL%dK}X|oe$Z)?04S;>y^yqo#10yXmJ6bv>nZPVLD6uD45_(P%0`tkI zumJXPa9YNJUJJI#k4V7++%t$CC zOax67$q9TDo%zk?(oo-Q#hZcgCGdpHSVX01h_W>${H zn5@ls+acp9Mjn8eVEc@-XGq+$VMA#@0cSI~C&kQ%fvX5bl(uayD{Xo6VCnu{TE=157*evK{K2_`9vhod7*ljcqq_&zNL&U|jg+|O5CWMbZVlvsIM5qL*N za@&{c?6EhyxwAc45bTs>ZeT#~l5J6EB2{c$^RV9aJ1OxSGTWy!ZB3moE@T zS*G9>3kebp$vg>q`DW|Y9PxupsZ^LJ8{MrWYm?b<2$r1e<`l(-xB|h@QdE7C9pe#+ z@#qT7q>B4~Deb_r@!~#Thl%wq7aGhC(Mq|K%|NRVlZb->Ou<_l2waLGw!3?Bln%yK zoFcF(_F0@gS|=~vp@Wf*azPr)@87WTojhSw#M10jK^$N;u_4os3mL<5%LtTjVgknc z@&x1-xhHqrA{Snm(`DWAA^;{~**yfnY>_h;w#fGiKnf<=bEX98o2xByZkC7X$`|nf zNipaRZ~r+{7R*%u&zYJs;q!yq2x-olnv#;PKRDyWh&v@@-cL=P5=tI0WqI5)?}RmB zX<+0}KVXWzc~K3R^@7UTK&t(4s8G6&-4>HCAHu#pnwxuNuw##?yl1b`{2ml*7{#Ky z)%{@d-W?Fah$42*9AHXf^cK>kHgovB3^f&F{YR=;N52Gm?@vwmScoCn)kda!zpq6$ znBB+*vs;QhVO~Zw?=7O70jZRI-?67V$(CQcg^z)_8&D8U_D8%GYn={!1515J6W{ID z)o~Jb!3NxYx4Yl>ec1!B^O}7B23@s8W+eFz1q$T+gjy_@z#KY{chIZHC+J%IpP=g! zVH2GabZnQPr(J@+Rs`H+k|5D6K}UlGJ8BW&6LhyAFyD9Kot&~TpP(aOCq4PNd*+jS z`M!&$qR%2J`+l{bZO(6@;unvL zuEiXfRz$)sFOD~T5YZYvpa|T@LQ@0r|bC6E59a<|5cFu1jn)g)MOAf*^Qd)K@Il~|MbRondFo2yr#d; z%J)&z?6<#ZP3lEmtW7dZ$`vLd%*|;=axQAV;BK8&>3e*4ORRHs?CiXpy^IW5uZ#50b9X{jK zXL51xa*ga=$~w;MU9OS6ON#FHE}3nFy~{OlXRu3&y~{PScWFAgI52Bu@6s?AKjx9i zE$CQqPz?XW+Ph3n1n4_)eC)>j2M4=7l~{~rwtdW@p33uqD<0Y7KV>XvEAP|`DAa`u zC<){=G?qK|3vT@a+V!I)u?Jo3*L%&|S@6nQBw$TD_NVvxA7qrCfu#coTU}Houj~J6;-2F29 ziyC9y`}JY;p#ylo9bWAQVEDJ)vVDIxeicNfyjWqT{@VnKZY~sdlmSB^ zza^l*cUzn`9`n0#+#!A>l;gks5&)KV0CH_HykD57 zBl)h3*g_0V3&T+2z))n|Q!=996UzJ;3BD=-zJshn(`lyYou+8)U%L+?$`@=g$eS-7 z6!U`#{`n!s%KmOYc^|MVH@@<=>f7LbZ`&ca7d@JJZelHgd>#RE|>9GB4oG*mD_?WR6YLn?Q zB3*oQp|mP2#7Q}1Zp38W_mcrs9D`uvu54y72AQ>zZo3wbhNdui3DneuL-THO0Ft?AmZJ$ zud-pS4I6COY{M2Cw%V}WhTCn}X~QlXcH6MmhW$1iupu|eczg*L zuGu)P5s|4v_V$^0Q)+IjYn)QQ>OGiR!bdK{ZPj(_jSS%_4IAoitKRUwDQh`19XZQX zwcY`ftD9u+6Of5-YM>+04wHBY%^eN%YKn!1hE ztJc*}9jm9*t;gh7-w>X1`4N;qbyX8)%V}$BRyExs9GW(6n6|Edb@jSwb?ecDYihz% zkRZyxt$s}t3SCpbdP+leW9>UEO>ARoy)hB$a5Ls_SkyYxJSZhR<*N1d>mh(GczyM4 zHDOv*x;+1WSxou1)HO8?HS5>ZtY2MMv+>`ehpB69NgHa`*1(Th4VC}f%am@3Vm5}S z)c+4P?C@?swLUy$Lyf^aUOk&b$MbtBYJw{bQ4Y~A|m#`+E6 zl{4qgDleWrx2$YNN%@T8@&(h&X3w8DbIyV}7zS+dgJDd7ZKzIdsEyp^jt53F2Oy|Jcj4ZP!x8@-hqs_(c~ z9B-D|;LX3Pq58c|HI=s30I%IReWo8>P3N&}{hEdAs&CooEpu`Yqn)fB|5;4tm2jMP*&%xhYUzUt(ft}uvMV(V&%F2A;V!^Y}sH_lqNbm8>bCG%0@ zvh{V1A~WFWGt#J;w|+x4%2{$-^*T`n3}nVi@0xU3P{XUP-8gr?TMSK~=_5#{P)JSb zm2KEiZB)9XI;jXQ7?vz4sawCXW&_qvQhhYcOoPwaP;*=T?FN>a%hX)fX|n{FzhtE> z*rZyEl|D)7;;wC=@#Slm&TF`4-n?s6v!ThB6t7&llm>*d=QSLXZl!mToh>h67Vs0n zhO=jvJ{6pkz(;>ea>7=Zwg2-MZUv6Lu-DZPx0V zS###hm_1|e+?i|F6jxUluPvEbJa^UV*(EdQ7N6r?WF)D(t)ZSRX(!W-RM0}zF00or zoxa+PDATEEYJMgDcy%yNAMN~XwCOBoa%sMH=}L5J-ual!ZfaPAL4B<$6J6fK{Zw@u zD{89OlFKSA=y~s>mJiBhAB}3`v-bXRFZsV2pjhe_teRSY-4c7LqK;HW(rcYnr zbeqTwH-dC^o&tsuyBZr}42|gnEG>e{bqsy^=fa&{-^dQLcIlEOGuNS|FlwNZNgNp# zSCj4B)VO_F4JHjv=fehYZJZ0dH8mORa1A&%&Z}2~a72M6iyfqlktl370}9#_4r$yQ zNzDb8&&Tep4<%sVylxnVms>yac`_HgO0U9x2QjO65U zZC%YB{zB%|Z7jd7q49mrP$lBi;w*71jETyvFTDhI#~!f}Bt{>!L_z$NtLrg8W8Pw~ zUFEr$pQ>(SCEV+}=0jB8k@>REHuIunruq10N|TB_w!u>7p4G}}O0&(Zs<`TT)+G7_ znO@B1Nmj+GCWToUvP{g@aIUH0gjO@Ze%(4OuHo5aZqt#>Y|i2ENSW{jmRxN8+Tq2` zl7uAvEHQSD9EV+w?s;>K>dMxwgY{rQN=ALkG$R;W!qCaU#i);NfiG^lhnh=8>&lUl zxS8kNt)lk#m)k05%sAxQW-iT6HgYkjC-0};h8cAO*3fl#`i0*34!B~H^i}zmcfbuD z*T?O!YMdHn&49^DbJ%{Tb^K9bBdw)f>t~KzU4S z=fPzBoz{5-&PQ1B5je8;tGxy+8`rJ%)?)ziHe!K{-QY&A&f}8DGy8a}%zhBI(bui2 zUVW?E!*O$#%-CLiV=eZK*4Nx|ot?_O)lD0)_>x7GcWcf2ygRUXqL*3;-s^8^ti`<9 zSe?~hDp`Q(up0ZtB2u#<9_F5xtSnzwb6fI3IlUpc%iNtq3vHB@x_O+AXXdwg@AcM; zup6(#28Z!8y~f)boTS4Zh~;?8{8+%dy}^&=jL$jq*a@NFvH7{D9Q(^H$NqZD*zq~b z@FrqlVovbbmb>s}Q!)fiVui^Yoc%(a}@AWUiSKa= zVka1Vj2(N-*rUf%D<__SJVEHLa5B_$$=I>LPNJr$M#*yWIK({flw&~19H(CBQDKEB z>0K9k3?`2E(pm;Bx9J45hP0qLlQ7ZWn%*}x5^xdsq#H*Wawg(MCa4Pqpz-)8XQE2J z(Ihv>5!>O(qfPRVPKK?dUpd#hcupRlA?J(=Y+Ft!C+`##i&&+JU5!{?U|Yn*v?MMr*9k>d}Y z|D@5!=@L&mbdGlkNm51=9Z|+fPR3@DaS|1Z{L;yDCLOxOGlc|otd;y{Qc1{fYHSim zEdQMJI-Yar5~qs9$vRFwbdC$sb6jxf9JAA-e;+9cRD%!Dgz9~#Nr zbJEqEbLa}?)L}GAb*aP15nvxm

dwf^6XE6M6%crMCbg`h;&bw8cB5kLOP4Mg8m3fKtd-dG zvYo#7*7f(m{Jj0{-MjslZEoEV{HR~Ka?pKYV#1uAJvm@6gUI#b z2V3WCZEXz=hgSbg@?A`LkbStSs!G)0?Sn^;JXaSpDk@I(uL|+q zUW@L{{@6yQpui!%FR3p;zAO}x)K}^Hd$>O6&Ye5RERP>Q#!k0t$3A_!G@0zJtfVB? zy_})JkB>E#aG(5~*nQ^!Rn{zWt%HNZp+kod&!0bkMhtSbu1umN-H9Wkkyj!qyO(H2 zKk#;sgk~OEv-F@h>HuG_&X+|&^b%3%e!P`akLC=63)mI z>>YOH<>mWvhPRI(Rp3)DCCOaAdUbhzKL5=ddOAAObDxef+2H2iym@2sIYA-M*5S{@ zr}_E$2M@@jA1QqA>f+&w>H*_>ad3gZS0hQ>&!*+>Ed zh4RX)Si5`u;!pS%O3av(`$xWY|HCUGAt5Y`qu5qoZ}M;E$KAVkg>tGZD-l)W6%`fn zC+w7O96xrIqQhl3nAV78srLAibtWLp>lF^r?)qX zVqzFdnB?xR&|o+wuwYFZ+(&|L|3C_L0|M20%j~GM;s=cc-G7d}r)z;Aw z)+?JwM3(|)W_3hiIxMM9?zmHFk%n$o2#}sK_^;`W@i>K)K$W)8= z`S56$ih(fs7+Gp*>2h-$BRIM+Js@%SP+ttv=FQk)$mALLUq_msScyI0T_pfWBF z0k51uIayixMMaLTu3g{1PuMeC9_{&_d*jCS>lYKGYTvytEye13 z{JrJoCPljY{K1_P`Q*v|0|z2wVk|5zr%fNW5QfM@3q0JG~89gBsM;-|yx0>5`&iJyOEv<|c!XZp}04iOI?J)zw59 z_l~Bf2cGw0K7Ra&F!1;HFDW_B%*>3ECMzquQihKTF=>>)%FtbC_LXV=Cw+G*OGI!mfKfLF_Z=I{$P{|qZa@aNuHAfF z{13{d=klD_#!5j+Nwho%BO{|5H6uU4ZFB7}&~lz$d0Ixsht<#4w{PF5aC(`T*#D4T zaLpT0>hOD@3Xphl@y@<|`_$Dxt)?H<_+nX%RQ0~00k9kS8YkoAsZ%3CgZZ~@Y}7C8 z{0JR6lB)Ug;lqdj{{2J6crqiGck;SueHkCGz^%Xv4>8|xpL#En6l$L^!ut{XmS818 zo7v}NG=TKEslLa(PUTj3EXAv3boBLEwk3C379%gwsI~0o>2SWcrANr##ZNkPgwXr^ z`HP6=Od8goKYykvaOhD+ov(8L^CCO@Cn2)AzFv`M|KGoVwKO%?Zr(I7xVN@s<>~2p z^=g;k)x57=U5+^~u}4fyOe939+rum@)G9pt`7XrH`^e$(kZ+G4M^ZkP-u;S>!tC$Q zZ`Ipd(oyF#Xy|a#dG=e?6lwy7T;OGA`sSNfT)fm*?uaUfhXwxGTAJ3{u0DSB=*s$f zOG^vQgSCSP4@Sqt+8anoCf$fG6G;PD( zvTRco_V%k+*V1A2j#OxpO3BP@1Pp18PQoV^7A_`Ay8<_>n0>RfvI` znHl7H%6(zvgX$B~5ql|}yhHpRo}M?~-JPDCwCV~$Y0yExWd<}T{iups0)7)bT~ z$B##+q*dN_yh=}h`*ve0PhYQN(c)6_K$&OP>s*`nxs2RQv%2SkUq>FGeBfu#+!7<& z*3$B8dRn271ISH8SlBG6@cjep?tD&Z>BztgiKv}Wd ztckbY3uo@i*VkM$P$JR0u22?qDOoPn*<661-~J9+sa=YE@5TMW?++92z8+u!z(+pE z$WKH}d^x~%VSc`>ygW4Qs!1PHf9Sn?FQr(hLZ{Ey4VRGa4)th>eDb8^{JGRy?gt1( zZ{7^c(+soq_4l`n5Zv6|OKtl<4!Zy#rhPlwFl>+GFc#>0=KOgI8@}6)c*=o+$HQM3 zVp^S3Jl%B-TW_^{R=Xb+i!n>kKh1kOuZpl#roPrN^yu6f^Nm=GN`{Y47>=&{^tZv<^yF&X% zzWv*`fK)>Z3kyfbKT|Gu0OtcW|LTcpa14H$1%J52#US($I417r&szZl29&$$Jv~*t zD%rX^{S@LAQ!_I+{#Z!$DVF(WXJ^mN*;=cO;f)tdBF|?S^LO|5-T;}aNDSdQW7DLW ztm2u%FCb8NB|j&Jl1X1AKskNEP&2A-m)OsCFYOCdLxItX9Gim*LSf>M(?9N7(z+kp z^7sQADRc+r7}jvr=XcnIZsvx>#9ZJFTdaKF7B-y7kB|)ua z!Qs)-@%z3+@h`+rpRWFnV|VM;t!|3P9?6R7(n4U=$L`;^Njos8!C$^pkkJFRUxH9TV3N9`rcIUIssB@gO9<=YjvD=XrO=H<)2^|Jngf%I%_ z2M!#dY*C@1p`kwUt)YRmK7!M>X?}EaGHAFdoQ{E#4kv;9O%`cu_`S91%!PT65EF-x zll&jVbH>MCWoI{}Ni`fl*W7fYbm)f$`Lc$FhK~YEdTOfgAB1*LiA)zI9pig(TO6W& zEG!`(8S3imN9X3`?_x#e)amUF?DT!YG{P|m>4WW$DwyiXDK)_8524G8qS8|4)_;MXR z`c$5Sqx1$yp+TRx28)zEAxe%kSm~7GM5~nhiG~He`12V|w{9iT(y=&XtOSLBnR%&I zE-+l{JKHUoi!cAA>? zdrI$;anOc&%X(FWR!ZACId*L`SX{c4@a&nOuZCFbZaTte^1XIRQVV0_Er9lpIy&@v z`U+(aK_^a0Nwp@)#yi-j<>btCWT%f&nSbYWou*^82>$w7+c*#$Yb`5~m|hPFrI1{Obz zjEsQ#=VoU!+AS};&go{q+7{sc!{{SHI7Q$m=Gf!&jil~^`X@3J4hIL7$1KCy|EfKg zMfmyoMMc{_v|6Vo^syQYh!UI#8pJiX3IBp0wQ)pVVv&+>Q%{VHl(gw7-q^TXR&n2c z59peMy?u%XzqSBsG2$uPP3B&W+j$OJ6u>8uktzj=DD@2u4Zs>lnP!0uadyDFh)K^8 z`KDxK&@(VJ25ef}*z^P70@|9J^YZbXsPPGY^eD1<3>DAG*;y9K45X{R?_0kItJl}o zo~SQtf1Hwui;8XJ$SxE*V-*uRbfdb=y{tdi1Fc?fXztE;c~ z*VR9gyPLJSl_<|)c`;#XY}CZm)W3dsWOP*R{CQ}bWs`zqlat9(4kI%^iU>X^qp>$i z2ddpJU%PfhfGh2Jp6%%L$=-$++g3p%BO@7VF>H{J*jPp=k08_f`hrG7P`GmCN^Drh zV>QT>US3|)ho+~KHC}#QT3P~O1s9nZ8)IZ<#*+PLY;64U#oj4?t@G09moHyVPfZEk zD9N!)A*Z3)o*%A9tUx5DaCA?!IbQz3H<4&t}d0(Zh$f{S|*lK0NyR zRhx<`6lBcP!=q=3nIF0lLPq(pHN%&J+s;3J40s%$NdrM~QCO0>CdE+Z5L87WnzFB6^$;0CxUwzrd<=^Y-ty5#kwuA4gtU7tiGFzNY&CF(d z-uwcD$>LQ?&(oLVv2>m=H8nLhF;P5oCeNUXg5gF&ZBvsaSUM1I5H;&9OH18i%Lw2s zEX<=vkGxx{ry+Y4Ted%Dl|FjxSkPMz35h3vf*gW)PMkP#>eO24;Jw>+c6|GTO$tg6 z?BAb|kU;7!!o{@+{!p8|zOoWBGH`M~9X)-}0o{K~OG5noZp(B1y51@)4V`P+1VedPT#b*w^ven4?SjfW~RaT zDzN3{mtQ$)uI<^om*$za{DlkFBkzNujm64&opQZ*!`g)f1;HnFcya{0-mkW-M-^0rKVqL68yT3GDoh$5AG`gX<@CL~7i1C(vrXH-Z6=1tsGay+1UppxK(gq$U^6`fEoX*T46)RAOQx_67 ztWc@;?>`g9`QY(mwmSt)o6ny=hm=FJ%2&}2X7=ghN2Wz0C=I2eSd-ycBvGV`$AHj5G*Jx+$r++ckh++S|bT%pUiFl_UbB> zgQ2OZm95Qn=U?AtaU_}|xRGbOJId}%N|%B5bE`ZKDJ!a{dN(e7qhw`u_3z=QUVkR2 zT-j<^Bc`S-Pn;;_+}6H+9YKSR%GdsW*)hht#>UB^p_(_B>A0En2{q_5P(za8{Q8uc zvEEnvDAT95wl?I-Z{MO;d&-3C0s_do5$1qCF+$hwOnu>WbaWKiII?%|UZ9G`z5`{@ zY1GtOYLgj&?B2fzxeI>y5J8!A(lL;EY2n9vQ1)mM{ZnZ?drz!HkB*K`H&#q-fBO76 zNydFqmr^KG^Cg-Qu~H6Peo-O>LmXk8T6WEQJRBS~U0tqHMY2DYm;X$*g}mN(;6N`@ z3eM3*9KcYKN!>TMqRPwN2L<0#>P=Z0*$CLt(?{W{A!=f|PD)EV_Qrf_Z5_LA(PfYO zs`B1`*EZEbA7gB6+|k+jrnopEF%i_L(a(cgack|D=&@sOpt?VH8_!yg78DS`U%kc? zy}J~+S83!PsKlY?f^(7;OE&$Sp&}8gPoty3sSosw`6P%}AfmYqCPqf?{FzX1&_}CE z@JE43P(lLBE22i!in4j>!sGLdVU3Lq4bTPAROo4I3w!nMWm(xutS8Zj_wRrH`qhi3 zjjRXVfdg6^8e%B>3=AJu_O4D#qrtV3Df*@jYbPJ4|TJHP#wI#{61PGqxnKL_uvv&g(AzdX*w^GUI zgvp&t%PR|`Xq@H9>Nf^VUXzxVzIG!uKYtzt3~&V^4H?IU(_)Qb?5>WEEp2Us#a3F^ zulGP66&4b@NBd|U??948E!!3B>GIX91)&ZFa=Lm#P(*|`vN>xp%aNun`E;_lNrS!j z?D|{}n#% zwRRMxMoOw|I|!dN`I+_8zUH>JuCHHNY;9GpHcYL*4hf<3QyfOKg_4G5vhMeTyXjsZ z9@5jW%dy*@P>&;rEbZw(Y#(8#({v@mp@riS8QSXg*^h{4Xz zZu#$Dsy%xY@~+A}bZ7yhzENt6*N5iajg8a%{OWaQyc=$`dofoy1x7Zd6j`>XAwS<4 zb{!iZKg&3VoaBhij7L6`-f|G=u`N-WVc)*mJ2V3;s%}0wMORif~&1=?{mJAn8boqIJ5s z_;{r6Uevr3FOGfVNH9exX=PqK>#S-==hcE<;Zbq%LphQx%*?+a(jHu|&dxrssrkg0 z#@eUdj3YuJi0$GBo0|vRh3FFzTS=#!Z{_5$Hw3n$_qDmXJc$0vkC$Yo_!c+=@52$uA@l-(eSIgCCXw%>G^gX9LGHNsTBfSA)j*pKwX0@B${d}+H zJj2E%EDbG%d~8%IZjurb-wa7y~*5CyrKhLz%dqZ&-`G2K4vCgL|&k zyRn(u3EPeq)d}0ap@}8#@OBR>22q2%(D@tcH^W07+O2}lpl?=YnO-2M^mnM%Zy$Fa zK9)?WD#X$W{XjiEy)prBLLf4>k30w9dq~o0G%|#WOG`b`Ekx_tJ%L9ue^f&#(td>{ zH$40cf(qwkYh{$i(u%{2CN(*EFiF;P?Fk8oh4$T+WH~R;hF+|O{msn${P4YRXd-+} zE5xLDpB5;QvU+=a=f&A@cQrEBKxE$l_`iRj$kOR@XMaCLz$&Bqz}ko)>-%0o#^UvL z31sBM$Wgruc@^I8IRla z=x%T#u|SoF&d8|O+1Cdd>Ew#zp+nEmWo=Nt2oe2N+L3~Qh!OiT=&qhX=6&uQ0iL0@ zc6P7v6Bb6(c=2`7UnL=PWi<^awC!HJc!8!mWcV*XH<}VodnYNUgSZ(9es&++!PjUP zeK53+yMi{#MS+Nw+$Nl8JGcB!nKWNeL*_{;b2Nw`6zhLrYA8a#3R zIAcn?<*O^Xg%ElF{hQGBMENKe4wDU4hStrRJN^R8i;RU{hq%9_d;=NE6DSV?hz$9YrVJu_Sub8F^F}(}xdTv#ny}L+DbQF!uMG7b&Ewa4<%>u^ z=+#`oZ*_GI7MPHg=pSs-eV(6h56W{jPp|gw)5rDi#&LF7Pv6_6R-EE&gAICv9cTz#UDKc$-!hFKkzWM4EP0c!5wX-T38uK;2#J{>;PYxtU5+}%c zT~|;rYBD^$Yu7G`XLmscnL_`eoow4v9NZsjg$%#2a7g5J88BZ-$v^y>Rl*K8`S|gc z)XAF&6syh`=qDAvp@N2wzg4ug0|EWm(t_JdJfG3QF&c-~D&B-{ytq~{0w(ep2UPOL z@8AE`2hoIx;sDs4IYYE~3w5<@jKLjkkho*FmET%}bAc%Wy6AiK5Wu1 zA#~7tg+QX`~gl+C3bmRX#Oeg!y^Vn zlBCuiKChPTt#!L|=YnxI9{i^El{XB!BTWVx{xTzD{6P%Wq=9l-?p^{p@`C*^(TTfe z)@zKL5m2Pw-1=r8)YveaWQ&l8KdJ81Dg+($;7fYSaV9$~?yHJy0ipxfOVM5%8Xktz z!nf~CWqEmlOV=uvA1y9c2jj0N9Nf1yPJaEu7{em#p{=ZJ-kx^$!uR@uvT;-glqc?p z8TQIJMx30>SFW(NpCk*^Y>>b01XfY5^zcx;Tm#{4Rn=g%cbo2R$G5Z7SjKdlFhqJh zlNNkq&xKfsNk~Y(zrNY_T?G5DAh^VRFzFGU0p9e zC=qqu*~R5^Ypc?og7kDOK6mz7`THuI)^^-6XL(0YPh9QI+?*WRHD{3ePgFM(7P=Ig zx?bP3v9SU8^d?_k#LA1kue`Utm8gCo5~UATgcN}e^goy9^h+*!?BJ0!EmwlNx;hAv zxehVPm$;J~I-`j9;ST%0@c4L75PvL^z< z1?Bp&25KUu|QSDJJWkv&I@58F9u}WMyRRj%U0AZ{90YLHH8}(cDNK0@O(@XCi}k z2$-7)`gAz>tyFq&dw2IruU&P3zdw43q5V|-Wo1$ggHY2PF-u|(pRq@>39gnhAz`2 z(Ky_dPj8O~p~k62cF%u)28%#UOuRhX8zfeHeACS6wynlLaahyFl)K))Cka*}CCFd7 zf{txS1)ZcMN|e~KV~6(#qd_^^H+5c3&9Q9g!DkBVA|9@YrWYdc5WFw3;{>70rV^lB z?OF36Wy&r13}nCb_wThbiZLI%RoFM;;^LYd#d!GmOw_u?egaCMv&_NbjmsTk*5~9* zMMuP+x)+iNsHM46wVWDJ?0Pq#Ib1}|RHtIBk0QBNbW@;K6{X8||9b_vtD~*m{q-!M zT({CR78M;a-40UlR-Vj#fp-t5v@><~RXD!_(*eb>&^Y&tq5Y(w(E-~fkRft`{<^I+t%PYZ+>VF8-Vj3rH= zpEv=oG9yVz$$x+Mm+YemYb?5z@oQ+vXV?N_rSaBLK2y5prY4YRf!l32ih4`?1_s#Z z=$sZt&W;%f!qzfePex4aSFpl-Rz-!|^$dr21^K049oL{C751N+ zq53FR$8G!Epb~M8e-W>@9b81d1v*5s4SCxH3Ay`}l{q^EDA?=1b#$C@lO;Bzv{vqF zY56tRUs>GVvQ^g;C6Wjd_!{qUiVP@fp8`yR6D+NeAD@YQVy4AJ3n+w!jkaeNtdqa1 zx6Oai42_Q;78MQ4evpvRm#yuDYBK7(V44BZX9=B_S(R$Q{q3&=|DxD#(^xDy@ zU^%fYO};FAu>4_h@ll?RFfWdR#}MC}&YA*cU~^7#2T1b(Z3?wn171MOxRf9z9(P)} z^03Lw%nYq^A1tJ3rxhI=R!~J~!l=L|Ny0i0NNc_k!?LSGbOq)<<{Q=g3 zw#gagpkDPj?tat*)RR{Id%?G z-tWG0N$UO<2pyf7mohy=2CF`+xjL~_*5+I!*>7%0wH^XO2;UtqYWggn=cRRl`79eX!gOu%^yF4 zk+;T*a|;WH-phc6W~Vm1aOc>cNk$Q`g^(uYOwxqrgZ1({BNlUQuid)#H_MY|=eN+pLR&A$YBP}duH`N8CH z^WJKJ+|77&fuIb53N8Nm13!=D(KtNnj;O1c7MsbKQgqntvD^65h73q)23;WI`SU?o%~_u>#Y9JcjytxuIm&DQA@XDr zHnt?#zBm80od!Wm_)X?QBG!pbf@aqkEqnuwy2fGA56bCk>Fp2&NZ*P<d5QH8SP_2E*?;C8yaR6r1kN4JLF~O90o4?` zyvf3{z>y;nk&%k@$9?;%D7W|`j4Ul5%zNCtIS5H1G`ig^xuLSE%1c+b8_@Sfk&%?y z(J-T%-#`f<87Rqhj=lHI51}-?^>F?=fHbPS{fJ6a6X5|jug|kXO-+U>f*Mv@WF#bd zZ{7CwNX})Vtq3a!Ef{LGT$G8oC@|Y@Y1-j5gXCjsBOew9NVIkv0wX{m>#YYI7ur%90n-`@=NO{mmlXSxb16Rh!cX@d^oo#I;cwP^< zHO>ShET%9lyUW~bpC%-W8a`b3s{i7@J5ir2O62^xNOC5<7U-<;@aodbzr8&{VwN#||rOtsF`2uV94u0jz zZ|1slH_*Gic;SMnM6V%IPu(BMK4ruuj5^SRDnsWGD($wvP&w6;LY*lyX3do*$+c=*EZa1j=YH2$3SM? zkOU1U&L3kP=lqsvoV74EO%F{*LREUtxd=eERo751O#rO!$cm*LYe=4W-~7%gWxsd z`p+Y_x7RmctR~+oHJd^s@JxR24%n6TJQ#Osu6A(eCs}fJM)%hZgYrA$$Wvc<`dZMti)zwK-Xi3n&*q#dh3n#(%>GAj!mcsOS-{@YVY9J>x1+fK{>+_^)Z$|sH< z{W>_vuBf2R{4mSPl0Ys&LD}&2>(fx>6M}nF`c}72cOOs-P)L6N`SToX-_|tu{WwO^ zppFwWx}TZJM>hB2`ru+H^9c-K?089*1fx){j~?`v24=fgdxCM5V znwmP=F-1f`tEtR!61(`hz|;v98pBkN)UzH`?PGs^GkxIHZUVv3)bxFWZtB(78Y-7J z?RI^pPJhICo+zl^-NPd=AV9(I#7`v^mC5mObUQ*NOHESkPM$u!4Y?9c2-KRUC_)Rg(bqErrWr5q?IrS3-9UE-hkT&_%3Q|X+?&IYh2yw zLd&`@j-dqocv?3GWfEl;X9pMoau?zr=%BT^S>eVvyyH^hDKpGoz+coj3JD0_5I}5X z1(jmVx#+N-aLwmwyBO=-{hck6& zK`0XhS4O7q`}ZqqYLDbOU}L!uD^}apwTz~1$lmCvC{`)^nx-aIXn{bL`ubh~F}NBQ z#Yj&~QqmEd134Q6z)c1kQRl~xKcU!!NGig6(qHA-Ra>io>uyzEiWM`0UV&W3gEZX)&Lwv)cTRcL5zZaXqw14C@6G?h=eNl<{K#j4IlMQ zz;pM&D5J_lE!Wi4*7iCjCEu*&;K2#HG|iW=K4@xaFiH$X$aCmkyT*C+4rH>HXkqXO zzsSTPdnvAnsj)Hm`$EMmF526R1uHSJcm~uDg9M@6aThXFqmc+v3ntq9mQcVCC9d5h zBw~?8mSQ;JXt}a!@?V8ygALkgPwHh?RrL=J?ihIIuTBgPqde~z3c{mbrli!sn1XlC z&-w=hV0qBSIbkYo*Ixmp5P;^?Scg3Z)i6V0WK?<=z!u_#;*0y3_TY(ZM)@=wrmN1( zv_O;rY1Yez;t#K0z8uy}uLRo%wrTwU`1(Ui>Do0T5f9ujM989d=Z+mK-n}=U;bvuY zbmFJ$>5trP7iN1;z!qmoezKvr)DD)|L%&ELJa`Zr7l*MCN$*Oax08+&A^cynQ&PfF zW6H8IjRcz7VDZdeD&ff!&3~$4u4ZQA?}HB<;v)r3`}XAvqeB(c+~=@lOKn6ZC*OqY zG%fA^>J}^!m?C0wV1`CM2Y|b|7rtWDN{P>{4ULVN7=na+TWttiSFn=tU1Ha$ z+sM-X2@>;MoQXk#NJ&mCj$lTW?c42~0^4Kx61P-5|AeC#^Rv`!L zSva9n3UJZfO5z{-L$KN_-AKLpTzWhF6Q#Gl34AXV5P9sfBKB|Ogk6V-o?&h~#3Du`h;vwYo`uV1S$QU}%#qn!d_@!7_1bldi^rQ)E?s^#?d^@YgX4#>{FHF))0E~-&CNT2?v6Bq96}mzS0zrTva&L{Nigsf1dsBT zshxx4?=PlBoc;A9T!b+$YeywJJ21dh^iD_GwIlY&zSWIq6O)Z~6FE0ZA0JAOPfFSu znXugVgDUDgtAr%4pV3i%{s+&bF)Ko=Be5T?aj2HVN#fdjZ2vAT!KECObF23L?j|jV zQF|##$)e$RL+~(#t2it!ETDHT*_jLhSDF6SdEUrr=_O?BrZD5h`FWf!kO#~vY8zbv zvj;KBY_~+aR4L>A5m8Z`h{xqOFhP6yY#pe~Has$|8?>0h%1TnkLPeLo+4YL_K5S4D z|N45lTR*Qu;rx1AWPWY{&9r#SV0xazN_Y!nGd(M{ZXJZrL z~g&YrE51w#5uoF_Z`y0WMYIV>E zw{Ehz*f8)FZgT6*ADx{Tz6<>60*iR{#$pRj$iBQQ>#yY?F`uyR_7ONHN{~Ny?&X^| zI%Mj$jBBk8-@eiR@q>ZjUU8Z~a!RN!w=+`a7r9U@!PVCW;|J5@V`IxOJI7nq2_eeG z<>%@n@~^v)fGit%`dRcL0ESgAuhtjp^7mj`h$$xV!3ID!+Wupwx80 zCH-FYRC%5tUGTuf9cONcMnV4q zDg*-7QVm1rZ(#tc2||A&J@qvCz}K%wb$8f3eZ4CR%%ORIt(RXhBtfZTBvprIV|p+Y;>Onj?X=-_!%G0}@$92`S4Ga>GG zgF;jl6n2$NADNh@J8m?KiiBXLT%q+FI7CPRZIaiaqu5<9<71GINZIDYaqpJsMpMl= zc9TE=!_QYQ$q#-9LT{vY|3=Ue6Ib*_NNcGG@?eg8d1c*Ok5J@S?Sq2|LIsmoy4oe> zrn|B;A0?K4(jOPj-r^S&^oDWqF0;ONtwjAk47d!}?Y3n7p=4ttY#w^by8eLqpMNOT zyRJ~g?|qI>uc+{l=hJwpZOxmCr`+ZPGGIAg(Yc)vyrhWiztQ;EklGkXMy`Bh(+YwZ0s(v*Q2<&@zz8B!!IivZ# zRIq3e)G2>{p(XdRx=D6B0_Iw6?bgqq14*B-lJD7Lqw^?m~LZ)jSN{3!4;Ywdqro@klAF$JOB*s~*C zC4U)xHrihJgXmZ^dHmCrmjRQ|vuX|FwQhBR=Xz%Y^CkKv9aAljQZ9(FdM;CD0w=kb9UJ$iwpf#Yx6yr zAa6-{aGa>T&BeInTsJRS_dOvN>L5-dVuH^FUXyq_<3C}T*0BD5T}jEbrt`tL+55LO z>S}73d6j_=5hX17v^Rz=9?vf1=H_~#>9*t4aCAh+;Fh7G7+mYEe{$rYVxWyKu$O}6 zyjn7hd9PmESzCwLl<4Z{pbL0KPcI=Z?m8^{RvkQ)`<^=ieZh5fq%HYZ@f$D7z451< z1xhUF2pYP&u@Moe01c&9T9bX{m}FtB+n$0c1jD(9`S`s5YfzargdFN7rDF<>Mx>$c zAlZYU2Or>r(a)IKj6*REsM6->*N%=l7ZuF!QpW2dGvU}0%OxDO(%iRp_bFskKuV_h z)Q1m05>&+N_Bq!02?LQJrKSp?3v7MbAJab`9;dE1viZt~M@4-YvZ^0lfM#pC?B^iW z7jj4v3e5cy4qthDXXg)JgmI@}l=$8Q%e~iibqzi9QC7re7?B=-PEU)kGo@4E%OYBj zN=m}dH1%f{AgqGK1=KIwBn~pG){6@fF)_d6bMg1E>>NIv0aHn7Nr~~^ri-47@7tT2 zbPTraI8(g|s=J1msF&k&asr-oB>nw$dD^V;!v_peHnp@YvpS7JL8c|g;sVr8&&(*@ zd%SAvR`%C_&%m8KldG$v1XZG;{i3f=M_9gm;WE6k!1i9?Bh;{~pOcecrY<~6(Bo$x zBqp#CXzLnFl`ekPR2-d%608s2LwTg>4#*x599Km538N7VM?|RphrA=QF5b22uh2m& zQJ!PzlQq7b;2ci}fYSEn@=dp|K{_iKVo8+7EuoWORH^Ucay-zg6B7C%5s#^+jw1rZU@ApzqK)_9-2{qY_+ z4&%SA2TH~mKM8b!*H_H(Bm3+uIY}L0U_n3BBI?=Bruuq#i?|*qb%N(2Z&Fg*f$c^# zkIA)5G>mXV#-;rHypvS{!F=Yg8J;LwRCkDvTZ@`t^X0SvVIL9E!H*xOxy|Nr{t^9< z2`QCS(0zg}B2b%$U0z>5G4ka!^||JW)a&1N*9@kmeXpn>F4hcs{`PHOL(Nc1tnRvo z&KpAhCB3_kQ#tn+tibwp+saDZUKYsj+V$&PCq0v*qB7Fb>T25j8b@K2kWM(ikAxnX z&Qe7Yg~j}-6FRp6E=_E6RXfJOkDm^7g!g!YZdh)ff-R*fs6029Dt9digG`HimJJVz z8id^H@oyZ(d=Z`p_F0WLT9|f!^X4x+lvx-1aMmkK>(F1&ST%$$NXmaUol8`dW_HQ8 zsho8&AYAUFmN3u$m-}yMN?9w%K-=Gu3boa)TsaQeqrmFu@#D%P3BahT7u;^X`D|`J zeCAAXDy8ON^>xBb@cW>J1JwpV?>qC-V$D{BICZhFPj3t!D@{!@Y8J-4Y-CB!1MQT- z=w}cMr@~Of#gOqND$0yEcW`-x*t!OzFE65NTG{POFoo9p2OMJNS*t!y5Q633^eaX?mDx&Co2$we72v zHAi*64GZacdR7KRf9E6l`-R{ZRR3e@7tM)7uV1}V-1__norKs}%E`hlF!04cKOm@B zKkeG8)qU$GzTb$O$k+bYci{=Um?ux}zt?>j930B8=#9oRPXm_Yj?&cu2oVvCoS4y~ zVm>aGcMHcy)hQ4G8;zqx*C9?{3);o$`Z4&J+Z04lhju@5b*Z0+}@qxeu)N7Ve} zoPoi+YVQS@QNZQ7mAmtAombD$g!??)pRA?1xqv6i4sGTqnU^urbL7Ag$9%?qxFFK> zSKzp&TAjn_23>B)H1ejh^>EA5QnHzuRg?98DxbRqy`X*aVUHgxkN;{Mwy)olauXwu z;jxU1SNbQ%`-|_chU;vWJO4VSpfIKrK)#3dN0nz&HcYe+1;*6%^mhDDidW1mEP{^b zaC36*in|bByTe|76R`c~RP+PTqMkEeh`|gO93x=LQgYr8( z2=4xgV=6A`?8?U|K|j{Togp1D6{zR<5)h^tYe7-b6Jlb9wAY0M1%J)Vv}S)w$M2=2 zaF7OSz;cM}p};Fxj4m(qdWm~XhurkK&78!WB9Sf|XvXV~;jG<=!idm=b5ABO#a{{O z=4jvE{juqJW+qJ@g`#~N8ihmtiP{3rfe+7<;{<*6XGBx=W%p2z8Dlf1iq9ybqZ|@z>|*L-J+tRvUCoBrouU$<8z+W z%QHXH)6(z_MQg`zf`x*YW0C=@5q=eY&&6M_t0BgtJ=0NjUW(-+!VG>Pm~gW0D1la^ zorZ@RS#Ya3Qa5ame?+bV!^-Lygn!A+!vp85yWfIaREWk3ZSsku^`nl;P|=zHWt%fuUu+-4%9J=6vwYUJ!_FA|A?PDY>VzHTW%3m$4FQ-C1gN6bjaU)fl zbZlbc9h~17Za{X`(fNj>Z6o9`*d7dedv9ePUmo*7l?SyH?Ka}x<`x7i9C!#Bk3u8N z7eRH|W2mW@slg8w0D|QaVPOpZb$tJhIqVNP62AT@Zq;}=6kxQ9umzIlt&HM!GMj?< ze7b`NQM1+I2h!4V>?yWV{r3S{*c8nLjDN(%_2BywXxa2O*8bkc@DF4r*mtI6LpYBR z-GNOeS=JK}Qt#%?*C-^0hCat>X=XdI>3@;bMn;S=+`dLrdoc0+zE6ug#s6;(2F!i3 zF&R|Q>~4Acwxs1SsNz30)h`-(M?81sfA3(@_y)Z;pY;r+UlxsT1zziO={wnoi*T=` zlwIT7gpW_m)T@sK!}Qm`eX?1$Z~H|^cK72c{8QP$b)ug)-k0YHFKB9t_yuIztu0O_ zSQHZ#Wfc9){A=Bl{daB)_MCDj)KFcY$H1QPf#)oJXU%r+HeLG5Po#0#KyIl1ZMxHOg1#OJ#xz8tuzmLD&${Stf8}&4e4WVP?kWN0 z?^WrFl#zr}HX27-e}42+cXkB@yCx||;P-o422-NggF$lQFXEOD{nU@#Yr3}EyxiJ) zS_xk=HWnmSp~SVXH;@V%v5zc0Se*64m=HA#p$dpiKcc=^_~@FjoxL`n!nv13Ub24) zLu6-N1^JH{sak68@!8-wrc%r$wC&w5Gi4}uT>Yx~sYCdRGT3Uqb#*l!e@iX5yt6Sp z@`hp|qqb-<52kdGQn2EgfyTTrwF=-R=)vuKDV9|4$oN9uDQc$KT>24RstlDdlJ(36-V9 zoEA%_a;#G%TT)3y$`Z$#eLt?HEG5}VvgM2=N46+Ol5H$uY(wgh^?s&vpL?I@KG*Z` z$7|l1dEfW9e7~Qqjg0yV0=#uwKQ_nD5i17thdGlk({(xB$DUbKdweOpy7s!U+|`wL zp{>52^JkMJ00%xkwO*Uz_MY=UmV9w0U*%d`&U$<{WTtD&t4mC~0OReErOUKY^D&Ig z6thF%gVC8Q{%$+a7%S8!+{8;bG&H*2aoaS>DtF&8;kYw|z9``^Kpqbr+)d?K7qVgnAY{A?&f#@^Sjt3Wf za%By;S%T~=$EGCG`ID3sOHO7D7pU3Om`2ob4v=sU|Fg{R$%yf*`pfrXqqw(9eI#d~ zgz4C=e^_D-x@Ae0D>H$zy?EPiMUIl2`$#*I`aaaWnf>J zosuG-B+KGa&fXou?wPWzfZ(!7&8*7vRBDiXJ%Ca=mL8F()xd!y1}t^4ej{v6^Fs|5 zi;aAlqQB~??%n?EU44M2AvT#~Pm84_B@6GZxN;aC2?;;+gAh~0(N5V!|MN0bs#)cC z8SnHjGag1}jdN7#pPKAzNhD>lngDXAA9g<|X+#VJU^x7N0=uiCRa^MLMe zAtqC(aZbkQz8abZT`gl(*aaV}jIOSjN?B`dVgonPV{LO9fZhEIGoRxXDeUB~8AA`Y zsxS=``p7}cu-q*WZ;pveM`}T~zQa`$hX0f2nb=1Q&TtC$>(ge(irL~}5OK!~n>97KylQ&zd#&`>wzxY8NtM~L$aJV;Hu zDfVko0)=HfL&p@;_Z!6HZEYH9y)<}wJl9rW=jg0^C1qlCkcZHr8C9;M18PEMfzm6E z-MH+o#YLL7?j=HFs^koX)8c@{QJ2P;q>}4mqN3QyPvl_x);@R6?e$McJD7Zaxm`Fz zbn>);K@6H=3qz;xc^fG3aMTxLZ>w))aUAC_1_p@0DTW#hBn!76x%JW@lgS(z@js|F z4j~CtDcV|EDc8TE%fj~lZD|Sq8LM`^bhN#W%*NP^+1VC7y?^x6#88c7Wwy-CyWDm@ ze(oBA*H}*4Bd*7c1L&ipo$c)#xwr~SO17SrkJ3p8Z~$J(SN$a96o!AM>t28N?jx0& zP*JXR=Ve&x!1AXiWDkb^CESW{u(pB6BQD;w|4&~w4XTcPP}w(k&o!2|W1k7_UM0Ms z^qIWsy)0cPAZggQAYuZ>kJ1;YkA?<8jXlZj$BJ*`;{)p5*53Ye^5L$oE*Q#4-2>Y( z?nFE-_Lp06fz=1(0RS^3sAiS6wwjobP>y17U2+%Mr*~O6M~DjA9616&?nN@LBqZDZ8SNchm@C{ZPl=U zxP0M7U$~EbAIXhZ15P}`1GoYUQ;}_pEBtK-o$uKqha)pDPlEFKjGkWZoihj5Up?Vc z`jo{+`tGI|kQ1olNb|<5M4^2b6g=bJzkfeK znH*y<&hCn-sUa`K{QH9+Lzn=e8n{};6&fl7lnj3)32=%btO7Nm=yX0X5ZV3ZAv+47 zyY)m2-+#^=hSvaqIAdwHo?*YzgY>zk>?5oz^!pdh%F_ z?7Dv#nWOz6?Syk1fFy`1~)ir0*Di5d~6n<~+={c;Z7#%ML zJ!Qz9RpEeIaAoi}NT^Tzeba-xU=p&}&#j7T2VHyr>IJuXQNFsx`gQKt!^&TjkLOKL z?`jtXC&UVvrO5j1@~ugG&F%e|bZx(%)W&D`gZOu(xn&fLeU{b@8lwoBrrF%yFQaJ8 z<8+|=1=YpY<@TH4Z$+Nr(>At^$`Z8XI91w%OTUTyzSP`2ci44BqhtX0o)R$n7wl#s z7bfqP6c^tx_1k{rNF~&aX}gl934*J){|OQXw?{%FTJ~|9nwncm|Hy$v%u~Jd((2gC zuU)^s7VA;`;)SdG6B)ihWWRx_LJ(kh`xb&oUD{b*mILM+#*jyEl^w4EJOi`%ez2COk)uC=kR#c)&E$(=fQFoi2Y+$Ja;C$Z3~G3a`Dj1W08NT&?d^leNMP z6?4v59f(Qby#G1r3+{~Bz$xi=tP`N7U*A}QLkvTP_n59j-^((fO4HpxvR^Fe_H(X) zAxc@j&G~gp%ii6)tF>8|DFExb2Q>Mp7R5`9_r$`&i?pwW$`;o34L3xW9r8JFv4;KP zoaW8=u&i*9(thOG@eY}!dDiFl3Ht-=fZTj|wMPC5F6H>~=7K*Ff^j(rM z-~|-?68dVr_Lo_cx0e9Q_B2mT22nD)i?0|11gCfqUPn(i%QvT7aRRS~APea8QT#g; zbqV`Ra*@;ZbE(CEi<@9^HM|JC36(iwQd?}Tj5kI!SmR3HGn{a11lyw2;2(mC8`>-- zy~GyVvh#3!LUM%h54pocR#4hgY|&7aA;a=qu2I614c-w=pEe50f|zzuZ1@wj7%Qou zrxZ_NQ+CImNG)pxQ!TC6XvQJ59kZSFfk+$LqQjo6N!K#q9x~Xo1&(tHP5jL8#6)6DjJ1;J7Q>^sVs(%5^Kvd1U=L4< zj&65z0qwElM2I78Bu`7~oqaLbq}n=yHE(Eu#lvoCBC-m?x!Sk&NOBndz}&Q919T&| z`a?h`Z~rmtWSlwA|iroG$E- zz5T77Qct$KhX>5hBK~lvN7TRZNbUy$&O@qYB`{iTEh)jG)20-vyPmLk8j#mwJEu&u z^2A^UiGMb`<7F0j6JBv;de%>%Z`}JujP}H0lA1%Umd|C)q(JjNw?#;bFA)AuKnbO% zL+bQ*@q4a(6_VRPc>THqzM$oK+7!m^4MYh9*VSYPJz?OvqZXLWvW#16LZ;u2?B_@-0j+*v81>^qDt{OySN}(c%xlL zwZ-NFH7q`-{Tw_zD!uk3w)|0YYf`HM{Nk!7b8?dZh3dl&djUb)^=S#$Xa#H;m#O)k zLsXwh$M%jMprBHYzHtg=5QI_=24%x{?Ho0hEz@NvB*Ka9DqtET0kU+p=zepJb%S_Bivb_#(2?`v-#$`Vo1gPH2{V%3KaCJ9ea*@87FHU5D;wVfgC z-&J-iBk_|@((PNwZWi`OX-e;S1JC&C#=Qhl6_FSj^dQFmeU7R4*389k-vEXd_`!YK zlc8gjX#iENb3Y(-)#=&Hw|3&uDy&%t)tPRriELPKuwr5hsWw6?9(InEDl{L>)6-}v zP@D8HxslyE=t>Y8W2@nB?M`WF%`5~(&}eH|&AK|)o4~(17*%0kya?6!dFst?pKavI zvftVv;O||9BeHWOn2XPJmtPbYt7MTlYVo2MGupchU_K;px55Aq9qo-FB|; zZf)HsEj)!GL679zAk609%I5;jE#kkpOw;n#woFRGbmNn2b7&x-G9Jk9N6`9XXITl@1XhgGnL>J zf!AQjfKNJFJHOM#$q8*g>iW-S{!eMJ-&C5fVM9bUi#leSsSCCaKT%Q`D@gWJ$rC(v z7P`1!02iN<7E^aup6~DuJ@LpqA5))1B8A+)@7QsjgCKn6Fc9g|)y7bMdbL6FrvYIg ziX0*QN!|GGW8Yu(_p!}zIio(nAJ&<~HYYs(@5lao^7mu^_hi-^{_n}Fv8x=;aRvo8 SRfALbFQI*$ax9N*;r%bz3+-zF literal 0 HcmV?d00001 diff --git a/Red Black Trees/files/fig2.png b/Red Black Trees/files/fig2.png new file mode 100644 index 0000000000000000000000000000000000000000..35b81e61c61f11906814e5503daf19847120a4a2 GIT binary patch literal 40534 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 literal 0 HcmV?d00001 From 23fede232175fdb00024efdb910e244bc3ae3811 Mon Sep 17 00:00:00 2001 From: axptwig Date: Thu, 5 May 2016 19:52:27 -0400 Subject: [PATCH 0341/1679] Delete RBTree.swift~ --- Red Black Trees/RBTree.swift~ | 332 ---------------------------------- 1 file changed, 332 deletions(-) delete mode 100644 Red Black Trees/RBTree.swift~ diff --git a/Red Black Trees/RBTree.swift~ b/Red Black Trees/RBTree.swift~ deleted file mode 100644 index 4cb0c2fcb..000000000 --- a/Red Black Trees/RBTree.swift~ +++ /dev/null @@ -1,332 +0,0 @@ -public class RBTNode{ - private(set) public var color: Bool - private(set) public var left: RBTNode! - private(set) public var right: RBTNode! - private(set) public var parent: RBTNode! - private(set) public var data: Int - init(){ - self.data = -1 - self.color = true - self.left = nil - self.right = nil - self.parent = nil - } - init(rootData: Int){ - self.data = rootData - self.color = true //0is black 1 is red - self.left = nil - self.right = nil - self.parent = nil - } - public func grandparent()->RBTNode?{ - if(self.parent === nil || self.parent.parent === nil){ - return nil - } - else{ - return self.parent.parent - } - } - public func sibling()->RBTNode?{ - if(self.parent === nil || self.parent.right === nil || self.parent.left === nil){ - return nil - } - if(self === self.parent!.left!){ - return self.parent!.right! - } - else{ - return self.parent!.left! - } - } - public func replaceNode(n1: RBTNode, n2: RBTNode){ - var temp = n1.data - var temp_color = n1.color - n1.data = n2.data - n1.color = n2.color - n2.data = temp - n2.color = temp_color - } - public func minimum(var node: RBTNode)->RBTNode { - while node.left !== nil{ - node = node.left - } - return node - } - public func successor(var node: RBTNode) -> RBTNode? { - if node.right !== nil { - return minimum(node.right) - } - var successor = node.parent - while successor !== nil && node === successor.right { - node = successor - successor = successor.parent - } - return successor - } - public func predecessor(var node: RBTNode) -> RBTNode{ - if node.left !== nil { - return minimum(node.left) - } - var successor = node.parent - while successor !== nil && node === successor.left { - node = successor - successor = successor.parent - } - return successor - } - public func maximum(var rootNode: RBTNode) -> RBTNode{ - while rootNode.right !== nil { - rootNode = rootNode.right - } - return rootNode - } -} -public class RBTree { - - private(set) public var root: RBTNode? - init(rootData: Int) { - root = RBTNode(rootData: rootData) - root!.color = false - } - init(){ - root = nil - } - public func depth()->Int{ - let n = depth(root!) - return n - } - private func depth(rooty:RBTNode?)->Int{ - if(rooty == nil){ - return 0 - } - else{ - return 1+(max(depth(root!.left),depth(root!.right))) - } - } - - public func inOrder(){ - inOrder(root) - } - private func inOrder(root: RBTNode?){ - if(root == nil){ - return - } - inOrder(root!.left) - print("Data: \(root!.data) Color: \(root!.color)") - inOrder(root!.right) - } - - private func leftRotate(x: RBTNode) { - let newRoot = x.right - x.right = newRoot.left - if (newRoot.left !== nil) { - newRoot.left.parent = x - } - newRoot.parent = x.parent - if(x.parent === nil) { - root = newRoot - } else if (x === x.parent.left) { - x.parent.left = newRoot - } else { - x.parent.right = newRoot - } - newRoot.left = x - x.parent = newRoot - } - private func rightRotate(x: RBTNode) { - let newRoot = x.left - x.left = newRoot.right - if newRoot.right !== nil { - newRoot.right.parent = x - } - newRoot.parent = x.parent - if x.parent === nil { - root = newRoot - } else if x === x.parent.right { - x.parent.right = newRoot - } else { - x.parent.left = newRoot - } - newRoot.right = x - x.parent = newRoot -} - -public func insertFixup(value: Int){ - let inserted = find(value) - - if(inserted == nil){ - print("INSERTEDNILLLLLLLL") - } - print("inserted: ") - print(inserted!.data) - insertCase1(inserted) -} -private func insertCase1(inserted: RBTNode?){ - let myroot = self.root! - if myroot === inserted!{ - self.root!.color = false - print("ITS THE ROOT") - print("insert case 1: The root was nil and we inserted a black node at root") - } - insertCase2(inserted!) -} -private func insertCase2(inserted: RBTNode?){ - if inserted!.parent!.color == false{ - print("Insert case 2: parent is black so nothing to change") - return - } - insertCase3(inserted!) -} -private func insertCase3(inserted: RBTNode?){ - if(inserted!.parent!.sibling() != nil && inserted!.parent!.sibling()!.color == true){ - print("insert case3: If both the parent P and the uncle U are red, then both of them can be repainted black and the grandparent G ") - inserted!.parent!.color = false - inserted!.parent!.sibling()!.color = false - let g = inserted!.grandparent - g()!.color = true - if(g()!.parent == nil){ - g()!.color = false - } - } - insertCase4(inserted) -} -//THIS ONE MAY BE BROKEN!?!?!?!? -private func insertCase4(var inserted: RBTNode?){ - if((inserted! === inserted!.parent!.right) && (inserted!.grandparent()!.left === inserted!.parent!)){ - print("case 4") - rightRotate(inserted!.parent) - inserted! = inserted!.left - } - else if((inserted! === inserted!.parent!.left) && (inserted!.grandparent()!.right === inserted!.parent!)){ - print("case 4") - leftRotate(inserted!.parent) - inserted! = inserted!.right - } - insertCase5(inserted) -} -private func insertCase5(inserted: RBTNode?){ - if((inserted!.parent!.color == true && (inserted!.parent!.sibling()?.color == false || inserted!.parent!.sibling() == nil ))){ - if(inserted! === inserted!.parent!.left && inserted!.grandparent()!.left === inserted!.parent!){ - print("insert case 5: The parent P is red but the uncle U is black/nil, the current node N is the left child of P, and P is the left child of its parent G") - inserted!.parent.color = false - inserted!.grandparent()?.color = true - if(inserted! === inserted!.parent!.left){ - print("its on the left") - rightRotate(inserted!.grandparent()!) - } - } - else if(inserted! === inserted!.parent!.right && inserted!.grandparent()!.right === inserted!.parent!){ - print("insert case 5: RIGHT RIGHT") - inserted!.parent.color = false - inserted!.grandparent()?.color = true - - print("Its on the right") - leftRotate(inserted!.grandparent()!) - } - } - print("weve reached the end boys") -} - - public func insert(value: Int) { - insert(value, parent: root!) - insertFixup(value) - } - private func insert(value: Int, parent: RBTNode) { - if self.root == nil{ - self.root = RBTNode(rootData: value) - return - } - else if value < parent.data { - if let left = parent.left { - insert(value, parent: left) - } else { - parent.left = RBTNode(rootData: value) - parent.left?.parent = parent - } - } else { - if let right = parent.right { - insert(value, parent: right) - } else { - parent.right = RBTNode(rootData: value) - parent.right?.parent = parent - } - } - } - public func find(data: Int)->RBTNode?{ - return find(root!,data: data) - } - - private func find(root: RBTNode, data: Int)->RBTNode?{ - if data == root.data{ - return root - } - if root.data != data && root.right == nil && root.left == nil { - return nil - } - else if data > root.data{ - return find(root.right, data: data) - } - else if data < root.data{ - return find(root.left, data: data) - } - else{ - return nil - } - } - - //DELETION HELPER FUNCTIONS - public func remove(value: Int){ - let toRemove = find(value) - if(toRemove == nil){ - return - } - } - - - -} - -var tree = RBTree(rootData: 8) -tree.insert(9) -tree.insert(6) -tree.insert(5) -tree.insert(4) -tree.insert(40) -tree.insert(400) -tree.insert(430) -var t = tree.root! -var min = t.minimum(t) -print("MIN: \(min.data)") -var x = tree.root!.left -tree.inOrder() -t.replaceNode(t,n2:x) -tree.inOrder() - -//print("_________________________") -//let x = tree.root! -//print("sibling: \(tree.root!.left!.sibling()!.data)") -//print("root: \(tree.root!.data)") -//tree.rightRotate(x) -//print("root: \(tree.root!.data)") -//tree.inOrder() - -//let l = tree.root!.left! -//let r = tree.root!.right! -//print(l.data) -//print(r.data) -//if tree.root!.parent == nil{ -// print("ASDASD") -//} - -//how you access certain elements -//let root = tree.root!.left! -//if(root.parent === nil){ -// print("nil") -//} -//else{ -// print(root.parent.data) -//} - -//print(tree.root!.data) -//print(tree.root!.right!.data) -//print(tree.root!.left!.data) - From 93dc8b9a70384a94b3a04d18d9faf38623e74ec7 Mon Sep 17 00:00:00 2001 From: axptwig Date: Thu, 5 May 2016 19:52:35 -0400 Subject: [PATCH 0342/1679] Delete README.md~ --- Red Black Trees/README.md~ | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 Red Black Trees/README.md~ diff --git a/Red Black Trees/README.md~ b/Red Black Trees/README.md~ deleted file mode 100644 index e69de29bb..000000000 From 9c44e70d0d99b7da3c2bb54ab4d7c3edf1b7508a Mon Sep 17 00:00:00 2001 From: axptwig Date: Thu, 5 May 2016 19:53:31 -0400 Subject: [PATCH 0343/1679] Update README.md --- Red Black Trees/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Red Black Trees/README.md b/Red Black Trees/README.md index dae7c4d62..e1b887c3a 100644 --- a/Red Black Trees/README.md +++ b/Red Black Trees/README.md @@ -1,5 +1,5 @@ # Red Black Tree -![fig1](Images/fig1.png) +![fig1](files/fig1.png) Red-black trees are an evolution of binary search trees that aim to keep the tree balanced without affecting the complexity of the primitive operations. This is done by coloring each node in the tree with either red or black and preserving a set of properties that guarantee that the deepest path in the tree is not longer than twice the shortest one. ## Motivation: * We want a balanced binary search tree @@ -28,7 +28,7 @@ Since an insertion or deletion may violate one of the invariant's of the red-bla #Rotation To ensure that its color scheme and properties don’t get thrown off, red-black trees employ a key operation known as rotation. Rotation is a binary operation, between a parent node and one of its children, that swaps nodes and modifys their pointers while preserving the inorder traversal of the tree (so that elements are still sorted). There are two types of rotations: left rotation and right rotation. Left rotation swaps the parent node with its right child, while right rotation swaps the parent node with its left child. -![fig2](Images/fig2.png) +![fig2](files/fig2.png) ###Left-Rotation: ```c++ y ← x->right From 97e93b6775bf7eb3426a9fd19ec36a834b52c479 Mon Sep 17 00:00:00 2001 From: Thukor Date: Thu, 5 May 2016 21:50:29 -0400 Subject: [PATCH 0344/1679] Got rid of random build files --- Red Black Trees/RBTree.swift | 552 ++++++++++++++++----------------- Red Black Trees/RBTree.swift~ | 332 -------------------- Red Black Trees/README.md | 65 +++- Red Black Trees/README.md~ | 0 Red Black Trees/files/fig1.png | Bin 0 -> 24455 bytes Red Black Trees/files/fig2.png | Bin 0 -> 40534 bytes Trie/{sources => }/Queue.swift | 0 Trie/ReadMe.md | 216 ++++++++++++- Trie/tests/LinuxMain.swift | 8 - Trie/tests/Trie/TrieTest.swift | 26 -- Trie/trie | Bin 60968 -> 0 bytes Trie/{sources => }/trie.swift | 0 12 files changed, 552 insertions(+), 647 deletions(-) delete mode 100644 Red Black Trees/RBTree.swift~ delete mode 100644 Red Black Trees/README.md~ create mode 100644 Red Black Trees/files/fig1.png create mode 100644 Red Black Trees/files/fig2.png rename Trie/{sources => }/Queue.swift (100%) delete mode 100644 Trie/tests/LinuxMain.swift delete mode 100644 Trie/tests/Trie/TrieTest.swift delete mode 100755 Trie/trie rename Trie/{sources => }/trie.swift (100%) diff --git a/Red Black Trees/RBTree.swift b/Red Black Trees/RBTree.swift index dab7e1fd8..50d1d00d4 100644 --- a/Red Black Trees/RBTree.swift +++ b/Red Black Trees/RBTree.swift @@ -21,6 +21,7 @@ public class RBTNode{ deinit{ print("Node: \(self.data) is bein deinitialized") } + public func grandparent()->RBTNode?{ if(self.parent === nil || self.parent.parent === nil){ return nil @@ -30,7 +31,7 @@ public class RBTNode{ } } public func sibling()->RBTNode?{ - if(self.parent === nil || self.parent.right === nil || self.parent.left === nil){ + if(self.parent === nil || self.parent.right === nil || self.parent.left === nil){ return nil } if(self === self.parent!.left!){ @@ -40,61 +41,60 @@ public class RBTNode{ return self.parent!.left! } } - - - } public class RBTree { - - private(set) public var root: RBTNode? - init(rootData: Int) { - root = RBTNode(rootData: rootData) - root!.color = false - } - init(){ - root = nil - } - public func depth()->Int{ - let n = depth(root!) - return n + private(set) public var root: RBTNode? + init(rootData: Int) { + root = RBTNode(rootData: rootData) + root!.color = false + } + init(){ + root = nil + } + public func depth()->Int{ + let n = depth(root!) + return n + } + private func depth(rooty:RBTNode?)->Int{ + if(rooty == nil){ + return 0 } - private func depth(rooty:RBTNode?)->Int{ - if(rooty == nil){ - return 0 - } - else{ - return 1+(max(depth(root!.left),depth(root!.right))) - } + else{ + return 1+(max(depth(root!.left),depth(root!.right))) } + } - public func inOrder(){ - inOrder(root) + public func inOrder(){ + inOrder(root) + } + private func inOrder(root: RBTNode?){ + if(self.root == nil ){ + print("The tree is empty.") } - private func inOrder(root: RBTNode?){ - if(root == nil){ - return - } - inOrder(root!.left) - print("Data: \(root!.data) Color: \(root!.color)") - inOrder(root!.right) + if(root == nil){ + return } + inOrder(root!.left) + print("Data: \(root!.data) Color: \(root!.color)") + inOrder(root!.right) + } - private func leftRotate(x: RBTNode) { - let newRoot = x.right - x.right = newRoot.left - if (newRoot.left !== nil) { - newRoot.left.parent = x - } - newRoot.parent = x.parent - if(x.parent === nil) { - root = newRoot - } else if (x === x.parent.left) { - x.parent.left = newRoot - } else { - x.parent.right = newRoot - } - newRoot.left = x - x.parent = newRoot + private func leftRotate(x: RBTNode) { + let newRoot = x.right + x.right = newRoot.left + if (newRoot.left !== nil) { + newRoot.left.parent = x + } + newRoot.parent = x.parent + if(x.parent === nil) { + root = newRoot + } else if (x === x.parent.left) { + x.parent.left = newRoot + } else { + x.parent.right = newRoot + } + newRoot.left = x + x.parent = newRoot } private func rightRotate(x: RBTNode) { let newRoot = x.left @@ -112,225 +112,241 @@ public class RBTree { } newRoot.right = x x.parent = newRoot -} - -public func insertFixup(value: Int){ - let inserted = find(value) - - if(inserted == nil){ - print("INSERTEDNILLLLLLLL") - } - print("inserted: ") - print(inserted!.data) - insertCase1(inserted) -} -private func insertCase1(inserted: RBTNode?){ - let myroot = self.root! - if myroot === inserted!{ - self.root!.color = false - print("ITS THE ROOT") - print("insert case 1: The root was nil and we inserted a black node at root") - } - insertCase2(inserted!) -} -private func insertCase2(inserted: RBTNode?){ - if inserted!.parent!.color == false{ - print("Insert case 2: parent is black so nothing to change") - return } - insertCase3(inserted!) -} -private func insertCase3(inserted: RBTNode?){ - if(inserted!.parent!.sibling() != nil && inserted!.parent!.sibling()!.color == true){ - print("insert case3: If both the parent P and the uncle U are red, then both of them can be repainted black and the grandparent G ") - inserted!.parent!.color = false - inserted!.parent!.sibling()!.color = false - let g = inserted!.grandparent - g()!.color = true - if(g()!.parent == nil){ - g()!.color = false + public func insertFixup(value: Int){ + let inserted = find(value) + print("Inserted Node: \(inserted!.data)") + insertCase1(inserted) + } + private func insertCase1(inserted: RBTNode?){ + let myroot = self.root! + if myroot === inserted!{ + self.root!.color = false + } + insertCase2(inserted!) + } + private func insertCase2(inserted: RBTNode?){ + if inserted!.parent!.color == false{ + return + } + insertCase3(inserted!) + } + private func insertCase3(inserted: RBTNode?){ + if(inserted!.parent!.sibling() != nil && + inserted!.parent!.sibling()!.color == true){ + inserted!.parent!.color = false + inserted!.parent!.sibling()!.color = false + let g = inserted!.grandparent + g()!.color = true + if(g()!.parent == nil){ + g()!.color = false + } } - } insertCase4(inserted) -} - -private func insertCase4(var inserted: RBTNode?){ - if((inserted! === inserted!.parent!.right) && (inserted!.grandparent()!.left === inserted!.parent!)){ - print("case 4") - leftRotate(inserted!.parent) - inserted! = inserted!.left } - else if((inserted! === inserted!.parent!.left) && (inserted!.grandparent()!.right === inserted!.parent!)){ - print("case 4") - rightRotate(inserted!.parent) - inserted! = inserted!.right + + private func insertCase4( insert: RBTNode?){ + var inserted = insert + if((inserted! === inserted!.parent!.right) && + (inserted!.grandparent()!.left === inserted!.parent!)){ + + leftRotate(inserted!.parent) + inserted! = inserted!.left + } + else if((inserted! === inserted!.parent!.left) && + (inserted!.grandparent()!.right === inserted!.parent!)){ + + rightRotate(inserted!.parent) + inserted! = inserted!.right + } + insertCase5(inserted) } - insertCase5(inserted) -} -private func insertCase5(inserted: RBTNode?){ - if((inserted!.parent!.color == true && (inserted!.parent!.sibling()?.color == false || inserted!.parent!.sibling() == nil ))){ - if(inserted! === inserted!.parent!.left && inserted!.grandparent()!.left === inserted!.parent!){ - print("insert case 5: The parent P is red but the uncle U is black/nil, the current node N is the left child of P, and P is the left child of its parent G") - inserted!.parent.color = false - inserted!.grandparent()?.color = true - if(inserted! === inserted!.parent!.left){ - print("its on the left") - rightRotate(inserted!.grandparent()!) - } - } - else if(inserted! === inserted!.parent!.right && inserted!.grandparent()!.right === inserted!.parent!){ - print("insert case 5: RIGHT RIGHT") - inserted!.parent.color = false - inserted!.grandparent()?.color = true + private func insertCase5(inserted: RBTNode?){ + if((inserted!.parent!.color == true && + (inserted!.parent!.sibling()?.color == false || + inserted!.parent!.sibling() == nil ))){ - print("Its on the right") + if(inserted! === inserted!.parent!.left && inserted!.grandparent()!.left === inserted!.parent!){ + inserted!.parent.color = false + inserted!.grandparent()?.color = true + if(inserted! === inserted!.parent!.left){ + rightRotate(inserted!.grandparent()!) + } + } + else if(inserted! === inserted!.parent!.right && inserted!.grandparent()!.right === inserted!.parent!){ + inserted!.parent.color = false + inserted!.grandparent()?.color = true leftRotate(inserted!.grandparent()!) - } + } + } } - print("weve reached the end boys") -} - public func insert(value: Int) { - insert(value, parent: root!) - insertFixup(value) - } - private func insert(value: Int, parent: RBTNode) { - if self.root == nil{ - self.root = RBTNode(rootData: value) - return + public func insert(value: Int) { + insert(value, parent: root!) + insertFixup(value) + } + private func insert(value: Int, parent: RBTNode) { + if self.root == nil{ + self.root = RBTNode(rootData: value) + return + } + else if value < parent.data { + if let left = parent.left { + insert(value, parent: left) + } else { + parent.left = RBTNode(rootData: value) + parent.left?.parent = parent } - else if value < parent.data { - if let left = parent.left { - insert(value, parent: left) - } else { - parent.left = RBTNode(rootData: value) - parent.left?.parent = parent - } + } else { + if let right = parent.right { + insert(value, parent: right) } else { - if let right = parent.right { - insert(value, parent: right) - } else { - parent.right = RBTNode(rootData: value) - parent.right?.parent = parent - } + parent.right = RBTNode(rootData: value) + parent.right?.parent = parent } } - public func find(data: Int)->RBTNode?{ - return find(root!,data: data) - } - - private func find(root: RBTNode, data: Int)->RBTNode?{ - if data == root.data{ - return root - } - if root.data != data && root.right == nil && root.left == nil { - return nil - } - else if data > root.data{ - return find(root.right, data: data) - } - else if data < root.data{ - return find(root.left, data: data) - } - else{ - return nil - } - } + } + public func find(data: Int)->RBTNode?{ + return find(root!,data: data) + } - //DELETION HELPER FUNCTIONS - public func remove(value: Int){ - let toRemove = find(value) - if(toRemove == nil){ - return - } - } - public func replaceNode(n1: RBTNode, n2: RBTNode){ - var temp = n1.data - var temp_color = n1.color - n1.data = n2.data - n1.color = n2.color - n2.data = temp - n2.color = temp_color - } - public func minimum(var node: RBTNode)->RBTNode { - while node.left !== nil{ - node = node.left + private func find(root: RBTNode, data: Int)->RBTNode?{ + if data == root.data{ + return root } - return node - } - public func successor(var node: RBTNode) -> RBTNode? { - if node.right !== nil { - return minimum(node.right) + if root.data != data && root.right == nil && root.left == nil { + return nil } - var successor = node.parent - while successor !== nil && node === successor.right { - node = successor - successor = successor.parent + else if data > root.data{ + return find(root.right, data: data) } - return successor - } - public func predecessor(var node: RBTNode) -> RBTNode{ - if node.left !== nil { - return minimum(node.left) + else if data < root.data{ + return find(root.left, data: data) } - var successor = node.parent - while successor !== nil && node === successor.left { - node = successor - successor = successor.parent + else{ + return nil } - return successor - } - public func maximum(var rootNode: RBTNode) -> RBTNode{ - while rootNode.right !== nil { - rootNode = rootNode.right + } + + //DELETION HELPER FUNCTIONS + public func remove(value: Int){ + let toRemove = find(value) + if(toRemove == nil){ + return } - return rootNode + } + public func replaceNode(n1: RBTNode, n2: RBTNode){ + let temp = n1.data + let temp_color = n1.color + n1.data = n2.data + n1.color = n2.color + n2.data = temp + n2.color = temp_color + } + public func minimum(Node: RBTNode)->RBTNode { + var node = Node + while node.left !== nil{ + node = node.left + } + return node + } + public func successor(Node: RBTNode) -> RBTNode? { + var node = Node + if node.right !== nil { + return minimum(node.right) + } + var successor = node.parent + while successor !== nil && node === successor.right { + node = successor + successor = successor.parent + } + return successor + } + public func predecessor(Node: RBTNode) -> RBTNode{ + var node = Node + if node.left !== nil { + return minimum(node.left) } - private func deletionFixup(x: RBTNode) {} + var successor = node.parent + while successor !== nil && node === successor.left { + node = successor + successor = successor.parent + } + return successor + } + public func maximum(rootnode: RBTNode) -> RBTNode{ + var rootNode = rootnode + while rootNode.right !== nil { + rootNode = rootNode.right + } + return rootNode + } public func delete(x: Int){ let toDel = find(x) deleteNode(toDel!) } - private func deleteNode(var toDel: RBTNode?){ - print("DELETE CASE 0") - if(toDel!.left == nil && toDel!.right == nil && toDel!.color == true){ - print("IM IN HERE") - //DEINIT NOT BEING CALLED AGAIN? + private func deleteNode(todel: RBTNode?){ + var toDel = todel + if(toDel!.left === nil && toDel!.right === nil && toDel!.parent === nil){ toDel = nil + self.root = nil + return + } + if(toDel!.left === nil && toDel!.right === nil && toDel!.color == true){ + if(toDel!.parent.left === toDel!){ + toDel!.parent.left = nil + toDel = nil + } + else if(toDel!.parent === nil){ + toDel = nil + } + else{ + toDel?.parent.right = nil + toDel = nil + } return } if(toDel!.left !== nil && toDel!.right !== nil){ - var pred = maximum(toDel!.left!) + let pred = maximum(toDel!.left!) toDel!.data = pred.data toDel! = pred } - var child: RBTNode? = nil + var child: RBTNode? = nil if(toDel!.right === nil){ child = toDel!.left } else{ child = toDel!.right } - - if(toDel!.color == false){ + if(toDel!.color == false && child !== nil){ toDel!.color = child!.color deleteCase1(toDel!) } if(child !== nil){ replaceNode(toDel!, n2: child!) - if(toDel!.parent === nil && child !== nil){ child!.color = false } } - print("This statement isnt actually deleting the object??? V") - toDel = nil + if(toDel!.parent.left === toDel!){ + toDel!.parent.left = nil + toDel = nil + return + } + else if(toDel!.parent === nil){ + toDel = nil + return + } + else{ + toDel?.parent.right = nil + toDel = nil + return + } } - private func deleteCase1(var toDel: RBTNode?){ - print("DELETE CASE 1") + private func deleteCase1( toDel: RBTNode?){ if(toDel?.parent === nil){ return } @@ -338,9 +354,8 @@ private func insertCase5(inserted: RBTNode?){ deleteCase2(toDel) } } - private func deleteCase2(var toDel: RBTNode?){ - print("DELETE CASE 2") - var sibling = toDel!.sibling() + private func deleteCase2(toDel: RBTNode?){ + let sibling = toDel!.sibling() if(sibling?.color == true){ toDel!.parent.color = true; sibling?.color = false @@ -353,9 +368,12 @@ private func insertCase5(inserted: RBTNode?){ deleteCase3(toDel!) } } - private func deleteCase3(var toDel: RBTNode?){ - print("DELETE CASE 3") - if(toDel!.parent?.color == false && toDel!.sibling()?.color == false && toDel!.sibling()?.left!.color == false && toDel!.sibling()?.right!.color == false){ + private func deleteCase3(toDel: RBTNode?){ + if(toDel!.parent?.color == false && + toDel!.sibling()?.color == false && + toDel!.sibling()?.left!.color == false && + toDel!.sibling()?.right!.color == false){ + toDel!.sibling()?.color = true toDel!.parent?.color = false } @@ -363,31 +381,41 @@ private func insertCase5(inserted: RBTNode?){ deleteCase4(toDel) } } - private func deleteCase4(var toDel: RBTNode?){ - print("DELETE CASE 4") - if(toDel!.parent?.color == true && toDel!.sibling()?.color == false && toDel!.sibling()?.left!.color == false && toDel!.sibling()?.right!.color == false){ - toDel!.sibling()?.color = true - toDel!.parent.color = false + private func deleteCase4(toDel: RBTNode?){ + if(toDel!.parent?.color == true && + toDel!.sibling()?.color == false && + toDel!.sibling()?.left!.color == false && + toDel!.sibling()?.right!.color == false){ + + toDel!.sibling()?.color = true + toDel!.parent.color = false } else{ deleteCase5(toDel) } } - private func deleteCase5(var toDel:RBTNode?){ - print("DELETE CASE 5") - if(toDel! === toDel!.parent?.left && toDel!.sibling()?.color == false && toDel!.sibling()?.left.color == true && toDel!.sibling()?.right.color == false){ - toDel!.sibling()?.color = true - toDel!.sibling()?.left?.color = false - rightRotate(toDel!.sibling()!) + private func deleteCase5(toDel:RBTNode?){ + if(toDel! === toDel!.parent?.left && + toDel!.sibling()?.color == false && + toDel!.sibling()?.left.color == true && + toDel!.sibling()?.right.color == false){ + + toDel!.sibling()?.color = true + toDel!.sibling()?.left?.color = false + rightRotate(toDel!.sibling()!) } - else if(toDel! === toDel!.parent?.right && toDel!.sibling()?.color == false && toDel!.sibling()?.left.color == false && toDel!.sibling()?.right.color == true){ - toDel!.sibling()?.color = true - toDel!.sibling()?.right?.color = false - leftRotate(toDel!.sibling()!) + + else if(toDel! === toDel!.parent?.right && + toDel!.sibling()?.color == false && + toDel!.sibling()?.left.color == false && + toDel!.sibling()?.right.color == true){ + + toDel!.sibling()?.color = true + toDel!.sibling()?.right?.color = false + leftRotate(toDel!.sibling()!) } } - private func deleteCase6(var toDel: RBTNode?){ - print("DELETE CASE 6") + private func deleteCase6(toDel: RBTNode?){ let color = toDel!.sibling()?.color toDel!.parent?.color = color! toDel!.parent?.color = false @@ -402,43 +430,13 @@ private func insertCase5(inserted: RBTNode?){ } } - - var tree = RBTree(rootData: 8) - -tree.insert(6) -tree.delete(6) +tree.insert(5) +tree.insert(4) +tree.insert(9) +tree.delete(9) +tree.insert(3) +tree.insert(10) +tree.delete(3) +var x = tree.find(5) tree.inOrder() -print("_______") - - - -//print("_________________________") -//let x = tree.root! -//print("sibling: \(tree.root!.left!.sibling()!.data)") -//print("root: \(tree.root!.data)") -//tree.rightRotate(x) -//print("root: \(tree.root!.data)") -//tree.inOrder() - -//let l = tree.root!.left! -//let r = tree.root!.right! -//print(l.data) -//print(r.data) -//if tree.root!.parent == nil{ -// print("ASDASD") -//} - -//how you access certain elements -//let root = tree.root!.left! -//if(root.parent === nil){ -// print("nil") -//} -//else{ -// print(root.parent.data) -//} - -//print(tree.root!.data) -//print(tree.root!.right!.data) -//print(tree.root!.left!.data) - diff --git a/Red Black Trees/RBTree.swift~ b/Red Black Trees/RBTree.swift~ deleted file mode 100644 index 4cb0c2fcb..000000000 --- a/Red Black Trees/RBTree.swift~ +++ /dev/null @@ -1,332 +0,0 @@ -public class RBTNode{ - private(set) public var color: Bool - private(set) public var left: RBTNode! - private(set) public var right: RBTNode! - private(set) public var parent: RBTNode! - private(set) public var data: Int - init(){ - self.data = -1 - self.color = true - self.left = nil - self.right = nil - self.parent = nil - } - init(rootData: Int){ - self.data = rootData - self.color = true //0is black 1 is red - self.left = nil - self.right = nil - self.parent = nil - } - public func grandparent()->RBTNode?{ - if(self.parent === nil || self.parent.parent === nil){ - return nil - } - else{ - return self.parent.parent - } - } - public func sibling()->RBTNode?{ - if(self.parent === nil || self.parent.right === nil || self.parent.left === nil){ - return nil - } - if(self === self.parent!.left!){ - return self.parent!.right! - } - else{ - return self.parent!.left! - } - } - public func replaceNode(n1: RBTNode, n2: RBTNode){ - var temp = n1.data - var temp_color = n1.color - n1.data = n2.data - n1.color = n2.color - n2.data = temp - n2.color = temp_color - } - public func minimum(var node: RBTNode)->RBTNode { - while node.left !== nil{ - node = node.left - } - return node - } - public func successor(var node: RBTNode) -> RBTNode? { - if node.right !== nil { - return minimum(node.right) - } - var successor = node.parent - while successor !== nil && node === successor.right { - node = successor - successor = successor.parent - } - return successor - } - public func predecessor(var node: RBTNode) -> RBTNode{ - if node.left !== nil { - return minimum(node.left) - } - var successor = node.parent - while successor !== nil && node === successor.left { - node = successor - successor = successor.parent - } - return successor - } - public func maximum(var rootNode: RBTNode) -> RBTNode{ - while rootNode.right !== nil { - rootNode = rootNode.right - } - return rootNode - } -} -public class RBTree { - - private(set) public var root: RBTNode? - init(rootData: Int) { - root = RBTNode(rootData: rootData) - root!.color = false - } - init(){ - root = nil - } - public func depth()->Int{ - let n = depth(root!) - return n - } - private func depth(rooty:RBTNode?)->Int{ - if(rooty == nil){ - return 0 - } - else{ - return 1+(max(depth(root!.left),depth(root!.right))) - } - } - - public func inOrder(){ - inOrder(root) - } - private func inOrder(root: RBTNode?){ - if(root == nil){ - return - } - inOrder(root!.left) - print("Data: \(root!.data) Color: \(root!.color)") - inOrder(root!.right) - } - - private func leftRotate(x: RBTNode) { - let newRoot = x.right - x.right = newRoot.left - if (newRoot.left !== nil) { - newRoot.left.parent = x - } - newRoot.parent = x.parent - if(x.parent === nil) { - root = newRoot - } else if (x === x.parent.left) { - x.parent.left = newRoot - } else { - x.parent.right = newRoot - } - newRoot.left = x - x.parent = newRoot - } - private func rightRotate(x: RBTNode) { - let newRoot = x.left - x.left = newRoot.right - if newRoot.right !== nil { - newRoot.right.parent = x - } - newRoot.parent = x.parent - if x.parent === nil { - root = newRoot - } else if x === x.parent.right { - x.parent.right = newRoot - } else { - x.parent.left = newRoot - } - newRoot.right = x - x.parent = newRoot -} - -public func insertFixup(value: Int){ - let inserted = find(value) - - if(inserted == nil){ - print("INSERTEDNILLLLLLLL") - } - print("inserted: ") - print(inserted!.data) - insertCase1(inserted) -} -private func insertCase1(inserted: RBTNode?){ - let myroot = self.root! - if myroot === inserted!{ - self.root!.color = false - print("ITS THE ROOT") - print("insert case 1: The root was nil and we inserted a black node at root") - } - insertCase2(inserted!) -} -private func insertCase2(inserted: RBTNode?){ - if inserted!.parent!.color == false{ - print("Insert case 2: parent is black so nothing to change") - return - } - insertCase3(inserted!) -} -private func insertCase3(inserted: RBTNode?){ - if(inserted!.parent!.sibling() != nil && inserted!.parent!.sibling()!.color == true){ - print("insert case3: If both the parent P and the uncle U are red, then both of them can be repainted black and the grandparent G ") - inserted!.parent!.color = false - inserted!.parent!.sibling()!.color = false - let g = inserted!.grandparent - g()!.color = true - if(g()!.parent == nil){ - g()!.color = false - } - } - insertCase4(inserted) -} -//THIS ONE MAY BE BROKEN!?!?!?!? -private func insertCase4(var inserted: RBTNode?){ - if((inserted! === inserted!.parent!.right) && (inserted!.grandparent()!.left === inserted!.parent!)){ - print("case 4") - rightRotate(inserted!.parent) - inserted! = inserted!.left - } - else if((inserted! === inserted!.parent!.left) && (inserted!.grandparent()!.right === inserted!.parent!)){ - print("case 4") - leftRotate(inserted!.parent) - inserted! = inserted!.right - } - insertCase5(inserted) -} -private func insertCase5(inserted: RBTNode?){ - if((inserted!.parent!.color == true && (inserted!.parent!.sibling()?.color == false || inserted!.parent!.sibling() == nil ))){ - if(inserted! === inserted!.parent!.left && inserted!.grandparent()!.left === inserted!.parent!){ - print("insert case 5: The parent P is red but the uncle U is black/nil, the current node N is the left child of P, and P is the left child of its parent G") - inserted!.parent.color = false - inserted!.grandparent()?.color = true - if(inserted! === inserted!.parent!.left){ - print("its on the left") - rightRotate(inserted!.grandparent()!) - } - } - else if(inserted! === inserted!.parent!.right && inserted!.grandparent()!.right === inserted!.parent!){ - print("insert case 5: RIGHT RIGHT") - inserted!.parent.color = false - inserted!.grandparent()?.color = true - - print("Its on the right") - leftRotate(inserted!.grandparent()!) - } - } - print("weve reached the end boys") -} - - public func insert(value: Int) { - insert(value, parent: root!) - insertFixup(value) - } - private func insert(value: Int, parent: RBTNode) { - if self.root == nil{ - self.root = RBTNode(rootData: value) - return - } - else if value < parent.data { - if let left = parent.left { - insert(value, parent: left) - } else { - parent.left = RBTNode(rootData: value) - parent.left?.parent = parent - } - } else { - if let right = parent.right { - insert(value, parent: right) - } else { - parent.right = RBTNode(rootData: value) - parent.right?.parent = parent - } - } - } - public func find(data: Int)->RBTNode?{ - return find(root!,data: data) - } - - private func find(root: RBTNode, data: Int)->RBTNode?{ - if data == root.data{ - return root - } - if root.data != data && root.right == nil && root.left == nil { - return nil - } - else if data > root.data{ - return find(root.right, data: data) - } - else if data < root.data{ - return find(root.left, data: data) - } - else{ - return nil - } - } - - //DELETION HELPER FUNCTIONS - public func remove(value: Int){ - let toRemove = find(value) - if(toRemove == nil){ - return - } - } - - - -} - -var tree = RBTree(rootData: 8) -tree.insert(9) -tree.insert(6) -tree.insert(5) -tree.insert(4) -tree.insert(40) -tree.insert(400) -tree.insert(430) -var t = tree.root! -var min = t.minimum(t) -print("MIN: \(min.data)") -var x = tree.root!.left -tree.inOrder() -t.replaceNode(t,n2:x) -tree.inOrder() - -//print("_________________________") -//let x = tree.root! -//print("sibling: \(tree.root!.left!.sibling()!.data)") -//print("root: \(tree.root!.data)") -//tree.rightRotate(x) -//print("root: \(tree.root!.data)") -//tree.inOrder() - -//let l = tree.root!.left! -//let r = tree.root!.right! -//print(l.data) -//print(r.data) -//if tree.root!.parent == nil{ -// print("ASDASD") -//} - -//how you access certain elements -//let root = tree.root!.left! -//if(root.parent === nil){ -// print("nil") -//} -//else{ -// print(root.parent.data) -//} - -//print(tree.root!.data) -//print(tree.root!.right!.data) -//print(tree.root!.left!.data) - diff --git a/Red Black Trees/README.md b/Red Black Trees/README.md index 6747154b8..e1b887c3a 100644 --- a/Red Black Trees/README.md +++ b/Red Black Trees/README.md @@ -1,8 +1,69 @@ # Red Black Tree +![fig1](files/fig1.png) +Red-black trees are an evolution of binary search trees that aim to keep the tree balanced without affecting the complexity of the primitive operations. This is done by coloring each node in the tree with either red or black and preserving a set of properties that guarantee that the deepest path in the tree is not longer than twice the shortest one. +## Motivation: +* We want a balanced binary search tree +* Height of the tree is O(log n) +* Red-Black Tree is an implementation of a balanced binary search tree -Under Construction. -See also [Wikipedia](https://en.wikipedia.org/wiki/Red%E2%80%93black_tree). +## Invariants: +1. Every node is colored either red or black +2. All leaf (nil) nodes are colored with black; if a node’s child is missing then we will assume that it has a nil child in that place and this nil child is always colored black. +3. Both children of a red node must be black nodes. +4. Every path from a node n to a descendent leaf has the same number of black nodes (not counting node n). + +## Methods: + +Since the red-black tree is a balanced BST, it supports the functions: + * find(key) + * Predecessor(key) + * Successor(key) + * Minimum(key) + * maximum(key) + * insert(key) + * delete(key) + +Since an insertion or deletion may violate one of the invariant's of the red-black tree we must either change colors, or perform rotation actions. + +#Rotation +To ensure that its color scheme and properties don’t get thrown off, red-black trees employ a key operation known as rotation. Rotation is a binary operation, between a parent node and one of its children, that swaps nodes and modifys their pointers while preserving the inorder traversal of the tree (so that elements are still sorted). There are two types of rotations: left rotation and right rotation. Left rotation swaps the parent node with its right child, while right rotation swaps the parent node with its left child. +![fig2](files/fig2.png) +###Left-Rotation: +```c++ +y ← x->right +x->right ← y->left +y->left->p ← x +y->p ← x->p +if x->p = Null + then T->root ← y + else if x = x->p->left + then x->p->left ← y + else x->p->right ← y +y->left ← x +x->p ← y +``` +###Right-Rotation: +```c++ +y ← x->left +x->left ← y->right +y->right->p ← x +y->p ← x->p +if x->p = Null + then T->root ← y + else if x = x->p->right + then x->p->right ← y + else x->p->left ← y +y->right ← x +x->p ← y +``` +###Insertion: +When adding a new node to a binary search tree, note that the new node will always be a leaf in the tree. To insert a new node, all we will do is navigate the BST starting from the root. If the new node value is smaller than the current node value, we go left – if it is larger, we go right. When we reach a leaf node, the last step is to attach the new node as a child to this leaf node in a way that preserves the BST constraint. We must recheck the RBTree invariants to see if any were violated + +###Deletion: +The same concept behind red-black tree insertions applies here. Removing a node from a red-black tree makes use of the BST deletion procedure and then restores the red-black tree properties in O(log n). The total running time for the deletion process takes O(log n) time, then, which meets the complexity requirements for the primitive operations. + +See also [Wikipedia](https://en.wikipedia.org/wiki/Red%E2%80%93black_tree). *Written for the Swift Algorithm Club by Ashwin Raghuraman* diff --git a/Red Black Trees/README.md~ b/Red Black Trees/README.md~ deleted file mode 100644 index e69de29bb..000000000 diff --git a/Red Black Trees/files/fig1.png b/Red Black Trees/files/fig1.png new file mode 100644 index 0000000000000000000000000000000000000000..7a91eb6932feddfc00890e16aeec6e1a079a75b9 GIT binary patch literal 24455 zcmagGcRbeb8$Nu8kgSTxULkullo1h1N=B)WJ<7}`AuB~lM)pV~WMw9+j3}WZdyhg$ z**u5O@Av)VdH#94KCkb$yKe9M{l2dAI?v-c&f~m;H7=@9Q7};u2n4Egs!Ey!0?}Rk z`4>46{`an9Unl;L*zwFcZE|w*-r-9_cuDJYR@X_(&fLk>=#Cjd%hK7&$?T5F{V#h6 z1P;PEB?WD_o|!~fJ+0>DWxgc?qCLJ}9%-MAcya#$2ZuTd18s{45rwX+&F!u?GuOKe zYDDf+9kk-g^GV}MMfG^y2zr{!{zk>YPJwZ*G~CNxDjuyMAtcCYkJ) z-fl@C@|EYHC0`%*)hGP-r=u0L^70$n+v$F+e1j$LL>FiT{_lfy z?0g_4DaF;RSO2@>A=P{Lwu&s;7^NSPYFxYK{%_`5w=*p{3qPZVj*j!zhI_X&mUF9q zVYKn~ty>!ORyH;PJL^dN;Q{f7XOb3%T?*-YS82l7Pd8{}7Zem^XH)!R+qqxTqeqX{ z_!2ScH+fsy*)?ipzk0RTNM<()(W(*I!@0RR(VOpT2K#_t5>grWOlbTHuCZDxh_pz z7QK9#mVUR$&A@(A-w?Z=-d=VYH(Gjnoom-lT6|`qp$Xe_fOl+cjDv~)?c3`&Zs6${ z+1YRE>RQ^`&W(&nc&#}Z7#MUHe3{znzPn1av8iCpMN9WwgP-qG((^V8Y!faSupN}1 zKI%(Mw)MNIf9#k&ELCN>ltmKu~b`hVwefw2b z))X!AhwT*2m)QT1&`|YDm#$v9;^N{`Qd$~xLmM9%?&L}=EltZrvE{jynUj-~pPye* zaa~hWQ%6TfMa9DKWw~SRGfBgmNi0}vM|U?P0|Ns+{kNW;pLnF<;nb|GrZQD4tLe{) z(l@K`3G?#0tSwEy)XIG97L%5i*4^EWy(1#b%+BiT>3#kB)o@ZVeZ4;4oGSJ>m5|

dwf^6XE6M6%crMCbg`h;&bw8cB5kLOP4Mg8m3fKtd-dG zvYo#7*7f(m{Jj0{-MjslZEoEV{HR~Ka?pKYV#1uAJvm@6gUI#b z2V3WCZEXz=hgSbg@?A`LkbStSs!G)0?Sn^;JXaSpDk@I(uL|+q zUW@L{{@6yQpui!%FR3p;zAO}x)K}^Hd$>O6&Ye5RERP>Q#!k0t$3A_!G@0zJtfVB? zy_})JkB>E#aG(5~*nQ^!Rn{zWt%HNZp+kod&!0bkMhtSbu1umN-H9Wkkyj!qyO(H2 zKk#;sgk~OEv-F@h>HuG_&X+|&^b%3%e!P`akLC=63)mI z>>YOH<>mWvhPRI(Rp3)DCCOaAdUbhzKL5=ddOAAObDxef+2H2iym@2sIYA-M*5S{@ zr}_E$2M@@jA1QqA>f+&w>H*_>ad3gZS0hQ>&!*+>Ed zh4RX)Si5`u;!pS%O3av(`$xWY|HCUGAt5Y`qu5qoZ}M;E$KAVkg>tGZD-l)W6%`fn zC+w7O96xrIqQhl3nAV78srLAibtWLp>lF^r?)qX zVqzFdnB?xR&|o+wuwYFZ+(&|L|3C_L0|M20%j~GM;s=cc-G7d}r)z;Aw z)+?JwM3(|)W_3hiIxMM9?zmHFk%n$o2#}sK_^;`W@i>K)K$W)8= z`S56$ih(fs7+Gp*>2h-$BRIM+Js@%SP+ttv=FQk)$mALLUq_msScyI0T_pfWBF z0k51uIayixMMaLTu3g{1PuMeC9_{&_d*jCS>lYKGYTvytEye13 z{JrJoCPljY{K1_P`Q*v|0|z2wVk|5zr%fNW5QfM@3q0JG~89gBsM;-|yx0>5`&iJyOEv<|c!XZp}04iOI?J)zw59 z_l~Bf2cGw0K7Ra&F!1;HFDW_B%*>3ECMzquQihKTF=>>)%FtbC_LXV=Cw+G*OGI!mfKfLF_Z=I{$P{|qZa@aNuHAfF z{13{d=klD_#!5j+Nwho%BO{|5H6uU4ZFB7}&~lz$d0Ixsht<#4w{PF5aC(`T*#D4T zaLpT0>hOD@3Xphl@y@<|`_$Dxt)?H<_+nX%RQ0~00k9kS8YkoAsZ%3CgZZ~@Y}7C8 z{0JR6lB)Ug;lqdj{{2J6crqiGck;SueHkCGz^%Xv4>8|xpL#En6l$L^!ut{XmS818 zo7v}NG=TKEslLa(PUTj3EXAv3boBLEwk3C379%gwsI~0o>2SWcrANr##ZNkPgwXr^ z`HP6=Od8goKYykvaOhD+ov(8L^CCO@Cn2)AzFv`M|KGoVwKO%?Zr(I7xVN@s<>~2p z^=g;k)x57=U5+^~u}4fyOe939+rum@)G9pt`7XrH`^e$(kZ+G4M^ZkP-u;S>!tC$Q zZ`Ipd(oyF#Xy|a#dG=e?6lwy7T;OGA`sSNfT)fm*?uaUfhXwxGTAJ3{u0DSB=*s$f zOG^vQgSCSP4@Sqt+8anoCf$fG6G;PD( zvTRco_V%k+*V1A2j#OxpO3BP@1Pp18PQoV^7A_`Ay8<_>n0>RfvI` znHl7H%6(zvgX$B~5ql|}yhHpRo}M?~-JPDCwCV~$Y0yExWd<}T{iups0)7)bT~ z$B##+q*dN_yh=}h`*ve0PhYQN(c)6_K$&OP>s*`nxs2RQv%2SkUq>FGeBfu#+!7<& z*3$B8dRn271ISH8SlBG6@cjep?tD&Z>BztgiKv}Wd ztckbY3uo@i*VkM$P$JR0u22?qDOoPn*<661-~J9+sa=YE@5TMW?++92z8+u!z(+pE z$WKH}d^x~%VSc`>ygW4Qs!1PHf9Sn?FQr(hLZ{Ey4VRGa4)th>eDb8^{JGRy?gt1( zZ{7^c(+soq_4l`n5Zv6|OKtl<4!Zy#rhPlwFl>+GFc#>0=KOgI8@}6)c*=o+$HQM3 zVp^S3Jl%B-TW_^{R=Xb+i!n>kKh1kOuZpl#roPrN^yu6f^Nm=GN`{Y47>=&{^tZv<^yF&X% zzWv*`fK)>Z3kyfbKT|Gu0OtcW|LTcpa14H$1%J52#US($I417r&szZl29&$$Jv~*t zD%rX^{S@LAQ!_I+{#Z!$DVF(WXJ^mN*;=cO;f)tdBF|?S^LO|5-T;}aNDSdQW7DLW ztm2u%FCb8NB|j&Jl1X1AKskNEP&2A-m)OsCFYOCdLxItX9Gim*LSf>M(?9N7(z+kp z^7sQADRc+r7}jvr=XcnIZsvx>#9ZJFTdaKF7B-y7kB|)ua z!Qs)-@%z3+@h`+rpRWFnV|VM;t!|3P9?6R7(n4U=$L`;^Njos8!C$^pkkJFRUxH9TV3N9`rcIUIssB@gO9<=YjvD=XrO=H<)2^|Jngf%I%_ z2M!#dY*C@1p`kwUt)YRmK7!M>X?}EaGHAFdoQ{E#4kv;9O%`cu_`S91%!PT65EF-x zll&jVbH>MCWoI{}Ni`fl*W7fYbm)f$`Lc$FhK~YEdTOfgAB1*LiA)zI9pig(TO6W& zEG!`(8S3imN9X3`?_x#e)amUF?DT!YG{P|m>4WW$DwyiXDK)_8524G8qS8|4)_;MXR z`c$5Sqx1$yp+TRx28)zEAxe%kSm~7GM5~nhiG~He`12V|w{9iT(y=&XtOSLBnR%&I zE-+l{JKHUoi!cAA>? zdrI$;anOc&%X(FWR!ZACId*L`SX{c4@a&nOuZCFbZaTte^1XIRQVV0_Er9lpIy&@v z`U+(aK_^a0Nwp@)#yi-j<>btCWT%f&nSbYWou*^82>$w7+c*#$Yb`5~m|hPFrI1{Obz zjEsQ#=VoU!+AS};&go{q+7{sc!{{SHI7Q$m=Gf!&jil~^`X@3J4hIL7$1KCy|EfKg zMfmyoMMc{_v|6Vo^syQYh!UI#8pJiX3IBp0wQ)pVVv&+>Q%{VHl(gw7-q^TXR&n2c z59peMy?u%XzqSBsG2$uPP3B&W+j$OJ6u>8uktzj=DD@2u4Zs>lnP!0uadyDFh)K^8 z`KDxK&@(VJ25ef}*z^P70@|9J^YZbXsPPGY^eD1<3>DAG*;y9K45X{R?_0kItJl}o zo~SQtf1Hwui;8XJ$SxE*V-*uRbfdb=y{tdi1Fc?fXztE;c~ z*VR9gyPLJSl_<|)c`;#XY}CZm)W3dsWOP*R{CQ}bWs`zqlat9(4kI%^iU>X^qp>$i z2ddpJU%PfhfGh2Jp6%%L$=-$++g3p%BO@7VF>H{J*jPp=k08_f`hrG7P`GmCN^Drh zV>QT>US3|)ho+~KHC}#QT3P~O1s9nZ8)IZ<#*+PLY;64U#oj4?t@G09moHyVPfZEk zD9N!)A*Z3)o*%A9tUx5DaCA?!IbQz3H<4&t}d0(Zh$f{S|*lK0NyR zRhx<`6lBcP!=q=3nIF0lLPq(pHN%&J+s;3J40s%$NdrM~QCO0>CdE+Z5L87WnzFB6^$;0CxUwzrd<=^Y-ty5#kwuA4gtU7tiGFzNY&CF(d z-uwcD$>LQ?&(oLVv2>m=H8nLhF;P5oCeNUXg5gF&ZBvsaSUM1I5H;&9OH18i%Lw2s zEX<=vkGxx{ry+Y4Ted%Dl|FjxSkPMz35h3vf*gW)PMkP#>eO24;Jw>+c6|GTO$tg6 z?BAb|kU;7!!o{@+{!p8|zOoWBGH`M~9X)-}0o{K~OG5noZp(B1y51@)4V`P+1VedPT#b*w^ven4?SjfW~RaT zDzN3{mtQ$)uI<^om*$za{DlkFBkzNujm64&opQZ*!`g)f1;HnFcya{0-mkW-M-^0rKVqL68yT3GDoh$5AG`gX<@CL~7i1C(vrXH-Z6=1tsGay+1UppxK(gq$U^6`fEoX*T46)RAOQx_67 ztWc@;?>`g9`QY(mwmSt)o6ny=hm=FJ%2&}2X7=ghN2Wz0C=I2eSd-ycBvGV`$AHj5G*Jx+$r++ckh++S|bT%pUiFl_UbB> zgQ2OZm95Qn=U?AtaU_}|xRGbOJId}%N|%B5bE`ZKDJ!a{dN(e7qhw`u_3z=QUVkR2 zT-j<^Bc`S-Pn;;_+}6H+9YKSR%GdsW*)hht#>UB^p_(_B>A0En2{q_5P(za8{Q8uc zvEEnvDAT95wl?I-Z{MO;d&-3C0s_do5$1qCF+$hwOnu>WbaWKiII?%|UZ9G`z5`{@ zY1GtOYLgj&?B2fzxeI>y5J8!A(lL;EY2n9vQ1)mM{ZnZ?drz!HkB*K`H&#q-fBO76 zNydFqmr^KG^Cg-Qu~H6Peo-O>LmXk8T6WEQJRBS~U0tqHMY2DYm;X$*g}mN(;6N`@ z3eM3*9KcYKN!>TMqRPwN2L<0#>P=Z0*$CLt(?{W{A!=f|PD)EV_Qrf_Z5_LA(PfYO zs`B1`*EZEbA7gB6+|k+jrnopEF%i_L(a(cgack|D=&@sOpt?VH8_!yg78DS`U%kc? zy}J~+S83!PsKlY?f^(7;OE&$Sp&}8gPoty3sSosw`6P%}AfmYqCPqf?{FzX1&_}CE z@JE43P(lLBE22i!in4j>!sGLdVU3Lq4bTPAROo4I3w!nMWm(xutS8Zj_wRrH`qhi3 zjjRXVfdg6^8e%B>3=AJu_O4D#qrtV3Df*@jYbPJ4|TJHP#wI#{61PGqxnKL_uvv&g(AzdX*w^GUI zgvp&t%PR|`Xq@H9>Nf^VUXzxVzIG!uKYtzt3~&V^4H?IU(_)Qb?5>WEEp2Us#a3F^ zulGP66&4b@NBd|U??948E!!3B>GIX91)&ZFa=Lm#P(*|`vN>xp%aNun`E;_lNrS!j z?D|{}n#% zwRRMxMoOw|I|!dN`I+_8zUH>JuCHHNY;9GpHcYL*4hf<3QyfOKg_4G5vhMeTyXjsZ z9@5jW%dy*@P>&;rEbZw(Y#(8#({v@mp@riS8QSXg*^h{4Xz zZu#$Dsy%xY@~+A}bZ7yhzENt6*N5iajg8a%{OWaQyc=$`dofoy1x7Zd6j`>XAwS<4 zb{!iZKg&3VoaBhij7L6`-f|G=u`N-WVc)*mJ2V3;s%}0wMORif~&1=?{mJAn8boqIJ5s z_;{r6Uevr3FOGfVNH9exX=PqK>#S-==hcE<;Zbq%LphQx%*?+a(jHu|&dxrssrkg0 z#@eUdj3YuJi0$GBo0|vRh3FFzTS=#!Z{_5$Hw3n$_qDmXJc$0vkC$Yo_!c+=@52$uA@l-(eSIgCCXw%>G^gX9LGHNsTBfSA)j*pKwX0@B${d}+H zJj2E%EDbG%d~8%IZjurb-wa7y~*5CyrKhLz%dqZ&-`G2K4vCgL|&k zyRn(u3EPeq)d}0ap@}8#@OBR>22q2%(D@tcH^W07+O2}lpl?=YnO-2M^mnM%Zy$Fa zK9)?WD#X$W{XjiEy)prBLLf4>k30w9dq~o0G%|#WOG`b`Ekx_tJ%L9ue^f&#(td>{ zH$40cf(qwkYh{$i(u%{2CN(*EFiF;P?Fk8oh4$T+WH~R;hF+|O{msn${P4YRXd-+} zE5xLDpB5;QvU+=a=f&A@cQrEBKxE$l_`iRj$kOR@XMaCLz$&Bqz}ko)>-%0o#^UvL z31sBM$Wgruc@^I8IRla z=x%T#u|SoF&d8|O+1Cdd>Ew#zp+nEmWo=Nt2oe2N+L3~Qh!OiT=&qhX=6&uQ0iL0@ zc6P7v6Bb6(c=2`7UnL=PWi<^awC!HJc!8!mWcV*XH<}VodnYNUgSZ(9es&++!PjUP zeK53+yMi{#MS+Nw+$Nl8JGcB!nKWNeL*_{;b2Nw`6zhLrYA8a#3R zIAcn?<*O^Xg%ElF{hQGBMENKe4wDU4hStrRJN^R8i;RU{hq%9_d;=NE6DSV?hz$9YrVJu_Sub8F^F}(}xdTv#ny}L+DbQF!uMG7b&Ewa4<%>u^ z=+#`oZ*_GI7MPHg=pSs-eV(6h56W{jPp|gw)5rDi#&LF7Pv6_6R-EE&gAICv9cTz#UDKc$-!hFKkzWM4EP0c!5wX-T38uK;2#J{>;PYxtU5+}%c zT~|;rYBD^$Yu7G`XLmscnL_`eoow4v9NZsjg$%#2a7g5J88BZ-$v^y>Rl*K8`S|gc z)XAF&6syh`=qDAvp@N2wzg4ug0|EWm(t_JdJfG3QF&c-~D&B-{ytq~{0w(ep2UPOL z@8AE`2hoIx;sDs4IYYE~3w5<@jKLjkkho*FmET%}bAc%Wy6AiK5Wu1 zA#~7tg+QX`~gl+C3bmRX#Oeg!y^Vn zlBCuiKChPTt#!L|=YnxI9{i^El{XB!BTWVx{xTzD{6P%Wq=9l-?p^{p@`C*^(TTfe z)@zKL5m2Pw-1=r8)YveaWQ&l8KdJ81Dg+($;7fYSaV9$~?yHJy0ipxfOVM5%8Xktz z!nf~CWqEmlOV=uvA1y9c2jj0N9Nf1yPJaEu7{em#p{=ZJ-kx^$!uR@uvT;-glqc?p z8TQIJMx30>SFW(NpCk*^Y>>b01XfY5^zcx;Tm#{4Rn=g%cbo2R$G5Z7SjKdlFhqJh zlNNkq&xKfsNk~Y(zrNY_T?G5DAh^VRFzFGU0p9e zC=qqu*~R5^Ypc?og7kDOK6mz7`THuI)^^-6XL(0YPh9QI+?*WRHD{3ePgFM(7P=Ig zx?bP3v9SU8^d?_k#LA1kue`Utm8gCo5~UATgcN}e^goy9^h+*!?BJ0!EmwlNx;hAv zxehVPm$;J~I-`j9;ST%0@c4L75PvL^z< z1?Bp&25KUu|QSDJJWkv&I@58F9u}WMyRRj%U0AZ{90YLHH8}(cDNK0@O(@XCi}k z2$-7)`gAz>tyFq&dw2IruU&P3zdw43q5V|-Wo1$ggHY2PF-u|(pRq@>39gnhAz`2 z(Ky_dPj8O~p~k62cF%u)28%#UOuRhX8zfeHeACS6wynlLaahyFl)K))Cka*}CCFd7 zf{txS1)ZcMN|e~KV~6(#qd_^^H+5c3&9Q9g!DkBVA|9@YrWYdc5WFw3;{>70rV^lB z?OF36Wy&r13}nCb_wThbiZLI%RoFM;;^LYd#d!GmOw_u?egaCMv&_NbjmsTk*5~9* zMMuP+x)+iNsHM46wVWDJ?0Pq#Ib1}|RHtIBk0QBNbW@;K6{X8||9b_vtD~*m{q-!M zT({CR78M;a-40UlR-Vj#fp-t5v@><~RXD!_(*eb>&^Y&tq5Y(w(E-~fkRft`{<^I+t%PYZ+>VF8-Vj3rH= zpEv=oG9yVz$$x+Mm+YemYb?5z@oQ+vXV?N_rSaBLK2y5prY4YRf!l32ih4`?1_s#Z z=$sZt&W;%f!qzfePex4aSFpl-Rz-!|^$dr21^K049oL{C751N+ zq53FR$8G!Epb~M8e-W>@9b81d1v*5s4SCxH3Ay`}l{q^EDA?=1b#$C@lO;Bzv{vqF zY56tRUs>GVvQ^g;C6Wjd_!{qUiVP@fp8`yR6D+NeAD@YQVy4AJ3n+w!jkaeNtdqa1 zx6Oai42_Q;78MQ4evpvRm#yuDYBK7(V44BZX9=B_S(R$Q{q3&=|DxD#(^xDy@ zU^%fYO};FAu>4_h@ll?RFfWdR#}MC}&YA*cU~^7#2T1b(Z3?wn171MOxRf9z9(P)} z^03Lw%nYq^A1tJ3rxhI=R!~J~!l=L|Ny0i0NNc_k!?LSGbOq)<<{Q=g3 zw#gagpkDPj?tat*)RR{Id%?G z-tWG0N$UO<2pyf7mohy=2CF`+xjL~_*5+I!*>7%0wH^XO2;UtqYWggn=cRRl`79eX!gOu%^yF4 zk+;T*a|;WH-phc6W~Vm1aOc>cNk$Q`g^(uYOwxqrgZ1({BNlUQuid)#H_MY|=eN+pLR&A$YBP}duH`N8CH z^WJKJ+|77&fuIb53N8Nm13!=D(KtNnj;O1c7MsbKQgqntvD^65h73q)23;WI`SU?o%~_u>#Y9JcjytxuIm&DQA@XDr zHnt?#zBm80od!Wm_)X?QBG!pbf@aqkEqnuwy2fGA56bCk>Fp2&NZ*P<d5QH8SP_2E*?;C8yaR6r1kN4JLF~O90o4?` zyvf3{z>y;nk&%k@$9?;%D7W|`j4Ul5%zNCtIS5H1G`ig^xuLSE%1c+b8_@Sfk&%?y z(J-T%-#`f<87Rqhj=lHI51}-?^>F?=fHbPS{fJ6a6X5|jug|kXO-+U>f*Mv@WF#bd zZ{7CwNX})Vtq3a!Ef{LGT$G8oC@|Y@Y1-j5gXCjsBOew9NVIkv0wX{m>#YYI7ur%90n-`@=NO{mmlXSxb16Rh!cX@d^oo#I;cwP^< zHO>ShET%9lyUW~bpC%-W8a`b3s{i7@J5ir2O62^xNOC5<7U-<;@aodbzr8&{VwN#||rOtsF`2uV94u0jz zZ|1slH_*Gic;SMnM6V%IPu(BMK4ruuj5^SRDnsWGD($wvP&w6;LY*lyX3do*$+c=*EZa1j=YH2$3SM? zkOU1U&L3kP=lqsvoV74EO%F{*LREUtxd=eERo751O#rO!$cm*LYe=4W-~7%gWxsd z`p+Y_x7RmctR~+oHJd^s@JxR24%n6TJQ#Osu6A(eCs}fJM)%hZgYrA$$Wvc<`dZMti)zwK-Xi3n&*q#dh3n#(%>GAj!mcsOS-{@YVY9J>x1+fK{>+_^)Z$|sH< z{W>_vuBf2R{4mSPl0Ys&LD}&2>(fx>6M}nF`c}72cOOs-P)L6N`SToX-_|tu{WwO^ zppFwWx}TZJM>hB2`ru+H^9c-K?089*1fx){j~?`v24=fgdxCM5V znwmP=F-1f`tEtR!61(`hz|;v98pBkN)UzH`?PGs^GkxIHZUVv3)bxFWZtB(78Y-7J z?RI^pPJhICo+zl^-NPd=AV9(I#7`v^mC5mObUQ*NOHESkPM$u!4Y?9c2-KRUC_)Rg(bqErrWr5q?IrS3-9UE-hkT&_%3Q|X+?&IYh2yw zLd&`@j-dqocv?3GWfEl;X9pMoau?zr=%BT^S>eVvyyH^hDKpGoz+coj3JD0_5I}5X z1(jmVx#+N-aLwmwyBO=-{hck6& zK`0XhS4O7q`}ZqqYLDbOU}L!uD^}apwTz~1$lmCvC{`)^nx-aIXn{bL`ubh~F}NBQ z#Yj&~QqmEd134Q6z)c1kQRl~xKcU!!NGig6(qHA-Ra>io>uyzEiWM`0UV&W3gEZX)&Lwv)cTRcL5zZaXqw14C@6G?h=eNl<{K#j4IlMQ zz;pM&D5J_lE!Wi4*7iCjCEu*&;K2#HG|iW=K4@xaFiH$X$aCmkyT*C+4rH>HXkqXO zzsSTPdnvAnsj)Hm`$EMmF526R1uHSJcm~uDg9M@6aThXFqmc+v3ntq9mQcVCC9d5h zBw~?8mSQ;JXt}a!@?V8ygALkgPwHh?RrL=J?ihIIuTBgPqde~z3c{mbrli!sn1XlC z&-w=hV0qBSIbkYo*Ixmp5P;^?Scg3Z)i6V0WK?<=z!u_#;*0y3_TY(ZM)@=wrmN1( zv_O;rY1Yez;t#K0z8uy}uLRo%wrTwU`1(Ui>Do0T5f9ujM989d=Z+mK-n}=U;bvuY zbmFJ$>5trP7iN1;z!qmoezKvr)DD)|L%&ELJa`Zr7l*MCN$*Oax08+&A^cynQ&PfF zW6H8IjRcz7VDZdeD&ff!&3~$4u4ZQA?}HB<;v)r3`}XAvqeB(c+~=@lOKn6ZC*OqY zG%fA^>J}^!m?C0wV1`CM2Y|b|7rtWDN{P>{4ULVN7=na+TWttiSFn=tU1Ha$ z+sM-X2@>;MoQXk#NJ&mCj$lTW?c42~0^4Kx61P-5|AeC#^Rv`!L zSva9n3UJZfO5z{-L$KN_-AKLpTzWhF6Q#Gl34AXV5P9sfBKB|Ogk6V-o?&h~#3Du`h;vwYo`uV1S$QU}%#qn!d_@!7_1bldi^rQ)E?s^#?d^@YgX4#>{FHF))0E~-&CNT2?v6Bq96}mzS0zrTva&L{Nigsf1dsBT zshxx4?=PlBoc;A9T!b+$YeywJJ21dh^iD_GwIlY&zSWIq6O)Z~6FE0ZA0JAOPfFSu znXugVgDUDgtAr%4pV3i%{s+&bF)Ko=Be5T?aj2HVN#fdjZ2vAT!KECObF23L?j|jV zQF|##$)e$RL+~(#t2it!ETDHT*_jLhSDF6SdEUrr=_O?BrZD5h`FWf!kO#~vY8zbv zvj;KBY_~+aR4L>A5m8Z`h{xqOFhP6yY#pe~Has$|8?>0h%1TnkLPeLo+4YL_K5S4D z|N45lTR*Qu;rx1AWPWY{&9r#SV0xazN_Y!nGd(M{ZXJZrL z~g&YrE51w#5uoF_Z`y0WMYIV>E zw{Ehz*f8)FZgT6*ADx{Tz6<>60*iR{#$pRj$iBQQ>#yY?F`uyR_7ONHN{~Ny?&X^| zI%Mj$jBBk8-@eiR@q>ZjUU8Z~a!RN!w=+`a7r9U@!PVCW;|J5@V`IxOJI7nq2_eeG z<>%@n@~^v)fGit%`dRcL0ESgAuhtjp^7mj`h$$xV!3ID!+Wupwx80 zCH-FYRC%5tUGTuf9cONcMnV4q zDg*-7QVm1rZ(#tc2||A&J@qvCz}K%wb$8f3eZ4CR%%ORIt(RXhBtfZTBvprIV|p+Y;>Onj?X=-_!%G0}@$92`S4Ga>GG zgF;jl6n2$NADNh@J8m?KiiBXLT%q+FI7CPRZIaiaqu5<9<71GINZIDYaqpJsMpMl= zc9TE=!_QYQ$q#-9LT{vY|3=Ue6Ib*_NNcGG@?eg8d1c*Ok5J@S?Sq2|LIsmoy4oe> zrn|B;A0?K4(jOPj-r^S&^oDWqF0;ONtwjAk47d!}?Y3n7p=4ttY#w^by8eLqpMNOT zyRJ~g?|qI>uc+{l=hJwpZOxmCr`+ZPGGIAg(Yc)vyrhWiztQ;EklGkXMy`Bh(+YwZ0s(v*Q2<&@zz8B!!IivZ# zRIq3e)G2>{p(XdRx=D6B0_Iw6?bgqq14*B-lJD7Lqw^?m~LZ)jSN{3!4;Ywdqro@klAF$JOB*s~*C zC4U)xHrihJgXmZ^dHmCrmjRQ|vuX|FwQhBR=Xz%Y^CkKv9aAljQZ9(FdM;CD0w=kb9UJ$iwpf#Yx6yr zAa6-{aGa>T&BeInTsJRS_dOvN>L5-dVuH^FUXyq_<3C}T*0BD5T}jEbrt`tL+55LO z>S}73d6j_=5hX17v^Rz=9?vf1=H_~#>9*t4aCAh+;Fh7G7+mYEe{$rYVxWyKu$O}6 zyjn7hd9PmESzCwLl<4Z{pbL0KPcI=Z?m8^{RvkQ)`<^=ieZh5fq%HYZ@f$D7z451< z1xhUF2pYP&u@Moe01c&9T9bX{m}FtB+n$0c1jD(9`S`s5YfzargdFN7rDF<>Mx>$c zAlZYU2Or>r(a)IKj6*REsM6->*N%=l7ZuF!QpW2dGvU}0%OxDO(%iRp_bFskKuV_h z)Q1m05>&+N_Bq!02?LQJrKSp?3v7MbAJab`9;dE1viZt~M@4-YvZ^0lfM#pC?B^iW z7jj4v3e5cy4qthDXXg)JgmI@}l=$8Q%e~iibqzi9QC7re7?B=-PEU)kGo@4E%OYBj zN=m}dH1%f{AgqGK1=KIwBn~pG){6@fF)_d6bMg1E>>NIv0aHn7Nr~~^ri-47@7tT2 zbPTraI8(g|s=J1msF&k&asr-oB>nw$dD^V;!v_peHnp@YvpS7JL8c|g;sVr8&&(*@ zd%SAvR`%C_&%m8KldG$v1XZG;{i3f=M_9gm;WE6k!1i9?Bh;{~pOcecrY<~6(Bo$x zBqp#CXzLnFl`ekPR2-d%608s2LwTg>4#*x599Km538N7VM?|RphrA=QF5b22uh2m& zQJ!PzlQq7b;2ci}fYSEn@=dp|K{_iKVo8+7EuoWORH^Ucay-zg6B7C%5s#^+jw1rZU@ApzqK)_9-2{qY_+ z4&%SA2TH~mKM8b!*H_H(Bm3+uIY}L0U_n3BBI?=Bruuq#i?|*qb%N(2Z&Fg*f$c^# zkIA)5G>mXV#-;rHypvS{!F=Yg8J;LwRCkDvTZ@`t^X0SvVIL9E!H*xOxy|Nr{t^9< z2`QCS(0zg}B2b%$U0z>5G4ka!^||JW)a&1N*9@kmeXpn>F4hcs{`PHOL(Nc1tnRvo z&KpAhCB3_kQ#tn+tibwp+saDZUKYsj+V$&PCq0v*qB7Fb>T25j8b@K2kWM(ikAxnX z&Qe7Yg~j}-6FRp6E=_E6RXfJOkDm^7g!g!YZdh)ff-R*fs6029Dt9digG`HimJJVz z8id^H@oyZ(d=Z`p_F0WLT9|f!^X4x+lvx-1aMmkK>(F1&ST%$$NXmaUol8`dW_HQ8 zsho8&AYAUFmN3u$m-}yMN?9w%K-=Gu3boa)TsaQeqrmFu@#D%P3BahT7u;^X`D|`J zeCAAXDy8ON^>xBb@cW>J1JwpV?>qC-V$D{BICZhFPj3t!D@{!@Y8J-4Y-CB!1MQT- z=w}cMr@~Of#gOqND$0yEcW`-x*t!OzFE65NTG{POFoo9p2OMJNS*t!y5Q633^eaX?mDx&Co2$we72v zHAi*64GZacdR7KRf9E6l`-R{ZRR3e@7tM)7uV1}V-1__norKs}%E`hlF!04cKOm@B zKkeG8)qU$GzTb$O$k+bYci{=Um?ux}zt?>j930B8=#9oRPXm_Yj?&cu2oVvCoS4y~ zVm>aGcMHcy)hQ4G8;zqx*C9?{3);o$`Z4&J+Z04lhju@5b*Z0+}@qxeu)N7Ve} zoPoi+YVQS@QNZQ7mAmtAombD$g!??)pRA?1xqv6i4sGTqnU^urbL7Ag$9%?qxFFK> zSKzp&TAjn_23>B)H1ejh^>EA5QnHzuRg?98DxbRqy`X*aVUHgxkN;{Mwy)olauXwu z;jxU1SNbQ%`-|_chU;vWJO4VSpfIKrK)#3dN0nz&HcYe+1;*6%^mhDDidW1mEP{^b zaC36*in|bByTe|76R`c~RP+PTqMkEeh`|gO93x=LQgYr8( z2=4xgV=6A`?8?U|K|j{Togp1D6{zR<5)h^tYe7-b6Jlb9wAY0M1%J)Vv}S)w$M2=2 zaF7OSz;cM}p};Fxj4m(qdWm~XhurkK&78!WB9Sf|XvXV~;jG<=!idm=b5ABO#a{{O z=4jvE{juqJW+qJ@g`#~N8ihmtiP{3rfe+7<;{<*6XGBx=W%p2z8Dlf1iq9ybqZ|@z>|*L-J+tRvUCoBrouU$<8z+W z%QHXH)6(z_MQg`zf`x*YW0C=@5q=eY&&6M_t0BgtJ=0NjUW(-+!VG>Pm~gW0D1la^ zorZ@RS#Ya3Qa5ame?+bV!^-Lygn!A+!vp85yWfIaREWk3ZSsku^`nl;P|=zHWt%fuUu+-4%9J=6vwYUJ!_FA|A?PDY>VzHTW%3m$4FQ-C1gN6bjaU)fl zbZlbc9h~17Za{X`(fNj>Z6o9`*d7dedv9ePUmo*7l?SyH?Ka}x<`x7i9C!#Bk3u8N z7eRH|W2mW@slg8w0D|QaVPOpZb$tJhIqVNP62AT@Zq;}=6kxQ9umzIlt&HM!GMj?< ze7b`NQM1+I2h!4V>?yWV{r3S{*c8nLjDN(%_2BywXxa2O*8bkc@DF4r*mtI6LpYBR z-GNOeS=JK}Qt#%?*C-^0hCat>X=XdI>3@;bMn;S=+`dLrdoc0+zE6ug#s6;(2F!i3 zF&R|Q>~4Acwxs1SsNz30)h`-(M?81sfA3(@_y)Z;pY;r+UlxsT1zziO={wnoi*T=` zlwIT7gpW_m)T@sK!}Qm`eX?1$Z~H|^cK72c{8QP$b)ug)-k0YHFKB9t_yuIztu0O_ zSQHZ#Wfc9){A=Bl{daB)_MCDj)KFcY$H1QPf#)oJXU%r+HeLG5Po#0#KyIl1ZMxHOg1#OJ#xz8tuzmLD&${Stf8}&4e4WVP?kWN0 z?^WrFl#zr}HX27-e}42+cXkB@yCx||;P-o422-NggF$lQFXEOD{nU@#Yr3}EyxiJ) zS_xk=HWnmSp~SVXH;@V%v5zc0Se*64m=HA#p$dpiKcc=^_~@FjoxL`n!nv13Ub24) zLu6-N1^JH{sak68@!8-wrc%r$wC&w5Gi4}uT>Yx~sYCdRGT3Uqb#*l!e@iX5yt6Sp z@`hp|qqb-<52kdGQn2EgfyTTrwF=-R=)vuKDV9|4$oN9uDQc$KT>24RstlDdlJ(36-V9 zoEA%_a;#G%TT)3y$`Z$#eLt?HEG5}VvgM2=N46+Ol5H$uY(wgh^?s&vpL?I@KG*Z` z$7|l1dEfW9e7~Qqjg0yV0=#uwKQ_nD5i17thdGlk({(xB$DUbKdweOpy7s!U+|`wL zp{>52^JkMJ00%xkwO*Uz_MY=UmV9w0U*%d`&U$<{WTtD&t4mC~0OReErOUKY^D&Ig z6thF%gVC8Q{%$+a7%S8!+{8;bG&H*2aoaS>DtF&8;kYw|z9``^Kpqbr+)d?K7qVgnAY{A?&f#@^Sjt3Wf za%By;S%T~=$EGCG`ID3sOHO7D7pU3Om`2ob4v=sU|Fg{R$%yf*`pfrXqqw(9eI#d~ zgz4C=e^_D-x@Ae0D>H$zy?EPiMUIl2`$#*I`aaaWnf>J zosuG-B+KGa&fXou?wPWzfZ(!7&8*7vRBDiXJ%Ca=mL8F()xd!y1}t^4ej{v6^Fs|5 zi;aAlqQB~??%n?EU44M2AvT#~Pm84_B@6GZxN;aC2?;;+gAh~0(N5V!|MN0bs#)cC z8SnHjGag1}jdN7#pPKAzNhD>lngDXAA9g<|X+#VJU^x7N0=uiCRa^MLMe zAtqC(aZbkQz8abZT`gl(*aaV}jIOSjN?B`dVgonPV{LO9fZhEIGoRxXDeUB~8AA`Y zsxS=``p7}cu-q*WZ;pveM`}T~zQa`$hX0f2nb=1Q&TtC$>(ge(irL~}5OK!~n>97KylQ&zd#&`>wzxY8NtM~L$aJV;Hu zDfVko0)=HfL&p@;_Z!6HZEYH9y)<}wJl9rW=jg0^C1qlCkcZHr8C9;M18PEMfzm6E z-MH+o#YLL7?j=HFs^koX)8c@{QJ2P;q>}4mqN3QyPvl_x);@R6?e$McJD7Zaxm`Fz zbn>);K@6H=3qz;xc^fG3aMTxLZ>w))aUAC_1_p@0DTW#hBn!76x%JW@lgS(z@js|F z4j~CtDcV|EDc8TE%fj~lZD|Sq8LM`^bhN#W%*NP^+1VC7y?^x6#88c7Wwy-CyWDm@ ze(oBA*H}*4Bd*7c1L&ipo$c)#xwr~SO17SrkJ3p8Z~$J(SN$a96o!AM>t28N?jx0& zP*JXR=Ve&x!1AXiWDkb^CESW{u(pB6BQD;w|4&~w4XTcPP}w(k&o!2|W1k7_UM0Ms z^qIWsy)0cPAZggQAYuZ>kJ1;YkA?<8jXlZj$BJ*`;{)p5*53Ye^5L$oE*Q#4-2>Y( z?nFE-_Lp06fz=1(0RS^3sAiS6wwjobP>y17U2+%Mr*~O6M~DjA9616&?nN@LBqZDZ8SNchm@C{ZPl=U zxP0M7U$~EbAIXhZ15P}`1GoYUQ;}_pEBtK-o$uKqha)pDPlEFKjGkWZoihj5Up?Vc z`jo{+`tGI|kQ1olNb|<5M4^2b6g=bJzkfeK znH*y<&hCn-sUa`K{QH9+Lzn=e8n{};6&fl7lnj3)32=%btO7Nm=yX0X5ZV3ZAv+47 zyY)m2-+#^=hSvaqIAdwHo?*YzgY>zk>?5oz^!pdh%F_ z?7Dv#nWOz6?Syk1fFy`1~)ir0*Di5d~6n<~+={c;Z7#%ML zJ!Qz9RpEeIaAoi}NT^Tzeba-xU=p&}&#j7T2VHyr>IJuXQNFsx`gQKt!^&TjkLOKL z?`jtXC&UVvrO5j1@~ugG&F%e|bZx(%)W&D`gZOu(xn&fLeU{b@8lwoBrrF%yFQaJ8 z<8+|=1=YpY<@TH4Z$+Nr(>At^$`Z8XI91w%OTUTyzSP`2ci44BqhtX0o)R$n7wl#s z7bfqP6c^tx_1k{rNF~&aX}gl934*J){|OQXw?{%FTJ~|9nwncm|Hy$v%u~Jd((2gC zuU)^s7VA;`;)SdG6B)ihWWRx_LJ(kh`xb&oUD{b*mILM+#*jyEl^w4EJOi`%ez2COk)uC=kR#c)&E$(=fQFoi2Y+$Ja;C$Z3~G3a`Dj1W08NT&?d^leNMP z6?4v59f(Qby#G1r3+{~Bz$xi=tP`N7U*A}QLkvTP_n59j-^((fO4HpxvR^Fe_H(X) zAxc@j&G~gp%ii6)tF>8|DFExb2Q>Mp7R5`9_r$`&i?pwW$`;o34L3xW9r8JFv4;KP zoaW8=u&i*9(thOG@eY}!dDiFl3Ht-=fZTj|wMPC5F6H>~=7K*Ff^j(rM z-~|-?68dVr_Lo_cx0e9Q_B2mT22nD)i?0|11gCfqUPn(i%QvT7aRRS~APea8QT#g; zbqV`Ra*@;ZbE(CEi<@9^HM|JC36(iwQd?}Tj5kI!SmR3HGn{a11lyw2;2(mC8`>-- zy~GyVvh#3!LUM%h54pocR#4hgY|&7aA;a=qu2I614c-w=pEe50f|zzuZ1@wj7%Qou zrxZ_NQ+CImNG)pxQ!TC6XvQJ59kZSFfk+$LqQjo6N!K#q9x~Xo1&(tHP5jL8#6)6DjJ1;J7Q>^sVs(%5^Kvd1U=L4< zj&65z0qwElM2I78Bu`7~oqaLbq}n=yHE(Eu#lvoCBC-m?x!Sk&NOBndz}&Q919T&| z`a?h`Z~rmtWSlwA|iroG$E- zz5T77Qct$KhX>5hBK~lvN7TRZNbUy$&O@qYB`{iTEh)jG)20-vyPmLk8j#mwJEu&u z^2A^UiGMb`<7F0j6JBv;de%>%Z`}JujP}H0lA1%Umd|C)q(JjNw?#;bFA)AuKnbO% zL+bQ*@q4a(6_VRPc>THqzM$oK+7!m^4MYh9*VSYPJz?OvqZXLWvW#16LZ;u2?B_@-0j+*v81>^qDt{OySN}(c%xlL zwZ-NFH7q`-{Tw_zD!uk3w)|0YYf`HM{Nk!7b8?dZh3dl&djUb)^=S#$Xa#H;m#O)k zLsXwh$M%jMprBHYzHtg=5QI_=24%x{?Ho0hEz@NvB*Ka9DqtET0kU+p=zepJb%S_Bivb_#(2?`v-#$`Vo1gPH2{V%3KaCJ9ea*@87FHU5D;wVfgC z-&J-iBk_|@((PNwZWi`OX-e;S1JC&C#=Qhl6_FSj^dQFmeU7R4*389k-vEXd_`!YK zlc8gjX#iENb3Y(-)#=&Hw|3&uDy&%t)tPRriELPKuwr5hsWw6?9(InEDl{L>)6-}v zP@D8HxslyE=t>Y8W2@nB?M`WF%`5~(&}eH|&AK|)o4~(17*%0kya?6!dFst?pKavI zvftVv;O||9BeHWOn2XPJmtPbYt7MTlYVo2MGupchU_K;px55Aq9qo-FB|; zZf)HsEj)!GL679zAk609%I5;jE#kkpOw;n#woFRGbmNn2b7&x-G9Jk9N6`9XXITl@1XhgGnL>J zf!AQjfKNJFJHOM#$q8*g>iW-S{!eMJ-&C5fVM9bUi#leSsSCCaKT%Q`D@gWJ$rC(v z7P`1!02iN<7E^aup6~DuJ@LpqA5))1B8A+)@7QsjgCKn6Fc9g|)y7bMdbL6FrvYIg ziX0*QN!|GGW8Yu(_p!}zIio(nAJ&<~HYYs(@5lao^7mu^_hi-^{_n}Fv8x=;aRvo8 SRfALbFQI*$ax9N*;r%bz3+-zF literal 0 HcmV?d00001 diff --git a/Red Black Trees/files/fig2.png b/Red Black Trees/files/fig2.png new file mode 100644 index 0000000000000000000000000000000000000000..35b81e61c61f11906814e5503daf19847120a4a2 GIT binary patch literal 40534 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 literal 0 HcmV?d00001 diff --git a/Trie/sources/Queue.swift b/Trie/Queue.swift similarity index 100% rename from Trie/sources/Queue.swift rename to Trie/Queue.swift diff --git a/Trie/ReadMe.md b/Trie/ReadMe.md index edabbb994..844eb1df0 100644 --- a/Trie/ReadMe.md +++ b/Trie/ReadMe.md @@ -1,8 +1,220 @@ # Trie -Under Construction. +##What is a Trie? +A trie (also known as a prefix tree, or radix tree in some other (but different) implementations) is a special type of tree used to store associative data structures where the key item is normally of type String. Each node in the trie is typically not associated with a value containing strictly itself, but more so is linked to some common prefix that precedes it in levels above it. Oftentimes, true key-value pairs are associated with the leaves of the trie, but they are not limited to this. -See also [Wikipedia](https://en.wikipedia.org/wiki/Trie). +##Why a Trie? +Tries are very useful simply for the fact that it has some advantages over other data structures, like the binary tree or a hash map. These advantages include: +* Looking up keys is typically faster in the worst case when compared to other data structures. +* Unlike a hash map, a trie need not worry about key collisions +* No need for hasing, as each key will have a unique path in the trie +* Tries, by implementation, can be by default alphabetically ordered. + + +##Common Algorithms + +###Find (or any general lookup function) +Tries make looking up keys a trivial task, as all one has to do is walk over the nodes until we either hit a null reference or we find the key in question. + +The algorithm would be as follows: +``` + let node be the root of the trie + + for each character in the key + if the child of node with value character is null + return false (key doesn't exist in trie) + else + node = child of node with value character (move to the next node) + return true (key exists in trie and was found +``` + +And in swift: +```swift +func find(key: String) -> (node: Node?, found: Bool) { + var currentNode = self.root + + for c in key.characters { + if currentNode.children[String(c)] == nil { + return(nil, false) + } + currentNode = currentNode.children[String(c)]! + } + + return(currentNode, currentNode.isValidWord()) + } +``` + +###Insertion +Insertion is also a trivial task with a Trie, as all one needs to do is walk over the nodes until we either halt on a node that we must mark as a key, or we reach a point where we need to add extra nodes to represent it. + +Let's walk through the algorithm: + +``` + let S be the root node of our tree + let word be the input key + let length be the length of the key + + + find(word) + if the word was found + return false + else + + for each character in word + if child node with value character does not exist + break + else + node = child node with value character + decrement length + + if length != 0 + let suffix be the remaining characters in the key defined by the shortened length + + for each character in suffix + create a new node with value character and let it be the child of node + node = newly created child now + mark node as a valid key + else + mark node as valid key +``` + +And the corresponding swift code: + +```swift + func insert(w: String) -> (word: String, inserted: Bool) { + + let word = w.lowercaseString + var currentNode = self.root + var length = word.characters.count + + if self.contains(word) { + return (w, false) + } + + var index = 0 + var c = Array(word.characters)[index] + + while let child = currentNode.children[String(c)] { + currentNode = child + length -= 1 + index += 1 + + if(length == 0) { + currentNode.isWord() + wordList.append(w) + wordCount += 1 + return (w, true) + } + + c = Array(word.characters)[index] + } + + let remainingChars = String(word.characters.suffix(length)) + for c in remainingChars.characters { + currentNode.children[String(c)] = Node(c: String(c), p: currentNode) + currentNode = currentNode.children[String(c)]! + } + + currentNode.isWord() + wordList.append(w) + wordCount += 1 + return (w, true) + } + +``` + +###Removal +Removing keys from the trie is a little more tricky, as there a few more cases that we have to take into account the fact that keys may exist that are actually sub-strings of other valid keys. That being said, it isn't as simple a process to just delete the nodes for a specific key, as we could be deleting references/nodes necessary for already exisitng keys! + +The algorithm would be as follows: + +``` + + let word be the key to remove + let node be the root of the trie + + find(word) + if word was not found + return false + else + + for each character in word + node = child node with value character + + if node has more than just 1 child node + Mark node as an invalid key, since removing it would remove nodes still in use + else + while node has no valid children and node is not the root node + let character = node's value + node = the parent of node + delete node's child node with value character + return true +``` + + + +and the corresponding swift code: + +```swift + func remove(w: String) -> (word: String, removed: Bool){ + let word = w.lowercaseString + + if(!self.contains(w)) { + return (w, false) + } + var currentNode = self.root + + for c in word.characters { + currentNode = currentNode.getChildAt(String(c)) + } + + if currentNode.numChildren() > 0 { + currentNode.isNotWord() + } else { + var character = currentNode.char() + while(currentNode.numChildren() == 0 && !currentNode.isRoot()) { + currentNode = currentNode.getParent() + currentNode.children[character]!.setParent(nil) + currentNode.children[character]!.update(nil) + currentNode.children[character] = nil + character = currentNode.char() + } + } + + wordCount -= 1 + + var index = 0 + for item in wordList{ + if item == w { + wordList.removeAtIndex(index) + } + index += 1 + } + + return (w, true) + } + +``` + + +###Running Times + +Let n be the length of some key in the trie + +* Find(...) : In the Worst case O(n) +* Insert(...) : O(n) +* Remove(...) : O(n) + +###Other Notable Operations + +* Count: Returns the number of keys in the trie ( O(1) ) +* getWords: Returns a list containing all keys in the trie ( *O(1) ) +* isEmpty: Returns true f the trie is empty, false otherwise ( *O(1) ) +* contains: Returns true if the trie has a given key, false otherwise ( O(n) ) + +`* denotes that running time may vary depending on implementation + +See also [Wikipedia entry for Trie](https://en.wikipedia.org/wiki/Trie). *Written for the Swift Algorithm Club by Christian Encarnacion* diff --git a/Trie/tests/LinuxMain.swift b/Trie/tests/LinuxMain.swift deleted file mode 100644 index 83504f1dd..000000000 --- a/Trie/tests/LinuxMain.swift +++ /dev/null @@ -1,8 +0,0 @@ - - -import XCTest -@testable import TrieTestSuite - -XCTMain([ - testCase(TrieTests.allTests) -]) diff --git a/Trie/tests/Trie/TrieTest.swift b/Trie/tests/Trie/TrieTest.swift deleted file mode 100644 index 8f49d1196..000000000 --- a/Trie/tests/Trie/TrieTest.swift +++ /dev/null @@ -1,26 +0,0 @@ -import XCTest -@testable import Trie - -class TrieTests: XCTestCase { - var trie : Trie! - - override func setUp() { - super.setUp() - trie = Trie() - } - - func testInsert() { - - var T: Trie = Trie() - var result = T.insert("Test").inserted - XCTAssertEqual(result, true) - } -} - -extension CalculatorTests { - static var allTests : [(String, CalculatorTests -> () throws -> Void)] { - return [ - ("Testing Insert...", testInsert) - ] - } -} diff --git a/Trie/trie b/Trie/trie deleted file mode 100755 index 08a387f2717bd69ad4f97d3c0f1a326f983d1bf4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 60968 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 diff --git a/Trie/sources/trie.swift b/Trie/trie.swift similarity index 100% rename from Trie/sources/trie.swift rename to Trie/trie.swift From d1874e83857c8503ac8f9bb17104ddf272e6c12c Mon Sep 17 00:00:00 2001 From: Thukor Date: Thu, 5 May 2016 21:56:02 -0400 Subject: [PATCH 0345/1679] Merged Queue with Trie --- Trie/Package.swift | 6 - Trie/Queue.swift | 47 ----- Trie/trie.swift | 41 ++++ Trie/trie.swift~ | 479 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 520 insertions(+), 53 deletions(-) delete mode 100644 Trie/Package.swift delete mode 100644 Trie/Queue.swift create mode 100644 Trie/trie.swift~ diff --git a/Trie/Package.swift b/Trie/Package.swift deleted file mode 100644 index fc323a1ec..000000000 --- a/Trie/Package.swift +++ /dev/null @@ -1,6 +0,0 @@ -import PackageDescription - -let package = Package( - name: "Trie", - targets: [] -) diff --git a/Trie/Queue.swift b/Trie/Queue.swift deleted file mode 100644 index efc573442..000000000 --- a/Trie/Queue.swift +++ /dev/null @@ -1,47 +0,0 @@ -/* - First-in first-out queue (FIFO) - - New elements are added to the end of the queue. Dequeuing pulls elements from - the front of the queue. - - Enqueuing and dequeuing are O(1) operations. -*/ -public struct Queue { - private var array = [T?]() - private var head = 0 - - public var isEmpty: Bool { - return count == 0 - } - - public var count: Int { - return array.count - head - } - - public mutating func enqueue(element: T) { - array.append(element) - } - - public mutating func dequeue() -> T? { - guard head < array.count, let element = array[head] else { return nil } - - array[head] = nil - head += 1 - - let percentage = Double(head)/Double(array.count) - if array.count > 50 && percentage > 0.25 { - array.removeFirst(head) - head = 0 - } - - return element - } - - public func peek() -> T? { - if isEmpty { - return nil - } else { - return array[head] - } - } -} diff --git a/Trie/trie.swift b/Trie/trie.swift index f2b339024..352ca26cc 100644 --- a/Trie/trie.swift +++ b/Trie/trie.swift @@ -1,4 +1,45 @@ +/* + Queue implementation (taken from repository, needed for findPrefix()) +*/ +public struct Queue { + private var array = [T?]() + private var head = 0 + + public var isEmpty: Bool { + return count == 0 + } + + public var count: Int { + return array.count - head + } + + public mutating func enqueue(element: T) { + array.append(element) + } + + public mutating func dequeue() -> T? { + guard head < array.count, let element = array[head] else { return nil } + + array[head] = nil + head += 1 + let percentage = Double(head)/Double(array.count) + if array.count > 50 && percentage > 0.25 { + array.removeFirst(head) + head = 0 + } + + return element + } + + public func peek() -> T? { + if isEmpty { + return nil + } else { + return array[head] + } + } +} /* A Trie (Pre-fix Tree) diff --git a/Trie/trie.swift~ b/Trie/trie.swift~ new file mode 100644 index 000000000..f2b339024 --- /dev/null +++ b/Trie/trie.swift~ @@ -0,0 +1,479 @@ + +/* + A Trie (Pre-fix Tree) + + Some of the functionality of the trie makes use of the Queue implementation for this project. + + + Every node in the Trie stores a bit of information pertainining to what it references: + -Character (letter of an inserted word) + -Parent (Letter that comes before the current letter in some word) + -Children (Words that have more letters than available in the prefix) + -isAWord (Does the current letter mark the end of a known inserted word?) + -visited (Mainly for the findPrefix() function) +*/ +public class Node { + private var character: String? + private var parent: Node? + private var children: [String:Node] + private var isAWord: Bool + private var visited: Bool //only for findPrefix + + init(c: String?, p: Node?){ + self.character = c + self.children = [String:Node]() + self.isAWord = false + self.parent = p + self.visited = false + } + + /* + Function Name: char() + Input: N/A + Output: String + Functionality: Returns the associated value of the node + */ + func char() -> String { + return self.character! + } + + /* + Function Name: update + Input: String + Output: N/A + Functionality: Updates the associated value of the node + */ + func update(c: String?) { + self.character = c + } + + /* + Function Name: isLeaf + Input: N/A + Output: Bool + Functionality: Returns true if the node is a leaf node, false otherwise + */ + func isLeaf() -> Bool{ + return self.children.count == 0 + } + + /* + Function Name: getParent + Input: N/A + Output: Node + Functionality: Returns the parent node of the current node + */ + func getParent() -> Node { + return parent! + } + + /* + Function Name: setParent + Input: Node + Output: N/A + Functionality: Changes the parent of the current node to the passed node + */ + + func setParent(node: Node?) { + self.parent = node + } + + /* + Function Name: getChildAt + Input: String + Output: Node + Functionality: returns the child node that holds the specific passed letter + */ + func getChildAt(s: String) -> Node { + return self.children[s]! + } + + /* + Function Name: isValidWord + Input: N/A + Output: Bool + Functionality: Returns whether or not the current node marks the end of a valid word + */ + func isValidWord() -> Bool{ + return self.isAWord + } + + /* + Function Name: isWord + Input: N/A + Output: N/A + Functionality: the current node is indeed a word + */ + func isWord() { + self.isAWord = true + } + + /* + Function Name: isNotWord + Input: N/A + Output: N/A + Functionality: marks the current node as not a word + */ + func isNotWord() { + self.isAWord = false + } + + /* + Function Name: isRoot + Input: N/A + Output: Bool + Functionality: Returns whether or not the current node is the root of the trie + */ + func isRoot() -> Bool { + return self.character == "" + } + + /* + Function Name: numChildren + Input: N/A + Output: Int + Functionality: Returns the number of immediate letters that follow the current node + */ + func numChildren() -> Int { + return self.children.count + } + + /* + Function Name: getChildren + Input: N/A + Output: [String: Node] + Functionality: Returns the letters that immediately follow the current node's value for possible word segments that follow + */ + func getChildren() -> [String: Node] { + return self.children + } + + + /* + Function Name: printNode + Input: String, Bool + Output: N/A + Functionality: prints to the console a string representation of the current node in the trie + */ + func printNode(var indent: String, leaf: Bool) { + + print(indent, terminator: "") + if(leaf) { + print("\\-", terminator: "") + indent += " " + } + else { + print("|-", terminator: "") + indent += "| " + } + + print(self.char()) + + var i = 0 + for (_, node) in self.children { + node.printNode(indent, leaf: i == self.getChildren().count-1) + i+=1 + } + + } + +} + + +/* + The Trie class has the following attributes: + -root (the root of the trie) + -wordList (the words that currently exist in the trie) + -wordCount (the number of words in the trie) +*/ +public class Trie { + private var root: Node + private var wordList: [String] + private var wordCount = 0 + + init() { + self.root = Node(c: "", p: nil) + self.wordList = [] + } + + init(wordList: Set) { + + self.root = Node(c: "", p: nil) + self.wordList = [] + + for word in wordList { + self.insert(word) + } + } + + /* + Function Name: merge + Input: Trie + Output: Trie + Functionality: Merges two tries into one and returns the merged trie + */ + func merge(other: Trie) -> Trie{ + let newWordList = Set(self.getWords() + other.getWords()) + return Trie(wordList: newWordList) + } + + /* + Function Name: find + Input: String + Output: (Node?, Bool) + Functionality: Looks for a specific key and returns a tuple that has a reference to the node(if found) and true/false depending on if it was found + */ + func find(key: String) -> (node: Node?, found: Bool) { + var currentNode = self.root + + for c in key.characters { + if currentNode.children[String(c)] == nil { + return(nil, false) + } + currentNode = currentNode.children[String(c)]! + } + + return(currentNode, currentNode.isValidWord()) + } + + /* + Function Name: isEmpty + Input: N/A + Output: Bool + Functionality: returns true if the trie is empty, false otherwise + */ + func isEmpty() -> Bool { + return wordCount == 0 + } + + /* + Function Name: count + Input: N/A + Output: Int + Functionality: returns the number of words in the trie + */ + func count() -> Int { + return wordCount + } + + /* + Function Name: getWords + Input: N/A + Output: [String] + Functionality: returns the list of words that exist in the trie + */ + func getWords() -> [String] { + return wordList + } + + /* + Function Name: contains + Input: String + Output: Bool + Functionality: returns true if the tries has the word passed, false otherwise + */ + func contains(w: String) -> Bool { + return find(w.lowercaseString).found + } + + /* + Function Name: isPrefix + Input: String + Output: (Node?, Bool) + Functionality: returns a tuple containing a reference to the final node in the prefix (if it exists) and true/false depending on whether or not the prefix exists in the trie + */ + func isPrefix(p: String) -> (node: Node?, found: Bool) { + let prefixP = p.lowercaseString + + var currentNode = self.root + + for c in prefixP.characters { + if currentNode.children[String(c)] == nil{ + return (nil, false) + } + + currentNode = currentNode.children[String(c)]! + } + + if currentNode.numChildren() > 0 { + return (currentNode, true) + } + + return (nil, false) + } + + /* + Function Name: insert + Input: String + Output: (String, Bool) + Functionality: Inserts a word int othe trie. Returns a tuple containing the word attempted to be added, and true/false depending on whether or not the insertion was successful + */ + func insert(w: String) -> (word: String, inserted: Bool) { + + let word = w.lowercaseString + var currentNode = self.root + var length = word.characters.count + + if self.contains(word) { + return (w, false) + } + + var index = 0 + var c = Array(word.characters)[index] + + while let child = currentNode.children[String(c)] { + currentNode = child + length -= 1 + index += 1 + + if(length == 0) { + currentNode.isWord() + wordList.append(w) + wordCount += 1 + return (w, true) + } + + c = Array(word.characters)[index] + } + + let remainingChars = String(word.characters.suffix(length)) + for c in remainingChars.characters { + currentNode.children[String(c)] = Node(c: String(c), p: currentNode) + currentNode = currentNode.children[String(c)]! + } + + currentNode.isWord() + wordList.append(w) + wordCount += 1 + return (w, true) + } + + /* + Function Name: insertWords + Input: [String] + Output: ([String], Bool) + Functionality: attempts to insert all words from input array. returns a tuple containing the input array and true if some of the words were succesffuly added, false if none were added + */ + + func insertWords(wordList: [String]) -> (wordList: [String], bool: inserted){ + + var successful: Bool = false + for word in wordList { + succesful |= self.insert(word).inserted + } + + return(wordList, succesful) + } + + /* + Function Name: remove + Input: String + Output: (String, Bool) + Functionality: Removes the specified key from the trie if it exists, returns tuple containing the word attempted to be removed and true/false if the removal was succesful + */ + func remove(w: String) -> (word: String, removed: Bool){ + let word = w.lowercaseString + + if(!self.contains(w)) { + return (w, false) + } + var currentNode = self.root + + for c in word.characters { + currentNode = currentNode.getChildAt(String(c)) + } + + if currentNode.numChildren() > 0 { + currentNode.isNotWord() + } else { + var character = currentNode.char() + while(currentNode.numChildren() == 0 && !currentNode.isRoot()) { + currentNode = currentNode.getParent() + currentNode.children[character]!.setParent(nil) + currentNode.children[character]!.update(nil) + currentNode.children[character] = nil + character = currentNode.char() + } + } + + wordCount -= 1 + + var index = 0 + for item in wordList{ + if item == w { + wordList.removeAtIndex(index) + } + index += 1 + } + + return (w, true) + } + + /* + Function Name: findPrefix + Input: String + Output: [String] + Functionality: returns a list containing all words in the trie that have the specified prefix + */ + func findPrefix(p: String) -> [String] { + + if !self.isPrefix(p).found { + return [] + } + + var q: Queue = Queue() + var n: Node = self.isPrefix(p).node! + + var wordsWithPrefix: [String] = [] + var word = p + var tmp = "" + q.enqueue(n) + + while let current = q.dequeue() { + for (char, child) in current.getChildren() { + if(!child.visited) { + q.enqueue(child) + child.visited = true + if(child.isValidWord()) { + var currentNode = child + while currentNode !== n { + tmp += currentNode.char() + currentNode = currentNode.getParent() + } + tmp = String(tmp.characters.reverse()) + wordsWithPrefix.append(word + tmp) + tmp = "" + } + } + } + } + + + return wordsWithPrefix + } + + + /* + Function Name: removeAll + Input: N/A + Output: N/A + Functionality: removes all nodes in the trie using remove as a subroutine + */ + func removeAll() { + for word in wordList { + self.remove(word) + } + } + + + /* + Function Name: printTrie + Input: N/A + Output: N/A + Functionality: prints all the nodes of the trie to console in a nice and easy to understand format + */ + func printTrie() { + self.root.printNode("", leaf: true) + } + +} From d6b64083de1e334a5dc5d2a4ab667329c8cdfc43 Mon Sep 17 00:00:00 2001 From: Thukor Date: Thu, 5 May 2016 21:57:56 -0400 Subject: [PATCH 0346/1679] Got rid of build files --- Trie/.build/debug/Trie | Bin 103286 -> 0 bytes Trie/.build/debug/Trie.a | Bin 139282 -> 0 bytes Trie/.build/debug/Trie.o/Trie/Queue.d | 3 - Trie/.build/debug/Trie.o/Trie/Queue.swiftdeps | 316 ----------- .../debug/Trie.o/Trie/Queue~partial.swiftdoc | Bin 540 -> 0 bytes .../Trie.o/Trie/Queue~partial.swiftmodule | Bin 11608 -> 0 bytes Trie/.build/debug/Trie.o/Trie/main.d | 3 - Trie/.build/debug/Trie.o/Trie/main.swiftdeps | 205 ------- .../debug/Trie.o/Trie/main~partial.swiftdoc | Bin 540 -> 0 bytes .../Trie.o/Trie/main~partial.swiftmodule | Bin 31660 -> 0 bytes .../.build/debug/Trie.o/Trie/master.swiftdeps | 6 - .../debug/Trie.o/Trie/output-file-map.json | 17 - Trie/.build/debug/Trie.o/Trie/trie.d | 3 - Trie/.build/debug/Trie.o/Trie/trie.swiftdeps | 532 ------------------ .../debug/Trie.o/Trie/trie~partial.swiftdoc | Bin 540 -> 0 bytes .../Trie.o/Trie/trie~partial.swiftmodule | Bin 66060 -> 0 bytes Trie/.build/debug/Trie.o/build.db | Bin 15360 -> 0 bytes Trie/.build/debug/Trie.o/llbuild.yaml | 29 - .../.build/debug/Trie.o/sources/Queue.swift.o | Bin 23408 -> 0 bytes Trie/.build/debug/Trie.o/sources/main.swift.o | Bin 14800 -> 0 bytes Trie/.build/debug/Trie.o/sources/trie.swift.o | Bin 107872 -> 0 bytes Trie/.build/debug/Trie.swiftdoc | Bin 540 -> 0 bytes Trie/.build/debug/Trie.swiftmodule | Bin 20828 -> 0 bytes .../build.db | Bin 7168 -> 0 bytes .../llbuild.yaml | 29 - .../Queue.d | 3 - .../Queue.swiftdeps | 316 ----------- .../master.swiftdeps | 6 - .../output-file-map.json | 17 - .../trie.d | 3 - .../trie.swiftdeps | 513 ----------------- Trie/Package.swift~ | 5 - Trie/trie.swift~ | 479 ---------------- 33 files changed, 2485 deletions(-) delete mode 100755 Trie/.build/debug/Trie delete mode 100644 Trie/.build/debug/Trie.a delete mode 100644 Trie/.build/debug/Trie.o/Trie/Queue.d delete mode 100644 Trie/.build/debug/Trie.o/Trie/Queue.swiftdeps delete mode 100644 Trie/.build/debug/Trie.o/Trie/Queue~partial.swiftdoc delete mode 100644 Trie/.build/debug/Trie.o/Trie/Queue~partial.swiftmodule delete mode 100644 Trie/.build/debug/Trie.o/Trie/main.d delete mode 100644 Trie/.build/debug/Trie.o/Trie/main.swiftdeps delete mode 100644 Trie/.build/debug/Trie.o/Trie/main~partial.swiftdoc delete mode 100644 Trie/.build/debug/Trie.o/Trie/main~partial.swiftmodule delete mode 100644 Trie/.build/debug/Trie.o/Trie/master.swiftdeps delete mode 100644 Trie/.build/debug/Trie.o/Trie/output-file-map.json delete mode 100644 Trie/.build/debug/Trie.o/Trie/trie.d delete mode 100644 Trie/.build/debug/Trie.o/Trie/trie.swiftdeps delete mode 100644 Trie/.build/debug/Trie.o/Trie/trie~partial.swiftdoc delete mode 100644 Trie/.build/debug/Trie.o/Trie/trie~partial.swiftmodule delete mode 100644 Trie/.build/debug/Trie.o/build.db delete mode 100644 Trie/.build/debug/Trie.o/llbuild.yaml delete mode 100644 Trie/.build/debug/Trie.o/sources/Queue.swift.o delete mode 100644 Trie/.build/debug/Trie.o/sources/main.swift.o delete mode 100644 Trie/.build/debug/Trie.o/sources/trie.swift.o delete mode 100644 Trie/.build/debug/Trie.swiftdoc delete mode 100644 Trie/.build/debug/Trie.swiftmodule delete mode 100644 Trie/.build/debug/package_name_here_and_keep_quote_marks.o/build.db delete mode 100644 Trie/.build/debug/package_name_here_and_keep_quote_marks.o/llbuild.yaml delete mode 100644 Trie/.build/debug/package_name_here_and_keep_quote_marks.o/package_name_here_and_keep_quote_marks/Queue.d delete mode 100644 Trie/.build/debug/package_name_here_and_keep_quote_marks.o/package_name_here_and_keep_quote_marks/Queue.swiftdeps delete mode 100644 Trie/.build/debug/package_name_here_and_keep_quote_marks.o/package_name_here_and_keep_quote_marks/master.swiftdeps delete mode 100644 Trie/.build/debug/package_name_here_and_keep_quote_marks.o/package_name_here_and_keep_quote_marks/output-file-map.json delete mode 100644 Trie/.build/debug/package_name_here_and_keep_quote_marks.o/package_name_here_and_keep_quote_marks/trie.d delete mode 100644 Trie/.build/debug/package_name_here_and_keep_quote_marks.o/package_name_here_and_keep_quote_marks/trie.swiftdeps delete mode 100644 Trie/Package.swift~ delete mode 100644 Trie/trie.swift~ diff --git a/Trie/.build/debug/Trie b/Trie/.build/debug/Trie deleted file mode 100755 index 188a7c4d0c444c157c71e7da34a6ba76d6069ca5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 103286 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ℑ6zsY!R%XN&BfGeX$d1EDcsFgvEeSHDCe7r~Qqc7 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 z zQ%W0kh&wxJi|m69l_zzdIbb7u%SttlD=k+=Qr&IrDLaC_^@x;1J^07#3fO157dLeJ iR}K%yhTHHY6}Dk$?O-278&-GACpPhXYjA`H*Z&8N!`eCk diff --git a/Trie/.build/debug/Trie.a b/Trie/.build/debug/Trie.a deleted file mode 100644 index 8a6855460ced86d852718c4d574c11b94b8e9168..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 139282 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 diff --git a/Trie/.build/debug/Trie.o/Trie/Queue.d b/Trie/.build/debug/Trie.o/Trie/Queue.d deleted file mode 100644 index bc5d30531..000000000 --- a/Trie/.build/debug/Trie.o/Trie/Queue.d +++ /dev/null @@ -1,3 +0,0 @@ -/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/sources/Queue.swift.o : /home/christian/Desktop/swift-algorithm-club/Trie/sources/trie.swift /home/christian/Desktop/swift-algorithm-club/Trie/sources/Queue.swift /home/christian/swiftv2/usr/lib/swift/linux/x86_64/Swift.swiftmodule /home/christian/swiftv2/usr/lib/swift/shims/UnicodeShims.h /home/christian/swiftv2/usr/lib/swift/shims/SwiftStdint.h /home/christian/swiftv2/usr/lib/swift/shims/SwiftStddef.h /home/christian/swiftv2/usr/lib/swift/shims/LibcShims.h /home/christian/swiftv2/usr/lib/swift/shims/RuntimeStubs.h /home/christian/swiftv2/usr/lib/swift/shims/RuntimeShims.h /home/christian/swiftv2/usr/lib/swift/shims/RefCount.h /home/christian/swiftv2/usr/lib/swift/shims/HeapObject.h /home/christian/swiftv2/usr/lib/swift/shims/GlobalObjects.h /home/christian/swiftv2/usr/lib/swift/shims/FoundationShims.h /home/christian/swiftv2/usr/lib/swift/shims/CoreFoundationShims.h /home/christian/swiftv2/usr/lib/swift/shims/module.map -/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/Trie/Queue~partial.swiftmodule : /home/christian/Desktop/swift-algorithm-club/Trie/sources/trie.swift /home/christian/Desktop/swift-algorithm-club/Trie/sources/Queue.swift /home/christian/swiftv2/usr/lib/swift/linux/x86_64/Swift.swiftmodule /home/christian/swiftv2/usr/lib/swift/shims/UnicodeShims.h /home/christian/swiftv2/usr/lib/swift/shims/SwiftStdint.h /home/christian/swiftv2/usr/lib/swift/shims/SwiftStddef.h /home/christian/swiftv2/usr/lib/swift/shims/LibcShims.h /home/christian/swiftv2/usr/lib/swift/shims/RuntimeStubs.h /home/christian/swiftv2/usr/lib/swift/shims/RuntimeShims.h /home/christian/swiftv2/usr/lib/swift/shims/RefCount.h /home/christian/swiftv2/usr/lib/swift/shims/HeapObject.h /home/christian/swiftv2/usr/lib/swift/shims/GlobalObjects.h /home/christian/swiftv2/usr/lib/swift/shims/FoundationShims.h /home/christian/swiftv2/usr/lib/swift/shims/CoreFoundationShims.h /home/christian/swiftv2/usr/lib/swift/shims/module.map -/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/Trie/Queue~partial.swiftdoc : /home/christian/Desktop/swift-algorithm-club/Trie/sources/trie.swift /home/christian/Desktop/swift-algorithm-club/Trie/sources/Queue.swift /home/christian/swiftv2/usr/lib/swift/linux/x86_64/Swift.swiftmodule /home/christian/swiftv2/usr/lib/swift/shims/UnicodeShims.h /home/christian/swiftv2/usr/lib/swift/shims/SwiftStdint.h /home/christian/swiftv2/usr/lib/swift/shims/SwiftStddef.h /home/christian/swiftv2/usr/lib/swift/shims/LibcShims.h /home/christian/swiftv2/usr/lib/swift/shims/RuntimeStubs.h /home/christian/swiftv2/usr/lib/swift/shims/RuntimeShims.h /home/christian/swiftv2/usr/lib/swift/shims/RefCount.h /home/christian/swiftv2/usr/lib/swift/shims/HeapObject.h /home/christian/swiftv2/usr/lib/swift/shims/GlobalObjects.h /home/christian/swiftv2/usr/lib/swift/shims/FoundationShims.h /home/christian/swiftv2/usr/lib/swift/shims/CoreFoundationShims.h /home/christian/swiftv2/usr/lib/swift/shims/module.map diff --git a/Trie/.build/debug/Trie.o/Trie/Queue.swiftdeps b/Trie/.build/debug/Trie.o/Trie/Queue.swiftdeps deleted file mode 100644 index 6151adec1..000000000 --- a/Trie/.build/debug/Trie.o/Trie/Queue.swiftdeps +++ /dev/null @@ -1,316 +0,0 @@ -### Swift dependencies file v0 ### -provides-top-level: -- "Queue" -provides-nominal: -- "V4Trie5Queue" -provides-member: -- ["V4Trie5Queue", ""] -depends-top-level: -- "Queue" -- !private "Double" -- !private "&&" -- "Int" -- "Bool" -- "IntegerLiteralType" -- !private "<" -- !private "-" -- !private "==" -- !private "+=" -- !private ">" -- !private "/" -- "FloatLiteralType" -depends-member: -- !private ["Ps16AbsoluteValuable", "init"] -- ["Sa", "Generator"] -- ["Sa", "Index"] -- ["Sa", "SubSequence"] -- ["Sa", "_Element"] -- !private ["Sa", "append"] -- !private ["Sa", "count"] -- !private ["Sa", "deinit"] -- ["Sa", "init"] -- !private ["Sa", "removeFirst"] -- !private ["Sa", "subscript"] -- ["Ps23ArrayLiteralConvertible", "Generator"] -- ["Ps23ArrayLiteralConvertible", "Index"] -- ["Ps23ArrayLiteralConvertible", "SubSequence"] -- ["Ps23ArrayLiteralConvertible", "_Element"] -- !private ["Ps23ArrayLiteralConvertible", "append"] -- !private ["Ps23ArrayLiteralConvertible", "count"] -- ["Ps23ArrayLiteralConvertible", "init"] -- !private ["Ps23ArrayLiteralConvertible", "removeFirst"] -- !private ["Ps23ArrayLiteralConvertible", "subscript"] -- ["Vs10ArraySlice", "Generator"] -- ["Vs10ArraySlice", "Index"] -- ["Ps22BidirectionalIndexType", "Distance"] -- ["Ps22BidirectionalIndexType", "IntegerLiteralType"] -- ["Ps21BitwiseOperationsType", "Distance"] -- ["Ps21BitwiseOperationsType", "IntegerLiteralType"] -- !private ["Sb", "_getBuiltinLogicValue"] -- !private ["Ps25BooleanLiteralConvertible", "_getBuiltinLogicValue"] -- !private ["Ps11BooleanType", "_getBuiltinLogicValue"] -- ["Ps11CVarArgType", "Distance"] -- ["Ps11CVarArgType", "IntegerLiteralType"] -- !private ["Ps11CVarArgType", "init"] -- ["Ps14CollectionType", "Generator"] -- ["Ps14CollectionType", "Index"] -- ["Ps14CollectionType", "SubSequence"] -- ["Ps14CollectionType", "_Element"] -- !private ["Ps14CollectionType", "append"] -- !private ["Ps14CollectionType", "count"] -- ["Ps14CollectionType", "init"] -- !private ["Ps14CollectionType", "removeFirst"] -- !private ["Ps14CollectionType", "subscript"] -- ["Ps10Comparable", "Distance"] -- ["Ps10Comparable", "IntegerLiteralType"] -- !private ["Ps10Comparable", "init"] -- ["Ps28CustomDebugStringConvertible", "Generator"] -- ["Ps28CustomDebugStringConvertible", "Index"] -- ["Ps28CustomDebugStringConvertible", "Some"] -- ["Ps28CustomDebugStringConvertible", "SubSequence"] -- ["Ps28CustomDebugStringConvertible", "_Element"] -- !private ["Ps28CustomDebugStringConvertible", "append"] -- !private ["Ps28CustomDebugStringConvertible", "count"] -- ["Ps28CustomDebugStringConvertible", "init"] -- !private ["Ps28CustomDebugStringConvertible", "removeFirst"] -- !private ["Ps28CustomDebugStringConvertible", "subscript"] -- ["Ps23CustomStringConvertible", "Distance"] -- ["Ps23CustomStringConvertible", "Generator"] -- ["Ps23CustomStringConvertible", "Index"] -- ["Ps23CustomStringConvertible", "IntegerLiteralType"] -- ["Ps23CustomStringConvertible", "SubSequence"] -- ["Ps23CustomStringConvertible", "_Element"] -- !private ["Ps23CustomStringConvertible", "_getBuiltinLogicValue"] -- !private ["Ps23CustomStringConvertible", "append"] -- !private ["Ps23CustomStringConvertible", "count"] -- ["Ps23CustomStringConvertible", "init"] -- !private ["Ps23CustomStringConvertible", "removeFirst"] -- !private ["Ps23CustomStringConvertible", "subscript"] -- !private ["Sd", "init"] -- ["Ps9Equatable", "Distance"] -- ["Ps9Equatable", "IntegerLiteralType"] -- !private ["Ps9Equatable", "_getBuiltinLogicValue"] -- !private ["Ps9Equatable", "init"] -- !private ["Ps23FloatLiteralConvertible", "init"] -- !private ["Ps17FloatingPointType", "init"] -- ["Ps16ForwardIndexType", "Distance"] -- ["Ps16ForwardIndexType", "IntegerLiteralType"] -- ["Ps13GeneratorType", "Element"] -- ["Ps8Hashable", "Distance"] -- ["Ps8Hashable", "IntegerLiteralType"] -- !private ["Ps8Hashable", "_getBuiltinLogicValue"] -- !private ["Ps8Hashable", "init"] -- ["Ps9Indexable", "Generator"] -- ["Ps9Indexable", "Index"] -- ["Ps9Indexable", "SubSequence"] -- ["Ps9Indexable", "_Element"] -- !private ["Ps9Indexable", "append"] -- !private ["Ps9Indexable", "count"] -- ["Ps9Indexable", "init"] -- !private ["Ps9Indexable", "removeFirst"] -- !private ["Ps9Indexable", "subscript"] -- ["Vs17IndexingGenerator", "Element"] -- ["Si", "Distance"] -- ["Si", "IntegerLiteralType"] -- ["Ps21IntegerArithmeticType", "Distance"] -- ["Ps21IntegerArithmeticType", "IntegerLiteralType"] -- ["Ps25IntegerLiteralConvertible", "Distance"] -- ["Ps25IntegerLiteralConvertible", "IntegerLiteralType"] -- !private ["Ps25IntegerLiteralConvertible", "init"] -- ["Ps11IntegerType", "Distance"] -- ["Ps11IntegerType", "IntegerLiteralType"] -- ["Ps14MirrorPathType", "Distance"] -- ["Ps14MirrorPathType", "IntegerLiteralType"] -- ["Ps21MutableCollectionType", "Generator"] -- ["Ps21MutableCollectionType", "Index"] -- ["Ps21MutableCollectionType", "SubSequence"] -- ["Ps21MutableCollectionType", "_Element"] -- !private ["Ps21MutableCollectionType", "append"] -- !private ["Ps21MutableCollectionType", "count"] -- ["Ps21MutableCollectionType", "init"] -- !private ["Ps21MutableCollectionType", "removeFirst"] -- !private ["Ps21MutableCollectionType", "subscript"] -- ["Ps16MutableIndexable", "Generator"] -- ["Ps16MutableIndexable", "Index"] -- ["Ps16MutableIndexable", "SubSequence"] -- ["Ps16MutableIndexable", "_Element"] -- !private ["Ps16MutableIndexable", "append"] -- !private ["Ps16MutableIndexable", "count"] -- ["Ps16MutableIndexable", "init"] -- !private ["Ps16MutableIndexable", "removeFirst"] -- !private ["Ps16MutableIndexable", "subscript"] -- ["Ps16MutableSliceable", "Generator"] -- ["Ps16MutableSliceable", "Index"] -- ["Ps16MutableSliceable", "SubSequence"] -- ["Ps16MutableSliceable", "_Element"] -- !private ["Ps16MutableSliceable", "append"] -- !private ["Ps16MutableSliceable", "count"] -- ["Ps16MutableSliceable", "init"] -- !private ["Ps16MutableSliceable", "removeFirst"] -- !private ["Ps16MutableSliceable", "subscript"] -- ["Ps21NilLiteralConvertible", "Some"] -- ["Sq", "Some"] -- ["V4Trie5Queue", "Bool"] -- !private ["V4Trie5Queue", "Double"] -- ["V4Trie5Queue", "Int"] -- ["V4Trie5Queue", "T"] -- !private ["V4Trie5Queue", "array"] -- ["V4Trie5Queue", "count"] -- ["V4Trie5Queue", "dequeue"] -- ["V4Trie5Queue", "enqueue"] -- !private ["V4Trie5Queue", "head"] -- ["V4Trie5Queue", "init"] -- ["V4Trie5Queue", "isEmpty"] -- ["V4Trie5Queue", "peek"] -- ["Ps21RandomAccessIndexType", "Distance"] -- ["Ps21RandomAccessIndexType", "IntegerLiteralType"] -- ["Ps30RangeReplaceableCollectionType", "Generator"] -- ["Ps30RangeReplaceableCollectionType", "Index"] -- ["Ps30RangeReplaceableCollectionType", "SubSequence"] -- ["Ps30RangeReplaceableCollectionType", "_Element"] -- !private ["Ps30RangeReplaceableCollectionType", "append"] -- !private ["Ps30RangeReplaceableCollectionType", "count"] -- ["Ps30RangeReplaceableCollectionType", "init"] -- !private ["Ps30RangeReplaceableCollectionType", "removeFirst"] -- !private ["Ps30RangeReplaceableCollectionType", "subscript"] -- ["Ps12SequenceType", "Element"] -- ["Ps12SequenceType", "Generator"] -- ["Ps12SequenceType", "Index"] -- ["Ps12SequenceType", "SubSequence"] -- ["Ps12SequenceType", "_Element"] -- !private ["Ps12SequenceType", "append"] -- !private ["Ps12SequenceType", "count"] -- ["Ps12SequenceType", "init"] -- !private ["Ps12SequenceType", "removeFirst"] -- !private ["Ps12SequenceType", "subscript"] -- ["Ps17SignedIntegerType", "Distance"] -- ["Ps17SignedIntegerType", "IntegerLiteralType"] -- ["Ps16SignedNumberType", "Distance"] -- ["Ps16SignedNumberType", "IntegerLiteralType"] -- !private ["Ps16SignedNumberType", "init"] -- !private ["Vs5Slice", "Generator"] -- !private ["Vs5Slice", "Index"] -- !private ["Vs5Slice", "SubSequence"] -- !private ["Vs5Slice", "_Element"] -- ["Ps10Strideable", "Distance"] -- ["Ps10Strideable", "IntegerLiteralType"] -- !private ["Ps10Strideable", "init"] -- ["Ps10_ArrayType", "Generator"] -- ["Ps10_ArrayType", "Index"] -- ["Ps10_ArrayType", "SubSequence"] -- ["Ps10_ArrayType", "_Element"] -- !private ["Ps10_ArrayType", "append"] -- !private ["Ps10_ArrayType", "count"] -- ["Ps10_ArrayType", "init"] -- !private ["Ps10_ArrayType", "removeFirst"] -- !private ["Ps10_ArrayType", "subscript"] -- !private ["Ps33_BuiltinBooleanLiteralConvertible", "_getBuiltinLogicValue"] -- !private ["Ps31_BuiltinFloatLiteralConvertible", "init"] -- ["Ps33_BuiltinIntegerLiteralConvertible", "Distance"] -- ["Ps33_BuiltinIntegerLiteralConvertible", "IntegerLiteralType"] -- !private ["Ps33_BuiltinIntegerLiteralConvertible", "init"] -- !private ["Ps19_CVarArgAlignedType", "init"] -- !private ["Ps22_CVarArgPassedAsDouble", "init"] -- ["Ps24_DestructorSafeContainer", "Generator"] -- ["Ps24_DestructorSafeContainer", "Index"] -- ["Ps24_DestructorSafeContainer", "SubSequence"] -- ["Ps24_DestructorSafeContainer", "_Element"] -- !private ["Ps24_DestructorSafeContainer", "append"] -- !private ["Ps24_DestructorSafeContainer", "count"] -- ["Ps24_DestructorSafeContainer", "init"] -- !private ["Ps24_DestructorSafeContainer", "removeFirst"] -- !private ["Ps24_DestructorSafeContainer", "subscript"] -- ["Ps14_Incrementable", "Distance"] -- ["Ps14_Incrementable", "IntegerLiteralType"] -- ["Ps22_IntegerArithmeticType", "Distance"] -- ["Ps22_IntegerArithmeticType", "IntegerLiteralType"] -- ["Ps12_IntegerType", "Distance"] -- ["Ps12_IntegerType", "IntegerLiteralType"] -- ["Ps22_RandomAccessAmbiguity", "Distance"] -- ["Ps22_RandomAccessAmbiguity", "IntegerLiteralType"] -- ["Ps12_Reflectable", "Distance"] -- ["Ps12_Reflectable", "Generator"] -- ["Ps12_Reflectable", "Index"] -- ["Ps12_Reflectable", "IntegerLiteralType"] -- ["Ps12_Reflectable", "Some"] -- ["Ps12_Reflectable", "SubSequence"] -- ["Ps12_Reflectable", "_Element"] -- !private ["Ps12_Reflectable", "_getBuiltinLogicValue"] -- !private ["Ps12_Reflectable", "append"] -- !private ["Ps12_Reflectable", "count"] -- ["Ps12_Reflectable", "init"] -- !private ["Ps12_Reflectable", "removeFirst"] -- !private ["Ps12_Reflectable", "subscript"] -- ["Ps18_SignedIntegerType", "Distance"] -- ["Ps18_SignedIntegerType", "IntegerLiteralType"] -depends-nominal: -- !private "Ps16AbsoluteValuable" -- "Sa" -- "Ps23ArrayLiteralConvertible" -- "Vs10ArraySlice" -- "Ps22BidirectionalIndexType" -- "Ps21BitwiseOperationsType" -- !private "Sb" -- !private "Ps25BooleanLiteralConvertible" -- !private "Ps11BooleanType" -- "Ps11CVarArgType" -- "Ps14CollectionType" -- "Ps10Comparable" -- "Ps28CustomDebugStringConvertible" -- "Ps23CustomStringConvertible" -- !private "Sd" -- "Ps9Equatable" -- !private "Ps23FloatLiteralConvertible" -- !private "Ps17FloatingPointType" -- "Ps16ForwardIndexType" -- "Ps13GeneratorType" -- "Ps8Hashable" -- "Ps9Indexable" -- "Vs17IndexingGenerator" -- "Si" -- "Ps21IntegerArithmeticType" -- "Ps25IntegerLiteralConvertible" -- "Ps11IntegerType" -- "Ps14MirrorPathType" -- "Ps21MutableCollectionType" -- "Ps16MutableIndexable" -- "Ps16MutableSliceable" -- "Ps21NilLiteralConvertible" -- "Sq" -- "V4Trie5Queue" -- "Ps21RandomAccessIndexType" -- "Ps30RangeReplaceableCollectionType" -- "Ps12SequenceType" -- "Ps17SignedIntegerType" -- "Ps16SignedNumberType" -- !private "Vs5Slice" -- "Ps10Strideable" -- "Ps10_ArrayType" -- !private "Ps33_BuiltinBooleanLiteralConvertible" -- !private "Ps31_BuiltinFloatLiteralConvertible" -- "Ps33_BuiltinIntegerLiteralConvertible" -- !private "Ps19_CVarArgAlignedType" -- !private "Ps22_CVarArgPassedAsDouble" -- "Ps24_DestructorSafeContainer" -- "Ps14_Incrementable" -- "Ps22_IntegerArithmeticType" -- "Ps12_IntegerType" -- "Ps22_RandomAccessAmbiguity" -- "Ps12_Reflectable" -- "Ps18_SignedIntegerType" -depends-dynamic-lookup: -depends-external: -- "/home/christian/swiftv2/usr/lib/swift/linux/x86_64/Swift.swiftmodule" -- "/home/christian/swiftv2/usr/lib/swift/shims/UnicodeShims.h" -- "/home/christian/swiftv2/usr/lib/swift/shims/SwiftStdint.h" -- "/home/christian/swiftv2/usr/lib/swift/shims/SwiftStddef.h" -- "/home/christian/swiftv2/usr/lib/swift/shims/LibcShims.h" -- "/home/christian/swiftv2/usr/lib/swift/shims/RuntimeStubs.h" -- "/home/christian/swiftv2/usr/lib/swift/shims/RuntimeShims.h" -- "/home/christian/swiftv2/usr/lib/swift/shims/RefCount.h" -- "/home/christian/swiftv2/usr/lib/swift/shims/HeapObject.h" -- "/home/christian/swiftv2/usr/lib/swift/shims/GlobalObjects.h" -- "/home/christian/swiftv2/usr/lib/swift/shims/FoundationShims.h" -- "/home/christian/swiftv2/usr/lib/swift/shims/CoreFoundationShims.h" -- "/home/christian/swiftv2/usr/lib/swift/shims/module.map" -interface-hash: "b268b101cc2bc2706939fa25905dab4d" diff --git a/Trie/.build/debug/Trie.o/Trie/Queue~partial.swiftdoc b/Trie/.build/debug/Trie.o/Trie/Queue~partial.swiftdoc deleted file mode 100644 index 12942dedfe6852aa61b902224cde186d2adaaf6c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 540 zcmaDfX9YVW2LppD0|Ns)qlJ#c+7Dby0=U-%aP4>CT5rI$Ux91Q2d>2%xY!*xUFbQa zy@N^j#3Ahshx9v`wD%m+SaZl(Xp58P1t*OOP8vYc#=uE?50mBxdSs$%*Q9pSHW1%LeHSMEDy*( z2E-K>X7Oewx}|y9dHLmex;dG7r4_pAd8I%phE||K?m*gzO@POXg+Yf2BnSi!U~-gz Gg#ZA|lTWSy diff --git a/Trie/.build/debug/Trie.o/Trie/Queue~partial.swiftmodule b/Trie/.build/debug/Trie.o/Trie/Queue~partial.swiftmodule deleted file mode 100644 index 1594ec4d238b3a285e3e18a9dbfd52390d125f0e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11608 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 diff --git a/Trie/.build/debug/Trie.o/Trie/main.d b/Trie/.build/debug/Trie.o/Trie/main.d deleted file mode 100644 index 73abc24e4..000000000 --- a/Trie/.build/debug/Trie.o/Trie/main.d +++ /dev/null @@ -1,3 +0,0 @@ -/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/sources/main.swift.o : /home/christian/Desktop/swift-algorithm-club/Trie/sources/main.swift /home/christian/Desktop/swift-algorithm-club/Trie/sources/trie.swift /home/christian/Desktop/swift-algorithm-club/Trie/sources/Queue.swift /home/christian/swiftv2/usr/lib/swift/linux/x86_64/Swift.swiftmodule /home/christian/swiftv2/usr/lib/swift/shims/UnicodeShims.h /home/christian/swiftv2/usr/lib/swift/shims/SwiftStdint.h /home/christian/swiftv2/usr/lib/swift/shims/SwiftStddef.h /home/christian/swiftv2/usr/lib/swift/shims/LibcShims.h /home/christian/swiftv2/usr/lib/swift/shims/RuntimeStubs.h /home/christian/swiftv2/usr/lib/swift/shims/RuntimeShims.h /home/christian/swiftv2/usr/lib/swift/shims/RefCount.h /home/christian/swiftv2/usr/lib/swift/shims/HeapObject.h /home/christian/swiftv2/usr/lib/swift/shims/GlobalObjects.h /home/christian/swiftv2/usr/lib/swift/shims/FoundationShims.h /home/christian/swiftv2/usr/lib/swift/shims/CoreFoundationShims.h /home/christian/swiftv2/usr/lib/swift/shims/module.map -/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/Trie/main~partial.swiftmodule : /home/christian/Desktop/swift-algorithm-club/Trie/sources/main.swift /home/christian/Desktop/swift-algorithm-club/Trie/sources/trie.swift /home/christian/Desktop/swift-algorithm-club/Trie/sources/Queue.swift /home/christian/swiftv2/usr/lib/swift/linux/x86_64/Swift.swiftmodule /home/christian/swiftv2/usr/lib/swift/shims/UnicodeShims.h /home/christian/swiftv2/usr/lib/swift/shims/SwiftStdint.h /home/christian/swiftv2/usr/lib/swift/shims/SwiftStddef.h /home/christian/swiftv2/usr/lib/swift/shims/LibcShims.h /home/christian/swiftv2/usr/lib/swift/shims/RuntimeStubs.h /home/christian/swiftv2/usr/lib/swift/shims/RuntimeShims.h /home/christian/swiftv2/usr/lib/swift/shims/RefCount.h /home/christian/swiftv2/usr/lib/swift/shims/HeapObject.h /home/christian/swiftv2/usr/lib/swift/shims/GlobalObjects.h /home/christian/swiftv2/usr/lib/swift/shims/FoundationShims.h /home/christian/swiftv2/usr/lib/swift/shims/CoreFoundationShims.h /home/christian/swiftv2/usr/lib/swift/shims/module.map -/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/Trie/main~partial.swiftdoc : /home/christian/Desktop/swift-algorithm-club/Trie/sources/main.swift /home/christian/Desktop/swift-algorithm-club/Trie/sources/trie.swift /home/christian/Desktop/swift-algorithm-club/Trie/sources/Queue.swift /home/christian/swiftv2/usr/lib/swift/linux/x86_64/Swift.swiftmodule /home/christian/swiftv2/usr/lib/swift/shims/UnicodeShims.h /home/christian/swiftv2/usr/lib/swift/shims/SwiftStdint.h /home/christian/swiftv2/usr/lib/swift/shims/SwiftStddef.h /home/christian/swiftv2/usr/lib/swift/shims/LibcShims.h /home/christian/swiftv2/usr/lib/swift/shims/RuntimeStubs.h /home/christian/swiftv2/usr/lib/swift/shims/RuntimeShims.h /home/christian/swiftv2/usr/lib/swift/shims/RefCount.h /home/christian/swiftv2/usr/lib/swift/shims/HeapObject.h /home/christian/swiftv2/usr/lib/swift/shims/GlobalObjects.h /home/christian/swiftv2/usr/lib/swift/shims/FoundationShims.h /home/christian/swiftv2/usr/lib/swift/shims/CoreFoundationShims.h /home/christian/swiftv2/usr/lib/swift/shims/module.map diff --git a/Trie/.build/debug/Trie.o/Trie/main.swiftdeps b/Trie/.build/debug/Trie.o/Trie/main.swiftdeps deleted file mode 100644 index d126051a2..000000000 --- a/Trie/.build/debug/Trie.o/Trie/main.swiftdeps +++ /dev/null @@ -1,205 +0,0 @@ -### Swift dependencies file v0 ### -provides-top-level: -- "T" -- "U" -- "V" -provides-nominal: -provides-member: -depends-top-level: -- "Trie" -- "U" -- "Array" -- "V" -- "print" -- "StringLiteralType" -- "T" -- "Set" -- "UnicodeScalarType" -depends-member: -- ["Ps9AnyObject", "findPrefix"] -- ["Ps9AnyObject", "getWords"] -- ["Ps9AnyObject", "init"] -- ["Ps9AnyObject", "insert"] -- ["Ps9AnyObject", "merge"] -- ["Ps9AnyObject", "removeAll"] -- ["Sa", "Element"] -- ["Sa", "Generator"] -- ["Sa", "Index"] -- ["Sa", "_Element"] -- ["Ps23ArrayLiteralConvertible", "Element"] -- ["Ps23ArrayLiteralConvertible", "Generator"] -- ["Ps23ArrayLiteralConvertible", "Index"] -- ["Ps23ArrayLiteralConvertible", "_Element"] -- ["Ps23ArrayLiteralConvertible", "init"] -- ["Ps22BidirectionalIndexType", "Distance"] -- ["Ps22BidirectionalIndexType", "IntegerLiteralType"] -- ["Ps21BitwiseOperationsType", "Distance"] -- ["Ps21BitwiseOperationsType", "IntegerLiteralType"] -- ["Ps11CVarArgType", "Distance"] -- ["Ps11CVarArgType", "IntegerLiteralType"] -- ["Ps14CollectionType", "Element"] -- ["Ps14CollectionType", "Generator"] -- ["Ps14CollectionType", "Index"] -- ["Ps14CollectionType", "_Element"] -- ["Ps14CollectionType", "init"] -- ["Ps10Comparable", "Distance"] -- ["Ps10Comparable", "IntegerLiteralType"] -- ["Ps28CustomDebugStringConvertible", "Element"] -- ["Ps28CustomDebugStringConvertible", "Generator"] -- ["Ps28CustomDebugStringConvertible", "Index"] -- ["Ps28CustomDebugStringConvertible", "_Element"] -- ["Ps28CustomDebugStringConvertible", "init"] -- ["Ps23CustomStringConvertible", "Distance"] -- ["Ps23CustomStringConvertible", "Element"] -- ["Ps23CustomStringConvertible", "Generator"] -- ["Ps23CustomStringConvertible", "Index"] -- ["Ps23CustomStringConvertible", "IntegerLiteralType"] -- ["Ps23CustomStringConvertible", "_Element"] -- ["Ps23CustomStringConvertible", "init"] -- ["Ps9Equatable", "Distance"] -- ["Ps9Equatable", "IntegerLiteralType"] -- ["Ps9Equatable", "init"] -- ["Ps16ForwardIndexType", "Distance"] -- ["Ps16ForwardIndexType", "IntegerLiteralType"] -- ["Ps13GeneratorType", "Element"] -- ["Ps8Hashable", "Distance"] -- ["Ps8Hashable", "IntegerLiteralType"] -- ["Ps8Hashable", "init"] -- ["Ps9Indexable", "Element"] -- ["Ps9Indexable", "Generator"] -- ["Ps9Indexable", "Index"] -- ["Ps9Indexable", "_Element"] -- ["Ps9Indexable", "init"] -- ["Vs17IndexingGenerator", "Element"] -- ["Si", "Distance"] -- ["Si", "IntegerLiteralType"] -- ["Si", "deinit"] -- ["Ps21IntegerArithmeticType", "Distance"] -- ["Ps21IntegerArithmeticType", "IntegerLiteralType"] -- ["Ps25IntegerLiteralConvertible", "Distance"] -- ["Ps25IntegerLiteralConvertible", "IntegerLiteralType"] -- ["Ps11IntegerType", "Distance"] -- ["Ps11IntegerType", "IntegerLiteralType"] -- ["Ps14MirrorPathType", "Distance"] -- ["Ps14MirrorPathType", "IntegerLiteralType"] -- ["Ps21MutableCollectionType", "Element"] -- ["Ps21MutableCollectionType", "Generator"] -- ["Ps21MutableCollectionType", "Index"] -- ["Ps21MutableCollectionType", "_Element"] -- ["Ps16MutableIndexable", "Element"] -- ["Ps16MutableIndexable", "Generator"] -- ["Ps16MutableIndexable", "Index"] -- ["Ps16MutableIndexable", "_Element"] -- ["Ps16MutableSliceable", "Element"] -- ["Ps16MutableSliceable", "Generator"] -- ["Ps16MutableSliceable", "Index"] -- ["Ps16MutableSliceable", "_Element"] -- ["Ps21RandomAccessIndexType", "Distance"] -- ["Ps21RandomAccessIndexType", "IntegerLiteralType"] -- ["Ps30RangeReplaceableCollectionType", "Element"] -- ["Ps30RangeReplaceableCollectionType", "Generator"] -- ["Ps30RangeReplaceableCollectionType", "Index"] -- ["Ps30RangeReplaceableCollectionType", "_Element"] -- ["Ps12SequenceType", "Element"] -- ["Ps12SequenceType", "Generator"] -- ["Ps12SequenceType", "Index"] -- ["Ps12SequenceType", "_Element"] -- ["Ps12SequenceType", "init"] -- ["Vs3Set", "init"] -- ["Ps17SignedIntegerType", "Distance"] -- ["Ps17SignedIntegerType", "IntegerLiteralType"] -- ["Ps16SignedNumberType", "Distance"] -- ["Ps16SignedNumberType", "IntegerLiteralType"] -- ["Ps10Strideable", "Distance"] -- ["Ps10Strideable", "IntegerLiteralType"] -- ["C4Trie4Trie", "findPrefix"] -- ["C4Trie4Trie", "getWords"] -- ["C4Trie4Trie", "init"] -- ["C4Trie4Trie", "insert"] -- ["C4Trie4Trie", "merge"] -- ["C4Trie4Trie", "removeAll"] -- ["Ps10_ArrayType", "Element"] -- ["Ps10_ArrayType", "Generator"] -- ["Ps10_ArrayType", "Index"] -- ["Ps10_ArrayType", "_Element"] -- ["Ps33_BuiltinIntegerLiteralConvertible", "Distance"] -- ["Ps33_BuiltinIntegerLiteralConvertible", "IntegerLiteralType"] -- ["Ps24_DestructorSafeContainer", "Element"] -- ["Ps24_DestructorSafeContainer", "Generator"] -- ["Ps24_DestructorSafeContainer", "Index"] -- ["Ps24_DestructorSafeContainer", "_Element"] -- ["Ps14_Incrementable", "Distance"] -- ["Ps14_Incrementable", "IntegerLiteralType"] -- ["Ps22_IntegerArithmeticType", "Distance"] -- ["Ps22_IntegerArithmeticType", "IntegerLiteralType"] -- ["Ps12_IntegerType", "Distance"] -- ["Ps12_IntegerType", "IntegerLiteralType"] -- ["Ps22_RandomAccessAmbiguity", "Distance"] -- ["Ps22_RandomAccessAmbiguity", "IntegerLiteralType"] -- ["Ps12_Reflectable", "Distance"] -- ["Ps12_Reflectable", "Element"] -- ["Ps12_Reflectable", "Generator"] -- ["Ps12_Reflectable", "Index"] -- ["Ps12_Reflectable", "IntegerLiteralType"] -- ["Ps12_Reflectable", "_Element"] -- ["Ps12_Reflectable", "init"] -- ["Ps18_SignedIntegerType", "Distance"] -- ["Ps18_SignedIntegerType", "IntegerLiteralType"] -depends-nominal: -- "Ps9AnyObject" -- "Sa" -- "Ps23ArrayLiteralConvertible" -- "Ps22BidirectionalIndexType" -- "Ps21BitwiseOperationsType" -- "Ps11CVarArgType" -- "Ps14CollectionType" -- "Ps10Comparable" -- "Ps28CustomDebugStringConvertible" -- "Ps23CustomStringConvertible" -- "Ps9Equatable" -- "Ps16ForwardIndexType" -- "Ps13GeneratorType" -- "Ps8Hashable" -- "Ps9Indexable" -- "Vs17IndexingGenerator" -- "Si" -- "Ps21IntegerArithmeticType" -- "Ps25IntegerLiteralConvertible" -- "Ps11IntegerType" -- "Ps14MirrorPathType" -- "Ps21MutableCollectionType" -- "Ps16MutableIndexable" -- "Ps16MutableSliceable" -- "Ps21RandomAccessIndexType" -- "Ps30RangeReplaceableCollectionType" -- "Ps12SequenceType" -- "Vs3Set" -- "Ps17SignedIntegerType" -- "Ps16SignedNumberType" -- "Ps10Strideable" -- "C4Trie4Trie" -- "Ps10_ArrayType" -- "Ps33_BuiltinIntegerLiteralConvertible" -- "Ps24_DestructorSafeContainer" -- "Ps14_Incrementable" -- "Ps22_IntegerArithmeticType" -- "Ps12_IntegerType" -- "Ps22_RandomAccessAmbiguity" -- "Ps12_Reflectable" -- "Ps18_SignedIntegerType" -depends-dynamic-lookup: -depends-external: -- "/home/christian/swiftv2/usr/lib/swift/linux/x86_64/Swift.swiftmodule" -- "/home/christian/swiftv2/usr/lib/swift/shims/UnicodeShims.h" -- "/home/christian/swiftv2/usr/lib/swift/shims/SwiftStdint.h" -- "/home/christian/swiftv2/usr/lib/swift/shims/SwiftStddef.h" -- "/home/christian/swiftv2/usr/lib/swift/shims/LibcShims.h" -- "/home/christian/swiftv2/usr/lib/swift/shims/RuntimeStubs.h" -- "/home/christian/swiftv2/usr/lib/swift/shims/RuntimeShims.h" -- "/home/christian/swiftv2/usr/lib/swift/shims/RefCount.h" -- "/home/christian/swiftv2/usr/lib/swift/shims/HeapObject.h" -- "/home/christian/swiftv2/usr/lib/swift/shims/GlobalObjects.h" -- "/home/christian/swiftv2/usr/lib/swift/shims/FoundationShims.h" -- "/home/christian/swiftv2/usr/lib/swift/shims/CoreFoundationShims.h" -- "/home/christian/swiftv2/usr/lib/swift/shims/module.map" -interface-hash: "57319b836b718d38040ac7809f4446f7" diff --git a/Trie/.build/debug/Trie.o/Trie/main~partial.swiftdoc b/Trie/.build/debug/Trie.o/Trie/main~partial.swiftdoc deleted file mode 100644 index 12942dedfe6852aa61b902224cde186d2adaaf6c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 540 zcmaDfX9YVW2LppD0|Ns)qlJ#c+7Dby0=U-%aP4>CT5rI$Ux91Q2d>2%xY!*xUFbQa zy@N^j#3Ahshx9v`wD%m+SaZl(Xp58P1t*OOP8vYc#=uE?50mBxdSs$%*Q9pSHW1%LeHSMEDy*( z2E-K>X7Oewx}|y9dHLmex;dG7r4_pAd8I%phE||K?m*gzO@POXg+Yf2BnSi!U~-gz Gg#ZA|lTWSy diff --git a/Trie/.build/debug/Trie.o/Trie/main~partial.swiftmodule b/Trie/.build/debug/Trie.o/Trie/main~partial.swiftmodule deleted file mode 100644 index 876e0ca6ba870dcbe4f14e6dff6cf29aedab8598..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 31660 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 diff --git a/Trie/.build/debug/Trie.o/Trie/master.swiftdeps b/Trie/.build/debug/Trie.o/Trie/master.swiftdeps deleted file mode 100644 index e309a3241..000000000 --- a/Trie/.build/debug/Trie.o/Trie/master.swiftdeps +++ /dev/null @@ -1,6 +0,0 @@ -version: "Swift version 2.2-dev (LLVM 3ebdbb2c7e, Clang f66c5bb67b, Swift 0ddf238ad7)" -options: "b9e1edeb018f28952094455e51afbd70" -build_time: [515622447, 803412000] -inputs: - "/home/christian/Desktop/swift-algorithm-club/Trie/sources/trie.swift": [515621876, 0] - "/home/christian/Desktop/swift-algorithm-club/Trie/sources/Queue.swift": [512710161, 0] diff --git a/Trie/.build/debug/Trie.o/Trie/output-file-map.json b/Trie/.build/debug/Trie.o/Trie/output-file-map.json deleted file mode 100644 index 6583c1858..000000000 --- a/Trie/.build/debug/Trie.o/Trie/output-file-map.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "": { - "swift-dependencies": "/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/Trie/master.swiftdeps" - }, - "/home/christian/Desktop/swift-algorithm-club/Trie/sources/trie.swift": { - "dependencies": "/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/Trie/trie.d", - "object": "/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/sources/trie.swift.o", - "swiftmodule": "/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/Trie/trie~partial.swiftmodule", - "swift-dependencies": "/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/Trie/trie.swiftdeps" - }, - "/home/christian/Desktop/swift-algorithm-club/Trie/sources/Queue.swift": { - "dependencies": "/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/Trie/Queue.d", - "object": "/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/sources/Queue.swift.o", - "swiftmodule": "/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/Trie/Queue~partial.swiftmodule", - "swift-dependencies": "/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/Trie/Queue.swiftdeps" - } -} diff --git a/Trie/.build/debug/Trie.o/Trie/trie.d b/Trie/.build/debug/Trie.o/Trie/trie.d deleted file mode 100644 index 6afbabc4c..000000000 --- a/Trie/.build/debug/Trie.o/Trie/trie.d +++ /dev/null @@ -1,3 +0,0 @@ -/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/sources/trie.swift.o : /home/christian/Desktop/swift-algorithm-club/Trie/sources/trie.swift /home/christian/Desktop/swift-algorithm-club/Trie/sources/Queue.swift /home/christian/swiftv2/usr/lib/swift/linux/x86_64/Swift.swiftmodule /home/christian/swiftv2/usr/lib/swift/shims/UnicodeShims.h /home/christian/swiftv2/usr/lib/swift/shims/SwiftStdint.h /home/christian/swiftv2/usr/lib/swift/shims/SwiftStddef.h /home/christian/swiftv2/usr/lib/swift/shims/LibcShims.h /home/christian/swiftv2/usr/lib/swift/shims/RuntimeStubs.h /home/christian/swiftv2/usr/lib/swift/shims/RuntimeShims.h /home/christian/swiftv2/usr/lib/swift/shims/RefCount.h /home/christian/swiftv2/usr/lib/swift/shims/HeapObject.h /home/christian/swiftv2/usr/lib/swift/shims/GlobalObjects.h /home/christian/swiftv2/usr/lib/swift/shims/FoundationShims.h /home/christian/swiftv2/usr/lib/swift/shims/CoreFoundationShims.h /home/christian/swiftv2/usr/lib/swift/shims/module.map -/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/Trie/trie~partial.swiftmodule : /home/christian/Desktop/swift-algorithm-club/Trie/sources/trie.swift /home/christian/Desktop/swift-algorithm-club/Trie/sources/Queue.swift /home/christian/swiftv2/usr/lib/swift/linux/x86_64/Swift.swiftmodule /home/christian/swiftv2/usr/lib/swift/shims/UnicodeShims.h /home/christian/swiftv2/usr/lib/swift/shims/SwiftStdint.h /home/christian/swiftv2/usr/lib/swift/shims/SwiftStddef.h /home/christian/swiftv2/usr/lib/swift/shims/LibcShims.h /home/christian/swiftv2/usr/lib/swift/shims/RuntimeStubs.h /home/christian/swiftv2/usr/lib/swift/shims/RuntimeShims.h /home/christian/swiftv2/usr/lib/swift/shims/RefCount.h /home/christian/swiftv2/usr/lib/swift/shims/HeapObject.h /home/christian/swiftv2/usr/lib/swift/shims/GlobalObjects.h /home/christian/swiftv2/usr/lib/swift/shims/FoundationShims.h /home/christian/swiftv2/usr/lib/swift/shims/CoreFoundationShims.h /home/christian/swiftv2/usr/lib/swift/shims/module.map -/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/Trie/trie~partial.swiftdoc : /home/christian/Desktop/swift-algorithm-club/Trie/sources/trie.swift /home/christian/Desktop/swift-algorithm-club/Trie/sources/Queue.swift /home/christian/swiftv2/usr/lib/swift/linux/x86_64/Swift.swiftmodule /home/christian/swiftv2/usr/lib/swift/shims/UnicodeShims.h /home/christian/swiftv2/usr/lib/swift/shims/SwiftStdint.h /home/christian/swiftv2/usr/lib/swift/shims/SwiftStddef.h /home/christian/swiftv2/usr/lib/swift/shims/LibcShims.h /home/christian/swiftv2/usr/lib/swift/shims/RuntimeStubs.h /home/christian/swiftv2/usr/lib/swift/shims/RuntimeShims.h /home/christian/swiftv2/usr/lib/swift/shims/RefCount.h /home/christian/swiftv2/usr/lib/swift/shims/HeapObject.h /home/christian/swiftv2/usr/lib/swift/shims/GlobalObjects.h /home/christian/swiftv2/usr/lib/swift/shims/FoundationShims.h /home/christian/swiftv2/usr/lib/swift/shims/CoreFoundationShims.h /home/christian/swiftv2/usr/lib/swift/shims/module.map diff --git a/Trie/.build/debug/Trie.o/Trie/trie.swiftdeps b/Trie/.build/debug/Trie.o/Trie/trie.swiftdeps deleted file mode 100644 index c56a23f66..000000000 --- a/Trie/.build/debug/Trie.o/Trie/trie.swiftdeps +++ /dev/null @@ -1,532 +0,0 @@ -### Swift dependencies file v0 ### -provides-top-level: -- "Node" -- "Trie" -provides-nominal: -- "C4Trie4Node" -- "C4Trie4Trie" -provides-member: -- ["C4Trie4Node", ""] -- ["C4Trie4Trie", ""] -depends-top-level: -- "FloatLiteralType" -- !private "-" -- !private "&&" -- "Trie" -- !private "BooleanLiteralType" -- !private "UnicodeScalarType" -- "Node" -- !private "print" -- "Set" -- !private "==" -- !private "Array" -- !private "+=" -- "IntegerLiteralType" -- !private "!" -- !private "StringLiteralType" -- "Int" -- !private "Queue" -- "Void" -- !private ">" -- !private "!==" -- !private "-=" -- "Bool" -- !private "+" -- "String" -depends-member: -- !private ["Vs12AnyGenerator", "Element"] -- !private ["Ps9AnyObject", "Array"] -- !private ["Ps9AnyObject", "Node"] -- !private ["Ps9AnyObject", "Queue"] -- !private ["Ps9AnyObject", "Set"] -- !private ["Ps9AnyObject", "String"] -- !private ["Ps9AnyObject", "Trie"] -- !private ["Ps9AnyObject", "char"] -- !private ["Ps9AnyObject", "character"] -- !private ["Ps9AnyObject", "children"] -- !private ["Ps9AnyObject", "contains"] -- !private ["Ps9AnyObject", "find"] -- !private ["Ps9AnyObject", "getChildAt"] -- !private ["Ps9AnyObject", "getChildren"] -- !private ["Ps9AnyObject", "getParent"] -- !private ["Ps9AnyObject", "getWords"] -- !private ["Ps9AnyObject", "init"] -- !private ["Ps9AnyObject", "insert"] -- !private ["Ps9AnyObject", "isAWord"] -- !private ["Ps9AnyObject", "isNotWord"] -- !private ["Ps9AnyObject", "isPrefix"] -- !private ["Ps9AnyObject", "isRoot"] -- !private ["Ps9AnyObject", "isValidWord"] -- !private ["Ps9AnyObject", "isWord"] -- !private ["Ps9AnyObject", "numChildren"] -- !private ["Ps9AnyObject", "parent"] -- !private ["Ps9AnyObject", "print"] -- !private ["Ps9AnyObject", "printNode"] -- !private ["Ps9AnyObject", "remove"] -- !private ["Ps9AnyObject", "root"] -- !private ["Ps9AnyObject", "setParent"] -- !private ["Ps9AnyObject", "update"] -- !private ["Ps9AnyObject", "visited"] -- !private ["Ps9AnyObject", "wordCount"] -- !private ["Ps9AnyObject", "wordList"] -- ["Ps9AnyObject", ""] -- !private ["Vs11AnySequence", "Generator"] -- !private ["Vs11AnySequence", "deinit"] -- !private ["Sa", "Element"] -- !private ["Sa", "Generator"] -- !private ["Sa", "Index"] -- !private ["Sa", "SubSequence"] -- !private ["Sa", "_Element"] -- !private ["Sa", "append"] -- !private ["Sa", "deinit"] -- !private ["Sa", "init"] -- !private ["Sa", "removeAtIndex"] -- !private ["Sa", "subscript"] -- !private ["Ps23ArrayLiteralConvertible", "Element"] -- !private ["Ps23ArrayLiteralConvertible", "Generator"] -- !private ["Ps23ArrayLiteralConvertible", "Index"] -- !private ["Ps23ArrayLiteralConvertible", "SubSequence"] -- !private ["Ps23ArrayLiteralConvertible", "_Element"] -- !private ["Ps23ArrayLiteralConvertible", "append"] -- !private ["Ps23ArrayLiteralConvertible", "init"] -- !private ["Ps23ArrayLiteralConvertible", "removeAtIndex"] -- !private ["Ps23ArrayLiteralConvertible", "subscript"] -- !private ["Vs10ArraySlice", "Generator"] -- !private ["Vs10ArraySlice", "Index"] -- !private ["Ps22BidirectionalIndexType", "Distance"] -- !private ["Ps22BidirectionalIndexType", "IntegerLiteralType"] -- !private ["Ps22BidirectionalIndexType", "_DisabledRangeIndex"] -- !private ["Ps21BitwiseOperationsType", "Distance"] -- !private ["Ps21BitwiseOperationsType", "IntegerLiteralType"] -- !private ["Sb", "_getBuiltinLogicValue"] -- !private ["Ps25BooleanLiteralConvertible", "_getBuiltinLogicValue"] -- !private ["Ps11BooleanType", "_getBuiltinLogicValue"] -- !private ["Ps11CVarArgType", "Distance"] -- !private ["Ps11CVarArgType", "IntegerLiteralType"] -- !private ["VSS13CharacterView", "Generator"] -- !private ["VSS13CharacterView", "Index"] -- !private ["VSS13CharacterView", "SubSequence"] -- !private ["VSS13CharacterView", "_Element"] -- !private ["VSS13CharacterView", "count"] -- !private ["VSS13CharacterView", "deinit"] -- !private ["VSS13CharacterView", "reverse"] -- !private ["VSS13CharacterView", "suffix"] -- !private ["Ps14CollectionType", "Element"] -- !private ["Ps14CollectionType", "Generator"] -- !private ["Ps14CollectionType", "Index"] -- !private ["Ps14CollectionType", "SubSequence"] -- !private ["Ps14CollectionType", "_Element"] -- !private ["Ps14CollectionType", "append"] -- !private ["Ps14CollectionType", "count"] -- !private ["Ps14CollectionType", "init"] -- !private ["Ps14CollectionType", "removeAtIndex"] -- !private ["Ps14CollectionType", "reverse"] -- !private ["Ps14CollectionType", "subscript"] -- !private ["Ps14CollectionType", "suffix"] -- !private ["Ps10Comparable", "Distance"] -- !private ["Ps10Comparable", "IntegerLiteralType"] -- !private ["Ps10Comparable", "_DisabledRangeIndex"] -- !private ["Ps10Comparable", "characters"] -- !private ["Ps10Comparable", "init"] -- !private ["Ps10Comparable", "lowercaseString"] -- !private ["Ps28CustomDebugStringConvertible", "Element"] -- !private ["Ps28CustomDebugStringConvertible", "Generator"] -- !private ["Ps28CustomDebugStringConvertible", "Index"] -- ["Ps28CustomDebugStringConvertible", "Some"] -- !private ["Ps28CustomDebugStringConvertible", "SubSequence"] -- !private ["Ps28CustomDebugStringConvertible", "_Element"] -- !private ["Ps28CustomDebugStringConvertible", "append"] -- !private ["Ps28CustomDebugStringConvertible", "characters"] -- !private ["Ps28CustomDebugStringConvertible", "count"] -- !private ["Ps28CustomDebugStringConvertible", "init"] -- !private ["Ps28CustomDebugStringConvertible", "lowercaseString"] -- !private ["Ps28CustomDebugStringConvertible", "removeAtIndex"] -- !private ["Ps28CustomDebugStringConvertible", "subscript"] -- !private ["Ps23CustomStringConvertible", "Distance"] -- !private ["Ps23CustomStringConvertible", "Element"] -- !private ["Ps23CustomStringConvertible", "Generator"] -- !private ["Ps23CustomStringConvertible", "Index"] -- !private ["Ps23CustomStringConvertible", "IntegerLiteralType"] -- !private ["Ps23CustomStringConvertible", "SubSequence"] -- !private ["Ps23CustomStringConvertible", "_Element"] -- !private ["Ps23CustomStringConvertible", "_getBuiltinLogicValue"] -- !private ["Ps23CustomStringConvertible", "append"] -- !private ["Ps23CustomStringConvertible", "count"] -- !private ["Ps23CustomStringConvertible", "init"] -- !private ["Ps23CustomStringConvertible", "removeAtIndex"] -- !private ["Ps23CustomStringConvertible", "subscript"] -- !private ["Vs10Dictionary", "Generator"] -- !private ["Vs10Dictionary", "Index"] -- !private ["Vs10Dictionary", "SubSequence"] -- !private ["Vs10Dictionary", "_Element"] -- !private ["Vs10Dictionary", "count"] -- !private ["Vs10Dictionary", "deinit"] -- !private ["Vs10Dictionary", "init"] -- !private ["Vs10Dictionary", "subscript"] -- !private ["Vs19DictionaryGenerator", "Element"] -- !private ["Vs15DictionaryIndex", "Distance"] -- !private ["Vs15DictionaryIndex", "_DisabledRangeIndex"] -- !private ["Ps28DictionaryLiteralConvertible", "Generator"] -- !private ["Ps28DictionaryLiteralConvertible", "Index"] -- !private ["Ps28DictionaryLiteralConvertible", "SubSequence"] -- !private ["Ps28DictionaryLiteralConvertible", "_Element"] -- !private ["Ps28DictionaryLiteralConvertible", "count"] -- !private ["Ps28DictionaryLiteralConvertible", "init"] -- !private ["Ps28DictionaryLiteralConvertible", "subscript"] -- !private ["Ps9Equatable", "Distance"] -- !private ["Ps9Equatable", "Generator"] -- !private ["Ps9Equatable", "IntegerLiteralType"] -- !private ["Ps9Equatable", "_DisabledRangeIndex"] -- !private ["Ps9Equatable", "_getBuiltinLogicValue"] -- !private ["Ps9Equatable", "characters"] -- !private ["Ps9Equatable", "init"] -- !private ["Ps9Equatable", "lowercaseString"] -- !private ["Ps41ExtendedGraphemeClusterLiteralConvertible", "characters"] -- !private ["Ps41ExtendedGraphemeClusterLiteralConvertible", "init"] -- !private ["Ps41ExtendedGraphemeClusterLiteralConvertible", "lowercaseString"] -- !private ["Ps16ForwardIndexType", "Distance"] -- !private ["Ps16ForwardIndexType", "IntegerLiteralType"] -- !private ["Ps16ForwardIndexType", "_DisabledRangeIndex"] -- !private ["Ps13GeneratorType", "Element"] -- !private ["Ps8Hashable", "Distance"] -- !private ["Ps8Hashable", "Generator"] -- !private ["Ps8Hashable", "IntegerLiteralType"] -- !private ["Ps8Hashable", "_getBuiltinLogicValue"] -- !private ["Ps8Hashable", "characters"] -- !private ["Ps8Hashable", "init"] -- !private ["Ps8Hashable", "lowercaseString"] -- !private ["VVSS13CharacterView5Index", "Distance"] -- !private ["VVSS13CharacterView5Index", "_DisabledRangeIndex"] -- !private ["VVSS13CharacterView5Index", "deinit"] -- !private ["Ps9Indexable", "Element"] -- !private ["Ps9Indexable", "Generator"] -- !private ["Ps9Indexable", "Index"] -- !private ["Ps9Indexable", "SubSequence"] -- !private ["Ps9Indexable", "_Element"] -- !private ["Ps9Indexable", "append"] -- !private ["Ps9Indexable", "count"] -- !private ["Ps9Indexable", "init"] -- !private ["Ps9Indexable", "removeAtIndex"] -- !private ["Ps9Indexable", "reverse"] -- !private ["Ps9Indexable", "subscript"] -- !private ["Ps9Indexable", "suffix"] -- !private ["Vs17IndexingGenerator", "Element"] -- !private ["Si", "Distance"] -- !private ["Si", "IntegerLiteralType"] -- !private ["Ps21IntegerArithmeticType", "Distance"] -- !private ["Ps21IntegerArithmeticType", "IntegerLiteralType"] -- !private ["Ps25IntegerLiteralConvertible", "Distance"] -- !private ["Ps25IntegerLiteralConvertible", "IntegerLiteralType"] -- !private ["Ps11IntegerType", "Distance"] -- !private ["Ps11IntegerType", "IntegerLiteralType"] -- !private ["Ps14MirrorPathType", "Distance"] -- !private ["Ps14MirrorPathType", "IntegerLiteralType"] -- !private ["Ps14MirrorPathType", "characters"] -- !private ["Ps14MirrorPathType", "init"] -- !private ["Ps14MirrorPathType", "lowercaseString"] -- !private ["Ps21MutableCollectionType", "Element"] -- !private ["Ps21MutableCollectionType", "Generator"] -- !private ["Ps21MutableCollectionType", "Index"] -- !private ["Ps21MutableCollectionType", "SubSequence"] -- !private ["Ps21MutableCollectionType", "_Element"] -- !private ["Ps21MutableCollectionType", "append"] -- !private ["Ps21MutableCollectionType", "init"] -- !private ["Ps21MutableCollectionType", "removeAtIndex"] -- !private ["Ps21MutableCollectionType", "subscript"] -- !private ["Ps16MutableIndexable", "Element"] -- !private ["Ps16MutableIndexable", "Generator"] -- !private ["Ps16MutableIndexable", "Index"] -- !private ["Ps16MutableIndexable", "SubSequence"] -- !private ["Ps16MutableIndexable", "_Element"] -- !private ["Ps16MutableIndexable", "append"] -- !private ["Ps16MutableIndexable", "init"] -- !private ["Ps16MutableIndexable", "removeAtIndex"] -- !private ["Ps16MutableIndexable", "subscript"] -- !private ["Ps16MutableSliceable", "Element"] -- !private ["Ps16MutableSliceable", "Generator"] -- !private ["Ps16MutableSliceable", "Index"] -- !private ["Ps16MutableSliceable", "SubSequence"] -- !private ["Ps16MutableSliceable", "_Element"] -- !private ["Ps16MutableSliceable", "append"] -- !private ["Ps16MutableSliceable", "init"] -- !private ["Ps16MutableSliceable", "removeAtIndex"] -- !private ["Ps16MutableSliceable", "subscript"] -- ["Ps21NilLiteralConvertible", "Some"] -- ["C4Trie4Node", "Bool"] -- ["C4Trie4Node", "Int"] -- ["C4Trie4Node", "Node"] -- ["C4Trie4Node", "String"] -- ["C4Trie4Node", "Void"] -- ["C4Trie4Node", "char"] -- !private ["C4Trie4Node", "character"] -- !private ["C4Trie4Node", "children"] -- ["C4Trie4Node", "deinit"] -- ["C4Trie4Node", "getChildAt"] -- ["C4Trie4Node", "getChildren"] -- ["C4Trie4Node", "getParent"] -- ["C4Trie4Node", "init"] -- !private ["C4Trie4Node", "isAWord"] -- ["C4Trie4Node", "isLeaf"] -- ["C4Trie4Node", "isNotWord"] -- ["C4Trie4Node", "isRoot"] -- ["C4Trie4Node", "isValidWord"] -- ["C4Trie4Node", "isWord"] -- ["C4Trie4Node", "numChildren"] -- !private ["C4Trie4Node", "parent"] -- !private ["C4Trie4Node", "print"] -- ["C4Trie4Node", "printNode"] -- ["C4Trie4Node", "setParent"] -- ["C4Trie4Node", "update"] -- !private ["C4Trie4Node", "visited"] -- ["Sq", "Some"] -- !private ["Sq", "deinit"] -- !private ["Ps16OutputStreamType", "characters"] -- !private ["Ps16OutputStreamType", "init"] -- !private ["Ps16OutputStreamType", "lowercaseString"] -- !private ["V4Trie5Queue", "dequeue"] -- !private ["V4Trie5Queue", "enqueue"] -- !private ["V4Trie5Queue", "init"] -- !private ["Ps21RandomAccessIndexType", "Distance"] -- !private ["Ps21RandomAccessIndexType", "IntegerLiteralType"] -- !private ["Ps30RangeReplaceableCollectionType", "Element"] -- !private ["Ps30RangeReplaceableCollectionType", "Generator"] -- !private ["Ps30RangeReplaceableCollectionType", "Index"] -- !private ["Ps30RangeReplaceableCollectionType", "SubSequence"] -- !private ["Ps30RangeReplaceableCollectionType", "_Element"] -- !private ["Ps30RangeReplaceableCollectionType", "append"] -- !private ["Ps30RangeReplaceableCollectionType", "count"] -- !private ["Ps30RangeReplaceableCollectionType", "init"] -- !private ["Ps30RangeReplaceableCollectionType", "removeAtIndex"] -- !private ["Ps30RangeReplaceableCollectionType", "reverse"] -- !private ["Ps30RangeReplaceableCollectionType", "subscript"] -- !private ["Ps30RangeReplaceableCollectionType", "suffix"] -- !private ["Vs17ReverseCollection", "Generator"] -- !private ["Vs17ReverseCollection", "Index"] -- !private ["Vs17ReverseCollection", "_Element"] -- !private ["Vs17ReverseCollection", "deinit"] -- !private ["Vs12ReverseIndex", "Distance"] -- !private ["Ps16ReverseIndexType", "Distance"] -- !private ["Ps12SequenceType", "Element"] -- !private ["Ps12SequenceType", "Generator"] -- !private ["Ps12SequenceType", "Index"] -- !private ["Ps12SequenceType", "SubSequence"] -- !private ["Ps12SequenceType", "_Element"] -- !private ["Ps12SequenceType", "append"] -- !private ["Ps12SequenceType", "count"] -- !private ["Ps12SequenceType", "init"] -- !private ["Ps12SequenceType", "removeAtIndex"] -- !private ["Ps12SequenceType", "reverse"] -- !private ["Ps12SequenceType", "subscript"] -- !private ["Ps12SequenceType", "suffix"] -- !private ["Vs3Set", "Generator"] -- !private ["Vs3Set", "init"] -- !private ["Vs12SetGenerator", "Element"] -- !private ["Ps17SignedIntegerType", "Distance"] -- !private ["Ps17SignedIntegerType", "IntegerLiteralType"] -- !private ["Ps16SignedNumberType", "Distance"] -- !private ["Ps16SignedNumberType", "IntegerLiteralType"] -- !private ["Vs5Slice", "Generator"] -- !private ["Vs5Slice", "Index"] -- !private ["Vs5Slice", "SubSequence"] -- !private ["Vs5Slice", "_Element"] -- !private ["Vs5Slice", "deinit"] -- !private ["Ps10Streamable", "characters"] -- !private ["Ps10Streamable", "init"] -- !private ["Ps10Streamable", "lowercaseString"] -- !private ["Ps10Strideable", "Distance"] -- !private ["Ps10Strideable", "IntegerLiteralType"] -- !private ["SS", "characters"] -- !private ["SS", "init"] -- !private ["SS", "lowercaseString"] -- !private ["Ps30StringInterpolationConvertible", "characters"] -- !private ["Ps30StringInterpolationConvertible", "init"] -- !private ["Ps30StringInterpolationConvertible", "lowercaseString"] -- !private ["Ps24StringLiteralConvertible", "characters"] -- !private ["Ps24StringLiteralConvertible", "init"] -- !private ["Ps24StringLiteralConvertible", "lowercaseString"] -- !private ["C4Trie4Trie", "Array"] -- ["C4Trie4Trie", "Bool"] -- ["C4Trie4Trie", "Int"] -- ["C4Trie4Trie", "Node"] -- !private ["C4Trie4Trie", "Queue"] -- ["C4Trie4Trie", "Set"] -- ["C4Trie4Trie", "String"] -- ["C4Trie4Trie", "Trie"] -- ["C4Trie4Trie", "contains"] -- ["C4Trie4Trie", "count"] -- ["C4Trie4Trie", "deinit"] -- ["C4Trie4Trie", "find"] -- ["C4Trie4Trie", "findPrefix"] -- ["C4Trie4Trie", "getWords"] -- ["C4Trie4Trie", "init"] -- ["C4Trie4Trie", "insert"] -- ["C4Trie4Trie", "isEmpty"] -- ["C4Trie4Trie", "isPrefix"] -- ["C4Trie4Trie", "merge"] -- ["C4Trie4Trie", "printTrie"] -- ["C4Trie4Trie", "remove"] -- ["C4Trie4Trie", "removeAll"] -- !private ["C4Trie4Trie", "root"] -- !private ["C4Trie4Trie", "wordCount"] -- !private ["C4Trie4Trie", "wordList"] -- !private ["Ps31UnicodeScalarLiteralConvertible", "characters"] -- !private ["Ps31UnicodeScalarLiteralConvertible", "init"] -- !private ["Ps31UnicodeScalarLiteralConvertible", "lowercaseString"] -- !private ["Ps10_ArrayType", "Element"] -- !private ["Ps10_ArrayType", "Generator"] -- !private ["Ps10_ArrayType", "Index"] -- !private ["Ps10_ArrayType", "SubSequence"] -- !private ["Ps10_ArrayType", "_Element"] -- !private ["Ps10_ArrayType", "append"] -- !private ["Ps10_ArrayType", "init"] -- !private ["Ps10_ArrayType", "removeAtIndex"] -- !private ["Ps10_ArrayType", "subscript"] -- !private ["Ps33_BuiltinBooleanLiteralConvertible", "_getBuiltinLogicValue"] -- !private ["Ps49_BuiltinExtendedGraphemeClusterLiteralConvertible", "characters"] -- !private ["Ps49_BuiltinExtendedGraphemeClusterLiteralConvertible", "init"] -- !private ["Ps49_BuiltinExtendedGraphemeClusterLiteralConvertible", "lowercaseString"] -- !private ["Ps33_BuiltinIntegerLiteralConvertible", "Distance"] -- !private ["Ps33_BuiltinIntegerLiteralConvertible", "IntegerLiteralType"] -- !private ["Ps32_BuiltinStringLiteralConvertible", "characters"] -- !private ["Ps32_BuiltinStringLiteralConvertible", "init"] -- !private ["Ps32_BuiltinStringLiteralConvertible", "lowercaseString"] -- !private ["Ps37_BuiltinUTF16StringLiteralConvertible", "characters"] -- !private ["Ps37_BuiltinUTF16StringLiteralConvertible", "init"] -- !private ["Ps37_BuiltinUTF16StringLiteralConvertible", "lowercaseString"] -- !private ["Ps39_BuiltinUnicodeScalarLiteralConvertible", "characters"] -- !private ["Ps39_BuiltinUnicodeScalarLiteralConvertible", "init"] -- !private ["Ps39_BuiltinUnicodeScalarLiteralConvertible", "lowercaseString"] -- !private ["Ps24_DestructorSafeContainer", "Element"] -- !private ["Ps24_DestructorSafeContainer", "Generator"] -- !private ["Ps24_DestructorSafeContainer", "Index"] -- !private ["Ps24_DestructorSafeContainer", "SubSequence"] -- !private ["Ps24_DestructorSafeContainer", "_Element"] -- !private ["Ps24_DestructorSafeContainer", "append"] -- !private ["Ps24_DestructorSafeContainer", "init"] -- !private ["Ps24_DestructorSafeContainer", "removeAtIndex"] -- !private ["Ps24_DestructorSafeContainer", "subscript"] -- !private ["Ps14_Incrementable", "Distance"] -- !private ["Ps14_Incrementable", "IntegerLiteralType"] -- !private ["Ps14_Incrementable", "_DisabledRangeIndex"] -- !private ["Ps22_IntegerArithmeticType", "Distance"] -- !private ["Ps22_IntegerArithmeticType", "IntegerLiteralType"] -- !private ["Ps12_IntegerType", "Distance"] -- !private ["Ps12_IntegerType", "IntegerLiteralType"] -- !private ["Vs26_OptionalNilComparisonType", "deinit"] -- !private ["Ps22_RandomAccessAmbiguity", "Distance"] -- !private ["Ps22_RandomAccessAmbiguity", "IntegerLiteralType"] -- !private ["Ps12_Reflectable", "Distance"] -- !private ["Ps12_Reflectable", "Element"] -- !private ["Ps12_Reflectable", "Generator"] -- !private ["Ps12_Reflectable", "Index"] -- !private ["Ps12_Reflectable", "IntegerLiteralType"] -- ["Ps12_Reflectable", "Some"] -- !private ["Ps12_Reflectable", "SubSequence"] -- !private ["Ps12_Reflectable", "_DisabledRangeIndex"] -- !private ["Ps12_Reflectable", "_Element"] -- !private ["Ps12_Reflectable", "_getBuiltinLogicValue"] -- !private ["Ps12_Reflectable", "append"] -- !private ["Ps12_Reflectable", "characters"] -- !private ["Ps12_Reflectable", "count"] -- !private ["Ps12_Reflectable", "init"] -- !private ["Ps12_Reflectable", "lowercaseString"] -- !private ["Ps12_Reflectable", "removeAtIndex"] -- !private ["Ps12_Reflectable", "subscript"] -- !private ["Ps22_ReverseCollectionType", "Generator"] -- !private ["Ps22_ReverseCollectionType", "Index"] -- !private ["Ps22_ReverseCollectionType", "_Element"] -- !private ["Ps18_SignedIntegerType", "Distance"] -- !private ["Ps18_SignedIntegerType", "IntegerLiteralType"] -depends-nominal: -- !private "Vs12AnyGenerator" -- "Ps9AnyObject" -- !private "Vs11AnySequence" -- !private "Sa" -- !private "Ps23ArrayLiteralConvertible" -- !private "Vs10ArraySlice" -- !private "Ps22BidirectionalIndexType" -- !private "Ps21BitwiseOperationsType" -- !private "Sb" -- !private "Ps25BooleanLiteralConvertible" -- !private "Ps11BooleanType" -- !private "Ps11CVarArgType" -- !private "VSS13CharacterView" -- !private "Ps14CollectionType" -- !private "Ps10Comparable" -- "Ps28CustomDebugStringConvertible" -- !private "Ps23CustomStringConvertible" -- !private "Vs10Dictionary" -- !private "Vs19DictionaryGenerator" -- !private "Vs15DictionaryIndex" -- !private "Ps28DictionaryLiteralConvertible" -- !private "Ps9Equatable" -- !private "Ps41ExtendedGraphemeClusterLiteralConvertible" -- !private "Ps16ForwardIndexType" -- !private "Ps13GeneratorType" -- !private "Ps8Hashable" -- !private "VVSS13CharacterView5Index" -- !private "Ps9Indexable" -- !private "Vs17IndexingGenerator" -- !private "Si" -- !private "Ps21IntegerArithmeticType" -- !private "Ps25IntegerLiteralConvertible" -- !private "Ps11IntegerType" -- !private "Ps14MirrorPathType" -- !private "Ps21MutableCollectionType" -- !private "Ps16MutableIndexable" -- !private "Ps16MutableSliceable" -- "Ps21NilLiteralConvertible" -- "C4Trie4Node" -- "Sq" -- !private "Ps16OutputStreamType" -- !private "V4Trie5Queue" -- !private "Ps21RandomAccessIndexType" -- !private "Ps30RangeReplaceableCollectionType" -- !private "Vs17ReverseCollection" -- !private "Vs12ReverseIndex" -- !private "Ps16ReverseIndexType" -- !private "Ps12SequenceType" -- !private "Vs3Set" -- !private "Vs12SetGenerator" -- !private "Ps17SignedIntegerType" -- !private "Ps16SignedNumberType" -- !private "Vs5Slice" -- !private "Ps10Streamable" -- !private "Ps10Strideable" -- !private "SS" -- !private "Ps30StringInterpolationConvertible" -- !private "Ps24StringLiteralConvertible" -- "C4Trie4Trie" -- !private "Ps31UnicodeScalarLiteralConvertible" -- !private "Ps10_ArrayType" -- !private "Ps33_BuiltinBooleanLiteralConvertible" -- !private "Ps49_BuiltinExtendedGraphemeClusterLiteralConvertible" -- !private "Ps33_BuiltinIntegerLiteralConvertible" -- !private "Ps32_BuiltinStringLiteralConvertible" -- !private "Ps37_BuiltinUTF16StringLiteralConvertible" -- !private "Ps39_BuiltinUnicodeScalarLiteralConvertible" -- !private "Ps24_DestructorSafeContainer" -- !private "Ps14_Incrementable" -- !private "Ps22_IntegerArithmeticType" -- !private "Ps12_IntegerType" -- !private "Vs26_OptionalNilComparisonType" -- !private "Ps22_RandomAccessAmbiguity" -- "Ps12_Reflectable" -- !private "Ps22_ReverseCollectionType" -- !private "Ps18_SignedIntegerType" -depends-dynamic-lookup: -depends-external: -- "/home/christian/swiftv2/usr/lib/swift/linux/x86_64/Swift.swiftmodule" -- "/home/christian/swiftv2/usr/lib/swift/shims/UnicodeShims.h" -- "/home/christian/swiftv2/usr/lib/swift/shims/SwiftStdint.h" -- "/home/christian/swiftv2/usr/lib/swift/shims/SwiftStddef.h" -- "/home/christian/swiftv2/usr/lib/swift/shims/LibcShims.h" -- "/home/christian/swiftv2/usr/lib/swift/shims/RuntimeStubs.h" -- "/home/christian/swiftv2/usr/lib/swift/shims/RuntimeShims.h" -- "/home/christian/swiftv2/usr/lib/swift/shims/RefCount.h" -- "/home/christian/swiftv2/usr/lib/swift/shims/HeapObject.h" -- "/home/christian/swiftv2/usr/lib/swift/shims/GlobalObjects.h" -- "/home/christian/swiftv2/usr/lib/swift/shims/FoundationShims.h" -- "/home/christian/swiftv2/usr/lib/swift/shims/CoreFoundationShims.h" -- "/home/christian/swiftv2/usr/lib/swift/shims/module.map" -interface-hash: "eefc37d55a335afd501967035d9090a5" diff --git a/Trie/.build/debug/Trie.o/Trie/trie~partial.swiftdoc b/Trie/.build/debug/Trie.o/Trie/trie~partial.swiftdoc deleted file mode 100644 index 12942dedfe6852aa61b902224cde186d2adaaf6c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 540 zcmaDfX9YVW2LppD0|Ns)qlJ#c+7Dby0=U-%aP4>CT5rI$Ux91Q2d>2%xY!*xUFbQa zy@N^j#3Ahshx9v`wD%m+SaZl(Xp58P1t*OOP8vYc#=uE?50mBxdSs$%*Q9pSHW1%LeHSMEDy*( z2E-K>X7Oewx}|y9dHLmex;dG7r4_pAd8I%phE||K?m*gzO@POXg+Yf2BnSi!U~-gz Gg#ZA|lTWSy diff --git a/Trie/.build/debug/Trie.o/Trie/trie~partial.swiftmodule b/Trie/.build/debug/Trie.o/Trie/trie~partial.swiftmodule deleted file mode 100644 index e7406d6766930d93bf2df20bf71744e783feb822..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 66060 zcmdSC4SZGAl{b9y0fZZxTqx4mqMpQ{0fOEjVt}Y8A7W6{E2NrsthoV#q(ul2G&&u7 zNTNoEcCME3p&e^48ZFFFn^HPM`(vIS1KK#lGmR~saXOCg717c@P8+Gy(J61|`Ty5m z`+g;8r|-=3`@Kug{#<+Qwbx#I?X~wgH=KBUZ%JN}#tQ0a=%(9>S=9xt>9;aE`g^|8=k zw0M6s^u1(g59-FcrX3824s;P~O5VZI!}-;t4f787&ObJM=|KMc!^2hkhZ|=c%b&Y{ z_|l-EYBYadT{!=eox@divm56D=UBtMf#HJ2!QtvN`3rUpqj43Q?HaC6R9EjyhK8cW z2giz^3_{-G&B}E;1xgZg}yf$`i2+!b^s1X zixijctSNpP)FYw2W5q+^&_O>m<+%gVM;hkt%;$*vd*{c8FCA^TBxsnMA%KFJhZ?F5 zLfj2iLk;u#WvnOjt9K0-T=aOu+(Qj>M;hkswC&F1SNHc;_czRkKm@7raPaH-A_D0>PRj-_PXn6i{aBBPc5k|Z-e;%4=we7mGYGk-7(J+NxipYo}y-*Jkc9xHw}8v2$|B~ub9{vIY5x^1R78afy+ z9s3$GYj$kl;R^zd78U{Ghirxe30z7;KgGE$7vgV0>jJ42)NN0p&(M2nw= z+G4FFsfYU_sdhs*KRFiqc9LrPHK<<{`Wt#`tT>C9bX5AuNnD@b84W?Nhx`y}#MtsF zuXx{B=-DxJO_oa^+n&+OgcvWK6FT4)?}-kv9Y(31DbNR|kai z47dZ25iGl6NDqAM!H7~F|LHBo&${n3)a1r*IFt{hwg;kA%I+4(a{pNIGZ0ZEN2vaG zjt|oY6Ce_ukib2I@#1I0p|7jpLi=MW;{G3@1!WH5M?;6=GU+gN@k|a9JL=~q8|EFu z3hSK@6ULPS)f%tRx3x!#_knY3A|bwmW3)M#IXj%uf#<3RL7=zlaQ-D$%L|T9F_Q!J zg24Ac+dK|x|Cs-;&&@@zyLzh!hpQ|)&E*Kp#_*+B)-W%1E%${(--=KN_l2QeR2HSD zWP&r#Rgd;oA0Mt7O*LvtL?~)Z)PZO*<`mOqdyV(^F2K4wlRtOYFt&js6`>)_Hbgj9 zJQxi<6@*IvrfPS?f(eP`j+r3_)~54OPczTurZiPjU%-dla)`#O!{Z#&!WDx+|Y1k`tX0RNeka@wZ(F zm}_syOG#-Ab~`CbfvpPrnx$TF5*y)!a*aN6gp>bx!;(XN^ZOf@?K+|}2=hOhzhGpz z;NvBGVx_OeOWq2XoCr$Zuu_0tK(+_QoGF=E*Z@gK*8mu&qj*B9xnMsxa6l3jACrGV19q!RVQ=X9l5o1e-IjUG1Da{qNP9W zDtW^#eI{D^3-BS*%oXM1S01P3s0#{~4IZiOFSv5>$g)F?Py)y%R|(F2rE$TbBX#|K zOLq0mKYV2VK;KgAsQpKlJdP)4TD|FM^VvCC4j{_r?*Z!Lt6o zWuuKtcODtnwE5q?(0kB<(UPA<#;L*RRfE0Db~i3f=5pG2v~AYw^-wMoY)>9{F|?^^KF?HE4gbDJyP;Ur1V$uk`pjDkYjwD9A8~|3~OIht$(-{OdP{i6-{% zZ#djryZ1=dKyTe(fvkpH;TAmjVXWspPU#rdL8OH86cNJtC^wu3NxbpCk+QZ|m^2%lP#SrpY zOq2I^Q`J!8(#QLj9mGr*T$#I`S6*3O{DxP0$}Rn6SLv^ESs8lo=z{*fxB@~b{oo*$(O={8^Phq56AkU_3c-tlCv!ktp{K?|&&DW` zgT~dr;U44oox%P}my~WuUCWz0;K_xa$?lS;(Kwx)r^jMnnQ{qEb-RZzO&zSU$7!Pz84f*#?jkrS(~aY- zWVU?b-efO)xVdMBGacL1!Itxspit()^~5pwuWUbY%o)dzqrtueMPueKV|>YPURyPQ zQy~09@pIuBA0Dngj^60jT>|$rOJ4E%Kg?z7xre5J^|}4HC&59Lb2#_7bs68cWx>Cl57%~RtayJk^p{YAv0_Xt z+_luQ;yioB6#ZD_x$jRXpZT~C86EEX@CBKtLC9FVbMM8>Mi_WQHM|bYIXqRcU$^d8 z&+%}9dy~x8P?~Q>i}ztVN9h(H9P?hA!s{8Hb0Cr7>YX@!=p6z5?z-0Z@`~XK|0QNt zn8zA<3WwHFy5Yw4F8!1HaE>?P-aR~jq+xzPZUvxVUB7uP1ReRhEREcgGn{y+%xGv2 z4t3D6_TYkVImJ+29BObX`mUU7KA=t8=P(1f7QnR$mIYUH=AlEDOBO$$edc%O=X-IS zs}f(CTs<<3!@+!L#L)1i)QjG^5X!-ZDjbKPX-2#2+~2+wf;^v$h7RCz==sl?;@O4A z8vc}1j%nV9Ll0_UAtA?b`qWq&MMo21OsW6Y5JrckkAqO^2JORo12Q~+ckkR|xDXkx zu3Mz%oJ$Y)V!2o2sCsPp$f7}%(pt>JQ3}TMOlAwOZ~=~1XK?uGg_fs|GSzie&(Ft= z6;7KN@(4&*FV8yj;O=A_)|p>?#Eb*jokC$A%mGvrcMQ9$eP*<7Do|`2)SY)B-v# z{SN2PJvLnM6glgyK8Xn%=55sI@R7e9f{+`kAms7JE{pe;X>;Y6DwCm$G;`#Q$5WJ4 zRw|zAx{Y6$Z{}{osmzdGeX_dJ+(XzK$I-&^_Y$RXdjWt|wl9(~r#~?jSl?JNv0@mp zZzEx{_SlOPbLod_~@*$O8?eW$BLoV zkk-><;Tpr|UwYWs(Jk*!23@<JC2YywFO_h;AFJq^`Hc9CN3V}!vF8YlzWq*Z^$0?Y)p+dZs49Ci%K##1yE(0oZQbe`U#mdt7$=|}A)MlS5iZ+#Wa+6L=V!hyfL|l`gN;oMOZc zlbhp-h7f{PCCzSG(d2U;@vfbpDFce4Rt3FwqoI8N_J-NxR+=`)%J z;uoBp(mpftUVZbF!iVA)6uwwmadJw1{tCDGzHs^DlX};UNI}D=-RAx?ZUYLhE}C(C zO8x1+qW9`i(tKZ{V)vBZlT)T&bam1EUU#}w#09l-aO%Rs(0ldwf$o>ixC5cy!Y%dp zg_|e8_uR=TuWgK%v!=2+++1|-jLM>Q{bypQ``lYbN{2U;UyZPbVebGs+}G!pr#fuC z44uuu!x9kMF~~8@YuI~%JNTQt(|u>W`$Ol<12-3b&OhT_6aGyB2DGRIJe;oe&>_a# zUy1>TUq{8BU8NY&Na?(RU**lHD1nFy@jTp$z{OK_0<#t%kreJbV-Z zCc(j^JG1c+I5#8#h~e>D1B6jLP>g^oz{gpYN1OsC*AB3WkKzQg&Iu+xA+ffI7`at= zb?f+Zsz_%c9>Po$8G>L~`f!}CqDoZM7P8tsrFk3f%~Y8^Pmvu>hfu z$MJ&%$OKHrrfx;(En*t*Arm?IeN&JU7UvXk5N~TmoyOP4S^9$IMoV3dDK!Fd0KSBd zv$LpzDQK=wzVil(nU@jHI?S38Z7{?PKp01iB}eeut4+fBFk%V|;G@kb6D|^AFcfDd zj5+lYv(`mC^wtW5(Rm0mAc?e#$HT+EX5fLM_-l3}L12H)lP*F?IXdysN`ym9mNir{ zN>zo+C_@rKm9R;*xsCacQc6;Tm~wS0MLiscwt}FQz78q&;#w3&Z7q=fLcxO`h0BOs z#;kh|*^H68H!p%Hz+iQ99VQdg5m?QMGwrEb*`E9yMjopp3)cvfMz>uy1B7DFH6rrt zI6fw&j+a;6!zM+RbtPCeSqlPkACO6(EXAH%hS0b3c!8l}c}#LFfSE54mw-4X2^d4f zpJ!SG4LE0Tjl2sH zI4Vk)Ec)wM0??%z(0BnxP2^PHGYzSbEGjUACJC*X8T3Agq#x6~6=Qzu7@LF{5R~bt zbA6a1Sfc{AOX9JFFvkGkX>IjY=O8zr-FiwR_V5r&13X205eyl@eiX^@ECd7X2v-4)e{X<*VY>o9xkSB^M*!puf3h@znRJ{Cnmm6CD% z76(b6isQalj?g2AoDFBy4z|C7$;JU${S+71xLX4t&f|Q3p3}7$55O0W>&XFNgNdAvqBKE1WjC@C=a`%)$qC?P6M-a0 zmqk)AwkS#E*7*rLV%d0-`D&FcNx_IJeUae{+G(p6K5AlLr^H%O3GdASp|KL_b?ofO!+?d7v7=mp0FM-cYVAR1)T2uQ7&4JltJPep0Pi$qCu{g7 z#Qt*T)Y|!E!CyhD0JUTOMJ5|lI$c^_W{UljGE1cJBuk3K{>gM?NmICLQpT;Uo>3Yq zE3sFB()ZY(m&nHOa|nEtEjJn*M^yQQPRE!QF5+@!*&@=l9lJ<7{j~IeAsv}uB&0}3 zztUo8;cbekqIN`-YEOVtc{TA8cx3jQ?_<9*4mR+Q?Lc#%Voi=tMRK$X$(Yg@K-vla z0YkK5LqOt>5HvAC2gpjsAs6l;1OTyuh$pc12LvHy&JxPCl|h-QcGS8UOX^Udm$GKz z6jrn`IhcPg!UvelSg_N|D_D}M`rB8@b)o7Rs|f4`j}KxVo9-B>?@VfhMu*6uaHP z6=pTH1!yuLJW6T+?bx4f zvYE%mvgyZ&Gy~5|NaSan&VG)vJPOgNz{5o(_Pic8i$Xe1bi~E4vgZf1D{J9I8&SRt z4}b%ZSXsfQ|0CvSIu%kPYFjv&Bjct9OL#uQ2$Nwh5WxWeo zu_Vco$h|Crq(}r17c=WPuPBo}rr6W!S`dc#T6>9N-EGe$0;szl2*=K2y50j_Zz+?; zG3#aWnIf81EG}Qp!wtyz&)-2sso|sm% ziRH##K12+&C35M6+2(q2qIgR~i0UXFt#*-nghebVn_f)@Ts$>QlzfFIB+GXZTk?{M z=pbqdKcPaiL0M@t^Gq(rQ_F<7#N@6557&poDWib)VjkJ;tixO#({iR+D52b{kvc(R z+V@Pq@m6^J)W}{PRSaoDDE5zEM3gwAi2KSVYGO^D-5_aikx zwr2X}g^V4xA-~Q(k8)puC)o28h$n7lQs-g}X~(@t`;_$#`mdv~8;|%*zABLj$ct*X zVunca^<0uNbFTHR#I*pW-+-JyG0EGqNoF}}F>)5PD28g4T)Cip2oE7*B3TniW;kkJ zLe@X|AnUmcEF`s&*|awsNzxqGqewY!B!*BZjo%2%ZXgQuU*(h(38x)Bweh}In?sj} zT)-_iYtM+2PGmPjRO`3`RTH~se8p6A4hiW!Lv|@=$8&7QCu@RYEb(QbBB8SKtB?i^ znJC+tle&?MO_jyisZ1#W?aiUo6B9yX;9Bp zPF2VsgogTDp5xuzqx0Ax?L1_8T*B`(i(wGW^#;;b20DR(R;SM_qcln0o2&@Pkl*40 z*RMn}W5N36O_XA)D)x^bqnHn?{E19pOW=(n$&2He84KX+D9aK$5gmU=j?h(st;TnNfqlOb!*!VS(-ew#OK&0QMqxTDiE4+^j?&9`qn8zmf9xr|%#! z7s+r9;$Xm~7!!E*qQmeg5;?c=N6`v}9?=mGC28bh%fPXq`a z;shRe#n*#pFOw#Uy&7Ba5?GjX3PsLy3;<2aNl`vc>MZ8Mg_Q^^DL;KF#IeU7j)HW6 zR1pK0^V#~@TM&kSgaF_#GVxIIAtYQ@5k76AMA=0q;j>`X4vzK5EE&w_eEd0x!|D>J zg-n>2Bzwt3#!C{dqVR`UA)vuT&c9%8TrPv1Q&Lpe z;D54Z@%c1Jy+9G*(gZxbLko&fP~EctMPU_0Am=AgWNW~%iT&Z2WF3d6MD_y+Abw%m z139uFjoblX;D3J&#sDn5zCkXqN_m1UQL7wyB_|90?a>{#AGHLYW;}}2oMwayH8$WN&6`QNCNcBifgLkI znF?ff;c>#;Hvo1qYz#-w-j+a&4FF{(Qb&Rme$HVT?=6PZ zak6Q=w?ia3e$Dn@iDH0dIK5`&Cf<89K&5*Dg7lhou0l3v&Hg)z2xiUx2C0lSdxBgo zFJ!5#*)vSMP(TaxHXd<<$C#M(CtSAm6eHjrRn|$kOi)WyrVDT#s%r!ZmZ-XCE|PYC z^;He{c7j{^N}^pKFG6@ijl!6UHy#>5>ATETeuBvgwxz9#R7fey^4W3`^+MN>GY@H} zUqVc-GP~ho6v7}mu{zgMVS{iOLF?Ej5xTk&Iyx><7nB!K!2px=UHTI`0#oWF5hu`# zhnOakV#8ef`Pib7l<^KFKY^q>3jx62VPd}DYC+Pja#Nc9o-r_mPW4sukt*sn*@SE2 z*0Cle!mI-L^(OY3yL2egX%$+;XdkuLmxBC0I&LysjYZtoQdQ<4s`HrS(5(kx?s+W* zxLO!Ap_G_p1h~wv7NF|u_nujbuWtW-u9*TYKgfrmI+6}4BM9PUgP{rsN9$D>W zjVqbwG|RRZo)Sk=##PoROKd&zqB=XvFGA7*(}w4Pf@WmTW0^Rn5vBmr!JtW}HVLvp zkc}65V!lPFG=&bhlbJ*|k@+n`bq}RrmD>XvA@vnN3lvret#Zv0Rz@uc(P>%`fVBH!Lm|`z^Xzk~oD;IlWxyv3sC}q) zod3mO10I$LU($e*;CEwWxkQ=IxLx?ah-C{ii= zSS10nJ|1|-)WnpaWcDd;W8CYALgQY`#Q6D?3pv!d+RMcAc^ex8h@>+?|C*Cn$ld`l zB{0*;&*vV%I_GG~xP7 zIsG!(&69}3Np*IXvjd9Nm!S?6Frux5OG{*_uC8B#pz#^g{Tsk;<6z_)8;$8*pz8AULo5JT{L41&3-M1D>) z2ll#_Ml`m=r-Bk>@Txe-E-#e(IdtMdSiW;~(o&SJB4+k?3C%152;+#Y!bGegM{`Fz zanZ>JA}3HVij2q105Xz50l8}ZbtS?o9v?EG3u)H6c-R*e5i{l0h~-0u3(y=os*ut{ zN0iBF<*ei4Gt*QwjWQI5rq?dPJ<^3 zLOm>+#y&)U%(*8)EOWc=k*xZ=Oq#1e?Mr0p>a~IGDWR2?k?YR~3;r7AgJY(62$P1A z<%nFJ5??r=KF+EmwtWE+SAwY*5CICzhAi9-C8?L5okw-1eQlLQ9U-(<3&xO9F*tCx zvhJ1w%EW(&_yDD7UM@Q+TM{+3De1+jgY@-WW2yHE!V~hd zzDi4URJ)a7ARoD=6=4idVG9DW8Pz@XCW?5n1bDi%tK^Fr6vR;AyVMm|q*l)}UO)*1 z2kv0cpJ0#ykb?&qP-OfBsmf{Oxzv2ON>ufbW7>?j$YImm%geZi&(Kk`Y;?{z04E~T z09sm@)VSIZGX4_McB0O(+y_#?VW!{Mn-8qa8>kwhOp;5r14IV|66)&4uvA7-XXSLN zw;E|hD!!e)4J#*h-95ZV3+UFFSMGa(#+x60287V3;>6ET1_^Q~3t2uV_Sr$k=U3wP z1z|a*_^68E$+jt?bnX=_2PN$}rc$uNF*ZeZKwwc}RuUZmn{qRvlzYyL2LNq~Xj2Zs znMbrBjvgZYUBu;;kM2&X2 zkr}{)U%&#&BIyysuTt^X36|sh3p--jc#`coBn6|&wDUO`PNQO2ExFcIS|v)DY|8kj z@9~F4{oNtJSQCR!=in881z4Vu|@;P^KeOn!a$AuRK~=anS$*oe!~BF{Phi zje8@*G=`f)AnSsM*3!9Ir=y1%0KeXISSJ3y?KsS;UM?iS%O=Wx^&q2PuNYRAe{L|X zs6AyhrUcTT+6{3;>DN{kFGE)(t3st`1_9+j9k;EXnvNaKfKt z2+7b20w%Eax0)I&-Ju-W>DU}y%*K-XWL$i!FY(I@UpDDgJ2=_(B$u&Z9|%uJf%s3X z@;f$@YkLKQqySsu@j%SQ6U}&uMf;L1bWyc8Rq?FQA2Wok(2XWR&rNa0=Up-qxdBUP zT_xjVY9p)y+gI$`jd;F53y2Gt=<_bybR`kuH4MRk&i;UEuXbZxJ4;+-Za8{dLRVLGHnIG*D`;f7X)L^#$ohOD@Ul|U-mz+3{g z+$KC`25L=$E?5}(*0IG1BjkplhbdPFCm(mAShNRS>uw&!*Fl_*gnnHWAdQzXFC&bz zr57U`A|ZbSDfMi3JcmX;$LpNv<@9i;_eqFv(0r80CsqD;RD3cPR4yY15I9r-zn>wz zWg_RnXPe7R(#P)XbLjyBjNcC9-;r;g#6gUay~nPk37*WGUI3*)uh>Nl;W+SMc;lWr z73q$jDAP`yt3iB5H&FZ-0)qI4hzs**N#0;lQT|qh@?C>D%gfhZk!$v%G=`^;fkS=O z+enXj=!G1oIWJAf+1p6ZWgRAVnof}KA}3#08DnH#sPz)ZoNal+*R!pB(Uozw)hY^q z8X3qq+fHUH*{oWT02rCqs|xDc(IXa7W|Dw8Vnrx;V=`hO6J?v$UKe3l#}t$!1BkE7 z1Hu6CJ@48`~RP`@{ar1%$6Z71e`xnihRIrA`00AFX)Gg(;} zEYI*BDA5e>flPUC1_;GeW&9}2dEXE9Z_`QA&B#+DK14!*4O*>cFvFAkGt_2XQTXJ@ z-^UPOce<4(OT{OQYPD6a^cBTYV!ZE%`bTw%TUlL|Ei1V`2$WwDoL8HTVXpqM_=FWG z1EsuCGoqYpbUMbg@clm2uQE7XScEL6LPo#RVi*J`=j$)KJOZswI~5*{W%@&X+JF0@ z{#+!_`l0^U3?<$-65j7a{isSt_8g$nGB~PqGWW6TvSsJ$qO`IjPXyVdU^m_?XO0v; z&V)Jk{{@rA9Xy}pG8Sychx$@wKGe6reqcKS)ua-GM=u^UJdv>gTIfj%Jb5k`+cbYSBk20 zopp>5IY+*g&6BUz#IpQlQ|(~KA*4ULlnXwyaFuu$1?hGhar&x}`l0>;RK-9exP(-; zcnDmX-c>tT@Yi_op+4LjN7NbdJ39Nhzgo=l6a$`R=qVOK-7-DJnbT0V0hQUFVo?m* zh(bC-VZ^Ot+;6R?Xf@1LjgX(Bqh7QV@uheG^b|SuiT`R(QNHu{YgC+HP(iMdPE(t@ ztJM!HlW9-U>3|SbC-_3u4ue;0##59}xQwUx!a_rqQXqnhIEn|J;?sz%r%0NFl&8q| zRXLvGmz5LaDfTgEJjHw}jqwz_$o1Jh#eq9e4X_{PWP6JC{X@!A^cDfve1|V{Y&^x6 zNWplDPm&4q>6N?}&F~bpik@OK`7>XEct~abK3%G0&yTPMAd9_U4`tFT3ZF4U_jOM6 zov?h;g<9G(Ic!r`gxDdJ5a>JM4^l9M)57CbB>C=%N$>&wEOv8wIlt(}LLrl$a(Msqg>)*<`(TD_kA}b^lI&Y(hsjK)*op z(85KW{h_3@8ASlgfkQ(AXf~0r)mX6d#|YkKvH9f3AP*9j{@ zoiXD)Df4oc^{3`wY{@1NRqC)igp5yqM%YFAlOGy0d-xzp*(SxZB2$OQY2uqufMq!S z$xjy#lir&FLV2y4{^TcMo19O6envEa`Q+#4NM(HTLz95_pe&_D_Wn1km$MMlL+~ac z@M{?Y8cdY?nVwK#gO}OTyn5V8R5K4QOJ#s|30%iY`$IH4K>3aUbEm0-^l0yb zL#l#`VdRvSP?fZkiz*>tezHmmZ{yKlLU1-ukRkI+h+`x%AIJf;UQs zG`(hhw#iwue~2Q2`Q(PVj5Yf&thun4rLtx}%lzv+5BYZ?70}v9qWAkyUth$CqSNFa z`TVX^A+dc~TQf-(v33 zY9=4S6C*ce)1{PUZ;Rll7qmG9aX(L}*U4K6!am*d(Yr$96Pa0_vAx{JZ zy^itt(Ru=T*;9R)TI47IZyf>xw{L*ibwef-5F=;muB#jHD z!~^#1ClL_r1RB?qMo?VO^O%@(ib`sYU=PxS=JURQP_{{YJt9Q^%YQ{(MFB=GWOo2c z8sJh80AIqi`%ESQ$>xrSbu~ zRP8Ls9*)fjeTke03MeMAn7UxdpEy%ik#1pwW)=gis+F0nowST^4)AW5Qzg_tPb^VH z^e1YuP21Vkpd%DbKvi6;t%9ZBgA0|cla!EHr+isvDHVX#LG@oOIf%=bdI#z{Oa2y@ z{qSK(%V+vE{p8(+xS}iz${IL3oT9z#%&$#iB;sEOWox*K;}E~F7n}ARF*v3|CcN3C z%B=)Ho{FI)K+4>-*#VCVZP@{UWKVfAA8H^3(_YHjartZpu*25BD<&d_dZET;H2{jd z7Lk`Da4*leF-a0?9iy(K+!$&TAUe&O8IYA58b|5N`$zW@gJxOExc}q)>;2!kNM-!O zk(`+eE)f_qqDYOD7Qiy8o|6n6#c`=L<6<(c6&slqt%x!OkRBdT*;(;~O=B*?^K&Uq=lBQ3dqyh2(&tVrASu+;uV2R(i?eZj5w9c2xHGf07&tu zvtYY2f0xcBitra>3b28}096hUNN8RXGb#O|*!+IW)nRi7QVZ;v-*4GYWT_8m&vvjr zDFN(YFGM<}saz@^4G%#v^aQ{vW1cM=Vu5Oui`%7%G#il_`#F7fBqXDHGyRYgo7hh98wfXlqw z+36bXS@ucfL;6!m*-Xq&C9fdu!pS_`N#6q^9+}5**+!JUOa%85n%scoq$-Y%SaOt= zyVX!Qlrf-7d)0ZAYhM%xDpMTf)UP0Z(EELazT!ITkzsy~Ens&qgt-L$N(@j)uTA}U zBOz<^1Qozr%!X?RK7`Q2u9RTbuPNkWaq-CCiF39D;5-3uHrqQ$kT>rY1cXaXgdab$ zco}np`BbO7m^AN%L`+#bKrJiR>DsjH_plIr=-AD>FNf1)d=C|w&)9#5r~sjjJSPPZ zNCp z_;3z}hz6`EfuuDdN+4|+i#TuT@5aJxV6GKBlFa^dYk@V8@)ztpZa=Z94G2@)#v)`0 zYx3rxRC*uGFG9h?EHz*Gm$A$6MLf*5?kk% zaNRWF$vzeCXNmp9BBp|}BNbB#ekNT?KKPM7OGelvYkgkEl9RgC*!4NYLN+#W)=ubA zcHRL~LpB_?am%fEjPliU4HVN!#dr?EXK3h z1d^jWKtJnmr0pd}_)`YY+yg)-zk>Xec(QnMC`tFQK{cQID2Ai*h!G=pNHMf9nZuLJ zDo|8H<_EDtfm38oVYJGCB&Ff?>kKL#y#<_ys(>_Vn3!=A3Z1$Id;vuOT+)-kYpUyU zr87ytU6M}Bw@bRi(eO=U%O+t?Y(UYp#VFXw((p$H5hj_GDsE{kInEOKO$p+-j_Yyl zt%H@|h0Y{EUIHPm?S4L~d<_9J9;!tcqYAyRR>#Qo6e|DREz`5phMyz7zj68=Ghb;iGz^`(siDo;c zFtmYI@=u!C#s3bFWd5qy3}X|=%l?L-&!J_Oe>(XTcUcjhO5cu_AkV)Lpp0Ym=(QH_1}uKpJ?g%$l9wDr03o*2&p?X z5jBb;T5NuTF&s8os*aL$CT00#twKx{(N2FPhZ~uGdsvZ;f6GJ|Ri-l|r!R^HNS|l5 zf$bu$d|H0fURxz~Q1+xD#lclMZqn3m>LJ4b;~){Gl?r0~x`4eH1z|@qwizm{XFY8O zz#O2Ee=#2j{GG12+7s*-N$toks~_c|pTxCj5YRR^li2hf7b0>%DO!ox=#J`@jMU@m z0a)FMsZ^})=tj=Q0CxGVN%GR-!^oz*PjNDlH>cH@VhNpr3X`+)dP^&<@i9l=-4qjG z5gwO`6tRS4^tN!P3d$05wNiGtj}F z`SuS!^AMi3%wj}!=`aEU9rln;u3e{QnLVio_%bw!n+DFLp?Br{5nsw^jQ#6I0e%Td zj>4nwPOu_5-N+nKzRHC8JKi2yNw1L4vW={eC~*K02J3TltAVZ3s^^-l6O&RdASOs5 zOir?Hd}1hYj_GW6K7zy1jy?HLUbeZ#8 zxhCV%%Df#HbCGp^B?-B(DVjzDUqNHY5d!@m?ofUIeENFl~z^N+^JZQ;>LD^bwR(ho7% zjRz%u46&c5+I>=or;&N-B;WN76Yb=K2<5|1Iaui*Ip9dlA;jg1DQl2UXhg-83YWpj zG)gA=?aD&dE3SSX!2n|>%D&@`vane(JmqP&3a-+$$o9i!#kz{2W3mkc)4*PCt<&}p zuds>iO#Dka$a=Kf_^SmsA?#sN@N)KLPCGzts(u&v1C+>Z$SX|D8Q}(IU(WI~Ktl2D9JswR8&f(D zKSx{u|5k~}FdF3BeZJl(|yu@IhZJZafT1DnF z_IImTb>=44?T5D+vH`SaOl5_?f!stU0ti010tw^zt3=00)}^cfc8k9(-2)n<8q4@o!v6Q@{D}$TVJgA__$Fw$#%|^Gsr@W+H)-Bwg{~ z9byB1Ya;#-jW9%U0z|D4ZpT7xvg2pFx6Xy3}Hgu``sIfL|2FkLWJ8`{tsNu3& znZ60DqFBsLSZfiI>6@?w+kEg%Sd6Uzx>NWnW?z*veG`@_2UgZGOK>731~WAnp_cX; zbl-4P;^~{Ppb?nHsOe@Y%Q5B}srXtLxQ1X#KuTY99qS?eZ&VGS1~*~s=mT!TDrm?6 zR-C*90oWmA9nll4bNP)TK}V6)IATg2J)&2b>?t4@YJ=b5Cd|#@MyCIELrVU5iqoEh zk^T1-59th!-~J|-8!A?Iszp|`uJRZ&SQ)4F5mBYoA8CxHRB1??+{PvYeWqc|(pk!l z`yiQp8Bf4Oq(bh?I5$5h(Fyj{1{4E^Oq6?zt{+v5=^$xt#TF7OU8EK zMU=wbOBmc!bqRp9+7VV8+qtu9ib;D^rU z!$y|{W|O0_w6`;IQ2HJIF!q<&q(Cpwj_P>xbh58!CAPjCag>}_{v7!RceYFzDw}Vl<^m(o z)yrPLiwD3_SfAEI-kV1xrXcYIhy+aH#~9oj*-OwXyJVIB{ATnYPzW3d;gE?Omf=a1 zJ!1-dv7qQXS-1?vT)rbsJg7k z`ea>7>cbzJl`djcwczB0S2M6k& zL)JxTM%pe>;$sd}*9V@*EOeaXBrPj(d_ELIR>U??Jd9)+t3_=6NU=mzuO10Pq<@4F zt%1u#)>-lkENMa&VaP<8KfPy(_hx`Fi6`T&n$I@L(U%ZreKOEPG)FQ`} z^V;seK?f83*g?k~Rbg)6u>#9E`?D4g1*t#AXGy;Qj~!I5pQ4*_zDBSFT$!{?W{gKXRGnD~aV_u9WRW)^Z4#8Xa#!t7B4{c~vmRk}Nf@WXUmY zXw|rjg#cZ29_%h5kTBD4cSOx%Z0EC5ywRA7V>e6Oa)zpqh+S0!D=YCKtaAc`nEI`m zV=*pdVVb}MYX*A;!8_N)vS#)pJ;9o}&Y)zknat70sN(=D%RtrAiaKJd9aX6em!4a8 z#y>lIF%iw{D%qMJyb;pO{+%O9``l6qpEQyAlX5J}k__#h^G%iAMnx5jDw8q%_T@-d zWf*9&uYK7;q+g*OB$f2V`UWDJSIBb5lXWx`36;q%=A@jzBnbel(<*Bo!_ywqM>CO} zIkhNPakh)(uo`GXEjE8i8+hZ^lq{mGnU1ijx1LnNfKINLGmo;UEOA-Sl{%$%rZ;30 z$oMOeE*YO-2;x(wH8rZd+FsO;A3ucPL!dXot!;~PpfZ(PTMuOu+}fTrsP-o{`r8XK zFwp@+Wozdu=YU~$EuV|te4g&n=!l3d@1js%m+91sIH6|33Q*tW>vc^O$X4${8N0J5 zOrpjsbDS6{iUZBW1G2UFbCBdQ%8bO?ULM$dM^(s<YRkSZ+H0{V-qBcnb?ENaujK40OwOnNScdHu46giT^ z_=Tj10cmx{a^YT={<)lSmdwxPD3{;iM>dY^mS0r;x5{`u8>e+O&}utFY0I#PERElS zUQj_y~T` zXKprutiO#_$GV~lgOQkK;?Y{fx8TXzziuziq zoyc@ivC{5)|f<3!a4RT ztcymCfNr`+NwN3|)+LPo+WEMiHHA6Gs+)yiL?w~)sry<}i@(Z$2~yJEU%eBdpazsYc&r1EhvrGoXiC2UAOcwM7~H2+ z*iydwt!3lzCttzv3H>|ZJA0L=`0u|Ks9K6)1rV28WLJ_~Wp&w|w_B~AJMUeaDzY!E z+@c;eHtxJyO_BX8A?JSr#fAOhY4aKfUM!t?vh=MLtf8V!e&&&1-s}`QZ7s`h*;Z52 zwz_+3=cYRvH*f8zS=hFAbJsm9HbpnKukBdha>b^OyH|JK+p)T{rUuEz_OAA|o!$2! zd-+oM2dfQf0 z+qS;FyM5y|TeoiBdPB#yZS8k-EN=l53s-lycXzHeoUCrcf7?Ni-fy0>vgFlIEimjZ zZ`@XM*$wTR&}?19_Vw#KwzhA-{I2$m+dFzb-nRVO)m=BYwV9B5kmr2i#@IhBF|4d= zUB0<(-7VV|e|*KJ?wZAI>sGJ1cXM>x5@Ds~p019zHez(HZqusO5%5eU&U1cz>!y}# zbwqbu4t8r*W`>6qx3q8F)|MvCp^9LeJKDPp${mZ_giSEl(?)&GbN=Bg$Lr5Jtc?>4 zD~iEUJ@cH8{q)}>-9{pxgh&?FwA~2l-PN(WqkDDt=B<#w~C9gJXI$JSf6T~4WC z)HQ8%Q1YBtKC*rGA7yY*s~j|SuI=vJys3TbJ!fTPOWS`HD^&PA=k_05@xr-eW!v4I z>$}^wb+6mlxu)&T_Kh1iuWj1~<>d)3-}!2C+vi?N&*3fGmNaf?-`c*myJIVt0P#QG zvb<(7rk(28v1NP5rnMbZjBRb#Vm7Z>v1wgL57x=G9S~1D#7qUbcJ;zG#!$;td8*Cj zt2cJ8?GQamsYJ$FTio8&)v-xLj#aenruExb_2hJYYtNDt*(-FpwcVT2w5{uVTH3g~ zUC?yFy?5nvMRUomYuhCM$)amnO^scIvDK~yn~OibsdMe-bsdd()+(o~SEVNS+SRKt z$G}_ExOwBo4w+1Y#bU@|VeQ8^ZEIiOVKgVYxpNZ)nBq~8R$oRvnLs3~J6CstgXNpI z-rc@+oyb#ZO9j-c^Nvj&sOavvqho7E)n%8pHEi$P*xk8F>sEH6*Y=Ij*1I~kc6YAX zh)IG40)Iy4It)xtEgl(C+qNarV>^+v%73@n&TImj(3z}~)r(-~IBX7b_2tYkvDhZA zkVH-!qT_*be3AwOauZ8zWLtCD`mLMqkQv{60A&ENRBy1S>=wz~J$wh0ty z>-v@(dM@wW)U~~POWVRlTRXbiJGZXbxDgX`XU96L`rB5o5i8$$=k`0(hQF=l+SOZN zBWpLbuM^X`dQBVm*gR)Xa`UE|^g3L-v3=XNwmUkyS8UqW-HxRc-Mp=nM(UcLZm2tV zm9|Y{wRo+U=e$1n+}@A>zAAi6)^d)dmUAtZ=LEW(QukX>pB50OZQMHMH2&XFTJS=} z0{2K{YpX5%T~$@_N$#>V%{HTsi&ROCN@9GqR!NswCAICL)opzK|E{6*Q}diR&j0i0 zcV%n=XH%LCji{MGBaAHIsBk~89s+@%;ae~Y{wQ#G~YF^poIbVD66RTYO$U}Cjnzb7*zXGY>&o}#EhYq_S1j8K=n?P#U z1edE|!E&}*+2ucAca!xA=X3(4Kw;MI!!^T6xn^55r=!}n#>d*W{@&&HPPoCZUbA`) z&S;QU=a!LI?lAhW>e{Uw@aF%|J{;UzOroK+n$C-CL7gn*m0X_l*6g0mQR#Ht@nBIK z%z9^PJ6PXxmXpBhPHbn38gJ@qha06z*v6AxzH>?0^2%yEq)3|#YMr>nZ5qkEni6=f z@R!?o?)k+PfAM!`Zx;ntb~~2vIG*QRy5sz}SL>o$zbL~s8o%c@u5YPbn?B^!=pxV~ z(87-F1JCL<-nHa8-Ro*^c|tpYs(p}?lv=b{EtLBBJ?Fp0!tjWm=iGhj;A3@Wa&u>Q zVFaGQ){br1o#`aiZ>wM3xMIcfmbTSvu!>X5XZ0E$!1J6#jsAah=1k;&t9J52JKwn~ z`0>l@Qv;aT-d$F6cW3tod0Omg+X5e%4+aRwrt4<9%qGUf zwB6js`-=OXKmWQXQ`7r_hox+z%=1~!k=35dxOlS7>{-?}O=_lXZOO9Uu&?wZJHf5I zAMwC4U8=JIkF>e476sqZ!e8W8X5=r|>lFLPd~Mb9D8E+kWqyeGJxza7uT#FH@fjS; z`L~FDy}Wr=ujWYSLcPD(f%sP$cNw;i7S6u~jPyDgtu08$&uRIbPd>2J@n>A^crRUm zKNuT!s&6lHE^40athl(q`LjRGb8h-u$DOm@NnCZg)AeMf)AN}b@~=|7_veMq?16lL z)irtEA3o(o-o4q`{o5*Mr$5tq(+fFA+)4gJ@%*5*IWM+&(DCjs(a*8+oE3ArYL`+` zvQDDn@2=}uckR~pt_`>_Y23Jd8%{4bZf?Nlxeh1gRoihQxuG4de~-Ctc)~)UKG;UVz z_7mQpT#`bvC*~af8gO~=8C(){;ed5d%ht{g?noY*?mOeU9~~*pe{F~NkbCt=>B7pQ#8j3x^%hQ@QMi24d-eT6 zQN`5*;qXUJPRVJa)RzFRQq^XrSVBU+_2OR}aK5XeydsQUBSPjpDvi5x5Y!7sbs?We;?scD+YF-aYyrC zEUl<)j=Svq1<7b;bZk9JHSAUfmq7`bQ9*3Vq7^=9LunKO_6m{1bl&Ws7`SXpZ~}G|`dwB(hYr zpXHtIo0fO;mHxxdcZ5cH_~%oK27iO%Gv587bLJ80Oy22&bMn4rkEs6v)ag4OS=k$UWoRX&*s?eLh`S?nPQ{GM=$;1X?!1=0d;JX; z)dzK7ba&v^Iltn|g?TkM^!kS`s`u7?(RIJOA{_pIDvJiXW)vQ+otppTx?^Ir9I8{AYoF70|z0nD_QgkXjig(Jw>j&72l@-IB@8 z;qb=_fcS+xV16I+t61lw=Y?LcS9Pu%zHxF<|E|3J_730QaIV|n9-bBs*AV|pz;F0p zPTrQwyxw5sTo-yDUWSVJ6L~X6_6F~ol6s=<0qXLXoQ3zsb#Gh8&2Y_Jn201yT~{Kj zn0M{`IdaT?UQq~7!ry-pOlURtu>_uKz8eJi9uVU{Mldi3L_9ib-`5S&nL~^t3;=vd z!CHDHJkl2H%M#Z|X7)h@gejMp*n14P-mYhmd+Y>)7CfKeXCpU%8Qru#41?Z+A+++# zJ_1fw5fMZ^HqgZpHlNXa-#(8@`WBd=0(=6>7J{%KbqJBi>{ zJf{Bx?ElN?KZZ`$tw7N9A{xayv318Wu&yp{Hh|eliEKN%7Oh)Rv@zB0Az0klK4kf$ z)_8*Gt$2K3nitBrYmNu<0uf=meKH9H>;>h)uYKw9)#4iwQZ^73~( zC7;#oWZd8TQ|t%iMnnDvb&oAaApPqvyu2v-cZFmjx-E;MzF}ep?2j{o@7pw3ssk2yn`SJpH~S z*aC#T7@2t$ZeO-;Kq*|38r~$Df$*I+ zrE!xpBPeuU!=N(3D|GW#>bk!da_Y)AHbBy$S=Sm|FF=*9F)$p=n2L@e>wtfgn^4q) zV0HsoV{TU%K^$7)Ax=U(9Lgw2uzU>9J$TCBMqnV5@7Yj(pT)#=3i0`-he5eJUI!T# z`7=29EszmqokZPf#0@9x$g^l=GsL-I8)fL_voe%Lf#VORZEW1$2yUvMGjs9C*acY$`J$}0G#RnLLh>gB+ zyKCJF6wYXb-&ohh*a%R|ElS8S2=mLE4016Jflzb{13WwMUOJhCh7xL}YbH`ml_Tc@ z*+(2;xQr7Ru8WwxpIx8A)Z0ujYwD%}B z+1HyM%uiklq0}C^>xZQYc7O&6dRY06=VD}3mb9OQx*&!=;wi=FUL5=oYn9Dj0U_$* zeV_-H11xPHSs&FSzE zPjftskPLo!$bR(E%RT1#>83$A0gh5C<+3o`iF(97Hj)J5^mh9Ya>*eKnN#x&9>xps za8x-a+zD?&VJ4(m3(tXVbT00?`%QHzi00?T_Uyns#2{J^!rzO2_{Ge#sB1-aHJ(|h zh6@y+nqOJ*_agrj)iG3Ig8eci;g)z%V}1j<8`Xb@>J6w`ga<2$Gd_gs7^)AV`V~}f z##4(bnyC^f7p5_R>f@+>3su;rEFBSY0BkQ3|LFcpFl$1{8#?Ub0}Xgw$qe!@qkmom9z7!#;HHVgjA;bq^pkR8OFK1dr4I!*Zb0S9EvLQ<=>=+--~v}V_>RMaqJfDSVB)}+ zk=!$w9@jM-*IbT^ew-QCLzogB*XMz5NG=7#W?YY6m>L)VWkBQh4?+zS2N85pF$p61 z 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 g4}{le29ON0Kw*&qWY}ZYi%DLOyvo|^4 zx_5htgB_B+s#2w@Qu_lTM5{^&ejtHD`9Yz4gi4iA5ww5+A&^=mXpu;f096Gm>nI^0xJLVhiiZn6{M4B(&L-md+&1 z^sF8$x^4=FLxWQxd3t>G_;g4f9Ul%oEPwC;d1Ab%PwqaeT~Mqb^|l29ID4-di6%7u zP)u9Y0A*6uwRA~`Bydd)4vmFufQ94bZvKQG11hFMBcX7w3~1!ZsqpCdNUwY>Jo?~Z z_=J2kbRsvBk5J^p6XDS4$T+*@z)<9H=x`_;8V`mhZB%+PZglH0MUiJlr;bcaPs!nl znbBeEPU3Cr1X&q*E`+QK#Xw7G7o%hV>QG!rWHI&UB8iM94~^~%wVo-k*@u5x^; z#=>I8)M5pl$};x0?bv~>6PzwaJv&Gd9jvD^{&QL?tsBV#GzncxnzJSSVCt!eSuj*# zwu$LK5&RmZA%TVjZVd@|Q4_+=SW=qk`$(d1Gp<|df9T)oHTpJv>(&rLgUf~lZdwU| zU2jJS>P?)*maGbGbM_?E-hEItv2M?90yU=JWfxoQhMhJ_Ljny6d_*O1%%N-ZkVLE| z932nL8w*-Molog$Q;#GA>GOKrJa=~>lTHN^depuSr04a8bYLW5L?elb=ow8l)Bbte z{$FMwH&Na=&>L+-0u2d#q$P0Mpak|`kNNN2jGGZfml3*5G5xIl_hIr3^m~!DbET!F zgpFY>ebzJsD6-^V@MO5YIs8eIMR$YdZ*z+}Xr#2mMkX2KdAv#H(}fpzKtttvXwkVC7R_!Z_(<~9+;FCx0AB!3E3|uze`~Mh46Z% z>c;HfiylGn`!x>ZH^_tJH}tekYn}B{w+CHxE7dVQs@4!`w_xgoaP6f`Eh`{W>=yMT z+ciy^v6vRGtWBK)`4zVCLn(v2ryk^bHC0vw@~>C4p_Tn>QKspnt{Smgs@x~A|F^Xg z>z1b%(6_B#@CiMcSqdy2xNr8pPX)OA?I_Onua$i36M~TUhF{~9>}oFYt)A?GN|dZV ztXzob$?8$%3m0rJ|0|&lKcUJDBk5HCGu+-~+3Lui1WJPCWKx?FKYN213&gZ&W{!uv zej^w3=Be`=j--AjinHEd^X=gh`uY95L2n59&b&9UgZ1o%`2VknVijSPBRI$j9Uc%$;uT0@4~SoJlOF0th=%*%zbG6&A(vJo45ae z?H%JQ(dr4bRTS(1`xU0_swZ$pZG$f zS^_t!i-fMq%!DcAyvmydv)wm>or~WsyGLcvkZuh1prr(&BI_f5Ntm97i=yz;r*JjeAjhw!>Mi_%g-J z>&zXGKKbgEr6*7;`rAeGjf(6Bk?p}rhLAU?3@R+=a?OExOCbY%;j$T ze68pebQ_u_=o{#LvP^d33GybI#T36tP5S-Zz{)51Iy%GdLK`g|byTw2NFABIe2{|= zpx1Aw3Muv+I0|_0&EYM&5WUdnXcMQBnaw8JE&vVSc)c{{^%tLxNLFwy{8kI}^6>oz zj(r9sy4qw__3*lvD(EgQBr;bzcN@V;el~%VlTpbEt+%X-ydqXXSUcA#u?&JbDm1Fz zW<;{Kt#%6Smv&{7e!GK`)#46LNuFv?D}4@a#t%^vAwKc~`91Bxf5KnEDt(lG4Z6Qf ze^4*C|98*Rmr$@yqS^Xl`=J3mcL-9w?xv}DKfeEEBvd|5N?XcZ>L1TCyN6Q2qmUB zp1Cp+)jA{HcnsyXDQwr7EBT8t_?~5FneSO@C(6pa2|fzI+Uf$954m$MyBAUp*B zM0OQlCj;a%d4&=>OfC8<{VjbL>FB4}k50j$+GP_Z?KmYuUw$!X`^|wUtX3f$UqddS z+TOTmzZU@%!F5NG_X2){M*{KUFl>O5ODpr)1gX)A(^b diff --git a/Trie/.build/debug/Trie.o/llbuild.yaml b/Trie/.build/debug/Trie.o/llbuild.yaml deleted file mode 100644 index 7f699a487..000000000 --- a/Trie/.build/debug/Trie.o/llbuild.yaml +++ /dev/null @@ -1,29 +0,0 @@ -client: - name: swift-build - -tools: {} - -targets: - "": [] - Trie: [] - -commands: - : - tool: swift-compiler - executable: "/home/christian/swiftv2/usr/bin/swiftc" - inputs: ["/home/christian/Desktop/swift-algorithm-club/Trie/sources/trie.swift","/home/christian/Desktop/swift-algorithm-club/Trie/sources/Queue.swift"] - outputs: ["","/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.swiftmodule","/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/sources/trie.swift.o","/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/sources/Queue.swift.o"] - module-name: "Trie" - module-output-path: "/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.swiftmodule" - is-library: true - sources: ["/home/christian/Desktop/swift-algorithm-club/Trie/sources/trie.swift","/home/christian/Desktop/swift-algorithm-club/Trie/sources/Queue.swift"] - objects: ["/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/sources/trie.swift.o","/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/sources/Queue.swift.o"] - import-paths: ["/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug"] - temps-path: "/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/Trie" - other-args: ["-j8","-Onone","-g","-enable-testing","-I","/usr/local/include"] - : - tool: shell - inputs: ["","/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/sources/trie.swift.o","/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/sources/Queue.swift.o"] - outputs: ["","/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.a"] - args: ["/bin/sh","-c","rm -f '/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.a'; ar cr '/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.a' '/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/sources/trie.swift.o' '/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/sources/Queue.swift.o'"] - description: "Linking Library: .build/debug/Trie.a" diff --git a/Trie/.build/debug/Trie.o/sources/Queue.swift.o b/Trie/.build/debug/Trie.o/sources/Queue.swift.o deleted file mode 100644 index 068c988f70a207bd47b06b045f22a76272695d32..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23408 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 diff --git a/Trie/.build/debug/Trie.o/sources/trie.swift.o b/Trie/.build/debug/Trie.o/sources/trie.swift.o deleted file mode 100644 index 35fa7256f2ff05ec4eaf4d7cc3f3e31fe2ff4dbb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 107872 zcmeFa3w%|@)i=Czjwb|A3BgOe6pxA;FF=r6uwD`%c*LMlK=FbkKrpFDQb;tl0#SNu zPEJn^YFeIFY}#r~TeZ=e8f{afwUFL4efqSem!~hawuRbD>eC{?|t`=liBm1HEY(aSu?X{_Uz5(@`?q4oE*)f6~O9d|VP66f8 zNbJ{(BX|9N8?Z=xR3v_7UPb)U{P}HH7Di&_yCShgyDMVld&*nCUDony&ivM;Ly=h1 zU?jG5AhNT(i;NI<+pw46j`IGTNPJ^gMSOX8B)+_Ne%sRiNbHXMirDpFd41UMxw;7X zI!O=OPNWx??Ry~yytkpacJOaS@hy>9qWQpq1M^!GwgVD`JuG{I(9}HKkS-?Ryc0Bx->~VtrL)dSoOnH^SF4 zzsQs^Q-auw7NtycOLojHrOexu9L>d%_|k2WSY>e%+)-MVqG}WIQ9pkT?s|!OzhU_| z){HylLo7_%BN7ksHWK$DTlRaLazvcIp!`iZG z7Zht6E>_-;cI}`As$Bk!wEArMeN`m35mc8#cogcAyGN z!L57%9Q#XKo1Pa94LUUfh7BeKAnDRQrEN{mm$v*S2joNh%7=2A05>rz%}PbBsV3h4&pF38Yn(>LyMgxw(Q0%2!l z%S%OKE`?#2?-u36mJXG-zL3;QtZ7%-KJ*8vWfQAoRbT#$s%cyK zGhI1NV^N9tMpgGT`$j(6cX_Wh?m=VROVI}Gm)5cup%NQAg|(^5aMr^SQ!|+0d~1JO zejhgNwYdc0kf_4y!*q%Gu}~?c9f~AX%KP%9+V(`E{o@|!2kS7bbIlZ=Jvjcw;P3Km zL|cH#mW@MR(>rfaN@Ch_w`)TqI6BB~BgVK>N=^TA^@}wj7mIC5=5fL_!8kS*BQH`H z6g!SC)yZsY=da&gzi**>3~LmzbU$okH{#uq*pH2+HFW}VW5}Xyk@!_mHPhNnSqXHy z_)^eg@Qjlf#)Cl>JO+`m)e0o`U15id#L`}}h&Qz&XZvNThOsPRJ7}R@Q1Gt9QSh#$ zf?J$AcDb7_dxH`Cu9sMM4gd^|zR~yFE-fXNjPJO#GzW&!F8vAVh$EAYZ~1)#D!M<* zcmbu9LlKKQF#vo@OugF`4_L+vDi;kX`r~-Pa4QCH1Q~DlJZ;QEECmX zI#%|XU_0)Ra`yh$JFQp|3XzJ1aWg{2NSC={g(7B0z66Q9B%632S(=KG1{D*Uc$755 zD@NUCtyo%P#f=LVyMxx&N@nqKXc|x0cIpvhBsMA%yEZQpyE17^Ljrf~ zksz@ffvI}DPng7eNPq@01Rc8=i@k^%kQ6@Rpa9>xEY=T`zc+uK(96c;rTVX*+G-=LUAqm&G^ow%iRGFQZ-ln}ReqDUk}yhKMg zmCI>&N5u7F$ZRy;FF|4e!Th%9AcC@%Aq+0`=Az4lUtgsJi3kFWIM-pcL9vX1q)YPW zMdGny!O?@`oW$wG_LT|^3Qm;BT}QD5Jw*ttCNU$$6UMN{i(N&-NIY;~5xK>pg(=E( zpRA85DYwiz&~Q6-v(l=-dEQ3%Gh+-~Z?qEI}OB69}DJ@6u|m6DG8 z%D2(uC_Rjk!eYYM|4$m#j!0Z80X!nf3F2i3zK@BkH*%mKg}sQvh5*iQ?f4UdaVa@b7wwbM*~nH#-`?f>(sdg zV2R~xhDEyqv|dW=Wz6qGSbt%eGGyptX0>S7hsJNv{=N7YLi#M%ewYur^5Z077k=Vt zIDakaFYk}U{ubHtLjJx>i_i;<$4^(Q=_v8C1^nc2;(yHN9#59M_nUq`| z`TW%sFOj$S9mrequaLI{?E~9b;7oGZYHnnCOAab8bfwojrLFs0U%*ZYH%ibj&MI`npU|G7e zd`PI{Tvf|f(=Lt;JIeQ9oLp)MW#P3GU3DN5E3<<|Y$tlOSzOtK!bofYhK_Bd)OZMa zq^M_$P{{D{Ds9~Ix8J+mPviQEYpVg7c{jGA5nCcV7lfs@vA#~uPO+YC2(oA?+MY`5 zlj&=xxHd*zJ>uoSr=YVF>k#kAY*Frra(09EI+6^W0uwAQU56cX7K{YGnT#;@!s28g9wiKJ~Wl~_+ify?zZY$)E-H6h}Y|P#RQBe_OPz;jv)ka#pntv zSFDAJ*e8~tqX7Y2vHPJ~xMC(PI>5BJB}oiQOemr5T@sVli^MOE#Gl{Itg*gY;;|oF z5&OCfnJ|oZNMZ2=3xmJ2P10m#dSDQ0?nT@xwvQxozjvHyjP5G8d$^~#u@{pRRu|=i za9nmTihcXC7k+n1dFu}rMX>=Jts>W$tb*<06jDV5>?uV6howXUS!m90-98mD*J{Di?$WPP>>Z8E&i$2ldLMX~d6WPeHThb+UA6DBwaQ^b^4$(COd+Q4#xlMZBg3hQZEO z5&LCD{Bc7SWhYz|+fxxsuvacZQtZ4*6>%9}Dq@Y3u;bEW*f&nXPI8Z7&^QUsR*zxb zI4O*K>CB)nQg|`$rLO}oQFv)ZY{{euxmNCou z@Y9o8Q2QjWrzf?Vs44#GN$u&Wd{6>nBgE5_I@43T7>zwJiBF;`Voy)v!W`5_prGX4++q9}16GulkY`wNd5+Nwpk>|1dqBm0DBd#+ibac3RLRG10%G%-{avl8QvQQ) zd^$CfK0di|B;%;$_a|h%pvSwerY2hx)ADrcF7M|Ii63Uj zrI;bjvsVm3Lzqo5*1c@i=N5NRI(EWkMc{kBGHg8l|8sryc)wr9`#xiPd??I^wh6Jn z_+|O@D`VCTg4Zc-6^7YXOn0DaQL`TJ#f!CGQ``_KPYmX|OsrOWY}N|QWS3?E*4{=m z1UnO$iKN09Xhr-C3@u(o;&D@&*>g`s3#DxFFEDwb615`n%N#FEbvU8(nT_3phqwT+ z-3Wkpm?tU)AO-JiUuBx~RSxa>9LWnoV3^IH6y~U2#6i9oTaL{_dn2ZV*qxI~D`KlL z7htRhYNrH|kBQ4{spMRhEO0(12)BvPc>*OiS76X;VU6P*ER=&(E2FW8&6I#p=7QK` zlRAN0jmyMo?~QKai7-_Z@8EC&Z21 zVPZdmwhj{Dd2VZmM~UK1gK$<_qq6@M>nTB^RMF%W5ASH%gdz`{LfUa(8A45yAZra2 z=Q_|%GfX0oJ6BD$MYP^J*u&1rEt!C{X{GmH{LLK4kKU>Qk2 zaC1e%_}Y9#*+UvM4a>xXN+>8Vm8mZ!NkaBrQTi^@V^3ZJtRH)l^muR{c)c#NQ=Txv z9=PlALR$ybue=`+%5^^83USQ05L09AIZ&q!tPGX z(+TA1rb3dBEP74MFiP|@7L$#2%gEOpT|&U-=x5RK4wjjEZrrCtFuU21idnYwF*uB8 z$R;~YP@X?nsowOOW&tw7a(sd#sroQnnNOx>+r^Gmvb!uB0~OQQk-5 zC72XC4K0+(y8~N2I6jbr1b8%xze#EBjXXQScCh42>=!zkNn4bE!G{nyw4)}i(T5m` z$ukw3U!H2Tbx6WpFLB;deoNZ^BzGT%xg6WZMWe8G=f))9Ql;+-yIDk>g^H0@9+oo3 zV+PB+;C@(lgbVgXa7SqIJl}%@Gd%w@%vHhy3X3SXAy^-p$I}`1C*zyLk>~*&2@#6n z`#)e~V$lG9 zga>(cc5x%`*qsiD8Wz;>uKh2&21s&Z^X2@q*vYD-&?bHf{O5yC9WbP3n%w&ie zqL_WaFOU0~9U|K7{}%VetT1Gz!>l3m7oKy8oODl0Lu!Jf`o54My&vJmVlX$!@W*i1w2>o*)&(v@y$Jz@*7Q?3{-vXItG5QtnBwl*{>$G?))rrg2X= zrMl8nk|bwilhe$`7+vB$NqTWln&6(afO*P2p&FcfG6>$*aZozR>YhMdmB=m9SXYG{ zFmMbYXie1w6o}V2g_8hiW0$|TrwWZ7TLHx99N}F zN~EjOnyQ|-DvWbNarQvUgK2l~@`Jc4EyC13e6?pA#4l+!3D6_&4r~n@zr@hXX$LEZ zIr)I+#hd0~uEcx>w;D%V z|L)J_{EKN*cH*$Msgki$PI$vKIqafm@bNnzdc=Cn^MB0#_6Pvad+`(iX!-OWV(}D! z5zA~*fz(WGvRH%#3SDxxHm3z>Cp<6!;!eY6TapbPL` z8k3RVD(BxaTbt6N?UWZZfyXNXa4u#NwAFyX%+}0>*}7H$QZUKR z)&zaCH5d75({$AEo}a#p(8q$gbAXNIM@*TkWf#E+X?77zNoJaMMfs*_yM4f|&~_Lz z_jzUe01t7bfCpq30Z+8ZmwOLgLiM2CN`6eXl5I=Kp(=ZCH(>an-&jsO4@Z5tql{6I z?Fv(>Lg2D?5lU-#bc=ogqog~4BPCeLF6S7kvURI_aus%V*x!XXjA&4T9_C^ZcgK-KvDymcTJQW2@ZqKsECv=qo`f6v#?b4QC z<+LvEHNzacUQsGnd3W2Q-qvs1$u$~AN^9a2{Iydo0V$v@O4RrwNf3%5uhfK>j~J?$ zCqdL>S}eN%A1NVIMJL<=K2jmiE*UfvmcwonGmOl}34EIrBj4J5P-@Bvk2KIJ%TyDd z62a_|$U&j#9#A#rL*u-GVs;~VJ+${8nKUE@Fki-BJ3Z_Ig;luBZj7th4fcItz#QEg zL`rMNEBHIErRzuGG?9D(ZSmQrvEDr)W$T>>~eG__3h?O{0>#vQdKi*^EVrl;i8s2-k)akIgUdBg; zZiz1s9o$B7e6sX#cvGyP(_pkUE!M(VBHAlf7Hu{$>xDH4rOA$s8X@WEmq1QKqT8Xt z6Naoq@?z1-O!PN;s^kvG0i))wW0?SGmV^+QL4k8Ka5IDO4l_tZ0L~!1<9NZjB9B|p z`CQi(a@FRhjyoq6bH5o6Be%005|viO)^Y>-@m2xWPO1c}cCo7YGIg*Vw*hU6z|_Gq z@Px91Dv=FnP8BWCA*YH~gsG|HYj)@PVKZmg$%2p7%tph9WU|1%xT*4kllqa}nZW=w z=5Pqx&3O zO{`cXi-v_VDjDDf7;&2=kOwGGxgkkNzF1!&GjPkLCttF57$A{{SVimw7=nkpMKNqN zCHDWFci*pwoot$(t)9iXKdId#n{Nf61uc3VjU~79VEFk^}g||;49w%qw zGz9Wy<1b?)SJ7Tf)3c0bwsi{{3wFR_vaagm+l|-{iUqjlY(e$yy*bhE&i8keQZaTd zZoF_BT%dSA!q=r{68VUD*wB(%4Y;UlS!Dex-dYsbr6$Pez%NQc9s7} zA?ewTK(y_8Z} zR&wAQXO^lYm#8GNWe3g$%1R1mLob+MN28WK(6f!j z;nAc7eXSBCS`e7RVey3GJ%r@UZ-O~&VpQni3y2e7GDn+{{(9i`a)`lOH1}@FnWFxE9IX1yV}&+Y;<0`_$gekjuLFRg78iOIlp3Bp+>| zdAOxqEKHNT3lf#xg(8yxJ@W3r);w_(h2H7B7Xz%hPnfrQ@H9^5RCx~whCV2SP-)6HVKtW+H+Zo^azY9#1nRo)7}`CW-Y_N+7G-*62== zJJBmaN4Eq$T`55lyM?-gP$V`UdNVXvQH3VgRr%OnLNd-%m(f2MU=BPpvx zkS_RY>xU!F8G z_oqC$?v-r5Y(gQu4Hb@wTQQE+P!5If+pW-SQMM{#myh0;Vxu@sC$W#LR z=_0z_qUh_En7m-qns^kEy|v?HIcW;QdlRfSUyj;_L~EH*-g97dBMx4lBVu}`Q%Js1 za-mTOH@R%~f6FGCDa~!74RXkf^|gwe^mkk2j+?lj#lA|q39>$eTg0ey~52Y=?DD%o_F8nc8 zI0mv4kH@BnCp`t!mRzk9?Jsigx2dI!M_!DBP$ImN4uV9*K`1r}&<*dBj~@)Z-glFG zey?QH1=t{f-(mNc!pLS7C7W>(?33cK_11jjX(W^Pew-tv&RM8(^4{gNd#nOsGm9y) zjywqxp2}lV+&iR(K;9uG5fs;&R@(m5G%5Rgt~C3+g~^=g6&3GU;ij52Mtc+q?;WE; zQ(;1_(ce0vHo2Vv=r@4c0^qaN*D(auA0d&?qFQlpz{sM%#kofxQD=9$;|E`iyUi-B>Hxn8H)sT5)dfI zU6n7-eNl0bJzVQ^wd1z6;x@@`w;= zic6kVvQ|rla~}YnL3A5yh{vcB^t7s?sad>kSR&qRq9v7*rgQ7|S~fOjxFxJJNv0@5 zyj{HIkYbd+Uh3(V`n(B8fizG%%T#JtBDgoe#cSQt$KY_(F4>*h8^DS!NHuZX zlZkj%DKs61dxx;XL0VHtu}NEIVkMFxQ7N&Why;D563F(Rtx2B{;Pr1w;WjQwT{VT? zt;uZWVx-&E3~!NRQ1T|iQle}q+Pd~s5=wMPis77GlNBM8%zw=7gz?|wJ4^@K?Tlbb zG24$=ftoV&Q<*Vz+0Du1mjw)w%nBsrtRN-r-OY6e20K^JJ)ASly08-?h|#$@w}5jZ zOq6xu%XVFuC(LAL6OQ11tS+%Gd=tUAmeDd`nEQ1>xEG$}rMn7j%t>YX`oXv&hHlu$;-I!(0p3O@>E>Ph z5knE}LTpiNH#YhOk0m+<*o&Md%Z1oIUd#8L`bf&%VR+4J`Jz)Fr6&-^J+s-p=&;U2bsJ{gl*%s^2ER}mm}+sO=^K!@hrmde=zOA0Usck zBkSh9C2Ldi9)hzk(Si9m4s>6I_CmF55!mKU2$Zn9#XfhpmI^elBf^lH5raF}f1DUml%O6(wHc4rKY?9P~6+?^pCw>vXL{&+uY`0mWe-?QRq8SCTX5F>(F9Gdr& zvH2#-!Ytk*lYUGNpULFf(M|bcJzWymFU`odzHJ~wiYIWU9zu@oZixx`fx(tHz+q== z$HxImt~R;l$E5KK0P#kx6q6r`-zRd% z?K$-hIvR%}AL(FmvVGiu`__*7R8IQ=962xnKbLE4ukmD*$~!bLGjN1)Io|2F6IpQ> z0P|ysZeN`c9V~M!F^l4ChSbVb$9^_opZg|QuVgOo1Rv8vi@GpYuo3XMtJ~@k>oa@} zPqqQv$ug^PtRJK20&nY>Z^^jB>Q)ZE#baJ!;l{5!>1|$dkwHQp(8wSW z5gBEl9|tIYnkSQHsR4IM@p+~NN`M{MTEu>h<10xS(kDkas*Z8Va}_b!?XQSEG62w3!Z0=m*y8eG zB50yWhBkZFL|*KK4YD+(nT<;O{UEakiY<7P7BTr`EW^-gVlsHx!}Hd4v6H0R-83)B z!g=8^;|A8~poy8)tJxqA_wiL1nVA24gjji65qL*N za@&{c?6Ehyxw9=<5bTs>ZeT#~l5J6EB2{c$^RV9aJ1Oy7GTWy!ZB3moE@T zS*G9>3kebp$vg>q`DW|Y9PxupsZ^LJ8{MrWYm?b<2$r1e<`l(-xB|h@QdE7C9pe#+ z@#qT7q>6iAm3Cm+cyXVv!^HZQ2@Ph4Xr;2a+><+Qkqa-(>9THl0RWS*>>dJOw#b4udO_uEAk}_2R484?Zi~s64`JUP&CR_s*s)tw-m}MOem9CWjAGGU z>V7bJ?+yrIL=ih@4lpG#dJE}Nn>qYmhMJ18{v%baqhA8O_opU&EX0uPY9rIV-`64= z%x+|Z*)2t$FfSvT_ZCskfKQ`49!248%~4WfGWE=kX4@_4o!|i~k#RT_SCwQ-Y3d z67;l7(ASE9yG#-!nkDFHkYIZ)0(^t+W(4K~FT9gu7UmmtF)!t>Jaa!Ux`sA;}jLG}+B0 z1f|oPsfayJzYENY4T+Rz94>GvHK65UJuMN!dRoTC0+%YorB;GIv1jv=BR<^(vt9(> zd^vpcCJYYv+@icSy0ja3FC6%O;AW}g|6qk(gP7p1m)I6*&2PVlmhFAlSaO8KtNQ7U zh0n7)hx^c5stKp-_|7Z8CXN5AAo&T7r30wRAZoG;HQ9|C?iv2+jcqc?C*OHZf1j1_ zqo&z!f79yJi@I2wWSEpIOoj^gd_(Mx-yJZrEZPNmAWIWu;aP-5`;)_7vJ><}CVp|< zysY{m8m{>sQkM6J|G%P7-GBGMW^gVNRpn>QOuvwk%Y&)9;f42TRy$VVWI4KxNrOL; zymtm;_bqLk9J2Y~Ls1n8e($D_oy=@pnl9YKE>#hG8xDo(fAT7T`BoGA9)@|Y(ag7+ z2ILN(aq2U>u-JVJ;!ZO=F=1@=N`M?#A?D0Qk%x^32 z)C(xog$pPNKP}vHqSKK^5`A`bC1f58 z%3cp1=YR?1;}b#-tM<0p-tH)G!Lm$$+ZNI>5&zpp3%nuW8na)}60gHPlH!1k5y3oS zOp0;WOYARdjCJqVhtY@j0M=3D6E zGVsj8{Mfhf6}uq}KYOS?_r`wK?|<6w+Y75_i=cwx-*(IP{n_}H5Sj8~g_-)_CQx*9 zp|GP27y|h%0sXz(;;hdJz5@zVCQy(|$>_q;nNdv}Jt z8z*~VZ{Cb0>+5P}Tv5Ne#@!RJMXsu?USEyk)_V=r>uc6EdaF>~{o$~yDBfYCjp%pG{!^vwm++Me)abErU8gDW0!nf6|-+=KpeEyX4 zC$Fx#EnHMlam}Le^qQ5cSFSvN)$E${!t>TvV`N@4Yu2inD_72%z4E-U$yvO5^_ugi zmsGEweYQ8Xw*Jqd+UN?1q&4ybV>l>y@X_Kqh-dw-FuCeyk$*a~jt(?kn zdg_MyruD08HcV|qWQvfzb0*&8np^7{C)clhAEuV@a|nr)Oj)=6QF zHE1ie>}32CJ>FWsx(Pz8u3t5|p}Mj5U6wA*Jf+^WHd}cUreYY!TGQGnB|Q1cb@l5Y z5E3@jOs?Jlm8@Kk77S0eqO7aFwI)n+Ntf{7FP$mhmb$v8p=RCcnsuw{YBu~^G&5zj zEopttni@DMtI!Dl_A;fr__fhudgvUtbF~jf<%hj&Yvn~TDQ^+ z7}Aw*t8RoE>Nc!GudZ8H-B`aqykf?jndQZ^=9HC9FDaj1Tt0tV*{peUXUv{IyS!}n zycr8-d9)Spu)Dt3P%oX&6R&c`l1A-hF6MAKjCV%)r%KnJYWn+B$!Lt;m=)NstMOJC z{}!dpt(!Gtg?Aa;FGLpCd5bZY^7g9tuUPzk&-uedE?xZo#fw+iJ0+Yz%N8wBkhfwL z2l*8%t2fk?t%mEnVS~3~ef90vh*!;08@zc}HdMdAsixA_8sIe>rp@r9tLPb)ty{fd zZS~C?yroXgCT|5sF?iTUuF4H_%GQ10N*Rh*K%T|u^6PGviN^4qrXiEctcw@(?-HrO z+`4Hiyt(!DYb9Z&H@|L`tOeG8Knj6y#VKgY z(Ph_Qe5<}@!_1{i7EGH}G7lv#U02sAG6SAAJ&l@q>(^JKoW-|RuN76mK&G$ou1=Q) zHN5hg4RhwXmCm#oK7wQlh18T@+4}X>Mx~3ZlZxPKVDaLTx^)|B)?;BL)knk3F!=2C zHMiE^W?-4yOwDBxHdBCki&w~MOscg=>64T$?%D<#U$$n++=i>?&b?YS8=7o!@ro5o zXh0}?Zo@(8R(KcM`SfCD0Y4FJID2;KLt&pzx58T`-jDN=rcWuEQXDS2xvsGkzuKmi zQ&!dAdI1)%YvIvwfPjYsZ)pk=mB%!vdRpS<~mtnXzVdadma^nvxmCb5^dJRWf5v@!8&m zMv}T)8|vATb~4>S1uanRvTDteX{*eLGL4F+=2zg4R|n(t(ay_8o6d3u*WGKDtU#yc zosY?^riRrR)Yq6Y(dA9tPgS>}qNaKcxva!$o%cS9IdG;bWm!)m2%L=j2{$AOZT(Pa z67vyHD+Zf++$Jb%T(fwwy?X z>=7G4V)Q{v6vR)tsvh$*<}LQxm7a_Fsp>XV!o99*K1k&qnJ@b+GcQVJnvZX$G^xmA z8!Tn+S*@I=G|SAYimRSyO`=bbX~k@wWL2zcQkaz?%fxIA=js|xXf^Zd*RI9N8JNl4Pq6l3SeameN9o;Sy+u59gESPurIWYnijGlH=t z44n*IjQZ&2`{Jg1sJT?Mt{fSOn|aRNDr$d!xwUfo^ncUfvlj)!E+891iblAI37jx%sN+*;b_ zP2$VSlc#rG%i$akx0b^>9cC>{R@ujEnO#Vi`fjU!sKp$nJ`R=rVJc~sc@$|^BKE=L zyH!bMriZD3%*+n6x^uV!lxMJZ9!$pHZJkHpe3%s<3|^eeKHXRkyf395-jljP2Do)?&|SUCr&++NsQ2)wCXqFIhx+ zx72*VyB&)sda0G*z3%45TFje`)miIQasP3M)iO@43KZFmb$>)-q_hjmM!iqy^1^gNgpu^uDc;fQz`t z*f^(SjmJMZ6IJpJCb>b*&kj!>ZIXv{GHfON%DKkHbMp9rIA>H~>oP() zc_*P*#41hfD#Y>vTO%eW&yq*;USEb;P7YoOO}~bfk~5MZ<8Mb|-yvXH^ zl;hY+RFa}sNsePFI`W%}9DDHmCyYKumw3X#bG%1Lk}{g;h%%n)WNa20Po+YUUpjft zsRu9d3?V@sYbE~~R1)%=8k@us%Rf84j%Odd#3>?ivW`;@p5y%V9OoZA$EjtdT+phtlO2 z21)r3C4aj7p)~nJY4RTex7>93a}O?mZo2%!ASwT$=is*%DlLbjR_ujUerkQnS*Y?R5F2FL+37`~6=>j-1vNMf6!NAxG^ zjdaeHktiC*xH2X&lW?6z_y*Qx1mUtO?42i!H0C!(#l;D3-EU@{Mw$PETZe2^>S!hz zSJ5WgtebcC8&%(aqtxc`=AFCJ`@~&R=7>&5G<~v;9y~|vDF~Pvw_^v-kr1hpj!`1b zF-jaf|5l%7x29`$t8hry>;u#+?0c6{{(a2h6urwR`eRnnBem%x{kBalpGR!TgNE%R z8A|SwlAZB>ejR2-^zl-NaDg4-xFzFTiCwx zU(A%O*WjH}uU`u2jcC5Fi!owcYcZw2ZpF8q>2(o*xHPVL{(KusN;c0Mwqn*R{0n)b zJ?t>^SF&dFn8w@3=y1+3In#W9BeP8D-KKVbx9qxXG#mLgQ?Ua~m+PI6TK~cvSY)SP zIoG&2whm-|9p|ild`@QV=c5CdN)_Z#37$6+*AtRln@O5;g5f%%RoozgUWe&3kpe%zSmejEa~<>|xt@`KC2 zT;w0mR^XK*9Fj^t6b9)PSe{mad!f%eWvwPB2?kRJA8tUFTuC@I3j$8=HQz0Lff=6Je>I z$6P0rdY(j>k&#s1Lc=>DLqL+FMW0EQ_&wa^N!h=`U4ANmp2>EP zW_emv%k&m0#ct&JOKi!Qm~Vu9KXsGT&uCN5cI3#5lo-W+(eU$g{ai+_R-Uiw#3c6- zwSQ<--tlKxK?)(aH!AN02E0y~n7qxKcszRmuM_zvncz)4esx-QZ$b&molvid@+MAL z3eeKQeV=#|Hw3(s=q%=W$9GssCwvh%$3LCMZ}fx#o%Mu?C&@e_SqoDvefWfrrk9_T zH*aE6iu{QuNu5r5MWjgLR^fBRlqXz_KosK@CMl9R|0+38&dHgI;@(q$I*E3Ump%mO zc_3H%Hh+leBlTdGk53=SH?N1LW$Qq;j8E~quv}4x&pvC*m2*l`z_EC}&J{@Z zGaxhymLsKQC_gO&3EJ?VjHJ$Cy$WfP6`{bN1wVIQgz-l3Q-^WAbeUam-r)$Mfp3jLqe7@_Q<}^us ziHndApL-_NNni#lojRnpOL(|5z%Sz6L~t-Cp1r-;P%`HwPr}nY;4Er`w+;fC6Q;+a zZmAa4$HUse$R4O31zp%Pi+=$M5iI*vDa}yoiAW?fZxISho~)b>8RU>?C6etS?xm`o zb)g+8hOB4;e3C~jp8+3xRMa~bX3K^)mZLdzqD50DiZ4V=A8Gz}`}5Vt0T0adnmu|73Q*9l1@y;#D{6(Jens6dlpld6o^J-2yT zZpJq=Sl!es7Arh%@JKP)j(e)(3x*UYyZ>s+b?Ooo((eExys^Y(3d>*N(F-Fc?@rMN zG7-Ed({E|)n=5H=v`Bm74;&G>a_+d=%W2NfIqAqzdF&o^T~4-X{NH%JvZM1q9GG`h zZe&Z4X(cvoHba+&Tc#}`hO3o-d}$5Da1HX0FYP15aQ&2jd}&?8a4qE@U)oE=aLF!- zFKxG^VB}-yOZ%ry8?EaHjCF9|6Oc_PU%nZn$0b`5zBCR5+0xe9v?oa5%hzhtuFR13 zuuVJNmlj66-=@8SQ76f>a?7ZXp(ztJf^e4Zi%Wr(4fW&X9Jp85O+iGNhH* zwA(YJEwO1|$&l7y(~2^reZ;2u>q$AgY+6}{d@qf_bN2{5|2YEBLX57wGRZl^re(5? zN}DGByswSdj=-~Z1fCC%z_Wh@oh^@A?u9GKW2o1&9G_H;T2}ePa1wVpVvR( z=47Ig`dga0By@7%HjLjkoAyPHT`o<@NZo(U(xiGyy($pg2{yMKhdVWbyQ zf4HvHcCN~&{1;l9_mj}ch+C#DvuT;e)kd3kL56(oHtm}k(jK#EPiIIQuxV#!NPEqu zU78_H_OO6w8s|>VV+Oc{{Nt-%iB0qOW!8O(P0Pfy!KP)h`H$E%nx((It`T^?WYaQ@ z3%hNa-^M1w?+=J|=j8n3=%c(GTqqU4oWp->-fP4gGxi%EM zTz*X6uS3UGhK|V%OfCqWo*P&;Av7TuNd>uELK7|zjn8ezZQkXf(3X%FTpyT`Gv=|t z%z`m_Yl7ngAIKRKtX~*9F<5YSD3lxcd`>~g%gy`rnBXmWYeL5bj{_U`$Kdra`=g`x4m6Ymb4m^%;(2hJ-9g&tz2W5)znEesU|Ckm(K!l-UcaK*yVgy3n< zL5u-1Ig3o57!$mKg`SB*PR`A1421&ENXdaS!R1==KW8E2xe$DB922~nY^N>^1uqYI z6=Q-|FgiUMT}blTcZVkC1{N2DP70g_f$|2Bvu{jr0n^@VL=ENrh+^J8CODVqB@~ln zdG8w&?AweSV}jrG^4ExFB@o z-J#QvFg`bM(S*>^P;dykKJsgZ;uK54tSO58+~0|U7cVXx_7I9Q=VBs;Llh8=H zfyaW7I&cv<=LXK75IQdRq0pp2aY1Ox!q5c|g)V#}R2I0fAarKnw1Ut)0uTrdF{ z&cU(Yysshg)tsY4c~jB8k8Qqi%)-Ep6UJN?I1hhv@6HV@IcCfkU?=ZA1_xv>K)bI- z*fsz_$8(;K zm2wtrXCjI^C-5@lpZr=VKlkR)=-k)XtI7&Pqp9Fy^G*v*%SE~8qvK8hF{<>L0J>c8 zLz@HV<%Et5zU@IRQ1Y_S86cbX5Q>3fg1K8kbJylTEhG)zl@s_HB|ETbA#&WEvk>+O zR%=k3pNt9qL(mTc4FUCX7mW$NDNtKZvP+@g|BqlF%|XLVfHj{6U4>Aphamuc{7*8(Si3u!MTAcu$H`ILM6F@7hxqAFAQB0_uif7LYN4mRS^fknrl1<+=N)O{XneF7WrX4iD#H_&obP{hf3zX?sCg+hBfY)z=HvYp@Gr4jTn){ zBDQY|EX@g>5&V^~+Agd{WvVoVGt1bR{1QB*Z1 zo>dbt(ZJooh=-ZzL}7yF{c-4+$5Hf!p;OyKr$7S}&|u*GTIdw0;q=!qq-^C7gMpt) z$2=x|_-wJche9Wz{o#*n4V`!$Js-6Hv_K7-GVn{3d_HV(eBerqZ@F|4&PB_e{ak2D z;Bt`%EjK=Q8SEJ~8~xSLsHqs3zZyC+@LJBX&?Ksl31vDp{KiH!o}I4fq2TswGJk!9 ze}h{CW}5iZM*36t1)xc^^T(u}(Wx>{u3qr>8)4>Xnm{|pO6c=ADE$PwOeppYdWV=} zehZdkf}aS$Mr1xe;YXpfIMK<}+`kE)N$`=)3xhxN(6Vw1KPUKeFYrEE z(90`G#o_q^XiNc6AzhTu3jKe3P#WEzWIS*V>BA|&(tk$i>92ST#{^vrrVC%j#Yl?C z8%}!{V?Dq}zX6Yrn}@9s=-OwwK8m&V5#FB<_>(_X#KnbOcq0+Z54mm^+-^_+ku@R0 zD=odFljQ{Pvn)=zcyW2k>jaBq`&cfw@c74Brd-*pLW-mRgT?VMMlOfv;_*q2I%3>l z3w|cg;4WV51QMREG|S8eK~-O!5*&WaN|J-}1xih6?t@Amof)T6HGgVS~L?+9sAgWsqF^9)r7ey{x5y9|ciJUzKb4xb`W7 zo{5)^GPvvq`1?*V^bHo5bvW=J zS-jX9g6zQq|Lhr--txZ_7_X_8zQxC95>6>lo_;I8>`Q~b!Qw-fkLL26oenO^aA3KJexqc9{WrzH*A|&_N;;b0UNQzhinr&{nK=aSK5x` z^nV8wLcH6Dzk((w-YJ_Cc25NSKX$6YTWq1ZY1H7{a}Qn zk2iSt6oEb2yTt7imVc$KsO(7szscHvmF4fAb5+}Z*KcvzLk0b7FbtO4ZgFQPui+UQ z@nYB`FWFZ`_-AL&H3H*hVRL=i;+-o^T=oxfd!6k^?Y3UBZw7qG;+&cn$V%TdY{C!#QOVKWw=pV~Me@_5+5*R$QoZSQ-(5&B$wzrkFH%5^2mJvES<XToU)nee$; z@Zv1xmS@5DX2G#9ow3}dS>)WAWjx%JML#RE=;42|)a%+T_-$GG?}{w)ABTP<{($XY zv%#0wPRK)ix1DDl{uNA=rv-r9rNMkd?ri}b@doQ?uswMF6#a;J*y4`99Ck&#{U$@_ z=!Y!*AjWTAj-Dr53=y#*`iGP-=2m4_p;F6mId$3B2QBm z{&!}fzbDK1P>OkcJoYPgS^I&X&nAL*f;Urmd@c5#coG&b44zPw_uzk zeYcPPDa)tdhu>lG{XTpV{1EclMv0f(L;KO%>4PNTQw`05|eWee73G*iL79W1GEq9v_pK8mk z_2CzW4WAMp90E= zahQvjP&nUn;6?n4_&NGB6`v}FzgOW}9%sjXd8!q?ma{1f{&9;_p7*PAo&SjG--Br+ z<@`z(dbsRzQ68;_6BYgs#peozqw6R6e_Y|ZzTdSt1OA-e{+GhxdL;2bTb%Mds_^k7 z!bM#3KT+XYZ+9tN)8C&3cV~kA?ea%Oulbu7PmMepKZ6W#`QxiG0^;fp>QqF=#Y>PqsIXa zx%_<2Qn=>BbviH7YkW=?e6zx}ocCwJdljzR>v@a&+iQoyb$k7{;BU$jB3fFwzusG#m*{)ugdgUT^wZc!Z zxL+!r+;kv!t8D#R;{p&8pU+e7=g==}v zz?yemyKy^qS9A7WeD9 zzx%e5U;Yya;36L_PuSvq`4?oNuTr>{pU**fk-wJzUd5j#>E!&3qSx{~q42*c`sWqi zrSKh!KbzX||B1yJXuEnt@zLe}P4QtJ9G_F*C-d^_ZH~gV9;y|t^-ybZ>X}XF_y$jR$0CBu-;UQQT-*Om3fKL*#^Qc?)++pq zD97m`s`#u>_`)M8jgd$9>miF%pP$9g@j3D+QXBd;2p#@_!nOQgSGbn{n-=%W|6PS^ z`G2PP=yBRIERS?~pP7IFFMug-$=IdUfYwOR0{EchoaPCd8a=k)mn zMX&Ytq{XSXxT5b>ctYXND_raIKNWuuzOgI!Cl>e1^OmANQ}Lf*7cbP?KNWtJ!nOWy z%7WjL1%FZD+ODp`ek?DRtMN}LT$lS;7CclSY=-fflLfy*;hO)oS@0f(YdQC3!QWQ6 z=06Ji94dnb?^XwuD;h;+^?To6us6D z_mOy!kJitN3fKDizQVPB_+C0M%BlP5|5CW_r{)7lrrev6$H~75`)0f-|91Qw{&9;_ z&eaM(70*q05!ZHjox-)f)nviD-+&rKGmeh%R0_}^)9f4QGl^c{-+8HH;*|AxZL75y35@8w1QAH&a; zJ4N9SDf|M3e?s946#glNFS0o6`&ET6QFyPyZ&0|_+e(GstLW<#{0GEAfC(c^6O`;#aXYn@pE=qU~xbH z_bU8@ihiNOwLM>Dah4lX^fxM8+ruh_Yx{Yh!nM7B)(UVi-t@H~PS%hmkPRrsAqbM1A3!u9x2 zW^up%D-^EvzgXc~|JN&A>%UszUsv+fDqPpMUg28*pR%}L|DUrs^`PrJ9?u1MkzV(& zSqi@fX-+?t7AK!iEBsoEQ$Otrze(XwD!fMFTNS=m;oOsV$_Fqy4>wq@ZK!= zjx6{qS@2&gT+6dR3x4hys0^+n@Y8b6$bvU!!Jn`=b-4*Yr_XO#+&_=JtZ+SE{ZQe0 zeEYe=^*H$}h3j$bcM8|z(w`Ns$HV;!*W>L0h3j#f=N5SR$NyOtr#|1p&*|YJi~IHS zh@#i+^(Td2tN8FdIWK>Ey(bG^r*O@uTj9FgA1YkWgMYF(<^ME(u3q~r?$^Ux3fJ@C z5k-{V=uPW$tipBs7ARb|3*S?7e6*c}6|U{-EQRZKpQ3PWKYT9l`0IJ_LWS#jaGt`o zy;YxW_^`e7Jb0_Zb-#O6;WfzP^jvvPijQuu_hrF1D_oDyPbggTc~0S4o;MY)$LF^# z&UV-HVCY;UCviPKpJ#FEVI_X9UL^|G<=&`pJrCZma83VU7W|Pc_!C+1=d$3xQ@GY! z=sZ(j)=T3jDqQRTGKFjUr3%;ex=-O+|Nmiezy3QF{zawde#J-Y|GNs;<^I9q?C<=! z_Hr-K5!3Ty!DIlqsE0@KbM!?D*Y&+n;kw*N7JO9}{QX(*JF?*I3fJjTby>K*EL^M zxE{}+Qn(%upH;XX5Bn9a$N!xQ*W>@o3cnXJIlKCy!u9z7bA^9N(f>-}di?*L!u9z7 zXNBwW|Ey_Xii>uB6@E^h=?d5Ouu|c=UH&5r{)oagpC_~6N1jh^AsP%uM z!gc$es&HN3B8BVrt+zP!a6Nub4|ghhU2cb>zd_M|TH(6B-%+^M+rBLL*y&)3i}L94 z_5y`#J_{7C%iW@IJ>Iri+&|uKRk$8+pHzHSLMEr5K85RYb7xR`BfpmOM1^bm4=G%? zd#A&zBXh z%N+&q)`flDMcJEzemB*Yx*VoVxiKeojA+DEjLZ z{%eJIDEy0;AcBkKYW!yk*X90J;abkorQ|YP{(@40ht+Fh7W}>}_&+Sp`ZnX|>N}{t=2+Y>&ohetT2*e|TtskDPOZK5+_tW?}J?ynO_0z8KA%*LC?M;R2dF^e5>v=6S4@_~9zn<5Q zRJfkkCMaCbYbPpP&ugbDT+eGo3fJ@6RE6t#ZI;6IytZh*h%fD>=e6q;uG{4+77rks z*7GZhUe9+Im8baYcC62We@NkaJnvSxmgl7`_^Vm)p)B~{vf$$uWR`!P!nHhW6t3$V zRk)__RJf-9FNJIRqc6=Y&kTiY`fC-g`QNEcevMl(j zEO@=bHUGyHuIKA7TiiciKc{d#?)_NtS&6E+apPAC*X15@nW-=BpFc-`yuyPDKilF* z0DDy7a}}=jbDP3-xp!y5w<=uo>C1xuI1BzOh3j&|3n4Tv%CGf&mc>T{*YnF1g=;-u zq4;P$U$1ao?guUI*YigeuJzoh_-H*pt8lHK1(&l{!{_mSGb;ks}=rrMPIA% zK84pST+g$&DLkR*o32Cz7xjM&eohZ}DO|V9XDm*AKBVZsuIOtNUR;R?F7nsya$y$y z7KQIa9w*OJ7WcQ~e=7QAiavZ5BDh$twv$SQ>w2|i!9SS=e^lYRUfl}U{J)k3FTPsD z6gf5hpB1k8pS3tM{Y47@0!WCg)djQ?$^51N6%EB_7JP#;(Hig5#q;Sn=Q1ST> zMgJ>Bzg*#ave3V+=x(@ zzohU}6@H(>ixmEp!lx>{Tj8@5{$+*Vdjlf4*uL+>&&mHug=_uqvN-ks8Abn^!aEf{ zr0|Co{-(vLw;qMRt#I8gCvmXAMLF5Uot)(g*K%H^aBXkPv)~_5_+J$Nr!CIqYDsiN28?HdZ$^1q!0Kazt8F7np&g<0@#XTg7z1%EXQK9mLjXBPYz zPOi8pr`G>_6t3kzI}3h(7X0EY_@!C!`YiY-Ezb764L{djUr_XVK6=vPwA&9U`ezmW z+Y0ZuxS#)<3g4{gkK&|-i}ZSYJI3NHw+%lh=V=PpXTj9FjU950D zo|G$Gk3SU(*W=-0h3j$ndWGxpwp!tOJg-%_9uIF*xE^mmq;NfMS5-lYxM-hm;pg;u za}^@EsQ=CQIsBn2L~s$`h@ZostU?4A@z3Dr@aL)!!A1N*{2cy56(YFUjxqck{@p4> za1qz-_=75<2G{NQ(<*_5{u$glKEG7>R}{WS;abmsQn=RVK80(2o>L8`xcqvXW^vY6 z>*ofAe*kGt&b1b2eeY5D?F!d=*raf+hp57}y?sRCx?cAyT-WOp3fFe>b&LD!`%R0p zzPet2RQO%0UO6if!A1Jd;OF!(M&a5{##@~F`G}%FS>akgrz>3R=NyG=JDH|%Z6_rP z*LHG=!nHmZC|v9F4vYKsc9+EisFT*u%Zgsl7r#*Sdj9>L!at$(vrpllQutdIr#_!k z_z~O;!bM!mKUU#-f1^O*TF)maT(?VD;a^7?uHDa4c%QRydW?a;> z-ru-D;d-9E(&7QoKZKu?r$*81{f%EKT(`?fB*JwBewzPTS@4-z@T(QB`Ts=Wn*UfX z#&EG*O>k0D*SncYd+u2g1>HY%6SxicjCt@ z|7H_X_Fzs*{x z&TF@#*YdxqaP3D0YfV1ZOZV#ni~IZI>586mx^l0uxL?k=!nK_|p9TLfh3j_w?=1Mt zIwL>J)%WY5#^7H z6hSBtxLb9Xt;jCfWmgNUY;pP5UB&LgE?wYxtoVrh)7|sUdEc9J-`v}#!Rgb?%x}K) ze&3vP=FH5QGk3r(&ff?2E34>V7I4dB`u$>{6PDxk;2O^@fqm$ATNV8&&X-NDs>R>x znI5nCZ@ZGe56ot@ST_6jxc_@`TrCawd)@M>Sid0Prc-MP-P9fb^?prf2kI+u91k^& zg>gPaBRB8FvdMlc;N1Z~J>aNTv3^s)bAf$*z()c;E8v?0o(TAsfS(cYtpPtR;MTU- zWbrq~Oa9L`EE}JTWt(lsvhmqiw%HCW8=r?|o9)E1@i|zw*(jEc|0$MjwhPO~8?bD% z-B>nWhh>{RgJt7?f@PcS#j^1~#jQp5z*_=-e83k3{N#Y=0=_8V{M}O9 z9M=EQ!2Yhles{o^2K2ONh>5=r;+!6nv3z=FfRm^e+^CB#w(7(dmJH zzwpn1uNTg8yiz#hxgOkR)?V>@fVT*b5YHW=a~1sFE&NV!{;smETDwHQ4~u>d`u`&Q zW$-6O|6b_t5&kGR&$H_HH=@5E`o9z2j`rl;XwRtg1oYn{{I}rzU1-`j;CSJAlbrd` z6r4xm^9B5#E&M{XOH0J>VV1~E=Lr8G_(j575D(9T8qcu!<##5p5WW`id_nZ*!0*+< z&jtUgaOT6^qR;P4{*~}Qhu`mu&PCAwJK@9N{GDyx-#wzw?^6D!@N41sCDFee`o9$Z zRq)>n=l;Iua9?g#?aY+l+dM}2N8au2J^;@6?}Yxz!XE->yG48YJzMk_K!36D>%jRP zLhAew`bqKo0{9x?^gAT_{I2N+;opN_{ysVV{u=t96a87Z@cFWE`n_HBN1=a@@az7_ z=kxbOrvdtZEBqqx9}4I1uRSTe9mn1C!Wrj&aMp+aL!7S(XPif%-D3Wzx zwb0)rd?WakqJJ0kw+N@-n}pNvoua=P`u7R{E%^PS^9*j99}qqR<@ktj`h80D-N#Gf ziN7b$a=agWpXhuZetBMHem)BRrr0k{C1aO#`^zh?-~ zfuAY-T*R|X`1#{H*Ys5zju+IU9ao7XB&lH-)pj zrsDj`_*q`Z3um0Cf-}x-i02I94}B2Y%1_8^V_&p6#MD9e(c<{t56O2xoacBAn&*v~b4x zJUHXz_px6VehK1yRdgOhC&U}V--|e>;(W;RrQhSg>6hQBo+*42{LU7gE8+JH;r!j+ zGljFfmI-G(tH2r0X865S_;zr9XMy`Q5Ah6&eh&OH;ViGKgtNSE63#g91ZSN5Zuxz} z{|<59FFN~haq)og44M*4+_5x@vIk} z2XURVNjUpMt`bhaUlDzNZ~Ru_Pr|Q#Ptzvm!%yM&Ug7k+Q*`)!)KTHbqh38KIxBEp z@wnLYJLh|ZH{yK#oapRBoG%DxoWB(w;d~P{naytUyJ>+@3`5-{6ESbGP`NH*z3@y6rIh`d57(&o48;6uJ4h;-;WOa_k%Nkz6qTZ#h%~kJw^CV z=*$tF??b0i>_=gLmhhYY#K+wsIxj%yW5Q3sL-LD+UypLh2xqwu2i%&ZZtu3{ih$cK z8Gko?OTf*(9`@G<-0azpdK)^Gk;zb{msySMfkPgZ;4J0`f;a~i^DcsJYNL=BlOdd)9(y$=G#{2pDO%& z;B}(275ejpe+RrxIQ_EUk$y*^ze@a`Hp}gVo4Q5k0qFM%e;T|X{41!RpBBz|t_5d2 z_3(S6@H^^!JljNPFZ{CqkNIrhxwPr8#h%Y=9v04c{x#rM|3^*4O-~2h%9qE>{|LVc z`}?bao6c4fanlBT3Ct-hQ3SSOhC!FPSws7Xd zvVh0!h6U!P^8y~`LrVB<$cMGUe*%8FaOT6+!n3gds_@srzZGzcbAKFVP0e2h+~WK- z>>miY+1Fyf9u9a|E{}t=T=p;U4)zE?r_J-{L??;-e^Kl^VgHKo&#v@3Z;1}ShZGMk zbS5nK+o3-V=M8d}?@7X0zNZJ=@`2+C8Uh}c??T}$$Mb}+WbFD>?b zo#?PWToG`Klg~XrA8?Cv3LeydDd1*54bL0C7I3pa8us^qGtRBZ|L+LD=2Dl)O+OHw z?a2R!g#Q@)Uxl;%c~&^f>k@evO@Dqif2!5JymSd~% z(_y~|oN>O;<@1NAGV7Q+j;xWvQ6Btt=O+o;Xeg`RCJz3eRy2#_riXU@T`xVb;~H;YCpuq&PLtSg zgZUal7V{jk45c)HKWf2-*H z263`oXFeZ;`+9!Qj-2uHyLBwb9Q1!Aes2YTT>O3j`cDeybD!sh)9=tNp#*}CkHpR3U3ErDx7}L7yWI}zeM;8 z;QgYr6a8uYejoGUb?{AM&;GhC!Wj>b8|K4)_`Ox)nV#|cd$;KH!SB7o?*@NB__?@_ z+9jO*bx#RroX>$X&RWF7N8 zC7k7WlW@j)CphCAMLhgoB>7|DeD2C};q$%+M86wxJ|dicpAx^jq5rJ#{{rXpRr>uY z>|PfAqv7{W;ViGI*iIeBa~wGLcR&2j6h8eEzW&S>oy+0x4B-!gpDCQ>wM;n6i{I1K zID28wIBOBlpzvPs^`d_X;<-ZXbFlxM@b7|OCpxUJHwx!?iCcxUpY~4S>_5C$IQs*? zE1dm%-xtpQx>4cmkNS~t-p4&AoY!?v3g>m&&xG^3>p9`Pj(Slz+xK4y=eW?CR!Y_gSmxO1) zZxR0A(78kSEZBcrcpEscN4UT50Dn;Ij{<*K_$%=Hm~f6i_^I$Sp|eLg%j4!dYH#31@j7iR(M=?@iEopYX4PA1j=3o+A94u%9LT+u(J=IljGBICT~X|0Q%5 z3I8?tIl`&GN;q{c5xy7CiPOSg1RoH73V2@l4)FED9|FHZcmp_}53^iu2ftD5Tfx67 zd@=a#!kG{E38&8YgueluzZK3G1pi(*^&b&Vo!!D&pPvxEaf)v@{zEwHGshP&e^{Si z6?^KxA^aKWABN|y)S>?Sgj4@y;h)Fx&T$RYA)h1m9M_eo!dry@1o~%H;Y)7L#JjCoOe6DaF z*B=%BBlztQ{yXrGRpA_8#`y0?|9(O2@524{<--3B{0jlcC0^Wc{6)a+x{l)~ZV|HG*sbPIoRrUwJUX`d7RZ_pVL&gc7Eg+DaQgPVo_ ze-52zg!6gpe&G+!^WZh%>zV@K7Fk};E$}>i zZ`!KJ3*fb8=qB2Kv)QkQ??IdWi+DM;UhH2658s0}`@~sZXMxzC4Zc+Pqj<5hTljNz zUS~i!;^W*Vd>8n3;n(2h;2pxR1>Y&0 z<+WS*wH@B?Gr})g?)hHf7lZE;emnSn;ok;-P56uzUZ2nRY_sL_tKie|+>iXQ^Sphn z@Wa9RJ{s+B0IwJOPp|YkEyDTSwo`eVx95AA)aP?gzGq4PyT#s~@1v13KXanb{2UR^ z{0!gAw)|m!ZV~%Ck#Adt-vxfNaOUSW;mptN!kM2tgx`jI-YJ~-dE8zA19BceMd96ukLL^8^S!nE z#Gdapv7M(q-y3~i?D<}2ja4W&(Y_Pc&ohMcJ;xT|d=IfpINuY@3Fmu!*9hl(c5Igz z58s3PC$Z;yYHT-3_IS?pP6NSy@qMdW;p~4qOZet#KK%v4`94umIN$5x@nV~;KJY!7 z`^298-n)eJeUs;fZ{x+?;XW?v^Zkn%!rAZEBAo9XbP4Z9WzPxU41SGpj)&had=&Qo zBz!OUUf~?4{g!Z!qn?iUt+>A&|J*2?g>#%L z-y@?w$DO_t#}hfnk@9yM$T==_k=S$mB;U`XJ;y_C7JH6Y{JLeh1^e5`IWA&Ub-KOZy}~(e;Vt1DhcE;8 z$JFPz0=7fs`y;P^vDou@`iO8o@BXrI{%#ff!>G^Sq584dm(Ekd`F#1EQ+!<1;d9|1; zNYpRN^b|8g*>rxRLmkOryEnV6s0^-$Sp3@j=9~jSH=&t~XjU+@DIXS(A^}*VN^s!E{|Q8Y$KkHe~vWsr2CB zP|wHLe8PoQQ@5s2fQ3(#8(vd%ffk(f>dvbBU6?m-VWu~e_j{Hej5EV_@L=f@^E-y} z8`Ak+Ns-JHs%;u}`C83geu*pZvf>&^9Z;w>_G<+bCvA>bGui%9ky!eM(%RTAS%596 zWTrnGx!8+Qf0Q5FIGkUSOuLi^D}Ln8xDqQQ8q4d6H>7Okt>deM%Zg;QZaB*JL_usW z`&3}Vh_Ai}&evuf24kUF=2UVK=Vg6cKA+y09L)4Y)$QVJQVm~2OZ6|CUW&r9l2uu&Q4`tmkTFkhTteUH1g^m3D!)C=e`3l)k!6wcE<;i5Bb@964 zbkVA&kJh1?c#M*~n*{X_$F=YkVB?Sy?FNt%0y6v30CT zEY)ppa|K!)2ge^6aa&VpEj5C1^5nWQ|CwyxkmIXYEgY(uJ2131n%gsw&lHN8baw8d zsPM_+P;PF#A9K=!{X_XoabWG7p26WYbGzKG%&lAF3c7c09DGdbhUONAhVwm9VXp0~ z&w@Jh5bxCZ`iTZE9~IM?EF*JyYI!89b@`z>*9@i|&khx%x+UkHKc`Sk_k7Z+ca)z* z`kQ)&hO@Rb<1d~Z$9)T~OzAo1~Tj2%eQ@&*^)wx5x zQ6iBYUfVw4YFs|bYT~K}D`Fq6`o-nnblz|@9F=O_V3aOItY`5l*d3_^(Lky%?^-si zz1bi}Tkn(gw5-eOa#^RGMIFjtoqu^?X8AyfHsCRBTVC8X*yu!K4Jr zW0+7SJx~mj5-5*hLe=y@F-%S%DopB}l}ybq4EObA>{@rjNFtFOUc)N`)Yjf8z6@+1 zOcx5vvaaQG7Y$Z-;tS}pGdWOGd|G!aVafIe>sIi+kS+`kZCK>x1JY(!o#h9It-F(y zJLkFi#iy7DmwTU3jj8JW&{LOt zpIFYX&lKGC*kp4)OkM7MVtE&)56k_~Q%!XIvBPnlaH%w#K=#5!-FK^~n zQ(}YQVx+m(?f{2lIc}fyNu=5JA6Q2SVjF+K9s6J5YHNLJQKn#bD!p+BNPJsuv8_mt zyF;(qsSw*QKQ#NUWPg(@yOhh%WV*etn3$KgyHMOD#&_i|pWMB<<&(1*UfG+{o7j;} zs~xP+E0gbA=Qfm*`vRMsM9N1{r6k6DZ?fGVfAckx+Az|RLT}Ng)g!L6sML3qPo~N$ zk?TboUoG0>`cm(=_(B=)WqgmqSdmQFIxg_>HRXWX<2o8DTibov_&9>YA;=_)+$u+> zHEvxUg?Y`s-z!~=&d+AD8Fx=QnAsHd#+N#--CelBwY;vLEX*+_s?{N;ba|Ux7hGT? z2gkEGpMtK+WO96}^83*77O_U9d;9UG@o_aVQ>Pjs^Rj9J5V{xH#Tt5@;oL8f} zsl~Ms@r9;ojkVx*K55AmI`dI{!J6!9%(`=kWh3q=QcZpC_Ss!zSUR5P4=q)>x5mCq zw%4`k6ZbT+6y;v#`(EeRkM#j0lde6re&`B&axhy_cBdrQ`4uR)cv4aNV8+#&gSaW0 z$f3!qQR(PBG!d)N{$AtI(pl}EL^|o{DQiaEu~+GEvCes`h2@8)Z(dWCHx`1Y3?r^u zS5yceMU)#=iXv$9;>QJX3B;|z`1a9qGU%JNX3g!uinu|Tuyr-U!i%##Xd@@5P#(pEZWIm}#pD#qqnOYQ!vUk1oI-gN6Uxt)9`u;S zwQ8(a*(PLIHV~5FpA|-CKB!jCFla3NSRJJ zO?VB_9A*7Y$w*gx6erX3)45#a&cPmZCHoo+sY0sP{fn>G+@rQWcN;ahIG-QNuZRkT zbiccMbq(3PWHDXL^dyUU_t4JWv!#;5saUgo&suYCd(ld_&)wWLx{ldCclF?%2TjNU z%tWsc6+7d$s1J?Nc&*ANV>))h(uxPsgM;pRyiB66Bok_$4id>^HOeEIP!n{JNG7Wh-&U1Mkh$$kx%}d$RL0}**xuM7G@;UIvFrBb z?ykjE#D@I1+Bz1mHE`}u zqM9K?o}iiSnR7ccyFl`pL42jM)1`l z6)}WW(Yk4El<$xFocHnoERAj}k3Lb)%cC~C)h8H8eP+S7AQ5SQqRBm|i}F40p*60jN?Kj>5-A&v;fCG#P3TZv zm}^7XncD!``t@f4nXR>Smwxiys~%@e=)8 z8k@ddCH;qyzTTUa{xTisjc&nW(mc!|{mrG6eu425U+DreE!($nVtT%h#BGe9>-N0{ zORxS1)_RN0G{ju}pXAb4%Kz=N{T^;bI?I1c%k<3uW2^Yz2mjk-$Cw_nHPfp2Z~0U2 zKZkMR=HK2SWqSJmxeLBh{%y&55AUTT%$c5es?)dh^#quI8R?tx`+?l-qw;Bt-Q$iQ zGTPYuU%u$q@S0(1liJ$v$yUt&I&ayHl(zr&YAfUC{!evgs%c5yakc$*^;?TyD|y>s|Uv@lToSEjJ?rEdHb1e~sV1d!w4>YvmpG*G*Ef)%I1F zzLNhfecqDe`pv(+Dx&`X-s!8Rxm|ge{jI5KJBa`9yX}?yFJ0?ZSx)BP-hWpAA8}@t z{NHeod9SH?T{g;UO{)Wy{C8LIZ$Ejj{+n_9#?FF2*W4Sd1dHn5zDM9#P7d>$tw{eG z9YRA^Yi@R+Qv4%`zZ35%SpM0e$n?zDYaGy+%+;2^w!bwsAC(3`ZNE^(|1O;W=*Rre eaR1f+gYNj%eK)_mM(uA+%?Jd{uN_L7{{I2Vb^Esf diff --git a/Trie/.build/debug/Trie.swiftdoc b/Trie/.build/debug/Trie.swiftdoc deleted file mode 100644 index 12942dedfe6852aa61b902224cde186d2adaaf6c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 540 zcmaDfX9YVW2LppD0|Ns)qlJ#c+7Dby0=U-%aP4>CT5rI$Ux91Q2d>2%xY!*xUFbQa zy@N^j#3Ahshx9v`wD%m+SaZl(Xp58P1t*OOP8vYc#=uE?50mBxdSs$%*Q9pSHW1%LeHSMEDy*( z2E-K>X7Oewx}|y9dHLmex;dG7r4_pAd8I%phE||K?m*gzO@POXg+Yf2BnSi!U~-gz Gg#ZA|lTWSy diff --git a/Trie/.build/debug/Trie.swiftmodule b/Trie/.build/debug/Trie.swiftmodule deleted file mode 100644 index 078d7a6e1f4157ce427046619f65d62ae669b16e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20828 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 G-v0&EBr~P} diff --git a/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/build.db b/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/build.db deleted file mode 100644 index 1c00411e4402e025363b0e2c481337daff6a3f53..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7168 zcmeHM%WvaE7@vn@Cqb}6VmB)EFb7sNQWGOsgg{H!KD;H}lF}rlo0H`x)6_JvgCAwl zBCT8`;J^h54u}i?0*4hyh{pkm8#lB^Zh%05fD00PV8+fQ?pCF4f-14isFuf*@A>;4 zV^3>qE2c-umhE&6k30?}03oJ-U|>Nbn1QUq?To zhuLH@{woBUl9DT&hXFLL7QN>99jZIj^*f%co2`A%sfDUGSJ%jTrM$MTk#c2GyGrh4 zAgh&qYh-4JzM2mfu#!_%xc7u-Y<6hK)S^AgR9a1wx(61dzOMS*{E8L{jMI~uki%>- zE9%;kR-GkG4XM?u<;v15d7)Z(8yO*GYACqr4cLLrU&E!^$3d(Z?zd13qYbpNcS{!s57*`>o$K zIzA=yE35OfWYaf0p3drO;AhkB_I!`FVvG6fP|2M=3xh^z7q^~YXrCQ?<#7GG)NxJQ zimB#Wor!;6vTd2K@c7hr#rF+pI0z$rmM1}Om387am5h4^powG!P<2>=r} zCkUK+1Y|kOFt`W&3b2W9;z!UQ=ri;d!te%MhSO~ME*k|5^=##0&uH!#ZK_*Fm+ITp zp}JwU^c_lj`pdrUQN3$8J8p?nXBLuDU%;@NPAa?LzG7~9%~F6QxTmBm>bBjbYIEB$ zUC%Tub&LU<5}`Ns6^Vk2A@mFr|*mG$+9zC0)Ir)k74LHuVbq*XuiD z7ZU6~ruwd?yBhMgeKO8W~2ZXp6&Akv2(TwNf(Za^n-edJK}ZuRtVs zVtrDiPw*Y}VkGp*eFY!B{ndj{-bktqfa_QRL5evjfZ6g2$KFrF4_BtM_VH7*?|t{t z14-2f5@OnOqveJupkb8xA$j~DTuMiVd^0^APJTNVJvV-t+2FHJ-$;jN>a3eEGp5Ef zBUZU@!$c_(iWXC)2-+qzLzWn)<`}jRPn@0tJFQHq=Vw1_3AaEE0&t_$ChNW!1 zpXA`jAHI$!|6zQC^>#)EI?wrpovkEVsQ6$TNIGKDPDhH8wzQJ?N7tjr^eA{nVOvdR Uv^pMdtBF] - package_name_here_and_keep_quote_marks: [] - -commands: - : - tool: swift-compiler - executable: "/home/christian/swiftv2/usr/bin/swiftc" - inputs: ["/home/christian/Desktop/swift-algorithm-club/Trie/sources/trie.swift","/home/christian/Desktop/swift-algorithm-club/Trie/sources/Queue.swift"] - outputs: ["","/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/package_name_here_and_keep_quote_marks.swiftmodule","/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/sources/trie.swift.o","/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/sources/Queue.swift.o"] - module-name: "package_name_here_and_keep_quote_marks" - module-output-path: "/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/package_name_here_and_keep_quote_marks.swiftmodule" - is-library: true - sources: ["/home/christian/Desktop/swift-algorithm-club/Trie/sources/trie.swift","/home/christian/Desktop/swift-algorithm-club/Trie/sources/Queue.swift"] - objects: ["/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/sources/trie.swift.o","/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/sources/Queue.swift.o"] - import-paths: ["/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug"] - temps-path: "/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/package_name_here_and_keep_quote_marks" - other-args: ["-j8","-Onone","-g","-enable-testing","-I","/usr/local/include"] - : - tool: shell - inputs: ["","/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/sources/trie.swift.o","/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/sources/Queue.swift.o"] - outputs: ["","/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/package_name_here_and_keep_quote_marks.a"] - args: ["/bin/sh","-c","rm -f '/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/package_name_here_and_keep_quote_marks.a'; ar cr '/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/package_name_here_and_keep_quote_marks.a' '/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/sources/trie.swift.o' '/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/sources/Queue.swift.o'"] - description: "Linking Library: .build/debug/package_name_here_and_keep_quote_marks.a" diff --git a/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/package_name_here_and_keep_quote_marks/Queue.d b/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/package_name_here_and_keep_quote_marks/Queue.d deleted file mode 100644 index 2b2aa612f..000000000 --- a/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/package_name_here_and_keep_quote_marks/Queue.d +++ /dev/null @@ -1,3 +0,0 @@ -/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/sources/Queue.swift.o : /home/christian/Desktop/swift-algorithm-club/Trie/sources/trie.swift /home/christian/Desktop/swift-algorithm-club/Trie/sources/Queue.swift /home/christian/swiftv2/usr/lib/swift/linux/x86_64/Swift.swiftmodule /home/christian/swiftv2/usr/lib/swift/shims/UnicodeShims.h /home/christian/swiftv2/usr/lib/swift/shims/SwiftStdint.h /home/christian/swiftv2/usr/lib/swift/shims/SwiftStddef.h /home/christian/swiftv2/usr/lib/swift/shims/LibcShims.h /home/christian/swiftv2/usr/lib/swift/shims/RuntimeStubs.h /home/christian/swiftv2/usr/lib/swift/shims/RuntimeShims.h /home/christian/swiftv2/usr/lib/swift/shims/RefCount.h /home/christian/swiftv2/usr/lib/swift/shims/HeapObject.h /home/christian/swiftv2/usr/lib/swift/shims/GlobalObjects.h /home/christian/swiftv2/usr/lib/swift/shims/FoundationShims.h /home/christian/swiftv2/usr/lib/swift/shims/CoreFoundationShims.h /home/christian/swiftv2/usr/lib/swift/shims/module.map -/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/package_name_here_and_keep_quote_marks/Queue~partial.swiftmodule : /home/christian/Desktop/swift-algorithm-club/Trie/sources/trie.swift /home/christian/Desktop/swift-algorithm-club/Trie/sources/Queue.swift /home/christian/swiftv2/usr/lib/swift/linux/x86_64/Swift.swiftmodule /home/christian/swiftv2/usr/lib/swift/shims/UnicodeShims.h /home/christian/swiftv2/usr/lib/swift/shims/SwiftStdint.h /home/christian/swiftv2/usr/lib/swift/shims/SwiftStddef.h /home/christian/swiftv2/usr/lib/swift/shims/LibcShims.h /home/christian/swiftv2/usr/lib/swift/shims/RuntimeStubs.h /home/christian/swiftv2/usr/lib/swift/shims/RuntimeShims.h /home/christian/swiftv2/usr/lib/swift/shims/RefCount.h /home/christian/swiftv2/usr/lib/swift/shims/HeapObject.h /home/christian/swiftv2/usr/lib/swift/shims/GlobalObjects.h /home/christian/swiftv2/usr/lib/swift/shims/FoundationShims.h /home/christian/swiftv2/usr/lib/swift/shims/CoreFoundationShims.h /home/christian/swiftv2/usr/lib/swift/shims/module.map -/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/package_name_here_and_keep_quote_marks/Queue~partial.swiftdoc : /home/christian/Desktop/swift-algorithm-club/Trie/sources/trie.swift /home/christian/Desktop/swift-algorithm-club/Trie/sources/Queue.swift /home/christian/swiftv2/usr/lib/swift/linux/x86_64/Swift.swiftmodule /home/christian/swiftv2/usr/lib/swift/shims/UnicodeShims.h /home/christian/swiftv2/usr/lib/swift/shims/SwiftStdint.h /home/christian/swiftv2/usr/lib/swift/shims/SwiftStddef.h /home/christian/swiftv2/usr/lib/swift/shims/LibcShims.h /home/christian/swiftv2/usr/lib/swift/shims/RuntimeStubs.h /home/christian/swiftv2/usr/lib/swift/shims/RuntimeShims.h /home/christian/swiftv2/usr/lib/swift/shims/RefCount.h /home/christian/swiftv2/usr/lib/swift/shims/HeapObject.h /home/christian/swiftv2/usr/lib/swift/shims/GlobalObjects.h /home/christian/swiftv2/usr/lib/swift/shims/FoundationShims.h /home/christian/swiftv2/usr/lib/swift/shims/CoreFoundationShims.h /home/christian/swiftv2/usr/lib/swift/shims/module.map diff --git a/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/package_name_here_and_keep_quote_marks/Queue.swiftdeps b/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/package_name_here_and_keep_quote_marks/Queue.swiftdeps deleted file mode 100644 index eaa595090..000000000 --- a/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/package_name_here_and_keep_quote_marks/Queue.swiftdeps +++ /dev/null @@ -1,316 +0,0 @@ -### Swift dependencies file v0 ### -provides-top-level: -- "Queue" -provides-nominal: -- "V38package_name_here_and_keep_quote_marks5Queue" -provides-member: -- ["V38package_name_here_and_keep_quote_marks5Queue", ""] -depends-top-level: -- "Queue" -- !private "/" -- !private "&&" -- !private "Double" -- !private "-" -- "Bool" -- "FloatLiteralType" -- "IntegerLiteralType" -- !private ">" -- !private "==" -- "Int" -- !private "<" -- !private "+=" -depends-member: -- !private ["Ps16AbsoluteValuable", "init"] -- ["Sa", "Generator"] -- ["Sa", "Index"] -- ["Sa", "SubSequence"] -- ["Sa", "_Element"] -- !private ["Sa", "append"] -- !private ["Sa", "count"] -- !private ["Sa", "deinit"] -- ["Sa", "init"] -- !private ["Sa", "removeFirst"] -- !private ["Sa", "subscript"] -- ["Ps23ArrayLiteralConvertible", "Generator"] -- ["Ps23ArrayLiteralConvertible", "Index"] -- ["Ps23ArrayLiteralConvertible", "SubSequence"] -- ["Ps23ArrayLiteralConvertible", "_Element"] -- !private ["Ps23ArrayLiteralConvertible", "append"] -- !private ["Ps23ArrayLiteralConvertible", "count"] -- ["Ps23ArrayLiteralConvertible", "init"] -- !private ["Ps23ArrayLiteralConvertible", "removeFirst"] -- !private ["Ps23ArrayLiteralConvertible", "subscript"] -- ["Vs10ArraySlice", "Generator"] -- ["Vs10ArraySlice", "Index"] -- ["Ps22BidirectionalIndexType", "Distance"] -- ["Ps22BidirectionalIndexType", "IntegerLiteralType"] -- ["Ps21BitwiseOperationsType", "Distance"] -- ["Ps21BitwiseOperationsType", "IntegerLiteralType"] -- !private ["Sb", "_getBuiltinLogicValue"] -- !private ["Ps25BooleanLiteralConvertible", "_getBuiltinLogicValue"] -- !private ["Ps11BooleanType", "_getBuiltinLogicValue"] -- ["Ps11CVarArgType", "Distance"] -- ["Ps11CVarArgType", "IntegerLiteralType"] -- !private ["Ps11CVarArgType", "init"] -- ["Ps14CollectionType", "Generator"] -- ["Ps14CollectionType", "Index"] -- ["Ps14CollectionType", "SubSequence"] -- ["Ps14CollectionType", "_Element"] -- !private ["Ps14CollectionType", "append"] -- !private ["Ps14CollectionType", "count"] -- ["Ps14CollectionType", "init"] -- !private ["Ps14CollectionType", "removeFirst"] -- !private ["Ps14CollectionType", "subscript"] -- ["Ps10Comparable", "Distance"] -- ["Ps10Comparable", "IntegerLiteralType"] -- !private ["Ps10Comparable", "init"] -- ["Ps28CustomDebugStringConvertible", "Generator"] -- ["Ps28CustomDebugStringConvertible", "Index"] -- ["Ps28CustomDebugStringConvertible", "Some"] -- ["Ps28CustomDebugStringConvertible", "SubSequence"] -- ["Ps28CustomDebugStringConvertible", "_Element"] -- !private ["Ps28CustomDebugStringConvertible", "append"] -- !private ["Ps28CustomDebugStringConvertible", "count"] -- ["Ps28CustomDebugStringConvertible", "init"] -- !private ["Ps28CustomDebugStringConvertible", "removeFirst"] -- !private ["Ps28CustomDebugStringConvertible", "subscript"] -- ["Ps23CustomStringConvertible", "Distance"] -- ["Ps23CustomStringConvertible", "Generator"] -- ["Ps23CustomStringConvertible", "Index"] -- ["Ps23CustomStringConvertible", "IntegerLiteralType"] -- ["Ps23CustomStringConvertible", "SubSequence"] -- ["Ps23CustomStringConvertible", "_Element"] -- !private ["Ps23CustomStringConvertible", "_getBuiltinLogicValue"] -- !private ["Ps23CustomStringConvertible", "append"] -- !private ["Ps23CustomStringConvertible", "count"] -- ["Ps23CustomStringConvertible", "init"] -- !private ["Ps23CustomStringConvertible", "removeFirst"] -- !private ["Ps23CustomStringConvertible", "subscript"] -- !private ["Sd", "init"] -- ["Ps9Equatable", "Distance"] -- ["Ps9Equatable", "IntegerLiteralType"] -- !private ["Ps9Equatable", "_getBuiltinLogicValue"] -- !private ["Ps9Equatable", "init"] -- !private ["Ps23FloatLiteralConvertible", "init"] -- !private ["Ps17FloatingPointType", "init"] -- ["Ps16ForwardIndexType", "Distance"] -- ["Ps16ForwardIndexType", "IntegerLiteralType"] -- ["Ps13GeneratorType", "Element"] -- ["Ps8Hashable", "Distance"] -- ["Ps8Hashable", "IntegerLiteralType"] -- !private ["Ps8Hashable", "_getBuiltinLogicValue"] -- !private ["Ps8Hashable", "init"] -- ["Ps9Indexable", "Generator"] -- ["Ps9Indexable", "Index"] -- ["Ps9Indexable", "SubSequence"] -- ["Ps9Indexable", "_Element"] -- !private ["Ps9Indexable", "append"] -- !private ["Ps9Indexable", "count"] -- ["Ps9Indexable", "init"] -- !private ["Ps9Indexable", "removeFirst"] -- !private ["Ps9Indexable", "subscript"] -- ["Vs17IndexingGenerator", "Element"] -- ["Si", "Distance"] -- ["Si", "IntegerLiteralType"] -- ["Ps21IntegerArithmeticType", "Distance"] -- ["Ps21IntegerArithmeticType", "IntegerLiteralType"] -- ["Ps25IntegerLiteralConvertible", "Distance"] -- ["Ps25IntegerLiteralConvertible", "IntegerLiteralType"] -- !private ["Ps25IntegerLiteralConvertible", "init"] -- ["Ps11IntegerType", "Distance"] -- ["Ps11IntegerType", "IntegerLiteralType"] -- ["Ps14MirrorPathType", "Distance"] -- ["Ps14MirrorPathType", "IntegerLiteralType"] -- ["Ps21MutableCollectionType", "Generator"] -- ["Ps21MutableCollectionType", "Index"] -- ["Ps21MutableCollectionType", "SubSequence"] -- ["Ps21MutableCollectionType", "_Element"] -- !private ["Ps21MutableCollectionType", "append"] -- !private ["Ps21MutableCollectionType", "count"] -- ["Ps21MutableCollectionType", "init"] -- !private ["Ps21MutableCollectionType", "removeFirst"] -- !private ["Ps21MutableCollectionType", "subscript"] -- ["Ps16MutableIndexable", "Generator"] -- ["Ps16MutableIndexable", "Index"] -- ["Ps16MutableIndexable", "SubSequence"] -- ["Ps16MutableIndexable", "_Element"] -- !private ["Ps16MutableIndexable", "append"] -- !private ["Ps16MutableIndexable", "count"] -- ["Ps16MutableIndexable", "init"] -- !private ["Ps16MutableIndexable", "removeFirst"] -- !private ["Ps16MutableIndexable", "subscript"] -- ["Ps16MutableSliceable", "Generator"] -- ["Ps16MutableSliceable", "Index"] -- ["Ps16MutableSliceable", "SubSequence"] -- ["Ps16MutableSliceable", "_Element"] -- !private ["Ps16MutableSliceable", "append"] -- !private ["Ps16MutableSliceable", "count"] -- ["Ps16MutableSliceable", "init"] -- !private ["Ps16MutableSliceable", "removeFirst"] -- !private ["Ps16MutableSliceable", "subscript"] -- ["Ps21NilLiteralConvertible", "Some"] -- ["Sq", "Some"] -- ["V38package_name_here_and_keep_quote_marks5Queue", "Bool"] -- !private ["V38package_name_here_and_keep_quote_marks5Queue", "Double"] -- ["V38package_name_here_and_keep_quote_marks5Queue", "Int"] -- ["V38package_name_here_and_keep_quote_marks5Queue", "T"] -- !private ["V38package_name_here_and_keep_quote_marks5Queue", "array"] -- ["V38package_name_here_and_keep_quote_marks5Queue", "count"] -- ["V38package_name_here_and_keep_quote_marks5Queue", "dequeue"] -- ["V38package_name_here_and_keep_quote_marks5Queue", "enqueue"] -- !private ["V38package_name_here_and_keep_quote_marks5Queue", "head"] -- ["V38package_name_here_and_keep_quote_marks5Queue", "init"] -- ["V38package_name_here_and_keep_quote_marks5Queue", "isEmpty"] -- ["V38package_name_here_and_keep_quote_marks5Queue", "peek"] -- ["Ps21RandomAccessIndexType", "Distance"] -- ["Ps21RandomAccessIndexType", "IntegerLiteralType"] -- ["Ps30RangeReplaceableCollectionType", "Generator"] -- ["Ps30RangeReplaceableCollectionType", "Index"] -- ["Ps30RangeReplaceableCollectionType", "SubSequence"] -- ["Ps30RangeReplaceableCollectionType", "_Element"] -- !private ["Ps30RangeReplaceableCollectionType", "append"] -- !private ["Ps30RangeReplaceableCollectionType", "count"] -- ["Ps30RangeReplaceableCollectionType", "init"] -- !private ["Ps30RangeReplaceableCollectionType", "removeFirst"] -- !private ["Ps30RangeReplaceableCollectionType", "subscript"] -- ["Ps12SequenceType", "Element"] -- ["Ps12SequenceType", "Generator"] -- ["Ps12SequenceType", "Index"] -- ["Ps12SequenceType", "SubSequence"] -- ["Ps12SequenceType", "_Element"] -- !private ["Ps12SequenceType", "append"] -- !private ["Ps12SequenceType", "count"] -- ["Ps12SequenceType", "init"] -- !private ["Ps12SequenceType", "removeFirst"] -- !private ["Ps12SequenceType", "subscript"] -- ["Ps17SignedIntegerType", "Distance"] -- ["Ps17SignedIntegerType", "IntegerLiteralType"] -- ["Ps16SignedNumberType", "Distance"] -- ["Ps16SignedNumberType", "IntegerLiteralType"] -- !private ["Ps16SignedNumberType", "init"] -- !private ["Vs5Slice", "Generator"] -- !private ["Vs5Slice", "Index"] -- !private ["Vs5Slice", "SubSequence"] -- !private ["Vs5Slice", "_Element"] -- ["Ps10Strideable", "Distance"] -- ["Ps10Strideable", "IntegerLiteralType"] -- !private ["Ps10Strideable", "init"] -- ["Ps10_ArrayType", "Generator"] -- ["Ps10_ArrayType", "Index"] -- ["Ps10_ArrayType", "SubSequence"] -- ["Ps10_ArrayType", "_Element"] -- !private ["Ps10_ArrayType", "append"] -- !private ["Ps10_ArrayType", "count"] -- ["Ps10_ArrayType", "init"] -- !private ["Ps10_ArrayType", "removeFirst"] -- !private ["Ps10_ArrayType", "subscript"] -- !private ["Ps33_BuiltinBooleanLiteralConvertible", "_getBuiltinLogicValue"] -- !private ["Ps31_BuiltinFloatLiteralConvertible", "init"] -- ["Ps33_BuiltinIntegerLiteralConvertible", "Distance"] -- ["Ps33_BuiltinIntegerLiteralConvertible", "IntegerLiteralType"] -- !private ["Ps33_BuiltinIntegerLiteralConvertible", "init"] -- !private ["Ps19_CVarArgAlignedType", "init"] -- !private ["Ps22_CVarArgPassedAsDouble", "init"] -- ["Ps24_DestructorSafeContainer", "Generator"] -- ["Ps24_DestructorSafeContainer", "Index"] -- ["Ps24_DestructorSafeContainer", "SubSequence"] -- ["Ps24_DestructorSafeContainer", "_Element"] -- !private ["Ps24_DestructorSafeContainer", "append"] -- !private ["Ps24_DestructorSafeContainer", "count"] -- ["Ps24_DestructorSafeContainer", "init"] -- !private ["Ps24_DestructorSafeContainer", "removeFirst"] -- !private ["Ps24_DestructorSafeContainer", "subscript"] -- ["Ps14_Incrementable", "Distance"] -- ["Ps14_Incrementable", "IntegerLiteralType"] -- ["Ps22_IntegerArithmeticType", "Distance"] -- ["Ps22_IntegerArithmeticType", "IntegerLiteralType"] -- ["Ps12_IntegerType", "Distance"] -- ["Ps12_IntegerType", "IntegerLiteralType"] -- ["Ps22_RandomAccessAmbiguity", "Distance"] -- ["Ps22_RandomAccessAmbiguity", "IntegerLiteralType"] -- ["Ps12_Reflectable", "Distance"] -- ["Ps12_Reflectable", "Generator"] -- ["Ps12_Reflectable", "Index"] -- ["Ps12_Reflectable", "IntegerLiteralType"] -- ["Ps12_Reflectable", "Some"] -- ["Ps12_Reflectable", "SubSequence"] -- ["Ps12_Reflectable", "_Element"] -- !private ["Ps12_Reflectable", "_getBuiltinLogicValue"] -- !private ["Ps12_Reflectable", "append"] -- !private ["Ps12_Reflectable", "count"] -- ["Ps12_Reflectable", "init"] -- !private ["Ps12_Reflectable", "removeFirst"] -- !private ["Ps12_Reflectable", "subscript"] -- ["Ps18_SignedIntegerType", "Distance"] -- ["Ps18_SignedIntegerType", "IntegerLiteralType"] -depends-nominal: -- !private "Ps16AbsoluteValuable" -- "Sa" -- "Ps23ArrayLiteralConvertible" -- "Vs10ArraySlice" -- "Ps22BidirectionalIndexType" -- "Ps21BitwiseOperationsType" -- !private "Sb" -- !private "Ps25BooleanLiteralConvertible" -- !private "Ps11BooleanType" -- "Ps11CVarArgType" -- "Ps14CollectionType" -- "Ps10Comparable" -- "Ps28CustomDebugStringConvertible" -- "Ps23CustomStringConvertible" -- !private "Sd" -- "Ps9Equatable" -- !private "Ps23FloatLiteralConvertible" -- !private "Ps17FloatingPointType" -- "Ps16ForwardIndexType" -- "Ps13GeneratorType" -- "Ps8Hashable" -- "Ps9Indexable" -- "Vs17IndexingGenerator" -- "Si" -- "Ps21IntegerArithmeticType" -- "Ps25IntegerLiteralConvertible" -- "Ps11IntegerType" -- "Ps14MirrorPathType" -- "Ps21MutableCollectionType" -- "Ps16MutableIndexable" -- "Ps16MutableSliceable" -- "Ps21NilLiteralConvertible" -- "Sq" -- "V38package_name_here_and_keep_quote_marks5Queue" -- "Ps21RandomAccessIndexType" -- "Ps30RangeReplaceableCollectionType" -- "Ps12SequenceType" -- "Ps17SignedIntegerType" -- "Ps16SignedNumberType" -- !private "Vs5Slice" -- "Ps10Strideable" -- "Ps10_ArrayType" -- !private "Ps33_BuiltinBooleanLiteralConvertible" -- !private "Ps31_BuiltinFloatLiteralConvertible" -- "Ps33_BuiltinIntegerLiteralConvertible" -- !private "Ps19_CVarArgAlignedType" -- !private "Ps22_CVarArgPassedAsDouble" -- "Ps24_DestructorSafeContainer" -- "Ps14_Incrementable" -- "Ps22_IntegerArithmeticType" -- "Ps12_IntegerType" -- "Ps22_RandomAccessAmbiguity" -- "Ps12_Reflectable" -- "Ps18_SignedIntegerType" -depends-dynamic-lookup: -depends-external: -- "/home/christian/swiftv2/usr/lib/swift/linux/x86_64/Swift.swiftmodule" -- "/home/christian/swiftv2/usr/lib/swift/shims/UnicodeShims.h" -- "/home/christian/swiftv2/usr/lib/swift/shims/SwiftStdint.h" -- "/home/christian/swiftv2/usr/lib/swift/shims/SwiftStddef.h" -- "/home/christian/swiftv2/usr/lib/swift/shims/LibcShims.h" -- "/home/christian/swiftv2/usr/lib/swift/shims/RuntimeStubs.h" -- "/home/christian/swiftv2/usr/lib/swift/shims/RuntimeShims.h" -- "/home/christian/swiftv2/usr/lib/swift/shims/RefCount.h" -- "/home/christian/swiftv2/usr/lib/swift/shims/HeapObject.h" -- "/home/christian/swiftv2/usr/lib/swift/shims/GlobalObjects.h" -- "/home/christian/swiftv2/usr/lib/swift/shims/FoundationShims.h" -- "/home/christian/swiftv2/usr/lib/swift/shims/CoreFoundationShims.h" -- "/home/christian/swiftv2/usr/lib/swift/shims/module.map" -interface-hash: "b268b101cc2bc2706939fa25905dab4d" diff --git a/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/package_name_here_and_keep_quote_marks/master.swiftdeps b/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/package_name_here_and_keep_quote_marks/master.swiftdeps deleted file mode 100644 index d0814f65b..000000000 --- a/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/package_name_here_and_keep_quote_marks/master.swiftdeps +++ /dev/null @@ -1,6 +0,0 @@ -version: "Swift version 2.2-dev (LLVM 3ebdbb2c7e, Clang f66c5bb67b, Swift 0ddf238ad7)" -options: "4b4cb3e8efe303c8a39bf9409934d3d3" -build_time: [515615518, 682291000] -inputs: - "/home/christian/Desktop/swift-algorithm-club/Trie/sources/trie.swift": !dirty [515615193, 0] - "/home/christian/Desktop/swift-algorithm-club/Trie/sources/Queue.swift": !dirty [512710161, 0] diff --git a/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/package_name_here_and_keep_quote_marks/output-file-map.json b/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/package_name_here_and_keep_quote_marks/output-file-map.json deleted file mode 100644 index 5b65a86c0..000000000 --- a/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/package_name_here_and_keep_quote_marks/output-file-map.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "": { - "swift-dependencies": "/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/package_name_here_and_keep_quote_marks/master.swiftdeps" - }, - "/home/christian/Desktop/swift-algorithm-club/Trie/sources/trie.swift": { - "dependencies": "/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/package_name_here_and_keep_quote_marks/trie.d", - "object": "/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/sources/trie.swift.o", - "swiftmodule": "/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/package_name_here_and_keep_quote_marks/trie~partial.swiftmodule", - "swift-dependencies": "/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/package_name_here_and_keep_quote_marks/trie.swiftdeps" - }, - "/home/christian/Desktop/swift-algorithm-club/Trie/sources/Queue.swift": { - "dependencies": "/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/package_name_here_and_keep_quote_marks/Queue.d", - "object": "/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/sources/Queue.swift.o", - "swiftmodule": "/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/package_name_here_and_keep_quote_marks/Queue~partial.swiftmodule", - "swift-dependencies": "/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/package_name_here_and_keep_quote_marks/Queue.swiftdeps" - } -} diff --git a/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/package_name_here_and_keep_quote_marks/trie.d b/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/package_name_here_and_keep_quote_marks/trie.d deleted file mode 100644 index eefb6fd8d..000000000 --- a/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/package_name_here_and_keep_quote_marks/trie.d +++ /dev/null @@ -1,3 +0,0 @@ -/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/sources/trie.swift.o : /home/christian/Desktop/swift-algorithm-club/Trie/sources/trie.swift /home/christian/Desktop/swift-algorithm-club/Trie/sources/Queue.swift /home/christian/swiftv2/usr/lib/swift/linux/x86_64/Swift.swiftmodule /home/christian/swiftv2/usr/lib/swift/shims/UnicodeShims.h /home/christian/swiftv2/usr/lib/swift/shims/SwiftStdint.h /home/christian/swiftv2/usr/lib/swift/shims/SwiftStddef.h /home/christian/swiftv2/usr/lib/swift/shims/LibcShims.h /home/christian/swiftv2/usr/lib/swift/shims/RuntimeStubs.h /home/christian/swiftv2/usr/lib/swift/shims/RuntimeShims.h /home/christian/swiftv2/usr/lib/swift/shims/RefCount.h /home/christian/swiftv2/usr/lib/swift/shims/HeapObject.h /home/christian/swiftv2/usr/lib/swift/shims/GlobalObjects.h /home/christian/swiftv2/usr/lib/swift/shims/FoundationShims.h /home/christian/swiftv2/usr/lib/swift/shims/CoreFoundationShims.h /home/christian/swiftv2/usr/lib/swift/shims/module.map -/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/package_name_here_and_keep_quote_marks/trie~partial.swiftmodule : /home/christian/Desktop/swift-algorithm-club/Trie/sources/trie.swift /home/christian/Desktop/swift-algorithm-club/Trie/sources/Queue.swift /home/christian/swiftv2/usr/lib/swift/linux/x86_64/Swift.swiftmodule /home/christian/swiftv2/usr/lib/swift/shims/UnicodeShims.h /home/christian/swiftv2/usr/lib/swift/shims/SwiftStdint.h /home/christian/swiftv2/usr/lib/swift/shims/SwiftStddef.h /home/christian/swiftv2/usr/lib/swift/shims/LibcShims.h /home/christian/swiftv2/usr/lib/swift/shims/RuntimeStubs.h /home/christian/swiftv2/usr/lib/swift/shims/RuntimeShims.h /home/christian/swiftv2/usr/lib/swift/shims/RefCount.h /home/christian/swiftv2/usr/lib/swift/shims/HeapObject.h /home/christian/swiftv2/usr/lib/swift/shims/GlobalObjects.h /home/christian/swiftv2/usr/lib/swift/shims/FoundationShims.h /home/christian/swiftv2/usr/lib/swift/shims/CoreFoundationShims.h /home/christian/swiftv2/usr/lib/swift/shims/module.map -/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/package_name_here_and_keep_quote_marks/trie~partial.swiftdoc : /home/christian/Desktop/swift-algorithm-club/Trie/sources/trie.swift /home/christian/Desktop/swift-algorithm-club/Trie/sources/Queue.swift /home/christian/swiftv2/usr/lib/swift/linux/x86_64/Swift.swiftmodule /home/christian/swiftv2/usr/lib/swift/shims/UnicodeShims.h /home/christian/swiftv2/usr/lib/swift/shims/SwiftStdint.h /home/christian/swiftv2/usr/lib/swift/shims/SwiftStddef.h /home/christian/swiftv2/usr/lib/swift/shims/LibcShims.h /home/christian/swiftv2/usr/lib/swift/shims/RuntimeStubs.h /home/christian/swiftv2/usr/lib/swift/shims/RuntimeShims.h /home/christian/swiftv2/usr/lib/swift/shims/RefCount.h /home/christian/swiftv2/usr/lib/swift/shims/HeapObject.h /home/christian/swiftv2/usr/lib/swift/shims/GlobalObjects.h /home/christian/swiftv2/usr/lib/swift/shims/FoundationShims.h /home/christian/swiftv2/usr/lib/swift/shims/CoreFoundationShims.h /home/christian/swiftv2/usr/lib/swift/shims/module.map diff --git a/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/package_name_here_and_keep_quote_marks/trie.swiftdeps b/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/package_name_here_and_keep_quote_marks/trie.swiftdeps deleted file mode 100644 index 39eba9f00..000000000 --- a/Trie/.build/debug/package_name_here_and_keep_quote_marks.o/package_name_here_and_keep_quote_marks/trie.swiftdeps +++ /dev/null @@ -1,513 +0,0 @@ -### Swift dependencies file v0 ### -provides-top-level: -- "Node" -- "Trie" -- "T" -- "U" -- "V" -provides-nominal: -- "C38package_name_here_and_keep_quote_marks4Node" -- "C38package_name_here_and_keep_quote_marks4Trie" -provides-member: -- ["C38package_name_here_and_keep_quote_marks4Node", ""] -- ["C38package_name_here_and_keep_quote_marks4Trie", ""] -depends-top-level: -- "Trie" -- "print" -- "Bool" -- !private "-=" -- "StringLiteralType" -- !private ">" -- !private "&&" -- !private "Queue" -- "U" -- "Int" -- "V" -- !private "BooleanLiteralType" -- "Node" -- "FloatLiteralType" -- "Set" -- "Array" -- !private "+" -- !private "-" -- !private "UnicodeScalarType" -- "IntegerLiteralType" -- !private "==" -- "Void" -- !private "+=" -- "T" -- !private "!" -- "String" -depends-member: -- !private ["Vs12AnyGenerator", "Element"] -- !private ["Ps9AnyObject", "Array"] -- !private ["Ps9AnyObject", "Node"] -- !private ["Ps9AnyObject", "Queue"] -- !private ["Ps9AnyObject", "Set"] -- !private ["Ps9AnyObject", "String"] -- !private ["Ps9AnyObject", "Trie"] -- !private ["Ps9AnyObject", "char"] -- !private ["Ps9AnyObject", "character"] -- !private ["Ps9AnyObject", "children"] -- !private ["Ps9AnyObject", "contains"] -- !private ["Ps9AnyObject", "find"] -- !private ["Ps9AnyObject", "getChildAt"] -- !private ["Ps9AnyObject", "getChildren"] -- !private ["Ps9AnyObject", "getParent"] -- ["Ps9AnyObject", "getWords"] -- ["Ps9AnyObject", "init"] -- ["Ps9AnyObject", "insert"] -- !private ["Ps9AnyObject", "isAWord"] -- !private ["Ps9AnyObject", "isNotWord"] -- !private ["Ps9AnyObject", "isRoot"] -- !private ["Ps9AnyObject", "isValidWord"] -- !private ["Ps9AnyObject", "isWord"] -- ["Ps9AnyObject", "merge"] -- !private ["Ps9AnyObject", "numChildren"] -- !private ["Ps9AnyObject", "parent"] -- !private ["Ps9AnyObject", "print"] -- !private ["Ps9AnyObject", "printNode"] -- !private ["Ps9AnyObject", "remove"] -- ["Ps9AnyObject", "removeAll"] -- !private ["Ps9AnyObject", "root"] -- !private ["Ps9AnyObject", "setParent"] -- !private ["Ps9AnyObject", "update"] -- !private ["Ps9AnyObject", "wordCount"] -- !private ["Ps9AnyObject", "wordList"] -- ["Ps9AnyObject", ""] -- !private ["Vs11AnySequence", "Generator"] -- !private ["Vs11AnySequence", "deinit"] -- ["Sa", "Element"] -- ["Sa", "Generator"] -- ["Sa", "Index"] -- !private ["Sa", "SubSequence"] -- ["Sa", "_Element"] -- !private ["Sa", "append"] -- !private ["Sa", "deinit"] -- !private ["Sa", "init"] -- !private ["Sa", "removeAtIndex"] -- !private ["Sa", "subscript"] -- ["Ps23ArrayLiteralConvertible", "Element"] -- ["Ps23ArrayLiteralConvertible", "Generator"] -- ["Ps23ArrayLiteralConvertible", "Index"] -- !private ["Ps23ArrayLiteralConvertible", "SubSequence"] -- ["Ps23ArrayLiteralConvertible", "_Element"] -- !private ["Ps23ArrayLiteralConvertible", "append"] -- ["Ps23ArrayLiteralConvertible", "init"] -- !private ["Ps23ArrayLiteralConvertible", "removeAtIndex"] -- !private ["Ps23ArrayLiteralConvertible", "subscript"] -- !private ["Vs10ArraySlice", "Generator"] -- !private ["Vs10ArraySlice", "Index"] -- ["Ps22BidirectionalIndexType", "Distance"] -- ["Ps22BidirectionalIndexType", "IntegerLiteralType"] -- ["Ps21BitwiseOperationsType", "Distance"] -- ["Ps21BitwiseOperationsType", "IntegerLiteralType"] -- !private ["Sb", "_getBuiltinLogicValue"] -- !private ["Ps25BooleanLiteralConvertible", "_getBuiltinLogicValue"] -- !private ["Ps11BooleanType", "_getBuiltinLogicValue"] -- ["Ps11CVarArgType", "Distance"] -- ["Ps11CVarArgType", "IntegerLiteralType"] -- !private ["VSS13CharacterView", "Generator"] -- !private ["VSS13CharacterView", "Index"] -- !private ["VSS13CharacterView", "SubSequence"] -- !private ["VSS13CharacterView", "_Element"] -- !private ["VSS13CharacterView", "count"] -- !private ["VSS13CharacterView", "deinit"] -- !private ["VSS13CharacterView", "suffix"] -- ["Ps14CollectionType", "Element"] -- ["Ps14CollectionType", "Generator"] -- ["Ps14CollectionType", "Index"] -- !private ["Ps14CollectionType", "SubSequence"] -- ["Ps14CollectionType", "_Element"] -- !private ["Ps14CollectionType", "append"] -- !private ["Ps14CollectionType", "count"] -- ["Ps14CollectionType", "init"] -- !private ["Ps14CollectionType", "removeAtIndex"] -- !private ["Ps14CollectionType", "subscript"] -- !private ["Ps14CollectionType", "suffix"] -- ["Ps10Comparable", "Distance"] -- ["Ps10Comparable", "IntegerLiteralType"] -- !private ["Ps10Comparable", "_DisabledRangeIndex"] -- !private ["Ps10Comparable", "characters"] -- !private ["Ps10Comparable", "init"] -- !private ["Ps10Comparable", "lowercaseString"] -- ["Ps28CustomDebugStringConvertible", "Element"] -- ["Ps28CustomDebugStringConvertible", "Generator"] -- ["Ps28CustomDebugStringConvertible", "Index"] -- ["Ps28CustomDebugStringConvertible", "Some"] -- !private ["Ps28CustomDebugStringConvertible", "SubSequence"] -- ["Ps28CustomDebugStringConvertible", "_Element"] -- !private ["Ps28CustomDebugStringConvertible", "append"] -- !private ["Ps28CustomDebugStringConvertible", "characters"] -- !private ["Ps28CustomDebugStringConvertible", "count"] -- ["Ps28CustomDebugStringConvertible", "init"] -- !private ["Ps28CustomDebugStringConvertible", "lowercaseString"] -- !private ["Ps28CustomDebugStringConvertible", "removeAtIndex"] -- !private ["Ps28CustomDebugStringConvertible", "subscript"] -- ["Ps23CustomStringConvertible", "Distance"] -- ["Ps23CustomStringConvertible", "Element"] -- ["Ps23CustomStringConvertible", "Generator"] -- ["Ps23CustomStringConvertible", "Index"] -- ["Ps23CustomStringConvertible", "IntegerLiteralType"] -- !private ["Ps23CustomStringConvertible", "SubSequence"] -- ["Ps23CustomStringConvertible", "_Element"] -- !private ["Ps23CustomStringConvertible", "_getBuiltinLogicValue"] -- !private ["Ps23CustomStringConvertible", "append"] -- !private ["Ps23CustomStringConvertible", "count"] -- ["Ps23CustomStringConvertible", "init"] -- !private ["Ps23CustomStringConvertible", "removeAtIndex"] -- !private ["Ps23CustomStringConvertible", "subscript"] -- !private ["Vs10Dictionary", "Generator"] -- !private ["Vs10Dictionary", "Index"] -- !private ["Vs10Dictionary", "SubSequence"] -- !private ["Vs10Dictionary", "_Element"] -- !private ["Vs10Dictionary", "count"] -- !private ["Vs10Dictionary", "deinit"] -- !private ["Vs10Dictionary", "init"] -- !private ["Vs10Dictionary", "subscript"] -- !private ["Vs19DictionaryGenerator", "Element"] -- !private ["Vs15DictionaryIndex", "Distance"] -- !private ["Vs15DictionaryIndex", "_DisabledRangeIndex"] -- !private ["Ps28DictionaryLiteralConvertible", "Generator"] -- !private ["Ps28DictionaryLiteralConvertible", "Index"] -- !private ["Ps28DictionaryLiteralConvertible", "SubSequence"] -- !private ["Ps28DictionaryLiteralConvertible", "_Element"] -- !private ["Ps28DictionaryLiteralConvertible", "count"] -- !private ["Ps28DictionaryLiteralConvertible", "init"] -- !private ["Ps28DictionaryLiteralConvertible", "subscript"] -- ["Ps9Equatable", "Distance"] -- !private ["Ps9Equatable", "Generator"] -- ["Ps9Equatable", "IntegerLiteralType"] -- !private ["Ps9Equatable", "_DisabledRangeIndex"] -- !private ["Ps9Equatable", "_getBuiltinLogicValue"] -- !private ["Ps9Equatable", "characters"] -- ["Ps9Equatable", "init"] -- !private ["Ps9Equatable", "lowercaseString"] -- !private ["Ps41ExtendedGraphemeClusterLiteralConvertible", "characters"] -- !private ["Ps41ExtendedGraphemeClusterLiteralConvertible", "init"] -- !private ["Ps41ExtendedGraphemeClusterLiteralConvertible", "lowercaseString"] -- ["Ps16ForwardIndexType", "Distance"] -- ["Ps16ForwardIndexType", "IntegerLiteralType"] -- !private ["Ps16ForwardIndexType", "_DisabledRangeIndex"] -- ["Ps13GeneratorType", "Element"] -- ["Ps8Hashable", "Distance"] -- !private ["Ps8Hashable", "Generator"] -- ["Ps8Hashable", "IntegerLiteralType"] -- !private ["Ps8Hashable", "_getBuiltinLogicValue"] -- !private ["Ps8Hashable", "characters"] -- ["Ps8Hashable", "init"] -- !private ["Ps8Hashable", "lowercaseString"] -- !private ["VVSS13CharacterView5Index", "Distance"] -- ["Ps9Indexable", "Element"] -- ["Ps9Indexable", "Generator"] -- ["Ps9Indexable", "Index"] -- !private ["Ps9Indexable", "SubSequence"] -- ["Ps9Indexable", "_Element"] -- !private ["Ps9Indexable", "append"] -- !private ["Ps9Indexable", "count"] -- ["Ps9Indexable", "init"] -- !private ["Ps9Indexable", "removeAtIndex"] -- !private ["Ps9Indexable", "subscript"] -- !private ["Ps9Indexable", "suffix"] -- ["Vs17IndexingGenerator", "Element"] -- ["Si", "Distance"] -- ["Si", "IntegerLiteralType"] -- ["Si", "deinit"] -- ["Ps21IntegerArithmeticType", "Distance"] -- ["Ps21IntegerArithmeticType", "IntegerLiteralType"] -- ["Ps25IntegerLiteralConvertible", "Distance"] -- ["Ps25IntegerLiteralConvertible", "IntegerLiteralType"] -- ["Ps11IntegerType", "Distance"] -- ["Ps11IntegerType", "IntegerLiteralType"] -- ["Ps14MirrorPathType", "Distance"] -- ["Ps14MirrorPathType", "IntegerLiteralType"] -- !private ["Ps14MirrorPathType", "characters"] -- !private ["Ps14MirrorPathType", "init"] -- !private ["Ps14MirrorPathType", "lowercaseString"] -- ["Ps21MutableCollectionType", "Element"] -- ["Ps21MutableCollectionType", "Generator"] -- ["Ps21MutableCollectionType", "Index"] -- !private ["Ps21MutableCollectionType", "SubSequence"] -- ["Ps21MutableCollectionType", "_Element"] -- !private ["Ps21MutableCollectionType", "append"] -- !private ["Ps21MutableCollectionType", "init"] -- !private ["Ps21MutableCollectionType", "removeAtIndex"] -- !private ["Ps21MutableCollectionType", "subscript"] -- ["Ps16MutableIndexable", "Element"] -- ["Ps16MutableIndexable", "Generator"] -- ["Ps16MutableIndexable", "Index"] -- !private ["Ps16MutableIndexable", "SubSequence"] -- ["Ps16MutableIndexable", "_Element"] -- !private ["Ps16MutableIndexable", "append"] -- !private ["Ps16MutableIndexable", "init"] -- !private ["Ps16MutableIndexable", "removeAtIndex"] -- !private ["Ps16MutableIndexable", "subscript"] -- ["Ps16MutableSliceable", "Element"] -- ["Ps16MutableSliceable", "Generator"] -- ["Ps16MutableSliceable", "Index"] -- !private ["Ps16MutableSliceable", "SubSequence"] -- ["Ps16MutableSliceable", "_Element"] -- !private ["Ps16MutableSliceable", "append"] -- !private ["Ps16MutableSliceable", "init"] -- !private ["Ps16MutableSliceable", "removeAtIndex"] -- !private ["Ps16MutableSliceable", "subscript"] -- ["Ps21NilLiteralConvertible", "Some"] -- ["C38package_name_here_and_keep_quote_marks4Node", "Bool"] -- ["C38package_name_here_and_keep_quote_marks4Node", "Int"] -- ["C38package_name_here_and_keep_quote_marks4Node", "Node"] -- ["C38package_name_here_and_keep_quote_marks4Node", "String"] -- ["C38package_name_here_and_keep_quote_marks4Node", "Void"] -- ["C38package_name_here_and_keep_quote_marks4Node", "char"] -- !private ["C38package_name_here_and_keep_quote_marks4Node", "character"] -- !private ["C38package_name_here_and_keep_quote_marks4Node", "children"] -- ["C38package_name_here_and_keep_quote_marks4Node", "deinit"] -- ["C38package_name_here_and_keep_quote_marks4Node", "getChildAt"] -- ["C38package_name_here_and_keep_quote_marks4Node", "getChildren"] -- ["C38package_name_here_and_keep_quote_marks4Node", "getParent"] -- ["C38package_name_here_and_keep_quote_marks4Node", "init"] -- !private ["C38package_name_here_and_keep_quote_marks4Node", "isAWord"] -- ["C38package_name_here_and_keep_quote_marks4Node", "isLeaf"] -- ["C38package_name_here_and_keep_quote_marks4Node", "isNotWord"] -- ["C38package_name_here_and_keep_quote_marks4Node", "isRoot"] -- ["C38package_name_here_and_keep_quote_marks4Node", "isValidWord"] -- ["C38package_name_here_and_keep_quote_marks4Node", "isWord"] -- ["C38package_name_here_and_keep_quote_marks4Node", "numChildren"] -- !private ["C38package_name_here_and_keep_quote_marks4Node", "parent"] -- !private ["C38package_name_here_and_keep_quote_marks4Node", "print"] -- ["C38package_name_here_and_keep_quote_marks4Node", "printNode"] -- ["C38package_name_here_and_keep_quote_marks4Node", "setParent"] -- ["C38package_name_here_and_keep_quote_marks4Node", "update"] -- ["Sq", "Some"] -- !private ["Sq", "deinit"] -- !private ["Ps16OutputStreamType", "characters"] -- !private ["Ps16OutputStreamType", "init"] -- !private ["Ps16OutputStreamType", "lowercaseString"] -- !private ["V38package_name_here_and_keep_quote_marks5Queue", "init"] -- ["Ps21RandomAccessIndexType", "Distance"] -- ["Ps21RandomAccessIndexType", "IntegerLiteralType"] -- ["Ps30RangeReplaceableCollectionType", "Element"] -- ["Ps30RangeReplaceableCollectionType", "Generator"] -- ["Ps30RangeReplaceableCollectionType", "Index"] -- !private ["Ps30RangeReplaceableCollectionType", "SubSequence"] -- ["Ps30RangeReplaceableCollectionType", "_Element"] -- !private ["Ps30RangeReplaceableCollectionType", "append"] -- !private ["Ps30RangeReplaceableCollectionType", "count"] -- !private ["Ps30RangeReplaceableCollectionType", "init"] -- !private ["Ps30RangeReplaceableCollectionType", "removeAtIndex"] -- !private ["Ps30RangeReplaceableCollectionType", "subscript"] -- !private ["Ps30RangeReplaceableCollectionType", "suffix"] -- ["Ps12SequenceType", "Element"] -- ["Ps12SequenceType", "Generator"] -- ["Ps12SequenceType", "Index"] -- !private ["Ps12SequenceType", "SubSequence"] -- ["Ps12SequenceType", "_Element"] -- !private ["Ps12SequenceType", "append"] -- !private ["Ps12SequenceType", "count"] -- ["Ps12SequenceType", "init"] -- !private ["Ps12SequenceType", "removeAtIndex"] -- !private ["Ps12SequenceType", "subscript"] -- !private ["Ps12SequenceType", "suffix"] -- !private ["Vs3Set", "Generator"] -- ["Vs3Set", "init"] -- !private ["Vs12SetGenerator", "Element"] -- ["Ps17SignedIntegerType", "Distance"] -- ["Ps17SignedIntegerType", "IntegerLiteralType"] -- ["Ps16SignedNumberType", "Distance"] -- ["Ps16SignedNumberType", "IntegerLiteralType"] -- !private ["Vs5Slice", "Generator"] -- !private ["Vs5Slice", "Index"] -- !private ["Vs5Slice", "SubSequence"] -- !private ["Vs5Slice", "_Element"] -- !private ["Vs5Slice", "deinit"] -- !private ["Ps10Streamable", "characters"] -- !private ["Ps10Streamable", "init"] -- !private ["Ps10Streamable", "lowercaseString"] -- ["Ps10Strideable", "Distance"] -- ["Ps10Strideable", "IntegerLiteralType"] -- !private ["SS", "characters"] -- !private ["SS", "init"] -- !private ["SS", "lowercaseString"] -- !private ["Ps30StringInterpolationConvertible", "characters"] -- !private ["Ps30StringInterpolationConvertible", "init"] -- !private ["Ps30StringInterpolationConvertible", "lowercaseString"] -- !private ["Ps24StringLiteralConvertible", "characters"] -- !private ["Ps24StringLiteralConvertible", "init"] -- !private ["Ps24StringLiteralConvertible", "lowercaseString"] -- !private ["C38package_name_here_and_keep_quote_marks4Trie", "Array"] -- ["C38package_name_here_and_keep_quote_marks4Trie", "Bool"] -- ["C38package_name_here_and_keep_quote_marks4Trie", "Int"] -- ["C38package_name_here_and_keep_quote_marks4Trie", "Node"] -- !private ["C38package_name_here_and_keep_quote_marks4Trie", "Queue"] -- ["C38package_name_here_and_keep_quote_marks4Trie", "Set"] -- ["C38package_name_here_and_keep_quote_marks4Trie", "String"] -- ["C38package_name_here_and_keep_quote_marks4Trie", "Trie"] -- ["C38package_name_here_and_keep_quote_marks4Trie", "contains"] -- ["C38package_name_here_and_keep_quote_marks4Trie", "count"] -- ["C38package_name_here_and_keep_quote_marks4Trie", "deinit"] -- ["C38package_name_here_and_keep_quote_marks4Trie", "find"] -- ["C38package_name_here_and_keep_quote_marks4Trie", "findPrefix"] -- ["C38package_name_here_and_keep_quote_marks4Trie", "getWords"] -- ["C38package_name_here_and_keep_quote_marks4Trie", "init"] -- ["C38package_name_here_and_keep_quote_marks4Trie", "insert"] -- ["C38package_name_here_and_keep_quote_marks4Trie", "isEmpty"] -- ["C38package_name_here_and_keep_quote_marks4Trie", "isPrefix"] -- ["C38package_name_here_and_keep_quote_marks4Trie", "merge"] -- ["C38package_name_here_and_keep_quote_marks4Trie", "printTrie"] -- ["C38package_name_here_and_keep_quote_marks4Trie", "remove"] -- ["C38package_name_here_and_keep_quote_marks4Trie", "removeAll"] -- !private ["C38package_name_here_and_keep_quote_marks4Trie", "root"] -- !private ["C38package_name_here_and_keep_quote_marks4Trie", "wordCount"] -- !private ["C38package_name_here_and_keep_quote_marks4Trie", "wordList"] -- !private ["Ps31UnicodeScalarLiteralConvertible", "characters"] -- !private ["Ps31UnicodeScalarLiteralConvertible", "init"] -- !private ["Ps31UnicodeScalarLiteralConvertible", "lowercaseString"] -- ["Ps10_ArrayType", "Element"] -- ["Ps10_ArrayType", "Generator"] -- ["Ps10_ArrayType", "Index"] -- !private ["Ps10_ArrayType", "SubSequence"] -- ["Ps10_ArrayType", "_Element"] -- !private ["Ps10_ArrayType", "append"] -- !private ["Ps10_ArrayType", "init"] -- !private ["Ps10_ArrayType", "removeAtIndex"] -- !private ["Ps10_ArrayType", "subscript"] -- !private ["Ps33_BuiltinBooleanLiteralConvertible", "_getBuiltinLogicValue"] -- !private ["Ps49_BuiltinExtendedGraphemeClusterLiteralConvertible", "characters"] -- !private ["Ps49_BuiltinExtendedGraphemeClusterLiteralConvertible", "init"] -- !private ["Ps49_BuiltinExtendedGraphemeClusterLiteralConvertible", "lowercaseString"] -- ["Ps33_BuiltinIntegerLiteralConvertible", "Distance"] -- ["Ps33_BuiltinIntegerLiteralConvertible", "IntegerLiteralType"] -- !private ["Ps32_BuiltinStringLiteralConvertible", "characters"] -- !private ["Ps32_BuiltinStringLiteralConvertible", "init"] -- !private ["Ps32_BuiltinStringLiteralConvertible", "lowercaseString"] -- !private ["Ps37_BuiltinUTF16StringLiteralConvertible", "characters"] -- !private ["Ps37_BuiltinUTF16StringLiteralConvertible", "init"] -- !private ["Ps37_BuiltinUTF16StringLiteralConvertible", "lowercaseString"] -- !private ["Ps39_BuiltinUnicodeScalarLiteralConvertible", "characters"] -- !private ["Ps39_BuiltinUnicodeScalarLiteralConvertible", "init"] -- !private ["Ps39_BuiltinUnicodeScalarLiteralConvertible", "lowercaseString"] -- ["Ps24_DestructorSafeContainer", "Element"] -- ["Ps24_DestructorSafeContainer", "Generator"] -- ["Ps24_DestructorSafeContainer", "Index"] -- !private ["Ps24_DestructorSafeContainer", "SubSequence"] -- ["Ps24_DestructorSafeContainer", "_Element"] -- !private ["Ps24_DestructorSafeContainer", "append"] -- !private ["Ps24_DestructorSafeContainer", "init"] -- !private ["Ps24_DestructorSafeContainer", "removeAtIndex"] -- !private ["Ps24_DestructorSafeContainer", "subscript"] -- ["Ps14_Incrementable", "Distance"] -- ["Ps14_Incrementable", "IntegerLiteralType"] -- !private ["Ps14_Incrementable", "_DisabledRangeIndex"] -- ["Ps22_IntegerArithmeticType", "Distance"] -- ["Ps22_IntegerArithmeticType", "IntegerLiteralType"] -- ["Ps12_IntegerType", "Distance"] -- ["Ps12_IntegerType", "IntegerLiteralType"] -- !private ["Vs26_OptionalNilComparisonType", "deinit"] -- ["Ps22_RandomAccessAmbiguity", "Distance"] -- ["Ps22_RandomAccessAmbiguity", "IntegerLiteralType"] -- ["Ps12_Reflectable", "Distance"] -- ["Ps12_Reflectable", "Element"] -- ["Ps12_Reflectable", "Generator"] -- ["Ps12_Reflectable", "Index"] -- ["Ps12_Reflectable", "IntegerLiteralType"] -- ["Ps12_Reflectable", "Some"] -- !private ["Ps12_Reflectable", "SubSequence"] -- ["Ps12_Reflectable", "_Element"] -- !private ["Ps12_Reflectable", "_getBuiltinLogicValue"] -- !private ["Ps12_Reflectable", "append"] -- !private ["Ps12_Reflectable", "characters"] -- !private ["Ps12_Reflectable", "count"] -- ["Ps12_Reflectable", "init"] -- !private ["Ps12_Reflectable", "lowercaseString"] -- !private ["Ps12_Reflectable", "removeAtIndex"] -- !private ["Ps12_Reflectable", "subscript"] -- ["Ps18_SignedIntegerType", "Distance"] -- ["Ps18_SignedIntegerType", "IntegerLiteralType"] -depends-nominal: -- !private "Vs12AnyGenerator" -- "Ps9AnyObject" -- !private "Vs11AnySequence" -- "Sa" -- "Ps23ArrayLiteralConvertible" -- !private "Vs10ArraySlice" -- "Ps22BidirectionalIndexType" -- "Ps21BitwiseOperationsType" -- !private "Sb" -- !private "Ps25BooleanLiteralConvertible" -- !private "Ps11BooleanType" -- "Ps11CVarArgType" -- !private "VSS13CharacterView" -- "Ps14CollectionType" -- "Ps10Comparable" -- "Ps28CustomDebugStringConvertible" -- "Ps23CustomStringConvertible" -- !private "Vs10Dictionary" -- !private "Vs19DictionaryGenerator" -- !private "Vs15DictionaryIndex" -- !private "Ps28DictionaryLiteralConvertible" -- "Ps9Equatable" -- !private "Ps41ExtendedGraphemeClusterLiteralConvertible" -- "Ps16ForwardIndexType" -- "Ps13GeneratorType" -- "Ps8Hashable" -- !private "VVSS13CharacterView5Index" -- "Ps9Indexable" -- "Vs17IndexingGenerator" -- "Si" -- "Ps21IntegerArithmeticType" -- "Ps25IntegerLiteralConvertible" -- "Ps11IntegerType" -- "Ps14MirrorPathType" -- "Ps21MutableCollectionType" -- "Ps16MutableIndexable" -- "Ps16MutableSliceable" -- "Ps21NilLiteralConvertible" -- "C38package_name_here_and_keep_quote_marks4Node" -- "Sq" -- !private "Ps16OutputStreamType" -- !private "V38package_name_here_and_keep_quote_marks5Queue" -- "Ps21RandomAccessIndexType" -- "Ps30RangeReplaceableCollectionType" -- "Ps12SequenceType" -- "Vs3Set" -- !private "Vs12SetGenerator" -- "Ps17SignedIntegerType" -- "Ps16SignedNumberType" -- !private "Vs5Slice" -- !private "Ps10Streamable" -- "Ps10Strideable" -- !private "SS" -- !private "Ps30StringInterpolationConvertible" -- !private "Ps24StringLiteralConvertible" -- "C38package_name_here_and_keep_quote_marks4Trie" -- !private "Ps31UnicodeScalarLiteralConvertible" -- "Ps10_ArrayType" -- !private "Ps33_BuiltinBooleanLiteralConvertible" -- !private "Ps49_BuiltinExtendedGraphemeClusterLiteralConvertible" -- "Ps33_BuiltinIntegerLiteralConvertible" -- !private "Ps32_BuiltinStringLiteralConvertible" -- !private "Ps37_BuiltinUTF16StringLiteralConvertible" -- !private "Ps39_BuiltinUnicodeScalarLiteralConvertible" -- "Ps24_DestructorSafeContainer" -- "Ps14_Incrementable" -- "Ps22_IntegerArithmeticType" -- "Ps12_IntegerType" -- !private "Vs26_OptionalNilComparisonType" -- "Ps22_RandomAccessAmbiguity" -- "Ps12_Reflectable" -- "Ps18_SignedIntegerType" -depends-dynamic-lookup: -depends-external: -- "/home/christian/swiftv2/usr/lib/swift/linux/x86_64/Swift.swiftmodule" -- "/home/christian/swiftv2/usr/lib/swift/shims/UnicodeShims.h" -- "/home/christian/swiftv2/usr/lib/swift/shims/SwiftStdint.h" -- "/home/christian/swiftv2/usr/lib/swift/shims/SwiftStddef.h" -- "/home/christian/swiftv2/usr/lib/swift/shims/LibcShims.h" -- "/home/christian/swiftv2/usr/lib/swift/shims/RuntimeStubs.h" -- "/home/christian/swiftv2/usr/lib/swift/shims/RuntimeShims.h" -- "/home/christian/swiftv2/usr/lib/swift/shims/RefCount.h" -- "/home/christian/swiftv2/usr/lib/swift/shims/HeapObject.h" -- "/home/christian/swiftv2/usr/lib/swift/shims/GlobalObjects.h" -- "/home/christian/swiftv2/usr/lib/swift/shims/FoundationShims.h" -- "/home/christian/swiftv2/usr/lib/swift/shims/CoreFoundationShims.h" -- "/home/christian/swiftv2/usr/lib/swift/shims/module.map" -interface-hash: "f003b1876d32aa37e370054fb3e811bb" diff --git a/Trie/Package.swift~ b/Trie/Package.swift~ deleted file mode 100644 index c9e5942b1..000000000 --- a/Trie/Package.swift~ +++ /dev/null @@ -1,5 +0,0 @@ -import PackageDescription - -let package = Package( - name: "package_name_here_and_keep_quote_marks" -) diff --git a/Trie/trie.swift~ b/Trie/trie.swift~ deleted file mode 100644 index f2b339024..000000000 --- a/Trie/trie.swift~ +++ /dev/null @@ -1,479 +0,0 @@ - -/* - A Trie (Pre-fix Tree) - - Some of the functionality of the trie makes use of the Queue implementation for this project. - - - Every node in the Trie stores a bit of information pertainining to what it references: - -Character (letter of an inserted word) - -Parent (Letter that comes before the current letter in some word) - -Children (Words that have more letters than available in the prefix) - -isAWord (Does the current letter mark the end of a known inserted word?) - -visited (Mainly for the findPrefix() function) -*/ -public class Node { - private var character: String? - private var parent: Node? - private var children: [String:Node] - private var isAWord: Bool - private var visited: Bool //only for findPrefix - - init(c: String?, p: Node?){ - self.character = c - self.children = [String:Node]() - self.isAWord = false - self.parent = p - self.visited = false - } - - /* - Function Name: char() - Input: N/A - Output: String - Functionality: Returns the associated value of the node - */ - func char() -> String { - return self.character! - } - - /* - Function Name: update - Input: String - Output: N/A - Functionality: Updates the associated value of the node - */ - func update(c: String?) { - self.character = c - } - - /* - Function Name: isLeaf - Input: N/A - Output: Bool - Functionality: Returns true if the node is a leaf node, false otherwise - */ - func isLeaf() -> Bool{ - return self.children.count == 0 - } - - /* - Function Name: getParent - Input: N/A - Output: Node - Functionality: Returns the parent node of the current node - */ - func getParent() -> Node { - return parent! - } - - /* - Function Name: setParent - Input: Node - Output: N/A - Functionality: Changes the parent of the current node to the passed node - */ - - func setParent(node: Node?) { - self.parent = node - } - - /* - Function Name: getChildAt - Input: String - Output: Node - Functionality: returns the child node that holds the specific passed letter - */ - func getChildAt(s: String) -> Node { - return self.children[s]! - } - - /* - Function Name: isValidWord - Input: N/A - Output: Bool - Functionality: Returns whether or not the current node marks the end of a valid word - */ - func isValidWord() -> Bool{ - return self.isAWord - } - - /* - Function Name: isWord - Input: N/A - Output: N/A - Functionality: the current node is indeed a word - */ - func isWord() { - self.isAWord = true - } - - /* - Function Name: isNotWord - Input: N/A - Output: N/A - Functionality: marks the current node as not a word - */ - func isNotWord() { - self.isAWord = false - } - - /* - Function Name: isRoot - Input: N/A - Output: Bool - Functionality: Returns whether or not the current node is the root of the trie - */ - func isRoot() -> Bool { - return self.character == "" - } - - /* - Function Name: numChildren - Input: N/A - Output: Int - Functionality: Returns the number of immediate letters that follow the current node - */ - func numChildren() -> Int { - return self.children.count - } - - /* - Function Name: getChildren - Input: N/A - Output: [String: Node] - Functionality: Returns the letters that immediately follow the current node's value for possible word segments that follow - */ - func getChildren() -> [String: Node] { - return self.children - } - - - /* - Function Name: printNode - Input: String, Bool - Output: N/A - Functionality: prints to the console a string representation of the current node in the trie - */ - func printNode(var indent: String, leaf: Bool) { - - print(indent, terminator: "") - if(leaf) { - print("\\-", terminator: "") - indent += " " - } - else { - print("|-", terminator: "") - indent += "| " - } - - print(self.char()) - - var i = 0 - for (_, node) in self.children { - node.printNode(indent, leaf: i == self.getChildren().count-1) - i+=1 - } - - } - -} - - -/* - The Trie class has the following attributes: - -root (the root of the trie) - -wordList (the words that currently exist in the trie) - -wordCount (the number of words in the trie) -*/ -public class Trie { - private var root: Node - private var wordList: [String] - private var wordCount = 0 - - init() { - self.root = Node(c: "", p: nil) - self.wordList = [] - } - - init(wordList: Set) { - - self.root = Node(c: "", p: nil) - self.wordList = [] - - for word in wordList { - self.insert(word) - } - } - - /* - Function Name: merge - Input: Trie - Output: Trie - Functionality: Merges two tries into one and returns the merged trie - */ - func merge(other: Trie) -> Trie{ - let newWordList = Set(self.getWords() + other.getWords()) - return Trie(wordList: newWordList) - } - - /* - Function Name: find - Input: String - Output: (Node?, Bool) - Functionality: Looks for a specific key and returns a tuple that has a reference to the node(if found) and true/false depending on if it was found - */ - func find(key: String) -> (node: Node?, found: Bool) { - var currentNode = self.root - - for c in key.characters { - if currentNode.children[String(c)] == nil { - return(nil, false) - } - currentNode = currentNode.children[String(c)]! - } - - return(currentNode, currentNode.isValidWord()) - } - - /* - Function Name: isEmpty - Input: N/A - Output: Bool - Functionality: returns true if the trie is empty, false otherwise - */ - func isEmpty() -> Bool { - return wordCount == 0 - } - - /* - Function Name: count - Input: N/A - Output: Int - Functionality: returns the number of words in the trie - */ - func count() -> Int { - return wordCount - } - - /* - Function Name: getWords - Input: N/A - Output: [String] - Functionality: returns the list of words that exist in the trie - */ - func getWords() -> [String] { - return wordList - } - - /* - Function Name: contains - Input: String - Output: Bool - Functionality: returns true if the tries has the word passed, false otherwise - */ - func contains(w: String) -> Bool { - return find(w.lowercaseString).found - } - - /* - Function Name: isPrefix - Input: String - Output: (Node?, Bool) - Functionality: returns a tuple containing a reference to the final node in the prefix (if it exists) and true/false depending on whether or not the prefix exists in the trie - */ - func isPrefix(p: String) -> (node: Node?, found: Bool) { - let prefixP = p.lowercaseString - - var currentNode = self.root - - for c in prefixP.characters { - if currentNode.children[String(c)] == nil{ - return (nil, false) - } - - currentNode = currentNode.children[String(c)]! - } - - if currentNode.numChildren() > 0 { - return (currentNode, true) - } - - return (nil, false) - } - - /* - Function Name: insert - Input: String - Output: (String, Bool) - Functionality: Inserts a word int othe trie. Returns a tuple containing the word attempted to be added, and true/false depending on whether or not the insertion was successful - */ - func insert(w: String) -> (word: String, inserted: Bool) { - - let word = w.lowercaseString - var currentNode = self.root - var length = word.characters.count - - if self.contains(word) { - return (w, false) - } - - var index = 0 - var c = Array(word.characters)[index] - - while let child = currentNode.children[String(c)] { - currentNode = child - length -= 1 - index += 1 - - if(length == 0) { - currentNode.isWord() - wordList.append(w) - wordCount += 1 - return (w, true) - } - - c = Array(word.characters)[index] - } - - let remainingChars = String(word.characters.suffix(length)) - for c in remainingChars.characters { - currentNode.children[String(c)] = Node(c: String(c), p: currentNode) - currentNode = currentNode.children[String(c)]! - } - - currentNode.isWord() - wordList.append(w) - wordCount += 1 - return (w, true) - } - - /* - Function Name: insertWords - Input: [String] - Output: ([String], Bool) - Functionality: attempts to insert all words from input array. returns a tuple containing the input array and true if some of the words were succesffuly added, false if none were added - */ - - func insertWords(wordList: [String]) -> (wordList: [String], bool: inserted){ - - var successful: Bool = false - for word in wordList { - succesful |= self.insert(word).inserted - } - - return(wordList, succesful) - } - - /* - Function Name: remove - Input: String - Output: (String, Bool) - Functionality: Removes the specified key from the trie if it exists, returns tuple containing the word attempted to be removed and true/false if the removal was succesful - */ - func remove(w: String) -> (word: String, removed: Bool){ - let word = w.lowercaseString - - if(!self.contains(w)) { - return (w, false) - } - var currentNode = self.root - - for c in word.characters { - currentNode = currentNode.getChildAt(String(c)) - } - - if currentNode.numChildren() > 0 { - currentNode.isNotWord() - } else { - var character = currentNode.char() - while(currentNode.numChildren() == 0 && !currentNode.isRoot()) { - currentNode = currentNode.getParent() - currentNode.children[character]!.setParent(nil) - currentNode.children[character]!.update(nil) - currentNode.children[character] = nil - character = currentNode.char() - } - } - - wordCount -= 1 - - var index = 0 - for item in wordList{ - if item == w { - wordList.removeAtIndex(index) - } - index += 1 - } - - return (w, true) - } - - /* - Function Name: findPrefix - Input: String - Output: [String] - Functionality: returns a list containing all words in the trie that have the specified prefix - */ - func findPrefix(p: String) -> [String] { - - if !self.isPrefix(p).found { - return [] - } - - var q: Queue = Queue() - var n: Node = self.isPrefix(p).node! - - var wordsWithPrefix: [String] = [] - var word = p - var tmp = "" - q.enqueue(n) - - while let current = q.dequeue() { - for (char, child) in current.getChildren() { - if(!child.visited) { - q.enqueue(child) - child.visited = true - if(child.isValidWord()) { - var currentNode = child - while currentNode !== n { - tmp += currentNode.char() - currentNode = currentNode.getParent() - } - tmp = String(tmp.characters.reverse()) - wordsWithPrefix.append(word + tmp) - tmp = "" - } - } - } - } - - - return wordsWithPrefix - } - - - /* - Function Name: removeAll - Input: N/A - Output: N/A - Functionality: removes all nodes in the trie using remove as a subroutine - */ - func removeAll() { - for word in wordList { - self.remove(word) - } - } - - - /* - Function Name: printTrie - Input: N/A - Output: N/A - Functionality: prints all the nodes of the trie to console in a nice and easy to understand format - */ - func printTrie() { - self.root.printNode("", leaf: true) - } - -} From d5648e1ceceee4caeee56750da670f5162a9278c Mon Sep 17 00:00:00 2001 From: Christian Encarnacion Date: Thu, 5 May 2016 21:59:06 -0400 Subject: [PATCH 0347/1679] Update trie.swift --- Trie/trie.swift | 8 -------- 1 file changed, 8 deletions(-) diff --git a/Trie/trie.swift b/Trie/trie.swift index 352ca26cc..b62d3f598 100644 --- a/Trie/trie.swift +++ b/Trie/trie.swift @@ -31,14 +31,6 @@ public struct Queue { return element } - - public func peek() -> T? { - if isEmpty { - return nil - } else { - return array[head] - } - } } /* A Trie (Pre-fix Tree) From 1649935a6d946c8ff5781cb5730c31acec50a0c6 Mon Sep 17 00:00:00 2001 From: Jayson Tung Date: Thu, 5 May 2016 22:05:41 -0400 Subject: [PATCH 0348/1679] Remove unnecessary files --- .Rhistory | 0 README.markdown | 1 - README.markdown~ | 212 ------------------------------------------- Radix-Sort/radixSort | Bin 20310 -> 0 bytes 4 files changed, 213 deletions(-) delete mode 100644 .Rhistory delete mode 100644 README.markdown~ delete mode 100755 Radix-Sort/radixSort diff --git a/.Rhistory b/.Rhistory deleted file mode 100644 index e69de29bb..000000000 diff --git a/README.markdown b/README.markdown index 480d8f26a..bbc10fb8d 100644 --- a/README.markdown +++ b/README.markdown @@ -210,4 +210,3 @@ Other algorithm repositories: All content is licensed under the terms of the MIT open source license. [![Build Status](https://travis-ci.org/hollance/swift-algorithm-club.svg?branch=master)](https://travis-ci.org/hollance/swift-algorithm-club) - diff --git a/README.markdown~ b/README.markdown~ deleted file mode 100644 index bbc10fb8d..000000000 --- a/README.markdown~ +++ /dev/null @@ -1,212 +0,0 @@ -# Welcome to the Swift Algorithm Club! - -Here you'll find implementations of popular algorithms and data structures in everyone's favorite new language Swift, with detailed explanations of how they work. - -If you're a computer science student who needs to learn this stuff for exams -- or if you're a self-taught programmer who wants to brush up on the theory behind your craft -- you've come to the right place! - -The goal of this project is to **explain how algorithms work**. The focus is on clarity and readability of the code, not on making a reusable library that you can drop into your own projects. That said, most of the code should be ready for production use but you may need to tweak it to fit into your own codebase. - -All code is compatible with **Xcode 7.3** and **Swift 2.2**. We'll keep this updated with the latest version of Swift. - -This is a work in progress. More algorithms will be added soon. :-) - -:heart_eyes: **Suggestions and contributions are welcome!** :heart_eyes: - -## Important links - -[What are algorithms and data structures?](What are Algorithms.markdown) Pancakes! - -[Why learn algorithms?](Why Algorithms.markdown) Worried this isn't your cup of tea? Then read this. - -[Big-O notation](Big-O Notation.markdown). We often say things like, "This algorithm is **O(n)**." If you don't know what that means, read this first. - -[Algorithm design techniques](Algorithm Design.markdown). How do you create your own algorithms? - -[How to contribute](How to Contribute.markdown). Report an issue to leave feedback, or submit a pull request. - -## Where to start? - -If you're new to algorithms and data structures, here are a few good ones to start out with: - -- [Stack](Stack/) -- [Queue](Queue/) -- [Insertion Sort](Insertion Sort/) -- [Binary Search](Binary Search/) and [Binary Search Tree](Binary Search Tree/) -- [Merge Sort](Merge Sort/) -- [Boyer-Moore string search](Boyer-Moore/) - -## The algorithms - -### Searching - -- [Linear Search](Linear Search/). Find an element in an array. -- [Binary Search](Binary Search/). Quickly find elements in a sorted array. -- [Count Occurrences](Count Occurrences/). Count how often a value appears in an array. -- [Select Minimum / Maximum](Select Minimum Maximum). Find the minimum/maximum value in an array. -- [k-th Largest Element](Kth Largest Element/). Find the *k*-th largest element in an array, such as the median. -- [Selection Sampling](Selection Sampling/). Randomly choose a bunch of items from a collection. -- [Union-Find](Union-Find/). Keeps track of disjoint sets and lets you quickly merge them. - -### String Search - -- [Brute-Force String Search](Brute-Force String Search/). A naive method. -- [Boyer-Moore](Boyer-Moore/). A fast method to search for substrings. It skips ahead based on a look-up table, to avoid looking at every character in the text. -- Rabin-Karp -- [Longest Common Subsequence](Longest Common Subsequence/). Find the longest sequence of characters that appear in the same order in both strings. - -### Sorting - -It's fun to see how sorting algorithms work, but in practice you'll almost never have to provide your own sorting routines. Swift's own `sort()` is more than up to the job. But if you're curious, read on... - -Basic sorts: - -- [Insertion Sort](Insertion Sort/) -- [Selection Sort](Selection Sort/) -- [Shell Sort](Shell Sort/) - -Fast sorts: - -- [Quicksort](Quicksort/) -- [Merge Sort](Merge Sort/) -- [Heap Sort](Heap Sort/) - -Special-purpose sorts: - -- [Bucket Sort](Bucket Sort/) :construction: -- [Counting Sort](Counting Sort/) -- Radix Sort -- [Topological Sort](Topological Sort/) - -Bad sorting algorithms (don't use these!): - -- [Bubble Sort](Bubble Sort/) - -### Compression - -- [Run-Length Encoding (RLE)](Run-Length Encoding/). Store repeated values as a single byte and a count. -- [Huffman Coding](Huffman Coding/). Store more common elements using a smaller number of bits. - -### Miscellaneous - -- [Shuffle](Shuffle/). Randomly rearranges the contents of an array. - -### Mathematics - -- [Greatest Common Divisor (GCD)](GCD/). Special bonus: the least common multiple. -- [Permutations and Combinations](Combinatorics/). Get your combinatorics on! -- [Shunting Yard Algorithm](Shunting Yard/). Convert infix expressions to postfix. -- Statistics - -### Machine learning - -- [k-Means Clustering](K-Means/). Unsupervised classifier that partitions data into *k* clusters. -- k-Nearest Neighbors -- Linear Regression -- Logistic Regression -- Neural Networks -- PageRank - -## Data structures - -The choice of data structure for a particular task depends on a few things. - -First, there is the shape of your data and the kinds of operations that you'll need to perform on it. If you want to look up objects by a key you need some kind of dictionary; if your data is hierarchical in nature you want a tree structure of some sort; if your data is sequential you want a stack or queue. - -Second, it matters what particular operations you'll be performing most, as certain data structures are optimized for certain actions. For example, if you often need to find the most important object in a collection, then a heap or priority queue is more optimal than a plain array. - -Most of the time using just the built-in `Array`, `Dictionary`, and `Set` types is sufficient, but sometimes you may want something more fancy... - -### Variations on arrays - -- [Array2D](Array2D/). A two-dimensional array with fixed dimensions. Useful for board games. -- [Bit Set](Bit Set/). A fixed-size sequence of *n* bits. -- [Fixed Size Array](Fixed Size Array/). When you know beforehand how large your data will be, it might be more efficient to use an old-fashioned array with a fixed size. -- [Ordered Array](Ordered Array/). An array that is always sorted. - -### Queues - -- [Stack](Stack/). Last-in, first-out! -- [Queue](Queue/). First-in, first-out! -- [Deque](Deque/). A double-ended queue. -- [Priority Queue](Priority Queue). A queue where the most important element is always at the front. -- [Bounded Priority Queue](Bounded Priority Queue). A queue that is bounded to have a limited number of elements. :construction: -- [Ring Buffer](Ring Buffer/). Also known as a circular buffer. An array of a certain size that conceptually wraps around back to the beginning. - -### Lists - -- [Linked List](Linked List/). A sequence of data items connected through links. Covers both singly and doubly linked lists. -- Skip List - -### Trees - -- [Tree](Tree/). A general-purpose tree structure. -- [Binary Tree](Binary Tree/). A tree where each node has at most two children. -- [Binary Search Tree (BST)](Binary Search Tree/). A binary tree that orders its nodes in a way that allows for fast queries. -- [AVL Tree](AVL Tree/). A binary search tree that balances itself using rotations. :construction: -- Red-Black Tree -- Splay Tree -- Threaded Binary Tree -- [Segment Tree](Segment Tree/). Can quickly compute a function over a portion of an array. -- kd-Tree -- [Heap](Heap/). A binary tree stored in an array, so it doesn't use pointers. Makes a great priority queue. -- Fibonacci Heap -- Trie -- [B-Tree](B Tree/) :construction: - -### Hashing - -- [Hash Table](Hash Table/). Allows you to store and retrieve objects by a key. This is how the dictionary type is usually implemented. -- Hash Functions - -### Sets - -- [Bloom Filter](Bloom Filter/). A constant-memory data structure that probabilistically tests whether an element is in a set. -- [Hash Set](Hash Set/). A set implemented using a hash table. -- Multiset -- [Ordered Set](Ordered Set/). A set where the order of items matters. - -### Graphs - -- [Graph](Graph/) -- [Breadth-First Search (BFS)](Breadth-First Search/) -- [Depth-First Search (DFS)](Depth-First Search/) -- [Shortest Path](Shortest Path %28Unweighted%29/) on an unweighted tree -- [Minimum Spanning Tree](Minimum Spanning Tree %28Unweighted%29/) on an unweighted tree -- All Paths - -## Puzzles - -A lot of software developer interview questions consist of algorithmic puzzles. Here is a small selection of fun ones. For more puzzles (with answers), see [here](http://elementsofprogramminginterviews.com/) and [here](http://www.crackingthecodinginterview.com). - -- [Two-Sum Problem](Two-Sum Problem/) -- [Fizz Buzz](Fizz Buzz/) -- [Monty Hall Problem](Monty Hall Problem/) - -## Learn more! - -For more information, check out these great books: - -- [Introduction to Algorithms](https://mitpress.mit.edu/books/introduction-algorithms) by Cormen, Leiserson, Rivest, Stein -- [The Algorithm Design Manual](http://www.algorist.com) by Skiena -- [Elements of Programming Interviews](http://elementsofprogramminginterviews.com) by Aziz, Lee, Prakash -- [Algorithms](http://www.cs.princeton.edu/~rs/) by Sedgewick - -The following books are available for free online: - -- [Algorithms](http://www.beust.com/algorithms.pdf) by Dasgupta, Papadimitriou, Vazirani -- [Algorithms, Etc.](http://jeffe.cs.illinois.edu/teaching/algorithms/) by Erickson -- [Algorithms + Data Structures = Programs](http://www.ethoberon.ethz.ch/WirthPubl/AD.pdf) by Wirth -- Algorithms and Data Structures: The Basic Toolbox by Mehlhorn and Sanders -- [Wikibooks: Algorithms and Implementations](https://en.wikibooks.org/wiki/Algorithm_Implementation) - -Other algorithm repositories: - -- [EKAlgorithms](https://github.com/EvgenyKarkan/EKAlgorithms). A great collection of algorithms in Objective-C. -- [@lorentey](https://github.com/lorentey/). Production-quality Swift implementations of common algorithms and data structures. -- [Rosetta Code](http://rosettacode.org). Implementations in pretty much any language you can think of. - -## License - -All content is licensed under the terms of the MIT open source license. - -[![Build Status](https://travis-ci.org/hollance/swift-algorithm-club.svg?branch=master)](https://travis-ci.org/hollance/swift-algorithm-club) diff --git a/Radix-Sort/radixSort b/Radix-Sort/radixSort deleted file mode 100755 index 6ebfbe215703f5c207e9c454062125f9e1fc466d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20310 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 QqHj!kR$tua|5y(DADjR>DF6Tf From a125a854f5832136f561e7bddf09b31f5e4d3ce3 Mon Sep 17 00:00:00 2001 From: Thukor Date: Thu, 5 May 2016 22:12:31 -0400 Subject: [PATCH 0349/1679] Got rid of binary --- Radix-Sort/radixSort | Bin 20310 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100755 Radix-Sort/radixSort diff --git a/Radix-Sort/radixSort b/Radix-Sort/radixSort deleted file mode 100755 index 6ebfbe215703f5c207e9c454062125f9e1fc466d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20310 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 QqHj!kR$tua|5y(DADjR>DF6Tf From ea555cc06ca40fd8052664dcfc1a2cb2e8a7e9d9 Mon Sep 17 00:00:00 2001 From: Thukor Date: Thu, 5 May 2016 22:39:05 -0400 Subject: [PATCH 0350/1679] Fixed a logic bug --- Trie/trie.swift | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Trie/trie.swift b/Trie/trie.swift index b62d3f598..f50363749 100644 --- a/Trie/trie.swift +++ b/Trie/trie.swift @@ -4,7 +4,7 @@ public struct Queue { private var array = [T?]() private var head = 0 - + public var isEmpty: Bool { return count == 0 } @@ -12,11 +12,11 @@ public struct Queue { public var count: Int { return array.count - head } - + public mutating func enqueue(element: T) { array.append(element) } - + public mutating func dequeue() -> T? { guard head < array.count, let element = array[head] else { return nil } @@ -28,7 +28,7 @@ public struct Queue { array.removeFirst(head) head = 0 } - + return element } } @@ -388,11 +388,11 @@ public class Trie { Functionality: attempts to insert all words from input array. returns a tuple containing the input array and true if some of the words were succesffuly added, false if none were added */ - func insertWords(wordList: [String]) -> (wordList: [String], bool: inserted){ + func insertWords(wordList: [String]) -> (wordList: [String], inserted: Bool){ - var successful: Bool = false + var succesful: Bool = false for word in wordList { - succesful |= self.insert(word).inserted + succesful = self.insert(word).inserted || succesful } return(wordList, succesful) From fc76bafd2452eabb6f8462eb966c6016be1125fd Mon Sep 17 00:00:00 2001 From: Matthijs Hollemans Date: Fri, 6 May 2016 11:03:05 +0200 Subject: [PATCH 0351/1679] Cleanup of text and code We're not using Swift 3 yet. ;-) --- README.markdown | 2 +- .../Images/radixtree.png | Bin Radix Tree/README.markdown | 72 ++++ .../RadixTree.playground/Contents.swift | 6 +- .../Sources/RadixTree.swift | 385 ++++++++++++++++++ .../contents.xcplayground | 4 + Radix Tree/RadixTree.swift | 385 ++++++++++++++++++ Radix-Tree/README.markdown | 46 --- Radix-Tree/RadixTree.swift | 374 ----------------- 9 files changed, 850 insertions(+), 424 deletions(-) rename {Radix-Tree => Radix Tree}/Images/radixtree.png (100%) create mode 100644 Radix Tree/README.markdown rename Radix-Tree/main.swift => Radix Tree/RadixTree.playground/Contents.swift (94%) create mode 100644 Radix Tree/RadixTree.playground/Sources/RadixTree.swift create mode 100644 Radix Tree/RadixTree.playground/contents.xcplayground create mode 100644 Radix Tree/RadixTree.swift delete mode 100644 Radix-Tree/README.markdown delete mode 100644 Radix-Tree/RadixTree.swift diff --git a/README.markdown b/README.markdown index 3c441f428..51aa0a60a 100644 --- a/README.markdown +++ b/README.markdown @@ -152,7 +152,7 @@ Most of the time using just the built-in `Array`, `Dictionary`, and `Set` types - Fibonacci Heap - Trie - [B-Tree](B Tree/) :construction: -- [Radix Tree](Radix-Tree/) :construction: +- [Radix Tree](Radix Tree/) :construction: ### Hashing diff --git a/Radix-Tree/Images/radixtree.png b/Radix Tree/Images/radixtree.png similarity index 100% rename from Radix-Tree/Images/radixtree.png rename to Radix Tree/Images/radixtree.png diff --git a/Radix Tree/README.markdown b/Radix Tree/README.markdown new file mode 100644 index 000000000..3fb1ab986 --- /dev/null +++ b/Radix Tree/README.markdown @@ -0,0 +1,72 @@ +# Radix Tree + +A radix tree is a [tree](../Tree/) where a node can have any number of children. Each edge leading from a node to a child has a label (usually a string). A radix tree is often used to store strings or IP addresses. By traversing from the root to any leaf in the tree, concatenating all the labels of edges along the way, you can find any string. + +This is an example of a radix tree (image from wikipedia.org): + +![](Images/radixtree.png) + +## Implemenation + +The radix tree is represented by a `RadixTree` object. This class has one member variable, `root`, of type `Root`. The `Root` is the object at the top of every `RadixTree`. + +Every other node is of type `Edge` and is a child (or child of a child, etc.) of the root. + +The difference between `Edge` and `Root` is that edges have a label (of type `String`) and a reference to a parent node. + +This approach is a little different from the conventional way of creating tree data structures but is easier to wrap your head around (see the picture above). + +## Operations + +Typical operations on a radix tree are: + +- lookup +- insertion +- deletion +- find predecessor +- find successor +- find all strings with common prefix + +The running time of lookup, insertion, and deletion is **O(k)** where **k** is the length of the key. This is different from most trees because these operations usually run in **O(log n)** time where **n** is the number of nodes in the tree. + +### Lookup + +The `find()` function returns true if the string you are searching for is in the tree and false if it is not. + +Every `RadixTree` contains at the very least the empty string `""` so `find("")` will always return true. + +A string is considered "in the tree" if the text you are searching for is a concatenation of `Edge` labels while traversing downwards, or a prefix of that concatenation. + +For example, if you look at the example tree above, `find("roma")` will return true because it is a prefix of the traversal `"r" -> "om" -> "an"`. + +On the other hand, `find("romans")` will return false. + +### Insertion + +The `insert()` function lets you add new strings to the radix tree. + +This function returns true if the string you are trying to insert was successfully inserted into the `RadixTree` and false if the string is already in the tree. + +### Deletion + +The `remove()` removes a string from the tree. When a string is removed, any other strings that have a prefix of the removed string are removed as well. + +For example, `remove("rom")` will also remove `"roman"`, `"rome"`, and `"romulus"` if those strings are in the tree as well. Calling `remove("")` will remove all strings in the tree. + +### printTree() + +You can use the `printTree()` function to visualize the tree. This function is a little buggy and not perfect yet but gets the job done thus far. + +### Helper functions + +The `sharedPrefix()` function is a non-member function in the **RadixTree.swift** file. It takes in two `String` objects and returns the shared prefix between them. + +For example, `sharedPrefix("apples", "oranges")` will return `""`, and `sharedPrefix("court", "coral")` will return `"co"`. + +This function is used in the implementation of the `find()`, `insert()`, and `remove()` functions. + +## See also + +[Radix Tree - Wikipedia](https://en.wikipedia.org/wiki/Radix_tree) + +*Written for Swift Algorithm Club by Steven Scally* diff --git a/Radix-Tree/main.swift b/Radix Tree/RadixTree.playground/Contents.swift similarity index 94% rename from Radix-Tree/main.swift rename to Radix Tree/RadixTree.playground/Contents.swift index 6495e5e1b..e161e48a2 100644 --- a/Radix-Tree/main.swift +++ b/Radix Tree/RadixTree.playground/Contents.swift @@ -30,7 +30,7 @@ radixWiki.insert("rubicunduses") radixWiki.printTree() -print("FIND TESTS") +print("\n\nFIND TESTS") print(radixWiki.find("courts")) // false print(radixWiki.find("r")) // true print(radixWiki.find("ro")) // true @@ -41,7 +41,7 @@ print(radixWiki.find("romane")) // true print(radixWiki.find("romans")) // false print(radixWiki.find("steve")) // true -print("REMOVE TESTS") +print("\n\nREMOVE TESTS") print(radixWiki.remove("c")) radixWiki.printTree() @@ -52,4 +52,4 @@ radixWiki.printTree() print(radixWiki.remove("stevenson")) print(radixWiki.remove("")) -radixWiki.printTree() \ No newline at end of file +radixWiki.printTree() diff --git a/Radix Tree/RadixTree.playground/Sources/RadixTree.swift b/Radix Tree/RadixTree.playground/Sources/RadixTree.swift new file mode 100644 index 000000000..8b11e2508 --- /dev/null +++ b/Radix Tree/RadixTree.playground/Sources/RadixTree.swift @@ -0,0 +1,385 @@ +import Foundation + +// The root is the top of the Radix Tree +public class Root { + var children: [Edge] + + public init() { + children = [Edge]() + } + + // Returns the length (in number of edges) of the longest traversal down the tree. + public func height() -> Int { + // Base case: no children: the tree has a height of 1 + if children.count == 0 { + return 1 + } + // Recursion: find the max height of a root's child and return 1 + that max + else { + var max = 1 + for c in children { + if c.height() > max { + max = c.height() + } + } + return 1 + max + } + } + + // Returns how far down in the tree a Root/Edge is. + // A root's level is always 0. + public func level() -> Int { + return 0 + } + + // Prints the tree for debugging/visualization purposes. + public func printRoot() { + // Print the first half of the children + if (children.count > 1) { + for c in 0...children.count/2-1 { + children[c].printEdge() + print("|") + } + } + else if children.count > 0 { + children[0].printEdge() + } + // Then print the root + print("ROOT") + // Print the second half of the children + if children.count > 1 { + for c in children.count/2...children.count-1 { + children[c].printEdge() + print("|") + } + } + print() + } +} + +// Edges are what actually store the Strings in the tree +public class Edge: Root { + var parent: Root? + var label: String + + public init(_ label: String) { + self.label = label + super.init() + } + + public override func level() -> Int { + // Recurse up the tree incrementing level by one until the root is reached + if parent != nil { + return 1 + parent!.level() + } + // If an edge has no parent, it's level is one + // NOTE: THIS SHOULD NEVER HAPPEN AS THE ROOT IS ALWAYS THE TOP OF THE TREE + else { + return 1 + } + } + + // Erases a specific edge (and all edges below it in the tree). + public func erase() { + self.parent = nil + if children.count > 0 { + // For each child, erase it, then remove it from the children array. + for _ in 0...children.count-1 { + children[0].erase() + children.removeAtIndex(0) + } + } + } + + // Prints the tree for debugging/visualization purposes. + public func printEdge() { + // Print the first half of the edge's children + if children.count > 1 { + for c in 0...children.count/2-1 { + children[c].printEdge() + } + } + else if children.count > 0 { + children[0].printEdge() + } + // Tab over once up to the edge's level + for x in 1...level() { + if x == level() { + print("|------>", terminator: "") + } + else { + print("| ", terminator: "") + } + } + print(label) + // Print the second half of the edge's children + if children.count == 0 { + for _ in 1...level() { + print("| ", terminator: "") + } + print() + } + if children.count > 1 { + for c in children.count/2...children.count-1 { + children[c].printEdge() + } + } + } +} + +public class RadixTree { + var root: Root + + public init() { + root = Root() + } + + // Returns the height of the tree by calling the root's height function. + public func height() -> Int { + return root.height() - 1 + } + + // Inserts a string into the tree. + public func insert(str: String) -> Bool { + //Account for a blank input. The empty string is already in the tree. + if str == "" { + return false + } + + // searchStr is the parameter of the function + // it will be substringed as the function traverses down the tree + var searchStr = str + + // currEdge is the current Edge (or Root) in question + var currEdge = root + + while (true) { + var found = false + + // If the current Edge has no children then the remaining searchStr is + // created as a child + if currEdge.children.count == 0 { + let newEdge = Edge(searchStr) + currEdge.children.append(newEdge) + newEdge.parent = currEdge + return true + } + + // Loop through all of the children + for e in currEdge.children { + // Get the shared prefix between the child in question and the + // search string + let shared = sharedPrefix(searchStr, e.label) + var index = shared.startIndex + + // If the search string is equal to the shared string, + // the string already exists in the tree + if searchStr == shared { + return false + } + + // If the child's label is equal to the shared string, you have to + // traverse another level down the tree, so substring the search + // string, break the loop, and run it back + else if shared == e.label { + currEdge = e + var tempIndex = searchStr.startIndex + for _ in 1...shared.characters.count { + tempIndex = tempIndex.successor() + } + searchStr = searchStr.substringFromIndex(tempIndex) + found = true + break + } + + // If the child's label and the search string share a partial prefix, + // then both the label and the search string need to be substringed + // and a new branch needs to be created + else if shared.characters.count > 0 { + var labelIndex = e.label.characters.startIndex + + // Create index objects and move them to after the shared prefix + for _ in 1...shared.characters.count { + index = index.successor() + labelIndex = labelIndex.successor() + } + + // Substring both the search string and the label from the shared prefix + searchStr = searchStr.substringFromIndex(index) + e.label = e.label.substringFromIndex(labelIndex) + + // Create 2 new edges and update parent/children values + let newEdge = Edge(e.label) + e.label = shared + for ec in e.children { + newEdge.children.append(ec) + } + newEdge.parent = e + e.children.removeAll() + for nec in newEdge.children { + nec.parent = newEdge + } + e.children.append(newEdge) + let newEdge2 = Edge(searchStr) + newEdge2.parent = e + e.children.append(newEdge2) + return true + } + // If they don't share a prefix, go to next child + } + + // If none of the children share a prefix, you have to create a new child + if !found { + let newEdge = Edge(searchStr) + currEdge.children.append(newEdge) + newEdge.parent = currEdge + return true + } + } + } + + // Tells you if a string is in the tree + public func find(str: String) -> Bool { + // A radix tree always contains the empty string + if str == "" { + return true + } + // If there are no children then the string cannot be in the tree + else if root.children.count == 0 { + return false + } + var searchStr = str + var currEdge = root + while (true) { + var found = false + // Loop through currEdge's children + for c in currEdge.children { + // First check if the search string and the child's label are equal + // if so the string is in the tree, return true + if searchStr == c.label { + return true + } + + // If that is not true, find the shared string b/t the search string + // and the label + let shared = sharedPrefix(searchStr, c.label) + + // If the shared string is equal to the label, update the curent node, + // break the loop, and run it back + if shared == c.label { + currEdge = c + var tempIndex = searchStr.startIndex + for _ in 1...shared.characters.count { + tempIndex = tempIndex.successor() + } + searchStr = searchStr.substringFromIndex(tempIndex) + found = true + break + } + + // If the shared string is empty, go to the next child + else if shared.characters.count == 0 { + continue + } + + // If the shared string matches the search string, return true + else if shared == searchStr { + return true + } + + // If the search string and the child's label only share some characters, + // the string is not in the tree, return false + else if shared[shared.startIndex] == c.label[c.label.startIndex] && + shared.characters.count < c.label.characters.count { + return false + } + } + + // If nothing was found, return false + if !found { + return false + } + } + } + + // Removes a string from the tree + public func remove(str: String) -> Bool { + // Removing the empty string removes everything in the tree + if str == "" { + for c in root.children { + c.erase() + root.children.removeAtIndex(0) + } + return true + } + // If the tree is empty, you cannot remove anything + else if root.children.count == 0 { + return false + } + + var searchStr = str + var currEdge = root + while (true) { + var found = false + // If currEdge has no children, then the searchStr is not in the tree + if currEdge.children.count == 0 { + return false + } + + // Loop through the children + for c in 0...currEdge.children.count-1 { + // If the child's label matches the search string, remove that child + // and everything below it in the tree + if currEdge.children[c].label == searchStr { + currEdge.children[c].erase() + currEdge.children.removeAtIndex(c) + return true + } + + // Find the shared string + let shared = sharedPrefix(searchStr, currEdge.children[c].label) + + // If the shared string is equal to the child's string, go down a level + if shared == currEdge.children[c].label { + currEdge = currEdge.children[c] + var tempIndex = searchStr.startIndex + for _ in 1...shared.characters.count { + tempIndex = tempIndex.successor() + } + searchStr = searchStr.substringFromIndex(tempIndex) + found = true + break + } + } + + // If there is no match, then the searchStr is not in the tree + if !found { + return false + } + } + } + + // Prints the tree by calling the root's print function + public func printTree() { + root.printRoot() + } +} + +// Returns the prefix that is shared between the two input strings +// i.e. sharedPrefix("court", "coral") -> "co" +public func sharedPrefix(str1: String, _ str2: String) -> String { + var temp = "" + var c1 = str1.characters.startIndex + var c2 = str2.characters.startIndex + for _ in 0...min(str1.characters.count-1, str2.characters.count-1) { + if str1[c1] == str2[c2] { + temp.append( str1[c1] ) + c1 = c1.successor() + c2 = c2.successor() + } + else { + return temp + } + } + return temp +} diff --git a/Radix Tree/RadixTree.playground/contents.xcplayground b/Radix Tree/RadixTree.playground/contents.xcplayground new file mode 100644 index 000000000..06828af92 --- /dev/null +++ b/Radix Tree/RadixTree.playground/contents.xcplayground @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Radix Tree/RadixTree.swift b/Radix Tree/RadixTree.swift new file mode 100644 index 000000000..8b11e2508 --- /dev/null +++ b/Radix Tree/RadixTree.swift @@ -0,0 +1,385 @@ +import Foundation + +// The root is the top of the Radix Tree +public class Root { + var children: [Edge] + + public init() { + children = [Edge]() + } + + // Returns the length (in number of edges) of the longest traversal down the tree. + public func height() -> Int { + // Base case: no children: the tree has a height of 1 + if children.count == 0 { + return 1 + } + // Recursion: find the max height of a root's child and return 1 + that max + else { + var max = 1 + for c in children { + if c.height() > max { + max = c.height() + } + } + return 1 + max + } + } + + // Returns how far down in the tree a Root/Edge is. + // A root's level is always 0. + public func level() -> Int { + return 0 + } + + // Prints the tree for debugging/visualization purposes. + public func printRoot() { + // Print the first half of the children + if (children.count > 1) { + for c in 0...children.count/2-1 { + children[c].printEdge() + print("|") + } + } + else if children.count > 0 { + children[0].printEdge() + } + // Then print the root + print("ROOT") + // Print the second half of the children + if children.count > 1 { + for c in children.count/2...children.count-1 { + children[c].printEdge() + print("|") + } + } + print() + } +} + +// Edges are what actually store the Strings in the tree +public class Edge: Root { + var parent: Root? + var label: String + + public init(_ label: String) { + self.label = label + super.init() + } + + public override func level() -> Int { + // Recurse up the tree incrementing level by one until the root is reached + if parent != nil { + return 1 + parent!.level() + } + // If an edge has no parent, it's level is one + // NOTE: THIS SHOULD NEVER HAPPEN AS THE ROOT IS ALWAYS THE TOP OF THE TREE + else { + return 1 + } + } + + // Erases a specific edge (and all edges below it in the tree). + public func erase() { + self.parent = nil + if children.count > 0 { + // For each child, erase it, then remove it from the children array. + for _ in 0...children.count-1 { + children[0].erase() + children.removeAtIndex(0) + } + } + } + + // Prints the tree for debugging/visualization purposes. + public func printEdge() { + // Print the first half of the edge's children + if children.count > 1 { + for c in 0...children.count/2-1 { + children[c].printEdge() + } + } + else if children.count > 0 { + children[0].printEdge() + } + // Tab over once up to the edge's level + for x in 1...level() { + if x == level() { + print("|------>", terminator: "") + } + else { + print("| ", terminator: "") + } + } + print(label) + // Print the second half of the edge's children + if children.count == 0 { + for _ in 1...level() { + print("| ", terminator: "") + } + print() + } + if children.count > 1 { + for c in children.count/2...children.count-1 { + children[c].printEdge() + } + } + } +} + +public class RadixTree { + var root: Root + + public init() { + root = Root() + } + + // Returns the height of the tree by calling the root's height function. + public func height() -> Int { + return root.height() - 1 + } + + // Inserts a string into the tree. + public func insert(str: String) -> Bool { + //Account for a blank input. The empty string is already in the tree. + if str == "" { + return false + } + + // searchStr is the parameter of the function + // it will be substringed as the function traverses down the tree + var searchStr = str + + // currEdge is the current Edge (or Root) in question + var currEdge = root + + while (true) { + var found = false + + // If the current Edge has no children then the remaining searchStr is + // created as a child + if currEdge.children.count == 0 { + let newEdge = Edge(searchStr) + currEdge.children.append(newEdge) + newEdge.parent = currEdge + return true + } + + // Loop through all of the children + for e in currEdge.children { + // Get the shared prefix between the child in question and the + // search string + let shared = sharedPrefix(searchStr, e.label) + var index = shared.startIndex + + // If the search string is equal to the shared string, + // the string already exists in the tree + if searchStr == shared { + return false + } + + // If the child's label is equal to the shared string, you have to + // traverse another level down the tree, so substring the search + // string, break the loop, and run it back + else if shared == e.label { + currEdge = e + var tempIndex = searchStr.startIndex + for _ in 1...shared.characters.count { + tempIndex = tempIndex.successor() + } + searchStr = searchStr.substringFromIndex(tempIndex) + found = true + break + } + + // If the child's label and the search string share a partial prefix, + // then both the label and the search string need to be substringed + // and a new branch needs to be created + else if shared.characters.count > 0 { + var labelIndex = e.label.characters.startIndex + + // Create index objects and move them to after the shared prefix + for _ in 1...shared.characters.count { + index = index.successor() + labelIndex = labelIndex.successor() + } + + // Substring both the search string and the label from the shared prefix + searchStr = searchStr.substringFromIndex(index) + e.label = e.label.substringFromIndex(labelIndex) + + // Create 2 new edges and update parent/children values + let newEdge = Edge(e.label) + e.label = shared + for ec in e.children { + newEdge.children.append(ec) + } + newEdge.parent = e + e.children.removeAll() + for nec in newEdge.children { + nec.parent = newEdge + } + e.children.append(newEdge) + let newEdge2 = Edge(searchStr) + newEdge2.parent = e + e.children.append(newEdge2) + return true + } + // If they don't share a prefix, go to next child + } + + // If none of the children share a prefix, you have to create a new child + if !found { + let newEdge = Edge(searchStr) + currEdge.children.append(newEdge) + newEdge.parent = currEdge + return true + } + } + } + + // Tells you if a string is in the tree + public func find(str: String) -> Bool { + // A radix tree always contains the empty string + if str == "" { + return true + } + // If there are no children then the string cannot be in the tree + else if root.children.count == 0 { + return false + } + var searchStr = str + var currEdge = root + while (true) { + var found = false + // Loop through currEdge's children + for c in currEdge.children { + // First check if the search string and the child's label are equal + // if so the string is in the tree, return true + if searchStr == c.label { + return true + } + + // If that is not true, find the shared string b/t the search string + // and the label + let shared = sharedPrefix(searchStr, c.label) + + // If the shared string is equal to the label, update the curent node, + // break the loop, and run it back + if shared == c.label { + currEdge = c + var tempIndex = searchStr.startIndex + for _ in 1...shared.characters.count { + tempIndex = tempIndex.successor() + } + searchStr = searchStr.substringFromIndex(tempIndex) + found = true + break + } + + // If the shared string is empty, go to the next child + else if shared.characters.count == 0 { + continue + } + + // If the shared string matches the search string, return true + else if shared == searchStr { + return true + } + + // If the search string and the child's label only share some characters, + // the string is not in the tree, return false + else if shared[shared.startIndex] == c.label[c.label.startIndex] && + shared.characters.count < c.label.characters.count { + return false + } + } + + // If nothing was found, return false + if !found { + return false + } + } + } + + // Removes a string from the tree + public func remove(str: String) -> Bool { + // Removing the empty string removes everything in the tree + if str == "" { + for c in root.children { + c.erase() + root.children.removeAtIndex(0) + } + return true + } + // If the tree is empty, you cannot remove anything + else if root.children.count == 0 { + return false + } + + var searchStr = str + var currEdge = root + while (true) { + var found = false + // If currEdge has no children, then the searchStr is not in the tree + if currEdge.children.count == 0 { + return false + } + + // Loop through the children + for c in 0...currEdge.children.count-1 { + // If the child's label matches the search string, remove that child + // and everything below it in the tree + if currEdge.children[c].label == searchStr { + currEdge.children[c].erase() + currEdge.children.removeAtIndex(c) + return true + } + + // Find the shared string + let shared = sharedPrefix(searchStr, currEdge.children[c].label) + + // If the shared string is equal to the child's string, go down a level + if shared == currEdge.children[c].label { + currEdge = currEdge.children[c] + var tempIndex = searchStr.startIndex + for _ in 1...shared.characters.count { + tempIndex = tempIndex.successor() + } + searchStr = searchStr.substringFromIndex(tempIndex) + found = true + break + } + } + + // If there is no match, then the searchStr is not in the tree + if !found { + return false + } + } + } + + // Prints the tree by calling the root's print function + public func printTree() { + root.printRoot() + } +} + +// Returns the prefix that is shared between the two input strings +// i.e. sharedPrefix("court", "coral") -> "co" +public func sharedPrefix(str1: String, _ str2: String) -> String { + var temp = "" + var c1 = str1.characters.startIndex + var c2 = str2.characters.startIndex + for _ in 0...min(str1.characters.count-1, str2.characters.count-1) { + if str1[c1] == str2[c2] { + temp.append( str1[c1] ) + c1 = c1.successor() + c2 = c2.successor() + } + else { + return temp + } + } + return temp +} diff --git a/Radix-Tree/README.markdown b/Radix-Tree/README.markdown deleted file mode 100644 index ce1dde6b7..000000000 --- a/Radix-Tree/README.markdown +++ /dev/null @@ -1,46 +0,0 @@ -# Radix Tree - -A radix tree is a tree where a node can have any number of children. Each edge leading from a node to a child has a label (usually a string). A radix tree is often used to store strings or IP addresses and by traversing from the root to any leaf in the tree, (by concatenating all the labels of edges along the way) you can find any string. This is a radix tree: -![](/Radix-Tree/Images/radixtree.png) -(Image from en.wikipedia.org) - -## Implemenation - -The RadixTree class itself has one member variable, root, of type Root. The Root is the top of every RadixTree. Every node that is added, removed, looked up, etc. is a child, a child of a child, etc. of that root. The rest of the tree is represented as an Edge, which inherits Root. The different between Edge and Root is that Edges have a label (of type String) and a parent (of type Root?) member variables. This approach is a little different from the conventional way of creating Tree data structures but is easier to wrap your head around (see the picture above). - -## Operations - -Typical operations on a radix tree include lookup, insertion, deletion, find predecessor, find successor, and find all strings with common prefix. The running time of lookup, insertion, and deletion is O(k) where k is the length of the key. This is different from most trees because these operations usually run in O(logn) time where n is the number of nodes in the tree. - -### RadixTree.find(_ str: String) -> Bool - -The find function returns true if the String you are searching for is in the tree and false if it is not. Every RadixTree contains at the very least one String ("") so find("") will always return true. A String is considered "in the tree" if the String you are searching for is a concatenation of Edge labels while traversing downwards or a prefix of that concatenation. For example, if you look at the example tree above, find("roma") will return true because it is a prefix of the traversal "r"->"om"->"an". On the other hand, find("romans") will return false. - -### RadixTree.insert(_ str: String) -> Bool - -The insert function returns true if the String you are trying to insert was successfully inserted into the RadixTree and false if the String is already in the tree. Similarly to find(""), insert("") will always return false because an empty RadixTree contains "" by default. - -### RadixTree.remove(_ str: String) -> Bool - -The remove function returns true if the String is removed and false if the String is not in the tree. When a string is removed, any other Strings that have a prefix of the removed String are removed as well. For example, remove("rom") will also remove "roman", "rome", and "romulus" if those Strings are in the tree as well. Calling remove("") will remove all Strings in the tree. - -### Root.level() -> Int - -The level function returns how far down in the tree the Root or Edge in question is. A Root object will always return 0. A child of the Root will return 1, a child of a child of the root will return 2, etc. - -### RadixTree.height() -> Int - -The height function returns an Int equal to the highest level in the Tree. An empty tree will return 0. - -### RadixTree.printTree() - -The printTree function was used to visualize the tree itself. This function is a little buggy and not perfect yet but gets the job done thus far. - -### sharedPrefix(_ str1: String, _ str2: String) -> String - -The sharedPrefix function is a non-member function in the RadixTree.swift file. It takes in two String objects and returns the shared prefix between them. For example, -sharedPrefix("apples", "oranges") will return "" and sharedPrefix("court", "coral") will return "co". This function is used in the implementation of the find, insert, and remove functions. - -## See Also - -[Radix Tree - Wikipedia](https://en.wikipedia.org/wiki/Radix_tree) diff --git a/Radix-Tree/RadixTree.swift b/Radix-Tree/RadixTree.swift deleted file mode 100644 index 6f1f8fa57..000000000 --- a/Radix-Tree/RadixTree.swift +++ /dev/null @@ -1,374 +0,0 @@ -import Foundation - -//The root is the top of the Radix Tree -class Root { - - var children: [Edge] - - init() { - children = [Edge]() - } - - //The height functions returns the length (in number of edges) of the longest - // traversal down the tree - func height() -> Int { - //Base case: no children: the tree has a height of 1 - if children.count == 0 { - return 1 - } - //Recursion: find the max height of a root's child and return 1 + that max - else { - var max = 1 - for c in children { - if c.height() > max { - max = c.height() - } - } - return 1 + max - } - } - - //The level function returns how far down in the tree a Root/Edge is - //A root's level is always 0 - func level() -> Int { - return 0 - } - - //printRoot is a recursive function that prints the tree for debugging/ - // visualization purposes - func printRoot() { - //Print the first half of the children - if (children.count > 1) { - for c in 0...children.count/2-1 { - children[c].printEdge() - print("|") - } - } - else if children.count > 0 { - children[0].printEdge() - } - //Then print the root - print("ROOT") - //Print the second half of the children - if children.count > 1 { - for c in children.count/2...children.count-1 { - children[c].printEdge() - print("|") - } - } - print() - } -} - -//Edges are what actually store the Strings in the tree -class Edge: Root { - - var parent: Root? - var label: String - - init(_ label: String) { //Edge(label: "label") - self.label = label - super.init() - } - - //The Edge class overrides root's level function - override - func level() -> Int { - //Recurse up the tree incrementing level by one until the root is reached - if parent != nil { - return 1 + parent!.level() - } - //If an edge has no parent, it's level is one - // NOTE: THIS SHOULD NEVER HAPPEN AS THE ROOT IS ALWAYS THE TOP OF THE TREE - else { - return 1 - } - } - - //Erase erases a specific edge (and all edges below it in the tree) - func erase() { - self.parent = nil - if children.count > 0 { - //For each child, erase it, then remove it from the children array - for _ in 0...children.count-1 { - children[0].erase() - children.remove(at: 0) - } - } - } - - //printEdge is used in printRoot to print the tree - // It follows a similar structure to printRoot - func printEdge() { - //Print the first half of the edge's children - if children.count > 1 { - for c in 0...children.count/2-1 { - children[c].printEdge() - } - } - else if children.count > 0 { - children[0].printEdge() - } - //Tab over once up to the edge's level - for x in 1...level() { - if x == level() { - print("|------>", terminator: "") - } - else { - print("| ", terminator: "") - } - } - print(label) - //Print the second half of the edge's children - if children.count == 0 { - for _ in 1...level() { - print("| ", terminator: "") - } - print() - } - if children.count > 1 { - for c in children.count/2...children.count-1 { - children[c].printEdge() - } - } - } -} - -class RadixTree { - - var root: Root - - init() { - root = Root() - } - - //Returns the height of the tree by calling the root's height function - func height() -> Int { - return root.height() - 1 - } - - //Inserts a string into the tree - func insert(_ str: String) -> Bool { - //Account for a blank input - // The empty string is already in the tree - if str == "" { - return false - } - //searchStr is the parameter of the function - // it will be substringed as the function traverses down the tree - var searchStr = str - //currEdge is the current Edge (or Root) in question - var currEdge = root - while (true) { - var found = false - //If the current Edge has no children then the remaining searchStr is - // created as a child - if currEdge.children.count == 0 { - let newEdge = Edge(searchStr) - currEdge.children.append(newEdge) - newEdge.parent = currEdge - return true - } - //Loop through all of the children - for e in currEdge.children { - //Get the shared prefix betweeen the child in question and the - // search string - var shared = sharedPrefix(searchStr, e.label) - var index = shared.startIndex - //If the search string is equal to the shared string, - // the string already exists in the tree - if searchStr == shared { - return false - } - //If the child's label is equal to the shared string, you have to - // traverse another level down the tree, so substring the search - // string, break the loop, and run it back - else if shared == e.label { - currEdge = e - var tempIndex = searchStr.startIndex - for _ in 1...shared.characters.count { - tempIndex = tempIndex.successor() - } - searchStr = searchStr.substringFromIndex(tempIndex) - found = true - break - } - //If the child's label and the search string share a partial prefix, - // then both the label and the search string need to be substringed - // and a new branch needs to be created - else if shared.characters.count > 0 { - var labelIndex = e.label.characters.startIndex - //Create index objects and move them to after the shared prefix - for _ in 1...shared.characters.count { - index = index.successor() - labelIndex = labelIndex.successor() - } - //Substring both the search string and the label from the - // shared prefix - searchStr = searchStr.substringFromIndex(index) - e.label = e.label.substringFromIndex(labelIndex) - //Create 2 new edges and update parent/children values - let newEdge = Edge(e.label) - e.label = shared - for ec in e.children { - newEdge.children.append(ec) - } - newEdge.parent = e - e.children.removeAll() - for nec in newEdge.children { - nec.parent = newEdge - } - e.children.append(newEdge) - let newEdge2 = Edge(searchStr) - newEdge2.parent = e - e.children.append(newEdge2) - return true - } - //If they don't share a prefix, go to next child - } - //If none of the children share a prefix, you have to create a new child - if (!found) { - let newEdge = Edge(searchStr) - currEdge.children.append(newEdge) - newEdge.parent = currEdge - return true - } - } - } - - //Tells you if a string is in the tree - func find(_ str: String) -> Bool { - //A radix tree always contains the empty string - if str == "" { - return true - } - //If there are no children then the string cannot be in the tree - else if root.children.count == 0 { - return false - } - //searchStr and currEdge have the same functionality as insert() - var searchStr = str - var currEdge = root - while (true) { - var found = false - //Loop through currEdge's children - for c in currEdge.children { - //First check if the search string and the child's label are equal - // if so the string is in the tree, return true - if searchStr == c.label { - return true - } - //If that is not true, find the shared string b/t the search string - // and the label - var shared = sharedPrefix(searchStr, c.label) - //If the shared string is equal to the label, update the curent node, - // break the loop, and run it back - if shared == c.label { - currEdge = c - var tempIndex = searchStr.startIndex - for _ in 1...shared.characters.count { - tempIndex = tempIndex.successor() - } - searchStr = searchStr.substringFromIndex(tempIndex) - found = true - break - } - //If the shared string is empty, go to the next child - else if shared.characters.count == 0 { - continue - } - //If the shared string matches the search string, return true - else if shared == searchStr { - return true - } - //If the search string and the child's label only share some characters, - // the string is not in the tree, return false - else if shared[shared.startIndex] == c.label[c.label.startIndex] && - shared.characters.count < c.label.characters.count { - return false - } - } - //If nothing was found, return false - if !found { - return false - } - } - } - - //Removes a string from the tree - func remove(_ str: String) -> Bool { - //Removing the empty string removes everything in the tree - if str == "" { - for c in root.children { - c.erase() - root.children.remove(at: 0) - } - return true - } - //If the tree is empty, you cannot remove anything - else if root.children.count == 0 { - return false - } - //searchStr and currEdge have the same functionality as in insert() and find() - var searchStr = str - var currEdge = root - while (true) { - var found = false - //If currEdge has no children, then the searchStr is not in the tree - if currEdge.children.count == 0 { - return false - } - //Loop through the children - for c in 0...currEdge.children.count-1 { - //If the child's label matches the search string, remove that child - // and everything below it in the tree - if currEdge.children[c].label == searchStr { - currEdge.children[c].erase() - currEdge.children.remove(at: c) - return true - } - //Find the shared string - var shared = sharedPrefix(searchStr, currEdge.children[c].label) - //If the shared string is equal to the child's string, go down a level - if shared == currEdge.children[c].label { - currEdge = currEdge.children[c] - var tempIndex = searchStr.startIndex - for _ in 1...shared.characters.count { - tempIndex = tempIndex.successor() - } - searchStr = searchStr.substringFromIndex(tempIndex) - found = true - break - } - } - //If there is no match, then the searchStr is not in the tree - if !found { - return false - } - } - } - - //Prints the tree by calling the root's print function - func printTree() { - root.printRoot() - } -} - -//Returns the prefix that is shared between the two input strings -//i.e. sharedPrefix("court", "coral") -> "co" -func sharedPrefix(_ str1: String, _ str2: String) -> String { - var temp = "" - var c1 = str1.characters.startIndex - var c2 = str2.characters.startIndex - for _ in 0...min(str1.characters.count-1, str2.characters.count-1) { - if str1[c1] == str2[c2] { - temp.append( str1[c1] ) - c1 = c1.successor() - c2 = c2.successor() - } - else { - return temp - } - } - return temp -} \ No newline at end of file From 6f9ef9bbc986aa31b6676fdc5285452085d54f8b Mon Sep 17 00:00:00 2001 From: Thukor Date: Fri, 6 May 2016 08:35:18 -0400 Subject: [PATCH 0352/1679] Radix-Sort -> Radix Sort, Got rid of unnecessary ()'s in Trie --- {Radix-Sort => Radix Sort}/ReadMe.md | 0 {Radix-Sort => Radix Sort}/radixSort.swift | 0 Trie/trie.swift | 10 +++++----- 3 files changed, 5 insertions(+), 5 deletions(-) rename {Radix-Sort => Radix Sort}/ReadMe.md (100%) rename {Radix-Sort => Radix Sort}/radixSort.swift (100%) diff --git a/Radix-Sort/ReadMe.md b/Radix Sort/ReadMe.md similarity index 100% rename from Radix-Sort/ReadMe.md rename to Radix Sort/ReadMe.md diff --git a/Radix-Sort/radixSort.swift b/Radix Sort/radixSort.swift similarity index 100% rename from Radix-Sort/radixSort.swift rename to Radix Sort/radixSort.swift diff --git a/Trie/trie.swift b/Trie/trie.swift index f50363749..839c4350b 100644 --- a/Trie/trie.swift +++ b/Trie/trie.swift @@ -191,7 +191,7 @@ public class Node { func printNode(var indent: String, leaf: Bool) { print(indent, terminator: "") - if(leaf) { + if leaf { print("\\-", terminator: "") indent += " " } @@ -359,7 +359,7 @@ public class Trie { length -= 1 index += 1 - if(length == 0) { + if length == 0 { currentNode.isWord() wordList.append(w) wordCount += 1 @@ -407,7 +407,7 @@ public class Trie { func remove(w: String) -> (word: String, removed: Bool){ let word = w.lowercaseString - if(!self.contains(w)) { + if !self.contains(w) { return (w, false) } var currentNode = self.root @@ -464,10 +464,10 @@ public class Trie { while let current = q.dequeue() { for (char, child) in current.getChildren() { - if(!child.visited) { + if !child.visited { q.enqueue(child) child.visited = true - if(child.isValidWord()) { + if child.isValidWord() { var currentNode = child while currentNode !== n { tmp += currentNode.char() From 9857cb7073b2e970cbb4dca8ab3cab52435e3eb9 Mon Sep 17 00:00:00 2001 From: Thukor Date: Fri, 6 May 2016 09:45:42 -0400 Subject: [PATCH 0353/1679] Renamed Red Black Trees -> Red-Black Tree --- {Red Black Trees => Red-Black Tree}/RBTree.swift | 0 {Red Black Trees => Red-Black Tree}/README.md | 0 {Red Black Trees => Red-Black Tree}/files/fig1.png | Bin {Red Black Trees => Red-Black Tree}/files/fig2.png | Bin 4 files changed, 0 insertions(+), 0 deletions(-) rename {Red Black Trees => Red-Black Tree}/RBTree.swift (100%) rename {Red Black Trees => Red-Black Tree}/README.md (100%) rename {Red Black Trees => Red-Black Tree}/files/fig1.png (100%) rename {Red Black Trees => Red-Black Tree}/files/fig2.png (100%) diff --git a/Red Black Trees/RBTree.swift b/Red-Black Tree/RBTree.swift similarity index 100% rename from Red Black Trees/RBTree.swift rename to Red-Black Tree/RBTree.swift diff --git a/Red Black Trees/README.md b/Red-Black Tree/README.md similarity index 100% rename from Red Black Trees/README.md rename to Red-Black Tree/README.md diff --git a/Red Black Trees/files/fig1.png b/Red-Black Tree/files/fig1.png similarity index 100% rename from Red Black Trees/files/fig1.png rename to Red-Black Tree/files/fig1.png diff --git a/Red Black Trees/files/fig2.png b/Red-Black Tree/files/fig2.png similarity index 100% rename from Red Black Trees/files/fig2.png rename to Red-Black Tree/files/fig2.png From 3aa88de547fad9b7f8ab2dbbd968c1f456f1a88f Mon Sep 17 00:00:00 2001 From: Ashwin Date: Fri, 6 May 2016 16:54:41 +0000 Subject: [PATCH 0354/1679] inline comments --- Red-Black Tree/RBTree.swift | 48 +++- Red-Black Tree/RBTree.swift~ | 477 +++++++++++++++++++++++++++++++++++ 2 files changed, 519 insertions(+), 6 deletions(-) create mode 100644 Red-Black Tree/RBTree.swift~ diff --git a/Red-Black Tree/RBTree.swift b/Red-Black Tree/RBTree.swift index 50d1d00d4..8b2653297 100644 --- a/Red-Black Tree/RBTree.swift +++ b/Red-Black Tree/RBTree.swift @@ -55,6 +55,7 @@ public class RBTree { let n = depth(root!) return n } + //return the max depth of the tree private func depth(rooty:RBTNode?)->Int{ if(rooty == nil){ return 0 @@ -67,6 +68,7 @@ public class RBTree { public func inOrder(){ inOrder(root) } + //Prints the in order traversal of the current tree private func inOrder(root: RBTNode?){ if(self.root == nil ){ print("The tree is empty.") @@ -78,7 +80,14 @@ public class RBTree { print("Data: \(root!.data) Color: \(root!.color)") inOrder(root!.right) } - + /* + Basic Algorithm: + Let Q be P's right child. + Set P's right child to be Q's left child. + [Set Q's left-child's parent to P] + Set Q's left child to be P. + [Set P's parent to Q] + */ private func leftRotate(x: RBTNode) { let newRoot = x.right x.right = newRoot.left @@ -96,6 +105,14 @@ public class RBTree { newRoot.left = x x.parent = newRoot } + /* + Basic Algorithm: + Let P be Q's left child. + Set Q's left child to be P's right child. + [Set P's right-child's parent to Q] + Set P's right child to be Q. + [Set Q's parent to P] + */ private func rightRotate(x: RBTNode) { let newRoot = x.left x.left = newRoot.right @@ -118,6 +135,7 @@ public class RBTree { print("Inserted Node: \(inserted!.data)") insertCase1(inserted) } + //Case where root is the only node private func insertCase1(inserted: RBTNode?){ let myroot = self.root! if myroot === inserted!{ @@ -125,12 +143,14 @@ public class RBTree { } insertCase2(inserted!) } + //Case for inserting a node as a child of a black node private func insertCase2(inserted: RBTNode?){ if inserted!.parent!.color == false{ return } insertCase3(inserted!) } + //Insert case for if the parent is black and parent's siblng is black private func insertCase3(inserted: RBTNode?){ if(inserted!.parent!.sibling() != nil && inserted!.parent!.sibling()!.color == true){ @@ -144,7 +164,7 @@ public class RBTree { } insertCase4(inserted) } - + //Insert case for Node N is left of parent and parent is right of grandparent private func insertCase4( insert: RBTNode?){ var inserted = insert if((inserted! === inserted!.parent!.right) && @@ -161,6 +181,7 @@ public class RBTree { } insertCase5(inserted) } + //Insert case for Node n where parent is red and parent's sibling is black private func insertCase5(inserted: RBTNode?){ if((inserted!.parent!.color == true && (inserted!.parent!.sibling()?.color == false || @@ -185,6 +206,7 @@ public class RBTree { insert(value, parent: root!) insertFixup(value) } + //Basic BST insert implementation private func insert(value: Int, parent: RBTNode) { if self.root == nil{ self.root = RBTNode(rootData: value) @@ -209,7 +231,7 @@ public class RBTree { public func find(data: Int)->RBTNode?{ return find(root!,data: data) } - + //Returns the reference to the RBTNode whos data was requested private func find(root: RBTNode, data: Int)->RBTNode?{ if data == root.data{ return root @@ -235,6 +257,7 @@ public class RBTree { return } } + //Transplant the positions of two nodes in the RBTree public func replaceNode(n1: RBTNode, n2: RBTNode){ let temp = n1.data let temp_color = n1.color @@ -243,6 +266,7 @@ public class RBTree { n2.data = temp n2.color = temp_color } + //returns the node with the minimum value in the subtree public func minimum(Node: RBTNode)->RBTNode { var node = Node while node.left !== nil{ @@ -250,6 +274,7 @@ public class RBTree { } return node } + //Returns the next largest node in the tree public func successor(Node: RBTNode) -> RBTNode? { var node = Node if node.right !== nil { @@ -262,6 +287,7 @@ public class RBTree { } return successor } + //Returns the next smallest node in the tree public func predecessor(Node: RBTNode) -> RBTNode{ var node = Node if node.left !== nil { @@ -274,6 +300,7 @@ public class RBTree { } return successor } + //Returns the node with the largest value in the subtree public func maximum(rootnode: RBTNode) -> RBTNode{ var rootNode = rootnode while rootNode.right !== nil { @@ -281,18 +308,21 @@ public class RBTree { } return rootNode } - + //call to remove a node from the tree public func delete(x: Int){ let toDel = find(x) deleteNode(toDel!) } + //Function call for removing a node private func deleteNode(todel: RBTNode?){ var toDel = todel + //case for if todel is the only node in the tree if(toDel!.left === nil && toDel!.right === nil && toDel!.parent === nil){ toDel = nil self.root = nil return } + //case for if toDell is a red node w/ no children if(toDel!.left === nil && toDel!.right === nil && toDel!.color == true){ if(toDel!.parent.left === toDel!){ toDel!.parent.left = nil @@ -307,12 +337,13 @@ public class RBTree { } return } + //case for toDel having two children if(toDel!.left !== nil && toDel!.right !== nil){ let pred = maximum(toDel!.left!) toDel!.data = pred.data toDel! = pred } - + //case for toDel having one child var child: RBTNode? = nil if(toDel!.right === nil){ child = toDel!.left @@ -346,6 +377,7 @@ public class RBTree { return } } + //delete case for if parent is nil after deletion private func deleteCase1( toDel: RBTNode?){ if(toDel?.parent === nil){ return @@ -354,6 +386,7 @@ public class RBTree { deleteCase2(toDel) } } + //case to fix tree after deletion and sibling is red private func deleteCase2(toDel: RBTNode?){ let sibling = toDel!.sibling() if(sibling?.color == true){ @@ -368,6 +401,7 @@ public class RBTree { deleteCase3(toDel!) } } + //delete case for fixing tree when parnet is black and sibling is black and sibling.children are also black private func deleteCase3(toDel: RBTNode?){ if(toDel!.parent?.color == false && toDel!.sibling()?.color == false && @@ -394,6 +428,7 @@ public class RBTree { deleteCase5(toDel) } } + //delete case for fixing tree if toDel is a left child and sibling(n) is black and children of sibling(n) are black and white respectibely private func deleteCase5(toDel:RBTNode?){ if(toDel! === toDel!.parent?.left && toDel!.sibling()?.color == false && @@ -404,7 +439,7 @@ public class RBTree { toDel!.sibling()?.left?.color = false rightRotate(toDel!.sibling()!) } - + //opposite case else if(toDel! === toDel!.parent?.right && toDel!.sibling()?.color == false && toDel!.sibling()?.left.color == false && @@ -415,6 +450,7 @@ public class RBTree { leftRotate(toDel!.sibling()!) } } + //final rotations to be done after deleting a black node from the tree private func deleteCase6(toDel: RBTNode?){ let color = toDel!.sibling()?.color toDel!.parent?.color = color! diff --git a/Red-Black Tree/RBTree.swift~ b/Red-Black Tree/RBTree.swift~ new file mode 100644 index 000000000..46abc897b --- /dev/null +++ b/Red-Black Tree/RBTree.swift~ @@ -0,0 +1,477 @@ +public class RBTNode{ + private(set) public var color: Bool + private(set) public var left: RBTNode! + private(set) public var right: RBTNode! + private(set) public var parent: RBTNode! + private(set) public var data: Int + init(){ + self.data = -1 + self.color = true + self.left = nil + self.right = nil + self.parent = nil + } + init(rootData: Int){ + self.data = rootData + self.color = true //0 is black 1 is red + self.left = nil + self.right = nil + self.parent = nil + } + deinit{ + print("Node: \(self.data) is bein deinitialized") + } + + public func grandparent()->RBTNode?{ + if(self.parent === nil || self.parent.parent === nil){ + return nil + } + else{ + return self.parent.parent + } + } + public func sibling()->RBTNode?{ + if(self.parent === nil || self.parent.right === nil || self.parent.left === nil){ + return nil + } + if(self === self.parent!.left!){ + return self.parent!.right! + } + else{ + return self.parent!.left! + } + } +} +public class RBTree { + private(set) public var root: RBTNode? + init(rootData: Int) { + root = RBTNode(rootData: rootData) + root!.color = false + } + init(){ + root = nil + } + public func depth()->Int{ + let n = depth(root!) + return n + } + //return the max depth of the tree + private func depth(rooty:RBTNode?)->Int{ + if(rooty == nil){ + return 0 + } + else{ + return 1+(max(depth(root!.left),depth(root!.right))) + } + } + + public func inOrder(){ + inOrder(root) + } + //Prints the in order traversal of the current tree + private func inOrder(root: RBTNode?){ + if(self.root == nil ){ + print("The tree is empty.") + } + if(root == nil){ + return + } + inOrder(root!.left) + print("Data: \(root!.data) Color: \(root!.color)") + inOrder(root!.right) + } + /* + Basic Algorithm: + Let Q be P's right child. + Set P's right child to be Q's left child. + [Set Q's left-child's parent to P] + Set Q's left child to be P. + [Set P's parent to Q] + */ + private func leftRotate(x: RBTNode) { + let newRoot = x.right + x.right = newRoot.left + if (newRoot.left !== nil) { + newRoot.left.parent = x + } + newRoot.parent = x.parent + if(x.parent === nil) { + root = newRoot + } else if (x === x.parent.left) { + x.parent.left = newRoot + } else { + x.parent.right = newRoot + } + newRoot.left = x + x.parent = newRoot + } + /* + Basic Algorithm: + Let P be Q's left child. + Set Q's left child to be P's right child. + [Set P's right-child's parent to Q] + Set P's right child to be Q. + [Set Q's parent to P] + */ + private func rightRotate(x: RBTNode) { + let newRoot = x.left + x.left = newRoot.right + if newRoot.right !== nil { + newRoot.right.parent = x + } + newRoot.parent = x.parent + if x.parent === nil { + root = newRoot + } else if x === x.parent.right { + x.parent.right = newRoot + } else { + x.parent.left = newRoot + } + newRoot.right = x + x.parent = newRoot + } + public func insertFixup(value: Int){ + let inserted = find(value) + print("Inserted Node: \(inserted!.data)") + insertCase1(inserted) + } + //Case where root is the only node + private func insertCase1(inserted: RBTNode?){ + let myroot = self.root! + if myroot === inserted!{ + self.root!.color = false + } + insertCase2(inserted!) + } + //Case for inserting a node as a child of a black node + private func insertCase2(inserted: RBTNode?){ + if inserted!.parent!.color == false{ + return + } + insertCase3(inserted!) + } + //Insert case for if the parent is black and parent's siblng is black + private func insertCase3(inserted: RBTNode?){ + if(inserted!.parent!.sibling() != nil && + inserted!.parent!.sibling()!.color == true){ + inserted!.parent!.color = false + inserted!.parent!.sibling()!.color = false + let g = inserted!.grandparent + g()!.color = true + if(g()!.parent == nil){ + g()!.color = false + } + } + insertCase4(inserted) + } + //Insert case for Node N is left of parent and parent is right of grandparent + private func insertCase4( insert: RBTNode?){ + var inserted = insert + if((inserted! === inserted!.parent!.right) && + (inserted!.grandparent()!.left === inserted!.parent!)){ + + leftRotate(inserted!.parent) + inserted! = inserted!.left + } + else if((inserted! === inserted!.parent!.left) && + (inserted!.grandparent()!.right === inserted!.parent!)){ + + rightRotate(inserted!.parent) + inserted! = inserted!.right + } + insertCase5(inserted) + } + //Insert case for Node n where parent is red and parent's sibling is black + private func insertCase5(inserted: RBTNode?){ + if((inserted!.parent!.color == true && + (inserted!.parent!.sibling()?.color == false || + inserted!.parent!.sibling() == nil ))){ + + if(inserted! === inserted!.parent!.left && inserted!.grandparent()!.left === inserted!.parent!){ + inserted!.parent.color = false + inserted!.grandparent()?.color = true + if(inserted! === inserted!.parent!.left){ + rightRotate(inserted!.grandparent()!) + } + } + else if(inserted! === inserted!.parent!.right && inserted!.grandparent()!.right === inserted!.parent!){ + inserted!.parent.color = false + inserted!.grandparent()?.color = true + leftRotate(inserted!.grandparent()!) + } + } + } + + public func insert(value: Int) { + insert(value, parent: root!) + insertFixup(value) + } + //Basic BST insert implementation + private func insert(value: Int, parent: RBTNode) { + if self.root == nil{ + self.root = RBTNode(rootData: value) + return + } + else if value < parent.data { + if let left = parent.left { + insert(value, parent: left) + } else { + parent.left = RBTNode(rootData: value) + parent.left?.parent = parent + } + } else { + if let right = parent.right { + insert(value, parent: right) + } else { + parent.right = RBTNode(rootData: value) + parent.right?.parent = parent + } + } + } + public func find(data: Int)->RBTNode?{ + return find(root!,data: data) + } + //Returns the reference to the RBTNode whos data was requested + private func find(root: RBTNode, data: Int)->RBTNode?{ + if data == root.data{ + return root + } + if root.data != data && root.right == nil && root.left == nil { + return nil + } + else if data > root.data{ + return find(root.right, data: data) + } + else if data < root.data{ + return find(root.left, data: data) + } + else{ + return nil + } + } + + //DELETION HELPER FUNCTIONS + public func remove(value: Int){ + let toRemove = find(value) + if(toRemove == nil){ + return + } + } + //Transplant the positions of two nodes in the RBTree + public func replaceNode(n1: RBTNode, n2: RBTNode){ + let temp = n1.data + let temp_color = n1.color + n1.data = n2.data + n1.color = n2.color + n2.data = temp + n2.color = temp_color + } + //returns the node with the minimum value in the subtree + public func minimum(Node: RBTNode)->RBTNode { + var node = Node + while node.left !== nil{ + node = node.left + } + return node + } + //Returns the next largest node in the tree + public func successor(Node: RBTNode) -> RBTNode? { + var node = Node + if node.right !== nil { + return minimum(node.right) + } + var successor = node.parent + while successor !== nil && node === successor.right { + node = successor + successor = successor.parent + } + return successor + } + //Returns the next smallest node in the tree + public func predecessor(Node: RBTNode) -> RBTNode{ + var node = Node + if node.left !== nil { + return minimum(node.left) + } + var successor = node.parent + while successor !== nil && node === successor.left { + node = successor + successor = successor.parent + } + return successor + } + //Returns the node with the largest value in the subtree + public func maximum(rootnode: RBTNode) -> RBTNode{ + var rootNode = rootnode + while rootNode.right !== nil { + rootNode = rootNode.right + } + return rootNode + } + //call to remove a node from the tree + public func delete(x: Int){ + let toDel = find(x) + deleteNode(toDel!) + } + //Function call for removing a node + private func deleteNode(todel: RBTNode?){ + var toDel = todel + //case for if todel is the only node in the tree + if(toDel!.left === nil && toDel!.right === nil && toDel!.parent === nil){ + toDel = nil + self.root = nil + return + } + //case for if toDell is a red node w/ no children + if(toDel!.left === nil && toDel!.right === nil && toDel!.color == true){ + if(toDel!.parent.left === toDel!){ + toDel!.parent.left = nil + toDel = nil + } + else if(toDel!.parent === nil){ + toDel = nil + } + else{ + toDel?.parent.right = nil + toDel = nil + } + return + } + //case for toDel having two children + if(toDel!.left !== nil && toDel!.right !== nil){ + let pred = maximum(toDel!.left!) + toDel!.data = pred.data + toDel! = pred + } + //case for toDel having one child + var child: RBTNode? = nil + if(toDel!.right === nil){ + child = toDel!.left + } + else{ + child = toDel!.right + } + if(toDel!.color == false && child !== nil){ + toDel!.color = child!.color + deleteCase1(toDel!) + } + + if(child !== nil){ + replaceNode(toDel!, n2: child!) + if(toDel!.parent === nil && child !== nil){ + child!.color = false + } + } + if(toDel!.parent.left === toDel!){ + toDel!.parent.left = nil + toDel = nil + return + } + else if(toDel!.parent === nil){ + toDel = nil + return + } + else{ + toDel?.parent.right = nil + toDel = nil + return + } + } + //delete case for if parent is nil after deletion + private func deleteCase1( toDel: RBTNode?){ + if(toDel?.parent === nil){ + return + } + else{ + deleteCase2(toDel) + } + } + //case to fix tree after deletion and sibling is red + private func deleteCase2(toDel: RBTNode?){ + let sibling = toDel!.sibling() + if(sibling?.color == true){ + toDel!.parent.color = true; + sibling?.color = false + if(toDel! === toDel!.parent.left){ + leftRotate(toDel!.parent) + } + else{ + rightRotate(toDel!.parent) + } + deleteCase3(toDel!) + } + } + //delete case for fixing tree when parnet is black and sibling is black and sibling.children are also black + private func deleteCase3(toDel: RBTNode?){ + if(toDel!.parent?.color == false && + toDel!.sibling()?.color == false && + toDel!.sibling()?.left!.color == false && + toDel!.sibling()?.right!.color == false){ + + toDel!.sibling()?.color = true + toDel!.parent?.color = false + } + else{ + deleteCase4(toDel) + } + } + private func deleteCase4(toDel: RBTNode?){ + if(toDel!.parent?.color == true && + toDel!.sibling()?.color == false && + toDel!.sibling()?.left!.color == false && + toDel!.sibling()?.right!.color == false){ + + toDel!.sibling()?.color = true + toDel!.parent.color = false + } + else{ + deleteCase5(toDel) + } + } + //delete case for fixing tree if toDel is a left child and sibling(n) is black and children of sibling(n) are black and white respectibely + private func deleteCase5(toDel:RBTNode?){ + if(toDel! === toDel!.parent?.left && + toDel!.sibling()?.color == false && + toDel!.sibling()?.left.color == true && + toDel!.sibling()?.right.color == false){ + + toDel!.sibling()?.color = true + toDel!.sibling()?.left?.color = false + rightRotate(toDel!.sibling()!) + } + //opposite case + else if(toDel! === toDel!.parent?.right && + toDel!.sibling()?.color == false && + toDel!.sibling()?.left.color == false && + toDel!.sibling()?.right.color == true){ + + toDel!.sibling()?.color = true + toDel!.sibling()?.right?.color = false + leftRotate(toDel!.sibling()!) + } + } + private func deleteCase6(toDel: RBTNode?){ + let color = toDel!.sibling()?.color + toDel!.parent?.color = color! + toDel!.parent?.color = false + if(toDel! === toDel!.parent.left){ + toDel!.sibling()?.right?.color = false + leftRotate(toDel!.parent!) + } + else{ + toDel!.sibling()?.left?.color = false + rightRotate(toDel!.parent!) + } + } +} + +var tree = RBTree(rootData: 8) +tree.insert(5) +tree.insert(4) +tree.insert(9) +tree.delete(9) +tree.insert(3) +tree.insert(10) +tree.delete(3) +var x = tree.find(5) +tree.inOrder() From 610b532b8720f2a04efd02831205057be4b26765 Mon Sep 17 00:00:00 2001 From: axptwig Date: Fri, 6 May 2016 16:55:36 +0000 Subject: [PATCH 0355/1679] Delete RBTree.swift~ removed temp --- Red-Black Tree/RBTree.swift~ | 477 ----------------------------------- 1 file changed, 477 deletions(-) delete mode 100644 Red-Black Tree/RBTree.swift~ diff --git a/Red-Black Tree/RBTree.swift~ b/Red-Black Tree/RBTree.swift~ deleted file mode 100644 index 46abc897b..000000000 --- a/Red-Black Tree/RBTree.swift~ +++ /dev/null @@ -1,477 +0,0 @@ -public class RBTNode{ - private(set) public var color: Bool - private(set) public var left: RBTNode! - private(set) public var right: RBTNode! - private(set) public var parent: RBTNode! - private(set) public var data: Int - init(){ - self.data = -1 - self.color = true - self.left = nil - self.right = nil - self.parent = nil - } - init(rootData: Int){ - self.data = rootData - self.color = true //0 is black 1 is red - self.left = nil - self.right = nil - self.parent = nil - } - deinit{ - print("Node: \(self.data) is bein deinitialized") - } - - public func grandparent()->RBTNode?{ - if(self.parent === nil || self.parent.parent === nil){ - return nil - } - else{ - return self.parent.parent - } - } - public func sibling()->RBTNode?{ - if(self.parent === nil || self.parent.right === nil || self.parent.left === nil){ - return nil - } - if(self === self.parent!.left!){ - return self.parent!.right! - } - else{ - return self.parent!.left! - } - } -} -public class RBTree { - private(set) public var root: RBTNode? - init(rootData: Int) { - root = RBTNode(rootData: rootData) - root!.color = false - } - init(){ - root = nil - } - public func depth()->Int{ - let n = depth(root!) - return n - } - //return the max depth of the tree - private func depth(rooty:RBTNode?)->Int{ - if(rooty == nil){ - return 0 - } - else{ - return 1+(max(depth(root!.left),depth(root!.right))) - } - } - - public func inOrder(){ - inOrder(root) - } - //Prints the in order traversal of the current tree - private func inOrder(root: RBTNode?){ - if(self.root == nil ){ - print("The tree is empty.") - } - if(root == nil){ - return - } - inOrder(root!.left) - print("Data: \(root!.data) Color: \(root!.color)") - inOrder(root!.right) - } - /* - Basic Algorithm: - Let Q be P's right child. - Set P's right child to be Q's left child. - [Set Q's left-child's parent to P] - Set Q's left child to be P. - [Set P's parent to Q] - */ - private func leftRotate(x: RBTNode) { - let newRoot = x.right - x.right = newRoot.left - if (newRoot.left !== nil) { - newRoot.left.parent = x - } - newRoot.parent = x.parent - if(x.parent === nil) { - root = newRoot - } else if (x === x.parent.left) { - x.parent.left = newRoot - } else { - x.parent.right = newRoot - } - newRoot.left = x - x.parent = newRoot - } - /* - Basic Algorithm: - Let P be Q's left child. - Set Q's left child to be P's right child. - [Set P's right-child's parent to Q] - Set P's right child to be Q. - [Set Q's parent to P] - */ - private func rightRotate(x: RBTNode) { - let newRoot = x.left - x.left = newRoot.right - if newRoot.right !== nil { - newRoot.right.parent = x - } - newRoot.parent = x.parent - if x.parent === nil { - root = newRoot - } else if x === x.parent.right { - x.parent.right = newRoot - } else { - x.parent.left = newRoot - } - newRoot.right = x - x.parent = newRoot - } - public func insertFixup(value: Int){ - let inserted = find(value) - print("Inserted Node: \(inserted!.data)") - insertCase1(inserted) - } - //Case where root is the only node - private func insertCase1(inserted: RBTNode?){ - let myroot = self.root! - if myroot === inserted!{ - self.root!.color = false - } - insertCase2(inserted!) - } - //Case for inserting a node as a child of a black node - private func insertCase2(inserted: RBTNode?){ - if inserted!.parent!.color == false{ - return - } - insertCase3(inserted!) - } - //Insert case for if the parent is black and parent's siblng is black - private func insertCase3(inserted: RBTNode?){ - if(inserted!.parent!.sibling() != nil && - inserted!.parent!.sibling()!.color == true){ - inserted!.parent!.color = false - inserted!.parent!.sibling()!.color = false - let g = inserted!.grandparent - g()!.color = true - if(g()!.parent == nil){ - g()!.color = false - } - } - insertCase4(inserted) - } - //Insert case for Node N is left of parent and parent is right of grandparent - private func insertCase4( insert: RBTNode?){ - var inserted = insert - if((inserted! === inserted!.parent!.right) && - (inserted!.grandparent()!.left === inserted!.parent!)){ - - leftRotate(inserted!.parent) - inserted! = inserted!.left - } - else if((inserted! === inserted!.parent!.left) && - (inserted!.grandparent()!.right === inserted!.parent!)){ - - rightRotate(inserted!.parent) - inserted! = inserted!.right - } - insertCase5(inserted) - } - //Insert case for Node n where parent is red and parent's sibling is black - private func insertCase5(inserted: RBTNode?){ - if((inserted!.parent!.color == true && - (inserted!.parent!.sibling()?.color == false || - inserted!.parent!.sibling() == nil ))){ - - if(inserted! === inserted!.parent!.left && inserted!.grandparent()!.left === inserted!.parent!){ - inserted!.parent.color = false - inserted!.grandparent()?.color = true - if(inserted! === inserted!.parent!.left){ - rightRotate(inserted!.grandparent()!) - } - } - else if(inserted! === inserted!.parent!.right && inserted!.grandparent()!.right === inserted!.parent!){ - inserted!.parent.color = false - inserted!.grandparent()?.color = true - leftRotate(inserted!.grandparent()!) - } - } - } - - public func insert(value: Int) { - insert(value, parent: root!) - insertFixup(value) - } - //Basic BST insert implementation - private func insert(value: Int, parent: RBTNode) { - if self.root == nil{ - self.root = RBTNode(rootData: value) - return - } - else if value < parent.data { - if let left = parent.left { - insert(value, parent: left) - } else { - parent.left = RBTNode(rootData: value) - parent.left?.parent = parent - } - } else { - if let right = parent.right { - insert(value, parent: right) - } else { - parent.right = RBTNode(rootData: value) - parent.right?.parent = parent - } - } - } - public func find(data: Int)->RBTNode?{ - return find(root!,data: data) - } - //Returns the reference to the RBTNode whos data was requested - private func find(root: RBTNode, data: Int)->RBTNode?{ - if data == root.data{ - return root - } - if root.data != data && root.right == nil && root.left == nil { - return nil - } - else if data > root.data{ - return find(root.right, data: data) - } - else if data < root.data{ - return find(root.left, data: data) - } - else{ - return nil - } - } - - //DELETION HELPER FUNCTIONS - public func remove(value: Int){ - let toRemove = find(value) - if(toRemove == nil){ - return - } - } - //Transplant the positions of two nodes in the RBTree - public func replaceNode(n1: RBTNode, n2: RBTNode){ - let temp = n1.data - let temp_color = n1.color - n1.data = n2.data - n1.color = n2.color - n2.data = temp - n2.color = temp_color - } - //returns the node with the minimum value in the subtree - public func minimum(Node: RBTNode)->RBTNode { - var node = Node - while node.left !== nil{ - node = node.left - } - return node - } - //Returns the next largest node in the tree - public func successor(Node: RBTNode) -> RBTNode? { - var node = Node - if node.right !== nil { - return minimum(node.right) - } - var successor = node.parent - while successor !== nil && node === successor.right { - node = successor - successor = successor.parent - } - return successor - } - //Returns the next smallest node in the tree - public func predecessor(Node: RBTNode) -> RBTNode{ - var node = Node - if node.left !== nil { - return minimum(node.left) - } - var successor = node.parent - while successor !== nil && node === successor.left { - node = successor - successor = successor.parent - } - return successor - } - //Returns the node with the largest value in the subtree - public func maximum(rootnode: RBTNode) -> RBTNode{ - var rootNode = rootnode - while rootNode.right !== nil { - rootNode = rootNode.right - } - return rootNode - } - //call to remove a node from the tree - public func delete(x: Int){ - let toDel = find(x) - deleteNode(toDel!) - } - //Function call for removing a node - private func deleteNode(todel: RBTNode?){ - var toDel = todel - //case for if todel is the only node in the tree - if(toDel!.left === nil && toDel!.right === nil && toDel!.parent === nil){ - toDel = nil - self.root = nil - return - } - //case for if toDell is a red node w/ no children - if(toDel!.left === nil && toDel!.right === nil && toDel!.color == true){ - if(toDel!.parent.left === toDel!){ - toDel!.parent.left = nil - toDel = nil - } - else if(toDel!.parent === nil){ - toDel = nil - } - else{ - toDel?.parent.right = nil - toDel = nil - } - return - } - //case for toDel having two children - if(toDel!.left !== nil && toDel!.right !== nil){ - let pred = maximum(toDel!.left!) - toDel!.data = pred.data - toDel! = pred - } - //case for toDel having one child - var child: RBTNode? = nil - if(toDel!.right === nil){ - child = toDel!.left - } - else{ - child = toDel!.right - } - if(toDel!.color == false && child !== nil){ - toDel!.color = child!.color - deleteCase1(toDel!) - } - - if(child !== nil){ - replaceNode(toDel!, n2: child!) - if(toDel!.parent === nil && child !== nil){ - child!.color = false - } - } - if(toDel!.parent.left === toDel!){ - toDel!.parent.left = nil - toDel = nil - return - } - else if(toDel!.parent === nil){ - toDel = nil - return - } - else{ - toDel?.parent.right = nil - toDel = nil - return - } - } - //delete case for if parent is nil after deletion - private func deleteCase1( toDel: RBTNode?){ - if(toDel?.parent === nil){ - return - } - else{ - deleteCase2(toDel) - } - } - //case to fix tree after deletion and sibling is red - private func deleteCase2(toDel: RBTNode?){ - let sibling = toDel!.sibling() - if(sibling?.color == true){ - toDel!.parent.color = true; - sibling?.color = false - if(toDel! === toDel!.parent.left){ - leftRotate(toDel!.parent) - } - else{ - rightRotate(toDel!.parent) - } - deleteCase3(toDel!) - } - } - //delete case for fixing tree when parnet is black and sibling is black and sibling.children are also black - private func deleteCase3(toDel: RBTNode?){ - if(toDel!.parent?.color == false && - toDel!.sibling()?.color == false && - toDel!.sibling()?.left!.color == false && - toDel!.sibling()?.right!.color == false){ - - toDel!.sibling()?.color = true - toDel!.parent?.color = false - } - else{ - deleteCase4(toDel) - } - } - private func deleteCase4(toDel: RBTNode?){ - if(toDel!.parent?.color == true && - toDel!.sibling()?.color == false && - toDel!.sibling()?.left!.color == false && - toDel!.sibling()?.right!.color == false){ - - toDel!.sibling()?.color = true - toDel!.parent.color = false - } - else{ - deleteCase5(toDel) - } - } - //delete case for fixing tree if toDel is a left child and sibling(n) is black and children of sibling(n) are black and white respectibely - private func deleteCase5(toDel:RBTNode?){ - if(toDel! === toDel!.parent?.left && - toDel!.sibling()?.color == false && - toDel!.sibling()?.left.color == true && - toDel!.sibling()?.right.color == false){ - - toDel!.sibling()?.color = true - toDel!.sibling()?.left?.color = false - rightRotate(toDel!.sibling()!) - } - //opposite case - else if(toDel! === toDel!.parent?.right && - toDel!.sibling()?.color == false && - toDel!.sibling()?.left.color == false && - toDel!.sibling()?.right.color == true){ - - toDel!.sibling()?.color = true - toDel!.sibling()?.right?.color = false - leftRotate(toDel!.sibling()!) - } - } - private func deleteCase6(toDel: RBTNode?){ - let color = toDel!.sibling()?.color - toDel!.parent?.color = color! - toDel!.parent?.color = false - if(toDel! === toDel!.parent.left){ - toDel!.sibling()?.right?.color = false - leftRotate(toDel!.parent!) - } - else{ - toDel!.sibling()?.left?.color = false - rightRotate(toDel!.parent!) - } - } -} - -var tree = RBTree(rootData: 8) -tree.insert(5) -tree.insert(4) -tree.insert(9) -tree.delete(9) -tree.insert(3) -tree.insert(10) -tree.delete(3) -var x = tree.find(5) -tree.inOrder() From a62271d5c68fd4b3b6bae11764e653b4c2fa4553 Mon Sep 17 00:00:00 2001 From: Andrew McKnight Date: Thu, 5 May 2016 20:37:44 -0400 Subject: [PATCH 0356/1679] Implement Floyd-Warshall algorith for All-Pairs Shortest Paths - implement as one of a possible family of algorithms to compute APSP; towards that end, some protocols are defined for a general APSP algorithm and its result structure Changes to Graph data structure: - track vertex objects in an array as they are created for random access later - make Vertex.index public for use by external algorithms - conform to CustomStringConvertible class for printing descriptions --- .travis.yml | 5 +- .../APSP/APSP.playground/Contents.swift | 29 ++ .../APSP.playground/contents.xcplayground | 4 + .../APSP/APSP.playground/timeline.xctimeline | 16 + .../APSP/APSP.xcodeproj/project.pbxproj | 423 ++++++++++++++++++ .../xcshareddata/xcschemes/APSP.xcscheme | 91 ++++ .../xcshareddata/xcschemes/APSPTests.xcscheme | 56 +++ All-Pairs Shortest Paths/APSP/APSP/APSP.h | 19 + All-Pairs Shortest Paths/APSP/APSP/APSP.swift | 33 ++ .../APSP/APSP/FloydWarshall.swift | 200 +++++++++ .../APSP/APSP/Helpers.swift | 60 +++ All-Pairs Shortest Paths/APSP/APSP/Info.plist | 28 ++ .../APSP/APSPTests/APSPTests.swift | 119 +++++ .../APSP/APSPTests/Info.plist | 24 + All-Pairs Shortest Paths/README.md | 76 ++++ All-Pairs Shortest Paths/img/d0.png | Bin 0 -> 26452 bytes All-Pairs Shortest Paths/img/d1.png | Bin 0 -> 25961 bytes All-Pairs Shortest Paths/img/d2.png | Bin 0 -> 25837 bytes All-Pairs Shortest Paths/img/d3.png | Bin 0 -> 25924 bytes .../img/example_graph.png | Bin 0 -> 10320 bytes .../img/original_adjacency_matrix.png | Bin 0 -> 23853 bytes All-Pairs Shortest Paths/img/pi0.png | Bin 0 -> 10557 bytes All-Pairs Shortest Paths/img/pi1.png | Bin 0 -> 10564 bytes All-Pairs Shortest Paths/img/pi2.png | Bin 0 -> 10799 bytes All-Pairs Shortest Paths/img/pi3.png | Bin 0 -> 10831 bytes .../img/weight_comparison_formula.png | Bin 0 -> 28752 bytes Graph/AdjacencyMatrix.swift | 38 +- .../timeline.xctimeline | 5 + README.markdown | 2 +- 29 files changed, 1222 insertions(+), 6 deletions(-) create mode 100644 All-Pairs Shortest Paths/APSP/APSP.playground/Contents.swift create mode 100644 All-Pairs Shortest Paths/APSP/APSP.playground/contents.xcplayground create mode 100644 All-Pairs Shortest Paths/APSP/APSP.playground/timeline.xctimeline create mode 100644 All-Pairs Shortest Paths/APSP/APSP.xcodeproj/project.pbxproj create mode 100644 All-Pairs Shortest Paths/APSP/APSP.xcodeproj/xcshareddata/xcschemes/APSP.xcscheme create mode 100644 All-Pairs Shortest Paths/APSP/APSP.xcodeproj/xcshareddata/xcschemes/APSPTests.xcscheme create mode 100644 All-Pairs Shortest Paths/APSP/APSP/APSP.h create mode 100644 All-Pairs Shortest Paths/APSP/APSP/APSP.swift create mode 100644 All-Pairs Shortest Paths/APSP/APSP/FloydWarshall.swift create mode 100644 All-Pairs Shortest Paths/APSP/APSP/Helpers.swift create mode 100644 All-Pairs Shortest Paths/APSP/APSP/Info.plist create mode 100644 All-Pairs Shortest Paths/APSP/APSPTests/APSPTests.swift create mode 100644 All-Pairs Shortest Paths/APSP/APSPTests/Info.plist create mode 100644 All-Pairs Shortest Paths/README.md create mode 100644 All-Pairs Shortest Paths/img/d0.png create mode 100644 All-Pairs Shortest Paths/img/d1.png create mode 100644 All-Pairs Shortest Paths/img/d2.png create mode 100644 All-Pairs Shortest Paths/img/d3.png create mode 100644 All-Pairs Shortest Paths/img/example_graph.png create mode 100644 All-Pairs Shortest Paths/img/original_adjacency_matrix.png create mode 100644 All-Pairs Shortest Paths/img/pi0.png create mode 100644 All-Pairs Shortest Paths/img/pi1.png create mode 100644 All-Pairs Shortest Paths/img/pi2.png create mode 100644 All-Pairs Shortest Paths/img/pi3.png create mode 100644 All-Pairs Shortest Paths/img/weight_comparison_formula.png diff --git a/.travis.yml b/.travis.yml index a980968be..294f4e158 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,5 @@ language: objective-c -osx_image: xcode7.2 +osx_image: xcode7.3 script: @@ -23,4 +23,5 @@ script: - xcodebuild test -project ./Shell\ Sort/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Stack/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Longest\ Common\ Subsequence/Tests/Tests.xcodeproj -scheme Tests -- xcodebuild test -project ./Bucket\ Sort/Tests/Tests.xcodeproj -scheme Tests \ No newline at end of file +- xcodebuild test -project ./Bucket\ Sort/Tests/Tests.xcodeproj -scheme Tests +- xcodebuild test -project ./All-Pairs\ Shortest\ Paths/APSP/APSP.xcodeproj -scheme APSPTests \ No newline at end of file diff --git a/All-Pairs Shortest Paths/APSP/APSP.playground/Contents.swift b/All-Pairs Shortest Paths/APSP/APSP.playground/Contents.swift new file mode 100644 index 000000000..e14966113 --- /dev/null +++ b/All-Pairs Shortest Paths/APSP/APSP.playground/Contents.swift @@ -0,0 +1,29 @@ +//: Playground - noun: a place where people can play + +import APSP + +var graph = Graph() + +let v1 = graph.createVertex("Montreal") +let v2 = graph.createVertex("New York") +let v3 = graph.createVertex("Boston") +let v4 = graph.createVertex("Portland") +let v5 = graph.createVertex("Portsmouth") + +graph.connect(v1, to: v2, withWeight: 3) +graph.connect(v1, to: v5, withWeight: -4) +graph.connect(v1, to: v3, withWeight: 8) + +graph.connect(v2, to: v4, withWeight: 1) +graph.connect(v2, to: v5, withWeight: 7) + +graph.connect(v3, to: v2, withWeight: 4) + +graph.connect(v4, to: v1, withWeight: 2) +graph.connect(v4, to: v3, withWeight: -5) + +graph.connect(v5, to: v4, withWeight: 6) + +let result = FloydWarshall.apply(graph) + +let path = result.path(fromVertex: v1, toVertex: v4, inGraph: graph) \ No newline at end of file diff --git a/All-Pairs Shortest Paths/APSP/APSP.playground/contents.xcplayground b/All-Pairs Shortest Paths/APSP/APSP.playground/contents.xcplayground new file mode 100644 index 000000000..06828af92 --- /dev/null +++ b/All-Pairs Shortest Paths/APSP/APSP.playground/contents.xcplayground @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/All-Pairs Shortest Paths/APSP/APSP.playground/timeline.xctimeline b/All-Pairs Shortest Paths/APSP/APSP.playground/timeline.xctimeline new file mode 100644 index 000000000..522661fa7 --- /dev/null +++ b/All-Pairs Shortest Paths/APSP/APSP.playground/timeline.xctimeline @@ -0,0 +1,16 @@ + + + + + + + + + diff --git a/All-Pairs Shortest Paths/APSP/APSP.xcodeproj/project.pbxproj b/All-Pairs Shortest Paths/APSP/APSP.xcodeproj/project.pbxproj new file mode 100644 index 000000000..7df369cd7 --- /dev/null +++ b/All-Pairs Shortest Paths/APSP/APSP.xcodeproj/project.pbxproj @@ -0,0 +1,423 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 493D8DE31CDD2A1C0089795A /* APSPTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 493D8DE21CDD2A1C0089795A /* APSPTests.swift */; }; + 493D8DF41CDD5B960089795A /* APSP.h in Headers */ = {isa = PBXBuildFile; fileRef = 493D8DF31CDD5B960089795A /* APSP.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 493D8DF91CDD5B9B0089795A /* FloydWarshall.swift in Sources */ = {isa = PBXBuildFile; fileRef = 493D8DD81CDC38C60089795A /* FloydWarshall.swift */; }; + 493D8DFA1CDD5B9E0089795A /* Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 493D8DDA1CDD29C80089795A /* Helpers.swift */; }; + 493D8DFB1CDD5BDE0089795A /* AdjacencyMatrix.swift in Sources */ = {isa = PBXBuildFile; fileRef = 493D8DB91CDC34D00089795A /* AdjacencyMatrix.swift */; }; + 49BFA27A1CDD93F400522D66 /* APSP.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49BFA2791CDD93F400522D66 /* APSP.swift */; }; + 49BFA2801CDE742900522D66 /* APSP.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 493D8DF11CDD5B960089795A /* APSP.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 49BFA27E1CDE742700522D66 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 493D8D7E1CDC2DAE0089795A /* Project object */; + proxyType = 1; + remoteGlobalIDString = 493D8DF01CDD5B960089795A; + remoteInfo = APSP; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 493D8DB91CDC34D00089795A /* AdjacencyMatrix.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdjacencyMatrix.swift; sourceTree = ""; }; + 493D8DD81CDC38C60089795A /* FloydWarshall.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FloydWarshall.swift; sourceTree = ""; }; + 493D8DDA1CDD29C80089795A /* Helpers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Helpers.swift; sourceTree = ""; }; + 493D8DE01CDD2A1C0089795A /* APSPTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = APSPTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 493D8DE21CDD2A1C0089795A /* APSPTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = APSPTests.swift; sourceTree = ""; }; + 493D8DE41CDD2A1C0089795A /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 493D8DF11CDD5B960089795A /* APSP.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = APSP.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 493D8DF31CDD5B960089795A /* APSP.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = APSP.h; sourceTree = ""; }; + 493D8DF51CDD5B960089795A /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 49BFA2791CDD93F400522D66 /* APSP.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = APSP.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 493D8DDD1CDD2A1C0089795A /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 49BFA2801CDE742900522D66 /* APSP.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 493D8DED1CDD5B960089795A /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 493D8D7D1CDC2DAE0089795A = { + isa = PBXGroup; + children = ( + 493D8DB71CDC34D00089795A /* Graph */, + 493D8D881CDC2DAE0089795A /* APSP */, + 493D8DE11CDD2A1C0089795A /* APSPTests */, + 493D8D871CDC2DAE0089795A /* Products */, + ); + sourceTree = ""; + }; + 493D8D871CDC2DAE0089795A /* Products */ = { + isa = PBXGroup; + children = ( + 493D8DE01CDD2A1C0089795A /* APSPTests.xctest */, + 493D8DF11CDD5B960089795A /* APSP.framework */, + ); + name = Products; + sourceTree = ""; + }; + 493D8D881CDC2DAE0089795A /* APSP */ = { + isa = PBXGroup; + children = ( + 493D8DF31CDD5B960089795A /* APSP.h */, + 49BFA2791CDD93F400522D66 /* APSP.swift */, + 493D8DD81CDC38C60089795A /* FloydWarshall.swift */, + 493D8DDA1CDD29C80089795A /* Helpers.swift */, + 493D8DF51CDD5B960089795A /* Info.plist */, + ); + path = APSP; + sourceTree = ""; + }; + 493D8DB71CDC34D00089795A /* Graph */ = { + isa = PBXGroup; + children = ( + 493D8DB91CDC34D00089795A /* AdjacencyMatrix.swift */, + ); + name = Graph; + path = ../../Graph; + sourceTree = ""; + }; + 493D8DE11CDD2A1C0089795A /* APSPTests */ = { + isa = PBXGroup; + children = ( + 493D8DE21CDD2A1C0089795A /* APSPTests.swift */, + 493D8DE41CDD2A1C0089795A /* Info.plist */, + ); + path = APSPTests; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 493D8DEE1CDD5B960089795A /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 493D8DF41CDD5B960089795A /* APSP.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 493D8DDF1CDD2A1C0089795A /* APSPTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 493D8DE51CDD2A1C0089795A /* Build configuration list for PBXNativeTarget "APSPTests" */; + buildPhases = ( + 493D8DDC1CDD2A1C0089795A /* Sources */, + 493D8DDD1CDD2A1C0089795A /* Frameworks */, + 493D8DDE1CDD2A1C0089795A /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 49BFA27F1CDE742700522D66 /* PBXTargetDependency */, + ); + name = APSPTests; + productName = APSPTests; + productReference = 493D8DE01CDD2A1C0089795A /* APSPTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 493D8DF01CDD5B960089795A /* APSP */ = { + isa = PBXNativeTarget; + buildConfigurationList = 493D8DF61CDD5B960089795A /* Build configuration list for PBXNativeTarget "APSP" */; + buildPhases = ( + 493D8DEC1CDD5B960089795A /* Sources */, + 493D8DED1CDD5B960089795A /* Frameworks */, + 493D8DEE1CDD5B960089795A /* Headers */, + 493D8DEF1CDD5B960089795A /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = APSP; + productName = APSP; + productReference = 493D8DF11CDD5B960089795A /* APSP.framework */; + productType = "com.apple.product-type.framework"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 493D8D7E1CDC2DAE0089795A /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0730; + LastUpgradeCheck = 0730; + ORGANIZATIONNAME = "Andrew McKnight"; + TargetAttributes = { + 493D8DDF1CDD2A1C0089795A = { + CreatedOnToolsVersion = 7.3; + }; + 493D8DF01CDD5B960089795A = { + CreatedOnToolsVersion = 7.3; + }; + }; + }; + buildConfigurationList = 493D8D811CDC2DAE0089795A /* Build configuration list for PBXProject "APSP" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 493D8D7D1CDC2DAE0089795A; + productRefGroup = 493D8D871CDC2DAE0089795A /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 493D8DDF1CDD2A1C0089795A /* APSPTests */, + 493D8DF01CDD5B960089795A /* APSP */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 493D8DDE1CDD2A1C0089795A /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 493D8DEF1CDD5B960089795A /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 493D8DDC1CDD2A1C0089795A /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 493D8DE31CDD2A1C0089795A /* APSPTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 493D8DEC1CDD5B960089795A /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 49BFA27A1CDD93F400522D66 /* APSP.swift in Sources */, + 493D8DF91CDD5B9B0089795A /* FloydWarshall.swift in Sources */, + 493D8DFA1CDD5B9E0089795A /* Helpers.swift in Sources */, + 493D8DFB1CDD5BDE0089795A /* AdjacencyMatrix.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 49BFA27F1CDE742700522D66 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 493D8DF01CDD5B960089795A /* APSP */; + targetProxy = 49BFA27E1CDE742700522D66 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 493D8D8B1CDC2DAE0089795A /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 493D8D8C1CDC2DAE0089795A /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + }; + name = Release; + }; + 493D8DE61CDD2A1C0089795A /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = APSPTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.armcknight.APSPTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 493D8DE71CDD2A1C0089795A /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = APSPTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.armcknight.APSPTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + 493D8DF71CDD5B960089795A /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + FRAMEWORK_VERSION = A; + INFOPLIST_FILE = APSP/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.armcknight.APSP; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 493D8DF81CDD5B960089795A /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + FRAMEWORK_VERSION = A; + INFOPLIST_FILE = APSP/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.armcknight.APSP; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 493D8D811CDC2DAE0089795A /* Build configuration list for PBXProject "APSP" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 493D8D8B1CDC2DAE0089795A /* Debug */, + 493D8D8C1CDC2DAE0089795A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 493D8DE51CDD2A1C0089795A /* Build configuration list for PBXNativeTarget "APSPTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 493D8DE61CDD2A1C0089795A /* Debug */, + 493D8DE71CDD2A1C0089795A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 493D8DF61CDD5B960089795A /* Build configuration list for PBXNativeTarget "APSP" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 493D8DF71CDD5B960089795A /* Debug */, + 493D8DF81CDD5B960089795A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 493D8D7E1CDC2DAE0089795A /* Project object */; +} diff --git a/All-Pairs Shortest Paths/APSP/APSP.xcodeproj/xcshareddata/xcschemes/APSP.xcscheme b/All-Pairs Shortest Paths/APSP/APSP.xcodeproj/xcshareddata/xcschemes/APSP.xcscheme new file mode 100644 index 000000000..475997aa9 --- /dev/null +++ b/All-Pairs Shortest Paths/APSP/APSP.xcodeproj/xcshareddata/xcschemes/APSP.xcscheme @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/All-Pairs Shortest Paths/APSP/APSP.xcodeproj/xcshareddata/xcschemes/APSPTests.xcscheme b/All-Pairs Shortest Paths/APSP/APSP.xcodeproj/xcshareddata/xcschemes/APSPTests.xcscheme new file mode 100644 index 000000000..867745024 --- /dev/null +++ b/All-Pairs Shortest Paths/APSP/APSP.xcodeproj/xcshareddata/xcschemes/APSPTests.xcscheme @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/All-Pairs Shortest Paths/APSP/APSP/APSP.h b/All-Pairs Shortest Paths/APSP/APSP/APSP.h new file mode 100644 index 000000000..59613bceb --- /dev/null +++ b/All-Pairs Shortest Paths/APSP/APSP/APSP.h @@ -0,0 +1,19 @@ +// +// APSP.h +// APSP +// +// Created by Andrew McKnight on 5/6/16. +// Copyright © 2016 Andrew McKnight. All rights reserved. +// + +#import + +//! Project version number for APSP. +FOUNDATION_EXPORT double APSPVersionNumber; + +//! Project version string for APSP. +FOUNDATION_EXPORT const unsigned char APSPVersionString[]; + +// In this header, you should import all the public headers of your framework using statements like #import + + diff --git a/All-Pairs Shortest Paths/APSP/APSP/APSP.swift b/All-Pairs Shortest Paths/APSP/APSP/APSP.swift new file mode 100644 index 000000000..22ad4a958 --- /dev/null +++ b/All-Pairs Shortest Paths/APSP/APSP/APSP.swift @@ -0,0 +1,33 @@ +// +// Base.swift +// APSP +// +// Created by Andrew McKnight on 5/6/16. +// Copyright © 2016 Andrew McKnight. All rights reserved. +// + +import Foundation + +/** + APSPAlgorithm is a protocol for encapsulating an All-Pairs Shortest Paths algorithm. It provides a single function `apply` that accepts a `Graph` and returns an object conforming to `APSPResult`. + */ +protocol APSPAlgorithm { + + associatedtype Q + associatedtype P: APSPResult + + static func apply(graph: Graph) -> P + +} + +/** + APSPResult is a protocol defining functions `distance` and `path`, allowing for opaque queries into the actual data structures that represent the APSP solution according to the algorithm used. + */ +protocol APSPResult { + + associatedtype T + + func distance(fromVertex from: Vertex, toVertex to: Vertex) -> Double? + func path(fromVertex from: Vertex, toVertex to: Vertex, inGraph graph: Graph) -> [T]? + +} diff --git a/All-Pairs Shortest Paths/APSP/APSP/FloydWarshall.swift b/All-Pairs Shortest Paths/APSP/APSP/FloydWarshall.swift new file mode 100644 index 000000000..976d3138c --- /dev/null +++ b/All-Pairs Shortest Paths/APSP/APSP/FloydWarshall.swift @@ -0,0 +1,200 @@ +// +// FloydWarshall.swift +// APSP +// +// Created by Andrew McKnight on 5/5/16. +// Copyright © 2016 Andrew McKnight. All rights reserved. +// + +import Foundation + +private typealias Distances = [[Double]] +private typealias Predecessors = [[Int?]] +private typealias StepResult = (distances: Distances, predecessors: Predecessors) + +/** + Encapsulation of the Floyd-Warshall All-Pairs Shortest Paths algorithm, conforming to the APSPAlgorithm protocol. + + - note: In all complexity bounds, `V` is the number of vertices in the graph, and `E` is the number of edges. + */ +public struct FloydWarshall: APSPAlgorithm { + + typealias Q = T + typealias P = FloydWarshallResult + + /** + Floyd-Warshall algorithm for computing all-pairs shortest paths in a weighted directed graph. + + - precondition: `graph` must have no negative weight cycles + - complexity: `Θ(V^3)` time, `Θ(V^2)` space + - returns a `FloydWarshallResult` struct which can be queried for shortest paths and their total weights + */ + public static func apply(graph: Graph) -> FloydWarshallResult { + + var previousDistance = constructInitialDistanceMatrix(graph) + var previousPredecessor = constructInitialPredecessorMatrix(previousDistance) + for intermediateIdx in 0 ..< graph.vertices.count { + let nextResult = nextStep(intermediateIdx, previousDistances: previousDistance, previousPredecessors: previousPredecessor, graph: graph) + previousDistance = nextResult.distances + previousPredecessor = nextResult.predecessors + +// // uncomment to see each new weight matrix +// print(" D(\(k)):\n") +// printMatrix(nextResult.distances) +// +// // uncomment to see each new predecessor matrix +// print(" ∏(\(k)):\n") +// printIntMatrix(nextResult.predecessors) + } + return FloydWarshallResult(weights: previousDistance, predecessors: previousPredecessor) + + } + + /** + For each iteration of `intermediateIdx`, perform the comparison for the dynamic algorith, checking for each pair of start/end vertices, whether a path taken through another vertex produces a shorter path. + + - complexity: `Θ(V^2)` time/space + - returns: a tuple containing the next distance matrix with weights of currently known shortest paths and the corresponding predecessor matrix + */ + static private func nextStep(intermediateIdx: Int, previousDistances: Distances, previousPredecessors: Predecessors, graph: Graph) -> StepResult { + + let vertexCount = graph.adjacencyMatrix.count + var nextDistances = Array(count: vertexCount, repeatedValue: Array(count: vertexCount, repeatedValue: Double.infinity)) + var nextPredecessors = Array(count: vertexCount, repeatedValue: Array(count: vertexCount, repeatedValue: nil)) + + for fromIdx in 0 ..< vertexCount { + for toIndex in 0 ..< vertexCount { +// printMatrix(previousDistances, i: fromIdx, j: toIdx, k: intermediateIdx) // uncomment to see each comparison being made + let originalPathWeight = previousDistances[fromIdx][toIndex] + let newPathWeightBefore = previousDistances[fromIdx][intermediateIdx] + let newPathWeightAfter = previousDistances[intermediateIdx][toIndex] + + let minimum = min(originalPathWeight, newPathWeightBefore + newPathWeightAfter) + nextDistances[fromIdx][toIndex] = minimum + + var predecessor: Int? + if originalPathWeight <= newPathWeightBefore + newPathWeightAfter { + predecessor = previousPredecessors[fromIdx][toIndex] + } else { + predecessor = previousPredecessors[intermediateIdx][toIndex] + } + nextPredecessors[fromIdx][toIndex] = predecessor + } + } + return (nextDistances, nextPredecessors) + + } + + /** + We need to convert the value system in Graph's adjacency matrix to the one we need to perform the algorithm. We need the actual weight between two vertices, or infinity if no edge exists, represented by nil in Graph.adjacencyMatrix. Also set the weight to 0 on the diagonal. + + - complexity: `Θ(V^2)` time/space + - returns: weighted adjacency matrix in form ready for processing with Floyd-Warshall + */ + static private func constructInitialDistanceMatrix(graph: Graph) -> Distances { + + let vertexCount = graph.adjacencyMatrix.count + var distances = Array(count: vertexCount, repeatedValue: Array(count: vertexCount, repeatedValue: Double.infinity)) + + for fromIdx in 0 ..< vertexCount { + for toIdx in 0 ..< vertexCount { + if fromIdx == toIdx { + distances[fromIdx][toIdx] = 0.0 + } else if let w = graph.adjacencyMatrix[fromIdx][toIdx] { + distances[fromIdx][toIdx] = w + } + } + } + + return distances + + } + + /** + Make the initial predecessor index matrix. Initially each value is equal to it's row index, it's "from" index when querying into it. + + - complexity: `Θ(V^2)` time/space + */ + static private func constructInitialPredecessorMatrix(distances: Distances) -> Predecessors { + + let vertexCount = distances.count + var predecessors = Array(count: vertexCount, repeatedValue: Array(count: vertexCount, repeatedValue: nil)) + + for fromIdx in 0 ..< vertexCount { + for toIdx in 0 ..< vertexCount { + if fromIdx != toIdx && distances[fromIdx][toIdx] < Double.infinity { + predecessors[fromIdx][toIdx] = fromIdx + } + } + } + + return predecessors + + } + +} + +/** + FloydWarshallResult encapsulates the result of the computation, namely the minimized distance adjacency matrix, and the matrix of predecessor indices. + + It conforms to the APSPResult procotol which provides methods to retrieve distances and paths between given pairs of start and end nodes. + */ +public struct FloydWarshallResult: APSPResult { + + private var weights: Distances + private var predecessors: Predecessors + + /** + - returns: the total weight of the path from a starting vertex to a destination. This value is the minimal connected weight between the two vertices. + - complexity: `Θ(1)` time/space + */ + public func distance(fromVertex from: Vertex, toVertex to: Vertex) -> Double? { + + return weights[from.index][to.index] + + } + + /** + - returns: the reconstructed path from a starting vertex to a destination, as an array containing the data property of each vertex + - complexity: `Θ(V)` time, `Θ(V^2)` space + */ + public func path(fromVertex from: Vertex, toVertex to: Vertex, inGraph graph: Graph) -> [T]? { + + if let path = recursePathFrom(predecessors, fromVertex: from, toVertex: to, path: [ to ], inGraph: graph) { + let pathValues = path.map() { vertex in + vertex.data + } + return pathValues + } + return nil + + } + + /** + The recursive component to rebuilding the shortest path between two vertices using the predecessor graph. + + - returns: the list of predecessors discovered so far + */ + private func recursePathFrom(predecessors: [[Int?]], fromVertex from: Vertex, toVertex to: Vertex, path: [Vertex], inGraph graph: Graph) -> [Vertex]? { + + if from.index == to.index { + return [ from, to ] + } + + if let predecessor = predecessors[from.index][to.index] { + let predecessorVertex = graph.vertices[predecessor] + if predecessor == from.index { + let newPath = [ from, to ] + return newPath + } else { + let buildPath = recursePathFrom(predecessors, fromVertex: from, toVertex: predecessorVertex, path: path, inGraph: graph) + let newPath = buildPath! + [ to ] + return newPath + } + } + + return nil + + } + +} diff --git a/All-Pairs Shortest Paths/APSP/APSP/Helpers.swift b/All-Pairs Shortest Paths/APSP/APSP/Helpers.swift new file mode 100644 index 000000000..c6f22e879 --- /dev/null +++ b/All-Pairs Shortest Paths/APSP/APSP/Helpers.swift @@ -0,0 +1,60 @@ +// +// Helpers.swift +// APSP +// +// Created by Andrew McKnight on 5/6/16. +// Copyright © 2016 Andrew McKnight. All rights reserved. +// + +import Foundation + +/** + Print a matrix, optionally specifying only the cells to display with the triplet (i, j, k) -> matrix[i][j], matrix[i][k], matrix[k][j] + */ +func printMatrix(matrix: [[Double]], i: Int = -1, j: Int = -1, k: Int = -1) { + + if i >= 0 { + print(" k: \(k); i: \(i); j: \(j)\n") + } + + var grid = [String]() + + let n = matrix.count + for x in 0.. + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + NSHumanReadableCopyright + Copyright © 2016 Andrew McKnight. All rights reserved. + NSPrincipalClass + + + diff --git a/All-Pairs Shortest Paths/APSP/APSPTests/APSPTests.swift b/All-Pairs Shortest Paths/APSP/APSPTests/APSPTests.swift new file mode 100644 index 000000000..47b71b3ea --- /dev/null +++ b/All-Pairs Shortest Paths/APSP/APSPTests/APSPTests.swift @@ -0,0 +1,119 @@ +// +// APSPTests.swift +// APSPTests +// +// Created by Andrew McKnight on 5/6/16. +// Copyright © 2016 Andrew McKnight. All rights reserved. +// + +import APSP +import XCTest + +struct TestCase { + + var from: Vertex + var to: Vertex + var expectedPath: [T] + var expectedDistance: Double + +} + +class APSPTests: XCTestCase { + + func testExampleFromBook() { + + var graph = Graph() + let v1 = graph.createVertex("Montreal") + let v2 = graph.createVertex("New York") + let v3 = graph.createVertex("Boston") + let v4 = graph.createVertex("Portland") + let v5 = graph.createVertex("Portsmouth") + + graph.connect(v1, to: v2, withWeight: 3) + graph.connect(v1, to: v5, withWeight: -4) + graph.connect(v1, to: v3, withWeight: 8) + + graph.connect(v2, to: v4, withWeight: 1) + graph.connect(v2, to: v5, withWeight: 7) + + graph.connect(v3, to: v2, withWeight: 4) + + graph.connect(v4, to: v1, withWeight: 2) + graph.connect(v4, to: v3, withWeight: -5) + + graph.connect(v5, to: v4, withWeight: 6) + + let result = FloydWarshall.apply(graph) + + let cases = [ + TestCase(from: v1, to: v4, expectedPath: ["Montreal", "Portsmouth", "Portland"], expectedDistance: 2), + TestCase(from: v1, to: v5, expectedPath: ["Montreal", "Portsmouth"], expectedDistance: -4), + TestCase(from: v2, to: v1, expectedPath: ["New York", "Portland", "Montreal"], expectedDistance: 3), + TestCase(from: v2, to: v3, expectedPath: ["New York", "Portland", "Boston"], expectedDistance: -4), + TestCase(from: v2, to: v4, expectedPath: ["New York", "Portland"], expectedDistance: 1), + TestCase(from: v2, to: v5, expectedPath: ["New York", "Portland", "Montreal", "Portsmouth"], expectedDistance: -1), + TestCase(from: v3, to: v1, expectedPath: ["Boston", "New York", "Portland", "Montreal"], expectedDistance: 7), + TestCase(from: v3, to: v2, expectedPath: ["Boston", "New York"], expectedDistance: 4), + TestCase(from: v3, to: v4, expectedPath: ["Boston", "New York", "Portland"], expectedDistance: 5), + TestCase(from: v3, to: v5, expectedPath: ["Boston", "New York", "Portland", "Montreal", "Portsmouth"], expectedDistance: 3), + TestCase(from: v4, to: v1, expectedPath: ["Portland", "Montreal"], expectedDistance: 2), + TestCase(from: v4, to: v2, expectedPath: ["Portland", "Boston", "New York"], expectedDistance: -1), + TestCase(from: v4, to: v3, expectedPath: ["Portland", "Boston"], expectedDistance: -5), + TestCase(from: v4, to: v5, expectedPath: ["Portland", "Montreal", "Portsmouth"], expectedDistance: -2), + TestCase(from: v5, to: v1, expectedPath: ["Portsmouth", "Portland", "Montreal"], expectedDistance: 8), + TestCase(from: v5, to: v2, expectedPath: ["Portsmouth", "Portland", "Boston", "New York"], expectedDistance: 5), + TestCase(from: v5, to: v3, expectedPath: ["Portsmouth", "Portland", "Boston"], expectedDistance: 1), + TestCase(from: v5, to: v4, expectedPath: ["Portsmouth", "Portland"], expectedDistance: 6), + ] + + for testCase: TestCase in cases { + if let computedPath = result.path(fromVertex: testCase.from, toVertex: testCase.to, inGraph: graph), + computedDistance = result.distance(fromVertex: testCase.from, toVertex: testCase.to) { + XCTAssert(computedDistance == testCase.expectedDistance, "expected distance \(testCase.expectedDistance) but got \(computedDistance)") + XCTAssert(computedPath == testCase.expectedPath, "expected path \(testCase.expectedPath) but got \(computedPath)") + } + } + + } + + func testExampleFromReadme() { + + var graph = Graph() + let v1 = graph.createVertex(1) + let v2 = graph.createVertex(2) + let v3 = graph.createVertex(3) + let v4 = graph.createVertex(4) + + graph.connect(v1, to: v2, withWeight: 4) + graph.connect(v1, to: v3, withWeight: 1) + graph.connect(v1, to: v4, withWeight: 3) + + graph.connect(v2, to: v3, withWeight: 8) + graph.connect(v2, to: v4, withWeight: -2) + + graph.connect(v3, to: v4, withWeight: -5) + + let result = FloydWarshall.apply(graph) + + let cases = [ + TestCase(from: v1, to: v2, expectedPath: [1, 2], expectedDistance: 4), + TestCase(from: v1, to: v3, expectedPath: [1, 3], expectedDistance: 1), + TestCase(from: v1, to: v4, expectedPath: [1, 3, 4], expectedDistance: -4), + + TestCase(from: v2, to: v3, expectedPath: [2, 3], expectedDistance: 8), + TestCase(from: v2, to: v4, expectedPath: [2, 4], expectedDistance: -2), + + TestCase(from: v3, to: v4, expectedPath: [3, 4], expectedDistance: -5), + ] + + for testCase: TestCase in cases { + if let computedPath = result.path(fromVertex: testCase.from, toVertex: testCase.to, inGraph: graph), + computedDistance = result.distance(fromVertex: testCase.from, toVertex: testCase.to) { + XCTAssert(computedDistance == testCase.expectedDistance, "expected distance \(testCase.expectedDistance) but got \(computedDistance)") + XCTAssert(computedPath == testCase.expectedPath, "expected path \(testCase.expectedPath) but got \(computedPath)") + } + } + + } + +} diff --git a/All-Pairs Shortest Paths/APSP/APSPTests/Info.plist b/All-Pairs Shortest Paths/APSP/APSPTests/Info.plist new file mode 100644 index 000000000..ba72822e8 --- /dev/null +++ b/All-Pairs Shortest Paths/APSP/APSPTests/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/All-Pairs Shortest Paths/README.md b/All-Pairs Shortest Paths/README.md new file mode 100644 index 000000000..8a75c8b73 --- /dev/null +++ b/All-Pairs Shortest Paths/README.md @@ -0,0 +1,76 @@ +# All-Pairs Shortest Paths + +The All-Pairs shortest path problem simultaneously computes the shortest path from each node in the graph to each other node, provded a path exists for each pair. In the naive approach, we could simply compute a single-source shortest path from each node to each other node. The number of shortest paths computed is then bound by `O(V^2)`, where `V` is the number of vertices in the graph. Because SSSP is also bounded by `O(V^2)`, the total running time for the naive approach would be `O(V^4)`. + +However, by applying a dynamic approach on the adjacency matrix of the graph, a running time of `Θ(V^3)` is achievable, using the `Floyd-Warshall` algorithm. Floyd-Warshall iterates through an adjacency matrix, and for each pair of start(`i`) and end(`j`) vertices it considers if the current distance between them is greater than a path taken through another vertex(`k`) in the graph (if paths `i` ~> `k` and `k` ~> `j` exist). It moves through an adjacency matrix for every vertex `k` applying its comparison for each pair (`i`, `j`), so for each `k` a new adjacency matrix `D(k)` is derived, where each value `d(k)[i][j]` is defined as: + + + +where `w[i][j]` is the weight of the edge connecting vertex `i` to vertex `j` in the graph's original adjacency matrix. + +When the algorithm memoizes each refined adjacency and predecessor matrix, its space complexity is `Θ(V^3)`, which can be optimised to `Θ(V^2)` by only memoizing the latest refinements. Reconstructing paths is a recursive procedure which requires `Θ(V)` time and `Θ(V^2)` space. + +# Example + +For the following weighted directed graph + + + +the adjacency matrix representation `w` is + + + +### Calculating shortest paths' weights + +At the beginning of the algorithm, `D(0)` is the same as `w`, with the following exceptions to accomodate the comparison function: + +1. vertices with no path connecting them have the `ø` replaced with `∞` +2. the diagonal has all `0`s + +Here are all the adjacency matrices derived when perform Floyd-Warshall on the above graph: + + + + + + + +with the last being the result, which tells for each pair of starting and ending vertices, the total weight of the shortest path connecting them. During the step where `k = 2`, the comparison that winds up changing the top right value from `2` to `-4` goes like this: + + k = 2, i = 0, j = 3 + d(k-1)[i][j] => d(1)[0][3] = 2 + d(k-1)[i][k] => d(1)[0][2] = 1 + d(k-1)[j][k] => d(1)[2][3] = -5 + +therefore `min(2, 2 + -5) => min(2, -4)` produces a new weight of `-4` for the element at `d(2)[0][3]`, meaning that the shortest known path 1 ~> 4 before this step was from 1 -> 2 -> 4 with a total weight of -2, and afterwards we discovered a shorter path from 1 -> 3 -> 4 with a total weight of -4. + +### Reconstructing shortest paths + +This algorithm finds only the lengths of the shortest paths between all pairs of nodes; a separate bookkeeping structure must be maintained to track predecessors' indices and reconstruct the shortest paths afterwards. The predecessor matrices at each step for the above graph follow: + + + + + + + +# Project Structure + +The provided xcworkspace allows working in the playground, which imports the APSP framework target from the xcodeproj. Build the framework target and rerun the playground to get started. There is also a test target in the xcodeproj. + +In the framework: + +- protocols for All-Pairs Shortest Paths algorithms and results structures +- an implementation of the Floyd-Warshall algorithm + +# TODO + +- Implement naive `Θ(V^4)` method for comparison +- Implement Johnson's algorithm for sparse graphs +- Implement other cool optimized versions + +# References + +Chapter 25 of Introduction to Algorithms, Third Edition by Cormen, Leiserson, Rivest and Stein [https://mitpress.mit.edu/books/introduction-algorithms](https://mitpress.mit.edu/books/introduction-algorithms) + +*Written for Swift Algorithm Club by [Andrew McKnight](https://github.com/armcknight)* \ No newline at end of file diff --git a/All-Pairs Shortest Paths/img/d0.png b/All-Pairs Shortest Paths/img/d0.png new file mode 100644 index 0000000000000000000000000000000000000000..4b0ea441cda3f02d6e50608f1f5785189a60ce83 GIT binary patch literal 26452 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≪a@nl#WTAt`?Z(f9Ycwizgm4h{x^08r4^`Ul;jlnfWC!F| zdYXDvE#v`5jfOX?9Z!F_qnt+^5F_1SXXh>Vw#=VWfL&ka7dAJpJo)!I5Gsw?1zz}XX@jUR*w6Dni~EtZ+8u4v-l8n9e;d$<(Bn_uJw2<; zCZS)NqyM`=SU@XIv06t~*V&K~jWoG_^*m)YX2ZiFbjW@zynl2t@T=HFlWBUivQPn6 z;G*)RX%CTpPiOpih8_?*{7nD|S@o2&+DVtPLhmnaj5i2#qmB)bo&W#3^TRct^1M0{ zlmv7hiVv#82AaINHm#? zjoCL=(O*wdTYz%s=crpR0-Mhb2mYoxH@vQbw^wp&Wf1@+!sQG>&>)?_|68i6V4KI!y2hnqRr5CYU`+z~3PngK#{|Ui~Yp%u$!#CPC2-hrGCKa+J;fS+} z0Rf3#BX8un#lo-PF}`*#YYK{K?i+g&PPz`jx5_rS2@b0dsn~<*W-jcyJqXt(;T`y@y!Irj@yX z=;{200LKAuqep{{DtppGFN@EG}lZ&$Gb`kb|` zm(iuYPpL#-{Z5G6vOt@if5Y6)Gq0pyj+eNULK!LMcL=RD#Wn3M^h9m(h{1yS*v-2(C%8{Uu2nel`= zc>Z^11P%iaz9hNmh4$FhE{L*o+Pu{rA~z6~Lej;WnhOH0vd5)e*iou>!Kn|lU;GIH z1M&efZ2F|R6MWGKy1-`={;xZedUTB3XqB>2w={@h)a}WA5Id-ai_H6GXsV;9-BYsI z-@%bVrn1KoeryA8D2leRKVn25fOTxhlPDs-(KkL(X;#7$qSx$n997~3jr}^rfO|&O zCw$5MT83Hz74q(Kjj5fB%eZqN(K6Ap`XbI9%^b?SOs{5$;U)?w64s7OE_u9hx<6A+ zjtErHEA=+f{rs-InFW*;fY(e2{#Om$8?mF-`ks7dV7Y8sc*w(8##@c0Um)H z*!z#iPi%J>G%iroHl%ALR!yv{sV*=@kkL;9UDl=`9&lav5kYkIC0*9MoL<3f`7p3 zOU@+#9=jkWMuD&8{n*EqF21SRIuAo8JS|-Fyk4Bdq7~!>$>eewf*;X-nE&B5#x)L60E`uKLDDjQQe z3-6!()HxW2m1EzP?6gAGb37-~!>SN72c@BSq%(Ajxx15L9-lWHXALcBYuD3q>~~*Q z41Vi6-`W zo-}pu)Q7ZwvjFgEqa$lpsQ&z;@M+bSk2vc+yyD=ds3m6M>v8l!SZTbogN`-0+889y z>$jH-FfaHQOV{;H_0VT{`p%{oZT$$y5h3e5rfM(K&C!~oW(N&w!L=TV7Yuip`F_0f z4zu`KLcR-RpJIL$84!E8l5$zz;x5=LY5Jg4oZf8+qBopB*NC~(V@tQp$T@lWmf+n4rTPIY2VxEr`1fAfo zI_>ifsiZCF`amHNTVy?KCahuO;F6@)LKQNm=kHLtQ!)88K^5H#Xo{JVY6U~&neY_> ztmd(g!Cd~?!d~Td5fp3jtH@8SH24XXRvW`9b4d>`U3_oVL!3lhj!)aa!!sZ~IMD;X zKHZ{qla@sDWX$IRRa^kN2g?VX`2;A6K4~%Xyn5e8x3BQQ0mde6R1V<>e+H{Dw!cUS zL5>fZ8|f0dwu(FQ>5k|&PiG<&jRmw%fKbG|nebIX_W(GC!1m^z&|X6!KeYsqrdl%2 zoI_`-iKT#TL~xS^zFnQoM)TBm%j%890$j0ECu1bH5LT8vs_*h^=DjKc-PXn=v3ywv zj!&qan^UPT#QDA0XMxA{SXzu^u1v~@vhTFpbcuA;BvPW_a<}A2?jO%$-tXUb(LPjP z<Dfs{oe44y7ipnhVNB4S;Xa`}2U}$2`JoD~U5j|9<{=(Sz6{bKE zbl~dDnWlFC+^2ds>U>9uBAUck9=YJ)CMEpi2>FJ_g4xP@d9*OW?}N8e{d?vgLKRGc zhG)%M4hLXiQuh%3p=jk`jKT@Z&;wZ)Q>!qAGWJFg8v4rCzmk_XON##nupqMGG|5dt z+>vKm%|z@#3y}>xPfgu8gHEb<6>%?&Vxy0npY&KBHD>b4yD!$2YsM=~J(%@6Y4Y0u zbV@vsI_{Adm^ZCzu+Dyj*XPT~3H4Zo@>BID*-t8oJjWe2u@CU{ShHnYVbZM?6Z2kO z1(Jpst`NGj(Np<%I*kT>r$Y1+JQPD&0F*9UR}zuC;rJexoBgaNP@%NMSG&@qA`dey zrPhOR_E;ObQe&fg^&>Z!Qe&1)-A^ib>!_rs&*#*eJi!6w!Y)Ps^5K!n{cQ!4!Lpoi z(yi@rBJu%Fp}jl`M4Qj64Q@ofNM>K=()6mm-EfM(KNG8Q00ppnzt!d9)@+n{Ldyft z`{3i?dfiPDfch8XfWLj*w%zwJ>S>ilA)Ojyj9-miVkx3uBcl_^zhETjqz-`dcPtCK zS-S@_A12@wTqnmfOg@=ne$#I4ij>uXks=lF?fS*IJGYDiD1Zb4NQ&e05SiAwJxWOo z1_x%FePxtNZNfyFSTsPX;sIyk@$l&>zZ89?`TS```^udcD*pcx z(1q9j9}l(i6dlYQqCjy9CZq?`JsaB!SnP#sKxJ~;Ss|xW+8<3vjMs5ulxaUfQX+#J zN**)XHO|a)_NX@H>^th$$4ZN4t93{Erhe3;i6{)gcTM#z0CrI^e*T_BjBW(VAXm$~ zQm4PO$95yOID)Pgfe&*LRqz4yArfLsYP5qY4d(Z@)u#$N$W#{qH^XV6MJ!}OJr3X=82-+SJo?MsOgPNwhEWI@v7pm4h zwA+7M($8deSIR}8F4Tp#clZPt!3+npl2tp9MbDhan(eK6!0>HVhNDk(nPIwHWb>np z8|gA|que)4#5T4lb)UZkioP00#TgXi$VFquYEouDt~x42A>TIR2$wP zNdhw2*}&2gGGo0t(HlMTnZTC+VH`iVOO07!Yu>#Ey;D|SnXZp_Uw6WWsXkC{= zB<$`x=94orG{~8W8z`L6?`~P^KqG(VoB9gDDtD3^vo~(}YNNR1)<`Pj&_D=kOFG8^ z%JiAXU>y1kgFLfbi$D5;my5f=`R2rqpM~n&=nJ0NMkCr2Xzt+Zp72CJau@bIp7uZ@ zr*F{WwlPbG7AL`bp_YR*q{odh{{DzA2jDP3+B||vf(A3aGPVGzOO5xlN{1II!!eXZ z(>j}+C!!4YG=TnvO&_;Hov76>uduLex`2rZ%#_{SX^Kxcuv6bqaFG@fR1T{O;M$gCS1JSQ{_*z7xpb(vO#f*zkfxk$y8;O7ovAQQaIik zPpM1_0d(wdor?uthBAG3$|Tmk2@Fol3L*ab!NFi%#DMfKM=+Wt`*}}GL%R8@2krSb zdK0w5-8&5lMVvZb{s)rb(*%t>Q}0h58)Z$LI}bc1tF}AbZ)XxJow-g@@t5tntidG8 zA9S}TiVd*NX*vM!D(B1v_mncy$=X}~#yx;#{;DDuWHWmrEPCh{5(D{0eD1E&E3izY zV26GSu*CjU>P=F3cKW<)MThSiY81{Fuv(*uHoR|81p4ofzTq#PA|K=E#+Zxb0+tdi zt`V=<=mrmkgIvXnELr$}7mtn!!MLu|vIN~v=b0veyo?HNC?cS})W{pw{4XKe1cY&s z*h~&%Bi~wZSC#-%LYW-7k9`}z(#8AyUU{Z6N6<~Hb0Ox%OXP4EPS^>jZ^%}ZSb7DJFV`>bpS_o|SvN9Z|!>K9H( z1-S5$GwwG(=w^(M?W99NZu7tgvn*ul$0wih|CsNq3&-r!1(T1xq#N!MfU}~P^edhG7 zM1+3zBc{uXfVI_+j}AxS=VDAUG-LwAA*^5n=qz!ksZ{kusYHkM@1Fqnp6avO(YzZj z(DX;)qhgAs=f+02vEU?kXw0v?-r4{9!uZe2V*#nV@%T~0^;%iX`q{;Yx_io3sPf9O PfIn45*e#^I#iRcL?EKdG literal 0 HcmV?d00001 diff --git a/All-Pairs Shortest Paths/img/d3.png b/All-Pairs Shortest Paths/img/d3.png new file mode 100644 index 0000000000000000000000000000000000000000..f582c7b8733be04b27a4dde1024461595027a44b GIT binary patch literal 25924 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 I0rB|%0COC&>i_@% literal 0 HcmV?d00001 diff --git a/All-Pairs Shortest Paths/img/example_graph.png b/All-Pairs Shortest Paths/img/example_graph.png new file mode 100644 index 0000000000000000000000000000000000000000..5d1a50acc12254bc819713247a44418d8cbe0535 GIT binary patch literal 10320 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 literal 0 HcmV?d00001 diff --git a/All-Pairs Shortest Paths/img/original_adjacency_matrix.png b/All-Pairs Shortest Paths/img/original_adjacency_matrix.png new file mode 100644 index 0000000000000000000000000000000000000000..8dcdd0237bdc4ffff12f6c0076fa76e56fe9a73b GIT binary patch literal 23853 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 literal 0 HcmV?d00001 diff --git a/All-Pairs Shortest Paths/img/pi1.png b/All-Pairs Shortest Paths/img/pi1.png new file mode 100644 index 0000000000000000000000000000000000000000..661d7ab5d1ae19ddcec1a979ab3598fbfecbda8e GIT binary patch literal 10564 zcmY*;2|Ux`AOA2%2RTbp<}B1U=jJxMFdK7Egt3`pv&}H%ibBa9ohVm2oE^xO9F2DYp{<0Ek*yqU-?xzGB{U zg@_REH=;1&8}AS3hrlBMfa>&JYuzJstpvR09Cw5&?h}UQ*m701yfV0H(bF z0KJ!CQ3?M75(q?&rb^1|Nqv+2>DO5cnySX z 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

lxp^1Z>mN23h6$7}Kp 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 literal 0 HcmV?d00001 diff --git a/Graph/AdjacencyMatrix.swift b/Graph/AdjacencyMatrix.swift index 85a16d94f..d1d35ac02 100644 --- a/Graph/AdjacencyMatrix.swift +++ b/Graph/AdjacencyMatrix.swift @@ -1,12 +1,19 @@ +import Foundation + public struct Vertex { public var data: T - private let index: Int + public let index: Int } + + public struct Graph { // If adjacencyMatrix[i][j] is not nil, then there is an edge from // vertex i to vertex j. - private var adjacencyMatrix: [[Double?]] = [] + var adjacencyMatrix: [[Double?]] = [] + var vertices: [Vertex] = [] + + public init() {} // Adds a new vertex to the matrix. // Performance: possibly O(n^2) because of the resizing of the matrix. @@ -22,9 +29,34 @@ public struct Graph { let newRow = [Double?](count: adjacencyMatrix.count + 1, repeatedValue: nil) adjacencyMatrix.append(newRow) + vertices.append(vertex) return vertex } - +} + +extension Graph: CustomStringConvertible { + public var description: String { + get { + var grid = [String]() + let n = self.adjacencyMatrix.count + for i in 0.. dest. public mutating func connect(sourceVertex: Vertex, to destinationVertex: Vertex, withWeight weight: Double = 0) { adjacencyMatrix[sourceVertex.index][destinationVertex.index] = weight diff --git a/Graph/Graph.playground/Pages/Adjacency Matrix.xcplaygroundpage/timeline.xctimeline b/Graph/Graph.playground/Pages/Adjacency Matrix.xcplaygroundpage/timeline.xctimeline index bf468afec..60cd19e82 100644 --- a/Graph/Graph.playground/Pages/Adjacency Matrix.xcplaygroundpage/timeline.xctimeline +++ b/Graph/Graph.playground/Pages/Adjacency Matrix.xcplaygroundpage/timeline.xctimeline @@ -2,5 +2,10 @@ + + diff --git a/README.markdown b/README.markdown index bbc10fb8d..4f2001ce6 100644 --- a/README.markdown +++ b/README.markdown @@ -172,7 +172,7 @@ Most of the time using just the built-in `Array`, `Dictionary`, and `Set` types - [Depth-First Search (DFS)](Depth-First Search/) - [Shortest Path](Shortest Path %28Unweighted%29/) on an unweighted tree - [Minimum Spanning Tree](Minimum Spanning Tree %28Unweighted%29/) on an unweighted tree -- All Paths +- [All-Pairs Shortest Paths](All-Pairs Shortest Paths/) ## Puzzles From fc64b1e04002078c8fb85b7e750368811e690029 Mon Sep 17 00:00:00 2001 From: Matthijs Hollemans Date: Sun, 8 May 2016 19:04:48 +0200 Subject: [PATCH 0357/1679] Rename README.md to .markdown --- All-Pairs Shortest Paths/{README.md => README.markdown} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename All-Pairs Shortest Paths/{README.md => README.markdown} (100%) diff --git a/All-Pairs Shortest Paths/README.md b/All-Pairs Shortest Paths/README.markdown similarity index 100% rename from All-Pairs Shortest Paths/README.md rename to All-Pairs Shortest Paths/README.markdown From c41a631cfdfe7394ecff9c8903ecb1cd0a95217b Mon Sep 17 00:00:00 2001 From: Matthijs Hollemans Date: Mon, 9 May 2016 09:11:50 +0200 Subject: [PATCH 0358/1679] No longer gitignore xcworkspace --- .gitignore | 1 - .../playground.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../project.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../project.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../playground.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../project.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../playground.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../project.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../playground.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../playground.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../project.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../playground.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../playground.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../playground.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../project.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../project.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../playground.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../playground.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../project.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../playground.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../playground.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../project.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../playground.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../playground.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../playground.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../project.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../playground.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../project.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../playground.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../playground.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../playground.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../playground.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../playground.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../project.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../project.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../playground.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../playground.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../project.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../project.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../playground.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../playground.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../playground.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../project.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../playground.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../project.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../playground.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../playground.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../project.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../playground.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../playground.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../playground.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../project.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../playground.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../project.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../playground.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../project.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../playground.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../playground.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../playground.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../project.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../playground.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../playground.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../project.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../playground.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../playground.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../project.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../project.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../playground.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../project.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../playground.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../playground.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../playground.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../project.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../project.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../playground.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../playground.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../playground.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../playground.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../playground.xcworkspace/contents.xcworkspacedata | 7 +++++++ 79 files changed, 546 insertions(+), 1 deletion(-) create mode 100644 AVL Tree/AVLTree.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 AVL Tree/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 All-Pairs Shortest Paths/APSP/APSP.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 Array2D/Array2D.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 Array2D/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 Binary Search Tree/Solution 1/BinarySearchTree.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 Binary Search Tree/Solution 1/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 Binary Search Tree/Solution 2/BinarySearchTree.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 Binary Search/BinarySearch.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 Binary Search/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 Binary Tree/BinaryTree.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 Bit Set/BitSet.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 Bloom Filter/BloomFilter.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 Bloom Filter/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 Bounded Priority Queue/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 Boyer-Moore/BoyerMoore.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 Breadth-First Search/BreadthFirstSearch.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 Breadth-First Search/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 Brute-Force String Search/BruteForceStringSearch.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 Bucket Sort/BucketSort.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 Bucket Sort/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 Combinatorics/Combinatorics.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 Count Occurrences/CountOccurrences.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 Counting Sort/CountingSort.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 Counting Sort/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 Depth-First Search/DepthFirstSearch.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 Depth-First Search/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 Deque/Deque.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 GCD/GCD.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 Graph/Graph.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 Hash Set/HashSet.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 Hash Table/HashTable.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 Heap Sort/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 Heap/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 Huffman Coding/Huffman.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 Insertion Sort/InsertionSort.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 Insertion Sort/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 K-Means/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 Kth Largest Element/kthLargest.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 Linear Search/LinearSearch.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 Linked List/LinkedList.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 Linked List/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 Longest Common Subsequence/LongestCommonSubsequence.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 Longest Common Subsequence/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 Merge Sort/MergeSort.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 Minimum Spanning Tree (Unweighted)/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 Monty Hall Problem/MontyHall.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 Ordered Array/OrderedArray.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 Ordered Set/OrderedSet.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 Priority Queue/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 Queue/Queue.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 Queue/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 Quicksort/Quicksort.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 Quicksort/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 Radix Tree/RadixTree.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 Ring Buffer/RingBuffer.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 Run-Length Encoding/RLE.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 Run-Length Encoding/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 Segment Tree/SegmentTree.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 Select Minimum Maximum/SelectMinimumMaximum.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 Select Minimum Maximum/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 Selection Sampling/SelectionSampling.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 Selection Sort/SelectionSort.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 Selection Sort/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 Shell Sort/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 Shortest Path (Unweighted)/ShortestPath.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 Shortest Path (Unweighted)/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 Shuffle/Shuffle.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 Shunting Yard/ShuntingYard.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 Stack/Stack.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 Stack/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 Topological Sort/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 Topological Sort/Topological Sort.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 Tree/Tree.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 Two-Sum Problem/Solution 1/2Sum.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 Two-Sum Problem/Solution 2/2Sum.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 Union-Find/UnionFind.playground/playground.xcworkspace/contents.xcworkspacedata diff --git a/.gitignore b/.gitignore index 189605960..c2f483cba 100644 --- a/.gitignore +++ b/.gitignore @@ -8,7 +8,6 @@ DerivedData/ *.perspectivev3 *.xccheckout *.moved-aside -*.xcworkspace *.xcuserstate xcuserdata diff --git a/AVL Tree/AVLTree.playground/playground.xcworkspace/contents.xcworkspacedata b/AVL Tree/AVLTree.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/AVL Tree/AVLTree.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/AVL Tree/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/AVL Tree/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..6c0ea8493 --- /dev/null +++ b/AVL Tree/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/All-Pairs Shortest Paths/APSP/APSP.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/All-Pairs Shortest Paths/APSP/APSP.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/All-Pairs Shortest Paths/APSP/APSP.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Array2D/Array2D.playground/playground.xcworkspace/contents.xcworkspacedata b/Array2D/Array2D.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Array2D/Array2D.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Array2D/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Array2D/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..6c0ea8493 --- /dev/null +++ b/Array2D/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Binary Search Tree/Solution 1/BinarySearchTree.playground/playground.xcworkspace/contents.xcworkspacedata b/Binary Search Tree/Solution 1/BinarySearchTree.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Binary Search Tree/Solution 1/BinarySearchTree.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Binary Search Tree/Solution 1/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Binary Search Tree/Solution 1/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..6c0ea8493 --- /dev/null +++ b/Binary Search Tree/Solution 1/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Binary Search Tree/Solution 2/BinarySearchTree.playground/playground.xcworkspace/contents.xcworkspacedata b/Binary Search Tree/Solution 2/BinarySearchTree.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Binary Search Tree/Solution 2/BinarySearchTree.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Binary Search/BinarySearch.playground/playground.xcworkspace/contents.xcworkspacedata b/Binary Search/BinarySearch.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Binary Search/BinarySearch.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Binary Search/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Binary Search/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..6c0ea8493 --- /dev/null +++ b/Binary Search/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Binary Tree/BinaryTree.playground/playground.xcworkspace/contents.xcworkspacedata b/Binary Tree/BinaryTree.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Binary Tree/BinaryTree.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Bit Set/BitSet.playground/playground.xcworkspace/contents.xcworkspacedata b/Bit Set/BitSet.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Bit Set/BitSet.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Bloom Filter/BloomFilter.playground/playground.xcworkspace/contents.xcworkspacedata b/Bloom Filter/BloomFilter.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Bloom Filter/BloomFilter.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Bloom Filter/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Bloom Filter/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..6c0ea8493 --- /dev/null +++ b/Bloom Filter/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Bounded Priority Queue/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Bounded Priority Queue/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Bounded Priority Queue/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Boyer-Moore/BoyerMoore.playground/playground.xcworkspace/contents.xcworkspacedata b/Boyer-Moore/BoyerMoore.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Boyer-Moore/BoyerMoore.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Breadth-First Search/BreadthFirstSearch.playground/playground.xcworkspace/contents.xcworkspacedata b/Breadth-First Search/BreadthFirstSearch.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Breadth-First Search/BreadthFirstSearch.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Breadth-First Search/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Breadth-First Search/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Breadth-First Search/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Brute-Force String Search/BruteForceStringSearch.playground/playground.xcworkspace/contents.xcworkspacedata b/Brute-Force String Search/BruteForceStringSearch.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Brute-Force String Search/BruteForceStringSearch.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Bucket Sort/BucketSort.playground/playground.xcworkspace/contents.xcworkspacedata b/Bucket Sort/BucketSort.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Bucket Sort/BucketSort.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Bucket Sort/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Bucket Sort/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Bucket Sort/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Combinatorics/Combinatorics.playground/playground.xcworkspace/contents.xcworkspacedata b/Combinatorics/Combinatorics.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Combinatorics/Combinatorics.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Count Occurrences/CountOccurrences.playground/playground.xcworkspace/contents.xcworkspacedata b/Count Occurrences/CountOccurrences.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Count Occurrences/CountOccurrences.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Counting Sort/CountingSort.playground/playground.xcworkspace/contents.xcworkspacedata b/Counting Sort/CountingSort.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Counting Sort/CountingSort.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Counting Sort/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Counting Sort/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..6c0ea8493 --- /dev/null +++ b/Counting Sort/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Depth-First Search/DepthFirstSearch.playground/playground.xcworkspace/contents.xcworkspacedata b/Depth-First Search/DepthFirstSearch.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Depth-First Search/DepthFirstSearch.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Depth-First Search/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Depth-First Search/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Depth-First Search/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Deque/Deque.playground/playground.xcworkspace/contents.xcworkspacedata b/Deque/Deque.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Deque/Deque.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/GCD/GCD.playground/playground.xcworkspace/contents.xcworkspacedata b/GCD/GCD.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/GCD/GCD.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Graph/Graph.playground/playground.xcworkspace/contents.xcworkspacedata b/Graph/Graph.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Graph/Graph.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Hash Set/HashSet.playground/playground.xcworkspace/contents.xcworkspacedata b/Hash Set/HashSet.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Hash Set/HashSet.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Hash Table/HashTable.playground/playground.xcworkspace/contents.xcworkspacedata b/Hash Table/HashTable.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Hash Table/HashTable.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Heap Sort/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Heap Sort/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..6c0ea8493 --- /dev/null +++ b/Heap Sort/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Heap/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Heap/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..6c0ea8493 --- /dev/null +++ b/Heap/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Huffman Coding/Huffman.playground/playground.xcworkspace/contents.xcworkspacedata b/Huffman Coding/Huffman.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Huffman Coding/Huffman.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Insertion Sort/InsertionSort.playground/playground.xcworkspace/contents.xcworkspacedata b/Insertion Sort/InsertionSort.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Insertion Sort/InsertionSort.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Insertion Sort/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Insertion Sort/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..6c0ea8493 --- /dev/null +++ b/Insertion Sort/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/K-Means/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/K-Means/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/K-Means/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Kth Largest Element/kthLargest.playground/playground.xcworkspace/contents.xcworkspacedata b/Kth Largest Element/kthLargest.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Kth Largest Element/kthLargest.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Linear Search/LinearSearch.playground/playground.xcworkspace/contents.xcworkspacedata b/Linear Search/LinearSearch.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Linear Search/LinearSearch.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Linked List/LinkedList.playground/playground.xcworkspace/contents.xcworkspacedata b/Linked List/LinkedList.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Linked List/LinkedList.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Linked List/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Linked List/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..6c0ea8493 --- /dev/null +++ b/Linked List/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Longest Common Subsequence/LongestCommonSubsequence.playground/playground.xcworkspace/contents.xcworkspacedata b/Longest Common Subsequence/LongestCommonSubsequence.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Longest Common Subsequence/LongestCommonSubsequence.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Longest Common Subsequence/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Longest Common Subsequence/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Longest Common Subsequence/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Merge Sort/MergeSort.playground/playground.xcworkspace/contents.xcworkspacedata b/Merge Sort/MergeSort.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Merge Sort/MergeSort.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/playground.xcworkspace/contents.xcworkspacedata b/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Minimum Spanning Tree (Unweighted)/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Minimum Spanning Tree (Unweighted)/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Minimum Spanning Tree (Unweighted)/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Monty Hall Problem/MontyHall.playground/playground.xcworkspace/contents.xcworkspacedata b/Monty Hall Problem/MontyHall.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Monty Hall Problem/MontyHall.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Ordered Array/OrderedArray.playground/playground.xcworkspace/contents.xcworkspacedata b/Ordered Array/OrderedArray.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Ordered Array/OrderedArray.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Ordered Set/OrderedSet.playground/playground.xcworkspace/contents.xcworkspacedata b/Ordered Set/OrderedSet.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Ordered Set/OrderedSet.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Priority Queue/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Priority Queue/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..6c0ea8493 --- /dev/null +++ b/Priority Queue/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Queue/Queue.playground/playground.xcworkspace/contents.xcworkspacedata b/Queue/Queue.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Queue/Queue.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Queue/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Queue/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..6c0ea8493 --- /dev/null +++ b/Queue/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Quicksort/Quicksort.playground/playground.xcworkspace/contents.xcworkspacedata b/Quicksort/Quicksort.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Quicksort/Quicksort.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Quicksort/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Quicksort/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..6c0ea8493 --- /dev/null +++ b/Quicksort/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Radix Tree/RadixTree.playground/playground.xcworkspace/contents.xcworkspacedata b/Radix Tree/RadixTree.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Radix Tree/RadixTree.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Ring Buffer/RingBuffer.playground/playground.xcworkspace/contents.xcworkspacedata b/Ring Buffer/RingBuffer.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Ring Buffer/RingBuffer.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Run-Length Encoding/RLE.playground/playground.xcworkspace/contents.xcworkspacedata b/Run-Length Encoding/RLE.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Run-Length Encoding/RLE.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Run-Length Encoding/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Run-Length Encoding/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..6c0ea8493 --- /dev/null +++ b/Run-Length Encoding/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Segment Tree/SegmentTree.playground/playground.xcworkspace/contents.xcworkspacedata b/Segment Tree/SegmentTree.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Segment Tree/SegmentTree.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Select Minimum Maximum/SelectMinimumMaximum.playground/playground.xcworkspace/contents.xcworkspacedata b/Select Minimum Maximum/SelectMinimumMaximum.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Select Minimum Maximum/SelectMinimumMaximum.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Select Minimum Maximum/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Select Minimum Maximum/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..6c0ea8493 --- /dev/null +++ b/Select Minimum Maximum/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Selection Sampling/SelectionSampling.playground/playground.xcworkspace/contents.xcworkspacedata b/Selection Sampling/SelectionSampling.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Selection Sampling/SelectionSampling.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Selection Sort/SelectionSort.playground/playground.xcworkspace/contents.xcworkspacedata b/Selection Sort/SelectionSort.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Selection Sort/SelectionSort.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Selection Sort/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Selection Sort/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..6c0ea8493 --- /dev/null +++ b/Selection Sort/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Shell Sort/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Shell Sort/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..6c0ea8493 --- /dev/null +++ b/Shell Sort/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Shortest Path (Unweighted)/ShortestPath.playground/playground.xcworkspace/contents.xcworkspacedata b/Shortest Path (Unweighted)/ShortestPath.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Shortest Path (Unweighted)/ShortestPath.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Shortest Path (Unweighted)/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Shortest Path (Unweighted)/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Shortest Path (Unweighted)/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Shuffle/Shuffle.playground/playground.xcworkspace/contents.xcworkspacedata b/Shuffle/Shuffle.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Shuffle/Shuffle.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Shunting Yard/ShuntingYard.playground/playground.xcworkspace/contents.xcworkspacedata b/Shunting Yard/ShuntingYard.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Shunting Yard/ShuntingYard.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Stack/Stack.playground/playground.xcworkspace/contents.xcworkspacedata b/Stack/Stack.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Stack/Stack.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Stack/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Stack/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..6c0ea8493 --- /dev/null +++ b/Stack/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Topological Sort/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Topological Sort/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..6c0ea8493 --- /dev/null +++ b/Topological Sort/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Topological Sort/Topological Sort.playground/playground.xcworkspace/contents.xcworkspacedata b/Topological Sort/Topological Sort.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Topological Sort/Topological Sort.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Tree/Tree.playground/playground.xcworkspace/contents.xcworkspacedata b/Tree/Tree.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Tree/Tree.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Two-Sum Problem/Solution 1/2Sum.playground/playground.xcworkspace/contents.xcworkspacedata b/Two-Sum Problem/Solution 1/2Sum.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Two-Sum Problem/Solution 1/2Sum.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Two-Sum Problem/Solution 2/2Sum.playground/playground.xcworkspace/contents.xcworkspacedata b/Two-Sum Problem/Solution 2/2Sum.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Two-Sum Problem/Solution 2/2Sum.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Union-Find/UnionFind.playground/playground.xcworkspace/contents.xcworkspacedata b/Union-Find/UnionFind.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Union-Find/UnionFind.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + From 4ab746d22aef252ba3b966c28c41b2dd774580a0 Mon Sep 17 00:00:00 2001 From: Andrew McKnight Date: Mon, 9 May 2016 08:36:25 -0400 Subject: [PATCH 0359/1679] add xcworkspace --- .../playground.xcworkspace/contents.xcworkspacedata | 7 +++++++ .../xcshareddata/WorkspaceSettings.xcsettings | 8 ++++++++ .../APSP/APSP.xcworkspace/contents.xcworkspacedata | 10 ++++++++++ .../xcshareddata/WorkspaceSettings.xcsettings | 8 ++++++++ 4 files changed, 33 insertions(+) create mode 100644 All-Pairs Shortest Paths/APSP/APSP.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 All-Pairs Shortest Paths/APSP/APSP.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings create mode 100644 All-Pairs Shortest Paths/APSP/APSP.xcworkspace/contents.xcworkspacedata create mode 100644 All-Pairs Shortest Paths/APSP/APSP.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings diff --git a/All-Pairs Shortest Paths/APSP/APSP.playground/playground.xcworkspace/contents.xcworkspacedata b/All-Pairs Shortest Paths/APSP/APSP.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/All-Pairs Shortest Paths/APSP/APSP.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/All-Pairs Shortest Paths/APSP/APSP.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/All-Pairs Shortest Paths/APSP/APSP.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 000000000..08de0be8d --- /dev/null +++ b/All-Pairs Shortest Paths/APSP/APSP.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded + + + diff --git a/All-Pairs Shortest Paths/APSP/APSP.xcworkspace/contents.xcworkspacedata b/All-Pairs Shortest Paths/APSP/APSP.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..615e34ecd --- /dev/null +++ b/All-Pairs Shortest Paths/APSP/APSP.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/All-Pairs Shortest Paths/APSP/APSP.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/All-Pairs Shortest Paths/APSP/APSP.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 000000000..08de0be8d --- /dev/null +++ b/All-Pairs Shortest Paths/APSP/APSP.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded + + + From 47249d08f7b99d1672096ef7c9c2a3ea894a4d90 Mon Sep 17 00:00:00 2001 From: Kevin Connor Date: Thu, 12 May 2016 12:30:21 -0700 Subject: [PATCH 0360/1679] fix broken link --- Shortest Path (Unweighted)/README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Shortest Path (Unweighted)/README.markdown b/Shortest Path (Unweighted)/README.markdown index 64ae52a80..0107964ae 100644 --- a/Shortest Path (Unweighted)/README.markdown +++ b/Shortest Path (Unweighted)/README.markdown @@ -97,6 +97,6 @@ This will output: Node(label: d, distance: 2), Node(label: e, distance: 2), Node(label: f, distance: 2), Node(label: g, distance: 2), Node(label: h, distance: 3) -> **Note:** This version of `breadthFirstSearchShortestPath()` does not actually produce the tree, it only computes the distances. See [minimum spanning tree](../Minimum Spanning Tree/) on how you can convert the graph into a tree by removing edges. +> **Note:** This version of `breadthFirstSearchShortestPath()` does not actually produce the tree, it only computes the distances. See [minimum spanning tree](../Minimum Spanning Tree (Unweighted)/) on how you can convert the graph into a tree by removing edges. *Written by [Chris Pilcher](https://github.com/chris-pilcher) and Matthijs Hollemans* From b41213f8a9ec0f130d9121c50a7f1d608efb26e2 Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Sat, 14 May 2016 17:36:49 +1200 Subject: [PATCH 0361/1679] Updating build status badge to point to RayWenderlich repository --- README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.markdown b/README.markdown index e3d9fd9cf..1c7ca4300 100644 --- a/README.markdown +++ b/README.markdown @@ -210,4 +210,4 @@ Other algorithm repositories: All content is licensed under the terms of the MIT open source license. -[![Build Status](https://travis-ci.org/hollance/swift-algorithm-club.svg?branch=master)](https://travis-ci.org/hollance/swift-algorithm-club) +[![Build Status](https://travis-ci.org/raywenderlich/swift-algorithm-club.svg?branch=master)](https://travis-ci.org/raywenderlich/swift-algorithm-club) From 4c7920d581cd9e4aa7388f3710ee72d36aaea364 Mon Sep 17 00:00:00 2001 From: Vinay Jain Date: Tue, 17 May 2016 18:51:16 +0530 Subject: [PATCH 0362/1679] Replaced Array2D with Swift inbuilt 2D array --- Combinatorics/Combinatorics.swift | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/Combinatorics/Combinatorics.swift b/Combinatorics/Combinatorics.swift index eb67fb53f..de82618c3 100644 --- a/Combinatorics/Combinatorics.swift +++ b/Combinatorics/Combinatorics.swift @@ -100,21 +100,22 @@ func quickBinomialCoefficient(n: Int, _ k: Int) -> Int { the calculation of much larger numbers, at the cost of temporary storage space for the cached values. */ + func binomialCoefficient(n: Int, _ k: Int) -> Int { - var bc = Array2D(columns: n + 1, rows: n + 1, initialValue: 0) - - for i in 0...n { - bc[i, 0] = 1 - bc[i, i] = 1 - } - - if n > 0 { - for i in 1...n { - for j in 1.. 0 { + for i in 1...n { + for j in 1.. Date: Tue, 17 May 2016 18:52:58 +0530 Subject: [PATCH 0363/1679] Updated ReadMe Replaced Array2D with Swift inbuilt 2D array --- Combinatorics/README.markdown | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/Combinatorics/README.markdown b/Combinatorics/README.markdown index 6e16e93c3..45e48693d 100644 --- a/Combinatorics/README.markdown +++ b/Combinatorics/README.markdown @@ -366,26 +366,26 @@ The following code calculates Pascal's triangle in order to find the `C(n, k)` y ```swift func binomialCoefficient(n: Int, _ k: Int) -> Int { - var bc = Array2D(columns: n + 1, rows: n + 1, initialValue: 0) - - for i in 0...n { - bc[i, 0] = 1 - bc[i, i] = 1 - } - - if n > 0 { - for i in 1...n { - for j in 1.. 0 { + for i in 1...n { + for j in 1.. Date: Fri, 20 May 2016 16:07:35 +0530 Subject: [PATCH 0364/1679] Changed Array2d to Swift standard 2d array in playground --- .../Combinatorics.playground/Contents.swift | 205 +++++++++--------- 1 file changed, 103 insertions(+), 102 deletions(-) diff --git a/Combinatorics/Combinatorics.playground/Contents.swift b/Combinatorics/Combinatorics.playground/Contents.swift index 2cafaa0c1..1ac77a5c4 100644 --- a/Combinatorics/Combinatorics.playground/Contents.swift +++ b/Combinatorics/Combinatorics.playground/Contents.swift @@ -2,13 +2,13 @@ /* Calculates n! */ func factorial(n: Int) -> Int { - var n = n - var result = 1 - while n > 1 { - result *= n - n -= 1 - } - return result + var n = n + var result = 1 + while n > 1 { + result *= n + n -= 1 + } + return result } factorial(5) @@ -17,17 +17,17 @@ factorial(20) /* - Calculates P(n, k), the number of permutations of n distinct symbols - in groups of size k. -*/ + Calculates P(n, k), the number of permutations of n distinct symbols + in groups of size k. + */ func permutations(n: Int, _ k: Int) -> Int { - var n = n - var answer = n - for _ in 1..(a: [T], _ n: Int) { - if n == 0 { - print(a) // display the current permutation - } else { - var a = a - permuteWirth(a, n - 1) - for i in 0.. Int { - return permutations(n, k) / factorial(k) + return permutations(n, k) / factorial(k) } combinations(3, 2) @@ -112,23 +112,23 @@ combinations(28, 5) print("\nCombinations:") for i in 1...20 { - print("\(20)-choose-\(i) = \(combinations(20, i))") + print("\(20)-choose-\(i) = \(combinations(20, i))") } /* - Calculates C(n, k), or "n-choose-k", i.e. the number of ways to choose - k things out of n possibilities. -*/ + Calculates C(n, k), or "n-choose-k", i.e. the number of ways to choose + k things out of n possibilities. + */ func quickBinomialCoefficient(n: Int, _ k: Int) -> Int { - var result = 1 + var result = 1 - for i in 0.. { - let columns: Int - let rows: Int - private var array: [T] - - init(columns: Int, rows: Int, initialValue: T) { - self.columns = columns - self.rows = rows - array = .init(count: rows*columns, repeatedValue: initialValue) - } - - subscript(column: Int, row: Int) -> T { - get { return array[row*columns + column] } - set { array[row*columns + column] = newValue } - } + let columns: Int + let rows: Int + private var array: [T] + + init(columns: Int, rows: Int, initialValue: T) { + self.columns = columns + self.rows = rows + array = .init(count: rows*columns, repeatedValue: initialValue) + } + + subscript(column: Int, row: Int) -> T { + get { return array[row*columns + column] } + set { array[row*columns + column] = newValue } + } } /* - Calculates C(n, k), or "n-choose-k", i.e. the number of ways to choose - k things out of n possibilities. + Calculates C(n, k), or "n-choose-k", i.e. the number of ways to choose + k things out of n possibilities. + + Thanks to the dynamic programming, this algorithm from Skiena allows for + the calculation of much larger numbers, at the cost of temporary storage + space for the cached values. + */ - Thanks to the dynamic programming, this algorithm from Skiena allows for - the calculation of much larger numbers, at the cost of temporary storage - space for the cached values. -*/ func binomialCoefficient(n: Int, _ k: Int) -> Int { - var bc = Array2D(columns: n + 1, rows: n + 1, initialValue: 0) - - for i in 0...n { - bc[i, 0] = 1 - bc[i, i] = 1 - } - - if n > 0 { - for i in 1...n { - for j in 1.. 0 { + for i in 1...n { + for j in 1.. Date: Wed, 25 May 2016 11:48:11 +0200 Subject: [PATCH 0365/1679] Adds AlgorithmVisualizer to README --- README.markdown | 1 + 1 file changed, 1 insertion(+) diff --git a/README.markdown b/README.markdown index e3d9fd9cf..ab309f724 100644 --- a/README.markdown +++ b/README.markdown @@ -205,6 +205,7 @@ Other algorithm repositories: - [EKAlgorithms](https://github.com/EvgenyKarkan/EKAlgorithms). A great collection of algorithms in Objective-C. - [@lorentey](https://github.com/lorentey/). Production-quality Swift implementations of common algorithms and data structures. - [Rosetta Code](http://rosettacode.org). Implementations in pretty much any language you can think of. +- [AlgorithmVisualizer](http://jasonpark.me/AlgorithmVisualizer/). Visualize algorithms on your browser. ## License From 5234381da1e6a85f1b405a458880dca47f5c910a Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Wed, 25 May 2016 23:29:50 +1200 Subject: [PATCH 0366/1679] Removing B-Tree as it has no content and has not been updated in 3 months. --- B Tree/README.markdown | 8 -------- README.markdown | 2 +- 2 files changed, 1 insertion(+), 9 deletions(-) delete mode 100644 B Tree/README.markdown diff --git a/B Tree/README.markdown b/B Tree/README.markdown deleted file mode 100644 index a96d59be2..000000000 --- a/B Tree/README.markdown +++ /dev/null @@ -1,8 +0,0 @@ -# B Tree - -Under Construction. - -See also [Wikipedia](https://en.wikipedia.org/wiki/B-tree). - -*Written by Jeroen Houtzager* - diff --git a/README.markdown b/README.markdown index 1c7ca4300..65c3b2b0d 100644 --- a/README.markdown +++ b/README.markdown @@ -151,7 +151,7 @@ Most of the time using just the built-in `Array`, `Dictionary`, and `Set` types - [Heap](Heap/). A binary tree stored in an array, so it doesn't use pointers. Makes a great priority queue. - Fibonacci Heap - Trie -- [B-Tree](B Tree/) :construction: +- B-Tree - [Radix Tree](Radix Tree/) :construction: ### Hashing From 636fee82741d6f1bae1f28177d0008ee34afd44f Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Thu, 26 May 2016 22:56:15 +1200 Subject: [PATCH 0367/1679] Bounded Priority Queue - adding updated implementation from Matthijs + updating readme --- .../Contents.swift | 104 ++++++++++ .../Sources/BoundedPriorityQueue.swift | 137 ++++++++++++ .../contents.xcplayground | 4 + .../contents.xcworkspacedata | 7 + .../BoundedPriorityQueue.swift | 145 ++++++++----- Bounded Priority Queue/README.markdown | 143 ++++++++----- .../Tests/BoundedPriorityQueueTests.swift | 196 +++++++++--------- 7 files changed, 528 insertions(+), 208 deletions(-) create mode 100644 Bounded Priority Queue/BoundedPriorityQueue.playground/Contents.swift create mode 100644 Bounded Priority Queue/BoundedPriorityQueue.playground/Sources/BoundedPriorityQueue.swift create mode 100644 Bounded Priority Queue/BoundedPriorityQueue.playground/contents.xcplayground create mode 100644 Bounded Priority Queue/BoundedPriorityQueue.playground/playground.xcworkspace/contents.xcworkspacedata diff --git a/Bounded Priority Queue/BoundedPriorityQueue.playground/Contents.swift b/Bounded Priority Queue/BoundedPriorityQueue.playground/Contents.swift new file mode 100644 index 000000000..b4977d6ce --- /dev/null +++ b/Bounded Priority Queue/BoundedPriorityQueue.playground/Contents.swift @@ -0,0 +1,104 @@ +struct Message: Comparable, CustomStringConvertible { + let name: String + let priority: Int + + var description: String { + return "\(name):\(priority)" + } +} + +func ==(m1: Message, m2: Message) -> Bool { + return m1.priority == m2.priority +} + +func <(m1: Message, m2: Message) -> Bool { + return m1.priority < m2.priority +} + + + +let queue = BoundedPriorityQueue(maxElements: 5) +queue.count + +queue.enqueue(Message(name: "hello", priority: 100)) +queue.count +queue.peek() +print(queue) + +queue.enqueue(Message(name: "there", priority: 99)) +queue.count +queue.peek() +print(queue) + +queue.enqueue(Message(name: "world", priority: 150)) +queue.count +queue.peek() +print(queue) + +queue.enqueue(Message(name: "swift", priority: 110)) +queue.count +queue.peek() +print(queue) + +queue.enqueue(Message(name: "is", priority: 30)) +queue.count +queue.peek() +print(queue) + +// At this point, the queue is: +// + + + +// Try to insert an item with a really low priority. This should not get added. +queue.enqueue(Message(name: "very", priority: -1)) +queue.count // 5 +queue.peek() +print(queue) // still same as before + +// Try to insert an item with medium priority. This gets added and the lowest +// priority item is removed. +queue.enqueue(Message(name: "cool", priority: 120)) +queue.count +queue.peek() +print(queue) + +// Try to insert an item with very high priority. This gets added and the +// lowest priority item is removed. +queue.enqueue(Message(name: "!!!", priority: 500)) +queue.count +queue.peek() +print(queue) + + + +// Test dequeuing +queue.dequeue() +queue.count +queue.peek() +print(queue) + +queue.dequeue() +queue.count +queue.peek() +print(queue) + +queue.dequeue() +queue.count +queue.peek() +print(queue) + +queue.dequeue() +queue.count +queue.peek() +print(queue) + +queue.dequeue() +queue.count +queue.peek() +print(queue) + +queue.dequeue() +queue.count +queue.peek() +print(queue) diff --git a/Bounded Priority Queue/BoundedPriorityQueue.playground/Sources/BoundedPriorityQueue.swift b/Bounded Priority Queue/BoundedPriorityQueue.playground/Sources/BoundedPriorityQueue.swift new file mode 100644 index 000000000..99f00d70c --- /dev/null +++ b/Bounded Priority Queue/BoundedPriorityQueue.playground/Sources/BoundedPriorityQueue.swift @@ -0,0 +1,137 @@ +public class LinkedListNode { + var value: T + var next: LinkedListNode? + var previous: LinkedListNode? + + public init(value: T) { + self.value = value + } +} + +public class BoundedPriorityQueue { + private typealias Node = LinkedListNode + + private(set) public var count = 0 + private var head: Node? + private var tail: Node? + private var maxElements: Int + + public init(maxElements: Int) { + self.maxElements = maxElements + } + + public var isEmpty: Bool { + return count == 0 + } + + public func peek() -> T? { + return head?.value + } + + public func enqueue(value: T) { + if let node = insert(value, after: findInsertionPoint(value)) { + // If the newly inserted node is the last one in the list, then update + // the tail pointer. + if node.next == nil { + tail = node + } + + // If the queue is full, then remove an element from the back. + count += 1 + if count > maxElements { + removeLeastImportantElement() + } + } + } + + private func insert(value: T, after: Node?) -> Node? { + if let previous = after { + + // If the queue is full and we have to insert at the end of the list, + // then there's no reason to insert the new value. + if count == maxElements && previous.next == nil { + print("Queue is full and priority of new object is too small") + return nil + } + + // Put the new node in between previous and previous.next (if exists). + let node = Node(value: value) + node.next = previous.next + previous.next?.previous = node + previous.next = node + node.previous = previous + return node + + } else if let first = head { + // Have to insert at the head, so shift the existing head up once place. + head = Node(value: value) + head!.next = first + first.previous = head + return head + + } else { + // This is the very first item in the queue. + head = Node(value: value) + return head + } + } + + /* Find the node after which to insert the new value. If this returns nil, + the new value should be inserted at the head of the list. */ + private func findInsertionPoint(value: T) -> Node? { + var node = head + var prev: Node? = nil + + while let current = node where value < current.value { + prev = node + node = current.next + } + return prev + } + + private func removeLeastImportantElement() { + if let last = tail { + tail = last.previous + tail?.next = nil + count -= 1 + } + + // Note: Instead of using a tail pointer, we could just scan from the new + // node until the end. Then nodes also don't need a previous pointer. But + // this is much slower on large lists. + } + + public func dequeue() -> T? { + if let first = head { + count -= 1 + if count == 0 { + head = nil + tail = nil + } else { + head = first.next + head!.previous = nil + } + return first.value + } else { + return nil + } + } +} + +extension LinkedListNode: CustomStringConvertible { + public var description: String { + return "\(value)" + } +} + +extension BoundedPriorityQueue: CustomStringConvertible { + public var description: String { + var s = "<" + var node = head + while let current = node { + s += "\(current), " + node = current.next + } + return s + ">" + } +} diff --git a/Bounded Priority Queue/BoundedPriorityQueue.playground/contents.xcplayground b/Bounded Priority Queue/BoundedPriorityQueue.playground/contents.xcplayground new file mode 100644 index 000000000..06828af92 --- /dev/null +++ b/Bounded Priority Queue/BoundedPriorityQueue.playground/contents.xcplayground @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Bounded Priority Queue/BoundedPriorityQueue.playground/playground.xcworkspace/contents.xcworkspacedata b/Bounded Priority Queue/BoundedPriorityQueue.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Bounded Priority Queue/BoundedPriorityQueue.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Bounded Priority Queue/BoundedPriorityQueue.swift b/Bounded Priority Queue/BoundedPriorityQueue.swift index abee9e526..fbd8d5450 100644 --- a/Bounded Priority Queue/BoundedPriorityQueue.swift +++ b/Bounded Priority Queue/BoundedPriorityQueue.swift @@ -1,18 +1,10 @@ -// -// BoundedPriorityQueue.swift -// -// Created by John Gill on 2/28/16. -// - public class LinkedListNode { var value: T var next: LinkedListNode? var previous: LinkedListNode? - + public init(value: T) { self.value = value - self.next = nil - self.previous = nil } } @@ -21,6 +13,7 @@ public class BoundedPriorityQueue { private(set) public var count = 0 private var head: Node? + private var tail: Node? private var maxElements: Int public init(maxElements: Int) { @@ -36,63 +29,109 @@ public class BoundedPriorityQueue { } public func enqueue(value: T) { - let newNode = Node(value: value) + if let node = insert(value, after: findInsertionPoint(value)) { + // If the newly inserted node is the last one in the list, then update + // the tail pointer. + if node.next == nil { + tail = node + } - if head == nil { - head = newNode - count = 1 - return + // If the queue is full, then remove an element from the back. + count += 1 + if count > maxElements { + removeLeastImportantElement() + } } + } - var node = head - if count == maxElements && newNode.value > node!.value { - return - } - - while (node!.next != nil) && (newNode.value < node!.value) { - node = node!.next - } - - if newNode.value < node!.value { - newNode.next = node!.next - newNode.previous = node - - if newNode.next != nil { /* TAIL */ - newNode.next!.previous = newNode + private func insert(value: T, after: Node?) -> Node? { + if let previous = after { + + // If the queue is full and we have to insert at the end of the list, + // then there's no reason to insert the new value. + if count == maxElements && previous.next == nil { + print("Queue is full and priority of new object is too small") + return nil } - node!.next = newNode + + // Put the new node in between previous and previous.next (if exists). + let node = Node(value: value) + node.next = previous.next + previous.next?.previous = node + previous.next = node + node.previous = previous + return node + + } else if let first = head { + // Have to insert at the head, so shift the existing head up once place. + head = Node(value: value) + head!.next = first + first.previous = head + return head + } else { - newNode.previous = node!.previous - newNode.next = node - if node!.previous == nil { /* HEAD */ - head = newNode - } else { - node!.previous!.next = newNode - } - node!.previous = newNode + // This is the very first item in the queue. + head = Node(value: value) + return head } + } + + /* Find the node after which to insert the new value. If this returns nil, + the new value should be inserted at the head of the list. */ + private func findInsertionPoint(value: T) -> Node? { + var node = head + var prev: Node? = nil - if count == maxElements { - dequeue() + while let current = node where value < current.value { + prev = node + node = current.next } - count += 1 + return prev } - - public func dequeue() -> T? { - if count == 0 { - return nil + + private func removeLeastImportantElement() { + if let last = tail { + tail = last.previous + tail?.next = nil + count -= 1 } - let retVal = head!.value - - if count == 1 { - head = nil + // Note: Instead of using a tail pointer, we could just scan from the new + // node until the end. Then nodes also don't need a previous pointer. But + // this is much slower on large lists. + } + + public func dequeue() -> T? { + if let first = head { + count -= 1 + if count == 0 { + head = nil + tail = nil + } else { + head = first.next + head!.previous = nil + } + return first.value } else { - head = head!.next - head!.previous = nil + return nil } + } +} + +extension LinkedListNode: CustomStringConvertible { + public var description: String { + return "\(value)" + } +} - count -= 1 - return retVal +extension BoundedPriorityQueue: CustomStringConvertible { + public var description: String { + var s = "<" + var node = head + while let current = node { + s += "\(current), " + node = current.next + } + return s + ">" } } diff --git a/Bounded Priority Queue/README.markdown b/Bounded Priority Queue/README.markdown index b62d87678..8d6ea1804 100644 --- a/Bounded Priority Queue/README.markdown +++ b/Bounded Priority Queue/README.markdown @@ -7,22 +7,22 @@ A bounded priority queue is similar to a regular [priority queue](../Priority Qu Suppose we have a bounded-priority-queue with maximum size 5 that has the following values and priorities: ``` -Value: [ A, B, C, D, E ] -Priority: [ 0.1, 0.25, 1.33, 3.2, 4.6 ] +Value: [ A, B, C, D, E ] +Priority: [ 4.6, 3.2, 1.33, 0.25, 0.1 ] ``` -Here, we consider the object with the lowest priority value to be the most important (so this is a *min-priority* queue). The larger the priority value, the less we care about the object. So `A` is more important than `B`, `B` is more important than `C`, and so on. +Here, we consider the object with the highest priority value to be the most important (so this is a *max-priority* queue). The larger the priority value, the more we care about the object. So `A` is more important than `B`, `B` is more important than `C`, and so on. Now we want to insert the element `F` with priority `0.4` into this bounded priority queue. Because the queue has maximum size 5, this will insert the element `F` but then evict the lowest-priority element (`E`), yielding the updated queue: ``` -Value: [ A, B, F, C, D ] -Priority: [ 0.1, 0.25, 0.4, 1.33, 3.2 ] +Value: [ A, B, C, F, D ] +Priority: [ 4.6, 3.2, 1.33, 0.4, 0.25 ] ``` -`F` is inserted between `B` and `C` because of its priority value. It's less important than `B` but more important than `C`. +`F` is inserted between `C` and `D` because of its priority value. It's less important than `C` but more important than `D`. -Suppose that we wish to insert the element `G` with priority 4.0 into this BPQ. Because `G`'s priority value is greater than the maximum-priority element in the queue, upon inserting `G` it will immediately be evicted. In other words, inserting an element into a BPQ with priority greater than the maximum-priority element of the BPQ has no effect. +Suppose that we wish to insert the element `G` with priority 0.1 into this BPQ. Because `G`'s priority value is less than the minimum-priority element in the queue, upon inserting `G` it will immediately be evicted. In other words, inserting an element into a BPQ with priority less than the minimum-priority element of the BPQ has no effect. ## Implementation @@ -36,69 +36,100 @@ public class BoundedPriorityQueue { private(set) public var count = 0 private var head: Node? + private var tail: Node? private var maxElements: Int public init(maxElements: Int) { self.maxElements = maxElements } - + public var isEmpty: Bool { return count == 0 } public func peek() -> T? { return head?.value - } + } ``` The `BoundedPriorityQueue` class contains a doubly linked list of `LinkedListNode` objects. Nothing special here yet. The fun stuff happens in the `enqueue()` method: ```swift - public func enqueue(value: T) { - let newNode = Node(value: value) - - if head == nil { - head = newNode - count = 1 - return +public func enqueue(value: T) { + if let node = insert(value, after: findInsertionPoint(value)) { + // If the newly inserted node is the last one in the list, then update + // the tail pointer. + if node.next == nil { + tail = node } - var node = head - if count == maxElements && newNode.value > node!.value { - return - } - - while (node!.next != nil) && (newNode.value < node!.value) { - node = node!.next - } - - if newNode.value < node!.value { - newNode.next = node!.next - newNode.previous = node - - if newNode.next != nil { /* TAIL */ - newNode.next!.previous = newNode - } - node!.next = newNode - } else { - newNode.previous = node!.previous - newNode.next = node - if node!.previous == nil { /* HEAD */ - head = newNode - } else { - node!.previous!.next = newNode - } - node!.previous = newNode + // If the queue is full, then remove an element from the back. + count += 1 + if count > maxElements { + removeLeastImportantElement() } + } +} + +private func insert(value: T, after: Node?) -> Node? { + if let previous = after { - if count == maxElements { - dequeue() + // If the queue is full and we have to insert at the end of the list, + // then there's no reason to insert the new value. + if count == maxElements && previous.next == nil { + print("Queue is full and priority of new object is too small") + return nil } - count += 1 + + // Put the new node in between previous and previous.next (if exists). + let node = Node(value: value) + node.next = previous.next + previous.next?.previous = node + previous.next = node + node.previous = previous + return node + + } else if let first = head { + // Have to insert at the head, so shift the existing head up once place. + head = Node(value: value) + head!.next = first + first.previous = head + return head + + } else { + // This is the very first item in the queue. + head = Node(value: value) + return head } +} + +/* Find the node after which to insert the new value. If this returns nil, + the new value should be inserted at the head of the list. */ +private func findInsertionPoint(value: T) -> Node? { + var node = head + var prev: Node? = nil + + while let current = node where value < current.value { + prev = node + node = current.next + } + return prev +} + +private func removeLeastImportantElement() { + if let last = tail { + tail = last.previous + tail?.next = nil + count -= 1 + } + + // Note: Instead of using a tail pointer, we could just scan from the new + // node until the end. Then nodes also don't need a previous pointer. But + // this is much slower on large lists. +} ``` -We first check if the queue already has the maximum number of elements. If so, and the new priority value is greater than the `head` element's priority value, then there is no room for this new element and we return without inserting it. +We first check if the queue already has the maximum number of elements. If so, and the new priority value is less than the `tail` element's priority value, then there is no room for this new element and we return without inserting it. If the new value is acceptable, then we search through the list to find the proper insertion location and update the `next` and `previous` pointers. @@ -107,23 +138,21 @@ Lastly, if the queue has now reached the maximum number of elements, then we `de By keeping the most important element at the front of the list, it makes dequeueing very easy: ```swift - public func dequeue() -> T? { +public func dequeue() -> T? { + if let first = head { + count -= 1 if count == 0 { - return nil - } - - let retVal = head!.value - - if count == 1 { head = nil + tail = nil } else { - head = head!.next + head = first.next head!.previous = nil } - - count -= 1 - return retVal + return first.value + } else { + return nil } +} ``` This simply removes the `head` element from the list and returns it. diff --git a/Bounded Priority Queue/Tests/BoundedPriorityQueueTests.swift b/Bounded Priority Queue/Tests/BoundedPriorityQueueTests.swift index 772999e84..c6ab5d554 100644 --- a/Bounded Priority Queue/Tests/BoundedPriorityQueueTests.swift +++ b/Bounded Priority Queue/Tests/BoundedPriorityQueueTests.swift @@ -8,114 +8,114 @@ import Foundation import XCTest private struct Message: Comparable { - let name: String - let priority: Int + let name: String + let priority: Int } private func ==(m1: Message, m2: Message) -> Bool { - return m1.priority == m2.priority + return m1.priority == m2.priority } private func <(m1: Message, m2: Message) -> Bool { - return m1.priority < m2.priority + return m1.priority < m2.priority } private func >(m1: Message, m2: Message) -> Bool { - return m1.priority > m2.priority + return m1.priority > m2.priority } class BoundedPriorityQueueTest: XCTestCase { - func testEmpty() { - let queue = BoundedPriorityQueue(maxElements: 5) - XCTAssertTrue(queue.isEmpty) - XCTAssertEqual(queue.count, 0) - XCTAssertNil(queue.dequeue()) - } - - func testOneElement() { - let queue = BoundedPriorityQueue(maxElements: 5) - - queue.enqueue(Message(name: "hello", priority: 100)) - XCTAssertFalse(queue.isEmpty) - XCTAssertEqual(queue.count, 1) - - let result = queue.dequeue() - XCTAssertEqual(result!.priority, 100) - XCTAssertTrue(queue.isEmpty) - XCTAssertEqual(queue.count, 0) - } - - func testMaxElements() { - let queue = BoundedPriorityQueue(maxElements: 5) - XCTAssertTrue(queue.isEmpty) - - queue.enqueue(Message(name: "john", priority: 100)) - XCTAssertEqual(queue.count, 1) - XCTAssertEqual(queue.peek()?.priority, 100) - - queue.enqueue(Message(name: "james", priority: 200)) - XCTAssertEqual(queue.count, 2) - XCTAssertEqual(queue.peek()?.priority, 200) - - queue.enqueue(Message(name: "mark", priority: 300)) - XCTAssertEqual(queue.count, 3) - XCTAssertEqual(queue.peek()?.priority, 300) - - queue.enqueue(Message(name: "ken", priority: 400)) - XCTAssertEqual(queue.count, 4) - XCTAssertEqual(queue.peek()?.priority, 400) - - queue.enqueue(Message(name: "thomas", priority: 500)) - XCTAssertEqual(queue.count, 5) - XCTAssertEqual(queue.peek()?.priority, 500) - - queue.enqueue(Message(name: "melanie", priority: 550)) - XCTAssertEqual(queue.count, 5) - XCTAssertEqual(queue.peek()?.priority, 500) - - queue.enqueue(Message(name: "lily", priority: 450)) - XCTAssertEqual(queue.count, 5) - XCTAssertEqual(queue.peek()?.priority, 450) - - queue.enqueue(Message(name: "fred", priority: 350)) - XCTAssertEqual(queue.count, 5) - XCTAssertEqual(queue.peek()?.priority, 400) - - queue.enqueue(Message(name: "rachel", priority: 50)) - XCTAssertEqual(queue.count, 5) - XCTAssertEqual(queue.peek()?.priority, 350) - - var result = queue.dequeue() - XCTAssertEqual(result!.priority, 350) - XCTAssertEqual(queue.count, 4) - - result = queue.dequeue() - XCTAssertEqual(result!.priority, 300) - XCTAssertEqual(queue.count, 3) - - result = queue.dequeue() - XCTAssertEqual(result!.priority, 200) - XCTAssertEqual(queue.count, 2) - - queue.enqueue(Message(name: "ryan", priority: 150)) - XCTAssertEqual(queue.count, 3) - XCTAssertEqual(queue.peek()?.priority, 150) - - result = queue.dequeue() - XCTAssertEqual(result!.priority, 150) - XCTAssertEqual(queue.count, 2) - - result = queue.dequeue() - XCTAssertEqual(result!.priority, 100) - XCTAssertEqual(queue.count, 1) - - result = queue.dequeue() - XCTAssertEqual(result!.priority, 50) - XCTAssertEqual(queue.count, 0) - - result = queue.dequeue() - XCTAssertNil(result) - XCTAssertEqual(queue.count, 0) - XCTAssertTrue(queue.isEmpty) - } + func testEmpty() { + let queue = BoundedPriorityQueue(maxElements: 5) + XCTAssertTrue(queue.isEmpty) + XCTAssertEqual(queue.count, 0) + XCTAssertNil(queue.dequeue()) + } + + func testOneElement() { + let queue = BoundedPriorityQueue(maxElements: 5) + + queue.enqueue(Message(name: "hello", priority: 100)) + XCTAssertFalse(queue.isEmpty) + XCTAssertEqual(queue.count, 1) + + let result = queue.dequeue() + XCTAssertEqual(result!.priority, 100) + XCTAssertTrue(queue.isEmpty) + XCTAssertEqual(queue.count, 0) + } + + func testMaxElements() { + let queue = BoundedPriorityQueue(maxElements: 5) + XCTAssertTrue(queue.isEmpty) + + queue.enqueue(Message(name: "john", priority: 100)) + XCTAssertEqual(queue.count, 1) + XCTAssertEqual(queue.peek()?.priority, 100) + + queue.enqueue(Message(name: "james", priority: 200)) + XCTAssertEqual(queue.count, 2) + XCTAssertEqual(queue.peek()?.priority, 200) + + queue.enqueue(Message(name: "mark", priority: 300)) + XCTAssertEqual(queue.count, 3) + XCTAssertEqual(queue.peek()?.priority, 300) + + queue.enqueue(Message(name: "ken", priority: 400)) + XCTAssertEqual(queue.count, 4) + XCTAssertEqual(queue.peek()?.priority, 400) + + queue.enqueue(Message(name: "thomas", priority: 500)) + XCTAssertEqual(queue.count, 5) + XCTAssertEqual(queue.peek()?.priority, 500) + + queue.enqueue(Message(name: "melanie", priority: 550)) + XCTAssertEqual(queue.count, 5) + XCTAssertEqual(queue.peek()?.priority, 550) + + queue.enqueue(Message(name: "lily", priority: 450)) + XCTAssertEqual(queue.count, 5) + XCTAssertEqual(queue.peek()?.priority, 550) + + queue.enqueue(Message(name: "fred", priority: 350)) + XCTAssertEqual(queue.count, 5) + XCTAssertEqual(queue.peek()?.priority, 550) + + queue.enqueue(Message(name: "rachel", priority: 50)) + XCTAssertEqual(queue.count, 5) + XCTAssertEqual(queue.peek()?.priority, 550) + + var result = queue.dequeue() + XCTAssertEqual(result!.priority, 550) + XCTAssertEqual(queue.count, 4) + + result = queue.dequeue() + XCTAssertEqual(result!.priority, 500) + XCTAssertEqual(queue.count, 3) + + result = queue.dequeue() + XCTAssertEqual(result!.priority, 450) + XCTAssertEqual(queue.count, 2) + + queue.enqueue(Message(name: "ryan", priority: 150)) + XCTAssertEqual(queue.count, 3) + XCTAssertEqual(queue.peek()?.priority, 400) + + result = queue.dequeue() + XCTAssertEqual(result!.priority, 400) + XCTAssertEqual(queue.count, 2) + + result = queue.dequeue() + XCTAssertEqual(result!.priority, 350) + XCTAssertEqual(queue.count, 1) + + result = queue.dequeue() + XCTAssertEqual(result!.priority, 150) + XCTAssertEqual(queue.count, 0) + + result = queue.dequeue() + XCTAssertNil(result) + XCTAssertEqual(queue.count, 0) + XCTAssertTrue(queue.isEmpty) + } } From d629c7e6d7fc63cd0b95b64f84aba216d4c41f71 Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Wed, 1 Jun 2016 21:20:33 +1200 Subject: [PATCH 0368/1679] Indentation changes for combinatorics --- .../Combinatorics.playground/Contents.swift | 156 +++++++++--------- Combinatorics/Combinatorics.swift | 86 +++++----- Combinatorics/README.markdown | 30 ++-- 3 files changed, 136 insertions(+), 136 deletions(-) diff --git a/Combinatorics/Combinatorics.playground/Contents.swift b/Combinatorics/Combinatorics.playground/Contents.swift index 1ac77a5c4..6dde6a9e0 100644 --- a/Combinatorics/Combinatorics.playground/Contents.swift +++ b/Combinatorics/Combinatorics.playground/Contents.swift @@ -2,13 +2,13 @@ /* Calculates n! */ func factorial(n: Int) -> Int { - var n = n - var result = 1 - while n > 1 { - result *= n - n -= 1 - } - return result + var n = n + var result = 1 + while n > 1 { + result *= n + n -= 1 + } + return result } factorial(5) @@ -21,13 +21,13 @@ factorial(20) in groups of size k. */ func permutations(n: Int, _ k: Int) -> Int { - var n = n - var answer = n - for _ in 1..(a: [T], _ n: Int) { - if n == 0 { - print(a) // display the current permutation - } else { - var a = a - permuteWirth(a, n - 1) - for i in 0.. Int { - return permutations(n, k) / factorial(k) + return permutations(n, k) / factorial(k) } combinations(3, 2) @@ -112,7 +112,7 @@ combinations(28, 5) print("\nCombinations:") for i in 1...20 { - print("\(20)-choose-\(i) = \(combinations(20, i))") + print("\(20)-choose-\(i) = \(combinations(20, i))") } @@ -122,13 +122,13 @@ for i in 1...20 { k things out of n possibilities. */ func quickBinomialCoefficient(n: Int, _ k: Int) -> Int { - var result = 1 - - for i in 0.. { - let columns: Int - let rows: Int - private var array: [T] - - init(columns: Int, rows: Int, initialValue: T) { - self.columns = columns - self.rows = rows - array = .init(count: rows*columns, repeatedValue: initialValue) - } - - subscript(column: Int, row: Int) -> T { - get { return array[row*columns + column] } - set { array[row*columns + column] = newValue } - } + let columns: Int + let rows: Int + private var array: [T] + + init(columns: Int, rows: Int, initialValue: T) { + self.columns = columns + self.rows = rows + array = .init(count: rows*columns, repeatedValue: initialValue) + } + + subscript(column: Int, row: Int) -> T { + get { return array[row*columns + column] } + set { array[row*columns + column] = newValue } + } } /* Calculates C(n, k), or "n-choose-k", i.e. the number of ways to choose k things out of n possibilities. - + Thanks to the dynamic programming, this algorithm from Skiena allows for the calculation of much larger numbers, at the cost of temporary storage space for the cached values. */ func binomialCoefficient(n: Int, _ k: Int) -> Int { - var bc = Array(count: n + 1, repeatedValue: Array(count: n + 1, repeatedValue: 0)) - - for i in 0...n { - bc[i][0] = 1 - bc[i][i] = 1 - } - - if n > 0 { - for i in 1...n { - for j in 1.. 0 { + for i in 1...n { + for j in 1.. Int { } /* - Calculates P(n, k), the number of permutations of n distinct symbols - in groups of size k. -*/ + Calculates P(n, k), the number of permutations of n distinct symbols + in groups of size k. + */ func permutations(n: Int, _ k: Int) -> Int { var n = n var answer = n @@ -24,10 +24,10 @@ func permutations(n: Int, _ k: Int) -> Int { } /* - Prints out all the permutations of the given array. - Original algorithm by Niklaus Wirth. - See also Dr.Dobb's Magazine June 1993, Algorithm Alley -*/ + Prints out all the permutations of the given array. + Original algorithm by Niklaus Wirth. + See also Dr.Dobb's Magazine June 1993, Algorithm Alley + */ func permuteWirth(a: [T], _ n: Int) { if n == 0 { print(a) // display the current permutation @@ -43,15 +43,15 @@ func permuteWirth(a: [T], _ n: Int) { } /* - Prints out all the permutations of an n-element collection. + Prints out all the permutations of an n-element collection. - The initial array must be initialized with all zeros. The algorithm - uses 0 as a flag that indicates more work to be done on each level - of the recursion. + The initial array must be initialized with all zeros. The algorithm + uses 0 as a flag that indicates more work to be done on each level + of the recursion. - Original algorithm by Robert Sedgewick. - See also Dr.Dobb's Magazine June 1993, Algorithm Alley -*/ + Original algorithm by Robert Sedgewick. + See also Dr.Dobb's Magazine June 1993, Algorithm Alley + */ func permuteSedgewick(a: [Int], _ n: Int, inout _ pos: Int) { var a = a pos += 1 @@ -70,21 +70,21 @@ func permuteSedgewick(a: [Int], _ n: Int, inout _ pos: Int) { } /* - Calculates C(n, k), or "n-choose-k", i.e. how many different selections - of size k out of a total number of distinct elements (n) you can make. - Doesn't work very well for large numbers. -*/ + Calculates C(n, k), or "n-choose-k", i.e. how many different selections + of size k out of a total number of distinct elements (n) you can make. + Doesn't work very well for large numbers. + */ func combinations(n: Int, _ k: Int) -> Int { return permutations(n, k) / factorial(k) } /* - Calculates C(n, k), or "n-choose-k", i.e. the number of ways to choose - k things out of n possibilities. -*/ + Calculates C(n, k), or "n-choose-k", i.e. the number of ways to choose + k things out of n possibilities. + */ func quickBinomialCoefficient(n: Int, _ k: Int) -> Int { var result = 1 - + for i in 0.. Int { } /* - Calculates C(n, k), or "n-choose-k", i.e. the number of ways to choose - k things out of n possibilities. + Calculates C(n, k), or "n-choose-k", i.e. the number of ways to choose + k things out of n possibilities. - Thanks to the dynamic programming, this algorithm from Skiena allows for - the calculation of much larger numbers, at the cost of temporary storage - space for the cached values. -*/ + Thanks to the dynamic programming, this algorithm from Skiena allows for + the calculation of much larger numbers, at the cost of temporary storage + space for the cached values. + */ func binomialCoefficient(n: Int, _ k: Int) -> Int { - var bc = Array(count: n + 1, repeatedValue: Array(count: n + 1, repeatedValue: 0)) - - for i in 0...n { - bc[i][0] = 1 - bc[i][i] = 1 - } - - if n > 0 { - for i in 1...n { - for j in 1.. 0 { + for i in 1...n { + for j in 1.. Int { - var bc = Array(count: n + 1, repeatedValue: Array(count: n + 1, repeatedValue: 0)) - - for i in 0...n { - bc[i][0] = 1 - bc[i][i] = 1 - } - - if n > 0 { - for i in 1...n { - for j in 1.. 0 { + for i in 1...n { + for j in 1.. Date: Thu, 2 Jun 2016 00:40:47 +1200 Subject: [PATCH 0369/1679] Minor typo --- How to Contribute.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/How to Contribute.markdown b/How to Contribute.markdown index 385d712e0..1862eda0a 100644 --- a/How to Contribute.markdown +++ b/How to Contribute.markdown @@ -28,7 +28,7 @@ Just so you know, I will probably edit your text and code for grammar etc, just For the unit tests: -- Add the unit test project to `.travis.yml` so they it be run on [Travis-CI](https://travis-ci.org/hollance/swift-algorithm-club). Add a line to `.travis.yml` like this: +- Add the unit test project to `.travis.yml` so they will be run on [Travis-CI](https://travis-ci.org/hollance/swift-algorithm-club). Add a line to `.travis.yml` like this: ``` - xcodebuild test -project ./Algorithm/Tests/Tests.xcodeproj -scheme Tests From 4a8ae7c7e2e912c9588690ed3bcc181a7fa4178f Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Thu, 2 Jun 2016 00:46:45 +1200 Subject: [PATCH 0370/1679] Updated links to point to new repository --- How to Contribute.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/How to Contribute.markdown b/How to Contribute.markdown index 1862eda0a..1e2f61b41 100644 --- a/How to Contribute.markdown +++ b/How to Contribute.markdown @@ -28,7 +28,7 @@ Just so you know, I will probably edit your text and code for grammar etc, just For the unit tests: -- Add the unit test project to `.travis.yml` so they will be run on [Travis-CI](https://travis-ci.org/hollance/swift-algorithm-club). Add a line to `.travis.yml` like this: +- Add the unit test project to `.travis.yml` so they will be run on [Travis-CI](https://travis-ci.org/raywenderlich/swift-algorithm-club). Add a line to `.travis.yml` like this: ``` - xcodebuild test -project ./Algorithm/Tests/Tests.xcodeproj -scheme Tests @@ -43,4 +43,4 @@ For the unit tests: ## Want to chat? -This isn't just a repo with a bunch of code... If you want to learn more about how an algorithm works or want to discuss better ways of solving problems, then open a [Github issue](https://github.com/hollance/swift-algorithm-club/issues) and we'll talk! +This isn't just a repo with a bunch of code... If you want to learn more about how an algorithm works or want to discuss better ways of solving problems, then open a [Github issue](https://github.com/raywenderlich/swift-algorithm-club/issues) and we'll talk! From 88f89491299675410f73b7014ddc9f2f9dd6a2d4 Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Sat, 4 Jun 2016 19:18:52 +1200 Subject: [PATCH 0371/1679] Adding logo --- Images/SwiftAlgorithm-1024-transp.png | Bin 0 -> 46580 bytes README.markdown | 2 ++ 2 files changed, 2 insertions(+) create mode 100644 Images/SwiftAlgorithm-1024-transp.png diff --git a/Images/SwiftAlgorithm-1024-transp.png b/Images/SwiftAlgorithm-1024-transp.png new file mode 100644 index 0000000000000000000000000000000000000000..5b903741432beb9d0a8478329873546c10598f05 GIT binary patch literal 46580 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

fet^qv3evI}+`Styw(o`*8SH*4kp645(LNy*8 zi`S`>Wg;ECP)b}d6p(!XLn!_PadIjym^Xuxg(vx4@QUqrJIoOSwBGGg$^H@egdl2s&} znm6LU)hy?2*2;}tM_wFKT(nKj28mz;FSa?^o2Va8UXI8HWSgzo`e$~z1b>$qW!#rD zx4Y2_@W^(qJ9OF-t|WE+vCrBxsPW=oOx|&g^jos-`l2A2%u{q@rP)}T1^0vlc|0$< zBnFO4JY9a)vfPIym#+M{EiRU`===bB5$k?=&5qJ~u}a)Dac8Cxy%B+Pq4-bwIy%!} z&oQenTz}Z|98=joJ9TM$^o}XHKa|K{n7wFT46h({ zz%uwjOB+x?eFV}|Gc~bsPvLDuz;5eCV}>XgN~_Z^(YZPwkHp0@PiLUNI7B6y0?jJ9 zGI*JvhJy`0=fCgm2o$4{&>;8g3=SR_uhwh6^}*lweN!OAGKr%bN5GCgIt_7>%9y~B zcm_(Iluw0!X7AK885B~|X^4VpLQ=L;Kb20AKl#?K@%1~iAwh_AdLYR8wNNJD;zmD~ zt?`I>E$wujC8D9cl6z5pa}epHo}Yh?YL$lh-!z-@2uFl3JQYRG#R6tjU<_CjcZBDd zd)gp0HIQMxqM2yB{wmP-1r2R8N%lnvPRVMvVw`{(LvSSq{LHaPa5-u7f69n>K>d%F0RIdNVw+qlqvBm~d@s@4D{Q z*YWT|ae(z?VaW5tOBs&qndT?UzrpB767HJ`CEt(%PE^$wg*P|;JiEB#O?!&o2P64+?;>J~N_?k|c zxP|cfv@N5WvmPe?C5i#|Uhi*&!1Zf>&8gaGr^Dxyq5NiepWAIgz#)ixR~$e9S?0uw z({tB*2m~WJ3?q(uF~?Oa{O&K=rs$(cPv@l@EuDAo!&ZugAIAuKJpUK`W^;=?w|TtS z)ukQ+J;X2E2e-09TKnC!Z3`Anc~7A=v+amDK58QS75Dp}sj2$+#fnHFMhEWDM!pJ72UEvpV#QK$ zMi(Ns$LOA(-2=AE8OKem8tzScXFPMKg0Qy!9p$c65H7DulH#9NyLJ@kyuV6cu;s{h z=^!~m3eE?}#f4`!i0G4i0{S;Ny#+DQ)AUvjs9XRxz#cD56xD!RDfGP`jSm zqWATw-=$w zu^GwxM!+z*lSDeG%;i-f_@Q$CC*M*(?Cm;4X$60q#e`LLW(-7$C0&X$0cYWT+<1wCWp>EU)_bTsI49UE@ zl$PRO&Di7E7H*((+VoDJm@cPtj>49~hAd{dU!m`7@8Pn8@O2*#S=v=g?K%19r5=0R zxz8IqKR7dwdpO(L;hWT`-Bg>K@6PQ8ouy8*BCvAjd(@e>-;uCe3(nE5>O;r2)1jl| z_jjUkU9M;t&rBSbk_>@m9(3;_7K9b?skaPm%g>|YoE#s4BN0Gi21Y9Knh-*Q?RPj= z%AsVW3Ap(!ovjRn|1hL<1wE1#=pq`b&Pvj-;i|2oTKmu+XF!u!O!8maAblx4TT1?U zr>+iNJwHB9e?yGGNk^2m3xqX%v1msxh36r*Oi?&G4cMs_?;uc=Fa|egi#YdguL4hr zAQstHiINZQDnCb?aD7k@JK|ogcla`V|HPM)WsZ+aF+KhCyBQ2% zP0KBA{ZB@i!|D6+t+~ns}H>nw~9$Cgu)bu|E;IOk{8J z;#FT0KQMbgcSECQk2|VV%XMi9}b9Afze0!tIA$G>4#7y z)}(N9hr4WIdKEXTCS;99-b!MyMIORxYwnog-*7tf@oyLnmOxNXM;v&;hYRns?+d!)ID*bgHFoQ-YJSu&uHYN4OWsi6MJ2j2bP8oU=-Yj=No(*?Pd>6{v4ZD)o(jK^P}`ts{!9EPx> z*j_6*`J`!yoj|~YqS84`_(Vf20osq~jlN}Bv2(iFD{N$?ygG-kW~O##^$Na9HHtJ@ zB}+XkJDa2F&kInBwb&<+TG94WCi^_im#qTqxAXK>3{4%m)vqc+dCcHu@G-pG(!`EW zyU92Yc|v+#Y(DEAXOAo-*4D9wKJ1f;A74g@-~&3@Qc~E@@27lTZ$P`94S26LasWWH zs&dW{!vGu@t{r@bVmmADzx#&e4bv+>bgn7mQ~u+5)iNE!Qctco*!i4>iln2K)AbtH zzj6NJM>m|y06_T9{kKVVUZl}WKBRz)r!_S;iHdH-RC08SrR%zyodva~!8}Q?_oGPI91-Kj#(Zz6`pUGud@DU?Yo-y)`dYX*)tKMbQ9!c(ep zA0^@4D@>SyNIt>;;vTp=j}DlouI1oWSlAesdoY2w`su!LffAr{aU=R(w&*ujg4rh@ zd!+y@;4||t%ufE^W4a>uzOSd0KTv7hR%~bwVKtzXVCYT=rLhWX_o9BB&1MJ*$)pQe46vr#n z{M9i)3p>L%6y1Kl)M~TmyA^!$jOgto97z7#mKdHleEG8ktd*^p7Z>YTpl`1PRSh`y zSGMzq9wF>0=?2yfhM#hnMV2}xk)zI755Cz>b2)1u?D{`UYmzc%bfN4^UH8O!YMzUi zr|@M3m9LL04oJK4)SBVfGut|&uHLpmfgIdu%tqTEQ8C@}f@tQ@bM)G!N;Kt=xc8Qt zbnnA;>y{NG2N(Fj3@QBVW!Clrd|Y$MyZX_oa{1UPW9K#fgQ4QkkQYmgqnFgaLln~{ z5AoktSwY(swx$sq_t1|w)<-WXxd1s&t!vHKVH>ACa;JAp5l>rF&Me>@Xdc*UBPoJP!eS4CcOM3hc&19p6JDeeNRlycRX5=D~)43+Qsr()td z3WU$J03fpY6B&BT$7_eDr~N0pA$Cy#W!0& z98109n_}JBCJ5m4djmzZS2Yket#3PP37{5)#-nG)v=3x^o|^7tIDHu%s{A7jGo9YG zm^Xr#lsiesZ=k{^0|ia2zWA0x(PjsYs18*R+wOcZsj15OAK+|M5gz98Vy9GH=x$}m z6N0_3MR)Y}FH;`OMa@6_X}qqe|0(BDA;QQB#RHMcpq;j6P8_RwnSv7#rCT0bvY)4W zt^qD+#pIS7+BP(Fw-dYhk0hfw8u0&k`o4duf;UI!27B%H){)Sow~Vf;Xn9toTzGQw zmDye~33-X`4^2)e-&-S9GkkX_P#->u05<>`c2XKt!v`Wq9;er)y3?}nzM++mOph2R zcp9V6=Eu%3rP!^-Wjm&)Ze_Ud!3|bUO7g=_Xo zeN1-NO#~AB_tXuY1{=?lwPE$gBy^8$u)G5=+49BEY?k?*5*lrtUM+vJidW0@gTifbAcNvA^Vjau ztISVJ6Fh3Mz{P;Jx)_}E*Ii>6@bQ_ZZ+T_fGS1b<(h(EmrwQ+`>_>ESm3x`v;R$XS zFnJ4a=gLrTxXQ~)YItCH5vW^P*jC(-#Z0BB8FwZ(3J1{{7 z0jjiO-mqNVuCPCDOC^*ec@_vmsvH$kM|is4W_+*pUiZoFlCasmAGkJa2o!WJOa|*Z zd&-GMtz)wTbTI(%V`Iv|#i0ovR~r5Z>3h4^{@zMs*c<6crmbCoDeIa@M$$qzMv>nY zqP_8+b9j>KS?%O72HSC*m{9zx2h%ntqZOZKJuYdij(DDLpvDkgbRhl&JZr=#M5FKgTFjCT7}&1Nky;4{5;PA~86JGb8WMHUF_Z)wZn$IGOP z)#*xxUx%@Ko?QvrOSS~Wk7;7;_gOULkxpe@-x=lI%LpYD0S8dYieMhu7j?nQ+XG-R(M3nOTszW!6gvSa~U2B-H;-ZO5;#}x%4zx_}@Yn{3a?Y?|k>z{u= zC-n}F*1;VNd?krAPzSl7og93tijFtpQyf}hm{S;10sf?EUtG|cDpQk)YgaR?VjkT% zA2HlOj9U0LZ4kyh=>Cm|H9YCw_4KprW}{7sF8nlA7Uo&@S4Fc3wamvH|M`MY zf0Q*=@p{%?Hcz=gj?Z923ulE9tf*p4%3t6!ch=6KNy36yW|Q+Pw!fr7=JxIRE7#Kz zC#NZ5&E%#NkG#mP5Q3s1m@#&A@yN9@j1}BdExuB@8Fnw%?Ehw_TzH*fCq9@ac{Yx{ zHmerwiTc#$wRGmuPG+Jj6F(z_Tl)#IHW1dShjG|4=FgowNq!$gnpZ>ogbz|8cr9IM z)~mt^O(LiEZB3y8P2mzUhB@|LkyKi698A*Z2fE6HP~Qy3+`4S1h7ICj7YA#K3`R7U zM~$Urw=K!HJ7Lni-Z%!10fK65(4-QoDjS!hFJu6+2CbVBJu5bs#87yXk<>Rfc^AL_ zO%yOkgt9$~rFF$StkZ-(M+&!_luoq0y(Z) z7Nt9P%qnG_GlVxVf4JY*HmP4{8F3JcBge&eKXvyx@EU#>^+M9SImcU$Z)-w7c--3u0y8jE@*~GYB zqI!x)G7W=)98KW6X*G8t+?Cuc2{0wS&ab&CFeg;C7tB!c_s+9mN?3X-F9!gg8TAv3 zZ91(R>_BYZu-IMB%x>}Sa{>LQeoJF49^||UN5A6UkADddGPS9A$F+(gBSYr)0ze|` zjciZ>re@3?|1GeXXQ9hm_q%wK=Zy;l9(1_tR`7uL&F_kI|L#xv)x<9b5cn)ufC*YS zdW+VOTvsk0$XSI2l64`?WDsrFhuOZonWv%B5~mGzAz9(l0u%PTCRc5?Os@M7AcyD| zhDC$i5{9AP%XkxVCF&gRHu-B1fXU(+ua}UxQ+a}?+?kYRq0=!|Z@@Iem!i{SOlX(* zph@(grOxLi2^ccY1?PK*>Sn)RjE(t2(}M3xvFrW}0kU;;V7mBjvG|Sbi~R-qz1|cX zEfWAu2l=k7E&{Q{#!TOzeN#c&mhM&4meBqcTsvAQ?8~NW1egRbYIyr`B^VI`es=fZ z$i~QhWo;FGl4$^%QuG)=m-HKsYI z>{UYLLz#!%Y80nE<0H1rYlE8Wr)-DAOd9R{1u7(>$EoSH$A`I^??i)mPg+$Tlw`38 zA%MlKv<+vG;-;*z_vFfYmx9>Hq`>)+?l1P8(|e(b%_KWX?Ovuq6Qb9*G6BqM&n|^E zTXsdVFU>0g2AyS}*Q@x>eX=e8Lw^T6dUxQtB$urDn$n2J#m2e&(RsNQhlx*NaRgV{ z;HqWcDlNlNu_^yCvggrg9iCE7L1N%G?b{|{|EYVG=G71GFE}EYD|%NTNZW|;MZ|Q^ z_m+Bz4L3s5>2@~P`AC#bxz4#j;CWEVg3rTG=4vsId9X13GV43`^`pEuDPK=RIVH`n z`T;2tI3Q5GbkRm>zg+|8f))8OFE7q+MSa zLx##iPDae9LQR5QUTd-5cz6FhpI;>2BX<2Fxy{7zvZjP$NKb`gd#`KZ>8ld)y2M^S zNSYu{i2^E{J^rV}H@k1I0{4Fr94&prBCYz&%F_%5z>v_{PX5$~(Q-bs3PDMW4an+C zymmm)S-8%h9)E4LK+yH9ZS4;e&E1b`H=74atxwdtkSS*VZ{ctV%rn^UpVQw=$5*MJpTqH}`tLTQUIO!vXgKH{!SS}_2L#zX-T*3!dI<}5n_Ey=lrr%)ZvS#)U6QF*A z@f*1dy!g!#!zb^?(uwO5?O&_Oa;}O{#Yn0DS`^<~- z0(jWNJ4*<5Z;D!l;S3y(+@rtJV2%m$%b3V^mVxdyJAo_m6Uf(|+84`;bL7X{oV&#nkDrd{Z9O%k z$Q-}XYs!}tymzq+yQxkpCtB1k`s9H#wS?W?n+RVFG~ce!Gq-+JD#Q=u3>u#4x;hq> zAe!_q&uBACMSt#%=X4$An@X3w9eZhXYe6Q@D!_RbyTkkEZ-Ib(`G|`w)mQJOy)`(M z@%AWjaw{2qyF zk1yHwDXqMXLl*reWFI_u z9^wHlhr=|EyY{4?8lekT?{?BXR2KE^7?yv#eBN&k zoUz?V!3Sp-lm}s(dv)LVrM%4W#XfZ70}giiyAEGz2WON3B0;PipRFvGtb{equUCpL zI+gDvcowi!uG$8(iw;R%2f7t^*T#PNHnIrj=!0d8F+3xOQmn;wjoUw-h!uSL=|F?^ z=A3FScG$N2(NEIrqM>ug*VoS&oTAf9$N;S;s!FN35+@@(ZXZY?eZMRgFLmHVkDY=%-{pxG_^2QrVxiG{KDt0Gk4%LlQU-%#`MSt599uxpgG8 z6T6wK==v5NnTZ~;b5j}^N-wn|KW7xiKNXlvR+9wG z_S+KdhkyEL>Mg_sKF2llUi0mVf1-v;7cKcV9yJ%ql;2%HF-y(7pnlFwe-m7$)#mgr z&_ZKymLi#~I?nrrzb80qSD@|fk4x-dLa{pUn&AHfHr9+e z3&R>ME~%vYCvq=QD&<^#Sg0j-eYVc;nr1?DV4ax8ebKj1M%~{`&`~F3q+i*x9DG|L z_8`Gg%q$JLaK1RwVI>8k?~6#cP~)ohW_EdSup*4(Zt<128S8NC|FJ!vqG}eUt>JguQVd9X((MFfecwW$T zTQEgutf-w0{T#0OdCx7#5q@2XC4sLc zs{bcsr|>y%j#TlLr}}>Ru7g>xpSOM&Ie5rV9jLH@r)c`RE2}ezbAKXnXu54tjGva{ zY+bDbliL`Q8+^`%g1xbnElfln99W%nnz zLkeW{UTI7_;T~jNW>_I6svj{XP4{WLJN449Pv1duiqhutwPPM1&iyWxuK9BO#3@jR zV}HU^_05*w_$khr36~qMd3L~kWoKKMkH_^DAv6uAn!1hGG}fDK%qsm&G7*3;eo6aD zs@S?ATV*SKy!)GxMCU0oM|FV-Q|yR7{1$69+GD(Q@pR9SA3p3?c3PtvIve_-VXU&2 z$AHKJ!dN5~Y=YW2(l%HJH)bWF*z##F2rlX!O{4&?@GtFD3q+0` zy;gAjDsf)7rq7bJeIZ2vPoT>d{6TSDM<;vq!TyG>K%1%*4!~|3p%~Fmr4tf8m0!EP zm)9>9oR1bRZ)?1p%k8MhMG6xhJqf{t<+?dz16AU;Vox_>{;qDXi;P}&BLN5!ZGMDj zm-=#m;ipdZR)PObB^LEsT}v%llc7^FHc~sC+^9UvzEyUf*UW07hP*nGs;1Qh8|n6@ zv3TX)6J`A0TPs1i%HMzyGFm-<+{R;_;NA*q8oD+?B^T#1qL>gb2S^S-E2U$p(*h5Q z;3LUYO4zk7n2pE(*46%<{CXWv!bV-K z_wcW~T~8lTtoQL;d(T+J7;%W^*lK)ixu2I_Fe%H#uP5gHtT3;8(e+cl?82d2O&5+a z1o`)2$J_#==JyrtfTyXyHWrhJL*Un2y!$l%fz_W%6-ItX?73a|lN3E9+UnX4n&Zya zFYdxH20t$vQyx1VSST%_Iz~}_T3)c^n88I;ib-xfN-+t)y)%1-Vp#F}xRHUoKbw$|THonEe9FV1bd&VzQMvVyu^TEpa`7gNG*LprY@GP@Y z{p#+cnx##8PI2BT<-?EOO$@Gy?B~HIDRoB}Pu?vF1uEO7{}hcsvd2Gp`PE|g1GsdI zd?L1_V*2c^ZTGB9BE_hzy<@}^@svM0?B{K>Hm{s1&J`GqKB?q%U(!!&MCxRo7Lwo8 zME3@^A22kP&l}AY2y*8?#9l9}D@uY4$ZaD0M5HI~emtDVaOOy<&Z=uly7!hTMzaUE zW%DY+Zd+Ly(1k!zv4B#>qGVy(I&Q(ADJqjIoy(P!XGtHRe_Y<~jYnlGNR%}|2asS6 zpwBY(C#z`G+K(jv3ghvoUdfFV8r&jcca4`C*!QYSMBKNu6KU(>ujd@#w`${FX)|0i z4BOG+CFv96(J7tSW)09Z6^=~uLSiHL`72E-r_<=mZ^wR9^ZP9sv8Yn2mLidw%;VRJ zua|^XXebkiEWVaf?Qm5Fgr=nRj-q+KS?!DV8jXrmts-^0Y%KFb^lV|1ar@ScYZ;i zV&W0;w(s_6{EGAYUWW-+T0}z!t7T?Z;p#;_ZO~)F_brKj#IIB@-&pOHl~cypsvF1} zt>FT*q*AU%?_VgH&|$7Css0l63ryE1yb19CxF{g@19qA4F2{i%&^?{;_OpC1|YQTh>_*T-!((DIUhW|L%EhpMUi((X&nRcV%}$v5V*Y`L2<1~2Jg=gzLTQ!!)^GyH+qKhTa`x5TCXYDG?SwfL>PLBPZ_^&_sv z95MfpisAE<*`R2?iX>G}%;xMahZr-@eRhEWZx`=pP0x?)`i%lpUdCbGxPVuvDdr#= zth+ZGm^wf>SRjPmAO6Wz-NZvTX+#UxdrvUHEfjPRoe#Rz%~gQ@pk#eU8(r zBvkw8G}CA*@LPTpaXE(h&^=|D`L?i(DER227ErLkq>gf?%K~mt`t8`;XUG__>f}_E zO%qk=@U{Ks(fX+k5!VDICa|egcn>hA4~$i~w5VQ@-f6&gza&Jt{m>5h+5R^yX)%?t zGmZzEz+a!gp{8UGL#_TQWHc*D+7&j67D_qZN#R%rWT4%J5SNfEg$>?tQG95@t7Y50 z`++h(t$RHCwiCiIIk+6GqGH%?aJ$OlPaWOm%aX{>#uBSR=s;mFYXDhf;iRikUPq77 zcCeb~Af-Yul!DU8zd5@~GZsL(HE^{&vD3JXn@e~Xy%>ts+IP_OyX{9dc{rgA~t z`Oi}ppp-BeUfd(2h}5u07?n(BPn*;Gi~X)(Zg9chr_R4!Z(5F7H5ztT_P8FuuCpobGEtFzYZlfQSHV5}0fkF}V{?`LuSorll-}Pz1N==`lSjgzqu%ps#%0U!LGnY%7^SjridaPzgt( zamjLCuxK4UK-69O7L#cATz)yHJ|_pvk(TB?v?F_zRt<$@+P7pez;$GLro=QUK=Y=9Qvx%v7X z!*R4sxlD4C6|t`OBg!1n7a@zKdaxYLfaAT%7BUpezpLJgefrSSi{rXeE=-D8x1JOp zHZUn!3VHpb)j(fpug3J9qhaVjl#@v;+9RsZ^Wd%@8c}9++E_dvl=exqGUookv{T_o z^|R47tE(i(2#^-@sTZJp1Z?%aO`FD&h_>o(TYv+RK+65ahqL~}($q!K(6U0g1#Qy( z(Y>g5d;%tJ!W)+gZ@qZzHy2&V# zTvmw_k-EqN$Pma>My+c0=-_@4!NI8gME#zwI{ku(!p|`hsnBT+_F+im*ot|wPXYuJ zXPlXnS?Jjjeti4*S?OtjxsS}dEVUXMn3HfjaN^v>g=KaB^BRM4U~9RDvoj2r#+D4o z4$b|%O2Vmqj;NVFGV@@p)gn!RB7r=+w__}&C7HAv^w>x$4gO*uVE@ZryB_i|*nI$9 z^VLJZ+w!&M4zH;#B>=0>O{x3QE0dZ#__QkfiCG4Kw32k;_ewKEekm4#`<99s;<4Dc zsQL_^nphQ@hwf=YvYN9o2!>f6}Lr~KGKQBz@$GebT%vP^{sS}E0W2J1tP zDTg!e_552TguQSBoGV!^%0kPSzY*-KaAn>aqYsmjMvQOGTrC#-%G0jAwWi&;S`0~= z)o%lYbRC>$*)1mQh8ZfKw^^3h6|bUm2Ulck(oB%UMD#@%QG>`qiZ!BOrQgoOJp{yW zB@~el$IOyVjD=flCcmLB>5E9O%L+8u>S!b*gscdl4hI;)TlvjU0b*7ld+|bGwV%#dmt)V zW6V8dgfS$xC{nY#je0u`x_1K|^!e+Fiyr3Yr0e+|UKH<( zSERZ8$d2ye4Me8JSRZW})A5;59kKRal&t1Ou$W=5`}V71+ZhLPsNa%Rwj>@NY!$>& zj>d6fC0AJzHCRq+iY|Y%*a}{1u{WJa+Lf(iwb-Rs*12viuI!Iq1@@6#d6N$^1*;ye zz)n=JhMU~c-(CR+ndXXs>BGYWro|uYOZMODdYe;9TGDRyb_W)Dpy)9^6j47EJ+UF{ za4weT@(=2BA&IkMA&nb|6PX&Hjp;@{m8>Bo5*Xf_l5W2(2|vxPwOsYm!)kr{w1erS#IRVA*vy#YU||_bQrHIhD?pR z$h-&nXx0pGHeLNQ3E#M_-0L_~#YQ$brmO>>jHL8#7nFB1#D~`nDWRe`J@vL(35O(F z$TY65NYEi80sGSpGx%Sf{Eqd*U>7Q2?Um2Au&)-cS**?W7{z=fGb%Y`<^UbjUCs2s90z*~Ho}kw*y%hzgnBL>W*QPFeoY^QMca#2K>2S#cFV6cJ8@ySDlslVjW$hJRwrcI4ibq98w z9DC;I6L1I~qsm2?TJvvmzB*7Q*lRJSwD;rsGa7+DYb2825dFi*n1PSFj2-~*K$V2v zE3=l@^O3lTFLtf_pqXCB3aeIKe=5+NA42X5baAXjaSRoiHB$!7NiwG9g$mO#YlQlZWj>=sZq`tu|J8)K#!0=yYj^!hH@ zsLOA58vHKN(^h&8;jlEvsHqpnx!V5SD<3iOv;q8SWG0O*M18|!uk;O@T%ujlv_aia z2x6B3tIMYQvIHj@n$oS-h`Adw{P8|Ef=_&tJ*&fe$L#O7EY<|b=liTFp>q7HZLipJ zsF;eqd9Zf|>jTqV{ z3gd*v-={v}Dg%KvlsUA_)Xw*)jJM8y--9LjF$>zr&4|yA84WPY-M2Jn;xJYgG~0w6 z_gyu3kMs)vx^cfWuba;5`BXk;wT$NFk2%&;(z`kv=Z5idBK*w0e3^Q8u6DDoNQTa) z?R%P}VQCxSI(@-8PEveIcO^P*BBf5r+iU}26mnZkZb=y0mLD9u3tMR=AGx>iOvI+o zwTPCLL^w>#YKi!xQA-)J4!eC>ySLx^Mobe*|Dh7Drq^3FX zrE63VN&fJ0qpVlFBbac1qb+mu)5@qGhb<@hK=XOwip$*@@(6h}gP_%F?;FH1OZ}Q7VF^)zDsRCx-NL^jUye1oPd*2PxKYV|` zLLN2}MPtt9O{Zz9e9K_Du8BV8SS zwCpZyD|cgglp|prxCUnfl=+lrEH`DWcud{{H!G72q!5p#f<>nxY1w20%|--WvsBUC zgQT4FY(QCEZn^ufAq|xNAo+6m=5&3Elr;Fw^fS>Aar1>Ve~F~0Zl>k7>Xaw#+&FNH z0lN>U`gGhi3qXN(QTHqGdTifCnZmxANbo3PN(jFkX37JBW^x#XHvkUKR9eo z@1@Xqi@bjf!{}9#|2mU<#3Y(0VWfPeHDuuz2bXJX1AjXZgCamLtB$=G>cwMYMIFiQ zo3mW0IulGTMecki7EHHmD7O{3d;Uz?-Ha2wcytG?7ItJbRzv?58Jfh4UfaOC%Xsc% z$*lyD$I433>rI<+c4lj8^;J@#yA9&czcQZ7DE$pZ#{*Q=aiS@$k3;_&!ntj@TaJ0! zF%SJNDU%Y7b5>Rp4t2s0yL%&A&J&(7Q{5DZ~bJ<%T zEvPgjQX;_v(Y(B{>Q`c>1Q2m(ne-M==Hp28oRU;E1RV)Sn_<`djBdjcPz1iKt~-&5 z5N^=$JzgA$YM&`#a$=vgjcp4uGnS-03jUBp$wvkug;<*GaqJ(+YEHD1Fm3-9xORUu zYJ2A469osRn2a?EB0Z`k-XcYp?kah~o{_0e)qkRFasB=Ibg{3IrFVXHcw#%mnfAdW zZ;G2njQ~7=aam3z4l54+7SND2A>1N@G;AqYG zJVu1`RUR(H32eVzWO4B><5|J_IC5umkB(U6s=m7sAX3l|K+JHbOIn?c^fUlyD!Ryy zo{iM6z@-XBa8AAuj+YE6rGfLrK&N}lPhaad$sJtG=zi;g|+s4K)Yxn8LK|_tB zou5~bY3J=Q^VJ9)|34(1by!qS7su}|OLw<~bTfi3wcXMypl!59YH1+-6Wm896+0_gZAMw*tL4Uy&>m}UOoU1RA^GVk1W}5 zQu{WC^v@{qQ7D}u(C~0412~-}OQbv*=rRC_*2sAaVrCFts(t58Ij1-5w9$BYd1K*q zVTzeDfwgYePlY4Jt!{i6XOsK4gd=;k-RapHc{`)aWnIr(Z?0Bjxy>9hy*QBl1||K> z0A6*)x(^IAB`7vSIkTrz*h;d`oUm6OSEzuWL13d z{fDt!V!7Xixm@KnqmC7$Z_t?Yd1xT&X^#B@cQOjQPjAX1^%fo+#J4|v!)`2V8OH;$ z6_LnH$?aFRO64t(XQY-2Cm&gXKj&4ti5u7Jq##8!76}nuhEiPfQR%J<@Y9A z23-Gj%qk8vJortLV41{qp=T3CV0E2IZB__js}cKPN0*=B_?qYkccb0sJO1?s%hD)nfcA&;$` zg&MU#GzM$W$4aziKF3yk5x-0)Hka%9fpNY2QRzpm53_gyo?w}21v2b92RqP?h7(ma zy#h3o=KcL#ldZRHZL;A#$gj_H>E3wERk;ZRyDGH|z$}6*sLpe27V@8GrjYO8>jiI$ zlw}5Ml__(#=KAL{KE#N@FRsg-7n-#z?iit&f-Yboe_>w~ePXs2#Mff9<0|+ko*17t zI`22(4D{9mPOnC6Il-F#k^&=L5R#Pi%V!=LLiI}k&(Ku6rs->(9NGs*0eX@eFh|C- z&MkLVo;{uO@4@#H>S0~D*O_KLTF_eQ>lMKj&Uw!vIEh$a*WXU`mQJaCJpz@gFQU_J zW$%$|gQQ_K^W+hQ#u{98aR8%3ol~S&`%<+LE!k&X8WZBlMN%W} zVX=aX6j31Hz^+5q_Sa4zXF7O-=@omOwUym4h8^}5wUi;nY;a|ZYqN9$c_&dQrLSJ+ z@@qCh2_rgKP(bbqOLp@NC}&Q2cC5OnaF&d$9yOF{8oAN^khM8O0%7%eCIaOMEa=+CNwMM}?1)g`BVlmuB z`IjcERcHDNwtgB?wbCs!JD6XzUARBw;{d&Ysb=&2Z{Alnb;P(MnX#?HbHa(iTjH!Z zFO;+8se0EAUhrf_p0z@}a@?~yt+&u=oskoy=MYU zV1Wf~T0g5SzUYy6gvD3LT*Kc!wyd05JMuWzzv8tpctA-mN;~tun~$X1*=R@e9ilrAM*j$U1fOXt*bVd011#yJ zrr_^Tw5K<7wnpz?(8x~sgW%KEc>`=M%17hyD^<{iWk-4)FqEMc-+8P(ls!WarpDxz3b_=0L!uC1GUsdrs|vh6_u?kK0_hHyRXntJu2_|(yx^{D{IPl+(nC@ zo+X%zE`-AA?B?7e8Ttw>?pWEuY^_~C=Lk=xSeNsSAG#etdcSmsrpWQ51V&=?s#YJE zkLE5Gu_%rpN-CEBkq3D{Na$TOIn={q(w zg9v3|^&KZCVbpuyTz1ZOG@QEbZwDr%)7CR-F|Z%sYzCi|Z;C%BDgt(4+-oVz#;`|EctGTa0{8>M`SV`OxCQ!)pH}kYCx9&ksL24kZg|cZ!VDF0%7Ji4& z3n$hq1k&WEgLp!+V0M6Isqj{6Do$H%AMN2u?1JKIsMTSYea8KADePpMTvbse*8i8@ zGZY`R@%Hrz|A-0%Asrs1{AUDB;4d<}tL3rQ*BU|QKTWI9FUe)^Y#(I?-h41`dH*@O zjSru;|ND4G6@HK5kbp7Y$Onb4x@Jr@lyxS(rCa(#e&{KZ?`HP==Q;l|r=JJxAhGR( zC`Ul~G`%8q8RjdE=ORcw-c2E?H>wZ|GYAZDXLYZ!ZTi+VO$eJok_2cmC8KePJx4iZ zU=lm07i8Bt#qDA@n^Th?(1vx=$xMXpr{mpr*GqE$F+OEWveFdqeDuN3Ngik<1aq-p zemxYPLF%Ak#H4l22~1y@PbJN&=Z}b;KVE8=XTRMcn$%U+xnuZPu=eHNbw16{-N0Qs z2qL7N zggEZ4Mck%pg~33fhGol&QsiU)YwUFv__1l{-5USZjP~-H%p2J6OZi=?BSS#2m!Laq zootc4m8Jt6SO2eh?+xbS;j4NwZA}ia*HC-l;5`3N%p6Znw=c+^29#N-oYfG=XYv7p z;O8Z-2jRH-pRxKimPZ9gWMWgf#1Qe~5?V)6kn-AHAs39xVJzx^?3qO%YFBd95OCbw z*b{UJaiOlp0(ETH*rNeHm@$4lL(C&-7$jegpFQ>WZV*>aDcCd(|85@RAXN>IsTmlrWUv;3}E|Z)PsRk{@-XPFa~|>zQweD{qjmKNrC{ zJl}7Qfvv}Pl;Wb*;%=f32tfjvpiF{gSdtdXHIw>p%gGO`H`6yC2~lIl5%W?@Q$F5R z_XWOIiAK!|B8oEChx|qZErpq4`%)KUCT1I%0g6{mc&GG0U`AzWkKnQ*PO0YU3Ng?! zv3Z#mc%0A%aN|t9`_^47r+fS@Z1LwEGN9fxWpTv@yMfu#dB1ouwrb@tlJbf!cE8Ye za!e>nf${qoTTuH!Jv#ij$&gPrFeY$nF}ELU=0Wy;jwx@1<6uP@x~X%lN`9+2>4JmbeKJbzw!=G_z%s$}sVrDR((lSkQe zeaZ+$RM(%a1dBD`BJgsJA#;{D5a_?}m0j89{cU|D)$g{r%HTJ|(A{}5r@`h^=6nlg zljh$$rI3fWv1bn7bj zw(AI`KU2?rRUNYG5}z?4vX0g{H!CY7y2hfWhw;*x7f;~)N$!a@r*+Pxt1^^(vMc+9 zy8J3b+comfTybAL32)>_9xG)U${JVvjocyU{IxPzls_hMEHF&9r$PyI%yssxlGgqO|~ zGEsL#;*MKA78@^!?PPUqhTcutDBJt2+?0u3T+CZ_Ado-BE8;|*Atn;9d`S8S4Qbr< zW+{Tg*nOcKd2WNu%ZM>w_c;`gIywhyUemw5>v(oO#bm* zD~&Jdn9&R;jUMvKu-vg!O-I7&=+1f_CObI$i12>8;FxQRREW*}phSE18wG}zv!!g- zo&Fs5IA;`BEkzPmQSVQt~mJ7!-Oxf_0+Mhh`0xcH?;8T}XFP3l`GYbz>Qcym9=lpMOyejzX3NRQW- zxAJq0MZaB7^dW>oYoRwEuQ!AhKI_e8Wa$K-RFg!OEDk8aHD13+AzB?yvc$ef*VRgs zbv2LgC(xVBbALw7lCwQMg-!XGi-2q5a~-XtXFV7Tvz#0Lpmzo&KuMw3xiZ zsnTWM@OYDxZ}js{7e>!^N~EIkw$G2ri}Ctb#)hXKMxrC|;ivV9>Iu7<73HM&5Ilw3 z)zAb~^)bt%&K0rtd@GTMe6Z^mSiG zAL{A)^Ts9ozxp9$KRy>oXS2+rmnh(m-LtkA8DM7DfnT@2T+$Vd%3KhAv%+wUS@ImN zS4QHKes2WZ);%}v#nEPm+_?&}gbP{l&UPlF;*Tw}wljkOgk{Um4=l&H>feZ?1B@qw z3il;G_Wsd>iAYt?mICu#3i^Am83&5i;@%1@P9Qm+@&`6z3e^-lsT+wo9r3q0raP{U~8~3+1)ee@juwJ7{1;=m*lkML4U3+qsMd}1w za`Nf_umr&_;SKh3wiwzYgdWbU?k%X;o;$yynT`6zvu&UDW#TnZ<{oiGf@6Y1ilWSw zhs8Tt;mZcYUd#ON5za0_8>_v3tlyuGJKK?Hw^B~t1at`fSb=1>YPIWx}rnelmkOsTaDR=K&V4X#GlHxppK)wc{y0c3_*)v*)| zbwsK5S$jIBSr5{{p_FIDKtM2`8zZcWPj4! z{M1$}N{Usbv;jfU|DP)-@8^>A&b3R4w|w*Its>icuM7b!>~5De=ReQjoKa?;&Ih2zl%-C2KnaX79}sQebR zVQZCr7tN#5Q4N^iy|Z=-A1v;@KtA#?!A#pytdG6Np#6%px!A{%Tw(tX)9+hSmBbhM z(ogDpCL7kYmYgc(whJ$A`Au^YB1&CwteDn5f485SEn}&70%Fq-VC?WVX|tH6#kP7G!jEG9{0`e=cGN ztD>UIDu!cjwf9AMDcerQrO^JNIhmdbnkHtpvpkus^9h)v?UZ_gI{0qzL*{P0Y_)b! z1dOnV)p_%G)L%Gc`;7{btM_n^=g#?btwfwS{}95hPYBK(cQsq@$be{eZoD^uYO^w} z=+#1fpK0673IV?a&id{reh;Ig!K|~*H_ioA#N)^nqcbtHq`i^@2$}N8bY;ph$Jk0K zOZtpn^1FfF=7|pG%-3_M6C|(9cmJ`M3ydHG^9N`kTCneb(8s>rA3`sCQE)~4xpDQu zegRY5srP`RoKQlN>NO<3b_AI=F#*NrU63uXLisqtYX;;fYWVMnh=iE$4D5}*DUTA!tXBx5=34D{C__%PV0u<0#-G#ZRw?9HhR zpt#FnKP`B04p6S#igA(lxA#aP{$(|z~L;u+@x>iZO|NLAfq8h=st;OPH*|Nd| z;k|~|sIh=)0oAQ+FHoS%MrBNhICn=r?g!W6a!=dGhqta5t(ZWFu6SE&^RExU9T@-Q zp$8}$Zr6Bxh49)=8or`r>tIA`(&PZEU`Ax9A=^Dq21`-d_wWJkmMioO)R*3#akkci!=Q2Ol>KJ+=J&iXst{rRbk zMYj>$FXlf2vCBgLn{wU~`*4J*PR7iP`$XPMaA$_)gmXe3ps7l8NRp7}icc#KQoQD! zXqg8`<1pTSZ^;x1a`kg6sbt`5PxIUyJ#!r^_pDm9Wvg`C zgB(>Iv?J7u|5oFG^#L#Z%#TbHRF_6Irr{^&yq)6_k641FYa%2-Nwz**r_;BEPav*RAdMZ{7c11TAF}`6paziYm{ITevwmn3UATHRdr3k)l#XYD=r;R$@{_;7kF_3m0#;_3Z@K9|Q-{l6nu-f@pv* z2R-bcn+HnD?-?Xu9Sij2=xR{e)h-bwA)*HX6Fxo4lm1-QFR!d|xB>V8uT$q~$53!SLW)s^b_ML4N5+Hmqy#Rm zRS@{gN-v~poiHdEK{VJvp=bg=iV7jT1>$R?Bm(zK1!YJ&0t*#M90s%A&Fl})(E}^h zDWKeLR%C-U!k-9K*wXFXsqOeCVN17~aO@#`>peBZik8Gw?005); zr@qDGo89Z0*E0`Q1B`Aj_@^LvIr# ziTZvne(N3L175=G5#+wywcI&r4B1|Px`+otM#d??&p*gkKPg}5-e}L4Vv=?ilq^Xi z>V{zmrm{ydY83+goWoNdev&Ab*n|r@2(*HFq2C)%GE1&|^!~|9@^Ah!w68)7z(`3t z(Xbs(=JipomUvc8oyp)>@P~wo@4ec74unpgq*PgmsRT#@X-9+``cNgpzMH^F=d#z)YuIZo~ix4_JU( zB!o1HH^|7+2%>hc-Bg^vIqgqxbK(R8Maj=#IM?I}S@5xVZQ+D31jdIm@gF6bXzAh2 zZAqMR|Cr@O$SB^UM&p?Ot{qir08SMN2+*4qH|41?EnJ^Rky+!{2bEa3+4xyem{W!P zz|8%#d09t7(T9QViMzVnPh zN%u|hXts0slY|K2VLdw7#8t>Sj{MgsMYui1D5W_YzPZJSV!f(P2g#(Jp73?(EeAGg zR*KHg?;D?Js8OC+PwE3loTL{7hLkl`Ics=%Y*=Msb7`TFpP&O~4*{d0`aW5PA2Psz z&AM2%_mhX}vQk@^&w`+&h#c^f4K0BaY%pX*Cx?LtvJ;>PloI85C-sXSsQts;8$$Xx zwNf1Lx*6W*_(`QX(j|kw%X!u<#X9z3pHYl0RTM^-`AFyngZLK zZL4;O<3xE9LH%^WZZ%I8BzqHo`CjS=Wx=ltyH5AB58G`5$KKH^!+%qavNHI7@YljBFnb;_u-`~8(Rkp{Ew^-#_zziGW{oli^_neo4<63ajT1~A7c@j1l5CKM; zql?CquPo;O==U^w2OGI%M8$us6$E4f*zRo#*8qZP|D^3tWA`fgHZrH3E%=(C8DUjF z(*8YMD?aJUHQ^x$?Vqd2Y(pZ*tzR1~2?6}9*TY*bwS67#+*r;^!(eV7RE!F(1btlM z0nNUJ>cN%18w`o*k}&rcM$C?`LG&9qs4xb|K$GH3;MM29$kVcW6x}+xmm9KW#(7@T zWPDc4&_+`QZy^QG-_WFb_?kaJ?|J9G*D`ZwZ_h1kY^Mb+(l_%c1>g+YK!dAJH zVraeZf~Ul{dQCg4Xx=@xZz0ggdY9Yvk= z)YE8Si#R1WZ$8Q!*UZFCpt%-u6JgMi!tL4H%mxi!`bl&4jm831B+$+c<r!*xwp5Ka(uVEf1B3PoXNbf_`?y|` zxvKZd=GuY=x5@J{YEu;w9x1Wqz*Ew24U>Saez=cuxBT z8&#vb6N5W_(S~e1%SCayQ;J*VorQuvVtmpDh^M(%W4S{IcU&)1!`aFJ|dUEk!ZI^4v6)KZcCZX8=ct!R# z6ErnJC@|#~VL=~10y51H0X7-*qhX|g7`75{eRs9akyXrq`47)!I z8MN}YhAZ5_od`aTZe+_IRWaf~0=(^7-4c0Z^yCq9ukU{q^HoF_uCFyl(NV& z0Q=F&BHn=*NFi3Y90yBQoMmirgs@F8libDulIY^d3YVl!;N)?gh?160`@W+Ej0&nNy7ktMU?_B z!0vAX*TBB8*KMsK`QdS;6dD=C5Yuv=MU%_WHcxFKG=;Bs701bWKR3{4~2MTxVsJp{~GNG zCW% z&ocM@inIQ7an7=-u)5OiSC5c1#YcG@I$PnI%5<=lXB=-_m&afEW|=dTew<_hqB;Sr!kULVoFSt@R+%Mxf0JwGi&*;ALl7#91UDY8BQguG2n>eW>kR;kueB zVL4$_opnmh5{2~6zMySHgyKO8+rVTVA!^rK82;pXc=KSpBox%9auD|9M0kg?R0FQP zpGYx|UQAav+l+{D_S3e}%6NCz5{LJ=v)|CT2QTg^tdq$r9{f3~m-(r4Od!qJtt)q` zHA()yUB3)PAKLXi!1{rzA|iYj5^ik&x0Ia#Iy+yvP~1=UN4`~-5K z5y2vCd|;CPpIUbO9)+R^N-@|Vk2n@G_4uLvMWpCKu<=Ky#)K;y`VVrzz{RDt?sM7W z1+;92H*Pf07J9k25*&Z(sf}FaJJgR*+SC>B-a>s{ZoUQ27r2dY{B(}!;x>=&l!tn{ zv?IXw`vx&j2R7OCj~`FIVJzA+-SVwZIm0&*a;#(7zt7lDY0B2qUZ{58s^L+(cVzR9 zwS{7wm}8@vZm3v?M>T@)8uCUF64y7$UR3eppA5#4Yv!DK=niS#%QOC{e~^IY248Ap zof1u+P54OgDJUQF{_32gI85Q9^1^Z?XC_AzwYz2GNtuh0j6mdClG&^~<0#@=3fJK* zeo9x5%{@w-D!tL<@FNMnptfxKO7?Qrfc7z}xJH5h@;?%6CuB+POt(m6mo3{JRf1rz zQ|jPP3=x2V`DxL~zo^?w1jM+yDhnC!;?j&k&1W!U|5UB7k=WDJ9zn7cPc76LRhg9h z1(sYE{V^pJFI+i1{puSjHB@WV{yOaWmm$`YGzw6n{5ooST_Z{&1e zbC<=2DSIFYv#5B?u^TgsMS0Pkjm?BkR3)Dr7E{}$Ed8zMo(OG6Y z85qkgaq1g7a=#cZ)rct`MXQZ@m|n^pPiDrd26v~inLC9Rj=P-~t)g*Zp~nzmMzlGL=FtXdb-KA5nD$qTzYhXLJv&NaZ;!Pw>OlMeo1z=`0(G$1S-1VNo2KLt$YY zc-B%fBm%>TUy6fZ?N2u`jF?}3!IF{lIm}0wp$FgX=zBRxQcbFQ&Y`kFYrvN9G2uti)7N*q*(!fH!qt#O zUWdNB7f@qtEAD=6RDx7_9nHYCMFnf&cr@BeLV*8cg{F4+FuKhIs} z&s+y2$hS%1a?Up)awSNf|;}?C)!@mK%qiZa0Sf}mk3y)?7 zIO2B&a{Ig!HbNd4FXp@!A9$Ym;vHZIw{z(uKTdqV8w5_-OuSvWxoJF)r8U^C?D?FL zoVN05yR`WxZp0z>WsWmu`@5yzF<)!3%yHs)-~<2s8F1(9C1UHB*itQ)wC1f&dW{!v zXVGrB1mix65|x@?mg_b%a1k>$KtFnDT6?V@pf5M8j4zhuEiy7&{#rP_EbS3@B^+9` zzYdw(p2li#z;uy_*c-n(YCCxFZk(XG<>;;aOqjhw z4#tkg{p}6SAC}HWl;A*9yGidVWzE?ugTvUPtDn7p1Tcc! z_)no~Z+PcTi)bEFm;DD`PX69Y%n)xpSyl?A{A8rjEfX2vIjPfMW( zPU`)+$@NM1CGfU*TYgdR5VIw7#JthJU8()Hau8{3_)&XZrorXuQTbn5f6Kho{6zLu zc6DIqdi!}58b^YssQH_c`;bcLR@>eo^hMCu+h5HmC$`J;`a^Ddw+&chS<~(v~1=7s{TCW&h89yPT>C_;hIO0`CzLDRVWT*8k?mo zIGu7J_!81iNzQnA)6^q0fpe6x%At3EYS2FE+{~iO z-Tg{l5&xS7BtqtB1Ydq1+-{+PkuuTc^KX~r+i$Mc_!sNI53>jh7{a2K$n><7Sqfuz zzX88}FlXmSRF3NVS$CfRT~Q%zGIy>?dmhS-f{*@5dru^n?6KmbniYiYMYb+K?$hsb zQ1DCn%l#kwbfq7+im_2c**)K7_F z%KK_7%3=_h1%J+Bo-#aqcN?E$rq#j>(Jh2uG{{*vf0bI0{rj7!BV9z>!O#0}XqC=) zU8`eZe~9T{LuGhw8Zs@Y%Gj_8+KcUxJf*JW!pPL118QMWD$b(?opz|7+EcwWh>XT+ z|F2i}mU-vL;e(~HrJsif*ZSXl+C2RmgN#z)lRJrutIr|^^#u2U4E_yfVmAj(CS}8` z9XFeeIqmEc|6017D(1EWQ#U1?C!KS%pKMIqJTc>@IO7~KZnN6Uh96ei|AtuKW(F(& zmVyrL5IQ})Bok38@C?)%i1YaAb1Y-lbZ{LA_nqa3FZ)(Pt|Te;+f0-Ih6CYQ1L)|4 zsUO)0y_Pc%cI0a@wUn~_i`?4Kj9iwXVHH@*^wG11sPez*nSzy(O8%#J?GYA5U&aPG z03nz6(Mgka675Y`0CyWVMJnB5+d$^9W^xkv&u5pvaAh#9bGEd&&Z`l?y!l;!1|$)< zH7QMkoaW+&l`tr|q%z+a{AD7lkDi?;4{3-?RAB1I0C*39NC((2(g^T>Gi z-NZ3u!K0{+>F(FvBEs{OR^X5CCIJy^zql#s<9c$Cj*1eHzjjxTPrK|gGtcm(eUFK{ zfvm^kN`hE`^bk#o3+0B&HRhe~^&gc;3d%V(ys_iFXPpj2m3H?Xe^Ix6{m*%>4i5YH zyLLpnv1+u(u2-wL+NRUUanyn)WWy!ocJG^8;PLP;lR?w$2lCWK`&Jc8kLN0>4j8#~7q=R7@ zmF1`0PY+3epBM2|2C`;ph11>7Hm0Lga~Ve1?jyT_JPBqV+}fDo`7Tc4_!D`RJjroIQP(HlK=rrWE1SAL{hfcWt(ZC%oIi)KldC?!8xk)&uRix|%y$ z+(UM()zBg;$e4bwZGXdF`7f7~&{?=*cC`U&dg|Mbxi<>_sb`q=p%F*F^Rl$TYjN** z<=_(+atCRsM}l_RsvG{H&eokujmA}L(=ZoE+2I=}h?sSDv%t8vMl`>gOIM4iR~(3L z#+HZ2n8iBFAJrf29CWqAO?fb3mj|bMJ=vA+aXxda{U;9|+a5sV@Y(H_Xz0cgt6;w9 z!q2r|H5GK~tj%>E!+w7R&PCbL-TV|LKLT=E%A7ak^#{A?CZ1yOX@(`6j&~J$ZUm$k z$UQ}vU?Tm7Kfq)@nS}K{40lwCi`Vd ztrV{RH~S3w_X(|soB$vI!u8X?M~I)`x{zylaUZ1-8mjSNnzN7+fF$WW7ST>QdRptB znerQ0g|-w0_pVconL%zJN_$?Yf3H2A8ArT3&jv+$AO~jt-k2>9o_Nk*M8g1bOOzmZ zXsI*qKHUS_}tsuWI57@w&vX`W8j==4h{T3s0dmLtZbDVJ20hL5CShYO#` zN>&QB>Ylvo!++=}DhB_|-Y_%tilp0(kmRH=TRa6-n3 z&3&(_{o?dDR)YFV&SD(eDpVCfJatMQhPjA9Ng9K_=dn`Uq5FiuI%=~hlD&$zng{it z?AFuL{oWL=3PpF=PG5Nv@TxBxz0G8!I1UeP^s^9GlYD-*DQI^aje%pfO&ufV7;`p` zvzTeQVnq}k_JwUi4B_x&Mu+X=1T&ay-ZUFBF^L3Wnzkdn9a$CY#Nzc(1Ri(h+{=>Z znhlzJ9kmVnx8K9|1UdsO<+P^Q)ufM{z79MzTr2;L8HOxJ1vWT`*Z@JS1;xMgs&D~r z6>H~p|ADQtT_Tf+=tV#t3QNxS5-_|`kAqTQnesTN?{3A;1bHnp0Lm(W*T<~$FJ??w zm*SD#H`M<`mD!bGO3S}p!=NCTSN?hMD@^;3Wy_DBlCx`^+nb%SX8no;uC}K*w}_p| zY@23F;0?_X-K)Rblg>e2fgA1Y=se{Y<_^`lED3iM(!^7S0lO^kvPuY@NoTBMgMc#V zW;xDa;?+^Wr@rgN_b`Tz%k;$K#`f6UWF5;8;WC28gxz<6Efb`Qhyx|ihRoGlhz3U{ z@>)uf#Jep&jeSP6C)unrq>RmF5du@$)@P2wHKWbAZCxm3nr?u^&ul%sVO3~bBLe2X z|Jt&>G(hyLZ%N%)LD&?f{^<`RYa5)s;fTkq5yCAFVYODQL@c`v@%moWMK&8DHOuc$ zpR(W*4S@m+!qC=wtEbwOFR_Uk&8NTd4``moH8$OA#+#qpo7+ZlpT=iI$5(ytxPFb# zn06-<%$+>=3R6u>OutYB&{9@Z2s9(z`QQ?f(Rtf_7+expN`Tm$M(N(kS3@#91ikSu4`CzDo>k3uB2}gFQ)zxKr{01kF{FZ75NwRq>R1TZxtofL^?mqT7EUOoZ*ayQ? z&Q_@2X|@h;siQJQi*@+h*(j&CPO~3S0_6#8)~Uu(2SAgZF{2pQtR^m^_F^ZbG6(>rt&MkOn8Wwv_q_D z$c~Tv{GF?G)3h~luK;|@8~XVHRC(dicYP>M_QY&f%=DWhun!6U8f6& zLKLlsPR2qZ$F7d!tR#e_M@{EQ;W^1p9GBD%4c&r#O(Wco@AtwR{p=i|oIO9lVo6Pzom8beU%o^X z5B>X!bD3zh)(f4I8I6TEo@3FREh{G=VehbbOmqLf+@_?eRPK+nAlk?Jp#tOn7yDRZ zr}>#^RrWc2^G$n8RRFo!%5YR+?TJ%%aT1?AoK^0---Bs$Bvv^_p`=a%QyxxhJP#w7$U4<0mzam~GbHW& zMZqJNlPn+)&Q}dRacumR>%aQuj(b<7E%?DKRc~TM;$vA zu1(hB0uK%djWC)fAE#-vW?)2aVAi@aSamVAIQ+Bb(3gN_t~m=$XC~?wI+Tm^-Y8dV z_=*Ie*k7&H*^KUcOrRxn36&CsFH1KuGTCpC#H$!niziY*Rh6RQ0qafia^B|YAD5hZ z`+^ybTE2{Y-+$G|cE&)Oys%!g#~*Ibw+}HS?4v6~e>q!kOy6<;ER^$EMSV3y$)BNC%leh(e$5+BUmKoO zy793uun*9J*YuX63>pU>tG>z0ZJFZ*TRKxLA*so)u?ufflOcA@_s|A(2~tg?)`m0w z@Dje`*Ne1KGPN;tzORHtHoQXbhP^{H7%qp@zygGiS)yc5MXENUq=)RO8?L+GgbU#{ zT-hr&*ItxU-)%}wtp+wW@^Pi%lMZpVstM^HuIMnQj|T=C&yt zKD}IX7C|1nhf*#vI6F{bv(dbBN-O#_V5Nmt)fg!5) z6SXYW919rx1SJ5jX9de>Y8`n3Jj`qQJDN|of8MLn^!RR%Kc7@&J+8wVGOrPwh^E~~ zF@!Is(JeNh53UQPHM4Jkg7U_)l>nTeciJL+D8Rd<{p#^L<9@(nMFYjhh#*hY024)0R6T5U6#t>8p7kP834ls4mAeTc_3#tv zi}(ft3mz%vX5~HzdqVdNUfqzX4JN}jv?#84hYo!8dz7_wCBQOuX=EG`#(~P|E8Arl zKqG0JYK>Xp_T5;8GZ1tx;PNg?-BRC$5~)~*B2XXeGsNKcY767sq{?^DmoIvW8(`XZ z#heedXEZWR89#8iZ35nMBGERJhK&L-S|cyn>z0u;YtvFoMTSzU_2^nbeO4$b97r2# z@emklq*QIE4Gj4Azv|xm5w7of9KOpcD_W3*AV~Cx9=#HoSBb7~I$}sj- z+AU;=`S8~Ic7=jQg-f}9ojmX>0)b98Mn{&Y{}5yw$}gUNKjWU}HaAnUYJV0Hz?L^z zK%cHh<_iJX0r&S*B1s+v`xP3-FJVA?!k@RO+Dp6AbibH*H`A~6x;GfHHp01dC@F#9 ziKGO+&_yUbZ89`Zx8ZvzJ3j_A}Tm2dz#qQk)Y~VKgiee*-FPR6~ z{G@5mk7iUaP7yLIS_X_A>EVFD6u)TM z`N-$l{6At@zYB>r?u{aP!mPhXPe>2xi-*#!hoWrjfrZT^v7h<;L^ssGo!9r+R%KF1))PKCS*9(z}*qlXUDqFnh_&7m2^7%ljbov(Y^V zkuu{MyT))Xd8IJv3+ZxF_9MA zUm9FMaEnygaorXTeS32-O~q?H@UA5SB6PRX4%l09M4#z^m$>>iF?Pb$ta5hkCF*Yf z^~MgU8*SSc@?h65i*+UN`wA8UQFF6P$b?%trrHCv;)O)SMUR<;xXvMfoNMP|L>^ub z+?)MlAbr8ZXf2?6a%@;gbk8XC!d(4`7*MN4+Bk@cI6?`y{?O2Dv#_e5$O?rr_E6o7 zGB7CEjysW$e)qTB0)kJp6FzL?&l{T??bEebjYtuJ$4rh&jhVoms+M6SFP8#Sy;Mo$ z^PDPpU())j6KSW>+T&Ncb}kQ}{oqeJqf!1r9faf&6e-LN>kYMyEd0#@?VP#F=qUWf zN&14(e38TV=qH3x7p6+=C1$T_NUS~#)gwH*+lRO2To?>qdaX>yPAO)iwM@$kSMTBL zJGg6GZM3lcgxP0~o4=$G+o|5^B>R${7Y^$((9BBz9( zm-qK8v6`1VLNn}lN}#Ad;4?H93Y=*2Wq-+cd6>@AqG%&>P3edk4!{AFs$Iwd@`cMo z`fn7`BBdmRpM_Mm5b;7t91sVfEVvTHgmvqtHRl@U=FACUZxCPhYj&X6Y6lc2Dv|wJ zgKi#wEm)UpSU@OL?O}@mpywHTg{<44dl=aQ)8l)4(EN51-i6?mh0KM7bD}tbXL0(fK1qYc74Go)MZcSxJ;bj@8;cUNQn~bkkV{|N@D|aKFyb^@eCrpe z5}lGL5H7hQWRq>#qFC`pY-MtCg@%+|-F@b@Asxv5F2EunKZNu$2x+O_usTGH?0M%3 zP?3Uy0Kp!#s2n>j2SjGfW$5Qj9Szu}v%lVn64EFq1#V_=gJ)$kQxF z?_I-xG`N34=I+cnbK5@Qf4HS)Y(JP|g-&?zb`KYqJCl(~YOH&vbZ)DocVX;Iz{d0o z#AT3#TrWezm>>)fSLwct9Ni>t`IxP|lR6-fY(;jia!iv^DsaMc)43Hl*u5Ei znre3vB#}mrGd^2vpwUOQ1z!ppnH{A$w=`9EFJx<97{{%Ip&y9(!3|yRr&kJetKS8V zs4uu!NeBy#LhjaVDzk7$30=DiPb#6&HM8{CJ1!J`j8_>2&dB;2NpE2qO6V~J{&6ZZr-3Pd;_0m~=*f^Is>Qs1Y zt3#%b3#MMuJtK4U?IQ(Rnz^1N2pk#*=DTp@`i#X#fp+%~Xwec2 zb%NvJK*7roRXDO}k?WcA7TVI9gz6r}jk5j)bkTITyZ<7cb-|i!SKXc!6O3_jW(q zw05UX=@1>_huXBU@E^(cV$>FSJ2&HqS{AYY%_C;{ZG3H!f|}g=_HI`su1rrMG$qJs zI75Fyd|lNX<7NviOm}s^y@@L3l3pQ7>anB@@Ud{Nos@d+oT?goDPNjESQVlY3GVce;-mevWPfNIU za__q90bBT!(zGg#+OL`qg18{+sT#!nP<(g%++)%7RJxry`RwXR3L6KpEx$M8og;AJ z#+M)M><&w^a^(IWpn-lgc56ntDderSHzul zbMb1&zYE@ZYZl;{!UryX1vK7QI8L4{V@%~&PrSrP0?7Nrms&t6MwkVx5-97|^YF_U z@J;|ko!h6tR7v8hzp&hbplqTWPnm2<&FDE9_%zZ^JC&l^@JD=itV`g{ck3Zae~ZE;l>gR~eE7#x zMg8A5rKitdX+(NI(#b8zaYI0GzUvaixi$)$DD?tuP=Czu^wf`k2mL|n;xby`HSNZ5 z38{K-fQ$OPmmd2$5pTrdWpy5{!qCmV3qzNOLT@Q8Ch%qh-j^rFlL(oc#%qNOu zdZ@nzF6gOhMjGA;{)C4lg9obWn>*vTl%97RFPl3a%^Bwk#F*5LG%PtLq8{tFsPWpY z**5vn_o4#n(hpr~CckJv%vX+Dco#jt$<{K%0G|Qp@IeeE!-^goqv;QZ*xXNerm@{H zA%pe3tjz86L=)uQ~IuK*$>k4)$BNm8Cmcu^brAiMpD{&ut$}_ok|QKxL)* zqyjfP9p|)iHzUtUhFq)J%6rBve5|H5rMUB9KT6a?GP8T2shH{)*sA6&` z&v^QGQze@MaJBdRE}ra`5c;P$w3$?qyY_9p|>)&5G>p(x$fZv=G5ooKIrX@AL;=E~dk+U)g|!n^Lu2{O51 zP;ryu)7|%|gN+>YQUQRaJ$hOwW>Ad?dx3e9YeO7yUB)7NG|$f~D17k=_LcQBb3v~! zAwIH5GbNh|R9vg?6H%s654v9JN~arA5mfp!TMdx6MXmGSA(hDtDcz5oC{6tp&S+#k zUT`v}XzBY*{K8x;h$`uBzLZ>hS=LjJ$Jy??MHb$b*de z?g#$?W|!Uz)7cqk3jAt7d96WtV5dodapJKcF{k72L~j#hXq1k>+bqd0@(_tS()3=I2A%oHfNU2h{ev34%$S*#dSL$^6NkQw$g%MNk(bW}{YL#Fp{h0&a*su$L+(6zTJKA zW;>?6WW<4|4y5Bc_1NgEqp@o0)hMF$BiyL}PbGCT;(kGg z(iiuqy**#)X=2o|v=FkO1kb-N$2zTZ8IW#svx;1t_M&6VmWXm@MTSCy4%MLl_qDj_ z7rS$bq@XF|gR#HGG_kmI=%eoJ?lF$b-iTkmFe|$regRu%-R_-k~FKSBBrCA~}m*T{yqGR4gxf}}=nvKwVSu#@a4bP?=X&+9E) z8Q{*BBrSDHyO-3oj=r6zpl`yup{2W+o6SOlxN*mOX&djCXg|29%)9-Q1;?QWB^0r* zo+p2rTT$c$80*^JJTXy)wZJJ$&+H;r=}B>y$2IjkKAh$-oMBhT=gaSc+wynF@pkho ziWZ*J7{#Fy0Wx+ftxjK=J+w)0Z%cDQ*U^$i>fG#%UVU0Lk+AWztiNBN>|5BJ4_1p9 zYRg40F?v-=1(yLBxYKtB&>HXPMc{zD*Gr@2)u{(|q*2~zB`EI8PiA&lrW%oOzD+st z-T($!PaPw>Hs-&3@pV(eCkCcMdtpLErbfgY2lQqZsV0&rYHX5^?F%$CHk~&$Z}mTk z(YVxPifeRB7fL6F5{4cihmcTP1NS)&m=a|Ra+UcrmGqg<3SGpcg;w|EN|Xu9{TsiQR0X+ z>r3Isxmiu-%wlRZsTm#6LSR|k3tyLRPu@~_sP!M7%{{|Xnov)5j3Ic zQ1DUhtHV(#(WPlGW+`*cYpkq4(#+-o_3vT3Lrqow6Pgb)Fm2vy`Qpcwzn5PLDSFag zZzDgq3|)2>aZ3~Sh$>)tUsWjDPsxsgi{IYPW)4Uprqd8Dxwf?~ui!mW3+aK;F@||+ zdYD(fLqCrli}ouklvn5(?)ovl{;P!h_N5~86Jj6OI7{s7;p@XK28^~3e2!gHL;gwz z$t+OrNob0F0zF~wRX-ikoVDAiK0fRn^Xm3!4h!IsOtw!KCiYA^8m%PZ?7Ln5`iP{Q zGgHoED_PEVuV5{BhvQF(vcy!%f5DjKg8s;NOXsF3%+YCp)MVwB_9@FKv3U z#S=RzuZUaxfU^{9J@hmDnV zA?uMDLlw=FEV8;~ck2!HxR*oI5x+lF*#*;PgfvaJ1j}d%|Dj=MWvK8}d4pCJ(`!tw z)HB~qI`~1|5ficW-g5}v>0#T(|9xA0N%RxP(GSM+>2*{0nqZ`c+_9^xg8>=u?_p-X z3HI28;#N6$Zk_BQkG~so!aP{Z_y}oEbs(#2THpBTeb9Dw_s%=11z9b0r$S9yS!?;d zsu|f27V*pe=Z-xVbEI>MX$I)|*DB6Y?F&}XmF*h0e;0uU!JjmnC&63#i=u=f&vZ`w z?!N^4 z#oJM6xn`;uX7`%QWzZy3dpq~LomtJkvNXnz9=X#X^aRd_5i}|bNxXu-y1LI{;{r~hyM-t zpE8UcIkj(lXRIE7I((OOR_8A>bU(zR>tN*|X-{Z}EPU&i^$XN=iicj9z3Q5}7UxpB zDcbU*a>{F>xuop{PUiEWg?~>7>T^2MOy9u{ZOr%7|?k7!WWsdR-9*UDyFyI*TDcqJu$cj9*v?5nAtkw|`m3>OY0;=a6MXzZB z336@O)bB{!b2;PJo-_>=9ETYL*F_cyS+5KVi9n2Ac7hKeZssS4&X3de=DC1>=h`!D z_B;db>hHgr-m2dY$h(d00o!uURdRjr65~fFd}(LscuusSSElhoYe&}7UTll|gjJ8s z!4Ni59m6Ci}itfu#*k4TatR;%Y_gjR0ryq$WT z@>fiB*!$&&gFH2Fo)+=HJ;t;KNk=|yCS^g{n*Pm^XT+cqbmN**>LZi&Gi~>(1Skp& z?Y6sB6EMxwmR#;@d2IbJ^ZTBRRHyyl%NvfDpjwmsh=ev%9nfTo{pB8&pS0<=%Jj}a zpuW`mFkpf#tV5Gb5xpbtvxX=?Zj`36Io5hP0vy@V06u7W$eo8RO@P&D8yBO&!g}^9TZRl zK)a+))@YNos+MUkhADEqxeJflSQi$zZwg0k9pj}Q`(ON$73OzlyD$t1AbbL^ubC!+ zfhN#N-?FE)I-E@-tb;n@?3^`69(hq}2j z3-}I%@Hs816)CXMuZhATQq0Uq&xt7iIxIx{794*|p7VY~<5Q}w*+@C(5`;u<%)VAk z5K24Pp4bnX+>L2TK*j<99Mx>ke>b@8W{uJ_LS^{U`{F=~0qz?-%z#~eK!APIit(_r2eNNB`dHO=4bx6a`_ zd@bw!oOYy=PyH1?ZOH0~tiN8%Q7wd_9RAfvE<%+G;N5()kRT+`$q6fu5P+1QYD$nz z;oxe%i96$(H~dCE`)_N&P~Y-!I?~CqUS=%&^$Dp`3TWQ9JSSxMHg1$#L!Bh)hK#?K z^;ixySaob%Hq0BcYy4=eGI^)z*8&a}&{5yJ);%3gI4YwLh+$K?s7?7ixj%c&`M7>j zytd_zOd4Bo8Xlt7n<@sWk%Uf-k}_Q;3~zO0LNus{N@-xc?nbT(iyptDPbPG@om@MT z7l%kIgGbAv)GAxT^(t+7vi!E1q{f}jG zGJ2ET7mklm5=Wex9zjn&Iucm76Gtief$;Bb7{`46b|{t`_N;)rEP2o98%vC{z`Fwn z&`a)}%H}Eq4D~eJyT;%+J;`eHW!gLDS0o+h=rbCn=Sx!y`B8F^@>O8C5H1eSN&O1d z4NNSW~|HEIs#juwgyU?N=H7QlrAC{nI>WL1OGfJ7 zDOO{8HNVJxe0T2`pNgkPU4|aoivQ$PY;)Z{$=h0H*~S7fGHc{KQSa})7LzJi9^vfyYa7vF$Y3=i5I$y?e-JdZVg2E4~ynq;l>*kK@nj+A9 z2bEugce~Lol^wvA{~FJ9TT9KcuAKol?Y}T)5%GJ8I~a-`&ij(S4B0^1o`R_ zAnd)eK`HL`!8VWzQmR`2fnk*?bcW^XlZ_#x{Bcj0Ld296w`ZP0@N&+^e%{i^&S0+&jwS@mE=05AMV6N{k7JZ|<%=lSAgfG=(2YHk8 z*yE2F2|!9Sbz5aF#rQ1+#}vk-(G zP3^?TO!lzwx$fbce(H?sVw$`p7lo&Qye(GFke2Uc4F6R;MTd?J^)HD;c;@qqT)2JT zDocmI0lj~%%x5p2uqT~H_ewps=G~b0bpE8<4la$7ObIb75@E^zK+UJ>J-3R4{ht}{ zy=;w-9hDx^X$U4f<#sN~zTBI=PXefHYUW5>oAc_} zmOv=IXX{qb=B>tvFRD4xYdWXzz1MupVi}zhXTX6&x!%}I$~7R%#w%BWhqJ`b8W>dl z*TS0(yO^PZbQ(mOH=L^J{WD&Ce-q~`JNo|goP0~mMYXelpUS02(w;epi>oFE$Q(M> zoUj4C&=9LVkJt71;i!VqAnkWg48N$cGRZ!YTzYe6w5d+XJe=Dk?If6A$#@8!iU8I( zax@=)5ei+T%5|YldJGzw`2%?@EwVb_q9f&}{UVjhsZX^Dvr;sx+Q+q{=I}-{C<-pi zTIWn^6tb6>qCxaC5fC1HsFNbrZaiznrH*U77L5T-*rn$5kH; zogJ}0$ILyVM0$TD>&zM0+2^(~j!}hiPwX&j1xWR2mba@O~E%NOL(RS+{{z{2TYL&|eVMHkM zNa?|ch~+w%eXk|2v;RNiB%~{2FovM$>b5ZNJ7QQ}rx=l;pvOZ@vwmFJ^ zxR!ytBLu{TFc2-9skjT#pHd%ZH6S9uEsLD$U5jq2vHp9$;1wb30bsLQ!W8l`+UIh1 zpI||A9@~MpCVxs~V+lFU=>-k(?z~*-O~imIeANhh7D8?4!1{Il*-XN(0(!`DdiJgL zSI5SQVqD~Ta!7oQ4pd*rFM0?@Ts=-aHOaL0Ivzgx;_z@ohP<8ioD6^^S-#v#5<2Jp z+uvi;>DawqntWZh$D{9ir%lv0x3uum;Kxc~oZ5b&Q0=4Gz2Vg-FtiP~b9$y?wC=xi z@UqU&gEGJJ?|qThtTqi5#RJjU2^Ynd7 zeinr%24s`mUv9-Z`s$_P38OE^;~%fj{YSu`YvwjbasK!wy8Wh1cC{{PSovDK zYC)~t=z&HtM5!h@w*Q;8Lx%C)x$;cR*7n8m~90ECYE5x`p?}}Q>F1=hYkpX{T*Kc+F=*6WNA{_6d7zH z=r&nbz7?Iq)OU*jw*1cr83>oQubjbCF2Gh$nI~IYtU;x^RHOliJVqjQp9~z@>y9c8kf>hr!k`B+QsG@8qhW zyzIP+)}S`2xQuo@Ki?c<uY`_O<>u>&$V_T04N&v7c?o+8nKL@o+wj>%wWu!}A z5@n8aqSCsSeU~(MZ-K#QiTUlFJ@}Z(U2Mtp3y{ipU!*7xECI@52bePDyS){;cE{JC1>J1%d~(R zG?&|QoKoB)LPe!;r^c-v0>d5K5zuo+shzdOg&Rwj7(_fBg0q7qiBbdw4DMCX;G@on z>A*1e{Bpgd-^?hY5BTKzX~#LCp8Ssnbo?+!r~c&)*J1&bB_i#oO}PN-uPoY(%tK6L zuAd9?NU?I|&#cQ&f}yhrI|Oj5THh$|{YsGPlfUtEY{12M*FQ##?9Lp^WYIi@bB{yI*K_ip*lABa~r z8M(X=liLb(Umm;y7rn*3- z)sdq#%|qglW<%hT=Tf+jFE_?&7e&T>YafHG{W}*@C!(5Y+bwpY=^_h ziV|cA$SmH+(>zz@+2PYmaf*k5idXPm3(uY?&Fcc3+02Io5ysuCf>KJga&rPw@&LQn zbU0FSkIvMpDQ zp%jUchultt%)K!in2oxa{lRbrC=LL?Z6w&joDhI+Wb+95R}@qc0BS@4IUaIFC8#kN zewqOQSHywhwsXZC(BMre0@H`bXc1VB$*y=4lBWZ`!u`J*yrJ{>E12KC{_sGwO(~Ri zg#It9bJEi6MI4~i5@4DbBS?Hj6s!MrDs=CAmSvc^IrAOwSPXNrmsfabcOT;zdk-2Z`L zXDTqK!5&o~H{{M;x0{fu*Et7Og2$(M zEZ!!IWhIKp+gSk;9F2W)B>yMkoDRQvhys$>$tRq~kL?Ki+$@S|ND7|6`^H4lky8|V zZ0d$&1W7r;2k83{gODGI8(=pEx!&1(w1L9Vs7F`8_9U~Nr zm5~Qs_-C|feJ{9qa3!%=a3^}?c@l3J6jHSF!>hSU3yWDFj+&7u>??kR?|Wg^3qRg4 zxWs`y_T37aHzi8KdErV@0HjXXER-t+&@A7{q=;F^JfLUncZSO=bJ1Lvzm-@VMX#ujJ0Ef#f0h(J-i%f9W-+FJ-_vVVSpQo@(JgYpF? zxJEFk*H(_H@wW=8!A!owF&nNQvjwSzf?z7A6m~@BQzBkS4kqeWMr(vf&dn1%48R*e zQ7nk{sWK9L^f{Qwq_oT0uz~#VozZ~TBOZH>uLm=fo@*;hS3*FE2j72VR(BG?o&$~p z%B7VMOfL18$!lOL#yy$JZIb69_=>ufBgZ_aJ4XY)*B3pO;UV#SL@*W}VFT0DUN`@x z{Fx=W*u)IG&;U8h;Oq|kH?om_Ft z?Ig^@vB+iJtNsHBH@gHk?t^QLq9TQIf|y+7lB>!A Date: Sat, 4 Jun 2016 19:21:46 +1200 Subject: [PATCH 0372/1679] Image size change --- Images/SwiftAlgorithm-1024-transp.png | Bin 46580 -> 0 bytes Images/SwiftAlgorithm-410-transp.png | Bin 0 -> 36570 bytes README.markdown | 2 +- 3 files changed, 1 insertion(+), 1 deletion(-) delete mode 100644 Images/SwiftAlgorithm-1024-transp.png create mode 100644 Images/SwiftAlgorithm-410-transp.png diff --git a/Images/SwiftAlgorithm-1024-transp.png b/Images/SwiftAlgorithm-1024-transp.png deleted file mode 100644 index 5b903741432beb9d0a8478329873546c10598f05..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 46580 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

fet^qv3evI}+`Styw(o`*8SH*4kp645(LNy*8 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 eGX>gLf&T}|G+>=F>2O8>0000OMC19 literal 0 HcmV?d00001 diff --git a/README.markdown b/README.markdown index b6a37da08..2e6bbb94c 100644 --- a/README.markdown +++ b/README.markdown @@ -1,4 +1,4 @@ -![Swift Algorithm Club](https://raw.githubusercontent.com/chris-pilcher/swift-algorithm-club/logo/Images/SwiftAlgorithm-1024-transp.png) +![Swift Algorithm Club](https://raw.githubusercontent.com/chris-pilcher/swift-algorithm-club/logo/Images/SwiftAlgorithm-410-transp.png) # Welcome to the Swift Algorithm Club! From c81cd526c30e67bdd6c724cd82af40b9fb0b555b Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Sat, 4 Jun 2016 19:24:05 +1200 Subject: [PATCH 0373/1679] Pointing logo to raywenderlich repository --- README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.markdown b/README.markdown index 2e6bbb94c..4d88ebdb0 100644 --- a/README.markdown +++ b/README.markdown @@ -1,4 +1,4 @@ -![Swift Algorithm Club](https://raw.githubusercontent.com/chris-pilcher/swift-algorithm-club/logo/Images/SwiftAlgorithm-410-transp.png) +![Swift Algorithm Club](https://raw.githubusercontent.com/raywenderlich/swift-algorithm-club/logo/Images/SwiftAlgorithm-410-transp.png) # Welcome to the Swift Algorithm Club! From 4329e3b8ab9d1b3a3a3c8ee9b52ac3006b1884c2 Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Sat, 4 Jun 2016 19:29:09 +1200 Subject: [PATCH 0374/1679] Relative logo image --- README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.markdown b/README.markdown index 4d88ebdb0..d13775410 100644 --- a/README.markdown +++ b/README.markdown @@ -1,4 +1,4 @@ -![Swift Algorithm Club](https://raw.githubusercontent.com/raywenderlich/swift-algorithm-club/logo/Images/SwiftAlgorithm-410-transp.png) +![Swift Algorithm Club](/Images/SwiftAlgorithm-410-transp.png) # Welcome to the Swift Algorithm Club! From ed59ea4cac70d6c65cb4e6b225cde01b355ef51c Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Sun, 5 Jun 2016 22:11:28 +1200 Subject: [PATCH 0375/1679] Moved under construction pages to a different area --- How to Contribute.markdown | 2 +- README.markdown | 6 ++---- Under Construction.markdown | 19 +++++++++++++++++++ 3 files changed, 22 insertions(+), 5 deletions(-) create mode 100644 Under Construction.markdown diff --git a/How to Contribute.markdown b/How to Contribute.markdown index 1e2f61b41..dc1562327 100644 --- a/How to Contribute.markdown +++ b/How to Contribute.markdown @@ -6,7 +6,7 @@ Want to help out with the Swift Algorithm Club? Great! Take a look at the [list](README.markdown). Any algorithms or data structures that don't have a link yet are up for grabs. -Things marked with :construction: need work. +Algorithms in the [Under construction](Under Construction.markdown) area are being worked on. Suggestions and feedback is welcome! New algorithms and data structures are always welcome (even if they aren't on the list). diff --git a/README.markdown b/README.markdown index d13775410..355e0c940 100644 --- a/README.markdown +++ b/README.markdown @@ -26,6 +26,8 @@ This is a work in progress. More algorithms will be added soon. :-) [How to contribute](How to Contribute.markdown). Report an issue to leave feedback, or submit a pull request. +[Under construction](Under Construction.markdown). Algorithms that are under construction. + ## Where to start? If you're new to algorithms and data structures, here are a few good ones to start out with: @@ -74,7 +76,6 @@ Fast sorts: Special-purpose sorts: -- [Bucket Sort](Bucket Sort/) :construction: - [Counting Sort](Counting Sort/) - Radix Sort - [Topological Sort](Topological Sort/) @@ -131,7 +132,6 @@ Most of the time using just the built-in `Array`, `Dictionary`, and `Set` types - [Queue](Queue/). First-in, first-out! - [Deque](Deque/). A double-ended queue. - [Priority Queue](Priority Queue). A queue where the most important element is always at the front. -- [Bounded Priority Queue](Bounded Priority Queue). A queue that is bounded to have a limited number of elements. :construction: - [Ring Buffer](Ring Buffer/). Also known as a circular buffer. An array of a certain size that conceptually wraps around back to the beginning. ### Lists @@ -144,7 +144,6 @@ Most of the time using just the built-in `Array`, `Dictionary`, and `Set` types - [Tree](Tree/). A general-purpose tree structure. - [Binary Tree](Binary Tree/). A tree where each node has at most two children. - [Binary Search Tree (BST)](Binary Search Tree/). A binary tree that orders its nodes in a way that allows for fast queries. -- [AVL Tree](AVL Tree/). A binary search tree that balances itself using rotations. :construction: - Red-Black Tree - Splay Tree - Threaded Binary Tree @@ -154,7 +153,6 @@ Most of the time using just the built-in `Array`, `Dictionary`, and `Set` types - Fibonacci Heap - Trie - B-Tree -- [Radix Tree](Radix Tree/) :construction: ### Hashing diff --git a/Under Construction.markdown b/Under Construction.markdown new file mode 100644 index 000000000..b7cf7a696 --- /dev/null +++ b/Under Construction.markdown @@ -0,0 +1,19 @@ +# Under Construction :construction: + +Here you'll find algorithms that are under construction. + +**Suggestions and feedback are welcome!** + +Special-purpose sorts: + +- [Bucket Sort](Bucket Sort/) + +### Queues + +- [Bounded Priority Queue](Bounded Priority Queue). A queue that is bounded to have a limited number of elements. + +### Trees + +- [AVL Tree](AVL Tree/). A binary search tree that balances itself using rotations. +- [Radix Tree](Radix Tree/) + From 19edb529452884b9a7e55d0d078ac995f84dcf09 Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Sun, 5 Jun 2016 22:13:13 +1200 Subject: [PATCH 0376/1679] Under construction title --- Under Construction.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Under Construction.markdown b/Under Construction.markdown index b7cf7a696..e5b942950 100644 --- a/Under Construction.markdown +++ b/Under Construction.markdown @@ -1,10 +1,10 @@ # Under Construction :construction: -Here you'll find algorithms that are under construction. +Here you'll find algorithms that are currently under construction. **Suggestions and feedback are welcome!** -Special-purpose sorts: +### Special-purpose sorts: - [Bucket Sort](Bucket Sort/) From d0ebabdabc8d51932de73458a4247baeb19c96ba Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Sun, 5 Jun 2016 22:13:51 +1200 Subject: [PATCH 0377/1679] Under construction formatting change --- Under Construction.markdown | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Under Construction.markdown b/Under Construction.markdown index e5b942950..0589c5491 100644 --- a/Under Construction.markdown +++ b/Under Construction.markdown @@ -1,8 +1,6 @@ # Under Construction :construction: -Here you'll find algorithms that are currently under construction. - -**Suggestions and feedback are welcome!** +Here you'll find algorithms that are currently under construction. Suggestions and feedback are welcome! ### Special-purpose sorts: From cafb8e1813219ed67ff09986dbeac37a36a80360 Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Sun, 5 Jun 2016 22:14:31 +1200 Subject: [PATCH 0378/1679] Under construction page --- Under Construction.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Under Construction.markdown b/Under Construction.markdown index 0589c5491..f6d2852ea 100644 --- a/Under Construction.markdown +++ b/Under Construction.markdown @@ -1,6 +1,6 @@ # Under Construction :construction: -Here you'll find algorithms that are currently under construction. Suggestions and feedback are welcome! +Here you'll find algorithms that are currently under construction. Suggestions and feedback is welcome! ### Special-purpose sorts: From 475d23cedaee132d536c342045e764e4b3d5ceec Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Sun, 5 Jun 2016 22:40:20 +1200 Subject: [PATCH 0379/1679] Update Under Construction.markdown Added minimum edit distance link --- Under Construction.markdown | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Under Construction.markdown b/Under Construction.markdown index f6d2852ea..63e696f75 100644 --- a/Under Construction.markdown +++ b/Under Construction.markdown @@ -15,3 +15,6 @@ Here you'll find algorithms that are currently under construction. Suggestions a - [AVL Tree](AVL Tree/). A binary search tree that balances itself using rotations. - [Radix Tree](Radix Tree/) +### Miscellaneous + +- [Minimum Edit Distance](Minimum Edit Distance/). Measure the similarity of two strings by counting the number of operations required to transform one string into the other. From c6e6de525fa971e9864aba9eb444308712682037 Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Sun, 5 Jun 2016 23:04:55 +1200 Subject: [PATCH 0380/1679] Update Under Construction.markdown Added link for ternary search tree. --- Under Construction.markdown | 1 + 1 file changed, 1 insertion(+) diff --git a/Under Construction.markdown b/Under Construction.markdown index 63e696f75..83d48716b 100644 --- a/Under Construction.markdown +++ b/Under Construction.markdown @@ -13,6 +13,7 @@ Here you'll find algorithms that are currently under construction. Suggestions a ### Trees - [AVL Tree](AVL Tree/). A binary search tree that balances itself using rotations. +- [Ternary Search Tree](Ternary Search Tree/) - [Radix Tree](Radix Tree/) ### Miscellaneous From af47d57057bde6f5850383a9a3ac3ab01e20c6ef Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Sun, 5 Jun 2016 23:54:59 +1200 Subject: [PATCH 0381/1679] Update Under Construction.markdown Added link to Treap --- Under Construction.markdown | 1 + 1 file changed, 1 insertion(+) diff --git a/Under Construction.markdown b/Under Construction.markdown index 83d48716b..f0befb3d9 100644 --- a/Under Construction.markdown +++ b/Under Construction.markdown @@ -19,3 +19,4 @@ Here you'll find algorithms that are currently under construction. Suggestions a ### Miscellaneous - [Minimum Edit Distance](Minimum Edit Distance/). Measure the similarity of two strings by counting the number of operations required to transform one string into the other. +- [Treap](Treap/) From 495303b9c02749766c6536ca54e7429ff1fc5171 Mon Sep 17 00:00:00 2001 From: Andrew McKnight Date: Mon, 30 May 2016 13:22:42 -0400 Subject: [PATCH 0382/1679] refactor Graph implementation - define an abstract class called AbstractGraph, with two concrete implementations: AdjacencyListGraph and AdjacencyMatrixGraph - improve some method naming, especially those dealing with creating (un)directed edges - make a framework target, and add xcodeproj and playground to a workspace to import the framework module so we don't need to duplicate the implementation in the playground - update README to reflect the new implementations/concepts consequently, the APSP implementation is updated to use the refactored Graph implementation, plus: - improvements to doc comments - remove redundant parameter in FloydWarshallResult.recursePathFrom - changed the test case ported from the book to reflect the exact names of the graph vertices --- .../APSP/APSP.playground/Contents.swift | 23 +- .../APSP/APSP.playground/timeline.xctimeline | 4 +- .../APSP/APSP.xcodeproj/project.pbxproj | 86 +++- All-Pairs Shortest Paths/APSP/APSP/APSP.h | 1 - All-Pairs Shortest Paths/APSP/APSP/APSP.swift | 18 +- .../APSP/APSP/FloydWarshall.swift | 58 +-- .../APSP/APSP/Helpers.swift | 1 - All-Pairs Shortest Paths/APSP/APSP/Info.plist | 2 - .../APSP/APSPTests/APSPTests.swift | 91 ++-- Graph/AdjacencyList.swift | 39 -- Graph/AdjacencyMatrix.swift | 75 ---- Graph/Graph.playground/Contents.swift | 45 ++ .../Contents.swift | 87 ---- .../timeline.xctimeline | 6 - .../Contents.swift | 99 ---- .../timeline.xctimeline | 11 - Graph/Graph.playground/contents.xcplayground | 7 +- Graph/Graph.xcodeproj/project.pbxproj | 421 ++++++++++++++++++ .../contents.xcworkspacedata | 4 + .../xcshareddata/xcschemes/Graph.xcscheme | 80 ++++ .../xcschemes/GraphTests.xcscheme | 56 +++ .../contents.xcworkspacedata | 10 + .../xcshareddata/WorkspaceSettings.xcsettings | 8 + Graph/Graph/AdjacencyListGraph.swift | 134 ++++++ Graph/Graph/AdjacencyMatrixGraph.swift | 107 +++++ Graph/Graph/Edge.swift | 60 +++ Graph/Graph/Graph.h | 18 + Graph/Graph/Graph.swift | 59 +++ Graph/Graph/Info.plist | 26 ++ Graph/Graph/Vertex.swift | 47 ++ Graph/GraphTests/GraphTests.swift | 57 +++ Graph/GraphTests/Info.plist | 24 + Graph/README.markdown | 206 +++++---- 33 files changed, 1434 insertions(+), 536 deletions(-) delete mode 100644 Graph/AdjacencyList.swift delete mode 100644 Graph/AdjacencyMatrix.swift create mode 100644 Graph/Graph.playground/Contents.swift delete mode 100644 Graph/Graph.playground/Pages/Adjacency List.xcplaygroundpage/Contents.swift delete mode 100644 Graph/Graph.playground/Pages/Adjacency List.xcplaygroundpage/timeline.xctimeline delete mode 100644 Graph/Graph.playground/Pages/Adjacency Matrix.xcplaygroundpage/Contents.swift delete mode 100644 Graph/Graph.playground/Pages/Adjacency Matrix.xcplaygroundpage/timeline.xctimeline create mode 100644 Graph/Graph.xcodeproj/project.pbxproj create mode 100644 Graph/Graph.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 Graph/Graph.xcodeproj/xcshareddata/xcschemes/Graph.xcscheme create mode 100644 Graph/Graph.xcodeproj/xcshareddata/xcschemes/GraphTests.xcscheme create mode 100644 Graph/Graph.xcworkspace/contents.xcworkspacedata create mode 100644 Graph/Graph.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings create mode 100644 Graph/Graph/AdjacencyListGraph.swift create mode 100644 Graph/Graph/AdjacencyMatrixGraph.swift create mode 100644 Graph/Graph/Edge.swift create mode 100644 Graph/Graph/Graph.h create mode 100644 Graph/Graph/Graph.swift create mode 100644 Graph/Graph/Info.plist create mode 100644 Graph/Graph/Vertex.swift create mode 100644 Graph/GraphTests/GraphTests.swift create mode 100644 Graph/GraphTests/Info.plist diff --git a/All-Pairs Shortest Paths/APSP/APSP.playground/Contents.swift b/All-Pairs Shortest Paths/APSP/APSP.playground/Contents.swift index e14966113..24c27cac8 100644 --- a/All-Pairs Shortest Paths/APSP/APSP.playground/Contents.swift +++ b/All-Pairs Shortest Paths/APSP/APSP.playground/Contents.swift @@ -1,8 +1,9 @@ //: Playground - noun: a place where people can play +import Graph import APSP -var graph = Graph() +var graph = AdjacencyListGraph() let v1 = graph.createVertex("Montreal") let v2 = graph.createVertex("New York") @@ -10,20 +11,20 @@ let v3 = graph.createVertex("Boston") let v4 = graph.createVertex("Portland") let v5 = graph.createVertex("Portsmouth") -graph.connect(v1, to: v2, withWeight: 3) -graph.connect(v1, to: v5, withWeight: -4) -graph.connect(v1, to: v3, withWeight: 8) +graph.addDirectedEdge(v1, to: v2, withWeight: 3) +graph.addDirectedEdge(v1, to: v5, withWeight: -4) +graph.addDirectedEdge(v1, to: v3, withWeight: 8) -graph.connect(v2, to: v4, withWeight: 1) -graph.connect(v2, to: v5, withWeight: 7) +graph.addDirectedEdge(v2, to: v4, withWeight: 1) +graph.addDirectedEdge(v2, to: v5, withWeight: 7) -graph.connect(v3, to: v2, withWeight: 4) +graph.addDirectedEdge(v3, to: v2, withWeight: 4) -graph.connect(v4, to: v1, withWeight: 2) -graph.connect(v4, to: v3, withWeight: -5) +graph.addDirectedEdge(v4, to: v1, withWeight: 2) +graph.addDirectedEdge(v4, to: v3, withWeight: -5) -graph.connect(v5, to: v4, withWeight: 6) +graph.addDirectedEdge(v5, to: v4, withWeight: 6) let result = FloydWarshall.apply(graph) -let path = result.path(fromVertex: v1, toVertex: v4, inGraph: graph) \ No newline at end of file +let path = result.path(fromVertex: v1, toVertex: v4, inGraph: graph) diff --git a/All-Pairs Shortest Paths/APSP/APSP.playground/timeline.xctimeline b/All-Pairs Shortest Paths/APSP/APSP.playground/timeline.xctimeline index 522661fa7..2c73a4e3e 100644 --- a/All-Pairs Shortest Paths/APSP/APSP.playground/timeline.xctimeline +++ b/All-Pairs Shortest Paths/APSP/APSP.playground/timeline.xctimeline @@ -3,12 +3,12 @@ version = "3.0"> diff --git a/All-Pairs Shortest Paths/APSP/APSP.xcodeproj/project.pbxproj b/All-Pairs Shortest Paths/APSP/APSP.xcodeproj/project.pbxproj index 7df369cd7..e7e95bbb7 100644 --- a/All-Pairs Shortest Paths/APSP/APSP.xcodeproj/project.pbxproj +++ b/All-Pairs Shortest Paths/APSP/APSP.xcodeproj/project.pbxproj @@ -7,16 +7,37 @@ objects = { /* Begin PBXBuildFile section */ + 491AA3821CE8C5F700A2E2C5 /* Graph.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 491AA37F1CE8C5C900A2E2C5 /* Graph.framework */; }; 493D8DE31CDD2A1C0089795A /* APSPTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 493D8DE21CDD2A1C0089795A /* APSPTests.swift */; }; 493D8DF41CDD5B960089795A /* APSP.h in Headers */ = {isa = PBXBuildFile; fileRef = 493D8DF31CDD5B960089795A /* APSP.h */; settings = {ATTRIBUTES = (Public, ); }; }; 493D8DF91CDD5B9B0089795A /* FloydWarshall.swift in Sources */ = {isa = PBXBuildFile; fileRef = 493D8DD81CDC38C60089795A /* FloydWarshall.swift */; }; 493D8DFA1CDD5B9E0089795A /* Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 493D8DDA1CDD29C80089795A /* Helpers.swift */; }; - 493D8DFB1CDD5BDE0089795A /* AdjacencyMatrix.swift in Sources */ = {isa = PBXBuildFile; fileRef = 493D8DB91CDC34D00089795A /* AdjacencyMatrix.swift */; }; 49BFA27A1CDD93F400522D66 /* APSP.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49BFA2791CDD93F400522D66 /* APSP.swift */; }; 49BFA2801CDE742900522D66 /* APSP.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 493D8DF11CDD5B960089795A /* APSP.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ + 491AA37E1CE8C5C900A2E2C5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 491AA3791CE8C5C900A2E2C5 /* Graph.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 49BFA2FD1CDF886B00522D66; + remoteInfo = Graph; + }; + 491AA3801CE8C5C900A2E2C5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 491AA3791CE8C5C900A2E2C5 /* Graph.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 49BFA3071CDF886B00522D66; + remoteInfo = GraphTests; + }; + 491AA3831CE8C5F900A2E2C5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 491AA3791CE8C5C900A2E2C5 /* Graph.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 49BFA2FC1CDF886B00522D66; + remoteInfo = Graph; + }; 49BFA27E1CDE742700522D66 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 493D8D7E1CDC2DAE0089795A /* Project object */; @@ -27,7 +48,7 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ - 493D8DB91CDC34D00089795A /* AdjacencyMatrix.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdjacencyMatrix.swift; sourceTree = ""; }; + 491AA3791CE8C5C900A2E2C5 /* Graph.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Graph.xcodeproj; path = ../../Graph/Graph.xcodeproj; sourceTree = ""; }; 493D8DD81CDC38C60089795A /* FloydWarshall.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FloydWarshall.swift; sourceTree = ""; }; 493D8DDA1CDD29C80089795A /* Helpers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Helpers.swift; sourceTree = ""; }; 493D8DE01CDD2A1C0089795A /* APSPTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = APSPTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -52,16 +73,26 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 491AA3821CE8C5F700A2E2C5 /* Graph.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 491AA37A1CE8C5C900A2E2C5 /* Products */ = { + isa = PBXGroup; + children = ( + 491AA37F1CE8C5C900A2E2C5 /* Graph.framework */, + 491AA3811CE8C5C900A2E2C5 /* GraphTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; 493D8D7D1CDC2DAE0089795A = { isa = PBXGroup; children = ( - 493D8DB71CDC34D00089795A /* Graph */, + 491AA3791CE8C5C900A2E2C5 /* Graph.xcodeproj */, 493D8D881CDC2DAE0089795A /* APSP */, 493D8DE11CDD2A1C0089795A /* APSPTests */, 493D8D871CDC2DAE0089795A /* Products */, @@ -89,15 +120,6 @@ path = APSP; sourceTree = ""; }; - 493D8DB71CDC34D00089795A /* Graph */ = { - isa = PBXGroup; - children = ( - 493D8DB91CDC34D00089795A /* AdjacencyMatrix.swift */, - ); - name = Graph; - path = ../../Graph; - sourceTree = ""; - }; 493D8DE11CDD2A1C0089795A /* APSPTests */ = { isa = PBXGroup; children = ( @@ -151,6 +173,7 @@ buildRules = ( ); dependencies = ( + 491AA3841CE8C5F900A2E2C5 /* PBXTargetDependency */, ); name = APSP; productName = APSP; @@ -165,7 +188,7 @@ attributes = { LastSwiftUpdateCheck = 0730; LastUpgradeCheck = 0730; - ORGANIZATIONNAME = "Andrew McKnight"; + ORGANIZATIONNAME = "Swift Algorithm Club"; TargetAttributes = { 493D8DDF1CDD2A1C0089795A = { CreatedOnToolsVersion = 7.3; @@ -185,6 +208,12 @@ mainGroup = 493D8D7D1CDC2DAE0089795A; productRefGroup = 493D8D871CDC2DAE0089795A /* Products */; projectDirPath = ""; + projectReferences = ( + { + ProductGroup = 491AA37A1CE8C5C900A2E2C5 /* Products */; + ProjectRef = 491AA3791CE8C5C900A2E2C5 /* Graph.xcodeproj */; + }, + ); projectRoot = ""; targets = ( 493D8DDF1CDD2A1C0089795A /* APSPTests */, @@ -193,6 +222,23 @@ }; /* End PBXProject section */ +/* Begin PBXReferenceProxy section */ + 491AA37F1CE8C5C900A2E2C5 /* Graph.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = Graph.framework; + remoteRef = 491AA37E1CE8C5C900A2E2C5 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 491AA3811CE8C5C900A2E2C5 /* GraphTests.xctest */ = { + isa = PBXReferenceProxy; + fileType = wrapper.cfbundle; + path = GraphTests.xctest; + remoteRef = 491AA3801CE8C5C900A2E2C5 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; +/* End PBXReferenceProxy section */ + /* Begin PBXResourcesBuildPhase section */ 493D8DDE1CDD2A1C0089795A /* Resources */ = { isa = PBXResourcesBuildPhase; @@ -226,13 +272,17 @@ 49BFA27A1CDD93F400522D66 /* APSP.swift in Sources */, 493D8DF91CDD5B9B0089795A /* FloydWarshall.swift in Sources */, 493D8DFA1CDD5B9E0089795A /* Helpers.swift in Sources */, - 493D8DFB1CDD5BDE0089795A /* AdjacencyMatrix.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ + 491AA3841CE8C5F900A2E2C5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = Graph; + targetProxy = 491AA3831CE8C5F900A2E2C5 /* PBXContainerItemProxy */; + }; 49BFA27F1CDE742700522D66 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 493D8DF01CDD5B960089795A /* APSP */; @@ -329,7 +379,7 @@ COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = APSPTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.armcknight.APSPTests; + PRODUCT_BUNDLE_IDENTIFIER = "com.swift-algorithm-club.APSPTests"; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; @@ -340,7 +390,7 @@ COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = APSPTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.armcknight.APSPTests; + PRODUCT_BUNDLE_IDENTIFIER = "com.swift-algorithm-club.APSPTests"; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; @@ -358,7 +408,7 @@ INFOPLIST_FILE = APSP/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.armcknight.APSP; + PRODUCT_BUNDLE_IDENTIFIER = "com.swift-algorithm-club.APSP"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; VERSIONING_SYSTEM = "apple-generic"; @@ -379,7 +429,7 @@ INFOPLIST_FILE = APSP/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.armcknight.APSP; + PRODUCT_BUNDLE_IDENTIFIER = "com.swift-algorithm-club.APSP"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; VERSIONING_SYSTEM = "apple-generic"; diff --git a/All-Pairs Shortest Paths/APSP/APSP/APSP.h b/All-Pairs Shortest Paths/APSP/APSP/APSP.h index 59613bceb..6936d5a21 100644 --- a/All-Pairs Shortest Paths/APSP/APSP/APSP.h +++ b/All-Pairs Shortest Paths/APSP/APSP/APSP.h @@ -3,7 +3,6 @@ // APSP // // Created by Andrew McKnight on 5/6/16. -// Copyright © 2016 Andrew McKnight. All rights reserved. // #import diff --git a/All-Pairs Shortest Paths/APSP/APSP/APSP.swift b/All-Pairs Shortest Paths/APSP/APSP/APSP.swift index 22ad4a958..bb773306e 100644 --- a/All-Pairs Shortest Paths/APSP/APSP/APSP.swift +++ b/All-Pairs Shortest Paths/APSP/APSP/APSP.swift @@ -3,31 +3,31 @@ // APSP // // Created by Andrew McKnight on 5/6/16. -// Copyright © 2016 Andrew McKnight. All rights reserved. // import Foundation +import Graph /** - APSPAlgorithm is a protocol for encapsulating an All-Pairs Shortest Paths algorithm. It provides a single function `apply` that accepts a `Graph` and returns an object conforming to `APSPResult`. + `APSPAlgorithm` is a protocol for encapsulating an All-Pairs Shortest Paths algorithm. It provides a single function `apply` that accepts a subclass of `AbstractGraph` and returns an object conforming to `APSPResult`. */ -protocol APSPAlgorithm { +public protocol APSPAlgorithm { - associatedtype Q + associatedtype Q: Hashable associatedtype P: APSPResult - static func apply(graph: Graph) -> P + static func apply(graph: AbstractGraph) -> P } /** - APSPResult is a protocol defining functions `distance` and `path`, allowing for opaque queries into the actual data structures that represent the APSP solution according to the algorithm used. + `APSPResult` is a protocol defining functions `distance` and `path`, allowing for opaque queries into the actual data structures that represent the APSP solution according to the algorithm used. */ -protocol APSPResult { +public protocol APSPResult { - associatedtype T + associatedtype T: Hashable func distance(fromVertex from: Vertex, toVertex to: Vertex) -> Double? - func path(fromVertex from: Vertex, toVertex to: Vertex, inGraph graph: Graph) -> [T]? + func path(fromVertex from: Vertex, toVertex to: Vertex, inGraph graph: AbstractGraph) -> [T]? } diff --git a/All-Pairs Shortest Paths/APSP/APSP/FloydWarshall.swift b/All-Pairs Shortest Paths/APSP/APSP/FloydWarshall.swift index 976d3138c..a655e215f 100644 --- a/All-Pairs Shortest Paths/APSP/APSP/FloydWarshall.swift +++ b/All-Pairs Shortest Paths/APSP/APSP/FloydWarshall.swift @@ -3,24 +3,24 @@ // APSP // // Created by Andrew McKnight on 5/5/16. -// Copyright © 2016 Andrew McKnight. All rights reserved. // import Foundation +import Graph private typealias Distances = [[Double]] private typealias Predecessors = [[Int?]] private typealias StepResult = (distances: Distances, predecessors: Predecessors) /** - Encapsulation of the Floyd-Warshall All-Pairs Shortest Paths algorithm, conforming to the APSPAlgorithm protocol. + Encapsulation of the Floyd-Warshall All-Pairs Shortest Paths algorithm, conforming to the `APSPAlgorithm` protocol. - note: In all complexity bounds, `V` is the number of vertices in the graph, and `E` is the number of edges. */ -public struct FloydWarshall: APSPAlgorithm { +public struct FloydWarshall: APSPAlgorithm { - typealias Q = T - typealias P = FloydWarshallResult + public typealias Q = T + public typealias P = FloydWarshallResult /** Floyd-Warshall algorithm for computing all-pairs shortest paths in a weighted directed graph. @@ -29,7 +29,7 @@ public struct FloydWarshall: APSPAlgorithm { - complexity: `Θ(V^3)` time, `Θ(V^2)` space - returns a `FloydWarshallResult` struct which can be queried for shortest paths and their total weights */ - public static func apply(graph: Graph) -> FloydWarshallResult { + public static func apply(graph: AbstractGraph) -> FloydWarshallResult { var previousDistance = constructInitialDistanceMatrix(graph) var previousPredecessor = constructInitialPredecessorMatrix(previousDistance) @@ -56,9 +56,9 @@ public struct FloydWarshall: APSPAlgorithm { - complexity: `Θ(V^2)` time/space - returns: a tuple containing the next distance matrix with weights of currently known shortest paths and the corresponding predecessor matrix */ - static private func nextStep(intermediateIdx: Int, previousDistances: Distances, previousPredecessors: Predecessors, graph: Graph) -> StepResult { + static private func nextStep(intermediateIdx: Int, previousDistances: Distances, previousPredecessors: Predecessors, graph: AbstractGraph) -> StepResult { - let vertexCount = graph.adjacencyMatrix.count + let vertexCount = graph.vertices.count var nextDistances = Array(count: vertexCount, repeatedValue: Array(count: vertexCount, repeatedValue: Double.infinity)) var nextPredecessors = Array(count: vertexCount, repeatedValue: Array(count: vertexCount, repeatedValue: nil)) @@ -86,22 +86,26 @@ public struct FloydWarshall: APSPAlgorithm { } /** - We need to convert the value system in Graph's adjacency matrix to the one we need to perform the algorithm. We need the actual weight between two vertices, or infinity if no edge exists, represented by nil in Graph.adjacencyMatrix. Also set the weight to 0 on the diagonal. + We need to map the graph's weight domain onto the one required by the algorithm: the graph stores either a weight as a `Double` or `nil` if no edge exists between two vertices, but the algorithm needs a lack of an edge represented as ∞ for the `min` comparison to work correctly. - complexity: `Θ(V^2)` time/space - returns: weighted adjacency matrix in form ready for processing with Floyd-Warshall */ - static private func constructInitialDistanceMatrix(graph: Graph) -> Distances { + static private func constructInitialDistanceMatrix(graph: AbstractGraph) -> Distances { - let vertexCount = graph.adjacencyMatrix.count + let vertices = graph.vertices + + let vertexCount = graph.vertices.count var distances = Array(count: vertexCount, repeatedValue: Array(count: vertexCount, repeatedValue: Double.infinity)) - for fromIdx in 0 ..< vertexCount { - for toIdx in 0 ..< vertexCount { - if fromIdx == toIdx { - distances[fromIdx][toIdx] = 0.0 - } else if let w = graph.adjacencyMatrix[fromIdx][toIdx] { - distances[fromIdx][toIdx] = w + for row in vertices { + for col in vertices { + let rowIdx = row.index + let colIdx = col.index + if rowIdx == colIdx { + distances[rowIdx][colIdx] = 0.0 + } else if let w = graph.weightFrom(row, to: col) { + distances[rowIdx][colIdx] = w } } } @@ -135,17 +139,17 @@ public struct FloydWarshall: APSPAlgorithm { } /** - FloydWarshallResult encapsulates the result of the computation, namely the minimized distance adjacency matrix, and the matrix of predecessor indices. + `FloydWarshallResult` encapsulates the result of the computation, namely the minimized distance adjacency matrix, and the matrix of predecessor indices. - It conforms to the APSPResult procotol which provides methods to retrieve distances and paths between given pairs of start and end nodes. + It conforms to the `APSPResult` procotol which provides methods to retrieve distances and paths between given pairs of start and end nodes. */ -public struct FloydWarshallResult: APSPResult { +public struct FloydWarshallResult: APSPResult { private var weights: Distances private var predecessors: Predecessors /** - - returns: the total weight of the path from a starting vertex to a destination. This value is the minimal connected weight between the two vertices. + - returns: the total weight of the path from a starting vertex to a destination. This value is the minimal connected weight between the two vertices, or `nil` if no path exists - complexity: `Θ(1)` time/space */ public func distance(fromVertex from: Vertex, toVertex to: Vertex) -> Double? { @@ -155,12 +159,12 @@ public struct FloydWarshallResult: APSPResult { } /** - - returns: the reconstructed path from a starting vertex to a destination, as an array containing the data property of each vertex + - returns: the reconstructed path from a starting vertex to a destination, as an array containing the data property of each vertex, or `nil` if no path exists - complexity: `Θ(V)` time, `Θ(V^2)` space */ - public func path(fromVertex from: Vertex, toVertex to: Vertex, inGraph graph: Graph) -> [T]? { + public func path(fromVertex from: Vertex, toVertex to: Vertex, inGraph graph: AbstractGraph) -> [T]? { - if let path = recursePathFrom(predecessors, fromVertex: from, toVertex: to, path: [ to ], inGraph: graph) { + if let path = recursePathFrom(fromVertex: from, toVertex: to, path: [ to ], inGraph: graph) { let pathValues = path.map() { vertex in vertex.data } @@ -171,11 +175,11 @@ public struct FloydWarshallResult: APSPResult { } /** - The recursive component to rebuilding the shortest path between two vertices using the predecessor graph. + The recursive component to rebuilding the shortest path between two vertices using the predecessor matrix. - returns: the list of predecessors discovered so far */ - private func recursePathFrom(predecessors: [[Int?]], fromVertex from: Vertex, toVertex to: Vertex, path: [Vertex], inGraph graph: Graph) -> [Vertex]? { + private func recursePathFrom(fromVertex from: Vertex, toVertex to: Vertex, path: [Vertex], inGraph graph: AbstractGraph) -> [Vertex]? { if from.index == to.index { return [ from, to ] @@ -187,7 +191,7 @@ public struct FloydWarshallResult: APSPResult { let newPath = [ from, to ] return newPath } else { - let buildPath = recursePathFrom(predecessors, fromVertex: from, toVertex: predecessorVertex, path: path, inGraph: graph) + let buildPath = recursePathFrom(fromVertex: from, toVertex: predecessorVertex, path: path, inGraph: graph) let newPath = buildPath! + [ to ] return newPath } diff --git a/All-Pairs Shortest Paths/APSP/APSP/Helpers.swift b/All-Pairs Shortest Paths/APSP/APSP/Helpers.swift index c6f22e879..644454491 100644 --- a/All-Pairs Shortest Paths/APSP/APSP/Helpers.swift +++ b/All-Pairs Shortest Paths/APSP/APSP/Helpers.swift @@ -3,7 +3,6 @@ // APSP // // Created by Andrew McKnight on 5/6/16. -// Copyright © 2016 Andrew McKnight. All rights reserved. // import Foundation diff --git a/All-Pairs Shortest Paths/APSP/APSP/Info.plist b/All-Pairs Shortest Paths/APSP/APSP/Info.plist index 9bf850304..d3de8eefb 100644 --- a/All-Pairs Shortest Paths/APSP/APSP/Info.plist +++ b/All-Pairs Shortest Paths/APSP/APSP/Info.plist @@ -20,8 +20,6 @@ ???? CFBundleVersion $(CURRENT_PROJECT_VERSION) - NSHumanReadableCopyright - Copyright © 2016 Andrew McKnight. All rights reserved. NSPrincipalClass diff --git a/All-Pairs Shortest Paths/APSP/APSPTests/APSPTests.swift b/All-Pairs Shortest Paths/APSP/APSPTests/APSPTests.swift index 47b71b3ea..52e87758c 100644 --- a/All-Pairs Shortest Paths/APSP/APSPTests/APSPTests.swift +++ b/All-Pairs Shortest Paths/APSP/APSPTests/APSPTests.swift @@ -3,13 +3,13 @@ // APSPTests // // Created by Andrew McKnight on 5/6/16. -// Copyright © 2016 Andrew McKnight. All rights reserved. // import APSP +import Graph import XCTest -struct TestCase { +struct TestCase { var from: Vertex var to: Vertex @@ -20,53 +20,56 @@ struct TestCase { class APSPTests: XCTestCase { + /** + See Figure 25.1 of “Introduction to Algorithms” by Cormen et al, 3rd ed., pg 690 + */ func testExampleFromBook() { - var graph = Graph() - let v1 = graph.createVertex("Montreal") - let v2 = graph.createVertex("New York") - let v3 = graph.createVertex("Boston") - let v4 = graph.createVertex("Portland") - let v5 = graph.createVertex("Portsmouth") + let graph = AdjacencyMatrixGraph() + let v1 = graph.createVertex(1) + let v2 = graph.createVertex(2) + let v3 = graph.createVertex(3) + let v4 = graph.createVertex(4) + let v5 = graph.createVertex(5) - graph.connect(v1, to: v2, withWeight: 3) - graph.connect(v1, to: v5, withWeight: -4) - graph.connect(v1, to: v3, withWeight: 8) + graph.addDirectedEdge(v1, to: v2, withWeight: 3) + graph.addDirectedEdge(v1, to: v5, withWeight: -4) + graph.addDirectedEdge(v1, to: v3, withWeight: 8) - graph.connect(v2, to: v4, withWeight: 1) - graph.connect(v2, to: v5, withWeight: 7) + graph.addDirectedEdge(v2, to: v4, withWeight: 1) + graph.addDirectedEdge(v2, to: v5, withWeight: 7) - graph.connect(v3, to: v2, withWeight: 4) + graph.addDirectedEdge(v3, to: v2, withWeight: 4) - graph.connect(v4, to: v1, withWeight: 2) - graph.connect(v4, to: v3, withWeight: -5) + graph.addDirectedEdge(v4, to: v1, withWeight: 2) + graph.addDirectedEdge(v4, to: v3, withWeight: -5) - graph.connect(v5, to: v4, withWeight: 6) + graph.addDirectedEdge(v5, to: v4, withWeight: 6) - let result = FloydWarshall.apply(graph) + let result = FloydWarshall.apply(graph) let cases = [ - TestCase(from: v1, to: v4, expectedPath: ["Montreal", "Portsmouth", "Portland"], expectedDistance: 2), - TestCase(from: v1, to: v5, expectedPath: ["Montreal", "Portsmouth"], expectedDistance: -4), - TestCase(from: v2, to: v1, expectedPath: ["New York", "Portland", "Montreal"], expectedDistance: 3), - TestCase(from: v2, to: v3, expectedPath: ["New York", "Portland", "Boston"], expectedDistance: -4), - TestCase(from: v2, to: v4, expectedPath: ["New York", "Portland"], expectedDistance: 1), - TestCase(from: v2, to: v5, expectedPath: ["New York", "Portland", "Montreal", "Portsmouth"], expectedDistance: -1), - TestCase(from: v3, to: v1, expectedPath: ["Boston", "New York", "Portland", "Montreal"], expectedDistance: 7), - TestCase(from: v3, to: v2, expectedPath: ["Boston", "New York"], expectedDistance: 4), - TestCase(from: v3, to: v4, expectedPath: ["Boston", "New York", "Portland"], expectedDistance: 5), - TestCase(from: v3, to: v5, expectedPath: ["Boston", "New York", "Portland", "Montreal", "Portsmouth"], expectedDistance: 3), - TestCase(from: v4, to: v1, expectedPath: ["Portland", "Montreal"], expectedDistance: 2), - TestCase(from: v4, to: v2, expectedPath: ["Portland", "Boston", "New York"], expectedDistance: -1), - TestCase(from: v4, to: v3, expectedPath: ["Portland", "Boston"], expectedDistance: -5), - TestCase(from: v4, to: v5, expectedPath: ["Portland", "Montreal", "Portsmouth"], expectedDistance: -2), - TestCase(from: v5, to: v1, expectedPath: ["Portsmouth", "Portland", "Montreal"], expectedDistance: 8), - TestCase(from: v5, to: v2, expectedPath: ["Portsmouth", "Portland", "Boston", "New York"], expectedDistance: 5), - TestCase(from: v5, to: v3, expectedPath: ["Portsmouth", "Portland", "Boston"], expectedDistance: 1), - TestCase(from: v5, to: v4, expectedPath: ["Portsmouth", "Portland"], expectedDistance: 6), + TestCase(from: v1, to: v4, expectedPath: [1, 5, 4], expectedDistance: 2), + TestCase(from: v1, to: v5, expectedPath: [1, 5], expectedDistance: -4), + TestCase(from: v2, to: v1, expectedPath: [2, 4, 1], expectedDistance: 3), + TestCase(from: v2, to: v3, expectedPath: [2, 4, 3], expectedDistance: -4), + TestCase(from: v2, to: v4, expectedPath: [2, 4], expectedDistance: 1), + TestCase(from: v2, to: v5, expectedPath: [2, 4, 1, 5], expectedDistance: -1), + TestCase(from: v3, to: v1, expectedPath: [3, 2, 4, 1], expectedDistance: 7), + TestCase(from: v3, to: v2, expectedPath: [3, 2], expectedDistance: 4), + TestCase(from: v3, to: v4, expectedPath: [3, 2, 4], expectedDistance: 5), + TestCase(from: v3, to: v5, expectedPath: [3, 2, 4, 1, 5], expectedDistance: 3), + TestCase(from: v4, to: v1, expectedPath: [4, 1], expectedDistance: 2), + TestCase(from: v4, to: v2, expectedPath: [4, 3, 2], expectedDistance: -1), + TestCase(from: v4, to: v3, expectedPath: [4, 3], expectedDistance: -5), + TestCase(from: v4, to: v5, expectedPath: [4, 1, 5], expectedDistance: -2), + TestCase(from: v5, to: v1, expectedPath: [5, 4, 1], expectedDistance: 8), + TestCase(from: v5, to: v2, expectedPath: [5, 4, 3, 2], expectedDistance: 5), + TestCase(from: v5, to: v3, expectedPath: [5, 4, 3], expectedDistance: 1), + TestCase(from: v5, to: v4, expectedPath: [5, 4], expectedDistance: 6), ] - for testCase: TestCase in cases { + for testCase: TestCase in cases { if let computedPath = result.path(fromVertex: testCase.from, toVertex: testCase.to, inGraph: graph), computedDistance = result.distance(fromVertex: testCase.from, toVertex: testCase.to) { XCTAssert(computedDistance == testCase.expectedDistance, "expected distance \(testCase.expectedDistance) but got \(computedDistance)") @@ -78,20 +81,20 @@ class APSPTests: XCTestCase { func testExampleFromReadme() { - var graph = Graph() + let graph = AdjacencyMatrixGraph() let v1 = graph.createVertex(1) let v2 = graph.createVertex(2) let v3 = graph.createVertex(3) let v4 = graph.createVertex(4) - graph.connect(v1, to: v2, withWeight: 4) - graph.connect(v1, to: v3, withWeight: 1) - graph.connect(v1, to: v4, withWeight: 3) + graph.addDirectedEdge(v1, to: v2, withWeight: 4) + graph.addDirectedEdge(v1, to: v3, withWeight: 1) + graph.addDirectedEdge(v1, to: v4, withWeight: 3) - graph.connect(v2, to: v3, withWeight: 8) - graph.connect(v2, to: v4, withWeight: -2) + graph.addDirectedEdge(v2, to: v3, withWeight: 8) + graph.addDirectedEdge(v2, to: v4, withWeight: -2) - graph.connect(v3, to: v4, withWeight: -5) + graph.addDirectedEdge(v3, to: v4, withWeight: -5) let result = FloydWarshall.apply(graph) diff --git a/Graph/AdjacencyList.swift b/Graph/AdjacencyList.swift deleted file mode 100644 index 3a8bc3006..000000000 --- a/Graph/AdjacencyList.swift +++ /dev/null @@ -1,39 +0,0 @@ -private var uniqueIDCounter = 0 - -public struct Edge { - public let from: Vertex - public let to: Vertex - public let weight: Double -} - -public struct Vertex { - public var data: T - public let uniqueID: Int - - private(set) public var edges: [Edge] = [] // the adjacency list - - public init(data: T) { - self.data = data - uniqueID = uniqueIDCounter - uniqueIDCounter += 1 - } - - // Creates the directed edge: self -----> dest - public mutating func connectTo(destinationVertex: Vertex, withWeight weight: Double = 0) { - edges.append(Edge(from: self, to: destinationVertex, weight: weight)) - } - - // Creates an undirected edge by making two directed edges: self ----> other, and other ----> self - public mutating func connectBetween(inout otherVertex: Vertex, withWeight weight: Double = 0) { - connectTo(otherVertex, withWeight: weight) - otherVertex.connectTo(self, withWeight: weight) - } - - // Does this vertex have an edge -----> otherVertex? - public func edgeTo(otherVertex: Vertex) -> Edge? { - for e in edges where e.to.uniqueID == otherVertex.uniqueID { - return e - } - return nil - } -} diff --git a/Graph/AdjacencyMatrix.swift b/Graph/AdjacencyMatrix.swift deleted file mode 100644 index d1d35ac02..000000000 --- a/Graph/AdjacencyMatrix.swift +++ /dev/null @@ -1,75 +0,0 @@ -import Foundation - -public struct Vertex { - public var data: T - public let index: Int -} - - - -public struct Graph { - // If adjacencyMatrix[i][j] is not nil, then there is an edge from - // vertex i to vertex j. - var adjacencyMatrix: [[Double?]] = [] - var vertices: [Vertex] = [] - - public init() {} - - // Adds a new vertex to the matrix. - // Performance: possibly O(n^2) because of the resizing of the matrix. - public mutating func createVertex(data: T) -> Vertex { - let vertex = Vertex(data: data, index: adjacencyMatrix.count) - - // Expand each existing row to the right one column. - for i in 0.. dest. - public mutating func connect(sourceVertex: Vertex, to destinationVertex: Vertex, withWeight weight: Double = 0) { - adjacencyMatrix[sourceVertex.index][destinationVertex.index] = weight - } - - // Creates an undirected edge by making 2 directed edges: - // some ----> other, and other ----> some. - public mutating func connect(someVertex: Vertex, symmetricallyWithVertex withVertex: Vertex, withWeight weight: Double = 0) { - adjacencyMatrix[someVertex.index][withVertex.index] = weight - adjacencyMatrix[withVertex.index][someVertex.index] = weight - } - - public func weightFrom(sourceVertex: Vertex, toDestinationVertex: Vertex) -> Double? { - return adjacencyMatrix[sourceVertex.index][toDestinationVertex.index] - } -} diff --git a/Graph/Graph.playground/Contents.swift b/Graph/Graph.playground/Contents.swift new file mode 100644 index 000000000..4e6d98a11 --- /dev/null +++ b/Graph/Graph.playground/Contents.swift @@ -0,0 +1,45 @@ +import Graph + +// Create the vertices +var adjacencyMatrixGraph = AdjacencyMatrixGraph() +var adjacencyListGraph = AdjacencyListGraph() + +for graph in [ adjacencyMatrixGraph, adjacencyListGraph ] { + + let v1 = graph.createVertex(1) + let v2 = graph.createVertex(2) + let v3 = graph.createVertex(3) + let v4 = graph.createVertex(4) + let v5 = graph.createVertex(5) + + // Set up a cycle like so: + // v5 + // ^ + // | (3.2) + // | + // v1 ---(1)---> v2 ---(1)---> v3 ---(4.5)---> v4 + // ^ | + // | V + // ---------<-----------<---------(2.8)----<----| + + graph.addDirectedEdge(v1, to: v2, withWeight: 1.0) + graph.addDirectedEdge(v2, to: v3, withWeight: 1.0) + graph.addDirectedEdge(v3, to: v4, withWeight: 4.5) + graph.addDirectedEdge(v4, to: v1, withWeight: 2.8) + graph.addDirectedEdge(v2, to: v5, withWeight: 3.2) + + // Returns the weight of the edge from v1 to v2 (1.0) + graph.weightFrom(v1, to: v2) + + // Returns the weight of the edge from v1 to v3 (nil, since there is not an edge) + graph.weightFrom(v1, to: v3) + + // Returns the weight of the edge from v3 to v4 (4.5) + graph.weightFrom(v3, to: v4) + + // Returns the weight of the edge from v4 to v1 (2.8) + graph.weightFrom(v4, to: v1) + + print(graph) + print() // separate by a newline +} diff --git a/Graph/Graph.playground/Pages/Adjacency List.xcplaygroundpage/Contents.swift b/Graph/Graph.playground/Pages/Adjacency List.xcplaygroundpage/Contents.swift deleted file mode 100644 index f3c89b112..000000000 --- a/Graph/Graph.playground/Pages/Adjacency List.xcplaygroundpage/Contents.swift +++ /dev/null @@ -1,87 +0,0 @@ -//: # Graph using an adjacency list -//: -//: In an adjacency list implementation of a graph, each vertex stores an -//: array of edges, indicating to which other vertices it has an edge. -//: (Note the directionality: we only record "to" edges, not "from" edges.) - -private var uniqueIDCounter = 0 - -public struct Edge { - public let from: Vertex - public let to: Vertex - public let weight: Double -} - -public struct Vertex { - public var data: T - public let uniqueID: Int - - private(set) public var edges: [Edge] = [] // the adjacency list - - public init(data: T) { - self.data = data - uniqueID = uniqueIDCounter - uniqueIDCounter += 1 - } - - // Creates the directed edge: self -----> dest - public mutating func connectTo(destinationVertex: Vertex, withWeight weight: Double = 0) { - edges.append(Edge(from: self, to: destinationVertex, weight: weight)) - } - - // Creates an undirected edge by making two directed edges: self ----> other, and other ----> self - public mutating func connectBetween(inout otherVertex: Vertex, withWeight weight: Double = 0) { - connectTo(otherVertex, withWeight: weight) - otherVertex.connectTo(self, withWeight: weight) - } - - // Does this vertex have an edge -----> otherVertex? - public func edgeTo(otherVertex: Vertex) -> Edge? { - for e in edges where e.to.uniqueID == otherVertex.uniqueID { - return e - } - return nil - } -} - - - -//: ### Demo - -// Create the vertices -var v1 = Vertex(data: 1) -var v2 = Vertex(data: 2) -var v3 = Vertex(data: 3) -var v4 = Vertex(data: 4) -var v5 = Vertex(data: 5) - -// Set up a cycle like so: -// v5 -// ^ -// | (3.2) -// | -// v1 ---(1)---> v2 ---(1)---> v3 ---(4.5)---> v4 -// ^ | -// | V -// ---------<-----------<---------(2.8)----<----| - -v1.connectTo(v2, withWeight: 1.0) -v2.connectTo(v3, withWeight: 1.0) -v3.connectTo(v4, withWeight: 4.5) -v4.connectTo(v1, withWeight: 2.8) -v2.connectTo(v5, withWeight: 3.2) - - -// Returns the weight of the edge from v1 to v2 (1.0) -v1.edgeTo(v2)?.weight - -// Returns the weight of the edge from v1 to v3 (nil, since there is not an edge) -v1.edgeTo(v3)?.weight - -// Returns the weight of the edge from v3 to v4 (4.5) -v3.edgeTo(v4)?.weight - -// Returns the weight of the edge from v4 to v1 (2.8) -v4.edgeTo(v1)?.weight - -//: [Next: Adjacency Matrix](@next) diff --git a/Graph/Graph.playground/Pages/Adjacency List.xcplaygroundpage/timeline.xctimeline b/Graph/Graph.playground/Pages/Adjacency List.xcplaygroundpage/timeline.xctimeline deleted file mode 100644 index bf468afec..000000000 --- a/Graph/Graph.playground/Pages/Adjacency List.xcplaygroundpage/timeline.xctimeline +++ /dev/null @@ -1,6 +0,0 @@ - - - - - diff --git a/Graph/Graph.playground/Pages/Adjacency Matrix.xcplaygroundpage/Contents.swift b/Graph/Graph.playground/Pages/Adjacency Matrix.xcplaygroundpage/Contents.swift deleted file mode 100644 index 8d9fb5080..000000000 --- a/Graph/Graph.playground/Pages/Adjacency Matrix.xcplaygroundpage/Contents.swift +++ /dev/null @@ -1,99 +0,0 @@ -//: [Previous: Adjacency List](@previous) - -//: # Graph using an adjacency matrix -//: -//: In an adjacency matrix implementation, each vertex is given an index -//: from `0.. { - public var data: T - private let index: Int -} - -public struct Graph { - // If adjacencyMatrix[i][j] is not nil, then there is an edge from - // vertex i to vertex j. - private var adjacencyMatrix: [[Double?]] = [] - - // Adds a new vertex to the matrix. - // Performance: possibly O(n^2) because of the resizing of the matrix. - public mutating func createVertex(data: T) -> Vertex { - let vertex = Vertex(data: data, index: adjacencyMatrix.count) - - // Expand each existing row to the right one column. - for i in 0.. dest. - public mutating func connect(sourceVertex: Vertex, to destinationVertex: Vertex, withWeight weight: Double = 0) { - adjacencyMatrix[sourceVertex.index][destinationVertex.index] = weight - } - - // Creates an undirected edge by making 2 directed edges: - // some ----> other, and other ----> some. - public mutating func connect(someVertex: Vertex, symmetricallyWithVertex withVertex: Vertex, withWeight weight: Double = 0) { - adjacencyMatrix[someVertex.index][withVertex.index] = weight - adjacencyMatrix[withVertex.index][someVertex.index] = weight - } - - public func weightFrom(sourceVertex: Vertex, toDestinationVertex: Vertex) -> Double? { - return adjacencyMatrix[sourceVertex.index][toDestinationVertex.index] - } -} - - - -//: ### Demo - -// Create the vertices -var graph = Graph() -let v1 = graph.createVertex(1) -let v2 = graph.createVertex(2) -let v3 = graph.createVertex(3) -let v4 = graph.createVertex(4) -let v5 = graph.createVertex(5) - -// Set up a cycle like so: -// v5 -// ^ -// | (3.2) -// | -// v1 ---(1)---> v2 ---(1)---> v3 ---(4.5)---> v4 -// ^ | -// | V -// ---------<-----------<---------(2.8)----<----| - -graph.connect(v1, to: v2, withWeight: 1.0) -graph.connect(v2, to: v3, withWeight: 1.0) -graph.connect(v3, to: v4, withWeight: 4.5) -graph.connect(v4, to: v1, withWeight: 2.8) -graph.connect(v2, to: v5, withWeight: 3.2) - -// Returns the weight of the edge from v1 to v2 (1.0) -graph.weightFrom(v1, toDestinationVertex: v2) - -// Returns the weight of the edge from v1 to v3 (nil, since there is not an edge) -graph.weightFrom(v1, toDestinationVertex: v3) - -// Returns the weight of the edge from v3 to v4 (4.5) -graph.weightFrom(v3, toDestinationVertex: v4) - -// Returns the weight of the edge from v4 to v1 (2.8) -graph.weightFrom(v4, toDestinationVertex: v1) - -print(graph.adjacencyMatrix) - diff --git a/Graph/Graph.playground/Pages/Adjacency Matrix.xcplaygroundpage/timeline.xctimeline b/Graph/Graph.playground/Pages/Adjacency Matrix.xcplaygroundpage/timeline.xctimeline deleted file mode 100644 index 60cd19e82..000000000 --- a/Graph/Graph.playground/Pages/Adjacency Matrix.xcplaygroundpage/timeline.xctimeline +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - diff --git a/Graph/Graph.playground/contents.xcplayground b/Graph/Graph.playground/contents.xcplayground index 32b5a98b9..50ce46d0b 100644 --- a/Graph/Graph.playground/contents.xcplayground +++ b/Graph/Graph.playground/contents.xcplayground @@ -1,7 +1,2 @@ - - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/Graph/Graph.xcodeproj/project.pbxproj b/Graph/Graph.xcodeproj/project.pbxproj new file mode 100644 index 000000000..0157eb377 --- /dev/null +++ b/Graph/Graph.xcodeproj/project.pbxproj @@ -0,0 +1,421 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 491AA3761CE6B81C00A2E2C5 /* AdjacencyListGraph.swift in Sources */ = {isa = PBXBuildFile; fileRef = 491AA3751CE6B81C00A2E2C5 /* AdjacencyListGraph.swift */; }; + 491AA3781CE6B82E00A2E2C5 /* AdjacencyMatrixGraph.swift in Sources */ = {isa = PBXBuildFile; fileRef = 491AA3771CE6B82E00A2E2C5 /* AdjacencyMatrixGraph.swift */; }; + 49BFA3011CDF886B00522D66 /* Graph.h in Headers */ = {isa = PBXBuildFile; fileRef = 49BFA3001CDF886B00522D66 /* Graph.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 49BFA3081CDF886B00522D66 /* Graph.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 49BFA2FD1CDF886B00522D66 /* Graph.framework */; }; + 49BFA30D1CDF886B00522D66 /* GraphTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49BFA30C1CDF886B00522D66 /* GraphTests.swift */; }; + 49BFA3181CDF887E00522D66 /* Graph.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49BFA3171CDF887E00522D66 /* Graph.swift */; }; + 49BFA3271CDF899400522D66 /* Edge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49BFA3261CDF899400522D66 /* Edge.swift */; }; + 49BFA32F1CDF89FC00522D66 /* Vertex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49BFA32E1CDF89FC00522D66 /* Vertex.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 49BFA3091CDF886B00522D66 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 49BFA2F41CDF886B00522D66 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 49BFA2FC1CDF886B00522D66; + remoteInfo = Graph; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 491AA3751CE6B81C00A2E2C5 /* AdjacencyListGraph.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AdjacencyListGraph.swift; sourceTree = ""; }; + 491AA3771CE6B82E00A2E2C5 /* AdjacencyMatrixGraph.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AdjacencyMatrixGraph.swift; sourceTree = ""; }; + 49BFA2FD1CDF886B00522D66 /* Graph.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Graph.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 49BFA3001CDF886B00522D66 /* Graph.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Graph.h; sourceTree = ""; }; + 49BFA3021CDF886B00522D66 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 49BFA3071CDF886B00522D66 /* GraphTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = GraphTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 49BFA30C1CDF886B00522D66 /* GraphTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GraphTests.swift; sourceTree = ""; }; + 49BFA30E1CDF886B00522D66 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 49BFA3171CDF887E00522D66 /* Graph.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Graph.swift; sourceTree = ""; }; + 49BFA3261CDF899400522D66 /* Edge.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Edge.swift; sourceTree = ""; }; + 49BFA32E1CDF89FC00522D66 /* Vertex.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Vertex.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 49BFA2F91CDF886B00522D66 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 49BFA3041CDF886B00522D66 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 49BFA3081CDF886B00522D66 /* Graph.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 49BFA2F31CDF886B00522D66 = { + isa = PBXGroup; + children = ( + 49BFA2FF1CDF886B00522D66 /* Graph */, + 49BFA30B1CDF886B00522D66 /* GraphTests */, + 49BFA2FE1CDF886B00522D66 /* Products */, + ); + sourceTree = ""; + }; + 49BFA2FE1CDF886B00522D66 /* Products */ = { + isa = PBXGroup; + children = ( + 49BFA2FD1CDF886B00522D66 /* Graph.framework */, + 49BFA3071CDF886B00522D66 /* GraphTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 49BFA2FF1CDF886B00522D66 /* Graph */ = { + isa = PBXGroup; + children = ( + 49BFA3001CDF886B00522D66 /* Graph.h */, + 49BFA3021CDF886B00522D66 /* Info.plist */, + 49BFA3261CDF899400522D66 /* Edge.swift */, + 49BFA32E1CDF89FC00522D66 /* Vertex.swift */, + 49BFA3171CDF887E00522D66 /* Graph.swift */, + 491AA3751CE6B81C00A2E2C5 /* AdjacencyListGraph.swift */, + 491AA3771CE6B82E00A2E2C5 /* AdjacencyMatrixGraph.swift */, + ); + path = Graph; + sourceTree = ""; + }; + 49BFA30B1CDF886B00522D66 /* GraphTests */ = { + isa = PBXGroup; + children = ( + 49BFA30C1CDF886B00522D66 /* GraphTests.swift */, + 49BFA30E1CDF886B00522D66 /* Info.plist */, + ); + path = GraphTests; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 49BFA2FA1CDF886B00522D66 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 49BFA3011CDF886B00522D66 /* Graph.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 49BFA2FC1CDF886B00522D66 /* Graph */ = { + isa = PBXNativeTarget; + buildConfigurationList = 49BFA3111CDF886B00522D66 /* Build configuration list for PBXNativeTarget "Graph" */; + buildPhases = ( + 49BFA2F81CDF886B00522D66 /* Sources */, + 49BFA2F91CDF886B00522D66 /* Frameworks */, + 49BFA2FA1CDF886B00522D66 /* Headers */, + 49BFA2FB1CDF886B00522D66 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Graph; + productName = Graph; + productReference = 49BFA2FD1CDF886B00522D66 /* Graph.framework */; + productType = "com.apple.product-type.framework"; + }; + 49BFA3061CDF886B00522D66 /* GraphTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 49BFA3141CDF886B00522D66 /* Build configuration list for PBXNativeTarget "GraphTests" */; + buildPhases = ( + 49BFA3031CDF886B00522D66 /* Sources */, + 49BFA3041CDF886B00522D66 /* Frameworks */, + 49BFA3051CDF886B00522D66 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 49BFA30A1CDF886B00522D66 /* PBXTargetDependency */, + ); + name = GraphTests; + productName = GraphTests; + productReference = 49BFA3071CDF886B00522D66 /* GraphTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 49BFA2F41CDF886B00522D66 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0730; + LastUpgradeCheck = 0730; + ORGANIZATIONNAME = "Swift Algorithm Club"; + TargetAttributes = { + 49BFA2FC1CDF886B00522D66 = { + CreatedOnToolsVersion = 7.3; + }; + 49BFA3061CDF886B00522D66 = { + CreatedOnToolsVersion = 7.3; + }; + }; + }; + buildConfigurationList = 49BFA2F71CDF886B00522D66 /* Build configuration list for PBXProject "Graph" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 49BFA2F31CDF886B00522D66; + productRefGroup = 49BFA2FE1CDF886B00522D66 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 49BFA2FC1CDF886B00522D66 /* Graph */, + 49BFA3061CDF886B00522D66 /* GraphTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 49BFA2FB1CDF886B00522D66 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 49BFA3051CDF886B00522D66 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 49BFA2F81CDF886B00522D66 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 491AA3761CE6B81C00A2E2C5 /* AdjacencyListGraph.swift in Sources */, + 49BFA3271CDF899400522D66 /* Edge.swift in Sources */, + 491AA3781CE6B82E00A2E2C5 /* AdjacencyMatrixGraph.swift in Sources */, + 49BFA3181CDF887E00522D66 /* Graph.swift in Sources */, + 49BFA32F1CDF89FC00522D66 /* Vertex.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 49BFA3031CDF886B00522D66 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 49BFA30D1CDF886B00522D66 /* GraphTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 49BFA30A1CDF886B00522D66 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 49BFA2FC1CDF886B00522D66 /* Graph */; + targetProxy = 49BFA3091CDF886B00522D66 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 49BFA30F1CDF886B00522D66 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 49BFA3101CDF886B00522D66 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 49BFA3121CDF886B00522D66 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + COMBINE_HIDPI_IMAGES = YES; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + FRAMEWORK_VERSION = A; + INFOPLIST_FILE = Graph/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.swift-algorithm-club.Graph"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 49BFA3131CDF886B00522D66 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + COMBINE_HIDPI_IMAGES = YES; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + FRAMEWORK_VERSION = A; + INFOPLIST_FILE = Graph/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.swift-algorithm-club.Graph"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + }; + name = Release; + }; + 49BFA3151CDF886B00522D66 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = GraphTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.swift-algorithm-club.GraphTests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 49BFA3161CDF886B00522D66 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = GraphTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.swift-algorithm-club.GraphTests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 49BFA2F71CDF886B00522D66 /* Build configuration list for PBXProject "Graph" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 49BFA30F1CDF886B00522D66 /* Debug */, + 49BFA3101CDF886B00522D66 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 49BFA3111CDF886B00522D66 /* Build configuration list for PBXNativeTarget "Graph" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 49BFA3121CDF886B00522D66 /* Debug */, + 49BFA3131CDF886B00522D66 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 49BFA3141CDF886B00522D66 /* Build configuration list for PBXNativeTarget "GraphTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 49BFA3151CDF886B00522D66 /* Debug */, + 49BFA3161CDF886B00522D66 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 49BFA2F41CDF886B00522D66 /* Project object */; +} diff --git a/Graph/Graph.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Graph/Graph.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..94b2795e2 --- /dev/null +++ b/Graph/Graph.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,4 @@ + + + diff --git a/Graph/Graph.xcodeproj/xcshareddata/xcschemes/Graph.xcscheme b/Graph/Graph.xcodeproj/xcshareddata/xcschemes/Graph.xcscheme new file mode 100644 index 000000000..a8ce1124d --- /dev/null +++ b/Graph/Graph.xcodeproj/xcshareddata/xcschemes/Graph.xcscheme @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Graph/Graph.xcodeproj/xcshareddata/xcschemes/GraphTests.xcscheme b/Graph/Graph.xcodeproj/xcshareddata/xcschemes/GraphTests.xcscheme new file mode 100644 index 000000000..8eb3c9fdf --- /dev/null +++ b/Graph/Graph.xcodeproj/xcshareddata/xcschemes/GraphTests.xcscheme @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Graph/Graph.xcworkspace/contents.xcworkspacedata b/Graph/Graph.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..eea257206 --- /dev/null +++ b/Graph/Graph.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/Graph/Graph.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/Graph/Graph.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 000000000..08de0be8d --- /dev/null +++ b/Graph/Graph.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded + + + diff --git a/Graph/Graph/AdjacencyListGraph.swift b/Graph/Graph/AdjacencyListGraph.swift new file mode 100644 index 000000000..fddd04033 --- /dev/null +++ b/Graph/Graph/AdjacencyListGraph.swift @@ -0,0 +1,134 @@ +// +// AdjacencyListGraph.swift +// Graph +// +// Created by Andrew McKnight on 5/13/16. +// + +import Foundation + +private class EdgeList { + + var vertex: Vertex + var edges: [Edge]? = nil + + init(vertex: Vertex) { + self.vertex = vertex + } + + func addEdge(edge: Edge) { + edges?.append(edge) + } + +} + +public class AdjacencyListGraph: AbstractGraph { + + private var adjacencyList: [EdgeList] = [] + + public override init() { + super.init() + } + + public override init(fromGraph graph: AbstractGraph) { + super.init(fromGraph: graph) + } + + public override var vertices: [Vertex] { + get { + var vertices = [Vertex]() + for edgeList in adjacencyList { + vertices.append(edgeList.vertex) + } + return vertices + } + } + + public override var edges: [Edge] { + get { + var allEdges = Set>() + for edgeList in adjacencyList { + guard let edges = edgeList.edges else { + continue + } + + for edge in edges { + allEdges.insert(edge) + } + } + return Array(allEdges) + } + } + + public override func createVertex(data: T) -> Vertex { + // check if the vertex already exists + let matchingVertices = vertices.filter() { vertex in + return vertex.data == data + } + + if matchingVertices.count > 0 { + return matchingVertices.last! + } + + // if the vertex doesn't exist, create a new one + let vertex = Vertex(data: data, index: adjacencyList.count) + adjacencyList.append(EdgeList(vertex: vertex)) + return vertex + } + + public override func addDirectedEdge(from: Vertex, to: Vertex, withWeight weight: Double?) { + // works + let edge = Edge(from: from, to: to, weight: weight) + let edgeList = adjacencyList[from.index] + if edgeList.edges?.count > 0 { + edgeList.addEdge(edge) + } else { + edgeList.edges = [edge] + } + } + + public override func addUndirectedEdge(vertices: (Vertex, Vertex), withWeight weight: Double?) { + addDirectedEdge(vertices.0, to: vertices.1, withWeight: weight) + addDirectedEdge(vertices.1, to: vertices.0, withWeight: weight) + } + + + public override func weightFrom(sourceVertex: Vertex, to destinationVertex: Vertex) -> Double? { + guard let edges = adjacencyList[sourceVertex.index].edges else { + return nil + } + + for edge: Edge in edges { + if edge.to == destinationVertex { + return edge.weight + } + } + + return nil + } + + public override var description: String { + get { + var rows = [String]() + for edgeList in adjacencyList { + + guard let edges = edgeList.edges else { + continue + } + + var row = [String]() + for edge in edges { + var value = "\(edge.to.data)" + if edge.weight != nil { + value = "(\(value): \(edge.weight!))" + } + row.append(value) + } + + rows.append("\(edgeList.vertex.data) -> [\(row.joinWithSeparator(", "))]") + } + + return rows.joinWithSeparator("\n") + } + } +} diff --git a/Graph/Graph/AdjacencyMatrixGraph.swift b/Graph/Graph/AdjacencyMatrixGraph.swift new file mode 100644 index 000000000..b2047797f --- /dev/null +++ b/Graph/Graph/AdjacencyMatrixGraph.swift @@ -0,0 +1,107 @@ +// +// AdjacencyMatrixGraph.swift +// Graph +// +// Created by Andrew McKnight on 5/13/16. +// + +import Foundation + +public class AdjacencyMatrixGraph: AbstractGraph { + + // If adjacencyMatrix[i][j] is not nil, then there is an edge from + // vertex i to vertex j. + private var adjacencyMatrix: [[Double?]] = [] + private var _vertices: [Vertex] = [] + + public override init() { + super.init() + } + + public override init(fromGraph graph: AbstractGraph) { + super.init(fromGraph: graph) + } + + public override var vertices: [Vertex] { + get { + return _vertices + } + } + + public override var edges: [Edge] { + get { + var edges = [Edge]() + for row in 0 ..< adjacencyMatrix.count { + for column in 0 ..< adjacencyMatrix.count { + if let weight = adjacencyMatrix[row][column] { + edges.append(Edge(from: vertices[row], to: vertices[column], weight: weight)) + } + } + } + return edges + } + } + + // Adds a new vertex to the matrix. + // Performance: possibly O(n^2) because of the resizing of the matrix. + public override func createVertex(data: T) -> Vertex { + // check if the vertex already exists + let matchingVertices = vertices.filter() { vertex in + return vertex.data == data + } + + if matchingVertices.count > 0 { + return matchingVertices.last! + } + + // if the vertex doesn't exist, create a new one + let vertex = Vertex(data: data, index: adjacencyMatrix.count) + + // Expand each existing row to the right one column. + for i in 0 ..< adjacencyMatrix.count { + adjacencyMatrix[i].append(nil) + } + + // Add one new row at the bottom. + let newRow = [Double?](count: adjacencyMatrix.count + 1, repeatedValue: nil) + adjacencyMatrix.append(newRow) + + _vertices.append(vertex) + + return vertex + } + + public override func addDirectedEdge(from: Vertex, to: Vertex, withWeight weight: Double?) { + adjacencyMatrix[from.index][to.index] = weight + } + + public override func addUndirectedEdge(vertices: (Vertex, Vertex), withWeight weight: Double?) { + addDirectedEdge(vertices.0, to: vertices.1, withWeight: weight) + addDirectedEdge(vertices.1, to: vertices.0, withWeight: weight) + } + + public override func weightFrom(sourceVertex: Vertex, to destinationVertex: Vertex) -> Double? { + return adjacencyMatrix[sourceVertex.index][destinationVertex.index] + } + + public override var description: String { + get { + var grid = [String]() + let n = self.adjacencyMatrix.count + for i in 0..: Equatable { + + public let from: Vertex + public let to: Vertex + + public let weight: Double? + +} + +extension Edge: CustomStringConvertible { + + public var description: String { + get { + guard let unwrappedWeight = weight else { + return "\(from.description) -> \(to.description)" + } + return "\(from.description) -(\(unwrappedWeight))-> \(to.description)" + } + } + +} + +extension Edge: Hashable { + + public var hashValue: Int { + get { + var string = "\(from.description)\(to.description)" + if weight != nil { + string.appendContentsOf("\(weight!)") + } + return string.hashValue + } + } + +} + +public func ==(lhs: Edge, rhs: Edge) -> Bool { + guard lhs.from == rhs.from else { + return false + } + + guard lhs.to == rhs.to else { + return false + } + + guard lhs.weight == rhs.weight else { + return false + } + + return true +} diff --git a/Graph/Graph/Graph.h b/Graph/Graph/Graph.h new file mode 100644 index 000000000..085103b23 --- /dev/null +++ b/Graph/Graph/Graph.h @@ -0,0 +1,18 @@ +// +// Graph.h +// Graph +// +// Created by Andrew McKnight on 5/8/16. +// + +#import + +//! Project version number for Graph. +FOUNDATION_EXPORT double GraphVersionNumber; + +//! Project version string for Graph. +FOUNDATION_EXPORT const unsigned char GraphVersionString[]; + +// In this header, you should import all the public headers of your framework using statements like #import + + diff --git a/Graph/Graph/Graph.swift b/Graph/Graph/Graph.swift new file mode 100644 index 000000000..4e27e989e --- /dev/null +++ b/Graph/Graph/Graph.swift @@ -0,0 +1,59 @@ +// +// Graph.swift +// Graph +// +// Created by Andrew McKnight on 5/8/16. +// + +import Foundation + +public class AbstractGraph: CustomStringConvertible { + + public init() {} + + public init(fromGraph graph: AbstractGraph) { + for edge in graph.edges { + let from = createVertex(edge.from.data) + let to = createVertex(edge.to.data) + + addDirectedEdge(from, to: to, withWeight: edge.weight) + } + } + + public var description: String { + get { + fatalError("abstract property accessed") + } + } + + public var vertices: [Vertex] { + get { + fatalError("abstract property accessed") + } + } + + public var edges: [Edge] { + get { + fatalError("abstract property accessed") + } + } + + // Adds a new vertex to the matrix. + // Performance: possibly O(n^2) because of the resizing of the matrix. + public func createVertex(data: T) -> Vertex { + fatalError("abstract function called") + } + + public func addDirectedEdge(from: Vertex, to: Vertex, withWeight weight: Double?) { + fatalError("abstract function called") + } + + public func addUndirectedEdge(vertices: (Vertex, Vertex), withWeight weight: Double?) { + fatalError("abstract function called") + } + + public func weightFrom(sourceVertex: Vertex, to destinationVertex: Vertex) -> Double? { + fatalError("abstract function called") + } + +} diff --git a/Graph/Graph/Info.plist b/Graph/Graph/Info.plist new file mode 100644 index 000000000..d3de8eefb --- /dev/null +++ b/Graph/Graph/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + NSPrincipalClass + + + diff --git a/Graph/Graph/Vertex.swift b/Graph/Graph/Vertex.swift new file mode 100644 index 000000000..1223eb116 --- /dev/null +++ b/Graph/Graph/Vertex.swift @@ -0,0 +1,47 @@ +// +// Vertex.swift +// Graph +// +// Created by Andrew McKnight on 5/8/16. +// + +import Foundation + +public struct Vertex: Equatable { + + public var data: T + public let index: Int + +} + +extension Vertex: CustomStringConvertible { + + public var description: String { + get { + return "\(index): \(data)" + } + } + +} + +extension Vertex: Hashable { + + public var hashValue: Int { + get { + return "\(data)\(index)".hashValue + } + } + +} + +public func ==(lhs: Vertex, rhs: Vertex) -> Bool { + guard lhs.index == rhs.index else { + return false + } + + guard lhs.data == rhs.data else { + return false + } + + return true +} diff --git a/Graph/GraphTests/GraphTests.swift b/Graph/GraphTests/GraphTests.swift new file mode 100644 index 000000000..e6360754e --- /dev/null +++ b/Graph/GraphTests/GraphTests.swift @@ -0,0 +1,57 @@ +// +// GraphTests.swift +// GraphTests +// +// Created by Andrew McKnight on 5/8/16. +// + +import XCTest +@testable import Graph + +class GraphTests: XCTestCase { + + func testAdjacencyMatrixGraphDescription() { + + let graph = AdjacencyMatrixGraph() + + let a = graph.createVertex("a") + let b = graph.createVertex("b") + let c = graph.createVertex("c") + + graph.addDirectedEdge(a, to: b, withWeight: 1.0) + graph.addDirectedEdge(b, to: c, withWeight: 2.0) + + let expectedValue = " ø 1.0 ø \n ø ø 2.0 \n ø ø ø " + XCTAssertEqual(graph.description, expectedValue) + } + + func testAdjacencyListGraphDescription() { + + let graph = AdjacencyListGraph() + + let a = graph.createVertex("a") + let b = graph.createVertex("b") + let c = graph.createVertex("c") + + graph.addDirectedEdge(a, to: b, withWeight: 1.0) + graph.addDirectedEdge(b, to: c, withWeight: 2.0) + graph.addDirectedEdge(a, to: c, withWeight: -5.5) + + let expectedValue = "a -> [(b: 1.0), (c: -5.5)]\nb -> [(c: 2.0)]" + XCTAssertEqual(graph.description, expectedValue) + } + + func testAddingPreexistingVertex() { + let adjacencyList = AdjacencyListGraph() + let adjacencyMatrix = AdjacencyMatrixGraph() + + for graph in [adjacencyList, adjacencyMatrix] { + let a = graph.createVertex("a") + let b = graph.createVertex("a") + + XCTAssertEqual(a, b, "Should have returned the same vertex when creating a new one with identical data") + XCTAssertEqual(graph.vertices.count, 1, "Graph should only contain one vertex after trying to create two vertices with identical data") + } + } + +} diff --git a/Graph/GraphTests/Info.plist b/Graph/GraphTests/Info.plist new file mode 100644 index 000000000..ba72822e8 --- /dev/null +++ b/Graph/GraphTests/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/Graph/README.markdown b/Graph/README.markdown index 8e88f80eb..349add81a 100644 --- a/Graph/README.markdown +++ b/Graph/README.markdown @@ -80,12 +80,14 @@ There are two main strategies: adjacency list and adjacency matrix. ![Adjacency list](Images/AdjacencyList.png) -The adjacency list describes outgoing edges. A has an edge to B but B does not have an edge back to A, so A does not appear in B's adjacency list. +The adjacency list describes outgoing edges. A has an edge to B but B does not have an edge back to A, so A does not appear in B's adjacency list. Finding an edge or weight between two vertices can be expensive because there is no random access to edges–you must traverse the adjacency lists until it is found. **Adjacency Matrix.** In an adjacency matrix implementation, a matrix with rows and columns representing vertices stores a weight to indicate if vertices are connected, and by what weight. For example, if there is a directed edge of weight 5.6 from vertex A to vertex B, then the entry with row for vertex A, column for vertex B would have value 5.6: ![Adjacency matrix](Images/AdjacencyMatrix.png) +Adding another vertex to the graph is expensive, because a new matrix structure must be created with enough space to hold the new row/column, and the existing structure must be copied into the new one. + So which one should you use? Most of the time, the adjacency list is the right approach. What follows is a more detailed comparison between the two. Let *V* be the number of vertices in the graph, and *E* the number of edges. Then we have: @@ -103,159 +105,167 @@ In the case of a *sparse* graph, where each vertex is connected to only a handfu We'll show you sample implementations of both adjacency list and adjacency matrix. -## The code: adjacency list +## The code: edges and vertices The adjacency list for each vertex consists of `Edge` objects: ```swift -public struct Edge { +public struct Edge: Equatable { + public let from: Vertex public let to: Vertex - public let weight: Double + + public let weight: Double? } ``` -This struct describes the "from" and "to" vertices and a weight value. Note that an `Edge` object is always directed, a one-way connection (shown as arrows in the illustrations above). If you want the connection to go both ways, you also need to add an `Edge` object to the adjacency list of the destination vertex. +This struct describes the "from" and "to" vertices and a weight value. Note that an `Edge` object is always directed, a one-way connection (shown as arrows in the illustrations above). If you want an undirected connection, you also need to add an `Edge` object in the opposite direction. Each `Edge` optionally stores a weight, so they can be used to describe both weighted and unweighted graphs. The `Vertex` looks like this: ```swift -private var uniqueIDCounter = 0 +public struct Vertex: Equatable { -public struct Vertex { public var data: T - public let uniqueID: Int - - private(set) public var edges: [Edge] = [] - - public init(data: T) { - self.data = data - uniqueID = uniqueIDCounter - uniqueIDCounter += 1 - } + public let index: Int + +} ``` -It stores arbitrary data with a generic type `T`. The vertex also has a unique identifier, which we use to compare equality later. The `edges` array is the adjacency list. +It stores arbitrary data with a generic type `T`, which is `Hashable` to enforce uniqueness, and also `Equatable`. Vertices themselves are also `Equatable`. + +## The code: graphs + +> **Note:** There are many, many ways to implement graphs. The code given here is just one possible implementation. You probably want to tailor the graph code to each individual problem you're trying to solve. For instance, your edges may not need a `weight` property, or you may not have the need to distinguish between directed and undirected edges. + +Here's an example of a very simple graph: + +![Demo](Images/Demo1.png) + +We can represent it as an adjacency matrix or adjacency list. The classes implementing those concept both inherit a common API from `AbstractGraph`, so they can be created in an identical fashion, with different optimized data structures behind the scenes. -To connect two vertices using a directed edge: +Let's create some directed, weighted graphs, using each representation, to store the example: ```swift - public mutating func connectTo(destinationVertex: Vertex, withWeight weight: Double = 0) { - edges.append(Edge(from: self, to: destinationVertex, weight: weight)) - } +var adjacencyMatrixGraph = AdjacencyMatrixGraph() +var adjacencyListGraph = AdjacencyListGraph() + +for graph in [ adjacencyMatrixGraph, adjacencyListGraph ] { + + let v1 = graph.createVertex(1) + let v2 = graph.createVertex(2) + let v3 = graph.createVertex(3) + let v4 = graph.createVertex(4) + let v5 = graph.createVertex(5) + + graph.addDirectedEdge(v1, to: v2, withWeight: 1.0) + graph.addDirectedEdge(v2, to: v3, withWeight: 1.0) + graph.addDirectedEdge(v3, to: v4, withWeight: 4.5) + graph.addDirectedEdge(v4, to: v1, withWeight: 2.8) + graph.addDirectedEdge(v2, to: v5, withWeight: 3.2) +} + ``` -As mentioned, to create an undirected edge you need to make two directed edges: +As mentioned earlier, to create an undirected edge you need to make two directed edges. If we wanted undirected graphs, we'd call this method instead, which takes care of that work for us: +```swift + graph.addUndirectedEdge(v1, to: v2, withWeight: 1.0) + graph.addUndirectedEdge(v2, to: v3, withWeight: 1.0) + graph.addUndirectedEdge(v3, to: v4, withWeight: 4.5) + graph.addUndirectedEdge(v4, to: v1, withWeight: 2.8) + graph.addUndirectedEdge(v2, to: v5, withWeight: 3.2) ``` - public mutating func connectBetween(inout otherVertex: Vertex, withWeight weight: Double = 0) { - connectTo(otherVertex, withWeight: weight) - otherVertex.connectTo(self, withWeight: weight) - } -``` -There is also a method for checking adjacency, i.e. to determine if there is an edge between two vertices: +We could provide `nil` as the values for the `withWeight` parameter in either case to make unweighted graphs. + +## The code: adjacency list + +To maintain the adjacency list, there is a class that maps a list of edges to a vertex. The graph simply maintains an array of such objects and modifies them as necessary. ```swift - public func edgeTo(otherVertex: Vertex) -> Edge? { - for e in edges where e.to.uniqueID == otherVertex.uniqueID { - return e - } - return nil +private class EdgeList { + + var vertex: Vertex + var edges: [Edge]? = nil + + init(vertex: Vertex) { + self.vertex = vertex } -``` -Here's an example of a very simple graph: + func addEdge(edge: Edge) { + edges?.append(edge) + } -![Demo](Images/Demo1.png) +} +``` -This is how you'd create it using `Vertex` objects: +They are implemented as a class as opposed to structs so we can modify them by reference, in place, like when adding an edge to a new vertex, where the source vertex already has an edge list: ```swift -var v1 = Vertex(data: 1) -var v2 = Vertex(data: 2) -var v3 = Vertex(data: 3) -var v4 = Vertex(data: 4) -var v5 = Vertex(data: 5) - -v1.connectTo(v2, withWeight: 1.0) -v2.connectTo(v3, withWeight: 1.0) -v3.connectTo(v4, withWeight: 4.5) -v4.connectTo(v1, withWeight: 2.8) -v2.connectTo(v5, withWeight: 3.2) -``` + public override func createVertex(data: T) -> Vertex { + // check if the vertex already exists + let matchingVertices = vertices.filter() { vertex in + return vertex.data == data + } -> **Note:** There are many, many ways to implement graphs. The code given here is just one possible implementation. You probably want to tailor the graph code to each individual problem you're trying to solve. For instance, your edges may not need a `weight` property, or you may not have the need to distinguish between directed and undirected edges. + if matchingVertices.count > 0 { + return matchingVertices.last! + } -## The code: adjacency matrix + // if the vertex doesn't exist, create a new one + let vertex = Vertex(data: data, index: adjacencyList.count) + adjacencyList.append(EdgeList(vertex: vertex)) + return vertex + } +``` -We'll keep track of the adjacency matrix in a two-dimensional `[[Double?]]` array. An entry of `nil` indicates no edge, while any other value indicates an edge of the given weight. +The adjacency list for the example looks like this: -```swift -public struct Graph { - private var adjacencyMatrix: [[Double?]] = [] -} +``` +v1 -> [(v2: 1.0)] +v2 -> [(v3: 1.0), (v5: 3.2)] +v3 -> [(v4: 4.5)] +v4 -> [(v1: 2.8)] ``` -If `adjacencyMatrix[i][j]` is not nil, then there is an edge from vertex `i` to vertex `j`. +where the general form `a -> [(b: w), ...]` means an edge exists from `a` to `b` with weight `w` (with possibly more edges connecting `a` to other vertices as well). -To index into the matrix using vertices, we give each `Vertex` a unique integer index: +## The code: adjacency matrix -```swift -public struct Vertex { - public var data: T - private let index: Int -} -``` +We'll keep track of the adjacency matrix in a two-dimensional `[[Double?]]` array. An entry of `nil` indicates no edge, while any other value indicates an edge of the given weight. If `adjacencyMatrix[i][j]` is not nil, then there is an edge from vertex `i` to vertex `j`. -To create a new vertex, the graph must resize the matrix: +To index into the matrix using vertices, we use the `index` property in `Vertex`, which is assigned when creating the vertex through the graph object. When creating a new vertex, the graph must resize the matrix: ```swift - public mutating func createVertex(data: T) -> Vertex { + public override func createVertex(data: T) -> Vertex { + // check if the vertex already exists + let matchingVertices = vertices.filter() { vertex in + return vertex.data == data + } + + if matchingVertices.count > 0 { + return matchingVertices.last! + } + + // if the vertex doesn't exist, create a new one let vertex = Vertex(data: data, index: adjacencyMatrix.count) - + // Expand each existing row to the right one column. - for i in 0.., to destinationVertex: Vertex, withWeight weight: Double = 0) { - adjacencyMatrix[sourceVertex.index][destinationVertex.index] = weight -} - -public func weightFrom(sourceVertex: Vertex, toDestinationVertex: Vertex) -> Double? { - return adjacencyMatrix[sourceVertex.index][toDestinationVertex.index] -} -``` - -You use these objects as follows: - -```swift -var graph = Graph() -let v1 = graph.createVertex(1) -let v2 = graph.createVertex(2) -let v3 = graph.createVertex(3) -let v4 = graph.createVertex(4) -let v5 = graph.createVertex(5) - -graph.connect(v1, to: v2, withWeight: 1.0) -graph.connect(v2, to: v3, withWeight: 1.0) -graph.connect(v3, to: v4, withWeight: 4.5) -graph.connect(v4, to: v1, withWeight: 2.8) -graph.connect(v2, to: v5, withWeight: 3.2) -``` - Then the adjacency matrix looks like this: [[nil, 1.0, nil, nil, nil] v1 From dd3ba8df3f9a24d521192af18a61a07d39134451 Mon Sep 17 00:00:00 2001 From: Andrew McKnight Date: Mon, 30 May 2016 13:24:00 -0400 Subject: [PATCH 0383/1679] add project for SSSP with Bellman-Ford implementation --- .travis.yml | 9 +- .../SSSP.playground/Contents.swift | 28 ++ .../SSSP.playground/contents.xcplayground | 4 + .../contents.xcworkspacedata | 7 + .../SSSP.xcodeproj/project.pbxproj | 472 ++++++++++++++++++ .../xcshareddata/xcschemes/SSSP.xcscheme | 99 ++++ .../xcshareddata/xcschemes/SSSPTests.xcscheme | 56 +++ .../SSSP.xcworkspace/contents.xcworkspacedata | 10 + .../xcshareddata/WorkspaceSettings.xcsettings | 8 + .../SSSP/BellmanFord.swift | 136 +++++ .../SSSP/Info.plist | 26 + .../SSSP/SSSP.h | 18 + .../SSSP/SSSP.swift | 32 ++ .../SSSPTests/Info.plist | 24 + .../SSSPTests/SSSPTests.swift | 134 +++++ 15 files changed, 1059 insertions(+), 4 deletions(-) create mode 100644 Single-Source Shortest Paths (Weighted)/SSSP.playground/Contents.swift create mode 100644 Single-Source Shortest Paths (Weighted)/SSSP.playground/contents.xcplayground create mode 100644 Single-Source Shortest Paths (Weighted)/SSSP.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 Single-Source Shortest Paths (Weighted)/SSSP.xcodeproj/project.pbxproj create mode 100644 Single-Source Shortest Paths (Weighted)/SSSP.xcodeproj/xcshareddata/xcschemes/SSSP.xcscheme create mode 100644 Single-Source Shortest Paths (Weighted)/SSSP.xcodeproj/xcshareddata/xcschemes/SSSPTests.xcscheme create mode 100644 Single-Source Shortest Paths (Weighted)/SSSP.xcworkspace/contents.xcworkspacedata create mode 100644 Single-Source Shortest Paths (Weighted)/SSSP.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings create mode 100644 Single-Source Shortest Paths (Weighted)/SSSP/BellmanFord.swift create mode 100644 Single-Source Shortest Paths (Weighted)/SSSP/Info.plist create mode 100644 Single-Source Shortest Paths (Weighted)/SSSP/SSSP.h create mode 100644 Single-Source Shortest Paths (Weighted)/SSSP/SSSP.swift create mode 100644 Single-Source Shortest Paths (Weighted)/SSSPTests/Info.plist create mode 100644 Single-Source Shortest Paths (Weighted)/SSSPTests/SSSPTests.swift diff --git a/.travis.yml b/.travis.yml index 294f4e158..b0210d197 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,17 +3,20 @@ osx_image: xcode7.3 script: +- xcodebuild test -project ./All-Pairs\ Shortest\ Paths/APSP/APSP.xcodeproj -scheme APSPTests - xcodebuild test -project ./Array2D/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./AVL\ Tree/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Binary\ Search/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Binary\ Search\ Tree/Solution\ 1/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Bloom\ Filter/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Breadth-First\ Search/Tests/Tests.xcodeproj -scheme Tests +- xcodebuild test -project ./Bucket\ Sort/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Heap/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Heap\ Sort/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Insertion\ Sort/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./K-Means/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Linked\ List/Tests/Tests.xcodeproj -scheme Tests +- xcodebuild test -project ./Longest\ Common\ Subsequence/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Priority\ Queue/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Queue/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Quicksort/Tests/Tests.xcodeproj -scheme Tests @@ -21,7 +24,5 @@ script: - xcodebuild test -project ./Select\ Minimum\ Maximum/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Selection\ Sort/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Shell\ Sort/Tests/Tests.xcodeproj -scheme Tests -- xcodebuild test -project ./Stack/Tests/Tests.xcodeproj -scheme Tests -- xcodebuild test -project ./Longest\ Common\ Subsequence/Tests/Tests.xcodeproj -scheme Tests -- xcodebuild test -project ./Bucket\ Sort/Tests/Tests.xcodeproj -scheme Tests -- xcodebuild test -project ./All-Pairs\ Shortest\ Paths/APSP/APSP.xcodeproj -scheme APSPTests \ No newline at end of file +- xcodebuild test -project ./Single-Source\ Shortest\ Paths\ \(Weighted\)/SSSP.xcodeproj -scheme SSSPTests +- xcodebuild test -project ./Stack/Tests/Tests.xcodeproj -scheme Tests \ No newline at end of file diff --git a/Single-Source Shortest Paths (Weighted)/SSSP.playground/Contents.swift b/Single-Source Shortest Paths (Weighted)/SSSP.playground/Contents.swift new file mode 100644 index 000000000..ece36a663 --- /dev/null +++ b/Single-Source Shortest Paths (Weighted)/SSSP.playground/Contents.swift @@ -0,0 +1,28 @@ +import Graph +import SSSP + +let graph = AdjacencyMatrixGraph() +let s = graph.createVertex("s") +let t = graph.createVertex("t") +let x = graph.createVertex("x") +let y = graph.createVertex("y") +let z = graph.createVertex("z") + +graph.addDirectedEdge(s, to: t, withWeight: 6) +graph.addDirectedEdge(s, to: y, withWeight: 7) + +graph.addDirectedEdge(t, to: x, withWeight: 5) +graph.addDirectedEdge(t, to: y, withWeight: 8) +graph.addDirectedEdge(t, to: z, withWeight: -4) + +graph.addDirectedEdge(x, to: t, withWeight: -2) + +graph.addDirectedEdge(y, to: x, withWeight: -3) +graph.addDirectedEdge(y, to: z, withWeight: 9) + +graph.addDirectedEdge(z, to: s, withWeight: 2) +graph.addDirectedEdge(z, to: x, withWeight: 7) + +let result = BellmanFord.apply(graph, source: s)! + +let path = result.path(z, inGraph: graph) diff --git a/Single-Source Shortest Paths (Weighted)/SSSP.playground/contents.xcplayground b/Single-Source Shortest Paths (Weighted)/SSSP.playground/contents.xcplayground new file mode 100644 index 000000000..06828af92 --- /dev/null +++ b/Single-Source Shortest Paths (Weighted)/SSSP.playground/contents.xcplayground @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Single-Source Shortest Paths (Weighted)/SSSP.playground/playground.xcworkspace/contents.xcworkspacedata b/Single-Source Shortest Paths (Weighted)/SSSP.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Single-Source Shortest Paths (Weighted)/SSSP.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Single-Source Shortest Paths (Weighted)/SSSP.xcodeproj/project.pbxproj b/Single-Source Shortest Paths (Weighted)/SSSP.xcodeproj/project.pbxproj new file mode 100644 index 000000000..55893acfd --- /dev/null +++ b/Single-Source Shortest Paths (Weighted)/SSSP.xcodeproj/project.pbxproj @@ -0,0 +1,472 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 49763FF21CF08FC500202EA9 /* Graph.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 49763FEF1CF08FB100202EA9 /* Graph.framework */; }; + 49BFA2971CDF86E100522D66 /* SSSP.h in Headers */ = {isa = PBXBuildFile; fileRef = 49BFA2961CDF86E100522D66 /* SSSP.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 49BFA29E1CDF86E100522D66 /* SSSP.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 49BFA2931CDF86E100522D66 /* SSSP.framework */; }; + 49BFA2A31CDF86E100522D66 /* SSSPTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49BFA2A21CDF86E100522D66 /* SSSPTests.swift */; }; + 49BFA2AE1CDF86FD00522D66 /* SSSP.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49BFA2AD1CDF86FD00522D66 /* SSSP.swift */; }; + 49BFA2B01CDF870600522D66 /* BellmanFord.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49BFA2AF1CDF870600522D66 /* BellmanFord.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 49763FEE1CF08FB100202EA9 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 49763FE91CF08FB100202EA9 /* Graph.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 49BFA2FD1CDF886B00522D66; + remoteInfo = Graph; + }; + 49763FF01CF08FB100202EA9 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 49763FE91CF08FB100202EA9 /* Graph.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 49BFA3071CDF886B00522D66; + remoteInfo = GraphTests; + }; + 49763FF31CF08FC900202EA9 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 49763FE91CF08FB100202EA9 /* Graph.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 49BFA2FC1CDF886B00522D66; + remoteInfo = Graph; + }; + 49BFA29F1CDF86E100522D66 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 49BFA28A1CDF86E100522D66 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 49BFA2921CDF86E100522D66; + remoteInfo = SSSP; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 49763FE91CF08FB100202EA9 /* Graph.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Graph.xcodeproj; path = ../Graph/Graph.xcodeproj; sourceTree = ""; }; + 49BFA2931CDF86E100522D66 /* SSSP.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SSSP.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 49BFA2961CDF86E100522D66 /* SSSP.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SSSP.h; sourceTree = ""; }; + 49BFA2981CDF86E100522D66 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 49BFA29D1CDF86E100522D66 /* SSSPTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SSSPTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 49BFA2A21CDF86E100522D66 /* SSSPTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SSSPTests.swift; sourceTree = ""; }; + 49BFA2A41CDF86E100522D66 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 49BFA2AD1CDF86FD00522D66 /* SSSP.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SSSP.swift; sourceTree = ""; }; + 49BFA2AF1CDF870600522D66 /* BellmanFord.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BellmanFord.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 49BFA28F1CDF86E100522D66 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 49763FF21CF08FC500202EA9 /* Graph.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 49BFA29A1CDF86E100522D66 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 49BFA29E1CDF86E100522D66 /* SSSP.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 49763FEA1CF08FB100202EA9 /* Products */ = { + isa = PBXGroup; + children = ( + 49763FEF1CF08FB100202EA9 /* Graph.framework */, + 49763FF11CF08FB100202EA9 /* GraphTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 49BFA2891CDF86E100522D66 = { + isa = PBXGroup; + children = ( + 49763FE91CF08FB100202EA9 /* Graph.xcodeproj */, + 49BFA2951CDF86E100522D66 /* SSSP */, + 49BFA2A11CDF86E100522D66 /* SSSPTests */, + 49BFA2941CDF86E100522D66 /* Products */, + ); + sourceTree = ""; + }; + 49BFA2941CDF86E100522D66 /* Products */ = { + isa = PBXGroup; + children = ( + 49BFA2931CDF86E100522D66 /* SSSP.framework */, + 49BFA29D1CDF86E100522D66 /* SSSPTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 49BFA2951CDF86E100522D66 /* SSSP */ = { + isa = PBXGroup; + children = ( + 49BFA2961CDF86E100522D66 /* SSSP.h */, + 49BFA2AD1CDF86FD00522D66 /* SSSP.swift */, + 49BFA2AF1CDF870600522D66 /* BellmanFord.swift */, + 49BFA2981CDF86E100522D66 /* Info.plist */, + ); + path = SSSP; + sourceTree = ""; + }; + 49BFA2A11CDF86E100522D66 /* SSSPTests */ = { + isa = PBXGroup; + children = ( + 49BFA2A21CDF86E100522D66 /* SSSPTests.swift */, + 49BFA2A41CDF86E100522D66 /* Info.plist */, + ); + path = SSSPTests; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 49BFA2901CDF86E100522D66 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 49BFA2971CDF86E100522D66 /* SSSP.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 49BFA2921CDF86E100522D66 /* SSSP */ = { + isa = PBXNativeTarget; + buildConfigurationList = 49BFA2A71CDF86E100522D66 /* Build configuration list for PBXNativeTarget "SSSP" */; + buildPhases = ( + 49BFA28E1CDF86E100522D66 /* Sources */, + 49BFA28F1CDF86E100522D66 /* Frameworks */, + 49BFA2901CDF86E100522D66 /* Headers */, + 49BFA2911CDF86E100522D66 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 49763FF41CF08FC900202EA9 /* PBXTargetDependency */, + ); + name = SSSP; + productName = SSSP; + productReference = 49BFA2931CDF86E100522D66 /* SSSP.framework */; + productType = "com.apple.product-type.framework"; + }; + 49BFA29C1CDF86E100522D66 /* SSSPTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 49BFA2AA1CDF86E100522D66 /* Build configuration list for PBXNativeTarget "SSSPTests" */; + buildPhases = ( + 49BFA2991CDF86E100522D66 /* Sources */, + 49BFA29A1CDF86E100522D66 /* Frameworks */, + 49BFA29B1CDF86E100522D66 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 49BFA2A01CDF86E100522D66 /* PBXTargetDependency */, + ); + name = SSSPTests; + productName = SSSPTests; + productReference = 49BFA29D1CDF86E100522D66 /* SSSPTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 49BFA28A1CDF86E100522D66 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0730; + LastUpgradeCheck = 0730; + ORGANIZATIONNAME = "Swift Algorithm Club"; + TargetAttributes = { + 49BFA2921CDF86E100522D66 = { + CreatedOnToolsVersion = 7.3; + }; + 49BFA29C1CDF86E100522D66 = { + CreatedOnToolsVersion = 7.3; + }; + }; + }; + buildConfigurationList = 49BFA28D1CDF86E100522D66 /* Build configuration list for PBXProject "SSSP" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 49BFA2891CDF86E100522D66; + productRefGroup = 49BFA2941CDF86E100522D66 /* Products */; + projectDirPath = ""; + projectReferences = ( + { + ProductGroup = 49763FEA1CF08FB100202EA9 /* Products */; + ProjectRef = 49763FE91CF08FB100202EA9 /* Graph.xcodeproj */; + }, + ); + projectRoot = ""; + targets = ( + 49BFA2921CDF86E100522D66 /* SSSP */, + 49BFA29C1CDF86E100522D66 /* SSSPTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXReferenceProxy section */ + 49763FEF1CF08FB100202EA9 /* Graph.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = Graph.framework; + remoteRef = 49763FEE1CF08FB100202EA9 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 49763FF11CF08FB100202EA9 /* GraphTests.xctest */ = { + isa = PBXReferenceProxy; + fileType = wrapper.cfbundle; + path = GraphTests.xctest; + remoteRef = 49763FF01CF08FB100202EA9 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; +/* End PBXReferenceProxy section */ + +/* Begin PBXResourcesBuildPhase section */ + 49BFA2911CDF86E100522D66 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 49BFA29B1CDF86E100522D66 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 49BFA28E1CDF86E100522D66 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 49BFA2B01CDF870600522D66 /* BellmanFord.swift in Sources */, + 49BFA2AE1CDF86FD00522D66 /* SSSP.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 49BFA2991CDF86E100522D66 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 49BFA2A31CDF86E100522D66 /* SSSPTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 49763FF41CF08FC900202EA9 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = Graph; + targetProxy = 49763FF31CF08FC900202EA9 /* PBXContainerItemProxy */; + }; + 49BFA2A01CDF86E100522D66 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 49BFA2921CDF86E100522D66 /* SSSP */; + targetProxy = 49BFA29F1CDF86E100522D66 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 49BFA2A51CDF86E100522D66 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 49BFA2A61CDF86E100522D66 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 49BFA2A81CDF86E100522D66 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + COMBINE_HIDPI_IMAGES = YES; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + FRAMEWORK_VERSION = A; + INFOPLIST_FILE = SSSP/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.swift-algorithm-club.SSSP"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 49BFA2A91CDF86E100522D66 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + COMBINE_HIDPI_IMAGES = YES; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + FRAMEWORK_VERSION = A; + INFOPLIST_FILE = SSSP/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.swift-algorithm-club.SSSP"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + }; + name = Release; + }; + 49BFA2AB1CDF86E100522D66 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = SSSPTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.swift-algorithm-club.SSSPTests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 49BFA2AC1CDF86E100522D66 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = SSSPTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.swift-algorithm-club.SSSPTests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 49BFA28D1CDF86E100522D66 /* Build configuration list for PBXProject "SSSP" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 49BFA2A51CDF86E100522D66 /* Debug */, + 49BFA2A61CDF86E100522D66 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 49BFA2A71CDF86E100522D66 /* Build configuration list for PBXNativeTarget "SSSP" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 49BFA2A81CDF86E100522D66 /* Debug */, + 49BFA2A91CDF86E100522D66 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 49BFA2AA1CDF86E100522D66 /* Build configuration list for PBXNativeTarget "SSSPTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 49BFA2AB1CDF86E100522D66 /* Debug */, + 49BFA2AC1CDF86E100522D66 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 49BFA28A1CDF86E100522D66 /* Project object */; +} diff --git a/Single-Source Shortest Paths (Weighted)/SSSP.xcodeproj/xcshareddata/xcschemes/SSSP.xcscheme b/Single-Source Shortest Paths (Weighted)/SSSP.xcodeproj/xcshareddata/xcschemes/SSSP.xcscheme new file mode 100644 index 000000000..9d28c18c4 --- /dev/null +++ b/Single-Source Shortest Paths (Weighted)/SSSP.xcodeproj/xcshareddata/xcschemes/SSSP.xcscheme @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Single-Source Shortest Paths (Weighted)/SSSP.xcodeproj/xcshareddata/xcschemes/SSSPTests.xcscheme b/Single-Source Shortest Paths (Weighted)/SSSP.xcodeproj/xcshareddata/xcschemes/SSSPTests.xcscheme new file mode 100644 index 000000000..38b6c1697 --- /dev/null +++ b/Single-Source Shortest Paths (Weighted)/SSSP.xcodeproj/xcshareddata/xcschemes/SSSPTests.xcscheme @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Single-Source Shortest Paths (Weighted)/SSSP.xcworkspace/contents.xcworkspacedata b/Single-Source Shortest Paths (Weighted)/SSSP.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..77aa9c473 --- /dev/null +++ b/Single-Source Shortest Paths (Weighted)/SSSP.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/Single-Source Shortest Paths (Weighted)/SSSP.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/Single-Source Shortest Paths (Weighted)/SSSP.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 000000000..08de0be8d --- /dev/null +++ b/Single-Source Shortest Paths (Weighted)/SSSP.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded + + + diff --git a/Single-Source Shortest Paths (Weighted)/SSSP/BellmanFord.swift b/Single-Source Shortest Paths (Weighted)/SSSP/BellmanFord.swift new file mode 100644 index 000000000..4c58e4d90 --- /dev/null +++ b/Single-Source Shortest Paths (Weighted)/SSSP/BellmanFord.swift @@ -0,0 +1,136 @@ +// +// BellmanFord.swift +// SSSP +// +// Created by Andrew McKnight on 5/8/16. +// + +import Foundation +import Graph + +public struct BellmanFord { + public typealias Q = T +} + +/** + Encapsulation of the Bellman-Ford Single-Source Shortest Paths algorithm, which operates on a general directed graph that may contain negative edge weights. + + - note: In all complexity bounds, `V` is the number of vertices in the graph, and `E` is the number of edges. + */ +extension BellmanFord: SSSPAlgorithm { + + /** + Compute the shortest path from `source` to each other vertex in `graph`, if such paths exist. Also report negative weight cycles reachable from `source`, which are cycles whose sum of edge weights is negative. + + - precondition: `graph` must have no negative weight cycles + - complexity: `O(VE)` time, `Θ(V)` space + - returns a `BellmanFordResult` struct which can be queried for shortest paths and their total weights, or `nil` if a negative weight cycle exists + */ + public static func apply(graph: AbstractGraph, source: Vertex) -> BellmanFordResult? { + let vertices = graph.vertices + let edges = graph.edges + + var predecessors = Array(count: vertices.count, repeatedValue: nil) + var weights = Array(count: vertices.count, repeatedValue: Double.infinity) + predecessors[source.index] = source.index + weights[source.index] = 0 + + for _ in 0 ..< vertices.count - 1 { + var weightsUpdated = false + edges.forEach() { edge in + let weight = edge.weight! + let relaxedDistance = weights[edge.from.index] + weight + let nextVertexIdx = edge.to.index + if relaxedDistance < weights[nextVertexIdx] { + predecessors[nextVertexIdx] = edge.from.index + weights[nextVertexIdx] = relaxedDistance + weightsUpdated = true + } + } + if !weightsUpdated { + break + } + } + + // check for negative weight cycles reachable from the source vertex + // TODO: modify to incorporate solution to 24.1-4, pg 654, to set the weight of a path containing a negative weight cycle to -∞, instead of returning nil for the entire result + for edge in edges { + if weights[edge.to.index] > weights[edge.from.index] + edge.weight! { + return nil + } + } + + return BellmanFordResult(predecessors: predecessors, weights: weights) + } + +} + +/** + `BellmanFordResult` encapsulates the result of the computation, namely the minimized distances, and the predecessor indices. + + It conforms to the `SSSPResult` procotol which provides methods to retrieve distances and paths between given pairs of start and end nodes. + */ +public struct BellmanFordResult { + + private var predecessors: [Int?] + private var weights: [Double] + +} + +extension BellmanFordResult: SSSPResult { + + /** + - returns: the total weight of the path from the source vertex to a destination. This value is the minimal connected weight between the two vertices, or `nil` if no path exists + - complexity: `Θ(1)` time/space + */ + public func distance(to: Vertex) -> Double? { + let distance = weights[to.index] + + guard distance != Double.infinity else { + return nil + } + + return distance + } + + /** + - returns: the reconstructed path from the source vertex to a destination, as an array containing the data property of each vertex, or `nil` if no path exists + - complexity: `Θ(V)` time, `Θ(V^2)` space + */ + public func path(to: Vertex, inGraph graph: AbstractGraph) -> [T]? { + guard weights[to.index] != Double.infinity else { + return nil + } + + guard let path = recursePath(to, inGraph: graph, path: [to]) else { + return nil + } + + return path.map() { vertex in + return vertex.data + } + } + + /** + The recursive component to rebuilding the shortest path between two vertices using predecessors. + + - returns: the list of predecessors discovered so far, or `nil` if the next vertex has no predecessor + */ + private func recursePath(to: Vertex, inGraph graph: AbstractGraph, path: [Vertex]) -> [Vertex]? { + guard let predecessorIdx = predecessors[to.index] else { + return nil + } + + let predecessor = graph.vertices[predecessorIdx] + if predecessor.index == to.index { + return [ to ] + } + + guard let buildPath = recursePath(predecessor, inGraph: graph, path: path) else { + return nil + } + + return buildPath + [ to ] + } + +} diff --git a/Single-Source Shortest Paths (Weighted)/SSSP/Info.plist b/Single-Source Shortest Paths (Weighted)/SSSP/Info.plist new file mode 100644 index 000000000..d3de8eefb --- /dev/null +++ b/Single-Source Shortest Paths (Weighted)/SSSP/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + NSPrincipalClass + + + diff --git a/Single-Source Shortest Paths (Weighted)/SSSP/SSSP.h b/Single-Source Shortest Paths (Weighted)/SSSP/SSSP.h new file mode 100644 index 000000000..46cc4de16 --- /dev/null +++ b/Single-Source Shortest Paths (Weighted)/SSSP/SSSP.h @@ -0,0 +1,18 @@ +// +// SSSP.h +// SSSP +// +// Created by Andrew McKnight on 5/8/16. +// + +#import + +//! Project version number for SSSP. +FOUNDATION_EXPORT double SSSPVersionNumber; + +//! Project version string for SSSP. +FOUNDATION_EXPORT const unsigned char SSSPVersionString[]; + +// In this header, you should import all the public headers of your framework using statements like #import + + diff --git a/Single-Source Shortest Paths (Weighted)/SSSP/SSSP.swift b/Single-Source Shortest Paths (Weighted)/SSSP/SSSP.swift new file mode 100644 index 000000000..3d50731ca --- /dev/null +++ b/Single-Source Shortest Paths (Weighted)/SSSP/SSSP.swift @@ -0,0 +1,32 @@ +// +// SSSP.swift +// SSSP +// +// Created by Andrew McKnight on 5/8/16. +// + +import Foundation +import Graph + +/** + `SSSPAlgorithm` is a protocol for encapsulating a Single-Source Shortest Path algorithm. It provides a single function `apply` that accepts a subclass of `AbstractGraph` and returns an object conforming to `SSSPResult`. + */ +protocol SSSPAlgorithm { + + associatedtype Q: Equatable, Hashable + associatedtype P: SSSPResult + + static func apply(graph: AbstractGraph, source: Vertex) -> P? + +} + +/** + `SSSPResult` is a protocol defining functions `distance` and `path`, allowing for opaque queries into the actual data structures that represent the SSSP solution according to the algorithm used. + */ +protocol SSSPResult { + + associatedtype T: Equatable, Hashable + + func distance(to: Vertex) -> Double? + func path(to: Vertex, inGraph graph: AbstractGraph) -> [T]? +} diff --git a/Single-Source Shortest Paths (Weighted)/SSSPTests/Info.plist b/Single-Source Shortest Paths (Weighted)/SSSPTests/Info.plist new file mode 100644 index 000000000..ba72822e8 --- /dev/null +++ b/Single-Source Shortest Paths (Weighted)/SSSPTests/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/Single-Source Shortest Paths (Weighted)/SSSPTests/SSSPTests.swift b/Single-Source Shortest Paths (Weighted)/SSSPTests/SSSPTests.swift new file mode 100644 index 000000000..1bb862b74 --- /dev/null +++ b/Single-Source Shortest Paths (Weighted)/SSSPTests/SSSPTests.swift @@ -0,0 +1,134 @@ +// +// SSSPTests.swift +// SSSPTests +// +// Created by Andrew McKnight on 5/8/16. +// + +import Graph +import XCTest +@testable import SSSP + +class SSSPTests: XCTestCase { + + /** + See Figure 24.4 of “Introduction to Algorithms” by Cormen et al, 3rd ed., pg 652 + */ + func testExampleFromBook() { + let graph = AdjacencyMatrixGraph() + let s = graph.createVertex("s") + let t = graph.createVertex("t") + let x = graph.createVertex("x") + let y = graph.createVertex("y") + let z = graph.createVertex("z") + + graph.addDirectedEdge(s, to: t, withWeight: 6) + graph.addDirectedEdge(s, to: y, withWeight: 7) + + graph.addDirectedEdge(t, to: x, withWeight: 5) + graph.addDirectedEdge(t, to: y, withWeight: 8) + graph.addDirectedEdge(t, to: z, withWeight: -4) + + graph.addDirectedEdge(x, to: t, withWeight: -2) + + graph.addDirectedEdge(y, to: x, withWeight: -3) + graph.addDirectedEdge(y, to: z, withWeight: 9) + + graph.addDirectedEdge(z, to: s, withWeight: 2) + graph.addDirectedEdge(z, to: x, withWeight: 7) + + let result = BellmanFord.apply(graph, source: s)! + + let expectedPath = ["s", "y", "x", "t", "z"] + let computedPath = result.path(z, inGraph: graph)! + XCTAssertEqual(expectedPath, computedPath, "expected path of \(expectedPath) but got \(computedPath)") + + let expectedWeight = -2.0 + let computedWeight = result.distance(z) + XCTAssertEqual(expectedWeight, computedWeight, "expected weight of \(expectedWeight) but got \(computedWeight)") + } + + func testSimpleExample() { + let graph = AdjacencyMatrixGraph() + let a = graph.createVertex("a") + let b = graph.createVertex("b") + let c = graph.createVertex("c") + let d = graph.createVertex("d") + let e = graph.createVertex("e") + + graph.addDirectedEdge(a, to: b, withWeight: 4) + graph.addDirectedEdge(a, to: c, withWeight: 5) + graph.addDirectedEdge(a, to: d, withWeight: 8) + + graph.addDirectedEdge(b, to: c, withWeight: -2) + + graph.addDirectedEdge(c, to: e, withWeight: 4) + + graph.addDirectedEdge(d, to: e, withWeight: 2) + + graph.addDirectedEdge(e, to: d, withWeight: 1) + + let result = BellmanFord.apply(graph, source: a)! + + let expectedPath = ["a", "b", "c", "e", "d"] + let computedPath = result.path(d, inGraph: graph)! + XCTAssertEqual(expectedPath, computedPath, "expected path of \(expectedPath) but got \(computedPath)") + + let expectedWeight = 7.0 + let computedWeight = result.distance(d) + XCTAssertEqual(expectedWeight, computedWeight, "expected weight of \(expectedWeight) but got \(computedWeight)") + } + + /** + Construct a nearly bipartite graph, except one vertex only has out-edges. Then no path should exist from the source to that vertex. + */ + func testGraphWithUnreachableVertex() { + let graph = AdjacencyMatrixGraph() + let a = graph.createVertex("a") + let b = graph.createVertex("b") + let s = graph.createVertex("s") + let t = graph.createVertex("t") + + graph.addDirectedEdge(a, to: s, withWeight: 9) + graph.addDirectedEdge(a, to: t, withWeight: 2) + + graph.addDirectedEdge(b, to: a, withWeight: 1) + graph.addDirectedEdge(b, to: s, withWeight: 2) + graph.addDirectedEdge(b, to: t, withWeight: 3) + + graph.addDirectedEdge(s, to: a, withWeight: 4) + graph.addDirectedEdge(s, to: t, withWeight: 1) + + graph.addDirectedEdge(t, to: a, withWeight: 7) + graph.addDirectedEdge(t, to: s, withWeight: 5) + + let result = BellmanFord.apply(graph, source: a)! + + XCTAssertNil(result.path(b, inGraph: graph), "a path should not be defined from a ~> b") + XCTAssertNil(result.distance(b), "a path should not be defined from a ~> b") + XCTAssertNotNil(result.path(s, inGraph: graph), "a path should be defined from a ~> s") + XCTAssertNotNil(result.distance(s), "a path should be defined from a ~> s") + XCTAssertNotNil(result.path(t, inGraph: graph), "a path should be defined from a ~> t") + XCTAssertNotNil(result.distance(t), "a path should be defined from a ~> t") + } + + func testNegativeWeightCycle() { + let graph = AdjacencyMatrixGraph() + let a = graph.createVertex("a") + let b = graph.createVertex("b") + let s = graph.createVertex("s") + let t = graph.createVertex("t") + + graph.addDirectedEdge(a, to: t, withWeight: 2) + + graph.addDirectedEdge(b, to: t, withWeight: 5) + + graph.addDirectedEdge(s, to: a, withWeight: 4) + graph.addDirectedEdge(s, to: b, withWeight: 4) + + graph.addDirectedEdge(t, to: s, withWeight: -15) + + XCTAssertNil(BellmanFord.apply(graph, source: s), "negative weight cycle not reported") + } + +} From 6c5ed4bcd2b297f60d41be666b563bfa18b3c76e Mon Sep 17 00:00:00 2001 From: Andrew McKnight Date: Wed, 1 Jun 2016 23:28:53 -0400 Subject: [PATCH 0384/1679] add and update readmes for SSSP --- README.markdown | 1 + .../README.markdown | 125 ++++++++++++++++++ .../img/example_graph.png | Bin 0 -> 61490 bytes .../img/negative_cycle_example.png | Bin 0 -> 40648 bytes 4 files changed, 126 insertions(+) create mode 100644 Single-Source Shortest Paths (Weighted)/README.markdown create mode 100644 Single-Source Shortest Paths (Weighted)/img/example_graph.png create mode 100644 Single-Source Shortest Paths (Weighted)/img/negative_cycle_example.png diff --git a/README.markdown b/README.markdown index e3d9fd9cf..b433608eb 100644 --- a/README.markdown +++ b/README.markdown @@ -172,6 +172,7 @@ Most of the time using just the built-in `Array`, `Dictionary`, and `Set` types - [Breadth-First Search (BFS)](Breadth-First Search/) - [Depth-First Search (DFS)](Depth-First Search/) - [Shortest Path](Shortest Path %28Unweighted%29/) on an unweighted tree +- [Single-Source Shortest Paths](Single-Source Shortest Paths (Weighted)/) - [Minimum Spanning Tree](Minimum Spanning Tree %28Unweighted%29/) on an unweighted tree - [All-Pairs Shortest Paths](All-Pairs Shortest Paths/) diff --git a/Single-Source Shortest Paths (Weighted)/README.markdown b/Single-Source Shortest Paths (Weighted)/README.markdown new file mode 100644 index 000000000..af66b45aa --- /dev/null +++ b/Single-Source Shortest Paths (Weighted)/README.markdown @@ -0,0 +1,125 @@ +# Single-Source Shortest Paths + +The Single-Source shortest path problem finds the shortest paths from a given source vertex to all other vertices in a directed weighted graph. Many variations exist on the problem, specifying whether or not edges may have negative values, whether cycles exist, or whether a path between a specific pair of vertices. + +## Bellman-Ford + +The Bellman-Ford shortest paths algorithm finds the shortest paths to all vertices from a given source vertex `s` in a directed graph that may contain negative edge weights. It iterates over all edges for each other vertex in the graph, applying a relaxation to the current state of known shortest path weights. The intuition here is that a path will not contain more vertices than are present in the graph, so performing a pass over all edges `|V|-1` number of times is sufficient to compare all possible paths. + +At each step, a value is stored for each vertex `v`, which is the weight of the current known shortest path `s`~>`v`. This value remains 0 for the source vertex itself, and all others are initially `∞`. Then, they are "relaxed" by applying the following test to each edge `e = (u, v)` (where `u` is a source vertex and `v` is a destination vertex for the directed edge): + + if weights[v] > weights[u] + e.weight { + weights[v] = weights[u] + e.weight + } + +Bellman-Ford in essence only computes the lengths of the shortest paths, but can optionally maintain a structure that memoizes the predecessor of each vertex on its shortest path from the source vertex. Then the paths themselves can be reconstructed by recursing through this structure from a destination vertex to the source vertex. This is maintained by simply adding the statement + + predecessors[v] = u + +inside of the `if` statement's body above. + +### Example + +For the following weighted directed graph: + + + +let's compute the shortest paths from vertex `s`. First, we prepare our `weights` and `predecessors` structures thusly: + +| weights | predecessors | +| ------------- |:-------------:| +| `weights[s] = 0` | `predecessors[s] = 1` | +| `weights[t] = ∞` | `predecessors[t] = ø` | +| `weights[x] = ∞` | `predecessors[x] = ø` | +| `weights[y] = ∞` | `predecessors[y] = ø` | +| `weights[z] = ∞` | `predecessors[z] = ø` | + +Here are their states after each relaxation iteration (each iteration is a pass over all edges, and there are 4 iterations total for this graph): + +###### Iteration 1: + +| weights | predecessors | +| ------------- |:-------------:| +| `weights[s] = 0` | `predecessors[s] = s` | +| `weights[t] = 6` | `predecessors[t] = s` | +| `weights[x] = 4` | `predecessors[x] = y` | +| `weights[y] = 7` | `predecessors[y] = s` | +| `weights[z] = 2` | `predecessors[z] = t` | + +###### Iteration 2: + +| weights | predecessors | +| ------------- |:-------------:| +| `weights[s] = 0` | `predecessors[s] = s` | +| `weights[t] = 2` | `predecessors[t] = x` | +| `weights[x] = 4` | `predecessors[x] = y` | +| `weights[y] = 7` | `predecessors[y] = s` | +| `weights[z] = 2` | `predecessors[z] = t` | + +###### Iteration 3: + +| weights | predecessors | +| ------------- |:-------------:| +| `weights[s] = 0` | `predecessors[s] = s` | +| `weights[t] = 2` | `predecessors[t] = x` | +| `weights[x] = 4` | `predecessors[x] = y` | +| `weights[y] = 7` | `predecessors[y] = s` | +| `weights[z] = -2` | `predecessors[z] = t` | + +###### Iteration 4: + +| weights | predecessors | +| ------------- |:-------------:| +| `weights[s] = 0` | `predecessors[s] = s` | +| `weights[t] = 2` | `predecessors[t] = x` | +| `weights[x] = 4` | `predecessors[x] = y` | +| `weights[y] = 7` | `predecessors[y] = s` | +| `weights[z] = -2` | `predecessors[z] = t` | + +#### Negative weight cycles + +An additional useful property of the solution structure is that it can answer whether or not a negative weight cycle exists in the graph and is reachable from the source vertex. A negative weight cycle is a cycle whose sum of edge weights is negative. This means that shortest paths are not well defined in the graph from the specified source, because you can decrease the weight of a path by reentering the cycle, pushing the path's weight towards `-∞`. After fully relaxing the paths, simply running a check over each edge `e = (u, v)` to see if the weight of the shortest path to `v` is greater than the path to `u`, plus the edge weight itself, signals that the edge has a negative weight and would decrease the shortest path's weight further. Since we know we've already performed the relaxations enough times according to the intuition stated above, we can safely assume this further decrease of weight will continue infinitely. + +##### Example + +For this example, we try to compute the shortest paths from `a`: + + + +The cycle `a`->`t`->`s`->`a` has a total edge weight of -9, therefore shortest paths for `a`~>`t` and `a`~>`s` are not well-defined. `a`~>`b` is also not well-defined because `b`->`t`->`s` is also a negative weight cycle. + +This is confirmed after running the relaxation loop, and checking all the edges as mentioned above. For this graph, we would have after relaxation: + +| weights | +| ------------- | +| `weights[a] = -5` | +| `weights[b] = -5` | +| `weights[s] = -18` | +| `weights[t] = -3` | + +One of the edge checks we would perform afterwards would be the following: + + e = (s, a) + e.weight = 4 + weight[a] > weight[s] + e.weight => -5 > -18 + 4 => -5 > -14 => true + +Because this check is true, we know the graph has a negative weight cycle reachable from `a`. + +#### Complexity + +The relaxation step requires constant time (`O(1)`) as it simply performs comparisons. That step is performed once per edge (`Θ(|E|)`), and the edges are iterated over `|V|-1` times. This would mean a total complexity of `Θ(|V||E|)`, but there is an optimization we can make: if the outer loop executes and no changes are made to the recorded weights, we can safely terminate the relaxation phase, which means it may execute in `O(|V|)` steps instead of `Θ(|V|)` steps (that is, the best case for any size graph is actually a constant number of iterations; the worst case is still iterating `|V|-1` times). + +The check for negative weight cycles at the end is `O(|E|)` if we return once we find a hit. To find all negative weight cycles reachable from the source vertex, we'd have to iterate `Θ(|E|)` times (we currently do not attempt to report the cycles, we simply return a `nil` result if such a cycle is present). + +The total running time of Bellman-Ford is therefore `O(|V||E|)`. + +## TODO + +- Dijkstra's algorithm for computing SSSP on a directed non-negative weighted graph + +# References + +- Chapter 24 of Introduction to Algorithms, Third Edition by Cormen, Leiserson, Rivest and Stein [https://mitpress.mit.edu/books/introduction-algorithms](https://mitpress.mit.edu/books/introduction-algorithms) +- Wikipedia: [Bellman–Ford algorithm](https://en.wikipedia.org/wiki/Bellman–Ford_algorithm) + +*Written for Swift Algorithm Club by [Andrew McKnight](https://github.com/armcknight)* \ No newline at end of file diff --git a/Single-Source Shortest Paths (Weighted)/img/example_graph.png b/Single-Source Shortest Paths (Weighted)/img/example_graph.png new file mode 100644 index 0000000000000000000000000000000000000000..69674ba93310f0273b55d9f0bad95b203734e69e GIT binary patch literal 61490 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 Z;Qx$nUts}xEKdLc002ovPDHLkV1n{zi$MSY literal 0 HcmV?d00001 diff --git a/Single-Source Shortest Paths (Weighted)/img/negative_cycle_example.png b/Single-Source Shortest Paths (Weighted)/img/negative_cycle_example.png new file mode 100644 index 0000000000000000000000000000000000000000..e1cbc451c76bcbabf09bd729cc175f5dda83ed10 GIT binary patch literal 40648 zcmY&=1yCGJu;wnVi~C~1-C=PL8azRQCAeE~cXto25!~I~-Q8UR1edq@>)zE}ZBbjb zRWs8))6?DG*FA)*D9NCs5TgJ90CYK7DK!897y|tZLqdT5A{`-<4E=&L6aOF%093`I zK7WA+0K@=tQsNqJz|%HlH@!Lci!!RA@64Z5tmWp7jpUKwiDA%5hdwB%O;6g}t$cR0 zn;~JPb@vmKjY^*m;x=v$8lpv$lcX;!=981`xNZ3$I*qnBJ$+*#3quJ!riL>bOEFf+ z=GGC|xM<)XK%yKWjw!5}&^~cruen_}%kiG~*r?lh^Vo1j4-arF?hV8c(GuX`sQUW$ z`a<%lR7-W-0revT3lmd`B5h)yN)!LWNZHpfU$#`<#Y14EA1*I1DOqFf+ia|@t$+Uh z{X2Q5YAk~<)?WC?P67pt1Rg{M!Fh8^kA^cGEPbKg44)*r;E@ILwXO@~m zMG6k+y1#cr)|l|#%j8Q)jnmBCjEn*Es{z?@Vc@XX?U^YQaR~@8t~`BsebTH73R!*l zG&D475sC4r?_c1!9q%uPTkk%jgHIi3aYV;Ck{zwEb*t^+F5Q2Tv}9soDgZ#=lnC=hJ5O|e!8=FJdz zFPW#)enHPQIlmTlpLlS?TYvO6+z=-Uo;C24V3la2{VBoRg}B(D{E^tTvZZ; z%@e~6#?Vuf zW-esZ2_q>f3B1(edO>0G-Rf)-`vcZjLRfu>+a*OKI|m%$v!B`R_WC33!P9(&!5gzJZCQLA3?d9- zwI8f_4zn)O2m)Hp+w*~DZV)OH6O(3vArr)h6vdY`;;l@h1mDCPAEgn^kWi9{0MkG# zyoFv>RW<%HQ@;hc7wlv>jYA)bF9poiV241`sMq7D$L$xL{Jy}O5Em;dUnT1M?T~Cr zlLP)z4Rg31PUgXam33W~OpFrAh(NGV5mNq%V4N~E0)xi4_D!7wzY`(Jn&t8J>u-&T zKUS*GdvKmsDvv$})|7OR)XqUQ%xWAt$Ri zyH}3CW&0Cy!`aq78-tylrsjg}u`BhX!#xtz)V01r%`L$lpN)u}UMRv~adlN!&aMTm z$Ol`#BS!zWg};2~9uC*a!p6piXaT!Kvx3(TtPP)z;MY{mfsU&KLIi=+I-BKgZ*Pw+ ziMN&`g(^a=FznYQwR7mm5g;H(?{|K^x=p0#7+{D9Vt@$0NG!hNKmq_(q$58jCPsic zfcP+0wf5xb;f+{KMccr@pe$HyvI&jC9v7>bN43*6-XvFT9Ko;>Ed{?0l{>BHRC#*+qMw8j)W+P{M=YK%;^GtR_oDTO)F7 z-SeVMO0GSNcT(zgfPU8UE7C_m0KNpxeBk-J8ygpGqyeiM3ntTQ_`JUWS;b8W0W?`i z=G>Gb$mxZ1;)LQYl&PY1dTIXun^!LOPfloB%nQ!5Z$I|@=2wR>3$ENrYY>vg7gFk4 zw82O~$RXtsSrc7iZ0rlh$kT`BsQp<6M;2uJ*{U#)WL1NMj~W1cCSWMOSQllL^WBE8 zubijn6X4mMp}MVg4(W{yg89$oRo^^P@8H8qFn4)t)R>NaSFmt~>9)(G*0fo!wIFrh zWtC^rxc+t_h|h9E7_7L^1!fOBhNGvg0{6R~EzimLVEVa5uTAEiz!52~VP|emFM&*KTrPbi2(AkUeT!~0V}ZM(522taoY~#EscYOj z5=gUxN5<4b&!nxT_&un}j$IOb65Ojs-1up<@kAKShBVZ!%OfnKQ_`Iv3%d2KyTaP6 z-dEKj`hGvvC3J(gOC%}Rk$AAIMc`9a-4zrR@Z9sxsmc$6g6)MqA)^Jru~O5GHj&Lp zeg3@Sb49s7a<=P%n9}#Q%`aT|0tCklOkH}5{PRSb@}B%RLjgZPOj5s9CAQGn?W8De zxwHM8E5Bz~r39Q1IXuvy$sbgdde~+aotWFM?fJLH(cJ*PRoGC|PQi2#@9IT_HuVLm zWOVww+y9%8%jVyN%m~4Q_UZ&JI7sJw73Jmlm=VMzBqJ&T$U_lDsuy!}<7-Su0vTLi z8NT0jdWBN1+7v|TOk0|V)_;}z#!>JHct*1=TD1Y?nGS4;P1133nKS$yYGpwP)>2om z30SwI8t&*LV{hVspNXh_GUr?#(>+^#a&cU9F6zpWm=Dka`VMbt_VSe>KD<8*+>7)4 zKrw5c0=+Q1_fb0X-kfZa;*|4qb03dT@+w_(Z*(A{$R&9}56DyRTf74|0+!v+lHwQFIkg~>S9B%20DQ+3#x0V==6?}dFPMRuqns!2$F$e>ga2C1cZnzQ~Y_WrQ@-rL*RMQC^qeQ7Cn}GQ4~oVm2-Fb(c%{H6bKb9?;x5^m@hH+RGu=T`SL=R#u4yOs zaAX*wcdJfEAA(J<7wwfd#Y&;!RL-=wj_}b~sq-@XuJyCp+8bQZEB%>C)R9Zsk3wHq(f-7Js##s1#r)4#jXhbKdOGvvU6z}E-Z%4%Lk z;sK&eMVTgjqHNO}scftp4g4`8>CT`G+%ylVZ4Dt_JB!)!x+WG*K`cf67)A8YBY63n zNaT$EoSPA($*a`md~({a@IJFzfB`-BU7Ma2^x@NVdVaH^@uSd5{!1tNFr>eYJ|5*$ z;l7A$TUCUa-Ld%3$yf0|PhWH8DVx?365>$-G_K? z#O>$t=a%ek>f?R9%CtIxl&j)jySvCz`7L0rOo!(3mBzYLvktkp375usI0T&}t-P|Cu;INuIZJgEX{;jV^4hulqNE3D zu1YX-dt@$-om&qHh?7ZxIlXF-6Df8A4BgrxFx$a(;lp8~g`QmLcSgffNwzr{v=Tr# zN{k-qH<3M*j&wxCU7ns#dU2DzYomCIX!Q!j|()0nU9%X1268ujc)D?q2Kb+?1 zW?*1zzH9C*vsIm0PIeb!q5I+H!2gIY|fncJ;*2XWlVv!gee^% z?w?@XSuc|Pt5s;BV~dQF&A`ZW(K!Ehfz@J6I;XWed3JqWzc=5ON63)H=M3d%(oPTt zn#B=+9Ov7+)CB0bUgCKe%+Tby=~Vh>qs`7!erQ5`>RyNIIu0EULugNejBr5oIX6|O z$DK%?{>myhuG_q@C~m#*P4-%sh`k~Y%_=WMRo>1dX&S1&q%C?$h0?YrWR&$^a;0~b z7AcaBhK39?o?VfMX~`i;3rtUaSzG!zw#qhUyv~GbnVB-Nl~me_e``JXQj9r3jNqMM zqLvXUA~!&YjUjSx$S^!GC2JPQY-czw!M{77sQsz!nJI=-1%Fs-iJr=&Xmqn*VKB?r z8kuKY|KE~r)l)p)y5878SR55>=JkE%0~D3MRMI2vJ@2 z3YQE8Wl2xXQ?~e0VN``M$E(x7_ivlZRjzKO1S{uA;lujxOX%WS9fp@vUY-tT-zpaT zF1lu}FjFF6V}W%lLl|5Nu}Vs>9yuBg9qxd~Iv1Yi z)y`)AAm;-kjlZrqgs-?3D=0lze4fS+)J^hsKeV zWFJRk)!tFDARxlwGBH6%Tov5rr8xYHmVe@A6(6Z1I4Va2fMW&$yww~Su=>OKYfIaz zZO;rehALucvP+Pd`&4_HvQI7#J^m^)kbfQmBKs@Xkkj8U75W!-#G*>qCea7Szl7FYpr$H zBftAVZI$7lWMuBUSPP9P9C>?q%J;6zxi%b!iEiA%Mn^atd2!hXC;`$SNzQQ!>0CoH zH5UiNYHPJ>Mh%x1mopupim~PwNsFr(*n07mud9E<{~BUj02L;1Cm$RQk}|>dzRce5 zXmKw#I(%XGrC^1p91hs*YaBxTP_&CC*ud`LWTt`#$?*%d`2DZne=Bze!89B*%M1~Yauddn&J7`gpZ8H3{klhHSWP=jJ7#=*!TUg)q0z`EzG(X5&Yr z`MoS=roTgjgR<@%isnGd1t6#&KS1>B{Hg9bNitqF(^u^%gxw!SmqOgltwktr*#}_y zViw+9^IF2MCCZf^D6eN5uVnyuZTn@5AN+|eeh-pU#F9;n8$*xOjx?&OKPp98b6%JX2!zp#FG-%L^Z4(uFiWpcJL9Y*Vzj+8jf^~d>xgdTMveKjb5w5Pzs5~! z*Gi{hOu5}dKBLX%`59X8l7PYBD3$DH>37(Fgn83~u%lt*9m=eJuTHr+n8?6KYH6?m zBuDl8b(zX-Dw~^|={0Y{uex~fkCOcT{b9r|@KORFgJPTum7^qgBSf%p;1CYjA!|)> z!xkw0pSlilp1Ux7R4QFB)&mB}eT6vT|DrRpe~^gXc)e{Pn4O))t*xz<3W(Vm`4t7V z8X@~lF@8U-_x8;7j*$gu66pqGz!j*yLDwYxAai(gcSqp$w6YO%Bez_(>*~U}@x0F` z^SE1>s1&hJ*!G=i$=Bq!$d=dQ$B%lu27X~;lrcYLmJ0Gr7=1(2t6ug>o&zj)HyZ2= z{CC}T6FI+AR}3CUTIoqNIYq)Y3&<`B7202YVWbkL6Q0UgI6 zJO`bmXmdo zZEH<1uoVTUnGTN=utW7RIqjoM-R z>yWY!c2ny1VSe^+WeB+=&m5J8Dfrv$5omEhxkJkouN_EP2E(8i`;GNcVU{odmqg4= zlXE^vKU>* z>d!h0ifw!=6Lcpy99^n%RJvg4IM!i&g(8clI_&A1EWE%qx8t^0U|JS zi?h;@by7b>{sop@Y8pg7(g(Hb;VF=5>0i0;zU^j=-ooe>-tpt`fDLhf@wS4IWjw7m zK3j|5B6-hLG4hs@@i9|7vst($ixN5j`a$!Aa2Q9QfD{RV7{em?V6$xZ;@p-NK^V+< z;d8kLB2K}8)8?N>1b>l%hmEK_uY0k}R5p&%nSbSUpnhy~h%P7UJyn*|IKND4hwNwg z_P~vob5|-p7Y~G554sqOY7rn}bEJbbTAo(O*@r+skV1rB8*b7bACi>!J8}N44`P)f zpO&4p>I6>6F#>!S+&Y6A&bX}wbrvtP~zETm-F!|wFA8O z_wV2McV~x(VYXJ5mJzfaSx~!)kEwDZZs7iy6NY@4+|4nX!{L#mx?TKpd*4BBcI(j1 zhy?&IZ<0?GzE4{bevC3d#F*CN@N0d_Q7Hv|04Jfk$D22W*DiJ)41y-$Y5zB>S5h5W zo2AZi=>O`zYp%(pNfhYyeAd6K)knPuR}e^nhJ{k;Z7A<#Q@o8)AjFsLILuI|Q7vnb zj=~2TLa|(CU>_4?39K!mprD_<(QvuoV$fhvDyJ4#n!&r6x*yLHe1fch(0dDW&RhPa z<`pNDAa*~f3hLF*xzGM3I{NYUn1DG~cHl7KR<|wh6%%uo%>hklqENZkGXdb2xB^n3 zUvOsB@~32#OZo&s8AfKX@RLQIyx4{VaQ#_p79Un5U;1JqLniixwmA4AB>}c-fzBn2 zw3Czn$fi>L$n`k+M#arpDYG z5&mz4A3J}M^Z2fn1An$$j+8ju>U%2s403U0t}jO9lH;K3f_sTCy3||)j?mPUD=g|U zIhj-4#mP&tQP|#4^&f)BujVtt$bpXS>{P?*C(I|K?^0aQzT{H{PP_NZm^%mw}!B(*F|3$iY=KArIb1>Z=A!3v$ZhOX|0!gI+ejJls8;CZn5@ z;M!+!r$88tv=%B&l)Oa!5S;^E9b?NLn;yORX6OH5OpH&a{@lnF{}~YXsx6V2k+eNk=h1C&1bhRB%yo* z5MR02%D)%+DGEn)IQpuy?}q%pa0{9hy`O_+-)($0(rSYy|61lXQ*?=;=hUhYrK6L; zPn_<koDD^E!n_v>0U5uQI&W0({~;a_a@B*G$c4nQa192j{J zu@HIO#p4LMA?Hfn0t{eGO0HExX>SASc@_E6ys&#oB<{lW+QFu7xUIxqkN$9$8zYWq zc)--~24e=anDOj0Uj^)|-aB?iV;Jt1X+H#Ya+wrU;y4++|j z4v@2nl#W||H5k9n#cukVObjm9El(}miFc75H0_hlXLSqhwFqJpmFH9tzw?FQ+23l^AJdJ;*!5nZ$?~p6aONh2#4Wq&;4dG7Z%!oX1j!SEZqpr^- zxu~dI)Jc{$ePa+}u{X5%C&2X8if=}R2!CG8n}d}NJanH2!)<&#lu7*e}9L;oev*A2tQAuY9SlYzMT*l zcvZRHov%sKvnurzHYkSc=vy+JF4tMz2NUQY26h;1EvEv4^`7o7E=nYX#F_ulZ2m6)36Ja92gfbH{Ia|FD@@1AJ+%M z!on(VidgpW-CMk;`K#~y@;4N)Kbbr%TyEzIH5KS*Kl#Mq!cvSf^_F6P$gKXm*U>>ZAdz54dkv zi=uDWqIdu3+L~LTQHZXyWfi&4{nnr39PsRV++z(9~faPkgfqYIKq%AXf`UFT#$ms9%I!~96y2FrPvtQ)>9c6$mY zezDQgI2xDV<|lo%FY+EqG`-We(6X+m!-qM#Z|tN*v+&NjIiBh6>lNqOBQpm@U7~Lf z6BV1v$^azZD>GlYsJwVB$%HgXAPUQ<10)8{4Tw^S4Hpy+t(m8tDLJc>?Hj@ABgVz~dZ{EBFC?ZF-( zl3qalV~Q?Iw}p7q2KJjl+C=Xnzc$*@m5Z};G#@v29DUTI+_&jz(F6lb!Q;T6Ch~qvNY`ig`f3c&myHFZKVXbP2KH`?@AITmncxkRxX7LqC9M@5ctU3Jj%lkkO$Z3Nbbd!%XPm7Z{wVV)k^kA=S?7U@9a6Kz z6Sq9HGDy1T3=l1;@mk(e{jO@_wE#!s{^gVR-x337{UP=Z#1YCIVl}jr2wVF1Qv_M= z`{^aB8p*X==-(V?(Mj^^8snmhmZpw&8v{Lc5t*S5$QZrDv_x4T9aqp!r4q>ko?Ftv z^fdwjQyWzJ>)Sh+dKr7F+V<+|YAn(1h?JC+f@|;<7U6ET-{ky!$bq?WR1}oL?abY9eg%jyu!d_(;c?KY9;w{=Y~D4UC%kiYT91^*gbz_;>t^~*&jy78j9W80r9n)CBzXo0w0DE|gcDe9zJ&Gn zUhpg3Lst$I{uwnc&TuzrRei8lkDby(`+JWo^5e&W zO#XCM7-P(PH;z-gM!(YxVDAs7GSkHv-O=<503$zAJ3UJIjPsbF5l;J-c1!+jSeiIxnL)kErum?aKEoZUOg>;s?vligs^>LFM6wKau*aAnw8evxe z_&orj?{l)ikng0uC{GIdjm|;}cdAqa7dsuG%TiSXRu9VwtT?g{*P^@ru#rQ+W&PPm z^>n+H`m(6o*9_emiABYB&~N`wm#-Ch;AZjI+eZjKAS#x>=j|l3{*UL5*?=OHdsfN; zCl1YcIcS*Acr|P)+^u`s(L|h{3H=Oz?wHZ~4TPg>z~y4D!FE-rG!)N}2WQ_559X%A1G#tI z8_{dj)v4g71=HJKQW)1jKLdlsusO!qSjkUWEMVt&W=_o{KTML9(&^Sz|{8T||Voq*le7qKm|$B?C65iV$l z&q?CarAJpmg6Sg;u^9Jo$R6k8k=~+}t+f03`}q3lnL{ym7bhWEC0^`k{q3g$ACH_5 zMrlWEDZ4G-h(_UIM`YcjDG4R3PUrJh1RTI~Q_VVNCnBjI(SMX+cCtJ4;c4DnKZ_VJ zo;!Rpg4Y;p5?P~tZCEXmFMjfF#D~NogMOv~;f;d#geC~P5n|xsWGI(z-z~)7ISBEP z=4FAdv#jpFO%Y{Y!^A&}944Y2CjJUYKlc&vvMnyvN{S5uvv|Buzy7=_u}iWBY0>>?0Y5vx2&vP z+m`pZB5K>)cSp~yJ%B5QAo^+Uv- znDRd4jCwW$Be%GO8vR}9Wq-<;PSdc`b%c6;emFDDo*JK=@5!8KSs=KP>+cmf3rrbx zO;n3x9P;L_+=e!~apE2!q3=nTqdVvpTOk*jUH&HQq(4}m+A3Qm;1MF;og#!ow_27T zyL1Dl(8qPc_?zKmXU=P~--K_u zA$+$gIfwI_^Xy)>N97t5xbgI+P<8UzBSEeCkO;Q(239iL8=RZP-#X~RE5VxVaQd^r z2ydRvi~QDMLSJ_X5g07)<2p(XJ`qo>K=kHJCrK9_FE!1QeE8-GfC=s;`&1D0uL&#K zmbC4x;VMmscuJdBpq+fik-`Ako;ro}f=BeX;4yet5SBI-!MaY3Qe9YEOi z1@PNX7sn%wQ+O!QqspTlsB!}|6qTUFxOxG`(4}-w#BRHe%cAc&zdstFSB5qDMRO78 z`+4)j!1aXa#+Y{`jLLH?>)^45(x=?~L*>2f(4-8o?DMIaDAU91T}MZXIR3?twT4Tj z`}X$=W==vMbL<)TrAW>S%GQTo%0@RHWKt3)?k&5Zex|;QCB2WmZZQ$poXzwLvVx>J z0~&E4y9`l90cA2QOmhyJidD>e921DMSI1649ocD@RIKv<+uAnee{f{=Yv<2q)oG_ z%m)mJ+2KnhhyMi zfMS4dUooc>esS^n%<7H^vhsD?@OkKND3Im=6P!1|J?N`AYSKtLF=#&RNYU7aug}w2 zlfh6UvVk&u2IKwtr`3RK`*l`(lkGIe2TEs>IdRsq^JTu0JhH*m)va(JHpA1jNGmm@$445fG4U(v{Oh20UW}EGEiLlj_L|{DEDe*{)?FRP4J{w zK}Eq^RE`uKr9Jx@@V7bpv9_9eKxvzwih;>!ej?McKuCyaTJNuttf5O5oo6IWh428v zA;k^+PXfz8)8h|U&aw_WekYV!F3T20T7^GUZqZu>SB6O2e|I-f)kmxfOMAU>*W~Oj z#)mCfFIAghETmAeNaaWslufe1T%yYaOfw+iA$V7nGQ#s z9a+1QfNrwEYf2x{FOmlxv}tjC5}l({(ns0j`FAeN7rF^-CoAi>^~9wi?~j|JJ?7PA z)e%<$|pXfFOXT0(a?MMXv~5Zu@t+MUFWM<+Fq%Qg_{Yt zZ1MwR(1B%4%(O#m?Yv*uMUz4+@sCUQ9WA8hNZrX1o68Vwvep@~J7__~PI5wE&yF-E z`5T^iTh7z!f%S7g7_M8LlI5rAak??g7R5mU8Tko6mo9-hI`4>rxH#Xm{$N^woZ+PR zZcPaV3z{#ET8zDzN-m>IuddEUbYU%~-qn8SZauOlnhPcOO0eXEb)^19KKd>DsHf^z zR3YDbi}FXQg_^%p0{DbCQl;C=M6Z+s<=4B!=Fs!Ze|*52G45gN+|VBVE+PG|^T+Z% z_R{AUg&@<@%{6etOjtCkB711}nM~r3Y>#6&CrsU5yMRBlLkHQO<2LeZ0$gXeX|db2 z^ds4|;Bmo=R%h;cTH-6S&A@pLI3Fzu&8|cx+Lb2e0o{|v?2Xlo-Y-;+D{_W+|qKo!@@}KgYBqz!_*>Q$HN#b5mGx@1+(@a?_tNq>tHr7adp0G zuv@xsS9d&LPb{@?2LYw$qZ1I()AJVY!)+XGV8DXcFKdN_yJGQ_p1AE%;Cd0<*|1>^ zz66)CzU0%g-1)h>UMY}P47V~R-toc@G`W65(`36yk%hHZxs)9P#XxvT50arj6Xz?B zFfXPuQ*PXj%>LYK#P^G|?XlP~^mX{q3h#0KiYkbd7ry zy-pA~btP$Q5+v%IRb1`Y5}%d)zE^PPkc02H`)79dI*KC`{w&}X_B#rhE((JwSXSs} zQWCEeu|D3>%HOs}?Q+cn2=C7F@HaX-y1tIS%6jC>YRj9S^W(?%H{yqa3|LuXyD zKYgrD4zpK^q=JW%3+mh&+Eya%%!3;VKa$N$`TfXi&}MF}iT9Vdv!zhXzcpKZ-pCKlf26xXg-+k;pxNx|Wef5I ziNnDU?9t+|s>A%P>VdWB4iW=jwwxM0O(%tsZD6^~uJklsOTYx#v=?3$#rP_B5`@+( z*(?9J8_ScrQvV$Qu3_C6gNHfbICSOdB=v}3r;G`|RS6pT3B*W*e;?-y4$fh8I!&gH<^kfH<7H;&)Ax7Q&8R1>Tk-aP{q8%p28^7-8=t!e zd~_>j8`v(}%1?RpS(F)+*oYiDoYA=QfYvy}(xqY}lffYw0Hk`73`YNK(*j(#z{ zC`rCl<@slT9+&0!EN4Zr_0@PMP9>iX|A>7#=IU{OhG2RccBX0vOtdETAFHjy1o_wv z?QnKnlf_)~PI)>>7!W*9Sz=OyzwAy-e3G#A2Qfoa!7F4E%3ZOJ=%qLMK3CwH3(i0_-MlR z#%t={l7FW0TC_xM4xy7c*+e)*IW)*)le`o6g-7Q7LXE8$W~6pIdf;G@Y!jCv0n6R_ zXRcNBb6V3XSzr^AgR%Fg6#n_nPC|HOsTkxZ%J?*Sun2GFgsO@Tso8Is&sUc zfkIbwZjueIrlGVSYuPwto+ZiM2OQ>kxrC>kmER8JTF6W2yYZt^ve#FHH5hszS~c>! zF;i)OYEL{D9t$ec8`W3~z-WSxJm$LGqLBWO(8q=<>lq|vkCJvF=7!;ZIVl|WByuq`A1um zA*gG2jR?~o_R$n(Voro-bDKP77N0yXs+QtJH##v=f&2mRbI9zqs!oA@FPE~K@lP^* zLYJMeb*vTf+YwE+0v)MBsh=ca%12BJhc4=vTgmRxajN+ljP{!w+iV4jbDwJgdZMLz zCszgJFNeBjLuO9Nl1rvT{#u{WZXAaz(R|P;7Q-ZJG_7KJP zxK?36>cXf&wW5q2U0c4xr0{z`bF9N;MdB#x3 zu>@F$^SP!bC9LSB>=JH0z1IC@xstZjogoe+rE5N9(1gg-X&RT-5l4MD)tbx`r4gvS zWcKoxviEOZ9t^3sY7sNJyQy!voqKWHoj?}&G6_M&Buy3eVs-$xL>)yROSpElH> zzsM$|LWtXz9F653M3O8_s`ro5Sz$(sUl>D64Y;`d13v$)tMD#+4nSok+s~zk<|=jkc>!DtR&W>%`(&bA z7rJUh3wZl+eDK=W!myjN>kiTBLvf8j?5DK|fP0FIKAE@^lH9pg625Jv zZ$-0joxjiPSb7^H@(zi%#hCqpsWOzqBWnfolRNyjq^$#y zBv^t0DDIPFrs{oK?YsBldgt5B#1CvU8D*3ex$zyt$-6uq3TxLRue5(xmM&>8&auF0 zhw~ue56V}{dCD-@togS&mBZzT8lsgRe~)?G2h!3swX856Y@}m!P!GgT@?xnrFy5V* z<@mlnRL)9|nq(er4`36583MZvBDW0`0!7!&sR)*?$r@U9Q;AIyEkyQ5uQNx31TB#I zww58~WxL=|%Fa6fYkZHay3vF(P>SSjq%M)g-WR;a)ggpIlUh9#PjbJCqDc^h&>U1S zT5XW2pwq2|kfW+$!hL8EtUhk=lR}iX^G};?p}db1>x1oin~fYlxJMKRtb)&0Z5Aj# z6#G*{g?cWC%3;$&?BQ0%D-p=CaWNMO;oxaCtnON-qK8rPJXA+4SaVG3Vd$7{kFB>A%+ zt+;KwO4}$F_+U)%;?T(tKMO?G!q^@`mQak&0j|6+$!JWDB7+4m%4S^?Ma}RE6UbQ? zTW`DoP=~_#YNAamM%k#QJB;h`=3c6S$c$G~5u@dO4)fkWBP4gLoyUk68nQ&lpXuC0 zJFM-f4cxh*F2Ra%Em(YfVHu!=dL!04Gzd~Hsb4^GT7mYru_k6G>{KcA4VlmUFw|e3 zpO_z@9p4rVfY}naTb<5TnmH0Tnf@fA6a%J(m2_NzTKDUH07@jKAK1ebx+0ESSYHQO zk0X8WS{00_8~3~LRI!?eJGH9^AvURu0s0E+wx1jU_BhrG^l3rdh@i$)*x@&s%WHVI zXN$q~{fj-UV0!SwQh)C+w!|O)ZXjih2Ga=G02t0koS*Pb&mt4T-MRiPamg25u4w~K zkkemr47LZi&>B2i7i#52UcKz@fX}LV*I5Vgxlc^#GfTBPh z1%AkAgprJ?6xE;Wgr|gfVHDNikh>tG{3H@>)~pn=n5jy zL)a;_P|^>4$3-~+lH-wXe;5xB+57th4R+teauC6JYGDxE%cIcD|bVO>xU_9(>TH zrUmJ^zC{KSUVXYrFS*Cl)O8@FxEHu#2Oc5XQ@v2NEsBPeZ?C%399XZ^k7-HCqHg-l zYeL^?Wuz6l09)I!U-gkH-m+!Z5mn5~yq}s+$`vMV4LU`GbM^%hVc2&)Q3u6dj;d%Y zpk1SqXz5@ve(4m+<0_NK4kC%AR_L2H`H*H5P?uwx;KbT+Js8s-PK`^{E2203_0I9FW z=)Yj+Kez6rZ1Wm=exsl8`Bhg3?Z-7hH1tiq??MFli~2XbNxfn&ygqjN!@lKw`kY-w zqv49hkLmXXD?P(5cHYtO-5d~iUgY@Pyh!Ov!lMq4zS`8Y1<)&RDvJsg72*RcXKn&S zNCsFNGYl&Hlw|_GHXHPJqVug{nr4vaq;ADPA6fuz~0`S z&PVH^CTx)*CNpk9x7C`nbNbZ)p#$jn88zKWe(3#Z5PSuxRRI zvMbID-j@d76|BNVlK>-K#Ej{1=l`V7s=>kUhh`2JnKB2GY^5q#_!_AA#olq1G%2qu zJ<37Qz=QON0ex|*E+L^G_We?N<}?k2#q7Va`Awo=e#>8#AJR0Et~C_q27>Wc30CD9 z`Z*qd21#EG*I@&K(RH*ht>9aaw^Mkp+D6qE+3e`91;B_P;{@2QuY=TlJvGI9fIkSX zZY>xznuy6jQ1p#Q#g2}s{~XDpYH1e7V~dKL(ToU%GAl}4ubGm>1BrP%vi?W$35hJf zUSU5Awx`%2VYaJ6VP-QPSaxQ*yX)N!^|lqC5ItG|kS|&;cUM2On<`7;D>^ zM`6(A-(2B`Xc7Q(YOgTPc)!~kJE&%OZ$~bvhImyt6lBTD1+{DD8o<@jg#!b6seaod zE3Tn%#Ke$Y^z7Svb31qU2WQqj^sriSnX7QN02rz$rQGqc##Iq}2|q{}~l5s||Wuw3y&Wi{JCR64c&bRPWd0gton|jCl7vz<_3J(q34G zk$79`ljhaYg&elJ2Gs!Uo`ea+*T^izW@LJFM!x-@ZrhHiJ9;A zN+scZ0g`hncbso#wgX#AZ_4B2BPgJ9jhW=En2SFH4*q_VH}k{gwkcyXNac|B;@$nT z#g*-Qa`-#d@p`}0GA%&JY4V5h6tv*OunhcQL>fhR6D!I4%*1WjHWqe`>^}%=n(xvlEDW? z`reFwkPZk(;QxfXaK5=b6bd5!-E`TF8tE8~8~~#bI9px0$)F|IV8r5;AaDzdqO5Wk ztA3ZU_n~}FaF!0*T7oa>Wt{9p1AWHTh9Pt*2K*E3f@?%6{|Ajp-p>P8zGky_MoAEf zM*Xfo8xdyBX+l`@H!8A~oI)N*=fj$-nrqn)Tjt>QMNMuEiur%DmG-5Q1iw8lbhKjx zyHN=rU`Po5nu9A(%BZ3^H@CKa4u(DqVDzKBwV4xWg;GYpObfCWRFuo|Gx8`8Esh_t z=A|ANcVb2VhpD%WimPd&g$MV+-5rAa;1+^Qa0m_|ID@-;(BK3Qkc0=f;O;KL-QC@} zC-1%ATHkLLXIiSet9I?$MZp@jY&Ba|E>lTl#@4pX^xTapE&{$;2H37BsY6x>bOvvG zg!!QbDNr7IAW@CjDDo92c4tw7*@Puu3_R%u`w7lXPdYniS64AV`tz`lAeb3yvLJ}{ zWHevx!ih&^4iFCar6pH8;3{a}1X~aB$&NzSz}e8FvU+W2isqfBVntY!5`dj?f})GK z1Zw)!m|CbJJm>(T61(0nh!2-=>C;#DoRIo=^W~GFw~rGckp=Y}uZqU3oUP}d@>NDG zJH5oJ@eF_Aowy=kHG=~O!_H2i4uhHArv|&hk~QUPZ!#GIX>lK)+V2e%|L6#SIZJCt zQsdE#!hom-tBG5;=cWqU!VLm- zEXB#*tsoQK_M^JQDK|{7|CIsu5LL_In+O}zLFNQ<3nNy7 zo!L5^p${>oMnWN8B)v$O6n1&br@z)mc1hxlLlN@t14w z(?Ow;`NzdZVeW( zbiFi98c2GZQkDfVZ?=~Xf*hA>tu;jV^mv5zS;Ax8$-W-S{U^-4C-fV$WRJwEL>p@@ zOoB%Vh1mz#M{1wXxC*J8AklNDTk+E$^(S9TvzfHv{)`bhNIvlU@30sbdt^jSpA4s3 zGh6kppW0O0CD)|3#J7;6{m8C%cTv^umr0HF+K8|D3fw2v3S{}5{p%8mf!9!=`0{CD zVuB!bya7>07~a0;dqc?Q5=WO4YSxI)q{Z6-H6t=*+UT{}-n_8zNK9KZJ@|h_Zl*QJ z0kY+jY~06oDDWnhK!72Z^kAd%z#$oMSjWihHmP-$mlXOipJ>~_u#%j$zr8l?RFXZ9 z|6_XJ6zh$i7OPcg!MVx74>vnSAt;(6ZtQmG^ff6^n=8iU@yzWAX4E=o7wW;VePRrM z6LT19>R547By$+}0;a2Ie|?k&2o?3snf8(}^%Jyn@oyx_m-cE)tF1m2do5p>Go}|7 z8smyYPS?c^@y_6f=uBi>IMXj$GQ+O=kRcJ+a*E8!MK2sH>9Bz&=f4t!&ks(s7Kw?r z7q^PfC}{6QSTrh$s?}NZ)%rIp?N}$c7M2%x>@#K=ap9^ z7q-Ls#OYCY8pR;)24o{fs+n>(S|;6H^BG2iaUlOKy8<1`zSEXu$uIqb%(NE6tc%W5 z&FGsEOV&}u3vUZ>1w$Ev!?E+6% z_AGqi9I{&SmcGP)_TxFC9L}PDqF+B3EY~zB9Zurr%}lIG_a(k^Y`@YZC6U9I!3+FH z^8H!n4>?ja^%5P<5DyC&8GLebQlJaY)&-ZVEGD7e9x5d;uu_5G+zClX# z)Xv50^lOb4iBqO~Z$1t~N`^u+H^*R>(w*SU(O(kCapoSTimY=O#u3musY}WROt`4> z6E+872y>+6@2b%DCGoDbOT#djb~B4(JKN){7F1bi!^AqBKFrZ}krZz%2wWJG-mm@5 zhYOs-0BN!m6y$ultNR8*y|B}`Vy*Lb#npuM!xRFc5Wt3ksA8q69DhhUqhEYL{!*(28vm8)Bz~J{qxa4m!Gu-7@BaSa2^07to^7p1 z-dJ{GF6X)b<0@$tjoACuA^656rjFoSk>91IrKZ=DNM1Rqg9{VXp#5%;6pIV9yTfvW z(|k3nzD##WO$wZQrGP}-2ktQwQckQBD|#163BtsaGqi-$pQcQeI`2r;*Er6u8*P5#{pFx7F9KmbvoTtCcV`ktD3ML>Djl>k7X9M`urn!8exrL>N{{~@fC zA8VW4knjO0Yfq^WbZb8u`X*Kb=kFoKdIT+Bf!=*z3F z#AW-Jmky|TxswE1XGe8v$6Owa+)>97Y+%yjDmn^!J0@|+Jj?-br2?Q9OD_&8pE3A< z@+y6J=_o5fip)W_gK2evMy;vRI0(kWtUDH}s^k924>46BHiW<)zYIeM>AP>jgVxN~ zS6SMnxO*P~&?Jv42>=N}utDXtF8FO#>=l{Ea-N2^U2e58lAeyUKSAhvEZ@~CADkti z5_;`wT3Rz063-b5+3S^0a=9v}L|58vPa=(?&E`MIe-@u z{#;=$M&gdF%;7yseU3Iw6uWGQIk&(eKKFi&HKZ0ZpWa@U^n7W&$}|^Ypb-LcADL z&L?k3V3+3D&Q9Y=|9r5v`F9|}rG$-K%Zq?fhVVuHDYH}=@PqXyLxb6p;ez3Wi(f*G z{DmdXP?g~vih2ctBKvwOgJX8_=|^| z)(hCVLmZ-I2knk@vi2z}+0H0MLsUqhh)G$X&Nd>3!aJuf zRsj@cSsHYANf_2c7B1*$zPYGViI_!o$Eb!j8&n`02cnBJvk7VICMbyL&OwFJ6!Icz zzV;E4eSQ3t5O}VdAkV^!0fy}ooY1!-v>2f-G1t(h0~q24dlHw=SL2j0=vi~?WJq`N zkpw(j`biRjeEDt(Ig`f>!dnwmsZyB*@p2(Bc+RaEBPIUt0^}7t=B3yQZ`9zlr2C4e zwzmaj8E>TYL=)L`(dC#5pVvX`dDy{2YjDW!Q%@Y-TGJyJy&xH8g05mR;nJJAL0QO~ zNTYDy3y%+klFo=Lk1S%A=|RO~a^!6p5&{0;yDqV5Yy70&`*?GtW6njS zYE?MZHV~qVdcyqGKsGS^2_leGVb+e+xk0Z%L)n0Ln2rM8=TEG~F*9c_WT7ySw^j)i z*%LH5YcDH1QP!L;s;TIC$0T|22De9En)oOX^WK@FdmJW`q0NVJE+PXYFcR!zzx2oc zNx%&EF-jV!YViX1Or}_5Z0Vk6IV$NHbcVM2`@HGHB-fze;MEccp|2U#+*a5#`m}t~MbnF`*?0o`V%MtFo zJie5uv?-~Y!5ibL-{G7NygsQgek~2klG!hnqJ0Bsxg$M6p{>4v&XA-9bKW*f9*rbS zQH2{Pv>QW!jLze|dg8(;5|rg+t05c7!<(a@C01U}Zm}k@F2#VFr-#gP)AyczmMk*5 zH!tNJDZw_@F1VJ!AtFnX2zaDw$@0D!f8`GF^YZfI8G03Rs3sQ$yI~2>2TiT{%xLM5 z!=oEr_z+H;pA>SyAlquBO4F`yE-FL}#PZa_fyYDXxs5viKoh0OB13xDl{96;G^Jrf z2txXun1p-Ltpy<_6>W`;jj$lA@T?AP7S^e*E-c%bCgP=3M4@+;Al^FQ|VTbKs3 zG|$j8Ez_me_8K8xCE4j0{F%1$av*O=oOD+y&`k&vrq3GT?0>fDtt0(3JTxRW!em$HTt|jtmm>LCI>trkmieMf=`&G3o@dq{} z&m>S)?VfhP*&qM%QAQ0o{1uy^p~ler4tb^kxKV-p9>a=V!Alhb@w>bcpM}%E8NXc= zM$G5OU&nK|WZgtcG>3z9yKl1Y%mtS_;v7y!zRlzRdCbE7)IF*<5@d&fxP{adOD9Wt zfJ6}pkLdGHLaQYhj%gQP7X?5;zAmu|A|R9vv;U5z{_O|AgJJeoV<;U}qc>{-Z!ahY zAMMFPFr)rHQ0@u6Pla>%b*jkGTD#u%bgEcUF1YuGA`Zy+5r8dNI3c_<8Nb@**TRo? zZX}HYv?>#9sdu=5i*c7G3xxLl;wd25U~Vf~9~C~QK7YgqOa|d(xx;Q3wlu5BfeA11 zM;tE5$+XL4&vc@l9ashM3tMFOdI5fZcMzRy+(W{-%(?_RB*DHT!JS&GL)b%@`~G+U z%g4K1jYtB9A@rIXNv*5*xI*nirQl)|hKwN`733>hH6GD_i`@yDOB2Bw00G5kT=ed~ zlxa8cvvXo9+?#dYr(rXWI}9YKE@yK$TV+dA_!qn>Gi1px=~zJJ z0~Q_$3CVF?^PkC4-x~1Fvhu17$Lrtil?Kn<9Wn0*VFMg z!E>BEU1?T4s1ksMWi!CXdj}Kc;B1cSgN(>A1V50xGtpl;4_{s~o7}sO{2O*p2}C5H zIzF#TEDH+>B_NdrTMW~24O0{GO0=WBAYLo)pHY>C1GiD!zmp(mbMl?fR)yLhD*W|6 z$#)?>*dI3G9)kL4$r={Z5Fht?z>5?UxENh>xHS@ekNox^?NEh#)gEID_2-VhoH6j+ z2m|LJ18Q&Dz>Y_E&Iez>e-R`#;rA-FEhfN$yrYh&I250Kf7ir?gfBr<43B$BU2K&L z#4YNEat#i(c!zm2fn6%eRsL@dtO!W&SiKbhK<9rnt@b!=?$#V6`{P*VCUvFgU@qSj{Ps&oR0OQ&7Pv_=S|9R4ocF1gw zxAnWM%x|qT1WB0rsS^a&5F{J}oOj?yFZ+$!%{#O%cTM4Ol#mbT!N{m&DJJy1i2~9X zOdEVm>%RnN)%TmW6BUvZ0tM0iT3cHM)W#TwoC!5mv7X&63< zfJJ@gK&nO{+Mclbs{GeJm`2UhFfFkht_;m5LUB`ZH$Y0C0hrWvpH7|uc{-LJ>Na0s zP~JqJ-CjA{r$6(Oy0_cNbVJR1(ZX~( zQE(bQyF4qTZD?e=HekB_&pH!Js{@n);W_vGcy`Qf&xC3XbBV@|9Dc=Ue1G2#-kF^g z8ts#mW|o2Ug&Sw%Xj4ut!d+>*4ajv(85scwpmbXzD^QZ9Q{J%&oo-xu$P^4@YPnkN zRzB#Xj@h|uE>irCHT^+e>Q~E1x`(3sGn&2WcP7H^B6E#!?~O#0B*u3Eja{Tb=!=9$%oR_A2<*~dfX zrTcQj=37n+Hx`M?l%{JKoYSL9aB(8r( z!-U?5h^}-S^*6RUtZ<*)_SHAfqTL!g*hfZIoL<6PCr@Qux`u?hlx2`s+ zycj|-|5Z`TJBF1;X9_&?(d3QJX$t(%SpIAADfWf58X;y?zmGulf2pm7Zy` z>$S@-e*sQP@e3NkIB=jq(;XMUw63^q1Tind!vJ+IApi*LNH7f#?;p*DyUjU~;pzFi zk#qX@`1n@r(w#Nj-DmB#Ywrzn_)2j|#7IwX0RdF25v+1p@ToXwi(pwP_83d&jGJ;; zqv^Z?c#Hm}C3LRn4D=Ae^R|EP>^K%zd1ashJ8+<`nTGiP3j*D?rR7^?+z->0SD4N^ zIwKzu9C~BiIM3gpOt=Sb#*K}suoVE;P<8M>)JY2c!4TPJ`1bpWXg7+-`;vMcjDyTG zD&3{gF{`Q?yq|J>50ml!t}!yNO~1cb2%f))9ia*eH#zmkk-M2rwlW)_{Tlw4DjM#( zJ^z&?XyUkF#4}fmry_Urvtna0_51hlD`(zw&CX_jIB(>+8Mh_?Jjl4m(48-JvToWV z_^1Mg%;7WNtZL0}qO>#M?dfU*SvFnm+r7KoCE-75cEI;)TE9RxaTv32|2r{sQB^79 zc;C`F=~e)e#&ZF|uZWw0zM6rzG5&$k_LXFpPb<2oi%2HA4k+6fZ%e|K2a%Z{!|OZ3 zlky8&t$hCe`^c5y?3h-1#XdaJ2c4U<<;E+oJweXR!;nBTW;aptN4&iIDgf(=<-79p zzc*a(_Zm0TbsaA^E48XKCEq+xvqvF`oJ}JG9Y3qPn8J{f)}RlWn#e zQDQ^G_Y8-M@^e6x_6HlU9IYeCqG8I*Y;+VyyGwv?(&G1_US#eb#&snYyVzu%Qzzn_!5gA6ebCka@G_YBB7_!&BCS1 zv;KYr?rO#b;9bqdG|3>8ikGB^$c9&-fbo5z51EpWeSakLT-a##TT;cg?`@x42_Nh8eBfq7s^^#hjIQIp#d zfuUGNxsIoiuOQZQ+C|EWui|OqxWhMn3>0*g(o4_DMOcN31fw(k)Ub(w(|y`GNg;T_ z{||t<#Kv2fOom4ShoiigrLBgnqUD0SDev;31fDA|cWcJ990ipB#MJSZ>f3ZkNqbMY4xLfN?FQANKWgzUofmgkvm>q(5_6Z{ds$pe43&A0@0OF`1;3M z8Wse~z~xrXYO>05n+$p*Hb--fVzr5RCzDB^=&CI_2LfF+rZD(0@!;eq9qI~Wcs7L} z9-m~;H&EFSyxaFK8M~SOs1{u73kG~Wl781E^KeBZu9=f}A7BJPGzfCOcsax_4T%0P zIL~C?0(?CvweWZW%xwUIBvnDX#X35K^zO^bhr|+3Ay%y-n$OE-l>$%eA(-WoQ3usu zSrINx@s|8kNEFJm2W`7y@YaX8a74)L0nYKxt`+^BAQ>Gcts{tOdEAuE;n#mAf@C2< z8<)WlAhnNB#lbJ`ZgnV}&%M8tfLlyPdUg{tZkQ*~Od|f^b9?{`-h)FdVB+;KwJkz= zhHtLGF!F!cDR}mf-;@J#S;^8g!q}dVz%@YvSGJT{{2E z-BuFqj#TTuNa%bsQG+Q9C;NG*|2{Z4bHxG=@3?g_x=tW^)0r;T-^r&jBC9k^-S!LS z9yLD2ob-1DBm)~?DD<4O3sb za0=t0Hk3p3B&T`Qkc*b=7_jiziS{mD^B=mG`eGY zZihFwj0poXr~M8N@B79@kw^hn2N8VWQaa?Gb8mRt&)hlXMoiwru743jo|PCsAjvW zoW8TG?yZiFtnHB1YDK~5Zn1PJwDqqhhg)o3;F6qe=X@_!e_XeRYMAt`dt>UPC*t^U z|29Fsv@SZ*4jVeOXNt2Q!N4~7d)3(NGC*5N8DgL$#yiX+2IfZ1<2&-_*Y9Pm%S2SE zBU6^bDgL4$X*CGBy7d}zvE6CttyKTX#$RDWdDR=(Q+&MDFz(9$4~df)u}6l2ByipU zd{_ea08ID;7<>DTkU|e(O%W7sDY4Q1jgp#@8gcS=LK^dhc8zjueJxye2OG)voAi(} z7$V*|X#UQN83UD!9YTMc@*}wx@4MIcR;{JPf>W3XnU2 zk4i9vQynQfMqZIuCd?h7MM{A#m*J!ikbw_!F9ZEB@I&v>Bo%?vZZfLHEw2JaPK8rK zwzdS^k@O7l#>X<$6`2M7{H1*R39h;O`g-|_E1iRHIT4!+W{!Aj_lzCu)ZT^0eZlwN zTeWkrr?{Qh6BXG7Lq%T0X`bmD&OcjRb8Mf5mz(DdI$o{ljW9Y5I0N7U&%bfU91k9F zd@<*uJN~@5lx4xJ2{j0vvXe!eCQ>|T>vlXgF&edEMk_fHaJ_yq$-{0%r`>8XH=`17-3 zgH=T$n;^^aXDK$O6x83y2!ByL7C&-69cLpdQa>%C28wkKRKB2tIsLc4mKqL}6X|Ke zUY|Cu^!O98z}&2B4~boTmWk>T2`|NxcE^`eGdVccU{2{K7Y~-=+JA-%mvJ{^TOPjw zaG-J%W{b3WBP|jG1@^3a5O*oUz;J>oZ7qJse7pO}qIhrFG&u4Z-Py_oSUg!E3A+Ix zok3(K*B?=Ee-07*ABrFdEEaEHqT(r}`P-(Bt@_-|=tRVtnoStgk}>Uq6w`=Qp$9IU zVon6rr8FMxF?5m#?%~wJNsIE|fRH~39v6uPd6p2ioCP$)L;=_S--FO)wWlutRX|WH zK+!^jmmKCwk69*0QQdXsl#XZ}c^1-NA%Qf^oxM;TQH6-Y)%RN!Qc)tZt0)r7v5rmk z&CN?jR&rdM68|zSw`;GgGUXu#DRtOh{s~+Do3eAbNmyh?=_%v=^h~tP(5%37$VchV447Cs+)I^wjc# zY?<$2A*Zcq&X|E>+VXDV5ea5}K>$Vp;6`_h`v{~ia#U*?gM8G$T_ZC;>L)+Y$mW&p ziTQOSUU<84^ZWx7d35nQq>Lw9uN=YDxl_JgzwEqzG9^7=`#rrGd&p;ww!A>TN*H=- zCf`I@t)%t=FGkBt{$zPf7DM>E$!bL#Qv{QmLYPg|r6}AP+)#pR(*2Xw$kMw_)P*L1 zc?J&5=UMB7NlW0Wdy{`!1H~UxHU3H0hE2m!Az=l<`)6*|4i9j+_SQ{RJqmdpmmPx8 z6$ImP74nGavDrF46wInu5?YKiRpUYVt~tGX!)~O$3L+)caYeM&ulf6!?F^-qF$txt z$QvjoG?UvV9{EJ^G@eN_=xoK}@9iVggCee9>HFqsOe7wLD}J++H9OlsLZW0&2ukP! z9aKgzQM$GMPK|aOsF~#Me!%PEfC1 zUM#3IH}LVJUGDqUdUL+4uJsW84r=vq!O=)_P4JNy(du(^4_nB&tVA~d1Gy{mtLTvM z6_dbDkG?73J7_OA222tL0E#(9OpzZ*T+#T9WaImZ$5yuOuhVa_-n)?b$_f5&^ZF~d zt!i<&1$Oh63PDgS$w7K+Qlx)M-QOZ8{UK+pNP$kU(0L?d?apYY)ri_*tESYvI;!}` zb<^DT?9-nOhG+!R%XFzhm#C<>s3+tDTfa}fkK+ea&R-oxf6S;$&{NlZ3cjVvg7lh)+~^3*VhlijCdX_ACo;S z6+e)gun;mVbRWEgW&x0Z=2;3Q*U%S)AF)MqNx57&AU zm3~LfD?j0P8Bn-E!Y1osf_Igo)j%w-Yedl^sjIGyfLCo!Tx-AYHS>6|pP*kf_m@5g zO!M>XfqnD?QP6w7S_%PqH1hC14OP)PPobUk=$H*ddG1mVA_-Ry>4KQwR^xX5sZ1z65S)Si0*ca&;xhVbHFRq zD`z`w=FTm)Mx?KFqOmtfPz|D(AQvPiSgfpemWO!KXEG0+G0TV*RAz@nZF7 zMa+Kc9YLh5W(l7K7a#?4K=YAW$RQxfKC=5Kpc#r{rfFZx=rbvp4=UT@QpZso#Fj_; z-Hto^Gn(9U6h9o(lcQg-JIRELtUzmfU?;Ry#K(tsbsU7abRN-k+{;e#RHutRx1>1o ztts5bA`q@N$->Re4YRq z{#JCOX7R15ud6&4OeT6<} zUdeXGvBVH5=(;5}6-L8p^|3tU$4h~=D#rbki$5&c8L}s2Lu_%(8oK?>R*_g|o%1{2 zX`SEdR%_!l6rk27@-oi!isD;UDqmau`I`{SqA7K9{a7AU{y9gg0>gJowaaw9<0E*2 z|6ezVI;36?J_#tFv6WtVH+>_9tr=-SI>|rH5`5W!giIvb={xKHZh6nfOg)|7OK^G} z^X*6Aq{ZpuPGWGqA$MT8z^Lf>db^Z^8*|QnP*B9`DRvqele!QJ3MW)CoIf zLLvZ+jVuk$ZcV6bKg)etfimx|MTTC!+2*I8z4=12u&%9QUONBkx|?h_P*1qmfS}t) zx||!_`p*4o_4p^zm@34^RD)9XCe}>34#(K)X7w|xP2ZakNV-q2$rrQs&XOaJ@K2O_ z!&uwV;N7=+bIIDJr>z_lX4c$Dvxo88jEkY6A$HgNi*S`i4N7}!(LGYNn18UCxYwj; zIio}4PO6s2s@E5Mdnf!m9qvTt)TZ#1Fj*KGxY2H$8$vRO@4@m}3u9_a-Yojf z;8KOvZxkQL$H4p(&aNmsBv5DxN{qeNVev1aXG6mxfZLIs!evKE$xwA`zAx#6pnKwTv5+Eo~7t?zN!HH z=4k%k7j4y#Px-%fzMRGR^jQrEemS%(mUC{?WpbBY+xIvtIBN(MGS9i!|AnI4@PegxsTE*WnS~|eAjnmyJU*Fym zL|*%*SvUqe1^t{@INHrQTb}Djpa98XF#XA%i4n7DMudX-` zGd~B!IR|=-^EIe!8!komdQ;BWZLdTNW!84@zbLsW^;zXMH_Q$_>@*k)0Ya6fQlmdT zPP883v%lpzgt3Ym&Hw#dgUT`po+rd-bZaE?n+iWVrt0=$+$>cs9iIkjHRVJu2WaV; zUh#o2>{QPnyhAgQ@1E<8rC$d5l}Nehsl|Vj|X0!Po*tR4%4K-y~*BTk0-oafB3} zxghGw3&M3tn#-zO!Kcv+!EKod75EYs8Pl)l;0oLYqz6%PQt{(EI=@0`-hI&trX;;^ zD^Q#iky8)MQFZ)8B%`i4!%DXv|3n8YQ%}>Rx>a6j?hi4H>Cb##m^W)uD?;lZ9d+O2 zq9SV3$<|w0^JQC8@Amzk<2%mzFNe%QaK^G{xmT2@+bcFj*{`%mT*aDc??wTM^h%u7 z64W6U&h%#ZNS9D0^6Ag4V~^WKHcD?9WgQ8g=bcE37rAM)F*Q_hx)rn)Qbb>%29hDJ zNf|UFQ(PqGFtDr)9Pj0Y@;|IcTGCu*TH(RBN3+7fA5XihF!p(d4?sg(0^jsI&-%Q= zVSY;b-|^lZ@6ESDk@6THD)M)DgSb}aKJJN!@vD`)3}AlT#rzBTgoKFb-*WNhcxGU- z)im}zMx3}QjVCii_c;oOUU+f-Xl1?(SJ>aeo{+EF$~~6%fX2RM;g3->DnTC!6l)&2 z5`h3gpEZU-a#;vXc%|XANnQZ_l|lKKVTEptWK{ToVW~lWt4{eV4!!zMI)%-r$+a^p zcAmofbmB2|uZTU+m$6ol(<9%t#7sY${9t<<>Ackzkdq85hlM_?NPqxM0d)LTUPj`e(~Nos*7q^;OAd5-2p^2_?yZC zNUo)bUiAK_z6ZM)p7&$b=}IgnD}fbxKlWbD{Lvksrg18{z;DWV&k5uR``IFN zNx`%cx0ifq!)_!)g=ou39EAB zOXXkg2Q3OW&S`7x1at6BT{iOl_Pac=C7@X&qGUYB=$_wf}NwG=Jf8j&0F#@3k zDb;>nH>{O9mVoSGiWXqe^-DO!@B3xxHPfVh@PTmsbo4m$jgSFFm$SB9_aEJMA zNM5I6)s)|^+A*Oc50}4ws0Gq+X~n|6zh%o3aRdM>LR1FO`F_MgQIQd7o-HfJQ(EX6-fT8;GG+4 zge~ZmK#9QzB=Y76^Na@zE<^7V&8^^st|cd%{z4b$ore-ChJ{9{D|epjD661ZVc|Z~ zL&M`~SQ+lm_Ojf+o_z6K!~PNcIE*l@+U9xS8}g;ADmcF$X2JzELzFk62*ZYMFTT2iX-d^|8qP%J$2aC4bQ0t z=h6q89FUjP%hG~_rIcYYOevJVNM2#Ai}Y5_c_o>~`F(#eJ-kHSp$py;=_g0ltc{AW zt%f8nHGUDeyXPEVQ+?H{9y^bh_$8_2SOGPXQPve<0S1oGEb$3_Ued?-e!gF9Hkcux z`6T(}si6bq<~D(kO^@9}VQJy=398<mei6QjSWDwSWMTj1Uv#(qTX)<--R zMp3>bM7PjFZLMD(rW6gCf${UTwa3|;=DALcn@<`ETdaI-KN_kNT718?^i9k`x zbSQSwgImt?ywnnHi`h=emWNB(uZo?CWn134>&Ka-Z zi;bJGQTpZK487~TW_i4m)7Tq$*)X^a`AqBi$nHD_!wXl3qvEP6W!=!f`(?+UnDKR) z>-crv%NBM#;tg#>?(V3%m$45&p7CjQD9SLD^bRU)PxrnP*Id>KgEf;;ofSj?DeD_{EdT_O& zH?_zc#a@YFV|f>Z_lc$-k*oJ%67rh?FlRPpm|e-JY!K>4EeNLB6V1>Z;? zql-)K16N%_tc8txE_g!c!NJm@^=9_Umr~Ie16%cLH|~DphNgQb2shif5N+ZOj_8G5 z;)K%FvhiZz8?7OLP=7X;m6e6#zx0Oh{ehJiWY<8G=?8Zt;dg}YsKsUptjpn|64B92 z;Pa>ZHxOlioi9kd`Q>)$m-TbByHpq~?<2XD8`AfF@g3h^?EYVcS_AVQNbbly?>8a} z)aLCN`u7NBU|?R$fF2`|-D!dJ=;Ked2ab8fEm9BMYuyzWqQ@qmToP*t3{V&#sRzv* z0N}LQ5FW|cyCwfoNq@&8Lp`-nvtP_eRaKACMIc6itd6i_DI~$F2)zxSq~nLgd1sbJ z>Yn4Sa-xv#yK}2^R1|lfn`s|`&$KqxBoYMqRq^H+>9HzY%||VY6wWOn$JelNmpSH3 zgS})B-pIU$KvmNcCH_Ad7IEV$)Ce621(zeVN-i!rXJ&!!V$tC%s!us4pGwuFq0EbV z=hUv+v^fS{eP-vO=Np3if8H;>s~b#4NO4hGM##JAxEH6n`+;u|eeIb4t1^>Y5o}32 zR*Yg=Nzj=jG&OOwe<4iySEQyRry#3?>y9Um66yR6V^1*nLFIHt@s;qHMfo+$8Oz%b zo6i^hSB{iv)PZ%`m;N^zgg=}JU0E{sL$0hOKO7Qz#kc%!Bv&Q9zQ1^E{t~vtLR^#V z!Ht9^hqWw^V9XjiUhm!;q9*H_Fm=#%R%e1%X`Boh(8htOuQBuJttdWfK*eam#)*>h zdY5n-P*ZhT#Upl%!Z6-^q;=#o=|{st+@JJ&qTFWPMkzdPVCNO8{;@q8(I0AZFymV+ z1n+|o>Wo7;u|WOUSa7~@FSQ=Dr{M#%zLQ-@ZjG%ajqg^^ZkMD!J~mDeRg3u#X5)4KQEdJ$5Q9DyBm=Dgq2JjG8t^- z%R1}K4Gs3l9s_p)2@4f}Z8$l~*Q}NM} zV-QDWwR@72({$?HCWpwy9^RPfV@UPn>yQM{LG=AN5F)2QOL{A-j7>bE=V@0_I{ipT}tX8AAtXjUhj0n5q1*P>IviIw>G<8FiMg*Uo~j)B0Z~}K4`e|kFE z*RGV?GOL4yp7m7d;txYQZDtng zO5b4lqAi z^cHq&7ZJB(w3fSo#a8#)O@>pQeSc$7LT+wO1DL+n_7)yP_!nzDz2VKg!*2DIb6Re_Y+t|Ps5z*-3OS7 zD3n1rScBBRC>LF<#R~Kq>ZwMto}Z+hcFP|>}-;vYgu-tc=y)(Yi-I{9F?rbd@u6BnvCs! z1R-S@PWd-djY5fc%z*tr+OgoPYR?eqa^!uJ)M3-??QOk-)i&*|^R?D|v6;Qay|T{y zOXj+HoxT$$Qf!afvpDna-(u$0kai~FkKzgmPvSgQY8i(02%^dvF3rvLL&I(nM@S}p zHBBi<<704}C`?;I8V{PWP|Fcs42iP6mX=oC7p5Zc{j)uv&IW>w`ENIMIF6 zJjF{C4p0R56K!YQC1OV+jT`2?!nE5<38MjAUkn{8D)yn0!}gE9W`zGCyY@mG@nTIN97;Mj~k=L zE;dm^~jVQ%{%{^IPsdqg3tF>ia6zA1o;NUBC)EoMHR2bWEyT#nH{W`X zN51Jq!2ey z_1-e&pTHNDEhS*$jWJb&`vMCDqoaO=*cby3i% zt}C;MIKR6l-OgxXIX?8%E|hTl_Y?`auI_8hb|p~}rH3#M%af-k2_47o+M<*CdA79q z;swgupd-Tb4zPGJoDJQDdj66Niv4G|eb&0M!lhx1o&6oWXhOVeQer(_BJeG|5i<+_ zT{vG5hiQOJ)gmzER*7Vv36$hdF3Zn_dw6IO-l+mBpYjW67gR}*Gru&_Avc_zEbPL6 z>?|U%S^$d|DBd|vRpBgxCQ{l_u*pV?ppXwNj{5IE@^hu(jC$r9T;z3muWpAUbep|J z!dpyx%4XC0@me=Y0+(_|gFIe$KyjIHzt%NMnM}*QF&|Sx725}qV#H#B*O-~}_Zbrs z<2Be{J{J73RpFJ*uXOsZvkkuNOWyjpp4Q?6^kE^v#``h&bT`sumeuz2 z;^IQjm*k3-%RA`)`T^&RoMQGn7z-JLQ6a>tY!1=?I|dFc&ES z=`m1j_V)2{T-V*p;Q8W^Z(6%muSNx_o}4^I4N|E-*`TBB0FB?r+vQUC<1tr~Adpxw zK3PfIp!0<=qK2gz`!|9+&~JV^xXl@Q7@psieTb|jAMeLqLHiz?1@1oJkc#}T0{}XH z28vYICvGi(1AY5}Ze4I&6Uf#76!dw3(ku^LSgPoCtKD{17Hh$FbzInWDv~~Sz?IqG zHu5uQ&%C61Qt89<#rItw%jA>ge;hoRH}4L_;wn@5*ZQ$)_WZqa&>54(p-z82c5TEA z^SAPV`@Xbw6vwsg>Ba9@?y%h4wg0E6?{J6fi@G+$D5FOE>CqW2BTDpPL>b)>y@u!| zlIXn?y+$2I38Ew+h^T|8(QEV&LJ&1VqI}o;z0dQ`KXC7vbI(3|ueJADqLz;qIy?p6 z0>_J{jgA@$F}zr=SzZ&WnL8H1^jd$j%;?#lvx_nIJ5YowpXr-JGHkX6N8 zcT-ueZIY`t{u6Ot#^6OZLQS5TtFCYzm!!>;$o+L91a#P}O`?q{h*K=Xk?77;prl?_OS*6R{ zU%fX!Z$j#Tt!8+CZJXSjL2f4@ooA`7NR!^*y+EFc9m;mNwoV{$p$(MA&0Jm=)K6Dd zG-B@DRI@_uyV9wyleflobR;nIEtf#PYWd*)ee@qdM$lc~4o`45CN_5WQ)}xkkcqQ7 z%IQcD;lgFoV0Ru;nx-&()&j1JuW&Pfjx#!!EMLhy;k%F=D4xwTbE#xp@>z8E{xMcW$y(K$ z3AkPZ(!^wW5sMP(^hXbKQ#F*{F>zJu*_80SrhC;x#uG*_4rOvZyjSBBY?g9zG;;i_ zfAId?z4u9b8bL~My_?>Z{AkI2mS*Gsv^3pfU+mNuql9kK9WOl7Gj#Mi(q!f7)4;Fv z!;Q8uOja+1C#^HhZ z?`vu^9E4MO8eBN}nCKsQFP|VWnS48D33oPP-(whBi0*KWK{K3-K9?dU^HE0I<*bF2 zI&p^%%Ik86_TER^NJF-5n>T9Q%WF?3k}V#MkE;DVwD)g!2`=(n5)fHOrINtM@z0_)2S8Hbr1{otAD)daSqMvE~ zchHGArv{|m52j%(3_Hv#mf^OiU97%K`g0Q#`iUpr!!wp_6M@#nzLJy&ym{wWH=Qs(Bc7MFQy&YX2-Pn?%K)MXj)tr57s`Fn}{G zbJuI2{!N+(?xH^l890SN;HNtIKJ|CjP5RI+gSbqPpTzef)efayDvgisE9Z_ zyci2r$jQzTU?no)jr zlPEcX$LfpB7fNHGO%fwc)_i09)2wful-avNPaQ1sA^bn>hR>~^lZN@bK5{r-wL9s^ zVl0eWm=LKcd_x3?bQpzBk2>EI^F5V{Bnl1rpH!;ce}8F_-U%XOGd5SR=Wsmz5E;2} zLPzGTIg7H|^xIleotm!ZPBoDF{<8=HD%!m-j`dxM<_bj@VrR!JM!1|Q8O*VO+on>j_s4ev7nw@}_A;RUcS&47P&?n9r*17{u8D+Rn zoW^#Ph_TtNL{7J1dQJ&1qow7moU)I3yC_&+gaXJEN zBvrtBucCIYGxOhp%22OX|5lR@R(_I~*%hRFEbUA*x#tFT-qYHeds4n1B&S4C;MPSe z3VNqyW{NijkI1T9Jnpa5f|KkRQ=Mnr86}~Sf8A7EHTZBt+ua_m)6I;^498|1K23)y z42^tziXcF?9GE9H*%R?;L6B7%m5NfSg8L+uBss76Qv3_;6x;eHG`;o+AM$g5B_uhg z(nP25UHqPz7V?GtQ7xW~ab*6xo#h5puvr z%`LXmE_w1E@LDSyX`Tz$@Ax05zgu~FI+@~7)?;6IV9i}E5gggJ{myZ*?46;ex)zFU z@oZ3XU=qXUROCWd)t3?E@DdQ>yh|~)A9S^AP1%iOYkJOeXaCjTaF1aiqT|)sJEq2n zg*m7f(BjS97lwg+8^dlJXOZYn`KMgmUxT$#n2noh`9~2PMGxF$&)uw6EWKwQ#blbb z=Y*g@BS;742vcya8n*;t@EsRA9sK)91r@f@EDyeaP||4S00mmBru0EcCvz=Xj8H|| zZ?xDuE@$W7Qj#u<5SKS+#yvDokdaN_0RjE)iLp|a`Dobd{CcYyn7d7B=h{}jCq=~C zgOH5}$eq)V)L~ZM@VnA~O|k5eQ`t4KukY7Kj*fB?k2yhu=2}AMR_ZZ(OU(wb3 z^vn(9MG^RRZfCKKvQVHv&*;AHcIX;4=$Y{Im%Wu`Ss(dyLKF$88^Y{gtyFbtpphSM*h}?=rEIJx&~usAM~w1z$ZFxr%dvS=;F`Mvtta&~G0S$K5q!CNPw-|8^j57f)wGu1iY>-lWaCLf~!tUy=vHd?$M- zG=u+!nq_Di3=OL{KY5y$0UkB++H2O4J$x`-VZBn`qC*$p8!pS}%P~bq%w-RWTCC>j zj8&+gQ2)!=mSPse3)75_Xg>CO19}v#8w%VIoVKpNMd)-&C+Nnee0s^%zexN(89To#03C#pc351Dwi|!gpW9? zArbNs-#nN;KQE)Iyfwjn-<2Py-UI5NU;tuhh!&e-LjsfXg`ZH@Zh{`o`GLKxrVA09 zG5@*tWpMpgWvKcr(NWPrUe@Cw02n~Y)=n&~`QQf(pHJs+Rmc1_&g25c4mTYgg@j z^*h>mU47eefHyh}%y$RMCMNegG@X^@#M~b8@NbE@-;Ty>pb#$e@c-4$hKZuwO<`Qt zn9tH@*}zNQw6AkC!!*bFeuYD5p~q47#bFd)(AFc{x;og{=omK#85-VrNSHI+6MnNqzEYt@SWdsIou% zz3=gDX==v;4~iyysL2+t5vtc*$I9OkUp7x*i54=D#^a_t0? z0JKS?)cjGM0D*1<4E9Ho6far6oa$hNU7&d%8`CN5ilZs2b`^LTwUwQh@=PubQSrQO zK?kXXabB3{v#u)Z>_VLeB|jH}!IyN>7s9!?$St*l7#EX>NQ7qvxiB?qSb-aBGR${U zLbd5+d@1Wq!eF6zf3c9*7z~CDL12%Z&Z+*=ucDNA&o;aTlS-aZdLG&l(R(-5cqXKX zDFn0jHdIOYn@BxaiM+QAU*--4G|D%X_4JI%l#Kz(JO#aljKKPmM|u(8q5-rE_jIi* zyd{HAH<^>g=UIl=o}NLN9;q~$kETaky!WC}icxpZL$#;O@!~3MYVbBCX@R#*bfN;* zrnuD_-r}a>NON~ZVWgS)0_rE{0cUl~wx?c0vNHtO0Ml^(e7{NtIa5xC6+q`#yP^2c za4$y+Sp9~QDv$GY&#X^ET=c?19&ATb-FU^8r1;cmUb;_M3zsnW4TWgC5RLd&*0vBr zTji8Q2TeBj%Ue>uW;X>Lk=C1qcXv^C@t4_OA~{*4Xs4dtK20ZWWcePUu3_%0vRJkN zr?ZO$YP3QsJtyu`m6mt`-QE`mKPcsrTm91Op*0Kuh4#`aZ#u1^n3_s3JR6tt zW9n4zpNZgw@sWi1H&;Eoxa1gtqel)d$nH6@SWld(;SCu`v}sd8@ zaq&3W2f3=~cCA^rQ@i>fOts&=eX_-2FdJI-c)gF)cI%2-g16|>(2J_AiN{CwDmb`| zj7FDO!7 zJO){(^+7ZmwQj8kujEk=9OfruM`B^?C~W4NCI8Rs@#Hu4r|Sv#MmztsAGC+D=OE!M z6L&^>O_sw9vXvgW)%ksW@+Y21qZBWqm|}HQytLrneV=dtoIDWG|J~5tbW@$+)Eph1 z?S;<-aER3xWyRxdw9&}4%tSvlH*P2>0Ot2BH-*EWFFU?KNmkEY0Rk^X@_%_~t&A)j z$`qUjJC0MwU~k^FrSfI@KWp1%qSd3yry~Yf9;M30>zB9KrohRn>Y=@g0s1%(FjW1| zMC?LLouyx5Dfuln$<){~j*F%-CQ4&dIO|tlYMiQBS93ArfvI>C$X|bj?{ljP)bJH> zVBctZ78wa(YTk(YP2J9TB}WGqtY47VM^=x5%wlvo6Ggl+>60h7r<;Ua__@CN^GUNj z%|IYPXtV~l37~CUZz(13bG=*208SMvHwQ?beTlSE(L5L0v~IipyUTTTbwz{sU#otD z$bZ%4<$2w%Z`&m=epbK5#B|(5+Z6%DeoT-5L#xbP(<21{cvT7yl6&vI*yq06DY3hPI!IP*!bNO6Gz|F#qT03vfv}_?DJ3w#t6!@s9*-ng7#F0SpAqBzb=0N_3Q( zpP2BXQHY)G=;+{ODTORo$j#KXw+{4%hlj%usSS=}A(ST*qHd9)NW;kit`xavARJ38 zy0QPv-MkbC*H3~0^20I-CqS%qJ3QbYHVnfj1l4V*pOYMmQ(N!Q&QjL8dAlC`(l{%4 zuHHB%jy2*=Ur^BLvmXe*GSW0Gtn^4dP=0Ve_hl1=z z{gcIBLCR^DM*LL4;v*)IA7wHiR_o2ui@Bw(&z>PC`Hr_!u9Yxa)RbR9z%72;)+WG* zsbQ@9blG?-+tD&QIx04273j|8P`*JNO;}L+Z+lbnFPbs_#k;%KsH>nsfX( zC@2V2tEqcUbs=@iVq3P&=v?TFT1up?l)eR&DK!Pd`FJ?aGjtWc4h*xXQn8e{jIG(t zr@XZV6)CfJ#7gzqvW9T!?H=+->DXSMA8q`Ae=b~`?;)PEtF(OE7w)!81;4g5xQ)7^ zJ^)z=Jr)%T-N#}%xUvfTz2h(kqE=dB1Br_L?`<9!zx@0m6Fm7aG*KKW_ViJcsndff zMTV$kKB+*H1(9}vUn|51XN1>P^XV|0A*!t4y>RoMBm}tsaXL)n0=fO&Q ztrLamtmk|#0CAn3MyiSV&r>AO14c4-Yr4n{`7^GfDQs(phGksa(CrsH}_U zcC{TmhSa(*pDFz4l%cT`UIL)Tldv0cUY@{~=5#UQIC^f=nDc*xJWMxO3*a7_^f{3? zxheYv_re8jeaUrhtWNmv9!3>T#>s$DF_%hqcIJdeU((YzH`4$wT{E`tvW^;zz_|>3 z0owWLg%+dn=Nfm-1u`W!e( z2EV}{shJmlDjWC9lCx(mnNoY=wh9o~y8*ws_*om^tkKBY#xRp2G!WXqKO1r<#ANQ- znOy&ci?;%(T)>AYw(PiHeZ8l#c-Hqem{goZMg!4Yb z-^fo6A0yK6bpCTkv{KtE%T#gTlg%uM^w5uO1G* zJ;i_h(2~F+E+J$+H8o)&G!v*;(4dESbRg)u{d@klQuFEQ>GW>ke1oHI`&PL)&xoqX zi)1Pj1~xVyuR@Zam%+y{f>p=yI8_mgkB2hg#{#42dAy^2zRNFfzZH48Dt>BwV8XQU zX6c8*gVAZqfpFFT&Ua#Q24Pzvcn#!w`}UpT^|@Dx*xEATa;3wNgaxt#262L@C2#~T zt`v4j(vVsA!Z&;azwHL4`BQwzki)Sc5|fK=UT>yfg`wFc{`WDJeW|PKR209@8S9-W zTjMr7V+Pg6sS<5I745S%QC6G2d;KEL>hYG!h?e#ZX^FEEO#ugT_H=|h!6d8e8hWzP3x9@dir?y|39 zhl39Hte^;Q=8-OMeuu%j@Y9JnA^ zsVE9eJ`BO%OL=_ERPyIOs|OpfW=@D?^ewxrd8R$ZkZrti)PL6#>{gi7m}M1+Z?cqZ zGe77b8e31}{*4gN|A9@Ae81UX;dddhvf3GV6I|YnO+(j4XqOQ>z(!Bbg%)wPU*wkx zu!dCp_V+Wj3tnGs3;jsW2>l{mmvv}&jp#Y*eBBnO$E0kY`(&lm3nO|1jHqcJSp#hy zKvzZ_@FJ3ZiNahA*^jtR0Mo1o6Xu?v@1ESghn-+s-#RyyxINoewy7yH8_U==C%p`I z**V|rV4{QYgIv~37oxMD5|leXa?}pLq%Qkv6U?bOeP5EUGbTaJTaEsP5GZu6EKSEqM>gtL(dY9@1d&HF{l)PckOaR^rExu^u_*fg8o z9W?Hn`sbMyX@m`;+*R=d_~&opWTP?sJ#(o#n;e@!jMcRi`$0~m7lp3DC&f_$@Hg78 zS0r^se7Z+9{;$t+9`8j@sKhJAA(bNfXkn=$w^vbwwYe$0=26l(KHeI0Jou+F!-sdl zsib*$N0L!tu1X(8q70rA;PA!;85{<&59g(zref2g(I9;^zT4QtBpc!S+om&@bl^|R ce*gOhzqMNmM@BT$j|covDmoAAkTwzj5AKVE7ytkO literal 0 HcmV?d00001 From 57b3c68766574bb3faea6c11357a19784bc2e7d3 Mon Sep 17 00:00:00 2001 From: Ray Wenderlich Date: Tue, 7 Jun 2016 10:44:19 -0400 Subject: [PATCH 0385/1679] Giving credit to Matthijs, Chris, Kelvin, and contributors :] --- README.markdown | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.markdown b/README.markdown index 10919f827..d36aec465 100644 --- a/README.markdown +++ b/README.markdown @@ -208,6 +208,14 @@ Other algorithm repositories: - [Rosetta Code](http://rosettacode.org). Implementations in pretty much any language you can think of. - [AlgorithmVisualizer](http://jasonpark.me/AlgorithmVisualizer/). Visualize algorithms on your browser. +## Credits + +The Swift Algorithm Club was originally created by [Matthijs Hollemans](https://github.com/hollance). + +It is now maintained by [Chris Pilcher](https://github.com/chris-pilcher) and [Kelvin Lau](https://github.com/kelvinlauKL). + +The Swift Algorithm Club is a a collaborative effort from the [most algorithmic members](https://github.com/rwenderlich/swift-algorithm-club/graphs/contributors) of the [raywenderlich.com](https://www.raywenderlich.com) community. We're always looking for help - why not [join the club](How to Contribute.markdown)? :] + ## License All content is licensed under the terms of the MIT open source license. From df44023c572558f57a9905e7bc4355d4cf35757e Mon Sep 17 00:00:00 2001 From: schlagelk Date: Tue, 7 Jun 2016 10:20:12 -0600 Subject: [PATCH 0386/1679] use swift guard statement consistently --- Quicksort/Quicksort.playground/Contents.swift | 24 +++++++++---------- .../Quicksort.playground/timeline.xctimeline | 6 ----- Quicksort/Quicksort.swift | 17 +++++++------ Quicksort/README.markdown | 17 +++++++------ 4 files changed, 27 insertions(+), 37 deletions(-) delete mode 100644 Quicksort/Quicksort.playground/timeline.xctimeline diff --git a/Quicksort/Quicksort.playground/Contents.swift b/Quicksort/Quicksort.playground/Contents.swift index 2d9ef3590..b88bafc12 100644 --- a/Quicksort/Quicksort.playground/Contents.swift +++ b/Quicksort/Quicksort.playground/Contents.swift @@ -6,20 +6,18 @@ import Foundation // *** Simple but inefficient version of quicksort *** func quicksort(a: [T]) -> [T] { - if a.count <= 1 { - return a - } else { - let pivot = a[a.count/2] - let less = a.filter { $0 < pivot } - let equal = a.filter { $0 == pivot } - let greater = a.filter { $0 > pivot } - - // Uncomment this following line to see in detail what the - // pivot is in each step and how the subarrays are partitioned. - //print(pivot, less, equal, greater) + guard a.count > 1 else { return a } + + let pivot = a[a.count/2] + let less = a.filter { $0 < pivot } + let equal = a.filter { $0 == pivot } + let greater = a.filter { $0 > pivot } + + // Uncomment this following line to see in detail what the + // pivot is in each step and how the subarrays are partitioned. + //print(pivot, less, equal, greater) return quicksort(less) + equal + quicksort(greater) - return quicksort(less) + equal + quicksort(greater) - } + return quicksort(less) + equal + quicksort(greater) } let list1 = [ 10, 0, 3, 9, 2, 14, 8, 27, 1, 5, 8, -1, 26 ] diff --git a/Quicksort/Quicksort.playground/timeline.xctimeline b/Quicksort/Quicksort.playground/timeline.xctimeline deleted file mode 100644 index bf468afec..000000000 --- a/Quicksort/Quicksort.playground/timeline.xctimeline +++ /dev/null @@ -1,6 +0,0 @@ - - - - - diff --git a/Quicksort/Quicksort.swift b/Quicksort/Quicksort.swift index 1d3b0602d..68c54ac5c 100644 --- a/Quicksort/Quicksort.swift +++ b/Quicksort/Quicksort.swift @@ -4,15 +4,14 @@ import Foundation Easy to understand but not very efficient. */ func quicksort(a: [T]) -> [T] { - if a.count <= 1 { - return a - } else { - let pivot = a[a.count/2] - let less = a.filter { $0 < pivot } - let equal = a.filter { $0 == pivot } - let greater = a.filter { $0 > pivot } - return quicksort(less) + equal + quicksort(greater) - } + guard a.count > 1 else { return a } + + let pivot = a[a.count/2] + let less = a.filter { $0 < pivot } + let equal = a.filter { $0 == pivot } + let greater = a.filter { $0 > pivot } + + return quicksort(less) + equal + quicksort(greater) } // MARK: - Lomuto diff --git a/Quicksort/README.markdown b/Quicksort/README.markdown index b8a908985..936f9f44c 100644 --- a/Quicksort/README.markdown +++ b/Quicksort/README.markdown @@ -8,15 +8,14 @@ Here's an implementation in Swift that should be easy to understand: ```swift func quicksort(a: [T]) -> [T] { - if a.count <= 1 { - return a - } else { - let pivot = a[a.count/2] - let less = a.filter { $0 < pivot } - let equal = a.filter { $0 == pivot } - let greater = a.filter { $0 > pivot } - return quicksort(less) + equal + quicksort(greater) - } + guard a.count > 1 else { return a } + + let pivot = a[a.count/2] + let less = a.filter { $0 < pivot } + let equal = a.filter { $0 == pivot } + let greater = a.filter { $0 > pivot } + + return quicksort(less) + equal + quicksort(greater) } ``` From feeccfbd6eac6b97d3072734464f6bf695e581d0 Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Wed, 8 Jun 2016 21:40:37 +1200 Subject: [PATCH 0387/1679] Update Under Construction.markdown Added links to algorithms submitted in PR #102 --- Under Construction.markdown | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Under Construction.markdown b/Under Construction.markdown index f0befb3d9..95ead4218 100644 --- a/Under Construction.markdown +++ b/Under Construction.markdown @@ -2,6 +2,11 @@ Here you'll find algorithms that are currently under construction. Suggestions and feedback is welcome! +### Sorting + +Special-purpose sorts: + - [Radix Sort](Radix Sort/) + ### Special-purpose sorts: - [Bucket Sort](Bucket Sort/) @@ -13,7 +18,10 @@ Here you'll find algorithms that are currently under construction. Suggestions a ### Trees - [AVL Tree](AVL Tree/). A binary search tree that balances itself using rotations. +- [Red-Black Tree](Red-Black Tree/) +- [Threaded Binary Tree](Threaded Binary Tree/) - [Ternary Search Tree](Ternary Search Tree/) +- [Trie](Trie/) - [Radix Tree](Radix Tree/) ### Miscellaneous From 2d4d59f24116e9647d81735562ef1380a009ae87 Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Wed, 8 Jun 2016 21:51:41 +1200 Subject: [PATCH 0388/1679] Configure Travis CI to run SwiftLint --- .travis.yml | 6 ++++++ install_swiftlint.sh | 23 +++++++++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 install_swiftlint.sh diff --git a/.travis.yml b/.travis.yml index b0210d197..e4c746b5e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,14 @@ language: objective-c osx_image: xcode7.3 +install: + +- ./install_swiftlint.sh + script: +- swiftlint + - xcodebuild test -project ./All-Pairs\ Shortest\ Paths/APSP/APSP.xcodeproj -scheme APSPTests - xcodebuild test -project ./Array2D/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./AVL\ Tree/Tests/Tests.xcodeproj -scheme Tests diff --git a/install_swiftlint.sh b/install_swiftlint.sh new file mode 100644 index 000000000..b33d83de2 --- /dev/null +++ b/install_swiftlint.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +# Installs the SwiftLint package. +# Tries to get the precompiled .pkg file from Github, but if that +# fails just recompiles from source. + +set -e + +SWIFTLINT_PKG_PATH="/tmp/SwiftLint.pkg" +SWIFTLINT_PKG_URL="https://github.com/realm/SwiftLint/releases/download/0.10.0/SwiftLint.pkg" + +wget --output-document=$SWIFTLINT_PKG_PATH $SWIFTLINT_PKG_URL + +if [ -f $SWIFTLINT_PKG_PATH ]; then + echo "SwiftLint package exists! Installing it..." + sudo installer -pkg $SWIFTLINT_PKG_PATH -target / +else + echo "SwiftLint package doesn't exist. Compiling from source..." && + git clone https://github.com/realm/SwiftLint.git /tmp/SwiftLint && + cd /tmp/SwiftLint && + git submodule update --init --recursive && + sudo make install +fi From 3df07d44b07d13e316d239ae921f0b3e9d59d606 Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Wed, 8 Jun 2016 22:01:55 +1200 Subject: [PATCH 0389/1679] CHMOD install_swiftlint.sh --- install_swiftlint.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 install_swiftlint.sh diff --git a/install_swiftlint.sh b/install_swiftlint.sh old mode 100644 new mode 100755 From e164943c9cabb53e6e34a21bf64f2bae4aec3da3 Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Wed, 8 Jun 2016 23:53:04 +1200 Subject: [PATCH 0390/1679] Added basic SwiftLint config file. Fixing all linting errors. --- .swiftlint.yml | 25 ++ AVL Tree/AVLTree.playground/Contents.swift | 2 +- AVL Tree/Tests/AVLTreeTests.swift | 40 ++- AVL Tree/Tests/TreeNodeTests.swift | 46 ++-- All-Pairs Shortest Paths/APSP/APSP/APSP.swift | 7 +- .../APSP/APSP/FloydWarshall.swift | 41 +-- Array2D/Array2D.playground/Contents.swift | 17 +- .../Array2D.playground/timeline.xctimeline | 6 - Array2D/Tests/Array2DTests.swift | 40 +-- .../Contents.swift | 2 +- .../Sources/BinarySearchTree.swift | 14 +- .../Solution 1/BinarySearchTree.swift | 14 +- .../Tests/BinarySearchTreeTests.swift | 4 +- .../Sources/BinarySearchTree.swift | 18 +- .../Solution 2/BinarySearchTree.swift | 18 +- .../BinaryTree.playground/Contents.swift | 8 +- .../BinaryTree.playground/timeline.xctimeline | 6 - Binary Tree/BinaryTree.swift | 6 +- Bit Set/BitSet.playground/Contents.swift | 6 +- .../BitSet.playground/Sources/BitSet.swift | 12 +- Bit Set/BitSet.swift | 12 +- .../BloomFilter.playground/Contents.swift | 20 +- Bloom Filter/BloomFilter.swift | 20 +- Bloom Filter/Tests/BloomFilterTests.swift | 46 ++-- .../Contents.swift | 8 +- .../Sources/BoundedPriorityQueue.swift | 6 +- .../Tests/BoundedPriorityQueueTests.swift | 6 +- .../BoyerMoore.playground/Contents.swift | 8 +- Boyer-Moore/BoyerMoore.swift | 18 +- .../Sources/Edge.swift | 4 +- .../Sources/Graph.swift | 8 +- .../Sources/Node.swift | 6 +- Breadth-First Search/BreadthFirstSearch.swift | 2 +- Breadth-First Search/Tests/Graph.swift | 20 +- .../BucketSort.playground/Contents.swift | 5 +- .../Sources/BucketSort.swift | 40 +-- Bucket Sort/BucketSort.swift | 54 ++-- Bucket Sort/Tests/Tests.swift | 44 +-- .../Combinatorics.playground/Contents.swift | 1 - .../Contents.swift | 4 +- .../CountingSort.playground/Contents.swift | 4 +- Counting Sort/CountingSort.swift | 4 +- Counting Sort/Tests/CountingSortTest.swift | 4 +- .../Sources/Edge.swift | 4 +- .../Sources/Graph.swift | 8 +- .../Sources/Node.swift | 6 +- Depth-First Search/Tests/Graph.swift | 20 +- Deque/Deque-Optimized.swift | 16 +- Deque/Deque-Simple.swift | 2 +- Deque/Deque.playground/Contents.swift | 16 +- GCD/GCD.playground/Contents.swift | 2 +- Graph/Graph/Edge.swift | 4 +- Graph/GraphTests/GraphTests.swift | 4 +- Hash Set/HashSet.playground/Contents.swift | 12 +- Hash Set/HashSet.swift | 12 +- .../HashTable.playground/Contents.swift | 18 +- Hash Table/HashTable.swift | 28 +- Heap/Heap.swift | 26 +- Heap/Tests/HeapTests.swift | 4 +- .../Huffman.playground/Contents.swift | 8 +- .../Huffman.playground/Sources/Heap.swift | 26 +- .../Huffman.playground/Sources/Huffman.swift | 44 +-- .../Sources/NSData+Bits.swift | 6 +- .../Sources/PriorityQueue.swift | 2 +- Huffman Coding/Huffman.swift | 44 +-- Huffman Coding/NSData+Bits.swift | 6 +- K-Means/KMeans.swift | 30 +-- K-Means/Tests/KMeansTests.swift | 24 +- K-Means/Tests/Vector.swift | 18 +- .../kthLargest.playground/Contents.swift | 4 +- Kth Largest Element/kthLargest.swift | 8 +- .../LinkedList.playground/Contents.swift | 30 +-- Linked List/LinkedList.swift | 46 ++-- .../Contents.swift | 12 +- .../LongestCommonSubsequence.swift | 12 +- .../Tests/LongestCommonSubsequenceTests.swift | 8 +- .../MergeSort.playground/Contents.swift | 10 +- Merge Sort/MergeSort.swift | 16 +- .../MinimumEditDistance.swift | 10 +- .../Sources/Edge.swift | 4 +- .../Sources/Graph.swift | 8 +- .../Sources/Node.swift | 6 +- .../Tests/Graph.swift | 20 +- .../OrderedArray.playground/Contents.swift | 13 +- Ordered Array/OrderedArray.swift | 16 +- .../Sources/OrderedSet.swift | 10 +- .../Sources/Player.swift | 6 +- Ordered Set/OrderedSet.swift | 10 +- Priority Queue/PriorityQueue.swift | 2 +- Queue/Queue-Optimized.swift | 10 +- Queue/Queue.playground/Contents.swift | 2 +- Quicksort/Quicksort.playground/Contents.swift | 20 +- Quicksort/Quicksort.swift | 8 +- Quicksort/Tests/QuicksortTests.swift | 4 +- Radix Sort/radixSort.swift | 2 +- .../Sources/RadixTree.swift | 20 +- Radix Tree/RadixTree.swift | 20 +- Red-Black Tree/RBTree.swift | 251 ++++++++---------- .../RingBuffer.playground/Contents.swift | 8 +- Ring Buffer/RingBuffer.swift | 16 +- .../RLE.playground/Contents.swift | 10 +- Run-Length Encoding/RLE.swift | 10 +- Run-Length Encoding/Tests/RLETests.swift | 8 +- .../SegmentTree.playground/Contents.swift | 15 +- Segment Tree/SegmentTree.swift | 14 +- Select Minimum Maximum/Maximum.swift | 2 +- .../Contents.swift | 3 +- .../Tests/MaximumTests.swift | 2 +- Select Minimum Maximum/Tests/TestHelper.swift | 2 +- .../Contents.swift | 6 +- Selection Sampling/SelectionSampling.swift | 8 +- Selection Sort/SelectionSort.swift | 4 +- Shell Sort/shellsort.swift | 2 +- .../Sources/Edge.swift | 4 +- .../Sources/Graph.swift | 8 +- .../Sources/Node.swift | 6 +- Shortest Path (Unweighted)/Tests/Graph.swift | 20 +- .../Tests/ShortestPathTests.swift | 2 +- .../ShuntingYard.playground/Contents.swift | 69 +++-- .../Sources/Stack.swift | 14 +- .../timeline.xctimeline | 6 - Shunting Yard/ShuntingYard.swift | 50 ++-- .../SSSP/BellmanFord.swift | 32 ++- .../SSSP/SSSP.swift | 8 +- Stack/Stack.playground/Contents.swift | 14 +- .../TST.playground/Contents.swift | 13 +- .../TST.playground/Sources/TSTNode.swift | 16 +- .../Sources/TernarySearchTree.swift | 52 ++-- .../contents.xcworkspacedata | 7 + .../TST.playground/timeline.xctimeline | 6 - Ternary Search Tree/TSTNode.swift | 24 +- Ternary Search Tree/TernarySearchTree.swift | 62 ++--- Threaded Binary Tree/ThreadedBinaryTree.swift | 16 +- .../ThreadedBinaryTreeTests.swift | 2 +- Topological Sort/Graph.swift | 14 +- .../Tests/TopologicalSortTests.swift | 8 +- .../Sources/Graph.swift | 16 +- .../Sources/TopologicalSort1.swift | 12 +- .../Sources/TopologicalSort3.swift | 2 +- Topological Sort/TopologicalSort1.swift | 14 +- Topological Sort/TopologicalSort3.swift | 2 +- Treap/Treap.swift | 52 ++-- .../contents.xcworkspacedata | 7 + Treap/Treap/Treap/AppDelegate.swift | 1 - Treap/Treap/TreapTests/TreapTests.swift | 13 +- Treap/TreapMergeSplit.swift | 53 ++-- Tree/Tree.playground/Contents.swift | 4 +- Tree/Tree.swift | 4 +- Trie/trie.swift | 43 +-- .../Solution 1/2Sum.playground/Contents.swift | 2 +- Two-Sum Problem/Solution 1/2Sum.swift | 4 +- .../Solution 2/2Sum.playground/Contents.swift | 2 +- .../UnionFind.playground/Contents.swift | 14 +- Union-Find/UnionFind.swift | 10 +- 154 files changed, 1240 insertions(+), 1232 deletions(-) create mode 100644 .swiftlint.yml delete mode 100644 Array2D/Array2D.playground/timeline.xctimeline delete mode 100644 Binary Tree/BinaryTree.playground/timeline.xctimeline delete mode 100644 Shunting Yard/ShuntingYard.playground/timeline.xctimeline create mode 100644 Ternary Search Tree/TST.playground/playground.xcworkspace/contents.xcworkspacedata delete mode 100644 Ternary Search Tree/TST.playground/timeline.xctimeline create mode 100644 Treap/Treap/Treap.xcodeproj/project.xcworkspace/contents.xcworkspacedata diff --git a/.swiftlint.yml b/.swiftlint.yml new file mode 100644 index 000000000..1434bf637 --- /dev/null +++ b/.swiftlint.yml @@ -0,0 +1,25 @@ +cyclomatic_complexity: 12 +file_length: 550 +function_body_length: 80 +function_parameter_count: 8 +line_length: 150 +type_body_length: 300 +variable_name: + min_length: + error: 1 + warning: 1 + excluded: + - N + +disabled_rules: + - valid_docs + +custom_rules: + smiley_face: + name: "Smiley Face" + regex: "(\:\))" + match_kinds: + - comment + - string + message: "A closing parenthesis smiley :) creates a half-hearted smile, and thus is not preferred. Use :]" + severity: warning diff --git a/AVL Tree/AVLTree.playground/Contents.swift b/AVL Tree/AVLTree.playground/Contents.swift index 4b4e1f3e2..2b8ee8b59 100644 --- a/AVL Tree/AVLTree.playground/Contents.swift +++ b/AVL Tree/AVLTree.playground/Contents.swift @@ -24,4 +24,4 @@ tree.delete(5) tree.delete(2) tree.delete(1) tree.delete(4) -tree.delete(3) \ No newline at end of file +tree.delete(3) diff --git a/AVL Tree/Tests/AVLTreeTests.swift b/AVL Tree/Tests/AVLTreeTests.swift index 51e1211c3..065367bb6 100644 --- a/AVL Tree/Tests/AVLTreeTests.swift +++ b/AVL Tree/Tests/AVLTreeTests.swift @@ -9,15 +9,15 @@ import XCTest class AVLTreeTests: XCTestCase { - - var tree : AVLTree? + + var tree: AVLTree? override func setUp() { super.setUp() - + tree = AVLTree() } - + override func tearDown() { // Put teardown code here. This method is called after the invocation of each test method in the class. super.tearDown() @@ -60,8 +60,8 @@ class AVLTreeTests: XCTestCase { } func testEmptyInitialization() { - let tree = AVLTree() - + let tree = AVLTree() + XCTAssertEqual(tree.size, 0) XCTAssertNil(tree.root) } @@ -71,45 +71,45 @@ class AVLTreeTests: XCTestCase { self.tree?.insert(5, "E") } } - + func testMultipleInsertionsPerformance() { self.measureBlock { self.tree?.autopopulateWithNodes(50) } } - + func testSearchExistentOnSmallTreePerformance() { self.measureBlock { self.tree?.search(2) } } - + func testSearchExistentElementOnLargeTreePerformance() { self.measureBlock { self.tree?.autopopulateWithNodes(500) self.tree?.search(400) } } - + func testMinimumOnPopulatedTree() { self.tree?.autopopulateWithNodes(500) let min = self.tree?.root?.minimum() XCTAssertNotNil(min, "Minimum function not working") } - + func testMinimumOnSingleTreeNode() { let treeNode = TreeNode(key: 1, payload: "A") let min = treeNode.minimum() - + XCTAssertNotNil(min, "Minimum on single node should be returned") - XCTAssertEqual(min?.payload,treeNode.payload) + XCTAssertEqual(min?.payload, treeNode.payload) } - + func testDeleteExistentKey() { self.tree?.delete(1) XCTAssertNil(self.tree?.search(1), "Key should not exist anymore") } - + func testDeleteNotExistentKey() { self.tree?.delete(1056) XCTAssertNil(self.tree?.search(1056), "Key should not exist") @@ -122,7 +122,7 @@ class AVLTreeTests: XCTestCase { XCTAssertEqual(tree.size, i + 1, "Insert didn't update size correctly!") } } - + func testDelete() { let permutations = [ [5, 1, 4, 2, 3], @@ -130,7 +130,7 @@ class AVLTreeTests: XCTestCase { [4, 5, 3, 2, 1], [3, 2, 5, 4, 1], ] - + for p in permutations { let tree = AVLTree() @@ -151,8 +151,8 @@ class AVLTreeTests: XCTestCase { } extension AVLTree where Key : SignedIntegerType { - func autopopulateWithNodes(count : Int) { - var k : Key = 1 + func autopopulateWithNodes(count: Int) { + var k: Key = 1 for _ in 0...count { self.insert(k) k = k + 1 @@ -185,5 +185,3 @@ extension AVLTree where Key : SignedIntegerType { } } } - - diff --git a/AVL Tree/Tests/TreeNodeTests.swift b/AVL Tree/Tests/TreeNodeTests.swift index c15721655..88b314e41 100644 --- a/AVL Tree/Tests/TreeNodeTests.swift +++ b/AVL Tree/Tests/TreeNodeTests.swift @@ -9,50 +9,50 @@ import XCTest class TreeNodeTests: XCTestCase { - - var root : TreeNode? - var left : TreeNode? - var right : TreeNode? - + + var root: TreeNode? + var left: TreeNode? + var right: TreeNode? + override func setUp() { super.setUp() - left = TreeNode(key: "Name", payload: "Left") - right = TreeNode(key: "Name", payload: "Right") - root = TreeNode(key: "Name", payload: "Root", leftChild: left, rightChild: right, parent: nil, height: 0) + left = TreeNode(key: "Name", payload: "Left") + right = TreeNode(key: "Name", payload: "Right") + root = TreeNode(key: "Name", payload: "Root", leftChild: left, rightChild: right, parent: nil, height: 0) } - + override func tearDown() { // Put teardown code here. This method is called after the invocation of each test method in the class. super.tearDown() } - - + + func testSingleNodeCreationNOPayload() { - let treeNode = TreeNode(key: "Building") + let treeNode = TreeNode(key: "Building") XCTAssertNil(treeNode.payload, "Payload for this case should be nil") } - + func testSingleNodeCreationWithPayload() { XCTAssertNotNil(self.root!, "Payload for this case should not be nil") } - + func testIsRoot() { XCTAssertTrue(self.root!.isRoot) } - + func testNotIsLeaf() { XCTAssertFalse(self.root!.isLeaf, "root node is not leaf") } - + func testNotIsLeftChild() { XCTAssertFalse(self.root!.isLeftChild, "root node is not left child") } - + func testNotIsRightChild() { XCTAssertFalse(self.root!.isRightChild, "root node is not right child") } - + func testIsLeftChild() { XCTAssertTrue(self.left!.isLeftChild) } @@ -64,21 +64,21 @@ class TreeNodeTests: XCTestCase { func isLeaf() { XCTAssertTrue(self.left!.isLeaf) } - + func testHasAnyChild() { XCTAssertTrue(self.root!.hasAnyChild) } - + func testNotHasAnyChild() { XCTAssertFalse(self.left!.hasAnyChild) } - + func testHasBothChildren() { XCTAssertTrue(self.root!.hasBothChildren) } - + func testNotHasBothChildren() { XCTAssertFalse(self.left!.hasBothChildren) } - + } diff --git a/All-Pairs Shortest Paths/APSP/APSP/APSP.swift b/All-Pairs Shortest Paths/APSP/APSP/APSP.swift index bb773306e..453f738b7 100644 --- a/All-Pairs Shortest Paths/APSP/APSP/APSP.swift +++ b/All-Pairs Shortest Paths/APSP/APSP/APSP.swift @@ -9,7 +9,9 @@ import Foundation import Graph /** - `APSPAlgorithm` is a protocol for encapsulating an All-Pairs Shortest Paths algorithm. It provides a single function `apply` that accepts a subclass of `AbstractGraph` and returns an object conforming to `APSPResult`. + `APSPAlgorithm` is a protocol for encapsulating an All-Pairs Shortest Paths algorithm. + It provides a single function `apply` that accepts a subclass of `AbstractGraph` and + returns an object conforming to `APSPResult`. */ public protocol APSPAlgorithm { @@ -21,7 +23,8 @@ public protocol APSPAlgorithm { } /** - `APSPResult` is a protocol defining functions `distance` and `path`, allowing for opaque queries into the actual data structures that represent the APSP solution according to the algorithm used. + `APSPResult` is a protocol defining functions `distance` and `path`, allowing for opaque + queries into the actual data structures that represent the APSP solution according to the algorithm used. */ public protocol APSPResult { diff --git a/All-Pairs Shortest Paths/APSP/APSP/FloydWarshall.swift b/All-Pairs Shortest Paths/APSP/APSP/FloydWarshall.swift index a655e215f..806c8677c 100644 --- a/All-Pairs Shortest Paths/APSP/APSP/FloydWarshall.swift +++ b/All-Pairs Shortest Paths/APSP/APSP/FloydWarshall.swift @@ -51,12 +51,16 @@ public struct FloydWarshall: APSPAlgorithm { } /** - For each iteration of `intermediateIdx`, perform the comparison for the dynamic algorith, checking for each pair of start/end vertices, whether a path taken through another vertex produces a shorter path. + For each iteration of `intermediateIdx`, perform the comparison for the dynamic algorith, + checking for each pair of start/end vertices, whether a path taken through another vertex + produces a shorter path. - complexity: `Θ(V^2)` time/space - - returns: a tuple containing the next distance matrix with weights of currently known shortest paths and the corresponding predecessor matrix + - returns: a tuple containing the next distance matrix with weights of currently known + shortest paths and the corresponding predecessor matrix */ - static private func nextStep(intermediateIdx: Int, previousDistances: Distances, previousPredecessors: Predecessors, graph: AbstractGraph) -> StepResult { + static private func nextStep(intermediateIdx: Int, previousDistances: Distances, + previousPredecessors: Predecessors, graph: AbstractGraph) -> StepResult { let vertexCount = graph.vertices.count var nextDistances = Array(count: vertexCount, repeatedValue: Array(count: vertexCount, repeatedValue: Double.infinity)) @@ -85,9 +89,11 @@ public struct FloydWarshall: APSPAlgorithm { } - /** - We need to map the graph's weight domain onto the one required by the algorithm: the graph stores either a weight as a `Double` or `nil` if no edge exists between two vertices, but the algorithm needs a lack of an edge represented as ∞ for the `min` comparison to work correctly. - + /** + We need to map the graph's weight domain onto the one required by the algorithm: the graph + stores either a weight as a `Double` or `nil` if no edge exists between two vertices, but + the algorithm needs a lack of an edge represented as ∞ for the `min` comparison to work correctly. + - complexity: `Θ(V^2)` time/space - returns: weighted adjacency matrix in form ready for processing with Floyd-Warshall */ @@ -116,7 +122,7 @@ public struct FloydWarshall: APSPAlgorithm { /** Make the initial predecessor index matrix. Initially each value is equal to it's row index, it's "from" index when querying into it. - + - complexity: `Θ(V^2)` time/space */ static private func constructInitialPredecessorMatrix(distances: Distances) -> Predecessors { @@ -139,9 +145,11 @@ public struct FloydWarshall: APSPAlgorithm { } /** - `FloydWarshallResult` encapsulates the result of the computation, namely the minimized distance adjacency matrix, and the matrix of predecessor indices. - - It conforms to the `APSPResult` procotol which provides methods to retrieve distances and paths between given pairs of start and end nodes. + `FloydWarshallResult` encapsulates the result of the computation, namely the + minimized distance adjacency matrix, and the matrix of predecessor indices. + + It conforms to the `APSPResult` procotol which provides methods to retrieve + distances and paths between given pairs of start and end nodes. */ public struct FloydWarshallResult: APSPResult { @@ -149,7 +157,8 @@ public struct FloydWarshallResult: APSPResult { private var predecessors: Predecessors /** - - returns: the total weight of the path from a starting vertex to a destination. This value is the minimal connected weight between the two vertices, or `nil` if no path exists + - returns: the total weight of the path from a starting vertex to a destination. + This value is the minimal connected weight between the two vertices, or `nil` if no path exists - complexity: `Θ(1)` time/space */ public func distance(fromVertex from: Vertex, toVertex to: Vertex) -> Double? { @@ -159,7 +168,8 @@ public struct FloydWarshallResult: APSPResult { } /** - - returns: the reconstructed path from a starting vertex to a destination, as an array containing the data property of each vertex, or `nil` if no path exists + - returns: the reconstructed path from a starting vertex to a destination, + as an array containing the data property of each vertex, or `nil` if no path exists - complexity: `Θ(V)` time, `Θ(V^2)` space */ public func path(fromVertex from: Vertex, toVertex to: Vertex, inGraph graph: AbstractGraph) -> [T]? { @@ -175,11 +185,13 @@ public struct FloydWarshallResult: APSPResult { } /** - The recursive component to rebuilding the shortest path between two vertices using the predecessor matrix. + The recursive component to rebuilding the shortest path between + two vertices using the predecessor matrix. - returns: the list of predecessors discovered so far */ - private func recursePathFrom(fromVertex from: Vertex, toVertex to: Vertex, path: [Vertex], inGraph graph: AbstractGraph) -> [Vertex]? { + private func recursePathFrom(fromVertex from: Vertex, toVertex to: Vertex, path: [Vertex], + inGraph graph: AbstractGraph) -> [Vertex]? { if from.index == to.index { return [ from, to ] @@ -198,7 +210,6 @@ public struct FloydWarshallResult: APSPResult { } return nil - } } diff --git a/Array2D/Array2D.playground/Contents.swift b/Array2D/Array2D.playground/Contents.swift index f73ba8b13..0bcb7b5b9 100644 --- a/Array2D/Array2D.playground/Contents.swift +++ b/Array2D/Array2D.playground/Contents.swift @@ -7,14 +7,14 @@ public struct Array2D { public let columns: Int public let rows: Int private var array: [T] - + public init(columns: Int, rows: Int, initialValue: T) { self.columns = columns self.rows = rows array = .init(count: rows*columns, repeatedValue: initialValue) } - - public subscript(column: Int, row: Int) -> T { + + public subscript(column: Int, row: Int) -> T { get { return array[row*columns + column] } @@ -51,14 +51,13 @@ print(matrix.array) // print out the 2D array with a reference around the grid for i in 0.. - - - - diff --git a/Array2D/Tests/Array2DTests.swift b/Array2D/Tests/Array2DTests.swift index 3383b5eb3..f4019a03a 100644 --- a/Array2D/Tests/Array2DTests.swift +++ b/Array2D/Tests/Array2DTests.swift @@ -9,65 +9,65 @@ import XCTest class Array2DTest: XCTestCase { - + override func setUp() { super.setUp() } - + override func tearDown() { super.tearDown() } - + func testIntegerArrayWithPositiveRowsAndColumns() { let array = Array2D(columns: 3, rows: 2, initialValue: 0) - + XCTAssertEqual(array.columns, 3, "Column count setup failed") XCTAssertEqual(array.rows, 2, "Rows count setup failed") - XCTAssertEqual(array[2,1], 0, "Integer array: Initialization value is wrong") + XCTAssertEqual(array[2, 1], 0, "Integer array: Initialization value is wrong") } - + func testStringArrayWithPositiveRowsAndColumns() { let array = Array2D(columns: 3, rows: 2, initialValue: "empty") - + XCTAssertEqual(array.columns, 3, "Column count setup failed") XCTAssertEqual(array.rows, 2, "Rows count setup failed") - XCTAssertEqual(array[2,1], "empty", "String array: Initialization value is wrong") + XCTAssertEqual(array[2, 1], "empty", "String array: Initialization value is wrong") } - + func testCustomClassArrayWithPositiveRowsAndColumns() { let array = Array2D(columns: 3, rows: 2, initialValue: TestElement(identifier: "pepe")) - + XCTAssertEqual(array.columns, 3, "Column count setup failed") XCTAssertEqual(array.rows, 2, "Rows count setup failed") - XCTAssertEqual(array[2,1], TestElement(identifier: "pepe"), "Custom Class array: Initialization value is wrong") + XCTAssertEqual(array[2, 1], TestElement(identifier: "pepe"), "Custom Class array: Initialization value is wrong") } - + func testPerformanceOnSmallArray() { self.measureBlock { self.printArrayWith(columns: 2, rows: 2, inititalValue: 1) } } - + // func testPerformanceOnLargeArray() { // self.measureBlock { // self.printArrayWith(columns: 2000, rows: 2000, inititalValue: 1) // } // } - - private func printArrayWith(columns columns: Int, rows: Int, inititalValue: Int){ + + private func printArrayWith(columns columns: Int, rows: Int, inititalValue: Int) { let array = Array2D(columns: columns, rows: rows, initialValue: 4) for r in 0.. Bool { return search(value) != nil } @@ -224,7 +224,7 @@ extension BinarySearchTree { } return node } - + /* Returns the rightmost descendent. O(h) time. */ @@ -235,7 +235,7 @@ extension BinarySearchTree { } return node } - + /* Calculates the depth of this node, i.e. the distance to the root. Takes O(h) time. @@ -249,7 +249,7 @@ extension BinarySearchTree { } return edges } - + /* Calculates the height of this node, i.e. the distance to the lowest leaf. Since this looks at all children of this node, performance is O(n). @@ -303,13 +303,13 @@ extension BinarySearchTree { process(value) right?.traverseInOrder(process) } - + public func traversePreOrder(@noescape process: T -> Void) { process(value) left?.traversePreOrder(process) right?.traversePreOrder(process) } - + public func traversePostOrder(@noescape process: T -> Void) { left?.traversePostOrder(process) right?.traversePostOrder(process) diff --git a/Binary Search Tree/Solution 1/BinarySearchTree.swift b/Binary Search Tree/Solution 1/BinarySearchTree.swift index 55683b639..a58ac075a 100644 --- a/Binary Search Tree/Solution 1/BinarySearchTree.swift +++ b/Binary Search Tree/Solution 1/BinarySearchTree.swift @@ -76,7 +76,7 @@ extension BinarySearchTree { public func insert(value: T) { insert(value, parent: self) } - + private func insert(value: T, parent: BinarySearchTree) { if value < self.value { if let left = left { @@ -209,7 +209,7 @@ extension BinarySearchTree { } } */ - + public func contains(value: T) -> Bool { return search(value) != nil } @@ -224,7 +224,7 @@ extension BinarySearchTree { } return node } - + /* Returns the rightmost descendent. O(h) time. */ @@ -235,7 +235,7 @@ extension BinarySearchTree { } return node } - + /* Calculates the depth of this node, i.e. the distance to the root. Takes O(h) time. @@ -249,7 +249,7 @@ extension BinarySearchTree { } return edges } - + /* Calculates the height of this node, i.e. the distance to the lowest leaf. Since this looks at all children of this node, performance is O(n). @@ -303,13 +303,13 @@ extension BinarySearchTree { process(value) right?.traverseInOrder(process) } - + public func traversePreOrder(@noescape process: T -> Void) { process(value) left?.traversePreOrder(process) right?.traversePreOrder(process) } - + public func traversePostOrder(@noescape process: T -> Void) { left?.traversePostOrder(process) right?.traversePostOrder(process) diff --git a/Binary Search Tree/Solution 1/Tests/BinarySearchTreeTests.swift b/Binary Search Tree/Solution 1/Tests/BinarySearchTreeTests.swift index 46fdd7c8a..7c7fd069b 100755 --- a/Binary Search Tree/Solution 1/Tests/BinarySearchTreeTests.swift +++ b/Binary Search Tree/Solution 1/Tests/BinarySearchTreeTests.swift @@ -302,9 +302,9 @@ class BinarySearchTreeTest: XCTestCase { func testRemoveRoot() { let tree = BinarySearchTree(array: [8, 5, 10, 4, 9, 20, 11, 15, 13]) - + let node9 = tree.search(9)! - + let newRoot = tree.remove() XCTAssertTrue(newRoot === node9) XCTAssertEqual(newRoot!.value, 9) diff --git a/Binary Search Tree/Solution 2/BinarySearchTree.playground/Sources/BinarySearchTree.swift b/Binary Search Tree/Solution 2/BinarySearchTree.playground/Sources/BinarySearchTree.swift index d370eb691..ce2868bbf 100644 --- a/Binary Search Tree/Solution 2/BinarySearchTree.playground/Sources/BinarySearchTree.swift +++ b/Binary Search Tree/Solution 2/BinarySearchTree.playground/Sources/BinarySearchTree.swift @@ -7,7 +7,7 @@ public enum BinarySearchTree { case Empty case Leaf(T) indirect case Node(BinarySearchTree, T, BinarySearchTree) - + /* How many nodes are in this subtree. Performance: O(n). */ public var count: Int { switch self { @@ -16,7 +16,7 @@ public enum BinarySearchTree { case let .Node(left, _, right): return left.count + 1 + right.count } } - + /* Distance of this node to its lowest leaf. Performance: O(n). */ public var height: Int { switch self { @@ -25,7 +25,7 @@ public enum BinarySearchTree { case let .Node(left, _, right): return 1 + max(left.height, right.height) } } - + /* Inserts a new element into the tree. Performance: runs in O(h) time, where h is the height of the tree. @@ -34,14 +34,14 @@ public enum BinarySearchTree { switch self { case .Empty: return .Leaf(newValue) - + case .Leaf(let value): if newValue < value { return .Node(.Leaf(newValue), value, .Empty) } else { return .Node(.Empty, value, .Leaf(newValue)) } - + case .Node(let left, let value, let right): if newValue < value { return .Node(left.insert(newValue), value, right) @@ -50,7 +50,7 @@ public enum BinarySearchTree { } } } - + /* Finds the "highest" node with the specified value. Performance: runs in O(h) time, where h is the height of the tree. @@ -71,11 +71,11 @@ public enum BinarySearchTree { } } } - + public func contains(x: T) -> Bool { return search(x) != nil } - + /* Returns the leftmost descendent. O(h) time. */ @@ -91,7 +91,7 @@ public enum BinarySearchTree { } return prev } - + /* Returns the rightmost descendent. O(h) time. */ diff --git a/Binary Search Tree/Solution 2/BinarySearchTree.swift b/Binary Search Tree/Solution 2/BinarySearchTree.swift index d370eb691..ce2868bbf 100644 --- a/Binary Search Tree/Solution 2/BinarySearchTree.swift +++ b/Binary Search Tree/Solution 2/BinarySearchTree.swift @@ -7,7 +7,7 @@ public enum BinarySearchTree { case Empty case Leaf(T) indirect case Node(BinarySearchTree, T, BinarySearchTree) - + /* How many nodes are in this subtree. Performance: O(n). */ public var count: Int { switch self { @@ -16,7 +16,7 @@ public enum BinarySearchTree { case let .Node(left, _, right): return left.count + 1 + right.count } } - + /* Distance of this node to its lowest leaf. Performance: O(n). */ public var height: Int { switch self { @@ -25,7 +25,7 @@ public enum BinarySearchTree { case let .Node(left, _, right): return 1 + max(left.height, right.height) } } - + /* Inserts a new element into the tree. Performance: runs in O(h) time, where h is the height of the tree. @@ -34,14 +34,14 @@ public enum BinarySearchTree { switch self { case .Empty: return .Leaf(newValue) - + case .Leaf(let value): if newValue < value { return .Node(.Leaf(newValue), value, .Empty) } else { return .Node(.Empty, value, .Leaf(newValue)) } - + case .Node(let left, let value, let right): if newValue < value { return .Node(left.insert(newValue), value, right) @@ -50,7 +50,7 @@ public enum BinarySearchTree { } } } - + /* Finds the "highest" node with the specified value. Performance: runs in O(h) time, where h is the height of the tree. @@ -71,11 +71,11 @@ public enum BinarySearchTree { } } } - + public func contains(x: T) -> Bool { return search(x) != nil } - + /* Returns the leftmost descendent. O(h) time. */ @@ -91,7 +91,7 @@ public enum BinarySearchTree { } return prev } - + /* Returns the rightmost descendent. O(h) time. */ diff --git a/Binary Tree/BinaryTree.playground/Contents.swift b/Binary Tree/BinaryTree.playground/Contents.swift index 5470f9741..b953b6a71 100644 --- a/Binary Tree/BinaryTree.playground/Contents.swift +++ b/Binary Tree/BinaryTree.playground/Contents.swift @@ -36,8 +36,8 @@ let node3 = BinaryTree.Node(.Empty, "3", .Empty) let nodeB = BinaryTree.Node(.Empty, "b", .Empty) // intermediate nodes on the left -let Aminus10 = BinaryTree.Node(nodeA, "-", node10) -let timesLeft = BinaryTree.Node(node5, "*", Aminus10) +let aMinus10 = BinaryTree.Node(nodeA, "-", node10) +let timesLeft = BinaryTree.Node(node5, "*", aMinus10) // intermediate nodes on the right let minus4 = BinaryTree.Node(.Empty, "-", node4) @@ -60,7 +60,7 @@ extension BinaryTree { right.traverseInOrder(process) } } - + public func traversePreOrder(@noescape process: T -> Void) { if case let .Node(left, value, right) = self { process(value) @@ -68,7 +68,7 @@ extension BinaryTree { right.traversePreOrder(process) } } - + public func traversePostOrder(@noescape process: T -> Void) { if case let .Node(left, value, right) = self { left.traversePostOrder(process) diff --git a/Binary Tree/BinaryTree.playground/timeline.xctimeline b/Binary Tree/BinaryTree.playground/timeline.xctimeline deleted file mode 100644 index bf468afec..000000000 --- a/Binary Tree/BinaryTree.playground/timeline.xctimeline +++ /dev/null @@ -1,6 +0,0 @@ - - - - - diff --git a/Binary Tree/BinaryTree.swift b/Binary Tree/BinaryTree.swift index edcb3b461..0c55af20e 100644 --- a/Binary Tree/BinaryTree.swift +++ b/Binary Tree/BinaryTree.swift @@ -6,7 +6,7 @@ public indirect enum BinaryTree { case Node(BinaryTree, T, BinaryTree) case Empty - + public var count: Int { switch self { case let .Node(left, _, right): @@ -36,7 +36,7 @@ extension BinaryTree { right.traverseInOrder(process) } } - + public func traversePreOrder(@noescape process: T -> Void) { if case let .Node(left, value, right) = self { process(value) @@ -44,7 +44,7 @@ extension BinaryTree { right.traversePreOrder(process) } } - + public func traversePostOrder(@noescape process: T -> Void) { if case let .Node(left, value, right) = self { left.traversePostOrder(process) diff --git a/Bit Set/BitSet.playground/Contents.swift b/Bit Set/BitSet.playground/Contents.swift index 3cb56ccbb..77d371420 100644 --- a/Bit Set/BitSet.playground/Contents.swift +++ b/Bit Set/BitSet.playground/Contents.swift @@ -4,8 +4,8 @@ var bits = BitSet(size: 140) // Initially, it looks like all zeros: -// 0000000000000000000000000000000000000000000000000000000000000000 -// 0000000000000000000000000000000000000000000000000000000000000000 +// 0000000000000000000000000000000000000000000000000000000000000000 +// 0000000000000000000000000000000000000000000000000000000000000000 // 0000000000000000000000000000000000000000000000000000000000000000 print(bits) @@ -63,7 +63,7 @@ c.cardinality // 4 print("") print(~a) // 0111000000000000000000000000000000000000000000000000000000000000 print(~b) // 1101110000000000000000000000000000000000000000000000000000000000 -print(~c) // 0101110000000000000000000000000000000000000000000000000000000000 +print(~c) // 0101110000000000000000000000000000000000000000000000000000000000 (~a).cardinality // 3 (~b).cardinality // 5 diff --git a/Bit Set/BitSet.playground/Sources/BitSet.swift b/Bit Set/BitSet.playground/Sources/BitSet.swift index e54bf9cc8..46f51dbba 100644 --- a/Bit Set/BitSet.playground/Sources/BitSet.swift +++ b/Bit Set/BitSet.playground/Sources/BitSet.swift @@ -112,7 +112,7 @@ public struct BitSet { while x != 0 { let y = x & ~(x - 1) // find lowest 1-bit x = x ^ y // and erase it - ++count + count += 1 } } return count @@ -148,7 +148,7 @@ public struct BitSet { extension BitSet: Equatable { } -public func ==(lhs: BitSet, rhs: BitSet) -> Bool { +public func == (lhs: BitSet, rhs: BitSet) -> Bool { return lhs.words == rhs.words } @@ -184,7 +184,7 @@ private func copyLargest(lhs: BitSet, _ rhs: BitSet) -> BitSet { That will strip off the higher bits from the larger BitSet when doing &. */ -public func &(lhs: BitSet, rhs: BitSet) -> BitSet { +public func & (lhs: BitSet, rhs: BitSet) -> BitSet { let m = max(lhs.size, rhs.size) var out = BitSet(size: m) let n = min(lhs.words.count, rhs.words.count) @@ -194,7 +194,7 @@ public func &(lhs: BitSet, rhs: BitSet) -> BitSet { return out } -public func |(lhs: BitSet, rhs: BitSet) -> BitSet { +public func | (lhs: BitSet, rhs: BitSet) -> BitSet { var out = copyLargest(lhs, rhs) let n = min(lhs.words.count, rhs.words.count) for i in 0.. BitSet { return out } -public func ^(lhs: BitSet, rhs: BitSet) -> BitSet { +public func ^ (lhs: BitSet, rhs: BitSet) -> BitSet { var out = copyLargest(lhs, rhs) let n = min(lhs.words.count, rhs.words.count) for i in 0.. BitSet { return out } -prefix public func ~(rhs: BitSet) -> BitSet { +prefix public func ~ (rhs: BitSet) -> BitSet { var out = BitSet(size: rhs.size) for i in 0.. Bool { +public func == (lhs: BitSet, rhs: BitSet) -> Bool { return lhs.words == rhs.words } @@ -184,7 +184,7 @@ private func copyLargest(lhs: BitSet, _ rhs: BitSet) -> BitSet { That will strip off the higher bits from the larger BitSet when doing &. */ -public func &(lhs: BitSet, rhs: BitSet) -> BitSet { +public func & (lhs: BitSet, rhs: BitSet) -> BitSet { let m = max(lhs.size, rhs.size) var out = BitSet(size: m) let n = min(lhs.words.count, rhs.words.count) @@ -194,7 +194,7 @@ public func &(lhs: BitSet, rhs: BitSet) -> BitSet { return out } -public func |(lhs: BitSet, rhs: BitSet) -> BitSet { +public func | (lhs: BitSet, rhs: BitSet) -> BitSet { var out = copyLargest(lhs, rhs) let n = min(lhs.words.count, rhs.words.count) for i in 0.. BitSet { return out } -public func ^(lhs: BitSet, rhs: BitSet) -> BitSet { +public func ^ (lhs: BitSet, rhs: BitSet) -> BitSet { var out = copyLargest(lhs, rhs) let n = min(lhs.words.count, rhs.words.count) for i in 0.. BitSet { return out } -prefix public func ~(rhs: BitSet) -> BitSet { +prefix public func ~ (rhs: BitSet) -> BitSet { var out = BitSet(size: rhs.size) for i in 0.. { private var array: [Bool] private var hashFunctions: [T -> Int] - + public init(size: Int = 1024, hashFunctions: [T -> Int]) { self.array = .init(count: size, repeatedValue: false) self.hashFunctions = hashFunctions } - + private func computeHashes(value: T) -> [Int] { return hashFunctions.map() { hashFunc in abs(hashFunc(value) % array.count) } } - + public func insert(element: T) { for hashValue in computeHashes(element) { array[hashValue] = true } } - + public func insert(values: [T]) { for value in values { insert(value) } } - + public func query(value: T) -> Bool { let hashValues = computeHashes(value) - + // Map hashes to indices in the Bloom Filter let results = hashValues.map() { hashValue in array[hashValue] } - + // All values must be 'true' for the query to return true - + // This does NOT imply that the value is in the Bloom filter, // only that it may be. If the query returns false, however, // you can be certain that the value was not added. - + let exists = results.reduce(true, combine: { $0 && $1 }) return exists } - + public func isEmpty() -> Bool { // As soon as the reduction hits a 'true' value, the && condition will fail. return array.reduce(true) { prev, next in prev && !next } diff --git a/Bloom Filter/BloomFilter.swift b/Bloom Filter/BloomFilter.swift index 83787ee7b..97a982f48 100644 --- a/Bloom Filter/BloomFilter.swift +++ b/Bloom Filter/BloomFilter.swift @@ -1,44 +1,44 @@ public class BloomFilter { private var array: [Bool] private var hashFunctions: [T -> Int] - + public init(size: Int = 1024, hashFunctions: [T -> Int]) { self.array = .init(count: size, repeatedValue: false) self.hashFunctions = hashFunctions } - + private func computeHashes(value: T) -> [Int] { return hashFunctions.map() { hashFunc in abs(hashFunc(value) % array.count) } } - + public func insert(element: T) { for hashValue in computeHashes(element) { array[hashValue] = true } } - + public func insert(values: [T]) { for value in values { insert(value) } } - + public func query(value: T) -> Bool { let hashValues = computeHashes(value) - + // Map hashes to indices in the Bloom Filter let results = hashValues.map() { hashValue in array[hashValue] } - + // All values must be 'true' for the query to return true - + // This does NOT imply that the value is in the Bloom filter, // only that it may be. If the query returns false, however, // you can be certain that the value was not added. - + let exists = results.reduce(true, combine: { $0 && $1 }) return exists } - + public func isEmpty() -> Bool { // As soon as the reduction hits a 'true' value, the && condition will fail. return array.reduce(true) { prev, next in prev && !next } diff --git a/Bloom Filter/Tests/BloomFilterTests.swift b/Bloom Filter/Tests/BloomFilterTests.swift index 1248e0150..ffac8192d 100644 --- a/Bloom Filter/Tests/BloomFilterTests.swift +++ b/Bloom Filter/Tests/BloomFilterTests.swift @@ -5,72 +5,72 @@ import XCTest func djb2(x: String) -> Int { var hash = 5381 - + for char in x.characters { hash = ((hash << 5) &+ hash) &+ char.hashValue } - + return Int(hash) } func sdbm(x: String) -> Int { var hash = 0 - + for char in x.characters { - hash = char.hashValue &+ (hash << 6) &+ (hash << 16) &- hash; + hash = char.hashValue &+ (hash << 6) &+ (hash << 16) &- hash } - + return Int(hash) } class BloomFilterTests: XCTestCase { - + func testSingleHashFunction() { let bloom = BloomFilter(hashFunctions: [djb2]) - + bloom.insert("Hello world!") - + let result_good = bloom.query("Hello world!") let result_bad = bloom.query("Hello world") - + XCTAssertTrue(result_good) XCTAssertFalse(result_bad) } - + func testEmptyFilter() { let bloom = BloomFilter(hashFunctions: [djb2]) - + let empty = bloom.isEmpty() - + XCTAssertTrue(empty) } - + func testMultipleHashFunctions() { let bloom = BloomFilter(hashFunctions: [djb2, sdbm]) - + bloom.insert("Hello world!") - + let result_good = bloom.query("Hello world!") let result_bad = bloom.query("Hello world") - + XCTAssertTrue(result_good) XCTAssertFalse(result_bad) } - + func testFalsePositive() { let bloom = BloomFilter(size: 5, hashFunctions: [djb2, sdbm]) - + bloom.insert(["hello", "elloh", "llohe", "lohel", "ohell"]) - + print("Inserted") - + let query = bloom.query("This wasn't inserted!") - + // This is true even though we did not insert the value in the Bloom filter; - // the Bloom filter is capable of producing false positives but NOT + // the Bloom filter is capable of producing false positives but NOT // false negatives. - + XCTAssertTrue(query) } } diff --git a/Bounded Priority Queue/BoundedPriorityQueue.playground/Contents.swift b/Bounded Priority Queue/BoundedPriorityQueue.playground/Contents.swift index b4977d6ce..1bc678ccc 100644 --- a/Bounded Priority Queue/BoundedPriorityQueue.playground/Contents.swift +++ b/Bounded Priority Queue/BoundedPriorityQueue.playground/Contents.swift @@ -1,17 +1,17 @@ struct Message: Comparable, CustomStringConvertible { let name: String let priority: Int - + var description: String { return "\(name):\(priority)" } } -func ==(m1: Message, m2: Message) -> Bool { +func == (m1: Message, m2: Message) -> Bool { return m1.priority == m2.priority } -func <(m1: Message, m2: Message) -> Bool { +func < (m1: Message, m2: Message) -> Bool { return m1.priority < m2.priority } @@ -63,7 +63,7 @@ queue.count queue.peek() print(queue) -// Try to insert an item with very high priority. This gets added and the +// Try to insert an item with very high priority. This gets added and the // lowest priority item is removed. queue.enqueue(Message(name: "!!!", priority: 500)) queue.count diff --git a/Bounded Priority Queue/BoundedPriorityQueue.playground/Sources/BoundedPriorityQueue.swift b/Bounded Priority Queue/BoundedPriorityQueue.playground/Sources/BoundedPriorityQueue.swift index 99f00d70c..58dc5034e 100644 --- a/Bounded Priority Queue/BoundedPriorityQueue.playground/Sources/BoundedPriorityQueue.swift +++ b/Bounded Priority Queue/BoundedPriorityQueue.playground/Sources/BoundedPriorityQueue.swift @@ -2,7 +2,7 @@ public class LinkedListNode { var value: T var next: LinkedListNode? var previous: LinkedListNode? - + public init(value: T) { self.value = value } @@ -61,7 +61,7 @@ public class BoundedPriorityQueue { previous.next = node node.previous = previous return node - + } else if let first = head { // Have to insert at the head, so shift the existing head up once place. head = Node(value: value) @@ -81,7 +81,7 @@ public class BoundedPriorityQueue { private func findInsertionPoint(value: T) -> Node? { var node = head var prev: Node? = nil - + while let current = node where value < current.value { prev = node node = current.next diff --git a/Bounded Priority Queue/Tests/BoundedPriorityQueueTests.swift b/Bounded Priority Queue/Tests/BoundedPriorityQueueTests.swift index c6ab5d554..b248c17ad 100644 --- a/Bounded Priority Queue/Tests/BoundedPriorityQueueTests.swift +++ b/Bounded Priority Queue/Tests/BoundedPriorityQueueTests.swift @@ -12,15 +12,15 @@ private struct Message: Comparable { let priority: Int } -private func ==(m1: Message, m2: Message) -> Bool { +private func == (m1: Message, m2: Message) -> Bool { return m1.priority == m2.priority } -private func <(m1: Message, m2: Message) -> Bool { +private func < (m1: Message, m2: Message) -> Bool { return m1.priority < m2.priority } -private func >(m1: Message, m2: Message) -> Bool { +private func > (m1: Message, m2: Message) -> Bool { return m1.priority > m2.priority } diff --git a/Boyer-Moore/BoyerMoore.playground/Contents.swift b/Boyer-Moore/BoyerMoore.playground/Contents.swift index 926a76f93..433935133 100644 --- a/Boyer-Moore/BoyerMoore.playground/Contents.swift +++ b/Boyer-Moore/BoyerMoore.playground/Contents.swift @@ -5,16 +5,16 @@ extension String { let patternLength = pattern.characters.count assert(patternLength > 0) assert(patternLength <= self.characters.count) - + var skipTable = [Character: Int]() for (i, c) in pattern.characters.enumerate() { skipTable[c] = patternLength - i - 1 } - + let p = pattern.endIndex.predecessor() let lastChar = pattern[p] var i = self.startIndex.advancedBy(patternLength - 1) - + func backwards() -> String.Index? { var q = p var j = i @@ -25,7 +25,7 @@ extension String { } return j } - + while i < self.endIndex { let c = self[i] if c == lastChar { diff --git a/Boyer-Moore/BoyerMoore.swift b/Boyer-Moore/BoyerMoore.swift index 50aa88048..12a1d86c1 100644 --- a/Boyer-Moore/BoyerMoore.swift +++ b/Boyer-Moore/BoyerMoore.swift @@ -12,24 +12,24 @@ extension String { let patternLength = pattern.characters.count assert(patternLength > 0) assert(patternLength <= self.characters.count) - + // Make the skip table. This table determines how far we skip ahead // when a character from the pattern is found. var skipTable = [Character: Int]() for (i, c) in pattern.characters.enumerate() { skipTable[c] = patternLength - i - 1 } - + // This points at the last character in the pattern. let p = pattern.endIndex.predecessor() let lastChar = pattern[p] - + // The pattern is scanned right-to-left, so skip ahead in the string by // the length of the pattern. (Minus 1 because startIndex already points // at the first character in the source string.) var i = self.startIndex.advancedBy(patternLength - 1) - - // This is a helper function that steps backwards through both strings + + // This is a helper function that steps backwards through both strings // until we find a character that doesn’t match, or until we’ve reached // the beginning of the pattern. func backwards() -> String.Index? { @@ -42,17 +42,17 @@ extension String { } return j } - + // The main loop. Keep going until the end of the string is reached. while i < self.endIndex { let c = self[i] - + // Does the current character match the last character from the pattern? if c == lastChar { - + // There is a possible match. Do a brute-force search backwards. if let k = backwards() { return k } - + // If no match, we can only safely skip one character ahead. i = i.successor() } else { diff --git a/Breadth-First Search/BreadthFirstSearch.playground/Sources/Edge.swift b/Breadth-First Search/BreadthFirstSearch.playground/Sources/Edge.swift index 3937a2cc7..9a58a1f96 100644 --- a/Breadth-First Search/BreadthFirstSearch.playground/Sources/Edge.swift +++ b/Breadth-First Search/BreadthFirstSearch.playground/Sources/Edge.swift @@ -1,4 +1,4 @@ -public class Edge : Equatable { +public class Edge: Equatable { public var neighbor: Node public init(neighbor: Node) { @@ -6,6 +6,6 @@ public class Edge : Equatable { } } -public func ==(lhs: Edge, rhs: Edge) -> Bool { +public func == (lhs: Edge, rhs: Edge) -> Bool { return lhs.neighbor == rhs.neighbor } diff --git a/Breadth-First Search/BreadthFirstSearch.playground/Sources/Graph.swift b/Breadth-First Search/BreadthFirstSearch.playground/Sources/Graph.swift index e89d4ac97..8cfb2a09c 100644 --- a/Breadth-First Search/BreadthFirstSearch.playground/Sources/Graph.swift +++ b/Breadth-First Search/BreadthFirstSearch.playground/Sources/Graph.swift @@ -1,4 +1,4 @@ -public class Graph : CustomStringConvertible, Equatable { +public class Graph: CustomStringConvertible, Equatable { public private(set) var nodes: [Node] public init() { @@ -21,14 +21,14 @@ public class Graph : CustomStringConvertible, Equatable { for node in nodes { if !node.neighbors.isEmpty { - description += "[node: \(node.label) edges: \(node.neighbors.map{ $0.neighbor.label})]" + description += "[node: \(node.label) edges: \(node.neighbors.map { $0.neighbor.label})]" } } return description } public func findNodeWithLabel(label: String) -> Node { - return nodes.filter{ $0.label == label }.first! + return nodes.filter { $0.label == label }.first! } public func duplicate() -> Graph { @@ -50,6 +50,6 @@ public class Graph : CustomStringConvertible, Equatable { } } -public func ==(lhs: Graph, rhs: Graph) -> Bool { +public func == (lhs: Graph, rhs: Graph) -> Bool { return lhs.nodes == rhs.nodes } diff --git a/Breadth-First Search/BreadthFirstSearch.playground/Sources/Node.swift b/Breadth-First Search/BreadthFirstSearch.playground/Sources/Node.swift index 9d8435ffa..37a3b3fdf 100644 --- a/Breadth-First Search/BreadthFirstSearch.playground/Sources/Node.swift +++ b/Breadth-First Search/BreadthFirstSearch.playground/Sources/Node.swift @@ -1,4 +1,4 @@ -public class Node : CustomStringConvertible, Equatable { +public class Node: CustomStringConvertible, Equatable { public var neighbors: [Edge] public private(set) var label: String @@ -23,10 +23,10 @@ public class Node : CustomStringConvertible, Equatable { } public func remove(edge: Edge) { - neighbors.removeAtIndex(neighbors.indexOf{ $0 === edge }!) + neighbors.removeAtIndex(neighbors.indexOf { $0 === edge }!) } } -public func ==(lhs: Node, rhs: Node) -> Bool { +public func == (lhs: Node, rhs: Node) -> Bool { return lhs.label == rhs.label && lhs.neighbors == rhs.neighbors } diff --git a/Breadth-First Search/BreadthFirstSearch.swift b/Breadth-First Search/BreadthFirstSearch.swift index 296bf42ed..aa396ac7b 100644 --- a/Breadth-First Search/BreadthFirstSearch.swift +++ b/Breadth-First Search/BreadthFirstSearch.swift @@ -4,7 +4,7 @@ func breadthFirstSearch(graph: Graph, source: Node) -> [String] { var nodesExplored = [source.label] source.visited = true - + while let current = queue.dequeue() { for edge in current.neighbors { let neighborNode = edge.neighbor diff --git a/Breadth-First Search/Tests/Graph.swift b/Breadth-First Search/Tests/Graph.swift index 6f69ee800..ed71cab7c 100644 --- a/Breadth-First Search/Tests/Graph.swift +++ b/Breadth-First Search/Tests/Graph.swift @@ -1,6 +1,6 @@ // MARK: - Edge -public class Edge : Equatable { +public class Edge: Equatable { public var neighbor: Node public init(neighbor: Node) { @@ -8,15 +8,15 @@ public class Edge : Equatable { } } -public func ==(lhs: Edge, rhs: Edge) -> Bool { +public func == (lhs: Edge, rhs: Edge) -> Bool { return lhs.neighbor == rhs.neighbor } // MARK: - Node -public class Node : CustomStringConvertible, Equatable { +public class Node: CustomStringConvertible, Equatable { public var neighbors: [Edge] - + public private(set) var label: String public var distance: Int? public var visited: Bool @@ -39,17 +39,17 @@ public class Node : CustomStringConvertible, Equatable { } public func remove(edge: Edge) { - neighbors.removeAtIndex(neighbors.indexOf{ $0 === edge }!) + neighbors.removeAtIndex(neighbors.indexOf { $0 === edge }!) } } -public func ==(lhs: Node, rhs: Node) -> Bool { +public func == (lhs: Node, rhs: Node) -> Bool { return lhs.label == rhs.label && lhs.neighbors == rhs.neighbors } // MARK: - Graph -public class Graph : CustomStringConvertible, Equatable { +public class Graph: CustomStringConvertible, Equatable { public private(set) var nodes: [Node] public init() { @@ -72,14 +72,14 @@ public class Graph : CustomStringConvertible, Equatable { for node in nodes { if !node.neighbors.isEmpty { - description += "[node: \(node.label) edges: \(node.neighbors.map{ $0.neighbor.label})]" + description += "[node: \(node.label) edges: \(node.neighbors.map { $0.neighbor.label})]" } } return description } public func findNodeWithLabel(label: String) -> Node { - return nodes.filter{ $0.label == label }.first! + return nodes.filter { $0.label == label }.first! } public func duplicate() -> Graph { @@ -101,6 +101,6 @@ public class Graph : CustomStringConvertible, Equatable { } } -public func ==(lhs: Graph, rhs: Graph) -> Bool { +public func == (lhs: Graph, rhs: Graph) -> Bool { return lhs.nodes == rhs.nodes } diff --git a/Bucket Sort/BucketSort.playground/Contents.swift b/Bucket Sort/BucketSort.playground/Contents.swift index 32cd6ed29..f7383746c 100644 --- a/Bucket Sort/BucketSort.playground/Contents.swift +++ b/Bucket Sort/BucketSort.playground/Contents.swift @@ -37,10 +37,9 @@ extension Int: IntConvertible, Sortable { // MARK: Playing code ////////////////////////////////////// -let input = [1,2,4,6,10] -let buckets = [Bucket(capacity: 15),Bucket(capacity: 15),Bucket(capacity: 15)] +let input = [1, 2, 4, 6, 10] +let buckets = [Bucket(capacity: 15), Bucket(capacity: 15), Bucket(capacity: 15)] let sortedElements = bucketSort(input, distributor: RangeDistributor(), sorter: InsertionSorter(), buckets: buckets) print(sortedElements) - diff --git a/Bucket Sort/BucketSort.playground/Sources/BucketSort.swift b/Bucket Sort/BucketSort.playground/Sources/BucketSort.swift index 8dfa80cd4..c93b96cb2 100644 --- a/Bucket Sort/BucketSort.playground/Sources/BucketSort.swift +++ b/Bucket Sort/BucketSort.playground/Sources/BucketSort.swift @@ -27,18 +27,18 @@ import Foundation ////////////////////////////////////// -public func bucketSort(elements: [T], distributor: Distributor,sorter: Sorter, buckets: [Bucket]) -> [T] { +public func bucketSort(elements: [T], distributor: Distributor, sorter: Sorter, buckets: [Bucket]) -> [T] { var bucketsCopy = buckets for elem in elements { distributor.distribute(elem, buckets: &bucketsCopy) } - + var results = [T]() - + for bucket in buckets { results += bucket.sort(sorter) } - + return results } @@ -48,7 +48,7 @@ public func bucketSort(elements: [T], distributor: Distributor,sorte public protocol Distributor { - func distribute(element: T, inout buckets: [Bucket]) + func distribute(element: T, inout buckets: [Bucket]) } /* @@ -67,13 +67,13 @@ public protocol Distributor { * By following the formula: element / capacity = #ofBucket */ public struct RangeDistributor: Distributor { - + public init() {} - - public func distribute(element: T, inout buckets: [Bucket]) { + + public func distribute(element: T, inout buckets: [Bucket]) { let value = element.toInt() let bucketCapacity = buckets.first!.capacity - + let bucketIndex = value / bucketCapacity buckets[bucketIndex].add(element) } @@ -95,23 +95,23 @@ public protocol Sortable: IntConvertible, Comparable { ////////////////////////////////////// public protocol Sorter { - func sort(items: [T]) -> [T] + func sort(items: [T]) -> [T] } public struct InsertionSorter: Sorter { - + public init() {} - - public func sort(items: [T]) -> [T] { + + public func sort(items: [T]) -> [T] { var results = items for i in 0 ..< results.count { var j = i - while ( j > 0 && results[j-i] > results[j]) { - + while j > 0 && results[j-i] > results[j] { + let auxiliar = results[i] results[i] = results[j] results[j] = auxiliar - + j -= 1 } } @@ -126,18 +126,18 @@ public struct InsertionSorter: Sorter { public struct Bucket { var elements: [T] let capacity: Int - + public init(capacity: Int) { self.capacity = capacity elements = [T]() } - + public mutating func add(item: T) { - if (elements.count < capacity) { + if elements.count < capacity { elements.append(item) } } - + public func sort(algorithm: Sorter) -> [T] { return algorithm.sort(elements) } diff --git a/Bucket Sort/BucketSort.swift b/Bucket Sort/BucketSort.swift index c28eb0284..8363fd867 100644 --- a/Bucket Sort/BucketSort.swift +++ b/Bucket Sort/BucketSort.swift @@ -30,41 +30,41 @@ import Foundation /** Performs bucket sort algorithm on the given input elements. [Bucket Sort Algorithm Reference](https://en.wikipedia.org/wiki/Bucket_sort) - + - Parameter elements: Array of Sortable elements - Parameter distributor: Performs the distribution of each element of a bucket - Parameter sorter: Performs the sorting inside each bucket, after all the elements are distributed - Parameter buckets: An array of buckets - + - Returns: A new array with sorted elements */ -public func bucketSort(elements: [T], distributor: Distributor,sorter: Sorter, buckets: [Bucket]) -> [T] { +public func bucketSort(elements: [T], distributor: Distributor, sorter: Sorter, buckets: [Bucket]) -> [T] { precondition(allPositiveNumbers(elements)) precondition(enoughSpaceInBuckets(buckets, elements: elements)) - + var bucketsCopy = buckets for elem in elements { distributor.distribute(elem, buckets: &bucketsCopy) } - + var results = [T]() - + for bucket in bucketsCopy { results += bucket.sort(sorter) } - + return results } -private func allPositiveNumbers(array: [T]) -> Bool { - return array.filter{ $0.toInt() >= 0 }.count > 0 +private func allPositiveNumbers(array: [T]) -> Bool { + return array.filter { $0.toInt() >= 0 }.count > 0 } -private func enoughSpaceInBuckets(buckets: [Bucket], elements: [T]) -> Bool { +private func enoughSpaceInBuckets(buckets: [Bucket], elements: [T]) -> Bool { let maximumValue = elements.maxElement()?.toInt() let totalCapacity = buckets.count * (buckets.first?.capacity)! - + return totalCapacity >= maximumValue } @@ -74,7 +74,7 @@ private func enoughSpaceInBuckets(buckets: [Bucket], elements: [T public protocol Distributor { - func distribute(element: T, inout buckets: [Bucket]) + func distribute(element: T, inout buckets: [Bucket]) } /* @@ -93,13 +93,13 @@ public protocol Distributor { * By following the formula: element / capacity = #ofBucket */ public struct RangeDistributor: Distributor { - + public init() {} - - public func distribute(element: T, inout buckets: [Bucket]) { + + public func distribute(element: T, inout buckets: [Bucket]) { let value = element.toInt() let bucketCapacity = buckets.first!.capacity - + let bucketIndex = value / bucketCapacity buckets[bucketIndex].add(element) } @@ -121,23 +121,23 @@ public protocol Sortable: IntConvertible, Comparable { ////////////////////////////////////// public protocol Sorter { - func sort(items: [T]) -> [T] + func sort(items: [T]) -> [T] } public struct InsertionSorter: Sorter { - + public init() {} - - public func sort(items: [T]) -> [T] { + + public func sort(items: [T]) -> [T] { var results = items for i in 0 ..< results.count { var j = i - while ( j > 0 && results[j-1] > results[j]) { - + while j > 0 && results[j-1] > results[j] { + let auxiliar = results[j-1] results[j-1] = results[j] results[j] = auxiliar - + j -= 1 } } @@ -152,18 +152,18 @@ public struct InsertionSorter: Sorter { public struct Bucket { var elements: [T] let capacity: Int - + public init(capacity: Int) { self.capacity = capacity elements = [T]() } - + public mutating func add(item: T) { - if (elements.count < capacity) { + if elements.count < capacity { elements.append(item) } } - + public func sort(algorithm: Sorter) -> [T] { return algorithm.sort(elements) } diff --git a/Bucket Sort/Tests/Tests.swift b/Bucket Sort/Tests/Tests.swift index f3b897b2b..22ac751de 100644 --- a/Bucket Sort/Tests/Tests.swift +++ b/Bucket Sort/Tests/Tests.swift @@ -9,79 +9,79 @@ import XCTest class TestTests: XCTestCase { - + var smallArray: [Int]? let total = 400 let maximum = 1000 var largeArray: [Int]? - + var sparsedArray: [Int]? - + override func setUp() { super.setUp() - - smallArray = [8,3,33,0,12,8,2,18] - + + smallArray = [8, 3, 33, 0, 12, 8, 2, 18] + largeArray = [Int]() for _ in 0.. [Int] { let value = (elements.maxElement()?.toInt())! + 1 let capacityRequired = Int( ceil( Double(value) / Double(totalBuckets) ) ) - + var buckets = [Bucket]() for _ in 0..(capacity: capacityRequired)) } - + let results = bucketSort(smallArray!, distributor: RangeDistributor(), sorter: InsertionSorter(), buckets: buckets) return results } - + func isSorted(array: [Int]) -> Bool { - + var index = 0 var sorted = true while index < (array.count - 1) && sorted { - if (array[index] > array[index+1]) { + if array[index] > array[index+1] { sorted = false } index += 1 } - + return sorted } } diff --git a/Combinatorics/Combinatorics.playground/Contents.swift b/Combinatorics/Combinatorics.playground/Contents.swift index 6dde6a9e0..5cb91967e 100644 --- a/Combinatorics/Combinatorics.playground/Contents.swift +++ b/Combinatorics/Combinatorics.playground/Contents.swift @@ -184,4 +184,3 @@ func binomialCoefficient(n: Int, _ k: Int) -> Int { binomialCoefficient(30, 15) binomialCoefficient(66, 33) - diff --git a/Count Occurrences/CountOccurrences.playground/Contents.swift b/Count Occurrences/CountOccurrences.playground/Contents.swift index 3a7ea9713..b90ba12ce 100644 --- a/Count Occurrences/CountOccurrences.playground/Contents.swift +++ b/Count Occurrences/CountOccurrences.playground/Contents.swift @@ -14,7 +14,7 @@ func countOccurrencesOfKey(key: Int, inArray a: [Int]) -> Int { } return low } - + func rightBoundary() -> Int { var low = 0 var high = a.count @@ -28,7 +28,7 @@ func countOccurrencesOfKey(key: Int, inArray a: [Int]) -> Int { } return low } - + return rightBoundary() - leftBoundary() } diff --git a/Counting Sort/CountingSort.playground/Contents.swift b/Counting Sort/CountingSort.playground/Contents.swift index 13249aea8..67d416f2f 100644 --- a/Counting Sort/CountingSort.playground/Contents.swift +++ b/Counting Sort/CountingSort.playground/Contents.swift @@ -8,11 +8,11 @@ func countingSort(array: [Int]) throws -> [Int] { guard array.count > 0 else { throw CountingSortError.ArrayEmpty } - + // Step 1 // Create an array to store the count of each element let maxElement = array.maxElement() ?? 0 - + var countArray = [Int](count: Int(maxElement + 1), repeatedValue: 0) for element in array { countArray[element] += 1 diff --git a/Counting Sort/CountingSort.swift b/Counting Sort/CountingSort.swift index 156782fef..ec8c5adcb 100644 --- a/Counting Sort/CountingSort.swift +++ b/Counting Sort/CountingSort.swift @@ -14,11 +14,11 @@ func countingSort(array: [Int]) throws -> [Int] { guard array.count > 0 else { throw CountingSortError.ArrayEmpty } - + // Step 1 // Create an array to store the count of each element let maxElement = array.maxElement() ?? 0 - + var countArray = [Int](count: Int(maxElement + 1), repeatedValue: 0) for element in array { countArray[element] += 1 diff --git a/Counting Sort/Tests/CountingSortTest.swift b/Counting Sort/Tests/CountingSortTest.swift index fba639ba4..d8d73fc76 100644 --- a/Counting Sort/Tests/CountingSortTest.swift +++ b/Counting Sort/Tests/CountingSortTest.swift @@ -9,11 +9,11 @@ import XCTest class CountingSort: XCTestCase { - + func testCountingSort() { let sequence = [10, 8, 1, 2, 5, 8] let sortedSequence = [1, 2, 5, 8, 8, 10] - + do { let afterCountingSort = try countingSort(sequence) XCTAssertEqual(afterCountingSort, sortedSequence) diff --git a/Depth-First Search/DepthFirstSearch.playground/Sources/Edge.swift b/Depth-First Search/DepthFirstSearch.playground/Sources/Edge.swift index 3937a2cc7..9a58a1f96 100644 --- a/Depth-First Search/DepthFirstSearch.playground/Sources/Edge.swift +++ b/Depth-First Search/DepthFirstSearch.playground/Sources/Edge.swift @@ -1,4 +1,4 @@ -public class Edge : Equatable { +public class Edge: Equatable { public var neighbor: Node public init(neighbor: Node) { @@ -6,6 +6,6 @@ public class Edge : Equatable { } } -public func ==(lhs: Edge, rhs: Edge) -> Bool { +public func == (lhs: Edge, rhs: Edge) -> Bool { return lhs.neighbor == rhs.neighbor } diff --git a/Depth-First Search/DepthFirstSearch.playground/Sources/Graph.swift b/Depth-First Search/DepthFirstSearch.playground/Sources/Graph.swift index e89d4ac97..8cfb2a09c 100644 --- a/Depth-First Search/DepthFirstSearch.playground/Sources/Graph.swift +++ b/Depth-First Search/DepthFirstSearch.playground/Sources/Graph.swift @@ -1,4 +1,4 @@ -public class Graph : CustomStringConvertible, Equatable { +public class Graph: CustomStringConvertible, Equatable { public private(set) var nodes: [Node] public init() { @@ -21,14 +21,14 @@ public class Graph : CustomStringConvertible, Equatable { for node in nodes { if !node.neighbors.isEmpty { - description += "[node: \(node.label) edges: \(node.neighbors.map{ $0.neighbor.label})]" + description += "[node: \(node.label) edges: \(node.neighbors.map { $0.neighbor.label})]" } } return description } public func findNodeWithLabel(label: String) -> Node { - return nodes.filter{ $0.label == label }.first! + return nodes.filter { $0.label == label }.first! } public func duplicate() -> Graph { @@ -50,6 +50,6 @@ public class Graph : CustomStringConvertible, Equatable { } } -public func ==(lhs: Graph, rhs: Graph) -> Bool { +public func == (lhs: Graph, rhs: Graph) -> Bool { return lhs.nodes == rhs.nodes } diff --git a/Depth-First Search/DepthFirstSearch.playground/Sources/Node.swift b/Depth-First Search/DepthFirstSearch.playground/Sources/Node.swift index 9d8435ffa..37a3b3fdf 100644 --- a/Depth-First Search/DepthFirstSearch.playground/Sources/Node.swift +++ b/Depth-First Search/DepthFirstSearch.playground/Sources/Node.swift @@ -1,4 +1,4 @@ -public class Node : CustomStringConvertible, Equatable { +public class Node: CustomStringConvertible, Equatable { public var neighbors: [Edge] public private(set) var label: String @@ -23,10 +23,10 @@ public class Node : CustomStringConvertible, Equatable { } public func remove(edge: Edge) { - neighbors.removeAtIndex(neighbors.indexOf{ $0 === edge }!) + neighbors.removeAtIndex(neighbors.indexOf { $0 === edge }!) } } -public func ==(lhs: Node, rhs: Node) -> Bool { +public func == (lhs: Node, rhs: Node) -> Bool { return lhs.label == rhs.label && lhs.neighbors == rhs.neighbors } diff --git a/Depth-First Search/Tests/Graph.swift b/Depth-First Search/Tests/Graph.swift index 6f69ee800..ed71cab7c 100644 --- a/Depth-First Search/Tests/Graph.swift +++ b/Depth-First Search/Tests/Graph.swift @@ -1,6 +1,6 @@ // MARK: - Edge -public class Edge : Equatable { +public class Edge: Equatable { public var neighbor: Node public init(neighbor: Node) { @@ -8,15 +8,15 @@ public class Edge : Equatable { } } -public func ==(lhs: Edge, rhs: Edge) -> Bool { +public func == (lhs: Edge, rhs: Edge) -> Bool { return lhs.neighbor == rhs.neighbor } // MARK: - Node -public class Node : CustomStringConvertible, Equatable { +public class Node: CustomStringConvertible, Equatable { public var neighbors: [Edge] - + public private(set) var label: String public var distance: Int? public var visited: Bool @@ -39,17 +39,17 @@ public class Node : CustomStringConvertible, Equatable { } public func remove(edge: Edge) { - neighbors.removeAtIndex(neighbors.indexOf{ $0 === edge }!) + neighbors.removeAtIndex(neighbors.indexOf { $0 === edge }!) } } -public func ==(lhs: Node, rhs: Node) -> Bool { +public func == (lhs: Node, rhs: Node) -> Bool { return lhs.label == rhs.label && lhs.neighbors == rhs.neighbors } // MARK: - Graph -public class Graph : CustomStringConvertible, Equatable { +public class Graph: CustomStringConvertible, Equatable { public private(set) var nodes: [Node] public init() { @@ -72,14 +72,14 @@ public class Graph : CustomStringConvertible, Equatable { for node in nodes { if !node.neighbors.isEmpty { - description += "[node: \(node.label) edges: \(node.neighbors.map{ $0.neighbor.label})]" + description += "[node: \(node.label) edges: \(node.neighbors.map { $0.neighbor.label})]" } } return description } public func findNodeWithLabel(label: String) -> Node { - return nodes.filter{ $0.label == label }.first! + return nodes.filter { $0.label == label }.first! } public func duplicate() -> Graph { @@ -101,6 +101,6 @@ public class Graph : CustomStringConvertible, Equatable { } } -public func ==(lhs: Graph, rhs: Graph) -> Bool { +public func == (lhs: Graph, rhs: Graph) -> Bool { return lhs.nodes == rhs.nodes } diff --git a/Deque/Deque-Optimized.swift b/Deque/Deque-Optimized.swift index 3b0d724dd..ea68059c0 100644 --- a/Deque/Deque-Optimized.swift +++ b/Deque/Deque-Optimized.swift @@ -7,25 +7,25 @@ public struct Deque { private var array: [T?] private var head: Int private var capacity: Int - + public init(capacity: Int = 10) { self.capacity = max(capacity, 1) array = .init(count: capacity, repeatedValue: nil) head = capacity } - + public var isEmpty: Bool { return count == 0 } - + public var count: Int { return array.count - head } - + public mutating func enqueue(element: T) { array.append(element) } - + public mutating func enqueueFront(element: T) { if head == 0 { capacity *= 2 @@ -52,7 +52,7 @@ public struct Deque { } return element } - + public mutating func dequeueBack() -> T? { if isEmpty { return nil @@ -60,7 +60,7 @@ public struct Deque { return array.removeLast() } } - + public func peekFront() -> T? { if isEmpty { return nil @@ -68,7 +68,7 @@ public struct Deque { return array[head] } } - + public func peekBack() -> T? { if isEmpty { return nil diff --git a/Deque/Deque-Simple.swift b/Deque/Deque-Simple.swift index c1b2489a7..0ccba0caa 100644 --- a/Deque/Deque-Simple.swift +++ b/Deque/Deque-Simple.swift @@ -2,7 +2,7 @@ Deque (pronounced "deck"), a double-ended queue This particular implementation is simple but not very efficient. Several - operations are O(n). A more efficient implementation would use a doubly + operations are O(n). A more efficient implementation would use a doubly linked list or a circular buffer. */ public struct Deque { diff --git a/Deque/Deque.playground/Contents.swift b/Deque/Deque.playground/Contents.swift index e3cedd706..15bf1ee07 100644 --- a/Deque/Deque.playground/Contents.swift +++ b/Deque/Deque.playground/Contents.swift @@ -2,23 +2,23 @@ public struct Deque { private var array = [T]() - + public var isEmpty: Bool { return array.isEmpty } - + public var count: Int { return array.count } - + public mutating func enqueue(element: T) { array.append(element) } - + public mutating func enqueueFront(element: T) { array.insert(element, atIndex: 0) } - + public mutating func dequeue() -> T? { if isEmpty { return nil @@ -26,7 +26,7 @@ public struct Deque { return array.removeFirst() } } - + public mutating func dequeueBack() -> T? { if isEmpty { return nil @@ -34,11 +34,11 @@ public struct Deque { return array.removeLast() } } - + public func peekFront() -> T? { return array.first } - + public func peekBack() -> T? { return array.last } diff --git a/GCD/GCD.playground/Contents.swift b/GCD/GCD.playground/Contents.swift index 387d5de94..dedf6e293 100644 --- a/GCD/GCD.playground/Contents.swift +++ b/GCD/GCD.playground/Contents.swift @@ -16,7 +16,7 @@ func gcd(m: Int, _ n: Int) -> Int { var a = 0 var b = max(m, n) var r = min(m, n) - + while r != 0 { a = b b = r diff --git a/Graph/Graph/Edge.swift b/Graph/Graph/Edge.swift index 5ce865af6..a867e164a 100644 --- a/Graph/Graph/Edge.swift +++ b/Graph/Graph/Edge.swift @@ -8,7 +8,7 @@ import Foundation public struct Edge: Equatable { - + public let from: Vertex public let to: Vertex @@ -43,7 +43,7 @@ extension Edge: Hashable { } -public func ==(lhs: Edge, rhs: Edge) -> Bool { +public func == (lhs: Edge, rhs: Edge) -> Bool { guard lhs.from == rhs.from else { return false } diff --git a/Graph/GraphTests/GraphTests.swift b/Graph/GraphTests/GraphTests.swift index e6360754e..0a2c8042f 100644 --- a/Graph/GraphTests/GraphTests.swift +++ b/Graph/GraphTests/GraphTests.swift @@ -9,7 +9,7 @@ import XCTest @testable import Graph class GraphTests: XCTestCase { - + func testAdjacencyMatrixGraphDescription() { let graph = AdjacencyMatrixGraph() @@ -53,5 +53,5 @@ class GraphTests: XCTestCase { XCTAssertEqual(graph.vertices.count, 1, "Graph should only contain one vertex after trying to create two vertices with identical data") } } - + } diff --git a/Hash Set/HashSet.playground/Contents.swift b/Hash Set/HashSet.playground/Contents.swift index d49864fa3..636d4d925 100644 --- a/Hash Set/HashSet.playground/Contents.swift +++ b/Hash Set/HashSet.playground/Contents.swift @@ -2,27 +2,27 @@ public struct HashSet { private var dictionary = Dictionary() - + public mutating func insert(element: T) { dictionary[element] = true } - + public mutating func remove(element: T) { dictionary[element] = nil } - + public func contains(element: T) -> Bool { return dictionary[element] != nil } - + public func allElements() -> [T] { return Array(dictionary.keys) } - + public var count: Int { return dictionary.count } - + public var isEmpty: Bool { return dictionary.isEmpty } diff --git a/Hash Set/HashSet.swift b/Hash Set/HashSet.swift index 57f8f2219..303353574 100644 --- a/Hash Set/HashSet.swift +++ b/Hash Set/HashSet.swift @@ -1,26 +1,26 @@ public struct HashSet { private var dictionary = Dictionary() - + public mutating func insert(element: T) { dictionary[element] = true } - + public mutating func remove(element: T) { dictionary[element] = nil } - + public func contains(element: T) -> Bool { return dictionary[element] != nil } - + public func allElements() -> [T] { return Array(dictionary.keys) } - + public var count: Int { return dictionary.count } - + public var isEmpty: Bool { return dictionary.isEmpty } diff --git a/Hash Table/HashTable.playground/Contents.swift b/Hash Table/HashTable.playground/Contents.swift index d5788176a..cda0919de 100644 --- a/Hash Table/HashTable.playground/Contents.swift +++ b/Hash Table/HashTable.playground/Contents.swift @@ -3,19 +3,19 @@ public struct HashTable { private typealias Element = (key: Key, value: Value) private typealias Bucket = [Element] - + private var buckets: [Bucket] private(set) var count = 0 - + public init(capacity: Int) { assert(capacity > 0) buckets = .init(count: capacity, repeatedValue: []) } - + public var isEmpty: Bool { return count == 0 } - + private func indexForKey(key: Key) -> Int { return abs(key.hashValue) % buckets.count } @@ -34,7 +34,7 @@ extension HashTable { } } } - + public func valueForKey(key: Key) -> Value? { let index = indexForKey(key) @@ -48,7 +48,7 @@ extension HashTable { public mutating func updateValue(value: Value, forKey key: Key) -> Value? { let index = indexForKey(key) - + // Do we already have this key in the bucket? for (i, element) in buckets[index].enumerate() { if element.key == key { @@ -57,13 +57,13 @@ extension HashTable { return oldValue } } - + // This key isn't in the bucket yet; add it to the chain. buckets[index].append((key: key, value: value)) count += 1 return nil } - + public mutating func removeValueForKey(key: Key) -> Value? { let index = indexForKey(key) @@ -77,7 +77,7 @@ extension HashTable { } return nil // key not in hash table } - + public mutating func removeAll() { buckets = .init(count: buckets.count, repeatedValue: []) count = 0 diff --git a/Hash Table/HashTable.swift b/Hash Table/HashTable.swift index da9ca9064..46c73e284 100644 --- a/Hash Table/HashTable.swift +++ b/Hash Table/HashTable.swift @@ -14,7 +14,7 @@ own bucket. In practice that is hard to achieve. When there is more than one hash value that maps to the same bucket index - -- a "collision" -- they are chained together, using an array. (Note that + -- a "collision" -- they are chained together, using an array. (Note that more clever ways exist for dealing with the chaining issue.) While there are free buckets, inserting/retrieving/removing are O(1). @@ -33,19 +33,19 @@ public struct HashTable { private typealias Element = (key: Key, value: Value) private typealias Bucket = [Element] - + private var buckets: [Bucket] private(set) var count = 0 - + public init(capacity: Int) { assert(capacity > 0) buckets = .init(count: capacity, repeatedValue: []) } - + public var isEmpty: Bool { return count == 0 } - + private func indexForKey(key: Key) -> Int { return abs(key.hashValue) % buckets.count } @@ -66,10 +66,10 @@ extension HashTable { } } } - + public func valueForKey(key: Key) -> Value? { let index = indexForKey(key) - + for element in buckets[index] { if element.key == key { return element.value @@ -77,10 +77,10 @@ extension HashTable { } return nil // key not in hash table } - + public mutating func updateValue(value: Value, forKey key: Key) -> Value? { let index = indexForKey(key) - + // Do we already have this key in the bucket? for (i, element) in buckets[index].enumerate() { if element.key == key { @@ -89,16 +89,16 @@ extension HashTable { return oldValue } } - + // This key isn't in the bucket yet; add it to the chain. buckets[index].append((key: key, value: value)) count += 1 return nil } - + public mutating func removeValueForKey(key: Key) -> Value? { let index = indexForKey(key) - + // Find the element in the bucket's chain and remove it. for (i, element) in buckets[index].enumerate() { if element.key == key { @@ -109,7 +109,7 @@ extension HashTable { } return nil // key not in hash table } - + public mutating func removeAll() { buckets = .init(count: buckets.count, repeatedValue: []) count = 0 @@ -128,7 +128,7 @@ extension HashTable { } return a } - + public var values: [Value] { var a = [Value]() for bucket in buckets { diff --git a/Heap/Heap.swift b/Heap/Heap.swift index 3293f75bb..64bd90cd8 100644 --- a/Heap/Heap.swift +++ b/Heap/Heap.swift @@ -6,10 +6,10 @@ public struct Heap { /** The array that stores the heap's nodes. */ var elements = [T]() - + /** Determines whether this is a max-heap (>) or min-heap (<). */ private var isOrderedBefore: (T, T) -> Bool - + /** * Creates an empty heap. * The sort function determines whether this is a min-heap or max-heap. @@ -38,7 +38,7 @@ public struct Heap { } } */ - + /** * Converts an array to a max-heap or min-heap in a bottom-up manner. * Performance: This runs pretty much in O(n). @@ -53,11 +53,11 @@ public struct Heap { public var isEmpty: Bool { return elements.isEmpty } - + public var count: Int { return elements.count } - + /** * Returns the index of the parent of the element at index i. * The element at index 0 is the root of the tree and has no parent. @@ -83,7 +83,7 @@ public struct Heap { @inline(__always) func indexOfRightChild(i: Int) -> Int { return 2*i + 2 } - + /** * Returns the maximum value in the heap (for a max-heap) or the minimum * value (for a min-heap). @@ -100,13 +100,13 @@ public struct Heap { elements.append(value) shiftUp(index: elements.count - 1) } - - public mutating func insert(sequence: S) { + + public mutating func insert(sequence: S) { for value in sequence { insert(value) } } - + /** * Allows you to change an element. In a max-heap, the new element should be * larger than the old one; in a min-heap it should be smaller. @@ -135,7 +135,7 @@ public struct Heap { return value } } - + /** * Removes an arbitrary node from the heap. Performance: O(log n). You need * to know the node's index, which may actually take O(n) steps to find. @@ -149,9 +149,9 @@ public struct Heap { } return elements.removeLast() } - + /** - * Takes a child node and looks at its parents; if a parent is not larger + * Takes a child node and looks at its parents; if a parent is not larger * (max-heap) or not smaller (min-heap) than the child, we exchange them. */ mutating func shiftUp(index index: Int) { @@ -167,7 +167,7 @@ public struct Heap { elements[childIndex] = child } - + mutating func shiftDown() { shiftDown(index: 0, heapSize: elements.count) } diff --git a/Heap/Tests/HeapTests.swift b/Heap/Tests/HeapTests.swift index b038687ad..ec17560a5 100644 --- a/Heap/Tests/HeapTests.swift +++ b/Heap/Tests/HeapTests.swift @@ -6,7 +6,7 @@ import XCTest class HeapTests: XCTestCase { - + private func verifyMaxHeap(h: Heap) -> Bool { for i in 0..(sort: >) XCTAssertEqual(0, heap.count) diff --git a/Huffman Coding/Huffman.playground/Contents.swift b/Huffman Coding/Huffman.playground/Contents.swift index 99170fa91..b67f93a6a 100644 --- a/Huffman Coding/Huffman.playground/Contents.swift +++ b/Huffman Coding/Huffman.playground/Contents.swift @@ -5,18 +5,18 @@ import Foundation let s1 = "so much words wow many compression" if let originalData = s1.dataUsingEncoding(NSUTF8StringEncoding) { print(originalData.length) - + let huffman1 = Huffman() let compressedData = huffman1.compressData(originalData) print(compressedData.length) - + let frequencyTable = huffman1.frequencyTable() //print(frequencyTable) - + let huffman2 = Huffman() let decompressedData = huffman2.decompressData(compressedData, frequencyTable: frequencyTable) print(decompressedData.length) - + let s2 = String(data: decompressedData, encoding: NSUTF8StringEncoding)! print(s2) assert(s1 == s2) diff --git a/Huffman Coding/Huffman.playground/Sources/Heap.swift b/Huffman Coding/Huffman.playground/Sources/Heap.swift index 3293f75bb..64bd90cd8 100644 --- a/Huffman Coding/Huffman.playground/Sources/Heap.swift +++ b/Huffman Coding/Huffman.playground/Sources/Heap.swift @@ -6,10 +6,10 @@ public struct Heap { /** The array that stores the heap's nodes. */ var elements = [T]() - + /** Determines whether this is a max-heap (>) or min-heap (<). */ private var isOrderedBefore: (T, T) -> Bool - + /** * Creates an empty heap. * The sort function determines whether this is a min-heap or max-heap. @@ -38,7 +38,7 @@ public struct Heap { } } */ - + /** * Converts an array to a max-heap or min-heap in a bottom-up manner. * Performance: This runs pretty much in O(n). @@ -53,11 +53,11 @@ public struct Heap { public var isEmpty: Bool { return elements.isEmpty } - + public var count: Int { return elements.count } - + /** * Returns the index of the parent of the element at index i. * The element at index 0 is the root of the tree and has no parent. @@ -83,7 +83,7 @@ public struct Heap { @inline(__always) func indexOfRightChild(i: Int) -> Int { return 2*i + 2 } - + /** * Returns the maximum value in the heap (for a max-heap) or the minimum * value (for a min-heap). @@ -100,13 +100,13 @@ public struct Heap { elements.append(value) shiftUp(index: elements.count - 1) } - - public mutating func insert(sequence: S) { + + public mutating func insert(sequence: S) { for value in sequence { insert(value) } } - + /** * Allows you to change an element. In a max-heap, the new element should be * larger than the old one; in a min-heap it should be smaller. @@ -135,7 +135,7 @@ public struct Heap { return value } } - + /** * Removes an arbitrary node from the heap. Performance: O(log n). You need * to know the node's index, which may actually take O(n) steps to find. @@ -149,9 +149,9 @@ public struct Heap { } return elements.removeLast() } - + /** - * Takes a child node and looks at its parents; if a parent is not larger + * Takes a child node and looks at its parents; if a parent is not larger * (max-heap) or not smaller (min-heap) than the child, we exchange them. */ mutating func shiftUp(index index: Int) { @@ -167,7 +167,7 @@ public struct Heap { elements[childIndex] = child } - + mutating func shiftDown() { shiftDown(index: 0, heapSize: elements.count) } diff --git a/Huffman Coding/Huffman.playground/Sources/Huffman.swift b/Huffman Coding/Huffman.playground/Sources/Huffman.swift index 0b6da03af..d50b90d82 100644 --- a/Huffman Coding/Huffman.playground/Sources/Huffman.swift +++ b/Huffman Coding/Huffman.playground/Sources/Huffman.swift @@ -1,19 +1,19 @@ import Foundation /* - Basic implementation of Huffman encoding. It encodes bytes that occur often + Basic implementation of Huffman encoding. It encodes bytes that occur often with a smaller number of bits than bytes that occur less frequently. - Based on Al Stevens' C Programming column from Dr.Dobb's Magazine, February - 1991 and October 1992. + Based on Al Stevens' C Programming column from Dr.Dobb's Magazine, February + 1991 and October 1992. Note: This code is not optimized for speed but explanation. */ public class Huffman { - /* Tree nodes don't use pointers to refer to each other, but simple integer + /* Tree nodes don't use pointers to refer to each other, but simple integer indices. That allows us to use structs for the nodes. */ typealias NodeIndex = Int - + /* A node in the compression tree. Leaf nodes represent the actual bytes that are present in the input data. The count of an intermediary node is the sum of the counts of all nodes below it. The root node's count is the number of @@ -25,29 +25,29 @@ public class Huffman { var left: NodeIndex = -1 var right: NodeIndex = -1 } - - /* The tree structure. The first 256 entries are for the leaf nodes (not all - of those may be used, depending on the input). We add additional nodes as + + /* The tree structure. The first 256 entries are for the leaf nodes (not all + of those may be used, depending on the input). We add additional nodes as we build the tree. */ var tree = [Node](count: 256, repeatedValue: Node()) /* This is the last node we add to the tree. */ var root: NodeIndex = -1 - /* The frequency table describes how often a byte occurs in the input data. + /* The frequency table describes how often a byte occurs in the input data. You need it to decompress the Huffman-encoded data. The frequency table should be serialized along with the compressed data. */ public struct Freq { var byte: UInt8 = 0 var count = 0 } - + public init() { } } extension Huffman { - /* To compress a block of data, first we need to count how often each byte - occurs. These counts are stored in the first 256 nodes in the tree, i.e. + /* To compress a block of data, first we need to count how often each byte + occurs. These counts are stored in the first 256 nodes in the tree, i.e. the leaf nodes. The frequency table used by decompression is derived from this. */ private func countByteFrequency(data: NSData) { @@ -59,7 +59,7 @@ extension Huffman { ptr = ptr.successor() } } - + /* Takes a frequency table and rebuilds the tree. This is the first step of decompression. */ private func restoreTree(frequencyTable: [Freq]) { @@ -70,9 +70,9 @@ extension Huffman { } buildTree() } - - /* Returns the frequency table. This is the first 256 nodes from the tree but - only those that are actually used, without the parent/left/right pointers. + + /* Returns the frequency table. This is the first 256 nodes from the tree but + only those that are actually used, without the parent/left/right pointers. You would serialize this along with the compressed file. */ public func frequencyTable() -> [Freq] { var a = [Freq]() @@ -109,7 +109,7 @@ extension Huffman { // Link the two nodes into their new parent node. tree[node1.index].parent = parentNode.index tree[node2.index].parent = parentNode.index - + // Put the intermediate node back into the queue. queue.enqueue(parentNode) } @@ -125,7 +125,7 @@ extension Huffman { public func compressData(data: NSData) -> NSData { countByteFrequency(data) buildTree() - + let writer = BitWriter() var ptr = UnsafePointer(data.bytes) for _ in 0.. var inByte: UInt8 = 0 var inCount = 8 - + public init(data: NSData) { ptr = UnsafePointer(data.bytes) } - + public func readBit() -> Bool { if inCount == 8 { inByte = ptr.memory // load the next byte diff --git a/Huffman Coding/Huffman.playground/Sources/PriorityQueue.swift b/Huffman Coding/Huffman.playground/Sources/PriorityQueue.swift index 7a7cee34b..757a6c539 100644 --- a/Huffman Coding/Huffman.playground/Sources/PriorityQueue.swift +++ b/Huffman Coding/Huffman.playground/Sources/PriorityQueue.swift @@ -3,7 +3,7 @@ the queue. The heap is a natural data structure for a priority queue, so this object - simply wraps the Heap struct. + simply wraps the Heap struct. All operations are O(lg n). diff --git a/Huffman Coding/Huffman.swift b/Huffman Coding/Huffman.swift index 0b6da03af..d50b90d82 100644 --- a/Huffman Coding/Huffman.swift +++ b/Huffman Coding/Huffman.swift @@ -1,19 +1,19 @@ import Foundation /* - Basic implementation of Huffman encoding. It encodes bytes that occur often + Basic implementation of Huffman encoding. It encodes bytes that occur often with a smaller number of bits than bytes that occur less frequently. - Based on Al Stevens' C Programming column from Dr.Dobb's Magazine, February - 1991 and October 1992. + Based on Al Stevens' C Programming column from Dr.Dobb's Magazine, February + 1991 and October 1992. Note: This code is not optimized for speed but explanation. */ public class Huffman { - /* Tree nodes don't use pointers to refer to each other, but simple integer + /* Tree nodes don't use pointers to refer to each other, but simple integer indices. That allows us to use structs for the nodes. */ typealias NodeIndex = Int - + /* A node in the compression tree. Leaf nodes represent the actual bytes that are present in the input data. The count of an intermediary node is the sum of the counts of all nodes below it. The root node's count is the number of @@ -25,29 +25,29 @@ public class Huffman { var left: NodeIndex = -1 var right: NodeIndex = -1 } - - /* The tree structure. The first 256 entries are for the leaf nodes (not all - of those may be used, depending on the input). We add additional nodes as + + /* The tree structure. The first 256 entries are for the leaf nodes (not all + of those may be used, depending on the input). We add additional nodes as we build the tree. */ var tree = [Node](count: 256, repeatedValue: Node()) /* This is the last node we add to the tree. */ var root: NodeIndex = -1 - /* The frequency table describes how often a byte occurs in the input data. + /* The frequency table describes how often a byte occurs in the input data. You need it to decompress the Huffman-encoded data. The frequency table should be serialized along with the compressed data. */ public struct Freq { var byte: UInt8 = 0 var count = 0 } - + public init() { } } extension Huffman { - /* To compress a block of data, first we need to count how often each byte - occurs. These counts are stored in the first 256 nodes in the tree, i.e. + /* To compress a block of data, first we need to count how often each byte + occurs. These counts are stored in the first 256 nodes in the tree, i.e. the leaf nodes. The frequency table used by decompression is derived from this. */ private func countByteFrequency(data: NSData) { @@ -59,7 +59,7 @@ extension Huffman { ptr = ptr.successor() } } - + /* Takes a frequency table and rebuilds the tree. This is the first step of decompression. */ private func restoreTree(frequencyTable: [Freq]) { @@ -70,9 +70,9 @@ extension Huffman { } buildTree() } - - /* Returns the frequency table. This is the first 256 nodes from the tree but - only those that are actually used, without the parent/left/right pointers. + + /* Returns the frequency table. This is the first 256 nodes from the tree but + only those that are actually used, without the parent/left/right pointers. You would serialize this along with the compressed file. */ public func frequencyTable() -> [Freq] { var a = [Freq]() @@ -109,7 +109,7 @@ extension Huffman { // Link the two nodes into their new parent node. tree[node1.index].parent = parentNode.index tree[node2.index].parent = parentNode.index - + // Put the intermediate node back into the queue. queue.enqueue(parentNode) } @@ -125,7 +125,7 @@ extension Huffman { public func compressData(data: NSData) -> NSData { countByteFrequency(data) buildTree() - + let writer = BitWriter() var ptr = UnsafePointer(data.bytes) for _ in 0.. var inByte: UInt8 = 0 var inCount = 8 - + public init(data: NSData) { ptr = UnsafePointer(data.bytes) } - + public func readBit() -> Bool { if inCount == 8 { inByte = ptr.memory // load the next byte diff --git a/K-Means/KMeans.swift b/K-Means/KMeans.swift index 743cdc824..972fd7230 100644 --- a/K-Means/KMeans.swift +++ b/K-Means/KMeans.swift @@ -4,17 +4,17 @@ class KMeans { let numCenters: Int let labels: [Label] private(set) var centroids = [Vector]() - + init(labels: [Label]) { assert(labels.count > 1, "Exception: KMeans with less than 2 centers.") self.labels = labels self.numCenters = labels.count } - + private func indexOfNearestCenter(x: Vector, centers: [Vector]) -> Int { var nearestDist = DBL_MAX var minIndex = 0 - + for (idx, center) in centers.enumerate() { let dist = x.distanceTo(center) if dist < nearestDist { @@ -24,18 +24,18 @@ class KMeans { } return minIndex } - + func trainCenters(points: [Vector], convergeDistance: Double) { let zeroVector = Vector([Double](count: points[0].length, repeatedValue: 0)) - + // Randomly take k objects from the input data to make the initial centroids. var centers = reservoirSample(points, k: numCenters) - + var centerMoveDist = 0.0 repeat { // This array keeps track of which data points belong to which centroids. var classification: [[Vector]] = .init(count: numCenters, repeatedValue: []) - + // For each data point, find the centroid that it is closest to. for p in points { let classIndex = indexOfNearestCenter(p, centers: centers) @@ -47,30 +47,30 @@ class KMeans { let newCenters = classification.map { assignedPoints in assignedPoints.reduce(zeroVector, combine: +) / Double(assignedPoints.count) } - + // Find out how far each centroid moved since the last iteration. If it's // only a small distance, then we're done. centerMoveDist = 0.0 for idx in 0.. convergeDistance - + centroids = centers } - + func fit(point: Vector) -> Label { assert(!centroids.isEmpty, "Exception: KMeans tried to fit on a non trained model.") - + let centroidIndex = indexOfNearestCenter(point, centers: centroids) return labels[centroidIndex] } - + func fit(points: [Vector]) -> [Label] { assert(!centroids.isEmpty, "Exception: KMeans tried to fit on a non trained model.") - + return points.map(fit) } } @@ -78,7 +78,7 @@ class KMeans { // Pick k random elements from samples func reservoirSample(samples: [T], k: Int) -> [T] { var result = [T]() - + // Fill the result array with first k elements for i in 0..(labels: ["A", "B", "C"]) kmm.trainCenters(points, convergeDistance: 0.01) - + for (label, centroid) in zip(kmm.labels, kmm.centroids) { print("\(label): \(centroid)") } - + print("\nClassifications") for (label, point) in zip(kmm.fit(points), points) { print("\(label): \(point)") } } - + func testSmall_10D() { let points = genPoints(10, numDimensions: 10) - + print("\nCenters") let kmm = KMeans(labels: [1, 2, 3]) kmm.trainCenters(points, convergeDistance: 0.01) @@ -49,23 +49,23 @@ class KMeansTests: XCTestCase { print(c) } } - + func testLarge_2D() { let points = genPoints(10000, numDimensions: 2) - + print("\nCenters") - let kmm = KMeans(labels: ["A","B","C","D","E"]) + let kmm = KMeans(labels: ["A", "B", "C", "D", "E"]) kmm.trainCenters(points, convergeDistance: 0.01) for c in kmm.centroids { print(c) } } - + func testLarge_10D() { let points = genPoints(10000, numDimensions: 10) - + print("\nCenters") - let kmm = KMeans(labels: [1,2,3,4,5]) + let kmm = KMeans(labels: [1, 2, 3, 4, 5]) kmm.trainCenters(points, convergeDistance: 0.01) for c in kmm.centroids { print(c) diff --git a/K-Means/Tests/Vector.swift b/K-Means/Tests/Vector.swift index 659bd914f..10baf9338 100644 --- a/K-Means/Tests/Vector.swift +++ b/K-Means/Tests/Vector.swift @@ -8,11 +8,11 @@ struct Vector: CustomStringConvertible, Equatable { self.data = data self.length = data.count } - + var description: String { return "Vector (\(data)" } - + func distanceTo(other: Vector) -> Double { var result = 0.0 for idx in 0.. Bool { +func == (left: Vector, right: Vector) -> Bool { for idx in 0.. Bool { return true } -func +(left: Vector, right: Vector) -> Vector { +func + (left: Vector, right: Vector) -> Vector { var results = [Double]() for idx in 0.. Vector { return Vector(results) } -func +=(inout left: Vector, right: Vector) { +func += (inout left: Vector, right: Vector) { left = left + right } -func -(left: Vector, right: Vector) -> Vector { +func - (left: Vector, right: Vector) -> Vector { var results = [Double]() for idx in 0.. Vector { return Vector(results) } -func -=(inout left: Vector, right: Vector) { +func -= (inout left: Vector, right: Vector) { left = left - right } -func /(left:Vector, right: Double) -> Vector { +func / (left: Vector, right: Double) -> Vector { var results = [Double](count: left.length, repeatedValue: 0) for (idx, value) in left.data.enumerate() { results[idx] = value / right @@ -63,6 +63,6 @@ func /(left:Vector, right: Double) -> Vector { return Vector(results) } -func /=(inout left: Vector, right: Double) { +func /= (inout left: Vector, right: Double) { left = left / right } diff --git a/Kth Largest Element/kthLargest.playground/Contents.swift b/Kth Largest Element/kthLargest.playground/Contents.swift index 7f97bb271..628892d9c 100644 --- a/Kth Largest Element/kthLargest.playground/Contents.swift +++ b/Kth Largest Element/kthLargest.playground/Contents.swift @@ -45,7 +45,7 @@ public func swap(inout a: [T], _ i: Int, _ j: Int) { public func randomizedSelect(array: [T], order k: Int) -> T { var a = array - + func randomPivot(inout a: [T], _ low: Int, _ high: Int) -> T { let pivotIndex = random(min: low, max: high) swap(&a, pivotIndex, high) @@ -79,7 +79,7 @@ public func randomizedSelect(array: [T], order k: Int) -> T { return a[low] } } - + precondition(a.count > 0) return randomizedSelect(&a, 0, a.count - 1, k) } diff --git a/Kth Largest Element/kthLargest.swift b/Kth Largest Element/kthLargest.swift index 5bf781932..1f90b096f 100644 --- a/Kth Largest Element/kthLargest.swift +++ b/Kth Largest Element/kthLargest.swift @@ -48,13 +48,13 @@ public func swap(inout a: [T], _ i: Int, _ j: Int) { */ public func randomizedSelect(array: [T], order k: Int) -> T { var a = array - + func randomPivot(inout a: [T], _ low: Int, _ high: Int) -> T { let pivotIndex = random(min: low, max: high) swap(&a, pivotIndex, high) return a[high] } - + func randomizedPartition(inout a: [T], _ low: Int, _ high: Int) -> Int { let pivot = randomPivot(&a, low, high) var i = low @@ -67,7 +67,7 @@ public func randomizedSelect(array: [T], order k: Int) -> T { swap(&a, i, high) return i } - + func randomizedSelect(inout a: [T], _ low: Int, _ high: Int, _ k: Int) -> T { if low < high { let p = randomizedPartition(&a, low, high) @@ -82,7 +82,7 @@ public func randomizedSelect(array: [T], order k: Int) -> T { return a[low] } } - + precondition(a.count > 0) return randomizedSelect(&a, 0, a.count - 1, k) } diff --git a/Linked List/LinkedList.playground/Contents.swift b/Linked List/LinkedList.playground/Contents.swift index c09bed736..cc7ed3d59 100644 --- a/Linked List/LinkedList.playground/Contents.swift +++ b/Linked List/LinkedList.playground/Contents.swift @@ -14,15 +14,15 @@ public class LinkedList { public typealias Node = LinkedListNode private var head: Node? - + public var isEmpty: Bool { return head == nil } - + public var first: Node? { return head } - + public var last: Node? { if var node = head { while case let next? = node.next { @@ -33,7 +33,7 @@ public class LinkedList { return nil } } - + public var count: Int { if var node = head { var c = 1 @@ -46,7 +46,7 @@ public class LinkedList { return 0 } } - + public func nodeAtIndex(index: Int) -> Node? { if index >= 0 { var node = head @@ -59,7 +59,7 @@ public class LinkedList { } return nil } - + public subscript(index: Int) -> T { let node = nodeAtIndex(index) assert(node != nil) @@ -75,10 +75,10 @@ public class LinkedList { head = newNode } } - + private func nodesBeforeAndAfter(index: Int) -> (Node?, Node?) { assert(index >= 0) - + var i = index var next = head var prev: Node? @@ -92,10 +92,10 @@ public class LinkedList { return (prev, next) } - + public func insert(value: T, atIndex index: Int) { let (prev, next) = nodesBeforeAndAfter(index) - + let newNode = Node(value: value) newNode.previous = prev newNode.next = next @@ -106,7 +106,7 @@ public class LinkedList { head = newNode } } - + public func removeAll() { head = nil } @@ -114,24 +114,24 @@ public class LinkedList { public func removeNode(node: Node) -> T { let prev = node.previous let next = node.next - + if let prev = prev { prev.next = next } else { head = next } next?.previous = prev - + node.previous = nil node.next = nil return node.value } - + public func removeLast() -> T { assert(!isEmpty) return removeNode(last!) } - + public func removeAtIndex(index: Int) -> T { let node = nodeAtIndex(index) assert(node != nil) diff --git a/Linked List/LinkedList.swift b/Linked List/LinkedList.swift index 8d2c27d7e..ef95a0b58 100755 --- a/Linked List/LinkedList.swift +++ b/Linked List/LinkedList.swift @@ -7,7 +7,7 @@ public class LinkedListNode { var value: T var next: LinkedListNode? weak var previous: LinkedListNode? - + public init(value: T) { self.value = value } @@ -15,17 +15,17 @@ public class LinkedListNode { public class LinkedList { public typealias Node = LinkedListNode - + private var head: Node? - + public var isEmpty: Bool { return head == nil } - + public var first: Node? { return head } - + public var last: Node? { if var node = head { while case let next? = node.next { @@ -36,7 +36,7 @@ public class LinkedList { return nil } } - + public var count: Int { if var node = head { var c = 1 @@ -49,7 +49,7 @@ public class LinkedList { return 0 } } - + public func nodeAtIndex(index: Int) -> Node? { if index >= 0 { var node = head @@ -62,13 +62,13 @@ public class LinkedList { } return nil } - + public subscript(index: Int) -> T { let node = nodeAtIndex(index) assert(node != nil) return node!.value } - + public func append(value: T) { let newNode = Node(value: value) if let lastNode = last { @@ -78,63 +78,63 @@ public class LinkedList { head = newNode } } - + private func nodesBeforeAndAfter(index: Int) -> (Node?, Node?) { assert(index >= 0) - + var i = index var next = head var prev: Node? - + while next != nil && i > 0 { i -= 1 prev = next next = next!.next } assert(i == 0) // if > 0, then specified index was too large - + return (prev, next) } - + public func insert(value: T, atIndex index: Int) { let (prev, next) = nodesBeforeAndAfter(index) - + let newNode = Node(value: value) newNode.previous = prev newNode.next = next prev?.next = newNode next?.previous = newNode - + if prev == nil { head = newNode } } - + public func removeAll() { head = nil } - + public func removeNode(node: Node) -> T { let prev = node.previous let next = node.next - + if let prev = prev { prev.next = next } else { head = next } next?.previous = prev - + node.previous = nil node.next = nil return node.value } - + public func removeLast() -> T { assert(!isEmpty) return removeNode(last!) } - + public func removeAtIndex(index: Int) -> T { let node = nodeAtIndex(index) assert(node != nil) @@ -176,7 +176,7 @@ extension LinkedList { } return result } - + public func filter(predicate: T -> Bool) -> LinkedList { let result = LinkedList() var node = head diff --git a/Longest Common Subsequence/LongestCommonSubsequence.playground/Contents.swift b/Longest Common Subsequence/LongestCommonSubsequence.playground/Contents.swift index 0fa00d48b..bb6fa7c2a 100644 --- a/Longest Common Subsequence/LongestCommonSubsequence.playground/Contents.swift +++ b/Longest Common Subsequence/LongestCommonSubsequence.playground/Contents.swift @@ -1,9 +1,9 @@ extension String { public func longestCommonSubsequence(other: String) -> String { - + func lcsLength(other: String) -> [[Int]] { var matrix = [[Int]](count: self.characters.count+1, repeatedValue: [Int](count: other.characters.count+1, repeatedValue: 0)) - + for (i, selfChar) in self.characters.enumerate() { for (j, otherChar) in other.characters.enumerate() { if otherChar == selfChar { @@ -15,14 +15,14 @@ extension String { } return matrix } - + func backtrack(matrix: [[Int]]) -> String { var i = self.characters.count var j = other.characters.count var charInSequence = self.endIndex - + var lcs = String() - + while i >= 1 && j >= 1 { if matrix[i][j] == matrix[i][j - 1] { j -= 1 @@ -38,7 +38,7 @@ extension String { } return String(lcs.characters.reverse()) } - + return backtrack(lcsLength(other)) } } diff --git a/Longest Common Subsequence/LongestCommonSubsequence.swift b/Longest Common Subsequence/LongestCommonSubsequence.swift index d9dda1364..23d191102 100644 --- a/Longest Common Subsequence/LongestCommonSubsequence.swift +++ b/Longest Common Subsequence/LongestCommonSubsequence.swift @@ -1,6 +1,6 @@ extension String { public func longestCommonSubsequence(other: String) -> String { - + // Computes the length of the lcs using dynamic programming. // Output is a matrix of size (n+1)x(m+1), where matrix[x][y] is the length // of lcs between substring (0, x-1) of self and substring (0, y-1) of other. @@ -31,12 +31,12 @@ extension String { func backtrack(matrix: [[Int]]) -> String { var i = self.characters.count var j = other.characters.count - + // charInSequence is in sync with i so we can get self[i] var charInSequence = self.endIndex - + var lcs = String() - + while i >= 1 && j >= 1 { // Indicates propagation without change: no new char was added to lcs. if matrix[i][j] == matrix[i][j - 1] { @@ -57,12 +57,12 @@ extension String { lcs.append(self[charInSequence]) } } - + // Due to backtrack, chars were added in reverse order: reverse it back. // Append and reverse is faster than inserting at index 0. return String(lcs.characters.reverse()) } - + // Combine dynamic programming approach with backtrack to find the lcs. return backtrack(lcsLength(other)) } diff --git a/Longest Common Subsequence/Tests/LongestCommonSubsequenceTests.swift b/Longest Common Subsequence/Tests/LongestCommonSubsequenceTests.swift index db388a65f..2498b6dd7 100644 --- a/Longest Common Subsequence/Tests/LongestCommonSubsequenceTests.swift +++ b/Longest Common Subsequence/Tests/LongestCommonSubsequenceTests.swift @@ -2,26 +2,26 @@ import Foundation import XCTest class LongestCommonSubsequenceTests: XCTestCase { - + func testLCSwithSelfIsSelf() { let a = "ABCDE" XCTAssertEqual(a, a.longestCommonSubsequence(a)) } - + func testLCSWithEmptyStringIsEmptyString() { let a = "ABCDE" XCTAssertEqual("", a.longestCommonSubsequence("")) } - + func testLCSIsEmptyWhenNoCharMatches() { let a = "ABCDE" let b = "WXYZ" XCTAssertEqual("", a.longestCommonSubsequence(b)) } - + func testLCSIsNotCommutative() { let a = "ABCDEF" let b = "XAWDMVBEKD" diff --git a/Merge Sort/MergeSort.playground/Contents.swift b/Merge Sort/MergeSort.playground/Contents.swift index 27e52ab09..a71a90136 100644 --- a/Merge Sort/MergeSort.playground/Contents.swift +++ b/Merge Sort/MergeSort.playground/Contents.swift @@ -52,20 +52,20 @@ func mergeSortBottomUp(a: [T], _ isOrderedBefore: (T, T) -> Bool) -> [T] { let n = a.count var z = [a, a] // the two working arrays var d = 0 // z[d] is used for reading, z[1 - d] for writing - + var width = 1 while width < n { - + var i = 0 while i < n { var j = i var l = i var r = i + width - + let lmax = min(l + width, n) let rmax = min(r + width, n) - + while l < lmax && r < rmax { if isOrderedBefore(z[d][l], z[d][r]) { z[1 - d][j] = z[d][l] @@ -89,7 +89,7 @@ func mergeSortBottomUp(a: [T], _ isOrderedBefore: (T, T) -> Bool) -> [T] { i += width*2 } - + width *= 2 // in each step, the subarray to merge becomes larger d = 1 - d // swap active array } diff --git a/Merge Sort/MergeSort.swift b/Merge Sort/MergeSort.swift index 35bf7b5f8..968484dd1 100644 --- a/Merge Sort/MergeSort.swift +++ b/Merge Sort/MergeSort.swift @@ -1,6 +1,6 @@ // // Mergesort.swift -// +// // // Created by Kelvin Lau on 2016-02-03. // @@ -63,20 +63,20 @@ func mergeSortBottomUp(a: [T], _ isOrderedBefore: (T, T) -> Bool) -> [T] { let n = a.count var z = [a, a] // the two working arrays var d = 0 // z[d] is used for reading, z[1 - d] for writing - + var width = 1 while width < n { - + var i = 0 while i < n { - + var j = i var l = i var r = i + width - + let lmax = min(l + width, n) let rmax = min(r + width, n) - + while l < lmax && r < rmax { if isOrderedBefore(z[d][l], z[d][r]) { z[1 - d][j] = z[d][l] @@ -97,10 +97,10 @@ func mergeSortBottomUp(a: [T], _ isOrderedBefore: (T, T) -> Bool) -> [T] { j += 1 r += 1 } - + i += width*2 } - + width *= 2 // in each step, the subarray to merge becomes larger d = 1 - d // swap active array } diff --git a/Minimum Edit Distance/MinimumEditDistance.swift b/Minimum Edit Distance/MinimumEditDistance.swift index 8008e03ba..a128b2dab 100644 --- a/Minimum Edit Distance/MinimumEditDistance.swift +++ b/Minimum Edit Distance/MinimumEditDistance.swift @@ -1,11 +1,11 @@ extension String { - + public func minimumEditDistance(other: String) -> Int { let m = self.characters.count let n = other.characters.count var matrix = [[Int]](count: m+1, repeatedValue: [Int](count: n+1, repeatedValue: 0)) - - + + // initialize matrix for index in 1...m { // the distance of any first string to an empty second string @@ -15,7 +15,7 @@ extension String { // the distance of any second string to an empty first string matrix[0][index]=index } - + // compute Levenshtein distance for (i, selfChar) in self.characters.enumerate() { for (j, otherChar) in other.characters.enumerate() { @@ -26,7 +26,7 @@ extension String { // minimum of the cost of insertion, deletion, or substitution added to the already computed costs in the corresponding cells matrix[i+1][j+1] = min(matrix[i][j]+1, matrix[i+1][j]+1, matrix[i][j+1]+1) } - + } } return matrix[m][n] diff --git a/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Sources/Edge.swift b/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Sources/Edge.swift index 3937a2cc7..9a58a1f96 100644 --- a/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Sources/Edge.swift +++ b/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Sources/Edge.swift @@ -1,4 +1,4 @@ -public class Edge : Equatable { +public class Edge: Equatable { public var neighbor: Node public init(neighbor: Node) { @@ -6,6 +6,6 @@ public class Edge : Equatable { } } -public func ==(lhs: Edge, rhs: Edge) -> Bool { +public func == (lhs: Edge, rhs: Edge) -> Bool { return lhs.neighbor == rhs.neighbor } diff --git a/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Sources/Graph.swift b/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Sources/Graph.swift index e89d4ac97..8cfb2a09c 100644 --- a/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Sources/Graph.swift +++ b/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Sources/Graph.swift @@ -1,4 +1,4 @@ -public class Graph : CustomStringConvertible, Equatable { +public class Graph: CustomStringConvertible, Equatable { public private(set) var nodes: [Node] public init() { @@ -21,14 +21,14 @@ public class Graph : CustomStringConvertible, Equatable { for node in nodes { if !node.neighbors.isEmpty { - description += "[node: \(node.label) edges: \(node.neighbors.map{ $0.neighbor.label})]" + description += "[node: \(node.label) edges: \(node.neighbors.map { $0.neighbor.label})]" } } return description } public func findNodeWithLabel(label: String) -> Node { - return nodes.filter{ $0.label == label }.first! + return nodes.filter { $0.label == label }.first! } public func duplicate() -> Graph { @@ -50,6 +50,6 @@ public class Graph : CustomStringConvertible, Equatable { } } -public func ==(lhs: Graph, rhs: Graph) -> Bool { +public func == (lhs: Graph, rhs: Graph) -> Bool { return lhs.nodes == rhs.nodes } diff --git a/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Sources/Node.swift b/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Sources/Node.swift index 9d8435ffa..37a3b3fdf 100644 --- a/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Sources/Node.swift +++ b/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Sources/Node.swift @@ -1,4 +1,4 @@ -public class Node : CustomStringConvertible, Equatable { +public class Node: CustomStringConvertible, Equatable { public var neighbors: [Edge] public private(set) var label: String @@ -23,10 +23,10 @@ public class Node : CustomStringConvertible, Equatable { } public func remove(edge: Edge) { - neighbors.removeAtIndex(neighbors.indexOf{ $0 === edge }!) + neighbors.removeAtIndex(neighbors.indexOf { $0 === edge }!) } } -public func ==(lhs: Node, rhs: Node) -> Bool { +public func == (lhs: Node, rhs: Node) -> Bool { return lhs.label == rhs.label && lhs.neighbors == rhs.neighbors } diff --git a/Minimum Spanning Tree (Unweighted)/Tests/Graph.swift b/Minimum Spanning Tree (Unweighted)/Tests/Graph.swift index 6f69ee800..ed71cab7c 100644 --- a/Minimum Spanning Tree (Unweighted)/Tests/Graph.swift +++ b/Minimum Spanning Tree (Unweighted)/Tests/Graph.swift @@ -1,6 +1,6 @@ // MARK: - Edge -public class Edge : Equatable { +public class Edge: Equatable { public var neighbor: Node public init(neighbor: Node) { @@ -8,15 +8,15 @@ public class Edge : Equatable { } } -public func ==(lhs: Edge, rhs: Edge) -> Bool { +public func == (lhs: Edge, rhs: Edge) -> Bool { return lhs.neighbor == rhs.neighbor } // MARK: - Node -public class Node : CustomStringConvertible, Equatable { +public class Node: CustomStringConvertible, Equatable { public var neighbors: [Edge] - + public private(set) var label: String public var distance: Int? public var visited: Bool @@ -39,17 +39,17 @@ public class Node : CustomStringConvertible, Equatable { } public func remove(edge: Edge) { - neighbors.removeAtIndex(neighbors.indexOf{ $0 === edge }!) + neighbors.removeAtIndex(neighbors.indexOf { $0 === edge }!) } } -public func ==(lhs: Node, rhs: Node) -> Bool { +public func == (lhs: Node, rhs: Node) -> Bool { return lhs.label == rhs.label && lhs.neighbors == rhs.neighbors } // MARK: - Graph -public class Graph : CustomStringConvertible, Equatable { +public class Graph: CustomStringConvertible, Equatable { public private(set) var nodes: [Node] public init() { @@ -72,14 +72,14 @@ public class Graph : CustomStringConvertible, Equatable { for node in nodes { if !node.neighbors.isEmpty { - description += "[node: \(node.label) edges: \(node.neighbors.map{ $0.neighbor.label})]" + description += "[node: \(node.label) edges: \(node.neighbors.map { $0.neighbor.label})]" } } return description } public func findNodeWithLabel(label: String) -> Node { - return nodes.filter{ $0.label == label }.first! + return nodes.filter { $0.label == label }.first! } public func duplicate() -> Graph { @@ -101,6 +101,6 @@ public class Graph : CustomStringConvertible, Equatable { } } -public func ==(lhs: Graph, rhs: Graph) -> Bool { +public func == (lhs: Graph, rhs: Graph) -> Bool { return lhs.nodes == rhs.nodes } diff --git a/Ordered Array/OrderedArray.playground/Contents.swift b/Ordered Array/OrderedArray.playground/Contents.swift index b83e9c62a..aae146ca2 100644 --- a/Ordered Array/OrderedArray.playground/Contents.swift +++ b/Ordered Array/OrderedArray.playground/Contents.swift @@ -2,7 +2,7 @@ public struct OrderedArray { private var array = [T]() - + public init(array: [T]) { self.array = array.sort() } @@ -10,23 +10,23 @@ public struct OrderedArray { public var isEmpty: Bool { return array.isEmpty } - + public var count: Int { return array.count } - + public subscript(index: Int) -> T { return array[index] } - + public mutating func removeAtIndex(index: Int) -> T { return array.removeAtIndex(index) } - + public mutating func removeAll() { array.removeAll() } - + public mutating func insert(newElement: T) -> Int { let i = findInsertionPoint(newElement) array.insert(newElement, atIndex: i) @@ -79,4 +79,3 @@ a // [-1, 1, 3, 4, 5, 7, 9] a.insert(-2) // inserted at index 0 a.insert(10) // inserted at index 8 a // [-2, -1, 1, 3, 4, 5, 7, 9, 10] - diff --git a/Ordered Array/OrderedArray.swift b/Ordered Array/OrderedArray.swift index e6e1ca79f..f92311445 100644 --- a/Ordered Array/OrderedArray.swift +++ b/Ordered Array/OrderedArray.swift @@ -4,37 +4,37 @@ */ public struct OrderedArray { private var array = [T]() - + public init(array: [T]) { self.array = array.sort() } - + public var isEmpty: Bool { return array.isEmpty } - + public var count: Int { return array.count } - + public subscript(index: Int) -> T { return array[index] } - + public mutating func removeAtIndex(index: Int) -> T { return array.removeAtIndex(index) } - + public mutating func removeAll() { array.removeAll() } - + public mutating func insert(newElement: T) -> Int { let i = findInsertionPoint(newElement) array.insert(newElement, atIndex: i) return i } - + private func findInsertionPoint(newElement: T) -> Int { var range = 0.. { } // Inserts an item. Performance: O(n) - public mutating func insert(item: T){ + public mutating func insert(item: T) { if exists(item) { return // don't add an item if it already exists } @@ -60,7 +60,7 @@ public struct OrderedSet { } else { // When we get here, we've landed on an item whose value is equal to the // value of the item we're looking for, but the items themselves are not - // equal. We need to check the items with the same value to the right + // equal. We need to check the items with the same value to the right // and to the left in order to find an exact match. // Check to the right. @@ -86,7 +86,7 @@ public struct OrderedSet { return nil } - // Returns the item at the given index. + // Returns the item at the given index. // Assertion fails if the index is out of the range of [0, count). public subscript(index: Int) -> T { assert(index >= 0 && index < count) @@ -103,7 +103,7 @@ public struct OrderedSet { return count == 0 ? nil : internalSet[0] } - // Returns the k-th largest element in the set, if k is in the range + // Returns the k-th largest element in the set, if k is in the range // [1, count]. Returns nil otherwise. public func kLargest(k: Int) -> T? { return k > count || k <= 0 ? nil : internalSet[count - k] diff --git a/Ordered Set/OrderedSet.playground/Sources/Player.swift b/Ordered Set/OrderedSet.playground/Sources/Player.swift index 7b8175107..9357744db 100644 --- a/Ordered Set/OrderedSet.playground/Sources/Player.swift +++ b/Ordered Set/OrderedSet.playground/Sources/Player.swift @@ -15,14 +15,14 @@ public struct Player: Comparable { } } -// Player x is equal to Player y if and only if both players have the +// Player x is equal to Player y if and only if both players have the // same name and number of points. -public func ==(x: Player, y: Player) -> Bool { +public func == (x: Player, y: Player) -> Bool { return x.name == y.name && x.points == y.points } // Player x is less than Player y if x has less points than y. -public func <(x: Player, y: Player) -> Bool { +public func < (x: Player, y: Player) -> Bool { return x.points < y.points } diff --git a/Ordered Set/OrderedSet.swift b/Ordered Set/OrderedSet.swift index 5f5a73fa2..a8b3b0966 100644 --- a/Ordered Set/OrderedSet.swift +++ b/Ordered Set/OrderedSet.swift @@ -1,4 +1,4 @@ -/* +/* An Ordered Set is a collection where all items in the set follow an ordering, usually ordered from 'least' to 'most'. The way you value and compare items can be user-defined. @@ -14,7 +14,7 @@ public struct OrderedSet { } // Inserts an item. Performance: O(n) - public mutating func insert(item: T){ + public mutating func insert(item: T) { if exists(item) { return // don't add an item if it already exists } @@ -60,7 +60,7 @@ public struct OrderedSet { } else { // When we get here, we've landed on an item whose value is equal to the // value of the item we're looking for, but the items themselves are not - // equal. We need to check the items with the same value to the right + // equal. We need to check the items with the same value to the right // and to the left in order to find an exact match. // Check to the right. @@ -86,7 +86,7 @@ public struct OrderedSet { return nil } - // Returns the item at the given index. + // Returns the item at the given index. // Assertion fails if the index is out of the range of [0, count). public subscript(index: Int) -> T { assert(index >= 0 && index < count) @@ -103,7 +103,7 @@ public struct OrderedSet { return count == 0 ? nil : internalSet[0] } - // Returns the k-th largest element in the set, if k is in the range + // Returns the k-th largest element in the set, if k is in the range // [1, count]. Returns nil otherwise. public func kLargest(k: Int) -> T? { return k > count || k <= 0 ? nil : internalSet[count - k] diff --git a/Priority Queue/PriorityQueue.swift b/Priority Queue/PriorityQueue.swift index 7a7cee34b..757a6c539 100644 --- a/Priority Queue/PriorityQueue.swift +++ b/Priority Queue/PriorityQueue.swift @@ -3,7 +3,7 @@ the queue. The heap is a natural data structure for a priority queue, so this object - simply wraps the Heap struct. + simply wraps the Heap struct. All operations are O(lg n). diff --git a/Queue/Queue-Optimized.swift b/Queue/Queue-Optimized.swift index efc573442..5a9d04394 100644 --- a/Queue/Queue-Optimized.swift +++ b/Queue/Queue-Optimized.swift @@ -9,7 +9,7 @@ public struct Queue { private var array = [T?]() private var head = 0 - + public var isEmpty: Bool { return count == 0 } @@ -17,11 +17,11 @@ public struct Queue { public var count: Int { return array.count - head } - + public mutating func enqueue(element: T) { array.append(element) } - + public mutating func dequeue() -> T? { guard head < array.count, let element = array[head] else { return nil } @@ -33,10 +33,10 @@ public struct Queue { array.removeFirst(head) head = 0 } - + return element } - + public func peek() -> T? { if isEmpty { return nil diff --git a/Queue/Queue.playground/Contents.swift b/Queue/Queue.playground/Contents.swift index da556d156..0c48afd5b 100644 --- a/Queue/Queue.playground/Contents.swift +++ b/Queue/Queue.playground/Contents.swift @@ -1,7 +1,7 @@ /* Queue - A queue is a list where you can only insert new items at the back and + A queue is a list where you can only insert new items at the back and remove items from the front. This ensures that the first item you enqueue is also the first item you dequeue. First come, first serve! diff --git a/Quicksort/Quicksort.playground/Contents.swift b/Quicksort/Quicksort.playground/Contents.swift index b88bafc12..0894ae61b 100644 --- a/Quicksort/Quicksort.playground/Contents.swift +++ b/Quicksort/Quicksort.playground/Contents.swift @@ -7,16 +7,16 @@ import Foundation func quicksort(a: [T]) -> [T] { guard a.count > 1 else { return a } - + let pivot = a[a.count/2] let less = a.filter { $0 < pivot } let equal = a.filter { $0 == pivot } let greater = a.filter { $0 > pivot } - + // Uncomment this following line to see in detail what the // pivot is in each step and how the subarrays are partitioned. //print(pivot, less, equal, greater) return quicksort(less) + equal + quicksort(greater) - + return quicksort(less) + equal + quicksort(greater) } @@ -36,7 +36,7 @@ quicksort(list1) */ func partitionLomuto(inout a: [T], low: Int, high: Int) -> Int { let pivot = a[high] - + var i = low for j in low..(inout a: [T], low: Int, high: Int) -> Int { i += 1 } } - + (a[i], a[high]) = (a[high], a[i]) return i } @@ -79,11 +79,11 @@ func partitionHoare(inout a: [T], low: Int, high: Int) -> Int { let pivot = a[low] var i = low - 1 var j = high + 1 - + while true { repeat { j -= 1 } while a[j] > pivot repeat { i += 1 } while a[i] < pivot - + if i < j { swap(&a[i], &a[j]) } else { @@ -120,7 +120,7 @@ func quicksortRandom(inout a: [T], low: Int, high: Int) { if low < high { let pivotIndex = random(min: low, max: high) (a[pivotIndex], a[high]) = (a[high], a[pivotIndex]) - + let p = partitionLomuto(&a, low: low, high: high) quicksortRandom(&a, low: low, high: p - 1) quicksortRandom(&a, low: p + 1, high: high) @@ -151,11 +151,11 @@ public func swap(inout a: [T], _ i: Int, _ j: Int) { */ func partitionDutchFlag(inout a: [T], low: Int, high: Int, pivotIndex: Int) -> (Int, Int) { let pivot = a[pivotIndex] - + var smaller = low var equal = low var larger = high - + while equal <= larger { if a[equal] < pivot { swap(&a, smaller, equal) diff --git a/Quicksort/Quicksort.swift b/Quicksort/Quicksort.swift index 68c54ac5c..6448dd815 100644 --- a/Quicksort/Quicksort.swift +++ b/Quicksort/Quicksort.swift @@ -5,12 +5,12 @@ import Foundation */ func quicksort(a: [T]) -> [T] { guard a.count > 1 else { return a } - + let pivot = a[a.count/2] let less = a.filter { $0 < pivot } let equal = a.filter { $0 == pivot } let greater = a.filter { $0 > pivot } - + return quicksort(less) + equal + quicksort(greater) } @@ -45,7 +45,7 @@ func partitionLomuto(inout a: [T], low: Int, high: Int) -> Int { i += 1 } } - + // Swap the pivot element with the first element that is greater than // the pivot. Now the pivot sits between the <= and > regions and the // array is properly partitioned. @@ -88,7 +88,7 @@ func partitionHoare(inout a: [T], low: Int, high: Int) -> Int { while true { repeat { j -= 1 } while a[j] > pivot repeat { i += 1 } while a[i] < pivot - + if i < j { swap(&a[i], &a[j]) } else { diff --git a/Quicksort/Tests/QuicksortTests.swift b/Quicksort/Tests/QuicksortTests.swift index ef95f1095..00135b31f 100644 --- a/Quicksort/Tests/QuicksortTests.swift +++ b/Quicksort/Tests/QuicksortTests.swift @@ -4,9 +4,9 @@ class QuicksortTests: XCTestCase { func testQuicksort() { checkSortAlgorithm(quicksort) } - + private typealias QuicksortFunction = (inout [Int], low: Int, high: Int) -> Void - + private func checkQuicksort(function: QuicksortFunction) { checkSortAlgorithm { (a: [Int]) -> [Int] in var b = a diff --git a/Radix Sort/radixSort.swift b/Radix Sort/radixSort.swift index 64166e88a..31a783db7 100644 --- a/Radix Sort/radixSort.swift +++ b/Radix Sort/radixSort.swift @@ -24,7 +24,7 @@ func radixSort(inout arr: [Int] ) { } - for number in arr { + for number in arr { index = number / digit //Which bucket will we access? buckets[index % radix].append(number) if done && index > 0 { //If we arent done, continue to finish, otherwise we are done diff --git a/Radix Tree/RadixTree.playground/Sources/RadixTree.swift b/Radix Tree/RadixTree.playground/Sources/RadixTree.swift index 8b11e2508..3cba5254a 100644 --- a/Radix Tree/RadixTree.playground/Sources/RadixTree.swift +++ b/Radix Tree/RadixTree.playground/Sources/RadixTree.swift @@ -35,13 +35,12 @@ public class Root { // Prints the tree for debugging/visualization purposes. public func printRoot() { // Print the first half of the children - if (children.count > 1) { + if children.count > 1 { for c in 0...children.count/2-1 { children[c].printEdge() print("|") } - } - else if children.count > 0 { + } else if children.count > 0 { children[0].printEdge() } // Then print the root @@ -98,16 +97,14 @@ public class Edge: Root { for c in 0...children.count/2-1 { children[c].printEdge() } - } - else if children.count > 0 { + } else if children.count > 0 { children[0].printEdge() } // Tab over once up to the edge's level for x in 1...level() { if x == level() { print("|------>", terminator: "") - } - else { + } else { print("| ", terminator: "") } } @@ -153,7 +150,7 @@ public class RadixTree { // currEdge is the current Edge (or Root) in question var currEdge = root - while (true) { + while true { var found = false // If the current Edge has no children then the remaining searchStr is @@ -250,7 +247,7 @@ public class RadixTree { } var searchStr = str var currEdge = root - while (true) { + while true { var found = false // Loop through currEdge's children for c in currEdge.children { @@ -319,7 +316,7 @@ public class RadixTree { var searchStr = str var currEdge = root - while (true) { + while true { var found = false // If currEdge has no children, then the searchStr is not in the tree if currEdge.children.count == 0 { @@ -376,8 +373,7 @@ public func sharedPrefix(str1: String, _ str2: String) -> String { temp.append( str1[c1] ) c1 = c1.successor() c2 = c2.successor() - } - else { + } else { return temp } } diff --git a/Radix Tree/RadixTree.swift b/Radix Tree/RadixTree.swift index 8b11e2508..3cba5254a 100644 --- a/Radix Tree/RadixTree.swift +++ b/Radix Tree/RadixTree.swift @@ -35,13 +35,12 @@ public class Root { // Prints the tree for debugging/visualization purposes. public func printRoot() { // Print the first half of the children - if (children.count > 1) { + if children.count > 1 { for c in 0...children.count/2-1 { children[c].printEdge() print("|") } - } - else if children.count > 0 { + } else if children.count > 0 { children[0].printEdge() } // Then print the root @@ -98,16 +97,14 @@ public class Edge: Root { for c in 0...children.count/2-1 { children[c].printEdge() } - } - else if children.count > 0 { + } else if children.count > 0 { children[0].printEdge() } // Tab over once up to the edge's level for x in 1...level() { if x == level() { print("|------>", terminator: "") - } - else { + } else { print("| ", terminator: "") } } @@ -153,7 +150,7 @@ public class RadixTree { // currEdge is the current Edge (or Root) in question var currEdge = root - while (true) { + while true { var found = false // If the current Edge has no children then the remaining searchStr is @@ -250,7 +247,7 @@ public class RadixTree { } var searchStr = str var currEdge = root - while (true) { + while true { var found = false // Loop through currEdge's children for c in currEdge.children { @@ -319,7 +316,7 @@ public class RadixTree { var searchStr = str var currEdge = root - while (true) { + while true { var found = false // If currEdge has no children, then the searchStr is not in the tree if currEdge.children.count == 0 { @@ -376,8 +373,7 @@ public func sharedPrefix(str1: String, _ str2: String) -> String { temp.append( str1[c1] ) c1 = c1.successor() c2 = c2.successor() - } - else { + } else { return temp } } diff --git a/Red-Black Tree/RBTree.swift b/Red-Black Tree/RBTree.swift index 8b2653297..fe7f34a72 100644 --- a/Red-Black Tree/RBTree.swift +++ b/Red-Black Tree/RBTree.swift @@ -1,43 +1,41 @@ -public class RBTNode{ +public class RBTNode { private(set) public var color: Bool private(set) public var left: RBTNode! private(set) public var right: RBTNode! private(set) public var parent: RBTNode! private(set) public var data: Int - init(){ + init() { self.data = -1 self.color = true self.left = nil self.right = nil self.parent = nil } - init(rootData: Int){ + init(rootData: Int) { self.data = rootData self.color = true //0 is black 1 is red self.left = nil self.right = nil self.parent = nil } - deinit{ + deinit { print("Node: \(self.data) is bein deinitialized") } - public func grandparent()->RBTNode?{ - if(self.parent === nil || self.parent.parent === nil){ + public func grandparent() -> RBTNode? { + if self.parent === nil || self.parent.parent === nil { return nil - } - else{ + } else { return self.parent.parent } } - public func sibling()->RBTNode?{ - if(self.parent === nil || self.parent.right === nil || self.parent.left === nil){ + public func sibling() -> RBTNode? { + if self.parent === nil || self.parent.right === nil || self.parent.left === nil { return nil } - if(self === self.parent!.left!){ + if self === self.parent!.left! { return self.parent!.right! - } - else{ + } else { return self.parent!.left! } } @@ -48,32 +46,31 @@ public class RBTree { root = RBTNode(rootData: rootData) root!.color = false } - init(){ + init() { root = nil } - public func depth()->Int{ + public func depth() -> Int { let n = depth(root!) return n } //return the max depth of the tree - private func depth(rooty:RBTNode?)->Int{ - if(rooty == nil){ + private func depth(rooty: RBTNode?) -> Int { + if rooty == nil { return 0 - } - else{ - return 1+(max(depth(root!.left),depth(root!.right))) + } else { + return 1+(max(depth(root!.left), depth(root!.right))) } } - public func inOrder(){ + public func inOrder() { inOrder(root) } //Prints the in order traversal of the current tree - private func inOrder(root: RBTNode?){ - if(self.root == nil ){ + private func inOrder(root: RBTNode?) { + if self.root == nil { print("The tree is empty.") } - if(root == nil){ + if root == nil { return } inOrder(root!.left) @@ -91,13 +88,13 @@ public class RBTree { private func leftRotate(x: RBTNode) { let newRoot = x.right x.right = newRoot.left - if (newRoot.left !== nil) { + if newRoot.left !== nil { newRoot.left.parent = x } newRoot.parent = x.parent - if(x.parent === nil) { + if x.parent === nil { root = newRoot - } else if (x === x.parent.left) { + } else if x === x.parent.left { x.parent.left = newRoot } else { x.parent.right = newRoot @@ -130,51 +127,50 @@ public class RBTree { newRoot.right = x x.parent = newRoot } - public func insertFixup(value: Int){ + public func insertFixup(value: Int) { let inserted = find(value) print("Inserted Node: \(inserted!.data)") insertCase1(inserted) } //Case where root is the only node - private func insertCase1(inserted: RBTNode?){ + private func insertCase1(inserted: RBTNode?) { let myroot = self.root! - if myroot === inserted!{ + if myroot === inserted! { self.root!.color = false } insertCase2(inserted!) } //Case for inserting a node as a child of a black node - private func insertCase2(inserted: RBTNode?){ - if inserted!.parent!.color == false{ + private func insertCase2(inserted: RBTNode?) { + if inserted!.parent!.color == false { return } insertCase3(inserted!) } //Insert case for if the parent is black and parent's siblng is black - private func insertCase3(inserted: RBTNode?){ - if(inserted!.parent!.sibling() != nil && - inserted!.parent!.sibling()!.color == true){ + private func insertCase3(inserted: RBTNode?) { + if inserted!.parent!.sibling() != nil && + inserted!.parent!.sibling()!.color == true { inserted!.parent!.color = false inserted!.parent!.sibling()!.color = false let g = inserted!.grandparent g()!.color = true - if(g()!.parent == nil){ + if g()!.parent == nil { g()!.color = false } } insertCase4(inserted) } //Insert case for Node N is left of parent and parent is right of grandparent - private func insertCase4( insert: RBTNode?){ + private func insertCase4( insert: RBTNode?) { var inserted = insert - if((inserted! === inserted!.parent!.right) && - (inserted!.grandparent()!.left === inserted!.parent!)){ + if (inserted! === inserted!.parent!.right) && + (inserted!.grandparent()!.left === inserted!.parent!) { leftRotate(inserted!.parent) inserted! = inserted!.left - } - else if((inserted! === inserted!.parent!.left) && - (inserted!.grandparent()!.right === inserted!.parent!)){ + } else if (inserted! === inserted!.parent!.left) && + (inserted!.grandparent()!.right === inserted!.parent!) { rightRotate(inserted!.parent) inserted! = inserted!.right @@ -182,19 +178,18 @@ public class RBTree { insertCase5(inserted) } //Insert case for Node n where parent is red and parent's sibling is black - private func insertCase5(inserted: RBTNode?){ - if((inserted!.parent!.color == true && + private func insertCase5(inserted: RBTNode?) { + if inserted!.parent!.color == true && (inserted!.parent!.sibling()?.color == false || - inserted!.parent!.sibling() == nil ))){ + inserted!.parent!.sibling() == nil) { - if(inserted! === inserted!.parent!.left && inserted!.grandparent()!.left === inserted!.parent!){ + if inserted! === inserted!.parent!.left && inserted!.grandparent()!.left === inserted!.parent! { inserted!.parent.color = false inserted!.grandparent()?.color = true - if(inserted! === inserted!.parent!.left){ + if inserted! === inserted!.parent!.left { rightRotate(inserted!.grandparent()!) } - } - else if(inserted! === inserted!.parent!.right && inserted!.grandparent()!.right === inserted!.parent!){ + } else if inserted! === inserted!.parent!.right && inserted!.grandparent()!.right === inserted!.parent! { inserted!.parent.color = false inserted!.grandparent()?.color = true leftRotate(inserted!.grandparent()!) @@ -208,11 +203,10 @@ public class RBTree { } //Basic BST insert implementation private func insert(value: Int, parent: RBTNode) { - if self.root == nil{ + if self.root == nil { self.root = RBTNode(rootData: value) return - } - else if value < parent.data { + } else if value < parent.data { if let left = parent.left { insert(value, parent: left) } else { @@ -228,37 +222,34 @@ public class RBTree { } } } - public func find(data: Int)->RBTNode?{ - return find(root!,data: data) + public func find(data: Int) -> RBTNode? { + return find(root!, data: data) } //Returns the reference to the RBTNode whos data was requested - private func find(root: RBTNode, data: Int)->RBTNode?{ - if data == root.data{ + private func find(root: RBTNode, data: Int) -> RBTNode? { + if data == root.data { return root } if root.data != data && root.right == nil && root.left == nil { return nil - } - else if data > root.data{ + } else if data > root.data { return find(root.right, data: data) - } - else if data < root.data{ + } else if data < root.data { return find(root.left, data: data) - } - else{ + } else { return nil } } //DELETION HELPER FUNCTIONS - public func remove(value: Int){ + public func remove(value: Int) { let toRemove = find(value) - if(toRemove == nil){ + if toRemove == nil { return } } //Transplant the positions of two nodes in the RBTree - public func replaceNode(n1: RBTNode, n2: RBTNode){ + public func replaceNode(n1: RBTNode, n2: RBTNode) { let temp = n1.data let temp_color = n1.color n1.data = n2.data @@ -267,41 +258,41 @@ public class RBTree { n2.color = temp_color } //returns the node with the minimum value in the subtree - public func minimum(Node: RBTNode)->RBTNode { - var node = Node - while node.left !== nil{ - node = node.left + public func minimum(node: RBTNode) -> RBTNode { + var minimumNode = node + while minimumNode.left !== nil { + minimumNode = minimumNode.left } - return node + return minimumNode } //Returns the next largest node in the tree - public func successor(Node: RBTNode) -> RBTNode? { - var node = Node - if node.right !== nil { - return minimum(node.right) + public func successor(node: RBTNode) -> RBTNode? { + var nextLargestNode = node + if nextLargestNode.right !== nil { + return minimum(nextLargestNode.right) } - var successor = node.parent - while successor !== nil && node === successor.right { - node = successor + var successor = nextLargestNode.parent + while successor !== nil && nextLargestNode === successor.right { + nextLargestNode = successor successor = successor.parent } return successor } //Returns the next smallest node in the tree - public func predecessor(Node: RBTNode) -> RBTNode{ - var node = Node - if node.left !== nil { - return minimum(node.left) + public func predecessor(node: RBTNode) -> RBTNode { + var nextSmallestNode = node + if nextSmallestNode.left !== nil { + return minimum(nextSmallestNode.left) } - var successor = node.parent - while successor !== nil && node === successor.left { - node = successor + var successor = nextSmallestNode.parent + while successor !== nil && nextSmallestNode === successor.left { + nextSmallestNode = successor successor = successor.parent } return successor } //Returns the node with the largest value in the subtree - public func maximum(rootnode: RBTNode) -> RBTNode{ + public func maximum(rootnode: RBTNode) -> RBTNode { var rootNode = rootnode while rootNode.right !== nil { rootNode = rootNode.right @@ -309,141 +300,132 @@ public class RBTree { return rootNode } //call to remove a node from the tree - public func delete(x: Int){ + public func delete(x: Int) { let toDel = find(x) deleteNode(toDel!) } //Function call for removing a node - private func deleteNode(todel: RBTNode?){ + private func deleteNode(todel: RBTNode?) { var toDel = todel //case for if todel is the only node in the tree - if(toDel!.left === nil && toDel!.right === nil && toDel!.parent === nil){ + if toDel!.left === nil && toDel!.right === nil && toDel!.parent === nil { toDel = nil self.root = nil return } //case for if toDell is a red node w/ no children - if(toDel!.left === nil && toDel!.right === nil && toDel!.color == true){ - if(toDel!.parent.left === toDel!){ + if toDel!.left === nil && toDel!.right === nil && toDel!.color == true { + if toDel!.parent.left === toDel! { toDel!.parent.left = nil toDel = nil - } - else if(toDel!.parent === nil){ + } else if toDel!.parent === nil { toDel = nil - } - else{ + } else { toDel?.parent.right = nil toDel = nil } return } //case for toDel having two children - if(toDel!.left !== nil && toDel!.right !== nil){ + if toDel!.left !== nil && toDel!.right !== nil { let pred = maximum(toDel!.left!) toDel!.data = pred.data toDel! = pred } //case for toDel having one child var child: RBTNode? = nil - if(toDel!.right === nil){ + if toDel!.right === nil { child = toDel!.left - } - else{ + } else { child = toDel!.right } - if(toDel!.color == false && child !== nil){ + if toDel!.color == false && child !== nil { toDel!.color = child!.color deleteCase1(toDel!) } - if(child !== nil){ + if child !== nil { replaceNode(toDel!, n2: child!) - if(toDel!.parent === nil && child !== nil){ + if toDel!.parent === nil && child !== nil { child!.color = false } } - if(toDel!.parent.left === toDel!){ + if toDel!.parent.left === toDel! { toDel!.parent.left = nil toDel = nil return - } - else if(toDel!.parent === nil){ + } else if toDel!.parent === nil { toDel = nil return - } - else{ + } else { toDel?.parent.right = nil toDel = nil return } } //delete case for if parent is nil after deletion - private func deleteCase1( toDel: RBTNode?){ - if(toDel?.parent === nil){ + private func deleteCase1( toDel: RBTNode?) { + if toDel?.parent === nil { return - } - else{ + } else { deleteCase2(toDel) } } //case to fix tree after deletion and sibling is red - private func deleteCase2(toDel: RBTNode?){ + private func deleteCase2(toDel: RBTNode?) { let sibling = toDel!.sibling() - if(sibling?.color == true){ - toDel!.parent.color = true; + if sibling?.color == true { + toDel!.parent.color = true sibling?.color = false - if(toDel! === toDel!.parent.left){ + if toDel! === toDel!.parent.left { leftRotate(toDel!.parent) - } - else{ + } else { rightRotate(toDel!.parent) } deleteCase3(toDel!) } } //delete case for fixing tree when parnet is black and sibling is black and sibling.children are also black - private func deleteCase3(toDel: RBTNode?){ - if(toDel!.parent?.color == false && + private func deleteCase3(toDel: RBTNode?) { + if toDel!.parent?.color == false && toDel!.sibling()?.color == false && toDel!.sibling()?.left!.color == false && - toDel!.sibling()?.right!.color == false){ + toDel!.sibling()?.right!.color == false { toDel!.sibling()?.color = true toDel!.parent?.color = false - } - else{ + } else { deleteCase4(toDel) } } - private func deleteCase4(toDel: RBTNode?){ - if(toDel!.parent?.color == true && + private func deleteCase4(toDel: RBTNode?) { + if toDel!.parent?.color == true && toDel!.sibling()?.color == false && toDel!.sibling()?.left!.color == false && - toDel!.sibling()?.right!.color == false){ + toDel!.sibling()?.right!.color == false { toDel!.sibling()?.color = true toDel!.parent.color = false - } - else{ + } else { deleteCase5(toDel) } } //delete case for fixing tree if toDel is a left child and sibling(n) is black and children of sibling(n) are black and white respectibely - private func deleteCase5(toDel:RBTNode?){ - if(toDel! === toDel!.parent?.left && + private func deleteCase5(toDel: RBTNode?) { + if toDel! === toDel!.parent?.left && toDel!.sibling()?.color == false && toDel!.sibling()?.left.color == true && - toDel!.sibling()?.right.color == false){ + toDel!.sibling()?.right.color == false { toDel!.sibling()?.color = true toDel!.sibling()?.left?.color = false rightRotate(toDel!.sibling()!) } //opposite case - else if(toDel! === toDel!.parent?.right && + else if toDel! === toDel!.parent?.right && toDel!.sibling()?.color == false && toDel!.sibling()?.left.color == false && - toDel!.sibling()?.right.color == true){ + toDel!.sibling()?.right.color == true { toDel!.sibling()?.color = true toDel!.sibling()?.right?.color = false @@ -451,15 +433,14 @@ public class RBTree { } } //final rotations to be done after deleting a black node from the tree - private func deleteCase6(toDel: RBTNode?){ + private func deleteCase6(toDel: RBTNode?) { let color = toDel!.sibling()?.color toDel!.parent?.color = color! toDel!.parent?.color = false - if(toDel! === toDel!.parent.left){ + if toDel! === toDel!.parent.left { toDel!.sibling()?.right?.color = false leftRotate(toDel!.parent!) - } - else{ + } else { toDel!.sibling()?.left?.color = false rightRotate(toDel!.parent!) } diff --git a/Ring Buffer/RingBuffer.playground/Contents.swift b/Ring Buffer/RingBuffer.playground/Contents.swift index 5e6c4d6eb..a7522c366 100644 --- a/Ring Buffer/RingBuffer.playground/Contents.swift +++ b/Ring Buffer/RingBuffer.playground/Contents.swift @@ -4,11 +4,11 @@ public struct RingBuffer { private var array: [T?] private var readIndex = 0 private var writeIndex = 0 - + public init(count: Int) { array = [T?](count: count, repeatedValue: nil) } - + public mutating func write(element: T) -> Bool { if !isFull { array[writeIndex % array.count] = element @@ -18,7 +18,7 @@ public struct RingBuffer { return false } } - + public mutating func read() -> T? { if !isEmpty { let element = array[readIndex % array.count] @@ -32,7 +32,7 @@ public struct RingBuffer { private var availableSpaceForReading: Int { return writeIndex - readIndex } - + public var isEmpty: Bool { return availableSpaceForReading == 0 } diff --git a/Ring Buffer/RingBuffer.swift b/Ring Buffer/RingBuffer.swift index 3176ab1fc..7e845aa74 100644 --- a/Ring Buffer/RingBuffer.swift +++ b/Ring Buffer/RingBuffer.swift @@ -14,11 +14,11 @@ public struct RingBuffer { private var array: [T?] private var readIndex = 0 private var writeIndex = 0 - + public init(count: Int) { array = [T?](count: count, repeatedValue: nil) } - + /* Returns false if out of space. */ public mutating func write(element: T) -> Bool { if !isFull { @@ -29,7 +29,7 @@ public struct RingBuffer { return false } } - + /* Returns nil if the buffer is empty. */ public mutating func read() -> T? { if !isEmpty { @@ -40,20 +40,20 @@ public struct RingBuffer { return nil } } - + private var availableSpaceForReading: Int { return writeIndex - readIndex } - + public var isEmpty: Bool { return availableSpaceForReading == 0 } - + private var availableSpaceForWriting: Int { return array.count - availableSpaceForReading } - + public var isFull: Bool { return availableSpaceForWriting == 0 } -} \ No newline at end of file +} diff --git a/Run-Length Encoding/RLE.playground/Contents.swift b/Run-Length Encoding/RLE.playground/Contents.swift index b79cdf9e6..41dcae3b1 100644 --- a/Run-Length Encoding/RLE.playground/Contents.swift +++ b/Run-Length Encoding/RLE.playground/Contents.swift @@ -11,12 +11,12 @@ extension NSData { if length > 0 { var ptr = UnsafePointer(bytes) let end = ptr + length - + while ptr < end { var count = 0 var byte = ptr.memory var next = byte - + // Is the next byte the same? Keep reading until we find a different // value, or we reach the end of the data, or the run is 64 bytes. while next == byte && ptr < end && count < 64 { @@ -36,7 +36,7 @@ extension NSData { } return data } - + /* Converts a run-length encoded NSData back to the original. */ @@ -47,11 +47,11 @@ extension NSData { let end = ptr + length while ptr < end { - // Read the next byte. This is either a single value less than 192, + // Read the next byte. This is either a single value less than 192, // or the start of a byte run. var byte = ptr.memory ptr = ptr.advancedBy(1) - + if byte < 192 { // single value data.appendBytes(&byte, length: 1) diff --git a/Run-Length Encoding/RLE.swift b/Run-Length Encoding/RLE.swift index f26299cf1..b62c59c63 100644 --- a/Run-Length Encoding/RLE.swift +++ b/Run-Length Encoding/RLE.swift @@ -9,12 +9,12 @@ extension NSData { if length > 0 { var ptr = UnsafePointer(bytes) let end = ptr + length - + while ptr < end { var count = 0 var byte = ptr.memory var next = byte - + // Is the next byte the same? Keep reading until we find a different // value, or we reach the end of the data, or the run is 64 bytes. while next == byte && ptr < end && count < 64 { @@ -34,7 +34,7 @@ extension NSData { } return data } - + /* Converts a run-length encoded NSData back to the original. */ @@ -45,11 +45,11 @@ extension NSData { let end = ptr + length while ptr < end { - // Read the next byte. This is either a single value less than 192, + // Read the next byte. This is either a single value less than 192, // or the start of a byte run. var byte = ptr.memory ptr = ptr.advancedBy(1) - + if byte < 192 { // single value data.appendBytes(&byte, length: 1) diff --git a/Run-Length Encoding/Tests/RLETests.swift b/Run-Length Encoding/Tests/RLETests.swift index a55f74fdc..f4b2f8d7d 100644 --- a/Run-Length Encoding/Tests/RLETests.swift +++ b/Run-Length Encoding/Tests/RLETests.swift @@ -36,17 +36,17 @@ class RLETests: XCTestCase { let bytes: [UInt8] = [] encodeAndDecode(bytes) } - + func testOneByteWithLowValue() { let bytes: [UInt8] = [ 0x80 ] encodeAndDecode(bytes) } - + func testOneByteWithHighValue() { let bytes: [UInt8] = [ 0xD0 ] encodeAndDecode(bytes) } - + func testSimpleCases() { let bytes: [UInt8] = [ 0x00, @@ -96,7 +96,7 @@ class RLETests: XCTestCase { bufferWithSpans(66) bufferWithSpans(80) } - + func testRandomBytes() { for _ in 0..<10 { let length = 1 + Int(arc4random_uniform(2048)) diff --git a/Segment Tree/SegmentTree.playground/Contents.swift b/Segment Tree/SegmentTree.playground/Contents.swift index e74591e56..14b7f57cf 100644 --- a/Segment Tree/SegmentTree.playground/Contents.swift +++ b/Segment Tree/SegmentTree.playground/Contents.swift @@ -1,14 +1,14 @@ //: Playground - noun: a place where people can play public class SegmentTree { - + private var value: T private var function: (T, T) -> T private var leftBound: Int private var rightBound: Int private var leftChild: SegmentTree? private var rightChild: SegmentTree? - + public init(array: [T], leftBound: Int, rightBound: Int, function: (T, T) -> T) { self.leftBound = leftBound self.rightBound = rightBound @@ -23,19 +23,19 @@ public class SegmentTree { value = function(leftChild!.value, rightChild!.value) } } - + public convenience init(array: [T], function: (T, T) -> T) { self.init(array: array, leftBound: 0, rightBound: array.count-1, function: function) } - + public func queryWithLeftBound(leftBound: Int, rightBound: Int) -> T { if self.leftBound == leftBound && self.rightBound == rightBound { return self.value } - + guard let leftChild = leftChild else { fatalError("leftChild should not be nil") } guard let rightChild = rightChild else { fatalError("rightChild should not be nil") } - + if leftChild.rightBound < leftBound { return rightChild.queryWithLeftBound(leftBound, rightBound: rightBound) } else if rightChild.leftBound > rightBound { @@ -83,7 +83,7 @@ func gcd(m: Int, _ n: Int) -> Int { var a = 0 var b = max(m, n) var r = min(m, n) - + while r != 0 { a = b b = r @@ -137,4 +137,3 @@ stringSegmentTree.replaceItemAtIndex(4, withItem: " swift") stringSegmentTree.replaceItemAtIndex(5, withItem: "!") print(stringSegmentTree.queryWithLeftBound(0, rightBound: 5)) - diff --git a/Segment Tree/SegmentTree.swift b/Segment Tree/SegmentTree.swift index e616255ec..608d5151a 100644 --- a/Segment Tree/SegmentTree.swift +++ b/Segment Tree/SegmentTree.swift @@ -1,6 +1,6 @@ /* Segment tree - + Performance: building the tree is O(n) query is O(log n) @@ -8,14 +8,14 @@ */ public class SegmentTree { - + private var value: T private var function: (T, T) -> T private var leftBound: Int private var rightBound: Int private var leftChild: SegmentTree? private var rightChild: SegmentTree? - + public init(array: [T], leftBound: Int, rightBound: Int, function: (T, T) -> T) { self.leftBound = leftBound self.rightBound = rightBound @@ -30,19 +30,19 @@ public class SegmentTree { value = function(leftChild!.value, rightChild!.value) } } - + public convenience init(array: [T], function: (T, T) -> T) { self.init(array: array, leftBound: 0, rightBound: array.count-1, function: function) } - + public func queryWithLeftBound(leftBound: Int, rightBound: Int) -> T { if self.leftBound == leftBound && self.rightBound == rightBound { return self.value } - + guard let leftChild = leftChild else { fatalError("leftChild should not be nil") } guard let rightChild = rightChild else { fatalError("rightChild should not be nil") } - + if leftChild.rightBound < leftBound { return rightChild.queryWithLeftBound(leftBound, rightBound: rightBound) } else if rightChild.leftBound > rightBound { diff --git a/Select Minimum Maximum/Maximum.swift b/Select Minimum Maximum/Maximum.swift index eb0204b0e..8c78ba478 100644 --- a/Select Minimum Maximum/Maximum.swift +++ b/Select Minimum Maximum/Maximum.swift @@ -6,7 +6,7 @@ func maximum(var array: [T]) -> T? { guard !array.isEmpty else { return nil } - + var maximum = array.removeFirst() for element in array { maximum = element > maximum ? element : maximum diff --git a/Select Minimum Maximum/SelectMinimumMaximum.playground/Contents.swift b/Select Minimum Maximum/SelectMinimumMaximum.playground/Contents.swift index 450b6624e..ef92ac1e6 100644 --- a/Select Minimum Maximum/SelectMinimumMaximum.playground/Contents.swift +++ b/Select Minimum Maximum/SelectMinimumMaximum.playground/Contents.swift @@ -25,8 +25,7 @@ func maximum(var array: [T]) -> T? { } // Compare in pairs to find minimum and maximum -func minimumMaximum(var array: [T]) -> (minimum: T, maximum: T)? -{ +func minimumMaximum(var array: [T]) -> (minimum: T, maximum: T)? { guard !array.isEmpty else { return nil } diff --git a/Select Minimum Maximum/Tests/MaximumTests.swift b/Select Minimum Maximum/Tests/MaximumTests.swift index 38bcf483b..cd63ac0a3 100644 --- a/Select Minimum Maximum/Tests/MaximumTests.swift +++ b/Select Minimum Maximum/Tests/MaximumTests.swift @@ -30,7 +30,7 @@ class MaximumTests: XCTestCase { let array = [ 9, 8, 6, 4, 3 ] let result = maximum(array) - + XCTAssertEqual(result, 9) } diff --git a/Select Minimum Maximum/Tests/TestHelper.swift b/Select Minimum Maximum/Tests/TestHelper.swift index 7afe751d0..cd782d305 100644 --- a/Select Minimum Maximum/Tests/TestHelper.swift +++ b/Select Minimum Maximum/Tests/TestHelper.swift @@ -1,5 +1,5 @@ import Foundation func createRandomList(numberOfElements: Int) -> [UInt32] { - return (1...numberOfElements).map{_ in arc4random()} + return (1...numberOfElements).map {_ in arc4random()} } diff --git a/Selection Sampling/SelectionSampling.playground/Contents.swift b/Selection Sampling/SelectionSampling.playground/Contents.swift index 4afbe4f03..f6032137b 100644 --- a/Selection Sampling/SelectionSampling.playground/Contents.swift +++ b/Selection Sampling/SelectionSampling.playground/Contents.swift @@ -25,13 +25,13 @@ func select(from a: [T], count requested: Int) -> [T] { var examined = 0 var selected = 0 var b = [T]() - + while selected < requested { examined += 1 - + // Calculate random variable 0.0 <= r < 1.0 (exclusive!). let r = Double(arc4random()) / 0x100000000 - + let leftToExamine = a.count - examined + 1 let leftToAdd = requested - selected diff --git a/Selection Sampling/SelectionSampling.swift b/Selection Sampling/SelectionSampling.swift index d562481c6..1e6257908 100644 --- a/Selection Sampling/SelectionSampling.swift +++ b/Selection Sampling/SelectionSampling.swift @@ -30,7 +30,7 @@ func reservoirSample(from a: [T], count k: Int) -> [T] { precondition(a.count >= k) var result = [T]() - + // Fill the result array with first k elements. for i in 0..(from a: [T], count requested: Int) -> [T] { var examined = 0 var selected = 0 var b = [T]() - + while selected < requested { examined += 1 - + // Calculate random variable 0.0 <= r < 1.0 (exclusive!). let r = Double(arc4random()) / 0x100000000 - + let leftToExamine = a.count - examined + 1 let leftToAdd = requested - selected diff --git a/Selection Sort/SelectionSort.swift b/Selection Sort/SelectionSort.swift index 4c50688e5..9d7b45ad8 100644 --- a/Selection Sort/SelectionSort.swift +++ b/Selection Sort/SelectionSort.swift @@ -3,7 +3,7 @@ func selectionSort(array: [T], _ isOrderedBefore: (T, T) -> Bool) -> [T] { var a = array for x in 0 ..< a.count - 1 { - + // Find the lowest value in the rest of the array. var lowest = x for y in x + 1 ..< a.count { @@ -11,7 +11,7 @@ func selectionSort(array: [T], _ isOrderedBefore: (T, T) -> Bool) -> [T] { lowest = y } } - + // Swap the lowest value with the current array index. if x != lowest { swap(&a[x], &a[lowest]) diff --git a/Shell Sort/shellsort.swift b/Shell Sort/shellsort.swift index 5b2c73763..489a92ebc 100644 --- a/Shell Sort/shellsort.swift +++ b/Shell Sort/shellsort.swift @@ -21,7 +21,7 @@ // SOFTWARE. public func insertionSort(inout list: [Int], start: Int, gap: Int) { - for i in (start + gap).stride(to: list.count, by: gap){ + for i in (start + gap).stride(to: list.count, by: gap) { let currentValue = list[i] var pos = i while pos >= gap && list[pos - gap] > currentValue { diff --git a/Shortest Path (Unweighted)/ShortestPath.playground/Sources/Edge.swift b/Shortest Path (Unweighted)/ShortestPath.playground/Sources/Edge.swift index 3937a2cc7..9a58a1f96 100644 --- a/Shortest Path (Unweighted)/ShortestPath.playground/Sources/Edge.swift +++ b/Shortest Path (Unweighted)/ShortestPath.playground/Sources/Edge.swift @@ -1,4 +1,4 @@ -public class Edge : Equatable { +public class Edge: Equatable { public var neighbor: Node public init(neighbor: Node) { @@ -6,6 +6,6 @@ public class Edge : Equatable { } } -public func ==(lhs: Edge, rhs: Edge) -> Bool { +public func == (lhs: Edge, rhs: Edge) -> Bool { return lhs.neighbor == rhs.neighbor } diff --git a/Shortest Path (Unweighted)/ShortestPath.playground/Sources/Graph.swift b/Shortest Path (Unweighted)/ShortestPath.playground/Sources/Graph.swift index e89d4ac97..8cfb2a09c 100644 --- a/Shortest Path (Unweighted)/ShortestPath.playground/Sources/Graph.swift +++ b/Shortest Path (Unweighted)/ShortestPath.playground/Sources/Graph.swift @@ -1,4 +1,4 @@ -public class Graph : CustomStringConvertible, Equatable { +public class Graph: CustomStringConvertible, Equatable { public private(set) var nodes: [Node] public init() { @@ -21,14 +21,14 @@ public class Graph : CustomStringConvertible, Equatable { for node in nodes { if !node.neighbors.isEmpty { - description += "[node: \(node.label) edges: \(node.neighbors.map{ $0.neighbor.label})]" + description += "[node: \(node.label) edges: \(node.neighbors.map { $0.neighbor.label})]" } } return description } public func findNodeWithLabel(label: String) -> Node { - return nodes.filter{ $0.label == label }.first! + return nodes.filter { $0.label == label }.first! } public func duplicate() -> Graph { @@ -50,6 +50,6 @@ public class Graph : CustomStringConvertible, Equatable { } } -public func ==(lhs: Graph, rhs: Graph) -> Bool { +public func == (lhs: Graph, rhs: Graph) -> Bool { return lhs.nodes == rhs.nodes } diff --git a/Shortest Path (Unweighted)/ShortestPath.playground/Sources/Node.swift b/Shortest Path (Unweighted)/ShortestPath.playground/Sources/Node.swift index 9d8435ffa..37a3b3fdf 100644 --- a/Shortest Path (Unweighted)/ShortestPath.playground/Sources/Node.swift +++ b/Shortest Path (Unweighted)/ShortestPath.playground/Sources/Node.swift @@ -1,4 +1,4 @@ -public class Node : CustomStringConvertible, Equatable { +public class Node: CustomStringConvertible, Equatable { public var neighbors: [Edge] public private(set) var label: String @@ -23,10 +23,10 @@ public class Node : CustomStringConvertible, Equatable { } public func remove(edge: Edge) { - neighbors.removeAtIndex(neighbors.indexOf{ $0 === edge }!) + neighbors.removeAtIndex(neighbors.indexOf { $0 === edge }!) } } -public func ==(lhs: Node, rhs: Node) -> Bool { +public func == (lhs: Node, rhs: Node) -> Bool { return lhs.label == rhs.label && lhs.neighbors == rhs.neighbors } diff --git a/Shortest Path (Unweighted)/Tests/Graph.swift b/Shortest Path (Unweighted)/Tests/Graph.swift index 6f69ee800..ed71cab7c 100644 --- a/Shortest Path (Unweighted)/Tests/Graph.swift +++ b/Shortest Path (Unweighted)/Tests/Graph.swift @@ -1,6 +1,6 @@ // MARK: - Edge -public class Edge : Equatable { +public class Edge: Equatable { public var neighbor: Node public init(neighbor: Node) { @@ -8,15 +8,15 @@ public class Edge : Equatable { } } -public func ==(lhs: Edge, rhs: Edge) -> Bool { +public func == (lhs: Edge, rhs: Edge) -> Bool { return lhs.neighbor == rhs.neighbor } // MARK: - Node -public class Node : CustomStringConvertible, Equatable { +public class Node: CustomStringConvertible, Equatable { public var neighbors: [Edge] - + public private(set) var label: String public var distance: Int? public var visited: Bool @@ -39,17 +39,17 @@ public class Node : CustomStringConvertible, Equatable { } public func remove(edge: Edge) { - neighbors.removeAtIndex(neighbors.indexOf{ $0 === edge }!) + neighbors.removeAtIndex(neighbors.indexOf { $0 === edge }!) } } -public func ==(lhs: Node, rhs: Node) -> Bool { +public func == (lhs: Node, rhs: Node) -> Bool { return lhs.label == rhs.label && lhs.neighbors == rhs.neighbors } // MARK: - Graph -public class Graph : CustomStringConvertible, Equatable { +public class Graph: CustomStringConvertible, Equatable { public private(set) var nodes: [Node] public init() { @@ -72,14 +72,14 @@ public class Graph : CustomStringConvertible, Equatable { for node in nodes { if !node.neighbors.isEmpty { - description += "[node: \(node.label) edges: \(node.neighbors.map{ $0.neighbor.label})]" + description += "[node: \(node.label) edges: \(node.neighbors.map { $0.neighbor.label})]" } } return description } public func findNodeWithLabel(label: String) -> Node { - return nodes.filter{ $0.label == label }.first! + return nodes.filter { $0.label == label }.first! } public func duplicate() -> Graph { @@ -101,6 +101,6 @@ public class Graph : CustomStringConvertible, Equatable { } } -public func ==(lhs: Graph, rhs: Graph) -> Bool { +public func == (lhs: Graph, rhs: Graph) -> Bool { return lhs.nodes == rhs.nodes } diff --git a/Shortest Path (Unweighted)/Tests/ShortestPathTests.swift b/Shortest Path (Unweighted)/Tests/ShortestPathTests.swift index 17c9264a1..003f3cf20 100644 --- a/Shortest Path (Unweighted)/Tests/ShortestPathTests.swift +++ b/Shortest Path (Unweighted)/Tests/ShortestPathTests.swift @@ -86,4 +86,4 @@ class ShortestPathTests: XCTestCase { XCTAssertEqual(shortestPaths.findNodeWithLabel(nodeH.label).distance, 1) XCTAssertEqual(shortestPaths.findNodeWithLabel(nodeI.label).distance, 2) } -} \ No newline at end of file +} diff --git a/Shunting Yard/ShuntingYard.playground/Contents.swift b/Shunting Yard/ShuntingYard.playground/Contents.swift index 52b952d1f..04fed7739 100644 --- a/Shunting Yard/ShuntingYard.playground/Contents.swift +++ b/Shunting Yard/ShuntingYard.playground/Contents.swift @@ -12,7 +12,7 @@ public enum OperatorType: CustomStringConvertible { case Multiply case Percent case Exponent - + public var description: String { switch self { case Add: @@ -36,7 +36,7 @@ public enum TokenType: CustomStringConvertible { case CloseBracket case Operator(OperatorToken) case Operand(Double) - + public var description: String { switch self { case OpenBracket: @@ -53,11 +53,11 @@ public enum TokenType: CustomStringConvertible { public struct OperatorToken: CustomStringConvertible { let operatorType: OperatorType - + init(operatorType: OperatorType) { self.operatorType = operatorType } - + var precedence: Int { switch operatorType { case .Add, .Subtract: @@ -68,44 +68,44 @@ public struct OperatorToken: CustomStringConvertible { return 10 } } - + var associativity: OperatorAssociativity { switch operatorType { case .Add, .Subtract, .Divide, .Multiply, .Percent: - return .LeftAssociative; + return .LeftAssociative case .Exponent: return .RightAssociative } } - + public var description: String { return operatorType.description } } -func <=(left: OperatorToken, right: OperatorToken) -> Bool { +func <= (left: OperatorToken, right: OperatorToken) -> Bool { return left.precedence <= right.precedence } -func <(left: OperatorToken, right: OperatorToken) -> Bool { +func < (left: OperatorToken, right: OperatorToken) -> Bool { return left.precedence < right.precedence } public struct Token: CustomStringConvertible { let tokenType: TokenType - + init(tokenType: TokenType) { self.tokenType = tokenType } - + init(operand: Double) { tokenType = .Operand(operand) } - + init(operatorType: OperatorType) { tokenType = .Operator(OperatorToken(operatorType: operatorType)) } - + var isOpenBracket: Bool { switch tokenType { case .OpenBracket: @@ -114,7 +114,7 @@ public struct Token: CustomStringConvertible { return false } } - + var isOperator: Bool { switch tokenType { case .Operator(_): @@ -123,7 +123,7 @@ public struct Token: CustomStringConvertible { return false } } - + var operatorToken: OperatorToken? { switch tokenType { case .Operator(let operatorToken): @@ -132,7 +132,7 @@ public struct Token: CustomStringConvertible { return nil } } - + public var description: String { return tokenType.description } @@ -140,27 +140,27 @@ public struct Token: CustomStringConvertible { public class InfixExpressionBuilder { private var expression = [Token]() - + public func addOperator(operatorType: OperatorType) -> InfixExpressionBuilder { expression.append(Token(operatorType: operatorType)) return self } - + public func addOperand(operand: Double) -> InfixExpressionBuilder { expression.append(Token(operand: operand)) return self } - + public func addOpenBracket() -> InfixExpressionBuilder { expression.append(Token(tokenType: .OpenBracket)) return self } - + public func addCloseBracket() -> InfixExpressionBuilder { expression.append(Token(tokenType: .CloseBracket)) return self } - + public func build() -> [Token] { // Maybe do some validation here return expression @@ -172,7 +172,7 @@ public func reversePolishNotation(expression: [Token]) -> String { var tokenStack = Stack() var reversePolishNotation = [Token]() - + for token in expression { switch token.tokenType { case .Operand(_): @@ -191,7 +191,7 @@ public func reversePolishNotation(expression: [Token]) -> String { if !tempToken.isOperator { break } - + if let tempOperatorToken = tempToken.operatorToken { if operatorToken.associativity == .LeftAssociative && operatorToken <= tempOperatorToken || operatorToken.associativity == .RightAssociative && operatorToken < tempOperatorToken { @@ -204,19 +204,34 @@ public func reversePolishNotation(expression: [Token]) -> String { tokenStack.push(token) } } - + while tokenStack.count > 0 { reversePolishNotation.append(tokenStack.pop()!) } - + return reversePolishNotation.map({token in token.description}).joinWithSeparator(" ") } // Simple demo -let expr = InfixExpressionBuilder().addOperand(3).addOperator(.Add).addOperand(4).addOperator(.Multiply).addOperand(2).addOperator(.Divide).addOpenBracket().addOperand(1).addOperator(.Subtract).addOperand(5).addCloseBracket().addOperator(.Exponent).addOperand(2).addOperator(.Exponent).addOperand(3).build() +let expr = InfixExpressionBuilder() + .addOperand(3) + .addOperator(.Add) + .addOperand(4) + .addOperator(.Multiply) + .addOperand(2) + .addOperator(.Divide) + .addOpenBracket() + .addOperand(1) + .addOperator(.Subtract) + .addOperand(5) + .addCloseBracket() + .addOperator(.Exponent) + .addOperand(2) + .addOperator(.Exponent) + .addOperand(3) + .build() print(expr.description) print(reversePolishNotation(expr)) - diff --git a/Shunting Yard/ShuntingYard.playground/Sources/Stack.swift b/Shunting Yard/ShuntingYard.playground/Sources/Stack.swift index 93feb2ca1..0df342af5 100644 --- a/Shunting Yard/ShuntingYard.playground/Sources/Stack.swift +++ b/Shunting Yard/ShuntingYard.playground/Sources/Stack.swift @@ -2,23 +2,23 @@ import Foundation public struct Stack { private var array = [T]() - + public init() { array = [] } - + public var isEmpty: Bool { return array.isEmpty } - + public var count: Int { return array.count } - + public mutating func push(element: T) { array.append(element) } - + public mutating func pop() -> T? { if isEmpty { return nil @@ -26,7 +26,7 @@ public struct Stack { return array.removeLast() } } - + public func peek() -> T? { return array.last } @@ -40,4 +40,4 @@ extension Stack: SequenceType { return curr.pop() } } -} \ No newline at end of file +} diff --git a/Shunting Yard/ShuntingYard.playground/timeline.xctimeline b/Shunting Yard/ShuntingYard.playground/timeline.xctimeline deleted file mode 100644 index bf468afec..000000000 --- a/Shunting Yard/ShuntingYard.playground/timeline.xctimeline +++ /dev/null @@ -1,6 +0,0 @@ - - - - - diff --git a/Shunting Yard/ShuntingYard.swift b/Shunting Yard/ShuntingYard.swift index 1da67990d..5159c9172 100644 --- a/Shunting Yard/ShuntingYard.swift +++ b/Shunting Yard/ShuntingYard.swift @@ -18,7 +18,7 @@ public enum OperatorType: CustomStringConvertible { case Multiply case Percent case Exponent - + public var description: String { switch self { case Add: @@ -42,7 +42,7 @@ public enum TokenType: CustomStringConvertible { case CloseBracket case Operator(OperatorToken) case Operand(Double) - + public var description: String { switch self { case OpenBracket: @@ -59,11 +59,11 @@ public enum TokenType: CustomStringConvertible { public struct OperatorToken: CustomStringConvertible { let operatorType: OperatorType - + init(operatorType: OperatorType) { self.operatorType = operatorType } - + var precedence: Int { switch operatorType { case .Add, .Subtract: @@ -74,44 +74,44 @@ public struct OperatorToken: CustomStringConvertible { return 10 } } - + var associativity: OperatorAssociativity { switch operatorType { case .Add, .Subtract, .Divide, .Multiply, .Percent: - return .LeftAssociative; + return .LeftAssociative case .Exponent: return .RightAssociative } } - + public var description: String { return operatorType.description } } -func <=(left: OperatorToken, right: OperatorToken) -> Bool { +func <= (left: OperatorToken, right: OperatorToken) -> Bool { return left.precedence <= right.precedence } -func <(left: OperatorToken, right: OperatorToken) -> Bool { +func < (left: OperatorToken, right: OperatorToken) -> Bool { return left.precedence < right.precedence } public struct Token: CustomStringConvertible { let tokenType: TokenType - + init(tokenType: TokenType) { self.tokenType = tokenType } - + init(operand: Double) { tokenType = .Operand(operand) } - + init(operatorType: OperatorType) { tokenType = .Operator(OperatorToken(operatorType: operatorType)) } - + var isOpenBracket: Bool { switch tokenType { case .OpenBracket: @@ -120,7 +120,7 @@ public struct Token: CustomStringConvertible { return false } } - + var isOperator: Bool { switch tokenType { case .Operator(_): @@ -129,7 +129,7 @@ public struct Token: CustomStringConvertible { return false } } - + var operatorToken: OperatorToken? { switch tokenType { case .Operator(let operatorToken): @@ -138,7 +138,7 @@ public struct Token: CustomStringConvertible { return nil } } - + public var description: String { return tokenType.description } @@ -146,27 +146,27 @@ public struct Token: CustomStringConvertible { public class InfixExpressionBuilder { private var expression = [Token]() - + public func addOperator(operatorType: OperatorType) -> InfixExpressionBuilder { expression.append(Token(operatorType: operatorType)) return self } - + public func addOperand(operand: Double) -> InfixExpressionBuilder { expression.append(Token(operand: operand)) return self } - + public func addOpenBracket() -> InfixExpressionBuilder { expression.append(Token(tokenType: .OpenBracket)) return self } - + public func addCloseBracket() -> InfixExpressionBuilder { expression.append(Token(tokenType: .CloseBracket)) return self } - + public func build() -> [Token] { // Maybe do some validation here return expression @@ -178,7 +178,7 @@ public func reversePolishNotation(expression: [Token]) -> String { var tokenStack = Stack() var reversePolishNotation = [Token]() - + for token in expression { switch token.tokenType { case .Operand(_): @@ -197,7 +197,7 @@ public func reversePolishNotation(expression: [Token]) -> String { if !tempToken.isOperator { break } - + if let tempOperatorToken = tempToken.operatorToken { if operatorToken.associativity == .LeftAssociative && operatorToken <= tempOperatorToken || operatorToken.associativity == .RightAssociative && operatorToken < tempOperatorToken { @@ -210,10 +210,10 @@ public func reversePolishNotation(expression: [Token]) -> String { tokenStack.push(token) } } - + while tokenStack.count > 0 { reversePolishNotation.append(tokenStack.pop()!) } - + return reversePolishNotation.map({token in token.description}).joinWithSeparator(" ") } diff --git a/Single-Source Shortest Paths (Weighted)/SSSP/BellmanFord.swift b/Single-Source Shortest Paths (Weighted)/SSSP/BellmanFord.swift index 4c58e4d90..e2114c963 100644 --- a/Single-Source Shortest Paths (Weighted)/SSSP/BellmanFord.swift +++ b/Single-Source Shortest Paths (Weighted)/SSSP/BellmanFord.swift @@ -13,18 +13,22 @@ public struct BellmanFord { } /** - Encapsulation of the Bellman-Ford Single-Source Shortest Paths algorithm, which operates on a general directed graph that may contain negative edge weights. - + Encapsulation of the Bellman-Ford Single-Source Shortest Paths algorithm, + which operates on a general directed graph that may contain negative edge weights. + - note: In all complexity bounds, `V` is the number of vertices in the graph, and `E` is the number of edges. */ extension BellmanFord: SSSPAlgorithm { /** - Compute the shortest path from `source` to each other vertex in `graph`, if such paths exist. Also report negative weight cycles reachable from `source`, which are cycles whose sum of edge weights is negative. + Compute the shortest path from `source` to each other vertex in `graph`, + if such paths exist. Also report negative weight cycles reachable from `source`, + which are cycles whose sum of edge weights is negative. - precondition: `graph` must have no negative weight cycles - complexity: `O(VE)` time, `Θ(V)` space - - returns a `BellmanFordResult` struct which can be queried for shortest paths and their total weights, or `nil` if a negative weight cycle exists + - returns a `BellmanFordResult` struct which can be queried for + shortest paths and their total weights, or `nil` if a negative weight cycle exists */ public static func apply(graph: AbstractGraph, source: Vertex) -> BellmanFordResult? { let vertices = graph.vertices @@ -53,7 +57,9 @@ extension BellmanFord: SSSPAlgorithm { } // check for negative weight cycles reachable from the source vertex - // TODO: modify to incorporate solution to 24.1-4, pg 654, to set the weight of a path containing a negative weight cycle to -∞, instead of returning nil for the entire result + // TO DO: modify to incorporate solution to 24.1-4, pg 654, to set the + // weight of a path containing a negative weight cycle to -∞, + // instead of returning nil for the entire result for edge in edges { if weights[edge.to.index] > weights[edge.from.index] + edge.weight! { return nil @@ -66,9 +72,11 @@ extension BellmanFord: SSSPAlgorithm { } /** - `BellmanFordResult` encapsulates the result of the computation, namely the minimized distances, and the predecessor indices. + `BellmanFordResult` encapsulates the result of the computation, + namely the minimized distances, and the predecessor indices. - It conforms to the `SSSPResult` procotol which provides methods to retrieve distances and paths between given pairs of start and end nodes. + It conforms to the `SSSPResult` procotol which provides methods to + retrieve distances and paths between given pairs of start and end nodes. */ public struct BellmanFordResult { @@ -80,7 +88,8 @@ public struct BellmanFordResult { extension BellmanFordResult: SSSPResult { /** - - returns: the total weight of the path from the source vertex to a destination. This value is the minimal connected weight between the two vertices, or `nil` if no path exists + - returns: the total weight of the path from the source vertex to a destination. + This value is the minimal connected weight between the two vertices, or `nil` if no path exists - complexity: `Θ(1)` time/space */ public func distance(to: Vertex) -> Double? { @@ -94,7 +103,8 @@ extension BellmanFordResult: SSSPResult { } /** - - returns: the reconstructed path from the source vertex to a destination, as an array containing the data property of each vertex, or `nil` if no path exists + - returns: the reconstructed path from the source vertex to a destination, + as an array containing the data property of each vertex, or `nil` if no path exists - complexity: `Θ(V)` time, `Θ(V^2)` space */ public func path(to: Vertex, inGraph graph: AbstractGraph) -> [T]? { @@ -105,7 +115,7 @@ extension BellmanFordResult: SSSPResult { guard let path = recursePath(to, inGraph: graph, path: [to]) else { return nil } - + return path.map() { vertex in return vertex.data } @@ -114,7 +124,7 @@ extension BellmanFordResult: SSSPResult { /** The recursive component to rebuilding the shortest path between two vertices using predecessors. - - returns: the list of predecessors discovered so far, or `nil` if the next vertex has no predecessor + - returns: the list of predecessors discovered so far, or `nil` if the next vertex has no predecessor */ private func recursePath(to: Vertex, inGraph graph: AbstractGraph, path: [Vertex]) -> [Vertex]? { guard let predecessorIdx = predecessors[to.index] else { diff --git a/Single-Source Shortest Paths (Weighted)/SSSP/SSSP.swift b/Single-Source Shortest Paths (Weighted)/SSSP/SSSP.swift index 3d50731ca..8e3afc40a 100644 --- a/Single-Source Shortest Paths (Weighted)/SSSP/SSSP.swift +++ b/Single-Source Shortest Paths (Weighted)/SSSP/SSSP.swift @@ -9,7 +9,9 @@ import Foundation import Graph /** - `SSSPAlgorithm` is a protocol for encapsulating a Single-Source Shortest Path algorithm. It provides a single function `apply` that accepts a subclass of `AbstractGraph` and returns an object conforming to `SSSPResult`. + `SSSPAlgorithm` is a protocol for encapsulating a Single-Source Shortest Path algorithm. + It provides a single function `apply` that accepts a subclass of `AbstractGraph` and returns + an object conforming to `SSSPResult`. */ protocol SSSPAlgorithm { @@ -21,7 +23,9 @@ protocol SSSPAlgorithm { } /** - `SSSPResult` is a protocol defining functions `distance` and `path`, allowing for opaque queries into the actual data structures that represent the SSSP solution according to the algorithm used. + `SSSPResult` is a protocol defining functions `distance` and `path`, allowing + for opaque queries into the actual data structures that represent the SSSP + solution according to the algorithm used. */ protocol SSSPResult { diff --git a/Stack/Stack.playground/Contents.swift b/Stack/Stack.playground/Contents.swift index 51567669c..242dbf518 100644 --- a/Stack/Stack.playground/Contents.swift +++ b/Stack/Stack.playground/Contents.swift @@ -1,11 +1,11 @@ /* Stack - A stack is like an array but with limited functionality. You can only push + A stack is like an array but with limited functionality. You can only push to add a new element to the top of the stack, pop to remove the element from the top, and peek at the top element without popping it off. - A stack gives you a LIFO or last-in first-out order. The element you pushed + A stack gives you a LIFO or last-in first-out order. The element you pushed last is the first one to come off with the next pop. Push and pop are O(1) operations. @@ -13,19 +13,19 @@ public struct Stack { private var array = [T]() - + public var count: Int { return array.count } - + public var isEmpty: Bool { return array.isEmpty } - + public mutating func push(element: T) { array.append(element) } - + public mutating func pop() -> T? { if isEmpty { return nil @@ -33,7 +33,7 @@ public struct Stack { return array.removeLast() } } - + public func peek() -> T? { return array.last } diff --git a/Ternary Search Tree/TST.playground/Contents.swift b/Ternary Search Tree/TST.playground/Contents.swift index cc2225057..6b1fe3eaa 100644 --- a/Ternary Search Tree/TST.playground/Contents.swift +++ b/Ternary Search Tree/TST.playground/Contents.swift @@ -11,24 +11,24 @@ let allowedChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567 func randomAlphaNumericString(length: Int) -> String { let allowedCharsCount = UInt32(allowedChars.characters.count) var randomString = "" - + for _ in (0.. { var key: Character var data: Element? var hasData: Bool - + //Children var left: TSTNode?, right: TSTNode?, middle: TSTNode? - - + + init(key: Character, data: Element?) { self.key = key self.data = data self.hasData = (data != nil) } - - init(key:Character) { + + init(key: Character) { self.key = key self.data = nil self.hasData = false } - -} \ No newline at end of file + +} diff --git a/Ternary Search Tree/TST.playground/Sources/TernarySearchTree.swift b/Ternary Search Tree/TST.playground/Sources/TernarySearchTree.swift index 1bbc1c390..43c4453e3 100644 --- a/Ternary Search Tree/TST.playground/Sources/TernarySearchTree.swift +++ b/Ternary Search Tree/TST.playground/Sources/TernarySearchTree.swift @@ -1,6 +1,6 @@ // // TernarySearchTree.swift -// +// // // Created by Siddharth Atre on 3/15/16. // @@ -10,44 +10,44 @@ import Foundation public class TernarySearchTree { - + var root: TSTNode? - + public init() {} - + //MARK: - Insertion - - public func insert(data:Element, withKey key: String) -> Bool{ + + public func insert(data: Element, withKey key: String) -> Bool { return insertNode(&root, withData: data, andKey: key, atIndex: 0) - + } - + private func insertNode(inout aNode: TSTNode?, withData data: Element, andKey key: String, atIndex charIndex: Int) -> Bool { - + //sanity check. - if(key.characters.count == 0) { + if key.characters.count == 0 { return false } - + //create a new node if necessary. - if(aNode == nil) { + if aNode == nil { let index = key.startIndex.advancedBy(charIndex) aNode = TSTNode(key: key[index]) } - + //if current char is less than the current node's char, go left let index = key.startIndex.advancedBy(charIndex) - if(key[index] < aNode!.key) { + if key[index] < aNode!.key { return insertNode(&aNode!.left, withData: data, andKey: key, atIndex: charIndex) } //if it's greater, go right. - else if(key[index] > aNode!.key) { + else if key[index] > aNode!.key { return insertNode(&aNode!.right, withData: data, andKey: key, atIndex: charIndex) } //current char is equal to the current nodes, go middle else { //continue down the middle. - if(charIndex + 1 < key.characters.count) { + if charIndex + 1 < key.characters.count { return insertNode(&aNode!.middle, withData: data, andKey: key, atIndex: charIndex + 1) } //otherwise, all done. @@ -58,23 +58,23 @@ public class TernarySearchTree { } } } - - + + //MARK: - Finding - - - public func find(key:String) -> Element? { + + + public func find(key: String) -> Element? { return findNode(root, withKey: key, atIndex: 0) } - - + + private func findNode(aNode: TSTNode?, withKey key: String, atIndex charIndex: Int) -> Element? { - + //Given key does not exist in tree. if aNode == nil { return nil } - + let index = key.startIndex.advancedBy(charIndex) //go left if key[index] < aNode!.key { @@ -93,4 +93,4 @@ public class TernarySearchTree { } } } -} \ No newline at end of file +} diff --git a/Ternary Search Tree/TST.playground/playground.xcworkspace/contents.xcworkspacedata b/Ternary Search Tree/TST.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Ternary Search Tree/TST.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Ternary Search Tree/TST.playground/timeline.xctimeline b/Ternary Search Tree/TST.playground/timeline.xctimeline deleted file mode 100644 index bf468afec..000000000 --- a/Ternary Search Tree/TST.playground/timeline.xctimeline +++ /dev/null @@ -1,6 +0,0 @@ - - - - - diff --git a/Ternary Search Tree/TSTNode.swift b/Ternary Search Tree/TSTNode.swift index 95376591f..16f1ba2cf 100644 --- a/Ternary Search Tree/TSTNode.swift +++ b/Ternary Search Tree/TSTNode.swift @@ -1,6 +1,6 @@ // // TSTNode.swift -// +// // // Created by Siddharth Atre on 3/15/16. // @@ -9,27 +9,27 @@ import Foundation /** - This class represents a node in the Ternary Search Tree. - A node has two main data members, the key and the data. + This class represents a node in the Ternary Search Tree. + A node has two main data members, the key and the data. All nodes in a TST must have keys, but only some will have data. This can be seen in the way the data variable is of Optional type. */ class TSTNode { //Member properties of a particular node. - + /// The key that identifies this node. var key: Character /// The data stored in this node. May be `nil` var data: Element? /// Boolean flag to depict whether this node holds data or not. var hasData: Bool - + /// The children of this node var left: TSTNode?, right: TSTNode?, middle: TSTNode? - + /** Initializer for key and/or data - + - parameter key: The key to set for this node. - parameter data: The optional data to set in this node. */ @@ -38,16 +38,16 @@ class TSTNode { self.data = data self.hasData = (data != nil) } - + /** Make a node that only has a key - + - parameter key: The key to ascribe to this node. */ - init(key:Character) { + init(key: Character) { self.key = key self.data = nil self.hasData = false } - -} \ No newline at end of file + +} diff --git a/Ternary Search Tree/TernarySearchTree.swift b/Ternary Search Tree/TernarySearchTree.swift index 5187e1e78..2f143bead 100644 --- a/Ternary Search Tree/TernarySearchTree.swift +++ b/Ternary Search Tree/TernarySearchTree.swift @@ -1,6 +1,6 @@ // // TernarySearchTree.swift -// +// // // Created by Siddharth Atre on 3/15/16. // @@ -14,65 +14,65 @@ Data structure uses key-value mappings. Keys are strings used to map to any data See README for more information. */ public class TernarySearchTree { - + /// A reference to the root node of this TST var root: TSTNode? - + /** Standard initializer */ public init() {} - + //MARK: - Insertion - + /** Public insertion method. - + - parameter data: The value to store in this TST. - parameter key: The key to associate with this value. - + - returns: Value indicating insertion success/failure. */ - public func insert(data:Element, withKey key: String) -> Bool{ + public func insert(data: Element, withKey key: String) -> Bool { return insertNode(&root, withData: data, andKey: key, atIndex: 0) } - + /** Helper method for insertion that does the actual legwork. Insertion is performed recursively. - + - parameter aNode: The current node to insert below. - parameter data: The data being inserted. - parameter key: The key being used to find an insertion location for the given data - parameter charIndex: The index of the character in the key string to use to for the next node. - + - returns: Value indicating insertion success/failure. */ private func insertNode(inout aNode: TSTNode?, withData data: Element, andKey key: String, atIndex charIndex: Int) -> Bool { - + //sanity check. - if(key.characters.count == 0) { + if key.characters.count == 0 { return false } - + //create a new node if necessary. - if(aNode == nil) { + if aNode == nil { let index = key.startIndex.advancedBy(charIndex) aNode = TSTNode(key: key[index]) } - + //if current char is less than the current node's char, go left let index = key.startIndex.advancedBy(charIndex) - if(key[index] < aNode!.key) { + if key[index] < aNode!.key { return insertNode(&aNode!.left, withData: data, andKey: key, atIndex: charIndex) } //if it's greater, go right. - else if(key[index] > aNode!.key) { + else if key[index] > aNode!.key { return insertNode(&aNode!.right, withData: data, andKey: key, atIndex: charIndex) } //current char is equal to the current nodes, go middle else { //continue down the middle. - if(charIndex + 1 < key.characters.count) { + if charIndex + 1 < key.characters.count { return insertNode(&aNode!.middle, withData: data, andKey: key, atIndex: charIndex + 1) } //otherwise, all done. @@ -83,37 +83,37 @@ public class TernarySearchTree { } } } - - + + //MARK: - Finding - + /** Public find method. - + - parameter key: Search for an object associated with this key. - + - returns: The element, if found. Otherwise, nil. */ - public func find(key:String) -> Element? { + public func find(key: String) -> Element? { return findNode(root, withKey: key, atIndex: 0) } - + /** Helper method that performs actual legwork of find operation. Implemented recursively. - + - parameter aNode: The current node being evaluated. - parameter key: The key being used for the search. - parameter charIndex: The index of the current char in the search key - + - returns: The element, if found. Nil otherwise. */ private func findNode(aNode: TSTNode?, withKey key: String, atIndex charIndex: Int) -> Element? { - + //Given key does not exist in tree. if aNode == nil { return nil } - + let index = key.startIndex.advancedBy(charIndex) //go left if key[index] < aNode!.key { @@ -132,4 +132,4 @@ public class TernarySearchTree { } } } -} \ No newline at end of file +} diff --git a/Threaded Binary Tree/ThreadedBinaryTree.swift b/Threaded Binary Tree/ThreadedBinaryTree.swift index a046d4378..98a23d013 100644 --- a/Threaded Binary Tree/ThreadedBinaryTree.swift +++ b/Threaded Binary Tree/ThreadedBinaryTree.swift @@ -4,7 +4,7 @@ Each node stores a value and two children. The left child contains a smaller value; the right a larger (or equal) value. - + Any nodes that lack either a left or right child instead keep track of their in-order predecessor and/or successor. @@ -82,7 +82,7 @@ extension ThreadedBinaryTree { public func insert(value: T) { insert(value, parent: self) } - + private func insert(value: T, parent: ThreadedBinaryTree) { if value < self.value { if let left = left { @@ -242,7 +242,7 @@ extension ThreadedBinaryTree { } } */ - + public func contains(value: T) -> Bool { return search(value) != nil } @@ -257,7 +257,7 @@ extension ThreadedBinaryTree { } return node } - + /* Returns the rightmost descendent. O(h) time. */ @@ -268,7 +268,7 @@ extension ThreadedBinaryTree { } return node } - + /* Calculates the depth of this node, i.e. the distance to the root. Takes O(h) time. @@ -282,7 +282,7 @@ extension ThreadedBinaryTree { } return edges } - + /* Calculates the height of this node, i.e. the distance to the lowest leaf. Since this looks at all children of this node, performance is O(n). @@ -346,13 +346,13 @@ extension ThreadedBinaryTree { } } } - + public func traversePreOrder(@noescape visit: T -> Void) { visit(value) left?.traversePreOrder(visit) right?.traversePreOrder(visit) } - + public func traversePostOrder(@noescape visit: T -> Void) { left?.traversePostOrder(visit) right?.traversePostOrder(visit) diff --git a/Threaded Binary Tree/ThreadedBinaryTreeTests.swift b/Threaded Binary Tree/ThreadedBinaryTreeTests.swift index 550df424d..514c0db63 100644 --- a/Threaded Binary Tree/ThreadedBinaryTreeTests.swift +++ b/Threaded Binary Tree/ThreadedBinaryTreeTests.swift @@ -8,7 +8,7 @@ // Simple little debug function to make testing output pretty func check(tree: ThreadedBinaryTree?) { if let tree = tree { - print("\(tree.count) Total Nodes:"); + print("\(tree.count) Total Nodes:") print(tree) print("Debug Info:") print(tree.debugDescription) diff --git a/Topological Sort/Graph.swift b/Topological Sort/Graph.swift index 5db37ad45..173676537 100644 --- a/Topological Sort/Graph.swift +++ b/Topological Sort/Graph.swift @@ -1,26 +1,26 @@ public class Graph: CustomStringConvertible { public typealias Node = String - + private(set) public var adjacencyLists: [Node : [Node]] public init() { adjacencyLists = [Node : [Node]]() } - + public func addNode(value: Node) -> Node { adjacencyLists[value] = [] return value } - + public func addEdge(fromNode from: Node, toNode to: Node) -> Bool { adjacencyLists[from]?.append(to) return adjacencyLists[from] != nil ? true : false } - + public var description: String { return adjacencyLists.description } - + public func adjacencyList(forNode node: Node) -> [Node]? { for (key, adjacencyList) in adjacencyLists { if key == node { @@ -36,11 +36,11 @@ extension Graph { func calculateInDegreeOfNodes() -> [Node : InDegree] { var inDegrees = [Node : InDegree]() - + for (node, _) in adjacencyLists { inDegrees[node] = 0 } - + for (_, adjacencyList) in adjacencyLists { for nodeInList in adjacencyList { inDegrees[nodeInList] = (inDegrees[nodeInList] ?? 0) + 1 diff --git a/Topological Sort/Tests/TopologicalSortTests.swift b/Topological Sort/Tests/TopologicalSortTests.swift index 441422703..5acdcf2ae 100644 --- a/Topological Sort/Tests/TopologicalSortTests.swift +++ b/Topological Sort/Tests/TopologicalSortTests.swift @@ -17,7 +17,7 @@ extension Graph { } class TopologicalSort: XCTestCase { - + // The topological sort is valid if a node does not have any of its // predecessors in its adjacency list. func checkIsValidTopologicalSort(graph: Graph, _ a: [Graph.Node]) { @@ -29,10 +29,10 @@ class TopologicalSort: XCTestCase { } } } - + func testTopologicalSort() { let graph = Graph() - + let node5 = graph.addNode("5") let node7 = graph.addNode("7") let node3 = graph.addNode("3") @@ -41,7 +41,7 @@ class TopologicalSort: XCTestCase { let node2 = graph.addNode("2") let node9 = graph.addNode("9") let node10 = graph.addNode("10") - + graph.addEdge(fromNode: node5, toNode: node11) graph.addEdge(fromNode: node7, toNode: node11) graph.addEdge(fromNode: node7, toNode: node8) diff --git a/Topological Sort/Topological Sort.playground/Sources/Graph.swift b/Topological Sort/Topological Sort.playground/Sources/Graph.swift index 7fbadb6ce..173676537 100644 --- a/Topological Sort/Topological Sort.playground/Sources/Graph.swift +++ b/Topological Sort/Topological Sort.playground/Sources/Graph.swift @@ -1,26 +1,26 @@ public class Graph: CustomStringConvertible { public typealias Node = String - + private(set) public var adjacencyLists: [Node : [Node]] - + public init() { adjacencyLists = [Node : [Node]]() } - + public func addNode(value: Node) -> Node { adjacencyLists[value] = [] return value } - + public func addEdge(fromNode from: Node, toNode to: Node) -> Bool { adjacencyLists[from]?.append(to) return adjacencyLists[from] != nil ? true : false } - + public var description: String { return adjacencyLists.description } - + public func adjacencyList(forNode node: Node) -> [Node]? { for (key, adjacencyList) in adjacencyLists { if key == node { @@ -36,11 +36,11 @@ extension Graph { func calculateInDegreeOfNodes() -> [Node : InDegree] { var inDegrees = [Node : InDegree]() - + for (node, _) in adjacencyLists { inDegrees[node] = 0 } - + for (_, adjacencyList) in adjacencyLists { for nodeInList in adjacencyList { inDegrees[nodeInList] = (inDegrees[nodeInList] ?? 0) + 1 diff --git a/Topological Sort/Topological Sort.playground/Sources/TopologicalSort1.swift b/Topological Sort/Topological Sort.playground/Sources/TopologicalSort1.swift index a7be2803c..7f1aca5e7 100644 --- a/Topological Sort/Topological Sort.playground/Sources/TopologicalSort1.swift +++ b/Topological Sort/Topological Sort.playground/Sources/TopologicalSort1.swift @@ -1,7 +1,7 @@ extension Graph { private func depthFirstSearch(source: Node, inout visited: [Node : Bool]) -> [Node] { var result = [Node]() - + if let adjacencyList = adjacencyList(forNode: source) { for nodeInAdjacencyList in adjacencyList { if let seen = visited[nodeInAdjacencyList] where !seen { @@ -9,30 +9,30 @@ extension Graph { } } } - + visited[source] = true return [source] + result } /* Topological sort using depth-first search. */ public func topologicalSort() -> [Node] { - + let startNodes = calculateInDegreeOfNodes().filter({ _, indegree in return indegree == 0 }).map({ node, indegree in return node }) - + var visited = [Node : Bool]() for (node, _) in adjacencyLists { visited[node] = false } - + var result = [Node]() for startNode in startNodes { result = depthFirstSearch(startNode, visited: &visited) + result } - + return result } } diff --git a/Topological Sort/Topological Sort.playground/Sources/TopologicalSort3.swift b/Topological Sort/Topological Sort.playground/Sources/TopologicalSort3.swift index 24a6189fa..cdc479b41 100644 --- a/Topological Sort/Topological Sort.playground/Sources/TopologicalSort3.swift +++ b/Topological Sort/Topological Sort.playground/Sources/TopologicalSort3.swift @@ -6,7 +6,7 @@ extension Graph { public func topologicalSortAlternative() -> [Node] { var stack = [Node]() - + var visited = [Node: Bool]() for (node, _) in adjacencyLists { visited[node] = false diff --git a/Topological Sort/TopologicalSort1.swift b/Topological Sort/TopologicalSort1.swift index e134bf9ce..7f1aca5e7 100644 --- a/Topological Sort/TopologicalSort1.swift +++ b/Topological Sort/TopologicalSort1.swift @@ -1,7 +1,7 @@ extension Graph { private func depthFirstSearch(source: Node, inout visited: [Node : Bool]) -> [Node] { var result = [Node]() - + if let adjacencyList = adjacencyList(forNode: source) { for nodeInAdjacencyList in adjacencyList { if let seen = visited[nodeInAdjacencyList] where !seen { @@ -9,30 +9,30 @@ extension Graph { } } } - + visited[source] = true return [source] + result } - + /* Topological sort using depth-first search. */ public func topologicalSort() -> [Node] { - + let startNodes = calculateInDegreeOfNodes().filter({ _, indegree in return indegree == 0 }).map({ node, indegree in return node }) - + var visited = [Node : Bool]() for (node, _) in adjacencyLists { visited[node] = false } - + var result = [Node]() for startNode in startNodes { result = depthFirstSearch(startNode, visited: &visited) + result } - + return result } } diff --git a/Topological Sort/TopologicalSort3.swift b/Topological Sort/TopologicalSort3.swift index 24a6189fa..cdc479b41 100644 --- a/Topological Sort/TopologicalSort3.swift +++ b/Topological Sort/TopologicalSort3.swift @@ -6,7 +6,7 @@ extension Graph { public func topologicalSortAlternative() -> [Node] { var stack = [Node]() - + var visited = [Node: Bool]() for (node, _) in adjacencyLists { visited[node] = false diff --git a/Treap/Treap.swift b/Treap/Treap.swift index 5413a17c2..e1d1d4892 100644 --- a/Treap/Treap.swift +++ b/Treap/Treap.swift @@ -46,7 +46,7 @@ public indirect enum Treap { return nil } } - + public func contains(key: Key) -> Bool { switch self { case .Empty: @@ -61,7 +61,7 @@ public indirect enum Treap { return false } } - + public var depth: Int { get { switch self { @@ -76,43 +76,39 @@ public indirect enum Treap { let rightDepth = right.depth return 1 + max(leftDepth, rightDepth) } - + } } - + public var count: Int { get { return Treap.countHelper(self) } } - - private static func countHelper(treap: Treap) -> Int - { - if case let .Node(_, _, _, left, right) = treap - { + + private static func countHelper(treap: Treap) -> Int { + if case let .Node(_, _, _, left, right) = treap { return countHelper(left) + 1 + countHelper(right) } - + return 0 } } internal func leftRotate(tree: Treap) -> Treap { if case let .Node(key, val, p, .Node(leftKey, leftVal, leftP, leftLeft, leftRight), right) = tree { - return .Node(key: leftKey, val: leftVal, p: leftP, left: leftLeft, right: Treap.Node(key: key, val: val, p: p, left: leftRight, right: right)) - } - else - { + return .Node(key: leftKey, val: leftVal, p: leftP, left: leftLeft, + right: Treap.Node(key: key, val: val, p: p, left: leftRight, right: right)) + } else { return .Empty } } internal func rightRotate(tree: Treap) -> Treap { if case let .Node(key, val, p, left, .Node(rightKey, rightVal, rightP, rightLeft, rightRight)) = tree { - return .Node(key: rightKey, val: rightVal, p: rightP, left: Treap.Node(key: key, val: val, p: p, left: left, right: rightLeft), right: rightRight) - } - else - { + return .Node(key: rightKey, val: rightVal, p: rightP, + left: Treap.Node(key: key, val: val, p: p, left: left, right: rightLeft), right: rightRight) + } else { return .Empty } } @@ -129,10 +125,11 @@ public extension Treap { default: // should never happen return .Empty } - + } - - private func insertAndBalance(nodeKey: Key, _ nodeVal: Element, _ nodeP: Int, _ left: Treap, _ right: Treap, _ key: Key, _ val: Element, _ p: Int) -> Treap { + + private func insertAndBalance(nodeKey: Key, _ nodeVal: Element, _ nodeP: Int, _ left: Treap, + _ right: Treap, _ key: Key, _ val: Element, _ p: Int) -> Treap { let newChild: Treap let newNode: Treap let rotate: (Treap) -> Treap @@ -140,27 +137,24 @@ public extension Treap { newChild = left.set(key, val: val, p: p) newNode = .Node(key: nodeKey, val: nodeVal, p: nodeP, left: newChild, right: right) rotate = leftRotate - } - else if key > nodeKey { + } else if key > nodeKey { newChild = right.set(key, val: val, p: p) newNode = .Node(key: nodeKey, val: nodeVal, p: nodeP, left: left, right: newChild) rotate = rightRotate - } - else { + } else { // It should be impossible to reach here newChild = .Empty newNode = .Empty return newNode } - + if case let .Node(_, _, newChildP, _, _) = newChild where newChildP < nodeP { return rotate(newNode) - } - else { + } else { return newNode } } - + internal func delete(key: Key) throws -> Treap { switch self { case .Empty: diff --git a/Treap/Treap/Treap.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Treap/Treap/Treap.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Treap/Treap/Treap.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Treap/Treap/Treap/AppDelegate.swift b/Treap/Treap/Treap/AppDelegate.swift index 1813d840b..a6a68a40c 100644 --- a/Treap/Treap/Treap/AppDelegate.swift +++ b/Treap/Treap/Treap/AppDelegate.swift @@ -41,4 +41,3 @@ class AppDelegate: NSObject, NSApplicationDelegate { } - diff --git a/Treap/Treap/TreapTests/TreapTests.swift b/Treap/Treap/TreapTests/TreapTests.swift index 496e2f940..5f43a376f 100644 --- a/Treap/Treap/TreapTests/TreapTests.swift +++ b/Treap/Treap/TreapTests/TreapTests.swift @@ -22,21 +22,23 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.*/ +// swiftlint:disable force_try + import XCTest @testable import Treap class TreapTests: XCTestCase { - + override func setUp() { super.setUp() // Put setup code here. This method is called before the invocation of each test method in the class. } - + override func tearDown() { // Put teardown code here. This method is called after the invocation of each test method in the class. super.tearDown() } - + func testSanity() { var treap = Treap.Empty treap = treap.set(5, val: "a").set(7, val: "b") @@ -62,12 +64,11 @@ class TreapTests: XCTestCase { func testFairlyBalancedCollection() { var treap = Treap() - for i in 0..<1000 - { + for i in 0..<1000 { treap[i] = Optional.None } let depth = treap.depth XCTAssert(depth > 0 && depth < 30) } - + } diff --git a/Treap/TreapMergeSplit.swift b/Treap/TreapMergeSplit.swift index 51929893b..277cb40b7 100644 --- a/Treap/TreapMergeSplit.swift +++ b/Treap/TreapMergeSplit.swift @@ -24,39 +24,32 @@ THE SOFTWARE.*/ import Foundation public extension Treap { - internal func split(key: Key) -> (left: Treap, right: Treap) - { + internal func split(key: Key) -> (left: Treap, right: Treap) { var current = self let val: Element - if let newVal = self.get(key) - { + if let newVal = self.get(key) { + // swiftlint:disable force_try current = try! current.delete(key) + // swiftlint:enable force_try val = newVal - } - else if case let .Node(_, newVal, _, _, _) = self - { + } else if case let .Node(_, newVal, _, _, _) = self { val = newVal - } - else - { + } else { fatalError("No values in treap") } - + switch self { case .Node: - if case let .Node(_, _, _, left, right) = current.set(key, val: val, p: -1) - { + if case let .Node(_, _, _, left, right) = current.set(key, val: val, p: -1) { return (left: left, right: right) - } - else - { + } else { return (left: .Empty, right: .Empty) } default: return (left: .Empty, right: .Empty) } } - + internal var leastKey: Key? { switch self { case .Empty: @@ -67,7 +60,7 @@ public extension Treap { return left.leastKey } } - + internal var mostKey: Key? { switch self { case .Empty: @@ -86,13 +79,11 @@ internal func merge(left: Treap, right: return right case (_, .Empty): return left - + case let (.Node(leftKey, leftVal, leftP, leftLeft, leftRight), .Node(rightKey, rightVal, rightP, rightLeft, rightRight)): if leftP < rightP { return .Node(key: leftKey, val: leftVal, p: leftP, left: leftLeft, right: merge(leftRight, right: right)) - } - else - { + } else { return .Node(key: rightKey, val: rightVal, p: rightP, left: merge(rightLeft, right: left), right: rightRight) } default: @@ -101,29 +92,25 @@ internal func merge(left: Treap, right: return .Empty } -extension Treap: CustomStringConvertible -{ +extension Treap: CustomStringConvertible { public var description: String { get { return Treap.descHelper(self, indent: 0) } } - - private static func descHelper(treap: Treap, indent: Int) -> String - { + + private static func descHelper(treap: Treap, indent: Int) -> String { if case let .Node(key, value, priority, left, right) = treap { var result = "" let tabs = String(count: indent, repeatedValue: Character("\t")) - + result += descHelper(left, indent: indent + 1) result += "\n" + tabs + "\(key), \(value), \(priority)\n" result += descHelper(right, indent: indent + 1) - + return result - } - else - { + } else { return "" } } -} \ No newline at end of file +} diff --git a/Tree/Tree.playground/Contents.swift b/Tree/Tree.playground/Contents.swift index 966870bdf..c8ee8fe71 100644 --- a/Tree/Tree.playground/Contents.swift +++ b/Tree/Tree.playground/Contents.swift @@ -2,14 +2,14 @@ public class TreeNode { public var value: T - + public var parent: TreeNode? public var children = [TreeNode]() public init(value: T) { self.value = value } - + public func addChild(node: TreeNode) { children.append(node) node.parent = self diff --git a/Tree/Tree.swift b/Tree/Tree.swift index 5c027141c..89f1a39da 100644 --- a/Tree/Tree.swift +++ b/Tree/Tree.swift @@ -1,13 +1,13 @@ public class TreeNode { public var value: T - + public var parent: TreeNode? public var children = [TreeNode]() public init(value: T) { self.value = value } - + public func addChild(node: TreeNode) { children.append(node) node.parent = self diff --git a/Trie/trie.swift b/Trie/trie.swift index 839c4350b..9ebfba8bc 100644 --- a/Trie/trie.swift +++ b/Trie/trie.swift @@ -52,7 +52,7 @@ public class Node { private var isAWord: Bool private var visited: Bool //only for findPrefix - init(c: String?, p: Node?){ + init(c: String?, p: Node?) { self.character = c self.children = [String:Node]() self.isAWord = false @@ -86,7 +86,7 @@ public class Node { Output: Bool Functionality: Returns true if the node is a leaf node, false otherwise */ - func isLeaf() -> Bool{ + func isLeaf() -> Bool { return self.children.count == 0 } @@ -127,7 +127,7 @@ public class Node { Output: Bool Functionality: Returns whether or not the current node marks the end of a valid word */ - func isValidWord() -> Bool{ + func isValidWord() -> Bool { return self.isAWord } @@ -194,8 +194,7 @@ public class Node { if leaf { print("\\-", terminator: "") indent += " " - } - else { + } else { print("|-", terminator: "") indent += "| " } @@ -245,7 +244,7 @@ public class Trie { Output: Trie Functionality: Merges two tries into one and returns the merged trie */ - func merge(other: Trie) -> Trie{ + func merge(other: Trie) -> Trie { let newWordList = Set(self.getWords() + other.getWords()) return Trie(wordList: newWordList) } @@ -254,7 +253,9 @@ public class Trie { Function Name: find Input: String Output: (Node?, Bool) - Functionality: Looks for a specific key and returns a tuple that has a reference to the node(if found) and true/false depending on if it was found + Functionality: Looks for a specific key and returns a tuple that + has a reference to the node(if found) and true/false + depending on if it was found */ func find(key: String) -> (node: Node?, found: Bool) { var currentNode = self.root @@ -313,7 +314,9 @@ public class Trie { Function Name: isPrefix Input: String Output: (Node?, Bool) - Functionality: returns a tuple containing a reference to the final node in the prefix (if it exists) and true/false depending on whether or not the prefix exists in the trie + Functionality: returns a tuple containing a reference to the final + node in the prefix (if it exists) and true/false + depending on whether or not the prefix exists in the trie */ func isPrefix(p: String) -> (node: Node?, found: Bool) { let prefixP = p.lowercaseString @@ -321,7 +324,7 @@ public class Trie { var currentNode = self.root for c in prefixP.characters { - if currentNode.children[String(c)] == nil{ + if currentNode.children[String(c)] == nil { return (nil, false) } @@ -339,7 +342,9 @@ public class Trie { Function Name: insert Input: String Output: (String, Bool) - Functionality: Inserts a word int othe trie. Returns a tuple containing the word attempted to be added, and true/false depending on whether or not the insertion was successful + Functionality: Inserts a word int othe trie. Returns a tuple containing + the word attempted to be added, and true/false depending on + whether or not the insertion was successful */ func insert(w: String) -> (word: String, inserted: Bool) { @@ -385,10 +390,12 @@ public class Trie { Function Name: insertWords Input: [String] Output: ([String], Bool) - Functionality: attempts to insert all words from input array. returns a tuple containing the input array and true if some of the words were succesffuly added, false if none were added + Functionality: attempts to insert all words from input array. returns a tuple + containing the input array and true if some of the words were + succesffuly added, false if none were added */ - func insertWords(wordList: [String]) -> (wordList: [String], inserted: Bool){ + func insertWords(wordList: [String]) -> (wordList: [String], inserted: Bool) { var succesful: Bool = false for word in wordList { @@ -402,9 +409,11 @@ public class Trie { Function Name: remove Input: String Output: (String, Bool) - Functionality: Removes the specified key from the trie if it exists, returns tuple containing the word attempted to be removed and true/false if the removal was succesful + Functionality: Removes the specified key from the trie if it exists, returns + tuple containing the word attempted to be removed and true/false + if the removal was succesful */ - func remove(w: String) -> (word: String, removed: Bool){ + func remove(w: String) -> (word: String, removed: Bool) { let word = w.lowercaseString if !self.contains(w) { @@ -420,7 +429,7 @@ public class Trie { currentNode.isNotWord() } else { var character = currentNode.char() - while(currentNode.numChildren() == 0 && !currentNode.isRoot()) { + while currentNode.numChildren() == 0 && !currentNode.isRoot() { currentNode = currentNode.getParent() currentNode.children[character]!.setParent(nil) currentNode.children[character]!.update(nil) @@ -432,7 +441,7 @@ public class Trie { wordCount -= 1 var index = 0 - for item in wordList{ + for item in wordList { if item == w { wordList.removeAtIndex(index) } @@ -492,7 +501,7 @@ public class Trie { Output: N/A Functionality: removes all nodes in the trie using remove as a subroutine */ - func removeAll() { + func removeAll() { for word in wordList { self.remove(word) } diff --git a/Two-Sum Problem/Solution 1/2Sum.playground/Contents.swift b/Two-Sum Problem/Solution 1/2Sum.playground/Contents.swift index 5fee2deb4..11c95b96c 100644 --- a/Two-Sum Problem/Solution 1/2Sum.playground/Contents.swift +++ b/Two-Sum Problem/Solution 1/2Sum.playground/Contents.swift @@ -2,7 +2,7 @@ func twoSumProblem(a: [Int], k: Int) -> ((Int, Int))? { var map = [Int: Int]() - + for i in 0 ..< a.count { if let newK = map[a[i]] { return (newK, i) diff --git a/Two-Sum Problem/Solution 1/2Sum.swift b/Two-Sum Problem/Solution 1/2Sum.swift index 0f438c11d..b3ef54790 100644 --- a/Two-Sum Problem/Solution 1/2Sum.swift +++ b/Two-Sum Problem/Solution 1/2Sum.swift @@ -4,12 +4,12 @@ Uses a dictionary to store differences between the target and each element. If any value in the dictionary equals an element in the array, they sum to k. - + This is an O(n) solution. */ func twoSumProblem(a: [Int], k: Int) -> ((Int, Int))? { var map = [Int: Int]() - + for i in 0 ..< a.count { if let newK = map[a[i]] { return (newK, i) diff --git a/Two-Sum Problem/Solution 2/2Sum.playground/Contents.swift b/Two-Sum Problem/Solution 2/2Sum.playground/Contents.swift index 07883e251..1d6b0a9c8 100644 --- a/Two-Sum Problem/Solution 2/2Sum.playground/Contents.swift +++ b/Two-Sum Problem/Solution 2/2Sum.playground/Contents.swift @@ -3,7 +3,7 @@ func twoSumProblem(a: [Int], k: Int) -> ((Int, Int))? { var i = 0 var j = a.count - 1 - + while i < j { let sum = a[i] + a[j] if sum == k { diff --git a/Union-Find/UnionFind.playground/Contents.swift b/Union-Find/UnionFind.playground/Contents.swift index dd57514cd..5747b15b5 100644 --- a/Union-Find/UnionFind.playground/Contents.swift +++ b/Union-Find/UnionFind.playground/Contents.swift @@ -4,13 +4,13 @@ public struct UnionFind { private var index = [T: Int]() private var parent = [Int]() private var size = [Int]() - + public mutating func addSetWith(element: T) { index[element] = parent.count parent.append(parent.count) size.append(1) } - + private mutating func setByIndex(index: Int) -> Int { if parent[index] == index { return index @@ -19,7 +19,7 @@ public struct UnionFind { return parent[index] } } - + public mutating func setOf(element: T) -> Int? { if let indexOfElement = index[element] { return setByIndex(indexOfElement) @@ -27,7 +27,7 @@ public struct UnionFind { return nil } } - + public mutating func unionSetsContaining(firstElement: T, and secondElement: T) { if let firstSet = setOf(firstElement), secondSet = setOf(secondElement) { if firstSet != secondSet { @@ -41,7 +41,7 @@ public struct UnionFind { } } } - + public mutating func inSameSet(firstElement: T, and secondElement: T) -> Bool { if let firstSet = setOf(firstElement), secondSet = setOf(secondElement) { return firstSet == secondSet @@ -114,7 +114,3 @@ print(dsuForStrings.inSameSet("border", and: "best")) print(dsuForStrings.inSameSet("amazing", and: "boy")) print(dsuForStrings.inSameSet("all", and: "border")) - - - - diff --git a/Union-Find/UnionFind.swift b/Union-Find/UnionFind.swift index f1500e6c9..4323b80d4 100644 --- a/Union-Find/UnionFind.swift +++ b/Union-Find/UnionFind.swift @@ -11,13 +11,13 @@ public struct UnionFind { private var index = [T: Int]() private var parent = [Int]() private var size = [Int]() - + public mutating func addSetWith(element: T) { index[element] = parent.count parent.append(parent.count) size.append(1) } - + private mutating func setByIndex(index: Int) -> Int { if parent[index] == index { return index @@ -26,7 +26,7 @@ public struct UnionFind { return parent[index] } } - + public mutating func setOf(element: T) -> Int? { if let indexOfElement = index[element] { return setByIndex(indexOfElement) @@ -34,7 +34,7 @@ public struct UnionFind { return nil } } - + public mutating func unionSetsContaining(firstElement: T, and secondElement: T) { if let firstSet = setOf(firstElement), secondSet = setOf(secondElement) { if firstSet != secondSet { @@ -56,4 +56,4 @@ public struct UnionFind { return false } } -} \ No newline at end of file +} From 6a8a677e5a943423f4fc60a1d6bd67ee8f25a652 Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Thu, 9 Jun 2016 00:03:57 +1200 Subject: [PATCH 0391/1679] Added instructions for running SwiftLint to the "How to Contribute" page --- How to Contribute.markdown | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/How to Contribute.markdown b/How to Contribute.markdown index dc1562327..94e69ae68 100644 --- a/How to Contribute.markdown +++ b/How to Contribute.markdown @@ -23,6 +23,15 @@ To keep this a high quality repo, please follow this process when submitting you 3. Write an explanation of how the algorithm works. Include **plenty of examples** for readers to follow along. Pictures are good. Take a look at [the explanation of quicksort](Quicksort/) to get an idea. 4. Include your name in the explanation, something like *Written by Your Name* at the end of the document. If you wrote it, you deserve the credit and fame. 5. Add a playground and/or unit tests. +6. Run [SwiftLint](https://github.com/realm/SwiftLint) + - [Install](https://github.com/realm/SwiftLint#installation) + - Open terminal and run the `swiftlint` command: + +``` +cd path/to/swift-algorithm-club +swiftlint +``` + Just so you know, I will probably edit your text and code for grammar etc, just to ensure a certain level of polish. From e90de2840daf9b77f71550dc11a0b600dd8a3756 Mon Sep 17 00:00:00 2001 From: Kevin Randrup Date: Wed, 8 Jun 2016 22:22:48 -0400 Subject: [PATCH 0392/1679] Added swift-algorithm-cllub.workspace so all projects can be viewed together. Using a workspace brings all of the projects together in a single window with all of the code highlighting, search and documentation features that Xcode brings. I found it extremely useful when viewing/comparing multiple projects. --- .../contents.xcworkspacedata | 2103 +++++++++++++++++ 1 file changed, 2103 insertions(+) create mode 100644 swift-algorithm-club.xcworkspace/contents.xcworkspacedata diff --git a/swift-algorithm-club.xcworkspace/contents.xcworkspacedata b/swift-algorithm-club.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..1ec94e727 --- /dev/null +++ b/swift-algorithm-club.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,2103 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 38d225247a7f7396ee30dbd08955db0cb8d14f59 Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Fri, 10 Jun 2016 13:40:39 +1200 Subject: [PATCH 0393/1679] Fix for #141 --- Fizz Buzz/README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Fizz Buzz/README.markdown b/Fizz Buzz/README.markdown index 0ce1e2c42..e4cf485ff 100644 --- a/Fizz Buzz/README.markdown +++ b/Fizz Buzz/README.markdown @@ -18,7 +18,7 @@ The modulus operator returns the remainder after an integer division. Here is an | Division | Division Result | Modulus | Modulus Result | | ------------- | -------------------------- | --------------- | ---------------:| -| 1 / 3 | 0 with a remainder of 3 | 1 % 3 | 3 | +| 1 / 3 | 0 with a remainder of 3 | 1 % 3 | 1 | | 5 / 3 | 1 with a remainder of 2 | 5 % 3 | 2 | | 16 / 3 | 5 with a remainder of 1 | 16 % 3 | 1 | From 8596b64870c95cd4b902c46155a2b8a096c7adef Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Sat, 11 Jun 2016 20:08:14 +1200 Subject: [PATCH 0394/1679] Changing from xcodebuild to xctool --- .travis.yml | 46 +++++++++++++++++++------------------- How to Contribute.markdown | 2 +- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/.travis.yml b/.travis.yml index b0210d197..685ad9235 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,26 +3,26 @@ osx_image: xcode7.3 script: -- xcodebuild test -project ./All-Pairs\ Shortest\ Paths/APSP/APSP.xcodeproj -scheme APSPTests -- xcodebuild test -project ./Array2D/Tests/Tests.xcodeproj -scheme Tests -- xcodebuild test -project ./AVL\ Tree/Tests/Tests.xcodeproj -scheme Tests -- xcodebuild test -project ./Binary\ Search/Tests/Tests.xcodeproj -scheme Tests -- xcodebuild test -project ./Binary\ Search\ Tree/Solution\ 1/Tests/Tests.xcodeproj -scheme Tests -- xcodebuild test -project ./Bloom\ Filter/Tests/Tests.xcodeproj -scheme Tests -- xcodebuild test -project ./Breadth-First\ Search/Tests/Tests.xcodeproj -scheme Tests -- xcodebuild test -project ./Bucket\ Sort/Tests/Tests.xcodeproj -scheme Tests -- xcodebuild test -project ./Heap/Tests/Tests.xcodeproj -scheme Tests -- xcodebuild test -project ./Heap\ Sort/Tests/Tests.xcodeproj -scheme Tests -- xcodebuild test -project ./Insertion\ Sort/Tests/Tests.xcodeproj -scheme Tests -- xcodebuild test -project ./K-Means/Tests/Tests.xcodeproj -scheme Tests -- xcodebuild test -project ./Linked\ List/Tests/Tests.xcodeproj -scheme Tests -- xcodebuild test -project ./Longest\ Common\ Subsequence/Tests/Tests.xcodeproj -scheme Tests -- xcodebuild test -project ./Priority\ Queue/Tests/Tests.xcodeproj -scheme Tests -- xcodebuild test -project ./Queue/Tests/Tests.xcodeproj -scheme Tests -- xcodebuild test -project ./Quicksort/Tests/Tests.xcodeproj -scheme Tests -- xcodebuild test -project ./Run-Length\ Encoding/Tests/Tests.xcodeproj -scheme Tests -- xcodebuild test -project ./Select\ Minimum\ Maximum/Tests/Tests.xcodeproj -scheme Tests -- xcodebuild test -project ./Selection\ Sort/Tests/Tests.xcodeproj -scheme Tests -- xcodebuild test -project ./Shell\ Sort/Tests/Tests.xcodeproj -scheme Tests -- xcodebuild test -project ./Single-Source\ Shortest\ Paths\ \(Weighted\)/SSSP.xcodeproj -scheme SSSPTests -- xcodebuild test -project ./Stack/Tests/Tests.xcodeproj -scheme Tests \ No newline at end of file +- xctool test -project ./All-Pairs\ Shortest\ Paths/APSP/APSP.xcodeproj -scheme APSPTests +- xctool test -project ./Array2D/Tests/Tests.xcodeproj -scheme Tests +- xctool test -project ./AVL\ Tree/Tests/Tests.xcodeproj -scheme Tests +- xctool test -project ./Binary\ Search/Tests/Tests.xcodeproj -scheme Tests +- xctool test -project ./Binary\ Search\ Tree/Solution\ 1/Tests/Tests.xcodeproj -scheme Tests +- xctool test -project ./Bloom\ Filter/Tests/Tests.xcodeproj -scheme Tests +- xctool test -project ./Breadth-First\ Search/Tests/Tests.xcodeproj -scheme Tests +- xctool test -project ./Bucket\ Sort/Tests/Tests.xcodeproj -scheme Tests +- xctool test -project ./Heap/Tests/Tests.xcodeproj -scheme Tests +- xctool test -project ./Heap\ Sort/Tests/Tests.xcodeproj -scheme Tests +- xctool test -project ./Insertion\ Sort/Tests/Tests.xcodeproj -scheme Tests +- xctool test -project ./K-Means/Tests/Tests.xcodeproj -scheme Tests +- xctool test -project ./Linked\ List/Tests/Tests.xcodeproj -scheme Tests +- xctool test -project ./Longest\ Common\ Subsequence/Tests/Tests.xcodeproj -scheme Tests +- xctool test -project ./Priority\ Queue/Tests/Tests.xcodeproj -scheme Tests +- xctool test -project ./Queue/Tests/Tests.xcodeproj -scheme Tests +- xctool test -project ./Quicksort/Tests/Tests.xcodeproj -scheme Tests +- xctool test -project ./Run-Length\ Encoding/Tests/Tests.xcodeproj -scheme Tests +- xctool test -project ./Select\ Minimum\ Maximum/Tests/Tests.xcodeproj -scheme Tests +- xctool test -project ./Selection\ Sort/Tests/Tests.xcodeproj -scheme Tests +- xctool test -project ./Shell\ Sort/Tests/Tests.xcodeproj -scheme Tests +- xctool test -project ./Single-Source\ Shortest\ Paths\ \(Weighted\)/SSSP.xcodeproj -scheme SSSPTests +- xctool test -project ./Stack/Tests/Tests.xcodeproj -scheme Tests diff --git a/How to Contribute.markdown b/How to Contribute.markdown index dc1562327..9aa0b07ca 100644 --- a/How to Contribute.markdown +++ b/How to Contribute.markdown @@ -31,7 +31,7 @@ For the unit tests: - Add the unit test project to `.travis.yml` so they will be run on [Travis-CI](https://travis-ci.org/raywenderlich/swift-algorithm-club). Add a line to `.travis.yml` like this: ``` -- xcodebuild test -project ./Algorithm/Tests/Tests.xcodeproj -scheme Tests +- xctool test -project ./Algorithm/Tests/Tests.xcodeproj -scheme Tests ``` - Configure the Test project's scheme to run on Travis-CI: From fa813a787ee5fa5b4f21c8c0c3acf805f01aeffa Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Sat, 11 Jun 2016 21:06:08 +1200 Subject: [PATCH 0395/1679] Configure tests projects for running for xctool --- .../xcshareddata/xcschemes/Tests.xcscheme | 34 +++++++++++++++++++ .../xcshareddata/xcschemes/APSPTests.xcscheme | 34 +++++++++++++++++++ .../xcshareddata/xcschemes/Tests.xcscheme | 34 +++++++++++++++++++ .../xcshareddata/xcschemes/Tests.xcscheme | 34 +++++++++++++++++++ .../xcshareddata/xcschemes/Tests.xcscheme | 34 +++++++++++++++++++ .../xcshareddata/xcschemes/Tests.xcscheme | 34 +++++++++++++++++++ .../xcshareddata/xcschemes/Tests.xcscheme | 34 +++++++++++++++++++ .../xcshareddata/xcschemes/Tests.xcscheme | 34 +++++++++++++++++++ .../xcshareddata/xcschemes/Tests.xcscheme | 34 +++++++++++++++++++ .../xcshareddata/xcschemes/Tests.xcscheme | 34 +++++++++++++++++++ .../xcshareddata/xcschemes/Tests.xcscheme | 34 +++++++++++++++++++ .../xcshareddata/xcschemes/Tests.xcscheme | 34 +++++++++++++++++++ .../xcshareddata/xcschemes/Tests.xcscheme | 34 +++++++++++++++++++ .../xcshareddata/xcschemes/Tests.xcscheme | 15 ++++++-- .../xcshareddata/xcschemes/Tests.xcscheme | 34 +++++++++++++++++++ .../xcshareddata/xcschemes/Tests.xcscheme | 34 +++++++++++++++++++ .../xcshareddata/xcschemes/Tests.xcscheme | 34 +++++++++++++++++++ .../xcshareddata/xcschemes/Tests.xcscheme | 34 +++++++++++++++++++ .../xcshareddata/xcschemes/Tests.xcscheme | 34 +++++++++++++++++++ .../xcshareddata/xcschemes/Tests.xcscheme | 34 +++++++++++++++++++ .../xcshareddata/xcschemes/Tests.xcscheme | 34 +++++++++++++++++++ .../xcshareddata/xcschemes/SSSPTests.xcscheme | 34 +++++++++++++++++++ .../xcshareddata/xcschemes/Tests.xcscheme | 34 +++++++++++++++++++ 23 files changed, 760 insertions(+), 3 deletions(-) diff --git a/AVL Tree/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/AVL Tree/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme index 74dd9450b..8ef8d8581 100644 --- a/AVL Tree/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme +++ b/AVL Tree/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -5,6 +5,22 @@ + + + + + + + + + + @@ -45,6 +70,15 @@ savedToolIdentifier = "" useCustomWorkingDirectory = "NO" debugDocumentVersioning = "YES"> + + + + diff --git a/All-Pairs Shortest Paths/APSP/APSP.xcodeproj/xcshareddata/xcschemes/APSPTests.xcscheme b/All-Pairs Shortest Paths/APSP/APSP.xcodeproj/xcshareddata/xcschemes/APSPTests.xcscheme index 867745024..cd141a407 100644 --- a/All-Pairs Shortest Paths/APSP/APSP.xcodeproj/xcshareddata/xcschemes/APSPTests.xcscheme +++ b/All-Pairs Shortest Paths/APSP/APSP.xcodeproj/xcshareddata/xcschemes/APSPTests.xcscheme @@ -5,6 +5,22 @@ + + + + + + + + + + @@ -45,6 +70,15 @@ savedToolIdentifier = "" useCustomWorkingDirectory = "NO" debugDocumentVersioning = "YES"> + + + + diff --git a/Array2D/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Array2D/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme index 74dd9450b..8ef8d8581 100644 --- a/Array2D/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme +++ b/Array2D/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -5,6 +5,22 @@ + + + + + + + + + + @@ -45,6 +70,15 @@ savedToolIdentifier = "" useCustomWorkingDirectory = "NO" debugDocumentVersioning = "YES"> + + + + diff --git a/Binary Search Tree/Solution 1/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Binary Search Tree/Solution 1/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme index 74dd9450b..8ef8d8581 100644 --- a/Binary Search Tree/Solution 1/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme +++ b/Binary Search Tree/Solution 1/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -5,6 +5,22 @@ + + + + + + + + + + @@ -45,6 +70,15 @@ savedToolIdentifier = "" useCustomWorkingDirectory = "NO" debugDocumentVersioning = "YES"> + + + + diff --git a/Binary Search/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Binary Search/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme index 74dd9450b..8ef8d8581 100644 --- a/Binary Search/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme +++ b/Binary Search/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -5,6 +5,22 @@ + + + + + + + + + + @@ -45,6 +70,15 @@ savedToolIdentifier = "" useCustomWorkingDirectory = "NO" debugDocumentVersioning = "YES"> + + + + diff --git a/Bloom Filter/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Bloom Filter/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme index 74dd9450b..8ef8d8581 100644 --- a/Bloom Filter/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme +++ b/Bloom Filter/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -5,6 +5,22 @@ + + + + + + + + + + @@ -45,6 +70,15 @@ savedToolIdentifier = "" useCustomWorkingDirectory = "NO" debugDocumentVersioning = "YES"> + + + + diff --git a/Breadth-First Search/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Breadth-First Search/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme index 74dd9450b..8ef8d8581 100644 --- a/Breadth-First Search/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme +++ b/Breadth-First Search/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -5,6 +5,22 @@ + + + + + + + + + + @@ -45,6 +70,15 @@ savedToolIdentifier = "" useCustomWorkingDirectory = "NO" debugDocumentVersioning = "YES"> + + + + diff --git a/Bucket Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Bucket Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme index 74dd9450b..8ef8d8581 100644 --- a/Bucket Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme +++ b/Bucket Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -5,6 +5,22 @@ + + + + + + + + + + @@ -45,6 +70,15 @@ savedToolIdentifier = "" useCustomWorkingDirectory = "NO" debugDocumentVersioning = "YES"> + + + + diff --git a/Heap Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Heap Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme index 74dd9450b..8ef8d8581 100644 --- a/Heap Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme +++ b/Heap Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -5,6 +5,22 @@ + + + + + + + + + + @@ -45,6 +70,15 @@ savedToolIdentifier = "" useCustomWorkingDirectory = "NO" debugDocumentVersioning = "YES"> + + + + diff --git a/Heap/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Heap/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme index 74dd9450b..8ef8d8581 100644 --- a/Heap/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme +++ b/Heap/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -5,6 +5,22 @@ + + + + + + + + + + @@ -45,6 +70,15 @@ savedToolIdentifier = "" useCustomWorkingDirectory = "NO" debugDocumentVersioning = "YES"> + + + + diff --git a/Insertion Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Insertion Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme index 74dd9450b..8ef8d8581 100644 --- a/Insertion Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme +++ b/Insertion Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -5,6 +5,22 @@ + + + + + + + + + + @@ -45,6 +70,15 @@ savedToolIdentifier = "" useCustomWorkingDirectory = "NO" debugDocumentVersioning = "YES"> + + + + diff --git a/K-Means/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/K-Means/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme index 81f549cef..a563876e7 100644 --- a/K-Means/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme +++ b/K-Means/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -5,6 +5,22 @@ + + + + + + + + + + @@ -45,6 +70,15 @@ savedToolIdentifier = "" useCustomWorkingDirectory = "NO" debugDocumentVersioning = "YES"> + + + + diff --git a/Linked List/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Linked List/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme index 74dd9450b..8ef8d8581 100644 --- a/Linked List/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme +++ b/Linked List/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -5,6 +5,22 @@ + + + + + + + + + + @@ -45,6 +70,15 @@ savedToolIdentifier = "" useCustomWorkingDirectory = "NO" debugDocumentVersioning = "YES"> + + + + diff --git a/Longest Common Subsequence/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Longest Common Subsequence/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme index 19caeb2ad..3d7f342b3 100644 --- a/Longest Common Subsequence/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme +++ b/Longest Common Subsequence/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -9,9 +9,9 @@ + buildForProfiling = "NO" + buildForArchiving = "NO" + buildForAnalyzing = "NO"> + + + + diff --git a/Priority Queue/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Priority Queue/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme index 74dd9450b..8ef8d8581 100644 --- a/Priority Queue/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme +++ b/Priority Queue/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -5,6 +5,22 @@ + + + + + + + + + + @@ -45,6 +70,15 @@ savedToolIdentifier = "" useCustomWorkingDirectory = "NO" debugDocumentVersioning = "YES"> + + + + diff --git a/Queue/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Queue/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme index 74dd9450b..8ef8d8581 100644 --- a/Queue/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme +++ b/Queue/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -5,6 +5,22 @@ + + + + + + + + + + @@ -45,6 +70,15 @@ savedToolIdentifier = "" useCustomWorkingDirectory = "NO" debugDocumentVersioning = "YES"> + + + + diff --git a/Quicksort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Quicksort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme index 74dd9450b..8ef8d8581 100644 --- a/Quicksort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme +++ b/Quicksort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -5,6 +5,22 @@ + + + + + + + + + + @@ -45,6 +70,15 @@ savedToolIdentifier = "" useCustomWorkingDirectory = "NO" debugDocumentVersioning = "YES"> + + + + diff --git a/Run-Length Encoding/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Run-Length Encoding/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme index 74dd9450b..8ef8d8581 100644 --- a/Run-Length Encoding/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme +++ b/Run-Length Encoding/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -5,6 +5,22 @@ + + + + + + + + + + @@ -45,6 +70,15 @@ savedToolIdentifier = "" useCustomWorkingDirectory = "NO" debugDocumentVersioning = "YES"> + + + + diff --git a/Select Minimum Maximum/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Select Minimum Maximum/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme index 74dd9450b..8ef8d8581 100644 --- a/Select Minimum Maximum/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme +++ b/Select Minimum Maximum/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -5,6 +5,22 @@ + + + + + + + + + + @@ -45,6 +70,15 @@ savedToolIdentifier = "" useCustomWorkingDirectory = "NO" debugDocumentVersioning = "YES"> + + + + diff --git a/Selection Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Selection Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme index 74dd9450b..8ef8d8581 100644 --- a/Selection Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme +++ b/Selection Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -5,6 +5,22 @@ + + + + + + + + + + @@ -45,6 +70,15 @@ savedToolIdentifier = "" useCustomWorkingDirectory = "NO" debugDocumentVersioning = "YES"> + + + + diff --git a/Shell Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Shell Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme index 74dd9450b..8ef8d8581 100644 --- a/Shell Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme +++ b/Shell Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -5,6 +5,22 @@ + + + + + + + + + + @@ -45,6 +70,15 @@ savedToolIdentifier = "" useCustomWorkingDirectory = "NO" debugDocumentVersioning = "YES"> + + + + diff --git a/Single-Source Shortest Paths (Weighted)/SSSP.xcodeproj/xcshareddata/xcschemes/SSSPTests.xcscheme b/Single-Source Shortest Paths (Weighted)/SSSP.xcodeproj/xcshareddata/xcschemes/SSSPTests.xcscheme index 38b6c1697..6efceaf20 100644 --- a/Single-Source Shortest Paths (Weighted)/SSSP.xcodeproj/xcshareddata/xcschemes/SSSPTests.xcscheme +++ b/Single-Source Shortest Paths (Weighted)/SSSP.xcodeproj/xcshareddata/xcschemes/SSSPTests.xcscheme @@ -5,6 +5,22 @@ + + + + + + + + + + @@ -45,6 +70,15 @@ savedToolIdentifier = "" useCustomWorkingDirectory = "NO" debugDocumentVersioning = "YES"> + + + + diff --git a/Stack/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Stack/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme index 74dd9450b..8ef8d8581 100644 --- a/Stack/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme +++ b/Stack/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -5,6 +5,22 @@ + + + + + + + + + + @@ -45,6 +70,15 @@ savedToolIdentifier = "" useCustomWorkingDirectory = "NO" debugDocumentVersioning = "YES"> + + + + From d8cf0504a9581e292ae9f48f6f51f7750e4ae5d0 Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Sat, 11 Jun 2016 21:21:12 +1200 Subject: [PATCH 0396/1679] Added test projects that were missing from .travis.yml --- .travis.yml | 8 ++ .../xcshareddata/xcschemes/Tests.xcscheme | 34 ++++++ .../xcschemes/GraphTests.xcscheme | 34 ++++++ .../xcshareddata/xcschemes/Tests.xcscheme | 34 ++++++ .../xcshareddata/xcschemes/Tests.xcscheme | 34 ++++++ .../xcshareddata/xcschemes/Tests.xcscheme | 34 ++++++ .../xcshareddata/xcschemes/Tests.xcscheme | 90 ++++++++++++++++ .../xcshareddata/xcschemes/Treap.xcscheme | 101 ++++++++++++++++++ 8 files changed, 369 insertions(+) create mode 100644 Treap/Treap/Treap.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme create mode 100644 Treap/Treap/Treap.xcodeproj/xcshareddata/xcschemes/Treap.xcscheme diff --git a/.travis.yml b/.travis.yml index 685ad9235..94fdde89e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,14 +9,19 @@ script: - xctool test -project ./Binary\ Search/Tests/Tests.xcodeproj -scheme Tests - xctool test -project ./Binary\ Search\ Tree/Solution\ 1/Tests/Tests.xcodeproj -scheme Tests - xctool test -project ./Bloom\ Filter/Tests/Tests.xcodeproj -scheme Tests +- xctool test -project ./Bounded\ Priority\ Queue/Tests/Tests.xcodeproj -scheme Tests - xctool test -project ./Breadth-First\ Search/Tests/Tests.xcodeproj -scheme Tests - xctool test -project ./Bucket\ Sort/Tests/Tests.xcodeproj -scheme Tests +- xctool test -project ./Counting\ Sort/Tests/Tests.xcodeproj -scheme Tests +- xctool test -project ./Depth-First Search/Tests/Tests.xcodeproj -scheme Tests +- xctool test -project ./Graph/Graph.xcodeproj -scheme GraphTests - xctool test -project ./Heap/Tests/Tests.xcodeproj -scheme Tests - xctool test -project ./Heap\ Sort/Tests/Tests.xcodeproj -scheme Tests - xctool test -project ./Insertion\ Sort/Tests/Tests.xcodeproj -scheme Tests - xctool test -project ./K-Means/Tests/Tests.xcodeproj -scheme Tests - xctool test -project ./Linked\ List/Tests/Tests.xcodeproj -scheme Tests - xctool test -project ./Longest\ Common\ Subsequence/Tests/Tests.xcodeproj -scheme Tests +- xctool test -project ./Minimum\ Spanning\ Tree\ \(Unweighted\)/Tests/Tests.xcodeproj -scheme Tests - xctool test -project ./Priority\ Queue/Tests/Tests.xcodeproj -scheme Tests - xctool test -project ./Queue/Tests/Tests.xcodeproj -scheme Tests - xctool test -project ./Quicksort/Tests/Tests.xcodeproj -scheme Tests @@ -24,5 +29,8 @@ script: - xctool test -project ./Select\ Minimum\ Maximum/Tests/Tests.xcodeproj -scheme Tests - xctool test -project ./Selection\ Sort/Tests/Tests.xcodeproj -scheme Tests - xctool test -project ./Shell\ Sort/Tests/Tests.xcodeproj -scheme Tests +- xctool test -project ./Shortest\ Path\ \(Unweighted\)/Tests/Tests.xcodeproj -scheme Tests - xctool test -project ./Single-Source\ Shortest\ Paths\ \(Weighted\)/SSSP.xcodeproj -scheme SSSPTests - xctool test -project ./Stack/Tests/Tests.xcodeproj -scheme Tests +- xctool test -project ./Topological\ Sort/Tests/Tests.xcodeproj -scheme Tests +- xctool test -project ./Treap/Treap/Treap.xcodeproj -scheme Tests diff --git a/Counting Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Counting Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme index 74dd9450b..8ef8d8581 100644 --- a/Counting Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme +++ b/Counting Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -5,6 +5,22 @@ + + + + + + + + + + @@ -45,6 +70,15 @@ savedToolIdentifier = "" useCustomWorkingDirectory = "NO" debugDocumentVersioning = "YES"> + + + + diff --git a/Graph/Graph.xcodeproj/xcshareddata/xcschemes/GraphTests.xcscheme b/Graph/Graph.xcodeproj/xcshareddata/xcschemes/GraphTests.xcscheme index 8eb3c9fdf..b5a957429 100644 --- a/Graph/Graph.xcodeproj/xcshareddata/xcschemes/GraphTests.xcscheme +++ b/Graph/Graph.xcodeproj/xcshareddata/xcschemes/GraphTests.xcscheme @@ -5,6 +5,22 @@ + + + + + + + + + + @@ -45,6 +70,15 @@ savedToolIdentifier = "" useCustomWorkingDirectory = "NO" debugDocumentVersioning = "YES"> + + + + diff --git a/Minimum Spanning Tree (Unweighted)/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Minimum Spanning Tree (Unweighted)/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme index 74dd9450b..8ef8d8581 100644 --- a/Minimum Spanning Tree (Unweighted)/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme +++ b/Minimum Spanning Tree (Unweighted)/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -5,6 +5,22 @@ + + + + + + + + + + @@ -45,6 +70,15 @@ savedToolIdentifier = "" useCustomWorkingDirectory = "NO" debugDocumentVersioning = "YES"> + + + + diff --git a/Shortest Path (Unweighted)/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Shortest Path (Unweighted)/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme index 74dd9450b..8ef8d8581 100644 --- a/Shortest Path (Unweighted)/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme +++ b/Shortest Path (Unweighted)/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -5,6 +5,22 @@ + + + + + + + + + + @@ -45,6 +70,15 @@ savedToolIdentifier = "" useCustomWorkingDirectory = "NO" debugDocumentVersioning = "YES"> + + + + diff --git a/Topological Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Topological Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme index 74dd9450b..8ef8d8581 100644 --- a/Topological Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme +++ b/Topological Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -5,6 +5,22 @@ + + + + + + + + + + @@ -45,6 +70,15 @@ savedToolIdentifier = "" useCustomWorkingDirectory = "NO" debugDocumentVersioning = "YES"> + + + + diff --git a/Treap/Treap/Treap.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Treap/Treap/Treap.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme new file mode 100644 index 000000000..3eb165e19 --- /dev/null +++ b/Treap/Treap/Treap.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -0,0 +1,90 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Treap/Treap/Treap.xcodeproj/xcshareddata/xcschemes/Treap.xcscheme b/Treap/Treap/Treap.xcodeproj/xcshareddata/xcschemes/Treap.xcscheme new file mode 100644 index 000000000..566c370e1 --- /dev/null +++ b/Treap/Treap/Treap.xcodeproj/xcshareddata/xcschemes/Treap.xcscheme @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 298ba4f7179e63da39c5b3bfef43d6bce8a415a3 Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Sat, 11 Jun 2016 21:23:09 +1200 Subject: [PATCH 0397/1679] Removing super user permission requirement to speed up build --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 94fdde89e..d56dd3cc4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,6 @@ language: objective-c osx_image: xcode7.3 +sudo: false script: From d4f5614deed539afd342180068400eb1c07c244a Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Sat, 11 Jun 2016 21:47:28 +1200 Subject: [PATCH 0398/1679] Removed treap tests as project is a cocoa application and causes Travis CI to terminate. --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index d56dd3cc4..b14f5d490 100644 --- a/.travis.yml +++ b/.travis.yml @@ -34,4 +34,3 @@ script: - xctool test -project ./Single-Source\ Shortest\ Paths\ \(Weighted\)/SSSP.xcodeproj -scheme SSSPTests - xctool test -project ./Stack/Tests/Tests.xcodeproj -scheme Tests - xctool test -project ./Topological\ Sort/Tests/Tests.xcodeproj -scheme Tests -- xctool test -project ./Treap/Treap/Treap.xcodeproj -scheme Tests From fe59cad3ed62e4f386114df984feeb0279c465da Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Sat, 11 Jun 2016 22:04:09 +1200 Subject: [PATCH 0399/1679] Missing escape character for Depth-First search --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index b14f5d490..0b14e9a40 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,7 +14,7 @@ script: - xctool test -project ./Breadth-First\ Search/Tests/Tests.xcodeproj -scheme Tests - xctool test -project ./Bucket\ Sort/Tests/Tests.xcodeproj -scheme Tests - xctool test -project ./Counting\ Sort/Tests/Tests.xcodeproj -scheme Tests -- xctool test -project ./Depth-First Search/Tests/Tests.xcodeproj -scheme Tests +- xctool test -project ./Depth-First\ Search/Tests/Tests.xcodeproj -scheme Tests - xctool test -project ./Graph/Graph.xcodeproj -scheme GraphTests - xctool test -project ./Heap/Tests/Tests.xcodeproj -scheme Tests - xctool test -project ./Heap\ Sort/Tests/Tests.xcodeproj -scheme Tests From 3d0655003c8cd97dd3eb1d6b284d6c848f685451 Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Sat, 11 Jun 2016 22:22:19 +1200 Subject: [PATCH 0400/1679] Making Depth-First search test scheme "shared" so that it will run on Travis --- .../xcshareddata/xcschemes/Tests.xcscheme | 99 +++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 Depth-First Search/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme diff --git a/Depth-First Search/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Depth-First Search/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme new file mode 100644 index 000000000..e5bd10d97 --- /dev/null +++ b/Depth-First Search/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From e38391108d765dde7be00cff881b1ce5fa50923f Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Sat, 11 Jun 2016 22:41:49 +1200 Subject: [PATCH 0401/1679] Turning off auto create schemes for depth first search --- .../xcshareddata/WorkspaceSettings.xcsettings | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 Depth-First Search/Tests/Tests.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings diff --git a/Depth-First Search/Tests/Tests.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/Depth-First Search/Tests/Tests.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 000000000..08de0be8d --- /dev/null +++ b/Depth-First Search/Tests/Tests.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded + + + From 7839c760fdd77ac964a94c1617c06c0c36a0f34a Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Sat, 11 Jun 2016 23:00:35 +1200 Subject: [PATCH 0402/1679] Turning off auto create schemes for bounded priority queue --- .../xcshareddata/WorkspaceSettings.xcsettings | 8 ++ .../xcshareddata/xcschemes/Tests.xcscheme | 90 +++++++++++++++++++ 2 files changed, 98 insertions(+) create mode 100644 Bounded Priority Queue/Tests/Tests.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings create mode 100644 Bounded Priority Queue/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme diff --git a/Bounded Priority Queue/Tests/Tests.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/Bounded Priority Queue/Tests/Tests.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 000000000..08de0be8d --- /dev/null +++ b/Bounded Priority Queue/Tests/Tests.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded + + + diff --git a/Bounded Priority Queue/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Bounded Priority Queue/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme new file mode 100644 index 000000000..0416248f1 --- /dev/null +++ b/Bounded Priority Queue/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -0,0 +1,90 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 9f62cf3d424ba1cf041bd089dfa9f91c4ddae426 Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Sun, 12 Jun 2016 15:09:59 +1200 Subject: [PATCH 0403/1679] Fix for #144 stack pop function is unnecessarily complex --- Stack/README.markdown | 6 +----- Stack/Stack.playground/Contents.swift | 6 +----- Stack/Stack.playground/timeline.xctimeline | 6 ------ Stack/Stack.swift | 8 ++------ 4 files changed, 4 insertions(+), 22 deletions(-) delete mode 100644 Stack/Stack.playground/timeline.xctimeline diff --git a/Stack/README.markdown b/Stack/README.markdown index 6e832b69b..17770643b 100644 --- a/Stack/README.markdown +++ b/Stack/README.markdown @@ -57,11 +57,7 @@ public struct Stack { } public mutating func pop() -> T? { - if isEmpty { - return nil - } else { - return array.removeLast() - } + return array.popLast() } public func peek() -> T? { diff --git a/Stack/Stack.playground/Contents.swift b/Stack/Stack.playground/Contents.swift index 51567669c..96e86e18a 100644 --- a/Stack/Stack.playground/Contents.swift +++ b/Stack/Stack.playground/Contents.swift @@ -27,11 +27,7 @@ public struct Stack { } public mutating func pop() -> T? { - if isEmpty { - return nil - } else { - return array.removeLast() - } + return array.popLast() } public func peek() -> T? { diff --git a/Stack/Stack.playground/timeline.xctimeline b/Stack/Stack.playground/timeline.xctimeline deleted file mode 100644 index bf468afec..000000000 --- a/Stack/Stack.playground/timeline.xctimeline +++ /dev/null @@ -1,6 +0,0 @@ - - - - - diff --git a/Stack/Stack.swift b/Stack/Stack.swift index 96c1ff284..454b66fa0 100644 --- a/Stack/Stack.swift +++ b/Stack/Stack.swift @@ -19,11 +19,7 @@ public struct Stack { } public mutating func pop() -> T? { - if isEmpty { - return nil - } else { - return array.removeLast() - } + return array.popLast() } public func peek() -> T? { @@ -34,7 +30,7 @@ public struct Stack { extension Stack: SequenceType { public func generate() -> AnyGenerator { var curr = self - return anyGenerator { + return AnyGenerator { _ -> T? in return curr.pop() } From 07de50d9f9ed1fa5d6e0f17b6125e9e5bc748df8 Mon Sep 17 00:00:00 2001 From: "Michael C. Rael" Date: Sun, 12 Jun 2016 09:52:39 -0600 Subject: [PATCH 0404/1679] Added Greedy Set Cover algorithm (unweighted) as extension to Set. --- SetCover.swift | 33 +++++++++++++++++++ .../contents.xcworkspacedata | 7 ++++ 2 files changed, 40 insertions(+) create mode 100644 SetCover.swift diff --git a/SetCover.swift b/SetCover.swift new file mode 100644 index 000000000..3a61140a8 --- /dev/null +++ b/SetCover.swift @@ -0,0 +1,33 @@ +extension Set { + func cover(from array: Array>) -> Array>? { + var result: [Set]? = [Set]() + var remainingSet = self + + func largestIntersectingSet() -> Set? { + var largestIntersectionLength = 0 + var largestSet: Set? + + for set in array { + let intersectionLength = remainingSet.intersect(set).count + if intersectionLength > largestIntersectionLength { + largestIntersectionLength = intersectionLength + largestSet = set + } + } + + return largestSet + } + + while remainingSet.count != 0 { + guard let largestSet = largestIntersectingSet() else { break } + result!.append(largestSet) + remainingSet = remainingSet.subtract(largestSet) + } + + if remainingSet.count != 0 || self.count == 0 { + result = nil + } + + return result + } +} \ No newline at end of file diff --git a/swift-algorithm-club.xcworkspace/contents.xcworkspacedata b/swift-algorithm-club.xcworkspace/contents.xcworkspacedata index 1ec94e727..1fdf194f5 100644 --- a/swift-algorithm-club.xcworkspace/contents.xcworkspacedata +++ b/swift-algorithm-club.xcworkspace/contents.xcworkspacedata @@ -1628,6 +1628,13 @@ + + + + From 9c0c08382dfd5da8cbe7f4a7abdb6a04db415fb6 Mon Sep 17 00:00:00 2001 From: "Michael C. Rael" Date: Sun, 12 Jun 2016 10:08:12 -0600 Subject: [PATCH 0405/1679] Added playground, separating algorthm source from playground source. --- SetCover.playground/Contents.swift | 31 +++++++++++++ .../Sources/RandomArrayOfSets.swift | 43 +++++++++++++++++++ SetCover.playground/Sources/SetCover.swift | 33 ++++++++++++++ SetCover.playground/contents.xcplayground | 4 ++ .../contents.xcworkspacedata | 3 ++ 5 files changed, 114 insertions(+) create mode 100644 SetCover.playground/Contents.swift create mode 100644 SetCover.playground/Sources/RandomArrayOfSets.swift create mode 100644 SetCover.playground/Sources/SetCover.swift create mode 100644 SetCover.playground/contents.xcplayground diff --git a/SetCover.playground/Contents.swift b/SetCover.playground/Contents.swift new file mode 100644 index 000000000..3822f16e3 --- /dev/null +++ b/SetCover.playground/Contents.swift @@ -0,0 +1,31 @@ +let universe1 = Set(1...7) +let array1 = randomArrayOfSets(covering: universe1) +let cover1 = universe1.cover(from: array1) + +let universe2 = Set(1...10) +let array2: Array> = [[1,2,3,4,5,6,7], [8,9]] +let cover2 = universe2.cover(from: array2) + +let universe3 = Set(["tall", "heavy"]) +let array3: Array> = [["tall", "light"], ["short", "heavy"], ["tall", "heavy", "young"]] +let cover3 = universe3.cover(from: array3) + +let universe4 = Set(["tall", "heavy", "green"]) +let cover4 = universe4.cover(from: array3) + +let universe5: Set = [16, 32, 64] +let array5: Array> = [[16,17,18], [16,32,128], [1,2,3], [32,64,128]] +let cover5 = universe5.cover(from: array5) + +let universe6: Set = [24, 89, 132, 90, 22] +let array6 = randomArrayOfSets(covering: universe6) +let cover6 = universe6.cover(from: array6) + +let universe7: Set = ["fast", "cheap", "good"] +let array7 = randomArrayOfSets(covering: universe7, minArraySizeFactor: 20.0, maxSetSizeFactor: 0.7) +let cover7 = universe7.cover(from: array7) + +let emptySet = Set() +let coverTest1 = emptySet.cover(from: array1) +let coverTest2 = universe1.cover(from: Array>()) +let coverTest3 = emptySet.cover(from: Array>()) \ No newline at end of file diff --git a/SetCover.playground/Sources/RandomArrayOfSets.swift b/SetCover.playground/Sources/RandomArrayOfSets.swift new file mode 100644 index 000000000..301fbf5f2 --- /dev/null +++ b/SetCover.playground/Sources/RandomArrayOfSets.swift @@ -0,0 +1,43 @@ +import Foundation + +public func randomArrayOfSets(covering universe: Set, + minArraySizeFactor: Double = 0.8, + maxSetSizeFactor: Double = 0.6) -> Array> { + var result = [Set]() + var ongoingUnion = Set() + + let minArraySize = Int(Double(universe.count) * minArraySizeFactor) + var maxSetSize = Int(Double(universe.count) * maxSetSizeFactor) + if maxSetSize > universe.count { + maxSetSize = universe.count + } + + while true { + var generatedSet = Set() + let targetSetSize = Int(arc4random_uniform(UInt32(maxSetSize)) + 1) + + while true { + let randomUniverseIndex = Int(arc4random_uniform(UInt32(universe.count))) + for (setIndex, value) in universe.enumerate() { + if setIndex == randomUniverseIndex { + generatedSet.insert(value) + break + } + } + + if generatedSet.count == targetSetSize { + result.append(generatedSet) + ongoingUnion = ongoingUnion.union(generatedSet) + break + } + } + + if result.count >= minArraySize { + if ongoingUnion == universe { + break + } + } + } + + return result +} \ No newline at end of file diff --git a/SetCover.playground/Sources/SetCover.swift b/SetCover.playground/Sources/SetCover.swift new file mode 100644 index 000000000..7f4cec314 --- /dev/null +++ b/SetCover.playground/Sources/SetCover.swift @@ -0,0 +1,33 @@ +public extension Set { + func cover(from array: Array>) -> Array>? { + var result: [Set]? = [Set]() + var remainingSet = self + + func largestIntersectingSet() -> Set? { + var largestIntersectionLength = 0 + var largestSet: Set? + + for set in array { + let intersectionLength = remainingSet.intersect(set).count + if intersectionLength > largestIntersectionLength { + largestIntersectionLength = intersectionLength + largestSet = set + } + } + + return largestSet + } + + while remainingSet.count != 0 { + guard let largestSet = largestIntersectingSet() else { break } + result!.append(largestSet) + remainingSet = remainingSet.subtract(largestSet) + } + + if remainingSet.count != 0 || self.count == 0 { + result = nil + } + + return result + } +} \ No newline at end of file diff --git a/SetCover.playground/contents.xcplayground b/SetCover.playground/contents.xcplayground new file mode 100644 index 000000000..06828af92 --- /dev/null +++ b/SetCover.playground/contents.xcplayground @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/swift-algorithm-club.xcworkspace/contents.xcworkspacedata b/swift-algorithm-club.xcworkspace/contents.xcworkspacedata index 1fdf194f5..e1f4380e7 100644 --- a/swift-algorithm-club.xcworkspace/contents.xcworkspacedata +++ b/swift-algorithm-club.xcworkspace/contents.xcworkspacedata @@ -1634,6 +1634,9 @@ + + Date: Sun, 12 Jun 2016 10:21:44 -0600 Subject: [PATCH 0406/1679] Added directory for all files. --- Set Cover (Unweighted)/README.markdown | 0 .../SetCover.playground}/Contents.swift | 0 .../Sources/RandomArrayOfSets.swift | 43 +++++++++++++++++++ .../Sources/SetCover.swift | 33 ++++++++++++++ .../contents.xcplayground | 0 Set Cover (Unweighted)/SetCover.swift | 33 ++++++++++++++ .../Sources/RandomArrayOfSets.swift | 43 ------------------- SetCover.playground/Sources/SetCover.swift | 33 -------------- SetCover.swift | 33 -------------- .../contents.xcworkspacedata | 7 ++- 10 files changed, 114 insertions(+), 111 deletions(-) create mode 100644 Set Cover (Unweighted)/README.markdown rename {SetCover.playground => Set Cover (Unweighted)/SetCover.playground}/Contents.swift (100%) create mode 100644 Set Cover (Unweighted)/SetCover.playground/Sources/RandomArrayOfSets.swift create mode 100644 Set Cover (Unweighted)/SetCover.playground/Sources/SetCover.swift rename {SetCover.playground => Set Cover (Unweighted)/SetCover.playground}/contents.xcplayground (100%) create mode 100644 Set Cover (Unweighted)/SetCover.swift delete mode 100644 SetCover.playground/Sources/RandomArrayOfSets.swift delete mode 100644 SetCover.playground/Sources/SetCover.swift delete mode 100644 SetCover.swift diff --git a/Set Cover (Unweighted)/README.markdown b/Set Cover (Unweighted)/README.markdown new file mode 100644 index 000000000..e69de29bb diff --git a/SetCover.playground/Contents.swift b/Set Cover (Unweighted)/SetCover.playground/Contents.swift similarity index 100% rename from SetCover.playground/Contents.swift rename to Set Cover (Unweighted)/SetCover.playground/Contents.swift diff --git a/Set Cover (Unweighted)/SetCover.playground/Sources/RandomArrayOfSets.swift b/Set Cover (Unweighted)/SetCover.playground/Sources/RandomArrayOfSets.swift new file mode 100644 index 000000000..64253014b --- /dev/null +++ b/Set Cover (Unweighted)/SetCover.playground/Sources/RandomArrayOfSets.swift @@ -0,0 +1,43 @@ +import Foundation + +public func randomArrayOfSets(covering universe: Set, + minArraySizeFactor: Double = 0.8, + maxSetSizeFactor: Double = 0.6) -> Array> { + var result = [Set]() + var ongoingUnion = Set() + + let minArraySize = Int(Double(universe.count) * minArraySizeFactor) + var maxSetSize = Int(Double(universe.count) * maxSetSizeFactor) + if maxSetSize > universe.count { + maxSetSize = universe.count + } + + while true { + var generatedSet = Set() + let targetSetSize = Int(arc4random_uniform(UInt32(maxSetSize)) + 1) + + while true { + let randomUniverseIndex = Int(arc4random_uniform(UInt32(universe.count))) + for (setIndex, value) in universe.enumerate() { + if setIndex == randomUniverseIndex { + generatedSet.insert(value) + break + } + } + + if generatedSet.count == targetSetSize { + result.append(generatedSet) + ongoingUnion = ongoingUnion.union(generatedSet) + break + } + } + + if result.count >= minArraySize { + if ongoingUnion == universe { + break + } + } + } + + return result +} \ No newline at end of file diff --git a/Set Cover (Unweighted)/SetCover.playground/Sources/SetCover.swift b/Set Cover (Unweighted)/SetCover.playground/Sources/SetCover.swift new file mode 100644 index 000000000..8e608cb52 --- /dev/null +++ b/Set Cover (Unweighted)/SetCover.playground/Sources/SetCover.swift @@ -0,0 +1,33 @@ +public extension Set { + func cover(from array: Array>) -> Array>? { + var result: [Set]? = [Set]() + var remainingSet = self + + func largestIntersectingSet() -> Set? { + var largestIntersectionLength = 0 + var largestSet: Set? + + for set in array { + let intersectionLength = remainingSet.intersect(set).count + if intersectionLength > largestIntersectionLength { + largestIntersectionLength = intersectionLength + largestSet = set + } + } + + return largestSet + } + + while remainingSet.count != 0 { + guard let largestSet = largestIntersectingSet() else { break } + result!.append(largestSet) + remainingSet = remainingSet.subtract(largestSet) + } + + if remainingSet.count != 0 || self.count == 0 { + result = nil + } + + return result + } +} \ No newline at end of file diff --git a/SetCover.playground/contents.xcplayground b/Set Cover (Unweighted)/SetCover.playground/contents.xcplayground similarity index 100% rename from SetCover.playground/contents.xcplayground rename to Set Cover (Unweighted)/SetCover.playground/contents.xcplayground diff --git a/Set Cover (Unweighted)/SetCover.swift b/Set Cover (Unweighted)/SetCover.swift new file mode 100644 index 000000000..58ffade9d --- /dev/null +++ b/Set Cover (Unweighted)/SetCover.swift @@ -0,0 +1,33 @@ +extension Set { + func cover(from array: Array>) -> Array>? { + var result: [Set]? = [Set]() + var remainingSet = self + + func largestIntersectingSet() -> Set? { + var largestIntersectionLength = 0 + var largestSet: Set? + + for set in array { + let intersectionLength = remainingSet.intersect(set).count + if intersectionLength > largestIntersectionLength { + largestIntersectionLength = intersectionLength + largestSet = set + } + } + + return largestSet + } + + while remainingSet.count != 0 { + guard let largestSet = largestIntersectingSet() else { break } + result!.append(largestSet) + remainingSet = remainingSet.subtract(largestSet) + } + + if remainingSet.count != 0 || self.count == 0 { + result = nil + } + + return result + } +} \ No newline at end of file diff --git a/SetCover.playground/Sources/RandomArrayOfSets.swift b/SetCover.playground/Sources/RandomArrayOfSets.swift deleted file mode 100644 index 301fbf5f2..000000000 --- a/SetCover.playground/Sources/RandomArrayOfSets.swift +++ /dev/null @@ -1,43 +0,0 @@ -import Foundation - -public func randomArrayOfSets(covering universe: Set, - minArraySizeFactor: Double = 0.8, - maxSetSizeFactor: Double = 0.6) -> Array> { - var result = [Set]() - var ongoingUnion = Set() - - let minArraySize = Int(Double(universe.count) * minArraySizeFactor) - var maxSetSize = Int(Double(universe.count) * maxSetSizeFactor) - if maxSetSize > universe.count { - maxSetSize = universe.count - } - - while true { - var generatedSet = Set() - let targetSetSize = Int(arc4random_uniform(UInt32(maxSetSize)) + 1) - - while true { - let randomUniverseIndex = Int(arc4random_uniform(UInt32(universe.count))) - for (setIndex, value) in universe.enumerate() { - if setIndex == randomUniverseIndex { - generatedSet.insert(value) - break - } - } - - if generatedSet.count == targetSetSize { - result.append(generatedSet) - ongoingUnion = ongoingUnion.union(generatedSet) - break - } - } - - if result.count >= minArraySize { - if ongoingUnion == universe { - break - } - } - } - - return result -} \ No newline at end of file diff --git a/SetCover.playground/Sources/SetCover.swift b/SetCover.playground/Sources/SetCover.swift deleted file mode 100644 index 7f4cec314..000000000 --- a/SetCover.playground/Sources/SetCover.swift +++ /dev/null @@ -1,33 +0,0 @@ -public extension Set { - func cover(from array: Array>) -> Array>? { - var result: [Set]? = [Set]() - var remainingSet = self - - func largestIntersectingSet() -> Set? { - var largestIntersectionLength = 0 - var largestSet: Set? - - for set in array { - let intersectionLength = remainingSet.intersect(set).count - if intersectionLength > largestIntersectionLength { - largestIntersectionLength = intersectionLength - largestSet = set - } - } - - return largestSet - } - - while remainingSet.count != 0 { - guard let largestSet = largestIntersectingSet() else { break } - result!.append(largestSet) - remainingSet = remainingSet.subtract(largestSet) - } - - if remainingSet.count != 0 || self.count == 0 { - result = nil - } - - return result - } -} \ No newline at end of file diff --git a/SetCover.swift b/SetCover.swift deleted file mode 100644 index 3a61140a8..000000000 --- a/SetCover.swift +++ /dev/null @@ -1,33 +0,0 @@ -extension Set { - func cover(from array: Array>) -> Array>? { - var result: [Set]? = [Set]() - var remainingSet = self - - func largestIntersectingSet() -> Set? { - var largestIntersectionLength = 0 - var largestSet: Set? - - for set in array { - let intersectionLength = remainingSet.intersect(set).count - if intersectionLength > largestIntersectionLength { - largestIntersectionLength = intersectionLength - largestSet = set - } - } - - return largestSet - } - - while remainingSet.count != 0 { - guard let largestSet = largestIntersectingSet() else { break } - result!.append(largestSet) - remainingSet = remainingSet.subtract(largestSet) - } - - if remainingSet.count != 0 || self.count == 0 { - result = nil - } - - return result - } -} \ No newline at end of file diff --git a/swift-algorithm-club.xcworkspace/contents.xcworkspacedata b/swift-algorithm-club.xcworkspace/contents.xcworkspacedata index e1f4380e7..4e0f19dc2 100644 --- a/swift-algorithm-club.xcworkspace/contents.xcworkspacedata +++ b/swift-algorithm-club.xcworkspace/contents.xcworkspacedata @@ -1632,10 +1632,13 @@ location = "container:" name = "Set Cover (Unweighted)"> + location = "group:Set Cover (Unweighted)/README.markdown"> + location = "group:Set Cover (Unweighted)/SetCover.playground"> + + Date: Sun, 12 Jun 2016 10:36:12 -0600 Subject: [PATCH 0407/1679] Started work on the README file. --- Set Cover (Unweighted)/README.markdown | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Set Cover (Unweighted)/README.markdown b/Set Cover (Unweighted)/README.markdown index e69de29bb..68538cc60 100644 --- a/Set Cover (Unweighted)/README.markdown +++ b/Set Cover (Unweighted)/README.markdown @@ -0,0 +1,13 @@ +# Set Cover (Unweighted) + +A cover + +If you have a set (also called the universe in the mathematical descriptions of the problem) + +## The algorithm + +## See also + +[Set cover problem on Wikipedia](https://en.wikipedia.org/wiki/Set_cover_problem) + +*Written for Swift Algorithm Club by [Michael C. Rael](https://github.com/mrael2)* \ No newline at end of file From a573bb240c2d5e8acf90faf599c59f8def6d7461 Mon Sep 17 00:00:00 2001 From: "Michael C. Rael" Date: Sun, 12 Jun 2016 11:34:31 -0600 Subject: [PATCH 0408/1679] Work in progress on README. --- Set Cover (Unweighted)/README.markdown | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/Set Cover (Unweighted)/README.markdown b/Set Cover (Unweighted)/README.markdown index 68538cc60..48b5f3bfa 100644 --- a/Set Cover (Unweighted)/README.markdown +++ b/Set Cover (Unweighted)/README.markdown @@ -1,11 +1,25 @@ # Set Cover (Unweighted) -A cover +If you have a group of sets, this algorithm finds a subset of those sets within that group whose union will cover an initial set that you're trying to match. The initial set is also known as the universe. -If you have a set (also called the universe in the mathematical descriptions of the problem) +For example, suppose you have a universe of `{1, 5, 7}` and you want to find the sets which cover the universe within the following group of sets: + +> {8, 4, 2} +> {3, 1} +> {7, 6, 5, 4} +> {2} +> {1, 2, 3} + +You can see that the sets `{3, 1} {7, 6, 5, 4}` when unioned together will cover the universe of `{1, 5, 7}`. Yes, there may be additional elements in the sets returned by the algorithm, but every element in the universe is represented. + +If there is no cover within the group of sets, the function returns nil. For example, if your universe is `{7, 9}`, there is no combination of sets within the grouping above that will yield a cover. ## The algorithm +The Greedy Set Cover algorithm (unweighted) is provided here. It's known as greedy because it uses the largest intersecting set from the group of sets first before examining other sets in the group. + +The function (named `cover`) is provided as an extension of the Swift type `Set`. The function takes a single parameter, which is an array of sets. This array represents the group, and the set itself represents the universe. + ## See also [Set cover problem on Wikipedia](https://en.wikipedia.org/wiki/Set_cover_problem) From 0ecf394d200cd6866d8443b72d5fd16430506f1a Mon Sep 17 00:00:00 2001 From: Michal Dabrowski Date: Tue, 14 Jun 2016 20:45:43 +0200 Subject: [PATCH 0409/1679] Added, tested and implemented edges from vertex function in graph --- Graph/Graph/AdjacencyListGraph.swift | 8 +- Graph/Graph/AdjacencyMatrixGraph.swift | 15 +++- Graph/Graph/Graph.swift | 7 +- Graph/GraphTests/GraphTests.swift | 103 ++++++++++++++++++++++++- 4 files changed, 126 insertions(+), 7 deletions(-) diff --git a/Graph/Graph/AdjacencyListGraph.swift b/Graph/Graph/AdjacencyListGraph.swift index fddd04033..562a48514 100644 --- a/Graph/Graph/AdjacencyListGraph.swift +++ b/Graph/Graph/AdjacencyListGraph.swift @@ -26,11 +26,11 @@ public class AdjacencyListGraph: AbstractGrap private var adjacencyList: [EdgeList] = [] - public override init() { + public required init() { super.init() } - public override init(fromGraph graph: AbstractGraph) { + public required init(fromGraph graph: AbstractGraph) { super.init(fromGraph: graph) } @@ -107,6 +107,10 @@ public class AdjacencyListGraph: AbstractGrap return nil } + public override func edgesFrom(sourceVertex: Vertex) -> [Edge] { + return adjacencyList[sourceVertex.index].edges ?? [] + } + public override var description: String { get { var rows = [String]() diff --git a/Graph/Graph/AdjacencyMatrixGraph.swift b/Graph/Graph/AdjacencyMatrixGraph.swift index b2047797f..6b19bcfcc 100644 --- a/Graph/Graph/AdjacencyMatrixGraph.swift +++ b/Graph/Graph/AdjacencyMatrixGraph.swift @@ -14,11 +14,11 @@ public class AdjacencyMatrixGraph: AbstractGr private var adjacencyMatrix: [[Double?]] = [] private var _vertices: [Vertex] = [] - public override init() { + public required init() { super.init() } - public override init(fromGraph graph: AbstractGraph) { + public required init(fromGraph graph: AbstractGraph) { super.init(fromGraph: graph) } @@ -84,6 +84,17 @@ public class AdjacencyMatrixGraph: AbstractGr return adjacencyMatrix[sourceVertex.index][destinationVertex.index] } + public override func edgesFrom(sourceVertex: Vertex) -> [Edge] { + var outEdges = [Edge]() + let fromIndex = sourceVertex.index + for column in 0..: CustomStringConvertible { - public init() {} + public required init() {} - public init(fromGraph graph: AbstractGraph) { + public required init(fromGraph graph: AbstractGraph) { for edge in graph.edges { let from = createVertex(edge.from.data) let to = createVertex(edge.to.data) @@ -56,4 +56,7 @@ public class AbstractGraph: CustomStringConve fatalError("abstract function called") } + public func edgesFrom(sourceVertex: Vertex) -> [Edge] { + fatalError("abstract function called") + } } diff --git a/Graph/GraphTests/GraphTests.swift b/Graph/GraphTests/GraphTests.swift index e6360754e..3b9c4645c 100644 --- a/Graph/GraphTests/GraphTests.swift +++ b/Graph/GraphTests/GraphTests.swift @@ -53,5 +53,106 @@ class GraphTests: XCTestCase { XCTAssertEqual(graph.vertices.count, 1, "Graph should only contain one vertex after trying to create two vertices with identical data") } } - + + func testEdgesFromReturnsCorrectEdgeInSingleEdgeDirecedGraphWithType(graphType: AbstractGraph.Type) { + let graph = graphType.init() + + let a = graph.createVertex(1) + let b = graph.createVertex(2) + + graph.addDirectedEdge(a, to: b, withWeight: 1.0) + + let edgesFromA = graph.edgesFrom(a) + let edgesFromB = graph.edgesFrom(b) + + XCTAssertEqual(edgesFromA.count, 1) + XCTAssertEqual(edgesFromB.count, 0) + + XCTAssertEqual(edgesFromA.first?.to, b) + } + + func testEdgesFromReturnsCorrectEdgeInSingleEdgeUndirectedGraphWithType(graphType: AbstractGraph.Type) { + let graph = graphType.init() + + let a = graph.createVertex(1) + let b = graph.createVertex(2) + + graph.addUndirectedEdge((a, b), withWeight: 1.0) + + let edgesFromA = graph.edgesFrom(a) + let edgesFromB = graph.edgesFrom(b) + + XCTAssertEqual(edgesFromA.count, 1) + XCTAssertEqual(edgesFromB.count, 1) + + XCTAssertEqual(edgesFromA.first?.to, b) + XCTAssertEqual(edgesFromB.first?.to, a) + } + + func testEdgesFromReturnsNoEdgesInNoEdgeGraphWithType(graphType: AbstractGraph.Type) { + let graph = graphType.init() + + let a = graph.createVertex(1) + let b = graph.createVertex(2) + + XCTAssertEqual(graph.edgesFrom(a).count, 0) + XCTAssertEqual(graph.edgesFrom(b).count, 0) + } + + func testEdgesFromReturnsCorrectEdgesInBiggerGraphInDirectedGraphWithType(graphType: AbstractGraph.Type) { + let graph = graphType.init() + let verticesCount = 100 + var vertices: [Vertex] = [] + + for i in 0..) + } + + func testEdgesFromReturnsCorrectEdgeInSingleEdgeUndirectedMatrixGraph() { + testEdgesFromReturnsCorrectEdgeInSingleEdgeUndirectedGraphWithType(AdjacencyMatrixGraph) + } + + func testEdgesFromReturnsNoInNoEdgeMatrixGraph() { + testEdgesFromReturnsNoEdgesInNoEdgeGraphWithType(AdjacencyMatrixGraph) + } + + func testEdgesFromReturnsCorrectEdgesInBiggerGraphInDirectedMatrixGraph() { + testEdgesFromReturnsCorrectEdgesInBiggerGraphInDirectedGraphWithType(AdjacencyMatrixGraph) + } + + func testEdgesFromReturnsCorrectEdgeInSingleEdgeDirecedListGraph() { + testEdgesFromReturnsCorrectEdgeInSingleEdgeDirecedGraphWithType(AdjacencyListGraph) + } + + func testEdgesFromReturnsCorrectEdgeInSingleEdgeUndirectedListGraph() { + testEdgesFromReturnsCorrectEdgeInSingleEdgeUndirectedGraphWithType(AdjacencyListGraph) + } + + func testEdgesFromReturnsNoInNoEdgeListGraph() { + testEdgesFromReturnsNoEdgesInNoEdgeGraphWithType(AdjacencyListGraph) + } + + func testEdgesFromReturnsCorrectEdgesInBiggerGraphInDirectedListGraph() { + testEdgesFromReturnsCorrectEdgesInBiggerGraphInDirectedGraphWithType(AdjacencyListGraph) + } } From 5005c28b606b61fc26d73f03f350cd3c97e56b2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viktor=20Szil=C3=A1rd=20Viktor?= Date: Fri, 17 Jun 2016 10:39:54 +0200 Subject: [PATCH 0410/1679] Added B-Tree --- BTree/BTree.playground/Contents.swift | 10 + BTree/BTree.playground/Sources/BTree.swift | 473 ++++++++++++++++++ BTree/BTree.playground/contents.xcplayground | 4 + .../contents.xcworkspacedata | 7 + BTree/BTree.swift | 473 ++++++++++++++++++ BTree/Images/BTree20.png | Bin 0 -> 16592 bytes BTree/Images/InsertionSplit.png | Bin 0 -> 17998 bytes BTree/Images/MergingNodes.png | Bin 0 -> 8359 bytes BTree/Images/MovingKey.png | Bin 0 -> 12354 bytes BTree/Images/Node.png | Bin 0 -> 6255 bytes BTree/README.md | 172 +++++++ BTree/Tests/Tests.xcodeproj/project.pbxproj | 268 ++++++++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/xcschemes/Tests.xcscheme | 100 ++++ BTree/Tests/Tests/BTreeNodeTests.swift | 54 ++ BTree/Tests/Tests/BTreeTests.swift | 257 ++++++++++ BTree/Tests/Tests/Info.plist | 24 + 17 files changed, 1849 insertions(+) create mode 100644 BTree/BTree.playground/Contents.swift create mode 100644 BTree/BTree.playground/Sources/BTree.swift create mode 100644 BTree/BTree.playground/contents.xcplayground create mode 100644 BTree/BTree.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 BTree/BTree.swift create mode 100644 BTree/Images/BTree20.png create mode 100644 BTree/Images/InsertionSplit.png create mode 100644 BTree/Images/MergingNodes.png create mode 100644 BTree/Images/MovingKey.png create mode 100644 BTree/Images/Node.png create mode 100644 BTree/README.md create mode 100644 BTree/Tests/Tests.xcodeproj/project.pbxproj create mode 100644 BTree/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 BTree/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme create mode 100644 BTree/Tests/Tests/BTreeNodeTests.swift create mode 100644 BTree/Tests/Tests/BTreeTests.swift create mode 100644 BTree/Tests/Tests/Info.plist diff --git a/BTree/BTree.playground/Contents.swift b/BTree/BTree.playground/Contents.swift new file mode 100644 index 000000000..7d2973f77 --- /dev/null +++ b/BTree/BTree.playground/Contents.swift @@ -0,0 +1,10 @@ +//: Playground - noun: a place where people can play + +import Foundation + +let bTree = BTree(order: 1)! + +bTree.insertValue(1, forKey: 1) +bTree.insertValue(2, forKey: 2) +bTree.insertValue(3, forKey: 3) +bTree.insertValue(4, forKey: 4) diff --git a/BTree/BTree.playground/Sources/BTree.swift b/BTree/BTree.playground/Sources/BTree.swift new file mode 100644 index 000000000..16c4eabe4 --- /dev/null +++ b/BTree/BTree.playground/Sources/BTree.swift @@ -0,0 +1,473 @@ +// The MIT License (MIT) + +// Copyright (c) 2016 Viktor Szilárd Simkó (aqviktor[at]gmail.com) + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +/* + B-Tree + + A B-Tree is a self-balancing search tree, in which nodes can have more than two children. + */ + +// MARK: - BTreeNode class + +class BTreeNode { + unowned var ownerTree: BTree + + private var keys = [Key]() + var values = [Value]() + var children: [BTreeNode]? + + var isLeaf: Bool { + return children == nil + } + + var numberOfKeys: Int { + return keys.count + } + + init(ownerTree: BTree) { + self.ownerTree = ownerTree + } + + convenience init(ownerTree: BTree, keys: [Key], + values: [Value], children: [BTreeNode]? = nil) { + self.init(ownerTree: ownerTree) + self.keys += keys + self.values += values + self.children = children + } +} + +// MARK: BTreeNode extesnion: Searching + +extension BTreeNode { + func valueForKey(key: Key) -> Value? { + var index = keys.startIndex + + while index.successor() < keys.endIndex && keys[index] < key { + index = index.successor() + } + + if key == keys[index] { + return values[index] + } else if key < keys[index] { + return children?[index].valueForKey(key) + } else { + return children?[index.successor()].valueForKey(key) + } + } +} + +// MARK: BTreeNode extension: Travelsals + +extension BTreeNode { + func traverseKeysInOrder(@noescape process: Key -> Void) { + for i in 0.. ownerTree.order * 2 { + splitChild(children![index], atIndex: index) + } + } + } + + private func splitChild(child: BTreeNode, atIndex index: Int) { + let middleIndex = child.numberOfKeys / 2 + keys.insert(child.keys[middleIndex], atIndex: index) + values.insert(child.values[middleIndex], atIndex: index) + child.keys.removeAtIndex(middleIndex) + child.values.removeAtIndex(middleIndex) + + let rightSibling = BTreeNode( + ownerTree: ownerTree, + keys: Array(child.keys[middleIndex..= 0 && + children![index.predecessor()].numberOfKeys > ownerTree.order { + + moveKeyAtIndex(index.predecessor(), toNode: child, + fromNode: children![index.predecessor()], atPosition: .Left) + + } else if index.successor() < children!.count && + children![index.successor()].numberOfKeys > ownerTree.order { + + moveKeyAtIndex(index, toNode: child, + fromNode: children![index.successor()], atPosition: .Right) + + } else if index.predecessor() >= 0 { + mergeChild(child, withIndex: index, toNodeAtPosition: .Left) + } else { + mergeChild(child, withIndex: index, toNodeAtPosition: .Right) + } + } + + private func moveKeyAtIndex(keyIndex: Int, toNode targetNode: BTreeNode, + fromNode: BTreeNode, atPosition position: BTreeNodePosition) { + switch position { + case .Left: + targetNode.keys.insert(keys[keyIndex], atIndex: targetNode.keys.startIndex) + targetNode.values.insert(values[keyIndex], atIndex: targetNode.values.startIndex) + keys[keyIndex] = fromNode.keys.last! + values[keyIndex] = fromNode.values.last! + fromNode.keys.removeLast() + fromNode.values.removeLast() + if !targetNode.isLeaf { + targetNode.children!.insert(fromNode.children!.last!, + atIndex: targetNode.children!.startIndex) + fromNode.children!.removeLast() + } + + case .Right: + targetNode.keys.insert(keys[keyIndex], atIndex: targetNode.keys.endIndex) + targetNode.values.insert(values[keyIndex], atIndex: targetNode.values.endIndex) + keys[keyIndex] = fromNode.keys.first! + values[keyIndex] = fromNode.values.first! + fromNode.keys.removeFirst() + fromNode.values.removeFirst() + if !targetNode.isLeaf { + targetNode.children!.insert(fromNode.children!.first!, + atIndex: targetNode.children!.endIndex) + fromNode.children!.removeFirst() + } + } + } + + private func mergeChild(child: BTreeNode, withIndex index: Int, toNodeAtPosition position: BTreeNodePosition) { + switch position { + case .Left: + // We can merge to the left sibling + + children![index.predecessor()].keys = children![index.predecessor()].keys + + [keys[index.predecessor()]] + child.keys + + children![index.predecessor()].values = children![index.predecessor()].values + + [values[index.predecessor()]] + child.values + + keys.removeAtIndex(index.predecessor()) + values.removeAtIndex(index.predecessor()) + + if !child.isLeaf { + children![index.predecessor()].children = + children![index.predecessor()].children! + child.children! + } + + case .Right: + // We should merge to the right sibling + + children![index.successor()].keys = child.keys + [keys[index]] + + children![index.successor()].keys + + children![index.successor()].values = child.values + [values[index]] + + children![index.successor()].values + + keys.removeAtIndex(index) + values.removeAtIndex(index) + + if !child.isLeaf { + children![index.successor()].children = + child.children! + children![index.successor()].children! + } + } + children!.removeAtIndex(index) + } +} + +// MARK: BTreeNode extension: Conversion + +extension BTreeNode { + func inorderArrayFromKeys() -> [Key] { + var array = [Key] () + + for i in 0.. { + + /** + The order of the B-Tree + + The number of keys in every node should be in the [order, 2*order] range, + except the root node which is allowed to contain less keys than the value of order. + */ + public let order: Int + + /// The root node of the tree + var rootNode: BTreeNode! + + private(set) public var numberOfKeys = 0 + + /** + Designated initializer for the tree + + - parameters: + - order: The order of the tree. + */ + public init?(order: Int) { + guard order > 0 else { + print("Order has to be greater than 0.") + return nil + } + self.order = order + rootNode = BTreeNode(ownerTree: self) + } +} + +// MARK: BTree extension: Travelsals + +extension BTree { + public func traverseKeysInOrder(@noescape process: Key -> Void) { + rootNode.traverseKeysInOrder(process) + } +} + +// MARK: BTree extension: Subscript + +extension BTree { + public subscript (key: Key) -> Value? { + return valueForKey(key) + } +} + +// MARK: BTree extension: Value for Key + +extension BTree { + public func valueForKey(key: Key) -> Value? { + guard rootNode.numberOfKeys > 0 else { + return nil + } + + return rootNode.valueForKey(key) + } +} + +// MARK: BTree extension: Insertion + +extension BTree { + public func insertValue(value: Value, forKey key: Key) { + rootNode.insertValue(value, forKey: key) + + if rootNode.numberOfKeys > order * 2 { + splitRoot() + } + } + + private func splitRoot() { + let middleIndexOfOldRoot = rootNode.numberOfKeys / 2 + + let newRoot = BTreeNode( + ownerTree: self, + keys: [rootNode.keys[middleIndexOfOldRoot]], + values: [rootNode.values[middleIndexOfOldRoot]], + children: [rootNode] + ) + rootNode.keys.removeAtIndex(middleIndexOfOldRoot) + rootNode.values.removeAtIndex(middleIndexOfOldRoot) + + let newRightChild = BTreeNode( + ownerTree: self, + keys: Array(rootNode.keys[middleIndexOfOldRoot.. 0 else { + return + } + + rootNode.removeKey(key) + + if rootNode.numberOfKeys == 0 && !rootNode.isLeaf { + rootNode = rootNode.children!.first! + } + } +} + +// MARK: BTree extension: Conversion + +extension BTree { + public func inorderArrayFromKeys() -> [Key] { + return rootNode.inorderArrayFromKeys() + } +} + +// MARK: BTree extension: Decription + +extension BTree: CustomStringConvertible { + // Returns a String containing the preorder representation of the nodes + public var description: String { + return rootNode.description + } +} diff --git a/BTree/BTree.playground/contents.xcplayground b/BTree/BTree.playground/contents.xcplayground new file mode 100644 index 000000000..06828af92 --- /dev/null +++ b/BTree/BTree.playground/contents.xcplayground @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/BTree/BTree.playground/playground.xcworkspace/contents.xcworkspacedata b/BTree/BTree.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/BTree/BTree.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/BTree/BTree.swift b/BTree/BTree.swift new file mode 100644 index 000000000..16c4eabe4 --- /dev/null +++ b/BTree/BTree.swift @@ -0,0 +1,473 @@ +// The MIT License (MIT) + +// Copyright (c) 2016 Viktor Szilárd Simkó (aqviktor[at]gmail.com) + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +/* + B-Tree + + A B-Tree is a self-balancing search tree, in which nodes can have more than two children. + */ + +// MARK: - BTreeNode class + +class BTreeNode { + unowned var ownerTree: BTree + + private var keys = [Key]() + var values = [Value]() + var children: [BTreeNode]? + + var isLeaf: Bool { + return children == nil + } + + var numberOfKeys: Int { + return keys.count + } + + init(ownerTree: BTree) { + self.ownerTree = ownerTree + } + + convenience init(ownerTree: BTree, keys: [Key], + values: [Value], children: [BTreeNode]? = nil) { + self.init(ownerTree: ownerTree) + self.keys += keys + self.values += values + self.children = children + } +} + +// MARK: BTreeNode extesnion: Searching + +extension BTreeNode { + func valueForKey(key: Key) -> Value? { + var index = keys.startIndex + + while index.successor() < keys.endIndex && keys[index] < key { + index = index.successor() + } + + if key == keys[index] { + return values[index] + } else if key < keys[index] { + return children?[index].valueForKey(key) + } else { + return children?[index.successor()].valueForKey(key) + } + } +} + +// MARK: BTreeNode extension: Travelsals + +extension BTreeNode { + func traverseKeysInOrder(@noescape process: Key -> Void) { + for i in 0.. ownerTree.order * 2 { + splitChild(children![index], atIndex: index) + } + } + } + + private func splitChild(child: BTreeNode, atIndex index: Int) { + let middleIndex = child.numberOfKeys / 2 + keys.insert(child.keys[middleIndex], atIndex: index) + values.insert(child.values[middleIndex], atIndex: index) + child.keys.removeAtIndex(middleIndex) + child.values.removeAtIndex(middleIndex) + + let rightSibling = BTreeNode( + ownerTree: ownerTree, + keys: Array(child.keys[middleIndex..= 0 && + children![index.predecessor()].numberOfKeys > ownerTree.order { + + moveKeyAtIndex(index.predecessor(), toNode: child, + fromNode: children![index.predecessor()], atPosition: .Left) + + } else if index.successor() < children!.count && + children![index.successor()].numberOfKeys > ownerTree.order { + + moveKeyAtIndex(index, toNode: child, + fromNode: children![index.successor()], atPosition: .Right) + + } else if index.predecessor() >= 0 { + mergeChild(child, withIndex: index, toNodeAtPosition: .Left) + } else { + mergeChild(child, withIndex: index, toNodeAtPosition: .Right) + } + } + + private func moveKeyAtIndex(keyIndex: Int, toNode targetNode: BTreeNode, + fromNode: BTreeNode, atPosition position: BTreeNodePosition) { + switch position { + case .Left: + targetNode.keys.insert(keys[keyIndex], atIndex: targetNode.keys.startIndex) + targetNode.values.insert(values[keyIndex], atIndex: targetNode.values.startIndex) + keys[keyIndex] = fromNode.keys.last! + values[keyIndex] = fromNode.values.last! + fromNode.keys.removeLast() + fromNode.values.removeLast() + if !targetNode.isLeaf { + targetNode.children!.insert(fromNode.children!.last!, + atIndex: targetNode.children!.startIndex) + fromNode.children!.removeLast() + } + + case .Right: + targetNode.keys.insert(keys[keyIndex], atIndex: targetNode.keys.endIndex) + targetNode.values.insert(values[keyIndex], atIndex: targetNode.values.endIndex) + keys[keyIndex] = fromNode.keys.first! + values[keyIndex] = fromNode.values.first! + fromNode.keys.removeFirst() + fromNode.values.removeFirst() + if !targetNode.isLeaf { + targetNode.children!.insert(fromNode.children!.first!, + atIndex: targetNode.children!.endIndex) + fromNode.children!.removeFirst() + } + } + } + + private func mergeChild(child: BTreeNode, withIndex index: Int, toNodeAtPosition position: BTreeNodePosition) { + switch position { + case .Left: + // We can merge to the left sibling + + children![index.predecessor()].keys = children![index.predecessor()].keys + + [keys[index.predecessor()]] + child.keys + + children![index.predecessor()].values = children![index.predecessor()].values + + [values[index.predecessor()]] + child.values + + keys.removeAtIndex(index.predecessor()) + values.removeAtIndex(index.predecessor()) + + if !child.isLeaf { + children![index.predecessor()].children = + children![index.predecessor()].children! + child.children! + } + + case .Right: + // We should merge to the right sibling + + children![index.successor()].keys = child.keys + [keys[index]] + + children![index.successor()].keys + + children![index.successor()].values = child.values + [values[index]] + + children![index.successor()].values + + keys.removeAtIndex(index) + values.removeAtIndex(index) + + if !child.isLeaf { + children![index.successor()].children = + child.children! + children![index.successor()].children! + } + } + children!.removeAtIndex(index) + } +} + +// MARK: BTreeNode extension: Conversion + +extension BTreeNode { + func inorderArrayFromKeys() -> [Key] { + var array = [Key] () + + for i in 0.. { + + /** + The order of the B-Tree + + The number of keys in every node should be in the [order, 2*order] range, + except the root node which is allowed to contain less keys than the value of order. + */ + public let order: Int + + /// The root node of the tree + var rootNode: BTreeNode! + + private(set) public var numberOfKeys = 0 + + /** + Designated initializer for the tree + + - parameters: + - order: The order of the tree. + */ + public init?(order: Int) { + guard order > 0 else { + print("Order has to be greater than 0.") + return nil + } + self.order = order + rootNode = BTreeNode(ownerTree: self) + } +} + +// MARK: BTree extension: Travelsals + +extension BTree { + public func traverseKeysInOrder(@noescape process: Key -> Void) { + rootNode.traverseKeysInOrder(process) + } +} + +// MARK: BTree extension: Subscript + +extension BTree { + public subscript (key: Key) -> Value? { + return valueForKey(key) + } +} + +// MARK: BTree extension: Value for Key + +extension BTree { + public func valueForKey(key: Key) -> Value? { + guard rootNode.numberOfKeys > 0 else { + return nil + } + + return rootNode.valueForKey(key) + } +} + +// MARK: BTree extension: Insertion + +extension BTree { + public func insertValue(value: Value, forKey key: Key) { + rootNode.insertValue(value, forKey: key) + + if rootNode.numberOfKeys > order * 2 { + splitRoot() + } + } + + private func splitRoot() { + let middleIndexOfOldRoot = rootNode.numberOfKeys / 2 + + let newRoot = BTreeNode( + ownerTree: self, + keys: [rootNode.keys[middleIndexOfOldRoot]], + values: [rootNode.values[middleIndexOfOldRoot]], + children: [rootNode] + ) + rootNode.keys.removeAtIndex(middleIndexOfOldRoot) + rootNode.values.removeAtIndex(middleIndexOfOldRoot) + + let newRightChild = BTreeNode( + ownerTree: self, + keys: Array(rootNode.keys[middleIndexOfOldRoot.. 0 else { + return + } + + rootNode.removeKey(key) + + if rootNode.numberOfKeys == 0 && !rootNode.isLeaf { + rootNode = rootNode.children!.first! + } + } +} + +// MARK: BTree extension: Conversion + +extension BTree { + public func inorderArrayFromKeys() -> [Key] { + return rootNode.inorderArrayFromKeys() + } +} + +// MARK: BTree extension: Decription + +extension BTree: CustomStringConvertible { + // Returns a String containing the preorder representation of the nodes + public var description: String { + return rootNode.description + } +} diff --git a/BTree/Images/BTree20.png b/BTree/Images/BTree20.png new file mode 100644 index 0000000000000000000000000000000000000000..1a6a6a50e6b4a732da6f2f75b28ca896cda9a2d0 GIT binary patch literal 16592 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 literal 0 HcmV?d00001 diff --git a/BTree/Images/Node.png b/BTree/Images/Node.png new file mode 100644 index 0000000000000000000000000000000000000000..346f940bfaabea7e9ac859b643646f23bc6f736f GIT binary patch literal 6255 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 VQtBuS_#=TxU&mOx4t6*CKLEWg(=q@6 literal 0 HcmV?d00001 diff --git a/BTree/README.md b/BTree/README.md new file mode 100644 index 000000000..0a25c44c3 --- /dev/null +++ b/BTree/README.md @@ -0,0 +1,172 @@ +# B-Tree + +A B-Tree is a self-balancing search tree, in which nodes can have more than two children. + +### Properties + +A B-Tree of order *n* satisfies the following properties: + - Every node has at most *2n* keys. + - Every node (except root) has at least *n* keys. + - Eyery non-leaf node with *k* keys has *k+1* children. + - The keys in all nodes are sorted in increasing order. + - The subtree between two keys *k* and *l* of a non-leaf node contains all the keys between *k* and *l*. + - All leaves appear at the same level. + +A second order B-Tree with keys from 1 to 20 looks like this: + +![A B-Tree with 20 keys.](Images/BTree20.png) + +### The representation of a B-Tree node in code + +```swift +class BTreeNode { + unowned var ownerTree: BTree + + private var keys = [Key]() + var children: [BTreeNode]? + + ... +} +``` + +The main parts of a node are two arrays: + - An array containing the keys + - An array containing the children + +![Node.](Images/Node.png) + +Nodes also have a reference to the tree they belong to. +This is necessary because nodes have to know the order of the tree. + +*Note: The array containing the children is an Optional, because leaf nodes don't have children.* + +## Searching + +1. Searching for a key `k` begins at the root node. +2. We perform a linear search on the keys of the node, until we find a key `l` that is not less than `k`, + or reach the end of the array. +3. If `k == l` then we have found the key. +4. If `k < l`: + - If the node we are on is not a leaf, then we go to the left child of `l`, and perform the steps 3.-5. again. + - If we are on a leaf, then `k` is not in the tree. +5. If we have reached the end of the array: + - If we are on a non-leaf node, then we go to the last child of the node, and perform the steps 3.-5. again. + - If we are on a leaf, then `k` is not in the tree. + +### The code + +`valueForKey(_:)` method searches for the given key and if it's in the tree, +it returns the value associated with it, else it returns `nil`. + +## Insertion + +Keys can only be inserted to leaf nodes. + +1. Perform a search for the key `k` we want to insert. +2. If we haven't found it and we are on a leaf node, we can insert it. + - If after the search the key `l` which we are standing on is greater than `k`: + We insert `k` to the position before `l`. + - Else: + We insert `k` to the position after `l`. + +After insertion we should check if the number of keys in the node is in the correct range. +If there are more keys in the node than `order*2`, we need to split the node. + +####Splitting a node + +1. Move up the middle key of the node we want to split, to its parent (if it has one). +2. If it hasn't got a parent(it is the root), then create a new root and insert to it. + Also add the old root as the left child of the new root. +3. Split the node into two by moving the keys (and children, if it's a non-leaf) that were after the middle key + to a new node. +4. Add the new node as a right child for the key that we have moved up. + +After splitting a node it is possible that the parent node will also contain too many keys, so we need to split it also. +In the worst case the splitting goes up to the root (in this case the height of the tree increases). + +An insertion to a first order tree looks like this: + +![Splitting](Images/InsertionSplit.png) + +### The code + +The method `insertValue(_:forKey:)` does the insertion. +After it has inserted a key, as the recursion goes up every node checks the number of keys in its child. +if a node has too many keys, its parent calls the `splitChild(_:atIndex:)` method on it. + +The root node is checked by the tree itself. +If the root has too many nodes after the insertion the tree calls the `splitRoot()` method. + +## Removal + +Keys can only be removed from leaf nodes. + +1. Perform a search for the key `k` we want to remove. +2. If we have found it: + - If we are on a leaf node: + We can remove the key. + - Else: + We overwrite `k` with its inorder predecessor `p`, then we remove `p` from the leaf node. + +After a key have been removed from a node we should check that the node has enough keys. +If a node has fewer keys than the order of the tree, then we should move a key to it, +or merge it with one of its siblings. + +####Moving a key to the child + +If the problematic node has a nearest sibling that has more keys than the order of the tree, +we should perform this operation on the tree, else we should merge the node with one of its siblings. + +Let's say the child we want to fix `c1` is at index `i` in its parent node's children array. + +If the child `c2` at index `i-1` has more keys than the order of the tree: + +1. We move the key at index `i-1` from the parent node to the child `c1`'s keys array at index `0`. +2. We move the last key from `c2` to the parent's keys array at index `i-1`. +3. (If `c1` is non-leaf) We move the last children from `c1` to `c2`'s children array at index 0. + +Else: + +1. We move the key at index `i` from the parent node to the end of child `c1`'s keys array. +2. We move the first key from `c2` to the parent's keys array at index `i`. +3. (If `c1` isn't a leaf) We move the first children from `c2` to the end of `c1`'s children array. + +![Moving Key](Images/MovingKey.png) + +####Merging two nodes + +Let's say we want to merge the child `c1` at index `i` in its parent's children array. + +If `c1` has a left sibling `c2`: + +1. We move the key from the parent at index `i-1` to the end of `c2`'s keys array. +2. We move the keys and the children(if it's a non-leaf) from `c1` to the end of `c2`'s keys and children array. +3. We remove the children at index `i` from the parent node. + +Else if `c1` only has a right sibling `c2`: + +1. We move the key from the parent at index `i` to the beginning of `c2`'s keys array. +2. We move the keys and the children(if it's a non-leaf) from `c1` to the beginning of `c2`'s keys and children array. +3. We remove the children at index `i` from the parent node. + +After merging it is possible that now the parent node contains too few keys, +so in the worst case merging also can go up to the root, in which case the height of the tree decreases. + +![Merging Nodes](Images/MergingNodes.png) + +### The code + +- `removeKey(_:)` method removes the given key from the tree. After a key has been deleted, + every node checks the number of keys in its child. If a child has less nodes than the order of the tree, + it calls the `fixChildWithLessNodesThanOrder(_:atIndex:)` method. + +- `fixChildWithLessNodesThanOrder(_:atIndex:)` method decides which way to fix the child (by moving a key to it, + or by merging it), then calls `moveKeyAtIndex(keyIndex:toNode:fromNode:atPosition:)` or + `mergeChild(_:withIndex:toNodeAtPosition:)` method according to its choice. + +## See also + +[Wikipedia](https://en.wikipedia.org/wiki/B-tree) +[GeeksforGeeks](http://www.geeksforgeeks.org/b-tree-set-1-introduction-2/) + +*Written for Swift Algorithm Club by Viktor Szilárd Simkó* diff --git a/BTree/Tests/Tests.xcodeproj/project.pbxproj b/BTree/Tests/Tests.xcodeproj/project.pbxproj new file mode 100644 index 000000000..0780f04c8 --- /dev/null +++ b/BTree/Tests/Tests.xcodeproj/project.pbxproj @@ -0,0 +1,268 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + C66702821D0EEE5F008CD769 /* BTreeNodeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C66702801D0EEE5F008CD769 /* BTreeNodeTests.swift */; }; + C66702831D0EEE5F008CD769 /* BTreeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C66702811D0EEE5F008CD769 /* BTreeTests.swift */; }; + C66702851D0EEE99008CD769 /* BTree.swift in Sources */ = {isa = PBXBuildFile; fileRef = C66702841D0EEE99008CD769 /* BTree.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + C66702781D0EEE25008CD769 /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + C667027C1D0EEE25008CD769 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + C66702801D0EEE5F008CD769 /* BTreeNodeTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BTreeNodeTests.swift; sourceTree = ""; }; + C66702811D0EEE5F008CD769 /* BTreeTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BTreeTests.swift; sourceTree = ""; }; + C66702841D0EEE99008CD769 /* BTree.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BTree.swift; path = ../../BTree.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + C66702751D0EEE25008CD769 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + C66702611D0EEE0D008CD769 = { + isa = PBXGroup; + children = ( + C66702791D0EEE25008CD769 /* Tests */, + C667026B1D0EEE0D008CD769 /* Products */, + ); + sourceTree = ""; + }; + C667026B1D0EEE0D008CD769 /* Products */ = { + isa = PBXGroup; + children = ( + C66702781D0EEE25008CD769 /* Tests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + C66702791D0EEE25008CD769 /* Tests */ = { + isa = PBXGroup; + children = ( + C66702841D0EEE99008CD769 /* BTree.swift */, + C66702801D0EEE5F008CD769 /* BTreeNodeTests.swift */, + C66702811D0EEE5F008CD769 /* BTreeTests.swift */, + C667027C1D0EEE25008CD769 /* Info.plist */, + ); + path = Tests; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + C66702771D0EEE25008CD769 /* Tests */ = { + isa = PBXNativeTarget; + buildConfigurationList = C667027D1D0EEE25008CD769 /* Build configuration list for PBXNativeTarget "Tests" */; + buildPhases = ( + C66702741D0EEE25008CD769 /* Sources */, + C66702751D0EEE25008CD769 /* Frameworks */, + C66702761D0EEE25008CD769 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Tests; + productName = Tests; + productReference = C66702781D0EEE25008CD769 /* Tests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + C66702621D0EEE0D008CD769 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0730; + LastUpgradeCheck = 0730; + ORGANIZATIONNAME = "Viktor Szilárd Simkó"; + TargetAttributes = { + C66702771D0EEE25008CD769 = { + CreatedOnToolsVersion = 7.3.1; + }; + }; + }; + buildConfigurationList = C66702651D0EEE0D008CD769 /* Build configuration list for PBXProject "Tests" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = C66702611D0EEE0D008CD769; + productRefGroup = C667026B1D0EEE0D008CD769 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + C66702771D0EEE25008CD769 /* Tests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + C66702761D0EEE25008CD769 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + C66702741D0EEE25008CD769 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + C66702831D0EEE5F008CD769 /* BTreeTests.swift in Sources */, + C66702821D0EEE5F008CD769 /* BTreeNodeTests.swift in Sources */, + C66702851D0EEE99008CD769 /* BTree.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + C667026F1D0EEE0D008CD769 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + C66702701D0EEE0D008CD769 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + }; + name = Release; + }; + C667027E1D0EEE25008CD769 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Tests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = viktorsimko.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + C667027F1D0EEE25008CD769 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Tests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = viktorsimko.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + C66702651D0EEE0D008CD769 /* Build configuration list for PBXProject "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C667026F1D0EEE0D008CD769 /* Debug */, + C66702701D0EEE0D008CD769 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C667027D1D0EEE25008CD769 /* Build configuration list for PBXNativeTarget "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C667027E1D0EEE25008CD769 /* Debug */, + C667027F1D0EEE25008CD769 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = C66702621D0EEE0D008CD769 /* Project object */; +} diff --git a/BTree/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/BTree/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..6c0ea8493 --- /dev/null +++ b/BTree/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/BTree/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/BTree/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme new file mode 100644 index 000000000..d9200547d --- /dev/null +++ b/BTree/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -0,0 +1,100 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/BTree/Tests/Tests/BTreeNodeTests.swift b/BTree/Tests/Tests/BTreeNodeTests.swift new file mode 100644 index 000000000..07457d937 --- /dev/null +++ b/BTree/Tests/Tests/BTreeNodeTests.swift @@ -0,0 +1,54 @@ +// +// BTreeNodeTests.swift +// BTree +// +// Created by Viktor Szilárd Simkó on 13/06/16. +// Copyright © 2016 Viktor Szilárd Simkó. All rights reserved. +// + +import XCTest + +class BTreeNodeTests: XCTestCase { + + let ownerTree = BTree(order: 2)! + var root: BTreeNode! + var leftChild: BTreeNode! + var rightChild: BTreeNode! + + override func setUp() { + super.setUp() + + root = BTreeNode(ownerTree: ownerTree) + leftChild = BTreeNode(ownerTree: ownerTree) + rightChild = BTreeNode(ownerTree: ownerTree) + + root.insertValue(1, forKey: 1) + root.children = [leftChild, rightChild] + } + + func testIsLeafRoot() { + XCTAssertFalse(root.isLeaf) + } + + func testIsLeafLeaf() { + XCTAssertTrue(leftChild.isLeaf) + XCTAssertTrue(rightChild.isLeaf) + } + + func testOwner() { + XCTAssert(root.ownerTree === ownerTree) + XCTAssert(leftChild.ownerTree === ownerTree) + XCTAssert(rightChild.ownerTree === ownerTree) + } + + func testNumberOfKeys() { + XCTAssertEqual(root.numberOfKeys, 1) + XCTAssertEqual(leftChild.numberOfKeys, 0) + XCTAssertEqual(rightChild.numberOfKeys, 0) + } + + func testChildren() { + XCTAssertEqual(root.children!.count, 2) + } +} + diff --git a/BTree/Tests/Tests/BTreeTests.swift b/BTree/Tests/Tests/BTreeTests.swift new file mode 100644 index 000000000..77337c5e4 --- /dev/null +++ b/BTree/Tests/Tests/BTreeTests.swift @@ -0,0 +1,257 @@ +// +// BTreeTests.swift +// BTreeTests +// +// Created by Viktor Szilárd Simkó on 09/06/16. +// Copyright © 2016 Viktor Szilárd Simkó. All rights reserved. +// + +import XCTest + +class BTreeTests: XCTestCase { + var bTree: BTree! + + override func setUp() { + super.setUp() + bTree = BTree(order: 3)! + } + + // MARK: - Tests on empty tree + + func testOrder() { + XCTAssertEqual(bTree.order, 3) + } + + func testRootNode() { + XCTAssertNotNil(bTree.rootNode) + } + + func testNumberOfNodesOnEmptyTree() { + XCTAssertEqual(bTree.numberOfKeys, 0) + } + + func testInorderTraversalOfEmptyTree() { + bTree.traverseKeysInOrder { i in + XCTFail("Inorder travelsal fail.") + } + } + + func testSubscriptOnEmptyTree() { + XCTAssertEqual(bTree[1], nil) + } + + func testSearchEmptyTree() { + XCTAssertEqual(bTree.valueForKey(1), nil) + } + + func testInsertToEmptyTree() { + bTree.insertValue(1, forKey: 1) + + XCTAssertEqual(bTree[1]!, 1) + } + + func testRemoveFromEmptyTree() { + bTree.removeKey(1) + XCTAssertEqual(bTree.description, "[]") + } + + func testInorderArrayFromEmptyTree() { + XCTAssertEqual(bTree.inorderArrayFromKeys(), [Int]()) + } + + func testDescriptionOfEmptyTree() { + XCTAssertEqual(bTree.description, "[]") + } + + // MARK: - Travelsal + + func testInorderTravelsal() { + for i in 1...20 { + bTree.insertValue(i, forKey: i) + } + + var j = 1 + + bTree.traverseKeysInOrder { i in + XCTAssertEqual(i, j) + j += 1 + } + } + + // MARK: - Searching + + func testSearchForMaximum() { + for i in 1...20 { + bTree.insertValue(i, forKey: i) + } + + XCTAssertEqual(bTree.valueForKey(20)!, 20) + } + + func testSearchForMinimum() { + for i in 1...20 { + bTree.insertValue(i, forKey: i) + } + + XCTAssertEqual(bTree.valueForKey(1)!, 1) + } + + // MARK: - Insertion + + func testInsertion() { + bTree.insertKeysUpTo(20) + + XCTAssertEqual(bTree.numberOfKeys, 20) + + for i in 1...20 { + XCTAssertNotNil(bTree[i]) + } + + do { + try bTree.checkBalanced() + } catch { + XCTFail("BTree is not balanced") + } + + XCTAssertEqual(bTree.description, + "[4, 8, 12, 16][1, 2, 3][5, 6, 7][9, 10, 11][13, 14, 15][17, 18, 19, 20]") + } + + // MARK: - Removal + + func testRemoveMaximum() { + for i in 1...20 { + bTree.insertValue(i, forKey: i) + } + + bTree.removeKey(20) + + XCTAssertNil(bTree[20]) + + do { + try bTree.checkBalanced() + } catch { + XCTFail("BTree is not balanced") + } + } + + func testRemoveMinimum() { + bTree.insertKeysUpTo(20) + + bTree.removeKey(1) + + XCTAssertNil(bTree[1]) + + do { + try bTree.checkBalanced() + } catch { + XCTFail("BTree is not balanced") + } + } + + func testRemoveSome() { + bTree.insertKeysUpTo(20) + + bTree.removeKey(6) + bTree.removeKey(9) + + XCTAssertNil(bTree[6]) + XCTAssertNil(bTree[9]) + + do { + try bTree.checkBalanced() + } catch { + XCTFail("BTree is not balanced") + } + + XCTAssertEqual(bTree.description, + "[7, 12, 16][1, 2, 3, 4, 5][8, 10, 11][13, 14, 15][17, 18, 19, 20]") + } + + func testRemoveSomeFrom2ndOrder() { + bTree = BTree(order: 2)! + bTree.insertKeysUpTo(20) + + bTree.removeKey(6) + bTree.removeKey(9) + + XCTAssertNil(bTree[6]) + XCTAssertNil(bTree[9]) + + do { + try bTree.checkBalanced() + } catch { + XCTFail("BTree is not balanced") + } + + XCTAssertEqual(bTree.description, + "[12][4, 8][1, 2, 3][5, 7][10, 11][15, 18][13, 14][16, 17][19, 20]") + } + + func testRemoveAll() { + bTree.insertKeysUpTo(20) + + XCTAssertEqual(bTree.numberOfKeys, 20) + + for i in (1...20).reverse() { + bTree.removeKey(i) + } + + do { + try bTree.checkBalanced() + } catch { + XCTFail("BTree is not balanced") + } + + XCTAssertEqual(bTree.numberOfKeys, 0) + } + + // MARK: - InorderArray + + func testInorderArray() { + bTree.insertKeysUpTo(20) + + let returnedArray = bTree.inorderArrayFromKeys() + let targetArray = Array(1...20) + + XCTAssertEqual(returnedArray, targetArray) + } +} + +enum BTreeError: ErrorType { + case TooManyNodes + case TooFewNodes +} + +extension BTreeNode { + func checkBalanced(isRoot root: Bool) throws { + if numberOfKeys > ownerTree.order * 2 { + throw BTreeError.TooManyNodes + } else if !root && numberOfKeys < ownerTree.order { + throw BTreeError.TooFewNodes + } + + if !isLeaf { + for child in children! { + try child.checkBalanced(isRoot: false) + } + } + } +} + +extension BTree where Key: SignedIntegerType, Value: SignedIntegerType { + func insertKeysUpTo(to: Int) { + var k: Key = 1 + var v: Value = 1 + + for _ in 1...to { + insertValue(v, forKey: k) + k = k + 1 + v = v + 1 + } + } + + func checkBalanced() throws { + try rootNode.checkBalanced(isRoot: true) + } +} diff --git a/BTree/Tests/Tests/Info.plist b/BTree/Tests/Tests/Info.plist new file mode 100644 index 000000000..ba72822e8 --- /dev/null +++ b/BTree/Tests/Tests/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + From 01248c5725728cfe8f56b06c7f44a55353c7d469 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viktor=20Szil=C3=A1rd=20Viktor?= Date: Fri, 17 Jun 2016 10:50:17 +0200 Subject: [PATCH 0411/1679] cleaned up tests --- BTree/Tests/Tests/BTreeTests.swift | 9 --------- 1 file changed, 9 deletions(-) diff --git a/BTree/Tests/Tests/BTreeTests.swift b/BTree/Tests/Tests/BTreeTests.swift index 77337c5e4..947781478 100644 --- a/BTree/Tests/Tests/BTreeTests.swift +++ b/BTree/Tests/Tests/BTreeTests.swift @@ -112,9 +112,6 @@ class BTreeTests: XCTestCase { } catch { XCTFail("BTree is not balanced") } - - XCTAssertEqual(bTree.description, - "[4, 8, 12, 16][1, 2, 3][5, 6, 7][9, 10, 11][13, 14, 15][17, 18, 19, 20]") } // MARK: - Removal @@ -163,9 +160,6 @@ class BTreeTests: XCTestCase { } catch { XCTFail("BTree is not balanced") } - - XCTAssertEqual(bTree.description, - "[7, 12, 16][1, 2, 3, 4, 5][8, 10, 11][13, 14, 15][17, 18, 19, 20]") } func testRemoveSomeFrom2ndOrder() { @@ -183,9 +177,6 @@ class BTreeTests: XCTestCase { } catch { XCTFail("BTree is not balanced") } - - XCTAssertEqual(bTree.description, - "[12][4, 8][1, 2, 3][5, 7][10, 11][15, 18][13, 14][16, 17][19, 20]") } func testRemoveAll() { From c40de6e3685f70244b265dedb3a54a8f6384cdd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viktor=20Szil=C3=A1rd=20Viktor?= Date: Fri, 17 Jun 2016 10:56:05 +0200 Subject: [PATCH 0412/1679] added test in .travis.yml --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 0b14e9a40..a7861ed76 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,6 +13,7 @@ script: - xctool test -project ./Bounded\ Priority\ Queue/Tests/Tests.xcodeproj -scheme Tests - xctool test -project ./Breadth-First\ Search/Tests/Tests.xcodeproj -scheme Tests - xctool test -project ./Bucket\ Sort/Tests/Tests.xcodeproj -scheme Tests +- xctool test -project ./BTree\ BTree/Tests/Tests.xcodeproj -scheme Tests - xctool test -project ./Counting\ Sort/Tests/Tests.xcodeproj -scheme Tests - xctool test -project ./Depth-First\ Search/Tests/Tests.xcodeproj -scheme Tests - xctool test -project ./Graph/Graph.xcodeproj -scheme GraphTests From 25e470ca002e3b7e104eb646a92843e9226980d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viktor=20Szil=C3=A1rd=20Viktor?= Date: Fri, 17 Jun 2016 11:08:41 +0200 Subject: [PATCH 0413/1679] renamed folder --- .travis.yml | 2 +- {BTree => B-Tree}/BTree.playground/Contents.swift | 0 .../BTree.playground/Sources/BTree.swift | 0 .../BTree.playground/contents.xcplayground | 0 .../playground.xcworkspace/contents.xcworkspacedata | 0 {BTree => B-Tree}/BTree.swift | 0 {BTree => B-Tree}/Images/BTree20.png | Bin {BTree => B-Tree}/Images/InsertionSplit.png | Bin {BTree => B-Tree}/Images/MergingNodes.png | Bin {BTree => B-Tree}/Images/MovingKey.png | Bin {BTree => B-Tree}/Images/Node.png | Bin {BTree => B-Tree}/README.md | 0 .../Tests/Tests.xcodeproj/project.pbxproj | 0 .../project.xcworkspace/contents.xcworkspacedata | 0 .../xcshareddata/xcschemes/Tests.xcscheme | 0 {BTree => B-Tree}/Tests/Tests/BTreeNodeTests.swift | 0 {BTree => B-Tree}/Tests/Tests/BTreeTests.swift | 0 {BTree => B-Tree}/Tests/Tests/Info.plist | 0 18 files changed, 1 insertion(+), 1 deletion(-) rename {BTree => B-Tree}/BTree.playground/Contents.swift (100%) rename {BTree => B-Tree}/BTree.playground/Sources/BTree.swift (100%) rename {BTree => B-Tree}/BTree.playground/contents.xcplayground (100%) rename {BTree => B-Tree}/BTree.playground/playground.xcworkspace/contents.xcworkspacedata (100%) rename {BTree => B-Tree}/BTree.swift (100%) rename {BTree => B-Tree}/Images/BTree20.png (100%) rename {BTree => B-Tree}/Images/InsertionSplit.png (100%) rename {BTree => B-Tree}/Images/MergingNodes.png (100%) rename {BTree => B-Tree}/Images/MovingKey.png (100%) rename {BTree => B-Tree}/Images/Node.png (100%) rename {BTree => B-Tree}/README.md (100%) rename {BTree => B-Tree}/Tests/Tests.xcodeproj/project.pbxproj (100%) rename {BTree => B-Tree}/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata (100%) rename {BTree => B-Tree}/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme (100%) rename {BTree => B-Tree}/Tests/Tests/BTreeNodeTests.swift (100%) rename {BTree => B-Tree}/Tests/Tests/BTreeTests.swift (100%) rename {BTree => B-Tree}/Tests/Tests/Info.plist (100%) diff --git a/.travis.yml b/.travis.yml index a7861ed76..019948716 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,7 +13,7 @@ script: - xctool test -project ./Bounded\ Priority\ Queue/Tests/Tests.xcodeproj -scheme Tests - xctool test -project ./Breadth-First\ Search/Tests/Tests.xcodeproj -scheme Tests - xctool test -project ./Bucket\ Sort/Tests/Tests.xcodeproj -scheme Tests -- xctool test -project ./BTree\ BTree/Tests/Tests.xcodeproj -scheme Tests +- xctool test -project ./B-Tree/Tests/Tests.xcodeproj -scheme Tests - xctool test -project ./Counting\ Sort/Tests/Tests.xcodeproj -scheme Tests - xctool test -project ./Depth-First\ Search/Tests/Tests.xcodeproj -scheme Tests - xctool test -project ./Graph/Graph.xcodeproj -scheme GraphTests diff --git a/BTree/BTree.playground/Contents.swift b/B-Tree/BTree.playground/Contents.swift similarity index 100% rename from BTree/BTree.playground/Contents.swift rename to B-Tree/BTree.playground/Contents.swift diff --git a/BTree/BTree.playground/Sources/BTree.swift b/B-Tree/BTree.playground/Sources/BTree.swift similarity index 100% rename from BTree/BTree.playground/Sources/BTree.swift rename to B-Tree/BTree.playground/Sources/BTree.swift diff --git a/BTree/BTree.playground/contents.xcplayground b/B-Tree/BTree.playground/contents.xcplayground similarity index 100% rename from BTree/BTree.playground/contents.xcplayground rename to B-Tree/BTree.playground/contents.xcplayground diff --git a/BTree/BTree.playground/playground.xcworkspace/contents.xcworkspacedata b/B-Tree/BTree.playground/playground.xcworkspace/contents.xcworkspacedata similarity index 100% rename from BTree/BTree.playground/playground.xcworkspace/contents.xcworkspacedata rename to B-Tree/BTree.playground/playground.xcworkspace/contents.xcworkspacedata diff --git a/BTree/BTree.swift b/B-Tree/BTree.swift similarity index 100% rename from BTree/BTree.swift rename to B-Tree/BTree.swift diff --git a/BTree/Images/BTree20.png b/B-Tree/Images/BTree20.png similarity index 100% rename from BTree/Images/BTree20.png rename to B-Tree/Images/BTree20.png diff --git a/BTree/Images/InsertionSplit.png b/B-Tree/Images/InsertionSplit.png similarity index 100% rename from BTree/Images/InsertionSplit.png rename to B-Tree/Images/InsertionSplit.png diff --git a/BTree/Images/MergingNodes.png b/B-Tree/Images/MergingNodes.png similarity index 100% rename from BTree/Images/MergingNodes.png rename to B-Tree/Images/MergingNodes.png diff --git a/BTree/Images/MovingKey.png b/B-Tree/Images/MovingKey.png similarity index 100% rename from BTree/Images/MovingKey.png rename to B-Tree/Images/MovingKey.png diff --git a/BTree/Images/Node.png b/B-Tree/Images/Node.png similarity index 100% rename from BTree/Images/Node.png rename to B-Tree/Images/Node.png diff --git a/BTree/README.md b/B-Tree/README.md similarity index 100% rename from BTree/README.md rename to B-Tree/README.md diff --git a/BTree/Tests/Tests.xcodeproj/project.pbxproj b/B-Tree/Tests/Tests.xcodeproj/project.pbxproj similarity index 100% rename from BTree/Tests/Tests.xcodeproj/project.pbxproj rename to B-Tree/Tests/Tests.xcodeproj/project.pbxproj diff --git a/BTree/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/B-Tree/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata similarity index 100% rename from BTree/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata rename to B-Tree/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata diff --git a/BTree/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/B-Tree/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme similarity index 100% rename from BTree/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme rename to B-Tree/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme diff --git a/BTree/Tests/Tests/BTreeNodeTests.swift b/B-Tree/Tests/Tests/BTreeNodeTests.swift similarity index 100% rename from BTree/Tests/Tests/BTreeNodeTests.swift rename to B-Tree/Tests/Tests/BTreeNodeTests.swift diff --git a/BTree/Tests/Tests/BTreeTests.swift b/B-Tree/Tests/Tests/BTreeTests.swift similarity index 100% rename from BTree/Tests/Tests/BTreeTests.swift rename to B-Tree/Tests/Tests/BTreeTests.swift diff --git a/BTree/Tests/Tests/Info.plist b/B-Tree/Tests/Tests/Info.plist similarity index 100% rename from BTree/Tests/Tests/Info.plist rename to B-Tree/Tests/Tests/Info.plist From 7dd0cb5cca1baa5115b5e111454d279cef42ad03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viktor=20Szil=C3=A1rd=20Viktor?= Date: Fri, 17 Jun 2016 13:59:36 +0200 Subject: [PATCH 0414/1679] Added playground contents. --- B-Tree/BTree.playground/Contents.swift | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/B-Tree/BTree.playground/Contents.swift b/B-Tree/BTree.playground/Contents.swift index 7d2973f77..186718bbd 100644 --- a/B-Tree/BTree.playground/Contents.swift +++ b/B-Tree/BTree.playground/Contents.swift @@ -8,3 +8,19 @@ bTree.insertValue(1, forKey: 1) bTree.insertValue(2, forKey: 2) bTree.insertValue(3, forKey: 3) bTree.insertValue(4, forKey: 4) + +bTree.valueForKey(3) +bTree[3] + +bTree.removeKey(2) + +bTree.traverseKeysInOrder { + key in + print(key) +} + +bTree.numberOfKeys + +bTree.order + +bTree.inorderArrayFromKeys() \ No newline at end of file From 396924baef1ec0bfad18d7105ec86419676f6d0c Mon Sep 17 00:00:00 2001 From: "Michael C. Rael" Date: Sat, 18 Jun 2016 09:38:31 -0600 Subject: [PATCH 0415/1679] Completed documentation. Also changed external parameter name in cover from 'from' to 'within'. --- Set Cover (Unweighted)/README.markdown | 12 ++++++++--- .../SetCover.playground/Contents.swift | 20 +++++++++---------- .../Sources/SetCover.swift | 2 +- Set Cover (Unweighted)/SetCover.swift | 2 +- 4 files changed, 21 insertions(+), 15 deletions(-) diff --git a/Set Cover (Unweighted)/README.markdown b/Set Cover (Unweighted)/README.markdown index 48b5f3bfa..fde032438 100644 --- a/Set Cover (Unweighted)/README.markdown +++ b/Set Cover (Unweighted)/README.markdown @@ -10,16 +10,22 @@ For example, suppose you have a universe of `{1, 5, 7}` and you want to find the > {2} > {1, 2, 3} -You can see that the sets `{3, 1} {7, 6, 5, 4}` when unioned together will cover the universe of `{1, 5, 7}`. Yes, there may be additional elements in the sets returned by the algorithm, but every element in the universe is represented. +You can see that the sets `{3, 1} {7, 6, 5, 4}` when unioned together will cover the universe of `{1, 5, 7}`. Yes, there may be additional elements in the sets returned by the algorithm, but every element in the universe is represented in the cover itself. -If there is no cover within the group of sets, the function returns nil. For example, if your universe is `{7, 9}`, there is no combination of sets within the grouping above that will yield a cover. +There may be cases where no cover exists. For example, if your universe is `{7, 9}`, there is no combination of sets within the group above that will yield a cover. ## The algorithm -The Greedy Set Cover algorithm (unweighted) is provided here. It's known as greedy because it uses the largest intersecting set from the group of sets first before examining other sets in the group. +The Greedy Set Cover algorithm (unweighted) is provided here. It's known as greedy because it uses the largest intersecting set from the group of sets first before examining other sets in the group. This is part of the reason why the cover may have additional elements which are not part of the universe. The function (named `cover`) is provided as an extension of the Swift type `Set`. The function takes a single parameter, which is an array of sets. This array represents the group, and the set itself represents the universe. +One of the first things done in `cover` is to make a copy of the universe in `remainingSet`. Then, the algorithm enters a `while` loop in which a call to `largestIntersectingSet` is made. The value returned from `largestIntersectingSet` is the set which has the most elements in common with the remaining universe identified by `remainingSet`. If all sets have nothing in common, `largestIntersectingSet` returns `nil`. + +If the result from `largestIntersectingSet` is not nil, that result is subtracted from `remainingSet` (reducing its size), and the loop continues until `remainingSet` has zero length (meaning a cover has been found) or until `largestIntersectingSet` returns `nil`. + +If there is no cover within the group of sets, `cover` returns `nil`. + ## See also [Set cover problem on Wikipedia](https://en.wikipedia.org/wiki/Set_cover_problem) diff --git a/Set Cover (Unweighted)/SetCover.playground/Contents.swift b/Set Cover (Unweighted)/SetCover.playground/Contents.swift index 3822f16e3..6fac33e6d 100644 --- a/Set Cover (Unweighted)/SetCover.playground/Contents.swift +++ b/Set Cover (Unweighted)/SetCover.playground/Contents.swift @@ -1,31 +1,31 @@ let universe1 = Set(1...7) let array1 = randomArrayOfSets(covering: universe1) -let cover1 = universe1.cover(from: array1) +let cover1 = universe1.cover(within: array1) let universe2 = Set(1...10) let array2: Array> = [[1,2,3,4,5,6,7], [8,9]] -let cover2 = universe2.cover(from: array2) +let cover2 = universe2.cover(within: array2) let universe3 = Set(["tall", "heavy"]) let array3: Array> = [["tall", "light"], ["short", "heavy"], ["tall", "heavy", "young"]] -let cover3 = universe3.cover(from: array3) +let cover3 = universe3.cover(within: array3) let universe4 = Set(["tall", "heavy", "green"]) -let cover4 = universe4.cover(from: array3) +let cover4 = universe4.cover(within: array3) let universe5: Set = [16, 32, 64] let array5: Array> = [[16,17,18], [16,32,128], [1,2,3], [32,64,128]] -let cover5 = universe5.cover(from: array5) +let cover5 = universe5.cover(within: array5) let universe6: Set = [24, 89, 132, 90, 22] let array6 = randomArrayOfSets(covering: universe6) -let cover6 = universe6.cover(from: array6) +let cover6 = universe6.cover(within: array6) let universe7: Set = ["fast", "cheap", "good"] let array7 = randomArrayOfSets(covering: universe7, minArraySizeFactor: 20.0, maxSetSizeFactor: 0.7) -let cover7 = universe7.cover(from: array7) +let cover7 = universe7.cover(within: array7) let emptySet = Set() -let coverTest1 = emptySet.cover(from: array1) -let coverTest2 = universe1.cover(from: Array>()) -let coverTest3 = emptySet.cover(from: Array>()) \ No newline at end of file +let coverTest1 = emptySet.cover(within: array1) +let coverTest2 = universe1.cover(within: Array>()) +let coverTest3 = emptySet.cover(within: Array>()) diff --git a/Set Cover (Unweighted)/SetCover.playground/Sources/SetCover.swift b/Set Cover (Unweighted)/SetCover.playground/Sources/SetCover.swift index 8e608cb52..c739a595a 100644 --- a/Set Cover (Unweighted)/SetCover.playground/Sources/SetCover.swift +++ b/Set Cover (Unweighted)/SetCover.playground/Sources/SetCover.swift @@ -1,5 +1,5 @@ public extension Set { - func cover(from array: Array>) -> Array>? { + func cover(within array: Array>) -> Array>? { var result: [Set]? = [Set]() var remainingSet = self diff --git a/Set Cover (Unweighted)/SetCover.swift b/Set Cover (Unweighted)/SetCover.swift index 58ffade9d..587da4d9d 100644 --- a/Set Cover (Unweighted)/SetCover.swift +++ b/Set Cover (Unweighted)/SetCover.swift @@ -1,5 +1,5 @@ extension Set { - func cover(from array: Array>) -> Array>? { + func cover(within array: Array>) -> Array>? { var result: [Set]? = [Set]() var remainingSet = self From f81304b29683e25e6b8947c5f96ab124ff1bbf97 Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Sun, 26 Jun 2016 17:15:23 -0700 Subject: [PATCH 0416/1679] Fixed some typos --- B-Tree/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/B-Tree/README.md b/B-Tree/README.md index 0a25c44c3..28b617ca1 100644 --- a/B-Tree/README.md +++ b/B-Tree/README.md @@ -7,7 +7,7 @@ A B-Tree is a self-balancing search tree, in which nodes can have more than two A B-Tree of order *n* satisfies the following properties: - Every node has at most *2n* keys. - Every node (except root) has at least *n* keys. - - Eyery non-leaf node with *k* keys has *k+1* children. + - Every non-leaf node with *k* keys has *k+1* children. - The keys in all nodes are sorted in increasing order. - The subtree between two keys *k* and *l* of a non-leaf node contains all the keys between *k* and *l*. - All leaves appear at the same level. @@ -47,10 +47,10 @@ This is necessary because nodes have to know the order of the tree. or reach the end of the array. 3. If `k == l` then we have found the key. 4. If `k < l`: - - If the node we are on is not a leaf, then we go to the left child of `l`, and perform the steps 3.-5. again. + - If the node we are on is not a leaf, then we go to the left child of `l`, and perform the steps 3 - 5 again. - If we are on a leaf, then `k` is not in the tree. 5. If we have reached the end of the array: - - If we are on a non-leaf node, then we go to the last child of the node, and perform the steps 3.-5. again. + - If we are on a non-leaf node, then we go to the last child of the node, and perform the steps 3 - 5 again. - If we are on a leaf, then `k` is not in the tree. ### The code From d680e0648f07e5ddf8912d5fa2bc845ba25ec18e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viktor=20Szil=C3=A1rd=20Viktor?= Date: Mon, 27 Jun 2016 09:35:56 +0200 Subject: [PATCH 0417/1679] Fixed link to B-Tree in README.md --- README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.markdown b/README.markdown index d36aec465..c125742fc 100644 --- a/README.markdown +++ b/README.markdown @@ -152,7 +152,7 @@ Most of the time using just the built-in `Array`, `Dictionary`, and `Set` types - [Heap](Heap/). A binary tree stored in an array, so it doesn't use pointers. Makes a great priority queue. - Fibonacci Heap - Trie -- B-Tree +- [B-Tree](B-Tree/). A self-balancing search tree, in which nodes can have more than two children. ### Hashing From 1da67165b48b33ff421fd8dfd2ac9883e5bdb83e Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Mon, 27 Jun 2016 21:17:12 -0700 Subject: [PATCH 0418/1679] Altered the tree diagram so that one of the leafs is actually labeled as a leaf rather than a node --- Tree/Images/Tree.png | Bin 19207 -> 21989 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/Tree/Images/Tree.png b/Tree/Images/Tree.png index 751dac2e33741afc1489102e8dcd1642f018360b..59ef800cbac28467b3ebcd9d5e51e0b2eec4f09f 100644 GIT binary patch literal 21989 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 Date: Tue, 28 Jun 2016 16:09:53 +0200 Subject: [PATCH 0419/1679] Removing swiftlint warnings from Set Cover (Unweighted) --- .../SetCover.playground/Contents.swift | 4 ++-- .../Sources/RandomArrayOfSets.swift | 14 +++++++------- .../SetCover.playground/Sources/SetCover.swift | 14 +++++++------- Set Cover (Unweighted)/SetCover.swift | 14 +++++++------- 4 files changed, 23 insertions(+), 23 deletions(-) diff --git a/Set Cover (Unweighted)/SetCover.playground/Contents.swift b/Set Cover (Unweighted)/SetCover.playground/Contents.swift index 6fac33e6d..dcf998a66 100644 --- a/Set Cover (Unweighted)/SetCover.playground/Contents.swift +++ b/Set Cover (Unweighted)/SetCover.playground/Contents.swift @@ -3,7 +3,7 @@ let array1 = randomArrayOfSets(covering: universe1) let cover1 = universe1.cover(within: array1) let universe2 = Set(1...10) -let array2: Array> = [[1,2,3,4,5,6,7], [8,9]] +let array2: Array> = [[1, 2, 3, 4, 5, 6, 7], [8, 9]] let cover2 = universe2.cover(within: array2) let universe3 = Set(["tall", "heavy"]) @@ -14,7 +14,7 @@ let universe4 = Set(["tall", "heavy", "green"]) let cover4 = universe4.cover(within: array3) let universe5: Set = [16, 32, 64] -let array5: Array> = [[16,17,18], [16,32,128], [1,2,3], [32,64,128]] +let array5: Array> = [[16, 17, 18], [16, 32, 128], [1, 2, 3], [32, 64, 128]] let cover5 = universe5.cover(within: array5) let universe6: Set = [24, 89, 132, 90, 22] diff --git a/Set Cover (Unweighted)/SetCover.playground/Sources/RandomArrayOfSets.swift b/Set Cover (Unweighted)/SetCover.playground/Sources/RandomArrayOfSets.swift index 64253014b..b64d8d70e 100644 --- a/Set Cover (Unweighted)/SetCover.playground/Sources/RandomArrayOfSets.swift +++ b/Set Cover (Unweighted)/SetCover.playground/Sources/RandomArrayOfSets.swift @@ -5,17 +5,17 @@ public func randomArrayOfSets(covering universe: Set, maxSetSizeFactor: Double = 0.6) -> Array> { var result = [Set]() var ongoingUnion = Set() - + let minArraySize = Int(Double(universe.count) * minArraySizeFactor) var maxSetSize = Int(Double(universe.count) * maxSetSizeFactor) if maxSetSize > universe.count { maxSetSize = universe.count } - + while true { var generatedSet = Set() let targetSetSize = Int(arc4random_uniform(UInt32(maxSetSize)) + 1) - + while true { let randomUniverseIndex = Int(arc4random_uniform(UInt32(universe.count))) for (setIndex, value) in universe.enumerate() { @@ -24,20 +24,20 @@ public func randomArrayOfSets(covering universe: Set, break } } - + if generatedSet.count == targetSetSize { result.append(generatedSet) ongoingUnion = ongoingUnion.union(generatedSet) break } } - + if result.count >= minArraySize { if ongoingUnion == universe { break } } } - + return result -} \ No newline at end of file +} diff --git a/Set Cover (Unweighted)/SetCover.playground/Sources/SetCover.swift b/Set Cover (Unweighted)/SetCover.playground/Sources/SetCover.swift index c739a595a..0e93caf0b 100644 --- a/Set Cover (Unweighted)/SetCover.playground/Sources/SetCover.swift +++ b/Set Cover (Unweighted)/SetCover.playground/Sources/SetCover.swift @@ -2,11 +2,11 @@ public extension Set { func cover(within array: Array>) -> Array>? { var result: [Set]? = [Set]() var remainingSet = self - + func largestIntersectingSet() -> Set? { var largestIntersectionLength = 0 var largestSet: Set? - + for set in array { let intersectionLength = remainingSet.intersect(set).count if intersectionLength > largestIntersectionLength { @@ -14,20 +14,20 @@ public extension Set { largestSet = set } } - + return largestSet } - + while remainingSet.count != 0 { guard let largestSet = largestIntersectingSet() else { break } result!.append(largestSet) remainingSet = remainingSet.subtract(largestSet) } - + if remainingSet.count != 0 || self.count == 0 { result = nil } - + return result } -} \ No newline at end of file +} diff --git a/Set Cover (Unweighted)/SetCover.swift b/Set Cover (Unweighted)/SetCover.swift index 587da4d9d..86be6729b 100644 --- a/Set Cover (Unweighted)/SetCover.swift +++ b/Set Cover (Unweighted)/SetCover.swift @@ -2,11 +2,11 @@ extension Set { func cover(within array: Array>) -> Array>? { var result: [Set]? = [Set]() var remainingSet = self - + func largestIntersectingSet() -> Set? { var largestIntersectionLength = 0 var largestSet: Set? - + for set in array { let intersectionLength = remainingSet.intersect(set).count if intersectionLength > largestIntersectionLength { @@ -14,20 +14,20 @@ extension Set { largestSet = set } } - + return largestSet } - + while remainingSet.count != 0 { guard let largestSet = largestIntersectingSet() else { break } result!.append(largestSet) remainingSet = remainingSet.subtract(largestSet) } - + if remainingSet.count != 0 || self.count == 0 { result = nil } - + return result } -} \ No newline at end of file +} From 31935d9ac62b7ad4d3a8464d855211cf29ece79e Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Tue, 28 Jun 2016 17:07:39 +0200 Subject: [PATCH 0420/1679] Set cover (unweighted) - replacing count = 0 conditions with isEmpty --- .../SetCover.playground/Sources/SetCover.swift | 4 ++-- .../playground.xcworkspace/contents.xcworkspacedata | 7 +++++++ Set Cover (Unweighted)/SetCover.swift | 4 ++-- 3 files changed, 11 insertions(+), 4 deletions(-) create mode 100644 Set Cover (Unweighted)/SetCover.playground/playground.xcworkspace/contents.xcworkspacedata diff --git a/Set Cover (Unweighted)/SetCover.playground/Sources/SetCover.swift b/Set Cover (Unweighted)/SetCover.playground/Sources/SetCover.swift index 0e93caf0b..8d40e1fda 100644 --- a/Set Cover (Unweighted)/SetCover.playground/Sources/SetCover.swift +++ b/Set Cover (Unweighted)/SetCover.playground/Sources/SetCover.swift @@ -18,13 +18,13 @@ public extension Set { return largestSet } - while remainingSet.count != 0 { + while !remainingSet.isEmpty { guard let largestSet = largestIntersectingSet() else { break } result!.append(largestSet) remainingSet = remainingSet.subtract(largestSet) } - if remainingSet.count != 0 || self.count == 0 { + if !remainingSet.isEmpty || isEmpty { result = nil } diff --git a/Set Cover (Unweighted)/SetCover.playground/playground.xcworkspace/contents.xcworkspacedata b/Set Cover (Unweighted)/SetCover.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Set Cover (Unweighted)/SetCover.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Set Cover (Unweighted)/SetCover.swift b/Set Cover (Unweighted)/SetCover.swift index 86be6729b..d67dfbfa9 100644 --- a/Set Cover (Unweighted)/SetCover.swift +++ b/Set Cover (Unweighted)/SetCover.swift @@ -18,13 +18,13 @@ extension Set { return largestSet } - while remainingSet.count != 0 { + while !remainingSet.isEmpty { guard let largestSet = largestIntersectingSet() else { break } result!.append(largestSet) remainingSet = remainingSet.subtract(largestSet) } - if remainingSet.count != 0 || self.count == 0 { + if !remainingSet.isEmpty || isEmpty { result = nil } From dfec36d031bfaa1e861da559498a4ebd6b367364 Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Tue, 28 Jun 2016 17:09:33 +0200 Subject: [PATCH 0421/1679] Set cover (unweighted) - adding link on under construction page --- Under Construction.markdown | 1 + 1 file changed, 1 insertion(+) diff --git a/Under Construction.markdown b/Under Construction.markdown index 95ead4218..555d778e6 100644 --- a/Under Construction.markdown +++ b/Under Construction.markdown @@ -28,3 +28,4 @@ Special-purpose sorts: - [Minimum Edit Distance](Minimum Edit Distance/). Measure the similarity of two strings by counting the number of operations required to transform one string into the other. - [Treap](Treap/) +- [Set Cover (Unweighted)][Set Cover (Unweighted)/] From 824d06c19cddd5855e36e7ee3239ddd5c09d93b6 Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Tue, 28 Jun 2016 17:10:50 +0200 Subject: [PATCH 0422/1679] Set cover (unweighted) - adding link on under construction page --- Under Construction.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Under Construction.markdown b/Under Construction.markdown index 555d778e6..0c59d90c1 100644 --- a/Under Construction.markdown +++ b/Under Construction.markdown @@ -28,4 +28,4 @@ Special-purpose sorts: - [Minimum Edit Distance](Minimum Edit Distance/). Measure the similarity of two strings by counting the number of operations required to transform one string into the other. - [Treap](Treap/) -- [Set Cover (Unweighted)][Set Cover (Unweighted)/] +- [Set Cover (Unweighted)](Set Cover (Unweighted)/) From 912c21d455aa7cda0579d9ffc68bdb211b5cfdee Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Thu, 30 Jun 2016 10:50:21 -0700 Subject: [PATCH 0423/1679] Fixed a typo in the main readme markdown file --- README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.markdown b/README.markdown index c125742fc..b1947a6c8 100644 --- a/README.markdown +++ b/README.markdown @@ -214,7 +214,7 @@ The Swift Algorithm Club was originally created by [Matthijs Hollemans](https:// It is now maintained by [Chris Pilcher](https://github.com/chris-pilcher) and [Kelvin Lau](https://github.com/kelvinlauKL). -The Swift Algorithm Club is a a collaborative effort from the [most algorithmic members](https://github.com/rwenderlich/swift-algorithm-club/graphs/contributors) of the [raywenderlich.com](https://www.raywenderlich.com) community. We're always looking for help - why not [join the club](How to Contribute.markdown)? :] +The Swift Algorithm Club is a collaborative effort from the [most algorithmic members](https://github.com/rwenderlich/swift-algorithm-club/graphs/contributors) of the [raywenderlich.com](https://www.raywenderlich.com) community. We're always looking for help - why not [join the club](How to Contribute.markdown)? :] ## License From c77a74803bc87a59cfac94f9bda8a5291b68ba68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andre=CC=81s=20Pesate?= Date: Fri, 1 Jul 2016 15:30:58 +0200 Subject: [PATCH 0424/1679] Added preconditions to subscript to avoid unwanted changes or crashes. --- Array2D/Array2D.swift | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Array2D/Array2D.swift b/Array2D/Array2D.swift index ca84275f3..6177974d7 100644 --- a/Array2D/Array2D.swift +++ b/Array2D/Array2D.swift @@ -19,6 +19,9 @@ public struct Array2D { return array[row*columns + column] } set { + precondition(row < rows, "Row \(row) Index is out of range. Array(columns: \(columns), rows:\(rows))") + precondition(column < columns, "Column \(column) Index is out of range. Array(columns: \(columns), rows:\(rows))") + array[row*columns + column] = newValue } } From 358ea45332f92c6d2a29d64c7c786a0acf1784da Mon Sep 17 00:00:00 2001 From: Stephen Rutstein Date: Wed, 13 Jul 2016 23:20:12 -0500 Subject: [PATCH 0425/1679] Palindromes swift file, playground, and README file added --- .../Palindromes.playground/Contents.swift | 36 +++++++++++ .../contents.xcplayground | 4 ++ Palindromes/Palindromes.swift | 21 ++++++ Palindromes/README.markdown | 64 +++++++++++++++++++ 4 files changed, 125 insertions(+) create mode 100644 Palindromes/Palindromes.playground/Contents.swift create mode 100644 Palindromes/Palindromes.playground/contents.xcplayground create mode 100644 Palindromes/Palindromes.swift create mode 100644 Palindromes/README.markdown diff --git a/Palindromes/Palindromes.playground/Contents.swift b/Palindromes/Palindromes.playground/Contents.swift new file mode 100644 index 000000000..c89231d09 --- /dev/null +++ b/Palindromes/Palindromes.playground/Contents.swift @@ -0,0 +1,36 @@ +import Cocoa + +public func palindromeCheck (text: String?) -> Bool { + if let text = text { + let mutableText = text.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceCharacterSet()).lowercaseString + let length: Int = mutableText.characters.count + + if length < 1 { + return false + } + + if length == 1 { + return true + } else if mutableText[mutableText.startIndex] == mutableText[mutableText.endIndex.predecessor()] { + let range = Range(mutableText.startIndex.successor().. + + + \ No newline at end of file diff --git a/Palindromes/Palindromes.swift b/Palindromes/Palindromes.swift new file mode 100644 index 000000000..96269fe23 --- /dev/null +++ b/Palindromes/Palindromes.swift @@ -0,0 +1,21 @@ +import Cocoa + +public func palindromeCheck (text: String?) -> Bool { + if let text = text { + let mutableText = text.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceCharacterSet()).lowercaseString + let length: Int = mutableText.characters.count + + if length < 1 { + return false + } + + if length == 1 { + return true + } else if mutableText[mutableText.startIndex] == mutableText[mutableText.endIndex.predecessor()] { + let range = Range(mutableText.startIndex.successor().. Bool { + if let text = text { + let mutableText = text.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceCharacterSet()).lowercaseString + let length: Int = mutableText.characters.count + + if length < 1 { + return false + } + + if length == 1 { + return true + } else if mutableText[mutableText.startIndex] == mutableText[mutableText.endIndex.predecessor()] { + let range = Range(mutableText.startIndex.successor().. Date: Wed, 13 Jul 2016 23:24:07 -0500 Subject: [PATCH 0426/1679] Updated README --- Palindromes/README.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Palindromes/README.markdown b/Palindromes/README.markdown index d27605ed4..a595408ca 100644 --- a/Palindromes/README.markdown +++ b/Palindromes/README.markdown @@ -25,7 +25,7 @@ original String. Here is a recursive implementation of this in Swift: -``swift +```swift func palindromeCheck (text: String?) -> Bool { if let text = text { let mutableText = text.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceCharacterSet()).lowercaseString @@ -45,7 +45,7 @@ func palindromeCheck (text: String?) -> Bool { return false } -`` +``` This code can be tested in a playground using the following: From 58c0128fb7d1235ae39ad23782db76543fe65fe8 Mon Sep 17 00:00:00 2001 From: srutstein21 Date: Wed, 13 Jul 2016 23:25:13 -0500 Subject: [PATCH 0427/1679] Updating markdown format for README --- Palindromes/README.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Palindromes/README.markdown b/Palindromes/README.markdown index a595408ca..a0696ff93 100644 --- a/Palindromes/README.markdown +++ b/Palindromes/README.markdown @@ -50,9 +50,9 @@ func palindromeCheck (text: String?) -> Bool { This code can be tested in a playground using the following: -``swift +```swift palindromeCheck("Race car") -`` +``` Since the phrase "Race car" is a palindrome, this will return true. From d67c81f1f82bec733a60e8819539c7b4781b32e2 Mon Sep 17 00:00:00 2001 From: lionel0806 Date: Thu, 14 Jul 2016 23:27:11 +0800 Subject: [PATCH 0428/1679] Processing index out of bounds --- Heap/Heap.swift | 4 ++++ Heap/Tests/HeapTests.swift | 11 +++++++++++ 2 files changed, 15 insertions(+) diff --git a/Heap/Heap.swift b/Heap/Heap.swift index 64bd90cd8..bf7031abe 100644 --- a/Heap/Heap.swift +++ b/Heap/Heap.swift @@ -112,6 +112,8 @@ public struct Heap { * larger than the old one; in a min-heap it should be smaller. */ public mutating func replace(index i: Int, value: T) { + guard i < elements.count else { return } + assert(isOrderedBefore(value, elements[i])) elements[i] = value shiftUp(index: i) @@ -141,6 +143,8 @@ public struct Heap { * to know the node's index, which may actually take O(n) steps to find. */ public mutating func removeAtIndex(i: Int) -> T? { + guard i < elements.count else { return nil } + let size = elements.count - 1 if i != size { swap(&elements[i], &elements[size]) diff --git a/Heap/Tests/HeapTests.swift b/Heap/Tests/HeapTests.swift index ec17560a5..6178a8094 100644 --- a/Heap/Tests/HeapTests.swift +++ b/Heap/Tests/HeapTests.swift @@ -196,6 +196,12 @@ class HeapTests: XCTestCase { XCTAssertTrue(verifyMaxHeap(h)) XCTAssertEqual(h.elements, [100, 50, 70, 10, 20, 60, 65]) + //test index out of bounds + let v = h.removeAtIndex(10) + XCTAssertEqual(v, nil) + XCTAssertTrue(verifyMaxHeap(h)) + XCTAssertEqual(h.elements, [100, 50, 70, 10, 20, 60, 65]) + let v1 = h.removeAtIndex(5) XCTAssertEqual(v1, 60) XCTAssertTrue(verifyMaxHeap(h)) @@ -308,5 +314,10 @@ class HeapTests: XCTestCase { h.replace(index: 5, value: 13) XCTAssertTrue(verifyMaxHeap(h)) XCTAssertEqual(h.elements, [16, 14, 13, 8, 7, 10, 3, 2, 4, 1]) + + //test index out of bounds + h.replace(index: 20, value: 2) + XCTAssertTrue(verifyMaxHeap(h)) + XCTAssertEqual(h.elements, [16, 14, 13, 8, 7, 10, 3, 2, 4, 1]) } } From 5524ef40ca461c445e40952011560fee391f414f Mon Sep 17 00:00:00 2001 From: Lukas Schramm Date: Sat, 16 Jul 2016 17:41:37 +0200 Subject: [PATCH 0429/1679] Added SlowSort --- Slow Sort/README.markdown | 50 +++++++++++++++++++ Slow Sort/SlowSort.swift | 28 +++++++++++ .../contents.xcworkspacedata | 7 +++ 3 files changed, 85 insertions(+) create mode 100644 Slow Sort/README.markdown create mode 100644 Slow Sort/SlowSort.swift diff --git a/Slow Sort/README.markdown b/Slow Sort/README.markdown new file mode 100644 index 000000000..f8cc743cc --- /dev/null +++ b/Slow Sort/README.markdown @@ -0,0 +1,50 @@ +# Slow Sort + +Goal: Sort an array of numbers from low to high (or high to low). + +You are given an array of numbers and need to put them in the right order. The insertion sort algorithm works as follows: + +We can decompose the problem of sorting n numbers in ascending order into + +1. find the maximum of the numbers + 1. find the maximum of the first n/2 elements + 2. find the maximum of the remaining n/2 elements + 3. find the largest of those two maxima +2. sorting the remaining ones + +## The code + +Here is an implementation of slow sort in Swift: + +```swift +public func slowsort(_ i: Int, _ j: Int) { + if i>=j { + return + } + let m = (i+j)/2 + slowsort(i,m) + slowsort(m+1,j) + if numberList[j] < numberList[m] { + let temp = numberList[j] + numberList[j] = numberList[m] + numberList[m] = temp + } + slowsort(i,j-1) +} +``` + +## Performance + +| Case | Performance | +|:-------------: |:---------------:| +| Worst | slow | +| Best | O(n^(log(n)/(2+e)))) | +| Average | O(n^(log(n)/2)) | + +## See also + +[Slow Sort explanation in the Internet](http://c2.com/cgi/wiki?SlowSort) + +*Written for Swift Algorithm Club by Lukas Schramm* + +(used the Insertion Sort Readme as template) \ No newline at end of file diff --git a/Slow Sort/SlowSort.swift b/Slow Sort/SlowSort.swift new file mode 100644 index 000000000..c21a77fd8 --- /dev/null +++ b/Slow Sort/SlowSort.swift @@ -0,0 +1,28 @@ +// +// SlowSort.swift +// +// +// Created by Pope Lukas Schramm (Dabendorf Orthodox Religion) on 16-07-16. +// +// + +var numberList = [1,12,9,17,13,12] + +public func slowsort(_ i: Int, _ j: Int) { + if i>=j { + return + } + let m = (i+j)/2 + slowsort(i,m) + slowsort(m+1,j) + if numberList[j] < numberList[m] { + let temp = numberList[j] + numberList[j] = numberList[m] + numberList[m] = temp + } + slowsort(i,j-1) +} + + +slowsort(0,numberList.count-1) +print(numberList) diff --git a/swift-algorithm-club.xcworkspace/contents.xcworkspacedata b/swift-algorithm-club.xcworkspace/contents.xcworkspacedata index 4e0f19dc2..3feeaa5c2 100644 --- a/swift-algorithm-club.xcworkspace/contents.xcworkspacedata +++ b/swift-algorithm-club.xcworkspace/contents.xcworkspacedata @@ -1019,6 +1019,13 @@ + + + + From 185e7caab77acdb6ae830f17ed1ab9ce6774d78b Mon Sep 17 00:00:00 2001 From: Stephen Rutstein Date: Sun, 17 Jul 2016 00:59:48 -0500 Subject: [PATCH 0430/1679] Added files for Comb Sort --- Comb Sort/Comb Sort.playground/Contents.swift | 50 ++++++++++++ .../contents.xcplayground | 4 + .../contents.xcworkspacedata | 7 ++ Comb Sort/Comb Sort.swift | 36 +++++++++ Comb Sort/README.markdown | 78 +++++++++++++++++++ 5 files changed, 175 insertions(+) create mode 100644 Comb Sort/Comb Sort.playground/Contents.swift create mode 100644 Comb Sort/Comb Sort.playground/contents.xcplayground create mode 100644 Comb Sort/Comb Sort.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 Comb Sort/Comb Sort.swift create mode 100644 Comb Sort/README.markdown diff --git a/Comb Sort/Comb Sort.playground/Contents.swift b/Comb Sort/Comb Sort.playground/Contents.swift new file mode 100644 index 000000000..3bc03546a --- /dev/null +++ b/Comb Sort/Comb Sort.playground/Contents.swift @@ -0,0 +1,50 @@ +// Comb Sort Function +// Created by Stephen Rutstein +// 7-16-2016 + +import Cocoa + +func combSort (input: [Int]) -> [Int] { + var copy: [Int] = input + var gap = copy.count + let shrink = 1.3 + + while gap > 1 { + gap = (Int)(Double(gap) / shrink) + if gap < 1 { + gap = 1 + } + + var index = 0 + while !(index + gap >= copy.count) { + if copy[index] > copy[index + gap] { + swap(©[index], ©[index + gap]) + } + index += 1 + } + } + return copy +} + +// A function to swap two integer values +// Used for swapping within the array of values. +func swap (inout a: Int, inout b: Int) { + let temp = a + a = b + b = temp +} + +// Test Comb Sort with small array of ten values +let array: [Int] = [2, 32, 9, -1, 89, 101, 55, -10, -12, 67] +combSort(array) + +// Test Comb Sort with large array of 1000 random values +var bigArray = [Int](count: 1000, repeatedValue: 0) +var i = 0 +while i < 1000 { + bigArray[i] = Int(arc4random_uniform(1000) + 1) + i += 1 +} +combSort(bigArray) + + diff --git a/Comb Sort/Comb Sort.playground/contents.xcplayground b/Comb Sort/Comb Sort.playground/contents.xcplayground new file mode 100644 index 000000000..06828af92 --- /dev/null +++ b/Comb Sort/Comb Sort.playground/contents.xcplayground @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Comb Sort/Comb Sort.playground/playground.xcworkspace/contents.xcworkspacedata b/Comb Sort/Comb Sort.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Comb Sort/Comb Sort.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Comb Sort/Comb Sort.swift b/Comb Sort/Comb Sort.swift new file mode 100644 index 000000000..7abba8c7f --- /dev/null +++ b/Comb Sort/Comb Sort.swift @@ -0,0 +1,36 @@ +// Comb Sort.swift +// Comb Sort +// +// Created by Stephen.Rutstein on 7/16/16. +// Copyright © 2016 Stephen.Rutstein. All rights reserved. +// + +import Foundation + +func combSort (input: [Int]) -> [Int] { + var copy: [Int] = input + var gap = copy.count + let shrink = 1.3 + + while gap > 1 { + gap = (Int)(Double(gap) / shrink) + if gap < 1 { + gap = 1 + } + + var index = 0 + while !(index + gap >= copy.count) { + if copy[index] > copy[index + gap] { + swap(©[index], ©[index + gap]) + } + index += 1 + } + } + return copy +} + +func swap (inout a: Int, inout b: Int) { + let temp = a + a = b + b = temp +} diff --git a/Comb Sort/README.markdown b/Comb Sort/README.markdown new file mode 100644 index 000000000..fedbc5705 --- /dev/null +++ b/Comb Sort/README.markdown @@ -0,0 +1,78 @@ +# Comb Sort + +A common issue for Bubble Sort is when small values are located near the end of an array. +This problem severely slows down Bubble Sort, as it must move the small value -- or _turtle_ -- +through nearly the entire array. Bubble Sort works by checking the current index of an array +against the next index, and when those two values are unsorted, they are swapped into place. +As a result, the values bubble into their rightful place within the array. + +Comb Sort improves upon Bubble Sort by dealing with these turtles near the end of the array. +The value of the current index of the array is compared against one a set distance away. This +removes a worst-case scenario of Bubble Sort, and greatly improves on the time complexity of Bubble Sort. + +## Example + +A step-by-step example of how Comb Sort works, and differs from Bubble Sort, can be seen [here](http://www.exforsys.com/tutorials/c-algorithms/comb-sort.html). + +Here is a visual to see Comb Sort in effect: +![](https://upload.wikimedia.org/wikipedia/commons/4/46/Comb_sort_demo.gif) + +## Algorithm + +Similar to Bubble Sort, two values within an array are compared. When the lower index value +is larger than the higher index value, and thus out of place within the array, they are +swapped. Unlike Bubble Sort, the value being compared against is a set distance away. This +value -- the _gap_ -- is slowly decreased through iterations. + +## The Code + +Here is a Swift implementation of Comb Sort: + +```swift +func combSort (input: [Int]) -> [Int] { + var copy: [Int] = input + var gap = copy.count + let shrink = 1.3 + + while gap > 1 { + gap = (Int)(Double(gap) / shrink) + if gap < 1 { + gap = 1 + } + + var index = 0 + while !(index + gap >= copy.count) { + if copy[index] > copy[index + gap] { + swap(©[index], ©[index + gap]) + } + index += 1 + } + } + return copy +} +``` + +This code can be tested in a playground by calling this method with a paramaterized array to sort: + +```swift +combSort(example_array_of_values) +``` + +This will sort the values of the array into ascending order -- increasing in value. + +## Performance + +Comb Sort was created to improve upon the worst case time complexity of Bubble Sort. With Comb +Sort, the worst case scenario for performance is exponential -- O(n^2). At best though, Comb Sort +performs at O(n logn) time complexity. This creates a drastic improvement over Bubble Sort's performance. + +Similar to Bubble Sort, the space complexity for Comb Sort is constant -- O(1). +This is extremely space efficient as it sorts the array in place. + + +## Additional Resources + +[Comb Sort Wikipedia](https://en.wikipedia.org/wiki/Comb_sort) + + +*Written for the _Swift Algorithm Club_ by [Stephen Rutstein](https://github.com/srutstein21)* From 0951ea332ec1ec7b8e700321d1558fd1ea4b35bc Mon Sep 17 00:00:00 2001 From: Stephen Rutstein Date: Sun, 17 Jul 2016 01:03:35 -0500 Subject: [PATCH 0431/1679] Quick change to the read me file to fix spacing --- Comb Sort/README.markdown | 1 + 1 file changed, 1 insertion(+) diff --git a/Comb Sort/README.markdown b/Comb Sort/README.markdown index fedbc5705..d30d429b3 100644 --- a/Comb Sort/README.markdown +++ b/Comb Sort/README.markdown @@ -15,6 +15,7 @@ removes a worst-case scenario of Bubble Sort, and greatly improves on the time c A step-by-step example of how Comb Sort works, and differs from Bubble Sort, can be seen [here](http://www.exforsys.com/tutorials/c-algorithms/comb-sort.html). Here is a visual to see Comb Sort in effect: + ![](https://upload.wikimedia.org/wikipedia/commons/4/46/Comb_sort_demo.gif) ## Algorithm From ab2d1a2c7c4017c0c3a37011abe82883ba9a565f Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Sun, 17 Jul 2016 08:49:31 -0700 Subject: [PATCH 0432/1679] Tweaks to palindrome article. Linked up Palindrome alg on front page --- Palindromes/Palindromes.playground/Contents.swift | 4 ++-- .../playground.xcworkspace/contents.xcworkspacedata | 7 +++++++ Palindromes/Palindromes.swift | 4 ++-- Palindromes/README.markdown | 4 ++-- README.markdown | 1 + 5 files changed, 14 insertions(+), 6 deletions(-) create mode 100644 Palindromes/Palindromes.playground/playground.xcworkspace/contents.xcworkspacedata diff --git a/Palindromes/Palindromes.playground/Contents.swift b/Palindromes/Palindromes.playground/Contents.swift index c89231d09..b548182af 100644 --- a/Palindromes/Palindromes.playground/Contents.swift +++ b/Palindromes/Palindromes.playground/Contents.swift @@ -2,10 +2,10 @@ import Cocoa public func palindromeCheck (text: String?) -> Bool { if let text = text { - let mutableText = text.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceCharacterSet()).lowercaseString + let mutableText = text.stringByTrimmingCharactersInSet(.whitespaceCharacterSet()).lowercaseString let length: Int = mutableText.characters.count - if length < 1 { + guard length >= 1 else { return false } diff --git a/Palindromes/Palindromes.playground/playground.xcworkspace/contents.xcworkspacedata b/Palindromes/Palindromes.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Palindromes/Palindromes.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Palindromes/Palindromes.swift b/Palindromes/Palindromes.swift index 96269fe23..61e7740ab 100644 --- a/Palindromes/Palindromes.swift +++ b/Palindromes/Palindromes.swift @@ -2,10 +2,10 @@ import Cocoa public func palindromeCheck (text: String?) -> Bool { if let text = text { - let mutableText = text.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceCharacterSet()).lowercaseString + let mutableText = text.stringByTrimmingCharactersInSet(.whitespaceCharacterSet()).lowercaseString let length: Int = mutableText.characters.count - if length < 1 { + guard length >= 1 else { return false } diff --git a/Palindromes/README.markdown b/Palindromes/README.markdown index a0696ff93..3df775e31 100644 --- a/Palindromes/README.markdown +++ b/Palindromes/README.markdown @@ -28,10 +28,10 @@ Here is a recursive implementation of this in Swift: ```swift func palindromeCheck (text: String?) -> Bool { if let text = text { - let mutableText = text.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceCharacterSet()).lowercaseString + let mutableText = text.stringByTrimmingCharactersInSet(.whitespaceCharacterSet()).lowercaseString let length: Int = mutableText.characters.count - if length < 1 { + guard length >= 1 { return false } diff --git a/README.markdown b/README.markdown index b1947a6c8..3d011a178 100644 --- a/README.markdown +++ b/README.markdown @@ -183,6 +183,7 @@ A lot of software developer interview questions consist of algorithmic puzzles. - [Two-Sum Problem](Two-Sum Problem/) - [Fizz Buzz](Fizz Buzz/) - [Monty Hall Problem](Monty Hall Problem/) +- [Finding Palindromes](Palindromes/) ## Learn more! From 790533767da1213c2886ae3f7790b950b14b702d Mon Sep 17 00:00:00 2001 From: jamesharrop Date: Sun, 17 Jul 2016 21:15:17 +0100 Subject: [PATCH 0433/1679] First draft of Linear Regression First draft --- .../Contents.swift | 23 +++++++++++++++++++ .../contents.xcplayground | 4 ++++ .../contents.xcworkspacedata | 7 ++++++ Linear Regression/README.markdown | 19 +++++++++++++++ 4 files changed, 53 insertions(+) create mode 100644 Linear Regression/LinearRegression.playground/Contents.swift create mode 100644 Linear Regression/LinearRegression.playground/contents.xcplayground create mode 100644 Linear Regression/LinearRegression.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 Linear Regression/README.markdown diff --git a/Linear Regression/LinearRegression.playground/Contents.swift b/Linear Regression/LinearRegression.playground/Contents.swift new file mode 100644 index 000000000..2b111ce68 --- /dev/null +++ b/Linear Regression/LinearRegression.playground/Contents.swift @@ -0,0 +1,23 @@ +// Linear Regression + +import Foundation + +let carAge: [Double] = [10, 8, 3, 3, 2, 1] +let carPrice: [Double] = [500, 400, 7000, 8500, 11000, 10500] +var intercept = 10000.0 +var slope = -1000.0 +let alpha = 0.0001 +let numberOfCarAdvertsWeSaw = carPrice.count + +func h(carAge: Double) -> Double { + return intercept + slope * carAge +} + +for n in 1...10000 { + for i in 1...numberOfCarAdvertsWeSaw { + intercept += alpha * (carPrice[i-1] - h(carAge[i-1])) * 1 + slope += alpha * (carPrice[i-1] - h(carAge[i-1])) * carAge[i-1] + } +} + +print("A car age 4 years is predicted to be worth £\(Int(h(4)))") diff --git a/Linear Regression/LinearRegression.playground/contents.xcplayground b/Linear Regression/LinearRegression.playground/contents.xcplayground new file mode 100644 index 000000000..5da2641c9 --- /dev/null +++ b/Linear Regression/LinearRegression.playground/contents.xcplayground @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Linear Regression/LinearRegression.playground/playground.xcworkspace/contents.xcworkspacedata b/Linear Regression/LinearRegression.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Linear Regression/LinearRegression.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Linear Regression/README.markdown b/Linear Regression/README.markdown new file mode 100644 index 000000000..1aa03fbe8 --- /dev/null +++ b/Linear Regression/README.markdown @@ -0,0 +1,19 @@ +# Linear Regression +## First draft version of this document + +Linear regression is a technique for creating a model of the relationship between two (or more) variable quantities. + +For example, let's say we are planning to sell a car. We are not sure how much money to ask for. So we look at recent advertisments for the asking prices of other cars. There are a lot of variables we could look at - for example: make, model, engine size. To simplify our task, we collect data on just the age of the car and the price: + +Age (in years)| Price (in £) +--------------|------------- +10 | 500 +8 | 400 +3 | 7,000 +3 | 8,500 +2 | 11,000 +1 | 10,500 + +Our car is 4 years old. How can we set a price for our car based on the data in this table? + +*Written for Swift Algorithm Club by James Harrop* \ No newline at end of file From 9f96077964cbf5d300888034ccf89bfe3ce44612 Mon Sep 17 00:00:00 2001 From: John Pham Date: Mon, 18 Jul 2016 16:23:19 +0700 Subject: [PATCH 0434/1679] Remove comma at end of array --- Merge Sort/README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Merge Sort/README.markdown b/Merge Sort/README.markdown index 023e18b32..a24c71f2f 100644 --- a/Merge Sort/README.markdown +++ b/Merge Sort/README.markdown @@ -19,7 +19,7 @@ Assume you're given an array of *n* numbers and you need to put them in the righ Let's say the numbers to sort are `[2, 1, 5, 4, 9]`. This is your unsorted pile. The goal is to keep splitting the pile until you can't split anymore. -First, split the array into two halves: `[2, 1,]` and `[5, 4, 9]`. Can you keep splitting them? Yes you can! +First, split the array into two halves: `[2, 1]` and `[5, 4, 9]`. Can you keep splitting them? Yes you can! Focus on the left pile. `[2, 1]` will split into `[2]` and `[1]`. Can you keep splitting them? No. Time to check the other pile. From 236c4e4b632f45e0d487eae168291ca836ed570f Mon Sep 17 00:00:00 2001 From: jamesharrop Date: Fri, 22 Jul 2016 22:03:23 +0100 Subject: [PATCH 0435/1679] Playground and readme file completed --- Linear Regression/Images/graph1.png | Bin 0 -> 22918 bytes Linear Regression/Images/graph2.png | Bin 0 -> 43570 bytes Linear Regression/Images/graph3.png | Bin 0 -> 31467 bytes .../Contents.swift | 47 ++++-- Linear Regression/README.markdown | 149 +++++++++++++++++- 5 files changed, 185 insertions(+), 11 deletions(-) create mode 100644 Linear Regression/Images/graph1.png create mode 100644 Linear Regression/Images/graph2.png create mode 100644 Linear Regression/Images/graph3.png diff --git a/Linear Regression/Images/graph1.png b/Linear Regression/Images/graph1.png new file mode 100644 index 0000000000000000000000000000000000000000..bffe838ef01e2d68a8b00963276fa0dc141e40ea GIT binary patch literal 22918 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 al{H3Ro0f`B&#>T{D19Bn<3(C_fBiR81dewA literal 0 HcmV?d00001 diff --git a/Linear Regression/Images/graph2.png b/Linear Regression/Images/graph2.png new file mode 100644 index 0000000000000000000000000000000000000000..cdb45b1a8ed6355b52ecc1007880860251a9c195 GIT binary patch literal 43570 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 z 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 Double { +func predictedCarPrice(carAge: Double) -> Double { return intercept + slope * carAge } -for n in 1...10000 { - for i in 1...numberOfCarAdvertsWeSaw { - intercept += alpha * (carPrice[i-1] - h(carAge[i-1])) * 1 - slope += alpha * (carPrice[i-1] - h(carAge[i-1])) * carAge[i-1] +// An iterative approach + +let numberOfCarAdvertsWeSaw = carPrice.count - 1 +let numberOfIterations = 100 +let alpha = 0.0001 + +for n in 1...numberOfIterations { + for i in 0...numberOfCarAdvertsWeSaw { + let difference = carPrice[i] - predictedCarPrice(carAge[i]) + intercept += alpha * difference + slope += alpha * difference * carAge[i] } } -print("A car age 4 years is predicted to be worth £\(Int(h(4)))") +print("A car age of 4 years is predicted to be worth £\(Int(predictedCarPrice(4)))") + +// A closed form solution + +func average(input: [Double]) -> Double { + return input.reduce(0, combine: +) / Double(input.count) +} + +func multiply(input1: [Double], _ input2: [Double]) -> [Double] { + return input1.enumerate().map({ (index, element) in return element*input2[index] }) +} + +func linearRegression(xVariable: [Double], _ yVariable: [Double]) -> (Double -> Double) { + let sum1 = average(multiply(xVariable, yVariable)) - average(xVariable) * average(yVariable) + let sum2 = average(multiply(xVariable, xVariable)) - pow(average(xVariable), 2) + let slope = sum1 / sum2 + let intercept = average(yVariable) - slope * average(xVariable) + return { intercept + slope * $0 } +} + +let result = linearRegression(carAge, carPrice)(4) + +print("A car of age 4 years is predicted to be worth £\(Int(result))") diff --git a/Linear Regression/README.markdown b/Linear Regression/README.markdown index 1aa03fbe8..e78514df5 100644 --- a/Linear Regression/README.markdown +++ b/Linear Regression/README.markdown @@ -1,5 +1,4 @@ # Linear Regression -## First draft version of this document Linear regression is a technique for creating a model of the relationship between two (or more) variable quantities. @@ -16,4 +15,152 @@ Age (in years)| Price (in £) Our car is 4 years old. How can we set a price for our car based on the data in this table? +Let's start by looking at the data plotted out: + +![graph1](Images/graph1.png) + +We could imagine a straight line drawn through the points on this graph. It's not (in this case) going to go exactly through every point, but we could place the line so that it goes as close to all the points as possible. + +To say this in another way, we want to make the distance from the line to each point as small as possible. This is most often done by minimising the square of the distance from the line to each point. + +We can describe the straight line in terms of two variables: + +1. The point at which it crosses the y-axis i.e. the predicted price of a brand new car. This is the *intercept*. +2. The *slope* of the line - i.e. for every year of age, how much does the price change. + +This is the equation for our line: + +$$ +carPrice = slope \times carAge + intercept +$$ + +How can we find the best values for the intercept and the slope? Let's look at two different ways to do this. + +## An iterative approach +One approach is to start with some arbitrary values for the intercept and the slope. We work out what small changes we make to these values to move our line closer to the data points. Then we repeat this multiple times. Eventually our line will approach the optimum position. + +First let's set up our data structures. We will use two Swift arrays for the car age and the car price: + +```swift +let carAge: [Double] = [10, 8, 3, 3, 2, 1] +let carPrice: [Double] = [500, 400, 7000, 8500, 11000, 10500] +``` + +This is how we can represent our straight line: + +```swift +var intercept = 0.0 +var slope = 0.0 +func predictedCarPrice(carAge: Double) -> Double { + return intercept + slope * carAge +} +``` +Now for the code which will perform the iterations: + +```swift +let numberOfCarAdvertsWeSaw = carPrice.count - 1 +let iterations = 2000 +let alpha = 0.0001 + +for n in 1...iterations { + for i in 0...numberOfCarAdvertsWeSaw { + let difference = carPrice[i] - predictedCarPrice(carAge[i]) + intercept += alpha * difference + slope += alpha * difference * carAge[i] + } +} +``` + +```alpha``` is a factor that determines how much closer we move to the correct solution with each iteration. If this factor is too large then our program will not converge on the correct solution. + +The program loops through each data point (each car age and car price). For each data point it adjusts the intercept and the slope to bring them closer to the correct values. The equations used in the code to adjust the intercept and the slope are based on moving in the direction of the maximal reduction of these variables. This is a *gradient descent*. + +We want to minimse the square of the distance between the line and the points. Let's define a function J which represents this distance - for simplicity we consider only one point here: + +$$ +J \propto ((slope.carAge+intercept) - carPrice))^2 +$$ + +In order to move in the direction of maximal reduction, we take the partial derivative of this function with respect to the slope: + +$$ +\frac{\partial J}{\partial (slope)} \propto (slope.carAge+intercept) - carPrice).carAge +$$ + +And similarly for the intercept: + +$$ +\frac{\partial J}{\partial (intercept)} \propto +(slope.carAge+intercept) - carPrice) +$$ + +We multiply these derivatives by our factor alpha and then use them to adjust the values of slope and intercept on each iteration. + +Looking at the code, it intuitively makes sense - the larger the difference between the current predicted car Price and the actual car price, and the larger the value of ```alpha```, the greater the adjustments to the intercept and the slope. + +It can take a lot of iterations to approach the ideal values. Let's look at how the intercept and slope change as we increase the number of iterations: + +Iterations | Intercept | Slope | Predicted value of a 4 year old car +:---------:|:---------:|:-----:|:------------------------: +0 | 0 | 0 | 0 +2000 | 4112 | -113 | 3659 +6000 | 8564 | -764 | 5507 +10000 | 10517 | -1049 | 6318 +14000 | 11374 | -1175 | 6673 +18000 | 11750 | -1230 | 6829 + +Here is the same data shown as a graph. Each of the blue lines on the graph represents a row in the table above. + +![graph2](Images/graph2.png) + +After 18,000 iterations it looks as if the line is getting closer to what we would expect (just by looking) to be the correct line of best fit. Also, each additional 2,000 iterations has less and less effect on the final result - the values of the intercept and the slope are converging on the correct values. + +##A closed form solution + +There is another way we can calculate the line of best fit, without having to do multiple iterations. We can solve the equations describing the least squares minimisation and just work out the intercept and slope directly. + +First we need some helper functions. This one calculates the average (the mean) of an array of Doubles: + +```swift +func average(input: [Double]) -> Double { + return input.reduce(0, combine: +) / Double(input.count) +} +``` +We are using the ```reduce``` Swift function to sum up all the elements of the array, and then divide that by the number of elements. This gives us the mean value. + +We also need to be able to multiply each element in an array by the corresponding element in another array, to create a new array. Here is a function which will do this: + +```swift +func multiply(input1: [Double], _ input2: [Double]) -> [Double] { + return input1.enumerate().map({ (index, element) in return element*input2[index] }) +} +``` + +We are using the ```map``` function to multiply each element. + +Finally, the function which fits the line to the data: + +```swift +func linearRegression(xVariable: [Double], _ yVariable: [Double]) -> (Double -> Double) { + let sum1 = average(multiply(xVariable, yVariable)) - average(xVariable) * average(yVariable) + let sum2 = average(multiply(xVariable, xVariable)) - pow(average(xVariable), 2) + let slope = sum1 / sum2 + let intercept = average(yVariable) - slope * average(xVariable) + return { intercept + slope * $0 } +} +``` +This function takes as arguments two arrays of Doubles, and returns a function which is the line of best fit. The formulas to calculate the slope and the intercept can be derived from our definition of the function J. Let's see how the output from this line fits our data: + +![graph3](Images/graph3.png) + +Using this line, we would predict a price for our 4 year old car of £6952. + + +##Summary +We've seen two different ways to implement a simple linear regression in Swift. An obvious question is: why bother with the iterative approach at all? + +Well, the line we've found doesn't fit the data perfectly. For one thing, the graph includes some negative values at high car ages! Possibly we would have to pay someone to tow away a very old car... but really these negative values just show that we have not modelled the real life situation very accurately. The relationship between the car age and the car price is not linear but instead is some other function. We also know that a car's price is not just related to its age but also other factors such as the make, model and engine size of the car. We would need to use additional variables to describe these other factors. + +It turns out that in some of these more complicated models, the iterative approach is the only viable or efficient approach. This can also occur when the arrays of data are very large and may be sparsely populated with data values. + *Written for Swift Algorithm Club by James Harrop* \ No newline at end of file From 0abfd03de68af02f62d1b41298e364d634362e15 Mon Sep 17 00:00:00 2001 From: jamesharrop Date: Fri, 22 Jul 2016 22:11:22 +0100 Subject: [PATCH 0436/1679] Removed LaTex equations --- Linear Regression/README.markdown | 26 ++++---------------------- 1 file changed, 4 insertions(+), 22 deletions(-) diff --git a/Linear Regression/README.markdown b/Linear Regression/README.markdown index e78514df5..3fc16ff31 100644 --- a/Linear Regression/README.markdown +++ b/Linear Regression/README.markdown @@ -30,9 +30,8 @@ We can describe the straight line in terms of two variables: This is the equation for our line: -$$ -carPrice = slope \times carAge + intercept -$$ +carPrice = slope * carAge + intercept + How can we find the best values for the intercept and the slope? Let's look at two different ways to do this. @@ -75,26 +74,9 @@ for n in 1...iterations { The program loops through each data point (each car age and car price). For each data point it adjusts the intercept and the slope to bring them closer to the correct values. The equations used in the code to adjust the intercept and the slope are based on moving in the direction of the maximal reduction of these variables. This is a *gradient descent*. -We want to minimse the square of the distance between the line and the points. Let's define a function J which represents this distance - for simplicity we consider only one point here: - -$$ -J \propto ((slope.carAge+intercept) - carPrice))^2 -$$ - -In order to move in the direction of maximal reduction, we take the partial derivative of this function with respect to the slope: - -$$ -\frac{\partial J}{\partial (slope)} \propto (slope.carAge+intercept) - carPrice).carAge -$$ - -And similarly for the intercept: - -$$ -\frac{\partial J}{\partial (intercept)} \propto -(slope.carAge+intercept) - carPrice) -$$ +We want to minimse the square of the distance between the line and the points. We define a function J which represents this distance - for simplicity we consider only one point here. This function J is proprotional to ((slope.carAge+intercept) - carPrice))^2 -We multiply these derivatives by our factor alpha and then use them to adjust the values of slope and intercept on each iteration. +In order to move in the direction of maximal reduction, we take the partial derivative of this function with respect to the slope, and similarly for the intercept. We multiply these derivatives by our factor alpha and then use them to adjust the values of slope and intercept on each iteration. Looking at the code, it intuitively makes sense - the larger the difference between the current predicted car Price and the actual car price, and the larger the value of ```alpha```, the greater the adjustments to the intercept and the slope. From a9aa744dd0a389bb6f2efa8b9c9e9a65ace0a8d9 Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Thu, 28 Jul 2016 07:03:07 -0700 Subject: [PATCH 0437/1679] Indexed the Linear Regression article in the main read.me file. Also made a code style change. --- Linear Regression/LinearRegression.playground/Contents.swift | 4 ++-- README.markdown | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Linear Regression/LinearRegression.playground/Contents.swift b/Linear Regression/LinearRegression.playground/Contents.swift index 07ebe6a5d..585471487 100644 --- a/Linear Regression/LinearRegression.playground/Contents.swift +++ b/Linear Regression/LinearRegression.playground/Contents.swift @@ -13,12 +13,12 @@ func predictedCarPrice(carAge: Double) -> Double { // An iterative approach -let numberOfCarAdvertsWeSaw = carPrice.count - 1 +let numberOfCarAdvertsWeSaw = carPrice.count let numberOfIterations = 100 let alpha = 0.0001 for n in 1...numberOfIterations { - for i in 0...numberOfCarAdvertsWeSaw { + for i in 0.. Date: Thu, 28 Jul 2016 07:03:49 -0700 Subject: [PATCH 0438/1679] Minor code style change in read.me file of Linear Regression --- Linear Regression/README.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Linear Regression/README.markdown b/Linear Regression/README.markdown index 3fc16ff31..c04e3b3dc 100644 --- a/Linear Regression/README.markdown +++ b/Linear Regression/README.markdown @@ -57,12 +57,12 @@ func predictedCarPrice(carAge: Double) -> Double { Now for the code which will perform the iterations: ```swift -let numberOfCarAdvertsWeSaw = carPrice.count - 1 +let numberOfCarAdvertsWeSaw = carPrice.count let iterations = 2000 let alpha = 0.0001 for n in 1...iterations { - for i in 0...numberOfCarAdvertsWeSaw { + for i in 0.. Date: Sun, 31 Jul 2016 09:56:27 +0900 Subject: [PATCH 0439/1679] Add public access in Tree --- Tree/Tree.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tree/Tree.swift b/Tree/Tree.swift index 89f1a39da..39d1f3df5 100644 --- a/Tree/Tree.swift +++ b/Tree/Tree.swift @@ -25,7 +25,7 @@ extension TreeNode: CustomStringConvertible { } extension TreeNode where T: Equatable { - func search(value: T) -> TreeNode? { + public func search(value: T) -> TreeNode? { if value == self.value { return self } From c95bec277b89eda7992abfe4716281d3bf136301 Mon Sep 17 00:00:00 2001 From: Tim Camber Date: Mon, 1 Aug 2016 12:59:24 -0400 Subject: [PATCH 0440/1679] Adds Knuth-Morris-Pratt to Substring Searches --- README.markdown | 1 + 1 file changed, 1 insertion(+) diff --git a/README.markdown b/README.markdown index 35dad0aff..418cb1fa8 100644 --- a/README.markdown +++ b/README.markdown @@ -55,6 +55,7 @@ If you're new to algorithms and data structures, here are a few good ones to sta - [Brute-Force String Search](Brute-Force String Search/). A naive method. - [Boyer-Moore](Boyer-Moore/). A fast method to search for substrings. It skips ahead based on a look-up table, to avoid looking at every character in the text. +- Knuth-Morris-Pratt - Rabin-Karp - [Longest Common Subsequence](Longest Common Subsequence/). Find the longest sequence of characters that appear in the same order in both strings. From 9c5aad72a5bf760088377ce0dc4ee0113337de9d Mon Sep 17 00:00:00 2001 From: Ian Alexander Rahman Date: Mon, 1 Aug 2016 22:02:35 -0400 Subject: [PATCH 0441/1679] Minor grammatical fixes --- K-Means/README.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/K-Means/README.markdown b/K-Means/README.markdown index bebcf225b..774cc18d2 100644 --- a/K-Means/README.markdown +++ b/K-Means/README.markdown @@ -45,11 +45,11 @@ The selection of initial centroids was fortuitous! We found the lower left clust #### Bad clustering -The next two examples highlight the unpredictability of k-Means and how it not always finds the best clustering. +The next two examples highlight the unpredictability of k-Means and how it does not always find the best clustering. ![Bad Clustering 1](Images/k_means_bad1.png) -As you can see in this one, the initial centroids were all a little too close to one another, and the blue one didn't quite get to a good place. By adjusting the convergence distance we should be able to get it better. +As you can see in this example, the initial centroids were all a little too close to one another, and the blue one didn't quite get to a good place. By adjusting the convergence distance we should be able to improve the fit of our centroids to the data. ![Bad Clustering 1](Images/k_means_bad2.png) From 4d56039855507bdbe090f8ecb1b7dc52b9ab6329 Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Wed, 3 Aug 2016 22:41:05 -0700 Subject: [PATCH 0442/1679] Minor styling fixes to comb sort --- Comb Sort/Comb Sort.playground/Contents.swift | 48 ++++++++----------- 1 file changed, 20 insertions(+), 28 deletions(-) diff --git a/Comb Sort/Comb Sort.playground/Contents.swift b/Comb Sort/Comb Sort.playground/Contents.swift index 3bc03546a..2d6155b50 100644 --- a/Comb Sort/Comb Sort.playground/Contents.swift +++ b/Comb Sort/Comb Sort.playground/Contents.swift @@ -5,45 +5,37 @@ import Cocoa func combSort (input: [Int]) -> [Int] { - var copy: [Int] = input - var gap = copy.count - let shrink = 1.3 - - while gap > 1 { - gap = (Int)(Double(gap) / shrink) - if gap < 1 { - gap = 1 - } - - var index = 0 - while !(index + gap >= copy.count) { - if copy[index] > copy[index + gap] { - swap(©[index], ©[index + gap]) - } - index += 1 - } + var copy = input + var gap = copy.count + let shrink = 1.3 + + while gap > 1 { + gap = Int(Double(gap) / shrink) + if gap < 1 { + gap = 1 } - return copy -} -// A function to swap two integer values -// Used for swapping within the array of values. -func swap (inout a: Int, inout b: Int) { - let temp = a - a = b - b = temp + var index = 0 + while index + gap < copy.count { + if copy[index] > copy[index + gap] { + swap(©[index], ©[index + gap]) + } + index += 1 + } + } + return copy } // Test Comb Sort with small array of ten values -let array: [Int] = [2, 32, 9, -1, 89, 101, 55, -10, -12, 67] +let array = [2, 32, 9, -1, 89, 101, 55, -10, -12, 67] combSort(array) // Test Comb Sort with large array of 1000 random values var bigArray = [Int](count: 1000, repeatedValue: 0) var i = 0 while i < 1000 { - bigArray[i] = Int(arc4random_uniform(1000) + 1) - i += 1 + bigArray[i] = Int(arc4random_uniform(1000) + 1) + i += 1 } combSort(bigArray) From 5046c1f6fd1496528ac7a072100aa625a31be03c Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Wed, 3 Aug 2016 22:43:42 -0700 Subject: [PATCH 0443/1679] Added Comb Sort to main readme file --- README.markdown | 1 + 1 file changed, 1 insertion(+) diff --git a/README.markdown b/README.markdown index 35dad0aff..233bd94f3 100644 --- a/README.markdown +++ b/README.markdown @@ -92,6 +92,7 @@ Bad sorting algorithms (don't use these!): ### Miscellaneous - [Shuffle](Shuffle/). Randomly rearranges the contents of an array. +- [Comb Sort](Comb Sort/). An improve upon the Bubble Sort algorithm. ### Mathematics From bbee485a20d3f8ce77243d110506abce87fd0042 Mon Sep 17 00:00:00 2001 From: Mike Date: Wed, 17 Aug 2016 19:36:23 +0200 Subject: [PATCH 0444/1679] Create README.md --- Skip-List/README.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 Skip-List/README.md diff --git a/Skip-List/README.md b/Skip-List/README.md new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/Skip-List/README.md @@ -0,0 +1 @@ + From 559c0b1c7039a87c769c10545f5731fad0da39e0 Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Thu, 18 Aug 2016 22:43:03 +1200 Subject: [PATCH 0445/1679] Xcode auto migration to Swift 3 --- AVL Tree/AVLTree.swift | 62 +++++++++---------- AVL Tree/Tests/AVLTreeTests.swift | 24 +++---- .../Tests/Tests.xcodeproj/project.pbxproj | 3 + 3 files changed, 46 insertions(+), 43 deletions(-) diff --git a/AVL Tree/AVLTree.swift b/AVL Tree/AVLTree.swift index 580a51e8e..427d3da11 100644 --- a/AVL Tree/AVLTree.swift +++ b/AVL Tree/AVLTree.swift @@ -20,16 +20,16 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. -public class TreeNode { +open class TreeNode { public typealias Node = TreeNode - public var payload: Payload? + open var payload: Payload? - private var key: Key + fileprivate var key: Key internal var leftChild: Node? internal var rightChild: Node? - private var height: Int - weak private var parent: Node? + fileprivate var height: Int + weak fileprivate var parent: Node? public init(key: Key, payload: Payload?, leftChild: Node?, rightChild: Node?, parent: Node?, height: Int) { self.key = key @@ -51,46 +51,46 @@ public class TreeNode { self.init(key: key, payload: nil) } - public var isRoot: Bool { + open var isRoot: Bool { return parent == nil } - public var isLeaf: Bool { + open var isLeaf: Bool { return rightChild == nil && leftChild == nil } - public var isLeftChild: Bool { + open var isLeftChild: Bool { return parent?.leftChild === self } - public var isRightChild: Bool { + open var isRightChild: Bool { return parent?.rightChild === self } - public var hasLeftChild: Bool { + open var hasLeftChild: Bool { return leftChild != nil } - public var hasRightChild: Bool { + open var hasRightChild: Bool { return rightChild != nil } - public var hasAnyChild: Bool { + open var hasAnyChild: Bool { return leftChild != nil || rightChild != nil } - public var hasBothChildren: Bool { + open var hasBothChildren: Bool { return leftChild != nil && rightChild != nil } } // MARK: - The AVL tree -public class AVLTree { +open class AVLTree { public typealias Node = TreeNode - private(set) public var root: Node? - private(set) public var size = 0 + fileprivate(set) open var root: Node? + fileprivate(set) open var size = 0 public init() { } } @@ -119,7 +119,7 @@ extension AVLTree { set { insert(key, newValue) } } - public func search(input: Key) -> Payload? { + public func search(_ input: Key) -> Payload? { if let result = search(input, root) { return result.payload } else { @@ -127,7 +127,7 @@ extension AVLTree { } } - private func search(key: Key, _ node: Node?) -> Node? { + fileprivate func search(_ key: Key, _ node: Node?) -> Node? { if let node = node { if key == node.key { return node @@ -144,7 +144,7 @@ extension AVLTree { // MARK: - Inserting new items extension AVLTree { - public func insert(key: Key, _ payload: Payload? = nil) { + public func insert(_ key: Key, _ payload: Payload? = nil) { if let root = root { insert(key, payload, root) } else { @@ -153,7 +153,7 @@ extension AVLTree { size += 1 } - private func insert(input: Key, _ payload: Payload?, _ node: Node) { + fileprivate func insert(_ input: Key, _ payload: Payload?, _ node: Node) { if input < node.key { if let child = node.leftChild { insert(input, payload, child) @@ -177,7 +177,7 @@ extension AVLTree { // MARK: - Balancing tree extension AVLTree { - private func updateHeightUpwards(node: Node?) { + fileprivate func updateHeightUpwards(_ node: Node?) { if let node = node { let lHeight = node.leftChild?.height ?? 0 let rHeight = node.rightChild?.height ?? 0 @@ -186,13 +186,13 @@ extension AVLTree { } } - private func lrDifference(node: Node?) -> Int { + fileprivate func lrDifference(_ node: Node?) -> Int { let lHeight = node?.leftChild?.height ?? 0 let rHeight = node?.rightChild?.height ?? 0 return lHeight - rHeight } - private func balance(node: Node?) { + fileprivate func balance(_ node: Node?) { guard let node = node else { return } @@ -200,8 +200,8 @@ extension AVLTree { updateHeightUpwards(node.leftChild) updateHeightUpwards(node.rightChild) - var nodes = [Node?](count: 3, repeatedValue: nil) - var subtrees = [Node?](count: 4, repeatedValue: nil) + var nodes = [Node?](repeating: nil, count: 3) + var subtrees = [Node?](repeating: nil, count: 4) let nodeParent = node.parent let lrFactor = lrDifference(node) @@ -295,7 +295,7 @@ extension AVLTree { // MARK: - Displaying tree extension AVLTree { - private func display(node: Node?, level: Int) { + fileprivate func display(_ node: Node?, level: Int) { if let node = node { display(node.rightChild, level: level + 1) print("") @@ -310,7 +310,7 @@ extension AVLTree { } } - public func display(node: Node) { + public func display(_ node: Node) { display(node, level: 0) print("") } @@ -319,7 +319,7 @@ extension AVLTree { // MARK: - Delete node extension AVLTree { - public func delete(key: Key) { + public func delete(_ key: Key) { if size == 1 { root = nil size -= 1 @@ -329,7 +329,7 @@ extension AVLTree { } } - private func delete(node: Node) { + fileprivate func delete(_ node: Node) { if node.isLeaf { // Just remove and balance up if let parent = node.parent { @@ -351,11 +351,11 @@ extension AVLTree { } } else { // Handle stem cases - if let replacement = node.leftChild?.maximum() where replacement !== node { + if let replacement = node.leftChild?.maximum() , replacement !== node { node.key = replacement.key node.payload = replacement.payload delete(replacement) - } else if let replacement = node.rightChild?.minimum() where replacement !== node { + } else if let replacement = node.rightChild?.minimum() , replacement !== node { node.key = replacement.key node.payload = replacement.payload delete(replacement) diff --git a/AVL Tree/Tests/AVLTreeTests.swift b/AVL Tree/Tests/AVLTreeTests.swift index 065367bb6..637f499e9 100644 --- a/AVL Tree/Tests/AVLTreeTests.swift +++ b/AVL Tree/Tests/AVLTreeTests.swift @@ -67,25 +67,25 @@ class AVLTreeTests: XCTestCase { } func testSingleInsertionPerformance() { - self.measureBlock { + self.measure { self.tree?.insert(5, "E") } } func testMultipleInsertionsPerformance() { - self.measureBlock { + self.measure { self.tree?.autopopulateWithNodes(50) } } func testSearchExistentOnSmallTreePerformance() { - self.measureBlock { + self.measure { self.tree?.search(2) } } func testSearchExistentElementOnLargeTreePerformance() { - self.measureBlock { + self.measure { self.tree?.autopopulateWithNodes(500) self.tree?.search(400) } @@ -150,8 +150,8 @@ class AVLTreeTests: XCTestCase { } } -extension AVLTree where Key : SignedIntegerType { - func autopopulateWithNodes(count: Int) { +extension AVLTree where Key : SignedInteger { + func autopopulateWithNodes(_ count: Int) { var k: Key = 1 for _ in 0...count { self.insert(k) @@ -160,12 +160,12 @@ extension AVLTree where Key : SignedIntegerType { } } -enum AVLTreeError: ErrorType { - case NotBalanced +enum AVLTreeError: Error { + case notBalanced } -extension AVLTree where Key : SignedIntegerType { - func height(node: Node?) -> Int { +extension AVLTree where Key : SignedInteger { + func height(_ node: Node?) -> Int { if let node = node { let lHeight = height(node.leftChild) let rHeight = height(node.rightChild) @@ -175,10 +175,10 @@ extension AVLTree where Key : SignedIntegerType { return 0 } - func inOrderCheckBalanced(node: Node?) throws { + func inOrderCheckBalanced(_ node: Node?) throws { if let node = node { guard abs(height(node.leftChild) - height(node.rightChild)) <= 1 else { - throw AVLTreeError.NotBalanced + throw AVLTreeError.notBalanced } try inOrderCheckBalanced(node.leftChild) try inOrderCheckBalanced(node.rightChild) diff --git a/AVL Tree/Tests/Tests.xcodeproj/project.pbxproj b/AVL Tree/Tests/Tests.xcodeproj/project.pbxproj index dfaf44e8d..079f0010b 100644 --- a/AVL Tree/Tests/Tests.xcodeproj/project.pbxproj +++ b/AVL Tree/Tests/Tests.xcodeproj/project.pbxproj @@ -91,6 +91,7 @@ TargetAttributes = { 7B2BBC7F1C779D720067B71D = { CreatedOnToolsVersion = 7.2; + LastSwiftMigration = 0800; }; }; }; @@ -224,6 +225,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -235,6 +237,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Release; }; From 4683bb9bf30ce68aa005111dfd3fd7b852a9091b Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Thu, 18 Aug 2016 22:49:37 +1200 Subject: [PATCH 0446/1679] Updating project to recommended settings --- AVL Tree/Tests/Tests.xcodeproj/project.pbxproj | 7 ++++++- .../Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/AVL Tree/Tests/Tests.xcodeproj/project.pbxproj b/AVL Tree/Tests/Tests.xcodeproj/project.pbxproj index 079f0010b..64c244747 100644 --- a/AVL Tree/Tests/Tests.xcodeproj/project.pbxproj +++ b/AVL Tree/Tests/Tests.xcodeproj/project.pbxproj @@ -86,7 +86,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; - LastUpgradeCheck = 0720; + LastUpgradeCheck = 0800; ORGANIZATIONNAME = "Swift Algorithm Club"; TargetAttributes = { 7B2BBC7F1C779D720067B71D = { @@ -150,8 +150,10 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; @@ -194,8 +196,10 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; @@ -214,6 +218,7 @@ MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; }; name = Release; }; diff --git a/AVL Tree/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/AVL Tree/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme index 8ef8d8581..14f27f777 100644 --- a/AVL Tree/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme +++ b/AVL Tree/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -1,6 +1,6 @@ Date: Thu, 18 Aug 2016 23:44:10 +1200 Subject: [PATCH 0447/1679] Removing "open" access level that was automatically included in auto migration to swift 3. Removing underscore labels. --- AVL Tree/AVLTree.swift | 102 +++++++++++++++--------------- AVL Tree/Tests/AVLTreeTests.swift | 34 +++++----- 2 files changed, 68 insertions(+), 68 deletions(-) diff --git a/AVL Tree/AVLTree.swift b/AVL Tree/AVLTree.swift index 427d3da11..b4b97f0d6 100644 --- a/AVL Tree/AVLTree.swift +++ b/AVL Tree/AVLTree.swift @@ -20,10 +20,10 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. -open class TreeNode { +public class TreeNode { public typealias Node = TreeNode - open var payload: Payload? + var payload: Payload? fileprivate var key: Key internal var leftChild: Node? @@ -51,35 +51,35 @@ open class TreeNode { self.init(key: key, payload: nil) } - open var isRoot: Bool { + var isRoot: Bool { return parent == nil } - open var isLeaf: Bool { + var isLeaf: Bool { return rightChild == nil && leftChild == nil } - open var isLeftChild: Bool { + var isLeftChild: Bool { return parent?.leftChild === self } - open var isRightChild: Bool { + var isRightChild: Bool { return parent?.rightChild === self } - open var hasLeftChild: Bool { + var hasLeftChild: Bool { return leftChild != nil } - open var hasRightChild: Bool { + var hasRightChild: Bool { return rightChild != nil } - open var hasAnyChild: Bool { + var hasAnyChild: Bool { return leftChild != nil || rightChild != nil } - open var hasBothChildren: Bool { + var hasBothChildren: Bool { return leftChild != nil && rightChild != nil } } @@ -89,8 +89,8 @@ open class TreeNode { open class AVLTree { public typealias Node = TreeNode - fileprivate(set) open var root: Node? - fileprivate(set) open var size = 0 + fileprivate(set) var root: Node? + fileprivate(set) var size = 0 public init() { } } @@ -115,26 +115,26 @@ extension TreeNode { extension AVLTree { subscript(key: Key) -> Payload? { - get { return search(key) } - set { insert(key, newValue) } + get { return search(input: key) } + set { insert(key: key, payload: newValue) } } - public func search(_ input: Key) -> Payload? { - if let result = search(input, root) { + public func search(input: Key) -> Payload? { + if let result = search(key: input, node: root) { return result.payload } else { return nil } } - fileprivate func search(_ key: Key, _ node: Node?) -> Node? { + fileprivate func search(key: Key, node: Node?) -> Node? { if let node = node { if key == node.key { return node } else if key < node.key { - return search(key, node.leftChild) + return search(key: key, node: node.leftChild) } else { - return search(key, node.rightChild) + return search(key: key, node: node.rightChild) } } return nil @@ -144,31 +144,31 @@ extension AVLTree { // MARK: - Inserting new items extension AVLTree { - public func insert(_ key: Key, _ payload: Payload? = nil) { + public func insert(key: Key, payload: Payload? = nil) { if let root = root { - insert(key, payload, root) + insert(input: key, payload: payload, node: root) } else { root = Node(key: key, payload: payload) } size += 1 } - fileprivate func insert(_ input: Key, _ payload: Payload?, _ node: Node) { + private func insert(input: Key, payload: Payload?, node: Node) { if input < node.key { if let child = node.leftChild { - insert(input, payload, child) + insert(input: input, payload: payload, node: child) } else { let child = Node(key: input, payload: payload, leftChild: nil, rightChild: nil, parent: node, height: 1) node.leftChild = child - balance(child) + balance(node: child) } } else { if let child = node.rightChild { - insert(input, payload, child) + insert(input: input, payload: payload, node: child) } else { let child = Node(key: input, payload: payload, leftChild: nil, rightChild: nil, parent: node, height: 1) node.rightChild = child - balance(child) + balance(node: child) } } } @@ -177,37 +177,37 @@ extension AVLTree { // MARK: - Balancing tree extension AVLTree { - fileprivate func updateHeightUpwards(_ node: Node?) { + fileprivate func updateHeightUpwards(node: Node?) { if let node = node { let lHeight = node.leftChild?.height ?? 0 let rHeight = node.rightChild?.height ?? 0 node.height = max(lHeight, rHeight) + 1 - updateHeightUpwards(node.parent) + updateHeightUpwards(node: node.parent) } } - fileprivate func lrDifference(_ node: Node?) -> Int { + fileprivate func lrDifference(node: Node?) -> Int { let lHeight = node?.leftChild?.height ?? 0 let rHeight = node?.rightChild?.height ?? 0 return lHeight - rHeight } - fileprivate func balance(_ node: Node?) { + fileprivate func balance(node: Node?) { guard let node = node else { return } - updateHeightUpwards(node.leftChild) - updateHeightUpwards(node.rightChild) + updateHeightUpwards(node: node.leftChild) + updateHeightUpwards(node: node.rightChild) var nodes = [Node?](repeating: nil, count: 3) var subtrees = [Node?](repeating: nil, count: 4) let nodeParent = node.parent - let lrFactor = lrDifference(node) + let lrFactor = lrDifference(node: node) if lrFactor > 1 { // left-left or left-right - if lrDifference(node.leftChild) > 0 { + if lrDifference(node: node.leftChild) > 0 { // left-left nodes[0] = node nodes[2] = node.leftChild @@ -230,7 +230,7 @@ extension AVLTree { } } else if lrFactor < -1 { // right-left or right-right - if lrDifference(node.rightChild) < 0 { + if lrDifference(node: node.rightChild) < 0 { // right-right nodes[1] = node nodes[2] = node.rightChild @@ -253,7 +253,7 @@ extension AVLTree { } } else { // Don't need to balance 'node', go for parent - balance(node.parent) + balance(node: node.parent) return } @@ -285,19 +285,19 @@ extension AVLTree { nodes[0]?.rightChild = subtrees[3] subtrees[3]?.parent = nodes[0] - updateHeightUpwards(nodes[1]) // Update height from left - updateHeightUpwards(nodes[0]) // Update height from right + updateHeightUpwards(node: nodes[1]) // Update height from left + updateHeightUpwards(node: nodes[0]) // Update height from right - balance(nodes[2]?.parent) + balance(node: nodes[2]?.parent) } } // MARK: - Displaying tree extension AVLTree { - fileprivate func display(_ node: Node?, level: Int) { + fileprivate func display(node: Node?, level: Int) { if let node = node { - display(node.rightChild, level: level + 1) + display(node: node.rightChild, level: level + 1) print("") if node.isRoot { print("Root -> ", terminator: "") @@ -306,12 +306,12 @@ extension AVLTree { print(" ", terminator: "") } print("(\(node.key):\(node.height))", terminator: "") - display(node.leftChild, level: level + 1) + display(node: node.leftChild, level: level + 1) } } - public func display(_ node: Node) { - display(node, level: 0) + public func display(node: Node) { + display(node: node, level: 0) print("") } } @@ -319,17 +319,17 @@ extension AVLTree { // MARK: - Delete node extension AVLTree { - public func delete(_ key: Key) { + public func delete(key: Key) { if size == 1 { root = nil size -= 1 - } else if let node = search(key, root) { - delete(node) + } else if let node = search(key: key, node: root) { + delete(node: node) size -= 1 } } - fileprivate func delete(_ node: Node) { + private func delete(node: Node) { if node.isLeaf { // Just remove and balance up if let parent = node.parent { @@ -344,7 +344,7 @@ extension AVLTree { parent.rightChild = nil } - balance(parent) + balance(node: parent) } else { // at root root = nil @@ -354,11 +354,11 @@ extension AVLTree { if let replacement = node.leftChild?.maximum() , replacement !== node { node.key = replacement.key node.payload = replacement.payload - delete(replacement) + delete(node: replacement) } else if let replacement = node.rightChild?.minimum() , replacement !== node { node.key = replacement.key node.payload = replacement.payload - delete(replacement) + delete(node: replacement) } } } diff --git a/AVL Tree/Tests/AVLTreeTests.swift b/AVL Tree/Tests/AVLTreeTests.swift index 637f499e9..51607d7c3 100644 --- a/AVL Tree/Tests/AVLTreeTests.swift +++ b/AVL Tree/Tests/AVLTreeTests.swift @@ -37,7 +37,7 @@ class AVLTreeTests: XCTestCase { self.tree?.autopopulateWithNodes(5) for i in 6...10 { - self.tree?.insert(i) + self.tree?.insert(key: i) do { try self.tree?.inOrderCheckBalanced(self.tree?.root) } catch _ { @@ -50,7 +50,7 @@ class AVLTreeTests: XCTestCase { self.tree?.autopopulateWithNodes(5) for i in 1...6 { - self.tree?.delete(i) + self.tree?.delete(key: i) do { try self.tree?.inOrderCheckBalanced(self.tree?.root) } catch _ { @@ -68,7 +68,7 @@ class AVLTreeTests: XCTestCase { func testSingleInsertionPerformance() { self.measure { - self.tree?.insert(5, "E") + self.tree?.insert(key: 5, payload: "E") } } @@ -80,14 +80,14 @@ class AVLTreeTests: XCTestCase { func testSearchExistentOnSmallTreePerformance() { self.measure { - self.tree?.search(2) + self.tree?.search(input: 2) } } func testSearchExistentElementOnLargeTreePerformance() { self.measure { self.tree?.autopopulateWithNodes(500) - self.tree?.search(400) + self.tree?.search(input: 400) } } @@ -106,19 +106,19 @@ class AVLTreeTests: XCTestCase { } func testDeleteExistentKey() { - self.tree?.delete(1) - XCTAssertNil(self.tree?.search(1), "Key should not exist anymore") + self.tree?.delete(key: 1) + XCTAssertNil(self.tree?.search(input: 1), "Key should not exist anymore") } func testDeleteNotExistentKey() { - self.tree?.delete(1056) - XCTAssertNil(self.tree?.search(1056), "Key should not exist") + self.tree?.delete(key: 1056) + XCTAssertNil(self.tree?.search(input: 1056), "Key should not exist") } func testInsertSize() { let tree = AVLTree() for i in 0...5 { - tree.insert(i, "") + tree.insert(key: i, payload: "") XCTAssertEqual(tree.size, i + 1, "Insert didn't update size correctly!") } } @@ -134,15 +134,15 @@ class AVLTreeTests: XCTestCase { for p in permutations { let tree = AVLTree() - tree.insert(1, "five") - tree.insert(2, "four") - tree.insert(3, "three") - tree.insert(4, "two") - tree.insert(5, "one") + tree.insert(key: 1, payload: "five") + tree.insert(key: 2, payload: "four") + tree.insert(key: 3, payload: "three") + tree.insert(key: 4, payload: "two") + tree.insert(key: 5, payload: "one") var count = tree.size for i in p { - tree.delete(i) + tree.delete(key: i) count -= 1 XCTAssertEqual(tree.size, count, "Delete didn't update size correctly!") } @@ -154,7 +154,7 @@ extension AVLTree where Key : SignedInteger { func autopopulateWithNodes(_ count: Int) { var k: Key = 1 for _ in 0...count { - self.insert(k) + self.insert(key: k) k = k + 1 } } From b094e0fde016e4cb19693a5eb3c67745c6bd9b02 Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Thu, 18 Aug 2016 23:45:28 +1200 Subject: [PATCH 0448/1679] Updating travis build to Xcode 8. Commenting out projects that have not yet been migrated. --- .travis.yml | 64 ++++++++++++++++++++++++++--------------------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/.travis.yml b/.travis.yml index 7f13f64eb..b01dfd26a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,5 @@ language: objective-c -osx_image: xcode7.3 +osx_image: xcode8 sudo: false install: @@ -8,34 +8,34 @@ install: script: -- xctool test -project ./All-Pairs\ Shortest\ Paths/APSP/APSP.xcodeproj -scheme APSPTests -- xctool test -project ./Array2D/Tests/Tests.xcodeproj -scheme Tests -- xctool test -project ./AVL\ Tree/Tests/Tests.xcodeproj -scheme Tests -- xctool test -project ./Binary\ Search/Tests/Tests.xcodeproj -scheme Tests -- xctool test -project ./Binary\ Search\ Tree/Solution\ 1/Tests/Tests.xcodeproj -scheme Tests -- xctool test -project ./Bloom\ Filter/Tests/Tests.xcodeproj -scheme Tests -- xctool test -project ./Bounded\ Priority\ Queue/Tests/Tests.xcodeproj -scheme Tests -- xctool test -project ./Breadth-First\ Search/Tests/Tests.xcodeproj -scheme Tests -- xctool test -project ./Bucket\ Sort/Tests/Tests.xcodeproj -scheme Tests -- xctool test -project ./B-Tree/Tests/Tests.xcodeproj -scheme Tests -- xctool test -project ./Counting\ Sort/Tests/Tests.xcodeproj -scheme Tests -- xctool test -project ./Depth-First\ Search/Tests/Tests.xcodeproj -scheme Tests -- xctool test -project ./Graph/Graph.xcodeproj -scheme GraphTests -- xctool test -project ./Heap/Tests/Tests.xcodeproj -scheme Tests -- xctool test -project ./Heap\ Sort/Tests/Tests.xcodeproj -scheme Tests -- xctool test -project ./Insertion\ Sort/Tests/Tests.xcodeproj -scheme Tests -- xctool test -project ./K-Means/Tests/Tests.xcodeproj -scheme Tests -- xctool test -project ./Linked\ List/Tests/Tests.xcodeproj -scheme Tests -- xctool test -project ./Longest\ Common\ Subsequence/Tests/Tests.xcodeproj -scheme Tests -- xctool test -project ./Minimum\ Spanning\ Tree\ \(Unweighted\)/Tests/Tests.xcodeproj -scheme Tests -- xctool test -project ./Priority\ Queue/Tests/Tests.xcodeproj -scheme Tests -- xctool test -project ./Queue/Tests/Tests.xcodeproj -scheme Tests -- xctool test -project ./Quicksort/Tests/Tests.xcodeproj -scheme Tests -- xctool test -project ./Run-Length\ Encoding/Tests/Tests.xcodeproj -scheme Tests -- xctool test -project ./Select\ Minimum\ Maximum/Tests/Tests.xcodeproj -scheme Tests -- xctool test -project ./Selection\ Sort/Tests/Tests.xcodeproj -scheme Tests -- xctool test -project ./Shell\ Sort/Tests/Tests.xcodeproj -scheme Tests -- xctool test -project ./Shortest\ Path\ \(Unweighted\)/Tests/Tests.xcodeproj -scheme Tests -- xctool test -project ./Single-Source\ Shortest\ Paths\ \(Weighted\)/SSSP.xcodeproj -scheme SSSPTests -- xctool test -project ./Stack/Tests/Tests.xcodeproj -scheme Tests -- xctool test -project ./Topological\ Sort/Tests/Tests.xcodeproj -scheme Tests +# - xctool test -project ./All-Pairs\ Shortest\ Paths/APSP/APSP.xcodeproj -scheme APSPTests +# - xctool test -project ./Array2D/Tests/Tests.xcodeproj -scheme Tests + - xctool test -project ./AVL\ Tree/Tests/Tests.xcodeproj -scheme Tests +# - xctool test -project ./Binary\ Search/Tests/Tests.xcodeproj -scheme Tests +# - xctool test -project ./Binary\ Search\ Tree/Solution\ 1/Tests/Tests.xcodeproj -scheme Tests +# - xctool test -project ./Bloom\ Filter/Tests/Tests.xcodeproj -scheme Tests +# - xctool test -project ./Bounded\ Priority\ Queue/Tests/Tests.xcodeproj -scheme Tests +# - xctool test -project ./Breadth-First\ Search/Tests/Tests.xcodeproj -scheme Tests +# - xctool test -project ./Bucket\ Sort/Tests/Tests.xcodeproj -scheme Tests +# - xctool test -project ./B-Tree/Tests/Tests.xcodeproj -scheme Tests +# - xctool test -project ./Counting\ Sort/Tests/Tests.xcodeproj -scheme Tests +# - xctool test -project ./Depth-First\ Search/Tests/Tests.xcodeproj -scheme Tests +# - xctool test -project ./Graph/Graph.xcodeproj -scheme GraphTests +# - xctool test -project ./Heap/Tests/Tests.xcodeproj -scheme Tests +# - xctool test -project ./Heap\ Sort/Tests/Tests.xcodeproj -scheme Tests +# - xctool test -project ./Insertion\ Sort/Tests/Tests.xcodeproj -scheme Tests +# - xctool test -project ./K-Means/Tests/Tests.xcodeproj -scheme Tests +# - xctool test -project ./Linked\ List/Tests/Tests.xcodeproj -scheme Tests +# - xctool test -project ./Longest\ Common\ Subsequence/Tests/Tests.xcodeproj -scheme Tests +# - xctool test -project ./Minimum\ Spanning\ Tree\ \(Unweighted\)/Tests/Tests.xcodeproj -scheme Tests +# - xctool test -project ./Priority\ Queue/Tests/Tests.xcodeproj -scheme Tests +# - xctool test -project ./Queue/Tests/Tests.xcodeproj -scheme Tests +# - xctool test -project ./Quicksort/Tests/Tests.xcodeproj -scheme Tests +# - xctool test -project ./Run-Length\ Encoding/Tests/Tests.xcodeproj -scheme Tests +# - xctool test -project ./Select\ Minimum\ Maximum/Tests/Tests.xcodeproj -scheme Tests +# - xctool test -project ./Selection\ Sort/Tests/Tests.xcodeproj -scheme Tests +# - xctool test -project ./Shell\ Sort/Tests/Tests.xcodeproj -scheme Tests +# - xctool test -project ./Shortest\ Path\ \(Unweighted\)/Tests/Tests.xcodeproj -scheme Tests +# - xctool test -project ./Single-Source\ Shortest\ Paths\ \(Weighted\)/SSSP.xcodeproj -scheme SSSPTests +# - xctool test -project ./Stack/Tests/Tests.xcodeproj -scheme Tests +# - xctool test -project ./Topological\ Sort/Tests/Tests.xcodeproj -scheme Tests From 8df51248547fe53cf199bc6ad7cea39d8e85d8d4 Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Thu, 18 Aug 2016 23:51:01 +1200 Subject: [PATCH 0449/1679] Removing "expression not used" warnings in test --- AVL Tree/Tests/AVLTreeTests.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/AVL Tree/Tests/AVLTreeTests.swift b/AVL Tree/Tests/AVLTreeTests.swift index 51607d7c3..7765c6d29 100644 --- a/AVL Tree/Tests/AVLTreeTests.swift +++ b/AVL Tree/Tests/AVLTreeTests.swift @@ -80,14 +80,14 @@ class AVLTreeTests: XCTestCase { func testSearchExistentOnSmallTreePerformance() { self.measure { - self.tree?.search(input: 2) + print(self.tree?.search(input: 2)) } } func testSearchExistentElementOnLargeTreePerformance() { self.measure { self.tree?.autopopulateWithNodes(500) - self.tree?.search(input: 400) + print(self.tree?.search(input: 400)) } } From f0ad3f504b4bcf7bff71dd58ac37916990e59fc5 Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Fri, 19 Aug 2016 00:05:37 +1200 Subject: [PATCH 0450/1679] Disabling swift lint until all projects can be built in Xcode 8 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index b01dfd26a..0cb6dc728 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,7 @@ sudo: false install: -- ./install_swiftlint.sh +# - ./install_swiftlint.sh script: From 9537cf8722778a7ecdaa0b3bf5bc9109e12da4c2 Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Fri, 19 Aug 2016 00:09:55 +1200 Subject: [PATCH 0451/1679] Trying to resolve build error "*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Got error while trying to deserialize event 'User defaults from command line:': The data is not in the correct format.'" --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 0cb6dc728..b8199a4a3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,6 @@ language: objective-c osx_image: xcode8 -sudo: false +# sudo: false install: From 2813695209a888e6f01364d79d9c3cc2a60f3fad Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Fri, 19 Aug 2016 00:14:20 +1200 Subject: [PATCH 0452/1679] Changing to xcodebuild as xctool fails to run tests. Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Got error while trying to deserialize event 'User defaults from command line:': The data is not in the correct format.' --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index b8199a4a3..228faab79 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,7 +10,7 @@ script: # - xctool test -project ./All-Pairs\ Shortest\ Paths/APSP/APSP.xcodeproj -scheme APSPTests # - xctool test -project ./Array2D/Tests/Tests.xcodeproj -scheme Tests - - xctool test -project ./AVL\ Tree/Tests/Tests.xcodeproj -scheme Tests + - xcodebuild test -project ./AVL\ Tree/Tests/Tests.xcodeproj -scheme Tests # - xctool test -project ./Binary\ Search/Tests/Tests.xcodeproj -scheme Tests # - xctool test -project ./Binary\ Search\ Tree/Solution\ 1/Tests/Tests.xcodeproj -scheme Tests # - xctool test -project ./Bloom\ Filter/Tests/Tests.xcodeproj -scheme Tests From 0267f61a4abd42606c7d5be4c7c5cec189944ad7 Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Fri, 19 Aug 2016 00:20:27 +1200 Subject: [PATCH 0453/1679] Changing xctool to xcodebuild for all tests --- .travis.yml | 60 ++++++++++++++++++++++++++--------------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/.travis.yml b/.travis.yml index 228faab79..970f85aa8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,34 +8,34 @@ install: script: -# - xctool test -project ./All-Pairs\ Shortest\ Paths/APSP/APSP.xcodeproj -scheme APSPTests -# - xctool test -project ./Array2D/Tests/Tests.xcodeproj -scheme Tests +# - xcodebuild test -project ./All-Pairs\ Shortest\ Paths/APSP/APSP.xcodeproj -scheme APSPTests +# - xcodebuild test -project ./Array2D/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./AVL\ Tree/Tests/Tests.xcodeproj -scheme Tests -# - xctool test -project ./Binary\ Search/Tests/Tests.xcodeproj -scheme Tests -# - xctool test -project ./Binary\ Search\ Tree/Solution\ 1/Tests/Tests.xcodeproj -scheme Tests -# - xctool test -project ./Bloom\ Filter/Tests/Tests.xcodeproj -scheme Tests -# - xctool test -project ./Bounded\ Priority\ Queue/Tests/Tests.xcodeproj -scheme Tests -# - xctool test -project ./Breadth-First\ Search/Tests/Tests.xcodeproj -scheme Tests -# - xctool test -project ./Bucket\ Sort/Tests/Tests.xcodeproj -scheme Tests -# - xctool test -project ./B-Tree/Tests/Tests.xcodeproj -scheme Tests -# - xctool test -project ./Counting\ Sort/Tests/Tests.xcodeproj -scheme Tests -# - xctool test -project ./Depth-First\ Search/Tests/Tests.xcodeproj -scheme Tests -# - xctool test -project ./Graph/Graph.xcodeproj -scheme GraphTests -# - xctool test -project ./Heap/Tests/Tests.xcodeproj -scheme Tests -# - xctool test -project ./Heap\ Sort/Tests/Tests.xcodeproj -scheme Tests -# - xctool test -project ./Insertion\ Sort/Tests/Tests.xcodeproj -scheme Tests -# - xctool test -project ./K-Means/Tests/Tests.xcodeproj -scheme Tests -# - xctool test -project ./Linked\ List/Tests/Tests.xcodeproj -scheme Tests -# - xctool test -project ./Longest\ Common\ Subsequence/Tests/Tests.xcodeproj -scheme Tests -# - xctool test -project ./Minimum\ Spanning\ Tree\ \(Unweighted\)/Tests/Tests.xcodeproj -scheme Tests -# - xctool test -project ./Priority\ Queue/Tests/Tests.xcodeproj -scheme Tests -# - xctool test -project ./Queue/Tests/Tests.xcodeproj -scheme Tests -# - xctool test -project ./Quicksort/Tests/Tests.xcodeproj -scheme Tests -# - xctool test -project ./Run-Length\ Encoding/Tests/Tests.xcodeproj -scheme Tests -# - xctool test -project ./Select\ Minimum\ Maximum/Tests/Tests.xcodeproj -scheme Tests -# - xctool test -project ./Selection\ Sort/Tests/Tests.xcodeproj -scheme Tests -# - xctool test -project ./Shell\ Sort/Tests/Tests.xcodeproj -scheme Tests -# - xctool test -project ./Shortest\ Path\ \(Unweighted\)/Tests/Tests.xcodeproj -scheme Tests -# - xctool test -project ./Single-Source\ Shortest\ Paths\ \(Weighted\)/SSSP.xcodeproj -scheme SSSPTests -# - xctool test -project ./Stack/Tests/Tests.xcodeproj -scheme Tests -# - xctool test -project ./Topological\ Sort/Tests/Tests.xcodeproj -scheme Tests +# - xcodebuild test -project ./Binary\ Search/Tests/Tests.xcodeproj -scheme Tests +# - xcodebuild test -project ./Binary\ Search\ Tree/Solution\ 1/Tests/Tests.xcodeproj -scheme Tests +# - xcodebuild test -project ./Bloom\ Filter/Tests/Tests.xcodeproj -scheme Tests +# - xcodebuild test -project ./Bounded\ Priority\ Queue/Tests/Tests.xcodeproj -scheme Tests +# - xcodebuild test -project ./Breadth-First\ Search/Tests/Tests.xcodeproj -scheme Tests +# - xcodebuild test -project ./Bucket\ Sort/Tests/Tests.xcodeproj -scheme Tests +# - xcodebuild test -project ./B-Tree/Tests/Tests.xcodeproj -scheme Tests +# - xcodebuild test -project ./Counting\ Sort/Tests/Tests.xcodeproj -scheme Tests +# - xcodebuild test -project ./Depth-First\ Search/Tests/Tests.xcodeproj -scheme Tests +# - xcodebuild test -project ./Graph/Graph.xcodeproj -scheme GraphTests +# - xcodebuild test -project ./Heap/Tests/Tests.xcodeproj -scheme Tests +# - xcodebuild test -project ./Heap\ Sort/Tests/Tests.xcodeproj -scheme Tests +# - xcodebuild test -project ./Insertion\ Sort/Tests/Tests.xcodeproj -scheme Tests +# - xcodebuild test -project ./K-Means/Tests/Tests.xcodeproj -scheme Tests +# - xcodebuild test -project ./Linked\ List/Tests/Tests.xcodeproj -scheme Tests +# - xcodebuild test -project ./Longest\ Common\ Subsequence/Tests/Tests.xcodeproj -scheme Tests +# - xcodebuild test -project ./Minimum\ Spanning\ Tree\ \(Unweighted\)/Tests/Tests.xcodeproj -scheme Tests +# - xcodebuild test -project ./Priority\ Queue/Tests/Tests.xcodeproj -scheme Tests +# - xcodebuild test -project ./Queue/Tests/Tests.xcodeproj -scheme Tests +# - xcodebuild test -project ./Quicksort/Tests/Tests.xcodeproj -scheme Tests +# - xcodebuild test -project ./Run-Length\ Encoding/Tests/Tests.xcodeproj -scheme Tests +# - xcodebuild test -project ./Select\ Minimum\ Maximum/Tests/Tests.xcodeproj -scheme Tests +# - xcodebuild test -project ./Selection\ Sort/Tests/Tests.xcodeproj -scheme Tests +# - xcodebuild test -project ./Shell\ Sort/Tests/Tests.xcodeproj -scheme Tests +# - xcodebuild test -project ./Shortest\ Path\ \(Unweighted\)/Tests/Tests.xcodeproj -scheme Tests +# - xcodebuild test -project ./Single-Source\ Shortest\ Paths\ \(Weighted\)/SSSP.xcodeproj -scheme SSSPTests +# - xcodebuild test -project ./Stack/Tests/Tests.xcodeproj -scheme Tests +# - xcodebuild test -project ./Topological\ Sort/Tests/Tests.xcodeproj -scheme Tests From c104087a821fef3b2058095ea70490a152d7fc80 Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Fri, 19 Aug 2016 00:35:32 +1200 Subject: [PATCH 0454/1679] Updating playground --- AVL Tree/AVLTree.playground/Contents.swift | 22 ++-- .../AVLTree.playground/Sources/AVLTree.swift | 108 +++++++++--------- .../AVLTree.playground/timeline.xctimeline | 6 - 3 files changed, 65 insertions(+), 71 deletions(-) delete mode 100644 AVL Tree/AVLTree.playground/timeline.xctimeline diff --git a/AVL Tree/AVLTree.playground/Contents.swift b/AVL Tree/AVLTree.playground/Contents.swift index 2b8ee8b59..409dfdc49 100644 --- a/AVL Tree/AVLTree.playground/Contents.swift +++ b/AVL Tree/AVLTree.playground/Contents.swift @@ -2,26 +2,26 @@ let tree = AVLTree() -tree.insert(5, "five") +tree.insert(key: 5, payload: "five") print(tree) -tree.insert(4, "four") +tree.insert(key: 4, payload: "four") print(tree) -tree.insert(3, "three") +tree.insert(key: 3, payload: "three") print(tree) -tree.insert(2, "two") +tree.insert(key: 2, payload: "two") print(tree) -tree.insert(1, "one") +tree.insert(key: 1, payload: "one") print(tree) print(tree.debugDescription) -let node = tree.search(2) // "two" +let node = tree.search(input: 2) // "two" -tree.delete(5) -tree.delete(2) -tree.delete(1) -tree.delete(4) -tree.delete(3) +tree.delete(key: 5) +tree.delete(key: 2) +tree.delete(key: 1) +tree.delete(key: 4) +tree.delete(key: 3) diff --git a/AVL Tree/AVLTree.playground/Sources/AVLTree.swift b/AVL Tree/AVLTree.playground/Sources/AVLTree.swift index 580a51e8e..b4b97f0d6 100644 --- a/AVL Tree/AVLTree.playground/Sources/AVLTree.swift +++ b/AVL Tree/AVLTree.playground/Sources/AVLTree.swift @@ -23,13 +23,13 @@ public class TreeNode { public typealias Node = TreeNode - public var payload: Payload? + var payload: Payload? - private var key: Key + fileprivate var key: Key internal var leftChild: Node? internal var rightChild: Node? - private var height: Int - weak private var parent: Node? + fileprivate var height: Int + weak fileprivate var parent: Node? public init(key: Key, payload: Payload?, leftChild: Node?, rightChild: Node?, parent: Node?, height: Int) { self.key = key @@ -51,46 +51,46 @@ public class TreeNode { self.init(key: key, payload: nil) } - public var isRoot: Bool { + var isRoot: Bool { return parent == nil } - public var isLeaf: Bool { + var isLeaf: Bool { return rightChild == nil && leftChild == nil } - public var isLeftChild: Bool { + var isLeftChild: Bool { return parent?.leftChild === self } - public var isRightChild: Bool { + var isRightChild: Bool { return parent?.rightChild === self } - public var hasLeftChild: Bool { + var hasLeftChild: Bool { return leftChild != nil } - public var hasRightChild: Bool { + var hasRightChild: Bool { return rightChild != nil } - public var hasAnyChild: Bool { + var hasAnyChild: Bool { return leftChild != nil || rightChild != nil } - public var hasBothChildren: Bool { + var hasBothChildren: Bool { return leftChild != nil && rightChild != nil } } // MARK: - The AVL tree -public class AVLTree { +open class AVLTree { public typealias Node = TreeNode - private(set) public var root: Node? - private(set) public var size = 0 + fileprivate(set) var root: Node? + fileprivate(set) var size = 0 public init() { } } @@ -115,26 +115,26 @@ extension TreeNode { extension AVLTree { subscript(key: Key) -> Payload? { - get { return search(key) } - set { insert(key, newValue) } + get { return search(input: key) } + set { insert(key: key, payload: newValue) } } public func search(input: Key) -> Payload? { - if let result = search(input, root) { + if let result = search(key: input, node: root) { return result.payload } else { return nil } } - private func search(key: Key, _ node: Node?) -> Node? { + fileprivate func search(key: Key, node: Node?) -> Node? { if let node = node { if key == node.key { return node } else if key < node.key { - return search(key, node.leftChild) + return search(key: key, node: node.leftChild) } else { - return search(key, node.rightChild) + return search(key: key, node: node.rightChild) } } return nil @@ -144,31 +144,31 @@ extension AVLTree { // MARK: - Inserting new items extension AVLTree { - public func insert(key: Key, _ payload: Payload? = nil) { + public func insert(key: Key, payload: Payload? = nil) { if let root = root { - insert(key, payload, root) + insert(input: key, payload: payload, node: root) } else { root = Node(key: key, payload: payload) } size += 1 } - private func insert(input: Key, _ payload: Payload?, _ node: Node) { + private func insert(input: Key, payload: Payload?, node: Node) { if input < node.key { if let child = node.leftChild { - insert(input, payload, child) + insert(input: input, payload: payload, node: child) } else { let child = Node(key: input, payload: payload, leftChild: nil, rightChild: nil, parent: node, height: 1) node.leftChild = child - balance(child) + balance(node: child) } } else { if let child = node.rightChild { - insert(input, payload, child) + insert(input: input, payload: payload, node: child) } else { let child = Node(key: input, payload: payload, leftChild: nil, rightChild: nil, parent: node, height: 1) node.rightChild = child - balance(child) + balance(node: child) } } } @@ -177,37 +177,37 @@ extension AVLTree { // MARK: - Balancing tree extension AVLTree { - private func updateHeightUpwards(node: Node?) { + fileprivate func updateHeightUpwards(node: Node?) { if let node = node { let lHeight = node.leftChild?.height ?? 0 let rHeight = node.rightChild?.height ?? 0 node.height = max(lHeight, rHeight) + 1 - updateHeightUpwards(node.parent) + updateHeightUpwards(node: node.parent) } } - private func lrDifference(node: Node?) -> Int { + fileprivate func lrDifference(node: Node?) -> Int { let lHeight = node?.leftChild?.height ?? 0 let rHeight = node?.rightChild?.height ?? 0 return lHeight - rHeight } - private func balance(node: Node?) { + fileprivate func balance(node: Node?) { guard let node = node else { return } - updateHeightUpwards(node.leftChild) - updateHeightUpwards(node.rightChild) + updateHeightUpwards(node: node.leftChild) + updateHeightUpwards(node: node.rightChild) - var nodes = [Node?](count: 3, repeatedValue: nil) - var subtrees = [Node?](count: 4, repeatedValue: nil) + var nodes = [Node?](repeating: nil, count: 3) + var subtrees = [Node?](repeating: nil, count: 4) let nodeParent = node.parent - let lrFactor = lrDifference(node) + let lrFactor = lrDifference(node: node) if lrFactor > 1 { // left-left or left-right - if lrDifference(node.leftChild) > 0 { + if lrDifference(node: node.leftChild) > 0 { // left-left nodes[0] = node nodes[2] = node.leftChild @@ -230,7 +230,7 @@ extension AVLTree { } } else if lrFactor < -1 { // right-left or right-right - if lrDifference(node.rightChild) < 0 { + if lrDifference(node: node.rightChild) < 0 { // right-right nodes[1] = node nodes[2] = node.rightChild @@ -253,7 +253,7 @@ extension AVLTree { } } else { // Don't need to balance 'node', go for parent - balance(node.parent) + balance(node: node.parent) return } @@ -285,19 +285,19 @@ extension AVLTree { nodes[0]?.rightChild = subtrees[3] subtrees[3]?.parent = nodes[0] - updateHeightUpwards(nodes[1]) // Update height from left - updateHeightUpwards(nodes[0]) // Update height from right + updateHeightUpwards(node: nodes[1]) // Update height from left + updateHeightUpwards(node: nodes[0]) // Update height from right - balance(nodes[2]?.parent) + balance(node: nodes[2]?.parent) } } // MARK: - Displaying tree extension AVLTree { - private func display(node: Node?, level: Int) { + fileprivate func display(node: Node?, level: Int) { if let node = node { - display(node.rightChild, level: level + 1) + display(node: node.rightChild, level: level + 1) print("") if node.isRoot { print("Root -> ", terminator: "") @@ -306,12 +306,12 @@ extension AVLTree { print(" ", terminator: "") } print("(\(node.key):\(node.height))", terminator: "") - display(node.leftChild, level: level + 1) + display(node: node.leftChild, level: level + 1) } } public func display(node: Node) { - display(node, level: 0) + display(node: node, level: 0) print("") } } @@ -323,8 +323,8 @@ extension AVLTree { if size == 1 { root = nil size -= 1 - } else if let node = search(key, root) { - delete(node) + } else if let node = search(key: key, node: root) { + delete(node: node) size -= 1 } } @@ -344,21 +344,21 @@ extension AVLTree { parent.rightChild = nil } - balance(parent) + balance(node: parent) } else { // at root root = nil } } else { // Handle stem cases - if let replacement = node.leftChild?.maximum() where replacement !== node { + if let replacement = node.leftChild?.maximum() , replacement !== node { node.key = replacement.key node.payload = replacement.payload - delete(replacement) - } else if let replacement = node.rightChild?.minimum() where replacement !== node { + delete(node: replacement) + } else if let replacement = node.rightChild?.minimum() , replacement !== node { node.key = replacement.key node.payload = replacement.payload - delete(replacement) + delete(node: replacement) } } } diff --git a/AVL Tree/AVLTree.playground/timeline.xctimeline b/AVL Tree/AVLTree.playground/timeline.xctimeline deleted file mode 100644 index bf468afec..000000000 --- a/AVL Tree/AVLTree.playground/timeline.xctimeline +++ /dev/null @@ -1,6 +0,0 @@ - - - - - From cd9c8246e7c14c89503b642ee25ab12888a30f63 Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Fri, 19 Aug 2016 00:45:38 +1200 Subject: [PATCH 0455/1679] Updating readme. Removing mentions of methods that are not contained in the AVLTree.swift file. --- AVL Tree/README.markdown | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/AVL Tree/README.markdown b/AVL Tree/README.markdown index 744d9a272..159f9e1dc 100644 --- a/AVL Tree/README.markdown +++ b/AVL Tree/README.markdown @@ -56,11 +56,7 @@ Most of the code in [AVLTree.swift](AVLTree.swift) is just regular [binary searc > **Note:** If you're a bit fuzzy on the regular operations of a binary search tree, I suggest you [catch up on those first](../Binary Search Tree/). It will make the rest of the AVL tree easier to understand. -The interesting bits are in the following methods: - -- `updateBalance()`. Called after inserting a new node. This may cause the node's parent to be rebalanced. -- `rebalance()`. Figures out how to rotate the nodes to restore the balance. -- `rotateRight()` and `rotateLeft()` perform the actual rotations. +The interesting bits are in the `balance()` method which is called after inserting or deleting a node. ## See also From aec3405f297ae40832057b8b29486ca54e012c17 Mon Sep 17 00:00:00 2001 From: lenli Date: Fri, 19 Aug 2016 18:00:48 -0400 Subject: [PATCH 0456/1679] Upgrade binary search code and test to Swift 3.0 --- .../BinarySearch.playground/Contents.swift | 59 ++------ .../Sources/BinarySearch.swift | 52 +++++++ Binary Search/BinarySearch.swift | 64 ++++++--- Binary Search/README.markdown | 131 +++++++++--------- .../project.pbxproj | 30 ++-- .../contents.xcworkspacedata | 0 .../xcshareddata/xcschemes/Tests.xcscheme | 26 ++-- 7 files changed, 207 insertions(+), 155 deletions(-) create mode 100644 Binary Search/BinarySearch.playground/Sources/BinarySearch.swift rename Binary Search/Tests/{Tests.xcodeproj => BinarySearchTests.xcodeproj}/project.pbxproj (89%) rename Binary Search/Tests/{Tests.xcodeproj => BinarySearchTests.xcodeproj}/project.xcworkspace/contents.xcworkspacedata (100%) rename Binary Search/Tests/{Tests.xcodeproj => BinarySearchTests.xcodeproj}/xcshareddata/xcschemes/Tests.xcscheme (77%) diff --git a/Binary Search/BinarySearch.playground/Contents.swift b/Binary Search/BinarySearch.playground/Contents.swift index fdfd37d8f..cccf9f8ac 100644 --- a/Binary Search/BinarySearch.playground/Contents.swift +++ b/Binary Search/BinarySearch.playground/Contents.swift @@ -4,53 +4,16 @@ let numbers = [11, 59, 3, 2, 53, 17, 31, 7, 19, 67, 47, 13, 37, 61, 29, 43, 5, 41, 23] // Binary search requires that the array is sorted from low to high -let sorted = numbers.sort() +let sorted = numbers.sorted() -/* - The recursive version of binary search. -*/ -func binarySearch(a: [T], key: T, range: Range) -> Int? { - if range.startIndex >= range.endIndex { - return nil - } else { - let midIndex = range.startIndex + (range.endIndex - range.startIndex) / 2 - if a[midIndex] > key { - return binarySearch(a, key: key, range: range.startIndex ..< midIndex) - } else if a[midIndex] < key { - return binarySearch(a, key: key, range: midIndex + 1 ..< range.endIndex) - } else { - return midIndex - } - } -} +// Using recursive solution +binarySearch(a: sorted, key: 2, range: 0 ..< sorted.count) // gives 0 +binarySearch(a: sorted, key: 67, range: 0 ..< sorted.count) // gives 18 +binarySearch(a: sorted, key: 43, range: 0 ..< sorted.count) // gives 13 +binarySearch(a: sorted, key: 42, range: 0 ..< sorted.count) // nil -binarySearch(sorted, key: 2, range: 0 ..< sorted.count) // gives 0 -binarySearch(sorted, key: 67, range: 0 ..< sorted.count) // gives 18 -binarySearch(sorted, key: 43, range: 0 ..< sorted.count) // gives 13 -binarySearch(sorted, key: 42, range: 0 ..< sorted.count) // nil - -/* - The iterative version of binary search. - - Notice how similar these functions are. The difference is that this one - uses a while loop, while the other calls itself recursively. -*/ -func binarySearch(a: [T], key: T) -> Int? { - var range = 0..(a: [T], key: T, range: Range) -> Int? { + if range.lowerBound >= range.upperBound { + return nil + } else { + let midIndex = range.lowerBound + (range.upperBound - range.lowerBound) / 2 + if a[midIndex] > key { + return binarySearch(a: a, key: key, range: range.lowerBound ..< midIndex) + } else if a[midIndex] < key { + return binarySearch(a: a, key: key, range: midIndex + 1 ..< range.upperBound) + } else { + return midIndex + } + } +} + +/** + The iterative version of binary search. + + Notice how similar these functions are. The difference is that this one + uses a while loop, while the other calls itself recursively. + **/ + +public func binarySearch(a: [T], key: T) -> Int? { + var lowerBound = 0 + var upperBound = a.count + while lowerBound < upperBound { + let midIndex = lowerBound + (upperBound - lowerBound) / 2 + if a[midIndex] == key { + return midIndex + } else if a[midIndex] < key { + lowerBound = midIndex + 1 + } else { + upperBound = midIndex + } + } + return nil +} diff --git a/Binary Search/BinarySearch.swift b/Binary Search/BinarySearch.swift index 5bcdf4152..d6623e355 100644 --- a/Binary Search/BinarySearch.swift +++ b/Binary Search/BinarySearch.swift @@ -1,24 +1,52 @@ -/* - Binary Search +/** + Binary Search + + Recursively splits the array in half until the value is found. + + If there is more than one occurrence of the search key in the array, then + there is no guarantee which one it finds. + + Note: The array must be sorted! + **/ - Recursively splits the array in half until the value is found. +import Foundation - If there is more than one occurrence of the search key in the array, then - there is no guarantee which one it finds. +// The recursive version of binary search. - Note: The array must be sorted! -*/ -func binarySearch(a: [T], key: T) -> Int? { - var range = 0..(_ a: [T], key: T, range: Range) -> Int? { + if range.lowerBound >= range.upperBound { + return nil } else { - range.endIndex = midIndex + let midIndex = range.lowerBound + (range.upperBound - range.lowerBound) / 2 + if a[midIndex] > key { + return binarySearch(a, key: key, range: range.lowerBound ..< midIndex) + } else if a[midIndex] < key { + return binarySearch(a, key: key, range: midIndex + 1 ..< range.upperBound) + } else { + return midIndex + } } - } - return nil +} + +/** + The iterative version of binary search. + + Notice how similar these functions are. The difference is that this one + uses a while loop, while the other calls itself recursively. + **/ + +public func binarySearch(_ a: [T], key: T) -> Int? { + var lowerBound = 0 + var upperBound = a.count + while lowerBound < upperBound { + let midIndex = lowerBound + (upperBound - lowerBound) / 2 + if a[midIndex] == key { + return midIndex + } else if a[midIndex] < key { + lowerBound = midIndex + 1 + } else { + upperBound = midIndex + } + } + return nil } diff --git a/Binary Search/README.markdown b/Binary Search/README.markdown index 8c5d8f0f1..6fb6e9985 100644 --- a/Binary Search/README.markdown +++ b/Binary Search/README.markdown @@ -16,12 +16,12 @@ The built-in `indexOf()` function performs a [linear search](../Linear Search/). ```swift func linearSearch(a: [T], _ key: T) -> Int? { - for i in 0 ..< a.count { - if a[i] == key { - return i - } - } - return nil +for i in 0 ..< a.count { +if a[i] == key { +return i +} +} +return nil } ``` @@ -58,27 +58,27 @@ Here is a recursive implementation of binary search in Swift: ```swift func binarySearch(a: [T], key: T, range: Range) -> Int? { - if range.startIndex >= range.endIndex { - // If we get here, then the search key is not present in the array. - return nil - - } else { - // Calculate where to split the array. - let midIndex = range.startIndex + (range.endIndex - range.startIndex) / 2 - - // Is the search key in the left half? - if a[midIndex] > key { - return binarySearch(a, key: key, range: range.startIndex ..< midIndex) - - // Is the search key in the right half? - } else if a[midIndex] < key { - return binarySearch(a, key: key, range: midIndex + 1 ..< range.endIndex) - - // If we get here, then we've found the search key! - } else { - return midIndex - } - } +if range.lowerBound >= range.upperBound { +// If we get here, then the search key is not present in the array. +return nil + +} else { +// Calculate where to split the array. +let midIndex = range.lowerBound + (range.upperBound - range.lowerBound) / 2 + +// Is the search key in the left half? +if a[midIndex] > key { +return binarySearch(a, key: key, range: range.lowerBound ..< midIndex) + +// Is the search key in the right half? +} else if a[midIndex] < key { +return binarySearch(a, key: key, range: midIndex + 1 ..< range.upperBound) + +// If we get here, then we've found the search key! +} else { +return midIndex +} +} } ``` @@ -94,7 +94,7 @@ Note that the `numbers` array is sorted. The binary search algorithm does not wo I said that binary search works by splitting the array in half, but we don't actually create two new arrays. Instead, we keep track of these splits using a Swift `Range` object. Initially, this range covers the entire array, `0 ..< numbers.count`. As we split the array, the range becomes smaller and smaller. -> **Note:** One thing to be aware of is that `range.endIndex` always points one beyond the last element. In the example, the range is `0..<19` because there are 19 numbers in the array, and so `range.startIndex = 0` and `range.endIndex = 19`. But in our array the last element is at index 18, not 19, since we start counting from 0. Just keep this in mind when working with ranges: the `endIndex` is always one more than the index of the last element. +> **Note:** One thing to be aware of is that `range.upperBound` always points one beyond the last element. In the example, the range is `0..<19` because there are 19 numbers in the array, and so `range.lowerBound = 0` and `range.upperBound = 19`. But in our array the last element is at index 18, not 19, since we start counting from 0. Just keep this in mind when working with ranges: the `upperBound` is always one more than the index of the last element. ## Stepping through the example @@ -102,76 +102,76 @@ It might be useful to look at how the algorithm works in detail. The array from the above example consists of 19 numbers and looks like this when sorted: - [ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67 ] +[ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67 ] We're trying to determine if the number `43` is in this array. To split the array in half, we need to know the index of the object in the middle. That's determined by this line: ```swift - let midIndex = range.startIndex + (range.endIndex - range.startIndex) / 2 +let midIndex = range.lowerBound + (range.upperBound - range.lowerBound) / 2 ``` -Initially, the range has `startIndex = 0` and `endIndex = 19`. Filling in these values, we find that `midIndex` is `0 + (19 - 0)/2 = 19/2 = 9`. It's actually `9.5` but because we're using integers, the answer is rounded down. +Initially, the range has `lowerBound = 0` and `upperBound = 19`. Filling in these values, we find that `midIndex` is `0 + (19 - 0)/2 = 19/2 = 9`. It's actually `9.5` but because we're using integers, the answer is rounded down. In the next figure, the `*` shows the middle item. As you can see, the number of items on each side is the same, so we're split right down the middle. - [ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67 ] - * +[ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67 ] +* Now binary search will determine which half to use. The relevant section from the code is: ```swift - if a[midIndex] > key { - // use left half - } else if a[midIndex] < key { - // use right half - } else { - return midIndex - } +if a[midIndex] > key { +// use left half +} else if a[midIndex] < key { +// use right half +} else { +return midIndex +} ``` In this case, `a[midIndex] = 29`. That's less than the search key, so we can safely conclude that the search key will never be in the left half of the array. After all, the left half only contains numbers smaller than `29`. Hence, the search key must be in the right half somewhere (or not in the array at all). -Now we can simply repeat the binary search, but on the array interval from `midIndex + 1` to `range.endIndex`: +Now we can simply repeat the binary search, but on the array interval from `midIndex + 1` to `range.upperBound`: - [ x, x, x, x, x, x, x, x, x, x | 31, 37, 41, 43, 47, 53, 59, 61, 67 ] +[ x, x, x, x, x, x, x, x, x, x | 31, 37, 41, 43, 47, 53, 59, 61, 67 ] Since we no longer need to concern ourselves with the left half of the array, I've marked that with `x`'s. From now on we'll only look at the right half, which starts at array index 10. We calculate the index of the new middle element: `midIndex = 10 + (19 - 10)/2 = 14`, and split the array down the middle again. - [ x, x, x, x, x, x, x, x, x, x | 31, 37, 41, 43, 47, 53, 59, 61, 67 ] - * +[ x, x, x, x, x, x, x, x, x, x | 31, 37, 41, 43, 47, 53, 59, 61, 67 ] +* As you can see, `a[14]` is indeed the middle element of the array's right half. Is the search key greater or smaller than `a[14]`? It's smaller because `43 < 47`. This time we're taking the left half and ignore the larger numbers on the right: - [ x, x, x, x, x, x, x, x, x, x | 31, 37, 41, 43 | x, x, x, x, x ] +[ x, x, x, x, x, x, x, x, x, x | 31, 37, 41, 43 | x, x, x, x, x ] The new `midIndex` is here: - [ x, x, x, x, x, x, x, x, x, x | 31, 37, 41, 43 | x, x, x, x, x ] - * +[ x, x, x, x, x, x, x, x, x, x | 31, 37, 41, 43 | x, x, x, x, x ] +* The search key is greater than `37`, so continue with the right side: - [ x, x, x, x, x, x, x, x, x, x | x, x | 41, 43 | x, x, x, x, x ] - * +[ x, x, x, x, x, x, x, x, x, x | x, x | 41, 43 | x, x, x, x, x ] +* Again, the search key is greater, so split once more and take the right side: - [ x, x, x, x, x, x, x, x, x, x | x, x | x | 43 | x, x, x, x, x ] - * +[ x, x, x, x, x, x, x, x, x, x | x, x | x | 43 | x, x, x, x, x ] +* And now we're done. The search key equals the array element we're looking at, so we've finally found what we were searching for: number `43` is at array index `13`. w00t! It may have seemed like a lot of work, but in reality it only took four steps to find the search key in the array, which sounds about right because `log_2(19) = 4.23`. With a linear search, it would have taken 14 steps. -What would happen if we were to search for `42` instead of `43`? In that case, we can't split up the array any further. The `range.endIndex` becomes smaller than `range.startIndex`. That tells the algorithm the search key is not in the array and it returns `nil`. +What would happen if we were to search for `42` instead of `43`? In that case, we can't split up the array any further. The `range.upperBound` becomes smaller than `range.lowerBound`. That tells the algorithm the search key is not in the array and it returns `nil`. -> **Note:** Many implementations of binary search calculate `midIndex = (startIndex + endIndex) / 2`. This contains a subtle bug that only appears with very large arrays, because `startIndex + endIndex` may overflow the maximum number an integer can hold. This situation is unlikely to happen on a 64-bit CPU, but it definitely can on 32-bit machines. +> **Note:** Many implementations of binary search calculate `midIndex = (lowerBound + upperBound) / 2`. This contains a subtle bug that only appears with very large arrays, because `lowerBound + upperBound` may overflow the maximum number an integer can hold. This situation is unlikely to happen on a 64-bit CPU, but it definitely can on 32-bit machines. ## Iterative vs recursive @@ -181,18 +181,19 @@ Here is an iterative implementation of binary search in Swift: ```swift func binarySearch(a: [T], key: T) -> Int? { - var range = 0.. + BuildableName = "BinarySearchTests.xctest" + BlueprintName = "BinarySearchTests" + ReferencedContainer = "container:BinarySearchTests.xcodeproj"> @@ -33,9 +33,9 @@ + BuildableName = "BinarySearchTests.xctest" + BlueprintName = "BinarySearchTests" + ReferencedContainer = "container:BinarySearchTests.xcodeproj"> @@ -56,9 +56,9 @@ + BuildableName = "BinarySearchTests.xctest" + BlueprintName = "BinarySearchTests" + ReferencedContainer = "container:BinarySearchTests.xcodeproj"> @@ -74,9 +74,9 @@ + BuildableName = "BinarySearchTests.xctest" + BlueprintName = "BinarySearchTests" + ReferencedContainer = "container:BinarySearchTests.xcodeproj"> From fba86e174042e95692f8e8b3a6e989bdba5b4141 Mon Sep 17 00:00:00 2001 From: lenli Date: Fri, 19 Aug 2016 18:14:22 -0400 Subject: [PATCH 0457/1679] Fix code indentation on Binary Search readme --- Binary Search/README.markdown | 86 +++++++++++++++++------------------ 1 file changed, 43 insertions(+), 43 deletions(-) diff --git a/Binary Search/README.markdown b/Binary Search/README.markdown index 6fb6e9985..0faa46128 100644 --- a/Binary Search/README.markdown +++ b/Binary Search/README.markdown @@ -16,12 +16,12 @@ The built-in `indexOf()` function performs a [linear search](../Linear Search/). ```swift func linearSearch(a: [T], _ key: T) -> Int? { -for i in 0 ..< a.count { -if a[i] == key { -return i -} -} -return nil + for i in 0 ..< a.count { + if a[i] == key { + return i + } + } + return nil } ``` @@ -58,27 +58,27 @@ Here is a recursive implementation of binary search in Swift: ```swift func binarySearch(a: [T], key: T, range: Range) -> Int? { -if range.lowerBound >= range.upperBound { -// If we get here, then the search key is not present in the array. -return nil - -} else { -// Calculate where to split the array. -let midIndex = range.lowerBound + (range.upperBound - range.lowerBound) / 2 - -// Is the search key in the left half? -if a[midIndex] > key { -return binarySearch(a, key: key, range: range.lowerBound ..< midIndex) - -// Is the search key in the right half? -} else if a[midIndex] < key { -return binarySearch(a, key: key, range: midIndex + 1 ..< range.upperBound) - -// If we get here, then we've found the search key! -} else { -return midIndex -} -} + if range.lowerBound >= range.upperBound { + // If we get here, then the search key is not present in the array. + return nil + + } else { + // Calculate where to split the array. + let midIndex = range.lowerBound + (range.upperBound - range.lowerBound) / 2 + + // Is the search key in the left half? + if a[midIndex] > key { + return binarySearch(a, key: key, range: range.lowerBound ..< midIndex) + + // Is the search key in the right half? + } else if a[midIndex] < key { + return binarySearch(a, key: key, range: midIndex + 1 ..< range.upperBound) + + // If we get here, then we've found the search key! + } else { + return midIndex + } + } } ``` @@ -123,11 +123,11 @@ Now binary search will determine which half to use. The relevant section from th ```swift if a[midIndex] > key { -// use left half + // use left half } else if a[midIndex] < key { -// use right half + // use right half } else { -return midIndex + return midIndex } ``` @@ -181,19 +181,19 @@ Here is an iterative implementation of binary search in Swift: ```swift func binarySearch(a: [T], key: T) -> Int? { -var lowerBound = 0 -var upperBound = a.count -while lowerBound < upperBound { -let midIndex = lowerBound + (upperBound - lowerBound) / 2 -if a[midIndex] == key { -return midIndex -} else if a[midIndex] < key { -lowerBound = midIndex + 1 -} else { -upperBound = midIndex -} -} -return nil + var lowerBound = 0 + var upperBound = a.count + while lowerBound < upperBound { + let midIndex = lowerBound + (upperBound - lowerBound) / 2 + if a[midIndex] == key { + return midIndex + } else if a[midIndex] < key { + lowerBound = midIndex + 1 + } else { + upperBound = midIndex + } + } + return nil } ``` From 232c92f1760601e35e8e9f3fe87df6706e6ccb6a Mon Sep 17 00:00:00 2001 From: lenli Date: Fri, 19 Aug 2016 18:19:55 -0400 Subject: [PATCH 0458/1679] Fix array midpoint figures in Binary Search readme --- Binary Search/README.markdown | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/Binary Search/README.markdown b/Binary Search/README.markdown index 0faa46128..0aa039254 100644 --- a/Binary Search/README.markdown +++ b/Binary Search/README.markdown @@ -102,7 +102,7 @@ It might be useful to look at how the algorithm works in detail. The array from the above example consists of 19 numbers and looks like this when sorted: -[ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67 ] + [ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67 ] We're trying to determine if the number `43` is in this array. @@ -116,8 +116,8 @@ Initially, the range has `lowerBound = 0` and `upperBound = 19`. Filling in thes In the next figure, the `*` shows the middle item. As you can see, the number of items on each side is the same, so we're split right down the middle. -[ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67 ] -* + [ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67 ] + * Now binary search will determine which half to use. The relevant section from the code is: @@ -135,35 +135,35 @@ In this case, `a[midIndex] = 29`. That's less than the search key, so we can saf Now we can simply repeat the binary search, but on the array interval from `midIndex + 1` to `range.upperBound`: -[ x, x, x, x, x, x, x, x, x, x | 31, 37, 41, 43, 47, 53, 59, 61, 67 ] + [ x, x, x, x, x, x, x, x, x, x | 31, 37, 41, 43, 47, 53, 59, 61, 67 ] Since we no longer need to concern ourselves with the left half of the array, I've marked that with `x`'s. From now on we'll only look at the right half, which starts at array index 10. We calculate the index of the new middle element: `midIndex = 10 + (19 - 10)/2 = 14`, and split the array down the middle again. -[ x, x, x, x, x, x, x, x, x, x | 31, 37, 41, 43, 47, 53, 59, 61, 67 ] -* + [ x, x, x, x, x, x, x, x, x, x | 31, 37, 41, 43, 47, 53, 59, 61, 67 ] + * As you can see, `a[14]` is indeed the middle element of the array's right half. Is the search key greater or smaller than `a[14]`? It's smaller because `43 < 47`. This time we're taking the left half and ignore the larger numbers on the right: -[ x, x, x, x, x, x, x, x, x, x | 31, 37, 41, 43 | x, x, x, x, x ] + [ x, x, x, x, x, x, x, x, x, x | 31, 37, 41, 43 | x, x, x, x, x ] The new `midIndex` is here: -[ x, x, x, x, x, x, x, x, x, x | 31, 37, 41, 43 | x, x, x, x, x ] -* + [ x, x, x, x, x, x, x, x, x, x | 31, 37, 41, 43 | x, x, x, x, x ] + * The search key is greater than `37`, so continue with the right side: -[ x, x, x, x, x, x, x, x, x, x | x, x | 41, 43 | x, x, x, x, x ] -* + [ x, x, x, x, x, x, x, x, x, x | x, x | 41, 43 | x, x, x, x, x ] + * Again, the search key is greater, so split once more and take the right side: -[ x, x, x, x, x, x, x, x, x, x | x, x | x | 43 | x, x, x, x, x ] -* + [ x, x, x, x, x, x, x, x, x, x | x, x | x | 43 | x, x, x, x, x ] + * And now we're done. The search key equals the array element we're looking at, so we've finally found what we were searching for: number `43` is at array index `13`. w00t! From 19cc32e3d6d0ccd9c9e507b2f52a9679c44823a9 Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Sat, 20 Aug 2016 20:47:51 +1200 Subject: [PATCH 0459/1679] Enabling binary search tree tests. Removed unused xcodeproj file. --- .travis.yml | 2 +- .../project.pbxproj | 20 ++++++++-------- .../contents.xcworkspacedata | 0 .../xcshareddata/xcschemes/Tests.xcscheme | 24 +++++++++---------- 4 files changed, 23 insertions(+), 23 deletions(-) rename Binary Search/Tests/{BinarySearchTests.xcodeproj => Tests.xcodeproj}/project.pbxproj (92%) rename Binary Search/Tests/{BinarySearchTests.xcodeproj => Tests.xcodeproj}/project.xcworkspace/contents.xcworkspacedata (100%) rename Binary Search/Tests/{BinarySearchTests.xcodeproj => Tests.xcodeproj}/xcshareddata/xcschemes/Tests.xcscheme (78%) diff --git a/.travis.yml b/.travis.yml index 970f85aa8..0ed853d81 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,7 +11,7 @@ script: # - xcodebuild test -project ./All-Pairs\ Shortest\ Paths/APSP/APSP.xcodeproj -scheme APSPTests # - xcodebuild test -project ./Array2D/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./AVL\ Tree/Tests/Tests.xcodeproj -scheme Tests -# - xcodebuild test -project ./Binary\ Search/Tests/Tests.xcodeproj -scheme Tests + - xcodebuild test -project ./Binary\ Search/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Binary\ Search\ Tree/Solution\ 1/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Bloom\ Filter/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Bounded\ Priority\ Queue/Tests/Tests.xcodeproj -scheme Tests diff --git a/Binary Search/Tests/BinarySearchTests.xcodeproj/project.pbxproj b/Binary Search/Tests/Tests.xcodeproj/project.pbxproj similarity index 92% rename from Binary Search/Tests/BinarySearchTests.xcodeproj/project.pbxproj rename to Binary Search/Tests/Tests.xcodeproj/project.pbxproj index 2db8ac5b6..6e29252ec 100644 --- a/Binary Search/Tests/BinarySearchTests.xcodeproj/project.pbxproj +++ b/Binary Search/Tests/Tests.xcodeproj/project.pbxproj @@ -12,7 +12,7 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ - 7B2BBC801C779D720067B71D /* BinarySearchTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = BinarySearchTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 7B2BBC801C779D720067B71D /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 7B2BBC941C779E7B0067B71D /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; 7B80C3CD1C77A256003CECC7 /* BinarySearchTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BinarySearchTests.swift; sourceTree = SOURCE_ROOT; }; 7B80C3CF1C77A263003CECC7 /* BinarySearch.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BinarySearch.swift; path = ../BinarySearch.swift; sourceTree = SOURCE_ROOT; }; @@ -40,7 +40,7 @@ 7B2BBC721C779D710067B71D /* Products */ = { isa = PBXGroup; children = ( - 7B2BBC801C779D720067B71D /* BinarySearchTests.xctest */, + 7B2BBC801C779D720067B71D /* Tests.xctest */, ); name = Products; sourceTree = ""; @@ -59,9 +59,9 @@ /* End PBXGroup section */ /* Begin PBXNativeTarget section */ - 7B2BBC7F1C779D720067B71D /* BinarySearchTests */ = { + 7B2BBC7F1C779D720067B71D /* Tests */ = { isa = PBXNativeTarget; - buildConfigurationList = 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "BinarySearchTests" */; + buildConfigurationList = 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */; buildPhases = ( 7B2BBC7C1C779D720067B71D /* Sources */, 7B2BBC7D1C779D720067B71D /* Frameworks */, @@ -71,9 +71,9 @@ ); dependencies = ( ); - name = BinarySearchTests; + name = Tests; productName = TestsTests; - productReference = 7B2BBC801C779D720067B71D /* BinarySearchTests.xctest */; + productReference = 7B2BBC801C779D720067B71D /* Tests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; /* End PBXNativeTarget section */ @@ -92,7 +92,7 @@ }; }; }; - buildConfigurationList = 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "BinarySearchTests" */; + buildConfigurationList = 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; @@ -105,7 +105,7 @@ projectDirPath = ""; projectRoot = ""; targets = ( - 7B2BBC7F1C779D720067B71D /* BinarySearchTests */, + 7B2BBC7F1C779D720067B71D /* Tests */, ); }; /* End PBXProject section */ @@ -245,7 +245,7 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "BinarySearchTests" */ = { + 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 7B2BBC871C779D720067B71D /* Debug */, @@ -254,7 +254,7 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "BinarySearchTests" */ = { + 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 7B2BBC8D1C779D720067B71D /* Debug */, diff --git a/Binary Search/Tests/BinarySearchTests.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Binary Search/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata similarity index 100% rename from Binary Search/Tests/BinarySearchTests.xcodeproj/project.xcworkspace/contents.xcworkspacedata rename to Binary Search/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata diff --git a/Binary Search/Tests/BinarySearchTests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Binary Search/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme similarity index 78% rename from Binary Search/Tests/BinarySearchTests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme rename to Binary Search/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme index d6cd9152b..14f27f777 100644 --- a/Binary Search/Tests/BinarySearchTests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme +++ b/Binary Search/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -15,9 +15,9 @@ + BuildableName = "Tests.xctest" + BlueprintName = "Tests" + ReferencedContainer = "container:Tests.xcodeproj"> @@ -33,9 +33,9 @@ + BuildableName = "Tests.xctest" + BlueprintName = "Tests" + ReferencedContainer = "container:Tests.xcodeproj"> @@ -56,9 +56,9 @@ + BuildableName = "Tests.xctest" + BlueprintName = "Tests" + ReferencedContainer = "container:Tests.xcodeproj"> @@ -74,9 +74,9 @@ + BuildableName = "Tests.xctest" + BlueprintName = "Tests" + ReferencedContainer = "container:Tests.xcodeproj"> From 20236b26099c0a4041f1043e26aa46281c229ca4 Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Sat, 20 Aug 2016 20:55:31 +1200 Subject: [PATCH 0460/1679] Removing "a" label from binarySearch method in playground so it matches BinarySearch.swift. Applying same change to readme. --- .../BinarySearch.playground/Contents.swift | 16 ++++++++-------- .../Sources/BinarySearch.swift | 8 ++++---- Binary Search/README.markdown | 8 ++++---- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/Binary Search/BinarySearch.playground/Contents.swift b/Binary Search/BinarySearch.playground/Contents.swift index cccf9f8ac..f673f25c4 100644 --- a/Binary Search/BinarySearch.playground/Contents.swift +++ b/Binary Search/BinarySearch.playground/Contents.swift @@ -7,13 +7,13 @@ let numbers = [11, 59, 3, 2, 53, 17, 31, 7, 19, 67, 47, 13, 37, 61, 29, 43, 5, 4 let sorted = numbers.sorted() // Using recursive solution -binarySearch(a: sorted, key: 2, range: 0 ..< sorted.count) // gives 0 -binarySearch(a: sorted, key: 67, range: 0 ..< sorted.count) // gives 18 -binarySearch(a: sorted, key: 43, range: 0 ..< sorted.count) // gives 13 -binarySearch(a: sorted, key: 42, range: 0 ..< sorted.count) // nil +binarySearch(sorted, key: 2, range: 0 ..< sorted.count) // gives 0 +binarySearch(sorted, key: 67, range: 0 ..< sorted.count) // gives 18 +binarySearch(sorted, key: 43, range: 0 ..< sorted.count) // gives 13 +binarySearch(sorted, key: 42, range: 0 ..< sorted.count) // nil // Using iterative solution -binarySearch(a: sorted, key: 2) // gives 0 -binarySearch(a: sorted, key: 67) // gives 18 -binarySearch(a: sorted, key: 43) // gives 13 -binarySearch(a: sorted, key: 42) // nil +binarySearch(sorted, key: 2) // gives 0 +binarySearch(sorted, key: 67) // gives 18 +binarySearch(sorted, key: 43) // gives 13 +binarySearch(sorted, key: 42) // nil diff --git a/Binary Search/BinarySearch.playground/Sources/BinarySearch.swift b/Binary Search/BinarySearch.playground/Sources/BinarySearch.swift index a7a24bd3a..d6623e355 100644 --- a/Binary Search/BinarySearch.playground/Sources/BinarySearch.swift +++ b/Binary Search/BinarySearch.playground/Sources/BinarySearch.swift @@ -13,15 +13,15 @@ import Foundation // The recursive version of binary search. -public func binarySearch(a: [T], key: T, range: Range) -> Int? { +public func binarySearch(_ a: [T], key: T, range: Range) -> Int? { if range.lowerBound >= range.upperBound { return nil } else { let midIndex = range.lowerBound + (range.upperBound - range.lowerBound) / 2 if a[midIndex] > key { - return binarySearch(a: a, key: key, range: range.lowerBound ..< midIndex) + return binarySearch(a, key: key, range: range.lowerBound ..< midIndex) } else if a[midIndex] < key { - return binarySearch(a: a, key: key, range: midIndex + 1 ..< range.upperBound) + return binarySearch(a, key: key, range: midIndex + 1 ..< range.upperBound) } else { return midIndex } @@ -35,7 +35,7 @@ public func binarySearch(a: [T], key: T, range: Range) -> In uses a while loop, while the other calls itself recursively. **/ -public func binarySearch(a: [T], key: T) -> Int? { +public func binarySearch(_ a: [T], key: T) -> Int? { var lowerBound = 0 var upperBound = a.count while lowerBound < upperBound { diff --git a/Binary Search/README.markdown b/Binary Search/README.markdown index 0aa039254..c65d0b5fd 100644 --- a/Binary Search/README.markdown +++ b/Binary Search/README.markdown @@ -15,7 +15,7 @@ numbers.indexOf(43) // returns 15 The built-in `indexOf()` function performs a [linear search](../Linear Search/). In code that looks something like this: ```swift -func linearSearch(a: [T], _ key: T) -> Int? { +func linearSearch(_ a: [T], _ key: T) -> Int? { for i in 0 ..< a.count { if a[i] == key { return i @@ -45,7 +45,7 @@ Sounds great, but there is a downside to using binary search: the array must be Here's how binary search works: -- Split the array in half and determine whether the thing you're looking for, known as the *search key*, is in the left half or in the right half. +- Split the array in half and determine whether the thing you're looking for, known as the *search key*, is in the left half or in the right half. - How do you determine in which half the search key is? This is why you sorted the array first, so you can do a simple `<` or `>` comparison. - If the search key is in the left half, you repeat the process there: split the left half into two even smaller pieces and look in which piece the search key must lie. (Likewise for when it's the right half.) - This repeats until the search key is found. If the array cannot be split up any further, you must regrettably conclude that the search key is not present in the array. @@ -57,7 +57,7 @@ Now you know why it's called a "binary" search: in every step it splits the arra Here is a recursive implementation of binary search in Swift: ```swift -func binarySearch(a: [T], key: T, range: Range) -> Int? { +func binarySearch(_ a: [T], key: T, range: Range) -> Int? { if range.lowerBound >= range.upperBound { // If we get here, then the search key is not present in the array. return nil @@ -180,7 +180,7 @@ Binary search is recursive in nature because you apply the same logic over and o Here is an iterative implementation of binary search in Swift: ```swift -func binarySearch(a: [T], key: T) -> Int? { +func binarySearch(_ a: [T], key: T) -> Int? { var lowerBound = 0 var upperBound = a.count while lowerBound < upperBound { From 6e77eba6b8c242c09093a160d90dee5ee3e92828 Mon Sep 17 00:00:00 2001 From: Joshua Alvarado Date: Sat, 20 Aug 2016 22:57:42 -0600 Subject: [PATCH 0461/1679] Updated Bubble Sort description Added the runtime, memory and a better description of bubble sort. The implementation was not added but it is good to know the concept. --- Bubble Sort/README.markdown | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/Bubble Sort/README.markdown b/Bubble Sort/README.markdown index 1c3d89798..8660d6d54 100644 --- a/Bubble Sort/README.markdown +++ b/Bubble Sort/README.markdown @@ -1,4 +1,13 @@ # Bubble Sort -This is a horrible algorithm. There is no reason why you should have to know it. +Bubble sort is a sorting algorthim that is implemented by starting in the beginning of the array and swapping the first two elements only if the first element is greater than the second element. This comparision is then moved onto the next pair and so on and so forth. This is done until the the array is completely sorted. The smaller items slowly “bubble” up to the beginning of the array. +Runtime: +- Average: O(N^2) +- Worst: O(N^2) + +Memory: +- O(1) + +Implementation: +The implemenatation will not be shown because as you can see from the average and worst runtimes this is a very inefficent algorithm but having a grasp of the concept will help in getting to know the basics of simple sorting algorthims. From 68f581965f060a2725446bb95c3cbaaa4344b1f6 Mon Sep 17 00:00:00 2001 From: Joshua Alvarado Date: Sat, 20 Aug 2016 23:09:03 -0600 Subject: [PATCH 0462/1679] Updated formatting and grammar errors --- Bubble Sort/README.markdown | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Bubble Sort/README.markdown b/Bubble Sort/README.markdown index 8660d6d54..ceb2a98cb 100644 --- a/Bubble Sort/README.markdown +++ b/Bubble Sort/README.markdown @@ -1,13 +1,14 @@ # Bubble Sort -Bubble sort is a sorting algorthim that is implemented by starting in the beginning of the array and swapping the first two elements only if the first element is greater than the second element. This comparision is then moved onto the next pair and so on and so forth. This is done until the the array is completely sorted. The smaller items slowly “bubble” up to the beginning of the array. +Bubble sort is a sorting algorithm that is implemented by starting in the beginning of the array and swapping the first two elements only if the first element is greater than the second element. This comparison is then moved onto the next pair and so on and so forth. This is done until the the array is completely sorted. The smaller items slowly “bubble” up to the beginning of the array. -Runtime: +##### Runtime: - Average: O(N^2) - Worst: O(N^2) -Memory: +##### Memory: - O(1) -Implementation: -The implemenatation will not be shown because as you can see from the average and worst runtimes this is a very inefficent algorithm but having a grasp of the concept will help in getting to know the basics of simple sorting algorthims. +### Implementation: + +The implementation will not be shown because as you can see from the average and worst runtimes this is a very inefficient algorithm but having a grasp of the concept will help in getting to know the basics of simple sorting algorithms. From a5411848ff096e8da74e7d8cc9ba3e35f3069ee7 Mon Sep 17 00:00:00 2001 From: Mike Taghavi Date: Sun, 21 Aug 2016 19:10:44 +0200 Subject: [PATCH 0463/1679] Add SkipList --- Skip-List/SkipList.swift | 266 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 266 insertions(+) create mode 100644 Skip-List/SkipList.swift diff --git a/Skip-List/SkipList.swift b/Skip-List/SkipList.swift new file mode 100644 index 000000000..b07cd98c8 --- /dev/null +++ b/Skip-List/SkipList.swift @@ -0,0 +1,266 @@ +// The MIT License (MIT) + +// Copyright (c) 2016 Mike Taghavi (mitghi[at]me.com) + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + + +import Foundation + + +// Stack from : https://github.com/raywenderlich/swift-algorithm-club/tree/master/Stack +public struct Stack { + private var array = [T]() + + public var isEmpty: Bool { + return array.isEmpty + } + + public var count: Int { + return array.count + } + + public mutating func push(element: T) { + array.append(element) + } + + public mutating func pop() -> T? { + return array.popLast() + } + + public func peek() -> T? { + return array.last + } +} + +extension Stack: SequenceType { + public func generate() -> AnyGenerator { + var curr = self + return AnyGenerator { + _ -> T? in + return curr.pop() + } + } +} + + +func random() -> Bool { + #if os(Linux) + return random() % 2 == 0 + #elseif os(OSX) + return arc4random_uniform(2) == 1 + #endif +} + + + +class DataNode{ + internal typealias Node = DataNode + + internal var key : Key? + internal var data : Payload? + internal var _next : Node? + internal var _down : Node? + + internal var next: Node? { + get { return self._next } + set(value) { self._next = value } + } + + internal var down:Node? { + get { return self._down } + set(value) { self._down = value } + } + + init(key:Key, data:Payload){ + self.key = key + self.data = data + } + + init(header: Bool){ + } + +} + + +class SkipList{ + internal typealias Node = DataNode + internal var head: Node? + + private func find_head(key:Key) -> Node? { + var current = self.head + var found: Bool = false + + while !found { + if let curr = current { + if curr.next == nil { current = curr.down } + else { + if curr.next!.key == key { found = true } + else { + if key < curr.next!.key{ current = curr.down } + else { current = curr.next } + } + } + } else { + break + } + } + + if found { + return current + } else { + return nil + } + } + + + private func insert_head(key:Key, data:Payload) -> Void { + + self.head = Node(header: true) + var temp = Node(key:key, data:data) + self.head!.next = temp + var top = temp + + while random() { + let newhead = Node(header: true) + temp = Node(key:key, data:data) + temp.down = top + newhead.next = temp + newhead.down = self.head + self.head = newhead + top = temp + } + } + + private func insert_rest(key:Key, data:Payload) -> Void { + var stack = Stack() + var current_head: Node? = self.head + + while current_head != nil { + + if let next = current_head!._next { + if next.key > key { + stack.push(current_head!) + current_head = next + } else { + current_head = next + } + + } else { + stack.push(current_head!) + current_head = current_head!.down + } + + } + + let lowest = stack.pop() + var temp = Node(key:key, data:data) + temp.next = lowest!.next + lowest!.next = temp + var top = temp + + while random() { + if stack.isEmpty { + let newhead = Node(header: true) + temp = Node(key:key, data:data) + temp.down = top + newhead.next = temp + newhead.down = self.head + self.head = newhead + top = temp + } else { + let next = stack.pop() + temp = Node(key:key, data:data) + temp.down = top + temp.next = next!.next + next!.next = temp + top = temp + } + } + } + + func search(key:Key) -> Payload? { + guard let item = self.find_head(key) else { + return nil + } + + return item.next!.data + } + + func remove(key:Key) -> Void { + guard let item = self.find_head(key) else { + return + } + + var curr = Optional(item) + + while curr != nil { + let node = curr!.next + + if node!.key != key { curr = node ; continue } + + let node_next = node!.next + curr!.next = node_next + curr = curr!.down + + } + + } + + func insert(key: Key, data:Payload){ + if self.head != nil{ + if let node = self.find_head(key) { + + var curr = node.next + while curr != nil && curr!.key == key{ + curr!.data = data + curr = curr!.down + } + + } else { + self.insert_rest(key, data:data) + } + + } else { + self.insert_head(key, data:data) + } + } + +} + + +class Map{ + var collection: SkipList + + init(){ + self.collection = SkipList() + } + + func insert(key:Key, data: Payload){ + self.collection.insert(key, data:data) + } + + func get(key:Key) -> Payload?{ + return self.collection.search(key) + } + + func remove(key:Key) -> Void { + return self.collection.remove(key) + } +} From 28df4f3ab785436bf08b1b6f1751f865bc59660c Mon Sep 17 00:00:00 2001 From: Mike Date: Sun, 21 Aug 2016 19:25:31 +0200 Subject: [PATCH 0464/1679] Update README.md --- Skip-List/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Skip-List/README.md b/Skip-List/README.md index 8b1378917..ca1dce7ae 100644 --- a/Skip-List/README.md +++ b/Skip-List/README.md @@ -1 +1,3 @@ +# Skip List +> Skip lists are a probabilistic data structure that seem likely to supplant balanced trees as the implementation method of choice for many applications. Skip list algorithms have the same asymptotic expected time bounds as balanced trees and are simpler, faster and use less space. -**[William Pugh](https://en.wikipedia.org/wiki/William_Pugh)** From 96f58f76902b7ce30142dfa4a1853642b0869ec4 Mon Sep 17 00:00:00 2001 From: Mark Baxter Date: Fri, 26 Aug 2016 08:59:23 -0700 Subject: [PATCH 0465/1679] Swift 3 --- .../Palindromes.playground/Contents.swift | 22 +++++++++---------- Palindromes/Palindromes.swift | 8 +++---- Palindromes/README.markdown | 12 +++++----- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/Palindromes/Palindromes.playground/Contents.swift b/Palindromes/Palindromes.playground/Contents.swift index b548182af..0df899937 100644 --- a/Palindromes/Palindromes.playground/Contents.swift +++ b/Palindromes/Palindromes.playground/Contents.swift @@ -2,7 +2,7 @@ import Cocoa public func palindromeCheck (text: String?) -> Bool { if let text = text { - let mutableText = text.stringByTrimmingCharactersInSet(.whitespaceCharacterSet()).lowercaseString + let mutableText = text.trimmingCharacters(in: NSCharacterSet.whitespaces()) let length: Int = mutableText.characters.count guard length >= 1 else { @@ -11,9 +11,9 @@ public func palindromeCheck (text: String?) -> Bool { if length == 1 { return true - } else if mutableText[mutableText.startIndex] == mutableText[mutableText.endIndex.predecessor()] { - let range = Range(mutableText.startIndex.successor()..(mutableText.index(mutableText.startIndex, offsetBy: 1).. Bool { } // Test to check that non-palindromes are handled correctly: -palindromeCheck("owls") +palindromeCheck(text: "owls") // Test to check that palindromes are accurately found (regardless of case and whitespace: -palindromeCheck("lol") -palindromeCheck("race car") -palindromeCheck("Race fast Safe car") +palindromeCheck(text: "lol") +palindromeCheck(text: "race car") +palindromeCheck(text: "Race fast Safe car") // Test to check that palindromes are found regardless of case: -palindromeCheck("HelloLLEH") +palindromeCheck(text: "HelloLLEH") // Test that nil and empty Strings return false: -palindromeCheck("") -palindromeCheck(nil) +palindromeCheck(text: "") +palindromeCheck(text: nil) diff --git a/Palindromes/Palindromes.swift b/Palindromes/Palindromes.swift index 61e7740ab..1e61cc1ca 100644 --- a/Palindromes/Palindromes.swift +++ b/Palindromes/Palindromes.swift @@ -2,7 +2,7 @@ import Cocoa public func palindromeCheck (text: String?) -> Bool { if let text = text { - let mutableText = text.stringByTrimmingCharactersInSet(.whitespaceCharacterSet()).lowercaseString + let mutableText = text.trimmingCharacters(in: NSCharacterSet.whitespaces()) let length: Int = mutableText.characters.count guard length >= 1 else { @@ -11,9 +11,9 @@ public func palindromeCheck (text: String?) -> Bool { if length == 1 { return true - } else if mutableText[mutableText.startIndex] == mutableText[mutableText.endIndex.predecessor()] { - let range = Range(mutableText.startIndex.successor()..(mutableText.index(mutableText.startIndex, offsetBy: 1).. Bool { if let text = text { - let mutableText = text.stringByTrimmingCharactersInSet(.whitespaceCharacterSet()).lowercaseString + let mutableText = text.trimmingCharacters(in: NSCharacterSet.whitespaces()) let length: Int = mutableText.characters.count - guard length >= 1 { + guard length >= 1 else { return false } if length == 1 { return true - } else if mutableText[mutableText.startIndex] == mutableText[mutableText.endIndex.predecessor()] { - let range = Range(mutableText.startIndex.successor()..(mutableText.index(mutableText.startIndex, offsetBy: 1).. Bool { This code can be tested in a playground using the following: ```swift -palindromeCheck("Race car") +palindromeCheck(text: "Race car") ``` Since the phrase "Race car" is a palindrome, this will return true. From 5f1b0715d5181b89e600fa8c64e74ff91f8c35cc Mon Sep 17 00:00:00 2001 From: Mark Baxter Date: Fri, 26 Aug 2016 09:11:30 -0700 Subject: [PATCH 0466/1679] Swift 3 --- Palindromes/Palindromes.playground/Contents.swift | 2 +- Palindromes/Palindromes.swift | 2 +- Palindromes/README.markdown | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Palindromes/Palindromes.playground/Contents.swift b/Palindromes/Palindromes.playground/Contents.swift index 0df899937..f1a85c073 100644 --- a/Palindromes/Palindromes.playground/Contents.swift +++ b/Palindromes/Palindromes.playground/Contents.swift @@ -2,7 +2,7 @@ import Cocoa public func palindromeCheck (text: String?) -> Bool { if let text = text { - let mutableText = text.trimmingCharacters(in: NSCharacterSet.whitespaces()) + let mutableText = text.trimmingCharacters(in: NSCharacterSet.whitespaces()).lowercased() let length: Int = mutableText.characters.count guard length >= 1 else { diff --git a/Palindromes/Palindromes.swift b/Palindromes/Palindromes.swift index 1e61cc1ca..2082dbb4d 100644 --- a/Palindromes/Palindromes.swift +++ b/Palindromes/Palindromes.swift @@ -2,7 +2,7 @@ import Cocoa public func palindromeCheck (text: String?) -> Bool { if let text = text { - let mutableText = text.trimmingCharacters(in: NSCharacterSet.whitespaces()) + let mutableText = text.trimmingCharacters(in: NSCharacterSet.whitespaces()).lowercased() let length: Int = mutableText.characters.count guard length >= 1 else { diff --git a/Palindromes/README.markdown b/Palindromes/README.markdown index 6d0ff8ef7..12f868251 100644 --- a/Palindromes/README.markdown +++ b/Palindromes/README.markdown @@ -28,7 +28,7 @@ Here is a recursive implementation of this in Swift: ```swift func palindromeCheck (text: String?) -> Bool { if let text = text { - let mutableText = text.trimmingCharacters(in: NSCharacterSet.whitespaces()) + let mutableText = text.trimmingCharacters(in: NSCharacterSet.whitespaces()).lowercased() let length: Int = mutableText.characters.count guard length >= 1 else { From be653b21e366c8225c07f7bc19ae790abb381b86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nemanja=20Vlahovic=CC=81?= Date: Mon, 29 Aug 2016 11:08:07 +0200 Subject: [PATCH 0467/1679] Migrate Array2D algorithm to Swift 3 --- Array2D/Array2D.playground/Contents.swift | 4 ++-- Array2D/Array2D.swift | 4 ++-- Array2D/Tests/Array2DTests.swift | 4 ++-- Array2D/Tests/Tests.xcodeproj/project.pbxproj | 3 +++ 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/Array2D/Array2D.playground/Contents.swift b/Array2D/Array2D.playground/Contents.swift index 0bcb7b5b9..7064de59c 100644 --- a/Array2D/Array2D.playground/Contents.swift +++ b/Array2D/Array2D.playground/Contents.swift @@ -6,12 +6,12 @@ public struct Array2D { public let columns: Int public let rows: Int - private var array: [T] + fileprivate var array: [T] public init(columns: Int, rows: Int, initialValue: T) { self.columns = columns self.rows = rows - array = .init(count: rows*columns, repeatedValue: initialValue) + array = .init(repeatElement(initialValue, count: rows*columns)) } public subscript(column: Int, row: Int) -> T { diff --git a/Array2D/Array2D.swift b/Array2D/Array2D.swift index 6177974d7..6d6c01902 100644 --- a/Array2D/Array2D.swift +++ b/Array2D/Array2D.swift @@ -6,12 +6,12 @@ public struct Array2D { public let columns: Int public let rows: Int - private var array: [T] + fileprivate var array: [T] public init(columns: Int, rows: Int, initialValue: T) { self.columns = columns self.rows = rows - array = .init(count: rows*columns, repeatedValue: initialValue) + array = .init(repeating: initialValue, count: rows*columns) } public subscript(column: Int, row: Int) -> T { diff --git a/Array2D/Tests/Array2DTests.swift b/Array2D/Tests/Array2DTests.swift index f4019a03a..b30769ac4 100644 --- a/Array2D/Tests/Array2DTests.swift +++ b/Array2D/Tests/Array2DTests.swift @@ -43,7 +43,7 @@ class Array2DTest: XCTestCase { } func testPerformanceOnSmallArray() { - self.measureBlock { + self.measure { self.printArrayWith(columns: 2, rows: 2, inititalValue: 1) } } @@ -54,7 +54,7 @@ class Array2DTest: XCTestCase { // } // } - private func printArrayWith(columns columns: Int, rows: Int, inititalValue: Int) { + fileprivate func printArrayWith(columns: Int, rows: Int, inititalValue: Int) { let array = Array2D(columns: columns, rows: rows, initialValue: 4) for r in 0.. Date: Mon, 29 Aug 2016 11:18:20 +0200 Subject: [PATCH 0468/1679] Uncomment Array2D in .travis.yml --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 0ed853d81..1eba40123 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,7 +9,7 @@ install: script: # - xcodebuild test -project ./All-Pairs\ Shortest\ Paths/APSP/APSP.xcodeproj -scheme APSPTests -# - xcodebuild test -project ./Array2D/Tests/Tests.xcodeproj -scheme Tests + - xcodebuild test -project ./Array2D/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./AVL\ Tree/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Binary\ Search/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Binary\ Search\ Tree/Solution\ 1/Tests/Tests.xcodeproj -scheme Tests From 99c00720289b9396b45c9045fea67ee983fbacf5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nemanja=20Vlahovic=CC=81?= Date: Mon, 29 Aug 2016 14:36:12 +0200 Subject: [PATCH 0469/1679] Migrate Stack to Swift 3 --- Stack/Stack.playground/Contents.swift | 6 +++--- Stack/Stack.swift | 10 +++++----- Stack/Tests/Tests.xcodeproj/project.pbxproj | 3 +++ 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/Stack/Stack.playground/Contents.swift b/Stack/Stack.playground/Contents.swift index 4f4f826f2..24b5e7176 100644 --- a/Stack/Stack.playground/Contents.swift +++ b/Stack/Stack.playground/Contents.swift @@ -12,7 +12,7 @@ */ public struct Stack { - private var array = [T]() + fileprivate var array = [T]() public var count: Int { return array.count @@ -36,10 +36,10 @@ public struct Stack { } // Create a stack and put some elements on it already. -var stackOfNames = Stack(array: ["Carl", "Lisa", "Stephanie", "Jeff", "Wade"]) +var stackOfNames = Stack(array:["Carl", "Lisa", "Stephanie", "Jeff", "Wade"]) // Add an element to the top of the stack. -stackOfNames.push("Mike") +stackOfNames.push(element: "Mike") // The stack is now ["Carl", "Lisa", "Stephanie", "Jeff", "Wade", "Mike"] print(stackOfNames.array) diff --git a/Stack/Stack.swift b/Stack/Stack.swift index 454b66fa0..49edaf4cb 100644 --- a/Stack/Stack.swift +++ b/Stack/Stack.swift @@ -4,7 +4,7 @@ Push and pop are O(1) operations. */ public struct Stack { - private var array = [T]() + fileprivate var array = [T]() public var isEmpty: Bool { return array.isEmpty @@ -14,7 +14,7 @@ public struct Stack { return array.count } - public mutating func push(element: T) { + public mutating func push(_ element: T) { array.append(element) } @@ -27,10 +27,10 @@ public struct Stack { } } -extension Stack: SequenceType { - public func generate() -> AnyGenerator { +extension Stack: Sequence { + public func makeIterator() -> AnyIterator { var curr = self - return AnyGenerator { + return AnyIterator { _ -> T? in return curr.pop() } diff --git a/Stack/Tests/Tests.xcodeproj/project.pbxproj b/Stack/Tests/Tests.xcodeproj/project.pbxproj index a36d7c51d..5ec8dc987 100644 --- a/Stack/Tests/Tests.xcodeproj/project.pbxproj +++ b/Stack/Tests/Tests.xcodeproj/project.pbxproj @@ -88,6 +88,7 @@ TargetAttributes = { 7B2BBC7F1C779D720067B71D = { CreatedOnToolsVersion = 7.2; + LastSwiftMigration = 0800; }; }; }; @@ -220,6 +221,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -231,6 +233,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Release; }; From 9ecfd88d02fff6d73a70e4e63ad41c6ed5931051 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nemanja=20Vlahovic=CC=81?= Date: Mon, 29 Aug 2016 14:40:44 +0200 Subject: [PATCH 0470/1679] Revert "Migrate Stack to Swift 3" This reverts commit 99c00720289b9396b45c9045fea67ee983fbacf5. --- Stack/Stack.playground/Contents.swift | 6 +++--- Stack/Stack.swift | 10 +++++----- Stack/Tests/Tests.xcodeproj/project.pbxproj | 3 --- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/Stack/Stack.playground/Contents.swift b/Stack/Stack.playground/Contents.swift index 24b5e7176..4f4f826f2 100644 --- a/Stack/Stack.playground/Contents.swift +++ b/Stack/Stack.playground/Contents.swift @@ -12,7 +12,7 @@ */ public struct Stack { - fileprivate var array = [T]() + private var array = [T]() public var count: Int { return array.count @@ -36,10 +36,10 @@ public struct Stack { } // Create a stack and put some elements on it already. -var stackOfNames = Stack(array:["Carl", "Lisa", "Stephanie", "Jeff", "Wade"]) +var stackOfNames = Stack(array: ["Carl", "Lisa", "Stephanie", "Jeff", "Wade"]) // Add an element to the top of the stack. -stackOfNames.push(element: "Mike") +stackOfNames.push("Mike") // The stack is now ["Carl", "Lisa", "Stephanie", "Jeff", "Wade", "Mike"] print(stackOfNames.array) diff --git a/Stack/Stack.swift b/Stack/Stack.swift index 49edaf4cb..454b66fa0 100644 --- a/Stack/Stack.swift +++ b/Stack/Stack.swift @@ -4,7 +4,7 @@ Push and pop are O(1) operations. */ public struct Stack { - fileprivate var array = [T]() + private var array = [T]() public var isEmpty: Bool { return array.isEmpty @@ -14,7 +14,7 @@ public struct Stack { return array.count } - public mutating func push(_ element: T) { + public mutating func push(element: T) { array.append(element) } @@ -27,10 +27,10 @@ public struct Stack { } } -extension Stack: Sequence { - public func makeIterator() -> AnyIterator { +extension Stack: SequenceType { + public func generate() -> AnyGenerator { var curr = self - return AnyIterator { + return AnyGenerator { _ -> T? in return curr.pop() } diff --git a/Stack/Tests/Tests.xcodeproj/project.pbxproj b/Stack/Tests/Tests.xcodeproj/project.pbxproj index 5ec8dc987..a36d7c51d 100644 --- a/Stack/Tests/Tests.xcodeproj/project.pbxproj +++ b/Stack/Tests/Tests.xcodeproj/project.pbxproj @@ -88,7 +88,6 @@ TargetAttributes = { 7B2BBC7F1C779D720067B71D = { CreatedOnToolsVersion = 7.2; - LastSwiftMigration = 0800; }; }; }; @@ -221,7 +220,6 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -233,7 +231,6 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 3.0; }; name = Release; }; From d6378f859dbf0d0fe65cfd1c69d90cc49f37714c Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Tue, 30 Aug 2016 12:15:29 +1200 Subject: [PATCH 0471/1679] Fixed warning when opening array 2d test project --- Array2D/Tests/Tests.xcodeproj/project.pbxproj | 7 ++++++- .../Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Array2D/Tests/Tests.xcodeproj/project.pbxproj b/Array2D/Tests/Tests.xcodeproj/project.pbxproj index acacd28ea..a0fb1480b 100644 --- a/Array2D/Tests/Tests.xcodeproj/project.pbxproj +++ b/Array2D/Tests/Tests.xcodeproj/project.pbxproj @@ -83,7 +83,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; - LastUpgradeCheck = 0720; + LastUpgradeCheck = 0800; ORGANIZATIONNAME = "Swift Algorithm Club"; TargetAttributes = { 7B2BBC7F1C779D720067B71D = { @@ -146,8 +146,10 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; @@ -190,8 +192,10 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; @@ -210,6 +214,7 @@ MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; }; name = Release; }; diff --git a/Array2D/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Array2D/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme index 8ef8d8581..14f27f777 100644 --- a/Array2D/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme +++ b/Array2D/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -1,6 +1,6 @@ Date: Tue, 30 Aug 2016 12:38:14 +1200 Subject: [PATCH 0472/1679] Fixing NSCharacterSet.whitespaces() warning --- Palindromes/Palindromes.playground/Contents.swift | 4 ++-- Palindromes/Palindromes.swift | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Palindromes/Palindromes.playground/Contents.swift b/Palindromes/Palindromes.playground/Contents.swift index f1a85c073..20df10ee4 100644 --- a/Palindromes/Palindromes.playground/Contents.swift +++ b/Palindromes/Palindromes.playground/Contents.swift @@ -1,8 +1,8 @@ import Cocoa -public func palindromeCheck (text: String?) -> Bool { +public func palindromeCheck(text: String?) -> Bool { if let text = text { - let mutableText = text.trimmingCharacters(in: NSCharacterSet.whitespaces()).lowercased() + let mutableText = text.trimmingCharacters(in: NSCharacterSet.whitespaces).lowercased() let length: Int = mutableText.characters.count guard length >= 1 else { diff --git a/Palindromes/Palindromes.swift b/Palindromes/Palindromes.swift index 2082dbb4d..b873af3b0 100644 --- a/Palindromes/Palindromes.swift +++ b/Palindromes/Palindromes.swift @@ -2,7 +2,7 @@ import Cocoa public func palindromeCheck (text: String?) -> Bool { if let text = text { - let mutableText = text.trimmingCharacters(in: NSCharacterSet.whitespaces()).lowercased() + let mutableText = text.trimmingCharacters(in: NSCharacterSet.whitespaces).lowercased() let length: Int = mutableText.characters.count guard length >= 1 else { From 9646535ec738fa6a72f2202ecd363a0ac7a1a434 Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Tue, 30 Aug 2016 12:39:07 +1200 Subject: [PATCH 0473/1679] Spacing --- Palindromes/Palindromes.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Palindromes/Palindromes.swift b/Palindromes/Palindromes.swift index b873af3b0..036ce3d34 100644 --- a/Palindromes/Palindromes.swift +++ b/Palindromes/Palindromes.swift @@ -1,6 +1,6 @@ import Cocoa -public func palindromeCheck (text: String?) -> Bool { +public func palindromeCheck(text: String?) -> Bool { if let text = text { let mutableText = text.trimmingCharacters(in: NSCharacterSet.whitespaces).lowercased() let length: Int = mutableText.characters.count From 93e1eeab430ff108e44182963f8fc053331e4501 Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Tue, 30 Aug 2016 13:16:39 +1200 Subject: [PATCH 0474/1679] Updating to Swift 3 --- Union-Find/README.markdown | 22 +++++++++---------- .../UnionFind.playground/Contents.swift | 14 ++++++------ Union-Find/UnionFind.swift | 14 ++++++------ 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/Union-Find/README.markdown b/Union-Find/README.markdown index 1d674e965..5102f6b89 100644 --- a/Union-Find/README.markdown +++ b/Union-Find/README.markdown @@ -9,7 +9,7 @@ What do we mean by this? For example, the Union-Find data structure could be kee [ g, d, c ] [ i, j ] -These sets are disjoint because they have no members in common. +These sets are disjoint because they have no members in common. Union-Find supports three basic operations: @@ -41,9 +41,9 @@ Example: If `parent` looks like this, parent [ 1, 1, 1, 0, 2, 0, 6, 6, 6 ] i 0 1 2 3 4 5 6 7 8 - + then the tree structure looks like: - + 1 6 / \ / \ 0 2 7 8 @@ -63,7 +63,7 @@ Note that the `parent[]` of a root node points to itself. So `parent[1] = 1` and Let's look at the implementation of these basic operations, starting with adding a new set. ```swift -public mutating func addSetWith(element: T) { +public mutating func addSetWith(_ element: T) { index[element] = parent.count // 1 parent.append(parent.count) // 2 size.append(1) // 3 @@ -83,7 +83,7 @@ When you add a new element, this actually adds a new subset containing just that Often we want to determine whether we already have a set that contains a given element. That's what the **Find** operation does. In our `UnionFind` data structure it is called `setOf()`: ```swift -public mutating func setOf(element: T) -> Int? { +public mutating func setOf(_ element: T) -> Int? { if let indexOfElement = index[element] { return setByIndex(indexOfElement) } else { @@ -95,7 +95,7 @@ public mutating func setOf(element: T) -> Int? { This looks up the element's index in the `index` dictionary and then uses a helper method to find the set that this element belongs to: ```swift -private mutating func setByIndex(index: Int) -> Int { +private mutating func setByIndex(_ index: Int) -> Int { if parent[index] == index { // 1 return index } else { @@ -109,7 +109,7 @@ Because we're dealing with a tree structure, this is a recursive method. Recall that each set is represented by a tree and that the index of the root node serves as the number that identifies the set. We're going to find the root node of the tree that the element we're searching for belongs to, and return its index. -1. First, we check if the given index represents a root node (i.e. a node whose `parent` points back to the node itself). If so, we're done. +1. First, we check if the given index represents a root node (i.e. a node whose `parent` points back to the node itself). If so, we're done. 2. Otherwise we recursively call this method on the parent of the current node. And then we do a **very important thing**: we overwrite the parent of the current node with the index of root node, in effect reconnecting the node directly to the root of the tree. The next time we call this method, it will execute faster because the path to the root of the tree is now much shorter. Without that optimization, this method's complexity is **O(n)** but now in combination with the size optimization (covered in the Union section) it is almost **O(1)**. @@ -130,8 +130,8 @@ Now if we need to call `setOf(4)` again, we no longer have to go through node `2 There is also a helper method to check that two elements are in the same set: ```swift -public mutating func inSameSet(firstElement: T, and secondElement: T) -> Bool { - if let firstSet = setOf(firstElement), secondSet = setOf(secondElement) { +public mutating func inSameSet(_ firstElement: T, and secondElement: T) -> Bool { + if let firstSet = setOf(firstElement), let secondSet = setOf(secondElement) { return firstSet == secondSet } else { return false @@ -146,8 +146,8 @@ Since this calls `setOf()` it also optimizes the tree. The final operation is **Union**, which combines two sets into one larger set. ```swift -public mutating func unionSetsContaining(firstElement: T, and secondElement: T) { - if let firstSet = setOf(firstElement), secondSet = setOf(secondElement) { // 1 +public mutating func unionSetsContaining(_ firstElement: T, and secondElement: T) { + if let firstSet = setOf(firstElement), let secondSet = setOf(secondElement) { // 1 if firstSet != secondSet { // 2 if size[firstSet] < size[secondSet] { // 3 parent[firstSet] = secondSet // 4 diff --git a/Union-Find/UnionFind.playground/Contents.swift b/Union-Find/UnionFind.playground/Contents.swift index 5747b15b5..09649b938 100644 --- a/Union-Find/UnionFind.playground/Contents.swift +++ b/Union-Find/UnionFind.playground/Contents.swift @@ -5,13 +5,13 @@ public struct UnionFind { private var parent = [Int]() private var size = [Int]() - public mutating func addSetWith(element: T) { + public mutating func addSetWith(_ element: T) { index[element] = parent.count parent.append(parent.count) size.append(1) } - private mutating func setByIndex(index: Int) -> Int { + private mutating func setByIndex(_ index: Int) -> Int { if parent[index] == index { return index } else { @@ -20,7 +20,7 @@ public struct UnionFind { } } - public mutating func setOf(element: T) -> Int? { + public mutating func setOf(_ element: T) -> Int? { if let indexOfElement = index[element] { return setByIndex(indexOfElement) } else { @@ -28,8 +28,8 @@ public struct UnionFind { } } - public mutating func unionSetsContaining(firstElement: T, and secondElement: T) { - if let firstSet = setOf(firstElement), secondSet = setOf(secondElement) { + public mutating func unionSetsContaining(_ firstElement: T, and secondElement: T) { + if let firstSet = setOf(firstElement), let secondSet = setOf(secondElement) { if firstSet != secondSet { if size[firstSet] < size[secondSet] { parent[firstSet] = secondSet @@ -42,8 +42,8 @@ public struct UnionFind { } } - public mutating func inSameSet(firstElement: T, and secondElement: T) -> Bool { - if let firstSet = setOf(firstElement), secondSet = setOf(secondElement) { + public mutating func inSameSet(_ firstElement: T, and secondElement: T) -> Bool { + if let firstSet = setOf(firstElement), let secondSet = setOf(secondElement) { return firstSet == secondSet } else { return false diff --git a/Union-Find/UnionFind.swift b/Union-Find/UnionFind.swift index 4323b80d4..506cdc1fe 100644 --- a/Union-Find/UnionFind.swift +++ b/Union-Find/UnionFind.swift @@ -12,13 +12,13 @@ public struct UnionFind { private var parent = [Int]() private var size = [Int]() - public mutating func addSetWith(element: T) { + public mutating func addSetWith(_ element: T) { index[element] = parent.count parent.append(parent.count) size.append(1) } - private mutating func setByIndex(index: Int) -> Int { + private mutating func setByIndex(_ index: Int) -> Int { if parent[index] == index { return index } else { @@ -27,7 +27,7 @@ public struct UnionFind { } } - public mutating func setOf(element: T) -> Int? { + public mutating func setOf(_ element: T) -> Int? { if let indexOfElement = index[element] { return setByIndex(indexOfElement) } else { @@ -35,8 +35,8 @@ public struct UnionFind { } } - public mutating func unionSetsContaining(firstElement: T, and secondElement: T) { - if let firstSet = setOf(firstElement), secondSet = setOf(secondElement) { + public mutating func unionSetsContaining(_ firstElement: T, and secondElement: T) { + if let firstSet = setOf(firstElement), let secondSet = setOf(secondElement) { if firstSet != secondSet { if size[firstSet] < size[secondSet] { parent[firstSet] = secondSet @@ -49,8 +49,8 @@ public struct UnionFind { } } - public mutating func inSameSet(firstElement: T, and secondElement: T) -> Bool { - if let firstSet = setOf(firstElement), secondSet = setOf(secondElement) { + public mutating func inSameSet(_ firstElement: T, and secondElement: T) -> Bool { + if let firstSet = setOf(firstElement), let secondSet = setOf(secondElement) { return firstSet == secondSet } else { return false From 310f110de8614fc65589158422bc671519a275bb Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Tue, 30 Aug 2016 13:30:51 +1200 Subject: [PATCH 0475/1679] Updating tree to Swift3 --- Tree/README.markdown | 12 ++++++------ Tree/Tree.playground/Contents.swift | 6 +++--- Tree/Tree.swift | 6 +++--- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Tree/README.markdown b/Tree/README.markdown index 52a46c597..5cf3e6beb 100644 --- a/Tree/README.markdown +++ b/Tree/README.markdown @@ -10,7 +10,7 @@ Nodes have links to their children and usually to their parent as well. The chil ![A tree](Images/ParentChildren.png) -A node without a parent is the *root* node. A node without children is a *leaf* node. +A node without a parent is the *root* node. A node without children is a *leaf* node. The pointers in a tree do not form cycles. This is not a tree: @@ -25,15 +25,15 @@ Here's a basic implementation in Swift: ```swift public class TreeNode { public var value: T - + public var parent: TreeNode? public var children = [TreeNode]() public init(value: T) { self.value = value } - - public func addChild(node: TreeNode) { + + public func addChild(_ node: TreeNode) { children.append(node) node.parent = self } @@ -49,7 +49,7 @@ extension TreeNode: CustomStringConvertible { public var description: String { var s = "\(value)" if !children.isEmpty { - s += " {" + children.map { $0.description }.joinWithSeparator(", ") + "}" + s += " {" + children.map { $0.description }.joined(separator: ", ") + "}" } return s } @@ -129,7 +129,7 @@ Here's the code: ```swift extension TreeNode where T: Equatable { - func search(value: T) -> TreeNode? { + func search(_ value: T) -> TreeNode? { if value == self.value { return self } diff --git a/Tree/Tree.playground/Contents.swift b/Tree/Tree.playground/Contents.swift index c8ee8fe71..7b3c97005 100644 --- a/Tree/Tree.playground/Contents.swift +++ b/Tree/Tree.playground/Contents.swift @@ -10,7 +10,7 @@ public class TreeNode { self.value = value } - public func addChild(node: TreeNode) { + public func addChild(_ node: TreeNode) { children.append(node) node.parent = self } @@ -20,7 +20,7 @@ extension TreeNode: CustomStringConvertible { public var description: String { var s = "\(value)" if !children.isEmpty { - s += " {" + children.map { $0.description }.joinWithSeparator(", ") + "}" + s += " {" + children.map { $0.description }.joined(separator: ", ") + "}" } return s } @@ -71,7 +71,7 @@ teaNode.parent teaNode.parent!.parent extension TreeNode where T: Equatable { - func search(value: T) -> TreeNode? { + func search(_ value: T) -> TreeNode? { if value == self.value { return self } diff --git a/Tree/Tree.swift b/Tree/Tree.swift index 39d1f3df5..00119c963 100644 --- a/Tree/Tree.swift +++ b/Tree/Tree.swift @@ -8,7 +8,7 @@ public class TreeNode { self.value = value } - public func addChild(node: TreeNode) { + public func addChild(_ node: TreeNode) { children.append(node) node.parent = self } @@ -18,14 +18,14 @@ extension TreeNode: CustomStringConvertible { public var description: String { var s = "\(value)" if !children.isEmpty { - s += " {" + children.map { $0.description }.joinWithSeparator(", ") + "}" + s += " {" + children.map { $0.description }.joined(separator: ", ") + "}" } return s } } extension TreeNode where T: Equatable { - public func search(value: T) -> TreeNode? { + public func search(_ value: T) -> TreeNode? { if value == self.value { return self } From 8680a97bc576c937d13cb9156c59662e636ce6de Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Tue, 30 Aug 2016 17:59:17 +1200 Subject: [PATCH 0476/1679] Updating to Swift3 --- .../BitSet.playground/Sources/BitSet.swift | 22 +++++----- Bit Set/BitSet.swift | 22 +++++----- Bit Set/README.markdown | 44 +++++++++---------- 3 files changed, 44 insertions(+), 44 deletions(-) diff --git a/Bit Set/BitSet.playground/Sources/BitSet.swift b/Bit Set/BitSet.playground/Sources/BitSet.swift index 46f51dbba..d8985bd13 100644 --- a/Bit Set/BitSet.playground/Sources/BitSet.swift +++ b/Bit Set/BitSet.playground/Sources/BitSet.swift @@ -11,7 +11,7 @@ public struct BitSet { */ private let N = 64 public typealias Word = UInt64 - private(set) public var words: [Word] + fileprivate(set) public var words: [Word] private let allOnes = ~Word() @@ -22,11 +22,11 @@ public struct BitSet { // Round up the count to the next multiple of 64. let n = (size + (N-1)) / N - words = .init(count: n, repeatedValue: 0) + words = [Word](repeating: 0, count: n) } /* Converts a bit index into an array index and a mask inside the word. */ - private func indexOf(i: Int) -> (Int, Word) { + private func indexOf(_ i: Int) -> (Int, Word) { precondition(i >= 0) precondition(i < size) let o = i / N @@ -52,7 +52,7 @@ public struct BitSet { that we're not using, or bitwise operations between two differently sized BitSets will go wrong. */ - private mutating func clearUnusedBits() { + fileprivate mutating func clearUnusedBits() { words[words.count - 1] &= lastWordMask() } @@ -63,7 +63,7 @@ public struct BitSet { } /* Sets the bit at the specified index to 1. */ - public mutating func set(i: Int) { + public mutating func set(_ i: Int) { let (j, m) = indexOf(i) words[j] |= m } @@ -77,7 +77,7 @@ public struct BitSet { } /* Sets the bit at the specified index to 0. */ - public mutating func clear(i: Int) { + public mutating func clear(_ i: Int) { let (j, m) = indexOf(i) words[j] &= ~m } @@ -90,14 +90,14 @@ public struct BitSet { } /* Changes 0 into 1 and 1 into 0. Returns the new value of the bit. */ - public mutating func flip(i: Int) -> Bool { + public mutating func flip(_ i: Int) -> Bool { let (j, m) = indexOf(i) words[j] ^= m return (words[j] & m) != 0 } /* Determines whether the bit at the specific index is 1 (true) or 0 (false). */ - public func isSet(i: Int) -> Bool { + public func isSet(_ i: Int) -> Bool { let (j, m) = indexOf(i) return (words[j] & m) != 0 } @@ -158,7 +158,7 @@ extension BitSet: Hashable { /* Based on the hashing code from Java's BitSet. */ public var hashValue: Int { var h = Word(1234) - for i in words.count.stride(to: 0, by: -1) { + for i in stride(from: words.count, to: 0, by: -1) { h ^= words[i - 1] &* Word(i) } return Int((h >> 32) ^ h) @@ -167,13 +167,13 @@ extension BitSet: Hashable { // MARK: - Bitwise operations -extension BitSet: BitwiseOperationsType { +extension BitSet: BitwiseOperations { public static var allZeros: BitSet { return BitSet(size: 64) } } -private func copyLargest(lhs: BitSet, _ rhs: BitSet) -> BitSet { +private func copyLargest(_ lhs: BitSet, _ rhs: BitSet) -> BitSet { return (lhs.words.count > rhs.words.count) ? lhs : rhs } diff --git a/Bit Set/BitSet.swift b/Bit Set/BitSet.swift index 46f51dbba..d8985bd13 100644 --- a/Bit Set/BitSet.swift +++ b/Bit Set/BitSet.swift @@ -11,7 +11,7 @@ public struct BitSet { */ private let N = 64 public typealias Word = UInt64 - private(set) public var words: [Word] + fileprivate(set) public var words: [Word] private let allOnes = ~Word() @@ -22,11 +22,11 @@ public struct BitSet { // Round up the count to the next multiple of 64. let n = (size + (N-1)) / N - words = .init(count: n, repeatedValue: 0) + words = [Word](repeating: 0, count: n) } /* Converts a bit index into an array index and a mask inside the word. */ - private func indexOf(i: Int) -> (Int, Word) { + private func indexOf(_ i: Int) -> (Int, Word) { precondition(i >= 0) precondition(i < size) let o = i / N @@ -52,7 +52,7 @@ public struct BitSet { that we're not using, or bitwise operations between two differently sized BitSets will go wrong. */ - private mutating func clearUnusedBits() { + fileprivate mutating func clearUnusedBits() { words[words.count - 1] &= lastWordMask() } @@ -63,7 +63,7 @@ public struct BitSet { } /* Sets the bit at the specified index to 1. */ - public mutating func set(i: Int) { + public mutating func set(_ i: Int) { let (j, m) = indexOf(i) words[j] |= m } @@ -77,7 +77,7 @@ public struct BitSet { } /* Sets the bit at the specified index to 0. */ - public mutating func clear(i: Int) { + public mutating func clear(_ i: Int) { let (j, m) = indexOf(i) words[j] &= ~m } @@ -90,14 +90,14 @@ public struct BitSet { } /* Changes 0 into 1 and 1 into 0. Returns the new value of the bit. */ - public mutating func flip(i: Int) -> Bool { + public mutating func flip(_ i: Int) -> Bool { let (j, m) = indexOf(i) words[j] ^= m return (words[j] & m) != 0 } /* Determines whether the bit at the specific index is 1 (true) or 0 (false). */ - public func isSet(i: Int) -> Bool { + public func isSet(_ i: Int) -> Bool { let (j, m) = indexOf(i) return (words[j] & m) != 0 } @@ -158,7 +158,7 @@ extension BitSet: Hashable { /* Based on the hashing code from Java's BitSet. */ public var hashValue: Int { var h = Word(1234) - for i in words.count.stride(to: 0, by: -1) { + for i in stride(from: words.count, to: 0, by: -1) { h ^= words[i - 1] &* Word(i) } return Int((h >> 32) ^ h) @@ -167,13 +167,13 @@ extension BitSet: Hashable { // MARK: - Bitwise operations -extension BitSet: BitwiseOperationsType { +extension BitSet: BitwiseOperations { public static var allZeros: BitSet { return BitSet(size: 64) } } -private func copyLargest(lhs: BitSet, _ rhs: BitSet) -> BitSet { +private func copyLargest(_ lhs: BitSet, _ rhs: BitSet) -> BitSet { return (lhs.words.count > rhs.words.count) ? lhs : rhs } diff --git a/Bit Set/README.markdown b/Bit Set/README.markdown index 85d55e06e..6bb6e7c89 100644 --- a/Bit Set/README.markdown +++ b/Bit Set/README.markdown @@ -18,7 +18,7 @@ public struct BitSet { private let N = 64 public typealias Word = UInt64 - private(set) public var words: [Word] + fileprivate(set) public var words: [Word] public init(size: Int) { precondition(size > 0) @@ -26,7 +26,7 @@ public struct BitSet { // Round up the count to the next multiple of 64. let n = (size + (N-1)) / N - words = .init(count: n, repeatedValue: 0) + words = [Word](repeating: 0, count: n) } ``` @@ -47,7 +47,7 @@ then the `BitSet` allocates an array of three words. Each word has 64 bits and t Most of the operations on `BitSet` take the index of the bit as a parameter, so it's useful to have a way to find which word contains that bit. ```swift - private func indexOf(i: Int) -> (Int, Word) { + private func indexOf(_ i: Int) -> (Int, Word) { precondition(i >= 0) precondition(i < size) let o = i / N @@ -77,7 +77,7 @@ Note that the mask is always 64 bits because we look at the data one word at a t Now that we know where to find a bit, setting it to 1 is easy: ```swift - public mutating func set(i: Int) { + public mutating func set(_ i: Int) { let (j, m) = indexOf(i) words[j] |= m } @@ -88,7 +88,7 @@ This looks up the word index and the mask, then performs a bitwise OR between th Clearing the bit -- i.e. changing it to 0 -- is just as easy: ```swift - public mutating func clear(i: Int) { + public mutating func clear(_ i: Int) { let (j, m) = indexOf(i) words[j] &= ~m } @@ -99,7 +99,7 @@ Instead of a bitwise OR we now do a bitwise AND with the inverse of the mask. So To see if a bit is set we also use the bitwise AND but without inverting: ```swift - public func isSet(i: Int) -> Bool { + public func isSet(_ i: Int) -> Bool { let (j, m) = indexOf(i) return (words[j] & m) != 0 } @@ -127,15 +127,15 @@ print(bits) This will print the three words that the 140-bit `BitSet` uses to store everything: ```swift -0010000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000010000000000000000000000000000 -1000000000000000000000000000000000000000000000000000000000000000 +0010000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000010000000000000000000000000000 +1000000000000000000000000000000000000000000000000000000000000000 ``` Something else that's fun to do with bits is flipping them. This changes 0 into 1 and 1 into 0. Here's `flip()`: ```swift - public mutating func flip(i: Int) -> Bool { + public mutating func flip(_ i: Int) -> Bool { let (j, m) = indexOf(i) words[j] ^= m return (words[j] & m) != 0 @@ -170,17 +170,17 @@ There is also `setAll()` to make all the bits 1. However, this has to deal with First, we copy ones into all the words in our array. The array is now: ```swift -1111111111111111111111111111111111111111111111111111111111111111 -1111111111111111111111111111111111111111111111111111111111111111 -1111111111111111111111111111111111111111111111111111111111111111 +1111111111111111111111111111111111111111111111111111111111111111 +1111111111111111111111111111111111111111111111111111111111111111 +1111111111111111111111111111111111111111111111111111111111111111 ``` But this is incorrect... Since we don't use most of the last word, we should leave those bits at 0: ```swift -1111111111111111111111111111111111111111111111111111111111111111 -1111111111111111111111111111111111111111111111111111111111111111 -1111111111110000000000000000000000000000000000000000000000000000 +1111111111111111111111111111111111111111111111111111111111111111 +1111111111111111111111111111111111111111111111111111111111111111 +1111111111110000000000000000000000000000000000000000000000000000 ``` Instead of 192 one-bits we now have only 140 one-bits. The fact that the last word may not be completely filled up means that we always have to treat this last word specially. @@ -189,7 +189,7 @@ Setting those "leftover" bits to 0 is what the `clearUnusedBits()` helper functi This uses some advanced bit manipulation, so pay close attention: -```swift +```swift private func lastWordMask() -> Word { let diff = words.count*N - size // 1 if diff > 0 { @@ -199,7 +199,7 @@ This uses some advanced bit manipulation, so pay close attention: return ~Word() } } - + private mutating func clearUnusedBits() { words[words.count - 1] &= lastWordMask() // 4 } @@ -211,15 +211,15 @@ Here's what it does, step-by-step: 2) Create a mask that is all 0's, except the highest bit that's still valid is a 1. In our example, that would be: - 0000000000010000000000000000000000000000000000000000000000000000 + 0000000000010000000000000000000000000000000000000000000000000000 3) Subtract 1 to turn it into: - 1111111111100000000000000000000000000000000000000000000000000000 + 1111111111100000000000000000000000000000000000000000000000000000 and add the high bit back in to get: - 1111111111110000000000000000000000000000000000000000000000000000 + 1111111111110000000000000000000000000000000000000000000000000000 There are now 12 one-bits in this word because `140 - 2*64 = 12`. @@ -236,7 +236,7 @@ The first one only uses the first 4 bits; the second one uses 8 bits. The first 00100011 -------- OR 10101111 - + That is wrong since two of those 1-bits aren't supposed to be here. The correct way to do it is: 10000000 unused bits set to 0 first! From e6cfec424571c1c5afed292fb4159b5e8b766df9 Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Tue, 30 Aug 2016 18:27:49 +1200 Subject: [PATCH 0477/1679] Updating to Swift3 --- .travis.yml | 2 +- .../BloomFilter.playground/Contents.swift | 18 ++-- Bloom Filter/BloomFilter.swift | 16 ++-- Bloom Filter/README.markdown | 16 ++-- Bloom Filter/Tests/BloomFilterTests.swift | 88 +++++++++---------- .../Tests/Tests.xcodeproj/project.pbxproj | 10 ++- .../xcshareddata/xcschemes/Tests.xcscheme | 2 +- 7 files changed, 80 insertions(+), 72 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1eba40123..5b31c3085 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,7 +13,7 @@ script: - xcodebuild test -project ./AVL\ Tree/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Binary\ Search/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Binary\ Search\ Tree/Solution\ 1/Tests/Tests.xcodeproj -scheme Tests -# - xcodebuild test -project ./Bloom\ Filter/Tests/Tests.xcodeproj -scheme Tests + - xcodebuild test -project ./Bloom\ Filter/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Bounded\ Priority\ Queue/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Breadth-First\ Search/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Bucket\ Sort/Tests/Tests.xcodeproj -scheme Tests diff --git a/Bloom Filter/BloomFilter.playground/Contents.swift b/Bloom Filter/BloomFilter.playground/Contents.swift index ce59eecaa..d5e7d2dc6 100644 --- a/Bloom Filter/BloomFilter.playground/Contents.swift +++ b/Bloom Filter/BloomFilter.playground/Contents.swift @@ -1,31 +1,31 @@ //: Playground - noun: a place where people can play public class BloomFilter { - private var array: [Bool] - private var hashFunctions: [T -> Int] + fileprivate var array: [Bool] + private var hashFunctions: [(T) -> Int] - public init(size: Int = 1024, hashFunctions: [T -> Int]) { - self.array = .init(count: size, repeatedValue: false) + public init(size: Int = 1024, hashFunctions: [(T) -> Int]) { + self.array = [Bool](repeating: false, count: size) self.hashFunctions = hashFunctions } - private func computeHashes(value: T) -> [Int] { + private func computeHashes(_ value: T) -> [Int] { return hashFunctions.map() { hashFunc in abs(hashFunc(value) % array.count) } } - public func insert(element: T) { + public func insert(_ element: T) { for hashValue in computeHashes(element) { array[hashValue] = true } } - public func insert(values: [T]) { + public func insert(_ values: [T]) { for value in values { insert(value) } } - public func query(value: T) -> Bool { + public func query(_ value: T) -> Bool { let hashValues = computeHashes(value) // Map hashes to indices in the Bloom Filter @@ -37,7 +37,7 @@ public class BloomFilter { // only that it may be. If the query returns false, however, // you can be certain that the value was not added. - let exists = results.reduce(true, combine: { $0 && $1 }) + let exists = results.reduce(true, { $0 && $1 }) return exists } diff --git a/Bloom Filter/BloomFilter.swift b/Bloom Filter/BloomFilter.swift index 97a982f48..03b5333f1 100644 --- a/Bloom Filter/BloomFilter.swift +++ b/Bloom Filter/BloomFilter.swift @@ -1,29 +1,29 @@ public class BloomFilter { private var array: [Bool] - private var hashFunctions: [T -> Int] + private var hashFunctions: [(T) -> Int] - public init(size: Int = 1024, hashFunctions: [T -> Int]) { - self.array = .init(count: size, repeatedValue: false) + public init(size: Int = 1024, hashFunctions: [(T) -> Int]) { + self.array = [Bool](repeating: false, count: size) self.hashFunctions = hashFunctions } - private func computeHashes(value: T) -> [Int] { + private func computeHashes(_ value: T) -> [Int] { return hashFunctions.map() { hashFunc in abs(hashFunc(value) % array.count) } } - public func insert(element: T) { + public func insert(_ element: T) { for hashValue in computeHashes(element) { array[hashValue] = true } } - public func insert(values: [T]) { + public func insert(_ values: [T]) { for value in values { insert(value) } } - public func query(value: T) -> Bool { + public func query(_ value: T) -> Bool { let hashValues = computeHashes(value) // Map hashes to indices in the Bloom Filter @@ -35,7 +35,7 @@ public class BloomFilter { // only that it may be. If the query returns false, however, // you can be certain that the value was not added. - let exists = results.reduce(true, combine: { $0 && $1 }) + let exists = results.reduce(true, { $0 && $1 }) return exists } diff --git a/Bloom Filter/README.markdown b/Bloom Filter/README.markdown index 3e37ee50b..a85d71be4 100644 --- a/Bloom Filter/README.markdown +++ b/Bloom Filter/README.markdown @@ -58,11 +58,11 @@ Performance of a Bloom Filter is **O(k)** where **k** is the number of hashing f ## The code -The code is quite straightforward. The internal bit array is set to a fixed length on initialization, which cannot be mutated once it is initialized. +The code is quite straightforward. The internal bit array is set to a fixed length on initialization, which cannot be mutated once it is initialized. ```swift -public init(size: Int = 1024, hashFunctions: [T -> Int]) { - self.array = .init(count: size, repeatedValue: false) +public init(size: Int = 1024, hashFunctions: [(T) -> Int]) { + self.array = [Bool](repeating: false, count: size) self.hashFunctions = hashFunctions } ``` @@ -72,7 +72,7 @@ Several hash functions should be specified at initialization. Which hash functio Insertion just flips the required bits to `true`: ```swift -public func insert(element: T) { +public func insert(_ element: T) { for hashValue in computeHashes(element) { array[hashValue] = true } @@ -82,7 +82,7 @@ public func insert(element: T) { This uses the `computeHashes()` function, which loops through the specified `hashFunctions` and returns an array of indices: ```swift -private func computeHashes(value: T) -> [Int] { +private func computeHashes(_ value: T) -> [Int] { return hashFunctions.map() { hashFunc in abs(hashFunc(value) % array.count) } } ``` @@ -90,14 +90,14 @@ private func computeHashes(value: T) -> [Int] { And querying checks to make sure the bits at the hashed values are `true`: ```swift -public func query(value: T) -> Bool { +public func query(_ value: T) -> Bool { let hashValues = computeHashes(value) let results = hashValues.map() { hashValue in array[hashValue] } - let exists = results.reduce(true, combine: { $0 && $1 }) + let exists = results.reduce(true, { $0 && $1 }) return exists } ``` -If you're coming from another imperative language, you might notice the unusual syntax in the `exists` assignment. Swift makes use of functional paradigms when it makes code more consise and readable, and in this case `reduce` is a much more consise way to check if all the required bits are `true` than a `for` loop. +If you're coming from another imperative language, you might notice the unusual syntax in the `exists` assignment. Swift makes use of functional paradigms when it makes code more consise and readable, and in this case `reduce` is a much more consise way to check if all the required bits are `true` than a `for` loop. *Written for Swift Algorithm Club by Jamil Dhanani. Edited by Matthijs Hollemans.* diff --git a/Bloom Filter/Tests/BloomFilterTests.swift b/Bloom Filter/Tests/BloomFilterTests.swift index ffac8192d..82bf4fb8f 100644 --- a/Bloom Filter/Tests/BloomFilterTests.swift +++ b/Bloom Filter/Tests/BloomFilterTests.swift @@ -1,76 +1,76 @@ import XCTest /* Two hash functions, adapted from - http://www.cse.yorku.ca/~oz/hash.html */ + http://www.cse.yorku.ca/~oz/hash.html */ -func djb2(x: String) -> Int { - var hash = 5381 +func djb2(_ x: String) -> Int { + var hash = 5381 - for char in x.characters { - hash = ((hash << 5) &+ hash) &+ char.hashValue - } + for char in x.characters { + hash = ((hash << 5) &+ hash) &+ char.hashValue + } - return Int(hash) + return Int(hash) } -func sdbm(x: String) -> Int { - var hash = 0 +func sdbm(_ x: String) -> Int { + var hash = 0 - for char in x.characters { - hash = char.hashValue &+ (hash << 6) &+ (hash << 16) &- hash - } + for char in x.characters { + hash = char.hashValue &+ (hash << 6) &+ (hash << 16) &- hash + } - return Int(hash) + return Int(hash) } class BloomFilterTests: XCTestCase { - func testSingleHashFunction() { - let bloom = BloomFilter(hashFunctions: [djb2]) + func testSingleHashFunction() { + let bloom = BloomFilter(hashFunctions: [djb2]) - bloom.insert("Hello world!") + bloom.insert("Hello world!") - let result_good = bloom.query("Hello world!") - let result_bad = bloom.query("Hello world") + let result_good = bloom.query("Hello world!") + let result_bad = bloom.query("Hello world") - XCTAssertTrue(result_good) - XCTAssertFalse(result_bad) - } + XCTAssertTrue(result_good) + XCTAssertFalse(result_bad) + } - func testEmptyFilter() { - let bloom = BloomFilter(hashFunctions: [djb2]) + func testEmptyFilter() { + let bloom = BloomFilter(hashFunctions: [djb2]) - let empty = bloom.isEmpty() + let empty = bloom.isEmpty() - XCTAssertTrue(empty) - } + XCTAssertTrue(empty) + } - func testMultipleHashFunctions() { - let bloom = BloomFilter(hashFunctions: [djb2, sdbm]) + func testMultipleHashFunctions() { + let bloom = BloomFilter(hashFunctions: [djb2, sdbm]) - bloom.insert("Hello world!") + bloom.insert("Hello world!") - let result_good = bloom.query("Hello world!") - let result_bad = bloom.query("Hello world") + let result_good = bloom.query("Hello world!") + let result_bad = bloom.query("Hello world") - XCTAssertTrue(result_good) - XCTAssertFalse(result_bad) - } + XCTAssertTrue(result_good) + XCTAssertFalse(result_bad) + } - func testFalsePositive() { - let bloom = BloomFilter(size: 5, hashFunctions: [djb2, sdbm]) + func testFalsePositive() { + let bloom = BloomFilter(size: 5, hashFunctions: [djb2, sdbm]) - bloom.insert(["hello", "elloh", "llohe", "lohel", "ohell"]) + bloom.insert(["hello", "elloh", "llohe", "lohel", "ohell"]) - print("Inserted") + print("Inserted") - let query = bloom.query("This wasn't inserted!") + let query = bloom.query("This wasn't inserted!") - // This is true even though we did not insert the value in the Bloom filter; - // the Bloom filter is capable of producing false positives but NOT - // false negatives. + // This is true even though we did not insert the value in the Bloom filter; + // the Bloom filter is capable of producing false positives but NOT + // false negatives. - XCTAssertTrue(query) - } + XCTAssertTrue(query) + } } diff --git a/Bloom Filter/Tests/Tests.xcodeproj/project.pbxproj b/Bloom Filter/Tests/Tests.xcodeproj/project.pbxproj index d413110c9..20998a80e 100644 --- a/Bloom Filter/Tests/Tests.xcodeproj/project.pbxproj +++ b/Bloom Filter/Tests/Tests.xcodeproj/project.pbxproj @@ -83,11 +83,12 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; - LastUpgradeCheck = 0720; + LastUpgradeCheck = 0800; ORGANIZATIONNAME = "Swift Algorithm Club"; TargetAttributes = { 7B2BBC7F1C779D720067B71D = { CreatedOnToolsVersion = 7.2; + LastSwiftMigration = 0800; }; }; }; @@ -145,8 +146,10 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; @@ -189,8 +192,10 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; @@ -209,6 +214,7 @@ MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; }; name = Release; }; @@ -220,6 +226,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -231,6 +238,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Release; }; diff --git a/Bloom Filter/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Bloom Filter/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme index 8ef8d8581..14f27f777 100644 --- a/Bloom Filter/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme +++ b/Bloom Filter/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -1,6 +1,6 @@ Date: Tue, 30 Aug 2016 11:33:34 +0200 Subject: [PATCH 0478/1679] Updating Stack to Swift 3 --- Stack/Stack.playground/Contents.swift | 4 ++-- Stack/Stack.swift | 10 +++++----- Stack/Tests/Tests.xcodeproj/project.pbxproj | 3 +++ 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/Stack/Stack.playground/Contents.swift b/Stack/Stack.playground/Contents.swift index 4f4f826f2..12c29faa0 100644 --- a/Stack/Stack.playground/Contents.swift +++ b/Stack/Stack.playground/Contents.swift @@ -12,7 +12,7 @@ */ public struct Stack { - private var array = [T]() + fileprivate var array = [T]() public var count: Int { return array.count @@ -39,7 +39,7 @@ public struct Stack { var stackOfNames = Stack(array: ["Carl", "Lisa", "Stephanie", "Jeff", "Wade"]) // Add an element to the top of the stack. -stackOfNames.push("Mike") +stackOfNames.push(element: "Mike") // The stack is now ["Carl", "Lisa", "Stephanie", "Jeff", "Wade", "Mike"] print(stackOfNames.array) diff --git a/Stack/Stack.swift b/Stack/Stack.swift index 454b66fa0..49edaf4cb 100644 --- a/Stack/Stack.swift +++ b/Stack/Stack.swift @@ -4,7 +4,7 @@ Push and pop are O(1) operations. */ public struct Stack { - private var array = [T]() + fileprivate var array = [T]() public var isEmpty: Bool { return array.isEmpty @@ -14,7 +14,7 @@ public struct Stack { return array.count } - public mutating func push(element: T) { + public mutating func push(_ element: T) { array.append(element) } @@ -27,10 +27,10 @@ public struct Stack { } } -extension Stack: SequenceType { - public func generate() -> AnyGenerator { +extension Stack: Sequence { + public func makeIterator() -> AnyIterator { var curr = self - return AnyGenerator { + return AnyIterator { _ -> T? in return curr.pop() } diff --git a/Stack/Tests/Tests.xcodeproj/project.pbxproj b/Stack/Tests/Tests.xcodeproj/project.pbxproj index a36d7c51d..5ec8dc987 100644 --- a/Stack/Tests/Tests.xcodeproj/project.pbxproj +++ b/Stack/Tests/Tests.xcodeproj/project.pbxproj @@ -88,6 +88,7 @@ TargetAttributes = { 7B2BBC7F1C779D720067B71D = { CreatedOnToolsVersion = 7.2; + LastSwiftMigration = 0800; }; }; }; @@ -220,6 +221,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -231,6 +233,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Release; }; From 8d4636648f751297d9b99e66f2170c564aed246b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nemanja=20Vlahovic=CC=81?= Date: Tue, 30 Aug 2016 11:38:23 +0200 Subject: [PATCH 0479/1679] Uncomment Stack tests --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1eba40123..f430659e0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,7 +9,7 @@ install: script: # - xcodebuild test -project ./All-Pairs\ Shortest\ Paths/APSP/APSP.xcodeproj -scheme APSPTests - - xcodebuild test -project ./Array2D/Tests/Tests.xcodeproj -scheme Tests +# - xcodebuild test -project ./Array2D/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./AVL\ Tree/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Binary\ Search/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Binary\ Search\ Tree/Solution\ 1/Tests/Tests.xcodeproj -scheme Tests @@ -37,5 +37,5 @@ script: # - xcodebuild test -project ./Shell\ Sort/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Shortest\ Path\ \(Unweighted\)/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Single-Source\ Shortest\ Paths\ \(Weighted\)/SSSP.xcodeproj -scheme SSSPTests -# - xcodebuild test -project ./Stack/Tests/Tests.xcodeproj -scheme Tests + - xcodebuild test -project ./Stack/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Topological\ Sort/Tests/Tests.xcodeproj -scheme Tests From adf2f61a6403d60ac0915bc234e29b6cc6712245 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nemanja=20Vlahovic=CC=81?= Date: Tue, 30 Aug 2016 11:46:19 +0200 Subject: [PATCH 0480/1679] Fix .travis.yml --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index f430659e0..2be5210c4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,8 +10,8 @@ script: # - xcodebuild test -project ./All-Pairs\ Shortest\ Paths/APSP/APSP.xcodeproj -scheme APSPTests # - xcodebuild test -project ./Array2D/Tests/Tests.xcodeproj -scheme Tests - - xcodebuild test -project ./AVL\ Tree/Tests/Tests.xcodeproj -scheme Tests - - xcodebuild test -project ./Binary\ Search/Tests/Tests.xcodeproj -scheme Tests +# - xcodebuild test -project ./AVL\ Tree/Tests/Tests.xcodeproj -scheme Tests +# - xcodebuild test -project ./Binary\ Search/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Binary\ Search\ Tree/Solution\ 1/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Bloom\ Filter/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Bounded\ Priority\ Queue/Tests/Tests.xcodeproj -scheme Tests From 5ad3bb022e98b21b7a3a1d11d6cb32d5b4eff26c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nemanja=20Vlahovic=CC=81?= Date: Tue, 30 Aug 2016 14:04:52 +0200 Subject: [PATCH 0481/1679] Update push method, update to recommended settings --- .travis.yml | 6 +++--- Stack/README.markdown | 4 ++-- Stack/Stack.playground/Contents.swift | 4 ++-- Stack/Tests/Tests.xcodeproj/project.pbxproj | 7 ++++++- .../Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme | 2 +- 5 files changed, 14 insertions(+), 9 deletions(-) diff --git a/.travis.yml b/.travis.yml index 2be5210c4..7ac58cd33 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,9 +9,9 @@ install: script: # - xcodebuild test -project ./All-Pairs\ Shortest\ Paths/APSP/APSP.xcodeproj -scheme APSPTests -# - xcodebuild test -project ./Array2D/Tests/Tests.xcodeproj -scheme Tests -# - xcodebuild test -project ./AVL\ Tree/Tests/Tests.xcodeproj -scheme Tests -# - xcodebuild test -project ./Binary\ Search/Tests/Tests.xcodeproj -scheme Tests + - xcodebuild test -project ./Array2D/Tests/Tests.xcodeproj -scheme Tests + - xcodebuild test -project ./AVL\ Tree/Tests/Tests.xcodeproj -scheme Tests + - xcodebuild test -project ./Binary\ Search/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Binary\ Search\ Tree/Solution\ 1/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Bloom\ Filter/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Bounded\ Priority\ Queue/Tests/Tests.xcodeproj -scheme Tests diff --git a/Stack/README.markdown b/Stack/README.markdown index 17770643b..9d157f290 100644 --- a/Stack/README.markdown +++ b/Stack/README.markdown @@ -42,7 +42,7 @@ A stack is easy to create in Swift. It's just a wrapper around an array that jus ```swift public struct Stack { - private var array = [T]() + fileprivate var array = [T]() public var isEmpty: Bool { return array.isEmpty @@ -52,7 +52,7 @@ public struct Stack { return array.count } - public mutating func push(element: T) { + public mutating func push(_ element: T) { array.append(element) } diff --git a/Stack/Stack.playground/Contents.swift b/Stack/Stack.playground/Contents.swift index 12c29faa0..f086ca817 100644 --- a/Stack/Stack.playground/Contents.swift +++ b/Stack/Stack.playground/Contents.swift @@ -22,7 +22,7 @@ public struct Stack { return array.isEmpty } - public mutating func push(element: T) { + public mutating func push(_ element: T) { array.append(element) } @@ -39,7 +39,7 @@ public struct Stack { var stackOfNames = Stack(array: ["Carl", "Lisa", "Stephanie", "Jeff", "Wade"]) // Add an element to the top of the stack. -stackOfNames.push(element: "Mike") +stackOfNames.push("Mike") // The stack is now ["Carl", "Lisa", "Stephanie", "Jeff", "Wade", "Mike"] print(stackOfNames.array) diff --git a/Stack/Tests/Tests.xcodeproj/project.pbxproj b/Stack/Tests/Tests.xcodeproj/project.pbxproj index 5ec8dc987..8924fc935 100644 --- a/Stack/Tests/Tests.xcodeproj/project.pbxproj +++ b/Stack/Tests/Tests.xcodeproj/project.pbxproj @@ -83,7 +83,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; - LastUpgradeCheck = 0720; + LastUpgradeCheck = 0800; ORGANIZATIONNAME = "Swift Algorithm Club"; TargetAttributes = { 7B2BBC7F1C779D720067B71D = { @@ -146,8 +146,10 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; @@ -190,8 +192,10 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; @@ -210,6 +214,7 @@ MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; }; name = Release; }; diff --git a/Stack/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Stack/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme index 8ef8d8581..14f27f777 100644 --- a/Stack/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme +++ b/Stack/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -1,6 +1,6 @@ Date: Tue, 30 Aug 2016 15:15:28 +0200 Subject: [PATCH 0482/1679] Update Queue to Swift 3 --- .travis.yml | 2 +- Queue/Queue-Optimized.swift | 6 +++--- Queue/Queue-Simple.swift | 4 ++-- Queue/Queue.playground/Contents.swift | 4 ++-- Queue/README.markdown | 10 +++++----- Queue/Tests/Tests.xcodeproj/project.pbxproj | 10 +++++++++- .../xcshareddata/xcschemes/Tests.xcscheme | 2 +- 7 files changed, 23 insertions(+), 15 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1eba40123..ff451b26e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -29,7 +29,7 @@ script: # - xcodebuild test -project ./Longest\ Common\ Subsequence/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Minimum\ Spanning\ Tree\ \(Unweighted\)/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Priority\ Queue/Tests/Tests.xcodeproj -scheme Tests -# - xcodebuild test -project ./Queue/Tests/Tests.xcodeproj -scheme Tests + - xcodebuild test -project ./Queue/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Quicksort/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Run-Length\ Encoding/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Select\ Minimum\ Maximum/Tests/Tests.xcodeproj -scheme Tests diff --git a/Queue/Queue-Optimized.swift b/Queue/Queue-Optimized.swift index 5a9d04394..ad6999295 100644 --- a/Queue/Queue-Optimized.swift +++ b/Queue/Queue-Optimized.swift @@ -7,8 +7,8 @@ Enqueuing and dequeuing are O(1) operations. */ public struct Queue { - private var array = [T?]() - private var head = 0 + fileprivate var array = [T?]() + fileprivate var head = 0 public var isEmpty: Bool { return count == 0 @@ -18,7 +18,7 @@ public struct Queue { return array.count - head } - public mutating func enqueue(element: T) { + public mutating func enqueue(_ element: T) { array.append(element) } diff --git a/Queue/Queue-Simple.swift b/Queue/Queue-Simple.swift index 6d3c197ee..27fbdee4d 100644 --- a/Queue/Queue-Simple.swift +++ b/Queue/Queue-Simple.swift @@ -8,7 +8,7 @@ implemented with a linked list, then both would be O(1). */ public struct Queue { - private var array = [T]() + fileprivate var array = [T]() public var count: Int { return array.count @@ -18,7 +18,7 @@ public struct Queue { return array.isEmpty } - public mutating func enqueue(element: T) { + public mutating func enqueue(_ element: T) { array.append(element) } diff --git a/Queue/Queue.playground/Contents.swift b/Queue/Queue.playground/Contents.swift index 0c48afd5b..6b771ccd1 100644 --- a/Queue/Queue.playground/Contents.swift +++ b/Queue/Queue.playground/Contents.swift @@ -12,7 +12,7 @@ */ public struct Queue { - private var array = [T]() + fileprivate var array = [T]() public var isEmpty: Bool { return array.isEmpty @@ -22,7 +22,7 @@ public struct Queue { return array.count } - public mutating func enqueue(element: T) { + public mutating func enqueue(_ element: T) { array.append(element) } diff --git a/Queue/README.markdown b/Queue/README.markdown index 92118d37b..f7779aa69 100644 --- a/Queue/README.markdown +++ b/Queue/README.markdown @@ -46,7 +46,7 @@ Here is a very simplistic implementation of a queue in Swift. It's just a wrappe ```swift public struct Queue { - private var array = [T]() + fileprivate var array = [T]() public var isEmpty: Bool { return array.isEmpty @@ -56,7 +56,7 @@ public struct Queue { return array.count } - public mutating func enqueue(element: T) { + public mutating func enqueue(_ element: T) { array.append(element) } @@ -136,8 +136,8 @@ Here is how you could implement this version of `Queue`: ```swift public struct Queue { - private var array = [T?]() - private var head = 0 + fileprivate var array = [T?]() + fileprivate var head = 0 public var isEmpty: Bool { return count == 0 @@ -147,7 +147,7 @@ public struct Queue { return array.count - head } - public mutating func enqueue(element: T) { + public mutating func enqueue(_ element: T) { array.append(element) } diff --git a/Queue/Tests/Tests.xcodeproj/project.pbxproj b/Queue/Tests/Tests.xcodeproj/project.pbxproj index ac23063a5..a554fd16e 100644 --- a/Queue/Tests/Tests.xcodeproj/project.pbxproj +++ b/Queue/Tests/Tests.xcodeproj/project.pbxproj @@ -83,11 +83,12 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; - LastUpgradeCheck = 0720; + LastUpgradeCheck = 0800; ORGANIZATIONNAME = "Swift Algorithm Club"; TargetAttributes = { 7B2BBC7F1C779D720067B71D = { CreatedOnToolsVersion = 7.2; + LastSwiftMigration = 0800; }; }; }; @@ -145,8 +146,10 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; @@ -189,8 +192,10 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; @@ -209,6 +214,7 @@ MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; }; name = Release; }; @@ -220,6 +226,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -231,6 +238,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Release; }; diff --git a/Queue/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Queue/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme index 8ef8d8581..14f27f777 100644 --- a/Queue/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme +++ b/Queue/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -1,6 +1,6 @@ Date: Tue, 30 Aug 2016 15:18:15 +0200 Subject: [PATCH 0483/1679] Fix .travis.yml --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index ff451b26e..278aba883 100644 --- a/.travis.yml +++ b/.travis.yml @@ -37,5 +37,5 @@ script: # - xcodebuild test -project ./Shell\ Sort/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Shortest\ Path\ \(Unweighted\)/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Single-Source\ Shortest\ Paths\ \(Weighted\)/SSSP.xcodeproj -scheme SSSPTests -# - xcodebuild test -project ./Stack/Tests/Tests.xcodeproj -scheme Tests + - xcodebuild test -project ./Stack/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Topological\ Sort/Tests/Tests.xcodeproj -scheme Tests From 8527a528c451b04d6e9c8a2ed4f54c77dfa9b831 Mon Sep 17 00:00:00 2001 From: Nemanja Vlahovic Date: Tue, 30 Aug 2016 22:21:21 +0200 Subject: [PATCH 0484/1679] Fix spaces in .travis.yml --- .travis.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 278aba883..c2ac363d1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,9 +9,9 @@ install: script: # - xcodebuild test -project ./All-Pairs\ Shortest\ Paths/APSP/APSP.xcodeproj -scheme APSPTests - - xcodebuild test -project ./Array2D/Tests/Tests.xcodeproj -scheme Tests - - xcodebuild test -project ./AVL\ Tree/Tests/Tests.xcodeproj -scheme Tests - - xcodebuild test -project ./Binary\ Search/Tests/Tests.xcodeproj -scheme Tests +- xcodebuild test -project ./Array2D/Tests/Tests.xcodeproj -scheme Tests +- xcodebuild test -project ./AVL\ Tree/Tests/Tests.xcodeproj -scheme Tests +- xcodebuild test -project ./Binary\ Search/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Binary\ Search\ Tree/Solution\ 1/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Bloom\ Filter/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Bounded\ Priority\ Queue/Tests/Tests.xcodeproj -scheme Tests @@ -29,7 +29,7 @@ script: # - xcodebuild test -project ./Longest\ Common\ Subsequence/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Minimum\ Spanning\ Tree\ \(Unweighted\)/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Priority\ Queue/Tests/Tests.xcodeproj -scheme Tests - - xcodebuild test -project ./Queue/Tests/Tests.xcodeproj -scheme Tests + - xcodebuild test -project ./Queue/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Quicksort/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Run-Length\ Encoding/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Select\ Minimum\ Maximum/Tests/Tests.xcodeproj -scheme Tests @@ -37,5 +37,5 @@ script: # - xcodebuild test -project ./Shell\ Sort/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Shortest\ Path\ \(Unweighted\)/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Single-Source\ Shortest\ Paths\ \(Weighted\)/SSSP.xcodeproj -scheme SSSPTests - - xcodebuild test -project ./Stack/Tests/Tests.xcodeproj -scheme Tests + - xcodebuild test -project ./Stack/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Topological\ Sort/Tests/Tests.xcodeproj -scheme Tests From 7d1c4a3a3b11ba5583df7d14bcc1e43ba48fdfc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nemanja=20Vlahovic=CC=81?= Date: Wed, 31 Aug 2016 09:56:45 +0200 Subject: [PATCH 0485/1679] Update Insertion Sort to Swift 3 --- .../InsertionSort.playground/Contents.swift | 4 +-- Insertion Sort/InsertionSort.swift | 2 +- Insertion Sort/README.markdown | 6 ++-- .../Tests/Tests.xcodeproj/project.pbxproj | 10 +++++- .../xcshareddata/xcschemes/Tests.xcscheme | 2 +- Quicksort/Tests/SortingTestHelpers.swift | 34 +++++++++---------- 6 files changed, 33 insertions(+), 25 deletions(-) diff --git a/Insertion Sort/InsertionSort.playground/Contents.swift b/Insertion Sort/InsertionSort.playground/Contents.swift index 867feb190..b25916b23 100644 --- a/Insertion Sort/InsertionSort.playground/Contents.swift +++ b/Insertion Sort/InsertionSort.playground/Contents.swift @@ -1,6 +1,6 @@ //: Playground - noun: a place where people can play -func insertionSort(array: [T], _ isOrderedBefore: (T, T) -> Bool) -> [T] { +func insertionSort(_ array: [T], _ isOrderedBefore: (T, T) -> Bool) -> [T] { var a = array for x in 1..(array: [T], _ isOrderedBefore: (T, T) -> Bool) -> [T] { let list = [ 10, -1, 3, 9, 2, 27, 8, 5, 1, 3, 0, 26 ] insertionSort(list, <) -insertionSort(list, >) +insertionSort(list, >) \ No newline at end of file diff --git a/Insertion Sort/InsertionSort.swift b/Insertion Sort/InsertionSort.swift index 886054e53..5d8a9565b 100644 --- a/Insertion Sort/InsertionSort.swift +++ b/Insertion Sort/InsertionSort.swift @@ -1,4 +1,4 @@ -func insertionSort(array: [T], _ isOrderedBefore: (T, T) -> Bool) -> [T] { +func insertionSort(_ array: [T], _ isOrderedBefore: (T, T) -> Bool) -> [T] { guard array.count > 1 else { return array } var a = array diff --git a/Insertion Sort/README.markdown b/Insertion Sort/README.markdown index b67541669..286d92ed1 100644 --- a/Insertion Sort/README.markdown +++ b/Insertion Sort/README.markdown @@ -90,7 +90,7 @@ This was a description of the inner loop of the insertion sort algorithm, which Here is an implementation of insertion sort in Swift: ```swift -func insertionSort(array: [Int]) -> [Int] { +func insertionSort(_ array: [Int]) -> [Int] { var a = array // 1 for x in 1.. [Int] { +func insertionSort(_ array: [Int]) -> [Int] { var a = array for x in 1..(array: [T], _ isOrderedBefore: (T, T) -> Bool) -> [T] { +func insertionSort(_ array: [T], _ isOrderedBefore: (T, T) -> Bool) -> [T] { ``` The array has type `[T]` where `T` is the placeholder type for the generics. Now `insertionSort()` will accept any kind of array, whether it contains numbers, strings, or something else. diff --git a/Insertion Sort/Tests/Tests.xcodeproj/project.pbxproj b/Insertion Sort/Tests/Tests.xcodeproj/project.pbxproj index f8c23899c..ee3ca1cae 100644 --- a/Insertion Sort/Tests/Tests.xcodeproj/project.pbxproj +++ b/Insertion Sort/Tests/Tests.xcodeproj/project.pbxproj @@ -86,11 +86,12 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; - LastUpgradeCheck = 0720; + LastUpgradeCheck = 0800; ORGANIZATIONNAME = "Swift Algorithm Club"; TargetAttributes = { 7B2BBC7F1C779D720067B71D = { CreatedOnToolsVersion = 7.2; + LastSwiftMigration = 0800; }; }; }; @@ -149,8 +150,10 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; @@ -193,8 +196,10 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; @@ -213,6 +218,7 @@ MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; }; name = Release; }; @@ -224,6 +230,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -235,6 +242,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Release; }; diff --git a/Insertion Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Insertion Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme index 8ef8d8581..14f27f777 100644 --- a/Insertion Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme +++ b/Insertion Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -1,6 +1,6 @@ [Int] { +func randomArray(_ size: Int) -> [Int] { var a = [Int]() for _ in 1...size { a.append(Int(arc4random_uniform(1000))) @@ -9,16 +9,16 @@ func randomArray(size: Int) -> [Int] { return a } -func arrayIsSortedLowToHigh(a: [Int]) -> Bool { +func arrayIsSortedLowToHigh(_ a: [Int]) -> Bool { for x in 1.. a[x] { return false } } return true } -typealias SortFunction = [Int] -> [Int] +typealias SortFunction = ([Int]) -> [Int] -func checkSortingRandomArray(sortFunction: SortFunction) { +func checkSortingRandomArray(_ sortFunction: SortFunction) { let numberOfIterations = 100 for _ in 1...numberOfIterations { let a = randomArray(Int(arc4random_uniform(100)) + 1) @@ -28,73 +28,73 @@ func checkSortingRandomArray(sortFunction: SortFunction) { } } -func checkSortingEmptyArray(sortFunction: SortFunction) { +func checkSortingEmptyArray(_ sortFunction: SortFunction) { let a = [Int]() let s = sortFunction(a) XCTAssertEqual(s.count, 0) } -func checkSortingArrayOneElement(sortFunction: SortFunction) { +func checkSortingArrayOneElement(_ sortFunction: SortFunction) { let a = [123] let s = sortFunction(a) XCTAssertEqual(s, [123]) } -func checkSortingArrayTwoElementsInOrder(sortFunction: SortFunction) { +func checkSortingArrayTwoElementsInOrder(_ sortFunction: SortFunction) { let a = [123, 456] let s = sortFunction(a) XCTAssertEqual(s, [123, 456]) } -func checkSortingArrayTwoElementsOutOfOrder(sortFunction: SortFunction) { +func checkSortingArrayTwoElementsOutOfOrder(_ sortFunction: SortFunction) { let a = [456, 123] let s = sortFunction(a) XCTAssertEqual(s, [123, 456]) } -func checkSortingArrayTwoEqualElements(sortFunction: SortFunction) { +func checkSortingArrayTwoEqualElements(_ sortFunction: SortFunction) { let a = [123, 123] let s = sortFunction(a) XCTAssertEqual(s, [123, 123]) } -func checkSortingArrayThreeElementsABC(sortFunction: SortFunction) { +func checkSortingArrayThreeElementsABC(_ sortFunction: SortFunction) { let a = [2, 4, 6] let s = sortFunction(a) XCTAssertEqual(s, [2, 4, 6]) } -func checkSortingArrayThreeElementsACB(sortFunction: SortFunction) { +func checkSortingArrayThreeElementsACB(_ sortFunction: SortFunction) { let a = [2, 6, 4] let s = sortFunction(a) XCTAssertEqual(s, [2, 4, 6]) } -func checkSortingArrayThreeElementsBAC(sortFunction: SortFunction) { +func checkSortingArrayThreeElementsBAC(_ sortFunction: SortFunction) { let a = [4, 2, 6] let s = sortFunction(a) XCTAssertEqual(s, [2, 4, 6]) } -func checkSortingArrayThreeElementsBCA(sortFunction: SortFunction) { +func checkSortingArrayThreeElementsBCA(_ sortFunction: SortFunction) { let a = [4, 6, 2] let s = sortFunction(a) XCTAssertEqual(s, [2, 4, 6]) } -func checkSortingArrayThreeElementsCAB(sortFunction: SortFunction) { +func checkSortingArrayThreeElementsCAB(_ sortFunction: SortFunction) { let a = [6, 2, 4] let s = sortFunction(a) XCTAssertEqual(s, [2, 4, 6]) } -func checkSortingArrayThreeElementsCBA(sortFunction: SortFunction) { +func checkSortingArrayThreeElementsCBA(_ sortFunction: SortFunction) { let a = [6, 4, 2] let s = sortFunction(a) XCTAssertEqual(s, [2, 4, 6]) } -func checkSortAlgorithm(sortFunction: SortFunction) { +func checkSortAlgorithm(_ sortFunction: SortFunction) { checkSortingEmptyArray(sortFunction) checkSortingArrayOneElement(sortFunction) checkSortingArrayTwoElementsInOrder(sortFunction) @@ -109,6 +109,6 @@ func checkSortAlgorithm(sortFunction: SortFunction) { checkSortingRandomArray(sortFunction) } -func checkSortAlgorithm(sortFunction: ([Int], (Int, Int) -> Bool) -> [Int]) { +func checkSortAlgorithm(_ sortFunction: @escaping ([Int], (Int, Int) -> Bool) -> [Int]) { checkSortAlgorithm { a in sortFunction(a, <) } } From a50e2879edd581fcc3c8b8388dde19dc4877e114 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nemanja=20Vlahovic=CC=81?= Date: Wed, 31 Aug 2016 10:01:20 +0200 Subject: [PATCH 0486/1679] Update travis.yml --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1eba40123..6b1fe2dff 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,7 +23,7 @@ script: # - xcodebuild test -project ./Graph/Graph.xcodeproj -scheme GraphTests # - xcodebuild test -project ./Heap/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Heap\ Sort/Tests/Tests.xcodeproj -scheme Tests -# - xcodebuild test -project ./Insertion\ Sort/Tests/Tests.xcodeproj -scheme Tests + - xcodebuild test -project ./Insertion\ Sort/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./K-Means/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Linked\ List/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Longest\ Common\ Subsequence/Tests/Tests.xcodeproj -scheme Tests @@ -37,5 +37,5 @@ script: # - xcodebuild test -project ./Shell\ Sort/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Shortest\ Path\ \(Unweighted\)/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Single-Source\ Shortest\ Paths\ \(Weighted\)/SSSP.xcodeproj -scheme SSSPTests -# - xcodebuild test -project ./Stack/Tests/Tests.xcodeproj -scheme Tests + - xcodebuild test -project ./Stack/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Topological\ Sort/Tests/Tests.xcodeproj -scheme Tests From 8f0447566427f089789a29e01dbdc60e97bf2d01 Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Wed, 31 Aug 2016 21:18:13 +1200 Subject: [PATCH 0487/1679] Update .travis.yml Removed space before insertion sort tests. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 32f43c129..8cf0b486b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,7 +23,7 @@ script: # - xcodebuild test -project ./Graph/Graph.xcodeproj -scheme GraphTests # - xcodebuild test -project ./Heap/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Heap\ Sort/Tests/Tests.xcodeproj -scheme Tests - - xcodebuild test -project ./Insertion\ Sort/Tests/Tests.xcodeproj -scheme Tests +- xcodebuild test -project ./Insertion\ Sort/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./K-Means/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Linked\ List/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Longest\ Common\ Subsequence/Tests/Tests.xcodeproj -scheme Tests From 283ba84440385e36965943aa0581e6b81d917d13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nemanja=20Vlahovic=CC=81?= Date: Wed, 31 Aug 2016 13:27:13 +0200 Subject: [PATCH 0488/1679] Update Merge Sort to Swift 3 --- Merge Sort/MergeSort.playground/Contents.swift | 6 +++--- Merge Sort/MergeSort.swift | 6 +++--- Merge Sort/README.markdown | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Merge Sort/MergeSort.playground/Contents.swift b/Merge Sort/MergeSort.playground/Contents.swift index a71a90136..ac166131e 100644 --- a/Merge Sort/MergeSort.playground/Contents.swift +++ b/Merge Sort/MergeSort.playground/Contents.swift @@ -1,6 +1,6 @@ /* Top-down recursive version */ -func mergeSort(array: [Int]) -> [Int] { +func mergeSort(_ array: [Int]) -> [Int] { guard array.count > 1 else { return array } let middleIndex = array.count / 2 let leftArray = mergeSort(Array(array[0.. [Int] { return merge(leftPile: leftArray, rightPile: rightArray) } -func merge(leftPile leftPile: [Int], rightPile: [Int]) -> [Int] { +func merge(leftPile: [Int], rightPile: [Int]) -> [Int] { var leftIndex = 0 var rightIndex = 0 var orderedPile = [Int]() @@ -48,7 +48,7 @@ let sortedArray = mergeSort(array) /* Bottom-up iterative version */ -func mergeSortBottomUp(a: [T], _ isOrderedBefore: (T, T) -> Bool) -> [T] { +func mergeSortBottomUp(_ a: [T], _ isOrderedBefore: (T, T) -> Bool) -> [T] { let n = a.count var z = [a, a] // the two working arrays var d = 0 // z[d] is used for reading, z[1 - d] for writing diff --git a/Merge Sort/MergeSort.swift b/Merge Sort/MergeSort.swift index 968484dd1..20316663f 100644 --- a/Merge Sort/MergeSort.swift +++ b/Merge Sort/MergeSort.swift @@ -6,7 +6,7 @@ // // -func mergeSort(array: [Int]) -> [Int] { +func mergeSort(_ array: [Int]) -> [Int] { guard array.count > 1 else { return array } let middleIndex = array.count / 2 let leftArray = mergeSort(Array(array[0.. [Int] { return merge(leftPile: leftArray, rightPile: rightArray) } -func merge(leftPile leftPile: [Int], rightPile: [Int]) -> [Int] { +func merge(leftPile: [Int], rightPile: [Int]) -> [Int] { var leftIndex = 0 var rightIndex = 0 var orderedPile = [Int]() @@ -59,7 +59,7 @@ func merge(leftPile leftPile: [Int], rightPile: [Int]) -> [Int] { To avoid allocating many temporary array objects, it uses double-buffering with just two arrays. */ -func mergeSortBottomUp(a: [T], _ isOrderedBefore: (T, T) -> Bool) -> [T] { +func mergeSortBottomUp(_ a: [T], _ isOrderedBefore: (T, T) -> Bool) -> [T] { let n = a.count var z = [a, a] // the two working arrays var d = 0 // z[d] is used for reading, z[1 - d] for writing diff --git a/Merge Sort/README.markdown b/Merge Sort/README.markdown index a24c71f2f..3ff69fdd5 100644 --- a/Merge Sort/README.markdown +++ b/Merge Sort/README.markdown @@ -42,7 +42,7 @@ You're left with only two piles and `[9]` finally gets its chance to merge, resu Here's what merge sort may look like in Swift: ```swift -func mergeSort(array: [Int]) -> [Int] { +func mergeSort(_ array: [Int]) -> [Int] { guard array.count > 1 else { return array } // 1 let middleIndex = array.count / 2 // 2 @@ -70,7 +70,7 @@ A step-by-step explanation of how the code works: Here's the merging algorithm: ```swift -func merge(leftPile leftPile: [Int], rightPile: [Int]) -> [Int] { +func merge(leftPile: [Int], rightPile: [Int]) -> [Int] { // 1 var leftIndex = 0 var rightIndex = 0 @@ -162,7 +162,7 @@ The implementation of merge sort you've seen so far is called "top-down" because Time to step up the game a little. :-) Here is a complete bottom-up implementation in Swift: ```swift -func mergeSortBottomUp(a: [T], _ isOrderedBefore: (T, T) -> Bool) -> [T] { +func mergeSortBottomUp(_ a: [T], _ isOrderedBefore: (T, T) -> Bool) -> [T] { let n = a.count var z = [a, a] // 1 From 33b6e653c03765fbaad06423bd2122de4199686e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nemanja=20Vlahovic=CC=81?= Date: Wed, 31 Aug 2016 13:46:09 +0200 Subject: [PATCH 0489/1679] Update Linear Search to Swift 3 --- Linear Search/LinearSearch.playground/Contents.swift | 4 ++-- Linear Search/LinearSearch.swift | 4 ++-- Linear Search/README.markdown | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Linear Search/LinearSearch.playground/Contents.swift b/Linear Search/LinearSearch.playground/Contents.swift index 02fb6e940..34e859fa3 100644 --- a/Linear Search/LinearSearch.playground/Contents.swift +++ b/Linear Search/LinearSearch.playground/Contents.swift @@ -1,7 +1,7 @@ //: Playground - noun: a place where people can play -func linearSearch(array: [T], _ object: T) -> Int? { - for (index, obj) in array.enumerate() where obj == object { +func linearSearch(_ array: [T], _ object: T) -> Int? { + for (index, obj) in array.enumerated() where obj == object { return index } return nil diff --git a/Linear Search/LinearSearch.swift b/Linear Search/LinearSearch.swift index fe64ef24e..882795180 100644 --- a/Linear Search/LinearSearch.swift +++ b/Linear Search/LinearSearch.swift @@ -1,5 +1,5 @@ -func linearSearch(array: [T], _ object: T) -> Int? { - for (index, obj) in array.enumerate() where obj == object { +func linearSearch(_ array: [T], _ object: T) -> Int? { + for (index, obj) in array.enumerated() where obj == object { return index } return nil diff --git a/Linear Search/README.markdown b/Linear Search/README.markdown index 115dd7ee2..4649f4fc4 100644 --- a/Linear Search/README.markdown +++ b/Linear Search/README.markdown @@ -17,8 +17,8 @@ We compare the number `2` from the array to our number `2` and notice they are e Here is a simple implementation of linear search in Swift: ```swift -func linearSearch(array: [T], _ object: T) -> Int? { - for (index, obj) in array.enumerate() where obj == object { +func linearSearch(_ array: [T], _ object: T) -> Int? { + for (index, obj) in array.enumerated() where obj == object { return index } return nil From 7f627a21b2beb5cf9f72c77eccb151ef66231d25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nemanja=20Vlahovic=CC=81?= Date: Wed, 31 Aug 2016 14:02:17 +0200 Subject: [PATCH 0490/1679] Update Count Occurrences to Swift 3 --- Count Occurrences/CountOccurrences.playground/Contents.swift | 4 ++-- Count Occurrences/CountOccurrences.swift | 2 +- Count Occurrences/README.markdown | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Count Occurrences/CountOccurrences.playground/Contents.swift b/Count Occurrences/CountOccurrences.playground/Contents.swift index b90ba12ce..cbb43c868 100644 --- a/Count Occurrences/CountOccurrences.playground/Contents.swift +++ b/Count Occurrences/CountOccurrences.playground/Contents.swift @@ -1,6 +1,6 @@ //: Playground - noun: a place where people can play -func countOccurrencesOfKey(key: Int, inArray a: [Int]) -> Int { +func countOccurrencesOfKey(_ key: Int, inArray a: [Int]) -> Int { func leftBoundary() -> Int { var low = 0 var high = a.count @@ -53,7 +53,7 @@ func createArray() -> [Int] { } } } - return a.sort(<) + return a.sorted() } for _ in 0..<10 { diff --git a/Count Occurrences/CountOccurrences.swift b/Count Occurrences/CountOccurrences.swift index 57c75c735..10dd12c4f 100644 --- a/Count Occurrences/CountOccurrences.swift +++ b/Count Occurrences/CountOccurrences.swift @@ -2,7 +2,7 @@ Counts the number of times a value appears in an array in O(lg n) time. The array must be sorted from low to high. */ -func countOccurrencesOfKey(key: Int, inArray a: [Int]) -> Int { +func countOccurrencesOfKey(_ key: Int, inArray a: [Int]) -> Int { func leftBoundary() -> Int { var low = 0 var high = a.count diff --git a/Count Occurrences/README.markdown b/Count Occurrences/README.markdown index be8c2061e..90a9ec2f3 100644 --- a/Count Occurrences/README.markdown +++ b/Count Occurrences/README.markdown @@ -22,7 +22,7 @@ The trick is to use two binary searches, one to find where the `3`s start (the l In code this looks as follows: ```swift -func countOccurrencesOfKey(key: Int, inArray a: [Int]) -> Int { +func countOccurrencesOfKey(_ key: Int, inArray a: [Int]) -> Int { func leftBoundary() -> Int { var low = 0 var high = a.count From ecae2cc08805bc2be1a22d4482a9d97e86d1776a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viktor=20Simk=C3=B3?= Date: Thu, 1 Sep 2016 10:53:51 +0200 Subject: [PATCH 0491/1679] migrated to Swift 3 --- B-Tree/BTree.swift | 419 +++++++++++------- B-Tree/Tests/Tests.xcodeproj/project.pbxproj | 10 +- .../xcshareddata/xcschemes/Tests.xcscheme | 2 +- B-Tree/Tests/Tests/BTreeNodeTests.swift | 16 +- B-Tree/Tests/Tests/BTreeTests.swift | 36 +- 5 files changed, 303 insertions(+), 180 deletions(-) diff --git a/B-Tree/BTree.swift b/B-Tree/BTree.swift index 16c4eabe4..f5638ea4e 100644 --- a/B-Tree/BTree.swift +++ b/B-Tree/BTree.swift @@ -21,17 +21,17 @@ // SOFTWARE. /* - B-Tree - - A B-Tree is a self-balancing search tree, in which nodes can have more than two children. + * B-Tree + * + * A B-Tree is a self-balancing search tree, in which nodes can have more than two children. */ // MARK: - BTreeNode class class BTreeNode { - unowned var ownerTree: BTree + unowned var owner: BTree - private var keys = [Key]() + fileprivate var keys = [Key]() var values = [Value]() var children: [BTreeNode]? @@ -43,13 +43,13 @@ class BTreeNode { return keys.count } - init(ownerTree: BTree) { - self.ownerTree = ownerTree + init(owner: BTree) { + self.owner = owner } - convenience init(ownerTree: BTree, keys: [Key], + convenience init(owner: BTree, keys: [Key], values: [Value], children: [BTreeNode]? = nil) { - self.init(ownerTree: ownerTree) + self.init(owner: owner) self.keys += keys self.values += values self.children = children @@ -59,19 +59,26 @@ class BTreeNode { // MARK: BTreeNode extesnion: Searching extension BTreeNode { - func valueForKey(key: Key) -> Value? { + + /** + * Returns the value for a given `key`, returns nil if the `key` is not found. + * + * - Parameters: + * - key: the key of the value to be returned + */ + func value(for key: Key) -> Value? { var index = keys.startIndex - while index.successor() < keys.endIndex && keys[index] < key { - index = index.successor() + while (index + 1) < keys.endIndex && keys[index] < key { + index = (index + 1) } if key == keys[index] { return values[index] } else if key < keys[index] { - return children?[index].valueForKey(key) + return children?[index].value(for: key) } else { - return children?[index.successor()].valueForKey(key) + return children?[(index + 1)].value(for: key) } } } @@ -79,7 +86,14 @@ extension BTreeNode { // MARK: BTreeNode extension: Travelsals extension BTreeNode { - func traverseKeysInOrder(@noescape process: Key -> Void) { + + /** + * Traverses the keys in order, executes `process` for every key. + * + * - Parameters: + * - process: the closure to be executed for every key + */ + func traverseKeysInOrder(_ process: (Key) -> Void) { for i in 0.. ownerTree.order * 2 { - splitChild(children![index], atIndex: index) + children![index].insert(value, for: key) + if children![index].numberOfKeys > owner.order * 2 { + split(children![index], at: index) } } } - private func splitChild(child: BTreeNode, atIndex index: Int) { + /** + * Splits `child` at `index`. + * The key-value pair at `index` gets moved up to the parent node, + * or if there is not an parent node, then a new parent node is created. + * + * - Parameters: + * - child: the child to be split + * - index: the index of the key, which will be moved up to the parent + */ + fileprivate func split(_ child: BTreeNode, at index: Int) { let middleIndex = child.numberOfKeys / 2 - keys.insert(child.keys[middleIndex], atIndex: index) - values.insert(child.values[middleIndex], atIndex: index) - child.keys.removeAtIndex(middleIndex) - child.values.removeAtIndex(middleIndex) + keys.insert(child.keys[middleIndex], at: index) + values.insert(child.values[middleIndex], at: index) + child.keys.remove(at: middleIndex) + child.values.remove(at: middleIndex) let rightSibling = BTreeNode( - ownerTree: ownerTree, - keys: Array(child.keys[middleIndex..= 0 && - children![index.predecessor()].numberOfKeys > ownerTree.order { - - moveKeyAtIndex(index.predecessor(), toNode: child, - fromNode: children![index.predecessor()], atPosition: .Left) - - } else if index.successor() < children!.count && - children![index.successor()].numberOfKeys > ownerTree.order { - - moveKeyAtIndex(index, toNode: child, - fromNode: children![index.successor()], atPosition: .Right) - - } else if index.predecessor() >= 0 { - mergeChild(child, withIndex: index, toNodeAtPosition: .Left) + if (index - 1) >= 0 && children![(index - 1)].numberOfKeys > owner.order { + move(keyAt: (index - 1), to: child, from: children![(index - 1)], at: .left) + } else if (index + 1) < children!.count && children![(index + 1)].numberOfKeys > owner.order { + move(keyAt: index, to: child, from: children![(index + 1)], at: .right) + } else if (index - 1) >= 0 { + merge(child, at: index, to: .left) } else { - mergeChild(child, withIndex: index, toNodeAtPosition: .Right) + merge(child, at: index, to: .right) } } - private func moveKeyAtIndex(keyIndex: Int, toNode targetNode: BTreeNode, - fromNode: BTreeNode, atPosition position: BTreeNodePosition) { + /** + * Moves the key at the specified `index` from `node` to + * the `targetNode` at `position` + * + * - Parameters: + * - index: the index of the key to be moved in `node` + * - targetNode: the node to move the key into + * - node: the node to move the key from + * - position: the position of the from node relative to the targetNode + */ + fileprivate func move(keyAt index: Int, to targetNode: BTreeNode, + from node: BTreeNode, at position: BTreeNodePosition) { switch position { - case .Left: - targetNode.keys.insert(keys[keyIndex], atIndex: targetNode.keys.startIndex) - targetNode.values.insert(values[keyIndex], atIndex: targetNode.values.startIndex) - keys[keyIndex] = fromNode.keys.last! - values[keyIndex] = fromNode.values.last! - fromNode.keys.removeLast() - fromNode.values.removeLast() + case .left: + targetNode.keys.insert(keys[index], at: targetNode.keys.startIndex) + targetNode.values.insert(values[index], at: targetNode.values.startIndex) + keys[index] = node.keys.last! + values[index] = node.values.last! + node.keys.removeLast() + node.values.removeLast() if !targetNode.isLeaf { - targetNode.children!.insert(fromNode.children!.last!, - atIndex: targetNode.children!.startIndex) - fromNode.children!.removeLast() + targetNode.children!.insert(node.children!.last!, + at: targetNode.children!.startIndex) + node.children!.removeLast() } - case .Right: - targetNode.keys.insert(keys[keyIndex], atIndex: targetNode.keys.endIndex) - targetNode.values.insert(values[keyIndex], atIndex: targetNode.values.endIndex) - keys[keyIndex] = fromNode.keys.first! - values[keyIndex] = fromNode.values.first! - fromNode.keys.removeFirst() - fromNode.values.removeFirst() + case .right: + targetNode.keys.insert(keys[index], at: targetNode.keys.endIndex) + targetNode.values.insert(values[index], at: targetNode.values.endIndex) + keys[index] = node.keys.first! + values[index] = node.values.first! + node.keys.removeFirst() + node.values.removeFirst() if !targetNode.isLeaf { - targetNode.children!.insert(fromNode.children!.first!, - atIndex: targetNode.children!.endIndex) - fromNode.children!.removeFirst() + targetNode.children!.insert(node.children!.first!, + at: targetNode.children!.endIndex) + node.children!.removeFirst() } } } - private func mergeChild(child: BTreeNode, withIndex index: Int, toNodeAtPosition position: BTreeNodePosition) { + /** + * Merges `child` at `position` to the node at the `position`. + * + * - Parameters: + * - child: the child to be merged + * - index: the index of the child in the current node + * - position: the position of the node to merge into + */ + fileprivate func merge(_ child: BTreeNode, at index: Int, to position: BTreeNodePosition) { switch position { - case .Left: + case .left: // We can merge to the left sibling - children![index.predecessor()].keys = children![index.predecessor()].keys + - [keys[index.predecessor()]] + child.keys + children![(index - 1)].keys = children![(index - 1)].keys + + [keys[(index - 1)]] + child.keys - children![index.predecessor()].values = children![index.predecessor()].values + - [values[index.predecessor()]] + child.values + children![(index - 1)].values = children![(index - 1)].values + + [values[(index - 1)]] + child.values - keys.removeAtIndex(index.predecessor()) - values.removeAtIndex(index.predecessor()) + keys.remove(at: (index - 1)) + values.remove(at: (index - 1)) if !child.isLeaf { - children![index.predecessor()].children = - children![index.predecessor()].children! + child.children! + children![(index - 1)].children = + children![(index - 1)].children! + child.children! } - case .Right: + case .right: // We should merge to the right sibling - children![index.successor()].keys = child.keys + [keys[index]] + - children![index.successor()].keys + children![(index + 1)].keys = child.keys + [keys[index]] + + children![(index + 1)].keys - children![index.successor()].values = child.values + [values[index]] + - children![index.successor()].values + children![(index + 1)].values = child.values + [values[index]] + + children![(index + 1)].values - keys.removeAtIndex(index) - values.removeAtIndex(index) + keys.remove(at: index) + values.remove(at: index) if !child.isLeaf { - children![index.successor()].children = - child.children! + children![index.successor()].children! + children![(index + 1)].children = + child.children! + children![(index + 1)].children! } } - children!.removeAtIndex(index) + children!.remove(at: index) } } // MARK: BTreeNode extension: Conversion extension BTreeNode { - func inorderArrayFromKeys() -> [Key] { + /** + * Returns an array which contains the keys from the current node + * and its descendants in order. + */ + var inorderArrayFromKeys: [Key] { var array = [Key] () for i in 0.. { - +open class BTree { /** - The order of the B-Tree - - The number of keys in every node should be in the [order, 2*order] range, - except the root node which is allowed to contain less keys than the value of order. + * The order of the B-Tree + * + * The number of keys in every node should be in the [order, 2*order] range, + * except the root node which is allowed to contain less keys than the value of order. */ - public let order: Int + open let order: Int - /// The root node of the tree + /** + * The root node of the tree + */ var rootNode: BTreeNode! - private(set) public var numberOfKeys = 0 + fileprivate(set) open var numberOfKeys = 0 /** - Designated initializer for the tree - - - parameters: - - order: The order of the tree. + * Designated initializer for the tree + * + * - Parameters: + * - order: The order of the tree. */ public init?(order: Int) { guard order > 0 else { @@ -362,14 +435,20 @@ public class BTree { return nil } self.order = order - rootNode = BTreeNode(ownerTree: self) + rootNode = BTreeNode(owner: self) } } // MARK: BTree extension: Travelsals extension BTree { - public func traverseKeysInOrder(@noescape process: Key -> Void) { + /** + * Traverses the keys in order, executes `process` for every key. + * + * - Parameters: + * - process: the closure to be executed for every key + */ + public func traverseKeysInOrder(_ process: (Key) -> Void) { rootNode.traverseKeysInOrder(process) } } @@ -377,6 +456,12 @@ extension BTree { // MARK: BTree extension: Subscript extension BTree { + /** + * Returns the value for a given `key`, returns nil if the `key` is not found. + * + * - Parameters: + * - key: the key of the value to be returned + */ public subscript (key: Key) -> Value? { return valueForKey(key) } @@ -385,52 +470,71 @@ extension BTree { // MARK: BTree extension: Value for Key extension BTree { - public func valueForKey(key: Key) -> Value? { + /** + * Returns the value for a given `key`, returns nil if the `key` is not found. + * + * - Parameters: + * - key: the key of the value to be returned + */ + public func valueForKey(_ key: Key) -> Value? { guard rootNode.numberOfKeys > 0 else { return nil } - return rootNode.valueForKey(key) + return rootNode.value(for: key) } } // MARK: BTree extension: Insertion extension BTree { - public func insertValue(value: Value, forKey key: Key) { - rootNode.insertValue(value, forKey: key) + /** + * Inserts the `value` for the `key` into the tree. + * + * - Parameters: + * - value: the value to be inserted for `key` + * - key: the key for the `value` + */ + public func insert(_ value: Value, for key: Key) { + rootNode.insert(value, for: key) if rootNode.numberOfKeys > order * 2 { splitRoot() } } - private func splitRoot() { + /** + * Splits the root node of the tree. + * + * - Precondition: + * The root node of the tree contains `order` * 2 keys. + */ + fileprivate func splitRoot() { let middleIndexOfOldRoot = rootNode.numberOfKeys / 2 let newRoot = BTreeNode( - ownerTree: self, + owner: self, keys: [rootNode.keys[middleIndexOfOldRoot]], values: [rootNode.values[middleIndexOfOldRoot]], children: [rootNode] ) - rootNode.keys.removeAtIndex(middleIndexOfOldRoot) - rootNode.values.removeAtIndex(middleIndexOfOldRoot) + rootNode.keys.remove(at: middleIndexOfOldRoot) + rootNode.values.remove(at: middleIndexOfOldRoot) let newRightChild = BTreeNode( - ownerTree: self, - keys: Array(rootNode.keys[middleIndexOfOldRoot.. 0 else { return } - rootNode.removeKey(key) + rootNode.remove(key) if rootNode.numberOfKeys == 0 && !rootNode.isLeaf { rootNode = rootNode.children!.first! @@ -458,15 +568,20 @@ extension BTree { // MARK: BTree extension: Conversion extension BTree { - public func inorderArrayFromKeys() -> [Key] { - return rootNode.inorderArrayFromKeys() + /** + * The keys of the tree in order. + */ + public var inorderArrayFromKeys: [Key] { + return rootNode.inorderArrayFromKeys } } // MARK: BTree extension: Decription extension BTree: CustomStringConvertible { - // Returns a String containing the preorder representation of the nodes + /** + * Returns a String containing the preorder representation of the nodes. + */ public var description: String { return rootNode.description } diff --git a/B-Tree/Tests/Tests.xcodeproj/project.pbxproj b/B-Tree/Tests/Tests.xcodeproj/project.pbxproj index 0780f04c8..79552bbe5 100644 --- a/B-Tree/Tests/Tests.xcodeproj/project.pbxproj +++ b/B-Tree/Tests/Tests.xcodeproj/project.pbxproj @@ -85,11 +85,12 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0730; - LastUpgradeCheck = 0730; + LastUpgradeCheck = 0800; ORGANIZATIONNAME = "Viktor Szilárd Simkó"; TargetAttributes = { C66702771D0EEE25008CD769 = { CreatedOnToolsVersion = 7.3.1; + LastSwiftMigration = 0800; }; }; }; @@ -148,8 +149,10 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; @@ -193,8 +196,10 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; @@ -213,6 +218,7 @@ MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; }; name = Release; }; @@ -226,6 +232,7 @@ PRODUCT_BUNDLE_IDENTIFIER = viktorsimko.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -238,6 +245,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = viktorsimko.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Release; }; diff --git a/B-Tree/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/B-Tree/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme index d9200547d..9d6c542ae 100644 --- a/B-Tree/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme +++ b/B-Tree/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -1,6 +1,6 @@ (order: 2)! + let owner = BTree(order: 2)! var root: BTreeNode! var leftChild: BTreeNode! var rightChild: BTreeNode! @@ -18,11 +18,11 @@ class BTreeNodeTests: XCTestCase { override func setUp() { super.setUp() - root = BTreeNode(ownerTree: ownerTree) - leftChild = BTreeNode(ownerTree: ownerTree) - rightChild = BTreeNode(ownerTree: ownerTree) + root = BTreeNode(owner: owner) + leftChild = BTreeNode(owner: owner) + rightChild = BTreeNode(owner: owner) - root.insertValue(1, forKey: 1) + root.insert(1, for: 1) root.children = [leftChild, rightChild] } @@ -36,9 +36,9 @@ class BTreeNodeTests: XCTestCase { } func testOwner() { - XCTAssert(root.ownerTree === ownerTree) - XCTAssert(leftChild.ownerTree === ownerTree) - XCTAssert(rightChild.ownerTree === ownerTree) + XCTAssert(root.owner === owner) + XCTAssert(leftChild.owner === owner) + XCTAssert(rightChild.owner === owner) } func testNumberOfKeys() { diff --git a/B-Tree/Tests/Tests/BTreeTests.swift b/B-Tree/Tests/Tests/BTreeTests.swift index 947781478..231a423e2 100644 --- a/B-Tree/Tests/Tests/BTreeTests.swift +++ b/B-Tree/Tests/Tests/BTreeTests.swift @@ -45,7 +45,7 @@ class BTreeTests: XCTestCase { } func testInsertToEmptyTree() { - bTree.insertValue(1, forKey: 1) + bTree.insert(1, for: 1) XCTAssertEqual(bTree[1]!, 1) } @@ -56,7 +56,7 @@ class BTreeTests: XCTestCase { } func testInorderArrayFromEmptyTree() { - XCTAssertEqual(bTree.inorderArrayFromKeys(), [Int]()) + XCTAssertEqual(bTree.inorderArrayFromKeys, [Int]()) } func testDescriptionOfEmptyTree() { @@ -67,7 +67,7 @@ class BTreeTests: XCTestCase { func testInorderTravelsal() { for i in 1...20 { - bTree.insertValue(i, forKey: i) + bTree.insert(i, for: i) } var j = 1 @@ -82,7 +82,7 @@ class BTreeTests: XCTestCase { func testSearchForMaximum() { for i in 1...20 { - bTree.insertValue(i, forKey: i) + bTree.insert(i, for: i) } XCTAssertEqual(bTree.valueForKey(20)!, 20) @@ -90,7 +90,7 @@ class BTreeTests: XCTestCase { func testSearchForMinimum() { for i in 1...20 { - bTree.insertValue(i, forKey: i) + bTree.insert(i, for: i) } XCTAssertEqual(bTree.valueForKey(1)!, 1) @@ -118,7 +118,7 @@ class BTreeTests: XCTestCase { func testRemoveMaximum() { for i in 1...20 { - bTree.insertValue(i, forKey: i) + bTree.insert(i, for: i) } bTree.removeKey(20) @@ -184,7 +184,7 @@ class BTreeTests: XCTestCase { XCTAssertEqual(bTree.numberOfKeys, 20) - for i in (1...20).reverse() { + for i in (1...20).reversed() { bTree.removeKey(i) } @@ -202,24 +202,24 @@ class BTreeTests: XCTestCase { func testInorderArray() { bTree.insertKeysUpTo(20) - let returnedArray = bTree.inorderArrayFromKeys() + let returnedArray = bTree.inorderArrayFromKeys let targetArray = Array(1...20) XCTAssertEqual(returnedArray, targetArray) } } -enum BTreeError: ErrorType { - case TooManyNodes - case TooFewNodes +enum BTreeError: Error { + case tooManyNodes + case tooFewNodes } extension BTreeNode { func checkBalanced(isRoot root: Bool) throws { - if numberOfKeys > ownerTree.order * 2 { - throw BTreeError.TooManyNodes - } else if !root && numberOfKeys < ownerTree.order { - throw BTreeError.TooFewNodes + if numberOfKeys > owner.order * 2 { + throw BTreeError.tooManyNodes + } else if !root && numberOfKeys < owner.order { + throw BTreeError.tooFewNodes } if !isLeaf { @@ -230,13 +230,13 @@ extension BTreeNode { } } -extension BTree where Key: SignedIntegerType, Value: SignedIntegerType { - func insertKeysUpTo(to: Int) { +extension BTree where Key: SignedInteger, Value: SignedInteger { + func insertKeysUpTo(_ to: Int) { var k: Key = 1 var v: Value = 1 for _ in 1...to { - insertValue(v, forKey: k) + insert(v, for: k) k = k + 1 v = v + 1 } From 9b3458e6fb974d2e1c02a4df6790a54e7c435975 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viktor=20Simk=C3=B3?= Date: Thu, 1 Sep 2016 10:56:05 +0200 Subject: [PATCH 0492/1679] updated .travis.yml --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 8cf0b486b..edfe5e624 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,7 +17,7 @@ script: # - xcodebuild test -project ./Bounded\ Priority\ Queue/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Breadth-First\ Search/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Bucket\ Sort/Tests/Tests.xcodeproj -scheme Tests -# - xcodebuild test -project ./B-Tree/Tests/Tests.xcodeproj -scheme Tests +- xcodebuild test -project ./B-Tree/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Counting\ Sort/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Depth-First\ Search/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Graph/Graph.xcodeproj -scheme GraphTests From 7f71ac77f17565f94444843d0c854c345aaa5298 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viktor=20Simk=C3=B3?= Date: Thu, 1 Sep 2016 12:16:42 +0200 Subject: [PATCH 0493/1679] corrected method naming --- B-Tree/BTree.swift | 45 +++++++++++++++-------------- B-Tree/Tests/Tests/BTreeTests.swift | 22 +++++++------- 2 files changed, 35 insertions(+), 32 deletions(-) diff --git a/B-Tree/BTree.swift b/B-Tree/BTree.swift index f5638ea4e..e6494af0a 100644 --- a/B-Tree/BTree.swift +++ b/B-Tree/BTree.swift @@ -29,10 +29,13 @@ // MARK: - BTreeNode class class BTreeNode { + /** + * The tree that owns the node. + */ unowned var owner: BTree fileprivate var keys = [Key]() - var values = [Value]() + fileprivate var values = [Value]() var children: [BTreeNode]? var isLeaf: Bool { @@ -147,7 +150,7 @@ extension BTreeNode { * - child: the child to be split * - index: the index of the key, which will be moved up to the parent */ - fileprivate func split(_ child: BTreeNode, at index: Int) { + private func split(_ child: BTreeNode, at index: Int) { let middleIndex = child.numberOfKeys / 2 keys.insert(child.keys[middleIndex], at: index) values.insert(child.values[middleIndex], at: index) @@ -188,7 +191,7 @@ private enum BTreeNodePosition { } extension BTreeNode { - fileprivate var inorderPredecessor: BTreeNode { + private var inorderPredecessor: BTreeNode { if isLeaf { return self } else { @@ -221,7 +224,7 @@ extension BTreeNode { values[index] = predecessor.values.last! children![index].remove(keys[index]) if children![index].numberOfKeys < owner.order { - fix(children![index], at: index) + fix(child: children![index], at: index) } } } else if key < keys[index] { @@ -230,7 +233,7 @@ extension BTreeNode { if let leftChild = children?[index] { leftChild.remove(key) if leftChild.numberOfKeys < owner.order { - fix(leftChild, at: index) + fix(child: leftChild, at: index) } } else { print("The key:\(key) is not in the tree.") @@ -241,7 +244,7 @@ extension BTreeNode { if let rightChild = children?[(index + 1)] { rightChild.remove(key) if rightChild.numberOfKeys < owner.order { - fix(rightChild, at: (index + 1)) + fix(child: rightChild, at: (index + 1)) } } else { print("The key:\(key) is not in the tree") @@ -259,16 +262,16 @@ extension BTreeNode { * - child: the child to be fixed * - index: the index of the child to be fixed in the current node */ - fileprivate func fix(_ child: BTreeNode, at index: Int) { + private func fix(child: BTreeNode, at index: Int) { if (index - 1) >= 0 && children![(index - 1)].numberOfKeys > owner.order { - move(keyAt: (index - 1), to: child, from: children![(index - 1)], at: .left) + move(keyAtIndex: (index - 1), to: child, from: children![(index - 1)], at: .left) } else if (index + 1) < children!.count && children![(index + 1)].numberOfKeys > owner.order { - move(keyAt: index, to: child, from: children![(index + 1)], at: .right) + move(keyAtIndex: index, to: child, from: children![(index + 1)], at: .right) } else if (index - 1) >= 0 { - merge(child, at: index, to: .left) + merge(child: child, atIndex: index, to: .left) } else { - merge(child, at: index, to: .right) + merge(child: child, atIndex: index, to: .right) } } @@ -282,7 +285,7 @@ extension BTreeNode { * - node: the node to move the key from * - position: the position of the from node relative to the targetNode */ - fileprivate func move(keyAt index: Int, to targetNode: BTreeNode, + private func move(keyAtIndex index: Int, to targetNode: BTreeNode, from node: BTreeNode, at position: BTreeNodePosition) { switch position { case .left: @@ -321,7 +324,7 @@ extension BTreeNode { * - index: the index of the child in the current node * - position: the position of the node to merge into */ - fileprivate func merge(_ child: BTreeNode, at index: Int, to position: BTreeNodePosition) { + private func merge(child: BTreeNode, atIndex index: Int, to position: BTreeNodePosition) { switch position { case .left: // We can merge to the left sibling @@ -407,21 +410,21 @@ extension BTreeNode: CustomStringConvertible { // MARK: - BTree class -open class BTree { +public class BTree { /** * The order of the B-Tree * * The number of keys in every node should be in the [order, 2*order] range, * except the root node which is allowed to contain less keys than the value of order. */ - open let order: Int + public let order: Int - /** + /** * The root node of the tree */ var rootNode: BTreeNode! - fileprivate(set) open var numberOfKeys = 0 + fileprivate(set) public var numberOfKeys = 0 /** * Designated initializer for the tree @@ -463,7 +466,7 @@ extension BTree { * - key: the key of the value to be returned */ public subscript (key: Key) -> Value? { - return valueForKey(key) + return value(for: key) } } @@ -476,7 +479,7 @@ extension BTree { * - Parameters: * - key: the key of the value to be returned */ - public func valueForKey(_ key: Key) -> Value? { + public func value(for key: Key) -> Value? { guard rootNode.numberOfKeys > 0 else { return nil } @@ -509,7 +512,7 @@ extension BTree { * - Precondition: * The root node of the tree contains `order` * 2 keys. */ - fileprivate func splitRoot() { + private func splitRoot() { let middleIndexOfOldRoot = rootNode.numberOfKeys / 2 let newRoot = BTreeNode( @@ -552,7 +555,7 @@ extension BTree { * - Parameters: * - key: the key to remove */ - public func removeKey(_ key: Key) { + public func remove(_ key: Key) { guard rootNode.numberOfKeys > 0 else { return } diff --git a/B-Tree/Tests/Tests/BTreeTests.swift b/B-Tree/Tests/Tests/BTreeTests.swift index 231a423e2..f81016ae7 100644 --- a/B-Tree/Tests/Tests/BTreeTests.swift +++ b/B-Tree/Tests/Tests/BTreeTests.swift @@ -41,7 +41,7 @@ class BTreeTests: XCTestCase { } func testSearchEmptyTree() { - XCTAssertEqual(bTree.valueForKey(1), nil) + XCTAssertEqual(bTree.value(for: 1), nil) } func testInsertToEmptyTree() { @@ -51,7 +51,7 @@ class BTreeTests: XCTestCase { } func testRemoveFromEmptyTree() { - bTree.removeKey(1) + bTree.remove(1) XCTAssertEqual(bTree.description, "[]") } @@ -85,7 +85,7 @@ class BTreeTests: XCTestCase { bTree.insert(i, for: i) } - XCTAssertEqual(bTree.valueForKey(20)!, 20) + XCTAssertEqual(bTree.value(for: 20)!, 20) } func testSearchForMinimum() { @@ -93,7 +93,7 @@ class BTreeTests: XCTestCase { bTree.insert(i, for: i) } - XCTAssertEqual(bTree.valueForKey(1)!, 1) + XCTAssertEqual(bTree.value(for: 1)!, 1) } // MARK: - Insertion @@ -121,7 +121,7 @@ class BTreeTests: XCTestCase { bTree.insert(i, for: i) } - bTree.removeKey(20) + bTree.remove(20) XCTAssertNil(bTree[20]) @@ -135,7 +135,7 @@ class BTreeTests: XCTestCase { func testRemoveMinimum() { bTree.insertKeysUpTo(20) - bTree.removeKey(1) + bTree.remove(1) XCTAssertNil(bTree[1]) @@ -149,8 +149,8 @@ class BTreeTests: XCTestCase { func testRemoveSome() { bTree.insertKeysUpTo(20) - bTree.removeKey(6) - bTree.removeKey(9) + bTree.remove(6) + bTree.remove(9) XCTAssertNil(bTree[6]) XCTAssertNil(bTree[9]) @@ -166,8 +166,8 @@ class BTreeTests: XCTestCase { bTree = BTree(order: 2)! bTree.insertKeysUpTo(20) - bTree.removeKey(6) - bTree.removeKey(9) + bTree.remove(6) + bTree.remove(9) XCTAssertNil(bTree[6]) XCTAssertNil(bTree[9]) @@ -185,7 +185,7 @@ class BTreeTests: XCTestCase { XCTAssertEqual(bTree.numberOfKeys, 20) for i in (1...20).reversed() { - bTree.removeKey(i) + bTree.remove(i) } do { From 26b9b64d66b693ee83346c470aefc9f68ae94bb6 Mon Sep 17 00:00:00 2001 From: Mike Date: Thu, 1 Sep 2016 17:05:20 +0200 Subject: [PATCH 0494/1679] Update README.md --- Skip-List/README.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Skip-List/README.md b/Skip-List/README.md index ca1dce7ae..1722e1fe6 100644 --- a/Skip-List/README.md +++ b/Skip-List/README.md @@ -1,3 +1,8 @@ # Skip List -> Skip lists are a probabilistic data structure that seem likely to supplant balanced trees as the implementation method of choice for many applications. Skip list algorithms have the same asymptotic expected time bounds as balanced trees and are simpler, faster and use less space. -**[William Pugh](https://en.wikipedia.org/wiki/William_Pugh)** +Skip List is a probablistic data-structure with same efficiency as AVL tree or Red-Black tree. Fast searching is possible by building a hierarchy of sorted linked-lists acting as an express lane to the layer underneath. Layers are created on top of the base layer ( regular sorted linked-list ) probablisticly by coin-flipping. + +A layer consists of a Head node, holding reference to the next and the node below. Each node has also same references similar to the Head node. + +#TODO + - finish readme From 568ae3cded5c0530d50926136f916ec6b499c4ce Mon Sep 17 00:00:00 2001 From: Mike Date: Thu, 1 Sep 2016 17:05:56 +0200 Subject: [PATCH 0495/1679] Images folder --- Skip-List/Images/base | 1 + 1 file changed, 1 insertion(+) create mode 100644 Skip-List/Images/base diff --git a/Skip-List/Images/base b/Skip-List/Images/base new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/Skip-List/Images/base @@ -0,0 +1 @@ + From afec24cba04b3d084f463c3f5185c7b4af5fee6a Mon Sep 17 00:00:00 2001 From: Mike Date: Thu, 1 Sep 2016 17:06:06 +0200 Subject: [PATCH 0496/1679] Delete base --- Skip-List/Images/base | 1 - 1 file changed, 1 deletion(-) delete mode 100644 Skip-List/Images/base diff --git a/Skip-List/Images/base b/Skip-List/Images/base deleted file mode 100644 index 8b1378917..000000000 --- a/Skip-List/Images/base +++ /dev/null @@ -1 +0,0 @@ - From 6db2dd7758a6f0bcadab6be316489887a7814b79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viktor=20Szil=C3=A1rd=20Simk=C3=B3?= Date: Thu, 1 Sep 2016 19:28:19 +0200 Subject: [PATCH 0497/1679] updated README.md --- B-Tree/README.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/B-Tree/README.md b/B-Tree/README.md index 28b617ca1..493fdedfb 100644 --- a/B-Tree/README.md +++ b/B-Tree/README.md @@ -20,9 +20,9 @@ A second order B-Tree with keys from 1 to 20 looks like this: ```swift class BTreeNode { - unowned var ownerTree: BTree + unowned var owner: BTree - private var keys = [Key]() + fileprivate var keys = [Key]() var children: [BTreeNode]? ... @@ -55,7 +55,7 @@ This is necessary because nodes have to know the order of the tree. ### The code -`valueForKey(_:)` method searches for the given key and if it's in the tree, +`value(for:)` method searches for the given key and if it's in the tree, it returns the value associated with it, else it returns `nil`. ## Insertion @@ -72,7 +72,7 @@ Keys can only be inserted to leaf nodes. After insertion we should check if the number of keys in the node is in the correct range. If there are more keys in the node than `order*2`, we need to split the node. -####Splitting a node +#### Splitting a node 1. Move up the middle key of the node we want to split, to its parent (if it has one). 2. If it hasn't got a parent(it is the root), then create a new root and insert to it. @@ -90,9 +90,9 @@ An insertion to a first order tree looks like this: ### The code -The method `insertValue(_:forKey:)` does the insertion. +The method `insert(_:for:)` does the insertion. After it has inserted a key, as the recursion goes up every node checks the number of keys in its child. -if a node has too many keys, its parent calls the `splitChild(_:atIndex:)` method on it. +if a node has too many keys, its parent calls the `split(child:atIndex:)` method on it. The root node is checked by the tree itself. If the root has too many nodes after the insertion the tree calls the `splitRoot()` method. @@ -112,7 +112,7 @@ After a key have been removed from a node we should check that the node has enou If a node has fewer keys than the order of the tree, then we should move a key to it, or merge it with one of its siblings. -####Moving a key to the child +#### Moving a key to the child If the problematic node has a nearest sibling that has more keys than the order of the tree, we should perform this operation on the tree, else we should merge the node with one of its siblings. @@ -156,13 +156,13 @@ so in the worst case merging also can go up to the root, in which case the heigh ### The code -- `removeKey(_:)` method removes the given key from the tree. After a key has been deleted, +- `remove(_:)` method removes the given key from the tree. After a key has been deleted, every node checks the number of keys in its child. If a child has less nodes than the order of the tree, - it calls the `fixChildWithLessNodesThanOrder(_:atIndex:)` method. + it calls the `fix(childWithTooFewKeys:atIndex:)` method. -- `fixChildWithLessNodesThanOrder(_:atIndex:)` method decides which way to fix the child (by moving a key to it, - or by merging it), then calls `moveKeyAtIndex(keyIndex:toNode:fromNode:atPosition:)` or - `mergeChild(_:withIndex:toNodeAtPosition:)` method according to its choice. +- `fix(childWithTooFewKeys:atIndex:)` method decides which way to fix the child (by moving a key to it, + or by merging it), then calls `move(keyAtIndex:to:from:at:)` or + `merge(child:atIndex:to:)` method according to its choice. ## See also From 3bc80955f527274fc3ab4a9f4dedf71198b77e54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viktor=20Simk=C3=B3?= Date: Thu, 1 Sep 2016 19:31:15 +0200 Subject: [PATCH 0498/1679] corrected comments, tweaked method naming --- B-Tree/BTree.swift | 21 +++++++++++---------- B-Tree/Tests/Tests/BTreeTests.swift | 20 ++++++++++---------- 2 files changed, 21 insertions(+), 20 deletions(-) diff --git a/B-Tree/BTree.swift b/B-Tree/BTree.swift index e6494af0a..52cda4e43 100644 --- a/B-Tree/BTree.swift +++ b/B-Tree/BTree.swift @@ -136,7 +136,7 @@ extension BTreeNode { } else { children![index].insert(value, for: key) if children![index].numberOfKeys > owner.order * 2 { - split(children![index], at: index) + split(child: children![index], atIndex: index) } } } @@ -150,7 +150,7 @@ extension BTreeNode { * - child: the child to be split * - index: the index of the key, which will be moved up to the parent */ - private func split(_ child: BTreeNode, at index: Int) { + private func split(child: BTreeNode, atIndex index: Int) { let middleIndex = child.numberOfKeys / 2 keys.insert(child.keys[middleIndex], at: index) values.insert(child.values[middleIndex], at: index) @@ -224,7 +224,7 @@ extension BTreeNode { values[index] = predecessor.values.last! children![index].remove(keys[index]) if children![index].numberOfKeys < owner.order { - fix(child: children![index], at: index) + fix(childWithTooFewKeys: children![index], atIndex: index) } } } else if key < keys[index] { @@ -233,7 +233,7 @@ extension BTreeNode { if let leftChild = children?[index] { leftChild.remove(key) if leftChild.numberOfKeys < owner.order { - fix(child: leftChild, at: index) + fix(childWithTooFewKeys: leftChild, atIndex: index) } } else { print("The key:\(key) is not in the tree.") @@ -244,7 +244,7 @@ extension BTreeNode { if let rightChild = children?[(index + 1)] { rightChild.remove(key) if rightChild.numberOfKeys < owner.order { - fix(child: rightChild, at: (index + 1)) + fix(childWithTooFewKeys: rightChild, atIndex: (index + 1)) } } else { print("The key:\(key) is not in the tree") @@ -253,16 +253,17 @@ extension BTreeNode { } /** - * Fixes the `child` at `index`. - * If `child` contains too many children then it moves a child to one of - * `child`'s neighbouring nodes. - * If `child` contains too few children then it merges it with one of its neighbours. + * Fixes `childWithTooFewKeys` by either moving a key to it from + * one of its neighbouring nodes, or by merging. + * + * - Precondition: + * `childWithTooFewKeys` must have less keys than the order of the tree. * * - Parameters: * - child: the child to be fixed * - index: the index of the child to be fixed in the current node */ - private func fix(child: BTreeNode, at index: Int) { + private func fix(childWithTooFewKeys child: BTreeNode, atIndex index: Int) { if (index - 1) >= 0 && children![(index - 1)].numberOfKeys > owner.order { move(keyAtIndex: (index - 1), to: child, from: children![(index - 1)], at: .left) diff --git a/B-Tree/Tests/Tests/BTreeTests.swift b/B-Tree/Tests/Tests/BTreeTests.swift index f81016ae7..c8db17fa3 100644 --- a/B-Tree/Tests/Tests/BTreeTests.swift +++ b/B-Tree/Tests/Tests/BTreeTests.swift @@ -108,7 +108,7 @@ class BTreeTests: XCTestCase { } do { - try bTree.checkBalanced() + try bTree.checkBalance() } catch { XCTFail("BTree is not balanced") } @@ -126,7 +126,7 @@ class BTreeTests: XCTestCase { XCTAssertNil(bTree[20]) do { - try bTree.checkBalanced() + try bTree.checkBalance() } catch { XCTFail("BTree is not balanced") } @@ -140,7 +140,7 @@ class BTreeTests: XCTestCase { XCTAssertNil(bTree[1]) do { - try bTree.checkBalanced() + try bTree.checkBalance() } catch { XCTFail("BTree is not balanced") } @@ -156,7 +156,7 @@ class BTreeTests: XCTestCase { XCTAssertNil(bTree[9]) do { - try bTree.checkBalanced() + try bTree.checkBalance() } catch { XCTFail("BTree is not balanced") } @@ -173,7 +173,7 @@ class BTreeTests: XCTestCase { XCTAssertNil(bTree[9]) do { - try bTree.checkBalanced() + try bTree.checkBalance() } catch { XCTFail("BTree is not balanced") } @@ -189,7 +189,7 @@ class BTreeTests: XCTestCase { } do { - try bTree.checkBalanced() + try bTree.checkBalance() } catch { XCTFail("BTree is not balanced") } @@ -215,7 +215,7 @@ enum BTreeError: Error { } extension BTreeNode { - func checkBalanced(isRoot root: Bool) throws { + func checkBalance(isRoot root: Bool) throws { if numberOfKeys > owner.order * 2 { throw BTreeError.tooManyNodes } else if !root && numberOfKeys < owner.order { @@ -224,7 +224,7 @@ extension BTreeNode { if !isLeaf { for child in children! { - try child.checkBalanced(isRoot: false) + try child.checkBalance(isRoot: false) } } } @@ -242,7 +242,7 @@ extension BTree where Key: SignedInteger, Value: SignedInteger { } } - func checkBalanced() throws { - try rootNode.checkBalanced(isRoot: true) + func checkBalance() throws { + try rootNode.checkBalance(isRoot: true) } } From 25a82a8b9769805fc413a592441726c326a14258 Mon Sep 17 00:00:00 2001 From: Mike Date: Fri, 2 Sep 2016 09:20:39 +0200 Subject: [PATCH 0499/1679] Update README.md --- Skip-List/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Skip-List/README.md b/Skip-List/README.md index 1722e1fe6..fc98a4768 100644 --- a/Skip-List/README.md +++ b/Skip-List/README.md @@ -2,7 +2,7 @@ Skip List is a probablistic data-structure with same efficiency as AVL tree or Red-Black tree. Fast searching is possible by building a hierarchy of sorted linked-lists acting as an express lane to the layer underneath. Layers are created on top of the base layer ( regular sorted linked-list ) probablisticly by coin-flipping. -A layer consists of a Head node, holding reference to the next and the node below. Each node has also same references similar to the Head node. +A layer consists of a Head node, holding reference to the next and the node below. Each node also holds references similar to the Head node. #TODO - finish readme From c20c4dec42a0281d930fb800134ba48c4bb0d33a Mon Sep 17 00:00:00 2001 From: Mike Date: Fri, 2 Sep 2016 09:41:01 +0200 Subject: [PATCH 0500/1679] Update README.md --- Skip-List/README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Skip-List/README.md b/Skip-List/README.md index fc98a4768..7c6ca754f 100644 --- a/Skip-List/README.md +++ b/Skip-List/README.md @@ -1,8 +1,6 @@ # Skip List -Skip List is a probablistic data-structure with same efficiency as AVL tree or Red-Black tree. Fast searching is possible by building a hierarchy of sorted linked-lists acting as an express lane to the layer underneath. Layers are created on top of the base layer ( regular sorted linked-list ) probablisticly by coin-flipping. - -A layer consists of a Head node, holding reference to the next and the node below. Each node also holds references similar to the Head node. +Skip List is a probablistic data-structure with same efficiency as AVL tree or Red-Black tree. The building blocks are hierarchy of layers (regular sorted linked-lists), created probablisticly by coin flipping, each acting as an express lane to the layer underneath, therefore making fast O(log n) search possible by skipping lanes. A layer consists of a Head node, holding reference to the subsequent and the node below. Each node also holds similar references as the Head node. #TODO - finish readme From e1ab353a76d48e18915013edfa8d3303996254ce Mon Sep 17 00:00:00 2001 From: Mike Taghavi Date: Fri, 2 Sep 2016 09:43:08 +0200 Subject: [PATCH 0501/1679] Add schematic image --- Skip-List/Intro.png | Bin 0 -> 21910 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 Skip-List/Intro.png diff --git a/Skip-List/Intro.png b/Skip-List/Intro.png new file mode 100644 index 0000000000000000000000000000000000000000..0bb64865d5d93747e5d2700376b2969b21f8aa9e GIT binary patch literal 21910 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 literal 0 HcmV?d00001 From 587aa152ff1d0f8c477a2ad9a5547b1cec756b90 Mon Sep 17 00:00:00 2001 From: Mike Taghavi Date: Fri, 2 Sep 2016 09:44:37 +0200 Subject: [PATCH 0502/1679] Add schematic image --- Skip-List/Intro.png | Bin 21910 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 Skip-List/Intro.png diff --git a/Skip-List/Intro.png b/Skip-List/Intro.png deleted file mode 100644 index 0bb64865d5d93747e5d2700376b2969b21f8aa9e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 21910 zcmeIabyQYg+wV(vceivmh;)~~YTi=Zx1e9J=m%uC?ZzYtFgm_j7%(J4{Vg4jqLA1quoZT|r)20}2Y}D-;xT z4H69aWVdPa5%>q%MMF*!>hmDkCOANLlGk&AfFb9X5n;W|u54)qY6$h7) zkPrtaHwQO28z{l%;^E+G;?CyaLVJIaf372K;bP`&{wp z>(6~XU2QD?$DJHp9-0Lj$N~9=gNvP$<6qYXr;0#66_#?ecXGCHaRJvCbp*ZOY-6V2;A-IvPIfhc)J~N9;q3o)iU0XpPn~TnK&$W0=6X2$-#>dO zFTw$7_`h|;eJ|gA3c6VoMTFyDk4zM$Vwrmm3Q8PGL0Uq~9eO7N@f&{U+_y-icS!Gy zB_c!Ny|h>*#yXxxqI;cd{o%tQ^&zmUB=w3W5i{VuIG_9xz;#jEJzDi-$nxSaI5B>3bZU~u zCpfjL|2p1xgxNwof&J(BH{2NJZ|NhYhtk%FxS&fN03!e941mh{5qR!W?cX7Mt*R%)Y(32s84<>-YWA50#U|Q4?b{uVSixSd_KFI$ZRd&*gq47Nu#85{9CM`9^qXk{a^^JCU~8M0QEar5M&2czxC85NwbsTjy8z4u$u1!kQpI|&TT zBKZa%?==wfSh`ZFyif9j`w-Z&94*##GX2tRclJDjXOKwPbwhz6qx$ydGNdjV6zqwi zHtUXha=sE@yWn%_GALwK-gsh*!wO%v*2hxbaC5OusC9PK!G3ZYOX2mWasj*o!9R%6 z3k$b5r?k-`aaIRMKc7C0P8I?$xXwqMPKzxbYpLsnc~R5ehXeJln;J?oszR%H{Rp+Q z&Zs|B4mL;fx|c#IeQwUzPq)Um-=VT^Oq9*MJ)Qg2=;h{cygPSU+kCxKRFElb+~TLN zXxCQ#+OGWIC`GzY&U&!EcL&j9@%4nBm3_nCuE{I6*;n04?BC(oKt0Q!YFG5eGwg|Z zpEbO_=x=U;@%r<9y(0`a@3%wK`I-?1#cYY&UL^ng*}T_YWSf!aW`3l=R3P2l+J~3N zd=u^)IU%_Qgof@*%mE14O=~gKPoErX;eD2Z!I2MWAvE&-dv!Rp_kBI{5Oi_VtC0fplcw+4-Z_iYw+fU08I2Y>=%G)u!%2X3u&>{#xe~qD$P4>nJ01Aij)RE8 z_v-JT<5|$y07T5)sVWBk%w!`Up^DCvh8c%?KDPA}WUWwh zwn~t3>4(vNy>NS>b#l7k+YBl^|N7U9zzXV+y2h0_CH98>Hs1b%EFY3w>>gE$fv&E3 zpUWM>eEXkV7JUi!HBVWSN-_PmSKQDg_x7b)M!=X|w(w}zCU zSnS1{De%;4kNIafWt~tlNFAz21QxsxLw>5(Ulf-RsnkrpnMviba^4QaeJXO~dt+7h zb%KUWO-f(}O_W-|7YuJ+q`*zGuM{%3A6|YwA20XmoLHH%${KLdw|@l&*ke!Ggm4R} zR2KsO7);SKzj(xvGSRme##&UIC?o3B{=zkckD9>Pob=-4*{j?BT#)f*dOgc`aQEri zV?s)wGins0APqkC>iz32xaOxKf2FBZ^|P13^K4Az=BV4C(c;M@YZI8Z&I3b)q3)GG7)lKf+v)&eKTni0-goo zo_+1S@OrvS6X@5aiFPp(%z4klfmdeTgM7c9%acA5+V1CJx{f9^A`7bCq>4%g+eSGU zlN`!m_%CccqSbEOWwrBLGqro{^?z_^IQw3$W%F`N;j(0n#vJSlPkjFSMRC>;Ol=;s zGtgMV#RaE!^p@6@fYTT$3=__7b>Z?L>%=SiZT`fS*~(X2E;ox{ly)?{SxtNv+;ny_ z<7remNpXc@5qSmfbnL`g3yz_TMcM*0Z&BJiyKN zP4mgbe6BQ<*pAy!IRfiTFi2cidSX-13#U&P-pVZ=ZT>9U(-v#G@w)_5>2kMz?_~1r zDWgEdBf78#3$mjWZnwrq(8$$tey>HgW1MO=3shg!zp)S$Ui5=iWP{$xx93P7iO9!} z7BfhvRweqWv|Nk9)Hw5LrkjlQwPSgrjy}_*dkUyxcnkX4ZiS4(*rsBy(k_5H-?O*OS`)=kZe=_+d35!O;i}Z+g1CbFI zkuCO0s@s^2&=d-s*u%A3s z51n^u?HWvkviR*u@^drIY^+ZG*AaQ3A|q8Yolg99JwkAw#5#@4e*g33NA7fp(@Ds; zTtR!`6gQ?IgNEOs)X;fvS=aeB$GNcJgJviB#N$Tord-8^1UD7~hQ#(7yksLy^WP3TVtD9_tf4cL17La+L@k2Li4^mMV? z7P+IcRbxp#$9qSPeM#f59vX#$JXYDr%sOJ754V*^$@wIYxT3iw2iooBd@448ysewbszu>*W-=i!0pI#u5e~*|dTd?Q=~9URt3?=e|=2d6~2B`^zu);XPAlx9+E7qXl+Yqx3*aheX{rjTw7}@T=R&~ zQ?zBGULo5Sc32)tL^r(-p1i7E%&CJ`8Z?CW>~)M>Qb_TSF2zf0gie)kRB3Z{omyh* z?Zo#z&FL^@VU%6UI8F{j1KL{Q`nMHC@*5^1ru;Ng9P(Dig|ipd3}C5as>+`kzLLRP zT8URR{eU?ihD*O6`Kbartj@31czUd8*7LHgRxMgG@AuiISu{Kkts8?%dgv83@?-9X z)ll`1ai@gEWeI=5GeSY$FVw-|AyamEq8rk_ztSSXBHDpRv#%jgkjLE1AFi20q<;13 zwHAE%Pa8XAnbMTE@`L_DlHR`5Z5msJ8zzh@Sl?-{{jfxRT4oVm^1_PBw|vRW=jnSL z+OH?lzt>IXqMSg`{j$8V>sNPZSI}zY5M5wB*L60p!b^e6)B3%p$3YsrgyncQ%apg) z17yp9 zip~}}47IHG-ziT%S|sTOqr>}{=7`!}gV}9vAuF1qtiXthz&X&}XjTc|W?&+1}WH4Q6e(M6m%wRg!*f=_l zxy9}LSeZ2pa)6etOCf(uYo+L2MvG$6vr_2B%9X5CjTYS z0N))bg5vKLhbt1;^kcL-q0XO z-I)D;n82h7S>9l_jZ%a_UwF_gF1QV9zGPHVf%9&zr1!R`-<>Ek`1Sb(gK`SiuFviD zX<)z5db+(V|35dAf|&y&{om1QDjpMf~6i(SWdn~s&yy)lJrDl7Y3L7cNwkCpjGucw(JLKPeHjhAPCm!Ei<4>9sWpAw?Xd82TER=$H; zj}1X5ohZ^|__*W-_R|_dJu>Z#(&%7B+4@;&K<1Sg_N4Fa^?AG9*%`U0_u13d8xH?m z9LRltd~Y6x384V*dJ-5|1hhqt%Jb97ViU{RE1Y4Un1vd3Zt#^Z+?kSHy2$=sC4R|x zLd_E}KJ;ToeExN!(c5F~g{HUNk)*#0o@UvO5r2Y*dzPbr5=786-4}eOqPuFI9ha{mCf_xn z1poys&YjGUfpW+Rda7m=$7_-p@2{BDcO7Its|Yf z(*s)IN|g`|k}YW z1`WM-_OMW}&$qOIJ{?fG;s#PzfzQqvS^IF~jY^lg_n`zWRo3eN1m4ZBlZaO03Q z0rz9sv$*El>pho#uI`!{2Z&_I`RKMiVITeEr0|i8?NNJw>dv(p>$ih&mg#x}FZXDQ zCpYeYJ68`S+Vq*N^^tjb{PUCa!!2ljm=YY>I~QJ^PXkHw>$!_clQYqQ1TxjmFC*Vb zh`d=U=Y>q7*}AKPAK$gd)uuiXO(9X5NK{P$bsVz-UeWJiSYA~#c|Srn=q@r#G_abt zl>g#U7NzZ=SsaC;>>%bRA7WIH?u?Su2ze0Ax0iR)vBCG|Fsm8#@ey2_h{wTAd&tmC z!O#^dYejdamuk8o7xVU7n&ZvtVr!%4>AdxF8$%OAO+JG0mqkOTu8>@*;Wv?Iau$yS>Wv+7$we1duyT0Q#8z)|hu+ zj%2HugfVdKq1G)3cySRcM=@m{uW}|ev_ybPL>4W2Vg37yWSdPIIq+$ppOxPtbbSZSFN8^~N4RF=qfFeBW?>lXPZu#I02nfahN1lepaC|%XHq@!kJ>)h?*s>JJxzYm z6*V_8W7kg9$|h*{ZA7+^)mLz*x}>}=e8fD>zBWV1g}zo*@Nb9I?Yi%T{!6wtXg=4f zfkj;B!)Fl2BAzm+zO8;#{(bF((e>7|_n>?JpUDB+&4f$2VIxw6WSr0!Y>KH#J!7$( zaF)-D<)n1DUk!`4bS2@U66}Be1+R(Gu933CA+fBR4s)^~t?g_Ai~h?$9GtOo*jTT} zwV!of?g%VYkbU2Ohni~uctblN9`8?U3>-56hg84R%x~lh)O%g zV^&4yiBu~M&qtT2kw4E%!{D67saTKNb^Qg$F-SUmfhw6)o3u!NA*nAbR70wG2!R>8 z=Lx|HZqHQnciU)*s@6a?Lue;OaQ<*;vHQMD2`gy;Op7PD`E=e3`UbE>@y!(P{V$I? zjHB{g4N*s!&mUze=Hj!fzP%Cs3Ghgm#|}V)Xpz?ttZ)M_PylTmHzaylYSirGKJsmZ zNY~IzlBzAuu_^38RS@wlA_kfKOLR(6GL8`B!6&D)QkYNhPVH;w2nc?EQz};xn8QP* zNJCYp3d+UNm<6jPF8st?<#>{TtOtg^MdC9<4|oopzQ4=eRoW;2jufn!wRSG|nrNLa zjyA_miz$tKTdrqahW?K2R9^0?I}j613%0bP>6XGYGwkEm5s5ELJPLjAE>X5{`K*8PJ{qnm?d{`_Ljim&_l z^bs;8UWw22ZSswmbExoOe7MMiY#4Q_4Uxv=#J&NM46Bm)#IgyI!kvofQ_Zw3iyd9OE>cEx|}EAts(Gc(xcICD@e(fGnKbrsJRJtQsF_ zCE8yj1Ar}{8_2k$sr~P=1uD+}WDAo^m44h!832swqDbl3Rdt=9{KZN6mL09F7#B*DW%M8C z)iyuH{XC=cGv*L8Df^*#`T0HCrVve6$yJY}KjwaSnX*Wh`HH!uTL-{H8TrnW+%mII zgkM@fJx(J?Iu+sBOopQsSsYBAr#*JRuVW|>RVY4v zoV1o_0E1JA3OzyboG4yk#;%I}Mcr5&1MLuCnEfRY5q5ualPtduOQLdh$WTvWr@A3S z)&y>>8!%c;Zj*oUDLqQ}y*bAe-k{=-Qi82|^{cXP3Tf6jA3QX1WN{v2UwjN04jQ(mEUTd zc|jEHT%&n;>h&H{A@{Uc0qs7KT=jl5GBVLN9gh}&#N2Bqx_9JB*dY`bm&;L7u;Ra# zIy=Gp_$^o)J6}yMh0tP7<8IZ^t?_+4?9H0%j3J3%# z2k zISPc^fbRXgkM#%t(+*6Je7@5d(wjyV)THLZV7yD3mDWp`CS2*&=hlf-#r z?*1b-qzb@^zMefcu)8CG5h+fj!$gcXi2lCBDI(-F%q+|}pfm^K0}hX-WM47k(S}o! z;eYy&zpq{swqO+MEI*@ek{CdgZfK>%h!ZvyvckHK^!GXlNvS9=HzbEwVkPPbR`To& z+J&@q1g&Pul9ZoNSJ=f>OnQx#V(k>LYpR(^JnzZX)I@nC|v@ zd9a!gb7)(a5ol3xzn!ke?1~8M%mT_UWhAfp>i2srQIFA&Jt{q8Oq#OIw>J@+Kh27! z4|R@35{imy!ER*&ZtKjulI*vuAr?Jf!R<#_3WN@M{%@e7{OLX^3p^=olAn_<$D0zV1_+xV*KiFA8k{e}WqV;_ zo(Fc)+StZ$J?)2y$`R&8#lJNbR#-cGzLavm9ttC}pi_RsG8Y1kPU7@u)Z|Uc^+`|mGw0gyL0!B%u=6X8B5M&V%*y}L9$>CF>DPyrTZA7vkcXXOXzwuZ;cqSj9#Ye=i2p8Ow?e%QdT2&J0bIm_@}eN-8Fh{ zhF6K}3u_4)U=r%GZRWLrUBvZ{`4?GR0tB$)ID)gG3nN6labMWq>aKsF6Yu*+2l3Y9 zv$z=}Q5Q5SE z8B?_>49FTp##BLoMZ9)zO%($K+UY9-qa*L2!2~Y zN3^7Ve0w-t12r2a+p%MNsQEagA;C$n9u5aU&8QOJPzX911JMA2qZH2TwN^u!fgd&E zQXg8Q0WJ{(Gd5+p{i}T8qe48ra*Fuw71*>_J}WmYN-+NiHQ<3ee}sBnGbI~AwGoIP z%V!HA;a$XA1A#7d@vM7nw9~rVsa6Xtm9hVP9_y(-zm@9~Q%j%@;R-Pi9c$FHs{xmD z=%6~3VscY=!VNt!J*v z2M;++P_sShhL!($T*{5C^>xLR)y5gOQv$a*HBiO(V>Vm?;0Dv0G>r#a)+imP+=tY( zTJWgZp+#ROhD6&N$6kOq^>pHwUI)B7brd%5FHsZ!F;)Hbk+aEGq{Rxq(xWFd4M%EN zFU7ykr7v~nR_g_GH6|jh=)vv~sSGAttii9k2aFJh4Ti@Zvw#3Qe_47kA$rPQ&OH?G z1*4X3*^>ETl+ps&XuUG=)!||OKtN*gB0tdYhHsC@wdo4Ex4^d91q82jQhPR3q!%e~ z&$>YvSHOO{dQ@2KzvK^WjU|ttz*zJ&10(@h!!eE$Yvr_UNrqD!vXET@cbi;?L*uc| z#SFlOxiPY@BZ#=(CFQ<(Dtb<51V{YD(=~6Ry4ds4FHGmo%7Ir^%viEX;)BTE7n=oF z*z>QJyApl)mi~5A8hPz}1=Ga4i`WW{T=?i?yef_AAj>Gx??h@b%l;HeaqWf!e-!X_Tn$TM=C2pLn0;_16ueOUdw{u+ zEWdx*f%{Z#2E@h1B&ILufsx^7-&f)e zQWKIZy!H1i6^x7WlT2mWP$IsXrLF4BCp;CqK63uS)?M&hzD;|22)HWRLG(5rlPZ`d zB|LQh_?J5bqnmZHTcNH9yTDWt5AN+MAn}u<>cKWu8G%%{-J)xBB)@pYXl0e>FoD=5Lx#bdUE=469hCD zAX~Oq`2;UqNAduC0CB1(8`%M-slaAIYG79hPcVW-VfRsA&Mbk(k(@Li?Ocw+1Mmv| zO#mPn-Dd1-JO6IvMa!DfxtP;>$DlW!fUErG5M{tU2F?sC5s1P}9iwz#^ar&^BTtrF z1e+MI^$a&rpnSk06Cp;}d#2~J4&RxK^c*+?7D4>IrSN^wA0VHf(vO3&G-NmgYWc){ z-ouEUS1?AE9FH9D83mS&`SX#N@GvAA!S^M0f3xMH3Lh>kkV0`wo30B1UwFBXO;(L4Q z3&=Nj3YQr|?M5kHH?F*3y%Bh~bSaizQ|;UN8IcH+2nxU6>aZJW_Pwnd6lNi^D>6PG zoS^pyfGS8U|N07$4~uURG+98kY@h)2t%Ap`BnQJ~nQG-gJ65UQ7h{Dc^0xz5iMkpR z{+^z*%rmDIX@ejNRE`GDv>J&51!FN|w2rHmN}?mWq?_&1DhxBKm()ovx)Q@~gwLHM zj@CdtH_arzZ;%TF!3OvU6NaG(^vtm_ezI2eb2p!La-^tzGw=+G;hWH<6<^kQ>A4d` zHU8xXdp)3=w|}F38#Z#^BcKsg00Rm_8XSEVuvH`mR(g~*mYObUhhZzFSvlf6nT<29 z5(Sq5a+WrQy<2F>nie{w_#qSfQNwc7;|)Yt(K}zphY&p;MuL>5BMe9dN;}_{qh=+) zx3d%Gv+Y?waY%|@n4dcsP=02aLzzEkTT-U`c?rNQ$t=;gh3>BJnXi8NUK7sGI5uZs zTu&G{1{tujGXCDFU66INY%_LaQ*=I=vT`ZGx%RU*gnxuJk&rV|Bsq40FWh(PQb*jk z0Sp%!CJwPg@IiVUl`rk^IJr&0Pn@-e+O%lPLKpOpb{f~k3V2Tm$|hAs2^ z;G9>Ic2WSA$ou1SwiE)Qxnf*H72o7+7-d>fP+qbiEaycDGp}^baZhzQ_&YOMI}*@EeZLFO^f^QkcpCXdO=K_f7Y0jfBsnZ%ydf2rXIpW5zfHEubRF}E0D_{VJzzn zsr*`vuOE^yZ~t?yPW=mZW(K@rQ;YQUCoLv;ZhIH_7X{U!`^hpM-fF1B_(YsQ2fGo( z=f5g;F0UR{Bw~=nk+mU1n=>IPX3nAydro=nH}|RKJ#=hpG1scQ{6J~} zk#@$9a5WRp)FRwJLTnk?sLPh9^mMm?mcKG~igJdr3VNFhkGH9%!&WqizSF*XO&hTCe5j%b%0~Nf65Rbbn2UU++&Q{iSO!`c`HM`XL5V&J8h;ki|0m+dT=4r{T~$t6Og z)-B5k7zeh*Fj2x=!p0B_Qyb^h{l;WiT;$(7vjx%c()ugwiX_ibq8ktD&)FpbVj zj8fzY;Nr`a`ZF|QU`wunipoX?jpht_^&*l8j(6hsHvbN1`D9fYs%Qgt0tf$KlLH@I zxg9~}?$GW;TvLlcs}XJ6Ae0(6(H8B?HF?#o&qU+c*@$%Yxu=Aj5oUDjg+S-_dy~yt za1GefUx@T<7Gy=W`XR@qbZlkQ@`*AGrf+R6>aQ4V z*J?SJp8tlfFdRR5xQrzEXpci0W`mK}{~)7mpt$qGLy%(T!XH!a%S?aHYhxHLeXCJU zYW&fZM}Y9kl+zxJ{seIm1N>Z+&d^molVUv-N{h6qOH}o+abf0C=bohY1G_F68P3a? z^i?wIre-V?rq>B+7)r}u-^g7+*PfNYwN6J{Rt)gZRD5sINXfgT#<%)gkxvO?Q~9a; zIcQ1K(#vfJZ$RiH=-$~u>}EI1id%J6R_tl8T`H*9`$MSGshWo0=uFoJNp3l8HqbcG z{E#S8G^zNBVx7lAjw0?HX7B2tM+>}lUA77tC?w&=6 zKCp=EbvV)SlE0?O{*Gjof*7c#7~iu+LukuObIvE>_o@y^S%NGC{*972{fWtCVdcHW z(b2`uTm8u7LL;ksA*E_fcSkznhcqHse=x%WGetry=Tw<%ffTQGOQl$NYt_lnd-@U+ z?V^K){`2Gt=EVUrAqJIHTrTHPTxUtzRH9yu@eJ?(nv?iD-Wb1jJS3H~z=0t0yQCC< z47!-l*M2V$M45WB23Hb%5OuyBQ;C9A4{{`=>Dq1wdf~Aa zdKTiV(h=M^^!16KePWb9VJIiwS`Ib`l23YfG7CRc=#5ZLECl&%sfzw5VF|xJ&4?eL z0wLUc|3U&o%frZyIm;q%!KE!7sxIF=A|o) z{FG21>SOJ>j~ObBr?WEE?HphC{wPk_ogn*ZJ3>GB>pFX0 z=q+9@2>JN`@M{pZh7SJa`&}PywLjkFud}Sut2LP2V`_UjzJE+EVi2QywL-JcH9d&1nzX?= zue<&32y65_R?Mg4c_2d{#Q~0iFRU8iH|;?BgQ!07O)iRz*yHs-Turs5{Pg3f_|Jl; zdvo=tE4}ejyL0t!lwv;K$?PvQnEI8|68(%8`b>Th-ic_8$5JCQqdqZ;sBd;>Jtiwm zGK62#xcRtE+b|>sXo;s4-940#QsAcKpQ{FHz-!)ZXF75A95@r)^*d9_@4lC(f(M3~ zk5I=2tcYktoIpzgd*$J!X3DKnwgX%>!Y_1-Yi?#&$Vj>Pnj>@_0_-Gs^=Rd1=Yuc13-bv6>B9EV71L^y52N9{sL;(#iS0@3cWotm6C8}KaGibk4ffqP zUH|%~3yW!Q?I?n2eZe!!7n#T5%O|$Ma>vz*O;kwhL_;!ipruEBhM^*@@jt}gJ+hL2 zJu=wPkAMczuKB*s^hGv+8jmM|T%2Tjh4{Y60Y8t$CB)xU(R=$R?XJkZt)r7}@kWws zMy2RspxWT1&<^wu)Dt7`!xxBnOTkF}0NOrg9l=^lE$DM{+pn7*^Yab-x<*^Mj5ip- zEQae)ccqTuoJ+Yv_BQVwvuh(>(@6osb@quebAQh8jF|D=+pqo4ZB=q<#yYG@kvNXNkbE3T@b$<|m=zFXSQIr>7Y zOb^Q+Y_-pUDFBo^<{1*H3eBD_{S|;I`fVwgl)Yxs^kr#f7Z9}qW?c~te4fMy=X;G7 zfzg5sAS*;9Me~z#m?X(K7np}##I~mZbR77sZH(lRe*L69&hp(S1~=;57o)^B`bzEw zL>aePRzOgxZy||Xz=5osTTbYIneGw3%U_VEq82T7a|U$(+;^9CoG{|ge3=%AFV;6`q`zB$S&9+4P|G)!^dvoh+RAlW5~=d-fO<~ zc~^a`_$~?LgPekGNfp5JtJP=>EI9t~QVnk5(%86ps(7FOPn9mJ;ZL-RxZxlZdBKQWLMM1$#8j)z01^Q0$+85}QMxEJk*=YrbH?)I zFsr#Hj>-_H4$$)ImW`Lrk}1mrFoZ+3@-JEyS<0%nKiA8~>UCf(0lgC@X}MYWJVMVh zkyR2d9N8x8?TH8Q!kC_Gv6~R9^?v{(&@y`YV9!y%TwXn1(`NfV){(vM8^sF@T3On!SA>DNEjwj-}99*7IT>Sg2z5lMEb8)I5PU@2!G84uG)n z`nIY8Su^;~PzpnRK8HllAN5=kBeA={bpZ+SM;J3sa5Nri$UB3`b1*c+RD(_;(P~it z_*~svqtr+btvka|{~M7RR*nh}ZcWpiY2aeGnFALMw()E{o_M@fm^bXJr$r8AklVZm zgMWwBaWe=?W3TVGV_I!lNOq=lDXv23kgxLe3Fg}%83ZZqZ;d-OGu$3|dYD9<**kE2 zA>0I2p0Y|1mI!eQb+OVhJlpcxZ$+epWSUTTZU7sBZpPJ)qptxl@OXIox6ofu-s~f4 zA!6BsE`@uuHO8cidY-mDshVn`$Ej^yhe=*oTpaVU=`Vw7x_mI8ZfyD^5F7^}!Y6T( z&&3)S$J@04>%;_#!uF3=10yChS{_y~vJMWMEcLltV0k}+nl(Q#{Ln5x9*ESykMzW! z$VDpzoB$FIjyy1F$a_9WBTbzs_%0(jB_}K47M)l%Q-m1tMMihz_cy>0mW|2Ucr==b zN7%`vSq?Engr9(+&fV|_R6|`p2t!#A4MREqdFx-u%8)J;zoPp*n~ajWi^ zXPH(u{g6nr%auFVFuYt)bLH8{2qMY*EA>5Hqu1LLkt)13`ie@W9g)yDfFL`yUu)p`Yz6^y0lF1z0|Wi`Eq7=d1OV2g}KZ2mcsxo8Em>=a~$ zRh6Te>QDfC7=;cuhCVSQ?WrA418=sHt?ZeukI`mcHt<(e)L4g|)71CE@TdGfP4)s+q9( zQv6p3F8mPs=v?@nsiSCIWbAJBPgOGt8Qe(Vo6BB9&`G?Km3q@7#3(LO0rKBW$hYyi z3uIaGA*pLdAO+Ma@0F7P@uB4}C4T#X^whaJA2@(qg79_3gB6`$k|Vxk z)Op12>EonzM*5y|TiyM8ifM)ZqhZXL`14he5ru-nYb%V2`T;u6bDNn6#{XgiF$LPa zS`8jXGt(AhZ_!d)0yevfXKGnydCjIk%4})iYK#*K3Re~KTL9D$4-zp+aN_S4e^>~4 zbM?s0S>ST}g4O*N0BiVorrpt(z_{4ytd_i9!8@Z@R|`TQj2OXzccvp@CVFTBmdTj* zISARb@k7@yCMbmwSsF`TMwPzv8gUu7GIXrF0WW2Vn%E+8n1;ok__|pO$||>{$&uL` zA&_1~thUA2AH6L8-nIrK)#4R7#ugZ0k>Vz_IqM;@Zb@+rp)EW?;i?QPNJ?LOJ))SO zYD`00zs0%vP1tN)5S_2PnyN*Fi%R2YZY;KV4KIrmjFhm9@)HN0q_QWy-&h{mUpJ-F z)Y&tvJLV95oLO6au&lRsx1>xecV$PYg0jOQ=q5td@1Qjg5sN}N_=9eBaYI>b#9|HmLr35Qo>S=hR3?mZLPpKSU+Q3o&hud@>_=igiAfBd}?*#XmQ#%^E_o+?~NwYN#YhCadlFvoMj048>;m9C#-Cf%_X*B3&QPG zBB7H%SFW%K6q!eb^@FH)V!>PG0EttD`|%f<;}WCmVrK24*OAkBndtCZx;5=ko%op& zV{(0p^+sQlVz3C*TULzee=x|VO?&BYLQyE9nYpLslj;I`X+t3sJwT0i^XDs%Q{W@| z#?ieu~D=WnJgXleN|VV`;JB#gRD8ot^Is_I)J(7_F^ z8Wrq6Wkj?SuJCsTQJM;GX(e5YMD5UkG$S3JSn@bMx)fU_m!6!ocojycQbMk!3bqe% zfp#6k3c3B29h}ZVxXkLtgXC%`*^`Q9xNMJXh*!ZPZf01xe6A0sv<7oNufdqaN!##Z zYOZ4Y_QnlxC=+o_RxKYn^dxPjb3vE9wi_<2QB!tJVOHlO`cSMw`rZh#i6NX3v{KnR z82-v|1;QWgKe8$#UwpDc;KF#(iDbTL5dd4SO2QI@7U<|l16I#$xNJzO*Axte2*sbr zyWePsTi=AhM8q4pmwRhmm$u(ro&D{_t^3vN*c9ljG!>v}p-{+#Jai25eJaD^VV z$VDp%bWz0ZUr=`8M3GlK?cy@lI(W$HQdCVh=B5tJP{%vLVjF7y6K76Eu`LtzJjWt9 z6+Zws2q#5ir%~wEZW$^ThP|B_bilc;=%VQF+l83h4J3%3zGhd2-k=LNETSQ7zWx$^PrmQRs_;) zEplK8X5|v9>~RS#N;+Fbwau*8Et{$~jTLrYkxx=-IF!scS%T~OP4jbTutD1 z8`(W)l%vCW!-@8zjDx=`G(aVhL><|>6oE*;Tyx=0pH_B^8}GQsO*D^EESrhJRKVYqlpd163ujTUuhAPZny+Q1@V5V;TSJH?2cx5JyeipsFX~ic0&|%Z_Jc1_nKwKeRjV7(zV5nMCECLaK z@$<+rc^J?qFEMW_tUweBXV(q zEV0|1#Q2kT?zZIbcmA`!(AYmZkV-4ko1|*p-ASm(nV4(Khvmg}_U`Xb878Wp2C25p zCd7jIwQ$;sc@g!y*;|<=#7jSB6(N0V(INka1p-0)K)07kua3$eNg(8Pg9r3KrxPYa>$z5BIrR zU0G5kcb&Gcmid5x1t|R%NNRSn`ODErl;Yvzi(~NXOOs~NiTo45_;dqI_DR7jQ!iZ4 z5BqC$zkF|2D?PC#uz{pcScU={W|SDl;9h?!4`7y4tcm5HGVd-z!euHAyk)tT9WP4f z4P4J@4}@*$7Po3-{i@^#>DG(g2qLEIt^q@VEcyVuAPdyL*@1W>*eW}4>^tqZD(>2) zk|o;cwl^Qo@D$@k)xBk`8%-x6Q{VOceVfp&v#nTR0<7(CfeI|p z)o879fUvS(pnB0G?=w61_LtgGe|3hl`!4ydYZ{j=Y}UNLL=8I!Zn#&F6e3_W0GU2Q zZ~jb_{nYUQt)ZnK=7&*f1 z>oz|zBU;qSfT8Buh#|NLg=Tz}WK%D)z+89bVQGLjRZaPEMq?V&cIgtBP0B!`IHt%x zRP)!BpZhkX_*yyJAkWF@cxT3K_S>ts7e`E{n5=bIGUk~AspBAxFm_{`-ER4M^Qmtx zn%G`E6fcJW@NCQ|0U=K2azlc}MJe z0{zx8HCmr`=agfZ1wrpjM;LgKp}Sn5Fygc{hp-NF`(*(Egtaj$w}4ewOr| zd&I{0kU0oX4Va}qy7m#cVrQrK{S}cQR~%QAxvf*uf8GxgR=^|+hoJFJo!_wLVpsc8 zuf(#GXh^E=!V3Q0xK6&*ohN^{*_qn-Ufxwy9+Ii}!F2#w*&!2DO&JhuysEi`e|}en z9&kzC&6||d_@|=1>q&sxM>=+dVqZ}QkG;4124k*k63@?EDEUiiiRDkD><>~ExEg0DUgaYw62QFY z$^R1|R(uNq>*4J3rVHkSt-=^Tv@|lUoX37`&nCShb&x=KZ$O From 5a0c71e2be157476105e9c833c9f2e719c64a30c Mon Sep 17 00:00:00 2001 From: Mike Taghavi Date: Fri, 2 Sep 2016 09:45:13 +0200 Subject: [PATCH 0503/1679] Add schematic image --- Skip-List/Images/Intro.png | Bin 0 -> 21910 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 Skip-List/Images/Intro.png diff --git a/Skip-List/Images/Intro.png b/Skip-List/Images/Intro.png new file mode 100644 index 0000000000000000000000000000000000000000..0bb64865d5d93747e5d2700376b2969b21f8aa9e GIT binary patch literal 21910 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 literal 0 HcmV?d00001 From 78048a69052819b0affc90ebc5e1f5f34bc0e68e Mon Sep 17 00:00:00 2001 From: Mike Date: Fri, 2 Sep 2016 09:46:56 +0200 Subject: [PATCH 0504/1679] Update README.md --- Skip-List/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Skip-List/README.md b/Skip-List/README.md index 7c6ca754f..5b2607b96 100644 --- a/Skip-List/README.md +++ b/Skip-List/README.md @@ -2,5 +2,7 @@ Skip List is a probablistic data-structure with same efficiency as AVL tree or Red-Black tree. The building blocks are hierarchy of layers (regular sorted linked-lists), created probablisticly by coin flipping, each acting as an express lane to the layer underneath, therefore making fast O(log n) search possible by skipping lanes. A layer consists of a Head node, holding reference to the subsequent and the node below. Each node also holds similar references as the Head node. +![Schematic view](Images/Intro.png +) #TODO - finish readme From 3f66f8413845b22653f91e1326a92ba0c01ea739 Mon Sep 17 00:00:00 2001 From: Mike Date: Fri, 2 Sep 2016 17:32:02 +0200 Subject: [PATCH 0505/1679] Update README.md --- Skip-List/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Skip-List/README.md b/Skip-List/README.md index 5b2607b96..f65609fb2 100644 --- a/Skip-List/README.md +++ b/Skip-List/README.md @@ -1,6 +1,6 @@ # Skip List -Skip List is a probablistic data-structure with same efficiency as AVL tree or Red-Black tree. The building blocks are hierarchy of layers (regular sorted linked-lists), created probablisticly by coin flipping, each acting as an express lane to the layer underneath, therefore making fast O(log n) search possible by skipping lanes. A layer consists of a Head node, holding reference to the subsequent and the node below. Each node also holds similar references as the Head node. +Skip List is a probablistic data-structure with same efficiency as AVL tree or Red-Black tree. The building blocks are hierarchy of layers (regular sorted linked-lists), created probablisticly by coin flipping, each acting as an express lane to the layer underneath, therefore making fast O(log n) search possible by skipping lanes and reducing travel distance. A layer consists of a Head node, holding reference to the subsequent and the node below. Each node also holds similar references as the Head node. ![Schematic view](Images/Intro.png ) From 297f9c25e638d9c760c5756ac7a4f1a00ecdf259 Mon Sep 17 00:00:00 2001 From: Mike Taghavi Date: Fri, 2 Sep 2016 18:13:11 +0200 Subject: [PATCH 0506/1679] New Images --- Skip-List/Images/Insert1.png | Bin 0 -> 8064 bytes Skip-List/Images/Insert10.png | Bin 0 -> 11662 bytes Skip-List/Images/Insert11.png | Bin 0 -> 11517 bytes Skip-List/Images/Insert12.png | Bin 0 -> 18755 bytes Skip-List/Images/Insert2.png | Bin 0 -> 11545 bytes Skip-List/Images/Insert3.png | Bin 0 -> 7420 bytes Skip-List/Images/Insert4.png | Bin 0 -> 7550 bytes Skip-List/Images/Insert5.png | Bin 0 -> 11124 bytes Skip-List/Images/Insert6.png | Bin 0 -> 11045 bytes Skip-List/Images/Insert8.png | Bin 0 -> 10902 bytes Skip-List/Images/Insert9.png | Bin 0 -> 11692 bytes Skip-List/Images/Search1.png | Bin 0 -> 18947 bytes Skip-List/Images/insert7.png | Bin 0 -> 11052 bytes 13 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 Skip-List/Images/Insert1.png create mode 100644 Skip-List/Images/Insert10.png create mode 100644 Skip-List/Images/Insert11.png create mode 100644 Skip-List/Images/Insert12.png create mode 100644 Skip-List/Images/Insert2.png create mode 100644 Skip-List/Images/Insert3.png create mode 100644 Skip-List/Images/Insert4.png create mode 100644 Skip-List/Images/Insert5.png create mode 100644 Skip-List/Images/Insert6.png create mode 100644 Skip-List/Images/Insert8.png create mode 100644 Skip-List/Images/Insert9.png create mode 100644 Skip-List/Images/Search1.png create mode 100644 Skip-List/Images/insert7.png diff --git a/Skip-List/Images/Insert1.png b/Skip-List/Images/Insert1.png new file mode 100644 index 0000000000000000000000000000000000000000..1e1a5959d07a3be6f5d3d5c327169025e90b7c02 GIT binary patch literal 8064 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 TD~I^U;%84=ohtm@>CS%u{E!-? literal 0 HcmV?d00001 diff --git a/Skip-List/Images/Insert10.png b/Skip-List/Images/Insert10.png new file mode 100644 index 0000000000000000000000000000000000000000..eaec313b3b90ac8447aa0579c6477e977970d350 GIT binary patch literal 11662 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 E1qH?G=>Px# literal 0 HcmV?d00001 diff --git a/Skip-List/Images/Insert11.png b/Skip-List/Images/Insert11.png new file mode 100644 index 0000000000000000000000000000000000000000..3c637093c27707b683eef78adda59c0c5787f1d4 GIT binary patch literal 11517 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 literal 0 HcmV?d00001 diff --git a/Skip-List/Images/Insert12.png b/Skip-List/Images/Insert12.png new file mode 100644 index 0000000000000000000000000000000000000000..408356a6f973a483bc6e5f66c71dbbc75eec8352 GIT binary patch literal 18755 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 Mk$ICRq~-Dd05m3}IRF3v literal 0 HcmV?d00001 diff --git a/Skip-List/Images/Insert2.png b/Skip-List/Images/Insert2.png new file mode 100644 index 0000000000000000000000000000000000000000..5fa0940197a8c0ce9130cd8d1d63e5f544e42f0f GIT binary patch literal 11545 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 I)&9}{0)NDwL;wH) literal 0 HcmV?d00001 diff --git a/Skip-List/Images/Insert3.png b/Skip-List/Images/Insert3.png new file mode 100644 index 0000000000000000000000000000000000000000..08f1b78bbb63f7488d23dc33f35600c62a9a408b GIT binary patch literal 7420 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 literal 0 HcmV?d00001 diff --git a/Skip-List/Images/Insert4.png b/Skip-List/Images/Insert4.png new file mode 100644 index 0000000000000000000000000000000000000000..779ad7dd863efe58ba05b58d321d4058d545ec9c GIT binary patch literal 7550 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 literal 0 HcmV?d00001 diff --git a/Skip-List/Images/Insert6.png b/Skip-List/Images/Insert6.png new file mode 100644 index 0000000000000000000000000000000000000000..e2b44c3b0141fa4275e41d2fab5c715bf26b224e GIT binary patch literal 11045 zcmeHtXH=9;)8-602r5y@qGSPuA!m>*K_m$R0s=!A!jSVQ0*WFkQ3NDPj*^G0fQ)3x zISP`IAersk_ucQ?-E-a_`*-)@oH_K|cXxGHbywAORnH4uZB+^~1~M27Mxm~DM-K+W zgTr9(7bJM#Nm7(I3-||j*Hcx56?HTH0$)g7)gHLRVC2-$2M$Y2x&k^3+Upy87;D{? zw01!WSUz^KvJvn>xq{v>n6!^1XrgR9EZKZePR{OH4+r05*pVI{u9AX+-rn8<-ogSdXgk5% z5)u-Ew}b?Rg!n-Zes^DI4@)0@XZP#>67oOg+_7=DM%%l3*t-4a<{qLEa-T$o?P*4zhBY0cjmf(NM21BKxr;OezNa)Y<^X(Dy3vHbN)YbAxq2x5i1H!o59(_r5ki?>rnF6J03Ss|!6+Aoo-e2pL~ zNx$5zxY_7Z-S}$0;dnzzSV~ID{bSGBc7wOwMzU{8kNcmXO=)*K?=FLU!@_2Ayh|7u z!Cfk(ZNFnu7>s}o_T-#O9)Fn_db|c&Yi%q&*I;mxRQN8OL>`9cMVbotvW{AU-uJ?e zpb>B^Xkkm+-J$nLSRf3@#F*hBF_RltT7)1%AzjQcwk0I(M1`6DGkXziop z>2q_b@7hx9<)qY{0~-fSHFN~#!KZus>*IoEwTOT%dW(SVH%gShCTiR_r|OIAe&aYa zU&NG# zv-{@QzJI9D^kd-u=&(g_;0IAuo`iKon~|vX)=YCO-^j#EqJ`TVw6ftMLPqp^jpwJE zo>LV=Cad9cC$rn_tkdbr zTba#wNzWCJfqSZ`s!1>B;rlu=SrQqEPNl7M?JWLIkxoBL;7`s^mgF|;|4hB$O38V0 zoM8Q0;&k_i|L*eTwMYZqZz_=tS)79PyZs5bty@sjeyfFPO5sF}TI;`gaXD*sJKeJm zZr^zritk&vHWQYW*!85uTLjfyn6eCKc5XPdHG?CEJ%`Q2Y;ZBy%?7EW(4b*1`hhzE zo7MBLSx;t&87_&9Av3PO7Psn7l9&$I>2k)d(`~4~q~jk8{4>cKeB#Ee8IsGXYU)y7 z5!OnrEw141>y3xfKhrnU{WSpesrdb1a!I!lChas*f)n{McHAy^=C(0WgHKF3VI3u7 z?lVhR@2Pq=K7A(YwPsAQk*H)py79lD#wu1m?@XUnQ`W9aYv#SKRe zp2KB(d`@d4r5UwP%q7*-MU)MNsGS1#28}$;CmBg9Z}4Rz>n`+W-ZA1`O7SoHdAsqj z%SHBhP1y6^u&~_8mQt>w&~+K-R!{k?nb(YB+W7Cymp%rct&M&T-pjX0cJG$ZBQ!gi z@)}1m%$Zqh`E%){Ol0e@*2^rXhJ4cbSR|06i8kXrU*M8ET#`GlX(nPk0d8})5Uqnq zSrPv9&>`z{QEAvQQ(iaNLn9&j{E1uJQ(o(1r(pYy-0hp7$$oxt$-9Z7hIjEThE8c5 z?ml=ofWod<;%L>@Z`cYMU~jxJdgvC)Q0XwZ0&FF{)r21{IK7m66 za>?QqsBuFThuwH?mD@d!m=URZy{!Igx6QU3s=Z?eHe=^>A4FSu-dvQNAjvuGJ3HPi zR;FQKHBb_dKRn4(rhkL2pjSk|C}Szu}H(04|SL8k~zoKxpa zVNr6(=WjlNw!4O-EEF6coXXToo+@G&LPd#;;{+{=9Ft#AbLBPQ@^WKu)Vg0`LIJ6- zbKpF$4Vya={uQrOA%+_heL}y&$84ye zf8IxNg@0H*KrXe+7k6eKy0~67U6fM%_|eYKF23QYGBMBjFOxl2dv$%%uh?c%GU)R3 zGT1mA2tZ#X(J_g^`r6$WnR%z>JI1q}jwgtt;kKj)DXcQ}hI^412QFpJZ0q|Kxu z#S{@?WSa98ipqh~RMQ{0DO~%b+3+EfUzL^4_;-^f4bn%dTrBKTuvWUGBKMLXU8`hq zbEU4Al$<-w1#w~WLO|VG+4q>$AMfCW-fG((qgOtrH>WU@Q6LeiiS@v%KR2GPyZjlo zV>MD2^A8!TRmcm-3G-i60cr$QnbFVS$n6sg;>UsRHe5Oqi!rHbe8{1K>+wzl<1Ynj zms`jMovP~vOhu=BtS1Ks$+%_c$_EWif9(|eGuF<%z4c9D()ajaKFYI4i%?Zwf}JDO zYtqxm>>5wUc)kB0;FM~b+N)O5Tw3v%XAi$qdxR+Pp?1kAiwxW=u)j&V71O)`9#9$O z9nNKX-moBl^=Coiw&7ry+$l+uN9m`nb;R*>#_QY-`BXrbcdC;E4Ex; z-xOiBA}L>}Z^+m6NkoCtL4`-nGX~jDs~#&hjc^~XW?Fn@v&x-)z8G)efMcD?PsxyK zVpuf$ts#^0Q@&w8GaBhJDH6Y+Nag>}9L9dLWeRq)+?}f9kRA4aZorsx1Yy zmC8t_KCWi@YOar7MhNm`(72c&=lcQQb|Gm4gWU+u0_$M3~(UcLv%3*}0Ubuu_geNt_%b4A}JAhzLnGU?%)>Fri2 zXp&ff++vqYE&|z@X@Dae=U;k5@RAomJ>EV`RtR4GMh1*W!)7A&wKq-4sOVvC;}DbBvJ0@;QqRZpF0tuv-lu~Gj{w-c zfZiIhNx8fuUOip=$=-h@|KNCk{dk=;Pk?8T%`Erm789Ed-gT8%J^((6>|*Cv5;22K zJlBi<%vQ7NZjwAkpPg{I@3>fUKEX|@#{vENR2cb?>?vQEZn=vW`y<+^V$cvo@UuUS=YgkPxi1o8V_?H@^^QJD zJX;bZMZyL_303EJj63s;jj?7j?);|IIbEDk#cmJ)x9ejS$ADdoRiYd_T&Nq;;i4^d zwo~|#Lg#P1_JTN&4y!9gYQ#8f3`@1@$t?N+T{kw zZ95Y#J9RXqUX5t@g9+E7coD*)l|nV7Z!ni+^M{zdOM z8CPoEo~KyQ{pqN=@2R3_+h)~t5Fkd_6g{t{SWHKPVB?9KCI}w-#7n|~#x6e-gWI>_7Vbz8i!?W@BUGa<($UPdnk(wGq!R6k^EktaX6zKNRJYrNM>t zVs`y&^rk+|}ONtS|Fr(zo4pPgCsPt#Mr8X~A zA|7x%s))9^RF2vLa-jTZ7FeIldVu07zZRVXs_w$UUU6_>Ga}qW zn$(w~`h62(xxWf()h3;jA?58~X&i-fev?`&2?_fwiW*}A0RE^KI$ta1Afg)eqCv!D zSYrXa0M$o)M&Ec4T2?=OJoRT_R`zg#+DMC0B*V!2?vJ<6g&9Mf) zq}N(bzCXpovimN3*x3z|swuzxsn-l5D}YMKZB);DEX|DCeH;{U>kTkua;{m7JKn(R zj9R|<`g`$vh2}^3WbJ8@;&oh;#*G-6Z|9zvwfNDEELN=;s%5VGMYSuu@ttoi#AsOEb{_-1dKXsmi-$%tkeIy1bqAamd=TpDT57#+~eZM0Jcl}ya{R@%bX?=6dvUJ-YFefllFLR}RwjOy_=*XSw|FEkc#Bdwv z(kUCI=56hdy8r?eH&(RBYKHYP5cFtl$;*r=Qi0guy5GTU_+)i1`e3lwq7jf)-NQM< zLX*&{)k4v*s!Y?NYF4Ha)hL$Y`u)VI6(I}jT6CAjtLpkhm1Ix|N<8YQP<}~gKMx8j z3&jLIu@->E5t7qAkIFA@%uexJkyuKit}E2lB`z$f8p39l={b7SnGvha(&(CXsqNjD zt~kCFc5%d2)5m2Lt)vUs%ax3vq8D!^!!l(?u9UucvR(UX2*+U;{mXR8f#)w9*TuA0>bdp2Fao`x*rO$X|Vyzf`B*DLu>dn1U! z!$Tw^Ef^QW!^>y((<|^~yPcQ&B^BawPNdkBxX*|2r~QOwT2~*3%6rdL%qf>@PL9#> zn~1MpcwJC6cBM|s@LQYD=%@1R-~JI;zXmEB90jMa_yjK?k;$XUIcZzZC~ldn;PZOI zC>BBa>ld|-^fo9@akm!lNjMi)alTMx_KYdo-Ba)NFi$qlWnoq$mqvsPWhot`HXr05 zvN#i*hAK5j0qqRiuiI|-tV=fL4CkViMDRgX}o$qGL**Dze81Y?7 zHc+)W9W;46BdMaa0*W;)T{{or6j!r6niYtdGZ%~_Uk#YCd%l~QsZCFm@-7l3GJQu| zcH0~euuNj4Z~jpoI<4a_YJ`_@o-rk!|22$3H~CN$J4?)_|D3QDn_wu7y!JmI8UuZ$Dgym2Po zX;Jx{VStH7G0ug&)!swk@v`R4n%CSbJa^-dmGN0Etnv^n`f_gWN2A8RojhL@l+h}D z#3m8|q1Q3iS2RVICfAjfgn3>1)-`OD5xwUikPp5x2#zK0owVk7nQ7M_2H3`Z_kj1= zgLfojXzo2=Bh4PV%!B`llbTCgUr%|D@8h>_^FqnN0!1DLicfPA=moXCtM$Ki##xJhbNgU9BdXk}BOTNc*~MQ9q5A?i@Jv|Bw z#qFCLeiJcRRwSx@x#Jo)!`4SGX%dP{jOP8qsIPmZDb_n-Dv^&3*2aUVllQq27UBJ4 z-Ff)Ees8kt+dfmRLrn}$m&A4ET(sYnTPyhzL((5(c>mf`#YQmi<~FGH3SF25 zKG|#KYw$z!$05KC_~-25Zx$dYH4C3&9sc66!@@jmg5{cuD0`h$F2+>MbB z)WTH8<~1GX#jv;jbvP37t#>OqL^#wWO*+~h*0;7ipH(B`eUSg0Q@J><^VQ?RbW_?=TkX#0 zNYt)_FDpa3|2rG4uK9s$<>-g>EgHUdzAKNHaKV4Tz_(ieabN*?MEA;gq6tstQcBD< zw-?7Q-ntNi*5$@~NPL4dUP#e|KCM{!NB_?o>%uP4=R6naRMu!ZgB>na|(**-FZzSJJW%sx2*nX{KsjfSuZ8iia^&Y2P&9jc!M%cu)`hs zAM*7M9$U-dTDD&t#&63?{uC04ek-TV<^CiRt1tbHL2LO3B<2&6iBRh)y1pq~x zjJDYd{n$b6CB9wtowH@#v{^r=y0En*IS)gNgSpS$EAhv_9+jdSFBw_nv!~SewyEyE zb$|nw4c#rNMPh>PJ-D75WU6IxtEllvreddCO0Xhh_&`2Xw4u#OT3Y(E#Kn-rCz=n5 z^}`BSpH2bnym#HBC^6`nww%ydmS#Mz5M5T)+qU$~@=526WU72~%RtMeWpI6SK(B)J zS~sDAUz$^7v`7$m$EehYnRte$bi#fMl=uPH!)1fSO~EQ#XWUIYc3_oOgsoV3y2A2Q zkpVEaj*_kqV#R^S`bp@kt+m)MJhe!D#Wb0$|LQDf!KleLBQUfV2fH_Nw2+iR=s?%+o-VkM2c ze<*okx_PeYY670;pgxSX-r0TQeXaG{DnT`6$rQfTVb2exQrCM|@ea9~Jmt@?HS_?MlK%Yq^4E&PXOF#qen13GZger*^=GOdtvm;JX1JZp*HxBZhIC$g{?j#00hk@RU20BF0ai|R zJY9(z|8h}o;`FY@T!=B!7^xd7I;FUoH`P8Dm~6Qx>;6oiWO?;gdn98#F6~5C4I1y$ zcx+%Y<;Dya;1cx%5IRtHf6XMJXF<~ku9uoah*xjl_LTx`a;o0HCsE|PX^*v}AtYGV zHZ|vr8F+U9F|i8+Rj&&X_vAFlfSLj|j{$-KX=N1DFaeO00arU6(Oj!lRE(mfHCer> zWT?8Xv$(inNVh;)ZE(ZX7R4%fk(iQ6Jn(22+$$cep=cXu8T8X4i`kJwAKsCdP2r~> z$USPpq?!PEKRe%3*JWMe)cv~*CPG{(@YYh-tA!IqX4oe8LSnND2ZOCR#RU1k26Cn0 zZU+wfwMF@_YnuZft|Q~>h6wd@Wf;Zt(3gLGyAJg6q18@;82F`^us?sSX48eBa#=Bn zEAxzjxZB@)-A%9~Hy`RlRje6W@S~!9*SQN&smmAy3FGPj&X1`vA0?EIY z22K;G#~FcoTye__VJMPVfmQtX1gUWIP-;7<4)FE=ex(eT$mwIDFysTY+2TzS|65$3 z1Em5w0bVE$ZAHKs{!!qc9r(|O{r`s})N~H--LaInKpiVUzg<;V*1l7u_~_~X0F+$F AxBvhE literal 0 HcmV?d00001 diff --git a/Skip-List/Images/Insert8.png b/Skip-List/Images/Insert8.png new file mode 100644 index 0000000000000000000000000000000000000000..2eecd75e454e51491cc97a282721a7f5c09948d6 GIT binary patch literal 10902 zcmeHNXE@wnn>Kog5JVY*AbPLSiKrnYL@!ZCi9TZV3DH{+y+=d~5kwCnx`|#Q(R+(7 zI(x?Z-}l|!Yxl$M*ZsRL{C;OndCqg5a^KIHFwI9wL?WJ7>FV~!v_1!Qq2+7dD5RBAxD$rrXR$C9Qr>-V$;pD($ zX6a;Z#e;Bg2E8#bBoX4^(ZLFC#(;2m?&v0tkYc>*Ar79=&Af~ZS6$%tQjB`)nhf$z zu2u}fJVHEtjM4-Q3=ER4me%4=9w`1b9K1;}+Q8w?;=H^b9v(a%f;>*HFkXH!F)>~~ z0bT(CZqS3<&C?NXhTwK|WBSJ=|31$HD>n;QTW7eflOqFqUNdticeoTIBYL5K{`^Bu zxUKcSR&sRvYg=H0yy#DO`FZ$w|2a1pDv53tmv?e-cC~VI1M^D@OJ4Q-Pi_BN=O6tw zZJgjvKnt$67AlT#D_1ZWZibdlTHvqI|8tN3I+up4trghy)oA{|M*qjQzxqq^qBs5@ z6!8x&U$p`?OA|=){`1JB3CiXLCNVJB3{)P-X(J%NGd#;~wT*`uzYXQ$LEhKQ%|<@X zEw6bd)Gi#LIN_n7PEIHn`H;cDV2)xQs$QsFn^a#D{KiGDt(-6M8HtM=&Rj5I06`~9 z=V7bLl0Wm%#! zBJ>3KNk}M(V!M~m4?=bWKGf>MAj2*m|G<6?&TCugcyVz6V^o~L``x(e40XUT=9-9q&y=?T{4C=2=$z93wh~$dwPd z@i39A&_2)qVYb*cpMw!yj|rEKv*W#oluJ#goApUXu3c-zAN`JIL!7E7U&KiLp|VOH z3V*ZSz9e-xA-JfzXPVI$Y9$&h2HV4^ zcpqw)Qq}oi#a?h%PwcMdXC+qGbjd2_)da6~L z{C0;Zjo*2uIhgR3r#4Zi`Gl$G;;mi5t%kivBbn-^4G4Y<@zNf)Ett&dxJ$?Fv2v>( zd?JakoC7s}*!GL)qlk_q&h zWa1U3B{FVFb`r|P$djm^<$rPPz4gUoE{t{XS+w|C!O$a#5?EhmLhX-IdAb9#w)5rdJMvJTl+l5vi-V7DODM5FKP)`Pt&;rD=IPIw_VZ=9^~z?-zTJ>GUWh*)bzyt*L5a?DVaj`J(maCuN6d30--D6k zZfJf`W$M9$^W6r|y~guDzkWG2`2rjH1s_uX*s!abYX3xV)Y!xLCq~xhWc`?!$4Y+= zuv7bncsYz;3mo%O2@daUBykyxiKX`YYnL;7?kx>I0c zlf+{@mpic_wbM#gdHi|IL}F?@IVw0eJ$%P!%qA=L^Ta5v8;XDbBGlXhMOYRI?bqy2 zIWWHine^4RSsN~VckhR_rrNhTdy)fWq|f1`hbiuZ{TT9R?`VZ<0&j?i8Z86&{Psl* zHgHRTO?nR{IF5E%;U9o12TGWwtar`~A;18M0Fmohzw(zK4?(A-qSZdu) z-gjPsY$F8JLXW{}7#WPIuIsncM(Nhq6Pi3Ml3`q_7Vkn~iZK{%gYnH1%CGOo!AN<0 zvi?!Y{`I_9N`|reDC?!CbpC?k+Or68^E{71Bu;S$fGM? z(cq9MJR0ESHmGDvyFt;;5lrdRdvE^wlUQ{l%3%yL?3tqCQghPeuA<%X0Nh8ygB(57J$EM)>c}Uo{)d7dIR0tp^-+BOlJ7#z3tjOy6>tLwE>@yn z{$3&PZYBKW*?I@MGSVO0Vw#$8`gA+?D@lcU=sDPI*4$!|g-mH=6^IpQxdr9(p88GdA>rk50o^%CI2$ zMf${#ZB}-TUv)E7jCEwyQv`x?q%Py|o^_G6AY*L4fi!_?;Qw;wdpH^Lc_FlhXc`3j zTKUv_E{yqn!bu-HLhX7bD{!4<4pD-AuT5CHQ75fgx84g0t_KAtkZnt6r+4}Psk9jg zpv9MQm2D3sCz+&|lHPj;cX%9-W(c9kdK{UD7!c!HWA$jg4^3R$LEU)B48pb!g=3Ow z;8P(<2h&CwlLS-00v7M>*mPnU;^s=cxc+>NtVxgQ+Yb>G*P3eh&C}}XN&7#vSbt`V zc#mu@(qU1)7u0|~6ueWZs&2IXwva@2s|$z!ZhL;^{c?GAQ#u2KoL^5_%8DxPx`*x= z-emUd+}Ojv{;;H$_}RGdF|EKw08< z)uL_h|Ly?VmCFVR@_wgOkl8(^^-(ey~sNla!rQ3Pl}1t z?PT_SkltyII64?JWuh72@>&h!oLJ%x6luE^r(y*oqmkth(NwW|+)kvVhN<#Z`wa#c6bXX33I|ddK{xhSD_R`$LxPp9lf}4q7r8b^LZ1?lYJv^P=<5; zwyM2zJp_~579&AHj48uO5oN>Bop4)#vXayhey--%9@M#4@x3M)_v^P66h;yu1`a|y zT*D{v3Y3+r$PyJW^L!wmducX!o71PaI1VbMgho%?06isWveq{3wA1X#YjZi2F8K7J z5z}iTfSB&OFfeJyo5BlPb*>sUWguC^1zAx_XcR`CfjopL#FSmA%-~^u=;~s>Hfp+E zSi7TNmLtYc0QoLAB7XNZH>SF&sRr?neN~RY7J-KDNBbYzN%$y-sZT1<^fc;Q4YYAwG*A5^aRK809 zJvv+^+uGhQB22K@WN~gM(STc~&#u4RN|z{$xRWBZMSotbc(E7$u)z*?hNdyrui7IUkb~mh@ZjJC2ov zG<0LV;}* z;6HY)_W-y(6$oOT@s)inzXAR*{o?X-UmeT?*5)z-Af*g|MCKj_nZ9A$&pKM(^I@u4sR~HkLu$^90B}Lwb2#n4voVE zlmaI-=P5s8dj>$&On-SdNm+jh_cbB^i?dp{27cl^yo84(fQ5VT2kn&M#vy1h`%VJ<7IL-ie zHUZ#lC&52Pe2on!`w_7rCBq zzzoWr%${N<3`9H!Nc8e#tjTXTK5N@aQGNJ>>NNzt=G78>*m_v)YDmtn1k}!3SOnCg zb&st4-(>g_t_u*YZjD#Ks-31UdU%_jkChrL`{B(NLrD~qb-#OMk02SKZy#C5fHT=> zdk}F&iz1MHp-&?!$GXH`E+KkLF_|a$o^JEqhCOvIS-O`O0K4U;-Y7=(-Y_5fnn%N) zlM5pLk>KRxu#5IY+O+3#Mj=gnWeeG(dv{jZ-}Ffw6Bv~)u`dM_sr<560e;X)0S?M= zryq*;$PrNQ)Q+zji$g~WwC7aK;c4y{j>A#LKog`xF*;!@EG6OAj)0qrNP|s z@e6PiM=!JU9wsHG3OW3&TraKP{7})`vdeGLzWw6mU@rCalJ7mfj?SI=j*8Y7?UB^f zqBY`6g%Ec!*gM~ay!?WQzNX8E&z4XrXKMmYpR`W2Ax-t;K*RbK)={)#y8uJfuN4(P z5?_6HnHigN*>tj2EU{S=Sgo80y#)4R;@Wk$L16~q=xN9L-*ny^{N0wFD+wt9-@P|$ zm%CMQJSJeRrqir|~Ne{naV9btBW=?SDx zCAJ#0E@XKFR{*G$J{Z?KtXkj6*i)Y&a1^8~|3D&pSr5PA=oCGA$4nqn=yW;zor}i{ItJi zSl`8x7D>e)u1LK)v+7Tbuw93$@!-wKJHK*5=(=N8dNU-FmfXjTJ=$PAMm4W{qaTxcD{uWp z`8=0q>N$1D5pEn}(kjXL z2XO&lN#9tDxO*-YjcMjWXs7&6f7b(7c%SCzwV0qgXZxfAggy8MF+E42+a?~pPqUhA zL;MX&7b{ppet8smR0o}TM?UZg_eg4S_zJLo=vE}^{nJ)&j$g_Hi0jGHz9;g;QgC34 zgO0ZCfT~lARj&kZd?S|eSud&P5G-$or4ZV&)#NJ0NFRsv0hd?0ad@`ZC$pUHw(|2R z)47Q@hP~!948JQhu#QUJMO2-PIji}|ck9ccH3JIq%JRlHwmNNb{JOT_(z&u4a+jb*ntczooljYfgr^GOQ42?!1lClvy98DZ0k) z2MBXTJlS!=aq-7S=-1rCceo}p5fqpuXW@(9ZyU3H{0|OiSX7&r-$w8-zFE|d4OhoB zSRXBUsIjc^B5_lH^~JaB)V?DgS?Clzdz4sM2!~&0J5jtsxZ1cIcuFd zl|?Z{wTH=-iz`G9xBjB1EbBpkD^=Wm?IG`%R*`X1D1|AOIQ+tAAy%m~o{wQp2Z;&N z!HeOUm5wg=xQ>{qmXl^I;(nP-&!v>~UEuagSZf7KN7H`iC$XH$dHJF1&r$722-ckW z#1>%t>t`y`uO4qx7(VBBnQL9K`DpTGg^c=Q-ax1hW`%z-<+WZy{_J!_*EDaPOTEE$ zXh@kz`BQO}uk9Ib-373u2a73xn8(#+^{M1v6zn8?sAQHNb*b>tu;3`vdN1DIL78W^ zowxGilZE8PeAAP6Mu_Z0cgjL69O*K@6(t5Y($C2h6OM2yTDNRJiqBAQ09>m>`AJ5kZ4IGi)l4W;w4Ozj zaH@@1e!ioRtwl77lQQ#tnsG7|5XAc`e-T8QJeS(vQKMdh$_s?DKW`E}yQjg#(xaiU zz(_53#SZ5$TtFSc5=s4=RjG@WM+=sl;uS8gtG}8B2>2bVn$w&lUT(FlXpGkkjN=E@ zP3KWN0;M=M;i+n={1KXH@+eqLy9G1%4AOtrp5v2Rm>>Fas*`B5ke`m| zS*<0U!2VUusu>iCb02ls&PyG$NyYY!eS+gLOWlDPas1s{L|kawR#fZY8*>T3e1Qk| zDKo}VJJJ?LWvCa%yA@kV2Hvr5(?i5>Mi~Qg%Q%afwON<#6Ka@pEqp}%E7sqBIS}kplLl*7HqrJmdS}VQ6 zT?L_26$6SivA1$^{g+Z;RG)Tv3H|gS3g!4x@-$OEd+O~+$sK{Y+ChwQIQQ>Sv&KQ@ z$#taSv~3a4GBX;27yF`3$3(dVPXa#d2eHO5^;;iVPOEP&^Cj<#dp?egk>OOcwVuAs z9SI;3Np3;?S6;T)XJ$dy&l#{p2ebE&P=Wl*)FoR>I>QEDeLfnIQXOH>pWezBb=%^SF)I5Ap<4Re%T+ zpCcmDEhiSW|C-QTHB!TNqw|KswdTPL$K}vwf9p$EOBc5^)iK4mkayfM&1H|$FCuby z*l(iwr#?>KD`%lfSP82J){bwq?vMqIyoF92pq~zz>E7n zlczeYwT+Tv>f`36(AZ0)w?omfNFw?nL~PtBNg5gUKs7}zXOzR+=p8t%IY|cT_qR!z zH7&nc3~E}$hbB|r24!1(W~|`4P96u2{Dil!o|!W_vjnv`9Mu;}y?Xjo zPWg!_W6v#t(V>1VAzSK0uInXOunnCdewx{yTcA;hH{uU}@`iciB4{ zO|hN>;>Qt&MV+&o592KCbVDP|;Wx-WykYVtO7wNSrWR%?Q3?Bnow4NULuk3vod~0f zvd|lvTq?>xo$qn3vVYfZ#0;)wnO39H`k+IkeAD_xakn3FnlB+|gk$M>_vf92HqPb> z6b=p*+!%eAu}u$dCcnP1&{C6Cs*-0?J5Hj-hxSy)q;{)v~EcYrDOipv^LYI@ky2erE;|iL=lc1}*W( z!{$?@*T9)G(j(UK^N3EvD;|#aw9xlzDNjxW-Ue%Y{5@bqV`>QZY^Xbgct)m*z%pb( zSyk1PZwwS=8}KnK-5h*I4Hf@vXknF8l5uljzq}(KTxmB#po=I5#c27xMXl1PKFYOJ zLwlZrr8}K@kfi_}Xw`p57~}z9;_$v zLXhrYHdDjG!Ztfu^&Rh>`(#v-2)-@v*=b3y6#Mx-{01G7G{T}=$3`ZieqJ{H*>a-O zK7!H@4PR{?JSmv`8y@qj`t zy)&$-11-*XMsoVmk;jWrd7(*z_->1p*)_{7Q0N$sc^u5OznXI$M_!BhH7?*nMB#Tv zW{2eOC>WYXXfzvX?pUOkhDb}j0n{p9)&b4%3@?uB>okb3N(?Vgz&AAxDt45muzkD= z==e4hWiRlP3A;^Ec8;Gkh({!`q3Fs%0mL@8k`7I=j+vhEu=(>3nWJB9Z)#!xd^(e~__W-Bhub3W%8Svsrgiys zmVOZ%0mE3m0LVLrR?HRL%ZN@m%L7n&dDJ1(nGztW^p7+>U;wCtno29aZfYwR>Nk7Q$N#c#Ugy+7Iz0$!TTTMnN zsMX*n1)(o4$-@CFEpT3oLK} z6dpN8x;PV>;9jl8Lx?UDv5|vtEfZ=78rQg8W|4Osf1qmPq+k zPYaqU6DY_Mv1#9PS44*tMi2o1wSt{&PD`O6x)UilchcGNGPHR2!85_FM;TXzsQ>*Q wvT>Qw#tg&=0)?x;xA6BV{B1~RU)c7S?TlBsoMgvCe_2#T;n9QA`_BUY4GP}qBme*a literal 0 HcmV?d00001 diff --git a/Skip-List/Images/Insert9.png b/Skip-List/Images/Insert9.png new file mode 100644 index 0000000000000000000000000000000000000000..f63345bddae66b57ba90cc6e9a19253709930528 GIT binary patch literal 11692 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

<7D6cDRzo58 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 xg_{s$bDFVX-2 literal 0 HcmV?d00001 diff --git a/Skip-List/Images/insert7.png b/Skip-List/Images/insert7.png new file mode 100644 index 0000000000000000000000000000000000000000..d92f607f73a5e7acf3dc5d04bc1c88e70adbd08b GIT binary patch literal 11052 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 Lp->`c5%_-qSsc3D literal 0 HcmV?d00001 From 1a880aad0336b13a46c987bd15bdb6257c09d681 Mon Sep 17 00:00:00 2001 From: Mike Date: Fri, 2 Sep 2016 18:38:55 +0200 Subject: [PATCH 0507/1679] Update README.md --- Skip-List/README.md | 40 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/Skip-List/README.md b/Skip-List/README.md index f65609fb2..64f221a23 100644 --- a/Skip-List/README.md +++ b/Skip-List/README.md @@ -4,5 +4,41 @@ Skip List is a probablistic data-structure with same efficiency as AVL tree or R ![Schematic view](Images/Intro.png ) -#TODO - - finish readme + + +#Inserting + +1. Inserting a new element in initial state where no prior layer is created yet begins by construction of a Head node with a reference to data node (just like regular lists). After this operation coin-flipping starts to determine wether a new layer must be created. When positive, a new layer containing Head and data node ( similar to previous layer ) is created and head is updated to reference the new layer and the head node underneath. Subsequently data node is also updated to reference the node below; until coin-flip function return a negative value to terminate this process. + +2. After initial state, we start at top most layer to find a node where its value is less than the new value and its next node value is greater-equal/nil than new value. Then we use this node to travel to layer underneath until we reach the layer 0 where the element must be inserted first, after this node. Node references must be updated accordingly by back tracing the path to the top. If the first element in the layer does not meet the criteria, same procedure is used to travel to the layer below using the head node. + + +**Example** + + +1 - Inserting 10 in initial state with coin flips (0) + +![Inserting first element](Images/Insert1.png) + + +2 - 12 inserted with coin flips (1,1,0) + + +3 - Inserting 13. with coin flips (0) + +![Inserting first element](Images/Insert5.png) +![Inserting first element](Images/Insert6.png) +![Inserting first element](Images/insert7.png) +![Inserting first element](Images/Insert8.png) +![Inserting first element](Images/Insert9.png) + + +#Searching + +TODO + +#See also + +[Skip List on Wikipedia](https://en.wikipedia.org/wiki/Skip_list) + +Written for Swift Algorithm Club by [Mike Taghavi](https://github.com/mitghi) From c8cfb08c8a6165a9c887d0c424de49ca66685ce4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viktor=20Simk=C3=B3?= Date: Sat, 3 Sep 2016 16:20:47 +0200 Subject: [PATCH 0508/1679] updated playground --- B-Tree/BTree.playground/Contents.swift | 14 +- B-Tree/BTree.playground/Sources/BTree.swift | 419 +++++++++++++------- 2 files changed, 276 insertions(+), 157 deletions(-) diff --git a/B-Tree/BTree.playground/Contents.swift b/B-Tree/BTree.playground/Contents.swift index 186718bbd..8238fe5a5 100644 --- a/B-Tree/BTree.playground/Contents.swift +++ b/B-Tree/BTree.playground/Contents.swift @@ -4,15 +4,15 @@ import Foundation let bTree = BTree(order: 1)! -bTree.insertValue(1, forKey: 1) -bTree.insertValue(2, forKey: 2) -bTree.insertValue(3, forKey: 3) -bTree.insertValue(4, forKey: 4) +bTree.insert(1, for: 1) +bTree.insert(2, for: 2) +bTree.insert(3, for: 3) +bTree.insert(4, for: 4) -bTree.valueForKey(3) +bTree.value(for: 3) bTree[3] -bTree.removeKey(2) +bTree.remove(2) bTree.traverseKeysInOrder { key in @@ -23,4 +23,4 @@ bTree.numberOfKeys bTree.order -bTree.inorderArrayFromKeys() \ No newline at end of file +bTree.inorderArrayFromKeys diff --git a/B-Tree/BTree.playground/Sources/BTree.swift b/B-Tree/BTree.playground/Sources/BTree.swift index 16c4eabe4..52cda4e43 100644 --- a/B-Tree/BTree.playground/Sources/BTree.swift +++ b/B-Tree/BTree.playground/Sources/BTree.swift @@ -21,18 +21,21 @@ // SOFTWARE. /* - B-Tree - - A B-Tree is a self-balancing search tree, in which nodes can have more than two children. + * B-Tree + * + * A B-Tree is a self-balancing search tree, in which nodes can have more than two children. */ // MARK: - BTreeNode class class BTreeNode { - unowned var ownerTree: BTree + /** + * The tree that owns the node. + */ + unowned var owner: BTree - private var keys = [Key]() - var values = [Value]() + fileprivate var keys = [Key]() + fileprivate var values = [Value]() var children: [BTreeNode]? var isLeaf: Bool { @@ -43,13 +46,13 @@ class BTreeNode { return keys.count } - init(ownerTree: BTree) { - self.ownerTree = ownerTree + init(owner: BTree) { + self.owner = owner } - convenience init(ownerTree: BTree, keys: [Key], + convenience init(owner: BTree, keys: [Key], values: [Value], children: [BTreeNode]? = nil) { - self.init(ownerTree: ownerTree) + self.init(owner: owner) self.keys += keys self.values += values self.children = children @@ -59,19 +62,26 @@ class BTreeNode { // MARK: BTreeNode extesnion: Searching extension BTreeNode { - func valueForKey(key: Key) -> Value? { + + /** + * Returns the value for a given `key`, returns nil if the `key` is not found. + * + * - Parameters: + * - key: the key of the value to be returned + */ + func value(for key: Key) -> Value? { var index = keys.startIndex - while index.successor() < keys.endIndex && keys[index] < key { - index = index.successor() + while (index + 1) < keys.endIndex && keys[index] < key { + index = (index + 1) } if key == keys[index] { return values[index] } else if key < keys[index] { - return children?[index].valueForKey(key) + return children?[index].value(for: key) } else { - return children?[index.successor()].valueForKey(key) + return children?[(index + 1)].value(for: key) } } } @@ -79,7 +89,14 @@ extension BTreeNode { // MARK: BTreeNode extension: Travelsals extension BTreeNode { - func traverseKeysInOrder(@noescape process: Key -> Void) { + + /** + * Traverses the keys in order, executes `process` for every key. + * + * - Parameters: + * - process: the closure to be executed for every key + */ + func traverseKeysInOrder(_ process: (Key) -> Void) { for i in 0.. ownerTree.order * 2 { - splitChild(children![index], atIndex: index) + children![index].insert(value, for: key) + if children![index].numberOfKeys > owner.order * 2 { + split(child: children![index], atIndex: index) } } } - private func splitChild(child: BTreeNode, atIndex index: Int) { + /** + * Splits `child` at `index`. + * The key-value pair at `index` gets moved up to the parent node, + * or if there is not an parent node, then a new parent node is created. + * + * - Parameters: + * - child: the child to be split + * - index: the index of the key, which will be moved up to the parent + */ + private func split(child: BTreeNode, atIndex index: Int) { let middleIndex = child.numberOfKeys / 2 - keys.insert(child.keys[middleIndex], atIndex: index) - values.insert(child.values[middleIndex], atIndex: index) - child.keys.removeAtIndex(middleIndex) - child.values.removeAtIndex(middleIndex) + keys.insert(child.keys[middleIndex], at: index) + values.insert(child.values[middleIndex], at: index) + child.keys.remove(at: middleIndex) + child.values.remove(at: middleIndex) let rightSibling = BTreeNode( - ownerTree: ownerTree, - keys: Array(child.keys[middleIndex..= 0 && - children![index.predecessor()].numberOfKeys > ownerTree.order { - - moveKeyAtIndex(index.predecessor(), toNode: child, - fromNode: children![index.predecessor()], atPosition: .Left) - - } else if index.successor() < children!.count && - children![index.successor()].numberOfKeys > ownerTree.order { - - moveKeyAtIndex(index, toNode: child, - fromNode: children![index.successor()], atPosition: .Right) - - } else if index.predecessor() >= 0 { - mergeChild(child, withIndex: index, toNodeAtPosition: .Left) + if (index - 1) >= 0 && children![(index - 1)].numberOfKeys > owner.order { + move(keyAtIndex: (index - 1), to: child, from: children![(index - 1)], at: .left) + } else if (index + 1) < children!.count && children![(index + 1)].numberOfKeys > owner.order { + move(keyAtIndex: index, to: child, from: children![(index + 1)], at: .right) + } else if (index - 1) >= 0 { + merge(child: child, atIndex: index, to: .left) } else { - mergeChild(child, withIndex: index, toNodeAtPosition: .Right) + merge(child: child, atIndex: index, to: .right) } } - private func moveKeyAtIndex(keyIndex: Int, toNode targetNode: BTreeNode, - fromNode: BTreeNode, atPosition position: BTreeNodePosition) { + /** + * Moves the key at the specified `index` from `node` to + * the `targetNode` at `position` + * + * - Parameters: + * - index: the index of the key to be moved in `node` + * - targetNode: the node to move the key into + * - node: the node to move the key from + * - position: the position of the from node relative to the targetNode + */ + private func move(keyAtIndex index: Int, to targetNode: BTreeNode, + from node: BTreeNode, at position: BTreeNodePosition) { switch position { - case .Left: - targetNode.keys.insert(keys[keyIndex], atIndex: targetNode.keys.startIndex) - targetNode.values.insert(values[keyIndex], atIndex: targetNode.values.startIndex) - keys[keyIndex] = fromNode.keys.last! - values[keyIndex] = fromNode.values.last! - fromNode.keys.removeLast() - fromNode.values.removeLast() + case .left: + targetNode.keys.insert(keys[index], at: targetNode.keys.startIndex) + targetNode.values.insert(values[index], at: targetNode.values.startIndex) + keys[index] = node.keys.last! + values[index] = node.values.last! + node.keys.removeLast() + node.values.removeLast() if !targetNode.isLeaf { - targetNode.children!.insert(fromNode.children!.last!, - atIndex: targetNode.children!.startIndex) - fromNode.children!.removeLast() + targetNode.children!.insert(node.children!.last!, + at: targetNode.children!.startIndex) + node.children!.removeLast() } - case .Right: - targetNode.keys.insert(keys[keyIndex], atIndex: targetNode.keys.endIndex) - targetNode.values.insert(values[keyIndex], atIndex: targetNode.values.endIndex) - keys[keyIndex] = fromNode.keys.first! - values[keyIndex] = fromNode.values.first! - fromNode.keys.removeFirst() - fromNode.values.removeFirst() + case .right: + targetNode.keys.insert(keys[index], at: targetNode.keys.endIndex) + targetNode.values.insert(values[index], at: targetNode.values.endIndex) + keys[index] = node.keys.first! + values[index] = node.values.first! + node.keys.removeFirst() + node.values.removeFirst() if !targetNode.isLeaf { - targetNode.children!.insert(fromNode.children!.first!, - atIndex: targetNode.children!.endIndex) - fromNode.children!.removeFirst() + targetNode.children!.insert(node.children!.first!, + at: targetNode.children!.endIndex) + node.children!.removeFirst() } } } - private func mergeChild(child: BTreeNode, withIndex index: Int, toNodeAtPosition position: BTreeNodePosition) { + /** + * Merges `child` at `position` to the node at the `position`. + * + * - Parameters: + * - child: the child to be merged + * - index: the index of the child in the current node + * - position: the position of the node to merge into + */ + private func merge(child: BTreeNode, atIndex index: Int, to position: BTreeNodePosition) { switch position { - case .Left: + case .left: // We can merge to the left sibling - children![index.predecessor()].keys = children![index.predecessor()].keys + - [keys[index.predecessor()]] + child.keys + children![(index - 1)].keys = children![(index - 1)].keys + + [keys[(index - 1)]] + child.keys - children![index.predecessor()].values = children![index.predecessor()].values + - [values[index.predecessor()]] + child.values + children![(index - 1)].values = children![(index - 1)].values + + [values[(index - 1)]] + child.values - keys.removeAtIndex(index.predecessor()) - values.removeAtIndex(index.predecessor()) + keys.remove(at: (index - 1)) + values.remove(at: (index - 1)) if !child.isLeaf { - children![index.predecessor()].children = - children![index.predecessor()].children! + child.children! + children![(index - 1)].children = + children![(index - 1)].children! + child.children! } - case .Right: + case .right: // We should merge to the right sibling - children![index.successor()].keys = child.keys + [keys[index]] + - children![index.successor()].keys + children![(index + 1)].keys = child.keys + [keys[index]] + + children![(index + 1)].keys - children![index.successor()].values = child.values + [values[index]] + - children![index.successor()].values + children![(index + 1)].values = child.values + [values[index]] + + children![(index + 1)].values - keys.removeAtIndex(index) - values.removeAtIndex(index) + keys.remove(at: index) + values.remove(at: index) if !child.isLeaf { - children![index.successor()].children = - child.children! + children![index.successor()].children! + children![(index + 1)].children = + child.children! + children![(index + 1)].children! } } - children!.removeAtIndex(index) + children!.remove(at: index) } } // MARK: BTreeNode extension: Conversion extension BTreeNode { - func inorderArrayFromKeys() -> [Key] { + /** + * Returns an array which contains the keys from the current node + * and its descendants in order. + */ + var inorderArrayFromKeys: [Key] { var array = [Key] () for i in 0.. { - /** - The order of the B-Tree - - The number of keys in every node should be in the [order, 2*order] range, - except the root node which is allowed to contain less keys than the value of order. + * The order of the B-Tree + * + * The number of keys in every node should be in the [order, 2*order] range, + * except the root node which is allowed to contain less keys than the value of order. */ public let order: Int - /// The root node of the tree + /** + * The root node of the tree + */ var rootNode: BTreeNode! - private(set) public var numberOfKeys = 0 + fileprivate(set) public var numberOfKeys = 0 /** - Designated initializer for the tree - - - parameters: - - order: The order of the tree. + * Designated initializer for the tree + * + * - Parameters: + * - order: The order of the tree. */ public init?(order: Int) { guard order > 0 else { @@ -362,14 +439,20 @@ public class BTree { return nil } self.order = order - rootNode = BTreeNode(ownerTree: self) + rootNode = BTreeNode(owner: self) } } // MARK: BTree extension: Travelsals extension BTree { - public func traverseKeysInOrder(@noescape process: Key -> Void) { + /** + * Traverses the keys in order, executes `process` for every key. + * + * - Parameters: + * - process: the closure to be executed for every key + */ + public func traverseKeysInOrder(_ process: (Key) -> Void) { rootNode.traverseKeysInOrder(process) } } @@ -377,60 +460,85 @@ extension BTree { // MARK: BTree extension: Subscript extension BTree { + /** + * Returns the value for a given `key`, returns nil if the `key` is not found. + * + * - Parameters: + * - key: the key of the value to be returned + */ public subscript (key: Key) -> Value? { - return valueForKey(key) + return value(for: key) } } // MARK: BTree extension: Value for Key extension BTree { - public func valueForKey(key: Key) -> Value? { + /** + * Returns the value for a given `key`, returns nil if the `key` is not found. + * + * - Parameters: + * - key: the key of the value to be returned + */ + public func value(for key: Key) -> Value? { guard rootNode.numberOfKeys > 0 else { return nil } - return rootNode.valueForKey(key) + return rootNode.value(for: key) } } // MARK: BTree extension: Insertion extension BTree { - public func insertValue(value: Value, forKey key: Key) { - rootNode.insertValue(value, forKey: key) + /** + * Inserts the `value` for the `key` into the tree. + * + * - Parameters: + * - value: the value to be inserted for `key` + * - key: the key for the `value` + */ + public func insert(_ value: Value, for key: Key) { + rootNode.insert(value, for: key) if rootNode.numberOfKeys > order * 2 { splitRoot() } } + /** + * Splits the root node of the tree. + * + * - Precondition: + * The root node of the tree contains `order` * 2 keys. + */ private func splitRoot() { let middleIndexOfOldRoot = rootNode.numberOfKeys / 2 let newRoot = BTreeNode( - ownerTree: self, + owner: self, keys: [rootNode.keys[middleIndexOfOldRoot]], values: [rootNode.values[middleIndexOfOldRoot]], children: [rootNode] ) - rootNode.keys.removeAtIndex(middleIndexOfOldRoot) - rootNode.values.removeAtIndex(middleIndexOfOldRoot) + rootNode.keys.remove(at: middleIndexOfOldRoot) + rootNode.values.remove(at: middleIndexOfOldRoot) let newRightChild = BTreeNode( - ownerTree: self, - keys: Array(rootNode.keys[middleIndexOfOldRoot.. 0 else { return } - rootNode.removeKey(key) + rootNode.remove(key) if rootNode.numberOfKeys == 0 && !rootNode.isLeaf { rootNode = rootNode.children!.first! @@ -458,15 +572,20 @@ extension BTree { // MARK: BTree extension: Conversion extension BTree { - public func inorderArrayFromKeys() -> [Key] { - return rootNode.inorderArrayFromKeys() + /** + * The keys of the tree in order. + */ + public var inorderArrayFromKeys: [Key] { + return rootNode.inorderArrayFromKeys } } // MARK: BTree extension: Decription extension BTree: CustomStringConvertible { - // Returns a String containing the preorder representation of the nodes + /** + * Returns a String containing the preorder representation of the nodes. + */ public var description: String { return rootNode.description } From 9035cddfca64d7814e774ab86dab36259338eea0 Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Tue, 6 Sep 2016 21:24:02 +1200 Subject: [PATCH 0509/1679] Update .travis.yml --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 76799365d..d0f565651 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,7 +13,7 @@ script: - xcodebuild test -project ./AVL\ Tree/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Binary\ Search/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Binary\ Search\ Tree/Solution\ 1/Tests/Tests.xcodeproj -scheme Tests - - xcodebuild test -project ./Bloom\ Filter/Tests/Tests.xcodeproj -scheme Tests +- xcodebuild test -project ./Bloom\ Filter/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Bounded\ Priority\ Queue/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Breadth-First\ Search/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Bucket\ Sort/Tests/Tests.xcodeproj -scheme Tests From 3945383d306ac027f779461789d6b0deddca4348 Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Wed, 7 Sep 2016 05:01:56 -0700 Subject: [PATCH 0510/1679] Migrated over to Swift 3 --- Heap/Heap.swift | 56 +++++++++---------- Heap/README.markdown | 4 +- Heap/Tests/HeapTests.swift | 42 +++++++------- Heap/Tests/Tests.xcodeproj/project.pbxproj | 10 +++- .../xcshareddata/xcschemes/Tests.xcscheme | 2 +- 5 files changed, 61 insertions(+), 53 deletions(-) diff --git a/Heap/Heap.swift b/Heap/Heap.swift index bf7031abe..eba7ca1cf 100644 --- a/Heap/Heap.swift +++ b/Heap/Heap.swift @@ -8,14 +8,14 @@ public struct Heap { var elements = [T]() /** Determines whether this is a max-heap (>) or min-heap (<). */ - private var isOrderedBefore: (T, T) -> Bool + fileprivate var isOrderedBefore: (T, T) -> Bool /** * Creates an empty heap. * The sort function determines whether this is a min-heap or max-heap. * For integers, > makes a max-heap, < makes a min-heap. */ - public init(sort: (T, T) -> Bool) { + public init(sort: @escaping (T, T) -> Bool) { self.isOrderedBefore = sort } @@ -24,9 +24,9 @@ public struct Heap { * the elements are inserted into the heap in the order determined by the * sort function. */ - public init(array: [T], sort: (T, T) -> Bool) { + public init(array: [T], sort: @escaping (T, T) -> Bool) { self.isOrderedBefore = sort - buildHeap(array) + buildHeap(fromArray: array) } /* @@ -43,9 +43,9 @@ public struct Heap { * Converts an array to a max-heap or min-heap in a bottom-up manner. * Performance: This runs pretty much in O(n). */ - private mutating func buildHeap(array: [T]) { + fileprivate mutating func buildHeap(fromArray array: [T]) { elements = array - for i in (elements.count/2 - 1).stride(through: 0, by: -1) { + for i in stride(from: (elements.count/2 - 1), through: 0, by: -1) { shiftDown(index: i, heapSize: elements.count) } } @@ -62,7 +62,7 @@ public struct Heap { * Returns the index of the parent of the element at index i. * The element at index 0 is the root of the tree and has no parent. */ - @inline(__always) func indexOfParent(i: Int) -> Int { + @inline(__always) func parentIndex(ofIndex i: Int) -> Int { return (i - 1) / 2 } @@ -71,7 +71,7 @@ public struct Heap { * Note that this index can be greater than the heap size, in which case * there is no left child. */ - @inline(__always) func indexOfLeftChild(i: Int) -> Int { + @inline(__always) func leftChildIndex(ofIndex i: Int) -> Int { return 2*i + 1 } @@ -80,7 +80,7 @@ public struct Heap { * Note that this index can be greater than the heap size, in which case * there is no right child. */ - @inline(__always) func indexOfRightChild(i: Int) -> Int { + @inline(__always) func rightChildIndex(ofIndex i: Int) -> Int { return 2*i + 2 } @@ -96,12 +96,12 @@ public struct Heap { * Adds a new value to the heap. This reorders the heap so that the max-heap * or min-heap property still holds. Performance: O(log n). */ - public mutating func insert(value: T) { + public mutating func insert(_ value: T) { elements.append(value) shiftUp(index: elements.count - 1) } - public mutating func insert(sequence: S) { + public mutating func insert(_ sequence: S) where S.Iterator.Element == T { for value in sequence { insert(value) } @@ -123,7 +123,7 @@ public struct Heap { * Removes the root node from the heap. For a max-heap, this is the maximum * value; for a min-heap it is the minimum value. Performance: O(log n). */ - public mutating func remove() -> T? { + @discardableResult public mutating func remove() -> T? { if elements.isEmpty { return nil } else if elements.count == 1 { @@ -142,14 +142,14 @@ public struct Heap { * Removes an arbitrary node from the heap. Performance: O(log n). You need * to know the node's index, which may actually take O(n) steps to find. */ - public mutating func removeAtIndex(i: Int) -> T? { - guard i < elements.count else { return nil } + public mutating func removeAt(index: Int) -> T? { + guard index < elements.count else { return nil } let size = elements.count - 1 - if i != size { - swap(&elements[i], &elements[size]) - shiftDown(index: i, heapSize: size) - shiftUp(index: i) + if index != size { + swap(&elements[index], &elements[size]) + shiftDown(index: index, heapSize: size) + shiftUp(index: index) } return elements.removeLast() } @@ -158,15 +158,15 @@ public struct Heap { * Takes a child node and looks at its parents; if a parent is not larger * (max-heap) or not smaller (min-heap) than the child, we exchange them. */ - mutating func shiftUp(index index: Int) { + mutating func shiftUp(index: Int) { var childIndex = index let child = elements[childIndex] - var parentIndex = indexOfParent(childIndex) + var parentIndex = self.parentIndex(ofIndex: childIndex) while childIndex > 0 && isOrderedBefore(child, elements[parentIndex]) { elements[childIndex] = elements[parentIndex] childIndex = parentIndex - parentIndex = indexOfParent(childIndex) + parentIndex = self.parentIndex(ofIndex: childIndex) } elements[childIndex] = child @@ -180,11 +180,11 @@ public struct Heap { * Looks at a parent node and makes sure it is still larger (max-heap) or * smaller (min-heap) than its childeren. */ - mutating func shiftDown(index index: Int, heapSize: Int) { + mutating func shiftDown(index: Int, heapSize: Int) { var parentIndex = index while true { - let leftChildIndex = indexOfLeftChild(parentIndex) + let leftChildIndex = self.leftChildIndex(ofIndex: parentIndex) let rightChildIndex = leftChildIndex + 1 // Figure out which comes first if we order them by the sort function: @@ -212,16 +212,16 @@ extension Heap where T: Equatable { /** * Searches the heap for the given element. Performance: O(n). */ - public func indexOf(element: T) -> Int? { - return indexOf(element, 0) + public func index(of element: T) -> Int? { + return index(of: element, 0) } - private func indexOf(element: T, _ i: Int) -> Int? { + fileprivate func index(of element: T, _ i: Int) -> Int? { if i >= count { return nil } if isOrderedBefore(element, elements[i]) { return nil } if element == elements[i] { return i } - if let j = indexOf(element, indexOfLeftChild(i)) { return j } - if let j = indexOf(element, indexOfRightChild(i)) { return j } + if let j = index(of: element, self.leftChildIndex(ofIndex: i)) { return j } + if let j = index(of: element, self.rightChildIndex(ofIndex: i)) { return j } return nil } } diff --git a/Heap/README.markdown b/Heap/README.markdown index fb5092fe3..88ea25eeb 100644 --- a/Heap/README.markdown +++ b/Heap/README.markdown @@ -260,7 +260,7 @@ It can be convenient to convert an array into a heap. This just shuffles the arr In code it would look like this: ```swift - private mutating func buildHeap(array: [T]) { + private mutating func buildHeap(fromArray array: [T]) { for value in array { insert(value) } @@ -274,7 +274,7 @@ If you didn't gloss over the math section, you'd have seen that for any heap the In code: ```swift - private mutating func buildHeap(array: [T]) { + private mutating func buildHeap(fromArray array: [T]) { elements = array for i in (elements.count/2 - 1).stride(through: 0, by: -1) { shiftDown(index: i, heapSize: elements.count) diff --git a/Heap/Tests/HeapTests.swift b/Heap/Tests/HeapTests.swift index 6178a8094..c5b479f14 100644 --- a/Heap/Tests/HeapTests.swift +++ b/Heap/Tests/HeapTests.swift @@ -7,11 +7,11 @@ import XCTest class HeapTests: XCTestCase { - private func verifyMaxHeap(h: Heap) -> Bool { + fileprivate func verifyMaxHeap(_ h: Heap) -> Bool { for i in 0.. 0 && h.elements[parent] < h.elements[i] { return false } @@ -19,11 +19,11 @@ class HeapTests: XCTestCase { return true } - private func verifyMinHeap(h: Heap) -> Bool { + fileprivate func verifyMinHeap(_ h: Heap) -> Bool { for i in 0.. h.elements[left] { return false } if right < h.count && h.elements[i] > h.elements[right] { return false } if i > 0 && h.elements[parent] > h.elements[i] { return false } @@ -31,14 +31,14 @@ class HeapTests: XCTestCase { return true } - private func isPermutation(array1: [Int], _ array2: [Int]) -> Bool { + fileprivate func isPermutation(_ array1: [Int], _ array2: [Int]) -> Bool { var a1 = array1 var a2 = array2 if a1.count != a2.count { return false } while a1.count > 0 { - if let i = a2.indexOf(a1[0]) { - a1.removeAtIndex(0) - a2.removeAtIndex(i) + if let i = a2.index(of: a1[0]) { + a1.remove(at: 0) + a2.remove(at: i) } else { return false } @@ -161,7 +161,7 @@ class HeapTests: XCTestCase { XCTAssertEqual(heap.elements, [1, 1, 1, 1, 1]) } - private func randomArray(n: Int) -> [Int] { + fileprivate func randomArray(_ n: Int) -> [Int] { var a = [Int]() for _ in 0.. Date: Thu, 8 Sep 2016 07:55:54 -0700 Subject: [PATCH 0511/1679] Updated playground to Swift 3 --- .../Contents.swift | 30 +++++----- .../Sources/BinarySearchTree.swift | 56 +++++++++---------- 2 files changed, 43 insertions(+), 43 deletions(-) diff --git a/Binary Search Tree/Solution 1/BinarySearchTree.playground/Contents.swift b/Binary Search Tree/Solution 1/BinarySearchTree.playground/Contents.swift index 4c2a6c358..6d73585b5 100644 --- a/Binary Search Tree/Solution 1/BinarySearchTree.playground/Contents.swift +++ b/Binary Search Tree/Solution 1/BinarySearchTree.playground/Contents.swift @@ -1,21 +1,21 @@ //: Playground - noun: a place where people can play let tree = BinarySearchTree(value: 7) -tree.insert(2) -tree.insert(5) -tree.insert(10) -tree.insert(9) -tree.insert(1) +tree.insert(value: 2) +tree.insert(value: 5) +tree.insert(value: 10) +tree.insert(value: 9) +tree.insert(value: 1) tree tree.debugDescription let tree2 = BinarySearchTree(array: [7, 2, 5, 10, 9, 1]) -tree.search(5) -tree.search(2) -tree.search(7) -tree.search(6) +tree.search(value: 5) +tree.search(value: 2) +tree.search(value: 7) +tree.search(value: 6) tree.traverseInOrder { value in print(value) } @@ -24,7 +24,7 @@ tree.toArray() tree.minimum() tree.maximum() -if let node2 = tree.search(2) { +if let node2 = tree.search(value: 2) { node2.remove() node2 print(tree) @@ -34,25 +34,25 @@ tree.height() tree.predecessor() tree.successor() -if let node10 = tree.search(10) { +if let node10 = tree.search(value: 10) { node10.depth() // 1 node10.height() // 1 node10.predecessor() node10.successor() // nil } -if let node9 = tree.search(9) { +if let node9 = tree.search(value: 9) { node9.depth() // 2 node9.height() // 0 node9.predecessor() node9.successor() } -if let node1 = tree.search(1) { +if let node1 = tree.search(value: 1) { // This makes it an invalid binary search tree because 100 is greater // than the root, 7, and so must be in the right branch not in the left. tree.isBST(minValue: Int.min, maxValue: Int.max) // true - node1.insert(100) - tree.search(100) // nil + node1.insert(value: 100) + tree.search(value: 100) // nil tree.isBST(minValue: Int.min, maxValue: Int.max) // false } diff --git a/Binary Search Tree/Solution 1/BinarySearchTree.playground/Sources/BinarySearchTree.swift b/Binary Search Tree/Solution 1/BinarySearchTree.playground/Sources/BinarySearchTree.swift index a58ac075a..f4960380e 100644 --- a/Binary Search Tree/Solution 1/BinarySearchTree.playground/Sources/BinarySearchTree.swift +++ b/Binary Search Tree/Solution 1/BinarySearchTree.playground/Sources/BinarySearchTree.swift @@ -10,10 +10,10 @@ you should insert new values in randomized order, not in sorted order. */ public class BinarySearchTree { - private(set) public var value: T - private(set) public var parent: BinarySearchTree? - private(set) public var left: BinarySearchTree? - private(set) public var right: BinarySearchTree? + fileprivate(set) public var value: T + fileprivate(set) public var parent: BinarySearchTree? + fileprivate(set) public var left: BinarySearchTree? + fileprivate(set) public var right: BinarySearchTree? public init(value: T) { self.value = value @@ -22,8 +22,8 @@ public class BinarySearchTree { public convenience init(array: [T]) { precondition(array.count > 0) self.init(value: array.first!) - for v in array.dropFirst() { - insert(v, parent: self) + for v in array.dropFirst() { + insert(value: v, parent: self) } } @@ -74,20 +74,20 @@ extension BinarySearchTree { Performance: runs in O(h) time, where h is the height of the tree. */ public func insert(value: T) { - insert(value, parent: self) + insert(value: value, parent: self) } - private func insert(value: T, parent: BinarySearchTree) { + fileprivate func insert(value: T, parent: BinarySearchTree) { if value < self.value { if let left = left { - left.insert(value, parent: left) + left.insert(value: value, parent: left) } else { left = BinarySearchTree(value: value) left?.parent = parent } } else { if let right = right { - right.insert(value, parent: right) + right.insert(value: value, parent: right) } else { right = BinarySearchTree(value: value) right?.parent = parent @@ -108,7 +108,7 @@ extension BinarySearchTree { Performance: runs in O(h) time, where h is the height of the tree. */ - public func remove() -> BinarySearchTree? { + @discardableResult public func remove() -> BinarySearchTree? { let replacement: BinarySearchTree? if let left = left { @@ -126,7 +126,7 @@ extension BinarySearchTree { replacement = nil } - reconnectParentToNode(replacement) + reconnectParentTo(node: replacement) // The current node is no longer part of the tree, so clean it up. parent = nil @@ -136,7 +136,7 @@ extension BinarySearchTree { return replacement } - private func removeNodeWithTwoChildren(left: BinarySearchTree, _ right: BinarySearchTree) -> BinarySearchTree { + private func removeNodeWithTwoChildren(_ left: BinarySearchTree, _ right: BinarySearchTree) -> BinarySearchTree { // This node has two children. It must be replaced by the smallest // child that is larger than this node's value, which is the leftmost // descendent of the right child. @@ -164,7 +164,7 @@ extension BinarySearchTree { return successor } - private func reconnectParentToNode(node: BinarySearchTree?) { + private func reconnectParentTo(node: BinarySearchTree?) { if let parent = parent { if isLeftChild { parent.left = node @@ -211,7 +211,7 @@ extension BinarySearchTree { */ public func contains(value: T) -> Bool { - return search(value) != nil + return search(value: value) != nil } /* @@ -298,32 +298,32 @@ extension BinarySearchTree { // MARK: - Traversal extension BinarySearchTree { - public func traverseInOrder(@noescape process: T -> Void) { - left?.traverseInOrder(process) + public func traverseInOrder(process: (T) -> Void) { + left?.traverseInOrder(process: process) process(value) - right?.traverseInOrder(process) + right?.traverseInOrder(process: process) } - public func traversePreOrder(@noescape process: T -> Void) { + public func traversePreOrder(process: (T) -> Void) { process(value) - left?.traversePreOrder(process) - right?.traversePreOrder(process) + left?.traversePreOrder(process: process) + right?.traversePreOrder(process: process) } - public func traversePostOrder(@noescape process: T -> Void) { - left?.traversePostOrder(process) - right?.traversePostOrder(process) + public func traversePostOrder(process: (T) -> Void) { + left?.traversePostOrder(process: process) + right?.traversePostOrder(process: process) process(value) } /* Performs an in-order traversal and collects the results in an array. */ - public func map(@noescape formula: T -> T) -> [T] { + public func map(formula: (T) -> T) -> [T] { var a = [T]() - if let left = left { a += left.map(formula) } + if let left = left { a += left.map(formula: formula) } a.append(formula(value)) - if let right = right { a += right.map(formula) } + if let right = right { a += right.map(formula: formula) } return a } } @@ -332,7 +332,7 @@ extension BinarySearchTree { Is this binary tree a valid binary search tree? */ extension BinarySearchTree { - public func isBST(minValue minValue: T, maxValue: T) -> Bool { + public func isBST(minValue: T, maxValue: T) -> Bool { if value < minValue || value > maxValue { return false } let leftBST = left?.isBST(minValue: minValue, maxValue: value) ?? true let rightBST = right?.isBST(minValue: value, maxValue: maxValue) ?? true From b502621861aa6bef64ba755736a0de3f509985fc Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Thu, 8 Sep 2016 07:59:12 -0700 Subject: [PATCH 0512/1679] Migration to Swift 3 --- .../BinarySearchTree.playground/Contents.swift | 18 ++++++++++-------- .../Sources/BinarySearchTree.swift | 10 +++++----- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/Binary Search Tree/Solution 2/BinarySearchTree.playground/Contents.swift b/Binary Search Tree/Solution 2/BinarySearchTree.playground/Contents.swift index 217cb489e..12fbba81d 100644 --- a/Binary Search Tree/Solution 2/BinarySearchTree.playground/Contents.swift +++ b/Binary Search Tree/Solution 2/BinarySearchTree.playground/Contents.swift @@ -2,13 +2,15 @@ // Each time you insert something, you get back a completely new tree. var tree = BinarySearchTree.Leaf(7) -tree = tree.insert(2) -tree = tree.insert(5) -tree = tree.insert(10) -tree = tree.insert(9) -tree = tree.insert(1) +tree = tree.insert(newValue: 2) +tree = tree.insert(newValue: 5) +tree = tree.insert(newValue: 10) +tree = tree.insert(newValue: 9) +tree = tree.insert(newValue: 1) print(tree) -tree.search(10) -tree.search(1) -tree.search(11) +tree.search(x: 10) +tree.search(x: 1) +tree.search(x: 11) + + diff --git a/Binary Search Tree/Solution 2/BinarySearchTree.playground/Sources/BinarySearchTree.swift b/Binary Search Tree/Solution 2/BinarySearchTree.playground/Sources/BinarySearchTree.swift index ce2868bbf..b692efdc4 100644 --- a/Binary Search Tree/Solution 2/BinarySearchTree.playground/Sources/BinarySearchTree.swift +++ b/Binary Search Tree/Solution 2/BinarySearchTree.playground/Sources/BinarySearchTree.swift @@ -44,9 +44,9 @@ public enum BinarySearchTree { case .Node(let left, let value, let right): if newValue < value { - return .Node(left.insert(newValue), value, right) + return .Node(left.insert(newValue: newValue), value, right) } else { - return .Node(left, value, right.insert(newValue)) + return .Node(left, value, right.insert(newValue: newValue)) } } } @@ -63,9 +63,9 @@ public enum BinarySearchTree { return (x == y) ? self : nil case let .Node(left, y, right): if x < y { - return left.search(x) + return left.search(x: x) } else if y < x { - return right.search(x) + return right.search(x: x) } else { return self } @@ -73,7 +73,7 @@ public enum BinarySearchTree { } public func contains(x: T) -> Bool { - return search(x) != nil + return search(x: x) != nil } /* From b88fb4d7bb422e81981b6ddfaef52a2f07fe649b Mon Sep 17 00:00:00 2001 From: Nemanja Vlahovic Date: Sat, 10 Sep 2016 19:22:35 +0200 Subject: [PATCH 0513/1679] Update Selection Sort to Swift 3 --- Selection Sort/README.markdown | 2 +- Selection Sort/SelectionSort.playground/Contents.swift | 2 +- Selection Sort/SelectionSort.swift | 2 +- Selection Sort/Tests/Tests.xcodeproj/project.pbxproj | 10 +++++++++- .../xcshareddata/xcschemes/Tests.xcscheme | 2 +- 5 files changed, 13 insertions(+), 5 deletions(-) diff --git a/Selection Sort/README.markdown b/Selection Sort/README.markdown index 6eb019ab1..c583b47ea 100644 --- a/Selection Sort/README.markdown +++ b/Selection Sort/README.markdown @@ -59,7 +59,7 @@ As you can see, selection sort is an *in-place* sort because everything happens Here is an implementation of selection sort in Swift: ```swift -func selectionSort(array: [Int]) -> [Int] { +func selectionSort(_ array: [Int]) -> [Int] { guard array.count > 1 else { return array } // 1 var a = array // 2 diff --git a/Selection Sort/SelectionSort.playground/Contents.swift b/Selection Sort/SelectionSort.playground/Contents.swift index dd57e9c3a..bd8c7cccf 100644 --- a/Selection Sort/SelectionSort.playground/Contents.swift +++ b/Selection Sort/SelectionSort.playground/Contents.swift @@ -1,6 +1,6 @@ //: Playground - noun: a place where people can play -func selectionSort(array: [T], _ isOrderedBefore: (T, T) -> Bool) -> [T] { +func selectionSort(_ array: [T], _ isOrderedBefore: (T, T) -> Bool) -> [T] { guard array.count > 1 else { return array } var a = array for x in 0 ..< a.count - 1 { diff --git a/Selection Sort/SelectionSort.swift b/Selection Sort/SelectionSort.swift index 9d7b45ad8..e02c87259 100644 --- a/Selection Sort/SelectionSort.swift +++ b/Selection Sort/SelectionSort.swift @@ -1,4 +1,4 @@ -func selectionSort(array: [T], _ isOrderedBefore: (T, T) -> Bool) -> [T] { +func selectionSort(_ array: [T], _ isOrderedBefore: (T, T) -> Bool) -> [T] { guard array.count > 1 else { return array } var a = array diff --git a/Selection Sort/Tests/Tests.xcodeproj/project.pbxproj b/Selection Sort/Tests/Tests.xcodeproj/project.pbxproj index 11aefac3c..a42f3dc3f 100644 --- a/Selection Sort/Tests/Tests.xcodeproj/project.pbxproj +++ b/Selection Sort/Tests/Tests.xcodeproj/project.pbxproj @@ -86,11 +86,12 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; - LastUpgradeCheck = 0720; + LastUpgradeCheck = 0800; ORGANIZATIONNAME = "Swift Algorithm Club"; TargetAttributes = { 7B2BBC7F1C779D720067B71D = { CreatedOnToolsVersion = 7.2; + LastSwiftMigration = 0800; }; }; }; @@ -149,8 +150,10 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; @@ -193,8 +196,10 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; @@ -213,6 +218,7 @@ MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; }; name = Release; }; @@ -224,6 +230,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -235,6 +242,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Release; }; diff --git a/Selection Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Selection Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme index 8ef8d8581..14f27f777 100644 --- a/Selection Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme +++ b/Selection Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -1,6 +1,6 @@ Date: Sat, 10 Sep 2016 19:30:13 +0200 Subject: [PATCH 0514/1679] Uncomment selection sort tests --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 8cf0b486b..bdda5eb7d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -33,7 +33,7 @@ script: # - xcodebuild test -project ./Quicksort/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Run-Length\ Encoding/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Select\ Minimum\ Maximum/Tests/Tests.xcodeproj -scheme Tests -# - xcodebuild test -project ./Selection\ Sort/Tests/Tests.xcodeproj -scheme Tests +- xcodebuild test -project ./Selection\ Sort/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Shell\ Sort/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Shortest\ Path\ \(Unweighted\)/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Single-Source\ Shortest\ Paths\ \(Weighted\)/SSSP.xcodeproj -scheme SSSPTests From 7480ea45bf0091251a86e9d2ddd7264d6047284a Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Sat, 10 Sep 2016 16:00:30 -0700 Subject: [PATCH 0515/1679] Marking the Swift file to read that it is currently undergoing refactoring --- Trie/trie.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Trie/trie.swift b/Trie/trie.swift index 9ebfba8bc..8227d0243 100644 --- a/Trie/trie.swift +++ b/Trie/trie.swift @@ -1,3 +1,5 @@ +/// TODO: - Undergoing refactoring. + /* Queue implementation (taken from repository, needed for findPrefix()) */ From 8a679ffae71e2dd0e1999d1abee43de74426e1ef Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Sat, 10 Sep 2016 16:39:06 -0700 Subject: [PATCH 0516/1679] Adds a playground with the first step of refactoring the implementation. --- Trie/Trie.playground/Contents.swift | 0 Trie/Trie.playground/Sources/Node.swift | 64 ++++++ Trie/Trie.playground/Sources/Queue.swift | 31 +++ Trie/Trie.playground/Sources/Trie.swift | 212 ++++++++++++++++++ Trie/Trie.playground/contents.xcplayground | 4 + .../contents.xcworkspacedata | 7 + 6 files changed, 318 insertions(+) create mode 100644 Trie/Trie.playground/Contents.swift create mode 100644 Trie/Trie.playground/Sources/Node.swift create mode 100644 Trie/Trie.playground/Sources/Queue.swift create mode 100644 Trie/Trie.playground/Sources/Trie.swift create mode 100644 Trie/Trie.playground/contents.xcplayground create mode 100644 Trie/Trie.playground/playground.xcworkspace/contents.xcworkspacedata diff --git a/Trie/Trie.playground/Contents.swift b/Trie/Trie.playground/Contents.swift new file mode 100644 index 000000000..e69de29bb diff --git a/Trie/Trie.playground/Sources/Node.swift b/Trie/Trie.playground/Sources/Node.swift new file mode 100644 index 000000000..72600af2f --- /dev/null +++ b/Trie/Trie.playground/Sources/Node.swift @@ -0,0 +1,64 @@ +/// A Trie (prefix tree) +/// +/// Some of the functionality of the trie makes use of the Queue implementation for this project +/// +/// Every node in the Trie stores a bit of information pertaining to what it references: +/// -Character (letter of an inserted word) +/// -Parent (Letter that comes before the current letter in some word) +/// -Children (Words that have more letters than available in the prefix) +/// -isAWord (Does the current letter mark the end of a known inserted word?) +/// -visited (Mainly for the findPrefix() function) +public class Node { + public var character: String + public var parent: Node? + public var children: [String: Node] + public var isAWord: Bool + public var visited: Bool // only for findPrefix + + init(character: String, parent: Node?) { + self.character = character + self.children = [:] + self.isAWord = false + self.parent = parent + self.visited = false + } + + /// Returns `true` if the node is a leaf node, false otherwise. + var isLeaf: Bool { + return children.count == 0 + } + + /// Changes the parent of the current node to the passed in node. + /// + /// - parameter node: A `Node` object. + func setParent(node: Node) { + parent = node + } + + /// Returns the child node that holds the specific passed letter. + /// + /// - parameter character: A `String` + /// + /// - returns: The `Node` object that contains the `character`. + func getChildAt(character: String) -> Node { + return children[character]! + } + + /// Returns whether or not the current node marks the end of a valid word. + var isValidWord: Bool { + return isAWord + } + + + /// Returns whether or not the current node is the root of the trie. + var isRoot: Bool { + return character == "" + } +} + +// MARK: - CustomStringConvertible +extension Node: CustomStringConvertible { + public var description: String { + return "" + } +} diff --git a/Trie/Trie.playground/Sources/Queue.swift b/Trie/Trie.playground/Sources/Queue.swift new file mode 100644 index 000000000..81bde190a --- /dev/null +++ b/Trie/Trie.playground/Sources/Queue.swift @@ -0,0 +1,31 @@ +/// Queue implementation taken from the repository. +public struct Queue { + private var array: [T?] = [] + private var head = 0 + + public var isEmpty: Bool { + return count == 0 + } + + public var count: Int { + return array.count - head + } + + public mutating func enqueue(element: T) { + array.append(element) + } + + public mutating func dequeue() -> T? { + guard head < array.count, let element = array[head] else { return nil } + array[head] = nil + head += 1 + + let percentage = Double(head) / Double(array.count) + if array.count > 50 && percentage > 0.25 { + array.removeFirst(head) + head = 0 + } + + return element + } +} diff --git a/Trie/Trie.playground/Sources/Trie.swift b/Trie/Trie.playground/Sources/Trie.swift new file mode 100644 index 000000000..053bd7113 --- /dev/null +++ b/Trie/Trie.playground/Sources/Trie.swift @@ -0,0 +1,212 @@ +/// The Trie class has the following attributes: +/// -root (the root of the trie) +/// -wordList (the words that currently exist in the trie) +/// -wordCount (the number of words in the trie) +public class Trie { + private var root = Node(character: "", parent: nil) + private(set) var wordList: [String] = [] + private(set) var wordCount = 0 + + init(words: Set) { + words.forEach { insert(word: $0) } + } + + /// Merge two `Trie` objects into one and returns the merged `Trie` + /// + /// - parameter other: Another `Trie` + /// + /// - returns: The newly unioned `Trie`. + func merge(other: Trie) -> Trie { + let newWordList = Set(wordList + other.wordList) + return Trie(words: newWordList) + } + + /// Looks for a specific key and returns a tuple that has a reference to the node (if found) and true/false depending on if it was found. + /// + /// - parameter key: A `String` that you would like to find. + /// + /// - returns: A tuple containing the an optional `Node`. If the key is found, it will return a non-nil `Node`. The second part of the tuple contains a bool indicating whether it was found or not. + func find(key: String) -> (node: Node?, found: Bool) { + var currentNode = root + + for character in key.characters { + if currentNode.children["\(character)"] == nil { + return (nil, false) + } + currentNode = currentNode.children["\(character)"]! + } + return (currentNode, currentNode.isValidWord) + } + + /// Returns true if the `Trie` is empty, false otherwise. + var isEmpty: Bool { + return wordCount == 0 + } + + /// Checks if the a word is currently in the `Trie`. + /// + /// - parameter word: A `String` you want to check. + /// + /// - returns: Returns `true` if the word exists in the `Trie`. False otherwise. + func contains(word: String) -> Bool { + return find(key: word.lowercased()).found + } + + func isPrefix(_ prefix: String) -> (node: Node?, found: Bool) { + let prefix = prefix.lowercased() + var currentNode = root + + for character in prefix.characters { + if currentNode.children["\(character)"] == nil { + return (nil, false) + } + + currentNode = currentNode.children["\(character)"]! + } + + if currentNode.children.count > 0 { + return (currentNode, true) + } + + return (nil, false) + } + + /// Inserts a word into the trie. Returns a tuple containing the word attempted to tbe added, and true/false depending on whether or not the insertion was successful. + /// + /// - parameter word: A `String`. + /// + /// - returns: A tuple containing the word attempted to be added, and whether it was successful. + @discardableResult func insert(word: String) -> (word: String, inserted: Bool) { + let word = word.lowercased() + guard !contains(word: word), !word.isEmpty else { return (word, false) } + + var currentNode = root + var length = word.characters.count + + var index = 0 + var character = word.characters.first! + + while let child = currentNode.children["\(character)"] { + currentNode = child + length -= 1 + index += 1 + + if length == 0 { + currentNode.isAWord = true + wordList.append(word) + wordCount += 1 + return (word, true) + } + + character = Array(word.characters)[index] + } + + let remainingCharacters = String(word.characters.suffix(length)) + for character in remainingCharacters.characters { + currentNode.children["\(character)"] = Node(character: "\(character)", parent: currentNode) + currentNode = currentNode.children["\(character)"]! + } + + currentNode.isAWord = true + wordList.append(word) + wordCount += 1 + return (word, true) + } + + /// Attempts to insert all words from input array. Returns a tuple containing the input array and true if some of the words were successfully added, false if none were added. + /// + /// - parameter words: An array of `String` objects. + /// + /// - returns: A tuple stating whether all the words were inserted. + func insert(words: [String]) -> (wordList: [String], inserted: Bool) { + var successful: Bool = false + for word in wordList { + successful = insert(word: word).inserted || successful + } + + return (wordList, successful) + } + + /// Removes the specified key from the `Trie` if it exists, returns tuple containing the word attempted to be removed and true/false if the removal was successful. + /// + /// - parameter word: A `String` to be removed. + /// + /// - returns: A tuple containing the word to be removed, and a `Bool` indicating whether removal was successful or not. + @discardableResult func remove(word: String) -> (word: String, removed: Bool) { + let word = word.lowercased() + + guard contains(word: word) else { return (word, false) } + var currentNode = root + + for character in word.characters { + currentNode = currentNode.getChildAt(character: "\(character)") + } + + if currentNode.children.count > 0 { + currentNode.isAWord = false + } else { + var character = currentNode.character + while currentNode.children.count == 0 && !currentNode.isRoot { + currentNode = currentNode.parent! + currentNode.children[character]!.parent = nil + character = currentNode.character + } + } + + wordCount -= 1 + + var index = 0 + for item in wordList { + if item == word { + wordList.remove(at: index) + } + index += 1 + } + + return (word, true) + } + + func find(prefix: String) -> [String] { + guard isPrefix(prefix).found else { return [] } + var queue = Queue() + let node = isPrefix(prefix).node! + + var wordsWithPrefix: [String] = [] + let word = prefix + var tmp = "" + queue.enqueue(element: node) + + while let current = queue.dequeue() { + for (_, child) in current.children { + if !child.visited { + queue.enqueue(element: child) + child.visited = true + if child.isValidWord { + var currentNode = child + while currentNode !== node { + tmp += currentNode.character + currentNode = currentNode.parent! + } + tmp = "\(tmp.characters.reversed())" + wordsWithPrefix.append(word + tmp) + tmp = "" + } + } + } + } + + return wordsWithPrefix + } + + func removeAll() { + for word in wordList { + remove(word: word) + } + } +} + +extension Trie: CustomStringConvertible { + public var description: String { + return "" + } +} diff --git a/Trie/Trie.playground/contents.xcplayground b/Trie/Trie.playground/contents.xcplayground new file mode 100644 index 000000000..5da2641c9 --- /dev/null +++ b/Trie/Trie.playground/contents.xcplayground @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Trie/Trie.playground/playground.xcworkspace/contents.xcworkspacedata b/Trie/Trie.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Trie/Trie.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + From 1da1118e1ff00d21ae02025c5a222631925d2e55 Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Mon, 12 Sep 2016 08:28:58 -0700 Subject: [PATCH 0517/1679] Refactored implementation of Trie. Leaving the old implementation in a folder for future reference. --- Trie/{ => Old Implementation}/trie.swift | 0 Trie/Trie.playground/Contents.swift | 16 ++ Trie/Trie.playground/Sources/Node.swift | 71 ++----- Trie/Trie.playground/Sources/Queue.swift | 31 --- Trie/Trie.playground/Sources/Trie.swift | 229 +++++------------------ 5 files changed, 80 insertions(+), 267 deletions(-) rename Trie/{ => Old Implementation}/trie.swift (100%) delete mode 100644 Trie/Trie.playground/Sources/Queue.swift diff --git a/Trie/trie.swift b/Trie/Old Implementation/trie.swift similarity index 100% rename from Trie/trie.swift rename to Trie/Old Implementation/trie.swift diff --git a/Trie/Trie.playground/Contents.swift b/Trie/Trie.playground/Contents.swift index e69de29bb..89a160c8d 100644 --- a/Trie/Trie.playground/Contents.swift +++ b/Trie/Trie.playground/Contents.swift @@ -0,0 +1,16 @@ +let trie = Trie() + +trie.insert(word: "apple") +trie.insert(word: "ap") +trie.insert(word: "a") + +trie.contains(word: "apple") +trie.contains(word: "ap") +trie.contains(word: "a") + +trie.remove(word: "apple") +trie.contains(word: "a") +trie.contains(word: "apple") + +trie.insert(word: "apple") +trie.contains(word: "apple") diff --git a/Trie/Trie.playground/Sources/Node.swift b/Trie/Trie.playground/Sources/Node.swift index 72600af2f..56faed3e5 100644 --- a/Trie/Trie.playground/Sources/Node.swift +++ b/Trie/Trie.playground/Sources/Node.swift @@ -1,64 +1,21 @@ -/// A Trie (prefix tree) -/// -/// Some of the functionality of the trie makes use of the Queue implementation for this project -/// -/// Every node in the Trie stores a bit of information pertaining to what it references: -/// -Character (letter of an inserted word) -/// -Parent (Letter that comes before the current letter in some word) -/// -Children (Words that have more letters than available in the prefix) -/// -isAWord (Does the current letter mark the end of a known inserted word?) -/// -visited (Mainly for the findPrefix() function) -public class Node { - public var character: String - public var parent: Node? - public var children: [String: Node] - public var isAWord: Bool - public var visited: Bool // only for findPrefix +public final class TrieNode { + public var value: T? + public weak var parent: TrieNode? + public var children: [T: TrieNode] = [:] + public var isTerminating = false - init(character: String, parent: Node?) { - self.character = character - self.children = [:] - self.isAWord = false - self.parent = parent - self.visited = false - } - - /// Returns `true` if the node is a leaf node, false otherwise. - var isLeaf: Bool { - return children.count == 0 - } - - /// Changes the parent of the current node to the passed in node. - /// - /// - parameter node: A `Node` object. - func setParent(node: Node) { - parent = node - } + init() {} - /// Returns the child node that holds the specific passed letter. - /// - /// - parameter character: A `String` - /// - /// - returns: The `Node` object that contains the `character`. - func getChildAt(character: String) -> Node { - return children[character]! - } - - /// Returns whether or not the current node marks the end of a valid word. - var isValidWord: Bool { - return isAWord - } - - - /// Returns whether or not the current node is the root of the trie. - var isRoot: Bool { - return character == "" + init(value: T, parent: TrieNode? = nil) { + self.value = value + self.parent = parent } } -// MARK: - CustomStringConvertible -extension Node: CustomStringConvertible { - public var description: String { - return "" +// MARK: - Insertion +public extension TrieNode { + func add(child: T) { + guard children[child] == nil else { return } + children[child] = TrieNode(value: child, parent: self) } } diff --git a/Trie/Trie.playground/Sources/Queue.swift b/Trie/Trie.playground/Sources/Queue.swift deleted file mode 100644 index 81bde190a..000000000 --- a/Trie/Trie.playground/Sources/Queue.swift +++ /dev/null @@ -1,31 +0,0 @@ -/// Queue implementation taken from the repository. -public struct Queue { - private var array: [T?] = [] - private var head = 0 - - public var isEmpty: Bool { - return count == 0 - } - - public var count: Int { - return array.count - head - } - - public mutating func enqueue(element: T) { - array.append(element) - } - - public mutating func dequeue() -> T? { - guard head < array.count, let element = array[head] else { return nil } - array[head] = nil - head += 1 - - let percentage = Double(head) / Double(array.count) - if array.count > 50 && percentage > 0.25 { - array.removeFirst(head) - head = 0 - } - - return element - } -} diff --git a/Trie/Trie.playground/Sources/Trie.swift b/Trie/Trie.playground/Sources/Trie.swift index 053bd7113..ddce0ba84 100644 --- a/Trie/Trie.playground/Sources/Trie.swift +++ b/Trie/Trie.playground/Sources/Trie.swift @@ -2,211 +2,82 @@ /// -root (the root of the trie) /// -wordList (the words that currently exist in the trie) /// -wordCount (the number of words in the trie) -public class Trie { - private var root = Node(character: "", parent: nil) - private(set) var wordList: [String] = [] - private(set) var wordCount = 0 +public final class Trie { + typealias Node = TrieNode + fileprivate let root: Node - init(words: Set) { - words.forEach { insert(word: $0) } + public init() { + root = TrieNode() } - - /// Merge two `Trie` objects into one and returns the merged `Trie` - /// - /// - parameter other: Another `Trie` - /// - /// - returns: The newly unioned `Trie`. - func merge(other: Trie) -> Trie { - let newWordList = Set(wordList + other.wordList) - return Trie(words: newWordList) - } - - /// Looks for a specific key and returns a tuple that has a reference to the node (if found) and true/false depending on if it was found. - /// - /// - parameter key: A `String` that you would like to find. - /// - /// - returns: A tuple containing the an optional `Node`. If the key is found, it will return a non-nil `Node`. The second part of the tuple contains a bool indicating whether it was found or not. - func find(key: String) -> (node: Node?, found: Bool) { +} + +// MARK: - Basic Methods +public extension Trie { + func insert(word: String) { + guard !word.isEmpty else { return } var currentNode = root - for character in key.characters { - if currentNode.children["\(character)"] == nil { - return (nil, false) - } - currentNode = currentNode.children["\(character)"]! - } - return (currentNode, currentNode.isValidWord) - } - - /// Returns true if the `Trie` is empty, false otherwise. - var isEmpty: Bool { - return wordCount == 0 - } - - /// Checks if the a word is currently in the `Trie`. - /// - /// - parameter word: A `String` you want to check. - /// - /// - returns: Returns `true` if the word exists in the `Trie`. False otherwise. - func contains(word: String) -> Bool { - return find(key: word.lowercased()).found - } - - func isPrefix(_ prefix: String) -> (node: Node?, found: Bool) { - let prefix = prefix.lowercased() - var currentNode = root + var characters = Array(word.lowercased().characters) + var currentIndex = 0 - for character in prefix.characters { - if currentNode.children["\(character)"] == nil { - return (nil, false) + while currentIndex < characters.count { + let character = characters[currentIndex] + if let child = currentNode.children[character] { + currentNode = child + } else { + currentNode.add(child: character) + currentNode = currentNode.children[character]! } - currentNode = currentNode.children["\(character)"]! - } - - if currentNode.children.count > 0 { - return (currentNode, true) + currentIndex += 1 + if currentIndex == characters.count { + currentNode.isTerminating = true + } } - - return (nil, false) } - /// Inserts a word into the trie. Returns a tuple containing the word attempted to tbe added, and true/false depending on whether or not the insertion was successful. - /// - /// - parameter word: A `String`. - /// - /// - returns: A tuple containing the word attempted to be added, and whether it was successful. - @discardableResult func insert(word: String) -> (word: String, inserted: Bool) { - let word = word.lowercased() - guard !contains(word: word), !word.isEmpty else { return (word, false) } - + func contains(word: String) -> Bool { + guard !word.isEmpty else { return false } var currentNode = root - var length = word.characters.count - var index = 0 - var character = word.characters.first! + var characters = Array(word.lowercased().characters) + var currentIndex = 0 - while let child = currentNode.children["\(character)"] { + while currentIndex < characters.count, let child = currentNode.children[characters[currentIndex]] { currentNode = child - length -= 1 - index += 1 - - if length == 0 { - currentNode.isAWord = true - wordList.append(word) - wordCount += 1 - return (word, true) - } - - character = Array(word.characters)[index] - } - - let remainingCharacters = String(word.characters.suffix(length)) - for character in remainingCharacters.characters { - currentNode.children["\(character)"] = Node(character: "\(character)", parent: currentNode) - currentNode = currentNode.children["\(character)"]! + currentIndex += 1 } - currentNode.isAWord = true - wordList.append(word) - wordCount += 1 - return (word, true) - } - - /// Attempts to insert all words from input array. Returns a tuple containing the input array and true if some of the words were successfully added, false if none were added. - /// - /// - parameter words: An array of `String` objects. - /// - /// - returns: A tuple stating whether all the words were inserted. - func insert(words: [String]) -> (wordList: [String], inserted: Bool) { - var successful: Bool = false - for word in wordList { - successful = insert(word: word).inserted || successful + if currentIndex == characters.count && currentNode.isTerminating { + return true + } else { + return false } - - return (wordList, successful) } - /// Removes the specified key from the `Trie` if it exists, returns tuple containing the word attempted to be removed and true/false if the removal was successful. - /// - /// - parameter word: A `String` to be removed. - /// - /// - returns: A tuple containing the word to be removed, and a `Bool` indicating whether removal was successful or not. - @discardableResult func remove(word: String) -> (word: String, removed: Bool) { - let word = word.lowercased() - - guard contains(word: word) else { return (word, false) } + func remove(word: String) { + guard !word.isEmpty else { return } var currentNode = root - for character in word.characters { - currentNode = currentNode.getChildAt(character: "\(character)") + var characters = Array(word.lowercased().characters) + var currentIndex = 0 + + while currentIndex < characters.count { + let character = characters[currentIndex] + guard let child = currentNode.children[character] else { return } + currentNode = child + currentIndex += 1 } if currentNode.children.count > 0 { - currentNode.isAWord = false + currentNode.isTerminating = false } else { - var character = currentNode.character - while currentNode.children.count == 0 && !currentNode.isRoot { - currentNode = currentNode.parent! - currentNode.children[character]!.parent = nil - character = currentNode.character - } - } - - wordCount -= 1 - - var index = 0 - for item in wordList { - if item == word { - wordList.remove(at: index) - } - index += 1 - } - - return (word, true) - } - - func find(prefix: String) -> [String] { - guard isPrefix(prefix).found else { return [] } - var queue = Queue() - let node = isPrefix(prefix).node! - - var wordsWithPrefix: [String] = [] - let word = prefix - var tmp = "" - queue.enqueue(element: node) - - while let current = queue.dequeue() { - for (_, child) in current.children { - if !child.visited { - queue.enqueue(element: child) - child.visited = true - if child.isValidWord { - var currentNode = child - while currentNode !== node { - tmp += currentNode.character - currentNode = currentNode.parent! - } - tmp = "\(tmp.characters.reversed())" - wordsWithPrefix.append(word + tmp) - tmp = "" - } - } + var character = currentNode.value + while currentNode.children.count == 0, let parent = currentNode.parent, !parent.isTerminating { + currentNode = parent + currentNode.children[character!] = nil + character = currentNode.value } } - - return wordsWithPrefix - } - - func removeAll() { - for word in wordList { - remove(word: word) - } - } -} - -extension Trie: CustomStringConvertible { - public var description: String { - return "" } } From 931e85bfb6d6fee122451840ea7cd044dd895763 Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Mon, 12 Sep 2016 13:48:25 -0700 Subject: [PATCH 0518/1679] Refactored README fileg --- Trie/ReadMe.md | 294 ++++++++++++++++++------------------------- Trie/images/trie.png | Bin 0 -> 174737 bytes 2 files changed, 119 insertions(+), 175 deletions(-) create mode 100644 Trie/images/trie.png diff --git a/Trie/ReadMe.md b/Trie/ReadMe.md index 844eb1df0..a1cd7757b 100644 --- a/Trie/ReadMe.md +++ b/Trie/ReadMe.md @@ -1,220 +1,164 @@ # Trie -##What is a Trie? -A trie (also known as a prefix tree, or radix tree in some other (but different) implementations) is a special type of tree used to store associative data structures where the key item is normally of type String. Each node in the trie is typically not associated with a value containing strictly itself, but more so is linked to some common prefix that precedes it in levels above it. Oftentimes, true key-value pairs are associated with the leaves of the trie, but they are not limited to this. +## What is a Trie? -##Why a Trie? -Tries are very useful simply for the fact that it has some advantages over other data structures, like the binary tree or a hash map. These advantages include: -* Looking up keys is typically faster in the worst case when compared to other data structures. -* Unlike a hash map, a trie need not worry about key collisions -* No need for hasing, as each key will have a unique path in the trie -* Tries, by implementation, can be by default alphabetically ordered. +A `Trie`, (also known as a prefix tree, or radix tree in some other implementations) is a special type of tree used to store associative data structures. A `Trie` for a dictionary might look like this: +![A Trie](Images/trie.png) -##Common Algorithms +Storing the English language is a primary use case for a `Trie`. Each node in the `Trie` would representing a single character of a word. A series of nodes then make up a word. -###Find (or any general lookup function) -Tries make looking up keys a trivial task, as all one has to do is walk over the nodes until we either hit a null reference or we find the key in question. +## Why a Trie? -The algorithm would be as follows: -``` - let node be the root of the trie - - for each character in the key - if the child of node with value character is null - return false (key doesn't exist in trie) - else - node = child of node with value character (move to the next node) - return true (key exists in trie and was found -``` +Tries are very useful for certain situations. Here are some of the advantages: -And in swift: -```swift -func find(key: String) -> (node: Node?, found: Bool) { - var currentNode = self.root - - for c in key.characters { - if currentNode.children[String(c)] == nil { - return(nil, false) - } - currentNode = currentNode.children[String(c)]! - } +* Looking up values typically have a better worst-case time complexity. +* Unlike a hash map, a `Trie` does not need to worry about key collisions. +* Doesn't utilize hashing to guarantee a unique path to elements. +* `Trie` structures can be alphabetically ordered by default. - return(currentNode, currentNode.isValidWord()) - } -``` +## Common Algorithms -###Insertion -Insertion is also a trivial task with a Trie, as all one needs to do is walk over the nodes until we either halt on a node that we must mark as a key, or we reach a point where we need to add extra nodes to represent it. +### Contains (or any general lookup method) -Let's walk through the algorithm: +`Trie` structures are great for lookup operations. For `Trie` structures that model the English language, finding a particular word is a matter of a few pointer traversals: -``` - let S be the root node of our tree - let word be the input key - let length be the length of the key - +```swift +func contains(word: String) -> Bool { + guard !word.isEmpty else { return false } + + // 1 + var currentNode = root - find(word) - if the word was found - return false - else - - for each character in word - if child node with value character does not exist - break - else - node = child node with value character - decrement length - - if length != 0 - let suffix be the remaining characters in the key defined by the shortened length - - for each character in suffix - create a new node with value character and let it be the child of node - node = newly created child now - mark node as a valid key - else - mark node as valid key + // 2 + var characters = Array(word.lowercased().characters) + var currentIndex = 0 + + // 3 + while currentIndex < characters.count, + let child = currentNode.children[character[currentIndex]] { + + currentNode = child + currentIndex += 1 + } + + // 4 + if currentIndex == characters.count && currentNode.isTerminating { + return true + } else { + return false + } +} ``` -And the corresponding swift code: +The `contains` method is fairly straightforward: -```swift - func insert(w: String) -> (word: String, inserted: Bool) { - - let word = w.lowercaseString - var currentNode = self.root - var length = word.characters.count +1. Create a reference to the `root`. This reference will allow you to walk down a chain of nodes. +2. Keep track of the characters of the word you're trying to match. +3. Walk the pointer down the nodes. +4. `isTerminating` is a boolean flag for whether or not this node is the end of a word. If this `if` condition is satisfied, it means you are able to find the word in the `trie`. - if self.contains(word) { - return (w, false) - } +### Insertion - var index = 0 - var c = Array(word.characters)[index] +Insertion into a `Trie` requires you to walk over the nodes until you either halt on a node that must be marked as `terminating`, or reach a point where you need to add extra nodes. - while let child = currentNode.children[String(c)] { - currentNode = child - length -= 1 - index += 1 +```swift +func insert(word: String) { + guard !word.isEmpty else { return } - if(length == 0) { - currentNode.isWord() - wordList.append(w) - wordCount += 1 - return (w, true) - } + // 1 + var currentNode = root + + // 2 + var characters = Array(word.lowercased().characters) + var currentIndex = 0 + + // 3 + while currentIndex < characters.count { + let character = characters[currentIndex] - c = Array(word.characters)[index] + // 4 + if let child = currentNode.children[character] { + currentNode = child + } else { + currentNode.add(child: character) + currentNode = currentNode.children[character]! } + + currentIndex += 1 - let remainingChars = String(word.characters.suffix(length)) - for c in remainingChars.characters { - currentNode.children[String(c)] = Node(c: String(c), p: currentNode) - currentNode = currentNode.children[String(c)]! + // 5 + if currentIndex == characters.count { + currentNode.isTerminating = true } - - currentNode.isWord() - wordList.append(w) - wordCount += 1 - return (w, true) } - +} ``` -###Removal -Removing keys from the trie is a little more tricky, as there a few more cases that we have to take into account the fact that keys may exist that are actually sub-strings of other valid keys. That being said, it isn't as simple a process to just delete the nodes for a specific key, as we could be deleting references/nodes necessary for already exisitng keys! +1. Once again, you create a reference to the root node. You'll move this reference down a chain of nodes. +2. Keep track of the word you want to insert. +3. Begin walking through your word letter by letter +4. Sometimes, the required node to insert already exists. That is the case for two words inside the `Trie` that shares letters (i.e "Apple", "App"). If a letter already exists, you'll reuse it, and simply traverse deeper down the chain. Otherwise, you'll create a new node representing the letter. +5. Once you get to the end, you mark `isTerminating` to true to mark that specific node as the end of a word. -The algorithm would be as follows: - -``` - - let word be the key to remove - let node be the root of the trie - - find(word) - if word was not found - return false - else - - for each character in word - node = child node with value character - - if node has more than just 1 child node - Mark node as an invalid key, since removing it would remove nodes still in use - else - while node has no valid children and node is not the root node - let character = node's value - node = the parent of node - delete node's child node with value character - return true -``` +### Removal +Removing keys from the trie is a little tricky, as there are a few more cases you'll need to take into account. Nodes in a `Trie` may be shared between different words. Consider the two words "Apple" and "App". Inside a `Trie`, the chain of nodes representing "App" is shared with "Apple". - -and the corresponding swift code: +If you'd like to remove "Apple", you'll need to take care to leave the "App" chain in tact. ```swift - func remove(w: String) -> (word: String, removed: Bool){ - let word = w.lowercaseString - - if(!self.contains(w)) { - return (w, false) - } - var currentNode = self.root +func remove(word: String) { + guard !word.isEmpty else { return } - for c in word.characters { - currentNode = currentNode.getChildAt(String(c)) - } - - if currentNode.numChildren() > 0 { - currentNode.isNotWord() - } else { - var character = currentNode.char() - while(currentNode.numChildren() == 0 && !currentNode.isRoot()) { - currentNode = currentNode.getParent() - currentNode.children[character]!.setParent(nil) - currentNode.children[character]!.update(nil) - currentNode.children[character] = nil - character = currentNode.char() - } - } - - wordCount -= 1 - - var index = 0 - for item in wordList{ - if item == w { - wordList.removeAtIndex(index) - } - index += 1 + // 1 + var currentNode = root + + // 2 + var characters = Array(word.lowercased().characters) + var currentIndex = 0 + + // 3 + while currentIndex < characters.count { + let character = characters[currentIndex] + guard let child = currentNode.children[character] else { return } + currentNode = child + currentIndex += 1 + } + + // 4 + if currentNode.children.count > 0 { + currentNode.isTerminating = false + } else { + var character = currentNode.value + while currentNode.children.count == 0, let parent = currentNode.parent, !parent.isTerminating { + currentNode = parent + currentNode.children[character!] = nil + character = currentNode.value } - - return (w, true) } - +} ``` +1. Once again, you create a reference to the root node. +2. Keep track of the word you want to remove. +3. Attempt to walk to the terminating node of the word. The `guard` statement will return if it can't find one of the letters; It's possible to call `remove` on a non-existant entry. +4. If you reach the node representing the last letter of the word you want to remove, you'll have 2 cases to deal with. Either it's a leaf node, or it has more children. If it has more children, it means the node is used for other words. In that case, you'll just mark `isTerminating` to false. In the other case, you'll delete the nodes. -###Running Times +### Time Complexity -Let n be the length of some key in the trie +Let n be the length of some value in the `Trie`. -* Find(...) : In the Worst case O(n) -* Insert(...) : O(n) -* Remove(...) : O(n) +* `contains` - Worst case O(n) +* `insert` - O(n) +* `remove` - O(n) -###Other Notable Operations +### Other Notable Operations -* Count: Returns the number of keys in the trie ( O(1) ) -* getWords: Returns a list containing all keys in the trie ( *O(1) ) -* isEmpty: Returns true f the trie is empty, false otherwise ( *O(1) ) -* contains: Returns true if the trie has a given key, false otherwise ( O(n) ) - -`* denotes that running time may vary depending on implementation +* `count`: Returns the number of keys in the `Trie` - O(1) +* `words`: Returns a list containing all the keys in the `Trie` - O(1) +* `isEmpty`: Returns `true` if the `Trie` is empty, `false` otherwise - O(1) See also [Wikipedia entry for Trie](https://en.wikipedia.org/wiki/Trie). -*Written for the Swift Algorithm Club by Christian Encarnacion* - +*Written for the Swift Algorithm Club by Christian Encarnacion. Refactored by Kelvin Lau* diff --git a/Trie/images/trie.png b/Trie/images/trie.png new file mode 100644 index 0000000000000000000000000000000000000000..00dacc0080cd596cc1d2934e2b5f2a15abb7ae1c GIT binary patch literal 174737 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

`8OzWVS<5_7y)1- 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%0D!S1G`PQ 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 caA^F`e#~HF)@`jl{0uFVdQ&MBb@07dCJ3;+NC literal 0 HcmV?d00001 From b563b932f903c732790f2e363a7e294483e4665b Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Mon, 12 Sep 2016 13:51:20 -0700 Subject: [PATCH 0519/1679] Fixed spacing --- Trie/ReadMe.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/Trie/ReadMe.md b/Trie/ReadMe.md index a1cd7757b..ee101a0a9 100644 --- a/Trie/ReadMe.md +++ b/Trie/ReadMe.md @@ -30,11 +30,11 @@ func contains(word: String) -> Bool { // 1 var currentNode = root - // 2 + // 2 var characters = Array(word.lowercased().characters) var currentIndex = 0 - // 3 + // 3 while currentIndex < characters.count, let child = currentNode.children[character[currentIndex]] { @@ -42,7 +42,7 @@ func contains(word: String) -> Bool { currentIndex += 1 } - // 4 + // 4 if currentIndex == characters.count && currentNode.isTerminating { return true } else { @@ -69,15 +69,15 @@ func insert(word: String) { // 1 var currentNode = root - // 2 + // 2 var characters = Array(word.lowercased().characters) var currentIndex = 0 - // 3 + // 3 while currentIndex < characters.count { let character = characters[currentIndex] - // 4 + // 4 if let child = currentNode.children[character] { currentNode = child } else { @@ -87,7 +87,7 @@ func insert(word: String) { currentIndex += 1 - // 5 + // 5 if currentIndex == characters.count { currentNode.isTerminating = true } @@ -111,14 +111,14 @@ If you'd like to remove "Apple", you'll need to take care to leave the "App" cha func remove(word: String) { guard !word.isEmpty else { return } - // 1 + // 1 var currentNode = root - // 2 + // 2 var characters = Array(word.lowercased().characters) var currentIndex = 0 - // 3 + // 3 while currentIndex < characters.count { let character = characters[currentIndex] guard let child = currentNode.children[character] else { return } @@ -126,7 +126,7 @@ func remove(word: String) { currentIndex += 1 } - // 4 + // 4 if currentNode.children.count > 0 { currentNode.isTerminating = false } else { From 0faf88a574d5ea8c923819c63cd394eb503eeecb Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Mon, 12 Sep 2016 13:51:49 -0700 Subject: [PATCH 0520/1679] Fixed a typo. --- Trie/ReadMe.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Trie/ReadMe.md b/Trie/ReadMe.md index ee101a0a9..3e3dad3a6 100644 --- a/Trie/ReadMe.md +++ b/Trie/ReadMe.md @@ -4,7 +4,7 @@ A `Trie`, (also known as a prefix tree, or radix tree in some other implementations) is a special type of tree used to store associative data structures. A `Trie` for a dictionary might look like this: -![A Trie](Images/trie.png) +![A Trie](images/trie.png) Storing the English language is a primary use case for a `Trie`. Each node in the `Trie` would representing a single character of a word. A series of nodes then make up a word. From 8035d8dccf919099ae581ef899ed5558fce938b1 Mon Sep 17 00:00:00 2001 From: Richard Date: Mon, 12 Sep 2016 18:03:20 -0700 Subject: [PATCH 0521/1679] Init & Claim Karatsuba Multiplication Algorithm --- Karatsuba Multiplication/KaratsubaMultiplication.swift | 9 +++++++++ Karatsuba Multiplication/README.markdown | 8 ++++++++ 2 files changed, 17 insertions(+) create mode 100644 Karatsuba Multiplication/KaratsubaMultiplication.swift create mode 100644 Karatsuba Multiplication/README.markdown diff --git a/Karatsuba Multiplication/KaratsubaMultiplication.swift b/Karatsuba Multiplication/KaratsubaMultiplication.swift new file mode 100644 index 000000000..725b87939 --- /dev/null +++ b/Karatsuba Multiplication/KaratsubaMultiplication.swift @@ -0,0 +1,9 @@ +// +// KaratsubaMultiplication.swift +// +// +// Created by Richard Ash on 9/12/16. +// +// + +import Foundation diff --git a/Karatsuba Multiplication/README.markdown b/Karatsuba Multiplication/README.markdown new file mode 100644 index 000000000..0afd91b0c --- /dev/null +++ b/Karatsuba Multiplication/README.markdown @@ -0,0 +1,8 @@ +# Karatsuba Multiplication + +TODO: Explanation/Examples + + + + +*Written for Swift Algorithm Club by Richard Ash* From b6c05be12875e17e1734b4438eb9e72869aeb228 Mon Sep 17 00:00:00 2001 From: Richard Date: Mon, 12 Sep 2016 18:04:23 -0700 Subject: [PATCH 0522/1679] Added implmentation for the Karatsuba Algorithm --- .../Contents.swift | 57 +++++++++++++++++++ .../contents.xcplayground | 4 ++ .../contents.xcworkspacedata | 7 +++ .../KaratsubaMultiplication.swift | 25 ++++++++ 4 files changed, 93 insertions(+) create mode 100644 Karatsuba Multiplication/KaratsubaMultiplication.playground/Contents.swift create mode 100644 Karatsuba Multiplication/KaratsubaMultiplication.playground/contents.xcplayground create mode 100644 Karatsuba Multiplication/KaratsubaMultiplication.playground/playground.xcworkspace/contents.xcworkspacedata diff --git a/Karatsuba Multiplication/KaratsubaMultiplication.playground/Contents.swift b/Karatsuba Multiplication/KaratsubaMultiplication.playground/Contents.swift new file mode 100644 index 000000000..bf4454956 --- /dev/null +++ b/Karatsuba Multiplication/KaratsubaMultiplication.playground/Contents.swift @@ -0,0 +1,57 @@ +//: Playground - noun: a place where people can play + +import Foundation + +infix operator ^^ { associativity left precedence 160 } +func ^^ (radix: Int, power: Int) -> Int { + return Int(pow(Double(radix), Double(power))) +} + +// Long Multiplication - O(n^2) +func multiply(num1: Int, _ num2: Int, base: Int = 10) -> Int { + let num1Array = String(num1).characters.reverse().map{ Int(String($0))! } + let num2Array = String(num2).characters.reverse().map{ Int(String($0))! } + + var product = Array(count: num1Array.count + num2Array.count, repeatedValue: 0) + + for i in num1Array.indices { + var carry = 0 + for j in num2Array.indices { + product[i + j] += carry + num1Array[i] * num2Array[j] + carry = product[i + j] / base + product[i + j] %= base + } + product[i + num2Array.count] += carry + } + + return Int(product.reverse().map{ String($0) }.reduce("", combine: +))! +} + +// Karatsuba Multiplication - O(nlogn) +func karatsuba(num1: Int, _ num2: Int) -> Int { + let num1Array = String(num1).characters + let num2Array = String(num2).characters + + guard num1Array.count > 1 && num2Array.count > 1 else { + return multiply(num1, num2) + } + + let n = max(num1Array.count, num2Array.count) + let nBy2 = n / 2 + + let a = num1 / 10^^nBy2 + let b = num1 % 10^^nBy2 + let c = num2 / 10^^nBy2 + let d = num2 % 10^^nBy2 + + let ac = karatsuba(a, c) + let bd = karatsuba(b, d) + let adPluscd = karatsuba(a+b, c+d) - ac - bd + + let product = ac * 10^^(2 * nBy2) + adPluscd * 10^^nBy2 + bd + + return product +} + +print(multiply(236742342, 1231234224)) +print(karatsuba(236742342, 1231234224)) \ No newline at end of file diff --git a/Karatsuba Multiplication/KaratsubaMultiplication.playground/contents.xcplayground b/Karatsuba Multiplication/KaratsubaMultiplication.playground/contents.xcplayground new file mode 100644 index 000000000..9f5f2f40c --- /dev/null +++ b/Karatsuba Multiplication/KaratsubaMultiplication.playground/contents.xcplayground @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Karatsuba Multiplication/KaratsubaMultiplication.playground/playground.xcworkspace/contents.xcworkspacedata b/Karatsuba Multiplication/KaratsubaMultiplication.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Karatsuba Multiplication/KaratsubaMultiplication.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Karatsuba Multiplication/KaratsubaMultiplication.swift b/Karatsuba Multiplication/KaratsubaMultiplication.swift index 725b87939..a315d7494 100644 --- a/Karatsuba Multiplication/KaratsubaMultiplication.swift +++ b/Karatsuba Multiplication/KaratsubaMultiplication.swift @@ -7,3 +7,28 @@ // import Foundation + +func karatsuba(num1: Int, _ num2: Int) -> Int { + let num1Array = String(num1).characters + let num2Array = String(num2).characters + + guard num1Array.count > 1 && num2Array.count > 1 else { + return num1 * num2 + } + + let n = max(num1Array.count, num2Array.count) + let nBy2 = n / 2 + + let a = num1 / 10^^nBy2 + let b = num1 % 10^^nBy2 + let c = num2 / 10^^nBy2 + let d = num2 % 10^^nBy2 + + let ac = karatsuba(a, c) + let bd = karatsuba(b, d) + let adPluscd = karatsuba(a+b, c+d) - ac - bd + + let product = ac * 10^^(2 * nBy2) + adPluscd * 10^^nBy2 + bd + + return product +} \ No newline at end of file From 8d03fea237fb50ab1420dcd1614dfb903e5629e7 Mon Sep 17 00:00:00 2001 From: Tulio Troncoso Date: Tue, 13 Sep 2016 16:33:55 -0400 Subject: [PATCH 0523/1679] Updated Linked List playground to swift 3 --- .../LinkedList.playground/Contents.swift | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/Linked List/LinkedList.playground/Contents.swift b/Linked List/LinkedList.playground/Contents.swift index cc7ed3d59..5c05c1a3e 100644 --- a/Linked List/LinkedList.playground/Contents.swift +++ b/Linked List/LinkedList.playground/Contents.swift @@ -13,7 +13,7 @@ public class LinkedListNode { public class LinkedList { public typealias Node = LinkedListNode - private var head: Node? + fileprivate var head: Node? public var isEmpty: Bool { return head == nil @@ -61,7 +61,7 @@ public class LinkedList { } public subscript(index: Int) -> T { - let node = nodeAtIndex(index) + let node = nodeAtIndex(index: index) assert(node != nil) return node!.value } @@ -94,7 +94,7 @@ public class LinkedList { } public func insert(value: T, atIndex index: Int) { - let (prev, next) = nodesBeforeAndAfter(index) + let (prev, next) = nodesBeforeAndAfter(index: index) let newNode = Node(value: value) newNode.previous = prev @@ -129,13 +129,13 @@ public class LinkedList { public func removeLast() -> T { assert(!isEmpty) - return removeNode(last!) + return removeNode(node: last!) } public func removeAtIndex(index: Int) -> T { - let node = nodeAtIndex(index) + let node = nodeAtIndex(index: index) assert(node != nil) - return removeNode(node!) + return removeNode(node: node!) } } @@ -164,22 +164,22 @@ extension LinkedList { } extension LinkedList { - public func map(transform: T -> U) -> LinkedList { + public func map(transform: (T) -> U) -> LinkedList { let result = LinkedList() var node = head while node != nil { - result.append(transform(node!.value)) + result.append(value: transform(node!.value)) node = node!.next } return result } - public func filter(predicate: T -> Bool) -> LinkedList { + public func filter(predicate: (T) -> Bool) -> LinkedList { let result = LinkedList() var node = head while node != nil { if predicate(node!.value) { - result.append(node!.value) + result.append(value: node!.value) } node = node!.next } @@ -195,13 +195,13 @@ list.isEmpty // true list.first // nil list.last // nil -list.append("Hello") +list.append(value: "Hello") list.isEmpty list.first!.value // "Hello" list.last!.value // "Hello" list.count // 1 -list.append("World") +list.append(value: "World") list.first!.value // "Hello" list.last!.value // "World" list.count // 2 @@ -211,15 +211,15 @@ list.first!.next!.value // "World" list.last!.previous!.value // "Hello" list.last!.next // nil -list.nodeAtIndex(0)!.value // "Hello" -list.nodeAtIndex(1)!.value // "World" -list.nodeAtIndex(2) // nil +list.nodeAtIndex(index: 0)!.value // "Hello" +list.nodeAtIndex(index: 1)!.value // "World" +list.nodeAtIndex(index: 2) // nil list[0] // "Hello" list[1] // "World" //list[2] // crash! -list.insert("Swift", atIndex: 1) +list.insert(value: "Swift", atIndex: 1) list[0] list[1] list[2] @@ -227,8 +227,8 @@ print(list) list.reverse() // [World, Swift, Hello] -list.nodeAtIndex(0)!.value = "Universe" -list.nodeAtIndex(1)!.value = "Swifty" +list.nodeAtIndex(index: 0)!.value = "Universe" +list.nodeAtIndex(index: 1)!.value = "Swifty" let m = list.map { s in s.characters.count } m // [8, 6, 5] let f = list.filter { s in s.characters.count > 5 } @@ -237,7 +237,7 @@ f // [Universe, Swifty] //list.removeAll() //list.isEmpty -list.removeNode(list.first!) // "Hello" +list.removeNode(node: list.first!) // "Hello" list.count // 2 list[0] // "Swift" list[1] // "World" @@ -246,5 +246,5 @@ list.removeLast() // "World" list.count // 1 list[0] // "Swift" -list.removeAtIndex(0) // "Swift" +list.removeAtIndex(index: 0) // "Swift" list.count // 0 From 900811288a73e20e1c17c5b80d852f0c120b56f3 Mon Sep 17 00:00:00 2001 From: Tulio Troncoso Date: Tue, 13 Sep 2016 16:48:40 -0400 Subject: [PATCH 0524/1679] Updated LinkedList.swift for Swift 3 --- .../Sources/LinkedList.swift | 191 ++++++++++++++++++ Linked List/LinkedList.swift | 20 +- 2 files changed, 201 insertions(+), 10 deletions(-) create mode 100755 Linked List/LinkedList.playground/Sources/LinkedList.swift diff --git a/Linked List/LinkedList.playground/Sources/LinkedList.swift b/Linked List/LinkedList.playground/Sources/LinkedList.swift new file mode 100755 index 000000000..ef95a0b58 --- /dev/null +++ b/Linked List/LinkedList.playground/Sources/LinkedList.swift @@ -0,0 +1,191 @@ +/* + Doubly-linked list + + Most operations on the linked list have complexity O(n). +*/ +public class LinkedListNode { + var value: T + var next: LinkedListNode? + weak var previous: LinkedListNode? + + public init(value: T) { + self.value = value + } +} + +public class LinkedList { + public typealias Node = LinkedListNode + + private var head: Node? + + public var isEmpty: Bool { + return head == nil + } + + public var first: Node? { + return head + } + + public var last: Node? { + if var node = head { + while case let next? = node.next { + node = next + } + return node + } else { + return nil + } + } + + public var count: Int { + if var node = head { + var c = 1 + while case let next? = node.next { + node = next + c += 1 + } + return c + } else { + return 0 + } + } + + public func nodeAtIndex(index: Int) -> Node? { + if index >= 0 { + var node = head + var i = index + while node != nil { + if i == 0 { return node } + i -= 1 + node = node!.next + } + } + return nil + } + + public subscript(index: Int) -> T { + let node = nodeAtIndex(index) + assert(node != nil) + return node!.value + } + + public func append(value: T) { + let newNode = Node(value: value) + if let lastNode = last { + newNode.previous = lastNode + lastNode.next = newNode + } else { + head = newNode + } + } + + private func nodesBeforeAndAfter(index: Int) -> (Node?, Node?) { + assert(index >= 0) + + var i = index + var next = head + var prev: Node? + + while next != nil && i > 0 { + i -= 1 + prev = next + next = next!.next + } + assert(i == 0) // if > 0, then specified index was too large + + return (prev, next) + } + + public func insert(value: T, atIndex index: Int) { + let (prev, next) = nodesBeforeAndAfter(index) + + let newNode = Node(value: value) + newNode.previous = prev + newNode.next = next + prev?.next = newNode + next?.previous = newNode + + if prev == nil { + head = newNode + } + } + + public func removeAll() { + head = nil + } + + public func removeNode(node: Node) -> T { + let prev = node.previous + let next = node.next + + if let prev = prev { + prev.next = next + } else { + head = next + } + next?.previous = prev + + node.previous = nil + node.next = nil + return node.value + } + + public func removeLast() -> T { + assert(!isEmpty) + return removeNode(last!) + } + + public func removeAtIndex(index: Int) -> T { + let node = nodeAtIndex(index) + assert(node != nil) + return removeNode(node!) + } +} + +extension LinkedList: CustomStringConvertible { + public var description: String { + var s = "[" + var node = head + while node != nil { + s += "\(node!.value)" + node = node!.next + if node != nil { s += ", " } + } + return s + "]" + } +} + +extension LinkedList { + public func reverse() { + var node = head + while let currentNode = node { + node = currentNode.next + swap(¤tNode.next, ¤tNode.previous) + head = currentNode + } + } +} + +extension LinkedList { + public func map(transform: T -> U) -> LinkedList { + let result = LinkedList() + var node = head + while node != nil { + result.append(transform(node!.value)) + node = node!.next + } + return result + } + + public func filter(predicate: T -> Bool) -> LinkedList { + let result = LinkedList() + var node = head + while node != nil { + if predicate(node!.value) { + result.append(node!.value) + } + node = node!.next + } + return result + } +} diff --git a/Linked List/LinkedList.swift b/Linked List/LinkedList.swift index ef95a0b58..336775c3c 100755 --- a/Linked List/LinkedList.swift +++ b/Linked List/LinkedList.swift @@ -16,7 +16,7 @@ public class LinkedListNode { public class LinkedList { public typealias Node = LinkedListNode - private var head: Node? + fileprivate var head: Node? public var isEmpty: Bool { return head == nil @@ -64,7 +64,7 @@ public class LinkedList { } public subscript(index: Int) -> T { - let node = nodeAtIndex(index) + let node = nodeAtIndex(index: index) assert(node != nil) return node!.value } @@ -97,7 +97,7 @@ public class LinkedList { } public func insert(value: T, atIndex index: Int) { - let (prev, next) = nodesBeforeAndAfter(index) + let (prev, next) = nodesBeforeAndAfter(index: index) let newNode = Node(value: value) newNode.previous = prev @@ -132,13 +132,13 @@ public class LinkedList { public func removeLast() -> T { assert(!isEmpty) - return removeNode(last!) + return removeNode(node: last!) } public func removeAtIndex(index: Int) -> T { - let node = nodeAtIndex(index) + let node = nodeAtIndex(index: index) assert(node != nil) - return removeNode(node!) + return removeNode(node: node!) } } @@ -167,22 +167,22 @@ extension LinkedList { } extension LinkedList { - public func map(transform: T -> U) -> LinkedList { + public func map(transform: (T)-> U) -> LinkedList { let result = LinkedList() var node = head while node != nil { - result.append(transform(node!.value)) + result.append(value: transform(node!.value)) node = node!.next } return result } - public func filter(predicate: T -> Bool) -> LinkedList { + public func filter(predicate: (T)-> Bool) -> LinkedList { let result = LinkedList() var node = head while node != nil { if predicate(node!.value) { - result.append(node!.value) + result.append(value: node!.value) } node = node!.next } From bd5b4c0fbcf18adb32f698fcd0f68afee1a8232e Mon Sep 17 00:00:00 2001 From: Tulio Troncoso Date: Tue, 13 Sep 2016 16:50:29 -0400 Subject: [PATCH 0525/1679] Removed LinkedList.swift from playground It was added by mistake --- .../Sources/LinkedList.swift | 191 ------------------ 1 file changed, 191 deletions(-) delete mode 100755 Linked List/LinkedList.playground/Sources/LinkedList.swift diff --git a/Linked List/LinkedList.playground/Sources/LinkedList.swift b/Linked List/LinkedList.playground/Sources/LinkedList.swift deleted file mode 100755 index ef95a0b58..000000000 --- a/Linked List/LinkedList.playground/Sources/LinkedList.swift +++ /dev/null @@ -1,191 +0,0 @@ -/* - Doubly-linked list - - Most operations on the linked list have complexity O(n). -*/ -public class LinkedListNode { - var value: T - var next: LinkedListNode? - weak var previous: LinkedListNode? - - public init(value: T) { - self.value = value - } -} - -public class LinkedList { - public typealias Node = LinkedListNode - - private var head: Node? - - public var isEmpty: Bool { - return head == nil - } - - public var first: Node? { - return head - } - - public var last: Node? { - if var node = head { - while case let next? = node.next { - node = next - } - return node - } else { - return nil - } - } - - public var count: Int { - if var node = head { - var c = 1 - while case let next? = node.next { - node = next - c += 1 - } - return c - } else { - return 0 - } - } - - public func nodeAtIndex(index: Int) -> Node? { - if index >= 0 { - var node = head - var i = index - while node != nil { - if i == 0 { return node } - i -= 1 - node = node!.next - } - } - return nil - } - - public subscript(index: Int) -> T { - let node = nodeAtIndex(index) - assert(node != nil) - return node!.value - } - - public func append(value: T) { - let newNode = Node(value: value) - if let lastNode = last { - newNode.previous = lastNode - lastNode.next = newNode - } else { - head = newNode - } - } - - private func nodesBeforeAndAfter(index: Int) -> (Node?, Node?) { - assert(index >= 0) - - var i = index - var next = head - var prev: Node? - - while next != nil && i > 0 { - i -= 1 - prev = next - next = next!.next - } - assert(i == 0) // if > 0, then specified index was too large - - return (prev, next) - } - - public func insert(value: T, atIndex index: Int) { - let (prev, next) = nodesBeforeAndAfter(index) - - let newNode = Node(value: value) - newNode.previous = prev - newNode.next = next - prev?.next = newNode - next?.previous = newNode - - if prev == nil { - head = newNode - } - } - - public func removeAll() { - head = nil - } - - public func removeNode(node: Node) -> T { - let prev = node.previous - let next = node.next - - if let prev = prev { - prev.next = next - } else { - head = next - } - next?.previous = prev - - node.previous = nil - node.next = nil - return node.value - } - - public func removeLast() -> T { - assert(!isEmpty) - return removeNode(last!) - } - - public func removeAtIndex(index: Int) -> T { - let node = nodeAtIndex(index) - assert(node != nil) - return removeNode(node!) - } -} - -extension LinkedList: CustomStringConvertible { - public var description: String { - var s = "[" - var node = head - while node != nil { - s += "\(node!.value)" - node = node!.next - if node != nil { s += ", " } - } - return s + "]" - } -} - -extension LinkedList { - public func reverse() { - var node = head - while let currentNode = node { - node = currentNode.next - swap(¤tNode.next, ¤tNode.previous) - head = currentNode - } - } -} - -extension LinkedList { - public func map(transform: T -> U) -> LinkedList { - let result = LinkedList() - var node = head - while node != nil { - result.append(transform(node!.value)) - node = node!.next - } - return result - } - - public func filter(predicate: T -> Bool) -> LinkedList { - let result = LinkedList() - var node = head - while node != nil { - if predicate(node!.value) { - result.append(node!.value) - } - node = node!.next - } - return result - } -} From b2fe7f39ccfedaf816d4a9c69ac3455ebd7db67b Mon Sep 17 00:00:00 2001 From: Tulio Troncoso Date: Tue, 13 Sep 2016 16:56:45 -0400 Subject: [PATCH 0526/1679] Changed naming of functions to fit the Swift 3 style Functions like nodeAtIndex(index: Int) are now nodeAt(index: Int) --- .../LinkedList.playground/Contents.swift | 28 +++++++++---------- Linked List/LinkedList.swift | 14 +++++----- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/Linked List/LinkedList.playground/Contents.swift b/Linked List/LinkedList.playground/Contents.swift index 5c05c1a3e..2078c0baf 100644 --- a/Linked List/LinkedList.playground/Contents.swift +++ b/Linked List/LinkedList.playground/Contents.swift @@ -47,7 +47,7 @@ public class LinkedList { } } - public func nodeAtIndex(index: Int) -> Node? { + public func nodeAt(index: Int) -> Node? { if index >= 0 { var node = head var i = index @@ -61,7 +61,7 @@ public class LinkedList { } public subscript(index: Int) -> T { - let node = nodeAtIndex(index: index) + let node = nodeAt(index: index) assert(node != nil) return node!.value } @@ -111,7 +111,7 @@ public class LinkedList { head = nil } - public func removeNode(node: Node) -> T { + public func remove(node: Node) -> T { let prev = node.previous let next = node.next @@ -129,13 +129,13 @@ public class LinkedList { public func removeLast() -> T { assert(!isEmpty) - return removeNode(node: last!) + return remove(node: last!) } - public func removeAtIndex(index: Int) -> T { - let node = nodeAtIndex(index: index) + public func removeAt(index: Int) -> T { + let node = nodeAt(index: index) assert(node != nil) - return removeNode(node: node!) + return remove(node: node!) } } @@ -211,9 +211,9 @@ list.first!.next!.value // "World" list.last!.previous!.value // "Hello" list.last!.next // nil -list.nodeAtIndex(index: 0)!.value // "Hello" -list.nodeAtIndex(index: 1)!.value // "World" -list.nodeAtIndex(index: 2) // nil +list.nodeAt(index: 0)!.value // "Hello" +list.nodeAt(index: 1)!.value // "World" +list.nodeAt(index: 2) // nil list[0] // "Hello" list[1] // "World" @@ -227,8 +227,8 @@ print(list) list.reverse() // [World, Swift, Hello] -list.nodeAtIndex(index: 0)!.value = "Universe" -list.nodeAtIndex(index: 1)!.value = "Swifty" +list.nodeAt(index: 0)!.value = "Universe" +list.nodeAt(index: 1)!.value = "Swifty" let m = list.map { s in s.characters.count } m // [8, 6, 5] let f = list.filter { s in s.characters.count > 5 } @@ -237,7 +237,7 @@ f // [Universe, Swifty] //list.removeAll() //list.isEmpty -list.removeNode(node: list.first!) // "Hello" +list.remove(node: list.first!) // "Hello" list.count // 2 list[0] // "Swift" list[1] // "World" @@ -246,5 +246,5 @@ list.removeLast() // "World" list.count // 1 list[0] // "Swift" -list.removeAtIndex(index: 0) // "Swift" +list.removeAt(index: 0) // "Swift" list.count // 0 diff --git a/Linked List/LinkedList.swift b/Linked List/LinkedList.swift index 336775c3c..8d95c4ac1 100755 --- a/Linked List/LinkedList.swift +++ b/Linked List/LinkedList.swift @@ -50,7 +50,7 @@ public class LinkedList { } } - public func nodeAtIndex(index: Int) -> Node? { + public func nodeAt(index: Int) -> Node? { if index >= 0 { var node = head var i = index @@ -64,7 +64,7 @@ public class LinkedList { } public subscript(index: Int) -> T { - let node = nodeAtIndex(index: index) + let node = nodeAt(index: index) assert(node != nil) return node!.value } @@ -114,7 +114,7 @@ public class LinkedList { head = nil } - public func removeNode(node: Node) -> T { + public func remove(node: Node) -> T { let prev = node.previous let next = node.next @@ -132,13 +132,13 @@ public class LinkedList { public func removeLast() -> T { assert(!isEmpty) - return removeNode(node: last!) + return remove(node: last!) } - public func removeAtIndex(index: Int) -> T { - let node = nodeAtIndex(index: index) + public func removeAt(index: Int) -> T { + let node = nodeAt(index: index) assert(node != nil) - return removeNode(node: node!) + return remove(node: node!) } } From b0baae91b1681c187fe7f8df37e296b733a1988e Mon Sep 17 00:00:00 2001 From: Tulio Troncoso Date: Tue, 13 Sep 2016 17:19:59 -0400 Subject: [PATCH 0527/1679] Updated tests to swift 3 and fixed playground There was a better way to do the naming. Instead of doing nodeAt(index: Int), I changed it to nodeAt(_ index: Int) which allows you to call nodeAt(3) instead of nodeAt(index: 3) --- .../LinkedList.playground/Contents.swift | 20 ++++---- Linked List/LinkedList.swift | 48 +++++++++---------- Linked List/Tests/LinkedListTests.swift | 34 ++++++------- .../Tests/Tests.xcodeproj/project.pbxproj | 3 ++ 4 files changed, 54 insertions(+), 51 deletions(-) diff --git a/Linked List/LinkedList.playground/Contents.swift b/Linked List/LinkedList.playground/Contents.swift index 2078c0baf..72dcffe02 100644 --- a/Linked List/LinkedList.playground/Contents.swift +++ b/Linked List/LinkedList.playground/Contents.swift @@ -47,7 +47,7 @@ public class LinkedList { } } - public func nodeAt(index: Int) -> Node? { + public func nodeAt(_ index: Int) -> Node? { if index >= 0 { var node = head var i = index @@ -61,7 +61,7 @@ public class LinkedList { } public subscript(index: Int) -> T { - let node = nodeAt(index: index) + let node = nodeAt(index) assert(node != nil) return node!.value } @@ -132,8 +132,8 @@ public class LinkedList { return remove(node: last!) } - public func removeAt(index: Int) -> T { - let node = nodeAt(index: index) + public func removeAt(_ index: Int) -> T { + let node = nodeAt(index) assert(node != nil) return remove(node: node!) } @@ -211,9 +211,9 @@ list.first!.next!.value // "World" list.last!.previous!.value // "Hello" list.last!.next // nil -list.nodeAt(index: 0)!.value // "Hello" -list.nodeAt(index: 1)!.value // "World" -list.nodeAt(index: 2) // nil +list.nodeAt(0)!.value // "Hello" +list.nodeAt(1)!.value // "World" +list.nodeAt(2) // nil list[0] // "Hello" list[1] // "World" @@ -227,8 +227,8 @@ print(list) list.reverse() // [World, Swift, Hello] -list.nodeAt(index: 0)!.value = "Universe" -list.nodeAt(index: 1)!.value = "Swifty" +list.nodeAt(0)!.value = "Universe" +list.nodeAt(1)!.value = "Swifty" let m = list.map { s in s.characters.count } m // [8, 6, 5] let f = list.filter { s in s.characters.count > 5 } @@ -246,5 +246,5 @@ list.removeLast() // "World" list.count // 1 list[0] // "Swift" -list.removeAt(index: 0) // "Swift" +list.removeAt(0) // "Swift" list.count // 0 diff --git a/Linked List/LinkedList.swift b/Linked List/LinkedList.swift index 8d95c4ac1..306743354 100755 --- a/Linked List/LinkedList.swift +++ b/Linked List/LinkedList.swift @@ -3,7 +3,7 @@ Most operations on the linked list have complexity O(n). */ -public class LinkedListNode { +open class LinkedListNode { var value: T var next: LinkedListNode? weak var previous: LinkedListNode? @@ -13,20 +13,20 @@ public class LinkedListNode { } } -public class LinkedList { +open class LinkedList { public typealias Node = LinkedListNode fileprivate var head: Node? - public var isEmpty: Bool { + open var isEmpty: Bool { return head == nil } - public var first: Node? { + open var first: Node? { return head } - public var last: Node? { + open var last: Node? { if var node = head { while case let next? = node.next { node = next @@ -37,7 +37,7 @@ public class LinkedList { } } - public var count: Int { + open var count: Int { if var node = head { var c = 1 while case let next? = node.next { @@ -50,7 +50,7 @@ public class LinkedList { } } - public func nodeAt(index: Int) -> Node? { + open func nodeAt(_ index: Int) -> Node? { if index >= 0 { var node = head var i = index @@ -63,13 +63,13 @@ public class LinkedList { return nil } - public subscript(index: Int) -> T { - let node = nodeAt(index: index) + open subscript(index: Int) -> T { + let node = nodeAt(index) assert(node != nil) return node!.value } - public func append(value: T) { + open func append(_ value: T) { let newNode = Node(value: value) if let lastNode = last { newNode.previous = lastNode @@ -79,7 +79,7 @@ public class LinkedList { } } - private func nodesBeforeAndAfter(index: Int) -> (Node?, Node?) { + fileprivate func nodesBeforeAndAfter(_ index: Int) -> (Node?, Node?) { assert(index >= 0) var i = index @@ -96,8 +96,8 @@ public class LinkedList { return (prev, next) } - public func insert(value: T, atIndex index: Int) { - let (prev, next) = nodesBeforeAndAfter(index: index) + open func insert(_ value: T, atIndex index: Int) { + let (prev, next) = nodesBeforeAndAfter(index) let newNode = Node(value: value) newNode.previous = prev @@ -110,11 +110,11 @@ public class LinkedList { } } - public func removeAll() { + open func removeAll() { head = nil } - public func remove(node: Node) -> T { + open func remove(_ node: Node) -> T { let prev = node.previous let next = node.next @@ -130,15 +130,15 @@ public class LinkedList { return node.value } - public func removeLast() -> T { + open func removeLast() -> T { assert(!isEmpty) - return remove(node: last!) + return remove(last!) } - public func removeAt(index: Int) -> T { - let node = nodeAt(index: index) + open func removeAt(_ index: Int) -> T { + let node = nodeAt(index) assert(node != nil) - return remove(node: node!) + return remove(node!) } } @@ -167,22 +167,22 @@ extension LinkedList { } extension LinkedList { - public func map(transform: (T)-> U) -> LinkedList { + public func map(_ transform: (T)-> U) -> LinkedList { let result = LinkedList() var node = head while node != nil { - result.append(value: transform(node!.value)) + result.append(transform(node!.value)) node = node!.next } return result } - public func filter(predicate: (T)-> Bool) -> LinkedList { + public func filter(_ predicate: (T)-> Bool) -> LinkedList { let result = LinkedList() var node = head while node != nil { if predicate(node!.value) { - result.append(value: node!.value) + result.append(node!.value) } node = node!.next } diff --git a/Linked List/Tests/LinkedListTests.swift b/Linked List/Tests/LinkedListTests.swift index 4bdc0adae..beba84299 100755 --- a/Linked List/Tests/LinkedListTests.swift +++ b/Linked List/Tests/LinkedListTests.swift @@ -3,7 +3,7 @@ import XCTest class LinkedListTest: XCTestCase { let numbers = [8, 2, 10, 9, 7, 5] - private func buildList() -> LinkedList { + fileprivate func buildList() -> LinkedList { let list = LinkedList() for number in numbers { list.append(number) @@ -88,7 +88,7 @@ class LinkedListTest: XCTestCase { func testNodeAtIndexInEmptyList() { let list = LinkedList() - let node = list.nodeAtIndex(0) + let node = list.nodeAt(0) XCTAssertNil(node) } @@ -96,7 +96,7 @@ class LinkedListTest: XCTestCase { let list = LinkedList() list.append(123) - let node = list.nodeAtIndex(0) + let node = list.nodeAt(0) XCTAssertNotNil(node) XCTAssertEqual(node!.value, 123) XCTAssertTrue(node === list.first) @@ -108,21 +108,21 @@ class LinkedListTest: XCTestCase { let nodeCount = list.count XCTAssertEqual(nodeCount, numbers.count) - XCTAssertNil(list.nodeAtIndex(-1)) - XCTAssertNil(list.nodeAtIndex(nodeCount)) + XCTAssertNil(list.nodeAt(-1)) + XCTAssertNil(list.nodeAt(nodeCount)) - let first = list.nodeAtIndex(0) + let first = list.nodeAt(0) XCTAssertNotNil(first) XCTAssertTrue(first === list.first) XCTAssertEqual(first!.value, numbers[0]) - let last = list.nodeAtIndex(nodeCount - 1) + let last = list.nodeAt(nodeCount - 1) XCTAssertNotNil(last) XCTAssertTrue(last === list.last) XCTAssertEqual(last!.value, numbers[nodeCount - 1]) for i in 0..() list.append(123) - let value = list.removeAtIndex(0) + let value = list.removeAt(0) XCTAssertEqual(value, 123) XCTAssertTrue(list.isEmpty) @@ -181,16 +181,16 @@ class LinkedListTest: XCTestCase { func testRemoveAtIndex() { let list = buildList() - let prev = list.nodeAtIndex(2) - let next = list.nodeAtIndex(3) + let prev = list.nodeAt(2) + let next = list.nodeAt(3) let nodeCount = list.count list.insert(444, atIndex: 3) - let value = list.removeAtIndex(3) + let value = list.removeAt(3) XCTAssertEqual(value, 444) - let node = list.nodeAtIndex(3) + let node = list.nodeAt(3) XCTAssertTrue(next === node) XCTAssertTrue(prev!.next === node) XCTAssertTrue(node!.previous === prev) diff --git a/Linked List/Tests/Tests.xcodeproj/project.pbxproj b/Linked List/Tests/Tests.xcodeproj/project.pbxproj index 7c6a2020a..3a29f5677 100644 --- a/Linked List/Tests/Tests.xcodeproj/project.pbxproj +++ b/Linked List/Tests/Tests.xcodeproj/project.pbxproj @@ -88,6 +88,7 @@ TargetAttributes = { 7B2BBC7F1C779D720067B71D = { CreatedOnToolsVersion = 7.2; + LastSwiftMigration = 0800; }; }; }; @@ -220,6 +221,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -231,6 +233,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Release; }; From 9857da6a63ddfdc22d1246d199a1030bbdfab662 Mon Sep 17 00:00:00 2001 From: Tulio Troncoso Date: Tue, 13 Sep 2016 17:28:12 -0400 Subject: [PATCH 0528/1679] Updated README.md --- Linked List/README.markdown | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/Linked List/README.markdown b/Linked List/README.markdown index e78735350..7b2ec0c0d 100644 --- a/Linked List/README.markdown +++ b/Linked List/README.markdown @@ -216,7 +216,7 @@ It loops through the list in the same manner but this time increments a counter What if we wanted to find the node at a specific index in the list? With an array we can just write `array[index]` and it's an **O(1)** operation. It's a bit more involved with linked lists, but again the code follows a similar pattern: ```swift - public func nodeAtIndex(index: Int) -> Node? { + public func nodeAt(_ index: Int) -> Node? { if index >= 0 { var node = head var i = index @@ -235,16 +235,16 @@ The loop looks a little different but it does the same thing: it starts at `head Try it out: ```swift -list.nodeAtIndex(0)!.value // "Hello" -list.nodeAtIndex(1)!.value // "World" -list.nodeAtIndex(2) // nil +list.nodeAt(0)!.value // "Hello" +list.nodeAt(1)!.value // "World" +list.nodeAt(2) // nil ``` For fun we can implement a `subscript` method too: ```swift public subscript(index: Int) -> T { - let node = nodeAtIndex(index) + let node = nodeAt(index) assert(node != nil) return node!.value } @@ -367,7 +367,7 @@ If you had a tail pointer, you'd set it to `nil` here too. Next we'll add some functions that let you remove individual nodes. If you already have a reference to the node, then using `removeNode()` is the most optimal because you don't need to iterate through the list to find the node first. ```swift - public func removeNode(node: Node) -> T { + public func remove(node: Node) -> T { let prev = node.previous let next = node.next @@ -391,24 +391,24 @@ Don't forget the `head` pointer! If this was the first node in the list then `he Try it out: ```swift -list.removeNode(list.first!) // "Hello" +list.remove(list.first!) // "Hello" list.count // 2 list[0] // "Swift" list[1] // "World" ``` -If you don't have a reference to the node, you can use `removeLast()` or `removeAtIndex()`: +If you don't have a reference to the node, you can use `removeLast()` or `removeAt()`: ```swift public func removeLast() -> T { assert(!isEmpty) - return removeNode(last!) + return remove(node: last!) } - public func removeAtIndex(index: Int) -> T { - let node = nodeAtIndex(index) + public func removeAt(_ index: Int) -> T { + let node = nodeAt(index) assert(node != nil) - return removeNode(node!) + return remove(node: node!) } ``` @@ -419,7 +419,7 @@ list.removeLast() // "World" list.count // 1 list[0] // "Swift" -list.removeAtIndex(0) // "Swift" +list.removeAt(0) // "Swift" list.count // 0 ``` From 5fbcd67b80b1f3295456341e857660e8db160ed8 Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Thu, 15 Sep 2016 18:08:04 -0700 Subject: [PATCH 0529/1679] Converted playground and fixed README for swift 3. --- .../BinaryTree.playground/Contents.swift | 18 +++++++++--------- Binary Tree/README.markdown | 18 +++++++++--------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/Binary Tree/BinaryTree.playground/Contents.swift b/Binary Tree/BinaryTree.playground/Contents.swift index b953b6a71..b35e90c27 100644 --- a/Binary Tree/BinaryTree.playground/Contents.swift +++ b/Binary Tree/BinaryTree.playground/Contents.swift @@ -53,26 +53,26 @@ tree.count // 12 extension BinaryTree { - public func traverseInOrder(@noescape process: T -> Void) { + public func traverseInOrder(process: (T) -> Void) { if case let .Node(left, value, right) = self { - left.traverseInOrder(process) + left.traverseInOrder(process: process) process(value) - right.traverseInOrder(process) + right.traverseInOrder(process: process) } } - public func traversePreOrder(@noescape process: T -> Void) { + public func traversePreOrder(process: (T) -> Void) { if case let .Node(left, value, right) = self { process(value) - left.traversePreOrder(process) - right.traversePreOrder(process) + left.traversePreOrder(process: process) + right.traversePreOrder(process: process) } } - public func traversePostOrder(@noescape process: T -> Void) { + public func traversePostOrder(process: (T) -> Void) { if case let .Node(left, value, right) = self { - left.traversePostOrder(process) - right.traversePostOrder(process) + left.traversePostOrder(process: process) + right.traversePostOrder(process: process) process(value) } } diff --git a/Binary Tree/README.markdown b/Binary Tree/README.markdown index 24498b035..4b5fe7180 100644 --- a/Binary Tree/README.markdown +++ b/Binary Tree/README.markdown @@ -111,26 +111,26 @@ Something you often need to do with trees is traverse them, i.e. look at all the Here is how you'd implement that: ```swift - public func traverseInOrder(@noescape process: T -> Void) { + public func traverseInOrder(process: (T) -> Void) { if case let .Node(left, value, right) = self { - left.traverseInOrder(process) + left.traverseInOrder(process: process) process(value) - right.traverseInOrder(process) + right.traverseInOrder(process: process) } } - public func traversePreOrder(@noescape process: T -> Void) { + public func traversePreOrder(process: (T) -> Void) { if case let .Node(left, value, right) = self { process(value) - left.traversePreOrder(process) - right.traversePreOrder(process) + left.traversePreOrder(process: process) + right.traversePreOrder(process: process) } } - public func traversePostOrder(@noescape process: T -> Void) { + public func traversePostOrder(process: (T) -> Void) { if case let .Node(left, value, right) = self { - left.traversePostOrder(process) - right.traversePostOrder(process) + left.traversePostOrder(process: process) + right.traversePostOrder(process: process) process(value) } } From 68be8b845f00c5c8eb284b46a534e448f69a630a Mon Sep 17 00:00:00 2001 From: Jaap Date: Fri, 16 Sep 2016 14:08:30 +0200 Subject: [PATCH 0530/1679] rbtree implementation --- Red-Black Tree 2/RBTree.swift | Bin 0 -> 1104 bytes Red-Black Tree 2/README.markdown | 10 + .../Contents.swift | 9 + .../Sources/RBTree.swift | 486 ++++++++++++++++++ .../contents.xcplayground | 4 + .../contents.xcworkspacedata | 7 + 6 files changed, 516 insertions(+) create mode 100644 Red-Black Tree 2/RBTree.swift create mode 100644 Red-Black Tree 2/README.markdown create mode 100644 Red-Black Tree 2/Red-Black Tree 2.playground/Contents.swift create mode 100644 Red-Black Tree 2/Red-Black Tree 2.playground/Sources/RBTree.swift create mode 100644 Red-Black Tree 2/Red-Black Tree 2.playground/contents.xcplayground create mode 100644 Red-Black Tree 2/Red-Black Tree 2.playground/playground.xcworkspace/contents.xcworkspacedata diff --git a/Red-Black Tree 2/RBTree.swift b/Red-Black Tree 2/RBTree.swift new file mode 100644 index 0000000000000000000000000000000000000000..0ed831f72932e9675aa57dc32405330ef33285a7 GIT binary patch literal 1104 zcmZ{jzi-n(6vxkL3PtLWv`CEr2@5eGR5zhc+R|2{af}3|FtiC%7stM~R-HJq9idJX z)CqN9U}QjuKY*bdv??1TBNDJNBGCbupyB(RyQD_qN#DEAd-weAr|Z7I$zTmDi2E5Z zDVL^bIzw#`<`);fw9>iV{WAG$k!BsGFbW9ErxXT@&^ zHV@gb{KlXf6Y+E^#ZECs^AL|iwAU)+K~JF<&=8cyzOq-5e8PYDIO+d6h>xe2|8D0v zkzaU{^k-it{kebqdEu+5LhJmD{u}fg8pgR?fX1PDXbGZq(%F~yce8WA9Hii0FcjNG zFq!O$69DGUfL;xnFcoy*0i0 z^jw918KOHanK!3&W7^OruT@M<*9)e0U9U`Q72PP7r)G>|si@2KKca7-@1x0{VpJ=S z{+!@@E4Ae%)3@6V-i&TLXxufI2Y2{Ze=i3(hZ5zZcbaY;*gGR)Y4nE4;>U6W)^+1n z#k|LzPKVY&HU`n(u@`%I|KL?Im;pZ%ya3)2Tm`=sTsy({!FwW}QW=ZHy$yoDig*V6 zLvR*+MdXZthXjv;bAnZHRd4|;>nn$hy_a>s7>aG=kg<;(withArray: array) +tree.insert(5) +tree.insert(8) +tree.insert(2) +tree.delete(6) +tree.delete(8) \ No newline at end of file diff --git a/Red-Black Tree 2/Red-Black Tree 2.playground/Sources/RBTree.swift b/Red-Black Tree 2/Red-Black Tree 2.playground/Sources/RBTree.swift new file mode 100644 index 000000000..c5bcd0a3e --- /dev/null +++ b/Red-Black Tree 2/Red-Black Tree 2.playground/Sources/RBTree.swift @@ -0,0 +1,486 @@ + +private enum RBTColor { + case Red + case Black + case DoubleBlack +} + +public class RBTNode { + fileprivate var color: RBTColor = .Red + public var value: T! = nil + public var right: RBTNode! + public var left: RBTNode! + public var parent: RBTNode! + + init(tree: RBTree) { + right = tree.nullLeaf + left = tree.nullLeaf + parent = tree.nullLeaf + } + + init() { + //This method is here to support the creation of a nullLeaf + } + + public var isLeftChild: Bool { + return self.parent.left === self + } + + public var isRightChild: Bool { + return self.parent.right === self + } + + public var grandparent: RBTNode { + return parent.parent + } + + public var sibling: RBTNode! { + if isLeftChild { + return self.parent.right + } else if isRightChild { + return self.parent.left + } else { + return nil + } + } + + public var uncle: RBTNode { + return parent.sibling + } + + fileprivate var isRed: Bool { + return color == .Red + } + + fileprivate var isBlack: Bool { + return color == .Black + } + + fileprivate var isDoubleBlack: Bool { + return color == .DoubleBlack + } +} + +public class RBTree { + public var root: RBTNode + fileprivate let nullLeaf: RBTNode + + public init() { + nullLeaf = RBTNode() + nullLeaf.color = .Black + root = nullLeaf + } + + public convenience init(withValue value: T) { + self.init() + insert(value) + } + + public convenience init(withArray array: [T]) { + self.init() + insert(array) + } + + public func insert(_ value: T) { + let newNode = RBTNode(tree: self) + newNode.value = value + insertNode(n: newNode) + } + + public func insert(_ values: [T]) { + for value in values { + print(value) + insert(value) + } + } + + public func delete(_ value: T) { + let nodeToDelete = find(value) + if nodeToDelete !== nullLeaf { + deleteNode(n: nodeToDelete) + } + } + + public func find(_ value: T) -> RBTNode { + let foundNode = findNode(rootNode: root, value: value) + return foundNode + } + + public func minimum(n: RBTNode) -> RBTNode { + var min = n + if n.left !== nullLeaf { + min = minimum(n: n.left) + } + + return min + } + + public func maximum(n: RBTNode) -> RBTNode { + var max = n + if n.right !== nullLeaf { + max = maximum(n: n.right) + } + + return max + } + + public func verify() { + if self.root === nullLeaf { + print("The tree is empty") + return + } + property1() + property2(n: self.root) + property3() + } + + private func findNode(rootNode: RBTNode, value: T) -> RBTNode { + var nextNode = rootNode + if rootNode !== nullLeaf && value != rootNode.value { + if value < rootNode.value { + nextNode = findNode(rootNode: rootNode.left, value: value) + } else { + nextNode = findNode(rootNode: rootNode.right, value: value) + } + } + + return nextNode + } + + private func insertNode(n: RBTNode) { + BSTInsertNode(n: n, parent: root) + insertCase1(n: n) + } + + private func BSTInsertNode(n: RBTNode, parent: RBTNode) { + if parent === nullLeaf { + self.root = n + } else if n.value < parent.value { + if parent.left !== nullLeaf { + BSTInsertNode(n: n, parent: parent.left) + } else { + parent.left = n + parent.left.parent = parent + } + } else { + if parent.right !== nullLeaf { + BSTInsertNode(n: n, parent: parent.right) + } else { + parent.right = n + parent.right.parent = parent + } + } + } + + // if node is root change color to black, else move on + private func insertCase1(n: RBTNode) { + if n === root { + n.color = .Black + } else { + insertCase2(n: n) + } + } + + // if parent of node is not black, and node is not root move on + private func insertCase2(n: RBTNode) { + if !n.parent.isBlack { + insertCase3(n: n) + } + } + + // if uncle is red do stuff otherwise move to 4 + private func insertCase3(n: RBTNode) { + if n.uncle.isRed { // node must have grandparent as children of root have a black parent + // both parent and uncle are red, so grandparent must be black. + n.parent.color = .Black + n.uncle.color = .Black + n.grandparent.color = .Red + // now both parent and uncle are black and grandparent is red. + // we repeat for the grandparent + insertCase1(n: n.grandparent) + } else { + insertCase4(n: n) + } + } + + // parent is red, grandparent is black, uncle is black + // There are 4 cases left: + // - left left + // - left right + // - right right + // - right left + + // the cases "left right" and "right left" can be rotated into the other two + // so if either of the two is detected we apply a rotation and then move on to + // deal with the final two cases, if neither is detected we move on to those cases anyway + private func insertCase4(n: RBTNode) { + if n.parent.isLeftChild && n.isRightChild { // left right case + leftRotate(n: n.parent) + insertCase5(n: n.left) + } else if n.parent.isRightChild && n.isLeftChild { // right left case + rightRotate(n: n.parent) + insertCase5(n: n.right) + } + } + + private func insertCase5(n: RBTNode) { + // swap color of parent and grandparent + // parent is red grandparent is black + n.parent.color = .Black + n.grandparent.color = .Red + + if n.isLeftChild { // left left case + rightRotate(n: n.grandparent) + } else { // right right case + leftRotate(n: n.grandparent) + } + } + + private func deleteNode(n: RBTNode) { + var toDel = n + + if toDel.left === nullLeaf && toDel.right === nullLeaf && toDel.parent === nullLeaf { + self.root = nullLeaf + return + } + + if toDel.left === nullLeaf && toDel.right === nullLeaf && toDel.isRed { + if toDel.isLeftChild { + toDel.parent.left = nullLeaf + } else { + toDel.parent.right = nullLeaf + } + return + } + + if toDel.left !== nullLeaf && toDel.right !== nullLeaf { + let pred = maximum(n: toDel.left) + toDel.value = pred.value + toDel = pred + } + + // from here toDel has at most 1 non nullLeaf child + + var child: RBTNode + if toDel.left !== nullLeaf { + child = toDel.left + } else { + child = toDel.right + } + + if toDel.isRed || child.isRed { + child.color = .Black + + if toDel.isLeftChild { + toDel.parent.left = child + } else { + toDel.parent.right = child + } + + if child !== nullLeaf { + child.parent = toDel.parent + } + } else { // both toDel and child are black + + var sibling = toDel.sibling + + if toDel.isLeftChild { + toDel.parent.left = child + } else { + toDel.parent.right = child + } + if child !== nullLeaf { + child.parent = toDel.parent + } + child.color = .DoubleBlack + + while child.isDoubleBlack || (child.parent !== nullLeaf && child.parent != nil) { + if sibling!.isBlack { + + var leftRedChild: RBTNode! = nil + if sibling!.left.isRed { + leftRedChild = sibling!.left + } + var rightRedChild: RBTNode! = nil + if sibling!.right.isRed { + rightRedChild = sibling!.right + } + + if leftRedChild != nil || rightRedChild != nil { // at least one of sibling's children are red + child.color = .Black + if sibling!.isLeftChild { + if leftRedChild != nil { // left left case + sibling!.left.color = .Black + let tempColor = sibling!.parent.color + sibling!.parent.color = sibling!.color + sibling!.color = tempColor + rightRotate(n: sibling!.parent) + } else { // left right case + if sibling!.parent.isRed { + sibling!.parent.color = .Black + } else { + sibling!.right.color = .Black + } + leftRotate(n: sibling!) + rightRotate(n: sibling!.grandparent) + } + } else { + if rightRedChild != nil { // right right case + sibling!.right.color = .Black + let tempColor = sibling!.parent.color + sibling!.parent.color = sibling!.color + sibling!.color = tempColor + leftRotate(n: sibling!.parent) + } else { // right left case + if sibling!.parent.isRed { + sibling!.parent.color = .Black + } else { + sibling!.left.color = .Black + } + rightRotate(n: sibling!) + leftRotate(n: sibling!.grandparent) + } + } + break + } else { // both sibling's children are black + child.color = .Black + sibling!.color = .Red + if sibling!.parent.isRed { + sibling!.parent.color = .Black + break + } + sibling!.parent.color = .DoubleBlack + child = sibling!.parent + sibling = child.sibling + } + } else { // sibling is red + sibling!.color = .Black + + if sibling!.isLeftChild { // left case + rightRotate(n: sibling!.parent) + sibling = sibling!.right.left + sibling!.parent.color = .Red + } else { // right case + leftRotate(n: sibling!.parent) + sibling = sibling!.left.right + sibling!.parent.color = .Red + } + } + + // sibling check is here for when child is a nullLeaf and thus does not have a parent. + // child is here as sibling can become nil when child is the root + if (sibling != nil && sibling!.parent === nullLeaf) || (child !== nullLeaf && child.parent === nullLeaf) { + child.color = .Black + } + } + } + } + + private func property1() { + + if self.root.isRed { + print("Root is not black") + } + } + + private func property2(n: RBTNode) { + if n === nullLeaf { + return + } + if n.isRed { + if n.left !== nullLeaf && n.left.isRed { + print("Red node: \(n.value), has red left child") + } else if n.right !== nullLeaf && n.right.isRed { + print("Red node: \(n.value), has red right child") + } + } + property2(n: n.left) + property2(n: n.right) + } + + private func property3() { + let bDepth = blackDepth(root: self.root) + + let leaves:[RBTNode] = getLeaves(n: self.root) + + for leaflet in leaves { + var leaf = leaflet + var i = 0 + + while leaf !== nullLeaf { + if leaf.isBlack { + i = i + 1 + } + leaf = leaf.parent + } + + if i != bDepth { + print("black depth: \(bDepth), is not equal (depth: \(i)) for leaf with value: \(leaflet.value)") + } + } + + } + + private func getLeaves(n: RBTNode) -> [RBTNode] { + var leaves = [RBTNode]() + + if n !== nullLeaf { + if n.left === nullLeaf && n.right === nullLeaf { + leaves.append(n) + } else { + let leftLeaves = getLeaves(n: n.left) + let rightLeaves = getLeaves(n: n.right) + + leaves.append(contentsOf: leftLeaves) + leaves.append(contentsOf: rightLeaves) + } + } + + return leaves + } + + private func blackDepth(root: RBTNode) -> Int { + if root === nullLeaf { + return 0 + } else { + let returnValue = root.isBlack ? 1 : 0 + return returnValue + (max(blackDepth(root: root.left), blackDepth(root: root.right))) + } + } + + private func leftRotate(n: RBTNode) { + let newRoot = n.right! + n.right = newRoot.left! + if newRoot.left !== nullLeaf { + newRoot.left.parent = n + } + newRoot.parent = n.parent + if n.parent === nullLeaf { + self.root = newRoot + } else if n.isLeftChild { + n.parent.left = newRoot + } else { + n.parent.right = newRoot + } + newRoot.left = n + n.parent = newRoot + } + + private func rightRotate(n: RBTNode) { + let newRoot = n.left! + n.left = newRoot.right! + if newRoot.right !== nullLeaf { + newRoot.right.parent = n + } + newRoot.parent = n.parent + if n.parent === nullLeaf { + self.root = newRoot + } else if n.isRightChild { + n.parent.right = newRoot + } else { + n.parent.left = newRoot + } + newRoot.right = n + n.parent = newRoot + } +} diff --git a/Red-Black Tree 2/Red-Black Tree 2.playground/contents.xcplayground b/Red-Black Tree 2/Red-Black Tree 2.playground/contents.xcplayground new file mode 100644 index 000000000..5da2641c9 --- /dev/null +++ b/Red-Black Tree 2/Red-Black Tree 2.playground/contents.xcplayground @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Red-Black Tree 2/Red-Black Tree 2.playground/playground.xcworkspace/contents.xcworkspacedata b/Red-Black Tree 2/Red-Black Tree 2.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Red-Black Tree 2/Red-Black Tree 2.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + From 7f94c350ab439aeeaecec3eabe365b3d127934df Mon Sep 17 00:00:00 2001 From: "Glenn R. Fisher" Date: Sat, 17 Sep 2016 11:54:48 -0500 Subject: [PATCH 0531/1679] Update hash table for Swift 3.0 --- .../HashTable.playground/Contents.swift | 115 ++----------- .../Sources/HashTable.swift | 153 +++++++++++++++++ .../HashTable.playground/timeline.xctimeline | 6 - Hash Table/HashTable.swift | 159 ------------------ Hash Table/README.markdown | 41 +++-- .../contents.xcworkspacedata | 3 - 6 files changed, 182 insertions(+), 295 deletions(-) create mode 100644 Hash Table/HashTable.playground/Sources/HashTable.swift delete mode 100644 Hash Table/HashTable.playground/timeline.xctimeline delete mode 100644 Hash Table/HashTable.swift diff --git a/Hash Table/HashTable.playground/Contents.swift b/Hash Table/HashTable.playground/Contents.swift index cda0919de..121fb6032 100644 --- a/Hash Table/HashTable.playground/Contents.swift +++ b/Hash Table/HashTable.playground/Contents.swift @@ -1,129 +1,34 @@ //: Playground - noun: a place where people can play -public struct HashTable { - private typealias Element = (key: Key, value: Value) - private typealias Bucket = [Element] - - private var buckets: [Bucket] - private(set) var count = 0 - - public init(capacity: Int) { - assert(capacity > 0) - buckets = .init(count: capacity, repeatedValue: []) - } - - public var isEmpty: Bool { - return count == 0 - } - - private func indexForKey(key: Key) -> Int { - return abs(key.hashValue) % buckets.count - } -} - -extension HashTable { - public subscript(key: Key) -> Value? { - get { - return valueForKey(key) - } - set { - if let value = newValue { - updateValue(value, forKey: key) - } else { - removeValueForKey(key) - } - } - } - - public func valueForKey(key: Key) -> Value? { - let index = indexForKey(key) - - for element in buckets[index] { - if element.key == key { - return element.value - } - } - return nil // key not in hash table - } - - public mutating func updateValue(value: Value, forKey key: Key) -> Value? { - let index = indexForKey(key) - - // Do we already have this key in the bucket? - for (i, element) in buckets[index].enumerate() { - if element.key == key { - let oldValue = element.value - buckets[index][i].value = value - return oldValue - } - } - - // This key isn't in the bucket yet; add it to the chain. - buckets[index].append((key: key, value: value)) - count += 1 - return nil - } - - public mutating func removeValueForKey(key: Key) -> Value? { - let index = indexForKey(key) - - // Find the element in the bucket's chain and remove it. - for (i, element) in buckets[index].enumerate() { - if element.key == key { - buckets[index].removeAtIndex(i) - count -= 1 - return element.value - } - } - return nil // key not in hash table - } - - public mutating func removeAll() { - buckets = .init(count: buckets.count, repeatedValue: []) - count = 0 - } -} - -extension HashTable: CustomStringConvertible { - public var description: String { - return buckets.flatMap { b in b.map { e in "\(e.key) = \(e.value)" } }.joinWithSeparator(", ") - } -} - -extension HashTable: CustomDebugStringConvertible { - public var debugDescription: String { - var s = "" - for (i, bucket) in buckets.enumerate() { - s += "bucket \(i): " + bucket.map { e in "\(e.key) = \(e.value)" }.joinWithSeparator(", ") + "\n" - } - return s - } -} - - - // Playing with hash values + "firstName".hashValue abs("firstName".hashValue) % 5 + "lastName".hashValue abs("lastName".hashValue) % 5 + "hobbies".hashValue abs("hobbies".hashValue) % 5 - - // Playing with the hash table + var hashTable = HashTable(capacity: 5) hashTable["firstName"] = "Steve" hashTable["lastName"] = "Jobs" hashTable["hobbies"] = "Programming Swift" -hashTable.description +print(hashTable) print(hashTable.debugDescription) let x = hashTable["firstName"] hashTable["firstName"] = "Tim" + let y = hashTable["firstName"] hashTable["firstName"] = nil + let z = hashTable["firstName"] + +print(hashTable) +print(hashTable.debugDescription) diff --git a/Hash Table/HashTable.playground/Sources/HashTable.swift b/Hash Table/HashTable.playground/Sources/HashTable.swift new file mode 100644 index 000000000..947737c32 --- /dev/null +++ b/Hash Table/HashTable.playground/Sources/HashTable.swift @@ -0,0 +1,153 @@ +/* + Hash Table: A symbol table of generic key-value pairs. + + The key must be `Hashable`, which means it can be transformed into a fairly + unique integer value. The more unique the hash value, the better. + + Hash tables use an internal array of buckets to store key-value pairs. The + hash table's capacity is determined by the number of buckets. This + implementation has a fixed capacity--it does not resize the array as more + key-value pairs are inserted. + + To insert or locate a particular key-value pair, a hash function transforms the + key into an array index. An ideal hash function would guarantee that different + keys map to different indices. In practice, however, this is difficult to + achieve. + + Since different keys can map to the same array index, all hash tables implement + a collision resolution strategy. This implementation uses a strategy called + separate chaining, where key-value pairs that hash to the same index are + "chained together" in a list. For good performance, the capacity of the hash + table should be sufficiently large so that the lists are small. + + A well-sized hash table provides very good average performance. In the + worst-case, however, all keys map to the same bucket, resulting in a list that + that requires O(n) time to traverse. + + Average Worst-Case + Space: O(n) O(n) + Search: O(1) O(n) + Insert: O(1) O(n) + Delete: O(1) O(n) + */ +public struct HashTable: CustomStringConvertible { + private typealias Element = (key: Key, value: Value) + private typealias Bucket = [Element] + private var buckets: [Bucket] + + /// The number of key-value pairs in the hash table. + private(set) public var count = 0 + + /// A Boolean value that indicates whether the hash table is empty. + public var isEmpty: Bool { return count == 0 } + + /// A string that represents the contents of the hash table. + public var description: String { + let pairs = buckets.flatMap { b in b.map { e in "\(e.key) = \(e.value)" } } + return pairs.joined(separator: ", ") + } + + /// A string that represents the contents of + /// the hash table, suitable for debugging. + public var debugDescription: String { + var str = "" + for (i, bucket) in buckets.enumerated() { + let pairs = bucket.map { e in "\(e.key) = \(e.value)" } + str += "bucket \(i): " + pairs.joined(separator: ", ") + "\n" + } + return str + } + + /** + Create a hash table with the given capacity. + */ + public init(capacity: Int) { + assert(capacity > 0) + buckets = Array(repeatElement([], count: capacity)) + } + + /** + Accesses the value associated with + the given key for reading and writing. + */ + public subscript(key: Key) -> Value? { + get { + return value(forKey: key) + } + set { + if let value = newValue { + updateValue(value, forKey: key) + } else { + removeValue(forKey: key) + } + } + } + + /** + Returns the value for the given key. + */ + public func value(forKey key: Key) -> Value? { + let index = self.index(forKey: key) + for element in buckets[index] { + if element.key == key { + return element.value + } + } + return nil // key not in hash table + } + + /** + Updates the value stored in the hash table for the given key, + or adds a new key-value pair if the key does not exist. + */ + @discardableResult public mutating func updateValue(_ value: Value, forKey key: Key) -> Value? { + let index = self.index(forKey: key) + + // Do we already have this key in the bucket? + for (i, element) in buckets[index].enumerated() { + if element.key == key { + let oldValue = element.value + buckets[index][i].value = value + return oldValue + } + } + + // This key isn't in the bucket yet; add it to the chain. + buckets[index].append((key: key, value: value)) + count += 1 + return nil + } + + /** + Removes the given key and its + associated value from the hash table. + */ + @discardableResult public mutating func removeValue(forKey key: Key) -> Value? { + let index = self.index(forKey: key) + + // Find the element in the bucket's chain and remove it. + for (i, element) in buckets[index].enumerated() { + if element.key == key { + buckets[index].remove(at: i) + count -= 1 + return element.value + } + } + return nil // key not in hash table + } + + /** + Removes all key-value pairs from the hash table. + */ + public mutating func removeAll() { + buckets = Array(repeatElement([], count: buckets.count)) + count = 0 + } + + /** + Returns the given key's array index. + */ + private func index(forKey key: Key) -> Int { + return abs(key.hashValue) % buckets.count + } +} diff --git a/Hash Table/HashTable.playground/timeline.xctimeline b/Hash Table/HashTable.playground/timeline.xctimeline deleted file mode 100644 index bf468afec..000000000 --- a/Hash Table/HashTable.playground/timeline.xctimeline +++ /dev/null @@ -1,6 +0,0 @@ - - - - - diff --git a/Hash Table/HashTable.swift b/Hash Table/HashTable.swift deleted file mode 100644 index 46c73e284..000000000 --- a/Hash Table/HashTable.swift +++ /dev/null @@ -1,159 +0,0 @@ -/* - Hash table - - Allows you to store and retrieve objects by a "key". - - The key must be Hashable, which means it can be converted into a fairly - unique Int that represents the key as a number. The more unique the hash - value, the better. - - The hashed version of the key is used to calculate an index into the array - of "buckets". The capacity of the hash table is how many of these buckets - it has. Ideally, the number of buckets is the same as the maximum number of - items you'll be storing in the HashTable, and each hash value maps to its - own bucket. In practice that is hard to achieve. - - When there is more than one hash value that maps to the same bucket index - -- a "collision" -- they are chained together, using an array. (Note that - more clever ways exist for dealing with the chaining issue.) - - While there are free buckets, inserting/retrieving/removing are O(1). - But when the buckets are full and the chains are long, using the hash table - becomes an O(n) operation. - - Counting the size of the hash table is O(1) because we're caching the count. - - The order of the elements in the hash table is undefined. - - This implementation has a fixed capacity; it does not resize when the table - gets too full. (To do that, you'd allocate a larger array of buckets and then - insert each of the elements into that new array; this is necessary because - the hash values will now map to different bucket indexes.) -*/ -public struct HashTable { - private typealias Element = (key: Key, value: Value) - private typealias Bucket = [Element] - - private var buckets: [Bucket] - private(set) var count = 0 - - public init(capacity: Int) { - assert(capacity > 0) - buckets = .init(count: capacity, repeatedValue: []) - } - - public var isEmpty: Bool { - return count == 0 - } - - private func indexForKey(key: Key) -> Int { - return abs(key.hashValue) % buckets.count - } -} - -// MARK: - Basic operations - -extension HashTable { - public subscript(key: Key) -> Value? { - get { - return valueForKey(key) - } - set { - if let value = newValue { - updateValue(value, forKey: key) - } else { - removeValueForKey(key) - } - } - } - - public func valueForKey(key: Key) -> Value? { - let index = indexForKey(key) - - for element in buckets[index] { - if element.key == key { - return element.value - } - } - return nil // key not in hash table - } - - public mutating func updateValue(value: Value, forKey key: Key) -> Value? { - let index = indexForKey(key) - - // Do we already have this key in the bucket? - for (i, element) in buckets[index].enumerate() { - if element.key == key { - let oldValue = element.value - buckets[index][i].value = value - return oldValue - } - } - - // This key isn't in the bucket yet; add it to the chain. - buckets[index].append((key: key, value: value)) - count += 1 - return nil - } - - public mutating func removeValueForKey(key: Key) -> Value? { - let index = indexForKey(key) - - // Find the element in the bucket's chain and remove it. - for (i, element) in buckets[index].enumerate() { - if element.key == key { - buckets[index].removeAtIndex(i) - count -= 1 - return element.value - } - } - return nil // key not in hash table - } - - public mutating func removeAll() { - buckets = .init(count: buckets.count, repeatedValue: []) - count = 0 - } -} - -// MARK: - Helper methods for inspecting the hash table - -extension HashTable { - public var keys: [Key] { - var a = [Key]() - for bucket in buckets { - for element in bucket { - a.append(element.key) - } - } - return a - } - - public var values: [Value] { - var a = [Value]() - for bucket in buckets { - for element in bucket { - a.append(element.value) - } - } - return a - } -} - -// MARK: - For debugging - -extension HashTable: CustomStringConvertible { - public var description: String { - return buckets.flatMap { b in b.map { e in "\(e.key) = \(e.value)" } }.joinWithSeparator(", ") - } -} - -extension HashTable: CustomDebugStringConvertible { - public var debugDescription: String { - var s = "" - for (i, bucket) in buckets.enumerate() { - s += "bucket \(i): " + bucket.map { e in "\(e.key) = \(e.value)" }.joinWithSeparator(", ") + "\n" - } - return s - } -} diff --git a/Hash Table/README.markdown b/Hash Table/README.markdown index 02a2c9578..4399b0f86 100644 --- a/Hash Table/README.markdown +++ b/Hash Table/README.markdown @@ -115,17 +115,15 @@ Let's look at a basic implementation of a hash table in Swift. We'll build it up public struct HashTable { private typealias Element = (key: Key, value: Value) private typealias Bucket = [Element] - private var buckets: [Bucket] - private(set) var count = 0 + + private(set) public var count = 0 + public var isEmpty: Bool { return count == 0 } + public init(capacity: Int) { assert(capacity > 0) - buckets = .init(count: capacity, repeatedValue: []) - } - - public var isEmpty: Bool { - return count == 0 + buckets = Array(repeatElement([], count: capacity)) } ``` @@ -142,7 +140,7 @@ var hashTable = HashTable(capacity: 5) Currently the hash table doesn't do anything yet, so let's add the remaining functionality. First, add a helper method that calculates the array index for a given key: ```swift - private func indexForKey(key: Key) -> Int { + private func index(forKey key: Key) -> Int { return abs(key.hashValue) % buckets.count } ``` @@ -170,24 +168,23 @@ We can do all these things with a `subscript` function: ```swift public subscript(key: Key) -> Value? { get { - return valueForKey(key) + return value(forKey: key) } set { if let value = newValue { updateValue(value, forKey: key) } else { - removeValueForKey(key) + removeValue(forKey: key) } } } ``` -This calls three helper functions to do the actual work. Let's take a look at `valueForKey()` first, which retrieves an object from the hash table. +This calls three helper functions to do the actual work. Let's take a look at `value(forKey:)` first, which retrieves an object from the hash table. ```swift - public func valueForKey(key: Key) -> Value? { - let index = indexForKey(key) - + public func value(forKey key: Key) -> Value? { + let index = self.index(forKey: key) for element in buckets[index] { if element.key == key { return element.value @@ -197,13 +194,13 @@ This calls three helper functions to do the actual work. Let's take a look at `v } ``` -First it calls `indexForKey()` to convert the key into an array index. That gives us the bucket number, but if there were collisions this bucket may be used by more than one key. So `valueForKey()` loops through the chain from that bucket and compares the keys one-by-one. If found, it returns the corresponding value, otherwise it returns `nil`. +First it calls `index(forKey:)` to convert the key into an array index. That gives us the bucket number, but if there were collisions this bucket may be used by more than one key. So `value(forKey:)` loops through the chain from that bucket and compares the keys one-by-one. If found, it returns the corresponding value, otherwise it returns `nil`. -The code to insert a new element or update an existing element lives in `updateValue(forKey)`. It's a little bit more complicated: +The code to insert a new element or update an existing element lives in `updateValue(_:forKey:)`. It's a little bit more complicated: ```swift - public mutating func updateValue(value: Value, forKey key: Key) -> Value? { - let index = indexForKey(key) + public mutating func updateValue(_ value: Value, forKey key: Key) -> Value? { + let index = self.index(forKey: key) // Do we already have this key in the bucket? for (i, element) in buckets[index].enumerate() { @@ -228,13 +225,13 @@ As you can see, it's important that chains are kept short (by making the hash ta Removing is similar in that again it loops through the chain: ```swift - public mutating func removeValueForKey(key: Key) -> Value? { - let index = indexForKey(key) + public mutating func removeValue(forKey key: Key) -> Value? { + let index = self.index(forKey: key) // Find the element in the bucket's chain and remove it. - for (i, element) in buckets[index].enumerate() { + for (i, element) in buckets[index].enumerated() { if element.key == key { - buckets[index].removeAtIndex(i) + buckets[index].remove(at: i) count -= 1 return element.value } diff --git a/swift-algorithm-club.xcworkspace/contents.xcworkspacedata b/swift-algorithm-club.xcworkspace/contents.xcworkspacedata index 4e0f19dc2..e7288f299 100644 --- a/swift-algorithm-club.xcworkspace/contents.xcworkspacedata +++ b/swift-algorithm-club.xcworkspace/contents.xcworkspacedata @@ -868,9 +868,6 @@ - - From 8aeacb054d85a3024675fb0985e369a1e01add86 Mon Sep 17 00:00:00 2001 From: Mike Taghavi Date: Sat, 17 Sep 2016 23:55:39 +0200 Subject: [PATCH 0532/1679] New style / Broken down into extensions --- Skip-List/SkipList.swift | 409 +++++++++++++++++++++------------------ 1 file changed, 218 insertions(+), 191 deletions(-) diff --git a/Skip-List/SkipList.swift b/Skip-List/SkipList.swift index b07cd98c8..31b4e9144 100644 --- a/Skip-List/SkipList.swift +++ b/Skip-List/SkipList.swift @@ -26,241 +26,268 @@ import Foundation // Stack from : https://github.com/raywenderlich/swift-algorithm-club/tree/master/Stack public struct Stack { - private var array = [T]() + fileprivate var array = [T]() - public var isEmpty: Bool { - return array.isEmpty - } + public var isEmpty: Bool { + return array.isEmpty + } - public var count: Int { - return array.count - } + public var count: Int { + return array.count + } - public mutating func push(element: T) { - array.append(element) - } + public mutating func push(_ element: T) { + array.append(element) + } - public mutating func pop() -> T? { - return array.popLast() - } + public mutating func pop() -> T? { + return array.popLast() + } - public func peek() -> T? { - return array.last - } + public func peek() -> T? { + return array.last + } } -extension Stack: SequenceType { - public func generate() -> AnyGenerator { - var curr = self - return AnyGenerator { - _ -> T? in - return curr.pop() - } - } +extension Stack: Sequence { + public func makeIterator() -> AnyIterator { + var curr = self + return AnyIterator { + _ -> T? in + return curr.pop() + } + } } -func random() -> Bool { - #if os(Linux) - return random() % 2 == 0 - #elseif os(OSX) - return arc4random_uniform(2) == 1 - #endif +private func coinFlip() -> Bool { + #if os(Linux) + return random() % 2 == 0 + #elseif os(OSX) + return arc4random_uniform(2) == 1 + #endif } +// MARK: - Node + +public class DataNode { + public typealias Node = DataNode + + var data : Payload? + fileprivate var key : Key? + internal var next : Node? + internal var down : Node? + + public init(key: Key, data: Payload) { + self.key = key + self.data = data + } + + public init(asHead head: Bool){ + } + +} -class DataNode{ - internal typealias Node = DataNode - - internal var key : Key? - internal var data : Payload? - internal var _next : Node? - internal var _down : Node? - - internal var next: Node? { - get { return self._next } - set(value) { self._next = value } - } - internal var down:Node? { - get { return self._down } - set(value) { self._down = value } - } - - init(key:Key, data:Payload){ - self.key = key - self.data = data - } +// MARK: - Skip List - init(header: Bool){ - } - +open class SkipList { + public typealias Node = DataNode + + fileprivate(set) var head: Node? + + public init() { } + } -class SkipList{ - internal typealias Node = DataNode - internal var head: Node? - - private func find_head(key:Key) -> Node? { - var current = self.head - var found: Bool = false - - while !found { - if let curr = current { - if curr.next == nil { current = curr.down } - else { - if curr.next!.key == key { found = true } - else { - if key < curr.next!.key{ current = curr.down } - else { current = curr.next } - } - } + +// MARK: - Searching + +extension SkipList { + + internal func findNode(key: Key) -> Node? { + var currentNode : Node? = self.head + var isFound : Bool = false + + while !isFound { + if let node = currentNode { + + switch node.next { + case .none: + + currentNode = node.down + case .some(let value) where value.key != nil: + + if value.key == key { + isFound = true + break + } + else { + if key < value.key! { + currentNode = node.down } else { - break - } + currentNode = node.next + } + } + + default: + continue } + + } else { + break + } + } - if found { - return current - } else { - return nil - } + if isFound { + return currentNode + } else { + return nil } + } - private func insert_head(key:Key, data:Payload) -> Void { - - self.head = Node(header: true) - var temp = Node(key:key, data:data) - self.head!.next = temp - var top = temp - - while random() { - let newhead = Node(header: true) - temp = Node(key:key, data:data) - temp.down = top - newhead.next = temp - newhead.down = self.head - self.head = newhead - top = temp - } + internal func search(key: Key) -> Payload? { + guard let node = self.findNode(key: key) else { + return nil } - private func insert_rest(key:Key, data:Payload) -> Void { - var stack = Stack() - var current_head: Node? = self.head + return node.next!.data + } + +} + - while current_head != nil { - if let next = current_head!._next { - if next.key > key { - stack.push(current_head!) - current_head = next - } else { - current_head = next - } - - } else { - stack.push(current_head!) - current_head = current_head!.down - } - - } - - let lowest = stack.pop() - var temp = Node(key:key, data:data) - temp.next = lowest!.next - lowest!.next = temp - var top = temp - - while random() { - if stack.isEmpty { - let newhead = Node(header: true) - temp = Node(key:key, data:data) - temp.down = top - newhead.next = temp - newhead.down = self.head - self.head = newhead - top = temp - } else { - let next = stack.pop() - temp = Node(key:key, data:data) - temp.down = top - temp.next = next!.next - next!.next = temp - top = temp - } - } - } - - func search(key:Key) -> Payload? { - guard let item = self.find_head(key) else { - return nil - } +// MARK: - Inserting + +extension SkipList { + private func bootstrapBaseLayer(key: Key, data: Payload) -> Void { + self.head = Node(asHead: true) + var node = Node(key: key, data: data) - return item.next!.data + self.head!.next = node + + var currentTopNode = node + + while coinFlip() { + let newHead = Node(asHead: true) + node = Node(key: key, data: data) + node.down = currentTopNode + newHead.next = node + newHead.down = self.head + self.head = newHead + currentTopNode = node } - func remove(key:Key) -> Void { - guard let item = self.find_head(key) else { - return + } + + + private func insertItem(key: Key, data: Payload) -> Void { + var stack = Stack() + var currentNode: Node? = self.head + + while currentNode != nil { + + if let nextNode = currentNode!.next { + if nextNode.key! > key { + stack.push(currentNode!) + currentNode = currentNode!.down + } else { + currentNode = nextNode } - var curr = Optional(item) + } else { + stack.push(currentNode!) + currentNode = currentNode!.down + } + + } + + let itemAtLayer = stack.pop() + var node = Node(key: key, data: data) + node.next = itemAtLayer!.next + itemAtLayer!.next = node + var currentTopNode = node + + while coinFlip() { + if stack.isEmpty { + let newHead = Node(asHead: true) - while curr != nil { - let node = curr!.next - - if node!.key != key { curr = node ; continue } - - let node_next = node!.next - curr!.next = node_next - curr = curr!.down - - } + node = Node(key: key, data: data) + node.down = currentTopNode + newHead.next = node + newHead.down = self.head + self.head = newHead + currentTopNode = node - } - - func insert(key: Key, data:Payload){ - if self.head != nil{ - if let node = self.find_head(key) { - - var curr = node.next - while curr != nil && curr!.key == key{ - curr!.data = data - curr = curr!.down - } - - } else { - self.insert_rest(key, data:data) - } - - } else { - self.insert_head(key, data:data) + } else { + let nextNode = stack.pop() + + node = Node(key: key, data: data) + node.down = currentTopNode + node.next = nextNode!.next + nextNode!.next = node + currentTopNode = node + } + } + } + + + internal func insert(key: Key, data: Payload) { + if self.head != nil { + if let node = self.findNode(key: key) { + // replace in case key already exists + var currentNode = node.next + while currentNode != nil && currentNode!.key == key { + currentNode!.data = data + currentNode = currentNode!.down } + } else { + self.insertItem(key: key, data: data) + } + + } else { + self.bootstrapBaseLayer(key: key, data: data) } - + } + } -class Map{ - var collection: SkipList +// MARK: - Removing - init(){ - self.collection = SkipList() +extension SkipList { + public func remove(key: Key) -> Void { + guard let item = self.findNode(key: key) else { + return } - func insert(key:Key, data: Payload){ - self.collection.insert(key, data:data) - } - - func get(key:Key) -> Payload?{ - return self.collection.search(key) - } + var currentNode = Optional(item) - func remove(key:Key) -> Void { - return self.collection.remove(key) + while currentNode != nil { + let node = currentNode!.next + + if node!.key != key { + currentNode = node + continue + } + + let nextNode = node!.next + + currentNode!.next = nextNode + currentNode = currentNode!.down + } + + } +} + +extension SkipList { + + public func get(key:Key) -> Payload?{ + return self.search(key: key) + } } From e9ce16b8e3328671537daf3c93e7510fb56458ab Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Sat, 17 Sep 2016 18:00:29 -0700 Subject: [PATCH 0533/1679] Fixes syntax in playground for Swift3. --- Quicksort/Quicksort.playground/Contents.swift | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Quicksort/Quicksort.playground/Contents.swift b/Quicksort/Quicksort.playground/Contents.swift index 0894ae61b..da02b69ce 100644 --- a/Quicksort/Quicksort.playground/Contents.swift +++ b/Quicksort/Quicksort.playground/Contents.swift @@ -5,7 +5,7 @@ import Foundation // *** Simple but inefficient version of quicksort *** -func quicksort(a: [T]) -> [T] { +func quicksort(_ a: [T]) -> [T] { guard a.count > 1 else { return a } let pivot = a[a.count/2] @@ -34,7 +34,7 @@ quicksort(list1) partition is [low...p-1]; the right partition is [p+1...high], where p is the return value. */ -func partitionLomuto(inout a: [T], low: Int, high: Int) -> Int { +func partitionLomuto(_ a: inout [T], low: Int, high: Int) -> Int { let pivot = a[high] var i = low @@ -53,7 +53,7 @@ var list2 = [ 10, 0, 3, 9, 2, 14, 26, 27, 1, 5, 8, -1, 8 ] partitionLomuto(&list2, low: 0, high: list2.count - 1) list2 -func quicksortLomuto(inout a: [T], low: Int, high: Int) { +func quicksortLomuto(_ a: inout [T], low: Int, high: Int) { if low < high { let p = partitionLomuto(&a, low: low, high: high) quicksortLomuto(&a, low: low, high: p - 1) @@ -75,7 +75,7 @@ quicksortLomuto(&list2, low: 0, high: list2.count - 1) where p is the return value. The pivot value is placed somewhere inside one of the two partitions, but the algorithm doesn't tell you which one or where. */ -func partitionHoare(inout a: [T], low: Int, high: Int) -> Int { +func partitionHoare(_ a: inout [T], low: Int, high: Int) -> Int { let pivot = a[low] var i = low - 1 var j = high + 1 @@ -96,7 +96,7 @@ var list3 = [ 8, 0, 3, 9, 2, 14, 10, 27, 1, 5, 8, -1, 26 ] partitionHoare(&list3, low: 0, high: list3.count - 1) list3 -func quicksortHoare(inout a: [T], low: Int, high: Int) { +func quicksortHoare(_ a: inout [T], low: Int, high: Int) { if low < high { let p = partitionHoare(&a, low: low, high: high) quicksortHoare(&a, low: low, high: p) @@ -111,12 +111,12 @@ quicksortHoare(&list3, low: 0, high: list3.count - 1) // *** Randomized sorting *** /* Returns a random integer in the range min...max, inclusive. */ -public func random(min min: Int, max: Int) -> Int { +public func random(min: Int, max: Int) -> Int { assert(min < max) return min + Int(arc4random_uniform(UInt32(max - min + 1))) } -func quicksortRandom(inout a: [T], low: Int, high: Int) { +func quicksortRandom(_ a: inout [T], low: Int, high: Int) { if low < high { let pivotIndex = random(min: low, max: high) (a[pivotIndex], a[high]) = (a[high], a[pivotIndex]) @@ -139,7 +139,7 @@ list4 Swift's swap() doesn't like it if the items you're trying to swap refer to the same memory location. This little wrapper simply ignores such swaps. */ -public func swap(inout a: [T], _ i: Int, _ j: Int) { +public func swap(_ a: inout [T], _ i: Int, _ j: Int) { if i != j { swap(&a[i], &a[j]) } @@ -149,7 +149,7 @@ public func swap(inout a: [T], _ i: Int, _ j: Int) { Dutch national flag partitioning. Returns a tuple with the start and end index of the middle area. */ -func partitionDutchFlag(inout a: [T], low: Int, high: Int, pivotIndex: Int) -> (Int, Int) { +func partitionDutchFlag(_ a: inout [T], low: Int, high: Int, pivotIndex: Int) -> (Int, Int) { let pivot = a[pivotIndex] var smaller = low @@ -175,7 +175,7 @@ var list5 = [ 10, 0, 3, 9, 2, 14, 8, 27, 1, 5, 8, -1, 26 ] partitionDutchFlag(&list5, low: 0, high: list5.count - 1, pivotIndex: 10) list5 -func quicksortDutchFlag(inout a: [T], low: Int, high: Int) { +func quicksortDutchFlag(_ a: inout [T], low: Int, high: Int) { if low < high { let pivotIndex = random(min: low, max: high) let (p, q) = partitionDutchFlag(&a, low: low, high: high, pivotIndex: pivotIndex) From 35cca84d481a6b20dacbc196b68e0db0d7925594 Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Sat, 17 Sep 2016 18:04:17 -0700 Subject: [PATCH 0534/1679] Changed README to reflect Swift 3 migration. --- Quicksort/README.markdown | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Quicksort/README.markdown b/Quicksort/README.markdown index 936f9f44c..e3d284333 100644 --- a/Quicksort/README.markdown +++ b/Quicksort/README.markdown @@ -7,7 +7,7 @@ Quicksort is one of the most famous algorithms in history. It was invented way b Here's an implementation in Swift that should be easy to understand: ```swift -func quicksort(a: [T]) -> [T] { +func quicksort(_ a: [T]) -> [T] { guard a.count > 1 else { return a } let pivot = a[a.count/2] @@ -131,7 +131,7 @@ In the first example of quicksort I showed you, partitioning was done by calling Here's an implementation of Lomuto's partitioning scheme in Swift: ```swift -func partitionLomuto(inout a: [T], low: Int, high: Int) -> Int { +func partitionLomuto(_ a: inout [T], low: Int, high: Int) -> Int { let pivot = a[high] var i = low @@ -250,7 +250,7 @@ And we return `i`, the index of the pivot element. Let's use this partitioning scheme to build quicksort. Here's the code: ```swift -func quicksortLomuto(inout a: [T], low: Int, high: Int) { +func quicksortLomuto(_ a: inout [T], low: Int, high: Int) { if low < high { let p = partitionLomuto(&a, low: low, high: high) quicksortLomuto(&a, low: low, high: p - 1) @@ -277,7 +277,7 @@ This partitioning scheme is by Hoare, the inventor of quicksort. Here is the code: ```Swift -func partitionHoare(inout a: [T], low: Int, high: Int) -> Int { +func partitionHoare(_ a: inout [T], low: Int, high: Int) -> Int { let pivot = a[low] var i = low - 1 var j = high + 1 @@ -318,7 +318,7 @@ The pivot is placed somewhere inside one of the two partitions, but the algorith Because of these differences, the implementation of Hoare's quicksort is slightly different: ```swift -func quicksortHoare(inout a: [T], low: Int, high: Int) { +func quicksortHoare(_ a: inout [T], low: Int, high: Int) { if low < high { let p = partitionHoare(&a, low: low, high: high) quicksortHoare(&a, low: low, high: p) @@ -380,7 +380,7 @@ Another common solution is to choose the pivot randomly. Sometimes this may resu Here is how you can do quicksort with a randomly chosen pivot: ```swift -func quicksortRandom(inout a: [T], low: Int, high: Int) { +func quicksortRandom(_ a: inout [T], low: Int, high: Int) { if low < high { let pivotIndex = random(min: low, max: high) // 1 @@ -412,7 +412,7 @@ But as you've seen with the Lomuto partitioning scheme, if the pivot occurs more The code for this scheme is: ```swift -func partitionDutchFlag(inout a: [T], low: Int, high: Int, pivotIndex: Int) -> (Int, Int) { +func partitionDutchFlag(_ a: inout [T], low: Int, high: Int, pivotIndex: Int) -> (Int, Int) { let pivot = a[pivotIndex] var smaller = low @@ -461,7 +461,7 @@ Notice how the two `8`s are in the middle now. The return value from `partitionD Here is how you would use it in quicksort: ```swift -func quicksortDutchFlag(inout a: [T], low: Int, high: Int) { +func quicksortDutchFlag(_ a: inout [T], low: Int, high: Int) { if low < high { let pivotIndex = random(min: low, max: high) let (p, q) = partitionDutchFlag(&a, low: low, high: high, pivotIndex: pivotIndex) From 6f14d9e9c739769b9b756c8d0fbd6ba81031e4c7 Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Sat, 17 Sep 2016 18:11:28 -0700 Subject: [PATCH 0535/1679] Revised playground code to compile in Swift3. --- .../Sources/BoundedPriorityQueue.swift | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Bounded Priority Queue/BoundedPriorityQueue.playground/Sources/BoundedPriorityQueue.swift b/Bounded Priority Queue/BoundedPriorityQueue.playground/Sources/BoundedPriorityQueue.swift index 58dc5034e..fc399811d 100644 --- a/Bounded Priority Queue/BoundedPriorityQueue.playground/Sources/BoundedPriorityQueue.swift +++ b/Bounded Priority Queue/BoundedPriorityQueue.playground/Sources/BoundedPriorityQueue.swift @@ -12,7 +12,7 @@ public class BoundedPriorityQueue { private typealias Node = LinkedListNode private(set) public var count = 0 - private var head: Node? + fileprivate var head: Node? private var tail: Node? private var maxElements: Int @@ -28,7 +28,7 @@ public class BoundedPriorityQueue { return head?.value } - public func enqueue(value: T) { + public func enqueue(_ value: T) { if let node = insert(value, after: findInsertionPoint(value)) { // If the newly inserted node is the last one in the list, then update // the tail pointer. @@ -44,7 +44,7 @@ public class BoundedPriorityQueue { } } - private func insert(value: T, after: Node?) -> Node? { + private func insert(_ value: T, after: Node?) -> Node? { if let previous = after { // If the queue is full and we have to insert at the end of the list, @@ -78,11 +78,11 @@ public class BoundedPriorityQueue { /* Find the node after which to insert the new value. If this returns nil, the new value should be inserted at the head of the list. */ - private func findInsertionPoint(value: T) -> Node? { + private func findInsertionPoint(_ value: T) -> Node? { var node = head var prev: Node? = nil - while let current = node where value < current.value { + while let current = node, value < current.value { prev = node node = current.next } From 6e2f5c199b67469988b452a3266aa1b9ab26da34 Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Sat, 17 Sep 2016 18:13:20 -0700 Subject: [PATCH 0536/1679] Fixes README file for Swift3. --- Bounded Priority Queue/README.markdown | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Bounded Priority Queue/README.markdown b/Bounded Priority Queue/README.markdown index 8d6ea1804..8d47adefb 100644 --- a/Bounded Priority Queue/README.markdown +++ b/Bounded Priority Queue/README.markdown @@ -35,7 +35,7 @@ public class BoundedPriorityQueue { private typealias Node = LinkedListNode private(set) public var count = 0 - private var head: Node? + fileprivate var head: Node? private var tail: Node? private var maxElements: Int @@ -55,7 +55,7 @@ public class BoundedPriorityQueue { The `BoundedPriorityQueue` class contains a doubly linked list of `LinkedListNode` objects. Nothing special here yet. The fun stuff happens in the `enqueue()` method: ```swift -public func enqueue(value: T) { +public func enqueue(_ value: T) { if let node = insert(value, after: findInsertionPoint(value)) { // If the newly inserted node is the last one in the list, then update // the tail pointer. @@ -71,7 +71,7 @@ public func enqueue(value: T) { } } -private func insert(value: T, after: Node?) -> Node? { +private func insert(_ value: T, after: Node?) -> Node? { if let previous = after { // If the queue is full and we have to insert at the end of the list, @@ -105,7 +105,7 @@ private func insert(value: T, after: Node?) -> Node? { /* Find the node after which to insert the new value. If this returns nil, the new value should be inserted at the head of the list. */ -private func findInsertionPoint(value: T) -> Node? { +private func findInsertionPoint(_ value: T) -> Node? { var node = head var prev: Node? = nil From 562c85c1b0d717c73e4a04d1a0913a5e83732cea Mon Sep 17 00:00:00 2001 From: FarzadShbfn Date: Sun, 18 Sep 2016 15:34:10 +0430 Subject: [PATCH 0537/1679] Upgrade to Swift3 --- GCD/GCD.playground/Contents.swift | 4 ++-- GCD/GCD.swift | 6 +++--- GCD/README.markdown | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/GCD/GCD.playground/Contents.swift b/GCD/GCD.playground/Contents.swift index dedf6e293..2e264be93 100644 --- a/GCD/GCD.playground/Contents.swift +++ b/GCD/GCD.playground/Contents.swift @@ -1,7 +1,7 @@ //: Playground - noun: a place where people can play // Recursive version -func gcd(a: Int, _ b: Int) -> Int { +func gcd(_ a: Int, _ b: Int) -> Int { let r = a % b if r != 0 { return gcd(b, r) @@ -26,7 +26,7 @@ func gcd(m: Int, _ n: Int) -> Int { } */ -func lcm(m: Int, _ n: Int) -> Int { +func lcm(_ m: Int, _ n: Int) -> Int { return m*n / gcd(m, n) } diff --git a/GCD/GCD.swift b/GCD/GCD.swift index dc473ccd4..ce7e7fa78 100644 --- a/GCD/GCD.swift +++ b/GCD/GCD.swift @@ -1,7 +1,7 @@ /* Euclid's algorithm for finding the greatest common divisor */ -func gcd(m: Int, _ n: Int) -> Int { +func gcd(_ m: Int, _ n: Int) -> Int { var a = 0 var b = max(m, n) var r = min(m, n) @@ -16,7 +16,7 @@ func gcd(m: Int, _ n: Int) -> Int { /* // Recursive version -func gcd(a: Int, _ b: Int) -> Int { +func gcd(_ a: Int, _ b: Int) -> Int { let r = a % b if r != 0 { return gcd(b, r) @@ -29,6 +29,6 @@ func gcd(a: Int, _ b: Int) -> Int { /* Returns the least common multiple of two numbers. */ -func lcm(m: Int, _ n: Int) -> Int { +func lcm(_ m: Int, _ n: Int) -> Int { return m*n / gcd(m, n) } diff --git a/GCD/README.markdown b/GCD/README.markdown index 1d20fb9cb..07d2de1ca 100644 --- a/GCD/README.markdown +++ b/GCD/README.markdown @@ -17,7 +17,7 @@ where `a % b` calculates the remainder of `a` divided by `b`. Here is an implementation of this idea in Swift: ```swift -func gcd(a: Int, _ b: Int) -> Int { +func gcd(_ a: Int, _ b: Int) -> Int { let r = a % b if r != 0 { return gcd(b, r) @@ -68,7 +68,7 @@ gcd(841, 299) // 1 Here is a slightly different implementation of Euclid's algorithm. Unlike the first version this doesn't use recursion but only a basic `while` loop. ```swift -func gcd(m: Int, _ n: Int) -> Int { +func gcd(_ m: Int, _ n: Int) -> Int { var a = 0 var b = max(m, n) var r = min(m, n) @@ -101,7 +101,7 @@ We can calculate the LCM using Euclid's algorithm too: In code: ```swift -func lcm(m: Int, _ n: Int) -> Int { +func lcm(_ m: Int, _ n: Int) -> Int { return m*n / gcd(m, n) } ``` From ab02cf521de7eca87ff67f5001b0f546844d5593 Mon Sep 17 00:00:00 2001 From: FarzadShbfn Date: Sun, 18 Sep 2016 15:54:01 +0430 Subject: [PATCH 0538/1679] Update to Swift3 --- .../SegmentTree.playground/Contents.swift | 192 +++++++++--------- .../contents.xcplayground | 2 +- .../timeline.xctimeline | 6 - Segment Tree/SegmentTree.swift | 116 +++++------ 4 files changed, 155 insertions(+), 161 deletions(-) delete mode 100644 Segment Tree/SegmentTree.playground/timeline.xctimeline diff --git a/Segment Tree/SegmentTree.playground/Contents.swift b/Segment Tree/SegmentTree.playground/Contents.swift index 14b7f57cf..6b33b2f44 100644 --- a/Segment Tree/SegmentTree.playground/Contents.swift +++ b/Segment Tree/SegmentTree.playground/Contents.swift @@ -1,64 +1,64 @@ //: Playground - noun: a place where people can play public class SegmentTree { - - private var value: T - private var function: (T, T) -> T - private var leftBound: Int - private var rightBound: Int - private var leftChild: SegmentTree? - private var rightChild: SegmentTree? - - public init(array: [T], leftBound: Int, rightBound: Int, function: (T, T) -> T) { - self.leftBound = leftBound - self.rightBound = rightBound - self.function = function - - if leftBound == rightBound { - value = array[leftBound] - } else { - let middle = (leftBound + rightBound) / 2 - leftChild = SegmentTree(array: array, leftBound: leftBound, rightBound: middle, function: function) - rightChild = SegmentTree(array: array, leftBound: middle+1, rightBound: rightBound, function: function) - value = function(leftChild!.value, rightChild!.value) - } - } - - public convenience init(array: [T], function: (T, T) -> T) { - self.init(array: array, leftBound: 0, rightBound: array.count-1, function: function) - } - - public func queryWithLeftBound(leftBound: Int, rightBound: Int) -> T { - if self.leftBound == leftBound && self.rightBound == rightBound { - return self.value - } - - guard let leftChild = leftChild else { fatalError("leftChild should not be nil") } - guard let rightChild = rightChild else { fatalError("rightChild should not be nil") } - - if leftChild.rightBound < leftBound { - return rightChild.queryWithLeftBound(leftBound, rightBound: rightBound) - } else if rightChild.leftBound > rightBound { - return leftChild.queryWithLeftBound(leftBound, rightBound: rightBound) - } else { - let leftResult = leftChild.queryWithLeftBound(leftBound, rightBound: leftChild.rightBound) - let rightResult = rightChild.queryWithLeftBound(rightChild.leftBound, rightBound: rightBound) - return function(leftResult, rightResult) - } - } - - public func replaceItemAtIndex(index: Int, withItem item: T) { - if leftBound == rightBound { - value = item - } else if let leftChild = leftChild, rightChild = rightChild { - if leftChild.rightBound >= index { - leftChild.replaceItemAtIndex(index, withItem: item) - } else { - rightChild.replaceItemAtIndex(index, withItem: item) - } - value = function(leftChild.value, rightChild.value) - } - } + + private var value: T + private var function: (T, T) -> T + private var leftBound: Int + private var rightBound: Int + private var leftChild: SegmentTree? + private var rightChild: SegmentTree? + + public init(array: [T], leftBound: Int, rightBound: Int, function: @escaping (T, T) -> T) { + self.leftBound = leftBound + self.rightBound = rightBound + self.function = function + + if leftBound == rightBound { + value = array[leftBound] + } else { + let middle = (leftBound + rightBound) / 2 + leftChild = SegmentTree(array: array, leftBound: leftBound, rightBound: middle, function: function) + rightChild = SegmentTree(array: array, leftBound: middle+1, rightBound: rightBound, function: function) + value = function(leftChild!.value, rightChild!.value) + } + } + + public convenience init(array: [T], function: @escaping (T, T) -> T) { + self.init(array: array, leftBound: 0, rightBound: array.count-1, function: function) + } + + public func query(withLeftBound: Int, rightBound: Int) -> T { + if self.leftBound == leftBound && self.rightBound == rightBound { + return self.value + } + + guard let leftChild = leftChild else { fatalError("leftChild should not be nil") } + guard let rightChild = rightChild else { fatalError("rightChild should not be nil") } + + if leftChild.rightBound < leftBound { + return rightChild.query(withLeftBound: leftBound, rightBound: rightBound) + } else if rightChild.leftBound > rightBound { + return leftChild.query(withLeftBound: leftBound, rightBound: rightBound) + } else { + let leftResult = leftChild.query(withLeftBound: leftBound, rightBound: leftChild.rightBound) + let rightResult = rightChild.query(withLeftBound:rightChild.leftBound, rightBound: rightBound) + return function(leftResult, rightResult) + } + } + + public func replaceItem(at index: Int, withItem item: T) { + if leftBound == rightBound { + value = item + } else if let leftChild = leftChild, let rightChild = rightChild { + if leftChild.rightBound >= index { + leftChild.replaceItem(at: index, withItem: item) + } else { + rightChild.replaceItem(at: index, withItem: item) + } + value = function(leftChild.value, rightChild.value) + } + } } @@ -68,42 +68,42 @@ let array = [1, 2, 3, 4] let sumSegmentTree = SegmentTree(array: array, function: +) -print(sumSegmentTree.queryWithLeftBound(0, rightBound: 3)) // 1 + 2 + 3 + 4 = 10 -print(sumSegmentTree.queryWithLeftBound(1, rightBound: 2)) // 2 + 3 = 5 -print(sumSegmentTree.queryWithLeftBound(0, rightBound: 0)) // 1 = 1 +print(sumSegmentTree.query(withLeftBound: 0, rightBound: 3)) // 1 + 2 + 3 + 4 = 10 +print(sumSegmentTree.query(withLeftBound: 1, rightBound: 2)) // 2 + 3 = 5 +print(sumSegmentTree.query(withLeftBound: 0, rightBound: 0)) // 1 = 1 -sumSegmentTree.replaceItemAtIndex(0, withItem: 2) //our array now is [2, 2, 3, 4] +sumSegmentTree.replaceItem(at: 0, withItem: 2) //our array now is [2, 2, 3, 4] -print(sumSegmentTree.queryWithLeftBound(0, rightBound: 0)) // 2 = 2 -print(sumSegmentTree.queryWithLeftBound(0, rightBound: 1)) // 2 + 2 = 4 +print(sumSegmentTree.query(withLeftBound: 0, rightBound: 0)) // 2 = 2 +print(sumSegmentTree.query(withLeftBound: 0, rightBound: 1)) // 2 + 2 = 4 //you can use any associative function (i.e (a+b)+c == a+(b+c)) as function for segment tree -func gcd(m: Int, _ n: Int) -> Int { - var a = 0 - var b = max(m, n) - var r = min(m, n) - - while r != 0 { - a = b - b = r - r = a % b - } - return b +func gcd(_ m: Int, _ n: Int) -> Int { + var a = 0 + var b = max(m, n) + var r = min(m, n) + + while r != 0 { + a = b + b = r + r = a % b + } + return b } let gcdArray = [2, 4, 6, 3, 5] let gcdSegmentTree = SegmentTree(array: gcdArray, function: gcd) -print(gcdSegmentTree.queryWithLeftBound(0, rightBound: 1)) // gcd(2, 4) = 2 -print(gcdSegmentTree.queryWithLeftBound(2, rightBound: 3)) // gcd(6, 3) = 3 -print(gcdSegmentTree.queryWithLeftBound(1, rightBound: 3)) // gcd(4, 6, 3) = 1 -print(gcdSegmentTree.queryWithLeftBound(0, rightBound: 4)) // gcd(2, 4, 6, 3, 5) = 1 +print(gcdSegmentTree.query(withLeftBound: 0, rightBound: 1)) // gcd(2, 4) = 2 +print(gcdSegmentTree.query(withLeftBound: 2, rightBound: 3)) // gcd(6, 3) = 3 +print(gcdSegmentTree.query(withLeftBound: 1, rightBound: 3)) // gcd(4, 6, 3) = 1 +print(gcdSegmentTree.query(withLeftBound: 0, rightBound: 4)) // gcd(2, 4, 6, 3, 5) = 1 -gcdSegmentTree.replaceItemAtIndex(3, withItem: 10) //gcdArray now is [2, 4, 6, 10, 5] +gcdSegmentTree.replaceItem(at: 3, withItem: 10) //gcdArray now is [2, 4, 6, 10, 5] -print(gcdSegmentTree.queryWithLeftBound(3, rightBound: 4)) // gcd(10, 5) = 5 +print(gcdSegmentTree.query(withLeftBound: 3, rightBound: 4)) // gcd(10, 5) = 5 //example of segment tree which finds minimum on given range @@ -111,12 +111,12 @@ let minArray = [2, 4, 1, 5, 3] let minSegmentTree = SegmentTree(array: minArray, function: min) -print(minSegmentTree.queryWithLeftBound(0, rightBound: 4)) // min(2, 4, 1, 5, 3) = 1 -print(minSegmentTree.queryWithLeftBound(0, rightBound: 1)) // min(2, 4) = 2 +print(minSegmentTree.query(withLeftBound: 0, rightBound: 4)) // min(2, 4, 1, 5, 3) = 1 +print(minSegmentTree.query(withLeftBound: 0, rightBound: 1)) // min(2, 4) = 2 -minSegmentTree.replaceItemAtIndex(2, withItem: 10) // minArray now is [2, 4, 10, 5, 3] +minSegmentTree.replaceItem(at: 2, withItem: 10) // minArray now is [2, 4, 10, 5, 3] -print(minSegmentTree.queryWithLeftBound(0, rightBound: 4)) // min(2, 4, 10, 5, 3) = 2 +print(minSegmentTree.query(withLeftBound: 0, rightBound: 4)) // min(2, 4, 10, 5, 3) = 2 //type of elements in array can be any type which has some associative function @@ -124,16 +124,16 @@ let stringArray = ["a", "b", "c", "A", "B", "C"] let stringSegmentTree = SegmentTree(array: stringArray, function: +) -print(stringSegmentTree.queryWithLeftBound(0, rightBound: 1)) // "a"+"b" = "ab" -print(stringSegmentTree.queryWithLeftBound(2, rightBound: 3)) // "c"+"A" = "cA" -print(stringSegmentTree.queryWithLeftBound(1, rightBound: 3)) // "b"+"c"+"A" = "bcA" -print(stringSegmentTree.queryWithLeftBound(0, rightBound: 5)) // "a"+"b"+"c"+"A"+"B"+"C" = "abcABC" +print(stringSegmentTree.query(withLeftBound: 0, rightBound: 1)) // "a"+"b" = "ab" +print(stringSegmentTree.query(withLeftBound: 2, rightBound: 3)) // "c"+"A" = "cA" +print(stringSegmentTree.query(withLeftBound: 1, rightBound: 3)) // "b"+"c"+"A" = "bcA" +print(stringSegmentTree.query(withLeftBound: 0, rightBound: 5)) // "a"+"b"+"c"+"A"+"B"+"C" = "abcABC" -stringSegmentTree.replaceItemAtIndex(0, withItem: "I") -stringSegmentTree.replaceItemAtIndex(1, withItem: " like") -stringSegmentTree.replaceItemAtIndex(2, withItem: " algorithms") -stringSegmentTree.replaceItemAtIndex(3, withItem: " and") -stringSegmentTree.replaceItemAtIndex(4, withItem: " swift") -stringSegmentTree.replaceItemAtIndex(5, withItem: "!") +stringSegmentTree.replaceItem(at: 0, withItem: "I") +stringSegmentTree.replaceItem(at: 1, withItem: " like") +stringSegmentTree.replaceItem(at: 2, withItem: " algorithms") +stringSegmentTree.replaceItem(at: 3, withItem: " and") +stringSegmentTree.replaceItem(at: 4, withItem: " swift") +stringSegmentTree.replaceItem(at: 5, withItem: "!") -print(stringSegmentTree.queryWithLeftBound(0, rightBound: 5)) +print(stringSegmentTree.query(withLeftBound: 0, rightBound: 5)) diff --git a/Segment Tree/SegmentTree.playground/contents.xcplayground b/Segment Tree/SegmentTree.playground/contents.xcplayground index 06828af92..16f9952aa 100644 --- a/Segment Tree/SegmentTree.playground/contents.xcplayground +++ b/Segment Tree/SegmentTree.playground/contents.xcplayground @@ -1,4 +1,4 @@ - + \ No newline at end of file diff --git a/Segment Tree/SegmentTree.playground/timeline.xctimeline b/Segment Tree/SegmentTree.playground/timeline.xctimeline deleted file mode 100644 index bf468afec..000000000 --- a/Segment Tree/SegmentTree.playground/timeline.xctimeline +++ /dev/null @@ -1,6 +0,0 @@ - - - - - diff --git a/Segment Tree/SegmentTree.swift b/Segment Tree/SegmentTree.swift index 608d5151a..b360d409a 100644 --- a/Segment Tree/SegmentTree.swift +++ b/Segment Tree/SegmentTree.swift @@ -8,62 +8,62 @@ */ public class SegmentTree { - - private var value: T - private var function: (T, T) -> T - private var leftBound: Int - private var rightBound: Int - private var leftChild: SegmentTree? - private var rightChild: SegmentTree? - - public init(array: [T], leftBound: Int, rightBound: Int, function: (T, T) -> T) { - self.leftBound = leftBound - self.rightBound = rightBound - self.function = function - - if leftBound == rightBound { - value = array[leftBound] - } else { - let middle = (leftBound + rightBound) / 2 - leftChild = SegmentTree(array: array, leftBound: leftBound, rightBound: middle, function: function) - rightChild = SegmentTree(array: array, leftBound: middle+1, rightBound: rightBound, function: function) - value = function(leftChild!.value, rightChild!.value) - } - } - - public convenience init(array: [T], function: (T, T) -> T) { - self.init(array: array, leftBound: 0, rightBound: array.count-1, function: function) - } - - public func queryWithLeftBound(leftBound: Int, rightBound: Int) -> T { - if self.leftBound == leftBound && self.rightBound == rightBound { - return self.value - } - - guard let leftChild = leftChild else { fatalError("leftChild should not be nil") } - guard let rightChild = rightChild else { fatalError("rightChild should not be nil") } - - if leftChild.rightBound < leftBound { - return rightChild.queryWithLeftBound(leftBound, rightBound: rightBound) - } else if rightChild.leftBound > rightBound { - return leftChild.queryWithLeftBound(leftBound, rightBound: rightBound) - } else { - let leftResult = leftChild.queryWithLeftBound(leftBound, rightBound: leftChild.rightBound) - let rightResult = rightChild.queryWithLeftBound(rightChild.leftBound, rightBound: rightBound) - return function(leftResult, rightResult) - } - } - - public func replaceItemAtIndex(index: Int, withItem item: T) { - if leftBound == rightBound { - value = item - } else if let leftChild = leftChild, rightChild = rightChild { - if leftChild.rightBound >= index { - leftChild.replaceItemAtIndex(index, withItem: item) - } else { - rightChild.replaceItemAtIndex(index, withItem: item) - } - value = function(leftChild.value, rightChild.value) - } - } + + private var value: T + private var function: (T, T) -> T + private var leftBound: Int + private var rightBound: Int + private var leftChild: SegmentTree? + private var rightChild: SegmentTree? + + public init(array: [T], leftBound: Int, rightBound: Int, function: @escaping (T, T) -> T) { + self.leftBound = leftBound + self.rightBound = rightBound + self.function = function + + if leftBound == rightBound { + value = array[leftBound] + } else { + let middle = (leftBound + rightBound) / 2 + leftChild = SegmentTree(array: array, leftBound: leftBound, rightBound: middle, function: function) + rightChild = SegmentTree(array: array, leftBound: middle+1, rightBound: rightBound, function: function) + value = function(leftChild!.value, rightChild!.value) + } + } + + public convenience init(array: [T], function: @escaping (T, T) -> T) { + self.init(array: array, leftBound: 0, rightBound: array.count-1, function: function) + } + + public func query(withLeftBound: Int, rightBound: Int) -> T { + if self.leftBound == leftBound && self.rightBound == rightBound { + return self.value + } + + guard let leftChild = leftChild else { fatalError("leftChild should not be nil") } + guard let rightChild = rightChild else { fatalError("rightChild should not be nil") } + + if leftChild.rightBound < leftBound { + return rightChild.query(withLeftBound: leftBound, rightBound: rightBound) + } else if rightChild.leftBound > rightBound { + return leftChild.query(withLeftBound: leftBound, rightBound: rightBound) + } else { + let leftResult = leftChild.query(withLeftBound: leftBound, rightBound: leftChild.rightBound) + let rightResult = rightChild.query(withLeftBound:rightChild.leftBound, rightBound: rightBound) + return function(leftResult, rightResult) + } + } + + public func replaceItem(at index: Int, withItem item: T) { + if leftBound == rightBound { + value = item + } else if let leftChild = leftChild, let rightChild = rightChild { + if leftChild.rightBound >= index { + leftChild.replaceItem(at: index, withItem: item) + } else { + rightChild.replaceItem(at: index, withItem: item) + } + value = function(leftChild.value, rightChild.value) + } + } } From f7ecb1ae4a886a8983670ce77e5bed3e6cde0890 Mon Sep 17 00:00:00 2001 From: FarzadShbfn Date: Sun, 18 Sep 2016 16:08:19 +0430 Subject: [PATCH 0539/1679] Updated ReadMe for Swift3 --- Segment Tree/README.markdown | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/Segment Tree/README.markdown b/Segment Tree/README.markdown index 0bb6d8da5..15b1a3227 100644 --- a/Segment Tree/README.markdown +++ b/Segment Tree/README.markdown @@ -73,7 +73,7 @@ The `leftBound` and `rightBound` of each node are marked in red. Here's how we create a node of the segment tree: ```swift -public init(array: [T], leftBound: Int, rightBound: Int, function: (T, T) -> T) { +public init(array: [T], leftBound: Int, rightBound: Int, function: @escaping (T, T) -> T) { self.leftBound = leftBound self.rightBound = rightBound self.function = function @@ -111,7 +111,7 @@ We go through all this trouble so we can efficiently query the tree. Here's the code: ```swift - public func queryWithLeftBound(leftBound: Int, rightBound: Int) -> T { + public func query(withLeftBound: leftBound: Int, rightBound: Int) -> T { // 1 if self.leftBound == leftBound && self.rightBound == rightBound { return self.value @@ -122,16 +122,16 @@ Here's the code: // 2 if leftChild.rightBound < leftBound { - return rightChild.queryWithLeftBound(leftBound, rightBound: rightBound) + return rightChild.query(withLeftBound: leftBound, rightBound: rightBound) // 3 } else if rightChild.leftBound > rightBound { - return leftChild.queryWithLeftBound(leftBound, rightBound: rightBound) + return leftChild.query(withLeftBound: leftBound, rightBound: rightBound) // 4 } else { - let leftResult = leftChild.queryWithLeftBound(leftBound, rightBound: leftChild.rightBound) - let rightResult = rightChild.queryWithLeftBound(rightChild.leftBound, rightBound: rightBound) + let leftResult = leftChild.query(withLeftBound: leftBound, rightBound: leftChild.rightBound) + let rightResult = rightChild.query(withLeftBound: rightChild.leftBound, rightBound: rightBound) return function(leftResult, rightResult) } } @@ -162,10 +162,10 @@ let array = [1, 2, 3, 4] let sumSegmentTree = SegmentTree(array: array, function: +) -sumSegmentTree.queryWithLeftBound(0, rightBound: 3) // 1 + 2 + 3 + 4 = 10 -sumSegmentTree.queryWithLeftBound(1, rightBound: 2) // 2 + 3 = 5 -sumSegmentTree.queryWithLeftBound(0, rightBound: 0) // just 1 -sumSegmentTree.queryWithLeftBound(3, rightBound: 3) // just 4 +sumSegmentTree.query(withLeftBound: 0, rightBound: 3) // 1 + 2 + 3 + 4 = 10 +sumSegmentTree.query(withLeftBound: 1, rightBound: 2) // 2 + 3 = 5 +sumSegmentTree.query(withLeftBound: 0, rightBound: 0) // just 1 +sumSegmentTree.query(withLeftBound: 3, rightBound: 3) // just 4 ``` Querying the tree takes **O(log n)** time. @@ -177,21 +177,21 @@ The value of a node in the segment tree depends on the nodes below it. So if we Here is the code: ```swift - public func replaceItemAtIndex(index: Int, withItem item: T) { + public func replaceItem(at index: Int, withItem item: T) { if leftBound == rightBound { value = item } else if let leftChild = leftChild, rightChild = rightChild { if leftChild.rightBound >= index { - leftChild.replaceItemAtIndex(index, withItem: item) + leftChild.replaceItem(at: index, withItem: item) } else { - rightChild.replaceItemAtIndex(index, withItem: item) + rightChild.replaceItem(at: index, withItem: item) } value = function(leftChild.value, rightChild.value) } } ``` -As usual, this works with recursion. If the node is a leaf, we just change its value. If the node is not a leaf, then we recursively call `replaceItemAtIndex()` to update its children. After that, we recalculate the node's own value so that it is up-to-date again. +As usual, this works with recursion. If the node is a leaf, we just change its value. If the node is not a leaf, then we recursively call `replaceItem(at: )` to update its children. After that, we recalculate the node's own value so that it is up-to-date again. Replacing an item takes **O(log n)** time. From a03d083365ba342e16ca44d2a5695f31e1cd22c6 Mon Sep 17 00:00:00 2001 From: Mike Taghavi Date: Mon, 19 Sep 2016 00:13:14 +0200 Subject: [PATCH 0540/1679] update documentation --- Skip-List/README.md | 96 +++++++++++++++++++++++++++++++++++++++------ 1 file changed, 85 insertions(+), 11 deletions(-) diff --git a/Skip-List/README.md b/Skip-List/README.md index 64f221a23..5c569e177 100644 --- a/Skip-List/README.md +++ b/Skip-List/README.md @@ -1,30 +1,95 @@ # Skip List -Skip List is a probablistic data-structure with same efficiency as AVL tree or Red-Black tree. The building blocks are hierarchy of layers (regular sorted linked-lists), created probablisticly by coin flipping, each acting as an express lane to the layer underneath, therefore making fast O(log n) search possible by skipping lanes and reducing travel distance. A layer consists of a Head node, holding reference to the subsequent and the node below. Each node also holds similar references as the Head node. +Skip List is a probablistic data-structure with same logarithmic time bound and +efficiency as AVL/ or Red-Black tree and provides a clever compromise to +efficiently support search and update operations and is relatively simpler to +implement compared to other map data structures. -![Schematic view](Images/Intro.png -) +A skip list *S* consists of series of sorted linked lists *{L0, ..., Ln}*, +layered hierarchicaly and each layer *L* stores a subset of items in layer *L0* +in incremental order. The items in layers *{L1, ... Ln}* are chosen at random +based on a coin flipping function with probability 1/2 . For traversing, every +item in a layer hold references to the node below and the next node. This +layers serve as express lanes to the layer underneath them, effectively making +fast O(log n) searching possible by skipping lanes and reducing travel distance +and in worse case searching degrades to O (n), as expected with regular linked +list. +For a skip list *S*: + +1. List *L0* contains every inserted item. +2. For lists *{L1, ..., Ln}*, *Li* contains a randomly generated subset of the + items in *Li-1* +3. Height is determined by coin-flipping. + +![Schematic view](Images/Intro.png) +Figure 1 + + +#Searching + +Searching for element *N* starts by traversing from top most layer *Ln* until +*L0*. + +Our objective is to find an element *K* such that its value at the rightmost +position of current layer, is less-than target item and its subsequent node has +a greater-equal value or nil ( * K.key < N.key <= (K.next.key or nil)* ). if +value of *K.next* is equal to *N*, search is terminated and we return *K.next*, +otherwise drop underneath using *K.down* to the node below ( at layer Ln-1 ) and +repeat the process until *L0* where *K.down* is `nil` which indicates that level +is *L0* and item doesn't exists. + + +###Example: + +![Inserting first element](Images/Insert5.png) #Inserting -1. Inserting a new element in initial state where no prior layer is created yet begins by construction of a Head node with a reference to data node (just like regular lists). After this operation coin-flipping starts to determine wether a new layer must be created. When positive, a new layer containing Head and data node ( similar to previous layer ) is created and head is updated to reference the new layer and the head node underneath. Subsequently data node is also updated to reference the node below; until coin-flip function return a negative value to terminate this process. +Inserting element *N* has a similar process as searching. It starts by +traversing from top most layer *Ln* until *L0*. We need to keep track of our +traversal path using a stack. It helps us to traverse the path upward when +coin-flipping starts, so we can insert our new element and update references to +it. -2. After initial state, we start at top most layer to find a node where its value is less than the new value and its next node value is greater-equal/nil than new value. Then we use this node to travel to layer underneath until we reach the layer 0 where the element must be inserted first, after this node. Node references must be updated accordingly by back tracing the path to the top. If the first element in the layer does not meet the criteria, same procedure is used to travel to the layer below using the head node. +Our objective is to find a element *K* such that its value at the rightmost +position of layer *Ln*, is less-than new item and its subsequent node has a +greater-equal value or nil ( * K.key < N.key < (K.next.key or nil)* ). Push +element *K* to the stack and with element *K*, go down using *K.down* to the +node below ( at layer Ln-1 ) and repeat the process ( forward searching ) up +until *L0* where *K.down* is `nil` which indicates that level is *L0*. We +terminate the process when *K.down* is nil. +At *L0*, *N* can be inserted after *K*. -**Example** +Here is the interesting part. We use coin flipping function to randomly create +layers. +When coin flip function returns 0, the whole process is finished but when +returns 1, there are two possibilities: -1 - Inserting 10 in initial state with coin flips (0) +1. Stack is empty ( Level is *L0* / -*Ln* or at uninitialized stage) +2. Stack has items ( traversing upward is possible ) -![Inserting first element](Images/Insert1.png) +In case 1: +A new layer M* is created with a head node *NM* referencing head node of layer +below and *NM.next* referencing new element *N*. New element *N* referecing +element *N* at previous layer. -2 - 12 inserted with coin flips (1,1,0) +In case 2: +repeat until stack is empty Pop an item *F* from stack and update the references +accordingly. *F.next* will be *K.next* and *K.next* will be *F* + +when stack is empty Create a new layer consisintg of a head node *NM* +referencing head node of layer below and *NM.next* referencing new element +*N*. New element *N* referencing element *N* at previous layer. + -3 - Inserting 13. with coin flips (0) +###Example: + +Inserting 13. with coin flips (0) ![Inserting first element](Images/Insert5.png) ![Inserting first element](Images/Insert6.png) @@ -33,7 +98,16 @@ Skip List is a probablistic data-structure with same efficiency as AVL tree or R ![Inserting first element](Images/Insert9.png) -#Searching + +Inserting 20. with 4 times coin flips (1) +![Inserting first element](Images/Insert9.png) +![Inserting first element](Images/Insert10.png) +![Inserting first element](Images/insert11.png) +![Inserting first element](Images/Insert12.png) + +#Removing + +Removing works similar to insert procedure. TODO From 23e776b334b69f3ede8a98282c2cd0726118870e Mon Sep 17 00:00:00 2001 From: Mike Date: Mon, 19 Sep 2016 00:16:04 +0200 Subject: [PATCH 0541/1679] Update README.md --- Skip-List/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Skip-List/README.md b/Skip-List/README.md index 5c569e177..575005ddc 100644 --- a/Skip-List/README.md +++ b/Skip-List/README.md @@ -102,7 +102,7 @@ Inserting 13. with coin flips (0) Inserting 20. with 4 times coin flips (1) ![Inserting first element](Images/Insert9.png) ![Inserting first element](Images/Insert10.png) -![Inserting first element](Images/insert11.png) +![Inserting first element](Images/Insert11.png) ![Inserting first element](Images/Insert12.png) #Removing From 8519c48d9f7f235f52a92b22f8fdb4a904e1f2e8 Mon Sep 17 00:00:00 2001 From: Mike Date: Mon, 19 Sep 2016 00:18:53 +0200 Subject: [PATCH 0542/1679] Update README.md --- Skip-List/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Skip-List/README.md b/Skip-List/README.md index 575005ddc..664684621 100644 --- a/Skip-List/README.md +++ b/Skip-List/README.md @@ -22,7 +22,7 @@ For a skip list *S*: items in *Li-1* 3. Height is determined by coin-flipping. -![Schematic view](Images/Intro.png) +![Schematic view](Images/Search.png) Figure 1 From 512b603a7acf860b4af0aac124ecfa5794a8ecd8 Mon Sep 17 00:00:00 2001 From: Mike Date: Mon, 19 Sep 2016 00:19:13 +0200 Subject: [PATCH 0543/1679] Update README.md --- Skip-List/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Skip-List/README.md b/Skip-List/README.md index 664684621..6d47f05df 100644 --- a/Skip-List/README.md +++ b/Skip-List/README.md @@ -22,7 +22,7 @@ For a skip list *S*: items in *Li-1* 3. Height is determined by coin-flipping. -![Schematic view](Images/Search.png) +![Schematic view](Images/Search1.png) Figure 1 From 87d81428ad852ee84f82a0e5f9583da9134c25c3 Mon Sep 17 00:00:00 2001 From: Mike Date: Mon, 19 Sep 2016 00:19:36 +0200 Subject: [PATCH 0544/1679] Update README.md --- Skip-List/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Skip-List/README.md b/Skip-List/README.md index 6d47f05df..5c39e3db8 100644 --- a/Skip-List/README.md +++ b/Skip-List/README.md @@ -22,7 +22,7 @@ For a skip list *S*: items in *Li-1* 3. Height is determined by coin-flipping. -![Schematic view](Images/Search1.png) +![Schematic view](Images/Intro.png) Figure 1 @@ -42,7 +42,7 @@ is *L0* and item doesn't exists. ###Example: -![Inserting first element](Images/Insert5.png) +![Inserting first element](Images/Search1.png) #Inserting From 5891a6b4b9d26d97b837d2fcfe2b93e50043fcb4 Mon Sep 17 00:00:00 2001 From: Mike Date: Mon, 19 Sep 2016 00:20:59 +0200 Subject: [PATCH 0545/1679] Update README.md --- Skip-List/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Skip-List/README.md b/Skip-List/README.md index 5c39e3db8..d3824952b 100644 --- a/Skip-List/README.md +++ b/Skip-List/README.md @@ -33,7 +33,7 @@ Searching for element *N* starts by traversing from top most layer *Ln* until Our objective is to find an element *K* such that its value at the rightmost position of current layer, is less-than target item and its subsequent node has -a greater-equal value or nil ( * K.key < N.key <= (K.next.key or nil)* ). if +a greater-equal value or nil ( *K.key < N.key <= (K.next.key or nil)* ). if value of *K.next* is equal to *N*, search is terminated and we return *K.next*, otherwise drop underneath using *K.down* to the node below ( at layer Ln-1 ) and repeat the process until *L0* where *K.down* is `nil` which indicates that level @@ -54,7 +54,7 @@ it. Our objective is to find a element *K* such that its value at the rightmost position of layer *Ln*, is less-than new item and its subsequent node has a -greater-equal value or nil ( * K.key < N.key < (K.next.key or nil)* ). Push +greater-equal value or nil ( *K.key < N.key < (K.next.key or nil)* ). Push element *K* to the stack and with element *K*, go down using *K.down* to the node below ( at layer Ln-1 ) and repeat the process ( forward searching ) up until *L0* where *K.down* is `nil` which indicates that level is *L0*. We @@ -68,7 +68,7 @@ layers. When coin flip function returns 0, the whole process is finished but when returns 1, there are two possibilities: -1. Stack is empty ( Level is *L0* / -*Ln* or at uninitialized stage) +1. Stack is empty ( Level is *L0* /- *Ln* or at uninitialized stage) 2. Stack has items ( traversing upward is possible ) In case 1: From a8b5ef93d12b8399586427624dac24cecb760e42 Mon Sep 17 00:00:00 2001 From: Kauserali Hafizji Date: Mon, 19 Sep 2016 21:20:22 +0530 Subject: [PATCH 0546/1679] Palindromes now work with strings with even length --- Palindromes/Palindromes.playground/Contents.swift | 8 +++----- Palindromes/Palindromes.swift | 6 +----- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/Palindromes/Palindromes.playground/Contents.swift b/Palindromes/Palindromes.playground/Contents.swift index 20df10ee4..bb666ee9a 100644 --- a/Palindromes/Palindromes.playground/Contents.swift +++ b/Palindromes/Palindromes.playground/Contents.swift @@ -5,11 +5,7 @@ public func palindromeCheck(text: String?) -> Bool { let mutableText = text.trimmingCharacters(in: NSCharacterSet.whitespaces).lowercased() let length: Int = mutableText.characters.count - guard length >= 1 else { - return false - } - - if length == 1 { + if length == 1 || length == 0 { return true } else if mutableText[mutableText.startIndex] == mutableText[mutableText.index(mutableText.endIndex, offsetBy: -1)] { let range = Range(mutableText.index(mutableText.startIndex, offsetBy: 1).. Bool { let mutableText = text.trimmingCharacters(in: NSCharacterSet.whitespaces).lowercased() let length: Int = mutableText.characters.count - guard length >= 1 else { - return false - } - - if length == 1 { + if length == 1 || length == 0 { return true } else if mutableText[mutableText.startIndex] == mutableText[mutableText.index(mutableText.endIndex, offsetBy: -1)] { let range = Range(mutableText.index(mutableText.startIndex, offsetBy: 1).. Date: Mon, 19 Sep 2016 20:03:12 +0200 Subject: [PATCH 0547/1679] made enums lowerCamelCase --- .../Sources/RBTree.swift | 62 +++++++++---------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/Red-Black Tree 2/Red-Black Tree 2.playground/Sources/RBTree.swift b/Red-Black Tree 2/Red-Black Tree 2.playground/Sources/RBTree.swift index c5bcd0a3e..9649a2175 100644 --- a/Red-Black Tree 2/Red-Black Tree 2.playground/Sources/RBTree.swift +++ b/Red-Black Tree 2/Red-Black Tree 2.playground/Sources/RBTree.swift @@ -1,12 +1,12 @@ private enum RBTColor { - case Red - case Black - case DoubleBlack + case red + case black + case doubleBlack } public class RBTNode { - fileprivate var color: RBTColor = .Red + fileprivate var color: RBTColor = .red public var value: T! = nil public var right: RBTNode! public var left: RBTNode! @@ -49,15 +49,15 @@ public class RBTNode { } fileprivate var isRed: Bool { - return color == .Red + return color == .red } fileprivate var isBlack: Bool { - return color == .Black + return color == .black } fileprivate var isDoubleBlack: Bool { - return color == .DoubleBlack + return color == .doubleBlack } } @@ -67,7 +67,7 @@ public class RBTree { public init() { nullLeaf = RBTNode() - nullLeaf.color = .Black + nullLeaf.color = .black root = nullLeaf } @@ -175,7 +175,7 @@ public class RBTree { // if node is root change color to black, else move on private func insertCase1(n: RBTNode) { if n === root { - n.color = .Black + n.color = .black } else { insertCase2(n: n) } @@ -192,9 +192,9 @@ public class RBTree { private func insertCase3(n: RBTNode) { if n.uncle.isRed { // node must have grandparent as children of root have a black parent // both parent and uncle are red, so grandparent must be black. - n.parent.color = .Black - n.uncle.color = .Black - n.grandparent.color = .Red + n.parent.color = .black + n.uncle.color = .black + n.grandparent.color = .red // now both parent and uncle are black and grandparent is red. // we repeat for the grandparent insertCase1(n: n.grandparent) @@ -226,8 +226,8 @@ public class RBTree { private func insertCase5(n: RBTNode) { // swap color of parent and grandparent // parent is red grandparent is black - n.parent.color = .Black - n.grandparent.color = .Red + n.parent.color = .black + n.grandparent.color = .red if n.isLeftChild { // left left case rightRotate(n: n.grandparent) @@ -269,7 +269,7 @@ public class RBTree { } if toDel.isRed || child.isRed { - child.color = .Black + child.color = .black if toDel.isLeftChild { toDel.parent.left = child @@ -292,7 +292,7 @@ public class RBTree { if child !== nullLeaf { child.parent = toDel.parent } - child.color = .DoubleBlack + child.color = .doubleBlack while child.isDoubleBlack || (child.parent !== nullLeaf && child.parent != nil) { if sibling!.isBlack { @@ -307,35 +307,35 @@ public class RBTree { } if leftRedChild != nil || rightRedChild != nil { // at least one of sibling's children are red - child.color = .Black + child.color = .black if sibling!.isLeftChild { if leftRedChild != nil { // left left case - sibling!.left.color = .Black + sibling!.left.color = .black let tempColor = sibling!.parent.color sibling!.parent.color = sibling!.color sibling!.color = tempColor rightRotate(n: sibling!.parent) } else { // left right case if sibling!.parent.isRed { - sibling!.parent.color = .Black + sibling!.parent.color = .black } else { - sibling!.right.color = .Black + sibling!.right.color = .black } leftRotate(n: sibling!) rightRotate(n: sibling!.grandparent) } } else { if rightRedChild != nil { // right right case - sibling!.right.color = .Black + sibling!.right.color = .black let tempColor = sibling!.parent.color sibling!.parent.color = sibling!.color sibling!.color = tempColor leftRotate(n: sibling!.parent) } else { // right left case if sibling!.parent.isRed { - sibling!.parent.color = .Black + sibling!.parent.color = .black } else { - sibling!.left.color = .Black + sibling!.left.color = .black } rightRotate(n: sibling!) leftRotate(n: sibling!.grandparent) @@ -343,34 +343,34 @@ public class RBTree { } break } else { // both sibling's children are black - child.color = .Black - sibling!.color = .Red + child.color = .black + sibling!.color = .red if sibling!.parent.isRed { - sibling!.parent.color = .Black + sibling!.parent.color = .black break } - sibling!.parent.color = .DoubleBlack + sibling!.parent.color = .doubleBlack child = sibling!.parent sibling = child.sibling } } else { // sibling is red - sibling!.color = .Black + sibling!.color = .black if sibling!.isLeftChild { // left case rightRotate(n: sibling!.parent) sibling = sibling!.right.left - sibling!.parent.color = .Red + sibling!.parent.color = .red } else { // right case leftRotate(n: sibling!.parent) sibling = sibling!.left.right - sibling!.parent.color = .Red + sibling!.parent.color = .red } } // sibling check is here for when child is a nullLeaf and thus does not have a parent. // child is here as sibling can become nil when child is the root if (sibling != nil && sibling!.parent === nullLeaf) || (child !== nullLeaf && child.parent === nullLeaf) { - child.color = .Black + child.color = .black } } } From a5397bbe7fd3ed678665980abaffb0ec00e92667 Mon Sep 17 00:00:00 2001 From: Jaap Date: Mon, 19 Sep 2016 20:51:36 +0200 Subject: [PATCH 0548/1679] adopted CustomStringConvertible protocol --- .../Sources/RBTree.swift | 29 +++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/Red-Black Tree 2/Red-Black Tree 2.playground/Sources/RBTree.swift b/Red-Black Tree 2/Red-Black Tree 2.playground/Sources/RBTree.swift index 9649a2175..adfd38216 100644 --- a/Red-Black Tree 2/Red-Black Tree 2.playground/Sources/RBTree.swift +++ b/Red-Black Tree 2/Red-Black Tree 2.playground/Sources/RBTree.swift @@ -5,13 +5,34 @@ private enum RBTColor { case doubleBlack } -public class RBTNode { +public class RBTNode: CustomStringConvertible { fileprivate var color: RBTColor = .red public var value: T! = nil public var right: RBTNode! public var left: RBTNode! public var parent: RBTNode! + public var description: String { + if self.value == nil { + return "null" + } else { + var nodeValue: String + + // If the value is encapsulated by parentheses it is red + // If the value is encapsulated by pipes it is black + // If the value is encapsulated by double pipes it is double black (This should not occur in a verified RBTree) + if self.isRed { + nodeValue = "(\(self.value!))" + } else if self.isBlack{ + nodeValue = "|\(self.value!)|" + } else { + nodeValue = "||\(self.value!)||" + } + + return "(\(self.left.description)<-\(nodeValue)->\(self.right.description))" + } + } + init(tree: RBTree) { right = tree.nullLeaf left = tree.nullLeaf @@ -61,10 +82,14 @@ public class RBTNode { } } -public class RBTree { +public class RBTree: CustomStringConvertible { public var root: RBTNode fileprivate let nullLeaf: RBTNode + public var description: String { + return root.description + } + public init() { nullLeaf = RBTNode() nullLeaf.color = .black From d663d5dfe909b3bde9e3c3391dca3239ebc8d920 Mon Sep 17 00:00:00 2001 From: Jaap Date: Tue, 20 Sep 2016 00:30:39 +0200 Subject: [PATCH 0549/1679] changed sibling property to be non optional and fixed insertion bug --- .../Contents.swift | 25 +++-- .../Sources/RBTree.swift | 98 ++++++++++--------- 2 files changed, 72 insertions(+), 51 deletions(-) diff --git a/Red-Black Tree 2/Red-Black Tree 2.playground/Contents.swift b/Red-Black Tree 2/Red-Black Tree 2.playground/Contents.swift index b4fadff92..d55c153d5 100644 --- a/Red-Black Tree 2/Red-Black Tree 2.playground/Contents.swift +++ b/Red-Black Tree 2/Red-Black Tree 2.playground/Contents.swift @@ -1,9 +1,20 @@ //: Playground - noun: a place where people can play +import Foundation -let array = [6,78,89,4] -var tree = RBTree(withArray: array) -tree.insert(5) -tree.insert(8) -tree.insert(2) -tree.delete(6) -tree.delete(8) \ No newline at end of file +let tree = RBTree() +let randomMax = Double(0x100000000) +var values = [Double]() +for _ in 0..<1000 { + let value = Double(arc4random()) / randomMax + values.append(value) + tree.insert(value) +} +tree.verify() + +for _ in 0..<1000 { + let rand = arc4random_uniform(UInt32(values.count)) + let index = Int(rand) + let value = values.remove(at: index) + tree.delete(value) +} +tree.verify() diff --git a/Red-Black Tree 2/Red-Black Tree 2.playground/Sources/RBTree.swift b/Red-Black Tree 2/Red-Black Tree 2.playground/Sources/RBTree.swift index adfd38216..1735798d5 100644 --- a/Red-Black Tree 2/Red-Black Tree 2.playground/Sources/RBTree.swift +++ b/Red-Black Tree 2/Red-Black Tree 2.playground/Sources/RBTree.swift @@ -55,13 +55,11 @@ public class RBTNode: CustomStringConvertible { return parent.parent } - public var sibling: RBTNode! { + public var sibling: RBTNode { if isLeftChild { return self.parent.right - } else if isRightChild { - return self.parent.left } else { - return nil + return self.parent.left } } @@ -245,6 +243,8 @@ public class RBTree: CustomStringConvertible { } else if n.parent.isRightChild && n.isLeftChild { // right left case rightRotate(n: n.parent) insertCase5(n: n.right) + } else { + insertCase5(n: n) } } @@ -320,81 +320,91 @@ public class RBTree: CustomStringConvertible { child.color = .doubleBlack while child.isDoubleBlack || (child.parent !== nullLeaf && child.parent != nil) { - if sibling!.isBlack { + if sibling.isBlack { var leftRedChild: RBTNode! = nil - if sibling!.left.isRed { - leftRedChild = sibling!.left + if sibling.left.isRed { + leftRedChild = sibling.left } var rightRedChild: RBTNode! = nil - if sibling!.right.isRed { - rightRedChild = sibling!.right + if sibling.right.isRed { + rightRedChild = sibling.right } if leftRedChild != nil || rightRedChild != nil { // at least one of sibling's children are red child.color = .black - if sibling!.isLeftChild { + if sibling.isLeftChild { if leftRedChild != nil { // left left case - sibling!.left.color = .black - let tempColor = sibling!.parent.color - sibling!.parent.color = sibling!.color - sibling!.color = tempColor - rightRotate(n: sibling!.parent) + sibling.left.color = .black + let tempColor = sibling.parent.color + sibling.parent.color = sibling.color + sibling.color = tempColor + rightRotate(n: sibling.parent) } else { // left right case - if sibling!.parent.isRed { - sibling!.parent.color = .black + if sibling.parent.isRed { + sibling.parent.color = .black } else { - sibling!.right.color = .black + sibling.right.color = .black } - leftRotate(n: sibling!) - rightRotate(n: sibling!.grandparent) + leftRotate(n: sibling) + rightRotate(n: sibling.grandparent) } } else { if rightRedChild != nil { // right right case - sibling!.right.color = .black - let tempColor = sibling!.parent.color - sibling!.parent.color = sibling!.color - sibling!.color = tempColor - leftRotate(n: sibling!.parent) + sibling.right.color = .black + let tempColor = sibling.parent.color + sibling.parent.color = sibling.color + sibling.color = tempColor + leftRotate(n: sibling.parent) } else { // right left case - if sibling!.parent.isRed { - sibling!.parent.color = .black + if sibling.parent.isRed { + sibling.parent.color = .black } else { - sibling!.left.color = .black + sibling.left.color = .black } - rightRotate(n: sibling!) - leftRotate(n: sibling!.grandparent) + rightRotate(n: sibling) + leftRotate(n: sibling.grandparent) } } break } else { // both sibling's children are black child.color = .black - sibling!.color = .red - if sibling!.parent.isRed { - sibling!.parent.color = .black + sibling.color = .red + if sibling.parent.isRed { + sibling.parent.color = .black break } - sibling!.parent.color = .doubleBlack - child = sibling!.parent + /* + sibling.parent.color = .doubleBlack + child = sibling.parent sibling = child.sibling + */ + if sibling.parent.parent === nullLeaf { // parent of child is root + break + } else { + sibling.parent.color = .doubleBlack + child = sibling.parent + sibling = child.sibling // can become nill if child is root as parent is nullLeaf + } + //--------------- } } else { // sibling is red - sibling!.color = .black + sibling.color = .black - if sibling!.isLeftChild { // left case - rightRotate(n: sibling!.parent) - sibling = sibling!.right.left - sibling!.parent.color = .red + if sibling.isLeftChild { // left case + rightRotate(n: sibling.parent) + sibling = sibling.right.left + sibling.parent.color = .red } else { // right case - leftRotate(n: sibling!.parent) - sibling = sibling!.left.right - sibling!.parent.color = .red + leftRotate(n: sibling.parent) + sibling = sibling.left.right + sibling.parent.color = .red } } // sibling check is here for when child is a nullLeaf and thus does not have a parent. // child is here as sibling can become nil when child is the root - if (sibling != nil && sibling!.parent === nullLeaf) || (child !== nullLeaf && child.parent === nullLeaf) { + if (sibling.parent === nullLeaf) || (child !== nullLeaf && child.parent === nullLeaf) { child.color = .black } } From 4800819588174de53542fc9a4b791d931e035541 Mon Sep 17 00:00:00 2001 From: Jaap Date: Tue, 20 Sep 2016 02:04:02 +0200 Subject: [PATCH 0550/1679] Updated readme --- Red-Black Tree 2/README.markdown | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Red-Black Tree 2/README.markdown b/Red-Black Tree 2/README.markdown index abb1c2f55..47fc6a08f 100644 --- a/Red-Black Tree 2/README.markdown +++ b/Red-Black Tree 2/README.markdown @@ -8,3 +8,5 @@ http://www.geeksforgeeks.org/red-black-tree-set-2-insert/ http://www.geeksforgeeks.org/red-black-tree-set-3-delete-2/ Important to note is that the last one doesn't mention a few important details about deletion cases which can be found in the code itself. + +*Written for Swift Algorithm Club by Jaap Wijnen* From 64f93cf4945fadde007756e040dbef4eb0d92ec9 Mon Sep 17 00:00:00 2001 From: Dee Date: Tue, 20 Sep 2016 13:35:59 +0800 Subject: [PATCH 0551/1679] make some conversion --- .../kthLargest.playground/Contents.swift | 34 +++++++++---------- .../xcshareddata/kthLargest.xcscmblueprint | 30 ++++++++++++++++ .../kthLargest.playground/timeline.xctimeline | 6 ---- 3 files changed, 47 insertions(+), 23 deletions(-) create mode 100644 Kth Largest Element/kthLargest.playground/playground.xcworkspace/xcshareddata/kthLargest.xcscmblueprint delete mode 100644 Kth Largest Element/kthLargest.playground/timeline.xctimeline diff --git a/Kth Largest Element/kthLargest.playground/Contents.swift b/Kth Largest Element/kthLargest.playground/Contents.swift index 628892d9c..9fba2b483 100644 --- a/Kth Largest Element/kthLargest.playground/Contents.swift +++ b/Kth Largest Element/kthLargest.playground/Contents.swift @@ -1,9 +1,9 @@ //: Playground - noun: a place where people can play -func kthLargest(a: [Int], k: Int) -> Int? { +func kthLargest(_ a: [Int], _ k: Int) -> Int? { let len = a.count if k > 0 && k <= len { - let sorted = a.sort() + let sorted = a.sorted() return sorted[len - k] } else { return nil @@ -12,15 +12,15 @@ func kthLargest(a: [Int], k: Int) -> Int? { let a = [5, 1, 3, 2, 7, 6, 4] -kthLargest(a, k: 0) -kthLargest(a, k: 1) -kthLargest(a, k: 2) -kthLargest(a, k: 3) -kthLargest(a, k: 4) -kthLargest(a, k: 5) -kthLargest(a, k: 6) -kthLargest(a, k: 7) -kthLargest(a, k: 8) +kthLargest(a, 0) +kthLargest(a, 1) +kthLargest(a, 2) +kthLargest(a, 3) +kthLargest(a, 4) +kthLargest(a, 5) +kthLargest(a, 6) +kthLargest(a, 7) +kthLargest(a, 8) @@ -28,7 +28,7 @@ kthLargest(a, k: 8) import Foundation /* Returns a random integer in the range min...max, inclusive. */ -public func random(min min: Int, max: Int) -> Int { +public func random( min: Int, max: Int) -> Int { assert(min < max) return min + Int(arc4random_uniform(UInt32(max - min + 1))) } @@ -37,22 +37,22 @@ public func random(min min: Int, max: Int) -> Int { Swift's swap() doesn't like it if the items you're trying to swap refer to the same memory location. This little wrapper simply ignores such swaps. */ -public func swap(inout a: [T], _ i: Int, _ j: Int) { +public func swap(_ a:inout [T], _ i: Int, _ j: Int) { if i != j { swap(&a[i], &a[j]) } } -public func randomizedSelect(array: [T], order k: Int) -> T { +public func randomizedSelect(_ array: [T], order k: Int) -> T { var a = array - func randomPivot(inout a: [T], _ low: Int, _ high: Int) -> T { + func randomPivot(_ a: inout[T], _ low: Int, _ high: Int) -> T { let pivotIndex = random(min: low, max: high) swap(&a, pivotIndex, high) return a[high] } - func randomizedPartition(inout a: [T], _ low: Int, _ high: Int) -> Int { + func randomizedPartition(_ a: inout[T], _ low: Int, _ high: Int) -> Int { let pivot = randomPivot(&a, low, high) var i = low for j in low..(array: [T], order k: Int) -> T { return i } - func randomizedSelect(inout a: [T], _ low: Int, _ high: Int, _ k: Int) -> T { + func randomizedSelect(_ a: inout [T], _ low: Int, _ high: Int, _ k: Int) -> T { if low < high { let p = randomizedPartition(&a, low, high) if k == p { diff --git a/Kth Largest Element/kthLargest.playground/playground.xcworkspace/xcshareddata/kthLargest.xcscmblueprint b/Kth Largest Element/kthLargest.playground/playground.xcworkspace/xcshareddata/kthLargest.xcscmblueprint new file mode 100644 index 000000000..c747b8a38 --- /dev/null +++ b/Kth Largest Element/kthLargest.playground/playground.xcworkspace/xcshareddata/kthLargest.xcscmblueprint @@ -0,0 +1,30 @@ +{ + "DVTSourceControlWorkspaceBlueprintPrimaryRemoteRepositoryKey" : "CF309AABC690F91A443043D5C69EECB0069B5411", + "DVTSourceControlWorkspaceBlueprintWorkingCopyRepositoryLocationsKey" : { + + }, + "DVTSourceControlWorkspaceBlueprintWorkingCopyStatesKey" : { + "CF309AABC690F91A443043D5C69EECB0069B5411" : 9223372036854775807, + "FA0506A44181383605977F2A9C8020B861F7CE04" : 9223372036854775807 + }, + "DVTSourceControlWorkspaceBlueprintIdentifierKey" : "6CCD70DA-EE44-4E31-98F0-6DA8B083772A", + "DVTSourceControlWorkspaceBlueprintWorkingCopyPathsKey" : { + "CF309AABC690F91A443043D5C69EECB0069B5411" : "swift-algorithm-club\/", + "FA0506A44181383605977F2A9C8020B861F7CE04" : "" + }, + "DVTSourceControlWorkspaceBlueprintNameKey" : "kthLargest", + "DVTSourceControlWorkspaceBlueprintVersion" : 204, + "DVTSourceControlWorkspaceBlueprintRelativePathToProjectKey" : "Kth Largest Element\/kthLargest.playground", + "DVTSourceControlWorkspaceBlueprintRemoteRepositoriesKey" : [ + { + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/github.com\/Deeer\/swift-algorithm-club.git", + "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git", + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "CF309AABC690F91A443043D5C69EECB0069B5411" + }, + { + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/github.com\/Deeer\/CuteSticker.git", + "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git", + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "FA0506A44181383605977F2A9C8020B861F7CE04" + } + ] +} \ No newline at end of file diff --git a/Kth Largest Element/kthLargest.playground/timeline.xctimeline b/Kth Largest Element/kthLargest.playground/timeline.xctimeline deleted file mode 100644 index bf468afec..000000000 --- a/Kth Largest Element/kthLargest.playground/timeline.xctimeline +++ /dev/null @@ -1,6 +0,0 @@ - - - - - From b4b572f4dcf580d550f5757f547e761db78a30b1 Mon Sep 17 00:00:00 2001 From: SendilKumar N Date: Tue, 20 Sep 2016 22:30:03 +0800 Subject: [PATCH 0552/1679] updated fizzBuzz to swift3 --- Fizz Buzz/FizzBuzz.playground/Contents.swift | 2 +- .../playground.xcworkspace/contents.xcworkspacedata | 7 +++++++ Fizz Buzz/FizzBuzz.playground/timeline.xctimeline | 6 ------ Fizz Buzz/FizzBuzz.swift | 2 +- Fizz Buzz/README.markdown | 2 +- 5 files changed, 10 insertions(+), 9 deletions(-) create mode 100644 Fizz Buzz/FizzBuzz.playground/playground.xcworkspace/contents.xcworkspacedata delete mode 100644 Fizz Buzz/FizzBuzz.playground/timeline.xctimeline diff --git a/Fizz Buzz/FizzBuzz.playground/Contents.swift b/Fizz Buzz/FizzBuzz.playground/Contents.swift index 9d7a974fa..ba2f83b15 100644 --- a/Fizz Buzz/FizzBuzz.playground/Contents.swift +++ b/Fizz Buzz/FizzBuzz.playground/Contents.swift @@ -1,4 +1,4 @@ -func fizzBuzz(numberOfTurns: Int) { +func fizzBuzz(_ numberOfTurns: Int) { for i in 1...numberOfTurns { var result = "" diff --git a/Fizz Buzz/FizzBuzz.playground/playground.xcworkspace/contents.xcworkspacedata b/Fizz Buzz/FizzBuzz.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Fizz Buzz/FizzBuzz.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Fizz Buzz/FizzBuzz.playground/timeline.xctimeline b/Fizz Buzz/FizzBuzz.playground/timeline.xctimeline deleted file mode 100644 index bf468afec..000000000 --- a/Fizz Buzz/FizzBuzz.playground/timeline.xctimeline +++ /dev/null @@ -1,6 +0,0 @@ - - - - - diff --git a/Fizz Buzz/FizzBuzz.swift b/Fizz Buzz/FizzBuzz.swift index a801f34ee..b6bb410e7 100644 --- a/Fizz Buzz/FizzBuzz.swift +++ b/Fizz Buzz/FizzBuzz.swift @@ -1,4 +1,4 @@ -func fizzBuzz(numberOfTurns: Int) { +func fizzBuzz(_ numberOfTurns: Int) { for i in 1...numberOfTurns { var result = "" diff --git a/Fizz Buzz/README.markdown b/Fizz Buzz/README.markdown index e4cf485ff..8c250da27 100644 --- a/Fizz Buzz/README.markdown +++ b/Fizz Buzz/README.markdown @@ -58,7 +58,7 @@ Finding numbers divisible by five: Here is a simple implementation in Swift: ```swift -func fizzBuzz(numberOfTurns: Int) { +func fizzBuzz(_ numberOfTurns: Int) { for i in 1...numberOfTurns { var result = "" From 3e6623179d8809e27fc9b151a3fd9d1ede4f503d Mon Sep 17 00:00:00 2001 From: Jaap Date: Tue, 20 Sep 2016 17:58:01 +0200 Subject: [PATCH 0553/1679] updated readme --- Red-Black Tree 2/README.markdown | 119 +++++++++++++++++++++++++++++-- 1 file changed, 113 insertions(+), 6 deletions(-) diff --git a/Red-Black Tree 2/README.markdown b/Red-Black Tree 2/README.markdown index 47fc6a08f..9496e6318 100644 --- a/Red-Black Tree 2/README.markdown +++ b/Red-Black Tree 2/README.markdown @@ -1,12 +1,119 @@ # Red-Black Tree -Used info from +A Red-Black tree is a special version of a [Binary Search Tree](https://github.com/raywenderlich/swift-algorithm-club/tree/master/Binary%20Search%20Tree). Binary search trees(BSTs) can become unbalanced after a lot of insertions/deletions. The only difference between a node from a BST and a Red-Black Tree(RBT) is that RBT nodes have a color property added to them which can either be red or black. A RBT rebalances itself by making sure the following properties hold: -https://en.wikipedia.org/wiki/Red–black_tree -http://www.geeksforgeeks.org/red-black-tree-set-1-introduction-2/ -http://www.geeksforgeeks.org/red-black-tree-set-2-insert/ -http://www.geeksforgeeks.org/red-black-tree-set-3-delete-2/ +## Properties +1. A node is either red or black +2. The root is always black +3. All leaves are black +4. If a node is red, both of its children are black +5. Every path to a leaf contains the same number of black nodes (The amount of black nodes met when going down a RBT is called the black-depth of the tree.) -Important to note is that the last one doesn't mention a few important details about deletion cases which can be found in the code itself. +## Methods +* `insert(_ value: T)` inserts the value into the tree +* `insert(_ values: [T])` inserts an array of values into the tree +* `delete(_ value: T)` deletes the value from the tree +* `find(_ value: T) -> RBTNode` looks for a node in the tree with given value and returns it +* `minimum(n: RBTNode) -> RBTNode` looks for the maximum value of a subtree starting at the given node +* `maximum(n: RBTNode) -> RBTNode` looks for the minimum value of a subtree starting at the given node +* `func verify()` verifies if the tree is still valid. Prints warning messages if this is not the case + +## Rotation + +In order to rebalance their nodes RBTs use an operation known as rotation. You can either left or right rotate a node and its child. Rotating a node and its child swaps the nodes and interchanges their subtrees. Left rotation swaps the parent node with its right child. while right rotation swaps the parent node with its left child. + +Left rotation: +``` +before left rotating p after left rotating p + p b + / \ / \ + a b -> p n + / \ / \ / \ +n n n n a n + / \ + n n +``` +Right rotation: +``` +before right rotating p after right rotating p + p a + / \ / \ + a b -> n p + / \ / \ / \ +n n n n n b + / \ + n n +``` + +## Insertion + +We create a new node with the value to be inserted into the tree. The color of this new node is always red. +We perform a standard BST insert with this node. Now the three might not be a valid RBT anymore. +We now go through several insertion steps in order to make the tree valid again. We call the just inserted node n. +1. We check if n is the rootNode, if so we paint it black and we are done. If not we go to step 2. + +We now know that n at least has a parent as it is not the rootNode. + +2. We check if the parent of n is black if so we are done. If not we go to step 3. + +We now know the parent is also not the root node as the parent is red. Thus n also has a grandparent and thus also an uncle as every node has two children. This uncle may however be a nullLeaf + +3. We check if n's uncle is red. If not we go to 4. If n's uncle is indeed red we recolor uncle and parent to black and n's grandparent to red. We now go back to step 1 performing the same logic on n's grandparent. + +From here there are four cases: +- **The left left case.** n's parent is the left child of its parent and n is the left child of its parent. +- **The left right case** n's parent is the left child of its parent and n is the right child of its parent. +- **The right right case** n's parent is the right child of its parent and n is the right child of its parent. +- **The right left case** n's parent is the right child of its parent and n is the left child of its parent. + +4. Step 4 checks if either the **left right** case or the **right left** case applies to the current situation. + - If we find the **left right case**, we left rotate n's parent and go to step 5 while setting n to n's parent. (This transforms the **left right** case into the **left left** case) + - If we find the **right left case**, we right rotate n's parent and go to step 5 while setting n to n's parent. (This transforms the **right left** case into the **right right** case) + - If we find neither of these two we proceed to step 5. + +n's parent is now red, while n's grandparent is black. + +5. We swap the colors of n's parent and grandparent. + - We either right rotate n's grandparent in case of the **left left** case + - Or we left rotate n's grandparent in case of the **right right** case + +Reaching the end we have successfully made the tree valid again. + +# Deletion + +Deletion is a little more complicated than insertion. In the following we call del the node to be deleted. +First we try and find the node to be deleted using find() +we send the result of find to del. +We now go through the following steps in order to delete the node del. + +First we do a few checks: +- Is del the rootNode if so set the root to a nullLeaf and we are done. +- If del has 2 nullLeaf children and is red. We check if del is either a left or a right child and set del's parent left or right to a nullLeaf. +- If del has two non nullLeaf children we look for the maximum value in del's left subtree. We set del's value to this maximum value and continue to instead delete this maximum node. Which we will now call del. + +Because of these checks we now know that del has at most 1 non nullLeaf child. It has either two nullLeaf children or one nullLeaf and one regular red child. (The child is red otherwise the black-depth wouldn't be the same for every leaf) + +We now call the non nullLeaf child of del, child. If del has two nullLeaf children child will be a nullLeaf. This means child can either be a nullLeaf or a red node. + +We now have three options + +- If del is red its child is a nullLeaf and we can just delete it as it doesn't change the black-depth of the tree. We are done + +- If child is red we recolor it black and child's parent to del's parent. del is now deleted and we are done. + +- Both del and child are black we go through + +If both del and child are black we introduce a new variable sibling. Which is del's sibling. We also replace del with child and recolor it doubleBlack. del is now deleted and child and sibling are siblings. + +We now have to go through a lot of steps in order to remove this doubleBlack color. Which are hard to explain in text without just writing the full code in text. This is due the many possible combination of nodes and colors. The code is commented, but if you don't quite understand please leave me a message. Also part of the deletion is described by the final link in the Also See section. + +## Also see + +* [Wikipedia](https://en.wikipedia.org/wiki/Red–black_tree) +* [GeeksforGeeks - introduction](http://www.geeksforgeeks.org/red-black-tree-set-1-introduction-2/) +* [GeeksforGeeks - insertion](http://www.geeksforgeeks.org/red-black-tree-set-2-insert/) +* [GeeksforGeeks - deletion](http://www.geeksforgeeks.org/red-black-tree-set-3-delete-2/) + +Important to note is that GeeksforGeeks doesn't mention a few deletion cases that do occur. The code however does implement these. *Written for Swift Algorithm Club by Jaap Wijnen* From 551fd6dec6f3490046d31a9ec726a8395c3245a0 Mon Sep 17 00:00:00 2001 From: Jaap Date: Tue, 20 Sep 2016 18:10:37 +0200 Subject: [PATCH 0554/1679] replaced old RBTree with new implementation --- Red-Black Tree 2/RBTree.swift | Bin 1104 -> 0 bytes Red-Black Tree/RBTree.swift | Bin 13367 -> 1104 bytes .../README.markdown | 0 Red-Black Tree/README.md | 69 ------------------ .../Contents.swift | 0 .../Sources/RBTree.swift | 0 .../contents.xcplayground | 0 .../contents.xcworkspacedata | 0 Red-Black Tree/files/fig1.png | Bin 24455 -> 0 bytes Red-Black Tree/files/fig2.png | Bin 40534 -> 0 bytes 10 files changed, 69 deletions(-) delete mode 100644 Red-Black Tree 2/RBTree.swift rename {Red-Black Tree 2 => Red-Black Tree}/README.markdown (100%) delete mode 100644 Red-Black Tree/README.md rename {Red-Black Tree 2 => Red-Black Tree}/Red-Black Tree 2.playground/Contents.swift (100%) rename {Red-Black Tree 2 => Red-Black Tree}/Red-Black Tree 2.playground/Sources/RBTree.swift (100%) rename {Red-Black Tree 2 => Red-Black Tree}/Red-Black Tree 2.playground/contents.xcplayground (100%) rename {Red-Black Tree 2 => Red-Black Tree}/Red-Black Tree 2.playground/playground.xcworkspace/contents.xcworkspacedata (100%) delete mode 100644 Red-Black Tree/files/fig1.png delete mode 100644 Red-Black Tree/files/fig2.png diff --git a/Red-Black Tree 2/RBTree.swift b/Red-Black Tree 2/RBTree.swift deleted file mode 100644 index 0ed831f72932e9675aa57dc32405330ef33285a7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1104 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 diff --git a/Red-Black Tree 2/README.markdown b/Red-Black Tree/README.markdown similarity index 100% rename from Red-Black Tree 2/README.markdown rename to Red-Black Tree/README.markdown diff --git a/Red-Black Tree/README.md b/Red-Black Tree/README.md deleted file mode 100644 index e1b887c3a..000000000 --- a/Red-Black Tree/README.md +++ /dev/null @@ -1,69 +0,0 @@ -# Red Black Tree -![fig1](files/fig1.png) -Red-black trees are an evolution of binary search trees that aim to keep the tree balanced without affecting the complexity of the primitive operations. This is done by coloring each node in the tree with either red or black and preserving a set of properties that guarantee that the deepest path in the tree is not longer than twice the shortest one. -## Motivation: -* We want a balanced binary search tree -* Height of the tree is O(log n) -* Red-Black Tree is an implementation of a balanced binary search tree - - -## Invariants: -1. Every node is colored either red or black -2. All leaf (nil) nodes are colored with black; if a node’s child is missing then we will assume that it has a nil child in that place and this nil child is always colored black. -3. Both children of a red node must be black nodes. -4. Every path from a node n to a descendent leaf has the same number of black nodes (not counting node n). - -## Methods: - -Since the red-black tree is a balanced BST, it supports the functions: - * find(key) - * Predecessor(key) - * Successor(key) - * Minimum(key) - * maximum(key) - * insert(key) - * delete(key) - -Since an insertion or deletion may violate one of the invariant's of the red-black tree we must either change colors, or perform rotation actions. - -#Rotation -To ensure that its color scheme and properties don’t get thrown off, red-black trees employ a key operation known as rotation. Rotation is a binary operation, between a parent node and one of its children, that swaps nodes and modifys their pointers while preserving the inorder traversal of the tree (so that elements are still sorted). There are two types of rotations: left rotation and right rotation. Left rotation swaps the parent node with its right child, while right rotation swaps the parent node with its left child. -![fig2](files/fig2.png) -###Left-Rotation: -```c++ -y ← x->right -x->right ← y->left -y->left->p ← x -y->p ← x->p -if x->p = Null - then T->root ← y - else if x = x->p->left - then x->p->left ← y - else x->p->right ← y -y->left ← x -x->p ← y -``` -###Right-Rotation: -```c++ -y ← x->left -x->left ← y->right -y->right->p ← x -y->p ← x->p -if x->p = Null - then T->root ← y - else if x = x->p->right - then x->p->right ← y - else x->p->left ← y -y->right ← x -x->p ← y -``` -###Insertion: -When adding a new node to a binary search tree, note that the new node will always be a leaf in the tree. To insert a new node, all we will do is navigate the BST starting from the root. If the new node value is smaller than the current node value, we go left – if it is larger, we go right. When we reach a leaf node, the last step is to attach the new node as a child to this leaf node in a way that preserves the BST constraint. We must recheck the RBTree invariants to see if any were violated - -###Deletion: -The same concept behind red-black tree insertions applies here. Removing a node from a red-black tree makes use of the BST deletion procedure and then restores the red-black tree properties in O(log n). The total running time for the deletion process takes O(log n) time, then, which meets the complexity requirements for the primitive operations. - -See also [Wikipedia](https://en.wikipedia.org/wiki/Red%E2%80%93black_tree). - -*Written for the Swift Algorithm Club by Ashwin Raghuraman* - diff --git a/Red-Black Tree 2/Red-Black Tree 2.playground/Contents.swift b/Red-Black Tree/Red-Black Tree 2.playground/Contents.swift similarity index 100% rename from Red-Black Tree 2/Red-Black Tree 2.playground/Contents.swift rename to Red-Black Tree/Red-Black Tree 2.playground/Contents.swift diff --git a/Red-Black Tree 2/Red-Black Tree 2.playground/Sources/RBTree.swift b/Red-Black Tree/Red-Black Tree 2.playground/Sources/RBTree.swift similarity index 100% rename from Red-Black Tree 2/Red-Black Tree 2.playground/Sources/RBTree.swift rename to Red-Black Tree/Red-Black Tree 2.playground/Sources/RBTree.swift diff --git a/Red-Black Tree 2/Red-Black Tree 2.playground/contents.xcplayground b/Red-Black Tree/Red-Black Tree 2.playground/contents.xcplayground similarity index 100% rename from Red-Black Tree 2/Red-Black Tree 2.playground/contents.xcplayground rename to Red-Black Tree/Red-Black Tree 2.playground/contents.xcplayground diff --git a/Red-Black Tree 2/Red-Black Tree 2.playground/playground.xcworkspace/contents.xcworkspacedata b/Red-Black Tree/Red-Black Tree 2.playground/playground.xcworkspace/contents.xcworkspacedata similarity index 100% rename from Red-Black Tree 2/Red-Black Tree 2.playground/playground.xcworkspace/contents.xcworkspacedata rename to Red-Black Tree/Red-Black Tree 2.playground/playground.xcworkspace/contents.xcworkspacedata diff --git a/Red-Black Tree/files/fig1.png b/Red-Black Tree/files/fig1.png deleted file mode 100644 index 7a91eb6932feddfc00890e16aeec6e1a079a75b9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24455 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 SRfALbFQI*$ax9N*;r%bz3+-zF diff --git a/Red-Black Tree/files/fig2.png b/Red-Black Tree/files/fig2.png deleted file mode 100644 index 35b81e61c61f11906814e5503daf19847120a4a2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 40534 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 From 52a29a16b2efb745a796017236acecf904474f8b Mon Sep 17 00:00:00 2001 From: Jaap Date: Tue, 20 Sep 2016 18:12:34 +0200 Subject: [PATCH 0555/1679] removed bad alias --- Red-Black Tree/RBTree.swift | Bin 1104 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 Red-Black Tree/RBTree.swift diff --git a/Red-Black Tree/RBTree.swift b/Red-Black Tree/RBTree.swift deleted file mode 100644 index 0ed831f72932e9675aa57dc32405330ef33285a7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1104 zcmZ{jzi-n(6vxkL3PtLWv`CEr2@5eGR5zhc+R|2{af}3|FtiC%7stM~R-HJq9idJX z)CqN9U}QjuKY*bdv??1TBNDJNBGCbupyB(RyQD_qN#DEAd-weAr|Z7I$zTmDi2E5Z zDVL^bIzw#`<`);fw9>iV{WAG$k!BsGFbW9ErxXT@&^ zHV@gb{KlXf6Y+E^#ZECs^AL|iwAU)+K~JF<&=8cyzOq-5e8PYDIO+d6h>xe2|8D0v zkzaU{^k-it{kebqdEu+5LhJmD{u}fg8pgR?fX1PDXbGZq(%F~yce8WA9Hii0FcjNG zFq!O$69DGUfL;xnFcoy*0i0 z^jw918KOHanK!3&W7^OruT@M<*9)e0U9U`Q72PP7r)G>|si@2KKca7-@1x0{VpJ=S z{+!@@E4Ae%)3@6V-i&TLXxufI2Y2{Ze=i3(hZ5zZcbaY;*gGR)Y4nE4;>U6W)^+1n z#k|LzPKVY&HU`n(u@`%I|KL?Im;pZ%ya3)2Tm`=sTsy({!FwW}QW=ZHy$yoDig*V6 zLvR*+MdXZthXjv;bAnZHRd4|;>nn$hy_a>s7>aG=kg<; Date: Tue, 20 Sep 2016 14:02:16 -0700 Subject: [PATCH 0556/1679] Added credit to previous author. --- Red-Black Tree/README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Red-Black Tree/README.markdown b/Red-Black Tree/README.markdown index 9496e6318..d4e86a095 100644 --- a/Red-Black Tree/README.markdown +++ b/Red-Black Tree/README.markdown @@ -116,4 +116,4 @@ We now have to go through a lot of steps in order to remove this doubleBlack col Important to note is that GeeksforGeeks doesn't mention a few deletion cases that do occur. The code however does implement these. -*Written for Swift Algorithm Club by Jaap Wijnen* +*Written for Swift Algorithm Club by Jaap Wijnen. Updated from Ashwin Raghuraman's contribution.* From c4a4c89d644476cbf01cde349156f4223c7280ab Mon Sep 17 00:00:00 2001 From: SendilKumar N Date: Wed, 21 Sep 2016 12:06:09 +0800 Subject: [PATCH 0557/1679] deque update to swift 3 updated readme --- Deque/Deque-Optimized.swift | 6 +++--- Deque/Deque-Simple.swift | 4 ++-- Deque/Deque.playground/Contents.swift | 6 +++--- Deque/Deque.playground/timeline.xctimeline | 6 ------ Deque/README.markdown | 10 +++++----- 5 files changed, 13 insertions(+), 19 deletions(-) delete mode 100644 Deque/Deque.playground/timeline.xctimeline diff --git a/Deque/Deque-Optimized.swift b/Deque/Deque-Optimized.swift index ea68059c0..17ff89e68 100644 --- a/Deque/Deque-Optimized.swift +++ b/Deque/Deque-Optimized.swift @@ -8,7 +8,7 @@ public struct Deque { private var head: Int private var capacity: Int - public init(capacity: Int = 10) { + public init(_ capacity: Int = 10) { self.capacity = max(capacity, 1) array = .init(count: capacity, repeatedValue: nil) head = capacity @@ -22,11 +22,11 @@ public struct Deque { return array.count - head } - public mutating func enqueue(element: T) { + public mutating func enqueue(_ element: T) { array.append(element) } - public mutating func enqueueFront(element: T) { + public mutating func enqueueFront(_ element: T) { if head == 0 { capacity *= 2 let emptySpace = [T?](count: capacity, repeatedValue: nil) diff --git a/Deque/Deque-Simple.swift b/Deque/Deque-Simple.swift index 0ccba0caa..f4f5f0409 100644 --- a/Deque/Deque-Simple.swift +++ b/Deque/Deque-Simple.swift @@ -16,11 +16,11 @@ public struct Deque { return array.count } - public mutating func enqueue(element: T) { + public mutating func enqueue(_ element: T) { array.append(element) } - public mutating func enqueueFront(element: T) { + public mutating func enqueueFront(_ element: T) { array.insert(element, atIndex: 0) } diff --git a/Deque/Deque.playground/Contents.swift b/Deque/Deque.playground/Contents.swift index 15bf1ee07..9e7b22c02 100644 --- a/Deque/Deque.playground/Contents.swift +++ b/Deque/Deque.playground/Contents.swift @@ -11,12 +11,12 @@ public struct Deque { return array.count } - public mutating func enqueue(element: T) { + public mutating func enqueue(_ element: T) { array.append(element) } - public mutating func enqueueFront(element: T) { - array.insert(element, atIndex: 0) + public mutating func enqueueFront(_ element: T) { + array.insert(element, at: 0) } public mutating func dequeue() -> T? { diff --git a/Deque/Deque.playground/timeline.xctimeline b/Deque/Deque.playground/timeline.xctimeline deleted file mode 100644 index bf468afec..000000000 --- a/Deque/Deque.playground/timeline.xctimeline +++ /dev/null @@ -1,6 +0,0 @@ - - - - - diff --git a/Deque/README.markdown b/Deque/README.markdown index 3329adca0..7671555dc 100644 --- a/Deque/README.markdown +++ b/Deque/README.markdown @@ -18,11 +18,11 @@ public struct Deque { return array.count } - public mutating func enqueue(element: T) { + public mutating func enqueue(_ element: T) { array.append(element) } - public mutating func enqueueFront(element: T) { + public mutating func enqueueFront(_ element: T) { array.insert(element, atIndex: 0) } @@ -120,7 +120,7 @@ public struct Deque { private var head: Int private var capacity: Int - public init(capacity: Int = 10) { + public init(_ capacity: Int = 10) { self.capacity = max(capacity, 1) array = .init(count: capacity, repeatedValue: nil) head = capacity @@ -134,11 +134,11 @@ public struct Deque { return array.count - head } - public mutating func enqueue(element: T) { + public mutating func enqueue(_ element: T) { array.append(element) } - public mutating func enqueueFront(element: T) { + public mutating func enqueueFront(_ element: T) { // this is explained below } From 4efac1614da03629229c2913da7896ce27199ec0 Mon Sep 17 00:00:00 2001 From: Jaap Date: Thu, 22 Sep 2016 02:00:24 +0200 Subject: [PATCH 0558/1679] Updated OrderedArray to Swift 3 --- .../OrderedArray.playground/Contents.swift | 36 ++++++++++--------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/Ordered Array/OrderedArray.playground/Contents.swift b/Ordered Array/OrderedArray.playground/Contents.swift index aae146ca2..dfbf67fcb 100644 --- a/Ordered Array/OrderedArray.playground/Contents.swift +++ b/Ordered Array/OrderedArray.playground/Contents.swift @@ -1,10 +1,10 @@ //: Playground - noun: a place where people can play public struct OrderedArray { - private var array = [T]() + fileprivate var array = [T]() public init(array: [T]) { - self.array = array.sort() + self.array = array.sorted() } public var isEmpty: Bool { @@ -20,16 +20,16 @@ public struct OrderedArray { } public mutating func removeAtIndex(index: Int) -> T { - return array.removeAtIndex(index) + return array.remove(at: index) } public mutating func removeAll() { array.removeAll() } - public mutating func insert(newElement: T) -> Int { - let i = findInsertionPoint(newElement) - array.insert(newElement, atIndex: i) + public mutating func insert(_ newElement: T) -> Int { + let i = findInsertionPoint(newElement: newElement) + array.insert(newElement, at: i) return i } @@ -47,18 +47,20 @@ public struct OrderedArray { // Fast version that uses a binary search. private func findInsertionPoint(newElement: T) -> Int { - var range = 0.. Date: Thu, 22 Sep 2016 02:09:38 +0200 Subject: [PATCH 0559/1679] updated readme --- .../OrderedArray.playground/Contents.swift | 4 +- Ordered Array/README.markdown | 52 ++++++++++--------- 2 files changed, 29 insertions(+), 27 deletions(-) diff --git a/Ordered Array/OrderedArray.playground/Contents.swift b/Ordered Array/OrderedArray.playground/Contents.swift index dfbf67fcb..1a0320a65 100644 --- a/Ordered Array/OrderedArray.playground/Contents.swift +++ b/Ordered Array/OrderedArray.playground/Contents.swift @@ -28,7 +28,7 @@ public struct OrderedArray { } public mutating func insert(_ newElement: T) -> Int { - let i = findInsertionPoint(newElement: newElement) + let i = findInsertionPoint(newElement) array.insert(newElement, at: i) return i } @@ -46,7 +46,7 @@ public struct OrderedArray { */ // Fast version that uses a binary search. - private func findInsertionPoint(newElement: T) -> Int { + private func findInsertionPoint(_ newElement: T) -> Int { var startIndex = 0 var endIndex = array.count diff --git a/Ordered Array/README.markdown b/Ordered Array/README.markdown index f64e55057..ca088c325 100644 --- a/Ordered Array/README.markdown +++ b/Ordered Array/README.markdown @@ -8,28 +8,28 @@ The implementation is quite basic. It's simply a wrapper around Swift's built-in ```swift public struct OrderedArray { - private var array = [T]() - + fileprivate var array = [T]() + public init(array: [T]) { - self.array = array.sort() + self.array = array.sorted() } public var isEmpty: Bool { return array.isEmpty } - + public var count: Int { return array.count } - + public subscript(index: Int) -> T { return array[index] } - + public mutating func removeAtIndex(index: Int) -> T { - return array.removeAtIndex(index) + return array.remove(at: index) } - + public mutating func removeAll() { array.removeAll() } @@ -47,13 +47,13 @@ As you can see, all these methods simply call the corresponding method on the in What remains is the `insert()` function. Here is an initial stab at it: ```swift - public mutating func insert(newElement: T) -> Int { + public mutating func insert(_ newElement: T) -> Int { let i = findInsertionPoint(newElement) - array.insert(newElement, atIndex: i) + array.insert(newElement, at: i) return i } - private func findInsertionPoint(newElement: T) -> Int { + private func findInsertionPoint(_ newElement: T) -> Int { for i in 0.. **Note:** Quite conveniently, `array.insert(... atIndex: array.count)` adds the new object to the end of the array, so if no suitable insertion point was found we can simply return `array.count` as the index. @@ -81,26 +81,28 @@ a.insert(10) // inserted at index 8 a // [-2, -1, 1, 3, 4, 5, 7, 9, 10] ``` -The array's contents will always be sorted from low to high, now matter what. +The array's contents will always be sorted from low to high, now matter what. Unfortunately, the current `findInsertionPoint()` function is a bit slow. In the worst case, it needs to scan through the entire array. We can speed this up by using a [binary search](../Binary Search) to find the insertion point. Here is the new version: ```swift - private func findInsertionPoint(newElement: T) -> Int { - var range = 0.. Int { + var startIndex = 0 + var endIndex = array.count + + while startIndex < endIndex { + let midIndex = startIndex + (endIndex - startIndex) / 2 + if array[midIndex] == newElement { + return midIndex + } else if array[midIndex] < newElement { + startIndex = midIndex + 1 + } else { + endIndex = midIndex + } } - return range.startIndex + return startIndex } ``` From 9cb0ca2ecffdda661fb4286bf077660c5775b326 Mon Sep 17 00:00:00 2001 From: Jaap Date: Thu, 22 Sep 2016 02:19:54 +0200 Subject: [PATCH 0560/1679] updated Priority Queue to swift 3 --- Priority Queue/PriorityQueue.swift | 10 +++++----- Priority Queue/README.markdown | 4 ++-- Priority Queue/Tests/Tests.xcodeproj/project.pbxproj | 10 +++++++++- .../xcshareddata/xcschemes/Tests.xcscheme | 2 +- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/Priority Queue/PriorityQueue.swift b/Priority Queue/PriorityQueue.swift index 757a6c539..92f7b6d3f 100644 --- a/Priority Queue/PriorityQueue.swift +++ b/Priority Queue/PriorityQueue.swift @@ -11,13 +11,13 @@ queue (largest element first) or a min-priority queue (smallest element first). */ public struct PriorityQueue { - private var heap: Heap + fileprivate var heap: Heap /* To create a max-priority queue, supply a > sort function. For a min-priority queue, use <. */ - public init(sort: (T, T) -> Bool) { + public init(sort: @escaping (T, T) -> Bool) { heap = Heap(sort: sort) } @@ -33,7 +33,7 @@ public struct PriorityQueue { return heap.peek() } - public mutating func enqueue(element: T) { + public mutating func enqueue(_ element: T) { heap.insert(element) } @@ -52,7 +52,7 @@ public struct PriorityQueue { } extension PriorityQueue where T: Equatable { - public func indexOf(element: T) -> Int? { - return heap.indexOf(element) + public func index(of element: T) -> Int? { + return heap.index(of: element) } } diff --git a/Priority Queue/README.markdown b/Priority Queue/README.markdown index 0c04e7445..8308ec16f 100644 --- a/Priority Queue/README.markdown +++ b/Priority Queue/README.markdown @@ -8,7 +8,7 @@ The queue can be a *max-priority* queue (largest element first) or a *min-priori Priority queues are useful for algorithms that need to process a (large) number of items and where you repeatedly need to identify which one is now the biggest or smallest -- or however you define "most important". -Examples of algorithms that can benefit from a priority queue: +Examples of algorithms that can benefit from a priority queue: - Event-driven simulations. Each event is given a timestamp and you want events to be performed in order of their timestamps. The priority queue makes it easy to find the next event that needs to be simulated. - Dijkstra's algorithm for graph searching uses a priority queue to calculate the minimum cost. @@ -39,7 +39,7 @@ Here's a Swift priority queue based on a heap: ```swift public struct PriorityQueue { - private var heap: Heap + fileprivate var heap: Heap public init(sort: (T, T) -> Bool) { heap = Heap(sort: sort) diff --git a/Priority Queue/Tests/Tests.xcodeproj/project.pbxproj b/Priority Queue/Tests/Tests.xcodeproj/project.pbxproj index 5c6a20355..77423c57a 100644 --- a/Priority Queue/Tests/Tests.xcodeproj/project.pbxproj +++ b/Priority Queue/Tests/Tests.xcodeproj/project.pbxproj @@ -86,11 +86,12 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; - LastUpgradeCheck = 0720; + LastUpgradeCheck = 0800; ORGANIZATIONNAME = "Swift Algorithm Club"; TargetAttributes = { 7B2BBC7F1C779D720067B71D = { CreatedOnToolsVersion = 7.2; + LastSwiftMigration = 0800; }; }; }; @@ -149,8 +150,10 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; @@ -193,8 +196,10 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; @@ -213,6 +218,7 @@ MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; }; name = Release; }; @@ -224,6 +230,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -235,6 +242,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Release; }; diff --git a/Priority Queue/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Priority Queue/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme index 8ef8d8581..14f27f777 100644 --- a/Priority Queue/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme +++ b/Priority Queue/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -1,6 +1,6 @@ Date: Thu, 22 Sep 2016 02:52:40 +0200 Subject: [PATCH 0561/1679] updated Ordered Set to swift 3 --- .../Example 1.xcplaygroundpage/Contents.swift | 2 +- .../timeline.xctimeline | 21 ++++++++++ .../Example 2.xcplaygroundpage/Contents.swift | 2 +- .../Example 3.xcplaygroundpage/Contents.swift | 6 +-- .../timeline.xctimeline | 6 +++ .../Sources/OrderedSet.swift | 24 +++++------ .../Sources/Player.swift | 2 +- .../Sources/Random.swift | 2 +- Ordered Set/README.markdown | 40 +++++++++---------- 9 files changed, 66 insertions(+), 39 deletions(-) create mode 100644 Ordered Set/OrderedSet.playground/Pages/Example 1.xcplaygroundpage/timeline.xctimeline create mode 100644 Ordered Set/OrderedSet.playground/Pages/Example 3.xcplaygroundpage/timeline.xctimeline diff --git a/Ordered Set/OrderedSet.playground/Pages/Example 1.xcplaygroundpage/Contents.swift b/Ordered Set/OrderedSet.playground/Pages/Example 1.xcplaygroundpage/Contents.swift index c1fe6fe11..2420019fc 100644 --- a/Ordered Set/OrderedSet.playground/Pages/Example 1.xcplaygroundpage/Contents.swift +++ b/Ordered Set/OrderedSet.playground/Pages/Example 1.xcplaygroundpage/Contents.swift @@ -4,7 +4,7 @@ var mySet = OrderedSet() // Insert random numbers into the set for _ in 0..<50 { - mySet.insert(random(50, max: 500)) + mySet.insert(random(min: 50, max: 500)) } print(mySet) diff --git a/Ordered Set/OrderedSet.playground/Pages/Example 1.xcplaygroundpage/timeline.xctimeline b/Ordered Set/OrderedSet.playground/Pages/Example 1.xcplaygroundpage/timeline.xctimeline new file mode 100644 index 000000000..454d1011b --- /dev/null +++ b/Ordered Set/OrderedSet.playground/Pages/Example 1.xcplaygroundpage/timeline.xctimeline @@ -0,0 +1,21 @@ + + + + + + + + + + + diff --git a/Ordered Set/OrderedSet.playground/Pages/Example 2.xcplaygroundpage/Contents.swift b/Ordered Set/OrderedSet.playground/Pages/Example 2.xcplaygroundpage/Contents.swift index 6fc1f66ed..c30260fff 100644 --- a/Ordered Set/OrderedSet.playground/Pages/Example 2.xcplaygroundpage/Contents.swift +++ b/Ordered Set/OrderedSet.playground/Pages/Example 2.xcplaygroundpage/Contents.swift @@ -23,7 +23,7 @@ print(playerSet.max()) print(playerSet.min()) // We'll find our player now: -let level = playerSet.count - playerSet.indexOf(anotherPlayer)! +let level = playerSet.count - playerSet.index(of: anotherPlayer)! print("\(anotherPlayer.name) is ranked at level \(level) with \(anotherPlayer.points) points") //: [Next](@next) diff --git a/Ordered Set/OrderedSet.playground/Pages/Example 3.xcplaygroundpage/Contents.swift b/Ordered Set/OrderedSet.playground/Pages/Example 3.xcplaygroundpage/Contents.swift index 872b5aeb4..52f154c05 100644 --- a/Ordered Set/OrderedSet.playground/Pages/Example 3.xcplaygroundpage/Contents.swift +++ b/Ordered Set/OrderedSet.playground/Pages/Example 3.xcplaygroundpage/Contents.swift @@ -17,6 +17,6 @@ repeatedSet.insert(Player(name: "Player 9", points: 25)) print(repeatedSet) //debugPrint(repeatedSet) -print(repeatedSet.indexOf(Player(name: "Player 5", points: 100))) -print(repeatedSet.indexOf(Player(name: "Random Player", points: 100))) -print(repeatedSet.indexOf(Player(name: "Player 5", points: 1000))) +print(repeatedSet.index(of: Player(name: "Player 5", points: 100))) +print(repeatedSet.index(of: Player(name: "Random Player", points: 100))) +print(repeatedSet.index(of: Player(name: "Player 5", points: 1000))) diff --git a/Ordered Set/OrderedSet.playground/Pages/Example 3.xcplaygroundpage/timeline.xctimeline b/Ordered Set/OrderedSet.playground/Pages/Example 3.xcplaygroundpage/timeline.xctimeline new file mode 100644 index 000000000..bf468afec --- /dev/null +++ b/Ordered Set/OrderedSet.playground/Pages/Example 3.xcplaygroundpage/timeline.xctimeline @@ -0,0 +1,6 @@ + + + + + diff --git a/Ordered Set/OrderedSet.playground/Sources/OrderedSet.swift b/Ordered Set/OrderedSet.playground/Sources/OrderedSet.swift index a8b3b0966..8490a3320 100644 --- a/Ordered Set/OrderedSet.playground/Sources/OrderedSet.swift +++ b/Ordered Set/OrderedSet.playground/Sources/OrderedSet.swift @@ -14,7 +14,7 @@ public struct OrderedSet { } // Inserts an item. Performance: O(n) - public mutating func insert(item: T) { + public mutating func insert(_ item: T) { if exists(item) { return // don't add an item if it already exists } @@ -22,7 +22,7 @@ public struct OrderedSet { // Insert new the item just before the one that is larger. for i in 0.. item { - internalSet.insert(item, atIndex: i) + internalSet.insert(item, at: i) return } } @@ -32,19 +32,19 @@ public struct OrderedSet { } // Removes an item if it exists. Performance: O(n) - public mutating func remove(item: T) { - if let index = indexOf(item) { - internalSet.removeAtIndex(index) + public mutating func remove(_ item: T) { + if let index = index(of: item) { + internalSet.remove(at: index) } } // Returns true if and only if the item exists somewhere in the set. - public func exists(item: T) -> Bool { - return indexOf(item) != nil + public func exists(_ item: T) -> Bool { + return index(of: item) != nil } // Returns the index of an item if it exists, or -1 otherwise. - public func indexOf(item: T) -> Int? { + public func index(of item: T) -> Int? { var leftBound = 0 var rightBound = count - 1 @@ -64,7 +64,7 @@ public struct OrderedSet { // and to the left in order to find an exact match. // Check to the right. - for j in mid.stride(to: count - 1, by: 1) { + for j in stride(from: mid, to: count - 1, by: 1) { if internalSet[j + 1] == item { return j + 1 } else if internalSet[j] < internalSet[j + 1] { @@ -73,7 +73,7 @@ public struct OrderedSet { } // Check to the left. - for j in mid.stride(to: 0, by: -1) { + for j in stride(from: mid, to: 0, by: -1) { if internalSet[j - 1] == item { return j - 1 } else if internalSet[j] > internalSet[j - 1] { @@ -105,13 +105,13 @@ public struct OrderedSet { // Returns the k-th largest element in the set, if k is in the range // [1, count]. Returns nil otherwise. - public func kLargest(k: Int) -> T? { + public func kLargest(_ k: Int) -> T? { return k > count || k <= 0 ? nil : internalSet[count - k] } // Returns the k-th smallest element in the set, if k is in the range // [1, count]. Returns nil otherwise. - public func kSmallest(k: Int) -> T? { + public func kSmallest(_ k: Int) -> T? { return k > count || k <= 0 ? nil : internalSet[k - 1] } } diff --git a/Ordered Set/OrderedSet.playground/Sources/Player.swift b/Ordered Set/OrderedSet.playground/Sources/Player.swift index 9357744db..26835b0a8 100644 --- a/Ordered Set/OrderedSet.playground/Sources/Player.swift +++ b/Ordered Set/OrderedSet.playground/Sources/Player.swift @@ -6,7 +6,7 @@ public struct Player: Comparable { public init() { self.name = String.random() - self.points = random(0, max: 5000) + self.points = random(min: 0, max: 5000) } public init(name: String, points: Int) { diff --git a/Ordered Set/OrderedSet.playground/Sources/Random.swift b/Ordered Set/OrderedSet.playground/Sources/Random.swift index b6e1f7736..eccd65df6 100644 --- a/Ordered Set/OrderedSet.playground/Sources/Random.swift +++ b/Ordered Set/OrderedSet.playground/Sources/Random.swift @@ -13,7 +13,7 @@ extension String { for _ in 0.. { Lets take a look at the `insert()` function first. This first checks if the item already exists in the collection. If so, it returns and does not insert the item. Otherwise, it will insert the item through straightforward iteration. ```swift - public mutating func insert(item: T){ + public mutating func insert(_ item: T){ if exists(item) { return // don't add an item if it already exists } @@ -63,7 +63,7 @@ Lets take a look at the `insert()` function first. This first checks if the item // Insert new the item just before the one that is larger. for i in 0.. item { - internalSet.insert(item, atIndex: i) + internalSet.insert(item, at: i) return } } @@ -82,19 +82,19 @@ The total performance of the `insert()` function is therefore **O(n)**. Next up is the `remove()` function: ```swift - public mutating func remove(item: T) { - if let index = indexOf(item) { - internalSet.removeAtIndex(index) + public mutating func remove(_ item: T) { + if let index = index(of: item) { + internalSet.remove(at: index) } } ``` First this checks if the item exists and then removes it from the array. Because of the `removeAtIndex()` function, the efficiency for remove is **O(n)**. -The next function is `indexOf()`, which takes in an object of type `T` and returns the index of the corresponding item if it is in the set, or `nil` if it is not. Since our set is sorted, we can use a binary search to quickly search for the item. +The next function is `indexOf()`, which takes in an object of type `T` and returns the index of the corresponding item if it is in the set, or `nil` if it is not. Since our set is sorted, we can use a binary search to quickly search for the item. ```swift - public func indexOf(item: T) -> Int? { + public func index(of item: T) -> Int? { var leftBound = 0 var rightBound = count - 1 @@ -115,9 +115,9 @@ The next function is `indexOf()`, which takes in an object of type `T` and retur } ``` -> **Note:** If you are not familiar with the concept of binary search, we have an [article that explains all about it](../Binary Search). +> **Note:** If you are not familiar with the concept of binary search, we have an [article that explains all about it](../Binary Search). -However, there is an important issue to deal with here. Recall that two objects can be unequal yet still have the same "value" for the purposes of comparing them. Since a set can contain multiple items with the same value, it is important to check that the binary search has landed on the correct item. +However, there is an important issue to deal with here. Recall that two objects can be unequal yet still have the same "value" for the purposes of comparing them. Since a set can contain multiple items with the same value, it is important to check that the binary search has landed on the correct item. For example, consider this ordered set of `Player` objects. Each `Player` has a name and a number of points: @@ -147,13 +147,13 @@ Therefore, we also need to check the items with the same value to the right and break } } - + return nil ``` These loops start at the current `mid` value and then look at the neighboring values until we've found the correct object. -The combined runtime for `indexOf()` is **O(log(n) + k)** where **n** is the length of the set, and **k** is the number of items with the same *value* as the one that is being searched for. +The combined runtime for `indexOf()` is **O(log(n) + k)** where **n** is the length of the set, and **k** is the number of items with the same *value* as the one that is being searched for. Since the set is sorted, the following operations are all **O(1)**: @@ -168,15 +168,15 @@ Since the set is sorted, the following operations are all **O(1)**: return count == 0 ? nil : internalSet[0] } - // Returns the k-th largest element in the set, if k is in the range + // Returns the k-th largest element in the set, if k is in the range // [1, count]. Returns nil otherwise. - public func kLargest(k: Int) -> T? { + public func kLargest(_ k: Int) -> T? { return k > count || k <= 0 ? nil : internalSet[count - k] } // Returns the k-th smallest element in the set, if k is in the range // [1, count]. Returns nil otherwise. - public func kSmallest(k: Int) -> T? { + public func kSmallest(_ k: Int) -> T? { return k > count || k <= 0 ? nil : internalSet[k - 1] } ``` @@ -228,7 +228,7 @@ public struct Player: Comparable { The `Player` also gets its own `==` and `<` operators. The `<` operator is used to determine the sort order of the set, while `==` determines whether two objects are really equal. Note that `==` compares both the name and the points: - + ```swifr func ==(x: Player, y: Player) -> Bool { return x.name == y.name && x.points == y.points @@ -272,7 +272,7 @@ print("\(anotherPlayer.name) is ranked at level \(level) with \(anotherPlayer.po ### Example 3 -The final example demonstrates the need to look for the right item even after the binary search has completed. +The final example demonstrates the need to look for the right item even after the binary search has completed. We insert 9 players into the set: @@ -299,7 +299,7 @@ The set looks something like this: The next line looks for `Player 2`: ```swift -print(repeatedSet.indexOf(Player(name: "Player 2", points: 100))) +print(repeatedSet.index(of: Player(name: "Player 2", points: 100))) ``` After the binary search finishes, the value of `mid` is at index 5: @@ -312,7 +312,7 @@ However, this is not `Player 2`. Both `Player 4` and `Player 2` have the same po But we do know that `Player 2` must be either to the immediate left or the right of `Player 4`, so we check both sides of `mid`. We only need to look at the objects with the same value as `Player 4`. The others are replaced by `X`: [X, X, Player 1, Player 2, Player 3, Player 4, Player 5, X, X] - mid + mid The code then first checks on the right of `mid` (where the `*` is): From 8e4dbdb2721d8171f7ab95dfa0d478c6b9607691 Mon Sep 17 00:00:00 2001 From: ssarber Date: Fri, 23 Sep 2016 10:57:21 -0700 Subject: [PATCH 0562/1679] Convert to Swift 3 syntax to get rid of Xcode 8 errors --- Counting Sort/CountingSort.playground/Contents.swift | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Counting Sort/CountingSort.playground/Contents.swift b/Counting Sort/CountingSort.playground/Contents.swift index 67d416f2f..2d85347ef 100644 --- a/Counting Sort/CountingSort.playground/Contents.swift +++ b/Counting Sort/CountingSort.playground/Contents.swift @@ -1,6 +1,6 @@ //: Playground - noun: a place where people can play -enum CountingSortError: ErrorType { +enum CountingSortError: Error { case ArrayEmpty } @@ -11,9 +11,9 @@ func countingSort(array: [Int]) throws -> [Int] { // Step 1 // Create an array to store the count of each element - let maxElement = array.maxElement() ?? 0 + let maxElement = array.max() ?? 0 - var countArray = [Int](count: Int(maxElement + 1), repeatedValue: 0) + var countArray = [Int](repeating: 0, count: Int(maxElement + 1)) for element in array { countArray[element] += 1 } @@ -29,7 +29,7 @@ func countingSort(array: [Int]) throws -> [Int] { // Step 3 // Place the element in the final array as per the number of elements before it - var sortedArray = [Int](count: array.count, repeatedValue: 0) + var sortedArray = [Int](repeating: 0, count: array.count) for element in array { countArray[element] -= 1 sortedArray[countArray[element]] = element @@ -38,4 +38,4 @@ func countingSort(array: [Int]) throws -> [Int] { } -try countingSort([10, 9, 8, 7, 1, 2, 7, 3]) +try countingSort(array: [10, 9, 8, 7, 1, 2, 7, 3]) \ No newline at end of file From 17887c35c322a1361c82b8f40b36f636c780101d Mon Sep 17 00:00:00 2001 From: ssarber Date: Fri, 23 Sep 2016 12:16:23 -0700 Subject: [PATCH 0563/1679] Update readme --- Counting Sort/README.markdown | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Counting Sort/README.markdown b/Counting Sort/README.markdown index 55b60104f..959becc8c 100644 --- a/Counting Sort/README.markdown +++ b/Counting Sort/README.markdown @@ -20,9 +20,9 @@ Count 0 1 1 1 0 0 0 2 1 1 1 Here is the code to accomplish this: ```swift - let maxElement = array.maxElement() ?? 0 - - var countArray = [Int](count: Int(maxElement + 1), repeatedValue: 0) + let maxElement = array.max() ?? 0 + + var countArray = [Int](repeating: 0, count: Int(maxElement + 1)) for element in array { countArray[element] += 1 } @@ -62,7 +62,7 @@ Output 1 2 3 7 7 8 9 10 Here is the code for this final step: ```swift - var sortedArray = [Int](count: array.count, repeatedValue: 0) + var sortedArray = [Int](repeating: 0, count: array.count) for element in array { countArray[element] -= 1 sortedArray[countArray[element]] = element From 4470e09fd636ddfad61848dc99ed26e07e6a37f3 Mon Sep 17 00:00:00 2001 From: dontfollowmeimcrazy Date: Sat, 24 Sep 2016 14:04:23 +0200 Subject: [PATCH 0564/1679] first commit: added Knuth-Morris-Pratt and Z algorithms for string search --- .../Contents.swift | 122 ++++++++++++++++++ .../contents.xcplayground | 4 + .../contents.xcworkspacedata | 7 + .../timeline.xctimeline | 6 + Knuth-Morris-Pratt/KnuthMorrisPratt.swift | 65 ++++++++++ Z-Algorithm/ZAlgorithm.swift | 66 ++++++++++ .../ZetaAlgorithm.playground/Contents.swift | 95 ++++++++++++++ .../contents.xcplayground | 4 + .../contents.xcworkspacedata | 7 + .../timeline.xctimeline | 6 + Z-Algorithm/ZetaAlgorithm.swift | 32 +++++ 11 files changed, 414 insertions(+) create mode 100644 Knuth-Morris-Pratt/KnuthMorrisPratt.playground/Contents.swift create mode 100644 Knuth-Morris-Pratt/KnuthMorrisPratt.playground/contents.xcplayground create mode 100644 Knuth-Morris-Pratt/KnuthMorrisPratt.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 Knuth-Morris-Pratt/KnuthMorrisPratt.playground/timeline.xctimeline create mode 100644 Knuth-Morris-Pratt/KnuthMorrisPratt.swift create mode 100644 Z-Algorithm/ZAlgorithm.swift create mode 100644 Z-Algorithm/ZetaAlgorithm.playground/Contents.swift create mode 100644 Z-Algorithm/ZetaAlgorithm.playground/contents.xcplayground create mode 100644 Z-Algorithm/ZetaAlgorithm.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 Z-Algorithm/ZetaAlgorithm.playground/timeline.xctimeline create mode 100644 Z-Algorithm/ZetaAlgorithm.swift diff --git a/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/Contents.swift b/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/Contents.swift new file mode 100644 index 000000000..147477c80 --- /dev/null +++ b/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/Contents.swift @@ -0,0 +1,122 @@ +//: Playground - noun: a place where people can play + + +func ZetaAlgorithm(ptnr: String) -> [Int]? { + + let pattern = Array(ptnr.characters) + let patternLength: Int = pattern.count + + guard patternLength > 0 else { + return nil + } + + var zeta: [Int] = [Int](count: patternLength, repeatedValue: 0) + + var left: Int = 0 + var right: Int = 0 + var k_1: Int = 0 + var betaLength: Int = 0 + var textIndex: Int = 0 + var patternIndex: Int = 0 + + for k in 1 ..< patternLength { + if k > right { + patternIndex = 0 + + while k + patternIndex < patternLength && + pattern[k + patternIndex] == pattern[patternIndex] { + patternIndex = patternIndex + 1 + } + + zeta[k] = patternIndex + + if zeta[k] > 0 { + left = k + right = k + zeta[k] - 1 + } + } else { + k_1 = k - left + 1 + betaLength = right - k + 1 + + if zeta[k_1 - 1] < betaLength { + zeta[k] = zeta[k_1 - 1] + } else if zeta[k_1 - 1] >= betaLength { + textIndex = betaLength + patternIndex = right + 1 + + while patternIndex < patternLength && pattern[textIndex] == pattern[patternIndex] { + textIndex = textIndex + 1 + patternIndex = patternIndex + 1 + } + zeta[k] = patternIndex - k + left = k + right = patternIndex - 1 + } + } + } + return zeta +} + +extension String { + + func indexesOf(ptnr: String) -> [Int]? { + + let text = Array(self.characters) + let pattern = Array(ptnr.characters) + + let textLength: Int = text.count + let patternLength: Int = pattern.count + + guard patternLength > 0 else { + return nil + } + + var suffixPrefix: [Int] = [Int](count: patternLength, repeatedValue: 0) + var textIndex: Int = 0 + var patternIndex: Int = 0 + var indexes: [Int] = [Int]() + + /* Pre-processing stage: computing the table for the shifts (through Z-Algorithm) */ + let zeta = ZetaAlgorithm(ptnr) + + for patternIndex in (1 ..< patternLength).reverse() { + textIndex = patternIndex + zeta![patternIndex] - 1 + suffixPrefix[textIndex] = zeta![patternIndex] + } + + /* Search stage: scanning the text for pattern matching */ + textIndex = 0 + patternIndex = 0 + + while textIndex + (patternLength - patternIndex - 1) < textLength { + + while patternIndex < patternLength && text[textIndex] == pattern[patternIndex] { + textIndex = textIndex + 1 + patternIndex = patternIndex + 1 + } + + if patternIndex == patternLength { + indexes.append(textIndex - patternIndex) + } + + if patternIndex == 0 { + textIndex = textIndex + 1 + } else { + patternIndex = suffixPrefix[patternIndex - 1] + } + } + + guard !indexes.isEmpty else { + return nil + } + return indexes + } +} + +/* Examples */ + +let dna = "ACCCGGTTTTAAAGAACCACCATAAGATATAGACAGATATAGGACAGATATAGAGACAAAACCCCATACCCCAATATTTTTTTGGGGAGAAAAACACCACAGATAGATACACAGACTACACGAGATACGACATACAGCAGCATAACGACAACAGCAGATAGACGATCATAACAGCAATCAGACCGAGCGCAGCAGCTTTTAAGCACCAGCCCCACAAAAAACGACAATFATCATCATATACAGACGACGACACGACATATCACACGACAGCATA" +dna.indexesOf("CATA") // [20, 64, 130, 140, 166, 234, 255, 270] + +let concert = "🎼🎹🎹🎸🎸🎻🎻🎷🎺🎤👏👏👏" +concert.indexesOf("🎻🎷") // [6] diff --git a/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/contents.xcplayground b/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/contents.xcplayground new file mode 100644 index 000000000..06828af92 --- /dev/null +++ b/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/contents.xcplayground @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/playground.xcworkspace/contents.xcworkspacedata b/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/timeline.xctimeline b/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/timeline.xctimeline new file mode 100644 index 000000000..bf468afec --- /dev/null +++ b/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/timeline.xctimeline @@ -0,0 +1,6 @@ + + + + + diff --git a/Knuth-Morris-Pratt/KnuthMorrisPratt.swift b/Knuth-Morris-Pratt/KnuthMorrisPratt.swift new file mode 100644 index 000000000..5cce1556f --- /dev/null +++ b/Knuth-Morris-Pratt/KnuthMorrisPratt.swift @@ -0,0 +1,65 @@ +/* Knuth-Morris-Pratt algorithm for pattern/string matching + + The code is based on the book: + "Algorithms on String, Trees and Sequences: Computer Science and Computational Biology" + by Dan Gusfield + Cambridge University Press, 1997 +*/ + +import Foundation + +extension String { + + func indexesOf(ptnr: String) -> [Int]? { + + let text = Array(self.characters) + let pattern = Array(ptnr.characters) + + let textLength: Int = text.count + let patternLength: Int = pattern.count + + guard patternLength > 0 else { + return nil + } + + var suffixPrefix: [Int] = [Int](count: patternLength, repeatedValue: 0) + var textIndex: Int = 0 + var patternIndex: Int = 0 + var indexes: [Int] = [Int]() + + /* Pre-processing stage: computing the table for the shifts (through Z-Algorithm) */ + let zeta = ZetaAlgorithm(ptnr) + + for patternIndex in (1 ..< patternLength).reverse() { + textIndex = patternIndex + zeta![patternIndex] - 1 + suffixPrefix[textIndex] = zeta![patternIndex] + } + + /* Search stage: scanning the text for pattern matching */ + textIndex = 0 + patternIndex = 0 + + while textIndex + (patternLength - patternIndex - 1) < textLength { + + while patternIndex < patternLength && text[textIndex] == pattern[patternIndex] { + textIndex = textIndex + 1 + patternIndex = patternIndex + 1 + } + + if patternIndex == patternLength { + indexes.append(textIndex - patternIndex) + } + + if patternIndex == 0 { + textIndex = textIndex + 1 + } else { + patternIndex = suffixPrefix[patternIndex - 1] + } + } + + guard !indexes.isEmpty else { + return nil + } + return indexes + } +} diff --git a/Z-Algorithm/ZAlgorithm.swift b/Z-Algorithm/ZAlgorithm.swift new file mode 100644 index 000000000..3b6d34908 --- /dev/null +++ b/Z-Algorithm/ZAlgorithm.swift @@ -0,0 +1,66 @@ +/* Z-Algorithm for pattern/string pre-processing + + The code is based on the book: + "Algorithms on String, Trees and Sequences: Computer Science and Computational Biology" + by Dan Gusfield + Cambridge University Press, 1997 +*/ + +import Foundation + +func ZetaAlgorithm(ptrn: String) -> [Int]? { + + let pattern = Array(ptrn.characters) + let patternLength: Int = pattern.count + + guard patternLength > 0 else { + return nil + } + + var zeta: [Int] = [Int](count: patternLength, repeatedValue: 0) + + var left: Int = 0 + var right: Int = 0 + var k_1: Int = 0 + var betaLength: Int = 0 + var textIndex: Int = 0 + var patternIndex: Int = 0 + + for k in 1 ..< patternLength { + if k > right { + patternIndex = 0 + + while k + patternIndex < patternLength && + pattern[k + patternIndex] == pattern[patternIndex] { + patternIndex = patternIndex + 1 + } + + zeta[k] = patternIndex + + if zeta[k] > 0 { + left = k + right = k + zeta[k] - 1 + } + } else { + k_1 = k - left + 1 + betaLength = right - k + 1 + + if zeta[k_1 - 1] < betaLength { + zeta[k] = zeta[k_1 - 1] + } else if zeta[k_1 - 1] >= betaLength { + textIndex = betaLength + patternIndex = right + 1 + + while patternIndex < patternLength && pattern[textIndex] == pattern[patternIndex] { + textIndex = textIndex + 1 + patternIndex = patternIndex + 1 + } + + zeta[k] = patternIndex - k + left = k + right = patternIndex - 1 + } + } + } + return zeta +} diff --git a/Z-Algorithm/ZetaAlgorithm.playground/Contents.swift b/Z-Algorithm/ZetaAlgorithm.playground/Contents.swift new file mode 100644 index 000000000..dfe24ddf6 --- /dev/null +++ b/Z-Algorithm/ZetaAlgorithm.playground/Contents.swift @@ -0,0 +1,95 @@ +//: Playground - noun: a place where people can play + + +func ZetaAlgorithm(ptrn: String) -> [Int]? { + + let pattern = Array(ptrn.characters) + let patternLength: Int = pattern.count + + guard patternLength > 0 else { + return nil + } + + var zeta: [Int] = [Int](count: patternLength, repeatedValue: 0) + + var left: Int = 0 + var right: Int = 0 + var k_1: Int = 0 + var betaLength: Int = 0 + var textIndex: Int = 0 + var patternIndex: Int = 0 + + for k in 1 ..< patternLength { + if k > right { + patternIndex = 0 + + while k + patternIndex < patternLength && + pattern[k + patternIndex] == pattern[patternIndex] { + patternIndex = patternIndex + 1 + } + + zeta[k] = patternIndex + + if zeta[k] > 0 { + left = k + right = k + zeta[k] - 1 + } + } else { + k_1 = k - left + 1 + betaLength = right - k + 1 + + if zeta[k_1 - 1] < betaLength { + zeta[k] = zeta[k_1 - 1] + } else if zeta[k_1 - 1] >= betaLength { + textIndex = betaLength + patternIndex = right + 1 + + while patternIndex < patternLength && pattern[textIndex] == pattern[patternIndex] { + textIndex = textIndex + 1 + patternIndex = patternIndex + 1 + } + + zeta[k] = patternIndex - k + left = k + right = patternIndex - 1 + } + } + } + return zeta +} + + +extension String { + + func indexesOf(pattern: String) -> [Int]? { + let patternLength: Int = pattern.characters.count + let zeta = ZetaAlgorithm(pattern + "💲" + self) + + guard zeta != nil else { + return nil + } + + var indexes: [Int] = [Int]() + + /* Scan the zeta array to find matched patterns */ + for i in 0 ..< zeta!.count { + if zeta![i] == patternLength { + indexes.append(i - patternLength - 1) + } + } + + guard !indexes.isEmpty else { + return nil + } + + return indexes + } +} + +/* Examples */ + +let str = "Hello, playground!" +str.indexesOf("ground") // [11] + +let traffic = "🚗🚙🚌🚕🚑🚐🚗🚒🚚🚎🚛🚐🏎🚜🚗🏍🚒🚲🚕🚓🚌🚑" +traffic.indexesOf("🚑") // [4, 21] diff --git a/Z-Algorithm/ZetaAlgorithm.playground/contents.xcplayground b/Z-Algorithm/ZetaAlgorithm.playground/contents.xcplayground new file mode 100644 index 000000000..06828af92 --- /dev/null +++ b/Z-Algorithm/ZetaAlgorithm.playground/contents.xcplayground @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Z-Algorithm/ZetaAlgorithm.playground/playground.xcworkspace/contents.xcworkspacedata b/Z-Algorithm/ZetaAlgorithm.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Z-Algorithm/ZetaAlgorithm.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Z-Algorithm/ZetaAlgorithm.playground/timeline.xctimeline b/Z-Algorithm/ZetaAlgorithm.playground/timeline.xctimeline new file mode 100644 index 000000000..bf468afec --- /dev/null +++ b/Z-Algorithm/ZetaAlgorithm.playground/timeline.xctimeline @@ -0,0 +1,6 @@ + + + + + diff --git a/Z-Algorithm/ZetaAlgorithm.swift b/Z-Algorithm/ZetaAlgorithm.swift new file mode 100644 index 000000000..c31e27c66 --- /dev/null +++ b/Z-Algorithm/ZetaAlgorithm.swift @@ -0,0 +1,32 @@ +/* Z-Algorithm based algorithm for pattern/string matching + + The code is based on the book: + "Algorithms on String, Trees and Sequences: Computer Science and Computational Biology" + by Dan Gusfield + Cambridge University Press, 1997 +*/ + +import Foundation + +extension String { + + func indexesOf(pattern: String) -> [Int]? { + let patternLength: Int = pattern.characters.count + let zeta = ZetaAlgorithm(pattern + "💲" + self) + + var indexes: [Int] = [Int]() + + /* Scan the zeta array to find matched patterns */ + for index in indexes { + if index == patternLength { + indexes.append(index) + } + } + + guard !indexes.isEmpty else { + return nil + } + + return indexes + } +} From 6230a2bbc54bb08b9815764bcfc7909d471131c2 Mon Sep 17 00:00:00 2001 From: dontfollowmeimcrazy Date: Sat, 24 Sep 2016 14:31:50 +0200 Subject: [PATCH 0565/1679] removed directories --- .../Contents.swift | 122 ------------------ .../contents.xcplayground | 4 - .../contents.xcworkspacedata | 7 - .../timeline.xctimeline | 6 - Knuth-Morris-Pratt/KnuthMorrisPratt.swift | 65 ---------- Z-Algorithm/ZAlgorithm.swift | 66 ---------- .../ZetaAlgorithm.playground/Contents.swift | 95 -------------- .../contents.xcplayground | 4 - .../contents.xcworkspacedata | 7 - .../timeline.xctimeline | 6 - Z-Algorithm/ZetaAlgorithm.swift | 32 ----- 11 files changed, 414 deletions(-) delete mode 100644 Knuth-Morris-Pratt/KnuthMorrisPratt.playground/Contents.swift delete mode 100644 Knuth-Morris-Pratt/KnuthMorrisPratt.playground/contents.xcplayground delete mode 100644 Knuth-Morris-Pratt/KnuthMorrisPratt.playground/playground.xcworkspace/contents.xcworkspacedata delete mode 100644 Knuth-Morris-Pratt/KnuthMorrisPratt.playground/timeline.xctimeline delete mode 100644 Knuth-Morris-Pratt/KnuthMorrisPratt.swift delete mode 100644 Z-Algorithm/ZAlgorithm.swift delete mode 100644 Z-Algorithm/ZetaAlgorithm.playground/Contents.swift delete mode 100644 Z-Algorithm/ZetaAlgorithm.playground/contents.xcplayground delete mode 100644 Z-Algorithm/ZetaAlgorithm.playground/playground.xcworkspace/contents.xcworkspacedata delete mode 100644 Z-Algorithm/ZetaAlgorithm.playground/timeline.xctimeline delete mode 100644 Z-Algorithm/ZetaAlgorithm.swift diff --git a/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/Contents.swift b/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/Contents.swift deleted file mode 100644 index 147477c80..000000000 --- a/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/Contents.swift +++ /dev/null @@ -1,122 +0,0 @@ -//: Playground - noun: a place where people can play - - -func ZetaAlgorithm(ptnr: String) -> [Int]? { - - let pattern = Array(ptnr.characters) - let patternLength: Int = pattern.count - - guard patternLength > 0 else { - return nil - } - - var zeta: [Int] = [Int](count: patternLength, repeatedValue: 0) - - var left: Int = 0 - var right: Int = 0 - var k_1: Int = 0 - var betaLength: Int = 0 - var textIndex: Int = 0 - var patternIndex: Int = 0 - - for k in 1 ..< patternLength { - if k > right { - patternIndex = 0 - - while k + patternIndex < patternLength && - pattern[k + patternIndex] == pattern[patternIndex] { - patternIndex = patternIndex + 1 - } - - zeta[k] = patternIndex - - if zeta[k] > 0 { - left = k - right = k + zeta[k] - 1 - } - } else { - k_1 = k - left + 1 - betaLength = right - k + 1 - - if zeta[k_1 - 1] < betaLength { - zeta[k] = zeta[k_1 - 1] - } else if zeta[k_1 - 1] >= betaLength { - textIndex = betaLength - patternIndex = right + 1 - - while patternIndex < patternLength && pattern[textIndex] == pattern[patternIndex] { - textIndex = textIndex + 1 - patternIndex = patternIndex + 1 - } - zeta[k] = patternIndex - k - left = k - right = patternIndex - 1 - } - } - } - return zeta -} - -extension String { - - func indexesOf(ptnr: String) -> [Int]? { - - let text = Array(self.characters) - let pattern = Array(ptnr.characters) - - let textLength: Int = text.count - let patternLength: Int = pattern.count - - guard patternLength > 0 else { - return nil - } - - var suffixPrefix: [Int] = [Int](count: patternLength, repeatedValue: 0) - var textIndex: Int = 0 - var patternIndex: Int = 0 - var indexes: [Int] = [Int]() - - /* Pre-processing stage: computing the table for the shifts (through Z-Algorithm) */ - let zeta = ZetaAlgorithm(ptnr) - - for patternIndex in (1 ..< patternLength).reverse() { - textIndex = patternIndex + zeta![patternIndex] - 1 - suffixPrefix[textIndex] = zeta![patternIndex] - } - - /* Search stage: scanning the text for pattern matching */ - textIndex = 0 - patternIndex = 0 - - while textIndex + (patternLength - patternIndex - 1) < textLength { - - while patternIndex < patternLength && text[textIndex] == pattern[patternIndex] { - textIndex = textIndex + 1 - patternIndex = patternIndex + 1 - } - - if patternIndex == patternLength { - indexes.append(textIndex - patternIndex) - } - - if patternIndex == 0 { - textIndex = textIndex + 1 - } else { - patternIndex = suffixPrefix[patternIndex - 1] - } - } - - guard !indexes.isEmpty else { - return nil - } - return indexes - } -} - -/* Examples */ - -let dna = "ACCCGGTTTTAAAGAACCACCATAAGATATAGACAGATATAGGACAGATATAGAGACAAAACCCCATACCCCAATATTTTTTTGGGGAGAAAAACACCACAGATAGATACACAGACTACACGAGATACGACATACAGCAGCATAACGACAACAGCAGATAGACGATCATAACAGCAATCAGACCGAGCGCAGCAGCTTTTAAGCACCAGCCCCACAAAAAACGACAATFATCATCATATACAGACGACGACACGACATATCACACGACAGCATA" -dna.indexesOf("CATA") // [20, 64, 130, 140, 166, 234, 255, 270] - -let concert = "🎼🎹🎹🎸🎸🎻🎻🎷🎺🎤👏👏👏" -concert.indexesOf("🎻🎷") // [6] diff --git a/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/contents.xcplayground b/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/contents.xcplayground deleted file mode 100644 index 06828af92..000000000 --- a/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/contents.xcplayground +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/playground.xcworkspace/contents.xcworkspacedata b/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/playground.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 919434a62..000000000 --- a/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/playground.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/timeline.xctimeline b/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/timeline.xctimeline deleted file mode 100644 index bf468afec..000000000 --- a/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/timeline.xctimeline +++ /dev/null @@ -1,6 +0,0 @@ - - - - - diff --git a/Knuth-Morris-Pratt/KnuthMorrisPratt.swift b/Knuth-Morris-Pratt/KnuthMorrisPratt.swift deleted file mode 100644 index 5cce1556f..000000000 --- a/Knuth-Morris-Pratt/KnuthMorrisPratt.swift +++ /dev/null @@ -1,65 +0,0 @@ -/* Knuth-Morris-Pratt algorithm for pattern/string matching - - The code is based on the book: - "Algorithms on String, Trees and Sequences: Computer Science and Computational Biology" - by Dan Gusfield - Cambridge University Press, 1997 -*/ - -import Foundation - -extension String { - - func indexesOf(ptnr: String) -> [Int]? { - - let text = Array(self.characters) - let pattern = Array(ptnr.characters) - - let textLength: Int = text.count - let patternLength: Int = pattern.count - - guard patternLength > 0 else { - return nil - } - - var suffixPrefix: [Int] = [Int](count: patternLength, repeatedValue: 0) - var textIndex: Int = 0 - var patternIndex: Int = 0 - var indexes: [Int] = [Int]() - - /* Pre-processing stage: computing the table for the shifts (through Z-Algorithm) */ - let zeta = ZetaAlgorithm(ptnr) - - for patternIndex in (1 ..< patternLength).reverse() { - textIndex = patternIndex + zeta![patternIndex] - 1 - suffixPrefix[textIndex] = zeta![patternIndex] - } - - /* Search stage: scanning the text for pattern matching */ - textIndex = 0 - patternIndex = 0 - - while textIndex + (patternLength - patternIndex - 1) < textLength { - - while patternIndex < patternLength && text[textIndex] == pattern[patternIndex] { - textIndex = textIndex + 1 - patternIndex = patternIndex + 1 - } - - if patternIndex == patternLength { - indexes.append(textIndex - patternIndex) - } - - if patternIndex == 0 { - textIndex = textIndex + 1 - } else { - patternIndex = suffixPrefix[patternIndex - 1] - } - } - - guard !indexes.isEmpty else { - return nil - } - return indexes - } -} diff --git a/Z-Algorithm/ZAlgorithm.swift b/Z-Algorithm/ZAlgorithm.swift deleted file mode 100644 index 3b6d34908..000000000 --- a/Z-Algorithm/ZAlgorithm.swift +++ /dev/null @@ -1,66 +0,0 @@ -/* Z-Algorithm for pattern/string pre-processing - - The code is based on the book: - "Algorithms on String, Trees and Sequences: Computer Science and Computational Biology" - by Dan Gusfield - Cambridge University Press, 1997 -*/ - -import Foundation - -func ZetaAlgorithm(ptrn: String) -> [Int]? { - - let pattern = Array(ptrn.characters) - let patternLength: Int = pattern.count - - guard patternLength > 0 else { - return nil - } - - var zeta: [Int] = [Int](count: patternLength, repeatedValue: 0) - - var left: Int = 0 - var right: Int = 0 - var k_1: Int = 0 - var betaLength: Int = 0 - var textIndex: Int = 0 - var patternIndex: Int = 0 - - for k in 1 ..< patternLength { - if k > right { - patternIndex = 0 - - while k + patternIndex < patternLength && - pattern[k + patternIndex] == pattern[patternIndex] { - patternIndex = patternIndex + 1 - } - - zeta[k] = patternIndex - - if zeta[k] > 0 { - left = k - right = k + zeta[k] - 1 - } - } else { - k_1 = k - left + 1 - betaLength = right - k + 1 - - if zeta[k_1 - 1] < betaLength { - zeta[k] = zeta[k_1 - 1] - } else if zeta[k_1 - 1] >= betaLength { - textIndex = betaLength - patternIndex = right + 1 - - while patternIndex < patternLength && pattern[textIndex] == pattern[patternIndex] { - textIndex = textIndex + 1 - patternIndex = patternIndex + 1 - } - - zeta[k] = patternIndex - k - left = k - right = patternIndex - 1 - } - } - } - return zeta -} diff --git a/Z-Algorithm/ZetaAlgorithm.playground/Contents.swift b/Z-Algorithm/ZetaAlgorithm.playground/Contents.swift deleted file mode 100644 index dfe24ddf6..000000000 --- a/Z-Algorithm/ZetaAlgorithm.playground/Contents.swift +++ /dev/null @@ -1,95 +0,0 @@ -//: Playground - noun: a place where people can play - - -func ZetaAlgorithm(ptrn: String) -> [Int]? { - - let pattern = Array(ptrn.characters) - let patternLength: Int = pattern.count - - guard patternLength > 0 else { - return nil - } - - var zeta: [Int] = [Int](count: patternLength, repeatedValue: 0) - - var left: Int = 0 - var right: Int = 0 - var k_1: Int = 0 - var betaLength: Int = 0 - var textIndex: Int = 0 - var patternIndex: Int = 0 - - for k in 1 ..< patternLength { - if k > right { - patternIndex = 0 - - while k + patternIndex < patternLength && - pattern[k + patternIndex] == pattern[patternIndex] { - patternIndex = patternIndex + 1 - } - - zeta[k] = patternIndex - - if zeta[k] > 0 { - left = k - right = k + zeta[k] - 1 - } - } else { - k_1 = k - left + 1 - betaLength = right - k + 1 - - if zeta[k_1 - 1] < betaLength { - zeta[k] = zeta[k_1 - 1] - } else if zeta[k_1 - 1] >= betaLength { - textIndex = betaLength - patternIndex = right + 1 - - while patternIndex < patternLength && pattern[textIndex] == pattern[patternIndex] { - textIndex = textIndex + 1 - patternIndex = patternIndex + 1 - } - - zeta[k] = patternIndex - k - left = k - right = patternIndex - 1 - } - } - } - return zeta -} - - -extension String { - - func indexesOf(pattern: String) -> [Int]? { - let patternLength: Int = pattern.characters.count - let zeta = ZetaAlgorithm(pattern + "💲" + self) - - guard zeta != nil else { - return nil - } - - var indexes: [Int] = [Int]() - - /* Scan the zeta array to find matched patterns */ - for i in 0 ..< zeta!.count { - if zeta![i] == patternLength { - indexes.append(i - patternLength - 1) - } - } - - guard !indexes.isEmpty else { - return nil - } - - return indexes - } -} - -/* Examples */ - -let str = "Hello, playground!" -str.indexesOf("ground") // [11] - -let traffic = "🚗🚙🚌🚕🚑🚐🚗🚒🚚🚎🚛🚐🏎🚜🚗🏍🚒🚲🚕🚓🚌🚑" -traffic.indexesOf("🚑") // [4, 21] diff --git a/Z-Algorithm/ZetaAlgorithm.playground/contents.xcplayground b/Z-Algorithm/ZetaAlgorithm.playground/contents.xcplayground deleted file mode 100644 index 06828af92..000000000 --- a/Z-Algorithm/ZetaAlgorithm.playground/contents.xcplayground +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/Z-Algorithm/ZetaAlgorithm.playground/playground.xcworkspace/contents.xcworkspacedata b/Z-Algorithm/ZetaAlgorithm.playground/playground.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 919434a62..000000000 --- a/Z-Algorithm/ZetaAlgorithm.playground/playground.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/Z-Algorithm/ZetaAlgorithm.playground/timeline.xctimeline b/Z-Algorithm/ZetaAlgorithm.playground/timeline.xctimeline deleted file mode 100644 index bf468afec..000000000 --- a/Z-Algorithm/ZetaAlgorithm.playground/timeline.xctimeline +++ /dev/null @@ -1,6 +0,0 @@ - - - - - diff --git a/Z-Algorithm/ZetaAlgorithm.swift b/Z-Algorithm/ZetaAlgorithm.swift deleted file mode 100644 index c31e27c66..000000000 --- a/Z-Algorithm/ZetaAlgorithm.swift +++ /dev/null @@ -1,32 +0,0 @@ -/* Z-Algorithm based algorithm for pattern/string matching - - The code is based on the book: - "Algorithms on String, Trees and Sequences: Computer Science and Computational Biology" - by Dan Gusfield - Cambridge University Press, 1997 -*/ - -import Foundation - -extension String { - - func indexesOf(pattern: String) -> [Int]? { - let patternLength: Int = pattern.characters.count - let zeta = ZetaAlgorithm(pattern + "💲" + self) - - var indexes: [Int] = [Int]() - - /* Scan the zeta array to find matched patterns */ - for index in indexes { - if index == patternLength { - indexes.append(index) - } - } - - guard !indexes.isEmpty else { - return nil - } - - return indexes - } -} From c416818dc12878181d8c5a0e54b78be72f68c665 Mon Sep 17 00:00:00 2001 From: dontfollowmeimcrazy Date: Sat, 24 Sep 2016 14:41:37 +0200 Subject: [PATCH 0566/1679] first commit: added Knuth-Morris-Pratt and Z algorithms implementation --- .../Contents.swift | 122 ++++++++++++++++++ .../contents.xcplayground | 4 + .../contents.xcworkspacedata | 7 + .../timeline.xctimeline | 6 + Knuth-Morris-Pratt/KnuthMorrisPratt.swift | 65 ++++++++++ Z-Algorithm/ZAlgorithm.swift | 66 ++++++++++ .../ZetaAlgorithm.playground/Contents.swift | 95 ++++++++++++++ .../contents.xcplayground | 4 + .../contents.xcworkspacedata | 7 + .../timeline.xctimeline | 6 + Z-Algorithm/ZetaAlgorithm.swift | 32 +++++ 11 files changed, 414 insertions(+) create mode 100644 Knuth-Morris-Pratt/KnuthMorrisPratt.playground/Contents.swift create mode 100644 Knuth-Morris-Pratt/KnuthMorrisPratt.playground/contents.xcplayground create mode 100644 Knuth-Morris-Pratt/KnuthMorrisPratt.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 Knuth-Morris-Pratt/KnuthMorrisPratt.playground/timeline.xctimeline create mode 100644 Knuth-Morris-Pratt/KnuthMorrisPratt.swift create mode 100644 Z-Algorithm/ZAlgorithm.swift create mode 100644 Z-Algorithm/ZetaAlgorithm.playground/Contents.swift create mode 100644 Z-Algorithm/ZetaAlgorithm.playground/contents.xcplayground create mode 100644 Z-Algorithm/ZetaAlgorithm.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 Z-Algorithm/ZetaAlgorithm.playground/timeline.xctimeline create mode 100644 Z-Algorithm/ZetaAlgorithm.swift diff --git a/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/Contents.swift b/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/Contents.swift new file mode 100644 index 000000000..147477c80 --- /dev/null +++ b/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/Contents.swift @@ -0,0 +1,122 @@ +//: Playground - noun: a place where people can play + + +func ZetaAlgorithm(ptnr: String) -> [Int]? { + + let pattern = Array(ptnr.characters) + let patternLength: Int = pattern.count + + guard patternLength > 0 else { + return nil + } + + var zeta: [Int] = [Int](count: patternLength, repeatedValue: 0) + + var left: Int = 0 + var right: Int = 0 + var k_1: Int = 0 + var betaLength: Int = 0 + var textIndex: Int = 0 + var patternIndex: Int = 0 + + for k in 1 ..< patternLength { + if k > right { + patternIndex = 0 + + while k + patternIndex < patternLength && + pattern[k + patternIndex] == pattern[patternIndex] { + patternIndex = patternIndex + 1 + } + + zeta[k] = patternIndex + + if zeta[k] > 0 { + left = k + right = k + zeta[k] - 1 + } + } else { + k_1 = k - left + 1 + betaLength = right - k + 1 + + if zeta[k_1 - 1] < betaLength { + zeta[k] = zeta[k_1 - 1] + } else if zeta[k_1 - 1] >= betaLength { + textIndex = betaLength + patternIndex = right + 1 + + while patternIndex < patternLength && pattern[textIndex] == pattern[patternIndex] { + textIndex = textIndex + 1 + patternIndex = patternIndex + 1 + } + zeta[k] = patternIndex - k + left = k + right = patternIndex - 1 + } + } + } + return zeta +} + +extension String { + + func indexesOf(ptnr: String) -> [Int]? { + + let text = Array(self.characters) + let pattern = Array(ptnr.characters) + + let textLength: Int = text.count + let patternLength: Int = pattern.count + + guard patternLength > 0 else { + return nil + } + + var suffixPrefix: [Int] = [Int](count: patternLength, repeatedValue: 0) + var textIndex: Int = 0 + var patternIndex: Int = 0 + var indexes: [Int] = [Int]() + + /* Pre-processing stage: computing the table for the shifts (through Z-Algorithm) */ + let zeta = ZetaAlgorithm(ptnr) + + for patternIndex in (1 ..< patternLength).reverse() { + textIndex = patternIndex + zeta![patternIndex] - 1 + suffixPrefix[textIndex] = zeta![patternIndex] + } + + /* Search stage: scanning the text for pattern matching */ + textIndex = 0 + patternIndex = 0 + + while textIndex + (patternLength - patternIndex - 1) < textLength { + + while patternIndex < patternLength && text[textIndex] == pattern[patternIndex] { + textIndex = textIndex + 1 + patternIndex = patternIndex + 1 + } + + if patternIndex == patternLength { + indexes.append(textIndex - patternIndex) + } + + if patternIndex == 0 { + textIndex = textIndex + 1 + } else { + patternIndex = suffixPrefix[patternIndex - 1] + } + } + + guard !indexes.isEmpty else { + return nil + } + return indexes + } +} + +/* Examples */ + +let dna = "ACCCGGTTTTAAAGAACCACCATAAGATATAGACAGATATAGGACAGATATAGAGACAAAACCCCATACCCCAATATTTTTTTGGGGAGAAAAACACCACAGATAGATACACAGACTACACGAGATACGACATACAGCAGCATAACGACAACAGCAGATAGACGATCATAACAGCAATCAGACCGAGCGCAGCAGCTTTTAAGCACCAGCCCCACAAAAAACGACAATFATCATCATATACAGACGACGACACGACATATCACACGACAGCATA" +dna.indexesOf("CATA") // [20, 64, 130, 140, 166, 234, 255, 270] + +let concert = "🎼🎹🎹🎸🎸🎻🎻🎷🎺🎤👏👏👏" +concert.indexesOf("🎻🎷") // [6] diff --git a/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/contents.xcplayground b/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/contents.xcplayground new file mode 100644 index 000000000..06828af92 --- /dev/null +++ b/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/contents.xcplayground @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/playground.xcworkspace/contents.xcworkspacedata b/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/timeline.xctimeline b/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/timeline.xctimeline new file mode 100644 index 000000000..bf468afec --- /dev/null +++ b/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/timeline.xctimeline @@ -0,0 +1,6 @@ + + + + + diff --git a/Knuth-Morris-Pratt/KnuthMorrisPratt.swift b/Knuth-Morris-Pratt/KnuthMorrisPratt.swift new file mode 100644 index 000000000..5cce1556f --- /dev/null +++ b/Knuth-Morris-Pratt/KnuthMorrisPratt.swift @@ -0,0 +1,65 @@ +/* Knuth-Morris-Pratt algorithm for pattern/string matching + + The code is based on the book: + "Algorithms on String, Trees and Sequences: Computer Science and Computational Biology" + by Dan Gusfield + Cambridge University Press, 1997 +*/ + +import Foundation + +extension String { + + func indexesOf(ptnr: String) -> [Int]? { + + let text = Array(self.characters) + let pattern = Array(ptnr.characters) + + let textLength: Int = text.count + let patternLength: Int = pattern.count + + guard patternLength > 0 else { + return nil + } + + var suffixPrefix: [Int] = [Int](count: patternLength, repeatedValue: 0) + var textIndex: Int = 0 + var patternIndex: Int = 0 + var indexes: [Int] = [Int]() + + /* Pre-processing stage: computing the table for the shifts (through Z-Algorithm) */ + let zeta = ZetaAlgorithm(ptnr) + + for patternIndex in (1 ..< patternLength).reverse() { + textIndex = patternIndex + zeta![patternIndex] - 1 + suffixPrefix[textIndex] = zeta![patternIndex] + } + + /* Search stage: scanning the text for pattern matching */ + textIndex = 0 + patternIndex = 0 + + while textIndex + (patternLength - patternIndex - 1) < textLength { + + while patternIndex < patternLength && text[textIndex] == pattern[patternIndex] { + textIndex = textIndex + 1 + patternIndex = patternIndex + 1 + } + + if patternIndex == patternLength { + indexes.append(textIndex - patternIndex) + } + + if patternIndex == 0 { + textIndex = textIndex + 1 + } else { + patternIndex = suffixPrefix[patternIndex - 1] + } + } + + guard !indexes.isEmpty else { + return nil + } + return indexes + } +} diff --git a/Z-Algorithm/ZAlgorithm.swift b/Z-Algorithm/ZAlgorithm.swift new file mode 100644 index 000000000..3b6d34908 --- /dev/null +++ b/Z-Algorithm/ZAlgorithm.swift @@ -0,0 +1,66 @@ +/* Z-Algorithm for pattern/string pre-processing + + The code is based on the book: + "Algorithms on String, Trees and Sequences: Computer Science and Computational Biology" + by Dan Gusfield + Cambridge University Press, 1997 +*/ + +import Foundation + +func ZetaAlgorithm(ptrn: String) -> [Int]? { + + let pattern = Array(ptrn.characters) + let patternLength: Int = pattern.count + + guard patternLength > 0 else { + return nil + } + + var zeta: [Int] = [Int](count: patternLength, repeatedValue: 0) + + var left: Int = 0 + var right: Int = 0 + var k_1: Int = 0 + var betaLength: Int = 0 + var textIndex: Int = 0 + var patternIndex: Int = 0 + + for k in 1 ..< patternLength { + if k > right { + patternIndex = 0 + + while k + patternIndex < patternLength && + pattern[k + patternIndex] == pattern[patternIndex] { + patternIndex = patternIndex + 1 + } + + zeta[k] = patternIndex + + if zeta[k] > 0 { + left = k + right = k + zeta[k] - 1 + } + } else { + k_1 = k - left + 1 + betaLength = right - k + 1 + + if zeta[k_1 - 1] < betaLength { + zeta[k] = zeta[k_1 - 1] + } else if zeta[k_1 - 1] >= betaLength { + textIndex = betaLength + patternIndex = right + 1 + + while patternIndex < patternLength && pattern[textIndex] == pattern[patternIndex] { + textIndex = textIndex + 1 + patternIndex = patternIndex + 1 + } + + zeta[k] = patternIndex - k + left = k + right = patternIndex - 1 + } + } + } + return zeta +} diff --git a/Z-Algorithm/ZetaAlgorithm.playground/Contents.swift b/Z-Algorithm/ZetaAlgorithm.playground/Contents.swift new file mode 100644 index 000000000..dfe24ddf6 --- /dev/null +++ b/Z-Algorithm/ZetaAlgorithm.playground/Contents.swift @@ -0,0 +1,95 @@ +//: Playground - noun: a place where people can play + + +func ZetaAlgorithm(ptrn: String) -> [Int]? { + + let pattern = Array(ptrn.characters) + let patternLength: Int = pattern.count + + guard patternLength > 0 else { + return nil + } + + var zeta: [Int] = [Int](count: patternLength, repeatedValue: 0) + + var left: Int = 0 + var right: Int = 0 + var k_1: Int = 0 + var betaLength: Int = 0 + var textIndex: Int = 0 + var patternIndex: Int = 0 + + for k in 1 ..< patternLength { + if k > right { + patternIndex = 0 + + while k + patternIndex < patternLength && + pattern[k + patternIndex] == pattern[patternIndex] { + patternIndex = patternIndex + 1 + } + + zeta[k] = patternIndex + + if zeta[k] > 0 { + left = k + right = k + zeta[k] - 1 + } + } else { + k_1 = k - left + 1 + betaLength = right - k + 1 + + if zeta[k_1 - 1] < betaLength { + zeta[k] = zeta[k_1 - 1] + } else if zeta[k_1 - 1] >= betaLength { + textIndex = betaLength + patternIndex = right + 1 + + while patternIndex < patternLength && pattern[textIndex] == pattern[patternIndex] { + textIndex = textIndex + 1 + patternIndex = patternIndex + 1 + } + + zeta[k] = patternIndex - k + left = k + right = patternIndex - 1 + } + } + } + return zeta +} + + +extension String { + + func indexesOf(pattern: String) -> [Int]? { + let patternLength: Int = pattern.characters.count + let zeta = ZetaAlgorithm(pattern + "💲" + self) + + guard zeta != nil else { + return nil + } + + var indexes: [Int] = [Int]() + + /* Scan the zeta array to find matched patterns */ + for i in 0 ..< zeta!.count { + if zeta![i] == patternLength { + indexes.append(i - patternLength - 1) + } + } + + guard !indexes.isEmpty else { + return nil + } + + return indexes + } +} + +/* Examples */ + +let str = "Hello, playground!" +str.indexesOf("ground") // [11] + +let traffic = "🚗🚙🚌🚕🚑🚐🚗🚒🚚🚎🚛🚐🏎🚜🚗🏍🚒🚲🚕🚓🚌🚑" +traffic.indexesOf("🚑") // [4, 21] diff --git a/Z-Algorithm/ZetaAlgorithm.playground/contents.xcplayground b/Z-Algorithm/ZetaAlgorithm.playground/contents.xcplayground new file mode 100644 index 000000000..06828af92 --- /dev/null +++ b/Z-Algorithm/ZetaAlgorithm.playground/contents.xcplayground @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Z-Algorithm/ZetaAlgorithm.playground/playground.xcworkspace/contents.xcworkspacedata b/Z-Algorithm/ZetaAlgorithm.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Z-Algorithm/ZetaAlgorithm.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Z-Algorithm/ZetaAlgorithm.playground/timeline.xctimeline b/Z-Algorithm/ZetaAlgorithm.playground/timeline.xctimeline new file mode 100644 index 000000000..bf468afec --- /dev/null +++ b/Z-Algorithm/ZetaAlgorithm.playground/timeline.xctimeline @@ -0,0 +1,6 @@ + + + + + diff --git a/Z-Algorithm/ZetaAlgorithm.swift b/Z-Algorithm/ZetaAlgorithm.swift new file mode 100644 index 000000000..c31e27c66 --- /dev/null +++ b/Z-Algorithm/ZetaAlgorithm.swift @@ -0,0 +1,32 @@ +/* Z-Algorithm based algorithm for pattern/string matching + + The code is based on the book: + "Algorithms on String, Trees and Sequences: Computer Science and Computational Biology" + by Dan Gusfield + Cambridge University Press, 1997 +*/ + +import Foundation + +extension String { + + func indexesOf(pattern: String) -> [Int]? { + let patternLength: Int = pattern.characters.count + let zeta = ZetaAlgorithm(pattern + "💲" + self) + + var indexes: [Int] = [Int]() + + /* Scan the zeta array to find matched patterns */ + for index in indexes { + if index == patternLength { + indexes.append(index) + } + } + + guard !indexes.isEmpty else { + return nil + } + + return indexes + } +} From e3967dfdd69b3a04243760d4ce73fd83576fef15 Mon Sep 17 00:00:00 2001 From: dontfollowmeimcrazy Date: Sat, 24 Sep 2016 21:15:04 +0200 Subject: [PATCH 0567/1679] swift 3 fix --- .../Contents.swift | 12 +++---- .../timeline.xctimeline | 6 ---- Knuth-Morris-Pratt/KnuthMorrisPratt.swift | 32 +++++++++---------- Z-Algorithm/ZAlgorithm.swift | 26 +++++++-------- .../ZetaAlgorithm.playground/Contents.swift | 8 ++--- .../timeline.xctimeline | 6 ---- Z-Algorithm/ZetaAlgorithm.swift | 22 +++++++------ 7 files changed, 52 insertions(+), 60 deletions(-) delete mode 100644 Knuth-Morris-Pratt/KnuthMorrisPratt.playground/timeline.xctimeline delete mode 100644 Z-Algorithm/ZetaAlgorithm.playground/timeline.xctimeline diff --git a/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/Contents.swift b/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/Contents.swift index 147477c80..35fb27ff8 100644 --- a/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/Contents.swift +++ b/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/Contents.swift @@ -10,7 +10,7 @@ func ZetaAlgorithm(ptnr: String) -> [Int]? { return nil } - var zeta: [Int] = [Int](count: patternLength, repeatedValue: 0) + var zeta: [Int] = [Int](repeating: 0, count: patternLength) var left: Int = 0 var right: Int = 0 @@ -71,15 +71,15 @@ extension String { return nil } - var suffixPrefix: [Int] = [Int](count: patternLength, repeatedValue: 0) + var suffixPrefix: [Int] = [Int](repeating: 0, count: patternLength) var textIndex: Int = 0 var patternIndex: Int = 0 var indexes: [Int] = [Int]() /* Pre-processing stage: computing the table for the shifts (through Z-Algorithm) */ - let zeta = ZetaAlgorithm(ptnr) + let zeta = ZetaAlgorithm(ptnr: ptnr) - for patternIndex in (1 ..< patternLength).reverse() { + for patternIndex in (1 ..< patternLength).reversed() { textIndex = patternIndex + zeta![patternIndex] - 1 suffixPrefix[textIndex] = zeta![patternIndex] } @@ -116,7 +116,7 @@ extension String { /* Examples */ let dna = "ACCCGGTTTTAAAGAACCACCATAAGATATAGACAGATATAGGACAGATATAGAGACAAAACCCCATACCCCAATATTTTTTTGGGGAGAAAAACACCACAGATAGATACACAGACTACACGAGATACGACATACAGCAGCATAACGACAACAGCAGATAGACGATCATAACAGCAATCAGACCGAGCGCAGCAGCTTTTAAGCACCAGCCCCACAAAAAACGACAATFATCATCATATACAGACGACGACACGACATATCACACGACAGCATA" -dna.indexesOf("CATA") // [20, 64, 130, 140, 166, 234, 255, 270] +dna.indexesOf(ptnr: "CATA") // [20, 64, 130, 140, 166, 234, 255, 270] let concert = "🎼🎹🎹🎸🎸🎻🎻🎷🎺🎤👏👏👏" -concert.indexesOf("🎻🎷") // [6] +concert.indexesOf(ptnr: "🎻🎷") // [6] diff --git a/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/timeline.xctimeline b/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/timeline.xctimeline deleted file mode 100644 index bf468afec..000000000 --- a/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/timeline.xctimeline +++ /dev/null @@ -1,6 +0,0 @@ - - - - - diff --git a/Knuth-Morris-Pratt/KnuthMorrisPratt.swift b/Knuth-Morris-Pratt/KnuthMorrisPratt.swift index 5cce1556f..46a88c134 100644 --- a/Knuth-Morris-Pratt/KnuthMorrisPratt.swift +++ b/Knuth-Morris-Pratt/KnuthMorrisPratt.swift @@ -9,54 +9,54 @@ import Foundation extension String { - + func indexesOf(ptnr: String) -> [Int]? { - + let text = Array(self.characters) let pattern = Array(ptnr.characters) - + let textLength: Int = text.count let patternLength: Int = pattern.count - + guard patternLength > 0 else { return nil } - - var suffixPrefix: [Int] = [Int](count: patternLength, repeatedValue: 0) + + var suffixPrefix: [Int] = [Int](repeating: 0, count: patternLength) var textIndex: Int = 0 var patternIndex: Int = 0 var indexes: [Int] = [Int]() - + /* Pre-processing stage: computing the table for the shifts (through Z-Algorithm) */ - let zeta = ZetaAlgorithm(ptnr) - - for patternIndex in (1 ..< patternLength).reverse() { + let zeta = ZetaAlgorithm(ptnr: ptnr) + + for patternIndex in (1 ..< patternLength).reversed() { textIndex = patternIndex + zeta![patternIndex] - 1 suffixPrefix[textIndex] = zeta![patternIndex] } - + /* Search stage: scanning the text for pattern matching */ textIndex = 0 patternIndex = 0 - + while textIndex + (patternLength - patternIndex - 1) < textLength { - + while patternIndex < patternLength && text[textIndex] == pattern[patternIndex] { textIndex = textIndex + 1 patternIndex = patternIndex + 1 } - + if patternIndex == patternLength { indexes.append(textIndex - patternIndex) } - + if patternIndex == 0 { textIndex = textIndex + 1 } else { patternIndex = suffixPrefix[patternIndex - 1] } } - + guard !indexes.isEmpty else { return nil } diff --git a/Z-Algorithm/ZAlgorithm.swift b/Z-Algorithm/ZAlgorithm.swift index 3b6d34908..c9d7de876 100644 --- a/Z-Algorithm/ZAlgorithm.swift +++ b/Z-Algorithm/ZAlgorithm.swift @@ -9,34 +9,34 @@ import Foundation func ZetaAlgorithm(ptrn: String) -> [Int]? { - + let pattern = Array(ptrn.characters) let patternLength: Int = pattern.count - + guard patternLength > 0 else { return nil } - - var zeta: [Int] = [Int](count: patternLength, repeatedValue: 0) - + + var zeta: [Int] = [Int](repeating: 0, count: patternLength) + var left: Int = 0 var right: Int = 0 var k_1: Int = 0 var betaLength: Int = 0 var textIndex: Int = 0 var patternIndex: Int = 0 - + for k in 1 ..< patternLength { if k > right { patternIndex = 0 - + while k + patternIndex < patternLength && pattern[k + patternIndex] == pattern[patternIndex] { - patternIndex = patternIndex + 1 + patternIndex = patternIndex + 1 } - + zeta[k] = patternIndex - + if zeta[k] > 0 { left = k right = k + zeta[k] - 1 @@ -44,18 +44,18 @@ func ZetaAlgorithm(ptrn: String) -> [Int]? { } else { k_1 = k - left + 1 betaLength = right - k + 1 - + if zeta[k_1 - 1] < betaLength { zeta[k] = zeta[k_1 - 1] } else if zeta[k_1 - 1] >= betaLength { textIndex = betaLength patternIndex = right + 1 - + while patternIndex < patternLength && pattern[textIndex] == pattern[patternIndex] { textIndex = textIndex + 1 patternIndex = patternIndex + 1 } - + zeta[k] = patternIndex - k left = k right = patternIndex - 1 diff --git a/Z-Algorithm/ZetaAlgorithm.playground/Contents.swift b/Z-Algorithm/ZetaAlgorithm.playground/Contents.swift index dfe24ddf6..c9d942149 100644 --- a/Z-Algorithm/ZetaAlgorithm.playground/Contents.swift +++ b/Z-Algorithm/ZetaAlgorithm.playground/Contents.swift @@ -10,7 +10,7 @@ func ZetaAlgorithm(ptrn: String) -> [Int]? { return nil } - var zeta: [Int] = [Int](count: patternLength, repeatedValue: 0) + var zeta: [Int] = [Int](repeating: 0, count: patternLength) var left: Int = 0 var right: Int = 0 @@ -63,7 +63,7 @@ extension String { func indexesOf(pattern: String) -> [Int]? { let patternLength: Int = pattern.characters.count - let zeta = ZetaAlgorithm(pattern + "💲" + self) + let zeta = ZetaAlgorithm(ptrn: pattern + "💲" + self) guard zeta != nil else { return nil @@ -89,7 +89,7 @@ extension String { /* Examples */ let str = "Hello, playground!" -str.indexesOf("ground") // [11] +str.indexesOf(pattern: "ground") // [11] let traffic = "🚗🚙🚌🚕🚑🚐🚗🚒🚚🚎🚛🚐🏎🚜🚗🏍🚒🚲🚕🚓🚌🚑" -traffic.indexesOf("🚑") // [4, 21] +traffic.indexesOf(pattern: "🚑") // [4, 21] diff --git a/Z-Algorithm/ZetaAlgorithm.playground/timeline.xctimeline b/Z-Algorithm/ZetaAlgorithm.playground/timeline.xctimeline deleted file mode 100644 index bf468afec..000000000 --- a/Z-Algorithm/ZetaAlgorithm.playground/timeline.xctimeline +++ /dev/null @@ -1,6 +0,0 @@ - - - - - diff --git a/Z-Algorithm/ZetaAlgorithm.swift b/Z-Algorithm/ZetaAlgorithm.swift index c31e27c66..4d80aa665 100644 --- a/Z-Algorithm/ZetaAlgorithm.swift +++ b/Z-Algorithm/ZetaAlgorithm.swift @@ -9,24 +9,28 @@ import Foundation extension String { - + func indexesOf(pattern: String) -> [Int]? { let patternLength: Int = pattern.characters.count - let zeta = ZetaAlgorithm(pattern + "💲" + self) - + let zeta = ZetaAlgorithm(ptrn: pattern + "💲" + self) + + guard zeta != nil else { + return nil + } + var indexes: [Int] = [Int]() - + /* Scan the zeta array to find matched patterns */ - for index in indexes { - if index == patternLength { - indexes.append(index) + for i in 0 ..< zeta!.count { + if zeta![i] == patternLength { + indexes.append(i - patternLength - 1) } } - + guard !indexes.isEmpty else { return nil } - + return indexes } } From aeaa72a741e2213cfaf3e55bb8f915fb5176f3e8 Mon Sep 17 00:00:00 2001 From: Richard Date: Sat, 24 Sep 2016 15:29:51 -0700 Subject: [PATCH 0568/1679] Updated syntax to Swift 3 --- .../Contents.swift | 30 +++++++++++-------- .../KaratsubaMultiplication.swift | 21 +++++++++---- 2 files changed, 33 insertions(+), 18 deletions(-) diff --git a/Karatsuba Multiplication/KaratsubaMultiplication.playground/Contents.swift b/Karatsuba Multiplication/KaratsubaMultiplication.playground/Contents.swift index bf4454956..53980ac1e 100644 --- a/Karatsuba Multiplication/KaratsubaMultiplication.playground/Contents.swift +++ b/Karatsuba Multiplication/KaratsubaMultiplication.playground/Contents.swift @@ -2,17 +2,23 @@ import Foundation -infix operator ^^ { associativity left precedence 160 } +precedencegroup ExponentiativePrecedence { + higherThan: MultiplicationPrecedence + lowerThan: BitwiseShiftPrecedence + associativity: left +} + +infix operator ^^: ExponentiativePrecedence func ^^ (radix: Int, power: Int) -> Int { return Int(pow(Double(radix), Double(power))) } // Long Multiplication - O(n^2) -func multiply(num1: Int, _ num2: Int, base: Int = 10) -> Int { - let num1Array = String(num1).characters.reverse().map{ Int(String($0))! } - let num2Array = String(num2).characters.reverse().map{ Int(String($0))! } +func multiply(_ num1: Int, by num2: Int, base: Int = 10) -> Int { + let num1Array = String(num1).characters.reversed().map{ Int(String($0))! } + let num2Array = String(num2).characters.reversed().map{ Int(String($0))! } - var product = Array(count: num1Array.count + num2Array.count, repeatedValue: 0) + var product = Array(repeating: 0, count: num1Array.count + num2Array.count) for i in num1Array.indices { var carry = 0 @@ -24,16 +30,16 @@ func multiply(num1: Int, _ num2: Int, base: Int = 10) -> Int { product[i + num2Array.count] += carry } - return Int(product.reverse().map{ String($0) }.reduce("", combine: +))! + return Int(product.reversed().map{ String($0) }.reduce("", +))! } // Karatsuba Multiplication - O(nlogn) -func karatsuba(num1: Int, _ num2: Int) -> Int { +func karatsuba(_ num1: Int, by num2: Int) -> Int { let num1Array = String(num1).characters let num2Array = String(num2).characters guard num1Array.count > 1 && num2Array.count > 1 else { - return multiply(num1, num2) + return multiply(num1, by: num2) } let n = max(num1Array.count, num2Array.count) @@ -44,14 +50,12 @@ func karatsuba(num1: Int, _ num2: Int) -> Int { let c = num2 / 10^^nBy2 let d = num2 % 10^^nBy2 - let ac = karatsuba(a, c) - let bd = karatsuba(b, d) - let adPluscd = karatsuba(a+b, c+d) - ac - bd + let ac = karatsuba(a, by: c) + let bd = karatsuba(b, by: d) + let adPluscd = karatsuba(a+b, by: c+d) - ac - bd let product = ac * 10^^(2 * nBy2) + adPluscd * 10^^nBy2 + bd return product } -print(multiply(236742342, 1231234224)) -print(karatsuba(236742342, 1231234224)) \ No newline at end of file diff --git a/Karatsuba Multiplication/KaratsubaMultiplication.swift b/Karatsuba Multiplication/KaratsubaMultiplication.swift index a315d7494..7837e3f3c 100644 --- a/Karatsuba Multiplication/KaratsubaMultiplication.swift +++ b/Karatsuba Multiplication/KaratsubaMultiplication.swift @@ -8,7 +8,18 @@ import Foundation -func karatsuba(num1: Int, _ num2: Int) -> Int { +precedencegroup ExponentiativePrecedence { + higherThan: MultiplicationPrecedence + lowerThan: BitwiseShiftPrecedence + associativity: left +} + +infix operator ^^: ExponentiativePrecedence +func ^^ (radix: Int, power: Int) -> Int { + return Int(pow(Double(radix), Double(power))) +} + +func karatsuba(_ num1: Int, by num2: Int) -> Int { let num1Array = String(num1).characters let num2Array = String(num2).characters @@ -24,11 +35,11 @@ func karatsuba(num1: Int, _ num2: Int) -> Int { let c = num2 / 10^^nBy2 let d = num2 % 10^^nBy2 - let ac = karatsuba(a, c) - let bd = karatsuba(b, d) - let adPluscd = karatsuba(a+b, c+d) - ac - bd + let ac = karatsuba(a, by: c) + let bd = karatsuba(b, by: d) + let adPluscd = karatsuba(a+b, by: c+d) - ac - bd let product = ac * 10^^(2 * nBy2) + adPluscd * 10^^nBy2 + bd return product -} \ No newline at end of file +} From 215ca9352840b52be84fc171954613ddde6f7a5e Mon Sep 17 00:00:00 2001 From: SendilKumar N Date: Mon, 26 Sep 2016 17:00:03 +0800 Subject: [PATCH 0569/1679] migrating dfs to swift3 --- .../Simple Example.xcplaygroundpage/Contents.swift | 2 +- .../timeline.xctimeline | 6 ------ .../DepthFirstSearch.playground/Sources/Edge.swift | 4 ++-- .../DepthFirstSearch.playground/Sources/Graph.swift | 12 ++++++------ .../DepthFirstSearch.playground/Sources/Node.swift | 8 ++++---- Depth-First Search/DepthFirstSearch.swift | 2 +- Depth-First Search/README.markdown | 2 +- 7 files changed, 15 insertions(+), 21 deletions(-) delete mode 100644 Depth-First Search/DepthFirstSearch.playground/Pages/Simple Example.xcplaygroundpage/timeline.xctimeline diff --git a/Depth-First Search/DepthFirstSearch.playground/Pages/Simple Example.xcplaygroundpage/Contents.swift b/Depth-First Search/DepthFirstSearch.playground/Pages/Simple Example.xcplaygroundpage/Contents.swift index 770712bfb..b1d8494d6 100644 --- a/Depth-First Search/DepthFirstSearch.playground/Pages/Simple Example.xcplaygroundpage/Contents.swift +++ b/Depth-First Search/DepthFirstSearch.playground/Pages/Simple Example.xcplaygroundpage/Contents.swift @@ -1,4 +1,4 @@ -func depthFirstSearch(graph: Graph, source: Node) -> [String] { +func depthFirstSearch(_ graph: Graph, source: Node) -> [String] { var nodesExplored = [source.label] source.visited = true diff --git a/Depth-First Search/DepthFirstSearch.playground/Pages/Simple Example.xcplaygroundpage/timeline.xctimeline b/Depth-First Search/DepthFirstSearch.playground/Pages/Simple Example.xcplaygroundpage/timeline.xctimeline deleted file mode 100644 index bf468afec..000000000 --- a/Depth-First Search/DepthFirstSearch.playground/Pages/Simple Example.xcplaygroundpage/timeline.xctimeline +++ /dev/null @@ -1,6 +0,0 @@ - - - - - diff --git a/Depth-First Search/DepthFirstSearch.playground/Sources/Edge.swift b/Depth-First Search/DepthFirstSearch.playground/Sources/Edge.swift index 9a58a1f96..7c841be30 100644 --- a/Depth-First Search/DepthFirstSearch.playground/Sources/Edge.swift +++ b/Depth-First Search/DepthFirstSearch.playground/Sources/Edge.swift @@ -1,11 +1,11 @@ public class Edge: Equatable { public var neighbor: Node - public init(neighbor: Node) { + public init(_ neighbor: Node) { self.neighbor = neighbor } } -public func == (lhs: Edge, rhs: Edge) -> Bool { +public func == (_ lhs: Edge, rhs: Edge) -> Bool { return lhs.neighbor == rhs.neighbor } diff --git a/Depth-First Search/DepthFirstSearch.playground/Sources/Graph.swift b/Depth-First Search/DepthFirstSearch.playground/Sources/Graph.swift index 8cfb2a09c..87e21897c 100644 --- a/Depth-First Search/DepthFirstSearch.playground/Sources/Graph.swift +++ b/Depth-First Search/DepthFirstSearch.playground/Sources/Graph.swift @@ -5,14 +5,14 @@ public class Graph: CustomStringConvertible, Equatable { self.nodes = [] } - public func addNode(label: String) -> Node { - let node = Node(label: label) + public func addNode(_ label: String) -> Node { + let node = Node(label) nodes.append(node) return node } - public func addEdge(source: Node, neighbor: Node) { - let edge = Edge(neighbor: neighbor) + public func addEdge(_ source: Node, neighbor: Node) { + let edge = Edge(neighbor) source.neighbors.append(edge) } @@ -27,7 +27,7 @@ public class Graph: CustomStringConvertible, Equatable { return description } - public func findNodeWithLabel(label: String) -> Node { + public func findNodeWithLabel(_ label: String) -> Node { return nodes.filter { $0.label == label }.first! } @@ -50,6 +50,6 @@ public class Graph: CustomStringConvertible, Equatable { } } -public func == (lhs: Graph, rhs: Graph) -> Bool { +public func == (_ lhs: Graph, rhs: Graph) -> Bool { return lhs.nodes == rhs.nodes } diff --git a/Depth-First Search/DepthFirstSearch.playground/Sources/Node.swift b/Depth-First Search/DepthFirstSearch.playground/Sources/Node.swift index 37a3b3fdf..48fc952e3 100644 --- a/Depth-First Search/DepthFirstSearch.playground/Sources/Node.swift +++ b/Depth-First Search/DepthFirstSearch.playground/Sources/Node.swift @@ -5,7 +5,7 @@ public class Node: CustomStringConvertible, Equatable { public var distance: Int? public var visited: Bool - public init(label: String) { + public init(_ label: String) { self.label = label neighbors = [] visited = false @@ -22,11 +22,11 @@ public class Node: CustomStringConvertible, Equatable { return distance != nil } - public func remove(edge: Edge) { - neighbors.removeAtIndex(neighbors.indexOf { $0 === edge }!) + public func remove(_ edge: Edge) { + neighbors.remove(at: neighbors.index { $0 === edge }!) } } -public func == (lhs: Node, rhs: Node) -> Bool { +public func == (_ lhs: Node, rhs: Node) -> Bool { return lhs.label == rhs.label && lhs.neighbors == rhs.neighbors } diff --git a/Depth-First Search/DepthFirstSearch.swift b/Depth-First Search/DepthFirstSearch.swift index 4393ac864..04e84cb66 100644 --- a/Depth-First Search/DepthFirstSearch.swift +++ b/Depth-First Search/DepthFirstSearch.swift @@ -1,4 +1,4 @@ -func depthFirstSearch(graph: Graph, source: Node) -> [String] { +func depthFirstSearch(_ graph: Graph, source: Node) -> [String] { var nodesExplored = [source.label] source.visited = true diff --git a/Depth-First Search/README.markdown b/Depth-First Search/README.markdown index a44ae8163..9e1a5112d 100644 --- a/Depth-First Search/README.markdown +++ b/Depth-First Search/README.markdown @@ -27,7 +27,7 @@ The parent of a node is the one that "discovered" that node. The root of the tre Simple recursive implementation of depth-first search: ```swift -func depthFirstSearch(graph: Graph, source: Node) -> [String] { +func depthFirstSearch(_ graph: Graph, source: Node) -> [String] { var nodesExplored = [source.label] source.visited = true From ef081622f899131b7ba45c863637a9049f962d8d Mon Sep 17 00:00:00 2001 From: SendilKumar N Date: Mon, 26 Sep 2016 17:04:03 +0800 Subject: [PATCH 0570/1679] migrating bfs to swift3 --- .../Simple example.xcplaygroundpage/Contents.swift | 2 +- .../timeline.xctimeline | 6 ------ .../BreadthFirstSearch.playground/Sources/Edge.swift | 4 ++-- .../Sources/Graph.swift | 12 ++++++------ .../BreadthFirstSearch.playground/Sources/Node.swift | 8 ++++---- .../Sources/Queue.swift | 2 +- Breadth-First Search/BreadthFirstSearch.swift | 2 +- Breadth-First Search/README.markdown | 2 +- 8 files changed, 16 insertions(+), 22 deletions(-) delete mode 100644 Breadth-First Search/BreadthFirstSearch.playground/Pages/Simple example.xcplaygroundpage/timeline.xctimeline diff --git a/Breadth-First Search/BreadthFirstSearch.playground/Pages/Simple example.xcplaygroundpage/Contents.swift b/Breadth-First Search/BreadthFirstSearch.playground/Pages/Simple example.xcplaygroundpage/Contents.swift index 93aa6b337..0fb98e1c8 100644 --- a/Breadth-First Search/BreadthFirstSearch.playground/Pages/Simple example.xcplaygroundpage/Contents.swift +++ b/Breadth-First Search/BreadthFirstSearch.playground/Pages/Simple example.xcplaygroundpage/Contents.swift @@ -1,4 +1,4 @@ -func breadthFirstSearch(graph: Graph, source: Node) -> [String] { +func breadthFirstSearch(_ graph: Graph, source: Node) -> [String] { var queue = Queue() queue.enqueue(source) diff --git a/Breadth-First Search/BreadthFirstSearch.playground/Pages/Simple example.xcplaygroundpage/timeline.xctimeline b/Breadth-First Search/BreadthFirstSearch.playground/Pages/Simple example.xcplaygroundpage/timeline.xctimeline deleted file mode 100644 index bf468afec..000000000 --- a/Breadth-First Search/BreadthFirstSearch.playground/Pages/Simple example.xcplaygroundpage/timeline.xctimeline +++ /dev/null @@ -1,6 +0,0 @@ - - - - - diff --git a/Breadth-First Search/BreadthFirstSearch.playground/Sources/Edge.swift b/Breadth-First Search/BreadthFirstSearch.playground/Sources/Edge.swift index 9a58a1f96..7c841be30 100644 --- a/Breadth-First Search/BreadthFirstSearch.playground/Sources/Edge.swift +++ b/Breadth-First Search/BreadthFirstSearch.playground/Sources/Edge.swift @@ -1,11 +1,11 @@ public class Edge: Equatable { public var neighbor: Node - public init(neighbor: Node) { + public init(_ neighbor: Node) { self.neighbor = neighbor } } -public func == (lhs: Edge, rhs: Edge) -> Bool { +public func == (_ lhs: Edge, rhs: Edge) -> Bool { return lhs.neighbor == rhs.neighbor } diff --git a/Breadth-First Search/BreadthFirstSearch.playground/Sources/Graph.swift b/Breadth-First Search/BreadthFirstSearch.playground/Sources/Graph.swift index 8cfb2a09c..87e21897c 100644 --- a/Breadth-First Search/BreadthFirstSearch.playground/Sources/Graph.swift +++ b/Breadth-First Search/BreadthFirstSearch.playground/Sources/Graph.swift @@ -5,14 +5,14 @@ public class Graph: CustomStringConvertible, Equatable { self.nodes = [] } - public func addNode(label: String) -> Node { - let node = Node(label: label) + public func addNode(_ label: String) -> Node { + let node = Node(label) nodes.append(node) return node } - public func addEdge(source: Node, neighbor: Node) { - let edge = Edge(neighbor: neighbor) + public func addEdge(_ source: Node, neighbor: Node) { + let edge = Edge(neighbor) source.neighbors.append(edge) } @@ -27,7 +27,7 @@ public class Graph: CustomStringConvertible, Equatable { return description } - public func findNodeWithLabel(label: String) -> Node { + public func findNodeWithLabel(_ label: String) -> Node { return nodes.filter { $0.label == label }.first! } @@ -50,6 +50,6 @@ public class Graph: CustomStringConvertible, Equatable { } } -public func == (lhs: Graph, rhs: Graph) -> Bool { +public func == (_ lhs: Graph, rhs: Graph) -> Bool { return lhs.nodes == rhs.nodes } diff --git a/Breadth-First Search/BreadthFirstSearch.playground/Sources/Node.swift b/Breadth-First Search/BreadthFirstSearch.playground/Sources/Node.swift index 37a3b3fdf..48fc952e3 100644 --- a/Breadth-First Search/BreadthFirstSearch.playground/Sources/Node.swift +++ b/Breadth-First Search/BreadthFirstSearch.playground/Sources/Node.swift @@ -5,7 +5,7 @@ public class Node: CustomStringConvertible, Equatable { public var distance: Int? public var visited: Bool - public init(label: String) { + public init(_ label: String) { self.label = label neighbors = [] visited = false @@ -22,11 +22,11 @@ public class Node: CustomStringConvertible, Equatable { return distance != nil } - public func remove(edge: Edge) { - neighbors.removeAtIndex(neighbors.indexOf { $0 === edge }!) + public func remove(_ edge: Edge) { + neighbors.remove(at: neighbors.index { $0 === edge }!) } } -public func == (lhs: Node, rhs: Node) -> Bool { +public func == (_ lhs: Node, rhs: Node) -> Bool { return lhs.label == rhs.label && lhs.neighbors == rhs.neighbors } diff --git a/Breadth-First Search/BreadthFirstSearch.playground/Sources/Queue.swift b/Breadth-First Search/BreadthFirstSearch.playground/Sources/Queue.swift index bf462bbdd..3d98f801c 100644 --- a/Breadth-First Search/BreadthFirstSearch.playground/Sources/Queue.swift +++ b/Breadth-First Search/BreadthFirstSearch.playground/Sources/Queue.swift @@ -13,7 +13,7 @@ public struct Queue { return array.count } - public mutating func enqueue(element: T) { + public mutating func enqueue(_ element: T) { array.append(element) } diff --git a/Breadth-First Search/BreadthFirstSearch.swift b/Breadth-First Search/BreadthFirstSearch.swift index aa396ac7b..75508682a 100644 --- a/Breadth-First Search/BreadthFirstSearch.swift +++ b/Breadth-First Search/BreadthFirstSearch.swift @@ -1,4 +1,4 @@ -func breadthFirstSearch(graph: Graph, source: Node) -> [String] { +func breadthFirstSearch(_ graph: Graph, source: Node) -> [String] { var queue = Queue() queue.enqueue(source) diff --git a/Breadth-First Search/README.markdown b/Breadth-First Search/README.markdown index 12e906532..23edf6da5 100644 --- a/Breadth-First Search/README.markdown +++ b/Breadth-First Search/README.markdown @@ -90,7 +90,7 @@ For an unweighted graph, this tree defines a shortest path from the starting nod Simple implementation of breadth-first search using a queue: ```swift -func breadthFirstSearch(graph: Graph, source: Node) -> [String] { +func breadthFirstSearch(_ graph: Graph, source: Node) -> [String] { var queue = Queue() queue.enqueue(source) From a2bdc50e9e2307c11ad232f37acca34d944ff211 Mon Sep 17 00:00:00 2001 From: SendilKumar N Date: Mon, 26 Sep 2016 17:26:34 +0800 Subject: [PATCH 0571/1679] Migrating Brute Force String Search to Swift3 --- .../Contents.swift | 11 ++++---- .../timeline.xctimeline | 6 ---- .../BruteForceStringSearch.swift | 28 +++++++++---------- Brute-Force String Search/README.markdown | 28 +++++++++---------- 4 files changed, 34 insertions(+), 39 deletions(-) delete mode 100644 Brute-Force String Search/BruteForceStringSearch.playground/timeline.xctimeline diff --git a/Brute-Force String Search/BruteForceStringSearch.playground/Contents.swift b/Brute-Force String Search/BruteForceStringSearch.playground/Contents.swift index 57f2b2090..61064c698 100644 --- a/Brute-Force String Search/BruteForceStringSearch.playground/Contents.swift +++ b/Brute-Force String Search/BruteForceStringSearch.playground/Contents.swift @@ -1,16 +1,17 @@ //: Playground - noun: a place where people can play extension String { - func indexOf(pattern: String) -> String.Index? { - for i in self.startIndex ..< self.endIndex { + func indexOf(_ pattern: String) -> String.Index? { + + for i in self.characters.indices { var j = i var found = true - for p in pattern.startIndex ..< pattern.endIndex { - if j == self.endIndex || self[j] != pattern[p] { + for p in pattern.characters.indices{ + if j == self.characters.endIndex || self[j] != pattern[p] { found = false break } else { - j = j.successor() + j = self.characters.index(after: j) } } if found { diff --git a/Brute-Force String Search/BruteForceStringSearch.playground/timeline.xctimeline b/Brute-Force String Search/BruteForceStringSearch.playground/timeline.xctimeline deleted file mode 100644 index bf468afec..000000000 --- a/Brute-Force String Search/BruteForceStringSearch.playground/timeline.xctimeline +++ /dev/null @@ -1,6 +0,0 @@ - - - - - diff --git a/Brute-Force String Search/BruteForceStringSearch.swift b/Brute-Force String Search/BruteForceStringSearch.swift index 431677a4a..03a2dff13 100644 --- a/Brute-Force String Search/BruteForceStringSearch.swift +++ b/Brute-Force String Search/BruteForceStringSearch.swift @@ -2,21 +2,21 @@ Brute-force string search */ extension String { - func indexOf(pattern: String) -> String.Index? { - for i in self.startIndex ..< self.endIndex { - var j = i - var found = true - for p in pattern.startIndex ..< pattern.endIndex { - if j == self.endIndex || self[j] != pattern[p] { - found = false - break - } else { - j = j.successor() + func indexOf(_ pattern: String) -> String.Index? { + for i in self.characters.indices { + var j = i + var found = true + for p in pattern.characters.indices{ + if j == self.characters.endIndex || self[j] != pattern[p] { + found = false + break + } else { + j = self.characters.index(after: j) + } + } + if found { + return i } - } - if found { - return i - } } return nil } diff --git a/Brute-Force String Search/README.markdown b/Brute-Force String Search/README.markdown index 748be872f..4e967bcfb 100644 --- a/Brute-Force String Search/README.markdown +++ b/Brute-Force String Search/README.markdown @@ -28,21 +28,21 @@ Here is a brute-force solution: ```swift extension String { - func indexOf(pattern: String) -> String.Index? { - for i in self.startIndex ..< self.endIndex { - var j = i - var found = true - for p in pattern.startIndex ..< pattern.endIndex { - if j == self.endIndex || self[j] != pattern[p] { - found = false - break - } else { - j = j.successor() + func indexOf(_ pattern: String) -> String.Index? { + for i in self.characters.indices { + var j = i + var found = true + for p in pattern.characters.indices{ + if j == self.characters.endIndex || self[j] != pattern[p] { + found = false + break + } else { + j = self.characters.index(after: j) + } + } + if found { + return i } - } - if found { - return i - } } return nil } From 183cfcf5e26c35f68a2f7ec0d075c11dcf597e55 Mon Sep 17 00:00:00 2001 From: SendilKumar N Date: Tue, 27 Sep 2016 12:08:19 +0800 Subject: [PATCH 0572/1679] migrating montyhall to swift 3 --- Monty Hall Problem/MontyHall.playground/Contents.swift | 2 +- Monty Hall Problem/MontyHall.playground/timeline.xctimeline | 6 ------ 2 files changed, 1 insertion(+), 7 deletions(-) delete mode 100644 Monty Hall Problem/MontyHall.playground/timeline.xctimeline diff --git a/Monty Hall Problem/MontyHall.playground/Contents.swift b/Monty Hall Problem/MontyHall.playground/Contents.swift index 930dad714..bcdafd137 100644 --- a/Monty Hall Problem/MontyHall.playground/Contents.swift +++ b/Monty Hall Problem/MontyHall.playground/Contents.swift @@ -2,7 +2,7 @@ import Foundation -func random(n: Int) -> Int { +func random(_ n: Int) -> Int { return Int(arc4random_uniform(UInt32(n))) } diff --git a/Monty Hall Problem/MontyHall.playground/timeline.xctimeline b/Monty Hall Problem/MontyHall.playground/timeline.xctimeline deleted file mode 100644 index bf468afec..000000000 --- a/Monty Hall Problem/MontyHall.playground/timeline.xctimeline +++ /dev/null @@ -1,6 +0,0 @@ - - - - - From ecbcfeaa8f41d8bc2fde76933d2bf664c958cf3c Mon Sep 17 00:00:00 2001 From: SendilKumar N Date: Tue, 27 Sep 2016 12:41:55 +0800 Subject: [PATCH 0573/1679] migrating radix-sort to swift3 --- .../Sources/RadixTree.swift | 38 +- Radix Tree/RadixTree.swift | 730 +++++++++--------- 2 files changed, 384 insertions(+), 384 deletions(-) diff --git a/Radix Tree/RadixTree.playground/Sources/RadixTree.swift b/Radix Tree/RadixTree.playground/Sources/RadixTree.swift index 3cba5254a..1914f57bc 100644 --- a/Radix Tree/RadixTree.playground/Sources/RadixTree.swift +++ b/Radix Tree/RadixTree.playground/Sources/RadixTree.swift @@ -85,7 +85,7 @@ public class Edge: Root { // For each child, erase it, then remove it from the children array. for _ in 0...children.count-1 { children[0].erase() - children.removeAtIndex(0) + children.remove(at: 0) } } } @@ -137,7 +137,7 @@ public class RadixTree { } // Inserts a string into the tree. - public func insert(str: String) -> Bool { + public func insert(_ str: String) -> Bool { //Account for a blank input. The empty string is already in the tree. if str == "" { return false @@ -182,9 +182,9 @@ public class RadixTree { currEdge = e var tempIndex = searchStr.startIndex for _ in 1...shared.characters.count { - tempIndex = tempIndex.successor() + tempIndex = searchStr.characters.index(after: tempIndex) } - searchStr = searchStr.substringFromIndex(tempIndex) + searchStr = searchStr.substring(from: tempIndex) found = true break } @@ -197,13 +197,13 @@ public class RadixTree { // Create index objects and move them to after the shared prefix for _ in 1...shared.characters.count { - index = index.successor() - labelIndex = labelIndex.successor() + index = searchStr.characters.index(after: index) + labelIndex = e.label.characters.index(after: labelIndex) } // Substring both the search string and the label from the shared prefix - searchStr = searchStr.substringFromIndex(index) - e.label = e.label.substringFromIndex(labelIndex) + searchStr = searchStr.substring(from: index) + e.label = e.label.substring(from: labelIndex) // Create 2 new edges and update parent/children values let newEdge = Edge(e.label) @@ -236,7 +236,7 @@ public class RadixTree { } // Tells you if a string is in the tree - public func find(str: String) -> Bool { + public func find(_ str: String) -> Bool { // A radix tree always contains the empty string if str == "" { return true @@ -267,9 +267,9 @@ public class RadixTree { currEdge = c var tempIndex = searchStr.startIndex for _ in 1...shared.characters.count { - tempIndex = tempIndex.successor() + tempIndex = searchStr.characters.index(after: tempIndex) } - searchStr = searchStr.substringFromIndex(tempIndex) + searchStr = searchStr.substring(from: tempIndex) found = true break } @@ -300,12 +300,12 @@ public class RadixTree { } // Removes a string from the tree - public func remove(str: String) -> Bool { + public func remove(_ str: String) -> Bool { // Removing the empty string removes everything in the tree if str == "" { for c in root.children { c.erase() - root.children.removeAtIndex(0) + root.children.remove(at: 0) } return true } @@ -329,7 +329,7 @@ public class RadixTree { // and everything below it in the tree if currEdge.children[c].label == searchStr { currEdge.children[c].erase() - currEdge.children.removeAtIndex(c) + currEdge.children.remove(at: c) return true } @@ -341,9 +341,9 @@ public class RadixTree { currEdge = currEdge.children[c] var tempIndex = searchStr.startIndex for _ in 1...shared.characters.count { - tempIndex = tempIndex.successor() + tempIndex = searchStr.characters.index(after: tempIndex) } - searchStr = searchStr.substringFromIndex(tempIndex) + searchStr = searchStr.substring(from: tempIndex) found = true break } @@ -364,15 +364,15 @@ public class RadixTree { // Returns the prefix that is shared between the two input strings // i.e. sharedPrefix("court", "coral") -> "co" -public func sharedPrefix(str1: String, _ str2: String) -> String { +public func sharedPrefix(_ str1: String, _ str2: String) -> String { var temp = "" var c1 = str1.characters.startIndex var c2 = str2.characters.startIndex for _ in 0...min(str1.characters.count-1, str2.characters.count-1) { if str1[c1] == str2[c2] { temp.append( str1[c1] ) - c1 = c1.successor() - c2 = c2.successor() + c1 = str1.characters.index(after:c1) + c2 = str2.characters.index(after:c2) } else { return temp } diff --git a/Radix Tree/RadixTree.swift b/Radix Tree/RadixTree.swift index 3cba5254a..5badf0810 100644 --- a/Radix Tree/RadixTree.swift +++ b/Radix Tree/RadixTree.swift @@ -2,380 +2,380 @@ import Foundation // The root is the top of the Radix Tree public class Root { - var children: [Edge] - - public init() { - children = [Edge]() - } - - // Returns the length (in number of edges) of the longest traversal down the tree. - public func height() -> Int { - // Base case: no children: the tree has a height of 1 - if children.count == 0 { - return 1 - } - // Recursion: find the max height of a root's child and return 1 + that max - else { - var max = 1 - for c in children { - if c.height() > max { - max = c.height() - } - } - return 1 + max - } - } - - // Returns how far down in the tree a Root/Edge is. - // A root's level is always 0. - public func level() -> Int { - return 0 - } - - // Prints the tree for debugging/visualization purposes. - public func printRoot() { - // Print the first half of the children - if children.count > 1 { - for c in 0...children.count/2-1 { - children[c].printEdge() - print("|") - } - } else if children.count > 0 { - children[0].printEdge() - } - // Then print the root - print("ROOT") - // Print the second half of the children - if children.count > 1 { - for c in children.count/2...children.count-1 { - children[c].printEdge() - print("|") - } - } - print() - } + var children: [Edge] + + public init() { + children = [Edge]() + } + + // Returns the length (in number of edges) of the longest traversal down the tree. + public func height() -> Int { + // Base case: no children: the tree has a height of 1 + if children.count == 0 { + return 1 + } + // Recursion: find the max height of a root's child and return 1 + that max + else { + var max = 1 + for c in children { + if c.height() > max { + max = c.height() + } + } + return 1 + max + } + } + + // Returns how far down in the tree a Root/Edge is. + // A root's level is always 0. + public func level() -> Int { + return 0 + } + + // Prints the tree for debugging/visualization purposes. + public func printRoot() { + // Print the first half of the children + if children.count > 1 { + for c in 0...children.count/2-1 { + children[c].printEdge() + print("|") + } + } else if children.count > 0 { + children[0].printEdge() + } + // Then print the root + print("ROOT") + // Print the second half of the children + if children.count > 1 { + for c in children.count/2...children.count-1 { + children[c].printEdge() + print("|") + } + } + print() + } } // Edges are what actually store the Strings in the tree public class Edge: Root { - var parent: Root? - var label: String - - public init(_ label: String) { - self.label = label - super.init() - } - - public override func level() -> Int { - // Recurse up the tree incrementing level by one until the root is reached - if parent != nil { - return 1 + parent!.level() - } - // If an edge has no parent, it's level is one - // NOTE: THIS SHOULD NEVER HAPPEN AS THE ROOT IS ALWAYS THE TOP OF THE TREE - else { - return 1 - } - } - - // Erases a specific edge (and all edges below it in the tree). - public func erase() { - self.parent = nil - if children.count > 0 { - // For each child, erase it, then remove it from the children array. - for _ in 0...children.count-1 { - children[0].erase() - children.removeAtIndex(0) - } - } - } - - // Prints the tree for debugging/visualization purposes. - public func printEdge() { - // Print the first half of the edge's children - if children.count > 1 { - for c in 0...children.count/2-1 { - children[c].printEdge() - } - } else if children.count > 0 { - children[0].printEdge() - } - // Tab over once up to the edge's level - for x in 1...level() { - if x == level() { - print("|------>", terminator: "") - } else { - print("| ", terminator: "") - } - } - print(label) - // Print the second half of the edge's children - if children.count == 0 { - for _ in 1...level() { - print("| ", terminator: "") - } - print() - } - if children.count > 1 { - for c in children.count/2...children.count-1 { - children[c].printEdge() - } - } - } + var parent: Root? + var label: String + + public init(_ label: String) { + self.label = label + super.init() + } + + public override func level() -> Int { + // Recurse up the tree incrementing level by one until the root is reached + if parent != nil { + return 1 + parent!.level() + } + // If an edge has no parent, it's level is one + // NOTE: THIS SHOULD NEVER HAPPEN AS THE ROOT IS ALWAYS THE TOP OF THE TREE + else { + return 1 + } + } + + // Erases a specific edge (and all edges below it in the tree). + public func erase() { + self.parent = nil + if children.count > 0 { + // For each child, erase it, then remove it from the children array. + for _ in 0...children.count-1 { + children[0].erase() + children.remove(at: 0) + } + } + } + + // Prints the tree for debugging/visualization purposes. + public func printEdge() { + // Print the first half of the edge's children + if children.count > 1 { + for c in 0...children.count/2-1 { + children[c].printEdge() + } + } else if children.count > 0 { + children[0].printEdge() + } + // Tab over once up to the edge's level + for x in 1...level() { + if x == level() { + print("|------>", terminator: "") + } else { + print("| ", terminator: "") + } + } + print(label) + // Print the second half of the edge's children + if children.count == 0 { + for _ in 1...level() { + print("| ", terminator: "") + } + print() + } + if children.count > 1 { + for c in children.count/2...children.count-1 { + children[c].printEdge() + } + } + } } public class RadixTree { - var root: Root - - public init() { - root = Root() - } - - // Returns the height of the tree by calling the root's height function. - public func height() -> Int { - return root.height() - 1 - } - - // Inserts a string into the tree. - public func insert(str: String) -> Bool { - //Account for a blank input. The empty string is already in the tree. - if str == "" { - return false - } - - // searchStr is the parameter of the function - // it will be substringed as the function traverses down the tree - var searchStr = str - - // currEdge is the current Edge (or Root) in question - var currEdge = root - - while true { - var found = false - - // If the current Edge has no children then the remaining searchStr is - // created as a child - if currEdge.children.count == 0 { - let newEdge = Edge(searchStr) - currEdge.children.append(newEdge) - newEdge.parent = currEdge - return true - } - - // Loop through all of the children - for e in currEdge.children { - // Get the shared prefix between the child in question and the - // search string - let shared = sharedPrefix(searchStr, e.label) - var index = shared.startIndex - - // If the search string is equal to the shared string, - // the string already exists in the tree - if searchStr == shared { - return false - } - - // If the child's label is equal to the shared string, you have to - // traverse another level down the tree, so substring the search - // string, break the loop, and run it back - else if shared == e.label { - currEdge = e - var tempIndex = searchStr.startIndex - for _ in 1...shared.characters.count { - tempIndex = tempIndex.successor() - } - searchStr = searchStr.substringFromIndex(tempIndex) - found = true - break - } - - // If the child's label and the search string share a partial prefix, - // then both the label and the search string need to be substringed - // and a new branch needs to be created - else if shared.characters.count > 0 { - var labelIndex = e.label.characters.startIndex - - // Create index objects and move them to after the shared prefix - for _ in 1...shared.characters.count { - index = index.successor() - labelIndex = labelIndex.successor() - } - - // Substring both the search string and the label from the shared prefix - searchStr = searchStr.substringFromIndex(index) - e.label = e.label.substringFromIndex(labelIndex) - - // Create 2 new edges and update parent/children values - let newEdge = Edge(e.label) - e.label = shared - for ec in e.children { - newEdge.children.append(ec) - } - newEdge.parent = e - e.children.removeAll() - for nec in newEdge.children { - nec.parent = newEdge - } - e.children.append(newEdge) - let newEdge2 = Edge(searchStr) - newEdge2.parent = e - e.children.append(newEdge2) - return true - } - // If they don't share a prefix, go to next child - } - - // If none of the children share a prefix, you have to create a new child - if !found { - let newEdge = Edge(searchStr) - currEdge.children.append(newEdge) - newEdge.parent = currEdge - return true - } - } - } - - // Tells you if a string is in the tree - public func find(str: String) -> Bool { - // A radix tree always contains the empty string - if str == "" { - return true - } - // If there are no children then the string cannot be in the tree - else if root.children.count == 0 { - return false - } - var searchStr = str - var currEdge = root - while true { - var found = false - // Loop through currEdge's children - for c in currEdge.children { - // First check if the search string and the child's label are equal - // if so the string is in the tree, return true - if searchStr == c.label { - return true - } - - // If that is not true, find the shared string b/t the search string - // and the label - let shared = sharedPrefix(searchStr, c.label) - - // If the shared string is equal to the label, update the curent node, - // break the loop, and run it back - if shared == c.label { - currEdge = c - var tempIndex = searchStr.startIndex - for _ in 1...shared.characters.count { - tempIndex = tempIndex.successor() - } - searchStr = searchStr.substringFromIndex(tempIndex) - found = true - break - } - - // If the shared string is empty, go to the next child - else if shared.characters.count == 0 { - continue - } - - // If the shared string matches the search string, return true - else if shared == searchStr { - return true - } - - // If the search string and the child's label only share some characters, - // the string is not in the tree, return false - else if shared[shared.startIndex] == c.label[c.label.startIndex] && - shared.characters.count < c.label.characters.count { - return false - } - } - - // If nothing was found, return false - if !found { - return false - } - } - } - - // Removes a string from the tree - public func remove(str: String) -> Bool { - // Removing the empty string removes everything in the tree - if str == "" { - for c in root.children { - c.erase() - root.children.removeAtIndex(0) - } - return true - } - // If the tree is empty, you cannot remove anything - else if root.children.count == 0 { - return false - } - - var searchStr = str - var currEdge = root - while true { - var found = false - // If currEdge has no children, then the searchStr is not in the tree - if currEdge.children.count == 0 { - return false - } - - // Loop through the children - for c in 0...currEdge.children.count-1 { - // If the child's label matches the search string, remove that child - // and everything below it in the tree - if currEdge.children[c].label == searchStr { - currEdge.children[c].erase() - currEdge.children.removeAtIndex(c) - return true - } - - // Find the shared string - let shared = sharedPrefix(searchStr, currEdge.children[c].label) - - // If the shared string is equal to the child's string, go down a level - if shared == currEdge.children[c].label { - currEdge = currEdge.children[c] - var tempIndex = searchStr.startIndex - for _ in 1...shared.characters.count { - tempIndex = tempIndex.successor() - } - searchStr = searchStr.substringFromIndex(tempIndex) - found = true - break - } - } - - // If there is no match, then the searchStr is not in the tree - if !found { - return false - } - } - } - - // Prints the tree by calling the root's print function - public func printTree() { - root.printRoot() - } + var root: Root + + public init() { + root = Root() + } + + // Returns the height of the tree by calling the root's height function. + public func height() -> Int { + return root.height() - 1 + } + + // Inserts a string into the tree. + public func insert(_ str: String) -> Bool { + //Account for a blank input. The empty string is already in the tree. + if str == "" { + return false + } + + // searchStr is the parameter of the function + // it will be substringed as the function traverses down the tree + var searchStr = str + + // currEdge is the current Edge (or Root) in question + var currEdge = root + + while true { + var found = false + + // If the current Edge has no children then the remaining searchStr is + // created as a child + if currEdge.children.count == 0 { + let newEdge = Edge(searchStr) + currEdge.children.append(newEdge) + newEdge.parent = currEdge + return true + } + + // Loop through all of the children + for e in currEdge.children { + // Get the shared prefix between the child in question and the + // search string + let shared = sharedPrefix(searchStr, e.label) + var index = shared.startIndex + + // If the search string is equal to the shared string, + // the string already exists in the tree + if searchStr == shared { + return false + } + + // If the child's label is equal to the shared string, you have to + // traverse another level down the tree, so substring the search + // string, break the loop, and run it back + else if shared == e.label { + currEdge = e + var tempIndex = searchStr.startIndex + for _ in 1...shared.characters.count { + tempIndex = searchStr.characters.index(after: tempIndex) + } + searchStr = searchStr.substring(from: tempIndex) + found = true + break + } + + // If the child's label and the search string share a partial prefix, + // then both the label and the search string need to be substringed + // and a new branch needs to be created + else if shared.characters.count > 0 { + var labelIndex = e.label.characters.startIndex + + // Create index objects and move them to after the shared prefix + for _ in 1...shared.characters.count { + index = searchStr.characters.index(after: index) + labelIndex = e.label.characters.index(after: labelIndex) + } + + // Substring both the search string and the label from the shared prefix + searchStr = searchStr.substring(from: index) + e.label = e.label.substring(from: labelIndex) + + // Create 2 new edges and update parent/children values + let newEdge = Edge(e.label) + e.label = shared + for ec in e.children { + newEdge.children.append(ec) + } + newEdge.parent = e + e.children.removeAll() + for nec in newEdge.children { + nec.parent = newEdge + } + e.children.append(newEdge) + let newEdge2 = Edge(searchStr) + newEdge2.parent = e + e.children.append(newEdge2) + return true + } + // If they don't share a prefix, go to next child + } + + // If none of the children share a prefix, you have to create a new child + if !found { + let newEdge = Edge(searchStr) + currEdge.children.append(newEdge) + newEdge.parent = currEdge + return true + } + } + } + + // Tells you if a string is in the tree + public func find(_ str: String) -> Bool { + // A radix tree always contains the empty string + if str == "" { + return true + } + // If there are no children then the string cannot be in the tree + else if root.children.count == 0 { + return false + } + var searchStr = str + var currEdge = root + while true { + var found = false + // Loop through currEdge's children + for c in currEdge.children { + // First check if the search string and the child's label are equal + // if so the string is in the tree, return true + if searchStr == c.label { + return true + } + + // If that is not true, find the shared string b/t the search string + // and the label + let shared = sharedPrefix(searchStr, c.label) + + // If the shared string is equal to the label, update the curent node, + // break the loop, and run it back + if shared == c.label { + currEdge = c + var tempIndex = searchStr.startIndex + for _ in 1...shared.characters.count { + tempIndex = searchStr.characters.index(after: tempIndex) + } + searchStr = searchStr.substring(from: tempIndex) + found = true + break + } + + // If the shared string is empty, go to the next child + else if shared.characters.count == 0 { + continue + } + + // If the shared string matches the search string, return true + else if shared == searchStr { + return true + } + + // If the search string and the child's label only share some characters, + // the string is not in the tree, return false + else if shared[shared.startIndex] == c.label[c.label.startIndex] && + shared.characters.count < c.label.characters.count { + return false + } + } + + // If nothing was found, return false + if !found { + return false + } + } + } + + // Removes a string from the tree + public func remove(_ str: String) -> Bool { + // Removing the empty string removes everything in the tree + if str == "" { + for c in root.children { + c.erase() + root.children.remove(at: 0) + } + return true + } + // If the tree is empty, you cannot remove anything + else if root.children.count == 0 { + return false + } + + var searchStr = str + var currEdge = root + while true { + var found = false + // If currEdge has no children, then the searchStr is not in the tree + if currEdge.children.count == 0 { + return false + } + + // Loop through the children + for c in 0...currEdge.children.count-1 { + // If the child's label matches the search string, remove that child + // and everything below it in the tree + if currEdge.children[c].label == searchStr { + currEdge.children[c].erase() + currEdge.children.remove(at: c) + return true + } + + // Find the shared string + let shared = sharedPrefix(searchStr, currEdge.children[c].label) + + // If the shared string is equal to the child's string, go down a level + if shared == currEdge.children[c].label { + currEdge = currEdge.children[c] + var tempIndex = searchStr.startIndex + for _ in 1...shared.characters.count { + tempIndex = searchStr.characters.index(after: tempIndex) + } + searchStr = searchStr.substring(from: tempIndex) + found = true + break + } + } + + // If there is no match, then the searchStr is not in the tree + if !found { + return false + } + } + } + + // Prints the tree by calling the root's print function + public func printTree() { + root.printRoot() + } } // Returns the prefix that is shared between the two input strings // i.e. sharedPrefix("court", "coral") -> "co" -public func sharedPrefix(str1: String, _ str2: String) -> String { - var temp = "" - var c1 = str1.characters.startIndex - var c2 = str2.characters.startIndex - for _ in 0...min(str1.characters.count-1, str2.characters.count-1) { - if str1[c1] == str2[c2] { - temp.append( str1[c1] ) - c1 = c1.successor() - c2 = c2.successor() - } else { - return temp - } - } - return temp +public func sharedPrefix(_ str1: String, _ str2: String) -> String { + var temp = "" + var c1 = str1.characters.startIndex + var c2 = str2.characters.startIndex + for _ in 0...min(str1.characters.count-1, str2.characters.count-1) { + if str1[c1] == str2[c2] { + temp.append( str1[c1] ) + c1 = str1.characters.index(after:c1) + c2 = str2.characters.index(after:c2) + } else { + return temp + } + } + return temp } From b2c302faf26a78e0eafceaf0496cd7262b9305b2 Mon Sep 17 00:00:00 2001 From: Hai Nguyen Date: Tue, 27 Sep 2016 21:10:24 -0700 Subject: [PATCH 0574/1679] Migrate LCS to Swift 3.0 --- .travis.yml | 2 +- .../Contents.swift | 18 ++++---- .../contents.xcplayground | 2 +- .../LongestCommonSubsequence.swift | 19 +++++---- Longest Common Subsequence/README.markdown | 31 +++++++------- .../Tests/Tests.xcodeproj/project.pbxproj | 41 ++++++++++++++++++- .../xcshareddata/xcschemes/Tests.xcscheme | 2 +- 7 files changed, 77 insertions(+), 38 deletions(-) diff --git a/.travis.yml b/.travis.yml index a04a2e742..949fc759f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -26,7 +26,7 @@ script: - xcodebuild test -project ./Insertion\ Sort/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./K-Means/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Linked\ List/Tests/Tests.xcodeproj -scheme Tests -# - xcodebuild test -project ./Longest\ Common\ Subsequence/Tests/Tests.xcodeproj -scheme Tests +- xcodebuild test -project ./Longest\ Common\ Subsequence/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Minimum\ Spanning\ Tree\ \(Unweighted\)/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Priority\ Queue/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Queue/Tests/Tests.xcodeproj -scheme Tests diff --git a/Longest Common Subsequence/LongestCommonSubsequence.playground/Contents.swift b/Longest Common Subsequence/LongestCommonSubsequence.playground/Contents.swift index bb6fa7c2a..0fc9ec325 100644 --- a/Longest Common Subsequence/LongestCommonSubsequence.playground/Contents.swift +++ b/Longest Common Subsequence/LongestCommonSubsequence.playground/Contents.swift @@ -1,11 +1,11 @@ extension String { - public func longestCommonSubsequence(other: String) -> String { + public func longestCommonSubsequence(_ other: String) -> String { - func lcsLength(other: String) -> [[Int]] { - var matrix = [[Int]](count: self.characters.count+1, repeatedValue: [Int](count: other.characters.count+1, repeatedValue: 0)) + func lcsLength(_ other: String) -> [[Int]] { + var matrix = [[Int]](repeating: [Int](repeating: 0, count: other.characters.count+1), count: self.characters.count+1) - for (i, selfChar) in self.characters.enumerate() { - for (j, otherChar) in other.characters.enumerate() { + for (i, selfChar) in self.characters.enumerated() { + for (j, otherChar) in other.characters.enumerated() { if otherChar == selfChar { matrix[i+1][j+1] = matrix[i][j] + 1 } else { @@ -16,7 +16,7 @@ extension String { return matrix } - func backtrack(matrix: [[Int]]) -> String { + func backtrack(_ matrix: [[Int]]) -> String { var i = self.characters.count var j = other.characters.count var charInSequence = self.endIndex @@ -28,15 +28,15 @@ extension String { j -= 1 } else if matrix[i][j] == matrix[i - 1][j] { i -= 1 - charInSequence = charInSequence.predecessor() + charInSequence = self.index(before: charInSequence) } else { i -= 1 j -= 1 - charInSequence = charInSequence.predecessor() + charInSequence = self.index(before: charInSequence) lcs.append(self[charInSequence]) } } - return String(lcs.characters.reverse()) + return String(lcs.characters.reversed()) } return backtrack(lcsLength(other)) diff --git a/Longest Common Subsequence/LongestCommonSubsequence.playground/contents.xcplayground b/Longest Common Subsequence/LongestCommonSubsequence.playground/contents.xcplayground index 5da2641c9..9f5f2f40c 100644 --- a/Longest Common Subsequence/LongestCommonSubsequence.playground/contents.xcplayground +++ b/Longest Common Subsequence/LongestCommonSubsequence.playground/contents.xcplayground @@ -1,4 +1,4 @@ - + \ No newline at end of file diff --git a/Longest Common Subsequence/LongestCommonSubsequence.swift b/Longest Common Subsequence/LongestCommonSubsequence.swift index 23d191102..b6834279d 100644 --- a/Longest Common Subsequence/LongestCommonSubsequence.swift +++ b/Longest Common Subsequence/LongestCommonSubsequence.swift @@ -1,17 +1,17 @@ extension String { - public func longestCommonSubsequence(other: String) -> String { + public func longestCommonSubsequence(_ other: String) -> String { // Computes the length of the lcs using dynamic programming. // Output is a matrix of size (n+1)x(m+1), where matrix[x][y] is the length // of lcs between substring (0, x-1) of self and substring (0, y-1) of other. - func lcsLength(other: String) -> [[Int]] { + func lcsLength(_ other: String) -> [[Int]] { // Create matrix of size (n+1)x(m+1). The algorithm needs first row and // first column to be filled with 0. - var matrix = [[Int]](count: self.characters.count+1, repeatedValue: [Int](count: other.characters.count+1, repeatedValue: 0)) + var matrix = [[Int]](repeating: [Int](repeating: 0, count: other.characters.count+1), count: self.characters.count+1) - for (i, selfChar) in self.characters.enumerate() { - for (j, otherChar) in other.characters.enumerate() { + for (i, selfChar) in self.characters.enumerated() { + for (j, otherChar) in other.characters.enumerated() { if otherChar == selfChar { // Common char found, add 1 to highest lcs found so far. matrix[i+1][j+1] = matrix[i][j] + 1 @@ -28,7 +28,7 @@ extension String { // Backtracks from matrix[n][m] to matrix[1][1] looking for chars that are // common to both strings. - func backtrack(matrix: [[Int]]) -> String { + func backtrack(_ matrix: [[Int]]) -> String { var i = self.characters.count var j = other.characters.count @@ -46,21 +46,22 @@ extension String { else if matrix[i][j] == matrix[i - 1][j] { i -= 1 // As i was decremented, move back charInSequence. - charInSequence = charInSequence.predecessor() + charInSequence = self.index(before: charInSequence) } // Value on the left and above are different than current cell. // This means 1 was added to lcs length (line 17). else { i -= 1 j -= 1 - charInSequence = charInSequence.predecessor() + charInSequence = self.index(before: charInSequence) + lcs.append(self[charInSequence]) } } // Due to backtrack, chars were added in reverse order: reverse it back. // Append and reverse is faster than inserting at index 0. - return String(lcs.characters.reverse()) + return String(lcs.characters.reversed()) } // Combine dynamic programming approach with backtrack to find the lcs. diff --git a/Longest Common Subsequence/README.markdown b/Longest Common Subsequence/README.markdown index 64d3988c6..ba514728a 100644 --- a/Longest Common Subsequence/README.markdown +++ b/Longest Common Subsequence/README.markdown @@ -18,9 +18,9 @@ To determine the length of the LCS between all combinations of substrings of `a` > **Note:** During the following explanation, `n` is the length of string `a`, and `m` is the length of string `b`. -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]`. +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]`. -Given strings `"ABCBX"` and `"ABDCAB"`, the output matrix of `lcsLength()` is the following: +Given strings `"ABCBX"` and `"ABDCAB"`, the output matrix of `lcsLength(_:)` is the following: ``` | | Ø | A | B | D | C | A | B | @@ -34,16 +34,15 @@ Given strings `"ABCBX"` and `"ABDCAB"`, the output matrix of `lcsLength()` is th 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.) -Here is the source code for `lcsLength()`; this lives in an extension on `String`: +Here is the source code for `lcsLength(_:)`; this lives in an extension on `String`: ```swift -func lcsLength(other: String) -> [[Int]] { +func lcsLength(_ other: String) -> [[Int]] { - var matrix = [[Int]](count: self.characters.count+1, - repeatedValue: [Int](count: other.characters.count+1, repeatedValue: 0)) + var matrix = [[Int]](repeating: [Int](repeating: 0, count: other.characters.count+1), count: self.characters.count+1) - for (i, selfChar) in self.characters.enumerate() { - for (j, otherChar) in other.characters.enumerate() { + for (i, selfChar) in self.characters.enumerated() { + for (j, otherChar) in other.characters.enumerated() { if otherChar == selfChar { // Common char found, add 1 to highest lcs found so far. 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` | X | 0 | | | | | | | ``` -And so on... this is how `lcsLength()` fills in the entire matrix. +And so on... this is how `lcsLength(_:)` fills in the entire matrix. ## Backtracking to find the actual subsequence @@ -125,7 +124,7 @@ One thing to notice is, as it's running backwards, the LCS is built in reverse o Here is the backtracking code: ```swift -func backtrack(matrix: [[Int]]) -> String { +func backtrack(_ matrix: [[Int]]) -> String { var i = self.characters.count var j = other.characters.count @@ -141,14 +140,14 @@ func backtrack(matrix: [[Int]]) -> String { // Indicates propagation without change: no new char was added to lcs. else if matrix[i][j] == matrix[i - 1][j] { i -= 1 - charInSequence = charInSequence.predecessor() + charInSequence = self.index(before: charInSequence) } // Value on the left and above are different than current cell. // This means 1 was added to lcs length. else { i -= 1 j -= 1 - charInSequence = charInSequence.predecessor() + charInSequence = self.index(before: charInSequence) lcs.append(self[charInSequence]) } } @@ -165,17 +164,17 @@ Due to backtracking, characters are added in reverse order, so at the end of the ## Putting it all together -To find the LCS between two strings, we first call `lcsLength()` and then `backtrack()`: +To find the LCS between two strings, we first call `lcsLength(_:)` and then `backtrack(_:)`: ```swift extension String { - public func longestCommonSubsequence(other: String) -> String { + public func longestCommonSubsequence(_ other: String) -> String { - func lcsLength(other: String) -> [[Int]] { + func lcsLength(_ other: String) -> [[Int]] { ... } - func backtrack(matrix: [[Int]]) -> String { + func backtrack(_ matrix: [[Int]]) -> String { ... } diff --git a/Longest Common Subsequence/Tests/Tests.xcodeproj/project.pbxproj b/Longest Common Subsequence/Tests/Tests.xcodeproj/project.pbxproj index abf3084dd..bf9c18fd3 100644 --- a/Longest Common Subsequence/Tests/Tests.xcodeproj/project.pbxproj +++ b/Longest Common Subsequence/Tests/Tests.xcodeproj/project.pbxproj @@ -82,7 +82,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; - LastUpgradeCheck = 0720; + LastUpgradeCheck = 0800; TargetAttributes = { 4716C7A61C93750500F6C1C0 = { CreatedOnToolsVersion = 7.2.1; @@ -132,12 +132,49 @@ 4716C7861C936DCB00F6C1C0 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + ONLY_ACTIVE_ARCH = YES; }; name = Debug; }; 4716C7871C936DCB00F6C1C0 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; }; name = Release; }; @@ -187,6 +224,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -228,6 +266,7 @@ PRODUCT_BUNDLE_IDENTIFIER = me.pedrovereza.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = macosx; + SWIFT_VERSION = 3.0; }; name = Release; }; diff --git a/Longest Common Subsequence/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Longest Common Subsequence/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme index 3d7f342b3..0b0682c43 100644 --- a/Longest Common Subsequence/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme +++ b/Longest Common Subsequence/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -1,6 +1,6 @@ Date: Wed, 28 Sep 2016 14:14:24 +0200 Subject: [PATCH 0575/1679] added Z-Algorithm README --- Z-Algorithm/README.markdown | 176 ++++++++++++++++++++++++++++++++++++ 1 file changed, 176 insertions(+) create mode 100644 Z-Algorithm/README.markdown diff --git a/Z-Algorithm/README.markdown b/Z-Algorithm/README.markdown new file mode 100644 index 000000000..7fbb9b48b --- /dev/null +++ b/Z-Algorithm/README.markdown @@ -0,0 +1,176 @@ +# Z-Algorithm String Search + +Goal: Write a simple linear-time string matching algorithm in Swift that returns the indexes of all the occurrencies of a given pattern. + +In other words, we want to implement an `indexesOf(pattern: String)` extension on `String` that returns an array `[Int]` of integers, representing all occurrences' indexes of the search pattern, or `nil` if the pattern could not be found inside the string. + +For example: + +```swift +let str = "Hello, playground!" +str.indexesOf(pattern: "ground") // Output: [11] + +let traffic = "🚗🚙🚌🚕🚑🚐🚗🚒🚚🚎🚛🚐🏎🚜🚗🏍🚒🚲🚕🚓🚌🚑" +traffic.indexesOf(pattern: "🚑") // Output: [4, 21] +``` + +Many string search algorithms use a pre-processing function to compute a table that will be used in successive stage. This table can save some time during the pattern search stage because it allows to avoid un-needed characters comparisons. The [Z-Algorithm]() is one of these functions. It borns as a pattern pre-processing function (this is its role in the [Knuth-Morris-Pratt algorithm](../Knuth-Morris-Pratt/) and others) but, just like we will show here, it can be used also as a single string search algorithm. + +### Z-Algorithm as pattern pre-processor + +As we said, the Z-Algorithm is foremost an algorithm that process a pattern in order to calculate a skip-comparisons-table. +The computation of the Z-Algorithm over a pattern `P` produces an array (called `Z` in the literature) of integers in which each element, call it `Z[i]`, represents the length of the longest substring of `P` that starts at `i` and matches a prefix of `P`. In simpler words, `Z[i]` records the longest prefix of `P[i...|P|]` that matches a prefix of `P`. As an example, let's consider `P = "ffgtrhghhffgtggfredg"`. We have that `Z[5] = 0 (f...h...)`, `Z[9] = 4 (ffgtr...ffgtg...)` and `Z[15] = 1 (ff...fr...)`. + +But how do we compute `Z`? Before we describe the algorithm we must indroduce the concept of Z-box. A Z-box is a pair `(left, right)` used during the computation that records the substring of maximal length that occurs also as a prefix of `P`. The two indices `left` and `right` represent, respectively, the left-end index and the right-end index of this substring. +The definition of the Z-Algorithm is inductive and it computes the elements of the array for every position `k` in the pattern, starting from `k = 1`. The following values (`Z[k + 1]`, `Z[k + 2]`, ...) are computed after `Z[k]`. The idea behind the algorithm is that previously computed values can speed up the calculus of `Z[k + 1]`, avoiding some character comparisons that were already done before. Consider this example: suppose we are at iteration `k = 100`, so we are analyzing position `100` of the pattern. All the values between `Z[1]` and `Z[99]` were correctly computed and `left = 70` and `right = 120`. This means that there is a substring of length `51` starting at position `70` and ending at position `120` that matches the prefix of the pattern/string we are considering. Reasoning on it a little bit we can say that the substring of length `21` starting at position `100` matches the substring of length `21` starting at position `30` of the pattern (because we are inside a substring that matches a prefix of the pattern). So we can use `Z[30]` to compute `Z[100]` without additional character comparisons. +This a simple description of the idea that is behind this algorithm. There are a few cases to manage when the use of pre-computed values cannot be directly applied and some comparisons are to be made. + +Here is the code of the function that computes the Z-array: +``` +swift +func ZetaAlgorithm(ptrn: String) -> [Int]? { + + let pattern = Array(ptrn.characters) + let patternLength: Int = pattern.count + + guard patternLength > 0 else { + return nil + } + + var zeta: [Int] = [Int](repeating: 0, count: patternLength) + + var left: Int = 0 + var right: Int = 0 + var k_1: Int = 0 + var betaLength: Int = 0 + var textIndex: Int = 0 + var patternIndex: Int = 0 + + for k in 1 ..< patternLength { + if k > right { // Outside a Z-box: compare the characters until mismatch + patternIndex = 0 + + while k + patternIndex < patternLength && + pattern[k + patternIndex] == pattern[patternIndex] { + patternIndex = patternIndex + 1 + } + + zeta[k] = patternIndex + + if zeta[k] > 0 { + left = k + right = k + zeta[k] - 1 + } + } else { // Inside a Z-box + k_1 = k - left + 1 + betaLength = right - k + 1 + + if zeta[k_1 - 1] < betaLength { // Entirely inside a Z-box: we can use the values computed before + zeta[k] = zeta[k_1 - 1] + } else if zeta[k_1 - 1] >= betaLength { // Not entirely inside a Z-box: we must proceed with comparisons too + textIndex = betaLength + patternIndex = right + 1 + + while patternIndex < patternLength && pattern[textIndex] == pattern[patternIndex] { + textIndex = textIndex + 1 + patternIndex = patternIndex + 1 + } + + zeta[k] = patternIndex - k + left = k + right = patternIndex - 1 + } + } + } + return zeta +} +``` + +Let's make an example reasoning with the code above. Let's consider the string `P = “abababab"`. The algorithm begins with `k = 1`, `left = right = 0`. So, no Z-box is "active" and thus, because `k > right` we start with the character comparisons beetwen `P[1]` and `P[0]`. + + + 01234567 + k: x + abababbb + x + Z: 00000000 + left: 0 + right: 0 + +We have a mismatch at the first comparison and so the substring starting at `P[1]` does not match a prefix of `P`. So, we put `Z[1] = 0` and let `left` and `right` untouched. We begin another iteration with `k = 2`, we have `2 > 0` and again we start comparing characters `P[2]` with `P[0]`. This time the characters match and so we continue the comparisons until a mismatch occurs. It happens at position `6`. The characters matched are `4`, so we put `Z[2] = 4` and set `left = k = 2` and `right = k + Z[k] - 1 = 5`. We have our first Z-box that is the substring `"abab"` (notice that it matches a prefix of `P`) starting at position `left = 2`. + + 01234567 + k: x + abababbb + x + Z: 00400000 + left: 2 + right: 5 + +We then proceed with `k = 3`. We have `3 <= 5`. We are inside the Z-box previously found and inside a prefix of `P`. So we can look for a position that has a previously computed value. We calculate `k_1 = k - left = 1` that is the index of the prefix's character equal to `P[k]`. We check `Z[1] = 0` and `0 < (right - k + 1 = 3)` and we find that we are exactly inside the Z-box. We can use the previously computed value, so we put `Z[3] = Z[1] = 0`, `left` and `right` remain unchanged. +At iteration `k = 4` we initially execute the `else` branch of the outer `if`. Then in the inner `if` we have that `k_1 = 2` and `(Z[2] = 4) >= 5 - 4 + 1`. So, the substring `P[k...r]` matches for `right - k + 1 = 2` chars the prefix of `P` but it could not for the following characters. We must then compare the characters starting at `r + 1 = 6` with those starting at `right - k + 1 = 2`. We have `P[6] != P[2]` and so we have to set `Z[k] = 6 - 4 = 2`, `left = 4` and `right = 5`. + + 01234567 + k: x + abababbb + x + Z: 00402000 + left: 4 + right: 5 + +With iteration `k = 5` we have `k <= right` and then `(Z[k_1] = 0) < (right - k + 1 = 1)` and so we set `z[k] = 0`. In iteration `6` and `7` we execute the first branch of the outer `if` but we only have mismatches, so the algorithms terminates returning the Z-array as `Z = [0, 0, 4, 0, 2, 0, 0, 0]`. + +The Z-Algorithm runs in linear time. More specifically, the Z-Algorithm for a string `P` of size `n` has a running time of `O(n)`. + +The implementation of Z-Algorithm as string pre-processor is contained in the [ZAlgorithm.swift](./ZAlgorithm.swift) file. + +### Z-Algorithm as string search algorithm + +The Z-Algorithm discussed above leads to the simplest linear-time string matching algorithm. To obtain it, we have to simply concatenate the pattern `P` and text `T` in a string `S = P$T` where `$` is a character that does not appear neither in `P` nor `T`. Then we run the algorithm on `S` obtaining the Z-array. All we have to do now is scan the Z-array looking for elements equal to `n` (which is the pattern length). When we find such value we can report an occurrence. + +```swift +extension String { + + func indexesOf(pattern: String) -> [Int]? { + let patternLength: Int = pattern.characters.count + /* Let's calculate the Z-Algorithm on the concatenation of pattern and text */ + let zeta = ZetaAlgorithm(ptrn: pattern + "💲" + self) + + guard zeta != nil else { + return nil + } + + var indexes: [Int] = [Int]() + + /* Scan the zeta array to find matched patterns */ + for i in 0 ..< zeta!.count { + if zeta![i] == patternLength { + indexes.append(i - patternLength - 1) + } + } + + guard !indexes.isEmpty else { + return nil + } + + return indexes + } +} +``` + +Let's make an example. Let `P = “CATA“` and `T = "GAGAACATACATGACCAT"` be the pattern and the text. Let's concatenate them with the character `$`. We have the string `S = "CATA$GAGAACATACATGACCAT"`. After computing the Z-Algorithm on `S` we obtain: + + 1 2 + 01234567890123456789012 + CATA$GAGAACATACATGACCAT + Z 00000000004000300001300 + ^ + +We scan the Z-array and at position `10` we find `Z[10] = 4 = n`. So we can report a match occuring at text position `10 - n - 1 = 5`. + +As said before, the complexity of this algorithm is linear. Defining `n` and `m` as pattern and text lengths, the final complexity we obtain is `O(n + m + 1) = O(n + m)`. + + +Credits: This code is based on the handbook ["Algorithm on String, Trees and Sequences: Computer Science and Computational Biology"]() by Dan Gusfield, Cambridge University Press, 1997. + +*Written for Swift Algorithm Club by Matteo Dunnhofer* From 41712e0275fbc50e63f32580d402ca12d1648888 Mon Sep 17 00:00:00 2001 From: dontfollowmeimcrazy Date: Wed, 28 Sep 2016 14:20:58 +0200 Subject: [PATCH 0576/1679] edited Z-Algorithm README --- Z-Algorithm/README.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Z-Algorithm/README.markdown b/Z-Algorithm/README.markdown index 7fbb9b48b..c6c50a23b 100644 --- a/Z-Algorithm/README.markdown +++ b/Z-Algorithm/README.markdown @@ -86,7 +86,7 @@ func ZetaAlgorithm(ptrn: String) -> [Int]? { } ``` -Let's make an example reasoning with the code above. Let's consider the string `P = “abababab"`. The algorithm begins with `k = 1`, `left = right = 0`. So, no Z-box is "active" and thus, because `k > right` we start with the character comparisons beetwen `P[1]` and `P[0]`. +Let's make an example reasoning with the code above. Let's consider the string `P = “abababbb"`. The algorithm begins with `k = 1`, `left = right = 0`. So, no Z-box is "active" and thus, because `k > right` we start with the character comparisons beetwen `P[1]` and `P[0]`. 01234567 @@ -171,6 +171,6 @@ We scan the Z-array and at position `10` we find `Z[10] = 4 = n`. So we can repo As said before, the complexity of this algorithm is linear. Defining `n` and `m` as pattern and text lengths, the final complexity we obtain is `O(n + m + 1) = O(n + m)`. -Credits: This code is based on the handbook ["Algorithm on String, Trees and Sequences: Computer Science and Computational Biology"]() by Dan Gusfield, Cambridge University Press, 1997. +Credits: This code is based on the handbook ["Algorithm on String, Trees and Sequences: Computer Science and Computational Biology"](https://books.google.it/books/about/Algorithms_on_Strings_Trees_and_Sequence.html?id=Ofw5w1yuD8kC&redir_esc=y) by Dan Gusfield, Cambridge University Press, 1997. *Written for Swift Algorithm Club by Matteo Dunnhofer* From 72ee49b05218ce4ca627caabaa9b2960154a9dde Mon Sep 17 00:00:00 2001 From: dontfollowmeimcrazy Date: Wed, 28 Sep 2016 16:32:15 +0200 Subject: [PATCH 0577/1679] edited Z-Algorithm README --- Z-Algorithm/README.markdown | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Z-Algorithm/README.markdown b/Z-Algorithm/README.markdown index c6c50a23b..8b84c28bf 100644 --- a/Z-Algorithm/README.markdown +++ b/Z-Algorithm/README.markdown @@ -26,8 +26,7 @@ The definition of the Z-Algorithm is inductive and it computes the elements of t This a simple description of the idea that is behind this algorithm. There are a few cases to manage when the use of pre-computed values cannot be directly applied and some comparisons are to be made. Here is the code of the function that computes the Z-array: -``` -swift +```swift func ZetaAlgorithm(ptrn: String) -> [Int]? { let pattern = Array(ptrn.characters) From 69758422a5fade80fda9c550818ad0056dc0634b Mon Sep 17 00:00:00 2001 From: Richard Date: Wed, 28 Sep 2016 16:49:22 -0700 Subject: [PATCH 0578/1679] Fixed a typo in the Karatsuba algorithm --- .../KaratsubaMultiplication.playground/Contents.swift | 4 ++-- Karatsuba Multiplication/KaratsubaMultiplication.swift | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Karatsuba Multiplication/KaratsubaMultiplication.playground/Contents.swift b/Karatsuba Multiplication/KaratsubaMultiplication.playground/Contents.swift index 53980ac1e..95a498322 100644 --- a/Karatsuba Multiplication/KaratsubaMultiplication.playground/Contents.swift +++ b/Karatsuba Multiplication/KaratsubaMultiplication.playground/Contents.swift @@ -52,9 +52,9 @@ func karatsuba(_ num1: Int, by num2: Int) -> Int { let ac = karatsuba(a, by: c) let bd = karatsuba(b, by: d) - let adPluscd = karatsuba(a+b, by: c+d) - ac - bd + let adPlusbc = karatsuba(a+b, by: c+d) - ac - bd - let product = ac * 10^^(2 * nBy2) + adPluscd * 10^^nBy2 + bd + let product = ac * 10^^(2 * nBy2) + adPlusbc * 10^^nBy2 + bd return product } diff --git a/Karatsuba Multiplication/KaratsubaMultiplication.swift b/Karatsuba Multiplication/KaratsubaMultiplication.swift index 7837e3f3c..fb20a667d 100644 --- a/Karatsuba Multiplication/KaratsubaMultiplication.swift +++ b/Karatsuba Multiplication/KaratsubaMultiplication.swift @@ -37,9 +37,9 @@ func karatsuba(_ num1: Int, by num2: Int) -> Int { let ac = karatsuba(a, by: c) let bd = karatsuba(b, by: d) - let adPluscd = karatsuba(a+b, by: c+d) - ac - bd + let adPlusbc = karatsuba(a+b, by: c+d) - ac - bd - let product = ac * 10^^(2 * nBy2) + adPluscd * 10^^nBy2 + bd + let product = ac * 10^^(2 * nBy2) + adPlusbc * 10^^nBy2 + bd return product } From ab2949e77658260df2153e95f32f525bff68b785 Mon Sep 17 00:00:00 2001 From: Richard Date: Wed, 28 Sep 2016 16:50:12 -0700 Subject: [PATCH 0579/1679] Added an explanation and examples to the README --- Karatsuba Multiplication/README.markdown | 123 ++++++++++++++++++++++- 1 file changed, 122 insertions(+), 1 deletion(-) diff --git a/Karatsuba Multiplication/README.markdown b/Karatsuba Multiplication/README.markdown index 0afd91b0c..af3392612 100644 --- a/Karatsuba Multiplication/README.markdown +++ b/Karatsuba Multiplication/README.markdown @@ -1,8 +1,129 @@ # Karatsuba Multiplication -TODO: Explanation/Examples +Goal: To quickly multiply two numbers together +## Long Multiplication +In grade school we all learned how to multiply two numbers together via Long Multiplication. So let's try that first! +Example 1: Multiply 1234 by 5678 using Long Multiplication + + 5678 + *1234 + ------ + 22712 + 17034- + 11356-- + 5678--- + -------- + 7006652 + +So what's the problem with long multiplication? Speed. Long Multiplication runs in **O(n^2)**. + +You can see where the **O(n^2)** comes from in the implementation for Long Multiplication: + +```swift +// Long Multiplication +func multiply(_ num1: Int, by num2: Int, base: Int = 10) -> Int { + let num1Array = String(num1).characters.reversed().map{ Int(String($0))! } + let num2Array = String(num2).characters.reversed().map{ Int(String($0))! } + + var product = Array(repeating: 0, count: num1Array.count + num2Array.count) + + for i in num1Array.indices { + var carry = 0 + for j in num2Array.indices { + product[i + j] += carry + num1Array[i] * num2Array[j] + carry = product[i + j] / base + product[i + j] %= base + } + product[i + num2Array.count] += carry + } + + return Int(product.reversed().map{ String($0) }.reduce("", +))! +} +``` + +The double for loop is the culprit! So Long Multiplication might not be the best algorithm after all. Can we do better? + +## Karatsuba Multiplication + +The Karatsuba Algorithm was discovered by Anatoly Karatsuba and published in 1962. Karatsuba discovered that you could compute the product of two large numbers using three smaller products and some addition and subtraction. + +For two numbers x, y, where m <= n: + + x = a*10^m + b + y = c*10^m + d + +Now, we can say: + + x*y = a*c*10^(2m) + (a*d + b*c)*10^(m) + b*d + +We can compute this function recursively, and that's what makes Karatsuba Multiplication fast. + +```swift +let ac = karatsuba(a, by: c) +let bd = karatsuba(b, by: d) +let adPlusbc = karatsuba(a+b, by: c+d) - ac - bd +``` + +The last recursion is interesting. Normally, you'd think we would have to run four recursions to find the product `x*y` (`a*c`, `a*d`, `b*c`, `b*d`). However, Karatsuba realized that you only need three recursions, and some addition and subtraction. Here's the math: + + (a+b)*(c+d) - a*c - b*c = (a*c + a*d + b*c + b*d) - a*c - b*c + = (a*d + b*c) + +Pretty cool, huh? + +Here's the full implementation + +```swift +// Karatsuba Multiplication +func karatsuba(_ num1: Int, by num2: Int) -> Int { + let num1Array = String(num1).characters + let num2Array = String(num2).characters + + guard num1Array.count > 1 && num2Array.count > 1 else { + return num1*num2 + } + + let n = max(num1Array.count, num2Array.count) + let nBy2 = n / 2 + + let a = num1 / 10^^nBy2 + let b = num1 % 10^^nBy2 + let c = num2 / 10^^nBy2 + let d = num2 % 10^^nBy2 + + let ac = karatsuba(a, by: c) + let bd = karatsuba(b, by: d) + let adPlusbc = karatsuba(a+b, by: c+d) - ac - bd + + let product = ac * 10^^(2 * nBy2) + adPlusbc * 10^^nBy2 + bd + + return product +} +``` + +The run time for this algorithm is about **O(n^1.56)** which is better than the **O(n^2)** for Long Multiplication. + +Example 2: Multiply 1234 by 5678 using Karatsuba Multiplication + + m = 2 + x = 1234 = a*10^2 + b = 12*10^2 + 34 + y = 5678 = c*10^2 + d = 56*10^2 + 78 + + a*c = 672 + b*d = 2652 + (a*d + b*c) = 2840 + + x*y = 672*10^4 + 2840*10^2 + 2652 + = 6720000 + 284000 + 2652 + = 7006652 + +## Resources + +[Wikipedia] (https://en.wikipedia.org/wiki/Karatsuba_algorithm) + +[WolframMathWorld] (http://mathworld.wolfram.com/KaratsubaMultiplication.html) *Written for Swift Algorithm Club by Richard Ash* From b8ea4fd9b63ac20c3ae521d3a1ff018500a587d3 Mon Sep 17 00:00:00 2001 From: dontfollowmeimcrazy Date: Sat, 1 Oct 2016 23:02:12 +0200 Subject: [PATCH 0580/1679] added Knuth-Morris-Pratt README --- Knuth-Morris-Pratt/README.markdown | 157 +++++++++++++++++++++++++++++ 1 file changed, 157 insertions(+) create mode 100644 Knuth-Morris-Pratt/README.markdown diff --git a/Knuth-Morris-Pratt/README.markdown b/Knuth-Morris-Pratt/README.markdown new file mode 100644 index 000000000..ab8e78cdc --- /dev/null +++ b/Knuth-Morris-Pratt/README.markdown @@ -0,0 +1,157 @@ +# Knuth-Morris-Pratt String Search + +Goal: Write a linear-time string matching algorithm in Swift that returns the indexes of all the occurrencies of a given pattern. + +In other words, we want to implement an `indexesOf(pattern: String)` extension on `String` that returns an array `[Int]` of integers, representing all occurrences' indexes of the search pattern, or `nil` if the pattern could not be found inside the string. + +For example: + +```swift +let dna = "ACCCGGTTTTAAAGAACCACCATAAGATATAGACAGATATAGGACAGATATAGAGACAAAACCCCATACCCCAATATTTTTTTGGGGAGAAAAACACCACAGATAGATACACAGACTACACGAGATACGACATACAGCAGCATAACGACAACAGCAGATAGACGATCATAACAGCAATCAGACCGAGCGCAGCAGCTTTTAAGCACCAGCCCCACAAAAAACGACAATFATCATCATATACAGACGACGACACGACATATCACACGACAGCATA" +dna.indexesOf(ptnr: "CATA") // Output: [20, 64, 130, 140, 166, 234, 255, 270] + +let concert = "🎼🎹🎹🎸🎸🎻🎻🎷🎺🎤👏👏👏" +concert.indexesOf(ptnr: "🎻🎷") // Output: [6] +``` + +The [Knuth-Morris-Pratt algorithm](https://en.wikipedia.org/wiki/Knuth–Morris–Pratt_algorithm) is considered one of the best algorithms for solving the pattern matching problem. Although in practice [Boyer-Moore](../Boyer-Moore/) is usually preferred, the algorithm that we will introduce is simpler, and has the same (linear) running time. + +The idea behind the algorithm is not too different from the [naive string search](../Brute-Force String Search/) procedure. As it, Knuth-Morris-Pratt aligns the text with the pattern and goes with character comparisons from left to right. But, instead of making a shift of one character when a mismatch occurs, it uses a more intelligent way to move the pattern along the text. In fact, the algorithm features a pattern pre-processing stage where it acquires all the informations that will make the algorithm skip redundant comparisons, resulting in larger shifts. + +The pre-processing stage produces an array (called `suffixPrefix` in the code) of integers in which every element `suffixPrefix[i]` records the length of the longest proper suffix of `P[0...i]` (where `P` is the pattern) that matches a prefix of `P`. In other words, `suffixPrefix[i]` is the longest proper substring of `P` that ends at position `i` and that is a prefix of `P`. Just a quick example. Consider `P = "abadfryaabsabadffg", then `suffixPrefix[4] = 0`, `suffixPrefix[9] = 2`, `suffixPrefix[14] = 4`. +There are different ways to obtain the values of `SuffixPrefix` array. We will use the method based on the [Z-Algorithm](../Z-Algorithm/). This function takes in input the pattern and produces an array of integers. Each element represents the length of the longest substring starting at position `i` of `P` and that matches a prefix of `P`. You can notice that the two arrays are similar, they record the same informations but on the different places. We only have to find a method to map `Z[i]` to `suffixPrefix[j]`. It is not that difficult and this is the code that will do for us: + +```swift +for patternIndex in (1 ..< patternLength).reversed() { + textIndex = patternIndex + zeta![patternIndex] - 1 + suffixPrefix[textIndex] = zeta![patternIndex] +} +``` + +We are simply computing the index of the end of the substring starting at position `i` (as we know matches a prefix of `P`). The element of `suffixPrefix` at that index then it will be set with the length of the substring. + +Once the shift-array `suffixPrefix` is ready we can begin with pattern search stage. The algorithm first attempts to compare the characters of the text with those of the pattern. If it succeeds, it goes on until a mismatch occurs. When it happens, it checks if an occurrence of the pattern is present (and reports it). Otherwise, if no comparisons are made then the text cursor is moved forward, else the pattern is shifted to the right. The shift's amount is based on the `suffixPrefix` array, and it guarantees that the prefix `P[0...suffixPrefix[i]]` will match its opposing substring in the text. In this way, shifts of more than one character are often made and lot of comparisons can be avoided, saving a lot of time. + +Here is the code of the Knuth-Morris-Pratt algorithm: + +```swift +extension String { + + func indexesOf(ptnr: String) -> [Int]? { + + let text = Array(self.characters) + let pattern = Array(ptnr.characters) + + let textLength: Int = text.count + let patternLength: Int = pattern.count + + guard patternLength > 0 else { + return nil + } + + var suffixPrefix: [Int] = [Int](repeating: 0, count: patternLength) + var textIndex: Int = 0 + var patternIndex: Int = 0 + var indexes: [Int] = [Int]() + + /* Pre-processing stage: computing the table for the shifts (through Z-Algorithm) */ + let zeta = ZetaAlgorithm(ptnr: ptnr) + + for patternIndex in (1 ..< patternLength).reversed() { + textIndex = patternIndex + zeta![patternIndex] - 1 + suffixPrefix[textIndex] = zeta![patternIndex] + } + + /* Search stage: scanning the text for pattern matching */ + textIndex = 0 + patternIndex = 0 + + while textIndex + (patternLength - patternIndex - 1) < textLength { + + while patternIndex < patternLength && text[textIndex] == pattern[patternIndex] { + textIndex = textIndex + 1 + patternIndex = patternIndex + 1 + } + + if patternIndex == patternLength { + indexes.append(textIndex - patternIndex) + } + + if patternIndex == 0 { + textIndex = textIndex + 1 + } else { + patternIndex = suffixPrefix[patternIndex - 1] + } + } + + guard !indexes.isEmpty else { + return nil + } + return indexes + } +} +``` + +Let's make an example reasoning with the code above. Let's consider the string `P = ACTGACTA"`, the consequentially obtained `suffixPrefix` array equal to `[0, 0, 0, 0, 0, 0, 3, 1]`, and the text `T = "GCACTGACTGACTGACTAG"`. The algorithm begins with the text and the pattern aligned like below. We have to compare `T[0]` with `P[0]`. + + 1 + 0123456789012345678 + text: GCACTGACTGACTGACTAG + textIndex: ^ + pattern: ACTGACTA + patternIndex: ^ + x + suffixPrefix: 00000031 + +We have a mismatch and we move on comparing `T[1]` and `P[0]`. We have to check if a pattern occurrence is present but there is not. So, we have to shift the pattern right and by doing so we have to check `suffixPrefix[1 - 1]`. Its value is `0` and we restart by comparing `T[1]` with `P[0]`. Again a mismath occurs, so we go on with `T[2]` and `P[0]`. + + 1 + 0123456789012345678 + text: GCACTGACTGACTGACTAG + textIndex: ^ + pattern: ACTGACTA + patternIndex: ^ + suffixPrefix: 00000031 + +This time we have a match. And it continues until position `8`. Unfortunately the length of the match is not equal to the pattern length, we cannot report an occurrence. But we are still lucky because we can use the values computed in the `suffixPrefix` array now. In fact, the length of the match is `7`, and if we look at the element `suffixPrefix[7 - 1]` we discover that is `3`. This information tell us that that the prefix of `P` matches the suffix of the susbtring `T[0...8]`. So the `suffixPrefix` array guarantees us that the two substring match and that we do not have to compare their characters, so we can shift right the pattern for more than one character! +The comparisons restart from `T[9]` and `P[3]`. + + 1 + 0123456789012345678 + text: GCACTGACTGACTGACTAG + textIndex: ^ + pattern: ACTGACTA + patternIndex: ^ + suffixPrefix: 00000031 + +They match so we continue the compares until position `13` where a misatch occurs beetwen charcter `G` and `A`. Just like before, we are lucky and we can use the `suffixPrefix` array to shift right the pattern. + + 1 + 0123456789012345678 + text: GCACTGACTGACTGACTAG + textIndex: ^ + pattern: ACTGACTA + patternIndex: ^ + suffixPrefix: 00000031 + +Again, we have to compare. But this time the comparisons finally take us to an occurrence, at position `17 - 7 = 10`. + + 1 + 0123456789012345678 + text: GCACTGACTGACTGACTAG + textIndex: ^ + pattern: ACTGACTA + patternIndex: ^ + suffixPrefix: 00000031 + +The algorithm than tries to compare `T[18]` with `P[1]` (because we used the element `suffixPrefix[8 - 1] = 1`) but it fails and at the next iteration it ends its work. + + +The pre-processing stage involves only the pattern. The running time of the Z-Algorithm is linear and takes `O(n)`, where `n` is the length of the pattern `P`. After that, the search stage does not "overshoot" the length of the text `T` (call it `m`). It can be be proved that number of comparisons of the search stage is bounded by `2 * m`. The final running time of the Knuth-Morris-Pratt algorithm is `O(n + m)`. + + +> **Note:** To execute the code in the [KnuthMorrisPratt.swift](./KnuthMorrisPratt.swift) you have to copy the [ZAlgorithm.swift](../Z-Algorithm/ZAlgorithm.swift) file contained in the [Z-Algorithm](../Z-Algorithm/) folder. The [KnuthMorrisPratt.playground](./KnuthMorrisPratt.playground) already includes the definition of the `Zeta` function. + +Credits: This code is based on the handbook ["Algorithm on String, Trees and Sequences: Computer Science and Computational Biology"](https://books.google.it/books/about/Algorithms_on_Strings_Trees_and_Sequence.html?id=Ofw5w1yuD8kC&redir_esc=y) by Dan Gusfield, Cambridge University Press, 1997. + +*Written for Swift Algorithm Club by Matteo Dunnhofer* From 5423763065c6844d2c573b76435623662670b947 Mon Sep 17 00:00:00 2001 From: dontfollowmeimcrazy Date: Sat, 1 Oct 2016 23:05:50 +0200 Subject: [PATCH 0581/1679] edited Knuth-Morris-Pratt README --- Knuth-Morris-Pratt/README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Knuth-Morris-Pratt/README.markdown b/Knuth-Morris-Pratt/README.markdown index ab8e78cdc..f01b87b3d 100644 --- a/Knuth-Morris-Pratt/README.markdown +++ b/Knuth-Morris-Pratt/README.markdown @@ -18,7 +18,7 @@ The [Knuth-Morris-Pratt algorithm](https://en.wikipedia.org/wiki/Knuth–Morris The idea behind the algorithm is not too different from the [naive string search](../Brute-Force String Search/) procedure. As it, Knuth-Morris-Pratt aligns the text with the pattern and goes with character comparisons from left to right. But, instead of making a shift of one character when a mismatch occurs, it uses a more intelligent way to move the pattern along the text. In fact, the algorithm features a pattern pre-processing stage where it acquires all the informations that will make the algorithm skip redundant comparisons, resulting in larger shifts. -The pre-processing stage produces an array (called `suffixPrefix` in the code) of integers in which every element `suffixPrefix[i]` records the length of the longest proper suffix of `P[0...i]` (where `P` is the pattern) that matches a prefix of `P`. In other words, `suffixPrefix[i]` is the longest proper substring of `P` that ends at position `i` and that is a prefix of `P`. Just a quick example. Consider `P = "abadfryaabsabadffg", then `suffixPrefix[4] = 0`, `suffixPrefix[9] = 2`, `suffixPrefix[14] = 4`. +The pre-processing stage produces an array (called `suffixPrefix` in the code) of integers in which every element `suffixPrefix[i]` records the length of the longest proper suffix of `P[0...i]` (where `P` is the pattern) that matches a prefix of `P`. In other words, `suffixPrefix[i]` is the longest proper substring of `P` that ends at position `i` and that is a prefix of `P`. Just a quick example. Consider `P = "abadfryaabsabadffg"`, then `suffixPrefix[4] = 0`, `suffixPrefix[9] = 2`, `suffixPrefix[14] = 4`. There are different ways to obtain the values of `SuffixPrefix` array. We will use the method based on the [Z-Algorithm](../Z-Algorithm/). This function takes in input the pattern and produces an array of integers. Each element represents the length of the longest substring starting at position `i` of `P` and that matches a prefix of `P`. You can notice that the two arrays are similar, they record the same informations but on the different places. We only have to find a method to map `Z[i]` to `suffixPrefix[j]`. It is not that difficult and this is the code that will do for us: ```swift From f4dc41feb8b66fe9c02d78627d2caafd3bd4f1fa Mon Sep 17 00:00:00 2001 From: Kevin Taniguchi Date: Tue, 4 Oct 2016 22:21:13 -0500 Subject: [PATCH 0582/1679] began convert to swift3 --- .../BoyerMoore.playground/Contents.swift | 18 +++++++++--------- .../BoyerMoore.playground/timeline.xctimeline | 6 ------ 2 files changed, 9 insertions(+), 15 deletions(-) delete mode 100644 Boyer-Moore/BoyerMoore.playground/timeline.xctimeline diff --git a/Boyer-Moore/BoyerMoore.playground/Contents.swift b/Boyer-Moore/BoyerMoore.playground/Contents.swift index 433935133..631b0d43a 100644 --- a/Boyer-Moore/BoyerMoore.playground/Contents.swift +++ b/Boyer-Moore/BoyerMoore.playground/Contents.swift @@ -7,20 +7,20 @@ extension String { assert(patternLength <= self.characters.count) var skipTable = [Character: Int]() - for (i, c) in pattern.characters.enumerate() { + for (i, c) in pattern.characters.enumerated() { skipTable[c] = patternLength - i - 1 } - let p = pattern.endIndex.predecessor() + let p = pattern.index(before: endIndex) let lastChar = pattern[p] - var i = self.startIndex.advancedBy(patternLength - 1) + var i = self.index(startIndex, offsetBy: patternLength - 1) func backwards() -> String.Index? { var q = p var j = i while q > pattern.startIndex { - j = j.predecessor() - q = q.predecessor() + j = index(before: j) + q = index(before: q) if self[j] != pattern[q] { return nil } } return j @@ -30,9 +30,9 @@ extension String { let c = self[i] if c == lastChar { if let k = backwards() { return k } - i = i.successor() + i = index(after: i) } else { - i = i.advancedBy(skipTable[c] ?? patternLength) + i = index(i, offsetBy: skipTable[c] ?? patternLength) } } return nil @@ -44,7 +44,7 @@ extension String { // A few simple tests let s = "Hello, World" -s.indexOf("World") // 7 +s.indexOf(pattern: "World") // 7 let animals = "🐶🐔🐷🐮🐱" -animals.indexOf("🐮") // 6 +animals.indexOf(pattern: "🐮") // 6 diff --git a/Boyer-Moore/BoyerMoore.playground/timeline.xctimeline b/Boyer-Moore/BoyerMoore.playground/timeline.xctimeline deleted file mode 100644 index bf468afec..000000000 --- a/Boyer-Moore/BoyerMoore.playground/timeline.xctimeline +++ /dev/null @@ -1,6 +0,0 @@ - - - - - From c79d699b5e31206341ee623b642c7181943e7928 Mon Sep 17 00:00:00 2001 From: Kevin Taniguchi Date: Tue, 4 Oct 2016 22:39:54 -0500 Subject: [PATCH 0583/1679] fixed bug with end index --- .../BoyerMoore.playground/Contents.swift | 6 ++---- .../BoyerMoore.playground/timeline.xctimeline | 21 +++++++++++++++++++ 2 files changed, 23 insertions(+), 4 deletions(-) create mode 100644 Boyer-Moore/BoyerMoore.playground/timeline.xctimeline diff --git a/Boyer-Moore/BoyerMoore.playground/Contents.swift b/Boyer-Moore/BoyerMoore.playground/Contents.swift index 631b0d43a..59cc85b86 100644 --- a/Boyer-Moore/BoyerMoore.playground/Contents.swift +++ b/Boyer-Moore/BoyerMoore.playground/Contents.swift @@ -11,7 +11,7 @@ extension String { skipTable[c] = patternLength - i - 1 } - let p = pattern.index(before: endIndex) + let p = pattern.index(before: pattern.endIndex) let lastChar = pattern[p] var i = self.index(startIndex, offsetBy: patternLength - 1) @@ -39,12 +39,10 @@ extension String { } } - - // A few simple tests let s = "Hello, World" s.indexOf(pattern: "World") // 7 let animals = "🐶🐔🐷🐮🐱" -animals.indexOf(pattern: "🐮") // 6 +//animals.indexOf(pattern: "🐮") // 6 diff --git a/Boyer-Moore/BoyerMoore.playground/timeline.xctimeline b/Boyer-Moore/BoyerMoore.playground/timeline.xctimeline new file mode 100644 index 000000000..623552dab --- /dev/null +++ b/Boyer-Moore/BoyerMoore.playground/timeline.xctimeline @@ -0,0 +1,21 @@ + + + + + + + + + + + From e53faf4fced5aa86e0bfb3f97bc98b1bd76557d2 Mon Sep 17 00:00:00 2001 From: Kevin Taniguchi Date: Tue, 4 Oct 2016 22:53:37 -0500 Subject: [PATCH 0584/1679] uncomment test --- Boyer-Moore/BoyerMoore.playground/Contents.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Boyer-Moore/BoyerMoore.playground/Contents.swift b/Boyer-Moore/BoyerMoore.playground/Contents.swift index 59cc85b86..6203d36e7 100644 --- a/Boyer-Moore/BoyerMoore.playground/Contents.swift +++ b/Boyer-Moore/BoyerMoore.playground/Contents.swift @@ -45,4 +45,4 @@ let s = "Hello, World" s.indexOf(pattern: "World") // 7 let animals = "🐶🐔🐷🐮🐱" -//animals.indexOf(pattern: "🐮") // 6 +animals.indexOf(pattern: "🐮") // 6 From df1cc1e4d16e488ff3ed35d3c0b5b1df3d59d4fe Mon Sep 17 00:00:00 2001 From: Kevin Taniguchi Date: Tue, 4 Oct 2016 22:56:33 -0500 Subject: [PATCH 0585/1679] formatting --- Boyer-Moore/BoyerMoore.playground/Contents.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Boyer-Moore/BoyerMoore.playground/Contents.swift b/Boyer-Moore/BoyerMoore.playground/Contents.swift index 6203d36e7..9a3d619dc 100644 --- a/Boyer-Moore/BoyerMoore.playground/Contents.swift +++ b/Boyer-Moore/BoyerMoore.playground/Contents.swift @@ -30,7 +30,7 @@ extension String { let c = self[i] if c == lastChar { if let k = backwards() { return k } - i = index(after: i) + i = index(after: i) } else { i = index(i, offsetBy: skipTable[c] ?? patternLength) } From 2e9e887c07f42306d80ac1d102e0253ecc1a9f06 Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Wed, 5 Oct 2016 21:40:45 +1300 Subject: [PATCH 0586/1679] LCS - Restoring executeOnSourceChanges to default --- .../LongestCommonSubsequence.playground/contents.xcplayground | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Longest Common Subsequence/LongestCommonSubsequence.playground/contents.xcplayground b/Longest Common Subsequence/LongestCommonSubsequence.playground/contents.xcplayground index 9f5f2f40c..fc5b4ab70 100644 --- a/Longest Common Subsequence/LongestCommonSubsequence.playground/contents.xcplayground +++ b/Longest Common Subsequence/LongestCommonSubsequence.playground/contents.xcplayground @@ -1,4 +1,4 @@ - + - \ No newline at end of file + From bf9ba314510af9a5dd15eaa0eb8d0f1dc789eb60 Mon Sep 17 00:00:00 2001 From: Chris Pilcher Date: Wed, 5 Oct 2016 21:55:24 +1300 Subject: [PATCH 0587/1679] Radix tree re-indent to use two spaces --- Radix Tree/RadixTree.swift | 684 ++++++++++++++++++------------------- 1 file changed, 342 insertions(+), 342 deletions(-) diff --git a/Radix Tree/RadixTree.swift b/Radix Tree/RadixTree.swift index 5badf0810..958ffb4e6 100644 --- a/Radix Tree/RadixTree.swift +++ b/Radix Tree/RadixTree.swift @@ -2,380 +2,380 @@ import Foundation // The root is the top of the Radix Tree public class Root { - var children: [Edge] - - public init() { - children = [Edge]() + var children: [Edge] + + public init() { + children = [Edge]() + } + + // Returns the length (in number of edges) of the longest traversal down the tree. + public func height() -> Int { + // Base case: no children: the tree has a height of 1 + if children.count == 0 { + return 1 } - - // Returns the length (in number of edges) of the longest traversal down the tree. - public func height() -> Int { - // Base case: no children: the tree has a height of 1 - if children.count == 0 { - return 1 - } - // Recursion: find the max height of a root's child and return 1 + that max - else { - var max = 1 - for c in children { - if c.height() > max { - max = c.height() - } - } - return 1 + max + // Recursion: find the max height of a root's child and return 1 + that max + else { + var max = 1 + for c in children { + if c.height() > max { + max = c.height() } + } + return 1 + max } - - // Returns how far down in the tree a Root/Edge is. - // A root's level is always 0. - public func level() -> Int { - return 0 + } + + // Returns how far down in the tree a Root/Edge is. + // A root's level is always 0. + public func level() -> Int { + return 0 + } + + // Prints the tree for debugging/visualization purposes. + public func printRoot() { + // Print the first half of the children + if children.count > 1 { + for c in 0...children.count/2-1 { + children[c].printEdge() + print("|") + } + } else if children.count > 0 { + children[0].printEdge() } - - // Prints the tree for debugging/visualization purposes. - public func printRoot() { - // Print the first half of the children - if children.count > 1 { - for c in 0...children.count/2-1 { - children[c].printEdge() - print("|") - } - } else if children.count > 0 { - children[0].printEdge() - } - // Then print the root - print("ROOT") - // Print the second half of the children - if children.count > 1 { - for c in children.count/2...children.count-1 { - children[c].printEdge() - print("|") - } - } - print() + // Then print the root + print("ROOT") + // Print the second half of the children + if children.count > 1 { + for c in children.count/2...children.count-1 { + children[c].printEdge() + print("|") + } } + print() + } } // Edges are what actually store the Strings in the tree public class Edge: Root { - var parent: Root? - var label: String - - public init(_ label: String) { - self.label = label - super.init() + var parent: Root? + var label: String + + public init(_ label: String) { + self.label = label + super.init() + } + + public override func level() -> Int { + // Recurse up the tree incrementing level by one until the root is reached + if parent != nil { + return 1 + parent!.level() } - - public override func level() -> Int { - // Recurse up the tree incrementing level by one until the root is reached - if parent != nil { - return 1 + parent!.level() - } - // If an edge has no parent, it's level is one - // NOTE: THIS SHOULD NEVER HAPPEN AS THE ROOT IS ALWAYS THE TOP OF THE TREE - else { - return 1 - } + // If an edge has no parent, it's level is one + // NOTE: THIS SHOULD NEVER HAPPEN AS THE ROOT IS ALWAYS THE TOP OF THE TREE + else { + return 1 } - - // Erases a specific edge (and all edges below it in the tree). - public func erase() { - self.parent = nil - if children.count > 0 { - // For each child, erase it, then remove it from the children array. - for _ in 0...children.count-1 { - children[0].erase() - children.remove(at: 0) - } - } + } + + // Erases a specific edge (and all edges below it in the tree). + public func erase() { + self.parent = nil + if children.count > 0 { + // For each child, erase it, then remove it from the children array. + for _ in 0...children.count-1 { + children[0].erase() + children.remove(at: 0) + } } - - // Prints the tree for debugging/visualization purposes. - public func printEdge() { - // Print the first half of the edge's children - if children.count > 1 { - for c in 0...children.count/2-1 { - children[c].printEdge() - } - } else if children.count > 0 { - children[0].printEdge() - } - // Tab over once up to the edge's level - for x in 1...level() { - if x == level() { - print("|------>", terminator: "") - } else { - print("| ", terminator: "") - } + } + + // Prints the tree for debugging/visualization purposes. + public func printEdge() { + // Print the first half of the edge's children + if children.count > 1 { + for c in 0...children.count/2-1 { + children[c].printEdge() + } + } else if children.count > 0 { + children[0].printEdge() + } + // Tab over once up to the edge's level + for x in 1...level() { + if x == level() { + print("|------>", terminator: "") + } else { + print("| ", terminator: "") + } + } + print(label) + // Print the second half of the edge's children + if children.count == 0 { + for _ in 1...level() { + print("| ", terminator: "") + } + print() + } + if children.count > 1 { + for c in children.count/2...children.count-1 { + children[c].printEdge() + } + } + } +} + +public class RadixTree { + var root: Root + + public init() { + root = Root() + } + + // Returns the height of the tree by calling the root's height function. + public func height() -> Int { + return root.height() - 1 + } + + // Inserts a string into the tree. + public func insert(_ str: String) -> Bool { + //Account for a blank input. The empty string is already in the tree. + if str == "" { + return false + } + + // searchStr is the parameter of the function + // it will be substringed as the function traverses down the tree + var searchStr = str + + // currEdge is the current Edge (or Root) in question + var currEdge = root + + while true { + var found = false + + // If the current Edge has no children then the remaining searchStr is + // created as a child + if currEdge.children.count == 0 { + let newEdge = Edge(searchStr) + currEdge.children.append(newEdge) + newEdge.parent = currEdge + return true + } + + // Loop through all of the children + for e in currEdge.children { + // Get the shared prefix between the child in question and the + // search string + let shared = sharedPrefix(searchStr, e.label) + var index = shared.startIndex + + // If the search string is equal to the shared string, + // the string already exists in the tree + if searchStr == shared { + return false } - print(label) - // Print the second half of the edge's children - if children.count == 0 { - for _ in 1...level() { - print("| ", terminator: "") - } - print() + + // If the child's label is equal to the shared string, you have to + // traverse another level down the tree, so substring the search + // string, break the loop, and run it back + else if shared == e.label { + currEdge = e + var tempIndex = searchStr.startIndex + for _ in 1...shared.characters.count { + tempIndex = searchStr.characters.index(after: tempIndex) + } + searchStr = searchStr.substring(from: tempIndex) + found = true + break } - if children.count > 1 { - for c in children.count/2...children.count-1 { - children[c].printEdge() - } + + // If the child's label and the search string share a partial prefix, + // then both the label and the search string need to be substringed + // and a new branch needs to be created + else if shared.characters.count > 0 { + var labelIndex = e.label.characters.startIndex + + // Create index objects and move them to after the shared prefix + for _ in 1...shared.characters.count { + index = searchStr.characters.index(after: index) + labelIndex = e.label.characters.index(after: labelIndex) + } + + // Substring both the search string and the label from the shared prefix + searchStr = searchStr.substring(from: index) + e.label = e.label.substring(from: labelIndex) + + // Create 2 new edges and update parent/children values + let newEdge = Edge(e.label) + e.label = shared + for ec in e.children { + newEdge.children.append(ec) + } + newEdge.parent = e + e.children.removeAll() + for nec in newEdge.children { + nec.parent = newEdge + } + e.children.append(newEdge) + let newEdge2 = Edge(searchStr) + newEdge2.parent = e + e.children.append(newEdge2) + return true } + // If they don't share a prefix, go to next child + } + + // If none of the children share a prefix, you have to create a new child + if !found { + let newEdge = Edge(searchStr) + currEdge.children.append(newEdge) + newEdge.parent = currEdge + return true + } } -} + } -public class RadixTree { - var root: Root - - public init() { - root = Root() + // Tells you if a string is in the tree + public func find(_ str: String) -> Bool { + // A radix tree always contains the empty string + if str == "" { + return true } - - // Returns the height of the tree by calling the root's height function. - public func height() -> Int { - return root.height() - 1 + // If there are no children then the string cannot be in the tree + else if root.children.count == 0 { + return false } - - // Inserts a string into the tree. - public func insert(_ str: String) -> Bool { - //Account for a blank input. The empty string is already in the tree. - if str == "" { - return false + var searchStr = str + var currEdge = root + while true { + var found = false + // Loop through currEdge's children + for c in currEdge.children { + // First check if the search string and the child's label are equal + // if so the string is in the tree, return true + if searchStr == c.label { + return true } - - // searchStr is the parameter of the function - // it will be substringed as the function traverses down the tree - var searchStr = str - - // currEdge is the current Edge (or Root) in question - var currEdge = root - - while true { - var found = false - - // If the current Edge has no children then the remaining searchStr is - // created as a child - if currEdge.children.count == 0 { - let newEdge = Edge(searchStr) - currEdge.children.append(newEdge) - newEdge.parent = currEdge - return true - } - - // Loop through all of the children - for e in currEdge.children { - // Get the shared prefix between the child in question and the - // search string - let shared = sharedPrefix(searchStr, e.label) - var index = shared.startIndex - - // If the search string is equal to the shared string, - // the string already exists in the tree - if searchStr == shared { - return false - } - - // If the child's label is equal to the shared string, you have to - // traverse another level down the tree, so substring the search - // string, break the loop, and run it back - else if shared == e.label { - currEdge = e - var tempIndex = searchStr.startIndex - for _ in 1...shared.characters.count { - tempIndex = searchStr.characters.index(after: tempIndex) - } - searchStr = searchStr.substring(from: tempIndex) - found = true - break - } - - // If the child's label and the search string share a partial prefix, - // then both the label and the search string need to be substringed - // and a new branch needs to be created - else if shared.characters.count > 0 { - var labelIndex = e.label.characters.startIndex - - // Create index objects and move them to after the shared prefix - for _ in 1...shared.characters.count { - index = searchStr.characters.index(after: index) - labelIndex = e.label.characters.index(after: labelIndex) - } - - // Substring both the search string and the label from the shared prefix - searchStr = searchStr.substring(from: index) - e.label = e.label.substring(from: labelIndex) - - // Create 2 new edges and update parent/children values - let newEdge = Edge(e.label) - e.label = shared - for ec in e.children { - newEdge.children.append(ec) - } - newEdge.parent = e - e.children.removeAll() - for nec in newEdge.children { - nec.parent = newEdge - } - e.children.append(newEdge) - let newEdge2 = Edge(searchStr) - newEdge2.parent = e - e.children.append(newEdge2) - return true - } - // If they don't share a prefix, go to next child - } - - // If none of the children share a prefix, you have to create a new child - if !found { - let newEdge = Edge(searchStr) - currEdge.children.append(newEdge) - newEdge.parent = currEdge - return true - } + + // If that is not true, find the shared string b/t the search string + // and the label + let shared = sharedPrefix(searchStr, c.label) + + // If the shared string is equal to the label, update the curent node, + // break the loop, and run it back + if shared == c.label { + currEdge = c + var tempIndex = searchStr.startIndex + for _ in 1...shared.characters.count { + tempIndex = searchStr.characters.index(after: tempIndex) + } + searchStr = searchStr.substring(from: tempIndex) + found = true + break } - } - - // Tells you if a string is in the tree - public func find(_ str: String) -> Bool { - // A radix tree always contains the empty string - if str == "" { - return true + + // If the shared string is empty, go to the next child + else if shared.characters.count == 0 { + continue } - // If there are no children then the string cannot be in the tree - else if root.children.count == 0 { - return false + + // If the shared string matches the search string, return true + else if shared == searchStr { + return true } - var searchStr = str - var currEdge = root - while true { - var found = false - // Loop through currEdge's children - for c in currEdge.children { - // First check if the search string and the child's label are equal - // if so the string is in the tree, return true - if searchStr == c.label { - return true - } - - // If that is not true, find the shared string b/t the search string - // and the label - let shared = sharedPrefix(searchStr, c.label) - - // If the shared string is equal to the label, update the curent node, - // break the loop, and run it back - if shared == c.label { - currEdge = c - var tempIndex = searchStr.startIndex - for _ in 1...shared.characters.count { - tempIndex = searchStr.characters.index(after: tempIndex) - } - searchStr = searchStr.substring(from: tempIndex) - found = true - break - } - - // If the shared string is empty, go to the next child - else if shared.characters.count == 0 { - continue - } - - // If the shared string matches the search string, return true - else if shared == searchStr { - return true - } - - // If the search string and the child's label only share some characters, - // the string is not in the tree, return false - else if shared[shared.startIndex] == c.label[c.label.startIndex] && - shared.characters.count < c.label.characters.count { - return false - } - } - - // If nothing was found, return false - if !found { - return false - } + + // If the search string and the child's label only share some characters, + // the string is not in the tree, return false + else if shared[shared.startIndex] == c.label[c.label.startIndex] && + shared.characters.count < c.label.characters.count { + return false } + } + + // If nothing was found, return false + if !found { + return false + } } - - // Removes a string from the tree - public func remove(_ str: String) -> Bool { - // Removing the empty string removes everything in the tree - if str == "" { - for c in root.children { - c.erase() - root.children.remove(at: 0) - } - return true - } - // If the tree is empty, you cannot remove anything - else if root.children.count == 0 { - return false + } + + // Removes a string from the tree + public func remove(_ str: String) -> Bool { + // Removing the empty string removes everything in the tree + if str == "" { + for c in root.children { + c.erase() + root.children.remove(at: 0) + } + return true + } + // If the tree is empty, you cannot remove anything + else if root.children.count == 0 { + return false + } + + var searchStr = str + var currEdge = root + while true { + var found = false + // If currEdge has no children, then the searchStr is not in the tree + if currEdge.children.count == 0 { + return false + } + + // Loop through the children + for c in 0...currEdge.children.count-1 { + // If the child's label matches the search string, remove that child + // and everything below it in the tree + if currEdge.children[c].label == searchStr { + currEdge.children[c].erase() + currEdge.children.remove(at: c) + return true } - - var searchStr = str - var currEdge = root - while true { - var found = false - // If currEdge has no children, then the searchStr is not in the tree - if currEdge.children.count == 0 { - return false - } - - // Loop through the children - for c in 0...currEdge.children.count-1 { - // If the child's label matches the search string, remove that child - // and everything below it in the tree - if currEdge.children[c].label == searchStr { - currEdge.children[c].erase() - currEdge.children.remove(at: c) - return true - } - - // Find the shared string - let shared = sharedPrefix(searchStr, currEdge.children[c].label) - - // If the shared string is equal to the child's string, go down a level - if shared == currEdge.children[c].label { - currEdge = currEdge.children[c] - var tempIndex = searchStr.startIndex - for _ in 1...shared.characters.count { - tempIndex = searchStr.characters.index(after: tempIndex) - } - searchStr = searchStr.substring(from: tempIndex) - found = true - break - } - } - - // If there is no match, then the searchStr is not in the tree - if !found { - return false - } + + // Find the shared string + let shared = sharedPrefix(searchStr, currEdge.children[c].label) + + // If the shared string is equal to the child's string, go down a level + if shared == currEdge.children[c].label { + currEdge = currEdge.children[c] + var tempIndex = searchStr.startIndex + for _ in 1...shared.characters.count { + tempIndex = searchStr.characters.index(after: tempIndex) + } + searchStr = searchStr.substring(from: tempIndex) + found = true + break } + } + + // If there is no match, then the searchStr is not in the tree + if !found { + return false + } } - - // Prints the tree by calling the root's print function - public func printTree() { - root.printRoot() - } + } + + // Prints the tree by calling the root's print function + public func printTree() { + root.printRoot() + } } // Returns the prefix that is shared between the two input strings // i.e. sharedPrefix("court", "coral") -> "co" public func sharedPrefix(_ str1: String, _ str2: String) -> String { - var temp = "" - var c1 = str1.characters.startIndex - var c2 = str2.characters.startIndex - for _ in 0...min(str1.characters.count-1, str2.characters.count-1) { - if str1[c1] == str2[c2] { - temp.append( str1[c1] ) - c1 = str1.characters.index(after:c1) - c2 = str2.characters.index(after:c2) - } else { - return temp - } + var temp = "" + var c1 = str1.characters.startIndex + var c2 = str2.characters.startIndex + for _ in 0...min(str1.characters.count-1, str2.characters.count-1) { + if str1[c1] == str2[c2] { + temp.append( str1[c1] ) + c1 = str1.characters.index(after:c1) + c2 = str2.characters.index(after:c2) + } else { + return temp } - return temp + } + return temp } From 00c6b720b984928f3ea3d3ab9f679c0d49cf8087 Mon Sep 17 00:00:00 2001 From: Richard Date: Thu, 6 Oct 2016 22:19:50 -0700 Subject: [PATCH 0588/1679] Updated README --- Karatsuba Multiplication/README.markdown | 35 ++++++++++-------------- 1 file changed, 15 insertions(+), 20 deletions(-) diff --git a/Karatsuba Multiplication/README.markdown b/Karatsuba Multiplication/README.markdown index af3392612..d4c99ec2d 100644 --- a/Karatsuba Multiplication/README.markdown +++ b/Karatsuba Multiplication/README.markdown @@ -4,9 +4,9 @@ Goal: To quickly multiply two numbers together ## Long Multiplication -In grade school we all learned how to multiply two numbers together via Long Multiplication. So let's try that first! +In grade school we learned how to multiply two numbers together via Long Multiplication. Let's try that first! -Example 1: Multiply 1234 by 5678 using Long Multiplication +### Example 1: Multiply 1234 by 5678 using Long Multiplication 5678 *1234 @@ -18,9 +18,9 @@ Example 1: Multiply 1234 by 5678 using Long Multiplication -------- 7006652 -So what's the problem with long multiplication? Speed. Long Multiplication runs in **O(n^2)**. +So what's the problem with Long Multiplication? Well remember the first part of our goal. To *quickly* multiply two numbers together. Long Multiplication is slow! (**O(n^2)**) -You can see where the **O(n^2)** comes from in the implementation for Long Multiplication: +You can see where the **O(n^2)** comes from in the implementation of Long Multiplication: ```swift // Long Multiplication @@ -44,7 +44,7 @@ func multiply(_ num1: Int, by num2: Int, base: Int = 10) -> Int { } ``` -The double for loop is the culprit! So Long Multiplication might not be the best algorithm after all. Can we do better? +The double for loop is the culprit! By comparing each of the digits (as is necessary!) we set ourselves up for an **O(n^2)** running time. So Long Multiplication might not be the best algorithm after all. Can we do better? ## Karatsuba Multiplication @@ -57,24 +57,17 @@ For two numbers x, y, where m <= n: Now, we can say: - x*y = a*c*10^(2m) + (a*d + b*c)*10^(m) + b*d + x*y = (a*10^m + b) * (c*10^m + d) + = a*c*10^(2m) + (a*d + b*c)*10^(m) + b*d -We can compute this function recursively, and that's what makes Karatsuba Multiplication fast. +This had been know since the 19th century. The problem is that the method requires 4 multiplications (`a*c`, `a*d`, `b*c`, `b*d`). Karatsuba's insight was that you only need three! (`a*c`, `b*d`, `(a+b)*(c+d)`). Now a perfectly valid question right now would be "How is that possible!?!" Here's the math: -```swift -let ac = karatsuba(a, by: c) -let bd = karatsuba(b, by: d) -let adPlusbc = karatsuba(a+b, by: c+d) - ac - bd -``` - -The last recursion is interesting. Normally, you'd think we would have to run four recursions to find the product `x*y` (`a*c`, `a*d`, `b*c`, `b*d`). However, Karatsuba realized that you only need three recursions, and some addition and subtraction. Here's the math: - - (a+b)*(c+d) - a*c - b*c = (a*c + a*d + b*c + b*d) - a*c - b*c - = (a*d + b*c) + (a+b)*(c+d) - a*c - b*c = (a*c + a*d + b*c + b*d) - a*c - b*c + = (a*d + b*c) Pretty cool, huh? -Here's the full implementation +Here's the full implementation. Note that the recursive algorithm is most efficient at m = n/2. ```swift // Karatsuba Multiplication @@ -104,9 +97,9 @@ func karatsuba(_ num1: Int, by num2: Int) -> Int { } ``` -The run time for this algorithm is about **O(n^1.56)** which is better than the **O(n^2)** for Long Multiplication. +What about the running time of this algorithm? Is all this extra work worth it? We can use the Master Theorem to answer this question. This leads us to `T(n) = 3*T(n/2) + c*n + d` where c & d are some constants. It follows (because 3 > 2^1) that the running time is **O(n^log2(3))** which is roughly **O(n^1.56)**. Much better! -Example 2: Multiply 1234 by 5678 using Karatsuba Multiplication +### Example 2: Multiply 1234 by 5678 using Karatsuba Multiplication m = 2 x = 1234 = a*10^2 + b = 12*10^2 + 34 @@ -126,4 +119,6 @@ Example 2: Multiply 1234 by 5678 using Karatsuba Multiplication [WolframMathWorld] (http://mathworld.wolfram.com/KaratsubaMultiplication.html) +[Master Theorem] (https://en.wikipedia.org/wiki/Master_theorem) + *Written for Swift Algorithm Club by Richard Ash* From d0da5de44f445e2d651e9e08eeb8854b16c52a99 Mon Sep 17 00:00:00 2001 From: Richard Date: Thu, 6 Oct 2016 23:03:27 -0700 Subject: [PATCH 0589/1679] Fixed a typo --- .../KaratsubaMultiplication.playground/Contents.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Karatsuba Multiplication/KaratsubaMultiplication.playground/Contents.swift b/Karatsuba Multiplication/KaratsubaMultiplication.playground/Contents.swift index 95a498322..075f75098 100644 --- a/Karatsuba Multiplication/KaratsubaMultiplication.playground/Contents.swift +++ b/Karatsuba Multiplication/KaratsubaMultiplication.playground/Contents.swift @@ -33,7 +33,7 @@ func multiply(_ num1: Int, by num2: Int, base: Int = 10) -> Int { return Int(product.reversed().map{ String($0) }.reduce("", +))! } -// Karatsuba Multiplication - O(nlogn) +// Karatsuba Multiplication - O(n^log2(3)) func karatsuba(_ num1: Int, by num2: Int) -> Int { let num1Array = String(num1).characters let num2Array = String(num2).characters From 3d26e9258de7d82a494806019919f93150bc9e8d Mon Sep 17 00:00:00 2001 From: Kevin Taniguchi Date: Fri, 7 Oct 2016 20:18:22 -0500 Subject: [PATCH 0590/1679] updated readme --- .../BoyerMoore.playground/Contents.swift | 3 + .../BoyerMoore.playground/timeline.xctimeline | 6 +- Boyer-Moore/README.markdown | 81 ++++++++++--------- 3 files changed, 47 insertions(+), 43 deletions(-) diff --git a/Boyer-Moore/BoyerMoore.playground/Contents.swift b/Boyer-Moore/BoyerMoore.playground/Contents.swift index 9a3d619dc..4b2bad42c 100644 --- a/Boyer-Moore/BoyerMoore.playground/Contents.swift +++ b/Boyer-Moore/BoyerMoore.playground/Contents.swift @@ -46,3 +46,6 @@ s.indexOf(pattern: "World") // 7 let animals = "🐶🐔🐷🐮🐱" animals.indexOf(pattern: "🐮") // 6 + + + diff --git a/Boyer-Moore/BoyerMoore.playground/timeline.xctimeline b/Boyer-Moore/BoyerMoore.playground/timeline.xctimeline index 623552dab..59d8c8667 100644 --- a/Boyer-Moore/BoyerMoore.playground/timeline.xctimeline +++ b/Boyer-Moore/BoyerMoore.playground/timeline.xctimeline @@ -3,17 +3,17 @@ version = "3.0"> diff --git a/Boyer-Moore/README.markdown b/Boyer-Moore/README.markdown index ad1d3bc73..4d98f5a28 100644 --- a/Boyer-Moore/README.markdown +++ b/Boyer-Moore/README.markdown @@ -9,14 +9,14 @@ For example: ```swift // Input: let s = "Hello, World" -s.indexOf("World") +s.indexOf(pattern: "World") // Output: 7 // Input: let animals = "🐶🐔🐷🐮🐱" -animals.indexOf("🐮") +animals.indexOf(pattern: "🐮") // Output: 6 @@ -32,67 +32,68 @@ Here's how you could write it in Swift: ```swift extension String { - func indexOf(pattern: String) -> String.Index? { - // Cache the length of the search pattern because we're going to - // use it a few times and it's expensive to calculate. +func indexOf(pattern: String) -> String.Index? { +// Cache the length of the search pattern because we're going to +// use it a few times and it's expensive to calculate. let patternLength = pattern.characters.count - assert(patternLength > 0) - assert(patternLength <= self.characters.count) + assert(patternLength > 0) + assert(patternLength <= self.characters.count) - // Make the skip table. This table determines how far we skip ahead - // when a character from the pattern is found. +// Make the skip table. This table determines how far we skip ahead +// when a character from the pattern is found. var skipTable = [Character: Int]() for (i, c) in pattern.characters.enumerate() { - skipTable[c] = patternLength - i - 1 + skipTable[c] = patternLength - i - 1 } - // This points at the last character in the pattern. +// This points at the last character in the pattern. let p = pattern.endIndex.predecessor() let lastChar = pattern[p] - // The pattern is scanned right-to-left, so skip ahead in the string by - // the length of the pattern. (Minus 1 because startIndex already points - // at the first character in the source string.) +// The pattern is scanned right-to-left, so skip ahead in the string by +// the length of the pattern. (Minus 1 because startIndex already points +// at the first character in the source string.) var i = self.startIndex.advancedBy(patternLength - 1) - // This is a helper function that steps backwards through both strings - // until we find a character that doesn’t match, or until we’ve reached - // the beginning of the pattern. +// This is a helper function that steps backwards through both strings +// until we find a character that doesn’t match, or until we’ve reached +// the beginning of the pattern. func backwards() -> String.Index? { - var q = p - var j = i - while q > pattern.startIndex { - j = j.predecessor() - q = q.predecessor() - if self[j] != pattern[q] { return nil } - } - return j + var q = p + var j = i + while q > pattern.startIndex { + j = j.predecessor() + q = q.predecessor() + if self[j] != pattern[q] { return nil } + } + return j } - // The main loop. Keep going until the end of the string is reached. +// The main loop. Keep going until the end of the string is reached. while i < self.endIndex { - let c = self[i] + let c = self[i] - // Does the current character match the last character from the pattern? - if c == lastChar { +// Does the current character match the last character from the pattern? + if c == lastChar { - // There is a possible match. Do a brute-force search backwards. +// There is a possible match. Do a brute-force search backwards. if let k = backwards() { return k } - // If no match, we can only safely skip one character ahead. +// If no match, we can only safely skip one character ahead. i = i.successor() - } else { - // The characters are not equal, so skip ahead. The amount to skip is - // determined by the skip table. If the character is not present in the - // pattern, we can skip ahead by the full pattern length. However, if - // the character *is* present in the pattern, there may be a match up - // ahead and we can't skip as far. + } else { +// The characters are not equal, so skip ahead. The amount to skip is +// determined by the skip table. If the character is not present in the +// pattern, we can skip ahead by the full pattern length. However, if +// the character *is* present in the pattern, there may be a match up +// ahead and we can't skip as far. i = i.advancedBy(skipTable[c] ?? patternLength) - } + } } - return nil - } + return nil + } } + ``` 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: From a2892beff7f3769087ecc20c00a868e6b99f5628 Mon Sep 17 00:00:00 2001 From: Kevin Taniguchi Date: Fri, 7 Oct 2016 20:36:43 -0500 Subject: [PATCH 0591/1679] formatting --- .../BoyerMoore.playground/Contents.swift | 1 + .../BoyerMoore.playground/timeline.xctimeline | 6 +- Boyer-Moore/README.markdown | 92 +++++++++---------- 3 files changed, 50 insertions(+), 49 deletions(-) diff --git a/Boyer-Moore/BoyerMoore.playground/Contents.swift b/Boyer-Moore/BoyerMoore.playground/Contents.swift index 4b2bad42c..14447f495 100644 --- a/Boyer-Moore/BoyerMoore.playground/Contents.swift +++ b/Boyer-Moore/BoyerMoore.playground/Contents.swift @@ -39,6 +39,7 @@ extension String { } } + // A few simple tests let s = "Hello, World" diff --git a/Boyer-Moore/BoyerMoore.playground/timeline.xctimeline b/Boyer-Moore/BoyerMoore.playground/timeline.xctimeline index 59d8c8667..7e38effd2 100644 --- a/Boyer-Moore/BoyerMoore.playground/timeline.xctimeline +++ b/Boyer-Moore/BoyerMoore.playground/timeline.xctimeline @@ -3,17 +3,17 @@ version = "3.0"> diff --git a/Boyer-Moore/README.markdown b/Boyer-Moore/README.markdown index 4d98f5a28..dc40413ec 100644 --- a/Boyer-Moore/README.markdown +++ b/Boyer-Moore/README.markdown @@ -33,65 +33,65 @@ Here's how you could write it in Swift: ```swift extension String { func indexOf(pattern: String) -> String.Index? { -// Cache the length of the search pattern because we're going to -// use it a few times and it's expensive to calculate. + // Cache the length of the search pattern because we're going to + // use it a few times and it's expensive to calculate. let patternLength = pattern.characters.count - assert(patternLength > 0) - assert(patternLength <= self.characters.count) + assert(patternLength > 0) + assert(patternLength <= self.characters.count) -// Make the skip table. This table determines how far we skip ahead -// when a character from the pattern is found. + // Make the skip table. This table determines how far we skip ahead + // when a character from the pattern is found. var skipTable = [Character: Int]() - for (i, c) in pattern.characters.enumerate() { - skipTable[c] = patternLength - i - 1 + for (i, c) in pattern.characters.enumerated() { + skipTable[c] = patternLength - i - 1 } -// This points at the last character in the pattern. - let p = pattern.endIndex.predecessor() + // This points at the last character in the pattern. + let p = index(before: pattern.endIndex) let lastChar = pattern[p] -// The pattern is scanned right-to-left, so skip ahead in the string by -// the length of the pattern. (Minus 1 because startIndex already points -// at the first character in the source string.) - var i = self.startIndex.advancedBy(patternLength - 1) + // The pattern is scanned right-to-left, so skip ahead in the string by + // the length of the pattern. (Minus 1 because startIndex already points + // at the first character in the source string.) + var i = index(self.startIndex, offsetBy: patternLength - 1) -// This is a helper function that steps backwards through both strings -// until we find a character that doesn’t match, or until we’ve reached -// the beginning of the pattern. + // This is a helper function that steps backwards through both strings + // until we find a character that doesn’t match, or until we’ve reached + // the beginning of the pattern. func backwards() -> String.Index? { - var q = p - var j = i - while q > pattern.startIndex { - j = j.predecessor() - q = q.predecessor() - if self[j] != pattern[q] { return nil } - } - return j + var q = p + var j = i + while q > pattern.startIndex { + j = index(before: j) + q = index(before: q) + if self[j] != pattern[q] { return nil } + } + return j } -// The main loop. Keep going until the end of the string is reached. + // The main loop. Keep going until the end of the string is reached. while i < self.endIndex { - let c = self[i] - -// Does the current character match the last character from the pattern? - if c == lastChar { - -// There is a possible match. Do a brute-force search backwards. - if let k = backwards() { return k } - -// If no match, we can only safely skip one character ahead. - i = i.successor() - } else { -// The characters are not equal, so skip ahead. The amount to skip is -// determined by the skip table. If the character is not present in the -// pattern, we can skip ahead by the full pattern length. However, if -// the character *is* present in the pattern, there may be a match up -// ahead and we can't skip as far. - i = i.advancedBy(skipTable[c] ?? patternLength) - } + let c = self[i] + + // Does the current character match the last character from the pattern? + if c == lastChar { + + // There is a possible match. Do a brute-force search backwards. + if let k = backwards() { return k } + + // If no match, we can only safely skip one character ahead. + i = index(after: i) + } else { + // The characters are not equal, so skip ahead. The amount to skip is + // determined by the skip table. If the character is not present in the + // pattern, we can skip ahead by the full pattern length. However, if + // the character *is* present in the pattern, there may be a match up + // ahead and we can't skip as far. + i = index(i, offsetBy: skipTable[c] ?? patternLength) + } + } + return nil } - return nil - } } ``` From f09b42be3e59052a5ec5937fc645f71467aa0677 Mon Sep 17 00:00:00 2001 From: Kevin Taniguchi Date: Fri, 7 Oct 2016 21:16:05 -0500 Subject: [PATCH 0592/1679] updated readme --- .../BoyerMoore.playground/Contents.swift | 4 -- .../BoyerMoore.playground/timeline.xctimeline | 6 +-- Boyer-Moore/README.markdown | 42 +++++++++++-------- 3 files changed, 28 insertions(+), 24 deletions(-) diff --git a/Boyer-Moore/BoyerMoore.playground/Contents.swift b/Boyer-Moore/BoyerMoore.playground/Contents.swift index 14447f495..9a3d619dc 100644 --- a/Boyer-Moore/BoyerMoore.playground/Contents.swift +++ b/Boyer-Moore/BoyerMoore.playground/Contents.swift @@ -39,7 +39,6 @@ extension String { } } - // A few simple tests let s = "Hello, World" @@ -47,6 +46,3 @@ s.indexOf(pattern: "World") // 7 let animals = "🐶🐔🐷🐮🐱" animals.indexOf(pattern: "🐮") // 6 - - - diff --git a/Boyer-Moore/BoyerMoore.playground/timeline.xctimeline b/Boyer-Moore/BoyerMoore.playground/timeline.xctimeline index 7e38effd2..a15b8d6e0 100644 --- a/Boyer-Moore/BoyerMoore.playground/timeline.xctimeline +++ b/Boyer-Moore/BoyerMoore.playground/timeline.xctimeline @@ -3,17 +3,17 @@ version = "3.0"> diff --git a/Boyer-Moore/README.markdown b/Boyer-Moore/README.markdown index dc40413ec..4acc1ffb3 100644 --- a/Boyer-Moore/README.markdown +++ b/Boyer-Moore/README.markdown @@ -150,34 +150,42 @@ Here's an implementation of the Boyer-Moore-Horspool algorithm: ```swift extension String { - public func indexOf(pattern: String) -> String.Index? { + func indexOf(pattern: String) -> String.Index? { let patternLength = pattern.characters.count assert(patternLength > 0) assert(patternLength <= self.characters.count) var skipTable = [Character: Int]() - for (i, c) in pattern.characters.dropLast().enumerate() { - skipTable[c] = patternLength - i - 1 + for (i, c) in pattern.characters.enumerated() { + skipTable[c] = patternLength - i - 1 } - var index = self.startIndex.advancedBy(patternLength - 1) - - while index < self.endIndex { - var i = index - var p = pattern.endIndex.predecessor() - - while self[i] == pattern[p] { - if p == pattern.startIndex { return i } - i = i.predecessor() - p = p.predecessor() - } + let p = pattern.index(before: pattern.endIndex) + let lastChar = pattern[p] + var i = self.index(startIndex, offsetBy: patternLength - 1) - let advance = skipTable[self[index]] ?? patternLength - index = index.advancedBy(advance) + func backwards() -> String.Index? { + var q = p + var j = i + while q > pattern.startIndex { + j = index(before: j) + q = index(before: q) + if self[j] != pattern[q] { return nil } + } + return j } + while i < self.endIndex { + let c = self[i] + if c == lastChar { + if let k = backwards() { return k } + i = index(after: i) + } else { + i = index(i, offsetBy: skipTable[c] ?? patternLength) + } + } return nil - } + } } ``` From 0fa26236edb993696d77e00e47e7eebec07fe2d0 Mon Sep 17 00:00:00 2001 From: Peter Ivanics Date: Sat, 8 Oct 2016 22:31:46 +0300 Subject: [PATCH 0593/1679] Migrate Linked List to Swift 3.0 --- .../LinkedList.playground/Contents.swift | 39 ++++---- Linked List/LinkedList.swift | 97 +++++++++---------- Linked List/Tests/LinkedListTests.swift | 32 +++--- 3 files changed, 80 insertions(+), 88 deletions(-) diff --git a/Linked List/LinkedList.playground/Contents.swift b/Linked List/LinkedList.playground/Contents.swift index 72dcffe02..e73f89518 100644 --- a/Linked List/LinkedList.playground/Contents.swift +++ b/Linked List/LinkedList.playground/Contents.swift @@ -47,7 +47,7 @@ public class LinkedList { } } - public func nodeAt(_ index: Int) -> Node? { + public func node(atIndex index: Int) -> Node? { if index >= 0 { var node = head var i = index @@ -61,12 +61,12 @@ public class LinkedList { } public subscript(index: Int) -> T { - let node = nodeAt(index) + let node = self.node(atIndex: index) assert(node != nil) return node!.value } - public func append(value: T) { + public func append(_ value: T) { let newNode = Node(value: value) if let lastNode = last { newNode.previous = lastNode @@ -93,7 +93,7 @@ public class LinkedList { return (prev, next) } - public func insert(value: T, atIndex index: Int) { + public func insert(_ value: T, atIndex index: Int) { let (prev, next) = nodesBeforeAndAfter(index: index) let newNode = Node(value: value) @@ -132,8 +132,8 @@ public class LinkedList { return remove(node: last!) } - public func removeAt(_ index: Int) -> T { - let node = nodeAt(index) + public func remove(atIndex index: Int) -> T { + let node = self.node(atIndex: index) assert(node != nil) return remove(node: node!) } @@ -168,7 +168,7 @@ extension LinkedList { let result = LinkedList() var node = head while node != nil { - result.append(value: transform(node!.value)) + result.append(transform(node!.value)) node = node!.next } return result @@ -179,7 +179,7 @@ extension LinkedList { var node = head while node != nil { if predicate(node!.value) { - result.append(value: node!.value) + result.append(node!.value) } node = node!.next } @@ -187,21 +187,18 @@ extension LinkedList { } } - - - let list = LinkedList() list.isEmpty // true list.first // nil list.last // nil -list.append(value: "Hello") +list.append("Hello") list.isEmpty list.first!.value // "Hello" list.last!.value // "Hello" list.count // 1 -list.append(value: "World") +list.append("World") list.first!.value // "Hello" list.last!.value // "World" list.count // 2 @@ -211,15 +208,15 @@ list.first!.next!.value // "World" list.last!.previous!.value // "Hello" list.last!.next // nil -list.nodeAt(0)!.value // "Hello" -list.nodeAt(1)!.value // "World" -list.nodeAt(2) // nil +list.node(atIndex: 0)!.value // "Hello" +list.node(atIndex: 1)!.value // "World" +list.node(atIndex: 2) // nil list[0] // "Hello" list[1] // "World" //list[2] // crash! -list.insert(value: "Swift", atIndex: 1) +list.insert("Swift", atIndex: 1) list[0] list[1] list[2] @@ -227,8 +224,8 @@ print(list) list.reverse() // [World, Swift, Hello] -list.nodeAt(0)!.value = "Universe" -list.nodeAt(1)!.value = "Swifty" +list.node(atIndex: 0)!.value = "Universe" +list.node(atIndex: 1)!.value = "Swifty" let m = list.map { s in s.characters.count } m // [8, 6, 5] let f = list.filter { s in s.characters.count > 5 } @@ -237,7 +234,7 @@ f // [Universe, Swifty] //list.removeAll() //list.isEmpty -list.remove(node: list.first!) // "Hello" +list.remove(node: list.first!) // "Hello" list.count // 2 list[0] // "Swift" list[1] // "World" @@ -246,5 +243,5 @@ list.removeLast() // "World" list.count // 1 list[0] // "Swift" -list.removeAt(0) // "Swift" +list.remove(atIndex: 0) // "Swift" list.count // 0 diff --git a/Linked List/LinkedList.swift b/Linked List/LinkedList.swift index 306743354..49f1c0915 100755 --- a/Linked List/LinkedList.swift +++ b/Linked List/LinkedList.swift @@ -1,32 +1,27 @@ -/* - Doubly-linked list - - Most operations on the linked list have complexity O(n). -*/ -open class LinkedListNode { +public class LinkedListNode { var value: T var next: LinkedListNode? weak var previous: LinkedListNode? - + public init(value: T) { self.value = value } } -open class LinkedList { +public class LinkedList { public typealias Node = LinkedListNode - + fileprivate var head: Node? - - open var isEmpty: Bool { + + public var isEmpty: Bool { return head == nil } - - open var first: Node? { + + public var first: Node? { return head } - - open var last: Node? { + + public var last: Node? { if var node = head { while case let next? = node.next { node = next @@ -36,8 +31,8 @@ open class LinkedList { return nil } } - - open var count: Int { + + public var count: Int { if var node = head { var c = 1 while case let next? = node.next { @@ -49,8 +44,8 @@ open class LinkedList { return 0 } } - - open func nodeAt(_ index: Int) -> Node? { + + public func node(atIndex index: Int) -> Node? { if index >= 0 { var node = head var i = index @@ -62,14 +57,14 @@ open class LinkedList { } return nil } - - open subscript(index: Int) -> T { - let node = nodeAt(index) + + public subscript(index: Int) -> T { + let node = self.node(atIndex: index) assert(node != nil) return node!.value } - - open func append(_ value: T) { + + public func append(_ value: T) { let newNode = Node(value: value) if let lastNode = last { newNode.previous = lastNode @@ -78,67 +73,67 @@ open class LinkedList { head = newNode } } - - fileprivate func nodesBeforeAndAfter(_ index: Int) -> (Node?, Node?) { + + private func nodesBeforeAndAfter(index: Int) -> (Node?, Node?) { assert(index >= 0) - + var i = index var next = head var prev: Node? - + while next != nil && i > 0 { i -= 1 prev = next next = next!.next } assert(i == 0) // if > 0, then specified index was too large - + return (prev, next) } - - open func insert(_ value: T, atIndex index: Int) { - let (prev, next) = nodesBeforeAndAfter(index) - + + public func insert(_ value: T, atIndex index: Int) { + let (prev, next) = nodesBeforeAndAfter(index: index) + let newNode = Node(value: value) newNode.previous = prev newNode.next = next prev?.next = newNode next?.previous = newNode - + if prev == nil { head = newNode } } - - open func removeAll() { + + public func removeAll() { head = nil } - - open func remove(_ node: Node) -> T { + + public func remove(node: Node) -> T { let prev = node.previous let next = node.next - + if let prev = prev { prev.next = next } else { head = next } next?.previous = prev - + node.previous = nil node.next = nil return node.value } - - open func removeLast() -> T { + + public func removeLast() -> T { assert(!isEmpty) - return remove(last!) + return remove(node: last!) } - - open func removeAt(_ index: Int) -> T { - let node = nodeAt(index) + + public func remove(atIndex index: Int) -> T { + let node = self.node(atIndex: index) assert(node != nil) - return remove(node!) + return remove(node: node!) } } @@ -167,17 +162,17 @@ extension LinkedList { } extension LinkedList { - public func map(_ transform: (T)-> U) -> LinkedList { + public func map(transform: (T) -> U) -> LinkedList { let result = LinkedList() var node = head while node != nil { - result.append(transform(node!.value)) + result.append(transform(node!.value)) node = node!.next } return result } - - public func filter(_ predicate: (T)-> Bool) -> LinkedList { + + public func filter(predicate: (T) -> Bool) -> LinkedList { let result = LinkedList() var node = head while node != nil { diff --git a/Linked List/Tests/LinkedListTests.swift b/Linked List/Tests/LinkedListTests.swift index beba84299..367ec8c6b 100755 --- a/Linked List/Tests/LinkedListTests.swift +++ b/Linked List/Tests/LinkedListTests.swift @@ -88,7 +88,7 @@ class LinkedListTest: XCTestCase { func testNodeAtIndexInEmptyList() { let list = LinkedList() - let node = list.nodeAt(0) + let node = list.node(atIndex: 0) XCTAssertNil(node) } @@ -96,7 +96,7 @@ class LinkedListTest: XCTestCase { let list = LinkedList() list.append(123) - let node = list.nodeAt(0) + let node = list.node(atIndex: 0) XCTAssertNotNil(node) XCTAssertEqual(node!.value, 123) XCTAssertTrue(node === list.first) @@ -108,21 +108,21 @@ class LinkedListTest: XCTestCase { let nodeCount = list.count XCTAssertEqual(nodeCount, numbers.count) - XCTAssertNil(list.nodeAt(-1)) - XCTAssertNil(list.nodeAt(nodeCount)) + XCTAssertNil(list.node(atIndex: -1)) + XCTAssertNil(list.node(atIndex: nodeCount)) - let first = list.nodeAt(0) + let first = list.node(atIndex: 0) XCTAssertNotNil(first) XCTAssertTrue(first === list.first) XCTAssertEqual(first!.value, numbers[0]) - let last = list.nodeAt(nodeCount - 1) + let last = list.node(atIndex: nodeCount - 1) XCTAssertNotNil(last) XCTAssertTrue(last === list.last) XCTAssertEqual(last!.value, numbers[nodeCount - 1]) for i in 0..() list.append(123) - let value = list.removeAt(0) + let value = list.remove(atIndex: 0) XCTAssertEqual(value, 123) XCTAssertTrue(list.isEmpty) @@ -181,16 +181,16 @@ class LinkedListTest: XCTestCase { func testRemoveAtIndex() { let list = buildList() - let prev = list.nodeAt(2) - let next = list.nodeAt(3) + let prev = list.node(atIndex: 2) + let next = list.node(atIndex: 3) let nodeCount = list.count list.insert(444, atIndex: 3) - let value = list.removeAt(3) + let value = list.remove(atIndex: 3) XCTAssertEqual(value, 444) - let node = list.nodeAt(3) + let node = list.node(atIndex: 3) XCTAssertTrue(next === node) XCTAssertTrue(prev!.next === node) XCTAssertTrue(node!.previous === prev) From 4f5565d15ef94ba1cc2a6f2f08c2cebc96baa058 Mon Sep 17 00:00:00 2001 From: Artur Date: Sat, 8 Oct 2016 23:58:07 +0300 Subject: [PATCH 0594/1679] Migrate treap to swift 3 --- .travis.yml | 1 + Treap/Treap.swift | 253 ++++--- Treap/Treap/Treap.xcodeproj/project.pbxproj | 162 +---- .../xcshareddata/WorkspaceSettings.xcsettings | 8 + .../xcshareddata/xcschemes/Tests.xcscheme | 33 +- .../xcshareddata/xcschemes/Treap.xcscheme | 101 --- Treap/Treap/Treap/AppDelegate.swift | 43 -- .../AppIcon.appiconset/Contents.json | 58 -- Treap/Treap/Treap/Base.lproj/MainMenu.xib | 681 ------------------ Treap/Treap/TreapTests/TreapTests.swift | 83 ++- Treap/TreapCollectionType.swift | 138 ++-- Treap/TreapMergeSplit.swift | 156 ++-- 12 files changed, 375 insertions(+), 1342 deletions(-) create mode 100644 Treap/Treap/Treap.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings delete mode 100644 Treap/Treap/Treap.xcodeproj/xcshareddata/xcschemes/Treap.xcscheme delete mode 100644 Treap/Treap/Treap/AppDelegate.swift delete mode 100644 Treap/Treap/Treap/Assets.xcassets/AppIcon.appiconset/Contents.json delete mode 100644 Treap/Treap/Treap/Base.lproj/MainMenu.xib diff --git a/.travis.yml b/.travis.yml index 949fc759f..35bcf6199 100644 --- a/.travis.yml +++ b/.travis.yml @@ -39,3 +39,4 @@ script: # - xcodebuild test -project ./Single-Source\ Shortest\ Paths\ \(Weighted\)/SSSP.xcodeproj -scheme SSSPTests - xcodebuild test -project ./Stack/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Topological\ Sort/Tests/Tests.xcodeproj -scheme Tests +- xcodebuild test -project ./Treap/Treap/Treap.xcodeproj -scheme Tests diff --git a/Treap/Treap.swift b/Treap/Treap.swift index e1d1d4892..478f248df 100644 --- a/Treap/Treap.swift +++ b/Treap/Treap.swift @@ -25,146 +25,145 @@ THE SOFTWARE.*/ import Foundation public indirect enum Treap { - case Empty - case Node(key: Key, val: Element, p: Int, left: Treap, right: Treap) - - public init() { - self = .Empty - } - - internal func get(key: Key) -> Element? { - switch self { - case .Empty: - return nil - case let .Node(treeKey, val, _, _, _) where treeKey == key: - return val - case let .Node(treeKey, _, _, left, _) where key < treeKey: - return left.get(key) - case let .Node(treeKey, _, _, _, right) where key > treeKey: - return right.get(key) - default: - return nil - } + case empty + case node(key: Key, val: Element, p: Int, left: Treap, right: Treap) + + public init() { + self = .empty + } + + internal func get(_ key: Key) -> Element? { + switch self { + case .empty: + return nil + case let .node(treeKey, val, _, _, _) where treeKey == key: + return val + case let .node(treeKey, _, _, left, _) where key < treeKey: + return left.get(key) + case let .node(treeKey, _, _, _, right) where key > treeKey: + return right.get(key) + default: + return nil } - - public func contains(key: Key) -> Bool { - switch self { - case .Empty: - return false - case let .Node(treeKey, _, _, _, _) where treeKey == key: - return true - case let .Node(treeKey, _, _, left, _) where key < treeKey: - return left.contains(key) - case let .Node(treeKey, _, _, _, right) where key > treeKey: - return right.contains(key) - default: - return false - } + } + + public func contains(_ key: Key) -> Bool { + switch self { + case .empty: + return false + case let .node(treeKey, _, _, _, _) where treeKey == key: + return true + case let .node(treeKey, _, _, left, _) where key < treeKey: + return left.contains(key) + case let .node(treeKey, _, _, _, right) where key > treeKey: + return right.contains(key) + default: + return false } - - public var depth: Int { - get { - switch self { - case .Empty: - return 0 - case let .Node(_, _, _, left, .Empty): - return 1 + left.depth - case let .Node(_, _, _, .Empty, right): - return 1 + right.depth - case let .Node(_, _, _, left, right): - let leftDepth = left.depth - let rightDepth = right.depth - return 1 + max(leftDepth, rightDepth) - } - - } + } + + public var depth: Int { + get { + switch self { + case .empty: + return 0 + case let .node(_, _, _, left, .empty): + return 1 + left.depth + case let .node(_, _, _, .empty, right): + return 1 + right.depth + case let .node(_, _, _, left, right): + let leftDepth = left.depth + let rightDepth = right.depth + return 1 + leftDepth > rightDepth ? leftDepth : rightDepth + } + } - - public var count: Int { - get { - return Treap.countHelper(self) - } + } + + public var count: Int { + get { + return Treap.countHelper(self) } - - private static func countHelper(treap: Treap) -> Int { - if case let .Node(_, _, _, left, right) = treap { - return countHelper(left) + 1 + countHelper(right) - } - - return 0 + } + + fileprivate static func countHelper(_ treap: Treap) -> Int { + if case let .node(_, _, _, left, right) = treap { + return countHelper(left) + 1 + countHelper(right) } + + return 0 + } } -internal func leftRotate(tree: Treap) -> Treap { - if case let .Node(key, val, p, .Node(leftKey, leftVal, leftP, leftLeft, leftRight), right) = tree { - return .Node(key: leftKey, val: leftVal, p: leftP, left: leftLeft, - right: Treap.Node(key: key, val: val, p: p, left: leftRight, right: right)) - } else { - return .Empty - } +internal func leftRotate(_ tree: Treap) -> Treap { + if case let .node(key, val, p, .node(leftKey, leftVal, leftP, leftLeft, leftRight), right) = tree { + return .node(key: leftKey, val: leftVal, p: leftP, left: leftLeft, + right: Treap.node(key: key, val: val, p: p, left: leftRight, right: right)) + } else { + return .empty + } } -internal func rightRotate(tree: Treap) -> Treap { - if case let .Node(key, val, p, left, .Node(rightKey, rightVal, rightP, rightLeft, rightRight)) = tree { - return .Node(key: rightKey, val: rightVal, p: rightP, - left: Treap.Node(key: key, val: val, p: p, left: left, right: rightLeft), right: rightRight) - } else { - return .Empty - } +internal func rightRotate(_ tree: Treap) -> Treap { + if case let .node(key, val, p, left, .node(rightKey, rightVal, rightP, rightLeft, rightRight)) = tree { + return .node(key: rightKey, val: rightVal, p: rightP, + left: Treap.node(key: key, val: val, p: p, left: left, right: rightLeft), right: rightRight) + } else { + return .empty + } } public extension Treap { - internal func set(key: Key, val: Element, p: Int = Int(arc4random())) -> Treap { - switch self { - case .Empty: - return .Node(key: key, val: val, p: p, left: .Empty, right: .Empty) - case let .Node(nodeKey, nodeVal, nodeP, left, right) where key != nodeKey: - return insertAndBalance(nodeKey, nodeVal, nodeP, left, right, key, val, p) - case let .Node(nodeKey, _, nodeP, left, right) where key == nodeKey: - return .Node(key: key, val: val, p: nodeP, left: left, right: right) - default: // should never happen - return .Empty - } - + internal func set(key: Key, val: Element, p: Int = Int(arc4random())) -> Treap { + switch self { + case .empty: + return .node(key: key, val: val, p: p, left: .empty, right: .empty) + case let .node(nodeKey, nodeVal, nodeP, left, right) where key != nodeKey: + return insertAndBalance(nodeKey, nodeVal, nodeP, left, right, key, val, p) + case let .node(nodeKey, _, nodeP, left, right) where key == nodeKey: + return .node(key: key, val: val, p: nodeP, left: left, right: right) + default: // should never happen + return .empty } - - private func insertAndBalance(nodeKey: Key, _ nodeVal: Element, _ nodeP: Int, _ left: Treap, - _ right: Treap, _ key: Key, _ val: Element, _ p: Int) -> Treap { - let newChild: Treap - let newNode: Treap - let rotate: (Treap) -> Treap - if key < nodeKey { - newChild = left.set(key, val: val, p: p) - newNode = .Node(key: nodeKey, val: nodeVal, p: nodeP, left: newChild, right: right) - rotate = leftRotate - } else if key > nodeKey { - newChild = right.set(key, val: val, p: p) - newNode = .Node(key: nodeKey, val: nodeVal, p: nodeP, left: left, right: newChild) - rotate = rightRotate - } else { - // It should be impossible to reach here - newChild = .Empty - newNode = .Empty - return newNode - } - - if case let .Node(_, _, newChildP, _, _) = newChild where newChildP < nodeP { - return rotate(newNode) - } else { - return newNode - } + } + + fileprivate func insertAndBalance(_ nodeKey: Key, _ nodeVal: Element, _ nodeP: Int, _ left: Treap, + _ right: Treap, _ key: Key, _ val: Element, _ p: Int) -> Treap { + let newChild: Treap + let newNode: Treap + let rotate: (Treap) -> Treap + if key < nodeKey { + newChild = left.set(key: key, val: val, p: p) + newNode = .node(key: nodeKey, val: nodeVal, p: nodeP, left: newChild, right: right) + rotate = leftRotate + } else if key > nodeKey { + newChild = right.set(key: key, val: val, p: p) + newNode = .node(key: nodeKey, val: nodeVal, p: nodeP, left: left, right: newChild) + rotate = rightRotate + } else { + // It should be impossible to reach here + newChild = .empty + newNode = .empty + return newNode } - - internal func delete(key: Key) throws -> Treap { - switch self { - case .Empty: - throw NSError(domain: "com.wta.treap.errorDomain", code: -1, userInfo: nil) - case let .Node(nodeKey, val, p, left, right) where key < nodeKey: - return try Treap.Node(key: nodeKey, val: val, p: p, left: left.delete(key), right: right) - case let .Node(nodeKey, val, p, left, right) where key > nodeKey: - return try Treap.Node(key: nodeKey, val: val, p: p, left: left, right: right.delete(key)) - case let .Node(_, _, _, left, right): - return merge(left, right: right) - } + + if case let .node(_, _, newChildP, _, _) = newChild , newChildP < nodeP { + return rotate(newNode) + } else { + return newNode + } + } + + internal func delete(key: Key) throws -> Treap { + switch self { + case .empty: + throw NSError(domain: "com.wta.treap.errorDomain", code: -1, userInfo: nil) + case let .node(nodeKey, val, p, left, right) where key < nodeKey: + return try Treap.node(key: nodeKey, val: val, p: p, left: left.delete(key: key), right: right) + case let .node(nodeKey, val, p, left, right) where key > nodeKey: + return try Treap.node(key: nodeKey, val: val, p: p, left: left, right: right.delete(key: key)) + case let .node(_, _, _, left, right): + return merge(left, right: right) } + } } diff --git a/Treap/Treap/Treap.xcodeproj/project.pbxproj b/Treap/Treap/Treap.xcodeproj/project.pbxproj index 319a22f37..df9a0d6ee 100644 --- a/Treap/Treap/Treap.xcodeproj/project.pbxproj +++ b/Treap/Treap/Treap.xcodeproj/project.pbxproj @@ -7,32 +7,15 @@ objects = { /* Begin PBXBuildFile section */ - E1E34DC71C7670240023AF4D /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1E34DC61C7670240023AF4D /* AppDelegate.swift */; }; - E1E34DC91C7670240023AF4D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E1E34DC81C7670240023AF4D /* Assets.xcassets */; }; - E1E34DCC1C7670240023AF4D /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = E1E34DCA1C7670240023AF4D /* MainMenu.xib */; }; + 750439C01DA9924E0045C660 /* Treap.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1E34DE11C7670350023AF4D /* Treap.swift */; }; + 750439C11DA992510045C660 /* TreapMergeSplit.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1E34DE21C7670350023AF4D /* TreapMergeSplit.swift */; }; + 750439C21DA992530045C660 /* TreapCollectionType.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1E34DE91C7671200023AF4D /* TreapCollectionType.swift */; }; E1E34DD71C7670250023AF4D /* TreapTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1E34DD61C7670250023AF4D /* TreapTests.swift */; }; - E1E34DE31C7670350023AF4D /* Treap.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1E34DE11C7670350023AF4D /* Treap.swift */; }; - E1E34DE41C7670350023AF4D /* TreapMergeSplit.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1E34DE21C7670350023AF4D /* TreapMergeSplit.swift */; }; - E1E34DEA1C7671200023AF4D /* TreapCollectionType.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1E34DE91C7671200023AF4D /* TreapCollectionType.swift */; }; /* End PBXBuildFile section */ -/* Begin PBXContainerItemProxy section */ - E1E34DD31C7670250023AF4D /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = E1E34DBB1C7670240023AF4D /* Project object */; - proxyType = 1; - remoteGlobalIDString = E1E34DC21C7670240023AF4D; - remoteInfo = Treap; - }; -/* End PBXContainerItemProxy section */ - /* Begin PBXFileReference section */ - E1E34DC31C7670240023AF4D /* Treap.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Treap.app; sourceTree = BUILT_PRODUCTS_DIR; }; - E1E34DC61C7670240023AF4D /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - E1E34DC81C7670240023AF4D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - E1E34DCB1C7670240023AF4D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; E1E34DCD1C7670240023AF4D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - E1E34DD21C7670250023AF4D /* TreapTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TreapTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + E1E34DD21C7670250023AF4D /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; E1E34DD61C7670250023AF4D /* TreapTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TreapTests.swift; sourceTree = ""; }; E1E34DD81C7670250023AF4D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; E1E34DE11C7670350023AF4D /* Treap.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Treap.swift; path = ../../Treap.swift; sourceTree = ""; }; @@ -41,13 +24,6 @@ /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ - E1E34DC01C7670240023AF4D /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; E1E34DCF1C7670250023AF4D /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -70,8 +46,7 @@ E1E34DC41C7670240023AF4D /* Products */ = { isa = PBXGroup; children = ( - E1E34DC31C7670240023AF4D /* Treap.app */, - E1E34DD21C7670250023AF4D /* TreapTests.xctest */, + E1E34DD21C7670250023AF4D /* Tests.xctest */, ); name = Products; sourceTree = ""; @@ -79,9 +54,6 @@ E1E34DC51C7670240023AF4D /* Treap */ = { isa = PBXGroup; children = ( - E1E34DC61C7670240023AF4D /* AppDelegate.swift */, - E1E34DC81C7670240023AF4D /* Assets.xcassets */, - E1E34DCA1C7670240023AF4D /* MainMenu.xib */, E1E34DE11C7670350023AF4D /* Treap.swift */, E1E34DE21C7670350023AF4D /* TreapMergeSplit.swift */, E1E34DE91C7671200023AF4D /* TreapCollectionType.swift */, @@ -102,26 +74,9 @@ /* End PBXGroup section */ /* Begin PBXNativeTarget section */ - E1E34DC21C7670240023AF4D /* Treap */ = { + E1E34DD11C7670250023AF4D /* Tests */ = { isa = PBXNativeTarget; - buildConfigurationList = E1E34DDB1C7670250023AF4D /* Build configuration list for PBXNativeTarget "Treap" */; - buildPhases = ( - E1E34DBF1C7670240023AF4D /* Sources */, - E1E34DC01C7670240023AF4D /* Frameworks */, - E1E34DC11C7670240023AF4D /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = Treap; - productName = Treap; - productReference = E1E34DC31C7670240023AF4D /* Treap.app */; - productType = "com.apple.product-type.application"; - }; - E1E34DD11C7670250023AF4D /* TreapTests */ = { - isa = PBXNativeTarget; - buildConfigurationList = E1E34DDE1C7670250023AF4D /* Build configuration list for PBXNativeTarget "TreapTests" */; + buildConfigurationList = E1E34DDE1C7670250023AF4D /* Build configuration list for PBXNativeTarget "Tests" */; buildPhases = ( E1E34DCE1C7670250023AF4D /* Sources */, E1E34DCF1C7670250023AF4D /* Frameworks */, @@ -130,11 +85,10 @@ buildRules = ( ); dependencies = ( - E1E34DD41C7670250023AF4D /* PBXTargetDependency */, ); - name = TreapTests; + name = Tests; productName = TreapTests; - productReference = E1E34DD21C7670250023AF4D /* TreapTests.xctest */; + productReference = E1E34DD21C7670250023AF4D /* Tests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; /* End PBXNativeTarget section */ @@ -144,15 +98,12 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; - LastUpgradeCheck = 0720; + LastUpgradeCheck = 0800; ORGANIZATIONNAME = "WillowTree, Inc."; TargetAttributes = { - E1E34DC21C7670240023AF4D = { - CreatedOnToolsVersion = 7.2.1; - }; E1E34DD11C7670250023AF4D = { CreatedOnToolsVersion = 7.2.1; - TestTargetID = E1E34DC21C7670240023AF4D; + LastSwiftMigration = 0800; }; }; }; @@ -169,22 +120,12 @@ projectDirPath = ""; projectRoot = ""; targets = ( - E1E34DC21C7670240023AF4D /* Treap */, - E1E34DD11C7670250023AF4D /* TreapTests */, + E1E34DD11C7670250023AF4D /* Tests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ - E1E34DC11C7670240023AF4D /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - E1E34DC91C7670240023AF4D /* Assets.xcassets in Resources */, - E1E34DCC1C7670240023AF4D /* MainMenu.xib in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; E1E34DD01C7670250023AF4D /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; @@ -195,46 +136,19 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ - E1E34DBF1C7670240023AF4D /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - E1E34DEA1C7671200023AF4D /* TreapCollectionType.swift in Sources */, - E1E34DE31C7670350023AF4D /* Treap.swift in Sources */, - E1E34DC71C7670240023AF4D /* AppDelegate.swift in Sources */, - E1E34DE41C7670350023AF4D /* TreapMergeSplit.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; E1E34DCE1C7670250023AF4D /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 750439C01DA9924E0045C660 /* Treap.swift in Sources */, E1E34DD71C7670250023AF4D /* TreapTests.swift in Sources */, + 750439C21DA992530045C660 /* TreapCollectionType.swift in Sources */, + 750439C11DA992510045C660 /* TreapMergeSplit.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ -/* Begin PBXTargetDependency section */ - E1E34DD41C7670250023AF4D /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = E1E34DC21C7670240023AF4D /* Treap */; - targetProxy = E1E34DD31C7670250023AF4D /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin PBXVariantGroup section */ - E1E34DCA1C7670240023AF4D /* MainMenu.xib */ = { - isa = PBXVariantGroup; - children = ( - E1E34DCB1C7670240023AF4D /* Base */, - ); - name = MainMenu.xib; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - /* Begin XCBuildConfiguration section */ E1E34DD91C7670250023AF4D /* Debug */ = { isa = XCBuildConfiguration; @@ -249,8 +163,10 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; @@ -293,8 +209,10 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; @@ -313,56 +231,31 @@ MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; - }; - name = Release; - }; - E1E34DDC1C7670250023AF4D /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = Treap/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.willowtree.Treap; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - E1E34DDD1C7670250023AF4D /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = Treap/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.willowtree.Treap; - PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; }; name = Release; }; E1E34DDF1C7670250023AF4D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = TreapTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.willowtree.TreapTests; PRODUCT_NAME = "$(TARGET_NAME)"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Treap.app/Contents/MacOS/Treap"; + SWIFT_VERSION = 3.0; }; name = Debug; }; E1E34DE01C7670250023AF4D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = TreapTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.willowtree.TreapTests; PRODUCT_NAME = "$(TARGET_NAME)"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Treap.app/Contents/MacOS/Treap"; + SWIFT_VERSION = 3.0; }; name = Release; }; @@ -378,21 +271,14 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - E1E34DDB1C7670250023AF4D /* Build configuration list for PBXNativeTarget "Treap" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - E1E34DDC1C7670250023AF4D /* Debug */, - E1E34DDD1C7670250023AF4D /* Release */, - ); - defaultConfigurationIsVisible = 0; - }; - E1E34DDE1C7670250023AF4D /* Build configuration list for PBXNativeTarget "TreapTests" */ = { + E1E34DDE1C7670250023AF4D /* Build configuration list for PBXNativeTarget "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( E1E34DDF1C7670250023AF4D /* Debug */, E1E34DE01C7670250023AF4D /* Release */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; diff --git a/Treap/Treap/Treap.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/Treap/Treap/Treap.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 000000000..08de0be8d --- /dev/null +++ b/Treap/Treap/Treap.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded + + + diff --git a/Treap/Treap/Treap.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Treap/Treap/Treap.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme index 3eb165e19..fa2508008 100644 --- a/Treap/Treap/Treap.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme +++ b/Treap/Treap/Treap.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -1,7 +1,7 @@ + LastUpgradeVersion = "0800" + version = "1.7"> @@ -15,8 +15,8 @@ @@ -33,12 +33,25 @@ + + + + + + @@ -56,8 +69,8 @@ @@ -74,8 +87,8 @@ diff --git a/Treap/Treap/Treap.xcodeproj/xcshareddata/xcschemes/Treap.xcscheme b/Treap/Treap/Treap.xcodeproj/xcshareddata/xcschemes/Treap.xcscheme deleted file mode 100644 index 566c370e1..000000000 --- a/Treap/Treap/Treap.xcodeproj/xcshareddata/xcschemes/Treap.xcscheme +++ /dev/null @@ -1,101 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Treap/Treap/Treap/AppDelegate.swift b/Treap/Treap/Treap/AppDelegate.swift deleted file mode 100644 index a6a68a40c..000000000 --- a/Treap/Treap/Treap/AppDelegate.swift +++ /dev/null @@ -1,43 +0,0 @@ -// -// AppDelegate.swift -// Treap -// -// Created by Robert Thompson on 2/18/16. -// Copyright © 2016 Robert Thompson -/* Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE.*/ -// - -import Cocoa - -@NSApplicationMain -class AppDelegate: NSObject, NSApplicationDelegate { - - @IBOutlet weak var window: NSWindow! - - - func applicationDidFinishLaunching(aNotification: NSNotification) { - // Insert code here to initialize your application - } - - func applicationWillTerminate(aNotification: NSNotification) { - // Insert code here to tear down your application - } - - -} diff --git a/Treap/Treap/Treap/Assets.xcassets/AppIcon.appiconset/Contents.json b/Treap/Treap/Treap/Assets.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index 2db2b1c7c..000000000 --- a/Treap/Treap/Treap/Assets.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "images" : [ - { - "idiom" : "mac", - "size" : "16x16", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "16x16", - "scale" : "2x" - }, - { - "idiom" : "mac", - "size" : "32x32", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "32x32", - "scale" : "2x" - }, - { - "idiom" : "mac", - "size" : "128x128", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "128x128", - "scale" : "2x" - }, - { - "idiom" : "mac", - "size" : "256x256", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "256x256", - "scale" : "2x" - }, - { - "idiom" : "mac", - "size" : "512x512", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "512x512", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/Treap/Treap/Treap/Base.lproj/MainMenu.xib b/Treap/Treap/Treap/Base.lproj/MainMenu.xib deleted file mode 100644 index 8955ad822..000000000 --- a/Treap/Treap/Treap/Base.lproj/MainMenu.xib +++ /dev/null @@ -1,681 +0,0 @@ - - - - - - - - - - - - - - - - - - - - -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Default - - - - - - - Left to Right - - - - - - - Right to Left - - - - - - - - - - - Default - - - - - - - Left to Right - - - - - - - Right to Left - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Treap/Treap/TreapTests/TreapTests.swift b/Treap/Treap/TreapTests/TreapTests.swift index 5f43a376f..f349e6ab8 100644 --- a/Treap/Treap/TreapTests/TreapTests.swift +++ b/Treap/Treap/TreapTests/TreapTests.swift @@ -25,50 +25,49 @@ THE SOFTWARE.*/ // swiftlint:disable force_try import XCTest -@testable import Treap class TreapTests: XCTestCase { - - override func setUp() { - super.setUp() - // Put setup code here. This method is called before the invocation of each test method in the class. + + override func setUp() { + super.setUp() + // Put setup code here. This method is called before the invocation of each test method in the class. + } + + override func tearDown() { + // Put teardown code here. This method is called after the invocation of each test method in the class. + super.tearDown() + } + + func testSanity() { + var treap = Treap.empty + treap = treap.set(key: 5, val: "a").set(key: 7, val: "b") + XCTAssert(treap.get(5) == "a") + XCTAssert(treap.get(7) == "b") + treap = treap.set(key: 2, val: "c") + XCTAssert(treap.get(2) == "c") + treap = treap.set(key: 2, val: "d") + XCTAssert(treap.get(2) == "d") + treap = try! treap.delete(key: 5) + XCTAssert(!treap.contains(5)) + XCTAssert(treap.contains(7)) + } + + func testFairlyBalanced() { + var treap = Treap.empty + for i in 0..<1000 { + treap = treap.set(key: i, val: nil) } - - override func tearDown() { - // Put teardown code here. This method is called after the invocation of each test method in the class. - super.tearDown() + let depth = treap.depth + XCTAssert(depth < 30, "treap.depth was \(depth)") + } + + func testFairlyBalancedCollection() { + var treap = Treap() + for i in 0..<1000 { + treap[i] = Optional.none } - - func testSanity() { - var treap = Treap.Empty - treap = treap.set(5, val: "a").set(7, val: "b") - XCTAssert(treap.get(5) == "a") - XCTAssert(treap.get(7) == "b") - treap = treap.set(2, val: "c") - XCTAssert(treap.get(2) == "c") - treap = treap.set(2, val: "d") - XCTAssert(treap.get(2) == "d") - treap = try! treap.delete(5) - XCTAssert(!treap.contains(5)) - XCTAssert(treap.contains(7)) - } - - func testFairlyBalanced() { - var treap = Treap.Empty - for i in 0..<1000 { - treap = treap.set(i, val: nil) - } - let depth = treap.depth - XCTAssert(depth < 30, "treap.depth was \(depth)") - } - - func testFairlyBalancedCollection() { - var treap = Treap() - for i in 0..<1000 { - treap[i] = Optional.None - } - let depth = treap.depth - XCTAssert(depth > 0 && depth < 30) - } - + let depth = treap.depth + XCTAssert(depth > 0 && depth < 30) + } + } diff --git a/Treap/TreapCollectionType.swift b/Treap/TreapCollectionType.swift index 36d02eaac..de40464d1 100644 --- a/Treap/TreapCollectionType.swift +++ b/Treap/TreapCollectionType.swift @@ -24,78 +24,88 @@ THE SOFTWARE.*/ import Foundation -extension Treap: MutableCollectionType { - public typealias Index = TreapIndex - - public subscript(index: TreapIndex) -> Element { - get { - guard let result = self.get(index.keys[index.keyIndex]) else { - fatalError("Invalid index!") - } - - return result - } - - mutating set { - let key = index.keys[index.keyIndex] - self = self.set(key, val: newValue) - } +extension Treap: MutableCollection { + + public typealias Index = TreapIndex + + public subscript(index: TreapIndex) -> Element { + get { + guard let result = self.get(index.keys[index.keyIndex]) else { + fatalError("Invalid index!") + } + + return result } - - public subscript(key: Key) -> Element? { - get { - return self.get(key) - } - - mutating set { - guard let value = newValue else { - let _ = try? self.delete(key) - return - } - - self = self.set(key, val: value) - } + + mutating set { + let key = index.keys[index.keyIndex] + self = self.set(key: key, val: newValue) } - - public var startIndex: TreapIndex { - return TreapIndex(keys: keys, keyIndex: 0) + } + + public subscript(key: Key) -> Element? { + get { + return self.get(key) } - - public var endIndex: TreapIndex { - let keys = self.keys - return TreapIndex(keys: keys, keyIndex: keys.count) + + mutating set { + guard let value = newValue else { + let _ = try? self.delete(key: key) + return + } + + self = self.set(key: key, val: value) } - - private var keys: [Key] { - var results: [Key] = [] - if case let .Node(key, _, _, left, right) = self { - results.appendContentsOf(left.keys) - results.append(key) - results.appendContentsOf(right.keys) - } - - return results + } + + public var startIndex: TreapIndex { + return TreapIndex(keys: keys, keyIndex: 0) + } + + public var endIndex: TreapIndex { + let keys = self.keys + return TreapIndex(keys: keys, keyIndex: keys.count) + } + + public func index(after i: TreapIndex) -> TreapIndex { + return i.successor() + } + + fileprivate var keys: [Key] { + var results: [Key] = [] + if case let .node(key, _, _, left, right) = self { + results.append(contentsOf: left.keys) + results.append(key) + results.append(contentsOf: right.keys) } + + return results + } } -public struct TreapIndex: BidirectionalIndexType { - private let keys: [Key] - private let keyIndex: Int - - public func successor() -> TreapIndex { - return TreapIndex(keys: keys, keyIndex: keyIndex + 1) - } - - public func predecessor() -> TreapIndex { - return TreapIndex(keys: keys, keyIndex: keyIndex - 1) - } - - private init(keys: [Key] = [], keyIndex: Int = 0) { - self.keys = keys - self.keyIndex = keyIndex - } +public struct TreapIndex: Comparable { + + public static func <(lhs: TreapIndex, rhs: TreapIndex) -> Bool { + return lhs.keyIndex < rhs.keyIndex + } + + fileprivate let keys: [Key] + fileprivate let keyIndex: Int + + public func successor() -> TreapIndex { + return TreapIndex(keys: keys, keyIndex: keyIndex + 1) + } + + public func predecessor() -> TreapIndex { + return TreapIndex(keys: keys, keyIndex: keyIndex - 1) + } + + fileprivate init(keys: [Key] = [], keyIndex: Int = 0) { + self.keys = keys + self.keyIndex = keyIndex + } } public func ==(lhs: TreapIndex, rhs: TreapIndex) -> Bool { - return lhs.keys == rhs.keys && lhs.keyIndex == rhs.keyIndex + return lhs.keys == rhs.keys && lhs.keyIndex == rhs.keyIndex } diff --git a/Treap/TreapMergeSplit.swift b/Treap/TreapMergeSplit.swift index 277cb40b7..660bd4932 100644 --- a/Treap/TreapMergeSplit.swift +++ b/Treap/TreapMergeSplit.swift @@ -24,93 +24,93 @@ THE SOFTWARE.*/ import Foundation public extension Treap { - internal func split(key: Key) -> (left: Treap, right: Treap) { - var current = self - let val: Element - if let newVal = self.get(key) { - // swiftlint:disable force_try - current = try! current.delete(key) - // swiftlint:enable force_try - val = newVal - } else if case let .Node(_, newVal, _, _, _) = self { - val = newVal - } else { - fatalError("No values in treap") - } - - switch self { - case .Node: - if case let .Node(_, _, _, left, right) = current.set(key, val: val, p: -1) { - return (left: left, right: right) - } else { - return (left: .Empty, right: .Empty) - } - default: - return (left: .Empty, right: .Empty) - } + internal func split(_ key: Key) -> (left: Treap, right: Treap) { + var current = self + let val: Element + if let newVal = self.get(key) { + // swiftlint:disable force_try + current = try! current.delete(key: key) + // swiftlint:enable force_try + val = newVal + } else if case let .node(_, newVal, _, _, _) = self { + val = newVal + } else { + fatalError("No values in treap") } - - internal var leastKey: Key? { - switch self { - case .Empty: - return nil - case let .Node(key, _, _, .Empty, _): - return key - case let .Node(_, _, _, left, _): - return left.leastKey - } + + switch self { + case .node: + if case let .node(_, _, _, left, right) = current.set(key: key, val: val, p: -1) { + return (left: left, right: right) + } else { + return (left: .empty, right: .empty) + } + default: + return (left: .empty, right: .empty) } - - internal var mostKey: Key? { - switch self { - case .Empty: - return nil - case let .Node(key, _, _, _, .Empty): - return key - case let .Node(_, _, _, _, right): - return right.mostKey - } + } + + internal var leastKey: Key? { + switch self { + case .empty: + return nil + case let .node(key, _, _, .empty, _): + return key + case let .node(_, _, _, left, _): + return left.leastKey + } + } + + internal var mostKey: Key? { + switch self { + case .empty: + return nil + case let .node(key, _, _, _, .empty): + return key + case let .node(_, _, _, _, right): + return right.mostKey } + } } -internal func merge(left: Treap, right: Treap) -> Treap { - switch (left, right) { - case (.Empty, _): - return right - case (_, .Empty): - return left - - case let (.Node(leftKey, leftVal, leftP, leftLeft, leftRight), .Node(rightKey, rightVal, rightP, rightLeft, rightRight)): - if leftP < rightP { - return .Node(key: leftKey, val: leftVal, p: leftP, left: leftLeft, right: merge(leftRight, right: right)) - } else { - return .Node(key: rightKey, val: rightVal, p: rightP, left: merge(rightLeft, right: left), right: rightRight) - } - default: - break +internal func merge(_ left: Treap, right: Treap) -> Treap { + switch (left, right) { + case (.empty, _): + return right + case (_, .empty): + return left + + case let (.node(leftKey, leftVal, leftP, leftLeft, leftRight), .node(rightKey, rightVal, rightP, rightLeft, rightRight)): + if leftP < rightP { + return .node(key: leftKey, val: leftVal, p: leftP, left: leftLeft, right: merge(leftRight, right: right)) + } else { + return .node(key: rightKey, val: rightVal, p: rightP, left: merge(rightLeft, right: left), right: rightRight) } - return .Empty + default: + break + } + return .empty } extension Treap: CustomStringConvertible { - public var description: String { - get { - return Treap.descHelper(self, indent: 0) - } + public var description: String { + get { + return Treap.descHelper(self, indent: 0) } - - private static func descHelper(treap: Treap, indent: Int) -> String { - if case let .Node(key, value, priority, left, right) = treap { - var result = "" - let tabs = String(count: indent, repeatedValue: Character("\t")) - - result += descHelper(left, indent: indent + 1) - result += "\n" + tabs + "\(key), \(value), \(priority)\n" - result += descHelper(right, indent: indent + 1) - - return result - } else { - return "" - } + } + + fileprivate static func descHelper(_ treap: Treap, indent: Int) -> String { + if case let .node(key, value, priority, left, right) = treap { + var result = "" + let tabs = String(repeating: "\t", count: indent) + + result += descHelper(left, indent: indent + 1) + result += "\n" + tabs + "\(key), \(value), \(priority)\n" + result += descHelper(right, indent: indent + 1) + + return result + } else { + return "" } + } } From 18c33157976e6d2f010460004ed2a8866243b4f6 Mon Sep 17 00:00:00 2001 From: Jaap Date: Tue, 11 Oct 2016 23:21:10 +0200 Subject: [PATCH 0595/1679] Haversine Distance --- .../Contents.swift | 31 +++++++++++++++++++ .../contents.xcplayground | 4 +++ .../contents.xcworkspacedata | 7 +++++ HaversineDistance/README.md | 23 ++++++++++++++ 4 files changed, 65 insertions(+) create mode 100644 HaversineDistance/HaversineDistance.playground/Contents.swift create mode 100644 HaversineDistance/HaversineDistance.playground/contents.xcplayground create mode 100644 HaversineDistance/HaversineDistance.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 HaversineDistance/README.md diff --git a/HaversineDistance/HaversineDistance.playground/Contents.swift b/HaversineDistance/HaversineDistance.playground/Contents.swift new file mode 100644 index 000000000..f46d7c394 --- /dev/null +++ b/HaversineDistance/HaversineDistance.playground/Contents.swift @@ -0,0 +1,31 @@ + +import UIKit + +func haversineDinstance(la1: Double, lo1: Double, la2: Double, lo2: Double, radius: Double = 6367444.7) -> Double { + + let haversin = { (angle: Double) -> Double in + return (1 - cos(angle))/2 + } + + let ahaversin = { (angle: Double) -> Double in + return 2*asin(sqrt(angle)) + } + + // Converts from degrees to radians + let dToR = { (angle: Double) -> Double in + return (angle / 360) * 2 * M_PI + } + + let lat1 = dToR(la1) + let lon1 = dToR(lo1) + let lat2 = dToR(la2) + let lon2 = dToR(lo2) + + return radius * ahaversin(haversin(lat2 - lat1) + cos(lat1) * cos(lat2) * haversin(lon2 - lon1)) +} + +let amsterdam = (52.3702, 4.8952) +let newYork = (40.7128, -74.0059) + +// 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. +haversineDinstance(la1: amsterdam.0, lo1: amsterdam.1, la2: newYork.0, lo2: newYork.1) diff --git a/HaversineDistance/HaversineDistance.playground/contents.xcplayground b/HaversineDistance/HaversineDistance.playground/contents.xcplayground new file mode 100644 index 000000000..5da2641c9 --- /dev/null +++ b/HaversineDistance/HaversineDistance.playground/contents.xcplayground @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/HaversineDistance/HaversineDistance.playground/playground.xcworkspace/contents.xcworkspacedata b/HaversineDistance/HaversineDistance.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/HaversineDistance/HaversineDistance.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/HaversineDistance/README.md b/HaversineDistance/README.md new file mode 100644 index 000000000..84030cbff --- /dev/null +++ b/HaversineDistance/README.md @@ -0,0 +1,23 @@ +# Haversine Distance + +Calculates the distance on a sphere between two points given in latitude and longitude using the haversine formula. + +The haversine formula can be found on [Wikipedia](https://en.wikipedia.org/wiki/Haversine_formula) + +The Haversine Distance is implemented as a function as a class would be kind of overkill. + +`haversineDinstance(la1: Double, lo1: Double, la2: Double, lo2: Double, radius: Double = 6367444.7) -> Double` + +- `la1` is the latitude of point 1 in degrees. +- `lo1` is the longitude of point 1 in degrees. +- `la2` is the latitude of point 2 in degrees. +- `lo2` is the longitude of point 2 in degrees. +- `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)). + +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. + +1. `haversine` implements the haversine, a trigonometric function. +2. `ahaversine` the inverse function of the haversine. +3. `dToR` a closure converting degrees to radians. + +The result of `haversineDistance` is returned in meters. From 08b9778deb23187d71c7221f04d57a4ba4a1a61d Mon Sep 17 00:00:00 2001 From: Jaap Date: Tue, 11 Oct 2016 23:23:56 +0200 Subject: [PATCH 0596/1679] update readme --- HaversineDistance/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/HaversineDistance/README.md b/HaversineDistance/README.md index 84030cbff..4d5f20e6a 100644 --- a/HaversineDistance/README.md +++ b/HaversineDistance/README.md @@ -21,3 +21,5 @@ The function contains 3 closures in order to make the code more readable and com 3. `dToR` a closure converting degrees to radians. The result of `haversineDistance` is returned in meters. + +*Written for Swift Algorithm Club by Jaap Wijnen.* From 5dc980eec227665710b452013dee0599e278d248 Mon Sep 17 00:00:00 2001 From: Michael Vilabrera Date: Thu, 13 Oct 2016 23:24:39 -0400 Subject: [PATCH 0597/1679] Added Swift Structures to repository list --- README.markdown | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.markdown b/README.markdown index 28a56dfd3..6b9f15a6c 100644 --- a/README.markdown +++ b/README.markdown @@ -10,7 +10,7 @@ The goal of this project is to **explain how algorithms work**. The focus is on All code is compatible with **Xcode 7.3** and **Swift 2.2**. We'll keep this updated with the latest version of Swift. -This is a work in progress. More algorithms will be added soon. :-) +This is a work in progress. More algorithms will be added soon. :-) :heart_eyes: **Suggestions and contributions are welcome!** :heart_eyes: @@ -26,7 +26,7 @@ This is a work in progress. More algorithms will be added soon. :-) [How to contribute](How to Contribute.markdown). Report an issue to leave feedback, or submit a pull request. -[Under construction](Under Construction.markdown). Algorithms that are under construction. +[Under construction](Under Construction.markdown). Algorithms that are under construction. ## Where to start? @@ -210,6 +210,7 @@ Other algorithm repositories: - [@lorentey](https://github.com/lorentey/). Production-quality Swift implementations of common algorithms and data structures. - [Rosetta Code](http://rosettacode.org). Implementations in pretty much any language you can think of. - [AlgorithmVisualizer](http://jasonpark.me/AlgorithmVisualizer/). Visualize algorithms on your browser. +- [Swift Structures](https://github.com/waynewbishop/SwiftStructures) Data Structures with directions on how to use them [here](http://waynewbishop.com/swift) ## Credits From d15c1b824ebdbe33b0d415b72ef193b337fbc01a Mon Sep 17 00:00:00 2001 From: Keita Ito Date: Fri, 14 Oct 2016 11:59:41 -0700 Subject: [PATCH 0598/1679] Fix method name from reverse() to reversed() in README.markdown --- Longest Common Subsequence/README.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Longest Common Subsequence/README.markdown b/Longest Common Subsequence/README.markdown index ba514728a..4cd2c2fcb 100644 --- a/Longest Common Subsequence/README.markdown +++ b/Longest Common Subsequence/README.markdown @@ -152,7 +152,7 @@ func backtrack(_ matrix: [[Int]]) -> String { } } - return String(lcs.characters.reverse()) + return String(lcs.characters.reversed()) } ``` @@ -160,7 +160,7 @@ This backtracks from `matrix[n+1][m+1]` (bottom-right corner) to `matrix[1][1]` 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.) -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.) +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.) ## Putting it all together From 67a2659ac972779ff7d410bcb0783375699cc5d9 Mon Sep 17 00:00:00 2001 From: Eric Yulianto Date: Sun, 16 Oct 2016 01:58:14 +0800 Subject: [PATCH 0599/1679] Migrated Topological Sort to Swift 3 --- .travis.yml | 2 +- Topological Sort/Graph.swift | 2 +- Topological Sort/Tests/Tests.xcodeproj/project.pbxproj | 10 +++++++++- .../xcshareddata/xcschemes/Tests.xcscheme | 2 +- Topological Sort/Tests/TopologicalSortTests.swift | 10 +++++----- .../Topological Sort.playground/Sources/Graph.swift | 2 +- .../Sources/TopologicalSort1.swift | 4 ++-- .../Sources/TopologicalSort3.swift | 8 ++++---- Topological Sort/TopologicalSort1.swift | 4 ++-- Topological Sort/TopologicalSort3.swift | 8 ++++---- 10 files changed, 30 insertions(+), 22 deletions(-) diff --git a/.travis.yml b/.travis.yml index 949fc759f..a495ecde6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -38,4 +38,4 @@ script: # - xcodebuild test -project ./Shortest\ Path\ \(Unweighted\)/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Single-Source\ Shortest\ Paths\ \(Weighted\)/SSSP.xcodeproj -scheme SSSPTests - xcodebuild test -project ./Stack/Tests/Tests.xcodeproj -scheme Tests -# - xcodebuild test -project ./Topological\ Sort/Tests/Tests.xcodeproj -scheme Tests +- xcodebuild test -project ./Topological\ Sort/Tests/Tests.xcodeproj -scheme Tests diff --git a/Topological Sort/Graph.swift b/Topological Sort/Graph.swift index 173676537..1e1be6919 100644 --- a/Topological Sort/Graph.swift +++ b/Topological Sort/Graph.swift @@ -7,7 +7,7 @@ public class Graph: CustomStringConvertible { adjacencyLists = [Node : [Node]]() } - public func addNode(value: Node) -> Node { + public func addNode(_ value: Node) -> Node { adjacencyLists[value] = [] return value } diff --git a/Topological Sort/Tests/Tests.xcodeproj/project.pbxproj b/Topological Sort/Tests/Tests.xcodeproj/project.pbxproj index 83c59dbab..f97ffdc69 100644 --- a/Topological Sort/Tests/Tests.xcodeproj/project.pbxproj +++ b/Topological Sort/Tests/Tests.xcodeproj/project.pbxproj @@ -92,11 +92,12 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; - LastUpgradeCheck = 0720; + LastUpgradeCheck = 0800; ORGANIZATIONNAME = "Swift Algorithm Club"; TargetAttributes = { 7B2BBC7F1C779D720067B71D = { CreatedOnToolsVersion = 7.2; + LastSwiftMigration = 0800; }; }; }; @@ -157,8 +158,10 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; @@ -201,8 +204,10 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; @@ -221,6 +226,7 @@ MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; }; name = Release; }; @@ -232,6 +238,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -243,6 +250,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Release; }; diff --git a/Topological Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Topological Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme index 8ef8d8581..14f27f777 100644 --- a/Topological Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme +++ b/Topological Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -1,6 +1,6 @@ Node { + public func addNode(_ value: Node) -> Node { adjacencyLists[value] = [] return value } diff --git a/Topological Sort/Topological Sort.playground/Sources/TopologicalSort1.swift b/Topological Sort/Topological Sort.playground/Sources/TopologicalSort1.swift index 7f1aca5e7..0f9566f6a 100644 --- a/Topological Sort/Topological Sort.playground/Sources/TopologicalSort1.swift +++ b/Topological Sort/Topological Sort.playground/Sources/TopologicalSort1.swift @@ -1,10 +1,10 @@ extension Graph { - private func depthFirstSearch(source: Node, inout visited: [Node : Bool]) -> [Node] { + private func depthFirstSearch(_ source: Node, visited: inout [Node : Bool]) -> [Node] { var result = [Node]() if let adjacencyList = adjacencyList(forNode: source) { for nodeInAdjacencyList in adjacencyList { - if let seen = visited[nodeInAdjacencyList] where !seen { + if let seen = visited[nodeInAdjacencyList], !seen { result = depthFirstSearch(nodeInAdjacencyList, visited: &visited) + result } } diff --git a/Topological Sort/Topological Sort.playground/Sources/TopologicalSort3.swift b/Topological Sort/Topological Sort.playground/Sources/TopologicalSort3.swift index cdc479b41..3d4a2bbbc 100644 --- a/Topological Sort/Topological Sort.playground/Sources/TopologicalSort3.swift +++ b/Topological Sort/Topological Sort.playground/Sources/TopologicalSort3.swift @@ -12,10 +12,10 @@ extension Graph { visited[node] = false } - func depthFirstSearch(source: Node) { + func depthFirstSearch(_ source: Node) { if let adjacencyList = adjacencyList(forNode: source) { for neighbor in adjacencyList { - if let seen = visited[neighbor] where !seen { + if let seen = visited[neighbor], !seen { depthFirstSearch(neighbor) } } @@ -25,11 +25,11 @@ extension Graph { } for (node, _) in visited { - if let seen = visited[node] where !seen { + if let seen = visited[node], !seen { depthFirstSearch(node) } } - return stack.reverse() + return stack.reversed() } } diff --git a/Topological Sort/TopologicalSort1.swift b/Topological Sort/TopologicalSort1.swift index 7f1aca5e7..0f9566f6a 100644 --- a/Topological Sort/TopologicalSort1.swift +++ b/Topological Sort/TopologicalSort1.swift @@ -1,10 +1,10 @@ extension Graph { - private func depthFirstSearch(source: Node, inout visited: [Node : Bool]) -> [Node] { + private func depthFirstSearch(_ source: Node, visited: inout [Node : Bool]) -> [Node] { var result = [Node]() if let adjacencyList = adjacencyList(forNode: source) { for nodeInAdjacencyList in adjacencyList { - if let seen = visited[nodeInAdjacencyList] where !seen { + if let seen = visited[nodeInAdjacencyList], !seen { result = depthFirstSearch(nodeInAdjacencyList, visited: &visited) + result } } diff --git a/Topological Sort/TopologicalSort3.swift b/Topological Sort/TopologicalSort3.swift index cdc479b41..3d4a2bbbc 100644 --- a/Topological Sort/TopologicalSort3.swift +++ b/Topological Sort/TopologicalSort3.swift @@ -12,10 +12,10 @@ extension Graph { visited[node] = false } - func depthFirstSearch(source: Node) { + func depthFirstSearch(_ source: Node) { if let adjacencyList = adjacencyList(forNode: source) { for neighbor in adjacencyList { - if let seen = visited[neighbor] where !seen { + if let seen = visited[neighbor], !seen { depthFirstSearch(neighbor) } } @@ -25,11 +25,11 @@ extension Graph { } for (node, _) in visited { - if let seen = visited[node] where !seen { + if let seen = visited[node], !seen { depthFirstSearch(node) } } - return stack.reverse() + return stack.reversed() } } From dc2b5ba3c19d9733efa3f97eb450d86fc9fea4ca Mon Sep 17 00:00:00 2001 From: Steven Chen Date: Mon, 17 Oct 2016 15:03:11 -0500 Subject: [PATCH 0600/1679] Update to Swift 3.0 --- Shell Sort/Tests/Tests.xcodeproj/project.pbxproj | 3 +++ Shell Sort/shellsort.swift | 6 +++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Shell Sort/Tests/Tests.xcodeproj/project.pbxproj b/Shell Sort/Tests/Tests.xcodeproj/project.pbxproj index 9f7f4391e..1de1c7213 100644 --- a/Shell Sort/Tests/Tests.xcodeproj/project.pbxproj +++ b/Shell Sort/Tests/Tests.xcodeproj/project.pbxproj @@ -91,6 +91,7 @@ TargetAttributes = { 7B2BBC7F1C779D720067B71D = { CreatedOnToolsVersion = 7.2; + LastSwiftMigration = 0800; }; }; }; @@ -224,6 +225,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -235,6 +237,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Release; }; diff --git a/Shell Sort/shellsort.swift b/Shell Sort/shellsort.swift index 489a92ebc..0740272fc 100644 --- a/Shell Sort/shellsort.swift +++ b/Shell Sort/shellsort.swift @@ -20,8 +20,8 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. -public func insertionSort(inout list: [Int], start: Int, gap: Int) { - for i in (start + gap).stride(to: list.count, by: gap) { +public func insertionSort(_ list: inout [Int], start: Int, gap: Int) { + for i in stride(from: (start + gap), to: list.count, by: gap) { let currentValue = list[i] var pos = i while pos >= gap && list[pos - gap] > currentValue { @@ -32,7 +32,7 @@ public func insertionSort(inout list: [Int], start: Int, gap: Int) { } } -public func shellSort(inout list: [Int]) { +public func shellSort(_ list: inout [Int]) { var sublistCount = list.count / 2 while sublistCount > 0 { for pos in 0.. Date: Mon, 17 Oct 2016 19:58:29 -0500 Subject: [PATCH 0601/1679] Added public init and array init I added a public init so this can be used in a Playground. I also added an extension to create a linked list from an array of values. --- Linked List/LinkedList.playground/Contents.swift | 10 ++++++++++ Linked List/LinkedList.swift | 14 +++++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/Linked List/LinkedList.playground/Contents.swift b/Linked List/LinkedList.playground/Contents.swift index e73f89518..a90b7180c 100644 --- a/Linked List/LinkedList.playground/Contents.swift +++ b/Linked List/LinkedList.playground/Contents.swift @@ -187,6 +187,16 @@ extension LinkedList { } } +extension LinkedList { + convenience init(array: Array) { + self.init() + + for element in array { + self.append(element) + } + } +} + let list = LinkedList() list.isEmpty // true list.first // nil diff --git a/Linked List/LinkedList.swift b/Linked List/LinkedList.swift index 49f1c0915..86d2bca9b 100755 --- a/Linked List/LinkedList.swift +++ b/Linked List/LinkedList.swift @@ -12,7 +12,9 @@ public class LinkedList { public typealias Node = LinkedListNode fileprivate var head: Node? - + + public init() {} + public var isEmpty: Bool { return head == nil } @@ -184,3 +186,13 @@ extension LinkedList { return result } } + +extension LinkedList { + convenience init(array: Array) { + self.init() + + for element in array { + self.append(element) + } + } +} From 133f2d85b0fa188da954c837381570efd263a5ec Mon Sep 17 00:00:00 2001 From: Sahn Cha Date: Tue, 18 Oct 2016 23:35:15 +0900 Subject: [PATCH 0602/1679] Miller-Rabin primality test: probabilistic version --- Miller-Rabin Primality Test/MRPrimality.swift | 61 +++++++++++++++++++ .../contents.xcworkspacedata | 7 +++ 2 files changed, 68 insertions(+) create mode 100644 Miller-Rabin Primality Test/MRPrimality.swift diff --git a/Miller-Rabin Primality Test/MRPrimality.swift b/Miller-Rabin Primality Test/MRPrimality.swift new file mode 100644 index 000000000..8be5ab00d --- /dev/null +++ b/Miller-Rabin Primality Test/MRPrimality.swift @@ -0,0 +1,61 @@ +// +// MRPrimality.swift +// +// +// Created by Sahn Cha on 2016. 10. 18.. +// +// + +import Foundation + +public func mrPrimalityTest(_ n: UInt64, iteration k: Int = 1) -> Bool { + guard n > 2 && n % 2 == 1 else { return false } + + var d = n - 1 + var s = 0 + + while d % 2 == 0 { + d /= 2 + s += 1 + } + + let range = UInt64.max - UInt64.max % (n - 2) + var r: UInt64 = 0 + + repeat { + arc4random_buf(&r, MemoryLayout.size(ofValue: r)) + } while r >= range + + r = r % (n - 2) + 2 + + for _ in 1 ... k { + var x = modpow64(r, d, n) + if x == 1 || x == n - 1 { continue } + + for _ in 1 ... s - 1 { + x = modpow64(x, 2, n) + if x == 1 { return false } + if x == n - 1 { break } + } + + if x != n - 1 { return false } + } + return true +} + +private func modpow64(_ base: UInt64, _ exp: UInt64, _ m: UInt64) -> UInt64 { + if m == 1 { return 0 } + + var result: UInt64 = 1 + var b = base % m + var e = exp + + while e > 0 { + if e % 2 == 1 { + result = (result * b) % m + } + e >>= 1 + b = (b * b) % m + } + return result +} diff --git a/swift-algorithm-club.xcworkspace/contents.xcworkspacedata b/swift-algorithm-club.xcworkspace/contents.xcworkspacedata index e7288f299..fb2aeda4b 100644 --- a/swift-algorithm-club.xcworkspace/contents.xcworkspacedata +++ b/swift-algorithm-club.xcworkspace/contents.xcworkspacedata @@ -25,6 +25,13 @@ + + + + From 902e6f6a4a9ec8780029e1c9f8277f9b86841948 Mon Sep 17 00:00:00 2001 From: Sahn Cha Date: Thu, 20 Oct 2016 02:09:45 +0900 Subject: [PATCH 0603/1679] Now with playground, comments and pesticide --- .../MRPrimality.playground/Contents.swift | 24 ++++ .../Sources/MRPrimality.swift | 111 ++++++++++++++++++ .../contents.xcplayground | 4 + Miller-Rabin Primality Test/MRPrimality.swift | 66 +++++++++-- .../contents.xcworkspacedata | 3 + 5 files changed, 200 insertions(+), 8 deletions(-) create mode 100644 Miller-Rabin Primality Test/MRPrimality.playground/Contents.swift create mode 100644 Miller-Rabin Primality Test/MRPrimality.playground/Sources/MRPrimality.swift create mode 100644 Miller-Rabin Primality Test/MRPrimality.playground/contents.xcplayground diff --git a/Miller-Rabin Primality Test/MRPrimality.playground/Contents.swift b/Miller-Rabin Primality Test/MRPrimality.playground/Contents.swift new file mode 100644 index 000000000..8d97dc409 --- /dev/null +++ b/Miller-Rabin Primality Test/MRPrimality.playground/Contents.swift @@ -0,0 +1,24 @@ +//: Playground - noun: a place where people can play + +// Real primes +mrPrimalityTest(5) +mrPrimalityTest(439) +mrPrimalityTest(1201) +mrPrimalityTest(143477) +mrPrimalityTest(1299869) +mrPrimalityTest(15487361) +mrPrimalityTest(179426363) +mrPrimalityTest(32416187747) + +// Fake primes +mrPrimalityTest(15) +mrPrimalityTest(435) +mrPrimalityTest(1207) +mrPrimalityTest(143473) +mrPrimalityTest(1291869) +mrPrimalityTest(15487161) +mrPrimalityTest(178426363) +mrPrimalityTest(32415187747) + +// With iteration +mrPrimalityTest(32416190071, iteration: 10) \ No newline at end of file diff --git a/Miller-Rabin Primality Test/MRPrimality.playground/Sources/MRPrimality.swift b/Miller-Rabin Primality Test/MRPrimality.playground/Sources/MRPrimality.swift new file mode 100644 index 000000000..9dca23996 --- /dev/null +++ b/Miller-Rabin Primality Test/MRPrimality.playground/Sources/MRPrimality.swift @@ -0,0 +1,111 @@ +// +// MRPrimality.swift +// +// +// Created by Sahn Cha on 2016. 10. 18.. +// +// + +import Foundation + +/* + Miller-Rabin Primality Test. + One of the most used algorithms for primality testing. + Since this is a probabilistic algorithm, it needs to be executed multiple times to increase accuracy. + + Inputs: + n: UInt64 { target integer to be tested for primality } + k: Int { optional. number of iterations } + + Outputs: + true { probably prime } + false { composite } + */ +public func mrPrimalityTest(_ n: UInt64, iteration k: Int = 1) -> Bool { + guard n > 2 && n % 2 == 1 else { return false } + + var d = n - 1 + var s = 0 + + while d % 2 == 0 { + d /= 2 + s += 1 + } + + let range = UInt64.max - UInt64.max % (n - 2) + var r: UInt64 = 0 + repeat { + arc4random_buf(&r, MemoryLayout.size(ofValue: r)) + } while r >= range + + r = r % (n - 2) + 2 + + for _ in 1 ... k { + var x = powmod64(r, d, n) + if x == 1 || x == n - 1 { continue } + + if s == 1 { s = 2 } + + for _ in 1 ... s - 1 { + x = powmod64(x, 2, n) + if x == 1 { return false } + if x == n - 1 { break } + } + + if x != n - 1 { return false } + } + + return true +} + +/* + Calculates (base^exp) mod m. + + Inputs: + base: UInt64 { base } + exp: UInt64 { exponent } + m: UInt64 { modulus } + + Outputs: + the result + */ +private func powmod64(_ base: UInt64, _ exp: UInt64, _ m: UInt64) -> UInt64 { + if m == 1 { return 0 } + + var result: UInt64 = 1 + var b = base % m + var e = exp + + while e > 0 { + if e % 2 == 1 { result = mulmod64(result, b, m) } + b = mulmod64(b, b, m) + e >>= 1 + } + + return result +} + +/* + Calculates (first * second) mod m, hopefully without overflow. :] + + Inputs: + first: UInt64 { first integer } + second: UInt64 { second integer } + m: UInt64 { modulus } + + Outputs: + the result + */ +private func mulmod64(_ first: UInt64, _ second: UInt64, _ m: UInt64) -> UInt64 { + var result: UInt64 = 0 + var a = first + var b = second + + while a != 0 { + if a % 2 == 1 { result = ((result % m) + (b % m)) % m } // This may overflow if 'm' is a 64bit number && both 'result' and 'b' are very close to but smaller than 'm'. + a >>= 1 + b = (b << 1) % m + } + + return result +} diff --git a/Miller-Rabin Primality Test/MRPrimality.playground/contents.xcplayground b/Miller-Rabin Primality Test/MRPrimality.playground/contents.xcplayground new file mode 100644 index 000000000..63b6dd8df --- /dev/null +++ b/Miller-Rabin Primality Test/MRPrimality.playground/contents.xcplayground @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Miller-Rabin Primality Test/MRPrimality.swift b/Miller-Rabin Primality Test/MRPrimality.swift index 8be5ab00d..9dca23996 100644 --- a/Miller-Rabin Primality Test/MRPrimality.swift +++ b/Miller-Rabin Primality Test/MRPrimality.swift @@ -8,6 +8,19 @@ import Foundation +/* + Miller-Rabin Primality Test. + One of the most used algorithms for primality testing. + Since this is a probabilistic algorithm, it needs to be executed multiple times to increase accuracy. + + Inputs: + n: UInt64 { target integer to be tested for primality } + k: Int { optional. number of iterations } + + Outputs: + true { probably prime } + false { composite } + */ public func mrPrimalityTest(_ n: UInt64, iteration k: Int = 1) -> Bool { guard n > 2 && n % 2 == 1 else { return false } @@ -21,7 +34,6 @@ public func mrPrimalityTest(_ n: UInt64, iteration k: Int = 1) -> Bool { let range = UInt64.max - UInt64.max % (n - 2) var r: UInt64 = 0 - repeat { arc4random_buf(&r, MemoryLayout.size(ofValue: r)) } while r >= range @@ -29,21 +41,35 @@ public func mrPrimalityTest(_ n: UInt64, iteration k: Int = 1) -> Bool { r = r % (n - 2) + 2 for _ in 1 ... k { - var x = modpow64(r, d, n) + var x = powmod64(r, d, n) if x == 1 || x == n - 1 { continue } + if s == 1 { s = 2 } + for _ in 1 ... s - 1 { - x = modpow64(x, 2, n) + x = powmod64(x, 2, n) if x == 1 { return false } if x == n - 1 { break } } if x != n - 1 { return false } } + return true } -private func modpow64(_ base: UInt64, _ exp: UInt64, _ m: UInt64) -> UInt64 { +/* + Calculates (base^exp) mod m. + + Inputs: + base: UInt64 { base } + exp: UInt64 { exponent } + m: UInt64 { modulus } + + Outputs: + the result + */ +private func powmod64(_ base: UInt64, _ exp: UInt64, _ m: UInt64) -> UInt64 { if m == 1 { return 0 } var result: UInt64 = 1 @@ -51,11 +77,35 @@ private func modpow64(_ base: UInt64, _ exp: UInt64, _ m: UInt64) -> UInt64 { var e = exp while e > 0 { - if e % 2 == 1 { - result = (result * b) % m - } + if e % 2 == 1 { result = mulmod64(result, b, m) } + b = mulmod64(b, b, m) e >>= 1 - b = (b * b) % m } + + return result +} + +/* + Calculates (first * second) mod m, hopefully without overflow. :] + + Inputs: + first: UInt64 { first integer } + second: UInt64 { second integer } + m: UInt64 { modulus } + + Outputs: + the result + */ +private func mulmod64(_ first: UInt64, _ second: UInt64, _ m: UInt64) -> UInt64 { + var result: UInt64 = 0 + var a = first + var b = second + + while a != 0 { + if a % 2 == 1 { result = ((result % m) + (b % m)) % m } // This may overflow if 'm' is a 64bit number && both 'result' and 'b' are very close to but smaller than 'm'. + a >>= 1 + b = (b << 1) % m + } + return result } diff --git a/swift-algorithm-club.xcworkspace/contents.xcworkspacedata b/swift-algorithm-club.xcworkspace/contents.xcworkspacedata index fb2aeda4b..dd0c6b668 100644 --- a/swift-algorithm-club.xcworkspace/contents.xcworkspacedata +++ b/swift-algorithm-club.xcworkspace/contents.xcworkspacedata @@ -31,6 +31,9 @@ + + Date: Thu, 20 Oct 2016 10:03:44 -0400 Subject: [PATCH 0604/1679] Switched to Double to handle large prime multiplier --- README.markdown | 2 +- Rabin-Karp/README.markdown | 79 ++++++++++++++ .../Rabin-Karp.playground/Contents.swift | 85 +++++++++++++++ .../contents.xcplayground | 4 + .../contents.xcworkspacedata | 7 ++ Rabin-Karp/rabin-karp.swift | 103 ++++++++++++++++++ 6 files changed, 279 insertions(+), 1 deletion(-) create mode 100644 Rabin-Karp/README.markdown create mode 100644 Rabin-Karp/Rabin-Karp.playground/Contents.swift create mode 100644 Rabin-Karp/Rabin-Karp.playground/contents.xcplayground create mode 100644 Rabin-Karp/Rabin-Karp.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 Rabin-Karp/rabin-karp.swift diff --git a/README.markdown b/README.markdown index 28a56dfd3..1bf9e7e6a 100644 --- a/README.markdown +++ b/README.markdown @@ -56,7 +56,7 @@ If you're new to algorithms and data structures, here are a few good ones to sta - [Brute-Force String Search](Brute-Force String Search/). A naive method. - [Boyer-Moore](Boyer-Moore/). A fast method to search for substrings. It skips ahead based on a look-up table, to avoid looking at every character in the text. - Knuth-Morris-Pratt -- Rabin-Karp +- [Rabin-Karp](Rabin-Karp/) Faster search by using hashing. - [Longest Common Subsequence](Longest Common Subsequence/). Find the longest sequence of characters that appear in the same order in both strings. ### Sorting diff --git a/Rabin-Karp/README.markdown b/Rabin-Karp/README.markdown new file mode 100644 index 000000000..0c3d0b1be --- /dev/null +++ b/Rabin-Karp/README.markdown @@ -0,0 +1,79 @@ +# Rabin-Karp string search algorithm + +The Rabin-Karp string search alogrithm is used to search text for a pattern. + +Algorithms that check for palindromes are a common programming interview question. + +## Example + +Given a text of "The big dog jumped over the fox" and a search pattern of "ump" this will return 13. +It starts by hashing "ump" then hashing "The". If hashed don't match then it slides the window a character +at a time (e.g. "he ") and subtracts out the previous hash from the "T". + +## Algorithm + +The Rabin-Karp alogrithm uses a sliding window the size of the search pattern. It starts by hashing the search pattern, then +hashing the first x characters of the text string where x is the length of the search pattern. It then slides the window one character over and uses +the previous hash value to calculate the new hash faster. Only when it finds a hash that matches the hash of the search pattern will it compare +the two strings it see if they are the same (prevent a hash collision from producing a false positive) + +## The code + +The major search method is next. More implementation details are in rabin-karp.swift + +```swift +public func search(text: String , pattern: String) -> Int { + // convert to array of ints + let patternArray = pattern.characters.flatMap { $0.asInt } + let textArray = text.characters.flatMap { $0.asInt } + + if textArray.count < patternArray.count { + return -1 + } + + let patternHash = hash(array: patternArray) + var endIdx = patternArray.count - 1 + let firstChars = Array(textArray[0...endIdx]) + let firstHash = hash(array: firstChars) + + if (patternHash == firstHash) { + // Verify this was not a hash collison + if firstChars == patternArray { + return 0 + } + } + + var prevHash = firstHash + // Now slide the window across the text to be searched + for idx in 1...(textArray.count - patternArray.count) { + endIdx = idx + (patternArray.count - 1) + let window = Array(textArray[idx...endIdx]) + let windowHash = nextHash(prevHash: prevHash, dropped: textArray[idx - 1], added: textArray[endIdx], patternSize: patternArray.count - 1) + + if windowHash == patternHash { + if patternArray == window { + return idx + } + } + + prevHash = windowHash + } + + return -1 +} +``` + +This code can be tested in a playground using the following: + +```swift + search(text: "The big dog jumped"", "ump") +``` + +This will return 13 since ump is in the 13 position of the zero based string. + +## Additional Resources + +[Rabin-Karp Wikipedia](https://en.wikipedia.org/wiki/Rabin%E2%80%93Karp_algorithm) + + +*Written by [Bill Barbour](https://github.com/brbatwork)* \ No newline at end of file diff --git a/Rabin-Karp/Rabin-Karp.playground/Contents.swift b/Rabin-Karp/Rabin-Karp.playground/Contents.swift new file mode 100644 index 000000000..f9c8c1919 --- /dev/null +++ b/Rabin-Karp/Rabin-Karp.playground/Contents.swift @@ -0,0 +1,85 @@ +//: Taking our rabin-karp algorithm for a walk + +import UIKit + +struct Constants { + static let hashMultiplier = 69069 +} + +precedencegroup PowerPrecedence { higherThan: MultiplicationPrecedence } +infix operator ** : PowerPrecedence +func ** (radix: Int, power: Int) -> Int { + return Int(pow(Double(radix), Double(power))) +} +func ** (radix: Double, power: Int) -> Double { + return pow(radix, Double(power)) +} + +extension Character { + var asInt:Int { + let s = String(self).unicodeScalars + return Int(s[s.startIndex].value) + } +} + +// Find first position of pattern in the text using Rabin Karp algorithm +public func search(text: String , pattern: String) -> Int { + // convert to array of ints + let patternArray = pattern.characters.flatMap { $0.asInt } + let textArray = text.characters.flatMap { $0.asInt } + + if textArray.count < patternArray.count { + return -1 + } + + let patternHash = hash(array: patternArray) + var endIdx = patternArray.count - 1 + let firstChars = Array(textArray[0...endIdx]) + let firstHash = hash(array: firstChars) + + if (patternHash == firstHash) { + // Verify this was not a hash collison + if firstChars == patternArray { + return 0 + } + } + + var prevHash = firstHash + // Now slide the window across the text to be searched + for idx in 1...(textArray.count - patternArray.count) { + endIdx = idx + (patternArray.count - 1) + let window = Array(textArray[idx...endIdx]) + let windowHash = nextHash(prevHash: prevHash, dropped: textArray[idx - 1], added: textArray[endIdx], patternSize: patternArray.count - 1) + + if windowHash == patternHash { + if patternArray == window { + return idx + } + } + + prevHash = windowHash + } + + return -1 +} + +public func hash(array: Array) -> Double { + var total : Double = 0 + var exponent = array.count - 1 + for i in array { + total += Double(i) * (Double(Constants.hashMultiplier) ** exponent) + exponent -= 1 + } + + return Double(total) +} + +public func nextHash(prevHash: Double, dropped: Int, added: Int, patternSize: Int) -> Double { + let oldHash = prevHash - (Double(dropped) * (Double(Constants.hashMultiplier) ** patternSize)) + return Double(Constants.hashMultiplier) * oldHash + Double(added) +} + +// TESTS +assert(search(text:"The big dog jumped over the fox", pattern:"ump") == 13, "Invalid index returned") +assert(search(text:"The big dog jumped over the fox", pattern:"missed") == Int(-1), "Invalid index returned") +assert(search(text:"The big dog jumped over the fox", pattern:"T") == 0, "Invalid index returned") diff --git a/Rabin-Karp/Rabin-Karp.playground/contents.xcplayground b/Rabin-Karp/Rabin-Karp.playground/contents.xcplayground new file mode 100644 index 000000000..5da2641c9 --- /dev/null +++ b/Rabin-Karp/Rabin-Karp.playground/contents.xcplayground @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Rabin-Karp/Rabin-Karp.playground/playground.xcworkspace/contents.xcworkspacedata b/Rabin-Karp/Rabin-Karp.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Rabin-Karp/Rabin-Karp.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Rabin-Karp/rabin-karp.swift b/Rabin-Karp/rabin-karp.swift new file mode 100644 index 000000000..54ef24fce --- /dev/null +++ b/Rabin-Karp/rabin-karp.swift @@ -0,0 +1,103 @@ +// The MIT License (MIT) + +// Copyright (c) 2016 Bill Barbour (brbatwork[at]gmail.com) + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +struct Constants { + static let hashMultiplier = 69069 +} + +precedencegroup PowerPrecedence { higherThan: MultiplicationPrecedence } +infix operator ** : PowerPrecedence +func ** (radix: Int, power: Int) -> Int { + return Int(pow(Double(radix), Double(power))) +} +func ** (radix: Double, power: Int) -> Double { + return pow(radix, Double(power)) +} + +extension Character { + var asInt:Int { + let s = String(self).unicodeScalars + return Int(s[s.startIndex].value) + } +} + +// Find first position of pattern in the text using Rabin Karp algorithm +public func search(text: String , pattern: String) -> Int { + // convert to array of ints + let patternArray = pattern.characters.flatMap { $0.asInt } + let textArray = text.characters.flatMap { $0.asInt } + + if textArray.count < patternArray.count { + return -1 + } + + let patternHash = hash(array: patternArray) + var endIdx = patternArray.count - 1 + let firstChars = Array(textArray[0...endIdx]) + let firstHash = hash(array: firstChars) + + if (patternHash == firstHash) { + // Verify this was not a hash collison + if firstChars == patternArray { + return 0 + } + } + + var prevHash = firstHash + // Now slide the window across the text to be searched + for idx in 1...(textArray.count - patternArray.count) { + endIdx = idx + (patternArray.count - 1) + let window = Array(textArray[idx...endIdx]) + let windowHash = nextHash(prevHash: prevHash, dropped: textArray[idx - 1], added: textArray[endIdx], patternSize: patternArray.count - 1) + + if windowHash == patternHash { + if patternArray == window { + return idx + } + } + + prevHash = windowHash + } + + return -1 +} + +public func hash(array: Array) -> Double { + var total : Double = 0 + var exponent = array.count - 1 + for i in array { + total += Double(i) * (Double(Constants.hashMultiplier) ** exponent) + exponent -= 1 + } + + return Double(total) +} + +public func nextHash(prevHash: Double, dropped: Int, added: Int, patternSize: Int) -> Double { + let oldHash = prevHash - (Double(dropped) * (Double(Constants.hashMultiplier) ** patternSize)) + return Double(Constants.hashMultiplier) * oldHash + Double(added) +} + +// TESTS +assert(search(text:"The big dog jumped over the fox", pattern:"ump") == 13, "Invalid index returned") +assert(search(text:"The big dog jumped over the fox", pattern:"missed") == -1, "Invalid index returned") +assert(search(text:"The big dog jumped over the fox", pattern:"T") == 0, "Invalid index returned") \ No newline at end of file From 4813ee12dcd26489ab10176694829a6c1d98c669 Mon Sep 17 00:00:00 2001 From: billbarbour Date: Thu, 20 Oct 2016 11:27:13 -0400 Subject: [PATCH 0605/1679] Corrected copy pasta --- Rabin-Karp/README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Rabin-Karp/README.markdown b/Rabin-Karp/README.markdown index 0c3d0b1be..79699caa8 100644 --- a/Rabin-Karp/README.markdown +++ b/Rabin-Karp/README.markdown @@ -2,7 +2,7 @@ The Rabin-Karp string search alogrithm is used to search text for a pattern. -Algorithms that check for palindromes are a common programming interview question. +A practical application of the algorithm is detecting plagiarism. Given source material, the algorithm can rapidly search through a paper for instances of sentences from the source material, ignoring details such as case and punctuation. Because of the abundance of the sought strings, single-string searching algorithms are impractical. ## Example From 663f902de3b1066c9c8bfc93bdbc05836d05fb02 Mon Sep 17 00:00:00 2001 From: billbarbour Date: Thu, 20 Oct 2016 11:56:09 -0400 Subject: [PATCH 0606/1679] linter cleanup --- .../Rabin-Karp.playground/Contents.swift | 45 ++++++++++++------- Rabin-Karp/rabin-karp.swift | 29 ++++++++---- 2 files changed, 48 insertions(+), 26 deletions(-) diff --git a/Rabin-Karp/Rabin-Karp.playground/Contents.swift b/Rabin-Karp/Rabin-Karp.playground/Contents.swift index f9c8c1919..4956fabe3 100644 --- a/Rabin-Karp/Rabin-Karp.playground/Contents.swift +++ b/Rabin-Karp/Rabin-Karp.playground/Contents.swift @@ -16,70 +16,81 @@ func ** (radix: Double, power: Int) -> Double { } extension Character { - var asInt:Int { + var asInt: Int { let s = String(self).unicodeScalars return Int(s[s.startIndex].value) } } // Find first position of pattern in the text using Rabin Karp algorithm -public func search(text: String , pattern: String) -> Int { +public func search(text: String, pattern: String) -> Int { // convert to array of ints let patternArray = pattern.characters.flatMap { $0.asInt } let textArray = text.characters.flatMap { $0.asInt } - + if textArray.count < patternArray.count { return -1 } - + let patternHash = hash(array: patternArray) var endIdx = patternArray.count - 1 let firstChars = Array(textArray[0...endIdx]) let firstHash = hash(array: firstChars) - - if (patternHash == firstHash) { + + if patternHash == firstHash { // Verify this was not a hash collison if firstChars == patternArray { return 0 } } - + var prevHash = firstHash // Now slide the window across the text to be searched for idx in 1...(textArray.count - patternArray.count) { endIdx = idx + (patternArray.count - 1) let window = Array(textArray[idx...endIdx]) - let windowHash = nextHash(prevHash: prevHash, dropped: textArray[idx - 1], added: textArray[endIdx], patternSize: patternArray.count - 1) - + let windowHash = nextHash( + prevHash: prevHash, + dropped: textArray[idx - 1], + added: textArray[endIdx], + patternSize: patternArray.count - 1 + ) + if windowHash == patternHash { if patternArray == window { return idx } } - + prevHash = windowHash } - + return -1 } public func hash(array: Array) -> Double { - var total : Double = 0 + var total: Double = 0 var exponent = array.count - 1 for i in array { total += Double(i) * (Double(Constants.hashMultiplier) ** exponent) exponent -= 1 } - + return Double(total) } public func nextHash(prevHash: Double, dropped: Int, added: Int, patternSize: Int) -> Double { - let oldHash = prevHash - (Double(dropped) * (Double(Constants.hashMultiplier) ** patternSize)) + let oldHash = prevHash - (Double(dropped) * + (Double(Constants.hashMultiplier) ** patternSize)) return Double(Constants.hashMultiplier) * oldHash + Double(added) } // TESTS -assert(search(text:"The big dog jumped over the fox", pattern:"ump") == 13, "Invalid index returned") -assert(search(text:"The big dog jumped over the fox", pattern:"missed") == Int(-1), "Invalid index returned") -assert(search(text:"The big dog jumped over the fox", pattern:"T") == 0, "Invalid index returned") +assert(search(text:"The big dog jumped over the fox", + pattern:"ump") == 13, "Invalid index returned") + +assert(search(text:"The big dog jumped over the fox", + pattern:"missed") == -1, "Invalid index returned") + +assert(search(text:"The big dog jumped over the fox", + pattern:"T") == 0, "Invalid index returned") diff --git a/Rabin-Karp/rabin-karp.swift b/Rabin-Karp/rabin-karp.swift index 54ef24fce..c337de1a7 100644 --- a/Rabin-Karp/rabin-karp.swift +++ b/Rabin-Karp/rabin-karp.swift @@ -34,14 +34,14 @@ func ** (radix: Double, power: Int) -> Double { } extension Character { - var asInt:Int { + var asInt: Int { let s = String(self).unicodeScalars return Int(s[s.startIndex].value) } } // Find first position of pattern in the text using Rabin Karp algorithm -public func search(text: String , pattern: String) -> Int { +public func search(text: String, pattern: String) -> Int { // convert to array of ints let patternArray = pattern.characters.flatMap { $0.asInt } let textArray = text.characters.flatMap { $0.asInt } @@ -55,7 +55,7 @@ public func search(text: String , pattern: String) -> Int { let firstChars = Array(textArray[0...endIdx]) let firstHash = hash(array: firstChars) - if (patternHash == firstHash) { + if patternHash == firstHash { // Verify this was not a hash collison if firstChars == patternArray { return 0 @@ -67,7 +67,12 @@ public func search(text: String , pattern: String) -> Int { for idx in 1...(textArray.count - patternArray.count) { endIdx = idx + (patternArray.count - 1) let window = Array(textArray[idx...endIdx]) - let windowHash = nextHash(prevHash: prevHash, dropped: textArray[idx - 1], added: textArray[endIdx], patternSize: patternArray.count - 1) + let windowHash = nextHash( + prevHash: prevHash, + dropped: textArray[idx - 1], + added: textArray[endIdx], + patternSize: patternArray.count - 1 + ) if windowHash == patternHash { if patternArray == window { @@ -82,7 +87,7 @@ public func search(text: String , pattern: String) -> Int { } public func hash(array: Array) -> Double { - var total : Double = 0 + var total: Double = 0 var exponent = array.count - 1 for i in array { total += Double(i) * (Double(Constants.hashMultiplier) ** exponent) @@ -93,11 +98,17 @@ public func hash(array: Array) -> Double { } public func nextHash(prevHash: Double, dropped: Int, added: Int, patternSize: Int) -> Double { - let oldHash = prevHash - (Double(dropped) * (Double(Constants.hashMultiplier) ** patternSize)) + let oldHash = prevHash - (Double(dropped) * + (Double(Constants.hashMultiplier) ** patternSize)) return Double(Constants.hashMultiplier) * oldHash + Double(added) } // TESTS -assert(search(text:"The big dog jumped over the fox", pattern:"ump") == 13, "Invalid index returned") -assert(search(text:"The big dog jumped over the fox", pattern:"missed") == -1, "Invalid index returned") -assert(search(text:"The big dog jumped over the fox", pattern:"T") == 0, "Invalid index returned") \ No newline at end of file +assert(search(text:"The big dog jumped over the fox", + pattern:"ump") == 13, "Invalid index returned") + +assert(search(text:"The big dog jumped over the fox", + pattern:"missed") == -1, "Invalid index returned") + +assert(search(text:"The big dog jumped over the fox", + pattern:"T") == 0, "Invalid index returned") From 182e51b1434ea3b8ecc3e94a1c6b5a7d2f21d0fe Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Fri, 21 Oct 2016 01:11:51 -0700 Subject: [PATCH 0607/1679] Updated README to show Slow sort, Karatsuba Manipulation, and Haversine Distance. --- .../KaratsubaMultiplication.playground/Contents.swift | 1 - README.markdown | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Karatsuba Multiplication/KaratsubaMultiplication.playground/Contents.swift b/Karatsuba Multiplication/KaratsubaMultiplication.playground/Contents.swift index 075f75098..bde8fd9f9 100644 --- a/Karatsuba Multiplication/KaratsubaMultiplication.playground/Contents.swift +++ b/Karatsuba Multiplication/KaratsubaMultiplication.playground/Contents.swift @@ -58,4 +58,3 @@ func karatsuba(_ num1: Int, by num2: Int) -> Int { return product } - diff --git a/README.markdown b/README.markdown index 28a56dfd3..2acedd0fa 100644 --- a/README.markdown +++ b/README.markdown @@ -84,6 +84,7 @@ Special-purpose sorts: Bad sorting algorithms (don't use these!): - [Bubble Sort](Bubble Sort/) +- [Slow Sort](Slow Sort/) ### Compression @@ -101,6 +102,7 @@ Bad sorting algorithms (don't use these!): - [Permutations and Combinations](Combinatorics/). Get your combinatorics on! - [Shunting Yard Algorithm](Shunting Yard/). Convert infix expressions to postfix. - Statistics +- [Karatsuba Multiplication](Karatsuba Multiplication/). Another take on elementary multiplication. ### Machine learning From 3947c6bff451b6d8724739ec9d3e157e481249bd Mon Sep 17 00:00:00 2001 From: Jaap Date: Fri, 21 Oct 2016 13:38:55 +0200 Subject: [PATCH 0608/1679] migrate ring buffer to swift 3 --- Ring Buffer/RingBuffer.playground/Contents.swift | 14 +++++++------- .../RingBuffer.playground/timeline.xctimeline | 6 ------ 2 files changed, 7 insertions(+), 13 deletions(-) delete mode 100644 Ring Buffer/RingBuffer.playground/timeline.xctimeline diff --git a/Ring Buffer/RingBuffer.playground/Contents.swift b/Ring Buffer/RingBuffer.playground/Contents.swift index a7522c366..29b9917a0 100644 --- a/Ring Buffer/RingBuffer.playground/Contents.swift +++ b/Ring Buffer/RingBuffer.playground/Contents.swift @@ -1,15 +1,15 @@ //: Playground - noun: a place where people can play public struct RingBuffer { - private var array: [T?] - private var readIndex = 0 - private var writeIndex = 0 + fileprivate var array: [T?] + fileprivate var readIndex = 0 + fileprivate var writeIndex = 0 public init(count: Int) { - array = [T?](count: count, repeatedValue: nil) + array = [T?](repeating: nil, count: count) } - public mutating func write(element: T) -> Bool { + public mutating func write(_ element: T) -> Bool { if !isFull { array[writeIndex % array.count] = element writeIndex += 1 @@ -29,7 +29,7 @@ public struct RingBuffer { } } - private var availableSpaceForReading: Int { + fileprivate var availableSpaceForReading: Int { return writeIndex - readIndex } @@ -37,7 +37,7 @@ public struct RingBuffer { return availableSpaceForReading == 0 } - private var availableSpaceForWriting: Int { + fileprivate var availableSpaceForWriting: Int { return array.count - availableSpaceForReading } diff --git a/Ring Buffer/RingBuffer.playground/timeline.xctimeline b/Ring Buffer/RingBuffer.playground/timeline.xctimeline deleted file mode 100644 index bf468afec..000000000 --- a/Ring Buffer/RingBuffer.playground/timeline.xctimeline +++ /dev/null @@ -1,6 +0,0 @@ - - - - - From 8cb4917968ad3e70bf7f67aca78908f22ecc97cd Mon Sep 17 00:00:00 2001 From: Jaap Date: Fri, 21 Oct 2016 13:45:33 +0200 Subject: [PATCH 0609/1679] migrate two sum problem to swift 3 --- Two-Sum Problem/Solution 1/2Sum.playground/Contents.swift | 2 +- .../Solution 1/2Sum.playground/timeline.xctimeline | 6 ------ Two-Sum Problem/Solution 2/2Sum.playground/Contents.swift | 6 +++--- 3 files changed, 4 insertions(+), 10 deletions(-) delete mode 100644 Two-Sum Problem/Solution 1/2Sum.playground/timeline.xctimeline diff --git a/Two-Sum Problem/Solution 1/2Sum.playground/Contents.swift b/Two-Sum Problem/Solution 1/2Sum.playground/Contents.swift index 11c95b96c..00ce05136 100644 --- a/Two-Sum Problem/Solution 1/2Sum.playground/Contents.swift +++ b/Two-Sum Problem/Solution 1/2Sum.playground/Contents.swift @@ -1,6 +1,6 @@ //: Playground - noun: a place where people can play -func twoSumProblem(a: [Int], k: Int) -> ((Int, Int))? { +func twoSumProblem(_ a: [Int], k: Int) -> ((Int, Int))? { var map = [Int: Int]() for i in 0 ..< a.count { diff --git a/Two-Sum Problem/Solution 1/2Sum.playground/timeline.xctimeline b/Two-Sum Problem/Solution 1/2Sum.playground/timeline.xctimeline deleted file mode 100644 index bf468afec..000000000 --- a/Two-Sum Problem/Solution 1/2Sum.playground/timeline.xctimeline +++ /dev/null @@ -1,6 +0,0 @@ - - - - - diff --git a/Two-Sum Problem/Solution 2/2Sum.playground/Contents.swift b/Two-Sum Problem/Solution 2/2Sum.playground/Contents.swift index 1d6b0a9c8..9a555f0eb 100644 --- a/Two-Sum Problem/Solution 2/2Sum.playground/Contents.swift +++ b/Two-Sum Problem/Solution 2/2Sum.playground/Contents.swift @@ -1,6 +1,6 @@ //: Playground - noun: a place where people can play -func twoSumProblem(a: [Int], k: Int) -> ((Int, Int))? { +func twoSumProblem(_ a: [Int], k: Int) -> ((Int, Int))? { var i = 0 var j = a.count - 1 @@ -9,9 +9,9 @@ func twoSumProblem(a: [Int], k: Int) -> ((Int, Int))? { if sum == k { return (i, j) } else if sum < k { - ++i + i += 1 } else { - --j + j -= 1 } } return nil From 56a5fa6f0273efd3959292977db3d092f0d42524 Mon Sep 17 00:00:00 2001 From: Jaap Date: Fri, 21 Oct 2016 13:46:43 +0200 Subject: [PATCH 0610/1679] Removed duplicate swift files as these were already in the playground itself --- Two-Sum Problem/Solution 1/2Sum.swift | 22 ---------------------- Two-Sum Problem/Solution 2/2Sum.swift | 21 --------------------- 2 files changed, 43 deletions(-) delete mode 100644 Two-Sum Problem/Solution 1/2Sum.swift delete mode 100644 Two-Sum Problem/Solution 2/2Sum.swift diff --git a/Two-Sum Problem/Solution 1/2Sum.swift b/Two-Sum Problem/Solution 1/2Sum.swift deleted file mode 100644 index b3ef54790..000000000 --- a/Two-Sum Problem/Solution 1/2Sum.swift +++ /dev/null @@ -1,22 +0,0 @@ -/* - Determines if there are any entries a[i] + a[j] == k in the array. - Returns a tuple with the indices of the first pair of elements that sum to k. - - Uses a dictionary to store differences between the target and each element. - If any value in the dictionary equals an element in the array, they sum to k. - - This is an O(n) solution. -*/ -func twoSumProblem(a: [Int], k: Int) -> ((Int, Int))? { - var map = [Int: Int]() - - for i in 0 ..< a.count { - if let newK = map[a[i]] { - return (newK, i) - } else { - map[k - a[i]] = i - } - } - - return nil // if empty array or no entries sum to target k -} diff --git a/Two-Sum Problem/Solution 2/2Sum.swift b/Two-Sum Problem/Solution 2/2Sum.swift deleted file mode 100644 index 184e23800..000000000 --- a/Two-Sum Problem/Solution 2/2Sum.swift +++ /dev/null @@ -1,21 +0,0 @@ -/* - Determines if there are any entries a[i] + a[j] == k in the array. - This is an O(n) solution. - The array must be sorted for this to work! -*/ -func twoSumProblem(a: [Int], k: Int) -> ((Int, Int))? { - var i = 0 - var j = a.count - 1 - - while i < j { - let sum = a[i] + a[j] - if sum == k { - return (i, j) - } else if sum < k { - ++i - } else { - --j - } - } - return nil -} From 0227ee1a5ffaec264238cfb1ae21d0779ec12f57 Mon Sep 17 00:00:00 2001 From: Jaap Date: Fri, 21 Oct 2016 13:49:11 +0200 Subject: [PATCH 0611/1679] update readme --- Two-Sum Problem/README.markdown | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Two-Sum Problem/README.markdown b/Two-Sum Problem/README.markdown index e2e15d4c0..a20666efd 100644 --- a/Two-Sum Problem/README.markdown +++ b/Two-Sum Problem/README.markdown @@ -8,10 +8,10 @@ There are a variety of solutions to this problem (some better than others). The This solution uses a dictionary to store differences between each element in the array and the sum `k` that we're looking for. The dictionary also stores the indices of each element. -With this approach, each key in the dictionary corresponds to a new target value. If one of the successive numbers from the array is equal to one of the dictionary's keys, then we know there exist two numbers that sum to `k`. +With this approach, each key in the dictionary corresponds to a new target value. If one of the successive numbers from the array is equal to one of the dictionary's keys, then we know there exist two numbers that sum to `k`. ```swift -func twoSumProblem(a: [Int], k: Int) -> ((Int, Int))? { +func twoSumProblem(_ a: [Int], k: Int) -> ((Int, Int))? { var dict = [Int: Int]() for i in 0 ..< a.count { @@ -69,7 +69,7 @@ The running time of this algorithm is **O(n)** because it potentially may need t Here is the code in Swift: ```swift -func twoSumProblem(a: [Int], k: Int) -> ((Int, Int))? { +func twoSumProblem(_ a: [Int], k: Int) -> ((Int, Int))? { var i = 0 var j = a.count - 1 @@ -78,9 +78,9 @@ func twoSumProblem(a: [Int], k: Int) -> ((Int, Int))? { if sum == k { return (i, j) } else if sum < k { - ++i + i += 1 } else { - --j + j -= 1 } } return nil From 6e281b957a2cee068ee55390dc7baad1f38779c5 Mon Sep 17 00:00:00 2001 From: Jaap Date: Fri, 21 Oct 2016 14:34:50 +0200 Subject: [PATCH 0612/1679] Migrate Graph to Swift3 --- Graph/Graph.playground/Contents.swift | 8 ++--- Graph/Graph.playground/timeline.xctimeline | 11 ++++++ Graph/Graph.xcodeproj/project.pbxproj | 12 ++++++- .../xcshareddata/xcschemes/Graph.xcscheme | 2 +- .../xcschemes/GraphTests.xcscheme | 2 +- Graph/Graph/AdjacencyListGraph.swift | 36 ++++++++++--------- Graph/Graph/AdjacencyMatrixGraph.swift | 26 +++++++------- Graph/Graph/Edge.swift | 4 +-- Graph/Graph/Graph.swift | 18 +++++----- Graph/Graph/Vertex.swift | 2 +- 10 files changed, 70 insertions(+), 51 deletions(-) create mode 100644 Graph/Graph.playground/timeline.xctimeline diff --git a/Graph/Graph.playground/Contents.swift b/Graph/Graph.playground/Contents.swift index 4e6d98a11..77de8484b 100644 --- a/Graph/Graph.playground/Contents.swift +++ b/Graph/Graph.playground/Contents.swift @@ -1,11 +1,7 @@ import Graph -// Create the vertices -var adjacencyMatrixGraph = AdjacencyMatrixGraph() -var adjacencyListGraph = AdjacencyListGraph() - -for graph in [ adjacencyMatrixGraph, adjacencyListGraph ] { - +for graph in [AdjacencyMatrixGraph(), AdjacencyListGraph()] { + let v1 = graph.createVertex(1) let v2 = graph.createVertex(2) let v3 = graph.createVertex(3) diff --git a/Graph/Graph.playground/timeline.xctimeline b/Graph/Graph.playground/timeline.xctimeline new file mode 100644 index 000000000..688276d32 --- /dev/null +++ b/Graph/Graph.playground/timeline.xctimeline @@ -0,0 +1,11 @@ + + + + + + + diff --git a/Graph/Graph.xcodeproj/project.pbxproj b/Graph/Graph.xcodeproj/project.pbxproj index 0157eb377..82a5f2377 100644 --- a/Graph/Graph.xcodeproj/project.pbxproj +++ b/Graph/Graph.xcodeproj/project.pbxproj @@ -158,11 +158,12 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0730; - LastUpgradeCheck = 0730; + LastUpgradeCheck = 0800; ORGANIZATIONNAME = "Swift Algorithm Club"; TargetAttributes = { 49BFA2FC1CDF886B00522D66 = { CreatedOnToolsVersion = 7.3; + LastSwiftMigration = 0800; }; 49BFA3061CDF886B00522D66 = { CreatedOnToolsVersion = 7.3; @@ -250,8 +251,10 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; @@ -298,8 +301,10 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; @@ -319,6 +324,7 @@ MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; @@ -328,6 +334,7 @@ isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_MODULES = YES; + CODE_SIGN_IDENTITY = ""; COMBINE_HIDPI_IMAGES = YES; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; @@ -341,6 +348,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -348,6 +356,7 @@ isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_MODULES = YES; + CODE_SIGN_IDENTITY = ""; COMBINE_HIDPI_IMAGES = YES; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; @@ -360,6 +369,7 @@ PRODUCT_BUNDLE_IDENTIFIER = "com.swift-algorithm-club.Graph"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; + SWIFT_VERSION = 3.0; }; name = Release; }; diff --git a/Graph/Graph.xcodeproj/xcshareddata/xcschemes/Graph.xcscheme b/Graph/Graph.xcodeproj/xcshareddata/xcschemes/Graph.xcscheme index a8ce1124d..c4750d846 100644 --- a/Graph/Graph.xcodeproj/xcshareddata/xcschemes/Graph.xcscheme +++ b/Graph/Graph.xcodeproj/xcshareddata/xcschemes/Graph.xcscheme @@ -1,6 +1,6 @@ { + + +private class EdgeList where T: Equatable, T: Hashable { var vertex: Vertex var edges: [Edge]? = nil @@ -16,15 +18,15 @@ private class EdgeList { self.vertex = vertex } - func addEdge(edge: Edge) { + func addEdge(_ edge: Edge) { edges?.append(edge) } } -public class AdjacencyListGraph: AbstractGraph { +open class AdjacencyListGraph: AbstractGraph where T: Equatable, T: Hashable { - private var adjacencyList: [EdgeList] = [] + fileprivate var adjacencyList: [EdgeList] = [] public required init() { super.init() @@ -34,7 +36,7 @@ public class AdjacencyListGraph: AbstractGrap super.init(fromGraph: graph) } - public override var vertices: [Vertex] { + open override var vertices: [Vertex] { get { var vertices = [Vertex]() for edgeList in adjacencyList { @@ -44,7 +46,7 @@ public class AdjacencyListGraph: AbstractGrap } } - public override var edges: [Edge] { + open override var edges: [Edge] { get { var allEdges = Set>() for edgeList in adjacencyList { @@ -60,7 +62,7 @@ public class AdjacencyListGraph: AbstractGrap } } - public override func createVertex(data: T) -> Vertex { + open override func createVertex(_ data: T) -> Vertex { // check if the vertex already exists let matchingVertices = vertices.filter() { vertex in return vertex.data == data @@ -76,24 +78,24 @@ public class AdjacencyListGraph: AbstractGrap return vertex } - public override func addDirectedEdge(from: Vertex, to: Vertex, withWeight weight: Double?) { + open override func addDirectedEdge(_ from: Vertex, to: Vertex, withWeight weight: Double?) { // works let edge = Edge(from: from, to: to, weight: weight) let edgeList = adjacencyList[from.index] - if edgeList.edges?.count > 0 { - edgeList.addEdge(edge) + if let _ = edgeList.edges { + edgeList.addEdge(edge) } else { - edgeList.edges = [edge] + edgeList.edges = [edge] } } - public override func addUndirectedEdge(vertices: (Vertex, Vertex), withWeight weight: Double?) { + open override func addUndirectedEdge(_ vertices: (Vertex, Vertex), withWeight weight: Double?) { addDirectedEdge(vertices.0, to: vertices.1, withWeight: weight) addDirectedEdge(vertices.1, to: vertices.0, withWeight: weight) } - public override func weightFrom(sourceVertex: Vertex, to destinationVertex: Vertex) -> Double? { + open override func weightFrom(_ sourceVertex: Vertex, to destinationVertex: Vertex) -> Double? { guard let edges = adjacencyList[sourceVertex.index].edges else { return nil } @@ -107,11 +109,11 @@ public class AdjacencyListGraph: AbstractGrap return nil } - public override func edgesFrom(sourceVertex: Vertex) -> [Edge] { + open override func edgesFrom(_ sourceVertex: Vertex) -> [Edge] { return adjacencyList[sourceVertex.index].edges ?? [] } - public override var description: String { + open override var description: String { get { var rows = [String]() for edgeList in adjacencyList { @@ -129,10 +131,10 @@ public class AdjacencyListGraph: AbstractGrap row.append(value) } - rows.append("\(edgeList.vertex.data) -> [\(row.joinWithSeparator(", "))]") + rows.append("\(edgeList.vertex.data) -> [\(row.joined(separator: ", "))]") } - return rows.joinWithSeparator("\n") + return rows.joined(separator: "\n") } } } diff --git a/Graph/Graph/AdjacencyMatrixGraph.swift b/Graph/Graph/AdjacencyMatrixGraph.swift index 6b19bcfcc..8f357bc8c 100644 --- a/Graph/Graph/AdjacencyMatrixGraph.swift +++ b/Graph/Graph/AdjacencyMatrixGraph.swift @@ -7,12 +7,12 @@ import Foundation -public class AdjacencyMatrixGraph: AbstractGraph { +open class AdjacencyMatrixGraph: AbstractGraph where T: Equatable, T: Hashable { // If adjacencyMatrix[i][j] is not nil, then there is an edge from // vertex i to vertex j. - private var adjacencyMatrix: [[Double?]] = [] - private var _vertices: [Vertex] = [] + fileprivate var adjacencyMatrix: [[Double?]] = [] + fileprivate var _vertices: [Vertex] = [] public required init() { super.init() @@ -22,13 +22,13 @@ public class AdjacencyMatrixGraph: AbstractGr super.init(fromGraph: graph) } - public override var vertices: [Vertex] { + open override var vertices: [Vertex] { get { return _vertices } } - public override var edges: [Edge] { + open override var edges: [Edge] { get { var edges = [Edge]() for row in 0 ..< adjacencyMatrix.count { @@ -44,7 +44,7 @@ public class AdjacencyMatrixGraph: AbstractGr // Adds a new vertex to the matrix. // Performance: possibly O(n^2) because of the resizing of the matrix. - public override func createVertex(data: T) -> Vertex { + open override func createVertex(_ data: T) -> Vertex { // check if the vertex already exists let matchingVertices = vertices.filter() { vertex in return vertex.data == data @@ -63,7 +63,7 @@ public class AdjacencyMatrixGraph: AbstractGr } // Add one new row at the bottom. - let newRow = [Double?](count: adjacencyMatrix.count + 1, repeatedValue: nil) + let newRow = [Double?](repeating: nil, count: adjacencyMatrix.count + 1) adjacencyMatrix.append(newRow) _vertices.append(vertex) @@ -71,20 +71,20 @@ public class AdjacencyMatrixGraph: AbstractGr return vertex } - public override func addDirectedEdge(from: Vertex, to: Vertex, withWeight weight: Double?) { + open override func addDirectedEdge(_ from: Vertex, to: Vertex, withWeight weight: Double?) { adjacencyMatrix[from.index][to.index] = weight } - public override func addUndirectedEdge(vertices: (Vertex, Vertex), withWeight weight: Double?) { + open override func addUndirectedEdge(_ vertices: (Vertex, Vertex), withWeight weight: Double?) { addDirectedEdge(vertices.0, to: vertices.1, withWeight: weight) addDirectedEdge(vertices.1, to: vertices.0, withWeight: weight) } - public override func weightFrom(sourceVertex: Vertex, to destinationVertex: Vertex) -> Double? { + open override func weightFrom(_ sourceVertex: Vertex, to destinationVertex: Vertex) -> Double? { return adjacencyMatrix[sourceVertex.index][destinationVertex.index] } - public override func edgesFrom(sourceVertex: Vertex) -> [Edge] { + open override func edgesFrom(_ sourceVertex: Vertex) -> [Edge] { var outEdges = [Edge]() let fromIndex = sourceVertex.index for column in 0..: AbstractGr return outEdges } - public override var description: String { + open override var description: String { get { var grid = [String]() let n = self.adjacencyMatrix.count @@ -111,7 +111,7 @@ public class AdjacencyMatrixGraph: AbstractGr } grid.append(row) } - return (grid as NSArray).componentsJoinedByString("\n") + return (grid as NSArray).componentsJoined(by: "\n") } } diff --git a/Graph/Graph/Edge.swift b/Graph/Graph/Edge.swift index a867e164a..03518da83 100644 --- a/Graph/Graph/Edge.swift +++ b/Graph/Graph/Edge.swift @@ -7,7 +7,7 @@ import Foundation -public struct Edge: Equatable { +public struct Edge: Equatable where T: Equatable, T: Hashable { public let from: Vertex public let to: Vertex @@ -35,7 +35,7 @@ extension Edge: Hashable { get { var string = "\(from.description)\(to.description)" if weight != nil { - string.appendContentsOf("\(weight!)") + string.append("\(weight!)") } return string.hashValue } diff --git a/Graph/Graph/Graph.swift b/Graph/Graph/Graph.swift index 75b4bddec..2ad91608b 100644 --- a/Graph/Graph/Graph.swift +++ b/Graph/Graph/Graph.swift @@ -7,7 +7,7 @@ import Foundation -public class AbstractGraph: CustomStringConvertible { +open class AbstractGraph: CustomStringConvertible where T: Equatable, T: Hashable { public required init() {} @@ -20,19 +20,19 @@ public class AbstractGraph: CustomStringConve } } - public var description: String { + open var description: String { get { fatalError("abstract property accessed") } } - public var vertices: [Vertex] { + open var vertices: [Vertex] { get { fatalError("abstract property accessed") } } - public var edges: [Edge] { + open var edges: [Edge] { get { fatalError("abstract property accessed") } @@ -40,23 +40,23 @@ public class AbstractGraph: CustomStringConve // Adds a new vertex to the matrix. // Performance: possibly O(n^2) because of the resizing of the matrix. - public func createVertex(data: T) -> Vertex { + open func createVertex(_ data: T) -> Vertex { fatalError("abstract function called") } - public func addDirectedEdge(from: Vertex, to: Vertex, withWeight weight: Double?) { + open func addDirectedEdge(_ from: Vertex, to: Vertex, withWeight weight: Double?) { fatalError("abstract function called") } - public func addUndirectedEdge(vertices: (Vertex, Vertex), withWeight weight: Double?) { + open func addUndirectedEdge(_ vertices: (Vertex, Vertex), withWeight weight: Double?) { fatalError("abstract function called") } - public func weightFrom(sourceVertex: Vertex, to destinationVertex: Vertex) -> Double? { + open func weightFrom(_ sourceVertex: Vertex, to destinationVertex: Vertex) -> Double? { fatalError("abstract function called") } - public func edgesFrom(sourceVertex: Vertex) -> [Edge] { + open func edgesFrom(_ sourceVertex: Vertex) -> [Edge] { fatalError("abstract function called") } } diff --git a/Graph/Graph/Vertex.swift b/Graph/Graph/Vertex.swift index 1223eb116..43cabcd1f 100644 --- a/Graph/Graph/Vertex.swift +++ b/Graph/Graph/Vertex.swift @@ -7,7 +7,7 @@ import Foundation -public struct Vertex: Equatable { +public struct Vertex: Equatable where T: Equatable, T: Hashable { public var data: T public let index: Int From 263faef2847eb2249e650138984df56dcb5cb702 Mon Sep 17 00:00:00 2001 From: Sahn Cha Date: Fri, 21 Oct 2016 23:18:42 +0900 Subject: [PATCH 0613/1679] README ready. --- .../Images/img_pseudo.png | Bin 0 -> 149885 bytes Miller-Rabin Primality Test/README.markdown | 43 ++++++++++++++++++ .../contents.xcworkspacedata | 12 ++++- 3 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 Miller-Rabin Primality Test/Images/img_pseudo.png create mode 100644 Miller-Rabin Primality Test/README.markdown diff --git a/Miller-Rabin Primality Test/Images/img_pseudo.png b/Miller-Rabin Primality Test/Images/img_pseudo.png new file mode 100644 index 0000000000000000000000000000000000000000..1a06d151aa90ae0d81fd6c413426357f907d2ae1 GIT binary patch literal 149885 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 a^d, a^(2·d), a^(4·d), ... , a^((2^(s-1))·d), a^((2^s)·d) = a^(n-1) + +And we say the number `n` passes the test, *probably prime*, if 1) `a^d` is congruence to `1` in modulo `n`, or 2) `a^((2^k)·d)` is congruence to `-1` for some `k = 1, 2, ..., s-1`. + +### Pseudo Code + +The following pseudo code is excerpted from Wikipedia[3]: + +![Image of Pseudocode](./Images/img_pseudo.png) + +## Usage + +```swift +mrPrimalityTest(7) // test if 7 is prime. (default iteration = 1) +mrPrimalityTest(7, iteration: 10) // test if 7 is prime & iterate 10 times. +``` + +## Reference +1. G. L. Miller, "Riemann's Hypothesis and Tests for Primality". *J. Comput. System Sci.* 13 (1976), 300-317. +2. M. O. Rabin, "Probabilistic algorithm for testing primality". *Journal of Number Theory.* 12 (1980), 128-138. +3. Miller–Rabin primality test - Wikipedia, the free encyclopedia + +*Written for Swift Algorithm Club by **Sahn Cha**, @scha00* + +[1]: https://cs.uwaterloo.ca/research/tr/1975/CS-75-27.pdf +[2]: http://www.sciencedirect.com/science/article/pii/0022314X80900840 +[3]: https://en.wikipedia.org/wiki/Miller–Rabin_primality_test diff --git a/swift-algorithm-club.xcworkspace/contents.xcworkspacedata b/swift-algorithm-club.xcworkspace/contents.xcworkspacedata index dd0c6b668..75a941c3f 100644 --- a/swift-algorithm-club.xcworkspace/contents.xcworkspacedata +++ b/swift-algorithm-club.xcworkspace/contents.xcworkspacedata @@ -28,11 +28,21 @@ + + + + + + + location = "group:README.markdown"> Date: Fri, 21 Oct 2016 23:25:01 +0900 Subject: [PATCH 0614/1679] Update README.markdown --- Miller-Rabin Primality Test/README.markdown | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Miller-Rabin Primality Test/README.markdown b/Miller-Rabin Primality Test/README.markdown index 9fa849836..84020a9ec 100644 --- a/Miller-Rabin Primality Test/README.markdown +++ b/Miller-Rabin Primality Test/README.markdown @@ -4,9 +4,9 @@ In 1976, Gray Miller introduced an algorithm, through his ph.d thesis[1], which ## Probabilistic -The result of the test is simply a boolean. However, `true` does not implicate *the number is prime*. In fact, it means *the number is **probably** prime*. But `false` does mean *the number is composite*. +The result of the test is simply a boolean. However, `true` does not implicate _the number is prime_. In fact, it means _the number is **probably** prime_. But `false` does mean _the number is composite_. -In order to increase the accuracy of the test, it needs to be iterated few times. If it returns `true` in every single iteration, than we can say with confidence that *the number is pro......bably prime*. +In order to increase the accuracy of the test, it needs to be iterated few times. If it returns `true` in every single iteration, than we can say with confidence that _the number is pro......bably prime_. ## Algorithm @@ -16,7 +16,7 @@ Now make a sequence, in modulo `n`, as following: > a^d, a^(2·d), a^(4·d), ... , a^((2^(s-1))·d), a^((2^s)·d) = a^(n-1) -And we say the number `n` passes the test, *probably prime*, if 1) `a^d` is congruence to `1` in modulo `n`, or 2) `a^((2^k)·d)` is congruence to `-1` for some `k = 1, 2, ..., s-1`. +And we say the number `n` passes the test, _probably prime_, if 1) `a^d` is congruence to `1` in modulo `n`, or 2) `a^((2^k)·d)` is congruence to `-1` for some `k = 1, 2, ..., s-1`. ### Pseudo Code @@ -32,11 +32,11 @@ mrPrimalityTest(7, iteration: 10) // test if 7 is prime & iterate 10 times ``` ## Reference -1. G. L. Miller, "Riemann's Hypothesis and Tests for Primality". *J. Comput. System Sci.* 13 (1976), 300-317. -2. M. O. Rabin, "Probabilistic algorithm for testing primality". *Journal of Number Theory.* 12 (1980), 128-138. +1. G. L. Miller, "Riemann's Hypothesis and Tests for Primality". _J. Comput. System Sci._ 13 (1976), 300-317. +2. M. O. Rabin, "Probabilistic algorithm for testing primality". _Journal of Number Theory._ 12 (1980), 128-138. 3. Miller–Rabin primality test - Wikipedia, the free encyclopedia -*Written for Swift Algorithm Club by **Sahn Cha**, @scha00* +_Written for Swift Algorithm Club by **Sahn Cha**, @scha00_ [1]: https://cs.uwaterloo.ca/research/tr/1975/CS-75-27.pdf [2]: http://www.sciencedirect.com/science/article/pii/0022314X80900840 From a2fa24d380496152dc83eb81c8ec6a10b600878c Mon Sep 17 00:00:00 2001 From: Sahn Cha Date: Fri, 21 Oct 2016 23:34:08 +0900 Subject: [PATCH 0615/1679] typo. --- Miller-Rabin Primality Test/README.markdown | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Miller-Rabin Primality Test/README.markdown b/Miller-Rabin Primality Test/README.markdown index 84020a9ec..07acb9e18 100644 --- a/Miller-Rabin Primality Test/README.markdown +++ b/Miller-Rabin Primality Test/README.markdown @@ -6,11 +6,11 @@ In 1976, Gray Miller introduced an algorithm, through his ph.d thesis[1], which The result of the test is simply a boolean. However, `true` does not implicate _the number is prime_. In fact, it means _the number is **probably** prime_. But `false` does mean _the number is composite_. -In order to increase the accuracy of the test, it needs to be iterated few times. If it returns `true` in every single iteration, than we can say with confidence that _the number is pro......bably prime_. +In order to increase the accuracy of the test, it needs to be iterated few times. If it returns `true` in every single iteration, then we can say with confidence that _the number is pro......bably prime_. ## Algorithm -Let `n` be the given number, and write `n-1` as `2^s·d`, where d is odd. And choose a random number `a` within the range from `2` to `n - 1`. +Let `n` be the given number, and write `n-1` as `2^s·d`, where `d` is odd. And choose a random number `a` within the range from `2` to `n - 1`. Now make a sequence, in modulo `n`, as following: @@ -28,7 +28,7 @@ The following pseudo code is excerpted from Wikipedia[3]: ```swift mrPrimalityTest(7) // test if 7 is prime. (default iteration = 1) -mrPrimalityTest(7, iteration: 10) // test if 7 is prime & iterate 10 times. +mrPrimalityTest(7, iteration: 10) // test if 7 is prime && iterate 10 times. ``` ## Reference From 4c19e5f9091112090b3ec6ce10a0376e1b41abf3 Mon Sep 17 00:00:00 2001 From: Mike Taghavi Date: Sat, 22 Oct 2016 10:43:38 +0200 Subject: [PATCH 0616/1679] Clean up --- Skip-List/SkipList.swift | 78 ++++++++++++++++++++-------------------- 1 file changed, 38 insertions(+), 40 deletions(-) diff --git a/Skip-List/SkipList.swift b/Skip-List/SkipList.swift index 31b4e9144..5fc61bf8e 100644 --- a/Skip-List/SkipList.swift +++ b/Skip-List/SkipList.swift @@ -26,7 +26,7 @@ import Foundation // Stack from : https://github.com/raywenderlich/swift-algorithm-club/tree/master/Stack public struct Stack { - fileprivate var array = [T]() + fileprivate var array: [T] = [] public var isEmpty: Bool { return array.isEmpty @@ -62,53 +62,48 @@ extension Stack: Sequence { private func coinFlip() -> Bool { #if os(Linux) - return random() % 2 == 0 + return random() % 2 == 0 #elseif os(OSX) - return arc4random_uniform(2) == 1 + return arc4random_uniform(2) == 1 #endif } -// MARK: - Node - public class DataNode { public typealias Node = DataNode var data : Payload? fileprivate var key : Key? - internal var next : Node? - internal var down : Node? + var next : Node? + var down : Node? public init(key: Key, data: Payload) { self.key = key self.data = data } - public init(asHead head: Bool){ - } + public init(asHead head: Bool){} } -// MARK: - Skip List - open class SkipList { public typealias Node = DataNode fileprivate(set) var head: Node? - public init() { } + public init() {} } -// MARK: - Searching +// MARK: - Search lanes for a node with a given key extension SkipList { - internal func findNode(key: Key) -> Node? { - var currentNode : Node? = self.head + func findNode(key: Key) -> Node? { + var currentNode : Node? = head var isFound : Bool = false while !isFound { @@ -117,7 +112,7 @@ extension SkipList { switch node.next { case .none: - currentNode = node.down + currentNode = node.down case .some(let value) where value.key != nil: if value.key == key { @@ -149,26 +144,26 @@ extension SkipList { } - internal func search(key: Key) -> Payload? { - guard let node = self.findNode(key: key) else { + func search(key: Key) -> Payload? { + guard let node = findNode(key: key) else { return nil } return node.next!.data } - + } -// MARK: - Inserting +// MARK: - Insert a node into lanes depending on skip list status ( bootstrap base-layer if head is empty / start insertion from current head ). extension SkipList { - private func bootstrapBaseLayer(key: Key, data: Payload) -> Void { - self.head = Node(asHead: true) - var node = Node(key: key, data: data) + private func bootstrapBaseLayer(key: Key, data: Payload) { + head = Node(asHead: true) + var node = Node(key: key, data: data) - self.head!.next = node + head!.next = node var currentTopNode = node @@ -177,17 +172,17 @@ extension SkipList { node = Node(key: key, data: data) node.down = currentTopNode newHead.next = node - newHead.down = self.head - self.head = newHead + newHead.down = head + head = newHead currentTopNode = node } } - private func insertItem(key: Key, data: Payload) -> Void { + private func insertItem(key: Key, data: Payload) { var stack = Stack() - var currentNode: Node? = self.head + var currentNode: Node? = head while currentNode != nil { @@ -219,8 +214,8 @@ extension SkipList { node = Node(key: key, data: data) node.down = currentTopNode newHead.next = node - newHead.down = self.head - self.head = newHead + newHead.down = head + head = newHead currentTopNode = node } else { @@ -236,32 +231,32 @@ extension SkipList { } - internal func insert(key: Key, data: Payload) { - if self.head != nil { - if let node = self.findNode(key: key) { - // replace in case key already exists + func insert(key: Key, data: Payload) { + if head != nil { + if let node = findNode(key: key) { + // replace, in case of key already exists. var currentNode = node.next while currentNode != nil && currentNode!.key == key { currentNode!.data = data currentNode = currentNode!.down } } else { - self.insertItem(key: key, data: data) + insertItem(key: key, data: data) } } else { - self.bootstrapBaseLayer(key: key, data: data) + bootstrapBaseLayer(key: key, data: data) } } } -// MARK: - Removing +// MARK: - Remove a node with a given key. First, find its position in layers at the top, then remove it from each lane by traversing down to the base layer. extension SkipList { - public func remove(key: Key) -> Void { - guard let item = self.findNode(key: key) else { + public func remove(key: Key) { + guard let item = findNode(key: key) else { return } @@ -285,9 +280,12 @@ extension SkipList { } } + +// MARK: - Get associated payload from a node with a given key. + extension SkipList { public func get(key:Key) -> Payload?{ - return self.search(key: key) + return search(key: key) } } From 1de177535f8facdd188464df0c98e50cc5148504 Mon Sep 17 00:00:00 2001 From: Richard Date: Mon, 24 Oct 2016 18:33:25 -0700 Subject: [PATCH 0617/1679] Init & claim of Strassen's Matrix Multiplication Algorithm --- Strassen Matrix Multiplication/README.markdown | 1 + 1 file changed, 1 insertion(+) create mode 100644 Strassen Matrix Multiplication/README.markdown diff --git a/Strassen Matrix Multiplication/README.markdown b/Strassen Matrix Multiplication/README.markdown new file mode 100644 index 000000000..d07004bad --- /dev/null +++ b/Strassen Matrix Multiplication/README.markdown @@ -0,0 +1 @@ +## TODO: Examples & Explanation From 95069fd26cd6c0f5c60f9c980411df72c61ce379 Mon Sep 17 00:00:00 2001 From: Richard Date: Wed, 26 Oct 2016 14:12:39 -0700 Subject: [PATCH 0618/1679] Implementation for Strassen Matrix Multiplication Algorithm --- .../Contents.swift | 316 ++++++++++++++++++ .../contents.xcplayground | 4 + .../contents.xcworkspacedata | 7 + 3 files changed, 327 insertions(+) create mode 100644 Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Contents.swift create mode 100644 Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/contents.xcplayground create mode 100644 Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/playground.xcworkspace/contents.xcworkspacedata diff --git a/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Contents.swift b/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Contents.swift new file mode 100644 index 000000000..d4b4d8330 --- /dev/null +++ b/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Contents.swift @@ -0,0 +1,316 @@ +//: Playground - noun: a place where people can play +// Reference - http://mathworld.wolfram.com/StrassenFormulas.html + + +import UIKit + +enum RowOrColumn { + case row, column +} + +protocol Number: Multipliable, Addable { + static var zero: Self { get } +} + +protocol Addable { + static func +(lhs: Self, rhs: Self) -> Self + static func -(lhs: Self, rhs: Self) -> Self +} + +protocol Multipliable { + static func *(lhs: Self, rhs: Self) -> Self +} + +extension Int: Number { + static var zero: Int { + return 0 + } +} + +extension Double: Number { + static var zero: Double { + return 0.0 + } +} + +extension Float: Number { + static var zero: Float { + return 0.0 + } +} + + +extension Array where Element: Number { + func dot(_ b: Array) -> Element { + let a = self + assert(a.count == b.count, "Can only take the dot product of arrays of the same length!") + let c = a.indices.map{ a[$0] * b[$0] } + return c.reduce(Element.zero, { $0 + $1 }) + } +} + +struct MatrixSize: Equatable { + let rows: Int + let columns: Int + + func forEach(_ body: (Int, Int) throws -> Void) rethrows { + for row in 0.. Bool { + return lhs.columns == rhs.columns && lhs.rows == rhs.rows +} + + +struct Matrix { + + // MARK: - Variables + + let rows: Int, columns: Int + var grid: [T] + + var isSquare: Bool { + return rows == columns + } + + var size: MatrixSize { + return MatrixSize(rows: rows, columns: columns) + } + + // MARK: - Init + + init(rows: Int, columns: Int, initialValue: T = T.zero) { + self.rows = rows + self.columns = columns + self.grid = Array(repeating: initialValue, count: rows * columns) + } + + init(size: Int, initialValue: T = T.zero) { + self.rows = size + self.columns = size + self.grid = Array(repeating: initialValue, count: rows * columns) + } + + // MARK: - Subscript + + subscript(row: Int, column: Int) -> T { + get { + assert(indexIsValid(row: row, column: column), "Index out of range") + return grid[(row * columns) + column] + } + set { + assert(indexIsValid(row: row, column: column), "Index out of range") + grid[(row * columns) + column] = newValue + } + } + + subscript(type: RowOrColumn, value: Int) -> [T] { + get { + switch type { + case .row: + assert(indexIsValid(row: value, column: 0), "Index out of range") + return Array(grid[(value * columns)..<(value * columns) + columns]) + case .column: + assert(indexIsValid(row: 0, column: value), "Index out of range") + var columns: [T] = [] + for row in 0.. Bool { + return row >= 0 && row < rows && column >= 0 && column < columns + } + + private func strassenR(by B: Matrix) -> Matrix { + let A = self + assert(A.isSquare && B.isSquare, "This function requires square matricies!") + guard A.rows > 1 && B.rows > 1 else { return A * B } + + let n = A.rows + let nBy2 = n / 2 + + var a11 = Matrix(size: nBy2) + var a12 = Matrix(size: nBy2) + var a21 = Matrix(size: nBy2) + var a22 = Matrix(size: nBy2) + var b11 = Matrix(size: nBy2) + var b12 = Matrix(size: nBy2) + var b21 = Matrix(size: nBy2) + var b22 = Matrix(size: nBy2) + + for i in 0.. Int { + return Int(pow(2, ceil(log2(Double(n))))) + } + + // MARK: - Functions + + func strassenMatrixMultiply(by B: Matrix) -> Matrix { + let A = self + assert(A.columns == B.rows, "Two matricies can only be matrix mulitiplied if one has dimensions mxn & the other has dimensions nxp where m, n, p are in R") + + let n = max(A.rows, A.columns, B.rows, B.columns) + let m = nextPowerOfTwo(of: n) + + var APrep = Matrix(size: m) + var BPrep = Matrix(size: m) + + A.size.forEach { (i, j) in + APrep[i,j] = A[i,j] + } + + B.size.forEach { (i, j) in + BPrep[i,j] = B[i,j] + } + + let CPrep = APrep.strassenR(by: BPrep) + var C = Matrix(rows: A.rows, columns: B.columns) + + for i in 0..) -> Matrix { + let A = self + assert(A.columns == B.rows, "Two matricies can only be matrix mulitiplied if one has dimensions mxn & the other has dimensions nxp where m, n, p are in R") + + var C = Matrix(rows: A.rows, columns: B.columns) + + for i in 0..(lhs: Matrix, rhs: Matrix) -> Matrix { + assert(lhs.size == rhs.size, "To term-by-term multiply matricies they need to be the same size!") + let rows = lhs.rows + let columns = lhs.columns + + var newMatrix = Matrix(rows: rows, columns: columns) + for row in 0..(lhs: Matrix, rhs: Matrix) -> Matrix { + assert(lhs.size == rhs.size, "To term-by-term add matricies they need to be the same size!") + let rows = lhs.rows + let columns = lhs.columns + + var newMatrix = Matrix(rows: rows, columns: columns) + for row in 0..(lhs: Matrix, rhs: Matrix) -> Matrix { + assert(lhs.size == rhs.size, "To term-by-term subtract matricies they need to be the same size!") + let rows = lhs.rows + let columns = lhs.columns + + var newMatrix = Matrix(rows: rows, columns: columns) + for row in 0.. + + + \ No newline at end of file diff --git a/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/playground.xcworkspace/contents.xcworkspacedata b/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + From 87c23249e572ed9b32191df58cf93d549072463e Mon Sep 17 00:00:00 2001 From: Jaap Date: Thu, 27 Oct 2016 10:47:09 +0200 Subject: [PATCH 0619/1679] update readme --- Ring Buffer/README.markdown | 36 +++++++++++++++++------------------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/Ring Buffer/README.markdown b/Ring Buffer/README.markdown index 70e0ad108..0652ff548 100644 --- a/Ring Buffer/README.markdown +++ b/Ring Buffer/README.markdown @@ -17,7 +17,7 @@ Initially, the array is empty and the read (`r`) and write (`w`) pointers are at Let's add some data to this array. We'll write, or "enqueue", the number `123`: [ 123, , , , ] - r + r ---> w Each time we add data, the write pointer moves one step forward. Let's add a few more elements: @@ -46,7 +46,7 @@ Whoops, the write pointer has reached the end of the array, so there is no more [ 555, 456, 789, 666, 333 ] ---> w r -We can now read the remaining three items, `666`, `333`, and `555`. +We can now read the remaining three items, `666`, `333`, and `555`. [ 555, 456, 789, 666, 333 ] w --------> r @@ -63,16 +63,15 @@ Here is a very basic implementation in Swift: ```swift public struct RingBuffer { - private var array: [T?] - private var readIndex = 0 - private var writeIndex = 0 - + fileprivate var array: [T?] + fileprivate var readIndex = 0 + fileprivate var writeIndex = 0 + public init(count: Int) { - array = [T?](count: count, repeatedValue: nil) + array = [T?](repeating: nil, count: count) } - - /* Returns false if out of space. */ - public mutating func write(element: T) -> Bool { + + public mutating func write(_ element: T) -> Bool { if !isFull { array[writeIndex % array.count] = element writeIndex += 1 @@ -81,8 +80,7 @@ public struct RingBuffer { return false } } - - /* Returns nil if the buffer is empty. */ + public mutating func read() -> T? { if !isEmpty { let element = array[readIndex % array.count] @@ -92,19 +90,19 @@ public struct RingBuffer { return nil } } - - private var availableSpaceForReading: Int { + + fileprivate var availableSpaceForReading: Int { return writeIndex - readIndex } - + public var isEmpty: Bool { return availableSpaceForReading == 0 } - - private var availableSpaceForWriting: Int { + + fileprivate var availableSpaceForWriting: Int { return array.count - availableSpaceForReading } - + public var isFull: Bool { return availableSpaceForWriting == 0 } @@ -130,7 +128,7 @@ In other words, we take the modulo (or the remainder) of the read index and writ The reason this is a bit controversial is that `writeIndex` and `readIndex` always increment, so in theory these values could become too large to fit into an integer and the app will crash. However, a quick back-of-the-napkin calculation should take away those fears. Both `writeIndex` and `readIndex` are 64-bit integers. If we assume that they are incremented 1000 times per second, which is a lot, then doing this continuously for one year requires `ceil(log_2(365 * 24 * 60 * 60 * 1000)) = 35` bits. That leaves 28 bits to spare, so that should give you about 2^28 years before running into problems. That's a long time. :-) - + To play with this ring buffer, copy the code to a playground and do the following to mimic the example above: ```swift From e0547e96c4e11f436b1a4f2a9c6c9cbe2de1fbb5 Mon Sep 17 00:00:00 2001 From: Jaap Date: Thu, 27 Oct 2016 10:55:53 +0200 Subject: [PATCH 0620/1679] update readme --- Graph/README.markdown | 94 +++++++++++++++++++++---------------------- 1 file changed, 46 insertions(+), 48 deletions(-) diff --git a/Graph/README.markdown b/Graph/README.markdown index 349add81a..1ff1a82ac 100644 --- a/Graph/README.markdown +++ b/Graph/README.markdown @@ -42,7 +42,7 @@ Like a tree this does not have any cycles in it (no matter where you start, ther Maybe you're shrugging your shoulders and thinking, what's the big deal? Well, it turns out that graphs are an extremely useful data structure. -If you have some programming problem where you can represent some of your data as vertices and some of it as edges between those vertices, then you can draw your problem as a graph and use well-known graph algorithms such as [breadth-first search](../Breadth-First Search/) or [depth-first search](../Depth-First Search) to find a solution. +If you have some programming problem where you can represent some of your data as vertices and some of it as edges between those vertices, then you can draw your problem as a graph and use well-known graph algorithms such as [breadth-first search](../Breadth-First Search/) or [depth-first search](../Depth-First Search) to find a solution. For example, let's say you have a list of tasks where some tasks have to wait on others before they can begin. You can model this using an acyclic directed graph: @@ -110,12 +110,13 @@ We'll show you sample implementations of both adjacency list and adjacency matri The adjacency list for each vertex consists of `Edge` objects: ```swift -public struct Edge: Equatable { - +public struct Edge: Equatable where T: Equatable, T: Hashable { + public let from: Vertex public let to: Vertex public let weight: Double? + } ``` @@ -124,7 +125,7 @@ This struct describes the "from" and "to" vertices and a weight value. Note that The `Vertex` looks like this: ```swift -public struct Vertex: Equatable { +public struct Vertex: Equatable where T: Equatable, T: Hashable { public var data: T public let index: Int @@ -147,10 +148,7 @@ We can represent it as an adjacency matrix or adjacency list. The classes implem Let's create some directed, weighted graphs, using each representation, to store the example: ```swift -var adjacencyMatrixGraph = AdjacencyMatrixGraph() -var adjacencyListGraph = AdjacencyListGraph() - -for graph in [ adjacencyMatrixGraph, adjacencyListGraph ] { +for graph in [AdjacencyMatrixGraph(), AdjacencyListGraph()] { let v1 = graph.createVertex(1) let v2 = graph.createVertex(2) @@ -163,8 +161,8 @@ for graph in [ adjacencyMatrixGraph, adjacencyListGraph ] { graph.addDirectedEdge(v3, to: v4, withWeight: 4.5) graph.addDirectedEdge(v4, to: v1, withWeight: 2.8) graph.addDirectedEdge(v2, to: v5, withWeight: 3.2) -} +} ``` As mentioned earlier, to create an undirected edge you need to make two directed edges. If we wanted undirected graphs, we'd call this method instead, which takes care of that work for us: @@ -184,7 +182,7 @@ We could provide `nil` as the values for the `withWeight` parameter in either ca To maintain the adjacency list, there is a class that maps a list of edges to a vertex. The graph simply maintains an array of such objects and modifies them as necessary. ```swift -private class EdgeList { +private class EdgeList where T: Equatable, T: Hashable { var vertex: Vertex var edges: [Edge]? = nil @@ -193,34 +191,34 @@ private class EdgeList { self.vertex = vertex } - func addEdge(edge: Edge) { + func addEdge(_ edge: Edge) { edges?.append(edge) } } -``` +``` They are implemented as a class as opposed to structs so we can modify them by reference, in place, like when adding an edge to a new vertex, where the source vertex already has an edge list: ```swift - public override func createVertex(data: T) -> Vertex { - // check if the vertex already exists - let matchingVertices = vertices.filter() { vertex in - return vertex.data == data - } - - if matchingVertices.count > 0 { - return matchingVertices.last! - } - - // if the vertex doesn't exist, create a new one - let vertex = Vertex(data: data, index: adjacencyList.count) - adjacencyList.append(EdgeList(vertex: vertex)) - return vertex +open override func createVertex(_ data: T) -> Vertex { + // check if the vertex already exists + let matchingVertices = vertices.filter() { vertex in + return vertex.data == data + } + + if matchingVertices.count > 0 { + return matchingVertices.last! } + + // if the vertex doesn't exist, create a new one + let vertex = Vertex(data: data, index: adjacencyList.count) + adjacencyList.append(EdgeList(vertex: vertex)) + return vertex +} ``` -The adjacency list for the example looks like this: +The adjacency list for the example looks like this: ``` v1 -> [(v2: 1.0)] @@ -238,32 +236,32 @@ We'll keep track of the adjacency matrix in a two-dimensional `[[Double?]]` arra To index into the matrix using vertices, we use the `index` property in `Vertex`, which is assigned when creating the vertex through the graph object. When creating a new vertex, the graph must resize the matrix: ```swift - public override func createVertex(data: T) -> Vertex { - // check if the vertex already exists - let matchingVertices = vertices.filter() { vertex in - return vertex.data == data - } +open override func createVertex(_ data: T) -> Vertex { + // check if the vertex already exists + let matchingVertices = vertices.filter() { vertex in + return vertex.data == data + } - if matchingVertices.count > 0 { - return matchingVertices.last! - } + if matchingVertices.count > 0 { + return matchingVertices.last! + } - // if the vertex doesn't exist, create a new one - let vertex = Vertex(data: data, index: adjacencyMatrix.count) + // if the vertex doesn't exist, create a new one + let vertex = Vertex(data: data, index: adjacencyMatrix.count) - // Expand each existing row to the right one column. - for i in 0 ..< adjacencyMatrix.count { - adjacencyMatrix[i].append(nil) - } + // Expand each existing row to the right one column. + for i in 0 ..< adjacencyMatrix.count { + adjacencyMatrix[i].append(nil) + } - // Add one new row at the bottom. - let newRow = [Double?](count: adjacencyMatrix.count + 1, repeatedValue: nil) - adjacencyMatrix.append(newRow) + // Add one new row at the bottom. + let newRow = [Double?](repeating: nil, count: adjacencyMatrix.count + 1) + adjacencyMatrix.append(newRow) - _vertices.append(vertex) + _vertices.append(vertex) - return vertex - } + return vertex +} ``` Then the adjacency matrix looks like this: @@ -273,7 +271,7 @@ Then the adjacency matrix looks like this: [nil, nil, nil, 4.5, nil] v3 [2.8, nil, nil, nil, nil] v4 [nil, nil, nil, nil, nil]] v5 - + v1 v2 v3 v4 v5 From 2b64b05087ab0b2014fd0a30fa8bda42f3b32a64 Mon Sep 17 00:00:00 2001 From: Jaap Date: Thu, 27 Oct 2016 16:15:44 +0200 Subject: [PATCH 0621/1679] migrate combinatorics to swift3 --- .../Combinatorics.playground/Contents.swift | 32 ++--- .../timeline.xctimeline | 6 + Combinatorics/Combinatorics.swift | 121 ------------------ Combinatorics/README.markdown | 36 +++--- 4 files changed, 40 insertions(+), 155 deletions(-) create mode 100644 Combinatorics/Combinatorics.playground/timeline.xctimeline delete mode 100644 Combinatorics/Combinatorics.swift diff --git a/Combinatorics/Combinatorics.playground/Contents.swift b/Combinatorics/Combinatorics.playground/Contents.swift index 5cb91967e..94951810f 100644 --- a/Combinatorics/Combinatorics.playground/Contents.swift +++ b/Combinatorics/Combinatorics.playground/Contents.swift @@ -1,7 +1,7 @@ //: Playground - noun: a place where people can play /* Calculates n! */ -func factorial(n: Int) -> Int { +func factorial(_ n: Int) -> Int { var n = n var result = 1 while n > 1 { @@ -20,7 +20,7 @@ factorial(20) Calculates P(n, k), the number of permutations of n distinct symbols in groups of size k. */ -func permutations(n: Int, _ k: Int) -> Int { +func permutations(_ n: Int, _ k: Int) -> Int { var n = n var answer = n for _ in 1..(a: [T], _ n: Int) { +func permuteWirth(_ a: [T], _ n: Int) { if n == 0 { print(a) // display the current permutation } else { @@ -75,7 +75,7 @@ permuteWirth(xyz, 2) Original algorithm by Robert Sedgewick. See also Dr.Dobb's Magazine June 1993, Algorithm Alley */ -func permuteSedgewick(a: [Int], _ n: Int, inout _ pos: Int) { +func permuteSedgewick(_ a: [Int], _ n: Int, _ pos: inout Int) { var a = a pos += 1 a[n] = pos @@ -103,16 +103,16 @@ permuteSedgewick(numbers, 0, &pos) Calculates C(n, k), or "n-choose-k", i.e. how many different selections of size k out of a total number of distinct elements (n) you can make. */ -func combinations(n: Int, _ k: Int) -> Int { +func combinations(_ n: Int, choose k: Int) -> Int { return permutations(n, k) / factorial(k) } -combinations(3, 2) -combinations(28, 5) +combinations(3, choose: 2) +combinations(28, choose: 5) print("\nCombinations:") for i in 1...20 { - print("\(20)-choose-\(i) = \(combinations(20, i))") + print("\(20)-choose-\(i) = \(combinations(20, choose: i))") } @@ -121,7 +121,7 @@ for i in 1...20 { Calculates C(n, k), or "n-choose-k", i.e. the number of ways to choose k things out of n possibilities. */ -func quickBinomialCoefficient(n: Int, _ k: Int) -> Int { +func quickBinomialCoefficient(_ n: Int, choose k: Int) -> Int { var result = 1 for i in 0.. Int { return result } -quickBinomialCoefficient(8, 2) -quickBinomialCoefficient(30, 15) +quickBinomialCoefficient(8, choose: 2) +quickBinomialCoefficient(30, choose: 15) @@ -145,7 +145,7 @@ struct Array2D { init(columns: Int, rows: Int, initialValue: T) { self.columns = columns self.rows = rows - array = .init(count: rows*columns, repeatedValue: initialValue) + array = Array(repeating: initialValue, count: rows*columns) } subscript(column: Int, row: Int) -> T { @@ -163,8 +163,8 @@ struct Array2D { space for the cached values. */ -func binomialCoefficient(n: Int, _ k: Int) -> Int { - var bc = Array(count: n + 1, repeatedValue: Array(count: n + 1, repeatedValue: 0)) +func binomialCoefficient(_ n: Int, choose k: Int) -> Int { + var bc = Array(repeating: Array(repeating: 0, count: n + 1), count: n + 1) for i in 0...n { bc[i][0] = 1 @@ -182,5 +182,5 @@ func binomialCoefficient(n: Int, _ k: Int) -> Int { return bc[n][k] } -binomialCoefficient(30, 15) -binomialCoefficient(66, 33) +binomialCoefficient(30, choose: 15) +binomialCoefficient(66, choose: 33) diff --git a/Combinatorics/Combinatorics.playground/timeline.xctimeline b/Combinatorics/Combinatorics.playground/timeline.xctimeline new file mode 100644 index 000000000..bf468afec --- /dev/null +++ b/Combinatorics/Combinatorics.playground/timeline.xctimeline @@ -0,0 +1,6 @@ + + + + + diff --git a/Combinatorics/Combinatorics.swift b/Combinatorics/Combinatorics.swift deleted file mode 100644 index 04ef98765..000000000 --- a/Combinatorics/Combinatorics.swift +++ /dev/null @@ -1,121 +0,0 @@ -/* Calculates n! */ -func factorial(n: Int) -> Int { - var n = n - var result = 1 - while n > 1 { - result *= n - n -= 1 - } - return result -} - -/* - Calculates P(n, k), the number of permutations of n distinct symbols - in groups of size k. - */ -func permutations(n: Int, _ k: Int) -> Int { - var n = n - var answer = n - for _ in 1..(a: [T], _ n: Int) { - if n == 0 { - print(a) // display the current permutation - } else { - var a = a - permuteWirth(a, n - 1) - for i in 0.. Int { - return permutations(n, k) / factorial(k) -} - -/* - Calculates C(n, k), or "n-choose-k", i.e. the number of ways to choose - k things out of n possibilities. - */ -func quickBinomialCoefficient(n: Int, _ k: Int) -> Int { - var result = 1 - - for i in 0.. Int { - var bc = Array(count: n + 1, repeatedValue: Array(count: n + 1, repeatedValue: 0)) - - for i in 0...n { - bc[i][0] = 1 - bc[i][i] = 1 - } - - if n > 0 { - for i in 1...n { - for j in 1.. Int { +func factorial(_ n: Int) -> Int { var n = n var result = 1 while n > 1 { @@ -62,7 +62,7 @@ You could implement this in terms of the `factorial()` function from earlier, bu Here is an algorithm that can deal with larger numbers: ```swift -func permutations(n: Int, _ k: Int) -> Int { +func permutations(_ n: Int, _ k: Int) -> Int { var n = n var answer = n for _ in 1..(a: [T], _ n: Int) { +func permuteWirth(_ a: [T], _ n: Int) { if n == 0 { print(a) // display the current permutation } else { @@ -216,7 +216,7 @@ If the above is still not entirely clear, then I suggest you give it a go in the For fun, here is an alternative algorithm, by Robert Sedgewick: ```swift -func permuteSedgewick(a: [Int], _ n: Int, inout _ pos: Int) { +func permuteSedgewick(_ a: [Int], _ n: Int, _ pos: inout Int) { var a = a pos += 1 a[n] = pos @@ -282,7 +282,7 @@ The formula for `C(n, k)` is: As you can see, you can derive it from the formula for `P(n, k)`. There are always more permutations than combinations. You divide the number of permutations by `k!` because a total of `k!` of these permutations give the same combination. -Above I showed that the number of permutations of `k` `l` `m` is 6, but if you pick only two of those letters the number of combinations is 3. If we use the formula we should get the same answer. We want to calculate `C(3, 2)` because we choose 2 letters out of a collection of 3. +Above I showed that the number of permutations of `k` `l` `m` is 6, but if you pick only two of those letters the number of combinations is 3. If we use the formula we should get the same answer. We want to calculate `C(3, 2)` because we choose 2 letters out of a collection of 3. 3 * 2 * 1 6 C(3, 2) = --------- = --- = 3 @@ -291,7 +291,7 @@ Above I showed that the number of permutations of `k` `l` `m` is 6, but if you p Here's a simple function to calculate `C(n, k)`: ```swift -func combinations(n: Int, _ k: Int) -> Int { +func combinations(_ n: Int, choose k: Int) -> Int { return permutations(n, k) / factorial(k) } ``` @@ -299,7 +299,7 @@ func combinations(n: Int, _ k: Int) -> Int { Use it like this: ```swift -combinations(28, 5) // prints 98280 +combinations(28, choose: 5) // prints 98280 ``` Because this uses the `permutations()` and `factorial()` functions under the hood, you're still limited by how large these numbers can get. For example, `combinations(30, 15)` is "only" `155,117,520` but because the intermediate results don't fit into a 64-bit integer, you can't calculate it with the given function. @@ -319,7 +319,7 @@ After the reduction of fractions, we get the following formula: We can implement this formula as follows: ```swift -func quickBinomialCoefficient(n: Int, _ k: Int) -> Int { +func quickBinomialCoefficient(_ n: Int, choose k: Int) -> Int { var result = 1 for i in 0.. Int { - var bc = Array(count: n + 1, repeatedValue: Array(count: n + 1, repeatedValue: 0)) +func binomialCoefficient(_ n: Int, choose k: Int) -> Int { + var bc = Array(repeating: Array(repeating: 0, count: n + 1), count: n + 1) for i in 0...n { bc[i][0] = 1 @@ -390,7 +390,7 @@ The algorithm itself is quite simple: the first loop fills in the 1s at the oute Now you can calculate `C(66, 33)` without any problems: ```swift -binomialCoefficient(66, 33) // prints a very large number +binomialCoefficient(66, choose: 33) // prints a very large number ``` You may wonder what the point is in calculating these permutations and combinations, but many algorithm problems are really combinatorics problems in disguise. Often you may need to look at all possible combinations of your data to see which one gives the right solution. If that means you need to search through `n!` potential solutions, you may want to consider a different approach -- as you've seen, these numbers become huge very quickly! From b15b38396a262291bee0b5db407d09eba3833148 Mon Sep 17 00:00:00 2001 From: Jaap Date: Thu, 27 Oct 2016 16:38:11 +0200 Subject: [PATCH 0622/1679] migrate fixedsizearray to swift3 --- .../FixedSizeArray.playground/Contents.swift | 56 ++++++++++++++ .../contents.xcplayground | 4 + .../contents.xcworkspacedata | 7 ++ .../timeline.xctimeline | 16 ++++ Fixed Size Array/FixedSizeArray.swift | 46 ----------- Fixed Size Array/README.markdown | 77 ++++++++++--------- 6 files changed, 125 insertions(+), 81 deletions(-) create mode 100644 Fixed Size Array/FixedSizeArray.playground/Contents.swift create mode 100644 Fixed Size Array/FixedSizeArray.playground/contents.xcplayground create mode 100644 Fixed Size Array/FixedSizeArray.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 Fixed Size Array/FixedSizeArray.playground/timeline.xctimeline delete mode 100644 Fixed Size Array/FixedSizeArray.swift diff --git a/Fixed Size Array/FixedSizeArray.playground/Contents.swift b/Fixed Size Array/FixedSizeArray.playground/Contents.swift new file mode 100644 index 000000000..663050d31 --- /dev/null +++ b/Fixed Size Array/FixedSizeArray.playground/Contents.swift @@ -0,0 +1,56 @@ +//: Playground - noun: a place where people can play + +/* + An unordered array with a maximum size. + + Performance is always O(1). + */ +struct FixedSizeArray { + private var maxSize: Int + private var defaultValue: T + private var array: [T] + private (set) var count = 0 + + init(maxSize: Int, defaultValue: T) { + self.maxSize = maxSize + self.defaultValue = defaultValue + self.array = [T](repeating: defaultValue, count: maxSize) + } + + subscript(index: Int) -> T { + assert(index >= 0) + assert(index < count) + return array[index] + } + + mutating func append(newElement: T) { + assert(count < maxSize) + array[count] = newElement + count += 1 + } + + mutating func removeAtIndex(index: Int) -> T { + assert(index >= 0) + assert(index < count) + count -= 1 + let result = array[index] + array[index] = array[count] + array[count] = defaultValue + return result + } + + mutating func removeAll() { + for i in 0.. + + + \ No newline at end of file diff --git a/Fixed Size Array/FixedSizeArray.playground/playground.xcworkspace/contents.xcworkspacedata b/Fixed Size Array/FixedSizeArray.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Fixed Size Array/FixedSizeArray.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Fixed Size Array/FixedSizeArray.playground/timeline.xctimeline b/Fixed Size Array/FixedSizeArray.playground/timeline.xctimeline new file mode 100644 index 000000000..def6161e4 --- /dev/null +++ b/Fixed Size Array/FixedSizeArray.playground/timeline.xctimeline @@ -0,0 +1,16 @@ + + + + + + + + + diff --git a/Fixed Size Array/FixedSizeArray.swift b/Fixed Size Array/FixedSizeArray.swift deleted file mode 100644 index 270222230..000000000 --- a/Fixed Size Array/FixedSizeArray.swift +++ /dev/null @@ -1,46 +0,0 @@ -/* - An unordered array with a maximum size. - - Performance is always O(1). -*/ -struct FixedSizeArray { - private var maxSize: Int - private var defaultValue: T - private var array: [T] - private (set) var count = 0 - - init(maxSize: Int, defaultValue: T) { - self.maxSize = maxSize - self.defaultValue = defaultValue - self.array = [T](count: maxSize, repeatedValue: defaultValue) - } - - subscript(index: Int) -> T { - assert(index >= 0) - assert(index < count) - return array[index] - } - - mutating func append(newElement: T) { - assert(count < maxSize) - array[count] = newElement - count += 1 - } - - mutating func removeAtIndex(index: Int) -> T { - assert(index >= 0) - assert(index < count) - count -= 1 - let result = array[index] - array[index] = array[count] - array[count] = defaultValue - return result - } - - mutating func removeAll() { - for i in 0.. { - private var maxSize: Int - private var defaultValue: T - private var array: [T] - private (set) var count = 0 - - init(maxSize: Int, defaultValue: T) { - self.maxSize = maxSize - self.defaultValue = defaultValue - self.array = [T](count: maxSize, repeatedValue: defaultValue) - } - - subscript(index: Int) -> T { - assert(index >= 0) - assert(index < count) - return array[index] - } - - mutating func append(newElement: T) { - assert(count < maxSize) - array[count] = newElement - count += 1 - } - - mutating func removeAtIndex(index: Int) -> T { - assert(index >= 0) - assert(index < count) - count -= 1 - let result = array[index] - array[index] = array[count] - array[count] = defaultValue - return result - } + private var maxSize: Int + private var defaultValue: T + private var array: [T] + private (set) var count = 0 + + init(maxSize: Int, defaultValue: T) { + self.maxSize = maxSize + self.defaultValue = defaultValue + self.array = [T](repeating: defaultValue, count: maxSize) + } + + subscript(index: Int) -> T { + assert(index >= 0) + assert(index < count) + return array[index] + } + + mutating func append(newElement: T) { + assert(count < maxSize) + array[count] = newElement + count += 1 + } + + mutating func removeAtIndex(index: Int) -> T { + assert(index >= 0) + assert(index < count) + count -= 1 + let result = array[index] + array[index] = array[count] + array[count] = defaultValue + return result + } + + mutating func removeAll() { + for i in 0.. Date: Fri, 28 Oct 2016 12:44:05 -0700 Subject: [PATCH 0623/1679] Added File implementations --- Strassen Matrix Multiplication/Matrix.swift | 9 +++++++++ Strassen Matrix Multiplication/MatrixSize.swift | 9 +++++++++ Strassen Matrix Multiplication/Number.swift | 9 +++++++++ 3 files changed, 27 insertions(+) create mode 100644 Strassen Matrix Multiplication/Matrix.swift create mode 100644 Strassen Matrix Multiplication/MatrixSize.swift create mode 100644 Strassen Matrix Multiplication/Number.swift diff --git a/Strassen Matrix Multiplication/Matrix.swift b/Strassen Matrix Multiplication/Matrix.swift new file mode 100644 index 000000000..493e27e06 --- /dev/null +++ b/Strassen Matrix Multiplication/Matrix.swift @@ -0,0 +1,9 @@ +// +// Matrix.swift +// +// +// Created by Richard Ash on 10/28/16. +// +// + +import Foundation diff --git a/Strassen Matrix Multiplication/MatrixSize.swift b/Strassen Matrix Multiplication/MatrixSize.swift new file mode 100644 index 000000000..a01123f3c --- /dev/null +++ b/Strassen Matrix Multiplication/MatrixSize.swift @@ -0,0 +1,9 @@ +// +// MatrixSize.swift +// +// +// Created by Richard Ash on 10/28/16. +// +// + +import Foundation diff --git a/Strassen Matrix Multiplication/Number.swift b/Strassen Matrix Multiplication/Number.swift new file mode 100644 index 000000000..1bd6cf634 --- /dev/null +++ b/Strassen Matrix Multiplication/Number.swift @@ -0,0 +1,9 @@ +// +// Number.swift +// +// +// Created by Richard Ash on 10/28/16. +// +// + +import Foundation From bf24ad0267c3cc6371f61450a9ada56aee1076cc Mon Sep 17 00:00:00 2001 From: TheIronBorn Date: Fri, 28 Oct 2016 23:33:46 -0700 Subject: [PATCH 0624/1679] fix for Swift 3 --- Shuffle/README.markdown | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Shuffle/README.markdown b/Shuffle/README.markdown index e0be6c1e4..ced138572 100644 --- a/Shuffle/README.markdown +++ b/Shuffle/README.markdown @@ -12,7 +12,7 @@ extension Array { var temp = [Element]() while !isEmpty { let i = random(count) - let obj = removeAtIndex(i) + let obj = remove(at: i) temp.append(obj) } self = temp @@ -44,7 +44,7 @@ Here is a much improved version of the shuffle algorithm: ```swift extension Array { public mutating func shuffle() { - for i in (count - 1).stride(through: 1, by: -1) { + for i in stride(from: count - 1, through: 1, by: -1) { let j = random(i + 1) if i != j { swap(&self[i], &self[j]) @@ -96,8 +96,8 @@ There is a slight variation on this algorithm that is useful for when you want t Here is the code: ```swift -public func shuffledArray(n: Int) -> [Int] { - var a = [Int](count: n, repeatedValue: 0) +public func shuffledArray(_ n: Int) -> [Int] { + var a = [Int](repeating: 0, count: n) for i in 0.. Date: Fri, 28 Oct 2016 23:38:01 -0700 Subject: [PATCH 0625/1679] fix for Swift 3 --- Shuffle/Shuffle.playground/Contents.swift | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Shuffle/Shuffle.playground/Contents.swift b/Shuffle/Shuffle.playground/Contents.swift index a12086548..e6d4f000d 100644 --- a/Shuffle/Shuffle.playground/Contents.swift +++ b/Shuffle/Shuffle.playground/Contents.swift @@ -3,7 +3,7 @@ import Foundation /* Returns a random integer between 0 and n-1. */ -public func random(n: Int) -> Int { +public func random(_ n: Int) -> Int { return Int(arc4random_uniform(UInt32(n))) } @@ -12,7 +12,7 @@ public func random(n: Int) -> Int { /* Fisher-Yates / Knuth shuffle */ extension Array { public mutating func shuffle() { - for i in (count - 1).stride(through: 1, by: -1) { + for i in stride(from: count - 1, through: 1, by: -1) { let j = random(i + 1) if i != j { swap(&self[i], &self[j]) @@ -29,8 +29,8 @@ list.shuffle() /* Create a new array of numbers that is already shuffled. */ -public func shuffledArray(n: Int) -> [Int] { - var a = [Int](count: n, repeatedValue: 0) +public func shuffledArray(_ n: Int) -> [Int] { + var a = [Int](repeating: 0, count: n) for i in 0.. Date: Mon, 31 Oct 2016 00:29:56 -0700 Subject: [PATCH 0626/1679] Added HaversineDistance to front page. --- README.markdown | 1 + 1 file changed, 1 insertion(+) diff --git a/README.markdown b/README.markdown index 2acedd0fa..bc0dbf21d 100644 --- a/README.markdown +++ b/README.markdown @@ -103,6 +103,7 @@ Bad sorting algorithms (don't use these!): - [Shunting Yard Algorithm](Shunting Yard/). Convert infix expressions to postfix. - Statistics - [Karatsuba Multiplication](Karatsuba Multiplication/). Another take on elementary multiplication. +- [Haversine Distance](HaversineDistance/). Calculating the distance between 2 points from a sphere. ### Machine learning From 8328491307b7850c1fd6eb6d50a279fc195ed075 Mon Sep 17 00:00:00 2001 From: Jaap Date: Mon, 31 Oct 2016 20:34:34 +0100 Subject: [PATCH 0627/1679] migratehashsetswift3 --- Hash Set/HashSet.playground/Contents.swift | 72 ------------ .../HashSet.playground/Sources/HashSet.swift | 76 +++++++++++++ Hash Set/README.markdown | 104 +++++++++--------- 3 files changed, 130 insertions(+), 122 deletions(-) create mode 100644 Hash Set/HashSet.playground/Sources/HashSet.swift diff --git a/Hash Set/HashSet.playground/Contents.swift b/Hash Set/HashSet.playground/Contents.swift index 636d4d925..551c6dc86 100644 --- a/Hash Set/HashSet.playground/Contents.swift +++ b/Hash Set/HashSet.playground/Contents.swift @@ -1,33 +1,5 @@ //: Playground - noun: a place where people can play -public struct HashSet { - private var dictionary = Dictionary() - - public mutating func insert(element: T) { - dictionary[element] = true - } - - public mutating func remove(element: T) { - dictionary[element] = nil - } - - public func contains(element: T) -> Bool { - return dictionary[element] != nil - } - - public func allElements() -> [T] { - return Array(dictionary.keys) - } - - public var count: Int { - return dictionary.count - } - - public var isEmpty: Bool { - return dictionary.isEmpty - } -} - var set = HashSet() set.insert("one") @@ -43,24 +15,8 @@ set.remove("one") set.allElements() set.contains("one") - - /* Union */ -extension HashSet { - public func union(otherSet: HashSet) -> HashSet { - var combined = HashSet() - for obj in dictionary.keys { - combined.insert(obj) - } - for obj in otherSet.dictionary.keys { - combined.insert(obj) - } - return combined - } -} - - var setA = HashSet() setA.insert(1) setA.insert(2) @@ -76,41 +32,13 @@ setB.insert(6) let union = setA.union(setB) union.allElements() // [5, 6, 2, 3, 1, 4] - - /* Intersection */ -extension HashSet { - public func intersect(otherSet: HashSet) -> HashSet { - var common = HashSet() - for obj in dictionary.keys { - if otherSet.contains(obj) { - common.insert(obj) - } - } - return common - } -} - let intersection = setA.intersect(setB) intersection.allElements() // [3, 4] - - /* Difference */ -extension HashSet { - public func difference(otherSet: HashSet) -> HashSet { - var diff = HashSet() - for obj in dictionary.keys { - if !otherSet.contains(obj) { - diff.insert(obj) - } - } - return diff - } -} - let difference1 = setA.difference(setB) difference1.allElements() // [2, 1] diff --git a/Hash Set/HashSet.playground/Sources/HashSet.swift b/Hash Set/HashSet.playground/Sources/HashSet.swift new file mode 100644 index 000000000..c3365110b --- /dev/null +++ b/Hash Set/HashSet.playground/Sources/HashSet.swift @@ -0,0 +1,76 @@ +//: Playground - noun: a place where people can play + +public struct HashSet { + fileprivate var dictionary = Dictionary() + + public init() { + + } + + public mutating func insert(_ element: T) { + dictionary[element] = true + } + + public mutating func remove(_ element: T) { + dictionary[element] = nil + } + + public func contains(_ element: T) -> Bool { + return dictionary[element] != nil + } + + public func allElements() -> [T] { + return Array(dictionary.keys) + } + + public var count: Int { + return dictionary.count + } + + public var isEmpty: Bool { + return dictionary.isEmpty + } +} + +/* Union */ + +extension HashSet { + public func union(_ otherSet: HashSet) -> HashSet { + var combined = HashSet() + for obj in self.dictionary.keys { + combined.insert(obj) + } + for obj in otherSet.dictionary.keys { + combined.insert(obj) + } + return combined + } +} + +/* Intersection */ + +extension HashSet { + public func intersect(_ otherSet: HashSet) -> HashSet { + var common = HashSet() + for obj in dictionary.keys { + if otherSet.contains(obj) { + common.insert(obj) + } + } + return common + } +} + +/* Difference */ + +extension HashSet { + public func difference(_ otherSet: HashSet) -> HashSet { + var diff = HashSet() + for obj in dictionary.keys { + if !otherSet.contains(obj) { + diff.insert(obj) + } + } + return diff + } +} diff --git a/Hash Set/README.markdown b/Hash Set/README.markdown index c6616fb42..368920a1c 100644 --- a/Hash Set/README.markdown +++ b/Hash Set/README.markdown @@ -38,31 +38,35 @@ Here are the beginnings of `HashSet` in Swift: ```swift public struct HashSet { - private var dictionary = Dictionary() - - public mutating func insert(element: T) { - dictionary[element] = true - } - - public mutating func remove(element: T) { - dictionary[element] = nil - } - - public func contains(element: T) -> Bool { - return dictionary[element] != nil - } - - public func allElements() -> [T] { - return Array(dictionary.keys) - } - - public var count: Int { - return dictionary.count - } - - public var isEmpty: Bool { - return dictionary.isEmpty - } + fileprivate var dictionary = Dictionary() + + public init() { + + } + + public mutating func insert(_ element: T) { + dictionary[element] = true + } + + public mutating func remove(_ element: T) { + dictionary[element] = nil + } + + public func contains(_ element: T) -> Bool { + return dictionary[element] != nil + } + + public func allElements() -> [T] { + return Array(dictionary.keys) + } + + public var count: Int { + return dictionary.count + } + + public var isEmpty: Bool { + return dictionary.isEmpty + } } ``` @@ -101,16 +105,16 @@ Here is the code for the union operation: ```swift extension HashSet { - public func union(otherSet: HashSet) -> HashSet { - var combined = HashSet() - for obj in dictionary.keys { - combined.insert(obj) - } - for obj in otherSet.dictionary.keys { - combined.insert(obj) + public func union(_ otherSet: HashSet) -> HashSet { + var combined = HashSet() + for obj in self.dictionary.keys { + combined.insert(obj) + } + for obj in otherSet.dictionary.keys { + combined.insert(obj) + } + return combined } - return combined - } } ``` @@ -141,15 +145,15 @@ The *intersection* of two sets contains only the elements that they have in comm ```swift extension HashSet { - public func intersect(otherSet: HashSet) -> HashSet { - var common = HashSet() - for obj in dictionary.keys { - if otherSet.contains(obj) { - common.insert(obj) - } + public func intersect(_ otherSet: HashSet) -> HashSet { + var common = HashSet() + for obj in dictionary.keys { + if otherSet.contains(obj) { + common.insert(obj) + } + } + return common } - return common - } } ``` @@ -166,15 +170,15 @@ Finally, the *difference* between two sets removes the elements they have in com ```swift extension HashSet { - public func difference(otherSet: HashSet) -> HashSet { - var diff = HashSet() - for obj in dictionary.keys { - if !otherSet.contains(obj) { - diff.insert(obj) - } + public func difference(_ otherSet: HashSet) -> HashSet { + var diff = HashSet() + for obj in dictionary.keys { + if !otherSet.contains(obj) { + diff.insert(obj) + } + } + return diff } - return diff - } } ``` From 3fe357f6fd4123fc063f39d5eec8607529a1f617 Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Tue, 1 Nov 2016 04:06:30 -0700 Subject: [PATCH 0628/1679] Removed an argument label for the append method in an effort to keep consistent with native collection types. Changed a method name to be more Swift like. --- .../FixedSizeArray.playground/Contents.swift | 10 +++++----- .../FixedSizeArray.playground/timeline.xctimeline | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Fixed Size Array/FixedSizeArray.playground/Contents.swift b/Fixed Size Array/FixedSizeArray.playground/Contents.swift index 663050d31..afe666a31 100644 --- a/Fixed Size Array/FixedSizeArray.playground/Contents.swift +++ b/Fixed Size Array/FixedSizeArray.playground/Contents.swift @@ -23,13 +23,13 @@ struct FixedSizeArray { return array[index] } - mutating func append(newElement: T) { + mutating func append(_ newElement: T) { assert(count < maxSize) array[count] = newElement count += 1 } - mutating func removeAtIndex(index: Int) -> T { + mutating func removeAt(index: Int) -> T { assert(index >= 0) assert(index < count) count -= 1 @@ -48,9 +48,9 @@ struct FixedSizeArray { } var array = FixedSizeArray(maxSize: 5, defaultValue: 0) -array.append(newElement: 4) -array.append(newElement: 2) +array.append(4) +array.append(2) array[1] -array.removeAtIndex(index: 0) +array.removeAt(index: 0) array.removeAll() diff --git a/Fixed Size Array/FixedSizeArray.playground/timeline.xctimeline b/Fixed Size Array/FixedSizeArray.playground/timeline.xctimeline index def6161e4..d95db1553 100644 --- a/Fixed Size Array/FixedSizeArray.playground/timeline.xctimeline +++ b/Fixed Size Array/FixedSizeArray.playground/timeline.xctimeline @@ -3,12 +3,12 @@ version = "3.0"> From b2bc31b7e8e1764f7431d07cbfacccccf7733518 Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Tue, 1 Nov 2016 04:10:58 -0700 Subject: [PATCH 0629/1679] Changed tabs from 4 spaces to 2 spaces. Updated README file to reflect the updated syntax. --- .../FixedSizeArray.playground/Contents.swift | 76 ++++++++--------- .../timeline.xctimeline | 4 +- Fixed Size Array/README.markdown | 84 +++++++++---------- 3 files changed, 82 insertions(+), 82 deletions(-) diff --git a/Fixed Size Array/FixedSizeArray.playground/Contents.swift b/Fixed Size Array/FixedSizeArray.playground/Contents.swift index afe666a31..f1bc63315 100644 --- a/Fixed Size Array/FixedSizeArray.playground/Contents.swift +++ b/Fixed Size Array/FixedSizeArray.playground/Contents.swift @@ -6,45 +6,45 @@ Performance is always O(1). */ struct FixedSizeArray { - private var maxSize: Int - private var defaultValue: T - private var array: [T] - private (set) var count = 0 - - init(maxSize: Int, defaultValue: T) { - self.maxSize = maxSize - self.defaultValue = defaultValue - self.array = [T](repeating: defaultValue, count: maxSize) - } - - subscript(index: Int) -> T { - assert(index >= 0) - assert(index < count) - return array[index] - } - - mutating func append(_ newElement: T) { - assert(count < maxSize) - array[count] = newElement - count += 1 - } - - mutating func removeAt(index: Int) -> T { - assert(index >= 0) - assert(index < count) - count -= 1 - let result = array[index] - array[index] = array[count] - array[count] = defaultValue - return result - } - - mutating func removeAll() { - for i in 0.. T { + assert(index >= 0) + assert(index < count) + return array[index] + } + + mutating func append(_ newElement: T) { + assert(count < maxSize) + array[count] = newElement + count += 1 + } + + mutating func removeAt(index: Int) -> T { + assert(index >= 0) + assert(index < count) + count -= 1 + let result = array[index] + array[index] = array[count] + array[count] = defaultValue + return result + } + + mutating func removeAll() { + for i in 0.. diff --git a/Fixed Size Array/README.markdown b/Fixed Size Array/README.markdown index efacda710..e9eade140 100644 --- a/Fixed Size Array/README.markdown +++ b/Fixed Size Array/README.markdown @@ -55,12 +55,12 @@ Fixed-size arrays are a good solution when: 1. You know beforehand the maximum number of elements you'll need. In a game this could be the number of sprites that can be active at a time. It's not unreasonable to put a limit on this. (For games it's a good idea to allocate all the objects you need in advance anyway.) 2. It is not necessary to have a sorted version of the array, i.e. the order of the elements does not matter. -If the array does not need to be sorted, then an `insertAtIndex()` operation is not needed. You can simply append any new elements to the end, until the array is full. +If the array does not need to be sorted, then an `insertAt(index)` operation is not needed. You can simply append any new elements to the end, until the array is full. The code for adding an element becomes: ```swift -func append(newElement) { +func append(_ newElement: T) { if count < maxSize { array[count] = newElement count += 1 @@ -75,7 +75,7 @@ Determining the number of elements in the array is just a matter of reading the The code for removing an element is equally simple: ```swift -func removeAtIndex(index) { +func removeAt(index: Int) { count -= 1 array[index] = array[count] } @@ -95,45 +95,45 @@ Here is an implementation in Swift: ```swift struct FixedSizeArray { - private var maxSize: Int - private var defaultValue: T - private var array: [T] - private (set) var count = 0 - - init(maxSize: Int, defaultValue: T) { - self.maxSize = maxSize - self.defaultValue = defaultValue - self.array = [T](repeating: defaultValue, count: maxSize) - } - - subscript(index: Int) -> T { - assert(index >= 0) - assert(index < count) - return array[index] - } - - mutating func append(newElement: T) { - assert(count < maxSize) - array[count] = newElement - count += 1 - } - - mutating func removeAtIndex(index: Int) -> T { - assert(index >= 0) - assert(index < count) - count -= 1 - let result = array[index] - array[index] = array[count] - array[count] = defaultValue - return result - } - - mutating func removeAll() { - for i in 0.. T { + assert(index >= 0) + assert(index < count) + return array[index] + } + + mutating func append(_ newElement: T) { + assert(count < maxSize) + array[count] = newElement + count += 1 + } + + mutating func removeAt(index: Int) -> T { + assert(index >= 0) + assert(index < count) + count -= 1 + let result = array[index] + array[index] = array[count] + array[count] = defaultValue + return result + } + + mutating func removeAll() { + for i in 0.. Date: Tue, 1 Nov 2016 18:54:39 -0500 Subject: [PATCH 0630/1679] took off an extra min --- .../SelectionSampling.playground/Contents.swift | 3 +-- .../SelectionSampling.playground/timeline.xctimeline | 6 ------ 2 files changed, 1 insertion(+), 8 deletions(-) delete mode 100644 Selection Sampling/SelectionSampling.playground/timeline.xctimeline diff --git a/Selection Sampling/SelectionSampling.playground/Contents.swift b/Selection Sampling/SelectionSampling.playground/Contents.swift index f6032137b..df1bb2e32 100644 --- a/Selection Sampling/SelectionSampling.playground/Contents.swift +++ b/Selection Sampling/SelectionSampling.playground/Contents.swift @@ -3,7 +3,7 @@ import Foundation /* Returns a random integer in the range min...max, inclusive. */ -public func random(min min: Int, max: Int) -> Int { +public func random(min: Int, max: Int) -> Int { assert(min < max) return min + Int(arc4random_uniform(UInt32(max - min + 1))) } @@ -45,7 +45,6 @@ func select(from a: [T], count requested: Int) -> [T] { } - let poem = [ "there", "once", "was", "a", "man", "from", "nantucket", "who", "kept", "all", "of", "his", "cash", "in", "a", "bucket", diff --git a/Selection Sampling/SelectionSampling.playground/timeline.xctimeline b/Selection Sampling/SelectionSampling.playground/timeline.xctimeline deleted file mode 100644 index bf468afec..000000000 --- a/Selection Sampling/SelectionSampling.playground/timeline.xctimeline +++ /dev/null @@ -1,6 +0,0 @@ - - - - - From f0c17d5aeedf8d78c5449fa326e91152dc3cc5dc Mon Sep 17 00:00:00 2001 From: Jacopo Mangiavacchi Date: Wed, 2 Nov 2016 12:12:45 +0000 Subject: [PATCH 0631/1679] Dining Philosophers Problem Algorithm --- .../project.pbxproj | 250 ++++++++++++++++++ .../contents.xcworkspacedata | 7 + .../xcschemes/DiningPhilosophers.xcscheme | 71 +++++ .../xcschemes/xcschememanagement.plist | 12 + DiningPhilosophers/LICENSE | 201 ++++++++++++++ DiningPhilosophers/Package.swift | 5 + DiningPhilosophers/README.md | 13 + DiningPhilosophers/Sources/main.swift | 107 ++++++++ 8 files changed, 666 insertions(+) create mode 100755 DiningPhilosophers/DiningPhilosophers.xcodeproj/project.pbxproj create mode 100755 DiningPhilosophers/DiningPhilosophers.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100755 DiningPhilosophers/DiningPhilosophers.xcodeproj/xcshareddata/xcschemes/DiningPhilosophers.xcscheme create mode 100755 DiningPhilosophers/DiningPhilosophers.xcodeproj/xcshareddata/xcschemes/xcschememanagement.plist create mode 100755 DiningPhilosophers/LICENSE create mode 100755 DiningPhilosophers/Package.swift create mode 100755 DiningPhilosophers/README.md create mode 100755 DiningPhilosophers/Sources/main.swift diff --git a/DiningPhilosophers/DiningPhilosophers.xcodeproj/project.pbxproj b/DiningPhilosophers/DiningPhilosophers.xcodeproj/project.pbxproj new file mode 100755 index 000000000..9743ff7d1 --- /dev/null +++ b/DiningPhilosophers/DiningPhilosophers.xcodeproj/project.pbxproj @@ -0,0 +1,250 @@ +// !$*UTF8*$! +{ + archiveVersion = "1"; + objectVersion = "46"; + objects = { + OBJ_1 = { + isa = "PBXProject"; + attributes = { + LastUpgradeCheck = "9999"; + }; + buildConfigurationList = OBJ_2; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = "English"; + hasScannedForEncodings = "0"; + knownRegions = ( + "en", + ); + mainGroup = OBJ_5; + productRefGroup = OBJ_11; + projectDirPath = "."; + targets = ( + OBJ_13, + ); + }; + OBJ_10 = { + isa = "PBXGroup"; + children = ( + ); + path = "Tests"; + sourceTree = ""; + }; + OBJ_11 = { + isa = "PBXGroup"; + children = ( + OBJ_12, + ); + name = "Products"; + path = ""; + sourceTree = "BUILT_PRODUCTS_DIR"; + }; + OBJ_12 = { + isa = "PBXFileReference"; + path = "DiningPhilosophers"; + sourceTree = "BUILT_PRODUCTS_DIR"; + }; + OBJ_13 = { + isa = "PBXNativeTarget"; + buildConfigurationList = OBJ_14; + buildPhases = ( + OBJ_17, + OBJ_19, + ); + dependencies = ( + ); + name = "DiningPhilosophers"; + productName = "DiningPhilosophers"; + productReference = OBJ_12; + productType = "com.apple.product-type.tool"; + }; + OBJ_14 = { + isa = "XCConfigurationList"; + buildConfigurations = ( + OBJ_15, + OBJ_16, + ); + defaultConfigurationIsVisible = "0"; + defaultConfigurationName = "Debug"; + }; + OBJ_15 = { + isa = "XCBuildConfiguration"; + buildSettings = { + FRAMEWORK_SEARCH_PATHS = ( + "$(PLATFORM_DIR)/Developer/Library/Frameworks", + ); + HEADER_SEARCH_PATHS = ( + ); + INFOPLIST_FILE = "DiningPhilosophers.xcodeproj/DiningPhilosophers_Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(TOOLCHAIN_DIR)/usr/lib/swift/macosx", + "@executable_path", + ); + OTHER_LDFLAGS = ( + "$(inherited)", + ); + OTHER_SWIFT_FLAGS = ( + "$(inherited)", + ); + SUPPORTED_PLATFORMS = ( + "macosx", + ); + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "SWIFT_PACKAGE"; + SWIFT_FORCE_DYNAMIC_LINK_STDLIB = "YES"; + SWIFT_FORCE_STATIC_LINK_STDLIB = "NO"; + SWIFT_VERSION = "3.0"; + TARGET_NAME = "DiningPhilosophers"; + }; + name = "Debug"; + }; + OBJ_16 = { + isa = "XCBuildConfiguration"; + buildSettings = { + FRAMEWORK_SEARCH_PATHS = ( + "$(PLATFORM_DIR)/Developer/Library/Frameworks", + ); + HEADER_SEARCH_PATHS = ( + ); + INFOPLIST_FILE = "DiningPhilosophers.xcodeproj/DiningPhilosophers_Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(TOOLCHAIN_DIR)/usr/lib/swift/macosx", + "@executable_path", + ); + OTHER_LDFLAGS = ( + "$(inherited)", + ); + OTHER_SWIFT_FLAGS = ( + "$(inherited)", + ); + SUPPORTED_PLATFORMS = ( + "macosx", + ); + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "SWIFT_PACKAGE"; + SWIFT_FORCE_DYNAMIC_LINK_STDLIB = "YES"; + SWIFT_FORCE_STATIC_LINK_STDLIB = "NO"; + SWIFT_VERSION = "3.0"; + TARGET_NAME = "DiningPhilosophers"; + }; + name = "Release"; + }; + OBJ_17 = { + isa = "PBXSourcesBuildPhase"; + files = ( + OBJ_18, + ); + }; + OBJ_18 = { + isa = "PBXBuildFile"; + fileRef = OBJ_9; + }; + OBJ_19 = { + isa = "PBXFrameworksBuildPhase"; + files = ( + ); + }; + OBJ_2 = { + isa = "XCConfigurationList"; + buildConfigurations = ( + OBJ_3, + OBJ_4, + ); + defaultConfigurationIsVisible = "0"; + defaultConfigurationName = "Debug"; + }; + OBJ_3 = { + isa = "XCBuildConfiguration"; + buildSettings = { + COMBINE_HIDPI_IMAGES = "YES"; + COPY_PHASE_STRIP = "NO"; + DEBUG_INFORMATION_FORMAT = "dwarf"; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_NS_ASSERTIONS = "YES"; + GCC_OPTIMIZATION_LEVEL = "0"; + MACOSX_DEPLOYMENT_TARGET = "10.10"; + ONLY_ACTIVE_ARCH = "YES"; + OTHER_SWIFT_FLAGS = ( + "-DXcode", + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + SUPPORTED_PLATFORMS = ( + "macosx", + "iphoneos", + "iphonesimulator", + "appletvos", + "appletvsimulator", + "watchos", + "watchsimulator", + ); + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + USE_HEADERMAP = "NO"; + }; + name = "Debug"; + }; + OBJ_4 = { + isa = "XCBuildConfiguration"; + buildSettings = { + COMBINE_HIDPI_IMAGES = "YES"; + COPY_PHASE_STRIP = "YES"; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_OPTIMIZATION_LEVEL = "s"; + MACOSX_DEPLOYMENT_TARGET = "10.10"; + OTHER_SWIFT_FLAGS = ( + "-DXcode", + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + SUPPORTED_PLATFORMS = ( + "macosx", + "iphoneos", + "iphonesimulator", + "appletvos", + "appletvsimulator", + "watchos", + "watchsimulator", + ); + SWIFT_OPTIMIZATION_LEVEL = "-O"; + USE_HEADERMAP = "NO"; + }; + name = "Release"; + }; + OBJ_5 = { + isa = "PBXGroup"; + children = ( + OBJ_6, + OBJ_7, + OBJ_10, + OBJ_11, + ); + path = ""; + sourceTree = ""; + }; + OBJ_6 = { + isa = "PBXFileReference"; + explicitFileType = "sourcecode.swift"; + path = "Package.swift"; + sourceTree = ""; + }; + OBJ_7 = { + isa = "PBXGroup"; + children = ( + OBJ_8, + ); + path = "Sources"; + sourceTree = ""; + }; + OBJ_8 = { + isa = "PBXGroup"; + children = ( + OBJ_9, + ); + name = "DiningPhilosophers"; + path = "Sources"; + sourceTree = "SOURCE_ROOT"; + }; + OBJ_9 = { + isa = "PBXFileReference"; + path = "main.swift"; + sourceTree = ""; + }; + }; + rootObject = OBJ_1; +} diff --git a/DiningPhilosophers/DiningPhilosophers.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/DiningPhilosophers/DiningPhilosophers.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100755 index 000000000..919434a62 --- /dev/null +++ b/DiningPhilosophers/DiningPhilosophers.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/DiningPhilosophers/DiningPhilosophers.xcodeproj/xcshareddata/xcschemes/DiningPhilosophers.xcscheme b/DiningPhilosophers/DiningPhilosophers.xcodeproj/xcshareddata/xcschemes/DiningPhilosophers.xcscheme new file mode 100755 index 000000000..3c17791b7 --- /dev/null +++ b/DiningPhilosophers/DiningPhilosophers.xcodeproj/xcshareddata/xcschemes/DiningPhilosophers.xcscheme @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/DiningPhilosophers/DiningPhilosophers.xcodeproj/xcshareddata/xcschemes/xcschememanagement.plist b/DiningPhilosophers/DiningPhilosophers.xcodeproj/xcshareddata/xcschemes/xcschememanagement.plist new file mode 100755 index 000000000..4cd3e1d66 --- /dev/null +++ b/DiningPhilosophers/DiningPhilosophers.xcodeproj/xcshareddata/xcschemes/xcschememanagement.plist @@ -0,0 +1,12 @@ + + + + SchemeUserState + + DiningPhilosophers.xcscheme + + + SuppressBuildableAutocreation + + + diff --git a/DiningPhilosophers/LICENSE b/DiningPhilosophers/LICENSE new file mode 100755 index 000000000..8dada3eda --- /dev/null +++ b/DiningPhilosophers/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/DiningPhilosophers/Package.swift b/DiningPhilosophers/Package.swift new file mode 100755 index 000000000..c7e5efd4f --- /dev/null +++ b/DiningPhilosophers/Package.swift @@ -0,0 +1,5 @@ +import PackageDescription + +let package = Package( + name: "DiningPhilosophers" +) diff --git a/DiningPhilosophers/README.md b/DiningPhilosophers/README.md new file mode 100755 index 000000000..06302cf2a --- /dev/null +++ b/DiningPhilosophers/README.md @@ -0,0 +1,13 @@ +# SwiftDiningPhilosophers +Dining philosophers problem Algorithm implemented in Swift (concurrent algorithm design to illustrate synchronization issues and techniques for resolving them using GCD and Semaphore in Swift) + +Written by Jacopo Mangiavacchi + + +# from https://en.wikipedia.org/wiki/Dining_philosophers_problem + +In computer science, the dining philosophers problem is an example problem often used in concurrent algorithm design to illustrate synchronization issues and techniques for resolving them. + +It was originally formulated in 1965 by Edsger Dijkstra as a student exam exercise, presented in terms of computers competing for access to tape drive peripherals. Soon after, Tony Hoare gave the problem its present formulation. + +This Swift implementation is based on the Chandy/Misra solution and it use GCD Dispatch and Semaphone on Swift cross platform diff --git a/DiningPhilosophers/Sources/main.swift b/DiningPhilosophers/Sources/main.swift new file mode 100755 index 000000000..dfde40773 --- /dev/null +++ b/DiningPhilosophers/Sources/main.swift @@ -0,0 +1,107 @@ +// +// Swift Dining philosophers problem Algorithm +// https://en.wikipedia.org/wiki/Dining_philosophers_problem +// +// Created by Jacopo Mangiavacchi on 11/02/16. +// +// + + +import Foundation +import Dispatch + +let numberOfPhilosophers = 4 + +class ForkPair { + static let forksSemaphore:[DispatchSemaphore] = Array(repeating: DispatchSemaphore(value: 1), count: numberOfPhilosophers) + + let leftFork: DispatchSemaphore + let rightFork: DispatchSemaphore + + init(leftIndex: Int, rightIndex: Int) { + //Order forks by index to prevent deadlock + if leftIndex > rightIndex { + leftFork = ForkPair.forksSemaphore[leftIndex] + rightFork = ForkPair.forksSemaphore[rightIndex] + } + else { + leftFork = ForkPair.forksSemaphore[rightIndex] + rightFork = ForkPair.forksSemaphore[leftIndex] + } + } + + func pickUp() { + //Acquire by starting with the lower index + leftFork.wait() + rightFork.wait() + } + + func putDown() { + //The order does not matter here + leftFork.signal() + rightFork.signal() + } +} + + +class Philosophers { + let forkPair: ForkPair + let philosopherIndex: Int + + var leftIndex = -1 + var rightIndex = -1 + + init(philosopherIndex: Int) { + leftIndex = philosopherIndex + rightIndex = philosopherIndex - 1 + + if rightIndex < 0 { + rightIndex += numberOfPhilosophers + } + + self.forkPair = ForkPair(leftIndex: leftIndex, rightIndex: rightIndex) + self.philosopherIndex = philosopherIndex + + print("Philosopher: \(philosopherIndex) left: \(leftIndex) right: \(rightIndex)") + } + + func run() { + while true { + print("Acquiring lock for Philosofer: \(philosopherIndex) Left:\(leftIndex) Right:\(rightIndex)") + forkPair.pickUp() + print("Start Eating Philosopher: \(philosopherIndex)") + //sleep(1000) + print("Releasing lock for Philosofer: \(philosopherIndex) Left:\(leftIndex) Right:\(rightIndex)") + forkPair.putDown() + } + } +} + + +// Layout of the table (P = philosopher, f = fork) for 4 Philosopher +// P0 +// f3 f0 +// P3 P1 +// f2 f1 +// P2 + +let globalSem = DispatchSemaphore(value: 0) + +for i in 0.. Date: Wed, 2 Nov 2016 15:23:31 +0100 Subject: [PATCH 0632/1679] Fix a bug in SegmentTree --- .../SegmentTree.playground/Contents.swift | 46 +++++++++---------- Segment Tree/SegmentTree.swift | 10 ++-- 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/Segment Tree/SegmentTree.playground/Contents.swift b/Segment Tree/SegmentTree.playground/Contents.swift index 6b33b2f44..5bba56cc0 100644 --- a/Segment Tree/SegmentTree.playground/Contents.swift +++ b/Segment Tree/SegmentTree.playground/Contents.swift @@ -28,7 +28,7 @@ public class SegmentTree { self.init(array: array, leftBound: 0, rightBound: array.count-1, function: function) } - public func query(withLeftBound: Int, rightBound: Int) -> T { + public func query(leftBound: Int, rightBound: Int) -> T { if self.leftBound == leftBound && self.rightBound == rightBound { return self.value } @@ -37,12 +37,12 @@ public class SegmentTree { guard let rightChild = rightChild else { fatalError("rightChild should not be nil") } if leftChild.rightBound < leftBound { - return rightChild.query(withLeftBound: leftBound, rightBound: rightBound) + return rightChild.query(leftBound: leftBound, rightBound: rightBound) } else if rightChild.leftBound > rightBound { - return leftChild.query(withLeftBound: leftBound, rightBound: rightBound) + return leftChild.query(leftBound: leftBound, rightBound: rightBound) } else { - let leftResult = leftChild.query(withLeftBound: leftBound, rightBound: leftChild.rightBound) - let rightResult = rightChild.query(withLeftBound:rightChild.leftBound, rightBound: rightBound) + let leftResult = leftChild.query(leftBound: leftBound, rightBound: leftChild.rightBound) + let rightResult = rightChild.query(leftBound:rightChild.leftBound, rightBound: rightBound) return function(leftResult, rightResult) } } @@ -68,14 +68,14 @@ let array = [1, 2, 3, 4] let sumSegmentTree = SegmentTree(array: array, function: +) -print(sumSegmentTree.query(withLeftBound: 0, rightBound: 3)) // 1 + 2 + 3 + 4 = 10 -print(sumSegmentTree.query(withLeftBound: 1, rightBound: 2)) // 2 + 3 = 5 -print(sumSegmentTree.query(withLeftBound: 0, rightBound: 0)) // 1 = 1 +print(sumSegmentTree.query(leftBound: 0, rightBound: 3)) // 1 + 2 + 3 + 4 = 10 +print(sumSegmentTree.query(leftBound: 1, rightBound: 2)) // 2 + 3 = 5 +print(sumSegmentTree.query(leftBound: 0, rightBound: 0)) // 1 = 1 sumSegmentTree.replaceItem(at: 0, withItem: 2) //our array now is [2, 2, 3, 4] -print(sumSegmentTree.query(withLeftBound: 0, rightBound: 0)) // 2 = 2 -print(sumSegmentTree.query(withLeftBound: 0, rightBound: 1)) // 2 + 2 = 4 +print(sumSegmentTree.query(leftBound: 0, rightBound: 0)) // 2 = 2 +print(sumSegmentTree.query(leftBound: 0, rightBound: 1)) // 2 + 2 = 4 //you can use any associative function (i.e (a+b)+c == a+(b+c)) as function for segment tree @@ -96,14 +96,14 @@ let gcdArray = [2, 4, 6, 3, 5] let gcdSegmentTree = SegmentTree(array: gcdArray, function: gcd) -print(gcdSegmentTree.query(withLeftBound: 0, rightBound: 1)) // gcd(2, 4) = 2 -print(gcdSegmentTree.query(withLeftBound: 2, rightBound: 3)) // gcd(6, 3) = 3 -print(gcdSegmentTree.query(withLeftBound: 1, rightBound: 3)) // gcd(4, 6, 3) = 1 -print(gcdSegmentTree.query(withLeftBound: 0, rightBound: 4)) // gcd(2, 4, 6, 3, 5) = 1 +print(gcdSegmentTree.query(leftBound: 0, rightBound: 1)) // gcd(2, 4) = 2 +print(gcdSegmentTree.query(leftBound: 2, rightBound: 3)) // gcd(6, 3) = 3 +print(gcdSegmentTree.query(leftBound: 1, rightBound: 3)) // gcd(4, 6, 3) = 1 +print(gcdSegmentTree.query(leftBound: 0, rightBound: 4)) // gcd(2, 4, 6, 3, 5) = 1 gcdSegmentTree.replaceItem(at: 3, withItem: 10) //gcdArray now is [2, 4, 6, 10, 5] -print(gcdSegmentTree.query(withLeftBound: 3, rightBound: 4)) // gcd(10, 5) = 5 +print(gcdSegmentTree.query(leftBound: 3, rightBound: 4)) // gcd(10, 5) = 5 //example of segment tree which finds minimum on given range @@ -111,12 +111,12 @@ let minArray = [2, 4, 1, 5, 3] let minSegmentTree = SegmentTree(array: minArray, function: min) -print(minSegmentTree.query(withLeftBound: 0, rightBound: 4)) // min(2, 4, 1, 5, 3) = 1 -print(minSegmentTree.query(withLeftBound: 0, rightBound: 1)) // min(2, 4) = 2 +print(minSegmentTree.query(leftBound: 0, rightBound: 4)) // min(2, 4, 1, 5, 3) = 1 +print(minSegmentTree.query(leftBound: 0, rightBound: 1)) // min(2, 4) = 2 minSegmentTree.replaceItem(at: 2, withItem: 10) // minArray now is [2, 4, 10, 5, 3] -print(minSegmentTree.query(withLeftBound: 0, rightBound: 4)) // min(2, 4, 10, 5, 3) = 2 +print(minSegmentTree.query(leftBound: 0, rightBound: 4)) // min(2, 4, 10, 5, 3) = 2 //type of elements in array can be any type which has some associative function @@ -124,10 +124,10 @@ let stringArray = ["a", "b", "c", "A", "B", "C"] let stringSegmentTree = SegmentTree(array: stringArray, function: +) -print(stringSegmentTree.query(withLeftBound: 0, rightBound: 1)) // "a"+"b" = "ab" -print(stringSegmentTree.query(withLeftBound: 2, rightBound: 3)) // "c"+"A" = "cA" -print(stringSegmentTree.query(withLeftBound: 1, rightBound: 3)) // "b"+"c"+"A" = "bcA" -print(stringSegmentTree.query(withLeftBound: 0, rightBound: 5)) // "a"+"b"+"c"+"A"+"B"+"C" = "abcABC" +print(stringSegmentTree.query(leftBound: 0, rightBound: 1)) // "a"+"b" = "ab" +print(stringSegmentTree.query(leftBound: 2, rightBound: 3)) // "c"+"A" = "cA" +print(stringSegmentTree.query(leftBound: 1, rightBound: 3)) // "b"+"c"+"A" = "bcA" +print(stringSegmentTree.query(leftBound: 0, rightBound: 5)) // "a"+"b"+"c"+"A"+"B"+"C" = "abcABC" stringSegmentTree.replaceItem(at: 0, withItem: "I") stringSegmentTree.replaceItem(at: 1, withItem: " like") @@ -136,4 +136,4 @@ stringSegmentTree.replaceItem(at: 3, withItem: " and") stringSegmentTree.replaceItem(at: 4, withItem: " swift") stringSegmentTree.replaceItem(at: 5, withItem: "!") -print(stringSegmentTree.query(withLeftBound: 0, rightBound: 5)) +print(stringSegmentTree.query(leftBound: 0, rightBound: 5)) diff --git a/Segment Tree/SegmentTree.swift b/Segment Tree/SegmentTree.swift index b360d409a..a3ec8b1bf 100644 --- a/Segment Tree/SegmentTree.swift +++ b/Segment Tree/SegmentTree.swift @@ -35,7 +35,7 @@ public class SegmentTree { self.init(array: array, leftBound: 0, rightBound: array.count-1, function: function) } - public func query(withLeftBound: Int, rightBound: Int) -> T { + public func query(leftBound: Int, rightBound: Int) -> T { if self.leftBound == leftBound && self.rightBound == rightBound { return self.value } @@ -44,12 +44,12 @@ public class SegmentTree { guard let rightChild = rightChild else { fatalError("rightChild should not be nil") } if leftChild.rightBound < leftBound { - return rightChild.query(withLeftBound: leftBound, rightBound: rightBound) + return rightChild.query(leftBound: leftBound, rightBound: rightBound) } else if rightChild.leftBound > rightBound { - return leftChild.query(withLeftBound: leftBound, rightBound: rightBound) + return leftChild.query(leftBound: leftBound, rightBound: rightBound) } else { - let leftResult = leftChild.query(withLeftBound: leftBound, rightBound: leftChild.rightBound) - let rightResult = rightChild.query(withLeftBound:rightChild.leftBound, rightBound: rightBound) + let leftResult = leftChild.query(leftBound: leftBound, rightBound: leftChild.rightBound) + let rightResult = rightChild.query(leftBound:rightChild.leftBound, rightBound: rightBound) return function(leftResult, rightResult) } } From ea634305e542a2d9601ca560ced4d4b84796f8cd Mon Sep 17 00:00:00 2001 From: Chris Amanse Date: Fri, 4 Nov 2016 23:37:20 -0700 Subject: [PATCH 0633/1679] Fix memory leak in Tree implementation - caused by retain cycle between parent and child (parent has a strong reference to child, and child has a strong reference to parent) --- Tree/Tree.playground/Contents.swift | 2 +- Tree/Tree.swift | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Tree/Tree.playground/Contents.swift b/Tree/Tree.playground/Contents.swift index 7b3c97005..77e8fd22e 100644 --- a/Tree/Tree.playground/Contents.swift +++ b/Tree/Tree.playground/Contents.swift @@ -3,7 +3,7 @@ public class TreeNode { public var value: T - public var parent: TreeNode? + public weak var parent: TreeNode? public var children = [TreeNode]() public init(value: T) { diff --git a/Tree/Tree.swift b/Tree/Tree.swift index 00119c963..fa49f25e9 100644 --- a/Tree/Tree.swift +++ b/Tree/Tree.swift @@ -1,7 +1,7 @@ public class TreeNode { public var value: T - public var parent: TreeNode? + public weak var parent: TreeNode? public var children = [TreeNode]() public init(value: T) { From b23ad94b1758cf572dc814966b3260fbedb8a8c1 Mon Sep 17 00:00:00 2001 From: Chris Amanse Date: Fri, 4 Nov 2016 23:41:44 -0700 Subject: [PATCH 0634/1679] Fix code in Tree docs (set parent to weak) --- Tree/README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tree/README.markdown b/Tree/README.markdown index 5cf3e6beb..529a68cf1 100644 --- a/Tree/README.markdown +++ b/Tree/README.markdown @@ -26,7 +26,7 @@ Here's a basic implementation in Swift: public class TreeNode { public var value: T - public var parent: TreeNode? + public weak var parent: TreeNode? public var children = [TreeNode]() public init(value: T) { From f77809c0476c7ed1d8701cb54d0eeb01fed36198 Mon Sep 17 00:00:00 2001 From: Divyendu Singh Date: Tue, 8 Nov 2016 01:58:40 +0530 Subject: [PATCH 0635/1679] typo fix and claim commit --- Bucket Sort/README.markdown | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/Bucket Sort/README.markdown b/Bucket Sort/README.markdown index f6e318c1f..f572fc9a1 100644 --- a/Bucket Sort/README.markdown +++ b/Bucket Sort/README.markdown @@ -9,16 +9,16 @@ Bucket Sort, also known as Bin Sort, is a distributed sorting algorithm, which s See the algorithm in action [here](https://www.cs.usfca.edu/~galles/visualization/BucketSort.html) and [here](http://www.algostructure.com/sorting/bucketsort.php). The performance for execution time is: - + | Case | Performance | |:-------------: |:---------------:| | Worst | O(n^2) | | Best | Omega(n + k) | -| Average | Theta(n + k) | - +| Average | Theta(n + k) | + Where **n** = the number of elements and **k** is the number of buckets. -In the *best case*, the algorithm distributes the elements uniformily between buckets, a few elements are placed on each bucket and sorting the buckets is **O(1)**. Rearranging the elements is one more run through the initial list. +In the *best case*, the algorithm distributes the elements uniformly between buckets, a few elements are placed on each bucket and sorting the buckets is **O(1)**. Rearranging the elements is one more run through the initial list. In the *worst case*, the elements are sent all to the same bucket, making the process take **O(n^2)**. @@ -63,11 +63,11 @@ So the buckets are: Now we need to choose a distribution function. `bucketNumber = (elementValue / totalNumberOfBuckets) + 1` - + Such that by applying that function we distribute all the elements in the buckets. In our example it is like the following: - + 1. Apply the distribution function to `2`. `bucketNumber = (2 / 10) + 1 = 1` 2. Apply the distribution function to `56`. `bucketNumber = (56 / 10) + 1 = 6` 3. Apply the distribution function to `4`. `bucketNumber = (4 / 10) + 1 = 1` @@ -91,12 +91,12 @@ Our buckets will be filled now: We can choose to insert the elements in every bucket in order, or sort every bucket after distributing all the elements. -### Put the elements back in the list +### Put the elements back in the list Finally we go through all the buckets and put the elements back in the list: - + `[2, 4, 26, 55, 56, 77, 98]` - + ## Swift implementation @@ -109,9 +109,9 @@ Here is a diagram that shows the functions, data structures and protocols for ou `bucketSort()` is a generic function that can apply the algorithm to any element of type `T`, as long as `T` is `Sortable`. ```swift -public func bucketSort(elements: [T], - distributor: Distributor, - sorter: Sorter, +public func bucketSort(elements: [T], + distributor: Distributor, + sorter: Sorter, buckets: [Bucket]) -> [T] { precondition(allPositiveNumbers(elements)) precondition(enoughSpaceInBuckets(buckets, elements: elements)) @@ -201,11 +201,11 @@ public struct InsertionSorter: Sorter { for i in 0 ..< results.count { var j = i while ( j > 0 && results[j-1] > results[j]) { - + let auxiliar = results[j-1] results[j-1] = results[j] results[j] = auxiliar - + j -= 1 } } @@ -236,7 +236,7 @@ public struct RangeDistributor: Distributor { public func distribute(element: T, inout buckets: [Bucket]) { let value = element.toInt() let bucketCapacity = buckets.first!.capacity - + let bucketIndex = value / bucketCapacity buckets[bucketIndex].add(element) } From 3132f5d75780fafe146258d934f4b4a5e5ff9463 Mon Sep 17 00:00:00 2001 From: BenEmdon Date: Mon, 7 Nov 2016 16:57:54 -0500 Subject: [PATCH 0636/1679] Initial commit and claim --- Rootish Array Stack/README.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 Rootish Array Stack/README.md diff --git a/Rootish Array Stack/README.md b/Rootish Array Stack/README.md new file mode 100644 index 000000000..e69de29bb From 6c9e3a86f9a564cff15170e5a22d088e9d381cd9 Mon Sep 17 00:00:00 2001 From: jsbean Date: Tue, 8 Nov 2016 20:46:21 -0500 Subject: [PATCH 0637/1679] Update to Swift 3.0 --- .../LinearRegression.playground/Contents.swift | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Linear Regression/LinearRegression.playground/Contents.swift b/Linear Regression/LinearRegression.playground/Contents.swift index 585471487..ae2e4fc14 100644 --- a/Linear Regression/LinearRegression.playground/Contents.swift +++ b/Linear Regression/LinearRegression.playground/Contents.swift @@ -19,26 +19,26 @@ let alpha = 0.0001 for n in 1...numberOfIterations { for i in 0.. Double { - return input.reduce(0, combine: +) / Double(input.count) +func average(_ input: [Double]) -> Double { + return input.reduce(0, +) / Double(input.count) } -func multiply(input1: [Double], _ input2: [Double]) -> [Double] { - return input1.enumerate().map({ (index, element) in return element*input2[index] }) +func multiply(_ input1: [Double], _ input2: [Double]) -> [Double] { + return input1.enumerated().map({ (index, element) in return element*input2[index] }) } -func linearRegression(xVariable: [Double], _ yVariable: [Double]) -> (Double -> Double) { - let sum1 = average(multiply(xVariable, yVariable)) - average(xVariable) * average(yVariable) +func linearRegression(_ xVariable: [Double], _ yVariable: [Double]) -> ((Double) -> Double) { + let sum1 = average(multiply(yVariable, xVariable)) - average(xVariable) * average(yVariable) let sum2 = average(multiply(xVariable, xVariable)) - pow(average(xVariable), 2) let slope = sum1 / sum2 let intercept = average(yVariable) - slope * average(xVariable) From 087dc18fdf9dac0429540ee353d8696ded901b2a Mon Sep 17 00:00:00 2001 From: jsbean Date: Tue, 8 Nov 2016 20:48:35 -0500 Subject: [PATCH 0638/1679] Make multiply(_:_:) function more elegant --- Linear Regression/LinearRegression.playground/Contents.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Linear Regression/LinearRegression.playground/Contents.swift b/Linear Regression/LinearRegression.playground/Contents.swift index ae2e4fc14..32d2cc195 100644 --- a/Linear Regression/LinearRegression.playground/Contents.swift +++ b/Linear Regression/LinearRegression.playground/Contents.swift @@ -34,7 +34,7 @@ func average(_ input: [Double]) -> Double { } func multiply(_ input1: [Double], _ input2: [Double]) -> [Double] { - return input1.enumerated().map({ (index, element) in return element*input2[index] }) + return zip(input1, input2).map { $0.0 * $0.1 } } func linearRegression(_ xVariable: [Double], _ yVariable: [Double]) -> ((Double) -> Double) { From dda0d7957da6dadc9edab569c79ccd11e1d702af Mon Sep 17 00:00:00 2001 From: jsbean Date: Tue, 8 Nov 2016 20:49:43 -0500 Subject: [PATCH 0639/1679] Make multiply(_:_:) function even more elegant --- Linear Regression/LinearRegression.playground/Contents.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Linear Regression/LinearRegression.playground/Contents.swift b/Linear Regression/LinearRegression.playground/Contents.swift index 32d2cc195..fd711849a 100644 --- a/Linear Regression/LinearRegression.playground/Contents.swift +++ b/Linear Regression/LinearRegression.playground/Contents.swift @@ -33,8 +33,8 @@ func average(_ input: [Double]) -> Double { return input.reduce(0, +) / Double(input.count) } -func multiply(_ input1: [Double], _ input2: [Double]) -> [Double] { - return zip(input1, input2).map { $0.0 * $0.1 } +func multiply(_ a: [Double], _ b: [Double]) -> [Double] { + return zip(a,b).map { $0.0 * $0.1 } } func linearRegression(_ xVariable: [Double], _ yVariable: [Double]) -> ((Double) -> Double) { From 95efaec8dc8bf00dd6d1da6702855c49d6a5fe87 Mon Sep 17 00:00:00 2001 From: jsbean Date: Tue, 8 Nov 2016 20:50:52 -0500 Subject: [PATCH 0640/1679] Rename (xVariable, yVariable) -> (xs, ys) --- .../LinearRegression.playground/Contents.swift | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Linear Regression/LinearRegression.playground/Contents.swift b/Linear Regression/LinearRegression.playground/Contents.swift index fd711849a..f50bdefbc 100644 --- a/Linear Regression/LinearRegression.playground/Contents.swift +++ b/Linear Regression/LinearRegression.playground/Contents.swift @@ -37,11 +37,11 @@ func multiply(_ a: [Double], _ b: [Double]) -> [Double] { return zip(a,b).map { $0.0 * $0.1 } } -func linearRegression(_ xVariable: [Double], _ yVariable: [Double]) -> ((Double) -> Double) { - let sum1 = average(multiply(yVariable, xVariable)) - average(xVariable) * average(yVariable) - let sum2 = average(multiply(xVariable, xVariable)) - pow(average(xVariable), 2) +func linearRegression(_ xs: [Double], _ ys: [Double]) -> ((Double) -> Double) { + let sum1 = average(multiply(ys, xs)) - average(xs) * average(ys) + let sum2 = average(multiply(xs, xs)) - pow(average(xs), 2) let slope = sum1 / sum2 - let intercept = average(yVariable) - slope * average(xVariable) + let intercept = average(ys) - slope * average(xs) return { intercept + slope * $0 } } From 58a7f1c9a8aaba7a527261a67cbdca3fc6c9c9d3 Mon Sep 17 00:00:00 2001 From: jsbean Date: Tue, 8 Nov 2016 20:52:54 -0500 Subject: [PATCH 0641/1679] Update multiply(_:_:) in README.md --- Linear Regression/README.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Linear Regression/README.markdown b/Linear Regression/README.markdown index c04e3b3dc..4c98b8995 100644 --- a/Linear Regression/README.markdown +++ b/Linear Regression/README.markdown @@ -113,8 +113,8 @@ We are using the ```reduce``` Swift function to sum up all the elements of the a We also need to be able to multiply each element in an array by the corresponding element in another array, to create a new array. Here is a function which will do this: ```swift -func multiply(input1: [Double], _ input2: [Double]) -> [Double] { - return input1.enumerate().map({ (index, element) in return element*input2[index] }) +func multiply(_ a: [Double], _ b: [Double]) -> [Double] { + return zip(a,b).map { $0.0 * $0.1 } } ``` From f7ec3c45d920155ea47c5c41869f5c984c98f8f9 Mon Sep 17 00:00:00 2001 From: jsbean Date: Tue, 8 Nov 2016 20:54:18 -0500 Subject: [PATCH 0642/1679] Update linearRegression(_:_:) in README.md --- Linear Regression/README.markdown | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Linear Regression/README.markdown b/Linear Regression/README.markdown index 4c98b8995..fde04ed2d 100644 --- a/Linear Regression/README.markdown +++ b/Linear Regression/README.markdown @@ -123,11 +123,11 @@ We are using the ```map``` function to multiply each element. Finally, the function which fits the line to the data: ```swift -func linearRegression(xVariable: [Double], _ yVariable: [Double]) -> (Double -> Double) { - let sum1 = average(multiply(xVariable, yVariable)) - average(xVariable) * average(yVariable) - let sum2 = average(multiply(xVariable, xVariable)) - pow(average(xVariable), 2) +func linearRegression(xs: [Double], _ ys: [Double]) -> (Double -> Double) { + let sum1 = average(multiply(xs, ys)) - average(xs) * average(ys) + let sum2 = average(multiply(xs, xs)) - pow(average(xs), 2) let slope = sum1 / sum2 - let intercept = average(yVariable) - slope * average(xVariable) + let intercept = average(ys) - slope * average(xs) return { intercept + slope * $0 } } ``` From 1c09008e5a4394d0058941debef9bba2c1798570 Mon Sep 17 00:00:00 2001 From: jsbean Date: Tue, 8 Nov 2016 20:55:16 -0500 Subject: [PATCH 0643/1679] Update README.md --- Linear Regression/README.markdown | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Linear Regression/README.markdown b/Linear Regression/README.markdown index fde04ed2d..9e61888ed 100644 --- a/Linear Regression/README.markdown +++ b/Linear Regression/README.markdown @@ -104,8 +104,8 @@ There is another way we can calculate the line of best fit, without having to do First we need some helper functions. This one calculates the average (the mean) of an array of Doubles: ```swift -func average(input: [Double]) -> Double { - return input.reduce(0, combine: +) / Double(input.count) +func average(_ input: [Double]) -> Double { + return input.reduce(0, +) / Double(input.count) } ``` We are using the ```reduce``` Swift function to sum up all the elements of the array, and then divide that by the number of elements. This gives us the mean value. @@ -123,7 +123,7 @@ We are using the ```map``` function to multiply each element. Finally, the function which fits the line to the data: ```swift -func linearRegression(xs: [Double], _ ys: [Double]) -> (Double -> Double) { +func linearRegression(_ xs: [Double], _ ys: [Double]) -> (Double -> Double) { let sum1 = average(multiply(xs, ys)) - average(xs) * average(ys) let sum2 = average(multiply(xs, xs)) - pow(average(xs), 2) let slope = sum1 / sum2 From 40d074807f83eba87d433b3b092afb7587f75660 Mon Sep 17 00:00:00 2001 From: jsbean Date: Tue, 8 Nov 2016 20:56:17 -0500 Subject: [PATCH 0644/1679] Make x variable explicit in closure --- Linear Regression/LinearRegression.playground/Contents.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Linear Regression/LinearRegression.playground/Contents.swift b/Linear Regression/LinearRegression.playground/Contents.swift index f50bdefbc..2d882314a 100644 --- a/Linear Regression/LinearRegression.playground/Contents.swift +++ b/Linear Regression/LinearRegression.playground/Contents.swift @@ -42,7 +42,7 @@ func linearRegression(_ xs: [Double], _ ys: [Double]) -> ((Double) -> Double) { let sum2 = average(multiply(xs, xs)) - pow(average(xs), 2) let slope = sum1 / sum2 let intercept = average(ys) - slope * average(xs) - return { intercept + slope * $0 } + return { x in intercept + slope * x } } let result = linearRegression(carAge, carPrice)(4) From f2564ce7bf38177b1c233a258795652ff8c7dacc Mon Sep 17 00:00:00 2001 From: jsbean Date: Tue, 8 Nov 2016 20:56:39 -0500 Subject: [PATCH 0645/1679] Update README.md --- Linear Regression/README.markdown | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Linear Regression/README.markdown b/Linear Regression/README.markdown index 9e61888ed..f50f4fd66 100644 --- a/Linear Regression/README.markdown +++ b/Linear Regression/README.markdown @@ -123,12 +123,12 @@ We are using the ```map``` function to multiply each element. Finally, the function which fits the line to the data: ```swift -func linearRegression(_ xs: [Double], _ ys: [Double]) -> (Double -> Double) { - let sum1 = average(multiply(xs, ys)) - average(xs) * average(ys) +func linearRegression(_ xs: [Double], _ ys: [Double]) -> ((Double) -> Double) { + let sum1 = average(multiply(ys, xs)) - average(xs) * average(ys) let sum2 = average(multiply(xs, xs)) - pow(average(xs), 2) let slope = sum1 / sum2 let intercept = average(ys) - slope * average(xs) - return { intercept + slope * $0 } + return { x in intercept + slope * x } } ``` This function takes as arguments two arrays of Doubles, and returns a function which is the line of best fit. The formulas to calculate the slope and the intercept can be derived from our definition of the function J. Let's see how the output from this line fits our data: From ba0d7558187b118c390bd9cf5b475aaa9697bacf Mon Sep 17 00:00:00 2001 From: jsbean Date: Tue, 8 Nov 2016 21:01:40 -0500 Subject: [PATCH 0646/1679] Remove parens Xcode convinced me I needed --- Linear Regression/LinearRegression.playground/Contents.swift | 2 +- Linear Regression/README.markdown | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Linear Regression/LinearRegression.playground/Contents.swift b/Linear Regression/LinearRegression.playground/Contents.swift index 2d882314a..648868971 100644 --- a/Linear Regression/LinearRegression.playground/Contents.swift +++ b/Linear Regression/LinearRegression.playground/Contents.swift @@ -37,7 +37,7 @@ func multiply(_ a: [Double], _ b: [Double]) -> [Double] { return zip(a,b).map { $0.0 * $0.1 } } -func linearRegression(_ xs: [Double], _ ys: [Double]) -> ((Double) -> Double) { +func linearRegression(_ xs: [Double], _ ys: [Double]) -> (Double) -> Double { let sum1 = average(multiply(ys, xs)) - average(xs) * average(ys) let sum2 = average(multiply(xs, xs)) - pow(average(xs), 2) let slope = sum1 / sum2 diff --git a/Linear Regression/README.markdown b/Linear Regression/README.markdown index f50f4fd66..b7a5b5ba0 100644 --- a/Linear Regression/README.markdown +++ b/Linear Regression/README.markdown @@ -123,7 +123,7 @@ We are using the ```map``` function to multiply each element. Finally, the function which fits the line to the data: ```swift -func linearRegression(_ xs: [Double], _ ys: [Double]) -> ((Double) -> Double) { +func linearRegression(_ xs: [Double], _ ys: [Double]) -> (Double) -> Double { let sum1 = average(multiply(ys, xs)) - average(xs) * average(ys) let sum2 = average(multiply(xs, xs)) - pow(average(xs), 2) let slope = sum1 / sum2 From c505f184d0cde36e7372fb1bfa3cd046213d7835 Mon Sep 17 00:00:00 2001 From: jsbean Date: Tue, 8 Nov 2016 21:03:24 -0500 Subject: [PATCH 0647/1679] Ensure README looks like code --- Linear Regression/README.markdown | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Linear Regression/README.markdown b/Linear Regression/README.markdown index b7a5b5ba0..3e132b013 100644 --- a/Linear Regression/README.markdown +++ b/Linear Regression/README.markdown @@ -58,12 +58,12 @@ Now for the code which will perform the iterations: ```swift let numberOfCarAdvertsWeSaw = carPrice.count -let iterations = 2000 +let numberOfIterations = 100 let alpha = 0.0001 -for n in 1...iterations { +for n in 1...numberOfIterations { for i in 0.. Date: Tue, 8 Nov 2016 21:06:21 -0500 Subject: [PATCH 0648/1679] Revert labeling of argument --- .../LinearRegression.playground/Contents.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Linear Regression/LinearRegression.playground/Contents.swift b/Linear Regression/LinearRegression.playground/Contents.swift index 648868971..4f18b7add 100644 --- a/Linear Regression/LinearRegression.playground/Contents.swift +++ b/Linear Regression/LinearRegression.playground/Contents.swift @@ -7,7 +7,7 @@ let carPrice: [Double] = [500, 400, 7000, 8500, 11000, 10500] var intercept = 0.0 var slope = 0.0 -func predictedCarPrice(carAge: Double) -> Double { +func predictedCarPrice(_ carAge: Double) -> Double { return intercept + slope * carAge } @@ -19,13 +19,13 @@ let alpha = 0.0001 for n in 1...numberOfIterations { for i in 0.. Date: Tue, 8 Nov 2016 21:07:29 -0500 Subject: [PATCH 0649/1679] Update README --- Linear Regression/README.markdown | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Linear Regression/README.markdown b/Linear Regression/README.markdown index 3e132b013..89f81842a 100644 --- a/Linear Regression/README.markdown +++ b/Linear Regression/README.markdown @@ -50,9 +50,10 @@ This is how we can represent our straight line: ```swift var intercept = 0.0 var slope = 0.0 -func predictedCarPrice(carAge: Double) -> Double { +func predictedCarPrice(_ carAge: Double) -> Double { return intercept + slope * carAge } + ``` Now for the code which will perform the iterations: @@ -63,7 +64,7 @@ let alpha = 0.0001 for n in 1...numberOfIterations { for i in 0.. Date: Tue, 8 Nov 2016 21:09:13 -0500 Subject: [PATCH 0650/1679] Add code formatting to distinguish equations --- Linear Regression/README.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Linear Regression/README.markdown b/Linear Regression/README.markdown index 89f81842a..41af0169e 100644 --- a/Linear Regression/README.markdown +++ b/Linear Regression/README.markdown @@ -30,7 +30,7 @@ We can describe the straight line in terms of two variables: This is the equation for our line: -carPrice = slope * carAge + intercept +`carPrice = slope * carAge + intercept` How can we find the best values for the intercept and the slope? Let's look at two different ways to do this. @@ -75,7 +75,7 @@ for n in 1...numberOfIterations { The program loops through each data point (each car age and car price). For each data point it adjusts the intercept and the slope to bring them closer to the correct values. The equations used in the code to adjust the intercept and the slope are based on moving in the direction of the maximal reduction of these variables. This is a *gradient descent*. -We want to minimse the square of the distance between the line and the points. We define a function J which represents this distance - for simplicity we consider only one point here. This function J is proprotional to ((slope.carAge+intercept) - carPrice))^2 +We want to minimse the square of the distance between the line and the points. We define a function J which represents this distance - for simplicity we consider only one point here. This function J is proprotional to `((slope.carAge+intercept) - carPrice))^2`. In order to move in the direction of maximal reduction, we take the partial derivative of this function with respect to the slope, and similarly for the intercept. We multiply these derivatives by our factor alpha and then use them to adjust the values of slope and intercept on each iteration. From be2167c6c071952b05ee53e88ef4c690cf363453 Mon Sep 17 00:00:00 2001 From: jsbean Date: Tue, 8 Nov 2016 21:13:00 -0500 Subject: [PATCH 0651/1679] Add code formatting to distinguish function name --- Linear Regression/README.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Linear Regression/README.markdown b/Linear Regression/README.markdown index 41af0169e..94ee6aa28 100644 --- a/Linear Regression/README.markdown +++ b/Linear Regression/README.markdown @@ -75,7 +75,7 @@ for n in 1...numberOfIterations { The program loops through each data point (each car age and car price). For each data point it adjusts the intercept and the slope to bring them closer to the correct values. The equations used in the code to adjust the intercept and the slope are based on moving in the direction of the maximal reduction of these variables. This is a *gradient descent*. -We want to minimse the square of the distance between the line and the points. We define a function J which represents this distance - for simplicity we consider only one point here. This function J is proprotional to `((slope.carAge+intercept) - carPrice))^2`. +We want to minimse the square of the distance between the line and the points. We define a function `J` which represents this distance - for simplicity we consider only one point here. This function `J` is proprotional to `((slope.carAge+intercept) - carPrice))^2`. In order to move in the direction of maximal reduction, we take the partial derivative of this function with respect to the slope, and similarly for the intercept. We multiply these derivatives by our factor alpha and then use them to adjust the values of slope and intercept on each iteration. @@ -132,7 +132,7 @@ func linearRegression(_ xs: [Double], _ ys: [Double]) -> (Double) -> Double { return { x in intercept + slope * x } } ``` -This function takes as arguments two arrays of Doubles, and returns a function which is the line of best fit. The formulas to calculate the slope and the intercept can be derived from our definition of the function J. Let's see how the output from this line fits our data: +This function takes as arguments two arrays of Doubles, and returns a function which is the line of best fit. The formulas to calculate the slope and the intercept can be derived from our definition of the function `J`. Let's see how the output from this line fits our data: ![graph3](Images/graph3.png) From ad9f78d936d7e2c15271d2aa854a22d9c24c7d4f Mon Sep 17 00:00:00 2001 From: jsbean Date: Tue, 8 Nov 2016 21:14:13 -0500 Subject: [PATCH 0652/1679] Give some breathing room --- Linear Regression/README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Linear Regression/README.markdown b/Linear Regression/README.markdown index 94ee6aa28..de233fae1 100644 --- a/Linear Regression/README.markdown +++ b/Linear Regression/README.markdown @@ -75,7 +75,7 @@ for n in 1...numberOfIterations { The program loops through each data point (each car age and car price). For each data point it adjusts the intercept and the slope to bring them closer to the correct values. The equations used in the code to adjust the intercept and the slope are based on moving in the direction of the maximal reduction of these variables. This is a *gradient descent*. -We want to minimse the square of the distance between the line and the points. We define a function `J` which represents this distance - for simplicity we consider only one point here. This function `J` is proprotional to `((slope.carAge+intercept) - carPrice))^2`. +We want to minimse the square of the distance between the line and the points. We define a function `J` which represents this distance - for simplicity we consider only one point here. This function `J` is proprotional to `((slope.carAge + intercept) - carPrice)) ^ 2`. In order to move in the direction of maximal reduction, we take the partial derivative of this function with respect to the slope, and similarly for the intercept. We multiply these derivatives by our factor alpha and then use them to adjust the values of slope and intercept on each iteration. From 75c0102bcfb7544c4464cb8090ffa1bfa17fa5a7 Mon Sep 17 00:00:00 2001 From: jsbean Date: Tue, 8 Nov 2016 21:31:27 -0500 Subject: [PATCH 0653/1679] Put xs back before ys --- Linear Regression/LinearRegression.playground/Contents.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Linear Regression/LinearRegression.playground/Contents.swift b/Linear Regression/LinearRegression.playground/Contents.swift index 4f18b7add..f265c3c5f 100644 --- a/Linear Regression/LinearRegression.playground/Contents.swift +++ b/Linear Regression/LinearRegression.playground/Contents.swift @@ -38,7 +38,7 @@ func multiply(_ a: [Double], _ b: [Double]) -> [Double] { } func linearRegression(_ xs: [Double], _ ys: [Double]) -> (Double) -> Double { - let sum1 = average(multiply(ys, xs)) - average(xs) * average(ys) + let sum1 = average(multiply(xs, ys)) - average(xs) * average(ys) let sum2 = average(multiply(xs, xs)) - pow(average(xs), 2) let slope = sum1 / sum2 let intercept = average(ys) - slope * average(xs) From 7513bc03d8df99ba5b117420922e2f90c7a1c562 Mon Sep 17 00:00:00 2001 From: jsbean Date: Wed, 9 Nov 2016 17:48:33 -0500 Subject: [PATCH 0654/1679] Make multiply(_:_:) even even more elegant --- Linear Regression/LinearRegression.playground/Contents.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Linear Regression/LinearRegression.playground/Contents.swift b/Linear Regression/LinearRegression.playground/Contents.swift index f265c3c5f..8b579b3c1 100644 --- a/Linear Regression/LinearRegression.playground/Contents.swift +++ b/Linear Regression/LinearRegression.playground/Contents.swift @@ -34,7 +34,7 @@ func average(_ input: [Double]) -> Double { } func multiply(_ a: [Double], _ b: [Double]) -> [Double] { - return zip(a,b).map { $0.0 * $0.1 } + return zip(a,b).map(*) } func linearRegression(_ xs: [Double], _ ys: [Double]) -> (Double) -> Double { From b5bda5b6453e13f1eae0623d4d06b260a4fecd2c Mon Sep 17 00:00:00 2001 From: jsbean Date: Wed, 9 Nov 2016 17:49:03 -0500 Subject: [PATCH 0655/1679] Update README --- Linear Regression/README.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Linear Regression/README.markdown b/Linear Regression/README.markdown index de233fae1..1a1a1eb8b 100644 --- a/Linear Regression/README.markdown +++ b/Linear Regression/README.markdown @@ -115,7 +115,7 @@ We also need to be able to multiply each element in an array by the correspondin ```swift func multiply(_ a: [Double], _ b: [Double]) -> [Double] { - return zip(a,b).map { $0.0 * $0.1 } + return zip(a,b).map(*) } ``` @@ -146,4 +146,4 @@ Well, the line we've found doesn't fit the data perfectly. For one thing, the gr It turns out that in some of these more complicated models, the iterative approach is the only viable or efficient approach. This can also occur when the arrays of data are very large and may be sparsely populated with data values. -*Written for Swift Algorithm Club by James Harrop* \ No newline at end of file +*Written for Swift Algorithm Club by James Harrop* From 8a5c49af0b15d0e61b7606ad6ac0cad8bb5672e6 Mon Sep 17 00:00:00 2001 From: Kenny Batista Date: Fri, 11 Nov 2016 11:11:13 -0800 Subject: [PATCH 0656/1679] Update ReadMe.md --- Trie/ReadMe.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Trie/ReadMe.md b/Trie/ReadMe.md index 3e3dad3a6..30082a450 100644 --- a/Trie/ReadMe.md +++ b/Trie/ReadMe.md @@ -6,7 +6,7 @@ A `Trie`, (also known as a prefix tree, or radix tree in some other implementati ![A Trie](images/trie.png) -Storing the English language is a primary use case for a `Trie`. Each node in the `Trie` would representing a single character of a word. A series of nodes then make up a word. +Storing the English language is a primary use case for a `Trie`. Each node in the `Trie` would represent a single character of a word. A series of nodes then make up a word. ## Why a Trie? From b40c3d6873caa252b4b63666642f3128e74bf891 Mon Sep 17 00:00:00 2001 From: Raul Ferreira Date: Sat, 12 Nov 2016 16:37:40 +0000 Subject: [PATCH 0657/1679] Fix mistake in the formula that simplifies to (a*d + b*c) (a+b)*(c+d) - a*c - b*c = (a*c + a*d + b*c + b*d) - a*c - b*c should be (a+b)*(c+d) - a*c - b*d = (a*c + a*d + b*c + b*d) - a*c - b*d --- Karatsuba Multiplication/README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Karatsuba Multiplication/README.markdown b/Karatsuba Multiplication/README.markdown index d4c99ec2d..c86f69831 100644 --- a/Karatsuba Multiplication/README.markdown +++ b/Karatsuba Multiplication/README.markdown @@ -62,7 +62,7 @@ Now, we can say: This had been know since the 19th century. The problem is that the method requires 4 multiplications (`a*c`, `a*d`, `b*c`, `b*d`). Karatsuba's insight was that you only need three! (`a*c`, `b*d`, `(a+b)*(c+d)`). Now a perfectly valid question right now would be "How is that possible!?!" Here's the math: - (a+b)*(c+d) - a*c - b*c = (a*c + a*d + b*c + b*d) - a*c - b*c + (a+b)*(c+d) - a*c - b*d = (a*c + a*d + b*c + b*d) - a*c - b*d = (a*d + b*c) Pretty cool, huh? From 16eb36c653007865a199e0d9fa1fc9cf5f2515ce Mon Sep 17 00:00:00 2001 From: Robin Malhotra Date: Thu, 17 Nov 2016 20:03:50 +0530 Subject: [PATCH 0658/1679] Update Contents.swift IMHO, making peek a computed variable feels _swiftier_ --- Queue/Queue.playground/Contents.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Queue/Queue.playground/Contents.swift b/Queue/Queue.playground/Contents.swift index 6b771ccd1..a8be21b08 100644 --- a/Queue/Queue.playground/Contents.swift +++ b/Queue/Queue.playground/Contents.swift @@ -34,7 +34,7 @@ public struct Queue { } } - public func peek() -> T? { + public var peek: T? { return array.first } } @@ -56,7 +56,7 @@ queueOfNames.dequeue() // Return the first element in the queue. // Returns "Lisa" since "Carl" was dequeued on the previous line. -queueOfNames.peek() +queueOfNames.peek // Check to see if the queue is empty. // Returns "false" since the queue still has elements in it. From d7267e911efa8ba6d7b3c26da6c8cef59d82b9c7 Mon Sep 17 00:00:00 2001 From: jsbean Date: Wed, 23 Nov 2016 23:32:37 -0500 Subject: [PATCH 0659/1679] Update code and README for Swift 3.0 --- .../Contents.swift} | 28 ++++++++------- .../contents.xcplayground | 4 +++ .../contents.xcworkspacedata | 7 ++++ Minimum Edit Distance/README.markdown | 35 +++++++++---------- 4 files changed, 43 insertions(+), 31 deletions(-) rename Minimum Edit Distance/{MinimumEditDistance.swift => MinimumEditDistance.playground/Contents.swift} (53%) mode change 100644 => 100755 create mode 100755 Minimum Edit Distance/MinimumEditDistance.playground/contents.xcplayground create mode 100755 Minimum Edit Distance/MinimumEditDistance.playground/playground.xcworkspace/contents.xcworkspacedata mode change 100644 => 100755 Minimum Edit Distance/README.markdown diff --git a/Minimum Edit Distance/MinimumEditDistance.swift b/Minimum Edit Distance/MinimumEditDistance.playground/Contents.swift old mode 100644 new mode 100755 similarity index 53% rename from Minimum Edit Distance/MinimumEditDistance.swift rename to Minimum Edit Distance/MinimumEditDistance.playground/Contents.swift index a128b2dab..d651ddf2e --- a/Minimum Edit Distance/MinimumEditDistance.swift +++ b/Minimum Edit Distance/MinimumEditDistance.playground/Contents.swift @@ -1,34 +1,36 @@ extension String { - + public func minimumEditDistance(other: String) -> Int { let m = self.characters.count let n = other.characters.count - var matrix = [[Int]](count: m+1, repeatedValue: [Int](count: n+1, repeatedValue: 0)) - - + var matrix = [[Int]](repeating: [Int](repeating: 0, count: n + 1), count: m + 1) + // initialize matrix for index in 1...m { // the distance of any first string to an empty second string - matrix[index][0]=index + matrix[index][0] = index } + for index in 1...n { // the distance of any second string to an empty first string - matrix[0][index]=index + matrix[0][index] = index } - + // compute Levenshtein distance - for (i, selfChar) in self.characters.enumerate() { - for (j, otherChar) in other.characters.enumerate() { + for (i, selfChar) in self.characters.enumerated() { + for (j, otherChar) in other.characters.enumerated() { if otherChar == selfChar { // substitution of equal symbols with cost 0 - matrix[i+1][j+1] = matrix[i][j] + matrix[i + 1][j + 1] = matrix[i][j] } else { - // minimum of the cost of insertion, deletion, or substitution added to the already computed costs in the corresponding cells - matrix[i+1][j+1] = min(matrix[i][j]+1, matrix[i+1][j]+1, matrix[i][j+1]+1) + // minimum of the cost of insertion, deletion, or substitution + // added to the already computed costs in the corresponding cells + matrix[i + 1][j + 1] = min(matrix[i][j] + 1, matrix[i + 1][j] + 1, matrix[i][j + 1] + 1) } - } } return matrix[m][n] } } + +"Door".minimumEditDistance(other: "Dolls") diff --git a/Minimum Edit Distance/MinimumEditDistance.playground/contents.xcplayground b/Minimum Edit Distance/MinimumEditDistance.playground/contents.xcplayground new file mode 100755 index 000000000..5da2641c9 --- /dev/null +++ b/Minimum Edit Distance/MinimumEditDistance.playground/contents.xcplayground @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Minimum Edit Distance/MinimumEditDistance.playground/playground.xcworkspace/contents.xcworkspacedata b/Minimum Edit Distance/MinimumEditDistance.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100755 index 000000000..919434a62 --- /dev/null +++ b/Minimum Edit Distance/MinimumEditDistance.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Minimum Edit Distance/README.markdown b/Minimum Edit Distance/README.markdown old mode 100644 new mode 100755 index d72e0dbda..905b358ae --- a/Minimum Edit Distance/README.markdown +++ b/Minimum Edit Distance/README.markdown @@ -6,7 +6,7 @@ The minimum edit distance is a possibility to measure the similarity of two stri A common distance measure is given by the *Levenshtein distance*, which allows the following three transformation operations: -* **Inseration** (*ε→x*) of a single symbol *x* with **cost 1**, +* **Insertion** (*ε→x*) of a single symbol *x* with **cost 1**, * **Deletion** (*x→ε*) of a single symbol *x* with **cost 1**, and * **Substitution** (*x→y*) of two single symbols *x, y* with **cost 1** if *x≠y* and with **cost 0** otherwise. @@ -15,7 +15,7 @@ When transforming a string by a sequence of operations, the costs of the single To avoid exponential time complexity, the minimum edit distance of two strings in the usual is computed using *dynamic programming*. For this in a matrix ```swift -var matrix = [[Int]](count: m+1, repeatedValue: [Int](count: n+1, repeatedValue: 0)) +var matrix = [[Int]](repeating: [Int](repeating: 0, count: n + 1), count: m + 1) ``` already computed minimal edit distances of prefixes of *w* and *u* (of length *m* and *n*, respectively) are used to fill the matrix. In a first step the matrix is initialized by filling the first row and the first column as follows: @@ -23,29 +23,30 @@ already computed minimal edit distances of prefixes of *w* and *u* (of length *m ```swift // initialize matrix for index in 1...m { - // the distance of any prefix of the first string to an empty second string - matrix[index][0]=index + // the distance of any first string to an empty second string + matrix[index][0] = index } + for index in 1...n { - // the distance of any prefix of the second string to an empty first string - matrix[0][index]=index + // the distance of any second string to an empty first string + matrix[0][index] = index } ``` + Then in each cell the minimum of the cost of insertion, deletion, or substitution added to the already computed costs in the corresponding cells is chosen. In this way the matrix is filled iteratively: ```swift // compute Levenshtein distance -for (i, selfChar) in self.characters.enumerate() { - for (j, otherChar) in other.characters.enumerate() { +for (i, selfChar) in self.characters.enumerated() { + for (j, otherChar) in other.characters.enumerated() { if otherChar == selfChar { // substitution of equal symbols with cost 0 - matrix[i+1][j+1] = matrix[i][j] + matrix[i + 1][j + 1] = matrix[i][j] } else { - // minimum of the cost of insertion, deletion, or substitution added - // to the already computed costs in the corresponing cells - matrix[i+1][j+1] = min(matrix[i][j]+1, matrix[i+1][j]+1, matrix[i][j+1]+1) - } - + // minimum of the cost of insertion, deletion, or substitution + // added to the already computed costs in the corresponding cells + matrix[i + 1][j + 1] = min(matrix[i][j] + 1, matrix[i + 1][j] + 1, matrix[i][j + 1] + 1) + } } } ``` @@ -58,8 +59,6 @@ return matrix[m][n] This algorithm has a time complexity of Θ(*mn*). -### Other distance measures - -**todo** +**TODO**: Other distance measures. -*Written for Swift Algorithm Club by Luisa Herrmann* \ No newline at end of file +*Written for Swift Algorithm Club by Luisa Herrmann* From 38dc9eefedf61e5edc838fcb034657df2a22dcc6 Mon Sep 17 00:00:00 2001 From: Joe Date: Thu, 24 Nov 2016 15:36:22 +0800 Subject: [PATCH 0660/1679] update Array2D, Deque to swift3.0 update Array2D, Deque to swift3.0 --- Array2D/README.markdown | 6 +++--- Deque/Deque-Optimized.swift | 4 ++-- Deque/README.markdown | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Array2D/README.markdown b/Array2D/README.markdown index e73d453a6..51e77435e 100644 --- a/Array2D/README.markdown +++ b/Array2D/README.markdown @@ -30,14 +30,14 @@ let myCookie = cookies[3][6] Actually, you could create the array in a single line of code, like so: ```swift -var cookies = [[Int]](count: 9, repeatedValue: [Int](count: 7, repeatedValue: 0)) +var cookies = [[Int]](repeating: [Int](repeating: 0, count: 7), count: 9) ``` but that's just ugly. To be fair, you can hide the ugliness in a helper function: ```swift func dim(count: Int, _ value: T) -> [T] { - return [T](count: count, repeatedValue: value) + return [T](repeating: value, count: count) } ``` @@ -72,7 +72,7 @@ public struct Array2D { public init(columns: Int, rows: Int, initialValue: T) { self.columns = columns self.rows = rows - array = .init(count: rows*columns, repeatedValue: initialValue) + array = .init(repeating: initialValue, count: rows*columns) } public subscript(column: Int, row: Int) -> T { diff --git a/Deque/Deque-Optimized.swift b/Deque/Deque-Optimized.swift index 17ff89e68..6326b457b 100644 --- a/Deque/Deque-Optimized.swift +++ b/Deque/Deque-Optimized.swift @@ -10,7 +10,7 @@ public struct Deque { public init(_ capacity: Int = 10) { self.capacity = max(capacity, 1) - array = .init(count: capacity, repeatedValue: nil) + array = [T?](repeating: nil, count: capacity) head = capacity } @@ -29,7 +29,7 @@ public struct Deque { public mutating func enqueueFront(_ element: T) { if head == 0 { capacity *= 2 - let emptySpace = [T?](count: capacity, repeatedValue: nil) + let emptySpace = [T?](repeating: nil, count: capacity) array.insertContentsOf(emptySpace, at: 0) head = capacity } diff --git a/Deque/README.markdown b/Deque/README.markdown index 7671555dc..5858f3e6d 100644 --- a/Deque/README.markdown +++ b/Deque/README.markdown @@ -122,7 +122,7 @@ public struct Deque { public init(_ capacity: Int = 10) { self.capacity = max(capacity, 1) - array = .init(count: capacity, repeatedValue: nil) + array = [T?](repeating: nil, count: capacity) head = capacity } @@ -238,8 +238,8 @@ There is one tiny problem... If you enqueue a lot of objects at the front, you'r public mutating func enqueueFront(element: T) { if head == 0 { capacity *= 2 - let emptySpace = [T?](count: capacity, repeatedValue: nil) - array.insertContentsOf(emptySpace, at: 0) + let emptySpace = [T?](repeating: nil, count: capacity) + array.insert(contentsOf: emptySpace, at: 0) head = capacity } From 653452a37c4a491e60ba66ff2d79f76b66c39014 Mon Sep 17 00:00:00 2001 From: JJ Date: Fri, 25 Nov 2016 21:33:24 -0500 Subject: [PATCH 0661/1679] Fix for #246: Invalid tree in MinimumMaximum.png and update README.markdown to match. --- Binary Search Tree/Images/MinimumMaximum.png | Bin 12151 -> 11913 bytes Binary Search Tree/README.markdown | 8 ++++---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Binary Search Tree/Images/MinimumMaximum.png b/Binary Search Tree/Images/MinimumMaximum.png index 70fe4ea7b2cee1bd641a785981e0015815f3a594..10b4e635291d25cc899f659679dafdf8c8985b1a 100644 GIT binary patch literal 11913 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 delta 11725 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 diff --git a/Binary Search Tree/README.markdown b/Binary Search Tree/README.markdown index 483e75a58..bacb1ffe1 100644 --- a/Binary Search Tree/README.markdown +++ b/Binary Search Tree/README.markdown @@ -412,7 +412,7 @@ To see how this works, take the following tree: ![Example](Images/MinimumMaximum.png) -For example, if we look at node `10`, its leftmost descendent is `6`. We get there by following all the `left` pointers until there are no more left children to look at. The leftmost descendent of the root node `7` is `1`. Therefore, `1` is the minimum value in the entire tree. +For example, if we look at node `10`, its leftmost descendent is `7`. We get there by following all the `left` pointers until there are no more left children to look at. The leftmost descendent of the root node `6` is `1`. Therefore, `1` is the minimum value in the entire tree. We won't need it for deleting, but for completeness' sake, here is the opposite of `minimum()`: @@ -426,7 +426,7 @@ We won't need it for deleting, but for completeness' sake, here is the opposite } ``` -It returns the rightmost descendent of the node. We find it by following `right` pointers until we get to the end. In the above example, the rightmost descendent of node `2` is `5`. The maximum value in the entire tree is `11`, because that is the rightmost descendent of the root node `7`. +It returns the rightmost descendent of the node. We find it by following `right` pointers until we get to the end. In the above example, the rightmost descendent of node `2` is `5`. The maximum value in the entire tree is `11`, because that is the rightmost descendent of the root node `6`. Finally, we can write the code that removes a node from the tree: @@ -500,11 +500,11 @@ if let node2 = tree.search(2) { First you find the node that you want to remove with `search()` and then you call `remove()` on that object. Before the removal, the tree printed like this: - ((1) <- 2 -> (5)) <- 7 -> ((9) <- 10) + ((1) <- 2 -> (5)) <- 6 -> ((9) <- 10) But after `remove()` you get: - ((1) <- 5) <- 7 -> ((9) <- 10) + ((1) <- 5) <- 6 -> ((9) <- 10) As you can see, node `5` has taken the place of `2`. From e9eeab8c00c7a1674ba8b0f5ac7f1b51356ef925 Mon Sep 17 00:00:00 2001 From: Divyendu Singh Date: Sun, 27 Nov 2016 18:34:47 +0530 Subject: [PATCH 0662/1679] Migration of code to swift 3 style This includes 1. Correct location for inout keyword 2. Correct function calls --- Bucket Sort/BucketSort.playground/Contents.swift | 7 ++----- .../Sources/BucketSort.swift | 15 +++++++-------- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/Bucket Sort/BucketSort.playground/Contents.swift b/Bucket Sort/BucketSort.playground/Contents.swift index f7383746c..c111c3961 100644 --- a/Bucket Sort/BucketSort.playground/Contents.swift +++ b/Bucket Sort/BucketSort.playground/Contents.swift @@ -20,9 +20,6 @@ // // - - - ////////////////////////////////////// // MARK: Extensions ////////////////////////////////////// @@ -38,8 +35,8 @@ extension Int: IntConvertible, Sortable { ////////////////////////////////////// let input = [1, 2, 4, 6, 10] -let buckets = [Bucket(capacity: 15), Bucket(capacity: 15), Bucket(capacity: 15)] +var buckets = [Bucket(capacity: 15), Bucket(capacity: 15), Bucket(capacity: 15)] -let sortedElements = bucketSort(input, distributor: RangeDistributor(), sorter: InsertionSorter(), buckets: buckets) +let sortedElements = bucketSort(elements: input, distributor: RangeDistributor(), sorter: InsertionSorter(), buckets: &buckets) print(sortedElements) diff --git a/Bucket Sort/BucketSort.playground/Sources/BucketSort.swift b/Bucket Sort/BucketSort.playground/Sources/BucketSort.swift index c93b96cb2..e510e51b4 100644 --- a/Bucket Sort/BucketSort.playground/Sources/BucketSort.swift +++ b/Bucket Sort/BucketSort.playground/Sources/BucketSort.swift @@ -27,16 +27,15 @@ import Foundation ////////////////////////////////////// -public func bucketSort(elements: [T], distributor: Distributor, sorter: Sorter, buckets: [Bucket]) -> [T] { - var bucketsCopy = buckets +public func bucketSort(elements: [T], distributor: Distributor, sorter: Sorter, buckets: inout [Bucket]) -> [T] { for elem in elements { - distributor.distribute(elem, buckets: &bucketsCopy) + distributor.distribute(element: elem, buckets: &buckets) } var results = [T]() for bucket in buckets { - results += bucket.sort(sorter) + results += bucket.sort(algorithm: sorter) } return results @@ -48,7 +47,7 @@ public func bucketSort(elements: [T], distributor: Distributor, sor public protocol Distributor { - func distribute(element: T, inout buckets: [Bucket]) + func distribute(element: T, buckets: inout [Bucket]) } /* @@ -70,12 +69,12 @@ public struct RangeDistributor: Distributor { public init() {} - public func distribute(element: T, inout buckets: [Bucket]) { + public func distribute(element: T, buckets: inout [Bucket]) { let value = element.toInt() let bucketCapacity = buckets.first!.capacity let bucketIndex = value / bucketCapacity - buckets[bucketIndex].add(element) + buckets[bucketIndex].add(item: element) } } @@ -139,6 +138,6 @@ public struct Bucket { } public func sort(algorithm: Sorter) -> [T] { - return algorithm.sort(elements) + return algorithm.sort(items: elements) } } From 2245c950594c4e9d7bde2383f0890c1fa95305d5 Mon Sep 17 00:00:00 2001 From: Divyendu Singh Date: Sun, 27 Nov 2016 19:44:26 +0530 Subject: [PATCH 0663/1679] uncomment bucket sort in travis.yml file --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 45f0d4beb..17655c21e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,7 +16,7 @@ script: - xcodebuild test -project ./Bloom\ Filter/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Bounded\ Priority\ Queue/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Breadth-First\ Search/Tests/Tests.xcodeproj -scheme Tests -# - xcodebuild test -project ./Bucket\ Sort/Tests/Tests.xcodeproj -scheme Tests +- xcodebuild test -project ./Bucket\ Sort/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./B-Tree/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Counting\ Sort/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Depth-First\ Search/Tests/Tests.xcodeproj -scheme Tests From 30dd3a043e44e63a0ba11bcfda2c6be26cbf1298 Mon Sep 17 00:00:00 2001 From: Divyendu Singh Date: Sun, 27 Nov 2016 20:00:31 +0530 Subject: [PATCH 0664/1679] move the text cases to swift 3 syntax --- Bucket Sort/BucketSort.swift | 44 ++++++++++++++----- Bucket Sort/Tests/Tests.swift | 8 ++-- .../Tests/Tests.xcodeproj/project.pbxproj | 3 ++ 3 files changed, 41 insertions(+), 14 deletions(-) diff --git a/Bucket Sort/BucketSort.swift b/Bucket Sort/BucketSort.swift index 8363fd867..ef72c67dc 100644 --- a/Bucket Sort/BucketSort.swift +++ b/Bucket Sort/BucketSort.swift @@ -21,6 +21,30 @@ // import Foundation +// FIXME: comparison operators with optionals were removed from the Swift Standard Libary. +// Consider refactoring the code to use the non-optional operators. +fileprivate func < (lhs: T?, rhs: T?) -> Bool { + switch (lhs, rhs) { + case let (l?, r?): + return l < r + case (nil, _?): + return true + default: + return false + } +} + +// FIXME: comparison operators with optionals were removed from the Swift Standard Libary. +// Consider refactoring the code to use the non-optional operators. +fileprivate func >= (lhs: T?, rhs: T?) -> Bool { + switch (lhs, rhs) { + case let (l?, r?): + return l >= r + default: + return !(lhs < rhs) + } +} + ////////////////////////////////////// // MARK: Main algorithm @@ -39,7 +63,7 @@ import Foundation - Returns: A new array with sorted elements */ -public func bucketSort(elements: [T], distributor: Distributor, sorter: Sorter, buckets: [Bucket]) -> [T] { +public func bucketSort(_ elements: [T], distributor: Distributor, sorter: Sorter, buckets: [Bucket]) -> [T] { precondition(allPositiveNumbers(elements)) precondition(enoughSpaceInBuckets(buckets, elements: elements)) @@ -57,12 +81,12 @@ public func bucketSort(elements: [T], distributor: Distributor, sor return results } -private func allPositiveNumbers(array: [T]) -> Bool { +private func allPositiveNumbers(_ array: [T]) -> Bool { return array.filter { $0.toInt() >= 0 }.count > 0 } -private func enoughSpaceInBuckets(buckets: [Bucket], elements: [T]) -> Bool { - let maximumValue = elements.maxElement()?.toInt() +private func enoughSpaceInBuckets(_ buckets: [Bucket], elements: [T]) -> Bool { + let maximumValue = elements.max()?.toInt() let totalCapacity = buckets.count * (buckets.first?.capacity)! return totalCapacity >= maximumValue @@ -74,7 +98,7 @@ private func enoughSpaceInBuckets(buckets: [Bucket], elements: [ public protocol Distributor { - func distribute(element: T, inout buckets: [Bucket]) + func distribute(_ element: T, buckets: inout [Bucket]) } /* @@ -96,7 +120,7 @@ public struct RangeDistributor: Distributor { public init() {} - public func distribute(element: T, inout buckets: [Bucket]) { + public func distribute(_ element: T, buckets: inout [Bucket]) { let value = element.toInt() let bucketCapacity = buckets.first!.capacity @@ -121,14 +145,14 @@ public protocol Sortable: IntConvertible, Comparable { ////////////////////////////////////// public protocol Sorter { - func sort(items: [T]) -> [T] + func sort(_ items: [T]) -> [T] } public struct InsertionSorter: Sorter { public init() {} - public func sort(items: [T]) -> [T] { + public func sort(_ items: [T]) -> [T] { var results = items for i in 0 ..< results.count { var j = i @@ -158,13 +182,13 @@ public struct Bucket { elements = [T]() } - public mutating func add(item: T) { + public mutating func add(_ item: T) { if elements.count < capacity { elements.append(item) } } - public func sort(algorithm: Sorter) -> [T] { + public func sort(_ algorithm: Sorter) -> [T] { return algorithm.sort(elements) } } diff --git a/Bucket Sort/Tests/Tests.swift b/Bucket Sort/Tests/Tests.swift index 22ac751de..b50789ed0 100644 --- a/Bucket Sort/Tests/Tests.swift +++ b/Bucket Sort/Tests/Tests.swift @@ -25,7 +25,7 @@ class TestTests: XCTestCase { largeArray = [Int]() for _ in 0.. [Int] { + fileprivate func performBucketSort(_ elements: [Int], totalBuckets: Int) -> [Int] { - let value = (elements.maxElement()?.toInt())! + 1 + let value = (elements.max()?.toInt())! + 1 let capacityRequired = Int( ceil( Double(value) / Double(totalBuckets) ) ) var buckets = [Bucket]() @@ -71,7 +71,7 @@ class TestTests: XCTestCase { return results } - func isSorted(array: [Int]) -> Bool { + func isSorted(_ array: [Int]) -> Bool { var index = 0 var sorted = true diff --git a/Bucket Sort/Tests/Tests.xcodeproj/project.pbxproj b/Bucket Sort/Tests/Tests.xcodeproj/project.pbxproj index 9a42afa4b..64eb170b0 100644 --- a/Bucket Sort/Tests/Tests.xcodeproj/project.pbxproj +++ b/Bucket Sort/Tests/Tests.xcodeproj/project.pbxproj @@ -88,6 +88,7 @@ TargetAttributes = { 7B2BBC7F1C779D720067B71D = { CreatedOnToolsVersion = 7.2; + LastSwiftMigration = 0810; }; }; }; @@ -222,6 +223,7 @@ PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -234,6 +236,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Release; }; From 187f9236924896710b945d879c426370bfb130d7 Mon Sep 17 00:00:00 2001 From: BenEmdon Date: Mon, 7 Nov 2016 22:38:03 -0500 Subject: [PATCH 0665/1679] Added implementation --- Rootish Array Stack/README.md | 19 +++ Rootish Array Stack/RootishArrayStack.swift | 115 ++++++++++++++++++ .../images/RootishArrayStackExample.png | Bin 0 -> 152134 bytes .../images/RootishArrayStackIntro.png | Bin 0 -> 72856 bytes .../contents.xcworkspacedata | 10 ++ 5 files changed, 144 insertions(+) create mode 100644 Rootish Array Stack/RootishArrayStack.swift create mode 100644 Rootish Array Stack/images/RootishArrayStackExample.png create mode 100644 Rootish Array Stack/images/RootishArrayStackIntro.png diff --git a/Rootish Array Stack/README.md b/Rootish Array Stack/README.md index e69de29bb..842439a0c 100644 --- a/Rootish Array Stack/README.md +++ b/Rootish Array Stack/README.md @@ -0,0 +1,19 @@ +# Rootish Array Stack + +A *Rootish Array Stack* is an ordered array based structure that minimizes wasted space (based on [Gauss's summation technique](https://betterexplained.com/articles/techniques-for-adding-the-numbers-1-to-100/)). A *Rootish Array Stack* consists of an array holding many fixed size arrays in ascending size. + +![Rootish Array Stack Intro](/images/RootishArrayStackIntro.png) + + +A resizable array holds references to blocks (arrays of fixed size). A block's capacity is the same as it's index in the resizable array. Blocks don't grow/shrink like regular Swift arrays. Instead, when their capacity is reached, a new slightly larger block is created. When a block is emptied the last block is freed. This is a great improvement on what a swift array does in terms of wasted space. + +![Rootish Array Stack Intro](/images/RootishArrayStackExample.png) + +Here you can see how insert/remove operations would behave (very similar to how a Swift array handles such operations). + +### How indices map: +| Subscript index | Indices of Blocks| +| :------------- | :------------- | +| `[0]` | `blocks[0][0]` | + +## A Mathematical Explanation diff --git a/Rootish Array Stack/RootishArrayStack.swift b/Rootish Array Stack/RootishArrayStack.swift new file mode 100644 index 000000000..f17f9620e --- /dev/null +++ b/Rootish Array Stack/RootishArrayStack.swift @@ -0,0 +1,115 @@ +// +// main.swift +// RootishArrayStack +// +// Created by Benjamin Emdon on 2016-11-07. +// + +import Darwin + +public struct RootishArrayStack { + fileprivate var blocks = [Array]() + fileprivate var internalCount = 0 + + public init() { } + + var count: Int { + return internalCount + } + + var capacity: Int { + return blocks.count * (blocks.count + 1) / 2 + } + + fileprivate static func toBlock(index: Int) -> Int { + let block = Int(ceil((-3.0 + sqrt(9.0 + 8.0 * Double(index))) / 2)) + return block + } + + fileprivate mutating func grow() { + let newArray = [T?](repeating: nil, count: blocks.count + 1) + blocks.append(newArray) + } + + fileprivate mutating func shrink() { + var numberOfBlocks = blocks.count + while numberOfBlocks > 0 && (numberOfBlocks - 2) * (numberOfBlocks - 1) / 2 >= count { + blocks.remove(at: blocks.count - 1) + numberOfBlocks -= 1 + } + } + + public subscript(index: Int) -> T { + get { + let block = RootishArrayStack.toBlock(index: index) + let blockIndex = index - block * (block + 1) / 2 + return blocks[block][blockIndex]! + } + set(newValue) { + let block = RootishArrayStack.toBlock(index: index) + let blockIndex = index - block * (block + 1) / 2 + blocks[block][blockIndex] = newValue + } + } + + public mutating func insert(element: T, atIndex index: Int) { + if capacity < count + 1 { + grow() + } + internalCount += 1 + var i = count - 1 + while i > index { + self[i] = self[i - 1] + i -= 1 + } + self[index] = element + } + + public mutating func append(element: T) { + insert(element: element, atIndex: count) + } + + fileprivate mutating func makeNil(atIndex index: Int) { + let block = RootishArrayStack.toBlock(index: index) + let blockIndex = index - block * (block + 1) / 2 + blocks[block][blockIndex] = nil + } + + public mutating func remove(atIndex index: Int) -> T { + let element = self[index] + for i in index..= count { + shrink() + } + return element + } + + public var memoryDescription: String { + var s = "{\n" + for i in blocks { + s += "\t[" + for j in i { + s += "\(j), " + } + s += "]\n" + } + return s + "}" + } +} + +extension RootishArrayStack: CustomStringConvertible { + public var description: String { + var s = "[" + for index in 0..jgQMsoAU^;^e| z;i15P=Lt@NE6thW*TMgeJKd81=U7%V-PEyTuwyr`U(<9yK082IrggXY%A)*TveQgY z0`Cq#^iQeLQvAN0S7M%^o-$77T2FUbwuz~>jz!jiK}wzXwCFFFjO%$t!ey^nZ_7m? z{7xD%vSfCA8Rxk;8<9UNSStNsY8&A$0$H65a zWr96C_SXkBJ{;QHO7C$l{ojB3bA<+v0yRMJpT7)C{EAC~;^eyX^}l^R2tEJT1NWb! zb_XX2P5JuDZ?gZeE$FUlAJpHw-TQLdmE+YrM2c@75dNn#!5%&wuJHOlNB#H9nr|Ks z`}$o{D*7*Hf;kLH?mg%4on2OfIUv81u^RjrX(kpeF#P?UJ+V`=CKegrAtdMdF9K2P zcRTZ+Pjd`GM6TAK{pkr|-gEvs7R-;3eO_DV>l4NQA`qb76MubY?MfPrdt&@jvf9>c;=`-u<}uzu>$VKmSDB{{`p$wD$kk+&lT`kE+b^Zu3S_!(&%& zUGK{3={)=Kc6H4H+GO^Vtl`p@tKMZwd6{!d6>m$csC;%fx!z86s0b&vAH^?-SmLy2 zqY~G?GQ%Fi;D|h&tkVK^Cjp%%;|yLoQ8|w8Hf&9Zn{_a+QH1pp)BXJ7*{C2>jy)X>JNrGaj%XV z+^8YUL3-gl86yZ$j;x>5Rfg*o=|q3CpFf%UQb1^58M_}4K~w-*Os*2fA6;YbuKVf$ z@lfSuwftv@p!Nd-adA>#$oJj<@CO(-5&L|X>Cd&O|GfHTJ+S(_b~g8;d3G<$q{#x9 zr`K2_^$4RN&(o~C z;QC#)p`mUS!O=-;EH6Pdy+?UDO2k|h|d@|PvWr8w9vnFB*IYsQoISM8wT#pRc~}lq%fgM zJ73?3&W+c=r~N|%b5iNZOHWU4{McUOl{i~yB|tWgeR=ID~UP44btS86{kGjV(X%(-2F+mT0@#_7D7OlCZK?b44$ntWdW3H>3eR zKHkB^Xyqhb5o^8JK~mIvM#;_QS2D_OIupyw@aijX{rq-P*fPSVG-_(E)f$tpycQlP z@NG~X^z0QQMxUT1LJNoWl-57?8{_k7Q+N1>m>6w+T@-7K`r3$RZIk=xFHf|L0_9Lc z?5r$giDM$UO# z$EQ`~q)FYqt(a1&yE1vpdfGxIbc9tY>@`VZb{HBQe=OwAH7=i#xX6XqK{=OZs2j^z zRo;|^1~7aJ4Vr1D`(a+?TQyCcQd<-g17~l2d2X;LmFMJ|)z)O!nm>5$W|3r(3gXn5Uy=gFBHz6rIG{ z_s2`^9?UNNh%=i(IR|fP8$Dx#OI{t%9`S(fG&YQUof5B#VlJ>8uljNB+vw}6)+?!) z);o;P5Chs(+sNjS&19oo{X%Vn2Ls*RcO-`v^rg|EBA#FK@0o?YO&WgfRMAb^6P+ME zh#e8sPO&~&Q8*CS|9jYPlL4*b~+mIAfns@tS(>bf`vF#g+BJcl34-1sF(< zN?NTPMDWfSeMu-^l@gz#7iCqE7!J>oH5@l)OQJO@Dm6EfaBuhHySuf0&-4ws_P~z0 zfk#zy(`>uHvSNH7ahKp_pI=4}(^g4lEf-D%@m{&-!u3Y{DrP0a-;GE>V>H2I^X}59 zJX>|M^+#Veiwyf~r}#ud#a7;L%reLX$<=ltC4@2Pd27?}`HhnsZ}F>KCPG55ogW{r z)Gx^2@(UQQa;T@ZjoCaUC1Cf)`N68;49^-Lx}HolvoGoQ?{87nXBf9m2XYtmiptSB zy7$BDQKrk^{LD~+PWGZ#U5(JPKRxeq9(BxP2-D;3%M@NZ7eS^$P!Z8R7ONcT zw*#l|OIoG8UW@jtqe@^6LR?*7$4b$+izK#zD z9$r|gHe(Z1dg^33Qhah=kTpd`5Bt?uKw?#7ZiZSm@9NkY8~4BmV`qPizK}Pg3&G}X zjcs@l_J3hM!_6~`^wPW@d3>ojN4us6Um)=`!+GugkDn68ez5N4%|98!_N-dJeQ>lH z$QWuPILxZ$JaP+smT^Qfa?e7X&e&!tNU^0z7MR3MSS_7iQ>`&S3hl@1A{SGP+++-{ zx>o6>)>>gES@k1ZLI{l+7@eXsc=R%8&uSaDFOt5syc_N}7OWs85+yw`E@Dq>sZRw%IK2eRZ8(Por#c zF+2X*8eDc(e8OP4F{z2_lYE@3&XoF8^&LSj+q1@!JFS90D@sjoH*PmXJE6EXSL|a# z?qq9J=z5AJxTy|yr_%~B{rq^k!lBE5#5k0;!oyJjz18o(xy@UAN6989E4b74d?|?y znfV=upQ9V&PsB~vi4}>gz5m7|a{y@!g%+tO19Q4hAu`{PV0rh8$48O;Vo|$$%|VVK z1Mqd>ut-)$cgxwU=JemjV(1JDSETrIHTg>K3>jmW?3F_U-Pg|`_00xKIsL0KjP{$4 zU$})?TU-0~3;Y&$P`xUBFVJ6}w?5cYUrvL1XDc%F?(fDJv;Hn5U4pcYje+mX&QjH^ zN6z~SgD^V<<1VVdygV3q`R6w-KEOs``gk-cpEoy3#=~_RiUYi-gVjsqq@<~`M34D$ zTj+MBkKWBr{@DHPbax(J`;tI;&BN{)4VjoMrO1gEkF0u40TRCLtg82`B=RJ5#qd+Q zU6UKDvok$6QYfOa50qkbds$v`JfbnODV4d}euh&12eTBW`fT;bp9PxIY$-!hqBUXS z7b?8FF%I2J7S$xuo-E_sx)lZGnIHfi3BJ8dK&U4L0s!Diyp4C#*SuDUqK-Cydh7bt z6BS9;_zzDHq>Ngd#*}ZN-Ok_kL=PEStkb zT{}3B-rYDkyV)s{zPb|n&WD(IZN;KmQiHXI&{&E+G{ITEk+b1j?AIQjquNFEQUHY9 zR5l|BQa~@uCx^m#TQMHd$q*sNp0*RERjfM-+Ibe`tu;Z*VsgFq9c_y=>wUH;Zv7m$ z^R9;Sk@m<33bZNL(}Q{A-CXEezvIB)3a>C$h^mOpe%kn9k3f28ojh*dM_ag2lp2N+#p#6}DKJPam*?Y;(F zVPRvv5ri^ZnXbTpwrBFRW<&JEkKpBw_Y1e8b$0 zuO_XeN^hV?&&zO1H;jB3YU1{2{59Zec}qk!<>cjJuSV<|qjL89DNL{Vr;j{c0H{yiPNE@D_6ylXSNE#XIqd@mbn|ORq*Il*oO;opvFp}@@E5B+7_Mj5_R&#>Iic$S z@%mf8bJoVMVGt+L8KKiZMO#r*G8@F9E!kc0Ataa0N){bw^|+*J(2V!#*`_X(+4p*j zYVu6?W4X=7|Ex~ZdeKP;H8bdX-or>stc2ZOt;vE6>Cg^g*Fa2X`W*uaQ;+=$n~L;O z^lRmoyk9Rw%(f+)VheesR&wT|dj`KNpKuM6iH;(<_j{F)&uXiTD$aR+2f*`=@r?&*n3-Jl5>RR- z9|(k=m4n!*Ud7jpjrE{v)#X)f?q%)xJDrhak;;+PW$njmC%P>4n8`;FY{hk+G4}mO zsc7WsJ-L>y+D84Bpl~)}>F?O0Bq_sTYW&Bh$Psw~+HbKjs$n_85^asyIJawO(Y#?v zwZ;_Ws#0R}yj^9hC)S^>v`8fObiecU^xm0e6eRC^ROB)nY4$zCzr7L37AiHp{AOU* z65F|iK9A(_Xc}u3LEMl&)O>K(&eU!sF@}Eeq9Zl#b#p)E zVUL{5_4L?w!f5b~$fK%OMTxt5Ce&+v3$7!);{smyzpZ_KV)&Khd`R%U*9=QiE8|NJ zt>uqL9?Dcudg!@?y7n>HY(9Y@v@}J@8iTn0En-G4mL{PuebxM*$LkUjr_YH< z&RhALG)t0?eDXS3Tc?h$u5}%_AY>bOXLA@{V;t`-;OlKKbINLCjc@aby<8z@R?yid zgFKcS;Up*4&(T{jE|#8yt6p`w)D%sYYLw?;;4#ZkEuS4v-9_j1k5a?B_3zblsIjS> z+P7xIt*USq|5Ki*iBk>6@ziGqAKX#0Vx`{kbmOh?zx21BWpQZB1{SS;#JldQI+`>s z!N;0TXnx&w!Fs?bwW`Ss6?#iGDkjA2*IPc9?`M-Ix{Rg7o5d^*SROYtV0)N(icyW{ zZe3o48$MVgZa2eb8ynR$oUwUx+oA~v-WU72Dzg?|+~anE1+gGF9&}FJ^rPFBnzT48 zy(CX`%!kQ1`We$-mGL{zCKDc1`GUQpR-gpEvCW z>C-qT`ZFN`0pH!TFK!58K7Hu}{XJ3Lq@!n|=J?|-@}#$);A?`la=NL##)>x# z3%bQq`X9K?{^)P8?Q%4z*K+ZyE-o}U?{!+Q_W4dD;mJ7G_Wb+di%##>+T znTNkNM)o-UoTHmCaMa8zWudiaaJw(D?07xw0)8!tg)mm?u}eHxo(%uzAHwVBp6e#v zJhCxdf_ym;Y6SJxL1z-iO(1af%Jy1FVek)aqqEF?I=>htOqKfilXr;GR?#PCX#jG+ zRP)TB>)hIE;AbI!`Um%w;>3hpeci-1KhGByM4WJy5=j|!y!MQ)#8>saKfUL@e$lDG z?su!2SnE>nycy3^o2Fo&;T~&UBBs7dbdnt7LS^C}m09?;<-)PF%)M{0Uq1wdN?gjK z&9kWIh$2F7{sq=?6^LJ1Z5U4xckl9m5tmw%hAL}bj9bU>lxwp@U^9oiITxOlGi=>7 zfUh+Dc!V0Ssl3BH@+O;(#_N=ohfA4amr?R>A)a!pCT<_Is+{m)a&%KDKHS@FyDLA6 zguFI?RD;@!?!gVZt<9F2=f`Js)fY--=)|q=&kCd87L62?nr>y>GrFfwp=WrCHV01U zy-003am_mHj!&Gw_fj9SwHw^~29?Av*4rmreSk4#WLLhV9`NK4DmK-k*4S8wlo#V< zMdOs9j9>Ly--e!X<5z39=f`U~>yBGnL4tHh@0*S2nY^XQ)QK9W7GBE-oS}ErWKM~D zo7|8&rGGts@@MZ#=i1U&M*9~JJ~(nD79}*~69gSBdB~x030?s{nAg^f z_{hbBz0@TG;KS2?k^LYD9IOrYuLd!?|2zDFzz)Hm|IeCtPOR*+N7AcG?>MszNga`M zYgy$<6713_GCo>3Hv-m4tQ0R%JdI9!{O7L9En+&ieuo)2nZ=nlW{WTn^})mRR^YE5YKtJofoH{_aw7ITCovqC zVndv8@a`dYDUASlZ_tf!roC&QIT9<4V?4U751rsAcVZFJj@fJ9N}S(4#DTL7mkJ!- z6(tBWw)b)6_7tE-s`h_QC=O0IkGr=tA_&})9VkHfa&L>EraMih*1y1H8F^t(x;pUV zc$hU|=fik6T?WWhY&nhkUn4_Ap9L#LY0j`8+EEiIONAesk?&oCN#Rj!tVB_(?+X}I zjSgT(^cHgp`__7w0&JT(MdQ#-YS2xTk^IN^D{TrONn)~!J)wawrwIZ<>NON$_S$Rd zN-zZSJ6XE;{>mW9-vHZ|RocaEySu8(1A>gtV;0&I3Aow|olR0RZlBss{08Xcvb=e^J`8qN4@82Xuz`j^`yy?QBJ!!^*o2rwQ zD)+C=kg5GLj(k41e*u?3vjp6fY@xQjf6bZ_+{76iv3~*F^c36_!E#G@e+xf>EREZ% z4nxAfHFq565|E{0r4Hbt_7(Mi8fC3yzy@Bk_XO(>Zo(njwoP$j z+FJ+QED9yRJGY)(-&?&^3fwd|GM#Z~$z-VwB;Y#c;<%?vu#MiEz*6E&;$H7bCD9Scl9NsQ;-UGrU-V!y z%?)R7*T)bikK_3k9^e1_ahwPi(09DqL&mvx4OR+{U&xsqzJCmGd^vD3ep4~Z{hP*! z!SQ`hukA^87r27<=|8X6UhHp33rIV2IQQz_x4=KdK|C4ZB+tIsoDjl*hYxX(he!Jm5+Eo|Tp%{x z&sb^f;PgQXktPQl(u6>ZR*F{YzR~pRgJ4qb7niUnSP&@3!7O7;drrvyCD>IU?51Dc z`?d~sNC5geqDjqCV340Jbg=tt6O3wr{(FMQ*#p($0fW?5%YCA-uiHcg@U)LCFG{ZM zU1}``Pm7ybnBG?r?tNvTwV(W1NZfP-lOOM7b3E6kFE1p|L!lIA1O?yd^9~1bHBAb^ z)7f=N@**tpHD0sWOh!I>BGyS|bzw-_@aG@-&|gqvUu5g@T<@`<<<;H5Ov+2s)Vnh7 z=?OB1jO>Rm&@-HqpeOIh-0EEAn;_-mNFD=&&X-t#ON589EgTS|H;p*UE)9JSAu<#(5W046>G99bz4FEHhfdXt^sT`7R zr5>(k#m`5kKx`2l&nbe46G((tXLC(nOxU-xkBN$#GQ$$-aQtxKj#*zjB>e0(R$s|< ziynx*BkSR`_T0Ep3!!El%ykqaM{BF;vh%Uvbd=nOUjB4x@K7>#iVfu-8VYruhfdsk z5tu!dU@a-rb4A1@#n(oxNAF6PeFP<2`+Da2Pz1+YXrfuYLi2=U7B(hXRJ|el`p&AmbDTgA) z!?5)JduUC$)3W=n4r5XUkZyv5*7O3*q#Sp8W~P0l)NLWYKyaDkIeoD`P4f0AyT=Vs z!-uObTfcelJ{!)901ePv-KtXcsEwtO5e#~vMf>?X4h~=#G4E1YUXUEvA3?qvFhD;w zS7sO!7AG5t@uV>iV~}hskdwkwN_y2&=DqQaF%+|dPW>|AF%buj$cXbT;0!O#2kd&E zeeH=e5~Kjex$3R9$iIKbehB~}g_^^X*JB2fr{PAEF+I0N+--QBytFpka}|<&B@lX} zB3b8!0J@haBe#n^H+~1S-wkP|K6k|g=8Z)Uh54-au)VzK@H_9p@2@rL+tNEzs>C0? zCv<>1YU|I^9H@f`a1`0kuM>tJL%0xg8COUQe9+D|I;4&?*IujCb0QB+Xnv{sE{Er5 zzFw3MkOpmpMp1&iI{nT6%jiA7x**BzKM^-f=WNXDTJ8<_RJB@DO%qC|GU@ zx!R`a@Ke{Ky2W=r&!C#~jUe#wE`c2X1K&DC&}%-d{2syC&W>K43Wu}}Jj;7LnY7cj z&z5?@XTgg&n9pZx6>LHpv4a{y=Db1Hv&Ovt0v*QKFxIJAbV~7Mdk9T2h~6z)Vz@GU zVF;FJ3L+CHs}>juH!;Ndcso_YI*0qbqL&lip$o7XXjcfY7 z7Rsk`;r8WO^HB4GyE9bk`UJGw$cyVwdM9#I!=b z+)Y)#)!$-YAs0du0nAHmyjgrfDN=Bm^V8;dOf4{FYH%nw_2+P4X|%*x2t0EfK%tK=WTf^lzW8yV&syADphBcXC+e%=)2J;usyjr)?~Y2kot zpYslLm;_l*e=@CrBgcc*YxvbusR2$Kjrm!ULHkc|I zZCCUb*?a35oiOnAkx>Cc+scQ>`J5+Po##fvq#1gwBHBo3im5;w>)UXCyGrn^fKGkF zx6=6%PF9uJb8BmB#i2;5#~Qz~t21T}@CxEJaoWSr{omuk)RYdBxFb9%MCiN2`+pR1 zqg7^1M}091!L$A7o7Xl1q_^*29#j3M!O^$Lku|%3HDg5U{3t-~%-M(dVFMU_i!96i zngOm@*rp5Ix8B{ni29QkTQBd1bF|yv;k;2pD1G#JBTwn<%dBWY>)T~ZHMGEl?-J5E zRGnRlTkvL^o}O;23=a^(t{Gz~ClcTl>f0X_q-cn?H|rj=AEca7kf5dQ&z}XaSJ;x( zRZxJ54Le)0fX8AgAb`0Voa9G{)w2vK(XY}81#mK)bcaTHEVKyptNwy9p52UghO}df9`+`gd|? z{p1cUu!~CpJ!}&=kMYmg(N$xApMe*#w|T6LSAR&2rwNl-z5yMC4IIQ{J?mh4j>#T6 zNJF4II7m3m)!eEjUb4^mG`>qL%r(Cd9HhCNPFsN?{%)#+$9R;*Me(LvqFKM`;@B1$ zu}h3gbM|oYTzD93(uRHMTtU&|SK@Muw=1_aobTdcE}kYn$XfSrgQRs&BYOllUD0H7 zdCV#Rz@~_U7@4e2@7#LrMV!ji)=akj)Z6us#}Ju?gJLhI++Bx!Q12|UTU|&Yppu+g z22MTuw@y%%Upt_6fG0;mogl5+Lkgg)EtO7=sjR0BKW~w01zv7DyDc!L&C|D?tqE9= z1shdtQZKSpgDQB-S8tVMsMF&BsfOD7%;;M`8%BayGcp{^8#*h~IX&qxw)PJKx$MYl zdZ3jtP;Bw0rZ@qYw8G)k&Qi)ANL5WZ&`Rdh``8^+7>{Ae`+zrI(#dJ*H3fZkeInFY z?ub`}v>)Q7r@LlMtyC`1lxNjZEkBeJxM#p$eaN zD8J`2`znJJPnXG={{9md#NUM}J2<*;XxNY1=tiVqx;&EyV!5kg{jo%Wr}lAf(JqWCL`q zjDoV11ghT&xc?d*9b{<>=D($)YNgz=$9>j za!j1uO$TXVD=Q}^X8BO1FrUq_NVDcxQRp;8&}k&syG4FKArF#UVq1Vk@!wT2aHyt~ zTXMU#Mfn$V<@^ae2LEv>VCBZBb@DCMJ;4@7!{LzsOUq|IUDQa}(lj@I=H0+um_Pmi zeY>c#^{vbZh+biFuDu`9*y?5C%_*=Mx_KZ|PM!lbSg3<5<$*27aU>G`jM~alehAaW z&1FUj_gW_9#*tr0Ph?jOuGCVQwiK@M`L=jeIuF|-r~R~CSbS+>hFd0BIyzb^m6*FPOkY)&$ukZ z(iGbeZz6NX8kV!savTXB_iZ)3=8G*>r`p*hZKgXuSm`IZ;=1-b)E51EM0|0x*%#E% z(zV?=W+P$nZ8O);uK0kTa66W(xKG=WPO<g27YqloeR7^^TQwgjaZ&7}*`&A< za!YFER%qI3iN(rQf$Z{iJqgUl2vE!%0n3@$muI)@Z(wGJ>Va23v(74J&8pbCpR^&q z;R^DZ$%Dv!nu4kI8bqk!&hZ1JlmPSb@$p;+2_SX%DDv|$;2@&+tu+CL@Pg_*$!!S9 z^wE4~d*1j(8d%wl@zEAv%xbE%U~_eXH`+NCK$u$HQnCYl918J+>{eYDV2J~`M(~}r z)qY9O)f)$A$VxjcI{JK7v*9&&FogP`GeEAQ3M@-xz1s{x*KD1fcMiDN(RvUG9?kWV zPj@qLF1lqDemp2nE$xA*)~Q^50nK8_#KA-*CF!-!CEzom2~wq~vQpGn1vzW`lBtxb z9^dT|MsUDhO2|cMvp5Zrys9ldAGNa&;^o-0>BVnnR8>(mwDwhx&q%%DvF^x%@dv>h-|#uC{*aen zADgJJ+YxmduWDD7wxxjM4=@0i-xdCz(t9B$B@Pi6e+;oseIvz<-5X#9B4q$e>r|5R zL5iOcP`HyBRtX9qMhJ(uYit8EQthL`^(UdFqBeMN%?6-B*>m-15noj4kgV%;);oHx zS6ZMP&WKgnCwpOu8UVS9`whqvf}ptz_1o8gr5+SV#Ytkrfy`|htY>~HwS+rb3J^HY z{Nz>eX^oq@(=j&fEIcul4Ps;$3T=oe%o_!C&s0NtdBp2*9-5o~U_4 zoz9JN%OCH~iM!gEy+B$%_R9rCR%BcU;X%T5hTgdhP%kAtjx%@Z`Lk6n?=94VvE^3t z2N*#6DR||v{#+SCM05~@eNit{1c69ES*VfT7$3&|!k0cL<9~{SraD1_plmj`VHo6X zlu6pdPL&}*J>t&fA9DO7+A*rp*Lhhx%HT+jZ@Q&k9a$WIQ9t{fdt$%rm&ue{F z0Q37>z;4Kq0RC=e^39(lm_gF>eFIG=AZk_;+=rj$JJql1f@YOZNyfEAQG_2cb&WB= zQI=b9-Ee&QdWjt=dd>$Rwz|yX86Gff#}F@}j@0`ckf#+$>q3vI$kA?%>NBBzpRlyq z4U~+DoBW87WvX{V`tGzjaqH#R^`k%d*OcI%JWbavLJiM0Di3mnlHQ-du-hrC z?h;nFfqh$FYTvqxV8yFB zMHpa(N?le*9uW;{!H=S)TXKmfabKFM{BF;)X!)nzO$CpN*CGQ&T3dK2VpC1z#uRA6@& zTEN0noo}X63cV%)23J3kN-|JJ$_s53nC;nlg}3Z)2$uc^VBO zf>S%iM}1F17d<#qRBee^{C2QtIM%**b8}^aRyXdxB^aj&Jj)Ei84^{#z%AAZ0M5w! zaFrlxWA7Zxa=b&4j6gFT#O36BD*dcjfIRdbPfL0y2Iv-M z^q^mTIGbBXvSBJPiGXqtPVDGBC*R5@Z5aEkb&8BUyJ`wBlwe|F@If>t0Oa_v?=Cs6 zSzI~Y`LUg09e|WwYE?Ys7Qdgrsx2{K+Kg`;$6!#%+Wumv_PZoFW276i7Sgm}zYaDP zo8z*n=$;l|Dz*ggT=i|)%T$NOBLKvs(D23`BuTPem_K&>#L4%&;3!pn8e}r5#}rxt zgwNSmgCqRc)K}-)my|da6b_@X4wNV!F=L?5?y^49pBo3W| zbW#mG=Jc2=AAos)R{fk1+m$ad)?u6AbT=5i+$mKP;rbJhY|05_DaL_%Okug&m*s5Xg&h6x@3Oy8KB^`enn^- zap)zKy>Dk5!hzB_P2#Yxf_i%hM0@5g7{38fUfFBX8%@LlUr>q_;j36p<^_emD#phV zu$k5LZv8(hj*CEVt?Y~IJM=o7oKh-i518RmaqGP@dhm^8$K|!@Xc4elI<{1D8AYN@ zKh@=lEvOjb+G1_x!Kr_xMs4JN=M8}$%_3gO@e8?@`5brjm)>Y8>5e!~oh$4hUxfRD^cJWOcnDEBUmu zXAY$O>|y}$hvN%iUl^|5YXr3qf%6j>zpN_1Rttb9Z4H3Bg#%<<>sGN6XSqfE-kI%) z{WwGR!_4uTaG6+`rCrzB-}I2DOra z^#&d=da1O&!8QCJSw5(wg$TLy3%Ddz9Hf)$Y(dFS3`#>G zbVg&*;osH(&GQO05PT3N#L&=qfi~7b<6@LAJt zs654Ia8JDY&B^wV%if3jFDJvZ8gSEPO*+%Hth51cPS|bkaQ~_OzH4aK(m5&7s4QFf zfcOic*=7oek~RJMgfIu9{O_=wNtiDh357!RFaVOuUDii(y(Gx>eHvZGgrt_*2teYb zPPC{*JkRQ=i-52>#Kd0~`ZB7@6y*j7yqn^Q7(O#Ob8I67HJu;99N|WuQ^|a$Re|q5 zA~%MEmon{rI6?m+fiko3i2bhvRokD@nqYw?$^ZoGeCphlM47Cqi?-CDZt5tsA1X+w zdm+fY_&M8$d(Qe+HxhJ5+CVb!AQb^+&M?08#x--SiXvv<)ppxxMqYE!Y;e^IY4*88 z=9I<*!u0faFvFjA9+ATA9@5_epU!J%uh+(`L z0M-K3nN$#J34XWHH-w>Li*vrElpt09SGIfw4IUZ1Y?gTl3n1b$Dl3}wG%RuE&?|T@ zjhH=gzItbSj4k^tJ%~P5mi2*?92zMAA>%HyEJkE|U)qH&>v#+Gl3sw0s&PZ22i)gA zcP&$7=^Q=+4miT)8}E2X(`0wMjC1S$v|As!s_PuSfihV|B~(U{0hfeUh%01qsg^Np zwjrvWga+4<>C@P2{TdKI8L$)B?Syxh@o>y0Xp3Q2q_GE*MR7pVWSU3K)$=b)P?q*Z)sHZ3VMh(xG6k*@&CTUq7ny#_TL>^OJ`04!@! z6{zyM3W;q{PCbjUuPAl^yoApk?V*EY1L{f0MPjDtZajop5SgcrP4#}Zw(uYB zi_i{QUxuXwe)}qh`x0jgQ2oE1v%w!{QbcYF3M^m#1l63B+6HG60D~IzPpq)LQ7kAj zmRe=b{B2i<;_5#pQ*FssbbAa8gd(9fqWWOc*0eT~#?OoGe7Q6zY{~+-q;NuT>UmXb z!WbD{TwFff0J#CcV4K(^>{^$x>R%or2uiWcAGy58af;8@QK6vzYD^Jst}BEn({?`7 z>h_hvKwH$bMG~dt<_SuMi(bZ{%R?}#W&%_l%9&lpFSVW%Mkxz{o2PUGdJ_QGdBnW zV)I~hkH<47dS?>+NGMKy@V9@$@4N%F7c$$SGCs(AB3;8ds1o=hb!vjIC&)bzc?_a0 zwKQlTngY%~jw~|xfHh`P69p>x!z4dH3x)HNjw3{P#5t{7-9un=ZLJecG1M*6SZ`?e zFL4V1omey+#5v5&xOqdpyFU9?s5EB79dJFtKlT5NMEtQ?7-$+ue|!tr$!dZOgJS*= zt)p3vlDzvGK0QUxR9sf^cy!QH!$jO@BAcS${!1bD-pnfEbNO|coi~8g2Q}zO*-G=( zAS6fh;rE*Men(65ePz1V$F?H$+DzoXfgCkIAf9k7DE%F-Tqs>s4I1CX?1q}@Q6UpM>Rj)Y@(OSV63fxt~l zs-M&qi+&(i%hR~}zv@2{Ibyk%VFXKu9V-#wxmbU5s^bWJV z*#ftV{W<{xw;^b69g1`vp&-!Bjq0fqYKBz4lMQaGU}2{9S>^>D`R$3cTg*^{JV`Y{ z%4$P+(A}&T&|2I$^)j>JDqI%Vz-y{UUFIfQpTKBVm8-5oSawbZ%KwlLY2 z1gDerxkLx%XJJLB$V=oDI|lSdxOhNsIceh~_te&*DS{_JD1_%e5|Y+sSAu4B`>zt0 znb*4pzmx0-QHx3U1E=el!<0(Zjg1-q1-zO`Fn)aavgyEXOTi0*yCZlZoyyciKkDG1;;B-rDD$vBy2-?xfB_*E&;CcaPxW=crYZX-q) zI-uIc0W@3W*6*N#C^?5g8DqPhI@Mv>dH=2Pfl?2C_T;hw)Ap!$*sa{rnMV5Wnibmf1VUaw<-E#Cbd2=<^N(>faL zBRGMx78jF?BBCj85V`sRFE8p#m)P@N(xB&rEJ<=P# zms~)86spiEwC>8XiUj?&a8~8}-e z^tbBPIG{5U*sdbZ9V$LwR2Mo79|;j21}!jqa02!1&#u~&03`gIP(DLCR%Bg!3?m`T zFe(?DvxP{^{n05+FHLzyALric(S>J>n8koy0a2Wj@^&9#$AFRftTc3(G{$|zU>h3$ zKN@ks(3!)(LubmMmv##O)VWskkJV++Gzdg`41Oh7jUa*wrJRva@sx6OXSOe8j~5?A z&-vqm$Y~MlAV=ra$oC^zF*1Lmo;L%~o@H+&JRFZq@*%dNp;>A9i!3lEW+*6U2suhW z4sXBbN^@!RyVc8dfefI8(YL=|acHFHr?JddW2) zOsKEf0)`u*E(hpqf`l-`cjxPqB9M5k)np?Nnhu(;K?u4#rkIa=-w2wX{O|=pY0d*E zP4Z+NDmH|`dkHo1tf*mtKeSJj|CGhyriS|VXTgx4hYc`fS$xT@$t1ZY>Zdvfh~c^P z@ra!5vFq0XbH)tJhW7K&DNPljyYh2v7tR+agjaQ_oh$c3g$}q4NzN^SuITXRE+eQo zCJmhI$+PeVt)Gx=-?fi9KjdhWS^U(uQ}PvV9!j{Q3P8o$Q>3Sk=Pyj8Zd-sjLH*wsOUz>rzKs5J7L>l6usf6Oen+>4DwZr`PYLJ(-6 zem)vN#k4^Hb=onE1AGS&#CJ%(JH&TT1by6mrm5M<^}LZgz6_SXxC!Nu9@{zOVKML8o8Is-t4J(Wxnnjb zjv~%PGZ3N0YkIW6P((PapeW%P`)Yk5_yEza(9()T=!DHii?*!h7-3a){?1mW)-o8N zjYh!m-c#mKk&8apTpX)jUQ!$`9on%26Ghxj36-}Gkq6&-K$Ld9#Re*FNxa(`Ixpg- zI0QCE^`Y6yW>s!ER5Gs*M=tVWG2}Tft|buW>zY&ro&{ve5Xd`}aU)198c7RiWKh;0 z4WO;QAb`$U%rt_Y^yA&$WZpVJfqzD36^R#a)LDey=T0XP?!O|1DsD+0@cr#a4Ykxj zkOTHiHQAo3x((WTfih<#okRYFqkhmpnUQ)bc?fgrKrQ1nR%aa01G@#$A5&vn2dH_s z^_^aw1{$qM2-NnjVYgebp!W?nW$-I6VaLY6d#O4H4B1fAuL6ooLPctG^hyvi@Gt@b zt;+d7tx8MPUGgLK-wuRI(yM2ys~4VABcLvT6+5t>K;XAfo&?LAfH9A!fJWnmNF%`E z1XJ^d0xP>}2WC57Cp3cDwte`P4;&e(W#GyROU%O?^qk2Qc(O-P?}DteTG#o9i@-!G zhu;r0hu=wr5aBH7=Io&`oAKnLRld?lEqSJ%#Gsq;a5{Z8*%}Ioac{i14yuBHYK?wY0yX5o#KKRqoeGr zEi`^s8pljXI%$G1A2t3RPJdQMXF?nfO-viBT-W4!0D)Z2*Ic?}VNzR`ptySo>%#+N z7$X?Y^PNRvF*#pO(!OW&gnEI1fDeI&Dh*TjhwH(-d>`<)zVUJJ;-c8KU3MBtPS*Ne z@g9iS0W`%!3b0bQz)EN&Z@#I|t~667Yvv;EeOVKrQER$th>c1yRFPX6avSpDbDizp zn2^RsWpy1S1Q z<)9%w`FEc3CV=97L9gXK5$E;}1XFt4mmHo@UlAIc_FM-{7Z_z3sksPm5BNHz0!(>- z{R}Ob13Z)KHW6)EC*JMECz4p;qc|;Ec!hSe*XLt8wcpQiZVy#rY_zDm8!-n3vYju6cdjPYX21#px7MX z133ZUt$s(Y=g(5Oy(v({WScw9f7qX<@VY@t5s<&z{U|waSAj9xa2~*as`(UYk)%lbNz;3=(`**my#X+-IO%|wC>y?t>1%SVMhJ8T<{#ag0IfUG8CsHOf zM^9FQ$!BtXyW+dOT?t^+W(o8Lpau{@epuxfd`3E;3!~MUF5Yt3vc&=@gM%OdnTy0# zbZb3iK1|?un85^-<}(=o%YsF9K#Px}`aq;^3aL{dHkV(>2HiO*ytIk;{qqpkgL{&M zW_Q#Mq+KbHfw4<CK3B_O7JU8A&KBLW%S|ke@OVy=Yn%5&r3hgrWt@=wj zZ3|1ZO11R2gQ;{W^c6bO71cZLMo{%7>vv`qly1$ul>L6oO;%Gd-Hx{Kx-8y>jh6FG zW~@>40c&x)oE}I2*5zpkVrZi8VoL7 zEzrGo4DpD%2t8k#S-v6eHgDsW_v#hJc`5IrZIG%9`dUun5HLMF_U8}8WtgM1ntr?| z^RLG^1?3hu=VOq^Z3EOV>lb8f5-Sm&-H?STFY9I-Nq#c}O%GFa(}j^^oCHj2i8w7% z=nSQ3ftxnS%+#7;?QeHO=*4f_Ot^BiJ|d+%j!OzV_UDgqqUZg>R^QaPa7pX9O~iBV znwy)?lXsh4KHg`}UhktJNaE)pQ|UVEv(}SmUQZ^RHB5m^+RB~ixde=$ukEc2erYS4 zYW%CWG64$z{PSqQS7?7}Tv7s-<1f*Oj@}N+m`kul;)faFj|V92Qhl2hA(I>mI~u zgJ|$pL|%N_%RtZ?Ga96J0K%qt0|VnXcfqtG87-}~Ti8f#n7-Fiwtiu=oiy!%DhM`8 zkJbCY?e9znJWL>nm4*+d-CP>>c0PZO)#%Q-OXR|*Wt|igm7@6D$~>G#`oU0Ht9W;- z2_E7dIRv`yf;Nb2`G$Re(Ve($PcSgx2(s5ZPC7TagJUF;;?+H;yeL%o&#~hRcsAka z)n3$K&Zn$=Ah`LPEjwRdPDqvDZLLl*_wZ8K50qRYrsnDJAs)W)@F6u0A0OXOqix&1 zg3qN}U{-LsRvM#DMovDro`?9?n7~;cN&{`9YHug25Ny1y1O=UWNBZ@rWHn-(;}oB4 zdA0sAs(X_c$F4Pq10wtD+nIXj*;p@KdOFu2_s6VQaCWxV$UF6=B_#Tbkki#zfag1V zOQo5azje0|9Wq=DE6j0dNbl7a)2~z;CpZtHEy>(cXSr<00cu+!=P*GGsx+i^uV{vraG<(X$3!ewc&2>;S0g9~C?lRCwEzRG-ZUY08ivzK07k9zhXqGMDgqLbeXmCo2VNus)$ zD_ZZ>!1%J!%8dKMfCe#)la+x5Oh3VUF6$PbOLOGfn?C&W(+FG|G57%V97$6!D60Fz z!$H&a9Q|n6di&DYKJs)d255w-p5ISP%ylLP^1=uUnFOu}rX}7d&}Q*bVf3Z;fpPH; z&;{Dl#lxq8)G$lOlJUDyV8gF#r&wXa5wG_&vmUqau6@Id>0m3`$WhhBBC+z^Du@|_ z@95420&M z*Mv8YtS##CWk?YbXbG?iOGGiy=8D#Te^wEPA$vIZGH|+SYl8OE#E; z?mcffVjsR#P#{9^5kmWhdb*vt;Z~Rz_<$ssuhRE`bgOF1<9Np-EF^?<;VOgK=Ta+2 zVqSQ)33TXX{y2;1*q7c1UFQwB>JCiz{^RrW1BJ<@rbFHTdF<;+;n)+Z`?8WvyhGD( ziwJ%HUQAqCnmtV4N!bDVL8TZ;pnD=sr_7u8A(0=Gm9@@AlkWxX=OouiZ!W<`wh_?2k6 zY>kkpPs4Vx8g^c5J=(8zKdjCcFD4)$&6{NMsuF zLmd0&MQLfj=%^^FcflkTM~~g$)>EJPBfleOs~mJ^Hf)2 zc8}au9dD7Z+cl&9#8lgDMg7aj5hDaN_U*-$4s?b$Ao8M?4E`r`cdJU=gkF_&po@?$v8QN8UEnP>^t=EEyzDTDlE{uEe;vbdOH5 zXQ3$O`j9zq0O#1rmY1E%Lqft&bik4o97qx}O(alntk!9x@znXj(Oa~%;;8CLlYf6% z=HaPd4%3Sa_kPDA8FDTPgET|~xpjIV^c(n=r`cAhCz3Ys@7P31Nk6)mD(st3GbGZe zga$caIN+zPP&scZGqJC@gYVq9_}Cw1eF!DyqX$hst(@bojF+^2p{?}@@9a->#H_rHZiX8Im$tOL&0X) z+2Qa|r*8ow%PrX%8gP(Y7axsO7TH~MkL;+>0%{oZ*Df-+@yU54AP0K zXt@scM9*}#dR4<04VZH|j{(Nl@6T7;BlbTA_3O}sy}(}&@_YyB3_sNr8XRQ|udiPp z1yg5rs0Bedo*8MjKZ*I(*%yu>dN1-xAKBX1v|wY82aX%l;#FYoQ5$%OlL#!)6!CDX z4M5%Q65V=q-=PT*z&7v;ceiGD47go)UrEKV+_qo-Jo8~j^YL%b4H=oc0j8;lk$rPO z*;`N$TWDiiw5!C#&b8;xXeh^KM`8)KD(S6TNOI$DJ_6Ev8<1G_VRAP;ef#p8?3)MUF01_V$(Y98<~~c-@j(Q5|F{BE z2q?q%U-^OSpbtrYVg*TA8P$ZJ%9{g+E?EuzfuIKw#gw~d23~7xmL_+YSy>e{Zi-JD zrBUFbJ!MLv@=E5kNb1c~?OGWFrf|{rq@d-5=cv2kRTQsf8n}o3O?00MefGp9C2j0^ zAnyE=cUjVa)4qX?^7k}|4YpqR>I>%naBRLf+f<}pq|vFb4IpBdAR{9yz3{|pr;G(3 z;YCIuH??{^FY8e(lb=`b6jKL56P$Gg)v?7`ZEPLy!0Kwlv3CDUEt3jCe*RG&pJO0R zF8yaNMi24%r7agYH!j_P;EQ!s+u(I zUXO|C=}C(K^4{%OUWb>xIg0OI@<9zzN_BLenD0@Aj#+lABV=0)73QODc2XZ&Z+aZL zF3Ry&oh$y$Mo*rB<8?jd74}Jlp9nJ0q`7Q+)nITAS z_ZLRG>FPr@uk9u?bZNIEmd$!^Lw{H+pWM?k7%PH7O+h4>nDNw^a~FoS4|2~O0Sm)O zx_@|k@)){J!fvOzG{VBd^oEM{JI|Gn{PGhgdEw*jubD!kFOPMBSzFV%H~Whf-sP}& zx~z!q&$}_9(wX(Og8)H(&8akgD z{V+ajKv==)#d@lb+4AI9SnhjXpjYWwObs8|i3`HUV<~_`eY}uYC~rxf~gdRWy)U2{!CnUS??A2eOp+VhOpqv+_rN$r2pc>fP@aPlSmy$O@A-{r$ z*EQHY8_!qZgYME#%*!z^n5;3}C2wSrxI5LU^@03jy_?G(NE8>9y~GBcnp^H->;|BW z(thb4DrIrx4Hy8{bbj5TqN1W(=GcV`|LjSMCA!!O;Y&^jp%Y$wh}6_n3I+y-;1Y8Z zmGD)_#Cr>DxO46!_zpACn`kad@#2_gFC}KFNNjxzX!X21xeJ3H_$)hm{hZ!?$KXum#XCwQK}f%8`Hv z6RPXtpZ#a;8!KS#_wD!Poe>8LjfvCsL`@uU(wG-lO(Gv&rqnUH*`^_fw!lU!AfP>R zDAEqWat4kIy7IM2GEXEPR`wUi?(Xi==m`)+M_uQ&e-tc<{FQHvUw|Seepw_3Z_VT+ z`?_Y8^^9hJ=oc-`jSCC69SCC2rYU8Ac=N$eEJd$1jMa75GDp44IEk{-b+0&q+lH!Z zlj|gEPe~!@Lq&<5|Iz;vV;G4$RFIPdmw$bO1F9mB(U4a_ph+|;uewDZ6e?!PAe~~W zieG-Fs~I_)7Qy&>6^V;+{(N*Oxu^sH4M~0akCOO&;rEmAX`X*^v_{ixaMuEnvKhC- zie{&f>8~wC#K4xGFtN<__bkMyl(<~+=+hl&oX^rLukTw|8|N*xu>~lUBN|TKMb%TEG%4^zX83=uNz!v@Q{ra2z-3}>4UvZbnUNzlea-HOxW$z^Iz2-DaruOm=7!3 zAfy;4jI#-S9B!)i+zbe-`uw;%MieQ{#sBav2CY_gY0sTcHsiE7XK>fVy&#Fuq>@cy zkQLZV9|39%y81J~b7CPF0RuM;xhiD&Ya=#MSc}E594i7%y>W=5Ksi?_G$tm-v;3y+ zjMmne;bls;^2_>k45*lYg~K%F$&)8swKMBe?D6zi3O}WntFbq`!sqx30nWC%h=_L|3b3l}5{MfILP$Faxw^e^$0?jx z9=lwWv|9mSxq`@H_(EtYtD8u9qY~$zV9BlzWS!%Ws3m-nNGvX*xMw$3Qw1Hs}CmzG_*I+cJ87n)-3|nJ^?Ef-|6W4o7jKSBYat{c9l zVB=_$|R@>tW4wPeVJ6fpBs3yyX_}5cNAmiJ4 zERv3ev73kNoE8w;h^ff9BGOuGCe+$NiSo537Fxp!IX6qxaFK9+dRd-8l@|^wn$ftg z9v~j4m^(gIm6qnS=M0-O17xa|gih{XpprYPUOZ0}N=G_Th{jEwY|@h%*r3wKyfE|V z5wXwox_@Q{ejK`z#V8p2Rrx~ADl+Jevj4yk8!yWF9_bt|sIs~rI648pFWs;!$r?)9 zYMhPDF2VMID{K@1%PgC4;r(W!C^ut1EN_iC(4GLuz}_xj?uGX#$JJT<_e1R=fNAsz zM6_t486O-ze~ytR7tO50(GQ5_Nkjw^kh2+ZyOBWrP$M`5+UROJWTZ}$;37marDDm{ z)YP1k+A)89Ts(~7r z9p8195AsByvej7@H^b6S(XMl5h4eK?r=k8Dw{`l2#rx}kH83OEqM4b2VjHTexVmLxBLCIWlkxg&6cKcAQa!u29Q$ENM{P@&bvm>**=+&0(Qe92zp@z?Y8#U7HyEa$wl%aD{BS*|5P6 z=;yBwn$SUOHdniJoQq!unfinPT!c z2;I4p4&#KJz41`4bzF;9qpU~f_m=tr056O?R%@$KwR8&J~6r85@;deWE-L*Uc zt@>|hH?y98_aSIKOrRUHn3}IkOru}7O`kjzsQ>h}?z$?(y9vxS=GI0N8{+_!&zbP? zWTr-rWNW`j_BMPGPPmI>q*(XXaWY4BLgp6xfhwHa)upvhW$~OA-ygMpP&4J*D#uQ8 zT)0R|g!;eh!CUPVa1nTU;yS_vB(&6|YI>t`%tc6m(t#UPoj1R;E|V<42PzcwS7$=$Rprtg zhosKW7i9VB2tK-8>@xh~xKM}v33XbI3GQ!m9GfT_Kl$5xl1?8R`kow2}jnKpn8F5%{lK&N95Ln8{Es0KTfU2k<)3~S` zX!v;dtHoy}i>5EWS=uM-J~;|(IpgD?TtZ_ReENXEwYz_B4Wz4b=xq_SJVE@NP>Pv8x;6yY&{B6JF$g< zLW>bjO3J(ag*wcj=HlEgn&d?*%^52PR!|+9bK1J=!WIQ;4?I0hP^FL?7u0@#TP!jZ z18^fLB6efF5e@0FO7l^kD*NR)U@wp3r@&$m{%bL=p%!E5jrMPg;is7b-UDw-J@8CMHgp?C zWPJ7Z`Zt=SB)=*F64?QPB;w{C#haa?sNJ;`g^l8sNcjD`FcHT6`LqCVvEv`m6&1oC zpSmXFQR`yg^sf!VXmv{hIO3mz%2kY%ib~|6u5O0o`tUJ*q0cPJd|x=%ZceAv(a5WQja>Vfd61_ZCB9V`;%o!{Xu=O6;({dG};GC!gS3@1;-SBV@CX|zgldu7z*Sa-;QhEixM5#uRx0xO+Fkd)V9cK2$@!H4A$C!_*vF&d#yoCZ1> zIe7-4?D#}P#-p8WZDDqc{jD%D33o#t_3{5QR*YL-6UaQ4tsl1fkv_!9I!!9J=(E+w z_bbJY+UGHCTqEkhnPoP%24d^A7{3!Lcw%>j(SKiH!hk|%Q`HOWBApoUwhHRD`*!y^ z%|}82QEmtJJejen;iYi`lto?n!=k*9_$hPlq-7j-sE1G}U!|lA&lQkH7b|24D zhmDS{cvl&!0aJf#@IxZLI?K2B*zT3Mj+@8A6kK zH8<7coKf!ME(P*)(esHaMl=jWIuZikk6Z%<^&Fx)U2y8dV6q4z{h6Rr92_vee;u&f zaKK1QS?z@X@n#s8yK)X8Dsw`OT*~VPsE3)v}xp z1iF@37;5+UV5i|Y65>1&IM(Z^x6%05+nhnY%}2jpsA&KBFivzoLS`oDxV-AkRc^1G z1Qu7Z)szSdRzSrYJd|}@{KGm<>VT79U1Sv7`weAUlS_d_s=HWU5==SBYQ~p+$JQkuffwvLcn?Q?Nk7Ra)!na#l9ii5J} zeGv_K6?n?lUtc^U4g==e)q(6eD`@1RvMyZ``g(FCm?!<8=2=gNyOf8XH3DuW7)>qA z{vc#&q+0r@Mz?|@SJZD>#wtZ zGc^95Ihk=;cUWvQPTr~IY$*W*Mk?cLbD$W|$aDYx%}A}nJP`)Q-3Ajt3v6OuK=~t) ze|<1jqu>>{f@T_KGU{fz0HRNl3n5co zFZ6;wghf5nBOa%-$@~zd)j2*e!elCvyQID!iuw=p-=3c*KQH_=E{*J|re8orVzKFK zG;!O-U^3;f^8E6n=TF2<3mxYPc03W8nm0HjYAV`!=uO7r=_LumH*3k*ouXaS-DgE5 zc3z~Vi?%N~X%jrBPQR|sEIG^6wr_Ly%b;tym>$~|o&`!HHGT%%p@e=ovn}}7t}&n> z@FW{(5Q>Y5g~%lGh(Dr9rjq$0<%){VTz`5#S8>k=!9~}#|DFZly3F z&uq&bO4A!@E7-8X49jycW!38mvtoTz8}EC_OE{)2IZ9a~x)tuwPtxi{F;M~d+>eax zi{;UQlUj{^0bp9qgYWz-Fh6EG4`a*nZDD;4Y}w2i2!Di1FAGs+d}LH=0*du8lt`a3 zkm6fRSvWRg-p8+eDbQJsBV*(WqNSjnE9X9Xm|&PMo66iGah~D%Xl@fUO3Y}gym3eI zOxIF+9fN*<+5AX(j~J#i-J2wS7-QIa#5&~6ILVAoI|B~x!PCkm`Yod3ow69||hx!`PjO^CufFVnju)vt_uH zZerz%Q`YP(kPC?hM13Onkw`Y2Ot(+p+$<1PP;HMB;t5Z48VPRF#>_5X#vjm{oP3z^ zz*alZdH<4$VMmmZJKsk4I=e?`hPhqmx$w_8@#2dHIFvly%`smd6zIR1obP7!o42cV z7Ta`__sLJ<7aIBgFihWjt-nYs-DQW%*Gy%Y)dbC-+>1PKt}T}jf4@w(ru{i)kKWOn zr^S{>*JAn1vuy#ik>}DKU!Yx;Ou;$QR~l=UfcAF=B*P-!I+WYW@W*$x|B=deFf=yo zei-42z&Y7K_&kJIF|&1EJ5A4DTI;I)Jb7KRU*rPbwyu=m$Jz{Ax8mpo{#PQIvYK?A z)_f-YOHssjpFa!h^)aB8)qIO4Og5rcZZbXE>}hBHV*cGqeAn_NgRE_TZtm&Ujj_2i zdd|V84RV6&t@V~7t0Xsx{HWEP10CggI17z9<;_Jt;|;CtDX5wAO8M%C&2vw=U^=-!n z`XSRO*2mApU);VulKxrvc`Pu$t2lp}pBnntDvSQ87n&FdKcuCdZ?fPWbBBpS#>bhA zQAKVwvl2_g*23&x>3ZhQUNk(cV=K?!S|lDTzf@mJ%=s`#YH9ejK+&-z`W^CI$&to+ z)+!H^Xl0%vypw_NDgvD*XNO6A$`$-$xj^CAiZ+Y!@|Y9zSzbytSrR2Ov3${$>)Uqm@N9pp5Cx zKE&j2fm(v$e=Wfk0N&z@lxYaiyr|@gs%ixci#s&=wXn{kpu;b7eLNqtQR)%gxRwUWd9oQ0^>H+sY&vi;RWwHYr0Tx?R5Dvrq{ zUk;0~uio&V>xdp&zn(zFVx#po$QzHVMnk1$p^Riy%b@y`%xn1%`jf76%&gd%Yg7So zPVbw?#e`y6SUU?01uC6YonDlMAGh4|u^n!GvLti00Z^j;vG0@;5wDWM|1PQ)7E0QU zxX#5OQEm$3PdC+pVtko0-f_akkn?(#9T!DBnxtHBUEq?aX{p_57&7YMt+-ngzZE^k zxGA$_NSJ>+m@r*!+voAPMmd$QV43-M2N#A@=eTv$&o40Jj2sMO_~+7WKMvyxZV&Y) z5EK8rV9k{%&{XYzh~#5xQz*&^m|tCBe$!m$ZcQ__b}q|<9LGh?XR>vwIhs)@Eoj+{ zbGd)VZO)MS+_G^r;9S`>CfQM6qjmrR+7~x7Z262T}7;wuSa!EMAK(%L6K1)pg#R)`1mFHZhMI&lHwx86XYCGZ ze_dCj*Y3kuOgYr|HrHLv?KodaFQK%`%Y^LS$}sso-j}91xE{GVQ#{|N z#_%%|2Iy)d9L&_K%=zbTA09l$YYd-*}(JbhXs0ch1Xr%t&p`d9_G%n0{TkM_{mom6~-NW^Q#M8?6 z*0b_o@|>=nf6{dR)(gV?hBBKfR?50ug;v%t+FI}K5@TqtPiV?Sf;?W`W$oFsad(d2 zO5l{KG!!J^^Cw0l7Xh)@Um@9r9QPxdTCrWLSZt-MDw2NJZD#Y+=19$jY!6@J!!bUbG2P8;6sX$26-=c~LpSy?vX7+gCg_fX%hFGmy;9(FIF z0HXb)0P;%3pBVSMOWEay2dn?Bj$Uv3bM3p}AV}5KIqGzb`|_#e_1nZ?avLSrEwMY2 zK9aMqgDKrx7EVOpa@dkxl8x#hw&Nqw<&%7?jMZyBXc4u@WE|!m`|>T5qm;{g<#@m7 zQw;~qdoDfw6)D)WpB1M@3pEKmzMFocnPQC~ilcTpdj$N~dtK0Q$+KfPg417J8})eh z0;*d3f$#nXm3pNDk5lKu!U({;gksSib&EW-B%{^QXZM=Y6!_oly;EvyRy@gUt4a!8pOPSO~%=cg2^Lcs6Fp|G$$}@fE(Zpyi`ZnjoypIUY zig_Qq{S4K|QN&SHieU|VpPEb#=Dy)G)wd9EI@dS%Y!vVK1btW6zP5-#;CZvx-+}$~ zF}yAX3_vwKaJ$ky#1 zMw;>@&5wAKQ(eG_{ETDF%c$BC#XRl#Off+3x@<&-II;G0DWcww4$@4hA_U42uZJ+Jnl;ucl=a?BAYUBy+3jw-ut3wl~$2(&0?;JBUcnSapu*kQ(35$+sRe(=o1ixvE-c zk~emo($1lNWbPd@<{++D{n$b9WAEMAu$jVS=dh)YSFSxqIsT4E9@!#pb4jfvj3J3p z2lb+o-|>c=Ch|q2EsI^yZrr%hU8F0TqghpK^}60|UvGeEcHkz`)%59q%d)W~0Y7>m zZbJfKscg!f%FVY8(oae>1f%+xoR5bS+KfZ7Dcau(GKOAoI9(!8qdXQfY5YEu#b|tT zjI1!U6AhtiL8kRaQ&>uy$->pSu^H3hT;gbrcsVgZq zjZtx?Jl}UZ(ZOg3{03j^KBUJgb`h{n17A%Aeg~dm( zi&G%HSlFGZngiOXlcWF2Ew__aDn&bqS__2@fEBh|aJglUYJlWqF1a;Fn zE?FkSq{zOWXVvWMj;{x@p0DC+Y9(3EI6W+TyA#jEtC(>7G@D2-eJNu8l!*8wa~7rB zt-Ggd*K-o==9+c!2zEa&LuZPDgF_`XEiEvWgvVA4MTf*c@Of@g@ZZWjFpz8(YZCKlR2@&`W;csNInMMM=jO-pi>Rpezj;HJ zai?#?nvzmY!6xx#3u|kcBKrNCMUB2%dHVG;?|LZnw@97xGaIPJ=_I;t9_nwc-F14E z5K>0MSbQ*T6*pt?D3tOwGsW(vH(lk_3%m5=lzx0c5C26MJ&N|+jFN(6hnKQv*V3ZK z_76qhwVsG>viEh|*(;Wu%@<(s-{-)v)I01`#XNwC{P&c?pheu5ihoG=dc53BW6}N4 zf%4&PRBCRw{znt*Lc|Fz11yQCO2E19kls_@a@E$vVM}te5)sKw5VMaMR5c74?6Tk3 z9}m^io0K$bP97IKqq*l1^%V?1|F z;qIv1{<&MJ>f4cfQ%P2f&C!qBZB}zfl~)4S=2Xe5@=RayzwRzx)rdlPxF2Jr>VKWa zn{>Y5VbfQeBGEI^>I*eie*IchSG3W|jlIxI#mp9F1P5TXtYq{HMOw6WUy}aGntQT>G(nP#)zUS@mh=HxC zhZ+|%3;zBPqkPfp@M6a=h?)jpp5ym!TVe=~z;wE-*Z3xk7Ee}3#O)uxe=JFNRT^0~Q&jT%8%ST9ISixA{r!s zD_&uZ7tj{IKF@1a)Dg=f_VB86_ad(pQHuci)NC!YuFI{R_SR?8zCRw^3RRxBT5GC=@E{{_O02#Z4&;J9qaX z&@+z^Z*nCE>UA?rR?l+BTPp-z6QIjd==4=8pbVXVHWL#O9urrV;a=d9@o+FPxZq=) zRq;dgx}D8u$;Wwp_tyPYZQqm2W%nBGr%RO{q-R|Vb=%*O*a)VkSe{$blgU=f$7d{C z?2qQzT8X5Ix9=o>r9%>w+oN(isO&&5v)!tlBH~$i@cU2Uh79I{#|o=*w2DREBX$k} zBdYt_Ir4S6NW(EvGOpC>w`u~5lMKmr@6KP3cs%YwEttf`ENDp0F4Qh2^^IR4%bh$& zBP;i?J@(aUR;y;LO_i5o5|xb_q zYjz~!mmYX+ycBroC}0)EI8FK+b+iS(hD0P*ZM1Swq^k+@e_P3EU?D^?G=x?XL&M>H zA<{BNSh-O5u!r|%XvvA0|Ng~;iy57#7P9p3D~~)g0V0qVNCUzEOH?cDfM5?51?pBq(ETk&Xm3?AI_dT0~ci#8+;(DvYii8U9Zgk ziVn!1ndcuhPNN1C$RLEc{#!o=V_GuBK)Ri?>hu4Hmhwa(kPj?+D^LH{he4ELynXvt z%+xgh0<-&mG8M3o%FlgD^I3TCKU%_TN&t;!JxqXj|2J>o1e!YfUv1@AK~05dIsgpE zO{j)17w=}Gj{4}IN8J&+kmCf5oxialPI#f=Wh-R(p|;oi@#BJZHa0d&Fc}3!MeJ#J z1fwIgmI`nFQ4gJT0EbsY-|Y13O@8Pw<>lqOt85IREnPG=_Yd@d^{pPk%!T?L#((_| zIGvibx4*H(;CE=yLPJCQ5gv~oWpBAdxljyz2yVLtr57W~@m~p{e@+B}$=xu2CgE^tvRT z>Hf#3QJ~@B;Q{-A5XFexI^wh#i+KB1m>Y=3p%KsGXLUR|J~X^AL-3igZ!`oM9^sgg zPZ<4RV3W#Oq7u{2sQ17BUdVZ`zYE@H8fgG#NCN4YLNw@FtEdtaqXcTH1pZtqQTUzf zIj_$DeukuOq~PxxKPQI!D*YwafQ_#f79K7wFM#!>>V(-sRcs#pnr+6^-c3G!P8&P) zq@M(QjA>v=x*y^A{zC~sNpR6=QUKl*`W8X2+F98S6ucQw^Miu-f3#hHam@eG?_$I# zAf;dC;U5^Mwk+v`h9@i{BBHL1b|a9! z_>}2F&(0~p-7IM%@F8sdYU}){7Hj+;EmkxQSjqbpf@QxQyhdtt?|)Kxo5*8W%Bt<6 zrUO*j!tqDhf_Mqcmqs%eLE0gB;%Xw@4<7Muc_Z{?L6;z~zAPcd;iYK+7eK%@SU_`|NuLI1Ot{k%Ov|puEi2sE|>Tb!TI$@6Y5m>ys>A94L(U z=^x;eJ~fw4>d51@{$GG-EVn1}}nW(J^cBDnBG@vq4qM?=uxb3lWUqow;%k_HBuecM1_9Ydd{ z1C^B0$(D)!_Q3xPQfn3`eP-5Iw=?X2_!)OP7+ym19;jQCbAs+5sUd^Q9M*f(&&ZUC zfP4{12&{DZ^(%r8-XNS{;zNL2z9Uo0k+u)cRVwg8H<`}i;6%dY6-m&i!QcHdanwKk z(tZALAQMPZc6Q~KpzHK-Z`<)wkk7Mc?I00MmroM`73~_M*A+H{_rN99zo0Hnb%lh4 z85m5gz)DMOG%2j3g5E7W?cBL2III%zH~)H?0U?I-XmLzk2=v{426Aic>@OOi#>f{6 zTpF!WEq)iHB2<-K^f?%4fFONfU4D{ZW%8C-+2E(+|+}J`Hkzex4x2f-8tT>iPhLHNvJRdHZq5{u&NK7$Ce6hCB)W;=P;PTnK*#{_lR)9>kbMJ#dtr0_TvBn zmMhn^0a9q?Ug7+5NjbR?)a(UN7MRz>+mYbP5m4nJj^Q*0bmzX%NAaIgv>gEzK0+?X zwUhv2{?9z2R@;3jiexR!a2ksL&j^N)B8L>~mh|o0Ki`1{NL8~(a2@3h!Q+FHQE4Ss zM;MNvkfT6Zb7&f)bAS4MXp7#f+|q@ofyR>Tn9Tk=XvSmjZS{a9YM%i*&n&+Er4sx7!8NIgjhS{<%L!ynLpbz1-g~3N z@bvlaB=jkm0Pt6ehT4ym6OaNDo}jz&lUlTfj+(R61`}%OK-X7HZw`Ovi%Zuen#QQ# zhqg5#p_wL28zXoQ3Q+RX|Oo;du&pjJ}D7&+BDbxLL z6XtUJUJBQkslW&fT?ZB5-oa#&#oipEe5AmFVcQ}lD#X##~YFYxW z3MMMd0M^37q(X2RBw8AfbsH?{{?76O$BfEoo-%eG{`@?a7mb2P>*x1iwl!6`?*ruy zQDP@yl$I1uG3SFES_PSt?9<(FX~YuMWBvTy1c@=TychYvchl9p2DKNci7sk;UZMC8 z=Zm}npTn$YY5wfTCwi)(GXbe$x!GfB@MaBJ6rHk!w$sc-BbdGb(<3@)Q)U%l68bC6 zTE|Z`_dyEX0Yl9oBp5E~HrsfCxwe7755Vq|ECeErI1HhH8u>rH!Bf!oHM~l%I{)+h z36Q0ynGAW5e`>diiwFmM?H>u;!(aMdqf9ljVO3{KD(lCzrbhIuDvI) zzr>dI7MSS-?54qSQ=WgUnv_?{0HfrCu@INPHqNsO-MBB862wfE6qJTnwgRmNE z;c-7DM3;31>1PQrpd5rjhaEftQubHJ0NOi(@p6)Ya%8|@_*weW;0Q6d$9L;!V8D?@ z06z4Tlu^_~(AlzW7eS-*FGnwjKvPqt%yWFjlKlv8(59UX4_pPs(#T&*K^yD{8u>e@ z@X2o68v-(cZ4+>3O;JdVmmCYd~E*`q{A_}h0q4f3jMcH?bT1lo8 zw)sX_U!jf;5bX6J1c`_%7wfp`rowuIOZm$TNCnYUDfzd&HLG3KUJ{-U4SSt#vYB?} z@<3A5(=GvOf(EI`YDVG^x-YNy3hnzTxt$*cn~tqT9_$|<(dHc|-oKt{)dWpV`uUWD z)n3^!CweiUwNu|9GLJq+i)Xv@{fqFGoo6>#cf=^?$5ynxBy@OhG6V}qlKouniD)#s z2i!*86hn0`65{*_nJO$#ghuT_bAmm=@l!SZ_jOLU~b1>ankRLB3o*aL8mP{hul`B{5mFwZY z6g`x;1;>E$wvxyX87$yGKFjX^*I%}x({l#1ad;xa&F|p-9X2en^bdNgxIf)(1N0Li;3n(m4HEt zn~kRSO#eFxVXINrmLQej6F~~C1rEFyk!jM`$aEJYv4@x8}J&xT`Vr9G9-6gk!Z7EV79`#F1nluj{JZO2^+S*!4MD&;I zn#e@<+f~KA%TaZ&4tsay+PPa^lKX;D`kfo=H~IAyf}PDn(%a4m>4aRYs)?!6%3H^w>5*ar&&%XR0&MZ#m2$U=S($#$!)Y50AwIz8* zwH<3XHrh-k*zYP`;%H3DmxV7~dIt-&tot{+H)k-5@6TJS)w|{}#IWD~-psui?Vg1j z%^?#R`HXpV2=BfLo^*1gyWMrw@7*nw#oT@CH@B;qA+K_y@BEwceg+MMpe5V)Rv_od ze&A9Z4T@}WRQ+PnaA?2HP}*mlh?(O!>aG@!NaIjEd^|kbK4bRC@v|{B$xMl)%c-VQ zGuk@aM+5k;(l*5^`FOH*%r7h^m27-zuoXBjV?H%kvwDC%(nT+^_17+@+(%Dx+g1b0 z73IDeA^WFniG#eNQMC?g77&cW_*T&X?@@?*FngAL5m5wP6~0SyHdk+fdcBfqzqu7s z;a|lR(%h@fY*PRA;2Z_jyBF1o`)bb8@B9ysjb^!grF*au&my{2TY5C~tHK3n<*nQ@ zj4H2I@YIQ_@XqfQzC34v$BZp%Z^Kh6YpJJrrOGm@(lv1Hg9vxrfF8d2g+5hTTD2+p zth$}x0(IJFr*=L(i=x7TqV18dFz#Qu9){ydb_Q`x%>)=F(DHd-1Lsp(6jageC>jqm z=(<7ETSI(wGS~pk6Yvs$i3Jia%SM_HAO#dI8;4t-EFfiJ^FsM-=w%di)m1A<^A%{@ z=Wx@*wMFJ#-c}qx9m`1yxpMVWdt0k6@25tI!>MZ=qO&{(L?=J@Mi#$5`D7wXS$Z^? z6jMCt-NT%LqMBP(dFjLK}z5nW^P-i>#LdN~D$hG>zPzayh%+{4t z84_Z|R(`4>-*=7}k}VF#T79!J4ju=$A4YCqO;1}Vk6&l#OSNbf#1FgHJ6)=o(|`MO zujQO{z~lBI%5Oghjr>@NWi;b!A7j*E;YM? zu2J;xX-5Kg4`5a{UT_IuyM_Da)u}s?6Ukgwsrfn$V}tMh9zVu~j}f(o!H$r4@}wqt z)$YP`w6YmlDfv5|uq|0JvBHTkjf0IJImP zN*(%hgjmK`bX0~!KqZCJHl?wkup7|qUmXTa;bWnWpc4#<3B>N>Br=e%Mt)RZy&-f5%I<4{uI$g--o z=Kf15;(foft}km!AAQn_Q`wxLCy#R0N#C!U;@H!-C{vN;+Ouz>9ID*PZa3lnstGXM z+{fkDmWjztcz@ScNdHDi%=BP>9;Cw;YaETwTC?MXeE-bu&y8^ZK2MEOzyGKU^zUTShfb1(@L7sV8|oixNr^Dn-(iyrc1v?n?dn-v>8vsskq<5%;ZSx8M(Kiu;<3E0K*X z9+{16tIZdC44>YE1c$t)fqT}rGBi7;Wdj5*-9=kM3VCrm$LABAZ7U8Ont0#}2#5Bf z5}D%mFY?`F<$1O%gEH#9xu!Z}eC3)|0^ioIliQ8uHXLh3Q4V%lUj0lebJ{lFsLua8 z$7=9mRBNuqwN?!oqY*{zdB+OP@{R$0hA8{O!Ia2bWmm%w)1^F??hZXlur$@J8=Ti;l(!}mWKGXHd z91MLh^$@nIF&_>38>j&Qt=ud1L|B=S_H~c48WF)RDapD;P6*m9M97o&r5(dv>0vNC z>&FhEW;>yj(+d_iT#UwQs{%*_1zf_%|BBA}jTwiMGY+~5XSE3X6a_R7@t3QB)Si9FFLGKYo?>*ND%nx6dhb*$m)+AIL}5>SvuzZn?!KfV zH8aySt!QVK+hegeMa#Kc!+EP)s+n`2*0P#s4->>xTL+d@o_keEeDJV3!1b~ zW?5*^)Q#O+o-hy8|NM?1gLug84981{iwV2c;}NX-ZI@re zNXi?=F=24ap?qf|ui=tm##h8027a5r@`U-r^jRsnrgqoOK)1sDRQin7Q8lN|ShjcO zU(-OM? zET%us-yy!!reEMTM+#FcjOZnPYLY#5Fngh9Ju=^0Fo$AlX(6M9T$v!G9_E$;s6@ka za!cBOaPVH*iG{lzP%E{#V){IvL#f+}Ex+8s#KvZ0l97=yFh3>q80Jr+pq_7-OZRRH zwdC)1=6TY$oDY4=N43vaX`Rq9^fgtrB;G-Ls|B0Yu*4tHp#LZ$F!2aKtQ^?L>d$% zq(i#9OG>)CLAtx)U5~NPKELaK-Y6Wgy(2ZLrII@e0?3j7x4sTPyh6oAK+IeDb3Htr#s#|EBN)T+(C$hX}PQ zWcHKV)}*tk)U=h$6jJAL&Y{tMK7Y52)s+(r{|Ou~vD|7-v~uQjJRT)%GuGBmk{ zW>A-+hA6p8q-VljfyxS`^WO#_F944aCO<3LuGYA;OJ&G@WE)<}RxX4Q(na-f;wf}6 zwRI2Typ8I(XT39;qEN5pnzL>{nspV&P|1%j^BW?aJ9_NRC0UC@a%2_>~T4 z6O*_;HJ7Uqfff$&DUnse+`{cbYeXJGm_YG>45&d9!2eZ>mBWMvxJdEYs3-6jfygR| zppPDKoA#bJ-K^4s*9($atXWTrBo_QQSuq5#$+v60UxigEh?;EwWEhbk|G;JC09nRq zyNZSeq~rb11vW^HrdU-diy1P`vXKZ&?u|p=_tY!kF94A^|Sue3R zrwR*i&28QnJZt*Flr6=Jjl(mpJc@UTVE!h~VOJ(0ud|&=wxo5nF)j@3ynMa&4BzCg zPwWZ3sE3j_9We0Xq)$Rfb<$_3F&4g$l{LzX+#8l9cDF<^zy12e%wAtj9WYyYul+q_TB3Tp*x>&+F!T zGZPYm47z|Jq8g@Svv+B>&zTh*f6wVGMmB&W==o-}sr(nj12c$ZzOa96c-eowpc6sQ zMke__oa-2Eu5s!mNA-gE8FRg#lQA zof4$Rw&$6ak(9w&Zr9JrWHKA(Ww(Uqb0VKv@{p94j+%~&Bsp=u)_%&=DUP}mdZf2( z%fvK({K8xYLlsaA zr%a5c$9dX&yCZ=$h3`u07Y7PY2U!#f32%FkLNRd$5)4V^+2O12*u2Veh36G#Y~C5{ zwPpyM^bURED%IIfU2oK3r;qwm138D?tKFvCeo;s@q*H&9c&}XJbeIMKFGer+A@$dW zpiB9{coq{9s!e2@wA@g%#+y>)+lr=KU#OeOc*tA0gEsW-CMZH?wNzNC;iktww< z1HSAfBj33qPM~{_eVr-|Mi%K6`yM$_Ki((O5=&R+9=AeP&Yqnbn8b0*l~VebV|N&+ zRcUV*%QH%ymLCL~Ye-UwYG~7_X}=xKR+in%Q}3IWe{HXl{oZ-XN>#WHDDCelme`aF zsWjR))^=PePO(*3UPHH@9UUojPZ7_Iu;gd$>wI<8Utlud`5-<}d#E5F=sk-fFD=q< zbDK~^cwf0A%R>_^Qs-g~$fm|;=$1|7@}(LC){~C+lk7Ijxie8qZ91@fH^EOa{%m*t zW+7<6V_?nM1A52?s=3nfY~lcCHv~s6Vajw3=?lZp3$qzk z9pKu0OmDMOCn(doIS@8mK45nl^O8}gRaxO`>-D8oMcJr_!Pm1b%LKCBvi)=q_=ycN z-x-e0DG!IJ_gr7g>gspL3ddVB7V@hyG%x@(@kJVY`QQ=Ds>s#<->ich4m%UA>}$Ji=Lr#BX;@;*oF^DYa1j7>ws@Coz@ zin!Zu#65#8j$$AEpd+l(e2ZwcSh% z_M|pax{ntw=MGawVY^;YK0N2SebRiV=mm|L@&GPD4T$VM3kra*E^E};Ium{3NuV_ne7W3?hdsc395RPQ96Yp@)F_?Ei51Rs7Tf!LUMVmv ztOF$TKUoU6AayVn!-(;lUQsASIq)1SRqr1^JlJqFA3xeIn!RPt`mD-(urYy{IzI6b z4yEAxH@J8!?w)x#GfVai1|DJS+7ye=nK@2&u;q2UEJ`Jw@ZsweNs3%U9-}?D^D0ZJ z-WspD2DGkURxRUUrWNKnsAQ+B&3m6SP8;bipvqIL=!+o{u#1S|h5VQG%0GYt5VE>5#HhI4`AJs>AXq6!pV z#TALo=kpuiX_|N();akK3BhmA(bM=MKfZS^+PjeUY&4 zf|mV1hJN9&JvL`A-&XS zorwdpxsO5i1Y8~>hY3f4{5Luux@XY3;dXgfl&f66H#x&&FgVOV#M?b<{jh4rAk=Ey zCn6l>Q9E%l!6;zq#`g|c+cj76Wo6&=He-|%2YXKKdxV5|yMQ^cI(|(~GY=e~Cinvt zFajV?@Eue-y@%1~^?%+0wiM8NLtuwg6ZzG$a4wA4Q1*bbIf4QZff5Q42~S7 zroDj@$7?H^nY!_*)!SI~mr^|RORH#_7W5aupD)6QKx*8MOzoH|)#zAzlVo^%)vI$1&JfHagP&>wnf2rWL0*a3Wj*vg+(W4w82I z42Wdw_Qol(Z{6`ib1@8pVA zul*$HRClLkI2H=W(I!#9_p;_`Q51W2&fN3TXupzxX;f1sex`+tC#amp5IjtuV5`$Q zN0IE;a(hI=o%wgcY{IoEF%;DwA!5_0JRKPjP1*6J6V*6@CwdLQWS zqPE5rK04FDeMBLkqIG(cr!sX>RMdEdSZ35$`h$Y716T|H(Es3U^0Bv9>OG)ApA4>e z?t^OiNptH=-FpRZpb{ZS)2LY+)kt{=Y|^60)Nk$pM++V}yH<*=K>a=N9wInZG*8CL z7XQpZM<~s!6=)lX_4=9L?S`P2t|u|1g4dpVRW6ICet|lMsdPAIJuCJy&ey zj_d+gZKT`ug8V7{^v=pISG{w~!hv~`yrbq+u%PP+9&>fkLdeU1b^r+!qgG%niinir zaLQ|#8bb)T(&rdlB*+k)ieqj(47Y?{Br;f<8(&O<$&^e{Q`Mp9cn%=DnLim(MTmG@ zFoDLNe=M8Gduwa!+~7SAz>+~jHLae*eh0+3PmF>tXQ(zeH%m?2+_>8WF*BrZqyh%2 zoDiBrf2{y8kaW2EL1H(W`J0<3`RXNTPdbEB+*6XAr4UQr&vTB{pGRv(!EqI7`%B77 zs5?QgKMvY6e(@Fhy662ZUJ6dMn{HfgX6^)j@r~1@r&5IX>HyuyA^!`UVDe7lo;&L9 zmy&cw>P6%XnC2%pKYp;foP`~wV+=Ux?Nk1~TrjN|y}{k64{Fy62gkr0;1f(NxFng$ zWD)`(ehX;c9u?+*g-F4-bqRnBAs|jp)q7Z^f;upV4XWVZL0l9J6tI`TfvceJ;80nP zy91U@_Ok%&ukD!3%TWAMQX%aL$5m$Mz4t&3NzJ7UQWQlq!wQg&1r(@fszuWt$=dnS zhu~p25UE4%C!ZSr>{g{(FPyl_Js;7wqR%Vx3bFnnPee;>XK*I#SKv?c)-5_zpUUc2 zPo?EoD2t4S$0mD~G@Z7x3O>AXRi3Ve-AWvH9v@ZR_FU=eoC=$aBiioIKCq>tC zC7+XGzJI<>avYd4_;r+}cxfU9d|m<-A2w(hm{pIU&)q zJv{<+{{0E!AuZa&RP5IZkoJ@$9*1{dcWm3((X9*n-A{|&N;D5RGZ8-2~j^MUx#B~Gg4dM!|tWAU$dLh_3D zfGT-V>SP7!7`*k9ehCPf;Ry-&b=|dQ#ClZN;TC{DvPXxFg(Z#(Z-?{tca#RsN+r1W zC@JTMqD7xa82JR8jqXODtkV=)TgF_|hV`L(sNn?jjNf0GCiU4gExtIzx9)FJ9Xq7b zEb1y9S`(EIPI%0mBf6X1fA|vz>0p@(&tS?|L|6L8sod)G`tvomjOz)e#^#^O zt`evPH}gbDF#}3kT>7%JG;W`*`y|w9#rwfJ35;a88uvtRZQp*KipoyjVlhX6K2#Ii=_$)=f`oZnF7OV@-2#7RJsgXoIm?!) z-C%&6Uvjcud3}LGVywWxxtko=p{bL7B}i=XX)>$JRQka(;4=FGr$qOxEVgd*!F%2i zhPnv(x|fKNTLD*|Vk2qrvmS&Dx(Y7W+yD z`SR0d+c8m)!kfZ@f9dE}QS3JwKLyUnqQti0t~@2AP<38(t?9FtgqYEJ2FkYFE=lX* zB-FtQDf|+`8PO`bsEoX6!x+BJ?*nmf=938i#%?Kyux zu(&|^1{Ek4i>PMa0I4oO(c)Ot=$jRdehv=RKNGN5NCrZMaE;}h{2 zrehtGiHV6?wH2|1#LlJam^sR!Eiqx-Xrb23uG=K>?+wd8_UPy0?dE`fE9!Dk{Nekb zhBVHkhy<888ni7fMGn+#^e0sXGy~2R9oauDCZBlzU}`wo2-%F2z5Bqys5qGCcT~Op zJ)b8avGGAhSqZ)dJE}ogNXwBk=}-+hKKMY-_bMeP z+$L}Y9&@iKN9-8;@fRdhUd4AV4^GoqS!+I?8AR*8ota5a&0L}<*@}mu8adx-2|ng) z_aADtFBr3;-A2eiXF(v)pz`!s6|u?k;m5kWP^o5n^7qn9;g5O*B%7aebK}!D-7pQ0 zjI3@4$zQv$l|0W;TeJsW2@atG6SlODUDTO^Ov?rEjAIc_xFf}Sf{v*rc|;&MXaSDF zBn?Bls&I~o0GURCC{(k!N0FWu)BK6c4dA3mmsG=(L)zXjd(Xb;#ZCO6ou0;EDkocR zu7PdR7#-t%Pevo`X7XV!Uv1N(wXR;$adlxvL?})5=Iv_p`z1n}*ozlFE}_l$JhP~~ znqPfdGS~0z8zes6uAuLTT_Fd$Qav0+LM>=53r}pmVI8qb*7&Jz5xBxNZ?C+j%uYMW zdDtcCWODYd+)~ZwxQ1`#g8jZdP{s3m!V+ZqNw~64eNCe_F6Y%+mysnH4R9j*lSkIv8}4o++X1SzAF5>r zDSDr(8@<=)g%UIpF&HqQLWM)K^mfA=!Z!SQh`grX_kQl{UI_@>EXU=r^+5c7-^^Z+*{p`|I(BB0GFJm+MexY22- zlu+lRpRZJ_FpWCVZFfOAm&MxV4S-kj^E;#UQPCEIJ#QDJKW=yKSzluO8&9dgB8HQ$ zO+B4VJrF%gdTc#e_WH}Qpsp^@o0YTi|3&J{#T(;LAW{nYhi^?!!n-o(wU$>V|MU!s&iiDKc#|<ylgfh&vR*aS zLwPZERbPhniY&RMAzxKZDRriYvi)kR(G|1vsM|)1w{%2{IVc(=$LbgRM%x6BcV;S< zPkXe2{m0>6tvA}^Wd4m}7dxOyVlM%^f`f&i3nz2JhVSmefL+C=-b}wc7La6CfM`dU zszcUCKuOX&w^&u3dR+JEiOP#{_gF4RItZIlZM%&JW8~N>{ZGEYpWIx5KN8>+-{K-~ zOx*Sye#YBf_eTOBW&h@$=YkpyzCqACyaqUt=VYa((ANqh(oie@z(@u*&wdo1=Ob0V zkk#6got_fUX@QD7mGK%MqH`)KC0JyF!LE`XY{C||sKxqhw;#P6L5fc=?QsMB(nt9m z@r-&q(I4|6!HGtsFjx@5w0@aLwL)&bm1M5ozdMiR`Sv%L3GzbdU8uHh?S8r|4&n3@ zW0S2KX+5W-LxD#nEcY1pR$_F~30Xe>CS4CjoXLivxQW}4k(oLDMs9k;td#dp6qAQ^ zQBDx};nDzk`{Tl=uNP)T55}%)L%_k7O`Pj&m&gKlrkYO}j*SwAJYg@bxW;RcESfSe zuzFPGw5SIgC0XaL77*UZZE+e>Ms`7(+ zp;HqoBF&l2qtOKhfzyw-UQ^5qRVA^9tZrrEn*|YfPJ^i)8fF#i-x#a+InLvFGXA{i zVpucaV+QoaN8Q=vgj2GyVFM!3xatoWn_za*#;dJ7iOn3`nnuuCCy_IwPJIiET9Dmg z(%kqURH)X>D@q;q@IT@19*LZXnpm?t>7n>{0pt=w!|~bOGjw`AX(gf&n)S-6O2M>) zmY}a2tBZ^0XXx^3M11p0lsfOLCMCkWcrQAS#QGH1)pA-`W`-;e;o&|o$Fnbe>p`9$ zXi0s$J)(MbO7x*pgBMf9+Y9EAXXnH1vc*}-AtJ_+RxF8la(LaHZRRne9|==lP2_4a zS#PyrjueWu^^8)^(n;RarM;KOL8XDkovm72{3jLKqdV9xYFY*)0eFk~dJ{3#_HweK zhO=jFBw4c-NC*a&mX-mmC{$)MK$=68N68sDHKG#`go3G1Ml^Z-+M7jLIYX&m;?LW2 z!q%JS(NyO$@zkoCuZs8Ku_;kzSD1Uee)ra#^TvxVz~$IBU!Ca*sY{Nmj>4US_Z$g> zal1=f2eDYCA0+2H4zE^KgH7tYa8On0==`Gtn)rOsluh#VOH#6MYGz6sXdC_AvR=@1^v|);Zh>K*p%dRTc8d_e=_Yy3e`{~rO25;F6_oR~ zZ5kF3wkUy!>RTttcviEAB@CrbpBBYu0331%bo~YEz4cG9pFHtB+dYLN3$cLN{`2G2 z<^1BrrNgp|7deqXy1QFs*Cp>!eue_2$8?iCU05K&VZLV``hd^uwb^Y$lS-`r2>I|Q z2PPO}+fr%IeX3~c!@`9&y9S4i!9v?E{yW)$ih54m(1p z4^B^oZ!;Z9vy~-TPF0^VMEH-%h6$&QWm|jJ-(K47wwRG}>WdO^bTK+POrcP}oH6L~ zXWWou9U#nqv(Ws_2gV7A@@#J-+68|n9};9~sLBPJ?LnlMPrhKng=YsI=1P7R6lcW{G*ZVMeq>S`KSEGUk(VkwP&7%nCart+klt)jzcuRx-j#ush z2`-h0v#N@&4q9-Ia~md47~SZ$MO9B{Cp-Xqae-6VA#g`c1Axs(d--}SD2&tTued20^%AeX8?w?6$7K17p$K^?l7YOw)rqDM0tm>zr9Q7t53UPZM zzr52+W{+Xan3#=LGm~M0mqFj{LtzD3?p9;2nZbfAPpCT@>o)S8>cfiFD-SdI8z>= z4XMu;d|&MeeC}yw#X#tBp%-vU1SH%am#lg7#5>86cxbl?!dU!gI*!Q+y!B$RrLX%e zJytwoAD)WAegiCcYPiex}ioem1=5j9#^)#Ai@8dr-#G}FKwfHHs; z^~8ej_9XJ8I7JxAI4MiTvM4tB?{}`k%$|DC^r*XaeIcQAx&b>CHC1){N@YM5Un@)7=O=f>w{+uWmof-I>_I$h`Ti$A2;1#1RMrur3dGAp6$!{$O8v^@6!thodk*>hIsNWBeExh=I8k4JY(dvr^i3IG=MQ zB_n$XS}sR5zg$ZHvg-4>0U0eDkITu1H-Lktde^(2f&&lqsWLWREF+m58nXt2YhFBA zOUChAW}EHbH-wyJ*)C9Y*_x+o^(22cIvp9rBQn6x8Xg57=!YYeTg++1P4KX@tJo+`vYIT8Dyp$lqI*91}xc6Rkp$(2mIiipsRo z%lmAwH#awE*w`Q8iQLfO;NV`lp5?z0a9aEMGX=2wZJs&)bKgR?iTBo%#UHm@W$RIY z0p0^ND0DPw85t4KXN<`Jl+Zv$Bg6TpWcX#>3N(PG0cetnxq(v=xOfjnB@dQ;C-r&r zGjNQDLTI*U?}3ub&n|mX?t|85x<5ri$Rl4RJ`mmGnxob8{W}0Fb|}VYwLlsJmr?&i zIodv;PNUM()4N@+#vq`ed{m=}j%S1hJtH09fFoY}1blia0k{9TNJ8-E+u0K&7U11> zgo%X9ZaRtpx&geLBthUtcSUXR=fs9k8)B5l7|=0>n4 z-sq}w#TO=k#?TAURelKWtrU>$)pj%43PT+hzXjgixa=1A6Cv3@S~36qyGl9WQc>>i z3;xf~A}aYe1NHuz;zI8OVPRnqld%?ys0jb-(?cO{V1Was2>1A36Z20r@y{RTsyFAw z6%F+K`XetGXaN0n01@=(V{)Lf1aGQ81ja3%?$W-YT{1LMGVtL5@T@&5WPQIUqj&D5 zJDc2v#G1Wol$Gs#+-GJLy`KQ4cnJXSk#QY-qP_c{+^_Y`BY?Hf;0SLcV#bELcUvl~ z3ul{ZYVn1ufs>PypB>q+F?rR3SKQ*|hTJyIIdDRYHlRgVW==%aG(nB#=(`_M;pp2e z3o}s7Ng$~nNJd}bCA)db*sm}uBx}HvxWpw&!%YKyGaG`QtyNcvKg*seGEnH3)G_br z@@%`S$ro?CYZ`o^0d!rf1=~GVR|zO2Z?KKj@sFDsy&pXxd!+&;$>sMzRQ;JN-iAqj z7V~I_tLctb3OP?GmQ~X<$Zs}15_3BUhep)gT!u%~pvFZY1LcK!c)n|EKneL+GUU&( z+1`UYex#yj3Qq}aC(xUx{Em!=`qMiJxua2~>Imk;q-pqkJK0Tf*=yJk+KiJ+mNTle zv9*;I81x$u;tGID$8KI5j3nipqRaHTUP_j`g+#_i&I<#b+K4RoiV{r7AvFL_j|Jv^ zE>~$N#OhQpgmU}c>9NPIDm7Z&U0w3Xdn1ZX4G~#)aUt|A$>`ToQG1j;nVUirLKV}W3k|7){N+o%#b$4awLQ;x zOLo}E2u0V->0o412VybXuSK10>K&)-{#rZy@BjCEse9ESvAi36Fh4)9z%D5vQEWcL zMpwDrES;4F5aZ@$UWA zb`faD<0>sJr7|)Kl7@1belZ;7om5->-Y7Fmn#AZA-0LlY0Z!uxU3J>OH^8rpVQ~uj z?(PoUH58zVPyRXp&LJ`qoJ|)znjMYvBO|=*844##5he7ANoO^`zYF3kvgXA`0}mST zUH-k#_~lc84WJXy-CtZ^CtpPm-T_9vBU}1=K~V=EX!vEne*Z+^^6Wc>s(|cQAFkiG zk}%*|sG_sb3;x$nIc0hk6%~Pl8Q~^S8up^;_Du6zR+cMSfNw))mao@p&`246fUp0F z9onb%U$ev?19nwyb?n#wGu0kYjI80YzD;1BY?c7?5}(iG4ewf*1C)zt)o?^)lE#b2i^PAACx9ecww{vO+ZVDfhu2Zx6(;HDj{wl?6n2kMGeCmZsYv0T$|8#!|l zk}@u)^215~N&jRaJ2+tFdT>SmMT!0#k|~nS;MVqqM->6t$4?so5D9_aR<~Y)UFefh zi;S1#JQWls1A?-73U;d8rSfVlV) z*^1UZ;Hl6w=@OTvm6$#rRIJ0Y{RPW;d4NT98eanYUtgXd${!Z8h`eFo(;&qzo(0c) zp2q7vE|V55j?Y|iup2pn;bH-5oUWawsg=ssBWTzt>SVKhR!4 zBP0xqrq%3L&dA8n1Af)W2R$Uyj{omjDo0|dE}9GC_&>9aOZ6Pu15~L+x5o=sT|93N zMcn{>yBc_`By3*%}L9)dRT0Gl7 zlim$0f!M#S=0c|%M?a}wXAQ&K$CaXGs}ub87lXix%-g4|^HY+h{wj4ZQXf~jpsmgw z*3{R%n5^;)VATOwDZaQ<)R}AOnnp%sK%6Hd$5n`v{eOM&E$Ew=;9Asy-=7W3dpVy# zt(;}3`>CQrGeTPv2L|%K=DHq;;pA?i)w$+7hTFLF9v>2LA|0;OYVdRlAu3gRAzYm9 zOerEB1h?C_LxM)2oGA(AQ9?ofKcCtSoe(WL_0jm(-OexGoEJ9yl(IqSltvaZj%;nH zBF@KHc!Sv}osAUB2SQPgfJjdohzpKRZES2H2N=Z1QfB3U?JMsf$S!BmL;SV;UQsj; z#`=2E$oyL3g!F?2n(TI<+125d=N&h&&y{=gh9=AUe=g+=u+yUn|CNvYUVWI*pa{|d zq8<9GRd9<=*4k4SYBx~*?;qm-3Vz5Cd-gw&)$botf(G*ygFQ`aJ_^w4j0X@aV~NO% zIut0Et>)oRQAy7}*}YB8LZLDG4UIw)FAua|Gxtv{g!rn2UrY=E^xnXfJjj{^7}p0{ z&B~PG;=w@8-FoTttdjGONhd5SUKPI);oEvpSsOz|g%~<_Ehazlae~RNB(tv$~^&5-M^Spzvcvlys7-Ux+$28z-={bv=(p> zC86$s0L#=P&FvfMG%&LP|DM?hFcJwSsjUBVR<%JxK|$d%y+x>RXvk2B{_;f^pc0T| z;7QfAbG(SG!Tw_qOXNQ=`@K5MAZ$QIz5mXr_@QtB$1EEiw48nfU5pY1x8PVQ0rh5p z=hg6UCl&>su$(3RJ0PH-Z(j6pMkfRz=oqz}LWqx#+s`#4Qm&a3YIdBON!X6rnS!g?2J#EKFpRO7G!ODMJ$v2jKAys)Tkr1z*v*X$8{m%ZLl$z3L!Dr1p;><5)O{1pj?=fFIj8f07i5+{I5A?z&T*zTjT}% z(mNN2;`QAW%Z}ufujLsbzf0zkfK?+D?GWqEYvip3)I^O-Rd+>a;XY`?aD9nS?(f;} zuJ0?CXKptsN>zL<9|&9{e;;hQ9jZ_^FyokIE_i{%RYlMi$`wqkvhnlrViMu)P+`eO zzFcYhjM%N(G&$AXj@?84iM2sFML#13Z|Hs+xdcz_g}n=+#_2QK;p2Rd*5}V(VETUK z4e>^`^WpPEct78NQSFk2gdk&q1sa? zDZew!RYQH%WtYtuOEFj@DZEgJkV91~n~$(WiljjUna?f6Y0jwmifZOY)3|pQYUQt1 z@i4-&y9|a{56)&=`Uhhq%zR_m``weg`b>F~jSW`g)AhDLi+0x)k+7*}r1cM^lKWmq zIZ&%xvm(S2zB6}rgu{p!G1um%cjsdZ(xHZ7(C7gVg$nDk@K&i(B8I1=Ut08J6lHwzxu1(=Jdj~-dqo^iVRZkX&4q(MS^ zUGrau+jH1gw5WXWn4tQM^yMd!;OucaBbSP+Zj&2n@bD8x%bVj#kLZ!wFI72bD<3PY zZ5CW^oIieS_NeK=&LB6CA5AXdeOWjA)RFt7^M~Q_ka~fcbD&!NW~>Iv&wb52!pZZ; zop`nnzrzs5WOH(ibVcZooERi*we4vtBqaI(V^~neqNR`U?<-+ua8yL3n^=<-`YMg? zP?#7je$4XltOs#^zGo(U^66)_id&^iX6{0=Kk*yjAlo1TH8Cpy9sJL@%c~C2>Str! zy!u%%v<%g!I?E?%(H3mk_Rdbm9g^9%A~aX5>l0sJXNRdqHlhzn66BFFI#AJtXa!{J zS@4E>IdVzqyn5!D)S!({V{6NT;acw>piABI!$*lmyH>e`2F*)6IO(-*6h5~yD>U4c z$z;>I=Gdk|+wImY7cwgEB;L6_BEag$sb&+F%QO!ro<17Sy2$-B<05diruOOr%dkOT zRf@F%s>DMD6N8z+((Q<=?6WEZku9Owx|3mkiyjma5s?YX9k6BjI!@Oevjyakl39Sv zrSVv2H;T>-0d-1NiDT4%PPc>iAPGO;xgMBTObG&D;^EG;{sHT8vCYy$Ox!ord3he* zT93*~92R!Hgifn6k2Dqu@V#Fe2rAPTdz_gj&}#lzl$nQiE7e6G)wfwv)D~&t7YR_d zroMbDf5w|1hZlILxW1Gas)@Dk*EAQxjXxI^5EX1hYEy3V!cL#+!Xjeoarc6M3_kKs z{8)$9NOD3vGU85*KH=Oe)NRE}a+@4c`}@7!-B8GZ59nz&ioi`SV02XJ|K|gOcz55z z@yl(hmm-oAG0oQFkasz=VkHMl0Ye6ihSM~?acpn~$pQRgUN#<^AtqZ9v?kBU_p0Qv zWL1;As;dM^MV^z8;3sNM*XC5sl-Qfl40AuPoid#acA`@HP3qw`6tlKewAK?*^x5;sg?&{W7Xw(b_n)l_3 z3q|t!R|)JNqRT!{)jXA!jJ9fA)>L{gY%BmiHhuB@_;d|zE2H^QyZ)}S4)i$(m%I_;!C`*@z4e>r~8C3CV!T}Sl2(t#y@z@m(v)7uM& zdZrZuKfXxErS!yfw6SnhoWxaI&?9V)jQpP3!SvS;C$X$kujEpzQ-Ljay-rDLfOq<-sS{8GQL* zvYarc`PvP0{2o5P50~4@y&C${X6Zv}FX3gCGx^agX=2|>>FQV*(b3_k#>R;AZr^bU zPu9M6FTh@yA0Xy667Xwoe7mw5ECbW2XFto59nRtC*)>d<>2V{wTJ@YWoJ~C}4{eg3 zmfGXooE0rNIz;)VaoRA>r~8&%nHk6W?iPe)#DGdfs~O$E`!zcHBS3~%fQ&-_0u;F! zF;8d%@yWNW66kyg-_^?)vdPrX;~O%(juBY)yj7R6mqRb!otR}<4}WN8kP4x=7R@m< zE=+BUG|-90m9b{AlfV}_FXpjfcGAUM3zI{t$uQ_~tdSYYlCTug<)ewiD75*S9+1R> z*F^>Moz$rBHENG{57p`6mmz55s(L@zD5xRBiDO~0b-5Fi-H>P~ss-=H21Y*Khk8l% z4gz~nFLFbtEjgeqg&r#*v&6)?!kzJ-NUZv|Wn9kQoiDSvl`EV0r1!`2@qEwBU^p^m zMIJa)x!8%z?3sz_YtSR zIavyFr>#qgj-GG?I5QI-Qsd~K4BDX92#}yvaU$;8dC02hqvmC7?W9xYj%S~a4Q5kkF2Q3CYQ-?}3G`4?g*q20`~br-A0O zjhQO?X;4sOXCNho0c}s8GB-azsYw_20{J?NaaxuUmGslioWQ`ZkOZZ=-fLATj&6a# z0c0vxCf*VHKXopiIv=a)%I8KieLz#@PB)Q=8(srQoP1Zfn1 zSw7ppO9UarJq`8b7HR}BoDbdS77t56<~p1NCv($13 z!SHO(*+oa4ma=6kU1H%n(=3kne5vo$eTHTK9#&vs3RN>)k19`eOv|#PMX8+(7S<{C zTQ$P8kvG$7!3=*%A(2c1+(Vb{s!9@H#UwP_9e+Q+*C9JtipK%8%*={$kvdXyq{B5P zI4J=3q2<`j5f*nP1Za@H3?x@6q)OS>5iFdRtc(XUq~V=*Q}!yUmZ+|A+D~iK6e*9> z9A~ol2s*R4d|ea||zBmV3?I_&!p5=^SC!!R9d%$hXe z8p~4fts=71j+?Kl2XcCu%*FUiE7tGIp0x4VN(CcjQJr&fI8a55ow6j;a=Ku^A*`H7 z7?tGqQ9yg}xSoB1zSOtYDhX_N01~Ju=!-bP2{t4D?+fOQyw}K4^|F>hJmum;XyK{r zVpEG3B;%gd3V&MT_uV^H+qW| z71GprK`Xox-9ZcD$|;aMtlHzY7C=4!Z-}Hh3WCvP)U{VCG)u#Vz3g~y zv!(DND=!~$i_HDB&0@459V4&|%BHWwS(Z!7u0~EUCfMrGC)({c0ElQCS{7(k5DUE-8JPN*+H*AO;&;9cv!14h zEwOx2kUiYUkf>qs=KPKLo=k7hTy73bpyWF7OC3cOqg+gHl5aUu_81H&@~|`a2J)1& z4lxq++LimCpIeGzxk2xE_G`k0uDt9G~q|;=(_(o$QHZ*^whT<`3?Ou;tIYCj-7((Aj>QQdvC4)EvQ8 zX(|HOb+pa_i6w}ZZL$Zk!v2Z7tto6{;##0O&Y{Vdm(IhkL~pvFW9TWtm#UG+m8^8m zQoOEO)SBK{_4r#}VeWL5C4FB@azq3P>k^P)SMc%#6k?FGYTL8+7#2y&8dwtiCjnpN zg+99t{^5Q#kOcOqGAN`BOk~5aYMv2>c6oXr6x>8L#g)=0=9OX}3pfB1>Q330=(VC$ z>x5G|rB3;LZeRGY9oRc^B%d02BVl>O>8aa7>t4exh=0ag9#G0Qj z0SCAl-yYl-YSme7kJG-XwR@yl`Q97h;QG>t-pRlSM?2vNTs`y@7^Q!YO# z-)eKyS8tq>wcd8BHf5Pm?vFvo;{2w=Z0v_ zJn9=JOA{iLwa6fqJgS+&AuJY)?ysn^qiniF$ph_}875B=QFD%a(jkeJd-UV&{-U}%@DjirHrhM5l}N{5kO0yB`t1%oq{{7l?GDJvQqnAl-r#}bwv zn2Dl~zmx@nK+rJoC|@!+(FxE14kzr;u3rZVw}XmJUo{@N8i2{I-<~2Z9o7Ev_ zWi(fdgIx0*oYeiY>KhtXTck$L4Bp{a_i7|Y?PPUz5w557meiSH;ew`xM-6?lGd}C- z`cau9jl1YaxK}KW=bHpUpQ?4)Mmu)=xfzMV;jSgfyl?M<)&(s0HSY&^I(OOw<)W*! zgL2LgozexX`n&y@*$v1SGUd)noHIE{MDi};x-COP1!kiSx?5J4-@NFM8Y<7O>szaK zd03?4^rnxQ8D0J}<77+$uf06TJljH&y?=5|g;~7$aEQeFnvV3Q@a|E`J5Nv&WpFys zb#k7&v#qYK#uXPA|IxGZ4he}O6#irsA%hW*hgHC&S41{cuJ>2bvJ3L|rFh@hbC^)1K+t*f4`cd*Hi4K#Ee2h#9U1hSkA49#cUwl(tEhg%3Ki#7v!J^a1KTuBOZs$ zOkyr}oSG?PYZ^l&l|FaE$hDWvDo%@mC4#da5=rH<(FP6E@0O!U8Fot?jMztzV03Qk zx;Hcx$J4i^Nliw2yRE92;NtGjJjS*rio};&v6YEWBU=RT5Ka$xi>Zm9rIW7fk3?f8 zaJpgx7FYXJxzdZmaKWF+>BSyR1(tZHY}F%Ei~dO}_jeT2;Tejg`)-cO0u~;;Hnzv| zpOS;i-DgVJj5tZM=!7p^dXE=#_;e3JQwquv>%hVf-t~HUgDwNjosg}wzr#rJ-rXH$Fxy%1O`nXY zw%?9^xs9KYqq1$hhvA-Vo5ToxL%ij_xD(4{gX%D?#5L?O8=-QlNuY_Xh>F{*HLQ@P zeoyGn$81#5(hILp<2gGF-f~sQ-vzZh3;27f=I!Bb#d{S<=*Vs^>-97Qc;rX+Y1k?{ zE{|%R6YuoLKVw635_q`p;MC7Tpgh{Gwbei?(Yf|PZF2zQG=$J&oWBOkm$y4LCu%4`M&A?7FGYmLtOk3r~-Y2kUT=pRx@S2lCJ9C zuV!Y^61%T&<_rYaKyFN>D!`~vJttT^rCel$)^^ez)k%5Trl$18zt_&p+ub_@lj9gy zY+&Ipkufo+sUlY41R14lBAPgQkHK$4z7yClX_QnMVM5CzaBce2*bD`|PYlpGOgYCr zN(nk;4C6C7yI7?OY>{X9)Ppxar!&$MU&w9R)|3(=o#+-ip6hAxW?v< zT%NfiZHUVnz^UOuYDyE3k|gWi6HRfbD)e{rmeA2sLB)A|sRlU9r%%tKDz<%SzR}28 zn8O~22=kgVavD9_32mxC_C(2Busd(&{ZtEH+c>T#YGFTgBim#3NdZ24$Ht{%%CiM_ z+KpP>TV86zuW$4D4MO5>6FyQgm)Ngx1tjrc0TJw2M*3&_?`MO05$VZRmk1tS^fg%I!OR|q$Z3ukiSQNFp=2h%eW=CbdSXFKPsb{o?TG>wekcBD zKwp+5y|}%(`8GdaYmda`7?=5k%f1`N#nKH2R3aeMhCk(q#T&@Yd(WefM7ihyU2qlJ z@$up%E?0S3W@E(;H|9ume#ePk%K=qRfm&wR^3x;+jpjN%uVqZhMzqiOD!4eugln=c z(8Rg&>!s0f0oV0btomfg`LCMX)Y;A_d*)2yA~k4BiM&cAJJM^$=h;wNd)VfKx}@Cj zW^9#{y5BWmALk%Cu@VJTQ=UCcDp00{zVU3Andd@ESoB^g_Bh1|8NXOZkP2`5o*et3 z`doidRwy}Ga?wEEV9MLmcSbSnO9rr0w9I3W3fBqu8|g@^8mBi8Y{yA#O>UlLUqlRbGV z8=sjSw2)$`)Oc3-Fm66*O82V0;0g}9wL@=p_G2u1gS?@KJHamU(~oR-h6}!&61Da! z^!F+O47VH@dRMkT-%nfP^Buy-7;85hj_4;3uesy+Xv_yY5Y(jrv*=>AxS6UaY3%Q< z{y)avI;_ep>=%|21QC!Fq?Jw;=}=Nq=}r~tl5R;sN-0GF=`QI;N&!VmkdOxH?)vTx zI^(?WIp_NRnagp8y&u-I*1GE#W|T+oHtt%783f)qBGrowd+};cO4y!ALwI(q=&%Oc zX|#`obp^Y@>h55oefG?1O1|Y$+Op1F*)O!PhQW)v)lLuQ&84L=o3syM!0EX1RqgJ| zFB2A~zcyAi44;!Wev*~GK#r##n+~p5T}sh=M1IMq(4e#EO@*2u^6?j+E``Ia`1Xw~ zf(%>lmUk4Qhx4K8RZlOJrm4kRN!q#cg~j^M(YmUiPveT&4u6p*EU9TfPkpo=PNC+) zUE@xctfRKZoYS4(j8$IhrLL`px?2W!GO+$LZ@TU*i^Cnw=lFfwKg|q_WXR?8GBYxp zob6FpI0GUvAj!8IMP6I@7kn^-e7wZL#z$eZK~G(6C$n+$_Vx-?Qacng90gX5LFtSD z$0J(Z-fjVriLR7;_!W%*FWg0(LPO3UEdT@tBQXm)hjm#g&S%mIFohFPq$cflZ?acmzM-0vDdMJ4?0+ZRBx z%@hUVOti#mfWLpG2YPln`sOX7xBoWvt=SNj5*XhItQNv|>l?iK>EHE9}_Olh~ zLGx-B6F8M*h%6BK@W+oImz$s%z0T(p>Vafb?Tnr?<)rHYIVa+m2R-eQFKg~FiN0=Ptdao;Upy%>?$csR^ zBzgs0=*`i<2MDHk+--}gc;ndbSAP^51>BMgd;5u84hr$66kdEmE+vyTDTUwI=frLZ zdil3BRb@}n1^;{=0K1y59^eS9o&yjoJqjSUrR~-cxGBJH7GLAhbne_j^qEqUhz$*5a2y#bp?+BLFV{=O$MuEcZ$V)fp1EY2e|!+4 zi5f`J{)hVaXPLYnBZPWsSy*JhdV;VtW4$LxwIF)2|3|o#R}I9oA?8-w|G7MgS|H$z z>b}3}t?s2{4jrP8fGoPNuAWiFMsyBFo9SNv9-9npSYzh?n3DgA0TtmzC_rv5^ebFi z4X&@nShYj-dx95msLFgp z>YT~qm-K%ptW1(#4M%M@k8=O#@1if7C>~5i!edQ^a5k8(h89=IWr18ekw3_ZGc1Nv zC}Q8cBNk+~Me%=qh?fYW2zv63%E{STqt^k>XRr~)e_>45f!1zin(b9_x@qh0!YReN z^hfLDpN%Y{f;H^EGXe+*DZg``DrJp2d6EEnxb|-_(0}VS{S9Ms{*m12Q^0^6(6>@@ za=8=PmB-Uf$R6KsyJ#vEzDt`jsd_j)J0@7tsXiAEVw{Oyj|+VG6@+5C5@yYt(Y)76p$Q6O2J9{~d#zL(7tZcQyZV)}C=p3>mOyc1hn0 z7zr|jkkn#_)H)<9jan}SdPdI9&KlKwA@!j@o@~n-GfBpZa@YrmHi8=hXCneMi&*J2 zOo(q57^+pJe?3Ng_x0=72P*97n`Zm3)Ol)u>8YobE6bIBF@?Z~jFft+jBvV;GRrGW z3WnrHoC1JWFT%bPoD}*H11~=gbJ)IL2LtSvT#S$BE8`r>6sxX3yNd`SfP;SbeFH8q zgg^no0C5NbQYiw4+$Bkwt4!v~L>v$QM_GEt`$uorjIS{=UZ`?hkuafBMBQ!frGee+ zzdiD+O?%w9sk(E**cntQ(9G||;Te|BbB=s^4GHdsr#cg1{<+VGHPy||E zUuPj@o{0+y4UI;5MnvzdA5)KjVI>f6><#Q~7!s!{OSw7dxy)TBASP~)`Uc`!m;Sz= zv*h5VnkLWs{f=;hs7=MJN@=o%7&&O@=tg_%(;!JiW>7KSHbIs>wh!>WYx< z#5*9OcN#13A~86Izi&L8P4zrEjumpRY_xYZL<53QJxo}wy6o4|KEs2tbUXdI=g(q? zasqVF`iwi7e_y=>XgMLV$Nf8FJqp5pvB@KD2km;t&%kAESm61AJi{tzhoK;>$yhX1f!G54 zNg~hPMoN}$XZ;smPW*SPuN%}J%_(?(1gkug_$K!d?~=ax^M`F8%^+~=I_@&VzKM5jx`XO2w1auLz-}Jqmr12Nb?p8 z1A`Q4?#jxFRm4{mBUG?_^tE63uAzL}WI)BteVF#1UuBU{?J1S&K#n9V({nB3piFHLRQ5%Phno!B zuz7=*;=P?;aBmV}n<3bNL3*f?6)K_ipjfm9w_QLP|j)#&ro`Cm^z)3~G^(;JuX; zk=3IivKj${8}Vd-JhO&)%n*Pdu0JIhBH;iXD|~^_>Rw=`5n_}IkkPn$FkRtv-8K*G zd^$&WwRwnP!utaEe|BGe1?)b@<%7oWXAn*@EWp5$gD$>=gG1@CjGmqz@JL@O8GNGo zTCxG`s(ap3aF{i2fr^&{u9cp3$_KRIadh_DT^jj#0mgo23g74AFIFI&ozAQg7HxCX zeZc9RLWZQ(i(oMZzx=-#d7ctDcJl7713ahCWvzz985OL)y8+-=TVgo0fk6A<6k!SG z=?rzk{Q$bmi=%a;Ne>Jg9u#7j0OthGo_>y339S2Ia@kK8tch9wI3aI{)C6m5Yeaq? za9}2X7$=ncr3rSL35*RR+7CNN1`DTKp&lEpDJhDkKu=lu+D@LvhsWI$Q8eluUn)?W zFpN3nUSe>>SphOPdd7KH@TMB4$LOF>0n{ktOJ$=oJ{<53#{A_UZ2#wuuOX=!U6wz-7Fxh4Pf>8(qYLgrmmoP-_4 zCOyE}dJJc65{*r_nn4hQnS~{idDe&H_1&GX;73+q+(}WP4NWx;a9Kl`z{yYkCz>#f z@xd=!^|i)O=5&wOH=_YrDn;bY-b55YEMjI%9oOC|w<97RJ$mvNv%wdxqleS|k~RMz}b;97HCXn7Om zl*G2D33gflcT`w~(OWn?EgD61XJ=Xj%^MuwXsM|iXpY!D_pm6yh&1>Xg>phYge(rL zp8~-VUy`_LYioBQii853TUl>XV6n|`Z35y}{ox&TF)`GZFv=B!%b|`tpl{MWh&!Vs z13bZdIHb*y0{?yb#A^#!0=I2cnp@DeTi@=z>dN*rqCWok>R#-g;ng+@^2jRXF@~Hl zPt4=#mnBzc$oG)*J9Yhv3Or0Qx7By=T&x^8YDz4oIM&tmTH%Tz{v$C1sRlv@mk{{? zL0(5WIKM~w;LB`+XDB%7Ro>OF1BUf3yo)dOwRoRM7j|Lg*P#5>Lft;uOc&-X$nWYD zIF(+Q2xixmWreGUyBeI+^z}!zgAV>FMCyN_Vir0VM%C9odAxinXUKl={rLphpvG6G z-bef;{Y48*{RPIaO6qGf7SWsXMvT;QSyI^Q4fuZ(-e7|l$WVcH2!yIv?Lmw>O$@70 zNw=8{X9{`idF+Y5*}qOp+n9t0d2CEKFL4E$Oe&@MKmigM_|`VtBlPgVgKvN)1icik zN%SRLTkSNH&<{_Ub7r~h{BLAp7<-EBCn?m#mrA{LCwX=7(k zB4*bG$pNk$Q>g>!Yfz_2Fi{SGO-&+!KBygy=fhayuOgWl8S*)CpijHC0Hp|M^pYTV29>&USpD9{Y-+_8n0T|2g2y9D zM}jbALqh}6oIr*f!dYVOx)tdyGgGS0oGUICQz7sGr0 zjx}S|$bPN(h1C5n2gtN(`cha&2E!j;JnVQ|E$i&zz7S)_(05Xsj{8FhZ;g=tr{s8O z$*zMr<>m$JUzb_T>FOg69+M3JR*@NCMo^ATEUh={Yt_T;!He(W;!v=uJ}>9A%)^J* z+R(QtU4Bu6+is}0J4$Ye>K5!$*rCm2Z1CF|>FY5kY6z{R`8ey>L2co*RMJl}zcYllcEI%;g2NO7NdLCwT^8{vS6EZ;(6ScZFoxlN z3e1^7vR5s_i{ya^h+OQMPGH9nGOH#+5QL<|94jy&2)Nq<9m1n-TAxbE?EXz4)A2vu zYj82c?~5ZPCE>iZvo~i_XyS3yw^7K_)%ML)j{ytHWt;XOLZ@vE=4puv={ z_G0gMXmCWt>y$B@2M;35yVK;zsyDv!XTV?*v8sf)N-Kehv!H3`3+<-Q#8%xY&u_`S zjExV_>ca};)<*bWJv26MCnmPKAE;mK)Z-WDfV6hSbLO?N^<4M$iu+(%84(_S&ePKq z5~qLeDbSyxy8qI<^L9ev&u_ZP-()5aHw`_G<~-kCOwDRz!wvlO8vk1@%X`J`L%xfm zz8}fZ`Gp44RymRt-%Naux>3IJy)5S4Y0B;0c3BGAp$G+9;3erz06$LD+&ssv19k+i zm8|TWTNj+2o!6V2pB&N0J0U}kH~q_6Bh}QgiNS8|ezV&=6W$9V+HGF@s9M*EH*Yk@ ztI}buyM362lzWXo5C8MT^;b|aFM0Y2Vq#y}+C}-s=PGB=VlWUNm`*lB-(=*JukXi9 z`ueJuWD8>sp*0;|m7Vm9>e$xrsaqT4g(8bQXGb8hx*il(3iTV1hpU~Hgt#C@K-k<0 z&B*s*BFfD-S|>4j9);xvvGd|AEKCwhcG(n2oRn_L$^?L3q2o>j?74caTLn-OEs*ux zx1y#VA4{}>mS`ZLl}-LMmAsIb8SdN4kq+3%1>w7l=XssmJ$QoS7^ThJ)co;o&!~ze zI%!R{+x`Aq7KwEU3WTOni3MXcnCyCu?^MU~&Zl|o&MgL*h%~>mtZ$!XyY*xYhn!&l zz^sU!fvKsl+ribjAw7@s(Cvt6r*dD*RQ-9|ZuQlX(mt1iLx27I=zi~4RHbiWhkg8* zaD&s;=Wbx#5kqy&FUDeA%IuF>7ji%m3kM@;$R}v!I)S02^m+e_Cnt*|SlWb-_R&`p zFlp{ipk2_pFRJl?^Fj4k$m+AwX3Ix$KhlP>wBAH(WSZqY&Pz)zy^@z1Rhhf3kehRR zP_Y|>-P^I6%rwc@S3fB+>B-4P=#6+3WB=EUSHCWCC+xoEy}44oQ9H^Tu=?6DzAP## z-ue{<(o)^^&EB@6-!GV(Z~%;&Z}E)^l+)Rk-|P#XWZO*=4_<}hN9$H106Cow*IGFN z-VnUxrc{GWQ+Awk@0In^AlF_KNGyh1hJGe1Pr9cMH|8#QB(k&xb?!jiV<}z3K6~@^ zeQ44fIFm!0=8106GAk0l2D9;zEyat(D(p{oJk?*D^I~Osel&OE$*N%zJ^nm0u)ZYW z_TdqC(Rz+CUw|iWWiz&zTb=q-Gr}BAy}fs)?!PGdFFYC_WKI)uJNito{wmUvOZ>U# zhNaVHA$56~F|&GI-+kXB#*@auFyZE(EDJ}0zoNYkC_T>ESZr>+cS~sdNjy!___g@U z!0s2K9^Q?%+iFhOL4kMkKs)HRkE$OUX=QyZab=)z$=5t+H8$J~Yb?Ar zQuH7pk(R^RJJp^{1xX`n_z^ zXaJL@pDw<=@(E#va9kcAIdQ66{18bmm1zvTlTK}-seM96rf`LRbGA9v13 z*JJNdFuk^+kr5}nwCELU8LF9{9j6Mqr$LR04rDh4K` z$yTBFq;GfDYka3=F6aK73MU=-LZ&Ah($o7r&M$8)PQ0gZG4Lbx9nsbCqSk3L*6-3P zt+T1Ob~qfg_$x9Wp}6>JjU?9=URqArrz?^adY+;c!!+LPM?%CQ& z6k(_JLt&5V8zdGaBl%B~jj-&N7wQckoMz&y+TNZ}ctR2jU81Wf2bcDx0wdX=N=_0# zjrrZzl0m!UJp6}BjxzZwkO`NKyZwcxAR#=wzP=VaMtqox6V%$%71IIt>PLE6g>vCZMpPdO3wS& z3-sI*Vm4ZFn1{dp3cam(e3e->$`Z3BqwI0A)_qioI+IH3nS%P`FaGC?7oN?i4pkFN z+HGkoXGb|5N2m{#Q6>B?ouilDv}<`iVpDh(WagP{$C@H%sRz3h8qF!yv?ENrFf zrhN@fzhXo)FAO1K4oNBdCO>Z17p#bOkEMaJZk#LztqG(Q5rn9iJM$rZQ{9qh5 ze1X#-Z`ZvS(S0XV`<)iV(~gA=Z{l!_MAm8bE4~RP>=f|leyL1TL&_{G??%z{o#MOt zpi5zIYJRM3l3Is|WlizkcNW=`1I?)!%jVI?8lFWB)x~{VNy-BJ2CSANv;~??wnjoi zaknq_sLkIh%MtU4sWiv*|FW;RcG!g@$P|-XZaejOFg}Ps$C9_=`jxg$lBbRCBgnZF z0j9^*Z*K^Om|Lu^IFv0%3J`7WmbLai+OYOyjv}KYLLXQQ@strm*T@&%cv!ndKAfci z&9g7cEN4`9L+z(l9uZLuL?Y;;j;Y0>F*UR?3IJ#}E z%BPGUKYpCD(EgodIz@}%y;P&8R#3|+!liuSd3nM7c`EbRvJUSB<~ILt%#ja<-rA>N zhJ4n14*n8y*PrA%%xE3R+E*v!T~E|}h`ET#we4TU^ z%8QB^$iYFcgk?UsXg9wini#TgZ1izE#* z9b>L@7X0dU1yyBNl|0@w+VlPT7G2pn+w}g00PpDyS)N>v#a`_NTJjZULPA2_89zWx z2e!c?JCy`mFc}j}<%)PTvQ={t9hAUCdg4|rM0&RiRpgX^Z^i@BH?n1b>RrE`r_2@} z7Z(h^*W=)PWjhYZ^W1q=m|IT&yEHi>*9&KcPSDXp-EUJyVZRIuqhCSxK zbmMD0Z|G*eaO1r4bj0yOTAj}>I~`3^c<>msjVpO<^QdX8QAw2sWB506`DEoTt#|r# zUu}4Vem#HK7jNWzc1kLeyhlYn!2mn|-RZtM-b#C`uqxSCSe}kUoGe*jj7%Wb4gCc#izShvU-s$*l zeQU2XFO__DkxSmG%K{rd%_z#BxwD)q`sa3*w3LJsOfP z^&XFGqYn^hmAa!PD1-C~S!sfuw0zwZYo*B<>SMY( zm3BJSi;FTdBG znxG6Wagih6aE@4+kFto~P9aTQqiB0#laP6+;@$^nm%YhU4?q1i zhjkLcgr&{SeR-I-B3tgwtp>1CMo()DzqeRP6aNOc!7##dwk>MNbNcynG4U}wP=To? za;QPxXYzzbuYu5bwv^6w+vVV{8SP>$MDI8Drg3QVwI;++W))ggIzP!8xFMDIM(BRf%A$f?OcV%HB7scy-=#3(~ee=>#L?;5Mb;pYzZJlpcXwHalQ@B)oCem9NSjIvb)FIMT=b`^N7?xviX0y1RaA?b)biyH}n_uv<3~5MZIQWv)hucDj zs$37!oD*oC8(?rKBBO*;%fDbvHe3?8^s&3XgZ$fCAJnij@PbK3@^fqd8r`HVAqeD(} z>*6+#LT1#$3vIMxQJ2^b4dRmC@jM=o3A;00DqUeJ3heZ7+o6upWpS6s&BKDatS$zD zhCRWndyWBLmapUo({2tlb7r7YFc8c3XvqGvnlkh&k`-O&JSYk9mocH8ZTj z069sktnGNs$cAKeKtm)Y&jmDh4UTBizULS+8*y+Hbc>AjRX=2#?@A7+ z4q^VCkYmPTp^k@LD6^f9vtlbdp8TpaT{`SBR9;9dolh_xl-Bi8w|seMY`bCl`z4Co zU;H%<6bEem+Ul@Lz4E@>*2XY9N`{jd+$upIHnz~1gZW93B>Gr{v}9y+5NF(C0NSGaU!ldf6j+BuQwna z^g%8jT0s88+d}U9V}8WC;iGoV9>@Ti`dD|o#jaiD@MYo}DE4;90+thl%O0FtL!IZ4G zCO55XU^`T{1=Td*<-Ea2#`!{1{ z2vI+&p$Sl&J?~d)>+MAiMjlV_KbklF1{j7l06J()Rd|3#RZ8_iC6l4S2(sa3*{59g z_%|GSZtm`>5$*5z>~D;A*wf=8gu~!xj5&#)N$G3>rIhc^f_D0ai4P|oH#QQz8~*Sw$sRKySgARfw!ku^i}qPr*n!>8v%RG z>}2u@U0Ml=l&^t4gmrQ=p?fk=`WP>+Iw z4E6QWjXXSrB;KqazCqs>mrjPU>dk`uo|nyM6S13UZf0f|P1T6QSSz~nP212@e)?q3 zS6PfM`0Zn}NH)gxmvA3!_r%Q%G3(?{(fM>^zx;I&MgN^u`k1t}gAwayfxOK?tqIM@ z6M7P{2g@5tvC*w^H~Sduvj;8nl=tu0e?d&(X6%i!Prq+0+Ut|ryZHD^oLNpFuY;Rx z$gHKBqmHy@R4cGEZ0EE)9`J?RW<=ln(nmbY@`l?g6voGQWF+bVT}%S)^mqk0{eGzZ3)QJ#>(31j-lp^CumDj?(t_R z$gFErbcXJ*ai{piR%K3 zgpu}J3DoB&D<{V|fblJB)X;dOf>vt&gT`IBV>V?Mq>S0+o@)11>a01ja^vJ~$#g7H zTbjQfrNVpV5WGhxmgmm)=Yk|*zHia+v0aT2rKe^46R&BN(|C{^_GiJYmph}kGIP2= zx%WJ+{hIaEWgjFvto;G53a8J8h-CBXV1)ltz@ zlo`7jv9H`{GK@>F#xtpF5*uQ#*}M!=NL-FXZzjRnCAIqC4YR?WvkBliw5J!GV#ug1 zJXRC0FmoJQdTMhj%o*y6^jE4iYp+#?I+lL4UnS$@6K;2T$h)^7NYZnYV*lB5HEZjB z&gRhDVU|Xi+ZCYTSiuQ+ad__>SkBrA0}Fr>_&zrkq`q@HJW7?^F|yuuQb zIZGslB>%4N+4k|*)pGCklCBT4Zr?BXrQ>aOYQ3MWj=vvGyCXQx^dSuKK8Ej)0j{J8 zIwN}7fkZe`H#fDJ2Z{jrxoS#NHINIOxDd%jgujTx@ zogv=geqX5I1d3EwbA3IM;B;THyhE5FOPSOcm)C)60^!vFY_gX6S|WizlaK+Hv9N8O z96J68Q-P-)w-jR3$a^!5n!;SZ4a~6dEQ+v;ZO*5-ZP#QMX5V)%>l55FQ7`G=|APGB zxU9~?aErq^S&doXmJ}nm0@3ZqQxocg=l$vn=kARQZ!6U}Q^jAhhGnSZ^f24{DuEYj zY?7cLUuruMbu(aF%SuO7cwwkQmmPFcXdPfQ`Yf2`fiH)0}b{g60H z--+UZ>%>8CJZ3$II2P?7>cZPBO=OqAbo)E=Nmg_TcYB& zP~IuSkyM4QVjgZH(}L7apO8yr`#MCNr@Gz6lcrLPNmnaoF5ZW%ZLHRZ{hY#?816n= zEnMqYd6PELhnM!n;&T81aW9QQ2eX;a*c*T zz;;UN5O#iFfb)bD*Q62m0 zZii7&0TzYPxz=7fACmYv6%$T%+edeg3G%$`DQK44Lq+qxL=B+DTf%5MKOAvXt zn)fSB-JR(1kvrP0fO#1O8k^0HSgz@NvRYLKs-cd}Z91Nk`o;oThhr$~FO3a!*YC+4 z32aZBInk;-TD{*(^%Ntcnkj#5*-6S|)k8O0k%$_#nLbhOUE6}=)a*1j>q^mJef3g6 z;toY*U(j2F$*7(IE5XvRjP0mVHyeL89y>BX@XTa4mYyPbM9`2Tb~IBezg242y731a zfJp5cxR|^LOp+$fPOPnAQYQ@dsQLM|T$t{zU>t)%-xvZSCB{d*_D~$k?WDkaqOC8k zD3w0X@1t6UO(Xq^IDyX|6Mzi?dpja?n})Y4oka#=Tx(Umc0MU7De}@<;L^lSNC`bv zC^^4>zpg8Gf4*J}dDE-A3W8e%0G_&L#Vmu=axeMO<-Fg+!$tP7K4ejetV8TqC6^S0 zZez{;VDdIrVh%3q;WQigAXTekzS1^Fa@&H{R<5FZ#Br^)CfPsJft_njqvOWNuL7Zt zJ6AP*H*wO&_pZ+;A4-NTrrUf)_S_^V${(aN<3~Sw?^E)Hu#9(g(30I^%0*J>twPEowFe6r1JWt5Jyy1FPX4ia- z4358zSt{96_|GGi4SUPWy_1U(k$eDJk=0tLDa}u|pg{jTBw!3)QXWcx-iCGW`1vfMyhPVl(c*`etjIno*q z;upiiZUi&46V@&_qQAPF4->SgM7qy*tXJ%KJ>KmJk;5!gK}{}KI?#GTqUxC)UH?ls zL$7n)7>o3oF5kRkFCrB%>+x;)9xafv+;!;oyae;@W38DPusBlHZ}_k<{^xYuvHEC@D>t9L;%h2t1wTt=)fckzawUg8G94PY zWMsjBNDszBOFM0vP78=J7T~s958SSZSU9> zn<7~aQ}&=4WfoD{Hae>3;v$+-us$U|e321rIGfjexEybS5q<3)c&$bR2hsaAtyRBg zcxC-NJGx(koYpna`IW?Xb8bPoGcKz3l2xq7ChJ`6jx(Lm)jr)(12&~WEE{~?mKI4m z#uw$aeGy44Ia=H2H|HA&(h_*n(uJ^lw%qD(6X8-oqDB^;~nGXm0jr(56}<^z)?nY zD@QqJ)&x0=bf6r-9CiBDT~qzx-wwwablzU_jhwErjJBqmmm|HLX-BvUJh8In$z=5o zlT6yQl4E9K50@Vn7a5e>9E=`4FiPaV+ap#v?K%_NDMS90B9TK>?0fpa+yrkT<_>+M zEy)jyty<2ynj?R++aRNAb(0+D^dN%d`Yu@SuypGT*jnPbxlTu^g-4}Y6bG=*TBjO0 zEDt{i#1g}8jj1cduW;hnLE^g}%s-88JRdUGpPh~!cbD;1qsr|y;tIv?rXQsD}55# zm%m0wrzsnmy=5B|DGAO23EwAJe!uHP5v~ixL6iYF#PWHz;e0d(S5;Zb{D^M1q-AGT zwZzjE;6rx~bMkW5HmX=};%87ufBqz&SxtT~ulG)ZFkR%R`uNdGiF}II_@_9stfP$y zPi~6)|!#V;*sv+j)?xGRoHAa$ZBC_J8;31GAy^=!bk^S40|6e;rkf zk0L^~HADP`YW!`BH@A?|9@tkZ3Ib38Ix5HB%xcAQ$aHi=?l5yM^f+<}whVf1+w5Br zCa@mZ>`sr$o3CoAf!inw#(IM%Q^B z`NAIoqw7}TQ?mEaJ;(mkQ++P2SvTkSwpQkAmBGAS3&r90D^IJ0 zHJ;mUJQ&TQ!oay?o}7OpT9qJUE!*V5a69?$S_d5~B_(Ang!^ZK3^UAXIE=qu4U-n7 zkuXzub1PH2L6Vctd3SZ(Y0Mja(N;$tR>$T;*5U;$K}kt5F)93|dESMfvD`n`!ufkV6QE@(4#L`nA_Iu4<%&=-D z%PpvuXNzMTZZ$PbgP&sRCZ?^z;X5qM05h-?9^8`Cx<#(x_k0VZxe?3)~3nb&Zl<@Th_el4cp)d4rB^Zh> zofbO}J!K||cfnWJ;|l`cF4A1@0ySv!8gs8F6l1Tn>XKjTw zWCY}I1o;3U(9zF&<1Y^ot0_(4huW{Z+M3bg(b$_eZSe1>d;=3Z!JB< zJ)5Q1 z7RZ-efZ>&;++c)FgxlZe_6)!Z><}<#^mo@`N#-Lmd-fR?8Aop+VuM`9+`PWUyJ-**qx3%wW3iok zU?KMq6#FxrX-;42Hzq0xe0I%ZDKi_n>87cCD0W{GJXz>Y4Nfx}P7RO6a9kQJ@qaoC zy@G)9wU5nf$k5|y1ao0wQBs=tbGVEqO-a4g+K&Htj$PL6<~09}>z7H|!UG){udJZ>hl&A#M1m%K~c}DW`02X^`b` zIrYf7o3>)R2tecE0ibD1x!T0T27y|I5Gk)J5du!$#7=lbf172{kdWU+kz5)Yr?I)K!=G3reRdplsMy(Y;PiS+5h_Ma zf8}3kLP)(sy#finpban3%;*&2UjW9E?B|j2@miSE#B=(K`7wm1_)^l+AA!P9Lik-n zT3~t|98$+a`Io;rrz{W>kA@T)wN8MQsz0~x;ib#?4m%6|IJ&yJ{{5YpzkzY5wY^Gx zjxgf8CaPf6GE2h4T=h07<0E(GBc?C8sG)I@# zr^tf+pB3Hs(@IED4mvs-L6eKfRw!-NrWm61{B-~hQsjNw(Xfj+&$H$w{ zB)5L8K<;zEW|ui|AMxYM?BSqK2&N`|X<*Kyr$>7I08wv(8^Z0raW?elhjR$NPo`4( z;$SLJNTlpYtd)y&UNb8T0Sr4OElqX6vgv$8r71`p14oW4i7!2G5?F$}L!-x!)hpkI zhvPD4P?C`?6e?ixZlM`Z{&O371z#YD9}auVH~wT2Ie9DU$;f*gX?MHmrE22|7PV(f zi22>vII>!vb|K>zDd;I7c$U|$U8`?xZEYmuK+j5sd-)-f=K)}40d zkq4?A^L3C95c1;y$pXTGs*aA$FJ}ax?n|SA7=>FziR!e<;{D#AhdWA}G)fe|XY1)@=u^IH}wQ#OB{VBkUGLEo3`{im~VQvVn!g2)Is za)>d9DLKvbS5SHn11vZR4IvJ(jQ7;k!yMh3L0cojQGo2qU>*kvEYgHC&Tx%QkRajp zo&a1s+ie|&Ytpn^;-nM`+D$935d$;DeWsct;#ZQvi5@WN*raG%|LY;>85yzvXaOMp zdXWYyULAD}#?zba3E?iZ8WBbi%@c-2s+{+hX~P7bfzb#<^u`pq>-J)VC5(s=Vx>># zd+$kC^pu#X?H(MEJz!nPNUDE%U52WAeV{V1dezVp)h4;+m1LYJc=YhtP6e{H047c5 zj=Mq)brM#v-(Qynu+mLI=)F#}!ujkhauDxAqhS^L6tAsb_BUs&fw+wnZ!Q^^={2j_ zpj0m@lWTO}YJhA!eTjTUEGrqP3sT;rzkWRdl7eJw7mKNtHwf|ulJS(XAm+G6VS@f( zG1WRr@A{>^y%E6-`|^SYJBlQe-O|D4Pb%}9dp`C8K?IsqF^EH)F(`0X) zghhf7ZaW3ctP$tgcNA0xuEb#a!eP{M5n3x6j@M~QB1m4d(=`#k%5rgaUC8r6AJ7|v zdo+lLH!2Zq(j!p6lEJQ1J5_n@#ieeHH(hd`@|K^-$myy>^D1TNu)B-FJ za9uE;wW`@7`Wi22*42nG8{DghDVS;DJ1Zv4z{Hhy_PUFBWBru~mm}#iTE!2=X8oae z^m45)v6R_PO9#?x7qc1a`hsBbBrNGPHrdT$Fb#qBbGx}rvkGTLfm7QZ)SZgI(+C7- z2My@EI^#@*A*UC*tjN@*&W?^q*Xt5jf#Vrfxj2eFej5NH zQ?s+o@v^e%9-$Wb^Vxrx-^aO-hHvm-2L;B;~!ovVJsKSX9$|9}e!@_VbU%m{pZ^K?8;ssgp% zvQ(HC&~5&iul+uw#0ZlkaW;ZD1X!S62enD+2w=(;GLBg#l=l`sz%2nBq;z4f}ImR-V%pwm^24j-lwZHM=?(G z;=>q|ch6>@i1=_yKO;xTDg|VJ5<>jy*3?LFHxrxYZrtLcr4^O#>CRN5fBNei5|F?Z zrSWD>sI?4zy`(4+L)E0>;@+f6h{Q?2uSJ*-SWT&aVyMG=g%`Z3LL(SeS0{{syH9@{ z{x8$-emxqR>7l8ncEO1GjnjvS#4mSROA?TddX*O4*tMs6m|qBv3byf!O zK&`HtdYJj~gKmw>C56T*%+UyhbsjJs3wE0%BqWl+wd~12!TV+h$y%Gz6)9(|h+}3! zLGl{c9f#*})L)l1e)j(u0foU`j}k|&-`Kk{EkZ$GDxfzT$Qz^YE#_Du=p zWhl*NuXpPEjNPgS0TXvd>TM_+p1$7ZlMxLL3d#u$O-r{>llt6KI`~4c?MGf_ zteBeYF`xMWhp(?M$&dz$nNnri*BKN2m?cd@!H{W{^;_F4rG0eqO?VB$5xQUc`}<3! z1y&hS&7>8Egf4Ctf03JGKsZ{J>L5PT>C8pz)Cw#QVFiZi6b>$0yayS2#?@CVDk>n4 zbeXR+l#bswyK#(Rd=MIlcaRsZr8@V9FD`v8f#je!V@d<0#!N1c6%=q-qgFb&URPM+ z8puzHMb+s*qf!(Ho)(U`xA!*xYqGwar*d;9L*no&SxQTGDcx%+U6PJ3?Q2Os4G*EP z67hDq;7jx5GH$X&#V=xnh{3Us6T*|oTMLtuVF6>h{!`TXDj|ENa+(JaXz;M0%%vMg;vEe z;0#Stc1q0p0g`GX=h0r==_iV%sXUg20R(9t#MPfw9Jdl){%Aj+-#55ggQtA_FXAK;vn#3IT8c_(*C7L z6fJoLqcw1a`y0-<*XsGwo&yM-!d zN`W_K^)1nRco&2ft_r!Sdvp?>DFvrqL)d4rBkZ$&!(;XlFVCul_V1T>-vT)zBH|a+ z#cs90?FVBp>~gogB7g?v(NodMhlYho!dP*tWo5VmA3+QswG%%x)nYs~)oMqWYRQ~d z#9jzfye;R#-&BILJ(r~e1_a2!*i3mVN- z5H9{7&pwEFcFX3Mf7awQ*u;uBIq|q`FJ9mr&r@g9F86}-mz#x3rL?j3*10B3!HsuB1mPpTgadK-u-i60l8Fp(2#=ptDMVOLKM@Mw# z6dMAY#mv``^DH?zi=8|^B0$%|BPI@b!)0~M$ga2%c=eD*1&6qwFheCf`l*hnsOYr( zRY4a5gcBKJ|8El_jM@}mB8=K%5JqjkE!FH{>HFNvWB#sN>Q`1mfbc70M);NeUhXzn9_AryoU@$bZ28}6g36E-_;%eRZMNN-R{`Zp z=+^MtSN-6zN8&WG1)e5CREt=^eg77Cp^%Klh!^L>evFEKx!IePQgac!-wLmtexfqM zcs1!l*`G_`G;w)^ij0DSM@fkTJ|mf5Qd3h0%57*NL!7+ft}n`r8R(_=`<8Gv201E( zI0dlT09TwO=LNd?#nDOWs*D!XAgBL4_3X+@f_scmuKYiVDBJaK1qPxBe+HmSD^`i` z6XBtL{rc4*)1#n}5G^S=xeM?M&XRCfJl&8GNNxDP+-0jz5t2AZ`1Qws1f9k3k@326A%)P!`P!4a;{W?B?AM4zHi9! zA9WGe%ukwRSv3MzkJgii>^KDp;A{xd{4hj#Va zm`auR#A~weGwRslS8+zh!BsI8^bkD?1J9j6i5T(v_1t@!<(?(*5;jR1DWZ5M?5T^n zs#p0m69SSw#y2JOX#b?mUayp73_*MSLI%Xvz#)R9*@s=I>db!abiqMU%d|+MEeVsxsc+A-D}8 zy(SxY@OQyF_6#9^cgM|501y_}$~>SS#RD+T!+7RAMk+;?Ezn#5T`mGyntFERBkeO8 z<3YSl<({s(u=xEir`Z9L0vK10zRJ6O@EeARNX5qhDY*6%$I*6j(8-M}XE;+Pna9Jt)0stC6h!Z|*I+H4ENTmRwoWUX71-#&&j7&`<`%7Qojurpq zj$%E4o|pH+}=vtgp8*9qc9gC>m{K(tNN2ABc+ZZ**?#8E$g{#?#Wn>+JS6bPrp z{?JTg;aZwg8X6i$=9dPPRLv7Vj&-vJ@C&vmMgJTFDCY*efEOQV+y@Or?_Hh2#m?+| z89emH_`@p$yOMb~qKz9_my(vY4PYj%S9);AHs4{C$0W6D!TrNY>jgr*dppshdwDK_Or*ntNCoOPdZVbP;hj zR5;j6(^nQTjl|B*@Dwz3xmlkMnK7+Aya$1B6@=-GP_|YMw0cAPTQq$rSh#*s*a zyv+|UG-pB{_cy$hH_FLN$;Fa4Z$W(__c&t zAxTYbg~GsRKihNPa6F@qm;JB}sX)FF0^=6$D+s|05{hId-EQ#Ic^)Jt7%rWf{}$mi*w#UJd7({Y;0V5} z!`obR5OwZtb?PDmcPgxfflkqqt`!@+hC<5R+EW_sv-=LYS5)D3N(o___@g3xi0|6Z zMD@^ydZcHz1F1pO3PcA0502cat*vdQ#x|5@@;h8%(%Qm?`^o8PH0%`)oyL2ZE6|o6 z33CP5(~4#qOf30$LddfJ;rruO_A++nKArfqifM)9J?P^r;$}dRMbl3-PCvW1(DOus z`1l@cqORD71J)B)Vy_m<9{!Apy9XclCMJAM$Ye@vYg}|@>F+}lCdPbWhsZk5?1+RK z8MO6unz$Vq<&=6`FfgKhwZjfrLp|v;Ll`shKMsZl4vS@#>-BJEoz`ON9Ud4zE72Jgq4{o?c10BCO8jR8ea-87LerYF`#>Ivfv$*})!(sp&0jr8?<$Q?=P-kM#=3t)7OX8R$cfx29BBm3+d7cp%>4n?{=2WtE2#za9dxszOuI}t*A!KU8?lfiw;Sy3r2 zDe~_6q_niV)(>gpWfWeYXnFe_Ij&H&{N40Kd=h_@>xH`M4J&l zZHzwFpS)e_GnXlAPEYKuCBvQ1ae_>YCTmP8@eX+t@f&#LG_7jBFqit*JS7I4O8R>c z5_EL*L4i7bIzaLn4XAqQG^r+Am2ohEct^O!AhX4kip4c>*6+i^A2qE8{h@LE-_UvP zKCr)aUld;xQ_OvU(F(vlmA;3hXi@*LfzxQs>Rs~Q1Fbj)qA$df{7xx0&c9d$l@U=5uxu%AEDbZ!imDXRD7yN($e*}43zUNR2j7=yS=9YL|IZ%iwC(>|gx zm8>W@4Tap-X`fgfsXQJVKN`)wx{vOT5{CcgF4Kzcz+k3IEd~0g?2wKWq7CQvk1O?I z1dcvsrSy-9q5l8T(Ik; zH##f(+tP#&);GpNwzIwB5n~Q2`(lHqQa_gT76^yK`Y-mOcBHC$=`-ZNTzz=Y&4}XQ zeo;q#EH$REd$D#CzOVWzYkqkC3D(|=*+3?1oh9V)EGz9ycKzE?j@oa~3Gq^wB8)@d zfVtXihUhG-3@@0hy?bTb>|711$i` zO7Dv4p3ZG=qcF4mS+MFNgQ#R8-om^h1g;{U`gld4C0^5c>l$b9Rq%7w^NC#SYjX;7E2xe#g5X|O) z3T9J6!?z+To%8y#{1cz;tXuFJTFvwn67u}*_315zYH>4a;Vi@Lbt>oXyDXe;8*Ux-!d#(!zvF&vd#gGl>-Wt){k~hjm3!~8`759 zd%YWs>Jg}Df+NpN$$TFp$^BkpysF2Ja5VO!&IaDqVIqp6*sA<>LnQ<^IBZ+yDpcS; zOXfoEQhT&B^5p3zteN<;*(b%jTp!+ggAB$lk9#IG%zj+}?T`YIzKool52zqgdb;YQ z4BFZy6|G!d<4C_g0&HcVV9yR(?uO?8v!58Hi_7T_ZKl4>jTXB!G6={kehSE^l)b{~ zPa7(?aN#x7Q_A7sS3QJoV!4-qbT5#jUG=2=@bs|G2#G4@23D*L^Frla!Kb!0!q>PA z@)SM2caZIf7-8?$bvza|zvXgn>(3jM>pK}ayJ5X6z0)VNZu{gxEfZ=r(tC_;s&@a8 zO@+xtL$TP1oTJx%(ZmzSgx;Cqj(Y9Y=RqxIBN)}|-#)rVG?99HYf;cr3I%38Kg}v@ zJjRL)y|O}D`#RUiAtNL69uw*bNue6q*8#VhI%hpVuSp!vaxL=R0MU$pB095I@;c@rft#^5IoR~i>_#SkBQ(ARMQJo?6EN(UrHJ1RiVCKuW|vAi zXgk9T9~pCXtM!91DWlESlO9h)6xhoht3p`LxkzI+a(l(yP-6dYNqHP2?_4yCnv`kX z7S!Xz0Yc+52g0Dj(E2@3kM}1j*69x=oT(-hYb{P4^4x{*@zhwF@8KJ2mV*o=lolG= zdjTW3z1ii1)jDrXf`RTebM!q~L8-boLl# zR8sAjun37rRVAL*&(pQ4ZlxkGql2t(5&#`$p3UK7LQel`XVmFT*GzVMeoFnA+^{T6 z1#8J;zmWKLUL^n1{PRQWnz+7I-E3q;M38=l{h>IrtP3*=>Y=aobKO992oO`80wkTF zQB!v320&{w&#_v$k$?M!AR{%4TZ}X*a61f*LU7_BFs8;NTKH&mh*LGL3YVUCJSBHh z^e~&WkY8RljLz;r_;F1;LJC~AhfI>yI znisOgT0B7a8T_LF0j)zp0J^l;8i?V*K}=o9>kWtqp|vF5dBDU7@ELbB8hh%ro&|+s zLFL?KB9efdJ0?`l9s5VwGy`m9u64gxpD5;bVEl0NOLcs0Jod|O5d4Kn=LhB=LI#<8 zl6Y_cWcKj`9NN!=`n#moFJ7oJHgbOCU#G0+u?RO&d+>E-MXx1;th01#Equ2q_o#O7 zfiD#mw^YSfbuxyn-F(Yo57iDI(us&dm!td%$5xq`uga;$T3RoqH(VkEn;S(2NMWvZ z(Qn^?YQSSAdGo=$W1HFJmF$lnzlbxcD%ky3{6`2fjG+ET!NWqbPVqvTP~}InX7gQm zvrC*T42L(8ARntCnu4ZXAD=NX*H83ve+%O@P1Wn5I5z>=P+@aUN*FOhXDFVjL~=Jb zSe}8llrSoEbGya4s6nUO?sleXfb=eVz~`3j@>P>DR}_^-HMosg*^aEk;hM#jHKX|Z z4(Y!2if0eB)ZV0SU&-1`2izYUguL-X&$e&j{E@DgmXh*EycJAFON;UtrwQ?)wY8@A z-kz25hiOpi5oNRZGm$O+kt&*}biTGB|0Zf^NX7P_tU1*XVMo<;)=lFQ3n%s9$7UwCF3K=#n zLz^Y%n6^aJur=*Thd9OK!!pa039O2%X$a@3=Gj(lmBc)_;x?9&|^2QPjbwm@|gSiV0kp6K}fxkdZ;cSLC)s#zCnkip+>o#?r8hgjy== z+ZU)3@jOH(v0oe;m|!<~*uAEYb|yJO3pJ}1cc1#syPH1yRw2n_|IYmRV)8Rjt0F1R z92VLM2RUxrmAJNXe%uT;d z`Xu+=4I6d$$Oak(hj*(ewL;&~+E%y`4z_Qgo@-77b$gI#Ap3l3S5ZTped{egtfU^r znB(>5kuX(`%lc+Q6L%+*(yBF)$BvMv#ELVl=Bn^dskdY&HGFy+`0}v!V%&LY)6omZ zCx>GAOtCfe76T+Xebj0PBv%CN^=CG(t*NsJvjd=I& zbC9>oWadeW)wR(C8kirqZGMyZC7=Wef6`-T3m^gKMQN2E6SHvS;^z9o-OQ$?@LqjHs z6=+jhHbEuid;=Oj#hoXYLo}>8yq`+OiAWm)r8GB~+>8u?IMYXb$?3FaH8Dr!f|BPC zU8p9<%ibnc=IlR&#&4m}6e!~kH#I!Bdh=IheYt+!g1Cdnqgjdk)-@#J)-!jX(8l_g zGAZZ6vGT-^qBrnetjDWlMm?gmLwm|SJW*h*wRU+mt0*)Z7es_cIvf^9xX6+JoH2~# zkxTU^%HMI=SY6CjyP*U=jOlF?nTyAY}MBO1N#M}%xnx#;q~ znOQp-DMHxS3$t0W3lq`0LvTwQ(rre?UwOp*r!NhUXNlYD7$AP(G3=IDtcD5vTF<@L zx#YY)`v4SN&E2o7lC7OME9qB9By9+zI#d15ot^ScEn7rEC)>X%F-p^*QiWaV2?y{H5YgmWTz;O#EsC&s~oiWJnCL z_Kf{qUC!p4Su?{U&sC~)kVa!Cc2{u%{3Y?{Y^0tZP-EhxH&L6}jcV2D*9C=n1g)D6 zKb5%G_9oYtdZuR|=}Qc5nC{XMOAuYGX_lV(r2fMxHS>t3g?YOAbaa0SXCzVjdU;V| zDZMXojuL#4m@j!}7~#(tPf?D{SL9V+?XdATlNaE-=%7?m4%>4Y-;b&iYYm7Y@q3^j zFCJcbg;gM1=d7eO{80-~u_U`t-cDb6l6!J-RP==A+4Y*b!z0G^hfyI$*}Du;MIh4e5w4zPQ6ojyN5x> zVR?|7lDp(qw+wCobUc2mfZ)lWDd$Qv%3Un)8&I;N?4$<;&98R>It&dI^4}B}7Y{pF z4;g?X)(I+DzskZVK+D&wjl5=r@KZ|7)H!Shp&|Kl5E$5sDWaS~N~e-E{zs#Y&xRs& z1f2Ib8L`u;abu?}_RhrQ`d{m=P@Br;xZzbzV_-7D1ZVN&tv`)<`ex7D2)7yGgjp3= zhJxk>J?FK5^tTf8Hi>(L94Mw^+4HTr^6b_N5tI#bcRnbQ=`LX`mYCois^n`1IiU8o zZe=eF2dzySB5n0)GQdclvka^%iLQg%OA62)Fq*z_aH#|lJt-NP-|ZW*tps;Re*Rl` z?mhIXwciwzYyjX&JIzmJWeE-IQr~$&iAwb++`=j}#&j-5Q5U*hg<~|~%DfUPS(2MP z@WpWPShSMRbm*@0dq4j6JXMu!&Xj5dgV0TL>vzX&Aq;lyPB~dId=2+MDQ%Z~RL5JI z5AQspQRjq({haSWN^R2*SI=k55ciB)`q*99O>Hr^l!uB>+xqEfp^6vf$EUBlBSd4E z-R~=rnJ?OkMt&6~`+O1FURJZ1$|+psU;7z>+b=WTFr%d~$`TLA71Bzb~>ZbLW1 z>e7-3X+tpp;{K?>59cdO}u29?R<@fdrFZ-))rL*{}Q(t~mAMHXe@W1MRcCt7AX!10XO9qp!P zdoU6GkO-ZDAxM60`DzrDkre3W#_quiOSCof;gHgkJ6AIAlCLQmW1kTtY>lgp6-^+&N<`32ST|I#zAZ)cRUnJ9SN5c@rrN1gU?;AR zFa*s-nZ1d$Oysy2&|$TJL@*SCE9C(gK%S73r-LwPZ-3srbED~Tdx9*e3R1eXKB?ey~17{)Jm5{G#2ADPh>|M(P(PUKZqGtN~;X{0( zMop$MXd;#Ow$W&<@6qCi?bB+Z%NUreLx#FG8wqDaUz7&aHlPNBHgv?!TRLwf&E48j zjIQR0#>bd6?jF5n`}%bTxQPQ*tKpeH;V5!mO=dny(QAnK#*avf5)t<-LE|Opei-Dn z4gtzskBT^O+`(F|Dyka0C_T*pC5gX4D6U8hv|&8ihO|H2R4p2470=W*e$x6xYArGK- zU7+1W1hfgzoD*xRv-m+f%RsRCFPR4nnIxv8MW2q+72Zrz&QZdE;yow|0gMV*gPa_Z`+J}Own2%# zGc0XsX$jcZl#%wJHbs-mZtZ=9ZD6*p#cjTiYQzN6CsbJ8Uu>e>aqb-&?@oUmVy^`W$ zm~qmw4X7mH*K-2{{h(#qaVUnduB1%vXMl|ie?I@8IlX}Ye>puNXj5r9#pVwVM)s1~aCKgK9-|dtX4PSgWDGOkcc4mRveXz{DgkB1?Ft z6YCGHwi-03RvQ&mtBpng3fYwb7!Q=?*ZMy|2vCR$6bIu~2=hlYru#wYr)aEFscSKT zpMPl_C~t8=%du4}(B@{T8>nR3Z!szl$-tt^ekgeRGf)UKr;J}mCk1ov6ckQ2sQ#{4 z$5M^;A`y_2z<2B1-}3K4hD&opE5g~ZEF@ka4@V} z1O=Upe`DqjfYn}K32_qh{mu0;MHwt}gD%a#s{Bafnj}A!pKSy0s>sX9y^oC4KeauC zJHh%3^71i($5lzJ>B)-fT$(meyX_qgP05Z6y>SPg;15*X8VLQh!?6FO;5PD9=I@k> z-8Ud~gazuo?SOSFuMmYh+#L=G`wV1?+qL;iSTUT-`z5;b`kShAxa$ zsRod^1Di(}(2|=vbhbb*zBoTA$}s?Zh5MqUD(S!8Tc^YeBoKk1)@wjM3!pt#0GLo# z5l2A~Z40p0}Xo!`KND%CCeo^pTGF*%7Kk?*$V!y;d z-T?tvw;%YxqJQv#W0*!W^&ATe3o@TpdOg#Enj5Q~zqGO5c9~eovcu$wd~G%iMjah(H8ro0Bj1fE*f3Z{T2R!62sGzsW1E8uI<_LtiHWFW!*stQp!;-<~M7#Zy6sB zYNEf+*Q{d&H2^VbSOGsnfML9slWU^5$0f(YcbI-o$T*gB!O4?vVWj2z>FS&DR5fGk z>u}w9NOW)Ud-Ki5kQ1GN%#V*E0E4r8%Pt8D>Hp{d{m-v5 zSYYDw(>nBiJ+wbJ`+X=l?DiTr*+0Agf1j8_1vZ4TU|7e`Xw?7A0>BEAfXRaGcmAWJ z^*?X(*HHNtp#Z%gqOc!o9NrMaU5~l^oE`UF&yib!0zMB0MPO4A$tV<_nDCQ?=rpSj z$!99gE3&(LnU17ssQKwp5_J2eE0x>m^7v>it;6y>Hg6$X-D_O5O-dVU`JOuh#5?wek7SEpRT1&Ua$_OPPiQ*}{ z4Bc5gASr%&eEr=o=o@-9uK8hP!-6Sf)Gd0o8vZXBy)cJemBn?V+CIZ#+?oO+C&j_qy^5s^5jffg;a@d zB4!>Lzv8kKTw%$mxn_#i2yYn%*hsz^=t65~hiT|w8-+z4ZAZK{?#ywE5 z*G}@xI;xE$`t9|)lYwheXto9M1N+lA`}U|>7aCb?Gcy*}po^Bb~;7{F`_C1ZSu&g?E-b4ZO1Q~5=)$}*(g2?R4-`264JHAj$>dDR@qAfHg z(!r#Ot?C)UXpr~Rt*K5B70;Gk_4M5*73!1>{@v&g@!5>EBlh@^>l}-~lbo&_MrfK?W6;L~ciG(F zc_|3{#AQeLnhgQDw3f~Lg@s~SaHX_)KJQWQaTzqkn^?F5q#zbB9z>3_GS-jT&&v0i zyji>~(;E>xydhgLF`^F^p6xY_Au1fV2oEKf;Z%ogdh_O8eSsLNRh1$P-MQjlKX1!} zX!%GB;-gZX&R9(;7?~BP=QkcUk)@exfWC$QwPz&VaCzO1>kSK}a+{olmLt!rP&cwO z#KURQr^-Abjc=uR>7kURbsnElW8BG1#2t@Qg(Oa7EPso z@7_pKtMk6Y`#t0pzZ9S1TT|+5y|c|^NC6vikfeOXlPtsa7FkmJ)8?ILO(SzdCoB+U zaY(s_x_D1Vcz9&CtH&Aa@{tYOo%}}^VyDJK?GATvp)6h0T z&SB&wEjp#fe3`?fKIKw-i3^)o+Oa{%*zh+LWa842$r;|7`1j@TQN}~&13d5PUF(hC zj1ov{>hSt+NS%oVRm`bEl3Qtd-S#Pu#Ty9Psb_DZJb3KAyD$buD(G*fG&M*T`>q;E zSq$65A{}Z1C*bkVmbl6UJ2kV^t5#CCQi^v;NqXGwLyTZqKFp3WWgfIEuDDKTepjn> zMJmmIdLVtp`~ArnWRfXr-RZ%nr2ZIQ(MJ`V^>PUoUA^HDoLrB{>B-~MZiM0BH4k@u z9O2HIU6|msUmc}am;s+cziG#l5K<!oJ#@#Jm0Ms@Lx%4S28 zO5W~}Wt$F^s=Hfk)2GWzH=5XN%y)8>a~yT)_Ae?S&-<{|rr&k-4~udTEgiDOe&u}o z!J<}j-9A+Fs#?)iY+51@AUHhV&w2EC!r%Jaod2_F9&3`wX100u-}Ah&P*zvW#pY!d zqsJTshBGm`HKr624X9zJy8w!RPfNVFjsuTki@bYnJjKUKa+}9v)D7v{Knv= zulZTf(b-3F`*qM-+?Hw6z~cVSfX2qyV!&p=Cl`jZbIG*H3{&-Nn(+*Ri6~=$PZg_ROVR&YT+g=wYMM6N?iJ=}riY z=#W_;8wFF_m7FVTRDAMWjvmx!=TZdx!e{q$!|-C!QOd;Td%gC%VOW1ei%b?}!Pr?C zoMrUtnDhu+f9rnqmW6ew<0{BHiDh2L#KT`$7Or%ef>3=_VmF}WMq6c zNEcAhvx$R&?oxjnJM=T~5$z_7HFu`m_E4WBsCSUDUxKCm9{yj>>V@i8sibqM;UVyw{FeOB`N9h*y&iT z2p3OWPR=H;_7pdVcuG4bo2ai!rKD2CvH&-|E5z-B<1{=LkF7rWfv@J?>Z0c=nPi0u z&A6FXSx4V+y0iU+)7M%5Y2AjK>{E!t9-T*b5x(Z_Lh)XWzxm63d)ui zIU-M~SmtHWv1b-vzHU4|W7|0-ZyR=HSRCae>zRfA63+R@y%=+SDiuc=)l)kbE?n-) zO-s+aJ7bfgP13MEHs6JZPsubJIJv6D#sxoO2i{C_* zvRlbs8(^qy=3NMLEWGd{Kh@Nc#r%b9OsRpFJL#&xFs#YM@t_`NtjbR=Urq@VcM)h}9SGJnQ$I-7xR_sHj zWWQ(GPH@jg&uJ!d-XEiC*-%LQV9$q5Un1J^F(%v7CB=1`O7eh%w=i3xDV$8*ew;>F z{^L=ezQ&t5kFPPpLf-#-uv@+O)7qQPifgl@dlx$*>yCuH6}6%oU3QdDm$S)UpZ6Yh9&+W`YkKV% ztaDiTazt|EW__}VPj%uvIO|=%_@^C3xox$l$sdlJ6O_$5WXsHQPh#O5m>{p-h`L7K zk1QNUVBKld#P3N$ZBnQy_I#v?@yXz#Q6Z9;QF=EbDODjjnyTQ{li8xoICCb)MZ;?W z)+QDQNmr|H8;;8b-_#Nh=JHDW;aaX$V)Wa8VZ+LAdA|#X6u8z+3WGL6Hnj}<@QcvX z>;-Fd_J;GFS5YR!+f)_YhVGw}58VZ#j@O%G6{b08rn4l{+PU8w+s?2@W^HkAlFt=V zDZACS41UXDT8U2AfD0I6w%8EK7e5cPRNSArsBvAWy+0`OwdnFFx@o)2%vOCK>8mZJ z^Jy$y#-zqKN&7No9zFZO$v({*R@DDBZ*iCue<+>tWf0^72F-;x8$G-vU0x|SIMpF&9`*}irh0pY` z{Y6w(nB|)Phc0I3uGBYAYsAC>(TFET`O*Lr>#vN|8kz`h#=AR*EoVpj2Ae6a^Pj@< z`qKw4D&05wAiVw0gW~XTwj$D4S$Ng9vm7ofAra?km6Wg+c1K5UtGh>$QCpR@Z@R3L z9n7ncLN8}s9?shocvC;2b`|kQqPdVQyY!+O`PwwWzfD`=nZzetH}bjGZ=%FBfoM(f z5+(G&T=2&6HVtdOpWSueH@3-BvZ6vk!)d~zsVW5~q=KeHQUl(iqL83luBA(biU zhW6crFMFa^x~^jqUG9Yb?@1B}|B8WxZRt%(@kuG*GBTGPy;iSgYf} zZbg&&Wh83VByo@3C~knZ{N1*9{JjcJrNu7;AD?MXur)?QXi>gSajR)n7YdQKTVw_y zBW)1WT@9E#(o7eyb=S^oWOuIdeY8tBkUvy7v`^t)zq1>?^P;w`AxjVols2h0?v*n+vzZu#JXK zahOdQ;6D+|HB3Ie@r%Tvf4I43pnlv|=s)tBO*xNi@H3D{^+1l7@%R1TDJSWNgHamj zep+qkL?@g15n@hA*~nPofJcz+ZbVX9Oizm!Bz{>Wq*g>-ub9sojbKWop-hqg=7qPP z-R8>m-BGj8iJY_1XXRQq!!Mss?k}z&Z^vOq5?4umGRUmwTe&F2+O+gO=AxQ$tRt%w zv1%gwMy2=Szp1C&aJmX9T|Rz>ed>3z)E{5tWK+GwQ(7mAuZP?S>K7(WML%G%Qz%+y zK}HI??$Ui%_+m2}OFatzRq1;Rd%u9o#xvd##!Xk6k!g#WWc!&HMmbE1Gkt<)cze~fvglk&f&;1&$6U`k|fdJm}q-SGJCle|ISE%pOGR>HfeZ(P|d z_b;;c?HUEul0G+iWF({Xun=K8mMWU8uDC}n4>7r(zdRdNHyJ%09&3UtGj2~Tgye>~ zpXMa*!eXiLR3`Jv%}RdSwf^L;eKq_1@Zq^NA*X6CZy@dJqknAc0zI!C79$vQk`**w+kEph+I(PM z)TyZS;oNvAeHoh7IM!POQpm?yBR&X=wVRFT>l3vFPn^~cqym-9sTJ$=sA*w3AdMSg^m+wSp_4D}MlH#3~q zlI}rNg{thc&-UmtDe@g{u1)Mi-BvxXn#-gGi~B~W*m^COIw3utS`dHOrQTC_QNsKU0Q>o%;W{xUTU)aghZ=YOJJ1=tGj|o%b3G3m}qB;3bGgnQ+ zRo$u!1PtDWe9K%~$&L2yVeLJ4KVLza{eZN&ib-`jhoQ)wka@@X!KKm8!7|D>KTU6T zPdlf}&!TZA7Y=VQMf69C8}jHf%bt0(*Et_&9+Xt7OUTXghI$}x*AgGDI@$28G{M~Z zMe>wZgrq26D0J79C*^~_i_x$d7IEoa?n~3lP)yU4m=0KP_w>@jU<0F`qfDv>%%$>1 ze&%G+;c3*cQbK;&o5i>WyI?9>@pFZ%x9b<@+=r9YBO^q(e8Yg}IS}tzyUVNTjgyTV zf_+rBF`m~qHMmXmxje4%r@3Z{4qR?uo_r%twCo|)+YYE6Wkpsjf41{pqtQRVxv|M$ zIedG?^eF`hLMIEWb)>!wOu%s0Xixe||LRQ2()IIL)|X*(TkIb-dRp;%&fN^iiuK{8 z61!WLJgY4~<;$ceYgJrdyV<6qx(Y@L+T^p?nyeK;oj%PqXgtZd$mDdQ;YK1{tPAVM zQ2l!RqV%{oOcxRodKsN<+Um5x)2OGP(uG z#D8)uY{R=x8C&Z;?m>}Jv4J*K+}48dE9aeqv&R>5eb$3cl~mf}Kta~__3F9V<+Eda ziqV9otr2|G(_GIyL4rW}ZyzBAil@?ycR9x%rW6Z&#jYo*ayfXrZg_2`6XH*>b+LMg zaN}nmOe@zhZ2ri#r{7r8TMbsCK8s zPxs39p6l{a@T(<}z;pd-31|gLa%WX|c-o0Mj$OpNh7$H^0d4kO>c(h;`hz!~UFyYE zc09)u@*6~-7u(%$I>HF<)G`s!W~e*9?mcu594q`%w&Ae6u=-(n0&|%og{l&#d!fc1 zWgTLEXl*+j36k>48kj==>kZHXu)TRvdj^6rY#TO<_(~vyS8pS+Usz4lNij=`TN`tz zl~`q!)r%#5h$+m*fk?s1zibuXCRW+1N*%~vy6GHvQERZx+;K`~-h6uXeYKZ0`Q|9O zu189st5mE|-Q-wHxUzBbYd*bFgw>nec(~IqaN?hSHU3`uejdlP8K?DJA%t9}gQq6@ zK5s`@TF31U#ozS%E_r}EhpuFg=@dSiyD)bq+e}OW$o3pPQX$iFyrG~!>oQrrl)@RT zFiPoaq7R%MK&9D9iJ(!>bC)dhI#fjt5h9?Q&1pNv!9Zk=VSFZS9AXrg7Y(nwUY!0l z-2n9$cP^3zxCOO}vaO+tv8O6YrfUMaW8OC;$2Qy4TB*yPYFTO1`Y4JucD%Cgw!1^H zq>b6U#@~{dL&c3uzdPu)qnVZ4TlG1R)3r2-l(a?lk4lO#h}NL?4a^a54QfLU3>#Es zXf`t)OtlzfRY{44J9lRbce=je^c8-8F@2p;;2M#rlJYqJen!}EA|3W%;iSj$YSvYw zh&A5c7w%;o`rJmhkYx3Wr3TWtDEt{2rx&hz^D`I7BKU;XXZHC6tHE{ZH}#zht{>7| z-=5|vC&8xP)!47_L@uPN_$LYU({BO1-eTG{H#h4<+ut2!-in2R24dTm=jFy@vg>R| z3dKp&$Av}4Vs;n^sFj00j(JpyE>^`3yWcaLh$%-r3AyZzOU#Fh^vY^8+{Jk;yZ0tD zyW`(`9IE?6F6D~O)7$f!kFo?SwEz^*j%Qt~R4^6J%a%B}!ya^z-HX3L5n*r4>7 z#<0Iw3Fw|hl${fqC*X;*Y`iiXZB_n!bL0^)&01Kgf8*3k!Qjbd&=YLA=DqW6#)r{7 z!M6ggvqn4E7xh>B4E!Dc5K_jpb5j`&ooWJKQ=rYRx?OYc{2)u59{PARpZVY^;#S>& zSqV+c^_@V9UpU<#Uf_)^)b8^QjxE5bANTm^2HS?)jb~@l*Xx9vYUAx&B{><)PM$xm z-Yq0A{Dn{a@oGizwfBiF&yPG*Tg+&u&Jb5EczfXW@j<$~l5=fQEX+GVwFMR_mz5Vvp2gIGXwosxb6T~cxakeJ4Ec=u=ZE!4%EgnU z)w>lG+rOJ%L=rTE+crCIabs3~H+DF*JvFbn#<8^W-%T&rFEQ|70{`DbevW?rFPjsR zZ<}|Ff0+3cXShb7>9Y->byoY-Mb&A}oC7b4E`Tm{KHvc5^t|CtBI?PV|6ZiYb-eX` z$anOGrO#}5|Mte{l4C}Z$Rh9JclM^*3ex4>gg)L&31YXs=P9mNjx{?pH4p+EoNPcH zG`F7gt^7_>7R@8#R;JgSLqY8j%bu<-MxKu6&;#Q=0qVl0u6xi5d4Sq&QmYz(l+4-o z%&@avr`fP9_zvCrjIsM9Idf@3R}csdz(!|}T}O|}4x^^~-^ZzY5u z&~W**xLc~d+g92;a=6()8vO`C-T7g1_`hNUj6vCI^uVJz5uKTO=g@B1&e&$a+`CXf zlKEK8E1RYvk?6-0M`PqI4R1?xH((h#7rGyhDAQWX^s+zZZfFBqYnJdvDBw-4=s>Bs z28#?FB<~z_qshubi|Tp*oOR0#yW!QtbbYD%_2hDO?VxL?|S%Ja*PlrZWjs)&;Z zqk;0@N5;hD0EYfR@{7btHFv(mDzwHAfQ{*6DK@{TXrTXn!n~!Wr9I68_zE+YY$t!# zE+_vL14U$M>e&8Jb!Y!kJgAfO9!DpsCg!s36+yRp!eG$zP}0tc5+%9!kCePde|X@y7hay;EPl_%{x;8QCCxzU?1&h$PfYV-dw@V$N$HN-M3ZOJ zXpttq$m)XZ5c7}(4CsPV23_4iRyi+k5U2>Lm{ppcVlG zR`)a==I>+*zoa+l^6qw;m~whtQ(s@dLV5BMjo~0r*-{8E8mjqwaqyKsA9bGz2_6s? zWdf~bgu`w8!y1=k6G9G~CrH9WSDNiZlN`-|?+^YIO7JCYnXF@frySHu`0d3INE7d= zufdFI*oFW$KU}kB#9PIxpZsrm$~@t8{P5ue=s;n>HKlqOAKu*^qr73edhN#5^v{dl^;X zFoCo#@DmlL*?@C8# z0=&l5=kl<>e0QrCc!&9LR&TU!0c+gRL{EtAbRSsmaOq?b4R&?|X#e=Kth;`_lCxHjLH zfZlf0ylNWTY#sCms{#H|KopJt$2TC8udb}*y?lGW<(uV1xhUxOMD#G|sJR6mn-I}D z6!_urnGQC{(jIm?HubKbZ_b>xIW|mGTbWF=QK%NvoCW`nmCHBNob%$-x0&bRnSYpkiTR z8P5c|JSqUVd;j<2U;^X#mO$b6_c-QWcwxfPm1tmYj~2$?K_w!%w}sO4O&#Yk=I-gq>4D$ z0{{+o4KTfvHxpx8H~Ri+wRPyhH_W{K>G~9cMgsqwbk8g=D>D;5>4+6ZpxuC`$Q14@ zq|E_3h?u^uEi?P=2^RJMzz$>z2)uxGEcWRbw|?rC%|xD^xo1bUTtJZY*Tnqd8!(~Y zaGN#{K%RMxY;HzdOS-KJANung`kmfPj)d z*bLv`_Uu-c$}y9qG7}=d48>w({+O5oU@6omt?vAY6`?C=x8XJbD5u!+Gy0E>2L0j9fcV~rxIDT<^N$o zkG>lw!}A{U4N&U9U0F0;J4`z*hP2!UB%KO?M{X3D)04ImNTppPJp-S@#h}lHBys)&g zpc`b2&~4hUXuVRHCu4oUFfLNOcCR*`#f zM9sOjqSY97R*W7B74j-&lQ75~yB&0qd)tms3cs7W8VPP4&1-#o=PygF4zyz;`c{WP zOIjho)808KcLZ?wmJ7@P4R1hUPfbTB1!TZqrF;a;yof!AfKMLFO^?*ZmDri*3-C5A z|9G3`+*{H+T#;!6f4Q`N2^j0b;)?nM`@-}~RTMci6)E#h@`*}we31b?xQmcp#63V= zqy<_7QEDWqg#7sdHTYa%^v29T*6a9@M=e_O5PXzxniD6#jVzorjtZtAm~dScu(RS{Ah99o*=ak7vLDhV6b36Y1Aq>zZXt zB@PB*QNvi8FdGZ2b+&;>?eTu=kos-4m(bNT5&=(t`6A)(hod3Zd4&(oS58_WYh`mT zcLKr*UvOl}(TItQK@){Nko{4y2A!G{rFz19Ok7~QW~ktCJ6SO_TW07ygSiq)N$zd9 zm9*2lWin@+y?8?ae$9avQ(HfPo1{vdd3(@bR#2b>>O+$g00U}gXV(mnanV@>7F$-w zdS&jmLz)~3507U11*Wo=^M0}&uv~hD@T7{Uzjo09Sir=VJ{x+6@z=QyfVnNl>BJ`r zxE)6OQ(yic_TDlo$}VghRs;o|o*yBSANKuV;$8M?a$MCtAx zq=)W~caOJqKacnKuJ!%>z8|hNx?D5++SlG^9OrQ!XGmluiODgTurUDCnB3!ry``W) z*cc41ecJH3uR*U0`3e{=4z2&V0t~2N@STdD@6Qxb@H)!A9yJ3(zXB!Z7?`7?J^gP> z{WPW)#Pt*oJoVu^f0!+DTODr?+-c+r!=yK?6s_nzYByw*z+2ED;HUbP@UvEa-y5`P zq#2c;1c)Eq{nmyHMZmBo{`05tqBg5PtdttbA66=$<2;*n?#8wq+WPM|oJK2X0Z+Yn z^mFCs&_H13l-WnnoWFW}Q+!}0h9qL2$PeDN!F4K@MG2B#B zPzV7coGBpTU^u*Z?K~d{y~O?uy+8`_Db@HKIqVyyx+W_-qLck!Ig{p^fC>saZAc^J=2)cAYjEeq89CHP{S{FRP zH@3pa=txhTDr;%+UtD-`7FY0yOh7ZCcRu4zY3KG8=>4l{oAdHHoSJqU_Vs5+FBI+6 z31OXV-TmcP&?MziAuva(lW zE*Q;eg13eK$J@fcbRN7jd@eKvZa0Gfc2kCd3cON-wU*`bTUxN9{>X4-XK zi@{X(6OJ%n*wOIV<(ubE!QfsE;S6#eOAQ?svs6-PC(`nR%o_%_h(~OZYVn}y3QE22 z_s-UpUrSr^9m*7%jorMgSXh3owl_veC}qP$v}xRtciiy>3Ccnkq8$gpQ`%{!A5+p{ zWY}m=kE-sEM2#2|=4P?v^v-$~CumzvN{^B|MsCg+?A&e85~1~_m>yXuEWKeAv2$_* zxsv2`V4u{V05vl?7C2M09vourJAzg4HMk$a0?c|6l{C9aMBtROBl!uG>mo*((cRbB z*w^$l+G@vYUt5qsF>jkxSZ(C<8nU)-0P6<}ADo9D(`9$eW+R%1kNtm~+{dIjILHT}HDC5Bh^K(2a) zNk%hXKWw##K4CgavlMT+w7uILhU5LMcALvojbCIMvQbrE>!z{Vt6I2EeDZp8X=*Sj zM{*02!)>qHc!F#|Gi>zj6F)7|c}-^Qpec&%%6ma`@26{2-T@KpBeTTlE!a67AI$j=NjIk=Q!3A}cG-pDBlbQ`(JW6nJ1ps@W!x4lyiQB)&v>-zAj8A>y^1@=(lC zCw7pyB9#xDy29l8dRWoPRSF9I+8 z^ANgN9D3eWiE>RhCvPt;r#7Qr^(Zq(Co_{&Ni4&Sz5{M~W>J-d*}}N)mr;>iL8mJ2 za`5yb&bGFIpPCFdPN7PK_ueaWkte)3Wd-b&ndD!eh>$KAz!ft$Dbk><; zsXa^|`K>#^5ZNFkIo_LAu8GPvyUb05-ylS}3V^VC8nMt_J60+xs=O{UTLh4L00%XW z%R2QCUm!^)9yD_S3s~8Qa(Zh5hYM6dqK9!mf@~fQWItB2SEZ@NJ6b1^V;?@DA}|S5 z$HrB?z=xFhA!wG10vn|y-NO}I&3up8UTrH&I&Fp>&ISds?$+_{h?X!>a865O6ut@w zJKudVr_s=s_|*D@wJ_W7%f#31oUQfD1Ky3?LZ{*)z=TTpR@eTV~8RpYLx|Ef^lNvl9D)f-~RE$ z=}Y+pA`>+YPWZ&;*&geNhH z6}zi&AV#$6*GRJqV(3}*2cERTYLv2u5-&O7=5*hw{6^^2`?0yONavWjsBWsJ1<7W; zbND8VZFLTp+r9}d{5gs}aA}6O{g%D4L*=dJ?6`^4Fe3Kr2FR>#Y5t5cwaR|gfXVHR z3r=gymx~>A{U{3{b;x7lq-W}I$NMK^3518k!S4$8`z`v?t6S$59YyZx6w26&dn#lq zBKJ3@&!dAQ4u-qYQng=EGe86B&t--J<7A#k6Cc(OT%hM5K$<-R5sI0uYs3aaVQH@! zf~)k}BWs-~gthn&W`b(hd;&kEAHJ8e-hCLE;|D7(d`BHSf!#%daz3P>ph`iy)kZ@A zqSrE}$ovQrv+egGBRYX|)p|V3&a_=( z*Ww~5qx2h#HzSmadMR8qIj!^C-|;LpLx{6mRiLIHO1k7mCtTV$8x*vgnz@`-_pF1J zsPoLDjYkurHXGVyPlKqKh^nVyst-OeR(ozCyy=j(2&b+fkNA;}fPe!JeL>f}^m zWo2bE8*<~USvz^|q18HRy3~5QE|`p=buqQtFo`{&SHOs#kaQr8iIjYt%9e!Gp{rE7C!ghP~DNLb)eGe zihm3`JbFQsD;f?3ufv0niTdl4bc6B^mGr5>p6qnWiF>#vdpR#n1WT?+{XGssQ3N^g4-;0 zbF9IMTOiF4Z|wSp&Sm>ccxDJaYww8`Qv6DvE2FhfC)0aX%U?&B!beDGgXVZ;ne!;p zt`915;1I(O4x}?YP3faquRVyBY1@E(x;^U^A+^v5@=>(&ZU9u%;enjGP}ZIu%*T07 z(6B{m)HdZKekS^1Akn{MwMn|9nD_Sp$&2Vbxv^hpL}DD~mp8RY;1P{S^-LYi-PxDf zobL!+#8>@-&ttF+Kb9ROcWc6wDAbHiZoJ=S8#+PFZ4;Rs)=!HGraCfDi@nxik@de> z*8-gBMeC+ZQtJZ#7{0J=KMY%h>)v>6?~%gkEr*6D4L<|KM7dhb{c!+ULaBHBzS{b& zfPm=HMBf9mU}Ezxd0Zd~FAoX&KQ1N7h|-P8qYG)Cpg?QY3P z4%ey%>F~sPE!Uu0H;M42j1T0&OI2z?8~XZ{Y?Sqk8WM8Uo4QuP|9=W8m z8Ke=OKXv7Ch{1tuQAK$6m!e831G zl4F2tsB+M(8!PG}7vV!RVq#)wsb&U`&E`xqfb75s(SFZ;pLsTO@6nch5)@KX7K&rYRE5ZhtRw?)X7|df`$96GTF-!S&T!4*JLK{tNLYm58UGK>KU>1k>iNa(63Zr}kB7Bhs-mc5&uOue7 z2}}z+R1@0rrHwnj@Y;$MKtAvIY|7=&5@96q72VOwHN!PM@#rPh9Pr7+dsatN-~W|; zvA?v`cG@${aOJiYx!Q$ijS)dw^6&dz9Kmsfj2`LH2Lf;-J>Z}4dlG)2S?#+2%@c+B z?1;Dtrwf8nQ>^!3kvLgtg!z@oe>N4Cvmqp+9l|jR5{b zQBWnh?50P}jnUKF8xjN#{ha1G={-F=w)LW3O9(Fb*oUfsMXCWX z!@Bd_pa`l`I(Sd@(y4JU!|1*U;SleMRuWC63~7W@k8TH4<3`2 zn1Ro<2i*8c2aZz}V~HlmbXO>i& z_dq1{*9PF8G68gU;B@5mVy&nHM3T*BK_(?N^&;s$n5J6nSUB#7(0*ZeN12k5QBvsr zm2L$k4Z?+#{IVRd??j`z*355U&McKA4kO4i0Z;JpdqJihh5B&ql(VDd(@o-ysoqcJ zta`FWmIq-!*zZ6)v09B(?)Ry+j8m*zPA|ATzU^Rzh*PGf!b1v|Z@ z6Wvl_d+Hgu+1;PXnCMk@-&|wE5Pd8oS08l(U?dDsl;F0-X5Vk7j$3fYcdh;LHwmGQ&UVeP#aK_AS5EnsEUR$K8bkFEA*l;#~oHINu$4h<)02;!7TvDnUmY+ zd=NCb{N-Mg(|A{}D(?;!BtpwPN`V_MGIPhl-CWT2#K|=&dA>^*m!NY5mye z=n-3$tM8Zd)v&1(lF~*ZvbeGe0t1BHngzoxQ6vPu`DsO@qEtJlAs{+yFf4bV z+usN<+}uVwnN&d_Q}T?Oax5QA28CPi`1Ey0PZX-NOcbd-$S;hI-W5EF;<6myE{wn% z!8KlsVkxqbX5h~rdrSp8?HibzYOYs3n9Gc0+qn_RX_=VX7M`MnP*1PlX=>S_JMVTW zc7o8bmr=s58HRg&5iToH2Ed@?f~Zc*>mI8#VXwCZ-fRJse;tA zeybW=g4HJ>*3@*6uTm-G1|LTcPWqf>Z0Pq;q}%Ofp5jCpE)lcUzx) zOh`zGL=C~7*RB5oo_d*}0u(-hZCof3J$~3D<-+?jtVS-) z%~ED~tczFWORlE@slCom;}^b~u7$^o9Kw`Kw4=+AP%)h3_~A?yxMl|SsG{mzbMWc( z_U85_vT=0lyIneEW}+40)Wa_vvDw7q)mBdm@YWw1D`Ia=QeuL#SC@JuY@EIwBI=GRz=6I0H9X2P!H$)>BZ$c zCpNOOpTMY~RDcz8cPUK!UD445;n1DxC4ylAfXfj5#$}oa0WMQ+E!2r`uz?nHQ6O>t z{>(ep4&bPkIOLvWlJ;Pv%S&jFP7SN-9SLrLY|YXln|qFe+hDs*tU&T1#34eDdE&KZ z^*f3ci(XgN2aweFI|gHZSrb&TeQWxB@lrQfXo@U~F^M&!Vh@q%l{36yhmKCUp^VX) z>2j$Ci+!}G+v1%DmUR~=B#asi@20r#?F+v-1EY=y{WvCWnj8bC3#G1RRxiWfm^%_K)-^@}sxPsk3J;z%8QrY-8|Rmn1G zbw4>7jb&l9#Bn|5s%B=E8h&7|w$tG#)4K)91z8W>)FF9x^!{jT!~Q}z$}o;w2)O~r$8ih+L* zLp{{q>}}OEJ_l8Tt~|j}CK7(L$oFT{h9P8pi5HG=7YmablcmN()bpk98Rc%9@!9C? zk@h95%)(1XY+8Fi0d5fDL0;p%W7-fR2Fp$PnysbOeZ-XV)LFeA`DnJ78``x>D+@S2QO`r^bmdQHzkl0xAp!=FvDgYde zN=-#5T(29fqEJ-dwTdMs1?H~BueJtBh8Vtmyuu%1?Gdg@Ks@b=y32HfAGA*bM39oB z5kwYj;0!3%%SyzNJuK_IU7|DU z0wl5E?BO7i{q)?~Exz#`TS-@2UCgAlEUZqxq|=z)rOw-Zsp8Y<8FJh=>-6I~Z#di; z7Ug=yKt2L$R1Iw8^~In-NQSu%0io9Uch{(;41h2Z0E%|dvLCixD;DCI>i~5`)nf6+ z017Gs$V==;2TF-ejuvk>Ap#=qmHTmDIh9fzE;lFdViDAWOQ7j8; zUs$!@Irv5>y4p7OO>?cA<}ZO9{Xr&@9C?g6E|lhk`$L2AxbRhc>0BZu=fJoc61)yx9k7s<%q}wi@_b z7KYPzxv@;md$R6H|y{?q+wkoPoHTsBz+WPtg88AD#ut5){pV84Pp_0eeCS#5%I8d^`57ZnXC8PA#p|$PLlJ+?$4FO1S z9PYO$$8%Csi+rzl-bXPto=NX~&iYnPm;GL?w#-lmg_*^;hmHKk%qAb(-NKqgdNo_# z<|UKkqVs}L-N!}|QeUFzV?>H1r~>kL)&stQHyXeUWaZ@C>j7Y30<_Km+PsGbGH74{ z{mupE$M89``y;?6N#a>`@GsXyKMXJpTPR)Suk%tlH$S%c^Xb!7Wtl+-q0d7daRLlj{q2HiQ;rPwEqM3Kn`ZZ>U5SlK{+fUs8`m3JH$#6S6W{x7)7cWT1g`J*^mBqn=Z;u*kU{ zZewZYg3`9dR)d3t``^ud8F0*NioTn_zaF#ipUo1*!4I$t`iB|!y%b91hoL-}rIG}8 zFd#>erTyM7Y@?Op|AK9lfkU_^>{IZ^uK`W%Yz8qWsSTs;zjs>DgKt)Rbn7>_Lol8IB$@{3vCsMe>4JuX zLy3&X?n>zXLQ+5xu;Y{Zc8PK*)&-c`QnA_MbM}-C?Wm!hw4@7t{Yra#22rfyqXe=> z7FG@;l#$T`H?Cct^E-p#AL7EBOK8b9>*w;NuKmHf;N9A2q*&^e7Qp!@9q;L3ecgnw zVcV|&Jr4u{`MED$y3m}4*v4b zss(#dTn=aBUtEhNHYv(7axr4kiyoIP z>ksOCy)?t1!QOS_>kV$l&DVKTD7wv2U|xOnd-lu1_&e~^B{*6LU@d&mrgFGQtG+Uc z{E%7q*@0bjCPPrNbFr91olWp1I7O7gfY#Qy@P)+$RP2Y*8U&pDj_XY(Fej0II(Lgd zM?3M5IuuUVV~7>i?lFy)?sN3Yq<;G<)L&Fu4Dr1uuhd8$Gfh zf`(sHE;4x0<`;3EO8Y*bP_Tq_1$-l}&`2J5Ema*u3^>op#i7*Nyv;|mVOk|sP_|yL z^=%?@={3G;(?HaBK||>Q67e1TKL@>et!ysRI2aV|Z`!si4eI#T1$`rVTmok7UXs(B z9OhK4F9hraKhU)|0+{D-9MZAeM5^+^%ne_Z7czHUQmfb(#x zNDOf8$0%xgcUOBFavD(6ud=zOBz->=?eyz_x8^F8p!ne)-^k{u8A**jy3hmu}NPEY?3x`p36GhfqILY2DfMpFfi* z4}hv*saxZJ>#FqyA1J` zIxOMueMN#cm?kRw;d%`8Sa$3`q!RbeZ??#0A8g%WRFzFG&^F%Xp(P$BIS9}R9;NQD ziSHl&t(7S8`ny)5$Bg-iob3+TzDVqIxVjIOtt9S8g7nCg1ufqPp~j>aX$NY%)Ol=eoEi! z#4io9evr>_NLSHDaF(iBYcaFi4Sl`~!uaQTtpBOTcz1I2RD`i2+7D*8u^o6AcFC!q zUvVu+dhI#n>DC7!S53H?yKW2QSj;p%&3SCu`iGpNT?-`Zm!M)2xV0RSA20svrv5%0 zP#JW(?XdDz2Du>5gjE*vm?#s)@vfh)sd8HEo}@9BTbJmFwGv zr-?g6^PFSK;G+5wCiDMtNWZ-v>J$FkH|9#vP~|MAs81YX<%X6e*(BwMFsAgll^VMg z8^35yN#^Pj8J`<9sbR5EsT+Xoa$_t>B7t0U0{Mn^| z@t8hN`^~HW#}WSgT@Ol`boj~9RUap0}j!2>~xJ}t)?&$Jm^v?T>t60Lge92RCY3Fl2ySmw#BHBmjqSPgEJzR*vH=YY%lZ$vd@a!ett3Kn&j;;&eoBUovm8q zA7X17FU0-KLf|et-G3eD+t~7CeOjR*;YuAO=~=J0p^E>BofQr(nQG33-?s}E7DFpzi8Hn=x^K??2c1Z8EeZk4=Nl$+ogY` zJUD&jKMu(oK}g-W`os zZ#Fgug)tQ=E4MW_2-0n1=2UIFR@@J1k+SHmG^NXkGYubX2a;d@0B z4rS6YEjt3C6l00DYuP=OOC@Q^ZM>u9SLK33Sk%jf3Pbw&iruK#MV1>LQo^(za5$wv zZb44A;&${N=Nm?T`m)Wy$7z(jNC^?dbEqzc8huz3S1?Ry;0-o^H1|}}MK{n&C?>1I z-EwodRHIi!QekCOH;i7-*G0&=c*)y<~9%ZE;!oa!)XqNmoJ$mxdcfXyF!d zhD$rRBfd%h=r}%{2O1rgTKRgstYT_(Oq%Ic4hanvn9G+Uhbo>1_(vqUhuj#oIE5>W z6xfsq^Knxp*Vb6Z6l7yW9(J8XZVl{87i49I^EHE{Ty$(-WF+0@Emo!(y*gXmB zB;y#nlZUWDgajSgN1*TGM4eyk_kf;!a9=XLa3ouCx^Zds!cl`LkZ)|)8Z{Zs;7c*P z-(z`C1Jw2v40vV>D#h%cM2|8t`-@*P@~sJW1-I=9w$(Z-6_ zmxf!fe#$o9=3v&?GVsDZ9BpX!~Fwbp0$njb<>=y;5F%KXmRnc}jPHfbqeXn(n$~Z|UZ<0x<)% zDV&z)4|6N_w95~${3}4m>RO~P_Rp;F&vz_IH7WP)6Iw_)?gPaIydd(P0-0Axq6?!H z1|NtN1)i9{XjrvqUKO@UeH}>dw4f3dUpyYd9J5urarBD%u|k|co`B-zl7Y^!)k(V0 zXD(m2wwsop0HJO&#EFz&9ws^|4pB{Ucai3akHSK=?f}PKSz#CH@ud`Mqs2AxcR=gr zjA_h9LaBdA^W<>_=Tuy4^PXW}+KURrnf~@d{+WQY{ROROj`JsHm(elr-lV+!KKvu* z`OhqyUFY8GUnrK%?2~n29NW_>FCD4aL74R`EiG0|I2bF9W=oWox+=Fov{IP6R}xJv z3GZ}bdd%y4d3Xw9-oE?fF7$#J=&Ylprf!aC=4x)P=h})GEQp9Oo{L;^>O@~O&pFUI zT;0>^GL{H6>V0^06ve-%z!w*Cy|#Fff+Q&+$pz8Jr?!~|pGnig87%>Mx2Yoyicj=E zLns65^GBS?IsL}k6P^NcI_@*Qg>y?O9FTO~)-dCP0tE6#?wRryEO{_9eRZxy$u0A3 zMP+0@VfMBS)jn|?)0RkYD32|T=7w9OiE+9|SAAa$9Mgt|_2k2i;1qFW@`TG>;;k=_x+CM*3hLNYPgE>p z9^Sue)^%mi|M7{di^AlQ417`fipWW>=L@zl{?`f(qv z!oJ4kOCwn5d%7RTLukG?+59`rz!!{C+qMCf$a^hwF&97hX(U^WYIcz8`*qL5q&JWMC3z`_ulj)R}Fi>PJh;>tt z?jTPxkiO>Ya!hd|%dGnR=JL`jIil)}wT^V9Mo(cfyPzGCq&<#UH)XsO)iyoV5)px; z;+-aYd!8xSLZg7=lRa4f<);E_DT!6LPL5gy6#Uy;!=vw=Ww>8M7=2v5XSk^pQu8{< zh57~EKn5c$WJ4x{8N0J4iS%q)#XRrRX4?IMPJKj9Y{+#Su^g;C4g=R9dz;<8=TxQv zvU7_uaeN7PeH!Z#8Akp-mG<%Z73q3~yZWU}i}ICURaww)mLsn4O8rKvfA5w7Bh-QK zWbP58#&K|}pP1Z}Xo8Oc-f~7G`1c&XKHbaO&$c~`?DpASh4U!@!fWYCce;wxQJA#a z^9mymy0i6s@x|DyT?5f!p~zv+D)-GfWFW~#*Ot?~N>ulfrc%V#Gy-`b;?lR#wB=-- zu-4tf2D<^Vtkx^8>x?FZ7dWI_9(5Vin;-PdlV02%|4JY(TB*fcUHN=hk~0-?JYRQl zP;my6FI4vgtG*^=iP3r&k&`7DH{_BNxU(O8aj(cUmavl)DBxB1wP&PF1TvOHz-1Ax zQ;x1>FiM&*ujeETand@c{4qNrakMl_wu<*aFRCpZ$@ss`F8*7zZq;ocNWYNKq90K% z;@aSg>dF>6=2nC11H1rM%=LlX&tv|guA&f*uS2PqGlbqpB1*6x+zlX-zkq%-n}l_EO}g&y&?Uv;1O1 zGCrXp(qm+MLhzFbwkEtnPE%*oxzdlrLu)oQ7@b<3&}JfqNY4y+oUJ4Wvp$gI22)j` z!0wlMzxu*{c~wx1JVo!BKT9GPGrqfM%3686Z|76Q)U)tRm@f9*TUb&Jck9(xYu$HR zA1$F#%^!_jS$btJ_BORsJfG{n>g9RAVpXAZC$UV1?B%J#_rkVO* zZPSPLsxCn#=Nj@sWG3}zpJ*PxDdmDS=PZDysV(co$YPgTj`wzo`3raBW` z_=-qcg&K2i;ZhDczfqf4WQe@IzK+^P;daO&7s55VmulkHOS6a5M%xTH(gwWI_DVM9 zNw}HJH(k{GhHPKW<03HTCiV{^V~A>_2&RJ<2nyM#-QH#KUmUWV%sSP3dU8aP6mc15 z@U@fUz(nHo!w%hk6hXt1kCV?s?6V+~%u^C(1#%2U6}&UWDyWs>Roalb5?n|HZJy*CxBbK;$$($jZ>` z;i%yFy_cVFQAt2 z4^^Bd_6sdKJrBRpOSnQLwTp6HdZl-|rzsY03ur!PTlQC2;F2X!e1=2+GQbb8xJ@i* z{`QmxYS8`MD?2=16Gl3Tm9{Tn=Tu~SjyN!1A7vzpht$|r?%DdRn5lps)+T80_US40 z%!Zlg(LMJ)+_jz0t(#oM<}>)y5-7dPLrQ13J!3VNo`?cJyJ! zq=UEvR~vW}b=j|pMoAv;m=Cn(;%Sm>!^CR}aWwACyIsgkT>+gWtQ;MGT_pz8Oyl^9 zLFp4U-mrDD{O#*U>gC-<>jp6uW_`ohQ^FojyBRzr6P25;80_h4Rd`wOi6)7QnK$n0 zP!z-}m+~H6n{|{6T^U4q(T1lLI!lttYH&ZsYK=9O{O7H`?<0)v_+cd@lwZ57yeys} zQ}9+$p*qU0=r>|kA~DoTyK!v{Z-+s!}c8tKo`l%&Gnin}bib=O6}eZ6^^q z1b$z36-+Iyp7zMMmqsf�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 literal 0 HcmV?d00001 diff --git a/Rootish Array Stack/images/RootishArrayStackIntro.png b/Rootish Array Stack/images/RootishArrayStackIntro.png new file mode 100644 index 0000000000000000000000000000000000000000..74802e4ba978ff729ea594a711a1d61231fae880 GIT binary patch literal 72856 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 F{{XywOS}L8 literal 0 HcmV?d00001 diff --git a/swift-algorithm-club.xcworkspace/contents.xcworkspacedata b/swift-algorithm-club.xcworkspace/contents.xcworkspacedata index 5f2c83aee..ac3a79be9 100644 --- a/swift-algorithm-club.xcworkspace/contents.xcworkspacedata +++ b/swift-algorithm-club.xcworkspace/contents.xcworkspacedata @@ -1520,6 +1520,16 @@ + + + + + + From dbc751f344f64648c175d83444f8dc0bcb6033ca Mon Sep 17 00:00:00 2001 From: Marcio Klepacz Date: Mon, 28 Nov 2016 22:09:59 -0500 Subject: [PATCH 0666/1679] Fix link to Minimum Spanning Tree (Unweighted) --- Breadth-First Search/README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Breadth-First Search/README.markdown b/Breadth-First Search/README.markdown index 23edf6da5..084f4611a 100644 --- a/Breadth-First Search/README.markdown +++ b/Breadth-First Search/README.markdown @@ -149,6 +149,6 @@ This will output: `["a", "b", "c", "d", "e", "f", "g", "h"]` Breadth-first search can be used to solve many problems. A small selection: * Computing the [shortest path](../Shortest Path/) between a source node and each of the other nodes (only for unweighted graphs). -* Calculating the [minimum spanning tree](../Minimum Spanning Tree/) on an unweighted graph. +* Calculating the [minimum spanning tree](../Minimum Spanning Tree (Unweighted)/) on an unweighted graph. *Written by [Chris Pilcher](https://github.com/chris-pilcher) and Matthijs Hollemans* From e0f13280433d5fe91855d3e133a145a1eaa2446f Mon Sep 17 00:00:00 2001 From: ViktorSimko Date: Sun, 4 Dec 2016 12:51:16 +0100 Subject: [PATCH 0667/1679] fixed typos in B-Tree README --- B-Tree/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/B-Tree/README.md b/B-Tree/README.md index 493fdedfb..f6924aadc 100644 --- a/B-Tree/README.md +++ b/B-Tree/README.md @@ -123,13 +123,13 @@ If the child `c2` at index `i-1` has more keys than the order of the tree: 1. We move the key at index `i-1` from the parent node to the child `c1`'s keys array at index `0`. 2. We move the last key from `c2` to the parent's keys array at index `i-1`. -3. (If `c1` is non-leaf) We move the last children from `c1` to `c2`'s children array at index 0. +3. (If `c1` is non-leaf) We move the last child from `c2` to `c1`'s children array at index 0. Else: 1. We move the key at index `i` from the parent node to the end of child `c1`'s keys array. 2. We move the first key from `c2` to the parent's keys array at index `i`. -3. (If `c1` isn't a leaf) We move the first children from `c2` to the end of `c1`'s children array. +3. (If `c1` isn't a leaf) We move the first child from `c2` to the end of `c1`'s children array. ![Moving Key](Images/MovingKey.png) @@ -141,13 +141,13 @@ If `c1` has a left sibling `c2`: 1. We move the key from the parent at index `i-1` to the end of `c2`'s keys array. 2. We move the keys and the children(if it's a non-leaf) from `c1` to the end of `c2`'s keys and children array. -3. We remove the children at index `i` from the parent node. +3. We remove the child at index `i-1` from the parent node. Else if `c1` only has a right sibling `c2`: 1. We move the key from the parent at index `i` to the beginning of `c2`'s keys array. 2. We move the keys and the children(if it's a non-leaf) from `c1` to the beginning of `c2`'s keys and children array. -3. We remove the children at index `i` from the parent node. +3. We remove the child at index `i` from the parent node. After merging it is possible that now the parent node contains too few keys, so in the worst case merging also can go up to the root, in which case the height of the tree decreases. From 4072983c1fb4725fa21a52421897d82e3040c459 Mon Sep 17 00:00:00 2001 From: Dannel Albert Date: Wed, 7 Dec 2016 00:25:05 -0500 Subject: [PATCH 0668/1679] + methods to append, insert, remove node objects Useful for manipulating linked lists and you already have node objects --- Linked List/LinkedList.swift | 366 ++++++++++++++++++----------------- 1 file changed, 187 insertions(+), 179 deletions(-) diff --git a/Linked List/LinkedList.swift b/Linked List/LinkedList.swift index 86d2bca9b..83f898f6c 100755 --- a/Linked List/LinkedList.swift +++ b/Linked List/LinkedList.swift @@ -1,198 +1,206 @@ public class LinkedListNode { - var value: T - var next: LinkedListNode? - weak var previous: LinkedListNode? - - public init(value: T) { - self.value = value - } + var value: T + var next: LinkedListNode? + weak var previous: LinkedListNode? + + public init(value: T) { + self.value = value + } } public class LinkedList { - public typealias Node = LinkedListNode - - fileprivate var head: Node? - - public init() {} - - public var isEmpty: Bool { - return head == nil - } - - public var first: Node? { - return head - } - - public var last: Node? { - if var node = head { - while case let next? = node.next { - node = next - } - return node - } else { - return nil - } - } - - public var count: Int { - if var node = head { - var c = 1 - while case let next? = node.next { - node = next - c += 1 - } - return c - } else { - return 0 - } - } - - public func node(atIndex index: Int) -> Node? { - if index >= 0 { - var node = head - var i = index - while node != nil { - if i == 0 { return node } - i -= 1 - node = node!.next - } - } - return nil - } - - public subscript(index: Int) -> T { - let node = self.node(atIndex: index) - assert(node != nil) - return node!.value - } - - public func append(_ value: T) { - let newNode = Node(value: value) - if let lastNode = last { - newNode.previous = lastNode - lastNode.next = newNode - } else { - head = newNode - } - } - - private func nodesBeforeAndAfter(index: Int) -> (Node?, Node?) { - assert(index >= 0) - - var i = index - var next = head - var prev: Node? - - while next != nil && i > 0 { - i -= 1 - prev = next - next = next!.next - } - assert(i == 0) // if > 0, then specified index was too large - - return (prev, next) - } - - public func insert(_ value: T, atIndex index: Int) { - let (prev, next) = nodesBeforeAndAfter(index: index) - - let newNode = Node(value: value) - newNode.previous = prev - newNode.next = next - prev?.next = newNode - next?.previous = newNode - - if prev == nil { - head = newNode - } - } - - public func removeAll() { - head = nil - } - - public func remove(node: Node) -> T { - let prev = node.previous - let next = node.next - - if let prev = prev { - prev.next = next - } else { - head = next - } - next?.previous = prev - - node.previous = nil - node.next = nil - return node.value - } - - public func removeLast() -> T { - assert(!isEmpty) - return remove(node: last!) - } - - public func remove(atIndex index: Int) -> T { - let node = self.node(atIndex: index) - assert(node != nil) - return remove(node: node!) - } + public typealias Node = LinkedListNode + + fileprivate var head: Node? + + public init() {} + + public var isEmpty: Bool { + return head == nil + } + + public var first: Node? { + return head + } + + public var last: Node? { + if var node = head { + while case let next? = node.next { + node = next + } + return node + } else { + return nil + } + } + + public var count: Int { + if var node = head { + var c = 1 + while case let next? = node.next { + node = next + c += 1 + } + return c + } else { + return 0 + } + } + + public func node(atIndex index: Int) -> Node? { + if index >= 0 { + var node = head + var i = index + while node != nil { + if i == 0 { return node } + i -= 1 + node = node!.next + } + } + return nil + } + + public subscript(index: Int) -> T { + let node = self.node(atIndex: index) + assert(node != nil) + return node!.value + } + + public func append(_ value: T) { + let newNode = Node(value: value) + self.append(newNode) + } + + public func append(_ newNode: Node) { + if let lastNode = last { + newNode.previous = lastNode + lastNode.next = newNode + } else { + head = newNode + } + } + + private func nodesBeforeAndAfter(index: Int) -> (Node?, Node?) { + assert(index >= 0) + + var i = index + var next = head + var prev: Node? + + while next != nil && i > 0 { + i -= 1 + prev = next + next = next!.next + } + assert(i == 0) // if > 0, then specified index was too large + + return (prev, next) + } + + public func insert(_ value: T, atIndex index: Int) { + let newNode = Node(value: value) + self.insert(newNode, atIndex: index) + } + + public func insert(_ newNode: Node, atIndex index: Int) { + let (prev, next) = nodesBeforeAndAfter(index: index) + + newNode.previous = prev + newNode.next = next + prev?.next = newNode + next?.previous = newNode + + if prev == nil { + head = newNode + } + } + + public func removeAll() { + head = nil + } + + @discardableResult public func remove(node: Node) -> T { + let prev = node.previous + let next = node.next + + if let prev = prev { + prev.next = next + } else { + head = next + } + next?.previous = prev + + node.previous = nil + node.next = nil + return node.value + } + + @discardableResult public func removeLast() -> T { + assert(!isEmpty) + return remove(node: last!) + } + + @discardableResult public func remove(atIndex index: Int) -> T { + let node = self.node(atIndex: index) + assert(node != nil) + return remove(node: node!) + } } extension LinkedList: CustomStringConvertible { - public var description: String { - var s = "[" - var node = head - while node != nil { - s += "\(node!.value)" - node = node!.next - if node != nil { s += ", " } - } - return s + "]" - } + public var description: String { + var s = "[" + var node = head + while node != nil { + s += "\(node!.value)" + node = node!.next + if node != nil { s += ", " } + } + return s + "]" + } } extension LinkedList { - public func reverse() { - var node = head - while let currentNode = node { - node = currentNode.next - swap(¤tNode.next, ¤tNode.previous) - head = currentNode - } - } + public func reverse() { + var node = head + while let currentNode = node { + node = currentNode.next + swap(¤tNode.next, ¤tNode.previous) + head = currentNode + } + } } extension LinkedList { - public func map(transform: (T) -> U) -> LinkedList { - let result = LinkedList() - var node = head - while node != nil { - result.append(transform(node!.value)) - node = node!.next - } - return result - } - - public func filter(predicate: (T) -> Bool) -> LinkedList { - let result = LinkedList() - var node = head - while node != nil { - if predicate(node!.value) { - result.append(node!.value) - } - node = node!.next - } - return result - } + public func map(transform: (T) -> U) -> LinkedList { + let result = LinkedList() + var node = head + while node != nil { + result.append(transform(node!.value)) + node = node!.next + } + return result + } + + public func filter(predicate: (T) -> Bool) -> LinkedList { + let result = LinkedList() + var node = head + while node != nil { + if predicate(node!.value) { + result.append(node!.value) + } + node = node!.next + } + return result + } } extension LinkedList { - convenience init(array: Array) { - self.init() + convenience init(array: Array) { + self.init() - for element in array { - self.append(element) + for element in array { + self.append(element) + } } - } } From cf5ca9cb198437b589f7c4ffcd47bcefe7e4b12a Mon Sep 17 00:00:00 2001 From: Andreas Date: Mon, 12 Dec 2016 10:13:35 +0100 Subject: [PATCH 0669/1679] Updated to Swift 3. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Updated to Swift 3 Syntax. The .swift file wasn’t converted yet. Additionally, I fixed a bug in there. --- .../BoyerMoore.playground/Contents.swift | 94 ++++++---- .../BoyerMoore.playground/timeline.xctimeline | 6 +- Boyer-Moore/BoyerMoore.swift | 118 ++++++------ Boyer-Moore/README.markdown | 169 +++++++++--------- 4 files changed, 209 insertions(+), 178 deletions(-) diff --git a/Boyer-Moore/BoyerMoore.playground/Contents.swift b/Boyer-Moore/BoyerMoore.playground/Contents.swift index 9a3d619dc..362a298f9 100644 --- a/Boyer-Moore/BoyerMoore.playground/Contents.swift +++ b/Boyer-Moore/BoyerMoore.playground/Contents.swift @@ -1,42 +1,66 @@ //: Playground - noun: a place where people can play extension String { - func indexOf(pattern: String) -> String.Index? { - let patternLength = pattern.characters.count - assert(patternLength > 0) - assert(patternLength <= self.characters.count) - - var skipTable = [Character: Int]() - for (i, c) in pattern.characters.enumerated() { - skipTable[c] = patternLength - i - 1 - } - - let p = pattern.index(before: pattern.endIndex) - let lastChar = pattern[p] - var i = self.index(startIndex, offsetBy: patternLength - 1) - - func backwards() -> String.Index? { - var q = p - var j = i - while q > pattern.startIndex { - j = index(before: j) - q = index(before: q) - if self[j] != pattern[q] { return nil } - } - return j - } - - while i < self.endIndex { - let c = self[i] - if c == lastChar { - if let k = backwards() { return k } - i = index(after: i) - } else { - i = index(i, offsetBy: skipTable[c] ?? patternLength) - } + func indexOf(pattern: String) -> String.Index? { + // Cache the length of the search pattern because we're going to + // use it a few times and it's expensive to calculate. + let patternLength = pattern.characters.count + assert(patternLength > 0) + assert(patternLength <= self.characters.count) + + // Make the skip table. This table determines how far we skip ahead + // when a character from the pattern is found. + var skipTable = [Character: Int]() + for (i, c) in pattern.characters.enumerated() { + skipTable[c] = patternLength - i - 1 + } + + // This points at the last character in the pattern. + let p = pattern.index(before: pattern.endIndex) + let lastChar = pattern[p] + + // The pattern is scanned right-to-left, so skip ahead in the string by + // the length of the pattern. (Minus 1 because startIndex already points + // at the first character in the source string.) + var i = self.index(startIndex, offsetBy: patternLength - 1) + + // This is a helper function that steps backwards through both strings + // until we find a character that doesn’t match, or until we’ve reached + // the beginning of the pattern. + func backwards() -> String.Index? { + var q = p + var j = i + while q > pattern.startIndex { + j = index(before: j) + q = index(before: q) + if self[j] != pattern[q] { return nil } + } + return j + } + + // The main loop. Keep going until the end of the string is reached. + while i < self.endIndex { + let c = self[i] + + // Does the current character match the last character from the pattern? + if c == lastChar { + + // There is a possible match. Do a brute-force search backwards. + if let k = backwards() { return k } + + // If no match, we can only safely skip one character ahead. + i = index(after: i) + } else { + // The characters are not equal, so skip ahead. The amount to skip is + // determined by the skip table. If the character is not present in the + // pattern, we can skip ahead by the full pattern length. However, if + // the character *is* present in the pattern, there may be a match up + // ahead and we can't skip as far. + i = self.index(i, offsetBy: skipTable[c] ?? patternLength) + } + } + return nil } - return nil - } } // A few simple tests diff --git a/Boyer-Moore/BoyerMoore.playground/timeline.xctimeline b/Boyer-Moore/BoyerMoore.playground/timeline.xctimeline index a15b8d6e0..89bc76f90 100644 --- a/Boyer-Moore/BoyerMoore.playground/timeline.xctimeline +++ b/Boyer-Moore/BoyerMoore.playground/timeline.xctimeline @@ -3,17 +3,17 @@ version = "3.0"> diff --git a/Boyer-Moore/BoyerMoore.swift b/Boyer-Moore/BoyerMoore.swift index 12a1d86c1..4d7660ec3 100644 --- a/Boyer-Moore/BoyerMoore.swift +++ b/Boyer-Moore/BoyerMoore.swift @@ -6,64 +6,64 @@ http://www.drdobbs.com/database/faster-string-searches/184408171 */ extension String { - func indexOf(pattern: String) -> String.Index? { - // Cache the length of the search pattern because we're going to - // use it a few times and it's expensive to calculate. - let patternLength = pattern.characters.count - assert(patternLength > 0) - assert(patternLength <= self.characters.count) - - // Make the skip table. This table determines how far we skip ahead - // when a character from the pattern is found. - var skipTable = [Character: Int]() - for (i, c) in pattern.characters.enumerate() { - skipTable[c] = patternLength - i - 1 - } - - // This points at the last character in the pattern. - let p = pattern.endIndex.predecessor() - let lastChar = pattern[p] - - // The pattern is scanned right-to-left, so skip ahead in the string by - // the length of the pattern. (Minus 1 because startIndex already points - // at the first character in the source string.) - var i = self.startIndex.advancedBy(patternLength - 1) - - // This is a helper function that steps backwards through both strings - // until we find a character that doesn’t match, or until we’ve reached - // the beginning of the pattern. - func backwards() -> String.Index? { - var q = p - var j = i - while q > pattern.startIndex { - j = j.predecessor() - q = q.predecessor() - if self[j] != pattern[q] { return nil } - } - return j - } - - // The main loop. Keep going until the end of the string is reached. - while i < self.endIndex { - let c = self[i] - - // Does the current character match the last character from the pattern? - if c == lastChar { - - // There is a possible match. Do a brute-force search backwards. - if let k = backwards() { return k } - - // If no match, we can only safely skip one character ahead. - i = i.successor() - } else { - // The characters are not equal, so skip ahead. The amount to skip is - // determined by the skip table. If the character is not present in the - // pattern, we can skip ahead by the full pattern length. However, if - // the character *is* present in the pattern, there may be a match up - // ahead and we can't skip as far. - i = i.advancedBy(skipTable[c] ?? patternLength) - } + func indexOf(pattern: String) -> String.Index? { + // Cache the length of the search pattern because we're going to + // use it a few times and it's expensive to calculate. + let patternLength = pattern.characters.count + assert(patternLength > 0) + assert(patternLength <= self.characters.count) + + // Make the skip table. This table determines how far we skip ahead + // when a character from the pattern is found. + var skipTable = [Character: Int]() + for (i, c) in pattern.characters.enumerated() { + skipTable[c] = patternLength - i - 1 + } + + // This points at the last character in the pattern. + let p = pattern.index(before: pattern.endIndex) + let lastChar = pattern[p] + + // The pattern is scanned right-to-left, so skip ahead in the string by + // the length of the pattern. (Minus 1 because startIndex already points + // at the first character in the source string.) + var i = self.index(startIndex, offsetBy: patternLength - 1) + + // This is a helper function that steps backwards through both strings + // until we find a character that doesn’t match, or until we’ve reached + // the beginning of the pattern. + func backwards() -> String.Index? { + var q = p + var j = i + while q > pattern.startIndex { + j = index(before: j) + q = index(before: q) + if self[j] != pattern[q] { return nil } + } + return j + } + + // The main loop. Keep going until the end of the string is reached. + while i < self.endIndex { + let c = self[i] + + // Does the current character match the last character from the pattern? + if c == lastChar { + + // There is a possible match. Do a brute-force search backwards. + if let k = backwards() { return k } + + // If no match, we can only safely skip one character ahead. + i = index(after: i) + } else { + // The characters are not equal, so skip ahead. The amount to skip is + // determined by the skip table. If the character is not present in the + // pattern, we can skip ahead by the full pattern length. However, if + // the character *is* present in the pattern, there may be a match up + // ahead and we can't skip as far. + i = self.index(i, offsetBy: skipTable[c] ?? patternLength) + } + } + return nil } - return nil - } } diff --git a/Boyer-Moore/README.markdown b/Boyer-Moore/README.markdown index 4acc1ffb3..576f6d17b 100644 --- a/Boyer-Moore/README.markdown +++ b/Boyer-Moore/README.markdown @@ -1,13 +1,13 @@ # Boyer-Moore String Search -Goal: Write a string search algorithm in pure Swift without importing Foundation or using `NSString`'s `rangeOfString()` method. - +Goal: Write a string search algorithm in pure Swift without importing Foundation or using `NSString`'s `rangeOfString()` method. + In other words, we want to implement an `indexOf(pattern: String)` extension on `String` that returns the `String.Index` of the first occurrence of the search pattern, or `nil` if the pattern could not be found inside the string. - + For example: ```swift -// Input: +// Input: let s = "Hello, World" s.indexOf(pattern: "World") @@ -24,7 +24,7 @@ animals.indexOf(pattern: "🐮") > **Note:** The index of the cow is 6, not 3 as you might expect, because the string uses more storage per character for emoji. The actual value of the `String.Index` is not so important, just that it points at the right character in the string. -The [brute-force approach](../Brute-Force String Search/) works OK, but it's not very efficient, especially on large chunks of text. As it turns out, you don't need to look at *every* character from the source string -- you can often skip ahead multiple characters. +The [brute-force approach](../Brute-Force String Search/) works OK, but it's not very efficient, especially on large chunks of text. As it turns out, you don't need to look at _every_ character from the source string -- you can often skip ahead multiple characters. The skip-ahead algorithm is called [Boyer-Moore](https://en.wikipedia.org/wiki/Boyer–Moore_string_search_algorithm) and it has been around for a long time. It is considered the benchmark for all string search algorithms. @@ -32,75 +32,76 @@ Here's how you could write it in Swift: ```swift extension String { -func indexOf(pattern: String) -> String.Index? { - // Cache the length of the search pattern because we're going to - // use it a few times and it's expensive to calculate. - let patternLength = pattern.characters.count - assert(patternLength > 0) - assert(patternLength <= self.characters.count) - - // Make the skip table. This table determines how far we skip ahead - // when a character from the pattern is found. - var skipTable = [Character: Int]() - for (i, c) in pattern.characters.enumerated() { - skipTable[c] = patternLength - i - 1 - } - - // This points at the last character in the pattern. - let p = index(before: pattern.endIndex) - let lastChar = pattern[p] - - // The pattern is scanned right-to-left, so skip ahead in the string by - // the length of the pattern. (Minus 1 because startIndex already points - // at the first character in the source string.) - var i = index(self.startIndex, offsetBy: patternLength - 1) - - // This is a helper function that steps backwards through both strings - // until we find a character that doesn’t match, or until we’ve reached - // the beginning of the pattern. - func backwards() -> String.Index? { - var q = p - var j = i - while q > pattern.startIndex { - j = index(before: j) - q = index(before: q) - if self[j] != pattern[q] { return nil } - } - return j - } - - // The main loop. Keep going until the end of the string is reached. - while i < self.endIndex { - let c = self[i] - - // Does the current character match the last character from the pattern? - if c == lastChar { - - // There is a possible match. Do a brute-force search backwards. - if let k = backwards() { return k } - - // If no match, we can only safely skip one character ahead. - i = index(after: i) - } else { - // The characters are not equal, so skip ahead. The amount to skip is - // determined by the skip table. If the character is not present in the - // pattern, we can skip ahead by the full pattern length. However, if - // the character *is* present in the pattern, there may be a match up - // ahead and we can't skip as far. - i = index(i, offsetBy: skipTable[c] ?? patternLength) - } - } - return nil + func indexOf(pattern: String) -> String.Index? { + // Cache the length of the search pattern because we're going to + // use it a few times and it's expensive to calculate. + let patternLength = pattern.characters.count + assert(patternLength > 0) + assert(patternLength <= self.characters.count) + + // Make the skip table. This table determines how far we skip ahead + // when a character from the pattern is found. + var skipTable = [Character: Int]() + for (i, c) in pattern.characters.enumerated() { + skipTable[c] = patternLength - i - 1 + } + + // This points at the last character in the pattern. + let p = pattern.index(before: pattern.endIndex) + let lastChar = pattern[p] + + // The pattern is scanned right-to-left, so skip ahead in the string by + // the length of the pattern. (Minus 1 because startIndex already points + // at the first character in the source string.) + var i = self.index(startIndex, offsetBy: patternLength - 1) + + // This is a helper function that steps backwards through both strings + // until we find a character that doesn’t match, or until we’ve reached + // the beginning of the pattern. + func backwards() -> String.Index? { + var q = p + var j = i + while q > pattern.startIndex { + j = index(before: j) + q = index(before: q) + if self[j] != pattern[q] { return nil } + } + return j + } + + // The main loop. Keep going until the end of the string is reached. + while i < self.endIndex { + let c = self[i] + + // Does the current character match the last character from the pattern? + if c == lastChar { + + // There is a possible match. Do a brute-force search backwards. + if let k = backwards() { return k } + + // If no match, we can only safely skip one character ahead. + i = index(after: i) + } else { + // The characters are not equal, so skip ahead. The amount to skip is + // determined by the skip table. If the character is not present in the + // pattern, we can skip ahead by the full pattern length. However, if + // the character *is* present in the pattern, there may be a match up + // ahead and we can't skip as far. + i = self.index(i, offsetBy: skipTable[c] ?? patternLength) + } + } + return nil } } - ``` -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: +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: - source string: Hello, World - search pattern: World - ^ +``` +source string: Hello, World +search pattern: World + ^ +``` There are three possibilities: @@ -112,25 +113,31 @@ There are three possibilities: In the example, the characters `o` and `d` do not match, but `o` does appear in the search pattern. That means we can skip ahead several positions: - source string: Hello, World - search pattern: World - ^ +``` +source string: Hello, World +search pattern: World + ^ +``` Note how the two `o` characters line up now. Again you compare the last character of the search pattern with the search text: `W` vs `d`. These are not equal but the `W` does appear in the pattern. So skip ahead again to line up those two `W` characters: - source string: Hello, World - search pattern: World - ^ +``` +source string: Hello, World +search pattern: World + ^ +``` This time the two characters are equal and there is a possible match. To verify the match you do a brute-force search, but backwards, from the end of the search pattern to the beginning. And that's all there is to it. The amount to skip ahead at any given time is determined by the "skip table", which is a dictionary of all the characters in the search pattern and the amount to skip by. The skip table in the example looks like: - W: 4 - o: 3 - r: 2 - l: 1 - d: 0 +``` +W: 4 +o: 3 +r: 2 +l: 1 +d: 0 +``` The closer a character is to the end of the pattern, the smaller the skip amount. If a character appears more than once in the pattern, the one nearest to the end of the pattern determines the skip value for that character. @@ -193,4 +200,4 @@ In practice, the Horspool version of the algorithm tends to perform a little bet Credits: This code is based on the paper: [R. N. Horspool (1980). "Practical fast searching in strings". Software - Practice & Experience 10 (6): 501–506.](http://www.cin.br/~paguso/courses/if767/bib/Horspool_1980.pdf) -*Written for Swift Algorithm Club by Matthijs Hollemans* +_Written for Swift Algorithm Club by Matthijs Hollemans, updated by Andreas Neusüß_ From 24fa81839a45e24a6d5600c774fce3b730eb4de1 Mon Sep 17 00:00:00 2001 From: zaccone Date: Mon, 12 Dec 2016 15:42:21 -0500 Subject: [PATCH 0670/1679] I created an Xcode project with my changes. It makes it easier to test and the playground was crashing! --- Trie/ReadMe.md | 10 + Trie/Trie/Trie.xcodeproj/project.pbxproj | 531 + .../contents.xcworkspacedata | 7 + Trie/Trie/Trie/AppDelegate.swift | 26 + .../AppIcon.appiconset/Contents.json | 58 + Trie/Trie/Trie/Base.lproj/Main.storyboard | 693 + Trie/Trie/Trie/Info.plist | 32 + Trie/Trie/Trie/Trie.swift | 207 + Trie/Trie/Trie/ViewController.swift | 27 + Trie/Trie/Trie/dictionary.txt | 162825 +++++++++++++++ Trie/Trie/TrieTests/Info.plist | 22 + Trie/Trie/TrieTests/TrieTests.swift | 162 + Trie/Trie/TrieUITests/Info.plist | 22 + Trie/Trie/TrieUITests/TrieUITests.swift | 36 + 14 files changed, 164658 insertions(+) create mode 100644 Trie/Trie/Trie.xcodeproj/project.pbxproj create mode 100644 Trie/Trie/Trie.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 Trie/Trie/Trie/AppDelegate.swift create mode 100644 Trie/Trie/Trie/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 Trie/Trie/Trie/Base.lproj/Main.storyboard create mode 100644 Trie/Trie/Trie/Info.plist create mode 100644 Trie/Trie/Trie/Trie.swift create mode 100644 Trie/Trie/Trie/ViewController.swift create mode 100644 Trie/Trie/Trie/dictionary.txt create mode 100644 Trie/Trie/TrieTests/Info.plist create mode 100644 Trie/Trie/TrieTests/TrieTests.swift create mode 100644 Trie/Trie/TrieUITests/Info.plist create mode 100644 Trie/Trie/TrieUITests/TrieUITests.swift diff --git a/Trie/ReadMe.md b/Trie/ReadMe.md index 30082a450..6b28dd189 100644 --- a/Trie/ReadMe.md +++ b/Trie/ReadMe.md @@ -162,3 +162,13 @@ Let n be the length of some value in the `Trie`. See also [Wikipedia entry for Trie](https://en.wikipedia.org/wiki/Trie). *Written for the Swift Algorithm Club by Christian Encarnacion. Refactored by Kelvin Lau* + +# Changes by Rick Zaccone + +* Added comments to all methods +* Refactored the `remove` method +* Renamed some variables. I have mixed feelings about the way Swift infers types. It's not always apparent what type a variable will have. To address this, I made changes such as renaming `parent` to `parentNode` to emphasize that it is a node and not the value contained within the node. +* Added a `words` property that recursively traverses the trie and constructs an array containing all of the words in the trie. +* Added a `isLeaf` property to `TrieNode` for readability. +* Implemented `count` and `isEmpty` properties for the trie. +* I tried stress testing the trie by adding 162,825 words. The playground was very slow while adding the words and eventually crashed. To fix this problem, I moved everything into a project and wrote `XCTest` tests that test the trie. There are also several performance tests. Everything passes. diff --git a/Trie/Trie/Trie.xcodeproj/project.pbxproj b/Trie/Trie/Trie.xcodeproj/project.pbxproj new file mode 100644 index 000000000..70a0626da --- /dev/null +++ b/Trie/Trie/Trie.xcodeproj/project.pbxproj @@ -0,0 +1,531 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + EB798DFE1DFEF79900F0628D /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB798DFD1DFEF79900F0628D /* AppDelegate.swift */; }; + EB798E001DFEF79900F0628D /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB798DFF1DFEF79900F0628D /* ViewController.swift */; }; + EB798E021DFEF79900F0628D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = EB798E011DFEF79900F0628D /* Assets.xcassets */; }; + EB798E051DFEF79900F0628D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = EB798E031DFEF79900F0628D /* Main.storyboard */; }; + EB798E101DFEF79900F0628D /* TrieTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB798E0F1DFEF79900F0628D /* TrieTests.swift */; }; + EB798E1B1DFEF79900F0628D /* TrieUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB798E1A1DFEF79900F0628D /* TrieUITests.swift */; }; + EB798E291DFEF81400F0628D /* Trie.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB798E281DFEF81400F0628D /* Trie.swift */; }; + EB798E2A1DFEF81400F0628D /* Trie.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB798E281DFEF81400F0628D /* Trie.swift */; }; + EB798E2C1DFEF90B00F0628D /* dictionary.txt in Resources */ = {isa = PBXBuildFile; fileRef = EB798E2B1DFEF90B00F0628D /* dictionary.txt */; }; + EB798E2D1DFEF90B00F0628D /* dictionary.txt in Resources */ = {isa = PBXBuildFile; fileRef = EB798E2B1DFEF90B00F0628D /* dictionary.txt */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + EB798E0C1DFEF79900F0628D /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = EB798DF21DFEF79900F0628D /* Project object */; + proxyType = 1; + remoteGlobalIDString = EB798DF91DFEF79900F0628D; + remoteInfo = Trie; + }; + EB798E171DFEF79900F0628D /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = EB798DF21DFEF79900F0628D /* Project object */; + proxyType = 1; + remoteGlobalIDString = EB798DF91DFEF79900F0628D; + remoteInfo = Trie; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + EB798DFA1DFEF79900F0628D /* Trie.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Trie.app; sourceTree = BUILT_PRODUCTS_DIR; }; + EB798DFD1DFEF79900F0628D /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + EB798DFF1DFEF79900F0628D /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; + EB798E011DFEF79900F0628D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + EB798E041DFEF79900F0628D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + EB798E061DFEF79900F0628D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + EB798E0B1DFEF79900F0628D /* TrieTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TrieTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + EB798E0F1DFEF79900F0628D /* TrieTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrieTests.swift; sourceTree = ""; }; + EB798E111DFEF79900F0628D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + EB798E161DFEF79900F0628D /* TrieUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TrieUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + EB798E1A1DFEF79900F0628D /* TrieUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrieUITests.swift; sourceTree = ""; }; + EB798E1C1DFEF79900F0628D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + EB798E281DFEF81400F0628D /* Trie.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Trie.swift; sourceTree = ""; }; + EB798E2B1DFEF90B00F0628D /* dictionary.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = dictionary.txt; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + EB798DF71DFEF79900F0628D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + EB798E081DFEF79900F0628D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + EB798E131DFEF79900F0628D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + EB798DF11DFEF79900F0628D = { + isa = PBXGroup; + children = ( + EB798DFC1DFEF79900F0628D /* Trie */, + EB798E0E1DFEF79900F0628D /* TrieTests */, + EB798E191DFEF79900F0628D /* TrieUITests */, + EB798DFB1DFEF79900F0628D /* Products */, + ); + sourceTree = ""; + }; + EB798DFB1DFEF79900F0628D /* Products */ = { + isa = PBXGroup; + children = ( + EB798DFA1DFEF79900F0628D /* Trie.app */, + EB798E0B1DFEF79900F0628D /* TrieTests.xctest */, + EB798E161DFEF79900F0628D /* TrieUITests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + EB798DFC1DFEF79900F0628D /* Trie */ = { + isa = PBXGroup; + children = ( + EB798DFD1DFEF79900F0628D /* AppDelegate.swift */, + EB798DFF1DFEF79900F0628D /* ViewController.swift */, + EB798E011DFEF79900F0628D /* Assets.xcassets */, + EB798E031DFEF79900F0628D /* Main.storyboard */, + EB798E061DFEF79900F0628D /* Info.plist */, + EB798E281DFEF81400F0628D /* Trie.swift */, + EB798E2B1DFEF90B00F0628D /* dictionary.txt */, + ); + path = Trie; + sourceTree = ""; + }; + EB798E0E1DFEF79900F0628D /* TrieTests */ = { + isa = PBXGroup; + children = ( + EB798E0F1DFEF79900F0628D /* TrieTests.swift */, + EB798E111DFEF79900F0628D /* Info.plist */, + ); + path = TrieTests; + sourceTree = ""; + }; + EB798E191DFEF79900F0628D /* TrieUITests */ = { + isa = PBXGroup; + children = ( + EB798E1A1DFEF79900F0628D /* TrieUITests.swift */, + EB798E1C1DFEF79900F0628D /* Info.plist */, + ); + path = TrieUITests; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + EB798DF91DFEF79900F0628D /* Trie */ = { + isa = PBXNativeTarget; + buildConfigurationList = EB798E1F1DFEF79900F0628D /* Build configuration list for PBXNativeTarget "Trie" */; + buildPhases = ( + EB798DF61DFEF79900F0628D /* Sources */, + EB798DF71DFEF79900F0628D /* Frameworks */, + EB798DF81DFEF79900F0628D /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Trie; + productName = Trie; + productReference = EB798DFA1DFEF79900F0628D /* Trie.app */; + productType = "com.apple.product-type.application"; + }; + EB798E0A1DFEF79900F0628D /* TrieTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = EB798E221DFEF79900F0628D /* Build configuration list for PBXNativeTarget "TrieTests" */; + buildPhases = ( + EB798E071DFEF79900F0628D /* Sources */, + EB798E081DFEF79900F0628D /* Frameworks */, + EB798E091DFEF79900F0628D /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + EB798E0D1DFEF79900F0628D /* PBXTargetDependency */, + ); + name = TrieTests; + productName = TrieTests; + productReference = EB798E0B1DFEF79900F0628D /* TrieTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + EB798E151DFEF79900F0628D /* TrieUITests */ = { + isa = PBXNativeTarget; + buildConfigurationList = EB798E251DFEF79900F0628D /* Build configuration list for PBXNativeTarget "TrieUITests" */; + buildPhases = ( + EB798E121DFEF79900F0628D /* Sources */, + EB798E131DFEF79900F0628D /* Frameworks */, + EB798E141DFEF79900F0628D /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + EB798E181DFEF79900F0628D /* PBXTargetDependency */, + ); + name = TrieUITests; + productName = TrieUITests; + productReference = EB798E161DFEF79900F0628D /* TrieUITests.xctest */; + productType = "com.apple.product-type.bundle.ui-testing"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + EB798DF21DFEF79900F0628D /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0810; + LastUpgradeCheck = 0810; + ORGANIZATIONNAME = "Rick Zaccone"; + TargetAttributes = { + EB798DF91DFEF79900F0628D = { + CreatedOnToolsVersion = 8.1; + ProvisioningStyle = Automatic; + }; + EB798E0A1DFEF79900F0628D = { + CreatedOnToolsVersion = 8.1; + ProvisioningStyle = Automatic; + TestTargetID = EB798DF91DFEF79900F0628D; + }; + EB798E151DFEF79900F0628D = { + CreatedOnToolsVersion = 8.1; + ProvisioningStyle = Automatic; + TestTargetID = EB798DF91DFEF79900F0628D; + }; + }; + }; + buildConfigurationList = EB798DF51DFEF79900F0628D /* Build configuration list for PBXProject "Trie" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = EB798DF11DFEF79900F0628D; + productRefGroup = EB798DFB1DFEF79900F0628D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + EB798DF91DFEF79900F0628D /* Trie */, + EB798E0A1DFEF79900F0628D /* TrieTests */, + EB798E151DFEF79900F0628D /* TrieUITests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + EB798DF81DFEF79900F0628D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + EB798E2C1DFEF90B00F0628D /* dictionary.txt in Resources */, + EB798E021DFEF79900F0628D /* Assets.xcassets in Resources */, + EB798E051DFEF79900F0628D /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + EB798E091DFEF79900F0628D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + EB798E2D1DFEF90B00F0628D /* dictionary.txt in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + EB798E141DFEF79900F0628D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + EB798DF61DFEF79900F0628D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + EB798E291DFEF81400F0628D /* Trie.swift in Sources */, + EB798E001DFEF79900F0628D /* ViewController.swift in Sources */, + EB798DFE1DFEF79900F0628D /* AppDelegate.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + EB798E071DFEF79900F0628D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + EB798E101DFEF79900F0628D /* TrieTests.swift in Sources */, + EB798E2A1DFEF81400F0628D /* Trie.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + EB798E121DFEF79900F0628D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + EB798E1B1DFEF79900F0628D /* TrieUITests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + EB798E0D1DFEF79900F0628D /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = EB798DF91DFEF79900F0628D /* Trie */; + targetProxy = EB798E0C1DFEF79900F0628D /* PBXContainerItemProxy */; + }; + EB798E181DFEF79900F0628D /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = EB798DF91DFEF79900F0628D /* Trie */; + targetProxy = EB798E171DFEF79900F0628D /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + EB798E031DFEF79900F0628D /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + EB798E041DFEF79900F0628D /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + EB798E1D1DFEF79900F0628D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVES = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.12; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + EB798E1E1DFEF79900F0628D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVES = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.12; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + }; + name = Release; + }; + EB798E201DFEF79900F0628D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Trie/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = edu.bucknell.zaccone.Trie; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; + }; + name = Debug; + }; + EB798E211DFEF79900F0628D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Trie/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = edu.bucknell.zaccone.Trie; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; + }; + name = Release; + }; + EB798E231DFEF79900F0628D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + BUNDLE_LOADER = "$(TEST_HOST)"; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = TrieTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = edu.bucknell.zaccone.TrieTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Trie.app/Contents/MacOS/Trie"; + }; + name = Debug; + }; + EB798E241DFEF79900F0628D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + BUNDLE_LOADER = "$(TEST_HOST)"; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = TrieTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = edu.bucknell.zaccone.TrieTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Trie.app/Contents/MacOS/Trie"; + }; + name = Release; + }; + EB798E261DFEF79900F0628D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = TrieUITests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = edu.bucknell.zaccone.TrieUITests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; + TEST_TARGET_NAME = Trie; + }; + name = Debug; + }; + EB798E271DFEF79900F0628D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = TrieUITests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = edu.bucknell.zaccone.TrieUITests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; + TEST_TARGET_NAME = Trie; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + EB798DF51DFEF79900F0628D /* Build configuration list for PBXProject "Trie" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + EB798E1D1DFEF79900F0628D /* Debug */, + EB798E1E1DFEF79900F0628D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + EB798E1F1DFEF79900F0628D /* Build configuration list for PBXNativeTarget "Trie" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + EB798E201DFEF79900F0628D /* Debug */, + EB798E211DFEF79900F0628D /* Release */, + ); + defaultConfigurationIsVisible = 0; + }; + EB798E221DFEF79900F0628D /* Build configuration list for PBXNativeTarget "TrieTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + EB798E231DFEF79900F0628D /* Debug */, + EB798E241DFEF79900F0628D /* Release */, + ); + defaultConfigurationIsVisible = 0; + }; + EB798E251DFEF79900F0628D /* Build configuration list for PBXNativeTarget "TrieUITests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + EB798E261DFEF79900F0628D /* Debug */, + EB798E271DFEF79900F0628D /* Release */, + ); + defaultConfigurationIsVisible = 0; + }; +/* End XCConfigurationList section */ + }; + rootObject = EB798DF21DFEF79900F0628D /* Project object */; +} diff --git a/Trie/Trie/Trie.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Trie/Trie/Trie.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..cd768f89b --- /dev/null +++ b/Trie/Trie/Trie.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Trie/Trie/Trie/AppDelegate.swift b/Trie/Trie/Trie/AppDelegate.swift new file mode 100644 index 000000000..4da9dc345 --- /dev/null +++ b/Trie/Trie/Trie/AppDelegate.swift @@ -0,0 +1,26 @@ +// +// AppDelegate.swift +// Trie +// +// Created by Rick Zaccone on 2016-12-12. +// Copyright © 2016 Rick Zaccone. All rights reserved. +// + +import Cocoa + +@NSApplicationMain +class AppDelegate: NSObject, NSApplicationDelegate { + + + + func applicationDidFinishLaunching(_ aNotification: Notification) { + // Insert code here to initialize your application + } + + func applicationWillTerminate(_ aNotification: Notification) { + // Insert code here to tear down your application + } + + +} + diff --git a/Trie/Trie/Trie/Assets.xcassets/AppIcon.appiconset/Contents.json b/Trie/Trie/Trie/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 000000000..2db2b1c7c --- /dev/null +++ b/Trie/Trie/Trie/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,58 @@ +{ + "images" : [ + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Trie/Trie/Trie/Base.lproj/Main.storyboard b/Trie/Trie/Trie/Base.lproj/Main.storyboard new file mode 100644 index 000000000..64d3d90d8 --- /dev/null +++ b/Trie/Trie/Trie/Base.lproj/Main.storyboard @@ -0,0 +1,693 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Default + + + + + + + Left to Right + + + + + + + Right to Left + + + + + + + + + + + Default + + + + + + + Left to Right + + + + + + + Right to Left + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Trie/Trie/Trie/Info.plist b/Trie/Trie/Trie/Info.plist new file mode 100644 index 000000000..ed3668788 --- /dev/null +++ b/Trie/Trie/Trie/Info.plist @@ -0,0 +1,32 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + Copyright © 2016 Rick Zaccone. All rights reserved. + NSMainStoryboardFile + Main + NSPrincipalClass + NSApplication + + diff --git a/Trie/Trie/Trie/Trie.swift b/Trie/Trie/Trie/Trie.swift new file mode 100644 index 000000000..bd1abc538 --- /dev/null +++ b/Trie/Trie/Trie/Trie.swift @@ -0,0 +1,207 @@ +// +// Trie.swift +// Trie +// +// Created by Rick Zaccone on 2016-12-12. +// Copyright © 2016 Rick Zaccone. All rights reserved. +// + +import Foundation + + +/// A node in the trie +class TrieNode { + var value: T? + weak var parentNode: TrieNode? + var children: [T: TrieNode] = [:] + var isTerminating = false + var isLeaf: Bool { + get { + return children.count == 0 + } + } + + /// Initializes a node. + /// + /// - Parameters: + /// - value: The value that goes into the node + /// - parentNode: A reference to this node's parent + init(value: T? = nil, parentNode: TrieNode? = nil) { + self.value = value + self.parentNode = parentNode + } + + /// Adds a child node to self. If the child is already present, + /// do nothing. + /// + /// - Parameter value: The item to be added to this node. + func add(value: T) { + guard children[value] == nil else { + return + } + children[value] = TrieNode(value: value, parentNode: self) + } +} + +/// A trie data structure containing words. Each node is a single +/// character of a word. +class Trie { + typealias Node = TrieNode + /// The number of words in the trie + public var count: Int { + return wordCount + } + /// Is the trie empty? + public var isEmpty: Bool { + return wordCount == 0 + } + /// All words currently in the trie + public var words: [String] { + return wordsInSubtrie(rootNode: root, partialWord: "") + } + fileprivate let root: Node + fileprivate var wordCount: Int + + /// Creats an empty trie. + init() { + root = Node() + wordCount = 0 + } +} + +// MARK: - Adds methods: insert, remove, contains +extension Trie { + + /// Inserts a word into the trie. If the word is already present, + /// there is no change. + /// + /// - Parameter word: the word to be inserted. + func insert(word: String) { + guard !word.isEmpty else { + return + } + var currentNode = root + let charactersInWord = Array(word.lowercased().characters) + var index = 0 + while index < charactersInWord.count { + let character = charactersInWord[index] + if let childNode = currentNode.children[character] { + currentNode = childNode + } else { + currentNode.add(value: character) + currentNode = currentNode.children[character]! + } + index += 1 + } + // Word already present? + guard !currentNode.isTerminating else { + return + } + self.wordCount += 1 + currentNode.isTerminating = true + } + + /// Determines whether a word is in the trie. + /// + /// - Parameter word: the word to check for + /// - Returns: true if the word is present, false otherwise. + func contains(word: String) -> Bool { + guard !word.isEmpty else { + return false + } + var currentNode = root + let charactersInWord = Array(word.lowercased().characters) + var index = 0 + while index < charactersInWord.count, let childNode = currentNode.children[charactersInWord[index]] { + index += 1 + currentNode = childNode + } + return index == charactersInWord.count && currentNode.isTerminating + } + + /// Attempts to walk to the terminating node of a word. The + /// search will fail if the word is not present. + /// + /// - Parameter word: the word in question + /// - Returns: the node where the search ended, nil if the + /// search failed. + private func findTerminalNodeOf(word: String) -> Node? { + var currentNode = root + var charactersInWord = Array(word.lowercased().characters) + var index = 0 + while index < charactersInWord.count { + let character = charactersInWord[index] + guard let childNode = currentNode.children[character] else { + return nil + } + currentNode = childNode + index += 1 + } + return currentNode.isTerminating ? currentNode : nil + } + + + /// Deletes a word from the trie by starting with the last letter + /// and moving back, deleting nodes until either a non-leaf or a + /// terminating node is found. + /// + /// - Parameter terminalNode: the node representing the last node + /// of a word + private func deleteNodesForWordEndingWith(terminalNode: Node) { + var lastNode = terminalNode + var character = lastNode.value + while lastNode.isLeaf, let parentNode = lastNode.parentNode { + lastNode = parentNode + lastNode.children[character!] = nil + character = lastNode.value + if lastNode.isTerminating { + break + } + } + } + + /// Removes a word from the trie. If the word is not present or + /// it is empty, just ignore it. If the last node is a leaf, + /// delete that node and higher nodes that are leaves until a + /// terminating node or non-leaf is found. If the last node of + /// the word has more children, the word is part of other words. + /// Mark the last node as non-terminating. + /// + /// - Parameter word: the word to be removed + func remove(word: String) { + guard !word.isEmpty else { + return + } + guard let terminalNode = findTerminalNodeOf(word: word) else { + return + } + if terminalNode.isLeaf { + deleteNodesForWordEndingWith(terminalNode: terminalNode) + } else { + terminalNode.isTerminating = false + } + self.wordCount -= 1 + } + + /// Returns an array of words in a subtrie of the trie + /// + /// - Parameters: + /// - rootNode: the root node of the subtrie + /// - partialWord: the letters collected by traversing to this node + /// - Returns: the words in the subtrie + func wordsInSubtrie(rootNode: Node, partialWord: String) -> [String] { + var subtrieWords = [String]() + var previousLetters = partialWord + if let value = rootNode.value { + previousLetters.append(value) + } + if rootNode.isTerminating { + subtrieWords.append(previousLetters) + } + for (_, childNode) in rootNode.children { + let childWords = wordsInSubtrie(rootNode: childNode, partialWord: previousLetters) + subtrieWords += childWords + } + return subtrieWords + } +} diff --git a/Trie/Trie/Trie/ViewController.swift b/Trie/Trie/Trie/ViewController.swift new file mode 100644 index 000000000..b2e9d9105 --- /dev/null +++ b/Trie/Trie/Trie/ViewController.swift @@ -0,0 +1,27 @@ +// +// ViewController.swift +// Trie +// +// Created by Rick Zaccone on 2016-12-12. +// Copyright © 2016 Rick Zaccone. All rights reserved. +// + +import Cocoa + +class ViewController: NSViewController { + + override func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + } + + override var representedObject: Any? { + didSet { + // Update the view, if already loaded. + } + } + + +} + diff --git a/Trie/Trie/Trie/dictionary.txt b/Trie/Trie/Trie/dictionary.txt new file mode 100644 index 000000000..4e5bcd075 --- /dev/null +++ b/Trie/Trie/Trie/dictionary.txt @@ -0,0 +1,162825 @@ +10s +10th +11th +12th +13th +14th +15th +16th +17th +1800s +1890s +18th +1900s +1910s +1920s +1930s +1940s +1950s +1960s +1970s +1980s +1990s +19th +1st +20s +20th +21st +22nd +23rd +24th +25th +26th +27th +28th +29th +2nd +30s +30th +31st +3rd +40s +4th +50s +5th +60s +6th +70s +7th +80s +8th +90s +9th +a +aachen +aah +aahed +aahing +aahs +aardvark +aardvarks +aardwolf +aardwolves +aaron +ab +aba +ababa +abaca +abaci +aback +abacterial +abacus +abacuses +abadan +abaft +abalone +abalones +abampere +abamperes +abandon +abandoned +abandonee +abandonees +abandoner +abandoners +abandoning +abandonment +abandonments +abandons +abapical +abase +abased +abasement +abasements +abases +abash +abashed +abashes +abashing +abashment +abashments +abasia +abasing +abatable +abate +abated +abatement +abatements +abater +abaters +abates +abating +abatis +abatises +abattoir +abattoirs +abaxial +abbacies +abbacy +abbatial +abbess +abbesses +abbeville +abbevillian +abbey +abbeys +abbot +abbots +abbreviate +abbreviated +abbreviates +abbreviating +abbreviation +abbreviations +abbreviator +abbreviators +abbé +abbés +abc +abcoulomb +abdicable +abdicate +abdicated +abdicates +abdicating +abdication +abdications +abdicator +abdicators +abdomen +abdomens +abdominal +abdominally +abdominous +abducens +abducent +abducentes +abduct +abducted +abducting +abduction +abductions +abductor +abductors +abducts +abeam +abecedarian +abecedarians +abed +abednego +abel +abelard +abelia +abelian +abelmosk +abelmosks +aberdare +aberdeen +aberdonian +aberdonians +aberrance +aberrancies +aberrancy +aberrant +aberrantly +aberrants +aberrated +aberration +aberrational +aberrations +abet +abetment +abetments +abets +abetted +abetter +abetters +abetting +abettor +abettors +abeyance +abeyant +abfarad +abfarads +abhenries +abhenry +abhor +abhorred +abhorrence +abhorrences +abhorrent +abhorrently +abhorrer +abhorrers +abhorring +abhors +abidance +abidances +abide +abided +abider +abiders +abides +abiding +abidingly +abidingness +abigail +abigails +abilities +ability +abiogeneses +abiogenesis +abiogenetic +abiogenetical +abiogenic +abiogenically +abiogenist +abiological +abiologically +abiosis +abiotic +abiotically +abject +abjection +abjections +abjectly +abjectness +abjuration +abjurations +abjure +abjured +abjurer +abjurers +abjures +abjuring +ablate +ablated +ablates +ablating +ablation +ablations +ablative +ablatively +ablatives +ablaut +ablaze +able +abler +ablest +abloom +abluted +ablution +ablutionary +ablutions +ably +abnegate +abnegated +abnegates +abnegating +abnegation +abnegations +abnegator +abnegators +abnormal +abnormalities +abnormality +abnormally +abnormals +aboard +abode +abodes +abohm +aboil +abolish +abolishable +abolished +abolisher +abolishers +abolishes +abolishing +abolishment +abolishments +abolition +abolitionary +abolitionism +abolitionist +abolitionists +abomasa +abomasal +abomasum +abominable +abominably +abominate +abominated +abominates +abominating +abomination +abominations +abominator +abominators +aboral +aborally +aboriginal +aboriginally +aborigine +aborigines +aborning +abort +aborted +aborter +aborters +abortifacient +aborting +abortion +abortionist +abortionists +abortions +abortive +abortively +abortiveness +aborts +abos +abound +abounded +abounding +abounds +about +above +aboveboard +aboveground +abracadabra +abrachia +abradable +abradant +abradants +abrade +abraded +abrader +abraders +abrades +abrading +abraham +abranchiate +abrash +abrasion +abrasions +abrasive +abrasively +abrasiveness +abrasives +abreact +abreacted +abreacting +abreaction +abreactions +abreacts +abreast +abridge +abridged +abridgement +abridgements +abridger +abridgers +abridges +abridging +abridgment +abridgments +abrin +abroach +abroad +abrogate +abrogated +abrogates +abrogating +abrogation +abrogations +abrupt +abruption +abruptly +abruptness +abruzzi +abruzzo +absalom +abscess +abscessed +abscesses +abscessing +abscise +abscised +abscises +abscisin +abscising +abscisins +abscissa +abscissae +abscissas +abscission +abscissions +abscond +absconded +absconder +absconders +absconding +absconds +absence +absences +absent +absented +absentee +absenteeism +absentees +absentia +absenting +absently +absentminded +absentmindedly +absentmindedness +absents +absinth +absinthe +absinthes +absinths +absolute +absolutely +absoluteness +absolutes +absolution +absolutions +absolutism +absolutisms +absolutist +absolutistic +absolutists +absolutize +absolutized +absolutizes +absolutizing +absolvable +absolve +absolved +absolver +absolvers +absolves +absolving +absorb +absorbability +absorbable +absorbance +absorbancy +absorbant +absorbants +absorbed +absorbedly +absorbedness +absorbefacient +absorbencies +absorbency +absorbent +absorbents +absorber +absorbers +absorbing +absorbingly +absorbs +absorptance +absorption +absorptions +absorptive +absorptivity +absquatulate +absquatulated +absquatulates +absquatulating +abstain +abstained +abstainer +abstainers +abstaining +abstains +abstemious +abstemiously +abstemiousness +abstention +abstentions +abstentious +abstinence +abstinent +abstinently +abstract +abstractable +abstracted +abstractedly +abstractedness +abstracter +abstracters +abstracting +abstraction +abstractional +abstractionism +abstractionist +abstractionists +abstractions +abstractive +abstractly +abstractness +abstractor +abstractors +abstracts +abstruse +abstrusely +abstruseness +abstrusities +abstrusity +absurd +absurdism +absurdist +absurdities +absurdity +absurdly +absurdness +absurdum +abu +abubble +abuilding +abulia +abulias +abulic +abundance +abundances +abundant +abundantly +abusable +abuse +abused +abuser +abusers +abuses +abusing +abusive +abusively +abusiveness +abut +abutilon +abutilons +abutment +abutments +abuts +abutted +abutter +abutters +abutting +abuzz +abvolt +abvolts +aby +abydos +abye +abyes +abying +abys +abysm +abysmal +abysmally +abysms +abyss +abyssal +abysses +abyssinia +abyssinian +abyssinians +acacia +acacias +academe +academes +academia +academic +academical +academically +academician +academicians +academicism +academics +academies +academism +academy +acantha +acanthae +acanthi +acanthocephalan +acanthoid +acanthopterygian +acanthus +acanthuses +acapnia +acapulco +acari +acariasis +acarid +acaridae +acarids +acarologist +acarology +acarophobia +acarpous +acarus +acatalectic +acaudate +acaulescent +accede +acceded +accedence +acceder +acceders +accedes +acceding +accelerando +accelerant +accelerate +accelerated +accelerates +accelerating +acceleratingly +acceleration +accelerations +accelerative +accelerator +accelerators +accelerograph +accelerometer +accelerometers +accent +accented +accenting +accentless +accents +accentual +accentually +accentuate +accentuated +accentuates +accentuating +accentuation +accept +acceptability +acceptable +acceptableness +acceptably +acceptance +acceptances +acceptant +acceptation +accepted +acceptedly +accepter +accepters +accepting +acceptingly +acceptingness +acceptive +acceptor +acceptors +accepts +access +accessaries +accessary +accessed +accesses +accessibility +accessible +accessibleness +accessibly +accessing +accession +accessional +accessioned +accessioning +accessions +accessorial +accessories +accessorily +accessoriness +accessorize +accessorized +accessorizes +accessorizing +accessory +acciaccatura +accidence +accident +accidental +accidentally +accidentalness +accidentals +accidently +accidents +accidie +accidies +accipiter +accipitrine +acclaim +acclaimed +acclaimer +acclaimers +acclaiming +acclaims +acclamation +acclamations +acclamatory +acclimate +acclimated +acclimates +acclimating +acclimation +acclimatization +acclimatize +acclimatized +acclimatizer +acclimatizers +acclimatizes +acclimatizing +acclivities +acclivitous +acclivity +accolade +accoladed +accolades +accolading +accommodate +accommodated +accommodates +accommodating +accommodatingly +accommodation +accommodational +accommodationist +accommodations +accommodative +accommodativeness +accommodator +accommodators +accompanied +accompanies +accompaniment +accompaniments +accompanist +accompanists +accompany +accompanying +accompli +accomplice +accomplices +accomplis +accomplish +accomplishable +accomplished +accomplisher +accomplishers +accomplishes +accomplishing +accomplishment +accomplishments +accord +accordance +accordances +accordant +accordantly +accorded +according +accordingly +accordion +accordionist +accordionists +accordions +accords +accost +accosted +accosting +accosts +accouchement +accouchements +account +accountabilities +accountability +accountable +accountableness +accountably +accountancies +accountancy +accountant +accountants +accountantship +accounted +accounting +accountings +accounts +accouter +accoutered +accoutering +accouterment +accouterments +accouters +accoutre +accoutred +accoutrement +accoutrements +accoutres +accoutring +accra +accredit +accreditable +accreditation +accreditations +accredited +accrediting +accredits +accrescent +accrete +accreted +accretes +accreting +accretion +accretionary +accretions +accretive +accruable +accrual +accruals +accrue +accrued +accruement +accruements +accrues +accruing +acculturate +acculturated +acculturates +acculturating +acculturation +acculturational +acculturative +accumbent +accumulable +accumulate +accumulated +accumulates +accumulating +accumulation +accumulations +accumulative +accumulatively +accumulativeness +accumulator +accumulators +accuracies +accuracy +accurate +accurately +accurateness +accurse +accursed +accursedly +accursedness +accurst +accusable +accusal +accusals +accusation +accusations +accusative +accusatively +accusatives +accusatorial +accusatorially +accusatory +accuse +accused +accuser +accusers +accuses +accusing +accusingly +accustom +accustomation +accustomed +accustomedness +accustoming +accustoms +ace +aced +acedia +acedias +aceldama +acellular +acentric +acephalous +acequia +acequias +acerate +acerated +acerb +acerbate +acerbated +acerbates +acerbating +acerbic +acerbically +acerbities +acerbity +acerola +acerolas +acerose +acervuli +acervulus +aces +acetabula +acetabular +acetabulum +acetal +acetaldehyde +acetals +acetamide +acetaminophen +acetanilide +acetate +acetates +acetic +acetification +acetified +acetifier +acetifies +acetify +acetifying +acetoaceticacetonic +acetone +acetones +acetonic +acetophenetidin +acetous +acetum +acetyl +acetylate +acetylated +acetylates +acetylating +acetylation +acetylative +acetylcholine +acetylcholinesterase +acetylene +acetylenic +acetylic +acetyls +acetylsalicylic +achaea +achaean +achaeans +achaemenid +achaemenids +achalasia +achates +ache +ached +achene +achenes +achenial +acheron +aches +acheulean +acheuleans +acheulian +acheulians +achier +achiest +achievable +achieve +achieved +achievement +achievements +achiever +achievers +achieves +achieving +achillea +achilles +achiness +aching +achingly +achira +achlamydeous +achlorhydria +achlorhydric +achlorophyllous +acholia +achondrite +achondritic +achondroplasia +achondroplastic +achromat +achromatic +achromatically +achromaticity +achromatin +achromatinic +achromatism +achromatize +achromatized +achromatizes +achromatizing +achromats +achromic +achy +acicula +aciculae +acicular +aciculas +aciculate +aciculated +acid +acidanthera +acidemia +acidhead +acidheads +acidic +acidifiable +acidification +acidified +acidifier +acidifiers +acidifies +acidify +acidifying +acidimeter +acidimeters +acidimetric +acidimetry +acidities +acidity +acidly +acidness +acidophil +acidophilic +acidophilus +acidosis +acidotic +acids +acidulate +acidulated +acidulates +acidulating +acidulation +acidulent +acidulous +aciduria +acidy +acinar +acing +acini +acinic +acinous +acinus +ackee +ackees +ackerman +acknowledge +acknowledgeable +acknowledged +acknowledgedly +acknowledgement +acknowledgements +acknowledges +acknowledging +acknowledgment +acknowledgments +acme +acmes +acne +acned +acock +acoelomate +acoelous +acold +acolyte +acolytes +aconite +aconites +acorn +acorns +acoustic +acoustical +acoustically +acoustician +acoustics +acoustoelectric +acoustoelectrically +acoustooptical +acoustooptically +acoustooptics +acquaint +acquaintance +acquaintances +acquaintanceship +acquaintanceships +acquainted +acquainting +acquaints +acquiesce +acquiesced +acquiescence +acquiescent +acquiescently +acquiesces +acquiescing +acquirable +acquire +acquired +acquirement +acquirements +acquirer +acquirers +acquires +acquiring +acquisition +acquisitional +acquisitions +acquisitive +acquisitively +acquisitiveness +acquisitor +acquit +acquits +acquittal +acquittals +acquittance +acquitted +acquitter +acquitters +acquitting +acre +acreage +acreages +acres +acrid +acridine +acridines +acridities +acridity +acridly +acridness +acriflavine +acrimonious +acrimoniously +acrimoniousness +acrimony +acrobat +acrobatic +acrobatically +acrobatics +acrobats +acrocentric +acrocephalic +acrocephaly +acrodont +acrodonts +acrolect +acrolein +acroleins +acromegalic +acromegalies +acromegaly +acromelic +acromion +acronym +acronymic +acronymically +acronymous +acronyms +acropetal +acropetally +acrophobia +acropolis +acropolises +acrosomal +acrosome +across +acrostic +acrostical +acrostically +acrostics +acrylate +acrylates +acrylic +acrylics +acrylonitrile +act +acta +actability +actable +actaeon +acte +acted +actes +actin +actinal +actinally +acting +actinia +actiniae +actinian +actinians +actinic +actinically +actinide +actinides +actinism +actinium +actinoid +actinolite +actinomere +actinometer +actinometers +actinometric +actinometrical +actinometry +actinomorphic +actinomorphous +actinomorphy +actinomyces +actinomycetal +actinomycete +actinomycetous +actinomycin +actinomycosis +actinomycotic +actinon +actinons +actinouranium +action +actionable +actionably +actionless +actions +actium +activate +activated +activates +activating +activation +activations +activator +activators +active +actively +activeness +actives +activism +activist +activistic +activists +activities +activity +actomyosin +actor +actorish +actors +actress +actresses +acts +actual +actualities +actuality +actualization +actualizations +actualize +actualized +actualizes +actualizing +actually +actuarial +actuarially +actuaries +actuary +actuate +actuated +actuates +actuating +actuation +actuations +actuator +actuators +acuity +aculeate +acumen +acuminate +acuminated +acuminates +acuminating +acumination +acupressure +acupuncture +acupunctured +acupunctures +acupuncturing +acupuncturist +acupuncturists +acute +acutely +acuteness +acuter +acutest +acyclic +acyclovir +acyl +acylate +acylated +acylates +acylating +acylation +acylations +acyls +ad +ada +adage +adages +adagio +adagios +adam +adamance +adamances +adamancies +adamancy +adamant +adamantine +adamantly +adamants +adapt +adaptability +adaptable +adaptableness +adaptation +adaptational +adaptationally +adaptations +adapted +adaptedness +adapter +adapters +adapting +adaption +adaptions +adaptive +adaptively +adaptiveness +adaptivity +adaptor +adaptors +adapts +adaxial +add +addable +addax +addaxes +added +addend +addenda +addends +addendum +adder +adders +addible +addict +addicted +addicting +addiction +addictions +addictive +addicts +adding +addis +addison +addition +additional +additionally +additions +additive +additively +additives +additivity +addle +addlebrained +addled +addlepated +addles +addling +address +addressability +addressable +addressed +addressee +addressees +addresser +addressers +addresses +addressing +adds +adduce +adduceable +adduced +adducer +adducers +adduces +adducing +adduct +adducted +adducting +adduction +adductive +adductor +adductors +adducts +adelaide +ademption +aden +adenectomy +adenine +adenines +adenitis +adenitises +adenocarcinoma +adenocarcinomatous +adenohypophyseal +adenohypophyses +adenohypophysial +adenohypophysis +adenoid +adenoidal +adenoids +adenoma +adenomas +adenomatoid +adenomatous +adenosine +adenosis +adenosyl +adenoviral +adenovirus +adenoviruses +adenyl +adept +adeptly +adeptness +adepts +adequacies +adequacy +adequate +adequately +adequateness +adhere +adhered +adherence +adherent +adherently +adherents +adheres +adhering +adhesion +adhesional +adhesions +adhesiotomies +adhesiotomy +adhesive +adhesively +adhesiveness +adhesives +adiabatic +adiabatically +adieu +adieus +adieux +adige +adios +adipic +adipocere +adipocyte +adipose +adiposeness +adiposity +adirondack +adirondacks +adit +adits +adjacencies +adjacency +adjacent +adjacently +adjectival +adjectivally +adjective +adjectively +adjectives +adjoin +adjoined +adjoining +adjoins +adjoint +adjoints +adjourn +adjourned +adjourning +adjournment +adjournments +adjourns +adjudge +adjudged +adjudges +adjudging +adjudicate +adjudicated +adjudicates +adjudicating +adjudication +adjudications +adjudicative +adjudicator +adjudicators +adjudicatory +adjunct +adjunction +adjunctive +adjunctly +adjuncts +adjuration +adjurations +adjuratory +adjure +adjured +adjurer +adjurers +adjures +adjuring +adjust +adjustability +adjustable +adjustably +adjusted +adjuster +adjusters +adjusting +adjustive +adjustment +adjustmental +adjustments +adjustor +adjustors +adjusts +adjutancy +adjutant +adjutants +adjuvant +adjuvants +adlerian +adlib +adlibbed +adlibs +adman +admass +admeasure +admeasured +admeasurement +admeasurements +admeasurer +admeasures +admeasuring +admen +admin +administer +administered +administering +administers +administrable +administrant +administrants +administrate +administrated +administrates +administrating +administration +administrational +administrations +administrative +administratively +administrator +administrators +administratra +administratrices +administratrix +admirability +admirable +admirableness +admirably +admiral +admirals +admiralties +admiralty +admiration +admirations +admire +admired +admirer +admirers +admires +admiring +admiringly +admissibility +admissible +admissibleness +admissibly +admission +admissions +admissive +admit +admits +admittance +admittances +admitted +admittedly +admitting +admix +admixed +admixes +admixing +admixture +admixtures +admonish +admonished +admonisher +admonishes +admonishing +admonishingly +admonishment +admonishments +admonition +admonitions +admonitorily +admonitory +adnate +adnation +adnations +adnexa +adnexal +adnominal +adnoun +adnouns +ado +adobe +adobes +adolescence +adolescent +adolescently +adolescents +adonais +adonis +adopt +adoptability +adoptable +adopted +adoptee +adoptees +adopter +adopters +adoptianism +adoptianist +adoptianists +adopting +adoption +adoptionism +adoptionist +adoptionists +adoptions +adoptive +adoptively +adopts +adorability +adorable +adorableness +adorably +adoral +adoration +adore +adored +adorer +adorers +adores +adoring +adoringly +adorn +adorned +adorner +adorners +adorning +adornment +adornments +adorns +adrenal +adrenalectomy +adrenalin +adrenaline +adrenalize +adrenalized +adrenalizes +adrenalizing +adrenally +adrenals +adrenergic +adrenergically +adrenochrome +adrenocortical +adrenocorticosteroid +adrenocorticotrophic +adrenocorticotrophin +adrenocorticotropic +adrenocorticotropin +adrenolytic +adriatic +adrift +adroit +adroitly +adroitness +ads +adscititious +adsorb +adsorbable +adsorbate +adsorbates +adsorbed +adsorbent +adsorbents +adsorbing +adsorbs +adsorption +adsorptive +adularia +adularias +adulate +adulated +adulates +adulating +adulation +adulations +adulator +adulators +adulatory +adult +adulterant +adulterants +adulterate +adulterated +adulterates +adulterating +adulteration +adulterations +adulterator +adulterators +adulterer +adulterers +adulteress +adulteresses +adulteries +adulterine +adulterous +adulterously +adultery +adulthood +adultlike +adultly +adultness +adults +adumbrate +adumbrated +adumbrates +adumbrating +adumbration +adumbrations +adumbrative +adumbratively +adust +advance +advanced +advancement +advancements +advancer +advancers +advances +advancing +advantage +advantaged +advantageous +advantageously +advantageousness +advantages +advantaging +advect +advected +advecting +advection +advections +advective +advects +advent +adventism +adventist +adventists +adventitia +adventitial +adventitious +adventitiously +adventitiousness +adventive +adventively +advents +adventure +adventured +adventurer +adventurers +adventures +adventuresome +adventuresomely +adventuresomeness +adventuress +adventuresses +adventuring +adventurism +adventurist +adventuristic +adventurists +adventurous +adventurously +adventurousness +adverb +adverbial +adverbially +adverbs +adversarial +adversaries +adversary +adversative +adversatively +adverse +adversely +adverseness +adversities +adversity +advert +adverted +advertence +advertences +advertencies +advertency +advertent +advertently +adverting +advertise +advertised +advertisement +advertisements +advertiser +advertisers +advertises +advertising +adverts +advice +advices +advisability +advisable +advisableness +advisably +advise +advised +advisedly +advisee +advisees +advisement +advisements +adviser +advisers +advises +advising +advisor +advisories +advisors +advisory +advocacy +advocate +advocated +advocates +advocating +advocation +advocative +advocator +advocators +advocatory +advowson +advowsons +adynamia +adynamias +adynamic +adyta +adytum +adz +adze +adzes +aechmea +aecia +aecial +aeciospore +aecium +aedes +aedilberct +aedile +aediles +aedine +aegean +aegeus +aegis +aeneas +aeneid +aeneous +aeolian +aeolians +aeolic +aeolus +aeon +aeonian +aeonic +aeons +aepyornis +aequorin +aerate +aerated +aerates +aerating +aeration +aerations +aerator +aerators +aerenchyma +aerial +aerialist +aerialists +aerially +aerials +aerie +aerier +aeries +aeriest +aerily +aero +aeroallergen +aeroballistic +aeroballistics +aerobat +aerobatic +aerobatics +aerobe +aerobes +aerobic +aerobically +aerobicize +aerobicized +aerobicizes +aerobicizing +aerobics +aerobiological +aerobiologically +aerobiology +aerobiosis +aerobiotic +aerobium +aeroculture +aerodrome +aerodromes +aerodynamic +aerodynamical +aerodynamically +aerodynamicist +aerodynamicists +aerodynamics +aerodyne +aerodynes +aeroembolism +aerofoil +aerofoils +aerogram +aerograms +aerographer +aerolite +aerolites +aerolith +aeroliths +aerolitic +aerologic +aerological +aerologist +aerologists +aerology +aeromagnetic +aeromagnetically +aeromagnetics +aeromechanical +aeromechanically +aeromechanics +aeromedical +aeromedicine +aerometeorograph +aerometer +aerometers +aeronaut +aeronautic +aeronautical +aeronautically +aeronautics +aeronauts +aeroneurosis +aeronomer +aeronomic +aeronomical +aeronomist +aeronomy +aeropause +aerophagia +aerophobia +aerophore +aerophyte +aeroplane +aeroplanes +aeroponics +aerosol +aerosolization +aerosolize +aerosolized +aerosolizes +aerosolizing +aerosols +aerospace +aerosphere +aerostat +aerostatic +aerostatical +aerostatics +aerostats +aerotactic +aerotaxis +aerothermodynamics +aery +aeschylus +aesculapian +aesculapius +aesop +aesopian +aesopic +aesthesia +aesthete +aesthetes +aesthetic +aesthetically +aesthetician +aestheticians +aestheticism +aestheticize +aestheticized +aestheticizes +aestheticizing +aesthetics +aestival +aestivate +aestivated +aestivates +aestivating +aestivation +aethelberht +aethelred +aether +aetheric +aethers +afar +afeard +afeared +afebrile +affability +affable +affably +affair +affaire +affaires +affairs +affect +affectability +affectable +affectation +affectations +affected +affectedly +affectedness +affecter +affecters +affecting +affectingly +affection +affectional +affectionally +affectionate +affectionately +affectionateness +affectioned +affectionless +affections +affective +affectively +affectivity +affectless +affectlessness +affects +affenpinscher +afferent +afferently +affiance +affianced +affiances +affiancing +affiant +affiants +afficionado +affidavit +affidavits +affiliate +affiliated +affiliates +affiliating +affiliation +affiliations +affine +affined +affinely +affinities +affinity +affirm +affirmable +affirmably +affirmance +affirmant +affirmation +affirmations +affirmative +affirmatively +affirmatives +affirmed +affirmer +affirmers +affirming +affirms +affix +affixable +affixal +affixation +affixations +affixed +affixer +affixers +affixes +affixial +affixing +affixment +afflatus +afflatuses +afflict +afflicted +afflicter +afflicting +affliction +afflictions +afflictive +afflictively +afflicts +affluence +affluency +affluent +affluently +affluents +afflux +affluxes +afford +affordability +affordable +affordably +afforded +affording +affords +afforest +afforestation +afforested +afforesting +afforests +affray +affrayed +affraying +affrays +affricate +affricates +affricative +affright +affrighted +affrighting +affrightment +affrights +affront +affronted +affronting +affronts +affusion +affusions +afghan +afghani +afghanistan +afghans +aficionada +aficionado +aficionados +afield +afire +aflame +aflatoxicosis +aflatoxin +afloat +aflutter +afoot +afore +aforementioned +aforesaid +aforethought +aforetime +aforetimes +afoul +afraid +afreet +afreets +afresh +africa +african +africanism +africanist +africanization +africanize +africanized +africanizes +africanizing +africans +africanus +afrikaans +afrikaner +afrikaners +afrit +afrits +afro +afros +aft +after +afterbirth +afterbirths +afterburner +afterburners +aftercare +afterclap +afterdamp +afterdeck +afterdecks +aftereffect +aftereffects +afterglow +afterimage +afterimages +afterlife +afterlives +aftermarket +aftermarkets +aftermath +aftermost +afternoon +afternoons +afterpains +afterpiece +afters +aftersensation +aftershave +aftershaves +aftershock +aftershocks +aftertaste +aftertastes +afterthought +afterthoughts +aftertime +aftertimes +afterward +afterwards +afterword +afterwork +afterworld +afterworlds +aftmost +agadir +again +against +agalactia +agama +agamas +agamemnon +agamete +agametes +agamic +agamically +agammaglobulinemia +agammaglobulinemic +agamogenesis +agamospermy +agapanthus +agape +agar +agaric +agarics +agars +agassiz +agate +agates +agave +agaves +agaze +age +aged +agedly +agedness +ageing +ageism +ageist +ageists +ageless +agelessly +agelessness +agelong +agencies +agency +agenda +agendaless +agendas +agendum +agendums +agenesis +agent +agential +agentries +agentry +agents +ager +ageratum +ageratums +agers +ages +aggie +aggies +aggiornamento +aggiornamentos +agglomerate +agglomerated +agglomerates +agglomerating +agglomeration +agglomerations +agglomerative +agglomerator +agglutinability +agglutinable +agglutinant +agglutinate +agglutinated +agglutinates +agglutinating +agglutination +agglutinations +agglutinative +agglutinin +agglutinins +agglutinogen +agglutinogenic +aggradation +aggradational +aggrade +aggraded +aggrades +aggrading +aggrandize +aggrandized +aggrandizement +aggrandizements +aggrandizer +aggrandizers +aggrandizes +aggrandizing +aggravate +aggravated +aggravates +aggravating +aggravatingly +aggravation +aggravations +aggravative +aggravator +aggravators +aggregate +aggregated +aggregately +aggregateness +aggregates +aggregating +aggregation +aggregational +aggregations +aggregative +aggregatively +aggregator +aggregators +aggress +aggressed +aggresses +aggressing +aggression +aggressions +aggressive +aggressively +aggressiveness +aggressivity +aggressor +aggressors +aggrieve +aggrieved +aggrievedly +aggrieves +aggrieving +agha +aghas +aghast +agile +agilely +agileness +agility +agin +agincourt +aging +agism +agist +agists +agita +agitate +agitated +agitatedly +agitates +agitating +agitation +agitational +agitative +agitato +agitator +agitators +agitprop +agitprops +aglaia +aglare +agleam +aglet +aglets +agley +aglitter +aglow +aglycon +aglycone +aglycones +aglycons +agnail +agnails +agnate +agnates +agnathan +agnatic +agnatically +agnation +agnations +agnes +agnize +agnized +agnizes +agnizing +agnomen +agnomens +agnomina +agnosia +agnostic +agnostically +agnosticism +agnostics +agnus +ago +agog +agon +agonal +agone +agones +agonic +agonies +agonist +agonistes +agonistic +agonistically +agonists +agonize +agonized +agonizes +agonizing +agonizingly +agony +agora +agorae +agoraphobia +agoraphobiac +agoraphobic +agoras +agorot +agoroth +agotis +agouti +agouties +agoutis +agra +agrafe +agrafes +agraffe +agraffes +agranulocytosis +agrapha +agraphia +agraphias +agraphic +agrarian +agrarianism +agrarianly +agrarians +agree +agreeability +agreeable +agreeableness +agreeably +agreed +agreeing +agreement +agreements +agrees +agribusiness +agricide +agricola +agricultural +agriculturalist +agriculturalists +agriculturally +agriculture +agricultures +agriculturist +agriculturists +agrigento +agrimation +agrimonies +agrimony +agrippa +agrippina +agrobiologic +agrobiological +agrobiologically +agrobiologist +agrobiology +agrochemical +agroforester +agroforesters +agroforestry +agroindustrial +agrologic +agrological +agrologically +agrologist +agrology +agronomic +agronomical +agronomically +agronomist +agronomists +agronomy +agrostologist +agrostology +aground +aguacate +ague +aguecheek +agues +aguish +aguishly +aguishness +ah +aha +ahab +ahead +ahem +ahems +ahimsa +ahimsas +ahistoric +ahistorical +ahmadabad +ahmedabad +ahold +aholds +ahoy +ahs +ai +aiblins +aid +aidan +aide +aided +aider +aiders +aides +aiding +aidman +aidmen +aids +aigret +aigrets +aigrette +aigrettes +aiguille +aiguilles +aiguillette +aikido +aikidos +ail +ailanthus +ailanthuses +ailed +aileron +ailerons +ailing +ailment +ailments +ails +ailurophile +ailurophobe +ailurophobia +aim +aimed +aiming +aimless +aimlessly +aimlessness +aims +ain +ain't +ainu +ainus +aioli +air +airbag +airbags +airbed +airbeds +airboat +airboats +airborne +airbrake +airbrakes +airbrush +airbrushed +airbrushes +airbrushing +airburst +airbursts +airbus +airbuses +aircraft +aircrew +aircrews +airdate +airdrome +airdromes +airdrop +airdropped +airdropping +airdrops +aired +airedale +airedales +airer +airers +aires +airfare +airfares +airfield +airfields +airflow +airfoil +airfoils +airforce +airforces +airframe +airframes +airfreight +airglow +airglows +airhead +airheads +airier +airiest +airily +airiness +airing +airings +airless +airlessness +airlift +airlifted +airlifting +airlifts +airline +airliner +airliners +airlines +airlock +airlocks +airmail +airmailed +airmailing +airmails +airman +airmanship +airmen +airmobile +airpark +airparks +airplane +airplanes +airplay +airport +airports +airpost +airpower +airs +airscrew +airscrews +airship +airships +airsick +airsickness +airside +airspace +airspeed +airspeeds +airstream +airstreams +airstrip +airstrips +airt +airted +airtight +airtightness +airtime +airting +airts +airwave +airwaves +airway +airways +airwoman +airwomen +airworthier +airworthiest +airworthiness +airworthy +airy +aisle +aisles +ait +aitch +aitchbone +aitches +aits +aix +ajar +ajax +ajuga +ajugas +akaryocyte +akbar +akee +akees +akhenaten +akhenaton +akimbo +akin +akinesia +akinetic +akkad +akrotiri +al +ala +alabama +alabaman +alabamans +alabamian +alabamians +alabaster +alabastrine +alack +alacritous +alacrity +aladdin +alae +alai +alameda +alamedas +alamein +alamo +alamode +alamodes +alamogordo +alamos +alanine +alanines +alanyl +alanyls +alar +alaric +alarm +alarmed +alarming +alarmingly +alarmism +alarmist +alarmists +alarms +alarum +alarums +alary +alas +alaska +alaskan +alaskans +alassio +alastor +alastors +alate +alb +albacore +albacores +alban +albania +albanian +albanians +albany +albatross +albatrosses +albedo +albedos +albeit +albert +alberta +albertus +albescent +albigenses +albigensian +albigensianism +albinism +albinistic +albino +albinos +albinotic +albion +albite +albites +albitic +albitical +albs +album +albumen +albumin +albuminoid +albuminous +albuminuria +albuminuric +albumose +albumoses +albums +albuquerque +alcaic +alcaics +alcaide +alcaides +alcalde +alcaldes +alcatraz +alcayde +alcaydes +alcazar +alcazars +alcestis +alchemic +alchemical +alchemically +alchemist +alchemistic +alchemistical +alchemists +alchemize +alchemized +alchemizes +alchemizing +alchemy +alcibiades +alcohol +alcoholic +alcoholically +alcoholicity +alcoholics +alcoholism +alcoholometer +alcoholometers +alcoholometry +alcohols +alcott +alcove +alcoves +alcuin +aldebaran +aldehyde +aldehydes +alder +alderman +aldermancy +aldermanic +aldermen +alders +alderwoman +alderwomen +aldicarb +aldis +aldol +aldolase +aldolases +aldols +aldose +aldoses +aldosterone +aldosteronism +aldrin +aldrins +ale +aleatoric +aleatory +alec +alecithal +aleck +alecks +alecky +alecs +alee +alegar +alegars +alehouse +alehouses +alembic +alembics +alençon +aleph +alephs +aleppo +alert +alerted +alerting +alertly +alertness +alerts +ales +aleuron +aleurone +aleurones +aleuronic +aleurons +aleut +aleutian +aleutians +aleuts +alevin +alevins +alewife +alewives +alex +alexander +alexandra +alexandria +alexandrian +alexandrine +alexandrines +alexandrite +alexandrites +alexia +alexin +alfa +alfalfa +alfas +alfilaria +alfonso +alforja +alforjas +alfred +alfredo +alfresco +alga +algae +algaecide +algaecides +algal +algaroba +algarobas +algarroba +algarrobas +algarve +algas +algebra +algebraic +algebraically +algebraist +algebraists +algebras +algeciras +alger +algeria +algerian +algerians +algicidal +algicide +algicides +algid +algidities +algidity +algiers +algin +alginate +alginates +algins +algoid +algol +algolagnia +algolagniac +algolagnic +algolagnist +algological +algologically +algologist +algologists +algology +algonquian +algonquians +algonquin +algonquins +algophobia +algorism +algorithm +algorithmic +algorithmically +algorithms +alhambra +ali +alia +alias +aliases +alibi +alibied +alibiing +alibis +alible +alicante +alice +alicyclic +alidad +alidade +alidades +alidads +alien +alienability +alienable +alienage +alienages +alienate +alienated +alienates +alienating +alienation +alienator +alienators +aliened +alienee +alienees +aliening +alienism +alienisms +alienist +alienists +alienly +alienness +alienor +alienors +aliens +aliesterase +aliform +alight +alighted +alighting +alightment +alights +align +aligned +aligner +aligners +aligning +alignment +alignments +aligns +alike +alikeness +aliment +alimental +alimentally +alimentary +alimentation +alimentative +alimented +alimenting +aliments +alimonies +alimony +aline +alined +alinement +alinements +alines +alining +aliphatic +aliquot +aliquots +alit +aliter +alive +aliveness +aliyah +aliyahs +alizarin +alizarine +alizarines +alizarins +alkahest +alkahestic +alkahestical +alkahests +alkalescence +alkalescent +alkali +alkalimeter +alkalimeters +alkalimetry +alkaline +alkalinity +alkalinization +alkalinize +alkalinized +alkalinizes +alkalinizing +alkalis +alkalization +alkalize +alkalized +alkalizes +alkalizing +alkaloid +alkaloidal +alkaloids +alkaloses +alkalosis +alkalotic +alkane +alkanes +alkanet +alkanets +alkene +alkenes +alkine +alkines +alkoxy +alkyd +alkyds +alkyl +alkylate +alkylated +alkylates +alkylating +alkylation +alkyls +alkyne +alkynes +all +alla +allah +allahabad +allamanda +allan +allantoic +allantoid +allantoides +allantoin +allantois +allargando +allay +allayed +allayer +allayers +allaying +allayment +allays +allegation +allegations +allege +allegeable +alleged +allegedly +alleger +allegers +alleges +alleghenies +allegheny +allegiance +allegiances +allegiant +alleging +allegoric +allegorical +allegorically +allegoricalness +allegories +allegorist +allegorists +allegorization +allegorize +allegorized +allegorizer +allegorizes +allegorizing +allegory +allegretto +allegrettos +allegro +allegros +allele +alleles +allelic +allelism +allelomorph +allelomorphic +allelomorphism +allelomorphs +allelopathic +allelopathy +alleluia +alleluias +allemande +allemandes +allen +allenby +aller +allergen +allergenic +allergenicity +allergens +allergic +allergies +allergist +allergists +allergy +allers +allethrin +alleviate +alleviated +alleviates +alleviating +alleviation +alleviations +alleviative +alleviator +alleviators +alleviatory +alley +alleyn +alleyne +alleys +alleyway +alleyways +alliaceous +alliance +alliances +allied +allies +alligator +alligatoring +alligators +allison +alliterate +alliterated +alliterates +alliterating +alliteration +alliterations +alliterative +alliteratively +alliterativeness +allium +alliums +alloantibody +alloantigen +allocable +allocatable +allocate +allocated +allocates +allocating +allocation +allocations +allocator +allocators +allochthonous +allocution +allocutions +allogamies +allogamous +allogamy +allogeneic +allogenic +allograft +allograph +allographic +allomerism +allomerous +allometric +allometry +allomorph +allomorphic +allomorphism +allomorphs +allonge +allonges +allonym +allonymous +allonymously +allonyms +allopath +allopathic +allopathically +allopathies +allopathist +allopathists +allopaths +allopathy +allopatric +allopatrically +allopatry +allophane +allophone +allophones +allophonic +allopolyploid +allopolyploidy +allopurinol +allosteric +allosterically +allostery +allot +allotetraploid +allotetraploidy +allotment +allotments +allotransplant +allotransplantation +allotransplanted +allotransplanting +allotransplants +allotrope +allotropes +allotropic +allotropical +allotropically +allotropy +allots +allotted +allottee +allottees +allotter +allotters +allotting +allotype +allotypes +allotypic +allotypically +allotypy +allover +allovers +allow +allowable +allowably +allowance +allowanced +allowances +allowancing +allowed +allowedly +allowing +allows +alloxan +alloxans +alloy +alloyed +alloying +alloys +allseed +allseeds +allspice +allude +alluded +alludes +alluding +allure +allured +allurement +allurements +allurer +allurers +allures +alluring +alluringly +allusion +allusions +allusive +allusively +allusiveness +alluvia +alluvial +alluvion +alluvium +alluviums +ally +allying +allyl +allylic +allyls +alma +almagest +almagests +almanac +almanacs +almandine +almandines +almandite +almandites +almeria +almightily +almightiness +almighty +almond +almonds +almoner +almoners +almost +alms +almsgiver +almsgivers +almsgiving +almshouse +almshouses +almsman +almsmen +alnico +alocasia +aloe +aloes +aloetic +aloft +alogical +alogically +alogicalness +aloha +aloin +aloins +alone +aloneness +along +alongshore +alongside +aloof +aloofly +aloofness +alopecia +alopecias +alopecic +aloud +alow +alp +alpaca +alpacas +alpenglow +alpenhorn +alpenhorns +alpenstock +alpenstocks +alpestrine +alpha +alphabet +alphabetic +alphabetical +alphabetically +alphabetization +alphabetizations +alphabetize +alphabetized +alphabetizer +alphabetizers +alphabetizes +alphabetizing +alphabets +alphameric +alphanumeric +alphanumerical +alphanumerically +alphanumerics +alphas +alpheus +alphorn +alphorns +alpine +alpinism +alpinist +alpinists +alps +already +alright +alsace +alsatian +alsatians +alsike +also +alstroemeria +alt +altai +altaic +altair +altamira +altar +altarpiece +altarpieces +altars +altazimuth +altazimuths +alter +alterability +alterable +alterableness +alterably +alteration +alterations +alterative +altercate +altercated +altercates +altercating +altercation +altercations +altered +alterer +alterers +altering +alternaria +alternate +alternated +alternately +alternateness +alternates +alternating +alternation +alternations +alternative +alternatively +alternativeness +alternatives +alternator +alternators +alters +althea +altho +althorn +althorns +although +altimeter +altimeters +altimetric +altimetry +altiplano +altiplanos +altitude +altitudes +altitudinal +altitudinous +altnaharra +alto +altocumuli +altocumulus +altogether +altoona +altos +altostratus +altricial +altruism +altruist +altruistic +altruistically +altruists +alts +alula +alulae +alular +alum +alumina +aluminas +aluminate +aluminiferous +aluminium +aluminize +aluminized +aluminizes +aluminizing +aluminosilicate +aluminous +aluminum +aluminums +alumna +alumnae +alumni +alumnus +alumroot +alumroots +alunite +alunites +alvarez +alveolar +alveolarly +alveolars +alveolate +alveolation +alveoli +alveolus +alway +always +alyssum +alyssums +alzheimer +alzheimer's +am +ama +amah +amahs +amain +amalfi +amalgam +amalgamate +amalgamated +amalgamates +amalgamating +amalgamation +amalgamations +amalgamative +amalgamator +amalgamators +amalgams +amanda +amandine +amanita +amanitas +amantadine +amanuenses +amanuensis +amaranth +amaranthine +amaranths +amarelle +amarelles +amaretto +amarettos +amarillo +amarna +amaryllis +amaryllises +amas +amass +amassable +amassed +amasser +amassers +amasses +amassing +amassment +amassments +amateur +amateurish +amateurishly +amateurishness +amateurism +amateurs +amative +amatively +amativeness +amatol +amatols +amatory +amaurosis +amaurotic +amaze +amazed +amazedly +amazedness +amazement +amazes +amazing +amazingly +amazon +amazonia +amazonian +amazonite +amazons +ambage +ambages +ambagious +ambarella +ambassador +ambassadorial +ambassadors +ambassadorship +ambassadorships +ambassadress +ambassadresses +ambeer +ambeers +amber +ambergris +amberjack +ambiance +ambiances +ambidexterity +ambidextrous +ambidextrously +ambience +ambiences +ambient +ambiguities +ambiguity +ambiguous +ambiguously +ambiguousness +ambipolar +ambisexual +ambisexuality +ambit +ambition +ambitionless +ambitions +ambitious +ambitiously +ambitiousness +ambits +ambivalence +ambivalent +ambivalently +ambiversion +ambivert +ambiverts +amble +ambled +ambler +amblers +ambles +ambling +amblygonite +amblyopia +amblyopic +ambo +amboina +amboinas +ambos +amboyna +amboynas +ambries +ambrose +ambrosia +ambrosial +ambrosially +ambrosian +ambrosias +ambrotype +ambry +ambsace +ambsaces +ambulacra +ambulacral +ambulacrum +ambulance +ambulances +ambulant +ambulate +ambulated +ambulates +ambulating +ambulation +ambulations +ambulatories +ambulatorily +ambulatory +ambuscade +ambuscaded +ambuscader +ambuscades +ambuscading +ambush +ambushed +ambusher +ambushers +ambushes +ambushing +ambushment +ameba +amebas +amebiasis +amebic +ameboid +ameer +ameers +ameliorate +ameliorated +ameliorates +ameliorating +amelioration +ameliorations +ameliorative +ameliorator +ameliorators +amelioratory +amen +amenability +amenable +amenableness +amenably +amend +amendable +amendatory +amended +amender +amenders +amending +amendment +amendments +amends +amenhotep +amenities +amenity +amenophis +amenorrhea +amenorrheic +amensalism +ament +amentaceous +amentia +amentias +amentiferous +aments +amerasian +amerasians +amerce +amerceable +amerced +amercement +amercements +amerces +amerciable +amercing +america +american +americana +americanism +americanisms +americanist +americanists +americanization +americanize +americanized +americanizes +americanizing +americanness +americans +americas +americium +amerind +amerindian +amerindians +amerinds +ames +ameslan +amethopterin +amethyst +amethystine +amethysts +ametropia +ametropic +amharic +amherst +ami +amiability +amiable +amiableness +amiably +amianthus +amicability +amicable +amicableness +amicably +amice +amices +amici +amicus +amid +amidase +amidases +amide +amides +amidic +amido +amidol +amidols +amidships +amidst +amiens +amigo +amigos +amine +amines +amino +aminoacidemia +aminoaciduria +aminobenzoic +aminobutyric +aminopeptidase +aminopeptidases +aminophenol +aminophylline +aminopterin +aminopyrine +aminopyrines +aminosalicylic +aminotransferase +amir +amirs +amish +amiss +amities +amitoses +amitosis +amitotic +amitotically +amitriptyline +amitrole +amitroles +amity +ammeter +ammeters +ammine +ammines +ammino +ammo +ammonia +ammoniac +ammoniacal +ammoniate +ammoniated +ammoniates +ammoniating +ammoniation +ammonification +ammonified +ammonifier +ammonifies +ammonify +ammonifying +ammonite +ammonites +ammonitic +ammonium +ammonoid +ammonoids +ammunition +ammunitions +amnesia +amnesiac +amnesiacs +amnesic +amnesics +amnestic +amnestied +amnesties +amnesty +amnestying +amnia +amniocenteses +amniocentesis +amniographies +amniography +amnion +amnions +amnioscope +amnioscopies +amnioscopy +amniote +amniotes +amniotic +amobarbital +amoeba +amoebae +amoebaean +amoebas +amoebiasis +amoebic +amoebocyte +amoeboid +amok +amoks +amole +amoles +among +amongst +amontillado +amontillados +amor +amoral +amoralism +amorality +amorally +amore +amoretti +amoretto +amorettos +amorist +amoristic +amorists +amorous +amorously +amorousness +amorphism +amorphous +amorphously +amorphousness +amort +amortizable +amortization +amortizations +amortize +amortized +amortizes +amortizing +amos +amosite +amosites +amount +amounted +amounting +amounts +amour +amours +amoxicillin +amp +amperage +amperages +ampere +amperes +ampersand +ampersands +amphetamine +amphetamines +amphiarthroses +amphiarthrosis +amphibia +amphibian +amphibians +amphibiotic +amphibious +amphibiously +amphibiousness +amphibole +amphiboles +amphibolic +amphibolite +amphibolitic +amphibologies +amphibology +amphibolous +amphibrach +amphictyonic +amphictyonies +amphictyony +amphidiploid +amphidiploidy +amphimacer +amphimictic +amphimixes +amphimixis +amphion +amphioxus +amphipathic +amphiploid +amphiploids +amphiploidy +amphipod +amphipods +amphiprostyle +amphisbaena +amphisbaenic +amphistylar +amphitheater +amphitheaters +amphitheatric +amphitheatrical +amphitheatrically +amphithecia +amphithecium +amphitrite +amphitropous +amphitryon +amphora +amphorae +amphoral +amphoras +amphoteric +ampicillin +ample +ampleness +ampler +amplest +amplexicaul +amplexus +amplidyne +amplidynes +amplification +amplifications +amplified +amplifier +amplifiers +amplifies +amplify +amplifying +amplitude +amplitudes +amply +ampoule +ampoules +amps +ampul +ampule +ampules +ampulla +ampullae +ampullar +ampuls +amputate +amputated +amputates +amputating +amputation +amputations +amputator +amputators +amputee +amputees +ampère +amreeta +amreetas +amrita +amritas +amritsar +amsterdam +amtrac +amtrack +amtracks +amtracs +amtrak +amuck +amulet +amulets +amun +amundsen +amusable +amuse +amused +amusedly +amusement +amusements +amuser +amusers +amuses +amusing +amusingly +amusingness +amusive +amygdala +amygdalae +amygdale +amygdales +amygdalin +amygdaline +amygdaloid +amygdaloidal +amygdule +amygdules +amyl +amylaceous +amylase +amylases +amyloid +amyloidosis +amyloids +amylolysis +amylolytic +amylopsin +amylose +amyloses +amyls +amylum +amylums +amyotonia +an +ana +anabaena +anabaenas +anabaptism +anabaptist +anabaptists +anabas +anabases +anabasis +anabatic +anabiosis +anabiotic +anabolic +anabolism +anachronic +anachronism +anachronisms +anachronistic +anachronistically +anachronous +anachronously +anaclisis +anaclitic +anacolutha +anacoluthic +anacoluthically +anacoluthon +anacoluthons +anaconda +anacondas +anacreon +anacreontic +anacruses +anacrusis +anadem +anadems +anadiploses +anadiplosis +anadromous +anaemia +anaemias +anaerobe +anaerobes +anaerobic +anaerobically +anaerobiosis +anaerobiotic +anaesthesia +anaesthesiology +anaesthetic +anaesthetics +anaesthetist +anaesthetists +anaesthetization +anaesthetizations +anaesthetize +anaesthetized +anaesthetizes +anaesthetizing +anagenesis +anaglyph +anaglyphic +anaglyphs +anagoge +anagoges +anagogic +anagogically +anagogies +anagogy +anagram +anagrammatic +anagrammatical +anagrammatically +anagrammatization +anagrammatize +anagrammatized +anagrammatizes +anagrammatizing +anagrams +anaheim +anal +analcime +analcimes +analcimic +analcite +analcites +analecta +analectic +analects +analemma +analemmas +analeptic +analgesia +analgesic +analgesics +analgetic +analities +anality +anally +analog +analogic +analogical +analogically +analogies +analogist +analogize +analogized +analogizes +analogizing +analogous +analogously +analogousness +analogs +analogue +analogues +analogy +analphabet +analphabetic +analphabetics +analphabetism +analphabets +analysand +analysands +analyses +analysis +analyst +analysts +analytic +analytical +analytically +analyticities +analyticity +analytics +analyzability +analyzable +analyzation +analyze +analyzed +analyzer +analyzers +analyzes +analyzing +anamneses +anamnesis +anamnestic +anamnestically +anamorphic +anamorphoses +anamorphosis +anapaest +anapaests +anapest +anapestic +anapests +anaphase +anaphases +anaphasic +anaphor +anaphora +anaphoras +anaphoric +anaphorically +anaphors +anaphrodisia +anaphrodisiac +anaphylactic +anaphylactically +anaphylactoid +anaphylaxes +anaphylaxis +anaplasia +anaplasmoses +anaplasmosis +anaplastic +anapsid +anapsids +anarch +anarchic +anarchical +anarchically +anarchies +anarchism +anarchist +anarchistic +anarchists +anarcho +anarchs +anarchy +anarthria +anarthric +anarthrous +anas +anasarca +anasarcas +anasarcous +anasazi +anastasia +anastigmat +anastigmatic +anastomose +anastomosed +anastomoses +anastomosing +anastomosis +anastomotic +anastrophe +anatase +anatases +anathema +anathemas +anathematization +anathematize +anathematized +anathematizes +anathematizing +anatolia +anatolian +anatolians +anatomic +anatomical +anatomically +anatomies +anatomist +anatomists +anatomization +anatomize +anatomized +anatomizes +anatomizing +anatomy +anatropous +anatto +anattos +anaxagoras +anaximander +ancestor +ancestors +ancestral +ancestrally +ancestress +ancestresses +ancestries +ancestry +anchor +anchorage +anchorages +anchored +anchoress +anchoresses +anchoret +anchorets +anchoring +anchorite +anchorites +anchoritic +anchoritically +anchorless +anchorman +anchormen +anchorperson +anchorpersons +anchors +anchorwoman +anchorwomen +anchovies +anchovy +ancien +anciens +ancient +anciently +ancientness +ancientry +ancients +ancilla +ancillae +ancillaries +ancillary +ancon +ancona +ancones +ancress +ancresses +ancylostomiasis +and +andalucía +andalusia +andalusian +andalusians +andalusite +andaman +andamanese +andamans +andante +andantes +andantino +andantinos +andean +andes +andesite +andesites +andesitic +andhra +andiron +andirons +andorra +andorran +andorrans +andouille +andradite +andrew +andrews +androcles +androecia +androecial +androecium +androgen +androgenic +androgenization +androgenize +androgenized +androgenizes +androgenizing +androgens +androgyne +androgynous +androgynously +androgyny +android +androids +andromache +andromeda +andronicus +androsterone +andré +ands +anecdota +anecdotage +anecdotal +anecdotalist +anecdotalists +anecdotally +anecdote +anecdotes +anecdotic +anecdotical +anecdotically +anecdotist +anecdotists +anechoic +anemia +anemias +anemic +anemically +anemics +anemochory +anemograph +anemography +anemometer +anemometers +anemometrical +anemometry +anemone +anemones +anemophilous +anencephalic +anencephalies +anencephaly +anent +aneroid +anesthesia +anesthesias +anesthesiologist +anesthesiologists +anesthesiology +anesthetic +anesthetically +anesthetics +anesthetist +anesthetists +anesthetization +anesthetize +anesthetized +anesthetizes +anesthetizing +anestrus +anestruses +aneuploid +aneuploidy +aneurism +aneurisms +aneurysm +aneurysmal +aneurysms +anew +anfractuosities +anfractuosity +anfractuous +anga +angaria +angarias +angaries +angary +angel +angela +angeleno +angelenos +angeles +angelfish +angelfishes +angelic +angelica +angelical +angelically +angelicas +angelico +angelina +angelologist +angelologists +angelology +angels +angelus +angeluses +anger +angered +angering +angerless +angers +angevin +angevins +angina +anginal +anginose +angiocardiographic +angiocardiography +angiogenesis +angiogram +angiograms +angiographic +angiography +angiology +angioma +angiomas +angiomata +angiomatous +angiopathies +angiopathy +angioplasties +angioplasty +angiosarcoma +angiosperm +angiosperms +angiotensin +angkor +angle +angled +angler +anglerfish +anglerfishes +anglers +angles +anglesite +angleworm +angleworms +anglia +anglian +anglians +anglican +anglicanism +anglicans +anglicanus +anglice +anglicism +anglicisms +anglicist +anglicization +anglicizations +anglicize +anglicized +anglicizes +anglicizing +angling +anglings +anglo +anglophil +anglophile +anglophiles +anglophilia +anglophiliac +anglophilic +anglophobe +anglophobes +anglophobia +anglophobic +anglophone +anglophonic +anglos +angola +angolan +angolans +angora +angoras +angostura +angoulême +angrier +angriest +angrily +angriness +angry +angst +angstrom +angstroms +anguilla +anguillan +anguillans +anguish +anguished +anguishes +anguishing +angular +angularities +angularity +angularly +angularness +angulate +angulated +angulately +angulates +angulating +angulation +angus +anguses +anhinga +anhingas +anhydride +anhydrides +anhydrite +anhydrous +anhydrously +ani +anil +anile +anilin +aniline +anilines +anilingus +anilins +anility +anils +anima +animadversion +animadversions +animadvert +animadverted +animadverting +animadverts +animal +animalcula +animalcule +animalcules +animalculum +animalism +animalist +animalistic +animality +animalization +animalize +animalized +animalizes +animalizing +animallike +animally +animals +animas +animate +animated +animatedly +animately +animateness +animates +animatic +animating +animation +animations +animato +animator +animators +animis +animism +animist +animistic +animists +animo +animosities +animosity +animus +animé +anion +anionic +anionically +anions +aniracetam +anis +anise +aniseed +aniseeds +aniseikonia +aniseikonic +anises +anisette +anisettes +anisogamete +anisogamic +anisogamy +anisometric +anisometropia +anisometropic +anisotropic +anisotropically +anisotropism +anisotropy +anjou +ankara +ankerite +ankerites +ankh +ankhs +ankle +anklebone +anklebones +ankles +anklet +anklets +ankylose +ankylosed +ankyloses +ankylosing +ankylosis +ankylotic +anlace +anlaces +anlage +anlagen +anlages +ann +anna +annalist +annalistic +annalists +annals +annan +annapolis +annapurna +annates +annatto +annattos +anne +anneal +annealed +annealing +anneals +annelid +annelidan +annelidans +annelids +annex +annexation +annexational +annexationism +annexationist +annexationists +annexations +annexed +annexes +annexing +annie +annihilability +annihilable +annihilate +annihilated +annihilates +annihilating +annihilation +annihilations +annihilative +annihilator +annihilators +annihilatory +anniversaries +anniversary +anno +annotate +annotated +annotates +annotating +annotation +annotations +annotative +annotator +annotators +announce +announced +announcement +announcements +announcer +announcers +announces +announcing +annoy +annoyance +annoyances +annoyed +annoyer +annoyers +annoying +annoyingly +annoys +annual +annualize +annualized +annualizes +annualizing +annually +annuals +annuitant +annuitants +annuities +annuity +annul +annular +annulate +annulated +annulation +annulet +annulets +annuli +annulled +annulling +annulment +annulments +annuls +annulus +annuluses +annum +annunciate +annunciated +annunciates +annunciating +annunciation +annunciations +annunciator +annunciators +annunciatory +annus +anoa +anoas +anodal +anodally +anode +anodes +anodic +anodically +anodization +anodize +anodized +anodizes +anodizing +anodyne +anodynes +anoint +anointed +anointer +anointers +anointing +anointment +anointments +anoints +anole +anoles +anomalies +anomalistic +anomalistical +anomalistically +anomalous +anomalously +anomalousness +anomaly +anomic +anomie +anomy +anon +anonym +anonymities +anonymity +anonymous +anonymously +anonymousness +anonyms +anopheles +anopheline +anorak +anoraks +anorectic +anorectics +anoretic +anorexia +anorexic +anorexics +anorexigenic +anorthic +anorthite +anorthitic +anorthosite +anosmia +anosmias +anosmic +anosognosia +anosognosic +anosognosics +another +anouilh +anovulant +anovulation +anovulatory +anoxemia +anoxemias +anoxemic +anoxia +anoxic +ansate +anschluss +anselm +anserine +anson +answer +answerability +answerable +answerableness +answerably +answerback +answered +answerer +answerers +answering +answers +ant +anta +antacid +antacids +antae +antaean +antagonism +antagonisms +antagonist +antagonistic +antagonistically +antagonists +antagonize +antagonized +antagonizes +antagonizing +antarctic +antarctica +antares +antas +ante +anteater +anteaters +antebellum +antecede +anteceded +antecedence +antecedent +antecedently +antecedents +antecedes +anteceding +antecessor +antecessors +antechamber +antechambers +antechoir +antechoirs +anted +antedate +antedated +antedates +antedating +antediluvian +antediluvians +anteed +antefix +antefixa +antefixal +antefixes +anteing +antelope +antelopes +antemeridian +antemortem +antenatal +antenatally +antenna +antennae +antennal +antennas +antennule +antependia +antependium +antepenult +antepenultima +antepenultimate +antepenultimates +antepenults +anterior +anteriorly +anteroom +anterooms +antes +anthelia +anthelion +anthelmintic +anthelmintics +anthem +anthemia +anthemion +anthems +anther +antheridia +antheridium +antherozoid +anthers +anthesis +anthill +anthills +anthocyanin +anthological +anthologies +anthologist +anthologists +anthologize +anthologized +anthologizer +anthologizers +anthologizes +anthologizing +anthology +anthony +anthozoan +anthozoic +anthracene +anthraces +anthracis +anthracite +anthracites +anthracitic +anthracnose +anthracosis +anthrax +anthropic +anthropical +anthropocentric +anthropocentrically +anthropocentricity +anthropocentrism +anthropogenesis +anthropogenic +anthropoid +anthropoidal +anthropoids +anthropologic +anthropological +anthropologically +anthropologist +anthropologists +anthropology +anthropometric +anthropometrical +anthropometrically +anthropometrist +anthropometry +anthropomorph +anthropomorphic +anthropomorphically +anthropomorphism +anthropomorphist +anthropomorphists +anthropomorphization +anthropomorphize +anthropomorphized +anthropomorphizes +anthropomorphizing +anthropomorphous +anthropomorphs +anthropopathism +anthropophagi +anthropophagic +anthropophagous +anthropophagus +anthropophagy +anthroposophical +anthroposophist +anthroposophy +anthurium +anti +antiabortion +antiabortionist +antiabortionists +antiacademic +antiadministration +antiaggression +antiaging +antiaircraft +antialcohol +antialcoholism +antialien +antiallergenic +antiallergic +antianemia +antianxiety +antiapartheid +antiaphrodisiac +antiaristocratic +antiarrhythmic +antiarthritic +antiarthritis +antiassimilation +antiasthma +antiatom +antiatoms +antiauthoritarian +antiauthoritarianism +antiauthority +antibacklash +antibacterial +antibaryon +antibes +antibias +antibillboard +antibioses +antibiosis +antibiotic +antibiotically +antibiotics +antiblack +antiblackism +antibodies +antibody +antiboss +antibourgeois +antiboycott +antibug +antibureaucratic +antiburglar +antiburglary +antibusiness +antibusing +antic +anticaking +antically +anticancer +anticancerous +anticapitalism +anticapitalist +anticapitalists +anticarcinogen +anticarcinogenic +anticaries +anticatalyst +anticathode +anticellulite +anticensorship +antichlor +antichloristic +anticholesterol +anticholinergic +anticholinesterase +antichrist +antichrists +antichurch +anticigarette +anticipant +anticipants +anticipatable +anticipate +anticipated +anticipates +anticipating +anticipation +anticipations +anticipative +anticipatively +anticipator +anticipators +anticipatory +anticity +anticlassical +anticlerical +anticlericalism +anticlimactic +anticlimactical +anticlimactically +anticlimax +anticlimaxes +anticlinal +anticline +anticlines +anticling +anticlockwise +anticlotting +anticoagulant +anticoagulants +anticoagulation +anticodon +anticold +anticollision +anticolonial +anticolonialism +anticolonialist +anticolonialists +anticommercial +anticommercialism +anticommunism +anticommunist +anticommunists +anticompetitive +anticonglomerate +anticonservation +anticonservationist +anticonservationists +anticonsumer +anticonventional +anticonvulsant +anticonvulsive +anticorporate +anticorrosion +anticorrosive +anticorrosives +anticorruption +anticounterfeiting +anticrack +anticreative +anticrime +anticruelty +antics +anticult +anticultural +anticyclone +anticyclones +anticyclonic +antidandruff +antidefamation +antidemocratic +antidepressant +antidepressants +antidepression +antidepressive +antiderivative +antiderivatives +antidesegregation +antidesertification +antidesiccant +antideuteron +antidevelopment +antidiabetic +antidiarrheal +antidilution +antidiscrimination +antidisestablishmentarian +antidisestablishmentarianism +antidogmatic +antidotal +antidotally +antidote +antidotes +antidraft +antidumping +antieconomic +antieducational +antiegalitarian +antielectron +antielectrons +antielite +antielitism +antielitist +antielitists +antiemetic +antientropic +antienvironmental +antienzymatic +antienzyme +antienzymic +antiepilepsy +antiepileptic +antierotic +antiestablishment +antiestrogen +antietam +antievolution +antievolutionary +antievolutionism +antievolutionist +antievolutionists +antifamily +antifascism +antifascist +antifascists +antifashion +antifashionable +antifatigue +antifebrile +antifederalism +antifederalist +antifemale +antifeminine +antifeminism +antifeminist +antifeminists +antifertility +antifilibuster +antiflu +antifluoridationist +antifoam +antifoaming +antifogging +antiforeclosure +antiforeign +antiforeigner +antiformalist +antiformalists +antifouling +antifraud +antifreeze +antifreezes +antifriction +antifundamentalist +antifundamentalists +antifungal +antifur +antigalaxy +antigambling +antigay +antigen +antigene +antigenes +antigenic +antigenically +antigenicity +antigens +antiglare +antiglobulin +antigone +antigovernment +antigravity +antigreenmail +antigrowth +antigua +antiguan +antiguans +antiguerrilla +antigun +antihelium +antihemophilic +antihero +antiheroes +antiheroic +antiheroine +antiheroism +antiherpes +antihierarchical +antihijack +antihistamine +antihistamines +antihistaminic +antihistorical +antihomosexual +antihuman +antihumanism +antihumanistic +antihumanitarian +antihunter +antihunting +antihydrogen +antihypertensive +antihypertensives +antihysteric +antijam +antijamming +antikickback +antiknock +antiknocks +antilabor +antileak +antileprosy +antilepton +antileukemic +antiliberal +antiliberalism +antilibertarian +antiliquor +antiliterate +antilitter +antilittering +antilles +antilock +antilog +antilogarithm +antilogarithmic +antilogarithms +antilogical +antilogies +antilogs +antilogy +antilynching +antimacassar +antimacassars +antimacho +antimagnetic +antimalaria +antimalarial +antimalarials +antimale +antiman +antimanagement +antimarijuana +antimarket +antimaterialism +antimaterialist +antimaterialists +antimatter +antimechanist +antimechanists +antimere +antimeres +antimerger +antimeric +antimetabolic +antimetabolite +antimetaphysical +antimicrobial +antimilitarism +antimilitarist +antimilitarists +antimilitary +antimiscegenation +antimissile +antimitotic +antimodern +antimodernist +antimodernists +antimonarchical +antimonarchist +antimonarchists +antimonial +antimonopolist +antimonopolists +antimonopoly +antimony +antimosquito +antimusical +antinarrative +antinational +antinationalist +antinationalists +antinatural +antinature +antinausea +antineoplastic +antinepotism +antineutrino +antineutrinos +antineutron +antineutrons +anting +antings +antinodal +antinode +antinodes +antinoise +antinome +antinomian +antinomianism +antinomians +antinomic +antinomies +antinomy +antinovel +antinovelist +antinuclear +antinucleon +antinucleons +antiobesity +antiobscenity +antioch +antiochus +antiorganization +antioxidant +antioxidants +antipapal +antiparasitic +antiparticle +antiparticles +antiparty +antipasti +antipasto +antipastos +antipathetic +antipathetical +antipathetically +antipathies +antipathy +antiperiodic +antipersonnel +antiperspirant +antiperspirants +antipesticide +antiphlogistic +antiphon +antiphonal +antiphonally +antiphonaries +antiphonary +antiphonies +antiphons +antiphony +antiphrases +antiphrasis +antipiracy +antiplague +antiplaque +antipleasure +antipneumococcal +antipoaching +antipodal +antipode +antipodean +antipodeans +antipodes +antipoetic +antipolice +antipolitical +antipolitics +antipollution +antipollutionist +antipope +antipopes +antipopular +antiporn +antipornographic +antipornography +antipot +antipoverty +antipredator +antipress +antiprofiteering +antiprogressive +antiprostitution +antiproton +antiprotons +antipruritic +antipsychotic +antipsychotics +antipyresis +antipyretic +antipyretics +antipyrine +antiquarian +antiquarianism +antiquarians +antiquaries +antiquark +antiquary +antiquate +antiquated +antiquatedness +antiquates +antiquating +antiquation +antique +antiqued +antiquely +antiqueness +antiquer +antiquers +antiques +antiquing +antiquities +antiquity +antirabies +antirachitic +antiracism +antiracist +antiracists +antiracketeering +antiradar +antiradical +antiradicalism +antirape +antirational +antirationalism +antirationalist +antirationalists +antirationality +antirealism +antirealist +antirealists +antirecession +antirecessionary +antired +antireductionism +antireductionist +antireductionists +antireflection +antireflective +antireform +antiregulatory +antireligion +antireligious +antirevolutionary +antirheumatic +antirheumatics +antiriot +antiritualism +antirock +antiroll +antiromantic +antiromanticism +antiroyalist +antiroyalists +antirrhinum +antirrhinums +antirust +antis +antisatellite +antischizophrenia +antischizophrenic +antiscience +antiscientific +antiscorbutic +antisecrecy +antisecretory +antisegregation +antiseizure +antisentimental +antiseparatist +antiseparatists +antisepses +antisepsis +antiseptic +antiseptically +antiseptics +antisera +antiserum +antiserums +antisex +antisexist +antisexists +antisexual +antisexuality +antishark +antiship +antishock +antishoplifting +antiskid +antislavery +antisleep +antislip +antismog +antismoke +antismoker +antismoking +antismuggling +antismut +antisnob +antisocial +antisocialist +antisocialists +antisocially +antispasmodic +antispasmodics +antispeculation +antispeculative +antispending +antistate +antistatic +antisthenes +antistick +antistory +antistress +antistrike +antistrophe +antistrophes +antistrophic +antistrophically +antistudent +antisubmarine +antisubsidy +antisubversion +antisubversive +antisuicide +antisymmetric +antisyphilitic +antitakeover +antitank +antitarnish +antitax +antitechnological +antitechnology +antiterrorism +antiterrorist +antiterrorists +antitheft +antitheoretical +antitheses +antithesis +antithetic +antithetical +antithetically +antithyroid +antitobacco +antitotalitarian +antitoxic +antitoxin +antitoxins +antitrade +antitrades +antitraditional +antitrust +antitruster +antitrusters +antitubercular +antituberculosis +antituberculous +antitumor +antitumoral +antitussive +antitype +antitypes +antityphoid +antitypical +antiulcer +antiunemployment +antiunion +antiuniversity +antiurban +antivenin +antivenins +antiviolence +antiviral +antivirus +antivitamin +antivivisection +antivivisectionist +antivivisectionists +antiwar +antiwear +antiwelfare +antiwhaling +antiwoman +antiwrinkle +antler +antlered +antlers +antoinette +antonine +antonines +antoninus +antonio +antonomasia +antony +antonym +antonymic +antonymous +antonyms +antonymy +antra +antral +antre +antres +antrim +antrorse +antrorsely +antrum +ants +antsier +antsiest +antsy +antwerp +anubis +anuran +anurans +anuresis +anuretic +anuria +anurias +anuric +anurous +anus +anuses +anvil +anvils +anxieties +anxiety +anxious +anxiously +anxiousness +any +anybody +anybody's +anyhow +anymore +anyone +anyone's +anyplace +anything +anytime +anyway +anyways +anywhere +anywise +anzio +aorist +aoristic +aoristically +aorists +aorta +aortae +aortal +aortas +aortic +aortographic +aortography +aosta +aoudad +aoudads +apace +apache +apachean +apaches +apanage +apanages +aparejo +aparejos +apart +apartheid +apartment +apartmental +apartments +apartness +apatetic +apathetic +apathetical +apathetically +apathy +apatite +apatites +ape +apeak +aped +apelike +apennine +apennines +aper +aperient +aperients +aperiodic +aperiodically +aperiodicity +aperitif +aperitifs +apertural +aperture +apertures +aperçu +aperçus +apes +apetalous +apetaly +apex +apexes +aphaereses +aphaeresis +aphaeretic +aphagia +aphagias +aphanite +aphanites +aphanitic +aphasia +aphasiac +aphasiacs +aphasias +aphasic +aphasics +aphelia +aphelion +apheresis +apheses +aphesis +aphetic +aphetically +aphid +aphides +aphidian +aphidians +aphids +aphis +aphonia +aphonias +aphonic +aphorism +aphorisms +aphorist +aphoristic +aphoristically +aphorists +aphorize +aphorized +aphorizes +aphorizing +aphotic +aphrodisiac +aphrodisiacal +aphrodisiacs +aphrodite +aphyllies +aphyllous +aphylly +apian +apiarian +apiaries +apiarist +apiarists +apiary +apical +apically +apices +apiculate +apicultural +apiculture +apiculturist +apiece +aping +apio +apios +apis +apish +apishly +apishness +apivorous +aplacental +aplanatic +aplasia +aplasias +aplastic +aplenty +aplite +aplites +aplitic +aplomb +apnea +apneas +apneic +apnoea +apnoeas +apocalypse +apocalypses +apocalyptic +apocalyptical +apocalyptically +apocalypticism +apocalyptism +apocalyptist +apocalyptists +apocarpies +apocarpous +apocarpy +apochromatic +apocope +apocopes +apocrine +apocrypha +apocryphal +apocryphally +apocryphalness +apodal +apodeictic +apodictic +apodictically +apodoses +apodosis +apodous +apoenzyme +apogamic +apogamies +apogamous +apogamy +apogean +apogee +apogees +apolitical +apolitically +apollinaris +apollo +apollonian +apollos +apollyon +apologetic +apologetically +apologetics +apologia +apologias +apologies +apologist +apologists +apologize +apologized +apologizer +apologizers +apologizes +apologizing +apologue +apologues +apology +apolune +apolunes +apomict +apomictic +apomictically +apomicts +apomixis +apomixises +apomorphine +aponeuroses +aponeurosis +aponeurotic +apophasis +apophthegm +apophthegms +apophyge +apophyges +apophyllite +apophysate +apophyseal +apophyses +apophysis +apoplectic +apoplectically +apoplexy +aport +aposematic +aposematically +aposiopeses +aposiopesis +aposiopetic +aposporous +apospory +apostasies +apostasy +apostate +apostates +apostatize +apostatized +apostatizes +apostatizing +apostle +apostlehood +apostles +apostleship +apostleships +apostolate +apostolic +apostolicity +apostrophe +apostrophes +apostrophic +apostrophize +apostrophized +apostrophizes +apostrophizing +apothecaries +apothecary +apothecia +apothecial +apothecium +apothegm +apothegmatic +apothegmatical +apothegmatically +apothegms +apothem +apothems +apotheoses +apotheosis +apotheosize +apotheosized +apotheosizes +apotheosizing +apotropaic +apotropaically +appal +appalachia +appalachian +appalachians +appall +appalled +appalling +appallingly +appalls +appaloosa +appaloosas +appals +appanage +appanages +apparat +apparatchik +apparatchiki +apparatchiks +apparats +apparatus +apparatuses +apparel +appareled +appareling +apparelled +apparelling +apparels +apparent +apparently +apparentness +apparition +apparitional +apparitions +apparitor +apparitors +appeal +appealability +appealable +appealed +appealer +appealers +appealing +appealingly +appeals +appear +appearance +appearances +appeared +appearing +appears +appeasable +appeasably +appease +appeased +appeasement +appeasements +appeaser +appeasers +appeases +appeasing +appel +appellant +appellants +appellate +appellation +appellations +appellative +appellatively +appellee +appellees +appels +append +appendage +appendages +appendant +appendectomies +appendectomy +appended +appendices +appendicitis +appendicular +appending +appendix +appendixes +appends +apperceive +apperceived +apperceives +apperceiving +apperception +apperceptive +appertain +appertained +appertaining +appertains +appestat +appestats +appetence +appetencies +appetency +appetent +appetite +appetites +appetitive +appetizer +appetizers +appetizing +appetizingly +appian +applaud +applaudable +applaudably +applauded +applauder +applauders +applauding +applauds +applause +applauses +apple +applejack +applejacks +apples +applesauce +appliance +appliances +applicability +applicable +applicably +applicant +applicants +application +applications +applicative +applicatively +applicator +applicators +applicatory +applied +applier +appliers +applies +appliqué +appliquéd +appliquéing +appliqués +apply +applying +appoggiatura +appoint +appointed +appointee +appointees +appointing +appointive +appointment +appointments +appointor +appoints +appomattox +apportion +apportioned +apportioning +apportionment +apportionments +apportions +appose +apposed +apposes +apposing +apposite +appositely +appositeness +apposition +appositional +appositionally +appositions +appositive +appositively +appositives +appraisable +appraisal +appraisals +appraise +appraised +appraisement +appraisements +appraiser +appraisers +appraises +appraising +appraisingly +appreciable +appreciably +appreciate +appreciated +appreciates +appreciating +appreciation +appreciations +appreciative +appreciatively +appreciativeness +appreciator +appreciators +appreciatory +apprehend +apprehended +apprehending +apprehends +apprehensible +apprehensibly +apprehension +apprehensions +apprehensive +apprehensively +apprehensiveness +apprentice +apprenticed +apprentices +apprenticeship +apprenticeships +apprenticing +appressed +apprise +apprised +apprises +apprising +apprize +apprized +apprizes +apprizing +approach +approachability +approachable +approached +approaches +approaching +approbate +approbated +approbates +approbating +approbation +approbations +approbative +approbatory +appropriable +appropriate +appropriated +appropriately +appropriateness +appropriates +appropriating +appropriation +appropriations +appropriative +appropriator +appropriators +approvable +approvably +approval +approvals +approve +approved +approver +approvers +approves +approving +approvingly +approximate +approximated +approximately +approximates +approximating +approximation +approximations +approximative +approximatively +appurtenance +appurtenances +appurtenant +appétit +apractic +apraxia +apraxias +apraxic +apricot +apricots +april +aprils +apriority +apron +aproned +aproning +aprons +apropos +après +apse +apses +apsidal +apsides +apsis +apt +apteral +apterous +apteryx +apteryxes +aptitude +aptitudes +aptitudinal +aptitudinally +aptly +aptness +apulia +apyrase +apyrases +apéritif +apéritifs +aqua +aquacade +aquacades +aquacultural +aquaculture +aquaculturist +aquae +aquafortis +aqualung +aqualungs +aquamarine +aquamarines +aquanaut +aquanauts +aquaplane +aquaplaned +aquaplaner +aquaplaners +aquaplanes +aquaplaning +aquarelle +aquarellist +aquaria +aquarian +aquarians +aquarist +aquarists +aquarium +aquariums +aquarius +aquas +aquatic +aquatically +aquatics +aquatint +aquatinted +aquatinter +aquatinting +aquatintist +aquatints +aquavit +aqueduct +aqueducts +aqueous +aquiculture +aquifer +aquiferous +aquifers +aquila +aquilegia +aquiline +aquilinity +aquinas +aquitaine +aquiver +arab +arabesque +arabesques +arabia +arabian +arabians +arabic +arabicize +arabicized +arabicizes +arabicizing +arability +arabinose +arabist +arabists +arabization +arabize +arabized +arabizes +arabizing +arable +arables +arabs +araby +arachne +arachnid +arachnidan +arachnidans +arachnids +arachnoid +arachnoids +arachnophobia +aragon +aragonese +aragonite +arak +araks +aralia +aramaean +aramaic +arame +aramean +arapaho +arapahoe +arapahoes +arapahos +arapaima +arapaimas +ararat +araucanian +araucaria +arawak +arawakan +arawakans +arawaks +arbalest +arbalester +arbalests +arbalist +arbalists +arbiter +arbiters +arbitrable +arbitrage +arbitraged +arbitrager +arbitragers +arbitrages +arbitrageur +arbitrageurs +arbitraging +arbitral +arbitrament +arbitraments +arbitrarily +arbitrariness +arbitrary +arbitrate +arbitrated +arbitrates +arbitrating +arbitration +arbitrational +arbitrations +arbitrative +arbitrator +arbitrators +arbor +arboreal +arboreally +arboreous +arbores +arborescence +arborescent +arboreta +arboretum +arboretums +arboricultural +arboriculture +arboricultures +arborist +arborists +arborization +arborize +arborized +arborizes +arborizing +arbors +arborvitae +arboviral +arbovirology +arbovirus +arbutus +arbutuses +arc +arcade +arcaded +arcades +arcadia +arcadian +arcadians +arcadias +arcading +arcady +arcana +arcane +arcanum +arcanums +arccosine +arced +arch +archaean +archaeans +archaeologic +archaeological +archaeologically +archaeologist +archaeologists +archaeology +archaeopteryx +archaic +archaically +archaism +archaisms +archaist +archaistic +archaists +archaize +archaized +archaizer +archaizers +archaizes +archaizing +archangel +archangelic +archangels +archbishop +archbishopric +archbishoprics +archbishops +archconservative +archconservatives +archdeacon +archdeaconate +archdeaconries +archdeaconry +archdeacons +archdeaconship +archdiocesan +archdiocese +archdioceses +archducal +archduchess +archduchesses +archduchies +archduchy +archduke +archdukes +archean +arched +archegonia +archegonial +archegoniate +archegonium +archencephalon +archenemies +archenemy +archenteric +archenteron +archeological +archeologically +archeologist +archeologists +archeology +archeozoic +archer +archerfish +archerfishes +archeries +archers +archery +arches +archetypal +archetypally +archetype +archetypes +archetypical +archetypically +archfiend +archfiends +archidiaconal +archidiaconate +archidiaconates +archiepiscopal +archiepiscopality +archiepiscopally +archiepiscopate +archiepiscopates +archil +archils +archimandrite +archimandrites +archimedean +archimedes +archine +archines +arching +archipelagic +archipelago +archipelagoes +archipelagos +architect +architectonic +architectonically +architectonics +architects +architectural +architecturally +architecture +architectures +architrave +architraves +archival +archive +archived +archives +archiving +archivist +archivists +archivolt +archivolts +archliberal +archly +archness +archon +archons +archonship +archonships +archosaur +archosaurs +archpriest +archrival +archway +archways +arciform +arcing +arcked +arcking +arco +arcs +arcsine +arctangent +arctic +arctically +arctics +arcturus +arcuate +arcuated +arcuately +arcuation +ardeb +ardebs +ardencies +ardency +ardennes +ardent +ardently +ardor +ardors +arduous +arduously +arduousness +are +area +areal +areally +areas +areaway +areaways +areca +arecas +aren +aren't +arena +arenaceous +arenas +arenicolous +areola +areolae +areolar +areolas +areolate +areolation +areole +areoles +areopagite +areopagites +areopagitic +areopagus +ares +arete +aretes +arethusa +arethusas +argali +argalis +argent +argentic +argentiferous +argentina +argentine +argentinean +argentineans +argentines +argentinian +argentinians +argentite +argentous +argents +argil +argillaceous +argillite +argils +arginase +arginases +arginine +arginines +argive +argives +argo +argol +argols +argon +argonaut +argonauts +argos +argosies +argosy +argot +argots +arguable +arguably +argue +argued +arguer +arguers +argues +argufied +argufier +argufiers +argufies +argufy +argufying +arguing +argument +argumenta +argumentation +argumentative +argumentatively +argumentativeness +argumentive +arguments +argumentum +argus +arguses +argyle +argyles +argyll +argylls +argyrol +arhat +arhats +arhatship +aria +ariadne +arian +arianism +arians +arias +ariboflavinosis +arid +aridity +aridness +ariel +ariels +aries +arietta +ariettas +ariette +ariettes +aright +arikara +arikaras +aril +ariled +arillate +arils +arimathaea +arimathea +arioso +ariosos +ariosto +arise +arisen +arises +arising +arista +aristae +aristarchus +aristas +aristate +aristides +aristocracies +aristocracy +aristocrat +aristocratic +aristocratical +aristocratically +aristocrats +aristophanes +aristophanic +aristotelean +aristotelian +aristotelianism +aristotelians +aristotle +arithmetic +arithmetical +arithmetically +arithmetician +arithmeticians +arithmetics +arizona +arizonan +arizonans +arizonian +arizonians +ark +arkansan +arkansans +arkansas +arks +arkwright +arles +arm +armada +armadas +armadillo +armadillos +armageddon +armagh +armament +armamentaria +armamentarium +armamentariums +armaments +armature +armatures +armband +armbands +armchair +armchairs +armed +armenia +armenian +armenians +armentières +armer +armers +armet +armets +armful +armfuls +armhole +armholes +armies +armiger +armigers +arming +arminian +arminianism +arminians +arminius +armistice +armistices +armless +armlet +armlets +armlike +armload +armloads +armoire +armoires +armor +armored +armorer +armorers +armorial +armorially +armorials +armories +armoring +armorless +armors +armory +armpit +armpits +armrest +armrests +arms +armsful +armstrong +army +armyworm +armyworms +arnatto +arnattos +arne +arnheim +arnhem +arnica +arnicas +arno +arnold +aroid +aroids +aroint +arointed +arointing +aroints +aroma +aromas +aromatherapies +aromatherapist +aromatherapists +aromatherapy +aromatic +aromatically +aromaticity +aromaticness +aromatics +aromatization +aromatize +aromatized +aromatizes +aromatizing +arose +around +arousal +arousals +arouse +aroused +arouses +arousing +arpanet +arpeggio +arpeggios +arpent +arpents +arquebus +arquebuses +arracacha +arrack +arracks +arraign +arraigned +arraigner +arraigning +arraignment +arraignments +arraigns +arrange +arranged +arrangement +arrangements +arranger +arrangers +arranges +arranging +arrant +arrantly +arras +array +arrayal +arrayals +arrayed +arrayer +arrayers +arraying +arrays +arrear +arrearage +arrears +arrest +arrestant +arrestants +arrested +arrestee +arrestees +arrester +arresters +arresting +arrestingly +arrestment +arrestments +arrestor +arrestors +arrests +arrhythmia +arrhythmias +arrhythmic +arrhythmically +arriba +arris +arrises +arrival +arrivals +arrive +arrived +arrivederci +arriver +arrivers +arrives +arriving +arriviste +arrière +arroba +arrobas +arrogance +arrogant +arrogantly +arrogate +arrogated +arrogates +arrogating +arrogation +arrogations +arrogative +arrogator +arrondissement +arrondissements +arrow +arrowed +arrowhead +arrowheads +arrowing +arrowroot +arrowroots +arrows +arrowwood +arrowworm +arrowworms +arrowy +arroyo +arroyos +arse +arsenal +arsenals +arsenate +arsenates +arsenic +arsenical +arsenide +arsenides +arsenious +arsenite +arsenites +arsenopyrite +arses +arshin +arshins +arsine +arsines +arsis +arson +arsonist +arsonists +arsonous +arsons +arsphenamine +art +artaxerxes +arte +artel +artels +artemis +artemisia +arterial +arterialization +arterialize +arterialized +arterializes +arterializing +arterially +arterials +arteries +arteriogram +arteriograms +arteriographic +arteriography +arteriolar +arteriole +arterioles +arterioloscleroses +arteriolosclerosis +arterioscleroses +arteriosclerosis +arteriosclerotic +arteriovenous +arteritis +artery +artesian +artful +artfully +artfulness +arthralgia +arthralgic +arthritic +arthritically +arthritics +arthritides +arthritis +arthrodesis +arthrogram +arthrograms +arthrography +arthrogryposis +arthromere +arthromeric +arthropathy +arthropod +arthropodal +arthropodous +arthropods +arthroscope +arthroscopic +arthroscopically +arthroscopies +arthroscopy +arthroses +arthrosis +arthrospore +arthrotomy +arthur +arthurian +artichoke +artichokes +article +articled +articles +articling +articulable +articulacy +articular +articularly +articulate +articulated +articulately +articulateness +articulates +articulating +articulation +articulations +articulative +articulator +articulators +articulatory +artier +artiest +artifact +artifacts +artifactual +artifice +artificer +artificers +artifices +artificial +artificialities +artificiality +artificially +artificialness +artilleries +artillerist +artillerists +artillery +artilleryman +artillerymen +artily +artiness +artiodactyl +artiodactylous +artisan +artisans +artisanship +artist +artiste +artistes +artistic +artistically +artistry +artists +artless +artlessly +artlessness +artois +arts +artwork +artworks +arty +aruba +arugula +arum +arums +arunachal +aryan +aryans +aryl +arytenoid +arytenoidal +arête +arêtes +as +asafetida +asafetidas +asafoetida +asafoetidas +asbestic +asbestine +asbestos +asbestoses +asbestosis +asbestotic +asbestus +asbestuses +ascariasis +ascarid +ascarides +ascarids +ascaris +ascend +ascendable +ascendance +ascendancy +ascendant +ascendantly +ascendants +ascended +ascendence +ascendency +ascendent +ascendents +ascender +ascenders +ascendible +ascending +ascendingly +ascends +ascension +ascensional +ascensions +ascensive +ascent +ascents +ascertain +ascertainable +ascertainableness +ascertainably +ascertained +ascertaining +ascertainment +ascertainments +ascertains +asceses +ascesis +ascetic +ascetical +ascetically +asceticism +ascetics +asci +ascidia +ascidian +ascidians +ascidiate +ascidiform +ascidium +ascii +ascites +ascitic +ascocarp +ascocarps +ascogonia +ascogonium +ascomycete +ascomycetes +ascomycetous +ascorbate +ascorbic +ascospore +ascosporic +ascosporous +ascot +ascots +ascribable +ascribe +ascribed +ascribes +ascribing +ascription +ascriptions +ascriptive +ascus +asdic +asdics +asepalous +asepses +asepsis +aseptic +aseptically +asepticism +asexual +asexuality +asexualize +asexualized +asexualizes +asexualizing +asexually +ash +ashamed +ashamedly +ashanti +ashcan +ashcans +ashed +ashen +asher +ashes +asheville +ashier +ashiest +ashiness +ashing +ashlar +ashlars +ashless +ashore +ashram +ashrams +ashton +ashtoreth +ashtray +ashtrays +ashy +asia +asian +asianization +asians +asiatic +asiatics +aside +asides +asinine +asininely +asininity +asinorum +ask +askance +askant +asked +asker +askers +askeses +askesis +askew +askewness +asking +asks +aslant +asleep +aslope +aslosh +asmodeus +asocial +asp +asparaginase +asparagine +asparagus +aspartame +aspartate +aspartic +aspartokinase +aspasia +aspect +aspects +aspectual +aspen +aspens +asperate +asperated +asperates +asperating +asperges +aspergill +aspergilla +aspergilli +aspergillosis +aspergillum +aspergillums +aspergillus +asperities +asperity +asperse +aspersed +asperses +aspersing +aspersion +aspersions +asphalt +asphalted +asphaltic +asphalting +asphaltite +asphaltites +asphalts +asphaltum +aspheric +aspherical +asphodel +asphodels +asphyxia +asphyxiant +asphyxiate +asphyxiated +asphyxiates +asphyxiating +asphyxiation +asphyxiations +asphyxiator +asphyxiators +aspic +aspics +aspidistra +aspidistras +aspirant +aspirants +aspirate +aspirated +aspirates +aspirating +aspiration +aspirations +aspirator +aspirators +aspiratory +aspire +aspired +aspirer +aspirers +aspires +aspirin +aspiring +aspiringly +aspirins +asps +asquint +ass +assagai +assagais +assai +assail +assailable +assailableness +assailant +assailants +assailed +assailer +assailers +assailing +assailment +assails +assais +assam +assassin +assassinate +assassinated +assassinates +assassinating +assassination +assassinations +assassinative +assassinator +assassins +assault +assaulted +assaulter +assaulters +assaulting +assaultive +assaultively +assaultiveness +assaults +assay +assayable +assayed +assayer +assayers +assaying +assays +assegai +assegais +assemblage +assemblages +assemblagist +assemble +assembled +assembler +assemblers +assembles +assemblies +assembling +assembly +assemblyman +assemblymen +assemblywoman +assemblywomen +assent +assentation +assented +assenter +assenters +assenting +assentingly +assentive +assentiveness +assentor +assentors +assents +assert +assertable +asserted +assertedly +asserter +asserters +assertible +asserting +assertion +assertional +assertions +assertive +assertively +assertiveness +assertor +assertors +asserts +asses +assess +assessable +assessed +assesses +assessing +assessment +assessments +assessor +assessorial +assessors +asset +assets +asseverate +asseverated +asseverates +asseverating +asseveration +asseverations +asseverative +asshole +assholes +assibilate +assibilated +assibilates +assibilating +assibilation +assiduities +assiduity +assiduous +assiduously +assiduousness +assign +assignability +assignable +assignably +assignat +assignation +assignational +assignations +assignats +assigned +assignee +assignees +assigner +assigners +assigning +assignment +assignments +assignor +assignors +assigns +assimilability +assimilable +assimilate +assimilated +assimilates +assimilating +assimilation +assimilationism +assimilationist +assimilationists +assimilations +assimilative +assimilator +assimilators +assimilatory +assiniboin +assiniboins +assisi +assist +assistance +assistant +assistants +assistantship +assistantships +assisted +assister +assisters +assisting +assists +assize +assizes +associability +associable +associableness +associate +associated +associates +associateship +associateships +associating +association +associational +associationism +associationist +associationistic +associations +associative +associatively +associativity +assoil +assoiled +assoiling +assoilment +assoils +assonance +assonances +assonant +assonantal +assonants +assort +assortative +assorted +assorter +assorters +assorting +assortment +assortments +assorts +assuage +assuaged +assuagement +assuagements +assuages +assuaging +assuasive +assumability +assumable +assumably +assume +assumed +assumedly +assumer +assumers +assumes +assuming +assumingly +assumpsit +assumption +assumptions +assumptive +assumptively +assurable +assurance +assurances +assure +assured +assuredly +assuredness +assureds +assurer +assurers +assures +assurgency +assurgent +assuring +assuror +assurors +assyria +assyrian +assyrians +assyriological +assyriologist +assyriologists +assyriology +astarboard +astarte +astasia +astasias +astatic +astatically +astaticism +astatine +astatines +aster +asteria +asterias +asteriated +asterisk +asterisked +asterisking +asteriskless +asterisks +asterism +asterismal +asterisms +astern +asternal +asteroid +asteroidal +asteroids +asters +asthenia +asthenic +asthenics +asthenopia +asthenopic +asthenosphere +asthenospheric +asthma +asthmatic +asthmatically +asthmatics +astigmatic +astigmatically +astigmatism +astigmatisms +astilbe +astir +astomatal +astomatous +astomous +astonied +astonish +astonished +astonishes +astonishing +astonishingly +astonishment +astonishments +astor +astoria +astound +astounded +astounding +astoundingly +astounds +astrachan +astrachans +astraddle +astragal +astragalar +astragali +astragals +astragalus +astrakhan +astrakhans +astral +astrally +astraphobia +astray +astrictive +astride +astringency +astringent +astringently +astringents +astrionics +astrobiological +astrobiologist +astrobiologists +astrobiology +astrochemist +astrochemistry +astrocyte +astrocytic +astrocytoma +astrocytomas +astrocytomata +astrodome +astrodomes +astrodynamic +astrodynamics +astrogate +astrogated +astrogates +astrogating +astrogation +astrogator +astrogeologist +astrogeology +astrolabe +astrolabes +astrologer +astrologers +astrologic +astrological +astrologically +astrology +astrometric +astrometrical +astrometry +astronaut +astronautic +astronautical +astronautically +astronautics +astronauts +astronavigation +astronavigator +astronomer +astronomers +astronomic +astronomical +astronomically +astronomy +astrophotographer +astrophotographers +astrophotographic +astrophotography +astrophysical +astrophysicist +astrophysicists +astrophysics +astrosphere +asturian +asturians +asturias +astute +astutely +astuteness +astyanax +astylar +asuncion +asunción +asunder +aswan +aswarm +aswirl +aswoon +asylum +asylums +asymmetric +asymmetrical +asymmetrically +asymmetries +asymmetry +asymptomatic +asymptomatically +asymptote +asymptotes +asymptotic +asymptotical +asymptotically +asynapsis +asynchronism +asynchronous +asynchronously +asynchrony +asyndetic +asyndetically +asyndeton +asyntactic +at +atalanta +ataman +atamans +atamasco +atapuerca +ataractic +ataraxia +ataraxias +ataraxic +ataraxics +ataturk +atavism +atavisms +atavist +atavistic +atavistically +atavists +ataxia +ataxias +ataxic +ataxics +ataxies +ataxy +ate +atelectasis +atelier +ateliers +atemoya +atemporal +athabascan +athabaskan +athanasian +athanasius +atheism +atheist +atheistic +atheistical +atheistically +atheists +atheling +athelings +athelstan +athena +athenaeum +athenaeums +atheneum +atheneums +athenian +athenians +athens +atheoretical +atherogenesis +atherogenic +atherogenicity +atheroma +atheromas +atheromata +atheromatosis +atheromatous +atheroscleroses +atherosclerosis +atherosclerotic +atherosclerotically +athirst +athlete +athletes +athletic +athletically +athleticism +athletics +athodyd +athodyds +athos +athwart +athwartship +atilt +atingle +ation +atlanta +atlantan +atlantes +atlantic +atlanticism +atlanticist +atlantis +atlas +atlases +atlatl +atlatls +atman +atmans +atmometer +atmometers +atmometric +atmometry +atmosphere +atmospheres +atmospheric +atmospherically +atmospherics +atmospherium +atoll +atolls +atom +atomic +atomically +atomicity +atomies +atomism +atomisms +atomist +atomistic +atomistical +atomistically +atomists +atomization +atomize +atomized +atomizer +atomizers +atomizes +atomizing +atoms +atomy +atonable +atonal +atonalism +atonalist +atonalistic +atonalities +atonality +atonally +atone +atoneable +atoned +atonement +atonements +atoner +atoners +atones +atonic +atonicity +atonics +atonies +atoning +atony +atop +atopic +atopies +atopy +atoxic +atrabilious +atrabiliousness +atrazine +atrazines +atremble +atresia +atresias +atresic +atreus +atria +atrial +atrioventricular +atrip +atrium +atriums +atrocious +atrociously +atrociousness +atrocities +atrocity +atrophic +atrophied +atrophies +atrophy +atrophying +atropine +atropines +atropins +attaboy +attach +attachable +attached +attacher +attachers +attaches +attaching +attachment +attachments +attaché +attachés +attack +attacked +attacker +attackers +attacking +attackman +attackmen +attacks +attain +attainability +attainable +attainableness +attainably +attainder +attainders +attained +attaining +attainment +attainments +attains +attaint +attainted +attainting +attaints +attar +attars +attelet +attempt +attemptable +attempted +attempter +attempters +attempting +attempts +attend +attendance +attendances +attendant +attendantly +attendants +attended +attendee +attendees +attender +attenders +attending +attends +attention +attentional +attentions +attentive +attentively +attentiveness +attenuate +attenuated +attenuates +attenuating +attenuation +attenuations +attenuator +attenuators +attest +attestant +attestation +attestations +attested +attester +attesters +attesting +attestor +attestors +attests +attic +attica +atticism +atticisms +attics +atticus +attila +attire +attired +attires +attiring +attitude +attitudes +attitudinal +attitudinize +attitudinized +attitudinizes +attitudinizing +attoampere +attoamperes +attobecquerel +attobecquerels +attocandela +attocandelas +attocoulomb +attocoulombs +attofarad +attofarads +attogram +attograms +attohenries +attohenry +attohenrys +attohertz +attojoule +attojoules +attokelvin +attokelvins +attolumen +attolumens +attolux +attometer +attometers +attomole +attomoles +attonewton +attonewtons +attoohm +attoohms +attopascal +attopascals +attoradian +attoradians +attorn +attorned +attorney +attorneys +attorneyship +attorning +attornment +attorns +attosecond +attoseconds +attosiemens +attosievert +attosieverts +attosteradian +attosteradians +attotesla +attoteslas +attovolt +attovolts +attowatt +attowatts +attoweber +attowebers +attract +attractable +attractant +attractants +attracted +attracter +attracting +attraction +attractions +attractive +attractively +attractiveness +attractor +attractors +attracts +attributable +attribute +attributed +attributer +attributers +attributes +attributing +attribution +attributional +attributions +attributive +attributively +attributiveness +attributives +attributor +attrit +attrite +attrited +attrites +attriting +attrition +attritional +attrits +attritted +attritting +attune +attuned +attunement +attunements +attunes +attuning +atwitter +atypical +atypicality +atypically +au +aubade +aubades +auberge +auberges +aubergine +aubergines +auburn +auburns +aubusson +auckland +auction +auctioned +auctioneer +auctioneered +auctioneering +auctioneers +auctioning +auctions +auctorial +aucuba +audacious +audaciously +audaciousness +audacities +audacity +auden +audi +audial +audibility +audible +audibleness +audibles +audibly +audience +audiences +audile +audiles +auding +audings +audio +audiocassette +audiogenic +audiogram +audiograms +audiological +audiologist +audiologists +audiology +audiometer +audiometers +audiometric +audiometry +audiophile +audiophiles +audios +audiotape +audiotaped +audiotapes +audiotaping +audiotyping +audiotypist +audiotypists +audiovisual +audiovisuals +audit +auditable +audited +auditing +audition +auditioned +auditioning +auditions +auditive +auditor +auditoria +auditorium +auditoriums +auditors +auditory +audits +audubon +auf +aufklarung +aufklärung +augean +augend +augends +auger +augers +aught +aughts +augite +augites +augitic +augment +augmentable +augmentation +augmentations +augmentative +augmented +augmenter +augmenters +augmenting +augmentor +augmentors +augments +augsburg +augur +augural +augured +auguries +auguring +augurs +augury +august +augusta +augustan +augustans +augustine +augustinian +augustinianism +augustinians +augustinism +augustly +augustness +augusts +augustus +auk +auklet +auklets +auks +auld +aunt +aunthood +aunthoods +auntie +aunties +auntlike +auntly +aunts +aura +aurae +aural +aurally +aurar +auras +aureate +aureately +aureateness +aurei +aurelian +aurelius +aureola +aureolas +aureole +aureoles +aureomycin +aureus +auric +auricle +auricled +auricles +auricula +auriculae +auricular +auricularly +auriculas +auriculate +auriculately +auriferous +auriform +auriga +aurochs +aurora +auroral +aurorally +auroras +aurorean +aurous +aurum +auschwitz +auscultate +auscultated +auscultates +auscultating +auscultation +auscultations +auscultative +auscultatory +ausform +ausformed +ausforming +ausforms +auslander +auspex +auspicate +auspicated +auspicates +auspicating +auspice +auspices +auspicious +auspiciously +auspiciousness +aussie +aussies +austen +austenite +austenitic +austere +austerely +austereness +austerer +austerest +austerities +austerity +austerlitz +austin +austral +australasia +australasian +australes +australia +australian +australians +australis +australoid +australopithecine +australopithecus +austria +austrian +austrians +austro +autacoid +autacoidal +autacoids +autarch +autarchic +autarchical +autarchies +autarchy +autarkic +autarkical +autarkies +autarky +autecological +autecology +auteur +auteurism +auteurist +auteurs +authentic +authentically +authenticate +authenticated +authenticates +authenticating +authentication +authentications +authenticator +authenticators +authenticity +author +authored +authoress +authoresses +authorial +authoring +authoritarian +authoritarianism +authoritarians +authoritative +authoritatively +authoritativeness +authorities +authority +authorization +authorizations +authorize +authorized +authorizer +authorizers +authorizes +authorizing +authors +authorship +autism +autist +autistic +autistically +auto +autoantibody +autobahn +autobahns +autobiographer +autobiographers +autobiographic +autobiographical +autobiographically +autobiographies +autobiography +autobus +autobuses +autobusses +autocatalyses +autocatalysis +autocatalytic +autocatalytically +autocephalous +autochthon +autochthones +autochthonism +autochthonous +autochthonously +autochthons +autochthony +autoclave +autoclaved +autoclaves +autoclaving +autocollimator +autocollimators +autocorrelation +autocracies +autocracy +autocrat +autocratic +autocratical +autocratically +autocrats +autocross +autodidact +autodidactic +autodidacts +autodyne +autodynes +autoecious +autoeciously +autoecism +autoed +autoerotic +autoeroticism +autoerotism +autofocus +autofocuses +autogamic +autogamies +autogamous +autogamy +autogeneses +autogenesis +autogenetic +autogenetically +autogenic +autogenies +autogenous +autogenously +autogeny +autogiro +autogiros +autograft +autografted +autografting +autografts +autograph +autographed +autographic +autographical +autographically +autographing +autographs +autography +autogyro +autogyros +autoharp +autohypnosis +autohypnotic +autoimmune +autoimmunities +autoimmunity +autoimmunization +autoinfection +autoinfections +autoing +autoinoculable +autoinoculation +autointoxication +autoloader +autoloaders +autoloading +autologous +autolycus +autolysate +autolysin +autolysis +autolytic +autolyze +autolyzed +autolyzes +autolyzing +automaker +automakers +automat +automata +automatable +automate +automated +automates +automatic +automatically +automaticity +automatics +automating +automation +automations +automatism +automatist +automative +automatization +automatize +automatized +automatizes +automatizing +automaton +automatons +automatous +automats +automobile +automobiles +automobilist +automobilists +automorphism +automorphisms +automotive +autonomic +autonomically +autonomies +autonomist +autonomists +autonomous +autonomously +autonomy +autopen +autophagy +autopiler +autopilot +autopilots +autoplastic +autoplastically +autoplasty +autopolyploid +autopolyploidy +autopsic +autopsical +autopsied +autopsies +autopsist +autopsy +autopsying +autoradiogram +autoradiograms +autoradiograph +autoradiographic +autoradiography +autorotate +autorotated +autorotates +autorotating +autorotation +autoroute +autos +autosensor +autosexing +autosomal +autosomally +autosome +autosomes +autostrada +autostradas +autosuggest +autosuggested +autosuggestibility +autosuggestible +autosuggesting +autosuggestion +autosuggestive +autosuggests +autotelic +autotetraploid +autotetraploids +autotetraploidy +autotomic +autotomies +autotomize +autotomized +autotomizes +autotomizing +autotomous +autotomy +autotoxemia +autotoxic +autotoxin +autotransformer +autotroph +autotrophic +autotrophically +autotrophy +autoworker +autre +autumn +autumnal +autumnally +autumns +autunite +autunites +auvergne +aux +auxesis +auxetic +auxetically +auxiliaries +auxiliary +auxin +auxinic +auxinically +auxins +auxotroph +auxotrophic +auxotrophy +avail +availability +available +availableness +availably +availed +availing +availingly +avails +avalanche +avalanched +avalanches +avalanching +avalon +avant +avarice +avaricious +avariciously +avariciousness +avascular +avascularity +avast +avatar +avatars +avaunt +ave +avellan +avellane +avenge +avenged +avenger +avengers +avenges +avenging +avengingly +avens +aventail +aventails +aventine +aventurine +avenue +avenues +aver +average +averaged +averagely +averageness +averages +averaging +averment +averments +avernus +averrable +averred +averring +avers +averse +aversely +averseness +aversion +aversions +aversive +aversively +aversiveness +avert +avertable +averted +avertible +averting +averts +aves +avesta +avgas +avgases +avgasses +avian +aviaries +aviarist +aviarists +aviary +aviate +aviated +aviates +aviating +aviation +aviator +aviators +aviatrices +aviatrix +aviatrixes +aviculture +aviculturist +avid +avidin +avidins +avidities +avidity +avidly +avidness +avifauna +avifaunal +avifaunas +avignon +avila +avion +avionic +avionics +avirulence +avirulent +avis +avises +avitaminoses +avitaminosis +avitaminotic +aviv +avo +avocado +avocadoes +avocados +avocation +avocational +avocationally +avocations +avocet +avocets +avogadro +avoid +avoidable +avoidably +avoidance +avoidances +avoided +avoider +avoiders +avoiding +avoids +avoirdupois +avon +avos +avouch +avouched +avouches +avouching +avouchment +avouchments +avow +avowable +avowably +avowal +avowals +avowed +avowedly +avower +avowers +avowing +avows +avulse +avulsed +avulses +avulsing +avulsion +avulsions +avuncular +aw +await +awaited +awaiting +awaits +awake +awaked +awaken +awakened +awakener +awakeners +awakening +awakenings +awakens +awakes +awaking +award +awardable +awarded +awardee +awardees +awarder +awarders +awarding +awards +aware +awareness +awash +away +awayness +awe +aweary +aweather +awed +aweigh +aweless +awes +awesome +awesomely +awesomeness +awestricken +awestruck +awful +awfully +awfulness +awhile +awhirl +awing +awkward +awkwardly +awkwardness +awl +awless +awls +awn +awned +awning +awninged +awnings +awnless +awns +awoke +awoken +awry +ax +axe +axed +axel +axels +axenic +axenically +axes +axial +axiality +axially +axil +axile +axilla +axillae +axillar +axillaries +axillars +axillary +axils +axing +axiological +axiologically +axiologist +axiology +axiom +axiomatic +axiomatically +axiomatization +axiomatizations +axiomatize +axiomatized +axiomatizes +axiomatizing +axioms +axis +axisymmetric +axisymmetrical +axisymmetrically +axisymmetry +axle +axles +axletree +axletrees +axman +axmen +axminster +axolotl +axolotls +axon +axonal +axone +axonemal +axoneme +axones +axonometric +axons +axoplasm +axoplasmic +axoplasms +ay +ayah +ayahs +ayatollah +ayatollahs +aye +ayers +ayes +ayin +ayins +azalea +azaleas +azathioprine +azeotrope +azeotropic +azeotropy +azerbaijan +azerbaijani +azerbaijanis +azide +azides +azido +azidothymidine +azimuth +azimuthal +azimuthally +azimuths +azine +azines +azo +azoic +azole +azoles +azonal +azonic +azorean +azores +azorian +azotemia +azotemias +azotemic +azoth +azoths +azotobacter +azoturia +azoturias +aztec +aztecan +aztecs +azure +azures +azurite +azurites +azygos +azygoses +azygous +aîné +aînée +añu +b +baa +baaed +baaing +baal +baalbek +baalim +baalism +baals +baas +baba +babar +babas +babassu +babassus +babbage +babbitt +babbittry +babbitts +babble +babbled +babblement +babbler +babblers +babbles +babbling +babcock +babe +babel +babels +babes +babesbabel +babesia +babesias +babesiosis +babied +babier +babies +babiest +babirusa +babirusas +babka +babkas +baboo +baboon +baboonery +baboonish +baboons +baboos +babu +babul +babuls +babus +babushka +babushkas +baby +babyhood +babying +babyish +babylon +babylonia +babylonian +babylonians +babysat +babysitter +babysitters +babysitting +baccalaureate +baccalaureates +baccarat +baccate +bacchanal +bacchanalia +bacchanalian +bacchanalians +bacchanalias +bacchanals +bacchant +bacchante +bacchantes +bacchantic +bacchants +bacchic +bacchus +bach +bached +bachelor +bachelor's +bachelorhood +bachelorhoods +bachelors +bachelorship +baches +baching +bacillar +bacillary +bacilli +bacillus +bacitracin +back +backache +backaches +backbeat +backbeats +backbencher +backbenchers +backbend +backbends +backbit +backbite +backbiter +backbiters +backbites +backbiting +backbitten +backboard +backboards +backbone +backboned +backbones +backbreaker +backbreakers +backbreaking +backcloth +backcountry +backcourt +backcourtman +backcourtmen +backcross +backcrossed +backcrosses +backcrossing +backdate +backdated +backdates +backdating +backdoor +backdoors +backdrop +backdrops +backed +backelordom +backer +backers +backfield +backfields +backfill +backfilled +backfilling +backfills +backfire +backfired +backfires +backfiring +backgammon +background +backgrounder +backgrounders +backgrounds +backhand +backhanded +backhandedly +backhandedness +backhander +backhanders +backhanding +backhands +backhoe +backhoes +backhouse +backhouses +backing +backings +backlash +backlashed +backlasher +backlashers +backlashes +backlashing +backless +backlight +backlighted +backlighting +backlights +backlist +backlisted +backlisting +backlists +backlit +backlog +backlogged +backlogging +backlogs +backorder +backorders +backpack +backpacked +backpacker +backpackers +backpacking +backpacks +backpedal +backpedaled +backpedaling +backpedalled +backpedalling +backpedals +backpressure +backpressures +backquote +backquotes +backrest +backrests +backroom +backrooms +backrush +backrushes +backs +backsaw +backsaws +backscatter +backscattered +backscattering +backscatters +backseat +backseats +backset +backsets +backshore +backshores +backside +backsides +backslap +backslapped +backslapper +backslappers +backslapping +backslaps +backslash +backslashes +backslid +backslidden +backslide +backslider +backsliders +backslides +backsliding +backspace +backspaced +backspaces +backspacing +backspin +backspins +backstab +backstabbed +backstabber +backstabbers +backstabbing +backstabs +backstage +backstairs +backstay +backstays +backstitch +backstitched +backstitches +backstitching +backstop +backstopped +backstopping +backstops +backstretch +backstretches +backstroke +backstrokeer +backstrokeers +backstrokes +backstroking +backswept +backswimmer +backswimmers +backswing +backswings +backsword +backswords +backtrace +backtrack +backtracked +backtracking +backtracks +backup +backups +backward +backwardly +backwardness +backwards +backwash +backwashes +backwater +backwaters +backwoods +backwoodsman +backwoodsmen +backyard +backyards +bacon +baconian +baconians +bacons +bacteremia +bacteremic +bacteremically +bacteria +bacterial +bacterially +bactericidal +bactericidally +bactericide +bactericides +bacterin +bacterins +bacteriocin +bacteriocins +bacteriogenic +bacteriologic +bacteriological +bacteriologically +bacteriologist +bacteriologists +bacteriology +bacteriolyses +bacteriolysis +bacteriolytic +bacteriophage +bacteriophages +bacteriophagic +bacteriophagy +bacteriorhodopsin +bacteriorhodopsins +bacterioscopy +bacteriostases +bacteriostasis +bacteriostat +bacteriostatic +bacteriostats +bacterium +bacteriuria +bacterization +bacterizations +bacterize +bacterized +bacterizes +bacterizing +bacteroid +bactria +bactrian +baculiform +bad +badajoz +badass +badasses +baddie +baddies +baddy +bade +baden +badge +badged +badger +badgered +badgering +badgers +badges +badging +badinage +badinages +badland +badlands +badly +badman +badmen +badminton +badmouth +badmouthed +badmouthing +badmouths +badness +baedeker +baedekers +bael +baels +baffin +baffle +baffled +bafflegabs +bafflement +bafflements +baffler +bafflers +baffles +baffling +bafflingly +bag +bagasse +bagasses +bagatelle +bagatelles +bagehot +bagel +bagels +bagful +bagfuls +baggage +bagged +bagger +baggers +baggier +baggiest +baggily +bagginess +bagging +baggings +baggy +baghdad +baglike +bagman +bagmen +bagnio +bagnios +bagpipe +bagpiper +bagpipers +bagpipes +bags +bagsful +baguette +baguettes +bagwig +bagwigs +bagworm +bagworms +bah +bahama +bahaman +bahamas +bahamian +bahamians +bahawalpur +bahrain +bahraini +bahrainis +baht +bahts +bail +bailable +bailed +bailee +bailees +bailer +bailers +bailey +baileys +bailie +bailies +bailiff +bailiffs +bailiffship +bailing +bailiwick +bailiwicks +bailment +bailments +bailor +bailors +bailout +bailouts +bails +bailsman +bailsmen +baird +bairn +bairns +bait +baited +baiter +baiters +baiting +baits +baiza +baizas +baize +baizes +bake +baked +bakelite +baker +bakeries +bakers +bakersfield +bakery +bakes +bakeshop +bakeshops +baking +baklava +baklavas +baksheesh +balaam +balaclava +balaclavas +balalaika +balalaikas +balance +balanced +balancer +balancers +balances +balancing +balas +balases +balata +balatas +balboa +balboas +balbriggan +balconies +balcony +bald +baldachin +baldachins +balder +balderdash +baldest +baldhead +baldheaded +baldheads +balding +baldish +baldly +baldness +baldpate +baldpates +baldric +baldrics +baldwin +baldwins +bale +balearic +balearics +baled +baleen +baleens +balefire +balefires +baleful +balefully +balefulness +baler +balers +bales +balfour +bali +balinese +baling +balk +balkan +balkanization +balkanize +balkanized +balkanizes +balkanizing +balkans +balked +balker +balkers +balkier +balkiest +balkiness +balking +balkline +balklines +balks +balky +ball +ballad +ballade +balladeer +balladeers +ballades +balladic +balladist +balladists +balladry +ballads +ballantyne +ballarat +ballast +ballasted +ballasting +ballasts +ballcarrier +ballcarriers +balled +ballerina +ballerinas +ballet +balletic +balletomane +balletomanes +balletomania +ballets +ballflower +ballflowers +ballgame +ballgames +balling +ballista +ballistae +ballistic +ballistically +ballistician +ballisticians +ballistics +ballistocardiogram +ballistocardiograms +ballistocardiograph +ballistocardiographs +ballistocardiography +ballon +ballonet +ballonets +ballons +balloon +ballooned +ballooning +balloonist +balloonists +balloons +ballot +balloted +balloter +balloters +balloting +ballots +ballottement +ballottements +ballpark +ballparks +ballplayer +ballplayers +ballpoint +ballpoints +ballroom +ballrooms +balls +ballsier +ballsiest +ballsy +bally +ballyhoo +ballyhooed +ballyhooing +ballyhoos +ballyrag +ballyragged +ballyragging +ballyrags +balm +balmacaan +balmacaans +balmier +balmiest +balmily +balminess +balmoral +balmorals +balms +balmy +balneal +balneology +baloney +baloneys +balsa +balsam +balsamic +balsamroot +balsamroots +balsams +balsas +balsasbalsa +balt +balthazar +baltic +baltimore +baltimorean +baltimoreans +balts +baluchi +baluchis +baluchistan +baluchithere +baluchitheres +baluster +balusters +balustrade +balustrades +balzac +bam +bamako +bambara +bambini +bambino +bambinos +bamboo +bamboos +bamboozle +bamboozled +bamboozlement +bamboozler +bamboozlers +bamboozles +bamboozling +ban +banach +banal +banalities +banality +banalize +banalized +banalizes +banalizing +banally +banana +bananas +banausic +banco +bancos +bancroft +band +banda +bandage +bandaged +bandager +bandagers +bandages +bandaging +bandana +bandanas +bandanna +bandannas +bandbox +bandboxes +bandeau +bandeaus +bandeaux +banded +bander +banderilla +banderillas +banderillero +banderilleros +banderol +banderole +banderoles +banderols +banders +bandicoot +bandicoots +bandied +bandies +banding +bandings +bandit +banditry +bandits +banditti +bandjarmasin +bandleader +bandleaders +bandmaster +bandmasters +bandog +bandogs +bandoleer +bandoleers +bandolier +bandoliers +bandoneon +bandoneonist +bandoneonists +bandoneons +bandora +bandoras +bandore +bandores +bands +bandsman +bandsmen +bandstand +bandstands +bandwagon +bandwagoning +bandwagons +bandwidth +bandwidths +bandy +bandying +bane +baneberries +baneberry +baneful +banefully +banes +bang +bangalore +banged +banger +bangers +banging +bangkok +bangkoks +bangladesh +bangladeshi +bangladeshis +bangle +bangles +bangor +bangs +bangtail +bangtails +bangui +bani +baning +banish +banished +banisher +banishers +banishes +banishing +banishment +banishments +banister +banisters +banjo +banjoes +banjoist +banjoists +banjos +bank +bankability +bankable +bankbook +bankbooks +bankcard +bankcards +banked +banker +bankerly +bankers +banking +bankings +banknote +banknotes +bankroll +bankrolled +bankroller +bankrollers +bankrolling +bankrolls +bankrupt +bankruptcies +bankruptcy +bankrupted +bankrupting +bankruptive +bankrupts +banks +banksia +banksias +bankside +banksides +banned +banner +bannered +banneret +bannerets +bannerette +bannerettes +bannering +bannerol +bannerols +banners +banning +bannister +bannisters +bannock +bannocks +banns +banquet +banqueted +banqueter +banqueters +banqueting +banquets +banquette +banquettes +banquo +bans +banshee +banshees +banshie +banshies +bantam +bantams +bantamweight +bantamweights +banter +bantered +banterer +banterers +bantering +banteringly +banters +bantling +bantlings +bantu +bantus +bantustan +bantustans +banyan +banyans +banzai +banzais +baobab +baobabs +baptisia +baptisias +baptism +baptismal +baptismally +baptisms +baptist +baptisteries +baptistery +baptistries +baptistry +baptists +baptize +baptized +baptizer +baptizers +baptizes +baptizing +bar +barabbas +barathea +baratheas +barb +barbadian +barbadians +barbados +barbara +barbarian +barbarianism +barbarians +barbaric +barbarically +barbarism +barbarisms +barbarities +barbarity +barbarization +barbarize +barbarized +barbarizes +barbarizing +barbarossa +barbarous +barbarously +barbarousness +barbary +barbasco +barbascos +barbate +barbe +barbecue +barbecued +barbecuer +barbecuers +barbecues +barbecuing +barbed +barbedness +barbel +barbell +barbellate +barbells +barbels +barber +barbered +barbering +barberries +barberry +barbers +barbershop +barbershops +barbes +barbet +barbets +barbette +barbettes +barbican +barbicans +barbicel +barbicels +barbing +barbirolli +barbital +barbitals +barbitone +barbitones +barbiturate +barbiturates +barbituric +barbizon +barbs +barbuda +barbudan +barbudans +barbule +barbules +barbwire +barbwires +barca +barcarole +barcaroles +barcas +barcelona +barclay +barcode +barcodes +bard +bardacious +barde +barded +bardes +bardic +barding +bardolino +bardolinos +bards +bare +bareback +barebacked +bared +barefaced +barefacedly +barefacedness +barefoot +barefooted +barege +bareges +barehanded +barehandedness +bareheaded +barelegged +bareleggedness +barely +bareness +barents +barer +bares +barest +barf +barfed +barfing +barflies +barfly +barfs +bargain +bargained +bargainer +bargainers +bargaining +bargains +barge +bargeboard +bargeboards +barged +bargee +bargees +bargello +bargellos +bargeman +bargemen +barges +barghest +barghests +barging +bargirl +bargirls +barhop +barhoping +barhopped +barhops +bari +bariatric +bariatrician +bariatricians +bariatrics +baric +barilla +barillas +baring +barite +barites +baritonal +baritone +baritones +barium +bark +barked +barkeep +barkeeper +barkeepers +barkeeps +barkentine +barkentines +barker +barkers +barkier +barkiest +barking +barkless +barks +barky +barley +barleycorn +barleycorns +barlow +barlows +barm +barmaid +barmaids +barman +barmecidal +barmecide +barmen +barmier +barmiest +barms +barmy +barn +barnabas +barnacle +barnacled +barnacles +barnardo +barnburner +barnburners +barns +barnstorm +barnstormed +barnstormer +barnstormers +barnstorming +barnstorms +barnum +barny +barnyard +barnyards +barogram +barograms +barograph +barographic +barographs +barolo +barolos +barometer +barometers +barometric +barometrical +barometrically +barometry +baron +baronage +baronages +baroness +baronesses +baronet +baronetage +baronetages +baronetcies +baronetcy +baronetess +baronets +barong +barongs +baronial +baronies +barons +barony +baroque +baroquely +baroques +baroreceptor +baroreceptors +barotseland +barouche +barouches +barque +barquentine +barquentines +barques +barrack +barracked +barracker +barrackers +barracking +barracks +barracoon +barracoons +barracuda +barracudas +barrage +barraged +barrages +barraging +barramunda +barramundas +barramundi +barramundis +barranca +barrancas +barranco +barrancos +barrater +barraters +barrator +barrators +barratries +barratrous +barratrously +barratry +barre +barred +barrel +barreled +barrelful +barrelfuls +barrelhead +barrelheads +barrelhouse +barrelhouses +barreling +barrelled +barrelling +barrels +barren +barrenly +barrenness +barrens +barres +barrette +barrettes +barricade +barricaded +barricader +barricaders +barricades +barricading +barrier +barriers +barring +barrio +barrios +barrister +barristers +barroom +barrooms +barrow +barrows +barry +barrymore +bars +barstool +barstools +bartend +bartended +bartender +bartenders +bartending +bartends +barter +bartered +barterer +barterers +bartering +barters +bartholomew +bartizan +bartizaned +bartizans +bartlett +bartletts +bartók +bartókian +baruch +barware +barycenter +barycenters +baryon +baryonic +baryons +barysphere +baryspheres +baryta +barytas +baryte +barytes +barytone +barytones +bas +basal +basally +basalt +basaltic +basalts +bascule +bascules +base +baseball +baseballs +baseboard +baseboards +baseborn +baseburner +baseburners +based +basel +baseless +baselessly +baseline +baselines +basely +baseman +basemen +basement +basementless +basements +baseness +basenji +basenjis +baser +baserunning +bases +basest +bash +bashaw +bashaws +bashed +basher +bashers +bashes +bashful +bashfully +bashfulness +bashing +basic +basically +basichromatic +basicities +basicity +basics +basidia +basidial +basidiocarp +basidiocarps +basidiomycete +basidiomycetes +basidiomycetous +basidiospore +basidiospores +basidiosporous +basidium +basification +basified +basifier +basifiers +basifies +basifixed +basify +basifying +basil +basilar +basilica +basilican +basilicas +basilicata +basilisk +basilisks +basils +basin +basinal +basined +basinet +basinets +basing +basins +basipetal +basipetally +basis +bask +basked +baskerville +basket +basketball +basketballs +basketful +basketfuls +basketlike +basketry +baskets +basketsful +basketwork +basking +basks +basle +basophil +basophile +basophiles +basophilia +basophilias +basophilic +basophils +basotho +basque +basques +basra +bass +basses +basset +bassets +bassett +bassi +bassinet +bassinets +bassist +bassists +basso +bassoon +bassoonist +bassoonists +bassoons +bassos +basswood +basswoods +bast +bastard +bastardies +bastardization +bastardizations +bastardize +bastardized +bastardizes +bastardizing +bastardly +bastards +bastardy +baste +basted +baster +basters +bastes +bastille +bastilles +bastinado +bastinadoed +bastinadoes +bastinadoing +basting +bastings +bastion +bastioned +bastions +bastnaesite +bastnaesites +basutoland +bat +batavia +batavian +batavians +batboy +batboys +batch +batched +batcher +batchers +batches +batching +bate +bateau +bateaux +bated +bates +batfish +batfishes +batfowl +batfowled +batfowling +batfowls +batgirl +batgirls +bath +bathe +bathed +bather +bathers +bathes +bathetic +bathetically +bathhouse +bathhouses +bathing +bathmat +bathmats +batholith +batholithic +batholiths +bathometer +bathometers +bathophobia +bathophobias +bathos +bathoses +bathrobe +bathrobes +bathroom +bathrooms +baths +bathsheba +bathtub +bathtubs +bathurst +bathwater +bathyal +bathymetric +bathymetrical +bathymetrically +bathymetry +bathypelagic +bathyscaph +bathyscaphe +bathyscaphes +bathyscaphs +bathysphere +bathyspheres +bathythermograph +bathythermographs +batik +batiks +bating +batiste +batman +batmen +baton +batons +batophobia +batrachian +batrachians +batrachotoxin +batrachotoxins +bats +batsman +batsmen +batswana +batswanas +batt +battailous +battalia +battalias +battalion +battalions +batteau +batted +battement +batten +battenbergs +battened +battening +battens +batter +battered +batterer +batterers +batterie +batteries +battering +batters +battery +battier +battiest +battiness +batting +battings +battle +battled +battledore +battledores +battlefield +battlefields +battlefront +battlefronts +battleground +battlegrounds +battlement +battlemented +battlements +battler +battlers +battles +battleship +battleships +battlewagon +battlewagons +battling +batts +battu +battue +battues +batty +batwing +batwings +bauble +baubles +baucis +baud +baudelaire +bauds +bauhaus +bauhinia +bauhinias +baum +baumé +bauxite +bauxites +bauxitic +bavaria +bavarian +bavarians +bawbee +bawbees +bawcock +bawcocks +bawd +bawdier +bawdiest +bawdily +bawdiness +bawdries +bawdry +bawds +bawdy +bawdyhouse +bawdyhouses +bawl +bawled +bawler +bawlers +bawling +bawls +bay +bayadere +bayaderes +bayberries +bayberry +bayed +bayesian +bayeux +baying +bayonet +bayoneted +bayoneting +bayonets +bayonetted +bayonetting +bayonne +bayou +bayous +bayreuth +bays +bayside +bazaar +bazaars +bazooka +bazookas +bdellium +bdelliums +be +beach +beachboy +beachboys +beachcomb +beachcombed +beachcomber +beachcombers +beachcombing +beachcombs +beached +beaches +beachfront +beachfronts +beachhead +beachheads +beaching +beachless +beachscape +beachscapes +beachside +beachwear +beachy +beacon +beaconed +beaconing +beacons +bead +beaded +beadier +beadiest +beadily +beading +beadings +beadle +beadles +beadroll +beadrolls +beads +beadsman +beadsmen +beadwork +beady +beagle +beagles +beak +beaked +beaker +beakers +beaks +beaky +beam +beamed +beamier +beamiest +beaming +beamingly +beamish +beamishly +beams +beamy +bean +beanbag +beanbags +beanball +beanballs +beaned +beaneries +beanery +beanie +beanies +beaning +beano +beanos +beanpole +beanpoles +beans +beanstalk +beanstalks +bear +bearability +bearable +bearably +bearbaiting +bearbaitings +bearberries +bearberry +bearcat +bearcats +beard +bearded +beardedness +bearding +beardless +beardlessness +beards +beardtongue +beardtongues +bearer +bearers +bearing +bearings +bearish +bearishly +bearishness +bearlike +bears +bearskin +bearskins +beast +beastie +beasties +beastings +beastlier +beastliest +beastliness +beastly +beasts +beat +beatable +beaten +beater +beaters +beatific +beatifically +beatification +beatifications +beatified +beatifies +beatify +beatifying +beating +beatings +beatitude +beatitudes +beatles +beatless +beatnik +beatniks +beatrice +beats +beau +beaucoup +beaucoups +beaufort +beaujolais +beaumont +beaune +beaus +beaut +beauteous +beauteously +beauteousness +beautician +beauticians +beauties +beautification +beautifications +beautified +beautifier +beautifiers +beautifies +beautiful +beautifully +beautifulness +beautify +beautifying +beauts +beauty +beautyberries +beautyberry +beautybush +beautybushes +beaux +beaver +beaverboard +beaverbrook +beavered +beavering +beavers +beavertail +beavertails +bebop +bebopper +beboppers +becalm +becalmed +becalming +becalms +became +because +beccafico +beccaficos +bechance +bechanced +bechances +bechancing +bechuana +bechuanaland +bechuanas +beck +becket +beckets +beckon +beckoned +beckoner +beckoners +beckoning +beckoningly +beckons +becks +becloud +beclouded +beclouding +beclouds +become +becomes +becoming +becomingly +becomingness +becquerel +becquerels +bed +bedabble +bedabbled +bedabbles +bedabbling +bedaub +bedaubed +bedaubing +bedaubs +bedazzle +bedazzled +bedazzlement +bedazzles +bedazzling +bedbug +bedbugs +bedchamber +bedchambers +bedclothes +bedcover +bedcovering +bedcovers +bedded +bedder +bedders +bedding +bede +bedeck +bedecked +bedecking +bedecks +bedevil +bedeviled +bedeviling +bedevilled +bedevilling +bedevilment +bedevils +bedew +bedewed +bedewing +bedews +bedfast +bedfellow +bedfellows +bedford +bedfordshire +bedight +bedighted +bedighting +bedights +bedim +bedimmed +bedimming +bedims +bedizen +bedizened +bedizening +bedizenment +bedizens +bedlam +bedlamite +bedlamites +bedmate +bedmates +bedouin +bedouins +bedpan +bedpans +bedplate +bedplates +bedpost +bedposts +bedraggle +bedraggled +bedraggles +bedraggling +bedrid +bedridden +bedrock +bedroll +bedrolls +bedroom +bedrooms +beds +bedside +bedsides +bedsonia +bedsoniae +bedsore +bedsores +bedspread +bedspreads +bedspring +bedsprings +bedstead +bedsteads +bedstraw +bedstraws +bedtime +bedtimes +beduin +beduins +bee +beebee +beebees +beebread +beech +beecham +beechdrops +beechen +beeches +beechnut +beechnuts +beef +beefalo +beefaloes +beefalos +beefcake +beefcakes +beefeater +beefeaters +beefed +beefier +beefiest +beefiness +beefing +beefs +beefsteak +beefsteaks +beefwood +beefwoods +beefy +beehive +beehives +beekeeper +beekeepers +beekeeping +beelike +beeline +beelines +beelzebub +been +beep +beeped +beeper +beepers +beeping +beeps +beer +beerbohm +beerhouse +beerhouses +beerier +beeriest +beers +beersheba +beery +bees +beestings +beeswax +beet +beethoven +beetle +beetled +beetles +beetleweed +beetleweeds +beetling +beetroot +beetroots +beets +beeves +befall +befallen +befalling +befalls +befell +befit +befits +befitted +befitting +befittingly +befog +befogged +befogging +befogs +befool +befooled +befooling +befools +before +beforehand +beforetime +befoul +befouled +befouling +befouls +befriend +befriended +befriending +befriends +befuddle +befuddled +befuddlement +befuddlements +befuddles +befuddling +beg +began +beget +begets +begetter +begetters +begetting +beggar +beggared +beggaries +beggaring +beggarliness +beggarly +beggars +beggary +begged +begging +begin +beginner +beginners +beginning +beginnings +begins +begird +begirded +begirding +begirds +begirt +begone +begonia +begonias +begorra +begot +begotten +begrime +begrimed +begrimes +begriming +begrudge +begrudged +begrudger +begrudgers +begrudges +begrudging +begrudgingly +begs +beguile +beguiled +beguilement +beguilements +beguiler +beguilers +beguiles +beguiling +beguilingly +beguine +beguines +begum +begums +begun +behalf +behalves +behave +behaved +behaver +behavers +behaves +behaving +behavior +behavioral +behaviorally +behaviorism +behaviorist +behavioristic +behaviorists +behaviors +behead +beheaded +beheading +beheadings +beheads +beheld +behemoth +behemoths +behest +behind +behindhand +behinds +behold +beholden +beholder +beholders +beholding +beholds +behoof +behoove +behooved +behooves +behooving +beige +beiges +beigy +beijing +being +beings +beirut +bejesus +bejewel +bejeweled +bejeweling +bejewelled +bejewels +bel +belabor +belabored +belaboring +belabors +belarus +belated +belatedly +belatedness +belaud +belauded +belauding +belauds +belay +belayed +belaying +belays +belch +belched +belches +belching +beldam +beldame +beldames +beldams +beleaguer +beleaguered +beleaguering +beleaguerment +beleaguers +belemnite +belemnites +belfast +belfried +belfries +belfry +belgae +belgian +belgians +belgic +belgium +belgrade +belgravia +belie +belied +belief +beliefs +belier +beliers +belies +believability +believable +believably +believe +believed +believer +believers +believes +believing +belike +belittle +belittled +belittlement +belittler +belittlers +belittles +belittling +belittlingly +belive +belize +belizian +belizians +bell +bella +belladonna +bellbird +bellbirds +bellboy +bellboys +belle +belled +belleek +belleeks +belles +belletrism +belletrist +belletristic +belletrists +bellflower +bellflowers +bellhop +bellhops +belli +bellicose +bellicosely +bellicoseness +bellicosity +bellied +bellies +belligerence +belligerency +belligerent +belligerently +belligerents +belling +bellini +bellman +bellmen +belloc +bellona +bellow +bellowed +bellower +bellowers +bellowing +bellows +bellpull +bellpulls +bells +bellum +bellwether +bellwethers +bellwort +bellworts +belly +bellyache +bellyached +bellyacher +bellyachers +bellyaches +bellyaching +bellyband +bellybands +bellybutton +bellybuttons +bellyful +bellyfuls +bellying +belmont +belmopan +beloit +belonephobia +belonephobias +belong +belonged +belonger +belongers +belonging +belongingness +belongings +belongs +belorussia +belorussian +belorussians +beloved +beloveds +below +belowground +bels +belsen +belshazzar +belt +beltane +belted +belting +beltings +beltless +belts +beltway +beltways +beluga +belukha +belvedere +belvederes +belying +bema +bemata +bemedaled +bemedalled +bemire +bemired +bemires +bemiring +bemoan +bemoaned +bemoaning +bemoans +bemock +bemocked +bemocking +bemocks +bemuse +bemused +bemusedly +bemusement +bemuses +bemusing +ben +benares +bench +benched +bencher +benchers +benches +benching +benchmark +benchmarked +benchmarking +benchmarks +benchwarmer +benchwarmers +bend +bendable +benday +bendayed +bendaying +bendays +bender +benders +bending +bends +bendy +bene +beneath +benedict +benedictine +benedictines +benediction +benedictions +benedictive +benedictory +benedicts +benedictus +benefaction +benefactions +benefactor +benefactors +benefactress +benefactresses +benefic +benefice +beneficed +beneficence +beneficences +beneficent +beneficently +benefices +beneficial +beneficially +beneficialness +beneficiaries +beneficiary +beneficiate +beneficiated +beneficiating +beneficiation +beneficing +benefit +benefited +benefiter +benefiters +benefiting +benefits +benefitted +benefitting +benelux +benevento +benevolence +benevolent +benevolently +benevolentness +bengal +bengalese +bengali +bengaline +bengalines +bengalis +benghazi +benidorm +benighted +benightedly +benightedness +benign +benignancies +benignancy +benignant +benignantly +benignities +benignity +benignly +benin +beninese +benison +benisons +benjamin +benne +bennet +bennets +bennies +bennington +benny +bens +bent +bentham +benthamism +benthamite +benthamites +benthic +benthonic +benthos +benthoses +bentonite +bentonites +bentonitic +bents +bentwood +bentwoods +benumb +benumbed +benumbing +benumbment +benumbs +benz +benzaldehyde +benzaldehydes +benzalkonium +benzanthracene +benzedrine +benzene +benzenes +benzidine +benzidines +benzimidazole +benzimidazoles +benzin +benzine +benzines +benzins +benzoate +benzoates +benzocaine +benzocaines +benzocarbazole +benzocarbazoles +benzodiazepine +benzodiazepines +benzoic +benzoin +benzoins +benzol +benzols +benzophenone +benzophenones +benzopyrene +benzopyrenes +benzoyl +benzoyls +benzyl +benzylic +benzyls +beowulf +bepaint +bepainted +bepainting +bepaints +bequeath +bequeathal +bequeathals +bequeathed +bequeather +bequeathers +bequeathing +bequeathment +bequeaths +bequest +bequests +berate +berated +berates +berating +berber +berberine +berberines +berbers +berceuse +berceuses +berdache +berdaches +berdachism +berea +bereave +bereaved +bereavement +bereavements +bereaver +bereavers +bereaves +bereaving +bereft +berenices +beret +berets +berg +bergamo +bergamot +bergamots +bergen +bergs +bergsonian +bergsonism +beribboned +beriberi +bering +berkeleian +berkeleianism +berkeley +berkelium +berkshire +berkshires +berlin +berline +berliner +berliners +berlioz +berm +berms +bermuda +bermudan +bermudans +bermudas +bermudian +bermudians +bern +bernadette +bernadotte +bernard +bernardine +berne +bernese +bernhardt +bernini +bernoulli +bernstein +berried +berries +berry +berrying +berrylike +berseem +berseems +berserk +berserker +berserkers +berserkly +berserks +berth +bertha +berthas +berthed +berthing +berths +beryl +berylline +beryllium +beryls +berzelius +bes +besançon +beseech +beseeched +beseecher +beseechers +beseeches +beseeching +beseechingly +beseem +beseemed +beseeming +beseems +beset +besetment +besets +besetting +beshrew +beshrewed +beshrewing +beshrews +beside +besides +besiege +besieged +besiegement +besieger +besiegers +besieges +besieging +besmear +besmeared +besmearing +besmears +besmirch +besmirched +besmircher +besmirchers +besmirches +besmirching +besmirchment +besom +besoms +besot +besots +besotted +besotting +besought +bespangle +bespangled +bespangles +bespangling +bespatter +bespattered +bespattering +bespatters +bespeak +bespeaking +bespeaks +bespectacled +bespoke +bespoken +besprent +besprinkle +besprinkled +besprinkles +besprinkling +bessarabia +bessel +bessemer +bessie +bessies +best +bestead +besteaded +besteading +besteads +bested +bestial +bestialities +bestiality +bestialize +bestialized +bestializes +bestializing +bestially +bestiaries +bestiary +besting +bestir +bestirred +bestirring +bestirs +bestow +bestowable +bestowal +bestowals +bestowed +bestowing +bestowment +bestows +bestraddle +bestraddled +bestraddles +bestraddling +bestrew +bestrewed +bestrewing +bestrewn +bestrews +bestridden +bestride +bestrides +bestriding +bestrode +bests +bestseller +bestsellerdom +bestsellers +bestselling +bet +beta +betaine +betaines +betake +betaken +betakes +betaking +betamethasone +betamethasones +betas +betatron +betatrons +betel +betelgeuse +betels +beth +bethanechol +bethanechols +bethany +bethel +bethels +bethesda +bethink +bethinking +bethinks +bethlehem +bethought +betide +betided +betides +betiding +betimes +betjeman +betoken +betokened +betokening +betokens +betonies +betony +betook +betray +betrayal +betrayals +betrayed +betrayer +betrayers +betraying +betrays +betroth +betrothal +betrothals +betrothed +betrothing +betroths +bets +betta +bettas +betted +better +bettered +bettering +betterment +betterments +betters +betterton +betting +bettor +bettors +betty +between +betweenbrain +betweenness +betweentimes +betweenwhiles +betwixt +beulah +bevel +beveled +beveling +bevelled +bevelling +bevels +beverage +beverages +beverly +bevies +bevy +bewail +bewailed +bewailer +bewailers +bewailing +bewailment +bewails +beware +bewared +bewares +bewaring +bewhiskered +bewick +bewigged +bewilder +bewildered +bewilderedly +bewilderedness +bewildering +bewilderingly +bewilderment +bewilders +bewitch +bewitched +bewitcher +bewitchers +bewitchery +bewitches +bewitching +bewitchingly +bewitchment +bewitchments +bewray +bewrayed +bewraying +bewrays +bey +beyond +beys +bezant +bezants +bezel +bezels +bezique +bezoar +bezoars +bhakti +bhaktis +bhang +bhangs +bhutan +bhutanese +bi +biafra +biafran +biafrans +bialy +bialys +biannual +biannually +biarritz +bias +biased +biases +biasing +biasness +biassed +biasses +biassing +biathlete +biathletes +biathlon +biathlons +biaxial +biaxiality +biaxially +bib +bibb +bibbed +bibber +bibbers +bibbery +bibbing +bibbs +bibcock +bibcocks +bibelot +bibelots +bible +bibles +bibless +biblical +biblically +biblicism +biblicist +biblicists +bibliofilm +bibliofilms +bibliographer +bibliographers +bibliographic +bibliographical +bibliographically +bibliographies +bibliography +bibliolater +bibliolaters +bibliolatrous +bibliolatry +bibliology +bibliomancies +bibliomancy +bibliomania +bibliomaniac +bibliomaniacal +bibliomaniacs +bibliopegic +bibliopegist +bibliopegists +bibliopegy +bibliophile +bibliophiles +bibliophilic +bibliophilism +bibliophilistic +bibliophily +bibliopole +bibliopoles +bibliopolic +bibliopolical +bibliopolist +bibliopolists +bibliotheca +bibliothecal +bibliothecas +bibliotherapies +bibliotherapy +bibliotic +bibliotics +bibliotist +bibliotists +bibs +bibulous +bibulously +bibulousness +bicameral +bicameralism +bicarb +bicarbonate +bicarbonates +bicarbs +bicaudal +bicellular +bicentenaries +bicentenary +bicentennial +bicentennials +bicentric +bicentricity +bicephalous +biceps +bicepses +bichloride +bichlorides +bichromate +bichromated +bichromates +bichrome +bicipital +bicker +bickered +bickerer +bickerers +bickering +bickers +bicoastal +bicolor +bicolored +bicolors +bicomponent +biconcave +biconcavity +biconditional +biconditionals +biconvex +biconvexity +bicorne +bicornes +bicornuate +bicultural +biculturalism +bicuspid +bicuspidate +bicuspids +bicycle +bicycled +bicycler +bicyclers +bicycles +bicyclic +bicycling +bicyclist +bicyclists +bid +bidarka +bidarkas +biddability +biddable +biddably +bidden +bidder +bidders +biddies +bidding +biddings +biddy +bide +bided +bidentate +bider +biders +bides +bidet +bidets +bidialectal +bidialectalism +bidialectalist +bidialectalists +biding +bidirectional +bidirectionally +bidonville +bidonvilles +bids +biedermeier +bien +biennia +biennial +biennially +biennials +biennium +bienniums +bier +biers +bierstadt +bifacial +biff +biffed +biffies +biffing +biffs +biffy +bifid +bifida +bifidity +bifidly +bifilar +bifilarly +biflagellate +bifocal +bifocaled +bifocalism +bifocals +bifoliolate +biform +bifunctional +bifurcate +bifurcated +bifurcately +bifurcates +bifurcating +bifurcation +bifurcations +big +bigamies +bigamist +bigamists +bigamous +bigamously +bigamy +bigarade +bigarades +bigeminal +bigeminies +bigeminy +bigeneric +bigeye +bigeyes +bigfoot +bigger +biggest +biggety +biggie +biggies +biggin +bigging +biggings +biggins +biggish +biggity +bighead +bigheaded +bigheadedness +bigheads +bighearted +bigheartedly +bigheartedness +bighorn +bighorns +bight +bights +bigly +bigmouth +bigmouthed +bigmouths +bigness +bignonia +bignonias +bigos +bigot +bigoted +bigotedly +bigotedness +bigotries +bigotry +bigots +bigtime +bigwig +bigwigs +bihar +bijection +bijections +bijective +bijou +bijous +bijouterie +bijouteries +bijoux +bijugate +bike +biked +biker +bikers +bikes +bikeway +bikeways +bikie +bikies +biking +bikini +bikinied +bikinis +bilabial +bilabially +bilabials +bilabiate +bilander +bilanders +bilateral +bilateralism +bilaterally +bilateralness +bilayer +bilayers +bilbao +bilberries +bilberry +bilbo +bilboa +bilboas +bilboes +bildungsroman +bildungsromans +bile +biles +bilge +bilged +bilges +bilging +bilgy +bilharzia +bilharzias +bilharziasis +biliary +bilimbi +bilimbis +bilinear +bilingual +bilingualism +bilingually +bilinguals +bilious +biliously +biliousness +bilirubin +bilirubins +biliverdin +biliverdins +bilk +bilked +bilker +bilkers +bilking +bilks +bill +billable +billabong +billabongs +billboard +billboarded +billboarding +billboards +billbug +billbugs +billed +biller +billers +billet +billeted +billeting +billets +billfish +billfishes +billfold +billfolds +billhead +billheads +billhook +billhooks +billiard +billiards +billies +billing +billings +billingsgate +billion +billionaire +billionaires +billionfold +billions +billionth +billionths +billon +billons +billow +billowed +billowiness +billowing +billows +billowy +billposter +billposters +billposting +bills +billy +billycock +billycocks +bilobate +bilobed +bilobular +bilocation +bilocations +bilocular +biltong +biltongs +bimanal +bimanous +bimanual +bimanually +bimaxillary +bimbo +bimbos +bimestrial +bimetal +bimetallic +bimetallism +bimetallist +bimetallistic +bimetallists +bimetals +bimillenaries +bimillenary +bimillenial +bimillenially +bimillennia +bimillennium +bimillenniums +biminis +bimodal +bimodality +bimolecular +bimolecularly +bimonthlies +bimonthly +bimorphemic +bin +binal +binaries +binary +binate +binational +binaural +binaurally +bind +binder +binderies +binders +bindery +binding +bindingly +bindingness +bindings +bindle +bindles +bindlestiff +bindlestiffs +binds +bindweed +bindweeds +bine +bines +binge +binged +bingeing +binger +bingers +binges +binging +bingo +bingoes +bingos +binnacle +binnacles +binned +binning +binocular +binocularity +binocularly +binoculars +binomial +binomially +binomials +binominal +bins +bint +bints +binturong +binturongs +binuclear +binucleate +binucleated +bio +bioaccumulation +bioaccumulations +bioaccumulative +bioacoustics +bioactive +bioactivities +bioactivity +bioagent +bioagents +bioassay +bioassays +bioastronautical +bioastronautics +bioavailability +biocatalyst +biocatalysts +biocatalytic +biocenology +biocenose +biocenoses +biocenosis +biochemical +biochemically +biochemist +biochemistries +biochemistry +biochemists +biochip +biochips +biocidal +biocide +biocides +bioclimatic +bioclimatology +biocoenoses +biocoenosis +biocompatibility +biocompatible +bioconversion +biodegradability +biodegradable +biodegradation +biodegrade +biodegraded +biodegrades +biodegrading +biodiversity +biodynamic +biodynamics +bioelectric +bioelectrical +bioelectricity +bioelectronic +bioelectronics +bioenergetic +bioenergetics +bioengineer +bioengineered +bioengineering +bioengineers +bioenvironmental +bioethical +bioethicist +bioethicists +bioethics +biofeedback +bioflavonoid +bioflavonoids +biogas +biogenesis +biogenetic +biogenetical +biogenetically +biogenetics +biogenic +biogenous +biogeochemical +biogeochemistry +biogeographer +biogeographers +biogeographic +biogeographical +biogeography +biogerontologist +biogerontologists +biogerontology +biographee +biographees +biographer +biographers +biographic +biographical +biographically +biographies +biography +biohazard +biohazards +bioinorganic +bioinstrumentation +bioinstrumentations +biologic +biological +biologically +biologicals +biologics +biologism +biologist +biologistic +biologists +biology +bioluminescence +bioluminescent +biolysis +biolytic +biomarker +biomarkers +biomass +biomasses +biomaterial +biomaterials +biomathematical +biomathematician +biomathematicians +biomathematics +biome +biomechanical +biomechanically +biomechanics +biomedical +biomedicine +biomembrane +biomembranes +biomes +biometeorology +biometric +biometrical +biometrically +biometrics +biometry +biomimesis +biomineralogist +biomineralogists +biomolecular +biomolecule +biomolecules +bionic +bionics +bionomic +bionomical +bionomically +bionomics +bioorganic +biophysical +biophysically +biophysicist +biophysicists +biophysics +biopic +biopics +biopolymer +biopolymers +bioprocess +bioprocessed +bioprocesses +bioprocessing +biopsic +biopsied +biopsies +biopsy +biopsychic +biopsychology +bioptic +bioreactor +bioreactors +bioregion +bioregional +bioregionalism +bioregionalist +bioregionalists +bioregions +bioresearch +biorhythm +biorhythmic +biorhythms +bios +biosatellite +biosatellites +bioscience +biosciences +bioscientific +bioscientist +bioscientists +bioscope +bioscopes +bioscopies +bioscopy +biosensor +biosensors +biosocial +biosocially +biosphere +biospheres +biospheric +biostatistician +biostatisticians +biostatistics +biosyntheses +biosynthesis +biosynthesize +biosynthesized +biosynthesizes +biosynthesizing +biosynthetic +biosynthetically +biosystematic +biosystematics +biosystematist +biosystematists +biota +biotas +biotech +biotechnical +biotechnological +biotechnologist +biotechnologists +biotechnology +biotelemetric +biotelemetry +biotherapies +biotherapy +biotic +biotin +biotins +biotite +biotites +biotitic +biotope +biotopes +biotransformation +biotransformations +biotron +biotrons +biotype +biotypes +biotypic +bioweapon +bioweapons +biparental +biparentally +biparous +bipartisan +bipartisanism +bipartisanship +bipartite +bipartitely +bipartition +biped +bipedal +bipedalism +bipedality +bipeds +biphenyl +biphenyls +bipinnate +bipinnately +biplane +biplanes +bipod +bipods +bipolar +bipolarity +bipolarization +bipolarize +bipolarized +bipolarizes +bipolarizing +bipotentialities +bipotentiality +bipropellant +bipropellants +biquadratic +biquadratics +biquarterly +biracial +biracialism +biradial +biramous +birch +birched +birchen +bircher +birchers +birches +birching +birchism +birchist +birchists +bird +birdbath +birdbaths +birdbrain +birdbrained +birdbrains +birdcage +birdcages +birdcall +birdcalls +birded +birder +birders +birdhouse +birdhouses +birdie +birdied +birdieing +birdies +birding +birdlike +birdlime +birdlimed +birdlimes +birdliming +birdman +birdmen +birds +birdseed +birdseeds +birdshot +birdwatcher +birdwatchers +birdying +birefringence +birefringent +bireme +biremes +biretta +birettas +birk +birkbeck +birkie +birkies +birks +birl +birled +birler +birlers +birling +birls +birmingham +biro +biros +birr +birred +birring +birrs +birth +birthday +birthdays +birthed +birthing +birthings +birthmark +birthmarks +birthplace +birthplaces +birthrate +birthrates +birthright +birthrights +birthroot +birthroots +births +birthstone +birthstones +birthwort +birthworts +biryani +biryanis +bis +biscay +biscayne +biscotti +biscotto +biscuit +biscuits +bise +bisect +bisected +bisecting +bisection +bisectional +bisectionally +bisections +bisector +bisectors +bisects +biseriate +biserrate +bises +bisexual +bisexuality +bisexually +bisexuals +bishop +bishopric +bishoprics +bishops +bislama +bismarck +bismarckian +bismuth +bismuthal +bismuthic +bison +bisons +bisque +bisques +bissau +bissextile +bissextiles +bistate +bister +bistered +bisters +bistort +bistorts +bistouries +bistoury +bistre +bistred +bistres +bistro +bistroic +bistros +bisulcate +bisulfate +bisulfates +bisulfide +bisulfides +bisulfite +bisulfites +bit +bitable +bitartrate +bitartrates +bitch +bitched +bitcheries +bitchery +bitches +bitchier +bitchiest +bitchily +bitchiness +bitching +bitchy +bite +biteable +biteplate +biteplates +biter +biters +bites +bitewing +bitewings +bithynia +bithynian +biting +bitingly +bitmap +bitmapped +bitmapping +bitmaps +bitok +bitoks +bits +bitstock +bitstocks +bitsy +bitt +bitted +bitten +bitter +bitterbrush +bitterbrushes +bittered +bitterender +bitterenders +bitterer +bitterest +bittering +bitterish +bitterly +bittern +bitterness +bitterns +bitternut +bitternuts +bitterroot +bitterroots +bitters +bittersweet +bittersweetly +bittersweetness +bittersweets +bitterweed +bittier +bittiest +bittiness +bitting +bittock +bittocks +bitts +bitty +bitumen +bitumens +bituminization +bituminize +bituminized +bituminizes +bituminizing +bituminoid +bituminous +bitwise +bivalence +bivalency +bivalent +bivalents +bivalve +bivalved +bivalves +bivariate +bivouac +bivouacked +bivouacking +bivouacks +bivouacs +biweeklies +biweekly +biyearly +biz +bizarre +bizarrely +bizarreness +bizet +bizonal +bizone +bizones +blab +blabbed +blabber +blabbered +blabbering +blabbermouth +blabbermouths +blabbers +blabbing +blabby +blabs +black +blackamoor +blackamoors +blackball +blackballed +blackballer +blackballers +blackballing +blackballs +blackbeard +blackberries +blackberry +blackbird +blackbirder +blackbirders +blackbirds +blackboard +blackboards +blackbodies +blackbody +blackbuck +blackbucks +blackcap +blackcaps +blackcock +blackcocks +blackcurrant +blackcurrants +blackdamp +blacked +blacken +blackened +blackener +blackeners +blackening +blackens +blacker +blackest +blackface +blackfaces +blackfeet +blackfish +blackfishes +blackflies +blackfly +blackfoot +blackguard +blackguarded +blackguarding +blackguardism +blackguardly +blackguards +blackhander +blackhanders +blackhead +blackheads +blackheart +blacking +blackings +blackish +blackjack +blackjacked +blackjacking +blackjacks +blackland +blackleg +blacklegs +blacklight +blacklist +blacklisted +blacklister +blacklisters +blacklisting +blacklists +blackly +blackmail +blackmailed +blackmailer +blackmailers +blackmailing +blackmails +blackness +blackout +blackouts +blackpoll +blackpolls +blacks +blacksburg +blacksmith +blacksmithing +blacksmiths +blacksnake +blacksnakes +blackstone +blackstrap +blackstraps +blacktail +blacktails +blackthorn +blackthorns +blacktop +blacktopped +blacktopping +blacktops +blackwash +blackwashed +blackwashes +blackwashing +blackwater +bladder +bladderlike +bladdernose +bladdernoses +bladdernut +bladdernuts +bladders +bladderwort +bladderworts +bladdery +blade +bladed +blades +blaff +blaffs +blagging +blagoveshchensk +blah +blahs +blain +blains +blamable +blamableness +blamably +blame +blamed +blameful +blamefully +blamefulness +blameless +blamelessly +blamelessness +blamer +blamers +blames +blameworthier +blameworthiest +blameworthiness +blameworthy +blaming +blanc +blanch +blanche +blanched +blancher +blanchers +blanches +blanching +blancmange +blancmanges +bland +blander +blandest +blandification +blandified +blandifies +blandify +blandifying +blandish +blandished +blandisher +blandishers +blandishes +blandishing +blandishment +blandishments +blandly +blandness +blank +blanked +blanker +blankest +blanket +blanketed +blanketflower +blanketflowers +blanketing +blanketlike +blankets +blanking +blankly +blankness +blanks +blare +blared +blares +blaring +blarney +blarneyed +blarneying +blarneys +blaspheme +blasphemed +blasphemer +blasphemers +blasphemes +blasphemies +blaspheming +blasphemous +blasphemously +blasphemousness +blasphemy +blast +blasted +blastema +blastemal +blastemas +blastemata +blastematic +blastemic +blaster +blasters +blastie +blasties +blasting +blastment +blastocoel +blastocoelic +blastocoels +blastocyst +blastocystic +blastocysts +blastoderm +blastodermatic +blastodermic +blastoderms +blastodisk +blastodisks +blastoff +blastoffs +blastogenesis +blastogenetic +blastogenic +blastoma +blastomas +blastomata +blastomere +blastomeres +blastomeric +blastomycete +blastomycetes +blastomycin +blastomycins +blastomycosis +blastoporal +blastopore +blastopores +blastoporic +blastosphere +blastospheres +blastospore +blastospores +blasts +blastula +blastulae +blastular +blastulas +blastulation +blasé +blat +blatancies +blatancy +blatant +blatantly +blate +blather +blathered +blatherer +blatherers +blathering +blathers +blatherskite +blatherskites +blats +blatted +blatter +blattered +blattering +blatters +blatting +blaw +blawed +blawing +blawn +blaws +blaxploitation +blaze +blazed +blazer +blazers +blazes +blazing +blazingly +blazon +blazoned +blazoner +blazoners +blazoning +blazonment +blazonries +blazonry +blazons +bleach +bleachable +bleached +bleacher +bleachers +bleaches +bleaching +bleak +bleaker +bleakest +bleakish +bleakly +bleakness +blear +bleared +blearier +bleariest +blearily +bleariness +blearing +blears +bleary +bleat +bleated +bleater +bleaters +bleating +bleats +bleb +blebby +blebs +bled +bleed +bleeder +bleeders +bleeding +bleedings +bleeds +bleep +bleeped +bleeper +bleepers +bleeping +bleeps +blemish +blemished +blemisher +blemishers +blemishes +blemishing +blench +blenched +blencher +blenchers +blenches +blenching +blend +blende +blended +blender +blenders +blendes +blending +blends +blenheim +blennies +blenny +blent +bleomycin +bleomycins +blepharitis +blepharoplast +blepharoplasts +blepharoplasty +blepharospasm +blepharospasms +blesbok +blesboks +bless +blessed +blessedly +blessedness +blesser +blessers +blesses +blessing +blessings +blest +blether +blethered +blethering +blethers +blew +bligh +blight +blighted +blighter +blighters +blighting +blights +blimp +blimpish +blimpishly +blimpishness +blimps +blin +blind +blinded +blinder +blinders +blindest +blindfish +blindfishes +blindfold +blindfolded +blindfolding +blindfolds +blinding +blindingly +blindly +blindman +blindman's +blindness +blinds +blindworm +blindworms +blini +blinis +blink +blinked +blinker +blinkered +blinkering +blinkers +blinking +blinks +blintz +blintze +blintzes +blip +blipped +blipping +blips +bliss +blissful +blissfully +blissfulness +blister +blistered +blistering +blisteringly +blisters +blistery +blithe +blithely +blitheness +blither +blithered +blithering +blithers +blithesome +blithesomely +blithest +blithsomeness +blitz +blitzed +blitzes +blitzing +blitzkrieg +blitzkriegs +blivit +blivits +blizzard +blizzards +blizzardy +bloat +bloated +bloater +bloaters +bloating +bloats +blob +blobbed +blobbing +blobs +bloc +block +blockade +blockaded +blockader +blockaders +blockades +blockading +blockage +blockages +blockbuster +blockbusters +blockbusting +blocked +blocker +blockers +blockhead +blockheadedness +blockheads +blockhouse +blockhouses +blockier +blockiest +blocking +blockish +blockishly +blockishness +blocks +blocky +blocs +bloemfontein +blois +bloke +blokes +blond +blonde +blonder +blondes +blondest +blondish +blondness +blonds +blood +bloodbath +bloodbaths +bloodcurdling +bloodcurdlingly +blooded +bloodedness +bloodguilt +bloodguiltiness +bloodguilty +bloodhound +bloodhounds +bloodied +bloodier +bloodies +bloodiest +bloodily +bloodiness +blooding +bloodless +bloodlessly +bloodlessness +bloodletter +bloodletters +bloodletting +bloodlettings +bloodline +bloodlines +bloodlust +bloodmobile +bloodmobiles +bloodred +bloodroot +bloodroots +bloods +bloodshed +bloodshot +bloodstain +bloodstained +bloodstaining +bloodstains +bloodstock +bloodstone +bloodstones +bloodstream +bloodstreams +bloodsucker +bloodsuckers +bloodsucking +bloodthirstily +bloodthirstiness +bloodthirsty +bloodworm +bloodworms +bloody +bloodying +bloom +bloomed +bloomer +bloomers +blooming +blooms +bloomy +bloop +blooped +blooper +bloopers +blooping +bloops +blossom +blossomed +blossoming +blossoms +blossomy +blot +blotch +blotched +blotches +blotchily +blotchiness +blotching +blotchy +blots +blotted +blotter +blotters +blotting +blotto +blouse +bloused +blouses +blousing +blouson +blousons +blousy +blow +blowback +blowbacks +blowby +blowbys +blower +blowers +blowfish +blowfishes +blowflies +blowfly +blowgun +blowguns +blowhard +blowhards +blowhole +blowholes +blowier +blowiest +blowing +blowjob +blowjobs +blown +blowoff +blowoffs +blowout +blowouts +blowpipe +blowpipes +blows +blowsier +blowsiest +blowsy +blowtorch +blowtorches +blowup +blowups +blowy +blowzier +blowziest +blowzily +blowziness +blowzy +blub +blubbed +blubber +blubbered +blubberer +blubberers +blubbering +blubberingly +blubbers +blubbery +blubbing +blubs +blucher +bluchers +bludgeon +bludgeoned +bludgeoneers +bludgeoner +bludgeoners +bludgeoning +bludgeons +blue +bluebeard +bluebeards +bluebell +bluebells +blueberries +blueberry +bluebill +bluebills +bluebird +bluebirds +bluebonnet +bluebonnets +bluebook +bluebooks +bluebottle +bluebottles +bluecoat +bluecoated +bluecoats +bluecurls +blued +bluefin +bluefish +bluefishes +bluegill +bluegills +bluegrass +blueing +blueings +bluejacket +bluejackets +bluely +blueness +bluenose +bluenosed +bluenoses +bluepoint +bluepoints +blueprint +blueprinted +blueprinting +blueprints +bluer +blues +blueshift +bluesman +bluesmen +bluest +bluestem +bluestems +bluestocking +bluestockings +bluestone +bluestones +bluesy +bluet +bluetongue +bluetongues +bluets +blueweed +blueweeds +bluey +blueys +bluff +bluffable +bluffed +bluffer +bluffers +bluffest +bluffing +bluffly +bluffness +bluffs +bluing +bluings +bluish +bluishness +blunder +blunderbuss +blunderbusses +blundered +blunderer +blunderers +blundering +blunderingly +blunderings +blunders +blunt +blunted +blunter +bluntest +blunting +bluntly +bluntness +blunts +blur +blurb +blurbs +blurred +blurrier +blurriest +blurrily +blurriness +blurring +blurringly +blurry +blurs +blurt +blurted +blurter +blurters +blurting +blurts +blush +blushed +blusher +blushers +blushes +blushful +blushing +blushingly +bluster +blustered +blusterer +blusterers +blustering +blusteringly +blusterous +blusters +blustery +blücher +bo +bo's'n +bo's'ns +bo'sun +bo'suns +boa +boadicea +boar +board +boarded +boarder +boarders +boarding +boardinghouse +boardinghouses +boardlike +boardman +boardmen +boardroom +boardrooms +boards +boardsailing +boardwalk +boardwalks +boarfish +boarfishes +boarhound +boarhounds +boarish +boars +boart +boarts +boas +boast +boasted +boaster +boasters +boastful +boastfully +boastfulness +boasting +boastings +boasts +boat +boatbill +boatbills +boatbuilder +boatbuilders +boated +boatel +boatels +boater +boaters +boathouse +boathouses +boating +boatlift +boatlifts +boatload +boatloads +boatman +boatmanship +boatmen +boats +boatsman +boatsmen +boatswain +boatswains +boatwright +boatwrights +boatyard +boatyards +bob +bobbed +bobber +bobberies +bobbers +bobbery +bobbie +bobbies +bobbin +bobbinet +bobbinets +bobbing +bobbins +bobble +bobbled +bobbles +bobbling +bobby +bobbysoxer +bobbysoxers +bobcat +bobcats +bobeche +bobeches +boboli +bobolink +bobolinks +bobs +bobsled +bobsledded +bobsledder +bobsledders +bobsledding +bobsleded +bobsleding +bobsleds +bobstay +bobstays +bobtail +bobtailed +bobtails +bobwhite +bobwhites +bocaccio +bocaccios +boccaccio +bocce +bocces +bocci +boccie +boccies +boccis +bock +bocks +bodacious +bodaciously +bode +boded +bodega +bodegas +bodement +bodements +bodensee +bodes +bodhisattva +bodhisattvas +bodice +bodices +bodied +bodies +bodiless +bodily +boding +bodings +bodkin +bodkins +bodleian +bodley +body +bodybuilder +bodybuilders +bodybuilding +bodyguard +bodyguards +bodying +bodysnatching +bodysuit +bodysuits +bodysurf +bodysurfed +bodysurfer +bodysurfers +bodysurfing +bodysurfs +bodyweight +bodywork +boehmite +boehmites +boeing +boeings +boeotia +boeotian +boeotians +boer +boers +boethius +boff +boffin +boffins +boffo +boffola +boffolas +boffos +boffs +bofors +bog +bogey +bogeyed +bogeying +bogeyman +bogeymen +bogeys +bogged +boggier +boggiest +bogginess +bogging +boggle +boggled +boggler +bogglers +boggles +boggling +boggy +bogie +bogies +bogle +bogles +bogotá +bogs +bogsat +bogtrotter +bogtrotters +bogus +bogwood +bogwoods +bogy +bogyman +bogymen +bohea +boheas +bohemia +bohemian +bohemianism +bohemians +bohemias +bohr +bohrium +bohunk +bohunks +bohème +boil +boilable +boiled +boiler +boilermaker +boilermakers +boilerplate +boilerplates +boilers +boiling +boiloff +boiloffs +boils +bois +boise +boisterous +boisterously +boisterousness +bokhara +bokmål +bola +bolas +bolases +bold +bolded +bolder +boldest +boldface +boldfaced +boldfaces +boldfacing +bolding +boldly +boldness +bole +bolection +bolections +bolero +boleros +boles +bolete +boletes +boleti +boletus +boletuses +boleyn +bolide +bolides +bolingbroke +bolivar +bolivars +bolivia +bolivian +boliviano +bolivianos +bolivians +boll +bollard +bollards +bolled +bolling +bollinger +bollix +bollixed +bollixes +bollixing +bolls +bollworm +bollworms +bolo +bologna +bolognan +bolognese +bolometer +bolometers +bolometric +bolometrically +boloney +bolos +bolshevik +bolsheviks +bolshevism +bolshevist +bolshevists +bolshevization +bolshevize +bolshevized +bolshevizes +bolshevizing +bolshie +bolshies +bolshy +bolster +bolstered +bolsterer +bolsterers +bolstering +bolsters +bolt +bolted +bolter +bolters +bolthole +boltholes +bolting +boltonia +boltonias +boltrope +boltropes +bolts +bolus +boluses +bolívar +bomb +bombard +bombarded +bombarder +bombardier +bombardiers +bombarding +bombardment +bombardments +bombardon +bombardons +bombards +bombast +bombaster +bombasters +bombastic +bombastically +bombasts +bombay +bombazine +bombazines +bombe +bombed +bomber +bombers +bombes +bombinate +bombinated +bombinates +bombinating +bombination +bombing +bombings +bomblet +bomblets +bombproof +bombs +bombshell +bombshells +bombsight +bombsights +bombycid +bombycids +bon +bona +bonanza +bonanzas +bonaparte +bonapartism +bonapartist +bonapartists +bonaventure +bonbon +bonbonnière +bonbonnières +bonbons +bond +bondable +bondage +bonded +bonder +bonders +bondholder +bondholders +bondi +bonding +bondings +bondmaid +bondmaids +bondman +bondmen +bonds +bondservant +bondservants +bondsman +bondsmen +bondstone +bondstones +bondwoman +bondwomen +bone +boneblack +boned +bonefish +bonefishes +bonehead +boneheaded +boneheadedness +boneheads +boneless +boner +boners +bones +boneset +bonesets +bonesetter +bonesetters +boney +boneyard +boneyards +bonfire +bonfires +bong +bonged +bonging +bongo +bongoes +bongoist +bongoists +bongos +bongs +bonhomie +bonhomies +bonier +boniest +boniface +bonifaces +boniness +boning +bonito +bonitos +bonjour +bonkers +bonn +bonne +bonnes +bonnet +bonneted +bonneting +bonnets +bonneville +bonnie +bonnier +bonniest +bonnily +bonniness +bonny +bonnyclabber +bonnyclabbers +bono +bons +bonsai +bonsoir +bonspiel +bonspiels +bontebok +bonteboks +bonum +bonus +bonuses +bony +bonze +bonzes +boo +boob +boobies +booboisie +booboisies +booboo +booboos +boobs +booby +boodle +boodles +booed +booger +boogerman +boogermen +boogers +boogeyman +boogeymen +boogie +boogied +boogies +boogying +boohoo +boohooed +boohooing +boohoos +booing +book +bookbinder +bookbinderies +bookbinders +bookbindery +bookbinding +bookbindings +bookcase +bookcases +booked +bookend +bookends +booker +bookers +bookful +bookie +bookies +booking +bookings +bookish +bookishly +bookishness +bookkeeper +bookkeepers +bookkeeping +booklet +booklets +booklists +booklore +booklores +booklouse +booklouses +bookmaker +bookmakers +bookmaking +bookman +bookmark +bookmarker +bookmarkers +bookmarks +bookmen +bookmobile +bookmobiles +bookplate +bookplates +bookrack +bookracks +bookroom +bookrooms +books +bookseller +booksellers +bookselling +bookshelf +bookshelves +bookshop +bookshops +bookstall +bookstalls +bookstand +bookstands +bookstore +bookstores +bookwork +bookworm +bookworms +boolean +boom +boomed +boomer +boomerang +boomeranged +boomeranging +boomerangs +boomers +boomier +boomiest +booming +boomlet +boomlets +booms +boomtown +boomtowns +boomy +boon +boondocks +boondoggle +boondoggled +boondoggler +boondogglers +boondoggles +boondoggling +boonies +boons +boor +boorish +boorishly +boorishness +boors +boos +boost +boosted +booster +boosterish +boosterism +boosters +boosting +boosts +boot +bootblack +bootblacks +booted +bootee +bootees +bootes +booth +booths +bootie +booties +booting +bootjack +bootjacks +bootlace +bootlaces +bootle +bootleg +bootlegged +bootlegger +bootleggers +bootlegging +bootlegs +bootless +bootlessly +bootlessness +bootlick +bootlicked +bootlicker +bootlickers +bootlicking +bootlicks +boots +bootstrap +bootstrapped +bootstrapping +bootstraps +booty +booze +boozed +boozehound +boozehounds +boozer +boozers +boozes +boozier +booziest +boozily +boozing +boozy +bop +bophuthatswana +bopped +bopper +boppers +bopping +boppish +bops +bora +boracic +borage +borages +borane +boranes +boras +borate +borated +borates +borax +boraxes +borazon +borborygmi +borborygmus +bordeaux +bordello +bordellos +border +bordereau +bordereaux +bordered +borderer +borderers +bordering +borderland +borderlands +borderline +borderlines +borders +bordetella +bordetellas +bordure +bordures +bore +boreal +borealis +boreas +borecole +borecoles +bored +boredom +borehole +boreholes +borer +borers +bores +borghese +borgia +boric +boride +borides +boring +boringly +boringness +borings +born +borne +bornean +borneo +borneol +borneols +bornholm +bornite +bornites +borodin +boron +boronic +borons +borosilicate +borosilicates +borough +boroughs +borrelia +borrelias +borrow +borrowed +borrower +borrowers +borrowing +borrowings +borrows +borsch +borsches +borscht +borschts +borsht +borshts +borstal +borstals +bort +borts +borty +borzoi +borzois +bos'n +bosc +boscage +boscages +bosch +bosh +bosk +boskage +boskages +boskier +boskiest +boskiness +bosks +bosky +bosnia +bosnian +bosnians +bosom +bosomed +bosoms +bosomy +boson +bosons +bosphorus +bosporus +bosque +bosques +bosquet +bosquets +boss +bossa +bossdom +bossdoms +bossed +bosses +bossier +bossies +bossiest +bossily +bossiness +bossing +bossism +bossisms +bossy +boston +bostonian +bostonians +bosun +bosuns +boswell +boswellian +boswellize +boswellized +boswellizes +boswellizing +boswells +bosworth +bot +botanic +botanical +botanically +botanicals +botanies +botanist +botanists +botanize +botanized +botanizer +botanizers +botanizes +botanizing +botany +botch +botched +botcher +botchers +botches +botching +botchy +botfly +both +bother +botheration +botherations +bothered +bothering +bothers +bothersome +bothnia +botonee +botonnee +botryoidal +botryoidally +botrytis +bots +botswana +botswanan +bott +botticelli +bottle +bottlebrush +bottlebrushes +bottlecap +bottlecaps +bottled +bottleful +bottleneck +bottlenecked +bottlenecking +bottlenecks +bottlenose +bottlenoses +bottler +bottlers +bottles +bottling +bottom +bottomed +bottomer +bottomers +bottoming +bottomland +bottomless +bottomlessly +bottomlessness +bottommost +bottoms +botts +botulin +botulinal +botulins +botulinum +botulinums +botulinus +botulism +boucicault +boucle +bouclé +boudicca +boudin +boudins +boudoir +boudoirs +bouffant +bouffe +bouffes +bougainvillaea +bougainvillaeas +bougainville +bougainvillea +bougainvilleas +bough +boughed +boughs +bought +bougie +bougies +bouillabaisse +bouillon +boulder +bouldered +boulderer +boulderers +bouldering +boulders +bouldery +boule +boules +boulevard +boulevardier +boulevardiers +boulevards +bouleversement +bouleversements +boulle +boulles +boulogne +bounce +bounced +bouncer +bouncers +bounces +bouncier +bounciest +bouncily +bouncing +bouncingly +bouncy +bound +boundaries +boundary +bounded +boundedness +bounden +bounder +bounderish +bounders +bounding +boundless +boundlessly +boundlessness +bounds +bounteous +bounteously +bounteousness +bountied +bounties +bountiful +bountifully +bountifulness +bounty +bouquet +bouquetier +bouquetiers +bouquets +bourbon +bourbonism +bourbons +bourdon +bourdons +bourg +bourgeois +bourgeoise +bourgeoises +bourgeoisie +bourgeoisification +bourgeoisified +bourgeoisifies +bourgeoisify +bourgeoisifying +bourgeon +bourgeoned +bourgeoning +bourgeons +bourget +bourgogne +bourgs +bourguignon +bourn +bourne +bournes +bourns +bourrée +bourrées +bourse +bourses +bouse +boused +bouses +bousing +boustrophedon +boustrophedonic +bout +boutique +boutiques +bouton +boutonniere +boutonnieres +boutonnière +boutonnières +boutons +bouts +bouvardia +bouvardias +bouvier +bouzouki +bouzoukis +bovid +bovids +bovine +bovinely +bovines +bovinity +bovril +bow +bowdlerism +bowdlerization +bowdlerizations +bowdlerize +bowdlerized +bowdlerizer +bowdlerizers +bowdlerizes +bowdlerizing +bowed +bowel +bowelless +bowels +bower +bowerbird +bowerbirds +bowered +bowering +bowers +bowery +bowfin +bowfins +bowfront +bowhead +bowheads +bowie +bowing +bowings +bowknot +bowknots +bowl +bowlder +bowlders +bowled +bowleg +bowlegged +bowlegs +bowler +bowlers +bowlful +bowlfuls +bowline +bowlines +bowling +bowls +bowman +bowmen +bows +bowse +bowsed +bowses +bowshot +bowshots +bowsing +bowsprit +bowsprits +bowstring +bowstrings +bowwow +bowwows +bowyer +bowyers +box +boxboard +boxboards +boxcar +boxcars +boxed +boxer +boxers +boxes +boxfish +boxfishes +boxful +boxfuls +boxhaul +boxhauled +boxhauling +boxhauls +boxier +boxiest +boxiness +boxing +boxings +boxlike +boxthorn +boxthorns +boxwood +boxwoods +boxy +boy +boyar +boyard +boyards +boyars +boycott +boycotted +boycotter +boycotters +boycotting +boycotts +boyfriend +boyfriends +boyhood +boyish +boyishly +boyishness +boyle +boyo +boyos +boys +boysenberries +boysenberry +bozcaada +bozeman +bozo +bozos +boîte +boîtes +boötes +bra +brabant +brabble +brabbled +brabbler +brabblers +brabbles +brabbling +brace +braced +bracelet +bracelets +bracer +bracero +braceros +bracers +braces +brachia +brachial +brachiate +brachiated +brachiates +brachiating +brachiation +brachiator +brachiators +brachiocephalic +brachiopod +brachiopods +brachiosaurus +brachium +brachycephalic +brachycephalism +brachycephaly +brachydactylia +brachydactylic +brachydactyly +brachylogies +brachylogy +brachypterism +brachypterous +brachyuran +bracing +bracingly +bracings +braciola +bracken +brackens +bracket +bracketed +bracketing +brackets +brackish +brackishness +braconid +braconids +bract +bracteal +bracteate +bracted +bracteolate +bracteole +bracteoles +bracts +brad +bradawl +bradawls +bradded +bradding +brads +bradshaw +bradycardia +bradycardias +bradycardic +bradykinin +bradykinins +bradylogia +bradylogias +brae +braes +brag +braganza +bragg +braggadocio +braggadocios +braggart +braggarts +bragged +bragger +braggers +braggest +bragging +braggy +brags +brahe +brahma +brahman +brahmanic +brahmanical +brahmanism +brahmanist +brahmanists +brahmans +brahmaputra +brahmas +brahmin +brahminism +brahmins +brahms +brahmsian +braid +braided +braider +braiders +braiding +braidings +braids +brail +brailed +brailing +braille +brailled +brailler +braillers +brailles +braillewriter +braillewriters +brailling +brails +brain +braincase +braincases +brainchild +brainchildren +brained +brainier +brainiest +brainily +braininess +braining +brainish +brainless +brainlessly +brainlessness +brainpan +brainpans +brainpower +brains +brainsick +brainsickly +brainsickness +brainstem +brainstems +brainstorm +brainstormed +brainstormer +brainstormers +brainstorming +brainstorms +brainteaser +brainteasers +brainwash +brainwashed +brainwasher +brainwashers +brainwashes +brainwashing +brainwave +brainwaves +brainwork +brainworker +brainworkers +brainworks +brainy +braise +braised +braises +braising +brake +braked +brakeless +brakeman +brakemen +brakes +braking +braky +braless +bralessness +bramble +brambleberries +brambleberry +brambles +brambling +bramblings +brambly +bran +branch +branched +branches +branchia +branchiae +branchial +branching +branchiopadous +branchiopod +branchiopodan +branchiopods +branchless +branchlet +branchlets +branchy +brand +brandade +brandades +branded +brandenburg +brander +branders +brandied +brandies +branding +brandish +brandished +brandisher +brandishers +brandishes +brandishing +brandling +brandlings +brands +brandy +brandying +brandywine +brank +branks +brannigan +brannigans +branny +brant +brants +braque +bras +brash +brasher +brashes +brashest +brashly +brashness +brass +brassard +brassards +brassbound +brasserie +brasseries +brasses +brassica +brassicas +brassie +brassier +brassiere +brassieres +brassies +brassiest +brassily +brassiness +brassware +brasswares +brassy +brasília +brat +bratislava +brats +brattice +bratticed +brattices +bratticing +brattier +brattiest +brattiness +brattish +brattishness +brattle +brattleboro +brattled +brattles +brattling +bratty +bratwurst +bratwursts +braunschweiger +braunschweigers +brava +bravado +bravadoes +bravados +bravas +brave +braved +bravely +braveness +braver +braveries +bravers +bravery +braves +bravest +braving +bravissimo +bravo +bravoed +bravoes +bravoing +bravos +bravura +bravuras +braw +brawer +brawest +brawl +brawled +brawler +brawlers +brawlier +brawliest +brawling +brawlingly +brawls +brawly +brawn +brawnier +brawniest +brawnily +brawniness +brawny +bray +brayed +brayer +brayers +braying +brays +braze +brazed +brazen +brazened +brazenfaced +brazening +brazenly +brazenness +brazens +brazer +brazers +brazes +brazier +braziers +brazil +brazilian +brazilians +brazils +brazilwood +brazilwoods +brazing +brazzaville +breach +breached +breaches +breaching +bread +breadbasket +breadbaskets +breadboard +breadboarded +breadboarding +breadboards +breadbox +breadboxes +breadcrumb +breadcrumbs +breaded +breadfruit +breadfruits +breading +breadline +breadlines +breadnut +breadnuts +breadroot +breadroots +breads +breadstuff +breadstuffs +breadth +breadths +breadthways +breadthwise +breadwinner +breadwinners +breadwinning +break +breakable +breakableness +breakables +breakage +breakages +breakaway +breakaways +breakdown +breakdowns +breaker +breakers +breakfast +breakfasted +breakfaster +breakfasters +breakfasting +breakfasts +breakfront +breakfronts +breaking +breakings +breakneck +breakoff +breakoffs +breakout +breakouts +breakpoint +breakpoints +breaks +breakthrough +breakthroughs +breakup +breakups +breakwater +breakwaters +bream +breamed +breaming +breams +breast +breastbone +breastbones +breasted +breastfed +breastfeed +breastfeeding +breastfeeds +breasting +breastplate +breastplates +breasts +breaststroke +breaststroker +breaststrokers +breaststrokes +breastwork +breastworks +breath +breathability +breathable +breathalyzer +breathalyzers +breathe +breathed +breather +breathers +breathes +breathier +breathiest +breathily +breathiness +breathing +breathings +breathless +breathlessly +breathlessness +breaths +breathtaking +breathtakingly +breathy +breccia +breccias +brecciate +brecciated +brecciates +brecciating +brecciation +brecht +brechtian +breckinridge +bred +breda +brede +bredes +breech +breechblock +breechblocks +breechcloth +breechcloths +breechclout +breechclouts +breeches +breeching +breechings +breechloader +breechloaders +breechloading +breed +breeder +breeders +breeding +breeds +breeks +breeze +breezed +breezeless +breezes +breezeway +breezeways +breezier +breeziest +breezily +breeziness +breezing +breezy +bregma +bregmata +bregmatic +bremen +bremsstrahlung +bremsstrahlungs +bren +brenner +brent +bresaola +bresaolas +brest +bretagne +brethren +breton +bretons +breughel +breve +breves +brevet +brevetcy +breveted +breveting +brevets +brevetted +brevetting +breviaries +breviary +brevity +brew +brewage +brewages +brewed +brewer +breweries +brewers +brewery +brewing +brewpub +brewpubs +brews +briand +briar +briard +briards +briarroot +briarroots +briars +briarwood +briarwoods +bribable +bribe +bribed +bribee +bribees +briber +briberies +bribers +bribery +bribes +bribing +brick +brickbat +brickbats +bricked +bricking +bricklayer +bricklayers +bricklaying +brickle +bricks +brickwork +bricky +brickyard +brickyards +bricolage +bricolages +bridal +bridals +bride +bridegroom +bridegrooms +brides +brideshead +bridesmaid +bridesmaids +bridewell +bridewells +bridge +bridgeable +bridgeboard +bridgeboards +bridged +bridgehead +bridgeheads +bridgeless +bridgeport +bridges +bridgetown +bridgework +bridging +bridie +bridle +bridled +bridler +bridlers +bridles +bridling +brie +brief +briefcase +briefcases +briefed +briefer +briefers +briefest +briefing +briefings +briefless +briefly +briefness +briefs +brier +briers +briery +bries +brig +brigade +brigaded +brigades +brigadier +brigadiers +brigading +brigadoon +brigand +brigandage +brigandine +brigandines +brigandism +brigands +brigantine +brigantines +bright +brighten +brightened +brightener +brighteners +brightening +brightens +brighter +brightest +brightly +brightness +brightwork +brightworks +brigs +brill +brilliance +brilliancy +brilliant +brilliantine +brilliantly +brilliantness +brilliants +brills +brim +brimful +brimless +brimmed +brimmer +brimmers +brimming +brims +brimstone +brimstones +brinded +brindisi +brindle +brindled +brindles +brine +brined +brinell +briner +briners +brines +bring +bringdown +bringdowns +bringer +bringers +bringing +brings +brinier +briniest +brininess +brining +brink +brinkmanship +brinksmanship +briny +brio +brioche +brioches +briolette +briolettes +briquet +briquets +briquette +briquetted +briquettes +briquetting +brisance +brisances +brisant +brisbane +brisk +brisker +briskest +brisket +briskets +briskly +briskness +brisling +brislings +bristle +bristlecone +bristled +bristlelike +bristles +bristletail +bristletails +bristlier +bristliest +bristling +bristly +bristol +bristols +brit +britain +britannia +britannic +britannica +britches +briticism +briticisms +british +britisher +britishers +britishness +briton +britons +brits +britt +brittany +britten +brittle +brittlebush +brittlebushes +brittlely +brittleness +brittler +brittlest +brittonic +britts +brno +bro +broach +broached +broacher +broachers +broaches +broaching +broad +broadax +broadaxe +broadaxes +broadband +broadcast +broadcasted +broadcaster +broadcasters +broadcasting +broadcastings +broadcasts +broadcloth +broaden +broadened +broadener +broadeners +broadening +broadens +broader +broadest +broadleaf +broadloom +broadlooms +broadly +broadminded +broadmindedly +broadmindedness +broadness +broads +broadsheet +broadsheets +broadside +broadsided +broadsides +broadsiding +broadsword +broadswords +broadtail +broadtails +broadway +brobdingnag +brobdingnagian +brobdingnagians +brocade +brocaded +brocades +brocatel +brocatelle +brocatelles +brocatels +broccoli +brochette +brochettes +brochure +brochures +brock +brockage +brockages +brocket +brockets +brocks +brogan +brogans +brogue +brogues +broider +broidered +broidering +broiders +broidery +broil +broiled +broiler +broilers +broiling +broils +broke +broken +brokenhearted +brokenheartedly +brokenly +brokenness +broker +brokerage +brokerages +brokered +brokering +brokers +brollies +brolly +bromate +bromated +bromates +bromating +brome +bromegrass +bromegrasses +bromelain +bromelains +bromeliad +bromeliads +bromelin +bromelins +bromes +bromic +bromide +bromides +bromidic +brominate +brominated +brominates +brominating +bromination +bromine +bromism +bromo +bromos +bronc +bronchi +bronchia +bronchial +bronchially +bronchiectasis +bronchiolar +bronchiole +bronchioles +bronchitic +bronchitis +bronchium +broncho +bronchodilator +bronchodilators +bronchopneumonia +bronchos +bronchoscope +bronchoscopes +bronchoscopic +bronchoscopically +bronchoscopist +bronchoscopists +bronchoscopy +bronchus +bronco +broncobuster +broncobusters +broncos +broncs +brontosaur +brontosaurs +brontosaurus +brontosauruses +brontë +brontës +bronx +bronze +bronzed +bronzer +bronzers +bronzes +bronzing +bronzy +brooch +brooches +brood +brooded +brooder +brooders +broodier +broodiest +broodiness +brooding +broodingly +broods +broody +brook +brooked +brookie +brookies +brooking +brookite +brookites +brooklet +brooklets +brooklime +brooklimes +brooklyn +brooklynese +brooks +broom +broomball +broomballer +broomballers +broomcorn +broomcorns +broomed +brooming +broomrape +broomrapes +brooms +broomstick +broomsticks +broomtail +broomtails +broomy +bros +brose +broses +broth +brothel +brothels +brother +brotherhood +brotherhoods +brotherliness +brotherly +brothers +broths +brougham +broughams +brought +brouhaha +brouhahas +brow +browallia +browallias +browbeat +browbeaten +browbeater +browbeaters +browbeating +browbeats +brown +browne +browned +browner +brownest +brownian +brownie +brownies +browning +brownings +brownish +brownness +brownnose +brownnosed +brownnoser +brownnosers +brownnoses +brownnosing +brownout +brownouts +browns +brownshirt +brownshirts +brownstone +brownstones +browny +browridge +brows +browse +browsed +browser +browsers +browses +browsing +bruce +brucella +brucellae +brucellas +brucellosis +brucine +brucines +bruckner +brueghel +bruges +bruin +bruins +bruise +bruised +bruiser +bruisers +bruises +bruising +bruit +bruited +bruiting +bruits +brulee +brulé +brulés +brumal +brumbies +brumby +brume +brumes +brummagem +brummell +brumous +brunch +brunched +brunches +brunching +brunei +bruneian +bruneians +brunel +brunelleschi +brunet +brunets +brunette +brunettes +brunhild +brunizem +brunswick +brunt +brush +brushability +brushback +brushed +brusher +brushers +brushes +brushfire +brushfires +brushier +brushing +brushings +brushland +brushoff +brushstroke +brushstrokes +brushup +brushups +brushwood +brushwork +brushy +brusk +brusque +brusquely +brusqueness +brusquer +brusquerie +brusqueries +brusquest +brussels +brut +brutal +brutalism +brutalist +brutalists +brutalities +brutality +brutalization +brutalize +brutalized +brutalizes +brutalizing +brutally +brute +brutes +brutish +brutishly +brutishness +brutism +brutum +brutus +bruxelles +bruxism +bruxisms +brynhild +bryological +bryologist +bryologists +bryology +bryonies +bryony +bryophyllum +bryophyta +bryophyte +bryophytes +bryophytic +bryozoa +bryozoan +bryozoans +brython +brythonic +brythons +brzezinski +brûlée +brûlées +bub +bubbies +bubble +bubbled +bubblegum +bubblehead +bubbleheaded +bubbleheads +bubbler +bubblers +bubbles +bubblier +bubblies +bubbliest +bubbling +bubbly +bubby +bubo +buboes +bubonic +bubonocele +bubonoceles +buccal +buccally +buccaneer +buccaneering +buccaneerish +buccaneers +buccinator +bucco +bucephalus +bucer +bucharest +buchenwald +buchu +buchus +buck +buckaroo +buckaroos +buckbean +buckbeans +buckboard +buckboards +bucked +bucker +buckeroo +buckers +bucket +bucketed +bucketful +bucketfuls +bucketing +buckets +bucketsful +buckeye +buckeyes +buckhorn +buckhorns +buckhound +buckhounds +bucking +buckinghamshire +buckjump +buckjumped +buckjumper +buckjumpers +buckjumping +buckjumps +buckle +buckled +buckler +bucklered +bucklering +bucklers +buckles +buckley's +buckling +buckminsterfullerene +buckminsterfullerenes +bucko +buckoes +buckram +buckramed +buckraming +buckrams +bucks +bucksaw +bucksaws +buckshee +buckshees +buckshot +buckskin +buckskinned +buckskins +bucktail +bucktails +buckteeth +buckthorn +buckthorns +bucktooth +bucktoothed +buckwheat +buckyball +buckyballs +buco +bucolic +bucolically +bucolics +bud +budapest +budded +budder +budders +buddha +buddhahood +buddhas +buddhism +buddhist +buddhistic +buddhistical +buddhists +buddied +buddies +budding +buddle +buddleia +buddleias +buddles +buddy +buddying +budge +budged +budgerigar +budgerigars +budges +budget +budgetary +budgeted +budgeteer +budgeteers +budgeter +budgeters +budgeting +budgets +budgie +budgies +budging +buds +budworm +budworms +buenos +buff +buffa +buffalo +buffaloberry +buffaloed +buffaloes +buffaloing +buffed +buffer +buffered +buffering +buffers +buffet +buffeted +buffeter +buffeters +buffeting +buffetings +buffets +buffi +buffing +bufflehead +buffleheads +buffo +buffoon +buffoonery +buffoonish +buffoons +buffos +buffs +bug +bugaboo +bugaboos +bugbane +bugbanes +bugbear +bugbears +bugeye +bugeyes +bugged +bugger +buggered +buggering +buggers +buggery +buggier +buggies +buggiest +bugginess +bugging +buggy +bughouse +bughouses +bugle +bugled +bugler +buglers +bugles +bugleweed +bugleweeds +bugling +bugloss +buglosses +bugs +buhl +buhls +buhrstone +buhrstones +buick +buicks +build +buildable +builddown +builddowns +builded +builder +builderer +builderers +buildering +builders +building +buildings +builds +buildup +buildups +built +buirdly +bujumbura +bukhara +bulawayo +bulb +bulbar +bulbed +bulbel +bulbels +bulbiferous +bulbil +bulbils +bulblet +bulblets +bulbourethral +bulbous +bulbously +bulbs +bulbul +bulbuls +bulgar +bulgaria +bulgarian +bulgarians +bulgars +bulge +bulged +bulges +bulgier +bulgiest +bulginess +bulging +bulgur +bulgy +bulimarexia +bulimarexias +bulimia +bulimic +bulk +bulked +bulkhead +bulkheads +bulkier +bulkiest +bulkily +bulkiness +bulking +bulks +bulky +bull +bulla +bullace +bullaces +bullae +bullate +bullbaiting +bullbat +bullbats +bullboat +bullboats +bulldog +bulldogged +bulldogger +bulldoggers +bulldogging +bulldogs +bulldoze +bulldozed +bulldozer +bulldozers +bulldozes +bulldozing +bulled +bullet +bulleted +bulletin +bulletined +bulleting +bulletining +bulletins +bulletproof +bulletproofed +bulletproofing +bulletproofs +bullets +bullfight +bullfighter +bullfighters +bullfighting +bullfights +bullfinch +bullfinches +bullfrog +bullfrogs +bullhead +bullheaded +bullheadedly +bullheadedness +bullheads +bullhorn +bullhorns +bullied +bullies +bulling +bullion +bullish +bullishly +bullishness +bullism +bullmastiff +bullmastiffs +bullnecked +bullock +bullocks +bullocky +bullous +bullpen +bullpens +bullring +bullrings +bullroarer +bullroarers +bullrush +bullrushes +bulls +bullshat +bullshit +bullshits +bullshitted +bullshitter +bullshitters +bullshitting +bullshot +bullterrier +bullterriers +bullwhacker +bullwhackers +bullwhip +bullwhipped +bullwhipping +bullwhips +bully +bullyboy +bullyboys +bullying +bullyrag +bullyragged +bullyragging +bullyrags +bulrush +bulrushes +bulwark +bulwarked +bulwarking +bulwarks +bulwer +bum +bumbershoot +bumbershoots +bumble +bumblebee +bumblebees +bumbled +bumbler +bumblers +bumbles +bumbling +bumblingly +bumboat +bumboats +bumf +bumkin +bumkins +bummalo +bummalos +bummed +bummer +bummers +bumming +bump +bumped +bumper +bumpers +bumph +bumpier +bumpiest +bumpily +bumpiness +bumping +bumpkin +bumpkinish +bumpkinly +bumpkins +bumps +bumptious +bumptiously +bumptiousness +bumpy +bums +bun +buna +bunas +bunch +bunchberries +bunchberry +bunched +bunches +bunchflower +bunchflowers +bunchgrass +bunchgrasses +bunchily +bunchiness +bunching +bunchy +bunco +buncoed +buncoing +buncombe +buncos +bund +bundist +bundists +bundle +bundled +bundler +bundlers +bundles +bundling +bunds +bung +bungalow +bungalows +bunged +bungee +bunghole +bungholes +bunging +bungle +bungled +bungler +bunglers +bungles +bunglesome +bungling +bunglingly +bungs +bunion +bunions +bunk +bunked +bunker +bunkered +bunkering +bunkerings +bunkers +bunkhouse +bunkhouses +bunking +bunkmate +bunkmates +bunko +bunkos +bunkroom +bunkrooms +bunks +bunkum +bunnies +bunny +bunraku +buns +bunsen +bunt +bunted +bunter +bunters +bunting +buntings +buntline +buntlines +bunts +bunyan +bunyanesque +bunyip +bunyips +buoy +buoyance +buoyances +buoyancy +buoyant +buoyantly +buoyed +buoying +buoys +buppie +buppies +buprestid +buprestids +bur +buran +burans +burbage +burberry +burble +burbled +burbler +burblers +burbles +burbling +burbly +burbot +burbots +burbs +burden +burdened +burdening +burdens +burdensome +burdensomely +burdensomeness +burdock +burdocks +bureau +bureaucracies +bureaucracy +bureaucrat +bureaucratese +bureaucrateses +bureaucratic +bureaucratically +bureaucratism +bureaucratization +bureaucratize +bureaucratized +bureaucratizes +bureaucratizing +bureaucrats +bureaus +bureaux +buret +burets +burette +burettes +burg +burgage +burgages +burgee +burgees +burgeon +burgeoned +burgeoning +burgeons +burger +burgers +burgess +burgesses +burgh +burghal +burgher +burghers +burghley +burghs +burglar +burglaries +burglarious +burglariously +burglarize +burglarized +burglarizes +burglarizing +burglarproof +burglarproofed +burglarproofing +burglarproofs +burglars +burglary +burgle +burgled +burgles +burgling +burgomaster +burgomasters +burgonet +burgonets +burgoo +burgoos +burgos +burgs +burgundian +burgundians +burgundies +burgundy +burial +burials +buried +burier +buriers +buries +burin +burins +burke +burked +burkes +burkina +burkinese +burking +burkitt +burl +burladero +burladeros +burlap +burlaps +burled +burleigh +burler +burlers +burlesque +burlesqued +burlesquely +burlesquer +burlesquers +burlesques +burlesquing +burley +burleys +burlier +burlies +burliest +burlily +burliness +burling +burls +burly +burma +burman +burmans +burmese +burn +burnable +burned +burner +burners +burnet +burnets +burning +burningly +burnings +burnish +burnished +burnisher +burnishers +burnishes +burnishing +burnoose +burnoosed +burnooses +burnous +burnouses +burnout +burnouts +burns +burnsides +burnt +burp +burped +burping +burps +burr +burred +burrer +burrers +burrier +burriest +burring +burrito +burritos +burro +burros +burrow +burrowed +burrower +burrowers +burrowing +burrows +burrs +burrstone +burrstones +burry +burs +bursa +bursae +bursal +bursar +bursarial +bursaries +bursars +bursary +bursas +burse +burses +bursitis +burst +bursted +burster +bursters +bursting +bursts +burthen +burthens +burton +burtons +burundi +burundian +burundians +burweed +burweeds +bury +burying +bus +busbies +busboy +busboys +busby +bused +buses +bush +bushbuck +bushbucks +bushed +bushel +busheled +busheler +bushelers +busheling +bushelman +bushels +bushes +bushfire +bushfires +bushido +bushidos +bushier +bushiest +bushily +bushiness +bushing +bushings +bushland +bushlands +bushman +bushmaster +bushmasters +bushmen +bushmills +bushnell +bushpig +bushpigs +bushranger +bushrangers +bushranging +bushtit +bushtits +bushwhack +bushwhacked +bushwhacker +bushwhackers +bushwhacking +bushwhacks +bushy +busied +busier +busies +busiest +busily +business +businesses +businesslike +businessman +businessmen +businesspeople +businessperson +businesspersons +businesswoman +businesswomen +busing +busk +busked +busker +buskers +buskin +busking +buskins +busks +busload +busloads +busman +busman's +busmen +buss +bussed +busses +bussing +bust +bustard +bustards +busted +buster +busters +busticate +busticated +busticates +busticating +bustier +bustiers +bustiest +busting +bustle +bustled +bustles +bustline +bustling +bustlingly +busts +busty +busulfan +busulfans +busy +busybodies +busybody +busying +busyness +busywork +but +butadiene +butane +butanes +butanol +butanols +butanone +butanones +butazolidin +butch +butcher +butcherbird +butcherbirds +butchered +butcherer +butcherers +butcheries +butchering +butcherly +butchers +butchery +butches +bute +butene +butenes +buteo +buteos +butler +butlers +butoxide +buts +butt +butte +butted +butter +butterball +butterballs +butterbur +butterburs +buttercup +buttercups +buttered +butterfat +butterfingered +butterfingers +butterfish +butterfishes +butterflied +butterflies +butterfly +butterflyer +butterflyers +butterflying +butteries +butteriness +buttering +butterless +buttermilk +buttermilks +butternut +butternuts +butters +butterscotch +butterweed +butterweeds +butterwort +butterworts +buttery +buttes +butties +butting +buttinski +buttinskies +buttinsky +buttock +buttocks +button +buttonball +buttonballs +buttonbush +buttonbushes +buttoned +buttoner +buttoners +buttonhole +buttonholed +buttonholer +buttonholers +buttonholes +buttonholing +buttonhook +buttonhooks +buttoning +buttonless +buttonmold +buttonmolds +buttonquail +buttonquails +buttons +buttonwood +buttonwoods +buttony +buttress +buttressed +buttresses +buttressing +butts +buttstock +buttstocks +butty +butut +bututs +butyl +butylate +butylated +butylates +butylating +butylation +butylene +butylenes +butyls +butyraceous +butyraldehyde +butyraldehydes +butyrate +butyrates +butyric +butyrin +butyrins +butyrophenone +butyrophenones +butyrophenoness +buxom +buxomly +buxomness +buxtehude +buy +buyable +buyback +buybacks +buyer +buyers +buying +buyout +buyouts +buys +buzz +buzzard +buzzards +buzzed +buzzer +buzzers +buzzes +buzzing +buzzword +buzzwords +bwana +bwanas +by +bye +byelaw +byelaws +byelorussia +byelorussian +byelorussians +byes +bygone +bygones +bylaw +bylaws +byline +bylined +byliner +byliners +bylines +bylining +byname +bynames +bypass +bypassed +bypasses +bypassing +bypast +bypath +bypaths +byplay +byplays +byproduct +byproducts +byre +byres +byroad +byroads +byron +byronic +byssi +byssinosis +byssus +byssuses +bystander +bystanders +bystreet +bystreets +byte +bytes +byway +byways +byword +bywords +byzantine +byzantines +byzantium +béarn +béarnaise +béchamel +béchamels +bêche +bêches +bête +bêtes +bêtise +bêtises +c +c'mon +cab +cabal +cabala +cabalas +cabaletta +cabalettas +cabalette +cabalism +cabalist +cabalistic +cabalistically +cabalists +caballed +caballero +caballeros +caballing +cabals +cabana +cabanas +cabaret +cabarets +cabaña +cabañas +cabbage +cabbages +cabbageworm +cabbageworms +cabbagy +cabbed +cabbie +cabbies +cabbing +cabby +cabdriver +cabdrivers +caber +cabernet +cabernets +cabers +cabin +cabined +cabinet +cabinetful +cabinetmaker +cabinetmakers +cabinetmaking +cabinetry +cabinets +cabinetwork +cabining +cabins +cable +cablecast +cablecaster +cablecasters +cablecasts +cabled +cablegram +cablegrams +cabler +cablers +cables +cablet +cablets +cablevision +cableway +cableways +cabling +cabman +cabmen +cabochon +cabochons +caboclo +caboclos +cabomba +cabombas +caboodle +caboose +cabooses +cabot +cabotage +cabotages +cabretta +cabrettas +cabrilla +cabrillas +cabriole +cabrioles +cabriolet +cabriolets +cabs +cabstand +cabstands +cacao +cacaos +cachaca +cachalot +cachalots +cachaça +cache +cachectic +cached +cachepot +cachepots +caches +cachet +cachets +cachexia +cachexias +caching +cachinnate +cachinnated +cachinnates +cachinnating +cachinnation +cachinnator +cachinnators +cachou +cachous +cachucha +cachuchas +cacique +caciques +cackle +cackled +cackler +cacklers +cackles +cackling +cacodemon +cacodemons +cacodyl +cacodylic +cacodyls +cacography +cacomistle +cacomistles +caconym +caconyms +caconymy +cacophonic +cacophonies +cacophonous +cacophonously +cacophony +cacoëthes +cacti +cactus +cactuses +cacuminal +cad +cadastral +cadastre +cadaver +cadaveric +cadaverine +cadaverines +cadaverous +cadaverously +cadaverousness +cadavers +caddie +caddied +caddies +caddis +caddish +caddishly +caddishness +caddo +caddoan +caddoans +caddos +caddy +caddying +cade +cadelle +cadelles +cadence +cadenced +cadences +cadencies +cadency +cadent +cadential +cadenza +cadenzas +cadet +cadets +cadetship +cadge +cadged +cadger +cadgers +cadges +cadging +cadillac +cadillacs +cadiz +cadmic +cadmium +cadmus +cadre +cadres +cads +caducean +caducei +caduceus +caducity +caducous +caecilian +caecilians +caelian +caelum +caerphillies +caerphilly +caesar +caesarea +caesarean +caesareans +caesarian +caesarians +caesarism +caesarist +caesaristic +caesarists +caesars +caesura +caesurae +caesural +caesuras +caesuric +cafe +cafes +cafeteria +cafeterias +cafetoria +cafetorium +cafetoriums +caffeinated +caffeine +caffeinism +caftan +caftans +café +cafés +cage +caged +cagelike +cageling +cagelings +cages +cagey +cageyness +cagier +cagiest +cagily +caginess +caging +cagliari +cahier +cahiers +cahoots +cahow +cahows +cahuilla +cahuillas +caicos +caiman +caimans +cain +cainotophobia +cainotophobias +caird +cairds +cairn +cairned +cairngorm +cairns +cairo +caisson +caissons +caitiff +caitiffs +cajan +cajans +cajole +cajoled +cajoler +cajolers +cajolery +cajoles +cajoling +cajolingly +cajun +cajuns +cake +caked +cakes +cakewalk +cakewalked +cakewalker +cakewalkers +cakewalking +cakewalks +caking +calabash +calabashes +calaboose +calabooses +calabrese +calabreses +calabria +calabrian +calabrians +caladium +calais +calamanco +calamancoes +calamander +calamanders +calamari +calamaries +calamary +calami +calamine +calamint +calamints +calamite +calamites +calamities +calamitous +calamitously +calamitousness +calamity +calamondin +calamondins +calamus +calando +calash +calashes +calathea +calatheas +calathi +calathus +calcanea +calcaneal +calcanei +calcaneocuboid +calcaneum +calcaneus +calcar +calcareous +calcareously +calcaria +calceolaria +calceolarias +calceolate +calcic +calcicole +calcicoles +calcicolous +calciferol +calciferols +calciferous +calcific +calcification +calcifications +calcified +calcifies +calcifugal +calcifuge +calcifugous +calcify +calcifying +calcimine +calcimined +calciminer +calciminers +calcimines +calcimining +calcination +calcine +calcined +calcines +calcining +calcinosis +calcite +calcitic +calcitonin +calcitonins +calcium +calcspar +calcspars +calculability +calculable +calculably +calculate +calculated +calculatedly +calculates +calculating +calculatingly +calculation +calculations +calculative +calculator +calculators +calculi +calculous +calculus +calculuses +calcutta +caldera +calderas +caldron +caldrons +caledonia +caledonian +caledonians +calendal +calendar +calendared +calendaring +calendars +calender +calendered +calenderer +calenderers +calendering +calenders +calendric +calendrical +calends +calendula +calendulas +calenture +calentures +calf +calfskin +calgarian +calgarians +calgary +caliban +caliber +calibers +calibrate +calibrated +calibrates +calibrating +calibration +calibrations +calibrator +calibrators +calices +caliche +caliches +calico +calicoback +calicobacks +calicoes +calicos +calicut +california +californian +californians +californite +californites +californium +caliginous +caligula +calinago +calinagos +calipash +calipashes +calipee +calipees +caliper +calipered +calipering +calipers +caliph +caliphate +caliphates +caliphs +calisthenic +calisthenics +calix +calk +calked +calking +calks +call +calla +callable +callback +callbacks +callboard +callboards +callboy +callboys +called +caller +callers +calligrapher +calligraphers +calligraphic +calligraphist +calligraphy +calling +callings +calliope +calliopes +calliopsis +callipygian +callisthenes +callisto +callose +calloses +callosities +callosity +callous +calloused +callouses +callousing +callously +callousness +callow +callowness +calls +callus +callused +calluses +callusing +calm +calmative +calmed +calmer +calmest +calming +calmly +calmness +calms +calomel +caloreceptor +caloreceptors +caloric +calorically +calorie +calories +calorific +calorifically +calorimeter +calorimeters +calorimetric +calorimetrically +calorimetry +calotte +calottes +calpac +calpacs +calque +calques +caltrop +caltrops +calumet +calumets +calumniate +calumniated +calumniates +calumniating +calumniation +calumniations +calumniator +calumniators +calumniatory +calumnies +calumnious +calumniously +calumny +calvados +calvarium +calvariums +calvary +calve +calved +calves +calvin +calving +calvinism +calvinist +calvinistic +calvinistical +calvinistically +calvinists +calx +calxes +calyces +calycine +calycular +calyculate +calyculi +calyculus +calypso +calypsos +calyptra +calyptrate +calyx +calyxes +calèche +cam +camaraderie +camargue +camarilla +camarillas +camas +camber +cambered +cambering +cambers +cambia +cambial +cambium +cambiums +cambodia +cambodian +cambodians +cambrai +cambria +cambrian +cambric +cambrics +cambridge +cambridgeshire +camcorder +camcorders +came +camel +camelback +camelbacks +cameleer +cameleers +camellia +camellias +camelopard +camelopardalis +camelot +camels +camembert +cameo +cameoed +cameoing +cameos +camera +camerae +cameral +cameraman +cameramen +cameraperson +camerapersons +cameras +camerawoman +camerawomen +camerawork +camerlingo +camerlingos +cameron +cameroon +cameroonian +cameroonians +cameroons +cameroun +cami +camion +camions +camis +camise +camises +camisole +camisoles +camorra +camouflage +camouflaged +camouflager +camouflagers +camouflages +camouflaging +camp +campaign +campaigned +campaigner +campaigners +campaigning +campaigns +campania +campanile +campaniles +campanologist +campanologists +campanology +campanula +campanulas +campanulate +camped +campeggio +camper +campers +campesino +campesinos +campestral +campfire +campfires +campground +campgrounds +camphene +camphenes +camphor +camphoraceous +camphorate +camphorated +camphorates +camphorating +camphoric +camphorweed +camphorweeds +camping +campion +campions +campo +camporee +camporees +campos +camps +campsite +campsites +campstool +campstools +campus +campuses +campy +campylobacterosis +campylotropous +cams +camshaft +camshafts +can +can't +canaan +canaanite +canaanites +canada +canadian +canadians +canaigre +canaigres +canaille +canal +canaletto +canalicular +canaliculate +canaliculi +canaliculus +canalization +canalize +canalized +canalizes +canalizing +canalled +canalling +canals +canapé +canapés +canard +canards +canaries +canary +canasta +canaveral +canberra +cancan +cancans +cancel +cancelable +canceled +canceler +cancelers +canceling +cancellate +cancellation +cancellations +cancelled +cancelling +cancellous +cancels +cancer +cancerian +cancerians +cancerous +cancers +cancroid +cancroids +cancún +candela +candelabra +candelabras +candelabrum +candelabrums +candelas +candelilla +candelillas +candent +candescence +candescent +candescently +candia +candid +candida +candidacies +candidacy +candidas +candidate +candidates +candidature +candidatures +candidiasis +candidly +candidness +candids +candied +candies +candle +candleberries +candleberry +candled +candlefish +candleholder +candleholders +candlelight +candlelit +candlemas +candlemases +candlenut +candlenuts +candlepin +candlepins +candlepower +candler +candlers +candles +candlesnuffer +candlesnuffers +candlestick +candlesticks +candlewick +candlewicks +candlewood +candlewoods +candling +candor +candy +candying +candytuft +candytufts +cane +canebrake +canebrakes +caned +caner +caners +canes +canescence +canescent +canfield +cangue +cangues +canicular +canid +canids +canine +canines +caning +canistel +canistels +canister +canisters +canker +cankered +cankering +cankerous +cankerroot +cankerroots +cankers +cankerworm +cankerworms +canna +cannabic +cannabidiol +cannabidiols +cannabin +cannabins +cannabis +canned +cannel +cannelloni +cannelure +cannelures +canner +canneries +canners +cannery +cannes +cannibal +cannibalism +cannibalistic +cannibalization +cannibalizations +cannibalize +cannibalized +cannibalizes +cannibalizing +cannibals +cannier +canniest +cannikin +cannikins +cannily +canniness +canning +cannoli +cannon +cannonade +cannonaded +cannonades +cannonading +cannonball +cannonballed +cannonballing +cannonballs +cannoned +cannoneer +cannoneers +cannoning +cannonries +cannonry +cannons +cannot +cannula +cannular +cannulas +cannulate +cannulated +cannulates +cannulating +cannulation +canny +canoe +canoed +canoeing +canoeist +canoeists +canoes +canola +canolas +canon +canoness +canonesses +canonic +canonical +canonically +canonicals +canonicate +canonicates +canonicity +canonist +canonistic +canonistical +canonists +canonization +canonizations +canonize +canonized +canonizer +canonizers +canonizes +canonizing +canonries +canonry +canons +canoodle +canoodled +canoodles +canoodling +canopic +canopied +canopies +canopus +canopy +canopying +canorous +canorously +canorousness +cans +cant +cantabile +cantabiles +cantabrigian +cantabrigians +cantala +cantalas +cantaloupe +cantaloupes +cantankerous +cantankerously +cantankerousness +cantata +cantatas +canted +canteen +canteens +canter +canterbury +cantered +cantering +canters +cantharides +cantharis +canthi +canthitis +canthus +canticle +canticles +cantilated +cantilates +cantilating +cantilena +cantilenas +cantilever +cantilevered +cantilevering +cantilevers +cantillate +cantillation +cantina +cantinas +canting +cantingly +cantingness +cantle +cantles +canto +canton +cantonal +cantonese +cantonment +cantonments +cantons +cantor +cantorial +cantors +cantos +cants +canuck +canucks +canute +canvas +canvasback +canvasbacks +canvases +canvass +canvassed +canvasser +canvassers +canvasses +canvassing +canyon +canyons +canzone +canzones +canzonet +canzonets +caoutchouc +caoutchoucs +cap +capabilities +capability +capable +capableness +capably +capacious +capaciously +capaciousness +capacitance +capacitances +capacitate +capacitated +capacitates +capacitating +capacitation +capacities +capacitive +capacitively +capacitor +capacitors +capacity +caparison +caparisoned +caparisoning +caparisons +cape +caped +capelin +capelins +capella +caper +capercaillie +capercaillies +capered +capering +capers +capes +capeskin +capeskins +capet +capetian +capetians +capful +capfuls +capias +capiases +capillaries +capillarities +capillarity +capillary +capita +capital +capitalism +capitalist +capitalistic +capitalistically +capitalists +capitalizable +capitalization +capitalizations +capitalize +capitalized +capitalizes +capitalizing +capitally +capitals +capitate +capitation +capitations +capitative +capitella +capitellum +capitol +capitoline +capitols +capitula +capitulant +capitular +capitularies +capitularly +capitulary +capitulate +capitulated +capitulates +capitulating +capitulation +capitulations +capitulator +capitulators +capitulatory +capitulum +caplet +caplets +capo +capon +caponata +caponatas +caponize +caponized +caponizes +caponizing +capons +caporal +caporals +capos +capote +capotes +cappadocia +cappadocian +cappadocians +capped +cappella +capper +cappers +capping +cappuccino +cappuccinos +capreomycin +capreomycins +capri +capriccio +capriccios +capriccioso +caprice +caprices +capricious +capriciously +capriciousness +capricorn +capricornian +capricornians +capricorns +caprification +caprifications +caprifig +caprifigs +capriole +caprioled +caprioles +caprioling +capris +caps +capsaicin +capsaicins +capsian +capsicum +capsicums +capsid +capsids +capsize +capsized +capsizes +capsizing +capsomere +capsomeres +capstan +capstans +capstone +capstones +capsular +capsulate +capsulated +capsulation +capsule +capsuled +capsules +capsuling +capsulize +capsulized +capsulizes +capsulizing +capsulotomies +capsulotomy +captain +captaincies +captaincy +captained +captaining +captains +captainship +captan +captans +caption +captioned +captioning +captions +captious +captiously +captiousness +captivate +captivated +captivates +captivating +captivatingly +captivation +captivator +captivators +captive +captives +captivities +captivity +captopril +captoprils +captor +captors +capture +captured +captures +capturing +capuche +capuches +capuchin +capuchins +capulet +capulets +capybara +capybaras +car +carabao +carabaos +carabid +carabids +carabineer +carabineers +carabiner +carabiners +carabiniere +carabinieri +caracal +caracalla +caracals +caracara +caracaras +caracas +caracole +caracoled +caracoles +caracoling +caractacus +caradoc +carafe +carafes +carambola +carambolas +caramel +caramelization +caramelize +caramelized +caramelizes +caramelizing +caramels +carangid +carangids +carapace +carapaces +carat +caratacus +carats +caravaggio +caravan +caravans +caravansaries +caravansary +caravel +caravels +caraway +caraways +carbamate +carbamates +carbamazepine +carbamazepines +carbamide +carbamides +carbamoyl +carbamoyls +carbanion +carbanions +carbaryl +carbaryls +carbenicillin +carbenicillins +carbide +carbides +carbine +carbines +carbinol +carbinols +carbocyclic +carbohydrase +carbohydrases +carbohydrate +carbohydrates +carbolated +carbolic +carbon +carbonaceous +carbonado +carbonadoed +carbonadoes +carbonadoing +carbonados +carbonara +carbonaras +carbonate +carbonated +carbonates +carbonating +carbonation +carbonator +carbonators +carbonic +carboniferous +carbonium +carboniums +carbonization +carbonize +carbonized +carbonizer +carbonizers +carbonizes +carbonizing +carbonous +carbons +carbonyl +carbonylic +carbonyls +carborane +carboranes +carborundum +carboxyhemoglobin +carboxyhemoglobins +carboxyl +carboxylase +carboxylases +carboxylation +carboxylations +carboxylic +carboxymethylcellulose +carboxymethylcelluloses +carboxypeptidase +carboxypeptidases +carboy +carboys +carbuncle +carbuncled +carbuncles +carbuncular +carburet +carbureted +carbureting +carburetion +carburetor +carburetors +carburets +carburization +carburize +carburized +carburizes +carburizing +carcajou +carcajous +carcanet +carcanets +carcass +carcasses +carcassonne +carcinogen +carcinogenesis +carcinogenic +carcinogenicity +carcinogens +carcinoid +carcinoids +carcinoma +carcinomas +carcinomatoid +carcinomatosis +carcinomatous +card +cardamom +cardamoms +cardboard +carded +cardholder +cardholders +cardholding +cardia +cardiac +cardiacs +cardiae +cardialgia +cardialgias +cardiff +cardigan +cardigans +cardinal +cardinalate +cardinalates +cardinalities +cardinality +cardinals +cardinalship +carding +cardioacceleration +cardioaccelerator +cardioaccelerators +cardiogenic +cardiogram +cardiograms +cardiograph +cardiographs +cardiography +cardioid +cardioids +cardiological +cardiologist +cardiologists +cardiology +cardiomegaly +cardiomyopathies +cardiomyopathy +cardiopathies +cardiopathy +cardiopulmonary +cardiorespiratory +cardiothoracic +cardiovascular +carditis +carditises +cardoon +cardoons +cards +cardsharp +cardsharper +cardsharpers +cardsharping +cardsharps +cardstock +care +cared +careen +careened +careener +careeners +careening +careens +career +careered +careering +careerism +careerist +careerists +careers +carefree +careful +carefully +carefulness +caregiver +caregivers +caregiving +careless +carelessly +carelessness +cares +caress +caressed +caresser +caressers +caresses +caressing +caressingly +caressive +caret +caretaker +caretakers +caretaking +carets +careworn +carfare +cargo +cargoes +carhop +carhops +carib +cariban +caribbean +caribbeans +caribe +caribes +caribou +caribous +caribs +caricature +caricatured +caricatures +caricaturing +caricaturist +caricaturists +caries +carillon +carillonned +carillonneur +carillonneurs +carillonning +carillons +carina +carinae +carinate +caring +carinthia +carioca +cariocan +cariocas +cariole +carioles +cariosity +carious +cariousness +cark +carked +carking +carks +carl +carling +carlings +carlisle +carlist +carlists +carlo +carload +carloads +carlos +carls +carlsbad +carlyle +carmaker +carmakers +carmel +carmelite +carmelites +carmen +carminative +carminatives +carmine +carnac +carnage +carnal +carnality +carnallite +carnallites +carnally +carnassial +carnassials +carnation +carnations +carnauba +carne +carnegie +carnelian +carnelians +carnet +carnets +carnies +carniola +carniolan +carniolans +carnitine +carnitines +carnival +carnivals +carnivore +carnivores +carnivorous +carnivorously +carnivorousness +carnotite +carnotites +carny +carob +carobs +caroche +caroches +carol +carolean +caroled +caroler +carolers +carolina +carolinas +caroline +caroling +carolingian +carolingians +carolinian +carolinians +carols +carom +caromed +caroming +caroms +carotene +carotenemia +carotenemias +carotenoid +carotenoids +carotid +carotids +carousal +carousals +carouse +caroused +carousel +carousels +carouser +carousers +carouses +carousing +carp +carpaccio +carpaccios +carpal +carpals +carpathian +carpathians +carpe +carped +carpel +carpellary +carpellate +carpels +carpentaria +carpenter +carpentered +carpentering +carpenters +carpentry +carper +carpers +carpet +carpetbag +carpetbagger +carpetbaggers +carpetbaggery +carpetbags +carpeted +carpeting +carpetings +carpets +carpetweed +carpetweeds +carpi +carping +carpingly +carpool +carpooling +carpools +carpophagous +carpophore +carpophores +carport +carports +carps +carpus +carrack +carracks +carrageen +carrageenan +carrantuohill +carrara +carrefour +carrefours +carrel +carrels +carreras +carriage +carriages +carried +carrier +carriers +carries +carrion +carroll +carrot +carrots +carroty +carrousel +carrousels +carry +carryall +carryalls +carrying +carryings +carryon +carryons +carryout +carryouts +carryover +carryovers +cars +carsick +carsickness +cart +carta +cartable +cartage +cartagena +carte +carted +cartel +cartelize +cartelized +cartelizes +cartelizing +cartels +carter +carters +cartesian +cartesianism +cartesians +carthage +carthaginian +carthaginians +carthorse +carthorses +carthusian +carthusians +cartilage +cartilaginous +carting +cartload +cartloads +cartogram +cartograms +cartographer +cartographers +cartographic +cartographical +cartography +carton +cartoned +cartoning +cartons +cartoon +cartooned +cartooning +cartoonish +cartoonist +cartoonists +cartoons +cartop +cartouche +cartouches +cartridge +cartridges +carts +cartularies +cartulary +cartwheel +cartwheels +caruncle +caruncles +caruncular +carunculate +carunculated +caruso +carvacrol +carvacrols +carve +carved +carver +carvers +carves +carving +carvings +caryatid +caryatidal +caryatidean +caryatides +caryatidic +caryatids +caryopses +caryopsis +casaba +casabas +casablanca +casanova +casanovas +casaubon +casbah +cascade +cascaded +cascades +cascading +cascara +cascaras +cascarilla +cascarillas +case +caseate +caseated +caseates +caseating +caseation +caseations +casebook +casebooks +cased +caseharden +casehardened +casehardening +casehardens +casein +caseload +caseloads +casemate +casemated +casemates +casement +casemented +casements +caseous +casern +caserne +casernes +caserns +caserta +cases +casework +caseworker +caseworkers +cash +cashable +cashbook +cashbooks +cashed +casher +cashers +cashes +cashew +cashews +cashier +cashiered +cashiering +cashiers +cashing +cashless +cashmere +cashmeres +casing +casings +casino +casinos +cask +casket +casketed +casketing +caskets +casks +caspian +casque +casqued +casques +cassandra +cassandras +cassation +cassations +cassava +cassavas +casserole +casseroles +cassette +cassettes +cassia +cassias +cassimere +cassina +cassiopeia +cassis +cassiterite +cassius +cassock +cassocked +cassocks +cassoulet +cassoulets +cassowaries +cassowary +cast +castanet +castanets +castaway +castaways +caste +castellan +castellans +castellated +castellation +caster +casters +castes +castigate +castigated +castigates +castigating +castigation +castigations +castigator +castigators +castigatory +castile +castilian +castilians +casting +castings +castle +castled +castlereagh +castles +castling +castoff +castoffs +castor +castors +castrate +castrated +castrater +castraters +castrates +castrati +castrating +castration +castrations +castrato +castrator +castrators +castroism +castroist +castroists +casts +casual +casually +casualness +casuals +casualties +casualty +casuarina +casuarinas +casuist +casuistic +casuistically +casuistries +casuistry +casuists +casus +cat +catabolic +catabolically +catabolism +catabolite +catabolites +catabolize +catabolized +catabolizes +catabolizing +catachreses +catachresis +catachrestic +catachrestical +catachrestically +cataclysm +cataclysmal +cataclysmic +cataclysms +catacomb +catacombs +catadromous +catafalque +catafalques +catalan +catalans +catalase +catalases +catalatic +catalectic +catalepsies +catalepsy +cataleptic +cataleptics +catalexis +catalog +cataloged +cataloger +catalogers +cataloging +catalogs +catalogue +catalogued +cataloguer +cataloguers +catalogues +cataloguing +catalonia +catalonian +catalonians +catalpa +catalpas +catalyses +catalysis +catalyst +catalysts +catalytic +catalytically +catalyze +catalyzed +catalyzer +catalyzers +catalyzes +catalyzing +catamaran +catamarans +catamenia +catamenial +catamenias +catamite +catamites +catamount +catamountain +catamountains +catamounts +catania +catanzaro +cataphoresis +cataphoretic +cataphoretically +cataplasia +cataplasias +cataplasm +cataplasms +cataplastic +cataplectic +cataplexies +cataplexy +catapult +catapulted +catapulting +catapults +cataract +cataracts +catarrh +catarrhal +catarrhally +catarrhous +catarrhs +catastases +catastasis +catastrophe +catastrophes +catastrophic +catastrophically +catastrophism +catastrophist +catastrophists +catatonia +catatonic +catatonically +catatonics +catawba +catawbas +catbird +catbirds +catboat +catboats +catbrier +catbriers +catcall +catcalled +catcalling +catcalls +catch +catchable +catchall +catchalls +catcher +catchers +catches +catchflies +catchfly +catchier +catchiest +catchily +catchiness +catching +catchment +catchments +catchpenny +catchphrase +catchphrases +catchpole +catchpoles +catchword +catchwords +catchy +catecheses +catechesis +catechetical +catechin +catechins +catechism +catechisms +catechist +catechistic +catechistical +catechists +catechization +catechize +catechized +catechizer +catechizers +catechizes +catechizing +catechol +catecholamine +catecholamines +catechols +catechu +catechumen +catechumens +catechus +categoric +categorical +categorically +categoricalness +categories +categorizable +categorization +categorizations +categorize +categorized +categorizes +categorizing +category +catena +catenae +catenaries +catenary +catenate +catenated +catenates +catenating +catenation +cater +catercorner +catercornered +catered +caterer +caterers +catering +caterpillar +caterpillars +caters +caterwaul +caterwauled +caterwauling +caterwauls +catfight +catfights +catfish +catfishes +catgut +cathar +cathari +catharism +catharist +catharists +cathars +catharses +catharsis +cathartic +cathartics +cathay +cathead +catheads +cathect +cathected +cathectic +cathecting +cathects +cathedra +cathedrae +cathedral +cathedrals +cathepsin +cathepsins +catherine +catheter +catheterization +catheterize +catheterized +catheterizes +catheterizing +catheters +cathexes +cathexis +cathode +cathodes +cathodic +cathodically +catholic +catholically +catholicism +catholicity +catholicize +catholicized +catholicizes +catholicizing +catholicon +catholicons +catholics +cathouse +cathouses +catiline +cation +cationic +cations +catjang +catjangs +catkin +catkins +catlike +catmint +catmints +catnap +catnapped +catnapping +catnaps +catnip +catnips +cato +catoptric +catoptrics +cats +catskill +catskills +catsup +catsups +cattail +cattails +cattalo +cattaloes +cattalos +catted +cattier +cattiest +cattily +cattiness +catting +cattle +cattleman +cattlemen +cattleya +cattleyas +catty +catullus +catwalk +catwalks +caucasian +caucasians +caucasus +caucus +caucused +caucuses +caucusing +caudad +caudal +caudally +caudate +caudation +caudex +caudexes +caudices +caudillismo +caudillo +caudillos +caudle +caudles +caught +caul +cauldron +cauldrons +caulescent +cauliflorous +cauliflory +cauliflower +cauliflowers +cauline +caulk +caulked +caulking +caulkings +caulks +cauls +causable +causal +causalities +causality +causally +causals +causation +causations +causative +causatively +cause +caused +causeless +causer +causerie +causeries +causers +causes +causeway +causeways +causing +caustic +caustically +causticity +caustics +cauteries +cauterization +cauterizations +cauterize +cauterized +cauterizes +cauterizing +cautery +caution +cautionary +cautioned +cautioner +cautioners +cautioning +cautions +cautious +cautiously +cautiousness +cava +cavae +cavalas +cavalcade +cavalcades +cavalier +cavalierly +cavaliers +cavalla +cavalries +cavalry +cavalryman +cavalrymen +cavatelli +cave +caveat +caveated +caveating +caveats +caved +cavefish +cavefishes +caveman +cavemen +caver +cavern +caverned +cavernicolous +caverning +cavernous +cavernously +caverns +cavers +caves +cavetti +cavetto +cavettos +caviar +cavies +cavil +caviled +caviler +cavilers +caviling +cavils +caving +cavitate +cavitated +cavitates +cavitating +cavitation +cavitations +cavities +cavity +cavort +cavorted +cavorting +cavorts +cavour +cavy +caw +cawdor +cawed +cawing +caws +caxton +cay +cayenne +cayman +caymans +cays +cayuga +cayugas +cayuse +cayuses +caïque +caïques +ceanothus +cease +ceased +ceaseless +ceaselessly +ceaselessness +ceases +ceasing +ceca +cecal +cecally +cecil +cecropia +cecum +cedar +cedarbird +cedarbirds +cedars +cede +ceded +cedes +cedi +cedilla +cedillas +ceding +cedis +cee +cees +ceiba +ceibas +ceil +ceiled +ceilidh +ceilidhs +ceiling +ceilinged +ceilings +ceilometer +ceilometers +ceils +celadon +celadonite +celadonites +celadons +celaeno +celandine +celandines +celeb +celebes +celebrant +celebrants +celebrate +celebrated +celebrates +celebrating +celebration +celebrations +celebrator +celebrators +celebratory +celebrities +celebrity +celebrityhood +celebs +celeriac +celeriacs +celeries +celerity +celery +celesta +celestas +celestial +celestially +celestials +celestine +celestines +celestite +celestites +celiac +celibacy +celibate +celibates +cell +cella +cellae +cellar +cellarage +cellarages +cellared +cellarer +cellarers +cellarette +cellarettes +cellaring +cellars +cellblock +cellblocks +celled +celling +cellini +cellist +cellists +cellmate +cellmates +cello +cellobiose +cellobioses +celloidin +celloidins +cellophane +cellos +cells +cellular +cellularity +cellularly +cellulase +cellulases +cellule +cellules +cellulite +cellulitis +celluloid +celluloids +cellulolytic +cellulose +cellulosic +celosia +celosias +celotex +celsius +celt +celtiberian +celtiberians +celtic +celticism +celticisms +celticist +celticists +celtics +celts +cembalist +cembalists +cembalo +cembalos +cement +cementation +cementations +cemented +cementer +cementers +cementing +cementite +cementites +cementitious +cements +cementum +cemeteries +cemetery +cenacle +cenacles +cenobite +cenobites +cenobitic +cenobitical +cenospecies +cenotaph +cenotaphic +cenotaphs +cenozoic +cense +censed +censer +censers +censes +censing +censor +censorable +censored +censorial +censoring +censorious +censoriously +censoriousness +censors +censorship +censurability +censurable +censurableness +censurably +censure +censured +censurer +censurers +censures +censuring +census +censuses +cent +cental +centals +centaur +centauries +centaurs +centaurus +centaury +centavo +centavos +centenarian +centenarians +centenaries +centenary +centennial +centennially +centennials +center +centerboard +centerboards +centered +centeredly +centeredness +centerfold +centerfolds +centering +centerline +centerlines +centermost +centerpiece +centerpieces +centers +centesimal +centesimally +centesimi +centesimo +centesimos +centiampere +centiamperes +centibecquerel +centibecquerels +centicandela +centicandelas +centicoulomb +centicoulombs +centifarad +centifarads +centigrade +centigram +centigrams +centihenries +centihenry +centihenrys +centihertz +centijoule +centijoules +centikelvin +centikelvins +centiliter +centiliters +centilumen +centilumens +centilux +centime +centimes +centimeter +centimeters +centimo +centimole +centimoles +centimos +centinewton +centinewtons +centiohm +centiohms +centipascal +centipascals +centipede +centipedes +centipoise +centipoises +centiradian +centiradians +centisecond +centiseconds +centisiemens +centisievert +centisieverts +centisteradian +centisteradians +centitesla +centiteslas +centivolt +centivolts +centiwatt +centiwatts +centiweber +centiwebers +centner +centners +cento +centos +centra +central +centralism +centralist +centralistic +centralists +centrality +centralization +centralize +centralized +centralizer +centralizers +centralizes +centralizing +centrally +centrals +centric +centrically +centricity +centrifugal +centrifugalism +centrifugally +centrifugation +centrifuge +centrifuged +centrifuges +centrifuging +centriole +centrioles +centripetal +centripetally +centrism +centrist +centrists +centrobaric +centroid +centroids +centrolecithal +centrolineal +centromere +centromeres +centromeric +centrosome +centrosomes +centrosomic +centrosphere +centrospheres +centrum +centrums +cents +centuple +centurial +centuries +centurion +centurions +century +centurylong +ceorl +ceorls +cep +cephalad +cephalalgia +cephalalgias +cephalexin +cephalexins +cephalic +cephalically +cephalin +cephalins +cephalization +cephalizations +cephalochordate +cephalochordates +cephalometer +cephalometers +cephalometric +cephalometry +cephalonia +cephalopod +cephalopodan +cephalopodans +cephalopods +cephalosporin +cephalosporins +cephalothin +cephalothins +cephalothorax +cephalothoraxes +cepheid +cepheids +cepheus +ceps +ceraceous +ceram +ceramal +ceramals +ceramic +ceramics +ceramist +ceramists +cerastes +cerate +cerated +cerates +ceratodus +ceratoduses +ceratoid +cerberean +cerberus +cercaria +cercariae +cercarial +cercarias +cerci +cercus +cere +cereal +cereals +cerebella +cerebellar +cerebellum +cerebellums +cerebra +cerebral +cerebrally +cerebrate +cerebrated +cerebrates +cerebrating +cerebration +cerebrations +cerebroside +cerebrosides +cerebrospinal +cerebrovascular +cerebrum +cerebrums +cerecloth +cered +cerement +cerements +ceremonial +ceremonialism +ceremonialist +ceremonialists +ceremonially +ceremonials +ceremonies +ceremonious +ceremoniously +ceremoniousness +ceremony +ceres +cereus +cereuses +ceric +cerise +cerium +cermet +cermets +cernuous +cero +ceros +cerotype +cerotypes +cerous +certain +certainly +certainties +certainty +certes +certifiable +certifiably +certificate +certificated +certificates +certificating +certification +certifications +certificatory +certified +certifier +certifiers +certifies +certify +certifying +certiorari +certioraris +certitude +certitudes +cerulean +ceruloplasmin +ceruloplasmins +cerumen +ceruminous +ceruse +ceruses +cerussite +cerussites +cervantes +cervical +cervices +cervicitis +cervine +cervix +cervixes +cesarean +cesareans +cesium +cespitose +cespitosely +cessation +cessations +cession +cessions +cessna +cesspit +cesspits +cesspool +cesspools +cesta +cestas +cesti +cestode +cestodes +cestus +cestuses +cetacean +cetaceans +cetaceous +cetane +cetanes +cete +cetera +ceteris +cetes +cetological +cetologist +cetologists +cetology +cevennes +ceviche +ceviches +ceylon +ceylonese +chablis +chachka +chachkas +chacma +chacmas +chaconne +chaconnes +chacun +chad +chadian +chadians +chadless +chador +chadors +chaeronea +chaeta +chaetae +chaetognath +chaetognathous +chaetognaths +chafe +chafed +chafer +chafers +chafes +chaff +chaffed +chaffer +chaffered +chafferer +chafferers +chaffering +chaffers +chaffinch +chaffinches +chaffing +chaffs +chafing +chagall +chagrin +chagrined +chagrining +chagrins +chain +chained +chaining +chainlike +chainlink +chainman +chainmen +chains +chainsaw +chainsaws +chair +chaired +chairing +chairlady +chairman +chairmanned +chairmanning +chairmans +chairmanship +chairmanships +chairmen +chairperson +chairpersons +chairs +chairwoman +chairwomen +chaise +chaises +chakra +chakras +chalaza +chalazae +chalazal +chalazas +chalazia +chalazion +chalcedon +chalcedonic +chalcedonies +chalcedony +chalcid +chalcidian +chalcidians +chalcidice +chalcids +chalcocite +chalcocites +chalcopyrite +chalcopyrites +chaldaic +chaldaics +chaldea +chaldean +chaldeans +chaldee +chaldees +chaldron +chaldrons +chalet +chalets +chaliapin +chalice +chalices +chalicothere +chalicotheres +chalk +chalkboard +chalkboards +chalked +chalkier +chalkiest +chalkiness +chalking +chalks +chalkstone +chalkstones +chalky +challah +challahs +challenge +challengeable +challenged +challenger +challengers +challenges +challenging +challengingly +challis +chalone +chalones +chalybeate +chalybeates +cham +chamaeleon +chamaephyte +chamaephytes +chamber +chambered +chambering +chamberlain +chamberlains +chambermaid +chambermaids +chambers +chambray +chameleon +chameleonic +chameleons +chamfer +chamfered +chamfering +chamfers +chamfron +chamfrons +chamise +chamises +chamizal +chamois +chamomile +chamomiles +chamonix +champ +champagne +champagnes +champaign +champaigns +champak +champaks +champed +champerties +champertous +champerty +champignon +champignons +champing +champion +championed +championing +champions +championship +championships +champlain +champlevé +champs +champêtre +champêtres +chams +chance +chanced +chanceful +chancel +chancelleries +chancellery +chancellor +chancellors +chancellorship +chancels +chanceries +chancery +chances +chancier +chanciest +chanciness +chancing +chancre +chancres +chancroid +chancroidal +chancroids +chancrous +chancy +chandelier +chandeliers +chandelle +chandelles +chandigarh +chandler +chandlers +chandlery +chandos +chandragupta +change +changeability +changeable +changeableness +changeably +changed +changeful +changefully +changefulness +changeless +changeling +changelings +changeover +changeovers +changer +changers +changes +changeup +changeups +changing +channel +channeled +channeler +channelers +channeling +channelings +channelization +channelizations +channelize +channelized +channelizes +channelizing +channels +chanoyu +chanoyus +chanson +chansons +chant +chanted +chanter +chanterelle +chanterelles +chanters +chanteuse +chanteuses +chantey +chanteys +chanticleer +chanticleers +chantilly +chanting +chantingly +chantries +chantry +chants +chanukah +chaos +chaotic +chaotically +chap +chaparral +chaparrals +chapati +chapatis +chapbook +chapbooks +chape +chapeau +chapeaus +chapeaux +chapel +chapels +chaperon +chaperonage +chaperone +chaperoned +chaperones +chaperoning +chaperons +chapes +chapfallen +chapiter +chapiters +chaplain +chaplaincies +chaplaincy +chaplains +chaplainship +chaplet +chapleted +chaplets +chaplin +chapman +chapmen +chapped +chapping +chaps +chapter +chapters +chapultepec +char +charabanc +charabancs +characin +characins +character +charactered +characterful +characteries +charactering +characteristic +characteristically +characteristics +characterization +characterizations +characterize +characterized +characterizer +characterizers +characterizes +characterizing +characterless +characters +charactery +charade +charades +charbroil +charbroiled +charbroiling +charbroils +charcoal +charcoaled +charcoaling +charcoals +charcuterie +charcuteries +chard +chardonnay +chardonnays +chare +chares +charge +chargeable +chargeableness +charged +charger +chargers +charges +charging +chargé +chargés +charier +chariest +charily +chariness +chariot +charioted +charioteer +charioteers +charioting +chariots +charism +charisma +charismata +charismatic +charismatics +charitable +charitableness +charitably +charities +charity +charivari +charivaris +charkha +charkhas +charlatan +charlatanic +charlatanical +charlatanism +charlatanry +charlatans +charlemagne +charleroi +charles +charleston +charlestons +charley +charlie +charlock +charlocks +charlotte +charlottes +charlottesville +charm +charmed +charmer +charmers +charmeuse +charmeuses +charming +charmingly +charmless +charmonium +charmoniums +charms +charnel +charnels +charolais +charon +charqui +charred +charring +chars +chart +charted +charter +chartered +charterer +charterers +charterhouse +charterhouses +chartering +charters +charting +chartings +chartism +chartist +chartists +chartres +chartreuse +chartroom +chartrooms +charts +charwoman +charwomen +chary +charybdis +chase +chased +chaser +chasers +chases +chasing +chasm +chasmal +chasmogamous +chasms +chassepots +chasseur +chasseurs +chassis +chassises +chassé +chasséd +chasséing +chassés +chaste +chastely +chasten +chastened +chastener +chasteners +chasteness +chastening +chastens +chaster +chastest +chastisable +chastise +chastised +chastisement +chastisements +chastiser +chastisers +chastises +chastising +chastity +chasuble +chasubles +chat +chateau +chateaubriand +chateaubriands +chateaus +chateaux +chatelain +chatelaine +chatelaines +chatelains +chatoyancy +chatoyant +chatoyants +chats +chattahoochee +chattanooga +chatted +chattel +chattels +chatter +chatterbox +chatterboxes +chattered +chatterer +chatterers +chattering +chatters +chatterton +chattier +chattiest +chattily +chattiness +chatting +chatty +chaucer +chaucerian +chaucerians +chauffeur +chauffeured +chauffeuring +chauffeurs +chaulmoogra +chaulmoogras +chautauqua +chauvinism +chauvinist +chauvinistic +chauvinistically +chauvinists +chaw +chawed +chawing +chaws +chayote +chayotes +chazan +chazans +cheap +cheapen +cheapened +cheapener +cheapeners +cheapening +cheapens +cheaper +cheapest +cheapie +cheapies +cheapjack +cheapjacks +cheaply +cheapness +cheapskate +cheapskates +cheat +cheated +cheater +cheaters +cheating +cheatingly +cheats +chebec +chebecs +chebyshev +check +checkable +checkbook +checkbooks +checkbox +checkboxes +checked +checker +checkerberries +checkerberry +checkerbloom +checkerblooms +checkerboard +checkerboards +checkered +checkering +checkers +checking +checklist +checklists +checkmark +checkmarks +checkmate +checkmated +checkmates +checkmating +checkoff +checkout +checkouts +checkpoint +checkpoints +checkrein +checkreins +checkroom +checkrooms +checks +checksum +checksums +checkup +checkups +cheddar +cheddars +cheek +cheekbone +cheekbones +cheeked +cheekier +cheekiest +cheekily +cheekiness +cheeking +cheeks +cheeky +cheep +cheeped +cheeper +cheepers +cheeping +cheeps +cheer +cheered +cheerer +cheerers +cheerful +cheerfully +cheerfulness +cheerier +cheeriest +cheerily +cheeriness +cheering +cheeringly +cheerio +cheerios +cheerlead +cheerleader +cheerleaders +cheerleading +cheerleads +cheerled +cheerless +cheerlessly +cheerlessness +cheers +cheery +cheese +cheeseburger +cheeseburgers +cheesecake +cheesecakes +cheesecloth +cheesed +cheeseparer +cheeseparers +cheeseparing +cheeses +cheesier +cheesiest +cheesiness +cheesing +cheesy +cheetah +cheetahs +chef +chefs +chekhov +chekhovian +chela +chelae +chelatable +chelate +chelated +chelates +chelating +chelation +chelator +chelators +chelicera +chelicerae +cheliform +chellian +chelonian +chelonians +chelsea +chemic +chemical +chemically +chemicals +chemiluminescence +chemiluminescent +chemin +chemins +chemise +chemises +chemisette +chemisettes +chemisorb +chemisorbed +chemisorbing +chemisorbs +chemisorption +chemist +chemistries +chemistry +chemists +chemoautotroph +chemoautotrophic +chemoautotrophically +chemoautotrophs +chemoautotrophy +chemoprevention +chemopreventions +chemopreventive +chemoprophylactic +chemoprophylaxis +chemoreception +chemoreceptive +chemoreceptivity +chemoreceptor +chemoreceptors +chemosensory +chemosphere +chemospheres +chemosurgery +chemosurgical +chemosynthesis +chemosynthetic +chemosynthetically +chemosystematics +chemotactic +chemotactically +chemotaxis +chemotaxonomic +chemotaxonomically +chemotaxonomist +chemotaxonomists +chemotaxonomy +chemotherapeutic +chemotherapeutically +chemotherapist +chemotherapists +chemotherapy +chemotropic +chemotropism +chemotropisms +chemurgic +chemurgical +chemurgy +chenille +chenilles +chenopod +chenopods +cheops +cheque +chequer +chequers +cheques +cherbourg +cherimoya +cherimoyas +cherish +cherishable +cherished +cherisher +cherishers +cherishes +cherishing +cherishingly +chernobyl +chernozem +chernozemic +chernozems +cherokee +cherokees +cheroot +cheroots +cherries +cherry +cherrystone +cherrystones +chersonese +chersoneses +chert +cherty +cherub +cherubic +cherubically +cherubim +cherubs +chervil +chesapeake +cheshire +chess +chessboard +chessboards +chesses +chessman +chessmen +chessylite +chessylites +chest +chested +chesterfield +chesterfields +chestier +chestiest +chestiness +chestnut +chestnuts +chests +chesty +chetrum +cheval +chevalet +chevalets +chevalier +chevaliers +chevaux +chevelure +chevelures +cheviot +cheviots +chevrolet +chevrolets +chevron +chevrons +chevrotain +chevrotains +chew +chewable +chewed +chewer +chewers +chewier +chewiest +chewiness +chewing +chewink +chewinks +chews +chewy +cheyenne +cheyennes +chez +chi +chia +chianti +chiantis +chiaroscurist +chiaroscurists +chiaroscuro +chiaroscuros +chias +chiasma +chiasmal +chiasmas +chiasmata +chiasmatic +chiasmatypies +chiasmatypy +chiasmi +chiasmic +chiasmus +chiastolite +chiastolites +chiaus +chibcha +chibchan +chibchans +chibchas +chibouk +chibouks +chic +chicago +chicagoan +chicagoans +chicana +chicane +chicaned +chicaner +chicaneries +chicaners +chicanery +chicanes +chicaning +chicano +chicanos +chicer +chicest +chichagof +chichi +chichier +chichiest +chick +chickadee +chickadees +chickaree +chickarees +chickasaw +chickasaws +chicken +chickened +chickenfeed +chickenhearted +chickening +chickenpox +chickens +chickpea +chickpeas +chicks +chickweed +chickweeds +chicle +chiclets +chicly +chicness +chicories +chicory +chid +chidden +chide +chided +chider +chiders +chides +chiding +chidingly +chief +chiefdom +chiefdoms +chiefly +chiefs +chiefship +chieftain +chieftaincy +chieftains +chieftainship +chiffchaff +chiffchaffs +chiffon +chiffonier +chiffoniers +chiffonnier +chiffonniers +chifforobe +chifforobes +chigger +chiggers +chignon +chignons +chigoe +chihuahua +chihuahuas +chilblain +chilblained +chilblains +child +childbearing +childbed +childbirth +childbirths +childermas +childermases +childfree +childhood +childish +childishly +childishness +childless +childlessness +childlike +childproof +childproofed +childproofing +childproofs +children +chile +chilean +chileans +chili +chiliad +chiliads +chiliasm +chiliast +chiliastic +chiliburger +chiliburgers +chilidog +chilidogs +chilies +chill +chilled +chiller +chillers +chillier +chilliest +chillily +chilliness +chilling +chillingly +chillness +chills +chilly +chiloe +chilopod +chilopods +chiloé +chimaera +chimaeras +chimborazo +chime +chimed +chimer +chimera +chimeras +chimeric +chimerical +chimerically +chimerism +chimerisms +chimers +chimes +chimichanga +chimichangas +chiming +chimney +chimneypiece +chimneypieces +chimneys +chimneysweep +chimneysweeper +chimneysweepers +chimneysweeps +chimp +chimpanzee +chimpanzees +chimps +chin +china +chinaberries +chinaberry +chinaman +chinamen +chinatown +chinatowns +chinaware +chinch +chincherinchee +chincherinchees +chinches +chinchilla +chinchillas +chincoteague +chindit +chindits +chindwin +chine +chines +chinese +chink +chinked +chinking +chinks +chinky +chinless +chinned +chinning +chino +chinoiserie +chinoiseries +chinook +chinookan +chinooks +chinos +chinquapin +chinquapins +chins +chintz +chintzes +chintzier +chintziest +chintzy +chip +chipboard +chipboards +chipewyan +chipewyans +chipmaker +chipmakers +chipmunk +chipmunks +chipped +chippendale +chipper +chippered +chippering +chippers +chippewa +chippewas +chippier +chippies +chippiest +chipping +chippy +chips +chiral +chirality +chiricahua +chiricahuas +chirk +chirked +chirking +chirks +chirographer +chirographers +chirographic +chirographical +chirography +chiromancer +chiromancers +chiromancy +chiron +chiropodist +chiropodists +chiropody +chiropractic +chiropractor +chiropractors +chiropteran +chiropterans +chirp +chirped +chirpier +chirpiest +chirpily +chirping +chirps +chirpy +chirr +chirred +chirring +chirrs +chirrup +chirruped +chirruping +chirrups +chisel +chiseled +chiseler +chiselers +chiseling +chisels +chit +chitchat +chitchats +chitchatted +chitchatting +chitin +chitinous +chitlins +chiton +chits +chittagong +chitter +chittered +chittering +chitterlings +chitters +chivalric +chivalries +chivalrous +chivalrously +chivalrousness +chivalry +chive +chives +chivied +chivies +chivvied +chivvies +chivvy +chivvying +chivy +chivying +chlamydate +chlamydeous +chlamydes +chlamydia +chlamydiae +chlamydial +chlamydospore +chlamydospores +chlamys +chlamyses +chloasma +chloasmata +chloe +chloracne +chloracnes +chloral +chloramine +chloramines +chloramphenicol +chlorate +chlorates +chlordane +chlordiazepoxide +chlorella +chlorenchyma +chloric +chloride +chlorides +chloridic +chlorinate +chlorinated +chlorinates +chlorinating +chlorination +chlorinations +chlorinator +chlorinators +chlorine +chlorite +chlorites +chlorobenzene +chlorocarbon +chlorocarbons +chlorofluorocarbon +chloroform +chloroformed +chloroforming +chloroforms +chlorohydrin +chloromycetin +chlorophyll +chloropicrin +chloroplast +chloroplasts +chloroprene +chloroquine +chlorosis +chlorothiazide +chlorothiazides +chlorotic +chlorotically +chlorpromazine +chlortetracycline +choanocyte +choanocytes +chock +chockablock +chocked +chockfull +chocking +chocks +chocoholic +chocoholics +chocolate +chocolates +choctaw +choctawhatchee +choctaws +choice +choicely +choiceness +choicer +choices +choicest +choir +choirboy +choirboys +choired +choirgirl +choirgirls +choiring +choirmaster +choirmasters +choirs +choiseul +choke +chokeberries +chokeberry +chokebore +chokebores +chokecherries +chokecherry +choked +chokedamp +chokehold +chokeholds +chokepoint +chokepoints +choker +chokers +chokes +chokier +chokiest +choking +chokingly +choky +cholangiographic +cholangiography +cholecalciferol +cholecyst +cholecystectomies +cholecystectomy +cholecystitis +cholecystokinin +cholecysts +cholelithiasis +choler +cholera +choleraic +choleric +cholerically +choleroid +cholestasis +cholesterin +cholesterol +cholestyramine +choline +cholinergic +cholinesterase +cholla +chomp +chomped +chomping +chomps +chomsky +chomskyan +chondrification +chondrified +chondrifies +chondrify +chondrifying +chondriosome +chondriosomes +chondrite +chondrites +chondritic +chondrocrania +chondrocranium +chondrocraniums +chondroma +chondromalacia +chondromas +chondromata +chondrule +chondrules +choose +chooser +choosers +chooses +choosier +choosiest +choosiness +choosing +choosy +chop +chophouse +chophouses +chopin +chopine +chopines +choplogic +chopped +chopper +choppered +choppering +choppers +choppier +choppiest +choppily +choppiness +chopping +choppy +chops +chopstick +chopsticks +choragi +choragic +choragus +choral +chorale +chorales +chorally +chord +chordal +chordate +chordates +chorded +chording +chords +chore +chorea +choreograph +choreographed +choreographer +choreographers +choreographic +choreographically +choreographies +choreographing +choreographs +choreography +chores +choriamb +choriambic +choriambs +choric +chorine +chorines +chorioallantoic +chorioallantois +chorion +chorionic +chorions +choripetalous +chorister +choristers +chorizo +chorizos +chorographer +chorographers +chorographic +chorographical +chorographically +chorography +choroid +choroids +chortle +chortled +chortler +chortlers +chortles +chortling +chorus +chorused +choruses +chorusing +chose +chosen +chott +chotts +choucroute +choucroutes +chough +choughs +chouse +choused +chouses +chousing +chow +chowchow +chowchows +chowder +chowders +chowed +chowhound +chowhounds +chowing +chows +chresard +chresards +chrestomathic +chrestomathies +chrestomathy +chris +chrism +chrismal +chrisms +chrisom +chrisoms +christ +christchurch +christen +christendom +christened +christening +christenings +christens +christi +christian +christiania +christianities +christianity +christianization +christianize +christianized +christianizer +christianizers +christianizes +christianizing +christianly +christians +christie +christies +christina +christine +christlike +christlikeness +christliness +christly +christmas +christmases +christmassy +christmastide +christmastime +christmastimes +christogram +christograms +christological +christologies +christology +christopher +chroma +chromaffin +chromate +chromatic +chromatically +chromaticism +chromaticity +chromatics +chromatid +chromatids +chromatin +chromatinic +chromatist +chromatists +chromatogram +chromatograms +chromatograph +chromatographed +chromatographer +chromatographers +chromatographic +chromatographically +chromatographing +chromatographs +chromatography +chromatolysis +chromatolytic +chromatophilic +chromatophore +chromatophores +chromatophoric +chrome +chromed +chromes +chromic +chroming +chromite +chromium +chromodynamics +chromogen +chromogenic +chromogens +chromolithograph +chromolithographer +chromolithographers +chromolithographic +chromolithographs +chromolithography +chromomere +chromomeres +chromomeric +chromonema +chromonemal +chromonemata +chromonemic +chromophil +chromophore +chromophores +chromophoric +chromoplast +chromoprotein +chromoproteins +chromosomal +chromosomally +chromosome +chromosomes +chromosomic +chromosphere +chromospheres +chromospheric +chromous +chronaxie +chronaxies +chronic +chronically +chronicity +chronicle +chronicled +chronicler +chroniclers +chronicles +chronicling +chronobiology +chronogram +chronogrammatic +chronogrammatically +chronograms +chronograph +chronographic +chronographically +chronographs +chronological +chronologically +chronologies +chronologist +chronologists +chronologize +chronologized +chronologizes +chronologizing +chronology +chronometer +chronometers +chronometric +chronometrical +chronometrically +chronometry +chronoscope +chronoscopes +chronoscopic +chrysalid +chrysalides +chrysalids +chrysalis +chrysalises +chrysanthemum +chrysanthemums +chryselephantine +chrysler +chryslers +chrysoberyl +chrysolite +chrysolites +chrysomelid +chrysomelids +chrysoprase +chrysoprases +chrysotherapy +chrysotile +chrysotiles +chthonic +chub +chubbier +chubbiest +chubbily +chubbiness +chubby +chubs +chuck +chucked +chuckhole +chuckholes +chucking +chuckle +chuckled +chucklehead +chuckleheaded +chuckleheads +chuckler +chucklers +chuckles +chucklesome +chuckling +chucklingly +chucks +chuckwalla +chuckwallas +chuddar +chuddars +chufa +chufas +chuff +chuffed +chuffing +chuffs +chuffy +chug +chugalug +chugalugged +chugalugging +chugalugs +chugged +chugger +chuggers +chugging +chugs +chukar +chukars +chukka +chukkas +chukker +chukkers +chum +chummed +chummier +chummiest +chummily +chumminess +chumming +chummy +chump +chumped +chumping +chumps +chums +chungking +chunk +chunked +chunkier +chunkiest +chunkily +chunkiness +chunking +chunks +chunky +chunnel +chunnels +chunter +chuntered +chuntering +chunters +church +churched +churches +churchgoer +churchgoers +churchgoing +churchier +churchiest +churchill +churchillian +churching +churchliness +churchly +churchman +churchmanly +churchmanship +churchmen +churchwarden +churchwardens +churchwoman +churchwomen +churchy +churchyard +churchyards +churl +churlish +churlishly +churlishness +churls +churn +churned +churner +churners +churning +churns +churr +churred +churrigueresque +churring +churro +churros +churrs +chute +chuted +chutes +chuting +chutist +chutists +chutney +chutneys +chutzpa +chutzpah +chutzpas +chuvash +chuvashes +chylaceous +chyle +chyles +chylomicron +chylomicrons +chylous +chyme +chymes +chymopapain +chymopapains +chymosin +chymosins +chymotrypsin +chymotrypsins +chymotryptic +chymous +châlons +château +châteaux +châtelherault +chèvre +ciao +cibber +ciboria +ciborium +cicada +cicadae +cicadas +cicala +cicalas +cicatrices +cicatricial +cicatricose +cicatrix +cicatrization +cicatrize +cicatrized +cicatrizes +cicatrizing +cicero +cicerone +cicerones +ciceroni +ciceronian +cichlid +cichlids +cider +ciders +cigar +cigarette +cigarettes +cigarillo +cigarillos +cigars +cilantro +cilia +ciliary +ciliate +ciliated +ciliately +ciliates +ciliation +cilice +cilices +cilicia +cilician +cilicians +ciliolate +cilium +cimarron +cimetidine +cimex +cimices +cimmerian +cinch +cinched +cincher +cinchers +cinches +cinching +cinchona +cinchonas +cinchonic +cinchonine +cinchonism +cincinnati +cincture +cinctured +cinctures +cincturing +cinder +cindered +cinderella +cindering +cinders +cindery +cindy +cine +cineaste +cineastes +cinema +cinemagoer +cinemagoers +cinemas +cinematheque +cinematheques +cinematic +cinematically +cinematization +cinematizations +cinematize +cinematized +cinematizes +cinematizing +cinematograph +cinematographer +cinematographers +cinematographically +cinematographs +cinematography +cineole +cineoles +cinephile +cinephiles +cineradiography +cinerama +cineraria +cinerarium +cinerary +cinereous +cinerin +cinerins +cines +cingalese +cingula +cingulate +cingulated +cingulum +cinnabar +cinnamic +cinnamon +cinquain +cinquains +cinque +cinquecentist +cinquecentists +cinquecento +cinquefoil +cinquefoils +cinques +cinéma +cipher +ciphered +ciphering +ciphers +circa +circadian +circadianly +circassia +circassian +circassians +circe +circean +circinate +circinately +circinus +circle +circled +circler +circlers +circles +circlet +circlets +circling +circuit +circuited +circuiting +circuitous +circuitously +circuitousness +circuitries +circuitry +circuits +circuity +circular +circularities +circularity +circularization +circularize +circularized +circularizer +circularizers +circularizes +circularizing +circularly +circulars +circulate +circulated +circulates +circulating +circulation +circulations +circulative +circulator +circulators +circulatory +circumambience +circumambiency +circumambient +circumambiently +circumambulate +circumambulated +circumambulates +circumambulating +circumambulation +circumambulations +circumboreal +circumcise +circumcised +circumciser +circumcisers +circumcises +circumcising +circumcision +circumcisions +circumduction +circumductions +circumference +circumferences +circumferential +circumflex +circumflexes +circumfluent +circumfuse +circumfused +circumfuses +circumfusing +circumfusion +circumlocution +circumlocutions +circumlocutorily +circumlocutory +circumlunar +circumnavigate +circumnavigated +circumnavigates +circumnavigating +circumnavigation +circumnavigations +circumnavigator +circumnavigators +circumpolar +circumrotate +circumrotated +circumrotates +circumrotating +circumrotation +circumrotations +circumrotatory +circumscissile +circumscribable +circumscribe +circumscribed +circumscriber +circumscribers +circumscribes +circumscribing +circumscription +circumscriptions +circumscriptive +circumscriptively +circumsolar +circumspect +circumspection +circumspectly +circumstance +circumstanced +circumstances +circumstancing +circumstantial +circumstantialities +circumstantiality +circumstantially +circumstantiate +circumstantiated +circumstantiates +circumstantiating +circumstantiation +circumstantiations +circumterrestrial +circumvallate +circumvallated +circumvallates +circumvallating +circumvallation +circumvallations +circumvent +circumvented +circumventer +circumventers +circumventing +circumvention +circumventions +circumventive +circumvents +circumvolution +circumvolutions +circumvolve +circumvolved +circumvolves +circumvolving +circus +circuses +circusy +cirque +cirques +cirrate +cirrhoses +cirrhosis +cirrhotic +cirri +cirriped +cirripeds +cirrocumuli +cirrocumulus +cirrostrati +cirrostratus +cirrus +ciré +cisalpine +cisatlantic +ciscaucasia +cisco +ciscoes +cislunar +cismontane +cist +cistercian +cistercians +cistern +cisterna +cisternae +cisternal +cisterns +cistron +cistronic +cistrons +cists +cit +citable +citadel +citadels +citation +citational +citations +citatory +cite +cited +cites +cithaeron +cithara +citharas +cither +cithers +citied +cities +citification +citified +citifies +citify +citifying +citing +citizen +citizeness +citizenesses +citizenly +citizenries +citizenry +citizens +citizenship +citlaltépetl +citral +citrals +citrate +citrates +citric +citriculture +citricultures +citriculturist +citriculturists +citrine +citrines +citroen +citron +citronella +citronellal +citronellals +citronellas +citronellol +citronellols +citrons +citrulline +citrullines +citrus +citruses +cittern +citterns +city +cityscape +cityscapes +citywide +civet +civets +civic +civics +civil +civilian +civilianization +civilianize +civilianized +civilianizes +civilianizing +civilians +civilities +civility +civilizable +civilization +civilizations +civilize +civilized +civilizer +civilizers +civilizes +civilizing +civilly +civism +civisms +civitavecchia +civvies +clabber +clabbered +clabbering +clabbers +clack +clacked +clacker +clackers +clacking +clacks +clactonian +clad +cladding +claddings +clade +clades +cladist +cladistic +cladistically +cladistics +cladists +cladoceran +cladocerans +cladode +cladodes +cladodial +cladogenesis +cladogenetic +cladogenetically +cladogram +cladograms +cladophyll +cladophylls +clads +clafouti +claim +claimable +claimant +claimants +claimed +claimer +claimers +claiming +claims +clair +clairaudience +clairaudiences +clairaudient +claire +clairvaux +clairvoyance +clairvoyant +clairvoyants +clam +clamant +clamantly +clambake +clambakes +clamber +clambered +clamberer +clamberers +clambering +clambers +clammed +clammer +clammers +clammier +clammiest +clammily +clamminess +clamming +clammy +clamor +clamored +clamorer +clamorers +clamoring +clamorous +clamorously +clamorousness +clamors +clamp +clampdown +clampdowns +clamped +clamper +clampers +clamping +clamps +clams +clamshell +clamshells +clamworm +clamworms +clan +clandestine +clandestinely +clandestineness +clandestinity +clang +clanged +clanging +clangor +clangored +clangoring +clangorous +clangorously +clangors +clangs +clank +clanked +clanking +clanks +clanky +clannish +clannishly +clannishness +clans +clansman +clansmen +clanswoman +clanswomen +clap +clapboard +clapboarded +clapboarding +clapboards +clapped +clapper +clappers +clapping +claps +claptrap +claque +claques +clarence +clarences +claret +clarets +claries +clarification +clarifications +clarificatory +clarified +clarifier +clarifiers +clarifies +clarify +clarifying +clarinet +clarinetist +clarinetists +clarinets +clarion +clarions +clarity +clarkia +clarkias +clary +clash +clashed +clashes +clashing +clasp +clasped +clasper +claspers +clasping +clasps +class +classed +classes +classic +classical +classicality +classically +classicalness +classicism +classicist +classicists +classicize +classicized +classicizes +classicizing +classics +classier +classiest +classifiable +classification +classifications +classificatorily +classificatory +classified +classifieds +classifier +classifiers +classifies +classify +classifying +classiness +classing +classis +classism +classisms +classist +classless +classman +classmate +classmates +classmen +classon +classons +classroom +classrooms +classy +clast +clastic +clasts +clathrate +clathrates +clatter +clattered +clatterer +clatterers +clattering +clatters +clattery +claude +claudication +claudications +claudius +claus +clausal +clause +clauses +clausewitz +claustrophobe +claustrophobia +claustrophobic +claustrophobically +clavate +clavately +clavichord +clavichordist +clavichordists +clavichords +clavicle +clavicles +clavicular +claviculate +clavier +claviers +clavus +claw +clawed +clawing +claws +clay +clayey +clayish +claylike +claymation +claymore +claymores +clays +clayware +clean +cleanable +cleaned +cleaner +cleaners +cleanest +cleaning +cleanlier +cleanliest +cleanliness +cleanly +cleanness +cleans +cleanse +cleansed +cleanser +cleansers +cleanses +cleansing +cleanthes +cleanup +cleanups +clear +clearable +clearance +clearances +clearchus +cleared +clearer +clearers +clearest +clearheaded +clearheadedly +clearing +clearinghouse +clearinghouses +clearings +clearly +clearness +clears +clearweed +clearweeds +clearwing +clearwings +cleat +cleated +cleating +cleats +cleavable +cleavage +cleavages +cleave +cleaved +cleaver +cleavers +cleaves +cleaving +clef +clefs +cleft +clefts +cleisthenes +cleistogamous +cleistogamously +cleistogamy +cleistothecia +cleistothecium +clematis +clematises +clemenceau +clemencies +clemency +clement +clementine +clementines +clemently +clench +clenched +clenches +clenching +cleome +cleomes +cleopatra +clepsydra +clepsydrae +clepsydras +clerestories +clerestory +clergies +clergy +clergyman +clergymen +clergywoman +clergywomen +cleric +clerical +clericalism +clericalist +clericalists +clerically +clericals +clerics +clerihew +clerihews +clerisies +clerisy +clerk +clerkdom +clerkdoms +clerked +clerking +clerklier +clerkliest +clerkliness +clerkly +clerks +clerkship +clerkships +cleveland +clever +cleverer +cleverest +cleverly +cleverness +cleves +clevis +clevises +clew +clewed +clewing +clews +cliché +clichéd +clichés +click +clicked +clicker +clickers +clicking +clicks +client +clientage +cliental +clientele +clienteles +clients +cliff +cliffhanger +cliffhangers +cliffhanging +clifford +cliffs +cliffy +climacteric +climacterics +climactic +climactically +climate +climates +climatic +climatically +climatologic +climatological +climatologically +climatologist +climatologists +climatology +climax +climaxed +climaxes +climaxing +climb +climbable +climbed +climber +climbers +climbing +climbs +clime +climes +clinandria +clinandrium +clinch +clinched +clincher +clinchers +clinches +clinching +cline +clines +cling +clinger +clingers +clingfish +clingfishes +clinging +clings +clingstone +clingstones +clingy +clinic +clinical +clinically +clinician +clinicians +clinics +clink +clinked +clinker +clinkered +clinkering +clinkers +clinking +clinks +clinometer +clinometers +clinometric +clinometrical +clinometry +clinquant +clinquants +clinton +clintonia +clintonias +clio +cliometric +cliometrician +cliometricians +cliometrics +clios +clip +clipboard +clipboards +clipped +clipper +clippers +clipping +clippings +clips +clipsheet +clipsheets +clique +cliqued +cliques +cliquey +cliquing +cliquish +cliquishly +cliquishness +clisthenes +clitella +clitellum +clitoral +clitoris +clitorises +clive +cloaca +cloacae +cloacal +cloak +cloaked +cloaking +cloakroom +cloakrooms +cloaks +clobber +clobbered +clobbering +clobbers +clochard +clochards +cloche +cloches +clock +clocked +clocker +clockers +clocking +clockmaker +clockmakers +clocks +clockwise +clockwork +clockworks +clod +cloddish +cloddishly +cloddishness +clodhopper +clodhoppers +clodhopping +clods +clofibrate +clofibrates +clog +clogged +clogging +clogs +cloisonné +cloister +cloistered +cloistering +cloisters +cloistral +clomiphene +clomiphenes +clomp +clomped +clomping +clomps +clonal +clonally +clone +cloned +cloner +cloners +clones +clonic +clonicity +clonidine +clonidines +cloning +clonism +clonus +clonuses +clop +clopped +clopping +clops +cloque +cloques +close +closed +closedown +closedowns +closefisted +closely +closemouthed +closeness +closeout +closeouts +closer +closers +closes +closest +closet +closeted +closetful +closeting +closets +closing +closings +clostridia +clostridial +clostridium +closure +closured +closures +closuring +clot +cloth +clothbound +clothe +clothed +clothes +clothesbasket +clothesbaskets +clotheshorse +clotheshorses +clothesline +clotheslined +clotheslines +clotheslining +clothespin +clothespins +clothespress +clothespresses +clothier +clothiers +clothing +clotho +cloths +clots +clotted +clotting +cloture +clotured +clotures +cloturing +cloud +cloudberries +cloudberry +cloudburst +cloudbursts +clouded +cloudier +cloudiest +cloudily +cloudiness +clouding +cloudland +cloudlands +cloudless +cloudlessness +cloudlet +cloudlets +clouds +cloudscape +cloudscapes +cloudy +clout +clouted +clouting +clouts +clove +cloven +clover +cloverleaf +cloverleaves +clovers +cloves +clovis +clown +clowned +clowning +clownish +clownishly +clownishness +clowns +cloxacillin +cloxacillins +cloy +cloyed +cloying +cloyingly +cloyingness +cloys +cloze +club +clubbable +clubbed +clubber +clubbers +clubbier +clubbiest +clubbiness +clubbing +clubby +clubface +clubfaces +clubfeet +clubfoot +clubfooted +clubfoots +clubhouse +clubhouses +clubman +clubmate +clubmates +clubmen +clubroom +clubrooms +clubs +clubwoman +clubwomen +cluck +clucked +clucking +clucks +clue +clued +clueing +clueless +clues +clump +clumped +clumping +clumpings +clumps +clumpy +clumsier +clumsiest +clumsily +clumsiness +clumsy +clung +cluniac +clunk +clunked +clunker +clunkers +clunkier +clunkiest +clunking +clunks +clunky +cluny +clupeid +clupeids +cluster +clustered +clustering +clusters +clutch +clutched +clutches +clutching +clutter +cluttered +cluttering +clutters +clwyd +clydesdale +clydesdales +clypeal +clypeate +clypeated +clypei +clypeus +clyster +clysters +clytemnestra +cnidoblast +cnidoblasts +cnut +coacervate +coacervated +coacervates +coacervating +coacervation +coach +coachable +coached +coacher +coachers +coaches +coaching +coachman +coachmen +coachwork +coact +coacted +coacting +coaction +coactions +coactive +coactively +coactor +coactors +coacts +coadaptation +coadapted +coadjutant +coadjutants +coadjutor +coadjutors +coadministration +coadunate +coadunation +coadunative +coagula +coagulability +coagulable +coagulant +coagulants +coagulase +coagulases +coagulate +coagulated +coagulates +coagulating +coagulation +coagulations +coagulative +coagulator +coagulators +coagulum +coal +coaled +coaler +coalers +coalesce +coalesced +coalescence +coalescent +coalesces +coalescing +coalfield +coalfields +coalfish +coalfishes +coalification +coalifications +coaling +coalition +coalitionist +coalitionists +coalitions +coals +coalsack +coalsacks +coaming +coamings +coanchor +coanchors +coarctate +coarctation +coarctations +coarse +coarsely +coarsen +coarsened +coarseness +coarsening +coarsens +coarser +coarsest +coassignee +coassignees +coast +coastal +coasted +coaster +coasters +coastguard +coastguards +coastguardsman +coastguardsmen +coasting +coastland +coastlands +coastline +coastlines +coasts +coastward +coastwards +coastwise +coat +coatdress +coatdresses +coated +coati +coatimundi +coating +coatings +coatis +coatroom +coatrooms +coats +coattail +coattails +coatzacoalcos +coauthor +coauthored +coauthoring +coauthors +coauthorship +coax +coaxed +coaxer +coaxers +coaxes +coaxial +coaxing +coaxingly +cob +cobalamin +cobalamins +cobalt +cobaltic +cobaltite +cobaltites +cobaltous +cobber +cobbers +cobbett +cobble +cobbled +cobbler +cobblers +cobbles +cobblestone +cobblestones +cobbling +cobden +cobelligerent +cobelligerents +cobia +cobias +coble +cobles +cobnut +cobnuts +cobourg +cobra +cobras +cobs +coburg +cobweb +cobwebbed +cobwebbing +cobwebby +cobwebs +coca +cocaine +cocainism +cocainisms +cocainization +cocainize +cocainized +cocainizes +cocainizing +cocaptain +cocaptains +cocarcinogen +cocarcinogenic +cocarcinogens +cocas +cocatalyst +cocatalysts +cocci +coccid +coccidia +coccidioidomycosis +coccidiosis +coccidium +coccids +coccobacilli +coccobacillus +coccoid +coccoids +coccolith +coccoliths +coccus +coccygeal +coccyges +coccyx +cochair +cochairman +cochairmen +cochairperson +cochairpersons +cochairs +cochairwoman +cochairwomen +cochampion +cochampions +cochere +cochineal +cochlea +cochleae +cochlear +cochleate +cock +cockade +cockaded +cockades +cockaigne +cockalorum +cockalorums +cockamamie +cockatiel +cockatiels +cockatoo +cockatoos +cockatrice +cockatrices +cockboat +cockboats +cockchafer +cockchafers +cockcrow +cocked +cocker +cockered +cockerel +cockerels +cockering +cockers +cockeye +cockeyed +cockeyes +cockfight +cockfighting +cockfights +cockhorse +cockhorses +cockier +cockiest +cockily +cockiness +cocking +cockle +cockleboat +cockleboats +cocklebur +cockleburs +cockled +cockles +cockleshell +cockleshells +cockling +cockloft +cocklofts +cockney +cockneys +cockpit +cockpits +cockroach +cockroaches +cocks +cockscomb +cockscombs +cocksfoot +cocksfoots +cockshies +cockshy +cocksucker +cocksuckers +cocksure +cocksurely +cocksureness +cocktail +cocktails +cocky +coco +cocoa +cocoas +cocobolo +cocobolos +cocomposer +cocomposers +coconspirator +coconspirators +coconut +coconuts +cocoon +cocooned +cocooning +cocoonings +cocoons +cocos +cocotte +cocottes +cocounsel +cocoyam +cocoyams +cocreate +cocreated +cocreates +cocreating +cocreator +cocreators +cocteau +cocultivate +cocultivated +cocultivates +cocultivating +cocultivation +coculture +cocurator +cocurators +cocurricular +cocytus +cod +coda +codas +coddle +coddled +coddler +coddlers +coddles +coddling +code +codebook +codebooks +codebreaker +codebreakers +codeclination +codeclinations +coded +codefendant +codefendants +codeine +codeines +codemaker +codemakers +coder +coders +codes +codesign +codesigned +codesigning +codesigns +codetermination +codeterminations +codetermine +codetermined +codetermines +codetermining +codevelop +codeveloped +codeveloper +codevelopers +codeveloping +codevelops +codex +codfish +codfishes +codger +codgers +codices +codicil +codicillary +codicils +codification +codifications +codified +codifier +codifiers +codifies +codify +codifying +coding +codirect +codirected +codirecting +codirection +codirector +codirectors +codirects +codiscover +codiscovered +codiscoverer +codiscoverers +codiscovering +codiscovers +codling +codlings +codominance +codominances +codominant +codominants +codon +codons +codpiece +codpieces +codrive +codriven +codriver +codrivers +codrives +codriving +codrove +cods +codswallop +codswallops +coed +coedit +coedited +coediting +coeditor +coeditors +coedits +coeds +coeducation +coeducational +coeducationally +coefficient +coefficients +coelacanth +coelacanthine +coelacanthous +coelacanths +coelentera +coelenterate +coelenterates +coelenteric +coelenteron +coelom +coelomate +coelomic +coeloms +coenocyte +coenocytes +coenocytic +coenuri +coenurus +coenzymatic +coenzymatically +coenzyme +coenzymes +coequal +coequality +coequally +coequals +coerce +coerced +coercer +coercers +coerces +coercible +coercing +coercion +coercionary +coercive +coercively +coerciveness +coessential +coessentiality +coessentially +coessentialness +coetaneous +coetaneously +coetaneousness +coeternal +coeternally +coeternity +coeur +coeval +coevally +coevals +coevolution +coevolutionary +coevolve +coevolved +coevolves +coevolving +coexecutor +coexecutors +coexist +coexisted +coexistence +coexistent +coexisting +coexists +coextend +coextended +coextending +coextends +coextension +coextensive +coextensively +cofactor +cofactors +cofavorite +cofavorites +cofeature +cofeatures +coffee +coffeecake +coffeecakes +coffeehouse +coffeehouses +coffeemaker +coffeemakers +coffeepot +coffeepots +coffees +coffer +cofferdam +cofferdams +coffered +coffering +coffers +coffin +coffined +coffining +coffins +coffle +coffled +coffles +coffling +cofinance +cofound +cofounded +cofounder +cofounders +cofounding +cofounds +cofunction +cofunctions +cog +cogency +cogeneration +cogent +cogently +cogged +cogging +cogitable +cogitate +cogitated +cogitates +cogitating +cogitation +cogitations +cogitative +cogitatively +cogitativeness +cogitator +cogitators +cognac +cognacs +cognate +cognates +cognation +cognition +cognitional +cognitive +cognitively +cognizable +cognizably +cognizance +cognizant +cognize +cognized +cognizes +cognizing +cognomen +cognomens +cognomina +cognominal +cognoscente +cognoscenti +cogon +cogons +cogs +cogwheel +cogwheels +cohabit +cohabitant +cohabitants +cohabitate +cohabitation +cohabitational +cohabited +cohabiter +cohabiters +cohabiting +cohabits +cohead +coheads +coheir +coheiress +coheiresses +coheirs +cohere +cohered +coherence +coherencies +coherency +coherent +coherently +coheres +cohering +cohesion +cohesionless +cohesive +cohesively +cohesiveness +coho +coholder +coholders +cohort +cohorts +cohos +cohosh +cohoshes +cohost +cohosted +cohostess +cohostesses +cohosting +cohosts +cohune +cohunes +coif +coifed +coiffeur +coiffeurs +coiffeuse +coiffeuses +coiffure +coiffured +coiffures +coiffuring +coifing +coifs +coign +coigns +coil +coiled +coiler +coilers +coiling +coils +coin +coinable +coinage +coinages +coincide +coincided +coincidence +coincidences +coincident +coincidental +coincidentally +coincides +coinciding +coined +coiner +coiners +coining +coins +coinsurance +coinsurances +coinsure +coinsured +coinsures +coinsuring +coinvent +coinvented +coinventing +coinventor +coinventors +coinvents +coinvestigator +coinvestigators +coinvestor +coinvestors +coir +coirs +coital +coitally +coition +coitus +cojoin +cojoined +cojoining +cojoins +coke +coked +cokehead +cokeheads +cokes +coking +col +cola +colada +colander +colanders +colas +colcannon +colcannons +colchicine +colchicines +colchicum +colcothar +colcothars +cold +coldcock +coldcocked +coldcocking +coldcocks +colder +coldest +coldhearted +coldheartedly +coldheartedness +coldly +coldness +colds +coldshoulder +coldshouldered +coldshouldering +coldshoulders +cole +colead +coleader +coleaders +coleading +coleads +colectomies +colectomy +coled +colemanite +colemanites +coleopteran +coleopterous +coleoptile +coleoptiles +coleorhiza +coleorhizae +coleridge +coles +coleslaw +coleus +coleuses +colewort +coleworts +coli +colic +colicin +colicins +colicky +colicroot +colicroots +coliform +colinear +colinearity +coliseum +coliseums +colistin +colistins +colitis +collaborate +collaborated +collaborates +collaborating +collaboration +collaborationism +collaborationist +collaborationists +collaborations +collaborative +collaboratively +collaborator +collaborators +collage +collaged +collagen +collagenase +collagenases +collagenic +collagenous +collages +collaging +collagist +collagists +collapse +collapsed +collapses +collapsibility +collapsible +collapsing +collar +collarbone +collarbones +collard +collards +collared +collaring +collars +collate +collated +collateral +collateralize +collateralized +collateralizes +collateralizing +collaterally +collates +collating +collation +collations +collator +collators +colleague +colleagues +colleagueship +collect +collectable +collectables +collectanea +collected +collectedly +collectedness +collectible +collectibles +collecting +collection +collections +collective +collectively +collectiveness +collectives +collectivism +collectivist +collectivistic +collectivistically +collectivists +collectivities +collectivity +collectivization +collectivize +collectivized +collectivizes +collectivizing +collector +collectors +collectorship +collects +colleen +colleens +college +colleges +collegia +collegial +collegiality +collegially +collegian +collegians +collegiate +collegium +collegiums +collembolan +collembolans +collenchyma +collenchymas +collenchymatous +collenchyme +collenchymes +collet +collets +collide +collided +collider +colliders +collides +colliding +collie +collier +collieries +colliers +colliery +collies +colligate +colligated +colligates +colligating +colligation +colligative +collimate +collimated +collimates +collimating +collimation +collimator +collimators +collinear +collinearity +collingwood +collins +collinsia +collision +collisional +collisions +collocate +collocated +collocates +collocating +collocation +collocational +collocations +collodion +collogue +collogued +collogues +colloguing +colloid +colloidal +colloidally +colloids +collop +collops +colloquia +colloquial +colloquialism +colloquialisms +colloquially +colloquialness +colloquies +colloquium +colloquiums +colloquy +collotype +collotypes +collude +colluded +colluder +colluders +colludes +colluding +collusion +collusive +collusively +collusiveness +colluvia +colluvial +colluvium +colluviums +collyria +collyrium +collyriums +collywobbles +coloboma +colobomata +colobomatous +colocynth +colocynths +cologne +colognes +colombia +colombian +colombians +colombo +colon +colonel +colonelcy +colonels +colonelship +colonial +colonialism +colonialist +colonialists +colonially +colonials +colonic +colonies +colonist +colonists +colonitis +colonization +colonizations +colonize +colonized +colonizer +colonizers +colonizes +colonizing +colonnade +colonnaded +colonnades +colonoscope +colonoscopes +colonoscopies +colonoscopy +colons +colony +colophon +colophons +color +colorability +colorable +colorableness +colorably +colorado +colorant +colorants +coloration +coloratura +coloraturas +colorblind +colorblindness +colorbred +colorbreed +colorbreeding +colorbreeds +colorcast +colorcasted +colorcasting +colorcasts +colorectal +colored +coloreds +colorer +colorers +colorfast +colorfastness +colorful +colorfully +colorfulness +colorific +colorimeter +colorimeters +colorimetric +colorimetrically +colorimetry +coloring +colorings +colorist +coloristic +colorists +colorization +colorizations +colorize +colorized +colorizer +colorizers +colorizes +colorizing +colorless +colorlessly +colorlessness +colors +coloscope +coloscopes +coloscopies +coloscopy +colossal +colossally +colosseum +colossi +colossians +colossus +colossuses +colostomies +colostomy +colostral +colostrum +colpitis +colportage +colportages +colporteur +colporteurs +colposcope +colposcopes +colposcopic +colposcopies +colposcopy +cols +colt +coltish +coltishly +coltishness +colts +coltsfoot +coltsfoots +colubrid +colubrids +colubrine +colugo +colugos +columba +columbaria +columbarium +columbia +columbian +columbine +columbines +columbite +columbites +columbium +columbus +columella +columellae +columellar +columellate +column +columnar +columnea +columned +columniation +columniations +columnist +columnists +columns +colza +colzas +coma +comae +comal +comanage +comanaged +comanagement +comanager +comanagers +comanages +comanaging +comanche +comanches +comas +comate +comates +comatose +comatosely +comatulid +comatulids +comb +combat +combatant +combatants +combated +combating +combative +combatively +combativeness +combats +combed +comber +combers +combinable +combination +combinational +combinations +combinative +combinatorial +combinatorics +combinatory +combine +combined +combiner +combiners +combines +combing +combings +combining +combinings +combo +combos +combs +combust +combusted +combustibility +combustible +combustibles +combustibly +combusting +combustion +combustive +combustor +combustors +combusts +come +comeback +comebacks +comecon +comedian +comedians +comedic +comedically +comedienne +comediennes +comedies +comedo +comedogenic +comedones +comedos +comedown +comedowns +comedy +comelier +comeliest +comeliness +comely +comember +comembers +comer +comers +comes +comestible +comestibles +comet +cometary +cometic +comets +comeuppance +comfier +comfiest +comfit +comfits +comfort +comfortable +comfortableness +comfortably +comforted +comforter +comforters +comforting +comfortingly +comfortless +comfortlessly +comforts +comfrey +comfreys +comfy +comic +comical +comicality +comically +comicalness +comice +comices +comics +coming +comings +comintern +comique +comitia +comitial +comities +comity +comix +comma +command +commandant +commandants +commanded +commandeer +commandeered +commandeering +commandeers +commander +commanders +commanding +commandingly +commandingness +commandment +commandments +commando +commandos +commands +commas +comme +commedia +commemorate +commemorated +commemorates +commemorating +commemoration +commemorations +commemorative +commemoratives +commemorator +commemorators +commemoratory +commence +commenced +commencement +commencements +commencer +commencers +commences +commencing +commend +commendable +commendableness +commendably +commendation +commendations +commendatory +commended +commending +commends +commensal +commensalism +commensally +commensals +commensurability +commensurable +commensurably +commensurate +commensurately +commensuration +comment +commentarial +commentaries +commentary +commentate +commentated +commentates +commentating +commentator +commentators +commented +commenting +comments +commerce +commercial +commercialism +commercialist +commercialistic +commercialists +commercialization +commercialize +commercialized +commercializes +commercializing +commercially +commercials +commie +commies +commination +comminations +comminatory +commingle +commingled +commingles +commingling +comminute +comminuted +comminutes +comminuting +comminution +comminutions +commiserate +commiserated +commiserates +commiserating +commiseration +commiserations +commiserative +commiseratively +commiserator +commiserators +commissar +commissariat +commissariats +commissaries +commissars +commissary +commission +commissionaire +commissionaires +commissional +commissioned +commissioner +commissioners +commissionership +commissioning +commissions +commissural +commissure +commissures +commissurotomies +commissurotomy +commit +commitment +commitments +commits +committable +committal +committals +committed +committee +committeeman +committeemen +committees +committeewoman +committeewomen +committing +commix +commixed +commixes +commixing +commixture +commixtures +commode +commodes +commodious +commodiously +commodiousness +commodities +commodity +commodore +commodores +common +commonage +commonages +commonalities +commonality +commonalties +commonalty +commoner +commoners +commonest +commonly +commonness +commonplace +commonplaceness +commonplaces +commons +commonsense +commonsensible +commonsensibly +commonsensical +commonweal +commonwealth +commonwealths +commotion +commove +commoved +commoves +commoving +communal +communalism +communalist +communalistic +communalists +communality +communalize +communalized +communalizes +communalizing +communally +communard +communards +commune +communed +communes +communicability +communicable +communicableness +communicably +communicant +communicants +communicate +communicated +communicates +communicating +communication +communicational +communications +communicative +communicatively +communicativeness +communicator +communicators +communicatory +communing +communion +communions +communiqué +communiqués +communism +communist +communistic +communistically +communists +communitarian +communitarians +communities +community +communization +communize +communized +communizes +communizing +commutability +commutable +commutate +commutated +commutates +commutating +commutation +commutations +commutative +commutativity +commutator +commutators +commute +commuted +commuter +commuters +commutes +commuting +como +comonomer +comonomers +comoran +comorans +comoros +comose +comp +compact +compacted +compacting +compaction +compactions +compactly +compactness +compactor +compactors +compacts +companied +companies +companion +companionable +companionableness +companionably +companionate +companioned +companioning +companionless +companions +companionship +companionships +companionway +companionways +company +companying +comparability +comparable +comparableness +comparably +comparatist +comparatists +comparative +comparatively +comparatives +comparator +comparators +compare +compared +comparer +comparers +compares +comparing +comparison +comparisons +comparitor +compart +comparted +comparting +compartment +compartmental +compartmentalization +compartmentalize +compartmentalized +compartmentalizes +compartmentalizing +compartmentation +compartmented +compartmenting +compartments +comparts +compass +compassable +compassed +compasses +compassing +compassion +compassionate +compassionated +compassionately +compassionateness +compassionates +compassionating +compassionless +compatibility +compatible +compatibleness +compatibles +compatibly +compatriot +compatriotic +compatriots +comped +compeer +compeers +compel +compellable +compellably +compellation +compellations +compelled +compeller +compellers +compelling +compellingly +compels +compend +compendia +compendious +compendiously +compendiousness +compendium +compendiums +compends +compensable +compensate +compensated +compensates +compensating +compensation +compensational +compensations +compensative +compensator +compensators +compensatory +compere +compered +comperes +compering +compete +competed +competence +competencies +competency +competent +competently +competes +competing +competition +competitions +competitive +competitively +competitiveness +competitor +competitors +compilation +compilations +compile +compiled +compiler +compilers +compiles +compiling +comping +complacence +complacency +complacent +complacently +complain +complainant +complainants +complained +complainer +complainers +complaining +complains +complaint +complaints +complaisance +complaisant +complaisantly +compleat +complect +complected +complecting +complects +complement +complemental +complementally +complementarily +complementariness +complementarity +complementary +complementation +complementations +complemented +complementing +complements +complete +completed +completely +completeness +completer +completes +completest +completing +completion +completions +completive +complex +complexes +complexion +complexional +complexioned +complexions +complexities +complexity +complexly +complexness +compliance +compliancy +compliant +compliantly +complicacies +complicacy +complicate +complicated +complicatedly +complicatedness +complicates +complicating +complication +complications +complicit +complicities +complicity +complied +complier +compliers +complies +compliment +complimentarily +complimentary +complimented +complimenting +compliments +complin +compline +complins +complot +complots +comply +complying +compo +component +componential +components +componentwise +comport +comported +comporting +comportment +comports +compos +compose +composed +composedly +composedness +composer +composers +composes +composing +composite +compositely +compositeness +composites +composition +compositional +compositionally +compositions +compositive +compositor +compositorial +compositors +compost +composted +compostela +composting +composts +composure +compote +compotes +compound +compoundable +compounded +compounder +compounding +compounds +comprador +compradors +comprehend +comprehended +comprehendible +comprehending +comprehendingly +comprehends +comprehensibility +comprehensible +comprehensibleness +comprehensibly +comprehension +comprehensions +comprehensive +comprehensively +comprehensiveness +comprehensives +compress +compressed +compresses +compressibility +compressible +compressibleness +compressing +compression +compressional +compressions +compressive +compressively +compressor +compressors +comprisable +comprise +comprised +comprises +comprising +compromise +compromised +compromiser +compromisers +compromises +compromising +comps +comptroller +comptrollers +compulsion +compulsions +compulsive +compulsively +compulsiveness +compulsives +compulsivity +compulsories +compulsorily +compulsoriness +compulsory +compunction +compunctions +compunctious +compunctiously +compurgation +compurgations +compurgator +compurgators +computability +computable +computably +computation +computational +computationally +computations +compute +computed +computer +computerate +computerdom +computerdoms +computerese +computerist +computerists +computerizable +computerization +computerize +computerized +computerizes +computerizing +computers +computes +computing +compôte +compôtes +comrade +comradely +comrades +comradeship +comsat +comsymp +comsymps +comus +comédie +con +conakry +conan +conation +conational +conations +conative +concatenate +concatenated +concatenates +concatenating +concatenation +concatenations +concave +concaved +concavely +concaveness +concaves +concaving +concavities +concavity +conceal +concealable +concealed +concealer +concealers +concealing +concealment +conceals +concede +conceded +concededly +conceder +conceders +concedes +conceding +conceit +conceited +conceitedly +conceitedness +conceiting +conceits +conceivability +conceivable +conceivableness +conceivably +conceive +conceived +conceiver +conceivers +conceives +conceiving +concelebrant +concelebrants +concelebrate +concelebrated +concelebrates +concelebrating +concelebration +concelebrations +concenter +concentered +concentering +concenters +concentrate +concentrated +concentrates +concentrating +concentration +concentrations +concentrative +concentratively +concentrator +concentrators +concentric +concentrically +concentricity +concept +conceptacle +conceptacles +conception +conceptional +conceptions +conceptive +conceptively +concepts +conceptual +conceptualism +conceptualist +conceptualistic +conceptualistically +conceptualists +conceptuality +conceptualization +conceptualizations +conceptualize +conceptualized +conceptualizer +conceptualizers +conceptualizes +conceptualizing +conceptually +conceptus +concern +concerned +concernedly +concerning +concernment +concernments +concerns +concert +concerted +concertedly +concertgoer +concertgoers +concertgoing +concerti +concertina +concertinas +concerting +concertino +concertinos +concertize +concertized +concertizes +concertizing +concertmaster +concertmasters +concertmistress +concertmistresses +concerto +concertos +concerts +concession +concessionaire +concessionaires +concessional +concessionary +concessioner +concessioners +concessions +concessive +concessively +conch +concha +conchae +conchal +conches +conchiferous +conchiolin +conchiolins +conchoidal +conchoidally +conchological +conchologist +conchologists +conchology +conchs +concierge +concierges +conciliable +conciliar +conciliate +conciliated +conciliates +conciliating +conciliation +conciliations +conciliator +conciliators +conciliatory +concinnities +concinnity +concise +concisely +conciseness +concision +concisions +conclave +conclaves +conclude +concluded +concluder +concluders +concludes +concluding +conclusion +conclusions +conclusive +conclusively +conclusiveness +conclusory +concoct +concocted +concocter +concocters +concocting +concoction +concoctions +concocts +concomitance +concomitant +concomitantly +concomitants +concord +concordance +concordances +concordant +concordantly +concordat +concordats +concords +concours +concourse +concourses +concrescence +concrescent +concrete +concreted +concretely +concreteness +concretes +concreting +concretion +concretionary +concretions +concretism +concretisms +concretist +concretists +concretization +concretize +concretized +concretizes +concretizing +concrète +concubinage +concubinages +concubine +concubines +concupiscence +concupiscent +concur +concurred +concurrence +concurrencies +concurrency +concurrent +concurrently +concurring +concurs +concuss +concussed +concusses +concussing +concussion +concussions +concussive +concussively +condemn +condemnable +condemnation +condemnations +condemnatory +condemned +condemner +condemners +condemning +condemns +condensability +condensable +condensate +condensates +condensation +condensational +condensations +condense +condensed +condenser +condensers +condenses +condensing +condescend +condescended +condescendence +condescendences +condescender +condescenders +condescending +condescendingly +condescends +condescension +condign +condignly +condiment +condimental +condiments +condition +conditional +conditionally +conditionals +conditioned +conditioner +conditioners +conditioning +conditionings +conditions +condo +condolatory +condole +condoled +condolence +condolences +condolent +condoler +condolers +condoles +condoling +condom +condominial +condominium +condominiums +condoms +condonable +condonation +condonations +condone +condoned +condoner +condoners +condones +condoning +condor +condors +condos +condottiere +condottieri +conduce +conduced +conducer +conducers +conduces +conducing +conducingly +conducive +conduciveness +conduct +conductance +conducted +conductibility +conductible +conductimetry +conducting +conduction +conductive +conductivities +conductivity +conductor +conductorial +conductors +conductorship +conductress +conductresses +conducts +conduit +conduits +conduplicate +conduplication +condylar +condyle +condyles +condyloid +condyloma +condylomas +condylomata +condylomatous +cone +coned +coneflower +coneflowers +conenose +cones +conestoga +conestogas +coney +coneys +confab +confabbed +confabbing +confabs +confabulate +confabulated +confabulates +confabulating +confabulation +confabulations +confabulator +confabulators +confabulatory +confect +confected +confecting +confection +confectionaries +confectionary +confectioned +confectioner +confectioneries +confectioners +confectionery +confectioning +confections +confects +confederacies +confederacy +confederal +confederalist +confederalists +confederate +confederated +confederates +confederating +confederation +confederationism +confederationist +confederationists +confederations +confederative +confer +conferee +conferees +conference +conferences +conferencing +conferential +conferment +conferrable +conferral +conferrals +conferred +conferrer +conferrers +conferring +confers +confess +confessable +confessed +confessedly +confesses +confessing +confession +confessional +confessionals +confessions +confessor +confessors +confetti +confidant +confidante +confidantes +confidants +confide +confided +confidence +confidences +confident +confidential +confidentiality +confidentially +confidentialness +confidently +confider +confiders +confides +confiding +confidingly +confidingness +configurable +configuration +configurational +configurationally +configurationism +configurations +configurative +configure +configured +configures +configuring +confinable +confine +confined +confinement +confinements +confiner +confiners +confines +confining +confirm +confirmability +confirmable +confirmand +confirmands +confirmation +confirmations +confirmatory +confirmed +confirmedly +confirmer +confirmers +confirming +confirms +confiscable +confiscate +confiscated +confiscates +confiscating +confiscation +confiscations +confiscator +confiscators +confiscatory +confiteor +confiteors +confiture +confitures +conflagrant +conflagration +conflagrations +conflate +conflated +conflates +conflating +conflation +conflations +conflict +conflicted +conflicting +confliction +conflictive +conflicts +conflictual +confluence +confluences +confluent +confluents +conflux +confluxes +confocal +confocally +conform +conformability +conformable +conformableness +conformably +conformal +conformance +conformant +conformation +conformational +conformationally +conformations +conformed +conformer +conformers +conforming +conformist +conformists +conformities +conformity +conforms +confound +confounded +confoundedly +confoundedness +confounder +confounders +confounding +confounds +confraternities +confraternity +confrere +confreres +confront +confrontation +confrontational +confrontationist +confrontationists +confrontations +confrontative +confronted +confronter +confronters +confronting +confrontment +confronts +confucian +confucianism +confucianist +confucianists +confucians +confucius +confusable +confuse +confused +confusedly +confusedness +confuser +confusers +confuses +confusing +confusingly +confusion +confusional +confusions +confutable +confutation +confutative +confute +confuted +confuter +confuters +confutes +confuting +conga +congaed +congaing +congas +congeal +congealable +congealed +congealer +congealers +congealing +congealment +congeals +congelation +congelations +congener +congeneric +congenerous +congeners +congenial +congeniality +congenially +congenialness +congenital +congenitally +conger +congeries +congers +congest +congested +congesting +congestion +congestive +congests +congii +congius +conglobate +conglobated +conglobates +conglobating +conglobation +conglobe +conglobed +conglobes +conglobing +conglomerate +conglomerated +conglomerates +conglomeratic +conglomerating +conglomeration +conglomerations +conglomerator +conglomerators +conglutinate +conglutinated +conglutinates +conglutinating +conglutination +congo +congolese +congou +congous +congratulate +congratulated +congratulates +congratulating +congratulation +congratulations +congratulator +congratulators +congratulatory +congregant +congregants +congregate +congregated +congregates +congregating +congregation +congregational +congregationalism +congregationalist +congregationalists +congregations +congregative +congregativeness +congregator +congregators +congress +congresses +congressional +congressionally +congressman +congressmen +congresspeople +congressperson +congresspersons +congresswoman +congresswomen +congreve +congruence +congruences +congruencies +congruency +congruent +congruently +congruities +congruity +congruous +congruously +congruousness +congé +conic +conical +conics +conidia +conidial +conidiophore +conidiophores +conidiophorous +conidium +conies +conifer +coniferous +conifers +coniine +coniines +coning +conium +coniums +conjecturable +conjecturably +conjectural +conjecturally +conjecture +conjectured +conjecturer +conjecturers +conjectures +conjecturing +conjoin +conjoined +conjoiner +conjoiners +conjoining +conjoins +conjoint +conjointly +conjugal +conjugality +conjugally +conjugant +conjugants +conjugate +conjugated +conjugately +conjugates +conjugating +conjugation +conjugational +conjugationally +conjugations +conjugative +conjugator +conjugators +conjunct +conjunction +conjunctional +conjunctionally +conjunctions +conjunctiva +conjunctivae +conjunctival +conjunctivas +conjunctive +conjunctively +conjunctives +conjunctivitis +conjunctly +conjuncts +conjuncture +conjunctures +conjunto +conjuntos +conjuration +conjure +conjured +conjurer +conjurers +conjures +conjuring +conjuror +conjurors +conk +conked +conker +conkers +conking +conks +conky +connate +connately +connateness +connatural +connaturality +connaturally +connaturalness +connect +connectable +connected +connectedly +connectedness +connectible +connecticut +connecting +connection +connectional +connectionless +connections +connective +connectively +connectives +connectivity +connector +connectors +connects +conned +conner +conners +conning +conniption +conniptions +connivance +connive +connived +connivent +conniver +connivers +connivery +connives +conniving +connoisseur +connoisseurs +connoisseurship +connotation +connotations +connotative +connotatively +connote +connoted +connotes +connoting +connubial +connubialism +connubiality +connubially +conodont +conodonts +conoid +conoids +conominee +conominees +conquer +conquerable +conquered +conquering +conqueror +conquerors +conquers +conquest +conquests +conquian +conquians +conquistador +conquistadors +conrad +cons +consanguine +consanguineous +consanguineously +consanguinities +consanguinity +conscience +conscienceless +consciences +conscientious +conscientiously +conscientiousness +conscionable +conscious +consciously +consciousness +conscript +conscripted +conscripting +conscription +conscripts +consecrate +consecrated +consecrates +consecrating +consecration +consecrations +consecrative +consecrator +consecrators +consecratory +consecution +consecutive +consecutively +consecutiveness +consensual +consensually +consensus +consensuses +consent +consentaneity +consentaneous +consentaneously +consentaneousness +consented +consenter +consenters +consenting +consents +consequence +consequences +consequent +consequential +consequentialities +consequentiality +consequentially +consequentialness +consequently +consequents +conservable +conservancies +conservancy +conservation +conservational +conservationist +conservationists +conservations +conservatism +conservative +conservatively +conservativeness +conservatives +conservatize +conservatized +conservatizes +conservatizing +conservatoire +conservatoires +conservator +conservatorial +conservatories +conservators +conservatorship +conservatory +conserve +conserved +conserver +conservers +conserves +conserving +consider +considerable +considerably +considerate +considerately +considerateness +consideration +considerations +considered +considerer +considerers +considering +considers +consigliere +consiglieri +consign +consignable +consignation +consigned +consignee +consignees +consigning +consignment +consignments +consignor +consignors +consigns +consist +consisted +consistence +consistencies +consistency +consistent +consistently +consisting +consistorial +consistories +consistory +consists +consociate +consociated +consociates +consociating +consociation +consociational +consociations +consolable +consolably +consolation +consolations +consolatory +console +consoled +consoler +consolers +consoles +consolidate +consolidated +consolidates +consolidating +consolidation +consolidations +consolidator +consolidators +consoling +consolingly +consolute +consommé +consommés +consonance +consonant +consonantal +consonantally +consonantly +consonants +consort +consorted +consortia +consortial +consorting +consortium +consortiums +consorts +conspecific +conspecifics +conspectus +conspectuses +conspicuity +conspicuous +conspicuously +conspicuousness +conspiracies +conspiracist +conspiracists +conspiracy +conspirator +conspiratorial +conspiratorialist +conspiratorialists +conspiratorially +conspirators +conspire +conspired +conspirer +conspirers +conspires +conspiring +conspiringly +constable +constables +constableship +constabular +constabularies +constabulary +constance +constancy +constant +constantan +constantans +constantine +constantinople +constantly +constants +constellate +constellated +constellates +constellating +constellation +constellational +constellations +constellatory +consternate +consternated +consternates +consternating +consternation +constipate +constipated +constipates +constipating +constipation +constituencies +constituency +constituent +constituently +constituents +constitute +constituted +constituter +constituters +constitutes +constituting +constitution +constitutional +constitutionalism +constitutionalist +constitutionalists +constitutionality +constitutionalization +constitutionalize +constitutionalized +constitutionalizes +constitutionalizing +constitutionally +constitutionals +constitutions +constitutive +constitutively +constrain +constrainable +constrained +constrainedly +constrainer +constrainers +constraining +constrains +constraint +constraints +constrict +constricted +constricting +constriction +constrictions +constrictive +constrictively +constrictor +constrictors +constricts +constringe +constringed +constringency +constringent +constringes +constringing +construal +construct +constructed +constructible +constructing +construction +constructional +constructionally +constructionist +constructionists +constructions +constructive +constructively +constructiveness +constructivism +constructivisms +constructivist +constructivists +constructor +constructors +constructs +construe +construed +construes +construing +consubstantial +consubstantiate +consubstantiated +consubstantiates +consubstantiating +consubstantiation +consubstantiations +consuetude +consuetudinary +consul +consular +consulate +consulates +consuls +consulship +consult +consultancies +consultancy +consultant +consultants +consultantship +consultation +consultations +consultative +consulted +consulter +consulters +consulting +consultor +consultors +consults +consumable +consumables +consume +consumed +consumedly +consumer +consumerism +consumerist +consumeristic +consumerists +consumers +consumership +consumes +consuming +consummate +consummated +consummately +consummates +consummating +consummation +consummations +consummative +consummator +consummators +consummatory +consumption +consumptive +consumptively +consumptives +contact +contacted +contacting +contacts +contactual +contactually +contagia +contagion +contagious +contagiously +contagiousness +contagium +contain +containable +contained +container +containerboard +containerboards +containerization +containerize +containerized +containerizes +containerizing +containerport +containerports +containers +containership +containing +containment +containments +contains +contaminant +contaminants +contaminate +contaminated +contaminates +contaminating +contamination +contaminations +contaminative +contaminator +contaminators +conte +contemn +contemned +contemner +contemners +contemning +contemns +contemplate +contemplated +contemplates +contemplating +contemplation +contemplations +contemplative +contemplatively +contemplativeness +contemplatives +contemplator +contemplators +contemporaneity +contemporaneous +contemporaneously +contemporaneousness +contemporaries +contemporarily +contemporary +contemporization +contemporize +contemporized +contemporizes +contemporizing +contempt +contemptibility +contemptible +contemptibleness +contemptibly +contempts +contemptuous +contemptuously +contemptuousness +contend +contended +contender +contenders +contending +contends +content +contented +contentedly +contentedness +contenting +contention +contentions +contentious +contentiously +contentiousness +contentment +contents +conterminous +conterminously +conterminousness +contes +contessa +contessas +contest +contestable +contestant +contestants +contestation +contested +contester +contesters +contesting +contests +context +contexts +contextual +contextualization +contextualize +contextualized +contextualizes +contextualizing +contextually +contextural +contexture +contextures +contiguities +contiguity +contiguous +contiguously +contiguousness +continence +continent +continental +continentalism +continentalist +continentalists +continentality +continentally +continentals +continently +continents +contingence +contingencies +contingency +contingent +contingently +contingents +continua +continuable +continual +continually +continuance +continuances +continuant +continuants +continuation +continuations +continuative +continuatively +continuatives +continuator +continuators +continue +continued +continuer +continuers +continues +continuing +continuities +continuity +continuo +continuos +continuous +continuously +continuousness +continuum +continuums +contort +contorted +contortedly +contortedness +contorting +contortion +contortionist +contortionistic +contortionists +contortions +contortive +contorts +contour +contoured +contouring +contours +contra +contraband +contrabandage +contrabandist +contrabandists +contrabands +contrabass +contrabasses +contrabassist +contrabassists +contrabassoon +contrabassoons +contraception +contraceptive +contraceptives +contract +contracted +contractibility +contractible +contractibleness +contractile +contractility +contracting +contraction +contractions +contractor +contractors +contracts +contractual +contractually +contracture +contractures +contracyclical +contradance +contradances +contradict +contradictable +contradicted +contradicter +contradicters +contradicting +contradiction +contradictions +contradictor +contradictories +contradictorily +contradictoriness +contradictors +contradictory +contradicts +contradistinction +contradistinctions +contradistinctive +contradistinctively +contradistinguish +contradistinguished +contradistinguishes +contradistinguishing +contragestation +contragestive +contragestives +contrail +contrails +contraindicate +contraindicated +contraindicates +contraindicating +contraindication +contraindications +contraindicative +contraire +contralateral +contralto +contraltos +contraposition +contrapositions +contrapositive +contrapositives +contrapposto +contrappostos +contraption +contraptions +contrapuntal +contrapuntally +contrapuntist +contrapuntists +contrarian +contrarians +contraries +contrarieties +contrariety +contrarily +contrariness +contrarious +contrariously +contrariwise +contrary +contras +contrast +contrasted +contrasting +contrastive +contrastively +contrasts +contrasty +contrate +contravariance +contravene +contravened +contravener +contraveners +contravenes +contravening +contravention +contretemps +contribute +contributed +contributes +contributing +contribution +contributions +contributive +contributively +contributiveness +contributor +contributories +contributors +contributory +contrite +contritely +contriteness +contrition +contrivance +contrivances +contrive +contrived +contrivedly +contriver +contrivers +contrives +contriving +control +controllability +controllable +controllably +controlled +controller +controllers +controllership +controlling +controls +controversial +controversialist +controversialists +controversiality +controversially +controversies +controversy +controvert +controverted +controvertibility +controvertible +controvertibly +controverting +controverts +contumacies +contumacious +contumaciously +contumaciousness +contumacy +contumelies +contumelious +contumeliously +contumely +contuse +contused +contuses +contusing +contusion +contusions +conundrum +conundrums +conurbation +convalesce +convalesced +convalescence +convalescent +convalescents +convalesces +convalescing +convect +convected +convecting +convection +convectional +convective +convectively +convector +convectors +convects +convenable +convene +convened +convener +conveners +convenes +convenience +conveniences +conveniencies +conveniency +convenient +conveniently +convening +convent +conventicle +conventicler +conventiclers +conventicles +convention +conventional +conventionalism +conventionalist +conventionalists +conventionalities +conventionality +conventionalization +conventionalize +conventionalized +conventionalizes +conventionalizing +conventionally +conventioneer +conventioneers +conventions +convents +conventual +conventuals +converge +converged +convergence +convergencies +convergency +convergent +converges +converging +conversance +conversances +conversancies +conversancy +conversant +conversantly +conversation +conversational +conversationalist +conversationalists +conversationally +conversations +conversazione +conversaziones +converse +conversed +conversely +converses +conversing +conversion +conversional +conversionary +conversions +convert +converted +converter +converters +convertibility +convertible +convertibleness +convertibles +convertibly +converting +convertiplane +convertiplanes +converts +convex +convexities +convexity +convexly +convey +conveyable +conveyance +conveyancer +conveyancers +conveyances +conveyancing +conveyancings +conveyed +conveyer +conveyers +conveying +conveyor +conveyors +conveys +convict +convicted +convicting +conviction +convictional +convictions +convictive +convictively +convicts +convince +convinced +convincement +convincer +convincers +convinces +convincible +convincing +convincingly +convincingness +convivial +conviviality +convivially +convocation +convocational +convocations +convoke +convoked +convoker +convokers +convokes +convoking +convolute +convoluted +convolutely +convolutes +convoluting +convolution +convolutional +convolutions +convolve +convolved +convolves +convolving +convolvuli +convolvulus +convolvuluses +convoy +convoyed +convoying +convoys +convulsant +convulsants +convulse +convulsed +convulses +convulsing +convulsion +convulsions +convulsive +convulsively +convulsiveness +cony +coo +cooed +cooer +cooers +cooing +cook +cookbook +cookbooks +cooked +cooker +cookeries +cookers +cookery +cookhouse +cookhouses +cookie +cookies +cooking +cookout +cookouts +cooks +cooktown +cookware +cool +coolant +coolants +cooled +cooler +coolers +coolest +coolgardie +coolheaded +coolie +coolies +cooling +coolish +coolly +coolness +cools +coon +cooncan +cooncans +coonhound +coonhounds +coons +coonskin +coonskins +coontie +coonties +coop +cooped +cooper +cooperage +cooperate +cooperated +cooperates +cooperating +cooperation +cooperationist +cooperationists +cooperative +cooperatively +cooperativeness +cooperatives +cooperator +cooperators +coopers +cooping +coops +coordinate +coordinated +coordinately +coordinateness +coordinates +coordinating +coordination +coordinations +coordinative +coordinator +coordinators +coos +coot +cootie +cooties +coots +cop +copacetic +copaiba +copal +coparcenaries +coparcenary +coparcener +coparceners +copartner +copartners +copartnership +cope +coped +copenhagen +copepod +copepods +coper +copernican +copernicans +copernicus +copers +copes +copestone +copestones +copied +copier +copiers +copies +copilot +copilots +coping +copings +copious +copiously +copiousness +coplanar +coplanarity +copland +copolymer +copolymeric +copolymerization +copolymerize +copolymerized +copolymerizes +copolymerizing +copolymers +copout +copouts +copped +copper +copperas +coppered +copperfield +copperhead +copperheads +coppering +copperleaf +copperleafs +copperplate +copperplates +coppers +coppersmith +coppersmiths +copperware +copperwares +coppery +coppice +coppices +copping +copra +copresent +copresented +copresenting +copresents +copresident +copresidents +coprince +coprinces +coprincipal +coprincipals +coprisoner +coprisoners +coprocessing +coprocessor +coprocessors +coproduce +coproduced +coproducer +coproducers +coproduces +coproducing +coproduction +coproductions +coprolalia +coprolalias +coprolite +coprolites +coprolitic +coprology +copromoter +copromoters +coprophagous +coprophagy +coprophilia +coprophiliac +coprophiliacs +coprophilic +coprophilous +coproprietor +coproprietors +coprosperity +cops +copse +copses +copt +copter +copters +coptic +copts +copublish +copublished +copublisher +copublishers +copublishes +copublishing +copula +copular +copulas +copulate +copulated +copulates +copulating +copulation +copulations +copulative +copulatively +copulatory +copy +copyable +copybook +copybooks +copyboy +copyboys +copycat +copycats +copycatted +copycatting +copydesk +copydesks +copyedit +copyedited +copyediting +copyeditor +copyeditors +copyedits +copyholder +copyholders +copying +copyist +copyists +copyreader +copyreaders +copyright +copyrightable +copyrighted +copyrighter +copyrighters +copyrighting +copyrights +copywriter +copywriters +coq +coquet +coquetries +coquetry +coquets +coquette +coquetted +coquettes +coquetting +coquettish +coquettishly +coquettishness +coquille +coquilles +coquina +coquinas +coquito +coquitos +coracle +coracles +coracoid +coracoids +coral +coralberries +coralberry +coralline +corallines +coralloid +coralroot +coralroots +corals +corban +corbans +corbeil +corbeils +corbel +corbeled +corbeling +corbelings +corbels +corbina +corbinas +corbusier +corcovado +cord +cordage +cordate +cordately +corded +cordelia +corder +corders +cordial +cordiale +cordiality +cordially +cordialness +cordials +cordierite +cordierites +cordiform +cordillera +cordilleran +cordilleras +cording +cordite +cordless +cordlessly +cordoba +cordon +cordoned +cordoning +cordons +cordova +cordovan +cordovans +cords +corduroy +corduroyed +corduroying +corduroys +cordwood +core +corecipient +corecipients +cored +coreligionist +coreligionists +coreopsis +corepressor +corepressors +corer +corers +cores +coresearcher +coresearchers +coresident +coresidential +coresidents +corespondency +corespondent +corespondents +corf +corfu +corgi +corgis +coria +coriaceous +coriander +coring +corinth +corinthian +corinthians +coriolanus +corium +cork +corkage +corkages +corkboard +corkboards +corked +corker +corkers +corkier +corkiest +corkiness +corking +corks +corkscrew +corkscrewed +corkscrewing +corkscrews +corkwood +corkwoods +corky +corm +cormel +cormels +cormorant +cormorants +corms +corn +cornball +cornballs +cornbraid +cornbraided +cornbraiding +cornbraids +cornbread +corncob +corncobs +corncrake +corncrakes +corncrib +corncribs +corndodger +corndodgers +cornea +corneal +corneas +corned +corneitis +cornel +cornell +cornels +corneous +corner +cornerback +cornerbacks +cornered +cornering +corners +cornerstone +cornerstones +cornerwise +cornet +cornetist +cornetists +cornets +cornfield +cornfields +cornflower +cornflowers +cornhusk +cornhusker +cornhuskers +cornhusking +cornhuskings +cornhusks +cornice +corniced +cornices +corniche +cornicing +cornicle +cornicles +corniculate +cornier +corniest +cornification +cornifications +cornified +cornifies +cornify +cornifying +cornily +corniness +corning +cornish +cornishman +cornishmen +cornishwoman +cornishwomen +cornmeal +cornpone +cornrow +cornrowed +cornrowing +cornrows +corns +cornstalk +cornstalks +cornstarch +cornu +cornua +cornual +cornucopia +cornucopian +cornucopias +cornute +cornwall +corny +corolla +corollaries +corollary +corollas +corollate +corona +coronae +coronagraph +coronagraphs +coronal +coronals +coronaries +coronary +coronas +coronation +coronations +coroner +coroners +coronership +coronet +coronets +corot +corotate +corotated +corotates +corotating +corotation +corotational +coroutine +coroutines +corpocracies +corpocracy +corpocratic +corpora +corporal +corporality +corporally +corporals +corporate +corporately +corporation +corporations +corporative +corporator +corporators +corporeal +corporeality +corporeally +corporealness +corporeity +corposant +corposants +corps +corpse +corpses +corpsman +corpsmen +corpulence +corpulent +corpulently +corpus +corpuscle +corpuscles +corpuscular +corpuses +corrade +corraded +corrades +corrading +corral +corralled +corralling +corrals +corrasion +corrasive +correct +correctable +corrected +correcting +correction +correctional +corrections +correctitude +correctitudes +corrective +correctively +correctives +correctly +correctness +corrector +correctors +corrects +correggio +correlate +correlated +correlates +correlating +correlation +correlational +correlations +correlative +correlatively +correlatives +correspond +corresponded +correspondence +correspondences +correspondencies +correspondency +correspondent +correspondently +correspondents +corresponding +correspondingly +corresponds +corresponsive +corresponsively +corrida +corridas +corridor +corridors +corrie +corries +corrigenda +corrigendum +corrigibility +corrigible +corrigibly +corrival +corrivalry +corrivals +corroborant +corroborate +corroborated +corroborates +corroborating +corroboration +corroborations +corroborative +corroborator +corroborators +corroboratory +corroboree +corroborees +corrode +corroded +corrodes +corrodible +corroding +corrosible +corrosion +corrosions +corrosive +corrosively +corrosiveness +corrosives +corrosivity +corrugate +corrugated +corrugates +corrugating +corrugation +corrugations +corrupt +corrupted +corrupter +corrupters +corruptibility +corruptible +corruptibleness +corruptibly +corrupting +corruption +corruptionist +corruptionists +corruptions +corruptive +corruptly +corruptness +corrupts +corsage +corsages +corsair +corsairs +corselet +corselets +corset +corseted +corseting +corsets +corsica +corsican +corsicans +cortege +corteges +cortex +cortexes +cortez +cortical +cortically +corticate +cortices +corticoid +corticoids +corticolous +corticospinal +corticosteroid +corticosteroids +corticosterone +corticosterones +corticotrophin +corticotrophins +corticotropin +corticotropins +cortin +cortins +cortisol +cortisols +cortisone +cortège +cortèges +coruler +corulers +corundum +corunna +coruscant +coruscate +coruscated +coruscates +coruscating +coruscation +coruscations +coruña +corves +corvette +corvettes +corvine +corvus +corvée +corybant +corybantes +corybantic +corybants +corydalis +corymb +corymbose +corymbosely +corymbous +corynebacterium +corynebacteriums +coryneform +coryphaei +coryphaeus +coryphée +coryphées +coryza +cosa +coscript +coscripted +coscripting +coscripts +cosec +cosecant +cosecants +coseismal +coseismic +cosign +cosignatories +cosignatory +cosigned +cosigner +cosigners +cosigning +cosigns +cosine +cosines +cosmetic +cosmetically +cosmetician +cosmeticians +cosmeticize +cosmeticized +cosmeticizes +cosmeticizing +cosmetics +cosmetologist +cosmetologists +cosmetology +cosmic +cosmically +cosmochemical +cosmochemistry +cosmodrome +cosmodromes +cosmogenic +cosmogonic +cosmogonical +cosmogonically +cosmogonies +cosmogonist +cosmogonists +cosmogony +cosmographer +cosmographers +cosmographic +cosmographical +cosmographically +cosmographies +cosmography +cosmologic +cosmological +cosmologically +cosmologies +cosmologist +cosmologists +cosmology +cosmonaut +cosmonauts +cosmopolis +cosmopolitan +cosmopolitanism +cosmopolitans +cosmopolite +cosmopolites +cosmopolitism +cosmos +cosmoses +cosponsor +cosponsored +cosponsoring +cosponsors +cosponsorship +cossack +cossacks +cosset +cosseted +cosseting +cossets +cost +costa +costae +costal +costar +costard +costards +costarred +costarring +costars +costate +costed +coster +costermonger +costermongers +costers +costing +costings +costive +costively +costiveness +costless +costlessness +costlier +costliest +costliness +costly +costmaries +costmary +costochondritis +costrel +costrels +costs +costume +costumed +costumer +costumers +costumes +costuming +cosurfactant +cosy +cot +cotangent +cotangential +cotangents +cote +cotenancy +cotenant +cotenants +coterie +coteries +coterminous +cotes +cothurni +cothurnus +cotidal +cotillion +cotillions +cotman +cotoneaster +cotoneasters +cotopaxi +cotransduce +cotransduced +cotransduces +cotransducing +cotransduction +cotransfer +cotransferred +cotransferring +cotransfers +cotransport +cotrustee +cotrustees +cots +cotswold +cotswolds +cotta +cottae +cottage +cottager +cottagers +cottages +cottas +cotter +cotters +cotton +cottoned +cottoning +cottonmouth +cottonmouths +cottons +cottonseed +cottonseeds +cottontail +cottontails +cottonweed +cottonweeds +cottonwood +cottonwoods +cottony +coturnix +coturnixs +cotyledon +cotyledonal +cotyledonous +cotyledons +cotyloid +couch +couchant +couched +coucher +couchers +couches +couchette +couchettes +couching +cougar +cougars +cough +coughed +coughing +coughs +could +could've +couldest +couldn +couldn't +couldst +coulee +coulees +coulisse +coulisses +couloir +couloirs +coulomb +coulombic +coulombs +coulometric +coulometrically +coulometry +coulter +coulters +coumaric +coumarin +coumarins +council +councilman +councilmen +councilor +councilors +councils +councilwoman +councilwomen +counsel +counseled +counseling +counselor +counselors +counselorship +counsels +count +countability +countable +countably +countdown +countdowns +counted +countenance +countenanced +countenancer +countenancers +countenances +countenancing +counter +counteraccusation +counteract +counteracted +counteracting +counteraction +counteractions +counteractive +counteractively +counteracts +counteradaptation +counteradvertising +counteragent +counteraggression +counterargue +counterargued +counterargues +counterarguing +counterargument +counterarguments +counterassault +counterattack +counterattacked +counterattacker +counterattacking +counterattacks +counterbalance +counterbalanced +counterbalances +counterbalancing +counterbid +counterblast +counterblockade +counterblow +counterblows +countercampaign +counterchallenge +counterchallenges +counterchange +counterchanged +counterchanges +counterchanging +countercharge +countercharged +countercharges +countercharging +countercheck +counterchecked +counterchecking +counterchecks +counterclaim +counterclaimant +counterclaimants +counterclaimed +counterclaiming +counterclaims +counterclockwise +countercommercial +countercomplaint +counterconditioning +counterconditionings +counterconspiracy +counterconvention +countercountermeasure +countercoup +countercoups +countercriticism +countercry +countercultural +counterculture +countercultures +counterculturist +counterculturists +countercurrent +countercurrently +countercurrents +countercyclical +counterdemand +counterdemonstrate +counterdemonstration +counterdemonstrations +counterdemonstrator +counterdemonstrators +counterdeployment +countered +countereducational +countereffort +counterespionage +counterevidence +counterexample +counterexamples +counterfactual +counterfeit +counterfeited +counterfeiter +counterfeiters +counterfeiting +counterfeits +counterfire +counterfoil +counterfoils +counterforce +counterforces +counterglow +counterglows +countergovernment +counterhypothesis +counterimage +counterincentive +counterinflation +counterinflationary +counterinfluence +countering +counterinstance +counterinstitution +counterinsurgencies +counterinsurgency +counterinsurgent +counterinsurgents +counterintelligence +counterinterpretation +counterintuitive +counterirritant +counterirritants +counterirritation +counterman +countermand +countermanded +countermanding +countermands +countermarch +countermarched +countermarches +countermarching +countermeasure +countermeasures +countermemo +countermen +countermine +countermined +countermines +countermining +countermobilization +countermove +countermoved +countermovement +countermoves +countermoving +countermyth +counteroffensive +counteroffensives +counteroffer +counteroffers +counterorder +counterpane +counterpanes +counterpart +counterparts +counterperson +counterpersons +counterpetition +counterpicket +counterplan +counterplans +counterplay +counterplayer +counterplays +counterplea +counterpleas +counterplot +counterplots +counterplotted +counterplotting +counterploy +counterpoint +counterpointed +counterpointing +counterpoints +counterpoise +counterpoised +counterpoises +counterpoising +counterpose +counterposed +counterposes +counterposing +counterpower +counterpressure +counterproductive +counterproductively +counterprogramming +counterprogrammings +counterproject +counterproliferation +counterpropaganda +counterproposal +counterproposals +counterprotest +counterpunch +counterpunched +counterpuncher +counterpunchers +counterpunches +counterpunching +counterquestion +counterraid +counterrally +counterreaction +counterreform +counterreformation +counterreformations +counterreformer +counterresponse +counterretaliation +counterrevolution +counterrevolutionaries +counterrevolutionary +counterrevolutionist +counterrevolutionists +counterrevolutions +counters +counterscientific +countershading +countershadings +countershaft +countershafts +countershot +countersign +countersignature +countersignatures +countersigned +countersigning +countersigns +countersink +countersinking +countersinks +countersniper +counterspell +counterspies +counterspy +counterstain +counterstained +counterstaining +counterstains +counterstate +counterstatement +counterstep +counterstrategist +counterstrategy +counterstream +counterstrike +counterstroke +counterstrokes +counterstyle +countersue +countersued +countersues +countersuggestion +countersuing +countersuit +countersuits +countersunk +countersurveillance +countertactics +countertendency +countertenor +countertenors +counterterror +counterterrorism +counterterrorist +counterterrorists +counterterrors +counterthreat +counterthrust +countertop +countertops +countertrade +countertrader +countertraders +countertrades +countertradition +countertransference +countertransferences +countertrend +countervail +countervailed +countervailing +countervails +counterviolence +counterweigh +counterweighed +counterweighing +counterweighs +counterweight +counterweighted +counterweights +counterwoman +counterwomen +counterworld +countess +countesses +counties +counting +countinghouse +countless +countlessly +countries +countrified +country +countryman +countrymen +countryseat +countryseats +countryside +countrysides +countrywide +countrywoman +countrywomen +counts +county +countywide +coup +coupe +coupes +couple +coupled +coupler +couplers +couples +couplet +couplets +coupling +couplings +coupon +couponing +couponings +coupons +coups +coupé +coupés +courage +courageous +courageously +courageousness +courant +courante +courantes +courgette +courgettes +courier +couriers +courlan +courlans +course +coursed +courser +coursers +courses +courseware +coursework +coursing +coursings +court +courted +courteous +courteously +courteousness +courtesan +courtesans +courtesies +courtesy +courthouse +courthouses +courtier +courtiers +courting +courtlier +courtliest +courtliness +courtly +courtroom +courtrooms +courts +courtship +courtships +courtside +courtyard +courtyards +couscous +cousin +cousinhood +cousinly +cousins +cousinship +couth +coutts +couture +couturier +couturiers +couturière +couturières +couvade +couvades +covalence +covalency +covalent +covalently +covariance +covariant +cove +coved +covellite +covellites +coven +covenant +covenantal +covenantally +covenanted +covenantee +covenantees +covenanter +covenanters +covenanting +covenantor +covenantors +covenants +covens +coventry +cover +coverable +coverage +coverall +coveralls +coverdale +covered +coverer +coverers +covering +coverings +coverless +coverlet +coverlets +covers +covert +covertly +covertness +coverts +coverture +covertures +coves +covet +covetable +coveted +coveter +coveters +coveting +covetingly +covetous +covetously +covetousness +covets +covey +coveys +coving +cow +coward +cowardice +cowardliness +cowardly +cowards +cowbane +cowbanes +cowbell +cowbells +cowberries +cowberry +cowbird +cowbirds +cowboy +cowboys +cowcatcher +cowcatchers +cowed +cowedly +cower +cowered +cowering +cowers +cowfish +cowfishes +cowgirl +cowgirls +cowhand +cowhands +cowherb +cowherbs +cowherd +cowherds +cowhide +cowhided +cowhides +cowhiding +cowing +cowinner +cowinners +cowl +cowled +cowlick +cowlicks +cowling +cowlings +cowls +cowman +cowmen +coworker +coworkers +cowpea +cowpeas +cowper +cowpoke +cowpokes +cowponies +cowpony +cowpox +cowpoxes +cowpuncher +cowpunchers +cowrie +cowries +cowrite +cowriter +cowriters +cowrites +cowriting +cowritten +cowrote +cowry +cows +cowshed +cowsheds +cowslip +cowslips +cox +coxa +coxae +coxal +coxalgia +coxalgias +coxalgic +coxcomb +coxcombries +coxcombry +coxcombs +coxed +coxes +coxing +coxitis +coxitises +coxsackievirus +coxsackieviruses +coxswain +coxswained +coxswaining +coxswains +coy +coydog +coydogs +coyer +coyest +coyly +coyness +coyote +coyotes +coyotillo +coyotillos +coypu +coypus +cozen +cozenage +cozenages +cozened +cozener +cozeners +cozening +cozens +cozied +cozier +cozies +coziest +cozily +coziness +cozumel +cozy +cozying +crab +crabapple +crabapples +crabbe +crabbed +crabbedly +crabbedness +crabber +crabbers +crabbier +crabbiest +crabbily +crabbiness +crabbing +crabby +crabgrass +crabmeat +crabmeats +crabs +crabstick +crabsticks +crabwise +crack +crackbrain +crackbrained +crackbrains +crackdown +crackdowns +cracked +cracker +crackerjack +crackerjacks +crackers +cracking +crackings +crackle +crackled +crackles +crackleware +cracklewares +cracklier +crackliest +crackling +cracklings +crackly +cracknel +cracknels +crackpot +crackpots +cracks +cracksman +cracksmen +crackup +crackups +cracow +cradle +cradleboard +cradleboards +cradled +cradler +cradlers +cradles +cradlesong +cradlesongs +cradling +craft +crafted +crafter +crafters +craftier +craftiest +craftily +craftiness +crafting +crafts +craftsman +craftsmanlike +craftsmanly +craftsmanship +craftsmen +craftspeople +craftsperson +craftspersons +craftswoman +craftswomen +craftwork +craftworker +craftworkers +craftworks +crafty +crag +cragged +craggier +craggiest +craggily +cragginess +craggy +crags +craig +crake +crakes +cram +crambe +crambes +crambo +cramboes +crammed +crammer +crammers +cramming +cramp +cramped +crampfish +crampfishes +cramping +crampon +crampons +cramps +crams +cranberries +cranberry +crane +craned +cranes +cranesbill +cranesbills +crania +cranial +cranially +craniate +craniates +craniectomies +craniectomy +craning +craniocerebral +craniofacial +craniological +craniologically +craniologist +craniologists +craniology +craniometer +craniometers +craniometric +craniometrical +craniometry +craniosacral +craniotomies +craniotomy +cranium +craniums +crank +crankcase +crankcases +cranked +crankier +crankiest +crankily +crankiness +cranking +crankpin +cranks +crankshaft +crankshafts +cranky +cranmer +crannied +crannies +cranny +crap +crape +craped +crapehanger +crapehangers +crapes +craping +crapped +crapper +crappers +crappie +crappier +crappies +crappiest +crapping +crappy +craps +crapshoot +crapshooter +crapshooters +crapshoots +crapulence +crapulent +crapulous +crapulously +crash +crashed +crasher +crashers +crashes +crashing +crashworthiness +crashworthy +crass +crasser +crassest +crassitude +crassly +crassness +crate +crated +crater +cratered +cratering +craterlet +craterlets +craters +crates +crating +cravat +cravats +crave +craved +craven +cravenly +cravenness +cravens +craver +cravers +craves +craving +cravingly +cravings +craw +crawdad +crawdads +crawfish +crawfished +crawfishes +crawfishing +crawl +crawled +crawler +crawlers +crawlier +crawliest +crawling +crawlingly +crawls +crawlspace +crawlspaces +crawlway +crawlways +crawly +craws +crayfish +crayfishes +crayon +crayoned +crayoning +crayonist +crayonists +crayons +craze +crazed +crazes +crazier +crazies +craziest +crazily +craziness +crazinesses +crazing +crazy +crazyweed +crazyweeds +creak +creaked +creakier +creakiest +creakily +creakiness +creaking +creakingly +creaks +creaky +cream +creamcups +creamed +creamer +creameries +creamers +creamery +creamier +creamiest +creamily +creaminess +creaming +creampuff +creampuffs +creams +creamy +crease +creased +creaseless +creaseproof +creaser +creasers +creases +creasing +creasy +create +created +creates +creatine +creatines +creating +creatinine +creatinines +creation +creational +creationism +creationist +creationists +creations +creative +creatively +creativeness +creativity +creator +creators +creatural +creature +creatureliness +creaturely +creatures +credence +credential +credentialed +credentialing +credentialism +credentialisms +credentials +credenza +credenzas +credibility +credible +credibleness +credibly +credit +creditability +creditable +creditableness +creditably +credited +crediting +creditor +creditors +credits +creditworthiness +creditworthy +credo +credos +credulity +credulous +credulously +credulousness +creed +creedal +creeds +creek +creeks +creel +creels +creep +creeper +creepers +creepier +creepiest +creepily +creepiness +creeping +creeps +creepy +cremains +cremate +cremated +cremates +cremating +cremation +cremations +cremator +crematoria +crematories +crematorium +crematoriums +cremators +crematory +creme +cremes +cremona +crenate +crenately +crenation +crenations +crenature +crenatures +crenel +crenelated +crenelation +crenellate +crenellated +crenellates +crenellating +crenellation +crenellations +crenellé +crenels +crenshaw +crenshaws +crenulate +crenulation +creodont +creodonts +creole +creoles +creolization +creolize +creolized +creolizes +creolizing +creon +creosol +creosols +creosote +creosoted +creosotes +creosoting +crepe +crepehanger +crepehangers +crepes +crepitant +crepitate +crepitated +crepitates +crepitating +crepitation +crepitations +crept +crepuscular +crepuscule +crepuscules +crescendi +crescendo +crescendoed +crescendoes +crescendoing +crescendos +crescent +crescentic +crescents +cresol +cresols +cress +cresset +cressets +cressida +crest +cresta +crested +crestfallen +crestfallenly +crestfallenness +cresting +crestings +crests +cresyl +cresylic +cresyls +cretaceous +cretaceously +cretan +cretans +crete +cretic +cretics +cretin +cretinism +cretinize +cretinized +cretinizes +cretinizing +cretinoid +cretinous +cretins +cretonne +cretonnes +crevalle +crevalles +crevasse +crevassed +crevasses +crevassing +crevice +creviced +crevices +crew +crewcut +crewed +crewel +crewels +crewelwork +crewelworks +crewing +crewman +crewmate +crewmates +crewmember +crewmembers +crewmen +crews +creüsa +cri +crib +cribbage +cribbed +cribber +cribbers +cribbing +cribriform +cribs +cricetid +cricetids +crick +cricked +cricket +cricketed +cricketer +cricketers +cricketing +crickets +crickety +cricking +cricks +cricoid +cricoids +cried +crier +criers +cries +crime +crimea +crimean +crimeless +crimelessness +crimes +criminal +criminalities +criminality +criminalization +criminalize +criminalized +criminalizes +criminalizing +criminally +criminals +criminate +criminated +criminates +criminating +crimination +criminative +criminator +criminators +criminatory +criminogenic +criminological +criminologically +criminologist +criminologists +criminology +crimp +crimped +crimper +crimpers +crimpier +crimpiest +crimpiness +crimping +crimps +crimpy +crimson +crimsoned +crimsoning +crimsons +cringe +cringed +cringes +cringing +cringle +cringles +crinkle +crinkled +crinkleroot +crinkleroots +crinkles +crinkling +crinkly +crinoid +crinoids +crinoline +crinolined +crinolines +crinum +crinums +criollo +criollos +criosphinx +criosphinxes +cripple +crippled +crippler +cripplers +cripples +crippling +cripps +cris +crises +crisis +crisp +crispate +crispation +crispations +crisped +crisper +crispers +crispest +crispier +crispiest +crispin +crispiness +crisping +crisply +crispness +crisps +crispy +crissa +crissal +crisscross +crisscrossed +crisscrosses +crisscrossing +crissum +crista +cristae +cristate +criteria +criterial +criterion +criterions +critic +critical +criticality +critically +criticalness +criticaster +criticasters +criticism +criticisms +criticizable +criticize +criticized +criticizer +criticizers +criticizes +criticizing +critics +critique +critiqued +critiques +critiquing +critter +critters +croak +croaked +croaker +croakers +croakily +croaking +croaks +croaky +croat +croatia +croatian +croatians +croats +crocein +croceins +crochet +crocheted +crocheting +crochets +crocidolite +crocidolites +crock +crocked +crockery +crocket +crockets +crocking +crocks +crocodile +crocodiles +crocodilian +crocodilians +crocoite +crocoites +crocus +crocuses +croesus +crofter +crofters +crohn +croissant +croissants +cromlech +cromlechs +cromwell +cromwellian +crone +crones +cronies +cronin +cronus +crony +cronyism +crook +crookbacked +crooked +crookedly +crookedness +crookeries +crookery +crooking +crookneck +crooknecks +crooks +croon +crooned +crooner +crooners +crooning +croons +crop +cropland +croplands +cropped +cropper +croppers +cropping +crops +croquet +croqueted +croqueting +croquets +croquette +croquettes +croquignole +croquignoles +crosier +crosiers +cross +crossbar +crossbars +crossbeam +crossbeams +crossbill +crossbills +crossbones +crossbow +crossbowman +crossbows +crossbred +crossbreed +crossbreeding +crossbreeds +crosscheck +crosschecked +crosschecking +crosschecks +crosscourt +crosscurrent +crosscurrents +crosscut +crosscuts +crosscutting +crosscuttings +crosse +crossed +crosser +crossers +crosses +crossfire +crosshair +crosshairs +crosshatch +crosshatched +crosshatches +crosshatching +crosshead +crossheads +crossing +crossings +crossly +crossness +crossopterygian +crossopterygians +crossover +crossovers +crosspatch +crosspatches +crosspiece +crosspieces +crossroad +crossroads +crossruff +crossruffed +crossruffing +crossruffs +crosstalk +crosstalks +crosstie +crossties +crosstree +crosstrees +crosswalk +crosswalks +crossway +crossways +crosswayss +crosswind +crosswinds +crosswise +crossword +crosswords +crotch +crotched +crotches +crotchet +crotchetiness +crotchets +crotchety +croton +crotons +crottin +crottins +crouch +crouched +crouches +crouching +croup +croupier +croupiers +croupous +croupy +crouse +croustade +croustades +crouton +croutons +crow +crowbar +crowbarred +crowbarring +crowbars +crowberries +crowberry +crowd +crowded +crowder +crowders +crowding +crowds +crowed +crowfoot +crowfoots +crowing +crown +crowned +crowning +crowns +crows +croze +crozes +cru +crucial +crucially +cruciate +cruciately +crucible +crucibles +crucifer +cruciferous +crucifers +crucified +crucifier +crucifiers +crucifies +crucifix +crucifixes +crucifixion +crucifixions +cruciform +cruciformly +crucify +crucifying +crud +cruddier +cruddiest +cruddiness +cruddy +crude +crudely +crudeness +cruder +crudest +crudities +crudity +crudités +cruel +crueler +cruelest +cruelly +cruelties +cruelty +cruet +cruets +cruise +cruised +cruiser +cruisers +cruiserweight +cruiserweights +cruises +cruising +cruller +crullers +crumb +crumbed +crumbing +crumble +crumbled +crumbles +crumblier +crumbliest +crumbliness +crumbling +crumbly +crumbs +crummier +crummiest +crummy +crump +crumped +crumpet +crumpets +crumping +crumple +crumpled +crumples +crumpling +crumply +crumps +crunch +crunchable +crunched +crunches +crunchier +crunchiest +crunchiness +crunching +crunchy +crupper +cruppers +crura +crural +crus +crusade +crusaded +crusader +crusaders +crusades +crusading +crusado +crusadoes +cruse +cruses +crush +crushable +crushed +crusher +crushers +crushes +crushing +crushingly +crushproof +crusoe +crust +crustacean +crustaceans +crustaceous +crustal +crusted +crustier +crustiest +crustily +crustiness +crusting +crustless +crustose +crusts +crusty +crutch +crutched +crutches +crutching +crux +cruxes +cruz +cruzeiro +cruzeiros +cry +crybabies +crybaby +crying +crymotherapies +crymotherapy +cryobank +cryobanks +cryobiological +cryobiologically +cryobiologist +cryobiologists +cryobiology +cryogen +cryogenic +cryogenically +cryogenics +cryogeny +cryolite +cryolites +cryometer +cryometers +cryonic +cryonics +cryophilic +cryopreservation +cryopreserve +cryopreserved +cryopreserves +cryopreserving +cryoprobe +cryoprobes +cryoprotectant +cryoprotectants +cryoprotective +cryoscope +cryoscopes +cryoscopic +cryoscopies +cryoscopy +cryostat +cryostatic +cryostats +cryosurgeon +cryosurgeons +cryosurgery +cryosurgical +cryotherapies +cryotherapy +crypt +cryptanalysis +cryptanalyst +cryptanalysts +cryptanalytic +cryptanalyze +cryptanalyzed +cryptanalyzes +cryptanalyzing +cryptesthesia +cryptic +cryptically +crypticness +crypto +cryptoclastic +cryptococcal +cryptococcosis +cryptococcus +cryptocrystalline +cryptogam +cryptogamic +cryptogamous +cryptogams +cryptogenic +cryptogram +cryptogrammic +cryptograms +cryptograph +cryptographed +cryptographer +cryptographers +cryptographic +cryptographically +cryptographing +cryptographs +cryptography +cryptologic +cryptological +cryptologist +cryptologists +cryptology +cryptomeria +cryptomerias +cryptorchid +cryptorchism +cryptos +cryptosporidiosis +cryptozoite +cryptozoites +cryptozoological +cryptozoologist +cryptozoologists +cryptozoology +crypts +crystal +crystalliferous +crystalline +crystallinity +crystallite +crystallites +crystallitic +crystallizable +crystallization +crystallize +crystallized +crystallizer +crystallizers +crystallizes +crystallizing +crystallographer +crystallographers +crystallographic +crystallographical +crystallographically +crystallography +crystalloid +crystalloidal +crystalloids +crystals +crécy +crèche +crèches +crème +crèmes +crêpe +crêpes +ctenidia +ctenidium +ctenoid +ctenophoran +ctenophore +ctenophores +cuadrilla +cuadrillas +cuatro +cuatros +cub +cuba +cubage +cubages +cuban +cubans +cubature +cubatures +cubbies +cubby +cubbyhole +cubbyholes +cube +cubeb +cubebs +cubed +cuber +cubers +cubes +cubic +cubical +cubically +cubicalness +cubicle +cubicles +cubicly +cubics +cubiform +cubing +cubism +cubist +cubistic +cubistically +cubists +cubit +cubits +cuboid +cuboidal +cuboids +cubs +cubé +cuchifrito +cuchifritos +cuchulain +cuckold +cuckolded +cuckolding +cuckoldries +cuckoldry +cuckolds +cuckoo +cuckooed +cuckooflower +cuckooflowers +cuckooing +cuckoopint +cuckoopints +cuckoos +cucullate +cucullately +cucumber +cucumbers +cucurbit +cucurbits +cud +cudbear +cudbears +cuddies +cuddle +cuddled +cuddles +cuddlesome +cuddlier +cuddliest +cuddling +cuddly +cuddy +cudgel +cudgeled +cudgeling +cudgels +cudweed +cudweeds +cue +cued +cueing +cuernavaca +cues +cuesta +cuestas +cuff +cuffed +cuffing +cufflink +cufflinks +cuffs +cui +cuing +cuirass +cuirassed +cuirasses +cuirassier +cuirassiers +cuirassing +cuisinart +cuisine +cuisse +cuisses +cul +culch +culches +culet +culets +culex +culiacán +culices +culinary +cull +culled +culler +cullers +cullet +cullets +cullies +culling +cullis +cullises +culloden +culls +cully +culm +culminant +culminate +culminated +culminates +culminating +culmination +culminations +culms +culotte +culottes +culpa +culpability +culpable +culpably +culprit +culprits +cult +cultic +cultigen +cultigens +cultish +cultism +cultist +cultists +cultivability +cultivable +cultivar +cultivatable +cultivate +cultivated +cultivates +cultivating +cultivation +cultivations +cultivator +cultivators +cultrate +cults +cultural +culturally +culturati +culture +cultured +cultures +culturing +cultus +cultuses +culver +culverin +culverins +culvers +culvert +culverts +cum +cumaean +cumber +cumbered +cumberer +cumberers +cumbering +cumberland +cumbers +cumbersome +cumbersomely +cumbria +cumbrian +cumbrians +cumbrous +cumbrously +cumbrousness +cumin +cummerbund +cummerbunds +cumshaw +cumshaws +cumulate +cumulated +cumulates +cumulating +cumulation +cumulations +cumulative +cumulatively +cumulativeness +cumuli +cumuliform +cumulonimbi +cumulonimbus +cumulonimbuses +cumulous +cumulus +cunard +cunctation +cunctations +cunctative +cunctator +cunctators +cuneal +cuneate +cuneately +cuneiform +cunha +cunner +cunners +cunnilingual +cunnilingus +cunnilinguses +cunning +cunningly +cunningness +cunnings +cunt +cunts +cup +cupbearer +cupbearers +cupboard +cupboards +cupcake +cupcakes +cupel +cupeled +cupeling +cupellation +cupellations +cupeller +cupellers +cupels +cupflower +cupflowers +cupful +cupfuls +cupid +cupidity +cupids +cupola +cupolas +cupped +cuppier +cuppiest +cupping +cuppings +cuppy +cupreous +cupric +cupriferous +cuprite +cuprites +cupronickel +cupronickels +cuprous +cups +cupulate +cupule +cupules +cur +curability +curable +curableness +curably +curacies +curacy +curare +curarization +curarize +curarized +curarizes +curarizing +curassow +curassows +curate +curates +curative +curatively +curativeness +curatives +curator +curatorial +curators +curatorship +curaçao +curaçaos +curb +curbed +curbing +curbs +curbside +curbsides +curbstone +curbstones +curculio +curculios +curcuma +curcumas +curd +curded +curding +curdle +curdled +curdles +curdling +curds +curdy +cure +cured +cureless +curer +curers +cures +curettage +curette +curettement +curettements +curettes +curfew +curfews +curia +curiae +curial +curie +curies +curing +curio +curios +curiosa +curiosities +curiosity +curious +curiously +curiousness +curium +curl +curled +curler +curlers +curlew +curlews +curlicue +curlicued +curlicues +curlier +curliest +curlily +curliness +curling +curlings +curls +curly +curmudgeon +curmudgeonly +curmudgeonry +curmudgeons +currant +currants +currencies +currency +current +currently +currentness +currents +curricle +curricles +curricula +curricular +curriculum +curriculums +curried +currier +currieries +curriers +curriery +curries +currish +currishly +curry +currycomb +currycombed +currycombing +currycombs +currying +curs +curse +cursed +cursedly +cursedness +curser +cursers +curses +cursing +cursive +cursively +cursiveness +cursives +cursor +cursorial +cursorily +cursoriness +cursors +cursory +curt +curtail +curtailed +curtailer +curtailers +curtailing +curtailment +curtailments +curtails +curtain +curtained +curtaining +curtains +curtate +curter +curtesies +curtest +curtesy +curtilage +curtilages +curtly +curtness +curtsey +curtseyed +curtseying +curtseys +curtsied +curtsies +curtsy +curtsying +curule +curvaceous +curvaceously +curvaceousness +curvature +curvatures +curve +curveball +curveballs +curved +curvedness +curves +curvet +curvets +curvetted +curvetting +curvilinear +curvilinearity +curvilinearly +curving +curvy +curé +curés +cuscus +cuscuses +cusec +cusecs +cushaw +cushaws +cushier +cushiest +cushily +cushiness +cushion +cushioned +cushioning +cushions +cushiony +cushitic +cushy +cusk +cusp +cuspate +cusped +cuspid +cuspidate +cuspidation +cuspidations +cuspidor +cuspidors +cuspids +cusps +cuss +cussed +cussedly +cussedness +cusses +cussing +cussword +cusswords +custard +custards +custardy +custodial +custodian +custodians +custodianship +custodies +custody +custom +customable +customarily +customariness +customary +customer +customers +customhouse +customhouses +customizable +customization +customizations +customize +customized +customizer +customizers +customizes +customizing +customs +cut +cutaneous +cutaneously +cutaway +cutaways +cutback +cutbacks +cutch +cutches +cute +cutely +cuteness +cuter +cutes +cutesier +cutesiest +cutesiness +cutest +cutesy +cutgrass +cutgrasses +cuticle +cuticles +cuticular +cutie +cuties +cutin +cutinization +cutinize +cutinized +cutinizes +cutinizing +cutins +cutis +cutlass +cutlasses +cutler +cutlers +cutlery +cutlet +cutlets +cutoff +cutoffs +cutout +cutouts +cutover +cutpurse +cutpurses +cuts +cuttable +cutter +cutters +cutthroat +cutthroats +cutting +cuttingly +cuttings +cuttingss +cuttlebone +cuttlebones +cuttlefish +cuttlefishes +cutup +cutups +cutwater +cutwaters +cutwork +cutworks +cutworm +cutworms +cuvette +cuvettes +cuvier +cyan +cyanamide +cyanamides +cyanate +cyanates +cyanic +cyanide +cyanided +cyanides +cyaniding +cyanine +cyanines +cyanoacrylate +cyanoacrylates +cyanobacterium +cyanobacteriums +cyanocobalamin +cyanocobalamins +cyanogen +cyanogenesis +cyanogenetic +cyanogens +cyanohydrin +cyanohydrins +cyanosed +cyanoses +cyanosis +cyanotic +cyanotype +cyanotypes +cyathium +cyathiums +cybele +cyberconference +cybernate +cybernated +cybernates +cybernating +cybernation +cybernetic +cybernetically +cybernetician +cyberneticians +cyberneticist +cyberneticists +cybernetics +cyberspace +cyborg +cyborgs +cycad +cycads +cyclades +cycladic +cyclamate +cyclamates +cyclamen +cyclamens +cyclase +cyclases +cycle +cycled +cycler +cyclers +cycles +cyclic +cyclical +cyclicality +cyclically +cycling +cyclist +cyclists +cyclization +cyclizations +cycloalkane +cycloalkanes +cyclohexane +cyclohexanes +cycloheximide +cycloheximides +cycloid +cycloidal +cycloids +cyclometer +cyclometers +cyclometric +cyclometry +cyclone +cyclones +cyclonic +cyclonical +cyclooxygenase +cycloparaffin +cycloparaffins +cyclopean +cyclopedia +cyclopedias +cyclopedic +cyclopedist +cyclopedists +cyclopentane +cyclopentanes +cyclopes +cyclophosphamide +cyclophosphamides +cycloplegia +cycloplegias +cyclopropane +cyclopropanes +cyclops +cyclopses +cyclorama +cycloramas +cycloramic +cycloserine +cycloserines +cycloses +cyclosis +cyclosporine +cyclosporines +cyclostomate +cyclostomatous +cyclostome +cyclostomes +cyclostyle +cyclostyled +cyclostyles +cyclostyling +cyclothyme +cyclothymes +cyclothymia +cyclothymias +cyclothymic +cyclotron +cyclotrons +cygnet +cygnets +cygnus +cylinder +cylinders +cylindric +cylindrical +cylindricality +cylindrically +cylindroid +cylindroids +cyma +cymas +cymatia +cymatium +cymbal +cymbaleer +cymbaleers +cymbalist +cymbalists +cymbals +cymbeline +cymbidium +cymbidiums +cyme +cymene +cymenes +cymes +cymiferous +cymling +cymlings +cymogene +cymogenes +cymoid +cymophane +cymophanes +cymose +cymosely +cymric +cymry +cynic +cynical +cynically +cynicalness +cynicism +cynicisms +cynics +cynoscephalae +cynosural +cynosure +cynosures +cynthia +cypress +cypresses +cyprian +cyprians +cyprinid +cyprinids +cyprinodont +cyprinodonts +cyprinoid +cyprinoids +cypriot +cypriots +cypripedium +cypripediums +cyproheptadine +cyproheptadines +cyproterone +cyproterones +cyprus +cypsela +cypselae +cyrenaic +cyrenaica +cyrenaics +cyrene +cyrillic +cyst +cystectomies +cystectomy +cysteine +cysteines +cystic +cysticerci +cysticercoid +cysticercoids +cysticercosis +cysticercus +cystine +cystines +cystitis +cystocele +cystoceles +cystoid +cystoids +cystolith +cystoliths +cystoscope +cystoscopes +cystoscopic +cystoscopy +cystostomies +cystostomy +cysts +cythera +cytherean +cytidine +cytidines +cytochemical +cytochemistry +cytochrome +cytochromes +cytogenesis +cytogenetic +cytogenetical +cytogenetically +cytogeneticist +cytogeneticists +cytogenetics +cytogeny +cytokinesis +cytokinetic +cytokinin +cytokinins +cytologic +cytological +cytologist +cytologists +cytology +cytolyses +cytolysin +cytolysins +cytolysis +cytolytic +cytomegalic +cytomegalovirus +cytomegaloviruses +cytomembrane +cytomembranes +cytopathic +cytopathogenic +cytopathogenicity +cytophilic +cytophotometer +cytophotometers +cytophotometric +cytophotometrically +cytophotometry +cytoplasm +cytoplasmic +cytoplasmically +cytoplast +cytoplastic +cytoplasts +cytosine +cytosines +cytoskeleton +cytoskeletons +cytosol +cytosols +cytostasis +cytostatic +cytostatically +cytostatics +cytotaxonomic +cytotaxonomies +cytotaxonomist +cytotaxonomists +cytotaxonomy +cytotechnologist +cytotechnologists +cytotechnology +cytotoxic +cytotoxicity +cytotoxin +cytotoxins +czar +czardas +czardom +czarevitch +czarevitches +czarevna +czarevnas +czarina +czarinas +czarism +czarisms +czarist +czarists +czaritza +czaritzas +czars +czech +czechoslovak +czechoslovakia +czechoslovakian +czechoslovakians +czechoslovaks +czechs +cádiz +cárdenas +céleste +célestes +célèbre +célèbres +cévennes +cézanne +cézannesque +cèpe +cèpes +cíbola +córdoba +côte +côtes +d +d'affaires +d'antibes +d'aosta +d'art +d'azur +d'elegance +d'esprit +d'estime +d'hôte +d'hôtel +d'oc +d'oeil +d'oeuvre +d'oeuvres +d'oyly +d'oïl +d'état +d'être +d'œil +d'œuvre +d'œuvres +da +dab +dabbed +dabber +dabbers +dabbing +dabble +dabbled +dabbler +dabblers +dabbles +dabbling +dabchick +dabchicks +dabs +dacca +dace +daces +dacha +dachas +dachau +dachshund +dachshunds +dacoit +dacoits +dacoity +dacquoise +dacquoises +dacron +dactinomycin +dactinomycins +dactyl +dactylic +dactylically +dactylogram +dactylograms +dactylographic +dactylography +dactylology +dactyls +dad +dada +dadaism +dadaist +dadaistic +dadaists +daddies +daddy +daddyish +dado +dadoed +dadoes +dadoing +dados +dadra +dads +daedal +daedalian +daedalus +daemon +daemonic +daemons +daffier +daffiest +daffily +daffiness +daffodil +daffodils +daffy +daft +dafter +daftest +daftly +daftness +dag +dagan +dagestan +dagger +daggers +dagon +dags +daguerre +daguerreotype +daguerreotyped +daguerreotyper +daguerreotypers +daguerreotypes +daguerreotyping +daguerreotypy +dagwood +dagwoods +dahabeah +dahabeahs +dahl +dahlia +dahlias +dahomey +dahoon +dahoons +daikon +dailies +dailiness +daily +daimio +daimios +daimon +daimons +daintier +dainties +daintiest +daintily +daintiness +dainty +daiquiri +daiquiris +dairies +dairy +dairyer +dairyers +dairying +dairymaid +dairymaids +dairyman +dairymen +dairywoman +dairywomen +dais +daises +daisies +daisy +dakar +dakota +dakotan +dakotans +dakotas +dalai +dalapon +dalapons +dalasi +dale +dalek +daleks +dales +daleth +dalhousie +dallas +dalles +dalliance +dalliances +dallied +dallier +dalliers +dallies +dally +dallying +dallyingly +dalmatia +dalmatian +dalmatians +dalmatic +dalmatics +dalrymple +dalton +daltonian +daltonic +daltonism +daltons +dam +damage +damageability +damageable +damaged +damager +damagers +damages +damaging +damagingly +daman +damascene +damascened +damascener +damasceners +damascenes +damascening +damascus +damask +damasked +damasking +damasks +dame +dames +daminozide +daminozides +dammar +dammars +dammed +dammer +dammers +damming +dammit +damn +damnable +damnableness +damnably +damnation +damnatory +damnder +damndest +damned +damneder +damnedest +damnification +damnified +damnifies +damnify +damnifying +damning +damningly +damns +damocles +damon +damp +damped +dampen +dampened +dampener +dampeners +dampening +dampens +damper +dampers +dampest +damping +dampings +dampish +damply +dampness +damps +dams +damsel +damselfish +damselfishes +damselflies +damselfly +damsels +damson +damsons +dan +dana +danaides +danaë +dance +danceability +danceable +danced +dancegoer +dancegoers +dancegoing +dancer +dancerly +dancers +dances +dancewear +dancewears +dancier +danciest +dancing +dancingly +dancy +dandelion +dandelions +dander +dandiacal +dandier +dandies +dandiest +dandification +dandified +dandifies +dandify +dandifying +dandily +dandle +dandled +dandles +dandling +dandruff +dandruffy +dandy +dandyish +dandyishly +dandyism +dandyisms +dane +danegeld +danegelds +danelaw +danelaws +danes +dang +danged +danger +dangerous +dangerously +dangerousness +dangers +dangle +dangleberries +dangleberry +dangled +dangler +danglers +dangles +dangling +dangly +dangs +daniel +danielle +danio +danios +danish +danishes +danite +danites +dank +danker +dankest +dankly +dankness +dans +danseur +danseurs +danseuse +danseuses +dante +dantean +danteans +dantesque +danton +danube +danubian +danville +danzig +dap +daphne +daphnes +daphnia +daphnis +dapped +dapper +dapperly +dapperness +dapping +dapple +dappled +dapples +dappling +daps +dapsone +dapsones +dardanelles +dardanus +dare +dared +daredevil +daredevilry +daredevils +daredeviltry +daren +daren't +darer +darers +dares +daresay +daring +daringly +daringness +dariole +darioles +darius +darién +darjeeling +dark +darken +darkened +darkener +darkeners +darkening +darkens +darker +darkest +darkish +darkle +darkled +darkles +darkling +darklings +darkly +darkness +darkroom +darkrooms +darks +darksome +darlene +darling +darlingly +darlingness +darlings +darn +darnation +darned +darnedest +darnedests +darnel +darnels +darner +darners +darning +darnley +darns +daro +dart +dartboard +dartboards +darted +darter +darters +darting +dartmouth +darts +darvon +darwin +darwinian +darwinians +darwinism +darwinist +darwinistic +darwinists +dash +dashboard +dashboards +dashed +dasheen +dasheens +dasher +dashers +dashes +dashi +dashiki +dashikis +dashing +dashingly +dashis +dashpot +dashpots +dassie +dassies +dastard +dastardliness +dastardly +dastards +dasyure +dasyures +data +databanks +database +databased +databases +databasing +datable +datagram +datamation +date +dateable +dated +datedly +datedness +dateless +dateline +datelined +datelines +datelining +dater +daters +dates +dating +dative +datively +datives +datum +datums +datura +daturas +daub +daubed +dauber +daubers +daubery +daubing +daubs +daugavpils +daughter +daughterless +daughterly +daughters +daunt +daunted +daunter +daunters +daunting +dauntingly +dauntless +dauntlessly +dauntlessness +daunts +dauphin +dauphine +dauphines +dauphins +dauphiné +dave +davenant +davenport +davenports +david +davit +davits +davos +davy +daw +dawdle +dawdled +dawdler +dawdlers +dawdles +dawdling +dawdlingly +dawn +dawned +dawning +dawns +daws +day +dayak +dayaks +daybed +daybeds +daybook +daybooks +daybreak +daybreaks +daycare +daydream +daydreamed +daydreamer +daydreamers +daydreaming +daydreams +daydreamt +dayflies +dayflower +dayflowers +dayfly +dayhop +dayhops +daylight +daylights +daylilies +daylily +daylong +daypack +daypacks +dayroom +dayrooms +days +dayside +daysides +dayspring +daystar +daystars +daytime +daytimes +dayton +daytona +daywear +daze +dazed +dazedly +dazedness +dazes +dazing +dazzle +dazzled +dazzler +dazzlers +dazzles +dazzling +dazzlingly +de +deaccession +deaccessioned +deaccessioning +deaccessions +deacidification +deacidified +deacidifies +deacidify +deacidifying +deacon +deaconess +deaconesses +deaconries +deaconry +deacons +deactivate +deactivated +deactivates +deactivating +deactivation +deactivations +deactivator +deactivators +dead +deadbeat +deadbeats +deadbolt +deadbolts +deaden +deadened +deadener +deadeners +deadening +deadeningly +deadenings +deadens +deader +deadest +deadeye +deadeyes +deadfall +deadfalls +deadhead +deadheaded +deadheading +deadheads +deadlier +deadliest +deadlight +deadlights +deadline +deadlined +deadlines +deadliness +deadlining +deadlock +deadlocked +deadlocking +deadlocks +deadly +deadness +deadpan +deadpanned +deadpanner +deadpanners +deadpanning +deadpans +deadweight +deadwood +deaerate +deaerated +deaerates +deaerating +deaeration +deaerator +deaerators +deaf +deafen +deafened +deafening +deafeningly +deafens +deafer +deafest +deafly +deafness +deal +dealate +dealated +dealateds +dealates +dealation +dealcoholization +dealcoholize +dealcoholized +dealcoholizes +dealcoholizing +dealer +dealers +dealership +dealerships +dealfish +dealfishes +dealignment +dealignments +dealing +dealings +deallocate +deallocated +deallocates +deallocating +deallocation +deallocations +deallocator +dealmaker +dealmakers +dealmaking +deals +dealt +deaminase +deaminases +deaminate +deaminated +deaminates +deaminating +deamination +deaminization +deaminize +deaminized +deaminizes +deaminizing +dean +deaneries +deanery +deans +deanship +dear +dearborn +dearer +dearest +dearly +dearness +dears +dearth +death +deathbed +deathbeds +deathblow +deathblows +deathless +deathlessly +deathlessness +deathlike +deathly +deaths +deathtrap +deathtraps +deathward +deathwatch +deathwatches +deattribution +deattributions +deauville +deb +debacle +debacles +debar +debark +debarkation +debarkations +debarked +debarking +debarks +debarment +debarments +debarred +debarring +debars +debase +debased +debasement +debasements +debaser +debasers +debases +debasing +debatable +debatably +debate +debated +debatement +debater +debaters +debates +debating +debauch +debauched +debauchedly +debauchee +debauchees +debaucher +debaucheries +debauchers +debauchery +debauches +debauching +debenture +debentures +debilitate +debilitated +debilitates +debilitating +debilitation +debilitations +debilitative +debilities +debility +debit +debited +debiting +debits +debonair +debonairly +debonairness +debone +deboned +deboner +deboners +debones +deboning +deborah +debouch +debouched +debouches +debouching +debouchment +debouchments +debouchure +debouchures +debra +debrief +debriefed +debriefing +debriefings +debriefs +debris +debt +debtless +debtor +debtors +debts +debug +debugged +debugger +debuggers +debugging +debugs +debunk +debunked +debunker +debunkers +debunking +debunks +debussy +debut +debutant +debutante +debutantes +debutants +debuted +debuting +debuts +decaampere +decaamperes +decabecquerel +decabecquerels +decacandela +decacandelas +decacoulomb +decacoulombs +decade +decadelong +decadence +decadencies +decadency +decadent +decadently +decadents +decades +decaf +decafarad +decafarads +decaffeinate +decaffeinated +decaffeinates +decaffeinating +decaffeination +decagon +decagonal +decagonally +decagons +decagram +decagrams +decagynous +decahedra +decahedral +decahedron +decahedrons +decahenries +decahenry +decahenrys +decahertz +decajoule +decajoules +decakelvin +decakelvins +decal +decalcification +decalcified +decalcifier +decalcifiers +decalcifies +decalcify +decalcifying +decalcomania +decalescence +decalescences +decalescent +decaliter +decaliters +decalogue +decalogues +decals +decalumen +decalumens +decalux +decameron +decameter +decameters +decametric +decamole +decamoles +decamp +decamped +decamping +decampment +decamps +decandrous +decane +decanes +decanewton +decanewtons +decant +decantation +decanted +decanter +decanters +decanting +decants +decaohm +decaohms +decapascal +decapascals +decapitate +decapitated +decapitates +decapitating +decapitation +decapitations +decapitator +decapitators +decapod +decapodal +decapodan +decapodous +decapods +decapolis +decaradian +decaradians +decarbonate +decarbonated +decarbonates +decarbonating +decarbonation +decarbonization +decarbonize +decarbonized +decarbonizer +decarbonizers +decarbonizes +decarbonizing +decarboxylase +decarboxylases +decarboxylation +decarboxylations +decarburization +decarburize +decarburized +decarburizes +decarburizing +decare +decares +decasecond +decaseconds +decasiemens +decasievert +decasieverts +decasteradian +decasteradians +decastyle +decastyles +decasualization +decasyllabic +decasyllabics +decasyllable +decasyllables +decatesla +decateslas +decathlete +decathletes +decathlon +decathlons +decatur +decavolt +decavolts +decawatt +decawatts +decaweber +decawebers +decay +decayed +decayer +decayers +decaying +decays +decca +deccan +decease +deceased +deceases +deceasing +decedent +decedents +deceit +deceitful +deceitfully +deceitfulness +deceits +deceivable +deceive +deceived +deceiver +deceivers +deceives +deceiving +deceivingly +decelerate +decelerated +decelerates +decelerating +deceleration +decelerations +decelerator +decelerators +december +decembers +decembrist +decembrists +decemvir +decemviral +decemvirate +decemvirates +decemviri +decemvirs +decencies +decency +decennaries +decennary +decennia +decennial +decennially +decennials +decennium +decenniums +decent +decently +decentness +decentralization +decentralizationist +decentralizationists +decentralizations +decentralize +decentralized +decentralizes +decentralizing +deception +deceptional +deceptions +deceptive +deceptively +deceptiveness +decerebrate +decerebrated +decerebrates +decerebrating +decerebration +decertification +decertified +decertifies +decertify +decertifying +dechlorinate +dechlorinated +dechlorinates +dechlorinating +dechlorination +deciampere +deciamperes +deciare +deciares +decibecquerel +decibecquerels +decibel +decibels +decicandela +decicandelas +decicoulomb +decicoulombs +decidability +decidable +decide +decided +decidedly +decidedness +decider +deciders +decides +deciding +decidua +deciduae +decidual +deciduas +deciduate +deciduous +deciduously +deciduousness +decifarad +decifarads +decigram +decigrams +decihenries +decihenry +decihenrys +decihertz +decijoule +decijoules +decikelvin +decikelvins +decile +deciles +deciliter +deciliters +decillion +decillions +decillionth +decillionths +decilumen +decilumens +decilux +decimal +decimalization +decimalize +decimalized +decimalizes +decimalizing +decimally +decimals +decimate +decimated +decimates +decimating +decimation +decimations +decimator +decimators +decimeter +decimeters +decimole +decimoles +decinewton +decinewtons +deciohm +deciohms +decipascal +decipascals +decipher +decipherability +decipherable +deciphered +decipherer +decipherers +deciphering +decipherment +deciphers +deciradian +deciradians +decisecond +deciseconds +decisiemens +decisievert +decisieverts +decision +decisional +decisioned +decisioning +decisions +decisive +decisively +decisiveness +decisteradian +decisteradians +decitesla +deciteslas +decivolt +decivolts +deciwatt +deciwatts +deciweber +deciwebers +deck +decked +decker +deckers +deckhand +deckhands +deckhouse +deckhouses +decking +deckle +deckled +deckles +deckling +decks +declaim +declaimed +declaimer +declaimers +declaiming +declaims +declamation +declamations +declamatory +declarable +declarant +declarants +declaration +declarations +declarative +declaratively +declaratives +declaratory +declare +declared +declarer +declarers +declares +declaring +declass +declassed +declasses +declassifiable +declassification +declassifications +declassified +declassifies +declassify +declassifying +declassing +declaw +declawed +declawing +declaws +declension +declensional +declensions +declinable +declination +declinational +declinations +decline +declined +decliner +decliners +declines +declining +declivities +declivitous +declivity +deco +decoct +decocted +decocting +decoction +decoctions +decocts +decode +decoded +decoder +decoders +decodes +decoding +decodings +decollate +decollated +decollates +decollating +decollation +decollations +decollator +decollators +decollectivization +decollectivize +decollectivized +decollectivizes +decollectivizing +decolonization +decolonize +decolonized +decolonizes +decolonizing +decolorant +decolorants +decolorization +decolorize +decolorized +decolorizer +decolorizers +decolorizes +decolorizing +decommission +decommissioned +decommissioning +decommissions +decompensate +decompensated +decompensates +decompensating +decompensation +decompile +decompiled +decompiler +decompilers +decompiles +decompiling +decomposability +decomposable +decompose +decomposed +decomposer +decomposers +decomposes +decomposing +decomposition +decompositional +decompositions +decompound +decompounded +decompounding +decompounds +decompress +decompressed +decompresses +decompressing +decompression +decompressions +deconcentrate +deconcentrated +deconcentrates +deconcentrating +deconcentration +decondition +deconditioned +deconditioning +deconditions +decongest +decongestant +decongestants +decongested +decongesting +decongestion +decongestive +decongests +deconsecrate +deconsecrated +deconsecrates +deconsecrating +deconsecration +deconsecrations +deconstruct +deconstructed +deconstructing +deconstruction +deconstructionism +deconstructionist +deconstructionists +deconstructs +decontaminant +decontaminate +decontaminated +decontaminates +decontaminating +decontamination +decontaminations +decontaminator +decontaminators +decontextualize +decontextualized +decontextualizes +decontextualizing +decontrol +decontrolled +decontrolling +decontrols +decor +decorate +decorated +decorates +decorating +decoration +decorations +decorative +decoratively +decorativeness +decorator +decorators +decorous +decorously +decorousness +decors +decorticate +decorticated +decorticates +decorticating +decortication +decorticator +decorticators +decorum +decos +decoupage +decoupages +decouple +decoupled +decoupler +decouplers +decouples +decoupling +decoy +decoyed +decoyer +decoyers +decoying +decoys +decrease +decreased +decreases +decreasing +decreasingly +decree +decreeable +decreed +decreeing +decreer +decreers +decrees +decrement +decremental +decremented +decrementing +decrements +decreolization +decreolizations +decrepit +decrepitate +decrepitated +decrepitates +decrepitating +decrepitation +decrepitly +decrepitude +decrescendo +decrescendos +decrescent +decretal +decretals +decretive +decretory +decried +decrier +decriers +decries +decriminalization +decriminalize +decriminalized +decriminalizes +decriminalizing +decry +decrying +decrypt +decrypted +decrypting +decryption +decrypts +decumbence +decumbency +decumbent +decuple +decurrent +decurrently +decussate +decussated +decussately +decussates +decussating +decussation +decussations +dedans +dedicate +dedicated +dedicatedly +dedicatee +dedicatees +dedicates +dedicating +dedication +dedications +dedicative +dedicator +dedicators +dedicatory +dedifferentiate +dedifferentiated +dedifferentiates +dedifferentiating +dedifferentiation +deduce +deduced +deduces +deducible +deducing +deduct +deducted +deductibility +deductible +deductibles +deducting +deduction +deductions +deductive +deductively +deducts +deed +deeded +deeding +deedless +deeds +deejay +deejays +deem +deemed +deeming +deems +deep +deepen +deepened +deepening +deepens +deeper +deepest +deepfreeze +deeply +deepness +deeps +deepwater +deer +deerflies +deerfly +deerhound +deerhounds +deerskin +deerskins +deerstalker +deerstalkers +deeryard +deeryards +deescalate +deescalated +deescalates +deescalating +deet +deets +deface +defaceable +defaced +defacement +defacements +defacer +defacers +defaces +defacing +defalcate +defalcated +defalcates +defalcating +defalcation +defalcations +defalcator +defalcators +defamation +defamatory +defame +defamed +defamer +defamers +defames +defaming +defang +defanged +defanging +defangs +defat +defats +defatted +defatting +default +defaulted +defaulter +defaulters +defaulting +defaults +defeasance +defeasances +defeasibility +defeasible +defeasibleness +defeat +defeated +defeater +defeaters +defeating +defeatism +defeatist +defeatists +defeats +defecate +defecated +defecates +defecating +defecation +defecations +defecator +defecators +defect +defected +defecting +defection +defections +defective +defectively +defectiveness +defectives +defector +defectors +defects +defeminize +defeminized +defeminizes +defeminizing +defend +defendable +defendant +defendants +defended +defender +defenders +defending +defends +defenestrate +defenestrated +defenestrates +defenestrating +defenestration +defenestrations +defense +defensed +defenseless +defenselessly +defenselessness +defenseman +defensemen +defenses +defensibility +defensible +defensibleness +defensibly +defensing +defensive +defensively +defensiveness +defensives +defer +deference +deferens +deferent +deferentia +deferential +deferentially +deferment +deferments +deferrable +deferral +deferrals +deferred +deferrer +deferrers +deferring +defers +defervesce +defervesced +defervescence +defervescences +defervescent +defervesces +defervescing +defiance +defiant +defiantly +defibrillate +defibrillated +defibrillates +defibrillating +defibrillation +defibrillative +defibrillator +defibrillators +defibrillatory +deficiencies +deficiency +deficient +deficiently +deficit +deficits +defied +defier +defiers +defies +defilade +defiladed +defilades +defilading +defile +defiled +defilement +defiler +defilers +defiles +defiling +defilingly +definability +definable +definably +define +defined +definement +definer +definers +defines +definienda +definiendum +definiens +definientia +defining +definite +definitely +definiteness +definition +definitional +definitions +definitive +definitively +definitiveness +definitives +definitude +definitudes +deflagrate +deflagrated +deflagrates +deflagrating +deflagration +deflate +deflated +deflates +deflating +deflation +deflationary +deflationist +deflationists +deflations +deflator +deflators +deflect +deflectable +deflected +deflecting +deflection +deflections +deflective +deflector +deflectors +deflects +deflexed +deflexion +deflexions +defloration +deflorations +deflower +deflowered +deflowerer +deflowerers +deflowering +deflowers +defoam +defoamed +defoaming +defoams +defocus +defocused +defocuses +defocusing +defocussed +defocusses +defocussing +defoe +defog +defogged +defogger +defoggers +defogging +defogs +defoliant +defoliants +defoliate +defoliated +defoliates +defoliating +defoliation +defoliator +defoliators +deforce +deforced +deforcement +deforces +deforcing +deforest +deforestation +deforested +deforester +deforesters +deforesting +deforests +deform +deformability +deformable +deformation +deformational +deformations +deformed +deforming +deformities +deformity +deforms +defraud +defraudation +defrauded +defrauder +defrauders +defrauding +defrauds +defray +defrayable +defrayal +defrayals +defrayed +defraying +defrays +defrock +defrocked +defrocking +defrocks +defrost +defrosted +defroster +defrosters +defrosting +defrosts +deft +defter +deftest +deftly +deftness +defuel +defueled +defueling +defuels +defunct +defunctive +defunctness +defund +defunded +defunding +defunds +defuse +defused +defuses +defusing +defy +defying +degas +degassed +degasses +degassing +degauss +degaussed +degausser +degaussers +degausses +degaussing +degeneracies +degeneracy +degenerate +degenerated +degenerately +degenerateness +degenerates +degenerating +degeneration +degenerations +degenerative +deglamorize +deglamorized +deglamorizes +deglamorizing +deglaze +deglazed +deglazes +deglazing +deglutinate +deglutinated +deglutinates +deglutinating +deglutination +deglutition +deglutitory +deglycerolize +deglycerolized +deglycerolizes +deglycerolizing +degradability +degradable +degradation +degradations +degrade +degraded +degradedly +degradedness +degrader +degraders +degrades +degrading +degradingly +degranulation +degrease +degreased +degreaser +degreasers +degreases +degreasing +degree +degreed +degrees +degression +degressions +degressive +degressively +degum +degumming +degust +degustation +degusted +degusting +degusts +dehire +dehired +dehires +dehiring +dehisce +dehisced +dehiscence +dehiscent +dehisces +dehiscing +dehorn +dehorned +dehorning +dehorns +dehumanization +dehumanize +dehumanized +dehumanizes +dehumanizing +dehumidification +dehumidifications +dehumidified +dehumidifier +dehumidifiers +dehumidifies +dehumidify +dehumidifying +dehydratase +dehydratases +dehydrate +dehydrated +dehydrates +dehydrating +dehydration +dehydrator +dehydrators +dehydrochlorinase +dehydrochlorinases +dehydrochlorinate +dehydrochlorinated +dehydrochlorinates +dehydrochlorinating +dehydrochlorination +dehydrogenase +dehydrogenases +dehydrogenate +dehydrogenated +dehydrogenates +dehydrogenating +dehydrogenation +dehydrogenization +dehydrogenize +dehydrogenized +dehydrogenizes +dehydrogenizing +dehypnotize +dehypnotized +dehypnotizes +dehypnotizing +dei +deice +deiced +deicer +deicers +deices +deicide +deicides +deicing +deictic +deictically +deific +deification +deified +deifier +deifiers +deifies +deify +deifying +deign +deigned +deigning +deigns +deimos +deindustrialization +deindustrialize +deindustrialized +deindustrializes +deindustrializing +deinstitutionalization +deinstitutionalize +deinstitutionalized +deinstitutionalizes +deinstitutionalizing +deionization +deionize +deionized +deionizer +deionizers +deionizes +deionizing +deipnosophist +deipnosophists +deirdre +deism +deist +deistic +deistical +deistically +deists +deities +deity +deject +dejected +dejectedly +dejectedness +dejecting +dejection +dejects +dekagram +dekagrams +dekaliter +dekaliters +dekameter +dekameters +deke +deked +dekes +deking +dekker +del +delacroix +delaminate +delaminated +delaminates +delaminating +delamination +delaminations +delate +delated +delates +delating +delation +delations +delator +delators +delaware +delawarean +delawares +delay +delayed +delayer +delayers +delaying +delays +dele +delectability +delectable +delectableness +delectables +delectably +delectation +delectations +deled +delegable +delegacies +delegacy +delegalization +delegalize +delegalized +delegalizes +delegalizing +delegate +delegated +delegates +delegating +delegation +delegations +delegator +delegators +delegitimization +delegitimize +delegitimized +delegitimizes +delegitimizing +deleing +deles +delete +deleted +deleterious +deleteriously +deleteriousness +deletes +deleting +deletion +deletions +delft +delfts +delftware +delhi +deli +deliberant +deliberate +deliberated +deliberately +deliberateness +deliberates +deliberating +deliberation +deliberations +deliberative +deliberatively +deliberativeness +deliberator +deliberators +delicacies +delicacy +delicate +delicately +delicateness +delicates +delicatessen +delicatessens +delicious +deliciously +deliciousness +delict +delicti +delicto +delicts +delight +delighted +delightedly +delightedness +delighter +delighters +delightful +delightfully +delightfulness +delighting +delights +delightsome +delightsomely +delightsomeness +delilah +delimit +delimitate +delimitated +delimitates +delimitating +delimitation +delimitative +delimited +delimiter +delimiters +delimiting +delimits +delineate +delineated +delineates +delineating +delineation +delineations +delineative +delineator +delineators +delinquencies +delinquency +delinquent +delinquently +delinquents +deliquesce +deliquesced +deliquescence +deliquescent +deliquesces +deliquescing +deliria +deliriant +delirious +deliriously +deliriousness +delirium +deliriums +delis +delist +delisted +delisting +delists +deliver +deliverability +deliverable +deliverables +deliverance +delivered +deliverer +deliverers +deliveries +delivering +delivers +delivery +deliveryman +deliverymen +dell +dell'arte +dells +delmonico +delocalization +delocalize +delocalized +delocalizes +delocalizing +delouse +deloused +delouses +delousing +delphi +delphian +delphic +delphically +delphinium +delphiniums +delphinus +delta +deltaic +deltas +deltic +deltiology +deltoid +deltoids +delude +deluded +deluder +deluders +deludes +deluding +deludingly +deluge +deluged +deluges +deluging +delusion +delusional +delusionary +delusions +delusive +delusively +delusiveness +delusory +deluster +deluxe +delve +delved +delver +delvers +delves +delving +demagnetization +demagnetize +demagnetized +demagnetizer +demagnetizers +demagnetizes +demagnetizing +demagnification +demagog +demagogic +demagogically +demagogism +demagogs +demagogue +demagoguery +demagogues +demagogy +demand +demandable +demanded +demander +demanders +demanding +demandingly +demands +demantoid +demantoids +demarcate +demarcated +demarcates +demarcating +demarcation +demarcations +demarcator +demarcators +demark +dematerialization +dematerialize +dematerialized +dematerializes +dematerializing +deme +demean +demeaned +demeaning +demeaningly +demeanor +demeanors +demeans +dement +demented +dementedly +dementedness +dementia +demential +dementing +dements +demerit +demeritorious +demeritoriously +demerits +demerol +demersal +demes +demesne +demesnes +demeter +demeton +demetons +demies +demigod +demigoddess +demigoddesses +demigods +demijohn +demijohns +demilitarization +demilitarize +demilitarized +demilitarizes +demilitarizing +demimondaine +demimondaines +demimonde +demimondes +demineralization +demineralize +demineralized +demineralizer +demineralizers +demineralizes +demineralizing +demirelief +demireliefs +demirep +demireps +demisable +demise +demised +demisemiquaver +demisemiquavers +demises +demising +demission +demissions +demit +demitasse +demitasses +demits +demitted +demitting +demiurge +demiurgeous +demiurges +demiurgic +demiurgical +demiurgically +demiworld +demiworlds +demo +demob +demobbed +demobbing +demobilization +demobilize +demobilized +demobilizes +demobilizing +demobs +democracies +democracy +democrat +democratic +democratically +democratization +democratize +democratized +democratizer +democratizes +democratizing +democrats +democritus +demodulate +demodulated +demodulates +demodulating +demodulation +demodulations +demodulator +demodulators +demoed +demogorgon +demographer +demographers +demographic +demographical +demographically +demographics +demography +demoing +demoiselle +demoiselles +demolish +demolished +demolisher +demolishers +demolishes +demolishing +demolishment +demolition +demolitionist +demolitionists +demolitions +demon +demonetization +demonetizations +demonetize +demonetized +demonetizes +demonetizing +demoniac +demoniacal +demoniacally +demonian +demonic +demonical +demonically +demonism +demonization +demonize +demonized +demonizes +demonizing +demonolatry +demonologic +demonological +demonologist +demonologists +demonology +demons +demonstrability +demonstrable +demonstrableness +demonstrably +demonstrandum +demonstrate +demonstrated +demonstrates +demonstrating +demonstration +demonstrational +demonstrations +demonstrative +demonstratively +demonstrativeness +demonstratives +demonstrator +demonstrators +demoralization +demoralize +demoralized +demoralizer +demoralizers +demoralizes +demoralizing +demoralizingly +demos +demosthenes +demote +demoted +demotes +demotic +demoting +demotion +demotions +demount +demountable +demounted +demounting +demounts +demulcent +demulcents +demur +demure +demurely +demureness +demurer +demurest +demurrable +demurrage +demurrages +demurral +demurrals +demurred +demurrer +demurrers +demurring +demurs +demy +demyelinate +demyelinated +demyelinates +demyelinating +demyelination +demystification +demystified +demystifier +demystifiers +demystifies +demystify +demystifying +demythologization +demythologize +demythologized +demythologizer +demythologizers +demythologizes +demythologizing +den +denarii +denarius +denary +denationalization +denationalize +denationalized +denationalizes +denationalizing +denaturalization +denaturalize +denaturalized +denaturalizes +denaturalizing +denaturant +denaturants +denaturation +denature +denatured +denatures +denaturing +dendriform +dendrimers +dendrite +dendrites +dendritic +dendritically +dendrobium +dendrobiums +dendrochronological +dendrochronologically +dendrochronologist +dendrochronologists +dendrochronology +dendroid +dendrologic +dendrological +dendrologist +dendrologists +dendrology +dendron +dendrons +dene +deneb +denebola +denegation +denegations +denervate +denervated +denervates +denervating +denervation +denes +dengue +deniability +deniable +deniably +denial +denials +denied +denier +deniers +denies +denigrate +denigrated +denigrates +denigrating +denigration +denigrations +denigrative +denigrator +denigrators +denigratory +denim +denims +denise +denitrification +denitrified +denitrifies +denitrify +denitrifying +denizen +denizenation +denizened +denizening +denizens +denmark +denned +denning +denominable +denominate +denominated +denominates +denominating +denomination +denominational +denominationalism +denominationalist +denominationalists +denominationally +denominations +denominative +denominatives +denominator +denominators +denormalize +denormalized +denotable +denotation +denotational +denotationally +denotations +denotative +denotatively +denote +denoted +denotement +denotes +denoting +denotive +denouement +denouements +denounce +denounced +denouncement +denouncements +denouncer +denouncers +denounces +denouncing +dens +dense +densely +denseness +denser +densest +densification +densify +densimeter +densimeters +densimetric +densities +densitometer +densitometers +densitometric +densitometry +density +dent +dental +dentalia +dentalium +dentaliums +dentally +dentals +dentate +dentately +dentation +dentations +dente +dented +denticle +denticles +denticular +denticulate +denticulated +denticulately +denticulation +dentiform +dentifrice +dentigerous +dentil +dentils +dentin +dentinal +dentine +denting +dentins +dentist +dentistry +dentists +dentition +dentoid +dents +dentulous +denture +dentures +denturist +denturists +denuclearization +denuclearize +denuclearized +denuclearizes +denuclearizing +denudate +denudated +denudates +denudating +denudation +denudations +denude +denuded +denudement +denudes +denuding +denumerability +denumerable +denumerably +denunciate +denunciated +denunciates +denunciating +denunciation +denunciations +denunciative +denunciator +denunciators +denunciatory +denver +deny +denying +denyingly +deo +deodar +deodara +deodaras +deodars +deodorant +deodorants +deodorization +deodorizations +deodorize +deodorized +deodorizer +deodorizers +deodorizes +deodorizing +deontological +deontologist +deontologists +deontology +deorbit +deorbited +deorbiting +deorbits +deoxidation +deoxidization +deoxidize +deoxidized +deoxidizer +deoxidizers +deoxidizes +deoxidizing +deoxycorticosterone +deoxycorticosterones +deoxygenate +deoxygenated +deoxygenates +deoxygenating +deoxygenation +deoxyribonuclease +deoxyribonucleases +deoxyribonucleic +deoxyribonucleotide +deoxyribonucleotides +deoxyribose +deoxyriboses +depart +departed +departeds +departing +department +departmental +departmentalization +departmentalize +departmentalized +departmentalizes +departmentalizing +departmentally +departments +departs +departure +departures +depauperate +depauperation +depend +dependability +dependable +dependableness +dependably +depended +dependence +dependences +dependencies +dependency +dependent +dependently +dependents +depending +depends +depersonalization +depersonalize +depersonalized +depersonalizes +depersonalizing +depict +depicted +depicter +depicting +depiction +depictions +depicts +depigmentation +depigmentations +depilate +depilated +depilates +depilating +depilation +depilator +depilatories +depilators +depilatory +deplane +deplaned +deplanes +deplaning +depletable +deplete +depleted +depletes +depleting +depletion +depletions +depletive +deplorability +deplorable +deplorableness +deplorably +deplore +deplored +deplorer +deplorers +deplores +deploring +deploringly +deploy +deployability +deployable +deployed +deployer +deployers +deploying +deployment +deployments +deploys +deplumation +deplume +deplumed +deplumes +depluming +depolarization +depolarize +depolarized +depolarizer +depolarizers +depolarizes +depolarizing +depoliticization +depoliticize +depoliticized +depoliticizes +depoliticizing +depollute +depolluted +depollutes +depolluting +depone +deponed +deponent +deponents +depones +deponing +depopulate +depopulated +depopulates +depopulating +depopulation +depopulations +depopulator +depopulators +deport +deportable +deportation +deportations +deported +deportee +deportees +deporting +deportment +deports +deposable +deposal +deposals +depose +deposed +deposes +deposing +deposit +depositaries +depositary +deposited +depositing +deposition +depositional +depositions +depositor +depositories +depositors +depository +deposits +depot +depots +depravation +depravations +deprave +depraved +depravedly +depravedness +depravement +depraver +depravers +depraves +depraving +depravities +depravity +deprecate +deprecated +deprecates +deprecating +deprecatingly +deprecation +deprecations +deprecative +deprecator +deprecatorily +deprecators +deprecatory +depreciable +depreciate +depreciated +depreciates +depreciating +depreciatingly +depreciation +depreciations +depreciative +depreciator +depreciators +depreciatory +depredate +depredated +depredates +depredating +depredation +depredations +depredator +depredators +depredatory +depress +depressant +depressants +depressed +depresses +depressible +depressing +depressingly +depression +depressions +depressive +depressively +depressiveness +depressives +depressor +depressors +depressurization +depressurize +depressurized +depressurizes +depressurizing +deprivable +deprival +deprivation +deprivations +deprive +deprived +deprives +depriving +deprogram +deprogrammed +deprogrammer +deprogrammers +deprogramming +deprograms +depth +depthless +depths +depurate +depurated +depurates +depurating +depuration +depurations +depurative +depurator +depurators +deputation +deputations +depute +deputed +deputes +deputies +deputing +deputization +deputize +deputized +deputizes +deputizing +deputy +dequeue +dequeued +dequeueing +dequeues +dequeuing +der +deracinate +deracinated +deracinates +deracinating +deracination +derail +derailed +derailing +derailleur +derailleurs +derailment +derailments +derails +derange +deranged +derangement +derangements +deranges +deranging +derate +derated +derates +derating +derbies +derby +derbyshire +derecognition +derecognize +derecognized +derecognizes +derecognizing +dereference +dereferenced +dereferencer +dereferencers +dereferences +dereferencing +deregulate +deregulated +deregulates +deregulating +deregulation +deregulations +deregulator +deregulators +deregulatory +derelict +dereliction +derelicts +derepress +derepressed +derepresses +derepressing +derepression +derib +deribbed +deribbing +deribs +deride +derided +derider +deriders +derides +deriding +deridingly +derision +derisive +derisively +derisiveness +derisory +derivability +derivable +derivate +derivation +derivational +derivationally +derivations +derivative +derivatively +derivativeness +derivatives +derive +derived +deriver +derivers +derives +deriving +derma +dermabrasion +dermabrasions +dermal +dermapteran +dermapterans +dermas +dermatitis +dermatogen +dermatogens +dermatoid +dermatologic +dermatological +dermatologist +dermatologists +dermatology +dermatome +dermatomes +dermatophyte +dermatophytes +dermatophytic +dermatophytosis +dermatoplasty +dermatoses +dermatosis +dermis +dermises +derogate +derogated +derogates +derogating +derogation +derogations +derogative +derogatively +derogator +derogatorily +derogatoriness +derogators +derogatory +derrick +derricks +derriere +derrieres +derring +derringer +derringers +derris +derrière +derrières +dervish +dervishes +desacralize +desacralized +desacralizes +desacralizing +desalinate +desalinated +desalinates +desalinating +desalination +desalinator +desalinators +desalinization +desalinize +desalinized +desalinizes +desalinizing +desalt +desalted +desalting +desalts +descant +descanted +descanter +descanters +descanting +descants +descartes +descend +descendant +descendants +descended +descendent +descendents +descender +descenders +descendible +descending +descends +descent +descents +deschutes +descramble +descrambled +descrambler +descramblers +descrambles +descrambling +describable +describe +described +describer +describers +describes +describing +descried +descrier +descriers +descries +description +descriptions +descriptive +descriptively +descriptiveness +descriptor +descriptors +descry +descrying +desdemona +desecrate +desecrated +desecrater +desecraters +desecrates +desecrating +desecration +desecrations +desecrator +desecrators +desegregate +desegregated +desegregates +desegregating +desegregation +desegregationist +desegregationists +deselect +deselected +deselecting +deselects +desensitization +desensitize +desensitized +desensitizer +desensitizers +desensitizes +desensitizing +desert +deserted +deserter +deserters +desertic +desertification +deserting +desertion +desertions +deserts +deserve +deserved +deservedly +deservedness +deserver +deservers +deserves +deserving +deservingly +desex +desexed +desexes +desexing +desexualization +desexualize +desexualized +desexualizes +desexualizing +desiccant +desiccants +desiccate +desiccated +desiccates +desiccating +desiccation +desiccations +desiccative +desiccator +desiccators +desiderata +desiderate +desiderated +desiderates +desiderating +desideration +desiderative +desideratum +design +designable +designate +designated +designates +designating +designation +designations +designative +designator +designators +designatory +designed +designedly +designee +designees +designer +designers +designing +designingly +designs +desipramine +desipramines +desirability +desirable +desirableness +desirables +desirably +desire +desired +desirer +desirers +desires +desiring +desirous +desirously +desirousness +desist +desistance +desisted +desisting +desists +desk +deskill +deskilled +deskilling +deskills +deskman +deskmen +desks +desktop +desktops +desman +desmans +desmid +desmids +desolate +desolated +desolately +desolateness +desolater +desolaters +desolates +desolating +desolatingly +desolation +desolator +desolators +desorb +desorbed +desorbing +desorbs +desorption +despair +despaired +despairer +despairers +despairing +despairingly +despairs +despatch +despatched +despatches +despatching +desperado +desperadoes +desperados +desperate +desperately +desperateness +desperation +despicable +despicableness +despicably +despisal +despise +despised +despisement +despisements +despiser +despisers +despises +despising +despite +despiteful +despitefully +despitefulness +despoil +despoiled +despoiler +despoilers +despoiling +despoilment +despoilments +despoils +despoliation +despond +desponded +despondence +despondency +despondent +despondently +desponding +despondingly +desponds +despot +despotic +despotically +despotism +despots +desquamate +desquamated +desquamates +desquamating +desquamation +dessert +desserts +dessertspoon +dessertspoonful +dessertspoonfuls +dessertspoons +destabilization +destabilize +destabilized +destabilizes +destabilizing +destain +destained +destaining +destains +destalinization +destalinizations +desterilize +desterilized +desterilizes +desterilizing +destination +destinations +destine +destined +destines +destinies +destining +destiny +destitute +destituteness +destitution +destroy +destroyed +destroyer +destroyers +destroying +destroys +destruct +destructed +destructibility +destructible +destructibleness +destructing +destruction +destructionist +destructionists +destructions +destructive +destructively +destructiveness +destructivity +destructor +destructors +destructs +desuetude +desulfurization +desulfurize +desulfurized +desulfurizes +desulfurizing +desultorily +desultoriness +desultory +desynchronize +desynchronized +desynchronizes +desynchronizing +detach +detachability +detachable +detachably +detached +detachedly +detachedness +detaches +detaching +detachment +detachments +detail +detailed +detailedly +detailedness +detailer +detailers +detailing +details +detain +detained +detainee +detainees +detainer +detainers +detaining +detainment +detains +detect +detectability +detectable +detected +detecter +detecters +detecting +detection +detections +detective +detectives +detector +detectors +detects +detent +detente +detentes +detention +detentions +detents +deter +deterge +deterged +detergence +detergences +detergency +detergent +detergents +deterges +deterging +deteriorate +deteriorated +deteriorates +deteriorating +deterioration +deteriorations +deteriorative +determent +determents +determinability +determinable +determinableness +determinably +determinacy +determinant +determinantal +determinants +determinate +determinately +determinateness +determinater +determinaters +determination +determinations +determinative +determinatively +determinativeness +determinatives +determine +determined +determinedly +determinedness +determiner +determiners +determines +determining +determinism +determinist +deterministic +deterministically +determinists +deterrable +deterred +deterrence +deterrent +deterrently +deterrents +deterrer +deterrers +deterring +deters +detersive +detersives +detest +detestability +detestable +detestableness +detestably +detestation +detested +detester +detesters +detesting +detests +dethatch +dethatched +dethatcher +dethatchers +dethatches +dethatching +dethrone +dethroned +dethronement +dethrones +dethroning +detinue +detinues +detonabilities +detonability +detonable +detonatable +detonate +detonated +detonates +detonating +detonation +detonations +detonative +detonator +detonators +detour +detoured +detouring +detours +detox +detoxed +detoxes +detoxicant +detoxicants +detoxicate +detoxicated +detoxicates +detoxicating +detoxication +detoxification +detoxified +detoxifies +detoxify +detoxifying +detoxing +detract +detracted +detracting +detractingly +detraction +detractions +detractive +detractively +detractor +detractors +detracts +detrain +detrained +detraining +detrainment +detrains +detribalization +detribalize +detribalized +detribalizes +detribalizing +detriment +detrimental +detrimentally +detriments +detrital +detrition +detritions +detritus +detroit +detumescence +detumescences +detumescent +deucalion +deuce +deuced +deucedly +deuces +deucing +deum +deums +deus +deuteragonist +deuteragonists +deuteranope +deuteranopia +deuteranopias +deuteranopic +deuterate +deuterated +deuterates +deuterating +deuteration +deuterations +deuterium +deuterocanonical +deuterogamy +deuteron +deuteronomic +deuteronomy +deuterons +deutoplasm +deutoplasmic +deutoplasms +deutsch +deutsche +deutschmark +deutschmarks +deutzia +deutzias +deux +devaluate +devaluated +devaluates +devaluating +devaluation +devaluations +devalue +devalued +devalues +devaluing +devanagari +devastate +devastated +devastates +devastating +devastatingly +devastation +devastations +devastative +devastator +devastators +develop +developable +developed +developer +developers +developing +development +developmental +developmentally +developments +develops +deverbative +deverbatives +devereux +devest +devested +devesting +devests +devi +deviance +deviances +deviancies +deviancy +deviant +deviants +deviate +deviated +deviates +deviating +deviation +deviational +deviationism +deviationist +deviationists +deviations +deviator +deviators +deviatory +device +devices +devil +deviled +devilfish +devilfishes +deviling +devilish +devilishly +devilishness +devilkin +devilkins +devilled +devilling +devilment +devilments +devilries +devilry +devils +deviltries +deviltry +devilwood +devilwoods +devious +deviously +deviousness +devisable +devise +devised +devisee +devisees +deviser +devisers +devises +devising +devisor +devisors +devitalization +devitalize +devitalized +devitalizes +devitalizing +devitrifiable +devitrification +devitrified +devitrifies +devitrify +devitrifying +devocalization +devocalize +devocalized +devocalizes +devocalizing +devoice +devoiced +devoices +devoicing +devoid +devoir +devoirs +devolatilization +devolatilize +devolatilized +devolatilizes +devolatilizing +devolution +devolutionary +devolutionist +devolutionists +devolve +devolved +devolvement +devolves +devolving +devon +devonian +devote +devoted +devotedly +devotedness +devotee +devotees +devotement +devotes +devoting +devotion +devotional +devotionally +devotionals +devotions +devour +devoured +devourer +devourers +devouring +devouringly +devours +devout +devouter +devoutest +devoutly +devoutness +dew +dewali +dewan +dewans +dewater +dewatered +dewatering +dewaters +dewberries +dewberry +dewclaw +dewclawed +dewdrop +dewdrops +dewed +dewfall +dewier +dewiest +dewily +dewiness +dewing +dewlap +dewlaps +dewless +deworm +dewormed +dewormer +dewormers +deworming +deworms +dews +dewy +dex +dexamethasone +dexamethasones +dexedrine +dexes +dexie +dexies +dexter +dexterity +dexterous +dexterously +dexterousness +dextral +dextrality +dextrally +dextran +dextrans +dextrin +dextro +dextroamphetamine +dextroamphetamines +dextroglucose +dextroglucoses +dextrorotation +dextrorotations +dextrorotatory +dextrorse +dextrorsely +dextrose +dhabi +dharma +dharmic +dharna +dharnas +dhaulagiri +dhole +dholes +dhoti +dhotis +dhow +dhows +dhurrie +dhurries +di +diabase +diabases +diabetes +diabetic +diabetics +diable +diablerie +diableries +diablo +diabolic +diabolical +diabolically +diabolicalness +diabolism +diabolist +diabolists +diabolize +diabolized +diabolizes +diabolizing +diacetylmorphine +diachronic +diachronically +diachronies +diachrony +diaconal +diaconate +diaconates +diacritic +diacritical +diacritically +diacritics +diadelphous +diadem +diademed +diademing +diadems +diadromous +diads +diaeresis +diagenesis +diagenetic +diageotropic +diageotropism +diaghilev +diagnosable +diagnose +diagnoseable +diagnosed +diagnoses +diagnosing +diagnosis +diagnostic +diagnostically +diagnostician +diagnosticians +diagnostics +diagonal +diagonalizable +diagonalization +diagonalize +diagonalized +diagonalizes +diagonalizing +diagonally +diagonals +diagram +diagramed +diagraming +diagrammable +diagrammatic +diagrammatical +diagrammatically +diagrammed +diagramming +diagrams +diakineses +diakinesis +diakinetic +dial +dialect +dialectal +dialectally +dialectic +dialectical +dialectically +dialectician +dialecticians +dialectics +dialectological +dialectologically +dialectologist +dialectologists +dialectology +dialects +dialed +dialer +dialers +dialing +dialled +dialling +dialog +dialoged +dialogic +dialogical +dialogically +dialoging +dialogist +dialogistic +dialogistical +dialogistically +dialogists +dialogs +dialogue +dialogued +dialoguer +dialoguers +dialogues +dialoguing +dials +dialup +dialups +dialyses +dialysis +dialytic +dialytically +dialyzabilities +dialyzability +dialyzable +dialyze +dialyzed +dialyzer +dialyzers +dialyzes +dialyzing +diamagnet +diamagnetic +diamagnetism +diamagnets +diamante +diamantes +diamanté +diamantés +diameter +diameters +diametral +diametric +diametrical +diametrically +diamine +diamines +diamond +diamondback +diamondbacks +diamonded +diamondiferous +diamonding +diamonds +diana +diandrous +diane +dianthus +diapason +diapasons +diapause +diapauses +diapedeses +diapedesis +diapedetic +diaper +diapered +diapering +diapers +diaphaneity +diaphanous +diaphanously +diaphanousness +diaphone +diaphoreses +diaphoresis +diaphoretic +diaphoretics +diaphragm +diaphragmatic +diaphragmatically +diaphragms +diaphyseal +diaphyses +diaphysial +diaphysis +diapir +diapiric +diapirs +diapophyses +diapophysial +diapophysis +diapositive +diapsid +diapsids +diarchal +diarchic +diarchies +diarchy +diaries +diarist +diarists +diarize +diarized +diarizes +diarizing +diarrhea +diarrheal +diarrheas +diarrheic +diarrhetic +diarthrodial +diarthroses +diarthrosis +diary +diaspora +diasporas +diaspore +diaspores +diastase +diastases +diastasic +diastasis +diastatic +diastema +diastemata +diastematic +diastole +diastoles +diastolic +diastrophic +diastrophically +diastrophism +diastrophisms +diatessaron +diatessarons +diathermic +diathermy +diatheses +diathesis +diathetic +diatom +diatomaceous +diatomic +diatomite +diatoms +diatonic +diatonically +diatonicism +diatribe +diatribes +diatropic +diatropism +diatropisms +diaz +diazepam +diazine +diazines +diazinon +diazinons +diazo +diazonium +diazoniums +dibasic +dibber +dibbers +dibble +dibbled +dibbler +dibblers +dibbles +dibbling +dibden +dibranchiate +dibranchiates +dibromide +dibromides +dibs +dicarboxylic +dicast +dicastic +dicasts +dice +diced +dicentra +dicentras +dicephalous +dicer +dicers +dices +dicey +dichasia +dichasial +dichasially +dichasium +dichloride +dichlorodiphenyl +dichlorodiphenyltrichloroethane +dichlorodiphenyltrichloroethanes +dichlorvos +dichogamous +dichogamy +dichondra +dichondras +dichotic +dichotically +dichotomic +dichotomies +dichotomist +dichotomists +dichotomization +dichotomize +dichotomized +dichotomizes +dichotomizing +dichotomous +dichotomously +dichotomousness +dichotomy +dichroic +dichroism +dichroisms +dichroite +dichroites +dichromat +dichromate +dichromatic +dichromatism +dichromats +dichromic +dicier +diciest +dicing +dick +dickcissel +dickcissels +dickens +dickensian +dickensians +dicker +dickered +dickering +dickers +dickey +dickeys +dickies +dicks +dicky +diclinous +dicliny +dicofol +dicofols +dicot +dicots +dicotyledon +dicotyledonous +dicotyledons +dicrotic +dicrotism +dicta +dictaphone +dictaphones +dictate +dictated +dictates +dictating +dictation +dictations +dictator +dictatorial +dictatorially +dictatorialness +dictators +dictatorship +dictatorships +diction +dictional +dictionally +dictionaries +dictionary +dictu +dictum +dictums +dictyosome +dictyosomes +dictyostelium +did +didact +didactic +didactical +didactically +didacticism +didactics +didacts +didapper +didappers +diddle +diddled +diddler +diddlers +diddles +diddling +diddly +diddlysquat +diderot +didn +didn't +dido +didoes +didos +didst +didymium +didymous +didynamous +die +dieback +diebacks +died +dieffenbachia +dieffenbachias +diego +diehard +diehards +dieldrin +dieldrins +dielectric +dielectrically +dielectrics +diem +diemen +diencephalic +diencephalon +diencephalons +dieppe +diereses +dieresis +dies +diesel +dieselize +dieselized +dieselizes +dieselizing +diesels +dieses +diesinker +diesinkers +diesinking +diesis +diestock +diestocks +diestrous +diestrus +diet +dietaries +dietarily +dietary +dieted +dieter +dieters +dietetic +dietetically +dietetics +diethyl +diethylcarbamazine +diethylstilbestrol +dietician +dieticians +dieting +dietitian +dietitians +dietrich +diets +differ +differed +difference +differenced +differences +differencing +different +differentia +differentiability +differentiable +differentiae +differential +differentially +differentials +differentiate +differentiated +differentiates +differentiating +differentiation +differentiations +differentiator +differentiators +differently +differentness +differing +differs +difficile +difficult +difficulties +difficultly +difficulty +diffidence +diffident +diffidently +diffract +diffracted +diffracting +diffraction +diffractions +diffractive +diffractively +diffractiveness +diffractometer +diffractometers +diffracts +diffuse +diffused +diffusely +diffuseness +diffuser +diffusers +diffuses +diffusible +diffusibly +diffusing +diffusion +diffusional +diffusions +diffusive +diffusively +diffusiveness +dig +digamma +digammas +digamous +digamy +digastric +digastrics +digest +digested +digester +digesters +digestibility +digestible +digestibleness +digestibly +digesting +digestion +digestions +digestive +digestively +digestiveness +digestives +digests +digger +diggers +digging +diggings +digit +digital +digitalin +digitalins +digitalis +digitalization +digitalize +digitalized +digitalizes +digitalizing +digitally +digitals +digitate +digitately +digitation +digitations +digitigrade +digitization +digitize +digitized +digitizer +digitizers +digitizes +digitizing +digitoxin +digitoxins +digits +diglossia +diglossias +diglyceride +diglycerides +dignified +dignifiedly +dignifies +dignify +dignifying +dignitaries +dignitary +dignities +dignity +digoxin +digoxins +digraph +digraphic +digraphs +digress +digressed +digresses +digressing +digression +digressional +digressionary +digressions +digressive +digressively +digressiveness +digs +dihedral +dihedrals +dihybrid +dihybrids +dihydric +dihydroxy +dihydroxyphenylalanine +dihydroxyphenylalanines +dijkstra +dijon +dikaryon +dikaryons +dike +diked +dikes +diking +diktat +diktats +dilantin +dilapidate +dilapidated +dilapidates +dilapidating +dilapidation +dilapidations +dilatability +dilatable +dilatably +dilatancies +dilatancy +dilatant +dilatants +dilatation +dilatational +dilatations +dilatator +dilatators +dilate +dilated +dilatedness +dilates +dilating +dilation +dilations +dilative +dilatometer +dilatometers +dilatometric +dilatometry +dilator +dilatorily +dilatoriness +dilators +dilatory +dildo +dildos +dilemma +dilemmas +dilemmatic +dilettante +dilettantes +dilettantish +dilettantism +diligence +diligent +diligently +dill +dillies +dills +dilly +dillydallied +dillydallies +dillydally +dillydallying +diluent +diluents +dilute +diluted +diluteness +diluter +diluters +dilutes +diluting +dilution +dilutions +dilutive +dilutor +dilutors +diluvial +dim +dime +dimenhydrinate +dimenhydrinates +dimension +dimensional +dimensionality +dimensionally +dimensioned +dimensioning +dimensionless +dimensions +dimer +dimercaprol +dimercaprols +dimeric +dimerism +dimerization +dimerize +dimerized +dimerizes +dimerizing +dimerous +dimers +dimes +dimeter +dimeters +dimethoate +dimethoates +dimethyl +dimethylnitrosamine +dimethylnitrosamines +dimethyls +dimethylsulfoxide +dimethylsulfoxides +diminish +diminishable +diminished +diminishes +diminishing +diminishment +diminishments +diminuendo +diminuendos +diminution +diminutional +diminutive +diminutively +diminutiveness +diminutives +dimities +dimittis +dimity +dimly +dimmable +dimmed +dimmer +dimmers +dimmest +dimming +dimness +dimorph +dimorphic +dimorphism +dimorphisms +dimorphous +dimorphs +dimout +dimple +dimpled +dimples +dimpling +dimply +dims +dimwit +dimwits +dimwitted +dimwittedly +dimwittedness +din +dinar +dinard +dinars +dine +dined +diner +diners +dines +dinette +dinettes +ding +dingbat +dingbats +dingdong +dingdonged +dingdonging +dingdongs +dinged +dinghies +dinghy +dingier +dingiest +dingily +dinginess +dinging +dingle +dingles +dingo +dingoes +dings +dingus +dinguses +dingy +dining +dinitrobenzene +dinitrobenzenes +dink +dinkey +dinkeys +dinkier +dinkiest +dinks +dinkum +dinky +dinned +dinner +dinnerless +dinners +dinnertime +dinnerware +dinning +dinoflagellate +dinoflagellates +dinosaur +dinosaurian +dinosaurians +dinosauric +dinosaurlike +dinosaurs +dinothere +dinotheres +dins +dint +dinted +dinting +dints +dinucleotide +dinucleotides +diocesan +diocesans +diocese +dioceses +diocletian +diode +diodes +diodorus +dioecious +dioeciously +dioecism +diogenes +dioicous +diomede +diomedes +dione +dionysia +dionysiac +dionysian +dionysius +dionysos +dionysus +diophantine +diopside +diopsides +diopter +diopters +dioptometer +dioptometers +dioptometry +dioptral +dioptric +dioptrics +diorama +dioramas +dioramic +diorite +diorites +dioritic +dioscuri +dioxane +dioxanes +dioxide +dioxides +dioxin +dioxins +dip +dipeptidase +dipeptidases +dipeptide +dipeptides +dipetalous +diphase +diphasic +diphenyl +diphenylamine +diphenylaminechloroarsine +diphenylaminechloroarsines +diphenylamines +diphenylhydantoin +diphenylhydantoins +diphenylketone +diphenylketones +diphenyls +diphosgene +diphosgenes +diphosphate +diphosphates +diphosphoglyceric +diphtheria +diphtherial +diphtheric +diphtheritic +diphtheroid +diphtheroids +diphthong +diphthongal +diphthongization +diphthongize +diphthongized +diphthongizes +diphthongizing +diphthongs +diphycercal +diphycercy +diphyletic +diphyllous +diphyodont +diplegia +diplegias +diplex +diplexer +diplexers +diploblastic +diplococcal +diplococci +diplococcic +diplococcus +diplodocus +diplodocuses +diploe +diploes +diploic +diploid +diploids +diploidy +diploma +diplomacies +diplomacy +diplomas +diplomat +diplomate +diplomates +diplomatic +diplomatically +diplomatics +diplomatist +diplomatists +diplomats +diplont +diplontic +diplonts +diplopia +diplopias +diplopic +diplopod +diplopodous +diplopods +diplosis +dipnoan +dipnoans +dipodic +dipodies +dipody +dipolar +dipole +dipoles +dipped +dipper +dipperful +dipperfuls +dippers +dippier +dippiest +dipping +dippy +dipropellant +dipropellants +diprotic +dips +dipsomania +dipsomaniac +dipsomaniacal +dipsomaniacs +dipstick +dipsticks +dipteral +dipteran +dipterans +dipterous +diptych +diptychs +dipyridamole +dipyridamoles +diquat +diquats +dirac +dire +direct +directed +directing +direction +directional +directionality +directionally +directionals +directionless +directions +directive +directives +directivity +directly +directness +directoire +director +directorate +directorates +directorial +directorially +directories +directors +directorship +directorships +directory +directress +directresses +directrices +directrix +directrixes +directs +direful +direfully +direfulness +direly +direness +direr +direst +dirge +dirgeful +dirges +dirham +dirhams +dirichlet +dirigible +dirigibles +dirk +dirked +dirking +dirks +dirndl +dirndls +dirt +dirtied +dirtier +dirties +dirtiest +dirtily +dirtiness +dirty +dirtying +disabilities +disability +disable +disabled +disablement +disables +disabling +disablingly +disabuse +disabused +disabuses +disabusing +disaccharidase +disaccharidases +disaccharide +disaccharides +disaccord +disaccorded +disaccording +disaccords +disaccustom +disaccustomed +disaccustoming +disaccustoms +disadvantage +disadvantaged +disadvantagedness +disadvantageous +disadvantageously +disadvantageousness +disadvantages +disadvantaging +disaffect +disaffected +disaffectedly +disaffecting +disaffection +disaffects +disaffiliate +disaffiliated +disaffiliates +disaffiliating +disaffiliation +disaffiliations +disaffirm +disaffirmance +disaffirmation +disaffirmed +disaffirming +disaffirms +disaggregate +disaggregated +disaggregates +disaggregating +disaggregation +disaggregative +disagree +disagreeable +disagreeableness +disagreeably +disagreed +disagreeing +disagreement +disagreements +disagrees +disallow +disallowable +disallowance +disallowed +disallowing +disallows +disambiguate +disambiguated +disambiguates +disambiguating +disambiguation +disambiguations +disannul +disannulled +disannulling +disannulment +disannuls +disappear +disappearance +disappearances +disappeared +disappearing +disappears +disappoint +disappointed +disappointedly +disappointing +disappointingly +disappointment +disappointments +disappoints +disapprobation +disapproval +disapprove +disapproved +disapprover +disapprovers +disapproves +disapproving +disapprovingly +disarm +disarmament +disarmed +disarmer +disarmers +disarming +disarmingly +disarms +disarrange +disarranged +disarrangement +disarranges +disarranging +disarray +disarrayed +disarraying +disarrays +disarticulate +disarticulated +disarticulates +disarticulating +disarticulation +disarticulator +disarticulators +disassemble +disassembled +disassembler +disassemblers +disassembles +disassembling +disassembly +disassociate +disassociated +disassociates +disassociating +disassociation +disaster +disasters +disastrous +disastrously +disastrousness +disavow +disavowable +disavowal +disavowals +disavowed +disavowing +disavows +disband +disbanded +disbanding +disbandment +disbandments +disbands +disbar +disbarment +disbarred +disbarring +disbars +disbelief +disbelieve +disbelieved +disbeliever +disbelievers +disbelieves +disbelieving +disbelievingly +disbranch +disbranched +disbranches +disbranching +disbud +disbudded +disbudding +disbuds +disburden +disburdened +disburdening +disburdenment +disburdens +disbursable +disbursal +disbursals +disburse +disbursed +disbursement +disbursements +disburser +disbursers +disburses +disbursing +disc +discalced +discard +discardable +discarded +discarder +discarders +discarding +discards +discarnate +discern +discerned +discerner +discerners +discernible +discernibly +discerning +discerningly +discernment +discerns +discharge +dischargeable +discharged +dischargee +dischargees +discharger +dischargers +discharges +discharging +disci +disciform +disciple +disciples +discipleship +disciplinable +disciplinal +disciplinarian +disciplinarians +disciplinarily +disciplinarity +disciplinary +discipline +disciplined +discipliner +discipliners +disciplines +disciplining +disclaim +disclaimed +disclaimer +disclaimers +disclaiming +disclaims +disclamation +disclamations +disclimax +disclimaxes +disclosable +disclose +disclosed +discloser +disclosers +discloses +disclosing +disclosure +disclosures +disco +discoed +discographer +discographers +discographic +discographical +discographies +discography +discoid +discoidal +discoideum +discoing +discolor +discoloration +discolored +discoloring +discolors +discombobulate +discombobulated +discombobulates +discombobulating +discombobulation +discomfit +discomfited +discomfiting +discomfits +discomfiture +discomfort +discomfortable +discomforted +discomforting +discomfortingly +discomforts +discommend +discommendable +discommended +discommending +discommends +discommode +discommoded +discommodes +discommoding +discompose +discomposed +discomposedly +discomposes +discomposing +discomposingly +discomposure +disconcert +disconcerted +disconcerting +disconcertingly +disconcertment +disconcerts +disconfirm +disconfirmatory +disconfirmed +disconfirming +disconfirms +disconformities +disconformity +disconnect +disconnected +disconnectedly +disconnectedness +disconnecting +disconnection +disconnects +disconsolate +disconsolately +disconsolateness +disconsolation +discontent +discontented +discontentedly +discontentedness +discontenting +discontentment +discontents +discontinuance +discontinuation +discontinuations +discontinue +discontinued +discontinues +discontinuing +discontinuities +discontinuity +discontinuous +discontinuously +discontinuousness +discophile +discophiles +discord +discordance +discordancy +discordant +discordantly +discorded +discording +discords +discorporate +discos +discotheque +discotheques +discothèque +discothèques +discount +discountable +discounted +discountenance +discountenanced +discountenances +discountenancing +discounter +discounters +discounting +discounts +discourage +discourageable +discouraged +discouragement +discouragements +discourager +discouragers +discourages +discouraging +discouragingly +discourse +discoursed +discourser +discoursers +discourses +discoursing +discourteous +discourteously +discourteousness +discourtesies +discourtesy +discover +discoverability +discoverable +discovered +discoverer +discoverers +discoveries +discovering +discovers +discovery +discredit +discreditable +discreditably +discredited +discrediting +discredits +discreet +discreetly +discreetness +discrepance +discrepances +discrepancies +discrepancy +discrepant +discrepantly +discrete +discretely +discreteness +discretion +discretional +discretionally +discretionarily +discretionary +discretization +discretize +discretized +discretizes +discretizing +discriminability +discriminable +discriminably +discriminant +discriminants +discriminate +discriminated +discriminately +discriminates +discriminating +discriminatingly +discrimination +discriminational +discriminations +discriminative +discriminatively +discriminator +discriminatorily +discriminators +discriminatory +discs +discursion +discursive +discursively +discursiveness +discus +discuses +discuss +discussable +discussant +discussants +discussed +discusser +discussers +discusses +discussible +discussing +discussion +discussions +disdain +disdained +disdainful +disdainfully +disdainfulness +disdaining +disdains +disease +diseased +diseases +diseconomies +diseconomy +disembark +disembarkation +disembarked +disembarking +disembarks +disembarrass +disembarrassed +disembarrasses +disembarrassing +disembarrassment +disembodied +disembodies +disembodiment +disembody +disembodying +disembogue +disembogued +disemboguement +disembogues +disemboguing +disembowel +disemboweled +disemboweling +disembowelment +disembowelments +disembowels +disemploy +disemployed +disemploying +disemployment +disemploys +disempower +disempowered +disempowering +disempowerment +disempowers +disenable +disenabled +disenables +disenabling +disenchant +disenchanted +disenchanter +disenchanters +disenchanting +disenchantingly +disenchantment +disenchants +disencumber +disencumbered +disencumbering +disencumberment +disencumbers +disendow +disendowed +disendower +disendowers +disendowing +disendowment +disendows +disenfranchise +disenfranchised +disenfranchisement +disenfranchises +disenfranchising +disengage +disengaged +disengagement +disengages +disengaging +disentail +disentailed +disentailing +disentailment +disentails +disentangle +disentangled +disentanglement +disentangles +disentangling +disenthrall +disenthralled +disenthralling +disenthralls +disentitle +disentitled +disentitles +disentitling +disentomb +disentombed +disentombing +disentombs +disentwine +disentwined +disentwines +disentwining +disequilibrate +disequilibrated +disequilibrates +disequilibrating +disequilibration +disequilibrium +disestablish +disestablished +disestablishes +disestablishing +disestablishment +disestablishmentarian +disestablishmentarians +disesteem +disesteemed +disesteeming +disesteems +diseur +diseurs +diseuse +diseuses +disfavor +disfavored +disfavoring +disfavors +disfeature +disfeatured +disfeaturement +disfeatures +disfeaturing +disfiguration +disfigure +disfigured +disfigurement +disfigurements +disfigurer +disfigurers +disfigures +disfiguring +disfranchise +disfranchised +disfranchisement +disfranchiser +disfranchisers +disfranchises +disfranchising +disfrock +disfrocked +disfrocking +disfrocks +disgorge +disgorged +disgorgement +disgorges +disgorging +disgrace +disgraced +disgraceful +disgracefully +disgracefulness +disgracer +disgracers +disgraces +disgracing +disgruntle +disgruntled +disgruntlement +disgruntles +disgruntling +disguise +disguised +disguisedly +disguisement +disguisements +disguiser +disguisers +disguises +disguising +disgust +disgusted +disgustedly +disgustful +disgustfully +disgusting +disgustingly +disgusts +dish +dishabille +disharmonic +disharmonies +disharmonious +disharmoniously +disharmonize +disharmonized +disharmonizes +disharmonizing +disharmony +dishcloth +dishcloths +dishearten +disheartened +disheartening +dishearteningly +disheartenment +disheartenments +disheartens +dished +dishes +dishevel +disheveled +disheveling +dishevelment +dishevels +dishier +dishiest +dishing +dishonest +dishonesties +dishonestly +dishonesty +dishonor +dishonorable +dishonorableness +dishonorably +dishonored +dishonorer +dishonorers +dishonoring +dishonors +dishpan +dishpans +dishrag +dishrags +dishtowel +dishtowels +dishware +dishwares +dishwasher +dishwashers +dishwashing +dishwater +dishwaters +dishy +disillusion +disillusioned +disillusioning +disillusionment +disillusions +disillusive +disincarnate +disincentive +disincentives +disinclination +disinclinations +disincline +disinclined +disinclines +disinclining +disincorporate +disincorporated +disincorporates +disincorporating +disincorporation +disinfect +disinfectant +disinfectants +disinfected +disinfecting +disinfection +disinfects +disinfest +disinfestant +disinfestants +disinfestation +disinfested +disinfesting +disinfests +disinflation +disinflationary +disinform +disinformant +disinformants +disinformation +disinformed +disinformer +disinformers +disinforming +disinforms +disingenuous +disingenuously +disingenuousness +disinherit +disinheritance +disinheritances +disinherited +disinheriting +disinherits +disinhibit +disinhibited +disinhibiting +disinhibition +disinhibitions +disinhibits +disintegrate +disintegrated +disintegrates +disintegrating +disintegration +disintegrations +disintegrative +disintegrator +disintegrators +disinter +disinterest +disinterested +disinterestedly +disinterestedness +disintermediation +disintermediations +disinterment +disinterred +disinterring +disinters +disintoxicate +disintoxicated +disintoxicates +disintoxicating +disintoxication +disinvent +disinvented +disinventing +disinvention +disinvents +disinvest +disinvested +disinvesting +disinvestment +disinvestments +disinvests +disinvitation +disinvite +disinvited +disinvites +disinviting +disjoin +disjoined +disjoining +disjoins +disjoint +disjointed +disjointedly +disjointedness +disjointing +disjoints +disjunct +disjunction +disjunctive +disjunctively +disjuncture +disjunctures +disk +disked +diskette +diskettes +disking +diskless +disklike +disks +dislikable +dislike +disliked +dislikes +disliking +dislocate +dislocated +dislocates +dislocating +dislocation +dislocations +dislodge +dislodged +dislodgement +dislodges +dislodging +dislodgment +disloyal +disloyally +disloyalties +disloyalty +dismal +dismally +dismalness +dismantle +dismantled +dismantlement +dismantles +dismantling +dismast +dismasted +dismasting +dismasts +dismay +dismayed +dismaying +dismayingly +dismays +dismember +dismembered +dismembering +dismemberment +dismembers +dismiss +dismissal +dismissals +dismissed +dismisses +dismissible +dismissing +dismission +dismissive +dismount +dismountable +dismounted +dismounting +dismounts +disney +disneyland +disobedience +disobedient +disobediently +disobey +disobeyed +disobeyer +disobeyers +disobeying +disobeys +disoblige +disobliged +disobliges +disobliging +disobligingly +disorder +disordered +disorderedly +disorderedness +disordering +disorderliness +disorderly +disorders +disorganization +disorganize +disorganized +disorganizes +disorganizing +disorient +disorientate +disorientated +disorientates +disorientating +disorientation +disoriented +disorienting +disorients +disown +disowned +disowning +disownment +disowns +disparage +disparaged +disparagement +disparager +disparagers +disparages +disparaging +disparagingly +disparate +disparately +disparateness +disparities +disparity +disparlure +disparlures +dispassion +dispassionate +dispassionately +dispassionateness +dispatch +dispatched +dispatcher +dispatchers +dispatches +dispatching +dispel +dispelled +dispelling +dispels +dispensability +dispensable +dispensableness +dispensaries +dispensary +dispensation +dispensational +dispensations +dispensatories +dispensatory +dispense +dispensed +dispenser +dispensers +dispenses +dispensing +dispeople +dispeopled +dispeoples +dispeopling +dispersal +dispersant +disperse +dispersed +dispersedly +disperser +dispersers +disperses +dispersible +dispersing +dispersion +dispersions +dispersive +dispersively +dispersiveness +dispirit +dispirited +dispiritedly +dispiritedness +dispiriting +dispirits +displace +displaceable +displaced +displacement +displacements +displacer +displacers +displaces +displacing +displant +displanted +displanting +displants +display +displayable +displayed +displaying +displays +displease +displeased +displeases +displeasing +displeasingly +displeasure +disport +disported +disporting +disportment +disports +disposability +disposable +disposal +disposals +dispose +disposed +disposer +disposers +disposes +disposing +disposition +dispositions +dispossess +dispossessed +dispossesses +dispossessing +dispossession +dispossessions +dispossessor +dispossessors +dispossessory +dispraise +dispraised +dispraiser +dispraisers +dispraises +dispraising +dispraisingly +disproof +disproportion +disproportional +disproportionally +disproportionate +disproportionately +disproportionateness +disproportionation +disproportioned +disproportioning +disproportions +disprovable +disproval +disprove +disproved +disproves +disproving +disputability +disputable +disputably +disputant +disputants +disputation +disputations +disputatious +disputatiously +disputatiousness +dispute +disputed +disputer +disputers +disputes +disputing +disqualification +disqualifications +disqualified +disqualifies +disqualify +disqualifying +disquiet +disquieted +disquieting +disquietingly +disquietly +disquietness +disquiets +disquietude +disquisition +disraeli +disrate +disrated +disrates +disrating +disregard +disregarded +disregarder +disregarders +disregardful +disregarding +disregards +disrelish +disrelished +disrelishes +disrelishing +disremember +disremembered +disremembering +disremembers +disrepair +disreputability +disreputable +disreputableness +disreputably +disrepute +disrespect +disrespectability +disrespectable +disrespected +disrespectful +disrespectfully +disrespectfulness +disrespecting +disrespects +disrobe +disrobed +disrober +disrobers +disrobes +disrobing +disrupt +disrupted +disrupter +disrupters +disrupting +disruption +disruptions +disruptive +disruptively +disruptiveness +disruptor +disruptors +disrupts +dissatisfaction +dissatisfactions +dissatisfactory +dissatisfied +dissatisfiedly +dissatisfies +dissatisfy +dissatisfying +dissect +dissected +dissectible +dissecting +dissection +dissections +dissector +dissectors +dissects +disseize +disseized +disseizes +disseizin +disseizing +disseizins +dissemblance +dissemble +dissembled +dissembler +dissemblers +dissembles +dissembling +dissemblingly +disseminate +disseminated +disseminates +disseminating +dissemination +disseminations +disseminator +disseminators +disseminule +disseminules +dissension +dissensions +dissent +dissented +dissenter +dissenters +dissentience +dissentient +dissentients +dissenting +dissentingly +dissents +dissepiment +dissepimental +dissepiments +dissert +dissertate +dissertated +dissertates +dissertating +dissertation +dissertations +dissertator +dissertators +disserted +disserting +disserts +disserve +disserved +disserves +disservice +disserving +dissever +disseverance +dissevered +dissevering +disseverment +dissevers +dissidence +dissident +dissidents +dissilient +dissimilar +dissimilarities +dissimilarity +dissimilarly +dissimilate +dissimilated +dissimilates +dissimilating +dissimilation +dissimilations +dissimilatory +dissimilitude +dissimulate +dissimulated +dissimulates +dissimulating +dissimulation +dissimulations +dissimulative +dissimulator +dissimulators +dissipate +dissipated +dissipatedly +dissipatedness +dissipater +dissipaters +dissipates +dissipating +dissipation +dissipations +dissipative +dissipator +dissipators +dissociability +dissociable +dissociableness +dissociably +dissociate +dissociated +dissociates +dissociating +dissociation +dissociations +dissociative +dissolubility +dissoluble +dissolubleness +dissolute +dissolutely +dissoluteness +dissolution +dissolutive +dissolvable +dissolve +dissolved +dissolvent +dissolvents +dissolver +dissolvers +dissolves +dissolving +dissonance +dissonances +dissonancies +dissonancy +dissonant +dissonantly +dissuade +dissuaded +dissuader +dissuaders +dissuades +dissuading +dissuasion +dissuasions +dissuasive +dissuasively +dissuasiveness +dissymmetric +dissymmetrical +dissymmetrically +dissymmetries +dissymmetry +distaff +distaffs +distal +distally +distance +distanced +distances +distancing +distant +distantly +distantness +distaste +distasted +distasteful +distastefully +distastefulness +distastes +distasting +distemper +distemperate +distempered +distempering +distempers +distend +distended +distending +distends +distensibility +distensible +distension +distensions +distention +distich +distichous +distichously +distichs +distil +distill +distillable +distillate +distillates +distillation +distillations +distilled +distiller +distilleries +distillers +distillery +distilling +distills +distils +distinct +distinction +distinctions +distinctive +distinctively +distinctiveness +distinctly +distinctness +distinguish +distinguishability +distinguishable +distinguishably +distinguished +distinguishes +distinguishing +distingué +distort +distortable +distorted +distortedly +distorter +distorters +distorting +distortion +distortional +distortionary +distortions +distortive +distorts +distract +distracted +distractedly +distracter +distracters +distractibility +distractible +distracting +distractingly +distraction +distractions +distractive +distracts +distrain +distrainable +distrained +distrainee +distrainees +distrainer +distrainers +distraining +distrainment +distrainor +distrainors +distrains +distraint +distraints +distrait +distraught +distraughtly +distress +distressed +distresses +distressful +distressfully +distressfulness +distressing +distressingly +distributable +distributaries +distributary +distribute +distributed +distributee +distributes +distributing +distribution +distributional +distributions +distributive +distributively +distributiveness +distributives +distributivity +distributor +distributors +distributorship +distributorships +district +districted +districting +districts +districtwide +distrust +distrusted +distrustful +distrustfully +distrustfulness +distrusting +distrusts +disturb +disturbance +disturbances +disturbed +disturber +disturbers +disturbing +disturbingly +disturbs +disulfide +disulfides +disulfoton +disulfotons +disunion +disunionist +disunionists +disunite +disunited +disunites +disunities +disuniting +disunity +disuse +disused +disutility +disvalue +disvalued +disvalues +disvaluing +disyllabic +disyllable +disyllables +ditch +ditched +ditcher +ditchers +ditches +ditching +dither +dithered +ditherer +ditherers +dithering +dithers +dithery +dithyramb +dithyrambic +dithyrambs +ditsier +ditsiest +ditsy +dittanies +dittany +ditties +ditto +dittoed +dittoes +dittoing +dittos +ditty +diu +diuresis +diuretic +diuretically +diuretics +diurnal +diurnally +diurnals +diuron +diurons +diva +divagate +divagated +divagates +divagating +divagation +divagations +divalent +divan +divans +divaricate +divaricated +divaricately +divaricates +divaricating +divarication +divarications +divas +dive +dived +diver +diverge +diverged +divergence +divergences +divergencies +divergency +divergent +divergently +diverges +diverging +divers +diverse +diversely +diverseness +diversification +diversified +diversifier +diversifiers +diversifies +diversiform +diversify +diversifying +diversion +diversionary +diversionist +diversionists +diversions +diversities +diversity +divert +diverted +diverter +diverters +diverticula +diverticular +diverticulitis +diverticulosis +diverticulum +divertimenti +divertimento +divertimentos +diverting +divertingly +divertissement +divertissements +diverts +dives +divest +divested +divesting +divestiture +divestitures +divestment +divestments +divests +dividable +divide +divided +dividend +dividends +divider +dividers +divides +dividing +divination +divinations +divinatory +divine +divined +divinely +divineness +diviner +diviners +divines +divinest +diving +divining +divinities +divinity +divisibility +divisible +divisibleness +divisibly +division +divisional +divisionism +divisionist +divisionists +divisions +divisive +divisively +divisiveness +divisor +divisors +divorce +divorced +divorcee +divorcees +divorcement +divorcements +divorces +divorcing +divorcé +divorcée +divorcées +divorcés +divot +divots +divulge +divulged +divulgement +divulgence +divulger +divulgers +divulges +divulging +divvied +divvies +divvy +divvying +diwali +dixie +dixiecrat +dixiecratic +dixiecrats +dixieland +dixit +dixon +dizen +dizened +dizening +dizenment +dizens +dizygotic +dizygous +dizzied +dizzier +dizzies +dizziest +dizzily +dizziness +dizzy +dizzying +dizzyingly +djakarta +djellaba +djellabah +djibouti +djiboutian +djiboutians +dna +dnieper +do +do's +doable +dobbies +dobbin +dobbins +dobby +doberman +dobermans +dobra +dobras +dobro +dobson +dobsonflies +dobsonfly +dobsons +doc +docent +docents +docetic +docetism +docetist +docetists +doch +docile +docilely +docility +dock +dockage +docked +docker +dockers +docket +docketed +docketing +dockets +dockhand +dockhands +docking +dockmackie +dockmackies +dockominium +dockominiums +docks +dockside +docksides +dockworker +dockworkers +dockyard +dockyards +docs +doctor +doctoral +doctorate +doctorates +doctored +doctoring +doctorless +doctorly +doctors +doctorship +doctrinaire +doctrinaires +doctrinairism +doctrinal +doctrinally +doctrinarian +doctrine +doctrines +docudrama +docudramas +docudramatic +document +documentable +documental +documentalist +documentalists +documentarian +documentarians +documentaries +documentarily +documentarist +documentarists +documentary +documentation +documentational +documented +documenter +documenters +documenting +documents +docutainment +docutainments +dodder +doddered +dodderer +dodderers +doddering +dodders +doddery +dodecagon +dodecagonal +dodecagons +dodecahedra +dodecahedral +dodecahedron +dodecahedrons +dodecanese +dodecaphonic +dodecaphonism +dodecaphonist +dodecaphonists +dodecaphony +dodge +dodged +dodger +dodgeries +dodgers +dodgery +dodges +dodgier +dodgiest +dodging +dodgy +dodo +dodoes +dodoma +dodos +doe +doer +doers +does +doeskin +doeskins +doesn +doesn't +doff +doffed +doffing +doffs +dog +dogbane +dogbanes +dogberries +dogberry +dogcart +dogcarts +dogcatcher +dogcatchers +doge +doges +dogface +dogfaces +dogfight +dogfighter +dogfighters +dogfighting +dogfightings +dogfights +dogfish +dogfishes +dogged +doggedly +doggedness +doggerel +doggerels +doggeries +doggery +doggie +doggier +doggies +doggiest +dogging +doggish +doggishly +doggishness +doggo +doggone +doggoned +doggoning +doggy +doghouse +doghouses +dogie +dogies +dogleg +doglegged +doglegging +doglegs +doglike +dogma +dogmas +dogmata +dogmatic +dogmatically +dogmaticalness +dogmatics +dogmatism +dogmatist +dogmatists +dogmatization +dogmatize +dogmatized +dogmatizes +dogmatizing +dognap +dognaped +dognaping +dognapped +dognapper +dognappers +dognapping +dognaps +dogrib +dogribs +dogs +dogsbodies +dogsbody +dogsled +dogsledder +dogsledders +dogsledding +dogsleds +dogtooth +dogtooths +dogtrot +dogtrots +dogtrotted +dogtrotting +dogwatch +dogwatches +dogwood +dogwoods +doilies +doily +doing +doings +doister +dojo +dojos +dolabriform +dolby +dolce +doldrums +dole +doled +doleful +dolefully +dolefulness +dolerite +doleritic +doles +dolesome +dolichocephalic +dolichocephalism +dolichocephaly +dolichocranial +dolichocrany +doling +doll +dollar +dollarfish +dollarfishes +dollars +dolled +dollhouse +dollhouses +dollied +dollies +dolling +dollish +dollishly +dollishness +dollop +dollops +dolls +dolly +dollying +dolma +dolmades +dolman +dolmans +dolmas +dolmen +dolmens +dolomite +dolomites +dolomitic +dolomitization +dolomitize +dolor +doloroso +dolorous +dolorously +dolorousness +dolors +dolphin +dolphins +dolt +doltish +doltishly +doltishness +dolts +dom +domain +domains +dome +domed +domenichino +domes +domesday +domestic +domestically +domesticate +domesticated +domesticates +domesticating +domestication +domestications +domesticities +domesticity +domesticize +domesticized +domesticizes +domesticizing +domestics +domical +domically +domicile +domiciled +domiciles +domiciliary +domiciliate +domiciliation +domiciling +dominance +dominant +dominantly +dominants +dominate +dominated +dominates +dominating +domination +dominations +dominative +dominator +dominators +dominatrices +dominatrix +dominatrixes +domineer +domineered +domineering +domineeringly +domineeringness +domineers +doming +domingo +domini +dominic +dominica +dominical +dominican +dominicans +dominie +dominies +dominion +dominions +dominique +domino +dominoes +dominos +domitian +domo +domos +doms +don +don't +don'ts +donald +donate +donated +donatello +donates +donating +donation +donations +donatism +donatist +donatists +donative +donatives +donator +donators +done +donee +donees +doneness +dong +dongs +donjon +donjons +donkey +donkeys +donkeywork +donkeyworks +donna +donnas +donne +donned +donning +donnish +donnishly +donnishness +donnybrook +donnybrooks +donnée +donor +donors +dons +donut +donuts +doodad +doodads +doodle +doodlebug +doodlebugs +doodled +doodler +doodlers +doodles +doodling +doohickey +doohickeys +doom +doomed +doomful +doomfully +dooming +dooms +doomsayer +doomsayers +doomsday +doomster +door +doorbell +doorbells +doored +doorframe +doorframes +dooring +doorjamb +doorjambs +doorkeeper +doorkeepers +doorknob +doorknobs +doorknocker +doorknockers +doorless +doorman +doormat +doormats +doormen +doornail +doornails +doorplate +doorplates +doorpost +doorposts +doors +doorsill +doorsills +doorstep +doorsteps +doorstop +doorstopper +doorstoppers +doorstops +doorway +doorways +doorwoman +doorwomen +dooryard +doozie +doozies +doozy +dopa +dopamine +dopant +dopants +dope +doped +doper +dopers +dopes +dopester +dopesters +dopey +dopier +dopiest +dopiness +doping +doppelganger +doppelgangers +doppelgänger +doppelgängers +doppler +dorado +dorbeetle +dorbeetles +dorchester +dordogne +dordrecht +dorian +dorians +doric +dories +dork +dorking +dorkings +dorks +dorm +dormancy +dormant +dormer +dormers +dormice +dormin +dormins +dormitories +dormitory +dormouse +dorms +dormy +dornick +dornicks +doronicum +doronicums +dorothy +dorp +dorps +dorris +dorsa +dorsad +dorsal +dorsally +dorset +dorsiventral +dorsiventrally +dorsolateral +dorsolaterally +dorsoventral +dorsum +dortmund +dory +dorée +dos +dosage +dosages +dose +dosed +doser +dosers +doses +dosimeter +dosimeters +dosimetric +dosimetry +dosing +doss +dossal +dossals +dossed +dosses +dossier +dossiers +dossing +dostoevski +dostoyevskian +dostoyevsky +dot +dotage +dotal +dotard +dotards +dote +doted +doter +doters +dotes +doting +dotingly +dotless +dots +dotted +dotter +dotterel +dotters +dottier +dottiest +dottily +dottiness +dotting +dottle +dottles +dotty +double +doubled +doubleday +doubleheader +doubleheaders +doubleness +doubler +doublers +doubles +doublespeak +doublet +doublethink +doublethinks +doubleton +doubletons +doubletree +doubletrees +doublets +doublewide +doublewides +doubleword +doublewords +doubling +doubloon +doubloons +doubly +doubt +doubtable +doubted +doubter +doubters +doubtful +doubtfully +doubtfulness +doubting +doubtingly +doubtless +doubtlessly +doubtlessness +doubts +douceur +douceurs +douche +douched +douches +douching +doug +dough +doughboy +doughboys +doughface +doughfaces +doughier +doughiest +doughiness +doughlike +doughnut +doughnuts +doughtier +doughtiest +doughtily +doughtiness +doughty +doughy +douglas +doum +doums +dour +dourer +dourest +dourine +dourines +dourly +dourness +douro +douse +doused +douser +dousers +douses +dousing +doute +dove +dovecote +dovecotes +dovekie +dovekies +dover +doves +dovetail +dovetailed +dovetailing +dovetails +dovish +dovishness +dow +dowager +dowagers +dowdier +dowdies +dowdiest +dowdily +dowdiness +dowdy +dowdyish +dowel +doweled +doweling +dowels +dower +dowered +dowering +dowers +dowitcher +dowitchers +down +downbeat +downbeats +downburst +downbursts +downcast +downcourt +downdraft +downdrafts +downed +downer +downers +downfall +downfallen +downfalls +downfield +downgrade +downgraded +downgrades +downgrading +downhaul +downhauls +downhearted +downheartedly +downheartedness +downhill +downhills +downier +downiest +downiness +downing +downlink +downlinked +downlinking +downlinks +download +downloadable +downloaded +downloading +downloads +downplay +downplayed +downplaying +downplays +downpour +downpours +downrange +downrigger +downriggers +downright +downrightly +downrightness +downriver +downs +downscale +downscaled +downscales +downscaling +downshift +downshifted +downshifting +downshifts +downside +downsides +downsize +downsized +downsizes +downsizing +downslide +downslides +downslope +downspin +downspins +downspout +downspouts +downstage +downstairs +downstate +downstater +downstaters +downstream +downstroke +downswing +downswings +downtick +downticks +downtime +downtimes +downtown +downtowner +downtowners +downtowns +downtrend +downtrended +downtrending +downtrends +downtrodden +downturn +downturns +downward +downwardly +downwardness +downwards +downwind +downy +downzone +downzoned +downzones +downzoning +dowries +dowry +dowse +dowsed +dowser +dowsers +dowses +dowsing +doxies +doxological +doxologically +doxologies +doxology +doxorubicin +doxorubicins +doxy +doxycycline +doxycyclines +doyen +doyenne +doyennes +doyens +doyle +doze +dozed +dozen +dozens +dozenth +dozer +dozers +dozes +dozier +doziest +dozily +doziness +dozing +dozy +doña +dr +drab +drabbed +drabber +drabbest +drabbing +drabble +drabbled +drabbles +drabbling +drably +drabness +drabs +dracaena +dracaenas +drachenfels +drachm +drachma +drachmae +drachmas +drachms +draconian +draconic +draconically +dracula +draft +draftable +drafted +draftee +draftees +drafter +drafters +draftier +draftiest +draftily +draftiness +drafting +draftings +drafts +draftsman +draftsmanship +draftsmen +draftsperson +draftspersons +draftswoman +draftswomen +drafty +drag +dragged +dragger +draggers +draggier +draggiest +dragging +draggingly +draggle +draggled +draggles +draggling +draggy +draglift +draglifts +dragline +draglines +dragnet +dragnets +dragoman +dragomans +dragomen +dragon +dragonet +dragonets +dragonflies +dragonfly +dragonhead +dragonheads +dragonish +dragonroot +dragonroots +dragons +dragoon +dragooned +dragooning +dragoons +drags +dragster +dragsters +dragée +drain +drainable +drainage +drained +drainer +drainers +draining +drainpipe +drainpipes +drains +drake +drakes +dram +drama +dramamine +dramas +dramatic +dramatically +dramatics +dramatis +dramatist +dramatists +dramatization +dramatizations +dramatize +dramatized +dramatizes +dramatizing +dramaturge +dramaturges +dramaturgic +dramaturgical +dramaturgically +dramaturgy +drams +drang +drank +drapability +drapable +drape +draped +draper +draperies +drapers +drapery +drapes +draping +drastic +drastically +drat +dratted +dratting +draught +draughts +dravidian +dravidians +dravidic +draw +drawable +drawback +drawbacks +drawbar +drawbars +drawbridge +drawbridges +drawdown +drawdowns +drawee +drawees +drawer +drawerful +drawers +drawing +drawings +drawknife +drawknives +drawl +drawled +drawler +drawlers +drawling +drawlingly +drawls +drawly +drawn +drawnwork +drawplate +drawplates +draws +drawshave +drawshaves +drawstring +drawstrings +drawtube +drawtubes +dray +drayage +drayed +draying +drayman +draymen +drays +drayton +dread +dreaded +dreadful +dreadfully +dreadfulness +dreading +dreadlocked +dreadlocks +dreadnought +dreadnoughts +dreads +dream +dreamboat +dreamboats +dreamed +dreamer +dreamers +dreamful +dreamfully +dreamfulness +dreamier +dreamiest +dreamily +dreaminess +dreaming +dreamland +dreamlands +dreamless +dreamlessly +dreamlessness +dreamlike +dreams +dreamscape +dreamscapes +dreamt +dreamtime +dreamtimes +dreamworld +dreamworlds +dreamy +drear +drearier +dreariest +drearily +dreariness +dreary +dreck +drecks +drecky +dredge +dredged +dredger +dredgers +dredges +dredging +dreg +dregs +dreidel +dreidels +drench +drenched +drencher +drenchers +drenches +drenching +dresden +dress +dressage +dressed +dresser +dressers +dresses +dressier +dressiest +dressily +dressiness +dressing +dressings +dressmaker +dressmakers +dressmaking +dressy +drew +dreyfus +drib +dribble +dribbled +dribbler +dribblers +dribbles +dribbling +driblet +driblets +dribs +dried +drier +driers +dries +driest +drift +driftage +driftages +drifted +drifter +drifters +drifting +driftingly +drifts +driftwood +drifty +drill +drillability +drillable +drilled +driller +drillers +drilling +drillings +drillmaster +drillmasters +drills +drillstock +drillstocks +drily +drink +drinkability +drinkable +drinkables +drinker +drinkers +drinking +drinks +drip +dripless +dripped +dripper +drippier +drippiest +drippily +drippiness +dripping +drippings +drippy +drips +dripstone +dripstones +drivability +drivable +drive +drivel +driveled +driveler +drivelers +driveline +drivelines +driveling +drivelled +drivelling +drivels +driven +drivenness +driver +driverless +drivers +drives +drivetrain +drivetrains +driveway +driveways +driving +drivingly +drizzle +drizzled +drizzles +drizzling +drizzly +drogue +drogues +droit +droits +droll +droller +drolleries +drollery +drollest +drollness +drolls +drolly +dromedaries +dromedary +dromond +dromonds +drone +droned +droner +droners +drones +droning +droningly +drool +drooled +drooling +drools +droop +drooped +droopier +droopiest +droopily +droopiness +drooping +droopingly +droops +droopy +drop +dropforge +dropforged +dropforges +dropforging +drophead +dropkick +dropkicked +dropkicker +dropkickers +dropkickes +dropkicking +dropkicks +droplet +droplets +droplight +droplights +dropout +dropouts +dropped +dropper +dropperful +droppers +dropping +droppings +drops +dropsical +dropsically +dropsy +dropwort +dropworts +drosera +droseras +droshkies +droshky +drosophila +dross +drossy +drought +droughtiness +droughts +droughty +drove +drover +drovers +droves +drown +drowned +drowning +drownings +drowns +drowse +drowsed +drowses +drowsier +drowsiest +drowsily +drowsiness +drowsing +drowsy +drub +drubbed +drubber +drubbers +drubbing +drubbings +drubs +drudge +drudged +drudger +drudgeries +drudgers +drudgery +drudges +drudgework +drudgeworks +drudging +drudgingly +drug +drugged +drugget +druggets +druggie +druggier +druggies +druggiest +drugging +druggist +druggists +druggy +drugless +drugmaker +drugmakers +drugola +drugolas +drugs +drugstore +drugstores +druid +druidic +druidical +druidically +druidism +druids +drum +drumbeat +drumbeater +drumbeaters +drumbeating +drumbeats +drumette +drumettes +drumfire +drumfires +drumhead +drumheads +drumlike +drumlin +drumlins +drummed +drummer +drummers +drumming +drumroll +drumrolls +drums +drumstick +drumsticks +drunk +drunkard +drunkards +drunken +drunkenly +drunkenness +drunker +drunkest +drunks +drupaceous +drupe +drupelet +drupelets +drupes +druse +druses +druthers +dry +dryable +dryad +dryadic +dryads +dryasdust +dryasdusts +dryden +dryer +dryers +dryest +drying +dryings +drylands +drylot +drylots +dryly +dryness +dryopithecine +dryopithecines +drypoint +drypoints +drys +drysalter +drysalters +drysaltery +drywall +drywalls +duad +duads +dual +dualism +dualist +dualistic +dualistically +dualists +dualities +duality +dualize +dualized +dualizes +dualizing +dually +dub +dubai +dubbed +dubber +dubbers +dubbin +dubbing +dubbins +dubieties +dubiety +dubious +dubiously +dubiousness +dubitable +dubitably +dublin +dubliner +dubliners +dubnium +dubrovnik +dubs +dubuque +ducal +ducally +ducat +ducats +duce +duces +duchess +duchesses +duchies +duchy +duck +duckbill +duckbilled +duckbills +duckboard +ducked +ducker +duckers +duckier +duckiest +ducking +duckling +ducklings +duckpin +duckpins +ducks +ducktail +ducktails +duckweed +duckweeds +ducky +duct +ductal +ducted +ductile +ductilibility +ductility +ducting +ductings +ductless +ducts +ductule +ductules +ductwork +ductworks +dud +dude +duded +dudeen +dudeens +dudes +dudgeon +dudgeons +duding +dudish +dudishly +duds +due +duel +dueled +dueler +duelers +dueling +duelist +duelists +duelled +duelling +duels +duende +duendes +dueness +duenna +duennas +duennaship +dues +duet +duets +duetted +duetting +duff +duffel +duffels +duffer +duffers +duffle +duffles +duffs +dug +dugong +dugongs +dugout +dugouts +dugs +duiker +duikers +duke +duked +dukedom +dukedoms +dukes +dukhobor +dukhobors +duking +dulcet +dulcetly +dulcification +dulcified +dulcifies +dulcify +dulcifying +dulcimer +dulcimers +dulcimore +dulcimores +dulcinea +dull +dullard +dullards +dulled +duller +dulles +dullest +dulling +dullish +dullishly +dullness +dulls +dullsville +dullsvilles +dully +dulness +dulse +dulses +duluth +duly +duma +dumas +dumb +dumbbell +dumbbells +dumbed +dumber +dumbest +dumbfound +dumbfounded +dumbfounding +dumbfounds +dumbing +dumbly +dumbness +dumbo +dumbos +dumbs +dumbstruck +dumbwaiter +dumbwaiters +dumdum +dumdums +dumfound +dumfounded +dumfounding +dumfounds +dumfries +dumka +dumky +dummied +dummies +dummkopf +dummkopfs +dummy +dummying +dumortierite +dumortierites +dump +dumpcart +dumpcarts +dumped +dumper +dumpers +dumpier +dumpiest +dumpily +dumpiness +dumping +dumpish +dumpling +dumplings +dumps +dumpsite +dumpsites +dumpster +dumpsters +dumpties +dumpty +dumpy +dun +duncan +dunce +dunces +dunderhead +dunderheaded +dunderheads +dundrearies +dune +dunedin +duneland +dunelike +dunes +dung +dungaree +dungarees +dunged +dungeon +dungeons +dunghill +dunghills +dunging +dungs +dungy +dunite +dunites +dunitic +dunk +dunked +dunker +dunkers +dunking +dunkirk +dunks +dunlin +dunlins +dunlop +dunlops +dunnage +dunnages +dunned +dunning +duns +duo +duodecimal +duodecimally +duodecimals +duodecimo +duodecimos +duodena +duodenal +duodenary +duodenum +duodenums +duologue +duologues +duomo +duomos +duopolies +duopoly +duopsonies +duopsony +duos +duotone +dupability +dupable +dupe +duped +duper +duperies +dupers +dupery +dupes +duping +duple +duplex +duplexer +duplexers +duplexes +duplexity +duplicable +duplicatable +duplicate +duplicated +duplicately +duplicates +duplicating +duplication +duplications +duplicative +duplicator +duplicators +duplicatory +duplicities +duplicitous +duplicitously +duplicitousness +duplicity +dupont +dura +durability +durable +durableness +durables +durably +dural +duralumin +duralumins +duramen +duramens +durance +duration +durations +durban +durbar +durbars +duress +durga +durham +durian +durians +during +durkheim +durkheimian +durmast +durmasts +duro +duroc +durocs +durometer +durometers +duros +durra +durras +durum +dusk +dusked +duskier +duskiest +duskily +duskiness +dusking +dusks +dusky +dust +dustbin +dustbins +dustcover +dustcovers +dusted +duster +dusters +dustheap +dustheaps +dustier +dustiest +dustily +dustiness +dusting +dustings +dustless +dustlike +dustman +dustmen +dustpan +dustpans +dusts +dustsheet +dustsheets +dustup +dustups +dusty +dutch +dutchman +dutchmen +dutchwoman +dutchwomen +duteous +duteously +dutiable +duties +dutiful +dutifully +dutifulness +duty +duumvir +duumvirate +duumvirates +duumvirs +duvet +duvets +duvetyn +duvetyns +dvorak +dvorák +dwarf +dwarfed +dwarfing +dwarfish +dwarfishly +dwarfishness +dwarfism +dwarflike +dwarfness +dwarfs +dwarves +dweeb +dweebs +dwell +dwelled +dweller +dwellers +dwelling +dwellings +dwells +dwelt +dwindle +dwindled +dwindles +dwindling +dyad +dyadic +dyadically +dyadics +dyads +dyak +dyaks +dyarchies +dyarchy +dybbuk +dybbukim +dybbuks +dye +dyeability +dyeable +dyed +dyeing +dyer +dyer's +dyers +dyes +dyestuff +dyestuffs +dyewood +dyewoods +dyfed +dying +dyke +dykes +dynamic +dynamical +dynamically +dynamicist +dynamicists +dynamics +dynamism +dynamist +dynamistic +dynamists +dynamite +dynamited +dynamiter +dynamiters +dynamites +dynamitic +dynamiting +dynamo +dynamoelectric +dynamoelectrical +dynamometer +dynamometers +dynamometric +dynamometrical +dynamometry +dynamos +dynamotor +dynamotors +dynast +dynastic +dynastically +dynasties +dynasts +dynasty +dynatron +dynatrons +dyne +dynes +dynode +dynodes +dyscalculia +dyscalculias +dyscrasia +dyscrasias +dysenteric +dysentery +dysfunction +dysfunctional +dysgenesis +dysgenic +dysgenics +dysgraphia +dysgraphias +dysgraphic +dyskinesia +dyskinesias +dyslectic +dyslexia +dyslexic +dyslexics +dyslogistic +dyslogistically +dysmenorrhea +dysmenorrheal +dysmenorrheic +dyspepsia +dyspeptic +dyspeptically +dyspeptics +dysphagia +dysphagias +dysphagic +dysphasia +dysphasic +dysphasics +dysphonia +dysphonias +dysphonic +dysphoria +dysphorias +dysphoric +dysplasia +dysplastic +dyspnea +dyspneas +dyspneic +dysprosium +dysrhythmia +dysrhythmias +dysteleological +dysteleologist +dysteleologists +dysteleology +dystopia +dystopian +dystopias +dystrophic +dystrophication +dystrophy +dysuria +dysurias +dysuric +dáil +débouché +débride +débrided +débridement +débrides +débriding +début +débutant +débutante +débutantes +débutants +débuts +débâcle +débâcles +déclassé +décolletage +décolletages +décolleté +décor +décors +dégagé +déjà +démarche +démodé +dénouement +dénouements +déshabillé +détente +détentes +détentist +détentists +développé +dürer +düsseldorf +e +e'er +each +eager +eagerer +eagerest +eagerly +eagerness +eagle +eagled +eagles +eaglet +eaglets +eagling +eagre +eagres +ealdorman +ealdormen +ear +earache +earaches +eardrop +eardrops +eardrum +eardrums +eared +earflap +earflaps +earful +earfuls +earing +earings +earl +earlap +earlaps +earldom +earldoms +earless +earlier +earliest +earliness +earlobe +earlobes +earlock +earlocks +earls +early +earmark +earmarked +earmarking +earmarkings +earmarks +earmuff +earmuffs +earn +earned +earner +earners +earnest +earnestly +earnestness +earnests +earning +earnings +earns +earp +earphone +earphones +earpiece +earpieces +earplug +earplugs +earring +earrings +ears +earshot +earshots +earsplitting +earth +earthborn +earthbound +earthed +earthen +earthenware +earthier +earthiest +earthily +earthiness +earthing +earthlight +earthlights +earthlike +earthliness +earthling +earthlings +earthly +earthman +earthmen +earthmover +earthmovers +earthmoving +earthnut +earthnuts +earthquake +earthquakes +earthrise +earthrises +earths +earthshaker +earthshakers +earthshaking +earthshakingly +earthshine +earthshines +earthstar +earthstars +earthward +earthwards +earthwork +earthworks +earthworm +earthworms +earthy +earwax +earwaxes +earwig +earwigged +earwigging +earwigs +earwitness +earwitnesses +earworm +earworms +ease +eased +easeful +easefully +easefulness +easel +easels +easement +easements +eases +easier +easiest +easily +easiness +easing +east +eastbound +easter +easterlies +easterly +eastern +easterner +easterners +easternmost +easternness +easters +eastertide +eastertides +easthampton +easting +eastings +eastward +eastwardly +eastwards +easy +easygoing +easygoingness +eat +eatable +eatables +eaten +eater +eateries +eaters +eatery +eating +eats +eau +eaux +eaves +eavesdrop +eavesdropped +eavesdropper +eavesdroppers +eavesdropping +eavesdrops +ebb +ebbed +ebbing +ebbs +ebola +eboli +ebon +ebonics +ebonies +ebonite +ebonites +ebonize +ebonized +ebonizes +ebonizing +ebons +ebony +ebracteate +ebro +ebullience +ebulliencies +ebulliency +ebullient +ebulliently +ebullition +ebullitions +eburnation +eburnations +ecce +eccentric +eccentrically +eccentricities +eccentricity +eccentrics +ecchymoses +ecchymosis +ecchymotic +ecclesia +ecclesiae +ecclesial +ecclesiastes +ecclesiastic +ecclesiastical +ecclesiastically +ecclesiasticism +ecclesiasticisms +ecclesiastics +ecclesiasticus +ecclesiological +ecclesiology +eccrine +ecdyses +ecdysiast +ecdysiasts +ecdysis +ecdysone +ecdysones +ecesis +ecesises +echard +echards +echelon +echeloned +echeloning +echelons +echeveria +echeverias +echidna +echidnas +echinate +echini +echinococci +echinococcoses +echinococcosis +echinococcus +echinoderm +echinodermal +echinodermatous +echinoderms +echinoid +echinoids +echinus +echo +echocardiogram +echocardiograms +echocardiograph +echocardiographic +echocardiographs +echocardiography +echoed +echoencephalogram +echoencephalograms +echoencephalograph +echoencephalographic +echoencephalographs +echoencephalography +echoer +echoers +echoes +echoey +echogram +echograms +echography +echoic +echoing +echolalia +echolalias +echolalic +echolocate +echolocated +echolocates +echolocating +echolocation +echovirus +echoviruses +eclair +eclairs +eclampsia +eclampsias +eclamptic +eclectic +eclectically +eclecticism +eclectics +eclipse +eclipsed +eclipses +eclipsing +ecliptic +ecliptics +eclogue +eclogues +eclosion +eclosions +ecocatastrophe +ecocatastrophes +ecocide +ecofreak +ecofreaks +ecologic +ecological +ecologically +ecologies +ecologist +ecologists +ecology +econometric +econometrical +econometrically +econometrician +econometricians +econometrics +econometrist +econometrists +economic +economical +economically +economics +economies +economist +economists +economize +economized +economizer +economizers +economizes +economizing +economy +ecophysiological +ecophysiology +ecospecies +ecosphere +ecospheres +ecosystem +ecosystems +ecoterrorism +ecoterrorist +ecoterrorists +ecotone +ecotones +ecotype +ecotypes +ecotypic +ecru +ecrus +ecstasies +ecstasy +ecstatic +ecstatically +ectocommensal +ectocommensals +ectoderm +ectodermal +ectodermic +ectogenous +ectomere +ectomeres +ectomeric +ectomorph +ectomorphic +ectomorphs +ectomorphy +ectoparasite +ectoparasites +ectoparasitic +ectoparasitism +ectopia +ectopias +ectopic +ectoplasm +ectoplasmic +ectosarc +ectosarcs +ectotherm +ectothermic +ectotherms +ectotrophic +ecuador +ecuadorean +ecuadoreans +ecuadorian +ecuadorians +ecumenical +ecumenicalism +ecumenically +ecumenicism +ecumenicisms +ecumenicist +ecumenicists +ecumenicity +ecumenics +ecumenism +ecumenist +ecumenists +eczema +eczemas +eczematous +edacious +edacities +edacity +edam +edaphic +edaphically +edda +eddic +eddied +eddies +eddo +eddoes +eddy +eddying +edelweiss +edelweisses +edema +edemas +edemata +edematous +eden +edenic +edentate +edentates +edentulous +edgar +edge +edged +edgeless +edger +edgers +edges +edgeways +edgewise +edgier +edgiest +edgily +edginess +edging +edgings +edgy +edh +edhs +edibility +edible +edibleness +edibles +edict +edictal +edicts +edification +edifice +edifices +edified +edifier +edifiers +edifies +edify +edifying +edifyingly +edinburgh +edison +edit +editable +edited +edith +editing +edition +editions +editor +editorial +editorialist +editorialists +editorialization +editorializations +editorialize +editorialized +editorializer +editorializers +editorializes +editorializing +editorially +editorials +editors +editorship +editorships +editress +editresses +edits +edmund +edom +edomite +edomites +edomitish +educability +educable +educate +educated +educatedness +educates +educating +education +educational +educationalist +educationalists +educationally +educationist +educationists +educations +educative +educator +educators +educe +educed +educes +educible +educing +eduction +eductions +eductor +eductors +edulcorate +edulcorated +edulcorates +edulcorating +edward +edwardian +eel +eelgrass +eelgrasses +eellike +eelpout +eelpouts +eels +eelskin +eelworm +eelworms +eely +eerie +eerier +eeriest +eerily +eeriness +eery +ef +efate +efface +effaceable +effaced +effacement +effacer +effacers +effaces +effacing +effect +effected +effecter +effecters +effectible +effecting +effective +effectively +effectiveness +effectives +effectivity +effector +effectors +effects +effectual +effectuality +effectually +effectualness +effectuate +effectuated +effectuates +effectuating +effectuation +effeminacy +effeminate +effeminately +effeminateness +effeminates +effeminize +effeminized +effeminizes +effeminizing +effendi +effendis +efferent +efferentia +efferently +efferents +effervesce +effervesced +effervescence +effervescency +effervescent +effervescently +effervesces +effervescing +effete +effetely +effeteness +efficacies +efficacious +efficaciously +efficaciousness +efficacity +efficacy +efficiencies +efficiency +efficient +efficiently +effigies +effigy +effloresce +effloresced +efflorescence +efflorescent +effloresces +efflorescing +effluence +effluences +effluent +effluents +effluvia +effluvial +effluvium +effluviums +efflux +effluxes +effluxion +effluxions +effort +effortful +effortfully +effortless +effortlessly +effortlessness +efforts +effronteries +effrontery +effulgence +effulgences +effulgent +effuse +effused +effuses +effusing +effusion +effusions +effusive +effusively +effusiveness +efik +efiks +eft +efts +eftsoons +egad +egads +egalitarian +egalitarianism +egalitarians +egalite +egalites +egeria +egerias +egest +egesta +egested +egesting +egestion +egestions +egestive +egests +egg +eggbeater +eggbeaters +eggcup +eggcups +egged +egger +eggers +eggfruit +eggfruits +egghead +eggheaded +eggheadedness +eggheads +egging +eggless +eggnog +eggnogs +eggplant +eggplants +eggs +eggshell +eggshells +eglantine +eglantines +ego +egocentric +egocentrically +egocentricities +egocentricity +egocentrics +egocentrism +egoism +egoisms +egoist +egoistic +egoistical +egoistically +egoists +egomania +egomaniac +egomaniacal +egomaniacally +egomaniacs +egomanias +egos +egotism +egotisms +egotist +egotistic +egotistical +egotistically +egotists +egregious +egregiously +egregiousness +egress +egressed +egresses +egressing +egression +egressions +egret +egrets +egypt +egyptian +egyptians +egyptological +egyptologist +egyptologists +egyptology +eh +eider +eiderdown +eiderdowns +eiders +eidetic +eidetically +eidola +eidolon +eidolons +eiffel +eigenfunction +eigenspace +eigenstate +eigenvalue +eigenvalues +eigenvector +eigenvectors +eight +eighteen +eighteenfold +eighteenmo +eighteenmos +eighteens +eighteenth +eighteenths +eightfold +eighth +eighthly +eighths +eighties +eightieth +eightieths +eightpenny +eights +eightvo +eightvos +eighty +eightyfold +eilat +eileen +eindhoven +einkorn +einkorns +einstein +einsteinian +einsteinium +eire +eisenach +eisenhower +eisteddfod +eisteddfodau +eisteddfods +either +ejaculate +ejaculated +ejaculates +ejaculating +ejaculation +ejaculations +ejaculator +ejaculators +ejaculatory +eject +ejecta +ejectable +ejected +ejecting +ejection +ejections +ejective +ejectment +ejectments +ejector +ejectors +ejects +eke +eked +ekes +eking +ekistic +ekistical +ekistician +ekisticians +ekistics +ekpwele +el +elaborate +elaborated +elaborately +elaborateness +elaborates +elaborating +elaboration +elaborations +elaborative +elaborator +elaborators +elagabalus +elaine +elam +elamite +elamites +eland +elands +elapid +elapids +elapse +elapsed +elapses +elapsing +elara +elasmobranch +elasmobranchs +elastase +elastases +elastic +elastically +elasticities +elasticity +elasticized +elastics +elastin +elastins +elastomer +elastomeric +elastomers +elate +elated +elatedly +elatedness +elater +elaterid +elaterids +elaterite +elaterites +elaters +elates +elating +elation +elations +elavil +elba +elbe +elbow +elbowed +elbowing +elbowroom +elbows +elder +elderberries +elderberry +eldercare +elderlies +elderliness +elderly +elders +eldership +eldest +eldritch +eleanor +eleatic +eleaticism +eleatics +elecampane +elecampanes +elect +electability +electable +elected +electing +election +electioneer +electioneered +electioneerer +electioneerers +electioneering +electioneers +elections +elective +electively +electiveness +electives +elector +electoral +electorally +electorate +electorates +electors +electra +electress +electresses +electret +electrets +electric +electrical +electrically +electrician +electricians +electricities +electricity +electrics +electrifiable +electrification +electrified +electrifier +electrifiers +electrifies +electrify +electrifying +electrifyingly +electroacoustic +electroacoustically +electroacoustics +electroanalyses +electroanalysis +electroanalytic +electroanalytical +electrocardiogram +electrocardiograms +electrocardiograph +electrocardiographic +electrocardiographically +electrocardiographs +electrocardiography +electrochemical +electrochemically +electrochemist +electrochemistry +electrochemists +electrocoagulation +electrocoagulations +electroconvulsive +electrocorticogram +electrocorticograms +electrocute +electrocuted +electrocutes +electrocuting +electrocution +electrocutions +electrode +electrodeposit +electrodeposited +electrodepositing +electrodeposition +electrodepositions +electrodeposits +electrodermal +electrodes +electrodialyses +electrodialysis +electrodialytic +electrodynamic +electrodynamics +electrodynamometer +electrodynamometers +electroencephalogram +electroencephalograms +electroencephalograph +electroencephalographic +electroencephalographs +electroencephalography +electroform +electroformed +electroforming +electroforms +electrogasdynamic +electrogasdynamics +electrogenesis +electrogenic +electrogram +electrograms +electrograph +electrographs +electrohydraulic +electrohydraulically +electrojet +electrokinetic +electrokinetics +electroless +electrologist +electrologists +electroluminescence +electroluminescences +electroluminescent +electrolyses +electrolysis +electrolyte +electrolytes +electrolytic +electrolytically +electrolyze +electrolyzed +electrolyzes +electrolyzing +electromagnet +electromagnetic +electromagnetically +electromagnetism +electromagnetisms +electromagnets +electromechanical +electromechanically +electrometallurgical +electrometallurgy +electrometer +electrometers +electromotive +electromyogram +electromyograms +electromyograph +electromyographic +electromyographically +electromyographs +electromyography +electron +electronegative +electronegativity +electronic +electronically +electronics +electrons +electrooculogram +electrooculograms +electrophile +electrophiles +electrophilic +electrophilicity +electrophorese +electrophoresed +electrophoreses +electrophoresing +electrophoresis +electrophoretic +electrophoretically +electrophoretogram +electrophoretograms +electrophori +electrophorus +electrophotographic +electrophotography +electrophysiologic +electrophysiological +electrophysiologically +electrophysiologist +electrophysiologists +electrophysiology +electroplate +electroplated +electroplates +electroplating +electropositive +electroreception +electroreceptor +electroreceptors +electroretinogram +electroretinograms +electroretinograph +electroretinographic +electroretinography +electroscope +electroscopes +electroscopic +electroshock +electroshocked +electroshocking +electroshocks +electrostatic +electrostatically +electrostatics +electrosurgeries +electrosurgery +electrosurgical +electrosurgically +electrotherapeutics +electrotherapies +electrotherapist +electrotherapists +electrotherapy +electrothermal +electrothermally +electrotonic +electrotonically +electrotonus +electrotonuses +electrotype +electrotyped +electrotyper +electrotypers +electrotypes +electrotypic +electrotyping +electrovalence +electrovalencies +electrovalency +electrovalent +electrowinning +electrum +electrums +elects +electuaries +electuary +eleemosynary +elegance +elegances +elegancies +elegancy +elegant +elegantly +elegiac +elegiacal +elegiacally +elegiacs +elegies +elegist +elegists +elegit +elegits +elegize +elegized +elegizes +elegizing +elegy +eleison +element +elemental +elementally +elementals +elementarily +elementariness +elementary +elements +elemi +elemis +elephant +elephantiasis +elephantine +elephants +eleusinian +eleusinians +eleusis +elevate +elevated +elevateds +elevates +elevating +elevation +elevations +elevator +elevators +eleven +elevenfold +elevens +elevenses +eleventh +elevenths +elevon +elevons +elf +elfin +elfish +elfishly +elfishness +elflock +elflocks +elgar +elhi +eli +elicit +elicitation +elicitations +elicited +eliciting +elicitor +elicitors +elicits +elide +elided +elides +eliding +eligibilities +eligibility +eligible +eligibles +eligibly +elijah +eliminate +eliminated +eliminates +eliminating +elimination +eliminations +eliminative +eliminator +eliminators +eliminatory +eliot +elisha +elision +elisions +elite +elites +elitism +elitisms +elitist +elitists +elixir +elixirs +elizabeth +elizabethan +elizabethans +elk +elkhound +elkhounds +elks +ell +ellagic +ellen +ellesmere +ellington +elliot +elliott +ellipse +ellipses +ellipsis +ellipsoid +ellipsoidal +ellipsoids +elliptic +elliptical +elliptically +ellipticity +ells +elm +elmo +elms +elocution +elocutionary +elocutionist +elocutionists +elodea +elodeas +eloign +eloigned +eloigning +eloigns +elongate +elongated +elongates +elongating +elongation +elongations +elope +eloped +elopement +elopements +eloper +elopers +elopes +eloping +eloquence +eloquent +eloquently +eloquentness +els +else +elsewhere +eluant +eluants +eluate +eluates +elucidate +elucidated +elucidates +elucidating +elucidation +elucidations +elucidative +elucidator +elucidators +elucidatory +elucubrate +elucubrated +elucubrates +elucubrating +elucubration +elucubrations +elude +eluded +eludes +eluding +elusion +elusions +elusive +elusively +elusiveness +elusory +elute +eluted +elutes +eluting +elution +elutions +elutriate +elutriated +elutriates +elutriating +elutriation +elutriations +elutriator +elutriators +eluvial +eluviate +eluviated +eluviates +eluviating +eluviation +eluviations +eluvium +eluviums +elver +elvers +elves +elvis +elvish +elysian +elysium +elytra +elytroid +elytron +em +emaciate +emaciated +emaciates +emaciating +emaciation +emaciations +email +emailed +emailing +emails +emalangeni +emanate +emanated +emanates +emanating +emanation +emanational +emanations +emanative +emancipate +emancipated +emancipates +emancipating +emancipation +emancipationist +emancipationists +emancipations +emancipative +emancipator +emancipators +emancipatory +emarginate +emargination +emarginations +emasculate +emasculated +emasculates +emasculating +emasculation +emasculations +emasculative +emasculator +emasculators +emasculatory +embalm +embalmed +embalmer +embalmers +embalming +embalmment +embalmments +embalms +embank +embanked +embanking +embankment +embankments +embanks +embarcadero +embarcaderos +embargo +embargoed +embargoes +embargoing +embargos +embark +embarkation +embarkations +embarked +embarking +embarkment +embarkments +embarks +embarrass +embarrassable +embarrassed +embarrassedly +embarrasses +embarrassing +embarrassingly +embarrassment +embarrassments +embassage +embassages +embassies +embassy +embattle +embattled +embattlement +embattlements +embattles +embattling +embay +embayed +embaying +embayment +embayments +embays +embed +embeddable +embedded +embedding +embedment +embedments +embeds +embellish +embellished +embellisher +embellishers +embellishes +embellishing +embellishment +embellishments +ember +embers +embezzle +embezzled +embezzlement +embezzlements +embezzler +embezzlers +embezzles +embezzling +embitter +embittered +embittering +embitterment +embitterments +embitters +emblaze +emblazed +emblazes +emblazing +emblazon +emblazoned +emblazoner +emblazoners +emblazoning +emblazonment +emblazonments +emblazonries +emblazonry +emblazons +emblem +emblematic +emblematical +emblematically +emblematize +emblematized +emblematizes +emblematizing +emblemed +emblements +embleming +emblemize +emblemized +emblemizes +emblemizing +emblems +embodied +embodier +embodiers +embodies +embodiment +embodiments +embody +embodying +embolden +emboldened +emboldening +emboldens +embolectomies +embolectomy +emboli +embolic +embolies +embolism +embolismic +embolisms +embolization +embolus +emboly +embonpoint +embonpoints +embosom +embosomed +embosoming +embosoms +emboss +embossable +embossed +embosser +embossers +embosses +embossing +embossment +embossments +embouchement +embouchure +embouchures +embourgeoisement +embourgeoisements +embowed +embowel +emboweled +emboweling +embowelled +embowelling +embowels +embower +embowered +embowering +embowers +embrace +embraceable +embraced +embracement +embracements +embraceor +embraceors +embracer +embraceries +embracers +embracery +embraces +embracing +embracingly +embracive +embranchment +embranchments +embrangle +embrangled +embranglement +embranglements +embrangles +embrangling +embrasure +embrasured +embrasures +embrittle +embrittled +embrittlement +embrittlements +embrittles +embrittling +embrocate +embrocated +embrocates +embrocating +embrocation +embrocations +embroider +embroidered +embroiderer +embroiderers +embroideries +embroidering +embroiders +embroidery +embroil +embroiled +embroiling +embroilment +embroilments +embroils +embrown +embrowned +embrowning +embrowns +embrue +embrued +embrues +embruing +embryectomies +embryectomy +embryo +embryogenesis +embryogenetic +embryogenic +embryogeny +embryoid +embryoids +embryologic +embryological +embryologically +embryologies +embryologist +embryologists +embryology +embryonal +embryonated +embryonic +embryonically +embryopathies +embryopathy +embryos +embryotic +emcee +emceed +emceeing +emcees +emend +emendable +emendate +emendated +emendates +emendating +emendation +emendations +emendator +emendators +emendatory +emended +emender +emenders +emending +emends +emerald +emeralds +emerge +emerged +emergence +emergences +emergencies +emergency +emergent +emergents +emerges +emerging +emeries +emerita +emeritae +emeritas +emeriti +emeritus +emersed +emersion +emersions +emerson +emery +emeses +emesis +emetic +emetically +emetics +emetine +emetines +emigrant +emigrants +emigrate +emigrated +emigrates +emigrating +emigration +emigrations +emigratory +emilia +emilion +eminence +eminences +eminencies +eminency +eminent +eminently +emir +emirate +emirates +emirs +emissaries +emissary +emission +emissions +emissive +emissivity +emit +emits +emittance +emitted +emitter +emitters +emitting +emma +emmanuel +emmaus +emmenagogue +emmenagogues +emmer +emmers +emmet +emmetropia +emmetropias +emmetropic +emmets +emmy +emmys +emodin +emodins +emollient +emollients +emolument +emoluments +emote +emoted +emoter +emoters +emotes +emoting +emotion +emotional +emotionalism +emotionalist +emotionalistic +emotionalists +emotionality +emotionalize +emotionalized +emotionalizes +emotionalizing +emotionally +emotionless +emotionlessly +emotionlessness +emotions +emotive +emotively +emotiveness +emotivity +empale +empaled +empales +empaling +empanada +empanel +empaneled +empaneling +empanelled +empanelling +empanels +empathetic +empathetically +empathic +empathize +empathized +empathizer +empathizers +empathizes +empathizing +empathy +empedocles +empennage +empennages +emperies +emperor +emperors +emperorship +emperorships +empery +emphases +emphasis +emphasize +emphasized +emphasizes +emphasizing +emphatic +emphatically +emphysema +emphysematous +emphysemic +emphysemics +empire +empires +empiric +empirical +empirically +empiricism +empiricist +empiricists +empirics +emplace +emplaced +emplacement +emplacements +emplaces +emplacing +emplane +emplaned +emplanes +emplaning +employ +employability +employable +employe +employed +employee +employees +employer +employers +employes +employing +employment +employments +employs +empoison +empoisoned +empoisoning +empoisonment +empoisons +emporia +emporium +emporiums +empower +empowered +empowering +empowerment +empowerments +empowers +empress +empressement +empressements +empresses +emprise +emprises +emptied +emptier +empties +emptiest +emptily +emptiness +emptor +empty +emptying +empurple +empurpled +empurples +empurpling +empyema +empyemas +empyemata +empyemic +empyreal +empyrean +empyreans +ems +emu +emulate +emulated +emulates +emulating +emulation +emulations +emulative +emulatively +emulator +emulators +emulous +emulously +emulousness +emulsible +emulsifiable +emulsification +emulsifications +emulsified +emulsifier +emulsifiers +emulsifies +emulsify +emulsifying +emulsion +emulsions +emulsive +emulsoid +emulsoidal +emulsoids +emunctories +emunctory +emus +en +enable +enabled +enabler +enablers +enables +enabling +enact +enactable +enacted +enacting +enactment +enactments +enactor +enactors +enacts +enamel +enameled +enameler +enamelers +enameling +enamelist +enamelists +enamelled +enamelling +enamels +enamelware +enamine +enamines +enamoenantiomeric +enamor +enamored +enamoring +enamors +enamour +enamoured +enamouring +enamours +enantiomer +enantiomers +enantiomorph +enantiomorphic +enantiomorphism +enantiomorphous +enantiomorphs +enarthroses +enarthrosis +enate +enates +enatic +enation +enations +encaenia +encage +encaged +encages +encaging +encamp +encamped +encamping +encampment +encampments +encamps +encapsulant +encapsulants +encapsulate +encapsulated +encapsulates +encapsulating +encapsulation +encapsulations +encapsulator +encapsulators +encapsule +encapsuled +encapsules +encapsuling +encase +encased +encasement +encasements +encases +encash +encashable +encashed +encashes +encashing +encashment +encasing +encaustic +encaustics +enceinte +enceintes +enceladus +encephala +encephalic +encephalitic +encephalitis +encephalitogen +encephalitogenic +encephalitogens +encephalogram +encephalograms +encephalograph +encephalographic +encephalographically +encephalographies +encephalographs +encephalography +encephaloma +encephalomas +encephalomata +encephalomyelitis +encephalon +encephalopathic +encephalopathies +encephalopathy +encephalous +enchain +enchained +enchaining +enchainment +enchainments +enchains +enchant +enchanted +enchanter +enchanters +enchanting +enchantingly +enchantment +enchantments +enchantress +enchantresses +enchants +enchase +enchased +enchases +enchasing +enchilada +enchiladas +enchiridia +enchiridion +enchiridions +encina +encinas +encipher +enciphered +encipherer +encipherers +enciphering +encipherment +encipherments +enciphers +encircle +encircled +encirclement +encirclements +encircles +encircling +enclasp +enclasped +enclasping +enclasps +enclave +enclaves +enclitic +enclitics +enclose +enclosed +encloses +enclosing +enclosure +enclosures +encode +encoded +encoder +encoders +encodes +encoding +encodings +encomia +encomiast +encomiastic +encomiastical +encomiasts +encomium +encomiums +encompass +encompassed +encompasses +encompassing +encompassment +encompassments +encore +encored +encores +encoring +encounter +encountered +encountering +encounters +encourage +encouraged +encouragement +encouragements +encourager +encouragers +encourages +encouraging +encouragingly +encrimson +encrimsoned +encrimsoning +encrimsons +encroach +encroached +encroacher +encroachers +encroaches +encroaching +encroachment +encroachments +encrust +encrustation +encrustations +encrusted +encrusting +encrusts +encrypt +encrypted +encrypting +encryption +encryptions +encrypts +encumber +encumbered +encumbering +encumbers +encumbrance +encumbrancer +encumbrancers +encumbrances +encyclical +encyclicals +encyclopaedia +encyclopaedias +encyclopedia +encyclopedias +encyclopedic +encyclopedically +encyclopedism +encyclopedisms +encyclopedist +encyclopedists +encyst +encystation +encystations +encysted +encysting +encystment +encystments +encysts +end +endamage +endamaged +endamages +endamaging +endameba +endamebae +endamebas +endamoeba +endanger +endangered +endangering +endangerment +endangerments +endangers +endarch +endarterectomies +endarterectomy +endarteritis +endbrain +endbrains +endear +endeared +endearing +endearingly +endearment +endearments +endears +endeavor +endeavored +endeavorer +endeavorers +endeavoring +endeavors +ended +endemic +endemically +endemicity +endemics +endemism +endemisms +ender +endergonic +endermic +endermically +enders +endexine +endexines +endgame +endgames +ending +endings +endive +endives +endleaf +endleaves +endless +endlessly +endlessness +endlong +endmost +endnote +endnotes +endobiotic +endoblast +endoblasts +endocardia +endocardial +endocarditic +endocarditis +endocardium +endocarp +endocarpal +endocarps +endochondral +endocrania +endocranium +endocrine +endocrinologic +endocrinological +endocrinologist +endocrinologists +endocrinology +endocytic +endocytose +endocytosed +endocytoses +endocytosing +endocytosis +endocytotic +endoderm +endodermal +endodermis +endoderms +endodontia +endodontic +endodontically +endodontics +endodontist +endodontists +endoenzyme +endoenzymes +endoergic +endogamous +endogamy +endogenic +endogenous +endogenously +endogeny +endolymph +endolymphatic +endolymphs +endometria +endometrial +endometrioses +endometriosis +endometrium +endomitosis +endomitotic +endomorph +endomorphic +endomorphism +endomorphs +endomorphy +endonuclease +endonucleases +endoparasite +endoparasites +endoparasitic +endoparasitism +endopeptidase +endopeptidases +endophyte +endophytes +endophytic +endoplasm +endoplasmic +endorphin +endorphins +endorsable +endorse +endorsed +endorsee +endorsees +endorsement +endorsements +endorser +endorsers +endorses +endorsing +endorsor +endorsors +endoscope +endoscopes +endoscopic +endoscopically +endoscopies +endoscopy +endoskeletal +endoskeleton +endoskeletons +endosmosis +endosmotic +endosmotically +endosperm +endospore +endospores +endosporia +endosporium +endostea +endosteal +endosteally +endosteum +endostyle +endosulfan +endosulfans +endosymbiont +endosymbiosis +endosymbiotic +endothecia +endothecium +endothelia +endothelial +endothelioid +endothelioma +endotheliomas +endotheliomata +endothelium +endotherm +endothermal +endothermic +endotherms +endothermy +endotoxic +endotoxin +endotoxins +endotracheal +endotrophic +endow +endowed +endowing +endowment +endowments +endows +endpaper +endpapers +endpin +endpins +endplate +endplates +endplay +endplayed +endplaying +endplays +endpoint +endpoints +endrin +endrins +ends +endsville +endsvilles +endue +endued +endues +enduing +endurable +endurably +endurance +endure +endured +endures +enduring +enduringly +enduringness +enduro +enduros +endways +endwise +endymion +enema +enemas +enemies +enemy +energetic +energetically +energetics +energies +energize +energized +energizer +energizers +energizes +energizing +energy +enervate +enervated +enervates +enervating +enervation +enervations +enervative +enervator +enervators +enface +enfaced +enfacement +enfacements +enfaces +enfacing +enfant +enfants +enfeeble +enfeebled +enfeeblement +enfeeblements +enfeebler +enfeeblers +enfeebles +enfeebling +enfeoff +enfeoffed +enfeoffing +enfeoffment +enfeoffments +enfeoffs +enfetter +enfettered +enfettering +enfetters +enfever +enfevered +enfevering +enfevers +enfield +enfilade +enfiladed +enfilades +enfilading +enfin +enflame +enflamed +enflames +enflaming +enfleurage +enfleurages +enflurane +enfluranes +enfold +enfolded +enfolder +enfolders +enfolding +enfolds +enforce +enforceability +enforceable +enforced +enforcement +enforcements +enforcer +enforcers +enforces +enforcing +enframe +enframed +enframement +enframes +enframing +enfranchise +enfranchised +enfranchisement +enfranchisements +enfranchises +enfranchising +engage +engaged +engagement +engagements +engager +engagers +engages +engaging +engagingly +engagé +engarland +engarlanded +engarlanding +engarlands +engels +engender +engendered +engenderer +engenderers +engendering +engenders +engild +engilded +engilding +engilds +engine +engined +engineer +engineered +engineering +engineerings +engineers +enginery +engines +engining +engird +engirded +engirding +engirdle +engirdled +engirdles +engirdling +engirds +engirt +englacial +england +englander +englanders +english +englished +englishes +englishing +englishman +englishmen +englishness +englishwoman +englishwomen +englut +engluts +englutted +englutting +engorge +engorged +engorgement +engorgements +engorges +engorging +engraft +engrafted +engrafting +engraftment +engraftments +engrafts +engrailed +engrain +engrained +engraining +engrains +engram +engrams +engrave +engraved +engraver +engravers +engraves +engraving +engravings +engross +engrossed +engrosser +engrossers +engrosses +engrossing +engrossingly +engrossment +engrossments +engulf +engulfed +engulfing +engulfment +engulfments +engulfs +enhalo +enhaloed +enhaloes +enhaloing +enhance +enhanced +enhancement +enhancements +enhancer +enhancers +enhances +enhancing +enhancive +enharmonic +enharmonically +enigma +enigmas +enigmatic +enigmatical +enigmatically +enisle +enisled +enisles +enisling +eniwetok +enjambement +enjambements +enjambment +enjambments +enjoin +enjoinder +enjoinders +enjoined +enjoiner +enjoiners +enjoining +enjoinment +enjoinments +enjoins +enjoy +enjoyable +enjoyableness +enjoyably +enjoyed +enjoyer +enjoyers +enjoying +enjoyment +enjoyments +enjoys +enkephalin +enkephalins +enkindle +enkindled +enkindler +enkindlers +enkindles +enkindling +enlace +enlaced +enlacement +enlacements +enlaces +enlacing +enlarge +enlargeable +enlarged +enlargement +enlargements +enlarger +enlargers +enlarges +enlarging +enlighten +enlightened +enlightener +enlighteners +enlightening +enlightenment +enlightenments +enlightens +enlist +enlisted +enlistee +enlistees +enlisting +enlistment +enlistments +enlists +enliven +enlivened +enlivener +enliveners +enlivening +enlivenment +enlivenments +enlivens +enmesh +enmeshed +enmeshes +enmeshing +enmeshment +enmeshments +enmities +enmity +ennead +enneads +ennoble +ennobled +ennoblement +ennoblements +ennobler +ennoblers +ennobles +ennobling +ennui +enoch +enoki +enokidake +enokidakes +enokis +enol +enolase +enolases +enolic +enological +enologist +enologists +enology +enols +enormities +enormity +enormous +enormously +enormousness +enosis +enough +enounce +enounced +enouncement +enouncements +enounces +enouncing +enow +enphytotic +enphytotics +enplane +enplaned +enplanes +enplaning +enqueue +enqueued +enqueueing +enqueues +enqueuing +enquire +enquired +enquires +enquiries +enquiring +enquiry +enrage +enraged +enragement +enragements +enrages +enraging +enrapt +enrapture +enraptured +enrapturement +enrapturements +enraptures +enrapturing +enrich +enriched +enricher +enrichers +enriches +enriching +enrichment +enrichments +enrobe +enrobed +enrobes +enrobing +enroll +enrolled +enrollee +enrollees +enrolling +enrollment +enrollments +enrolls +enroot +enrooted +enrooting +enroots +ens +ensample +ensamples +ensanguine +ensanguined +ensanguines +ensanguining +ensconce +ensconced +ensconces +ensconcing +ensemble +ensembles +enserf +enserfed +enserfing +enserfment +enserfs +enshrine +enshrined +enshrinement +enshrinements +enshrines +enshrining +enshroud +enshrouded +enshrouding +enshrouds +ensiform +ensign +ensigns +ensilage +ensilaged +ensilages +ensilaging +ensile +ensiled +ensiles +ensiling +enskied +enskies +ensky +enskying +enslave +enslaved +enslavement +enslavements +enslaver +enslavers +enslaves +enslaving +ensnare +ensnared +ensnarement +ensnarements +ensnarer +ensnarers +ensnares +ensnaring +ensnarl +ensnarled +ensnarling +ensnarls +ensorcel +ensorceled +ensorceling +ensorcell +ensorcelled +ensorcelling +ensorcellment +ensorcells +ensorcels +ensoul +ensouled +ensouling +ensouls +ensphere +ensphered +enspheres +ensphering +enstatite +enstatites +ensue +ensued +ensues +ensuing +ensure +ensured +ensures +ensuring +enswathe +enswathed +enswathes +enswathing +entablature +entablatures +entablement +entablements +entail +entailed +entailer +entailers +entailing +entailment +entailments +entails +entameba +entamebae +entamebas +entamoeba +entamoebae +entamoebas +entangle +entangled +entanglement +entanglements +entangler +entanglers +entangles +entangling +entases +entasis +entebbe +entelechies +entelechy +entendre +entendres +entente +ententes +enter +enterable +enteral +enterally +entered +enteric +entering +enteritis +enterobacteria +enterobacterium +enterobiasis +enterococcal +enterococci +enterococcus +enterocoele +enterocoeles +enterocolitis +enterogastrone +enterogastrones +enterohepatitis +enterokinase +enterokinases +enteron +enterons +enteropathies +enteropathogen +enteropathogenic +enteropathogens +enteropathy +enterostomal +enterostomies +enterostomy +enterotomies +enterotomy +enterotoxin +enterotoxins +enteroviral +enterovirus +enteroviruses +enterprise +enterpriser +enterprisers +enterprises +enterprising +enterprisingly +enters +entertain +entertained +entertainer +entertainers +entertaining +entertainingly +entertainment +entertainments +entertains +enthalpies +enthalpy +enthrall +enthralled +enthralling +enthrallingly +enthrallment +enthrallments +enthralls +enthrone +enthroned +enthronement +enthronements +enthrones +enthroning +enthuse +enthused +enthuses +enthusiasm +enthusiasms +enthusiast +enthusiastic +enthusiastically +enthusiasts +enthusing +enthymeme +enthymemes +entice +enticed +enticement +enticements +enticer +enticers +entices +enticing +enticingly +entire +entirely +entireness +entires +entireties +entirety +entities +entitle +entitled +entitlement +entitlements +entitles +entitling +entity +entoblast +entoblasts +entoderm +entodermal +entodermic +entoderms +entoil +entoiled +entoiling +entoils +entomb +entombed +entombing +entombment +entombments +entombs +entomologic +entomological +entomologically +entomologist +entomologists +entomology +entomophagous +entomophilous +entomophily +entomostracan +entomostracans +entourage +entourages +entozoa +entozoan +entozoic +entr +entr'acte +entr'actes +entrails +entrain +entrained +entrainer +entrainers +entraining +entrainment +entrainments +entrains +entrance +entranced +entrancement +entrancements +entrances +entranceway +entranceways +entrancing +entrancingly +entrant +entrants +entrap +entrapment +entrapments +entrapped +entrapping +entraps +entreat +entreated +entreaties +entreating +entreatingly +entreatment +entreatments +entreats +entreaty +entrechat +entrechats +entrecôte +entree +entrees +entremets +entrench +entrenched +entrenches +entrenching +entrenchment +entrenchments +entrepreneur +entrepreneurial +entrepreneurialism +entrepreneurism +entrepreneurs +entrepreneurship +entrepreneurships +entrepôt +entresol +entresols +entries +entropic +entropically +entropies +entropy +entrust +entrusted +entrusting +entrustment +entrusts +entry +entryway +entryways +entrée +entrées +entwine +entwined +entwinement +entwinements +entwines +entwining +entwist +entwisted +entwisting +entwists +enucleate +enucleated +enucleates +enucleating +enucleation +enucleations +enucleator +enucleators +enumerable +enumerate +enumerated +enumerates +enumerating +enumeration +enumerations +enumerative +enumerator +enumerators +enunciable +enunciate +enunciated +enunciates +enunciating +enunciation +enunciations +enunciative +enunciatively +enunciator +enunciators +enure +enured +enures +enuresis +enuretic +enuring +envelop +envelope +enveloped +enveloper +envelopers +envelopes +enveloping +envelopment +envelopments +envelops +envenom +envenomed +envenoming +envenoms +enviable +enviableness +enviably +envied +envier +enviers +envies +envious +enviously +enviousness +environ +environed +environing +environment +environmental +environmentalism +environmentalist +environmentalists +environmentally +environments +environs +envisage +envisaged +envisages +envisaging +envision +envisioned +envisioning +envisions +envoi +envois +envoy +envoys +envy +envying +envyingly +enwheel +enwheeled +enwheeling +enwheels +enwind +enwinding +enwinds +enwomb +enwombed +enwombing +enwombs +enwound +enwrap +enwrapped +enwrapping +enwraps +enwreathe +enwreathed +enwreathes +enwreathing +enzootic +enzootics +enzymatic +enzymatically +enzyme +enzymes +enzymic +enzymically +enzymologist +enzymologists +enzymology +eocene +eohippus +eolian +eolith +eolithic +eoliths +eon +eonian +eons +eos +eosin +eosinophil +eosinophilia +eosinophilias +eosinophilic +eosinophilous +eosinophils +eosins +epact +epacts +epaminondas +eparchies +eparchy +epaulet +epaulets +epaulette +epaulettes +epee +epees +epeirogenic +epeirogenically +epeirogenies +epeirogeny +epentheses +epenthesis +epenthetic +epergne +epergnes +epernay +epexegesis +epexegetic +epexegetical +epexegetically +ephah +ephahs +ephebe +ephebes +ephebic +ephedrine +ephemera +ephemerae +ephemeral +ephemerality +ephemerally +ephemeralness +ephemerals +ephemeras +ephemerid +ephemerides +ephemerids +ephemeris +ephemeron +ephemerons +ephesian +ephesians +ephesus +ephod +ephods +ephor +ephori +ephors +ephraim +epiblast +epiblastic +epiblasts +epibolic +epiboly +epic +epical +epically +epicalyces +epicalyx +epicalyxes +epicanthi +epicanthic +epicanthus +epicardia +epicardial +epicardium +epicarp +epicarps +epicene +epicenes +epicenism +epicenter +epicenters +epicentral +epichlorohydrin +epichlorohydrins +epicondyle +epicondyles +epicotyl +epicotyls +epicritic +epics +epictetus +epicure +epicurean +epicureanism +epicureanisms +epicureans +epicures +epicurism +epicurisms +epicurus +epicuticle +epicuticles +epicycle +epicycles +epicyclic +epicyclical +epicyclically +epicycloid +epicycloidal +epicycloids +epidaurus +epidemic +epidemical +epidemically +epidemicity +epidemics +epidemiologic +epidemiological +epidemiologically +epidemiologist +epidemiologists +epidemiology +epidermal +epidermic +epidermis +epidermoid +epidiascope +epidiascopes +epididymal +epididymides +epididymis +epidote +epidotes +epidotic +epidural +epidurals +epifauna +epifaunae +epifaunal +epifaunas +epigastria +epigastric +epigastrium +epigeal +epigean +epigene +epigenesis +epigenetic +epigenous +epigeous +epiglottal +epiglottic +epiglottides +epiglottis +epiglottises +epigone +epigones +epigonic +epigonism +epigram +epigrammatic +epigrammatically +epigrammatism +epigrammatisms +epigrammatist +epigrammatists +epigrammatize +epigrammatized +epigrammatizer +epigrammatizers +epigrammatizes +epigrammatizing +epigrams +epigraph +epigrapher +epigraphers +epigraphic +epigraphical +epigraphically +epigraphist +epigraphists +epigraphs +epigraphy +epigynies +epigynous +epigyny +epilepsies +epilepsy +epileptic +epileptics +epileptogenic +epileptoid +epilog +epilogs +epilogue +epilogues +epimer +epimeric +epimers +epimetheus +epimysia +epimysium +epinastic +epinasties +epinasty +epinephrine +epineuria +epineurial +epineurium +epipelagic +epipetalous +epiphanic +epiphanies +epiphanous +epiphany +epiphenomena +epiphenomenal +epiphenomenalism +epiphenomenally +epiphenomenon +epiphyseal +epiphyses +epiphysial +epiphysis +epiphyte +epiphytes +epiphytic +epiphytical +epiphytically +epiphytotic +epiphytotics +episcia +episcias +episcopacies +episcopacy +episcopal +episcopalian +episcopalians +episcopally +episcopate +episcopates +episcope +episcopes +episiotomies +episiotomy +episode +episodes +episodic +episodically +episomal +episomally +episome +episomes +epistases +epistasis +epistatic +epistaxes +epistaxis +epistemic +epistemically +epistemological +epistemologically +epistemologist +epistemologists +epistemology +epistle +epistler +epistlers +epistles +epistolary +epistoler +epistolers +epistrophe +epistyle +epistyles +epitaph +epitaphial +epitaphic +epitaphs +epitases +epitasis +epitaxial +epitaxially +epitaxies +epitaxy +epithalamia +epithalamion +epithalamium +epithalamiums +epithelia +epithelial +epithelialization +epithelializations +epithelialize +epithelialized +epithelializes +epithelializing +epithelioid +epithelioma +epitheliomas +epitheliomata +epitheliomatous +epithelium +epitheliums +epithelization +epithelizations +epithelize +epithelized +epithelizes +epithelizing +epithet +epithetic +epithetical +epithets +epitome +epitomes +epitomic +epitomical +epitomize +epitomized +epitomizes +epitomizing +epizoa +epizoic +epizoism +epizoisms +epizoite +epizoites +epizoon +epizootic +epizootically +epizootics +epoch +epochal +epochally +epochs +epode +epodes +eponym +eponymic +eponymies +eponymous +eponyms +eponymy +epopee +epopees +epos +eposes +epoxide +epoxides +epoxied +epoxies +epoxy +epoxying +epsilon +epsilons +epsom +epstein +equability +equable +equableness +equably +equal +equaled +equaling +equalitarian +equalitarianism +equalities +equality +equalization +equalizations +equalize +equalized +equalizer +equalizers +equalizes +equalizing +equalled +equalling +equally +equals +equanimities +equanimity +equate +equated +equates +equating +equation +equational +equationally +equations +equator +equatorial +equatorially +equatorials +equators +equatorward +equerries +equerry +equestrian +equestrianism +equestrians +equestrianship +equestrienne +equestriennes +equiangular +equicaloric +equid +equidistance +equidistant +equidistantly +equids +equilateral +equilateralism +equilateralist +equilateralists +equilaterally +equilaterals +equilibrate +equilibrated +equilibrates +equilibrating +equilibration +equilibrations +equilibrator +equilibrators +equilibratory +equilibria +equilibrist +equilibristic +equilibrists +equilibrium +equilibriums +equimolar +equine +equinely +equines +equinoctial +equinoctials +equinox +equinoxes +equip +equipage +equipages +equipment +equipoise +equipoised +equipoises +equipoising +equipollence +equipollences +equipollent +equipollently +equipollents +equiponderance +equiponderances +equiponderant +equiponderate +equiponderated +equiponderates +equiponderating +equipotent +equipotential +equipped +equipping +equiprobable +equips +equiseta +equisetum +equisetums +equitability +equitable +equitableness +equitably +equitant +equitation +equities +equity +equivalence +equivalences +equivalencies +equivalency +equivalent +equivalently +equivalents +equivocal +equivocalities +equivocality +equivocally +equivocalness +equivocate +equivocated +equivocates +equivocating +equivocation +equivocations +equivocator +equivocators +equivoque +equivoques +er +era +eradicable +eradicate +eradicated +eradicates +eradicating +eradication +eradications +eradicative +eradicator +eradicators +eras +erasabilities +erasability +erasable +erase +erased +eraser +erasers +erases +erasing +erasmus +erastian +erastianism +erastians +erastus +erasure +erasures +erat +erato +eratosthenes +erbium +ere +erebus +erect +erectable +erected +erectile +erectilities +erectility +erecting +erection +erections +erectly +erectness +erector +erectors +erects +erelong +eremite +eremites +eremitic +eremitical +eremurus +erenow +erepsin +erepsins +erethism +erethismic +erethisms +erewhile +erfurt +erg +ergastic +ergative +ergo +ergocalciferol +ergocalciferols +ergodic +ergodicity +ergograph +ergographic +ergographs +ergometer +ergometers +ergometric +ergonometric +ergonomic +ergonomically +ergonomics +ergonomist +ergonomists +ergonovine +ergosterol +ergosterols +ergot +ergotamine +ergotamines +ergotic +ergotism +ergotisms +ergots +ergs +eric +ericoid +ericsson +eridanus +erie +eries +erigeron +erigerons +erin +eristic +eristics +eritrea +eritrean +eritreans +erlangen +erlenmeyer +ermine +ermines +erne +ernes +erode +eroded +erodes +erodibility +erodible +eroding +erogenous +eroica +eros +erose +erosely +erosion +erosional +erosionally +erosions +erosive +erosiveness +erosivity +erotic +erotica +erotically +eroticism +eroticist +eroticists +eroticization +eroticizations +eroticize +eroticized +eroticizes +eroticizing +erotics +erotism +erotisms +erotize +erotized +erotizes +erotizing +erotogenic +erotomania +erotomanias +err +errancies +errancy +errand +errands +errant +errantly +errantries +errantry +errants +errata +erratas +erratic +erratical +erratically +erraticism +erratics +erratum +erred +errhine +errhines +erring +erroneous +erroneously +erroneousness +error +errorless +errors +errs +ersatz +ersatzes +erse +erst +erstwhile +erucic +eruct +eructate +eructated +eructates +eructating +eructation +eructations +eructative +eructed +eructing +eructs +erudite +eruditely +eruditeness +erudition +erumpent +erupt +erupted +eruptible +erupting +eruption +eruptions +eruptive +eruptively +erupts +erymanthian +erymanthos +erymanthus +eryngo +eryngoes +eryngos +erysipelas +erysipelatous +erysipeloid +erysipeloids +erythema +erythematic +erythematous +erythemic +erythorbic +erythrism +erythrismal +erythrisms +erythrite +erythrites +erythroblast +erythroblastic +erythroblastoses +erythroblastosis +erythroblasts +erythrocyte +erythrocytes +erythrocytic +erythrocytometer +erythrocytometers +erythromycin +erythropoiesis +erythropoietic +erythropoietin +erythropoietins +erzgebirge +esau +escadrille +escadrilles +escalade +escaladed +escalader +escaladers +escalades +escalading +escalate +escalated +escalates +escalating +escalation +escalations +escalator +escalators +escalatory +escallop +escalloped +escalloping +escallops +escambia +escapable +escapade +escapades +escape +escaped +escapee +escapees +escapement +escapements +escaper +escapers +escapes +escaping +escapism +escapisms +escapist +escapists +escapologist +escapologists +escapology +escargot +escargots +escarole +escaroles +escarp +escarped +escarping +escarpment +escarpments +escarps +eschalot +eschalots +eschar +escharotic +escharotics +eschars +eschatological +eschatologically +eschatologist +eschatologists +eschatology +escheat +escheatable +escheatage +escheatages +escheated +escheating +escheats +escher +escherichia +eschew +eschewal +eschewals +eschewed +eschewing +eschews +escolar +escolars +escort +escorted +escorting +escorts +escot +escoted +escoting +escots +escritoire +escritoires +escrow +escrowed +escrowing +escrows +escudo +escudos +esculent +esculents +escutcheon +escutcheoned +escutcheons +esdraelon +esdras +esemplastic +eserine +eserines +esfahan +esker +eskers +eskimo +eskimoan +eskimos +esophageal +esophagi +esophagus +esoteric +esoterica +esoterically +esotericism +esotericisms +espadrille +espadrilles +espalier +espaliered +espaliering +espaliers +esparto +espartos +español +especial +especially +esperance +esperances +esperantist +esperantists +esperanto +espial +espials +espied +espiegle +espies +espionage +esplanade +esplanades +espousal +espousals +espouse +espoused +espouser +espousers +espouses +espousing +espresso +espressos +esprit +espy +espying +espíritu +esquiline +esquimau +esquimaux +esquire +esquires +ess +essay +essayed +essayer +essayers +essaying +essayist +essayistic +essayists +essays +essen +essence +essences +essene +essenes +essenian +essenic +essenism +essential +essentialism +essentialist +essentialists +essentiality +essentially +essentialness +essentials +essequibo +essex +essoin +essoins +essonite +essonites +est +establish +establishable +established +establisher +establishers +establishes +establishing +establishment +establishmentarian +establishmentarianism +establishmentarians +establishments +estaminet +estaminets +estancia +estancias +estate +estates +esteem +esteemed +esteeming +esteems +ester +esterase +esterases +esterification +esterifications +esterified +esterifies +esterify +esterifying +esters +esther +esthesia +esthesias +esthesiometer +esthesiometers +esthete +esthetes +esthetic +esthetically +esthetician +estheticians +estheticism +esthetics +estimable +estimableness +estimably +estimate +estimated +estimates +estimating +estimation +estimations +estimative +estimator +estimators +estival +estivate +estivated +estivates +estivating +estivation +estivations +estonia +estonian +estonians +estop +estoppage +estoppages +estopped +estoppel +estoppels +estopping +estops +estradiol +estradiols +estragon +estragons +estral +estrange +estranged +estrangement +estrangements +estranger +estrangers +estranges +estranging +estray +estrayed +estraying +estrays +estremadura +estremaduran +estremadurans +estriol +estriols +estrogen +estrogenic +estrogenically +estrogens +estrone +estrones +estrous +estrual +estrum +estrums +estrus +estruses +estuarial +estuaries +estuarine +estuary +esurience +esuriency +esurient +esuriently +et +eta +etagere +etageres +etamine +etamines +etatism +etatisms +etatist +etc +etcetera +etceteras +etch +etched +etcher +etchers +etches +etching +etchings +eternal +eternality +eternalize +eternalized +eternalizes +eternalizing +eternally +eternalness +eternals +eterne +eternities +eternity +eternization +eternizations +eternize +eternized +eternizes +eternizing +etesian +eth +ethacrynic +ethambutol +ethambutols +ethamine +ethamines +ethane +ethanes +ethanol +ethanolamine +ethanolamines +ethanols +ethelbert +ethelred +ethene +ethenes +ether +ethereal +ethereality +etherealization +etherealizations +etherealize +etherealized +etherealizes +etherealizing +ethereally +etherealness +etheric +etherification +etherifications +etherified +etherifies +etherify +etherifying +etherization +etherizations +etherize +etherized +etherizer +etherizers +etherizes +etherizing +ethernet +ethernets +ethers +ethic +ethical +ethicalities +ethicality +ethically +ethicalness +ethicals +ethician +ethicians +ethicist +ethicists +ethics +ethinyl +ethinyls +ethion +ethions +ethiopia +ethiopian +ethiopians +ethiopic +ethiopics +ethmoid +ethmoidal +ethmoids +ethnarch +ethnarchs +ethnarchy +ethnic +ethnical +ethnically +ethnicities +ethnicity +ethnics +ethnobotanical +ethnobotanically +ethnobotanist +ethnobotanists +ethnobotany +ethnocentric +ethnocentrically +ethnocentricity +ethnocentrism +ethnographer +ethnographers +ethnographic +ethnographical +ethnographically +ethnography +ethnohistorian +ethnohistorians +ethnohistoric +ethnohistorical +ethnohistory +ethnologic +ethnological +ethnologically +ethnologist +ethnologists +ethnology +ethnomethodologist +ethnomethodologists +ethnomethodology +ethnomusicological +ethnomusicologist +ethnomusicologists +ethnomusicology +ethogram +ethograms +ethological +ethologies +ethologist +ethologists +ethology +ethos +ethoxy +ethoxyl +ethoxyls +eths +ethyl +ethylamine +ethylamines +ethylate +ethylated +ethylates +ethylating +ethylation +ethylations +ethylene +ethylenes +ethylenic +ethylic +ethyls +ethyne +ethynes +ethynyl +ethynyls +etiolate +etiolated +etiolates +etiolating +etiolation +etiolations +etiologic +etiological +etiologically +etiologies +etiologist +etiologists +etiology +etiquette +etiquettes +etna +eton +etonian +etonians +etruria +etrurian +etrurians +etruscan +etruscans +etude +etudes +etyma +etymological +etymologically +etymologies +etymologist +etymologists +etymologize +etymologized +etymologizes +etymologizing +etymology +etymon +etymons +euboea +eucaine +eucaines +eucalypt +eucalypti +eucalyptol +eucalyptols +eucalypts +eucalyptus +eucalyptuses +eucharist +eucharistic +eucharistical +eucharists +euchre +euchred +euchres +euchring +euchromatic +euchromatin +euchromatins +euclase +euclases +euclid +euclidean +eucrite +eucrites +eucritic +eudaemonist +eudaemonists +eudemon +eudemonism +eudemonist +eudemonistic +eudemonistical +eudemonists +eudemons +eugene +eugenic +eugenically +eugenicist +eugenicists +eugenics +eugenist +eugenists +eugenol +eugenols +euglena +euglenas +euglobulin +euglobulins +eugénie +euhemerism +euhemerisms +euhemerist +euhemeristic +euhemeristically +euhemerists +euhemerize +euhemerized +euhemerizes +euhemerizing +eukaryote +eukaryotes +eukaryotic +eulachon +eulachons +euler +eulerian +eulogia +eulogies +eulogist +eulogistic +eulogistically +eulogists +eulogium +eulogiums +eulogize +eulogized +eulogizer +eulogizers +eulogizes +eulogizing +eulogy +eumenides +eunuch +eunuchism +eunuchoid +eunuchoids +eunuchs +euonymus +euonymuses +eupatrid +eupatridae +eupatrids +eupepsia +eupepsias +eupeptic +eupeptically +euphemism +euphemisms +euphemist +euphemistic +euphemistically +euphemists +euphemize +euphemized +euphemizer +euphemizers +euphemizes +euphemizing +euphenic +euphenics +euphonic +euphonically +euphonies +euphonious +euphoniously +euphoniousness +euphonium +euphoniums +euphonize +euphonized +euphonizes +euphonizing +euphony +euphorbia +euphorbias +euphoria +euphoriant +euphoriants +euphorias +euphoric +euphorically +euphotic +euphrates +euphrosyne +euphuism +euphuisms +euphuist +euphuistic +euphuistical +euphuistically +euphuists +euplastic +euploid +euploidies +euploids +euploidy +eupnea +eupneas +eupneic +eupneically +eurasia +eurasian +eurasians +eureka +eurhythmic +eurhythmics +eurhythmy +euripedes +euripi +euripidean +euripides +euripus +euro +eurobond +eurobonds +eurocentric +eurocentrism +eurocommunism +eurocommunist +eurocommunists +eurocrat +eurocratic +eurocrats +eurocurrencies +eurocurrency +eurodollar +eurodollars +euromarket +euromarkets +europa +europe +european +europeanism +europeanization +europeanize +europeanized +europeanizes +europeanizing +europeans +europium +euros +eurus +euryale +euryales +eurybath +eurybathic +eurybaths +eurydice +euryhaline +euryphagous +eurypterid +eurypterids +eurytherm +eurythermal +eurytherms +eurythmic +eurythmics +eurythmies +eurythmy +eurytopic +eurytopicity +eusebius +eustachian +eustasies +eustasy +eustatic +eustele +eusteles +eutectic +eutectics +euterpe +euthanasia +euthanasic +euthanize +euthanized +euthanizes +euthanizing +euthenics +euthenist +euthenists +eutherian +eutherians +euthyroid +eutrophic +eutrophication +eutrophications +eutrophies +eutrophy +euxenite +euxenites +evacuant +evacuants +evacuate +evacuated +evacuates +evacuating +evacuation +evacuations +evacuative +evacuator +evacuators +evacuee +evacuees +evadable +evade +evaded +evader +evaders +evades +evadible +evading +evaginate +evaginated +evaginates +evaginating +evagination +evaginations +evaluate +evaluated +evaluates +evaluating +evaluation +evaluations +evaluative +evaluator +evaluators +evanesce +evanesced +evanescence +evanescent +evanescently +evanesces +evanescing +evangel +evangelic +evangelical +evangelicalism +evangelically +evangelicals +evangelism +evangelist +evangelistic +evangelistically +evangelists +evangelization +evangelizations +evangelize +evangelized +evangelizer +evangelizers +evangelizes +evangelizing +evangels +evanton +evaporability +evaporable +evaporate +evaporated +evaporates +evaporating +evaporation +evaporations +evaporative +evaporatively +evaporativity +evaporator +evaporators +evaporite +evaporites +evaporitic +evapotranspiration +evasion +evasions +evasive +evasively +evasiveness +eve +evection +evectional +evections +evelyn +even +evened +evener +eveners +evenfall +evenfalls +evenhanded +evenhandedly +evenhandedness +evening +evenings +eveningwear +eveningwears +evenki +evenkis +evenly +evenness +evens +evensong +evensongs +event +eventful +eventfully +eventfulness +eventide +eventides +eventless +events +eventual +eventualities +eventuality +eventually +eventuate +eventuated +eventuates +eventuating +ever +everbearing +everblooming +everest +everglade +everglades +evergreen +evergreens +everlasting +everlastingly +everlastingness +evermore +eversible +eversion +eversions +evert +everted +everting +everts +every +everybody +everybody's +everyday +everydayness +everyman +everymen +everyone +everyone's +everyplace +everything +everywhere +everywoman +everywomen +eves +evict +evicted +evictee +evictees +evicting +eviction +evictions +evictor +evictors +evicts +evidence +evidenced +evidences +evidencing +evident +evidential +evidentially +evidentiary +evidently +evil +evildoer +evildoers +evildoing +evildoings +eviler +evilest +evilly +evilness +evils +evince +evinced +evinces +evincible +evincing +eviscerate +eviscerated +eviscerates +eviscerating +evisceration +eviscerations +evitable +evocable +evocation +evocations +evocative +evocatively +evocativeness +evocator +evocators +evoke +evoked +evokes +evoking +evolute +evolutes +evolution +evolutional +evolutionarily +evolutionary +evolutionism +evolutionist +evolutionists +evolutions +evolvable +evolve +evolved +evolvement +evolvements +evolves +evolving +evulsion +evulsions +evzone +evzones +ewe +ewer +ewers +ewes +ex +exaampere +exaamperes +exabecquerel +exabecquerels +exabit +exabits +exabyte +exabytes +exacandela +exacandelas +exacerbate +exacerbated +exacerbates +exacerbating +exacerbation +exacerbations +exacoulomb +exacoulombs +exact +exacta +exactable +exactas +exacted +exacter +exacters +exacting +exactingly +exactingness +exaction +exactions +exactitude +exactly +exactness +exactor +exactors +exacts +exafarad +exafarads +exaggerate +exaggerated +exaggeratedly +exaggeratedness +exaggerates +exaggerating +exaggeration +exaggerations +exaggerative +exaggerator +exaggerators +exaggeratory +exagram +exagrams +exahenries +exahenry +exahenrys +exahertz +exajoule +exajoules +exakelvin +exakelvins +exalt +exaltation +exaltations +exalted +exaltedly +exaltedness +exalter +exalters +exalting +exalts +exalumen +exalumens +exalux +exam +examen +examens +exameter +exameters +examinable +examinant +examinants +examination +examinational +examinations +examine +examined +examinee +examinees +examiner +examiners +examines +examining +examole +examoles +example +exampled +examples +exampling +exams +exanewton +exanewtons +exanimate +exanthem +exanthema +exanthemas +exanthemata +exanthematic +exanthematous +exanthems +exaohm +exaohms +exapascal +exapascals +exaradian +exaradians +exarch +exarchal +exarchate +exarchates +exarchies +exarchs +exarchy +exasecond +exaseconds +exasiemens +exasievert +exasieverts +exasperate +exasperated +exasperatedly +exasperater +exasperaters +exasperates +exasperating +exasperatingly +exasperation +exasteradian +exasteradians +exatesla +exateslas +exavolt +exavolts +exawatt +exawatts +exaweber +exawebers +excalibur +excaliburs +excaudate +excavate +excavated +excavates +excavating +excavation +excavational +excavations +excavator +excavators +exceed +exceeded +exceeding +exceedingly +exceeds +excel +excelled +excellence +excellences +excellencies +excellency +excellent +excellently +excelling +excels +excelsior +except +excepted +excepting +exception +exceptionability +exceptionable +exceptionably +exceptional +exceptionality +exceptionally +exceptionalness +exceptions +exceptive +excepts +excerpt +excerpted +excerpter +excerpters +excerpting +excerption +excerptions +excerptor +excerptors +excerpts +excess +excessed +excesses +excessing +excessive +excessively +excessiveness +exchange +exchangeability +exchangeable +exchanged +exchanger +exchangers +exchanges +exchanging +exchequer +exchequers +excimer +excimers +excipient +excipients +exciple +exciples +excisable +excise +excised +exciseman +excisemen +excises +excising +excision +excisions +excitabilities +excitability +excitable +excitableness +excitably +excitant +excitants +excitation +excitations +excitative +excitatory +excite +excited +excitedly +excitement +excitements +exciter +exciters +excites +exciting +excitingly +exciton +excitonics +excitons +excitor +excitors +exclaim +exclaimed +exclaimer +exclaimers +exclaiming +exclaims +exclamation +exclamations +exclamatory +exclave +exclaves +excludability +excludable +exclude +excluded +excluder +excluders +excludes +excludible +excluding +exclusion +exclusionary +exclusionism +exclusionist +exclusionistic +exclusionists +exclusions +exclusive +exclusively +exclusiveness +exclusives +exclusivity +excogitate +excogitated +excogitates +excogitating +excogitation +excogitations +excogitative +excommunicable +excommunicate +excommunicated +excommunicates +excommunicating +excommunication +excommunications +excommunicative +excommunicator +excommunicators +excommunicatory +excoriate +excoriated +excoriates +excoriating +excoriation +excoriations +excoriator +excoriators +excrement +excremental +excrementitious +excrements +excrescence +excrescences +excrescencies +excrescency +excrescent +excrescently +excreta +excretal +excrete +excreted +excreter +excreters +excretes +excreting +excretion +excretions +excretory +excruciate +excruciated +excruciates +excruciating +excruciatingly +excruciation +excruciations +exculpable +exculpate +exculpated +exculpates +exculpating +exculpation +exculpations +exculpatory +excurrent +excursion +excursionist +excursionists +excursions +excursive +excursively +excursiveness +excursus +excursuses +excusable +excusableness +excusably +excusatory +excuse +excused +excuser +excusers +excuses +excusing +exec +execrable +execrableness +execrably +execrate +execrated +execrates +execrating +execration +execrations +execrative +execrator +execrators +execratory +execs +executable +executables +executant +executants +execute +executed +executer +executers +executes +executing +execution +executioner +executioners +executions +executive +executives +executor +executorial +executors +executorship +executorships +executory +executrices +executrix +executrixes +exedra +exedrae +exedras +exegeses +exegesis +exegete +exegetes +exegetic +exegetical +exegetically +exegetist +exegetists +exempla +exemplar +exemplarily +exemplariness +exemplarity +exemplars +exemplary +exempli +exemplifiable +exemplification +exemplifications +exemplified +exemplifier +exemplifiers +exemplifies +exemplify +exemplifying +exemplum +exempt +exempted +exemptible +exempting +exemption +exemptions +exempts +exenterate +exenterated +exenterates +exenterating +exenteration +exenterations +exercisable +exercise +exercised +exerciser +exercisers +exercises +exercising +exercitation +exercitations +exercycle +exergonic +exergue +exergues +exert +exerted +exerting +exertion +exertions +exerts +exes +exeter +exeunt +exfoliate +exfoliated +exfoliates +exfoliating +exfoliation +exfoliations +exfoliative +exfoliator +exfoliators +exhalant +exhalants +exhalation +exhalations +exhale +exhaled +exhalent +exhalents +exhales +exhaling +exhaust +exhausted +exhaustedly +exhauster +exhausters +exhaustibility +exhaustible +exhausting +exhaustingly +exhaustion +exhaustive +exhaustively +exhaustiveness +exhaustivity +exhaustless +exhaustlessly +exhaustlessness +exhausts +exhibit +exhibited +exhibiter +exhibiters +exhibiting +exhibition +exhibitioner +exhibitioners +exhibitionism +exhibitionist +exhibitionistic +exhibitionists +exhibitions +exhibitive +exhibitively +exhibitor +exhibitors +exhibitory +exhibits +exhilarant +exhilarants +exhilarate +exhilarated +exhilarates +exhilarating +exhilaratingly +exhilaration +exhilarative +exhilarator +exhilarators +exhort +exhortation +exhortations +exhortative +exhortatory +exhorted +exhorter +exhorters +exhorting +exhorts +exhumation +exhumations +exhume +exhumed +exhumer +exhumers +exhumes +exhuming +exigence +exigences +exigencies +exigency +exigent +exigently +exiguities +exiguity +exiguous +exiguously +exiguousness +exile +exiled +exiles +exilian +exilic +exiling +eximious +exine +exines +exist +existed +existence +existences +existent +existential +existentialism +existentialist +existentialistic +existentialistically +existentialists +existentially +existents +existing +exists +exit +exited +exiting +exits +exobiological +exobiologist +exobiologists +exobiology +exocarp +exocarps +exocet +exocets +exocrine +exocyclic +exocytose +exocytosed +exocytoses +exocytosing +exocytosis +exocytotic +exodermis +exodontia +exodontias +exodontics +exodontist +exodontists +exodus +exoduses +exoenzyme +exoenzymes +exoergic +exogamic +exogamies +exogamous +exogamy +exogenous +exogenously +exon +exonerate +exonerated +exonerates +exonerating +exoneration +exonerations +exonerative +exonic +exons +exonuclease +exonucleases +exopeptidase +exopeptidases +exophthalmic +exophthalmos +exorbitance +exorbitances +exorbitant +exorbitantly +exorcise +exorcised +exorciser +exorcisers +exorcises +exorcising +exorcism +exorcisms +exorcist +exorcistic +exorcistical +exorcists +exorcize +exorcized +exorcizes +exorcizing +exordia +exordial +exordium +exordiums +exoskeletal +exoskeleton +exoskeletons +exosmosis +exosmotic +exosphere +exospheres +exospheric +exospore +exospores +exosporia +exosporium +exostoses +exostosis +exoteric +exoterically +exothermal +exothermally +exothermic +exothermically +exotic +exotica +exotically +exoticism +exoticisms +exoticness +exotics +exotism +exotisms +exotoxin +exotoxins +expand +expandable +expanded +expander +expanders +expanding +expandor +expandors +expands +expanse +expanses +expansibility +expansible +expansile +expansion +expansional +expansionary +expansionism +expansionist +expansionistic +expansionists +expansions +expansive +expansively +expansiveness +expansivity +expatiate +expatiated +expatiates +expatiating +expatiation +expatiations +expatiatory +expatriate +expatriated +expatriates +expatriating +expatriation +expatriations +expect +expectable +expectably +expectance +expectances +expectancies +expectancy +expectant +expectantly +expectants +expectation +expectational +expectations +expectative +expected +expectedly +expectedness +expecting +expectorant +expectorants +expectorate +expectorated +expectorates +expectorating +expectoration +expectorations +expectorator +expectorators +expects +expedience +expediences +expediencies +expediency +expedient +expediential +expedientially +expediently +expedients +expedite +expedited +expediter +expediters +expedites +expediting +expedition +expeditionary +expeditions +expeditious +expeditiously +expeditiousness +expeditor +expeditors +expel +expellable +expellant +expelled +expellee +expellees +expeller +expellers +expelling +expels +expend +expendability +expendable +expendables +expendably +expended +expender +expenders +expending +expenditure +expenditures +expends +expense +expensed +expenses +expensing +expensive +expensively +expensiveness +experience +experienced +experiencer +experiencers +experiences +experiencing +experiential +experientialism +experientially +experiment +experimental +experimentalism +experimentalist +experimentalists +experimentally +experimentation +experimentations +experimented +experimenter +experimenters +experimenting +experiments +expert +experted +experting +expertise +expertism +expertly +expertness +experts +expiable +expiate +expiated +expiates +expiating +expiation +expiations +expiator +expiators +expiatory +expiration +expirations +expiratory +expire +expired +expires +expiries +expiring +expiry +explain +explainable +explained +explainer +explainers +explaining +explains +explanation +explanations +explanative +explanatively +explanatorily +explanatory +explant +explantation +explantations +explanted +explanting +explants +expletive +expletives +expletory +explicable +explicably +explicate +explicated +explicates +explicating +explication +explications +explicative +explicatively +explicatives +explicator +explicators +explicatory +explicit +explicitly +explicitness +explode +exploded +exploder +exploders +explodes +exploding +exploit +exploitability +exploitable +exploitation +exploitations +exploitative +exploitatively +exploited +exploiter +exploiters +exploiting +exploitive +exploitively +exploits +exploration +explorational +explorations +explorative +exploratively +exploratory +explore +explored +explorer +explorers +explores +exploring +explosion +explosions +explosive +explosively +explosiveness +explosives +expo +exponent +exponential +exponentially +exponentiate +exponentiated +exponentiates +exponentiating +exponentiation +exponentiations +exponents +export +exportability +exportable +exportation +exportations +exported +exporter +exporters +exporting +exports +expos +expose +exposed +exposer +exposers +exposes +exposing +exposit +exposited +expositing +exposition +expositional +expositions +expositive +expositor +expositors +expository +exposits +expostulate +expostulated +expostulates +expostulating +expostulation +expostulations +expostulative +expostulator +expostulators +expostulatory +exposure +exposures +exposé +exposés +expound +expounded +expounder +expounders +expounding +expounds +express +expressage +expressed +expresser +expressers +expresses +expressible +expressing +expression +expressional +expressionism +expressionist +expressionistic +expressionistically +expressionists +expressionless +expressionlessly +expressionlessness +expressions +expressive +expressively +expressiveness +expressivities +expressivity +expressly +expressway +expressways +expropriate +expropriated +expropriates +expropriating +expropriation +expropriations +expropriator +expropriators +expropriatory +expulse +expulsed +expulses +expulsing +expulsion +expulsions +expulsive +expunction +expunctions +expunge +expunged +expunger +expungers +expunges +expunging +expurgate +expurgated +expurgates +expurgating +expurgation +expurgations +expurgator +expurgatorial +expurgators +expurgatory +exquisite +exquisitely +exquisiteness +exsanguinate +exsanguinated +exsanguinates +exsanguinating +exsanguination +exsanguinations +exsanguine +exscind +exscinded +exscinding +exscinds +exsert +exserted +exsertile +exserting +exsertion +exsertions +exserts +exsiccate +exsiccated +exsiccates +exsiccating +exsiccation +exsiccations +exsiccative +exsiccator +exsiccators +exstipulate +extant +extemporal +extemporally +extemporaneity +extemporaneous +extemporaneously +extemporaneousness +extemporarily +extemporary +extempore +extemporization +extemporizations +extemporize +extemporized +extemporizer +extemporizers +extemporizes +extemporizing +extend +extendability +extendable +extended +extendedly +extendedness +extender +extenders +extendibility +extendible +extending +extends +extensibility +extensible +extensile +extension +extensional +extensionality +extensionally +extensions +extensities +extensity +extensive +extensively +extensiveness +extenso +extensometer +extensometers +extensor +extensors +extent +extents +extenuate +extenuated +extenuates +extenuating +extenuatingly +extenuation +extenuations +extenuative +extenuatives +extenuator +extenuators +extenuatory +exterior +exteriority +exteriorization +exteriorizations +exteriorize +exteriorized +exteriorizes +exteriorizing +exteriorly +exteriors +exterminate +exterminated +exterminates +exterminating +extermination +exterminations +exterminative +exterminator +exterminators +exterminatory +extermine +extermined +extermines +extermining +extern +external +externalism +externalisms +externalist +externalists +externalities +externality +externalization +externalizations +externalize +externalized +externalizes +externalizing +externally +externals +externe +externes +externs +externship +externships +exteroceptive +exteroceptor +exteroceptors +exterritorial +exterritoriality +exterritorially +extinct +extinction +extinctions +extinctive +extinguish +extinguishable +extinguished +extinguisher +extinguishers +extinguishes +extinguishing +extinguishment +extinguishments +extirpate +extirpated +extirpates +extirpating +extirpation +extirpations +extirpative +extirpator +extirpators +extol +extolled +extoller +extollers +extolling +extolment +extols +extort +extorted +extorter +extorters +extorting +extortion +extortionary +extortionate +extortionately +extortioner +extortioners +extortionist +extortionists +extortions +extortive +extorts +extra +extracellular +extracellularly +extrachromosomal +extracode +extracodes +extraconstitutional +extracorporeal +extracorporeally +extracranial +extract +extractability +extractable +extracted +extractible +extracting +extraction +extractions +extractive +extractively +extractives +extractor +extractors +extracts +extracurricular +extraditable +extradite +extradited +extradites +extraditing +extradition +extraditions +extrados +extradoses +extragalactic +extrahepatic +extrajudicial +extrajudicially +extralegal +extralegally +extralimital +extralinguistic +extralinguistically +extralities +extrality +extramarital +extramundane +extramural +extramurally +extramusical +extraneous +extraneously +extraneousness +extranuclear +extraocular +extraordinaire +extraordinarily +extraordinariness +extraordinary +extrapolate +extrapolated +extrapolates +extrapolating +extrapolation +extrapolations +extrapolative +extrapolator +extrapolators +extrapyramidal +extras +extrasensory +extrasolar +extrasystole +extrasystoles +extraterrestrial +extraterrestrials +extraterritorial +extraterritorialities +extraterritoriality +extraterritorially +extrauterine +extravagance +extravagances +extravagancies +extravagancy +extravagant +extravagantly +extravagantness +extravaganza +extravaganzas +extravagate +extravagated +extravagates +extravagating +extravagation +extravagations +extravasate +extravasated +extravasates +extravasating +extravasation +extravasations +extravascular +extravehicular +extraversion +extravert +extraverted +extraverting +extraverts +extrema +extreme +extremely +extremeness +extremes +extremis +extremism +extremist +extremists +extremities +extremity +extremum +extricable +extricate +extricated +extricates +extricating +extrication +extrications +extrinsic +extrinsically +extrorse +extroversion +extroversive +extroversively +extrovert +extroverted +extroverts +extrudability +extrudable +extrude +extruded +extruder +extruders +extrudes +extruding +extrusion +extrusions +extrusive +exuberance +exuberant +exuberantly +exuberate +exuberated +exuberates +exuberating +exudate +exudates +exudation +exudations +exudative +exude +exuded +exudes +exuding +exult +exultance +exultancy +exultant +exultantly +exultation +exulted +exulting +exultingly +exults +exurb +exurban +exurbanite +exurbanites +exurbia +exurbias +exurbs +exuviae +exuvial +exuviate +exuviated +exuviates +exuviating +exuviation +exuviations +exxon +eyas +eyases +eye +eyeball +eyeballed +eyeballing +eyeballs +eyebolt +eyebolts +eyebright +eyebrights +eyebrow +eyebrows +eyecup +eyecups +eyed +eyedness +eyednesses +eyedropper +eyedropperful +eyedroppers +eyeful +eyefuls +eyeglass +eyeglasses +eyehole +eyeholes +eyehook +eyehooks +eyeing +eyelash +eyelashes +eyeless +eyelet +eyelets +eyelid +eyelids +eyelift +eyelifts +eyelike +eyeliner +eyeliners +eyepiece +eyepieces +eyepopper +eyepoppers +eyepopping +eyer +eyers +eyes +eyeshade +eyeshades +eyeshot +eyeshots +eyesight +eyesights +eyesore +eyesores +eyespot +eyespots +eyestalk +eyestalks +eyestrain +eyestrings +eyeteeth +eyetooth +eyewash +eyewashes +eyewear +eyewink +eyewinks +eyewitness +eyewitnesses +eying +eyra +eyras +eyre +eyres +eyrir +ezekias +ezekiel +ezra +f +fa +fab +fabergé +fabian +fabianism +fabianist +fabianists +fabians +fabius +fable +fabled +fabler +fablers +fables +fabliau +fabliaux +fabling +fabre +fabric +fabricability +fabricable +fabricant +fabricants +fabricate +fabricated +fabricates +fabricating +fabrication +fabrications +fabricator +fabricators +fabrics +fabular +fabulate +fabulated +fabulates +fabulating +fabulation +fabulations +fabulator +fabulators +fabulist +fabulists +fabulous +fabulously +fabulousness +facade +facades +face +faceable +facecloth +facecloths +faced +facedown +facedowns +faceless +facelessness +facelift +facelifts +facemask +facemasks +faceplate +faceplates +facer +facers +faces +facet +facete +faceted +facetiae +facetious +facetiously +facetiousness +facets +facetted +faceup +facia +facial +facially +facials +facias +facie +facies +facile +facilely +facileness +facilitate +facilitated +facilitates +facilitating +facilitation +facilitative +facilitator +facilitators +facilitatory +facilities +facility +facing +facings +facsimile +facsimiles +fact +facticity +faction +factional +factionalism +factionalize +factionalized +factionalizes +factionalizing +factionally +factions +factious +factiously +factiousness +factitious +factitiously +factitiousness +factitive +factitively +facto +factoid +factoidal +factoids +factor +factorability +factorable +factorage +factorages +factored +factorial +factorials +factories +factoring +factorings +factorization +factorizations +factorize +factorized +factorizes +factorizing +factors +factorship +factory +factotum +factotums +facts +factual +factualism +factualist +factualists +factuality +factually +factualness +facture +factures +facula +faculae +facultative +facultatively +faculties +faculty +fad +faddish +faddishly +faddishness +faddism +faddisms +faddist +faddists +faddy +fade +fadeaway +fadeaways +faded +fadeless +fadelessly +fadeout +fadeouts +fader +faders +fades +fading +fadings +fado +fados +fads +faecal +faeces +faena +faenas +faerie +faeries +faeroe +faeroes +faeroese +faery +fafnir +fag +fagged +fagging +faggot +faggoted +faggoting +faggots +fagin +fagins +fagot +fagoted +fagoting +fagotings +fagots +fags +fahrenheit +faience +faiences +fail +failed +failing +failingly +failings +faille +failles +fails +failsafe +failure +failures +fain +faint +fainted +fainter +fainters +faintest +fainthearted +faintheartedly +faintheartedness +fainting +faintish +faintishness +faintly +faintness +faints +fainéant +fainéants +fair +fairbanks +faire +faired +fairer +fairest +fairfax +fairgoer +fairgoers +fairground +fairgrounds +fairhaven +fairies +fairing +fairings +fairish +fairishly +fairlead +fairleader +fairleaders +fairleads +fairly +fairness +fairs +fairwater +fairwaters +fairway +fairways +fairy +fairyism +fairyisms +fairyland +fairylands +fairylike +fairytale +fairytales +faisalabad +fait +faith +faithful +faithfully +faithfulness +faithfuls +faithless +faithlessly +faithlessness +faiths +faitour +faitours +faits +fajita +fajitas +fake +faked +faker +fakeries +fakers +fakery +fakes +faking +fakir +fakirs +falafel +falange +falangism +falangist +falangists +falasha +falashas +falcate +falcated +falces +falchion +falchions +falciform +falciparum +falcon +falconer +falconers +falconet +falconets +falconoid +falconry +falcons +falderal +falderals +faldstool +faldstools +faliscan +faliscans +falkland +falklands +fall +fallacies +fallacious +fallaciously +fallaciousness +fallacy +fallal +fallalery +fallals +fallback +fallbacks +fallboard +fallboards +fallen +faller +fallers +fallfish +fallfishes +fallibility +fallible +fallibleness +fallibly +falling +fallings +falloff +falloffs +fallopian +fallout +fallouts +fallow +fallowed +fallowing +fallowness +fallows +falls +falmouth +false +falsehood +falsehoods +falsely +falseness +falser +falsest +falsetto +falsettos +falsie +falsies +falsifiability +falsifiable +falsification +falsifications +falsified +falsifier +falsifiers +falsifies +falsify +falsifying +falsities +falsity +falstaff +falstaffian +falster +faltboat +faltboats +falter +faltered +falterer +falterers +faltering +falteringly +falters +falx +famagusta +fame +famed +fames +familial +familiar +familiarities +familiarity +familiarization +familiarizations +familiarize +familiarized +familiarizer +familiarizers +familiarizes +familiarizing +familiarly +familiarness +familiars +families +familism +familistic +famille +family +famine +famines +faming +famish +famished +famishes +famishing +famishment +famishments +famous +famously +famousness +famuli +famulus +fan +fanac +fanacs +fanatic +fanatical +fanatically +fanaticalness +fanaticism +fanaticize +fanaticized +fanaticizes +fanaticizing +fanatics +fancied +fancier +fanciers +fancies +fanciest +fanciful +fancifully +fancifulness +fancily +fanciness +fancy +fancying +fancywork +fandangle +fandangles +fandango +fandangos +fandom +fandoms +fane +fanes +fanfare +fanfares +fanfaronade +fanfaronades +fanfold +fanfolds +fang +fanged +fangs +fanion +fanions +fanjet +fanjets +fanlight +fanlights +fanlike +fanned +fanner +fanners +fannies +fanning +fanny +fanout +fans +fantabulous +fantail +fantailed +fantails +fantasia +fantasias +fantasie +fantasied +fantasies +fantasist +fantasists +fantasize +fantasized +fantasizer +fantasizes +fantasizing +fantasm +fantasms +fantast +fantastic +fantastical +fantasticality +fantastically +fantasticalness +fantasticate +fantasticated +fantasticates +fantasticating +fantastication +fantastications +fantastico +fantasticoes +fantasts +fantasy +fantasying +fantasyland +fantasylands +fante +fanti +fantoccini +fantod +fantods +fantom +fantoms +fanwise +fanwort +fanworts +fanzine +fanzines +far +farad +faradaic +faraday +faradays +faradic +faradism +faradisms +faradization +faradizations +faradize +faradized +faradizes +faradizing +farads +farandole +farandoles +faraway +farce +farced +farces +farceur +farceurs +farci +farcical +farcicality +farcically +farcicalness +farcie +farcing +farcy +fard +farded +fardel +fardels +farding +fards +fare +farebeat +farebeaten +farebeater +farebeaters +farebeating +farebeats +fared +farer +farers +fares +farewell +farewelled +farewelling +farewells +farfal +farfals +farfel +farfels +farfetched +farfetchedness +faridabad +farina +farinaceous +farinas +faring +farinha +farinhas +farinose +farkleberries +farkleberry +farl +farls +farm +farmability +farmable +farmed +farmer +farmers +farmhand +farmhands +farmhouse +farmhouses +farming +farmington +farmland +farmlands +farms +farmstead +farmsteads +farmwoman +farmwomen +farmworker +farmworkers +farmyard +farmyards +farnese +faro +faroe +faroes +faroese +farolito +farolitos +faros +farouche +farraginous +farrago +farragoes +farrier +farrieries +farriers +farriery +farrow +farrowed +farrowing +farrows +farseeing +farsi +farsighted +farsightedly +farsightedness +farsistan +fart +farted +farther +farthermost +farthest +farthing +farthingale +farthingales +farthings +farting +farts +fasces +fascia +fasciae +fascial +fascias +fasciate +fasciated +fasciation +fasciations +fascicle +fascicled +fascicles +fascicular +fascicularly +fasciculate +fasciculated +fasciculately +fasciculation +fasciculations +fascicule +fascicules +fasciculi +fasciculus +fascinate +fascinated +fascinates +fascinating +fascinatingly +fascination +fascinations +fascinator +fascinators +fascine +fascines +fascioliases +fascioliasis +fascism +fascist +fascisti +fascistic +fascistically +fascists +fash +fashed +fashes +fashing +fashion +fashionability +fashionable +fashionableness +fashionables +fashionably +fashioned +fashioner +fashioners +fashioning +fashionmonger +fashionmongers +fashions +fast +fastback +fastbacks +fastball +fastballs +fasted +fasten +fastened +fastener +fasteners +fastening +fastenings +fastens +faster +fastest +fastidious +fastidiously +fastidiousness +fastigiate +fastigiated +fastigiately +fastigium +fastigiums +fasting +fastness +fastnesses +fasts +fastuous +fat +fata +fatal +fatale +fatales +fatalism +fatalist +fatalistic +fatalistically +fatalists +fatalities +fatality +fatally +fatback +fate +fated +fateful +fatefully +fatefulness +fates +fathead +fatheaded +fatheadedly +fatheadedness +fatheads +father +fathered +fatherhood +fathering +fatherland +fatherlands +fatherless +fatherlessness +fatherlike +fatherliness +fatherly +fathers +fathom +fathomable +fathomed +fathometer +fathoming +fathomless +fathomlessly +fathomlessness +fathoms +fatidic +fatidical +fatigabilities +fatigability +fatigable +fatigue +fatigued +fatigues +fatiguing +fatiguingly +fatima +fatimid +fatimids +fatimite +fatimites +fating +fatless +fatling +fatlings +fatly +fatness +fats +fatso +fatsoes +fatstock +fatted +fatten +fattened +fattener +fatteners +fattening +fattens +fatter +fattest +fattier +fatties +fattiest +fattily +fattiness +fatting +fattish +fattishness +fatty +fatuities +fatuity +fatuous +fatuously +fatuousness +fatuus +fatwood +fatwoods +faubourg +faubourgs +faucal +fauces +faucet +faucets +faucial +faugh +faulkner +faulknerian +fault +faulted +faultfinder +faultfinders +faultfinding +faultfindings +faultier +faultiest +faultily +faultiness +faulting +faultless +faultlessly +faultlessness +faults +faulty +faun +fauna +faunae +faunal +faunally +faunas +faunistic +faunistically +fauns +faunus +faust +faustian +faustus +faut +faute +fauteuil +fauteuils +fauve +fauves +fauvism +fauvist +fauvists +faux +favela +favelas +faveolate +favonian +favor +favorable +favorableness +favorably +favored +favoredness +favorer +favorers +favoring +favoringly +favorite +favorites +favoritism +favors +favus +favuses +fawkes +fawn +fawned +fawner +fawners +fawning +fawningly +fawns +fawny +fax +faxed +faxes +faxing +fay +fayalite +fayalites +fayed +fayetteville +faying +fays +faze +fazed +fazes +fazing +façade +façades +façadism +faïence +faïences +fealties +fealty +fear +feared +fearer +fearers +fearful +fearfully +fearfulness +fearing +fearless +fearlessly +fearlessness +fears +fearsome +fearsomely +fearsomeness +feasibility +feasible +feasiblefeasters +feasibleness +feasibly +feast +feasted +feaster +feasters +feasting +feasts +feat +feater +featest +feather +featherbed +featherbedded +featherbedding +featherbeddings +featherbeds +featherbone +featherbones +featherbrain +featherbrained +featherbrains +feathered +featheredge +featheredged +featheredges +featherhead +featherheaded +featherheads +featheriness +feathering +featherings +featherless +feathers +featherstitch +featherstitched +featherstitches +featherstitching +featherweight +featherweights +feathery +featly +feats +feature +featured +featureless +features +featuring +feaze +feazed +feazes +feazing +febricity +febrifacient +febrifacients +febrific +febrifuge +febrifuges +febrile +februaries +february +februarys +fecal +feces +feckless +fecklessly +fecklessness +feckly +feculence +feculent +fecund +fecundate +fecundated +fecundates +fecundating +fecundation +fecundations +fecundity +fed +fedayee +fedayeen +federacies +federacy +federal +federalism +federalist +federalists +federalization +federalizations +federalize +federalized +federalizes +federalizing +federally +federate +federated +federates +federating +federation +federations +federative +federatively +fedora +fedoras +feds +fee +feeble +feebleminded +feeblemindedly +feeblemindedness +feebleness +feebler +feeblest +feeblish +feebly +feed +feedback +feedbag +feedbags +feedbox +feedboxes +feeder +feeders +feedhole +feedholes +feeding +feedings +feedlot +feedlots +feeds +feedstock +feedstuff +feedthrough +feedthroughs +feeing +feel +feeler +feelers +feeling +feelingly +feelingness +feelings +feels +fees +feet +feetfirst +feeze +feezes +fehling +feign +feigned +feigner +feigners +feigning +feigns +feijoada +feint +feinted +feinting +feints +feirie +feist +feistier +feistiest +feistiness +feists +feisty +felafel +feldspar +feldspars +feldspathic +felicific +felicitate +felicitated +felicitates +felicitating +felicitation +felicitations +felicitator +felicitators +felicities +felicitous +felicitously +felicitousness +felicity +felid +felids +feline +felinely +felineness +felines +felinities +felinity +felix +fell +fellable +fellah +fellaheen +fellahin +fellate +fellated +fellates +fellating +fellatio +fellation +fellations +fellatios +fellator +fellators +felled +feller +fellers +fellies +felling +fellness +felloe +felloes +fellow +fellowly +fellowman +fellowmen +fellows +fellowship +fellowships +fells +felly +felon +felones +felonies +felonious +feloniously +feloniousness +felonries +felonry +felons +felony +felsic +felsite +felsites +felsitic +felspar +felspars +felt +felted +felting +feltings +felts +felty +felucca +feluccas +felwort +felworts +female +femaleness +females +feme +femes +feminine +femininely +feminineness +feminines +femininities +femininity +feminism +feminist +feministic +feminists +feminity +feminization +feminizations +feminize +feminized +feminizes +feminizing +femme +femmes +femora +femoral +femtoampere +femtoamperes +femtobecquerel +femtobecquerels +femtocandela +femtocandelas +femtocoulomb +femtocoulombs +femtofarad +femtofarads +femtogram +femtograms +femtohenries +femtohenry +femtohenrys +femtohertz +femtojoule +femtojoules +femtokelvin +femtokelvins +femtolumen +femtolumens +femtolux +femtometer +femtometers +femtomole +femtomoles +femtonewton +femtonewtons +femtoohm +femtoohms +femtopascal +femtopascals +femtoradian +femtoradians +femtosecond +femtoseconds +femtosiemens +femtosievert +femtosieverts +femtosteradian +femtosteradians +femtotesla +femtoteslas +femtovolt +femtovolts +femtowatt +femtowatts +femtoweber +femtowebers +femur +femurs +fen +fence +fenced +fenceless +fencelessness +fencer +fencerow +fencerows +fencers +fences +fencing +fend +fended +fender +fenders +fending +fends +fenestra +fenestrae +fenestral +fenestrate +fenestrated +fenestration +fenestrations +fenfluramine +feng +fenian +fenianism +fenians +fennec +fennecs +fennel +fenny +fens +fentanyl +fentanyls +fenugreek +fenuron +fenurons +feoffee +feoffees +feoffer +feoffers +feoffment +feoffments +feoffor +feoffors +fer +feral +ferbam +ferbams +ferdinand +fere +feres +feretories +feretory +feria +feriae +ferial +ferias +ferine +ferity +fermanagh +fermat +fermata +fermatas +ferment +fermentability +fermentable +fermentation +fermentations +fermentative +fermented +fermenter +fermenters +fermenting +ferments +fermi +fermion +fermions +fermis +fermium +fern +ferneries +fernery +fernier +ferniest +fernlike +ferns +ferny +ferocious +ferociously +ferociousness +ferocity +ferrara +ferrate +ferrates +ferredoxin +ferredoxins +ferret +ferreted +ferreter +ferreters +ferreting +ferretings +ferrets +ferrety +ferriage +ferriages +ferric +ferricyanide +ferricyanides +ferried +ferries +ferriferous +ferris +ferrite +ferrites +ferritic +ferritin +ferritins +ferroalloy +ferroalloys +ferroconcrete +ferrocyanide +ferrocyanides +ferroelectric +ferroelectricity +ferroelectrics +ferromagnesian +ferromagnet +ferromagnetic +ferromagnetism +ferromagnets +ferromanganese +ferrosilicon +ferrosilicons +ferrotype +ferrotypes +ferrous +ferruginous +ferrule +ferruled +ferrules +ferruling +ferry +ferryboat +ferryboats +ferrying +ferryman +ferrymen +fertile +fertilely +fertileness +fertilities +fertility +fertilizable +fertilization +fertilizational +fertilizations +fertilize +fertilized +fertilizer +fertilizers +fertilizes +fertilizing +ferula +ferulas +ferule +feruled +ferules +ferulic +feruling +fervencies +fervency +fervent +fervently +ferventness +fervid +fervidity +fervidly +fervidness +fervor +fervors +fescennine +fescue +fescues +fess +fesse +fessed +fesses +fessing +fest +festal +festally +fester +festered +festering +festers +festinate +festinated +festinately +festinates +festinating +festival +festivalgoer +festivalgoers +festivals +festive +festively +festiveness +festivities +festivity +festoon +festooned +festooneries +festoonery +festooning +festoons +fests +festschrift +festschriften +festschrifts +feta +fetal +fetch +fetched +fetcher +fetchers +fetches +fetching +fetchingly +fete +feted +feterita +feteritas +fetes +fetich +fetiches +fetichism +feticidal +feticide +feticides +fetid +fetidly +fetidness +feting +fetish +fetishes +fetishism +fetishist +fetishistic +fetishistically +fetishists +fetishize +fetishized +fetishizes +fetishizing +fetlock +fetlocks +fetologist +fetologists +fetology +fetoprotein +fetoproteins +fetor +fetors +fetoscope +fetoscopes +fetoscopy +fetter +fetterbush +fetterbushes +fettered +fettering +fetters +fettle +fettled +fettles +fettling +fettlings +fettuccine +fetus +fetuses +feu +feud +feudal +feudalism +feudalist +feudalistic +feudalists +feudalities +feudality +feudalization +feudalizations +feudalize +feudalized +feudalizes +feudalizing +feudally +feudatories +feudatory +feuded +feuding +feudist +feudists +feuds +feuilleton +feuilletonism +feuilletonist +feuilletonistic +feuilletonists +feuilletons +fever +fevered +feverfew +feverfews +fevering +feverish +feverishly +feverishness +feverous +fevers +feverweed +feverweeds +feverwort +feverworts +few +fewer +fewest +fewness +fewtrils +fey +feyly +feyness +feynman +fez +fezzes +fiacre +fiacres +fiancee +fiancees +fianchetti +fianchetto +fianchettoed +fianchettoing +fianchettos +fiancé +fiancée +fiancées +fiancés +fiaschi +fiasco +fiascoes +fiascos +fiat +fiats +fib +fibbed +fibber +fibbers +fibbing +fiber +fiberboard +fibered +fiberfill +fiberglass +fiberization +fiberizations +fiberize +fiberized +fiberizes +fiberizing +fibers +fiberscope +fiberscopes +fibonacci +fibranne +fibrannes +fibril +fibrillar +fibrillary +fibrillate +fibrillated +fibrillates +fibrillating +fibrillation +fibrillations +fibrillose +fibrils +fibrin +fibrinogen +fibrinogenic +fibrinogenically +fibrinogenous +fibrinogens +fibrinoid +fibrinoids +fibrinolyses +fibrinolysin +fibrinolysins +fibrinolysis +fibrinolytic +fibrinous +fibroblast +fibroblastic +fibroblasts +fibrocartilage +fibrocartilages +fibrocystic +fibroid +fibroids +fibroin +fibroins +fibroma +fibromas +fibromata +fibromatous +fibronectin +fibroplasia +fibroplastic +fibroses +fibrosis +fibrositis +fibrositises +fibrotic +fibrous +fibrously +fibrousness +fibrovascular +fibs +fibula +fibulae +fibular +fibulas +fiche +fiches +fichtelgebirge +fichu +fichus +ficin +fickle +fickleness +fickler +ficklest +fickly +fico +ficoes +fictile +fiction +fictional +fictionality +fictionalization +fictionalizations +fictionalize +fictionalized +fictionalizes +fictionalizing +fictionally +fictioneer +fictioneering +fictioneers +fictionist +fictionists +fictionization +fictionizations +fictionize +fictionized +fictionizes +fictionizing +fictions +fictitious +fictitiously +fictitiousness +fictive +fictively +fictiveness +ficus +ficuses +fid +fiddle +fiddleback +fiddled +fiddlehead +fiddleheads +fiddler +fiddlers +fiddles +fiddlestick +fiddlesticks +fiddling +fide +fideism +fideist +fideistic +fideists +fidelis +fidelities +fidelity +fides +fidge +fidged +fidges +fidget +fidgeted +fidgetiness +fidgeting +fidgets +fidgety +fidging +fido +fidos +fids +fiducial +fiducially +fiduciaries +fiduciary +fidus +fie +fief +fiefdom +fiefdoms +fiefs +field +fielded +fielder +fielders +fieldfare +fieldfares +fielding +fieldpiece +fieldpieces +fields +fieldsman +fieldsmen +fieldstone +fieldstrip +fieldstripped +fieldstripping +fieldstrips +fieldwork +fieldworker +fieldworkers +fiend +fiendish +fiendishly +fiendishness +fiends +fierce +fiercely +fierceness +fiercer +fiercest +fierier +fieriest +fierily +fieriness +fiery +fiesole +fiesta +fiestas +fife +fifer +fifers +fifes +fifo +fifteen +fifteenfold +fifteens +fifteenth +fifteenths +fifth +fifthly +fifths +fifties +fiftieth +fiftieths +fifty +fiftyfold +fiftyish +fig +figaro +fight +fightability +fightable +fighter +fighters +fighting +fightingly +fights +figment +figments +figs +figural +figurant +figurants +figuration +figurations +figurative +figuratively +figurativeness +figure +figured +figurehead +figureheads +figurer +figurers +figures +figurine +figurines +figuring +figwort +figworts +fiji +fijian +fijians +fila +filament +filamentary +filamentous +filaments +filar +filaree +filarees +filaria +filariae +filarial +filarian +filariases +filariasis +filariid +filariids +filature +filatures +filbert +filberts +filch +filched +filcher +filchers +filches +filching +filchner +file +filed +filefish +filefishes +filename +filenames +filer +filers +files +filet +filets +filial +filially +filiate +filiated +filiates +filiating +filiation +filiations +filibuster +filibustered +filibusterer +filibusterers +filibustering +filibusters +filiform +filigree +filigreed +filigreeing +filigrees +filing +filings +filiopietistic +filipina +filipinas +filipino +filipinos +filippo +fill +fille +filled +filler +fillers +fillet +filleted +filleting +fillets +fillies +filling +fillings +fillip +filliped +filliping +fillips +fills +filly +fillér +fillérs +film +filmcard +filmcards +filmdom +filmed +filmgoer +filmgoers +filmgoing +filmic +filmically +filmier +filmiest +filmily +filminess +filming +filmland +filmmaker +filmmakers +filmmaking +filmographer +filmographers +filmographies +filmography +films +filmset +filmsets +filmsetter +filmsetters +filmsetting +filmsettings +filmstrip +filmstrips +filmy +filoplume +filoplumes +filose +filovirus +filoviruses +fils +filter +filterability +filterable +filtered +filterer +filterers +filtering +filterless +filters +filth +filthier +filthiest +filthily +filthiness +filthy +filtrable +filtrate +filtrated +filtrates +filtrating +filtration +filtrations +filum +filé +fimbria +fimbriae +fimbrial +fimbriate +fimbriated +fimbriation +fimbriations +fin +finable +finagle +finagled +finagler +finaglers +finagles +finagling +final +finale +finales +finalist +finalists +finalities +finality +finalization +finalizations +finalize +finalized +finalizer +finalizers +finalizes +finalizing +finally +finals +finance +financeable +financed +finances +financial +financially +financials +financier +financiers +financing +finback +finbacks +finca +fincas +finch +finches +find +findable +finder +finders +finding +findings +finds +fine +fineable +fined +finely +fineness +finer +fineries +finery +fines +finespun +finesse +finessed +finesses +finessing +finest +finfish +finfishes +fingal +finger +fingerboard +fingerboards +fingerbreadth +fingerbreadths +fingered +fingerer +fingerers +fingering +fingerings +fingerless +fingerlike +fingerling +fingerlings +fingernail +fingernails +fingerpick +fingerpicked +fingerpicker +fingerpickers +fingerpicking +fingerpicks +fingerpost +fingerposts +fingerprint +fingerprinted +fingerprinting +fingerprints +fingers +fingerspell +fingerspelled +fingerspelling +fingerspells +fingertip +fingertips +finial +finials +finical +finically +finicalness +finickier +finickiest +finickiness +finicking +finicky +fining +finis +finish +finished +finisher +finishers +finishes +finishing +finisterre +finite +finitely +finiteness +finites +finitude +finitudes +fink +finked +finking +finks +finland +finlander +finlanders +finlandization +finlandize +finlandized +finlandizes +finlandizing +finlike +finn +finnan +finnbogadóttir +finned +finnic +finnier +finniest +finning +finnish +finns +finny +finocchio +finochio +finochios +fins +finsteraarhorn +fiord +fiords +fipple +fipples +fir +firdausi +firdusi +fire +fireable +firearm +firearms +fireball +fireballs +firebase +firebases +firebird +firebirds +fireboard +fireboards +fireboat +fireboats +firebomb +firebombed +firebomber +firebombers +firebombing +firebombs +firebox +fireboxes +firebrand +firebrands +firebrat +firebrats +firebreak +firebreaks +firebrick +firebricks +firebug +firebugs +fireclay +fireclays +firecracker +firecrackers +fired +firedamp +firedog +firedogs +firedrake +firedrakes +firefighter +firefighters +firefighting +firefights +fireflies +fireflood +fireflooding +firefloodings +firefloods +firefly +fireguard +fireguards +firehouse +firehouses +fireless +firelight +firelock +firelocks +fireman +firemen +firenze +fireplace +fireplaces +fireplug +fireplugs +firepower +fireproof +fireproofed +fireproofing +fireproofs +firer +firers +fires +fireside +firesides +firestone +firestones +firestorm +firestorms +firetrap +firetraps +firewall +firewalled +firewalling +firewalls +firewater +fireweed +fireweeds +firewood +firework +fireworks +firing +firings +firkin +firkins +firm +firma +firmament +firmamental +firmaments +firmed +firmer +firmest +firming +firmly +firmness +firms +firmware +firn +firns +firozabad +firry +firs +first +firstborn +firstborns +firstfruits +firsthand +firstling +firstlings +firstly +firsts +firth +firths +fisc +fiscal +fiscally +fiscs +fish +fishability +fishable +fishbone +fishbones +fishbowl +fishbowls +fishcake +fishcakes +fished +fisher +fisheries +fisherman +fishermen +fishers +fishery +fishes +fisheye +fisheyes +fishgig +fishgigs +fishhook +fishhooks +fishier +fishiest +fishily +fishiness +fishing +fishings +fishless +fishlike +fishmeal +fishmonger +fishmongers +fishnet +fishnets +fishplate +fishplates +fishpond +fishponds +fishtail +fishtailed +fishtailing +fishtails +fishway +fishways +fishwife +fishwives +fishy +fissile +fissility +fission +fissionability +fissionable +fissional +fissioned +fissioning +fissions +fissipalmate +fissiparous +fissiparously +fissiparousness +fissiped +fissipeds +fissure +fissured +fissures +fissuring +fist +fisted +fistfight +fistfights +fistful +fistfuls +fistic +fisticuffer +fisticuffers +fisticuffs +fisting +fistnote +fistnotes +fists +fistula +fistulae +fistular +fistulas +fistulous +fit +fitch +fitches +fitchet +fitchets +fitchew +fitchews +fitful +fitfully +fitfulness +fitly +fitment +fitments +fitness +fits +fitted +fitter +fitters +fittest +fitting +fittingly +fittingness +fittings +fitzgerald +five +fivefold +fiver +fivers +fives +fix +fixable +fixate +fixated +fixates +fixating +fixation +fixations +fixative +fixatives +fixe +fixed +fixedly +fixedness +fixer +fixers +fixes +fixing +fixings +fixities +fixity +fixture +fixtures +fizz +fizzed +fizzes +fizzier +fizziest +fizzing +fizzle +fizzled +fizzles +fizzling +fizzy +fjeld +fjelds +fjord +fjords +flab +flabbergast +flabbergasted +flabbergasting +flabbergastingly +flabbergasts +flabbier +flabbiest +flabbily +flabbiness +flabby +flabella +flabellate +flabelliform +flabellum +flaccid +flaccidity +flaccidly +flaccidness +flack +flacked +flackery +flacking +flacks +flacon +flacons +flag +flagella +flagellant +flagellantism +flagellants +flagellar +flagellate +flagellated +flagellates +flagellating +flagellation +flagellations +flagellator +flagellators +flagelliform +flagellin +flagellins +flagellum +flagellums +flageolet +flageolets +flagged +flagger +flaggers +flagging +flaggingly +flagitious +flagitiously +flagitiousness +flagman +flagmen +flagon +flagons +flagpole +flagpoles +flagrance +flagrancy +flagrant +flagrante +flagrantly +flags +flagship +flagships +flagstaff +flagstaffs +flagstick +flagsticks +flagstone +flagstones +flail +flailed +flailing +flails +flair +flairs +flak +flake +flaked +flaker +flakers +flakes +flakey +flakier +flakiest +flakily +flakiness +flaking +flaky +flam +flambeau +flambeaus +flambeaux +flamboyance +flamboyancy +flamboyant +flamboyantly +flamboyants +flambé +flambéed +flambéing +flambés +flame +flamed +flamen +flamenco +flamencos +flamens +flameout +flameouts +flameproof +flameproofed +flameproofer +flameproofers +flameproofing +flameproofs +flamer +flamers +flames +flamethrower +flamethrowers +flamier +flamiest +flamines +flaming +flamingly +flamingo +flamingoes +flamingos +flaminian +flammability +flammable +flammables +flams +flamy +flan +flanders +flange +flanged +flanges +flanging +flank +flanked +flanken +flankens +flanker +flankerback +flankerbacks +flankers +flanking +flanks +flannel +flannelette +flannelettes +flannelly +flannels +flans +flap +flapdoodle +flapdoodles +flapjack +flapjacks +flappable +flapped +flapper +flappers +flapping +flappy +flaps +flare +flareback +flarebacks +flared +flares +flaring +flaringly +flash +flashback +flashbacks +flashboard +flashboards +flashbulb +flashbulbs +flashcube +flashcubes +flashed +flasher +flashers +flashes +flashflood +flashfloods +flashgun +flashguns +flashier +flashiest +flashily +flashiness +flashing +flashings +flashlamp +flashlamps +flashlight +flashlights +flashover +flashovers +flashpoint +flashpoints +flashtube +flashtubes +flashy +flask +flasks +flat +flatbed +flatbeds +flatboat +flatboats +flatbottom +flatbottomed +flatbread +flatbreads +flatcar +flatcars +flatfeet +flatfish +flatfishes +flatfoot +flatfooted +flatfooting +flatfoots +flathead +flatheads +flatiron +flatirons +flatland +flatlander +flatlanders +flatlands +flatlet +flatlets +flatling +flatlings +flatly +flatness +flats +flatted +flatten +flattened +flattener +flatteners +flattening +flattens +flatter +flattered +flatterer +flatterers +flatteries +flattering +flatteringly +flatters +flattery +flattest +flatting +flattish +flattop +flattops +flatulence +flatulencies +flatulency +flatulent +flatulently +flatus +flatware +flatways +flatwise +flatwork +flatworks +flatworm +flatworms +flaubert +flaunt +flaunted +flaunter +flaunters +flauntier +flauntiest +flauntily +flauntiness +flaunting +flauntingly +flaunts +flaunty +flauta +flautas +flautist +flautists +flavanone +flavanones +flavescent +flavian +flavin +flavine +flavines +flavins +flavius +flavone +flavones +flavonoid +flavonoids +flavonol +flavonols +flavoprotein +flavoproteins +flavor +flavored +flavorer +flavorers +flavorful +flavorfully +flavoring +flavorings +flavorist +flavorists +flavorless +flavorous +flavors +flavorsome +flavory +flaw +flawed +flawing +flawless +flawlessly +flawlessness +flaws +flawy +flax +flaxen +flaxes +flaxier +flaxiest +flaxseed +flaxseeds +flaxy +flay +flayed +flayer +flayers +flaying +flays +flea +fleabag +fleabags +fleabane +fleabanes +fleabite +fleabites +fleapit +fleapits +fleas +fleawort +fleaworts +fleck +flecked +flecking +flecks +flection +flectional +flections +fled +fledermaus +fledge +fledged +fledgeling +fledgelings +fledges +fledging +fledgling +fledglings +flee +fleece +fleeced +fleecer +fleecers +fleeces +fleech +fleeched +fleeches +fleeching +fleecier +fleeciest +fleecily +fleeciness +fleecing +fleecy +fleeing +fleer +fleered +fleering +fleeringly +fleers +flees +fleet +fleeted +fleeter +fleetest +fleeting +fleetingly +fleetingness +fleetly +fleetness +fleets +fleishig +fleming +flemings +flemish +flense +flensed +flenser +flensers +flenses +flensing +flesh +fleshed +fleshes +fleshier +fleshiest +fleshiness +fleshing +fleshless +fleshlier +fleshliest +fleshliness +fleshly +fleshment +fleshpot +fleshpots +fleshy +fletch +fletched +fletcher +fletchers +fletches +fletching +fletschhorn +fleur +fleurs +fleury +flew +flews +flex +flexagon +flexagons +flexed +flexes +flexibilities +flexibility +flexible +flexibleness +flexibly +flexile +flexing +flexion +flexions +flexitime +flexitimes +flexographer +flexographers +flexographic +flexographically +flexography +flexor +flexors +flextime +flexuosity +flexuous +flexuously +flexural +flexure +flexures +fley +fleyed +fleying +fleys +flibbertigibbet +flibbertigibbets +flibbertigibbety +flic +flick +flickable +flicked +flicker +flickered +flickering +flickeringly +flickerings +flickers +flickertail +flickertails +flickery +flicking +flicks +flics +flied +flier +fliers +flies +flight +flighted +flightier +flightiest +flightily +flightiness +flighting +flightless +flights +flightworthiness +flightworthy +flighty +flimflam +flimflammed +flimflammer +flimflammers +flimflammery +flimflamming +flimflams +flimsier +flimsies +flimsiest +flimsily +flimsiness +flimsy +flinch +flinched +flincher +flinchers +flinches +flinching +flinchingly +flinders +fling +flinger +flingers +flinging +flings +flint +flinthead +flintheads +flintier +flintiest +flintily +flintiness +flintlike +flintlock +flintlocks +flints +flinty +flip +flipbook +flipbooks +flippancies +flippancy +flippant +flippantly +flipped +flipper +flippers +flippest +flipping +flips +flirt +flirtation +flirtations +flirtatious +flirtatiously +flirtatiousness +flirted +flirter +flirters +flirting +flirts +flirty +flit +flitch +flitches +flits +flitted +flitter +flittered +flittering +flitters +flitting +flivver +flivvers +float +floatable +floatage +floatages +floatation +floated +floater +floaters +floating +floatplane +floatplanes +floats +floaty +floc +floccose +flocculate +flocculated +flocculates +flocculating +flocculation +flocculations +floccule +flocculence +flocculences +flocculent +flocculently +floccules +flocculi +flocculus +flock +flocked +flocking +flocks +flocs +floe +floes +flog +flogged +flogger +floggers +flogging +floggings +flogs +flood +flooded +flooder +flooders +floodgate +floodgates +flooding +floodlight +floodlighted +floodlighting +floodlights +floodlit +floodplain +floodplains +floods +floodtide +floodtides +floodwall +floodwalls +floodwater +floodwaters +floodway +floodways +flooey +floor +floorage +floorages +floorboard +floorboards +floored +floorer +floorers +flooring +floorings +floors +floorshow +floorshows +floorwalker +floorwalkers +floozie +floozies +floozy +flop +flophouse +flophouses +flopped +flopper +floppers +floppier +floppies +floppiest +floppily +floppiness +flopping +floppy +flops +flora +florae +floral +florally +floras +floreated +florence +florentine +florentines +flores +florescence +florescent +floret +florets +floriated +floriation +floriations +floribunda +floribundas +floricane +floricanes +floricultural +floriculturally +floriculture +floriculturist +floriculturists +florid +florida +floridan +floridans +floridean +floridian +floridians +floridity +floridly +floridness +floriferous +floriferously +floriferousness +florigen +florigenic +florigens +florilegia +florilegium +florin +florins +florist +floristic +floristically +floristics +floristry +florists +floruit +floruits +floss +flossed +flosser +flossers +flosses +flossier +flossiest +flossily +flossiness +flossing +flossy +flota +flotage +flotages +flotas +flotation +flotilla +flotillas +flotsam +flotta +flounce +flounced +flounces +flouncing +flouncings +flouncy +flounder +floundered +floundering +flounders +flour +floured +flouring +flourish +flourished +flourisher +flourishers +flourishes +flourishing +flourishingly +flours +floury +flout +flouted +flouter +flouters +flouting +floutingly +flouts +flow +flowage +flowages +flowchart +flowcharted +flowcharting +flowcharts +flowed +flower +flowerage +flowerages +flowerbed +flowerbeds +flowered +flowerer +flowerers +floweret +flowerets +flowerful +flowerier +floweriest +floweriness +flowering +flowerless +flowerlike +flowerpot +flowerpots +flowers +flowery +flowing +flowingly +flowmeter +flowmeters +flown +flows +flowstone +flowstones +flu +flub +flubbed +flubber +flubbers +flubbing +flubdub +flubdubs +flubs +fluctuant +fluctuate +fluctuated +fluctuates +fluctuating +fluctuation +fluctuational +fluctuations +flue +fluegelhorn +fluegelhorns +fluency +fluent +fluently +flueric +fluerics +flues +fluff +fluffed +fluffier +fluffiest +fluffily +fluffiness +fluffing +fluffs +fluffy +fluid +fluidal +fluidally +fluidextract +fluidextracts +fluidic +fluidics +fluidified +fluidifies +fluidify +fluidifying +fluidities +fluidity +fluidization +fluidizations +fluidize +fluidized +fluidizer +fluidizers +fluidizes +fluidizing +fluidly +fluidness +fluidram +fluidrams +fluids +fluke +flukes +flukey +flukier +flukiest +flukily +flukiness +fluky +flulike +flume +flumes +flummeries +flummery +flummox +flummoxed +flummoxes +flummoxing +flump +flumped +flumping +flumps +flung +flunk +flunked +flunker +flunkers +flunkey +flunkeys +flunkies +flunking +flunkout +flunkouts +flunks +flunky +flunkyism +fluor +fluoresce +fluoresced +fluorescein +fluoresceins +fluorescence +fluorescent +fluorescents +fluorescer +fluorescers +fluoresces +fluorescing +fluoridate +fluoridated +fluoridates +fluoridating +fluoridation +fluoridations +fluoride +fluorides +fluorimeter +fluorimeters +fluorimetric +fluorimetry +fluorinate +fluorinated +fluorinates +fluorinating +fluorination +fluorinations +fluorine +fluorite +fluorites +fluorocarbon +fluorocarbons +fluorochemical +fluorochemicals +fluorochrome +fluorochromes +fluorography +fluorometer +fluorometers +fluorometry +fluoroscope +fluoroscoped +fluoroscopes +fluoroscopic +fluoroscopically +fluoroscopies +fluoroscoping +fluoroscopist +fluoroscopists +fluoroscopy +fluorosis +fluorotic +fluorouracil +fluorouracils +fluors +fluorspar +fluorspars +fluphenazine +fluphenazines +flurazepam +flurazepams +flurried +flurries +flurry +flurrying +flush +flushable +flushed +flusher +flushers +flushes +flushest +flushing +flushless +flushness +flushometer +flushometers +fluster +flustered +flustering +flusters +flute +fluted +flutelike +fluter +fluters +flutes +flutey +fluting +flutings +flutist +flutists +flutter +flutterboard +flutterboards +fluttered +flutterer +flutterers +fluttering +flutters +fluttery +fluty +fluvial +fluviatile +fluviomarine +flux +fluxed +fluxes +fluxing +fluxion +fluxional +fluxionally +fluxionary +fluxions +fly +flyable +flyaway +flyaways +flyblew +flyblow +flyblowing +flyblown +flyblows +flyboat +flyboats +flyboy +flyboys +flyby +flybys +flycatcher +flycatchers +flyer +flyers +flying +flyings +flyleaf +flyleaves +flyman +flymen +flyover +flyovers +flypaper +flypapers +flypast +flypasts +flysch +flysches +flysheet +flysheets +flyspeck +flyspecked +flyspecking +flyspecks +flyswatter +flyswatters +flytrap +flytraps +flyway +flyways +flyweight +flyweights +flywheel +flywheels +flywhisk +flywhisks +flânerie +flâneur +flâneurs +fléchette +flèche +flèches +flügelhorn +flügelhornist +flügelhornists +flügelhorns +fo +fo'c +fo'c'sle +fo'c'sles +foal +foaled +foaling +foals +foam +foamed +foamer +foamers +foamflower +foamflowers +foamier +foamiest +foamily +foaminess +foaming +foamless +foams +foamy +fob +fobbed +fobbing +fobs +focal +focalization +focalizations +focalize +focalized +focalizes +focalizing +focally +fochabers +foci +focus +focusable +focused +focuser +focusers +focuses +focusing +focusless +focussed +focusses +focussing +fodder +foddered +foddering +fodders +fodgel +foe +foehn +foehns +foeman +foemen +foes +foetal +foetid +foetidus +foetor +foetors +foetus +fog +fogbound +fogbow +fogbows +fogdog +fogdogs +fogey +fogeys +foggage +foggages +fogged +fogger +foggers +foggier +foggiest +foggily +fogginess +fogging +foggy +foghorn +foghorns +fogies +fogless +fogs +fogy +fogyish +fogyism +fogyisms +foible +foibles +foil +foiled +foiling +foils +foilsman +foilsmen +foin +foined +foining +foins +foison +foisons +foist +foisted +foisting +foists +fokker +folacin +folacins +folate +folates +fold +foldable +foldaway +foldaways +foldboat +foldboats +folded +folder +folderol +folderols +folders +folding +foldout +foldouts +folds +foldup +foldups +folia +foliaceous +foliage +foliaged +foliages +foliar +foliate +foliated +foliates +foliating +foliation +foliations +folic +folie +foliicolous +folio +folioed +folioing +folios +foliose +folium +folk +folkie +folkier +folkies +folkiest +folkish +folkishly +folkishness +folklike +folklore +folkloric +folklorish +folklorist +folkloristic +folkloristics +folklorists +folkmoot +folkmoots +folkmote +folkmotes +folks +folksier +folksiest +folksily +folksiness +folksinger +folksingers +folksinging +folksong +folksongs +folksy +folktale +folktales +folkway +folkways +folky +follicle +follicles +follicular +folliculate +folliculated +folliculitis +follies +follow +followed +follower +followers +followership +followerships +following +followings +follows +followup +followups +folly +folsom +fomalhaut +foment +fomentation +fomentations +fomented +fomenter +fomenters +fomenting +foments +fomite +fomites +fon +fond +fondant +fondants +fonder +fondest +fondle +fondled +fondler +fondlers +fondles +fondling +fondly +fondness +fondnesses +fonds +fondu +fondue +fondued +fondues +fonduing +fondus +fongafale +fons +fonseca +font +fontainebleau +fontal +fontanel +fontanelle +fontanelles +fontanels +fontenoy +fonteyn +fontina +fontinas +fonts +food +foodie +foodies +foodless +foodlessness +foods +foodservices +foodstuff +foodstuffs +foodways +foofaraw +foofaraws +fool +fooled +fooleries +foolery +foolhardier +foolhardiest +foolhardily +foolhardiness +foolhardy +fooling +foolings +foolish +foolishly +foolishness +foolproof +fools +foolscap +foolscaps +foon +foons +foot +footage +footages +football +footballer +footballers +footballs +footbath +footbaths +footboard +footboards +footboy +footboys +footbridge +footbridges +footcloth +footcloths +footed +footedly +footer +footers +footfall +footfalls +footgear +foothill +foothills +foothold +footholds +footing +footings +footle +footled +footler +footlers +footles +footless +footlessly +footlessness +footlight +footlights +footling +footlocker +footlockers +footlong +footloose +footman +footmark +footmarks +footmen +footnote +footnoted +footnotes +footnoting +footpace +footpaces +footpad +footpads +footpath +footpaths +footprint +footprinting +footprints +footrace +footraces +footracing +footrest +footrests +footrope +footropes +foots +footsie +footslog +footslogged +footslogger +footsloggers +footslogging +footslogs +footsore +footsoreness +footstalk +footstalks +footstall +footstalls +footstep +footsteps +footstone +footstones +footstool +footstools +footsy +footwall +footwalls +footway +footways +footwear +footwork +foozle +foozled +foozler +foozlers +foozles +foozling +fop +fopped +fopperies +foppery +fopping +foppish +foppishly +foppishness +fops +for +fora +forage +foraged +forager +foragers +forages +foraging +foraker +foram +foramen +foramens +foramina +foraminal +foraminifer +foraminifera +foraminiferal +foraminiferan +foraminiferous +foraminifers +foraminous +forams +forasmuch +foray +forayed +forayer +forayers +foraying +forays +forb +forbad +forbade +forbear +forbearance +forbearer +forbearers +forbearing +forbears +forbid +forbiddance +forbidden +forbidder +forbidders +forbidding +forbiddingly +forbiddingness +forbids +forbore +forborne +forbs +forby +forbye +force +forceable +forced +forcedly +forceful +forcefully +forcefulness +forceless +forcemeat +forceps +forcepslike +forcer +forcers +forces +forcible +forcibleness +forcibly +forcing +forcipate +forcipes +ford +fordable +forded +fordid +fording +fordo +fordoes +fordoing +fordone +fords +fore +forearm +forearmed +forearming +forearms +forebay +forebays +forebear +forebears +forebode +foreboded +foreboder +foreboders +forebodes +foreboding +forebodingly +forebodingness +forebodings +forebrain +forebrains +forecaddie +forecaddies +forecast +forecastable +forecasted +forecaster +forecasters +forecasting +forecastle +forecastles +forecasts +foreclosable +foreclose +foreclosed +forecloses +foreclosing +foreclosure +foreclosures +forecourt +forecourts +foredeck +foredecks +foredid +foredo +foredoes +foredoing +foredone +foredoom +foredoomed +foredooming +foredooms +foreface +forefaces +forefather +forefathers +forefeel +forefeeling +forefeels +forefeet +forefelt +forefend +forefended +forefending +forefends +forefinger +forefingers +forefoot +forefront +foregather +foregathered +foregathering +foregathers +forego +foregoer +foregoers +foregoes +foregoing +foregone +foreground +foregrounds +foregut +foreguts +forehand +forehanded +forehandedly +forehandedness +forehands +forehead +foreheads +forehoof +foreign +foreigner +foreigners +foreignism +foreignisms +foreignness +forejudge +forejudged +forejudges +forejudging +forejudgment +forejudgments +foreknew +foreknow +foreknowing +foreknowledge +foreknown +foreknows +foreladies +forelady +foreland +forelands +foreleg +forelegs +forelimb +forelimbs +forelock +forelocks +foreman +foremanship +foremast +foremasts +foremen +foremilk +foremost +foremother +foremothers +forename +forenamed +forenames +forenoon +forenoons +forensic +forensically +forensics +foreordain +foreordained +foreordaining +foreordainment +foreordainments +foreordains +foreordination +foreordinations +forepart +foreparts +forepassed +forepast +forepaw +forepaws +forepeak +forepeaks +foreperson +forepersons +foreplay +forequarter +forequarters +foreran +forereach +forereached +forereaches +forereaching +forerun +forerunner +forerunners +forerunning +foreruns +foresaid +foresail +foresails +foresaw +foresee +foreseeability +foreseeable +foreseeing +foreseen +foreseer +foreseers +foresees +foreshadow +foreshadowed +foreshadower +foreshadowers +foreshadowing +foreshadows +foreshank +foresheet +foresheets +foreshock +foreshocks +foreshore +foreshores +foreshorten +foreshortened +foreshortening +foreshortens +foreshow +foreshowed +foreshowing +foreshown +foreshows +foreside +foresides +foresight +foresighted +foresightedly +foresightedness +foresightful +foreskin +foreskins +forespeak +forespeaking +forespeaks +forespoke +forespoken +forest +forestage +forestages +forestal +forestall +forestalled +forestaller +forestallers +forestalling +forestallment +forestalls +forestation +forestations +forestay +forestays +forestaysail +forestaysails +forested +forester +foresters +forestial +foresting +forestland +forestlands +forestry +forests +foretaste +foretasted +foretastes +foretasting +foretell +foreteller +foretellers +foretelling +foretells +forethought +forethoughtful +forethoughtfully +forethoughtfulness +forethoughts +foretime +foretimes +foretoken +foretokened +foretokening +foretokens +foretold +foretop +foretopgallant +foretopmast +foretopmasts +foretops +foretopsail +foretopsails +forever +forevermore +foreverness +forewarn +forewarned +forewarning +forewarnings +forewarns +forewent +forewing +forewings +forewoman +forewomen +foreword +forewords +foreworn +foreyard +foreyards +forfeit +forfeitable +forfeited +forfeiter +forfeiters +forfeiting +forfeits +forfeiture +forfeitures +forfend +forfended +forfending +forfends +forficate +forgather +forgathered +forgathering +forgathers +forgave +forge +forgeability +forgeable +forged +forger +forgeries +forgers +forgery +forges +forget +forgetful +forgetfully +forgetfulness +forgetive +forgets +forgettable +forgetter +forgetters +forgetting +forging +forgings +forgivable +forgivably +forgive +forgiven +forgiveness +forgiver +forgivers +forgives +forgiving +forgivingly +forgivingness +forgo +forgoer +forgoers +forgoes +forgoing +forgone +forgot +forgotten +forint +forints +fork +forkball +forkballer +forkballers +forkballs +forked +forker +forkers +forkful +forkfuls +forkier +forkiest +forking +forklift +forklifted +forklifting +forklifts +forks +forky +forlorn +forlornly +forlornness +form +forma +formability +formable +formal +formaldehyde +formalin +formalins +formalism +formalisms +formalist +formalistic +formalistically +formalists +formalities +formality +formalizable +formalization +formalizations +formalize +formalized +formalizer +formalizers +formalizes +formalizing +formally +formalness +formals +formalwear +formant +formants +format +formate +formates +formation +formational +formations +formative +formatively +formativeness +formatives +formats +formatted +formatter +formatters +formatting +forme +formed +formee +former +formerly +formers +formes +formfeed +formfeeds +formfitting +formful +formic +formica +formicaries +formicary +formicivorous +formidability +formidable +formidableness +formidably +forming +formless +formlessly +formlessness +formosa +forms +formula +formulae +formulaic +formulaically +formularies +formularization +formularizations +formularize +formularized +formularizer +formularizers +formularizes +formularizing +formulary +formulas +formulate +formulated +formulates +formulating +formulation +formulations +formulator +formulators +formulization +formulizations +formulize +formulized +formulizer +formulizers +formulizes +formulizing +formwork +formworks +formyl +formyls +fornax +fornicate +fornicated +fornicates +fornicating +fornication +fornications +fornicator +fornicators +fornices +fornix +forrader +forrarder +forsake +forsaken +forsakes +forsaking +forsook +forsooth +forspent +forswear +forswearer +forswearers +forswearing +forswears +forswore +forsworn +forsythia +forsythias +fort +fortalice +fortalices +forte +fortes +forth +forthcoming +forthcomings +forthright +forthrightly +forthrightness +forthwith +forties +fortieth +fortieths +fortifiable +fortification +fortifications +fortified +fortifier +fortifiers +fortifies +fortify +fortifying +fortifyingly +fortiori +fortis +fortises +fortissimo +fortissimos +fortississimo +fortitude +fortitudinous +fortnight +fortnightlies +fortnightly +fortnights +fortran +fortress +fortresses +fortresslike +forts +fortuities +fortuitous +fortuitously +fortuitousness +fortuity +fortuna +fortunate +fortunately +fortunateness +fortunates +fortune +fortuned +fortunes +fortuneteller +fortunetellers +fortunetelling +fortuning +forty +fortyfold +fortyish +forum +forums +forward +forwarded +forwarder +forwarders +forwarding +forwardly +forwardness +forwards +forwent +forworn +forzando +forzandos +foss +fossa +fossae +fossate +fosse +fosses +fossick +fossicked +fossicker +fossickers +fossicking +fossicks +fossil +fossiliferous +fossilization +fossilizations +fossilize +fossilized +fossilizes +fossilizing +fossils +fossorial +foster +fosterage +fostered +fosterer +fosterers +fostering +fosterling +fosterlings +fosters +fou +foucault +foudroyant +fought +foul +foulard +foulards +foulbrood +foulbroods +fouled +fouler +foulest +fouling +foully +foulmouthed +foulness +fouls +found +foundation +foundational +foundationally +foundationless +foundations +founded +founder +foundered +foundering +founders +founding +foundling +foundlings +foundries +foundry +founds +fount +fountain +fountained +fountainhead +fountainheads +fountaining +fountains +founts +four +fourchee +fourchette +fourchettes +fourdrinier +fourdriniers +fourfold +fourgon +fourgons +fourhanded +fourier +fourierism +fourierist +fourierists +fourierite +fourierites +fourpenny +fourragère +fours +fourscore +foursome +foursomes +foursquare +foursquarely +fourteen +fourteenfold +fourteens +fourteenth +fourteenths +fourth +fourthly +fourths +fovea +foveae +foveal +foveate +foveiform +foveola +foveolae +foveolas +fowl +fowled +fowler +fowlers +fowling +fowls +fox +foxed +foxes +foxfire +foxfires +foxglove +foxgloves +foxhole +foxholes +foxhound +foxhounds +foxhunt +foxhunted +foxhunter +foxhunters +foxhunting +foxhunts +foxier +foxiest +foxily +foxiness +foxing +foxtail +foxtails +foxtrot +foxtrots +foxtrotted +foxtrotting +foxy +foy +foyer +foyers +foyle +foys +fra +fracas +fracases +fractal +fractals +fracted +fraction +fractional +fractionalization +fractionalizations +fractionalize +fractionalized +fractionalizes +fractionalizing +fractionally +fractionate +fractionated +fractionates +fractionating +fractionation +fractionations +fractionator +fractionators +fractionization +fractionizations +fractionize +fractionized +fractionizes +fractionizing +fractions +fractious +fractiously +fractiousness +fractur +fracture +fractured +fractures +fracturing +fracturs +frae +frag +fragged +fragger +fraggers +fragging +fragile +fragilely +fragileness +fragilities +fragility +fragment +fragmental +fragmentally +fragmentarily +fragmentariness +fragmentary +fragmentate +fragmentated +fragmentates +fragmentating +fragmentation +fragmentations +fragmented +fragmenting +fragmentize +fragmentized +fragmentizer +fragmentizers +fragmentizes +fragmentizing +fragments +fragonard +fragrance +fragrances +fragrancy +fragrant +fragrantly +frags +fraidy +frail +frailer +frailest +frailly +frailness +frailties +frailty +fraise +fraises +fraktur +frakturs +framable +frambesia +frambesias +frame +frameable +framed +framer +framers +frames +frameshift +framework +frameworks +framing +framingham +framings +franc +franca +francas +france +franchise +franchised +franchisee +franchisees +franchiser +franchisers +franchises +franchising +franchisor +franchisors +francis +franciscan +franciscans +francisco +francium +franco +francolin +francolins +franconia +franconian +franconians +francophile +francophiles +francophilia +francophobe +francophobes +francophobia +francophobic +francophone +francophones +francophonic +francs +frangibility +frangible +frangibleness +frangipane +frangipani +frangipanis +franglais +frank +franked +frankenstein +frankenstein's +frankensteinian +frankensteins +franker +frankers +frankest +frankfort +frankforter +frankforters +frankfurt +frankfurter +frankfurters +frankincense +franking +frankish +franklin +franklinite +franklinites +franklins +frankly +frankness +frankpledge +frankpledges +franks +franseria +franserias +frantic +frantically +franticly +franticness +française +frap +frappe +frapped +frappes +frapping +frappé +frappés +fraps +fraser +frat +fraternal +fraternalism +fraternally +fraternities +fraternity +fraternization +fraternizations +fraternize +fraternized +fraternizer +fraternizers +fraternizes +fraternizing +fratricidal +fratricide +fratricides +frats +frau +fraud +frauds +fraudulence +fraudulent +fraudulently +fraudulentness +frauen +fraught +fraughted +fraughting +fraughts +fraunhofer +fraxinella +fraxinellas +fray +frayed +fraying +frays +frazzle +frazzled +frazzles +frazzling +freak +freaked +freakier +freakiest +freakily +freakiness +freaking +freakish +freakishly +freakishness +freaks +freaky +freckle +freckled +freckles +freckling +freckly +frederick +fredericton +free +freebase +freebased +freebaser +freebasers +freebases +freebasing +freebee +freebees +freebie +freebies +freeboard +freeboards +freeboot +freebooted +freebooter +freebooters +freebooting +freeboots +freeborn +freed +freedman +freedmen +freedom +freedoms +freedwoman +freedwomen +freeform +freehand +freehanded +freehandedly +freehandedness +freehearted +freeheartedly +freeheartedness +freehold +freeholder +freeholders +freeholds +freeing +freelance +freelanced +freelancer +freelancers +freelances +freelancing +freeload +freeloaded +freeloader +freeloaders +freeloading +freeloads +freely +freeman +freemartin +freemartins +freemason +freemasonry +freemasons +freemen +freeness +freeport +freer +freers +frees +freesia +freesias +freest +freestanding +freestone +freestones +freestyle +freestyles +freethinker +freethinkers +freethinking +freetown +freeware +freeway +freeways +freewheel +freewheeled +freewheeler +freewheelers +freewheeling +freewheelingly +freewheels +freewill +freezable +freeze +freezer +freezers +freezes +freezing +freiberg +freiburg +freight +freightage +freighted +freighter +freighters +freighting +freightliner +freightliners +freights +fremantle +fremitus +fremontia +fremontias +frena +french +frenched +frenches +frenchification +frenchified +frenchifies +frenchify +frenchifying +frenching +frenchman +frenchmen +frenchness +frenchwoman +frenchwomen +frenetic +frenetical +frenetically +freneticism +frenula +frenulum +frenum +frenums +frenzied +frenziedly +frenzies +frenzy +frenzying +freon +frequence +frequences +frequencies +frequency +frequent +frequentation +frequentations +frequentative +frequentatives +frequented +frequenter +frequenters +frequenting +frequently +frequentness +frequents +fresco +frescoed +frescoer +frescoers +frescoes +frescoing +frescoist +frescoists +frescos +fresh +freshen +freshened +freshener +fresheners +freshening +freshens +fresher +freshest +freshet +freshets +freshly +freshman +freshmen +freshness +freshwater +fresnel +fresno +fret +fretful +fretfully +fretfulness +fretless +frets +fretsaw +fretsaws +fretted +fretter +fretters +fretting +fretwork +freud +freudian +freudianism +freudians +frey +freya +freyr +friability +friable +friableness +friar +friarbird +friarbirds +friaries +friarly +friars +friary +fribble +fribbled +fribbler +fribblers +fribbles +fribbling +fribourg +fricandeau +fricandeaus +fricassee +fricasseed +fricasseeing +fricassees +fricative +fricatives +friction +frictional +frictionally +frictionless +frictionlessly +frictions +friday +fridays +fridge +fridges +fried +friedland +friedrichshafen +friend +friended +friending +friendless +friendlessness +friendlier +friendlies +friendliest +friendlily +friendliness +friendly +friends +friendship +friendships +frier +friers +fries +friesian +friesians +friesland +frieze +friezes +frig +frigate +frigates +frigg +frigga +frigged +frigging +fright +frighted +frighten +frightened +frightener +frighteners +frightening +frighteningly +frightens +frightful +frightfully +frightfulness +frighting +frights +frigid +frigidaire +frigidities +frigidity +frigidly +frigidness +frigorific +frigorifical +frigs +frijol +frijole +frijoles +frill +frilled +frillier +frilliest +frilliness +frilling +frills +frilly +fringe +fringed +fringes +fringing +fringy +fripperies +frippery +frisbee +frisbees +frisch +frisette +frisettes +friseur +friseurs +frisian +frisians +frisk +frisked +frisker +friskers +frisket +friskets +friskier +friskiest +friskily +friskiness +frisking +frisks +frisky +frisson +frissons +frisé +frisée +frit +frith +friths +fritillaries +fritillary +frits +frittata +frittatas +fritted +fritter +frittered +fritterer +fritterers +frittering +fritters +fritting +fritz +fritzes +friuli +frivol +frivoled +frivoler +frivolers +frivoling +frivolities +frivolity +frivolled +frivoller +frivollers +frivolling +frivolous +frivolously +frivolousness +frivols +frizette +frizettes +frizz +frizzed +frizzer +frizzers +frizzes +frizzier +frizziest +frizzily +frizziness +frizzing +frizzle +frizzled +frizzles +frizzlier +frizzliest +frizzling +frizzly +frizzy +fro +frobenius +frobisher +frock +frocked +frocking +frocks +froe +froebel +froes +frog +frogeye +frogeyes +frogfish +frogfishes +froghopper +froghoppers +frogman +frogmen +frogmouth +frogmouths +frogs +froissart +frolic +frolicked +frolicker +frolickers +frolicking +frolics +frolicsome +from +frond +fronded +frondescence +frondescent +frondeur +frondeurs +frondose +frondosely +fronds +frons +front +frontage +frontages +frontal +frontality +frontally +frontals +frontcourt +frontcourts +fronted +frontenis +frontes +frontier +frontiers +frontiersman +frontiersmen +frontierswoman +frontierswomen +fronting +frontispiece +frontispieces +frontless +frontlet +frontlets +frontline +frontogeneses +frontogenesis +frontolyses +frontolysis +fronton +frontons +frontrunner +frontrunners +fronts +frontward +frontwards +frore +frosh +froshes +frost +frostbelt +frostbit +frostbite +frostbites +frostbiting +frostbitten +frosted +frostfish +frostfishes +frostier +frostiest +frostily +frostiness +frosting +frostings +frosts +frostwork +frostworks +frosty +froth +frothed +frothier +frothiest +frothily +frothiness +frothing +froths +frothy +frottage +frottages +froufrou +froufrous +frow +froward +frowardly +frowardness +frown +frowned +frowner +frowners +frowning +frowningly +frowns +frows +frowsier +frowsiest +frowstier +frowstiest +frowsty +frowsy +frowzier +frowziest +frowziness +frowzy +froze +frozen +frozenly +frozenness +fructiferous +fructification +fructifications +fructified +fructifies +fructify +fructifying +fructose +fructuous +frugal +frugalities +frugality +frugally +frugalness +frugivore +frugivores +frugivorous +fruit +fruitage +fruitages +fruitarian +fruitarians +fruitcake +fruitcakes +fruited +fruiterer +fruiterers +fruitful +fruitfully +fruitfulness +fruitier +fruitiest +fruitiness +fruiting +fruition +fruitions +fruitless +fruitlessly +fruitlessness +fruitlet +fruitlets +fruits +fruitwood +fruitwoods +fruity +frumentaceous +frumenties +frumenty +frump +frumpier +frumpiest +frumpily +frumpiness +frumpish +frumpishly +frumpishness +frumps +frumpy +frusta +frustrate +frustrated +frustrater +frustraters +frustrates +frustrating +frustratingly +frustration +frustrations +frustule +frustules +frustum +frustums +frutescence +frutescent +fruticose +fry +fryer +fryers +frying +fräulein +fräuleins +ftp +fu +fubsier +fubsiest +fubsy +fuchsia +fuchsias +fuchsin +fuchsine +fuchsines +fuchsins +fuck +fucked +fucker +fuckers +fucking +fucks +fuckup +fuckups +fucoid +fucoids +fucose +fucoses +fucoxanthin +fucoxanthins +fucus +fucuses +fud +fuddle +fuddled +fuddles +fuddling +fudge +fudged +fudges +fudging +fuds +fuego +fuehrer +fuehrers +fuel +fueled +fueler +fuelers +fueling +fuelled +fuelling +fuels +fuertaventura +fuerteventura +fug +fugacious +fugaciously +fugaciousness +fugacities +fugacity +fugal +fugally +fugged +fugging +fuggy +fugit +fugitive +fugitively +fugitiveness +fugitives +fugle +fugled +fugleman +fuglemen +fugles +fugling +fugs +fugu +fugue +fugued +fugues +fuguing +fuguist +fuguists +fugus +fuissé +fujairah +fuji +fujian +fujinoyama +fujis +fujisan +fujisawa +fukien +fula +fulani +fulanis +fulas +fulbright +fulcra +fulcrum +fulcrums +fulfil +fulfill +fulfilled +fulfiller +fulfillers +fulfilling +fulfillment +fulfillments +fulfills +fulfilment +fulfils +fulgent +fulgently +fulgurant +fulgurate +fulgurated +fulgurates +fulgurating +fulguration +fulgurations +fulgurite +fulgurites +fulgurous +fulham +fulhams +fuliginous +fuliginously +full +fullback +fullbacks +fulled +fuller +fullerene +fullerenes +fullers +fullest +fulling +fullmouthed +fullness +fulls +fulltime +fully +fulmar +fulmars +fulminant +fulminate +fulminated +fulminates +fulminating +fulmination +fulminations +fulminator +fulminators +fulminatory +fulmine +fulmined +fulmines +fulminic +fulmining +fulness +fulsome +fulsomely +fulsomeness +fulvous +fumarase +fumarases +fumarate +fumarates +fumaric +fumarole +fumaroles +fumarolic +fumatoria +fumatories +fumatorium +fumatoriums +fumatory +fumble +fumbled +fumbler +fumblers +fumbles +fumbling +fumblingly +fume +fumed +fumes +fumet +fumets +fumier +fumiest +fumigant +fumigants +fumigate +fumigated +fumigates +fumigating +fumigation +fumigations +fumigator +fumigators +fuming +fumitories +fumitory +fumy +fun +funafuti +funambulism +funambulist +funambulists +funchal +function +functional +functionalism +functionalist +functionalistic +functionalists +functionalities +functionality +functionally +functionaries +functionary +functioned +functioning +functionless +functions +functor +functors +fund +fundable +fundament +fundamental +fundamentalism +fundamentalist +fundamentalistic +fundamentalists +fundamentally +fundamentals +fundaments +funded +fundi +fundic +funding +fundraise +fundraised +fundraiser +fundraisers +fundraises +fundraising +funds +fundus +funeral +funerals +funerary +funereal +funereally +funfair +funfairs +funfest +funfests +fungal +fungi +fungibility +fungible +fungibles +fungicidal +fungicidally +fungicide +fungicides +fungiform +fungistat +fungistats +fungivorous +fungo +fungoes +fungoid +fungoids +fungous +fungus +funguses +funicle +funicles +funicular +funiculars +funiculi +funiculus +funk +funked +funkia +funkias +funkier +funkiest +funkiness +funking +funks +funky +funned +funnel +funneled +funnelform +funneling +funnelled +funnelling +funnels +funnier +funnies +funniest +funnily +funniness +funning +funny +funnyman +funnymen +funs +fur +furan +furane +furanes +furanose +furanoses +furans +furbearer +furbearers +furbearing +furbelow +furbelowed +furbelowing +furbelows +furbish +furbished +furbisher +furbishers +furbishes +furbishing +furcate +furcated +furcately +furcates +furcating +furcation +furcations +furcula +furculae +furcular +furfur +furfuraceous +furfural +furfurals +furfuran +furfurans +furfures +furies +furioso +furious +furiously +furl +furled +furless +furling +furlong +furlongs +furlough +furloughed +furloughing +furloughs +furls +furmities +furmity +furnace +furnaces +furnish +furnished +furnisher +furnishers +furnishes +furnishing +furnishings +furniture +furor +furore +furores +furors +furosemide +furosemides +furred +furrier +furrieries +furriers +furriery +furriest +furriner +furriners +furriness +furring +furrings +furrow +furrowed +furrowing +furrows +furry +furs +further +furtherance +furthered +furtherer +furtherers +furthering +furthermore +furthermost +furthers +furthest +furtive +furtively +furtiveness +furuncle +furuncles +furuncular +furunculosis +furunculous +fury +furze +furzes +furzy +fusain +fusains +fusaria +fusarium +fuscous +fuse +fused +fusee +fusees +fusel +fuselage +fuselages +fusels +fuser +fusers +fuses +fusibility +fusible +fusibleness +fusiform +fusil +fusile +fusileer +fusileers +fusilier +fusiliers +fusillade +fusilladed +fusillades +fusillading +fusils +fusing +fusion +fusionism +fusionist +fusionists +fusions +fuss +fussbudget +fussbudgets +fussbudgety +fussed +fusser +fussers +fusses +fussier +fussiest +fussily +fussiness +fussing +fusspot +fusspots +fussy +fustian +fustians +fustic +fustics +fustier +fustiest +fustigate +fustigated +fustigates +fustigating +fustigation +fustigations +fustily +fustiness +fusty +fusuma +futhark +futharks +futhorc +futhork +futile +futilely +futileness +futilitarian +futilitarianism +futilitarians +futilities +futility +futon +futons +futtock +futtocks +futuna +future +futureless +futurelessness +futures +futurism +futurisms +futurist +futuristic +futuristically +futuristics +futurists +futurities +futurity +futurological +futurologist +futurologists +futurology +futz +futzed +futzes +futzing +fuze +fuzed +fuzee +fuzees +fuzes +fuzing +fuzz +fuzzed +fuzzes +fuzzier +fuzziest +fuzzily +fuzziness +fuzzing +fuzzy +fuzzyheaded +fuzzyheadedness +fyce +fyces +fyke +fykes +fylfot +fylfots +fyn +fátima +fès +fête +fêted +fêtes +fêting +föhn +föhns +führer +führers +g +gab +gabardine +gabardines +gabbed +gabber +gabbers +gabbier +gabbiest +gabbiness +gabbing +gabble +gabbled +gabbler +gabblers +gabbles +gabbling +gabbro +gabbroic +gabbroid +gabbros +gabby +gabelle +gabelles +gaberdine +gaberdines +gabfest +gabfests +gabies +gabion +gabions +gable +gabled +gabler +gables +gabon +gabonese +gaboon +gaboons +gaborone +gabriel +gabs +gaby +gad +gadabout +gadabouts +gadara +gadarene +gadarenes +gaddafi +gadded +gadder +gadders +gadding +gadflies +gadfly +gadget +gadgeteer +gadgeteers +gadgetry +gadgets +gadgety +gadid +gadids +gadoid +gadoids +gadolinite +gadolinites +gadolinium +gadoliniums +gadroon +gadrooned +gadrooning +gadroonings +gadroons +gads +gadwall +gadwalls +gadzooks +gaea +gael +gaeldom +gaelic +gaels +gaff +gaffe +gaffed +gaffer +gaffers +gaffes +gaffing +gaffs +gag +gaga +gage +gaged +gager +gagers +gages +gagged +gagger +gaggers +gagging +gaggle +gaggles +gaging +gagman +gagmen +gags +gagster +gagsters +gahnite +gahnites +gaia +gaieties +gaiety +gaillardia +gaillardias +gaily +gain +gained +gainer +gainers +gainesville +gainful +gainfully +gainfulness +gaingiving +gaining +gains +gainsaid +gainsay +gainsayer +gainsayers +gainsaying +gainsays +gainsborough +gainst +gaiseric +gait +gaited +gaiter +gaiters +gaithersburg +gaiting +gaits +gaius +gal +gala +galabia +galabias +galactic +galactopoiesis +galactopoietic +galactorrhea +galactosamine +galactosamines +galactose +galactosemia +galactosemias +galactosemic +galactosidase +galactosidases +galactoside +galactosides +galago +galagos +galah +galahad +galahads +galahs +galangal +galangals +galantine +galantines +galanty +galapagos +galas +galatea +galateas +galatia +galatian +galatians +galavant +galavanted +galavanting +galavants +galax +galaxes +galaxies +galaxy +galbanum +galbanums +gale +galea +galeae +galeate +galeated +galen +galena +galenas +galenical +galenicals +galenism +galenist +galenists +galere +galeres +galerius +gales +galibi +galibis +galicia +galician +galicians +galilean +galileans +galilee +galilees +galileo +galimatias +galimatiases +galingale +galingales +galiot +galiots +galipot +galipots +galivant +galivanted +galivanting +galivants +gall +galla +gallamine +gallant +gallanted +gallanting +gallantly +gallantries +gallantry +gallants +gallas +gallate +gallates +gallbladder +gallbladders +galleass +galleasses +galled +gallein +galleins +galleon +galleons +galleria +gallerias +galleried +galleries +gallery +galleta +galletas +galley +galleys +gallflies +gallfly +gallia +galliard +galliards +gallic +gallican +gallicanism +gallicans +gallicism +gallicisms +gallicization +gallicizations +gallicize +gallicized +gallicizes +gallicizing +gallied +gallies +galligaskins +gallimaufries +gallimaufry +gallinacean +gallinaceans +gallinaceous +gallinas +galling +gallingly +gallinipper +gallinippers +gallinule +gallinules +galliot +galliots +gallipoli +gallipot +gallipots +gallium +gallivant +gallivanted +gallivanting +gallivants +galliwasp +galliwasps +gallnut +gallnuts +gallo +galloglass +galloglasses +gallomania +gallomanias +gallon +gallonage +gallonages +gallons +galloon +gallooned +galloons +gallop +gallopade +galloped +galloper +gallopers +galloping +gallops +galloway +gallowglass +gallowglasses +gallows +gallowses +galls +gallstone +gallstones +gallus +galluses +gally +gallying +galois +galoot +galoots +galop +galops +galore +galosh +galoshed +galoshes +gals +galsworthy +galumph +galumphed +galumphing +galumphs +galvanic +galvanically +galvanism +galvanisms +galvanization +galvanizations +galvanize +galvanized +galvanizer +galvanizers +galvanizes +galvanizing +galvanomagnetic +galvanometer +galvanometers +galvanometric +galvanometrical +galvanometry +galvanoscope +galvanoscopes +galvanoscopic +galvanoscopy +galveston +galway +galwegian +galwegians +galyak +galyaks +galápagos +galère +gam +gama +gamage +gamay +gamays +gamba +gambado +gambadoes +gambados +gambas +gambia +gambian +gambians +gambier +gambiers +gambir +gambirs +gambit +gambits +gamble +gambled +gambler +gamblers +gambles +gambling +gamboge +gamboges +gambol +gamboled +gamboling +gambolled +gambolling +gambols +gambrel +gambrels +gambusia +gambusias +game +gamecock +gamecocks +gamed +gamekeeper +gamekeepers +gamelan +gamelans +gamelike +gamely +gameness +gamer +games +gamesman +gamesmanship +gamesmen +gamesome +gamesomely +gamesomeness +gamest +gamester +gamesters +gametangia +gametangial +gametangium +gamete +gametes +gametic +gametically +gametocyte +gametocytes +gametogenesis +gametogenic +gametogenous +gametophore +gametophores +gametophoric +gametophyte +gametophytes +gametophytic +gamey +gamic +gamier +gamiest +gamily +gamin +gamine +gamines +gaminess +gaming +gamings +gamins +gamma +gammas +gammed +gammer +gammers +gamming +gammon +gammoned +gammoner +gammoners +gammoning +gammons +gamogenesis +gamogenetic +gamogenetically +gamopetalous +gamophyllous +gamosepalous +gamow +gamp +gamps +gams +gamut +gamuts +gamy +gan +ganciclovir +gander +ganders +gandhi +gandhian +ganef +ganefs +ganesha +gang +ganga +gangbang +gangbanged +gangbanging +gangbangs +gangbuster +gangbusters +ganged +ganger +gangers +ganges +ganging +gangland +ganglia +gangliate +gangliated +ganglier +gangliest +gangling +ganglion +ganglionated +ganglionic +ganglions +ganglioside +gangliosides +gangly +gangplank +gangplanks +gangplow +gangplows +gangpunch +gangpunched +gangpunches +gangpunching +gangrel +gangrels +gangrene +gangrened +gangrenes +gangrening +gangrenous +gangs +gangster +gangsterdom +gangsterism +gangsters +gangue +gangues +gangway +gangways +ganister +ganisters +ganja +ganjas +gannet +gannets +gannister +gannisters +ganof +ganofs +ganoid +ganoids +gansu +gantlet +gantleted +gantleting +gantlets +gantline +gantlines +gantlope +gantlopes +gantries +gantry +gantt +ganymede +gaol +gaoled +gaoler +gaolers +gaoling +gaols +gap +gape +gaped +gaper +gapers +gapes +gapeworm +gapeworms +gaping +gapingly +gapped +gapping +gappy +gaps +gar +garage +garageable +garaged +garageman +garagemen +garages +garaging +garamond +garb +garbage +garbanzo +garbanzos +garbed +garbing +garble +garbled +garbler +garblers +garbles +garbling +garbo +garboard +garboards +garboil +garboils +garbologist +garbologists +garbology +garbs +garcía +garda +gardant +garde +garden +gardened +gardener +gardeners +gardenful +gardenia +gardenias +gardening +gardens +garderobe +garderobes +gardiners +gardyloo +garfield +garfish +garfishes +garganey +garganeys +gargantua +gargantuan +gargantuas +garget +gargets +gargle +gargled +gargles +gargling +gargoyle +gargoyles +garibaldi +garibaldis +garish +garishly +garishness +garland +garlanded +garlanding +garlands +garlic +garlicked +garlicking +garlicks +garlicky +garment +garmented +garmenting +garments +garner +garnered +garnering +garners +garnet +garnetiferous +garnets +garni +garnierite +garnierites +garnis +garnish +garnished +garnishee +garnisheed +garnisheeing +garnishees +garnishes +garnishing +garnishment +garnishments +garniture +garnitures +garonne +garotte +garotted +garotter +garotters +garottes +garotting +garpike +garpikes +garred +garret +garrets +garrick +garring +garrison +garrisoned +garrisoning +garrisons +garron +garrons +garrote +garroted +garroter +garroters +garrotes +garroting +garrotte +garrotted +garrottes +garrotting +garrulity +garrulous +garrulously +garrulousness +gars +garter +gartered +gartering +garters +garth +garths +garve +garvey +garveys +garçon +garçons +gas +gasbag +gasbags +gascon +gasconade +gasconaded +gasconader +gasconaders +gasconades +gasconading +gascons +gascony +gasdynamic +gasdynamicist +gasdynamicists +gasdynamics +gaseous +gaseousness +gases +gash +gashed +gasherbrum +gashes +gashing +gasholder +gasholders +gashouse +gashouses +gasifiable +gasification +gasifications +gasified +gasifier +gasifiers +gasifies +gasiform +gasify +gasifying +gaskell +gasket +gaskets +gaskin +gaskins +gaslight +gaslights +gaslit +gasogene +gasogenes +gasohol +gasolene +gasolenes +gasolier +gasoliers +gasoline +gasolines +gasolinic +gasometer +gasometers +gasp +gaspar +gasped +gasper +gaspers +gasping +gaspingly +gasps +gaspé +gassed +gasser +gassers +gasses +gassier +gassiest +gassily +gassiness +gassing +gassings +gassy +gast +gasted +gastight +gastightness +gasting +gastness +gastraea +gastraeas +gastrea +gastreas +gastrectomies +gastrectomy +gastric +gastrin +gastrins +gastritis +gastrocnemii +gastrocnemius +gastroenteric +gastroenteritis +gastroenterologic +gastroenterological +gastroenterologist +gastroenterologists +gastroenterology +gastrointestinal +gastrolith +gastroliths +gastrologic +gastrological +gastrologically +gastrologist +gastrologists +gastrology +gastronome +gastronomer +gastronomers +gastronomes +gastronomic +gastronomical +gastronomically +gastronomies +gastronomist +gastronomists +gastronomy +gastropod +gastropodan +gastropodous +gastropods +gastroscope +gastroscopes +gastroscopic +gastroscopist +gastroscopists +gastroscopy +gastrostomies +gastrostomy +gastrotomies +gastrotomy +gastrotrich +gastrotriches +gastrovascular +gastrula +gastrulae +gastrular +gastrulas +gastrulate +gastrulated +gastrulates +gastrulating +gastrulation +gastrulations +gasts +gasworks +gat +gate +gateau +gateaux +gatecrash +gatecrashed +gatecrasher +gatecrashers +gatecrashes +gatecrashing +gated +gatefold +gatefolds +gatehouse +gatehouses +gatekeeper +gatekeepers +gatepost +gateposts +gater +gaters +gates +gateway +gatewayed +gatewaying +gateways +gather +gathered +gatherer +gatherers +gathering +gatherings +gathers +gatherum +gatherums +gatineau +gating +gatling +gatlings +gator +gatorade +gators +gats +gatún +gauche +gauchely +gaucheness +gaucher +gaucherie +gaucheries +gauchest +gaucho +gauchos +gaud +gaudeamus +gauderies +gaudery +gaudier +gaudies +gaudiest +gaudily +gaudiness +gauds +gaudy +gaufer +gaufers +gauffer +gauffered +gauffering +gauffers +gaugamela +gauge +gaugeable +gauged +gauger +gaugers +gauges +gauging +gauguin +gaul +gaulish +gaulle +gaullism +gaullist +gaullists +gauls +gault +gaults +gaum +gaumed +gauming +gaumont +gaums +gaunt +gaunter +gauntest +gauntlet +gauntleted +gauntlets +gauntly +gauntness +gaur +gaurs +gauss +gausses +gaussian +gautama +gauze +gauzelike +gauzes +gauzier +gauziest +gauzily +gauziness +gauzy +gavage +gavages +gavarnie +gave +gavel +gaveled +gaveling +gavelkind +gavelled +gavelling +gavels +gavial +gavials +gavotte +gavotted +gavottes +gavotting +gawain +gawk +gawked +gawker +gawkers +gawkier +gawkiest +gawkily +gawking +gawkish +gawkishly +gawkishness +gawks +gawky +gawp +gawped +gawper +gawpers +gawping +gawps +gay +gayal +gayals +gayer +gayest +gayety +gayly +gayness +gays +gaza +gazar +gazars +gaze +gazebo +gazeboes +gazebos +gazed +gazehound +gazehounds +gazelle +gazelles +gazer +gazers +gazes +gazette +gazetted +gazetteer +gazetteers +gazettes +gazetting +gaziantep +gazillion +gazillionaire +gazillionaires +gazillions +gazing +gazogene +gazogenes +gazpacho +gazpachos +gdansk +geanticlinal +geanticline +geanticlines +gear +gearbox +gearboxes +geared +gearing +gearings +gearless +gears +gearshift +gearshifts +gearwheel +gearwheels +geat +geats +gebel +geber +gecko +geckoes +geckos +gedankenexperiment +gedankenexperiments +gee +geechee +geechees +geed +geegaw +geegaws +geeing +geek +geekish +geeks +geeky +geelong +gees +geese +geezer +geezers +gefilte +gegenschein +gegenscheins +gehenna +gehennas +gehrig +geiger +geisha +geishas +gel +gelable +gelada +gelate +gelated +gelates +gelati +gelatin +gelatine +gelatines +gelating +gelatinization +gelatinizations +gelatinize +gelatinized +gelatinizes +gelatinizing +gelatinous +gelatinously +gelatinousness +gelatins +gelation +gelations +gelato +geld +gelded +gelderland +gelding +geldings +gelds +gelee +gelees +gelid +gelidities +gelidity +gelidly +gelidness +gelignite +gelignites +gellant +gellants +gelled +gelling +gels +gelsenkirchen +gelt +gelts +geländesprung +geländesprungs +gem +gemara +gemaric +gemarist +gemarists +geminal +geminally +geminate +geminated +geminates +geminating +gemination +geminations +gemini +geminian +geminians +geminis +gemlike +gemma +gemmae +gemmate +gemmated +gemmates +gemmating +gemmation +gemmations +gemmed +gemming +gemmiparous +gemmiparously +gemmologist +gemmologists +gemmology +gemmulation +gemmulations +gemmule +gemmules +gemmuliferous +gemmy +gemological +gemologist +gemologists +gemology +gemot +gemote +gemotes +gemots +gems +gemsbok +gemsboks +gemstone +gemstones +gemütlich +gemütlichkeit +gendarme +gendarmerie +gendarmeries +gendarmes +gender +gendered +gendering +genderless +genders +gene +genealogical +genealogically +genealogies +genealogist +genealogists +genealogize +genealogized +genealogizes +genealogizing +genealogy +genera +generable +general +generalcies +generalcy +generalissimo +generalissimos +generalist +generalists +generalities +generality +generalizability +generalizable +generalization +generalizations +generalize +generalized +generalizer +generalizers +generalizes +generalizing +generally +generalness +generals +generalship +generalships +generate +generated +generates +generating +generation +generational +generations +generative +generatively +generativeness +generator +generators +generatrices +generatrix +generic +generically +genericness +generics +generis +generosities +generosity +generous +generously +generousness +genes +genesee +geneses +genesis +genet +genetic +genetical +genetically +geneticist +geneticists +genetics +genets +geneva +genevan +genevans +genevese +genghis +genial +geniality +genially +genialness +genials +genic +genically +geniculate +geniculated +geniculately +geniculation +geniculations +genie +genies +genii +genip +genipap +genipaps +genips +genital +genitalia +genitalic +genitally +genitals +genitival +genitivally +genitive +genitives +genitor +genitors +genitourinary +geniture +genitures +genius +geniuses +genoa +genoas +genocidal +genocidally +genocide +genocides +genoese +genoise +genoises +genom +genome +genomes +genomic +genomics +genoms +genotype +genotypes +genotypic +genotypical +genotypically +genotypicity +genova +genre +genres +genro +genros +gens +genseric +gent +gentamicin +gentamicins +genteel +genteelism +genteelisms +genteelly +genteelness +gentes +gentian +gentians +gentile +gentiles +gentilesse +gentilesses +gentilities +gentility +gentle +gentled +gentlefolk +gentlefolks +gentleman +gentlemanlike +gentlemanlikeness +gentlemanliness +gentlemanly +gentlemen +gentleness +gentlepeople +gentlepeoples +gentleperson +gentlepersons +gentler +gentles +gentlest +gentlewoman +gentlewomen +gentling +gently +gentrice +gentrices +gentries +gentrification +gentrifications +gentrified +gentrifier +gentrifiers +gentrifies +gentrify +gentrifying +gentry +gents +genuflect +genuflected +genuflecting +genuflection +genuflections +genuflects +genuflexion +genuine +genuinely +genuineness +genus +geobotanic +geobotanical +geobotanically +geobotanist +geobotanists +geobotany +geocentric +geocentrically +geocentricism +geochemical +geochemically +geochemist +geochemistry +geochemists +geochronologic +geochronological +geochronologically +geochronologist +geochronologists +geochronology +geochronometric +geochronometry +geocode +geocodes +geocorona +geocoronas +geode +geodes +geodesic +geodesics +geodesist +geodesists +geodesy +geodetic +geodetical +geodetically +geoduck +geoducks +geoeconomic +geoeconomically +geoeconomics +geoeconomist +geoeconomists +geographer +geographers +geographic +geographical +geographically +geographies +geography +geohydrologic +geohydrologist +geohydrologists +geohydrology +geoid +geoidal +geoids +geologic +geological +geologically +geologies +geologist +geologists +geologize +geologized +geologizes +geologizing +geology +geomagnetic +geomagnetically +geomagnetism +geomancer +geomancers +geomancy +geomantic +geometer +geometers +geometric +geometrical +geometrically +geometrician +geometricians +geometricize +geometricized +geometricizes +geometricizing +geometrics +geometrid +geometrids +geometries +geometrize +geometrized +geometrizes +geometrizing +geometry +geomorphic +geomorphologic +geomorphological +geomorphologically +geomorphologist +geomorphologists +geomorphology +geophagism +geophagist +geophagists +geophagy +geophone +geophones +geophysical +geophysically +geophysicist +geophysicists +geophysics +geophyte +geophytes +geopolitical +geopolitically +geopolitician +geopoliticians +geopolitics +geoponic +geoponics +geopressured +geopressurized +geordie +geordies +george +georges +georgetown +georgette +georgettes +georgia +georgian +georgians +georgic +georgical +georgics +geoscience +geosciences +geoscientist +geoscientists +geostationary +geostrategic +geostrategies +geostrategist +geostrategists +geostrategy +geostrophic +geostrophically +geosynchronous +geosynchronously +geosynclinal +geosyncline +geosynclines +geotactic +geotactically +geotaxes +geotaxis +geotectonic +geothermal +geothermally +geothermic +geotropic +geotropically +geotropism +gerah +gerahs +geraint +geranial +geranials +geraniol +geraniols +geranium +geraniums +gerardia +gerardias +gerbera +gerberas +gerbil +gerbille +gerbilles +gerbils +gerent +gerents +gerenuk +gerenuks +gerfalcon +gerfalcons +geriatric +geriatrician +geriatricians +geriatrics +geriatrist +geriatrists +germ +german +germander +germanders +germane +germanely +germaneness +germania +germanic +germanicus +germanism +germanisms +germanist +germanists +germanium +germanization +germanizations +germanize +germanized +germanizer +germanizers +germanizes +germanizing +germanophile +germanophiles +germanophobe +germanophobes +germanophobia +germans +germantown +germany +germen +germens +germfree +germicidal +germicide +germicides +germier +germiest +germinability +germinal +germinally +germinate +germinated +germinates +germinating +germination +germinations +germinative +germinator +germinators +germiness +germproof +germs +germy +gerodontic +gerodontics +gerona +geronimo +gerontic +gerontocracies +gerontocracy +gerontocrat +gerontocratic +gerontocrats +gerontologic +gerontological +gerontologist +gerontologists +gerontology +gerontomorphic +gerrymander +gerrymandered +gerrymandering +gerrymanders +gershwin +gertrude +gertrudis +gerund +gerundial +gerundive +gerundives +gerunds +geryon +gesneriad +gesneriads +gesso +gessoed +gessoes +gest +gestalt +gestalten +gestaltist +gestaltists +gestalts +gestapo +gestapos +gestate +gestated +gestates +gestating +gestation +gestational +gestations +gestatory +geste +gestes +gestic +gesticulate +gesticulated +gesticulates +gesticulating +gesticulation +gesticulations +gesticulative +gesticulator +gesticulators +gesticulatory +gests +gestural +gesturally +gesture +gestured +gesturer +gesturers +gestures +gesturing +gesundheit +get +geta +getable +getas +getatable +getaway +getaways +gethsemane +gethsemanes +gets +gettable +getter +getters +getting +getty +gettysburg +getup +getups +geum +geums +gewgaw +gewgaws +gewürztraminer +gewürztraminers +gey +geyser +geyserite +geyserites +geysers +ghaghara +ghaghra +ghana +ghanaian +ghanaians +gharial +gharials +gharries +gharry +ghast +ghastful +ghastfully +ghastlier +ghastliest +ghastliness +ghastly +ghat +ghats +ghaut +ghauts +ghazi +ghaziabad +ghazies +ghee +ghees +ghent +gherkin +gherkins +ghetto +ghettoed +ghettoes +ghettoing +ghettoization +ghettoizations +ghettoize +ghettoized +ghettoizes +ghettoizing +ghettos +ghi +ghibelline +ghibellines +ghibli +ghiblis +ghillie +ghillies +ghis +ghost +ghosted +ghosting +ghostings +ghostlier +ghostliest +ghostlike +ghostliness +ghostly +ghosts +ghostweed +ghostweeds +ghostwrite +ghostwriter +ghostwriters +ghostwrites +ghostwriting +ghostwritten +ghostwrote +ghosty +ghoul +ghoulish +ghoulishly +ghoulishness +ghouls +giant +giantess +giantesses +giantism +giantisms +giantlike +giants +giaour +giaours +giardia +giardias +giardiasis +gib +gibbed +gibber +gibbered +gibberellic +gibberellin +gibberellins +gibbering +gibberish +gibbers +gibbet +gibbeted +gibbeting +gibbets +gibbetted +gibbetting +gibbing +gibbon +gibbons +gibbosities +gibbosity +gibbous +gibbously +gibbousness +gibe +gibed +gibeon +gibeonite +gibeonites +giber +gibers +gibes +gibing +gibingly +giblet +giblets +gibraltar +gibraltarian +gibraltarians +gibs +gibson +gibsons +gid +giddap +giddied +giddier +giddies +giddiest +giddily +giddiness +giddy +giddyap +giddying +giddyup +gideon +gids +gie +gied +gieing +gies +gift +giftable +giftables +gifted +giftedly +giftedness +gifting +gifts +giftware +giftwares +gig +gigaampere +gigaamperes +gigabecquerel +gigabecquerels +gigabit +gigabits +gigabyte +gigabytes +gigacandela +gigacandelas +gigacoulomb +gigacoulombs +gigacycle +gigacycles +gigafarad +gigafarads +gigaflop +gigaflops +gigagram +gigagrams +gigahenries +gigahenry +gigahenrys +gigahertz +gigajoule +gigajoules +gigakelvin +gigakelvins +gigalumen +gigalumens +gigalux +gigameter +gigameters +gigamole +gigamoles +giganewton +giganewtons +gigantesque +gigantic +gigantically +gigantism +gigantisms +gigaohm +gigaohms +gigapascal +gigapascals +gigaradian +gigaradians +gigas +gigasecond +gigaseconds +gigasiemens +gigasievert +gigasieverts +gigasteradian +gigasteradians +gigatesla +gigateslas +gigaton +gigatons +gigavolt +gigavolts +gigawatt +gigawatts +gigaweber +gigawebers +gigged +gigging +giggle +giggled +giggler +gigglers +giggles +giggling +gigglingly +giggly +gigolo +gigolos +gigot +gigots +gigs +gigue +gigues +gikuyu +gikuyus +gila +gilbert +gilbertian +gilberts +gilboa +gild +gildas +gilded +gilder +gilders +gilding +gildings +gilds +gilead +giles +gilgamesh +gill +gilled +giller +gillers +gillette +gillie +gillied +gillies +gilling +gillnet +gillnets +gillnetted +gillnetting +gills +gillyflower +gillyflowers +gillying +gilsonite +gilt +gilts +gimbal +gimbaled +gimbaling +gimballed +gimballing +gimbals +gimcrack +gimcrackery +gimcracks +gimel +gimels +gimignano +gimlet +gimleted +gimleting +gimlets +gimmal +gimmals +gimme +gimmes +gimmick +gimmicked +gimmicking +gimmickries +gimmickry +gimmicks +gimmicky +gimp +gimped +gimping +gimps +gimpy +gin +ginger +gingerbread +gingerbreaded +gingerbreads +gingerbready +gingered +gingering +gingerliness +gingerly +gingerroot +gingerroots +gingers +gingersnap +gingersnaps +gingery +gingham +ginghams +gingiva +gingivae +gingival +gingivectomies +gingivectomy +gingivitis +gingko +gingkoes +gink +ginkgo +ginkgoes +ginks +ginned +ginner +ginners +ginning +ginny +gins +ginsberg +ginseng +ginsengs +ginzo +ginzoes +giorgione +giotto +giovanni +gip +gipped +gipping +gips +gipsies +gipsy +giraffe +giraffes +giraffish +girandole +girandoles +girasol +girasole +girasoles +girasols +gird +girded +girder +girders +girding +girdle +girdled +girdler +girdlers +girdles +girdling +girds +girl +girlfriend +girlfriends +girlhood +girlie +girlies +girlish +girlishly +girlishness +girls +girly +girn +girned +girning +girns +giro +giroed +giroes +giroing +giron +gironde +girondin +girondins +girondist +girondists +girons +giros +girosol +girosols +girt +girted +girth +girthed +girthing +girths +girting +girts +gisarme +gisarmes +gismo +gismos +gist +gists +git +gite +gites +gittern +gitterns +giulia +giuseppe +give +giveaway +giveaways +giveback +givebacks +given +givens +giver +givers +gives +giving +gizmo +gizmos +gizzard +gizzards +glabella +glabellae +glabellar +glabrate +glabrescent +glabrous +glabrousness +glacial +glacially +glaciate +glaciated +glaciates +glaciating +glaciation +glaciations +glacier +glaciered +glaciers +glaciologic +glaciological +glaciologist +glaciologists +glaciology +glacis +glacé +glacéed +glacéing +glacés +glad +gladded +gladden +gladdened +gladdening +gladdens +gladder +gladdest +gladding +glade +glades +gladiate +gladiator +gladiatorial +gladiators +gladiola +gladiolas +gladioli +gladiolus +gladioluses +gladly +gladness +glads +gladsome +gladsomely +gladsomeness +gladstone +gladstones +glady +glagolithic +glagolitic +glaiket +glaikit +glair +glaire +glaires +glairier +glairiest +glairs +glairy +glaive +glaives +glamor +glamored +glamorgan +glamoring +glamorization +glamorizations +glamorize +glamorized +glamorizer +glamorizers +glamorizes +glamorizing +glamorless +glamorous +glamorously +glamorousness +glamors +glamour +glamoured +glamouring +glamourization +glamourizations +glamourize +glamourized +glamourizer +glamourizers +glamourizes +glamourizing +glamourous +glamourously +glamourousness +glamours +glance +glanced +glances +glancing +glancingly +gland +glandered +glanderous +glanders +glandes +glandless +glands +glandular +glandularly +glans +glare +glared +glares +glarier +glariest +glaring +glaringly +glaringness +glary +glasgow +glasnost +glass +glassblower +glassblowers +glassblowing +glassed +glasses +glassfish +glassfishes +glassful +glassfuls +glasshouse +glasshouses +glassie +glassier +glassies +glassiest +glassily +glassine +glassines +glassiness +glassing +glassless +glasslike +glassmaker +glassmakers +glassmaking +glassware +glasswork +glassworker +glassworkers +glassworks +glasswort +glassworts +glassy +glastonbury +glaswegian +glaswegians +glauber +glaucoma +glaucomatous +glauconite +glauconites +glauconitic +glaucous +glaucousness +glaze +glazed +glazer +glazers +glazes +glazier +glazieries +glaziers +glaziery +glazing +glazings +gleam +gleamed +gleamer +gleamers +gleaming +gleams +gleamy +glean +gleanable +gleaned +gleaner +gleaners +gleaning +gleanings +gleans +gleba +glebae +glebe +glebes +glede +gledes +glee +gleed +gleeds +gleeful +gleefully +gleefulness +gleek +gleeked +gleeking +gleeks +gleeman +gleemen +glees +gleesome +gleet +gleets +gleety +gleg +glen +glenda +glendale +glengarries +glengarry +glens +gley +gleys +glia +gliadin +gliadins +glial +glias +glib +glibber +glibbest +glibly +glibness +glide +glided +glider +gliders +glides +gliding +glim +glimmer +glimmered +glimmering +glimmerings +glimmers +glimpse +glimpsed +glimpser +glimpsers +glimpses +glimpsing +glims +glint +glinted +glintier +glintiest +glinting +glints +glinty +glioma +gliomas +gliomata +glissade +glissaded +glissader +glissaders +glissades +glissading +glissandi +glissando +glissandos +glisten +glistened +glistening +glistens +glister +glistered +glistering +glisters +glitch +glitches +glitchy +glitter +glitterati +glittered +glittering +glitteringly +glitters +glittertinden +glittery +glitz +glitzed +glitzes +glitziness +glitzing +glitzy +gloam +gloaming +gloams +gloat +gloated +gloater +gloaters +gloating +gloats +glob +global +globalism +globalisms +globalist +globalists +globalization +globalizations +globalize +globalized +globalizer +globalizers +globalizes +globalizing +globally +globals +globate +globe +globed +globefish +globefishes +globeflower +globeflowers +globes +globetrot +globetrots +globetrotted +globetrotter +globetrotters +globetrotting +globin +globing +globins +globoid +globoids +globose +globosely +globoseness +globosity +globous +globs +globular +globularly +globularness +globule +globules +globuliferous +globulin +globulins +glochid +glochidia +glochidiate +glochidium +glochids +glockenspiel +glockenspiels +glogg +gloggs +glom +glomera +glomerate +glomerular +glomerulate +glomerule +glomerules +glomeruli +glomerulus +glomma +glommed +glomming +gloms +glomus +gloom +gloomed +gloomier +gloomiest +gloomily +gloominess +glooming +glooms +gloomy +glop +gloped +gloping +gloppy +glops +gloria +gloriam +gloriana +glorias +gloried +glories +glorification +glorifications +glorified +glorifier +glorifiers +glorifies +glorify +glorifying +gloriole +glorioles +gloriosi +gloriosus +glorious +gloriously +gloriousness +glory +glorying +gloss +glossa +glossae +glossal +glossarial +glossaries +glossarist +glossarists +glossary +glossas +glossed +glosser +glossers +glosses +glossier +glossies +glossiest +glossily +glossiness +glossing +glossitic +glossitis +glossographer +glossographers +glossography +glossolalia +glossolalias +glossolalist +glossolalists +glossopharyngeal +glossy +glottal +glottides +glottis +glottises +glottochronological +glottochronology +gloucester +gloucestershire +glout +glouted +glouting +glouts +glove +gloved +glover +glovers +gloves +gloving +glow +glowed +glower +glowered +glowering +gloweringly +glowers +glowing +glowingly +glows +glowworm +glowworms +gloxinia +gloxinias +gloze +glozed +glozes +glozing +glucagon +gluck +glucocorticoid +glucocorticoids +gluconeogenesis +gluconeogenetic +glucose +glucoside +glucosides +glucosidic +glucosidically +glue +glued +glueing +glues +gluey +gluily +gluiness +gluing +glum +glumaceous +glume +glumes +glumly +glummer +glummest +glumness +glums +gluon +gluons +glut +glutamate +glutamates +glutamic +glutamine +glutamines +glutaraldehyde +glutaraldehydes +gluteal +glutei +gluten +glutenous +glutens +glutethimide +glutethimides +gluteus +glutinosity +glutinous +glutinously +glutinousness +gluts +glutted +glutting +glutton +gluttonies +gluttonize +gluttonized +gluttonizes +gluttonizing +gluttonous +gluttonously +gluttonousness +gluttons +gluttony +glycan +glycans +glyceraldehyde +glyceraldehydes +glyceric +glyceride +glycerides +glycerin +glycerinate +glycerinated +glycerinates +glycerinating +glycerine +glycerines +glycerins +glycerol +glycerolize +glycerolized +glycerolizes +glycerolizing +glycerols +glyceryl +glyceryls +glycin +glycine +glycines +glycins +glycogen +glycogenesis +glycogenetic +glycogenic +glycogenolyses +glycogenolysis +glycogenolytic +glycogens +glycol +glycolic +glycolipid +glycolipids +glycols +glycolyses +glycolysis +glycolytic +glycopeptide +glycopeptides +glycoprotein +glycoproteins +glycosaminoglycan +glycosaminoglycans +glycosidase +glycosidases +glycoside +glycosides +glycosidic +glycosidically +glycosuria +glycosuric +glycosyl +glycosylate +glycosylated +glycosylates +glycosylating +glycosylation +glycosyls +glycyl +glycyls +glyph +glyphic +glyphs +glyptic +glyptics +glyptograph +glyptographer +glyptographers +glyptographic +glyptographical +glyptographs +glyptography +glåma +glögg +glöggs +gmelina +gmelinas +gnar +gnarl +gnarled +gnarling +gnarls +gnarly +gnarr +gnarred +gnarring +gnarrs +gnars +gnash +gnashed +gnashes +gnashing +gnat +gnatcatcher +gnatcatchers +gnathal +gnathic +gnathite +gnathites +gnats +gnatty +gnaw +gnawed +gnawer +gnawers +gnawing +gnaws +gneiss +gneisses +gneissic +gneissoid +gneissose +gniezno +gnocchi +gnome +gnomelike +gnomes +gnomic +gnomish +gnomon +gnomonic +gnomonical +gnomons +gnosis +gnostic +gnosticism +gnostics +gnotobiotic +gnotobiotically +gnu +gnus +go +goa +goad +goaded +goading +goads +goal +goaled +goalie +goalies +goaling +goalkeeper +goalkeepers +goalless +goalpost +goalposts +goals +goaltender +goaltenders +goaltending +goaltendings +goanese +goas +goat +goatee +goateed +goatees +goatfish +goatfishes +goatherd +goatherds +goatish +goatlike +goats +goatsbeard +goatskin +goatskins +goatsucker +goatsuckers +gob +gobbet +gobbets +gobble +gobbled +gobbledegook +gobbledygook +gobbler +gobblers +gobbles +gobbling +gobelin +gobelins +gobi +gobies +goblet +goblets +goblin +goblins +gobo +goboes +gobos +gobs +goby +god +godalmighty +godavari +godchild +godchildren +goddam +goddamn +goddamned +goddamning +goddamns +goddams +goddard +goddaughter +goddaughters +godded +goddess +goddesses +godding +godfather +godfathered +godfathering +godfathers +godforsaken +godhead +godheads +godhood +godhoods +godiva +godless +godlessly +godlessness +godlier +godliest +godlike +godlikeness +godliness +godling +godlings +godly +godmother +godmothered +godmothering +godmothers +godown +godowns +godoxious +godparent +godparents +gods +godsend +godsends +godson +godsons +godspeed +godspeeds +godthåb +godunov +godwit +godwits +goebbels +goer +goering +goers +goes +goethe +goethite +goethites +gofer +gofers +goffer +goffered +goffering +goffers +goggle +goggled +goggler +gogglers +goggles +goggling +goggly +gogh +gogol +gogra +goidelic +going +goings +goiter +goiters +goitre +goitres +goitrogen +goitrogenic +goitrogenicity +goitrous +goiânia +golan +golconda +golcondas +gold +goldbeater +goldbeaters +goldbeating +goldbeatings +goldberg +goldbergian +goldbrick +goldbricked +goldbricker +goldbrickers +goldbricking +goldbricks +goldbug +goldbugs +golden +goldeneye +goldeneyes +goldenly +goldenness +goldenrod +goldenrods +goldenseal +goldenseals +goldfield +goldfields +goldfinch +goldfinches +goldfish +goldfishes +goldilocks +golds +goldsmith +goldsmiths +goldstone +goldstones +goldthread +goldthreads +goldwyn +golem +golems +golf +golfed +golfer +golfers +golfing +golflinks +golfs +golgi +golgotha +golgothas +goliard +goliardic +goliards +goliath +goliaths +gollancz +golliwog +golliwogg +golliwoggs +golliwogs +golly +gombeen +gombeens +gomorrah +gomorrahs +gomphoses +gomphosis +gonad +gonadal +gonadectomies +gonadectomized +gonadectomy +gonadic +gonadotrophic +gonadotrophin +gonadotrophins +gonadotropic +gonadotropin +gonadotropins +gonads +gond +gondi +gondola +gondolas +gondolier +gondoliers +gonds +gondwana +gondwanaland +gondwanalands +gone +goner +goneril +goners +gonfalon +gonfalonier +gonfaloniers +gonfalons +gong +gonged +gonging +gongorism +gongorisms +gongoristic +gongs +gonidia +gonidial +gonidium +gonif +gonifs +goniometer +goniometers +goniometric +goniometrical +goniometry +gonion +gonions +gonococcal +gonococci +gonococcic +gonococcus +gonocyte +gonocytes +gonophore +gonophores +gonophoric +gonophorous +gonopore +gonopores +gonorrhea +gonorrheal +gonorrheic +gonzo +goo +goober +goobers +good +goodbye +goodbyes +gooder +gooders +goodhearted +goodheartedly +goodheartedness +goodie +goodies +goodish +goodlier +goodliest +goodliness +goodly +goodman +goodmen +goodness +goodnight +goodnights +goods +goodwife +goodwill +goodwills +goodwin +goodwives +goody +goodyear +gooey +goof +goofball +goofballs +goofed +goofier +goofiest +goofily +goofiness +goofing +goofproof +goofs +goofy +googol +googolplex +googolplexes +googols +gooier +gooiest +gook +gooks +goombah +goombahs +goon +gooney +gooneys +goonies +goons +goony +goop +goops +goopy +goos +goosander +goosanders +goose +gooseberries +gooseberry +goosed +goosefish +goosefishes +gooseflesh +goosefoot +goosefoots +gooseneck +goosenecked +goosenecks +gooses +goosestep +goosestepped +goosestepping +goosesteps +goosey +goosier +goosiest +goosing +goosy +gopher +gophers +gorbachev +gordian +gordon +gordons +gore +gored +gores +gorge +gorged +gorgeous +gorgeously +gorgeousness +gorger +gorgerin +gorgerins +gorgers +gorges +gorget +gorgets +gorging +gorgon +gorgonian +gorgonians +gorgonize +gorgonized +gorgonizes +gorgonizing +gorgons +gorgonzola +gorier +goriest +gorilla +gorillas +gorily +goriness +goring +gorki +gorky +gormandize +gormandized +gormandizer +gormandizers +gormandizes +gormandizing +gormless +gorp +gorps +gorse +gorses +gorsy +gory +gosh +goshawk +goshawks +goshen +gosiute +gosiutes +gosling +goslings +gospel +gospeler +gospelers +gospeller +gospellers +gospels +gosport +gosports +gossamer +gossamers +gossamery +gossan +gossans +gossip +gossiped +gossiper +gossipers +gossiping +gossipmonger +gossipmongers +gossipries +gossipry +gossips +gossipy +gossypol +gossypols +got +goth +gotha +gotham +gothamite +gothamites +gothenburg +gothic +gothically +gothicism +gothicisms +gothicist +gothicists +gothicize +gothicized +gothicizes +gothicizing +goths +gotland +gotten +gotterdammerung +gotterdämmerung +gotthard +gottwaldov +gouache +gouaches +gouda +gouge +gouged +gouger +gougers +gouges +gouging +goulash +goulashes +gounod +gourami +gouramis +gourd +gourde +gourdes +gourds +gourmand +gourmandise +gourmandises +gourmandism +gourmandize +gourmandized +gourmandizes +gourmandizing +gourmandlike +gourmands +gourmet +gourmets +gout +goutiness +gouts +goutweed +goutweeds +gouty +govern +governable +governance +governances +governed +governess +governesses +governessy +governing +government +governmental +governmentalism +governmentalist +governmentalists +governmentalize +governmentalized +governmentalizes +governmentalizing +governmentally +governmentese +governments +governor +governorate +governorates +governors +governorship +governorships +governs +gowan +gowans +gowany +gown +gowned +gowning +gowns +gownsman +gownsmen +goy +goya +goyim +goyish +goys +goût +graaff +graafian +grab +grabbed +grabber +grabbers +grabbier +grabbiest +grabbiness +grabbing +grabble +grabbled +grabbler +grabblers +grabbles +grabbling +grabby +graben +grabens +grabs +grace +graced +graceful +gracefully +gracefulness +graceless +gracelessly +gracelessness +graces +gracile +gracileness +gracility +gracing +gracioso +graciosos +gracious +graciously +graciousness +grackle +grackles +grad +gradable +gradate +gradated +gradates +gradating +gradation +gradational +gradationally +gradations +grade +graded +gradeless +grader +graders +grades +gradient +gradients +gradin +gradine +gradines +grading +gradings +gradins +gradiometer +gradiometers +grads +gradual +gradualism +gradualist +gradualistic +gradualists +gradually +gradualness +graduals +graduand +graduands +graduate +graduated +graduates +graduating +graduation +graduations +graduator +graduators +graffiti +graffitist +graffitists +graffito +graft +graftage +graftages +grafted +grafter +grafters +grafting +grafts +graham +grahams +grail +grails +grain +grained +grainer +grainers +grainfield +grainfields +grainier +grainiest +graininess +graining +grains +grainy +gram +grama +gramarye +gramaryes +gramas +gramercy +gramicidin +gramineous +gramineousness +graminivorous +gramma +grammar +grammarian +grammarians +grammars +grammas +grammatical +grammaticality +grammatically +grammaticalness +grammatologic +grammatological +grammatologist +grammatologists +grammatology +gramme +grammes +grammies +grammy +gramophone +gramophones +gramp +grampian +gramps +grampus +grampuses +grams +grana +granada +granadilla +granadillas +granaries +granary +grand +grandad +grandaddies +grandaddy +grandads +grandam +grandame +grandames +grandams +grandaunt +grandaunts +grandbabies +grandbaby +grandchild +grandchildren +granddad +granddaddies +granddaddy +granddads +granddaughter +granddaughters +grande +grandee +grandees +grander +grandest +grandeur +grandeurs +grandfather +grandfathered +grandfathering +grandfatherly +grandfathers +grandiloquence +grandiloquent +grandiloquently +grandiose +grandiosely +grandioseness +grandiosity +grandioso +grandkid +grandkids +grandly +grandma +grandmas +grandmaster +grandmasters +grandmother +grandmotherly +grandmothers +grandnephew +grandnephews +grandness +grandniece +grandnieces +grandpa +grandparent +grandparental +grandparenthood +grandparents +grandpas +grands +grandsir +grandsire +grandsires +grandsirs +grandson +grandsons +grandstand +grandstanded +grandstander +grandstanders +grandstanding +grandstands +granduncle +granduncles +grange +granger +grangerism +grangers +granges +granite +granites +graniteware +granitewares +granitic +granitoid +granivorous +grannie +grannies +granny +granola +granolas +granolith +granolithic +granoliths +granophyre +granophyres +granophyric +grant +grantable +granted +grantee +grantees +granter +granters +granting +grantor +grantors +grants +grantsman +grantsmanship +grantsmanships +grantsmen +granular +granularity +granularly +granulate +granulated +granulates +granulating +granulation +granulations +granulative +granulator +granulators +granule +granules +granulite +granulites +granulitic +granulize +granulized +granulizes +granulizing +granulocyte +granulocytes +granulocytic +granulocytopoiesis +granuloma +granulomas +granulomata +granulomatous +granulose +granum +grape +grapefruit +grapefruits +grapes +grapeshot +grapeshots +grapevine +grapevines +grapey +graph +graphed +grapheme +graphemes +graphemic +graphemically +graphemics +graphic +graphical +graphically +graphicness +graphics +graphing +graphite +graphites +graphitic +graphitizable +graphitization +graphitize +graphitized +graphitizes +graphitizing +graphological +graphologies +graphologist +graphologists +graphology +graphotype +graphotypes +graphs +grapier +grapiest +grapiness +grapnel +grapnels +grappa +grappas +grapple +grappled +grappler +grapplers +grapples +grappling +grapplings +graptolite +graptolites +grapy +gras +grasp +graspable +grasped +grasper +graspers +grasping +graspingly +graspingness +grasps +grass +grassed +grasser +grassers +grasses +grassfire +grassfires +grasshopper +grasshoppers +grassier +grassiest +grassing +grassland +grasslands +grasslike +grassplot +grassplots +grassroots +grassy +grat +grata +grate +grated +grateful +gratefully +gratefulness +grater +graters +grates +gratia +gratian +gratias +graticule +graticules +gratification +gratifications +gratified +gratifier +gratifiers +gratifies +gratify +gratifying +gratifyingly +gratin +grating +gratingly +gratings +gratins +gratis +gratitude +gratuities +gratuitous +gratuitously +gratuitousness +gratuity +gratulate +gratulated +gratulates +gratulating +gratulation +gratulations +gratulatory +graupel +graupels +gravamen +gravamens +gravamina +grave +graved +gravedigger +gravediggers +gravel +graveled +graveless +graveling +gravelled +gravelling +gravelly +gravels +gravely +graven +graveness +graver +gravers +graves +graveside +gravesides +gravesite +gravesites +gravest +gravestone +gravestones +graveyard +graveyards +gravid +gravida +gravidae +gravidas +gravidities +gravidity +gravidly +gravidness +gravies +gravimeter +gravimeters +gravimetric +gravimetrical +gravimetrically +gravimetry +graving +gravis +gravisphere +gravispheres +gravitas +gravitate +gravitated +gravitater +gravitaters +gravitates +gravitating +gravitation +gravitational +gravitationally +gravitations +gravitative +gravities +graviton +gravitons +gravity +gravlax +gravure +gravures +gravy +gray +graybeard +graybeards +grayed +grayer +grayest +grayfish +grayfishes +graying +grayish +graylag +graylags +grayling +graylings +grayly +graymail +graymails +grayness +grays +graysbies +graysby +graywacke +graywackes +graz +grazable +graze +grazeable +grazed +grazer +grazers +grazes +grazier +graziers +grazing +grazings +grazioso +grease +greased +greaseless +greasepaint +greasepaints +greaseproof +greaser +greasers +greases +greasewood +greasier +greasiest +greasily +greasiness +greasing +greasy +great +greatcoat +greatcoats +greaten +greatened +greatening +greatens +greater +greatest +greathearted +greatheartedly +greatheartedness +greatly +greatness +greats +greave +greaves +grebe +grebes +grecian +grecianize +grecianized +grecianizes +grecianizing +grecians +grecism +grecisms +grecize +grecized +grecizes +grecizing +greco +gree +greece +greed +greedier +greediest +greedily +greediness +greedy +greeing +greek +greeks +green +greenback +greenbacker +greenbackers +greenbackism +greenbacks +greenbelt +greenbelts +greenbrier +greenbriers +greenbug +greenbugs +greene +greened +greener +greeneries +greenery +greenest +greenfinch +greenfinches +greenflies +greenfly +greengage +greengages +greengrocer +greengroceries +greengrocers +greengrocery +greenhead +greenheads +greenheart +greenhearts +greenhorn +greenhorns +greenhouse +greenhouses +greenie +greenies +greening +greenings +greenish +greenishness +greenland +greenlander +greenlanders +greenlandic +greenlet +greenlets +greenling +greenlings +greenly +greenmail +greenmailer +greenmailers +greenmails +greenmarket +greenmarkets +greenness +greenockite +greenockites +greenroom +greenrooms +greens +greensand +greensands +greenshank +greenshanks +greensick +greensickness +greenside +greenskeeper +greenskeepers +greenstick +greenstone +greenstones +greensward +greenway +greenways +greenwich +greenwood +greenwoods +greeny +grees +greet +greeted +greeter +greeters +greeting +greetings +greets +gregarine +gregarines +gregarinian +gregarious +gregariously +gregariousness +gregorian +gregory +greige +greisen +greisens +gremlin +gremlins +grenada +grenade +grenades +grenadian +grenadians +grenadier +grenadiers +grenadine +grenadines +grendel +grenoble +gresham +gressorial +grew +grewsome +grex +grexs +grey +greyed +greyer +greyest +greyhen +greyhens +greyhound +greyhounds +greying +greyish +greylag +greylags +greyness +greys +gribble +gribbles +grid +gridded +gridder +gridders +griddle +griddlecake +griddlecakes +griddled +griddles +griddling +gridiron +gridirons +gridlock +gridlocked +gridlocking +gridlocks +grids +grief +griefs +grieg +grievance +grievances +grievant +grievants +grieve +grieved +griever +grievers +grieves +grieving +grievingly +grievous +grievously +grievousness +griffin +griffins +griffon +griffons +grift +grifted +grifter +grifters +grifting +grifts +grig +grigri +grigris +grigs +grill +grillage +grillages +grille +grilled +griller +grilleries +grillers +grillery +grilles +grilling +grillroom +grillrooms +grills +grillwork +grilse +grim +grimace +grimaced +grimacer +grimacers +grimaces +grimacing +grimalkin +grimalkins +grime +grimed +grimes +grimier +grimiest +grimily +griminess +griming +grimly +grimm +grimmer +grimmest +grimness +grimsel +grimy +grin +grind +grinder +grinders +grinding +grindingly +grindings +grinds +grindstone +grindstones +gringo +gringos +grinned +grinner +grinners +grinning +grinningly +grins +griot +griots +grip +gripe +griped +griper +gripers +gripes +griping +grippe +gripped +gripper +grippers +grippes +gripping +grippingly +grippy +grips +gripsack +gripsacks +gris +grisaille +grisailles +grise +griselda +griseofulvin +griseofulvins +griseous +grises +grisette +grisettes +grislier +grisliest +grisliness +grisly +grison +grisons +grist +gristle +gristles +gristlier +gristliest +gristliness +gristly +gristmill +gristmills +grit +grith +griths +grits +gritted +grittier +grittiest +grittily +grittiness +gritting +gritty +grivet +grivets +grizzle +grizzled +grizzles +grizzlier +grizzlies +grizzliest +grizzling +grizzly +groan +groaned +groaner +groaners +groaning +groaningly +groans +groat +groats +groatss +grocer +groceries +grocers +grocery +grog +groggier +groggiest +groggily +grogginess +groggy +grogram +grograms +grogs +grogshop +grogshops +groin +groined +groining +groins +grok +grokked +grokking +groks +grolier +grommet +grommets +gromwell +gromwells +groom +groomed +groomer +groomers +grooming +grooms +groomsman +groomsmen +groove +grooved +groover +groovers +grooves +groovier +grooviest +grooviness +grooving +groovy +grope +groped +groper +gropers +gropes +groping +gropingly +gropings +grosbeak +grosbeaks +groschen +grosgrain +grosgrains +gross +grossed +grosser +grossers +grosses +grossest +grossglockner +grossing +grossly +grossness +grossular +grossularite +grossularites +grossulars +grosz +groszy +grot +grotesque +grotesquely +grotesqueness +grotesquerie +grotesqueries +grotesquery +grotesques +grots +grottier +grottiest +grottiness +grotto +grottoes +grottos +grotty +grouch +grouched +grouches +grouchier +grouchiest +grouchily +grouchiness +grouching +grouchy +ground +groundbreaker +groundbreakers +groundbreaking +groundbreakings +grounded +grounder +grounders +groundhog +groundhogs +grounding +groundkeeper +groundkeepers +groundless +groundlessly +groundlessness +groundling +groundlings +groundmass +groundmasses +groundnut +groundnuts +groundout +groundouts +grounds +groundsel +groundsels +groundsheet +groundsheets +groundside +groundsides +groundsill +groundsills +groundskeeper +groundskeepers +groundskeeping +groundsman +groundsmen +groundstroke +groundstrokes +groundswell +groundswells +groundwater +groundwork +group +groupable +grouped +grouper +groupers +groupie +groupies +grouping +groupings +groups +groupthink +groupthinks +grouse +groused +grouser +grousers +grouses +grousing +grout +grouted +grouter +grouters +grouting +grouts +grove +grovel +groveled +groveler +grovelers +groveling +grovelingly +grovelled +grovelling +grovels +groves +grow +grower +growers +growing +growingly +growl +growled +growler +growlers +growlier +growliest +growliness +growling +growlingly +growls +growly +grown +grownup +grownups +grows +growth +growths +groyne +groynes +grub +grubbed +grubber +grubbers +grubbier +grubbiest +grubbily +grubbiness +grubbing +grubby +grubs +grubstake +grubstaked +grubstaker +grubstakers +grubstakes +grubstaking +grudge +grudged +grudger +grudgers +grudges +grudging +grudgingly +grudziadz +gruel +grueling +gruelingly +gruelling +gruesome +gruesomely +gruesomeness +gruff +gruffer +gruffest +gruffly +gruffness +grumble +grumbled +grumbler +grumblers +grumbles +grumbling +grumblingly +grumbly +grummet +grummets +grump +grumped +grumpier +grumpiest +grumpily +grumpiness +grumping +grumps +grumpy +grundy +grunge +grunges +grungier +grungiest +grungy +grunion +grunions +grunt +grunted +grunter +grunters +grunting +gruntingly +gruntle +gruntled +gruntles +gruntling +grunts +grus +grutten +gruyere +gruyère +gryphon +gryphons +grâce +guacamole +guacharo +guacharos +guadalajara +guadalcanal +guadalquivir +guadalupe +guadeloupe +guadeloupian +guadeloupians +guaiac +guaiacol +guaiacols +guaiacs +guaiacum +guaiacums +guam +guamanian +guamanians +guan +guanabara +guanaco +guanacos +guanethidine +guanethidines +guangdong +guangxi +guangzhou +guanidine +guanine +guanines +guano +guanos +guanosine +guanosines +guans +guantánamo +guanylic +guaporé +guar +guarani +guaranies +guaranis +guarantee +guaranteed +guaranteeing +guarantees +guarantied +guaranties +guarantor +guarantors +guaranty +guarantying +guard +guardant +guardants +guarded +guardedly +guardedness +guarder +guarders +guardhouse +guardhouses +guardian +guardians +guardianship +guardianships +guarding +guardmember +guardmembers +guardrail +guardrails +guardroom +guardrooms +guards +guardsman +guardsmen +guarneri +guarnerius +guars +guatemala +guatemalan +guatemalans +guava +guavas +guayaquil +guayule +guayules +gubernator +gubernatorial +gubernators +guck +gudgeon +gudgeons +gudrun +guelder +guelf +guelfs +guelph +guelphs +guenevere +guenon +guenons +guerdon +guerdoned +guerdoning +guerdons +gueridon +gueridons +guerilla +guerillas +guernica +guernsey +guernseys +guerre +guerrilla +guerrillas +guess +guessed +guesser +guessers +guesses +guessing +guesstimate +guesstimated +guesstimates +guesstimating +guesswork +guest +guested +guesthouse +guesthouses +guesting +guestroom +guestrooms +guests +guff +guffaw +guffawed +guffawing +guffaws +guffs +guggenheim +guggle +guggled +guggles +guggling +guianese +guidable +guidance +guide +guideboard +guideboards +guidebook +guidebooks +guided +guideline +guidelines +guidepost +guideposts +guider +guiders +guides +guideway +guideways +guideword +guidewords +guiding +guidon +guidons +guienne +guignol +guild +guildenstern +guilder +guilders +guildhall +guildhalls +guilds +guildship +guildsman +guildsmen +guile +guiled +guileful +guilefully +guilefulness +guileless +guilelessly +guilelessness +guiles +guiling +guillemot +guillemots +guilloche +guilloches +guillotine +guillotined +guillotines +guillotining +guilt +guiltier +guiltiest +guiltily +guiltiness +guiltless +guiltlessly +guiltlessness +guilty +guimpe +guimpes +guinea +guinean +guineans +guineas +guinevere +guinness +guipure +guipures +guiro +guisard +guisards +guise +guises +guitar +guitarfish +guitarfishes +guitarist +guitarists +guitars +gujarat +gujarati +gujaratis +gujerati +gujeratis +gujranwala +gul +gulag +gulags +gular +gulch +gulches +gulden +guldens +gules +guleses +gulf +gulfed +gulfing +gulfs +gulfweed +gulfweeds +gull +gullability +gullable +gullably +gullah +gulled +gullet +gullets +gulley +gullibility +gullible +gullibly +gullied +gullies +gulling +gulliver +gulls +gullwing +gully +gullying +gulosities +gulosity +gulp +gulped +gulper +gulpers +gulping +gulpingly +gulps +guls +gum +gumball +gumballs +gumbo +gumboil +gumboils +gumbos +gumdrop +gumdrops +gumma +gummas +gummata +gummatous +gummed +gummer +gummers +gummier +gummiest +gumminess +gumming +gummite +gummites +gummose +gummoses +gummosis +gummous +gummy +gumption +gums +gumshoe +gumshoed +gumshoeing +gumshoes +gumwood +gumwoods +gun +gunboat +gunboats +guncotton +gundog +gundogs +gunfight +gunfighter +gunfighters +gunfights +gunfire +gunflint +gunflints +gung +gunite +gunites +gunk +gunky +gunlock +gunlocks +gunman +gunmen +gunmetal +gunmetals +gunnar +gunnbjørn +gunned +gunnel +gunnels +gunner +gunnera +gunneras +gunneries +gunners +gunnery +gunnies +gunning +gunnings +gunny +gunnysack +gunnysacks +gunplay +gunpoint +gunpoints +gunpowder +gunpowders +gunroom +gunrooms +gunrunner +gunrunners +gunrunning +guns +gunsel +gunsels +gunship +gunships +gunshot +gunshots +gunslinger +gunslingers +gunslinging +gunsmith +gunsmiths +gunstock +gunstocks +gunther +gunwale +gunwales +guoyu +guoyus +guppies +guppy +gurdies +gurdy +gurgitation +gurgitations +gurgle +gurgled +gurgles +gurgling +gurglingly +gurkha +gurkhas +gurnard +gurnards +gurney +gurneys +gurries +gurry +guru +gurus +gush +gushed +gusher +gushers +gushes +gushier +gushiest +gushily +gushiness +gushing +gushingly +gushy +gusset +gusseted +gusseting +gussets +gussied +gussies +gussy +gussying +gust +gustation +gustations +gustative +gustatorily +gustatory +gustavus +gusted +gustier +gustiest +gustily +gustiness +gusting +gusto +gustoes +gusts +gusty +gut +gutbucket +gutbuckets +gutenberg +guthrie +guthrun +gutless +gutlessly +gutlessness +guts +gutsier +gutsiest +gutsily +gutsiness +gutsy +gutta +guttae +guttate +guttated +guttation +guttations +gutted +gutter +guttered +guttering +gutters +guttersnipe +guttersnipes +guttersnipish +guttier +guttiest +gutting +guttural +gutturalism +gutturality +gutturalization +gutturalizations +gutturalize +gutturalized +gutturalizes +gutturalizing +gutturally +gutturalness +gutturals +gutty +guy +guyana +guyanese +guyed +guyenne +guying +guyot +guyots +guys +guzzle +guzzled +guzzler +guzzlers +guzzles +guzzling +gweduc +gweducs +gwent +gwynedd +gybe +gybed +gybes +gybing +gym +gymkhana +gymkhanas +gymnasia +gymnasium +gymnasiums +gymnast +gymnastic +gymnastically +gymnastics +gymnasts +gymnosophist +gymnosophists +gymnosperm +gymnospermous +gymnosperms +gymnospermy +gyms +gynandries +gynandromorph +gynandromorphic +gynandromorphism +gynandromorphous +gynandromorphy +gynandrous +gynandry +gynarchic +gynarchies +gynarchy +gynecocracies +gynecocracy +gynecocratic +gynecoid +gynecologic +gynecological +gynecologist +gynecologists +gynecology +gynecomastia +gynecopathies +gynecopathy +gynocracies +gynocracy +gynodioecious +gynodioecism +gynoecia +gynoecium +gynogenesis +gynophore +gynophores +gynophoric +gyoza +gyozas +gyoár +gyp +gypped +gypper +gyppers +gypping +gyps +gypseous +gypsied +gypsies +gypsiferous +gypsophila +gypsophilas +gypsophile +gypsophiles +gypsum +gypsums +gypsy +gypsying +gyral +gyrally +gyrate +gyrated +gyrates +gyrating +gyration +gyrational +gyrations +gyrator +gyrators +gyratory +gyre +gyred +gyrene +gyrenes +gyres +gyrfalcon +gyrfalcons +gyri +gyring +gyro +gyrocompass +gyrocompasses +gyrofrequency +gyromagnetic +gyron +gyrons +gyroplane +gyroplanes +gyros +gyroscope +gyroscopes +gyroscopic +gyroscopically +gyrostabilizer +gyrostabilizers +gyrostat +gyrostatic +gyrostatically +gyrostats +gyrus +gyve +gyved +gyves +gyving +gâteau +gâteaux +gît +göta +göteborg +götterdämmerung +götterdämmerungs +göttingen +gütersloh +h +ha +haakon +haarlem +haarlemmermeer +habakkuk +habanera +habaneras +habdalah +habdalahs +habeas +haber +haberdasher +haberdasheries +haberdashers +haberdashery +habergeon +habergeons +habile +habiliment +habiliments +habilitate +habilitated +habilitates +habilitating +habilitation +habilitations +habit +habitability +habitable +habitableness +habitably +habitan +habitans +habitant +habitants +habitat +habitation +habitations +habitats +habited +habiting +habits +habitual +habitually +habitualness +habituate +habituated +habituates +habituating +habituation +habituations +habitude +habitudes +habitus +habitué +habitués +haboob +haboobs +habsburg +habsburgs +hacek +haceks +hachinohe +hachioji +hachure +hachured +hachures +hachuring +hacienda +haciendas +hack +hackable +hackamore +hackamores +hackberries +hackberry +hackbut +hackbuteer +hackbuteers +hackbuts +hackbutter +hackbutters +hacked +hackensack +hacker +hackers +hackie +hackies +hacking +hackle +hackleback +hacklebacks +hackled +hackler +hacklers +hackles +hackling +hackly +hackman +hackmatack +hackmatacks +hackmen +hackney +hackneyed +hackneying +hackneys +hacks +hacksaw +hacksawed +hacksawing +hacksaws +hackwork +had +hadal +haddie +haddock +haddocks +hade +hadean +hades +hadith +hadj +hadjes +hadji +hadjis +hadley +hadn +hadn't +hadrian +hadron +hadronic +hadrons +hadrosaur +hadrosaurs +hadst +hae +haeckel +haed +haeing +haen +haes +haet +haets +hafez +haffet +haffets +hafiz +hafizes +hafnium +haft +haftarah +hafted +hafting +haftorah +hafts +hafun +hag +hagar +hagen +hagerstown +hagfish +hagfishes +haggada +haggadah +haggadic +haggadist +haggadistic +haggadists +haggadoth +haggai +haggard +haggardly +haggardness +haggards +haggis +haggises +haggish +haggishly +haggishness +haggle +haggled +haggler +hagglers +haggles +haggling +hagiarchies +hagiarchy +hagiocracies +hagiocracy +hagiographa +hagiographer +hagiographers +hagiographic +hagiographical +hagiographies +hagiography +hagiolatries +hagiolatry +hagiologic +hagiological +hagiologies +hagiologist +hagiologists +hagiology +hagioscope +hagioscopes +hagioscopic +hagridden +hagride +hagrides +hagriding +hagrode +hags +hague +hah +hahn +hahnemann +hahnium +haick +haida +haidan +haidas +haifa +haig +haighthaicks +haik +haikou +haiks +haiku +haikus +hail +haile +hailed +hailer +hailers +hailing +hails +hailstone +hailstones +hailstorm +hailstorms +haimish +hainan +hainault +hainaut +haiphong +hair +hairball +hairballs +hairbreadth +hairbreadths +hairbrush +hairbrushes +haircloth +haircloths +haircut +haircuts +haircutter +haircutters +haircutting +haircuttings +hairdo +hairdos +hairdresser +hairdressers +hairdressing +hairdressings +hairdryer +hairdryers +haired +hairier +hairiest +hairiness +hairless +hairlessness +hairlike +hairline +hairlines +hairnet +hairnets +hairpiece +hairpieces +hairpin +hairpins +hairs +hairsbreadth +hairsbreadths +hairsplitter +hairsplitters +hairsplitting +hairsplittings +hairspray +hairsprays +hairspring +hairsprings +hairstreak +hairstreaks +hairstyle +hairstyles +hairstyling +hairstylings +hairstylist +hairstylists +hairweave +hairweaver +hairweavers +hairweaves +hairweaving +hairweavings +hairworm +hairworms +hairwove +hairwoven +hairy +haiti +haitian +haitians +haj +hajes +haji +hajis +hajj +hajjes +hajji +hajjis +haka +hakas +hake +hakeem +hakeems +hakenkreuz +hakenkreuzes +hakes +hakim +hakims +hakluyt +hakodate +haku +hakus +halacha +halachas +halakah +halakahs +halakic +halal +halala +halalas +halals +halation +halations +halavah +halavahs +halberd +halberdier +halberdiers +halberds +halbert +halberts +halcyon +halcyons +haldane +hale +haleakala +haled +haleness +haler +halers +haleru +hales +halest +halethorpe +haley +half +halfback +halfbacks +halfbeak +halfbeaks +halfcocked +halfhearted +halfheartedly +halfheartedness +halfness +halfpence +halfpennies +halfpenny +halfpennyworth +halftime +halftimes +halftone +halftones +halftoning +halfway +halfwit +halfwits +halfword +halfwords +halibut +halibuts +halicarnassus +halide +halides +halidom +halidome +halidomes +halidoms +halifax +haling +halite +halitosis +hall +hallah +hallahs +hallandale +hallel +hallels +hallelujah +hallelujahs +halley +halliard +halliards +hallmark +hallmarked +hallmarking +hallmarks +hallo +halloa +halloaed +halloaing +halloas +halloed +halloo +hallooed +hallooing +halloos +hallos +hallow +hallowe +hallowe'en +hallowe'ens +hallowed +halloween +halloweens +hallowing +hallowmas +hallowmases +hallowmass +hallows +halls +hallstatt +halluces +hallucinate +hallucinated +hallucinates +hallucinating +hallucination +hallucinational +hallucinations +hallucinative +hallucinator +hallucinators +hallucinatory +hallucinogen +hallucinogenic +hallucinogens +hallucinosis +hallux +hallway +hallways +halma +halmahera +halo +halobiont +halobionts +halocarbon +halocarbons +halocline +haloclines +haloed +haloes +halogen +halogenate +halogenated +halogenates +halogenating +halogenation +halogenations +halogenous +halogens +haloing +halomorphic +halon +halons +haloperidol +halophile +halophiles +halophilic +halophilous +halophyte +halophytes +halophytic +halos +halothane +halothanes +halsted +halt +halted +haltemprice +halter +halterbreak +halterbreaking +halterbreaks +halterbroke +halterbroken +haltere +haltered +halteres +haltering +halters +halting +haltingly +halts +halva +halvah +halvahs +halvas +halve +halved +halvers +halves +halving +halyard +halyards +halévy +ham +hama +hamadan +hamadryad +hamadryades +hamadryads +hamadryas +hamadryases +hamah +hamal +hamals +hamamatsu +haman +hamartia +hamartias +hamate +hamates +hamburg +hamburger +hamburgers +hamburgs +hamden +hame +hamelin +hameln +hames +hamilcar +hamilton +hamiltonian +hamiltonians +hamite +hamites +hamitic +hamitics +hamito +hamlet +hamlets +hamlin +hammal +hammals +hammarskjöld +hammed +hammer +hammered +hammerer +hammerers +hammerfest +hammerhead +hammerheads +hammering +hammerkop +hammerkops +hammerless +hammerlock +hammerlocks +hammers +hammerstein +hammertoe +hammertoes +hammier +hammiest +hammily +hamminess +hamming +hammock +hammocks +hammond +hammurabi +hammy +hamper +hampered +hampering +hampers +hampshire +hampton +hams +hamster +hamsters +hamstring +hamstringing +hamstrings +hamstrung +hamtramck +hamuli +hamulus +hamza +hamzah +hamzahs +hamzas +han +hanau +hancock +hand +handan +handbag +handbags +handball +handballs +handbarrow +handbarrows +handbill +handbills +handblown +handbook +handbooks +handbrake +handbrakes +handbreadth +handbreadths +handcar +handcars +handcart +handcarts +handclap +handclaps +handclasp +handclasps +handcraft +handcrafted +handcrafter +handcrafters +handcrafting +handcraftmanship +handcrafts +handcraftsman +handcraftsmanship +handcraftsmen +handcuff +handcuffed +handcuffing +handcuffs +handed +handedly +handedness +handel +handelian +hander +handers +handfast +handfasts +handful +handfuls +handgrip +handgrips +handgun +handguns +handheld +handhelds +handhold +handholding +handholdings +handholds +handicap +handicapped +handicapper +handicappers +handicapping +handicaps +handicraft +handicrafter +handicrafters +handicrafts +handicraftsman +handicraftsmen +handicraftswoman +handicraftswomen +handier +handies +handiest +handily +handiness +handing +handiwork +handkerchief +handkerchiefs +handkerchieves +handle +handleable +handlebar +handlebars +handled +handleless +handler +handlers +handles +handless +handlin +handling +handlings +handlist +handlists +handloom +handlooms +handmade +handmaid +handmaiden +handmaidens +handmaids +handoff +handoffs +handout +handouts +handpick +handpicked +handpicking +handpicks +handpress +handpresses +handprint +handprints +handrail +handrails +hands +handsaw +handsaws +handsbreadth +handsel +handseled +handseling +handselled +handselling +handsels +handset +handsets +handsful +handshake +handshakes +handshaking +handsome +handsomely +handsomeness +handsomer +handsomest +handspike +handspikes +handspring +handsprings +handstand +handstands +handwheel +handwheels +handwork +handworker +handworkers +handwoven +handwringer +handwringers +handwringing +handwringings +handwrite +handwrites +handwriting +handwritings +handwritten +handwrote +handwrought +handy +handyman +handymen +hang +hangable +hangar +hangars +hangchou +hangchow +hangdog +hangdogs +hanged +hanger +hangers +hanging +hangings +hangman +hangmen +hangnail +hangnails +hangout +hangouts +hangover +hangovers +hangs +hangtag +hangtags +hangzhou +hank +hanker +hankered +hankerer +hankerers +hankering +hankerings +hankers +hankie +hankies +hanks +hanky +hannibal +hanno +hannover +hanoi +hanover +hanoverian +hanoverians +hans +hansa +hansard +hansards +hanse +hanseatic +hansel +hanseled +hanseling +hanselled +hanselling +hansels +hansen +hansen's +hanses +hansom +hansoms +hantan +hantavirus +hanukah +hanukkah +hanukkahs +hanuman +hanumans +hao +haole +haoles +haos +hap +hapax +haphazard +haphazardly +haphazardness +haphazardry +haphtarah +haphtaroth +haphtoros +haphtorot +haphtoroth +hapless +haplessly +haplessness +haplite +haplites +haploid +haploidies +haploids +haploidy +haplology +haplont +haplonts +haplosis +haply +happed +happen +happenchance +happenchances +happened +happening +happenings +happens +happenstance +happenstances +happi +happier +happiest +happily +happiness +happinesses +happing +happy +haps +hapsburg +hapsburgs +hapten +haptene +haptenes +haptenic +haptens +haptic +haptoglobin +haptoglobins +hara +haran +harangue +harangued +haranguer +haranguers +harangues +haranguing +harappa +harare +harass +harassed +harasser +harassers +harasses +harassing +harassment +harassments +harbinger +harbingered +harbingering +harbingers +harbor +harborage +harborages +harbored +harborer +harborers +harborful +harboring +harborless +harbormaster +harbormasters +harbors +harbour +harboured +harbourer +harbourers +harbouring +harbours +hard +hardback +hardbacks +hardball +hardballs +hardboard +hardboards +hardboiled +hardboot +hardboots +hardbound +hardbounds +hardcase +hardcopies +hardcopy +hardcore +hardcover +hardcovers +hardecanute +hardedge +hardedges +harden +hardened +hardener +hardeners +hardening +hardenings +hardens +harder +hardest +hardfisted +hardhack +hardhacks +hardhanded +hardhandedness +hardhat +hardhats +hardhead +hardheaded +hardheadedly +hardheadedness +hardheads +hardhearted +hardheartedly +hardheartedness +hardicanute +hardier +hardies +hardiest +hardihood +hardily +hardiment +hardiness +hardly +hardmouthed +hardness +hardnesses +hardpan +hardpans +hardscrabble +hardscrabbles +hardship +hardships +hardstand +hardstanding +hardstands +hardtack +hardtacks +hardtop +hardtops +hardware +hardwire +hardwired +hardwires +hardwiring +hardwood +hardwoods +hardworking +hardy +hare +harebell +harebells +harebrain +harebrained +harebrains +hared +harelip +harelipped +harelips +harem +harems +hares +haricot +haricots +harijan +harijans +haring +hark +harked +harken +harkened +harkening +harkens +harking +harks +harlem +harlemite +harlemites +harlequin +harlequinade +harlequinades +harlequins +harlot +harlotries +harlotry +harlots +harlow +harm +harmattan +harmattans +harmed +harmer +harmers +harmful +harmfully +harmfulness +harming +harmless +harmlessly +harmlessness +harmolodic +harmonic +harmonica +harmonically +harmonicas +harmonics +harmonies +harmonious +harmoniously +harmoniousness +harmonist +harmonistic +harmonistically +harmonists +harmonium +harmoniums +harmonization +harmonizations +harmonize +harmonized +harmonizer +harmonizers +harmonizes +harmonizing +harmony +harms +harness +harnessed +harnesser +harnessers +harnesses +harnessing +harney +harold +harp +harped +harper +harpers +harpies +harping +harpist +harpists +harpoon +harpooned +harpooner +harpooners +harpooning +harpoons +harps +harpsichord +harpsichordist +harpsichordists +harpsichords +harpy +harquebus +harquebuses +harquebusier +harquebusiers +harran +harridan +harridans +harried +harrier +harriers +harries +harriman +harrington +harris +harrisburg +harrison +harrisonburg +harrow +harrowed +harrower +harrowers +harrowing +harrows +harrumph +harrumphed +harrumphing +harrumphs +harry +harrying +harsh +harshen +harshened +harshening +harshens +harsher +harshest +harshly +harshness +harslet +harslets +hart +hartebeest +hartebeests +hartford +harts +hartshorn +hartshorns +harum +haruspex +haruspication +haruspications +haruspices +harvard +harvest +harvestability +harvestable +harvested +harvester +harvesters +harvesting +harvestman +harvestmen +harvests +harvesttime +harvesttimes +harvey +haryana +harz +has +hasdrubal +hasenpfeffer +hasenpfeffers +hash +hashana +hashanah +hashed +hasheesh +hashemite +hashemites +hasher +hashers +hashes +hashimite +hashimites +hashing +hashish +hashishes +hashona +hashonah +hasid +hasidic +hasidim +hasidism +haslet +haslets +hasmonaean +hasmonean +hasn +hasn't +hasp +hasped +hasping +hasps +hassid +hassium +hassle +hassled +hassles +hassling +hassock +hassocks +hast +hasta +hastate +hastately +haste +hasted +hasten +hastened +hastener +hasteners +hastening +hastens +hastes +hastier +hastiest +hastily +hastiness +hasting +hastings +hasty +hat +hatband +hatbands +hatbox +hatboxes +hatch +hatchability +hatchable +hatchback +hatchbacks +hatcheck +hatchecks +hatched +hatchel +hatcheled +hatcheling +hatchelled +hatchelling +hatchels +hatcher +hatcheries +hatchers +hatchery +hatches +hatchet +hatchets +hatching +hatchings +hatchling +hatchlings +hatchment +hatchments +hatchway +hatchways +hate +hated +hateful +hatefully +hatefulness +hater +haters +hates +hath +hating +hatless +hatmaker +hatmakers +hatpin +hatpins +hatred +hatreds +hats +hatshepsut +hatted +hatter +hatteras +hatters +hattiesburg +hatting +haubergeon +haubergeons +hauberk +hauberks +haugh +haughs +haughtier +haughtiest +haughtily +haughtiness +haughty +haul +haulage +haulages +hauled +hauler +haulers +hauling +haulm +haulms +hauls +haunch +haunches +haunt +haunted +haunter +haunters +haunting +hauntingly +haunts +hauraki +hausa +hausas +hausfrau +hausfraus +haustella +haustellate +haustellum +haustoria +haustorial +haustorium +haut +hautbois +hautboy +hautboys +haute +hauteur +havana +havanan +havanans +havant +havasupai +havasupais +havdalah +havdalahs +have +haveli +havelock +havelocks +haven +haven't +havened +havening +havens +haver +havered +havering +havers +haversack +haversacks +haversian +haves +having +havoc +havocked +havocking +havocs +havre +haw +hawaii +hawaiian +hawaiians +hawed +hawfinch +hawfinches +hawing +hawk +hawked +hawker +hawkers +hawkeye +hawkeyes +hawking +hawkins +hawkish +hawkishly +hawkishness +hawkmoth +hawkmoths +hawks +hawksbill +hawksbills +hawkshaw +hawkshaws +hawkweed +hawkweeds +haworthia +haworthias +haws +hawse +hawsehole +hawseholes +hawser +hawsers +hawses +hawthorn +hawthorne +hawthorns +hay +haycock +haycocks +haydn +hayed +hayer +hayers +hayes +hayfield +hayfields +hayfork +hayforks +haying +haylage +haylages +hayloft +haylofts +haymaker +haymakers +haymaking +haymow +haymows +hayrack +hayracks +hayrick +hayricks +hayride +hayrides +hays +hayseed +hayseeds +haystack +haystacks +haywire +hazan +hazanim +hazard +hazarded +hazarding +hazardous +hazardously +hazardousness +hazards +haze +hazed +hazel +hazelnut +hazelnuts +hazels +hazer +hazers +hazes +hazier +haziest +hazily +haziness +hazing +hazings +hazleton +hazlitt +hazy +hazzan +hazzans +he +he'd +he'll +he's +head +headache +headaches +headachy +headband +headbands +headboard +headboards +headcheese +headcount +headcounter +headcounters +headcounts +headdress +headdresses +headed +headedness +header +headers +headfast +headfasts +headfirst +headforemost +headful +headfuls +headgate +headgates +headgear +headhunt +headhunted +headhunter +headhunters +headhunting +headhunts +headier +headiest +headily +headiness +heading +headings +headlamp +headlamps +headland +headlands +headless +headlessness +headlight +headlights +headline +headlined +headliner +headliners +headlines +headlining +headlock +headlocks +headlong +headman +headmaster +headmasters +headmastership +headmen +headmistress +headmistresses +headmost +headnote +headnotes +headphone +headphones +headpiece +headpieces +headpin +headpins +headquarter +headquartered +headquartering +headquarters +headrace +headraces +headrest +headrests +headroom +heads +headsail +headsails +headscarf +headscarfs +headscarves +headset +headsets +headshake +headshakes +headshaking +headship +headships +headshot +headshots +headshrinker +headshrinkers +headsman +headsmen +headspace +headspaces +headspring +headsprings +headstall +headstalls +headstand +headstands +headstock +headstocks +headstone +headstones +headstream +headstreams +headstrong +headwaiter +headwaiters +headwall +headwalls +headwater +headwaters +headway +headwear +headwears +headwind +headwinds +headword +headwords +headwork +headworker +headworkers +heady +heal +healable +healed +healer +healers +healing +heals +health +healthful +healthfully +healthfulness +healthier +healthiest +healthily +healthiness +healths +healthy +heap +heaped +heaping +heaps +heapsort +hear +hearable +heard +hearer +hearers +hearing +hearings +hearken +hearkened +hearkening +hearkens +hears +hearsay +hearse +hearsed +hearses +hearsing +heart +heartache +heartaches +heartbeat +heartbeats +heartbreak +heartbreaker +heartbreakers +heartbreaking +heartbreakingly +heartbreaks +heartbroken +heartbrokenly +heartbrokenness +heartburn +heartburning +hearted +heartedly +heartedness +hearten +heartened +heartening +hearteningly +heartens +heartfelt +hearth +hearthrug +hearthrugs +hearths +hearthside +hearthsides +hearthstone +hearthstones +heartier +hearties +heartiest +heartily +heartiness +hearting +heartland +heartlands +heartleaf +heartleafs +heartless +heartlessly +heartlessness +heartrending +heartrendingly +hearts +heartsease +heartseases +heartsick +heartsickness +heartsome +heartsomely +heartsore +heartstring +heartstrings +heartthrob +heartthrobs +heartwarming +heartwarmingly +heartwood +heartworm +heartworms +hearty +heat +heatable +heated +heatedly +heater +heaters +heath +heathen +heathendom +heathenish +heathenishly +heathenishness +heathenism +heathenize +heathenized +heathenizes +heathenizing +heathenry +heathens +heather +heathers +heathery +heathless +heathlike +heathrow +heaths +heathy +heating +heatless +heatproof +heats +heatstroke +heatstrokes +heave +heaved +heaven +heavenliness +heavenly +heavens +heavenward +heavenwards +heaver +heavers +heaves +heavier +heavies +heaviest +heavily +heaviness +heaving +heaviside +heavy +heavyhearted +heavyheartedly +heavyheartedness +heavyset +heavyweight +heavyweights +hebdomad +hebdomadal +hebdomadally +hebdomads +hebe +hebei +hebephrenia +hebephrenias +hebephrenic +hebetate +hebetated +hebetates +hebetating +hebetation +hebetations +hebetative +hebetude +hebetudes +hebetudinous +hebraic +hebraical +hebraically +hebraism +hebraist +hebraistic +hebraistical +hebraistically +hebraists +hebraization +hebraizations +hebraize +hebraized +hebraizes +hebraizing +hebrew +hebrews +hebridean +hebrideans +hebrides +hebron +hecate +hecatomb +hecatombs +heck +heckelphone +heckelphones +heckle +heckled +heckler +hecklers +heckles +heckling +heckuva +hectare +hectares +hectic +hectically +hectoampere +hectoamperes +hectobecquerel +hectobecquerels +hectocandela +hectocandelas +hectocotyli +hectocotylus +hectocoulomb +hectocoulombs +hectofarad +hectofarads +hectogram +hectograms +hectograph +hectographed +hectographic +hectographically +hectographing +hectographs +hectohenries +hectohenry +hectohenrys +hectohertz +hectojoule +hectojoules +hectokelvin +hectokelvins +hectoliter +hectoliters +hectolumen +hectolumens +hectolux +hectometer +hectometers +hectomole +hectomoles +hectonewton +hectonewtons +hectoohm +hectoohms +hectopascal +hectopascals +hector +hectoradian +hectoradians +hectored +hectoring +hectors +hectosecond +hectoseconds +hectosiemens +hectosievert +hectosieverts +hectosteradian +hectosteradians +hectotesla +hectoteslas +hectovolt +hectovolts +hectowatt +hectowatts +hectoweber +hectowebers +hecuba +hedda +heddle +heddles +heder +heders +hedge +hedged +hedgehog +hedgehogs +hedgehop +hedgehopped +hedgehopper +hedgehoppers +hedgehopping +hedgehops +hedgepig +hedgepigs +hedger +hedgerow +hedgerows +hedgers +hedges +hedging +hedgingly +hedgy +hedjaz +hedonic +hedonically +hedonics +hedonism +hedonist +hedonistic +hedonistically +hedonists +hee +heebie +heed +heeded +heedful +heedfully +heedfulness +heeding +heedless +heedlessly +heedlessness +heeds +heehaw +heehawed +heehawing +heehaws +heel +heelball +heelballs +heeled +heeler +heelers +heeling +heelless +heelpiece +heelpieces +heelpost +heelposts +heels +heeltap +heeltaps +heelwork +heelworks +heft +hefted +heftier +heftiest +heftily +heftiness +hefting +hefts +hefty +hegang +hegari +hegaris +hegel +hegelian +hegelianism +hegelians +hegemonic +hegemonies +hegemonism +hegemonist +hegemonists +hegemony +hegira +hegiras +heidelberg +heifer +heifers +heigh +height +heighten +heightened +heightener +heighteners +heightening +heightens +heights +heilbronn +heilongjiang +heilungkiang +heimish +heimlich +heinie +heinies +heinous +heinously +heinousness +heir +heirdom +heirdoms +heiress +heiresses +heirless +heirloom +heirlooms +heirs +heirship +heirships +heisenberg +heist +heisted +heisting +heists +hejaz +hejira +hejiras +hekate +hekla +held +heldentenor +heldentenors +helen +helena +helens +helgoland +heliacal +heliacally +heliborne +helical +helically +helices +helicoid +helicoidal +helicoids +helicon +helicons +helicopter +helicoptered +helicoptering +helicopters +helicultural +heliculturalist +heliculturalists +heliculture +heligoland +heliocentric +heliocentrical +heliocentricity +heliogabalus +heliograph +heliographed +heliographer +heliographers +heliographic +heliographing +heliographs +heliography +heliolatrous +heliolatry +heliometer +heliometers +heliometric +heliometrical +heliometrically +heliometry +heliopolis +helios +helioseismology +heliosphere +heliospheres +heliostat +heliostats +heliotactic +heliotaxis +heliotaxises +heliotherapies +heliotherapy +heliotrope +heliotropes +heliotropic +heliotropically +heliotropin +heliotropins +heliotropism +heliotype +heliotyped +heliotypes +heliotypic +heliotyping +heliotypy +heliozoan +heliozoans +heliozoic +helipad +helipads +heliport +heliports +helistop +helistops +helium +helix +helixes +hell +hellacious +helladic +hellas +hellbender +hellbenders +hellbox +hellboxes +hellbroth +hellcat +hellcats +helldiver +helldivers +hellebore +hellebores +helled +hellene +hellenes +hellenian +hellenians +hellenic +hellenism +hellenist +hellenistic +hellenistical +hellenists +hellenization +hellenizations +hellenize +hellenized +hellenizer +hellenizers +hellenizes +hellenizing +heller +helleri +helleries +hellers +hellespont +hellfire +hellfires +hellgrammite +hellgrammites +hellhole +hellholes +hellhound +hellhounds +helling +hellion +hellions +hellish +hellishly +hellishness +hello +helloed +helloes +helloing +hellos +hells +helluva +helm +helmed +helmet +helmeted +helmeting +helmetlike +helmets +helming +helminth +helminthiases +helminthiasis +helminthic +helminthics +helminthologist +helminthologists +helminthology +helminths +helms +helmsman +helmsmanship +helmsmen +helo +helos +helot +helotism +helotisms +helotries +helotry +helots +help +helped +helper +helpers +helpful +helpfully +helpfulness +helping +helpings +helpless +helplessly +helplessness +helpmate +helpmates +helpmeet +helpmeets +helps +helsingborg +helsingør +helsinki +helter +helve +helves +helvetia +helvetian +helvetians +helvetic +helvetica +helvetii +hem +hemacytometer +hemacytometers +hemagglutinate +hemagglutinated +hemagglutinates +hemagglutinating +hemagglutination +hemagglutinations +hemagglutinin +hemagglutinins +hemal +hemangioma +hemangiomas +hemangiomata +hemaphereses +hemapheresis +hematein +hemateins +hematic +hematics +hematin +hematinic +hematinics +hematins +hematite +hematites +hematitic +hematoblast +hematoblastic +hematoblasts +hematocrit +hematocrits +hematogenesis +hematogenetic +hematogenic +hematogenous +hematologic +hematological +hematologically +hematologist +hematologists +hematology +hematolysis +hematoma +hematomas +hematomata +hematophagous +hematopoiesis +hematopoietic +hematoporphyrin +hematoporphyrins +hematothermia +hematoxylin +hematoxylins +hematozoa +hematozoal +hematozoic +hematozoon +hematuria +hematurias +hematuric +heme +hemelytra +hemelytron +hemeralopia +hemeralopias +hemeralopic +hemerocallis +hemerocallises +hemes +hemialgia +hemialgias +hemic +hemicellulose +hemicelluloses +hemichordate +hemichordates +hemicycle +hemicycles +hemidemisemiquaver +hemidemisemiquavers +hemihedral +hemihydrate +hemihydrated +hemihydrates +hemimetabolic +hemimetabolism +hemimetabolous +hemimorphic +hemimorphism +hemimorphite +hemimorphites +hemin +hemingway +hemins +hemiola +hemiolas +hemiparasite +hemiparasites +hemiparasitic +hemiplegia +hemiplegias +hemiplegic +hemiplegics +hemipteran +hemipterans +hemipterous +hemisphere +hemispheres +hemispheric +hemispherical +hemispherically +hemistich +hemistichs +hemline +hemlines +hemlock +hemlocks +hemmed +hemmer +hemmers +hemming +hemochromatosis +hemocoel +hemocoels +hemocyanin +hemocyanins +hemocyte +hemocytes +hemodialyses +hemodialysis +hemodynamic +hemodynamically +hemodynamics +hemoflagellate +hemoflagellates +hemoglobin +hemoglobinopathies +hemoglobinopathy +hemoglobins +hemoglobinuria +hemoglobinurias +hemoglobinuric +hemolymph +hemolymphatic +hemolymphs +hemolysin +hemolysins +hemolysis +hemolytic +hemolyze +hemolyzed +hemolyzes +hemolyzing +hemophilia +hemophiliac +hemophiliacs +hemophilic +hemophobia +hemophobic +hemopoiesis +hemopoietic +hemoprotein +hemoproteins +hemoptysis +hemorrhage +hemorrhaged +hemorrhages +hemorrhagic +hemorrhaging +hemorrhoid +hemorrhoidal +hemorrhoidectomies +hemorrhoidectomy +hemorrhoids +hemosiderin +hemosiderins +hemostasia +hemostasis +hemostat +hemostatic +hemostatics +hemostats +hemp +hempen +hemps +hems +hemstitch +hemstitched +hemstitcher +hemstitchers +hemstitches +hemstitching +hen +henbane +henbanes +henbit +henbits +hence +henceforth +henceforward +henchman +henchmen +hencoop +hencoops +hendecasyllabic +hendecasyllabics +hendecasyllable +hendecasyllables +hendiadys +hendiadyses +hendrix +henequen +henequens +henequin +henequins +hengist +henhouse +henhouses +henna +hennaed +hennaing +hennas +henneries +hennery +hennish +hennishly +hennishness +henotheism +henotheist +henotheistic +henotheists +henpeck +henpecked +henpecking +henpecks +henries +henry +henrys +hens +hent +hented +henting +hents +hep +heparin +heparinize +heparinized +heparinizes +heparinizing +hepatic +hepatica +hepaticas +hepatics +hepatitides +hepatitis +hepatocellular +hepatocyte +hepatocytes +hepatoma +hepatomas +hepatomata +hepatomegalies +hepatomegaly +hepatotoxic +hepatotoxicity +hepatotoxin +hepatotoxins +hepcat +hepcats +hephaestos +hephaestus +hepper +heppest +hepplewhite +heptachlor +heptachlors +heptad +heptads +heptagon +heptagonal +heptagons +heptahedra +heptahedral +heptahedron +heptahedrons +heptameter +heptameters +heptane +heptanes +heptarchic +heptarchical +heptarchies +heptarchy +heptastich +heptastiches +heptateuch +heptathlon +heptathlons +heptavalent +heptose +heptoses +her +hera +heraclea +heracles +heraclitean +heraclitus +heraclius +herakles +herald +heralded +heraldic +heraldically +heralding +heraldist +heraldists +heraldries +heraldry +heralds +herb +herbaceous +herbage +herbal +herbalist +herbalists +herbals +herbaria +herbarium +herbariums +herbed +herbert +herbicidal +herbicidally +herbicide +herbicides +herbivore +herbivores +herbivorous +herbivorously +herblike +herbs +herby +herculaneum +herculean +hercules +hercynian +herd +herded +herder +herders +herdic +herdics +herding +herdlike +herds +herdsman +herdsmen +here +hereabout +hereabouts +hereafter +hereaway +hereaways +hereby +hereditament +hereditaments +hereditarian +hereditarianism +hereditarians +hereditarily +hereditariness +hereditary +heredities +hereditist +hereditists +heredity +hereford +herefords +herein +hereinabove +hereinafter +hereinbefore +hereinbelow +hereinto +hereof +hereon +herero +hereros +heresiarch +heresiarchs +heresies +heresy +heretic +heretical +heretically +hereticalness +heretics +hereto +heretofore +hereunder +hereunto +hereupon +hereward +herewith +heriot +heriots +heritabilities +heritability +heritable +heritably +heritage +heritages +heritor +heritors +heriz +herizes +herky +herl +herls +herm +herma +hermae +hermai +herman +hermaphrodism +hermaphrodite +hermaphrodites +hermaphroditic +hermaphroditically +hermaphroditism +hermaphroditus +hermas +hermatypic +hermeneutic +hermeneutical +hermeneutically +hermeneutics +hermeneutist +hermeneutists +hermes +hermetic +hermetical +hermetically +hermeticism +hermetism +hermetist +hermetists +hermit +hermitage +hermitages +hermitian +hermitic +hermitical +hermitically +hermitism +hermits +hermon +hermosillo +herms +hern +hernia +herniae +hernial +hernias +herniate +herniated +herniates +herniating +herniation +herniations +herns +hero +herod +herodas +herodian +herodias +herodotus +heroes +heroic +heroical +heroically +heroicalness +heroicomic +heroicomical +heroics +heroin +heroine +heroines +heroinism +heroinisms +heroism +heron +heronries +heronry +herons +heros +herpes +herpesvirus +herpesviruses +herpetic +herpetologic +herpetological +herpetologically +herpetologist +herpetologists +herpetology +herr +herren +herrenvolk +herrenvolks +herrick +herring +herringbone +herringboned +herringbones +herringboning +herrings +hers +herschel +herself +hershey +herstories +herstory +hertfordshire +hertz +hertzian +hertzsprung +herzegovina +herzegovinian +herzegovinians +heshvan +heshvans +heshwan +heshwans +hesiod +hesitance +hesitancies +hesitancy +hesitant +hesitantly +hesitate +hesitated +hesitater +hesitaters +hesitates +hesitating +hesitatingly +hesitation +hesitations +hesperian +hesperidean +hesperides +hesperidia +hesperidian +hesperidin +hesperidins +hesperidium +hesperus +hess +hesse +hessian +hessians +hessite +hessites +hessonite +hessonites +hest +hestia +hests +het +hetaera +hetaerae +hetaeras +hetaeric +hetaira +hetairai +hetairas +hetero +heteroatom +heteroatoms +heterocarpies +heterocarpous +heterocarpy +heterocercal +heterochromatic +heterochromatin +heterochromatins +heterochromatism +heterochromatisms +heterochromosome +heterochromosomes +heterocycle +heterocycles +heterocyclic +heterocyst +heterocysts +heterodox +heterodoxies +heterodoxy +heterodyne +heterodyned +heterodynes +heterodyning +heteroecious +heteroecism +heterogamete +heterogametes +heterogametic +heterogamic +heterogamies +heterogamous +heterogamy +heterogeneity +heterogeneous +heterogeneously +heterogeneousness +heterogenic +heterogenous +heterogeny +heterogonic +heterogonous +heterogony +heterograft +heterografts +heterogynous +heterokaryon +heterokaryons +heterokaryotic +heterolecithal +heterologous +heterologously +heterology +heterolyses +heterolysis +heterolytic +heteromerous +heteromorphic +heteromorphism +heteronomous +heteronomously +heteronomy +heteronym +heteronymous +heteronyms +heteroousian +heterophil +heterophile +heterophonic +heterophony +heterophyllous +heterophylly +heterophyte +heterophytes +heterophytic +heteroplastic +heteroplasties +heteroplasty +heteroploid +heteroploids +heteroploidy +heteropterous +heteros +heterosexism +heterosexual +heterosexuality +heterosexually +heterosexuals +heterosis +heterosporous +heterospory +heterostyled +heterostylous +heterostyly +heterotactic +heterotactous +heterotaxes +heterotaxia +heterotaxias +heterotaxies +heterotaxis +heterotaxy +heterothallic +heterothallism +heterotic +heterotopia +heterotopias +heterotopic +heterotopies +heterotopy +heterotroph +heterotrophic +heterotrophically +heterotrophs +heterotrophy +heterotypic +heterotypical +heterousian +heterozygosis +heterozygosity +heterozygote +heterozygotes +heterozygous +heth +hetman +hetmans +heulandite +heulandites +heuristic +heuristically +heuristics +hew +hewed +hewer +hewers +hewing +hewn +hews +hex +hexachlorethane +hexachlorethanes +hexachloride +hexachloroethane +hexachloroethanes +hexachlorophene +hexachord +hexachords +hexad +hexadecimal +hexadecimally +hexadecimals +hexadic +hexads +hexafluoride +hexagon +hexagonal +hexagonally +hexagons +hexagram +hexagrams +hexahedra +hexahedral +hexahedron +hexahedrons +hexahydrate +hexamerism +hexamerous +hexameter +hexameters +hexamethonium +hexamethylenetetramine +hexamethylenetetramines +hexametric +hexametrical +hexane +hexaploid +hexaploids +hexaploidy +hexapod +hexapodous +hexapods +hexastyle +hexateuch +hexavalent +hexed +hexer +hexerei +hexereis +hexers +hexes +hexing +hexosan +hexosans +hexose +hexoses +hexyl +hexylresorcinol +hexylresorcinols +hexyls +hey +heyday +heydays +heywood +hezekiah +hi +hialeah +hiatal +hiatus +hiatuses +hiawatha +hibachi +hibachis +hibernacula +hibernaculum +hibernal +hibernate +hibernated +hibernates +hibernating +hibernation +hibernations +hibernator +hibernators +hibernia +hibernian +hibernians +hiberno +hibiscus +hibiscuses +hic +hiccough +hiccoughed +hiccoughing +hiccoughs +hiccup +hiccuped +hiccuping +hiccupped +hiccupping +hiccups +hick +hickey +hickeys +hickories +hickory +hicks +hid +hidalgo +hidalgos +hidatsa +hidatsas +hidden +hiddenite +hiddenites +hiddenness +hide +hideaway +hideaways +hidebound +hided +hideosity +hideous +hideously +hideousness +hideout +hideouts +hider +hiders +hides +hiding +hidings +hidroses +hidrosis +hidrotic +hie +hied +hieing +hiemal +hierapolis +hierarch +hierarchal +hierarchic +hierarchical +hierarchically +hierarchies +hierarchization +hierarchizations +hierarchize +hierarchized +hierarchizes +hierarchizing +hierarchs +hierarchy +hieratic +hieratically +hierocracies +hierocracy +hierocratic +hierocratical +hierodule +hierodules +hierodulic +hieroglyph +hieroglyphic +hieroglyphical +hieroglyphically +hieroglyphics +hieroglyphs +hierologies +hierologist +hierologists +hierology +hierophant +hierophantic +hierophants +hies +hifalutin +higashiosaka +higgle +higgled +higgledy +higgler +higglers +higgles +higgling +high +highball +highballed +highballing +highballs +highbinder +highbinders +highborn +highboy +highboys +highbred +highbrow +highbrowed +highbrowism +highbrows +highbush +highchair +highchairs +higher +highest +highfalutin +highfaluting +highflier +highfliers +highflyer +highflyers +highflying +highhanded +highhandedly +highhandedness +highjack +highjacked +highjacker +highjackers +highjacking +highjacks +highland +highlander +highlanders +highlands +highlife +highlifer +highlifers +highlifes +highlight +highlighted +highlighter +highlighters +highlighting +highlights +highline +highly +highness +highnesses +highroad +highroads +highs +hight +hightail +hightailed +hightailing +hightails +highway +highwayman +highwaymen +highways +hijack +hijacked +hijacker +hijackers +hijacking +hijackings +hijacks +hijiki +hijikis +hijinks +hike +hiked +hiker +hikers +hikes +hiking +hila +hilar +hilarious +hilariously +hilariousness +hilarities +hilarity +hilary +hilbert +hildebrand +hildesheim +hilding +hildings +hill +hillbillies +hillbilly +hillcrest +hillcrests +hilled +hillel +hiller +hillers +hilliard +hillier +hilliest +hilliness +hilling +hillock +hillocks +hillocky +hills +hillscape +hillside +hillsides +hilltop +hilltops +hilly +hilo +hilt +hilted +hilton +hilts +hilum +hilversum +him +himachal +himalaya +himalayan +himalayans +himalayas +himalia +himatia +himation +himations +himmler +himself +himyarite +himyarites +himyaritic +hin +hinayana +hinayanist +hinayanistic +hinayanists +hind +hindbrain +hindbrains +hindemith +hindenburg +hinder +hindered +hinderer +hinderers +hindering +hindermost +hinders +hindgut +hindguts +hindi +hindmost +hindoo +hindquarter +hindquarters +hindrance +hindrances +hinds +hindsight +hindu +hinduism +hindus +hindustan +hindustani +hinge +hinged +hinges +hinging +hinnies +hinny +hins +hint +hinted +hinter +hinterland +hinterlands +hinters +hinting +hints +hip +hipbone +hipbones +hipline +hiplines +hiply +hipness +hipparchus +hipped +hipper +hippest +hippias +hippie +hippiedom +hippiehood +hippies +hipping +hippo +hippocampal +hippocampi +hippocampus +hippocras +hippocrases +hippocrates +hippocratic +hippocrene +hippodrome +hippodromes +hippogriff +hippogriffs +hippogryph +hippolyta +hippolytus +hippomenes +hippopotami +hippopotamus +hippopotamuses +hippos +hippy +hips +hipster +hipsterism +hipsters +hirable +hiragana +hircine +hire +hireable +hired +hireling +hirelings +hirer +hirers +hires +hiring +hirohito +hiroshima +hirsute +hirsuteness +hirsutism +hirudin +hirudins +his +hispanic +hispanicism +hispanicisms +hispanicization +hispanicizations +hispanicize +hispanicized +hispanicizes +hispanicizing +hispanics +hispaniola +hispanism +hispanisms +hispanist +hispanists +hispano +hispanophile +hispanophiles +hispanophilia +hispanophobe +hispanophobes +hispanophobia +hispanos +hispid +hispidity +hiss +hissarlik +hissed +hisself +hisser +hissers +hisses +hissing +hissingly +hissy +hist +histaminase +histaminases +histamine +histaminergic +histamines +histaminic +histidine +histidines +histiocyte +histiocytes +histiocytic +histiocytoses +histiocytosis +histochemical +histochemically +histochemistry +histocompatibilities +histocompatibility +histocompatible +histodialyses +histodialysis +histogenesis +histogenetic +histogenetically +histogenic +histogenically +histogram +histograms +histologic +histological +histologically +histologies +histologist +histologists +histology +histolysis +histolytic +histolytically +histomoniases +histomoniasis +histone +histones +histopathologic +histopathological +histopathologically +histopathologist +histopathologists +histopathology +histophysiologic +histophysiological +histophysiology +histoplasmoses +histoplasmosis +historian +historians +historiated +historic +historical +historically +historicalness +historicism +historicist +historicists +historicity +historicization +historicizations +historicize +historicized +historicizes +historicizing +historied +histories +historiographer +historiographers +historiographic +historiographical +historiographically +historiography +history +histrionic +histrionical +histrionically +histrionics +hit +hitachi +hitch +hitched +hitcher +hitchers +hitches +hitchhike +hitchhiked +hitchhiker +hitchhikers +hitchhikes +hitchhiking +hitching +hither +hithermost +hitherto +hitherward +hitherwards +hitler +hitlerism +hitlerite +hitlerites +hitless +hits +hittable +hitter +hitters +hitting +hittite +hittites +hive +hived +hiveless +hives +hiving +hiwassee +hkakabo +hmm +hmong +hmongs +ho +hoagie +hoagies +hoagy +hoar +hoard +hoarded +hoarder +hoarders +hoarding +hoardings +hoards +hoarfrost +hoarfrosts +hoarier +hoariest +hoarily +hoariness +hoars +hoarse +hoarsely +hoarsen +hoarsened +hoarseness +hoarsening +hoarsens +hoarser +hoarsest +hoary +hoatzin +hoatzins +hoax +hoaxed +hoaxer +hoaxers +hoaxes +hoaxing +hob +hobart +hobbed +hobbes +hobbesian +hobbies +hobbing +hobbism +hobbist +hobbists +hobbit +hobbits +hobble +hobblebush +hobblebushes +hobbled +hobbledehoy +hobbledehoys +hobbler +hobblers +hobbles +hobbling +hobby +hobbyhorse +hobbyhorses +hobbyist +hobbyists +hobgoblin +hobgoblins +hobnail +hobnailed +hobnails +hobnob +hobnobbed +hobnobber +hobnobbers +hobnobbing +hobnobs +hobo +hoboed +hoboes +hoboing +hoboism +hoboken +hobos +hobs +hoc +hock +hocked +hocker +hockers +hockey +hocking +hocks +hockshop +hockshops +hocus +hocused +hocuses +hocusing +hocussed +hocusses +hocussing +hod +hodgepodge +hodgepodges +hodgkin +hodoscope +hodoscopes +hods +hoe +hoecake +hoecakes +hoed +hoedown +hoedowns +hoeing +hoer +hoers +hoes +hog +hogan +hogans +hogarth +hogback +hogbacks +hogfish +hogfishes +hogg +hogged +hogging +hoggish +hoggishly +hoggishness +hoggs +hogmanay +hogmanays +hognose +hogs +hogshead +hogsheads +hogwash +hogweed +hogweeds +hohenlohe +hohenstaufen +hohenstaufens +hohenzollern +hohenzollerns +hoi +hoick +hoicked +hoicking +hoicks +hoise +hoised +hoises +hoisin +hoising +hoist +hoisted +hoister +hoisters +hoisting +hoists +hoity +hokan +hokang +hoke +hoked +hokes +hokey +hokeyness +hokeypokey +hokeypokeys +hokier +hokiest +hokily +hokiness +hoking +hokkaido +hokku +hokum +hokums +hokusai +hokypokies +holandric +holarctic +holbein +hold +holdall +holdalls +holdback +holdbacks +holden +holder +holders +holdfast +holdfasts +holding +holdings +holdout +holdouts +holdover +holdovers +holds +holdup +holdups +hole +holed +holes +holey +holiday +holidayed +holidayer +holidayers +holidaying +holidaymaker +holidaymakers +holidays +holier +holies +holiest +holily +holiness +holing +holinshed +holism +holisms +holist +holistic +holistically +holists +holla +hollaed +hollaing +holland +hollandaise +hollander +hollanders +hollas +holler +hollered +hollering +hollerith +hollers +hollies +hollo +holloa +holloaed +holloaing +holloas +holloed +holloes +holloing +hollos +hollow +holloware +hollowed +hollower +hollowest +hollowing +hollowly +hollowness +hollows +hollowware +holly +hollyhock +hollyhocks +hollywood +holm +holmes +holmic +holmium +holms +holoblastic +holoblastically +holocaust +holocaustal +holocaustic +holocausts +holocene +holocrine +holoenzyme +holoenzymes +holofernes +hologamous +hologram +holograms +holograph +holographic +holographical +holographically +holographs +holography +hologynic +holohedral +holometabolism +holometabolous +holophrastic +holophytic +holoplankton +holoplanktons +holothurian +holothurians +holotype +holotypes +holotypic +holozoic +holp +holpen +holst +holstein +holsteins +holster +holstered +holstering +holsters +holt +holts +holy +holyoke +holystone +holystoned +holystones +holystoning +homage +homager +homagers +hombre +hombres +homburg +homburgs +home +homebodies +homebody +homebound +homeboy +homeboys +homebred +homebuilder +homebuilders +homebuilding +homebuilt +homebuyer +homebuyers +homecoming +homecomings +homed +homefolk +homefolks +homegrown +homeland +homelands +homeless +homelessness +homelier +homeliest +homelike +homeliness +homely +homemade +homemaker +homemakers +homemaking +homeobox +homeoboxes +homeomorphic +homeomorphism +homeomorphisms +homeomorphous +homeopath +homeopathic +homeopathically +homeopathies +homeopathist +homeopathists +homeopaths +homeopathy +homeostasis +homeostatic +homeotherm +homeothermal +homeothermic +homeothermous +homeotherms +homeowner +homeowners +homeownership +homer +homered +homeric +homerically +homering +homeroom +homerooms +homers +homes +homesick +homesickness +homesite +homesites +homespun +homestead +homesteaded +homesteader +homesteaders +homesteading +homesteads +homestretch +homestretches +hometown +hometowns +homeward +homewards +homework +homey +homeyness +homicidal +homicidally +homicide +homicides +homier +homiest +homiletic +homiletical +homiletically +homiletics +homilies +homilist +homilists +homily +hominem +hominess +homing +hominid +hominidae +hominids +hominization +hominizations +hominoid +hominoids +hominy +hommos +homo +homocentric +homocercal +homochirality +homochromatic +homochromatism +homoecious +homoerotic +homoeroticism +homoerotism +homogametic +homogamous +homogamy +homogenate +homogenates +homogeneities +homogeneity +homogeneous +homogeneously +homogeneousness +homogenies +homogenization +homogenizations +homogenize +homogenized +homogenizer +homogenizers +homogenizes +homogenizing +homogenous +homogeny +homograft +homografts +homograph +homographic +homographs +homoiotherm +homoiothermal +homoiothermic +homoiothermous +homoiotherms +homoiousian +homoiousians +homolecithal +homolog +homologate +homologated +homologates +homologating +homologation +homologic +homological +homologically +homologies +homologize +homologized +homologizer +homologizers +homologizes +homologizing +homologous +homolographic +homologs +homologue +homologues +homology +homolosine +homolysis +homolytic +homomorphic +homomorphism +homomorphisms +homomorphous +homonuclear +homonym +homonymic +homonymies +homonymous +homonymously +homonyms +homonymy +homoousian +homoousians +homophile +homophiles +homophobe +homophobes +homophobia +homophobic +homophone +homophones +homophonic +homophonies +homophonous +homophony +homophylic +homophylies +homophyly +homoplasies +homoplastic +homoplastically +homoplasy +homopolar +homopolymer +homopolymers +homopteran +homopterans +homopterous +homos +homoscedastic +homoscedasticity +homosexual +homosexuality +homosexually +homosexuals +homosporous +homospory +homostyled +homostylous +homostyly +homotaxial +homotaxic +homotaxis +homotaxises +homothallic +homothallism +homotransplant +homotransplantation +homozygosis +homozygosity +homozygote +homozygotes +homozygotic +homozygous +homozygously +homunculi +homunculus +homy +hon +honan +honans +honcho +honchoed +honchoing +honchos +honduran +hondurans +honduras +hone +honed +honer +honers +hones +honest +honesties +honestly +honesty +honewort +honeworts +honey +honeybee +honeybees +honeyberries +honeyberry +honeybunch +honeybunches +honeycomb +honeycombed +honeycombing +honeycombs +honeycreeper +honeycreepers +honeydew +honeydews +honeyeater +honeyeaters +honeyed +honeying +honeymoon +honeymooned +honeymooner +honeymooners +honeymooning +honeymoons +honeys +honeysuckle +honeysuckles +honeywell +honfleur +hong +hongs +honiara +honied +honing +honk +honked +honker +honkers +honkey +honkeys +honkie +honkies +honking +honks +honky +honkytonks +honolulu +honor +honorabilities +honorability +honorable +honorableness +honorably +honoraria +honorarily +honorarium +honorariums +honorary +honored +honoree +honorees +honorer +honorers +honorific +honorifically +honorifics +honoring +honors +honshu +hoo +hooch +hooches +hood +hooded +hoodedness +hooding +hoodlike +hoodlum +hoodlumish +hoodlumism +hoodlums +hoodmold +hoodmolds +hoodoo +hoodooed +hoodooing +hoodooism +hoodoos +hoods +hoodwink +hoodwinked +hoodwinker +hoodwinkers +hoodwinking +hoodwinks +hooey +hoof +hoofbeat +hoofbeats +hoofbound +hoofed +hoofer +hoofers +hoofing +hoofprint +hoofprints +hoofs +hook +hookah +hookahs +hooked +hookedness +hooker +hookers +hookey +hookeys +hookies +hooking +hooklet +hooklets +hooknose +hooknosed +hooknoses +hooks +hookup +hookups +hookworm +hookworms +hooky +hooligan +hooliganism +hooligans +hoop +hooped +hooper +hoopers +hooping +hoopla +hooplike +hoopoe +hoopoes +hoops +hoopskirt +hoopskirts +hoorah +hoorahs +hooray +hoorayed +hooraying +hoorays +hoosegow +hoosegows +hoosier +hoosiers +hoot +hootch +hootches +hootchy +hooted +hootenannies +hootenanny +hooter +hooters +hooting +hoots +hooved +hooverville +hoovervilles +hooves +hop +hopatcong +hope +hoped +hopeful +hopefully +hopefulness +hopefuls +hopeh +hopei +hopeless +hopelessly +hopelessness +hoper +hopers +hopes +hopewell +hophead +hopheads +hopi +hoping +hopis +hoplite +hoplites +hoplitic +hopped +hopper +hoppergrass +hoppergrasses +hoppers +hopping +hops +hopsack +hopsacking +hopsacks +hopscotch +hopscotched +hopscotches +hopscotching +hora +horace +horah +horahs +horary +horas +horatian +horatio +horde +hordes +horehound +horehounds +horizon +horizonal +horizons +horizontal +horizontally +horizontals +hormogonia +hormogonium +hormonal +hormonally +hormone +hormonelike +hormones +hormonic +horn +hornbeam +hornbeams +hornbill +hornbills +hornblende +hornblower +hornbook +hornbooks +horned +hornedness +horner +hornet +hornets +hornfels +hornier +horniest +horniness +horning +hornist +hornists +hornito +hornitos +hornless +hornlessness +hornlike +hornpipe +hornpipes +hornpout +hornpouts +horns +hornswoggle +hornswoggled +hornswoggles +hornswoggling +horntail +horntails +hornworm +hornworms +hornwort +hornworts +horny +horologe +horologer +horologers +horologes +horologic +horological +horologist +horologists +horologium +horology +horometrical +horoscope +horoscopes +horrendous +horrendously +horrent +horrible +horribleness +horribly +horrid +horridly +horridness +horrific +horrifically +horrification +horrified +horrifiedly +horrifies +horrify +horrifying +horrifyingly +horripilate +horripilated +horripilates +horripilating +horripilation +horripilations +horror +horrors +horrorstricken +horrorstruck +hors +horsa +horse +horseback +horsebacks +horsecar +horsecars +horsed +horsefeathers +horseflesh +horseflies +horsefly +horsehair +horsehide +horsehides +horselaugh +horselaughs +horseleech +horseleeches +horseless +horselike +horseman +horsemanship +horsemeat +horsemen +horsemint +horsemints +horseplay +horseplayer +horseplayers +horsepower +horserace +horseraces +horseracing +horseradish +horseradishes +horses +horseshit +horseshits +horseshoe +horseshoed +horseshoeing +horseshoer +horseshoers +horseshoes +horsetail +horsetails +horseweed +horseweeds +horsewhip +horsewhipped +horsewhipping +horsewhips +horsewoman +horsewomen +horsey +horsier +horsiest +horsily +horsiness +horsing +horst +horsts +horsy +hortative +hortatively +hortatory +horticultural +horticulturalist +horticulturalists +horticulturally +horticulture +horticulturist +horticulturists +horus +hosanna +hosannah +hosannahs +hosannas +hose +hosea +hosed +hosel +hosels +hoses +hosey +hoseyed +hoseying +hoseys +hosiery +hosing +hospice +hospices +hospitable +hospitably +hospital +hospitaler +hospitalers +hospitalities +hospitality +hospitalization +hospitalizations +hospitalize +hospitalized +hospitalizes +hospitalizing +hospitaller +hospitallers +hospitals +host +hosta +hostage +hostages +hostas +hosted +hostel +hosteled +hosteler +hostelers +hosteling +hostelries +hostelry +hostels +hostess +hostesses +hostile +hostilely +hostiles +hostilities +hostility +hosting +hostler +hostlers +hostly +hosts +hot +hotbed +hotbeds +hotblood +hotbloods +hotbox +hotboxes +hotcake +hotcakes +hotch +hotched +hotches +hotching +hotchpot +hotchpotch +hotchpotches +hotchpots +hotdog +hotdogged +hotdogging +hotdogs +hotel +hotelier +hoteliers +hotelkeeper +hotelkeepers +hotelman +hotelmen +hotels +hotfoot +hotfooted +hotfooting +hotfoots +hothead +hotheaded +hotheadedly +hotheadedness +hotheads +hothouse +hothouses +hotkey +hotline +hotlines +hotly +hotness +hotplate +hotplates +hotpot +hotpots +hotrod +hotrods +hots +hotshot +hotshots +hotspot +hotspots +hotspur +hotted +hottentot +hottentots +hotter +hottest +hotting +hottish +houdah +houdahs +houdan +houdans +houdini +hound +hounded +hounder +hounders +hounding +hounds +houndstooth +hour +hourglass +hourglasses +houri +houris +hourlies +hourlong +hourly +hours +housatonic +house +houseboat +houseboats +housebound +houseboy +houseboys +housebreak +housebreaker +housebreakers +housebreaking +housebreaks +housebroke +housebroken +housecarl +housecarls +houseclean +housecleaned +housecleaner +housecleaners +housecleaning +housecleans +housecoat +housecoats +housed +housedog +housedogs +housedress +housedresses +housefather +housefathers +houseflies +housefly +housefront +housefronts +houseful +housefuls +houseguest +houseguests +household +householder +householders +households +househusband +househusbands +housekeep +housekeeper +housekeepers +housekeeping +housekeeps +housekept +housel +houseled +houseleek +houseleeks +houseless +houselessness +houselights +houseling +housels +housemaid +housemaids +houseman +housemaster +housemasters +housemate +housemates +housemen +housemother +housemothers +housepainter +housepainters +houseparent +houseparents +houseperson +housepersons +houseplant +houseplants +houseroom +houserooms +housers +houses +housesat +housesit +housesits +housesitting +housetop +housetops +housetrain +housetrained +housetraining +housetrains +housewares +housewarming +housewarmings +housewife +housewifeliness +housewifely +housewifery +housewives +housework +houseworker +houseworkers +housing +housings +houston +houstonian +houstonians +hove +hovel +hovels +hover +hovercraft +hovercrafts +hovered +hoverer +hoverers +hovering +hoveringly +hovers +how +howard +howards +howbeit +howdah +howdahs +howdy +howe +howes +however +howf +howff +howffs +howfs +howitzer +howitzers +howl +howled +howler +howlers +howling +howls +hows +howsoever +hoy +hoya +hoyas +hoyden +hoydenish +hoydens +hoyle +hoys +html +hualapai +hualapais +huang +huarache +huaraches +huascarán +hub +hubba +hubbard +hubbies +hubble +hubbub +hubbubs +hubby +hubcap +hubcaps +hubris +hubristic +hubristically +hubs +huck +huckaback +huckabacks +huckleberries +huckleberry +hucks +huckster +huckstered +huckstering +hucksterism +hucksters +huddle +huddled +huddler +huddlers +huddles +huddling +hudibras +hudibrastic +hudson +hue +hued +hues +huevos +huff +huffed +huffier +huffiest +huffily +huffiness +huffing +huffish +huffishly +huffishness +huffs +huffy +hug +huge +hugely +hugeness +hugeous +hugeously +hugeousness +huger +hugest +huggable +hugged +hugger +huggermugger +huggermuggered +huggermuggering +huggermuggers +huggermuggery +huggers +hugging +hugo +hugs +huguenot +huguenotic +huguenotism +huguenots +huh +hui +huipil +huipils +huis +hula +hulas +hulk +hulked +hulking +hulks +hulky +hull +hullaballoo +hullaballoos +hullabaloo +hullabaloos +hulled +huller +hullers +hulling +hullo +hulls +hum +human +humane +humanely +humaneness +humanhood +humanism +humanist +humanistic +humanistically +humanists +humanitarian +humanitarianism +humanitarians +humanities +humanity +humanization +humanize +humanized +humanizer +humanizers +humanizes +humanizing +humankind +humanlike +humanly +humanness +humanoid +humanoids +humans +humate +humates +humberside +humble +humblebee +humblebees +humbled +humbleness +humbler +humblers +humbles +humblest +humbling +humbly +humboldt +humbug +humbugged +humbugger +humbuggers +humbuggery +humbugging +humbugs +humdinger +humdingers +humdrum +hume +humectant +humectants +humectation +humeral +humerals +humeri +humerus +humic +humid +humidification +humidifications +humidified +humidifier +humidifiers +humidifies +humidify +humidifying +humidistat +humidistats +humidity +humidly +humidor +humidors +humification +humifications +humified +humiliate +humiliated +humiliates +humiliating +humiliatingly +humiliation +humiliations +humilities +humility +hummable +hummed +hummer +hummers +humming +hummingbird +hummingbirds +hummock +hummocks +hummocky +hummus +humongous +humor +humoral +humored +humoredly +humoresque +humoresques +humoring +humorist +humoristic +humorists +humorless +humorlessly +humorlessness +humorous +humorously +humorousness +humors +hump +humpback +humpbacked +humpbacks +humped +humperdinck +humph +humphed +humphing +humphrey +humphreys +humphs +humpier +humpiest +humping +humps +humpty +humpy +hums +humungous +humus +humuses +hun +hunan +hunch +hunchback +hunchbacked +hunchbacks +hunched +hunches +hunching +hundred +hundredfold +hundreds +hundredth +hundredths +hundredweight +hundredweights +hung +hungarian +hungarians +hungary +hunger +hungered +hungering +hungers +hungrier +hungriest +hungrily +hungriness +hungry +hunk +hunker +hunkered +hunkering +hunkers +hunkies +hunkpapa +hunkpapas +hunks +hunky +hunnish +hunnishness +huns +hunt +hunted +hunter +hunters +hunting +huntings +huntington +huntress +huntresses +hunts +huntsman +huntsmen +huntsville +hup +hurdle +hurdled +hurdler +hurdlers +hurdles +hurdling +hurdy +hurl +hurled +hurler +hurlers +hurlies +hurling +hurlings +hurls +hurly +huron +hurons +hurrah +hurrahed +hurrahing +hurrahs +hurray +hurricane +hurricanes +hurried +hurriedly +hurriedness +hurrier +hurriers +hurries +hurry +hurrying +hurt +hurter +hurters +hurtful +hurtfully +hurtfulness +hurting +hurtle +hurtled +hurtles +hurtless +hurtling +hurts +husband +husbanded +husbander +husbanders +husbanding +husbandly +husbandman +husbandmen +husbandry +husbands +hush +hushed +hushes +hushing +hushpuppies +hushpuppy +husk +husked +husker +huskers +huskier +huskies +huskiest +huskily +huskiness +husking +huskings +husks +husky +huss +hussar +hussars +hussies +hussite +hussites +hussitism +hussy +hustings +hustle +hustled +hustler +hustlers +hustles +hustling +hut +hutch +hutches +hutment +huts +hutted +hutterite +hutterites +hutting +hutu +hutus +hutzpa +hutzpah +huxley +huygens +huzza +huzzah +huzzahs +huzzas +huáscar +hwang +hwei +hweis +hyacinth +hyacinthine +hyacinths +hyacinthus +hyades +hyaena +hyaenas +hyalin +hyaline +hyalines +hyalinization +hyalins +hyalite +hyalites +hyaloid +hyaloplasm +hyaloplasms +hyaluronic +hyaluronidase +hyaluronidases +hyannis +hybrid +hybridism +hybridist +hybridists +hybridity +hybridization +hybridizations +hybridize +hybridized +hybridizer +hybridizers +hybridizes +hybridizing +hybridoma +hybridomas +hybrids +hybris +hydathode +hydathodes +hydatid +hydatids +hyde +hyderabad +hydra +hydrae +hydralazine +hydralazines +hydramine +hydramines +hydrangea +hydrangeas +hydrant +hydranth +hydranths +hydrants +hydrarch +hydras +hydrase +hydrases +hydrastine +hydrastines +hydrate +hydrated +hydrates +hydrating +hydration +hydrations +hydrator +hydrators +hydraulic +hydraulically +hydraulics +hydrazide +hydrazides +hydrazine +hydric +hydride +hydrides +hydrilla +hydrillas +hydriodic +hydro +hydrobiological +hydrobiologist +hydrobiologists +hydrobiology +hydrobromic +hydrocarbon +hydrocarbonaceous +hydrocarbonic +hydrocarbonous +hydrocarbons +hydrocele +hydroceles +hydrocephalic +hydrocephaloid +hydrocephalous +hydrocephalus +hydrocephaly +hydrochemistry +hydrochloric +hydrochloride +hydrochlorides +hydrochlorothiazide +hydrochlorothiazides +hydrocolloid +hydrocolloidal +hydrocolloids +hydrocoral +hydrocorals +hydrocortisone +hydrocrack +hydrocracked +hydrocracker +hydrocrackers +hydrocracking +hydrocrackings +hydrocracks +hydrocyanic +hydrodynamic +hydrodynamical +hydrodynamically +hydrodynamicist +hydrodynamicists +hydrodynamics +hydroelectric +hydroelectrically +hydroelectricity +hydrofluoric +hydrofoil +hydrofoils +hydroformer +hydroformers +hydroforming +hydroformings +hydrogen +hydrogenase +hydrogenases +hydrogenate +hydrogenated +hydrogenates +hydrogenating +hydrogenation +hydrogenations +hydrogenolysis +hydrogenous +hydrogeologic +hydrogeological +hydrogeologist +hydrogeologists +hydrogeology +hydrographer +hydrographers +hydrographic +hydrographically +hydrographies +hydrography +hydroid +hydroids +hydrokinetic +hydrokinetical +hydrokinetics +hydrolase +hydrolases +hydrologic +hydrological +hydrologically +hydrologist +hydrologists +hydrology +hydrolysate +hydrolysates +hydrolysis +hydrolyte +hydrolytic +hydrolytically +hydrolyzable +hydrolyzate +hydrolyzates +hydrolyzation +hydrolyze +hydrolyzed +hydrolyzes +hydrolyzing +hydromagnetic +hydromagnetics +hydromancy +hydromechanical +hydromechanics +hydromedusa +hydromedusae +hydromedusas +hydromel +hydromels +hydrometallurgical +hydrometallurgy +hydrometeor +hydrometeorological +hydrometeorologist +hydrometeorologists +hydrometeorology +hydrometeors +hydrometer +hydrometers +hydrometric +hydrometrical +hydrometrically +hydrometry +hydromorphic +hydronic +hydronically +hydronium +hydroniums +hydropath +hydropathic +hydropathical +hydropathies +hydropathist +hydropathists +hydropaths +hydropathy +hydroperoxide +hydrophane +hydrophanes +hydrophanous +hydrophile +hydrophiles +hydrophilic +hydrophilicity +hydrophilous +hydrophily +hydrophobia +hydrophobias +hydrophobic +hydrophobicity +hydrophone +hydrophones +hydrophyte +hydrophytes +hydrophytic +hydroplane +hydroplaned +hydroplanes +hydroplaning +hydroponic +hydroponically +hydroponicist +hydroponicists +hydroponics +hydroponist +hydroponists +hydropower +hydroquinol +hydroquinols +hydroquinone +hydroquinones +hydros +hydroscope +hydroscopes +hydroscopic +hydrosere +hydrosol +hydrosolic +hydrosols +hydrospace +hydrospaces +hydrosphere +hydrospheres +hydrospheric +hydrostatic +hydrostatical +hydrostatically +hydrostatics +hydrosulfate +hydrosulfates +hydrosulfide +hydrosulfides +hydrosulfite +hydrosulfites +hydrosulfurous +hydrotactic +hydrotaxis +hydrotaxises +hydrotherapeutic +hydrotherapeutics +hydrotherapies +hydrotherapy +hydrothermal +hydrothermally +hydrothorax +hydrothoraxes +hydrotropic +hydrotropically +hydrotropism +hydrous +hydroxide +hydroxides +hydroxy +hydroxyapatite +hydroxyapatites +hydroxyl +hydroxylamine +hydroxylamines +hydroxylate +hydroxylated +hydroxylates +hydroxylating +hydroxylation +hydroxylic +hydroxyls +hydroxyproline +hydroxyzine +hydrozoa +hydrozoan +hydrozoans +hydrus +hyena +hyenas +hyenic +hyetal +hyetometer +hyetometers +hyetometrograph +hyetometrographs +hygeia +hygiene +hygienic +hygienically +hygienics +hygienist +hygienists +hygrograph +hygrographs +hygrometer +hygrometers +hygrometric +hygrometry +hygrophyte +hygrophytes +hygrophytic +hygroscope +hygroscopes +hygroscopic +hygroscopically +hygroscopicity +hygrostat +hygrostats +hying +hyla +hylas +hylozoic +hylozoism +hylozoist +hylozoistic +hylozoists +hymen +hymenal +hymeneal +hymeneally +hymeneals +hymenia +hymenial +hymenium +hymeniums +hymenopteran +hymenopterans +hymenopteron +hymenopterons +hymenopterous +hymens +hymettus +hymie +hymies +hymn +hymnal +hymnals +hymnaries +hymnary +hymnbook +hymnbooks +hymned +hymning +hymnodies +hymnodist +hymnodists +hymnody +hymnography +hymnologic +hymnological +hymnologist +hymnologists +hymnology +hymns +hyoid +hyoids +hyoscine +hyoscines +hyoscyamine +hyoscyamines +hypabyssal +hypabyssally +hypaethral +hypanthia +hypanthial +hypanthium +hype +hyped +hyper +hyperacid +hyperacidity +hyperactive +hyperactively +hyperactivity +hyperacuity +hyperacute +hyperaesthesia +hyperaesthesias +hyperaesthetic +hyperaggressive +hyperalert +hyperarid +hyperarousal +hyperaware +hyperawareness +hyperbaric +hyperbarically +hyperbaton +hyperbatons +hyperbola +hyperbolae +hyperbolas +hyperbole +hyperbolic +hyperbolical +hyperbolically +hyperbolism +hyperbolisms +hyperbolist +hyperbolists +hyperbolize +hyperbolized +hyperbolizes +hyperbolizing +hyperboloid +hyperboloidal +hyperboloids +hyperborean +hyperboreans +hypercalcemia +hypercalcemias +hypercapnia +hypercapnias +hypercatabolism +hypercatalectic +hypercatalexis +hypercautious +hypercharge +hypercharged +hypercharges +hypercholesterolemia +hypercholesterolemias +hypercivilized +hypercoagulability +hypercoagulable +hypercompetitive +hyperconcentration +hyperconscious +hyperconsciousness +hypercorrect +hypercorrection +hypercorrections +hypercorrectly +hypercorrectness +hypercritic +hypercritical +hypercritically +hypercriticism +hypercriticisms +hypercriticize +hypercriticizes +hypercritics +hypercube +hypercubes +hyperdense +hyperdevelopment +hyperefficient +hyperemia +hyperemic +hyperemotional +hyperemotionality +hyperendemic +hyperenergetic +hyperesthesia +hyperesthesias +hyperesthetic +hypereutectic +hyperexcitability +hyperexcitable +hyperexcited +hyperexcitement +hyperexcretion +hyperextend +hyperextended +hyperextending +hyperextends +hyperextension +hyperextensions +hyperfastidious +hyperfine +hyperfunction +hyperfunctional +hyperfunctioning +hypergamies +hypergamy +hypergeometric +hyperglycemia +hyperglycemic +hypergol +hypergolic +hypergolically +hyperimmune +hyperimmunization +hyperimmunize +hyperimmunized +hyperimmunizes +hyperimmunizing +hyperinflated +hyperinflation +hyperinflationary +hyperinflations +hyperinnervation +hyperinsulinism +hyperinsulinisms +hyperintellectual +hyperintelligent +hyperintense +hyperinvolution +hyperion +hyperirritability +hyperirritable +hyperkeratoses +hyperkeratosis +hyperkeratotic +hyperkinesia +hyperkinesis +hyperkinetic +hyperlink +hyperlinks +hyperlipemia +hyperlipemias +hyperlipidemia +hyperlipidemias +hypermania +hypermanic +hypermarket +hypermarkets +hypermasculine +hypermedia +hypermetabolic +hypermetabolism +hypermeter +hypermeters +hypermetric +hypermetrical +hypermetropia +hypermetropias +hypermetropic +hypermetropical +hypermetropy +hypermnesia +hypermnesias +hypermnesic +hypermobility +hypermodern +hypermodernist +hypermutability +hypermutable +hypernationalistic +hyperon +hyperons +hyperope +hyperopia +hyperopias +hyperopic +hyperostoses +hyperostosis +hyperostotic +hyperparasite +hyperparasites +hyperparasitic +hyperparasitism +hyperparathyroidism +hyperphagia +hyperphagic +hyperphysical +hyperpigmentation +hyperpigmented +hyperpituitarism +hyperpituitarisms +hyperpituitary +hyperplane +hyperplanes +hyperplasia +hyperplasias +hyperplastic +hyperploid +hyperploidy +hyperpnea +hyperpneas +hyperpneic +hyperpolarize +hyperpolarized +hyperpolarizes +hyperpolarizing +hyperproducer +hyperproducers +hyperproduction +hyperpure +hyperpyretic +hyperpyrexia +hyperpyrexial +hyperpyrexias +hyperrational +hyperrationality +hyperreactive +hyperreactivity +hyperreactor +hyperreactors +hyperrealism +hyperrealisms +hyperrealist +hyperrealistic +hyperrealists +hyperresponsive +hyperromantic +hypersaline +hypersalinity +hypersalivation +hypersecretion +hypersensitive +hypersensitiveness +hypersensitivities +hypersensitivity +hypersensitization +hypersensitize +hypersensitized +hypersensitizes +hypersensitizing +hypersexual +hypersexuality +hypersomnolence +hypersonic +hypersonically +hyperspace +hyperspaces +hyperstatic +hypersthene +hypersthenes +hypersthenic +hyperstimulate +hyperstimulated +hyperstimulates +hyperstimulating +hyperstimulation +hypersurface +hypersurfaces +hypersusceptibility +hypersusceptible +hypertense +hypertension +hypertensive +hypertext +hypertexts +hyperthermal +hyperthermia +hyperthermias +hyperthermic +hyperthyroid +hyperthyroidism +hypertonia +hypertonias +hypertonic +hypertonicity +hypertrophic +hypertrophied +hypertrophies +hypertrophy +hypertrophying +hypertypical +hypervelocity +hyperventilate +hyperventilated +hyperventilates +hyperventilating +hyperventilation +hypervigilance +hypervigilant +hypervirulent +hyperviscosity +hypervitaminoses +hypervitaminosis +hypes +hypesthesia +hypesthesias +hypethral +hypha +hyphae +hyphal +hyphen +hyphenate +hyphenated +hyphenates +hyphenating +hyphenation +hyphenations +hyphened +hyphening +hyphenless +hyphens +hyping +hypnagogic +hypnoanalyses +hypnoanalysis +hypnogenesis +hypnogenetic +hypnogenetically +hypnogogic +hypnoid +hypnoidal +hypnopedia +hypnopedias +hypnophobia +hypnophobias +hypnophobic +hypnopompic +hypnos +hypnoses +hypnosis +hypnotherapies +hypnotherapy +hypnotic +hypnotically +hypnotics +hypnotism +hypnotist +hypnotists +hypnotizability +hypnotizable +hypnotization +hypnotize +hypnotized +hypnotizer +hypnotizers +hypnotizes +hypnotizing +hypo +hypoacidities +hypoacidity +hypoactive +hypoallergenic +hypobaric +hypobarism +hypoblast +hypoblastic +hypoblasts +hypocaust +hypocausts +hypocenter +hypocenters +hypocentral +hypochlorite +hypochlorites +hypochlorous +hypochondria +hypochondriac +hypochondriacal +hypochondriacally +hypochondriacs +hypochondriases +hypochondriasis +hypochondrium +hypocorism +hypocorisms +hypocoristic +hypocoristical +hypocoristically +hypocotyl +hypocotyls +hypocrisies +hypocrisy +hypocrite +hypocrites +hypocritical +hypocritically +hypocycloid +hypocycloids +hypoderm +hypodermal +hypodermic +hypodermically +hypodermics +hypodermis +hypodermises +hypoderms +hypoed +hypoesthesia +hypoesthesias +hypoeutectic +hypogastria +hypogastric +hypogastrium +hypogea +hypogeal +hypogeally +hypogean +hypogene +hypogenous +hypogeous +hypogeum +hypoglossal +hypoglycemia +hypoglycemic +hypogynous +hypogyny +hypoing +hypolimnetic +hypolimnial +hypolimnion +hypolimnions +hypomania +hypomanias +hypomanic +hypomorphic +hyponastic +hyponasties +hyponasty +hypophosphite +hypophosphites +hypophosphorous +hypophyseal +hypophyses +hypophysial +hypophysis +hypopituitarism +hypopituitarisms +hypopituitary +hypoplasia +hypoplasias +hypoplastic +hypoploid +hypoploidy +hypopnea +hypopneas +hypopneic +hypos +hyposensitive +hyposensitivities +hyposensitivity +hyposensitization +hyposensitizations +hyposensitize +hyposensitized +hyposensitizes +hyposensitizing +hypostases +hypostasis +hypostatic +hypostatical +hypostatically +hypostatization +hypostatize +hypostatized +hypostatizes +hypostatizing +hyposthenia +hyposthenias +hyposthenic +hypostyle +hypostyles +hyposulfite +hyposulfites +hyposulfurous +hypotactic +hypotaxis +hypotaxises +hypotension +hypotensions +hypotensive +hypotensives +hypotenuse +hypotenuses +hypothalamic +hypothalamus +hypothalamuses +hypothecate +hypothecated +hypothecates +hypothecating +hypothecation +hypothecations +hypothecator +hypothecators +hypothenuse +hypothermal +hypothermia +hypothermic +hypotheses +hypothesi +hypothesis +hypothesize +hypothesized +hypothesizer +hypothesizers +hypothesizes +hypothesizing +hypothetic +hypothetical +hypothetically +hypothyroid +hypothyroidism +hypotonic +hypotonicity +hypotrophic +hypotrophies +hypotrophy +hypoventilation +hypoventilations +hypoxanthine +hypoxanthines +hypoxemia +hypoxemias +hypoxemic +hypoxia +hypoxias +hypoxic +hypsographic +hypsographical +hypsographies +hypsography +hypsometer +hypsometers +hypsometric +hypsometrical +hypsometrically +hypsometrist +hypsometrists +hypsometry +hyraces +hyrax +hyraxes +hyson +hysons +hyssop +hyssops +hysterectomies +hysterectomize +hysterectomized +hysterectomizes +hysterectomizing +hysterectomy +hystereses +hysteresis +hysteretic +hysteria +hysterias +hysteric +hysterical +hysterically +hysterics +hysterogenic +hysteroid +hysteron +hysterotomies +hysterotomy +hälsingborg +héloise +hôte +hôtel +i +i'd +i'll +i'm +i've +iago +iamb +iambi +iambic +iambics +iambs +iambus +iambuses +iapetus +iatrogenic +iatrogenically +iberia +iberian +iberians +ibex +ibexes +ibibio +ibibios +ibid +ibidem +ibis +ibises +ibiza +ibizan +ibo +ibos +ibsen +ibsenian +ibsenism +ibsenite +ibsenites +ibuprofen +icaria +icarus +ice +iceball +iceballs +iceberg +icebergs +iceblink +iceblinks +iceboat +iceboater +iceboaters +iceboating +iceboats +icebound +icebox +iceboxes +icebreaker +icebreakers +icebreaking +icecap +icecaps +iced +icefall +icefalls +icehouse +icehouses +iceland +icelander +icelanders +icelandic +iceless +icelike +icemaker +icemakers +iceman +icemen +iceni +icenian +icenic +icepack +icepacks +ices +icescape +icescapes +ich +ichihara +ichikawa +ichinomiya +ichneumon +ichneumons +ichnite +ichnites +ichnographies +ichnography +ichnolite +ichnolites +ichor +ichorous +ichors +ichthyic +ichthyofauna +ichthyofaunal +ichthyofaunas +ichthyoid +ichthyoids +ichthyologic +ichthyological +ichthyologically +ichthyologist +ichthyologists +ichthyology +ichthyophagous +ichthyornis +ichthyornises +ichthyosaur +ichthyosauri +ichthyosaurian +ichthyosaurs +ichthyosaurus +ichthyosis +ici +icicle +icicles +icier +iciest +icily +iciness +icing +icings +ickier +ickiest +ickiness +icky +icon +iconic +iconically +iconicity +iconified +iconifies +iconify +iconifying +iconoclasm +iconoclast +iconoclastic +iconoclastically +iconoclasts +iconographer +iconographers +iconographic +iconographical +iconographically +iconographies +iconography +iconolater +iconolaters +iconolatric +iconolatry +iconological +iconologist +iconologists +iconology +iconoscope +iconoscopes +iconostases +iconostasis +icons +icosahedra +icosahedral +icosahedron +icosahedrons +icteric +icterics +icterus +ictinus +ictus +ictuses +icy +id +ida +idaho +idahoan +idahoans +idahoes +idahos +idea +ideal +idealess +idealism +idealist +idealistic +idealistically +idealists +idealities +ideality +idealization +idealizations +idealize +idealized +idealizer +idealizers +idealizes +idealizing +idealless +ideally +idealogue +idealogy +ideals +ideas +ideate +ideated +ideates +ideating +ideation +ideational +ideationally +ideations +idem +idempotent +identic +identical +identically +identicalness +identics +identifiable +identifiably +identification +identifications +identified +identifier +identifiers +identifies +identify +identifying +identities +identity +identité +ideogram +ideogramic +ideogrammatic +ideogrammatically +ideogrammic +ideograms +ideograph +ideographic +ideographically +ideographs +ideography +ideologic +ideological +ideologically +ideologies +ideologist +ideologists +ideologize +ideologized +ideologizes +ideologizing +ideologue +ideologues +ideology +ideomotor +ides +idioblast +idioblastic +idioblasts +idiocies +idiocy +idiographic +idiolect +idiolectal +idiolectic +idiolects +idiom +idiomatic +idiomatically +idiomaticness +idiomorphic +idioms +idiopathic +idiopathically +idiopathies +idiopathy +idiosyncrasies +idiosyncrasy +idiosyncratic +idiosyncratically +idiot +idiotic +idiotical +idiotically +idiotism +idiots +idiotype +idiotypic +idle +idled +idleness +idler +idlers +idles +idlesse +idlest +idling +idly +idocrase +idocrases +idol +idolater +idolaters +idolator +idolators +idolatries +idolatrous +idolatrously +idolatrousness +idolatry +idolization +idolizations +idolize +idolized +idolizer +idolizers +idolizes +idolizing +idols +ids +idyl +idyll +idyllic +idyllically +idyllist +idyllists +idylls +idyls +idée +idées +if +iffier +iffiest +iffiness +iffy +ifni +ifs +igbo +igbos +igg +igged +igging +iggs +igitur +igloo +igloos +ignatius +igneous +ignes +ignescent +igni +ignimbrite +ignimbrites +ignis +ignitability +ignitable +ignite +ignited +igniter +igniters +ignites +ignitible +igniting +ignition +ignitions +ignitor +ignitors +ignitron +ignitrons +ignobility +ignoble +ignobleness +ignobly +ignominies +ignominious +ignominiously +ignominiousness +ignominy +ignorable +ignoramus +ignoramuses +ignorance +ignorant +ignorantia +ignorantly +ignorantness +ignoratio +ignore +ignored +ignorer +ignorers +ignores +ignoring +ignotius +ignotum +igorot +igorots +igraine +iguana +iguanas +iguanodon +iguanodons +iguassú +iguaçú +ihram +ihrams +ijmuiden +ijsselmeer +ikaria +ikat +ikebana +ikhnaton +ikon +ikons +il +ilang +ilea +ileac +ileal +ileitis +ileostomies +ileostomy +ileum +ileus +ilex +ilexes +ilia +iliac +iliad +iliadic +ilial +iliamna +ilion +ilium +ilk +ilka +ill +illae +illampu +illation +illations +illative +illatively +illatives +illaudable +illaudably +illegal +illegalities +illegality +illegalization +illegalize +illegalized +illegalizes +illegalizing +illegally +illegals +illegibility +illegible +illegibleness +illegibly +illegitimacies +illegitimacy +illegitimate +illegitimated +illegitimately +illegitimates +illegitimating +illegitimatize +illegitimatizes +iller +illiberal +illiberalism +illiberality +illiberally +illiberalness +illicit +illicitly +illicitness +illimani +illimitability +illimitable +illimitableness +illimitably +illinoian +illinois +illinoisan +illinoisans +illiquid +illiquidity +illis +illite +illiteracies +illiteracy +illiterate +illiterately +illiterateness +illiterates +illitic +illness +illnesses +illocutionary +illogic +illogical +illogicalities +illogicality +illogically +illogicalness +ills +illume +illumed +illumes +illuminable +illuminance +illuminances +illuminant +illuminants +illuminate +illuminated +illuminates +illuminati +illuminating +illuminatingly +illumination +illuminations +illuminative +illuminator +illuminators +illumine +illumined +illumines +illuming +illumining +illuminism +illuminist +illuminists +illusion +illusional +illusionary +illusionism +illusionist +illusionistic +illusionistically +illusionists +illusionless +illusions +illusive +illusively +illusiveness +illusorily +illusoriness +illusory +illustratable +illustrate +illustrated +illustrates +illustrating +illustration +illustrational +illustrations +illustrative +illustratively +illustrator +illustrators +illustrious +illustriously +illustriousness +illuvial +illuviate +illuviated +illuviates +illuviating +illuviation +illuviations +illy +illyria +illyrian +illyrians +illyricums +ilmenite +ilmenites +ilocano +ilocanos +iloilo +ilokano +ilokanos +ilorin +ils +image +imaged +imageless +imager +imageries +imagers +imagery +images +imaginability +imaginable +imaginableness +imaginably +imaginaire +imaginal +imaginaries +imaginarily +imaginariness +imaginary +imagination +imaginational +imaginations +imaginative +imaginatively +imaginativeness +imagine +imagined +imaginer +imaginers +imagines +imaging +imagings +imagining +imaginings +imagism +imagist +imagistic +imagistically +imagists +imago +imagoes +imam +imamate +imamates +imams +imaret +imarets +imari +imbalance +imbalanced +imbalances +imbecile +imbecilely +imbeciles +imbecilic +imbecilities +imbecility +imbed +imbedded +imbedding +imbedment +imbeds +imbibe +imbibed +imbiber +imbibers +imbibes +imbibing +imbibition +imbibitional +imbibitions +imbitter +imbosom +imbricate +imbricated +imbricates +imbricating +imbrication +imbrications +imbroglio +imbroglios +imbrown +imbrue +imbrued +imbrues +imbruing +imbrute +imbruted +imbrutes +imbruting +imbue +imbued +imbues +imbuing +imidazole +imidazoles +imide +imides +imidic +imido +imine +imines +imino +imipramine +imipramines +imitable +imitate +imitated +imitates +imitating +imitation +imitational +imitations +imitative +imitatively +imitativeness +imitator +imitators +immaculacies +immaculacy +immaculate +immaculately +immaculateness +immane +immanence +immanency +immanent +immanentism +immanentist +immanentistic +immanentists +immanently +immanuel +immaterial +immaterialism +immaterialist +immaterialists +immaterialities +immateriality +immaterialize +immaterialized +immaterializes +immaterializing +immaterially +immaterialness +immature +immaturely +immatureness +immaturity +immeasurability +immeasurable +immeasurableness +immeasurably +immediacies +immediacy +immediate +immediately +immediateness +immedicable +immedicably +immelmann +immemorial +immemorially +immense +immensely +immenseness +immensities +immensity +immensurable +immerge +immerged +immergence +immergences +immerges +immerging +immerse +immersed +immerses +immersible +immersing +immersion +immersions +immesh +immeshed +immeshes +immeshing +immethodical +immethodically +immigrant +immigrants +immigrate +immigrated +immigrates +immigrating +immigration +immigrational +immigrations +imminence +imminencies +imminency +imminent +imminently +imminentness +immingle +immiscibility +immiscible +immiscibly +immitigability +immitigable +immitigableness +immitigably +immittance +immittances +immix +immixed +immixes +immixing +immixture +immixtures +immobile +immobilism +immobility +immobilization +immobilizations +immobilize +immobilized +immobilizer +immobilizers +immobilizes +immobilizing +immoderacies +immoderacy +immoderate +immoderately +immoderateness +immoderation +immodest +immodestly +immodesty +immolate +immolated +immolates +immolating +immolation +immolations +immolator +immolators +immoral +immoralism +immoralist +immoralists +immoralities +immorality +immorally +immortal +immortality +immortalization +immortalize +immortalized +immortalizer +immortalizers +immortalizes +immortalizing +immortally +immortals +immortelle +immortelles +immotile +immotility +immovability +immovable +immovableness +immovables +immovably +immune +immunes +immunities +immunity +immunization +immunizations +immunize +immunized +immunizes +immunizing +immunoassay +immunoassayable +immunoassays +immunoblot +immunoblotting +immunochemical +immunochemically +immunochemist +immunochemistry +immunochemists +immunocompetence +immunocompetent +immunocompromised +immunocytochemical +immunocytochemically +immunocytochemistry +immunodeficiencies +immunodeficiency +immunodeficient +immunodepressant +immunodepressants +immunodepression +immunodepressive +immunodiagnosis +immunodiagnostic +immunodiffusion +immunoelectrophoresis +immunoelectrophoretic +immunoelectrophoretically +immunofluorescence +immunofluorescences +immunofluorescent +immunogen +immunogenesis +immunogenetic +immunogenetically +immunogeneticist +immunogeneticists +immunogenetics +immunogenic +immunogenicity +immunogens +immunoglobulin +immunoglobulins +immunohematologic +immunohematological +immunohematologist +immunohematologists +immunohematology +immunohistochemical +immunohistochemistry +immunologic +immunological +immunologically +immunologist +immunologists +immunology +immunomodulator +immunomodulators +immunomodulatory +immunopathologic +immunopathological +immunopathologist +immunopathologists +immunopathology +immunoprecipitate +immunoprecipitated +immunoprecipitates +immunoprecipitating +immunoprecipitation +immunoreaction +immunoreactions +immunoreactive +immunoreactivity +immunoregulation +immunoregulatory +immunosorbent +immunosuppress +immunosuppressant +immunosuppressants +immunosuppressed +immunosuppresses +immunosuppressing +immunosuppression +immunosuppressive +immunotherapeutic +immunotherapies +immunotherapist +immunotherapists +immunotherapy +immure +immured +immurement +immurements +immures +immuring +immutability +immutable +immutableness +immutably +imogen +imp +impact +impacted +impacter +impacters +impacting +impaction +impactions +impactive +impactor +impactors +impacts +impaint +impainted +impainting +impaints +impair +impaired +impairer +impairers +impairing +impairment +impairments +impairs +impala +impalas +impale +impaled +impalement +impalements +impaler +impalers +impales +impaling +impalpability +impalpable +impalpably +impanel +impaneled +impaneling +impanelled +impanelling +impanelment +impanelments +impanels +imparadise +imparadised +imparadises +imparadising +imparities +imparity +impart +impartation +imparted +impartial +impartiality +impartially +impartialness +impartibility +impartible +impartibly +imparting +impartment +imparts +impassability +impassable +impassableness +impassably +impasse +impasses +impassibility +impassible +impassibleness +impassibly +impassion +impassioned +impassioning +impassions +impassive +impassively +impassiveness +impassivity +impaste +impasted +impastes +impasting +impasto +impastoed +impastos +impatience +impatiens +impatient +impatiently +impawn +impawned +impawning +impawns +impeach +impeachability +impeachable +impeached +impeachers +impeaches +impeaching +impeachment +impeachments +impearl +impearled +impearling +impearls +impeccability +impeccable +impeccably +impecuniosity +impecunious +impecuniously +impecuniousness +imped +impedance +impede +impeded +impeder +impeders +impedes +impediment +impedimenta +impedimental +impedimentary +impediments +impeding +impel +impelled +impeller +impellers +impelling +impellor +impellors +impels +impend +impended +impendent +impending +impends +impenetrability +impenetrable +impenetrableness +impenetrably +impenetrate +impenitence +impenitent +impenitently +impenitents +impera +imperative +imperatively +imperativeness +imperatives +imperator +imperatorial +imperators +imperatriz +imperceivable +imperceptibility +imperceptible +imperceptibleness +imperceptibly +imperceptive +imperceptiveness +imperceptivity +impercipience +impercipient +imperfect +imperfecta +imperfectability +imperfection +imperfections +imperfective +imperfectly +imperfectness +imperfects +imperforate +imperforates +imperia +imperial +imperialism +imperialist +imperialistic +imperialistically +imperialists +imperially +imperials +imperil +imperiled +imperiling +imperilled +imperilling +imperilment +imperilments +imperils +imperious +imperiously +imperiousness +imperishability +imperishable +imperishableness +imperishably +imperium +impermanence +impermanency +impermanent +impermanently +impermeabilities +impermeability +impermeable +impermeableness +impermeably +impermissibility +impermissible +impermissibly +impersonal +impersonality +impersonalization +impersonalize +impersonalized +impersonalizes +impersonalizing +impersonally +impersonate +impersonated +impersonates +impersonating +impersonation +impersonations +impersonator +impersonators +impertinence +impertinencies +impertinency +impertinent +impertinently +imperturbability +imperturbable +imperturbableness +imperturbably +impervious +imperviously +imperviousness +impetiginous +impetigo +impetigos +impetrate +impetrated +impetrates +impetrating +impetration +impetrations +impetuosities +impetuosity +impetuous +impetuously +impetuousness +impetus +impetuses +impieties +impiety +imping +impinge +impinged +impingement +impingements +impinger +impingers +impinges +impinging +impious +impiously +impiousness +impish +impishly +impishness +impitoyable +impitoyables +implacability +implacable +implacableness +implacably +implant +implantable +implantation +implantations +implanted +implanter +implanters +implanting +implants +implausibility +implausible +implausibleness +implausibly +implead +impleaded +impleading +impleads +implement +implementation +implementations +implemented +implementer +implementers +implementing +implementor +implementors +implements +implicate +implicated +implicates +implicating +implication +implications +implicative +implicatively +implicativeness +implicit +implicitly +implicitness +implied +implies +implode +imploded +implodes +imploding +imploration +implorations +implore +implored +implorer +implorers +implores +imploring +imploringly +implosion +implosions +implosive +implosives +implume +imply +implying +impolite +impolitely +impoliteness +impolitic +impolitical +impolitically +impoliticly +imponderability +imponderable +imponderableness +imponderables +imponderably +impone +imponed +impones +imponing +import +importability +importable +importance +importancy +important +importantly +importation +importations +imported +importer +importers +importing +imports +importunate +importunately +importunateness +importune +importuned +importunely +importuner +importuners +importunes +importuning +importunities +importunity +impose +imposed +imposer +imposers +imposes +imposing +imposingly +imposition +impositions +impossibilities +impossibility +impossible +impossibleness +impossibly +impost +imposter +imposters +imposthume +impostor +impostors +imposts +impostume +imposture +impostures +impotence +impotencies +impotency +impotent +impotently +impound +impoundage +impoundages +impounded +impounder +impounders +impounding +impoundment +impoundments +impounds +impoverish +impoverished +impoverisher +impoverishers +impoverishes +impoverishing +impoverishment +impoverishments +impracticability +impracticable +impracticableness +impracticably +impractical +impracticalities +impracticality +impractically +impracticalness +imprecate +imprecated +imprecates +imprecating +imprecation +imprecations +imprecator +imprecators +imprecatory +imprecise +imprecisely +impreciseness +imprecision +imprecisions +impregnability +impregnable +impregnableness +impregnably +impregnant +impregnants +impregnate +impregnated +impregnates +impregnating +impregnation +impregnations +impregnator +impregnators +impresa +impresario +impresarios +impresas +impress +impressed +impresser +impressers +impresses +impressibility +impressible +impressibly +impressing +impression +impressionability +impressionable +impressionableness +impressionably +impressionism +impressionist +impressionistic +impressionistically +impressionists +impressions +impressive +impressively +impressiveness +impressment +impressments +impressure +impressures +imprest +imprests +imprimatur +imprimaturs +imprimis +imprint +imprinted +imprinter +imprinters +imprinting +imprintings +imprints +imprison +imprisonable +imprisoned +imprisoning +imprisonment +imprisonments +imprisons +improbabilist +improbabilists +improbabilities +improbability +improbable +improbableness +improbably +improbity +impromptu +impromptus +improper +improperly +improperness +impropriate +impropriated +impropriates +impropriating +impropriation +improprieties +impropriety +improvability +improvable +improve +improved +improvement +improvements +improver +improvers +improves +improvidence +improvident +improvidently +improving +improvisation +improvisational +improvisationally +improvisations +improvisator +improvisatore +improvisatores +improvisatori +improvisatorial +improvisators +improvisatory +improvise +improvised +improviser +improvisers +improvises +improvising +improvisor +improvisors +improviste +imprudence +imprudent +imprudently +imps +impudence +impudences +impudencies +impudency +impudent +impudently +impudicity +impugn +impugnable +impugned +impugner +impugners +impugning +impugns +impuissance +impuissances +impuissant +impulse +impulsed +impulses +impulsing +impulsion +impulsive +impulsively +impulsiveness +impulsivity +impunities +impunity +impure +impurely +impureness +impurer +impurest +impurities +impurity +imputability +imputable +imputably +imputation +imputations +imputative +imputatively +impute +imputed +imputes +imputing +in +inability +inaccessibility +inaccessible +inaccessibly +inaccuracies +inaccuracy +inaccurate +inaccurately +inaccurateness +inaction +inactivate +inactivated +inactivates +inactivating +inactivation +inactivations +inactive +inactively +inactiveness +inactivity +inadequacies +inadequacy +inadequate +inadequately +inadequateness +inadmissibility +inadmissible +inadmissibly +inadvertence +inadvertencies +inadvertency +inadvertent +inadvertently +inadvisability +inadvisable +inadvisably +inalienability +inalienable +inalienably +inalterability +inalterable +inalterableness +inalterably +inamorata +inamoratas +inamorato +inamoratos +inane +inanely +inaneness +inaner +inanest +inanimate +inanimately +inanimateness +inanities +inanition +inanity +inapparent +inapparently +inappeasable +inappetence +inappetences +inappetencies +inappetency +inappetent +inapplicability +inapplicable +inapplicably +inapposite +inappositely +inappositeness +inappreciable +inappreciably +inappreciative +inappreciatively +inappreciativeness +inapproachability +inapproachable +inapproachably +inappropriate +inappropriately +inappropriateness +inapt +inaptitude +inaptly +inaptness +inarguable +inarguably +inarticulacy +inarticulate +inarticulately +inarticulateness +inartistic +inartistically +inasmuch +inassimilable +inattention +inattentive +inattentively +inattentiveness +inaudibility +inaudible +inaudibly +inaugural +inaugurals +inaugurate +inaugurated +inaugurates +inaugurating +inauguration +inaugurations +inaugurator +inaugurators +inauguratory +inauspicious +inauspiciously +inauspiciousness +inauthentic +inauthenticity +inboard +inboards +inborn +inbound +inbounded +inbounding +inbounds +inbreathe +inbreathed +inbreathes +inbreathing +inbred +inbreed +inbreeder +inbreeders +inbreeding +inbreedings +inbreeds +inbuilt +inca +incaic +incalculability +incalculable +incalculableness +incalculably +incalescence +incalescent +incan +incandesce +incandesced +incandescence +incandescent +incandescently +incandesces +incandescing +incans +incantation +incantational +incantations +incantatory +incapability +incapable +incapableness +incapably +incapacitant +incapacitants +incapacitate +incapacitated +incapacitates +incapacitating +incapacitation +incapacitations +incapacities +incapacity +incapsulate +incapsulated +incapsulates +incapsulating +incapsulation +incapsulations +incapsulator +incapsulators +incarcerate +incarcerated +incarcerates +incarcerating +incarceration +incarcerations +incarcerator +incarcerators +incarnadine +incarnadined +incarnadines +incarnadining +incarnate +incarnated +incarnates +incarnating +incarnation +incarnations +incarnator +incarnators +incas +incase +incased +incasement +incasements +incases +incasing +incautious +incautiously +incautiousness +incendiaries +incendiarism +incendiary +incense +incensed +incenses +incensing +incentive +incentives +incentivize +incentivized +incentivizes +incentivizing +incept +incepted +incepting +inception +inceptions +inceptive +inceptives +inceptor +inceptors +incepts +incertitude +incessancy +incessant +incessantly +incest +incestuous +incestuously +incestuousness +inch +inched +incher +inchers +inches +inching +inchmeal +inchoate +inchoately +inchoateness +inchoative +inchoatively +inchoatives +inchworm +inchworms +incidence +incidences +incident +incidental +incidentally +incidentals +incidents +incinerate +incinerated +incinerates +incinerating +incineration +incinerations +incinerator +incinerators +incipience +incipiency +incipient +incipiently +incipit +incipits +incise +incised +incises +incising +incision +incisions +incisive +incisively +incisiveness +incisor +incisors +incitation +incitations +incite +incited +incitement +incitements +inciter +inciters +incites +inciting +incivilities +incivility +inclasp +inclasped +inclasping +inclasps +inclemency +inclement +inclemently +inclinable +inclination +inclinations +incline +inclined +incliner +incliners +inclines +inclining +inclinometer +inclinometers +inclose +inclosed +incloses +inclosing +includable +include +included +includes +includible +including +inclusion +inclusionary +inclusions +inclusive +inclusively +inclusiveness +incoercible +incogitant +incognita +incognitas +incognito +incognitos +incognitum +incognizance +incognizant +incoherence +incoherencies +incoherency +incoherent +incoherently +incoherentness +incombustibility +incombustible +incombustibles +incombustibly +income +incomes +incoming +incomings +incommensurability +incommensurable +incommensurables +incommensurably +incommensurate +incommensurately +incommensurateness +incommode +incommoded +incommodes +incommoding +incommodious +incommodiously +incommodiousness +incommodities +incommodity +incommunicability +incommunicable +incommunicably +incommunicado +incommunicative +incommunicatively +incommunicativeness +incommutability +incommutable +incommutableness +incommutably +incomparability +incomparable +incomparableness +incomparably +incompatibilities +incompatibility +incompatible +incompatibleness +incompatibles +incompatibly +incompetence +incompetency +incompetent +incompetently +incompetents +incomplete +incompletely +incompleteness +incompletion +incompletions +incompliance +incompliancy +incompliant +incompliantly +incomprehensibility +incomprehensible +incomprehensibleness +incomprehensibly +incomprehension +incomprehensive +incomprehensively +incomprehensiveness +incompressibility +incompressible +incomputability +incomputable +inconceivability +inconceivable +inconceivableness +inconceivably +inconcinnity +inconclusive +inconclusively +inconclusiveness +incondensability +incondensable +incondensible +incondite +inconditely +inconformity +incongruence +incongruences +incongruent +incongruently +incongruities +incongruity +incongruous +incongruously +incongruousness +inconsequence +inconsequent +inconsequential +inconsequentiality +inconsequentially +inconsequentialness +inconsequently +inconsiderable +inconsiderableness +inconsiderably +inconsiderate +inconsiderately +inconsiderateness +inconsideration +inconsistence +inconsistences +inconsistencies +inconsistency +inconsistent +inconsistently +inconsolability +inconsolable +inconsolableness +inconsolably +inconsonance +inconsonant +inconsonantly +inconspicuous +inconspicuously +inconspicuousness +inconstancies +inconstancy +inconstant +inconstantly +inconsumable +inconsumably +incontestability +incontestable +incontestableness +incontestably +incontinence +incontinent +incontinently +incontrollable +incontrovertibility +incontrovertible +incontrovertibleness +incontrovertibly +inconvenience +inconvenienced +inconveniences +inconveniencing +inconvenient +inconveniently +inconvertibility +inconvertible +inconvertibleness +inconvertibly +inconvincible +incoordinate +incoordinately +incoordination +incoordinations +incorporable +incorporate +incorporated +incorporates +incorporating +incorporation +incorporations +incorporative +incorporator +incorporators +incorporeal +incorporeality +incorporeally +incorporeity +incorrect +incorrectly +incorrectness +incorrigibility +incorrigible +incorrigibleness +incorrigibles +incorrigibly +incorrupt +incorruptibility +incorruptible +incorruptibly +incorruption +incorruptly +incorruptness +increasable +increase +increased +increaser +increasers +increases +increasing +increasingly +increate +increately +incredibility +incredible +incredibleness +incredibly +incredulity +incredulous +incredulously +incredulousness +increment +incremental +incrementalism +incrementalist +incrementalists +incrementally +incremented +incrementing +increments +increscent +incretion +incretions +incriminate +incriminated +incriminates +incriminating +incrimination +incriminations +incriminator +incriminators +incriminatory +incrust +incrustation +incrustations +incrusted +incrusting +incrusts +incubate +incubated +incubates +incubating +incubation +incubational +incubations +incubative +incubator +incubators +incubi +incubus +incubuses +incudes +inculcate +inculcated +inculcates +inculcating +inculcation +inculcations +inculcator +inculcators +inculpable +inculpate +inculpated +inculpates +inculpating +inculpation +inculpations +inculpatory +incult +incumbencies +incumbency +incumbent +incumbently +incumbents +incunable +incunables +incunabula +incunabular +incunabulars +incunabulis +incunabulum +incur +incurability +incurable +incurableness +incurables +incurably +incuriosity +incurious +incuriously +incuriousness +incurred +incurrence +incurrences +incurrent +incurring +incurs +incursion +incursions +incurvate +incurvated +incurvates +incurvating +incurvation +incurvations +incurvature +incurve +incurved +incurves +incurving +incus +incuse +incused +incuses +incusing +indaba +indabas +indagate +indagated +indagates +indagating +indagation +indagator +indagators +indamine +indamines +indebted +indebtedness +indecencies +indecency +indecent +indecently +indecipherability +indecipherable +indecipherableness +indecipherably +indecision +indecisive +indecisively +indecisiveness +indeclinable +indecomposable +indecorous +indecorously +indecorousness +indecorum +indecorums +indeed +indefatigability +indefatigable +indefatigableness +indefatigably +indefeasibility +indefeasible +indefeasibly +indefectibility +indefectible +indefectibly +indefensibility +indefensible +indefensibleness +indefensibly +indefinability +indefinable +indefinableness +indefinables +indefinably +indefinite +indefinitely +indefiniteness +indehiscence +indehiscent +indelibility +indelible +indelibleness +indelibly +indelicacies +indelicacy +indelicate +indelicately +indelicateness +indemnification +indemnifications +indemnificatory +indemnified +indemnifier +indemnifiers +indemnifies +indemnify +indemnifying +indemnities +indemnity +indemonstrability +indemonstrable +indemonstrableness +indemonstrably +indene +indenes +indent +indentation +indentations +indented +indenter +indenters +indenting +indention +indents +indenture +indentured +indentures +indenturing +independence +independencies +independency +independent +independently +independents +inderal +indescribability +indescribable +indescribableness +indescribably +indestructibility +indestructible +indestructibleness +indestructibly +indeterminable +indeterminably +indeterminacy +indeterminate +indeterminately +indeterminateness +indetermination +indeterminations +indeterminism +indeterminist +indeterministic +indeterminists +index +indexation +indexed +indexer +indexers +indexes +indexical +indexing +india +indiaman +indian +indiana +indianapolis +indianism +indianist +indianists +indianization +indianize +indianized +indianizes +indianizing +indianness +indians +indic +indican +indicans +indicant +indicants +indicate +indicated +indicates +indicating +indication +indicational +indications +indicative +indicatively +indicatives +indicator +indicators +indicatory +indices +indicia +indicium +indics +indict +indictable +indicted +indictee +indictees +indicter +indicters +indicting +indiction +indictions +indictment +indictments +indictor +indictors +indicts +indie +indies +indifference +indifferency +indifferent +indifferentism +indifferentist +indifferentists +indifferently +indigen +indigence +indigene +indigenes +indigenization +indigenizations +indigenize +indigenized +indigenizes +indigenizing +indigenous +indigenously +indigenousness +indigens +indigent +indigently +indigents +indigested +indigestibility +indigestible +indigestibly +indigestion +indigirka +indign +indignant +indignantly +indignation +indignities +indignity +indigo +indigoes +indigos +indigotin +indigotins +indirect +indirection +indirectly +indirectness +indiscernible +indiscernibly +indisciplinable +indiscipline +indisciplined +indisciplines +indiscoverable +indiscreet +indiscreetly +indiscreetness +indiscrete +indiscretion +indiscretions +indiscriminate +indiscriminately +indiscriminateness +indiscriminating +indiscriminatingly +indiscrimination +indiscriminations +indiscriminative +indispensability +indispensable +indispensableness +indispensables +indispensably +indispose +indisposed +indisposes +indisposing +indisposition +indispositions +indisputable +indisputableness +indisputably +indissociable +indissociably +indissolubility +indissoluble +indissolubleness +indissolubly +indistinct +indistinctive +indistinctively +indistinctiveness +indistinctly +indistinctness +indistinguishability +indistinguishable +indistinguishableness +indistinguishably +indite +indited +inditement +inditements +inditer +inditers +indites +inditing +indium +indiums +individual +individualism +individualist +individualistic +individualistically +individualists +individualities +individuality +individualization +individualizations +individualize +individualized +individualizes +individualizing +individually +individuals +individuate +individuated +individuates +individuating +individuation +indivisibility +indivisible +indivisibleness +indivisibly +indo +indochina +indochinese +indocile +indocility +indocin +indoctrinate +indoctrinated +indoctrinates +indoctrinating +indoctrination +indoctrinations +indoctrinator +indoctrinators +indole +indoleacetic +indoleamine +indoleamines +indolebutyric +indolence +indolent +indolently +indoles +indologist +indologists +indology +indomethacin +indomethacins +indomitability +indomitable +indomitableness +indomitably +indonesia +indonesian +indonesians +indoor +indoors +indophenol +indophenols +indorsable +indorse +indorsed +indorsement +indorsements +indorser +indorsers +indorses +indorsing +indorsor +indorsors +indoxyl +indoxyls +indra +indraft +indrafts +indrawn +indri +indris +indubitability +indubitable +indubitableness +indubitably +induce +induced +inducement +inducements +inducer +inducers +induces +inducibility +inducible +inducing +induct +inductance +inducted +inductee +inductees +inducting +induction +inductions +inductive +inductively +inductiveness +inductor +inductors +inducts +indue +indued +indues +induing +indulge +indulged +indulgence +indulgenced +indulgences +indulgencing +indulgent +indulgently +indulger +indulgers +indulges +indulging +indult +indults +indument +indumenta +induments +indumentum +induplicate +indurate +indurated +indurates +indurating +induration +indurations +indurative +indus +indusia +indusium +industrial +industrialism +industrialist +industrialists +industrialization +industrializations +industrialize +industrialized +industrializes +industrializing +industrially +industrials +industries +industrious +industriously +industriousness +industry +industrywide +indwell +indweller +indwellers +indwelling +indwells +indwelt +inebriant +inebriants +inebriate +inebriated +inebriates +inebriating +inebriation +inebriations +inebriety +inedibility +inedible +inedibly +inedited +ineducability +ineducable +ineffability +ineffable +ineffableness +ineffably +ineffaceability +ineffaceable +ineffaceably +ineffective +ineffectively +ineffectiveness +ineffectual +ineffectuality +ineffectually +ineffectualness +inefficacious +inefficaciously +inefficaciousness +inefficacy +inefficiencies +inefficiency +inefficient +inefficiently +inegalitarian +inelastic +inelasticity +inelegance +inelegant +inelegantly +ineligibility +ineligible +ineligibles +ineligibly +ineloquence +ineloquent +ineloquently +ineluctability +ineluctable +ineluctably +ineludible +inenarrable +inept +ineptitude +ineptly +ineptness +inequalities +inequality +inequitable +inequitableness +inequitably +inequities +inequity +inequivalve +inequivalved +ineradicability +ineradicable +ineradicably +inerrancy +inerrant +inerrantism +inerrantist +inerrantists +inert +inertia +inertial +inertially +inertly +inertness +inescapable +inescapably +inessential +inessentiality +inessentials +inestimable +inestimably +inevitabilist +inevitabilists +inevitabilities +inevitability +inevitable +inevitableness +inevitably +inexact +inexactitude +inexactitudes +inexactly +inexactness +inexcusable +inexcusableness +inexcusably +inexhaustibility +inexhaustible +inexhaustibleness +inexhaustibly +inexistence +inexistent +inexorability +inexorable +inexorableness +inexorably +inexpedience +inexpediency +inexpedient +inexpediently +inexpensive +inexpensively +inexpensiveness +inexperience +inexperienced +inexpert +inexpertly +inexpertness +inexpiable +inexpiably +inexplainable +inexplainably +inexplicability +inexplicable +inexplicableness +inexplicably +inexplicit +inexpressibility +inexpressible +inexpressibleness +inexpressibly +inexpressive +inexpressively +inexpressiveness +inexpugnability +inexpugnable +inexpugnableness +inexpugnably +inexpungible +inextensible +inextinguishable +inextinguishably +inextirpable +inextricability +inextricable +inextricableness +inextricably +infall +infallibility +infallible +infallibleness +infallibly +infalling +infalls +infamies +infamous +infamously +infamousness +infamy +infancies +infancy +infant +infanta +infantas +infante +infantes +infanticidal +infanticide +infanticides +infantile +infantilism +infantility +infantilization +infantilizations +infantilize +infantilized +infantilizes +infantilizing +infantine +infantries +infantry +infantryman +infantrymen +infants +infantum +infarct +infarcted +infarction +infarctions +infarcts +infare +infares +infatuate +infatuated +infatuatedly +infatuates +infatuating +infatuation +infatuations +infauna +infaunal +infaunas +infaustus +infeasibility +infeasible +infect +infecta +infected +infecting +infection +infections +infectious +infectiously +infectiousness +infective +infectiveness +infectivity +infector +infectors +infects +infecundity +infelicities +infelicitous +infelicitously +infelicity +infer +inferable +inferably +inference +inferences +inferential +inferentially +inferior +inferiority +inferiorly +inferiors +infernal +infernally +inferno +infernos +inferred +inferrer +inferrers +inferrible +inferring +infers +infertile +infertility +infest +infestant +infestants +infestation +infestations +infested +infester +infesters +infesting +infests +infidel +infidelities +infidelity +infidelium +infidels +infield +infielder +infielders +infields +infight +infighter +infighters +infighting +infights +infill +infills +infiltrate +infiltrated +infiltrates +infiltrating +infiltration +infiltrations +infiltrative +infiltrator +infiltrators +infinite +infinitely +infiniteness +infinitesimal +infinitesimally +infinitesimals +infinities +infinitival +infinitive +infinitively +infinitives +infinitude +infinitudes +infinitum +infinity +infirm +infirmaries +infirmary +infirmities +infirmity +infirmly +infix +infixation +infixations +infixed +infixes +infixing +inflame +inflamed +inflamer +inflamers +inflames +inflaming +inflammability +inflammable +inflammableness +inflammably +inflammation +inflammations +inflammatorily +inflammatory +inflatable +inflatables +inflate +inflated +inflater +inflaters +inflates +inflating +inflation +inflationary +inflationism +inflationist +inflationists +inflations +inflator +inflators +inflect +inflectable +inflected +inflecting +inflection +inflectional +inflectionally +inflections +inflective +inflector +inflectors +inflects +inflexed +inflexibility +inflexible +inflexibleness +inflexibly +inflexion +inflexions +inflict +inflicted +inflicter +inflicters +inflicting +infliction +inflictions +inflictive +inflictor +inflictors +inflicts +inflorescence +inflorescences +inflorescent +inflow +inflows +influence +influenceable +influenced +influencer +influencers +influences +influencing +influent +influential +influentially +influentials +influents +influenza +influenzal +influx +influxes +info +infobahn +infold +infolded +infolder +infolders +infolding +infoldment +infoldments +infolds +infomercial +infomercials +inform +informal +informalities +informality +informally +informant +informants +informatics +information +informational +informationally +informative +informatively +informativeness +informatorily +informatory +informed +informedly +informer +informercial +informercials +informers +informing +informs +infotainment +infotainments +infra +infraclass +infraclasses +infract +infracted +infracting +infraction +infractions +infractor +infractors +infracts +infrahuman +infrahumans +infrangibility +infrangible +infrangibly +infrared +infrareds +infrasonic +infrasound +infrasounds +infraspecific +infrastructure +infrastructures +infrequence +infrequency +infrequent +infrequently +infringe +infringed +infringement +infringements +infringer +infringers +infringes +infringing +infructescence +infructescences +infundibula +infundibular +infundibulate +infundibuliform +infundibulum +infuriate +infuriated +infuriates +infuriating +infuriatingly +infuriation +infuriations +infuse +infused +infuser +infusers +infuses +infusibility +infusible +infusibleness +infusing +infusion +infusions +infusorial +infusorian +infusorians +infâme +ing +ingather +ingathered +ingathering +ingathers +ingeminate +ingeminated +ingeminates +ingeminating +ingenious +ingeniously +ingeniousness +ingenue +ingenues +ingenuities +ingenuity +ingenuous +ingenuously +ingenuousness +ingest +ingesta +ingested +ingestible +ingesting +ingestion +ingestions +ingestive +ingests +ingle +inglenook +inglenooks +ingles +inglese +inglorious +ingloriously +ingloriousness +ingoing +ingot +ingots +ingrain +ingrained +ingrainedly +ingraining +ingrains +ingrate +ingrates +ingratiate +ingratiated +ingratiates +ingratiating +ingratiatingly +ingratiation +ingratiations +ingratiatory +ingratitude +ingredient +ingredients +ingres +ingress +ingression +ingressions +ingressive +ingressiveness +ingrowing +ingrown +ingrownness +ingrowth +ingrowths +inguinal +inguinale +ingurgitate +ingurgitated +ingurgitates +ingurgitating +ingurgitation +ingurgitations +ingénue +ingénues +inhabit +inhabitability +inhabitable +inhabitancies +inhabitancy +inhabitant +inhabitants +inhabitation +inhabitations +inhabited +inhabiter +inhabiters +inhabiting +inhabits +inhalant +inhalants +inhalation +inhalational +inhalations +inhalator +inhalators +inhale +inhaled +inhaler +inhalers +inhales +inhaling +inharmonic +inharmonies +inharmonious +inharmoniously +inharmoniousness +inharmony +inhere +inhered +inherence +inherency +inherent +inherently +inheres +inhering +inherit +inheritability +inheritable +inheritableness +inheritance +inheritances +inherited +inheriting +inheritor +inheritors +inheritress +inheritresses +inheritrix +inheritrixes +inherits +inhibin +inhibins +inhibit +inhibitable +inhibited +inhibiter +inhibiters +inhibiting +inhibition +inhibitions +inhibitive +inhibitor +inhibitors +inhibitory +inhibits +inholder +inholders +inholding +inholdings +inhomogeneities +inhomogeneity +inhomogeneous +inhospitable +inhospitableness +inhospitably +inhospitality +inhuman +inhumane +inhumanely +inhumanities +inhumanity +inhumanly +inhumanness +inhumation +inhumations +inhume +inhumed +inhumer +inhumers +inhumes +inhuming +inigo +inimical +inimically +inimitability +inimitable +inimitableness +inimitably +inion +inions +iniquities +iniquitous +iniquitously +iniquitousness +iniquity +initial +initialed +initialing +initialism +initialization +initializations +initialize +initialized +initializer +initializers +initializes +initializing +initialled +initialling +initially +initialness +initials +initiate +initiated +initiates +initiating +initiation +initiations +initiative +initiatively +initiatives +initiator +initiators +initiatory +initio +inject +injectable +injectables +injectant +injectants +injected +injecting +injection +injections +injective +injector +injectors +injects +injudicious +injudiciously +injudiciousness +injunction +injunctions +injunctive +injure +injured +injurer +injurers +injures +injuries +injuring +injurious +injuriously +injuriousness +injury +injustice +injustices +ink +inkberries +inkberry +inkblot +inkblots +inked +inker +inkers +inkhorn +inkhorns +inkier +inkiest +inkiness +inking +inkle +inkles +inkling +inklings +inkpot +inkpots +inks +inkstand +inkstands +inkstone +inkstones +inkwell +inkwells +inky +inlace +inlaced +inlacement +inlacements +inlaces +inlacing +inlaid +inland +inlander +inlanders +inlay +inlayer +inlayers +inlaying +inlays +inlet +inlets +inlier +inliers +inly +inlying +inmate +inmates +inmesh +inmeshed +inmeshes +inmeshing +inmeshment +inmeshments +inmost +inn +innards +innate +innately +innateness +inner +innerly +innermost +innerness +innersole +innersoles +innerspring +innersprings +innervate +innervated +innervates +innervating +innervation +innervational +innervations +innerve +innerved +innerves +innerving +innerwear +innigkeit +inning +innings +innkeeper +innkeepers +innocence +innocencies +innocency +innocent +innocently +innocents +innocuous +innocuously +innocuousness +innominate +innovate +innovated +innovates +innovating +innovation +innovational +innovations +innovative +innovatively +innovativeness +innovator +innovators +innovatory +inns +innsbruck +innuendo +innuendoes +innuit +innuits +innumerable +innumerableness +innumerably +innumeracy +innumerate +innumerates +innumerous +innutrition +innutritious +inobservance +inobservant +inobtrusive +inocula +inoculability +inoculable +inoculant +inoculants +inoculate +inoculated +inoculates +inoculating +inoculation +inoculations +inoculative +inoculator +inoculators +inoculum +inoculums +inodorous +inoffensive +inoffensively +inoffensiveness +inofficious +inoperable +inoperably +inoperative +inoperativeness +inoperculate +inopportune +inopportunely +inopportuneness +inordinacy +inordinate +inordinately +inordinateness +inorganic +inorganically +inosculate +inosculated +inosculates +inosculating +inosculation +inosculations +inositol +inositols +inotropic +inpatient +inpatients +inphase +inpouring +inpourings +input +inputs +inputted +inputting +inquest +inquests +inquietude +inquietudes +inquiline +inquilines +inquilinism +inquilinity +inquilinous +inquire +inquired +inquirer +inquirers +inquires +inquiries +inquiring +inquiringly +inquiry +inquisition +inquisitional +inquisitions +inquisitive +inquisitively +inquisitiveness +inquisitor +inquisitorial +inquisitorially +inquisitors +inro +inroad +inroads +inrush +inrushes +ins +insalivate +insalivated +insalivates +insalivating +insalivation +insalivations +insalubrious +insalubriously +insalubrity +insane +insanely +insaneness +insanitary +insanitation +insanities +insanity +insatiability +insatiable +insatiableness +insatiably +insatiate +insatiately +insatiateness +inscape +inscapes +inscribe +inscribed +inscriber +inscribers +inscribes +inscribing +inscription +inscriptional +inscriptions +inscriptive +inscriptively +inscroll +inscrolled +inscrolling +inscrolls +inscrutability +inscrutable +inscrutableness +inscrutably +insculp +insculped +insculping +insculps +inseam +inseams +insect +insectaria +insectaries +insectarium +insectary +insecticidal +insecticidally +insecticide +insecticides +insectile +insectival +insectivore +insectivores +insectivorous +insects +insecure +insecurely +insecureness +insecurities +insecurity +inselberg +inselberge +inselberges +inselbergs +inseminate +inseminated +inseminates +inseminating +insemination +inseminations +inseminator +inseminators +insensate +insensately +insensateness +insensibility +insensible +insensibleness +insensibly +insensitive +insensitively +insensitiveness +insensitivity +insentience +insentient +inseparability +inseparable +inseparableness +inseparably +insert +inserted +inserter +inserters +inserting +insertion +insertional +insertions +inserts +insessorial +inset +insets +insetted +insetting +inshallah +inshore +inshrine +inshrined +inshrinement +inshrinements +inshrines +inshrining +inside +insider +insiders +insides +insidious +insidiously +insidiousness +insight +insightful +insightfully +insightfulness +insights +insigne +insignia +insignias +insignificance +insignificancies +insignificancy +insignificant +insignificantly +insincere +insincerely +insincerity +insinuate +insinuated +insinuates +insinuating +insinuatingly +insinuation +insinuations +insinuative +insinuator +insinuators +insinuatory +insipid +insipidities +insipidity +insipidly +insipidness +insipidus +insipience +insist +insisted +insistence +insistency +insistent +insistently +insister +insisters +insisting +insistingly +insists +insnare +insnared +insnarement +insnarements +insnarer +insnarers +insnares +insnaring +insobriety +insociability +insociable +insociably +insofar +insolate +insolated +insolates +insolating +insolation +insolations +insole +insolence +insolent +insolently +insolents +insoles +insolubility +insolubilization +insolubilizations +insolubilize +insolubilized +insolubilizes +insolubilizing +insoluble +insolubleness +insolubles +insolubly +insolvability +insolvable +insolvably +insolvencies +insolvency +insolvent +insolvents +insomnia +insomniac +insomniacs +insomuch +insouciance +insouciant +insouciantly +insoul +insouled +insouling +insouls +inspan +inspanned +inspanning +inspans +inspect +inspected +inspecting +inspection +inspectional +inspections +inspective +inspector +inspectoral +inspectorate +inspectorates +inspectorial +inspectors +inspectorship +inspectorships +inspects +insphere +insphered +inspheres +insphering +inspiration +inspirational +inspirationally +inspirations +inspirator +inspirators +inspiratory +inspire +inspired +inspiredly +inspirer +inspirers +inspires +inspiring +inspiringly +inspirit +inspirited +inspiriting +inspiritingly +inspirits +inspissate +inspissated +inspissates +inspissating +inspissation +inspissations +inspissator +inspissators +instabilities +instability +instal +install +installation +installations +installed +installer +installers +installing +installment +installments +installs +instalment +instalments +instals +instance +instanced +instances +instancies +instancing +instancy +instant +instantaneity +instantaneous +instantaneously +instantaneousness +instanter +instantiate +instantiated +instantiates +instantiating +instantiation +instantiations +instantly +instantness +instants +instar +instarred +instarring +instars +instate +instated +instatement +instates +instating +instauration +instaurations +instead +instep +insteps +instigate +instigated +instigates +instigating +instigation +instigations +instigative +instigator +instigators +instil +instill +instillation +instillations +instilled +instiller +instillers +instilling +instillment +instills +instils +instinct +instinctive +instinctively +instincts +instinctual +instinctually +institute +instituted +instituter +instituters +institutes +instituting +institution +institutional +institutionalism +institutionalist +institutionalists +institutionalization +institutionalizations +institutionalize +institutionalized +institutionalizes +institutionalizing +institutionally +institutions +institutor +institutors +instroke +instrokes +instruct +instructed +instructing +instruction +instructional +instructions +instructive +instructively +instructiveness +instructor +instructors +instructorship +instructorships +instructress +instructresses +instructs +instrument +instrumental +instrumentalism +instrumentalist +instrumentalists +instrumentalities +instrumentality +instrumentally +instrumentals +instrumentation +instrumented +instrumenting +instruments +insubordinate +insubordinately +insubordinates +insubordination +insubordinations +insubstantial +insubstantiality +insufferable +insufferableness +insufferably +insufficiencies +insufficiency +insufficient +insufficiently +insufflate +insufflated +insufflates +insufflating +insufflation +insufflations +insufflator +insufflators +insulant +insulants +insular +insularism +insularity +insularly +insulate +insulated +insulates +insulating +insulation +insulations +insulative +insulator +insulators +insulin +insult +insulted +insulter +insulters +insulting +insultingly +insults +insuperability +insuperable +insuperableness +insuperably +insupportable +insupportableness +insupportably +insuppressible +insuppressibly +insurability +insurable +insurance +insurances +insure +insured +insureds +insurer +insurers +insures +insurgence +insurgencies +insurgency +insurgent +insurgently +insurgents +insuring +insurmountability +insurmountable +insurmountableness +insurmountably +insurrection +insurrectional +insurrectionary +insurrectionism +insurrectionist +insurrectionists +insurrections +insusceptibility +insusceptible +insusceptibly +intact +intactly +intactness +intaglio +intaglios +intake +intakes +intangibility +intangible +intangibleness +intangibles +intangibly +intarsia +intarsias +integer +integers +integrability +integrable +integral +integrality +integrally +integrals +integrand +integrands +integrant +integrate +integrated +integrates +integrating +integration +integrationist +integrationists +integrations +integrative +integrator +integrators +integrity +integro +integument +integumentary +intellect +intellection +intellections +intellective +intellectively +intellectronics +intellects +intellectual +intellectualism +intellectualist +intellectualistic +intellectualists +intellectuality +intellectualization +intellectualizations +intellectualize +intellectualized +intellectualizer +intellectualizers +intellectualizes +intellectualizing +intellectually +intellectualness +intellectuals +intelligam +intelligence +intelligencer +intelligencers +intelligences +intelligent +intelligential +intelligently +intelligentsia +intelligibility +intelligible +intelligibleness +intelligibly +intelligunt +intelsat +intemperance +intemperate +intemperately +intemperateness +intend +intendance +intendances +intendancies +intendancy +intendant +intendants +intended +intendedly +intender +intenders +intending +intendment +intendments +intends +intenerate +intenerated +intenerates +intenerating +inteneration +intenerations +intense +intensely +intenseness +intenser +intensest +intensification +intensifications +intensified +intensifier +intensifiers +intensifies +intensify +intensifying +intension +intensional +intensionality +intensionally +intensions +intensities +intensity +intensive +intensively +intensiveness +intensives +intent +intention +intentional +intentionality +intentionally +intentioned +intentions +intently +intentness +intents +inter +interabang +interabangs +interact +interactant +interactants +interacted +interacting +interaction +interactional +interactions +interactive +interactively +interactivity +interacts +interagency +interallelic +interallied +interanimation +interanimations +interannual +interassociation +interassociations +interatomic +interavailability +interbank +interbasin +interbed +interbehavior +interbehavioral +interborough +interbrain +interbrains +interbranch +interbred +interbreed +interbreeding +interbreeds +intercalary +intercalate +intercalated +intercalates +intercalating +intercalation +intercalations +intercalative +intercalibration +intercampus +intercaste +intercede +interceded +interceder +interceders +intercedes +interceding +intercell +intercellular +intercensal +intercept +intercepted +intercepter +intercepters +intercepting +interception +interceptions +interceptive +interceptor +interceptors +intercepts +intercession +intercessional +intercessions +intercessor +intercessors +intercessory +interchain +interchange +interchangeability +interchangeable +interchangeableness +interchangeably +interchanged +interchanger +interchangers +interchanges +interchanging +interchannel +interchromosomal +interchurch +intercity +interclan +interclass +interclavicle +interclavicles +interclavicular +interclub +intercluster +intercoastal +intercollegiate +intercolonial +intercolumniation +intercolumniations +intercom +intercommunal +intercommunicate +intercommunicated +intercommunicates +intercommunicating +intercommunication +intercommunications +intercommunicative +intercommunion +intercommunions +intercommunity +intercompany +intercomparable +intercompare +intercomparison +intercomprehensibility +intercoms +interconnect +interconnectable +interconnected +interconnectedness +interconnectible +interconnecting +interconnection +interconnections +interconnectivity +interconnects +intercontinental +interconversion +interconvert +interconverted +interconvertibility +interconvertible +interconverting +interconverts +intercool +intercooled +intercooler +intercoolers +intercooling +intercools +intercorporate +intercorrelate +intercorrelation +intercortical +intercostal +intercostals +intercountry +intercounty +intercouple +intercourse +intercrater +intercrop +intercropped +intercropping +intercrops +intercross +intercrystalline +intercultural +interculturally +interculture +intercurrent +intercut +intercuts +intercutting +interdealer +interdenominational +interdental +interdentally +interdentals +interdepartmental +interdepartmentally +interdepend +interdependence +interdependencies +interdependency +interdependent +interdependently +interdialectal +interdict +interdicted +interdicting +interdiction +interdictions +interdictive +interdictively +interdictor +interdictors +interdictory +interdicts +interdictus +interdiffuse +interdiffusion +interdigitate +interdigitated +interdigitates +interdigitating +interdigitation +interdisciplinary +interdistrict +interdivisional +interdominion +interelectrode +interelectron +interelectronic +interepidemic +interest +interested +interestedly +interestedness +interesting +interestingly +interestingness +interests +interethnic +interface +interfaced +interfaces +interfacial +interfacing +interfacings +interfaculty +interfaith +interfamilial +interfamily +interfascicular +interfere +interfered +interference +interferences +interferential +interferer +interferers +interferes +interfering +interferingly +interferogram +interferograms +interferometer +interferometers +interferometric +interferometrically +interferometry +interferon +interfertile +interfertility +interfiber +interfile +interfirm +interflow +interfluve +interfluves +interfluvial +interfold +interfraternity +interfuse +interfused +interfuses +interfusing +interfusion +intergalactic +intergalactically +intergang +intergeneration +intergenerational +intergeneric +interglacial +interglacials +intergovernmental +intergovernmentally +intergradation +intergradational +intergradations +intergrade +intergraded +intergrades +intergrading +intergraft +intergranular +intergroup +intergrowth +interhemispheric +interim +interindividual +interindustry +interinfluence +interinstitutional +interinvolve +interionic +interior +interiority +interiorization +interiorizations +interiorize +interiorized +interiorizes +interiorizing +interiorly +interiors +interisland +interject +interjected +interjecting +interjection +interjectional +interjectionally +interjections +interjector +interjectors +interjectory +interjects +interjurisdictional +interlace +interlaced +interlacement +interlaces +interlacing +interlacustrine +interlaken +interlaminar +interlaminate +interlaminated +interlaminates +interlaminating +interlamination +interlaminations +interlanguage +interlanguages +interlard +interlarded +interlarding +interlards +interlay +interlayer +interleaf +interleave +interleaved +interleaves +interleaving +interlend +interleukin +interleukins +interlibrary +interline +interlinear +interlinearly +interlineation +interlined +interliner +interlines +interlingua +interlining +interlinings +interlink +interlinked +interlinking +interlinks +interlobular +interlocal +interlock +interlocked +interlocking +interlocks +interlocution +interlocutions +interlocutor +interlocutors +interlocutory +interlope +interloped +interloper +interlopers +interlopes +interloping +interlude +interludes +interlunar +interlunary +intermale +intermarginal +intermarriage +intermarriages +intermarried +intermarries +intermarry +intermarrying +intermeddle +intermeddled +intermeddler +intermeddlers +intermeddles +intermeddling +intermediacy +intermediaries +intermediary +intermediate +intermediated +intermediately +intermediateness +intermediates +intermediating +intermediation +intermediations +intermediator +intermediators +intermedin +intermedins +intermembrane +intermenstrual +interment +interments +intermesh +intermeshed +intermeshes +intermeshing +intermetallic +intermezzi +intermezzo +intermezzos +interminability +interminable +interminableness +interminably +intermingle +intermingled +intermingles +intermingling +interministerial +intermission +intermissionless +intermissions +intermit +intermitotic +intermits +intermitted +intermittence +intermittency +intermittent +intermittently +intermitter +intermitters +intermitting +intermix +intermixed +intermixes +intermixing +intermixture +intermixtures +intermodal +intermodulation +intermodulations +intermolecular +intermolecularly +intermont +intermontane +intermountain +intern +internal +internality +internalization +internalizations +internalize +internalized +internalizes +internalizing +internally +internals +international +internationale +internationalism +internationalist +internationalists +internationality +internationalization +internationalizations +internationalize +internationalized +internationalizes +internationalizing +internationally +internationals +interne +internecine +interned +internee +internees +internet +interneuron +interneuronal +interneurons +interning +internist +internists +internment +internodal +internode +internodes +interns +internship +internships +internuclear +internucleon +internucleonic +internucleotide +internuncial +internuncially +internuncio +internuncios +interobserver +interocean +interoceanic +interoceptive +interoceptor +interoceptors +interoffice +interoperability +interoperable +interoperative +interorbital +interorgan +interorganizational +interosculate +interosculated +interosculates +interosculating +interpandemic +interparish +interparochial +interparoxysmal +interparticle +interparty +interpellate +interpellated +interpellates +interpellating +interpellation +interpellations +interpellator +interpellators +interpenetrate +interpenetrated +interpenetrates +interpenetrating +interpenetration +interpenetrations +interperceptual +interpermeate +interpersonal +interpersonally +interphalangeal +interphase +interphased +interphases +interphasing +interplanetary +interplant +interplanted +interplanting +interplants +interplay +interplayed +interplaying +interplays +interplead +interpleaded +interpleader +interpleaders +interpleading +interpleads +interpluvial +interpoint +interpol +interpolate +interpolated +interpolates +interpolating +interpolation +interpolations +interpolative +interpolator +interpolators +interpopulation +interpopulational +interposal +interpose +interposed +interposer +interposers +interposes +interposing +interposition +interpositions +interpret +interpretability +interpretable +interpretableness +interpretably +interpretation +interpretational +interpretations +interpretative +interpretatively +interpreted +interpreter +interpreters +interpreting +interpretive +interpretively +interprets +interprofessional +interprovincial +interproximal +interpsychic +interpupillary +interracial +interracially +interred +interregional +interregna +interregnal +interregnum +interregnums +interrelate +interrelated +interrelatedly +interrelatedness +interrelates +interrelating +interrelation +interrelations +interrelationship +interrelationships +interreligious +interrenal +interring +interrobang +interrobangs +interrogate +interrogated +interrogatee +interrogatees +interrogates +interrogating +interrogation +interrogational +interrogations +interrogative +interrogatively +interrogatives +interrogator +interrogatories +interrogatorily +interrogators +interrogatory +interrogee +interrogees +interrow +interrupt +interrupted +interrupter +interrupters +interruptible +interrupting +interruption +interruptions +interruptive +interruptor +interruptors +interrupts +interruptus +inters +interscholastic +interscholastically +interschool +intersect +intersected +intersecting +intersection +intersectional +intersections +intersects +intersegment +intersegmental +intersensory +interservice +intersession +intersessional +intersessions +intersex +intersexes +intersexual +intersexuality +intersexually +intersocietal +intersociety +interspace +interspaced +interspaces +interspacing +interspatial +interspecies +interspecific +intersperse +interspersed +interspersedly +intersperses +interspersing +interspersion +interspersions +interstadial +interstage +interstate +interstates +interstation +interstellar +intersterile +intersterility +interstice +interstices +interstimulation +interstimulus +interstitial +interstitially +interstrain +interstrand +interstratification +interstratify +intersubjective +intersubjectively +intersubjectivity +intersubstitutability +intersubstitutable +intersystem +interterm +interterminal +interterritorial +intertestamental +intertexture +intertextures +intertidal +intertidally +intertie +interties +intertill +intertillage +intertilled +intertilling +intertills +intertranslatable +intertransmutation +intertrial +intertribal +intertroop +intertropical +intertwine +intertwined +intertwinement +intertwinements +intertwines +intertwining +intertwist +intertwisted +intertwisting +intertwists +interunion +interunit +interuniversity +interurban +interval +intervale +intervales +intervalic +intervalley +intervallic +intervalometer +intervalometers +intervals +intervene +intervened +intervener +interveners +intervenes +intervening +intervenor +intervenors +intervention +interventional +interventionism +interventionist +interventionists +interventions +interventricular +intervertebral +intervertebrally +interview +interviewable +interviewed +interviewee +interviewees +interviewer +interviewers +interviewing +interviews +intervillage +intervisibility +intervisible +intervisitation +intervocalic +intervocalically +interwar +interweave +interweaves +interweaving +interwired +interwork +interworking +interwove +interwoven +interzonal +interzone +intestacies +intestacy +intestate +intestates +intestinal +intestinally +intestine +intestines +inthrall +inthralled +inthralling +inthrallingly +inthrallment +inthralls +inthrone +inthroned +inthronement +inthronements +inthrones +inthroning +inti +intima +intimacies +intimacy +intimae +intimal +intimas +intimate +intimated +intimately +intimateness +intimater +intimaters +intimates +intimating +intimation +intimations +intime +intimidate +intimidated +intimidates +intimidating +intimidatingly +intimidation +intimidations +intimidator +intimidators +intimidatory +intinction +intinctions +intine +intines +intis +intitule +intituled +intitules +intituling +into +intolerability +intolerable +intolerableness +intolerably +intolerance +intolerant +intolerantly +intolerantness +intonate +intonated +intonates +intonating +intonation +intonational +intonations +intone +intoned +intonement +intonements +intoner +intoners +intones +intoning +intoxicant +intoxicants +intoxicate +intoxicated +intoxicatedly +intoxicates +intoxicating +intoxicatingly +intoxication +intoxications +intoxicative +intoxicator +intoxicators +intra +intracardiac +intracardial +intracardially +intracellular +intracellularly +intracerebral +intracerebrally +intracoastal +intracompany +intracranial +intracranially +intractability +intractable +intractableness +intractably +intracutaneous +intracutaneously +intracytoplasmic +intraday +intradepartmental +intradermal +intradermally +intrados +intradoses +intraepithelial +intragalactic +intragenic +intralingual +intramolecular +intramolecularly +intramural +intramurally +intramuscular +intramuscularly +intranasal +intranasally +intransigeance +intransigeant +intransigeantly +intransigence +intransigency +intransigent +intransigently +intransigents +intransitive +intransitively +intransitiveness +intransitives +intransitivity +intranuclear +intraocular +intraocularly +intraperitoneal +intraperitoneally +intrapersonal +intrapersonally +intraplate +intrapopulation +intrapreneur +intrapreneurial +intrapreneurialism +intrapreneurially +intrapreneurs +intrapsychic +intrapsychically +intrapulmonary +intraspecies +intraspecific +intrastate +intrathecal +intrathecally +intrathoracic +intrathoracically +intrauterine +intravasation +intravasations +intravascular +intravascularly +intravenous +intravenouses +intravenously +intraventricular +intraventricularly +intravital +intravitally +intravitam +intrazonal +intreat +intreated +intreating +intreatingly +intreatment +intreats +intrench +intrenched +intrenches +intrenching +intrenchment +intrenchments +intrepid +intrepidity +intrepidly +intrepidness +intricacies +intricacy +intricate +intricately +intricateness +intrigant +intrigants +intriguant +intriguants +intrigue +intrigued +intriguer +intriguers +intrigues +intriguing +intriguingly +intrinsic +intrinsical +intrinsically +intro +introduce +introduced +introducer +introducers +introduces +introducible +introducing +introduction +introductions +introductorily +introductory +introgressant +introgressants +introgression +introgressions +introgressive +introit +introits +introject +introjected +introjecting +introjection +introjections +introjects +intromission +intromissions +intromissive +intromit +intromits +intromitted +intromittent +intromitter +intromitters +intromitting +intron +introns +introrse +intros +introspect +introspected +introspecting +introspection +introspectional +introspectionism +introspectionist +introspectionistic +introspectionists +introspective +introspectively +introspectiveness +introspects +introversion +introversions +introversive +introversively +introvert +introverted +introverting +introverts +intrude +intruded +intruder +intruders +intrudes +intruding +intrusion +intrusions +intrusive +intrusively +intrusiveness +intrust +intrusted +intrusting +intrusts +intubate +intubated +intubates +intubating +intubation +intubational +intubationally +intubations +intuit +intuitable +intuited +intuiting +intuition +intuitional +intuitionally +intuitionism +intuitionist +intuitionists +intuitions +intuitive +intuitively +intuitiveness +intuits +intumesce +intumesced +intumescence +intumescences +intumescent +intumesces +intumescing +intussuscept +intussuscepted +intussuscepting +intussusception +intussusceptions +intussusceptive +intussuscepts +intwine +intwined +intwinement +intwinements +intwines +intwining +intwist +intwisted +intwisting +intwists +inuit +inuits +inuktitut +inulase +inulases +inulin +inulins +inunction +inunctions +inundate +inundated +inundates +inundating +inundation +inundations +inundator +inundators +inundatory +inupiaq +inupiaqs +inupiat +inupiats +inure +inured +inurement +inurements +inures +inuring +inurn +inurned +inurning +inurns +inutile +inutilely +inutility +inuvik +invade +invaded +invader +invaders +invades +invading +invaginate +invaginated +invaginates +invaginating +invagination +invaginations +invalid +invalidate +invalidated +invalidates +invalidating +invalidation +invalidations +invalidator +invalidators +invalided +invaliding +invalidism +invalidity +invalidly +invalids +invaluable +invaluableness +invaluably +invariability +invariable +invariableness +invariably +invariance +invariant +invariantly +invariants +invasion +invasions +invasive +invasively +invasiveness +invective +invectively +invectiveness +invectives +inveigh +inveighed +inveigher +inveighers +inveighing +inveighs +inveigle +inveigled +inveiglement +inveiglements +inveigler +inveiglers +inveigles +inveigling +invenient +invenit +invent +invented +inventible +inventing +invention +inventional +inventions +inventive +inventively +inventiveness +inventor +inventorial +inventorially +inventoried +inventories +inventors +inventory +inventorying +inventress +inventresses +invents +inveracities +inveracity +invercargill +inverness +invernesses +inverse +inversely +inverses +inversion +inversions +inversive +invert +invertase +invertases +invertebrate +invertebrates +inverted +inverter +inverters +invertible +inverting +inverts +invest +investable +invested +investigable +investigate +investigated +investigates +investigating +investigation +investigational +investigations +investigative +investigator +investigatorial +investigators +investigatory +investing +investiture +investitures +investment +investments +investor +investors +invests +inveteracy +inveterate +inveterately +inveterateness +inviability +inviable +invidia +invidious +invidiously +invidiousness +invigilate +invigilated +invigilates +invigilating +invigilation +invigilations +invigilator +invigilators +invigorant +invigorants +invigorate +invigorated +invigorates +invigorating +invigoratingly +invigoration +invigorations +invigorative +invigorator +invigorators +invincibility +invincible +invincibleness +invincibly +inviolability +inviolable +inviolableness +inviolably +inviolacy +inviolate +inviolately +inviolateness +inviscid +invisibility +invisible +invisibleness +invisibles +invisibly +invita +invitation +invitational +invitationals +invitations +invitatories +invitatory +invite +invited +invitee +invitees +inviter +inviters +invites +inviting +invitingly +invocate +invocated +invocates +invocating +invocation +invocational +invocations +invocatory +invoice +invoiced +invoices +invoicing +invoke +invoked +invoker +invokers +invokes +invoking +involucel +involucels +involucra +involucral +involucrate +involucre +involucres +involucrum +involuntarily +involuntariness +involuntary +involute +involuted +involutely +involutes +involuting +involution +involutional +involutions +involve +involved +involvedly +involvement +involvements +involver +involvers +involves +involving +invulnerability +invulnerable +invulnerableness +invulnerably +inward +inwardly +inwardness +inwards +inweave +inweaved +inweaves +inweaving +inwind +inwinding +inwinds +inwound +inwove +inwoven +inwrap +inwrapped +inwrapping +inwraps +inwreathe +inwreathed +inwreathes +inwreathing +inwrought +io +iodate +iodated +iodates +iodating +iodation +iodations +iodic +iodide +iodides +iodinate +iodinated +iodinates +iodinating +iodination +iodinations +iodine +iodization +iodizations +iodize +iodized +iodizes +iodizing +iodoform +iodoforms +iodophor +iodophors +iodopsin +iodopsins +ion +iona +ionia +ionian +ionians +ionic +ionicity +ionics +ionium +ionizable +ionization +ionize +ionized +ionizer +ionizers +ionizes +ionizing +ionone +ionones +ionophore +ionophores +ionosphere +ionospheric +ionospherically +ions +iontophoreses +iontophoresis +iontophoretic +iontophoretically +iota +iotacism +iowa +iowan +iowans +iowas +ipecac +ipecacuanha +iphigenia +iproniazid +iproniazids +ipse +ipsilateral +ipsilaterally +ipsissima +ipso +ipsos +ipsum +iran +iranian +iranians +iraq +iraqi +iraqis +irascibility +irascible +irascibleness +irascibly +irate +irately +irateness +ire +ireful +irefully +ireland +irelands +irenic +irenical +irenically +ireton +iridaceous +iridectomies +iridectomy +irides +iridescence +iridescent +iridescently +iridic +iridium +iridologist +iridologists +iridology +iridosmine +iridosmines +iris +irises +irish +irishism +irishisms +irishman +irishmen +irishness +irishries +irishry +irishwoman +irishwomen +iritic +iritis +irk +irked +irking +irks +irksome +irksomely +irksomeness +irkutsk +iroko +irokos +iron +ironbark +ironbarks +ironbound +ironclad +ironclads +irondequoit +ironed +ironer +ironers +ironfisted +ironhanded +ironhandedness +ironhearted +ironic +ironical +ironically +ironicalness +ironies +ironing +ironings +ironist +ironists +ironize +ironized +ironizes +ironizing +ironmaster +ironmasters +ironmonger +ironmongeries +ironmongers +ironmongery +ironness +irons +ironside +ironsides +ironsmith +ironsmiths +ironstone +ironstones +ironware +ironweed +ironweeds +ironwood +ironwoods +ironwork +ironworker +ironworkers +ironworks +irony +iroquoian +iroquoians +iroquois +irradiance +irradiances +irradiancy +irradiant +irradiate +irradiated +irradiates +irradiating +irradiation +irradiations +irradiative +irradiator +irradiators +irradicable +irradicably +irrational +irrationalism +irrationalist +irrationalistic +irrationalists +irrationalities +irrationality +irrationalize +irrationalized +irrationalizes +irrationalizing +irrationally +irrationalness +irrawaddy +irreal +irreality +irreclaimability +irreclaimable +irreclaimableness +irreclaimably +irreconcilability +irreconcilable +irreconcilableness +irreconcilables +irreconcilably +irrecoverable +irrecoverableness +irrecoverably +irrecusable +irrecusably +irredeemable +irredeemably +irredenta +irredentism +irredentist +irredentists +irreducibility +irreducible +irreducibleness +irreducibly +irreflexive +irreformability +irreformable +irrefragability +irrefragable +irrefragably +irrefrangible +irrefrangibly +irrefutability +irrefutable +irrefutably +irregardless +irregular +irregularities +irregularity +irregularly +irregulars +irrelative +irrelatively +irrelevance +irrelevancies +irrelevancy +irrelevant +irrelevantly +irreligion +irreligionist +irreligionists +irreligions +irreligious +irreligiously +irreligiousness +irremeable +irremediable +irremediableness +irremediably +irremissibility +irremissible +irremissibly +irremovability +irremovable +irremovably +irreparability +irreparable +irreparableness +irreparably +irrepealability +irrepealable +irreplaceability +irreplaceable +irreplaceableness +irreplaceably +irrepressibility +irrepressible +irrepressibleness +irrepressibly +irreproachability +irreproachable +irreproachableness +irreproachably +irreproducibility +irreproducible +irresistibility +irresistible +irresistibleness +irresistibly +irresoluble +irresolute +irresolutely +irresoluteness +irresolution +irresolvable +irrespective +irrespectively +irrespirable +irresponsibility +irresponsible +irresponsibleness +irresponsibles +irresponsibly +irresponsive +irresponsively +irresponsiveness +irretrievability +irretrievable +irretrievableness +irretrievably +irreverence +irreverences +irreverent +irreverently +irreversibility +irreversible +irreversibleness +irreversibly +irrevocability +irrevocable +irrevocableness +irrevocably +irridenta +irrigable +irrigate +irrigated +irrigates +irrigating +irrigation +irrigational +irrigations +irrigator +irrigators +irritabilities +irritability +irritable +irritableness +irritably +irritant +irritants +irritate +irritated +irritatedly +irritates +irritating +irritatingly +irritation +irritations +irritative +irritator +irritators +irrotational +irrupt +irrupted +irrupting +irruption +irruptions +irruptive +irruptively +irrupts +irving +iráklion +is +isaac +isabella +isaiah +isaias +isallobar +isallobaric +isallobars +iscariot +ischaemia +ischemia +ischemic +ischia +ischial +ischium +isentropic +isentropically +iseult +isfahan +ishmael +ishmaelite +ishmaelites +ishmaelitish +ishmaelitism +ishmaels +ishtar +isinglass +isis +iskenderun +islam +islamabad +islamic +islamics +islamism +islamist +islamists +islamization +islamize +islamized +islamizes +islamizing +island +islanded +islander +islanders +islanding +islands +islay +isle +isled +isles +islet +islets +isling +ism +ismaili +ismailian +ismailians +ismailis +ismene +isms +isn +isn't +isoagglutination +isoagglutinations +isoagglutinin +isoagglutinins +isoagglutinogen +isoagglutinogens +isoalloxazine +isoantibodies +isoantibody +isoantigen +isoantigenic +isoantigenicity +isoantigens +isobar +isobaric +isobars +isobutane +isobutanes +isobutylene +isobutylenes +isocaloric +isocarboxazid +isocarboxazids +isochromatic +isochromosome +isochromosomes +isochron +isochronal +isochronally +isochrone +isochrones +isochronism +isochronize +isochronized +isochronizes +isochronizing +isochronous +isochronously +isochrons +isochroous +isocitric +isoclinal +isoclinally +isoclinals +isoclinic +isocrates +isocyanate +isocyanates +isocyclic +isodiametric +isodimorphism +isodose +isodynamic +isoelectric +isoelectronic +isoelectronically +isoenzymatic +isoenzyme +isoenzymes +isoenzymic +isogamete +isogametes +isogametic +isogamies +isogamous +isogamy +isogeneic +isogenic +isogenous +isogeny +isogloss +isoglossal +isoglosses +isoglossic +isogon +isogonal +isogonic +isogons +isogony +isograft +isografts +isogram +isograms +isohel +isohels +isohyet +isohyetal +isohyets +isokinetic +isolable +isolatable +isolate +isolated +isolates +isolating +isolation +isolationism +isolationist +isolationistic +isolationists +isolations +isolator +isolators +isolde +isolecithal +isoleucine +isoleucines +isoline +isolines +isomagnetic +isomer +isomerase +isomerases +isomeric +isomerism +isomerisms +isomerization +isomerizations +isomerize +isomerized +isomerizes +isomerizing +isomerous +isomers +isometric +isometrical +isometrically +isometrics +isometropia +isometropias +isometry +isomorph +isomorphic +isomorphically +isomorphism +isomorphous +isomorphs +isoniazid +isoniazids +isooctane +isopach +isophotal +isophote +isophotes +isopiestic +isopiestics +isopleth +isoplethic +isopleths +isopod +isopods +isoprenaline +isoprenalines +isoprene +isoprenoid +isopropyl +isoproterenol +isopycnic +isosceles +isoseismal +isoseismic +isosmotic +isosmotically +isospin +isospins +isostasy +isostatic +isostatically +isotach +isotactic +isotherm +isothermal +isothermally +isothermals +isotherms +isotone +isotones +isotonic +isotonically +isotonicity +isotope +isotopes +isotopic +isotopically +isotretinoin +isotretinoins +isotropic +isotropism +isotropy +isozyme +isozymes +isozymic +ispahan +israel +israeli +israelis +israelite +israelites +israelitic +issachar +issei +isseis +issuable +issuably +issuance +issuant +issue +issued +issueless +issuer +issuers +issues +issuing +istanbul +isthmi +isthmian +isthmic +isthmus +isthmuses +istle +istles +istria +istrian +istrians +it +it'd +it'll +it's +itacolumite +itacolumites +itaconic +italian +italianate +italianism +italianisms +italianization +italianizations +italianize +italianized +italianizes +italianizing +italians +italic +italicism +italicisms +italicization +italicizations +italicize +italicized +italicizes +italicizing +italics +italophile +italophiles +italophilia +italophobe +italophobes +italophobia +italy +itasca +itch +itched +itches +itchier +itchiest +itchiness +itching +itchy +item +itemed +iteming +itemization +itemizations +itemize +itemized +itemizer +itemizers +itemizes +itemizing +items +iterance +iterances +iterant +iterate +iterated +iterates +iterating +iteration +iterations +iterative +iteratively +ithaca +ithaka +ithyphallic +itháki +itineracy +itinerancies +itinerancy +itinerant +itinerantly +itinerants +itineraries +itinerary +itinerate +itinerated +itinerates +itinerating +itineration +itinerations +its +itself +itsukushima +itsy +itty +ituraea +ituraean +ituraeans +ivanhoe +ivermectin +ivermectins +ivied +ivies +iviza +ivories +ivory +ivorybill +ivorybills +ivy +iwis +ixion +ixodid +ixtle +ixtles +iyar +iyyar +izalco +izar +izars +izzard +j +jab +jabbed +jabber +jabbered +jabberer +jabberers +jabbering +jabbers +jabberwocky +jabbing +jabiru +jabirus +jaborandi +jaborandis +jabot +jaboticaba +jabots +jabs +jacal +jacales +jacals +jacamar +jacamars +jacana +jacanas +jacaranda +jacarandas +jacinth +jacinths +jacinto +jack +jackal +jackals +jackanapes +jackanapeses +jackass +jackassery +jackasses +jackboot +jackbooted +jackboots +jackdaw +jackdaws +jacked +jacker +jackers +jacket +jacketed +jacketing +jacketless +jackets +jackfruit +jackfruits +jackhammer +jackhammered +jackhammering +jackhammers +jacking +jackknife +jackknifed +jackknifes +jackknifing +jackknives +jackleg +jacklegs +jacklight +jacklighted +jacklighting +jacklights +jackplane +jackplanes +jackpot +jackpots +jackrabbit +jackrabbited +jackrabbiting +jackrabbits +jacks +jackscrew +jackscrews +jackshaft +jackshafts +jacksmelt +jacksnipe +jacksnipes +jackson +jacksonian +jacksonianism +jacksonians +jackstay +jackstays +jackstone +jackstones +jackstraw +jackstraws +jacob +jacobean +jacobeans +jacobian +jacobians +jacobin +jacobinic +jacobinical +jacobinism +jacobinize +jacobinized +jacobinizes +jacobinizing +jacobins +jacobite +jacobites +jacobitical +jacobitism +jacobus +jaconet +jaconets +jacquard +jacquards +jacquerie +jacqueries +jactitation +jactitations +jacuzzi +jade +jaded +jadedly +jadedness +jadeite +jadeites +jades +jadestone +jadestones +jading +jaditic +jaeger +jaegers +jaffa +jaffas +jag +jagatai +jagged +jaggedly +jaggedness +jagger +jaggeries +jaggers +jaggery +jaggier +jaggiest +jagging +jaggy +jagless +jags +jaguar +jaguarondi +jaguarondis +jaguars +jaguarundi +jaguarundis +jah +jahveh +jahweh +jai +jail +jailbait +jailbird +jailbirds +jailbreak +jailbreaks +jailed +jailer +jailers +jailhouse +jailhouses +jailing +jailor +jailors +jails +jain +jaina +jainas +jainism +jainisms +jains +jaipur +jakarta +jake +jakes +jakob +jalalabad +jalap +jalapeño +jalapeños +jalaps +jalopies +jalopy +jalousie +jalousies +jam +jamaica +jamaican +jamaicans +jamb +jambalaya +jambe +jambeau +jambeaux +jambes +jamboree +jamborees +jambs +james +jamesian +jammable +jammed +jammer +jammers +jammies +jamming +jammu +jammy +jams +jamshid +jamshyd +jane +janeiro +janeite +janeites +jangle +jangled +jangler +janglers +jangles +jangling +jangly +janissaries +janissary +janitor +janitorial +janitors +janizaries +janizary +jansenism +jansenist +jansenistic +jansenists +januaries +january +januarys +janus +jap +japan +japanese +japanization +japanize +japanized +japanizes +japanizing +japanned +japanner +japanners +japanning +japans +jape +japed +japer +japers +japery +japes +japheth +japhetic +japing +japlish +japonaiserie +japonaiseries +japonica +japonicas +japonism +japonisms +japs +japurá +jar +jardiniere +jardinieres +jardinière +jardinières +jarful +jarfuls +jargon +jargoned +jargoneer +jargoneers +jargoning +jargonish +jargonist +jargonistic +jargonists +jargonize +jargonized +jargonizes +jargonizing +jargons +jargoon +jargoons +jarhead +jarheads +jarl +jarls +jarlsberg +jarrah +jarrahs +jarred +jarring +jarringly +jars +jasmine +jasmines +jason +jasper +jaspers +jasperware +jaspery +jassid +jassids +jat +jato +jatos +jats +jaunce +jaunced +jaunces +jauncing +jaundice +jaundiced +jaundices +jaundicing +jaunt +jaunted +jauntier +jauntiest +jauntily +jauntiness +jaunting +jaunts +jaunty +java +javanese +javarí +javas +javelin +javelina +javelinas +javelins +javelle +jaw +jawbone +jawboned +jawboner +jawboners +jawbones +jawboning +jawbreaker +jawbreakers +jawbreaking +jawbreakingly +jawed +jawing +jawless +jawline +jawlines +jaws +jay +jaybird +jaybirds +jaycee +jaycees +jaygee +jaygees +jayhawker +jayhawkers +jays +jayvee +jayvees +jaywalk +jaywalked +jaywalker +jaywalkers +jaywalking +jaywalks +jazz +jazzed +jazzer +jazzers +jazzes +jazzier +jazziest +jazzily +jazziness +jazzing +jazzish +jazzlike +jazzman +jazzmen +jazzy +jaçana +jaçanas +je +jealous +jealousies +jealously +jealousness +jealousy +jean +jeaned +jeans +jeddah +jee +jeebies +jeep +jeepers +jeepney +jeepneys +jeeps +jeer +jeered +jeerer +jeerers +jeering +jeeringly +jeers +jeez +jefe +jefes +jefferson +jeffersonian +jeffersonianism +jeffersonians +jeffrey +jehad +jehads +jehoshaphat +jehovah +jehu +jehus +jejuna +jejunal +jejune +jejunely +jejuneness +jejunum +jekyll +jell +jellaba +jellabas +jelled +jellicoe +jellied +jellies +jellified +jellifies +jellify +jellifying +jelling +jells +jelly +jellybean +jellybeans +jellyfish +jellyfishes +jellying +jellylike +jellyroll +jellyrolls +jelutong +jemmied +jemmies +jemmy +jemmying +jena +jenner +jennet +jennets +jennies +jenny +jeon +jeopard +jeoparded +jeopardies +jeoparding +jeopardize +jeopardized +jeopardizes +jeopardizing +jeopardous +jeopards +jeopardy +jequirity +jequitinhonha +jerboa +jerboas +jeremiad +jeremiads +jeremiah +jeremiahs +jeremias +jerez +jericho +jerk +jerked +jerker +jerkers +jerkier +jerkiest +jerkily +jerkin +jerkiness +jerking +jerkingly +jerkins +jerks +jerkwater +jerky +jeroboam +jeroboams +jerome +jerrican +jerricans +jerries +jerry +jerrybuild +jerrybuilder +jerrybuilders +jerrybuilding +jerrybuilds +jerrybuilt +jersey +jerseys +jerusalem +jess +jessamine +jessamines +jesse +jessed +jesses +jessing +jest +jested +jester +jesters +jesting +jestingly +jests +jesuit +jesuitic +jesuitical +jesuitically +jesuitism +jesuitry +jesuits +jesus +jet +jetavator +jetavators +jetbead +jetbeads +jetfighter +jetfighters +jetfoil +jetfoils +jetful +jetlike +jetliner +jetliners +jetpack +jetpacks +jetport +jetports +jets +jetsam +jetted +jettied +jetties +jettiness +jetting +jettison +jettisonable +jettisoned +jettisoning +jettisons +jetty +jettying +jetway +jeté +jeu +jeunesse +jeux +jew +jewel +jeweled +jeweler +jewelers +jewelfish +jewelfishes +jeweling +jewelled +jeweller +jewellers +jewellery +jewellike +jewelling +jewelry +jewels +jewelweed +jewelweeds +jewess +jewesses +jewfish +jewfishes +jewish +jewishly +jewishness +jewries +jewry +jews +jezebel +jezebels +jiao +jib +jibaro +jibaros +jibbed +jibber +jibbers +jibbing +jibboom +jibbooms +jibe +jibed +jibes +jibing +jibs +jicama +jicamas +jicarilla +jicarillas +jiff +jiffies +jiffs +jiffy +jig +jigged +jigger +jiggers +jiggery +jigging +jiggle +jiggled +jiggles +jiggling +jiggly +jigs +jigsaw +jigsaws +jihad +jihads +jill +jillion +jillionaire +jillionaires +jillions +jillionth +jillionths +jills +jilt +jilted +jilter +jilters +jilting +jilts +jim +jimjams +jimmied +jimmies +jimmy +jimmying +jimsonweed +jimsonweeds +jingle +jingled +jingler +jinglers +jingles +jingling +jingly +jingo +jingoes +jingoish +jingoism +jingoist +jingoistic +jingoistically +jingoists +jink +jinked +jinking +jinks +jinmen +jinn +jinnee +jinni +jinns +jinricksha +jinrickshas +jinrikisha +jinrikishas +jinriksha +jinrikshas +jinx +jinxed +jinxes +jinxing +jipijapa +jipijapas +jitney +jitneys +jitter +jitterbug +jitterbugged +jitterbugging +jitterbugs +jittered +jitterier +jitteriest +jitteriness +jittering +jitters +jittery +jiujitsu +jiujutsu +jivaro +jivaros +jive +jived +jiver +jivers +jives +jivey +jiving +jivy +jo +joan +job +jobbed +jobber +jobbers +jobbery +jobbing +jobholder +jobholders +jobless +joblessness +jobs +jocasta +jock +jockey +jockeyed +jockeying +jockeys +jocks +jockstrap +jockstraps +jocose +jocosely +jocoseness +jocosity +jocular +jocularity +jocularly +jocund +jocundity +jocundly +jodhpur +jodhpurs +jodrell +joe +joel +joes +joey +joeys +jog +jogged +jogger +joggers +jogging +joggle +joggled +joggles +joggling +jogjakarta +jogs +johannesburg +john +johnboat +johnboats +johnnies +johnny +johnnycake +johnnycakes +johns +johnson +johnsonian +johnsonians +johnstone +johnstown +joie +join +joinder +joinders +joined +joiner +joineries +joiners +joinery +joining +joins +joint +jointed +jointer +jointers +jointing +jointly +joints +jointure +jointures +jointworm +jointworms +joist +joisted +joisting +joists +jojoba +jojobas +joke +joked +joker +jokers +jokes +jokester +jokesters +jokey +jokier +jokiest +jokily +jokiness +joking +jokingly +joky +jolie +jollied +jollier +jollies +jolliest +jollification +jollifications +jollily +jolliness +jollities +jollity +jolly +jollyboat +jollyboats +jollying +jolt +jolted +jolter +jolters +joltily +joltiness +jolting +jolts +jolty +jomada +jonah +jonahs +jonathan +jones +jongleur +jongleurs +jonnycake +jonnycakes +jonquil +jonquils +jonson +jooal +jordan +jordanian +jordanians +jorum +jorums +joseph +josephs +josephus +josh +joshed +josher +joshers +joshes +joshing +joshingly +joshua +josiah +joss +josses +jostle +jostled +jostler +jostlers +jostles +jostling +josé +jot +jots +jotted +jotting +jottings +joual +joule +joules +jounce +jounced +jounces +jouncing +jour +journal +journalese +journalism +journalist +journalistic +journalistically +journalists +journalize +journalized +journalizer +journalizers +journalizes +journalizing +journals +journey +journeyed +journeyer +journeyers +journeying +journeyman +journeymen +journeys +journeywork +joust +jousted +jouster +jousters +jousting +jousts +jove +jovial +joviality +jovially +jovian +jowett +jowl +jowlier +jowliest +jowliness +jowls +jowly +joy +joyance +joyce +joyed +joyful +joyfully +joyfulness +joying +joyless +joylessly +joylessness +joyous +joyously +joyousness +joypop +joypopped +joypopper +joypoppers +joypopping +joypops +joyride +joyrider +joyriders +joyrides +joyriding +joys +joystick +joysticks +joão +juan +juanism +juans +juba +jubal +jubas +jubilance +jubilant +jubilantly +jubilarian +jubilarians +jubilate +jubilated +jubilates +jubilating +jubilation +jubilee +jubilees +judaea +judah +judaic +judaica +judaical +judaically +judaism +judaist +judaistic +judaists +judaization +judaizations +judaize +judaized +judaizer +judaizers +judaizes +judaizing +judas +judases +judder +juddered +juddering +judders +jude +judea +judean +judeans +judeo +judge +judged +judgement +judgements +judger +judgers +judges +judgeship +judgeships +judging +judgmatic +judgmatical +judgmatically +judgment +judgmental +judgmentally +judgments +judicable +judicata +judicator +judicatories +judicators +judicatory +judicature +judicatures +judice +judicial +judicially +judiciaries +judiciary +judicious +judiciously +judiciousness +judith +judo +judoist +judoists +judos +judy +jug +juga +jugate +jugful +jugfuls +jugged +juggernaut +juggernauts +jugging +juggle +juggled +juggler +juggleries +jugglers +jugglery +juggles +juggling +jugoslav +jugoslavs +jugs +jugular +jugulars +jugulate +jugulated +jugulates +jugulating +jugum +jugums +juice +juiced +juicehead +juiceheads +juiceless +juicer +juicers +juices +juicier +juiciest +juicily +juiciness +juicing +juicy +jujitsu +juju +jujube +jujubes +jujuism +jujus +jujutsu +juke +jukebox +jukeboxes +juked +jukes +juking +julep +juleps +julian +julienne +julienned +juliet +juliett +julius +july +julys +jumada +jumble +jumbled +jumbles +jumbling +jumbo +jumbos +jumbuck +jumbucks +jump +jumped +jumper +jumpers +jumpier +jumpiest +jumpily +jumpiness +jumping +jumpmaster +jumpmasters +jumps +jumpsuit +jumpsuits +jumpy +junco +juncoes +juncos +junction +junctional +junctions +junctural +juncture +junctures +june +juneau +juneberries +juneberry +junes +jung +jungfrau +jungian +jungians +jungle +jungled +junglelike +jungles +jungly +junior +juniorate +juniors +juniper +junipers +junius +junk +junked +junker +junkerdom +junkerism +junkers +junket +junketed +junketeer +junketeered +junketeering +junketeers +junketer +junketers +junketing +junkets +junkie +junkier +junkies +junkiest +junking +junkman +junkmen +junks +junky +junkyard +junkyards +juno +junoesque +junta +juntas +junto +juntos +jupiter +jura +jural +jurally +jurassic +jurat +jurats +jure +jureipswich +jurel +jurels +juridic +juridical +juridically +juried +juries +juris +jurisconsult +jurisconsults +jurisdiction +jurisdictional +jurisdictionally +jurisdictions +jurisprudence +jurisprudent +jurisprudential +jurisprudentially +jurisprudents +jurist +juristic +juristical +juristically +jurists +juror +jurors +jury +jurying +juryman +jurymen +jurywoman +jurywomen +jus +jussive +jussives +just +juste +justed +justes +justice +justices +justiciability +justiciable +justiciar +justiciaries +justiciars +justiciary +justifiability +justifiable +justifiableness +justifiably +justification +justifications +justificative +justificatory +justified +justifier +justifiers +justifies +justify +justifying +justing +justinian +justly +justness +justs +jut +jute +jutish +jutland +juts +jutted +juttied +jutties +jutting +jutty +juttying +juvenal +juvenescence +juvenescent +juvenile +juvenilely +juvenileness +juveniles +juvenilia +juvenilities +juvenility +juxtapose +juxtaposed +juxtaposes +juxtaposing +juxtaposition +juxtapositional +juxtapositions +juárez +jyväskylä +k +kaaba +kab +kabala +kabalas +kabbala +kabbalah +kabbalas +kabob +kabobs +kabs +kabuki +kabukis +kabul +kabyle +kabyles +kachina +kachinas +kaddish +kaffeeklatsch +kaffeeklatsches +kaffir +kaffirs +kaffiyeh +kaffiyehs +kafir +kafiri +kafirs +kafka +kafkaesque +kaftan +kaftans +kagoshima +kahn +kahoolawe +kahuna +kaiak +kaiaked +kaiaker +kaiakers +kaiaking +kaiaks +kailas +kailyard +kainit +kainite +kainites +kainits +kaiser +kaiserdom +kaiserdoms +kaiserin +kaiserins +kaiserism +kaisers +kaka +kakapo +kakapos +kakas +kakemono +kakemonos +kaki +kakiemon +kakis +kakistocracies +kakistocracy +kalahari +kalamazoo +kalanchoe +kalashnikov +kalashnikovs +kale +kaleidoscope +kaleidoscopes +kaleidoscopic +kaleidoscopical +kaleidoscopically +kalends +kalgoorlie +kalimantan +kalimba +kalimbas +kaliningrad +kallidin +kallidins +kallikrein +kallikreins +kalmar +kalmuck +kalmucks +kalmuk +kalmuks +kalmyk +kalmyks +kalpac +kalpacs +kalsomine +kalsomines +kama +kamaaina +kamala +kamalas +kamasutra +kamchatka +kame +kamehameha +kames +kamet +kamikaze +kamikazes +kampala +kampong +kampongs +kampuchea +kampuchean +kampucheans +kana +kanak +kanaka +kanakas +kanaks +kanamycin +kanamycins +kanarese +kanas +kanban +kanchenjunga +kandy +kangaroo +kangaroos +kangchenjunga +kaniapiskau +kanji +kanjis +kankakee +kannada +kano +kansa +kansan +kansans +kansas +kansu +kant +kantele +kanteles +kantian +kantians +kanuri +kanuris +kanzu +kanzus +kaolin +kaoline +kaolines +kaolinite +kaolinites +kaolinitic +kaolinize +kaolinized +kaolinizes +kaolinizing +kaolins +kaon +kaons +kapellmeister +kaph +kapok +kaposi +kaposi's +kappa +kaput +kaputt +kara +karabiner +karabiners +karachi +karaism +karaite +karaites +karakoram +karakorum +karakul +karakuls +karaoke +karaokes +karat +karate +karateist +karateists +karats +karaya +karelia +karelian +karelians +karen +karenina +karens +kari +kariba +karma +karmic +karnak +karnataka +karok +karoks +karoo +karoos +kaross +karroo +karroos +karst +karstic +karsts +kart +karting +kartings +karts +karyogamies +karyogamy +karyokinesis +karyokinetic +karyologic +karyological +karyology +karyolymph +karyolymphs +karyoplasm +karyoplasms +karyosome +karyosomes +karyotype +karyotyped +karyotypes +karyotypic +karyotypical +karyotypically +karyotyping +kasbah +kasha +kashan +kashans +kasher +kashered +kashering +kashers +kashmir +kashmiri +kashmiris +kashrut +kashruth +kashubian +kaskaskia +kaskaskias +kata +katabatic +katahdin +katakana +katakanas +katanga +katangese +katas +katchina +katcina +katharevusa +katharsis +kathiawar +kathmandu +katmai +katmandu +kattegat +katydid +katydids +katzenjammer +katzenjammers +kauai +kauri +kauris +kava +kavas +kaw +kawartha +kaws +kay +kayak +kayaked +kayaker +kayakers +kayaking +kayaks +kaybecker +kaybeckers +kayo +kayoed +kayoing +kayos +kazak +kazakh +kazakhs +kazakhstan +kazaks +kazbek +kazoo +kazoos +kea +kealakekua +kean +keas +keats +keatsian +kebab +kebabs +kebbock +kebbocks +kebbuck +kebbucks +keble +kebob +kebobs +kechua +kechuas +ked +kedge +kedged +kedgeree +kedges +kedging +keek +keeked +keeking +keeks +keel +keelboat +keelboats +keeled +keelhaul +keelhauled +keelhauling +keelhauls +keeling +keelless +keels +keelson +keelsons +keen +keened +keener +keeners +keenest +keening +keenly +keenness +keens +keep +keeper +keepers +keeping +keeps +keepsake +keepsakes +keeshond +keeshonden +keeshonds +keester +keesters +keewatin +kef +kefallinía +keffiyeh +kefir +kefirs +keflavík +kefs +keg +kegged +kegging +kegler +keglers +kegling +kegs +keister +keisters +kelim +kelims +kelly +keloid +keloidal +keloids +kelp +kelpie +kelpies +kelps +kelpy +kelson +kelsons +kelt +keltic +kelts +kelvin +kelvins +kemijoki +kemp +kempis +kempt +ken +kenaf +kenai +kendal +kendo +kendos +kenilworth +kennebec +kenned +kennedy +kennel +kenneled +kenneling +kennelled +kennelling +kennels +kenning +kennings +keno +kenos +kenosis +kenotic +kens +kenspeckle +kent +kentish +kentledge +kentledges +kentuckian +kentuckians +kentucky +kenya +kenyan +kenyans +keogh +kephalin +kephalins +kepi +kepis +kepler +kept +kerala +keratectomies +keratectomy +keratin +keratinization +keratinizations +keratinize +keratinized +keratinizes +keratinizing +keratinophilic +keratinous +keratitides +keratitis +keratoconjunctivitis +keratoplasties +keratoplasty +keratoses +keratosis +keratotic +keratotomies +keratotomy +kerb +kerbs +kerch +kerchief +kerchiefed +kerchiefs +kerchieves +keresan +keresans +kerf +kerfs +kerfuffle +kerfuffles +kerguelen +kerman +kermans +kermes +kermess +kermesse +kermesses +kermis +kermises +kern +kerne +kerned +kernel +kerneled +kernels +kernes +kerning +kernite +kernites +kerns +kerogen +kerogens +kerosene +kerosenes +kerosine +kerosines +kerria +kerrias +kerries +kerry +kersey +kerseymere +kerseymeres +kerseys +kerygma +kerygmas +kerygmatic +kestrel +kestrels +ketch +ketches +ketchup +ketene +ketenes +ketoacidosis +ketogenesis +ketogenic +ketoglutaric +ketone +ketones +ketonic +ketose +ketoses +ketosis +ketosteroid +ketosteroids +ketotic +kettle +kettledrum +kettledrums +kettles +kevel +kevels +keweenaw +kewpie +kewpies +key +keyboard +keyboarded +keyboarder +keyboarders +keyboarding +keyboardist +keyboardists +keyboards +keybutton +keybuttons +keycard +keycards +keyed +keyhole +keyholes +keying +keyless +keynes +keynesian +keynesianism +keynesians +keynote +keynoted +keynoter +keynoters +keynotes +keynoting +keypad +keypads +keypunch +keypunched +keypuncher +keypunchers +keypunches +keypunching +keys +keystone +keystones +keystroke +keystroked +keystrokes +keystroking +keyway +keyways +keyword +keywords +kg +khaddar +khaddars +khadi +khaki +khakis +khalif +khalifs +khalkha +khalkidhikí +khamsin +khamsins +khan +khanate +khanates +khans +khapra +khartoum +khartum +khat +khatanga +khats +khedival +khedive +khedives +khedivial +khi +khmer +khmerian +khmers +khoikhoi +khoikhoin +khoikhoins +khoikhois +khoisan +khoisans +khoum +khowar +khwarizmi +khyber +khíos +kiang +kiangs +kiangsi +kiangsu +kiaugh +kiaughs +kibbe +kibbi +kibbitz +kibbitzer +kibbitzers +kibble +kibbled +kibbles +kibbling +kibbutz +kibbutzim +kibbutznik +kibbutzniks +kibe +kibei +kibeis +kibes +kibitz +kibitzed +kibitzer +kibitzers +kibitzes +kibitzing +kiblah +kiblahs +kibosh +kiboshed +kiboshes +kiboshing +kick +kickable +kickapoo +kickapoos +kickback +kickbacks +kickboard +kickboards +kickboxer +kickboxers +kickboxing +kicked +kicker +kickers +kickier +kickiest +kicking +kickoff +kickoffs +kicks +kickshaw +kickshaws +kickstand +kickstands +kickup +kickups +kicky +kid +kidcom +kidcoms +kidded +kidder +kidderminster +kidderminsters +kidders +kiddie +kiddies +kidding +kiddingly +kiddish +kiddo +kiddos +kiddush +kiddushes +kiddy +kideo +kideos +kidnap +kidnaped +kidnapee +kidnapees +kidnaper +kidnapers +kidnaping +kidnapped +kidnappee +kidnappees +kidnapper +kidnappers +kidnapping +kidnappings +kidnaps +kidney +kidneys +kids +kidskin +kidvid +kidvids +kielbasa +kierkegaard +kieselguhr +kieselguhrs +kieserite +kieserites +kiev +kif +kifs +kigali +kike +kikes +kikládhes +kikongo +kikongos +kikuyu +kikuyus +kilauea +kilderkin +kilderkins +kilim +kilimanjaro +kilims +kill +killable +killarney +killdeer +killdeers +killed +killer +killers +killersat +killersats +killick +killicks +killie +killies +killifish +killifishes +killing +killingly +killings +killjoy +killjoys +killock +killocks +kills +kiln +kilned +kilning +kilns +kilo +kiloampere +kiloamperes +kilobar +kilobars +kilobase +kilobases +kilobecquerel +kilobecquerels +kilobit +kilobits +kilobyte +kilobytes +kilocalorie +kilocalories +kilocandela +kilocandelas +kilocoulomb +kilocoulombs +kilocurie +kilocuries +kilocycle +kilocycles +kilofarad +kilofarads +kilogauss +kilogausses +kilogram +kilograms +kilohenries +kilohenry +kilohenrys +kilohertz +kilojoule +kilojoules +kilokelvin +kilokelvins +kiloliter +kiloliters +kilolumen +kilolumens +kilolux +kilomegacycle +kilomegacycles +kilometer +kilometers +kilometric +kilomole +kilomoles +kilonewton +kilonewtons +kilooersted +kilooersteds +kiloohm +kiloohms +kiloparsec +kiloparsecs +kilopascal +kilopascals +kilorad +kiloradian +kiloradians +kilorads +kilos +kilosecond +kiloseconds +kilosiemens +kilosievert +kilosieverts +kilosteradian +kilosteradians +kilotesla +kiloteslas +kiloton +kilotons +kilovolt +kilovolts +kilowatt +kilowatts +kiloweber +kilowebers +kilt +kilted +kilter +kiltie +kilties +kilting +kilts +kilty +kimberley +kimberlite +kimberlites +kimberlitic +kimbundu +kimbundus +kimchee +kimchees +kimchi +kimchis +kimono +kimonoed +kimonos +kin +kina +kinas +kinase +kinases +kind +kinder +kindergarten +kindergartener +kindergarteners +kindergartens +kindergartner +kindergartners +kindersley +kindest +kindhearted +kindheartedly +kindheartedness +kindle +kindled +kindler +kindlers +kindles +kindless +kindlessly +kindlier +kindliest +kindliness +kindling +kindlings +kindly +kindness +kindnesses +kindred +kindredness +kinds +kine +kinema +kinematic +kinematical +kinematically +kinematics +kinescope +kinescoped +kinescopes +kinescoping +kineses +kinesic +kinesics +kinesiologist +kinesiologists +kinesiology +kinesis +kinestheses +kinesthesia +kinesthesias +kinesthesis +kinesthetic +kinesthetically +kinetic +kinetically +kineticism +kineticist +kineticists +kinetics +kinetin +kinetins +kinetochore +kinetochores +kinetoplast +kinetoplasts +kinetoscope +kinetoscopes +kinetosome +kinetosomes +kinfolk +kinfolks +king +king's +kingbird +kingbirds +kingbolt +kingbolts +kingcraft +kingcrafts +kingcup +kingcups +kingdom +kingdoms +kinged +kingfish +kingfisher +kingfishers +kingfishes +kinging +kinglet +kinglets +kinglier +kingliest +kingliness +kingly +kingmaker +kingmakers +kingmaking +kingpin +kingpins +kings +kingship +kingships +kingside +kingsides +kingsley +kingstown +kingwood +kingwoods +kinin +kinins +kink +kinkajou +kinkajous +kinked +kinkier +kinkiest +kinkily +kinkiness +kinking +kinks +kinky +kinnikinnic +kinnikinnick +kinnikinnicks +kinnikinnics +kino +kinos +kinsfolk +kinshasa +kinship +kinsman +kinsmen +kinswoman +kinswomen +kinyarwanda +kioga +kiosk +kiosks +kiowa +kiowas +kip +kipling +kipped +kipper +kippered +kipperer +kipperers +kippering +kippers +kipping +kippur +kips +kir +kirche +kirchhoff +kirghiz +kirghizes +kirghizia +kirghizstan +kirgiz +kirgizes +kirgizia +kirgizstan +kiri +kiribati +kirigami +kirin +kirk +kirkpatrick +kirks +kirlian +kirman +kirmans +kirmess +kirmesses +kirs +kirsch +kirschwasser +kirschwassers +kirtland +kirtle +kirtles +kirundi +kirundis +kishka +kishkas +kishke +kishkes +kiska +kislev +kismet +kiss +kissable +kissed +kisser +kissers +kisses +kissimmee +kissing +kist +kists +kiswahili +kit +kitchen +kitchenette +kitchenettes +kitchens +kitchenware +kite +kited +kitelike +kites +kith +kithara +kitharas +kithe +kithed +kithing +kitikmeot +kiting +kits +kitsch +kitschified +kitschifies +kitschifing +kitschify +kitschy +kitted +kitten +kittened +kittening +kittenish +kittenishly +kittenishness +kittens +kitties +kitting +kittiwake +kittiwakes +kittle +kittled +kittles +kittling +kitts +kitty +kiva +kivas +kiwanian +kiwanians +kiwi +kiwifruit +kiwis +klagenfurt +klamath +klamaths +klan +klanism +klansman +klansmen +klatch +klatches +klatsch +klavern +klaverns +klaxon +klaxons +klebsiella +klebsiellas +klee +kleenex +kleenexes +kleig +klein +klemperer +klepht +klephtic +klephts +kleptocracies +kleptocracy +kleptocratic +kleptomania +kleptomaniac +kleptomaniacal +kleptomaniacs +klezmer +klezmorim +klieg +kliegs +klinefelter +klingon +klingons +klipspringer +klipspringers +klister +klisters +klondike +kloof +kloofs +klosters +kludge +kludged +kludges +kludging +kludgy +kluge +kluged +kluges +kluging +klugy +klutz +klutzes +klutziness +klutzy +klux +kluxer +kluxism +klystron +klystrons +km +knack +knacker +knackered +knackers +knackery +knacks +knackwurst +knackwursts +knap +knapped +knapper +knappers +knapping +knaps +knapsack +knapsacked +knapsacks +knapweed +knapweeds +knar +knars +knaur +knaurs +knave +knaveries +knavery +knaves +knavish +knavishly +knavishness +knawe +knawel +knawels +knawes +knead +kneadable +kneaded +kneader +kneaders +kneading +kneads +knee +kneeboard +kneeboarded +kneeboarding +kneeboards +kneecap +kneecapped +kneecapping +kneecaps +kneed +kneehole +kneeholes +kneeing +kneel +kneeled +kneeler +kneelers +kneeling +kneels +kneepad +kneepads +kneepan +kneepans +knees +kneesock +kneesocks +knell +knelled +knelling +knells +knelt +knesset +knessets +knew +knickerbocker +knickerbockers +knickers +knickknack +knickknacks +knife +knifed +knifelike +knifeman +knifemen +knifepoint +knifepoints +knifer +knifers +knifes +knifing +knifings +knight +knighted +knighthood +knighting +knightliness +knightly +knights +knish +knishes +knit +knits +knitted +knitter +knitters +knitting +knitwear +knives +knob +knobbed +knobbier +knobbiest +knobblier +knobbliest +knobbly +knobby +knobkerrie +knobkerries +knobs +knock +knockabout +knockabouts +knockdown +knockdowns +knocked +knocker +knockers +knocking +knockings +knockoff +knockoffs +knockout +knockouts +knocks +knockwurst +knockwursts +knoll +knolled +knolling +knolls +knop +knopped +knops +knossos +knot +knotgrass +knotgrasses +knothole +knotholes +knots +knotted +knotter +knotters +knottier +knottiest +knottiness +knotting +knotty +knotweed +knotweeds +knout +knouted +knouting +knouts +know +knowable +knower +knowers +knowing +knowingly +knowingness +knowledge +knowledgeability +knowledgeable +knowledgeableness +knowledgeably +known +knows +knox +knoxville +knubby +knuckle +knuckleball +knuckleballer +knuckleballers +knuckleballs +knucklebone +knucklebones +knuckled +knucklehead +knuckleheaded +knuckleheads +knuckler +knucklers +knuckles +knuckling +knur +knurl +knurled +knurling +knurls +knurly +knurs +ko +koa +koala +koalas +koan +koans +koas +kob +kobo +kobold +kobolds +kobs +koch +kodak +kodiak +kohl +kohlrabi +kohlrabies +koi +koine +koines +kokanee +kokanees +kola +kolache +kolacky +kolas +kolinskies +kolinsky +kolkhoz +kolkhozes +kolkhoznik +kolkhozniki +kolkhozniks +kolkhozy +kolo +kolos +kolyma +komandorski +komati +komatik +komatiks +kombu +kombus +komodo +komondor +komondorok +komondors +komsomol +kong +kongo +kongos +konkani +koodoo +koodoos +kook +kookaburra +kookaburras +kookie +kookier +kookiest +kookiness +kooks +kooky +kootchy +kootenay +kopeck +kopecks +kopek +kopeks +koph +kopje +kopjes +koppie +koppies +kor +korai +koran +koranic +korat +korats +kordofanian +kordofanians +kore +korea +korean +koreans +kors +korsakoff +korsakov +korun +koruna +korunas +koruny +kos +kosciusko +kosher +koshered +koshering +koshers +kosovo +koto +kotos +koumiss +koumisses +kouprey +kouroi +kouros +kowloon +kowtow +kowtowed +kowtowing +kowtows +kra +kraal +kraals +kraft +krait +kraits +krakatau +krakatoa +kraken +krakens +kraków +krater +kraters +kraut +krauts +krebs +kremlin +kremlinological +kremlinologist +kremlinologists +kremlinology +kreplach +kreutzer +kreutzers +kreuzer +kreuzers +krewe +krewes +kriemhild +kriemhilde +krill +krimmer +krimmers +kringle +krio +kris +krises +krishna +krishnaism +krishnas +kriss +kroenecker +krona +krone +kronecker +kronen +kroner +kronor +kronos +kronur +krugerrand +krugerrands +krumhorn +krumhorns +krummholz +krummhorn +krummhorns +krummkake +krummkakes +krypton +kshatriya +kshatriyas +ku +kuala +kublai +kuchean +kuchen +kuchens +kudo +kudos +kudu +kudus +kudzu +kufic +kugel +kugels +kulak +kulaks +kultur +kulturkampf +kulturkampfs +kulturs +kumiss +kumisses +kumquat +kumquats +kundalini +kung +kunlun +kunming +kunzite +kunzites +kuoyu +kuoyus +kurchatovium +kurd +kurdish +kurdistan +kurds +kurgan +kurgans +kuril +kurile +kurilian +kurilians +kurland +kuroshio +kurrajong +kurrajongs +kurtoses +kurtosis +kuru +kurus +kush +kuskokwim +kutch +kutenai +kutenais +kuwait +kuwaiti +kuwaitis +kvass +kvasses +kvetch +kvetched +kvetches +kvetching +kvetchy +kwa +kwacha +kwachas +kwajalein +kwakiutl +kwakiutls +kwangtung +kwantung +kwanza +kwanzaa +kwanzas +kwas +kwashiorkor +kweichow +kyack +kyacks +kyanite +kyanites +kyanize +kyanized +kyanizes +kyanizing +kyat +kyats +kybosh +kylikes +kylix +kymogram +kymograms +kymograph +kymographic +kymographs +kymography +kymric +kyoga +kyoto +kyphosis +kyphotic +kyrgyz +kyrgyzstan +kyrie +kyries +kyte +kythe +kyushu +kárpathos +kérkira +kíthira +kórinthos +köln +königsberg +küche +kümmel +kümmelweck +l +l'oeil +l'oeils +l'évêque +la +laager +laagered +laagering +laagers +laari +lab +laban +labanotation +labanotations +labara +labarum +labdanum +labdanums +label +labelable +labeled +labeler +labelers +labeling +labella +labellate +labelled +labeller +labellers +labelling +labellum +labels +labia +labial +labialization +labializations +labialize +labialized +labializes +labializing +labially +labials +labiate +labiates +labile +lability +labiodental +labiodentals +labionasal +labionasals +labiovelar +labiovelars +labium +lablab +lablabs +labor +laboratories +laboratory +labored +laborer +laborers +laboring +laborious +laboriously +laboriousness +laborite +laborites +labors +laborsaving +labour +labourite +labourites +labours +labra +labrador +labradorean +labradoreans +labradorian +labradorians +labradorite +labradorites +labradors +labret +labrets +labrum +labs +labuan +laburnum +laburnums +labyrinth +labyrinthian +labyrinthine +labyrinthodont +labyrinthodonts +labyrinths +lac +laccadive +laccolith +laccolithic +laccoliths +lace +laced +lacedaemon +lacedaemonian +laceless +lacelike +lacer +lacerate +lacerated +lacerates +lacerating +laceration +lacerations +lacerative +lacers +lacerta +lacertilian +laces +lacewing +lacewings +lacework +lacey +laches +lachesis +lachrymal +lachrymation +lachrymations +lachrymator +lachrymators +lachrymatory +lachrymose +lachrymosely +lachrymosity +lacier +laciest +laciness +lacing +lacings +lacinia +lacinias +laciniate +laciniation +laciniations +lack +lackadaisical +lackadaisically +lackadaisicalness +lackaday +lacked +lackey +lackeyed +lackeying +lackeys +lacking +lackluster +lacks +laconia +laconic +laconically +laconism +laconisms +lacquer +lacquered +lacquerer +lacquerers +lacquering +lacquers +lacquerware +lacquerwork +lacrimal +lacrimation +lacrimations +lacrimator +lacrimators +lacrosse +lacs +lactalbumin +lactalbumins +lactamase +lactase +lactate +lactated +lactates +lactating +lactation +lactational +lactations +lacteal +lacteally +lactescence +lactescent +lactic +lactiferous +lactiferousness +lactobacilli +lactobacillus +lactoflavin +lactoflavins +lactogenic +lactoglobulin +lactoglobulins +lactometer +lactometers +lactone +lactones +lactonic +lactoprotein +lactoproteins +lactose +lacuna +lacunae +lacunal +lacunar +lacunaria +lacunars +lacunas +lacunate +lacustrine +lacy +lad +ladanum +ladanums +ladder +laddered +laddering +ladderlike +ladders +laddie +laddies +lade +laded +laden +ladened +ladening +ladens +lades +ladies +ladin +lading +ladino +ladinos +ladins +ladle +ladled +ladler +ladlers +ladles +ladling +ladoga +lads +lady +ladybird +ladybirds +ladybug +ladybugs +ladyfinger +ladyfingers +ladyfish +ladyfishes +ladykin +ladykins +ladylike +ladylikeness +ladylove +ladyloves +ladysfinger +ladysfingers +ladyship +ladyships +ladysmith +laertes +laetare +laetrile +lafayette +lag +lagan +lagans +lagend +lagends +lager +lagers +laggard +laggardly +laggardness +laggards +lagged +lagger +laggers +lagging +laggings +lagniappe +lagniappes +lagomorph +lagomorphic +lagomorphous +lagomorphs +lagoon +lagoonal +lagoons +lagos +lagrangian +lagrangians +lags +lahar +lahars +lahnda +lahontan +lahore +laic +laical +laically +laicals +laicism +laicization +laicizations +laicize +laicized +laicizes +laicizing +laics +laid +laide +lain +lair +laird +lairdly +lairds +lairs +laisser +laissez +lait +laitance +laity +laius +lake +lakebed +lakebeds +laked +lakefront +lakefronts +lakeland +lakelike +laker +lakers +lakes +lakeshore +lakeshores +lakeside +lakesides +lakh +laking +lakota +lakotas +lakshadweep +lakshmi +laky +lalapalooza +lalapaloozas +lallan +lalland +lallands +lallans +lallapalooza +lallapaloozas +lallation +lallations +lally +lallygag +lallygagged +lallygagging +lallygags +lam +lama +lamaism +lamaist +lamaistic +lamaists +lamarck +lamarckian +lamarckianism +lamarckians +lamarckism +lamas +lamaseries +lamasery +lamaze +lamb +lambast +lambaste +lambasted +lambastes +lambasting +lambasts +lambda +lambdoid +lambed +lambency +lambent +lambently +lamber +lambers +lambert +lamberts +lambing +lambkill +lambkills +lamblike +lambrequin +lambrequins +lambrusco +lambs +lambskin +lamby +lame +lamebrain +lamebrained +lamebrains +lamed +lamedh +lamella +lamellae +lamellar +lamellarly +lamellas +lamellate +lamellated +lamellately +lamellation +lamellations +lamellibranch +lamellibranchs +lamellicorn +lamellicorns +lamelliform +lamely +lameness +lament +lamentable +lamentableness +lamentably +lamentation +lamentations +lamented +lamentedly +lamenter +lamenters +lamenting +laments +lamer +lames +lamest +lamia +lamiae +lamian +lamians +lamias +lamina +laminae +laminal +laminar +laminaria +laminarian +laminarians +laminarin +laminarins +laminas +laminate +laminated +laminates +laminating +lamination +laminations +laminator +laminators +laminectomies +laminectomy +laming +laminitis +lamister +lamisters +lammas +lammases +lammastide +lammed +lammergeier +lammergeiers +lammergeyer +lammergeyers +lammermoor +lamming +lamp +lampblack +lampbrush +lamper +lampion +lampions +lamplight +lamplighter +lamplighters +lampoon +lampooned +lampooner +lampooners +lampoonery +lampooning +lampoonist +lampoonists +lampoons +lamppost +lampposts +lamprey +lampreys +lamprophyre +lamprophyres +lamps +lampshade +lampshades +lampshell +lampshells +lampworking +lampworkings +lams +lamster +lamsters +lamé +lamés +lanai +lanais +lanate +lancashire +lancaster +lancasters +lancastrian +lancastrians +lance +lanced +lancelet +lancelets +lancelot +lanceolate +lanceolately +lancer +lancers +lances +lancet +lanceted +lancets +lancewood +lancewoods +lancinating +lancing +land +landau +landaulet +landaulets +landaus +landed +lander +landers +landes +landfall +landfalls +landfill +landfilled +landfilling +landfills +landform +landforms +landgrab +landgrabs +landgrave +landgraves +landgraviate +landgraviates +landgravine +landgravines +landholder +landholders +landholding +landholdings +landing +landings +landladies +landlady +landless +landlessness +landline +landlines +landlocked +landlord +landlordism +landlords +landlubber +landlubberliness +landlubberly +landlubbers +landlubbing +landmark +landmarks +landmass +landmasses +landmine +landmines +landowner +landowners +landownership +landowning +landrace +landraces +lands +landscape +landscaped +landscaper +landscapers +landscapes +landscaping +landscapist +landscapists +landseer +landside +landsides +landsleit +landslide +landslides +landslip +landslips +landsmaal +landsmal +landsman +landsmen +landsmål +landtag +landtags +landward +landwards +lane +lanes +laneway +laneways +lanfranc +lang +langbeinite +langbeinites +langerhans +langlauf +langlaufer +langlaufers +langlaufs +langley +langleys +langobard +langobardic +langobards +langostino +langostinos +langouste +langoustes +langoustine +langoustines +langrage +langrages +langsyne +language +languages +langue +languedoc +langues +languet +languets +languid +languidly +languidness +languish +languished +languisher +languishers +languishes +languishing +languishingly +languishment +languishments +languor +languorous +languorously +languorousness +langur +langurs +laniard +laniards +laniferous +lank +lanka +lankan +lankans +lanker +lankest +lankier +lankiest +lankily +lankiness +lankly +lankness +lanky +lanner +lanneret +lannerets +lanners +lanolin +lanose +lanosity +lansing +lantana +lantanas +lantern +lanterns +lanthanide +lanthanum +lanthorn +lanthorns +lanuginose +lanuginous +lanuginousness +lanugo +lanugos +lanyard +lanyards +lanzarote +lao +laocoon +laodicea +laodicean +laodiceans +laomedon +laos +laotian +laotians +lap +laparoscope +laparoscopes +laparoscopic +laparoscopies +laparoscopist +laparoscopists +laparoscopy +laparotomies +laparotomy +lapboard +lapboards +lapdog +lapdogs +lapel +lapeled +lapelled +lapels +lapful +lapfuls +lapidarian +lapidaries +lapidary +lapilli +lapillus +lapin +lapis +lapith +lapiths +laplace +lapland +laplander +laplanders +lapp +lapped +lapper +lappers +lappet +lappets +lapping +lappish +lapps +laps +lapsang +lapse +lapsed +lapser +lapsers +lapses +lapsing +lapstrake +lapstreak +laptev +laptop +laptops +laputa +laputan +laputans +lapwing +lapwings +lar +laramie +larboard +larboards +larcener +larceners +larcenies +larcenist +larcenists +larcenous +larcenously +larceny +larch +larches +lard +larded +larder +larders +larding +lardon +lardons +lardoon +lardoons +lards +lardy +laree +larees +lares +large +largehearted +largeheartedness +largely +largemouth +largeness +larger +largess +largesse +largesses +largest +larghetto +larghettos +largish +largo +largos +lariat +lariats +lark +larked +larker +larkers +larkier +larkiest +larkiness +larking +larkish +larks +larkspur +larkspurs +larky +larmoyante +larnaca +larrigan +larrigans +larrikin +larrikins +larrup +larruped +larruping +larrups +larum +larums +larva +larvae +larval +larvas +larvicidal +larvicide +larvicides +laryngal +laryngals +laryngeal +laryngeals +laryngectomies +laryngectomized +laryngectomy +larynges +laryngitic +laryngitis +laryngologist +laryngologists +laryngology +laryngopharynx +laryngopharynxs +laryngoscope +laryngoscopes +laryngoscopic +laryngoscopical +laryngoscopically +laryngoscopy +larynx +larynxes +lasagna +lasagnas +lasagne +lascar +lascars +lascivious +lasciviously +lasciviousness +lase +lased +laser +laserlike +lasers +lases +lash +lashed +lasher +lashers +lashes +lashing +lashings +lashins +lasing +lass +lassa +lassen +lasses +lassie +lassies +lassitude +lasso +lassoed +lassoer +lassoers +lassoes +lassoing +lassos +last +lasted +laster +lasters +lastex +lasting +lastingly +lastingness +lastly +lasts +latakia +latch +latched +latches +latchet +latchets +latching +latchkey +latchkeys +latchstring +latchstrings +late +latecomer +latecomers +lated +lateen +lateener +lateeners +lateens +latelies +lately +laten +latencies +latency +latened +lateness +latening +latens +latensification +latensifications +latent +latently +later +laterad +lateral +lateraled +lateraling +laterality +lateralization +lateralizations +lateralize +lateralized +lateralizes +lateralizing +lateralled +lateralling +laterally +laterals +laterite +laterites +lateritic +laterization +laterizations +latest +latests +latewood +latewoods +latex +latexes +lath +lathe +lathed +lather +lathered +latherer +latherers +lathering +lathers +lathery +lathes +lathing +lathings +laths +lathyrism +lathyrisms +lathyritic +latices +laticifer +laticiferous +laticifers +latifundia +latifundio +latifundios +latifundium +latigo +latigoes +latigos +latimer +latin +latina +latinate +latinism +latinisms +latinist +latinists +latinity +latinization +latinizations +latinize +latinized +latinizer +latinizers +latinizes +latinizing +latino +latinos +latins +latish +latissimi +latissimus +latitude +latitudes +latitudinal +latitudinally +latitudinarian +latitudinarianism +latitudinarians +latium +latke +latkes +latosol +latosolic +latosols +latrine +latrines +latten +lattens +latter +latterly +lattermost +lattice +latticed +lattices +latticework +latticing +latus +latvia +latvian +latvians +lauan +lauans +laud +laudability +laudable +laudableness +laudably +laudanum +laudation +laudations +laudative +laudatory +laude +lauded +lauder +lauderdale +lauders +lauding +lauds +laugh +laughable +laughableness +laughably +laughed +laugher +laughers +laughing +laughingly +laughingstock +laughingstocks +laughs +laughter +launce +launces +launch +launched +launcher +launchers +launches +launching +launchings +launchpad +launchpads +launder +laundered +launderer +launderers +launderette +launderettes +laundering +launderings +launders +laundress +laundresses +laundrette +laundrettes +laundries +laundromat +laundromats +laundry +laundryman +laundrymen +launfal +laura +lauras +laurasia +laureate +laureates +laureateship +laureateships +laureation +laureations +laurel +laureled +laureling +laurelled +laurelling +laurels +laurent +laurentian +lauric +lauryl +lausanne +lautrec +lava +lavabo +lavaboes +lavage +lavages +lavalava +lavalavas +lavalier +lavaliere +lavalieres +lavalike +lavallière +lavallières +lavas +lavation +lavations +lavatories +lavatory +lave +laved +lavender +lavendered +lavendering +lavenders +laver +laverock +laverocks +lavers +laves +laving +lavinia +lavish +lavished +lavisher +lavishers +lavishes +lavishing +lavishly +lavishness +lavoisier +lavrock +lavrocks +law +lawbreaker +lawbreakers +lawbreaking +lawed +lawful +lawfully +lawfulness +lawgiver +lawgivers +lawing +lawless +lawlessly +lawlessness +lawmaker +lawmakers +lawmaking +lawman +lawmen +lawn +lawnmower +lawnmowers +lawns +lawny +lawrence +lawrencian +lawrencium +lawrentian +laws +lawsuit +lawsuits +lawyer +lawyering +lawyerings +lawyerlike +lawyerly +lawyers +lax +laxation +laxations +laxative +laxatives +laxer +laxest +laxities +laxity +laxly +laxness +lay +layabout +layabouts +layaway +layaways +layback +laybacks +layer +layerage +layerages +layered +layering +layerings +layers +layette +layettes +laying +layman +laymen +layoff +layoffs +layout +layouts +layover +layovers +laypeople +layperson +laypersons +lays +layup +layups +laywoman +laywomen +lazar +lazaret +lazarets +lazarette +lazarettes +lazaretto +lazarettos +lazarist +lazarists +lazars +lazarus +laze +lazed +lazes +lazied +lazier +lazies +laziest +lazily +laziness +lazing +lazuli +lazulite +lazulites +lazurite +lazurites +lazy +lazybones +lazying +lazyish +lb +lea +leach +leachability +leachable +leachate +leachates +leached +leacher +leachers +leaches +leaching +lead +leaded +leaden +leadenly +leadenness +leader +leaderless +leaders +leadership +leaderships +leadier +leadiest +leading +leadingly +leadless +leadman +leadmen +leadoff +leadoffs +leadplant +leadplants +leads +leadscrew +leadscrews +leadsman +leadsmen +leadwork +leadwort +leadworts +leady +leaf +leafage +leafed +leafhopper +leafhoppers +leafier +leafiest +leafiness +leafing +leafless +leaflet +leafleted +leafleteer +leafleteers +leafleting +leaflets +leafletted +leafletting +leaflike +leafs +leafstalk +leafstalks +leafy +league +leagued +leaguer +leaguered +leaguering +leaguers +leagues +leaguing +leah +leak +leakage +leakages +leaked +leaker +leakers +leakier +leakiest +leakily +leakiness +leaking +leakproof +leaks +leaky +leal +leally +lean +leander +leaned +leaner +leanest +leaning +leanings +leanly +leanness +leans +leant +leap +leaped +leaper +leapers +leapfrog +leapfrogged +leapfrogging +leapfrogs +leaping +leaps +leapt +lear +learn +learnable +learned +learnedly +learnedness +learner +learners +learning +learns +learnt +leary +leas +leasable +lease +leaseback +leased +leasehold +leaseholder +leaseholders +leaseholds +leaser +leasers +leases +leash +leashed +leashes +leashing +leasing +leasings +least +leastways +leastwise +leather +leatherback +leatherbacks +leathered +leatherette +leatherettes +leatherhead +leatherheads +leatheriness +leathering +leatherjacket +leatherjackets +leatherleaf +leatherlike +leathern +leatherneck +leathernecks +leathers +leatherwear +leatherwood +leatherwoods +leatherwork +leatherworker +leatherworkers +leatherworking +leatherworks +leathery +leave +leaved +leaven +leavened +leavening +leavenings +leavens +leaver +leavers +leaves +leaving +leavings +leavis +leavisite +lebanese +lebanon +lebensraum +lebenswelt +lebkuchen +lecce +lech +leched +lecher +lecheries +lecherous +lecherously +lecherousness +lechers +lechery +leches +leching +lechwe +lechwes +lecithin +lecithinase +lecithinases +lectern +lecterns +lectin +lectins +lection +lectionaries +lectionary +lections +lector +lectors +lectotype +lectotypes +lecture +lectured +lecturer +lecturers +lectures +lectureship +lectureships +lecturing +led +leda +lederhosen +ledge +ledger +ledgers +ledges +ledgy +lee +leeboard +leeboards +leech +leeched +leeches +leeching +leechlike +leek +leeks +leer +leered +leerier +leeriest +leerily +leeriness +leering +leeringly +leers +leery +lees +leeuwenhoek +leeward +leeway +left +lefties +leftish +leftism +leftist +leftists +leftmost +leftover +leftovers +lefts +leftward +leftwards +leftwing +lefty +leg +legacies +legacy +legal +legalese +legaleses +legalism +legalisms +legalist +legalistic +legalistically +legalists +legalities +legality +legalization +legalizations +legalize +legalized +legalizer +legalizers +legalizes +legalizing +legally +legals +legate +legated +legatee +legatees +legates +legateship +legateships +legatine +legating +legation +legationary +legations +legato +legator +legators +legatos +legend +legendarily +legendary +legendries +legendry +legends +leger +legerdemain +legerdemains +legerity +legers +leges +legged +legger +leggers +leggier +leggiest +leggin +legginess +legging +leggings +leggins +leggy +leghold +leghorn +leghorns +legibility +legible +legibleness +legibly +legion +legionaries +legionary +legionella +legionellae +legionnaire +legionnaires +legions +legislate +legislated +legislates +legislating +legislation +legislative +legislatively +legislatives +legislator +legislatorial +legislators +legislatorship +legislatorships +legislature +legislatures +legist +legists +legit +legitimacy +legitimate +legitimated +legitimately +legitimateness +legitimates +legitimating +legitimation +legitimations +legitimatize +legitimatized +legitimatizes +legitimatizing +legitimator +legitimators +legitimism +legitimist +legitimists +legitimization +legitimizations +legitimize +legitimized +legitimizer +legitimizers +legitimizes +legitimizing +legless +legman +legmen +legomena +legomenon +legroom +legs +legume +legumes +leguminous +legwork +lehar +lehigh +lehua +lehuas +lei +leibnitz +leicester +leicesters +leicestershire +leiden +leipzig +leis +leishmania +leishmanial +leishmanias +leishmaniasis +leister +leistered +leistering +leisters +leisure +leisured +leisureliness +leisurely +leisurewear +leitmotif +leitmotifs +leitmotiv +leitmotivs +lek +leke +leks +leku +lekvar +lekvars +lely +leman +lemans +lemma +lemmas +lemmata +lemming +lemminglike +lemmings +lemniscal +lemniscate +lemnisci +lemniscus +lemnos +lemon +lemonade +lemonades +lemongrass +lemongrasses +lemons +lemony +lempira +lempiras +lemur +lemures +lemurlike +lemurs +lenape +lenapes +lend +lendable +lender +lenders +lending +lends +length +lengthen +lengthened +lengthener +lengtheners +lengthening +lengthens +lengthier +lengthiest +lengthily +lengthiness +lengths +lengthways +lengthwise +lengthy +lenience +leniencies +leniency +lenient +leniently +lenin +leningrad +leninism +leninist +leninists +leninite +leninites +lenis +lenition +lenitions +lenitive +lenitively +lenitives +lenity +lennon +lennox +leno +lenos +lens +lense +lensed +lenses +lensing +lensless +lensman +lensmen +lent +lentamente +lentando +lenten +lentic +lenticel +lenticellate +lenticels +lenticular +lenticule +lenticules +lentigines +lentiginose +lentiginous +lentigo +lentil +lentils +lentisk +lentisks +lentissimo +lentivirus +lentiviruses +lento +lentos +lents +leo +leonardo +leone +leones +leonian +leonians +leonid +leonides +leonids +leonine +leopard +leopardess +leopardesses +leopardi +leopards +leopold +leos +leotard +leotarded +leotards +lepanto +lepcha +lepchas +leper +lepers +lepidolite +lepidolites +lepidoptera +lepidopteran +lepidopterans +lepidopterist +lepidopterists +lepidopterological +lepidopterologist +lepidopterologists +lepidopterology +lepidopterous +lepidote +lepontic +lepontine +leporine +leprechaun +leprechaunish +leprechauns +lepromatous +leprosaria +leprosarium +leprosariums +leprose +leprosy +leprotic +leprous +leprously +leprousness +lepta +leptocephali +leptocephalus +lepton +leptonic +leptons +leptosomatic +leptosome +leptosomes +leptospiral +leptospire +leptospires +leptospirosis +leptotene +leptotenes +lepus +lerici +lesbian +lesbianism +lesbians +lesbos +lese +lesion +lesioned +lesions +lesotho +lespedeza +lespedezas +less +lessee +lessees +lessen +lessened +lessening +lessens +lesser +lesson +lessoned +lessoning +lessons +lessor +lessors +lest +let +let's +letch +letches +letdown +letdowns +lethal +lethality +lethally +lethalness +lethargic +lethargically +lethargies +lethargy +lethe +lethean +leto +lets +lett +letted +letter +letterbox +letterboxed +letterboxes +letterboxing +lettered +letterer +letterers +letterform +letterforms +lettergram +lettergrams +letterhead +letterheads +lettering +letterings +letterman +lettermen +letterpress +letterpresses +letters +letterspacing +lettic +letting +lettings +lettish +letts +lettuce +lettuces +letup +letups +leu +leucine +leucines +leucite +leucites +leucitic +leucocidin +leucocidins +leucocyte +leucocytes +leucocytic +leucocytoid +leucocytoses +leucocytosis +leucocytotic +leucoderma +leucodermal +leucodermas +leucodermic +leucopenia +leucopenias +leucopenic +leucoplast +leucoplastid +leucoplastids +leucoplasts +leucorrhea +leucorrheal +leucorrheas +leucotomies +leucotomy +leukemia +leukemic +leukemics +leukemogenesis +leukemogenic +leukemoid +leukocyte +leukocytes +leukocytic +leukocytoid +leukocytoses +leukocytosis +leukocytotic +leukoderma +leukodermal +leukodermas +leukodermic +leukodystrophy +leukopenia +leukopenias +leukopenic +leukoplakia +leukoplakias +leukoplakic +leukoplasia +leukoplasias +leukopoiesis +leukopoietic +leukorrhea +leukorrheal +leukorrheas +leukoses +leukosis +leukotomies +leukotomy +leukotriene +leukotrienes +lev +leva +levalloisian +levant +levanted +levanter +levanters +levantine +levantines +levanting +levants +levas +levator +levatores +levators +levee +leveed +leveeing +levees +level +leveled +leveler +levelers +levelheaded +levelheadedly +levelheadedness +leveling +levelled +leveller +levellers +levelling +levelly +levelness +levels +lever +leverage +leveraged +leverages +leveraging +levered +leveret +leverets +leverhulme +levering +leverkusen +levers +levi +levi's +leviable +leviathan +leviathans +levied +levier +leviers +levies +levigate +levigated +levigates +levigating +levigation +levigations +levin +levins +levirate +levirates +leviratic +leviratical +levis +levitate +levitated +levitates +levitating +levitation +levitational +levitations +levitator +levitators +levite +levites +levitic +levitical +leviticus +levities +levity +levo +levodopa +levodopas +levorotary +levorotation +levorotations +levorotatory +levs +levulose +levuloses +levy +levying +lewd +lewder +lewdest +lewdly +lewdness +lewis +lewises +lewisite +lewisites +lewisson +lewissons +lex +lexeme +lexemes +lexemic +lexes +lexica +lexical +lexicality +lexicalization +lexicalizations +lexicalize +lexicalized +lexicalizes +lexicalizing +lexically +lexicographer +lexicographers +lexicographic +lexicographical +lexicographically +lexicography +lexicological +lexicologically +lexicologist +lexicologists +lexicology +lexicon +lexicons +lexington +lexis +lexises +ley +leyden +león +lhasa +lhotse +li +liabilities +liability +liable +liaise +liaised +liaises +liaising +liaison +liaisons +liana +lianas +liane +lianes +liang +liao +liaodong +liaoning +liaotung +liar +liars +liassic +lib +libation +libationary +libations +libbed +libber +libbers +libbing +libecchio +libeccio +libel +libelant +libelants +libeled +libelee +libelees +libeler +libelers +libeling +libelist +libelists +libellant +libellants +libelled +libellee +libellees +libelling +libellous +libelous +libelously +libels +libera +liberace +liberal +liberalism +liberalist +liberalistic +liberalists +liberalities +liberality +liberalization +liberalizations +liberalize +liberalized +liberalizer +liberalizers +liberalizes +liberalizing +liberally +liberalness +liberals +liberate +liberated +liberates +liberating +liberatingly +liberation +liberationist +liberationists +liberations +liberator +liberators +liberia +liberian +liberians +libertarian +libertarianism +libertarians +liberties +libertinage +libertinages +libertine +libertines +libertinism +liberty +libidinal +libidinally +libidinous +libidinously +libidinousness +libido +libidos +libitum +libra +librae +libran +librans +librarian +librarians +librarianship +librarianships +libraries +library +libration +librational +librations +libratory +libre +libres +libretti +librettist +librettists +libretto +librettos +libriform +libris +librist +librists +librium +libs +libya +libyan +libyans +lice +licence +licenced +licences +licencing +licensable +license +licensed +licensee +licensees +licenser +licensers +licenses +licensing +licensor +licensors +licensure +licensures +licente +licentiate +licentiates +licentious +licentiously +licentiousness +lich +lichee +lichees +lichen +lichened +lichening +lichenological +lichenologist +lichenologists +lichenology +lichenous +lichens +licit +licitly +licitness +lick +licked +licker +lickerish +lickerishly +lickerishness +lickers +lickety +licking +lickings +licks +lickspittle +lickspittles +licorice +lictor +lictors +lid +lidar +lidded +lidding +lidless +lido +lidocaine +lidos +lids +lie +liebfraumilch +liebig +liechtenstein +liechtensteiner +liechtensteiners +lied +lieder +liederkranz +lief +liefer +liefest +liege +liegeman +liegemen +lieges +lien +liens +lier +lierne +liernes +liers +lies +lieu +lieutenancies +lieutenancy +lieutenant +lieutenants +life +lifeblood +lifeboat +lifeboats +lifeful +lifeguard +lifeguarded +lifeguarding +lifeguards +lifejacket +lifejackets +lifeless +lifelessly +lifelessness +lifelike +lifelikeness +lifeline +lifelines +lifelong +lifer +lifers +lifes +lifesaver +lifesavers +lifesaving +lifestyle +lifestyles +lifetime +lifetimes +lifeway +lifework +lifo +lift +liftable +lifted +lifter +lifters +liftgate +liftgates +lifting +liftman +liftmen +liftoff +liftoffs +lifts +ligament +ligamental +ligamentary +ligamentous +ligaments +ligan +ligand +ligands +ligans +ligase +ligases +ligate +ligated +ligates +ligating +ligation +ligations +ligature +ligatured +ligatures +ligaturing +liger +ligers +light +lightbulb +lightbulbs +lighted +lighten +lightened +lightener +lighteners +lightening +lightens +lighter +lighterage +lighterages +lighters +lightest +lightface +lightfaced +lightfast +lightfastness +lightheaded +lightheadedly +lightheadedness +lighthearted +lightheartedly +lightheartedness +lighthouse +lighthouses +lighting +lightings +lightish +lightless +lightlessness +lightly +lightness +lightning +lightninged +lightninglike +lightnings +lightplane +lightplanes +lightproof +lights +lightship +lightships +lightsome +lightsomely +lightsomeness +lighttight +lightweight +lightweights +lightwood +lightwoods +ligneous +lignification +lignifications +lignified +lignifies +lignify +lignifying +lignin +lignite +lignitic +lignocellulose +lignocelluloses +lignocellulosic +lignosulfonate +lignosulfonates +lignum +ligroin +ligula +ligulae +ligulas +ligulate +ligule +ligules +ligure +ligures +liguria +ligurian +ligurians +likability +likable +likableness +like +likeable +likeableness +liked +likelier +likeliest +likelihood +likeliness +likely +liken +likened +likeness +likenesses +likening +likens +likes +likewise +liking +likings +likker +likuta +lilac +lilacs +lilangeni +lilied +lilies +lilith +lille +lilliput +lilliputian +lilliputians +lilt +lilted +lilting +liltingly +liltingness +lilts +lily +lima +limacine +limacon +limacons +limas +limassol +limb +limba +limbas +limbate +limbeck +limbecks +limbed +limber +limbered +limbering +limberly +limberness +limbers +limbi +limbic +limbing +limbless +limbo +limbos +limbs +limburg +limburger +limburgers +limbus +limby +lime +limeade +limeades +limed +limekiln +limekilns +limelight +limen +limens +limerick +limericks +limes +limestone +limewater +limewaters +limey +limeys +limicoline +limicolous +limier +limiest +limina +liminal +liming +limit +limitability +limitable +limitary +limitation +limitational +limitations +limitative +limited +limitedly +limitedness +limiteds +limiter +limiters +limites +limiting +limitingly +limitless +limitlessly +limitlessness +limitrophe +limits +limmer +limmers +limn +limned +limner +limners +limnetic +limning +limnologic +limnological +limnologically +limnologist +limnologists +limnology +limns +limo +limoges +limonene +limonenes +limonite +limonitic +limos +limousin +limousine +limousines +limp +limpa +limped +limper +limpest +limpet +limpets +limpid +limpidity +limpidly +limpidness +limping +limpkin +limpkins +limply +limpness +limpopo +limps +limuli +limulus +limy +linac +linacs +linage +linages +linalool +linalools +linchpin +linchpins +lincoln +lincolnesque +lincolniana +lincolnshire +lincomycin +lincomycins +lindane +lindanes +lindbergh +lindemann +linden +lindens +lindesnes +lindies +lindisfarne +lindy +line +lineage +lineages +lineal +lineality +lineally +lineament +lineamental +lineaments +linear +linearity +linearization +linearizations +linearize +linearized +linearizes +linearizing +linearly +lineation +lineations +linebacker +linebackers +linebacking +linebred +linebreeding +linecaster +linecasters +linecasting +linecut +linecuts +lined +linefeed +linefeeds +lineman +linemen +linen +linens +lineolate +liner +linerboard +linerboards +linerless +liners +lines +linesman +linesmen +lineswoman +lineswomen +lineup +lineups +liney +ling +linga +lingala +lingalas +lingam +lingams +lingas +lingayat +lingayats +lingayen +lingberries +lingberry +lingcod +lingcods +linger +lingered +lingerer +lingerers +lingerie +lingering +lingeringly +lingers +lingo +lingoes +lingonberries +lingonberry +lings +lingua +linguae +lingual +lingually +linguals +linguine +linguini +linguist +linguistic +linguistical +linguistically +linguistician +linguisticians +linguistics +linguists +lingulate +liniment +liniments +linin +lining +linings +linins +link +linkage +linkages +linkboy +linkboys +linked +linker +linkers +linking +linkings +linkman +linkmen +links +linksman +linksmen +linkup +linkups +linn +linnaean +linnaeus +linnean +linnet +linnets +linnhe +linns +linocut +linocuts +linoleate +linoleates +linoleic +linolenic +linoleum +linotype +linotypes +linsang +linsangs +linseed +linseeds +linsey +linstock +linstocks +lint +lintel +lintels +linter +linters +lintless +lintwhite +lintwhites +linty +linuron +linurons +lion +lioness +lionesses +lionfish +lionfishes +lionheart +lionhearted +lionization +lionizations +lionize +lionized +lionizer +lionizers +lionizes +lionizing +lionlike +lions +lip +lipan +lipans +lipari +lipase +lipases +lipectomies +lipectomy +lipid +lipide +lipides +lipidic +lipids +lipizzan +lipizzaner +lipizzaners +lipizzans +lipless +liplike +lipogenesis +lipoic +lipoid +lipoidal +lipoids +lipolyses +lipolysis +lipolytic +lipoma +lipomas +lipomata +lipomatous +lipophilic +lipopolysaccharide +lipopolysaccharides +lipoprotein +lipoproteins +liposomal +liposome +liposomes +liposuction +liposuctions +lipotropic +lipotropin +lipotropins +lipotropism +lipotropy +lipped +lippes +lippi +lippier +lippiest +lipping +lippizan +lippizaner +lippizaners +lippizans +lippy +lipreading +lips +lipstick +lipsticked +lipsticks +liptauer +liptauers +lipton +liquate +liquated +liquates +liquating +liquation +liquations +liquefacient +liquefaction +liquefactions +liquefactive +liquefiable +liquefied +liquefier +liquefiers +liquefies +liquefy +liquefying +liquescence +liquescency +liquescent +liqueur +liqueurs +liquid +liquidambar +liquidambars +liquidate +liquidated +liquidates +liquidating +liquidation +liquidations +liquidator +liquidators +liquidity +liquidize +liquidized +liquidizes +liquidizing +liquidly +liquidness +liquids +liquified +liquifies +liquify +liquifying +liquor +liquored +liquorice +liquoring +liquors +lira +liras +lire +liri +liripipe +liripipes +lirot +liroth +lisbon +lisente +lisle +lisp +lisped +lisper +lispers +lisping +lisps +lissom +lissome +lissomely +lissomeness +list +listed +listee +listees +listel +listels +listen +listenability +listenable +listened +listener +listeners +listenership +listenerships +listening +listens +lister +listeria +listerias +listeriosis +listers +listing +listings +listless +listlessly +listlessness +lists +liszt +lit +litanies +litany +litchi +litchis +lite +liter +literacy +literal +literalism +literalist +literalistic +literalists +literality +literalization +literalizations +literalize +literalized +literalizes +literalizing +literally +literalness +literals +literarily +literariness +literary +literate +literately +literateness +literates +literati +literatim +literation +literations +literator +literators +literature +literatures +literatus +liters +litharge +litharges +lithe +lithely +litheness +lither +lithesome +lithest +lithia +lithias +lithiases +lithiasis +lithic +lithification +lithifications +lithified +lithifies +lithify +lithifying +lithium +litho +lithoed +lithoes +lithograph +lithographed +lithographer +lithographers +lithographic +lithographical +lithographically +lithographing +lithographs +lithography +lithoing +lithologic +lithological +lithologically +lithologist +lithologists +lithology +lithophane +lithophanes +lithophyte +lithophytes +lithophytic +lithopone +lithopones +lithos +lithosol +lithosols +lithosphere +lithospheres +lithospheric +lithostratigraphic +lithostratigraphy +lithotomies +lithotomy +lithotripsies +lithotripsy +lithotripter +lithotripters +lithotriptor +lithotriptors +lithotrities +lithotrity +lithuania +lithuanian +lithuanians +litigable +litigant +litigants +litigate +litigated +litigates +litigating +litigation +litigations +litigator +litigators +litigious +litigiously +litigiousness +litmus +litotes +litre +litres +litten +litter +litterateur +litterateurs +litterbag +litterbags +litterbug +litterbugs +littered +litterer +litterers +littering +littermate +littermates +litters +littery +little +littleneck +littlenecks +littleness +littler +littlest +littoral +littorals +littérateur +littérateurs +liturgic +liturgical +liturgically +liturgics +liturgies +liturgiologist +liturgiologists +liturgiology +liturgist +liturgists +liturgy +livability +livable +livableness +live +liveability +liveable +livebearer +livebearers +lived +livelier +liveliest +livelihood +livelihoods +livelily +liveliness +livelong +lively +liven +livened +liveness +livening +livens +liver +livered +liveried +liveries +liverish +liverishness +liverleaf +liverleaves +liverpudlian +liverpudlians +livers +liverwort +liverworts +liverwurst +livery +liveryman +liverymen +lives +livestock +livetrap +livetraps +livid +lividity +lividly +lividness +living +livingly +livingness +livings +livingstone +livonia +livonian +livonians +livorno +livre +livres +livy +lixiviate +lixiviated +lixiviates +lixiviating +lixiviation +lixiviations +lizard +lizardfish +lizardfishes +lizardlike +lizards +lizzie +liège +ljubljana +ll +llama +llamas +llano +llanos +lloyd +llullaillaco +lo +loach +loaches +load +loaded +loader +loaders +loading +loadings +loadmaster +loadmasters +loads +loadstar +loadstars +loadstone +loadstones +loaf +loafed +loafer +loafers +loafing +loafs +loam +loamed +loaming +loams +loamy +loan +loanable +loanda +loaned +loaner +loaners +loaning +loans +loansharking +loansharkings +loanword +loanwords +loath +loathe +loathed +loather +loathers +loathes +loathing +loathingly +loathings +loathly +loathness +loathsome +loathsomely +loathsomeness +loaves +lob +lobar +lobate +lobated +lobately +lobation +lobations +lobbed +lobber +lobbers +lobbied +lobbies +lobbing +lobby +lobbyer +lobbyers +lobbygow +lobbygows +lobbying +lobbyism +lobbyist +lobbyists +lobe +lobectomies +lobectomy +lobed +lobefin +lobefinned +lobefins +lobelia +lobelias +lobeline +lobelines +lobes +loblollies +loblolly +lobo +lobola +lobolas +lobos +lobotomies +lobotomize +lobotomized +lobotomizes +lobotomizing +lobotomy +lobs +lobscouse +lobscouses +lobster +lobstered +lobsterer +lobsterers +lobstering +lobsterlike +lobsterman +lobstermen +lobsters +lobular +lobularly +lobulate +lobulated +lobulation +lobulations +lobule +lobules +lobulose +lobworm +lobworms +loc +local +locale +locales +localism +localisms +localist +localists +localite +localites +localities +locality +localizability +localizable +localization +localizations +localize +localized +localizer +localizers +localizes +localizing +locally +localness +locals +locarno +locatable +locate +located +locater +locaters +locates +locating +location +locational +locationally +locations +locative +locatives +locator +locators +loch +lochia +lochial +lochs +loci +lock +lockable +lockage +lockages +lockbox +lockboxes +lockdown +lockdowns +locke +locked +locker +lockers +locket +lockets +locking +lockjaw +lockkeeper +lockkeepers +lockmaster +lockmasters +locknut +locknuts +lockout +lockouts +lockram +locks +lockset +locksets +locksmith +locksmithing +locksmiths +lockstep +lockstitch +lockstitched +lockstitches +lockstitching +lockup +lockups +loco +locoed +locoes +locofoco +locofocos +locoing +locoism +locoisms +locomote +locomoted +locomotes +locomoting +locomotion +locomotive +locomotives +locomotor +locomotory +locos +locoweed +locoweeds +locular +loculate +loculated +loculation +loculations +locule +loculed +locules +loculi +loculicidal +loculus +locum +locus +locust +locusts +locution +locutions +lode +loden +lodens +lodes +lodestar +lodestars +lodestone +lodestones +lodge +lodged +lodgement +lodgements +lodgepole +lodger +lodgers +lodges +lodging +lodgings +lodgment +lodgments +lodicule +lodicules +loeb +loess +loessial +loft +lofted +loftier +loftiest +loftily +loftiness +lofting +loftlike +lofts +lofty +log +loganberries +loganberry +logarithm +logarithmic +logarithmical +logarithmically +logarithms +logbook +logbooks +loge +loges +logged +logger +loggerhead +loggerheads +loggers +loggia +loggias +logging +loggings +logia +logic +logical +logicality +logically +logicalness +logician +logicians +logics +logier +logiest +login +logins +logion +logistic +logistical +logistically +logistician +logisticians +logistics +logjam +logjams +lognormal +lognormality +lognormally +logo +logogram +logogrammatic +logogrammatically +logograms +logograph +logographic +logographically +logographs +logography +logogriph +logogriphs +logoi +logomachies +logomachy +logorrhea +logorrheic +logos +logotype +logotypes +logout +logroll +logrolled +logroller +logrollers +logrolling +logrollings +logrolls +logs +logwood +logwoods +logy +lohengrin +loin +loincloth +loincloths +loins +loire +loiter +loitered +loiterer +loiterers +loitering +loiters +loki +lolita +lolitas +loll +lolland +lollapalooza +lollapaloozas +lollard +lollardism +lollards +lollardy +lolled +loller +lollers +lollies +lolling +lollingly +lollipop +lollipops +lollop +lolloped +lolloping +lollops +lollopy +lolls +lolly +lollygag +lollygagged +lollygagging +lollygags +lollypop +lollypops +lombard +lombardian +lombardic +lombards +lombardy +lombok +loment +loments +lomond +lomé +london +londonderry +londoner +londoners +lone +lonelier +loneliest +lonelily +loneliness +lonely +loneness +loner +loners +lonesome +lonesomely +lonesomeness +lonesomes +long +longan +longanimity +longans +longboat +longboats +longbow +longbowman +longbowmen +longbows +longcase +longed +longer +longeron +longerons +longest +longevities +longevity +longevous +longfellow +longhair +longhaired +longhairs +longhand +longhead +longheaded +longheadedness +longheads +longhorn +longhorns +longhouse +longhouses +longicorn +longicorns +longing +longingly +longings +longish +longitude +longitudes +longitudinal +longitudinally +longleaf +longlegs +longline +longlines +longman +longneck +longnecks +longness +longobard +longobardi +longobardic +longobards +longs +longship +longships +longshore +longshoreman +longshoremen +longshoring +longsighted +longsightedness +longsome +longsomely +longsomeness +longspur +longspurs +longstanding +longsuffering +longtime +longue +longues +longueur +longueurs +longwinded +longwindedly +longwise +longyi +longyis +lonsdale +loo +loobies +looby +loofa +loofah +loofahs +loofas +look +lookalike +lookalikes +lookdown +lookdowns +looked +looker +lookers +looking +lookout +lookouts +looks +lookup +lookups +loom +loomed +looming +looms +loon +looney +looneys +loonier +loonies +looniest +loonily +looniness +loons +loony +loop +looped +looper +loopers +loophole +loopholes +loopier +loopiest +looping +loops +loopy +loos +loose +loosed +loosely +loosen +loosened +looseness +loosening +loosens +looser +looses +loosest +loosestrife +loosestrifes +loosey +loosing +loot +looted +looter +looters +looting +loots +lop +lope +loped +loper +lopers +lopes +lophophore +lophophores +loping +lopped +lopper +loppers +loppier +loppiest +lopping +loppy +lops +lopsided +lopsidedly +lopsidedness +loquacious +loquaciously +loquaciousness +loquacity +loquat +loquats +loran +lorca +lord +lorded +lording +lordings +lordlier +lordliest +lordliness +lordling +lordlings +lordly +lordoses +lordosis +lordotic +lords +lordship +lordships +lordy +lore +loreal +lorelei +loreleis +lorentz +lorenz +lorgnette +lorgnettes +lorgnon +lorgnons +lorica +loricae +loricate +loricated +lories +lorikeet +lorikeets +loris +lorises +lorn +lorne +lornness +lorraine +lorries +lorry +lory +los +losable +losableness +lose +losel +losels +loser +losers +loses +losing +losingest +losings +loss +losses +lossless +lossy +lost +lostness +lot +lota +lotah +lotahs +lotas +loth +lothario +lotharios +lothian +loti +lotic +lotion +lotions +lotos +lotoses +lots +lotte +lotted +lotteries +lottery +lotting +lotto +lottos +lotus +lotuses +lotusland +louche +loud +louden +loudened +loudening +loudens +louder +loudest +loudly +loudmouth +loudmouthed +loudmouths +loudness +loudspeaker +loudspeakers +loudun +lough +loughs +louis +louise +louisiana +louisville +lounge +lounged +lounger +loungers +lounges +loungewear +lounging +loupe +loupes +lour +lourdes +loured +lourenço +louring +lours +loury +louse +loused +louses +lousewort +louseworts +lousier +lousiest +lousily +lousiness +lousing +lousy +lout +louted +louting +loutish +loutishly +loutishness +louts +louvain +louver +louvered +louvers +louvre +louvred +louvres +lovability +lovable +lovableness +lovably +lovage +lovages +lovastatin +lovat +lovats +love +loveable +lovebird +lovebirds +lovebug +lovebugs +loved +lovelace +loveless +lovelessly +lovelessness +lovelier +lovelies +loveliest +lovelily +loveliness +lovelock +lovelocks +lovelorn +lovelornness +lovely +lovemaking +lover +loverly +lovers +loves +loveseat +loveseats +lovesick +lovesickness +lovesome +lovey +loving +lovingly +lovingness +low +lowball +lowballed +lowballing +lowballs +lowborn +lowboy +lowboys +lowbred +lowbrow +lowbrowed +lowbrows +lowdown +lowed +lower +lowercase +lowercased +lowercases +lowercasing +lowerclassman +lowerclassmen +lowered +lowering +loweringly +lowermost +lowers +lowery +lowest +lowing +lowland +lowlander +lowlanders +lowlands +lowlier +lowliest +lowlife +lowlifes +lowlight +lowlights +lowlihead +lowliheads +lowliness +lowlives +lowly +lown +lowness +lows +lox +loxes +loxodrome +loxodromes +loxodromic +loxodromical +loxodromically +loyal +loyalism +loyalist +loyalists +loyally +loyalties +loyalty +loyola +lozenge +lozenges +lsd +luanda +luau +luaus +luba +lubas +lubavitcher +lubavitchers +lubber +lubberliness +lubberly +lubbers +lube +lubed +lubes +lubing +lubricant +lubricants +lubricate +lubricated +lubricates +lubricating +lubrication +lubrications +lubricative +lubricator +lubricators +lubricious +lubriciously +lubriciousness +lubricities +lubricity +lubricous +lucania +lucarne +lucarnes +lucca +lucency +lucent +lucently +lucerne +luces +lucia +lucian +lucians +lucid +lucida +lucidas +lucidity +lucidly +lucidness +lucifer +luciferase +luciferases +luciferin +luciferins +lucina +lucinas +lucite +luck +lucked +luckier +luckiest +luckily +luckiness +lucking +luckless +lucknow +lucks +lucky +lucrative +lucre +lucrece +lucretian +lucretius +lucubrate +lucubrated +lucubrates +lucubrating +lucubration +lucubrations +luculent +lucullan +luddism +luddite +luddites +lude +ludes +ludicrous +ludicrously +ludicrousness +lues +luetic +luetically +luff +luffa +luffas +luffed +luffing +luffs +lufthansa +luftwaffe +lug +lugano +luge +luged +luger +lugers +luges +luggage +lugged +lugger +luggers +lugging +luging +lugs +lugsail +lugsails +lugubrious +lugubriously +lugubriousness +lugworm +lugworms +luichow +luiseño +luiseños +luke +lukewarm +lukewarmly +lukewarmness +lull +lullabied +lullabies +lullaby +lullabying +lulled +lulling +lulls +lully +lulu +lulus +lumbago +lumbar +lumber +lumbered +lumberer +lumberers +lumbering +lumberingly +lumberjack +lumberjacks +lumberman +lumbermen +lumbers +lumberyard +lumberyards +lumbricoid +lumeloid +lumen +lumenal +lumens +lumina +luminal +luminance +luminaria +luminarias +luminaries +luminary +luminesce +luminesced +luminescence +luminescent +luminesces +luminescing +luminiferous +luminism +luminist +luminists +luminosities +luminosity +luminous +luminously +luminousness +lumière +lummox +lummoxes +lump +lumpectomies +lumpectomy +lumped +lumpen +lumpenproletariat +lumpenproletariats +lumpfish +lumpfishes +lumpier +lumpiest +lumpily +lumpiness +lumping +lumpish +lumpishly +lumpishness +lumps +lumpur +lumpy +luna +lunacies +lunacy +lunar +lunarscape +lunarscapes +lunate +lunated +lunates +lunatic +lunatics +lunation +lunch +lunched +luncheon +luncheonette +luncheonettes +luncheons +luncher +lunchers +lunches +lunching +lunchmeat +lunchmeats +lunchroom +lunchrooms +lunchtime +lunchtimes +lundy +lune +lunes +lunette +lunettes +lung +lunge +lunged +lunger +lungers +lunges +lungfish +lungfishes +lungi +lunging +lungis +lungs +lungworm +lungworms +lungwort +lungworts +lungyi +lungyis +lunisolar +lunitidal +lunker +lunkers +lunkhead +lunkheaded +lunkheads +lunula +lunulae +lunular +lunulate +lunulated +lunule +lunules +luny +lupercalia +lupercalian +lupin +lupine +lupines +lupins +lupulin +lupulins +lupus +lurch +lurched +lurcher +lurchers +lurches +lurching +lurchingly +lure +lured +lurer +lurers +lures +lurex +lurid +luridly +luridness +luring +luringly +lurk +lurked +lurker +lurkers +lurking +lurkingly +lurks +lusaka +lusatia +lusatian +lusatians +luscious +lusciously +lusciousness +lush +lushed +lusher +lushes +lushest +lushing +lushly +lushness +lusitania +lusitanian +lusitanians +lust +lusted +luster +lustered +lustering +lusterless +lusters +lusterware +lustful +lustfully +lustfulness +lustier +lustiest +lustily +lustiness +lusting +lustra +lustral +lustrate +lustrated +lustrates +lustrating +lustration +lustrations +lustrative +lustrous +lustrously +lustrousness +lustrum +lustrums +lusts +lusty +lusus +lutanist +lutanists +lute +luteal +lutecium +luted +lutefisk +lutefisks +lutein +luteinization +luteinizations +luteinize +luteinized +luteinizes +luteinizing +luteins +lutenist +lutenists +luteous +lutes +lutetium +lutfisk +lutfisks +luther +lutheran +lutheranism +lutheranize +lutheranized +lutheranizes +lutheranizing +lutherans +lutherism +luthier +luthiers +luting +lutist +lutists +lutyens +lutz +lutzes +luwian +luwians +lux +luxate +luxated +luxates +luxating +luxation +luxations +luxe +luxembourg +luxembourger +luxembourgers +luxemburg +luxes +luxor +luxuriance +luxuriant +luxuriantly +luxuriate +luxuriated +luxuriates +luxuriating +luxuries +luxurious +luxuriously +luxuriousness +luxury +luzon +lwei +lyam +lyase +lyases +lycanthrope +lycanthropes +lycanthropies +lycanthropy +lyceum +lyceums +lych +lychee +lychees +lychnis +lychnises +lycia +lycian +lycians +lycopene +lycopenes +lycopod +lycopodium +lycopodiums +lycopods +lycra +lycée +lycées +lyddite +lyddites +lydia +lydian +lydians +lye +lygus +lying +lyings +lyme +lymph +lymphadenitis +lymphadenopathies +lymphadenopathy +lymphangiogram +lymphangiograms +lymphangiographic +lymphangiographies +lymphangiography +lymphatic +lymphatically +lymphatics +lymphoblast +lymphoblastic +lymphoblasts +lymphocyte +lymphocytes +lymphocytic +lymphocytosis +lymphocytotic +lymphogram +lymphograms +lymphogranuloma +lymphogranulomatoses +lymphogranulomatosis +lymphographic +lymphography +lymphoid +lymphokine +lymphokines +lymphoma +lymphomas +lymphomata +lymphomatoid +lymphomatoses +lymphomatosis +lymphomatous +lymphopoieses +lymphopoiesis +lymphopoietic +lymphosarcoma +lymphosarcomas +lymphosarcomata +lymphotoxin +lymphotoxins +lymphotropic +lynch +lynched +lyncher +lynchers +lynches +lynching +lynchings +lynchpin +lynchpins +lynx +lynxes +lyon +lyonnais +lyonnaise +lyonnesse +lyons +lyophile +lyophiled +lyophilic +lyophilization +lyophilizations +lyophilize +lyophilized +lyophilizer +lyophilizers +lyophilizes +lyophilizing +lyophobic +lyra +lyrate +lyre +lyrebird +lyrebirds +lyres +lyric +lyrical +lyrically +lyricalness +lyricism +lyricist +lyricists +lyricize +lyricized +lyricizes +lyricizing +lyrics +lyrism +lyrist +lyrists +lysander +lysate +lysates +lyse +lysed +lysenko +lysenkoism +lysergic +lyses +lysimeter +lysimeters +lysimetric +lysin +lysine +lysing +lysins +lysis +lysistrata +lysithea +lysogen +lysogenic +lysogenicity +lysogenies +lysogenization +lysogenizations +lysogenize +lysogenized +lysogenizes +lysogenizing +lysogens +lysogeny +lysol +lysolecithin +lysolecithins +lysosomal +lysosome +lysosomes +lysozyme +lysozymes +lytic +lytically +lytta +lyttae +lytton +lázne +lésvos +lèse +límnos +lübeck +m +m1 +m16 +ma +ma'am +maar +maars +maasai +maasais +maastricht +mab +mabe +mac +macabre +macabrely +macaco +macacos +macadam +macadamia +macadamias +macadamization +macadamizations +macadamize +macadamized +macadamizer +macadamizers +macadamizes +macadamizing +macanese +macao +macaque +macaques +macaroni +macaronic +macaronics +macaronies +macaronis +macaroon +macaroons +macassar +macau +macaulay +macaw +macaws +macbeth +maccabean +maccabees +macduff +mace +macebearer +macebearers +maced +macedon +macedonia +macedonian +macedonians +macer +macerate +macerated +macerater +maceraters +macerates +macerating +maceration +macerations +macerator +macerators +macers +maces +mach +machabees +mache +maches +machete +machetes +machiavelli +machiavellian +machiavellianism +machiavellians +machiavellism +machiavellist +machiavellists +machicolate +machicolated +machicolates +machicolating +machicolation +machicolations +machina +machinability +machinable +machinate +machinated +machinates +machinating +machination +machinations +machinator +machinators +machine +machineability +machineable +machined +machineless +machinelike +machineries +machinery +machines +machining +machinist +machinists +machismo +machmeter +machmeters +macho +machoism +machos +machzor +macing +macintosh +macintoshes +mack +mackenzie +mackerel +mackerels +mackinac +mackinaw +mackinaws +mackintosh +mackintoshes +mackle +mackled +mackles +macklin +mackling +maclaurin +macle +macled +macles +macmillan +macon +macpherson +macramé +macready +macro +macroaggregate +macroaggregated +macroaggregates +macrobiotic +macrobiotics +macrocephalia +macrocephalic +macrocephalous +macrocephaly +macroclimate +macroclimates +macroclimatic +macrocode +macrocodes +macrocosm +macrocosmic +macrocosmically +macrocosms +macrocyclic +macrocyte +macrocytes +macrocytic +macrocytoses +macrocytosis +macrocytotic +macrodome +macrodomes +macroeconomic +macroeconomics +macroeconomist +macroeconomists +macroevolution +macroevolutionary +macroevolutions +macrofossil +macrofossils +macrogamete +macrogametes +macroglobulin +macroglobulinemia +macroglobulinemias +macroglobulinemic +macroglobulins +macrograph +macrographs +macrography +macroinstruction +macroinstructions +macrolepidoptera +macromere +macromeres +macromolecular +macromolecule +macromolecules +macron +macrons +macronuclear +macronuclei +macronucleus +macronutrient +macronutrients +macrophage +macrophages +macrophagic +macrophotograph +macrophotographs +macrophotography +macrophysics +macrophyte +macrophytes +macrophytic +macropterous +macros +macroscale +macroscales +macroscopic +macroscopical +macroscopically +macrosporangia +macrosporangium +macrospore +macrospores +macrostructural +macrostructure +macrostructures +macs +macula +maculae +macular +maculas +maculate +maculated +maculates +maculating +maculation +macule +maculed +macules +maculing +macumba +macédoine +mad +madagascan +madagascans +madagascar +madam +madame +madames +madams +madcap +madcaps +madded +madden +maddened +maddening +maddeningly +maddens +madder +madders +maddest +madding +maddish +made +madeira +madeiran +madeirans +madeiras +madeleine +madeleines +mademoiselle +mademoiselles +madhouse +madhouses +madhya +madison +madly +madman +madmen +madness +madnesses +madonna +madonnas +madras +madrepore +madrepores +madreporian +madreporic +madreporite +madreporites +madrid +madrigal +madrigalian +madrigalist +madrigalists +madrigals +madrilene +madrilenes +madrilène +madrilènes +madrona +madrone +madrones +madrono +madroña +madroñas +madroño +madroños +mads +maduro +maduros +madwoman +madwomen +madwort +madworts +mae +maecenas +maecenases +maelstrom +maelstroms +maenad +maenadic +maenads +maestoso +maestri +maestro +maestros +mafeking +maffick +mafficked +mafficking +mafficks +mafia +mafic +mafiosi +mafioso +mafiosos +mag +magadha +magazine +magazines +magazinist +magazinists +magdalen +magdalene +magdalenes +magdalenian +magdalens +magdeburg +mage +magellan +magellanic +magen +magenta +magentas +mages +maggiore +maggot +maggots +maggoty +maghreb +maghrib +magi +magian +magianism +magic +magical +magically +magician +magicians +magicked +magicking +magics +maginot +magisterial +magisterially +magisterium +magisteriums +magistracies +magistracy +magistral +magistrally +magistrate +magistrates +magistratical +magistratically +magistrature +magistratures +maglemosian +maglev +maglevs +magma +magmas +magmata +magmatic +magna +magnanimities +magnanimity +magnanimous +magnanimously +magnanimousness +magnate +magnates +magnesia +magnesian +magnesite +magnesites +magnesium +magnet +magnetar +magnetars +magnetic +magnetically +magnetism +magnetisms +magnetite +magnetizable +magnetization +magnetizations +magnetize +magnetized +magnetizer +magnetizers +magnetizes +magnetizing +magneto +magnetoelectric +magnetoelectricity +magnetofluiddynamic +magnetofluiddynamics +magnetogasdynamic +magnetogasdynamics +magnetograph +magnetographs +magnetohydrodynamic +magnetohydrodynamics +magnetometer +magnetometers +magnetometric +magnetometry +magnetomotive +magneton +magnetons +magnetopause +magnetopauses +magnetoplasmadynamic +magnetoplasmadynamics +magnetoresistance +magnetoresistances +magnetos +magnetosphere +magnetospheres +magnetospheric +magnetostatic +magnetostriction +magnetostrictions +magnetostrictive +magnetostrictively +magnetron +magnetrons +magnets +magnifiable +magnific +magnifical +magnifically +magnificat +magnification +magnifications +magnificats +magnificence +magnificent +magnificently +magnifico +magnificoes +magnified +magnifier +magnifiers +magnifies +magnify +magnifying +magniloquence +magniloquent +magniloquently +magnitude +magnitudes +magnolia +magnolias +magnon +magnum +magnums +magnus +magot +magots +magpie +magpies +mags +maguey +magueys +magus +magyar +magyars +mah +mahabharata +mahal +mahaleb +mahalebs +mahalo +maharaja +maharajah +maharajahs +maharajas +maharanee +maharanees +maharani +maharanis +maharashtra +maharishi +maharishis +mahatma +mahatmas +mahayana +mahayanas +mahayanist +mahayanistic +mahayanists +mahdi +mahdis +mahdism +mahdist +mahdists +mahi +mahican +mahicans +mahimahi +mahis +mahjong +mahjongg +mahjonggs +mahjongs +mahler +mahlstick +mahlsticks +mahoe +mahoes +mahoganies +mahogany +mahomet +mahonia +mahout +mahouts +mahrati +mahratta +mahratti +mahuang +mahuangs +mahzor +mahzorim +mahzors +maia +maid +maiden +maidenhair +maidenhairs +maidenhead +maidenheads +maidenhood +maidenliness +maidenly +maidens +maidhood +maidish +maidishness +maids +maidservant +maidservants +maidu +maidus +maieutic +maieutical +mail +mailability +mailable +mailbag +mailbags +mailbox +mailboxes +maile +mailed +mailer +mailers +mailgram +mailing +mailings +maillot +maillots +mailman +mailmen +mailroom +mailrooms +mails +maim +maimed +maimer +maimers +maiming +maims +main +maine +mainframe +mainframes +mainland +mainlander +mainlanders +mainline +mainlined +mainliner +mainliners +mainlines +mainlining +mainly +mainmast +mainmasts +mains +mainsail +mainsails +mainsheet +mainsheets +mainspring +mainsprings +mainstay +mainstays +mainstream +mainstreamed +mainstreamer +mainstreamers +mainstreaming +mainstreams +maintain +maintainability +maintainable +maintained +maintainer +maintainers +maintaining +maintains +maintenance +maintop +maintops +mainz +maiolica +maisonette +maisonettes +maitre +maitres +maize +maizes +majeste +majestic +majestical +majestically +majesties +majesty +majesté +majeure +majolica +major +majora +majorca +majorcan +majorcans +majordomo +majordomos +majored +majorette +majorettes +majoring +majoritarian +majoritarianism +majoritarians +majorities +majority +majorly +majors +majuscular +majuscule +majuscules +makable +makalu +makar +makars +makassar +make +makeable +makebate +makebates +makefast +makefasts +makeover +makeovers +maker +makereadies +makeready +makers +makes +makeshift +makeshifts +makeup +makeups +makeweight +makeweights +makimono +makimonos +making +makings +mako +makos +makuta +mal +malabar +malabo +malabsorption +malabsorptions +malacca +malaccas +malachi +malachias +malachite +malacological +malacologist +malacologists +malacology +malacostracan +malacostracans +maladaptation +maladaptations +maladapted +maladaptive +maladies +maladjusted +maladjustive +maladjustment +maladjustments +maladminister +maladministered +maladministering +maladministers +maladministration +maladministrations +maladroit +maladroitly +maladroitness +maladroits +malady +malaga +malagas +malagasies +malagasy +malagueña +malaise +malamute +malamutes +malapert +malapertly +malapertness +malaperts +malapportioned +malapportionment +malapportionments +malaprop +malapropian +malapropism +malapropisms +malapropist +malapropists +malapropos +malaprops +malar +malaria +malarial +malarian +malariologist +malariologists +malariology +malarious +malarkey +malarky +malars +malassimilation +malassimilations +malate +malates +malathion +malawi +malawian +malawians +malay +malaya +malayalam +malayalams +malayan +malayans +malays +malaysia +malaysian +malaysians +malcontent +malcontented +malcontentedly +malcontentedness +malcontents +maldistribution +maldistributions +maldivan +maldivans +maldive +maldives +maldivian +maldivians +male +maleate +maleates +malebranche +malecite +malecites +maledict +maledicted +maledicting +malediction +maledictions +maledictory +maledicts +malefaction +malefactions +malefactor +malefactors +malefic +maleficence +maleficent +maleic +malemute +malemutes +maleness +malentendu +malentendus +males +malevolence +malevolent +malevolently +malfeasance +malfeasant +malfeasants +malfi +malformation +malformations +malformed +malfunction +malfunctioned +malfunctioning +malfunctions +malgre +mali +malian +malians +malic +malice +malicious +maliciously +maliciousness +malign +malignance +malignancies +malignancy +malignant +malignantly +maligned +maligner +maligners +maligning +malignities +malignity +malignly +maligns +malihini +malihinis +maline +malines +malinger +malingered +malingerer +malingerers +malingering +malingers +malinke +malinkes +malinois +maliseet +maliseets +malison +malisons +malkin +malkins +mall +mallard +mallards +malleability +malleable +malleableness +malleably +malled +mallee +mallees +mallei +mallemuck +mallemucks +mallet +mallets +malleus +malling +mallorca +mallow +mallows +malls +malmsey +malmseys +malnourish +malnourished +malnourishes +malnourishing +malnourishment +malnourishments +malnutrition +malo +malocclusion +malocclusions +malodor +malodorous +malodorously +malodorousness +malodors +malolactic +malonic +maloti +malpighian +malplaquet +malposition +malpositions +malpractice +malpractitioner +malpractitioners +malt +malta +maltase +malted +maltese +maltha +malthas +malthus +malthusian +malthusianism +malthusians +malting +maltose +maltreat +maltreated +maltreater +maltreaters +maltreating +maltreatment +maltreatments +maltreats +malts +maltster +maltsters +malty +malvasia +malvasias +malversation +malversations +malvinas +malvoisie +malvoisies +mama +mamas +mamba +mambas +mamberamo +mambo +mamboed +mamboing +mambos +mameluke +mamelukes +mamey +mameys +mamluk +mamluks +mamma +mammae +mammal +mammalian +mammalians +mammalogical +mammalogist +mammalogists +mammalogy +mammals +mammaplasties +mammaplasty +mammary +mammas +mammate +mammee +mammer +mammered +mammering +mammers +mammies +mammiferous +mammilla +mammillae +mammillary +mammillate +mammillated +mammillation +mammillations +mammock +mammocked +mammocking +mammocks +mammogram +mammograms +mammographic +mammographies +mammography +mammon +mammonism +mammonist +mammonists +mammoplasties +mammoplasty +mammoth +mammoths +mammy +mamoré +man +mana +manacle +manacled +manacles +manacling +manage +manageability +manageable +manageableness +manageably +managed +management +managemental +managements +manager +manageress +manageresses +managerial +managerially +managers +managership +managerships +manages +managing +managua +managuan +managuans +manakin +manakins +manama +manamah +manas +manasseh +manatee +manatees +manchester +manchineel +manchineels +manchu +manchuguo +manchukuo +manchuria +manchurian +manchurians +manchus +manciple +manciples +mancunian +mancunians +mandaean +mandaeans +mandala +mandalas +mandalay +mandalic +mandamus +mandamused +mandamuses +mandamusing +mandan +mandans +mandarin +mandarinate +mandarinates +mandarinic +mandarinism +mandarins +mandataries +mandatary +mandate +mandated +mandates +mandating +mandator +mandatories +mandatorily +mandators +mandatory +mande +mandean +mandeans +mandekan +mandekans +mandelbrot +mandes +mandible +mandibles +mandibular +mandibulate +mandibulates +mandingo +mandingoes +mandingos +mandinka +mandinkas +mandioca +mandola +mandolas +mandolin +mandoline +mandolines +mandolinist +mandolinists +mandolins +mandragora +mandragoras +mandrake +mandrakes +mandrel +mandrels +mandril +mandrill +mandrills +mandrils +mane +maned +manege +maneges +manes +manet +maneuver +maneuverability +maneuverable +maneuvered +maneuverer +maneuverers +maneuvering +maneuverings +maneuvers +manful +manfully +manfulness +mangabey +mangabeys +manganate +manganates +manganese +manganesian +manganic +manganite +manganites +manganous +mange +mangel +manger +mangers +mangier +mangiest +mangily +manginess +mangle +mangled +mangler +manglers +mangles +mangling +mango +mangoes +mangonel +mangonels +mangos +mangosteen +mangosteens +mangrove +mangroves +mangy +manhandle +manhandled +manhandles +manhandling +manhattan +manhattanite +manhattanites +manhattanization +manhattanizations +manhattanize +manhattanized +manhattanizes +manhattanizing +manhattans +manhole +manholes +manhood +manhunt +manhunts +mania +maniac +maniacal +maniacally +maniacs +manias +manic +manically +manichaean +manichaeanism +manichaeanisms +manichaeans +manichaeism +manichaeisms +manichean +manicheans +manichee +manichees +manicheism +manicotti +manics +manicure +manicured +manicures +manicuring +manicurist +manicurists +manifest +manifestant +manifestants +manifestation +manifestations +manifested +manifester +manifesters +manifesting +manifestly +manifesto +manifestoed +manifestoes +manifestoing +manifestos +manifests +manifold +manifolded +manifolding +manifoldly +manifoldness +manifolds +manikin +manikins +manila +manilas +manilla +manillas +manille +maninka +maninkas +manioc +manioca +maniocas +maniocs +maniple +maniples +manipulability +manipulable +manipular +manipulars +manipulatable +manipulate +manipulated +manipulates +manipulating +manipulation +manipulations +manipulative +manipulatively +manipulativeness +manipulator +manipulators +manipulatory +manipur +manito +manitoba +manitoban +manitobans +manitos +manitou +manitoulin +manitous +manitu +manitus +mankind +manless +manlier +manliest +manlike +manliness +manly +manmade +manna +mannan +mannans +mannar +manned +mannequin +mannequins +manner +mannered +mannerism +mannerisms +mannerist +manneristic +mannerists +mannerless +mannerliness +mannerly +manners +mannheim +mannikin +mannikins +manning +mannish +mannishly +mannishness +mannite +mannites +mannitol +mannitols +mannose +mannoses +mano +manometer +manometers +manometric +manometrical +manometrically +manometry +manor +manorial +manorialism +manors +manos +manpack +manpower +manqué +manrope +manropes +mans +mansard +mansarded +mansards +manse +manservant +manses +mansfield +mansion +mansions +manslaughter +manslayer +manslayers +mansuetude +mansuetudes +manta +mantas +manteau +manteaus +manteaux +mantegna +mantel +mantelet +mantelets +mantelletta +mantellettas +mantelpiece +mantelpieces +mantels +mantelshelf +mantelshelfs +manteltree +manteltrees +mantes +mantic +mantically +manticore +mantid +mantids +mantilla +mantillas +mantis +mantises +mantissa +mantissas +mantle +mantled +mantles +mantlet +mantlets +mantling +mantoux +mantova +mantra +mantrap +mantraps +mantras +mantric +mantua +mantuan +mantuans +mantuas +manu +manual +manually +manuals +manubria +manubrium +manufactories +manufactory +manufacturable +manufactural +manufacture +manufactured +manufacturer +manufacturers +manufactures +manufacturing +manumission +manumissions +manumit +manumits +manumitted +manumitter +manumitters +manumitting +manure +manured +manurer +manurers +manures +manurial +manuring +manus +manuscript +manuscripts +manward +manwards +manwise +manx +manxman +manxmen +manxwoman +manxwomen +many +manyfold +manyplies +manzanilla +manzanillas +manzanita +manzanitas +manzoni +manège +manèges +mao +maoism +maoist +maoists +maori +maoris +map +maple +maples +maplike +mapmaker +mapmakers +mapmaking +mappable +mapped +mapper +mappers +mapping +mappings +maps +maputo +maquette +maquettes +maqui +maquila +maquiladora +maquiladoras +maquilas +maquillage +maquillages +maquis +maquisard +maquisards +mar +mara +marabou +marabous +marabout +marabouts +maraca +maracaibo +maracas +maraging +marajó +maranta +marantas +maras +marasca +marascas +maraschino +maraschinos +marasmic +marasmus +marat +maratha +marathas +marathi +marathon +marathoner +marathoners +marathoning +marathons +marattas +maraud +marauded +marauder +marauders +marauding +marauds +marañón +marbella +marble +marbled +marbleize +marbleized +marbleizes +marbleizing +marbles +marblewood +marblewoods +marbling +marbly +marburg +marc +marcasite +marcasites +marcasitical +marcato +marcatos +marcel +marcelled +marcelling +marcels +marcescent +march +marchand +marche +marched +marchen +marcher +marchers +marches +marchesa +marchese +marchesi +marching +marchioness +marchionesses +marchland +marchlands +marchlike +marchpane +marchpanes +marcionism +marcionite +marcionites +marconi +marcs +mardi +marduk +mare +marek +marengo +mares +marfan +margarine +margarines +margarita +margaritas +margarite +margarites +margay +marge +margent +margents +margin +marginal +marginalia +marginality +marginalization +marginalizations +marginalize +marginalized +marginalizes +marginalizing +marginally +marginate +marginated +marginates +marginating +margination +marginations +margined +margining +margins +margravate +margravates +margrave +margraves +margravial +margraviate +margraviates +margravine +margravines +marguerite +marguerites +maria +mariachi +mariachis +marian +mariana +marianas +marianist +marianists +maricopa +maricopas +maricultural +mariculture +maricultures +mariculturist +mariculturists +marie +marienberg +marienbourg +marienburg +marigold +marigolds +marihuana +marijuana +marimba +marimbas +marimbist +marimbists +marina +marinade +marinaded +marinades +marinading +marinara +marinaras +marinas +marinate +marinated +marinates +marinating +marination +marinations +marine +mariner +mariners +marines +marino +mariolater +mariolaters +mariolatrous +mariolatry +mariological +mariology +marionette +marionettes +mariposa +marish +marishes +marist +marists +marital +maritally +maritime +mariánské +marjoram +mark +markdown +markdowns +marked +markedly +markedness +marker +markers +market +marketability +marketable +marketed +marketeer +marketeering +marketeers +marketer +marketers +marketing +marketings +marketplace +marketplaces +markets +marketwise +markham +markhor +markhors +marking +markings +markka +markkaa +markkas +markoff +markov +markovian +marks +marksman +marksmanship +marksmen +markswoman +markswomen +markup +markups +marl +marled +marlin +marline +marlines +marlinespike +marlinespikes +marling +marlingspike +marlingspikes +marlins +marlinspike +marlinspikes +marlite +marlites +marlitic +marls +marlstone +marlstones +marly +marmalade +marmalades +marmara +marmite +marmites +marmolada +marmoreal +marmoreally +marmorean +marmoset +marmosets +marmot +marmots +marne +marocain +marocains +maronite +maronites +maroon +marooned +marooning +maroons +marplot +marplots +marque +marquee +marquees +marques +marquesan +marquesans +marquess +marquessate +marquessates +marquesses +marqueterie +marqueteries +marquetries +marquetry +marquette +marquis +marquisate +marquisates +marquise +marquises +marquisette +marquisettes +marrakech +marrakesh +marram +marrams +marrano +marranos +marred +marriage +marriageability +marriageable +marriageableness +marriages +married +marrieds +marries +marring +marron +marrons +marrow +marrowbone +marrowbones +marrowfat +marrowfats +marrowy +marry +marrying +mars +marsala +marsalas +marse +marseillaise +marseille +marseilles +marsh +marshal +marshalcy +marshaled +marshaling +marshall +marshalled +marshalling +marshals +marshalship +marshalships +marshes +marshier +marshiest +marshiness +marshland +marshlands +marshmallow +marshmallows +marshmallowy +marshy +marston +marsupia +marsupial +marsupials +marsupium +mart +martaban +martagon +martagons +marted +martel +martello +marten +martens +martensite +martensites +martensitic +martensitically +martha +martial +martialed +martialing +martialism +martialist +martialists +martialled +martialling +martially +martials +martian +martians +martin +martinet +martinets +marting +martingal +martingale +martingales +martingals +martini +martinique +martinis +martinmas +martinmases +martins +martlet +martlets +marts +martyr +martyrdom +martyred +martyries +martyring +martyrization +martyrizations +martyrize +martyrized +martyrizes +martyrizing +martyrologies +martyrologist +martyrologists +martyrology +martyrs +martyry +martí +marvel +marveled +marveling +marvelled +marvelling +marvellous +marvelous +marvelously +marvelousness +marvels +marx +marxian +marxianism +marxians +marxism +marxist +marxists +mary +maryknoller +maryknollers +maryland +marylander +marylanders +maryology +marys +marzipan +mas +masaccio +masachusetts +masada +masai +masais +masala +masalas +masbate +mascara +mascaraed +mascaraing +mascaras +mascarpone +mascarpones +mascon +mascons +mascot +mascots +masculine +masculinely +masculineness +masculines +masculinities +masculinity +masculinization +masculinizations +masculinize +masculinized +masculinizes +masculinizing +masefield +maser +masers +maseru +mash +mashed +masher +masherbrum +mashers +mashes +mashgiach +mashgiah +mashgichim +mashgihim +mashie +mashies +mashing +mashy +masjid +masjids +mask +maskable +masked +maskeg +maskegs +masker +maskers +masking +maskings +maskinonge +maskinonges +masklike +masks +masochism +masochist +masochistic +masochistically +masochists +mason +masoned +masonic +masoning +masonite +masonries +masonry +masons +masora +masorah +masorahs +masoras +masorete +masoretes +masoretic +masque +masquer +masquerade +masqueraded +masquerader +masqueraders +masquerades +masquerading +masquers +masques +mass +massachuset +massachusets +massachusett +massachusetts +massacre +massacred +massacrer +massacrers +massacres +massacring +massage +massaged +massager +massagers +massages +massaging +massasauga +massasaugas +masscult +masscults +masse +massed +massena +masses +masseter +masseteric +masseters +masseur +masseurs +masseuse +masseuses +massicot +massicots +massier +massiest +massif +massifs +massing +massinger +massive +massively +massiveness +massless +massorete +massoretes +massy +massé +mast +mastaba +mastabah +mastabahs +mastabas +mastectomies +mastectomy +masted +master +masterdom +mastered +masterful +masterfully +masterfulness +masteries +mastering +masterliness +masterly +mastermind +masterminded +masterminding +masterminds +masterpiece +masterpieces +masters +mastership +masterships +mastersinger +mastersingers +masterstroke +masterstrokes +masterwork +masterworks +mastery +masthead +mastheads +mastic +masticate +masticated +masticates +masticating +mastication +mastications +masticator +masticatories +masticators +masticatory +mastics +mastiff +mastiffs +mastigophoran +mastigophorans +mastitic +mastitis +mastodon +mastodonic +mastodons +mastodont +mastoid +mastoidectomies +mastoidectomy +mastoiditis +mastoids +masts +masturbate +masturbated +masturbates +masturbating +masturbation +masturbational +masturbator +masturbators +masturbatory +masuria +masurian +mat +matabele +matabeleland +matabeles +matador +matadors +matagorda +matapan +match +matchability +matchable +matchboard +matchboards +matchbook +matchbooks +matchbox +matchboxes +matched +matcher +matchers +matches +matching +matchless +matchlessly +matchlessness +matchlock +matchlocks +matchmaker +matchmakers +matchmaking +matchstick +matchsticks +matchup +matchups +matchwood +matchwoods +mate +mated +matelot +matelote +matelotes +matelots +matelotte +matelottes +mater +materfamilias +materfamiliases +materia +material +materialism +materialist +materialistic +materialistically +materialists +materialities +materiality +materialization +materializations +materialize +materialized +materializer +materializers +materializes +materializing +materially +materialness +materials +materiel +maternal +maternalism +maternally +maternities +maternity +maters +mates +matey +mateyness +math +mathematic +mathematical +mathematically +mathematician +mathematicians +mathematics +mathematization +mathematizations +mathematize +mathematized +mathematizes +mathematizing +maths +matilda +matilija +matin +matinal +matinee +matinees +mating +matins +matinée +matinées +matisse +matjes +matriarch +matriarchal +matriarchalism +matriarchate +matriarchates +matriarchic +matriarchies +matriarchs +matriarchy +matrices +matricidal +matricide +matricides +matriclinous +matriculant +matriculants +matriculate +matriculated +matriculates +matriculating +matriculation +matriculations +matrilineage +matrilineages +matrilineal +matrilineally +matrilocal +matrilocally +matrimonial +matrimonially +matrimonies +matrimony +matrix +matrixes +matron +matronal +matronliness +matronly +matrons +matronymic +matronymics +mats +matsu +matte +matted +matter +mattered +matterhorn +mattering +matters +mattery +mattes +matthaean +matthean +matthew +matthias +matting +mattings +mattock +mattocks +mattress +mattresses +maturate +maturated +maturates +maturating +maturation +maturational +maturations +maturative +mature +matured +maturely +matureness +maturer +matures +maturest +maturing +maturities +maturity +matutinal +matutinally +matzo +matzoh +matzohs +matzos +matzot +matzoth +maté +matériel +mau +maud +maudlin +maudlinly +maudlinness +maued +maugham +maugre +maui +mauing +maul +mauled +mauler +maulers +mauling +mauls +maulstick +maulsticks +maund +maunder +maundered +maunderer +maunderers +maundering +maunders +maunds +maundy +maupassant +mauretania +mauretanian +mauretanians +maurice +mauritania +mauritanian +mauritanians +mauritian +mauritians +mauritius +mauser +mausolea +mausolean +mausoleum +mausoleums +mauve +mauves +maven +mavens +maverick +mavericks +mavin +mavins +mavis +mavises +mavourneen +mavourneens +mavournin +mavournins +maw +mawkish +mawkishly +mawkishness +maws +max +maxed +maxes +maxi +maxilla +maxillae +maxillaries +maxillary +maxillas +maxilliped +maxillipeds +maxillofacial +maxim +maxima +maximal +maximalist +maximalists +maximally +maximals +maximi +maximilian +maximin +maximization +maximizations +maximize +maximized +maximizer +maximizers +maximizes +maximizing +maxims +maximum +maximums +maximus +maxing +maxis +maxixe +maxixes +maxwell +may +maya +mayagüez +mayan +mayanist +mayanists +mayans +mayapple +mayapples +mayas +maybe +maybes +mayday +maydays +mayest +mayflies +mayflower +mayflowers +mayfly +mayhap +mayhem +mayhems +maying +mayings +maymyo +mayn +mayn't +mayo +mayon +mayonnaise +mayor +mayoral +mayoralties +mayoralty +mayoress +mayoresses +mayors +mayorship +mayorships +mayos +mayotte +maypole +maypoles +maypop +maypops +mays +mayst +maytime +mayweed +mayweeds +mazaedia +mazaedium +mazal +mazard +mazards +mazatlán +mazda +mazdaism +mazdeism +maze +mazed +mazel +mazelike +mazer +mazers +mazes +mazier +maziest +mazily +maziness +mazing +mazourka +mazourkas +mazuma +mazumas +mazurka +mazurkas +mazy +mazzard +mazzards +maître +mañana +mbabane +mbira +mbiras +mbundu +mbundus +mccarthyism +mccarthyist +mccarthyists +mccarthyite +mccarthyites +mcclure +mccoy +mccoys +mcintosh +mcintoshes +mckinley +mdewakanton +mdewakantons +me +mea +mead +meadow +meadowfoam +meadowland +meadowlands +meadowlark +meadowlarks +meadows +meadowsweet +meadowsweets +meadowy +meager +meagerly +meagerness +meagre +meal +mealie +mealier +mealies +mealiest +mealiness +meals +mealtime +mealtimes +mealworm +mealworms +mealy +mealybug +mealybugs +mealymouthed +mean +meander +meandered +meanderer +meanderers +meandering +meanderingly +meanders +meandrous +meaner +meanest +meanie +meanies +meaning +meaningful +meaningfully +meaningfulness +meaningless +meaninglessly +meaninglessness +meaningly +meanings +meanly +meanness +means +meant +meantime +meanwhile +meany +measle +measles +measlier +measliest +measly +measurability +measurable +measurably +measure +measured +measuredly +measuredness +measureless +measurelessly +measurelessness +measurement +measurements +measurer +measurers +measures +measuring +meat +meatball +meatballs +meated +meathead +meatheads +meatier +meatiest +meatiness +meatless +meatloaf +meatloaves +meatpacker +meatpackers +meatpacking +meatpackings +meats +meatus +meatuses +meaty +mecamylamine +mecamylamines +mecca +meccas +mechanic +mechanical +mechanically +mechanicalness +mechanicals +mechanician +mechanicians +mechanics +mechanism +mechanisms +mechanist +mechanistic +mechanistically +mechanists +mechanizable +mechanization +mechanizations +mechanize +mechanized +mechanizer +mechanizers +mechanizes +mechanizing +mechanochemical +mechanochemistry +mechanoreception +mechanoreceptions +mechanoreceptive +mechanoreceptor +mechanoreceptors +mechanotherapies +mechanotherapist +mechanotherapists +mechanotherapy +mechlin +mechlins +mecklenburg +meclizine +meclizines +meconium +meconiums +mecopteran +mecopterans +mecopterous +mecum +mecums +med +medaillon +medaillons +medaka +medakas +medal +medaled +medaling +medalist +medalists +medalled +medallic +medalling +medallion +medallions +medallist +medallists +medals +meddle +meddled +meddler +meddlers +meddles +meddlesome +meddlesomely +meddlesomeness +meddling +mede +medea +medellín +medes +medevac +medevaced +medevacing +medevacs +medflies +medfly +media +mediacy +mediad +mediae +mediaeval +mediaevalism +mediaevalisms +mediaevalist +mediaevalists +mediagenic +medial +medially +medials +median +medianly +medians +mediant +mediants +medias +mediastina +mediastinal +mediastinum +mediate +mediated +mediately +mediates +mediating +mediation +mediational +mediations +mediative +mediatization +mediatizations +mediatize +mediatized +mediatizes +mediatizing +mediator +mediators +mediatory +mediatrix +medic +medica +medicable +medicaid +medical +medically +medicals +medicament +medicamentous +medicaments +medicare +medicate +medicated +medicates +medicating +medication +medications +medicative +medicatrix +medicean +medici +medicinable +medicinal +medicinally +medicine +medicines +medick +medicks +medico +medicolegal +medicos +medics +medieval +medievalism +medievalisms +medievalist +medievalists +medievally +medina +medinas +mediocre +mediocrities +mediocritization +mediocritizations +mediocritize +mediocritized +mediocritizes +mediocritizing +mediocrity +meditate +meditated +meditates +meditating +meditation +meditational +meditations +meditative +meditatively +meditativeness +meditator +meditators +mediterranean +mediterraneans +medium +mediumistic +mediums +mediumship +medlar +medlars +medley +medleys +medoc +medocs +medulla +medullae +medullar +medullary +medullas +medullated +medullization +medullizations +medulloblastoma +medulloblastomas +medulloblastomata +medusa +medusae +medusan +medusans +medusas +medusoid +medusoids +meed +meeds +meek +meeker +meekest +meekly +meekness +meemies +meerkat +meerkats +meerschaum +meerschaums +meet +meeter +meeters +meeting +meetinghouse +meetinghouses +meetings +meetly +meets +mefenamic +megaampere +megaamperes +megabar +megabars +megabecquerel +megabecquerels +megabit +megabits +megabuck +megabucks +megabyte +megabytes +megacandela +megacandelas +megacephalic +megacephalies +megacephalous +megacephaly +megacities +megacity +megacorporation +megacorporations +megacoulomb +megacoulombs +megacycle +megacycles +megadeal +megadeals +megadeath +megadeaths +megadose +megadoses +megaera +megafarad +megafarads +megafauna +megafaunal +megaflop +megaflops +megagamete +megagametes +megagametophyte +megagametophytes +megagram +megagrams +megahenries +megahenry +megahenrys +megahertz +megahit +megahits +megajoule +megajoules +megakaryocyte +megakaryocytes +megakaryocytic +megakelvin +megakelvins +megalith +megalithic +megaliths +megaloblast +megaloblastic +megaloblasts +megalocardia +megalocardias +megalocephalic +megalocephalies +megalocephalous +megalocephaly +megalomania +megalomaniac +megalomaniacal +megalomaniacally +megalomaniacs +megalomanic +megalopolis +megalopolises +megalopolistic +megalopolitan +megalosaur +megalosaurian +megalosaurians +megalosaurs +megalumen +megalumens +megalux +megameter +megameters +megamole +megamoles +meganewton +meganewtons +megaohm +megaohms +megaparsec +megaparsecs +megapascal +megapascals +megaphone +megaphoned +megaphones +megaphonic +megaphonically +megaphoning +megapode +megapodes +megapolis +megaproject +megaprojects +megara +megaradian +megaradians +megarian +megarians +megaric +megarics +megaron +megarons +megascopic +megascopically +megasecond +megaseconds +megasiemens +megasievert +megasieverts +megasporangia +megasporangium +megaspore +megaspores +megasporic +megasporocyte +megasporocytes +megasporogeneses +megasporogenesis +megasporophyll +megasporophylls +megastar +megastars +megasteradian +megasteradians +megastructure +megastructures +megatesla +megateslas +megathere +megatheres +megatherian +megaton +megatonnage +megatons +megavitamin +megavitamins +megavolt +megavoltage +megavoltages +megavolts +megawatt +megawattage +megawattages +megawatts +megaweber +megawebers +meghalaya +megillah +megillahs +megilp +megilps +megohm +megohms +megrez +megrim +megrims +meiji +mein +meioses +meiosis +meiotic +meiotically +meissen +meissens +meistersinger +meistersingers +meitnerium +mekong +melamine +melancholia +melancholiac +melancholiacs +melancholic +melancholically +melancholics +melancholily +melancholiness +melancholy +melanchthon +melanesia +melanesian +melanesians +melange +melanges +melanic +melanin +melanism +melanistic +melanite +melanites +melanitic +melanization +melanizations +melanize +melanized +melanizes +melanizing +melanoblast +melanoblastic +melanoblasts +melanocyte +melanocytes +melanogenesis +melanoid +melanoids +melanoma +melanomas +melanomata +melanophore +melanophores +melanoses +melanosis +melanosity +melanosome +melanosomes +melanotic +melanous +melaphyre +melaphyres +melatonin +melatonins +melba +melbourne +melchior +melchite +melchites +melchizedek +melchizedeks +meld +melded +melding +melds +melee +melees +melena +melenas +melic +melilot +melilots +meliorable +meliorate +meliorated +meliorates +meliorating +melioration +meliorations +meliorative +melioratives +meliorator +meliorators +meliorism +meliorist +melioristic +meliorists +melisma +melismas +melismata +melismatic +melkite +melkites +mell +melled +melliferous +mellific +mellifluence +mellifluent +mellifluently +mellifluous +mellifluously +mellifluousness +melling +mellitus +mellophone +mellophones +mellotron +mellotrons +mellow +mellowed +mellower +mellowest +mellowing +mellowly +mellowness +mellows +mells +melodeon +melodeons +melodic +melodically +melodies +melodious +melodiously +melodiousness +melodist +melodists +melodize +melodized +melodizer +melodizers +melodizes +melodizing +melodrama +melodramas +melodramatic +melodramatically +melodramatics +melodramatist +melodramatists +melodramatization +melodramatizations +melodramatize +melodramatized +melodramatizes +melodramatizing +melody +meloid +meloids +melon +melongene +melongenes +melons +melos +melphalan +melphalans +melpomene +melt +meltability +meltable +meltage +meltages +meltdown +meltdowns +melted +melter +melters +melting +meltingly +melton +meltons +melts +meltwater +melty +melville +mem +member +membered +members +membership +memberships +membranal +membrane +membraned +membranes +membranous +membranously +memento +mementoes +mementos +memnon +memo +memoir +memoire +memoirist +memoirists +memoirs +memorabilia +memorability +memorable +memorableness +memorably +memoranda +memorandum +memorandums +memorial +memorialist +memorialists +memorialization +memorializations +memorialize +memorialized +memorializer +memorializers +memorializes +memorializing +memorially +memorials +memoriam +memories +memoriter +memorizable +memorization +memorizations +memorize +memorized +memorizer +memorizers +memorizes +memorizing +memory +memos +memphis +memsahib +memsahibs +men +menace +menaced +menacer +menacers +menaces +menacing +menacingly +menad +menadione +menadiones +menads +menage +menagerie +menageries +menages +menander +menarche +menarcheal +menazon +menazons +mencken +menckenian +mend +mendable +mendacious +mendaciously +mendaciousness +mendacities +mendacity +mende +mended +mendel +mendeleev +mendelevium +mendelian +mendelianism +mendelianisms +mendelians +mendelism +mendelisms +mendelist +mendelists +mendelssohn +mender +menders +mendes +mendicancy +mendicant +mendicants +mendicity +mending +mendings +mends +meneer +meneers +menelaus +menenius +menfolk +menfolks +menhaden +menhadens +menhir +menhirs +menial +menially +menials +meniere +meningeal +meninges +meningioma +meningiomas +meningiomata +meningitic +meningitides +meningitis +meningococcal +meningococci +meningococcic +meningococcus +meningoencephalitic +meningoencephalitis +meninx +meniscal +meniscate +meniscectomy +menisci +meniscoid +meniscoidal +meniscus +meniscuses +mennonite +mennonites +meno +menology +menominee +menominees +menopausal +menopause +menorah +menorahs +menorca +menorrhagia +menorrhagias +menorrhagic +mens +mensa +mensal +mensch +menschen +mensches +mensem +menservants +menses +mensh +menshevik +mensheviki +mensheviks +menshevism +menshevist +menshevists +menstrua +menstrual +menstruate +menstruated +menstruates +menstruating +menstruation +menstruous +menstruum +menstruums +mensurability +mensurable +mensurableness +mensural +mensuration +mensurations +mensurative +menswear +menta +mental +mentalism +mentalisms +mentalist +mentalistic +mentalists +mentalities +mentality +mentally +mentation +mentations +menthe +menthol +mentholated +menthols +mention +mentionable +mentioned +mentioner +mentioners +mentioning +mentions +mentis +mentor +mentored +mentoring +mentors +mentorship +mentorships +mentum +menu +menuhin +menus +meo +meos +meow +meowed +meowing +meows +meperidine +meperidines +mephistophelean +mephistopheles +mephistophelian +mephitic +mephitical +mephitically +mephitis +mephitises +meprobamate +meprobamates +mer +meramec +merbromin +merbromins +mercalli +mercantile +mercantilism +mercantilist +mercantilistic +mercantilists +mercaptan +mercaptans +mercaptopurine +mercaptopurines +mercator +mercedario +mercedes +mercenaries +mercenarily +mercenariness +mercenary +mercer +merceries +mercerization +mercerizations +mercerize +mercerized +mercerizes +mercerizing +mercers +mercery +merchandisable +merchandise +merchandised +merchandiser +merchandisers +merchandises +merchandising +merchandisings +merchandize +merchandized +merchandizes +merchandizing +merchandizings +merchant +merchantability +merchantable +merchantman +merchantmen +merchants +mercia +mercian +mercians +mercies +merciful +mercifully +mercifulness +merciless +mercilessly +mercilessness +mercurate +mercurated +mercurates +mercurating +mercuration +mercurations +mercurial +mercurialism +mercurialisms +mercurially +mercurialness +mercurials +mercuric +mercurochrome +mercurous +mercury +mercutio +mercy +merde +mere +meredith +merely +merengue +merengues +merest +meretricious +meretriciously +meretriciousness +merganser +mergansers +merge +merged +mergence +merger +mergers +merges +merging +meridian +meridians +meridiem +meridional +meridionally +meridionals +meringue +meringues +merino +merinos +meristem +meristematic +meristematically +meristems +meristic +meristically +merit +merited +meriting +meritless +meritocracies +meritocracy +meritocrat +meritocratic +meritocrats +meritorious +meritoriously +meritoriousness +merits +merl +merle +merles +merlin +merlins +merlon +merlons +merlot +merlots +merls +mermaid +mermaids +merman +mermen +meroblastic +meroblastically +merocrine +meromorphic +meromyosin +meromyosins +merope +meropia +meropic +meroplankton +meroplanktonic +meroplanktons +merovingian +merovingians +merowe +merozoite +merozoites +meroë +merrier +merriest +merrily +merrimack +merriment +merriness +merry +merrymaker +merrymakers +merrymaking +merrythought +merrythoughts +merseyside +merthiolate +mesa +mesabi +mesarch +mesas +mescal +mescalero +mescaleros +mescaline +mescals +mesdames +mesdemoiselles +meseemed +meseems +mesembryanthemum +mesembryanthemums +mesencephalic +mesencephalon +mesenchymal +mesenchymatous +mesenchyme +mesenchymes +mesenteric +mesenteries +mesenteritis +mesenteritises +mesenteron +mesenteronic +mesenterons +mesentery +mesh +meshach +meshed +meshes +meshing +meshuga +meshugaas +meshugah +meshugga +meshuggah +meshugge +meshuggener +meshuggeners +meshwork +meshy +mesial +mesially +mesic +mesityl +mesitylene +mesitylenes +mesmer +mesmeric +mesmerically +mesmerism +mesmerist +mesmerists +mesmerization +mesmerizations +mesmerize +mesmerized +mesmerizer +mesmerizers +mesmerizes +mesmerizing +mesne +mesoamerica +mesoamerican +mesoamericans +mesoblast +mesoblastic +mesoblasts +mesocarp +mesocarps +mesocephalic +mesocephally +mesocyclone +mesocyclones +mesoderm +mesodermal +mesodermic +mesogastria +mesogastric +mesogastrium +mesoglea +mesogleal +mesogloea +mesolithic +mesomere +mesomeres +mesomorph +mesomorphic +mesomorphism +mesomorphous +mesomorphs +mesomorphy +meson +mesonephric +mesonephros +mesonephroses +mesonic +mesons +mesopause +mesopauses +mesopelagic +mesophyll +mesophyllic +mesophyllous +mesophylls +mesophyte +mesophytes +mesophytic +mesopotamia +mesopotamian +mesopotamians +mesoscale +mesosome +mesosomes +mesosphere +mesospheric +mesothelia +mesothelial +mesothelioma +mesotheliomas +mesotheliomata +mesothelium +mesothoraces +mesothoracic +mesothorax +mesothoraxes +mesothorium +mesothoriums +mesotrophic +mesozoic +mesquite +mesquites +mess +message +messaged +messages +messaging +messaline +messalines +messed +messeigneurs +messenger +messengered +messengering +messengers +messenia +messenian +messenians +messes +messiah +messiahs +messiahship +messianic +messianism +messianisms +messianist +messianists +messias +messier +messiest +messieurs +messily +messina +messiness +messing +messmate +messmates +messrs +messuage +messuages +messy +mestiza +mestizas +mestizo +mestizoes +mestizos +mestranol +mestranols +met +metabolic +metabolically +metabolism +metabolisms +metabolite +metabolites +metabolizable +metabolize +metabolized +metabolizes +metabolizing +metacarpal +metacarpally +metacarpals +metacarpi +metacarpus +metacenter +metacenters +metacentric +metacentricity +metacentrics +metacercaria +metacercarial +metacercarias +metachromatic +metachromatism +metachromatisms +metaethical +metaethics +metafiction +metafictional +metafictionist +metafictionists +metafictions +metagalactic +metagalaxies +metagalaxy +metagenesis +metagenetic +metagnathism +metagnathous +metal +metalanguage +metalanguages +metaled +metaling +metalinguistic +metalinguistics +metalize +metalized +metalizes +metalizing +metalled +metallic +metallically +metallics +metalliferous +metalline +metalling +metallization +metallizations +metallize +metallized +metallizes +metallizing +metallographer +metallographers +metallographic +metallographically +metallography +metalloid +metalloidal +metalloids +metallophone +metallophones +metallurgic +metallurgical +metallurgically +metallurgist +metallurgists +metallurgy +metalmark +metalmarks +metals +metalsmith +metalsmiths +metalware +metalwork +metalworker +metalworkers +metalworking +metamathematical +metamathematician +metamathematicians +metamathematics +metamere +metameres +metameric +metamerically +metamerism +metamerisms +metamorphic +metamorphically +metamorphism +metamorphose +metamorphosed +metamorphoses +metamorphosing +metamorphosis +metamorphous +metanalyses +metanalysis +metanephric +metanephros +metanephroses +metaphase +metaphases +metaphor +metaphoric +metaphorical +metaphorically +metaphors +metaphosphate +metaphosphates +metaphosphoric +metaphrase +metaphrased +metaphrases +metaphrasing +metaphrast +metaphrastic +metaphrasts +metaphysic +metaphysical +metaphysically +metaphysician +metaphysicians +metaphysics +metaplasia +metaplasias +metaplasm +metaplasmic +metaplasms +metaplastic +metapontum +metaprotein +metaproteins +metapsychological +metapsychology +metasequoia +metasilicate +metasomatic +metasomatically +metasomatism +metasomatosis +metastability +metastable +metastably +metastases +metastasis +metastasize +metastasized +metastasizes +metastasizing +metastatic +metastatically +metatarsal +metatarsally +metatarsals +metatarsi +metatarsus +metate +metates +metatheses +metathesis +metathesize +metathesized +metathesizes +metathesizing +metathetic +metathetical +metathetically +metathoraces +metathoracic +metathorax +metathoraxes +metaxylem +metaxylems +metazoal +metazoan +metazoans +metazoic +mete +meted +metempsychoses +metempsychosis +metencephala +metencephalic +metencephalon +meteor +meteoric +meteorically +meteorite +meteorites +meteoritic +meteoritical +meteoriticist +meteoriticists +meteoritics +meteorograph +meteorographs +meteoroid +meteoroidal +meteoroids +meteorologic +meteorological +meteorologically +meteorologist +meteorologists +meteorology +meteors +meter +metered +metering +meters +meterstick +metersticks +metes +metestrous +metestrus +metestruses +meth +methacrylate +methacrylates +methacrylic +methadon +methadone +methamphetamine +methamphetamines +methanation +methanations +methane +methanol +methaqualone +methaqualones +methedrine +metheglin +metheglins +methemoglobin +methemoglobinemia +methemoglobins +methenamine +methenamines +methicillin +methicillins +methinks +methionine +methionines +method +methodic +methodical +methodically +methodicalness +methodism +methodist +methodistic +methodistical +methodists +methodization +methodizations +methodize +methodized +methodizer +methodizers +methodizes +methodizing +methodological +methodologically +methodologies +methodologist +methodologists +methodology +methods +methotrexate +methotrexates +methought +methoxychlor +methoxychlors +methoxyflurane +methuen +methuselah +methyl +methylal +methylals +methylamine +methylamines +methylase +methylases +methylate +methylated +methylates +methylating +methylation +methylations +methylator +methylators +methylbenzene +methylbenzenes +methylcellulose +methylcelluloses +methylcholanthrene +methyldopa +methyldopas +methylene +methylenes +methylic +methylmercury +methylnaphthalene +methylnaphthalenes +methylphenidate +methylphenidates +methylprednisolone +methylxanthine +methylxanthines +methysergide +methysergides +meticais +metical +meticals +meticulosity +meticulous +meticulously +meticulousness +metier +metiers +meting +metis +metonic +metonym +metonymic +metonymical +metonymically +metonymies +metonyms +metonymy +metoo +metope +metopes +metopic +metopon +metopons +metralgia +metralgias +metrazol +metric +metrical +metrically +metricate +metricated +metricates +metricating +metrication +metricize +metricized +metricizes +metricizing +metrics +metrification +metrifications +metrified +metrifies +metrify +metrifying +metrist +metrists +metritis +metritises +metro +metrological +metrologically +metrologies +metrologist +metrologists +metrology +metronidazole +metronidazoles +metronome +metronomes +metronomic +metronomical +metronomically +metronymic +metroplex +metroplexs +metropolis +metropolises +metropolitan +metropolitans +metrorrhagia +metrorrhagias +metrorrhagic +metros +metternich +mettle +mettled +mettles +mettlesome +metz +meunière +meursault +meuse +mew +mewed +mewing +mewl +mewled +mewling +mewls +mews +mex +mexicali +mexican +mexicans +mexico +meyerbeer +meze +mezereon +mezereons +mezereum +mezereums +mezes +mezuza +mezuzah +mezuzahs +mezuzas +mezuzot +mezza +mezzanine +mezzanines +mezzo +mezzos +mezzotint +mezzotints +mi +miami +miamis +miao +miaos +miaow +miasma +miasmal +miasmas +miasmata +miasmatic +miasmic +miasmically +mica +micaceous +micah +micas +micawber +micawberish +micawbers +miccosukee +miccosukees +mice +micellar +micelle +micelles +mich +michael +michaelis +michaelmas +michaelmases +micheas +michelangelo +michelin +michigan +michigander +michiganders +mick +mickey +mickeys +mickle +micks +micmac +micmacs +micra +micro +microampere +microamperes +microanalyses +microanalysis +microanalyst +microanalysts +microanalytic +microanalytical +microanatomical +microanatomy +microbalance +microbalances +microbar +microbarograph +microbarographs +microbars +microbe +microbeam +microbeams +microbecquerel +microbecquerels +microbes +microbial +microbic +microbiologic +microbiological +microbiologically +microbiologist +microbiologists +microbiology +microbrewer +microbreweries +microbrewers +microbrewery +microbrewing +microburst +microbursts +microbus +microbuses +microbusses +microcalorimeter +microcalorimeters +microcalorimetric +microcalorimetry +microcandela +microcandelas +microcapsule +microcapsules +microcassette +microcassettes +microcavity +microcephalic +microcephalics +microcephalies +microcephalous +microcephaly +microchemical +microchemist +microchemistries +microchemistry +microchemists +microchip +microchips +microcircuit +microcircuitry +microcircuits +microcirculation +microcirculations +microcirculatory +microclimate +microclimates +microclimatic +microclimatologic +microclimatological +microclimatology +microcline +microclines +micrococcal +micrococci +micrococcus +microcode +microcomputer +microcomputers +microcopied +microcopies +microcopy +microcopying +microcosm +microcosmic +microcosmical +microcosmically +microcosmos +microcosms +microcoulomb +microcoulombs +microcrystal +microcrystalline +microcrystallinity +microcrystals +microcultural +microculture +microcultures +microcurie +microcuries +microcyte +microcytes +microcytic +microdensitometer +microdensitometers +microdensitometric +microdensitometry +microdissection +microdissections +microdot +microdots +microearthquake +microearthquakes +microeconomic +microeconomics +microelectrode +microelectrodes +microelectromechanical +microelectronic +microelectronically +microelectronics +microelectrophoresis +microelectrophoretic +microelectrophoretically +microelement +microelements +microencapsulate +microencapsulated +microencapsulates +microencapsulating +microencapsulation +microencapsulations +microenvironment +microenvironmental +microenvironments +microevolution +microevolutionary +microevolutions +microfabrication +microfarad +microfarads +microfauna +microfaunal +microfibril +microfibrillar +microfibrils +microfiche +microfiches +microfilament +microfilamentous +microfilaments +microfilaria +microfilariae +microfilarial +microfilm +microfilmable +microfilmed +microfilmer +microfilmers +microfilming +microfilms +microfloppies +microfloppy +microflora +microfloral +microform +microforms +microfossil +microfossils +microfungi +microfungus +microfunguses +microgamete +microgametes +microgametocyte +microgametocytes +microgram +micrograms +micrograph +micrographic +micrographically +micrographics +micrographs +micrography +microgravity +microgroove +microgrooves +microhabitat +microhabitats +microhenries +microhenry +microhenrys +microhertz +microimage +microimages +microinch +microinches +microinject +microinjected +microinjecting +microinjection +microinjections +microinjects +microinstruction +microinstructions +microjet +microjets +microjoule +microjoules +microkelvin +microkelvins +microlepidoptera +microlepidopterous +microliter +microliters +microlith +microlithic +microlithography +microliths +microlumen +microlumens +microlux +micromachining +micromanage +micromanaged +micromanagement +micromanager +micromanagers +micromanages +micromanaging +micromanipulation +micromanipulations +micromanipulative +micromanipulator +micromanipulators +micromere +micromeres +micrometeorite +micrometeorites +micrometeoritic +micrometeoroid +micrometeoroids +micrometeorological +micrometeorologist +micrometeorologists +micrometeorology +micrometer +micrometers +micromethod +micromethods +micrometric +micrometrical +micrometrically +micrometry +micromini +microminiature +microminiaturization +microminiaturizations +microminiaturize +microminiaturized +microminiaturizes +microminiaturizing +microminis +micromolar +micromole +micromoles +micromorphological +micromorphology +micron +microneedle +microneedles +micronesia +micronesian +micronesians +micronewton +micronewtons +micronize +micronized +micronizes +micronizing +microns +micronuclear +micronuclei +micronucleus +micronucleuses +micronutrient +micronutrients +microohm +microohms +microorganism +microorganisms +micropaleontologic +micropaleontological +micropaleontologist +micropaleontologists +micropaleontology +microparticle +microparticles +micropascal +micropascals +microphage +microphages +microphagic +microphone +microphones +microphonic +microphonics +microphotograph +microphotographer +microphotographers +microphotographic +microphotographs +microphotography +microphotometer +microphotometers +microphotometric +microphotometrically +microphotometry +microphyll +microphyllous +microphylls +microphysical +microphysically +microphysicist +microphysicists +microphysics +microphyte +microphytes +microphytic +micropipet +micropipets +micropipette +micropipettes +microplankton +microplanktons +micropore +micropores +microporosity +microporous +microprint +microprints +microprism +microprisms +microprobe +microprobes +microprocessor +microprocessors +microprogram +microprogramming +microprogrammings +microprograms +microprojection +microprojections +microprojector +microprojectors +micropublisher +micropublishers +micropublishing +micropublishings +micropulsation +micropulsations +micropuncture +micropunctures +micropylar +micropyle +micropyles +microquake +microquakes +microradian +microradians +microradiograph +microradiographic +microradiographs +microradiography +microreader +microreaders +microreproduction +microreproductions +micros +microscale +microscales +microscope +microscopes +microscopic +microscopical +microscopically +microscopies +microscopist +microscopists +microscopium +microscopy +microsecond +microseconds +microseism +microseismic +microseismicity +microseisms +microsensor +microsensors +microsiemens +microsievert +microsieverts +microsoft +microsomal +microsome +microsomes +microsomic +microspectrophotometer +microspectrophotometers +microspectrophotometric +microspectrophotometry +microsphere +microspheres +microspherical +microsporangia +microsporangiate +microsporangium +microspore +microspores +microsporic +microsporocyte +microsporocytes +microsporogenesis +microsporophyll +microsporophylls +microsporous +microstate +microstates +microsteradian +microsteradians +microstructural +microstructure +microstructures +microsurgeries +microsurgery +microsurgical +microswitch +microswitches +microsystems +microteaching +microteachings +microtechnic +microtechnics +microtechnique +microtechniques +microtesla +microteslas +microtome +microtomes +microtomic +microtomies +microtomy +microtonal +microtonality +microtonally +microtone +microtones +microtubular +microtubule +microtubules +microvascular +microvasculature +microvasculatures +microvillar +microvilli +microvillous +microvillus +microvolt +microvolts +microwatt +microwatts +microwavable +microwave +microwaveable +microwaved +microwaves +microwaving +microweber +microwebers +microworld +microworlds +micturate +micturated +micturates +micturating +micturition +micturitions +mid +midair +midas +midbrain +midbrains +midcourse +midcult +midcults +midday +midden +middens +middies +middle +middlebrow +middlebrows +middled +middleman +middlemen +middlemost +middler +middlers +middles +middleton +middleweight +middleweights +middling +middlingly +middlings +middorsal +middy +mideast +mideasterner +mideasterners +midfield +midfielder +midfielders +midfields +midgard +midge +midges +midget +midgets +midgut +midguts +midi +midianite +midianites +midiron +midirons +midis +midland +midlander +midlanders +midlands +midlatitude +midlatitudes +midlevel +midlevels +midlife +midline +midlines +midlives +midlothian +midmonth +midmorning +midmost +midnight +midnightly +midpoint +midpoints +midrange +midranges +midrash +midrashic +midrashim +midrib +midribs +midriff +midriffs +midsagittal +midseason +midsection +midsections +midship +midshipman +midshipmen +midships +midsize +midsized +midsole +midsoles +midst +midstream +midsummer +midterm +midterms +midtown +midtowns +midway +midways +midweek +midweekly +midwest +midwestern +midwesterner +midwesterners +midwife +midwifed +midwifery +midwifes +midwifing +midwinter +midwinters +midwived +midwives +midwiving +midyear +midyears +mien +miens +mieux +miff +miffed +miffier +miffiest +miffiness +miffing +miffs +miffy +might +mightier +mightiest +mightily +mightiness +mightn't +mighty +mignon +mignonette +mignonettes +mignons +migraine +migraines +migrainous +migrant +migrants +migrate +migrated +migrates +migrating +migration +migrational +migrations +migrator +migrators +migratory +mihrab +mihrabs +mikado +mikados +mikasuki +mikasukis +mike +miked +mikes +miking +mikra +mikron +mikrons +mikvah +mikvos +mikvot +mikvoth +mil +miladies +milady +milage +milages +milah +milan +milanese +milano +milch +milchig +mild +milder +mildest +mildew +mildewed +mildewing +mildews +mildewy +mildly +mildness +mile +mileage +mileages +milepost +mileposts +miler +milers +miles +milesian +milesians +milestone +milestones +miletus +milfoil +milfoils +milia +miliaria +miliarial +miliarias +miliary +milieu +milieus +milieux +militance +militancy +militant +militantly +militantness +militants +militaria +militaries +militarily +militarism +militarist +militaristic +militaristically +militarists +militarization +militarizations +militarize +militarized +militarizes +militarizing +military +militate +militated +militates +militating +milites +militia +militiaman +militiamen +militias +milium +milk +milked +milker +milkers +milkfish +milkfishes +milkier +milkiest +milkiness +milking +milkmaid +milkmaids +milkman +milkmen +milks +milkshake +milkshakes +milksop +milksoppy +milksops +milkweed +milkweeds +milkwort +milkworts +milky +mill +millage +millages +millais +millboard +millboards +milldam +milldams +mille +milled +millefiori +millefleur +millefleurs +millenarian +millenarianism +millenarians +millenaries +millenary +millennia +millennial +millennialism +millennialist +millennialists +millennially +millennium +millenniums +millepede +millepedes +millepore +millepores +miller +millerite +millerites +millers +millesimal +millesimally +millesimals +millet +millets +millhouse +millhouses +milliammeter +milliammeters +milliampere +milliamperes +milliard +milliards +milliary +millibar +millibars +millibecquerel +millibecquerels +millicandela +millicandelas +millicoulomb +millicoulombs +millicurie +millicuries +millidegree +millidegrees +millieme +milliemes +millifarad +millifarads +milligal +milligals +milligram +milligrams +millihenries +millihenry +millihenrys +millihertz +millijoule +millijoules +millikelvin +millikelvins +millilambert +millilamberts +milliliter +milliliters +millilitre +millilitres +millilumen +millilumens +millilux +millime +millimeter +millimeters +millimetre +millimetres +millimicron +millimicrons +millimolar +millimole +millimoles +milline +milliner +millineries +milliners +millinery +millines +millinewton +millinewtons +milling +millings +milliohm +milliohms +million +millionaire +millionaires +millionairess +millionairesses +millionfold +millions +millionth +millionths +milliosmol +milliosmols +millipascal +millipascals +millipede +millipedes +milliradian +milliradians +millirem +millirems +milliroentgen +milliroentgens +millisecond +milliseconds +millisiemens +millisievert +millisieverts +millisteradian +millisteradians +millitesla +milliteslas +millivolt +millivoltmeter +millivoltmeters +millivolts +milliwatt +milliwatts +milliweber +milliwebers +millpond +millponds +millrace +millraces +millrun +millruns +mills +millstone +millstones +millstream +millstreams +millwork +millworks +millwright +millwrights +milo +milord +milos +milpa +milpas +milquetoast +milquetoasts +milquetoasty +milreis +milrinone +mils +milt +milted +milter +milters +miltiades +milting +milton +miltonian +miltonic +milts +milwaukee +mim +mimas +mimbres +mime +mimed +mimeo +mimeoed +mimeograph +mimeographed +mimeographing +mimeographs +mimeoing +mimeos +mimer +mimers +mimes +mimeses +mimesis +mimetic +mimetically +mimic +mimicked +mimicker +mimickers +mimicking +mimicries +mimicry +mimics +miming +mimosa +mimosas +min +mina +minable +minacious +minaciously +minaciousness +minacity +minae +minamata +minaret +minarets +minas +minatorial +minatorily +minatory +minaudière +minaudières +mince +minced +mincemeat +mincer +mincers +minces +minch +mincing +mincingly +mind +mindanao +mindblower +mindblowers +minded +mindedly +mindedness +minden +minder +minders +mindful +mindfully +mindfulness +minding +mindless +mindlessly +mindlessness +mindoro +minds +mindscape +mindscapes +mindset +mindsets +mine +mineable +mined +minefield +minefields +minelayer +minelayers +miner +mineral +mineralizable +mineralization +mineralizations +mineralize +mineralized +mineralizer +mineralizers +mineralizes +mineralizing +mineralocorticoid +mineralocorticoids +mineralogic +mineralogical +mineralogically +mineralogies +mineralogist +mineralogists +mineralogy +minerals +miners +minerva +mines +mineshaft +mineshafts +minestrone +minestrones +minesweeper +minesweepers +minesweeping +mineworker +mineworkers +ming +mingier +mingiest +mingle +mingled +mingler +minglers +mingles +mingling +mingy +minho +mini +miniature +miniatures +miniaturist +miniaturistic +miniaturists +miniaturization +miniaturizations +miniaturize +miniaturized +miniaturizes +miniaturizing +minibar +minibars +minibike +minibiker +minibikers +minibikes +minibus +minibuses +minibusses +minicab +minicabs +minicam +minicamp +minicamps +minicams +minicar +minicars +minicomputer +minicomputers +miniconjou +miniconjous +miniconvention +miniconventions +minicourse +minicourses +minicoy +minicycle +minicycles +minidisk +minidisks +minie +minified +minifies +minify +minifying +minikin +minikins +minilab +minilabs +minim +minima +minimal +minimalism +minimalist +minimalists +minimality +minimalization +minimalizations +minimalize +minimalized +minimalizes +minimalizing +minimally +minimax +minimill +minimills +minimization +minimizations +minimize +minimized +minimizer +minimizers +minimizes +minimizing +minims +minimum +minimums +mining +minings +minion +minions +minipark +miniparks +minis +minischool +minischools +miniscule +miniseries +miniski +miniskirt +miniskirted +miniskirts +miniskis +ministate +ministates +minister +ministered +ministerial +ministerially +ministering +ministers +ministership +ministrant +ministrants +ministration +ministrations +ministrative +ministries +ministroke +ministrokes +ministry +minitrack +minitracks +minium +miniums +minivan +minivans +miniver +minivers +minié +mink +minke +minks +minn +minnan +minneapolis +minneconjou +minneconjous +minnesinger +minnesingers +minnesota +minnesotan +minnesotans +minnow +minnows +minoan +minoans +minor +minora +minorca +minorcan +minorcans +minored +minoring +minorite +minorites +minorities +minority +minors +minos +minotaur +minoxidil +minsk +minster +minsters +minstrel +minstrels +minstrelsies +minstrelsy +mint +mintage +minted +minter +minters +minting +mintmark +mintmarks +minton +mints +minty +minuend +minuends +minuet +minuets +minus +minuscular +minuscule +minuses +minute +minuted +minutely +minuteman +minutemen +minuteness +minuter +minutes +minutest +minutia +minutiae +minuting +minx +minxes +minxish +minyan +minyanim +minyans +miocene +mioses +miosis +miotic +miotics +miquelet +miquelets +miquelon +mir +mirabile +mirabiles +mirabilia +mirabilis +miracidia +miracidial +miracidium +miracle +miracles +miraculous +miraculously +miraculousness +mirador +miradors +mirage +mirages +miranda +mirandize +mirandized +mirandizes +mirandizing +mire +mired +mirepoix +mirepoixs +mires +mirex +mirexes +mirier +miriest +mirin +miriness +miring +mirins +mirk +mirks +mirky +mirliton +mirlitons +mirror +mirrored +mirroring +mirrorlike +mirrors +mirs +mirth +mirthful +mirthfully +mirthfulness +mirthless +mirthlessly +mirthlessness +mirv +mirved +mirving +mirvs +miry +miró +misact +misacts +misaddress +misaddressed +misaddresses +misaddressing +misadjust +misadjusted +misadjusting +misadjusts +misadministration +misadministrations +misadventure +misadventures +misadvise +misadvised +misadvises +misadvising +misaim +misaimed +misaiming +misaims +misalign +misaligned +misaligning +misalignment +misalignments +misaligns +misalliance +misalliances +misallied +misallies +misallocate +misallocated +misallocates +misallocating +misallocation +misallocations +misally +misallying +misanalyses +misanalysis +misanthrope +misanthropes +misanthropic +misanthropically +misanthropist +misanthropists +misanthropy +misapplication +misapplications +misapplied +misapplies +misapply +misapplying +misappraisal +misappraisals +misapprehend +misapprehended +misapprehending +misapprehends +misapprehension +misapprehensions +misappropriate +misappropriated +misappropriates +misappropriating +misappropriation +misappropriations +misarrange +misarranged +misarranges +misarranging +misarticulate +misarticulated +misarticulates +misarticulating +misassemble +misassembled +misassembles +misassembling +misassumption +misassumptions +misattribute +misattributed +misattributes +misattributing +misattribution +misattributions +misbalance +misbalanced +misbalances +misbalancing +misbecame +misbecome +misbecomes +misbecoming +misbegotten +misbehave +misbehaved +misbehaver +misbehavers +misbehaves +misbehaving +misbehavior +misbehaviors +misbelief +misbeliefs +misbelieve +misbelieved +misbeliever +misbelievers +misbelieves +misbelieving +misbound +misbrand +misbranded +misbranding +misbrands +misbutton +misbuttoned +misbuttoning +misbuttons +misc +miscalculate +miscalculated +miscalculates +miscalculating +miscalculation +miscalculations +miscall +miscalled +miscalling +miscalls +miscaption +miscaptioned +miscaptioning +miscaptions +miscarriage +miscarriages +miscarried +miscarries +miscarry +miscarrying +miscast +miscasting +miscasts +miscatalog +miscataloged +miscataloging +miscatalogs +miscegenation +miscegenational +miscegenations +miscellanea +miscellaneous +miscellaneously +miscellaneousness +miscellanies +miscellanist +miscellanists +miscellany +misch +mischance +mischannel +mischanneled +mischanneling +mischannels +mischaracterization +mischaracterizations +mischaracterize +mischaracterized +mischaracterizes +mischaracterizing +mischarge +mischarged +mischarges +mischarging +mischief +mischievous +mischievously +mischievousness +mischoice +mischoices +miscibility +miscible +miscitation +miscitations +misclassification +misclassifications +misclassified +misclassifies +misclassify +misclassifying +miscode +miscoded +miscodes +miscoding +miscommunication +miscommunications +miscomprehend +miscomprehended +miscomprehending +miscomprehends +miscomprehension +miscomprehensions +miscomputation +miscomputations +miscompute +miscomputed +miscomputes +miscomputing +misconceive +misconceived +misconceiver +misconceivers +misconceives +misconceiving +misconception +misconceptions +misconduct +misconducted +misconducting +misconducts +misconnect +misconnected +misconnecting +misconnection +misconnections +misconnects +misconstruction +misconstructions +misconstrue +misconstrued +misconstrues +misconstruing +miscopied +miscopies +miscopy +miscopying +miscorrelation +miscorrelations +miscount +miscounted +miscounting +miscounts +miscreant +miscreants +miscreate +miscreated +miscreates +miscreating +miscreation +miscreations +miscue +miscued +miscueing +miscues +miscuing +miscut +misdate +misdated +misdates +misdating +misdeal +misdealer +misdealers +misdealing +misdeals +misdealt +misdeed +misdeeds +misdeem +misdeemed +misdeeming +misdeems +misdefine +misdefined +misdefines +misdefining +misdemeanant +misdemeanants +misdemeanor +misdemeanors +misdemeanour +misdemeanours +misdescribe +misdescribed +misdescribes +misdescribing +misdescription +misdescriptions +misdevelop +misdeveloped +misdeveloping +misdevelops +misdiagnose +misdiagnosed +misdiagnoses +misdiagnosing +misdiagnosis +misdial +misdialed +misdialing +misdialled +misdialling +misdials +misdid +misdirect +misdirected +misdirecting +misdirection +misdirects +misdistribution +misdistributions +misdivision +misdivisions +misdo +misdoer +misdoers +misdoes +misdoing +misdone +misdoubt +misdoubted +misdoubting +misdoubts +misdraw +misdrawing +misdrawn +misdrew +mise +miseducate +miseducated +miseducates +miseducating +miseducation +miseducations +misemphases +misemphasis +misemphasize +misemphasized +misemphasizes +misemphasizing +misemploy +misemployed +misemploying +misemployment +misemployments +misemploys +miser +miserable +miserableness +miserably +miserere +misereres +misericord +misericorde +misericordes +misericords +miseries +miserliness +miserly +misers +misery +misesteem +misesteemed +misesteeming +misesteems +misestimate +misestimated +misestimates +misestimating +misestimation +misestimations +misevaluate +misevaluated +misevaluates +misevaluating +misevaluation +misevaluations +misfeasance +misfeasor +misfeasors +misfield +misfielded +misfielding +misfields +misfile +misfiled +misfiles +misfiling +misfire +misfired +misfires +misfiring +misfit +misfits +misfocus +misfocused +misfocuses +misfocusing +misfortune +misfortunes +misfuel +misfueled +misfueling +misfuelled +misfuelling +misfuels +misfunction +misfunctioned +misfunctioning +misfunctions +misgauge +misgauged +misgauges +misgauging +misgave +misgive +misgiven +misgives +misgiving +misgivings +misgovern +misgoverned +misgoverning +misgovernment +misgovernments +misgovernor +misgovernors +misgoverns +misgrade +misgraded +misgrades +misgrading +misguidance +misguide +misguided +misguidedly +misguidedness +misguider +misguiders +misguides +misguiding +mishandle +mishandled +mishandles +mishandling +mishanter +mishanters +mishap +mishaps +mishear +misheard +mishearing +mishears +mishegaas +mishegoss +mishit +mishits +mishitting +mishmash +mishmashes +mishna +mishnah +mishnaic +misidentification +misidentifications +misidentified +misidentifies +misidentify +misidentifying +misimpression +misimpressions +misinform +misinformant +misinformants +misinformation +misinformed +misinformer +misinformers +misinforming +misinforms +misinterpret +misinterpretation +misinterpretations +misinterpreted +misinterpreter +misinterpreters +misinterpreting +misinterprets +misjoinder +misjoinders +misjudge +misjudged +misjudges +misjudging +misjudgment +misjudgments +miskick +miskicked +miskicking +miskicks +miskito +miskitos +misknew +misknow +misknowing +misknowledge +misknown +misknows +mislabel +mislabeled +mislabeling +mislabelled +mislabelling +mislabels +mislaid +mislay +mislayer +mislayers +mislaying +mislays +mislead +misleader +misleaders +misleading +misleadingly +misleads +mislearn +mislearned +mislearning +mislearns +mislearnt +misled +mislike +misliked +mislikes +misliking +mislocate +mislocated +mislocates +mislocating +mislocation +mislocations +mismanage +mismanaged +mismanagement +mismanages +mismanaging +mismark +mismarked +mismarking +mismarks +mismarriage +mismarriages +mismatch +mismatched +mismatches +mismatching +mismate +mismated +mismates +mismating +misname +misnamed +misnames +misnaming +misnomer +misnomered +misnomers +miso +misogamic +misogamist +misogamists +misogamy +misogynic +misogynist +misogynistic +misogynists +misogynous +misogyny +misologist +misologists +misology +misoneism +misoneist +misoneists +misorder +misordered +misordering +misorders +misorient +misorientation +misoriented +misorienting +misorients +misos +mispackage +mispackaged +mispackages +mispackaging +misperceive +misperceived +misperceives +misperceiving +misperception +misperceptions +mispickel +mispickels +misplace +misplaced +misplacement +misplacements +misplaces +misplacing +misplan +misplanned +misplanning +misplans +misplay +misplayed +misplaying +misplays +misposition +mispositioned +mispositioning +mispositions +misprint +misprinted +misprinting +misprints +misprision +misprisions +misprize +misprized +misprizer +misprizers +misprizes +misprizing +misprogram +misprogramed +misprograming +misprogrammed +misprogramming +misprograms +mispronounce +mispronounced +mispronounces +mispronouncing +mispronunciation +mispronunciations +misquotation +misquotations +misquote +misquoted +misquoter +misquoters +misquotes +misquoting +misread +misreading +misreads +misreckon +misreckoned +misreckoning +misreckons +misrecollection +misrecollections +misrecord +misrecorded +misrecording +misrecords +misreference +misreferenced +misreferences +misreferencing +misregister +misregistered +misregistering +misregisters +misregistration +misregistrations +misrelate +misrelated +misrelates +misrelating +misremember +misremembered +misremembering +misremembers +misrender +misrendered +misrendering +misrenders +misreport +misreported +misreporter +misreporters +misreporting +misreports +misrepresent +misrepresentation +misrepresentations +misrepresentative +misrepresented +misrepresenter +misrepresenters +misrepresenting +misrepresents +misroute +misrouted +misroutes +misrouting +misrule +misruled +misrules +misruling +miss +missa +missable +missal +missals +missed +missend +missending +missends +missense +missenses +missent +misses +misset +missets +missetting +misshape +misshaped +misshapen +misshapenly +misshaper +misshapers +misshapes +misshaping +missies +missile +missileer +missileers +missileman +missilemen +missileries +missilery +missiles +missilries +missilry +missing +missiol +mission +missional +missionaries +missionary +missioned +missioner +missioners +missioning +missionization +missionizations +missionize +missionized +missionizer +missionizers +missionizes +missionizing +missions +missis +missises +mississippi +mississippian +mississippians +missive +missives +missolonghi +missort +missorted +missorting +missorts +missouri +missourian +missourians +missouris +missout +missouts +misspeak +misspeaking +misspeaks +misspell +misspelled +misspelling +misspellings +misspells +misspelt +misspend +misspending +misspends +misspent +misspoke +misspoken +misstate +misstated +misstatement +misstatements +misstates +misstating +misstep +missteps +misstricken +misstrike +misstrikes +misstriking +misstruck +missus +missuses +missy +mist +mistakable +mistakably +mistake +mistaken +mistakenly +mistaker +mistakers +mistakes +mistaking +mistassini +misted +mister +misters +mistflower +mistflowers +misthink +misthinking +misthinks +misthought +misthrew +misthrow +misthrowing +misthrown +misthrows +mistier +mistiest +mistily +mistime +mistimed +mistimes +mistiming +mistiness +misting +mistitle +mistitled +mistitles +mistitling +mistletoe +mistletoes +misto +mistook +mistrain +mistrained +mistraining +mistrains +mistral +mistrals +mistranscribe +mistranscribed +mistranscribes +mistranscribing +mistranscription +mistranscriptions +mistranslate +mistranslated +mistranslates +mistranslating +mistranslation +mistranslations +mistreat +mistreated +mistreating +mistreatment +mistreatments +mistreats +mistress +mistresses +mistrial +mistrials +mistrust +mistrusted +mistrustful +mistrustfully +mistrustfulness +mistrusting +mistrusts +mistruth +mistruths +mists +mistune +mistuned +mistunes +mistuning +misty +mistype +mistyped +mistypes +mistyping +misunderstand +misunderstanding +misunderstandings +misunderstands +misunderstood +misusage +misusages +misuse +misused +misuser +misusers +misuses +misusing +misutilization +misutilizations +misvalue +misvalued +misvalues +misvaluing +misvocalization +misvocalizations +misword +misworded +miswording +miswords +miswrite +miswrites +miswriting +miswritten +miswrote +mitanni +mitannian +mitannians +mitchell +mite +miter +mitered +miterer +miterers +mitering +miters +miterwort +miterworts +mites +mithraic +mithraism +mithraist +mithraists +mithras +mithridate +mithridates +mithridatic +mithridatism +mithridatisms +miticidal +miticide +miticides +mitigable +mitigate +mitigated +mitigates +mitigating +mitigation +mitigations +mitigative +mitigator +mitigators +mitigatory +mitochondria +mitochondrial +mitochondrion +mitogen +mitogenic +mitogenicity +mitogens +mitomycin +mitomycins +mitoses +mitosis +mitotic +mitotically +mitral +mitre +mitred +mitres +mitrewort +mitreworts +mitring +mitsubishi +mitsubishis +mitt +mitten +mittens +mittimus +mitts +mitty +mittyish +mitzvah +mitzvahed +mitzvahing +mitzvahs +mitzvoth +miwok +miwoks +mix +mixable +mixed +mixer +mixers +mixes +mixing +mixologist +mixologists +mixology +mixt +mixtec +mixtecs +mixture +mixtures +mizar +mizen +mizenmast +mizenmasts +mizens +mizoram +mizzen +mizzenmast +mizzenmasts +mizzens +mizzle +mizzled +mizzles +mizzling +mizzly +miño +ml +mlle +mlles +mm +mme +mmes +mnemonic +mnemonically +mnemonics +mnemosyne +moa +moab +moabite +moabites +moabitish +moan +moaned +moaner +moaners +moaning +moans +moas +moat +moated +moating +moatlike +moats +mob +mobbed +mobbing +mobbish +mobbishly +mobcap +mobcaps +mobe +mobil +mobile +mobiles +mobility +mobilization +mobilizations +mobilize +mobilized +mobilizes +mobilizing +mobled +mobocracies +mobocracy +mobocrat +mobocratic +mobocratical +mobocrats +mobs +mobster +mobsters +mobuto +moc +moccasin +moccasins +mocha +mochas +moche +mochica +mock +mocked +mocker +mockeries +mockers +mockery +mocking +mockingbird +mockingbirds +mockingly +mocks +mockup +mockups +mocs +mod +modacrylic +modacrylics +modal +modalities +modality +modally +mode +model +modeled +modeler +modelers +modeless +modeling +modelings +modelled +modelling +models +modem +modems +modena +moderate +moderated +moderately +moderateness +moderates +moderating +moderation +moderations +moderato +moderator +moderators +moderatorship +moderatorships +moderatos +modern +moderne +modernism +modernisms +modernist +modernistic +modernists +modernities +modernity +modernization +modernizations +modernize +modernized +modernizer +modernizers +modernizes +modernizing +modernly +modernness +moderns +modes +modest +modesties +modestly +modesty +modi +modica +modicum +modicums +modifiability +modifiable +modification +modifications +modificative +modificator +modificators +modificatory +modified +modifier +modifiers +modifies +modify +modifying +modigliani +modillion +modillions +modioli +modiolus +modish +modishly +modishness +modiste +modistes +modoc +modocs +modred +mods +modulability +modular +modularity +modularization +modularizations +modularize +modularized +modularizes +modularizing +modularly +modulars +modulate +modulated +modulates +modulating +modulation +modulations +modulative +modulator +modulators +modulatory +module +modules +moduli +modulo +modulus +modus +moesia +mofette +mofettes +moffette +moffettes +mogadishu +mogen +moggie +moggies +moggy +moghul +moghuls +mogollon +mogul +moguls +mohair +mohammed +mohammedan +mohammedanism +mohammedanisms +mohammedans +moharram +mohave +mohaves +mohawk +mohawks +mohegan +mohegans +mohenjo +mohican +mohicans +moho +mohock +mohockism +mohorovicic +mohos +mohs +mohur +mohurs +moidore +moidores +moieties +moiety +moil +moiled +moiler +moilers +moiling +moilingly +moils +moines +moirai +moire +moires +moiré +moist +moisten +moistened +moistener +moisteners +moistening +moistens +moister +moistest +moistly +moistness +moisture +moistures +moisturize +moisturized +moisturizer +moisturizers +moisturizes +moisturizing +mojarra +mojarras +mojave +mojaves +mojo +mojoes +mojos +moke +mokes +mol +mola +molal +molalities +molality +molar +molarities +molarity +molars +molas +molasses +mold +moldable +moldavia +moldavian +moldavians +moldboard +moldboards +molded +molder +moldered +moldering +molders +moldier +moldiest +moldiness +molding +moldings +moldova +moldovan +moldovans +molds +moldy +mole +molecular +molecularity +molecularly +molecule +molecules +molehill +molehills +moles +moleskin +moleskins +molest +molestation +molestations +molested +molester +molesters +molesting +molests +molies +moline +molise +molière +moll +mollie +mollies +mollifiable +mollification +mollifications +mollified +mollifier +mollifiers +mollifies +mollify +mollifying +mollifyingly +molls +mollusc +mollusca +molluscan +molluscicidal +molluscicide +molluscicides +molluscoid +molluscous +molluscs +molluscum +mollusk +molluskan +mollusks +molly +mollycoddle +mollycoddled +mollycoddler +mollycoddlers +mollycoddles +mollycoddling +moloch +molokai +molopo +molotov +mols +molt +molted +molten +molter +molters +molting +molto +molts +moluccan +moluccans +moluccas +moly +molybdate +molybdates +molybdenite +molybdenites +molybdenum +molybdic +molybdous +mom +mombasa +mome +moment +momenta +momentarily +momentariness +momentary +momently +momento +momentous +momentously +momentousness +moments +momentum +momentums +momes +momma +mommas +mommies +mommy +moms +momus +mon +mona +monacan +monacans +monachal +monachism +monachisms +monaco +monad +monadelphous +monadic +monadical +monadically +monadism +monadnock +monadnocks +monads +monandries +monandrous +monandry +monanthous +monarch +monarchal +monarchally +monarchial +monarchian +monarchianism +monarchic +monarchical +monarchically +monarchies +monarchism +monarchist +monarchistic +monarchists +monarchs +monarchy +monarda +monardas +monasterial +monasteries +monasterries +monastery +monastic +monastical +monastically +monasticism +monastics +monatomic +monatomically +monaural +monaurally +monaxial +monazite +monazites +monday +mondays +monde +mondrian +monecious +monel +monensin +monensins +moneran +monerans +monestrous +monet +monetarily +monetarism +monetarist +monetarists +monetary +monetization +monetizations +monetize +monetized +monetizes +monetizing +money +moneybag +moneybags +moneybox +moneyboxes +moneychanger +moneychangers +moneyed +moneyer +moneyers +moneygrubber +moneygrubbers +moneygrubbing +moneylender +moneylenders +moneymaker +moneymakers +moneymaking +moneyman +moneymen +moneys +moneysaving +moneywort +moneyworts +mongeese +monger +mongered +mongering +mongers +mongo +mongol +mongolia +mongolian +mongolians +mongolic +mongolism +mongoloid +mongoloids +mongols +mongoose +mongooses +mongrel +mongrelism +mongrelization +mongrelizations +mongrelize +mongrelized +mongrelizes +mongrelizing +mongrelly +mongrels +monicker +monickers +monied +monies +moniker +monikers +monilial +moniliasis +moniliform +moniliformly +monish +monished +monishes +monishing +monism +monist +monistic +monistically +monists +monition +monitions +monitor +monitored +monitorial +monitorially +monitories +monitoring +monitors +monitorship +monitorships +monitory +monk +monkeries +monkery +monkey +monkeyed +monkeying +monkeylike +monkeypod +monkeypods +monkeys +monkeyshine +monkeyshines +monkfish +monkfishes +monkhood +monkhoods +monkish +monkishly +monkishness +monks +monkshood +monkshoods +mono +monoacid +monoacidic +monoacids +monoamine +monoaminergic +monoamines +monobasic +monocarboxylic +monocarp +monocarpellary +monocarpic +monocarpous +monocarps +monocausal +monocephalic +monocephalous +monoceros +monochasia +monochasial +monochasium +monochord +monochords +monochromat +monochromatic +monochromatically +monochromaticity +monochromatism +monochromator +monochromators +monochromats +monochrome +monochromes +monochromic +monochromist +monochromists +monocle +monocled +monocles +monoclinal +monocline +monoclines +monoclinic +monoclinous +monoclonal +monocoque +monocoques +monocot +monocots +monocotyledon +monocotyledonous +monocotyledons +monocracies +monocracy +monocrat +monocratic +monocrats +monocrystal +monocrystalline +monocrystals +monocular +monocularly +monocultural +monoculture +monocultures +monocycle +monocycles +monocyclic +monocyte +monocytes +monocytic +monocytoid +monocytoses +monocytosis +monodactyl +monodactylous +monodactyls +monodic +monodical +monodically +monodies +monodisperse +monodist +monodists +monodrama +monodramas +monodramatic +monody +monoecious +monoeciously +monoecism +monoester +monoesters +monofilament +monofilaments +monogamic +monogamist +monogamists +monogamous +monogamously +monogamy +monogastric +monogenean +monogeneans +monogenesis +monogenetic +monogenic +monogenically +monogenism +monogenist +monogenistic +monogenists +monogenous +monogerm +monoglot +monoglots +monoglyceride +monoglycerides +monogram +monogramed +monograming +monogrammatic +monogrammed +monogrammer +monogrammers +monogramming +monograms +monograph +monographed +monographer +monographers +monographic +monographically +monographing +monographs +monogynist +monogynists +monogynous +monogyny +monohull +monohulls +monohybrid +monohybrids +monohydrate +monohydrated +monohydrates +monohydric +monohydroxy +monoicous +monolayer +monolayers +monolingual +monolingualism +monolinguals +monolith +monolithic +monolithically +monoliths +monolog +monologged +monologging +monologic +monological +monologist +monologists +monologize +monologized +monologizes +monologizing +monologs +monologue +monologued +monologues +monologuing +monologuist +monologuists +monomania +monomaniac +monomaniacal +monomaniacally +monomaniacs +monomer +monomeric +monomers +monometallic +monometallism +monometallist +monometallists +monometer +monometers +monomial +monomials +monomolecular +monomolecularly +monomorphemic +monomorphic +monomorphism +monomorphous +monongahela +mononuclear +mononucleate +mononucleated +mononucleosis +mononucleotide +mononucleotides +monopetalous +monophagous +monophagy +monophobia +monophobias +monophobic +monophonic +monophonically +monophonies +monophony +monophosphate +monophthong +monophthongal +monophthongs +monophyletic +monophyletically +monophyly +monophysite +monophysites +monophysitic +monophysitism +monoplane +monoplanes +monoplegia +monoplegias +monoplegic +monoploid +monoploids +monopod +monopode +monopodes +monopodia +monopodial +monopodially +monopodium +monopods +monopole +monopoles +monopolies +monopolism +monopolist +monopolistic +monopolistically +monopolists +monopolization +monopolizations +monopolize +monopolized +monopolizer +monopolizers +monopolizes +monopolizing +monopoly +monopropellant +monopropellants +monoprotic +monopsonies +monopsonist +monopsonistic +monopsonists +monopsony +monorail +monorails +monorchid +monorchidism +monorchids +monorhyme +monorhymed +monorhymes +monos +monosaccharide +monosaccharides +monosepalous +monosodium +monosome +monosomes +monosomic +monosomy +monospecific +monospecificity +monospermal +monospermous +monostele +monosteles +monostelic +monostely +monostich +monostiches +monostichous +monostome +monostomous +monostylous +monosyllabic +monosyllabically +monosyllabicity +monosyllable +monosyllables +monosynaptic +monosynaptically +monoterpene +monoterpenes +monotheism +monotheist +monotheistic +monotheistical +monotheistically +monotheists +monothematic +monotint +monotints +monotone +monotones +monotonic +monotonically +monotonicity +monotonies +monotonous +monotonously +monotonousness +monotony +monotrematous +monotreme +monotremes +monotrichate +monotrichic +monotrichous +monotype +monotypes +monotypic +monounsaturate +monounsaturated +monounsaturates +monovalence +monovalency +monovalent +monovular +monoxide +monoxides +monozygotic +monroe +monrovia +mons +monseigneur +monsieur +monsignor +monsignori +monsignorial +monsignors +monsoon +monsoonal +monsoons +monster +monsters +monstrance +monstrances +monstrosities +monstrosity +monstrous +monstrously +monstrousness +montadale +montadales +montage +montaged +montages +montaging +montagnais +montagnard +montagnards +montague +montagues +montaigne +montan +montana +montanan +montanans +montane +montanism +montanist +montanists +montargis +montauk +montauks +monte +montecristo +montego +monteith +monteiths +montenegrin +montenegrins +montenegro +monterey +montero +monteros +monterrey +montes +montesquieu +montessori +montessorian +monteverdi +montevideo +montezuma +montferrat +montfort +montgolfier +montgomery +month +monthlies +monthlong +monthly +months +monticello +monticule +monticules +montmartre +montmorency +montmorillonite +montmorillonites +montmorillonitic +montparnasse +montpelier +montpellier +montrachet +montreal +montreux +montréal +montserrat +monument +monumental +monumentality +monumentalize +monumentalized +monumentalizes +monumentalizing +monumentally +monuments +monuron +monurons +monzonite +monzonites +monzonitic +monégasque +monégasques +moo +mooch +mooched +moocher +moochers +mooches +mooching +mood +moodier +moodiest +moodily +moodiness +moods +moody +mooed +mooing +moola +moolah +moon +moonbeam +moonbeams +moonblind +mooncalf +mooncalves +moonchild +moonchildren +moondust +mooned +mooneye +mooneyed +mooneyes +moonfaced +moonfish +moonfishes +moonflower +moonflowers +moonie +moonier +moonies +mooniest +mooning +moonish +moonishly +moonless +moonlet +moonlets +moonlight +moonlighted +moonlighter +moonlighters +moonlighting +moonlights +moonlike +moonlit +moonquake +moonquakes +moonrise +moonrises +moons +moonscape +moonscapes +moonseed +moonseeds +moonset +moonsets +moonshine +moonshined +moonshiner +moonshiners +moonshines +moonshining +moonstone +moonstones +moonstricken +moonstruck +moonwalk +moonwalked +moonwalker +moonwalkers +moonwalking +moonwalks +moonward +moonwort +moonworts +moony +moor +moorage +moore +moorea +moored +moorfowl +moorfowls +moorhen +moorhens +mooring +moorings +moorish +moorland +moorlands +moors +moos +moose +moosebird +moosebirds +moosehead +mooser +moosewood +moosewoods +moot +mooted +mooting +mootness +moots +mop +mopboard +mopboards +mope +moped +mopeds +moper +mopers +mopes +mopey +moping +mopish +mopishly +mopped +mopper +moppers +moppet +moppets +mopping +mops +moquette +moquettes +mor +mora +morae +morainal +moraine +moraines +morainic +moral +morale +moralism +moralisms +moralist +moralistic +moralistically +moralists +moralities +morality +moralization +moralizations +moralize +moralized +moralizer +moralizers +moralizes +moralizing +morally +morals +moras +morass +morasses +morassy +moratoria +moratorium +moratoriums +moratory +moravia +moravian +moravians +moray +morays +morbid +morbidities +morbidity +morbidly +morbidness +morbific +morbus +morceau +morceaux +mordacious +mordaciously +mordacity +mordancy +mordant +mordanted +mordanting +mordantly +mordants +mordecai +mordent +mordents +mordovia +mordvinia +more +moreen +moreens +morel +morello +morellos +morels +moreover +mores +moresque +moresques +morgan +morgana +morganatic +morganatically +morganite +morganites +morgans +morgen +morgens +morgue +morgues +mori +moribund +moribundity +moribundly +morion +morions +morisco +moriscoes +moriscos +moritz +mormon +mormonism +mormons +morn +mornay +morning +mornings +morns +morny +moro +moroccan +moroccans +morocco +moroccos +moron +moronic +moronically +moronism +moronity +morons +moros +morose +morosely +moroseness +morosity +morph +morphactin +morphactins +morphallaxes +morphallaxis +morphean +morpheme +morphemes +morphemic +morphemically +morphemics +morpheus +morphia +morphias +morphine +morphing +morphinism +morphinisms +morphinist +morphinists +morpho +morphogen +morphogenesis +morphogenetic +morphogenetically +morphogenic +morphogens +morphologic +morphological +morphologically +morphologies +morphologist +morphologists +morphology +morphometric +morphometrically +morphometry +morphophonemic +morphophonemics +morphos +morphoses +morphosis +morphs +morris +morrow +morrows +morse +morsel +morsels +mort +mortadella +mortadellas +mortal +mortalities +mortality +mortally +mortals +mortar +mortarboard +mortarboards +mortared +mortaring +mortarless +mortars +mortem +mortems +mortgage +mortgaged +mortgagee +mortgagees +mortgager +mortgagers +mortgages +mortgaging +mortgagor +mortgagors +mortice +morticed +mortices +mortician +morticians +morticing +mortification +mortifications +mortified +mortifier +mortifiers +mortifies +mortify +mortifying +mortifyingly +mortimer +mortis +mortise +mortised +mortises +mortising +mortmain +mortola +morton +morts +mortuaries +mortuary +morula +morulae +morular +morulation +morulations +mosaic +mosaically +mosaicism +mosaicisms +mosaicist +mosaicists +mosaicked +mosaicking +mosaiclike +mosaics +mosasaur +mosasaurs +moschatel +moschatels +moscow +moselle +moselles +moses +mosey +moseyed +moseying +moseys +mosfet +moshav +moshavim +moslem +moslems +mosotho +mosque +mosques +mosquito +mosquitoes +mosquitoey +mosquitos +moss +mossback +mossbacked +mossbacks +mossbunker +mossbunkers +mossed +mosses +mossgrown +mossier +mossiest +mossiness +mossing +mosslike +mosso +mossy +most +mostaccioli +mostly +mot +mote +motel +motels +motes +motet +motets +moth +mothball +mothballed +mothballing +mothballs +mother +motherboard +motherboards +mothered +motherfucker +motherfuckers +motherfucking +motherhood +motherhouse +motherhouses +mothering +motherings +motherland +motherlands +motherless +motherlessness +motherliness +motherly +mothers +motherwort +motherworts +mothier +mothiest +mothlike +mothproof +mothproofed +mothproofer +mothproofers +mothproofing +mothproofs +moths +mothy +motif +motific +motifs +motile +motility +motion +motional +motioned +motioning +motionless +motionlessly +motionlessness +motions +motivate +motivated +motivates +motivating +motivation +motivational +motivationally +motivations +motivative +motivator +motivators +motive +motived +motiveless +motivelessly +motives +motivic +motiving +motivities +motivity +motley +motleys +motmot +motmots +motocross +motocrosses +motoneuron +motoneurons +motor +motorbike +motorbikes +motorboat +motorboater +motorboaters +motorboating +motorboats +motorbus +motorbuses +motorbusses +motorcade +motorcaded +motorcades +motorcading +motorcar +motorcars +motorcycle +motorcycled +motorcycles +motorcycling +motorcyclist +motorcyclists +motordom +motored +motoric +motorically +motoring +motorist +motorists +motorization +motorizations +motorize +motorized +motorizes +motorizing +motorless +motorman +motormen +motormouth +motormouths +motorola +motors +motortruck +motortrucks +motorway +motorways +mots +mott +motte +mottes +mottle +mottled +mottler +mottlers +mottles +mottling +motto +mottoes +mottos +motts +moue +moues +moufflon +moufflons +mouflon +mouflons +mouillé +moujik +moujiks +moulage +moulages +moulin +moulins +mound +moundbird +moundbirds +mounded +mounding +mounds +mount +mountable +mountain +mountaineer +mountaineered +mountaineering +mountaineers +mountainous +mountainously +mountainousness +mountains +mountainside +mountainsides +mountaintop +mountaintops +mountainy +mountbatten +mountebank +mountebanked +mountebankery +mountebanking +mountebanks +mounted +mounter +mounters +mountie +mounties +mounting +mountings +mounts +mounty +mourn +mourned +mourner +mourners +mournful +mournfully +mournfulness +mourning +mourningly +mourns +mouse +moused +mouser +mousers +mouses +mousetrap +mousetrapped +mousetrapping +mousetraps +mousey +mousier +mousiest +mousily +mousiness +mousing +mousings +mousquetaire +mousquetaires +moussaka +mousse +moussed +mousseline +mousselines +mousses +moussing +moustache +moustaches +moustachio +moustachioed +moustachios +mousterian +mousy +mouth +mouthbreeder +mouthbreeders +mouthed +mouther +mouthers +mouthful +mouthfuls +mouthier +mouthiest +mouthiness +mouthing +mouthings +mouthlike +mouthpart +mouthparts +mouthpiece +mouthpieces +mouths +mouthwash +mouthwashes +mouthwatering +mouthwateringly +mouthy +mouton +moutonnée +moutonnéed +moutonnées +moutons +movability +movable +movableness +movables +movably +move +moveable +moved +moveless +movelessly +movelessness +movement +movements +mover +movers +moves +movie +moviedom +moviedoms +moviegoer +moviegoers +moviegoing +moviemaker +moviemakers +moviemaking +movies +moving +movingly +moviola +moviolas +mow +mowed +mower +mowers +mowing +mown +mows +moxie +moyen +mozambican +mozambicans +mozambique +mozarab +mozarabic +mozarabs +mozart +mozartian +mozartians +mozetta +mozettas +mozo +mozos +mozzarella +mozzetta +mozzettas +mpg +mph +mr +mri +mridanga +mridangam +mrs +ms +msg +mu +much +muchacho +muchachos +muchness +muciferous +mucilage +mucilaginous +mucilaginously +mucin +mucinous +mucins +muck +muckamuck +muckamucks +mucked +mucker +muckers +muckety +muckier +muckiest +muckily +mucking +muckluck +mucklucks +muckrake +muckraked +muckraker +muckrakers +muckrakes +muckraking +mucks +muckworm +muckworms +mucky +mucocutaneous +mucoid +mucoids +mucolytic +mucopeptide +mucopeptides +mucopolysaccharide +mucopolysaccharides +mucoprotein +mucoproteins +mucopurulent +mucosa +mucosae +mucosal +mucosas +mucous +mucoviscidosis +mucro +mucronate +mucronation +mucronations +mucrones +mucus +mud +mudbug +mudbugs +mudded +mudder +mudders +muddied +muddier +muddies +muddiest +muddily +muddiness +mudding +muddle +muddled +muddleheaded +muddleheadedly +muddleheadedness +muddler +muddlers +muddles +muddling +muddly +muddy +muddying +mudfish +mudfishes +mudflat +mudflats +mudflow +mudflows +mudguard +mudguards +mudpack +mudpacks +mudra +mudras +mudroom +mudrooms +muds +mudsill +mudsills +mudskipper +mudskippers +mudslide +mudslides +mudslinger +mudslingers +mudslinging +mudstone +mudstones +mudéjar +mudéjares +muenster +muensters +muesli +mueslis +muezzin +muezzins +muff +muffed +muffin +muffing +muffins +muffle +muffled +muffler +mufflered +mufflers +muffles +muffling +muffs +muffuletta +muffulettas +mufti +muftis +mug +mugful +mugged +muggee +muggees +mugger +muggers +muggier +muggiest +mugginess +mugging +muggings +muggy +mughal +mughals +mugho +mugo +mugs +mugwump +mugwumpery +mugwumps +muhammad +muhammadan +muhammadanism +muhammadanisms +muhammadans +muhammedan +muhammedans +muharram +muharrum +mujahedeen +mujahedeens +mujahedin +mujahedins +mujahideen +mujahideens +mujahidin +mujahidins +mujik +mujiks +mukluk +mukluks +muktuk +mulatto +mulattoes +mulattos +mulberries +mulberry +mulch +mulched +mulches +mulching +mulct +mulcted +mulcting +mulcts +mule +mules +muleskinner +muleskinners +muleta +muletas +muleteer +muleteers +muley +muleys +mulhacén +muliebrity +mulish +mulishly +mulishness +mull +mulla +mullah +mullahism +mullahs +mullas +mulled +mullein +mulleins +mullen +mullens +muller +mullerian +mullers +mullet +mullets +mulligan +mulligans +mulligatawnies +mulligatawny +mulling +mullion +mullioned +mullions +mullite +mullites +mulls +multi +multiaddress +multiage +multiagency +multiarmed +multiatom +multiauthor +multiaxial +multiband +multibank +multibarrel +multibarreled +multibillion +multibillionaire +multibillionaires +multibladed +multibranched +multibuilding +multicampus +multicar +multicarbon +multicausal +multicell +multicelled +multicellular +multicellularity +multicellulocentric +multicenter +multichain +multichambered +multichannel +multicharacter +multicity +multiclient +multicoated +multicolor +multicolored +multicolumn +multicomponent +multiconductor +multicopy +multicounty +multicourse +multicultural +multiculturalism +multicurie +multicurrency +multidentate +multidialectal +multidimensional +multidimensionality +multidirectional +multidisciplinary +multidiscipline +multidivisional +multidomain +multidrug +multielectrode +multielement +multiemployer +multiengine +multienzyme +multiethnic +multifaceted +multifactor +multifactorial +multifactorially +multifamily +multifarious +multifariously +multifariousness +multifid +multifilament +multiflash +multiflora +multiflorous +multifocal +multifoil +multifoils +multifold +multiform +multiformity +multifrequency +multifunction +multifunctional +multigenerational +multigenic +multigerm +multigrade +multigrain +multigravida +multigravidas +multigrid +multigrooved +multigroup +multihandicapped +multiheaded +multihospital +multihued +multihull +multilane +multilateral +multilateralism +multilateralist +multilateralists +multilaterally +multilayer +multilayered +multilevel +multileveled +multiline +multilingual +multilingualism +multilingually +multilobed +multilocular +multimanned +multimedia +multimegaton +multimegawatt +multimember +multimetallic +multimillennial +multimillion +multimillionaire +multimillionaires +multimodal +multimode +multimolecular +multination +multinational +multinationalism +multinationals +multinomial +multinomials +multinuclear +multinucleate +multinucleated +multiorgasmic +multipack +multipacks +multipage +multipaned +multipara +multiparae +multiparameter +multiparas +multiparity +multiparous +multipart +multiparticle +multipartite +multiparty +multipath +multiped +multipede +multiphase +multiphasic +multiphoton +multipicture +multipiece +multipion +multipiston +multiplant +multiplayer +multiple +multiples +multiplet +multiplets +multiplex +multiplexed +multiplexer +multiplexers +multiplexes +multiplexing +multiplexor +multiplexors +multipliable +multiplicable +multiplicand +multiplicands +multiplicate +multiplication +multiplicational +multiplications +multiplicative +multiplicatively +multiplicities +multiplicity +multiplied +multiplier +multipliers +multiplies +multiply +multiplying +multipoint +multipolar +multipolarity +multipole +multiport +multipotential +multipower +multiproblem +multiprocessing +multiprocessor +multiprocessors +multiproduct +multiprogramming +multipronged +multipurpose +multiracial +multiracialism +multiracialisms +multirange +multiregional +multireligious +multiroom +multiscreen +multisense +multisensory +multiservice +multisided +multisite +multisize +multiskilled +multisource +multispecies +multispectral +multispeed +multisport +multisports +multistage +multistate +multistemmed +multistep +multistoried +multistory +multistranded +multisyllabic +multisystem +multitalented +multitask +multitasked +multitasking +multitasks +multiterminal +multithreaded +multitiered +multiton +multitone +multitowered +multitrack +multitracked +multitracking +multitrillion +multitude +multitudes +multitudinous +multitudinously +multitudinousness +multiunion +multiunit +multiuse +multiuser +multivalence +multivalent +multivariable +multivariate +multiversities +multiversity +multivitamin +multivitamins +multivoltine +multivolume +multiwall +multiwarhead +multiwavelength +multiword +multiyear +multnomah +multure +multures +mum +mumble +mumbled +mumbler +mumblers +mumbles +mumblety +mumbling +mumbly +mumbo +mummed +mummer +mummeries +mummers +mummery +mummichog +mummichogs +mummies +mummification +mummifications +mummified +mummifies +mummify +mummifying +mumming +mummy +mump +mumped +mumps +mums +munch +munchausen +munched +muncher +munchers +munches +munchhausen +munchies +munching +munchkin +munchkins +munda +mundane +mundanely +mundaneness +mundanity +mundungus +mung +mungo +mungos +muni +munich +municipal +municipalities +municipality +municipalization +municipalizations +municipalize +municipalized +municipalizes +municipalizing +municipally +municipals +munificence +munificent +munificently +muniment +muniments +munis +munition +munitioned +munitioning +munitions +munsee +munsees +munster +munsters +muntin +muntins +muntjac +muntjacs +muntjak +muntjaks +muon +muonic +muonium +muons +muppie +muppies +mural +muraled +muralist +muralists +muralled +murals +muramic +murat +murchison +murder +murdered +murderee +murderees +murderer +murderers +murderess +murderesses +murdering +murderous +murderously +murderousness +murders +murein +mureins +murex +murexes +muriate +muriates +muriatic +muricate +muricated +murices +murid +murids +murine +murines +murk +murkier +murkiest +murkily +murkiness +murks +murky +murmansk +murmur +murmured +murmurer +murmurers +murmuring +murmuringly +murmurous +murmurously +murmurs +murphies +murphy +murrain +murrains +murray +murre +murres +murrey +murreys +murrumbidgee +murther +murthered +murthering +murthers +musca +muscadet +muscadets +muscadine +muscadines +muscae +muscarine +muscarines +muscarinic +muscat +muscatel +muscatels +muscats +muscid +muscids +muscle +musclebound +muscled +muscleman +musclemen +muscles +muscling +muscly +muscovite +muscovites +muscovy +muscular +muscularity +muscularly +musculature +musculoskeletal +muse +mused +museological +museologically +museologist +museologists +museology +muser +musers +muses +musette +musettes +museum +museumgoer +museumgoers +museums +mush +mushed +musher +mushers +mushes +mushier +mushiest +mushily +mushiness +mushing +mushroom +mushroomed +mushrooming +mushrooms +mushy +music +musical +musicale +musicales +musicality +musicalization +musicalizations +musicalize +musicalized +musicalizes +musicalizing +musically +musicals +musician +musicianly +musicians +musicianship +musicological +musicologically +musicologist +musicologists +musicology +musing +musingly +musings +musique +musk +muskeg +muskegs +muskellunge +muskellunges +muskelunge +muskelunges +musket +musketeer +musketeers +musketry +muskets +muskhogean +muskhogeans +muskie +muskier +muskies +muskiest +muskiness +muskingum +muskmelon +muskmelons +muskogean +muskogeans +muskogee +muskogees +muskox +muskoxen +muskrat +muskrats +muskroot +muskroots +musky +muslim +muslims +muslin +muslins +musquash +musquashes +musquashs +muss +mussalman +mussed +mussel +mussels +musses +mussier +mussiest +mussily +mussiness +mussing +mussolini +mussorgsky +mussulman +mussulmans +mussulmen +mussy +must +mustache +mustached +mustaches +mustachio +mustachioed +mustachios +mustang +mustangs +mustard +mustards +mustardy +musteline +muster +mustered +mustering +musters +musth +musths +mustier +mustiest +mustily +mustiness +mustn +mustn't +musts +musty +mutability +mutable +mutableness +mutably +mutagen +mutageneses +mutagenesis +mutagenic +mutagenically +mutagenicity +mutagenize +mutagenized +mutagenizes +mutagenizing +mutagens +mutandis +mutant +mutants +mutase +mutases +mutate +mutated +mutates +mutating +mutation +mutational +mutationally +mutations +mutatis +mutative +mutchkin +mutchkins +mute +muted +mutedly +mutely +muteness +muter +mutes +mutest +mutilate +mutilated +mutilates +mutilating +mutilation +mutilations +mutilative +mutilator +mutilators +mutine +mutined +mutineer +mutineers +mutines +muting +mutinied +mutinies +mutining +mutinous +mutinously +mutinousness +mutiny +mutinying +mutism +mutisms +muton +mutons +mutt +mutter +muttered +mutterer +mutterers +muttering +mutterings +mutters +mutton +muttonchops +muttonfish +muttonfishes +muttonhead +muttonheaded +muttonheads +muttons +muttony +mutts +mutual +mutualism +mutualisms +mutualist +mutualistic +mutualists +mutuality +mutualization +mutualizations +mutualize +mutualized +mutualizes +mutualizing +mutually +mutuals +mutuel +mutuels +muumuu +muumuus +muzak +muzhik +muzhiks +muzjik +muzjiks +muztag +muztagata +muztagh +muzzier +muzziest +muzzily +muzziness +muzzle +muzzled +muzzleloader +muzzleloaders +muzzleloading +muzzler +muzzlers +muzzles +muzzling +muzzy +mv +my +myalgia +myalgic +myanmar +myasthenia +myasthenic +myc +mycelia +mycelial +mycelium +mycenae +mycenaean +mycenaeans +mycenian +mycenians +mycetoma +mycetomas +mycetomata +mycetomatous +mycetophagous +mycetozoan +mycetozoans +mycobacteria +mycobacterial +mycobacterium +mycoflora +mycologic +mycological +mycologically +mycologies +mycologist +mycologists +mycology +mycophagist +mycophagists +mycophagous +mycophagy +mycophile +mycophiles +mycoplasma +mycoplasmal +mycoplasmas +mycorhiza +mycorrhiza +mycorrhizae +mycorrhizal +mycorrhizas +mycoses +mycosis +mycotic +mycotoxicoses +mycotoxicosis +mycotoxin +mycotoxins +mycs +mydriasis +mydriatic +mydriatics +myelencephalic +myelencephalon +myelencephalons +myelin +myelinated +myelination +myelinations +myeline +myelines +myelinic +myelinization +myelinizations +myelinize +myelinized +myelinizes +myelinizing +myelins +myelitis +myeloblast +myeloblastic +myeloblasts +myelocyte +myelocytes +myelocytic +myelofibroses +myelofibrosis +myelofibrotic +myelogenic +myelogenous +myelogram +myelograms +myelography +myeloid +myeloma +myelomas +myelomata +myelomatoid +myelomatous +myelopathic +myelopathy +myeloproliferative +myiases +myiasis +mykonos +mylar +mylonite +mylonites +myna +mynah +mynahs +mynas +mynheer +mynheers +myoblast +myoblasts +myocardia +myocardial +myocarditis +myocarditises +myocardium +myoclonic +myoclonus +myoclonuses +myoelectric +myoelectrical +myofibril +myofibrillar +myofibrils +myofilament +myofilaments +myogenetic +myogenic +myoglobin +myoglobins +myograph +myographs +myoinositol +myoinositols +myologic +myologist +myologists +myology +myoma +myomas +myomata +myomatous +myoneural +myopathic +myopathies +myopathy +myope +myopes +myopia +myopic +myopically +myosin +myosis +myositis +myositises +myosotis +myosotises +myotic +myotome +myotomes +myotonia +myotonias +myotonic +myriad +myriads +myriapod +myriapodous +myriapods +myriopod +myriopods +myristic +myrmecological +myrmecologist +myrmecologists +myrmecology +myrmecophile +myrmecophiles +myrmecophilous +myrmecophily +myrmidon +myrmidons +myrobalan +myrobalans +myrrh +myrtle +myself +mysia +mysian +mysians +mysid +mysids +mysophobia +mysophobias +mysore +mystagogic +mystagogue +mystagogues +mystagogy +mysteries +mysterious +mysteriously +mysteriousness +mystery +mystic +mystical +mystically +mysticalness +mysticete +mysticetes +mysticetous +mysticism +mystics +mystification +mystified +mystifier +mystifiers +mystifies +mystify +mystifying +mystifyingly +mystique +mystiques +myth +mythic +mythical +mythically +mythicize +mythicized +mythicizer +mythicizers +mythicizes +mythicizing +mythmaker +mythmakers +mythmaking +mythographer +mythographers +mythographies +mythography +mythoi +mythologer +mythologers +mythologic +mythological +mythologically +mythologies +mythologist +mythologists +mythologize +mythologized +mythologizer +mythologizers +mythologizes +mythologizing +mythology +mythomania +mythomaniac +mythomanias +mythopeic +mythopoeia +mythopoeic +mythopoesis +mythopoetic +mythopoetical +mythos +myths +mythy +myxameba +myxamoeba +myxamoebae +myxamoebas +myxedema +myxedemas +myxedematous +myxedemic +myxobacteria +myxobacterium +myxoedema +myxoedemas +myxoid +myxoma +myxomas +myxomata +myxomatoses +myxomatosis +myxomatous +myxomycete +myxomycetes +myxoviral +myxovirus +myxoviruses +málaga +mâche +mâches +mâché +mâcon +mälaren +märchen +médaillon +médaillons +médoc +mélange +mélanges +ménage +ménages +ménière +mérida +mérite +mésalliance +mésalliances +métier +métiers +métis +mêlée +mêlées +même +míkonos +mílos +möbius +mössbauer +müller +müllerian +münster +n +n'djamena +n'gana +n'ganas +naan +nab +nabataea +nabataean +nabataeans +nabatean +nabateans +nabbed +nabber +nabbers +nabbing +nabe +nabes +nabob +nabobs +nabokov +naboth +nabs +nacelle +nacelles +nacho +nachos +nacre +nacred +nacreous +nacres +nada +nadir +nadirs +nadu +naff +naffed +naffing +naffs +nag +naga +nagaland +nagana +naganas +nagar +nagas +nagasaki +nagged +nagger +naggers +nagging +naggingly +nags +nah +nahuatl +nahuatlan +nahuatls +nahum +naiad +naiades +naiads +naif +naifs +nail +nailbrush +nailbrushes +nailed +nailer +nailers +nailing +nails +nainsook +naipaul +naira +nairas +nairobi +naive +naively +naiveness +naiveties +naivety +naiveté +naked +nakedly +nakedness +naled +naleds +nalidixic +nalorphine +nalorphines +naloxone +naloxones +naltrexone +naltrexones +nam +nama +namable +namaland +namaqualand +namas +namaycush +namaycushes +namby +name +nameable +named +nameless +namelessly +namelessness +namely +nameplate +nameplates +namer +namers +names +namesake +namesakes +nametag +nametags +nametape +nametapes +namib +namibia +namibian +namibians +naming +nan +nana +nanak +nanas +nance +nances +nancy +nandina +nanism +nanisms +nankeen +nankeens +nankin +nanking +nankins +nannie +nannies +nannofossil +nannofossils +nannoplankton +nannoplanktons +nanny +nannyberries +nannyberry +nannyish +nanoampere +nanoamperes +nanobecquerel +nanobecquerels +nanocandela +nanocandelas +nanocoulomb +nanocoulombs +nanoengineering +nanofarad +nanofarads +nanofossil +nanofossils +nanogram +nanograms +nanohenries +nanohenry +nanohenrys +nanohertz +nanojoule +nanojoules +nanokelvin +nanokelvins +nanolumen +nanolumens +nanolux +nanometer +nanometers +nanomole +nanomoles +nanonewton +nanonewtons +nanoohm +nanoohms +nanopascal +nanopascals +nanoplankton +nanoplanktons +nanoradian +nanoradians +nanosecond +nanoseconds +nanosiemens +nanosievert +nanosieverts +nanosteradian +nanosteradians +nanotechnology +nanotesla +nanoteslas +nanovolt +nanovolts +nanowatt +nanowatts +nanoweber +nanowebers +nansen +nanterre +nantes +nanticoke +nanticokes +nantua +nantucket +nantucketer +nantucketers +naoise +naomi +nap +napa +napalm +napalmed +napalming +napalms +napas +nape +naperies +naperville +napery +napes +naphtali +naphtha +naphthalene +naphthalenes +naphthalenic +naphthalin +naphthaline +naphthalines +naphthalins +naphthas +naphthene +naphthenes +naphthenic +naphthol +naphthols +naphthous +naphthylamine +naphthylamines +naphtol +naphtols +napier +napierian +napiform +napkin +napkins +naples +napless +napoleon +napoleonic +napoleons +napoli +napoléon +nappa +nappas +nappe +napped +nappes +nappier +nappies +nappiest +napping +nappy +naprapath +naprapathies +naprapaths +naprapathy +naproxen +naproxens +naps +naptime +naptimes +narbonne +narc +narceine +narceines +narcism +narcisms +narcissi +narcissism +narcissisms +narcissist +narcissistic +narcissistically +narcissists +narcissus +narcissuses +narco +narcoanalyses +narcoanalysis +narcoanalytic +narcodollar +narcodollars +narcokleptocracies +narcokleptocracy +narcolepsies +narcolepsy +narcoleptic +narcoma +narcomas +narcomata +narcos +narcoses +narcosis +narcosyntheses +narcosynthesis +narcotic +narcotically +narcotics +narcotism +narcotisms +narcotization +narcotizations +narcotize +narcotized +narcotizes +narcotizing +narcs +nard +nards +nares +narghile +narghiles +nargileh +nargilehs +narial +naris +nark +narked +narking +narks +narraganset +narragansets +narragansett +narragansetts +narratability +narratable +narrate +narrated +narrater +narraters +narrates +narrating +narration +narrational +narrationally +narrations +narrative +narratively +narratives +narratological +narratologist +narratologists +narratology +narrator +narrators +narrow +narrowback +narrowbacks +narrowband +narrowcast +narrowcaster +narrowcasters +narrowcasting +narrowcasts +narrowed +narrower +narrowest +narrowing +narrowish +narrowly +narrowness +narrows +narthex +narthexes +narváez +narwal +narwals +narwhal +narwhale +narwhales +narwhals +nary +nasal +nasality +nasalization +nasalizations +nasalize +nasalized +nasalizes +nasalizing +nasally +nasals +nascence +nascency +nascent +naseberries +naseberry +naseby +nashville +nasion +nasions +naskapi +naskapis +nasofrontal +nasogastric +nasopharyngeal +nasopharynges +nasopharynx +nasopharynxes +nassau +nastic +nastier +nasties +nastiest +nastily +nastiness +nasturtium +nasturtiums +nasty +natal +natalities +natality +natant +natation +natations +natatorial +natatorium +natatory +natch +natchez +nates +nathan +nathanael +natheless +nathless +natick +naticks +nation +national +nationalism +nationalist +nationalistic +nationalistically +nationalists +nationalities +nationality +nationalization +nationalizations +nationalize +nationalized +nationalizer +nationalizers +nationalizes +nationalizing +nationally +nationals +nationhood +nationless +nations +nationwide +native +natively +nativeness +natives +nativism +nativisms +nativist +nativistic +nativists +nativities +nativity +nato +natriureses +natriuresis +natriuretic +natrolite +natrolites +natron +natrons +natter +nattered +nattering +natters +nattier +nattiest +nattily +nattiness +natty +naturae +natural +naturalism +naturalist +naturalistic +naturalistically +naturalists +naturalizable +naturalization +naturalizations +naturalize +naturalized +naturalizes +naturalizing +naturally +naturalness +naturals +nature +natured +naturedly +naturedness +naturel +natures +naturism +naturist +naturists +naturopath +naturopathic +naturopathies +naturopaths +naturopathy +naugahyde +naught +naughtier +naughties +naughtiest +naughtily +naughtiness +naughts +naughty +naumachia +naumachiae +naumachias +nauplial +nauplii +nauplius +nauru +nauruan +nauruans +nausea +nauseam +nauseant +nauseants +nauseate +nauseated +nauseates +nauseating +nauseatingly +nauseation +nauseations +nauseous +nauseously +nauseousness +nausicaa +nautch +nautical +nautically +nautili +nautiloid +nautiloids +nautilus +nautiluses +navaho +navahos +navaid +navaids +navajo +navajos +naval +navarre +nave +navel +navels +navelwort +navelworts +naves +navicular +naviculars +navies +navigability +navigable +navigableness +navigably +navigate +navigated +navigates +navigating +navigation +navigational +navigationally +navigations +navigator +navigators +navvies +navvy +navy +nawab +nawabs +naxos +nay +nays +naysaid +naysay +naysayer +naysayers +naysaying +naysays +nazarene +nazarenes +nazareth +nazarite +nazarites +naze +nazi +nazification +nazifications +nazify +naziism +nazirite +nazirites +naziritism +nazis +nazism +naïf +naïfs +naïve +naïvely +naïver +naïvest +naïvety +naïveté +naïvetés +nco +ncos +ncr +ndebele +ndebeles +ndjamena +ndongo +ndongos +ne +ne'er +neandertal +neanderthal +neanderthaloid +neanderthals +neanthropic +neap +neapolitan +neapolitans +neaps +near +nearby +nearctic +neared +nearer +nearest +nearing +nearly +nearness +nears +nearshore +nearside +nearsighted +nearsightedly +nearsightedness +neat +neaten +neatened +neatening +neatens +neater +neatest +neath +neatherd +neatly +neatness +neats +neb +nebbish +nebbishes +nebbishy +nebenkern +nebenkerns +nebraska +nebraskan +nebraskans +nebs +nebuchadnezzar +nebuchadnezzars +nebula +nebulae +nebular +nebulas +nebulization +nebulizations +nebulize +nebulized +nebulizer +nebulizers +nebulizes +nebulizing +nebulosities +nebulosity +nebulous +nebulously +nebulousness +necessaries +necessarily +necessary +necessitarian +necessitarianism +necessitarians +necessitate +necessitated +necessitates +necessitating +necessitation +necessitations +necessitative +necessities +necessitous +necessitously +necessitousness +necessity +neck +neckband +neckbands +necked +neckerchief +neckerchiefs +neckerchieves +necking +neckings +necklace +necklaces +neckless +neckline +necklines +neckpiece +neckpieces +necks +necktie +neckties +neckwear +necrobiosis +necrobiotic +necrologic +necrological +necrologies +necrologist +necrologists +necrology +necromancer +necromancers +necromancy +necromantic +necromantically +necrophagia +necrophagias +necrophagous +necrophile +necrophiles +necrophilia +necrophiliac +necrophiliacs +necrophilic +necrophilism +necrophobia +necrophobias +necrophobic +necropoleis +necropolis +necropolises +necropsied +necropsies +necropsing +necropsy +necrose +necrosed +necroses +necrosing +necrosis +necrotic +necrotize +necrotized +necrotizes +necrotizing +necrotomies +necrotomy +nectar +nectarial +nectaries +nectarine +nectarines +nectarous +nectars +nectary +nee +need +needed +needful +needfully +needfulness +needier +neediest +neediness +needing +needle +needlecraft +needlecrafts +needled +needlefish +needlefishes +needlelike +needlepoint +needlepointed +needlepointing +needlepoints +needler +needlers +needles +needless +needlessly +needlessness +needlewoman +needlewomen +needlework +needleworker +needleworkers +needling +needn +needn't +needs +needy +neem +neems +nefarious +nefariously +nefariousness +nefertiti +nefyn +negate +negated +negater +negaters +negates +negating +negation +negational +negations +negative +negatived +negatively +negativeness +negatives +negativing +negativism +negativist +negativistic +negativists +negativity +negator +negators +negatory +negatron +negatrons +negev +neglect +neglected +neglecter +neglecters +neglectful +neglectfully +neglectfulness +neglecting +neglects +negligee +negligees +negligence +negligent +negligently +negligibility +negligible +negligibleness +negligibly +negligé +negligée +negligées +negligés +negotiability +negotiable +negotiably +negotiant +negotiants +negotiate +negotiated +negotiates +negotiating +negotiation +negotiations +negotiator +negotiators +negotiatory +negress +negresses +negrillo +negrilloes +negrillos +negrito +negritoes +negritos +negritude +negro +negroes +negroid +negroids +negroness +negrophile +negrophiles +negrophilism +negrophobe +negrophobes +negrophobia +negros +negus +neguses +nehemiah +nehemias +nehru +neigh +neighbor +neighbored +neighborhood +neighborhoods +neighboring +neighborliness +neighborly +neighbors +neighed +neighing +neighs +neither +nekton +nektonic +nektons +nellie +nellies +nelly +nellyism +nelson +nelsons +nem +nematic +nematicidal +nematicide +nematicides +nematocidal +nematocide +nematocides +nematocyst +nematocystic +nematocysts +nematode +nematodes +nematological +nematologist +nematologists +nematology +nembutal +nemean +nemeans +nemertean +nemerteans +nemertine +nemertines +nemeses +nemesis +nemophila +nemophilas +nene +nenes +nenets +nennius +neo +neoarsphenamine +neoarsphenamines +neoclassic +neoclassical +neoclassicism +neoclassicist +neoclassicists +neocolonial +neocolonialism +neocolonialist +neocolonialists +neocon +neocons +neoconservatism +neoconservative +neoconservatives +neocortex +neocortexes +neocortical +neocortices +neodymium +neofascism +neofascist +neofascists +neogaea +neogaean +neogaeas +neogea +neogeas +neogenesis +neogenetic +neoimpressionism +neoimpressionist +neoimpressionists +neoliberal +neoliberalism +neoliberals +neolith +neolithic +neoliths +neological +neologically +neologies +neologism +neologisms +neologist +neologistic +neologistical +neologists +neologize +neologized +neologizes +neologizing +neology +neomycin +neon +neonatal +neonatally +neonate +neonates +neonatologist +neonatologists +neonatology +neoned +neoorthodox +neoorthodoxy +neopallia +neopallium +neopalliums +neophilia +neophiliac +neophiliacs +neophyte +neophytes +neoplasia +neoplasias +neoplasm +neoplasms +neoplastic +neoplasticism +neoplasticist +neoplasticists +neoplatonic +neoplatonism +neoplatonist +neoplatonists +neoprene +neoptolemus +neorealism +neorealist +neorealistic +neorealists +neorican +neoricans +neostigmine +neostigmines +neotenic +neotenies +neotenous +neoteny +neoteric +neoterics +neotropic +neotropical +neotropics +neotype +neotypes +nepal +nepalese +nepali +nepalis +nepenthe +nepenthean +nepenthes +nepheline +nephelines +nephelinic +nephelinite +nephelinites +nephelinitic +nephelite +nephelites +nephelometer +nephelometers +nephelometric +nephelometrically +nephelometry +nephew +nephews +nephological +nephology +nephoscope +nephoscopes +nephrectomies +nephrectomize +nephrectomized +nephrectomizes +nephrectomizing +nephrectomy +nephric +nephridia +nephridial +nephridium +nephrite +nephrites +nephritic +nephritides +nephritis +nephritises +nephrogenic +nephrogenous +nephrologist +nephrologists +nephrology +nephron +nephrons +nephropathic +nephropathies +nephropathy +nephroses +nephrosis +nephrostome +nephrostomes +nephrotic +nephrotomies +nephrotomy +nephrotoxic +nephrotoxicity +nepotism +nepotist +nepotistic +nepotistical +nepotists +neptune +neptunian +neptunium +neral +nerals +nerd +nerdish +nerds +nerdy +nereid +nereides +nereids +nereis +nereus +neritic +nero +nerol +neroli +nerols +neronian +nerts +nervate +nervation +nervations +nerve +nerved +nerveless +nervelessly +nervelessness +nerves +nervier +nerviest +nervily +nerviness +nerving +nervosa +nervosity +nervous +nervously +nervousness +nervure +nervures +nervy +nescience +nesciences +nescient +nescients +ness +nesselrode +nesselrodes +nesses +nessus +nest +nested +nester +nesters +nesting +nestle +nestled +nestler +nestlers +nestles +nestling +nestlings +nestor +nestorian +nestorianism +nestorians +nestorius +nestors +nests +net +netback +netbacks +nether +netherlander +netherlanders +netherlandish +netherlands +nethermost +netherworld +netherworldly +netherworlds +netkeeper +netkeepers +netless +netlike +netminder +netminders +nets +netsuke +netsukes +netted +netter +netters +netting +nettle +nettled +nettles +nettlesome +nettling +netty +network +networked +networker +networkers +networking +networkings +networks +netzahualcóyotl +neuchâtel +neufchâtel +neum +neumatic +neume +neumes +neums +neural +neuralgia +neuralgic +neurally +neuraminidase +neuraminidases +neurasthenia +neurasthenic +neurasthenically +neurasthenics +neurectomies +neurectomy +neurilemma +neurilemmal +neurilemmas +neuristor +neuristors +neuritic +neuritis +neuroanatomical +neuroanatomies +neuroanatomist +neuroanatomists +neuroanatomy +neurobiological +neurobiologist +neurobiologists +neurobiology +neuroblast +neuroblastoma +neuroblastomas +neuroblastomata +neuroblasts +neurochemical +neurochemist +neurochemistry +neurochemists +neuroendocrine +neuroendocrinological +neuroendocrinologist +neuroendocrinologists +neuroendocrinology +neurofibril +neurofibrillary +neurofibrils +neurofibroma +neurofibromas +neurofibromata +neurofibromatoses +neurofibromatosis +neurofilament +neurofilamentous +neurofilaments +neurogeneses +neurogenesis +neurogenetics +neurogenic +neurogenically +neuroglia +neuroglial +neurohormonal +neurohormone +neurohormones +neurohypophyseal +neurohypophyses +neurohypophysial +neurohypophysis +neuroimaging +neuroleptic +neuroleptics +neurologic +neurological +neurologically +neurologist +neurologists +neurology +neuroma +neuromas +neuromata +neuromuscular +neuron +neuronal +neurone +neurones +neuronic +neuronically +neurons +neuropath +neuropathic +neuropathically +neuropathies +neuropathologic +neuropathological +neuropathologist +neuropathologists +neuropathology +neuropaths +neuropathy +neuropharmacological +neuropharmacologist +neuropharmacologists +neuropharmacology +neurophysiologic +neurophysiological +neurophysiologist +neurophysiologists +neurophysiology +neuropsychiatric +neuropsychiatrist +neuropsychiatrists +neuropsychiatry +neuropsychological +neuropsychologist +neuropsychologists +neuropsychology +neuropteran +neuropterans +neuropterous +neuroradiological +neuroradiologist +neuroradiologists +neuroradiology +neuroscience +neuroscientific +neuroscientist +neuroscientists +neurosecretion +neurosecretions +neurosecretory +neurosensory +neuroses +neurosis +neurospora +neurosurgeon +neurosurgeons +neurosurgeries +neurosurgery +neurosurgical +neurotic +neurotically +neuroticism +neurotics +neurotomies +neurotomy +neurotoxic +neurotoxicity +neurotoxin +neurotoxins +neurotransmission +neurotransmissions +neurotransmitter +neurotransmitters +neurotropic +neurotropism +neurula +neurulae +neurulas +neurulation +neurulations +neustadt +neuston +neustons +neustria +neustrian +neustrians +neuter +neutered +neutering +neuters +neutral +neutralism +neutralist +neutralistic +neutralists +neutrality +neutralization +neutralizations +neutralize +neutralized +neutralizer +neutralizers +neutralizes +neutralizing +neutrally +neutralness +neutrals +neutrino +neutrinoless +neutrinos +neutron +neutronic +neutrons +neutrophil +neutrophile +neutrophilic +neutrophils +nevada +nevadan +nevadans +nevadian +nevadians +never +neverland +nevermore +nevertheless +nevi +neville +nevilles +nevis +nevoid +nevus +new +newark +newborn +newborns +newburg +newburgh +newcastle +newcomen +newcomer +newcomers +newel +newels +newer +newest +newfangled +newfangledness +newfound +newfoundland +newfoundlander +newfoundlanders +newie +newies +newish +newly +newlywed +newlyweds +newmarket +newmarkets +newness +newport +news +newsagent +newsagents +newsboy +newsboys +newsbreak +newsbreaks +newscast +newscaster +newscasters +newscasts +newsdealer +newsdealers +newsgathering +newsgatherings +newsgirl +newsgirls +newsgroup +newsgroups +newshound +newshounds +newsier +newsiest +newsiness +newsless +newsletter +newsletters +newsmagazine +newsmagazines +newsmaker +newsmakers +newsman +newsmen +newsmonger +newsmongers +newspaper +newspapering +newspaperings +newspaperman +newspapermen +newspapers +newspaperwoman +newspaperwomen +newspeak +newspeople +newsperson +newspersons +newsprint +newsreader +newsreaders +newsreel +newsreels +newsroom +newsrooms +newsstand +newsstands +newsweeklies +newsweekly +newswire +newswires +newswoman +newswomen +newsworthier +newsworthiest +newsworthiness +newsworthy +newswriting +newsy +newt +newton +newtonian +newtons +newts +next +nexus +nexuses +nez +ngorongoro +ngultrum +ngultrums +nguni +ngunis +ngwee +niacin +niacinamide +niagara +nialamide +niamey +nib +nibble +nibbled +nibbler +nibblers +nibbles +nibbling +nibelung +nibelungen +nibelungenlied +nibelungs +niblick +niblicks +nibs +nicad +nicads +nicaea +nicaragua +nicaraguan +nicaraguans +niccolite +niccolites +nice +nicely +nicene +niceness +nicer +nicest +niceties +nicety +niche +niched +niches +niching +nicholas +nichrome +nick +nicked +nickel +nickeled +nickelic +nickeliferous +nickeling +nickelled +nickelling +nickelodeon +nickelodeons +nickelous +nickels +nicker +nickered +nickering +nickers +nicking +nickle +nickles +nicknack +nicknacks +nickname +nicknamed +nicknamer +nicknamers +nicknames +nicknaming +nicks +nicobar +nicodemus +nicomedia +nicosia +nicotiana +nicotianas +nicotinamide +nicotine +nicotinic +nicotinism +nictate +nictated +nictates +nictating +nictitate +nictitated +nictitates +nictitating +nictitation +nictitations +nidate +nidated +nidates +nidating +nidation +nidations +niddering +nidderings +nide +nides +nidi +nidicolous +nidificate +nidificated +nidificates +nidificating +nidification +nidifications +nidified +nidifies +nidifugous +nidify +nidifying +nidus +niduses +niece +nieces +nielli +niellist +niellists +niello +nielloed +nielloing +niellos +nielsbohrium +niente +nietzsche +nietzschean +nietzscheans +nifedipine +nifedipines +niflheim +niftier +nifties +niftiest +niftily +niftiness +nifty +nigella +nigellas +niger +nigeria +nigerian +nigerians +niggard +niggardliness +niggardly +niggards +nigger +niggers +niggle +niggled +niggler +nigglers +niggles +niggling +nigglingly +nigglings +nigh +nighed +nigher +nighest +nighing +nighs +night +nightcap +nightcaps +nightclothes +nightclub +nightclubber +nightclubbers +nightclubby +nightclubs +nightdress +nightdresses +nighter +nighters +nightfall +nightglow +nightglows +nightgown +nightgowns +nighthawk +nighthawks +nightie +nighties +nightingale +nightingales +nightjar +nightjars +nightless +nightlife +nightlong +nightly +nightmare +nightmares +nightmarish +nightmarishly +nightmarishness +nightrider +nightriders +nights +nightscape +nightscapes +nightscope +nightscopes +nightshade +nightshades +nightshirt +nightshirts +nightside +nightsides +nightspot +nightspots +nightstand +nightstands +nightstick +nightsticks +nighttime +nightwalker +nightwalkers +nightwear +nighty +nigra +nigrae +nigrescence +nigrescences +nigrescent +nigrosine +nigrosines +nihil +nihilism +nihilist +nihilistic +nihilistically +nihilists +nihilities +nihility +niihau +nijinsky +nike +nikkei +nil +nile +niles +nilgai +nilgais +nill +nilled +nilling +nills +nilly +nilotic +nilpotency +nilpotent +nilpotents +nim +nimbi +nimble +nimbleness +nimbler +nimblest +nimbly +nimbostrati +nimbostratus +nimbus +nimbuses +nimes +nimieties +nimiety +niminy +nimmed +nimming +nimrod +nimrods +nims +nincompoop +nincompoopery +nincompoops +nine +ninebark +ninebarks +ninefold +ninepin +ninepins +niner +niners +nines +nineteen +nineteenfold +nineteens +nineteenth +nineteenths +nineties +ninetieth +ninetieths +ninety +ninetyfold +nineveh +ninhydrin +ninhydrins +ninja +ninjas +ninnies +ninny +ninnyhammer +ninnyhammers +ninon +ninons +ninth +ninthly +ninths +niobate +niobates +niobe +niobite +niobites +niobium +nip +nipa +nipas +niping +nipped +nipper +nippers +nippier +nippiest +nippily +nippiness +nipping +nippingly +nipple +nippled +nipples +nipplewort +nippleworts +nippon +nipponese +nippy +nips +nirvana +nirvanas +nirvanic +nisan +nisei +niseis +nisi +nissan +nissans +nissen +nisus +nit +niter +niterie +niteries +niters +nitery +nitid +nitinol +nitpick +nitpicked +nitpicker +nitpickers +nitpicking +nitpickings +nitpicks +nitpicky +nitrate +nitrated +nitrates +nitrating +nitration +nitrations +nitrator +nitrators +nitric +nitride +nitrided +nitrides +nitriding +nitrifiable +nitrification +nitrifications +nitrified +nitrifier +nitrifiers +nitrifies +nitrify +nitrifying +nitril +nitrile +nitriles +nitrils +nitrite +nitrites +nitro +nitrobacteria +nitrobacterium +nitrobenzene +nitrocellulose +nitrocellulosic +nitrochloroform +nitrochloroforms +nitrofuran +nitrofurans +nitrofurantoin +nitrofurantoins +nitrogen +nitrogenase +nitrogenases +nitrogenize +nitrogenized +nitrogenizes +nitrogenizing +nitrogenous +nitroglycerin +nitroglycerine +nitrohydrochloric +nitromethane +nitromethanes +nitroparaffin +nitroparaffins +nitroreductase +nitros +nitrosamine +nitrosamines +nitrostarch +nitrostarches +nitrous +nits +nitty +nitwit +nitwits +nitwitted +niue +nival +niveous +nivernais +nix +nixed +nixes +nixie +nixies +nixing +nixy +nizam +nizamate +nizams +niño +niños +no +noachian +noachic +noachical +noah +noah's +nob +nobbier +nobbiest +nobble +nobbled +nobbler +nobblers +nobbles +nobbling +nobby +nobel +nobelist +nobelists +nobelium +nobiliary +nobilities +nobility +noble +nobleman +noblemen +nobleness +nobler +nobles +noblesse +noblest +noblewoman +noblewomen +nobly +nobodies +nobody +nobs +nocent +nociceptive +nociceptor +nociceptors +nock +nocked +nocking +nocks +noctambulation +noctambulations +noctambulism +noctambulisms +noctambulist +noctambulists +noctiluca +noctilucas +noctilucent +noctuid +noctuids +noctule +noctules +nocturn +nocturnal +nocturnally +nocturne +nocturnes +nocturns +nocuous +nocuously +nod +nodal +nodality +nodally +nodded +nodder +nodders +noddies +nodding +noddle +noddles +noddy +node +nodes +nodi +nodose +nodosity +nods +nodular +nodulation +nodulations +nodule +nodules +nodulose +nodulous +nodus +noel +noels +noes +noesis +noetic +nog +noggin +nogging +noggins +nogs +noh +nohow +noil +noils +noir +noire +noires +noirish +noise +noised +noiseless +noiselessly +noiselessness +noisemaker +noisemakers +noisemaking +noises +noisette +noisettes +noisier +noisiest +noisily +noisiness +noising +noisome +noisomely +noisomeness +noisy +nolens +nolle +nolo +nolos +nom +noma +nomad +nomadic +nomadically +nomadism +nomads +nomarchies +nomarchy +nomas +nombril +nombrils +nome +nomen +nomenclator +nomenclatorial +nomenclators +nomenclatural +nomenclature +nomenclatures +nomenklatura +nomenklaturas +nomes +nomina +nominal +nominalism +nominalist +nominalistic +nominalists +nominalization +nominalize +nominalized +nominalizes +nominalizing +nominally +nominals +nominate +nominated +nominates +nominating +nomination +nominations +nominative +nominatives +nominator +nominators +nominee +nominees +nomogram +nomograms +nomograph +nomographic +nomographs +nomography +nomologic +nomological +nomologically +nomologist +nomologists +nomology +nomothetic +nomothetical +nomothetically +noms +non +nonabrasive +nonabsorbable +nonabsorbent +nonabsorptive +nonabstract +nonacademic +nonacceptance +nonaccountable +nonaccredited +nonaccrual +nonachievement +nonacid +nonacidic +nonacquisitive +nonacting +nonaction +nonactivated +nonactor +nonadaptive +nonaddict +nonaddictive +nonadditive +nonadditivity +nonadhesive +nonadiabatic +nonadjacent +nonadjustable +nonadmirer +nonadmission +nonaesthetic +nonaffiliated +nonaffluent +nonage +nonagenarian +nonagenarians +nonages +nonaggression +nonaggressive +nonagon +nonagons +nonagricultural +nonalcoholic +nonalcoholics +nonaligned +nonalignment +nonallelic +nonallergenic +nonallergic +nonalphabetic +nonaluminum +nonambiguous +nonanalytic +nonanatomic +nonanimal +nonanoic +nonanswer +nonantagonistic +nonanthropological +nonanthropologist +nonantibiotic +nonantigenic +nonappearance +nonappearances +nonaquatic +nonaqueous +nonarable +nonarbitrariness +nonarbitrary +nonarchitect +nonarchitecture +nonargument +nonaristocratic +nonaromatic +nonart +nonartist +nonartistic +nonary +nonascetic +nonaspirin +nonassertive +nonassessable +nonassociated +nonastronomical +nonathlete +nonathletic +nonatomic +nonattached +nonattachment +nonattendance +nonattender +nonauditory +nonauthor +nonauthoritarian +nonautomated +nonautomatic +nonautomotive +nonautonomous +nonavailability +nonbacterial +nonbank +nonbanking +nonbarbiturate +nonbaryonic +nonbasic +nonbearing +nonbehavioral +nonbeing +nonbeings +nonbelief +nonbeliever +nonbelievers +nonbelligerency +nonbelligerent +nonbelligerents +nonbetting +nonbibliographic +nonbinary +nonbinding +nonbiodegradable +nonbiographical +nonbiological +nonbiologically +nonbiologist +nonbiting +nonblack +nonblacks +nonblank +nonbody +nonbonded +nonbonding +nonbook +nonbooks +nonbotanist +nonbrand +nonbreakable +nonbreathing +nonbreeder +nonbreeding +nonbroadcast +nonbuilding +nonburnable +nonbusiness +nonbuying +noncabinet +noncaking +noncallable +noncaloric +noncampus +noncancelable +noncancerous +noncandidacy +noncandidate +noncandidates +noncannibalistic +noncapital +noncapitalist +noncarcinogen +noncarcinogenic +noncardiac +noncareer +noncarrier +noncash +noncasual +noncausal +nonce +noncelebration +noncelebrity +noncellular +noncellulosic +noncentral +noncertificated +noncertified +nonchalance +nonchalant +nonchalantly +noncharacter +noncharismatic +nonchauvinist +nonchemical +nonchromosomal +nonchronological +nonchurch +nonchurchgoer +noncircular +noncirculating +noncitizen +noncitizens +nonclandestine +nonclass +nonclassical +nonclassified +nonclassroom +nonclearing +nonclerical +noncling +nonclinical +nonclogging +noncoercive +noncognitive +noncoherent +noncoincidence +noncoital +noncoking +noncola +noncollector +noncollege +noncollegiate +noncollinear +noncolor +noncolored +noncolorfast +noncom +noncombat +noncombatant +noncombatants +noncombative +noncombustible +noncommercial +noncommissioned +noncommitment +noncommittal +noncommittally +noncommitted +noncommunicating +noncommunication +noncommunicative +noncommunist +noncommunists +noncommunity +noncommutative +noncommutativity +noncomparability +noncomparable +noncompatible +noncompetition +noncompetitive +noncompetitor +noncomplementary +noncomplex +noncompliance +noncompliances +noncompliant +noncompliants +noncomplicated +noncomplying +noncomposer +noncompound +noncomprehension +noncompressible +noncompulsory +noncomputer +noncomputerized +noncoms +nonconceptual +nonconcern +nonconclusion +nonconcur +nonconcured +nonconcuring +nonconcurrence +nonconcurrent +nonconcurring +nonconcurs +noncondensable +nonconditioned +nonconducting +nonconduction +nonconductive +nonconductor +nonconductors +nonconference +nonconfidence +nonconfidential +nonconflicting +nonconform +nonconformance +nonconformances +nonconformed +nonconformer +nonconformers +nonconforming +nonconformism +nonconformist +nonconformists +nonconformity +nonconforms +nonconfrontation +nonconfrontational +noncongruent +nonconjugated +nonconnection +nonconscious +nonconsecutive +nonconsensual +nonconservation +nonconservative +nonconsolidated +nonconstant +nonconstitutional +nonconstruction +nonconstructive +nonconsumer +nonconsuming +nonconsumption +nonconsumptive +noncontact +noncontagious +noncontemporary +noncontiguous +noncontingent +noncontinuous +noncontract +noncontractual +noncontradiction +noncontradictory +noncontributing +noncontributory +noncontrollable +noncontrolled +noncontrolling +noncontroversial +nonconventional +nonconvertible +noncooperation +noncooperationist +noncooperationists +noncooperations +noncooperative +noncooperator +noncooperators +noncoplanar +noncorporate +noncorrelation +noncorrodible +noncorroding +noncorrosive +noncountry +noncounty +noncoverage +noncreative +noncreativity +noncredentialed +noncredit +noncrime +noncriminal +noncrisis +noncritical +noncrossover +noncrushable +noncrystalline +nonculinary +noncultivated +noncultivation +noncultural +noncumulative +noncurrent +noncustodial +noncustomer +noncyclic +noncyclical +nondairy +nondance +nondancer +nondeceptive +nondecision +nondecreasing +nondeductibility +nondeductible +nondeductive +nondefense +nondeferrable +nondeforming +nondegenerate +nondegradable +nondegree +nondelegate +nondeliberate +nondelinquent +nondelivery +nondemanding +nondemocratic +nondenominational +nondenominationalism +nondepartmental +nondependent +nondepletable +nondepleting +nondeposition +nondepressed +nonderivative +nondescript +nondescriptive +nondescriptly +nondescripts +nondesert +nondestructive +nondestructively +nondestructiveness +nondetachable +nondeterministic +nondevelopment +nondeviant +nondiabetic +nondialyzable +nondiapausing +nondidactic +nondiffusible +nondimensional +nondiplomatic +nondirected +nondirectional +nondirective +nondisabled +nondisclosure +nondisclosures +nondiscount +nondiscretionary +nondiscrimination +nondiscriminatory +nondiscursive +nondisjunction +nondisjunctional +nondisjunctions +nondispersive +nondisruptive +nondistinctive +nondiversified +nondividing +nondoctor +nondoctrinaire +nondocumentary +nondogmatic +nondollar +nondomestic +nondominant +nondormant +nondramatic +nondrinker +nondrinkers +nondrinking +nondriver +nondrug +nondrying +nondurable +nondurables +none +nonearning +nonecclesiastical +noneconomic +noneconomist +nonedible +noneditorial +noneducation +noneducational +noneffective +nonego +nonelastic +nonelected +nonelection +nonelective +nonelectric +nonelectrical +nonelectrolyte +nonelectrolytes +nonelectronic +nonelementary +nonelite +nonemergency +nonemotional +nonemphatic +nonempirical +nonemployee +nonemployment +nonempty +nonencapsulated +nonending +nonenergy +nonenforceability +nonenforcement +nonengagement +nonengineering +nonentertainment +nonentities +nonentity +nonenzymatic +nonenzymic +nonequilibrium +nonequivalence +nonequivalent +nonerotic +nones +nonessential +nonessentials +nonestablished +nonestablishment +nonesterified +nonesuch +nonesuches +nonet +nonetheless +nonethical +nonethnic +nonets +nonevaluative +nonevent +nonevents +nonevidence +nonexclusive +nonexecutive +nonexempt +nonexistence +nonexistent +nonexistential +nonexotic +nonexpendable +nonexperimental +nonexpert +nonexplanatory +nonexploitation +nonexploitative +nonexploitive +nonexplosive +nonexplosives +nonexposed +nonextant +nonfact +nonfactor +nonfactual +nonfaculty +nonfading +nonfamilial +nonfamily +nonfan +nonfarm +nonfarmer +nonfat +nonfatal +nonfattening +nonfatty +nonfeasance +nonfederal +nonfederated +nonfeminist +nonferrous +nonfiction +nonfictional +nonfigurative +nonfilamentous +nonfilterable +nonfinal +nonfinancial +nonfinite +nonfissionable +nonflammability +nonflammable +nonflowering +nonfluency +nonfluorescent +nonflying +nonfood +nonforfeitable +nonforfeiture +nonformal +nonfossil +nonfraternization +nonfreezing +nonfrivolous +nonfrozen +nonfuel +nonfulfillment +nonfunctional +nonfunctioning +nongame +nongaseous +nongay +nongenetic +nongenital +nongeometrical +nonghetto +nonglamorous +nonglare +nongolfer +nongonococcal +nongovernment +nongovernmental +nongraded +nongraduate +nongrammatical +nongranular +nongravitational +nongreasy +nongreen +nongregarious +nongrowing +nongrowth +nonguest +nonhalogenated +nonhandicapped +nonhappening +nonhardy +nonharmonic +nonhazardous +nonheme +nonhemolytic +nonhereditary +nonhero +nonheroes +nonhierarchical +nonhistone +nonhistorical +nonhome +nonhomogeneous +nonhomologous +nonhomosexual +nonhormonal +nonhospital +nonhospitalized +nonhostile +nonhousing +nonhuman +nonhumans +nonhunter +nonhunting +nonhygroscopic +nonhysterical +nonideal +nonidentical +nonidentity +nonideological +nonillion +nonillions +nonillionth +nonillionths +nonimage +nonimitative +nonimmigrant +nonimmigrants +nonimmune +nonimpact +nonimplication +nonimportation +noninclusion +nonincreasing +nonincumbent +nonindependence +nonindigenous +nonindividual +noninductive +nonindustrial +nonindustrialized +nonindustry +noninfected +noninfectious +noninfective +noninfested +noninflammable +noninflammatory +noninflationary +noninflectional +noninfluence +noninformation +noninitial +noninitiate +noninjury +noninsect +noninsecticidal +noninstallment +noninstitutional +noninstitutionalized +noninstructional +noninstrumental +noninsurance +noninsured +nonintegral +nonintegrated +nonintellectual +noninteracting +noninteractive +noninterchangeable +nonintercourse +noninterest +noninterference +nonintersecting +nonintervention +noninterventionist +noninterventionists +nonintimidating +nonintoxicant +nonintoxicating +nonintrospective +nonintrusive +nonintuitive +noninvasive +noninvolved +noninvolvement +nonionic +nonionizing +nonirradiated +nonirrigated +nonirritant +nonirritating +nonissue +nonissues +nonjoinder +nonjoinders +nonjoiner +nonjudgmental +nonjudicial +nonjuring +nonjuror +nonjurors +nonjury +nonjusticiable +nonkosher +nonlabor +nonlandowner +nonlanguage +nonlawyer +nonleaded +nonleague +nonlegal +nonlegume +nonleguminous +nonlethal +nonlexical +nonlibrarian +nonlibrary +nonlife +nonlineal +nonlinear +nonlinearities +nonlinearity +nonlinearly +nonlinguistic +nonliquid +nonliteral +nonliterary +nonliterate +nonliterates +nonliving +nonlocal +nonlogical +nonluminous +nonmagnetic +nonmainstream +nonmajor +nonmalignant +nonmalleable +nonmammalian +nonmanagement +nonmanagerial +nonmandatory +nonmanual +nonmanufacturing +nonmarital +nonmarket +nonmarketable +nonmaterial +nonmaterialistic +nonmathematical +nonmatriculated +nonmeaningful +nonmeasurable +nonmeat +nonmechanical +nonmechanistic +nonmedical +nonmeeting +nonmember +nonmembers +nonmembership +nonmental +nonmercurial +nonmetal +nonmetallic +nonmetals +nonmetameric +nonmetaphorical +nonmetric +nonmetrical +nonmetro +nonmetropolitan +nonmicrobial +nonmigrant +nonmigratory +nonmilitant +nonmilitary +nonmimetic +nonminority +nonmobile +nonmolecular +nonmonetarist +nonmonetary +nonmoney +nonmonogamous +nonmoral +nonmotile +nonmotility +nonmotorized +nonmoving +nonmunicipal +nonmusic +nonmusical +nonmusician +nonmutant +nonmyelinated +nonmystical +nonnarrative +nonnational +nonnative +nonnatural +nonnecessity +nonnegative +nonnegligent +nonnegotiable +nonnetwork +nonneural +nonnews +nonnitrogenous +nonnormative +nonnovel +nonnuclear +nonnucleated +nonnumeric +nonnumerical +nonnumerically +nonnutritious +nonnutritive +nonobjective +nonobjectivism +nonobjectivist +nonobjectivists +nonobjectivity +nonobligatory +nonobscene +nonobservance +nonobservances +nonobservant +nonobservantly +nonobvious +nonoccupational +nonoccurrence +nonofficial +nonohmic +nonoily +nonoperatic +nonoperating +nonoperational +nonoperative +nonoptimal +nonorganic +nonorgasmic +nonorthodox +nonoverlapping +nonowner +nonoxidizing +nonoxynol +nonpaid +nonpainful +nonparallel +nonparametric +nonparasitic +nonpareil +nonpareils +nonparticipant +nonparticipating +nonparticipation +nonparticipatory +nonpartisan +nonpartisans +nonpartisanship +nonpartisanships +nonparty +nonpasserine +nonpassive +nonpast +nonpathogenic +nonpaying +nonpayment +nonpeak +nonperformance +nonperformer +nonperforming +nonperishable +nonpermanent +nonpermissive +nonpersistent +nonperson +nonpersonal +nonpersons +nonpetroleum +nonphilosopher +nonphilosophical +nonphonemic +nonphonetic +nonphosphate +nonphotographic +nonphysical +nonphysician +nonplanar +nonplastic +nonplay +nonplaying +nonplus +nonplused +nonpluses +nonplusing +nonplussed +nonplusses +nonplussing +nonpoetic +nonpoint +nonpoisonous +nonpolar +nonpolarizable +nonpolice +nonpolitical +nonpolitically +nonpolitician +nonpolluting +nonpoor +nonporous +nonpossession +nonpractical +nonpracticing +nonpregnant +nonprescription +nonprime +nonprint +nonprinting +nonproblem +nonprocedural +nonproducing +nonproductive +nonproductively +nonproductiveness +nonproductives +nonprofessional +nonprofessionally +nonprofessionals +nonprofessorial +nonprofit +nonprogram +nonprogrammer +nonprogressive +nonproliferation +nonproprietary +nonpros +nonprossed +nonprosses +nonprossing +nonprotein +nonpsychiatric +nonpsychiatrist +nonpsychological +nonpsychotic +nonpublic +nonpunitive +nonpurposive +nonquantifiable +nonquantitative +nonracial +nonracially +nonradioactive +nonrailroad +nonrandom +nonrandomness +nonrated +nonrational +nonreactive +nonreactor +nonreader +nonreaders +nonreading +nonrealistic +nonreappointment +nonreceipt +nonreciprocal +nonrecognition +nonrecombinant +nonrecourse +nonrecoverable +nonrectangular +nonrecurrent +nonrecurring +nonrecursive +nonrecyclable +nonreducing +nonredundant +nonrefillable +nonreflecting +nonrefundable +nonregulated +nonregulation +nonrelative +nonrelativistic +nonrelativistically +nonrelevant +nonreligious +nonrenewable +nonrenewal +nonrepayable +nonrepresentational +nonrepresentationalism +nonrepresentative +nonreproductive +nonresidence +nonresidency +nonresident +nonresidential +nonresidents +nonresistance +nonresistances +nonresistant +nonresistants +nonresonant +nonrespondent +nonresponder +nonresponse +nonresponsive +nonrestricted +nonrestrictive +nonretractile +nonretroactive +nonreturnable +nonreusable +nonreversible +nonrevolutionary +nonrigid +nonrioter +nonrioting +nonromantic +nonrotating +nonroutine +nonroyal +nonrubber +nonruling +nonruminant +nonsalable +nonsaline +nonsaponifiable +nonscheduled +nonschizophrenic +nonschool +nonscience +nonscientific +nonscientist +nonscientists +nonseasonal +nonsecretor +nonsecretors +nonsecretory +nonsectarian +nonsectarianism +nonsecure +nonsedimentable +nonsegregated +nonsegregation +nonselected +nonselective +nonself +nonsensational +nonsense +nonsensical +nonsensicality +nonsensically +nonsensicalness +nonsensitive +nonsensuous +nonsentence +nonseptate +nonsequential +nonserious +nonsexist +nonsexual +nonshrink +nonshrinkable +nonsigner +nonsignificance +nonsignificant +nonsignificantly +nonsimultaneous +nonsingular +nonsinkable +nonskater +nonsked +nonskeds +nonskeletal +nonskid +nonskier +nonslip +nonsmoker +nonsmokers +nonsmoking +nonsocial +nonsocialist +nonsolar +nonsolid +nonsolution +nonspatial +nonspeaker +nonspeaking +nonspecialist +nonspecialists +nonspecific +nonspecifically +nonspectacular +nonspeculative +nonspeech +nonspherical +nonsporting +nonstandard +nonstarter +nonstarters +nonstationary +nonstatistical +nonsteady +nonsteroid +nonsteroidal +nonstick +nonstop +nonstory +nonstrategic +nonstructural +nonstructured +nonstudent +nonstyle +nonsubject +nonsubjective +nonsubsidized +nonsuccess +nonsuch +nonsuches +nonsugar +nonsuit +nonsuited +nonsuiting +nonsuits +nonsuperimposable +nonsupervisory +nonsupport +nonsurgical +nonswimmer +nonswimmers +nonsyllabic +nonsymbolic +nonsymmetric +nonsymmetrical +nonsynchronous +nonsystem +nonsystematic +nonsystemic +nonsystems +nontarget +nontariff +nontaxable +nonteaching +nontechnical +nontemporal +nontenured +nonterminal +nonterminating +nontheatrical +nontheist +nontheistic +nontheological +nontheoretical +nontherapeutic +nonthermal +nonthinking +nonthreatening +nontidal +nontitle +nontobacco +nontonal +nontotalitarian +nontoxic +nontraditional +nontraditionally +nontransferable +nontransparent +nontreatment +nontrivial +nontropical +nonturbulent +nontypical +nonunanimous +nonuniform +nonuniformity +nonunion +nonunionized +nonunique +nonuniqueness +nonuniversal +nonuniversity +nonuple +nonuples +nonurban +nonurgent +nonuse +nonuser +nonusers +nonutilitarian +nonutility +nonutopian +nonvalid +nonvalidity +nonvanishing +nonvascular +nonvector +nonvectors +nonvegetarian +nonvenomous +nonverbal +nonverbally +nonveteran +nonviable +nonviewer +nonvintage +nonviolence +nonviolent +nonviolently +nonviral +nonvirgin +nonviscous +nonvisual +nonvocal +nonvocational +nonvolatile +nonvolcanic +nonvoluntary +nonvoter +nonvoters +nonvoting +nonwar +nonwestern +nonwhite +nonwhites +nonwinning +nonwoody +nonword +nonwords +nonwork +nonworker +nonworking +nonwoven +nonwovens +nonwriter +nonyellowing +nonylphenylhydroxynonaoxyethylene +nonzero +noodle +noodled +noodles +noodling +nook +nooks +nooky +noon +noonday +nooning +noons +noontide +noontime +noose +noosed +nooses +noosing +noosphere +nootka +nootkas +nopal +nopals +nope +nor +nor'easter +nor'easters +nor'wester +nor'westers +noradrenalin +noradrenaline +noradrenalins +noradrenergic +noradrenergically +nordic +nordics +nordkyn +nordmann +norepinephrine +norepinephrines +norethindrone +norethindrones +norfolk +nori +noria +norias +noricum +noris +norite +norites +noritic +norland +norm +norma +normal +normalcy +normality +normalizable +normalization +normalizations +normalize +normalized +normalizer +normalizers +normalizes +normalizing +normally +normals +norman +normande +normandy +normans +normative +normatively +normativeness +normed +normocyte +normocytes +normotensive +normotensives +normothermia +normothermic +norms +norn +nornicotine +nornicotines +norns +norrköping +norse +norseman +norsemen +north +northamptonshire +northanger +northbound +northeast +northeaster +northeasterly +northeastern +northeasterner +northeasterners +northeasternmost +northeasters +northeastward +northeastwardly +northeastwards +norther +northerlies +northerly +northern +northerner +northerners +northernmost +northernness +northers +northing +northings +northland +northlander +northlanders +northlands +northman +northmen +northrop +northumberland +northumbria +northumbrian +northumbrians +northward +northwardly +northwards +northwest +northwester +northwesterly +northwestern +northwesterner +northwesterners +northwesternmost +northwesters +northwestward +northwestwardly +northwestwards +nortriptyline +nortriptylines +norway +norwegian +norwegians +norwich +nose +nosebag +nosebags +noseband +nosebands +nosebleed +nosebleeds +nosed +nosedive +nosedives +nosegay +nosegays +noseguard +noseguards +nosepiece +nosepieces +noser +noses +nosewheel +nosewheels +nosey +nosh +noshed +nosher +noshers +noshes +noshing +nosier +nosiest +nosily +nosiness +nosing +nosings +nosocomial +nosographer +nosographers +nosographic +nosographical +nosography +nosologic +nosological +nosologically +nosologies +nosologist +nosologists +nosology +nostalgia +nostalgic +nostalgically +nostalgist +nostalgists +nostoc +nostocs +nostra +nostradamus +nostril +nostrils +nostrum +nostrums +nosy +not +nota +notabilities +notability +notable +notableness +notables +notably +notarial +notarially +notaries +notarization +notarizations +notarize +notarized +notarizes +notarizing +notary +notate +notated +notates +notating +notation +notational +notations +notch +notchback +notchbacks +notched +notches +notching +note +notebook +notebooks +notecase +notecases +noted +notedly +notedness +noteless +notepad +notepads +notepaper +noter +noters +notes +noteworthier +noteworthiest +noteworthily +noteworthiness +noteworthy +nothing +nothingism +nothingness +nothings +notice +noticeability +noticeable +noticeably +noticed +noticer +noticers +notices +noticing +notifiable +notification +notifications +notified +notifier +notifiers +notifies +notify +notifying +noting +notion +notional +notionality +notionally +notions +notochord +notochordal +notochords +notogaea +notogea +notoriety +notorious +notoriously +notoriousness +notornis +nottinghamshire +notum +notwithstanding +nouakchott +nougat +nougats +nought +noughts +noumena +noumenal +noumenon +nouméa +noun +nouns +nourish +nourished +nourisher +nourishers +nourishes +nourishing +nourishment +nourishments +nous +nouveau +nouveaux +nouvelle +nova +novaculite +novaculites +novae +novalike +novas +novation +novations +novaya +novel +novelette +novelettes +novelettish +novelist +novelistic +novelistically +novelists +novelization +novelizations +novelize +novelized +novelizer +novelizers +novelizes +novelizing +novella +novellas +novelle +novelly +novels +novelties +novelty +november +novembers +novemdecillion +novena +novenae +novenas +novercal +novgorod +novice +novices +noviciate +noviciates +novitiate +novitiates +novo +novobiocin +novobiocins +novocain +novocaine +novocaines +now +nowadays +noway +noways +nowhere +nowhither +nowise +nowness +noxious +noxiously +noxiousness +nozzle +nozzles +noël +noëls +ns +nt +nth +nu +nuance +nuanced +nuances +nub +nuba +nubbier +nubbiest +nubbin +nubbins +nubble +nubbles +nubbly +nubby +nubia +nubian +nubians +nubile +nubility +nubs +nucellar +nucelli +nucellus +nucha +nuchal +nuchas +nuclear +nuclearization +nuclearizations +nuclearize +nuclearized +nuclearizes +nuclearizing +nuclease +nucleases +nucleate +nucleated +nucleates +nucleating +nucleation +nucleations +nucleator +nucleators +nuclei +nucleic +nuclein +nucleinic +nucleins +nucleocapsid +nucleocapsids +nucleohistone +nucleohistones +nucleoid +nucleoids +nucleolar +nucleolate +nucleolated +nucleoli +nucleolus +nucleon +nucleonic +nucleonics +nucleons +nucleophile +nucleophiles +nucleophilic +nucleophilically +nucleophilicity +nucleoplasm +nucleoplasmatic +nucleoplasmic +nucleoplasms +nucleoprotein +nucleoproteins +nucleoside +nucleosides +nucleosomal +nucleosome +nucleosomes +nucleosynthesis +nucleosynthetic +nucleotidase +nucleotidases +nucleotide +nucleotides +nucleus +nucleuses +nuclide +nuclides +nuclidic +nude +nudely +nudeness +nuder +nudes +nudest +nudge +nudged +nudger +nudgers +nudges +nudging +nudibranch +nudibranches +nudibranchian +nudibranchians +nudibranchiate +nudibranchiates +nudism +nudist +nudists +nudity +nudnick +nudnicks +nudnik +nudniks +nudzh +nudzhed +nudzhes +nudzhing +nudzhs +nugatory +nugget +nuggets +nuisance +nuisances +nuke +nuked +nukes +nuking +null +nullah +nullahs +nullarbor +nulled +nullification +nullificationist +nullificationists +nullifications +nullified +nullifier +nullifiers +nullifies +nullify +nullifying +nulling +nullipara +nulliparas +nulliparous +nullities +nullity +nulls +numb +numbed +number +numberable +numbered +numberer +numberers +numbering +numberings +numberless +numbers +numbest +numbfish +numbfishes +numbing +numbingly +numbly +numbness +numbs +numbskull +numbskulls +numen +numerable +numeracy +numeral +numerally +numerals +numerary +numerate +numerated +numerates +numerating +numeration +numerations +numerator +numerators +numeric +numerical +numerically +numerics +numero +numerological +numerologist +numerologists +numerology +numerous +numerously +numerousness +numidia +numidian +numidians +numina +numinous +numinousness +numismatic +numismatically +numismatics +numismatist +numismatists +nummular +nummulite +nummulites +nummulitic +numskull +numskulls +nun +nunatak +nunataks +nunc +nunchaku +nunchakus +nunciature +nunciatures +nuncio +nuncios +nuncle +nuncles +nuncupative +nunivak +nunlike +nunneries +nunnery +nuns +nuptial +nuptiality +nuptially +nuptials +nurd +nurds +nuremberg +nureyev +nuristan +nuristani +nuristanis +nurse +nursed +nursemaid +nursemaids +nurser +nurseries +nursers +nursery +nurseryman +nurserymen +nurses +nursing +nursling +nurslings +nurturance +nurturances +nurturant +nurture +nurtured +nurturer +nurturers +nurtures +nurturing +nut +nutate +nutated +nutates +nutating +nutation +nutational +nutations +nutcase +nutcases +nutcracker +nutcrackers +nutgall +nutgalls +nuthatch +nuthatches +nuthouse +nuthouses +nutlet +nutlets +nutlike +nutmeat +nutmeats +nutmeg +nutmegs +nutpick +nutpicks +nutria +nutrias +nutrient +nutrients +nutriment +nutrimental +nutriments +nutrition +nutritional +nutritionally +nutritionist +nutritionists +nutritious +nutritiously +nutritiousness +nutritive +nutritively +nuts +nutsedge +nutshell +nutshells +nutted +nutter +nutters +nuttier +nuttiest +nuttily +nuttiness +nutting +nutty +nux +nuzzle +nuzzled +nuzzler +nuzzlers +nuzzles +nuzzling +nw +nyala +nyalas +nyanja +nyasa +nyasaland +nyctalopia +nyctalopias +nyctalopic +nyctitropic +nyctitropism +nyctitropisms +nyctophobia +nyctophobias +nyet +nylon +nylons +nymph +nympha +nymphae +nymphal +nymphalid +nymphalids +nymphet +nymphets +nymphette +nymphettes +nympho +nympholepsies +nympholepsy +nympholept +nympholeptic +nympholepts +nymphomania +nymphomaniac +nymphomaniacal +nymphomaniacs +nymphos +nymphs +nynorsk +nystagmic +nystagmus +nystagmuses +nystatin +nystatins +náxos +née +névé +nîmes +nürnberg +o +o'clock +o'er +o'neill +o'odham +o'odhams +oaf +oafish +oafishly +oafishness +oafs +oahu +oak +oaken +oakland +oakley +oakleys +oakmoss +oakmosses +oaks +oakum +oar +oared +oarfish +oarfishes +oaring +oarless +oarlock +oarlocks +oars +oarsman +oarsmanship +oarsmen +oarswoman +oarswomen +oases +oasis +oast +oasts +oat +oatcake +oatcakes +oaten +oater +oaters +oath +oaths +oatmeal +oats +obadiah +obbligati +obbligato +obbligatos +obcompressed +obcordate +obduracy +obdurate +obdurately +obdurateness +obeah +obeahs +obedience +obedient +obediently +obeisance +obeisances +obeisant +obeisantly +obeli +obelia +obelias +obeliscal +obelisk +obeliskoid +obelisks +obelize +obelized +obelizes +obelizing +obelus +obento +obentos +oberammergau +oberon +obese +obesely +obeseness +obesity +obey +obeyed +obeyer +obeyers +obeying +obeys +obfuscate +obfuscated +obfuscates +obfuscating +obfuscation +obfuscations +obfuscatory +obi +obie +obies +obis +obit +obiter +obits +obituaries +obituarist +obituarists +obituary +object +objected +objectification +objectifications +objectified +objectifier +objectifiers +objectifies +objectify +objectifying +objecting +objection +objectionability +objectionable +objectionableness +objectionably +objections +objective +objectively +objectiveness +objectives +objectivism +objectivist +objectivistic +objectivists +objectivity +objectivization +objectivizations +objectivize +objectivized +objectivizes +objectivizing +objectless +objectlessness +objector +objectors +objects +objet +objets +objurgate +objurgated +objurgates +objurgating +objurgation +objurgations +objurgatorily +objurgatory +oblanceolate +oblast +oblasti +oblasts +oblate +oblately +oblateness +oblates +oblation +oblational +oblations +oblatory +obligable +obligate +obligated +obligately +obligates +obligati +obligating +obligation +obligational +obligations +obligato +obligator +obligatorily +obligators +obligatory +obligatos +oblige +obliged +obligee +obligees +obliger +obligers +obliges +obliging +obligingly +obligingness +obligor +obligors +oblique +obliqued +obliquely +obliqueness +obliques +obliquing +obliquities +obliquitous +obliquity +obliterate +obliterated +obliterates +obliterating +obliteration +obliterations +obliterative +obliterator +obliterators +oblivion +oblivious +obliviously +obliviousness +oblong +oblongata +oblongatae +oblongatas +oblongs +obloquies +obloquy +obnoxious +obnoxiously +obnoxiousness +obnubilate +obnubilated +obnubilates +obnubilating +obnubilation +obnubilations +oboe +oboes +oboist +oboists +obol +oboli +obols +obolus +obovate +obovoid +obscene +obscenely +obsceneness +obscener +obscenest +obscenities +obscenity +obscura +obscurant +obscurantic +obscurantism +obscurantist +obscurantists +obscurants +obscuras +obscuration +obscurations +obscure +obscured +obscurely +obscureness +obscurer +obscurers +obscures +obscurest +obscuring +obscurities +obscurity +obsequies +obsequious +obsequiously +obsequiousness +obsequy +observability +observable +observables +observably +observance +observances +observant +observantly +observants +observation +observational +observationally +observations +observatories +observatory +observe +observed +observer +observers +observes +observing +observingly +obsess +obsessed +obsesses +obsessing +obsession +obsessional +obsessionally +obsessions +obsessive +obsessively +obsessiveness +obsessives +obsessor +obsessors +obsidian +obsidians +obsolesce +obsolesced +obsolescence +obsolescent +obsolescently +obsolesces +obsolescing +obsolete +obsoleted +obsoletely +obsoleteness +obsoletes +obsoleting +obsoletism +obstacle +obstacles +obstante +obstetric +obstetrical +obstetrically +obstetrician +obstetricians +obstetrics +obstinacies +obstinacy +obstinate +obstinately +obstinateness +obstreperous +obstreperously +obstreperousness +obstruct +obstructed +obstructer +obstructers +obstructing +obstruction +obstructionism +obstructionist +obstructionistic +obstructionists +obstructions +obstructive +obstructively +obstructiveness +obstructor +obstructors +obstructs +obstruent +obstruents +obtain +obtainability +obtainable +obtained +obtainer +obtainers +obtaining +obtainment +obtainments +obtains +obtect +obtected +obtest +obtestation +obtestations +obtested +obtesting +obtests +obtrude +obtruded +obtruder +obtruders +obtrudes +obtruding +obtrusion +obtrusions +obtrusive +obtrusively +obtrusiveness +obtund +obtunded +obtundent +obtunding +obtundity +obtunds +obturate +obturated +obturates +obturating +obturation +obturations +obturator +obturators +obtuse +obtusely +obtuseness +obtuser +obtusest +obverse +obversely +obverses +obversion +obversions +obvert +obverted +obverting +obverts +obviate +obviated +obviates +obviating +obviation +obviations +obviator +obviators +obvious +obviously +obviousness +oca +ocarina +ocarinas +ocas +occam +occasion +occasional +occasionally +occasioned +occasioning +occasions +occident +occidental +occidentalism +occidentalization +occidentalizations +occidentalize +occidentalized +occidentalizes +occidentalizing +occidentally +occidentals +occipita +occipital +occipitally +occipitals +occiput +occiputs +occitan +occitanian +occitans +occlude +occluded +occludent +occludes +occluding +occlusal +occlusion +occlusions +occlusive +occlusives +occult +occultation +occultations +occulted +occulter +occulters +occulting +occultism +occultist +occultists +occultly +occultness +occults +occupancies +occupancy +occupant +occupants +occupation +occupational +occupationally +occupations +occupied +occupier +occupiers +occupies +occupy +occupying +occur +occurred +occurrence +occurrences +occurrent +occurring +occurs +ocean +oceanaria +oceanarium +oceanariums +oceanaut +oceanauts +oceanfront +oceangoing +oceania +oceanian +oceanians +oceanic +oceanid +oceanides +oceanids +oceanographer +oceanographers +oceanographic +oceanographical +oceanographically +oceanography +oceanologic +oceanological +oceanologically +oceanologist +oceanologists +oceanology +oceans +oceanus +ocellar +ocellate +ocellated +ocellation +ocellations +ocelli +ocellus +ocelot +ocelots +ocher +ocherous +ochers +ochery +ochlocracies +ochlocracy +ochlocrat +ochlocratic +ochlocratical +ochlocratically +ochlocrats +ochlophobia +ochlophobic +ochlophobics +ochre +ochreous +ochres +ockham +ocotillo +ocotillos +ocrea +ocreae +octad +octadic +octads +octagon +octagonal +octagonally +octagons +octahedra +octahedral +octahedrally +octahedron +octahedrons +octal +octamerous +octameter +octameters +octandrious +octane +octans +octant +octantal +octants +octapeptide +octapeptides +octastyle +octaval +octavalent +octave +octaves +octavian +octavius +octavo +octavos +octennial +octet +octets +octillion +octillions +octillionth +octillionths +october +octobers +octobrist +octobrists +octocentenary +octodecillion +octodecimo +octodecimos +octogenarian +octogenarians +octometer +octometers +octonaries +octonary +octopi +octoploid +octoploids +octopod +octopodous +octopods +octopus +octopuses +octoroon +octoroons +octosyllabic +octosyllabics +octosyllable +octosyllables +octothorp +octothorps +octuple +octupled +octuples +octupling +octylcyanoacrylate +ocular +ocularist +ocularists +oculars +oculi +oculist +oculists +oculogyric +oculomotor +oculus +odalisk +odalisks +odalisque +odalisques +odd +oddball +oddballs +odder +oddest +oddish +oddities +oddity +oddjobber +oddjobbers +oddly +oddment +oddments +oddness +odds +oddsmaker +oddsmakers +ode +odea +odense +odeon +oder +odes +odessa +odeum +odic +odin +odious +odiously +odiousness +odist +odists +odium +odograph +odographs +odometer +odometers +odometry +odonate +odonates +odontalgia +odontalgias +odontalgic +odontoblast +odontoblastic +odontoblasts +odontoglossum +odontoid +odontological +odontologically +odontologist +odontologists +odontology +odontophoral +odontophore +odontophores +odontophorine +odontophorous +odor +odorant +odorants +odored +odoriferous +odoriferously +odoriferousness +odorize +odorized +odorizes +odorizing +odorless +odorlessly +odorlessness +odorous +odorously +odorousness +odors +odyssean +odysseus +odyssey +odysseys +oecumenical +oedema +oedipal +oedipally +oedipus +oeil +oeillade +oeillades +oeils +oenological +oenologist +oenologists +oenology +oenomel +oenomels +oenone +oenophile +oenophiles +oersted +oersteds +oesophagi +oesophagus +oestrogen +oestrogens +oestrus +oeuvre +oeuvres +of +ofay +off +offa +offal +offbeat +offcast +offcasts +offcut +offcuts +offed +offenbach +offence +offences +offend +offended +offender +offenders +offending +offends +offense +offenseless +offenses +offensive +offensively +offensiveness +offensives +offer +offered +offerer +offerers +offering +offerings +offeror +offerors +offers +offertories +offertory +offhand +offhanded +offhandedly +offhandedness +office +officeholder +officeholders +officemate +officemates +officer +officered +officering +officers +offices +official +officialdom +officialdoms +officialese +officialeses +officialism +officially +officials +officiant +officiants +officiaries +officiary +officiate +officiated +officiates +officiating +officiation +officiations +officiator +officiators +officinal +officinally +officinals +officio +officious +officiously +officiousness +offing +offish +offishly +offishness +offline +offload +offloaded +offloading +offloads +offprint +offprinted +offprinting +offprints +offs +offscouring +offscourings +offscreen +offset +offsets +offsetting +offshoot +offshoots +offshore +offside +offsides +offspring +offsprings +offstage +offtrack +offy +oft +often +oftener +oftenest +oftentimes +ofttimes +ogam +ogams +ogee +ogees +ogham +oghamic +oghamist +oghamists +oghams +ogival +ogive +ogives +oglala +oglalas +ogle +ogled +ogler +oglers +ogles +ogling +ogre +ogreish +ogres +ogress +ogresses +oh +ohia +ohio +ohioan +ohioans +ohm +ohmic +ohmically +ohmmeter +ohmmeters +ohms +oho +oidia +oidium +oil +oilbird +oilbirds +oilcan +oilcans +oilcloth +oilcloths +oiled +oiler +oilers +oilfield +oilfields +oilier +oiliest +oilily +oiliness +oiling +oilman +oilmen +oilpaper +oilpapers +oils +oilseed +oilseeds +oilskin +oilskins +oilstone +oilstones +oily +oink +oinked +oinking +oinks +ointment +ointments +oireachtas +oiticica +oiticicas +ojibwa +ojibwas +ojibway +ojibways +ok +ok'd +ok'ing +ok's +oka +okapi +okapis +okas +okay +okayed +okaying +okays +okeechobee +okeydoke +okeydokey +okhotsk +okie +okies +okinawa +oklahoma +oklahoman +oklahomans +okra +okras +oks +oktoberfest +olaf +old +olden +oldenburg +older +oldest +oldfangled +oldie +oldies +oldish +oldness +olds +oldsquaw +oldsquaws +oldster +oldsters +oldwife +oldwives +olea +oleaginous +oleaginously +oleaginousness +oleander +oleanders +oleandomycin +oleaster +oleasters +oleate +oleates +olecranal +olecranial +olecranian +olecranon +olecranons +olefin +olefinic +olefins +oleic +olein +oleine +oleines +oleins +oleo +oleograph +oleographer +oleographers +oleographic +oleographs +oleography +oleomargarine +oleomargarines +oleoresin +oleoresinous +oleoresins +oleos +oleum +oleums +olfaction +olfactometer +olfactometers +olfactometric +olfactometry +olfactory +olicook +olicooks +oligarch +oligarchic +oligarchical +oligarchies +oligarchs +oligarchy +oligocene +oligochaete +oligochaetes +oligochaetous +oligochete +oligochetes +oligoclase +oligoclases +oligodendrocyte +oligodendrocytes +oligodendroglia +oligodendroglial +oligodendroglias +oligomer +oligomeric +oligomerization +oligomerizations +oligomers +oligonucleotide +oligonucleotides +oligophagous +oligophagy +oligopolies +oligopolistic +oligopoly +oligopsonies +oligopsonistic +oligopsony +oligosaccharide +oligosaccharides +oligotrophic +oligotrophy +olingo +olingos +olio +olios +olivaceous +olive +olivenite +olivenites +oliver +olives +olivewood +olivewoods +olivia +olivier +olivine +olivinic +olivinitic +olla +ollas +olmec +olmecs +ologies +ology +ololiuqui +oloroso +olorosos +olympia +olympiad +olympiads +olympian +olympians +olympic +olympics +olympus +olé +om +omaha +omahas +oman +omani +omanis +omar +omasa +omasum +omayyad +omber +ombre +ombudsman +ombudsmanship +ombudsmen +ombudsperson +ombudspersons +ombudspersonship +ombudswoman +ombudswomanship +ombudswomen +omdurman +omega +omegas +omelet +omelets +omelette +omelettes +omen +omened +omening +omens +omenta +omental +omentum +omentums +omer +omers +omertà +omicron +omicrons +ominous +ominously +ominousness +omissible +omission +omissions +omissive +omit +omits +omitted +omitting +ommatidia +ommatidial +ommatidium +ommatophore +ommatophores +ommatophorous +ommiad +omnibus +omnibuses +omnicompetence +omnicompetent +omnidirectional +omnifarious +omnifariously +omnifariousness +omnificent +omnipotence +omnipotency +omnipotent +omnipotently +omnipotents +omnipresence +omnipresent +omnirange +omniranges +omniscience +omnisciency +omniscient +omnisciently +omniscients +omnium +omnivore +omnivores +omnivorous +omnivorously +omnivorousness +omphali +omphalos +omphaloskepsis +omsk +on +onager +onagers +onanism +onanist +onanistic +onanists +onboard +once +onchocerciasis +oncidium +oncidiums +oncogene +oncogenes +oncogenesis +oncogenic +oncogenicity +oncologic +oncological +oncologist +oncologists +oncology +oncoming +oncornavirus +oncornaviruses +one +one's +onefold +oneida +oneidas +oneiric +oneirically +oneiromancer +oneiromancers +oneiromancy +oneness +onerous +onerously +onerousness +ones +oneself +onetime +ongoing +ongoingness +onion +onions +onionskin +onionskins +oniony +onium +onlay +onlays +online +onload +onloaded +onloading +onloads +onlooker +onlookers +onlooking +only +onomastic +onomastically +onomastician +onomasticians +onomastics +onomatologist +onomatologists +onomatology +onomatopoeia +onomatopoeias +onomatopoeic +onomatopoeically +onomatopoetic +onomatopoetically +onondaga +onondagan +onondagas +onrush +onrushes +onrushing +onset +onsets +onshore +onside +onsite +onslaught +onslaughts +onstage +onstream +ontario +ontic +ontically +onto +ontogeneses +ontogenesis +ontogenetic +ontogenetically +ontogenies +ontogeny +ontological +ontologically +ontologist +ontologists +ontology +onus +onuses +onward +onwards +onycholyses +onycholysis +onychophoran +onychophorans +onyx +onyxes +oocyst +oocysts +oocyte +oocytes +oodles +oogamete +oogametes +oogamous +oogamy +oogenesis +oogenetic +oogonia +oogonial +oogonium +oogoniums +ooh +oohed +oohing +oohs +oolemma +oolemmas +oolite +oolites +oolith +ooliths +oolitic +oologic +oological +oologically +oologist +oologists +oology +oolong +oolongs +oomiak +oomiaks +oompah +oompahs +oomph +oop +oophorectomies +oophorectomy +oophoritis +oophoritises +oops +oort +oosphere +oospheres +oospore +oospores +oosporic +oosporous +ootheca +oothecae +oothecal +ootid +ootids +ooze +oozed +oozes +oozier +ooziest +oozily +ooziness +oozing +oozy +op +opacifier +opacifiers +opacities +opacity +opah +opahs +opal +opalesce +opalesced +opalescence +opalescent +opalescently +opalesces +opalescing +opaline +opallesces +opals +opaque +opaquely +opaqueness +opaques +ope +oped +open +openability +openable +opencast +opened +opener +openers +openest +openhanded +openhandedly +openhandedness +openhearted +openheartedly +openheartedness +opening +openings +openly +openmouthed +openmouthedly +openmouthedness +openness +opens +openwork +opera +operability +operable +operably +operagoer +operagoers +operagoing +operand +operandi +operands +operant +operantly +operants +operas +operate +operated +operates +operatic +operatically +operatics +operating +operation +operational +operationalism +operationalist +operationalistic +operationalists +operationalize +operationalized +operationalizes +operationalizing +operationally +operationism +operationist +operationists +operations +operative +operatively +operativeness +operatives +operator +operatorless +operators +opercula +opercular +opercularly +operculate +operculated +operculum +operculums +operetta +operettas +operettist +operettists +operon +operons +operose +operosely +operoseness +opes +ophelia +ophidian +ophidians +ophiolite +ophiolites +ophiological +ophiologist +ophiologists +ophiology +ophiophagous +ophir +ophite +ophites +ophitic +ophiuchus +ophiuroid +ophiuroids +ophthalmia +ophthalmias +ophthalmic +ophthalmitis +ophthalmitises +ophthalmologic +ophthalmological +ophthalmologically +ophthalmologist +ophthalmologists +ophthalmology +ophthalmoscope +ophthalmoscopes +ophthalmoscopic +ophthalmoscopical +ophthalmoscopy +opiate +opiated +opiates +opiating +opine +opined +opines +oping +opining +opinion +opinionated +opinionatedly +opinionatedness +opinionative +opinionatively +opinionativeness +opinioned +opinions +opioid +opioids +opisthobranch +opisthobranchs +opisthognathism +opisthognathous +opium +oporto +opossum +opossums +opponency +opponent +opponents +opportune +opportunely +opportuneness +opportunism +opportunist +opportunistic +opportunistically +opportunists +opportunities +opportunity +opposability +opposable +oppose +opposed +opposeless +opposer +opposers +opposes +opposing +opposite +oppositely +oppositeness +opposites +opposition +oppositional +oppositionist +oppositionists +oppositions +oppress +oppressed +oppresses +oppressing +oppression +oppressions +oppressive +oppressively +oppressiveness +oppressor +oppressors +opprobrious +opprobriously +opprobriousness +opprobrium +oppugn +oppugned +oppugner +oppugners +oppugning +oppugns +opsin +opsins +opsonic +opsonin +opsonins +opsonization +opsonizations +opsonize +opsonized +opsonizes +opsonizing +opt +optative +optatively +optatives +opted +optic +optical +optically +optician +opticians +optics +optima +optimal +optimality +optimally +optimism +optimist +optimistic +optimistically +optimists +optimization +optimizations +optimize +optimized +optimizer +optimizers +optimizes +optimizing +optimum +optimums +opting +option +optional +optionality +optionally +optioned +optioning +options +optoelectronic +optoelectronics +optokinetic +optometric +optometrical +optometrist +optometrists +optometry +opts +opulence +opulency +opulent +opulently +opuntia +opuntias +opus +opuscula +opuscule +opuscules +opusculum +opuses +opéra +oquassa +oquassas +or +ora +orach +orache +oraches +oracle +oracles +oracular +oracularity +oracularly +oral +oralism +oralist +oralists +orality +orally +orals +oran +orang +orange +orangeade +orangeades +orangeism +orangeman +orangemen +orangerie +orangeries +orangeroot +orangeroots +orangery +oranges +orangewood +orangewoods +orangey +orangish +orangoutang +orangoutangs +orangs +orangutan +orangutans +orangy +orate +orated +orates +orating +oration +orations +orator +oratorial +oratorian +oratorians +oratorical +oratorically +oratories +oratorio +oratorios +orators +oratorship +oratory +orb +orbed +orbicular +orbicularity +orbicularly +orbiculate +orbiculated +orbiculately +orbing +orbit +orbital +orbitals +orbited +orbiteer +orbiteered +orbiteering +orbiteers +orbiter +orbiters +orbiting +orbits +orbs +orca +orcadian +orcadians +orcas +orchard +orchardist +orchardists +orchards +orchestra +orchestral +orchestrally +orchestras +orchestrate +orchestrated +orchestrater +orchestraters +orchestrates +orchestrating +orchestration +orchestrational +orchestrations +orchestrator +orchestrators +orchestrina +orchestrion +orchid +orchidaceous +orchidectomies +orchidectomy +orchidlike +orchids +orchiectomies +orchiectomy +orchil +orchils +orchis +orchises +orcus +ordain +ordained +ordainer +ordainers +ordaining +ordainment +ordainments +ordains +ordeal +ordeals +order +orderable +ordered +orderer +orderers +ordering +orderings +orderless +orderlies +orderliness +orderly +orders +ordinal +ordinals +ordinance +ordinances +ordinand +ordinands +ordinaries +ordinarily +ordinariness +ordinary +ordinate +ordinates +ordination +ordinations +ordines +ordnance +ordo +ordonnance +ordonnances +ordos +ordovician +ordure +ore +oread +oreads +oregano +oregon +oregonian +oregonians +oreide +oreides +oreo +oreos +ores +orestes +oresund +orfray +orfrays +organ +organa +organdie +organdies +organdy +organelle +organelles +organic +organically +organicism +organicist +organicists +organicity +organics +organism +organismal +organismic +organismically +organisms +organist +organists +organizable +organization +organizational +organizationally +organizations +organize +organized +organizer +organizers +organizes +organizing +organochlorine +organochlorines +organogeneses +organogenesis +organogenetic +organogenetically +organographic +organographically +organographies +organography +organoleptic +organoleptically +organologic +organological +organology +organomercurial +organomercurials +organometallic +organon +organons +organophosphate +organophosphates +organophosphorous +organophosphorus +organophosphoruses +organotherapeutic +organotherapies +organotherapy +organotropic +organotropically +organotropism +organotropy +organs +organum +organums +organza +organzine +organzines +orgasm +orgasmic +orgasmically +orgasms +orgastic +orgastically +orgeat +orgeats +orgiast +orgiastic +orgiastically +orgiasts +orgies +orgone +orgones +orgulous +orgy +oribatid +oribatids +oribi +oribis +oriel +oriels +orient +oriental +orientalia +orientalism +orientalist +orientalists +orientalize +orientalized +orientalizes +orientalizing +orientally +orientals +orientate +orientated +orientates +orientating +orientation +orientational +orientationally +orientations +oriented +orienteer +orienteering +orienteers +orienting +orients +orifice +orifices +orificial +oriflamme +oriflammes +origami +origamis +origanum +origanums +origin +original +originalism +originalist +originalists +originalities +originality +originally +originals +originate +originated +originates +originating +origination +originations +originative +originatively +originator +originators +origins +orinasal +orinasals +orinoco +oriole +orioles +orion +orion's +orismological +orismology +orison +orisons +orissa +oriya +orizaba +orkney +orlando +orleanian +orleanians +orleanist +orleanists +orleans +orlon +orlop +orlops +orléanais +orléans +ormazd +ormer +ormers +ormolu +ormolus +ormuz +ormuzd +ornament +ornamental +ornamentally +ornamentals +ornamentation +ornamented +ornamenter +ornamenters +ornamenting +ornaments +ornate +ornately +ornateness +ornerier +orneriest +orneriness +ornery +ornithic +ornithine +ornithines +ornithischian +ornithischians +ornithologic +ornithological +ornithologically +ornithologist +ornithologists +ornithology +ornithopod +ornithopods +ornithopter +ornithopters +ornithosis +orogenesis +orogenetic +orogenic +orogenically +orogeny +orographic +orographical +orographically +orography +oroide +oroides +orological +orologically +orologist +orologists +orology +oromo +oromos +oropharyngeal +oropharynges +oropharynx +oropharynxes +orotund +orotundity +orphan +orphanage +orphanages +orphaned +orphanhood +orphaning +orphans +orphean +orpheus +orphic +orphically +orphism +orphist +orphists +orphrey +orphreys +orpiment +orpine +orpines +orpington +orpingtons +orreries +orrery +orris +orrises +orrisroot +orrisroots +ors +ort +orthicon +orthicons +ortho +orthocenter +orthocenters +orthochromatic +orthochromatism +orthoclase +orthoclastic +orthodontia +orthodontic +orthodontically +orthodontics +orthodontist +orthodontists +orthodonture +orthodox +orthodoxes +orthodoxies +orthodoxly +orthodoxy +orthoepic +orthoepical +orthoepically +orthoepist +orthoepists +orthoepy +orthogenesis +orthogenetic +orthogenetically +orthogonal +orthogonality +orthogonalization +orthogonalizations +orthogonalize +orthogonalized +orthogonalizes +orthogonalizing +orthogonally +orthograde +orthographer +orthographers +orthographic +orthographical +orthographically +orthographies +orthographist +orthographists +orthography +orthomolecular +orthonormal +orthopaedic +orthopaedics +orthopedic +orthopedically +orthopedics +orthopedist +orthopedists +orthophosphate +orthophosphates +orthophosphoric +orthopsychiatric +orthopsychiatrical +orthopsychiatrist +orthopsychiatrists +orthopsychiatry +orthoptera +orthopteral +orthopteran +orthopterans +orthopterist +orthopterists +orthopteroid +orthopteron +orthopterons +orthopterous +orthorhombic +orthoscopic +orthoses +orthosis +orthostatic +orthotic +orthotics +orthotist +orthotists +orthotropic +orthotropically +orthotropism +orthotropous +ortler +ortles +ortolan +ortolans +orts +orvieto +orwellian +oryx +oryxes +orzo +orzos +os +osage +osages +osaka +osar +osborne +oscan +oscans +oscar +oscars +osceola +oscillate +oscillated +oscillates +oscillating +oscillation +oscillational +oscillations +oscillator +oscillators +oscillatory +oscillogram +oscillograms +oscillograph +oscillographic +oscillographically +oscillographs +oscillography +oscilloscope +oscilloscopes +oscilloscopic +oscine +oscines +oscitance +oscitances +oscitancies +oscitancy +oscitant +oscula +osculant +oscular +osculate +osculated +osculates +osculating +osculation +osculations +osculatory +oscule +oscules +osculum +osee +osier +osiers +osiris +oslo +osmanli +osmanlis +osmatic +osmeteria +osmeterium +osmic +osmically +osmics +osmious +osmiridium +osmiridiums +osmium +osmol +osmolal +osmolalities +osmolality +osmolar +osmolarities +osmolarity +osmole +osmoles +osmols +osmometer +osmometers +osmometric +osmometry +osmoregulation +osmoregulations +osmoregulatory +osmose +osmosed +osmoses +osmosing +osmosis +osmotic +osmotically +osmous +osmund +osmunda +osmundas +osmunds +osnabrück +osnaburg +osnaburgs +osprey +ospreys +osric +ossa +ossature +ossatures +ossein +osseins +osseous +osseously +osset +ossete +ossetes +ossetia +ossetian +ossetians +ossetic +ossets +ossia +ossian +ossianic +ossicle +ossicles +ossicular +ossiculate +ossific +ossification +ossified +ossifies +ossifrage +ossifrages +ossify +ossifying +osso +ossuaries +ossuary +osteal +osteitis +ostend +ostende +ostensible +ostensibly +ostensive +ostensively +ostensoria +ostensories +ostensorium +ostensory +ostentation +ostentatious +ostentatiously +ostentatiousness +osteoarthritic +osteoarthritis +osteoblast +osteoblastic +osteoblasts +osteoclases +osteoclasis +osteoclast +osteoclastic +osteoclasts +osteocyte +osteocytes +osteogeneses +osteogenesis +osteogenetic +osteogenic +osteogenous +osteoid +osteoids +osteological +osteologically +osteologies +osteologist +osteologists +osteology +osteolyses +osteolysis +osteolytic +osteoma +osteomalacia +osteomalacias +osteomas +osteomata +osteomyelitis +osteomyelitises +osteopath +osteopathic +osteopathically +osteopathist +osteopathists +osteopaths +osteopathy +osteophyte +osteophytes +osteophytic +osteoplastic +osteoplasties +osteoplasty +osteoporoses +osteoporosis +osteoporotic +osteosarcoma +osteosarcomas +osteosarcomata +osteoses +osteosis +osteotomies +osteotomist +osteotomists +osteotomy +ostia +ostiak +ostiaks +ostiaries +ostiary +ostinato +ostinatos +ostiolar +ostiole +ostioles +ostium +ostler +ostlers +ostmark +ostmarks +ostomate +ostomates +ostomies +ostomy +ostoses +ostosis +ostraca +ostracism +ostracize +ostracized +ostracizes +ostracizing +ostracod +ostracode +ostracoderm +ostracoderms +ostracodes +ostracods +ostracon +ostrich +ostriches +ostrichlike +ostrogoth +ostrogothic +ostrogoths +ostyak +ostyaks +oswego +otaheite +otalgia +otalgias +otalgic +othello +other +otherguess +otherness +others +otherwhere +otherwhile +otherwhiles +otherwise +otherworld +otherworldliness +otherworldly +otherworlds +othman +othmans +otic +otiose +otiosely +otioseness +otiosity +otitic +otitis +oto +otocyst +otocystic +otocysts +otolaryngological +otolaryngologist +otolaryngologists +otolaryngology +otolith +otolithic +otoliths +otological +otologist +otologists +otology +otophone +otorhinolaryngological +otorhinolaryngologist +otorhinolaryngologists +otorhinolaryngology +otos +otoscleroses +otosclerosis +otosclerotic +otoscope +otoscopes +ototoxic +ototoxicity +otranto +ottar +ottars +ottava +ottawa +ottawas +otter +otters +otto +ottoman +ottomans +ottos +otway +ouabain +ouabains +ouachita +ouagadougou +oubliette +oubliettes +ouch +ouches +oud +oudenarde +oudh +ouds +ought +oughtn +oughtn't +oughts +ouguiya +ouguiyas +ouija +ounce +ounces +our +ours +ourself +ourselves +ousel +ousels +oushak +oust +ousted +ouster +ousters +ousting +ousts +out +outachieve +outachieved +outachieves +outachieving +outact +outacted +outacting +outacts +outage +outages +outate +outback +outbacker +outbackers +outbalance +outbalanced +outbalances +outbalancing +outbargain +outbargained +outbargaining +outbargains +outbid +outbidden +outbidding +outbids +outbitch +outbitched +outbitches +outbitching +outbluff +outbluffed +outbluffing +outbluffs +outboard +outboards +outbought +outbound +outbox +outboxed +outboxes +outboxing +outbrag +outbraged +outbraging +outbrags +outbrave +outbraved +outbraves +outbraving +outbrawl +outbrawled +outbrawling +outbrawls +outbreak +outbreaks +outbred +outbreed +outbreeding +outbreedings +outbreeds +outbuilding +outbuildings +outbulk +outbulked +outbulking +outbulks +outburst +outbursts +outbuy +outbuying +outbuys +outcall +outcalls +outcast +outcaste +outcastes +outcasts +outcatch +outcatches +outcatching +outcaught +outcharge +outcharged +outcharges +outcharging +outclass +outclassed +outclasses +outclassing +outclimb +outclimbed +outclimbing +outclimbs +outcoach +outcoached +outcoaches +outcoaching +outcome +outcomes +outcompete +outcompeted +outcompetes +outcompeting +outcries +outcrop +outcropped +outcropping +outcroppings +outcrops +outcross +outcrossed +outcrosses +outcrossing +outcry +outcurve +outcurves +outdance +outdanced +outdances +outdancing +outdate +outdated +outdatedly +outdatedness +outdates +outdating +outdazzle +outdazzled +outdazzles +outdazzling +outdebate +outdebated +outdebates +outdebating +outdeliver +outdelivered +outdelivering +outdelivers +outdesign +outdesigned +outdesigning +outdesigns +outdid +outdistance +outdistanced +outdistances +outdistancing +outdo +outdoes +outdoing +outdone +outdoor +outdoors +outdoorsman +outdoorsmanship +outdoorsmen +outdoorswoman +outdoorswomen +outdoorsy +outdrag +outdragged +outdragging +outdrags +outdrank +outdraw +outdrawing +outdrawn +outdraws +outdress +outdressed +outdresses +outdressing +outdrew +outdrink +outdrinking +outdrinks +outdrive +outdriven +outdrives +outdriving +outdrove +outdrunk +outduel +outdueled +outdueling +outduelled +outduelling +outduels +outearn +outearned +outearning +outearns +outeat +outeaten +outeating +outeats +outed +outer +outercoat +outercoats +outermost +outers +outerwear +outface +outfaced +outfaces +outfacing +outfall +outfalls +outfield +outfielder +outfielders +outfields +outfight +outfighting +outfights +outfigure +outfigured +outfigures +outfiguring +outfish +outfished +outfishes +outfishing +outfit +outfits +outfitted +outfitter +outfitters +outfitting +outflank +outflanked +outflanking +outflanks +outflew +outflies +outflow +outflowed +outflowing +outflown +outflows +outfly +outflying +outfoot +outfooted +outfooting +outfoots +outfought +outfox +outfoxed +outfoxes +outfoxing +outfumble +outfumbled +outfumbles +outfumbling +outgain +outgained +outgaining +outgains +outgas +outgassed +outgasses +outgassing +outgeneral +outgeneraled +outgeneraling +outgenerals +outgiving +outglitter +outglittered +outglittering +outglitters +outgo +outgoes +outgoing +outgoingness +outgoings +outgone +outgrew +outgrip +outgripped +outgripping +outgrips +outgross +outgrossed +outgrosses +outgrossing +outgrow +outgrowing +outgrown +outgrows +outgrowth +outgrowths +outguess +outguessed +outguesses +outguessing +outgun +outgunned +outgunning +outguns +outhaul +outhauls +outhit +outhits +outhitting +outhomer +outhomered +outhomering +outhomers +outhouse +outhouses +outhunt +outhunted +outhunting +outhunts +outhustle +outhustled +outhustles +outhustling +outing +outings +outintrigue +outintrigued +outintrigues +outintriguing +outjump +outjumped +outjumping +outjumps +outkick +outkicked +outkicking +outkicks +outkill +outkilled +outkilling +outkills +outlaid +outland +outlander +outlanders +outlandish +outlandishly +outlandishness +outlands +outlast +outlasted +outlasting +outlasts +outlaw +outlawed +outlawing +outlawries +outlawry +outlaws +outlay +outlaying +outlays +outleap +outleaped +outleaping +outleaps +outleapt +outlearn +outlearned +outlearning +outlearns +outlearnt +outlet +outlets +outlier +outliers +outline +outlined +outliner +outliners +outlines +outlining +outlive +outlived +outlives +outliving +outlook +outlooks +outlying +outman +outmaneuver +outmaneuvered +outmaneuvering +outmaneuvers +outmanipulate +outmanipulated +outmanipulates +outmanipulating +outmanned +outmanning +outmans +outmarch +outmarched +outmarches +outmarching +outmatch +outmatched +outmatches +outmatching +outmode +outmoded +outmodes +outmoding +outmost +outmuscle +outmuscled +outmuscles +outmuscling +outness +outnumber +outnumbered +outnumbering +outnumbers +outorganize +outorganized +outorganizes +outorganizing +outpace +outpaced +outpaces +outpacing +outpass +outpassed +outpasses +outpassing +outpatient +outpatients +outperform +outperformed +outperforming +outperforms +outpitch +outpitched +outpitches +outpitching +outplace +outplaced +outplacement +outplacements +outplacer +outplacers +outplaces +outplacing +outplay +outplayed +outplaying +outplays +outplot +outplots +outplotted +outplotting +outpoint +outpointed +outpointing +outpoints +outpolitick +outpoliticked +outpoliticking +outpoliticks +outpoll +outpolled +outpolling +outpolls +outpopulate +outpopulated +outpopulates +outpopulating +outport +outports +outpost +outposts +outpour +outpoured +outpourer +outpourers +outpouring +outpourings +outpours +outpower +outpowered +outpowering +outpowers +outpray +outprayed +outpraying +outprays +outpreach +outpreached +outpreaches +outpreaching +outprice +outpriced +outprices +outpricing +outproduce +outproduced +outproduces +outproducing +outpromise +outpromised +outpromises +outpromising +outpull +outpulled +outpulling +outpulls +outpunch +outpunched +outpunches +outpunching +output +outputs +outputted +outputting +outrace +outraced +outraces +outracing +outrage +outraged +outrageous +outrageously +outrageousness +outrages +outraging +outran +outrange +outranged +outranges +outranging +outrank +outranked +outranking +outranks +outrate +outrated +outrates +outrating +outreach +outreached +outreaches +outreaching +outrebound +outrebounded +outrebounding +outrebounds +outreproduce +outreproduced +outreproduces +outreproducing +outridden +outride +outrider +outriders +outrides +outriding +outrigger +outriggers +outright +outrightly +outrightness +outrival +outrivaled +outrivaling +outrivalled +outrivalling +outrivals +outroar +outroared +outroaring +outroars +outrode +outrow +outrowed +outrowing +outrows +outrun +outrunning +outruns +outrush +outrushed +outrushes +outrushing +outré +outs +outsail +outsailed +outsailing +outsails +outsang +outsat +outscheme +outschemed +outschemes +outscheming +outscoop +outscooped +outscooping +outscoops +outscore +outscored +outscores +outscoring +outsell +outselling +outsells +outset +outsets +outshine +outshines +outshining +outshone +outshoot +outshooting +outshoots +outshot +outshout +outshouted +outshouting +outshouts +outside +outsider +outsiderness +outsiders +outsides +outsight +outsights +outsing +outsinging +outsings +outsit +outsits +outsitting +outsize +outsized +outsizes +outskate +outskated +outskates +outskating +outskirt +outskirts +outslick +outslicked +outslicking +outslicks +outsmart +outsmarted +outsmarting +outsmarts +outsoar +outsoared +outsoaring +outsoars +outsold +outsole +outsoles +outsource +outsourced +outsources +outsourcing +outsourcings +outsparkle +outsparkled +outsparkles +outsparkling +outspeak +outspeaking +outspeaks +outsped +outspeed +outspeeded +outspeeding +outspeeds +outspend +outspending +outspends +outspent +outspoke +outspoken +outspokenly +outspokenness +outspread +outspreading +outspreads +outsprint +outsprinted +outsprinting +outsprints +outstand +outstanding +outstandingly +outstands +outstare +outstared +outstares +outstaring +outstation +outstations +outstay +outstayed +outstaying +outstays +outstood +outstretch +outstretched +outstretches +outstretching +outstridden +outstride +outstrides +outstriding +outstrip +outstripped +outstripping +outstrips +outstrode +outstroke +outstrokes +outsung +outswam +outswear +outswearing +outswears +outswim +outswimming +outswims +outswore +outsworn +outswum +outtake +outtakes +outtalk +outtalked +outtalking +outtalks +outthink +outthinking +outthinks +outthought +outthrew +outthrow +outthrowing +outthrown +outthrows +outthrust +outthrusted +outthrusting +outthrusts +outtrade +outtraded +outtrades +outtrading +outturn +outturning +outturns +outvie +outvied +outvies +outvote +outvoted +outvotes +outvoting +outvying +outwait +outwaited +outwaiting +outwaits +outwalk +outwalked +outwalking +outwalks +outward +outwardly +outwardness +outwards +outwash +outwashes +outwatch +outwatched +outwatches +outwatching +outwear +outwearing +outwears +outweigh +outweighed +outweighing +outweighs +outwent +outwit +outwits +outwitted +outwitting +outwore +outwork +outworked +outworker +outworkers +outworking +outworks +outworn +outwrestle +outwrestled +outwrestles +outwrestling +outwrite +outwrites +outwriting +outwritten +outwrote +outwrought +outyell +outyelled +outyelling +outyells +outyield +outyielded +outyielding +outyields +ouzel +ouzels +ouzo +ouzos +ova +oval +ovalbumin +ovalbumins +ovality +ovally +ovalness +ovals +ovambo +ovambos +ovarial +ovarian +ovariectomies +ovariectomized +ovariectomy +ovaries +ovariole +ovarioles +ovariotomies +ovariotomy +ovaritis +ovaritises +ovary +ovate +ovately +ovation +ovational +ovations +oven +ovenable +ovenbird +ovenbirds +ovenproof +ovens +ovenware +over +overabounding +overabstract +overabundance +overabundances +overabundant +overabundantly +overaccentuate +overaccentuated +overaccentuates +overaccentuating +overachieve +overachieved +overachievement +overachievements +overachiever +overachievers +overachieves +overachieving +overact +overacted +overacting +overaction +overactions +overactive +overactivity +overacts +overadjustment +overadjustments +overadvertise +overadvertised +overadvertises +overadvertising +overage +overaged +overages +overaggressive +overaggressively +overaggressiveness +overalert +overall +overalled +overalls +overambition +overambitious +overambitiously +overambitiousness +overamplified +overanalyses +overanalysis +overanalytical +overanalyze +overanalyzed +overanalyzes +overanalyzing +overanxieties +overanxiety +overanxious +overanxiously +overanxiousness +overapplication +overapplications +overarch +overarched +overarches +overarching +overarchingly +overarm +overarmed +overarming +overarms +overarousal +overarousals +overarrange +overarranged +overarranges +overarranging +overarticulate +overassert +overasserted +overasserting +overassertion +overassertions +overassertive +overasserts +overassess +overassessed +overassesses +overassessing +overassessment +overassessments +overate +overattention +overattentions +overawe +overawed +overawes +overawing +overbake +overbaked +overbakes +overbaking +overbalance +overbalanced +overbalances +overbalancing +overbear +overbearing +overbearingly +overbearingness +overbears +overbeat +overbeaten +overbeating +overbeats +overbejeweled +overbid +overbidden +overbidder +overbidders +overbidding +overbids +overbill +overbilled +overbilling +overbills +overbite +overbites +overbleach +overbleached +overbleaches +overbleaching +overblew +overblouse +overblouses +overblow +overblowing +overblown +overblows +overboard +overboil +overboiled +overboiling +overboils +overbold +overbook +overbooked +overbooking +overbooks +overbore +overborne +overborrow +overborrowed +overborrowing +overborrows +overbought +overbreathing +overbrief +overbright +overbroad +overbrowse +overbrowsed +overbrowses +overbrowsing +overbrutal +overbuild +overbuilding +overbuilds +overbuilt +overburden +overburdened +overburdening +overburdens +overburn +overbusy +overbuy +overbuying +overbuys +overcall +overcalled +overcalling +overcalls +overcame +overcapacities +overcapacity +overcapitalization +overcapitalizations +overcapitalize +overcapitalized +overcapitalizes +overcapitalizing +overcareful +overcast +overcasting +overcastings +overcasts +overcaution +overcautious +overcautiously +overcautiousness +overcentralization +overcentralize +overcentralized +overcentralizes +overcentralizing +overcharge +overcharged +overcharges +overcharging +overchill +overchilled +overchilling +overchills +overcivilized +overclaim +overclaimed +overclaiming +overclaims +overclassification +overclassifications +overclassified +overclassifies +overclassify +overclassifying +overclean +overcleaned +overcleaning +overcleans +overclear +overcloud +overclouded +overclouding +overclouds +overcoach +overcoached +overcoaches +overcoaching +overcoat +overcoating +overcoatings +overcoats +overcome +overcomer +overcomers +overcomes +overcoming +overcommercialization +overcommercialize +overcommercialized +overcommercializes +overcommercializing +overcommit +overcommitment +overcommitments +overcommits +overcommitted +overcommitting +overcommunicate +overcommunicated +overcommunicates +overcommunicating +overcommunication +overcompensate +overcompensated +overcompensates +overcompensating +overcompensation +overcompensatory +overcomplex +overcompliance +overcomplicate +overcomplicated +overcomplicates +overcomplicating +overcompress +overcompressed +overcompresses +overcompressing +overconcentration +overconcentrations +overconcern +overconcerned +overconcerning +overconcerns +overconfidence +overconfident +overconfidently +overconscientious +overconscious +overconservative +overconstruct +overconstructed +overconstructing +overconstructs +overconsume +overconsumed +overconsumes +overconsuming +overconsumption +overcontrol +overcontrolled +overcontrolling +overcontrols +overcook +overcooked +overcooking +overcooks +overcool +overcooled +overcooling +overcools +overcorrect +overcorrected +overcorrecting +overcorrection +overcorrections +overcorrects +overcount +overcounted +overcounting +overcountings +overcounts +overcredulous +overcritical +overcritically +overcriticalness +overcrop +overcropped +overcropping +overcrops +overcrowd +overcrowded +overcrowding +overcrowds +overcultivation +overcure +overcurious +overcut +overcuts +overcutting +overdecorate +overdecorated +overdecorates +overdecorating +overdecoration +overdelicate +overdemanding +overdependence +overdependent +overdesign +overdesigned +overdesigning +overdesigns +overdetermine +overdetermined +overdetermines +overdetermining +overdevelop +overdeveloped +overdeveloping +overdevelopment +overdevelops +overdid +overdifferentiation +overdirect +overdiscount +overdiscounted +overdiscounting +overdiscounts +overdiversity +overdo +overdocument +overdocumented +overdocumenting +overdocuments +overdoer +overdoers +overdoes +overdog +overdogs +overdoing +overdominance +overdominances +overdominant +overdone +overdosage +overdosages +overdose +overdosed +overdoses +overdosing +overdraft +overdrafts +overdramatic +overdramatize +overdramatized +overdramatizes +overdramatizing +overdrank +overdraught +overdraughts +overdraw +overdrawing +overdrawn +overdraws +overdress +overdressed +overdresses +overdressing +overdrew +overdried +overdries +overdrink +overdrinking +overdrinks +overdrive +overdriven +overdrives +overdriving +overdrove +overdry +overdrying +overdub +overdubbed +overdubbing +overdubs +overdue +overeager +overeagerly +overeagerness +overearnest +overeat +overeaten +overeater +overeaters +overeating +overeats +overed +overedit +overedited +overediting +overedits +overeducate +overeducated +overeducates +overeducating +overeducation +overelaborate +overelaborated +overelaborates +overelaborating +overelaboration +overembellish +overembellished +overembellishes +overembellishing +overemote +overemotional +overemphases +overemphasis +overemphasize +overemphasized +overemphasizes +overemphasizing +overemphatic +overenamored +overencourage +overencouraged +overencourages +overencouraging +overenergetic +overengineer +overengineered +overengineering +overengineers +overenrolled +overentertained +overenthusiasm +overenthusiasms +overenthusiastic +overequip +overequipped +overequipping +overequips +overestimate +overestimated +overestimates +overestimating +overestimation +overestimations +overevaluation +overevaluations +overexaggerate +overexaggerated +overexaggerates +overexaggerating +overexaggeration +overexaggerations +overexcite +overexcited +overexcites +overexciting +overexercise +overexercised +overexercises +overexercising +overexert +overexerted +overexerting +overexertion +overexertions +overexerts +overexpand +overexpanded +overexpanding +overexpands +overexpansion +overexpectation +overexpectations +overexplain +overexplained +overexplaining +overexplains +overexplicit +overexploit +overexploitation +overexploitations +overexploited +overexploiting +overexploits +overexpose +overexposed +overexposes +overexposing +overexposure +overexposures +overextend +overextended +overextending +overextends +overextension +overextensions +overextraction +overextractions +overextrapolation +overextrapolations +overextravagant +overexuberant +overfacile +overfamiliar +overfamiliarities +overfamiliarity +overfastidious +overfat +overfatigue +overfatigued +overfavor +overfavored +overfavoring +overfavors +overfed +overfeed +overfeeding +overfeeds +overfertilization +overfertilize +overfertilized +overfertilizes +overfertilizing +overfill +overfilled +overfilling +overfills +overfish +overfished +overfishes +overfishing +overflew +overflies +overflight +overflights +overflow +overflowed +overflowing +overflown +overflows +overfly +overflying +overfocus +overfocused +overfocuses +overfocusing +overfocussed +overfocusses +overfocussing +overfond +overfulfill +overfulfilled +overfulfilling +overfulfills +overfull +overfund +overfunded +overfunding +overfunds +overfussy +overgarment +overgarments +overgeneralization +overgeneralizations +overgeneralize +overgeneralized +overgeneralizes +overgeneralizing +overgenerosity +overgenerous +overgenerously +overglamorize +overglamorized +overglamorizes +overglamorizing +overglaze +overglazed +overglazes +overglazing +overgovern +overgoverned +overgoverning +overgoverns +overgraze +overgrazed +overgrazes +overgrazing +overgrew +overgrow +overgrowing +overgrown +overgrows +overgrowth +overgrowths +overhand +overhanded +overhanding +overhandle +overhandled +overhandles +overhandling +overhands +overhang +overhanging +overhangs +overharvest +overharvested +overharvesting +overharvests +overhasty +overhaul +overhauled +overhauler +overhaulers +overhauling +overhauls +overhead +overheads +overhear +overheard +overhearer +overhearers +overhearing +overhears +overheat +overheated +overheating +overheats +overhit +overhits +overhitting +overhomogenize +overhomogenized +overhomogenizes +overhomogenizing +overhung +overhunt +overhunted +overhunting +overhunts +overhydrate +overhydrated +overhydrates +overhydrating +overhydration +overhype +overhyped +overhypes +overhyping +overidealize +overidealized +overidealizes +overidealizing +overidentification +overidentified +overidentifies +overidentify +overidentifying +overimaginative +overimpress +overimpressed +overimpresses +overimpressing +overindebtedness +overindulge +overindulged +overindulgence +overindulgences +overindulgent +overindulgently +overindulges +overindulging +overindustrialize +overindustrialized +overindustrializes +overindustrializing +overinflate +overinflated +overinflates +overinflating +overinflation +overinform +overinformed +overinforming +overinforms +overing +overingenious +overingenuity +overinsistent +overintellectualization +overintellectualize +overintellectualized +overintellectualizes +overintellectualizing +overintense +overintensity +overinterpret +overinterpretation +overinterpretations +overinterpreted +overinterpreting +overinterprets +overinvestment +overissuance +overissue +overissued +overissues +overissuing +overjoy +overjoyed +overjoying +overjoys +overkill +overkilled +overkilling +overkills +overlabor +overlabored +overlaboring +overlabors +overladen +overlaid +overlain +overland +overlap +overlapped +overlapping +overlaps +overlarge +overlavish +overlay +overlaying +overlays +overleaf +overleap +overleaped +overleaping +overleaps +overleapt +overlearn +overlearned +overlearning +overlearns +overlearnt +overlend +overlending +overlends +overlength +overlengthen +overlengthened +overlengthening +overlengthens +overlent +overlie +overlies +overlight +overliteral +overliterary +overload +overloaded +overloading +overloads +overlong +overlook +overlooked +overlooking +overlooks +overlord +overlords +overlordship +overloud +overlush +overly +overlying +overman +overmanage +overmanaged +overmanages +overmanaging +overmanned +overmannered +overmanning +overmans +overmantel +overmantels +overmaster +overmastered +overmastering +overmasters +overmatch +overmatched +overmatches +overmatching +overmature +overmaturity +overmedicate +overmedicated +overmedicates +overmedicating +overmedication +overmen +overmighty +overmilk +overmilked +overmilking +overmilks +overmine +overmined +overmines +overmining +overmix +overmixed +overmixes +overmixing +overmodest +overmodestly +overmuch +overmuscled +overnice +overnight +overnighted +overnighter +overnighters +overnighting +overnights +overnourish +overnourished +overnourishes +overnourishing +overnutrition +overobvious +overoperate +overoperated +overoperates +overoperating +overopinionated +overoptimism +overoptimist +overoptimistic +overoptimistically +overoptimists +overorchestrate +overorchestrated +overorchestrates +overorchestrating +overorganize +overorganized +overorganizes +overorganizing +overornament +overornamented +overornamenting +overornaments +overpackage +overpackaged +overpackages +overpackaging +overpaid +overparticular +overpass +overpassed +overpasses +overpassing +overpast +overpay +overpaying +overpayment +overpayments +overpays +overpedal +overpedaled +overpedaling +overpedals +overpeople +overpeopled +overpeoples +overpeopling +overpersuade +overpersuaded +overpersuades +overpersuading +overpersuasion +overplaid +overplaided +overplan +overplanned +overplanning +overplans +overplant +overplanted +overplanting +overplants +overplay +overplayed +overplaying +overplays +overplenty +overplot +overplots +overplotted +overplotting +overplus +overpluses +overpopulate +overpopulated +overpopulates +overpopulating +overpopulation +overpotent +overpower +overpowered +overpowering +overpoweringly +overpowers +overpraise +overpraised +overpraises +overpraising +overprecise +overprescribe +overprescribed +overprescribes +overprescribing +overprescription +overprescriptions +overpressure +overpressured +overpressures +overpressuring +overpressurization +overpressurizations +overprice +overpriced +overprices +overpricing +overprint +overprinted +overprinting +overprints +overprivileged +overprize +overprized +overprizes +overprizing +overprocess +overprocessed +overprocesses +overprocessing +overproduce +overproduced +overproducer +overproducers +overproduces +overproducing +overproduction +overproductions +overprogram +overprogrammed +overprogramming +overprograms +overpromise +overpromised +overpromises +overpromising +overpromote +overpromoted +overpromotes +overpromoting +overproof +overproportion +overproportionate +overproportionately +overproportioned +overproportioning +overproportions +overprotect +overprotected +overprotecting +overprotection +overprotections +overprotective +overprotectiveness +overprotects +overpump +overpumped +overpumping +overpumps +overqualified +overran +overrate +overrated +overrates +overrating +overreach +overreached +overreacher +overreachers +overreaches +overreaching +overreact +overreacted +overreacting +overreaction +overreactions +overreactive +overreacts +overrefine +overrefined +overrefinement +overrefinements +overrefines +overrefining +overregulate +overregulated +overregulates +overregulating +overregulation +overregulations +overreliance +overreport +overreported +overreporting +overreports +overrepresentation +overrepresentations +overrepresented +overrespond +overresponded +overresponding +overresponds +overrich +overridden +override +overrides +overriding +overridingly +overrigid +overripe +overripely +overripeness +overrode +overruff +overruffed +overruffing +overruffs +overrule +overruled +overrules +overruling +overrun +overrunning +overruns +overs +oversalt +oversalted +oversalting +oversalts +oversanguine +oversaturate +oversaturated +oversaturates +oversaturating +oversaturation +oversauce +oversauced +oversauces +oversaucing +oversaw +overscale +overscaled +overscore +overscored +overscores +overscoring +overscrupulous +oversea +overseas +oversecretion +oversee +overseeing +overseen +overseer +overseers +oversees +oversell +overselling +oversells +oversensitive +oversensitiveness +oversensitivities +oversensitivity +overserious +overseriously +overservice +overserviced +overservices +overservicing +overset +oversets +oversetting +oversew +oversewed +oversewing +oversewn +oversews +oversexed +overshadow +overshadowed +overshadowing +overshadows +overshirt +overshirts +overshoe +overshoes +overshoot +overshooting +overshoots +overshot +oversight +oversights +oversimple +oversimplification +oversimplifications +oversimplified +oversimplifier +oversimplifiers +oversimplifies +oversimplify +oversimplifying +oversimplistic +oversimply +oversize +oversized +oversizes +overskirt +overskirts +overslaugh +overslaughed +overslaughing +overslaughs +oversleep +oversleeping +oversleeps +overslept +overslip +overslipped +overslipping +overslips +oversmoke +oversmoked +oversmokes +oversmoking +oversold +oversolicitous +oversophisticated +oversoul +oversouls +overspecialization +overspecializations +overspecialize +overspecialized +overspecializes +overspecializing +overspeculate +overspeculated +overspeculates +overspeculating +overspeculation +overspeculations +overspend +overspender +overspenders +overspending +overspends +overspent +overspill +overspilled +overspilling +overspills +overspilt +overspread +overspreading +overspreads +overstability +overstaff +overstaffed +overstaffing +overstaffs +overstate +overstated +overstatement +overstatements +overstates +overstating +overstay +overstayed +overstaying +overstays +oversteer +oversteers +overstep +overstepped +overstepping +oversteps +overstimulate +overstimulated +overstimulates +overstimulating +overstimulation +overstimulations +overstitch +overstitched +overstitches +overstitching +overstock +overstocked +overstocking +overstocks +overstories +overstory +overstrain +overstrained +overstraining +overstrains +overstress +overstressed +overstresses +overstressing +overstretch +overstretched +overstretches +overstretching +overstrew +overstrewed +overstrewing +overstrews +overstridden +overstride +overstrides +overstriding +overstrike +overstrikes +overstrode +overstructured +overstrung +overstuff +overstuffed +overstuffing +overstuffs +oversubscribe +oversubscribed +oversubscribes +oversubscribing +oversubscription +oversubscriptions +oversubtle +oversuds +oversupplied +oversupplies +oversupply +oversupplying +oversuspicious +oversweet +oversweeten +oversweetened +oversweetening +oversweetens +oversweetness +overswing +overt +overtake +overtaken +overtakes +overtaking +overtalk +overtalkative +overtalked +overtalking +overtalks +overtax +overtaxation +overtaxations +overtaxed +overtaxes +overtaxing +overthin +overthink +overthinking +overthinks +overthinned +overthinning +overthins +overthought +overthrew +overthrow +overthrowing +overthrown +overthrows +overthrust +overtighten +overtightened +overtightening +overtightens +overtime +overtimed +overtimes +overtiming +overtip +overtipped +overtipping +overtips +overtire +overtired +overtires +overtiring +overtly +overtness +overtone +overtones +overtook +overtop +overtopped +overtopping +overtops +overtrade +overtraded +overtrades +overtrading +overtrain +overtrained +overtraining +overtrains +overtreat +overtreated +overtreating +overtreatment +overtreats +overtrick +overtricks +overtrump +overtrumped +overtrumping +overtrumps +overture +overtured +overtures +overturing +overturn +overturned +overturning +overturns +overtype +overtyped +overtyping +overuse +overused +overuses +overusing +overutilization +overutilize +overutilized +overutilizes +overutilizing +overvaluation +overvaluations +overvalue +overvalued +overvalues +overvaluing +overview +overviews +overviolent +overvivid +overvoltage +overvoltages +overwater +overwatered +overwatering +overwaters +overwear +overwearied +overwearies +overwearing +overwears +overweary +overwearying +overweening +overweeningly +overweigh +overweighed +overweighing +overweighs +overweight +overweighted +overweighting +overweights +overwhelm +overwhelmed +overwhelming +overwhelmingly +overwhelms +overwind +overwinding +overwinds +overwinter +overwintered +overwintering +overwinters +overwithheld +overwithhold +overwithholding +overwithholds +overwore +overwork +overworked +overworking +overworks +overworn +overwound +overwrite +overwrites +overwriting +overwritten +overwrote +overwrought +overzealous +overzealously +overzealousness +ovicidal +ovicide +ovicides +ovid +ovidian +oviduct +oviductal +oviducts +oviferous +oviform +ovimbundu +ovimbundus +ovine +ovines +ovipara +oviparity +oviparous +oviparously +oviposit +oviposited +ovipositing +oviposition +ovipositional +ovipositions +ovipositor +ovipositors +oviposits +ovisac +ovisacs +ovoid +ovoidal +ovoidals +ovoids +ovolactovegetarian +ovolactovegetarians +ovoli +ovolo +ovonic +ovonics +ovotestes +ovotestis +ovoviviparity +ovoviviparous +ovoviviparously +ovoviviparousness +ovular +ovulary +ovulate +ovulated +ovulates +ovulating +ovulation +ovulations +ovulatory +ovule +ovules +ovum +ow +owe +owed +owes +owing +owl +owlet +owlets +owlish +owlishly +owlishness +owls +own +owned +owner +ownerless +owners +ownership +owning +owns +owyheei +ox +oxacillin +oxacillins +oxalacetate +oxalacetates +oxalacetic +oxalate +oxalated +oxalates +oxalating +oxalic +oxalis +oxalises +oxaloacetate +oxaloacetates +oxaloacetic +oxalosuccinic +oxazepam +oxazepams +oxblood +oxbow +oxbows +oxbridge +oxcart +oxcarts +oxen +oxeye +oxeyes +oxford +oxfords +oxfordshire +oxheart +oxhearts +oxidant +oxidants +oxidase +oxidases +oxidasic +oxidation +oxidations +oxidative +oxidatively +oxide +oxides +oxidic +oxidizable +oxidization +oxidizations +oxidize +oxidized +oxidizer +oxidizers +oxidizes +oxidizing +oxidoreductase +oxidoreductases +oxime +oximes +oximeter +oximeters +oximetric +oximetrically +oximetry +oxlip +oxlips +oxo +oxon +oxonian +oxonians +oxpecker +oxpeckers +oxtail +oxtails +oxter +oxters +oxtongue +oxtongues +oxus +oxyacetylene +oxyacid +oxyacids +oxycephalic +oxycephalies +oxycephalous +oxycephaly +oxycodone +oxycodones +oxygen +oxygenase +oxygenases +oxygenate +oxygenated +oxygenates +oxygenating +oxygenation +oxygenations +oxygenator +oxygenators +oxygenic +oxygenically +oxygenize +oxygenized +oxygenizes +oxygenizing +oxygenless +oxygenous +oxyhemoglobin +oxyhemoglobins +oxyhydrogen +oxymetazoline +oxymetazolines +oxymora +oxymoron +oxymoronic +oxymoronically +oxymorons +oxyphenbutazone +oxyphenbutazones +oxyphilic +oxysulfide +oxysulfides +oxytetracycline +oxytetracyclines +oxytocia +oxytocias +oxytocic +oxytocics +oxytocin +oxytocins +oxytone +oxytones +oxyuriasis +oyer +oyes +oyesses +oyez +oyster +oystercatcher +oystercatchers +oystered +oystering +oysterman +oystermen +oysters +oz +ozark +ozarkian +ozarkians +ozarks +ozocerite +ozocerites +ozokerite +ozokerites +ozonate +ozonated +ozonates +ozonating +ozonation +ozonations +ozone +ozonic +ozonide +ozonides +ozonization +ozonizations +ozonize +ozonized +ozonizer +ozonizers +ozonizes +ozonizing +ozonosphere +ozonospheric +ozonospherical +ozonous +ozostomia +ozostomias +p +pa +pa'anga +pablum +pablums +pabulum +pac +paca +pacas +pace +paced +pacemaker +pacemakers +pacemaking +pacer +pacers +paces +pacesetter +pacesetters +pacesetting +pacha +pachas +pachinko +pachinkos +pachisi +pachisis +pachouli +pachoulis +pachuco +pachucos +pachyderm +pachydermal +pachydermatous +pachydermic +pachydermous +pachyderms +pachysandra +pachysandras +pachytene +pachytenes +pacifarin +pacifarins +pacifiable +pacific +pacifical +pacifically +pacification +pacifications +pacificator +pacificators +pacificatory +pacificism +pacificisms +pacificist +pacificists +pacified +pacifier +pacifiers +pacifies +pacifism +pacifist +pacifistic +pacifistically +pacifists +pacify +pacifying +pacing +pacinian +pack +packability +packable +package +packaged +packager +packagers +packages +packaging +packagings +packboard +packboards +packed +packer +packers +packet +packets +packhorse +packhorses +packing +packinghouse +packinghouses +packings +packman +packmen +packs +packsack +packsacks +packsaddle +packsaddles +packthread +packthreads +pacs +pact +pacts +pad +padauk +padauks +padded +padder +padders +paddies +padding +paddings +paddle +paddleball +paddleballs +paddleboard +paddleboards +paddleboat +paddleboats +paddled +paddlefish +paddlefishes +paddler +paddlers +paddles +paddling +paddlings +paddock +paddocked +paddocking +paddocks +paddy +paderborn +padi +padis +padishah +padishahs +padless +padlock +padlocked +padlocking +padlocks +padouk +padouks +padova +padre +padres +padrone +padrones +padroni +padronism +pads +padua +paduan +paduans +paduasoy +paduasoys +paean +paeanistic +paeans +paedogeneses +paedogenesis +paedogenetic +paedogenetically +paedogenic +paedomorph +paedomorphic +paedomorphism +paedomorphisms +paedomorphoses +paedomorphosis +paedomorphs +paella +paellas +paeon +paeons +pagan +pagandom +pagandoms +paganini +paganish +paganism +paganization +paganizations +paganize +paganized +paganizer +paganizers +paganizes +paganizing +pagans +page +pageant +pageantries +pageantry +pageants +pageboy +pageboys +paged +pageful +pagefuls +pager +pagers +pages +paginal +paginate +paginated +paginates +paginating +pagination +paginations +paging +pagoda +pagodas +pah +pahlavi +pahlavis +paid +pail +pailful +pailfuls +paillard +paillards +paillasse +paillasses +paillette +pailletted +paillettes +pails +pain +pained +painful +painfuller +painfullest +painfully +painfulness +paining +painkiller +painkillers +painkilling +painless +painlessly +painlessness +pains +painstaking +painstakingly +paint +paintability +paintable +paintbrush +paintbrushes +painted +painter +painterliness +painterly +painters +painting +paintings +paints +paintwork +pair +paired +pairing +pairings +pairs +paisa +paisan +paisano +paisanos +paisans +paisas +paise +paisley +paisleys +paiute +paiutes +pajama +pajamaed +pajamas +pakeha +pakehas +pakistan +pakistani +pakistanis +pal +palace +palaces +paladin +paladins +palaestra +palankeen +palankeens +palanquin +palanquins +palapa +palapas +palatability +palatable +palatableness +palatably +palatal +palatalization +palatalizations +palatalize +palatalized +palatalizes +palatalizing +palatally +palatals +palate +palates +palatial +palatially +palatialness +palatinate +palatinates +palatine +palatines +palatino +palau +palaver +palavered +palavering +palavers +palawan +palazzi +palazzo +palazzos +pale +palea +paleae +paleal +palearctic +paled +paleethnologic +paleethnological +paleethnologies +paleethnology +paleface +palefaces +palely +paleness +paleoanthropic +paleoanthropologic +paleoanthropological +paleoanthropologist +paleoanthropologists +paleoanthropology +paleobiochemical +paleobiochemistries +paleobiochemistry +paleobiogeographic +paleobiogeographical +paleobiogeography +paleobiologic +paleobiological +paleobiologist +paleobiologists +paleobiology +paleobotanic +paleobotanical +paleobotanically +paleobotanist +paleobotanists +paleobotany +paleocene +paleoclimatologist +paleoclimatologists +paleoclimatology +paleoecologic +paleoecological +paleoecologist +paleoecologists +paleoecology +paleogene +paleogeographic +paleogeographical +paleogeographically +paleogeography +paleographer +paleographers +paleographic +paleographical +paleographically +paleography +paleolith +paleolithic +paleoliths +paleomagnetic +paleomagnetically +paleomagnetism +paleomagnetist +paleomagnetists +paleontologic +paleontological +paleontologist +paleontologists +paleontology +paleopathological +paleopathologist +paleopathologists +paleopathology +paleozoic +paleozoological +paleozoologist +paleozoologists +paleozoology +paler +palermo +pales +palest +palestine +palestinian +palestinians +palestra +palestrae +palestral +palestras +palestrian +palestrina +palette +palettes +paley +palfrey +palfreys +pali +palier +paliest +palimony +palimpsest +palimpsests +palindrome +palindromes +palindromic +palindromist +palindromists +paling +palingeneses +palingenesis +palingenetic +palingenetically +palings +palinode +palinodes +palisade +palisaded +palisades +palisading +palish +pall +palladia +palladian +palladianism +palladic +palladio +palladium +palladiums +palladous +pallas +pallbearer +pallbearers +palled +pallet +palletization +palletizations +palletize +palletized +palletizer +palletizers +palletizes +palletizing +pallets +pallette +pallettes +pallia +pallial +palliasse +palliasses +palliate +palliated +palliates +palliating +palliation +palliations +palliative +palliatively +palliatives +palliator +palliators +pallid +pallidly +pallidness +pallier +palliest +palling +pallium +palliums +pallor +pallors +palls +pally +palm +palma +palmar +palmary +palmas +palmate +palmated +palmately +palmatifid +palmation +palmations +palmatisect +palmed +palmer +palmers +palmerston +palmerworm +palmerworms +palmette +palmettes +palmetto +palmettoes +palmettos +palmful +palmfuls +palmier +palmiest +palming +palmist +palmister +palmisters +palmistry +palmists +palmitate +palmitates +palmitic +palmitin +palmitins +palmlike +palms +palmy +palmyra +palmyras +palomar +palomino +palominos +palooka +palookas +palouse +palouses +paloverde +paloverdes +palp +palpability +palpable +palpably +palpal +palpate +palpated +palpates +palpating +palpation +palpations +palpator +palpators +palpatory +palpebra +palpebrae +palpebral +palpebras +palpi +palpitant +palpitate +palpitated +palpitates +palpitating +palpitatingly +palpitation +palpitations +palps +palpus +pals +palsgrave +palsgraves +palship +palships +palsied +palsies +palsy +palsying +palter +paltered +palterer +palterers +paltering +palters +paltrier +paltriest +paltrily +paltriness +paltry +paludal +paludism +paludisms +paly +palynologic +palynological +palynologically +palynologist +palynologists +palynology +pam +pamby +pamir +pamlico +pampa +pampas +pampean +pamper +pampered +pamperer +pamperers +pampering +pampero +pamperos +pampers +pamphlet +pamphletary +pamphleteer +pamphleteered +pamphleteering +pamphleteers +pamphlets +pamplona +pamprodactylous +pan +panacea +panacean +panaceas +panache +panaches +panada +panadas +panama +panamanian +panamanians +panamint +panatela +panatelas +panay +pancake +pancaked +pancakes +pancaking +pancetta +pancettas +panchax +panchaxes +panchen +panchromatic +panchromatism +pancratium +pancratiums +pancreas +pancreases +pancreatectomies +pancreatectomized +pancreatectomy +pancreatic +pancreatin +pancreatins +pancreatitis +pancreozymin +pancreozymins +pancytopenia +pancytopenias +panda +pandaemonium +pandanaceous +pandanus +pandanuses +pandar +pandarus +pandas +pandean +pandect +pandects +pandemic +pandemics +pandemoniac +pandemonium +pander +pandered +panderer +panderers +pandering +panders +pandied +pandies +pandit +pandits +pandora +pandore +pandores +pandowdies +pandowdy +pandurate +panduriform +pandy +pandying +pane +paned +panegyric +panegyrical +panegyrically +panegyrics +panegyrist +panegyrists +panegyrize +panegyrized +panegyrizes +panegyrizing +panel +paneled +paneling +panelings +panelist +panelists +panelization +panelizations +panelize +panelized +panelizes +panelizing +panelled +panelling +panellings +panels +panencephalitis +panes +panetela +panetelas +panetella +panetellas +panettone +panettones +panettoni +panfish +panfishes +panfried +panfries +panfry +panfrying +panful +panfuls +pang +panga +pangaea +pangas +pangea +panged +pangenesis +pangenetic +pangenetically +panging +pangloss +panglossian +pangola +pangolin +pangolins +pangram +pangrammatic +pangrams +pangs +panhandle +panhandled +panhandler +panhandlers +panhandles +panhandling +panhellenic +panhuman +panic +panicked +panicking +panicky +panicle +panicled +panicles +panics +paniculate +paniculated +paniculately +panicum +panicums +panier +paniers +panini +panjabi +panjandrum +panjandrums +panky +panleucopenia +panleukopenia +panmictic +panmixia +panmixias +panmixis +panne +panned +pannes +pannier +panniered +panniers +pannikin +pannikins +panning +pannonia +pannonian +pannonians +panocha +panochas +panoche +panoches +panoplied +panoplies +panoply +panoptic +panoptical +panorama +panoramas +panoramic +panoramically +panpipe +panpipes +pans +pansexual +pansexuality +pansies +panspermia +panspermias +pansy +pant +pantagruel +pantagruelian +pantagruelism +pantagruelist +pantagruelists +pantalet +pantalets +pantalette +pantalettes +pantalone +pantalones +pantaloon +pantaloons +pantdress +pantdresses +pantechnicon +pantechnicons +panted +pantheism +pantheist +pantheistic +pantheistical +pantheistically +pantheists +pantheon +pantheons +panther +panthers +pantie +panties +pantile +pantiled +pantiles +panting +pantingly +pantisocracies +pantisocracy +pantisocratic +pantisocratical +pantisocratist +pantisocratists +panto +pantoffle +pantoffles +pantofle +pantofles +pantograph +pantographic +pantographs +pantomime +pantomimed +pantomimes +pantomimic +pantomiming +pantomimist +pantomimists +pantos +pantothenate +pantothenates +pantothenic +pantoum +pantoums +pantries +pantropic +pantropical +pantry +pantryman +pantrymen +pants +pantsuit +pantsuited +pantsuits +panty +pantyhose +pantywaist +pantywaists +panzer +panzers +pap +papa +papacies +papacy +papago +papagos +papain +papains +papal +papally +papanicolaou +paparazzi +paparazzo +papas +papaverine +papaverines +papaw +papaws +papaya +papayas +papeete +paper +paperback +paperbacked +paperbacks +paperboard +paperboards +paperbound +paperboy +paperboys +paperclip +paperclips +papercraft +papered +paperer +paperers +papergirl +papergirls +paperhanger +paperhangers +paperhanging +paperiness +papering +paperings +paperknife +paperknives +paperless +papermaker +papermakers +papermaking +papers +paperweight +paperweights +paperwork +papery +papeterie +papeteries +paphian +paphians +paphos +papiamento +papiamentu +papier +papilionaceous +papilla +papillae +papillary +papillate +papilloma +papillomas +papillomata +papillomatous +papillomavirus +papillomaviruses +papillon +papillons +papillose +papillote +papillotes +papist +papistic +papistry +papists +papoose +papooses +papovavirus +papovaviruses +pappataci +pappi +pappier +pappies +pappiest +pappose +pappous +pappus +pappy +paprika +paprikas +paps +papua +papuan +papuans +papula +papulae +papular +papule +papules +papyri +papyrologic +papyrological +papyrologist +papyrologists +papyrology +papyrus +papyruses +par +para +parabioses +parabiosis +parabiotic +parabiotically +parablast +parablastic +parablasts +parable +parables +parabola +parabolas +parabolic +parabolical +parabolically +paraboloid +paraboloidal +paraboloids +paracelsus +parachute +parachuted +parachuter +parachuters +parachutes +parachutic +parachuting +parachutist +parachutists +paraclete +parade +paraded +parader +paraders +parades +paradichlorobenzene +paradichlorobenzenes +paradiddle +paradiddles +paradigm +paradigmatic +paradigmatically +paradigms +parading +paradisaic +paradisaical +paradisaically +paradisal +paradisally +paradise +paradises +paradisiac +paradisiacal +paradisiacally +paradisial +paradisical +parador +paradores +paradors +paradox +paradoxes +paradoxical +paradoxicality +paradoxically +paradoxicalness +paradrop +paradropped +paradropping +paradrops +paraesthesia +paraffin +paraffined +paraffinic +paraffining +paraffins +parafoil +parafoils +paraformaldehyde +paraformaldehydes +paragenesia +paragenesis +paragenetic +paragenetically +paragon +paragoned +paragoning +paragons +paragraph +paragraphed +paragrapher +paragraphers +paragraphic +paragraphical +paragraphing +paragraphs +paraguay +paraguayan +paraguayans +parainfluenza +parajournalism +parajournalist +parajournalistic +parajournalists +parakeet +parakeets +paralanguage +paraldehyde +paralegal +paralegals +paralinguistic +paralinguistics +paralipomenon +parallactic +parallax +parallaxes +parallel +paralleled +parallelepiped +parallelepipeds +paralleling +parallelism +parallelisms +parallelled +parallelling +parallelogram +parallelograms +parallels +paralogism +paralogisms +paralogist +paralogistic +paralogists +paralympian +paralympians +paralympic +paralyses +paralysis +paralytic +paralytically +paralytics +paralyzation +paralyzations +paralyze +paralyzed +paralyzer +paralyzers +paralyzes +paralyzing +paralyzingly +paramagnet +paramagnetic +paramagnetically +paramagnetism +paramagnets +paramaribo +paramatta +paramattas +paramecia +paramecium +parameciums +paramedic +paramedical +paramedics +parament +paramenta +paraments +parameter +parameterization +parameterizations +parameterize +parameterized +parameterizes +parameterizing +parameters +parametric +parametrical +parametrically +parametrization +parametrizations +parametrize +parametrized +parametrizes +parametrizing +paramilitaries +paramilitary +paramnesia +paramo +paramorph +paramorphic +paramorphine +paramorphines +paramorphism +paramorphisms +paramorphous +paramorphs +paramos +paramount +paramountcy +paramountly +paramour +paramours +paramylon +paramylons +paramylum +paramylums +paramyxovirus +paramyxoviruses +parang +parangs +paranoia +paranoiac +paranoiacs +paranoic +paranoically +paranoics +paranoid +paranoidal +paranoids +paranormal +paranormality +paranormally +paranymph +paranymphs +parapareses +paraparesis +parapet +parapeted +parapets +paraph +paraphernalia +paraphrasable +paraphrase +paraphrased +paraphraser +paraphrasers +paraphrases +paraphrasing +paraphrastic +paraphrastical +paraphrastically +paraphs +paraphyses +paraphysis +paraplegia +paraplegic +paraplegics +parapodia +parapodial +parapodium +parapraxes +parapraxis +paraprofessional +paraprofessionals +parapsychological +parapsychologist +parapsychologists +parapsychology +paraquat +paraquats +pararosaniline +pararosanilines +paras +parasail +parasailed +parasailer +parasailers +parasailing +parasails +parasang +parasangs +paraselenae +paraselene +paraselenic +parasensorily +parasensory +parasexual +parasexuality +parashah +parasite +parasites +parasitic +parasitical +parasitically +parasiticidal +parasiticide +parasiticides +parasitism +parasitization +parasitizations +parasitize +parasitized +parasitizes +parasitizing +parasitoid +parasitoids +parasitologic +parasitological +parasitologically +parasitologist +parasitologists +parasitology +parasitoses +parasitosis +parasol +parasoled +parasols +parasomnia +parasomnias +parastatal +parastatals +parasympathetic +parasympathetically +parasympathetics +parasympathomimetic +parasympathomimetics +parasyntheses +parasynthesis +parasynthetic +paratactic +paratactical +paratactically +parataxis +parathion +parathions +parathormone +parathormones +parathyroid +parathyroidectomies +parathyroidectomized +parathyroidectomy +parathyroids +paratroop +paratrooper +paratroopers +paratroops +paratyphoid +paravane +paravanes +paraxial +parboil +parboiled +parboiling +parboils +parbuckle +parbuckled +parbuckles +parbuckling +parcae +parcel +parceled +parceling +parcelled +parcelling +parcels +parcenaries +parcenary +parcener +parceners +parch +parched +parchedness +parcheesi +parches +parching +parchment +parchments +pard +pardi +pardie +pardner +pardners +pardon +pardonable +pardonableness +pardonably +pardoned +pardoner +pardoners +pardoning +pardons +pards +pardy +pare +pared +paregoric +paregorics +parenchyma +parenchymal +parenchymatous +parenchymatously +parent +parentage +parental +parentally +parented +parenteral +parenterally +parentheses +parenthesis +parenthesize +parenthesized +parenthesizes +parenthesizing +parenthetic +parenthetical +parenthetically +parenthood +parenting +parentis +parentless +parents +parenty +pareo +pareos +parer +parers +pares +pareses +paresis +paresthesia +paresthetic +paretic +paretically +paretics +pareu +pareus +pareve +parfait +parfaits +parfleche +parfleches +parfocal +parfocality +parfocalize +parfocalized +parfocalizes +parfocalizing +parge +parged +parges +parget +pargeted +pargeting +pargets +pargetted +pargetting +parging +pargyline +pargylines +parhelia +parhelic +parhelion +pari +pariah +pariahs +parian +parians +paribus +paricutin +paries +parietal +parietals +parietes +paring +parings +paripinnate +paris +parish +parishes +parishioner +parishioners +parisian +parisians +parisienne +parities +parity +park +parka +parkas +parked +parker +parkers +parking +parkinson +parkinson's +parkinsonian +parkinsonism +parkinsonisms +parkland +parklands +parklike +parks +parkway +parkways +parlance +parlances +parlando +parlante +parlay +parlayed +parlaying +parlays +parle +parled +parles +parley +parleyed +parleying +parleys +parliament +parliamentarian +parliamentarians +parliamentary +parliaments +parling +parlor +parlors +parlous +parlously +parma +parmenides +parmesan +parmesans +parmigiana +parmigiano +parnassian +parnassians +parnassus +parnassós +parnell +parochial +parochialism +parochialist +parochialists +parochially +parodic +parodical +parodied +parodies +parodist +parodistic +parodists +parody +parodying +parol +parole +paroled +parolee +parolees +paroles +paroling +parols +paronomasia +paronomasial +paronomasias +paronomastic +paronomastically +paronychia +paronychial +paronychias +paronym +paronymic +paronymous +paronyms +paros +parosmia +parosmias +parotid +parotidectomies +parotidectomy +parotiditis +parotids +parotitic +parotitis +parous +parousia +paroxysm +paroxysmal +paroxysmally +paroxysms +paroxytone +paroxytones +parquet +parqueted +parqueting +parquetries +parquetry +parquets +parr +parrakeet +parrakeets +parral +parrals +parramatta +parramattas +parred +parrel +parrels +parricidal +parricidally +parricide +parricides +parried +parries +parring +parrot +parroted +parroter +parroters +parrotfish +parrotfishes +parroting +parrots +parrs +parry +parrying +pars +parse +parsec +parsecs +parsed +parsee +parseeism +parsees +parser +parsers +parses +parsi +parsifal +parsiism +parsimonious +parsimoniously +parsimoniousness +parsimony +parsing +parsis +parsley +parsleyed +parsleys +parslied +parsnip +parsnips +parson +parsonage +parsonages +parsons +part +partake +partaken +partaker +partakers +partakes +partaking +parte +parted +parterre +parterres +parthenocarpic +parthenocarpically +parthenocarpy +parthenogenesis +parthenogenetic +parthenogenetically +parthenogenone +parthenogenones +parthenon +parthia +parthian +parthians +parti +partial +partialities +partiality +partially +partialness +partials +partibility +partible +participance +participant +participants +participate +participated +participates +participating +participation +participational +participations +participative +participator +participators +participatory +participial +participially +participials +participle +participles +particle +particleboard +particles +particular +particularism +particularist +particularistic +particularists +particularities +particularity +particularization +particularizations +particularize +particularized +particularizer +particularizers +particularizes +particularizing +particularly +particulars +particulate +particulates +partied +parties +parting +partings +partis +partisan +partisanly +partisans +partisanship +partisanships +partita +partitas +partite +partition +partitioned +partitioner +partitioners +partitioning +partitionings +partitionist +partitionists +partitionment +partitionments +partitions +partitive +partitively +partitives +partizan +partizans +partlet +partlets +partly +partner +partnered +partnering +partnerless +partners +partnership +partnerships +parton +partons +partook +partout +partridge +partridgeberry +partridges +parts +parturiency +parturient +parturifacient +parturifacients +parturition +parturitions +partway +party +partyer +partyers +partygoer +partygoers +partying +parure +parures +parvati +parve +parvenu +parvenue +parvenues +parvenus +parvis +parvise +parvises +parvo +parvos +parvovirus +parvoviruses +pará +pas +pasadena +pascal +pascals +pasch +pascha +paschal +pase +paseo +paseos +pases +pash +pasha +pashas +pashes +pashto +pashtun +pashtuns +pasiphaë +paso +pasqueflower +pasqueflowers +pasquinade +pasquinaded +pasquinader +pasquinaders +pasquinades +pasquinading +pass +passable +passableness +passably +passacaglia +passacaglias +passade +passades +passado +passadoes +passados +passage +passaged +passages +passageway +passageways +passagework +passageworks +passaging +passamaquoddies +passamaquoddy +passant +passband +passbands +passbook +passbooks +passchendaele +passe +passed +passel +passels +passementerie +passementeries +passenger +passengers +passepied +passepieds +passer +passerby +passerine +passerines +passers +passersby +passes +passibility +passible +passim +passing +passingly +passings +passion +passional +passionals +passionate +passionately +passionateness +passionflower +passionflowers +passionist +passionists +passionless +passionlessly +passions +passiontide +passiontides +passivate +passivated +passivates +passivating +passivation +passivations +passivator +passivators +passive +passively +passiveness +passives +passivism +passivisms +passivist +passivists +passivity +passkey +passkeys +passover +passovers +passport +passports +passu +password +passwords +passé +past +pasta +pastas +paste +pasteboard +pasteboards +pasted +pastedown +pastedowns +pastel +pastelist +pastelists +pastellist +pastellists +pastels +paster +pastern +pasternak +pasterns +pasters +pastes +pasteup +pasteups +pasteur +pasteurization +pasteurizations +pasteurize +pasteurized +pasteurizer +pasteurizers +pasteurizes +pasteurizing +pasticci +pasticcio +pasticcios +pastiche +pastiches +pasticheur +pasticheurs +pastier +pasties +pastiest +pastil +pastille +pastilles +pastils +pastime +pastimes +pastina +pastiness +pasting +pastis +pastises +pastless +pastness +pastor +pastoral +pastorale +pastorales +pastorali +pastoralism +pastoralisms +pastoralist +pastoralists +pastoralization +pastoralizations +pastoralize +pastoralized +pastoralizes +pastoralizing +pastorally +pastoralness +pastorals +pastorate +pastorates +pastored +pastoring +pastorium +pastoriums +pastors +pastorship +pastorships +pastrami +pastramis +pastries +pastromi +pastromis +pastry +pasts +pasturable +pasturage +pasture +pastured +pastureland +pasturelands +pasturer +pasturers +pastures +pasturing +pasty +pat +pataca +patacas +patagia +patagial +patagium +patagonia +patagonian +patagonians +pataphysics +patas +patch +patchable +patchboard +patchboards +patched +patcher +patchers +patches +patchier +patchiest +patchily +patchiness +patching +patchouli +patchoulies +patchoulis +patchouly +patchwork +patchworks +patchy +pate +pated +patella +patellae +patellar +patellate +patelliform +paten +patency +patens +patent +patentability +patentable +patented +patentee +patentees +patenting +patently +patentor +patentors +patents +pater +paterfamilias +paterfamiliases +paternal +paternalism +paternalist +paternalistic +paternalistically +paternalists +paternally +paternities +paternity +paternoster +paternosters +paters +pates +path +pathan +pathans +pathbreaking +pathetic +pathetical +pathetically +pathfinder +pathfinders +pathfinding +pathless +pathlessness +pathname +pathobiology +pathogen +pathogeneses +pathogenesis +pathogenetic +pathogenic +pathogenically +pathogenicity +pathogenies +pathogens +pathogeny +pathognomonic +pathography +pathologic +pathological +pathologically +pathologies +pathologist +pathologists +pathology +pathophysiologic +pathophysiological +pathophysiologist +pathophysiologists +pathophysiology +pathos +paths +pathway +pathways +pathétique +patience +patient +patiently +patients +patin +patina +patinae +patinaed +patinas +patinate +patinated +patinates +patinating +patination +patinations +patine +patined +patines +patining +patins +patio +patios +patisserie +patisseries +patissier +patissiers +patly +patmos +patna +patness +patois +patresfamilias +patriarch +patriarchal +patriarchalism +patriarchally +patriarchate +patriarchates +patriarchic +patriarchies +patriarchs +patriarchy +patricia +patrician +patricianly +patricians +patriciate +patriciates +patricidal +patricide +patricides +patrick +patriclinous +patrilineage +patrilineages +patrilineal +patrilocal +patrilocally +patrimonial +patrimonially +patrimonies +patrimony +patriot +patriotic +patriotically +patriotism +patriots +patristic +patristical +patristically +patristics +patroclinous +patroclus +patrol +patrolled +patroller +patrollers +patrolling +patrolman +patrolmen +patrols +patrolwoman +patrolwomen +patron +patronage +patronal +patroness +patronesses +patronization +patronizations +patronize +patronized +patronizer +patronizers +patronizes +patronizing +patronizingly +patrons +patronymic +patronymically +patronymics +patroon +patroons +pats +patsies +patsy +patted +patten +pattens +patter +pattered +patterer +patterers +pattering +pattern +patterned +patterning +patternings +patternless +patternmaker +patternmakers +patternmaking +patterns +patters +pattie +patties +patting +patty +pattypan +pattypans +patulent +patulous +patulously +patulousness +patzer +patzers +paucity +paul +pauline +paulist +paulists +paulo +paulownia +paulownias +paunch +paunches +paunchier +paunchiest +paunchiness +paunchy +pauper +pauperism +pauperization +pauperizations +pauperize +pauperized +pauperizes +pauperizing +paupers +paupiette +paupiettes +pausanias +pause +paused +pauses +pausing +pavan +pavane +pavanes +pavans +pavarotti +pave +paved +paveed +pavement +pavements +paver +pavers +paves +pavia +pavid +pavilion +pavilioned +pavilioning +pavilions +paving +pavings +pavis +pavises +pavisse +pavisses +pavlov +pavlova +pavlovian +pavo +pavonine +pavé +paw +pawed +pawer +pawers +pawing +pawkier +pawkiest +pawky +pawl +pawls +pawn +pawnable +pawnage +pawnages +pawnbroker +pawnbrokers +pawnbroking +pawned +pawnee +pawnees +pawner +pawners +pawning +pawnor +pawnors +pawns +pawnshop +pawnshops +pawpaw +pawpaws +paws +pax +pay +payable +payables +payback +paybacks +paycheck +paychecks +payday +paydays +payed +payee +payees +payer +payers +paying +payload +payloader +payloads +paymaster +paymasters +payment +payments +paynim +paynims +payoff +payoffs +payola +payolas +payor +payors +payout +payouts +payphone +payphones +payroll +payrolls +pays +pc +pcs +pe +pea +peabody +peace +peaceable +peaceableness +peaceably +peaceful +peacefully +peacefulness +peacekeeper +peacekeepers +peacekeeping +peacemaker +peacemakers +peacemaking +peacenik +peaceniks +peacetime +peacetimes +peach +peached +peaches +peachick +peachicks +peachier +peachiest +peachiness +peaching +peachy +peacock +peacocked +peacocking +peacockish +peacocks +peacocky +peafowl +peafowls +peag +peage +peages +peags +peahen +peahens +peak +peaked +peakedness +peaking +peaks +peaky +peal +pealed +pealike +pealing +peals +pean +peans +peanut +peanuts +pear +pearl +pearled +pearler +pearlers +pearlescence +pearlescent +pearlier +pearliest +pearliness +pearling +pearlite +pearlites +pearlitic +pearlized +pearls +pearly +pears +peart +peartly +peas +peasant +peasantry +peasants +peascod +peascods +pease +peasecod +peasecods +peashooter +peashooters +peat +peats +peaty +peavey +peaveys +peavies +peavy +peavys +pebble +pebbled +pebbles +pebbling +pebbly +pec +pecan +pecans +peccability +peccable +peccadillo +peccadilloes +peccadillos +peccancies +peccancy +peccant +peccantly +peccaries +peccary +peccavi +peccavis +peck +pecked +pecker +peckers +peckerwood +peckerwoods +pecking +peckish +pecks +pecksniffian +pecky +pecorino +pecorinos +pecs +pectase +pectases +pectate +pectates +pecten +pectens +pectic +pectin +pectinaceous +pectinate +pectinated +pectination +pectinations +pectines +pectinesterase +pectinesterases +pectinous +pectins +pectoral +pectorals +pectoris +peculate +peculated +peculates +peculating +peculation +peculations +peculator +peculators +peculiar +peculiarities +peculiarity +peculiarly +peculiars +pecuniarily +pecuniary +ped +pedagog +pedagogic +pedagogical +pedagogically +pedagogics +pedagogs +pedagogue +pedagogues +pedagoguish +pedagogy +pedal +pedaled +pedaler +pedalers +pedalfer +pedalfers +pedaling +pedalled +pedaller +pedallers +pedalling +pedalo +pedalos +pedals +pedant +pedantic +pedantically +pedantries +pedantry +pedants +pedate +peddle +peddled +peddler +peddlers +peddles +peddling +pederast +pederastic +pederasties +pederasts +pederasty +pedes +pedestal +pedestaled +pedestaling +pedestalled +pedestalling +pedestals +pedestrian +pedestrianism +pedestrianization +pedestrianizations +pedestrianize +pedestrianized +pedestrianizes +pedestrianizing +pedestrians +pediatric +pediatrician +pediatricians +pediatrics +pediatrist +pediatrists +pedicab +pedicabs +pedicel +pedicellar +pedicellate +pedicels +pedicle +pedicled +pedicles +pedicular +pediculate +pediculates +pediculosis +pediculous +pedicure +pedicured +pedicures +pedicuring +pedicurist +pedicurists +pediform +pedigree +pedigreed +pedigrees +pediment +pedimental +pedimented +pediments +pedipalp +pedipalps +pedlar +pedlars +pedocal +pedocalic +pedocals +pedodontia +pedodontias +pedodontics +pedodontists +pedogeneses +pedogenesis +pedogenetic +pedogenic +pedologic +pedological +pedologically +pedologist +pedologists +pedology +pedometer +pedometers +pedomorph +pedomorphism +pedomorphisms +pedomorphoses +pedomorphosis +pedomorphs +pedophile +pedophiles +pedophilia +pedophiliac +pedophiliacs +pedophilic +peduncle +peduncled +peduncles +peduncular +pedunculate +pedunculated +pee +peed +peeing +peek +peekaboo +peeked +peeking +peeks +peel +peelable +peeled +peeler +peelers +peeling +peelings +peels +peen +peened +peening +peens +peep +peeped +peeper +peepers +peephole +peepholes +peeping +peeps +peepshow +peepshows +peepul +peepuls +peer +peerage +peerages +peered +peeress +peeresses +peering +peerless +peerlessly +peerlessness +peers +pees +peetweet +peetweets +peeve +peeved +peeves +peeving +peevish +peevishly +peevishness +peewee +peewees +peewit +peewits +peg +pegasus +pegboard +pegboards +pegged +pegging +pegmatite +pegmatitic +pegs +pehlevi +peignoir +peignoirs +pein +peined +peining +peins +pejoration +pejorations +pejorative +pejoratively +pejoratives +pekan +pekans +peke +pekes +pekin +pekinese +peking +pekingese +pekins +pekoe +pekoes +pelage +pelages +pelagian +pelagianism +pelagians +pelagic +pelargonic +pelargonium +pelargoniums +pelasgian +pelasgians +pelasgic +pelecypod +pelecypods +pelerine +pelerines +pelew +pelf +pelican +pelicans +pelion +pelisse +pelisses +pelite +pelites +pelitic +pell +pellagra +pellagrin +pellagrins +pellagrous +pellet +pelletal +pelleted +pelleting +pelletization +pelletizations +pelletize +pelletized +pelletizer +pelletizers +pelletizes +pelletizing +pellets +pellicle +pellicles +pellicular +pellitories +pellitory +pellucid +pellucida +pellucidae +pellucidity +pellucidly +pellucidness +pelmet +pelmets +peloponnese +peloponnesian +peloponnesians +peloponnesos +peloponnesus +peloria +pelorias +peloric +pelorus +peloruses +pelota +pelotas +pelt +peltate +peltately +pelted +pelter +pelters +pelting +peltries +peltry +pelts +pelves +pelvic +pelvimeter +pelvimeters +pelvimetry +pelvis +pelvises +pelycosaur +pelycosaurs +pelée +pemba +pembroke +pemican +pemicans +pemmican +pemmicans +pemoline +pemolines +pemphigous +pemphigus +pemphiguses +pen +penal +penalization +penalizations +penalize +penalized +penalizes +penalizing +penally +penalties +penalty +penance +penanced +penances +penancing +penang +penates +pence +pencel +pencels +penchant +penchants +pencil +penciled +penciler +pencilers +penciling +pencilled +penciller +pencillers +pencilling +pencils +pendant +pendants +pendelikón +pendency +pendent +pendentive +pendently +pendents +pending +pendular +pendulous +pendulously +pendulousness +pendulum +pendulums +penelope +peneplain +peneplains +peneplane +peneplanes +penes +penetrability +penetrable +penetrably +penetralia +penetrameter +penetrameters +penetrance +penetrances +penetrant +penetrants +penetrate +penetrated +penetrates +penetrating +penetratingly +penetration +penetrations +penetrative +penetrator +penetrators +penetrometer +penetrometers +penghu +pengo +pengos +penguin +penguins +penh +penholder +penholders +penicillamine +penicillamines +penicillate +penicillately +penicillation +penicillations +penicillia +penicillin +penicillinase +penicillinases +penicillium +penicilliums +penicuik +penile +peninsula +peninsular +peninsulas +penis +penises +penitence +penitences +penitent +penitente +penitentes +penitential +penitentially +penitentials +penitentiaries +penitentiary +penitently +penitents +penknife +penknives +penlight +penlights +penlite +penlites +penman +penmanship +penmen +penn +penna +pennaceous +pennae +penname +pennames +pennant +pennants +pennate +pennated +penne +penned +penner +penners +penni +pennia +pennies +penniless +pennilessly +pennilessness +pennine +pennines +penning +pennis +pennon +pennoncel +pennoncelle +pennoncelles +pennoncels +pennoned +pennons +pennsylvania +pennsylvanian +pennsylvanians +penny +pennycress +pennycresses +pennyroyal +pennyroyals +pennyweight +pennyweights +pennywhistle +pennywhistles +pennywise +pennywort +pennyworth +pennyworths +pennyworts +penobscot +penobscots +penoche +penological +penologically +penologist +penologists +penology +penoncel +penoncels +pens +pensil +pensile +pensils +pension +pensionable +pensionaries +pensionary +pensione +pensioned +pensioner +pensioners +pensiones +pensioning +pensionless +pensions +pensive +pensively +pensiveness +penstemon +penstemons +penstock +penstocks +pensée +pensées +pent +pentachlorophenol +pentachlorophenols +pentacle +pentacles +pentad +pentadactyl +pentadactylate +pentadactylism +pentads +pentagon +pentagonal +pentagonally +pentagonese +pentagons +pentagram +pentagrams +pentagynous +pentahedra +pentahedral +pentahedron +pentahedrons +pentamerism +pentamerous +pentameter +pentameters +pentamidine +pentandrous +pentane +pentanes +pentangle +pentangles +pentangular +pentapeptide +pentapeptides +pentaploid +pentaploids +pentaploidy +pentaquin +pentaquine +pentaquines +pentaquins +pentarchical +pentarchies +pentarchy +pentastich +pentastiches +pentastome +pentastomes +pentateuch +pentateuchal +pentathlete +pentathletes +pentathlon +pentathlons +pentatonic +pentavalent +pentazocine +pentazocines +pentecost +pentecostal +pentecostalism +pentecostalist +pentecostalists +pentecostals +penthouse +penthouses +pentimenti +pentimento +pentlandite +pentlandites +pentobarbital +pentobarbitone +pentobarbitones +pentosan +pentosans +pentose +pentoses +pentothal +pentoxide +pentoxides +pentstemon +pentstemons +pentyl +pentylenetetrazol +pentylenetetrazols +pentyls +penuche +penuches +penuchi +penuchis +penuchle +penuckle +penult +penultima +penultimas +penultimate +penultimately +penultimates +penults +penumbra +penumbrae +penumbral +penumbras +penumbrous +penurious +penuriously +penuriousness +penury +penutian +peon +peonage +peones +peonies +peons +peony +people +peopled +peoplehood +peopleless +peopler +peoplers +peoples +peopling +peoria +peorias +pep +peperomia +peperomias +pepier +pepiest +pepino +pepinos +peplos +peploses +peplum +peplumed +peplums +peplus +pepluses +pepo +pepos +pepped +pepper +pepperbox +pepperboxes +pepperbush +pepperbushes +peppercorn +peppercorns +peppercress +peppercresses +peppered +pepperer +pepperers +peppergrass +peppergrasses +pepperidge +pepperidges +pepperiness +peppering +peppermint +peppermints +pepperminty +pepperoni +pepperonis +peppers +peppershaker +peppershakers +peppertree +peppertrees +pepperwood +pepperwoods +pepperwort +pepperworts +peppery +peppier +peppiest +peppily +peppiness +pepping +peppy +peps +pepsi +pepsin +pepsine +pepsines +pepsinogen +pepsinogens +pepsins +peptic +peptics +peptidase +peptidases +peptide +peptides +peptidic +peptidically +peptidoglycan +peptidoglycans +peptization +peptizations +peptize +peptized +peptizer +peptizers +peptizes +peptizing +peptone +peptones +peptonic +peptonization +peptonizations +peptonize +peptonized +peptonizes +peptonizing +pepys +pequot +pequots +per +peracid +peracids +peradventure +peradventures +perambulate +perambulated +perambulates +perambulating +perambulation +perambulations +perambulator +perambulators +perambulatory +perborate +perborates +percale +percales +percaline +percalines +perceivable +perceivably +perceive +perceived +perceiver +perceivers +perceives +perceiving +percent +percentage +percentages +percenter +percenters +percentile +percentiles +percentism +percents +percept +perceptibility +perceptible +perceptibly +perception +perceptional +perceptions +perceptive +perceptively +perceptiveness +perceptivity +percepts +perceptual +perceptually +perch +perchance +perched +percher +percheron +percherons +perchers +perches +perching +perchlorate +perchlorates +perchloric +perchlorid +perchloride +perchlorides +perchlorids +perchloroethylene +perchloroethylenes +perciatelli +percipience +percipiency +percipient +percipiently +percipients +percodan +percoid +percoidean +percoids +percolate +percolated +percolates +percolating +percolation +percolations +percolator +percolators +percurrent +percuss +percussed +percusses +percussing +percussion +percussionist +percussionists +percussions +percussive +percussively +percussiveness +percutaneous +percutaneously +percy +perdie +perdita +perdition +perdu +perdue +perdues +perdurability +perdurable +perdurably +perdure +perdured +perdures +perduring +perdus +peregrinate +peregrinated +peregrinates +peregrinating +peregrination +peregrinations +peregrinator +peregrinators +peregrine +peregrines +pereion +pereiopod +pereiopods +peremptorily +peremptoriness +peremptory +perennate +perennated +perennates +perennating +perennation +perennations +perennial +perennially +perennials +perentie +perenties +pereon +pereopod +pereopods +perestroika +perfect +perfecta +perfectas +perfected +perfecter +perfecters +perfectibility +perfectible +perfecting +perfection +perfectionism +perfectionist +perfectionistic +perfectionists +perfections +perfective +perfectively +perfectiveness +perfectives +perfectivity +perfectly +perfectness +perfecto +perfectos +perfects +perfervid +perfervidly +perfervidness +perfidies +perfidious +perfidiously +perfidiousness +perfidy +perfoliate +perfoliation +perforable +perforate +perforated +perforates +perforating +perforation +perforations +perforative +perforator +perforators +perforce +perform +performability +performable +performance +performances +performative +performatory +performed +performer +performers +performing +performs +perfume +perfumed +perfumer +perfumeries +perfumers +perfumery +perfumes +perfuming +perfunctorily +perfunctoriness +perfunctory +perfusate +perfusates +perfuse +perfused +perfuses +perfusing +perfusion +perfusionist +perfusionists +perfusions +perfusive +pergamum +pergola +pergolas +perhaps +perianth +perianths +periapt +periapts +periaqueductal +pericardia +pericardiac +pericardial +pericarditis +pericardium +pericarp +pericarpial +pericarps +perichondral +perichondria +perichondrial +perichondrium +periclase +periclases +periclean +pericles +pericline +periclines +pericope +pericopes +pericrania +pericranial +pericranium +pericycle +pericycles +pericyclic +periderm +peridermal +peridermic +periderms +peridia +peridial +peridium +peridot +peridotic +peridotite +peridotites +peridotitic +peridots +perigeal +perigean +perigee +perigees +perigynous +perigyny +perihelia +perihelial +perihelion +perikarya +perikaryal +perikaryon +peril +periled +periling +perilla +perillas +perilled +perilling +perilous +perilously +perilousness +perils +perilune +perilunes +perilymph +perilymphatic +perilymphs +perimeter +perimeters +perimetric +perimetrical +perimetrically +perimorph +perimorphic +perimorphism +perimorphous +perimorphs +perimysia +perimysium +perinatal +perinatally +perinatology +perinea +perineal +perinephral +perinephria +perinephrial +perinephric +perinephrium +perineum +perineuria +perineurial +perineurium +period +periodic +periodical +periodically +periodicals +periodicities +periodicity +periodization +periodizations +periodontal +periodontally +periodontia +periodontias +periodontic +periodontical +periodontics +periodontist +periodontists +periodontology +periods +perionychia +perionychium +periostea +periosteal +periosteous +periosteum +periostitic +periostitis +periostitises +periostraca +periostracum +periotic +peripatetic +peripatetically +peripateticism +peripatetics +peripatus +peripatuses +peripeteia +peripeteias +peripetia +peripetias +peripeties +peripety +peripheral +peripherally +peripherals +peripheries +periphery +periphrases +periphrasis +periphrastic +periphrastically +periphytic +periphytics +periphyton +periphytons +periplasm +periplasmic +periplasms +periplast +periplasts +periproct +periprocts +peripteral +perique +periques +perisarc +perisarcal +perisarcous +perisarcs +periscope +periscopes +periscopic +periscopical +perish +perishability +perishable +perishableness +perishables +perishably +perished +perishes +perishing +perisperm +perisperms +perissodactyl +perissodactyla +perissodactylous +perissodactyls +peristalses +peristalsis +peristaltic +peristaltically +peristomal +peristome +peristomes +peristomial +peristylar +peristyle +peristyles +perithecia +perithecial +perithecium +peritonaea +peritonaeum +peritonea +peritoneal +peritoneally +peritoneum +peritoneums +peritonitis +peritrich +peritricha +peritrichous +peritrichously +peritrichs +perivisceral +periwig +periwigged +periwigs +periwinkle +periwinkles +perjure +perjured +perjurer +perjurers +perjures +perjuries +perjuring +perjurious +perjuriously +perjury +perk +perked +perkier +perkiest +perkily +perkiness +perking +perks +perky +perlite +perlites +perlitic +perm +permaculture +permacultures +permafrost +permalloy +permanence +permanencies +permanency +permanent +permanently +permanentness +permanents +permanganate +permanganates +permanganic +permeabilities +permeability +permeable +permeably +permeance +permeances +permeant +permease +permeases +permeate +permeated +permeates +permeating +permeation +permeations +permeative +permed +permethrin +permian +permillage +perming +permissibility +permissible +permissibleness +permissibly +permission +permissions +permissive +permissively +permissiveness +permit +permits +permitted +permittee +permittees +permitter +permitters +permitting +permittivities +permittivity +perms +permutability +permutable +permutably +permutation +permutational +permutations +permute +permuted +permutes +permuting +pernambuco +pernicious +perniciously +perniciousness +pernickety +pernod +peroneal +peroral +perorally +perorate +perorated +perorates +perorating +peroration +perorational +perorations +perovskite +perovskites +peroxidase +peroxidases +peroxide +peroxided +peroxides +peroxidic +peroxiding +peroxisomal +peroxisome +peroxisomes +peroxyacetyl +perp +perpend +perpended +perpendicular +perpendicularity +perpendicularly +perpendiculars +perpending +perpends +perpetrate +perpetrated +perpetrates +perpetrating +perpetration +perpetrations +perpetrator +perpetrators +perpetual +perpetually +perpetuance +perpetuances +perpetuate +perpetuated +perpetuates +perpetuating +perpetuation +perpetuations +perpetuator +perpetuators +perpetuities +perpetuity +perphenazine +perphenazines +perpignan +perplex +perplexed +perplexedly +perplexes +perplexing +perplexingly +perplexities +perplexity +perps +perquisite +perquisites +perrault +perries +perron +perrons +perry +perse +persecute +persecuted +persecutee +persecutees +persecutes +persecuting +persecution +persecutional +persecutions +persecutive +persecutor +persecutors +persecutory +perseid +perseides +perseids +persephone +persepolis +perseus +perseverance +perseverant +perseverate +perseverated +perseverates +perseverating +perseveration +perseverations +perseverative +persevere +persevered +perseveres +persevering +perseveringly +persia +persian +persians +persiflage +persimmon +persimmons +persist +persisted +persistence +persistency +persistent +persistently +persister +persisters +persisting +persists +persnicketiness +persnickety +person +persona +personable +personableness +personably +personae +personage +personages +personal +personalia +personalism +personalisms +personalist +personalistic +personalists +personalities +personality +personalization +personalizations +personalize +personalized +personalizes +personalizing +personally +personals +personalties +personalty +personas +personate +personated +personates +personating +personation +personations +personative +personator +personators +personhood +personification +personifications +personified +personifier +personifiers +personifies +personify +personifying +personnel +persons +perspectival +perspective +perspectively +perspectives +perspex +perspicacious +perspicaciously +perspicaciousness +perspicacity +perspicuity +perspicuous +perspicuously +perspicuousness +perspiration +perspiratory +perspire +perspired +perspires +perspiring +persuadable +persuadably +persuade +persuaded +persuader +persuaders +persuades +persuading +persuasibility +persuasible +persuasibleness +persuasion +persuasions +persuasive +persuasively +persuasiveness +pert +pertain +pertained +pertaining +pertains +perter +pertest +perth +pertinacious +pertinaciously +pertinaciousness +pertinacity +pertinence +pertinency +pertinent +pertinently +pertly +pertness +perturb +perturbable +perturbation +perturbational +perturbations +perturbed +perturbing +perturbs +pertussal +pertussis +peru +perugia +peruke +peruked +perukes +perusable +perusal +perusals +peruse +perused +peruser +perusers +peruses +perusing +peruvian +peruvians +pervade +pervaded +pervader +pervaders +pervades +pervading +pervasion +pervasions +pervasive +pervasively +pervasiveness +perverse +perversely +perverseness +perversion +perversions +perversities +perversity +perversive +pervert +perverted +pervertedly +pervertedness +perverter +perverters +pervertible +perverting +perverts +pervious +perviously +perviousness +pes +pesach +pesade +pesades +pescadores +peseta +pesetas +pesewa +pesewas +peshawar +peskier +peskiest +peskily +peskiness +pesky +peso +pesos +pessaries +pessary +pessimism +pessimist +pessimistic +pessimistically +pessimists +pest +pester +pestered +pesterer +pesterers +pestering +pesters +pesthole +pestholes +pesthouse +pesthouses +pesticidal +pesticide +pesticides +pestiferous +pestiferously +pestiferousness +pestilence +pestilences +pestilent +pestilential +pestilentially +pestilently +pestle +pestled +pestles +pestling +pesto +pestos +pests +pesty +pet +petaampere +petaamperes +petabecquerel +petabecquerels +petabit +petabits +petabyte +petabytes +petacandela +petacandelas +petacoulomb +petacoulombs +petafarad +petafarads +petagram +petagrams +petahenries +petahenry +petahenrys +petahertz +petajoule +petajoules +petakelvin +petakelvins +petal +petaled +petaliferous +petaline +petalled +petallike +petaloid +petalous +petals +petalumen +petalumens +petalux +petameter +petameters +petamole +petamoles +petanewton +petanewtons +petaohm +petaohms +petapascal +petapascals +petaradian +petaradians +petard +petards +petasecond +petaseconds +petasiemens +petasievert +petasieverts +petasos +petasoses +petasteradian +petasteradians +petasus +petasuses +petatesla +petateslas +petavolt +petavolts +petawatt +petawatts +petaweber +petawebers +petcock +petcocks +petechia +petechiae +petechial +petechiate +peter +peter's +petered +petering +peters +petersburg +petiolar +petiolate +petiole +petioled +petioles +petiolule +petiolules +petit +petite +petiteness +petites +petition +petitionary +petitioned +petitioner +petitioners +petitioning +petitions +petits +petnapper +petnappers +petnapping +petnappings +petrale +petrarch +petrarchan +petrel +petrels +petri +petrifaction +petrifactions +petrification +petrifications +petrified +petrifies +petrify +petrifying +petrine +petrochemical +petrochemicals +petrochemistries +petrochemistry +petrodollar +petrodollars +petrogenesis +petrogenetic +petroglyph +petroglyphic +petroglyphs +petrograd +petrographer +petrographers +petrographic +petrographical +petrographically +petrography +petrol +petrolatum +petroleum +petrolic +petroliferous +petrologic +petrological +petrologically +petrologist +petrologists +petrology +petronel +petronels +petronius +petropolitics +petrosal +petrous +pets +petted +petter +petters +petti +petticoat +petticoated +petticoats +pettier +pettiest +pettifog +pettifogged +pettifogger +pettifoggers +pettifoggery +pettifogging +pettifogs +pettily +pettiness +pettinesses +petting +pettis +pettish +pettishly +pettishness +pettiskirt +pettiskirts +pettislip +pettislips +pettitoes +petty +petulance +petulancy +petulant +petulantly +petunia +petunias +petuntse +petuntses +petuntze +petuntzes +peugeot +pew +pewee +pewees +pewholder +pewholders +pewit +pewits +pews +pewter +pewterer +pewterers +peyote +peyotl +peyotls +pfennig +pfennige +pfennigs +pfft +ph +phacoemulsification +phacoemulsifications +phaedra +phaedrus +phaeton +phaetons +phage +phages +phagocyte +phagocytes +phagocytic +phagocytize +phagocytized +phagocytizes +phagocytizing +phagocytose +phagocytosed +phagocytoses +phagocytosing +phagocytosis +phagocytotic +phagosome +phagosomes +phalangal +phalange +phalangeal +phalangean +phalanger +phalangers +phalanges +phalangist +phalangists +phalansterian +phalansterianism +phalansterians +phalansteries +phalanstery +phalanx +phalanxes +phalarope +phalaropes +phalli +phallic +phallically +phallicism +phallocentric +phallus +phalluses +phanerogam +phanerogamic +phanerogamous +phanerogams +phanerophyte +phanerophytes +phanerozoic +phantasies +phantasm +phantasma +phantasmagoria +phantasmagorias +phantasmagoric +phantasmagorical +phantasmagorically +phantasmagories +phantasmagory +phantasmal +phantasmata +phantasmic +phantasms +phantasy +phantom +phantomlike +phantoms +pharaoh +pharaohs +pharaonic +pharisaic +pharisaical +pharisaically +pharisaicalness +pharisaism +pharisaisms +pharisee +phariseeism +phariseeisms +pharisees +pharmaceutic +pharmaceutical +pharmaceutically +pharmaceuticals +pharmaceutics +pharmacies +pharmacist +pharmacists +pharmacodynamic +pharmacodynamically +pharmacodynamics +pharmacogenetic +pharmacogenetics +pharmacogenomic +pharmacogenomics +pharmacognosist +pharmacognosists +pharmacognostic +pharmacognostical +pharmacognosy +pharmacokinetic +pharmacokinetics +pharmacologic +pharmacological +pharmacologically +pharmacologist +pharmacologists +pharmacology +pharmacopeia +pharmacopeial +pharmacopeias +pharmacopoeia +pharmacopoeial +pharmacopoeias +pharmacopoeist +pharmacopoeists +pharmacotherapies +pharmacotherapy +pharmacy +pharos +pharoses +pharyngal +pharyngals +pharyngeal +pharyngeals +pharyngectomies +pharyngectomy +pharynges +pharyngitis +pharyngitises +pharyngocele +pharyngoceles +pharyngology +pharyngoscope +pharyngoscopes +pharyngoscopy +pharynx +pharynxes +phase +phased +phasedown +phasedowns +phaseout +phaseouts +phases +phasic +phasing +phasmid +phasmids +phatic +phatically +phaëthon +pheasant +pheasants +phellem +phellems +phelloderm +phellodermal +phelloderms +phellogen +phellogenic +phellogens +phenacaine +phenacaines +phenacetin +phenacetins +phenacite +phenacites +phenakite +phenakites +phenanthrene +phenanthrenes +phenarsazine +phenazin +phenazine +phenazines +phenazins +phencyclidine +phencyclidines +phenelzine +phenelzines +phenetic +phenetically +pheneticist +pheneticists +phenetics +phenix +phenixes +phenmetrazine +phenmetrazines +phenobarbital +phenobarbitone +phenobarbitones +phenocopies +phenocopy +phenocryst +phenocrystic +phenocrysts +phenol +phenolate +phenolates +phenolic +phenolics +phenological +phenologically +phenologist +phenologists +phenology +phenolphthalein +phenolphthaleins +phenols +phenom +phenomena +phenomenal +phenomenalism +phenomenalisms +phenomenalist +phenomenalistic +phenomenalistically +phenomenalists +phenomenally +phenomenological +phenomenologically +phenomenologist +phenomenologists +phenomenology +phenomenon +phenomenons +phenoms +phenothiazine +phenothiazines +phenotype +phenotypes +phenotypic +phenotypical +phenotypically +phenoxide +phenoxides +phenoxybenzamine +phenoxybenzamines +phentolamine +phentolamines +phenyl +phenylalanine +phenylalanines +phenylbutazone +phenylbutazones +phenylene +phenylenes +phenylenevinylene +phenylephrine +phenylephrines +phenylethylamine +phenylethylamines +phenylic +phenylketonuria +phenylketonurias +phenylketonuric +phenylketonurics +phenylpropanolamine +phenylpropanolamines +phenyls +phenylthiocarbamide +phenylthiocarbamides +phenylthiourea +phenylthioureas +phenytoin +phenytoins +pheochromocytoma +pheochromocytomas +pheochromocytomata +pheresis +pheromonal +pheromone +pheromones +phew +phi +phial +phials +phidias +philadelphia +philadelphian +philadelphians +philadelphus +philander +philandered +philanderer +philanderers +philandering +philanders +philanthropic +philanthropical +philanthropically +philanthropies +philanthropist +philanthropists +philanthropoid +philanthropoids +philanthropy +philatelic +philatelical +philatelically +philatelist +philatelists +philately +philemon +philharmonic +philharmonics +philhellene +philhellenes +philhellenic +philhellenism +philhellenist +philhellenists +philip +philippi +philippians +philippic +philippics +philippine +philippines +philistia +philistine +philistines +philistinism +philistinisms +phillips +phillumenist +phillumenists +philoctetes +philodendra +philodendron +philodendrons +philologer +philologers +philologic +philological +philologically +philologist +philologists +philology +philomel +philomela +philomels +philoprogenitive +philoprogenitively +philoprogenitiveness +philosophe +philosopher +philosophers +philosophes +philosophic +philosophical +philosophically +philosophies +philosophize +philosophized +philosophizer +philosophizers +philosophizes +philosophizing +philosophy +philter +philtered +philtering +philters +philtre +philtred +philtres +philtring +phimoses +phimosis +phiz +phizes +phlebitic +phlebitides +phlebitis +phlebogram +phlebograms +phlebographic +phlebography +phlebology +phlebosclerosis +phlebotomic +phlebotomical +phlebotomies +phlebotomist +phlebotomists +phlebotomize +phlebotomized +phlebotomizes +phlebotomizing +phlebotomus +phlebotomy +phlegethon +phlegm +phlegmatic +phlegmatical +phlegmatically +phlegmy +phloem +phlogistic +phlogiston +phlogistons +phlogopite +phlogopites +phlox +phloxes +phlyctaena +phlyctaenae +phlyctena +phlyctenae +phlyctenar +phnom +phobia +phobias +phobic +phobics +phobos +phocine +phocomelia +phocomelias +phoebe +phoebes +phoebus +phoenicia +phoenician +phoenicians +phoenix +phoenixes +phoenixlike +phon +phonate +phonated +phonates +phonating +phonation +phonations +phone +phoned +phonematic +phoneme +phonemes +phonemic +phonemically +phonemicist +phonemicists +phonemics +phones +phonetic +phonetical +phonetically +phonetician +phoneticians +phoneticist +phoneticists +phonetics +phoney +phoneyed +phoneying +phoneys +phonic +phonically +phonics +phonied +phonier +phonies +phoniest +phonily +phoniness +phoning +phono +phonocardiogram +phonocardiograms +phonocardiograph +phonocardiographic +phonocardiographs +phonocardiography +phonogram +phonogramic +phonogramically +phonogrammic +phonogrammically +phonograms +phonograph +phonographer +phonographers +phonographic +phonographically +phonographist +phonographists +phonographs +phonography +phonolite +phonolites +phonolitic +phonologic +phonological +phonologically +phonologies +phonologist +phonologists +phonology +phonometric +phonon +phonons +phonoreception +phonoreceptions +phonoreceptor +phonoreceptors +phonos +phonoscope +phonoscopes +phonotactic +phonotactics +phonotype +phonotypes +phonotypic +phonotypical +phonotypically +phonotypist +phonotypists +phonotypy +phons +phony +phonying +phooey +phorate +phorates +phoresies +phoresy +phoronid +phoronids +phosgene +phosphamidon +phosphamidons +phosphatase +phosphatases +phosphate +phosphates +phosphatic +phosphatide +phosphatides +phosphatidic +phosphatization +phosphatizations +phosphatize +phosphatized +phosphatizes +phosphatizing +phosphaturia +phosphaturias +phosphaturic +phosphene +phosphenes +phosphid +phosphide +phosphides +phosphids +phosphin +phosphine +phosphines +phosphins +phosphite +phosphites +phosphocreatin +phosphocreatine +phosphocreatines +phosphocreatins +phosphofructokinase +phosphofructokinases +phosphoinositide +phospholipid +phospholipids +phosphonium +phosphoniums +phosphoprotein +phosphoproteins +phosphor +phosphorate +phosphorated +phosphorates +phosphorating +phosphore +phosphores +phosphoresce +phosphoresced +phosphorescence +phosphorescent +phosphorescently +phosphoresces +phosphorescing +phosphoric +phosphorism +phosphorisms +phosphorite +phosphorites +phosphoritic +phosphorolysis +phosphorolytic +phosphorous +phosphors +phosphorus +phosphoryl +phosphorylase +phosphorylases +phosphorylate +phosphorylated +phosphorylates +phosphorylating +phosphorylation +phosphorylations +phosphorylative +phosphoryls +phot +photic +photically +photo +photoactive +photoactivity +photoautotroph +photoautotrophic +photoautotrophically +photoautotrophs +photobiologic +photobiological +photobiologist +photobiologists +photobiology +photobiotic +photocathode +photocathodes +photocell +photocells +photochemical +photochemically +photochemist +photochemistry +photochemists +photochromic +photochromism +photocoagulate +photocoagulated +photocoagulates +photocoagulating +photocoagulation +photocoagulations +photocompose +photocomposed +photocomposer +photocomposers +photocomposes +photocomposing +photocomposition +photoconduction +photoconductive +photoconductivities +photoconductivity +photocopied +photocopier +photocopiers +photocopies +photocopy +photocopying +photocurrent +photocurrents +photodecomposition +photodecompositions +photodegradable +photodetector +photodetectors +photodiode +photodiodes +photodisintegrate +photodisintegrated +photodisintegrates +photodisintegrating +photodisintegration +photodisintegrations +photodissociate +photodissociated +photodissociates +photodissociating +photodissociation +photodissociations +photodrama +photodramas +photoduplicate +photoduplicated +photoduplicates +photoduplicating +photoduplication +photoduplications +photodynamic +photodynamically +photodynamics +photoed +photoelectric +photoelectrical +photoelectrically +photoelectron +photoelectronic +photoelectrons +photoemission +photoemissions +photoemissive +photoengrave +photoengraved +photoengraver +photoengravers +photoengraves +photoengraving +photoengravings +photoexcitation +photoexcitations +photoexcited +photofinisher +photofinishers +photofinishing +photofinishings +photoflash +photoflashes +photoflood +photofloods +photofluorogram +photofluorograms +photofluorographic +photofluorography +photog +photogelatin +photogene +photogenes +photogenic +photogenically +photogeologic +photogeological +photogeologist +photogeologists +photogeology +photogram +photogrammetric +photogrammetrist +photogrammetrists +photogrammetry +photograms +photograph +photographable +photographed +photographer +photographers +photographic +photographical +photographically +photographing +photographs +photography +photogravure +photogravures +photogs +photoheliograph +photoheliographs +photoinduced +photoinduction +photoinductions +photoinductive +photoing +photointerpretation +photointerpreter +photointerpreters +photoionization +photoionizations +photoionize +photoionized +photoionizes +photoionizing +photojournalism +photojournalist +photojournalistic +photojournalists +photokinesis +photokinetic +photolithograph +photolithographed +photolithographer +photolithographers +photolithographic +photolithographically +photolithographing +photolithographs +photolithography +photoluminescence +photolysis +photolytic +photolytically +photolyzable +photolyze +photolyzed +photolyzes +photolyzing +photomap +photomapped +photomapping +photomaps +photomask +photomasks +photomechanical +photomechanically +photometer +photometers +photometric +photometrical +photometrically +photometrist +photometrists +photometry +photomicrograph +photomicrographed +photomicrographer +photomicrographers +photomicrographic +photomicrographing +photomicrographs +photomicrography +photomicroscope +photomicroscopes +photomicroscopic +photomontage +photomontages +photomorphogenesis +photomorphogenic +photomosaic +photomosaics +photomultiplier +photomural +photomuralist +photomuralists +photomurals +photon +photonegative +photonic +photonics +photons +photonuclear +photooxidation +photooxidations +photooxidative +photooxidize +photooxidized +photooxidizes +photooxidizing +photoperiod +photoperiodic +photoperiodical +photoperiodically +photoperiodicities +photoperiodicity +photoperiodism +photoperiodisms +photoperiods +photophase +photophases +photophilic +photophilous +photophobia +photophobias +photophobic +photophore +photophores +photophosphorylation +photophosphorylations +photopia +photopias +photopic +photoplay +photoplays +photopolarimeter +photopolarimeters +photopolymer +photopolymers +photopositive +photoproduct +photoproduction +photoproductions +photoproducts +photoreaction +photoreactions +photoreactivating +photoreactivation +photoreactivations +photoreception +photoreceptive +photoreceptor +photoreceptors +photoreconnaissance +photoreduce +photoreduced +photoreduces +photoreducing +photoreduction +photoreductions +photoreproduction +photoreproductions +photoresist +photoresists +photorespiration +photorespirations +photos +photosensitive +photosensitivities +photosensitivity +photosensitization +photosensitizations +photosensitize +photosensitized +photosensitizer +photosensitizers +photosensitizes +photosensitizing +photoset +photosets +photosetter +photosetters +photosetting +photosphere +photospheres +photospheric +photostat +photostatic +photostats +photostatted +photostatting +photosynthate +photosynthates +photosynthesis +photosynthesize +photosynthesized +photosynthesizes +photosynthesizing +photosynthetic +photosynthetically +photosystem +photosystems +phototactic +phototactically +phototaxis +phototaxises +phototelegraphy +phototherapeutic +phototherapies +phototherapy +phototonic +phototonus +phototonuses +phototoxic +phototoxicity +phototransistor +phototransistors +phototroph +phototrophic +phototrophically +phototrophs +phototropic +phototropically +phototropism +phototube +phototubes +phototypeset +phototypesets +phototypesetter +phototypesetters +phototypesetting +phototypographic +phototypographical +phototypographically +phototypography +photovoltaic +photovoltaics +phots +phragmites +phragmoplast +phragmoplasts +phrasal +phrasally +phrase +phrased +phrasemaker +phrasemakers +phrasemaking +phrasemonger +phrasemongering +phrasemongers +phraseogram +phraseograms +phraseograph +phraseographic +phraseographs +phraseological +phraseologies +phraseologist +phraseologists +phraseology +phrases +phrasing +phrasings +phratric +phratries +phratry +phreatic +phreatophyte +phreatophytes +phreatophytic +phrenetic +phrenetical +phrenic +phrenitic +phrenitis +phrenologic +phrenological +phrenologist +phrenologists +phrenology +phrensy +phrenzied +phrenzies +phrenzy +phrenzying +phrygia +phrygian +phrygians +phthalate +phthalates +phthalein +phthaleine +phthaleines +phthaleins +phthalic +phthalin +phthalins +phthalocyanine +phthalocyanines +phthiriasis +phthises +phthisic +phthisical +phthisics +phthisis +phycobilin +phycobilins +phycocyanin +phycocyanins +phycoerythrin +phycoerythrins +phycological +phycologist +phycologists +phycology +phycomycete +phycomycetes +phycomycetous +phyla +phylacteries +phylactery +phylae +phyle +phyletic +phyletically +phylic +phyllaries +phyllary +phyllite +phyllites +phyllitic +phyllo +phylloclad +phylloclade +phylloclades +phylloclads +phyllode +phyllodes +phyllodia +phyllodial +phyllodium +phylloid +phyllome +phyllomes +phyllomic +phyllophagous +phyllopod +phyllopodan +phyllopodans +phyllopodous +phyllopods +phyllotactic +phyllotactical +phyllotaxes +phyllotaxies +phyllotaxis +phyllotaxy +phylloxera +phylloxerae +phylloxeran +phylloxerans +phylogenesis +phylogenetic +phylogenetically +phylogenetics +phylogenic +phylogenies +phylogeny +phylum +physiatrics +physiatrist +physiatrists +physiatry +physic +physical +physicalism +physicalist +physicalistic +physicalists +physicality +physicalization +physicalizations +physicalize +physicalized +physicalizes +physicalizing +physically +physicalness +physicals +physician +physicians +physicist +physicists +physicked +physicking +physicochemical +physicochemically +physics +physiochemical +physiocrat +physiocratic +physiocrats +physiognomic +physiognomical +physiognomically +physiognomies +physiognomist +physiognomists +physiognomy +physiographer +physiographers +physiographic +physiographical +physiographically +physiography +physiologic +physiological +physiologically +physiologist +physiologists +physiology +physiopathologic +physiopathological +physiopathologist +physiopathologists +physiopathology +physiotherapeutic +physiotherapist +physiotherapists +physiotherapy +physique +physiqued +physiques +physostigmin +physostigmine +physostigmines +physostigmins +physostomous +phytane +phytanes +phytoalexin +phytoalexins +phytochemical +phytochemically +phytochemist +phytochemistry +phytochemists +phytochrome +phytochromes +phytoflagellate +phytoflagellates +phytogenesis +phytogenetic +phytogenetical +phytogenetically +phytogenic +phytogenous +phytogeny +phytogeographer +phytogeographers +phytogeographic +phytogeographical +phytogeographically +phytogeography +phytography +phytohemagglutinin +phytohemagglutinins +phytohormone +phytohormones +phytol +phytologic +phytological +phytology +phytols +phyton +phytonic +phytons +phytopathogen +phytopathogenic +phytopathogens +phytopathologic +phytopathological +phytopathologist +phytopathologists +phytopathology +phytophagous +phytoplankter +phytoplankters +phytoplankton +phytoplanktonic +phytoplanktons +phytosociological +phytosociologically +phytosociologist +phytosociologists +phytosociology +phytosterol +phytosterols +phytotoxic +phytotoxicity +pi +pia +piacenza +piacular +piaffe +piaffed +piaffer +piaffers +piaffes +piaffing +piaget +pial +pianism +pianissimo +pianissimos +pianist +pianistic +pianistically +pianistics +pianists +piano +pianoforte +pianofortes +pianos +pias +piassaba +piassabas +piassava +piassavas +piaster +piasters +piastre +piastres +piazza +piazzas +piazze +pibroch +pibrochs +pic +pica +picador +picadores +picadors +picaninnies +picaninny +picante +picara +picaras +picardy +picaresque +picaro +picaroon +picarooned +picarooning +picaroons +picaros +picas +picasso +picayune +picayunes +picayunish +piccadilly +piccalilli +piccalillis +piccata +piccolo +piccoloist +piccoloists +piccolos +pice +piceous +pichiciego +pichiciegos +pick +pickaninnies +pickaninny +pickax +pickaxe +pickaxed +pickaxes +pickaxing +picked +picker +pickerel +pickerels +pickerelweed +pickerelweeds +pickers +picket +picketboat +picketboats +picketed +picketer +picketers +picketing +pickets +pickier +pickiest +picking +pickings +pickle +pickled +pickles +pickleworm +pickleworms +pickling +picklock +picklocks +pickoff +pickoffs +pickpocket +pickpockets +pickproof +picks +pickthank +pickthanks +pickup +pickups +pickwick +pickwickian +picky +picloram +piclorams +picnic +picnicked +picnicker +picnickers +picnicking +picnicky +picnics +picoampere +picoamperes +picobecquerel +picobecquerels +picocandela +picocandelas +picocoulomb +picocoulombs +picofarad +picofarads +picogram +picograms +picohenries +picohenry +picohenrys +picohertz +picojoule +picojoules +picokelvin +picokelvins +picoline +picolines +picolumen +picolumens +picolux +picometer +picometers +picomole +picomoles +piconewton +piconewtons +picoohm +picoohms +picopascal +picopascals +picoradian +picoradians +picornavirus +picornaviruses +picosecond +picoseconds +picosiemens +picosievert +picosieverts +picosteradian +picosteradians +picot +picoted +picotee +picotees +picotesla +picoteslas +picoting +picots +picovolt +picovolts +picowatt +picowatts +picowave +picowaved +picowaves +picowaving +picoweber +picowebers +picquet +picquets +picrate +picrates +picric +picrotoxic +picrotoxin +picrotoxins +pics +pict +pictish +pictogram +pictograms +pictograph +pictographic +pictographically +pictographs +pictography +pictor +pictorial +pictorialism +pictorialist +pictorialists +pictoriality +pictorialization +pictorializations +pictorialize +pictorialized +pictorializes +pictorializing +pictorially +pictorialness +pictorials +picts +picture +pictured +picturephone +picturephones +pictures +picturesque +picturesquely +picturesqueness +picturing +picturization +picturizations +picturize +picturized +picturizes +picturizing +picul +piculs +piddle +piddled +piddles +piddling +piddock +piddocks +pidgin +pidginization +pidginizations +pidginize +pidginized +pidginizes +pidginizing +pidgins +pie +piebald +piebalds +piece +pieced +piecemeal +piecer +piecers +pieces +piecewise +piecework +pieceworker +pieceworkers +piecing +piecrust +piecrusts +pied +piedmont +piedmontese +piedmonts +piegan +piegans +pieing +pieplant +pieplants +pier +pierce +pierced +piercer +piercers +pierces +piercing +piercingly +pierian +pierogi +pierogies +pierre +pierrot +piers +pies +pieta +pietas +pietermaritzburg +pieties +pietism +pietist +pietistic +pietistical +pietistically +pietists +piety +pietà +piezoelectric +piezoelectrical +piezoelectrically +piezoelectricity +piezometer +piezometers +piezometric +piezometrical +piezometry +piffle +piffled +piffles +piffling +pig +pigboat +pigboats +pigeon +pigeonhole +pigeonholed +pigeonholer +pigeonholers +pigeonholes +pigeonholing +pigeonite +pigeonites +pigeons +pigeonwing +pigeonwings +pigfish +pigfishes +pigged +piggeries +piggery +piggier +piggies +piggiest +piggin +pigging +piggins +piggish +piggishly +piggishness +piggledy +piggy +piggyback +piggybacked +piggybacking +piggybacks +pigheaded +pigheadedly +pigheadedness +piglet +piglets +piglike +pigment +pigmentary +pigmentation +pigmentations +pigmented +pigmenting +pigmentosa +pigments +pigmies +pigmy +pignoli +pignolia +pignut +pignuts +pigpen +pigpens +pigs +pigskin +pigskins +pigsney +pigsneys +pigstick +pigsticked +pigsticker +pigstickers +pigsticking +pigsticks +pigsties +pigsty +pigtail +pigtailed +pigtails +pigweed +pigweeds +piing +pika +pikake +pikakes +pikas +pike +piked +pikeman +pikemen +pikeperch +pikeperches +piker +pikers +pikes +pikestaff +pikestaffs +piki +piking +pilaf +pilaff +pilaffs +pilafs +pilar +pilaster +pilasters +pilate +pilatus +pilau +pilaw +pilchard +pilchards +pile +pilea +pileate +pileated +piled +pilei +pileless +piles +pileum +pileup +pileups +pileus +pilewort +pileworts +pilfer +pilferable +pilferage +pilfered +pilferer +pilferers +pilfering +pilferproof +pilfers +pilgarlic +pilgarlics +pilgrim +pilgrimage +pilgrimaged +pilgrimages +pilgrimaging +pilgrims +pili +piliferous +piliform +piling +pilings +pilipino +pill +pillage +pillaged +pillager +pillagers +pillages +pillaging +pillar +pillared +pillaring +pillarless +pillars +pillbox +pillboxes +pilled +pilling +pillion +pillions +pilloried +pillories +pillory +pillorying +pillow +pillowcase +pillowcases +pillowed +pillowing +pillows +pillowslip +pillowslips +pillowy +pills +pilocarpine +pilocarpines +pilose +pilosity +pilot +pilotage +piloted +pilothouse +pilothouses +piloting +pilotings +pilotless +pilots +pilous +pilsener +pilseners +pilsner +pilsners +piltdown +pilular +pilule +pilules +pilus +pima +piman +pimas +pimento +pimentos +pimiento +pimientos +piminy +pimp +pimped +pimpernel +pimpernels +pimping +pimple +pimpled +pimples +pimply +pimpmobile +pimpmobiles +pimps +pin +pinafore +pinafored +pinafores +pinaster +pinasters +pinball +pinballs +pinbone +pinbones +pince +pincer +pincerlike +pincers +pinch +pinchbeck +pinchbecks +pinchcock +pinchcocks +pinched +pincher +pinchers +pinches +pinching +pinchpennies +pinchpenny +pincushion +pincushions +pindar +pindaric +pindling +pine +pineal +pinealectomize +pinealectomized +pinealectomizes +pinealectomizing +pinealectomy +pineapple +pineapples +pinecone +pinecones +pined +pinedrops +pineland +pinelands +pinene +pinenes +pineries +pinery +pines +pinesap +pinesaps +pineta +pinetum +pinewood +pinewoods +piney +pinfeather +pinfeathers +pinfish +pinfishes +pinfold +pinfolded +pinfolding +pinfolds +ping +pinged +pinger +pingers +pinging +pingo +pingoes +pingos +pings +pinguid +pinhead +pinheaded +pinheadedness +pinheads +pinhole +pinholes +pinier +piniest +pining +pinion +pinioned +pinioning +pinions +pinite +pinites +pink +pinked +pinker +pinkest +pinkeye +pinkie +pinkies +pinking +pinkish +pinkishness +pinkly +pinkness +pinko +pinkoes +pinkos +pinkroot +pinkroots +pinks +pinkster +pinksters +pinky +pinna +pinnace +pinnaces +pinnacle +pinnacled +pinnacles +pinnacling +pinnae +pinnal +pinnas +pinnate +pinnated +pinnately +pinnatifid +pinnatifidly +pinnatiped +pinnatisect +pinned +pinner +pinners +pinnigrade +pinning +pinniped +pinnipeds +pinnula +pinnulae +pinnular +pinnule +pinnules +pinocchio +pinochle +pinocle +pinocytic +pinocytosis +pinocytotic +pinocytotically +pinole +pinoles +pinot +pinots +pinpoint +pinpointed +pinpointing +pinpoints +pinprick +pinpricked +pinpricking +pinpricks +pins +pinscher +pinschers +pinsetter +pinsetters +pinspotter +pinspotters +pinstripe +pinstriped +pinstripes +pint +pinta +pintail +pintails +pintano +pintanos +pintas +pintle +pintles +pinto +pintoes +pintos +pints +pintsize +pintsized +pinup +pinups +pinwale +pinweed +pinweeds +pinwheel +pinwheels +pinwork +pinworm +pinworms +pinwrench +pinwrenches +pinxter +pinxters +piny +pinyin +pinyon +pinyons +piolet +piolets +pion +pioneer +pioneered +pioneering +pioneers +pionic +pions +piosities +piosity +pious +piously +piousness +pip +pipal +pipals +pipe +piped +pipefish +pipefishes +pipefitting +pipefittings +pipeful +pipefuls +pipeless +pipelike +pipeline +pipelined +pipelines +pipelining +piper +piperazine +piperazines +piperidine +piperidines +piperine +piperines +piperonal +piperonals +piperonyl +pipers +pipes +pipestone +pipestones +pipet +pipets +pipette +pipetted +pipettes +pipetting +piping +pipings +pipistrel +pipistrelle +pipistrelles +pipistrels +pipit +pipits +pipkin +pipkins +pipped +pippin +pipping +pippins +pips +pipsissewa +pipsissewas +pipsqueak +pipsqueaks +piquance +piquancy +piquant +piquantly +piquantness +pique +piqued +piques +piquet +piquets +piquing +piqué +piracies +piracy +piraeus +piragua +piraguas +piranesi +piranha +piranhas +pirarucu +pirarucus +pirate +pirated +pirates +piratic +piratical +piratically +pirating +piraña +pirañas +pirog +piroghi +pirogi +pirogue +pirogues +piroplasm +piroplasma +piroplasmata +piroplasmoses +piroplasmosis +piroplasms +piroshki +pirouette +pirouetted +pirouettes +pirouetting +pirozhki +pis +pisa +pisan +pisans +piscaries +piscary +piscatorial +piscatorially +piscatory +piscean +pisceans +pisces +piscicultural +pisciculture +pisciculturist +pisciculturists +pisciform +piscina +piscinae +piscinal +piscine +piscis +piscivorous +pish +pishoge +pishoges +pishogue +pishogues +pisiform +pisiforms +pismire +pismires +pismo +piso +pisolite +pisolites +pisolith +pisoliths +pisolitic +pisos +piss +pissant +pissants +pissarro +pissed +pisser +pissers +pisses +pissing +pissoir +pissoirs +pistachio +pistachios +pistareen +pistareens +piste +pistes +pistil +pistillate +pistils +pistol +pistole +pistoled +pistoleer +pistoleers +pistoles +pistoling +pistols +piston +pistons +pistou +pistous +pit +pita +pitapat +pitapats +pitapatted +pitapatting +pitas +pitcairn +pitch +pitchblende +pitched +pitcher +pitcherful +pitcherfuls +pitchers +pitches +pitchfork +pitchforked +pitchforking +pitchforks +pitchier +pitchiest +pitchiness +pitching +pitchman +pitchmen +pitchout +pitchouts +pitchpole +pitchpoled +pitchpoles +pitchpoling +pitchstone +pitchstones +pitchwoman +pitchwomen +pitchy +piteous +piteously +piteousness +pitfall +pitfalls +pith +pithead +pitheads +pithecanthropi +pithecanthropic +pithecanthropine +pithecanthropus +pithecoid +pithed +pithier +pithiest +pithily +pithiness +pithing +piths +pithy +pitiable +pitiableness +pitiably +pitied +pitier +pitiers +pities +pitiful +pitifully +pitifulness +pitiless +pitilessly +pitilessness +pitman +pitmans +pitmen +piton +pitons +pitot +pits +pitsaw +pitsaws +pitta +pittance +pittances +pittas +pitted +pitter +pitting +pittosporum +pittosporums +pittsburgh +pituicyte +pituicytes +pituitaries +pituitary +pity +pitying +pityingly +pityriases +pityriasis +piute +piutes +pivot +pivotable +pivotal +pivotally +pivoted +pivoting +pivotman +pivotmen +pivots +pix +pixel +pixelate +pixelated +pixelates +pixelating +pixelation +pixels +pixes +pixie +pixieish +pixies +pixilated +pixilation +pixilations +pixillated +pixiness +pixy +pixyish +pizarro +pizazz +pizazzy +pizza +pizzalike +pizzas +pizzaz +pizzazes +pizzazz +pizzazzes +pizzazzy +pizzeria +pizzerias +pizzicati +pizzicato +pizzicatos +pizzle +pizzles +pièce +pièces +piña +piñata +piñon +piñones +piñons +più +pkwy +placability +placable +placably +placard +placarded +placarder +placarders +placarding +placards +placate +placated +placater +placaters +placates +placating +placatingly +placation +placations +placative +placatory +place +placeable +placebo +placeboes +placebos +placed +placeholder +placeholders +placekick +placekicked +placekicker +placekickers +placekicking +placekicks +placeless +placelessly +placeman +placemen +placement +placements +placenta +placentae +placental +placentas +placentation +placentations +placer +placers +places +placid +placidity +placidly +placidness +placing +placket +plackets +placoid +plafond +plafonds +plagal +plage +plages +plagiaries +plagiarism +plagiarisms +plagiarist +plagiaristic +plagiarists +plagiarize +plagiarized +plagiarizer +plagiarizers +plagiarizes +plagiarizing +plagiary +plagioclase +plagioclases +plagiotropic +plagiotropically +plagiotropism +plagiotropisms +plague +plagued +plaguer +plaguers +plagues +plaguey +plaguily +plaguing +plaguy +plaice +plaices +plaid +plaided +plaids +plain +plainchant +plainchants +plainclothes +plainclothesman +plainclothesmen +plainer +plainest +plainly +plainness +plains +plainsman +plainsmen +plainsong +plainsongs +plainspoken +plainspokenness +plainswoman +plainswomen +plaint +plaintext +plaintexts +plaintful +plaintiff +plaintiffs +plaintive +plaintively +plaintiveness +plaints +plait +plaited +plaiter +plaiters +plaiting +plaits +plan +planar +planaria +planarian +planarians +planarity +planate +planation +planations +planchet +planchets +planchette +planchettes +planck +plane +planed +planeload +planeloads +planeness +planer +planers +planes +planeside +planesides +planet +planetaria +planetarium +planetariums +planetary +planetesimal +planetesimals +planetlike +planetoid +planetoidal +planetoids +planetological +planetologist +planetologists +planetology +planets +planetwide +planform +planforms +plangency +plangent +plangently +planimeter +planimeters +planimetric +planimetrical +planimetrically +planimetry +planing +planish +planished +planisher +planishers +planishes +planishing +planisphere +planispheres +planispheric +planispherical +plank +planked +planking +plankings +planks +plankter +plankters +plankton +planktonic +planless +planlessly +planlessness +planned +planner +planners +planning +plano +planoblast +planoblasts +planoconcave +planoconvex +planogamete +planogametes +planographic +planographically +planography +planometer +planometers +planometry +planosol +planosols +plans +plant +plantable +plantagenet +plantagenets +plantain +plantains +plantar +plantation +plantations +planted +planter +planters +plantigrade +plantigrades +planting +plantings +plantlet +plantlets +plantlike +plantocracy +plants +plantsman +plantsmen +planula +planulae +planular +planulate +plaque +plaques +plash +plashed +plashes +plashing +plasm +plasma +plasmablast +plasmablasts +plasmacyte +plasmacytes +plasmagel +plasmagels +plasmagene +plasmagenes +plasmagenic +plasmalemma +plasmalemmas +plasmapheresis +plasmas +plasmasol +plasmasols +plasmatic +plasmic +plasmid +plasmids +plasmin +plasminogen +plasminogens +plasmins +plasmodesm +plasmodesma +plasmodesmas +plasmodesmata +plasmodesms +plasmodia +plasmodial +plasmodium +plasmogamies +plasmogamy +plasmolyses +plasmolysis +plasmolytic +plasmolytically +plasmolyze +plasmolyzed +plasmolyzes +plasmolyzing +plasmon +plasmons +plasms +plassey +plaster +plasterboard +plasterboards +plastered +plasterer +plasterers +plastering +plasterings +plasters +plasterwork +plasterworks +plastery +plastic +plastically +plasticene +plasticenes +plasticine +plasticines +plasticity +plasticization +plasticizations +plasticize +plasticized +plasticizer +plasticizers +plasticizes +plasticizing +plasticky +plastics +plastid +plastidial +plastids +plastique +plastisol +plastisols +plastocyanin +plastocyanins +plastoquinone +plastoquinones +plastral +plastron +plastrons +plat +platan +platans +plate +plateau +plateaued +plateauing +plateaus +plateaux +plated +plateful +platefuls +plateglass +platelet +platelets +platelike +platemaker +platemakers +platemaking +platen +platens +plater +plateresque +platers +plates +platform +platforms +platier +platies +platiest +platina +platinas +plating +platings +platinic +platinize +platinized +platinizes +platinizing +platinocyanide +platinocyanides +platinoid +platinoids +platinotype +platinotypes +platinous +platinum +platitude +platitudes +platitudinal +platitudinarian +platitudinarians +platitudinize +platitudinized +platitudinizes +platitudinizing +platitudinous +platitudinously +plato +platonic +platonical +platonically +platonism +platonist +platonistic +platonists +platonize +platonized +platonizes +platonizing +platoon +platooned +platooning +platoons +plats +plattdeutsch +platted +platter +platterful +platterfuls +platters +platting +platy +platyfish +platyfishes +platyhelminth +platyhelminthic +platyhelminths +platypi +platypus +platypuses +platyrrhine +platyrrhinian +platyrrhiny +platys +plaudit +plaudits +plausibility +plausible +plausibleness +plausibly +plausive +plautus +play +playa +playability +playable +playact +playacted +playacting +playacts +playas +playback +playbacks +playbill +playbills +playbook +playbooks +playboy +playboys +played +player +players +playfellow +playfellows +playfield +playfields +playful +playfully +playfulness +playgirl +playgirls +playgoer +playgoers +playgoing +playground +playgrounds +playhouse +playhouses +playing +playland +playlands +playlet +playlets +playlist +playlists +playmaker +playmakers +playmaking +playmate +playmates +playoff +playoffs +playpen +playpens +playroom +playrooms +plays +playsuit +playsuits +plaything +playthings +playtime +playtimes +playwear +playwright +playwrighting +playwrights +playwriting +plaza +plazas +plaît +plea +pleach +pleached +pleaches +pleaching +plead +pleadable +pleaded +pleader +pleaders +pleading +pleadingly +pleadings +pleads +pleas +pleasance +pleasances +pleasant +pleasanter +pleasantest +pleasantly +pleasantness +pleasantries +pleasantry +please +pleased +pleaser +pleasers +pleases +pleasing +pleasingly +pleasingness +pleasurability +pleasurable +pleasurableness +pleasurably +pleasure +pleasured +pleasureless +pleasures +pleasuring +pleat +pleated +pleater +pleaters +pleating +pleatless +pleats +pleb +plebe +plebeian +plebeianism +plebeianly +plebeians +plebes +plebianly +plebiscitary +plebiscite +plebiscites +plebs +plecopteran +plecopterans +plectognath +plectognaths +plectra +plectrum +plectrums +pled +pledge +pledged +pledgee +pledgees +pledgeor +pledgeors +pledger +pledgers +pledges +pledget +pledgets +pledging +pledgor +pledgors +pleiad +pleiades +plein +pleinairism +pleinairist +pleinairists +pleiotaxies +pleiotaxy +pleiotropic +pleiotropically +pleiotropies +pleiotropism +pleiotropisms +pleiotropy +pleistocene +plena +plenarily +plenariness +plenary +plenipotent +plenipotentiaries +plenipotentiary +plenish +plenished +plenishes +plenishing +plenitude +plenitudinous +plenteous +plenteously +plenteousness +plentiful +plentifully +plentifulness +plentitude +plenty +plenum +plenums +pleochroic +pleochroism +pleochroisms +pleomorphic +pleomorphism +pleomorphisms +pleonasm +pleonasms +pleonastic +pleonastically +pleopod +pleopods +plerocercoid +plerocercoids +plesiosaur +plesiosauri +plesiosaurs +plesiosaurus +plessimeter +plessimeters +plessor +plessors +plethora +plethoric +plethorically +plethysmogram +plethysmograms +plethysmograph +plethysmographic +plethysmographically +plethysmographs +plethysmography +pleura +pleurae +pleural +pleuras +pleurisy +pleuritic +pleurodont +pleurodonts +pleurodynia +pleurodynias +pleuron +pleuropneumonia +pleurotomies +pleurotomy +pleuston +pleustonic +pleustons +plexiform +plexiglas +pleximeter +pleximeters +pleximetric +pleximetry +plexor +plexors +plexus +plexuses +pliability +pliable +pliableness +pliably +pliancy +pliant +pliantly +pliantness +plica +plicae +plical +plicate +plicated +plicately +plicateness +plication +plications +plicature +plicatures +plied +plier +pliers +plies +plight +plighted +plighter +plighters +plighting +plights +plimsol +plimsole +plimsoles +plimsoll +plimsolls +plimsols +plink +plinked +plinker +plinkers +plinking +plinks +plinth +plinths +pliny +pliocene +pliofilm +pliskie +pliskies +plisky +plisse +plisses +plissé +plissés +plié +plod +plodded +plodder +plodders +plodding +ploddingly +plods +ploidies +ploidy +plonk +plonked +plonking +plonks +plop +plopped +plopping +plops +plosion +plosions +plosive +plosives +plot +plotinism +plotinist +plotinists +plotinus +plotless +plotlessness +plotline +plotlines +plots +plottage +plottages +plotted +plotter +plotters +plottier +plottiest +plotting +plotty +plough +ploughed +ploughing +ploughman +ploughs +plover +plovers +plow +plowable +plowback +plowbacks +plowboy +plowboys +plowed +plower +plowers +plowing +plowman +plowmen +plows +plowshare +plowshares +ploy +ploys +pluck +plucked +plucker +pluckers +pluckier +pluckiest +pluckily +pluckiness +plucking +plucks +plucky +plug +plugged +plugger +pluggers +plugging +plugola +plugs +plum +plumage +plumaged +plumate +plumb +plumbable +plumbago +plumbagos +plumbean +plumbed +plumber +plumberies +plumbers +plumbery +plumbic +plumbiferous +plumbing +plumbism +plumbisms +plumbs +plume +plumed +plumelet +plumelets +plumeria +plumes +plumier +plumiest +pluming +plumlike +plummet +plummeted +plummeting +plummets +plummier +plummiest +plummy +plumose +plumosely +plumosity +plump +plumped +plumpen +plumpened +plumpening +plumpens +plumper +plumpest +plumping +plumpish +plumply +plumpness +plumps +plums +plumule +plumules +plumulose +plumy +plunder +plunderable +plundered +plunderer +plunderers +plundering +plunderous +plunders +plunge +plunged +plunger +plungers +plunges +plunging +plunk +plunked +plunker +plunkers +plunking +plunks +plunky +pluperfect +pluperfects +plural +pluralism +pluralist +pluralistic +pluralistically +pluralists +pluralities +plurality +pluralization +pluralizations +pluralize +pluralized +pluralizes +pluralizing +plurally +plurals +pluribus +pluripotent +plus +pluses +plush +plusher +plushest +plushier +plushiest +plushily +plushiness +plushly +plushness +plushy +plussage +plusses +plutarch +plutarchan +plutarchian +pluto +plutocracies +plutocracy +plutocrat +plutocratic +plutocratical +plutocratically +plutocrats +plutographic +plutography +pluton +plutonian +plutonic +plutonium +plutons +pluvial +pluviograph +pluviographs +pluviometer +pluviometers +pluviometric +pluviometrical +pluviometrically +pluviometry +pluviose +pluviosity +pluvious +ply +plyer +plyers +plying +plymouth +plymouths +plywood +pneuma +pneumas +pneumatic +pneumatical +pneumatically +pneumaticity +pneumatics +pneumatograph +pneumatographs +pneumatologic +pneumatological +pneumatologist +pneumatologists +pneumatology +pneumatolysis +pneumatolytic +pneumatometer +pneumatometers +pneumatometry +pneumatophore +pneumatophores +pneumatophoric +pneumectomy +pneumobacilli +pneumobacillus +pneumococcal +pneumococci +pneumococcus +pneumoconiosis +pneumoconiotic +pneumoconiotics +pneumocystis +pneumocystises +pneumogastric +pneumograph +pneumographic +pneumographs +pneumonectomies +pneumonectomy +pneumonia +pneumonic +pneumonitis +pneumostome +pneumostomes +pneumotachogram +pneumotachograms +pneumotachograph +pneumotachographic +pneumotachographs +pneumotachography +pneumothorax +pneumothoraxes +po +poach +poachable +poached +poacher +poachers +poaches +poaching +poblano +pocahontas +pochard +pochards +pock +pocked +pocket +pocketable +pocketbook +pocketbooks +pocketed +pocketful +pocketfuls +pocketing +pocketknife +pocketknives +pocketless +pockets +pocketsful +pocketsize +pocking +pockmark +pockmarked +pockmarking +pockmarks +pocks +pocky +poco +pococurante +pococurantes +pococurantism +pocono +poconos +pocosin +pocosins +pocus +pocused +pocuses +pocusing +pocussed +pocusses +pocussing +pod +podagra +podagral +podagras +podagric +podded +podding +podesta +podestas +podetia +podetium +podgier +podgiest +podgy +podia +podiatric +podiatrist +podiatrists +podiatry +podite +podites +poditic +podium +podiums +podophylli +podophyllin +podophyllins +podophyllum +podophyllums +podrida +podridas +pods +podsol +podsolization +podsolizations +podsols +podunk +podzol +podzolic +podzolization +podzolizations +podzolize +podzolized +podzolizes +podzolizing +podzols +poem +poems +poenology +poesies +poesy +poet +poetaster +poetasters +poetess +poetesses +poetic +poetical +poeticality +poetically +poeticalness +poeticism +poeticisms +poeticize +poeticized +poeticizes +poeticizing +poetics +poetize +poetized +poetizer +poetizers +poetizes +poetizing +poetry +poets +pogies +pogo +pogonia +pogonias +pogonip +pogonips +pogonomyrmex +pogonophoran +pogonophorans +pogonophore +pogonophores +pogonophorous +pogrom +pogromed +pogroming +pogromist +pogromists +pogroms +pogy +poi +poignance +poignancy +poignant +poignantly +poikilotherm +poikilothermal +poikilothermia +poikilothermic +poikilothermism +poikilothermous +poikilotherms +poilu +poilus +poincaré +poinciana +poinsettia +poinsettias +point +pointblank +pointe +pointed +pointedly +pointedness +pointelle +pointer +pointers +pointes +pointier +pointiest +pointillism +pointillist +pointillistic +pointillists +pointing +pointless +pointlessly +pointlessness +points +pointtillist +pointy +pois +poise +poised +poises +poisha +poising +poison +poisoned +poisoner +poisoners +poisoning +poisonings +poisonous +poisonously +poisonousness +poisons +poisonwood +poisonwoods +poisson +poitiers +poitou +poivre +poke +pokeberries +pokeberry +poked +poker +pokerfaced +pokeroot +pokeroots +pokers +pokery +pokes +pokeweed +pokeweeds +pokey +pokeys +pokier +pokies +pokiest +pokily +pokiness +poking +poky +pol +polab +polabian +polabians +polabs +polack +polacks +poland +polar +polarimeter +polarimeters +polarimetric +polarimetry +polaris +polariscope +polariscopes +polariscopic +polarities +polarity +polarizability +polarizable +polarization +polarizations +polarize +polarized +polarizer +polarizers +polarizes +polarizing +polarographic +polarographically +polarography +polaroid +polaron +polarons +polder +polders +pole +poleax +poleaxe +poleaxed +poleaxes +poleaxing +polecat +polecats +poled +poleis +poleless +polemic +polemical +polemically +polemicist +polemicists +polemicize +polemicized +polemicizes +polemicizing +polemics +polemist +polemists +polemize +polemized +polemizes +polemizing +polemonium +polenta +polentas +poler +polers +poles +polestar +polestars +poleward +police +policeable +policed +policeman +policemen +policer +policers +polices +policewoman +policewomen +policies +policing +policlinic +policlinics +policy +policyholder +policyholders +policymaker +policymakers +policymaking +poling +polio +poliomyelitic +poliomyelitis +poliovirus +polioviruses +polis +polish +polished +polisher +polishers +polishes +polishing +polishings +politburo +politburos +polite +politely +politeness +politenesses +politer +politesse +politest +politic +political +politicalization +politicalizations +politicalize +politicalized +politicalizes +politicalizing +politically +politician +politicians +politicization +politicizations +politicize +politicized +politicizes +politicizing +politick +politicked +politicker +politickers +politicking +politicks +politicly +politico +politicos +politics +polities +polity +polka +polkaed +polkaing +polkas +poll +pollack +pollacks +pollard +pollarded +pollarding +pollards +polled +pollen +pollenate +pollenated +pollenates +pollenating +polleniferous +pollenosis +pollens +poller +pollers +pollex +pollices +pollinate +pollinated +pollinates +pollinating +pollination +pollinations +pollinator +pollinators +polling +pollinia +polliniferous +pollinium +pollinization +pollinizations +pollinize +pollinized +pollinizer +pollinizers +pollinizes +pollinizing +pollinosis +polliwog +polliwogs +pollo +pollock +pollocks +polloi +polls +pollster +pollsters +polltaker +polltakers +pollutant +pollutants +pollute +polluted +polluter +polluters +pollutes +polluting +pollution +pollutive +pollux +pollyanna +pollyannaish +pollyannaism +pollyannas +pollyannish +pollywog +pollywogs +polo +poloist +poloists +polonaise +polonaises +polonia +polonium +polonius +pols +poltergeist +poltergeists +poltroon +poltrooneries +poltroonery +poltroons +poly +polyacetylene +polyacrylamide +polyacrylamides +polyacrylonitrile +polyadenylic +polyalcohol +polyalcohols +polyamide +polyamides +polyamine +polyamines +polyandric +polyandrous +polyandry +polyantha +polyanthas +polyanthus +polyanthuses +polyatomic +polybasic +polybasite +polybasites +polybius +polybrominated +polybutadiene +polybutadienes +polycarbonate +polycarbonates +polycarpellary +polycarpic +polycarpous +polycarpy +polycentric +polycentrics +polycentrism +polychaete +polychaetes +polychete +polychetes +polychetous +polychlorinated +polychotomous +polychotomy +polychromatic +polychromatophile +polychromatophilia +polychromatophilic +polychrome +polychromes +polychromic +polychromies +polychromophilia +polychromous +polychromy +polycistronic +polyclinic +polyclinics +polyclonal +polyclonally +polyclone +polyclones +polycondensation +polycondensations +polyconic +polycot +polycots +polycotyledon +polycotyledonous +polycotyledons +polycrystal +polycrystalline +polycrystals +polycyclic +polycystic +polycythemia +polycythemias +polycythemic +polycytidylic +polydactyl +polydactylism +polydactylous +polydactyly +polydemic +polydiacetylene +polydipsia +polydipsic +polydisperse +polydispersity +polydorus +polyelectrolyte +polyelectrolytes +polyembryonic +polyembryonies +polyembryony +polyene +polyenes +polyenic +polyester +polyesterification +polyesterifications +polyesters +polyestrous +polyether +polyethers +polyethylene +polygala +polygalas +polygamic +polygamist +polygamists +polygamize +polygamized +polygamizes +polygamizing +polygamous +polygamously +polygamy +polygene +polygenes +polygenesis +polygenesist +polygenesists +polygenetic +polygenic +polygenically +polyglot +polyglotism +polyglots +polyglottism +polygon +polygonal +polygonally +polygons +polygonum +polygonums +polygraph +polygraphed +polygrapher +polygraphers +polygraphic +polygraphing +polygraphist +polygraphists +polygraphs +polygynous +polygyny +polyhedra +polyhedral +polyhedron +polyhedrons +polyhedroses +polyhedrosis +polyhistor +polyhistoric +polyhistors +polyhydric +polyhydroxy +polyhydroxybutyrate +polyhymnia +polyimide +polyimides +polyinosinic +polylysine +polylysines +polymath +polymathic +polymaths +polymathy +polymer +polymerase +polymerases +polymeric +polymerically +polymerism +polymerization +polymerizations +polymerize +polymerized +polymerizes +polymerizing +polymerous +polymers +polymethyl +polymnia +polymorph +polymorphic +polymorphically +polymorphism +polymorphisms +polymorphonuclear +polymorphonuclears +polymorphous +polymorphously +polymorphs +polymyxin +polymyxins +polynesia +polynesian +polynesians +polyneuritic +polyneuritis +polyneuritises +polynices +polynomial +polynomials +polynuclear +polynucleotide +polynucleotides +polynya +polynyas +polynyi +polyolefin +polyolefins +polyoma +polyomas +polyonymous +polyp +polyparia +polyparies +polyparium +polypary +polypeptide +polypeptides +polypeptidic +polypetalous +polyphagia +polyphagian +polyphagous +polyphagy +polyphase +polyphasic +polyphemus +polyphenol +polyphenolic +polyphenols +polyphiloprogenitive +polyphone +polyphones +polyphonic +polyphonically +polyphonies +polyphonous +polyphonously +polyphony +polyphosphate +polyphosphates +polyphyletic +polyphyletically +polypide +polypides +polyploid +polyploids +polyploidy +polypnea +polypneas +polypneic +polypod +polypodies +polypodous +polypody +polypoid +polypore +polypores +polyposes +polyposis +polypropylene +polypropylenes +polyprotic +polyps +polyptych +polyptyches +polyrhythm +polyrhythmic +polyrhythmically +polyrhythms +polyribonucleotide +polyribonucleotides +polyribosomal +polyribosome +polyribosomes +polys +polysaccharid +polysaccharide +polysaccharides +polysaccharids +polysaccharose +polysaccharoses +polysemous +polysemy +polysepalous +polysome +polysomes +polysomic +polysomics +polysorbate +polysorbates +polyspermic +polyspermies +polyspermy +polystichous +polystyrene +polystyrenes +polysulfide +polysulfides +polysyllabic +polysyllabically +polysyllable +polysyllables +polysynaptic +polysynaptically +polysyndeton +polysyndetons +polysynthetic +polytechnic +polytechnics +polytene +polytenic +polyteny +polytetrafluoroethylene +polytetrafluoroethylenes +polytheism +polytheist +polytheistic +polytheistical +polytheists +polythene +polythenes +polytocous +polytonal +polytonality +polytonally +polytrophic +polytypic +polytypical +polyunsaturate +polyunsaturated +polyunsaturates +polyurethane +polyurethanes +polyuria +polyurias +polyuric +polyvalence +polyvalency +polyvalent +polyvinyl +polywater +polyzoan +polyzoans +polyzoaria +polyzoaries +polyzoarium +polyzoary +polyzoic +pom +pomace +pomaceous +pomaces +pomade +pomaded +pomades +pomading +pomander +pomanders +pomatum +pomatums +pome +pomegranate +pomegranates +pomelo +pomelos +pomerania +pomeranian +pomeranians +pomes +pomiculture +pomicultures +pomiferous +pommee +pommel +pommeled +pommeling +pommelled +pommelling +pommels +pommie +pommies +pommy +pomo +pomological +pomologically +pomologist +pomologists +pomology +pomona +pomos +pomp +pompadour +pompadoured +pompadours +pompano +pompanos +pompei +pompeian +pompeians +pompeii +pompeiian +pompeiians +pompelmous +pompelmouses +pompey +pompidou +pompom +pompoms +pompon +pompons +pomposity +pompous +pompously +pompousness +poms +ponca +poncas +ponce +ponces +poncho +ponchos +pond +ponder +ponderability +ponderable +pondered +ponderer +ponderers +pondering +ponderosa +ponderosas +ponderosity +ponderous +ponderously +ponderousness +ponders +pondicherry +ponds +pondweed +pondweeds +pone +pones +pong +pongee +pongees +pongid +pongids +poniard +poniarded +poniarding +poniards +ponied +ponies +pons +pontes +ponthieu +pontiac +pontic +pontifex +pontiff +pontiffs +pontifical +pontifically +pontificals +pontificate +pontificated +pontificates +pontificating +pontification +pontifications +pontificator +pontificators +pontifices +pontil +pontils +pontine +pontonier +pontoniers +pontoon +pontoons +pontus +pony +ponying +ponytail +ponytailed +ponytails +ponzi +pooch +pooches +pood +poodle +poodled +poodles +poodling +poods +poof +poofs +pooftah +poofter +poofters +pooh +poohed +poohing +poohs +pool +pooled +pooler +poolers +pooling +poolroom +poolrooms +pools +poolside +poolsides +poon +poona +poons +poop +pooped +pooper +pooping +poops +poor +poorer +poorest +poorhouse +poorhouses +poori +pooris +poorish +poorly +poormouth +poormouthed +poormouthing +poormouths +poorness +poove +pooves +pop +popcorn +pope +popedom +popedoms +popery +popes +popeyed +popgun +popguns +popinjay +popinjays +popish +popishly +popishness +poplar +poplars +poplin +poplins +popliteal +popocatépetl +popover +popovers +poppa +poppas +popped +popper +poppers +poppet +poppets +poppied +poppies +popping +popple +poppled +popples +poppling +poppy +poppycock +poppyhead +poppyheads +pops +popsicle +popsicles +populace +populaces +popular +popularity +popularization +popularizations +popularize +popularized +popularizer +popularizers +popularizes +popularizing +popularly +populate +populated +populates +populating +population +populational +populations +populi +populism +populist +populistic +populists +populous +populously +populousness +popup +porbeagle +porbeagles +porcelain +porcelainize +porcelainized +porcelainizes +porcelainizing +porcelainlike +porcelains +porcelaneous +porcellaneous +porch +porches +porcine +porcini +porcino +porcupine +porcupines +pore +pored +pores +porgies +porgy +poriferal +poriferan +poriferans +poriferous +poring +pork +porker +porkers +porkier +porkies +porkiest +porkpie +porkpies +porky +porn +pornier +porniest +porno +pornographer +pornographers +pornographic +pornographically +pornography +porny +poromeric +poromerics +porosities +porosity +porous +porously +porousness +porphyria +porphyrias +porphyric +porphyries +porphyrin +porphyrins +porphyritic +porphyritical +porphyroid +porphyroids +porphyropsin +porphyropsins +porphyry +porpoise +porpoises +porrect +porridge +porridges +porridgy +porringer +porringers +port +portability +portable +portableness +portables +portably +portage +portaged +portages +portaging +portal +portals +portamenti +portamento +portamentos +portapack +portapacks +portapak +portapaks +portative +portcullis +portcullises +porte +ported +portend +portended +portending +portends +portent +portentous +portentously +portentousness +portents +porter +porterage +porterages +porteress +porteresses +porterhouse +porterhouses +porters +portfolio +portfolios +porthole +portholes +portia +portico +porticoed +porticoes +porticos +portiere +portieres +porting +portion +portionable +portioned +portioner +portioners +portioning +portionless +portions +portière +portières +portland +portlander +portlanders +portlier +portliest +portliness +portly +portmanteau +portmanteaus +portmanteaux +portofino +portrait +portraitist +portraitists +portraits +portraiture +portraitures +portray +portrayable +portrayal +portrayals +portrayed +portrayer +portrayers +portraying +portrays +portress +portresses +ports +portside +portugal +portuguese +portulaca +portulacas +posable +posada +posadas +pose +posed +poseidon +poser +posers +poses +poseur +poseurs +posh +poshly +poshness +posies +posigrade +posing +posit +positano +posited +positing +position +positional +positionally +positioned +positioner +positioners +positioning +positions +positive +positively +positiveness +positives +positivism +positivist +positivistic +positivistically +positivists +positivity +positron +positronium +positrons +posits +posology +posse +posses +possess +possessed +possessedly +possessedness +possesses +possessing +possession +possessional +possessionless +possessions +possessive +possessively +possessiveness +possessives +possessor +possessors +possessory +posset +possets +possibilities +possibility +possible +possibly +possum +possums +post +postabortion +postaccident +postadolescent +postage +postages +postal +postally +postamputation +postapocalyptic +postarrest +postatomic +postattack +postaxial +postaxially +postbaccalaureate +postbag +postbags +postbase +postbellum +postbiblical +postbourgeois +postbox +postboxes +postboy +postboys +postburn +postcapitalist +postcard +postcardlike +postcards +postcava +postcaval +postcavas +postclassic +postclassical +postcode +postcodes +postcoital +postcollege +postcollegiate +postcolonial +postconception +postconcert +postcondition +postconditions +postconquest +postconsonantal +postconvention +postcopulatory +postcoronary +postcoup +postcranial +postcranially +postcrash +postcrisis +postdate +postdated +postdates +postdating +postdeadline +postdebate +postdebutante +postdelivery +postdepositional +postdepression +postdevaluation +postdiluvial +postdiluvian +postdive +postdivestiture +postdivorce +postdoc +postdocs +postdoctoral +postdoctorate +postdrug +poste +posted +postediting +postelection +postembryonal +postembryonic +postemergence +postemergency +postencephalitic +postepileptic +poster +posterior +posteriori +posteriority +posteriorly +posteriors +posterity +postern +posterns +posterolateral +posters +posteruptive +postexercise +postexilian +postexilic +postexperience +postexperimental +postexposure +postface +postfaces +postfault +postfeminist +postfire +postfix +postfixal +postfixed +postfixes +postfixial +postfixing +postflight +postfracture +postfreeze +postfrontal +postgame +postganglionic +postglacial +postgraduate +postgraduates +postgraduation +postharvest +posthaste +posthemorrhagic +posthole +postholes +postholiday +postholocaust +posthospital +posthumous +posthumously +posthumousness +posthypnotic +postiche +postiches +postilion +postilions +postillion +postillions +postimpact +postimperial +postimpressionism +postimpressionist +postimpressionistic +postimpressionists +postinaugural +postindependence +postindustrial +postinfection +posting +postings +postinjection +postinoculation +postirradiation +postischemic +postisolation +postlanding +postlapsarian +postlaunch +postliberation +postliterate +postlude +postludes +postman +postmarital +postmark +postmarked +postmarking +postmarks +postmastectomy +postmaster +postmasters +postmastership +postmasterships +postmating +postmedieval +postmen +postmenopausal +postmenstrual +postmeridian +postmidnight +postmillenarian +postmillenarianism +postmillenarians +postmillennial +postmillennialism +postmillennialist +postmillennialists +postmillennian +postmistress +postmistresses +postmodern +postmodernism +postmodernist +postmodernists +postmortem +postmortems +postnasal +postnatal +postnatally +postneonatal +postnuptial +postnuptially +postoperative +postoperatively +postorbital +postorgasmic +postovulatory +postpaid +postpartum +postpollination +postponable +postpone +postponed +postponement +postponements +postponer +postponers +postpones +postponing +postpose +postposed +postposes +postposing +postposition +postpositional +postpositionally +postpositions +postpositive +postpositively +postpositives +postprandial +postprandially +postpresidential +postprimary +postprison +postprocessor +postprocessors +postproduction +postproductions +postpsychoanalytic +postpuberty +postpubescent +postrace +postrecession +postresurrection +postretirement +postrevolutionary +postriot +postromantic +posts +postscript +postscripts +postseason +postsecondary +postshow +poststimulation +poststimulatory +poststimulus +poststrike +postsurgical +postsynaptic +postsynaptically +posttax +postteen +posttension +posttensioned +posttensioning +posttensions +posttest +posttests +posttranscriptional +posttransfusion +posttranslational +posttraumatic +posttreatment +posttrial +postulancy +postulant +postulants +postulantship +postulate +postulated +postulates +postulating +postulation +postulational +postulations +postulator +postulators +postural +posture +postured +posturer +posturers +postures +posturing +posturist +posturists +postvaccinal +postvaccination +postvagotomy +postvasectomy +postvertebral +postvocalic +postwar +postweaning +postworkshop +posy +pot +potability +potable +potableness +potables +potage +potages +potamoplankton +potamoplanktons +potash +potashes +potassic +potassium +potation +potations +potato +potatoes +potatory +potawatomi +potawatomis +potbellied +potbellies +potbelly +potboil +potboiled +potboiler +potboilers +potboiling +potboils +potbound +potboy +potboys +poteen +poteens +potemkin +potence +potences +potencies +potency +potent +potentate +potentates +potential +potentialities +potentiality +potentialize +potentialized +potentializes +potentializing +potentially +potentials +potentiate +potentiated +potentiates +potentiating +potentiation +potentiations +potentiator +potentiators +potentilla +potentillas +potentiometer +potentiometers +potentiometric +potently +potentness +potful +potfuls +pothead +potheads +potheen +potheens +pother +potherb +potherbs +pothered +pothering +pothers +potholder +potholders +pothole +potholed +potholes +pothook +pothooks +pothouse +pothouses +pothunter +pothunters +pothunting +potiche +potiches +potion +potions +potiphar +potlatch +potlatches +potline +potlines +potluck +potlucks +potomac +potometer +potometers +potpie +potpies +potpourri +potpourris +pots +potsdam +potshard +potshards +potsherd +potsherds +potshot +potshots +potshotting +potstone +potstones +pottage +potted +potter +pottered +potterer +potterers +potteries +pottering +potteringly +potters +pottery +pottier +potties +pottiest +potting +pottle +pottles +potto +pottos +potty +potzer +potzers +pouch +pouched +pouches +pouchier +pouchiest +pouching +pouchy +pouf +poufed +pouffe +pouffed +pouffes +pouffy +poufs +pouilly +poulard +poularde +poulardes +poulards +poult +poulter +poulterer +poulterers +poultice +poulticed +poultices +poulticing +poultry +poultryman +poultrymen +poults +pounce +pounced +pouncer +pouncers +pounces +pouncet +pouncets +pouncing +pound +poundage +poundal +poundals +pounded +pounder +pounders +pounding +pounds +pour +pourable +pourboire +pourboires +poured +pourer +pourers +pouring +pouringly +pourparler +pourparlers +pourpoint +pourpoints +pours +pousse +poussette +poussetted +poussettes +poussetting +poussin +pout +pouted +pouter +pouters +pouting +pouts +pouty +poverty +pow +powder +powdered +powderer +powderers +powdering +powderless +powderlike +powders +powdery +powell +power +powerboat +powerboats +powered +powerful +powerfully +powerfulness +powerhouse +powerhouses +powering +powerless +powerlessly +powerlessness +powerlifting +powerliftings +powers +powerwalking +powhatan +powhatans +pows +powwow +powwowed +powwowing +powwows +powys +pox +poxes +poxvirus +poxviruses +pozzolan +pozzolana +pozzolanas +pozzolanic +pozzolans +pozzuolana +pozzuolanas +pozzuolanic +pozzuoli +ppm +pq +praam +praams +practicability +practicable +practicableness +practicably +practical +practicalities +practicality +practically +practicalness +practice +practiced +practicer +practicers +practices +practicing +practicum +practicums +practise +practised +practises +practising +practitioner +practitioners +pradesh +prado +praecipe +praecipes +praecox +praedial +praemunire +praemunires +praenomen +praenomens +praenomina +praenominal +praesidium +praesidiums +praetor +praetorial +praetorian +praetorians +praetors +praetorship +praetorships +pragmatic +pragmatical +pragmatically +pragmaticism +pragmaticist +pragmaticists +pragmatics +pragmatism +pragmatist +pragmatistic +pragmatists +prague +prahu +prahus +prairie +prairies +praise +praised +praiseful +praiser +praisers +praises +praiseworthier +praiseworthiest +praiseworthily +praiseworthiness +praiseworthy +praising +prakrit +prakritic +prakrits +praline +pralines +pralltriller +pralltrillers +pram +prams +prance +pranced +prancer +prancers +prances +prancing +prancingly +prandial +prandially +prang +pranged +pranging +prangs +prank +pranked +pranking +prankish +prankishly +prankishness +pranks +prankster +pranksters +prase +praseodymium +prases +prat +prate +prated +prater +praters +prates +pratfall +pratfalls +pratincole +pratincoles +prating +pratingly +pratique +pratiques +prato +prats +prattle +prattled +prattler +prattlers +prattles +prattling +prattlingly +prau +praus +prawn +prawned +prawner +prawners +prawning +prawns +praxeological +praxeology +praxes +praxiology +praxis +praxiteles +pray +prayed +prayer +prayerful +prayerfully +prayerfulness +prayerlessness +prayers +praying +prays +prazosin +prazosins +pre +preach +preached +preacher +preachers +preaches +preachier +preachiest +preachification +preachifications +preachified +preachifies +preachify +preachifying +preachily +preachiness +preaching +preachingly +preachment +preachments +preachy +preadaptation +preadaptations +preadapted +preadaptive +preadmission +preadmissions +preadolescence +preadolescent +preadolescents +preadult +preagricultural +preamble +preambles +preambulary +preamp +preamplified +preamplifier +preamplifiers +preamps +preanesthetic +preannounce +preannounced +preannounces +preannouncing +preapprehension +preapprove +preapproved +preapproves +preapproving +prearrange +prearranged +prearrangement +prearrangements +prearranges +prearranging +preassembled +preassign +preassigned +preassigning +preassigns +preatomic +preaxial +preaxially +prebake +prebaked +prebakes +prebaking +prebattle +prebattled +prebattles +prebattling +prebend +prebendal +prebendaries +prebendary +prebends +prebiblical +prebiologic +prebiological +prebiologist +prebiologists +prebiology +prebiotic +prebook +prebooked +prebooking +prebooks +prebreakfast +prebreakfasts +prebuilt +precalculus +precambrian +precancel +precanceled +precanceling +precancellation +precancellations +precancelled +precancelling +precancels +precancer +precancerous +precancers +precapitalist +precarious +precariously +precariousness +precast +precasting +precasts +precative +precatory +precaution +precautional +precautionary +precautions +precava +precavae +precaval +precede +preceded +precedence +precedency +precedent +precedential +precedents +precedes +preceding +precensor +precensored +precensoring +precensors +precentor +precentorial +precentors +precentorship +precentorships +precept +preceptive +preceptively +preceptor +preceptorial +preceptorially +preceptories +preceptors +preceptorship +preceptorships +preceptory +precepts +precess +precessed +precesses +precessing +precession +precessional +precessions +prechill +prechilled +prechilling +prechills +prechristmas +precieuse +precieux +precinct +precincts +preciosities +preciosity +precious +preciously +preciousness +precipe +precipes +precipice +precipices +precipitable +precipitance +precipitancy +precipitant +precipitantly +precipitantness +precipitants +precipitate +precipitated +precipitately +precipitateness +precipitates +precipitating +precipitation +precipitations +precipitative +precipitator +precipitators +precipitin +precipitinogen +precipitinogens +precipitins +precipitous +precipitously +precipitousness +precise +precisely +preciseness +precisian +precisianism +precisians +precision +precisionism +precisionist +precisionists +precisions +preclear +preclearance +precleared +preclearing +preclears +preclinical +preclude +precluded +precludes +precluding +preclusion +preclusive +preclusively +precocial +precocious +precociously +precociousness +precocity +precode +precoded +precodes +precoding +precognition +precognitions +precognitive +precognizant +precoital +precollege +precollegiate +precolonial +precombustion +precommitment +precommitments +precompute +precomputed +precomputer +precomputes +precomputing +preconceive +preconceived +preconceives +preconceiving +preconception +preconceptions +preconcert +preconcerted +preconcerting +preconcerts +precondition +preconditioned +preconditioning +preconditions +preconquest +preconscious +preconsciously +preconsonantal +preconstructed +precontact +precontract +precontracted +precontracting +precontracts +precontrived +preconvention +preconviction +preconvictions +precook +precooked +precooking +precooks +precool +precooled +precooling +precools +precopulatory +precrash +precrease +precreased +precreases +precreasing +precrisis +precritical +precursive +precursor +precursors +precursory +precut +precuts +precutting +predaceous +predaceousness +predacious +predaciousness +predacity +predate +predated +predates +predating +predation +predations +predator +predatorily +predatoriness +predators +predatory +predawn +predawns +predecease +predeceased +predeceases +predeceasing +predecessor +predecessors +predefine +predefined +predefines +predefining +predefinition +predefinitions +predelivery +predeparture +predesignate +predesignated +predesignates +predesignating +predesignation +predesignations +predestinarian +predestinarianism +predestinarians +predestinate +predestinated +predestinates +predestinating +predestination +predestinator +predestinators +predestine +predestined +predestines +predestining +predeterminate +predetermination +predeterminations +predetermine +predetermined +predeterminer +predeterminers +predetermines +predetermining +predevaluation +predevelopment +prediabetes +prediabetic +prediabetics +predial +predicability +predicable +predicableness +predicables +predicament +predicamental +predicamentally +predicaments +predicate +predicated +predicates +predicating +predication +predicational +predications +predicative +predicatively +predicator +predicators +predicatory +predict +predictability +predictable +predictably +predicted +predicting +prediction +predictions +predictive +predictively +predictiveness +predictor +predictors +predicts +predigest +predigested +predigesting +predigestion +predigestions +predigests +predilection +predilections +predinner +predischarge +prediscoveries +prediscovery +predispose +predisposed +predisposes +predisposing +predisposition +predispositions +predive +prednisolone +prednisolones +prednisone +prednisones +predoctoral +predominance +predominancy +predominant +predominantly +predominate +predominated +predominately +predominates +predominating +predominatingly +predomination +predominations +predominator +predominators +predrill +predrilled +predrilling +predrills +predynastic +preeclampsia +preeclamptic +preelection +preelectric +preembargo +preemergence +preemergent +preemie +preemies +preeminence +preeminent +preeminently +preemployment +preemployments +preempt +preempted +preempting +preemption +preemptions +preemptive +preemptively +preemptor +preemptors +preemptory +preempts +preen +preened +preener +preeners +preengineered +preening +preenrollment +preens +preerect +preerected +preerecting +preerects +preestablish +preestablished +preestablishes +preestablishing +preethical +preexilian +preexilic +preexist +preexisted +preexistence +preexistent +preexisting +preexists +preexperiment +prefab +prefabed +prefabing +prefabricate +prefabricated +prefabricates +prefabricating +prefabrication +prefabrications +prefabricator +prefabricators +prefabs +preface +prefaced +prefacer +prefacers +prefaces +prefacing +prefade +prefaded +prefades +prefading +prefascist +prefatorily +prefatory +prefect +prefects +prefectural +prefecture +prefectures +prefer +preferability +preferable +preferableness +preferably +preference +preferences +preferential +preferentialism +preferentialist +preferentialists +preferentially +preferment +preferments +preferred +preferrer +preferrers +preferring +prefers +prefeudal +prefight +prefiguration +prefigurations +prefigurative +prefiguratively +prefigurativeness +prefigure +prefigured +prefigurement +prefigurements +prefigures +prefiguring +prefile +prefiled +prefiles +prefiling +prefilled +prefinance +prefinanced +prefinances +prefinancing +prefinished +prefire +prefix +prefixal +prefixally +prefixed +prefixes +prefixing +preflame +preflight +preflighted +preflighting +preflights +prefocus +prefocused +prefocuses +prefocusing +preform +preformat +preformation +preformationist +preformationists +preformations +preformats +preformatted +preformatting +preformed +preforming +preforms +preformulate +preformulated +preformulates +preformulating +prefreshman +prefreshmen +prefrontal +prefrozen +pregame +preganglionic +pregenital +pregnability +pregnable +pregnancies +pregnancy +pregnant +pregnantly +pregnenolone +pregnenolones +preharvest +preheadache +preheat +preheated +preheater +preheaters +preheating +preheats +prehensile +prehensility +prehension +prehensions +prehiring +prehistorian +prehistorians +prehistoric +prehistorical +prehistorically +prehistories +prehistory +preholiday +prehominid +prehominids +prehuman +preignition +preignitions +preimplantation +preinaugural +preincorporation +preinduction +preindustrial +preinstall +preinstalled +preinstalling +preinstalls +preinterview +preinvasion +prejudge +prejudged +prejudgement +prejudgements +prejudger +prejudgers +prejudges +prejudging +prejudgment +prejudgments +prejudice +prejudiced +prejudices +prejudicial +prejudicially +prejudicialness +prejudicing +prejudicious +prejudiciously +prekindergarten +prelacies +prelacy +prelapsarian +prelate +prelates +prelateship +prelateships +prelatic +prelature +prelatures +prelaunch +prelaw +prelect +prelected +prelecting +prelection +prelections +prelector +prelectors +prelects +prelibation +prelibations +prelife +prelim +preliminaries +preliminarily +preliminary +prelims +preliterary +preliterate +preliterates +preloaded +prelogical +prelude +preluded +preluder +preluders +preludes +preludial +preluding +prelunch +preluncheon +prelusion +prelusions +prelusive +prelusively +premade +premalignant +preman +premanufacture +premarital +premaritally +premarket +premarketed +premarketing +premarkets +premarriage +premature +prematurely +prematureness +prematurity +premaxilla +premaxillae +premaxillary +premeal +premeasure +premeasured +premeasures +premeasuring +premed +premedical +premedieval +premeditate +premeditated +premeditatedly +premeditates +premeditating +premeditation +premeditative +premeditator +premeditators +premeds +premeet +premeiotic +premenopausal +premenstrual +premenstrually +premerger +premie +premier +premiere +premiered +premieres +premiering +premiers +premiership +premierships +premies +premigration +premillenarian +premillenarianism +premillenarians +premillennial +premillennialism +premillennialist +premillennialists +premillennially +premise +premised +premises +premising +premiss +premisses +premium +premiums +premix +premixed +premixes +premixing +première +premièred +premières +premièring +premodern +premodification +premodified +premodifies +premodify +premodifying +premoisten +premoistened +premoistening +premoistens +premolar +premolars +premold +premolded +premolding +premolds +premolt +premonish +premonished +premonishes +premonishing +premonition +premonitions +premonitorily +premonitory +premonstratensian +premonstratensians +premoral +premorse +premune +premunition +premunitions +premycotic +prename +prenames +prenatal +prenatally +prenominate +prenominated +prenominates +prenominating +prenomination +prenominations +prenoon +prenotification +prenotifications +prenotified +prenotifies +prenotify +prenotifying +prenotion +prenotions +prentice +prenticed +prentices +prenticing +prenumber +prenumbered +prenumbering +prenumbers +prenuptial +preoccupancy +preoccupation +preoccupations +preoccupied +preoccupies +preoccupy +preoccupying +preopening +preoperational +preoperative +preoperatively +preoral +preorbital +preordain +preordained +preordaining +preordainment +preordainments +preordains +preorder +preordered +preordering +preorders +preordination +preordinations +preovulatory +preowned +prep +prepack +prepackage +prepackaged +prepackages +prepackaging +prepacked +prepacking +prepacks +prepaid +preparation +preparations +preparative +preparatively +preparatives +preparator +preparatorily +preparators +preparatory +prepare +prepared +preparedly +preparedness +preparer +preparers +prepares +preparing +prepaste +prepasted +prepastes +prepasting +prepay +prepaying +prepayment +prepayments +prepays +prepense +prepensely +preperformance +prepill +preplan +preplanned +preplanning +preplans +preplant +preplanting +preponderance +preponderancy +preponderant +preponderantly +preponderate +preponderated +preponderately +preponderates +preponderating +preponderation +preponderations +preportion +preportioned +preportioning +preportions +preposition +prepositional +prepositionally +prepositioned +prepositioning +prepositions +prepositive +prepositively +prepositives +prepossess +prepossessed +prepossesses +prepossessing +prepossessingly +prepossessingness +prepossession +prepossessions +preposterous +preposterously +preposterousness +prepotencies +prepotency +prepotent +prepotently +prepped +preppie +preppies +preppily +preppiness +prepping +preppy +preprandial +prepreg +preprepared +prepresidential +preprice +prepriced +preprices +prepricing +preprimaries +preprimary +preprint +preprinted +preprinting +preprints +preprocess +preprocessed +preprocesses +preprocessing +preprocessor +preprocessors +preproduction +preproductions +preprofessional +preprogram +preprogramed +preprograming +preprogrammed +preprogramming +preprograms +preps +prepsychedelic +prepuberal +prepubertal +prepuberty +prepubescence +prepubescent +prepubescents +prepublication +prepuce +prepuces +prepunch +prepunched +prepunches +prepunching +prepupa +prepupae +prepupal +prepupas +prepurchase +prepurchased +prepurchases +prepurchasing +preputial +prequalification +prequalified +prequalifies +prequalify +prequalifying +prequel +prequels +prerace +prerecession +prerecord +prerecorded +prerecording +prerecords +preregister +preregistered +preregistering +preregisters +preregistration +preregistrations +prerehearsal +prerelease +prereleases +prerequire +prerequired +prerequires +prerequiring +prerequisite +prerequisites +preretirement +preretirements +prereturn +prereview +prerevisionist +prerevolution +prerevolutionary +prerinse +prerinsed +prerinses +prerinsing +preriot +prerock +prerogative +prerogatived +prerogatives +preromantic +presage +presaged +presageful +presager +presagers +presages +presaging +presale +presales +presanctified +presbyope +presbyopes +presbyopia +presbyopic +presbyter +presbyterate +presbyterates +presbyterial +presbyterially +presbyterian +presbyterianism +presbyterians +presbyteries +presbyters +presbytery +preschedule +prescheduled +preschedules +prescheduling +preschool +preschooler +preschoolers +preschooling +preschools +prescience +prescient +prescientific +presciently +prescind +prescinded +prescinding +prescinds +prescore +prescored +prescores +prescoring +prescreen +prescreened +prescreening +prescreens +prescribe +prescribed +prescriber +prescribers +prescribes +prescribing +prescript +prescriptibility +prescriptible +prescription +prescriptions +prescriptive +prescriptively +prescriptiveness +prescriptivist +prescriptivists +prescripts +preseason +preseasons +preselect +preselected +preselecting +preselection +preselections +preselects +presell +preselling +presells +presence +present +presentability +presentable +presentableness +presentably +presentation +presentational +presentations +presentative +presentativeness +presented +presentee +presentees +presentence +presentencing +presenter +presenters +presentient +presentiment +presentimental +presentiments +presenting +presentism +presentist +presentists +presently +presentment +presentments +presentness +presents +preservability +preservable +preservation +preservationism +preservationist +preservationists +preservations +preservative +preservatives +preserve +preserved +preserver +preservers +preserves +preservice +preserving +preset +presets +presettable +presetting +presettlement +preshow +preshrank +preshrink +preshrinks +preshrunk +preside +presided +presidencies +presidency +president +presidential +presidentially +presidents +presidentship +presidentships +presider +presiders +presides +presidia +presidial +presidiary +presiding +presidio +presidios +presidium +presidiums +presignified +presignifies +presignify +presignifying +preslaughter +presleep +preslice +presliced +preslices +preslicing +presoak +presoaked +presoaking +presoaks +presold +presong +presort +presorted +presorting +presorts +prespecified +prespecifies +prespecify +prespecifying +presplit +press +pressboard +pressboards +pressed +presser +pressers +presses +pressing +pressingly +pressings +pressman +pressmark +pressmarks +pressmen +pressor +pressroom +pressrooms +pressrun +pressruns +pressure +pressured +pressureless +pressures +pressuring +pressurization +pressurizations +pressurize +pressurized +pressurizer +pressurizers +pressurizes +pressurizing +presswork +prest +prestamp +prestamped +prestamping +prestamps +prestellar +prester +presterilize +presterilized +presterilizes +presterilizing +presternum +presternums +prestidigitation +prestidigitations +prestidigitator +prestidigitators +prestige +prestigeful +prestigious +prestigiously +prestigiousness +prestissimo +prestissimos +presto +prestorage +prestos +prestress +prestressed +prestresses +prestressing +prestrike +prestructure +prestructured +prestructures +prestructuring +presumable +presumably +presume +presumed +presumedly +presumer +presumers +presumes +presuming +presumingly +presummit +presumption +presumptions +presumptive +presumptively +presumptuous +presumptuously +presumptuousness +presuppose +presupposed +presupposes +presupposing +presupposition +presuppositional +presuppositions +presurgery +presweeten +presweetened +presweetening +presweetens +presymptomatic +presynaptic +presynaptically +pretape +pretaped +pretapes +pretaping +pretax +pretechnological +preteen +preteenager +preteenagers +preteens +pretelevision +pretence +pretences +pretend +pretended +pretendedly +pretender +pretenders +pretending +pretends +pretense +pretenses +pretension +pretensionless +pretensions +pretentious +pretentiously +pretentiousness +preterit +preterite +preterition +preteritions +preterits +preterm +preterminal +pretermination +pretermission +pretermissions +pretermit +pretermits +pretermitted +pretermitter +pretermitters +pretermitting +preterms +preternatural +preternaturalism +preternaturally +preternaturalness +pretest +pretested +pretesting +pretests +pretext +pretexted +pretexting +pretexts +pretheater +preticket +preticketed +preticketing +pretickets +pretor +pretoria +pretorian +pretorians +pretors +pretournament +pretrain +pretravel +pretreat +pretreated +pretreating +pretreatment +pretreatments +pretreats +pretrial +pretrials +pretrimmed +prettied +prettier +pretties +prettiest +prettification +prettifications +prettified +prettifier +prettifiers +prettifies +prettify +prettifying +prettily +prettiness +pretty +prettying +prettyish +pretype +pretyped +pretypes +pretyping +pretzel +pretzels +preunification +preuniversity +prevail +prevailed +prevailer +prevailers +prevailing +prevailingly +prevailingness +prevails +prevalence +prevalent +prevalently +prevaricate +prevaricated +prevaricates +prevaricating +prevarication +prevarications +prevaricator +prevaricators +prevenience +preveniences +prevenient +preveniently +prevent +preventability +preventable +preventative +preventatively +preventatives +prevented +preventer +preventers +preventibility +preventible +preventing +prevention +preventions +preventive +preventively +preventiveness +preventives +prevents +preverb +preverbal +preverbs +previable +preview +previewed +previewer +previewers +previewing +previews +previous +previously +previousness +previse +prevised +previses +prevising +prevision +previsional +previsionary +previsioned +previsioning +previsions +previsor +previsors +prevocalic +prevocational +prevue +prevued +prevues +prevuing +prewar +prewarn +prewarned +prewarning +prewarns +prewash +prewashed +prewashes +prewashing +preweaning +prework +prewrap +prewrapped +prewrapping +prewraps +prewriting +prex +prexes +prexies +prexy +prey +preyed +preyer +preyers +preying +preys +prez +prezes +priam +priapean +priapic +priapism +priapus +priapuses +pribilof +price +priceable +priced +priceless +pricelessly +pricer +pricers +prices +pricey +priceyness +pricier +priciest +pricily +pricing +prick +pricked +pricker +prickers +pricket +prickets +prickier +prickiest +pricking +prickle +prickled +prickles +pricklier +prickliest +prickliness +prickling +prickly +pricks +pricky +pricy +pride +prided +prideful +pridefully +pridefulness +prides +priding +pried +prier +priers +pries +priest +priested +priestess +priestesses +priesthood +priesting +priestley +priestlier +priestliest +priestliness +priestly +priests +prig +prigged +priggery +prigging +priggish +priggishly +priggishness +priggism +prigs +prill +prilled +prilling +prills +prim +prima +primacies +primacy +primal +primality +primaries +primarily +primary +primate +primates +primateship +primatial +primatological +primatologist +primatologists +primatology +primavera +primaveras +prime +primed +primely +primeness +primer +primero +primers +primes +primeval +primevally +primi +priming +primings +primipara +primiparae +primiparas +primiparity +primiparous +primitive +primitively +primitiveness +primitives +primitivism +primitivist +primitivistic +primitivists +primitivity +primly +primmed +primmer +primmest +primming +primness +primo +primogenital +primogenitary +primogenitor +primogenitors +primogeniture +primogenitures +primordia +primordial +primordially +primordials +primordium +primos +primp +primped +primping +primps +primrose +primroses +prims +primula +primus +primuses +prince +princedom +princedoms +princelet +princelets +princelier +princeliest +princeliness +princeling +princelings +princely +princes +princeship +princeships +princess +princesse +princesses +princeton +principal +principalities +principality +principally +principals +principalship +principalships +principe +principia +principium +principle +principled +principles +princox +prink +prinked +prinker +prinkers +prinking +prinks +print +printability +printable +printed +printer +printer's +printeries +printers +printery +printhead +printheads +printing +printings +printless +printmaker +printmakers +printmaking +printout +printouts +prints +prion +prions +prior +priorate +priorates +prioress +prioresses +priori +priories +priorities +prioritization +prioritizations +prioritize +prioritized +prioritizes +prioritizing +priority +priorly +priors +priorship +priorships +priory +pris +prise +prised +prises +prising +prism +prismatic +prismatical +prismatically +prismatoid +prismatoidal +prismatoids +prismoid +prismoidal +prismoids +prisms +prison +prisoned +prisoner +prisoners +prisoning +prisons +prissier +prissiest +prissily +prissiness +prissy +pristane +pristanes +pristine +pristinely +prithee +privacy +privatdocent +privatdocents +private +privateer +privateered +privateering +privateers +privately +privateness +privates +privation +privations +privatism +privatist +privatistic +privatists +privative +privatively +privatives +privatization +privatizations +privatize +privatized +privatizes +privatizing +privet +privets +privies +privilege +privileged +privileges +privileging +privily +privities +privity +privy +prix +prize +prized +prizefight +prizefighter +prizefighters +prizefighting +prizefights +prizer +prizers +prizes +prizewinner +prizewinners +prizewinning +prizing +pro +proa +proabortion +proaction +proactions +proactive +proactively +proas +probabilism +probabilist +probabilistic +probabilistically +probabilists +probabilities +probability +probable +probably +proband +probands +probang +probangs +probate +probated +probates +probating +probation +probational +probationally +probationary +probationer +probationers +probations +probative +probatory +probe +probed +probenecid +probenecids +prober +probers +probes +probing +probingly +probit +probits +probity +problem +problematic +problematical +problematically +problematization +problematize +problematized +problematizes +problematizing +problems +proboscidean +proboscideans +proboscides +proboscidian +proboscidians +proboscis +proboscises +procaine +procaines +procambial +procambium +procambiums +procarbazine +procarbazines +procaryote +procaryotes +procathedral +procathedrals +procedural +procedurally +procedurals +procedure +procedures +proceed +proceeded +proceeder +proceeders +proceeding +proceedings +proceeds +procephalic +procercoid +procercoids +process +processability +processable +processed +processes +processibility +processible +processing +procession +processional +processionally +processionals +processioned +processioning +processions +processor +processors +proclaim +proclaimed +proclaimer +proclaimers +proclaiming +proclaims +proclamation +proclamations +proclamatory +proclitic +proclitics +proclivities +proclivity +procoagulant +procoagulants +procommunist +procommunists +proconsul +proconsular +proconsulate +proconsulates +proconsuls +proconsulship +proconsulships +procrastinate +procrastinated +procrastinates +procrastinating +procrastination +procrastinations +procrastinative +procrastinator +procrastinators +procrastinatory +procreant +procreate +procreated +procreates +procreating +procreation +procreations +procreative +procreativity +procreator +procreators +procrustean +procryptic +proctitis +proctodaea +proctodaeum +proctodaeums +proctodea +proctodeum +proctodeums +proctologic +proctological +proctologically +proctologist +proctologists +proctology +proctor +proctored +proctorial +proctoring +proctors +proctorship +proctorships +proctoscope +proctoscopes +proctoscopic +proctoscopy +procumbent +procurable +procurance +procuration +procurations +procurator +procuratorial +procurators +procure +procured +procurement +procurements +procurer +procurers +procures +procuress +procuresses +procuring +procyon +procès +prod +prodded +prodder +prodders +prodding +prodigal +prodigalities +prodigality +prodigally +prodigals +prodigies +prodigious +prodigiously +prodigiousness +prodigy +prodromal +prodromata +prodrome +prodromes +prodromic +prodrug +prodrugs +prods +produce +produceable +produced +producer +producers +produces +producible +producing +product +production +productional +productions +productive +productively +productiveness +productivity +products +proem +proemial +proems +proenzyme +proenzymes +proestrus +proestruses +prof +profanation +profanations +profanatory +profane +profaned +profanely +profaneness +profaner +profaners +profanes +profaning +profanities +profanity +profess +professed +professedly +professes +professing +profession +professional +professionalism +professionalization +professionalizations +professionalize +professionalized +professionalizes +professionalizing +professionally +professionals +professions +professor +professorate +professorates +professorial +professorially +professoriat +professoriate +professoriates +professoriats +professors +professorship +professorships +proffer +proffered +profferer +profferers +proffering +proffers +proficiencies +proficiency +proficient +proficiently +proficients +profile +profiled +profiler +profilers +profiles +profiling +profit +profitability +profitable +profitableness +profitably +profited +profiteer +profiteered +profiteering +profiteers +profiterole +profiteroles +profiting +profitless +profits +profitwise +profligacy +profligate +profligately +profligates +profluent +profound +profounder +profoundest +profoundly +profoundness +profs +profundis +profundities +profundity +profundo +profundos +profuse +profusely +profuseness +profusion +progenies +progenitor +progenitors +progeny +progeria +progestational +progesterone +progestin +progestins +progestogen +progestogenic +progestogens +proglottic +proglottid +proglottidean +proglottides +proglottids +proglottis +prognathic +prognathism +prognathous +prognoses +prognosis +prognostic +prognosticate +prognosticated +prognosticates +prognosticating +prognostication +prognostications +prognosticative +prognosticator +prognosticators +prognosticatory +prognostics +prograde +program +programed +programer +programers +programing +programmability +programmable +programmatic +programmatically +programmed +programmer +programmers +programming +programs +progress +progressed +progresses +progressing +progression +progressional +progressions +progressive +progressively +progressiveness +progressives +progressivism +progressivist +progressivistic +progressivists +progressivities +progressivity +prohibit +prohibited +prohibiting +prohibition +prohibitionism +prohibitionist +prohibitionists +prohibitions +prohibitive +prohibitively +prohibitiveness +prohibitory +prohibits +proinsulin +proinsulins +project +projectable +projected +projectile +projectiles +projecting +projection +projectional +projectionist +projectionists +projections +projective +projectively +projector +projectors +projects +projet +projets +prokaryote +prokaryotes +prokaryotic +prokofiev +prolactin +prolactins +prolamin +prolamine +prolamines +prolamins +prolan +prolans +prolapse +prolapsed +prolapses +prolapsing +prolapsus +prolate +prolately +prolateness +prole +proleg +prolegomena +prolegomenon +prolegomenous +prolegs +prolepses +prolepsis +proleptic +proleptical +proleptically +proles +proletarian +proletarianism +proletarianization +proletarianizations +proletarianize +proletarianized +proletarianizes +proletarianizing +proletarians +proletariat +proletariats +proliferate +proliferated +proliferates +proliferating +proliferation +proliferations +proliferative +proliferator +proliferators +proliferous +proliferously +prolific +prolificacy +prolifically +prolificity +prolificness +proline +prolines +prolix +prolixity +prolixly +prolocutor +prolocutors +prolog +prologize +prologized +prologizes +prologizing +prologs +prologue +prologues +prologuize +prologuized +prologuizes +prologuizing +prolong +prolongate +prolongated +prolongates +prolongating +prolongation +prolongations +prolonged +prolonger +prolongers +prolonging +prolongs +prolusion +prolusions +prolusory +prom +promenade +promenaded +promenader +promenaders +promenades +promenading +promethean +prometheans +prometheus +promethium +prominence +prominences +prominency +prominent +prominently +promiscuities +promiscuity +promiscuous +promiscuously +promiscuousness +promise +promised +promisee +promisees +promiser +promisers +promises +promising +promisingly +promisor +promisors +promissory +promo +promontories +promontory +promos +promotability +promotable +promote +promoted +promoter +promoters +promotes +promoting +promotion +promotional +promotionally +promotions +promotive +promotiveness +prompt +promptbook +promptbooks +prompted +prompter +prompters +promptest +prompting +promptitude +promptly +promptness +prompts +proms +promulgate +promulgated +promulgates +promulgating +promulgation +promulgations +promulgator +promulgators +pronatalism +pronatalist +pronatalistic +pronatalists +pronate +pronated +pronates +pronating +pronation +pronations +pronator +pronators +prone +pronely +proneness +pronephra +pronephric +pronephroi +pronephros +prong +pronged +pronghorn +pronghorns +pronging +prongs +pronograde +pronominal +pronominally +pronoun +pronounce +pronounceability +pronounceable +pronounced +pronouncedly +pronouncedness +pronouncement +pronouncements +pronouncer +pronouncers +pronounces +pronouncing +pronouns +pronto +prontosil +pronuclear +pronuclei +pronucleus +pronunciamento +pronunciamentoes +pronunciamentos +pronunciation +pronunciational +pronunciations +proof +proofed +proofer +proofers +proofing +proofread +proofreader +proofreaders +proofreading +proofreads +proofroom +proofrooms +proofs +prop +propaedeutic +propaedeutics +propagable +propaganda +propagandism +propagandist +propagandistic +propagandistically +propagandists +propagandize +propagandized +propagandizer +propagandizers +propagandizes +propagandizing +propagate +propagated +propagates +propagating +propagation +propagational +propagations +propagative +propagator +propagators +propagule +propagules +propane +propanoate +propanoic +propanol +propel +propellant +propellants +propelled +propellent +propellents +propeller +propellers +propelling +propellor +propellors +propels +propend +propended +propending +propends +propene +propenes +propense +propensities +propensity +proper +properdin +properdins +properly +properness +propertied +properties +propertius +property +propertyless +propertylessness +prophage +prophages +prophase +prophases +prophasic +prophecies +prophecy +prophesied +prophesier +prophesiers +prophesies +prophesy +prophesying +prophet +prophetess +prophetesses +prophethood +prophetic +prophetical +prophetically +propheticalness +prophets +prophylactic +prophylactically +prophylactics +prophylaxes +prophylaxis +propinquity +propionaldehyde +propionaldehydes +propionate +propionates +propionic +propitiable +propitiate +propitiated +propitiates +propitiating +propitiatingly +propitiation +propitiations +propitiative +propitiator +propitiatorily +propitiators +propitiatory +propitious +propitiously +propitiousness +propjet +propjets +proplastid +proplastids +propman +propmen +propolis +propolises +propone +proponed +proponent +proponents +propones +proponing +proportion +proportionable +proportionably +proportional +proportionality +proportionally +proportionals +proportionate +proportionated +proportionately +proportionateness +proportionates +proportionating +proportioned +proportioner +proportioners +proportioning +proportionment +proportionments +proportions +proposal +proposals +propose +proposed +proposer +proposers +proposes +proposing +propositi +proposition +propositional +propositionally +propositioned +propositioning +propositions +propositus +propound +propounded +propounder +propounders +propounding +propounds +propoxyphene +propoxyphenes +propped +propping +propraetor +propraetorial +propraetorian +propraetors +propranolol +propranolols +propre +propretor +propretors +propria +propriae +proprietaries +proprietarily +proprietary +proprieties +proprietor +proprietorial +proprietorially +proprietors +proprietorship +proprietorships +proprietress +proprietresses +propriety +proprioception +proprioceptions +proprioceptive +proprioceptor +proprioceptors +props +proptoses +proptosis +propulsion +propulsions +propulsive +propulsory +propyl +propyla +propylaea +propylaeum +propylene +propylic +propylon +propyls +proratable +prorate +prorated +prorates +prorating +proration +prorations +prorogate +prorogated +prorogates +prorogating +prorogation +prorogations +prorogue +prorogued +prorogues +proroguing +pros +prosaic +prosaically +prosaicness +prosaism +prosaisms +prosaist +prosaists +prosateur +prosateurs +prosauropod +prosauropods +proscenia +proscenium +prosceniums +prosciutti +prosciutto +prosciuttos +proscribe +proscribed +proscriber +proscribers +proscribes +proscribing +proscription +proscriptions +proscriptive +proscriptively +prose +prosector +prosectors +prosecutable +prosecute +prosecuted +prosecutes +prosecuting +prosecution +prosecutions +prosecutor +prosecutorial +prosecutors +prosed +proselyte +proselyted +proselyter +proselyters +proselytes +proselytical +proselyting +proselytism +proselytisms +proselytization +proselytizations +proselytize +proselytized +proselytizer +proselytizers +proselytizes +proselytizing +proseminar +proseminars +prosencephalic +prosencephalon +prosencephalons +prosenchyma +prosenchymas +prosenchymatous +prosequi +prosequitur +proser +proserpine +prosers +proses +prosier +prosiest +prosily +prosimian +prosimians +prosiness +prosing +prosit +proslavery +proso +prosobranch +prosobranchs +prosodic +prosodical +prosodically +prosodies +prosodist +prosodists +prosody +prosoma +prosomal +prosomas +prosopographical +prosopography +prosopopeia +prosopopeial +prosopopeias +prosopopoeia +prosopopoeias +prospect +prospected +prospecting +prospective +prospectively +prospector +prospectors +prospects +prospectus +prospectuses +prosper +prospered +prospering +prosperity +prosperous +prosperously +prosperousness +prospers +prost +prostacyclin +prostacyclins +prostaglandin +prostaglandins +prostate +prostatectomies +prostatectomy +prostates +prostatic +prostatism +prostatisms +prostatitis +prostheses +prosthesis +prosthetic +prosthetically +prosthetics +prosthetist +prosthetists +prosthodontia +prosthodontic +prosthodontics +prosthodontist +prosthodontists +prostitute +prostituted +prostitutes +prostituting +prostitution +prostitutions +prostitutor +prostitutors +prostomia +prostomial +prostomium +prostrate +prostrated +prostrates +prostrating +prostration +prostrations +prostrator +prostrators +prostyle +prosy +protactinium +protagonist +protagonists +protamin +protamine +protamines +protamins +protandrous +protandry +protanopia +protanopias +protanopic +protases +protasis +protatic +protea +protean +proteas +protease +proteases +protect +protectant +protectants +protected +protecter +protecters +protecting +protectingly +protection +protectional +protectionism +protectionist +protectionists +protections +protective +protectively +protectiveness +protectives +protector +protectoral +protectorate +protectorates +protectories +protectors +protectorship +protectorships +protectory +protectress +protectresses +protects +protei +proteid +proteids +protein +proteinaceous +proteinase +proteinases +proteinic +proteinoid +proteinoids +proteins +proteinuria +proteinurias +protend +protended +protending +protends +protensive +protensively +proteoclastic +proteoglycan +proteoglycans +proteolyses +proteolysis +proteolytic +proteolytically +proteose +proteoses +proteron +proterozoic +protest +protestant +protestantism +protestants +protestation +protestations +protested +protester +protesters +protesting +protestingly +protestor +protestors +protests +proteus +prothalamia +prothalamion +prothalamium +prothalli +prothallia +prothallial +prothallium +prothallus +protheses +prothesis +prothetic +prothetically +prothonotarial +prothonotaries +prothonotary +prothoraces +prothoracic +prothorax +prothoraxes +prothrombin +prothrombins +protist +protista +protistan +protistans +protistology +protists +protium +protiums +protocol +protocolar +protocolary +protocoled +protocoling +protocolled +protocolling +protocols +protocontinent +protocontinents +protoctist +protoctists +protoderm +protodermal +protoderms +protogalaxies +protogalaxy +protogynous +protogyny +protohistorian +protohistorians +protohistoric +protohistory +protohuman +protohumans +protolanguage +protolanguages +protolithic +protomartyr +protomartyrs +protomorph +protomorphic +protomorphs +proton +protonate +protonated +protonates +protonating +protonation +protonations +protonema +protonemal +protonemata +protonematal +protonic +protonotaries +protonotary +protons +protopathic +protopathy +protophloem +protophloems +protoplanet +protoplanetary +protoplanets +protoplasm +protoplasmal +protoplasmatic +protoplasmic +protoplast +protoplastic +protoplasts +protoporphyrin +protoporphyrins +protostar +protostars +protostele +protosteles +protostelic +protostome +protostomes +prototroph +prototrophic +prototrophs +prototrophy +prototypal +prototype +prototyped +prototypes +prototypic +prototypical +prototypically +prototyping +protoxylem +protoxylems +protozoa +protozoal +protozoan +protozoans +protozoic +protozoological +protozoologist +protozoologists +protozoology +protozoon +protract +protracted +protractedly +protractedness +protractible +protractile +protractility +protracting +protraction +protractions +protractive +protractor +protractors +protracts +protreptic +protreptics +protrude +protruded +protrudent +protrudes +protruding +protrusible +protrusile +protrusility +protrusion +protrusions +protrusive +protrusively +protrusiveness +protuberance +protuberances +protuberancies +protuberancy +protuberant +protuberantly +protuberate +protuberated +protuberates +protuberating +protuberation +protuberations +protégé +protégée +protégées +protégés +proud +prouder +proudest +proudful +proudhearted +proudly +proudness +proust +proustian +proustite +proustites +provability +provable +provableness +provably +provascular +prove +proved +proven +provenance +provenances +provence +provender +provenience +proveniences +provenly +proventricular +proventriculi +proventriculus +provençal +provençale +provençals +provençaux +prover +proverb +proverbial +proverbially +proverbs +provers +proves +provide +provided +providence +provident +providential +providentially +providently +provider +providers +provides +providing +province +provinces +provincial +provincialism +provincialist +provincialists +provinciality +provincialization +provincializations +provincialize +provincialized +provincializes +provincializing +provincially +provincials +proving +proviral +provirus +proviruses +provision +provisional +provisionally +provisionals +provisionary +provisioned +provisioner +provisioners +provisioning +provisions +proviso +provisoes +provisorily +provisory +provisos +provitamin +provitamins +provo +provocateur +provocateurs +provocation +provocations +provocative +provocatively +provocativeness +provocatives +provoke +provoked +provoker +provokers +provokes +provoking +provokingly +provolone +provos +provost +provosts +prow +prowess +prowl +prowled +prowler +prowlers +prowling +prowls +prows +proxemic +proxemics +proxies +proximal +proximally +proximate +proximately +proximateness +proximity +proximo +proxy +prude +prudence +prudent +prudential +prudentially +prudently +pruderies +prudery +prudes +prudish +prudishly +prudishness +pruinose +prune +pruned +prunella +prunellas +prunelle +prunelles +prunello +prunellos +pruner +pruners +prunes +pruning +prunus +prurience +pruriency +prurient +pruriently +pruriginous +prurigo +prurigos +pruritic +pruritus +prurituses +prussia +prussian +prussianism +prussianization +prussianizations +prussianize +prussianized +prussianizes +prussianizing +prussians +prussiate +prussiates +prussic +pruta +prutah +prutot +prutoth +pry +pryer +pryers +prying +pryingly +przewalski +précis +précised +précises +précising +príncipe +ps +psalm +psalmbook +psalmbooks +psalmed +psalming +psalmist +psalmists +psalmodies +psalmodist +psalmodists +psalmody +psalms +psalter +psalteria +psalterial +psalteries +psalterium +psalters +psaltery +psaltries +psaltry +psephological +psephologist +psephologists +psephology +pseudaxis +pseudaxises +pseudepigraph +pseudepigrapha +pseudepigraphal +pseudepigraphic +pseudepigraphical +pseudepigraphon +pseudepigraphous +pseudepigraphs +pseudepigraphy +pseudo +pseudoallele +pseudoalleles +pseudobulb +pseudobulbs +pseudocarp +pseudocarpous +pseudocarps +pseudocholinesterase +pseudocholinesterases +pseudoclassic +pseudoclassicism +pseudoclassics +pseudocoel +pseudocoelom +pseudocoelomate +pseudocoelomates +pseudocoeloms +pseudocoels +pseudocyesis +pseudogene +pseudogenes +pseudohermaphrodite +pseudohermaphrodites +pseudohermaphroditic +pseudohermaphroditism +pseudomonad +pseudomonades +pseudomonads +pseudomonas +pseudomorph +pseudomorphic +pseudomorphism +pseudomorphous +pseudomorphs +pseudonym +pseudonymity +pseudonymous +pseudonymously +pseudonymousness +pseudonyms +pseudoparenchyma +pseudoparenchymatous +pseudopod +pseudopodal +pseudopodia +pseudopodial +pseudopodium +pseudopods +pseudopregnancies +pseudopregnancy +pseudopregnant +pseudorandom +pseudoscience +pseudoscientific +pseudoscientist +pseudoscientists +pseudoscorpion +pseudoscorpions +pseudosophisticated +pseudosophistication +pseudotuberculosis +pshaw +psi +psilocin +psilocins +psilocybin +psilomelane +psilomelanes +psilophyte +psilophytes +psilophytic +psittacine +psittacoses +psittacosis +psittacotic +psoas +psoases +psocid +psocids +psoralen +psoralens +psoriases +psoriasis +psoriatic +psych +psychasthenia +psychasthenias +psychasthenic +psyche +psyched +psychedelia +psychedelias +psychedelic +psychedelically +psychedelics +psyches +psychiatric +psychiatrical +psychiatrically +psychiatrist +psychiatrists +psychiatry +psychic +psychical +psychically +psychics +psyching +psycho +psychoacoustic +psychoacoustical +psychoacoustics +psychoactive +psychoanalyses +psychoanalysis +psychoanalyst +psychoanalysts +psychoanalytic +psychoanalytical +psychoanalytically +psychoanalyze +psychoanalyzed +psychoanalyzes +psychoanalyzing +psychobabble +psychobabbler +psychobabblers +psychobabbles +psychobiographer +psychobiographers +psychobiographic +psychobiographical +psychobiographies +psychobiography +psychobiologic +psychobiological +psychobiologically +psychobiologist +psychobiologists +psychobiology +psychochemical +psychochemicals +psychodrama +psychodramas +psychodramatic +psychodynamic +psychodynamically +psychodynamics +psychogenesis +psychogenetic +psychogenetically +psychogenic +psychogenically +psychograph +psychographic +psychographics +psychographs +psychohistorian +psychohistorians +psychohistorical +psychohistories +psychohistory +psychokineses +psychokinesis +psychokinetic +psychokinetically +psycholinguist +psycholinguistic +psycholinguistics +psycholinguists +psychologic +psychological +psychologically +psychologies +psychologism +psychologist +psychologists +psychologize +psychologized +psychologizes +psychologizing +psychology +psychometric +psychometrical +psychometrically +psychometrician +psychometricians +psychometrics +psychometrist +psychometrists +psychometry +psychomotor +psychoneuroses +psychoneurosis +psychoneurotic +psychoneurotics +psychopath +psychopathic +psychopathically +psychopathologic +psychopathological +psychopathologically +psychopathologist +psychopathologists +psychopathology +psychopaths +psychopathy +psychopharmacologic +psychopharmacological +psychopharmacologist +psychopharmacologists +psychopharmacology +psychophysical +psychophysically +psychophysicist +psychophysicists +psychophysics +psychophysiologic +psychophysiological +psychophysiologically +psychophysiologist +psychophysiologists +psychophysiology +psychos +psychoses +psychosexual +psychosexuality +psychosexually +psychosis +psychosocial +psychosocially +psychosomatic +psychosomatically +psychosomatics +psychosurgeon +psychosurgeons +psychosurgeries +psychosurgery +psychosurgical +psychosynthesis +psychotechnical +psychotechnician +psychotechnicians +psychotechnics +psychotherapeutic +psychotherapeutically +psychotherapeutics +psychotherapies +psychotherapist +psychotherapists +psychotherapy +psychotic +psychotically +psychotics +psychotomimetic +psychotomimetically +psychotomimetics +psychotropic +psychotropics +psychrometer +psychrometers +psychrometric +psychrometry +psychrophile +psychrophiles +psychrophilic +psylla +psyllas +psyllid +psyllids +psyllium +psylliums +psywar +psywars +pt +pta +ptarmigan +ptarmigans +ptas +pteranodon +pteranodons +pteridine +pteridines +pteridological +pteridologist +pteridologists +pteridology +pteridophyte +pteridophytes +pteridophytic +pteridophytous +pteridosperm +pteridosperms +pterin +pterins +pterodactyl +pterodactyloid +pterodactylous +pterodactyls +pteropod +pteropodan +pteropodans +pteropods +pterosaur +pterosaurs +pteroylglutamic +pterygia +pterygial +pterygium +pterygiums +pterygoid +pterygoids +pteryla +pterylae +ptisan +ptisans +ptolemaic +ptolemaist +ptolemaists +ptolemies +ptolemy +ptomaine +ptoses +ptosis +ptotic +ptyalin +ptyalism +ptyalisms +pub +puberal +pubertal +puberty +puberulent +puberulous +pubes +pubescence +pubescent +pubic +pubis +public +publica +publically +publican +publicans +publication +publications +publicist +publicists +publicity +publicize +publicized +publicizes +publicizing +publicly +publicness +publico +publics +publish +publishable +published +publisher +publishers +publishes +publishing +pubs +puccini +puccoon +puccoons +puce +puck +pucka +pucker +puckered +puckering +puckers +puckery +puckish +puckishly +puckishness +pucks +pudding +puddings +puddingstone +puddingstones +puddle +puddled +puddler +puddlers +puddles +puddling +puddlings +puddly +pudency +pudenda +pudendal +pudendum +pudgier +pudgiest +pudginess +pudgy +pudibund +pueblo +pueblos +puerile +puerilely +puerileness +puerilism +puerilisms +puerilities +puerility +puerperal +puerperia +puerperium +puerto +puff +puffball +puffballs +puffed +puffer +puffers +puffery +puffier +puffiest +puffily +puffin +puffiness +puffing +puffins +puffs +puffy +pug +pugaree +pugarees +puget +puggaree +puggarees +pugged +pugging +puggree +puggrees +pugil +pugilism +pugilist +pugilistic +pugilists +pugmark +pugmarks +pugnacious +pugnaciously +pugnaciousness +pugnacity +pugs +puisne +puisnes +puissance +puissant +puissantly +puke +puked +pukes +puking +pukka +pul +pula +pulas +pulaski +pulchritude +pulchritudinous +pule +puled +puler +pulers +pules +puli +pulik +puling +pulis +pulitzer +pull +pullback +pullbacks +pulled +puller +pullers +pullet +pullets +pulley +pulleys +pulling +pullman +pullmans +pullorum +pullout +pullouts +pullover +pullovers +pulls +pullulate +pullulated +pullulates +pullulating +pullulation +pullulations +pullulative +pulmonale +pulmonalia +pulmonary +pulmonate +pulmonates +pulmonic +pulmotor +pulmotors +pulp +pulpal +pulpally +pulped +pulper +pulpers +pulpier +pulpiest +pulpiness +pulping +pulpit +pulpits +pulpous +pulps +pulpwood +pulpy +pulque +pulques +puls +pulsant +pulsar +pulsars +pulsate +pulsated +pulsates +pulsatile +pulsating +pulsation +pulsations +pulsator +pulsators +pulsatory +pulse +pulsed +pulsejet +pulsejets +pulser +pulsers +pulses +pulsing +pulsometer +pulsometers +pulverable +pulverizable +pulverization +pulverizations +pulverizator +pulverizators +pulverize +pulverized +pulverizer +pulverizers +pulverizes +pulverizing +pulverous +pulverulent +pulvilli +pulvillus +pulvinate +pulvinated +pulvini +pulvinus +puma +pumas +pumelo +pumelos +pumice +pumiced +pumiceous +pumicer +pumicers +pumices +pumicing +pumicite +pumicites +pummel +pummeled +pummeling +pummelled +pummelling +pummelo +pummelos +pummels +pump +pumped +pumper +pumpernickel +pumpernickels +pumpers +pumping +pumpkin +pumpkins +pumpkinseed +pumpkinseeds +pumps +pun +puna +punch +punchball +punchboard +punchboards +punchbowl +punchbowls +punched +puncheon +puncheons +puncher +punchers +punches +punchier +punchiest +punchily +punchinello +punchinelloes +punchinellos +punchiness +punching +punchless +punchy +punctate +punctated +punctation +punctations +punctilio +punctilios +punctilious +punctiliously +punctiliousness +punctual +punctuality +punctually +punctualness +punctuate +punctuated +punctuates +punctuating +punctuation +punctuations +punctuative +punctuator +punctuators +puncturable +puncture +punctured +punctures +puncturing +pundit +punditry +pundits +pung +pungency +pungent +pungently +pungle +pungled +pungles +pungling +pungs +punic +punier +puniest +punily +puniness +punish +punishability +punishable +punishably +punished +punisher +punishers +punishes +punishing +punishment +punishments +punition +punitions +punitive +punitively +punitiveness +punitory +punjab +punjabi +punjabis +punji +punk +punka +punkah +punkahs +punkas +punker +punkers +punkie +punkier +punkies +punkiest +punkin +punkiness +punkins +punkish +punks +punky +punned +punnet +punnets +punnier +punniest +punning +punningly +punny +puns +punster +punsters +punt +punted +punter +punters +punties +punting +punts +punty +punxsutawney +puny +pup +pupa +pupae +pupal +puparia +puparium +pupas +pupate +pupated +pupates +pupating +pupation +pupations +pupfish +pupfishes +pupil +pupilage +pupilages +pupilar +pupillage +pupillages +pupillary +pupils +pupiparous +pupped +puppet +puppeteer +puppeteers +puppetlike +puppetries +puppetry +puppets +puppies +pupping +puppis +puppy +puppyhood +puppyish +puppylike +pups +purana +puranas +puranic +purblind +purblindly +purblindness +purcell +purchasability +purchasable +purchase +purchased +purchaser +purchasers +purchases +purchasing +purdah +purdahs +pure +pureblood +pureblooded +purebloods +purebred +purebreds +puree +pureed +pureeing +purees +purely +pureness +purer +purest +purfle +purfled +purfles +purfling +purgation +purgations +purgative +purgatives +purgatorial +purgatories +purgatory +purge +purgeable +purged +purger +purgers +purges +purging +puri +purification +purifications +purificator +purificators +purificatory +purified +purifier +purifiers +purifies +purify +purifying +purim +purine +purines +puris +purism +purisms +purist +puristic +puristically +purists +puritan +puritanical +puritanically +puritanicalness +puritanism +puritans +purity +purkinje +purl +purled +purlieu +purlieus +purlin +purline +purlines +purling +purlins +purloin +purloined +purloiner +purloiners +purloining +purloins +purls +puromycin +puromycins +purple +purpled +purpleheart +purplehearts +purpler +purples +purplest +purpling +purplish +purply +purport +purported +purportedly +purporting +purports +purpose +purposed +purposeful +purposefully +purposefulness +purposeless +purposelessly +purposelessness +purposely +purposes +purposing +purposive +purposively +purposiveness +purpura +purpuras +purpure +purpures +purpuric +purpurin +purpurins +purr +purred +purring +purringly +purrs +purse +pursed +purselike +purser +pursers +purses +pursestrings +pursier +pursiest +pursiness +pursing +purslane +pursuable +pursuance +pursuant +pursue +pursued +pursuer +pursuers +pursues +pursuing +pursuit +pursuits +pursuivant +pursuivants +pursy +purtenance +purtenances +purty +purulence +purulent +purulently +purvey +purveyance +purveyed +purveying +purveyor +purveyors +purveys +purview +purviews +purée +puréed +puréeing +purées +puréing +pus +pusey +puseyism +puseyite +puseyites +push +pushback +pushbacks +pushball +pushballs +pushbutton +pushbuttons +pushcart +pushcarts +pushchair +pushchairs +pushdown +pushdowns +pushed +pusher +pushers +pushes +pushful +pushfulness +pushier +pushiest +pushily +pushiness +pushing +pushingly +pushkin +pushover +pushovers +pushpin +pushpins +pushrod +pushrods +pushtu +pushtun +pushtuns +pushup +pushups +pushy +pusillanimity +pusillanimous +pusillanimously +puss +pusses +pussier +pussies +pussiest +pussley +pussy +pussycat +pussycats +pussyfoot +pussyfooted +pussyfooter +pussyfooters +pussyfooting +pussyfoots +pussytoes +pustulant +pustulants +pustular +pustulate +pustulated +pustulates +pustulating +pustulation +pustulations +pustule +pustules +put +putamen +putamina +putaminous +putative +putatively +putdown +putdownable +putdowns +putlog +putlogs +putnam +putoff +putoffs +putonghua +putout +putouts +putrefacient +putrefaction +putrefactive +putrefied +putrefies +putrefy +putrefying +putrescence +putrescent +putrescible +putrescine +putrescines +putrid +putridity +putridly +putridness +puts +putsch +putsches +putschist +putschists +putt +putted +puttee +puttees +putter +puttered +putterer +putterers +puttering +putters +putti +puttied +putties +putting +puttingly +putto +puttrefied +puttrefies +puttrefying +putts +putty +puttying +puttyless +puttylike +puttyroot +puttyroots +putz +putzed +putzes +putzing +puzzle +puzzled +puzzleheaded +puzzleheadedness +puzzlement +puzzler +puzzlers +puzzles +puzzling +puzzlingly +pvc +pycnidia +pycnidial +pycnidium +pycnogonid +pycnogonids +pycnometer +pycnometers +pyelitic +pyelitis +pyelitises +pyelogram +pyelograms +pyelographic +pyelography +pyelonephritic +pyelonephritis +pyelonephritises +pyemia +pyemic +pygidia +pygidial +pygidium +pygmaean +pygmalion +pygmean +pygmies +pygmoid +pygmy +pyknic +pyknics +pylon +pylons +pylori +pyloric +pylorus +pylos +pyoderma +pyodermas +pyodermic +pyogenesis +pyogenic +pyoid +pyongyang +pyorrhea +pyorrheal +pyorrheas +pyorrhoea +pyorrhoeas +pyosis +pyracantha +pyracanthas +pyralid +pyralidid +pyralidids +pyralids +pyramid +pyramidal +pyramidally +pyramided +pyramidic +pyramidical +pyramiding +pyramids +pyramus +pyran +pyrans +pyrargyrite +pyrargyrites +pyre +pyrene +pyrenean +pyrenees +pyrenes +pyrenoid +pyrenoids +pyres +pyrethrin +pyrethrins +pyrethroid +pyrethroids +pyrethrum +pyrethrums +pyretic +pyrex +pyrexia +pyrexial +pyrexias +pyrexic +pyrheliometer +pyrheliometers +pyrheliometric +pyric +pyridic +pyridine +pyridines +pyridoxal +pyridoxals +pyridoxamine +pyridoxamines +pyridoxin +pyridoxine +pyridoxines +pyridoxins +pyriform +pyrimethamine +pyrimethamines +pyrimidine +pyrimidines +pyrite +pyrites +pyritic +pyritical +pyrocellulose +pyrocelluloses +pyrochemical +pyrochemically +pyroclastic +pyroelectric +pyroelectricity +pyroelectrics +pyrogallic +pyrogallol +pyrogallols +pyrogen +pyrogenic +pyrogenicity +pyrogenous +pyrogens +pyrograph +pyrographer +pyrographers +pyrographic +pyrographies +pyrographs +pyrography +pyroligneous +pyrolusite +pyrolusites +pyrolysis +pyrolytic +pyrolytically +pyrolyze +pyrolyzed +pyrolyzes +pyrolyzing +pyromancy +pyromania +pyromaniac +pyromaniacal +pyromaniacs +pyromantic +pyrometallurgical +pyrometallurgies +pyrometallurgy +pyrometer +pyrometers +pyrometric +pyrometrical +pyrometrically +pyrometry +pyromorphite +pyromorphites +pyronine +pyronines +pyrope +pyropes +pyrophoric +pyrophosphate +pyrophosphates +pyrophosphatic +pyrophosphoric +pyrophyllite +pyrophyllites +pyrosis +pyrostat +pyrostats +pyrosulfate +pyrosulfates +pyrosulfuric +pyrotechnic +pyrotechnical +pyrotechnically +pyrotechnics +pyrotechnist +pyrotechnists +pyrotechny +pyroxene +pyroxenes +pyroxenic +pyroxenite +pyroxenites +pyroxenitic +pyroxenoid +pyroxenoids +pyroxylin +pyroxyline +pyroxylines +pyroxylins +pyrrhic +pyrrhics +pyrrhonism +pyrrhonist +pyrrhonists +pyrrhotine +pyrrhotines +pyrrhotite +pyrrhotites +pyrrhuloxia +pyrrhuloxias +pyrrhus +pyrrole +pyrroles +pyrrolic +pyruvate +pyruvates +pyruvic +pythagoras +pythagorean +pythagoreanism +pythagoreans +pythiad +pythiads +pythian +pythias +pythic +python +pythoness +pythonesses +pythonic +pythons +pyuria +pyurias +pyx +pyxes +pyxides +pyxidia +pyxidium +pyxie +pyxies +pyxis +páros +pátmos +pâte +pâté +pâtés +pépin +périgord +pétanque +père +q +qantas +qatar +qatari +qataris +qattara +qed +qilian +qindarka +qindarkas +qindars +qinghai +qintar +qintars +qiviut +qiviuts +qoph +qophs +qt +qty +qua +quaalude +quaaludes +quack +quacked +quackery +quacking +quackish +quackishly +quacks +quacksalver +quacksalvers +quacky +quad +quadded +quadding +quadragenarian +quadragesima +quadragesimal +quadrangle +quadrangles +quadrangular +quadrangularly +quadrangularness +quadrant +quadrantal +quadrantid +quadrants +quadraphonic +quadraphonically +quadraphonics +quadraphony +quadrasonic +quadrat +quadrate +quadrated +quadrates +quadratic +quadratically +quadratics +quadrating +quadrats +quadrature +quadratures +quadrennia +quadrennial +quadrennially +quadrennials +quadrennium +quadrenniums +quadric +quadricentennial +quadricentennials +quadriceps +quadricipital +quadrics +quadrifid +quadriga +quadrigae +quadrilateral +quadrilaterals +quadrille +quadrilles +quadrillion +quadrillions +quadrillionth +quadrillionths +quadrinomial +quadripartite +quadriphonic +quadriphonics +quadriphony +quadriplegia +quadriplegic +quadriplegics +quadrisect +quadrivalence +quadrivalency +quadrivalent +quadrivia +quadrivial +quadrivium +quadroon +quadroons +quadrophonic +quadrumanal +quadrumanous +quadrumvir +quadrumvirate +quadrumvirates +quadrumvirs +quadruped +quadrupedal +quadrupeds +quadruple +quadrupled +quadruples +quadruplet +quadruplets +quadruplicate +quadruplicated +quadruplicately +quadruplicates +quadruplicating +quadruplication +quadruplications +quadruplicity +quadrupling +quadruply +quadrupole +quadrupoles +quads +quaere +quaeres +quaestor +quaestorial +quaestors +quaestorship +quaestorships +quaff +quaffed +quaffer +quaffers +quaffing +quaffs +quag +quagga +quaggas +quaggier +quaggiest +quaggy +quagmire +quagmires +quags +quahaug +quahaugs +quahog +quahogs +quai +quaich +quaiches +quaigh +quaighs +quail +quailed +quailing +quails +quaint +quainter +quaintest +quaintly +quaintness +quake +quaked +quakeproof +quakeproofed +quakeproofing +quakeproofs +quaker +quakerish +quakerism +quakerly +quakers +quakes +quaking +quaky +quale +qualia +qualifiable +qualification +qualifications +qualificatory +qualified +qualifiedly +qualifier +qualifiers +qualifies +qualify +qualifying +qualitative +qualitatively +qualities +quality +qualm +qualmish +qualmishly +qualmishness +qualms +qualmy +quamash +quamashes +quandang +quandangs +quandaries +quandary +quandong +quandongs +quango +quangos +quant +quanta +quantal +quantally +quantasome +quantasomes +quanted +quantic +quantics +quantifiability +quantifiable +quantifiably +quantification +quantificational +quantificationally +quantifications +quantified +quantifier +quantifiers +quantifies +quantify +quantifying +quanting +quantitate +quantitated +quantitates +quantitating +quantitation +quantitations +quantitative +quantitatively +quantitativeness +quantities +quantity +quantization +quantizations +quantize +quantized +quantizer +quantizers +quantizes +quantizing +quants +quantum +quapaw +quapaws +quarantinable +quarantine +quarantined +quarantines +quarantining +quark +quarks +quarrel +quarreled +quarreler +quarrelers +quarreling +quarrelled +quarreller +quarrellers +quarrelling +quarrels +quarrelsome +quarrelsomely +quarrelsomeness +quarried +quarrier +quarriers +quarries +quarry +quarrying +quarryman +quarrymen +quart +quartan +quartans +quarter +quarterage +quarterages +quarterback +quarterbacked +quarterbacking +quarterbacks +quarterdeck +quarterdecks +quartered +quarterfinal +quarterfinalist +quarterfinalists +quarterfinals +quartering +quarterlies +quarterly +quartermaster +quartermasters +quartern +quarterns +quarters +quartersaw +quartersawed +quartersawing +quartersawn +quartersaws +quarterstaff +quarterstaves +quartertone +quartertones +quartet +quartets +quartette +quartettes +quartic +quartics +quartile +quartiles +quarto +quartos +quarts +quartz +quartzes +quartziferous +quartzite +quartzitic +quartzose +quasar +quasars +quash +quashed +quashes +quashing +quasi +quasiliquid +quasimodo +quasiparticle +quasiparticles +quasiperiodic +quasiperiodicity +quassia +quassias +quatercentenaries +quatercentenary +quaternaries +quaternary +quaternion +quaternions +quaternities +quaternity +quatorze +quatrain +quatrains +quatre +quatrefoil +quatrefoils +quattrocento +quattrocentos +quattuordecillion +quattuordecillions +quaver +quavered +quavering +quaveringly +quavers +quavery +quay +quayage +quayages +quays +quayside +quaysides +quean +queans +queasier +queasiest +queasily +queasiness +queasy +queazier +queaziest +queazy +quebec +quebecer +quebecers +quebecker +quebeckers +quebecois +quebracho +quebrachos +quechan +quechua +quechuan +quechuas +quechumaran +quechumarans +queen +queen's +queened +queening +queenlier +queenliest +queenliness +queenly +queens +queensberry +queenship +queenships +queenside +queensides +queensland +queer +queered +queerer +queerest +queering +queerish +queerly +queerness +queers +queleas +quell +quelled +queller +quellers +quelling +quells +quem +quench +quenchable +quenched +quencher +quenchers +quenches +quenching +quenchless +quenelle +quenelles +quercetin +quercetins +quercitron +quercitrons +queried +querier +queriers +queries +querist +querists +quern +querns +querulous +querulously +querulousness +query +querying +quesadilla +quesadillas +quest +quested +quester +questers +questing +question +questionability +questionable +questionableness +questionably +questionaries +questionary +questioned +questioner +questioners +questioning +questioningly +questionings +questionless +questionnaire +questionnaires +questions +questor +questors +quests +quetzal +quetzalcoatl +quetzales +quetzals +queue +queued +queueing +queuer +queuers +queues +queuing +quibble +quibbled +quibbler +quibblers +quibbles +quibbling +quiberon +quiche +quiches +quiché +quichés +quick +quicken +quickened +quickener +quickeners +quickening +quickens +quicker +quickest +quickie +quickies +quicklime +quickly +quickness +quicks +quicksand +quicksands +quickset +quicksets +quicksilver +quickstep +quickstepped +quickstepping +quicksteps +quid +quiddities +quiddity +quidnunc +quidnuncs +quids +quiescence +quiescent +quiescently +quiet +quieted +quieten +quietened +quietening +quietens +quieter +quietest +quieting +quietism +quietisms +quietist +quietistic +quietists +quietly +quietness +quiets +quietude +quietus +quietuses +quiff +quiffs +quill +quillback +quillbacks +quilled +quiller +quilling +quills +quillwork +quillworks +quillwort +quillworts +quilt +quilted +quilter +quilters +quilting +quilts +quinacrine +quinalizarin +quinalizarins +quinary +quinate +quince +quincentenary +quincentennial +quinces +quincey +quincuncial +quincuncially +quincunx +quincunxes +quincunxial +quincy +quindecennial +quindecennials +quindecillion +quindecillions +quinella +quinellas +quinidine +quinidines +quiniela +quinielas +quinine +quinines +quinnat +quinoa +quinoas +quinoid +quinoidine +quinoidines +quinoids +quinoline +quinolines +quinone +quinones +quinonoid +quinquagenarian +quinquagenarians +quinquagesima +quinquagesimas +quinquennia +quinquennial +quinquennially +quinquennials +quinquennium +quinquenniums +quinquevalence +quinquevalent +quinsy +quint +quinta +quintain +quintains +quintal +quintals +quintan +quintas +quintessence +quintessential +quintessentially +quintet +quintets +quintette +quintettes +quintic +quintics +quintile +quintiles +quintilian +quintillion +quintillions +quintillionth +quintillionths +quints +quintuple +quintupled +quintuples +quintuplet +quintuplets +quintuplicate +quintuplicated +quintuplicates +quintuplicating +quintupling +quintuply +quinze +quip +quipped +quipper +quippers +quipping +quippy +quips +quipster +quipsters +quipu +quipus +quire +quires +quirinal +quirinus +quirk +quirked +quirkier +quirkiest +quirkily +quirkiness +quirking +quirkish +quirks +quirky +quirt +quirts +quisling +quislingism +quislings +quit +quitch +quitclaim +quitclaimed +quitclaiming +quitclaims +quite +quito +quitrent +quitrents +quits +quittance +quittances +quitted +quitter +quitters +quitting +quittor +quittors +quiver +quivered +quivering +quiveringly +quivers +quivery +quixote +quixotes +quixotic +quixotical +quixotically +quixotism +quixotry +quiz +quizmaster +quizmasters +quizzed +quizzer +quizzers +quizzes +quizzical +quizzicality +quizzically +quizzing +quo +quod +quodlibet +quodlibets +quoi +quoin +quoined +quoining +quoins +quoit +quoits +quokka +quokkas +quondam +quonset +quorum +quorums +quos +quota +quotability +quotable +quotably +quotas +quotation +quotational +quotationally +quotations +quote +quoted +quoter +quoters +quotes +quoth +quotha +quotidian +quotient +quotients +quoting +quran +qurush +qurushes +québec +québecois +qwerty +r +ra +rabat +rabato +rabatos +rabats +rabbet +rabbeted +rabbeting +rabbets +rabbi +rabbin +rabbinate +rabbinates +rabbinic +rabbinical +rabbinically +rabbinism +rabbinist +rabbinistic +rabbinists +rabbinitic +rabbins +rabbis +rabbit +rabbitbrush +rabbited +rabbiter +rabbiters +rabbiting +rabbitries +rabbitry +rabbits +rabbity +rabble +rabbled +rabblement +rabblements +rabbler +rabblers +rabbles +rabbling +rabe +rabelais +rabelaisian +rabi +rabia +rabic +rabid +rabidity +rabidly +rabidness +rabies +rabietic +raccoon +raccoons +race +racecar +racecars +racecourse +racecourses +raced +racehorse +racehorses +racemate +racemates +raceme +racemes +racemic +racemiform +racemism +racemization +racemizations +racemize +racemized +racemizes +racemizing +racemose +racemosely +racer +racers +racerunner +racerunners +races +racetrack +racetracker +racetrackers +racetracks +racewalker +racewalkers +racewalking +raceway +raceways +rachel +rachial +rachides +rachilla +rachillae +rachis +rachises +rachitic +rachitis +rachmaninoff +rachmanism +racial +racialism +racialist +racialistic +racialists +racially +racier +raciest +racily +racine +raciness +racing +racism +racist +racists +rack +racked +racker +rackers +racket +racketed +racketeer +racketeered +racketeering +racketeers +racketing +rackets +rackety +rackful +rackfuls +racking +rackingly +racks +raclette +raclettes +raclopride +racon +racons +raconteur +raconteurs +racoon +racoons +racquet +racquetball +racquets +racy +rad +radar +radars +radarscope +radarscopes +raddle +raddled +raddles +raddling +radial +radially +radials +radian +radiance +radiancy +radians +radiant +radiantly +radiants +radiate +radiated +radiately +radiates +radiating +radiation +radiational +radiationless +radiations +radiative +radiator +radiators +radical +radicalism +radicalization +radicalizations +radicalize +radicalized +radicalizes +radicalizing +radically +radicalness +radicals +radicand +radicands +radicchio +radicchios +radices +radicle +radicles +radicular +radii +radio +radioactive +radioactively +radioactivity +radioallergosorbent +radioastronomy +radioautograph +radioautographic +radioautographs +radioautography +radiobiologic +radiobiological +radiobiologically +radiobiologist +radiobiologists +radiobiology +radiobroadcast +radiobroadcasted +radiobroadcaster +radiobroadcasters +radiobroadcasting +radiobroadcasts +radiocarbon +radiocast +radiocasts +radiochemical +radiochemically +radiochemist +radiochemistry +radiochemists +radiochromatogram +radiochromatograms +radioecological +radioecologist +radioecologists +radioecology +radioed +radioelement +radioelements +radiogenic +radiogram +radiograms +radiograph +radiographed +radiographer +radiographers +radiographic +radiographically +radiographing +radiographs +radiography +radioimmunoassay +radioimmunoassayable +radioimmunological +radioimmunology +radioing +radioiodine +radioiodines +radioisotope +radioisotopes +radioisotopic +radioisotopically +radiolabel +radiolabeled +radiolabeling +radiolabelled +radiolabelling +radiolabels +radiolarian +radiolarians +radiolocation +radiologic +radiological +radiologically +radiologist +radiologists +radiology +radiolucency +radiolucent +radiolyses +radiolysis +radiolytic +radioman +radiomen +radiometer +radiometers +radiometric +radiometrically +radiometry +radiomimetic +radionuclide +radionuclides +radiopacity +radiopaque +radiopharmaceutical +radiopharmaceuticals +radiophone +radiophones +radiophonic +radiophoto +radiophotograph +radiophotographs +radiophotography +radiophotos +radioprotection +radioprotections +radioprotective +radios +radioscopic +radioscopical +radioscopy +radiosensitive +radiosensitivity +radiosonde +radiosondes +radiostrontium +radiotelegraph +radiotelegraphic +radiotelegraphs +radiotelegraphy +radiotelemetric +radiotelemetry +radiotelephone +radiotelephones +radiotelephonic +radiotelephony +radiotherapies +radiotherapist +radiotherapists +radiotherapy +radiothorium +radiotoxic +radiotoxicity +radiotracer +radiotracers +radish +radishes +radium +radius +radiuses +radix +radixes +radome +radomes +radon +rads +radula +radulae +radular +radwaste +raeburn +raff +raffia +raffias +raffinate +raffinates +raffinose +raffinoses +raffish +raffishly +raffishness +raffle +raffled +raffler +rafflers +raffles +rafflesia +rafflesias +raffling +raft +rafted +rafter +raftered +rafters +rafting +rafts +raftsman +raftsmen +rag +raga +ragamuffin +ragamuffins +ragas +ragbag +ragbags +rage +raged +rages +ragged +raggedier +raggediest +raggedly +raggedness +raggedy +ragging +raggle +ragi +raging +ragis +raglan +raglans +ragman +ragmen +ragnarok +ragout +ragouts +ragpicker +ragpickers +rags +ragtag +ragtime +ragtop +ragtops +ragusa +ragweed +ragwort +ragworts +rah +raiatea +raid +raided +raider +raiders +raiding +raids +rail +railbird +railbirds +railbus +railcar +railcars +railed +railer +railers +railhead +railheads +railing +railings +railleries +raillery +railroad +railroaded +railroader +railroaders +railroading +railroadings +railroads +rails +railway +railways +raiment +rain +rainbird +rainbirds +rainbow +rainbowlike +rainbows +raincoat +raincoats +raindrop +raindrops +rained +rainfall +rainfalls +rainforest +rainforests +rainier +rainiest +raininess +raining +rainless +rainmaker +rainmakers +rainmaking +rainout +rainouts +rainproof +rains +rainspout +rainspouts +rainsquall +rainsqualls +rainstorm +rainstorms +rainwash +rainwater +rainwear +rainy +raise +raised +raiser +raisers +raises +raisin +raising +raisingly +raisings +raisins +raison +raisonné +raisonnés +raisons +raj +raja +rajab +rajabs +rajah +rajahs +rajas +rajasthan +rajasthani +rajpoot +rajpoots +rajput +rajputana +rajputs +rajs +rake +raked +rakee +rakees +rakehell +rakehells +rakehelly +raker +rakers +rakes +raki +raking +rakis +rakish +rakishly +rakishness +rale +raleigh +rales +ralik +rallentando +rallentandos +rallied +rallies +ralliform +rally +rallye +rallyes +rallying +ralph +ralphed +ralphing +ralphs +ram +rama +ramada +ramadan +ramadas +ramadhan +ramakrishna +raman +ramate +ramayana +ramble +rambled +rambler +ramblers +rambles +rambling +ramblingly +ramblings +rambo +rambos +rambouillet +rambouillets +rambunctious +rambunctiously +rambunctiousness +rambutan +rambutans +ramekin +ramekins +ramequin +ramequins +rameses +ramet +ramets +rami +ramie +ramification +ramifications +ramified +ramifies +ramiform +ramify +ramifying +ramillies +ramism +ramist +ramists +ramjet +ramjets +rammed +rammer +rammers +ramming +ramona +ramonas +ramose +ramous +ramp +rampage +rampaged +rampageous +rampageously +rampageousness +rampager +rampagers +rampages +rampaging +rampancy +rampant +rampantly +rampart +ramparted +ramparting +ramparts +ramped +rampike +rampikes +ramping +rampion +rampions +ramps +ramrod +ramrodded +ramrodding +ramrods +rams +ramses +ramshackle +ramshorn +ramshorns +ramson +ramsons +ramtil +ramtilla +ramtillas +ramtils +ramulose +ramus +ran +ranch +ranched +rancher +rancheria +rancherias +ranchero +rancheros +ranchers +ranches +ranching +ranchman +ranchmen +rancho +ranchos +rancid +rancidity +rancidness +rancor +rancorous +rancorously +rancorousness +rancors +rand +randan +randans +randier +randiest +random +randomization +randomizations +randomize +randomized +randomizer +randomizers +randomizes +randomizing +randomly +randomness +rands +randy +ranee +ranees +rang +range +ranged +rangefinder +rangefinders +rangeland +rangelands +ranger +rangers +ranges +rangier +rangiest +ranginess +ranging +rangoon +rangy +rani +ranid +ranids +ranis +rank +ranked +ranker +rankers +rankest +rankine +ranking +rankings +rankle +rankled +rankles +rankling +rankly +rankness +ranks +ransack +ransacked +ransacker +ransackers +ransacking +ransacks +ransom +ransomed +ransomer +ransomers +ransoming +ransoms +rant +ranted +ranter +ranters +ranting +rantingly +rantings +rants +ranula +ranulas +ranunculi +ranunculus +ranunculuses +rap +rapacious +rapaciously +rapaciousness +rapacity +rapallo +rape +raped +raper +rapers +rapes +rapeseed +rapeseeds +raphae +raphael +raphaelesque +raphaelite +raphaelites +raphaelitism +raphe +raphia +raphias +raphide +raphides +raphis +rapid +rapider +rapidest +rapidity +rapidly +rapidness +rapids +rapier +rapierlike +rapiers +rapine +rapines +raping +rapini +rapist +rapists +rapparee +rapparees +rapped +rappee +rappees +rappel +rappelled +rappelling +rappels +rappen +rapper +rappers +rapping +rappini +rapport +rapporteur +rapporteurs +rapprochement +rapprochements +raps +rapscallion +rapscallions +rapt +raptly +raptness +raptor +raptorial +raptors +rapture +raptured +raptures +rapturing +rapturous +rapturously +rapturousness +rara +rarae +rare +rarebit +rarebits +raree +rarefaction +rarefactional +rarefactions +rarefactive +rarefiable +rarefication +rarefied +rarefies +rarefy +rarefying +rarely +rareness +rarer +rareripe +rareripes +rarest +rarified +rarifies +rarify +rarifying +raring +rarities +rarity +rarotonga +rasa +rasae +rasbora +rasboras +rascal +rascalities +rascality +rascally +rascals +rase +rased +rases +rash +rasher +rashers +rashes +rashest +rashly +rashness +rasing +rasorial +rasp +raspberries +raspberry +rasped +rasper +raspers +raspier +raspiest +rasping +raspingly +rasps +rasputin +raspy +rasselas +rasta +rastafarian +rastafarianism +rastafarians +rastas +raster +rasters +rat +rata +ratability +ratable +ratableness +ratables +ratably +ratafee +ratafees +ratafia +ratafias +ratak +rataplan +rataplans +ratatouille +ratatouilles +ratbag +ratbags +ratchet +ratcheted +ratcheting +ratchets +rate +rateable +rated +ratel +ratels +ratemaking +ratemakings +ratemeter +ratemeters +ratepayer +ratepayers +rater +raters +rates +ratfink +ratfinks +ratfish +ratfishes +rathe +rather +rathskeller +rathskellers +raticide +raticides +ratifiable +ratification +ratifications +ratified +ratifier +ratifiers +ratifies +ratify +ratifying +ratine +ratines +rating +ratings +ratiné +ratio +ratiocinate +ratiocinated +ratiocinates +ratiocinating +ratiocination +ratiocinations +ratiocinative +ratiocinator +ratiocinators +ration +rational +rationale +rationales +rationalism +rationalist +rationalistic +rationalistically +rationalists +rationalities +rationality +rationalizable +rationalization +rationalizations +rationalize +rationalized +rationalizer +rationalizers +rationalizes +rationalizing +rationally +rationalness +rationed +rationing +rations +ratios +ratite +ratites +ratlike +ratlin +ratline +ratlines +ratlins +ratoon +ratooned +ratooning +ratoons +rats +ratsbane +ratsbanes +rattail +rattails +rattan +rattans +ratted +ratteen +ratteens +ratter +ratters +rattier +rattiest +ratting +rattle +rattlebox +rattleboxes +rattlebrain +rattlebrained +rattlebrains +rattled +rattler +rattlers +rattles +rattlesnake +rattlesnakes +rattletrap +rattletraps +rattling +rattlingly +rattly +rattoon +rattooned +rattooning +rattoons +rattrap +rattraps +ratty +raucity +raucous +raucously +raucousness +raunch +raunchier +raunchiest +raunchily +raunchiness +raunchy +rauwolfia +rauwolfias +ravage +ravaged +ravagement +ravagements +ravager +ravagers +ravages +ravaging +rave +raved +ravel +raveled +raveler +ravelers +raveling +ravelings +ravelled +ravelling +ravellings +ravello +ravelment +ravelments +ravels +raven +ravened +ravener +raveners +ravening +raveningly +ravenings +ravenna +ravenous +ravenously +ravenousness +ravens +raver +ravers +raves +ravigote +ravigotes +ravigotte +ravigottes +ravin +ravine +ravined +ravines +raving +ravingly +ravings +ravins +ravioli +raviolis +ravish +ravished +ravisher +ravishers +ravishes +ravishing +ravishingly +ravishment +ravishments +raw +rawalpindi +rawboned +rawer +rawest +rawhide +rawhided +rawhides +rawhiding +rawinsonde +rawinsondes +rawly +rawness +ray +rayed +raying +rayleigh +rayless +raylessness +raynaud +rayon +rayonism +rayonist +rayonistic +rayonists +rays +raze +razed +razee +razees +razer +razers +razes +razing +razor +razorback +razorbacks +razorbill +razorbills +razorblade +razorblades +razors +razz +razzed +razzes +razzing +razzle +razzmatazz +rca +rd +re +rea +reabsorb +reabsorbed +reabsorbing +reabsorbs +reabsorption +reabsorptions +reaccelerate +reaccelerated +reaccelerates +reaccelerating +reaccept +reaccepted +reaccepting +reaccepts +reaccession +reaccessioned +reaccessioning +reaccessions +reacclimatize +reacclimatized +reacclimatizes +reacclimatizing +reaccredit +reaccreditation +reaccreditations +reaccredited +reaccrediting +reaccredits +reach +reachable +reached +reacher +reachers +reaches +reaching +reacquaint +reacquainted +reacquainting +reacquaints +reacquire +reacquired +reacquires +reacquiring +reacquisition +reacquisitions +react +reactance +reactant +reactants +reacted +reacting +reaction +reactionaries +reactionary +reactionaryism +reactions +reactivate +reactivated +reactivates +reactivating +reactivation +reactivations +reactive +reactively +reactiveness +reactivity +reactor +reactors +reacts +read +readability +readable +readableness +readably +readapt +readapted +readapting +readapts +readdress +readdressed +readdresses +readdressing +reader +readerly +readers +readership +readerships +readied +readier +readies +readiest +readily +readiness +reading +readings +readjust +readjusted +readjuster +readjusters +readjusting +readjustment +readjustments +readjusts +readmission +readmissions +readmit +readmits +readmitted +readmitting +readopt +readopted +readopting +readopts +readout +readouts +reads +ready +readying +readymade +reaffirm +reaffirmation +reaffirmations +reaffirmed +reaffirming +reaffirms +reaffix +reaffixed +reaffixes +reaffixing +reagent +reagents +reaggregate +reaggregated +reaggregates +reaggregating +reaggregation +reaggregations +reagin +reaginic +reaginically +reagins +real +realer +reales +realest +realgar +realgars +realia +realign +realigned +realigning +realignment +realignments +realigns +realism +realist +realistic +realistically +realists +realities +reality +realizability +realizable +realizably +realization +realizationism +realizationist +realizationists +realizations +realize +realized +realizer +realizers +realizes +realizing +reallocate +reallocated +reallocates +reallocating +reallocation +reallocations +really +realm +realms +realness +realpolitik +realpolitiker +realpolitikers +realpolitiks +reals +realties +realtor +realtors +realty +ream +reamed +reamer +reamers +reaming +reams +reanalyses +reanalysis +reanalyze +reanalyzed +reanalyzes +reanalyzing +reanimate +reanimated +reanimates +reanimating +reanimation +reanimations +reannex +reannexation +reannexations +reannexed +reannexes +reannexing +reap +reaped +reaper +reapers +reaphook +reaphooks +reaping +reappear +reappearance +reappearances +reappeared +reappearing +reappears +reapplication +reapplications +reapplied +reapplies +reapply +reapplying +reappoint +reappointed +reappointing +reappointment +reappointments +reappoints +reapportion +reapportioned +reapportioning +reapportionment +reapportionments +reapportions +reappraisal +reappraisals +reappraise +reappraised +reappraises +reappraising +reappropriate +reappropriated +reappropriates +reappropriating +reapprove +reapproved +reapproves +reapproving +reaps +rear +reared +rearer +rearers +rearguard +rearguards +reargue +reargued +reargues +rearguing +reargument +rearguments +rearing +rearm +rearmament +rearmaments +rearmed +rearming +rearmost +rearms +rearousal +rearousals +rearouse +rearoused +rearouses +rearousing +rearrange +rearranged +rearrangement +rearrangements +rearranges +rearranging +rearrest +rearrested +rearresting +rearrests +rears +rearticulate +rearticulated +rearticulates +rearticulating +rearview +rearward +rearwards +reascend +reascended +reascending +reascends +reascent +reascents +reason +reasonability +reasonable +reasonableness +reasonably +reasoned +reasoner +reasoners +reasoning +reasonings +reasonless +reasonlessly +reasons +reassemblage +reassemblages +reassemble +reassembled +reassembles +reassemblies +reassembling +reassembly +reassert +reasserted +reasserting +reassertion +reassertions +reasserts +reassess +reassessed +reassesses +reassessing +reassessment +reassessments +reassign +reassigned +reassigning +reassignment +reassignments +reassigns +reassume +reassumed +reassumes +reassuming +reassurance +reassurances +reassure +reassured +reassures +reassuring +reassuringly +reata +reatas +reattach +reattached +reattaches +reattaching +reattachment +reattachments +reattain +reattained +reattaining +reattains +reattempt +reattempted +reattempting +reattempts +reattribute +reattributed +reattributes +reattributing +reattribution +reattributions +reaumur +reauthorization +reauthorizations +reauthorize +reauthorized +reauthorizes +reauthorizing +reave +reaved +reaver +reavers +reaves +reaving +reawake +reawaked +reawaken +reawakened +reawakening +reawakens +reawakes +reawaking +reb +rebait +rebaited +rebaiting +rebaits +rebalance +rebalanced +rebalances +rebalancing +rebaptism +rebaptisms +rebaptize +rebaptized +rebaptizes +rebaptizing +rebar +rebarbative +rebarbatively +rebars +rebate +rebated +rebater +rebaters +rebates +rebating +rebato +rebatos +rebbe +rebbes +rebec +rebecca +rebeck +rebecks +rebecs +rebegan +rebegin +rebeginning +rebegins +rebegun +rebel +rebelled +rebelling +rebellion +rebellions +rebellious +rebelliously +rebelliousness +rebels +rebid +rebidden +rebidding +rebids +rebilling +rebind +rebinding +rebinds +rebirth +rebirths +reblend +reblended +reblending +reblends +reblochon +rebloom +rebloomed +reblooming +reblooms +reboant +reboard +reboarded +reboarding +reboards +reboil +reboiled +reboiling +reboils +rebook +rebooked +rebooking +rebooks +reboot +rebooted +rebooting +reboots +rebore +rebored +rebores +reboring +reborn +rebottle +rebottled +rebottles +rebottling +rebought +rebound +rebounded +rebounder +rebounders +rebounding +rebounds +rebozo +rebozos +rebranch +rebranched +rebranches +rebranching +rebred +rebreed +rebreeding +rebreeds +rebroadcast +rebroadcasted +rebroadcasting +rebroadcasts +rebs +rebuff +rebuffed +rebuffing +rebuffs +rebuild +rebuilding +rebuilds +rebuilt +rebuke +rebuked +rebuker +rebukers +rebukes +rebuking +reburial +reburials +reburied +reburies +rebury +reburying +rebus +rebuses +rebut +rebuts +rebuttable +rebuttal +rebuttals +rebutted +rebutter +rebutters +rebutting +rebuy +rebuying +rebuys +rec +recalcitrance +recalcitrancy +recalcitrant +recalcitrants +recalculate +recalculated +recalculates +recalculating +recalculation +recalculations +recalescence +recalescences +recalescent +recalibrate +recalibrated +recalibrates +recalibrating +recalibration +recalibrations +recall +recallability +recallable +recalled +recaller +recallers +recalling +recalls +recamier +recamiers +recanalization +recanalizations +recanalize +recanalized +recanalizes +recanalizing +recant +recantation +recantations +recanted +recanter +recanters +recanting +recants +recap +recapitalization +recapitalizations +recapitalize +recapitalized +recapitalizes +recapitalizing +recapitulate +recapitulated +recapitulates +recapitulating +recapitulation +recapitulations +recapitulative +recapitulatory +recappable +recapped +recapping +recaps +recapture +recaptured +recaptures +recapturing +recast +recasting +recasts +recce +recces +recd +recede +receded +recedes +receding +receipt +receipted +receipting +receipts +receivable +receivables +receive +received +receiver +receivers +receivership +receiverships +receives +receiving +recency +recension +recensions +recent +recently +recentness +recentralization +recentrifuge +recentrifuged +recentrifuges +recentrifuging +receptacle +receptacles +reception +receptionist +receptionists +receptions +receptive +receptively +receptiveness +receptivity +receptor +receptors +recertification +recertifications +recertified +recertifies +recertify +recertifying +recess +recessed +recesses +recessing +recession +recessional +recessionals +recessionary +recessions +recessive +recessively +recessiveness +recessives +rechallenge +rechallenged +rechallenges +rechallenging +rechannel +rechanneled +rechanneling +rechannels +recharge +rechargeable +recharged +recharger +rechargers +recharges +recharging +recharter +rechartered +rechartering +recharters +recheat +recheats +recheck +rechecked +rechecking +rechecks +recherché +rechoreograph +rechoreographed +rechoreographing +rechoreographs +rechristen +rechristened +rechristening +rechristens +rechromatograph +rechromatography +recidivate +recidivism +recidivist +recidivistic +recidivists +recidivous +recipe +recipes +recipience +recipiency +recipient +recipients +reciprocal +reciprocality +reciprocally +reciprocalness +reciprocals +reciprocate +reciprocated +reciprocates +reciprocating +reciprocation +reciprocations +reciprocative +reciprocator +reciprocators +reciprocities +reciprocity +recirculate +recirculated +recirculates +recirculating +recirculation +recirculations +recision +recisions +recital +recitalist +recitalists +recitals +recitation +recitations +recitative +recitatives +recitativi +recitativo +recitativos +recite +recited +reciter +reciters +recites +reciting +reck +recked +recking +reckless +recklessly +recklessness +reckon +reckoned +reckoner +reckoners +reckoning +reckonings +reckons +recks +reclad +recladding +reclads +reclaim +reclaimable +reclaimant +reclaimants +reclaimed +reclaimer +reclaimers +reclaiming +reclaims +reclamation +reclamations +reclassification +reclassifications +reclassified +reclassifies +reclassify +reclassifying +reclinate +reclination +reclinations +recline +reclined +recliner +recliners +reclines +reclining +reclosable +reclothe +reclothed +reclothes +reclothing +recluse +recluses +reclusion +reclusions +reclusive +reclusively +reclusiveness +recock +recocked +recocking +recocks +recodification +recodifications +recodified +recodifies +recodify +recodifying +recognition +recognitions +recognitive +recognitory +recognizability +recognizable +recognizably +recognizance +recognizances +recognizant +recognize +recognized +recognizer +recognizers +recognizes +recognizing +recoil +recoiled +recoiler +recoilers +recoiling +recoilless +recoils +recoin +recoinage +recoined +recoining +recoins +recollect +recollected +recollecting +recollection +recollections +recollective +recollectively +recollects +recolonization +recolonize +recolonized +recolonizes +recolonizing +recolor +recolored +recoloring +recolors +recombinant +recombinants +recombinase +recombinases +recombination +recombinational +recombinations +recombine +recombined +recombines +recombining +recommence +recommenced +recommencement +recommencements +recommences +recommencing +recommend +recommendable +recommendation +recommendations +recommendatory +recommended +recommender +recommenders +recommending +recommends +recommission +recommissioned +recommissioning +recommissions +recommit +recommitment +recommitments +recommits +recommittal +recommittals +recommitted +recommitting +recompense +recompensed +recompenses +recompensing +recompilation +recompilations +recompile +recompiled +recompiles +recompiling +recompose +recomposed +recomposes +recomposing +recomposition +recompositions +recompress +recompressed +recompresses +recompressing +recompression +recompressions +recomputation +recomputations +recompute +recomputed +recomputes +recomputing +recon +reconceive +reconceived +reconceives +reconceiving +reconcentrate +reconcentrated +reconcentrates +reconcentrating +reconcentration +reconcentrations +reconception +reconceptions +reconceptualization +reconceptualizations +reconceptualize +reconceptualized +reconceptualizes +reconceptualizing +reconcilability +reconcilable +reconcilableness +reconcilably +reconcile +reconciled +reconcilement +reconcilements +reconciler +reconcilers +reconciles +reconciliation +reconciliations +reconciliatory +reconciling +recondense +recondensed +recondenses +recondensing +recondite +reconditely +reconditeness +recondition +reconditioned +reconditioning +reconditions +reconfiguration +reconfigurations +reconfigure +reconfigured +reconfigures +reconfiguring +reconfirm +reconfirmation +reconfirmations +reconfirmed +reconfirming +reconfirms +reconnaissance +reconnaissances +reconnect +reconnected +reconnecting +reconnection +reconnections +reconnects +reconnoissance +reconnoissances +reconnoiter +reconnoitered +reconnoiterer +reconnoiterers +reconnoitering +reconnoiters +reconnoitre +reconnoitred +reconnoitres +reconnoitring +reconquer +reconquered +reconquering +reconquers +reconquest +reconquests +recons +reconsecrate +reconsecrated +reconsecrates +reconsecrating +reconsecration +reconsecrations +reconsider +reconsideration +reconsiderations +reconsidered +reconsidering +reconsiders +reconsolidate +reconsolidated +reconsolidates +reconsolidating +reconsolidation +reconsolidations +reconstitute +reconstituted +reconstitutes +reconstituting +reconstitution +reconstitutions +reconstruct +reconstructed +reconstructible +reconstructing +reconstruction +reconstructionism +reconstructionist +reconstructionists +reconstructions +reconstructive +reconstructor +reconstructors +reconstructs +recontact +recontacted +recontacting +recontacts +recontaminate +recontaminated +recontaminates +recontaminating +recontamination +recontextualize +recontextualized +recontextualizes +recontextualizing +recontour +recontoured +recontouring +recontours +reconvene +reconvened +reconvenes +reconvening +reconvention +reconversion +reconversions +reconvert +reconverted +reconverting +reconverts +reconvey +reconveyance +reconveyances +reconveyed +reconveying +reconveys +reconvict +reconvicted +reconvicting +reconviction +reconvictions +reconvicts +reconvince +reconvinced +reconvinces +reconvincing +recopied +recopies +recopy +recopying +record +recordable +recordation +recordations +recorded +recorder +recorders +recording +recordings +recordist +recordists +records +recork +recorked +recorking +recorks +recount +recountal +recountals +recounted +recounter +recounters +recounting +recounts +recoup +recoupable +recouped +recouping +recoupment +recoupments +recoups +recourse +recourses +recover +recoverability +recoverable +recoverably +recovered +recoverer +recoverers +recoveries +recovering +recovers +recovery +recreance +recreancy +recreant +recreantly +recreants +recreate +recreated +recreates +recreating +recreation +recreational +recreationally +recreationist +recreationists +recreations +recreative +recrement +recremental +recrements +recriminate +recriminated +recriminates +recriminating +recrimination +recriminations +recriminative +recriminator +recriminators +recriminatory +recross +recrossed +recrosses +recrossing +recrudesce +recrudesced +recrudescence +recrudescent +recrudesces +recrudescing +recruit +recruited +recruiter +recruiters +recruiting +recruitment +recruitments +recruits +recrystallization +recrystallizations +recrystallize +recrystallized +recrystallizes +recrystallizing +recta +rectal +rectally +rectangle +rectangles +rectangular +rectangularity +rectangularly +recti +rectifiability +rectifiable +rectification +rectifications +rectified +rectifier +rectifiers +rectifies +rectify +rectifying +rectilinear +rectilinearly +rectitude +rectitudinous +recto +rector +rectorate +rectorates +rectorial +rectories +rectors +rectorship +rectorships +rectory +rectos +rectrices +rectrix +rectum +rectums +rectus +recultivate +recultivated +recultivates +recultivating +recumbence +recumbency +recumbent +recumbently +recuperate +recuperated +recuperates +recuperating +recuperation +recuperations +recuperative +recuperatory +recur +recurred +recurrence +recurrences +recurrent +recurrently +recurring +recurs +recursion +recursions +recursive +recursively +recursiveness +recurvate +recurvation +recurvations +recurve +recurved +recurves +recurving +recusal +recusancies +recusancy +recusant +recusants +recuse +recused +recuses +recusing +recut +recuts +recutting +recyclable +recyclables +recycle +recycled +recycler +recyclers +recycles +recycling +red +redact +redacted +redacting +redaction +redactional +redactor +redactors +redacts +redargue +redargued +redargues +redarguing +redate +redated +redates +redating +redbait +redbaited +redbaiter +redbaiters +redbaiting +redbaitings +redbaits +redbelly +redbird +redbirds +redbone +redbones +redbreast +redbreasts +redbrick +redbud +redbuds +redbug +redbugs +redcap +redcaps +redcoat +redcoats +redden +reddened +reddener +reddeners +reddening +reddens +redder +reddest +reddish +reddishness +reddle +reddled +reddles +reddling +rede +redear +redecorate +redecorated +redecorates +redecorating +redecoration +redecorations +redecorator +redecorators +reded +rededicate +rededicated +rededicates +rededicating +rededication +rededications +redeem +redeemable +redeemably +redeemed +redeemer +redeemers +redeeming +redeems +redefect +redefine +redefined +redefines +redefining +redefinition +redefinitions +redeliver +redelivered +redeliveries +redelivering +redelivers +redelivery +redemption +redemptional +redemptioner +redemptioners +redemptions +redemptive +redemptorist +redemptorists +redemptory +redeploy +redeployed +redeploying +redeployment +redeployments +redeploys +redeposit +redeposited +redepositing +redeposits +redes +redescribe +redescribed +redescribes +redescribing +redescription +redescriptions +redesign +redesigned +redesigning +redesigns +redetect +redetected +redetects +redetermination +redeterminations +redetermine +redetermined +redetermines +redetermining +redevelop +redeveloped +redeveloper +redevelopers +redeveloping +redevelopment +redevelopments +redevelops +redeye +redeyes +redfish +redfishes +redhead +redheaded +redheads +redhorse +redhorses +redia +rediae +redial +redialed +redialing +redialled +redialling +redials +redias +redid +redifferentiation +redifferentiations +redigestion +reding +redingote +redingotes +redintegrate +redintegrated +redintegrates +redintegrating +redintegration +redintegrations +redintegrative +redintegrator +redintegrators +redirect +redirected +redirecting +redirection +redirections +redirector +redirectors +redirects +rediscount +rediscountable +rediscounted +rediscounting +rediscounts +rediscover +rediscovered +rediscoveries +rediscovering +rediscovers +rediscovery +rediscuss +rediscussed +rediscusses +rediscussing +redisplay +redisplayed +redisplaying +redisplays +redispose +redisposed +redisposes +redisposing +redisposition +redispositions +redissolve +redissolved +redissolves +redissolving +redistill +redistillation +redistillations +redistilled +redistilling +redistills +redistribute +redistributed +redistributes +redistributing +redistribution +redistributional +redistributionist +redistributionists +redistributions +redistributive +redistrict +redistricted +redistricting +redistricts +redivide +redivided +redivides +redividing +redivision +redivisions +redivivus +redleg +redlegs +redline +redlined +redlines +redlining +redly +redneck +rednecked +rednecks +redness +redo +redoes +redoing +redolence +redolency +redolent +redolently +redon +redone +redonned +redonning +redons +redouble +redoubled +redoubles +redoubling +redoubt +redoubtable +redoubtably +redoubts +redound +redounded +redounding +redounds +redout +redouts +redox +redoxes +redpoll +redpolls +redraft +redrafted +redrafting +redrafts +redraw +redrawing +redrawn +redraws +redream +redreamed +redreaming +redreams +redreamt +redress +redressed +redresser +redressers +redresses +redressing +redressor +redressors +redrew +redrill +redrilled +redrilling +redrills +redroot +redroots +reds +redshank +redshanks +redshift +redshifted +redshifts +redshirt +redshirted +redshirting +redshirts +redshouldered +redskin +redskins +redstart +redstarts +redtop +redtops +redub +redubbed +redubbing +redubs +reduce +reduced +reducer +reducers +reduces +reducibility +reducible +reducibly +reducing +reductant +reductants +reductase +reductases +reductio +reduction +reductional +reductiones +reductionism +reductionist +reductionistic +reductionists +reductions +reductive +reductively +reductiveness +reductivism +reductivist +reductivists +redundancies +redundancy +redundant +redundantly +reduplicate +reduplicated +reduplicates +reduplicating +reduplication +reduplications +reduplicative +reduplicatively +reduviid +reduviids +redux +redware +redwing +redwings +redwood +redwoods +reecho +reechoed +reechoes +reechoing +reed +reedbird +reedbirds +reedbuck +reedbucks +reeded +reedier +reediest +reedified +reedifies +reedify +reedifying +reediness +reeding +reedings +reedit +reedited +reediting +reedition +reeditions +reedits +reedlike +reedling +reedlings +reedman +reedmen +reeds +reeducate +reeducated +reeducates +reeducating +reeducation +reeducations +reeducative +reedy +reef +reefable +reefed +reefer +reefers +reefing +reefs +reefy +reek +reeked +reeker +reekers +reeking +reeks +reeky +reel +reelable +reelect +reelected +reelecting +reelection +reelections +reelects +reeled +reeler +reelers +reeligibility +reeligible +reeling +reels +reembroider +reembroidered +reembroidering +reembroiders +reemerge +reemerged +reemergence +reemergences +reemerges +reemerging +reemission +reemissions +reemit +reemits +reemitted +reemitting +reemphases +reemphasis +reemphasize +reemphasized +reemphasizes +reemphasizing +reemploy +reemployed +reemploying +reemployment +reemployments +reemploys +reenact +reenacted +reenacting +reenactment +reenactments +reenacts +reencounter +reencountered +reencountering +reencounters +reendow +reendowed +reendowing +reendows +reenergize +reenergized +reenergizes +reenergizing +reenforce +reenforced +reenforces +reenforcing +reengage +reengaged +reengagement +reengagements +reengages +reengaging +reengineer +reengineered +reengineering +reengineers +reengrave +reengraved +reengraves +reengraving +reenlist +reenlisted +reenlisting +reenlistment +reenlistments +reenlists +reenroll +reenrolled +reenrolling +reenrolls +reenter +reentered +reentering +reenters +reenthrone +reenthroned +reenthrones +reenthroning +reentrance +reentrances +reentrant +reentrants +reentries +reentry +reequip +reequipment +reequipped +reequipping +reequips +reerect +reerected +reerecting +reerects +reescalate +reescalated +reescalates +reescalating +reescalation +reescalations +reestablish +reestablished +reestablishes +reestablishing +reestablishment +reestimate +reestimated +reestimates +reestimating +reevaluate +reevaluated +reevaluates +reevaluating +reevaluation +reevaluations +reeve +reeved +reeves +reeving +reexamination +reexaminations +reexamine +reexamined +reexamines +reexamining +reexperience +reexperienced +reexperiences +reexperiencing +reexplore +reexplored +reexplores +reexploring +reexport +reexportation +reexportations +reexported +reexporting +reexports +reexpose +reexposed +reexposes +reexposing +reexposure +reexposures +reexpress +reexpressed +reexpresses +reexpressing +ref +reface +refaced +refaces +refacing +refashion +refashioned +refashioning +refashions +refasten +refastened +refastening +refastens +refect +refected +refecting +refection +refections +refectories +refectory +refects +refed +refeed +refeeding +refeeds +refeel +refeeling +refeels +refelt +refence +refenced +refences +refencing +refer +referable +referee +refereed +refereeing +referees +reference +referenced +referencer +referencers +references +referencing +referenda +referendum +referendums +referent +referential +referentiality +referentially +referents +referral +referrals +referred +referrer +referrers +referring +refers +refight +refighting +refights +refigure +refigured +refigures +refiguring +refile +refiled +refiles +refiling +refill +refillable +refilled +refilling +refills +refinance +refinanced +refinancer +refinancers +refinances +refinancier +refinanciers +refinancing +refind +refinding +refinds +refine +refined +refinement +refinements +refiner +refineries +refiners +refinery +refines +refining +refinish +refinished +refinisher +refinishers +refinishes +refinishing +refire +refired +refires +refiring +refit +refits +refitted +refitting +refix +refixed +refixes +refixing +reflag +reflagged +reflagging +reflags +reflate +reflated +reflates +reflating +reflation +reflationary +reflect +reflectance +reflected +reflecting +reflection +reflectional +reflections +reflective +reflectively +reflectiveness +reflectivities +reflectivity +reflectometer +reflectometers +reflectometry +reflector +reflectorize +reflectorized +reflectorizes +reflectorizing +reflectors +reflects +reflex +reflexed +reflexes +reflexing +reflexive +reflexively +reflexiveness +reflexives +reflexivity +reflexly +reflexologist +reflexologists +reflexology +refloat +refloated +refloating +refloats +reflow +reflowed +reflowing +reflows +refluence +refluent +reflux +refluxed +refluxes +refluxing +refocus +refocused +refocuses +refocusing +refocussed +refocussing +refold +refolded +refolding +refolds +reforecast +reforecasting +reforecasts +reforest +reforestation +reforestations +reforested +reforesting +reforests +reforge +reforged +reforges +reforging +reform +reformability +reformable +reformat +reformate +reformates +reformation +reformational +reformations +reformative +reformatories +reformatory +reformats +reformatted +reformatting +reformed +reformer +reformers +reforming +reformism +reformist +reformists +reforms +reformulate +reformulated +reformulates +reformulating +reformulation +reformulations +refortification +refortified +refortifies +refortify +refortifying +refought +refound +refoundation +refoundations +refounded +refounding +refounds +refract +refracted +refractile +refracting +refraction +refractional +refractive +refractively +refractiveness +refractivity +refractometer +refractometers +refractometric +refractometry +refractor +refractories +refractorily +refractoriness +refractors +refractory +refracts +refrain +refrained +refrainer +refrainers +refraining +refrainment +refrainments +refrains +reframe +reframed +reframes +reframing +refrangibility +refrangible +refrangibleness +refreeze +refreezes +refreezing +refresh +refreshed +refreshen +refreshened +refreshening +refreshens +refresher +refreshers +refreshes +refreshing +refreshingly +refreshment +refreshments +refried +refries +refrigerant +refrigerants +refrigerate +refrigerated +refrigerates +refrigerating +refrigeration +refrigerations +refrigerative +refrigerator +refrigerators +refrigeratory +refringence +refringences +refringent +refroze +refrozen +refry +refrying +refs +reft +refuel +refueled +refueling +refuelled +refuelling +refuels +refuge +refuged +refugee +refugeeism +refugees +refuges +refugia +refuging +refugium +refulgence +refulgency +refulgent +refulgently +refund +refundability +refundable +refunded +refunder +refunders +refunding +refundment +refundments +refunds +refurbish +refurbished +refurbisher +refurbishers +refurbishes +refurbishing +refurbishment +refurbishments +refurnish +refurnished +refurnishes +refurnishing +refusal +refusals +refuse +refused +refusednik +refusedniks +refusenik +refuseniks +refuser +refusers +refuses +refusing +refusnik +refusniks +refutability +refutable +refutably +refutal +refutals +refutation +refutations +refute +refuted +refuter +refuters +refutes +refuting +regain +regained +regainer +regainers +regaining +regains +regal +regale +regaled +regalement +regalements +regales +regalia +regaling +regalities +regality +regally +regard +regardant +regarded +regardful +regardfully +regardfulness +regarding +regardless +regardlessly +regardlessness +regards +regather +regathered +regathering +regathers +regatta +regattas +regave +regear +regeared +regearing +regears +regelate +regelated +regelates +regelating +regelation +regelations +regencies +regency +regenerable +regeneracy +regenerate +regenerated +regenerately +regenerateness +regenerates +regenerating +regeneration +regenerations +regenerative +regeneratively +regenerator +regenerators +regensburg +regent +regental +regents +regerminate +regerminated +regerminates +regerminating +regermination +reggae +reggaes +reggio +regicidal +regicide +regicides +regild +regilded +regilding +regilds +regime +regimen +regimens +regiment +regimental +regimentally +regimentals +regimentation +regimentations +regimented +regimenting +regiments +regimes +regina +region +regional +regionalism +regionalisms +regionalist +regionalistic +regionalists +regionalization +regionalizations +regionalize +regionalized +regionalizes +regionalizing +regionally +regionals +regions +regisseurs +register +registerable +registered +registerer +registerers +registering +registers +registrable +registrant +registrants +registrar +registrars +registration +registrations +registries +registry +regius +regive +regiven +regives +regiving +reglaze +reglazed +reglazes +reglazing +reglet +reglets +regna +regnal +regnant +regnum +regolith +regoliths +regorge +regorged +regorges +regorging +regosol +regosols +regrade +regraded +regrades +regrading +regraft +regrafted +regrafting +regrafts +regrant +regranted +regranting +regrants +regreen +regreened +regreening +regreens +regress +regressed +regresses +regressing +regression +regressions +regressive +regressively +regressiveness +regressivity +regressor +regressors +regret +regretful +regretfully +regretfulness +regretless +regrets +regrettable +regrettably +regretted +regretter +regretters +regretting +regrew +regrind +regrinding +regrinds +regroom +regroomed +regrooming +regrooms +regroove +regrooved +regrooves +regrooving +reground +regroup +regrouped +regrouping +regroups +regrow +regrowing +regrown +regrows +regrowth +regrowths +regular +regularities +regularity +regularization +regularizations +regularize +regularized +regularizer +regularizers +regularizes +regularizing +regularly +regulars +regulate +regulated +regulates +regulating +regulation +regulations +regulative +regulator +regulators +regulatory +reguli +reguline +regulus +reguluses +regurgitant +regurgitate +regurgitated +regurgitates +regurgitating +regurgitation +regurgitations +regurgitative +rehab +rehabbed +rehabber +rehabbers +rehabbing +rehabilitant +rehabilitants +rehabilitatable +rehabilitate +rehabilitated +rehabilitates +rehabilitating +rehabilitation +rehabilitations +rehabilitative +rehabilitator +rehabilitators +rehabs +rehandle +rehandled +rehandles +rehandling +rehang +rehanged +rehanging +rehangs +rehash +rehashed +rehashes +rehashing +rehear +reheard +rehearing +rehearings +rehears +rehearsal +rehearsals +rehearse +rehearsed +rehearser +rehearsers +rehearses +rehearsing +reheat +reheated +reheating +reheats +rehinge +rehinged +rehinges +rehinging +rehire +rehired +rehires +rehiring +rehospitalization +rehospitalizations +rehospitalize +rehospitalized +rehospitalizes +rehospitalizing +rehouse +rehoused +rehouses +rehousing +rehumanize +rehumanized +rehumanizes +rehumanizing +rehung +rehydratable +rehydrate +rehydrated +rehydrates +rehydrating +rehydration +rehydrations +rehypnotize +rehypnotized +rehypnotizes +rehypnotizing +reich +reichsmark +reichsmarks +reichstag +reidentified +reidentifies +reidentify +reidentifying +reification +reifications +reificatory +reified +reifier +reifiers +reifies +reify +reifying +reign +reigned +reigning +reignite +reignited +reignites +reigniting +reignition +reigns +reimage +reimagine +reimagined +reimagines +reimagining +reimbursable +reimburse +reimbursed +reimbursement +reimbursements +reimburses +reimbursing +reimmerse +reimmersed +reimmerses +reimmersing +reimplant +reimplantation +reimplanted +reimplanting +reimplants +reimport +reimportation +reimportations +reimported +reimporting +reimports +reimpose +reimposed +reimposes +reimposing +reimposition +reimpositions +reimpression +reimpressions +rein +reincarnate +reincarnated +reincarnates +reincarnating +reincarnation +reincarnations +reincorporate +reincorporated +reincorporates +reincorporating +reincorporation +reincorporations +reindeer +reindeers +reindict +reindicted +reindicting +reindictment +reindictments +reindicts +reindustrialization +reindustrialize +reindustrialized +reindustrializes +reindustrializing +reined +reinfection +reinfections +reinfestation +reinfestations +reinflate +reinflated +reinflates +reinflating +reinflation +reinforce +reinforceable +reinforced +reinforcement +reinforcements +reinforcer +reinforcers +reinforces +reinforcing +reinhabit +reinhabited +reinhabiting +reinhabits +reining +reinitialization +reinitializations +reinitialize +reinitialized +reinitializer +reinitializers +reinitializes +reinitializing +reinitiate +reinitiated +reinitiates +reinitiating +reinject +reinjected +reinjecting +reinjection +reinjections +reinjects +reinjure +reinjured +reinjures +reinjuries +reinjuring +reinjury +reink +reinked +reinking +reinks +reinnervate +reinnervated +reinnervates +reinnervating +reinnervation +reinoculate +reinoculated +reinoculates +reinoculating +reinoculation +reinoculations +reins +reinsert +reinserted +reinserting +reinsertion +reinsertions +reinserts +reinsman +reinsmen +reinspect +reinspected +reinspecting +reinspection +reinspections +reinspects +reinspire +reinspired +reinspires +reinspiring +reinstall +reinstallation +reinstalled +reinstalling +reinstalls +reinstate +reinstated +reinstatement +reinstatements +reinstates +reinstating +reinstitute +reinstituted +reinstitutes +reinstituting +reinstitution +reinstitutionalization +reinsurance +reinsurances +reinsure +reinsured +reinsurer +reinsurers +reinsures +reinsuring +reintegrate +reintegrated +reintegrates +reintegrating +reintegration +reintegrations +reintegrative +reinter +reinterpret +reinterpretation +reinterpretations +reinterpreted +reinterpreting +reinterprets +reinterred +reinterring +reinterrogate +reinterrogated +reinterrogates +reinterrogating +reinterrogation +reinterrogations +reinters +reinterview +reinterviewed +reinterviewing +reinterviews +reintroduce +reintroduced +reintroduces +reintroducing +reintroduction +reintroductions +reinvade +reinvaded +reinvades +reinvading +reinvasion +reinvasions +reinvent +reinvented +reinventing +reinvention +reinvents +reinvest +reinvested +reinvestigate +reinvestigated +reinvestigates +reinvestigating +reinvestigation +reinvestigations +reinvesting +reinvestment +reinvestments +reinvests +reinvigorate +reinvigorated +reinvigorates +reinvigorating +reinvigoration +reinvigorations +reinvigorator +reinvigorators +reis +reissue +reissued +reissues +reissuing +reiter +reiterate +reiterated +reiterates +reiterating +reiteration +reiterations +reiterative +reiteratively +reiterator +reiterators +reith +rejacket +rejacketed +rejacketing +rejackets +reject +rejected +rejectee +rejectees +rejecter +rejecters +rejecting +rejectingly +rejection +rejections +rejective +rejectivist +rejector +rejectors +rejects +rejig +rejigged +rejigger +rejiggered +rejiggering +rejiggers +rejigging +rejigs +rejoice +rejoiced +rejoicer +rejoicers +rejoices +rejoicing +rejoicingly +rejoicings +rejoin +rejoinder +rejoinders +rejoined +rejoining +rejoins +rejudge +rejudged +rejudges +rejudging +rejuggle +rejuggled +rejuggles +rejuggling +rejuvenate +rejuvenated +rejuvenates +rejuvenating +rejuvenation +rejuvenations +rejuvenator +rejuvenators +rejuvenescence +rejuvenescences +rejuvenescent +rekey +rekeyboard +rekeyed +rekeying +rekeys +rekindle +rekindled +rekindles +rekindling +reknit +reknits +reknitted +reknitting +relabel +relabeled +relabeling +relabels +relacquer +relacquered +relacquering +relacquers +relaid +relandscape +relandscaped +relandscapes +relandscaping +relapse +relapsed +relapser +relapsers +relapses +relapsing +relatable +relate +related +relatedly +relatedness +relater +relaters +relates +relating +relation +relational +relationally +relations +relationship +relationships +relative +relatively +relativeness +relatives +relativism +relativist +relativistic +relativistically +relativists +relativity +relativize +relativized +relativizes +relativizing +relator +relators +relaunch +relaunched +relaunches +relaunching +relax +relaxable +relaxant +relaxants +relaxation +relaxations +relaxed +relaxedly +relaxedness +relaxer +relaxers +relaxes +relaxin +relaxing +relay +relayed +relaying +relays +relearn +relearned +relearning +relearns +relearnt +releasability +releasable +releasably +release +released +releaser +releasers +releases +releasing +relegate +relegated +relegates +relegating +relegation +relegations +relend +relending +relends +relent +relented +relenting +relentless +relentlessly +relentlessness +relents +relevance +relevancy +relevant +relevantly +reliability +reliable +reliableness +reliably +reliance +reliant +reliantly +relic +relicense +relicensed +relicenses +relicensing +relicensure +relics +relict +reliction +relictions +relicts +relied +relief +reliefs +relier +reliers +relies +relievable +relieve +relieved +relievedly +reliever +relievers +relieves +relieving +relievo +relievos +relight +relighted +relighting +relights +religion +religionism +religionist +religionists +religionless +religions +religiose +religiosity +religious +religiously +religiousness +reline +relined +relines +relining +relink +relinked +relinking +relinks +relinquish +relinquished +relinquisher +relinquishers +relinquishes +relinquishing +relinquishment +relinquishments +reliquaries +reliquary +reliquefied +reliquefies +reliquefy +reliquefying +reliquiae +relish +relishable +relished +relishes +relishing +relit +relive +relived +relives +reliving +reload +reloaded +reloading +reloads +relocatable +relocate +relocated +relocatee +relocatees +relocates +relocating +relocation +relocations +relock +relocked +relocking +relocks +relook +relooked +relooking +relooks +relubricate +relubricated +relubricates +relubricating +relubrication +relubrications +relucent +reluct +reluctance +reluctancy +reluctant +reluctantly +reluctate +reluctated +reluctates +reluctating +reluctation +reluctations +relucted +relucting +reluctivity +relucts +relume +relumed +relumes +reluming +rely +relying +rem +remade +remain +remainder +remaindered +remaindering +remainders +remained +remaining +remains +remake +remaker +remakers +remakes +remaking +reman +remand +remanded +remanding +remandment +remandments +remands +remanence +remanent +remanned +remanning +remans +remanufacture +remanufactured +remanufacturer +remanufacturers +remanufactures +remanufacturing +remap +remapped +remapping +remaps +remark +remarkable +remarkableness +remarkably +remarked +remarker +remarkers +remarket +remarketed +remarketing +remarkets +remarking +remarks +remarque +remarques +remarriage +remarriages +remarried +remarries +remarry +remarrying +remaster +remastered +remastering +remasters +rematch +rematches +remate +remated +rematerialize +rematerialized +rematerializes +rematerializing +remates +remating +rembrandt +remeasure +remeasured +remeasurement +remeasurements +remeasures +remeasuring +remediability +remediable +remediableness +remediably +remedial +remedially +remediate +remediated +remediates +remediating +remediation +remediations +remedied +remedies +remediless +remedy +remedying +remeet +remeeting +remeets +remelt +remelted +remelting +remelts +remember +rememberability +rememberable +remembered +rememberer +rememberers +remembering +remembers +remembrance +remembrancer +remembrancers +remembrances +remerge +remerged +remerges +remerging +remet +remex +remiges +remigial +remigration +remigrations +remilitarization +remilitarizations +remilitarize +remilitarized +remilitarizes +remilitarizing +remind +reminded +reminder +reminders +remindful +reminding +reminds +remington +reminisce +reminisced +reminiscence +reminiscences +reminiscent +reminiscential +reminiscently +reminiscer +reminiscers +reminisces +reminiscing +remint +reminted +reminting +remints +remise +remised +remises +remising +remiss +remissibility +remissible +remissibly +remission +remissions +remissly +remissness +remit +remitment +remitments +remits +remittable +remittal +remittals +remittance +remittances +remitted +remittence +remittency +remittent +remittently +remitter +remitters +remitting +remix +remixed +remixes +remixing +remnant +remnants +remo +remobilization +remobilizations +remobilize +remobilized +remobilizes +remobilizing +remodel +remodeled +remodeler +remodelers +remodeling +remodelled +remodelling +remodels +remodification +remodifications +remodified +remodifies +remodify +remodifying +remoisten +remoistened +remoistening +remoistens +remold +remolded +remolding +remolds +remonetization +remonetizations +remonetize +remonetized +remonetizes +remonetizing +remonstrance +remonstrances +remonstrant +remonstrantly +remonstrants +remonstrate +remonstrated +remonstrates +remonstrating +remonstration +remonstrations +remonstrative +remonstratively +remonstrator +remonstrators +remora +remoras +remorse +remorseful +remorsefully +remorsefulness +remorseless +remorselessly +remorselessness +remote +remotely +remoteness +remoter +remotes +remotest +remotion +remotions +remotivate +remotivated +remotivates +remotivating +remotivation +remotivations +remoulins +remount +remounted +remounting +remounts +removability +removable +removableness +removably +removal +removals +remove +removed +removedly +removedness +remover +removers +removes +removing +rems +remuda +remudas +remunerability +remunerable +remunerably +remunerate +remunerated +remunerates +remunerating +remuneration +remunerations +remunerative +remuneratively +remunerativeness +remunerator +remunerators +remuneratory +remus +remy +remythologize +remythologized +remythologizes +remythologizing +renail +renailed +renailing +renails +renaissance +renal +rename +renamed +renames +renaming +renascence +renascences +renascent +renationalization +renationalizations +renationalize +renationalized +renationalizes +renationalizing +renaturation +renaturations +renature +renatured +renatures +renaturing +rencontre +rencontres +rencounter +rencountered +rencountering +rencounters +rend +rended +render +renderable +rendered +renderer +renderers +rendering +renderings +renders +rendezvous +rendezvoused +rendezvousing +rending +rendition +renditions +rends +rendzina +rendzinas +renegade +renegaded +renegades +renegading +renege +reneged +reneger +renegers +reneges +reneging +renegotiable +renegotiate +renegotiated +renegotiates +renegotiating +renegotiation +renegotiations +renest +renested +renesting +renests +renew +renewability +renewable +renewably +renewal +renewals +renewed +renewedly +renewer +renewers +renewing +renews +reniform +renin +renins +renitence +renitency +renitent +renminbi +rennet +rennin +renninogen +renninogens +reno +renogram +renograms +renographic +renography +renoir +renominate +renominated +renominates +renominating +renomination +renominations +renormalization +renormalizations +renormalize +renormalized +renormalizes +renormalizing +renounce +renounced +renouncement +renouncements +renouncer +renouncers +renounces +renouncing +renovascular +renovate +renovated +renovates +renovating +renovation +renovations +renovative +renovator +renovators +renown +renowned +rent +rentability +rentable +rental +rentals +rented +renter +renters +rentier +rentiers +renting +rents +renumber +renumbered +renumbering +renumbers +renunciation +renunciations +renunciative +renunciatory +reobserve +reobserved +reobserves +reobserving +reoccupation +reoccupied +reoccupies +reoccupy +reoccupying +reoccur +reoccurred +reoccurrence +reoccurrences +reoccurring +reoccurs +reoffer +reoffered +reoffering +reoffers +reoil +reoiled +reoiling +reoils +reopen +reopened +reopening +reopens +reoperate +reoperated +reoperates +reoperating +reoperation +reoperations +reorchestrate +reorchestrated +reorchestrates +reorchestrating +reorchestration +reorchestrations +reorder +reordered +reordering +reorders +reorganization +reorganizational +reorganizations +reorganize +reorganized +reorganizer +reorganizers +reorganizes +reorganizing +reorient +reorientate +reorientated +reorientates +reorientating +reorientation +reorientations +reoriented +reorienting +reorients +reoutfit +reoutfits +reoutfitted +reoutfitting +reovirus +reoviruses +reoxidation +reoxidations +reoxidize +reoxidized +reoxidizes +reoxidizing +rep +repack +repackage +repackaged +repackager +repackagers +repackages +repackaging +repacked +repacking +repacks +repaginate +repaginated +repaginates +repaginating +repagination +repaid +repaint +repainted +repainting +repaints +repair +repairability +repairable +repairably +repaired +repairer +repairers +repairing +repairman +repairmen +repairperson +repairpersons +repairs +repairwoman +repairwomen +repand +reparability +reparable +reparably +reparation +reparations +reparative +reparatory +repark +reparked +reparking +reparks +repartee +repartees +repartition +repartitioned +repartitioning +repartitions +repass +repassage +repassages +repassed +repasses +repassing +repast +repasted +repasting +repasts +repatch +repatched +repatches +repatching +repatriate +repatriated +repatriates +repatriating +repatriation +repatriations +repattern +repatterned +repatterning +repatterns +repave +repaved +repaves +repaving +repay +repayable +repaying +repayment +repayments +repays +repeal +repealable +repealed +repealer +repealers +repealing +repeals +repeat +repeatability +repeatable +repeated +repeatedly +repeater +repeaters +repeating +repeats +repechage +repechages +repeg +repegged +repegging +repegs +repel +repellant +repelled +repellence +repellency +repellent +repellently +repellents +repeller +repellers +repelling +repels +repent +repentance +repentant +repentantly +repented +repenter +repenters +repenting +repents +repeople +repeopled +repeoples +repeopling +repercussion +repercussions +repercussive +repertoire +repertoires +repertorial +repertories +repertory +repetend +repetends +repetition +repetitional +repetitions +repetitious +repetitiously +repetitiousness +repetitive +repetitively +repetitiveness +rephotograph +rephotographed +rephotographing +rephotographs +rephrase +rephrased +rephrases +rephrasing +repine +repined +repiner +repiners +repines +repining +replace +replaceable +replaced +replacement +replacements +replacer +replacers +replaces +replacing +replan +replanned +replanning +replans +replant +replantation +replantations +replanted +replanting +replants +replaster +replastered +replastering +replasters +replate +replated +replates +replating +replay +replayed +replaying +replays +repleader +repleaders +repledge +repledged +repledges +repledging +replenish +replenishable +replenished +replenisher +replenishers +replenishes +replenishing +replenishment +replenishments +replete +repleteness +repletion +repleviable +replevied +replevies +replevin +replevined +replevines +replevining +replevins +replevy +replevying +replica +replicability +replicable +replicas +replicase +replicases +replicate +replicated +replicates +replicating +replication +replications +replicative +replicon +replicons +replied +replier +repliers +replies +replot +replots +replotted +replotting +replumb +replumbed +replumbing +replumbs +reply +replying +repo +repolarization +repolarizations +repolarize +repolarized +repolarizes +repolarizing +repolish +repolished +repolishes +repolishing +repoll +repolled +repolling +repolls +repopularize +repopularized +repopularizes +repopularizing +repopulate +repopulated +repopulates +repopulating +repopulation +report +reportable +reportage +reported +reportedly +reporter +reporters +reporting +reportorial +reportorially +reports +repos +reposal +reposals +repose +reposed +reposeful +reposefully +reposefulness +reposer +reposers +reposes +reposing +reposit +reposited +repositing +reposition +repositioned +repositioning +repositions +repositories +repository +reposits +repossess +repossessed +repossesses +repossessing +repossession +repossessions +repossessor +repossessors +repot +repots +repotted +repotting +repoussé +repower +repowered +repowering +repowers +repp +repps +reprehend +reprehended +reprehending +reprehends +reprehensibility +reprehensible +reprehensibleness +reprehensibly +reprehension +reprehensions +reprehensive +represent +representability +representable +representation +representational +representationalism +representationalist +representationalists +representationally +representations +representative +representatively +representativeness +representatives +representativity +represented +representer +representers +representing +represents +repress +repressed +represser +repressers +represses +repressibility +repressible +repressing +repression +repressionist +repressionists +repressions +repressive +repressively +repressiveness +repressor +repressors +repressurize +repressurized +repressurizes +repressurizing +reprice +repriced +reprices +repricing +reprievable +reprieval +reprievals +reprieve +reprieved +reprieves +reprieving +reprimand +reprimanded +reprimanding +reprimands +reprint +reprinted +reprinter +reprinters +reprinting +reprints +reprisal +reprisals +reprise +reprised +reprises +reprising +repristinate +repristinated +repristinates +repristinating +repristination +repristinations +reprivatization +reprivatizations +reprivatize +reprivatized +reprivatizes +reprivatizing +repro +reproach +reproachable +reproachableness +reproachably +reproached +reproacher +reproachers +reproaches +reproachful +reproachfully +reproachfulness +reproaching +reproachingly +reprobance +reprobances +reprobate +reprobated +reprobates +reprobating +reprobation +reprobations +reprobative +reprobatory +reprocess +reprocessed +reprocesses +reprocessing +reproduce +reproduced +reproducer +reproducers +reproduces +reproducibility +reproducible +reproducibly +reproducing +reproduction +reproductions +reproductive +reproductively +reproductiveness +reproductives +reprogram +reprogramed +reprograming +reprogrammability +reprogrammable +reprogrammed +reprogramming +reprograms +reprographer +reprographers +reprographic +reprographics +reprography +reproof +reproofing +reproofs +repros +reprovable +reprove +reproved +reprover +reprovers +reproves +reproving +reprovingly +reprovision +reprovisioned +reprovisioning +reprovisions +reps +reptant +reptile +reptilelike +reptiles +reptilia +reptilian +reptilians +reptilium +republic +republican +republicanism +republicanization +republicanizations +republicanize +republicanized +republicanizes +republicanizing +republicans +republication +republications +republics +republish +republished +republisher +republishers +republishes +republishing +repudiate +repudiated +repudiates +repudiating +repudiation +repudiationist +repudiationists +repudiations +repudiative +repudiator +repudiators +repugn +repugnance +repugnancies +repugnancy +repugnant +repugnantly +repugned +repugning +repugns +repulse +repulsed +repulser +repulsers +repulses +repulsing +repulsion +repulsions +repulsive +repulsively +repulsiveness +repump +repumped +repumping +repumps +repunctuation +repurchase +repurchased +repurchases +repurchasing +repurified +repurifies +repurify +repurifying +reputability +reputable +reputably +reputation +reputational +reputations +repute +reputed +reputedly +reputes +reputing +request +requested +requester +requesters +requesting +requestor +requestors +requests +requiem +requiems +requiescat +requiescats +requirable +require +required +requirement +requirements +requirer +requirers +requires +requiring +requisite +requisitely +requisiteness +requisites +requisition +requisitioned +requisitioning +requisitions +requitable +requital +requitals +requite +requited +requiter +requiters +requites +requiting +rerack +reracked +reracking +reracks +reradiate +reradiated +reradiates +reradiating +reradiation +reradiations +reraise +reraised +reraises +reraising +reran +reread +rereading +rereadings +rereads +rerecord +rerecorded +rerecording +rerecords +reredos +reredoses +reregister +reregistered +reregistering +reregisters +reregistration +reregistrations +reregulate +reregulated +reregulates +reregulating +reregulation +rerelease +rereleased +rereleases +rereleasing +reremind +rereminded +rereminding +rereminds +rerepeat +rerepeated +rerepeating +rerepeats +rereview +rereviewed +rereviewing +rereviews +rereward +rerewards +rerig +rerigged +rerigging +rerigs +reroof +reroofed +reroofing +reroofs +reroute +rerouted +reroutes +rerouting +rerun +rerunning +reruns +res +resail +resailed +resailing +resails +resalable +resale +resales +resample +resampled +resamples +resampling +resat +resaw +resawed +resawing +resawn +resaws +rescale +rescaled +rescales +rescaling +rescan +rescanned +rescanning +rescans +reschedule +rescheduled +reschedules +rescheduling +reschool +reschooled +reschooling +reschools +rescind +rescindable +rescinded +rescinder +rescinders +rescinding +rescindment +rescindments +rescinds +rescission +rescissions +rescissory +rescore +rescored +rescores +rescoring +rescreen +rescreened +rescreening +rescreens +rescript +rescripts +rescuable +rescue +rescued +rescuer +rescuers +rescues +rescuing +resculpt +resculpted +resculpting +resculpts +reseal +resealable +resealed +resealing +reseals +research +researchable +researched +researcher +researchers +researches +researching +researchist +researchists +reseason +reseasoned +reseasoning +reseasons +reseat +reseated +reseating +reseats +reseau +resect +resectability +resectable +resected +resecting +resection +resections +resectoscope +resectoscopes +resects +resecure +resecured +resecures +resecuring +reseda +resedas +resee +reseed +reseeded +reseeding +reseeds +reseeing +reseen +resees +resegregate +resegregated +resegregates +resegregating +resegregation +resegregations +reselect +reselected +reselecting +reselection +reselections +reselects +resell +reseller +resellers +reselling +resells +resemblance +resemblances +resemblant +resemble +resembled +resembler +resemblers +resembles +resembling +resend +resending +resends +resensitize +resensitized +resensitizes +resensitizing +resent +resented +resentence +resentenced +resentences +resentencing +resentful +resentfully +resentfulness +resenting +resentment +resentments +resents +reserpine +reserpines +reservable +reservation +reservationist +reservationists +reservations +reserve +reserved +reservedly +reservedness +reserver +reservers +reserves +reservice +reserviced +reservices +reservicing +reserving +reservist +reservists +reservoir +reservoirs +reset +resets +resettable +resetter +resetters +resetting +resettle +resettled +resettlement +resettlements +resettles +resettling +resew +resewed +resewing +resewn +resews +resh +reshape +reshaped +reshaper +reshapers +reshapes +reshaping +reshes +reshingle +reshingled +reshingles +reshingling +reship +reshipment +reshipments +reshipped +reshipping +reships +reshod +reshoe +reshoed +reshoeing +reshoes +reshoot +reshooting +reshoots +reshot +reshow +reshowed +reshowing +reshown +reshows +reshuffle +reshuffled +reshuffles +reshuffling +resid +reside +resided +residence +residences +residencies +residency +resident +residential +residentially +residentiaries +residentiary +residents +resider +residers +resides +residing +resids +residua +residual +residually +residuals +residuary +residue +residues +residuum +resift +resifted +resifting +resifts +resight +resighted +resighting +resights +resign +resignation +resignations +resigned +resignedly +resignedness +resigner +resigners +resigning +resigns +resile +resiled +resiles +resilience +resiliency +resilient +resiliently +resilin +resiling +resilins +resilver +resilvered +resilvering +resilvers +resin +resinate +resinated +resinates +resinating +resined +resines +resiniferous +resining +resinoid +resinoids +resinous +resins +resist +resistance +resistances +resistant +resisted +resister +resisters +resistibility +resistible +resistibly +resisting +resistive +resistively +resistiveness +resistivities +resistivity +resistless +resistlessly +resistlessness +resistor +resistors +resists +resit +resite +resited +resites +resiting +resits +resitting +resittings +resituate +resituated +resituates +resituating +resize +resized +resizes +resizing +reslate +reslated +reslates +reslating +resoak +resoaked +resoaking +resoaks +resocialization +resocialize +resocialized +resocializes +resocializing +resod +resodded +resodding +resods +resold +resolder +resoldered +resoldering +resolders +resole +resoled +resoles +resolidification +resolidified +resolidifies +resolidify +resolidifying +resoling +resolubility +resoluble +resolubleness +resolute +resolutely +resoluteness +resolution +resolutions +resolvability +resolvable +resolvableness +resolve +resolved +resolvedly +resolvent +resolvents +resolver +resolvers +resolves +resolving +resonance +resonances +resonant +resonantly +resonate +resonated +resonates +resonating +resonation +resonations +resonator +resonators +resorb +resorbed +resorbing +resorbs +resorcin +resorcinol +resorcinols +resorcins +resorption +resorptions +resorptive +resort +resorted +resorter +resorters +resorting +resorts +resound +resounded +resounding +resoundingly +resounds +resource +resourceful +resourcefully +resourcefulness +resources +resow +resowed +resowing +resown +resows +respect +respectability +respectable +respectableness +respectably +respected +respecter +respecters +respectful +respectfully +respectfulness +respecting +respective +respectively +respectiveness +respects +respell +respelled +respelling +respells +respelt +respirability +respirable +respiration +respirational +respirations +respirator +respirators +respiratory +respire +respired +respires +respiring +respiritualize +respiritualized +respiritualizes +respiritualizing +respirometer +respirometers +respirometric +respirometry +respite +respited +respites +respiting +resplendence +resplendency +resplendent +resplendently +respond +responded +respondence +respondency +respondent +respondents +responder +responders +responding +responds +responsa +response +responses +responsibilities +responsibility +responsible +responsibleness +responsibly +responsions +responsive +responsively +responsiveness +responsorial +responsories +responsory +responsum +respot +respots +respotted +respotting +respray +resprayed +respraying +resprays +respring +respringing +resprings +resprout +resprouted +resprouting +resprouts +resprung +ressentiment +ressentiments +rest +restabilize +restabilized +restabilizes +restabilizing +restack +restacked +restacking +restacks +restage +restaged +restages +restaging +restamp +restamped +restamping +restamps +restante +restart +restartable +restarted +restarting +restarts +restate +restated +restatement +restatements +restates +restating +restaurant +restauranteur +restauranteurs +restaurants +restaurateur +restaurateurs +rested +rester +resters +restful +restfully +restfulness +restharrow +restharrows +restick +resticking +resticks +restiform +restimulate +restimulated +restimulates +restimulating +restimulation +resting +restitute +restituted +restitutes +restituting +restitution +restitutions +restive +restively +restiveness +restless +restlessly +restlessness +restock +restocked +restocking +restocks +restoke +restoked +restokes +restoking +restorability +restorable +restoral +restorals +restoration +restorations +restorative +restoratively +restorativeness +restoratives +restore +restored +restorer +restorers +restores +restoring +restrain +restrainable +restrained +restrainedly +restrainer +restrainers +restraining +restrains +restraint +restraints +restrengthen +restrengthened +restrengthening +restrengthens +restress +restressed +restresses +restressing +restrict +restricted +restrictedly +restricter +restricters +restricting +restriction +restrictionism +restrictionist +restrictionists +restrictions +restrictive +restrictively +restrictiveness +restrictor +restrictors +restricts +restrike +restrikes +restriking +restring +restringing +restrings +restroom +restrooms +restruck +restructure +restructured +restructures +restructuring +restrung +rests +restuck +restudied +restudies +restudy +restudying +restuff +restuffed +restuffing +restuffs +restyle +restyled +restyles +restyling +resublime +resublimed +resublimes +resubliming +resubmission +resubmissions +resubmit +resubmits +resubmitted +resubmitting +result +resultant +resultantly +resultants +resulted +resultful +resultfulness +resulting +resultless +results +resumable +resume +resumed +resumer +resumers +resumes +resuming +resummon +resummoned +resummoning +resummons +resumption +resumptions +resumé +resumés +resupinate +resupination +resupinations +resupine +resupplied +resupplies +resupply +resupplying +resurface +resurfaced +resurfacer +resurfacers +resurfaces +resurfacing +resurge +resurged +resurgence +resurgent +resurgently +resurges +resurging +resurrect +resurrected +resurrecting +resurrection +resurrectional +resurrectionist +resurrectionists +resurrections +resurrector +resurrectors +resurrects +resurvey +resurveyed +resurveying +resurveys +resuscitable +resuscitate +resuscitated +resuscitates +resuscitating +resuscitation +resuscitations +resuscitative +resuscitator +resuscitators +resveratrol +resynchronization +resynchronize +resyntheses +resynthesis +resynthesize +resynthesized +resynthesizes +resynthesizing +resystematize +resystematized +resystematizes +resystematizing +ret +retable +retables +retackle +retackled +retackles +retackling +retag +retagged +retagging +retags +retail +retailed +retailer +retailers +retailing +retails +retain +retainability +retainable +retained +retainer +retainers +retaining +retainment +retainments +retains +retake +retaken +retakes +retaking +retaliate +retaliated +retaliates +retaliating +retaliation +retaliations +retaliative +retaliator +retaliators +retaliatory +retard +retardant +retardants +retardate +retardates +retardation +retardations +retarded +retarder +retarders +retarding +retards +retarget +retargeted +retargeting +retargets +retaste +retasted +retastes +retasting +retaught +retch +retched +retches +retching +rete +reteach +reteaches +reteaching +reteam +reteamed +reteaming +reteams +retell +retelling +retellings +retells +retene +retenes +retention +retentions +retentive +retentively +retentiveness +retentivity +retest +retested +retesting +retests +retexture +retextured +retextures +retexturing +rethink +rethinker +rethinkers +rethinking +rethinks +rethought +rethread +rethreaded +rethreading +rethreads +retia +retiary +reticence +reticencies +reticency +reticent +reticently +reticle +reticles +reticula +reticular +reticulate +reticulated +reticulately +reticulates +reticulating +reticulation +reticulations +reticule +reticules +reticulocyte +reticulocytes +reticulocytic +reticuloendothelial +reticulum +retie +retied +reties +retiform +retighten +retightened +retightening +retightens +retile +retiled +retiles +retiling +retime +retimed +retimes +retiming +retina +retinacula +retinacular +retinaculum +retinae +retinal +retinas +retinene +retinenes +retinitis +retinoblastoma +retinoblastomas +retinoblastomata +retinoic +retinoid +retinoids +retinol +retinols +retinopathic +retinopathies +retinopathy +retinoscope +retinoscopes +retinoscopic +retinoscopies +retinoscopy +retinotectal +retinue +retinues +retinula +retinulae +retinular +retirant +retirants +retire +retired +retiredly +retiredness +retiree +retirees +retirement +retirements +retires +retiring +retiringly +retiringness +retold +retook +retool +retooled +retooling +retools +retorsion +retorsions +retort +retorted +retorter +retorters +retorting +retortion +retortions +retorts +retouch +retouched +retoucher +retouchers +retouches +retouching +retrace +retraceable +retraced +retracement +retracements +retracer +retracers +retraces +retracing +retract +retractability +retractable +retractation +retractations +retracted +retractibility +retractible +retractile +retractility +retracting +retraction +retractions +retractive +retractively +retractiveness +retractor +retractors +retracts +retrain +retrainable +retrained +retrainee +retrainees +retraining +retrains +retral +retrally +retransfer +retransferred +retransferring +retransfers +retransform +retransformation +retransformations +retransformed +retransforming +retransforms +retranslate +retranslated +retranslates +retranslating +retranslation +retranslations +retransmission +retransmissions +retransmit +retransmits +retransmitted +retransmitting +retread +retreaded +retreading +retreads +retreat +retreatant +retreatants +retreated +retreater +retreaters +retreating +retreats +retrench +retrenched +retrencher +retrenchers +retrenches +retrenching +retrenchment +retrenchments +retrial +retrials +retribution +retributions +retributive +retributively +retributory +retried +retries +retrievability +retrievable +retrievably +retrieval +retrievals +retrieve +retrieved +retriever +retrievers +retrieves +retrieving +retro +retroact +retroacted +retroacting +retroaction +retroactions +retroactive +retroactively +retroactivity +retroacts +retrocede +retroceded +retrocedes +retroceding +retrocession +retrocessions +retrodict +retrodicted +retrodicting +retrodiction +retrodictions +retrodictive +retrodicts +retrofire +retrofired +retrofires +retrofiring +retrofit +retrofits +retrofittable +retrofitted +retrofitter +retrofitters +retrofitting +retroflection +retroflections +retroflex +retroflexed +retroflexes +retroflexion +retroflexions +retrogradation +retrogradations +retrograde +retrograded +retrogradely +retrogrades +retrograding +retrogress +retrogressed +retrogresses +retrogressing +retrogression +retrogressions +retrogressive +retrogressively +retrolental +retroocular +retropack +retropacks +retroperitoneal +retroperitoneally +retropharyngeal +retroreflection +retroreflections +retroreflective +retroreflector +retroreflectors +retrorocket +retrorockets +retrorse +retrorsely +retros +retrospect +retrospected +retrospecting +retrospection +retrospections +retrospective +retrospectively +retrospectives +retrospects +retroussé +retroversion +retroversions +retroviral +retrovirus +retroviruses +retry +retrying +rets +retsina +retted +retting +retune +retuned +retunes +retuning +return +returnable +returnables +returned +returnee +returnees +returner +returners +returning +returns +retuse +retying +retype +retyped +retypes +retyping +reuben +reunification +reunifications +reunified +reunifies +reunify +reunifying +reunion +reunionism +reunionist +reunionistic +reunionists +reunions +reunite +reunited +reunites +reuniting +reupholster +reupholstered +reupholstering +reupholsters +reusability +reusable +reuse +reused +reuses +reusing +reuter +reutilization +reutilize +reutilized +reutilizes +reutilizing +rev +revaccinate +revaccinated +revaccinates +revaccinating +revaccination +revaccinations +revalidate +revalidated +revalidates +revalidating +revalidation +revalidations +revalorization +revalorizations +revalorize +revalorized +revalorizes +revalorizing +revaluate +revaluated +revaluates +revaluating +revaluation +revaluations +revalue +revalued +revalues +revaluing +revamp +revamped +revamping +revampment +revampments +revamps +revanche +revanches +revanchism +revanchist +revanchistic +revanchists +revascularization +revascularizations +reveal +revealable +revealed +revealer +revealers +revealing +revealingly +revealment +revealments +reveals +revegetate +revegetated +revegetates +revegetating +revegetation +revegetations +reveille +reveilles +revel +revelation +revelations +revelator +revelators +revelatory +reveled +reveler +revelers +reveling +revelled +reveller +revellers +revelling +revelries +revelrous +revelry +revels +revenant +revenants +revenge +revenged +revengeful +revengefully +revengefulness +revenger +revengers +revenges +revenging +revenue +revenuer +revenuers +revenues +reverb +reverbed +reverberant +reverberantly +reverberate +reverberated +reverberates +reverberating +reverberation +reverberations +reverberative +reverberatively +reverberator +reverberatories +reverberators +reverberatory +reverbing +reverbs +revere +revered +reverence +reverenced +reverencer +reverencers +reverences +reverencing +reverend +reverends +reverent +reverential +reverentially +reverently +reveres +reverie +reveries +reverification +revering +revers +reversal +reversals +reverse +reversed +reversely +reverser +reversers +reverses +reversibility +reversible +reversibleness +reversibles +reversibly +reversing +reversion +reversional +reversionary +reversioner +reversioners +reversions +revert +revertant +revertants +reverted +reverter +reverters +revertible +reverting +revertive +reverts +revery +revest +revested +revesting +revests +revet +revetment +revetments +revets +revetted +revetting +revictual +revictualed +revictualing +revictuals +review +reviewable +reviewed +reviewer +reviewers +reviewing +reviews +revile +reviled +revilement +revilements +reviler +revilers +reviles +reviling +revilingly +revillagigedo +revisable +revisal +revisals +revise +revised +reviser +revisers +revises +revising +revision +revisionary +revisionism +revisionist +revisionists +revisions +revisit +revisitation +revisitations +revisited +revisiting +revisits +revisor +revisors +revisory +revisualization +revisualizations +revitalization +revitalizations +revitalize +revitalized +revitalizes +revitalizing +revivable +revival +revivalism +revivalist +revivalistic +revivalists +revivals +revive +revived +reviver +revivers +revives +revivification +revivifications +revivified +revivifies +revivify +revivifying +reviving +reviviscence +reviviscent +revocability +revocable +revocation +revocations +revocatory +revoir +revoirs +revokable +revoke +revoked +revoker +revokers +revokes +revoking +revolt +revolted +revolter +revolters +revolting +revoltingly +revolts +revolute +revolution +revolutionaries +revolutionarily +revolutionariness +revolutionary +revolutionist +revolutionists +revolutionize +revolutionized +revolutionizer +revolutionizers +revolutionizes +revolutionizing +revolutions +revolvable +revolve +revolved +revolver +revolvers +revolves +revolving +revote +revoted +revotes +revoting +revs +revue +revues +revulsed +revulsion +revulsive +revved +revving +rewake +rewaked +rewaken +rewakened +rewakening +rewakens +rewakes +rewaking +reward +rewardable +rewarded +rewarder +rewarders +rewarding +rewardingly +rewards +rewarm +rewarmed +rewarming +rewarms +rewash +rewashed +rewashes +rewashing +reweave +reweaves +reweaving +reweigh +reweighed +reweighing +reweighs +rewet +rewets +rewetted +rewetting +rewind +rewinder +rewinders +rewinding +rewinds +rewire +rewired +rewires +rewiring +rewoke +rewoken +reword +reworded +rewording +rewordings +rewords +rework +reworked +reworking +reworks +rewound +rewove +rewoven +rewrap +rewrapped +rewrapping +rewraps +rewrite +rewriter +rewriters +rewrites +rewriting +rewritten +rewrote +rex +rexes +reye +reykjavik +reykjavík +reynard +reynards +reynolds +rezone +rezoned +rezones +rezoning +rhabdocoele +rhabdocoeles +rhabdom +rhabdomancer +rhabdomancers +rhabdomancy +rhabdome +rhabdomere +rhabdomeres +rhabdomes +rhabdoms +rhabdomyoma +rhabdomyomas +rhabdomyomata +rhabdomyosarcoma +rhabdomyosarcomas +rhabdomyosarcomata +rhabdovirus +rhabdoviruses +rhadamanthine +rhadamanthus +rhadamanthys +rhaetia +rhaetian +rhaetians +rhamnose +rhamnoses +rhaphe +rhapsode +rhapsodes +rhapsodic +rhapsodical +rhapsodically +rhapsodies +rhapsodist +rhapsodists +rhapsodize +rhapsodized +rhapsodizes +rhapsodizing +rhapsody +rhatanies +rhatany +rhea +rheas +rhebok +rheboks +rhenish +rhenishes +rhenium +rheological +rheologically +rheologist +rheologists +rheology +rheometer +rheometers +rheostat +rheostatic +rheostats +rheotactic +rheotaxis +rheotaxises +rhesus +rhesuses +rhetor +rhetoric +rhetorical +rhetorically +rhetorician +rhetoricians +rhetors +rheum +rheumatic +rheumatically +rheumatics +rheumatism +rheumatoid +rheumatoidal +rheumatoidally +rheumatologist +rheumatologists +rheumatology +rheumy +rhinal +rhine +rhineland +rhinencephala +rhinencephalic +rhinencephalon +rhinestone +rhinestoned +rhinestones +rhinitis +rhino +rhinoceros +rhinoceroses +rhinologist +rhinologists +rhinology +rhinopharyngitis +rhinoplastic +rhinoplasties +rhinoplasty +rhinos +rhinoscopies +rhinoscopy +rhinovirus +rhinoviruses +rhizanthous +rhizobia +rhizobial +rhizobium +rhizocephalan +rhizocephalans +rhizocephalous +rhizoctonia +rhizoctonias +rhizogenetic +rhizogenic +rhizoid +rhizoidal +rhizoids +rhizomatous +rhizome +rhizomes +rhizomic +rhizophagous +rhizoplane +rhizoplanes +rhizopod +rhizopodan +rhizopodans +rhizopodous +rhizopods +rhizopus +rhizopuses +rhizosphere +rhizospheres +rhizotomies +rhizotomy +rho +rhodamine +rhodamines +rhode +rhodes +rhodesia +rhodesian +rhodesians +rhodium +rhodochrosite +rhodochrosites +rhododendron +rhododendrons +rhodolite +rhodolites +rhodomontade +rhodomontaded +rhodomontades +rhodomontading +rhodonite +rhodonites +rhodope +rhodopsin +rhodopsins +rhodora +rhodoras +rhomb +rhombencephalic +rhombencephalon +rhombencephalons +rhombi +rhombic +rhombohedra +rhombohedral +rhombohedron +rhombohedrons +rhomboid +rhomboidal +rhomboidei +rhomboideus +rhomboids +rhombs +rhombus +rhombuses +rhonchal +rhonchi +rhonchial +rhonchus +rhone +rhos +rhubarb +rhubarbs +rhumb +rhumba +rhumbaed +rhumbaing +rhumbas +rhumbs +rhus +rhuses +rhyme +rhymed +rhymeless +rhymer +rhymers +rhymes +rhymester +rhymesters +rhyming +rhynchocephalian +rhynchocephalians +rhyolite +rhyolites +rhyolitic +rhythm +rhythmic +rhythmical +rhythmically +rhythmicity +rhythmics +rhythmist +rhythmists +rhythmization +rhythmizations +rhythmize +rhythmized +rhythmizes +rhythmizing +rhythms +rhytidectomies +rhytidectomy +rhytidome +rhytidomes +rhyton +rhytons +rhône +rial +rials +rialto +rialtos +riant +riantly +riata +riatas +rib +ribald +ribaldries +ribaldry +ribalds +riband +ribands +ribavirin +ribavirins +ribband +ribbands +ribbed +ribbentrop +ribber +ribbers +ribbing +ribbings +ribbon +ribboned +ribbonfish +ribbonfishes +ribboning +ribbonlike +ribbons +ribbony +ribby +ribcage +ribcages +ribes +ribgrass +ribgrasses +riblet +riblets +riboflavin +ribonuclease +ribonucleases +ribonucleic +ribonucleoprotein +ribonucleoproteins +ribonucleoside +ribonucleosides +ribonucleotide +ribonucleotides +ribose +ribosomal +ribosome +ribosomes +ribozymes +ribs +ribwort +ribworts +rica +rican +ricans +riccio +riccocheted +riccocheting +riccochets +rice +ricebird +ricebirds +riced +ricer +ricercar +ricercare +ricercari +ricercars +ricers +rices +rich +richard +riche +richelieu +richen +richened +richening +richens +richer +riches +richest +richfield +richly +richmond +richness +richter +richweed +richweeds +ricin +ricing +ricinoleic +ricins +rick +ricked +ricketier +ricketiest +ricketiness +rickets +rickettsia +rickettsiae +rickettsial +rickettsioses +rickettsiosis +rickety +rickey +rickeys +ricking +rickrack +ricks +ricksha +rickshas +rickshaw +rickshaws +rico +ricochet +ricocheted +ricocheting +ricochets +ricotta +ricottas +ricrac +rictal +rictus +rictuses +rid +ridable +riddance +ridded +ridden +ridder +ridders +ridding +riddle +riddled +riddler +riddlers +riddles +riddling +ride +rideable +rider +riderless +riders +ridership +riderships +rides +ridesharing +ridesharings +ridge +ridgeback +ridgebacks +ridged +ridgeline +ridgelines +ridgeling +ridgelings +ridgepole +ridgepoles +ridges +ridgier +ridgiest +ridging +ridgling +ridglings +ridgy +ridicule +ridiculed +ridiculer +ridiculers +ridicules +ridiculing +ridiculous +ridiculously +ridiculousness +riding +ridings +ridley +ridleys +ridotto +ridottos +rids +riel +riels +riemann +riemannian +riesling +rieslings +rifampicin +rifampicins +rifampin +rifampins +rifamycin +rifamycins +rife +rifely +rifer +rifest +riff +riffed +riffian +riffians +riffing +riffle +riffled +riffler +rifflers +riffles +riffling +riffraff +riffs +rifle +riflebird +riflebirds +rifled +rifleman +riflemen +rifler +riflers +riflery +rifles +riflescope +riflescopes +rifling +rift +rifted +rifting +rifts +rig +rigadoon +rigadoons +rigamarole +rigamaroles +rigatoni +rigaudon +rigaudons +rigel +rigged +rigger +riggers +rigging +riggings +right +righted +righteous +righteously +righteousness +righter +righters +rightest +rightful +rightfully +rightfulness +righties +righting +rightish +rightism +rightist +rightists +rightly +rightmost +rightness +righto +rights +rightward +rightwards +righty +rigid +rigidification +rigidifications +rigidified +rigidifies +rigidify +rigidifying +rigidities +rigidity +rigidly +rigidness +rigmarole +rigmaroles +rigor +rigorism +rigorist +rigoristic +rigorists +rigorous +rigorously +rigorousness +rigors +rigs +rigueur +rijstafel +rijstafels +rijstaffel +rijstaffels +rijsttafel +rijsttaffel +rijsttaffels +riksmaal +riksmal +rile +riled +riles +riley +riling +rill +rille +rilles +rillet +rillets +rillettes +rills +rim +rima +rimbaud +rime +rimed +rimer +rimers +rimes +rimester +rimesters +rimfire +rimier +rimiest +riming +rimini +rimland +rimlands +rimless +rimmed +rimming +rimose +rimosely +rimosity +rimple +rimpled +rimples +rimpling +rimrock +rims +rimsky +rimy +rind +rinded +rinderpest +rinderpests +rinds +rinforzando +ring +ringbark +ringbarked +ringbarking +ringbarks +ringbolt +ringbolts +ringbone +ringbones +ringdove +ringdoves +ringed +ringent +ringer +ringers +ringgit +ringgits +ringhals +ringhalses +ringing +ringingly +ringleader +ringleaders +ringlet +ringleted +ringlets +ringlike +ringmaster +ringmasters +ringneck +ringnecks +rings +ringside +ringsider +ringsiders +ringsides +ringstraked +ringtail +ringtails +ringtaw +ringtoss +ringworm +ringworms +rink +rinks +rinky +rinsable +rinse +rinsed +rinser +rinsers +rinses +rinsible +rinsing +rio +rioja +riot +rioted +rioter +rioters +rioting +riotous +riotously +riotousness +riots +rip +riparian +ripcord +ripcords +ripe +ripely +ripen +ripened +ripener +ripeners +ripeness +ripening +ripens +riper +ripest +ripieni +ripieno +ripienos +riposte +riposted +ripostes +riposting +ripped +ripper +rippers +ripping +ripple +rippled +ripplegrass +ripplegrasses +rippler +ripplers +ripples +ripplet +ripplets +ripplier +rippliest +rippling +ripplingly +ripply +riprap +riprapped +riprapping +ripraps +rips +ripsaw +ripsaws +ripsnorter +ripsnorters +ripsnorting +ripstop +riptide +riptides +ripuarian +ripuarians +rise +risen +riser +risers +rises +risibilities +risibility +risible +risibles +risibly +rising +risings +risk +risked +risker +riskers +riskier +riskiest +riskiness +risking +riskless +risks +risky +risorgimento +risotto +risottos +risqué +rissole +rissoles +rissolé +ritalin +ritard +ritardando +ritards +rite +rites +ritornelli +ritornello +ritornellos +ritter +ritual +ritualism +ritualist +ritualistic +ritualistically +ritualists +rituality +ritualization +ritualizations +ritualize +ritualized +ritualizes +ritualizing +ritually +rituals +ritz +ritzier +ritziest +ritziness +ritzy +rivage +rivages +rival +rivaled +rivaling +rivalled +rivalling +rivalries +rivalrous +rivalry +rivals +rive +rived +riven +river +riverbank +riverbanks +riverbed +riverbeds +riverboat +riverboats +riverfront +riverfronts +riverhead +riverheads +riverine +riverines +rivers +riverside +riversides +riverward +riverwards +riverweed +riverweeds +rives +rivet +riveted +riveter +riveters +riveting +rivetingly +rivets +riviera +riving +rivière +rivulet +rivulets +riyadh +riyal +rizzio +rna +rns +roach +roached +roaches +roaching +road +roadability +roadbed +roadbeds +roadblock +roadblocks +roadholding +roadhouse +roadhouses +roadie +roadies +roadkill +roadkills +roadless +roadrunner +roadrunners +roads +roadside +roadsides +roadstead +roadsteads +roadster +roadsters +roadway +roadways +roadwork +roadworthier +roadworthiest +roadworthiness +roadworthy +roady +roam +roamed +roamer +roamers +roaming +roams +roan +roanoke +roans +roar +roared +roarer +roarers +roaring +roaringly +roars +roast +roasted +roaster +roasters +roasting +roasts +rob +robalo +robalos +roband +robands +robbed +robber +robberies +robbers +robbery +robbing +robe +robed +robert +robertson +robes +robespierre +robin +robing +robins +robinson +roble +robles +roborant +roborants +robot +robotic +robotically +roboticize +roboticized +roboticizes +roboticizing +robotics +robotism +robotistic +robotization +robotizations +robotize +robotized +robotizes +robotizing +robots +robs +robust +robusta +robustious +robustiously +robustiousness +robustly +robustness +roc +rocaille +rocambole +rocamboles +roche +rochefoucauld +rochelle +roches +rochester +rochet +rochets +rock +rock'n'roll +rockabilly +rockaby +rockabye +rockaway +rockaways +rockbound +rocked +rockefeller +rocker +rockeries +rockers +rockery +rocket +rocketed +rocketeer +rocketeers +rocketing +rocketry +rockets +rocketsonde +rocketsondes +rockfall +rockfalls +rockfish +rockfishes +rockhopper +rockhoppers +rockhounding +rockier +rockies +rockiest +rockiness +rocking +rockingly +rocklike +rockling +rocklings +rockoon +rockoons +rockrose +rockroses +rocks +rockshaft +rockshafts +rockslide +rockslides +rockweed +rockweeds +rockwork +rocky +rococo +rocs +rod +rodded +rodding +rode +rodent +rodenticide +rodenticides +rodents +rodeo +rodeos +rodes +rodin +rodless +rodlike +rodman +rodmen +rodomontade +rodomontaded +rodomontades +rodomontading +rods +roe +roebuck +roebucks +roentgen +roentgenize +roentgenized +roentgenizes +roentgenizing +roentgenogram +roentgenograms +roentgenograph +roentgenographic +roentgenographically +roentgenographs +roentgenography +roentgenologic +roentgenological +roentgenologically +roentgenologist +roentgenologists +roentgenology +roentgenoscope +roentgenoscopes +roentgenoscopic +roentgenoscopy +roentgenotherapies +roentgenotherapy +roentgens +roes +rogation +rogations +rogatory +roger +roget +rogue +rogued +rogueing +rogueries +roguery +rogues +roguing +roguish +roguishly +roguishness +roil +roiled +roilier +roiliest +roiling +roils +roily +roister +roistered +roisterer +roisterers +roistering +roisterous +roisterously +roisters +rolamite +rolamites +roland +role +roles +rolf +rolfed +rolfer +rolfers +rolfing +rolfs +roll +rollaway +rollback +rollbacks +rolle +rolled +roller +rollers +rollick +rollicked +rollicking +rollickingly +rollicks +rollicksome +rollicky +rolling +rollmops +rollout +rollouts +rollover +rollovers +rolls +rolltop +rollway +rollways +rolodex +roly +roma +romagna +romaic +romaine +roman +romance +romanced +romancer +romancers +romances +romancing +romanesque +romania +romanian +romanians +romanic +romanics +romanies +romanism +romanist +romanistic +romanists +romanization +romanizations +romanize +romanized +romanizes +romanizing +romano +romanoff +romanoffs +romanov +romanovs +romans +romansch +romansh +romantic +romantically +romanticism +romanticist +romanticists +romanticization +romanticizations +romanticize +romanticized +romanticizes +romanticizing +romantics +romany +romaunt +romaunts +romblon +rome +romeldale +romeldales +romeo +romeos +romish +romishly +romishness +rommel +romney +romp +romped +romper +rompers +romping +romps +roms +romulus +roncevaux +rondeau +rondeaux +rondel +rondelet +rondelets +rondelle +rondelles +rondels +rondo +rondos +rondure +rondures +ronnel +ronnels +ronyon +ronyons +rood +roods +roof +roofed +roofer +roofers +roofing +roofless +rooflike +roofline +rooflines +roofs +rooftop +rooftops +rooftree +rooftrees +rook +rooked +rookeries +rookery +rookie +rookies +rooking +rooks +rooky +room +roomed +roomer +roomers +roomette +roomettes +roomful +roomfuls +roomier +roomiest +roomily +roominess +rooming +roommate +roommates +rooms +roomy +roorback +roorbacks +roosevelt +roost +roosted +rooster +roosterfish +roosterfishes +roosters +roosting +roosts +root +rootage +rootages +rooted +rootedness +rooter +rooters +roothold +rootholds +rootier +rootiest +rootiness +rooting +rootless +rootlessness +rootlet +rootlets +rootlike +roots +rootstalk +rootstalks +rootstock +rootstocks +rootworm +rootworms +rooty +rope +roped +ropedancer +ropedancers +ropedancing +ropelike +roper +ropers +ropery +ropes +ropewalk +ropewalker +ropewalkers +ropewalks +ropeway +ropeways +ropey +ropier +ropiest +ropily +ropiness +roping +ropy +roque +roquefort +roquelaure +roquelaures +roquet +roqueted +roqueting +roquets +roquette +rorqual +rorquals +rorschach +rosa +rosacea +rosaceous +rosalind +rosanilin +rosaniline +rosanilines +rosanilins +rosarian +rosarians +rosaries +rosary +roscius +roscoe +roscoes +rose +roseate +roseately +rosebay +rosebays +rosebud +rosebuds +rosebush +rosebushes +rosefish +rosefishes +roselle +roselles +rosemaries +rosemary +rosencrantz +roseola +roseolar +roseolas +roseroot +roseroots +roses +rosetta +rosette +rosettes +rosewater +rosewood +rosewoods +rosh +rosicrucian +rosicrucianism +rosicrucians +rosier +rosiest +rosily +rosin +rosined +rosiness +rosining +rosins +rosinweed +rosinweeds +rosiny +rossetti +rossini +rostella +rostellar +rostellate +rostellum +roster +rosters +rostock +rostra +rostral +rostrally +rostrate +rostrum +rostrums +rosy +rosé +rosés +rot +rota +rotameter +rotameters +rotarian +rotarians +rotaries +rotary +rotas +rotatable +rotate +rotated +rotates +rotating +rotation +rotational +rotationally +rotations +rotative +rotatively +rotator +rotatores +rotators +rotatory +rotavirus +rotaviruses +rote +rotenone +rotes +rotgut +rothschild +rothschilds +roti +rotifer +rotiferal +rotiferous +rotifers +rotiform +rotisserie +rotisseries +rotl +rotls +roto +rotogravure +rotogravures +rotor +rotorcraft +rotorcrafts +rotors +rotos +rototill +rototilled +rototiller +rototillers +rototilling +rototills +rots +rotted +rotten +rottener +rottenest +rottenly +rottenness +rottenstone +rottenstones +rotter +rotterdam +rotters +rotting +rottweiler +rottweilers +rotund +rotunda +rotundas +rotundity +rotundly +rotundness +roturier +roturiers +rouble +roubles +rouen +rouge +rouged +rouges +rough +roughage +roughback +roughbacks +roughcast +roughcaster +roughcasters +roughcasting +roughcasts +roughdried +roughdries +roughdry +roughdrying +roughed +roughen +roughened +roughening +roughens +rougher +roughers +roughest +roughhew +roughhewed +roughhewing +roughhewn +roughhews +roughhouse +roughhoused +roughhouses +roughhousing +roughies +roughing +roughish +roughleg +roughlegs +roughly +roughneck +roughnecks +roughness +roughrider +roughriders +roughs +roughshod +roughy +rouging +rouille +roulade +roulades +rouleau +rouleaus +rouleaux +roulette +rouletted +roulettes +rouletting +roumanian +round +roundabout +roundaboutness +roundabouts +rounded +roundedness +roundel +roundelay +roundelays +roundels +rounder +rounders +roundest +roundhead +roundheaded +roundheadedness +roundheads +roundhouse +roundhouses +rounding +roundish +roundishness +roundlet +roundlets +roundly +roundness +roundoff +rounds +roundsman +roundsmen +roundtable +roundtables +roundtrip +roundtrips +roundup +roundups +roundwood +roundworm +roundworms +roup +roups +rouse +rouseabout +rouseabouts +roused +rousement +rousements +rouser +rousers +rouses +rousing +rousingly +rousseau +rousseauism +rousseauist +rousseauistic +rousseauists +roussillon +roust +roustabout +roustabouts +rousted +rouster +rousters +rousting +rousts +rout +route +routed +routeman +routemen +router +routers +routes +routeway +routeways +routine +routinely +routines +routing +routings +routinism +routinist +routinists +routinization +routinizations +routinize +routinized +routinizes +routinizing +routs +roux +roué +roués +rove +roved +rover +rovers +roves +roving +row +rowan +rowanberries +rowanberry +rowans +rowboat +rowboats +rowdier +rowdies +rowdiest +rowdily +rowdiness +rowdy +rowdyish +rowdyism +rowed +rowel +roweled +roweling +rowels +rowen +rowens +rower +rowers +rowing +rowlandson +rowlock +rowlocks +rows +royal +royalism +royalist +royalists +royally +royalmast +royalmasts +royals +royalties +royalty +rpm +rsvp +ruana +ruanas +rub +rubaiyat +rubasse +rubasses +rubato +rubatos +rubbed +rubber +rubberier +rubberiest +rubberize +rubberized +rubberizes +rubberizing +rubberlike +rubberneck +rubbernecked +rubbernecker +rubberneckers +rubbernecking +rubbernecks +rubbers +rubberstamp +rubberstamps +rubbery +rubbing +rubbings +rubbish +rubbishing +rubbishy +rubble +rubbled +rubbles +rubblework +rubbling +rubbly +rubdown +rubdowns +rube +rubefacient +rubefacients +rubefaction +rubefactions +rubella +rubellite +rubellites +rubenesque +rubens +rubeola +rubeolar +rubes +rubescence +rubescent +rubicon +rubicund +rubicundity +rubidium +rubies +rubiginose +rubiginous +rubik +rubious +ruble +rubles +ruboff +ruboffs +rubout +rubouts +rubredoxin +rubredoxins +rubric +rubrical +rubrically +rubricate +rubricated +rubricates +rubricating +rubrication +rubrications +rubricator +rubricators +rubrician +rubricians +rubrics +rubs +rubus +ruby +rubythroat +rubythroats +rubáiyát +ruche +ruched +ruches +ruching +ruck +rucked +rucking +rucks +rucksack +rucksacks +ruckus +ruckuses +ruction +ructions +rudbeckia +rudd +rudder +rudderfish +rudderfishes +rudderless +rudderpost +rudderposts +rudders +rudderstock +rudderstocks +ruddier +ruddiest +ruddily +ruddiness +ruddle +ruddled +ruddles +ruddling +ruddock +ruddocks +rudds +ruddy +rude +rudely +rudeness +rudenesses +ruder +ruderal +ruderals +rudest +rudiment +rudimental +rudimentarily +rudimentariness +rudimentary +rudiments +rudolf +rue +rued +rueful +ruefully +ruefulness +ruer +ruers +rues +rufescence +rufescent +ruff +ruffe +ruffed +ruffes +ruffian +ruffianism +ruffianly +ruffians +ruffing +ruffle +ruffled +ruffler +rufflers +ruffles +ruffling +ruffly +ruffs +rufiyaa +rufiyaas +rufous +rufus +rug +ruga +rugae +rugate +rugby +rugged +ruggedization +ruggedizations +ruggedize +ruggedized +ruggedizes +ruggedizing +ruggedly +ruggedness +rugola +rugosa +rugose +rugosely +rugosity +rugous +rugs +rugulose +ruin +ruinable +ruinate +ruination +ruinations +ruined +ruiner +ruiners +ruing +ruining +ruinous +ruinously +ruinousness +ruins +rulable +rule +ruled +ruleless +ruler +rulers +rulership +rulerships +rules +rulier +ruliest +ruling +rulings +ruly +rum +rumaki +rumakis +rumania +rumanian +rumanians +rumba +rumbaed +rumbaing +rumbas +rumble +rumbled +rumbler +rumblers +rumbles +rumbling +rumblingly +rumblings +rumbly +rumbustious +rumbustiously +rumbustiousness +rumen +rumens +rumina +ruminal +ruminant +ruminantly +ruminants +ruminate +ruminated +ruminates +ruminating +rumination +ruminations +ruminative +ruminatively +ruminator +ruminators +rummage +rummaged +rummager +rummagers +rummages +rummaging +rummer +rummers +rummest +rummier +rummies +rummiest +rummy +rumor +rumored +rumoring +rumormonger +rumormongered +rumormongering +rumormongers +rumors +rump +rumpelstiltskin +rumple +rumpled +rumples +rumplier +rumpliest +rumpling +rumply +rumps +rumpus +rumpuses +rumrunner +rumrunners +rums +run +runabout +runabouts +runagate +runagates +runaround +runarounds +runaway +runaways +runback +runbacks +runcible +runcinate +rundle +rundles +rundlet +rundlets +rundown +rundowns +rune +runes +rung +rungs +runic +runless +runlet +runlets +runnable +runnel +runnels +runner +runners +runnier +runniest +running +runnings +runny +runnymede +runoff +runoffs +runout +runouts +runover +runovers +runs +runt +runtime +runtiness +runtish +runts +runty +runway +runways +runza +runzas +rupee +rupees +rupiah +rupiahs +rupicolous +rupturable +rupture +ruptured +ruptures +rupturing +rural +ruralism +ruralist +ruralists +ruralities +rurality +ruralization +ruralizations +ruralize +ruralized +ruralizes +ruralizing +rurally +rurban +ruritan +ruritania +ruritanian +ruritans +ruse +ruses +rush +rushed +rushee +rushees +rusher +rushers +rushes +rushier +rushiest +rushing +rushlight +rushlights +rushmore +rushy +rusine +rusk +ruskin +ruskinian +rusks +russell +russet +russeting +russets +russetting +russia +russian +russianization +russianizations +russianize +russianized +russianizes +russianizing +russianness +russians +russification +russifications +russified +russifies +russify +russifying +russki +russkie +russkies +russkis +russky +russo +russophile +russophiles +russophilia +russophobe +russophobes +russophobia +rust +rustable +rusted +rustic +rustical +rustically +rusticate +rusticated +rusticates +rusticating +rustication +rustications +rusticator +rusticators +rusticities +rusticity +rustics +rustier +rustiest +rustily +rustiness +rusting +rustle +rustled +rustler +rustlers +rustles +rustless +rustling +rustlingly +rustproof +rustproofed +rustproofing +rustproofs +rusts +rusty +rut +rutabaga +rutabagas +ruth +ruthenia +ruthenian +ruthenians +ruthenic +ruthenious +ruthenium +rutherford +rutherfordium +rutherfords +ruthful +ruthfully +ruthfulness +ruthless +ruthlessly +ruthlessness +rutilant +rutile +rutiles +ruts +rutted +ruttier +ruttiest +ruttiness +rutting +ruttish +ruttishly +ruttishness +rutty +ruwenzori +rwanda +rwandan +rwandans +rya +ryas +rye +ryegrass +ryegrasses +ryes +ryukyu +râle +râles +réaumur +réchauffé +réclame +régime +régimes +régisseur +régisseurs +rémoulade +répondez +réseau +réseaus +réseaux +résistance +résumé +résumés +réunion +rôle +rôles +röntgen +röntgens +rügen +s +s'le +s'n +s'ns +saanen +saaremaa +saarland +saarlander +saarlanders +sabadilla +sabadillas +sabal +sabals +sabaoth +sabayon +sabayons +sabbat +sabbatarian +sabbatarianism +sabbatarians +sabbath +sabbaths +sabbatic +sabbatical +sabbaticals +sabbats +sabellian +sabellians +saber +sabered +sabering +sabermetrician +sabermetricians +sabermetrics +sabers +sabian +sabians +sabin +sabine +sabines +sabins +sable +sablefish +sablefishes +sables +sabot +sabotage +sabotaged +sabotages +sabotaging +saboteur +saboteurs +sabots +sabra +sabras +sabre +sabred +sabres +sabring +sabulose +sabulosity +sabulous +sac +sacahuista +sacahuiste +sacajawea +sacaton +sacatons +saccade +saccades +saccadic +saccate +saccharase +saccharases +saccharate +saccharates +saccharic +saccharide +saccharides +saccharification +saccharifications +saccharified +saccharifies +saccharify +saccharifying +saccharimeter +saccharimeters +saccharimetry +saccharin +saccharine +saccharinely +saccharinity +saccharoid +saccharoidal +saccharometer +saccharometers +saccharomyces +saccharomycete +saccharomycetes +saccharomycetic +saccharomycetous +saccharose +saccharoses +saccular +sacculate +sacculated +sacculation +sacculations +saccule +saccules +sacculi +sacculus +sacerdotal +sacerdotalism +sacerdotalist +sacerdotalists +sacerdotally +sachem +sachemic +sachems +sacher +sachet +sacheted +sachets +sack +sackbut +sackbuts +sackcloth +sacked +sacker +sackers +sackful +sackfuls +sacking +sackings +sacks +saclike +sacque +sacques +sacra +sacral +sacrament +sacramental +sacramentalism +sacramentalist +sacramentalists +sacramentally +sacramentals +sacramentarian +sacramentarianism +sacramentarians +sacramento +sacraments +sacraria +sacrarium +sacred +sacredly +sacredness +sacrifice +sacrificed +sacrificer +sacrificers +sacrifices +sacrificial +sacrificially +sacrificing +sacrificingly +sacrilege +sacrileges +sacrilegious +sacrilegiously +sacrilegiousness +sacrilegist +sacrilegists +sacristan +sacristans +sacristies +sacristy +sacrococcygeal +sacroiliac +sacroiliacs +sacrolumbar +sacrosanct +sacrosanctity +sacrosciatic +sacrum +sacs +sad +sadden +saddened +saddening +saddens +sadder +saddest +saddhu +saddhus +saddle +saddleback +saddlebacks +saddlebag +saddlebags +saddlebow +saddlebows +saddlebred +saddlebreds +saddlecloth +saddlecloths +saddled +saddleless +saddler +saddleries +saddlers +saddlery +saddles +saddletree +saddletrees +saddling +sadducean +sadducee +sadduceeism +sadducees +sadhe +sadhes +sadhu +sadhus +sadiron +sadirons +sadism +sadist +sadistic +sadistically +sadists +sadly +sadness +sadnesses +sadomasochism +sadomasochist +sadomasochistic +sadomasochists +safar +safari +safaris +safe +safecracker +safecrackers +safecracking +safeguard +safeguarded +safeguarding +safeguards +safekeeping +safelight +safelights +safely +safeness +safer +safes +safest +safetied +safeties +safety +safetying +safetyman +safetymen +safflower +safflowers +saffron +safranin +safranine +safranines +safranins +safrole +safroles +sag +saga +sagacious +sagaciously +sagaciousness +sagacity +sagamore +sagamores +sagas +sage +sagebrush +sagebrushes +sagely +sageness +sager +sages +sagest +saggar +saggars +sagged +sagger +saggers +sagging +saggy +sagitta +sagittal +sagittally +sagittarian +sagittarians +sagittarius +sagittate +sago +sagos +sagrada +sags +saguaro +saguaros +sahaptian +sahara +saharan +sahel +sahelian +sahib +sahibs +sahuaro +sahuaros +said +saiga +saigas +saigon +sail +sailable +sailboard +sailboarded +sailboarder +sailboarders +sailboarding +sailboards +sailboat +sailboater +sailboaters +sailboating +sailboats +sailcloth +sailed +sailer +sailers +sailfish +sailfishes +sailing +sailor +sailorman +sailormen +sailors +sailplane +sailplaned +sailplaner +sailplaners +sailplanes +sailplaning +sails +saimin +saimins +sainfoin +sainfoins +saint +saintdom +sainted +sainthood +sainting +saintlier +saintliest +saintlike +saintliness +saintly +saints +saintship +saipan +saipanese +sais +saith +saithe +saiva +saivas +saivism +sake +saker +sakers +sakes +saki +sakishima +sakti +saktism +sal +salaam +salaamed +salaaming +salaams +salability +salable +salableness +salably +salacious +salaciously +salaciousness +salacity +salad +saladin +salads +salal +salals +salamanca +salamander +salamanders +salamandrine +salami +salamis +salariat +salaried +salaries +salary +salaryman +salarymen +salbutamol +salbutamols +salchow +salchows +sale +saleable +salem +salep +saleps +saleratus +salerno +saleroom +salerooms +sales +salesclerk +salesclerks +salesgirl +salesgirls +salesian +salesians +salesladies +saleslady +salesman +salesmanship +salesmen +salespeople +salesperson +salespersons +salesroom +salesrooms +saleswoman +saleswomen +salian +salians +salic +salicin +salicins +salicylate +salicylates +salicylic +salicylism +salience +saliences +saliencies +saliency +salient +salientian +salientians +saliently +salientness +salients +saliferous +salimeter +salimeters +salimetric +salimetry +salina +salinas +saline +salinity +salinization +salinizations +salinize +salinized +salinizes +salinizing +salinometer +salinometers +salinometric +salinometry +salique +salisbury +salish +salishan +saliva +salivary +salivate +salivated +salivates +salivating +salivation +salivator +salivators +salk +sallet +sallets +sallied +sallies +sallow +sallowed +sallower +sallowest +sallowing +sallowish +sallowly +sallowness +sallows +sally +sallying +salmacis +salmagundi +salmagundis +salmi +salmis +salmon +salmonberries +salmonberry +salmonella +salmonellae +salmonellas +salmonelloses +salmonellosis +salmonid +salmonids +salmonoid +salmonoids +salmons +salol +salols +salome +salometer +salometers +salon +salonika +salons +saloon +saloonkeeper +saloonkeepers +saloons +saloop +saloops +salopian +salopians +salp +salpa +salpas +salpiform +salpiglossis +salpingectomies +salpingectomy +salpinges +salpingian +salpingitis +salpinx +salps +sals +salsa +salsas +salsifies +salsify +salt +saltarelli +saltarello +saltarellos +saltation +saltations +saltatorial +saltatory +saltbox +saltboxes +saltbush +saltbushes +saltcellar +saltcellars +salted +salter +saltern +salterns +salters +saltgrass +saltier +saltiest +saltily +saltimbocca +saltimboccas +saltine +saltines +saltiness +salting +saltire +saltires +saltish +saltless +saltlike +saltness +saltpeter +salts +saltshaker +saltshakers +saltwater +saltworks +saltwort +salty +salubrious +salubriously +salubriousness +salubrity +saluki +salukis +saluretic +saluretics +salutarily +salutariness +salutary +salutation +salutational +salutations +salutatorian +salutatorians +salutatories +salutatory +salute +saluted +saluter +saluters +salutes +salutiferous +saluting +salvable +salvador +salvadoran +salvadorans +salvadorean +salvadoreans +salvadorian +salvage +salvageability +salvageable +salvaged +salvager +salvagers +salvages +salvaging +salvarsan +salvation +salvational +salvationism +salvationist +salvationists +salve +salved +salver +salverform +salvers +salves +salvia +salvias +salvific +salvifically +salving +salvo +salvoes +salvor +salvors +salvos +salzburg +samara +samaras +samaria +samaritan +samaritans +samarium +samarkand +samarskite +samarskites +samba +sambaed +sambaing +sambal +sambar +sambars +sambas +sambo +sambuca +sambucas +sambur +samburs +same +samekh +sameness +samian +samians +samiel +samiels +samisen +samisens +samite +samites +samizdat +samlet +samlets +sammarinese +sammarinesi +samnite +samnites +samnium +samoa +samoan +samoans +samos +samosa +samosas +samothrace +samothráki +samovar +samovars +samoyed +samoyede +samoyedes +samoyedic +samoyeds +samp +sampan +sampans +samphire +samphires +sample +sampled +sampler +samplers +samples +sampling +samplings +samsara +samson +samsonian +samsons +samuel +samurai +samurais +san +san'a +sana +sanaa +sanataria +sanatarium +sanatariums +sanative +sanatoria +sanatorium +sanatoriums +sanbenito +sanbenitos +sancerre +sancta +sanctification +sanctifications +sanctified +sanctifier +sanctifiers +sanctifies +sanctify +sanctifying +sanctimonious +sanctimoniously +sanctimoniousness +sanctimony +sanction +sanctionable +sanctioned +sanctioning +sanctions +sanctities +sanctity +sanctuaries +sanctuary +sanctum +sanctums +sanctus +sanctuses +sand +sandal +sandaled +sandals +sandalwood +sandalwoods +sandarac +sandaracs +sandbag +sandbagged +sandbagger +sandbaggers +sandbagging +sandbags +sandbank +sandbanks +sandbar +sandbars +sandblast +sandblasted +sandblaster +sandblasters +sandblasting +sandblasts +sandblindness +sandbox +sandboxes +sandbur +sandburs +sanded +sander +sanderling +sanderlings +sanders +sandfish +sandfishes +sandfly +sandglass +sandglasses +sandgrouse +sandhi +sandhill +sandhis +sandhog +sandhogs +sandier +sandiest +sandiness +sanding +sandinista +sandinistas +sandlot +sandlots +sandlotter +sandlotters +sandman +sandmen +sandpainting +sandpaper +sandpapered +sandpapering +sandpapers +sandpapery +sandpile +sandpiles +sandpiper +sandpipers +sandpit +sandpits +sands +sandshoe +sandshoes +sandsoap +sandspur +sandspurs +sandstone +sandstorm +sandstorms +sandwich +sandwiched +sandwiches +sandwiching +sandworm +sandworms +sandwort +sandworts +sandy +sane +sanely +saneness +saner +sanest +sanforized +sang +sangaree +sangarees +sangfroid +sangreal +sangria +sangrias +sanguicolous +sanguinaria +sanguinarias +sanguinarily +sanguinary +sanguine +sanguinely +sanguineness +sanguineous +sanguinity +sanguinolent +sanhedrim +sanhedrin +sanicle +sanicles +sanidine +sanidines +sanies +sanified +sanifies +sanify +sanifying +sanious +sanitaire +sanitaria +sanitarian +sanitarians +sanitarily +sanitarium +sanitariums +sanitary +sanitate +sanitated +sanitates +sanitating +sanitation +sanitization +sanitizations +sanitize +sanitized +sanitizer +sanitizers +sanitizes +sanitizing +sanitoria +sanitorium +sanitoriums +sanity +sank +sankhya +sannup +sannups +sannyasi +sannyasin +sannyasins +sannyasis +sanpaku +sanpakus +sans +sansculotte +sansculottes +sansculottic +sansculottish +sansculottism +sansei +sanseis +sanserif +sanserifs +sansevieria +sansevierias +sanskrit +sanskritic +sanskritist +sanskritists +santa +santalol +santalols +santander +santas +santee +santees +santeria +santiago +santir +santirs +santo +santolina +santolinas +santonica +santonicas +santonin +santonins +santorini +santos +santour +santours +sao +sap +sapajou +sapajous +saphar +saphead +sapheaded +sapheads +saphena +saphenae +saphenous +sapid +sapidity +sapience +sapiens +sapient +sapiently +sapless +saplessness +sapling +saplings +sapodilla +sapogenin +sapogenins +saponaceous +saponaceousness +saponated +saponifiable +saponification +saponified +saponifier +saponifiers +saponifies +saponify +saponifying +saponin +saponins +saponite +saponites +sapor +saporific +saporous +sapota +sapotas +sapote +sapotes +sappanwood +sappanwoods +sapped +sapper +sappers +sapphic +sapphics +sapphire +sapphires +sapphirine +sapphirines +sapphism +sappho +sappier +sappiest +sappily +sappiness +sapping +sappy +sapraemia +sapremia +sapremic +saprobe +saprobes +saprobial +saprobic +saprobically +saprobiological +saprobiologist +saprobiologists +saprobiology +saprogenic +saprogenicity +saprogenous +saprolite +saprolites +sapropel +sapropelic +sapropels +saprophagous +saprophyte +saprophytes +saprophytic +saprophytically +saprozoic +saps +sapsago +sapsagos +sapsucker +sapsuckers +sapwood +saraband +sarabande +sarabandes +sarabands +saracen +saracenic +saracens +saragossa +sarah +sarajevo +saran +sarape +sarapes +sarasvati +saratoga +sarawak +sarcasm +sarcasms +sarcastic +sarcastically +sarcenet +sarcenets +sarcodinian +sarcodinians +sarcoid +sarcoidoses +sarcoidosis +sarcoids +sarcolactic +sarcolemma +sarcolemmal +sarcolemmas +sarcoma +sarcomas +sarcomata +sarcomatoid +sarcomatosis +sarcomatous +sarcomere +sarcomeres +sarcophagi +sarcophagic +sarcophagous +sarcophagus +sarcophaguses +sarcoplasm +sarcoplasmatic +sarcoplasmic +sarcoptic +sarcosomal +sarcosome +sarcosomes +sarcostyle +sarcostyles +sarcous +sard +sardanapalus +sardar +sardars +sardine +sardined +sardines +sardinia +sardinian +sardinians +sardining +sardius +sardiuses +sardonic +sardonically +sardonicism +sardonyx +sardonyxes +sards +saree +sarema +sargasso +sargassos +sargassum +sargassums +sarge +sarges +sargon +sargonid +sari +sarin +saris +sark +sarkese +sarmatia +sarmatian +sarmatians +sarmentose +sarod +sarode +sarodes +sarodist +sarodists +sarods +sarong +sarongs +sarpedon +sarracenia +sarsaparilla +sarsaparillas +sarsenet +sarsenets +sartorial +sartorially +sartorii +sartorius +sartre +sartrean +sarum +sarus +sasanian +sasanid +sasanids +sash +sashay +sashayed +sashaying +sashays +sashed +sashes +sashimi +sashimis +sashing +saskatchewan +saskatoon +saskatoons +sasquatch +sass +sassabies +sassaby +sassafras +sassanian +sassanid +sassanide +sassed +sasses +sassier +sassies +sassiest +sassily +sassiness +sassing +sassoon +sasswood +sasswoods +sassy +sastruga +sastrugas +sat +satan +satang +satangs +satanic +satanical +satanically +satanism +satanist +satanists +satay +satchel +satcheled +satchelful +satchelfuls +satchels +sate +sated +sateen +satellite +satellites +satem +sates +sati +satiability +satiable +satiably +satiate +satiated +satiates +satiating +satiation +satiations +satiety +satin +satinet +satinets +sating +satinized +satins +satinwood +satinwoods +satiny +satire +satires +satiric +satirical +satirically +satirist +satirists +satirizable +satirization +satirize +satirized +satirizes +satirizing +satis +satisfaction +satisfactions +satisfactorily +satisfactoriness +satisfactory +satisfiability +satisfiable +satisfied +satisfiedly +satisfier +satisfiers +satisfies +satisfy +satisfying +satisfyingly +satori +satrap +satrapies +satraps +satrapy +satsuma +satsumas +saturable +saturant +saturants +saturate +saturated +saturates +saturating +saturation +saturations +saturator +saturators +saturday +saturdays +saturn +saturnalia +saturnalian +saturnalianly +saturnalias +saturnian +saturniid +saturniids +saturnine +saturninely +saturnism +satyagraha +satyr +satyriasis +satyric +satyrical +satyrid +satyrids +satyrs +saté +sauce +sauceboat +sauceboats +saucebox +sauceboxes +sauced +saucepan +saucepans +saucepot +saucepots +saucer +saucerlike +saucers +sauces +saucier +sauciest +saucily +sauciness +saucing +saucy +saudi +saudis +sauerbraten +sauerkraut +sauger +saugers +sauk +sauks +saul +sault +saults +saumur +sauna +saunas +saunter +sauntered +saunterer +saunterers +sauntering +saunters +saurel +saurels +saurian +saurians +sauries +saurischian +saurischians +sauropod +sauropodous +sauropods +saury +sausage +sausages +sauterne +sauternes +sauté +sautéed +sautéing +sautés +sauvignon +savable +savage +savaged +savagely +savageness +savageries +savagery +savages +savaging +savagism +savagisms +savai'i +savaii +savanna +savannah +savannahs +savannas +savant +savants +savarin +savarins +savate +save +saveable +saved +saveloy +saveloys +saver +savers +saves +savin +savine +savines +saving +savings +savins +savior +saviors +saviour +saviours +savoir +savonarola +savor +savored +savorer +savorers +savories +savorily +savoriness +savoring +savorless +savorous +savors +savory +savour +savoured +savouries +savouring +savours +savoury +savoy +savoyard +savoyards +savvied +savvier +savvies +savviest +savvily +savvy +savvying +saw +sawbones +sawboneses +sawbuck +sawbucks +sawdust +sawdusty +sawed +sawer +sawers +sawfish +sawfishes +sawflies +sawfly +sawhorse +sawhorses +sawing +sawlike +sawlog +sawlogs +sawmill +sawmills +sawn +sawney +sawneys +saws +sawtimber +sawtimbers +sawtooth +sawyer +sawyers +sax +saxatile +saxe +saxes +saxhorn +saxhorns +saxicoline +saxicolous +saxifrage +saxifrages +saxitoxin +saxitoxins +saxon +saxondom +saxonies +saxonism +saxons +saxony +saxophone +saxophones +saxophonic +saxophonist +saxophonists +saxtuba +saxtubas +say +sayable +sayer +sayers +sayest +saying +sayings +sayonara +says +sayyid +sazerac +saëns +saône +scab +scabbard +scabbarded +scabbarding +scabbards +scabbed +scabbier +scabbiest +scabbily +scabbiness +scabbing +scabble +scabbled +scabbles +scabbling +scabby +scabies +scabietic +scabiosa +scabiosas +scabious +scabiouses +scabland +scablands +scabrous +scabrously +scabrousness +scabs +scad +scads +scaffold +scaffolded +scaffolding +scaffoldings +scaffolds +scag +scagliola +scagliolas +scalability +scalable +scalade +scalades +scalado +scalados +scalage +scalages +scalar +scalare +scalares +scalariform +scalariformly +scalars +scalawag +scalawags +scald +scalded +scalding +scaldingly +scalds +scale +scaled +scaleless +scalelike +scalene +scaleni +scalenus +scaler +scalers +scales +scalier +scaliest +scaliness +scaling +scall +scallion +scallions +scallop +scalloped +scalloper +scallopers +scalloping +scallopini +scallops +scalls +scallywag +scallywags +scalogram +scalograms +scaloppine +scaloppini +scalp +scalped +scalpel +scalpels +scalper +scalpers +scalping +scalps +scaly +scam +scammed +scammer +scammers +scamming +scammonies +scammony +scamp +scamped +scamper +scampered +scampering +scampers +scampi +scamping +scampish +scamps +scams +scan +scandal +scandale +scandalization +scandalizations +scandalize +scandalized +scandalizer +scandalizers +scandalizes +scandalizing +scandalmonger +scandalmongering +scandalmongers +scandalous +scandalously +scandalousness +scandals +scandent +scandia +scandian +scandians +scandic +scandinavia +scandinavian +scandinavians +scandium +scannable +scanned +scanner +scanners +scanning +scans +scansion +scansions +scansorial +scant +scanted +scanter +scantest +scantier +scanties +scantiest +scantily +scantiness +scanting +scantling +scantlings +scantly +scantness +scants +scanty +scape +scaped +scapegoat +scapegoated +scapegoating +scapegoatism +scapegoats +scapegrace +scapegraces +scapes +scaphocephalic +scaphocephaly +scaphoid +scaphoids +scaphopod +scaphopods +scaping +scapolite +scapolites +scapose +scapula +scapulae +scapular +scapulars +scapulary +scapulas +scapuloclavicular +scar +scarab +scarabaei +scarabaeid +scarabaeids +scarabaeus +scarabaeuses +scaraboid +scarabs +scaramouch +scaramouche +scaramouches +scarce +scarcely +scarceness +scarcer +scarcest +scarcities +scarcity +scare +scarecrow +scarecrows +scared +scaredy +scarehead +scareheads +scaremonger +scaremongering +scaremongers +scarer +scarers +scares +scarf +scarfed +scarfing +scarfpin +scarfpins +scarfs +scarfskin +scarfskins +scarier +scariest +scarification +scarifications +scarificator +scarificators +scarified +scarifier +scarifiers +scarifies +scarify +scarifying +scarifyingly +scarily +scariness +scaring +scariose +scarious +scarlatina +scarlatinal +scarlatinoid +scarlatti +scarless +scarlet +scarlets +scarp +scarped +scarping +scarps +scarred +scarring +scarry +scars +scarum +scarves +scary +scat +scatback +scatbacks +scathe +scathed +scatheless +scathes +scathing +scathingly +scatologic +scatological +scatologies +scatologist +scatologists +scatology +scats +scatted +scatter +scatteration +scatterations +scatterbrain +scatterbrained +scatterbrains +scattered +scatterer +scatterers +scattergood +scattergoods +scattergram +scattergrams +scattergun +scatterguns +scattering +scatteringly +scatterings +scatters +scattershot +scattier +scattiest +scatting +scatty +scaup +scaups +scavenge +scavenged +scavenger +scavengers +scavenges +scavenging +scena +scenario +scenarios +scenarist +scenarists +scenas +scend +scended +scending +scends +scene +sceneries +scenery +scenes +sceneshifter +sceneshifters +scenic +scenical +scenically +scenics +scenographer +scenographers +scenographic +scenography +scent +scented +scenting +scentless +scents +scepter +sceptered +sceptering +scepters +sceptic +sceptical +scepticism +sceptics +schadenfreude +schadenfreudes +scharnhorst +schav +schavs +schedular +schedule +scheduled +scheduler +schedulers +schedules +scheduling +scheelite +scheelites +schefflera +scheffleras +scheherazade +schelde +scheldt +schema +schemas +schemata +schematic +schematically +schematics +schematism +schematization +schematizations +schematize +schematized +schematizes +schematizing +scheme +schemed +schemer +schemers +schemes +scheming +scherzando +scherzandos +scherzi +scherzo +scherzos +scheveningen +schick +schiff +schiller +schillers +schilling +schillings +schindler +schiphol +schipperke +schipperkes +schism +schismatic +schismatical +schismatically +schismatics +schismatize +schismatized +schismatizes +schismatizing +schisms +schist +schistocyte +schistocytes +schistocytoses +schistocytosis +schistorrhachis +schistorrhachises +schistose +schistosity +schistosomal +schistosome +schistosomes +schistosomiases +schistosomiasis +schistosomula +schistosomulum +schistous +schists +schizier +schiziest +schizo +schizoaffective +schizocarp +schizocarpic +schizocarpous +schizocarps +schizogamy +schizogenesis +schizogenous +schizogonic +schizogonous +schizogony +schizoid +schizoids +schizont +schizonts +schizophrene +schizophrenes +schizophrenia +schizophrenic +schizophrenically +schizophrenics +schizophreniform +schizophrenogenic +schizopod +schizopodous +schizopods +schizos +schizothyme +schizothymes +schizothymia +schizothymic +schizothymics +schizy +schizzy +schlemiel +schlemiels +schlep +schlepp +schlepped +schlepper +schleppers +schlepping +schlepps +schleps +schleswig +schliemann +schlieren +schlieric +schlimazel +schlimazels +schlock +schlockmeister +schlockmeisters +schlocky +schmaltz +schmaltzier +schmaltziest +schmaltziness +schmaltzy +schmalz +schmalzy +schmear +schmeer +schmidt +schmo +schmoe +schmoes +schmoose +schmoosed +schmooses +schmoosing +schmooze +schmoozed +schmoozes +schmoozing +schmos +schmuck +schmucks +schnapper +schnappers +schnapps +schnauzer +schnauzers +schnitzel +schnitzels +schnook +schnooks +schnorrer +schnorrers +schnoz +schnozes +schnozzle +schnozzles +schoenberg +schoenbergian +scholar +scholarliness +scholarly +scholars +scholarship +scholarships +scholastic +scholastically +scholasticate +scholasticates +scholasticism +scholastics +scholia +scholiast +scholiastic +scholiasts +scholium +scholiums +school +schoolbag +schoolbags +schoolbook +schoolbooks +schoolboy +schoolboyish +schoolboys +schoolchild +schoolchildren +schooldays +schooled +schooler +schoolers +schoolfellow +schoolfellows +schoolgirl +schoolgirls +schoolhouse +schoolhouses +schooling +schoolings +schoolkid +schoolkids +schoolma'am +schoolma'ams +schoolman +schoolmarm +schoolmarmish +schoolmarms +schoolmaster +schoolmasterish +schoolmasterly +schoolmasters +schoolmate +schoolmates +schoolmen +schoolmistress +schoolmistresses +schoolroom +schoolrooms +schools +schoolteacher +schoolteachers +schooltime +schooltimes +schoolwork +schoolyard +schoolyards +schooner +schooners +schopenhauer +schopenhauerian +schorl +schorls +schottische +schottisches +schouten +schrod +schrodinger +schtick +schticks +schubert +schumann +schuss +schussboomer +schussboomers +schussed +schusses +schussing +schuylkill +schwa +schwann +schwarmerei +schwarzhorn +schwarzschild +schwarzwald +schwas +sciaenid +sciaenoid +sciaenoids +sciatic +sciatica +science +sciences +scienter +sciential +scientific +scientifically +scientism +scientist +scientistic +scientists +scientize +scientized +scientizes +scientizing +scientology +scilicet +scilla +scilly +scimitar +scimitars +scincoid +scincoids +scintigram +scintigrams +scintigraph +scintigraphic +scintigraphically +scintigraphs +scintigraphy +scintilla +scintillant +scintillantly +scintillate +scintillated +scintillates +scintillating +scintillatingly +scintillation +scintillations +scintillator +scintillators +scintillometer +scintillometers +scintiscan +scintiscanner +scintiscanners +scintiscans +sciolism +sciolist +sciolistic +sciolists +scion +scions +scipio +scirocco +sciroccos +scirrhi +scirrhoid +scirrhous +scirrhus +scirrhuses +scissile +scission +scissions +scissor +scissored +scissoring +scissors +scissortail +scissortails +scissure +scissures +sciurid +sciurids +sciuroid +sclaff +sclaffed +sclaffer +sclaffers +sclaffing +sclaffs +sclera +scleral +sclereid +sclereids +sclerenchyma +sclerenchymas +sclerenchymatous +sclerite +sclerites +scleritic +scleritis +scleroderma +sclerodermatous +scleroid +scleroma +scleromas +scleromata +sclerometer +sclerometers +scleroprotein +scleroproteins +sclerosed +scleroses +sclerosing +sclerosis +sclerotia +sclerotial +sclerotic +sclerotics +sclerotin +sclerotins +sclerotium +sclerotization +sclerotizations +sclerotized +sclerotomies +sclerotomy +sclerous +scoff +scoffed +scoffer +scoffers +scoffing +scoffingly +scofflaw +scofflaws +scoffs +scold +scolded +scolder +scolders +scolding +scoldingly +scoldings +scolds +scoleces +scolecite +scolecites +scolex +scolices +scoliosis +scoliotic +scollop +scolloped +scolloping +scollops +scolopendra +scolopendrid +scolopendrids +scolopendrine +scombroid +scombroids +sconce +sconces +scone +scones +scoop +scooped +scooper +scoopers +scoopful +scoopfuls +scooping +scoops +scoot +scooted +scooter +scooters +scooting +scoots +scop +scope +scoped +scopes +scoping +scopolamine +scops +scopula +scopulae +scopulate +scorbutic +scorbutical +scorbutically +scorch +scorched +scorcher +scorchers +scorches +scorching +scorchingly +score +scoreboard +scoreboards +scorecard +scorecards +scored +scorekeeper +scorekeepers +scorekeeping +scoreless +scorer +scorers +scores +scoresby +scoria +scoriaceous +scoriae +scorification +scorifications +scorified +scorifier +scorifiers +scorifies +scorify +scorifying +scoring +scorings +scorn +scorned +scorner +scorners +scornful +scornfully +scornfulness +scorning +scorns +scorpaenid +scorpaenids +scorpaenoid +scorpaenoids +scorpio +scorpioid +scorpion +scorpions +scorpios +scorpius +scot +scotch +scotched +scotches +scotching +scotchman +scotchmen +scotchwoman +scotchwomen +scoter +scoters +scotia +scotic +scotism +scotist +scotists +scotland +scotoma +scotomas +scotomata +scotomatous +scotophil +scotophilic +scotophily +scotophobic +scotophobin +scotophobins +scotopia +scotopias +scotopic +scots +scotsman +scotsmen +scotswoman +scotswomen +scott +scotticism +scotticisms +scottie +scotties +scottish +scottishness +scotty +scotus +scoundrel +scoundrelly +scoundrels +scour +scoured +scourer +scourers +scourge +scourged +scourger +scourgers +scourges +scourging +scouring +scourings +scours +scouse +scouser +scousers +scouses +scout +scoutcraft +scoutcrafts +scouted +scouter +scouters +scouting +scoutings +scoutmaster +scoutmasters +scouts +scow +scowl +scowled +scowler +scowlers +scowling +scowlingly +scowls +scows +scrabble +scrabbled +scrabbler +scrabblers +scrabbles +scrabbling +scrabbly +scrag +scragged +scraggier +scraggiest +scraggily +scragginess +scragging +scragglier +scraggliest +scraggly +scraggy +scrags +scram +scramble +scrambled +scrambler +scramblers +scrambles +scrambling +scramjet +scramjets +scrammed +scramming +scrams +scrannel +scrap +scrapbook +scrapbooks +scrape +scraped +scraper +scraperboard +scraperboards +scrapers +scrapes +scrapheap +scrapheaps +scrapie +scraping +scrapings +scrappage +scrapped +scrapper +scrappers +scrappier +scrappiest +scrappily +scrappiness +scrapping +scrapple +scrappy +scraps +scratch +scratchboard +scratchboards +scratched +scratcher +scratchers +scratches +scratchier +scratchiest +scratchily +scratchiness +scratching +scratchpad +scratchpads +scratchproof +scratchy +scrawl +scrawled +scrawler +scrawlers +scrawling +scrawls +scrawly +scrawnier +scrawniest +scrawniness +scrawny +screak +screaked +screaking +screaks +screaky +scream +screamed +screamer +screamers +screaming +screamingly +screams +scree +screech +screeched +screecher +screechers +screeches +screeching +screechy +screed +screeds +screen +screenable +screened +screener +screeners +screening +screenings +screenland +screenplay +screenplays +screens +screenwriter +screenwriters +screenwriting +screes +screw +screwable +screwball +screwballs +screwbean +screwbeans +screwdriver +screwdrivers +screwed +screwer +screwers +screwier +screwiest +screwiness +screwing +screwlike +screws +screwup +screwups +screwworm +screwworms +screwy +scribal +scribble +scribbled +scribbler +scribblers +scribbles +scribbling +scribbly +scribe +scribed +scriber +scribers +scribes +scribing +scried +scries +scrim +scrimmage +scrimmaged +scrimmager +scrimmagers +scrimmages +scrimmaging +scrimp +scrimped +scrimper +scrimpers +scrimpiness +scrimping +scrimps +scrimption +scrimpy +scrims +scrimshander +scrimshanders +scrimshaw +scrimshawed +scrimshawing +scrimshaws +scrip +scrips +script +scripted +scripter +scripters +scripting +scriptoria +scriptorium +scriptoriums +scripts +scriptural +scripturally +scripture +scriptures +scriptwriter +scriptwriters +scriptwriting +scrivener +scriveners +scrobiculate +scrod +scrods +scrofula +scrofulous +scrofulously +scrofulousness +scroll +scrollbar +scrollbars +scrolled +scrolling +scrolls +scrollwork +scrooch +scrooched +scrooches +scrooching +scrooge +scrooges +scroogie +scroogies +scrootch +scrootched +scrootches +scrootching +scrota +scrotal +scrotum +scrotums +scrouge +scrouged +scrouges +scrouging +scrounge +scrounged +scrounger +scroungers +scrounges +scroungier +scroungiest +scrounging +scroungy +scrub +scrubbable +scrubbed +scrubber +scrubbers +scrubbier +scrubbiest +scrubbily +scrubbiness +scrubbing +scrubby +scrubland +scrublands +scrubs +scrubwoman +scrubwomen +scruff +scruffier +scruffiest +scruffily +scruffiness +scruffs +scruffy +scrum +scrummage +scrummaged +scrummager +scrummagers +scrummages +scrummaging +scrummed +scrumming +scrumptious +scrumptiously +scrumptiousness +scrums +scrunch +scrunchable +scrunched +scrunches +scrunching +scruple +scrupled +scruples +scrupling +scrupulosity +scrupulous +scrupulously +scrupulousness +scrutable +scrutineer +scrutineers +scrutinies +scrutinize +scrutinized +scrutinizer +scrutinizers +scrutinizes +scrutinizing +scrutinizingly +scrutiny +scry +scrying +scuba +scubas +scud +scudded +scudding +scudi +scudo +scuds +scuff +scuffed +scuffer +scuffers +scuffing +scuffle +scuffled +scuffler +scufflers +scuffles +scuffling +scuffs +scull +sculled +sculler +sculleries +scullers +scullery +sculling +scullion +scullions +sculls +sculpin +sculpins +sculpt +sculpted +sculpting +sculptor +sculptors +sculptress +sculptresses +sculpts +sculptural +sculpturally +sculpture +sculptured +sculptures +sculpturesque +sculpturesquely +sculpturing +scum +scumbag +scumbags +scumble +scumbled +scumbles +scumbling +scummed +scummer +scummers +scummier +scummiest +scummily +scumminess +scumming +scummy +scums +scungilli +scunner +scunners +scup +scupper +scuppered +scuppering +scuppernong +scuppernongs +scuppers +scups +scurf +scurfiness +scurfy +scurried +scurries +scurril +scurrile +scurrilities +scurrility +scurrilous +scurrilously +scurrilousness +scurry +scurrying +scurvier +scurviest +scurvily +scurviness +scurvy +scut +scuta +scutage +scutages +scutate +scutch +scutched +scutcheon +scutcheons +scutcher +scutchers +scutches +scutching +scute +scutella +scutellar +scutellate +scutellated +scutellation +scutellations +scutellum +scutes +scutiform +scuts +scutter +scuttered +scuttering +scutters +scuttle +scuttlebutt +scuttled +scuttles +scuttling +scutum +scutwork +scuzzier +scuzziest +scuzzy +scylla +scyphistoma +scyphistomae +scyphistomas +scyphozoan +scyphozoans +scyros +scythe +scythed +scythes +scythia +scythian +scythians +scything +scène +scènes +se +sea +seabag +seabags +seabed +seabeds +seabee +seabees +seabird +seabirds +seaboard +seaboards +seaboot +seaboots +seaborgium +seaborne +seacoast +seacoasts +seacock +seacocks +seacraft +seadog +seadogs +seafarer +seafarers +seafaring +seafloor +seafloors +seafood +seafowl +seafront +seafronts +seagirt +seagoing +seagull +seagulls +seahorse +seahorses +seajack +seajacked +seajacker +seajackers +seajacking +seajackings +seajacks +seal +sealable +sealant +sealants +sealed +sealer +sealers +sealift +sealifted +sealifting +sealifts +sealing +seals +sealskin +sealskins +sealyham +seam +seaman +seamanlike +seamanly +seamanship +seamark +seamarks +seamed +seamen +seamer +seamers +seamier +seamiest +seaminess +seaming +seamless +seamlessly +seamlessness +seamlike +seamount +seamounts +seams +seamster +seamsters +seamstress +seamstresses +seamy +seance +seances +seapiece +seapieces +seaplane +seaplanes +seaport +seaports +seaquake +seaquakes +sear +search +searchable +searched +searcher +searchers +searches +searching +searchingly +searchless +searchlight +searchlights +seared +searing +searingly +sears +seas +seascape +seascapes +seashell +seashells +seashore +seashores +seasick +seasickness +seaside +season +seasonable +seasonableness +seasonably +seasonal +seasonality +seasonally +seasoned +seasoner +seasoners +seasoning +seasonings +seasonless +seasons +seastrand +seastrands +seat +seatback +seatbacks +seated +seater +seaters +seating +seatmate +seatmates +seatrain +seatrains +seats +seattle +seatwork +seawall +seawalls +seaward +seawards +seaware +seawater +seaway +seaways +seaweed +seaweeds +seaworthier +seaworthiest +seaworthiness +seaworthy +sebaceous +sebacic +sebastian +sebastopol +sebiferous +sebiparous +seborrhea +seborrheic +seborrhoea +sebum +sec +secant +secants +secco +seccos +secede +seceded +seceder +seceders +secedes +seceding +secern +secerned +secerning +secernment +secernments +secerns +secession +secessional +secessionism +secessionist +secessionists +secessions +sechuana +seckel +seclude +secluded +secludedly +secludedness +secludes +secluding +seclusion +seclusive +seclusively +seclusiveness +secobarbital +secobarbitals +seconal +second +secondaries +secondarily +secondariness +secondary +seconded +seconder +seconders +secondhand +secondi +seconding +secondly +secondo +seconds +secondstory +secrecies +secrecy +secret +secreta +secretagogue +secretagogues +secretarial +secretariat +secretariats +secretaries +secretary +secretaryship +secrete +secreted +secreter +secreters +secretes +secretin +secreting +secretins +secretion +secretionary +secretions +secretive +secretively +secretiveness +secretly +secretor +secretors +secretory +secrets +sect +sectarian +sectarianism +sectarianize +sectarianized +sectarianizes +sectarianizing +sectarians +sectaries +sectary +sectile +sectility +section +sectional +sectionalism +sectionalist +sectionalists +sectionalization +sectionalizations +sectionalize +sectionalized +sectionalizes +sectionalizing +sectionally +sectionals +sectioned +sectioning +sections +sector +sectored +sectorial +sectoring +sectors +sects +secular +secularism +secularist +secularistic +secularists +secularities +secularity +secularization +secularizations +secularize +secularized +secularizer +secularizers +secularizes +secularizing +secularly +seculars +secund +secundines +securable +secure +secured +securely +securement +securements +secureness +securer +securers +secures +securest +securing +securities +securitization +securitize +securitized +securitizes +securitizing +security +sedan +sedans +sedarim +sedate +sedated +sedately +sedateness +sedates +sedating +sedation +sedations +sedative +sedatives +sedentarily +sedentariness +sedentary +seder +seders +sederunt +sederunts +sedge +sedges +sedgwick +sedile +sedilia +sediment +sedimental +sedimentary +sedimentation +sedimentologic +sedimentological +sedimentologist +sedimentologists +sedimentology +sediments +sedition +seditionist +seditionists +seditious +seditiously +seditiousness +seduce +seduceable +seduced +seducement +seducements +seducer +seducers +seduces +seducible +seducing +seduction +seductions +seductive +seductively +seductiveness +seductress +seductresses +sedulity +sedulous +sedulously +sedulousness +sedum +see +seeable +seecatch +seecatchie +seed +seedbed +seedbeds +seedcake +seedcakes +seedcase +seedcases +seedeater +seedeaters +seeded +seeder +seeders +seedier +seediest +seedily +seediness +seeding +seedless +seedlike +seedling +seedlings +seedpod +seedpods +seeds +seedsman +seedsmen +seedtime +seedtimes +seedy +seeing +seek +seeker +seekers +seeking +seeks +seel +seeled +seeling +seels +seem +seemed +seeming +seemingly +seemingness +seemlier +seemliest +seemliness +seemly +seems +seen +seep +seepage +seeped +seeping +seeps +seepy +seer +seeress +seeresses +seers +seersucker +sees +seesaw +seesawed +seesawing +seesaws +seethe +seethed +seethes +seething +segment +segmental +segmentally +segmentary +segmentation +segmentations +segmented +segmenting +segments +segno +segnos +sego +segos +segovia +segregable +segregant +segregants +segregate +segregated +segregates +segregating +segregation +segregationist +segregationists +segregations +segregative +segregator +segregators +segue +segued +segueing +segues +seguidilla +seguidillas +seguing +sei +seicento +seicentos +seiche +seiches +seidel +seidels +seidlitz +seigneur +seigneurial +seigneuries +seigneurs +seigneury +seignior +seigniorage +seigniorial +seigniories +seigniors +seigniory +seignorage +seignorial +seignory +seine +seined +seiner +seiners +seines +seining +seis +seise +seised +seises +seisin +seising +seisins +seism +seismic +seismically +seismicity +seismism +seismogram +seismograms +seismograph +seismographer +seismographers +seismographic +seismographical +seismographs +seismography +seismologic +seismological +seismologically +seismologist +seismologists +seismology +seismometer +seismometers +seismometric +seismometrical +seismometry +seismoscope +seismoscopes +seismoscopic +seisms +seisor +seisors +seizable +seize +seized +seizer +seizers +seizes +seizin +seizing +seizings +seizins +seizor +seizors +seizure +seizures +sejant +selachian +selachians +seladang +seladangs +selaginella +selaginellas +selah +selassie +selcouth +seldom +seldomness +select +selectable +selected +selectee +selectees +selecting +selection +selectional +selectionism +selectionist +selectionists +selections +selective +selectively +selectiveness +selectivities +selectivity +selectman +selectmen +selectness +selector +selectors +selects +selectwoman +selectwomen +selenate +selenates +selene +selenic +selenide +selenides +seleniferous +selenite +selenites +selenium +selenocentric +selenographer +selenographers +selenographic +selenographical +selenographically +selenographist +selenographists +selenography +selenological +selenologist +selenologists +selenology +selenosis +seleucid +seleucids +self +selfdom +selfhood +selfish +selfishly +selfishness +selfless +selflessly +selflessness +selfmate +selfness +selfridge +selfsame +selfsameness +seljuk +seljukian +sell +sellable +sellback +sellbacks +seller +sellers +selling +selloff +sellout +sellouts +sells +selsyn +selsyns +seltzer +seltzers +selva +selvage +selvaged +selvages +selvas +selvedge +selvedged +selvedges +selves +semanteme +semantemes +semantic +semantical +semantically +semanticist +semanticists +semantics +semaphore +semaphored +semaphores +semaphoric +semaphorically +semaphoring +semasiological +semasiologist +semasiologists +semasiology +sematic +semblable +semblables +semblably +semblance +seme +semeiology +semeiotic +semeiotical +semeiotics +sememe +sememes +sememic +semen +semes +semester +semesters +semestral +semestrial +semi +semiabstract +semiabstraction +semiabstractions +semiannual +semiannually +semiaquatic +semiarboreal +semiarid +semiaridity +semiattached +semiautobiographical +semiautomated +semiautomatic +semiautomatically +semiautomatics +semiautonomous +semiautonomously +semiautonomy +semibreve +semibreves +semicentennial +semicentennials +semicircle +semicircles +semicircular +semicivilized +semiclassic +semiclassical +semiclassics +semicolon +semicolonial +semicolonialism +semicolonies +semicolons +semicolony +semicoma +semicomas +semicomatose +semicommercial +semiconducting +semiconductor +semiconductors +semiconscious +semiconsciously +semiconsciousness +semiconservative +semiconservatively +semicrystalline +semidarkness +semidarknesses +semideified +semideifies +semideify +semideifying +semidesert +semideserts +semidetached +semidiameter +semidiameters +semidiurnal +semidivine +semidocumentaries +semidocumentary +semidome +semidomed +semidomes +semidomesticated +semidomestication +semidominant +semidried +semidry +semidrying +semidwarf +semidwarfs +semielliptical +semiempirical +semierect +semievergreen +semifeudal +semifinal +semifinalist +semifinalists +semifinals +semifinished +semifitted +semiflexible +semiflexion +semiflexions +semifluid +semifluidity +semifluids +semiformal +semigloss +semiglosses +semiglossy +semigovernmental +semigroup +semigroups +semihard +semilegendary +semilethal +semiliquid +semiliquidity +semiliquids +semiliteracy +semiliterate +semillon +semillons +semilog +semilogarithmic +semilunar +semilunate +semilustrous +semimajor +semimat +semimatt +semimatte +semimembranous +semimetal +semimetallic +semimetals +semimicro +semiminor +semimoist +semimonastic +semimonthlies +semimonthly +semimystical +seminal +seminally +seminar +seminarian +seminarians +seminaries +seminarist +seminarists +seminars +seminary +seminatural +seminiferous +seminivorous +seminole +seminoles +seminoma +seminomad +seminomadic +seminomads +seminomas +seminomata +seminude +seminudity +semiofficial +semiofficially +semiological +semiologically +semiologist +semiologists +semiology +semiopaque +semiosis +semiotic +semiotical +semiotician +semioticians +semioticist +semioticists +semiotics +semioviparous +semipalmate +semipalmated +semiparasite +semiparasites +semiparasitic +semiparasitism +semipermanent +semipermeability +semipermeable +semipolitical +semipopular +semiporcelain +semiporcelains +semipornographic +semipornography +semipostal +semipostals +semiprecious +semiprivate +semipro +semiprofessional +semiprofessionally +semiprofessionals +semipros +semipublic +semipublicly +semiquantitative +semiquantitatively +semiquaver +semiquavers +semireligious +semiretired +semiretirement +semiretirements +semirigid +semiround +semirounds +semirural +semis +semisacred +semisecret +semisedentary +semiserious +semiseriously +semishrubby +semiskilled +semisoft +semisolid +semisolids +semispherical +semistaged +semisterile +semisubmersible +semisubmersibles +semisweet +semisynthetic +semite +semiterrestrial +semites +semitic +semiticist +semiticists +semitics +semitism +semitist +semitists +semitization +semitize +semitized +semitizes +semitizing +semitonal +semitonally +semitone +semitones +semitonic +semitonically +semitrailer +semitrailers +semitranslucent +semitransparent +semitropic +semitropical +semitropics +semivowel +semivowels +semiweeklies +semiweekly +semiworks +semiyearlies +semiyearly +semolina +sempervivum +sempervivums +sempiternal +sempiternally +sempiternity +semplice +sempre +sempstress +sempstresses +semtex +semé +sen +senarii +senarius +senary +senate +senates +senator +senatorial +senatorially +senatorian +senators +senatorship +senatorships +send +sendal +sendals +sender +senders +sending +sendoff +sendoffs +sends +sene +seneca +senecas +senecio +senecios +senectitude +senega +senegal +senegalese +senegambia +senegas +senesce +senesced +senescence +senescent +senesces +seneschal +seneschals +senescing +senhor +senhora +senhores +senhorita +senhors +senile +senilely +senility +senior +seniorities +seniority +seniors +seniti +senna +sennas +sennet +sennets +sennight +sennights +sennit +sennits +senopia +senopias +senryu +sensa +sensate +sensated +sensately +sensation +sensational +sensationalism +sensationalist +sensationalistic +sensationalists +sensationalization +sensationalizations +sensationalize +sensationalized +sensationalizes +sensationalizing +sensationally +sensations +sensatory +sense +sensed +senseful +sensei +senseis +senseless +senselessly +senselessness +senses +sensibilia +sensibilities +sensibility +sensible +sensibleness +sensibly +sensilla +sensillum +sensing +sensitive +sensitively +sensitiveness +sensitives +sensitivities +sensitivity +sensitization +sensitizations +sensitize +sensitized +sensitizer +sensitizers +sensitizes +sensitizing +sensitometer +sensitometers +sensitometric +sensitometry +sensor +sensoria +sensorial +sensorially +sensorimotor +sensorineural +sensorium +sensoriums +sensors +sensory +sensual +sensualism +sensualist +sensualistic +sensualists +sensuality +sensualization +sensualizations +sensualize +sensualized +sensualizes +sensualizing +sensually +sensualness +sensum +sensuosity +sensuous +sensuously +sensuousness +sensurround +sent +sentence +sentenced +sentencer +sentencers +sentences +sentencing +sentencings +sententia +sententiae +sentential +sententially +sententious +sententiously +sententiousness +sentience +sentient +sentiently +sentiment +sentimental +sentimentalism +sentimentalist +sentimentalists +sentimentalities +sentimentality +sentimentalization +sentimentalizations +sentimentalize +sentimentalized +sentimentalizes +sentimentalizing +sentimentally +sentiments +sentimo +sentimos +sentinel +sentineled +sentineling +sentinelled +sentinelling +sentinels +sentries +sentry +seoul +sepal +sepaled +sepaline +sepaloid +sepalous +sepals +separability +separable +separableness +separably +separate +separated +separately +separateness +separates +separating +separation +separationist +separationists +separations +separatism +separatist +separatistic +separatists +separative +separator +separators +sephardi +sephardic +sephardim +sepia +sepias +sepiolite +sepiolites +sepoy +sepoys +seppuku +seppukus +sepses +sepsis +sept +septa +septage +septages +septal +septaria +septarian +septarium +septate +septavalent +septcentenary +septectomies +septectomy +september +septembers +septembrist +septembrists +septenarii +septenarius +septenary +septenate +septendecillion +septendecillions +septennial +septennially +septennials +septentrion +septentrional +septentrions +septet +septets +septette +septettes +septic +septicemia +septicemic +septicidal +septicidally +septicity +septifragal +septifragally +septilateral +septillion +septillions +septillionth +septillionths +septimal +septivalent +septs +septuagenarian +septuagenarians +septuagesima +septuagesimas +septuagint +septuagintal +septum +septuple +septupled +septuples +septuplet +septuplets +septupling +sepulcher +sepulchered +sepulchering +sepulchers +sepulchral +sepulchrally +sepulchre +sepulchred +sepulchres +sepulchring +sepulture +sepultures +seq +sequacious +sequaciously +sequacity +sequel +sequela +sequelae +sequels +sequenator +sequenators +sequence +sequenced +sequencer +sequencers +sequences +sequencing +sequency +sequent +sequential +sequentiality +sequentially +sequents +sequester +sequestered +sequestering +sequesters +sequestra +sequestrant +sequestrants +sequestrate +sequestrated +sequestrates +sequestrating +sequestration +sequestrations +sequestrator +sequestrators +sequestrum +sequin +sequined +sequining +sequinned +sequins +sequitur +sequiturs +sequoia +sequoias +sera +seraglio +seraglios +serai +seral +serape +serapes +seraph +seraphic +seraphical +seraphically +seraphim +seraphs +serapis +serb +serbia +serbian +serbians +serbo +serbs +sere +serenade +serenaded +serenader +serenaders +serenades +serenading +serenata +serenatas +serendipitous +serendipitously +serendipity +serene +serenely +sereneness +serener +serenest +serenissima +serenity +serer +serest +serf +serfage +serfdom +serfs +serge +sergeancy +sergeant +sergeanties +sergeants +sergeantship +sergeanty +serges +serging +serial +serialism +serialist +serialists +serialization +serializations +serialize +serialized +serializes +serializing +serially +serials +seriate +seriated +seriately +seriates +seriatim +seriating +seriation +sericeous +sericin +sericins +sericteria +sericterium +sericultural +sericulture +sericulturist +sericulturists +seriema +seriemas +series +serif +serifed +seriffed +serifs +serigraph +serigrapher +serigraphers +serigraphs +serigraphy +serin +serine +serines +serins +seriocomic +seriocomically +serious +seriously +seriousness +serjeant +serjeants +serjeanty +sermon +sermonette +sermonettes +sermonic +sermonical +sermonize +sermonized +sermonizer +sermonizers +sermonizes +sermonizing +sermons +seroconversion +seroconversions +serodiagnoses +serodiagnosis +serodiagnostic +serologic +serological +serologically +serologies +serologist +serologists +serology +seronegative +seronegativity +seropositive +seropositivity +seropurulent +serosa +serosae +serosal +serosas +serositis +serositises +serotherapies +serotherapist +serotherapists +serotherapy +serotinal +serotine +serotines +serotinous +serotonergic +serotonin +serotoninergic +serotonins +serotype +serotyped +serotypes +serotyping +serous +serow +serows +serpens +serpent +serpentaria +serpentarium +serpentariums +serpentine +serpentinely +serpentines +serpents +serpiginous +serpiginously +serpigo +serpigos +serranid +serranids +serrano +serranos +serrate +serrated +serrates +serrating +serration +serried +serriedly +serriedness +serries +serrulate +serrulated +serrulation +serry +serrying +sertoli +sertoman +sertularian +sertularians +serum +serums +serval +servant +servanthood +servantless +servants +serve +served +server +servers +serves +servibar +servibars +service +serviceability +serviceable +serviceableness +serviceably +serviceberries +serviceberry +serviced +serviceman +servicemen +servicepeople +serviceperson +servicepersons +servicer +servicers +services +servicewoman +servicewomen +servicing +serviette +serviettes +servile +servilely +servileness +servility +serving +servingly +servings +servite +servites +servitor +servitors +servitorship +servitorships +servitude +servo +servomechanism +servomechanisms +servomotor +servomotors +servos +sesame +sesames +sesamoid +sesamoids +sesotho +sesquicarbonate +sesquicarbonates +sesquicentenary +sesquicentennial +sesquicentennials +sesquipedal +sesquipedalian +sesquipedalians +sesquiterpene +sesquiterpenes +sessile +sessility +session +sessional +sessionally +sessions +sesterce +sesterces +sestertia +sestertium +sestet +sestets +sestina +sestinas +set +seta +setaceous +setaceously +setae +setal +setback +setbacks +seth +setiferous +setiform +setigerous +setline +setlines +setoff +setoffs +setose +setout +setouts +sets +setscrew +setscrews +setswana +settable +settee +settees +setter +setters +setting +settings +settle +settleable +settled +settlement +settlements +settler +settlers +settles +settling +settlings +settlor +settlors +setup +setups +seurat +sevastopol +seven +sevenfold +sevens +seventeen +seventeenfold +seventeens +seventeenth +seventeenths +seventh +seventhly +sevenths +seventies +seventieth +seventieths +seventy +seventyfold +sever +severability +severable +several +severalfold +severally +severalties +severalty +severance +severances +severe +severed +severely +severeness +severer +severest +severing +severities +severity +severs +severus +seviche +seviches +seville +sevres +sevruga +sevrugas +sew +sewability +sewable +sewage +sewed +sewellel +sewellels +sewer +sewerage +sewers +sewing +sewn +sews +sex +sexagenarian +sexagenarians +sexagenaries +sexagenary +sexagesima +sexagesimal +sexagesimally +sexagesimas +sexcentenaries +sexcentenary +sexdecillion +sexdecillions +sexduction +sexductions +sexed +sexennial +sexennially +sexennials +sexes +sexier +sexiest +sexily +sexiness +sexing +sexism +sexist +sexists +sexivalent +sexless +sexlessly +sexlessness +sexologic +sexological +sexologist +sexologists +sexology +sexpartite +sexploitation +sexpot +sexpots +sext +sextans +sextant +sextants +sextet +sextets +sextile +sextillion +sextillions +sextillionth +sextillionths +sexto +sextodecimo +sextodecimos +sexton +sextons +sextos +sexts +sextuple +sextupled +sextuples +sextuplet +sextuplets +sextuplicate +sextuplicated +sextuplicately +sextuplicates +sextuplicating +sextuplication +sextuplications +sextupling +sextuply +sexual +sexuality +sexualization +sexualizations +sexualize +sexualized +sexualizes +sexualizing +sexually +sexvalent +sexy +seychelles +seychellois +seyfert +seymour +seymours +señor +señora +señores +señorita +señors +sferics +sforza +sforzandi +sforzando +sforzandos +sforzas +sfumato +sfumatos +sgraffiti +sgraffito +sh +sha'ban +shaaban +shaanxi +shaba +shabbat +shabbier +shabbiest +shabbily +shabbiness +shabby +shabu +shabuoth +shack +shacked +shacking +shackle +shacklebone +shacklebones +shackled +shackler +shacklers +shackles +shackling +shacko +shacks +shad +shadberries +shadberry +shadblow +shadblows +shadbush +shadbushes +shaddock +shaddocks +shade +shaded +shadeless +shader +shaders +shades +shadflies +shadfly +shadier +shadiest +shadily +shadiness +shading +shadings +shadoof +shadoofs +shadow +shadowbox +shadowboxed +shadowboxes +shadowboxing +shadowed +shadower +shadowers +shadowgraph +shadowgraphs +shadowgraphy +shadowier +shadowiest +shadowily +shadowiness +shadowing +shadowless +shadowlike +shadows +shadowy +shads +shaduf +shadufs +shady +shaft +shafted +shafting +shaftings +shafts +shag +shagbark +shagbarks +shagged +shaggier +shaggiest +shaggily +shagginess +shagging +shaggy +shaggymane +shaggymanes +shagreen +shagreens +shags +shah +shahaptian +shahaptians +shahaptin +shahaptins +shahdom +shahdoms +shahs +shaitan +shaitans +shakable +shake +shakeable +shakedown +shakedowns +shaken +shakeout +shakeouts +shaker +shakerism +shakers +shakes +shakespeare +shakespearean +shakespeareana +shakespeareans +shakespearian +shakespeariana +shakespearians +shakeup +shakeups +shakier +shakiest +shakily +shakiness +shaking +shako +shakoes +shakos +shaksperean +shaksperian +shakta +shaktas +shakti +shaktism +shaktist +shaktists +shaky +shale +shaley +shalimar +shall +shallied +shallies +shalling +shalloon +shalloons +shallop +shallops +shallot +shallots +shallow +shallowed +shallower +shallowest +shallowing +shallowly +shallowness +shallows +shallu +shallus +shally +shallying +shallys +shalom +shalt +sham +shaman +shamanic +shamanism +shamanist +shamanistic +shamanists +shamans +shamash +shamble +shambled +shambles +shambling +shambolic +shambolically +shame +shamed +shamefaced +shamefacedly +shamefacedness +shamefast +shameful +shamefully +shamefulness +shameless +shamelessly +shamelessness +shames +shaming +shammed +shammer +shammers +shammes +shammies +shamming +shammosim +shammy +shampoo +shampooed +shampooer +shampooers +shampooing +shampoos +shamrock +shamrocks +shams +shamus +shamuses +shan +shan't +shandies +shandong +shandy +shandygaff +shandygaffs +shanghai +shanghaied +shanghaier +shanghaiers +shanghaiing +shanghais +shangri +shank +shanked +shanking +shankpiece +shankpieces +shanks +shans +shansi +shanter +shanters +shantey +shanteys +shanties +shantung +shanty +shantyman +shantymen +shantytown +shantytowns +shanxi +shapable +shape +shapeable +shaped +shapeless +shapelessly +shapelessness +shapelier +shapeliest +shapeliness +shapely +shapen +shaper +shapers +shapes +shapeup +shapeups +shaping +sharable +shard +shards +share +shareability +shareable +sharecrop +sharecropped +sharecropper +sharecroppers +sharecropping +sharecrops +shared +shareholder +shareholders +shareholding +shareowner +shareowners +sharer +sharers +shares +shareware +shari'a +shari'ah +sharia +sharif +sharifian +sharifs +sharing +shark +sharked +sharking +sharklike +sharks +sharkskin +sharon +sharp +sharped +sharpen +sharpened +sharpener +sharpeners +sharpening +sharpens +sharper +sharpers +sharpest +sharpie +sharpies +sharping +sharply +sharpness +sharps +sharpshooter +sharpshooters +sharpshooting +sharpshootings +sharpy +shashlick +shashlicks +shashlik +shashliks +shaslik +shasta +shastra +shastras +shat +shatter +shattered +shattering +shatteringly +shatterproof +shatters +shave +shaved +shaveling +shavelings +shaven +shaver +shavers +shaves +shavetail +shavetails +shavian +shavians +shaving +shavings +shavuot +shaw +shawl +shawled +shawling +shawls +shawm +shawms +shawnee +shawnees +shawwal +shay +shays +she +she'd +she'll +she's +shea +sheaf +sheafed +sheafing +sheaflike +sheafs +shear +sheared +shearer +shearers +shearing +shearling +shearlings +shears +shearwater +shearwaters +sheatfish +sheatfishes +sheath +sheathbill +sheathbills +sheathe +sheathed +sheather +sheathers +sheathes +sheathing +sheathings +sheaths +sheave +sheaved +sheaves +sheaving +shebang +shebat +shebats +shebeen +shebeens +shechinah +shed +shedder +shedders +shedding +shedlike +shedrow +shedrows +sheds +sheen +sheenies +sheeny +sheep +sheepberries +sheepberry +sheepcote +sheepcotes +sheepdog +sheepdogs +sheepfold +sheepfolds +sheepherder +sheepherders +sheepherding +sheepish +sheepishly +sheepishness +sheepshank +sheepshanks +sheepshead +sheepsheads +sheepshearer +sheepshearers +sheepshearing +sheepshearings +sheepskin +sheepskins +sheer +sheered +sheerer +sheerest +sheering +sheerlegs +sheerly +sheerness +sheers +sheet +sheeted +sheeter +sheeters +sheetfed +sheeting +sheetlike +sheetrock +sheets +shegetz +sheik +sheika +sheikas +sheikdom +sheikdoms +sheikh +sheikha +sheikhas +sheikhdom +sheikhdoms +sheikhs +sheiks +sheila +shekel +shekels +shekinah +shelby +sheldonian +sheldrake +sheldrakes +shelduck +shelducks +shelf +shelfful +shelffuls +shelflike +shelikof +shell +shellac +shellack +shellacked +shellacking +shellacks +shellacs +shellback +shellbacks +shellbark +shellbarks +shellcracker +shellcrackers +shelled +sheller +shellers +shelley +shelleys +shellfire +shellfish +shellfisheries +shellfishery +shellfishes +shellfishing +shellflower +shellflowers +shellier +shelliest +shelling +shellproof +shells +shellshocked +shellwork +shelly +shelta +shelter +shelterbelt +shelterbelts +sheltered +shelterer +shelterers +sheltering +shelterless +shelters +sheltie +shelties +shelty +shelve +shelved +shelver +shelvers +shelves +shelving +shema +shemini +shenandoah +shenanigan +shenanigans +shensi +sheol +shepherd +shepherded +shepherdess +shepherdesses +shepherding +shepherds +sheqalim +sheqel +sheraton +sherbert +sherberts +sherbet +sherbets +sherd +sherds +shergottite +shergottites +sheridan +sherif +sheriff +sheriffdom +sheriffs +sherifs +sherlock +sheroot +sheroots +sherpa +sherpas +sherries +sherry +shetland +shetlander +shetlanders +shetlands +shevat +shevats +shewbread +shewbreads +shi +shi'ism +shi'ite +shi'ites +shia +shias +shiatsu +shiatzu +shibah +shibboleth +shibboleths +shied +shield +shielded +shielder +shielders +shielding +shields +shieling +shielings +shier +shies +shiest +shift +shiftable +shifted +shifter +shifters +shiftier +shiftiest +shiftily +shiftiness +shifting +shiftless +shiftlessly +shiftlessness +shifts +shifty +shigella +shigellae +shigellas +shigelloses +shigellosis +shiism +shiitake +shiite +shiites +shiitic +shikar +shikari +shikaris +shikarred +shikarring +shikoku +shiksa +shiksas +shikse +shikses +shill +shillalah +shillalahs +shilled +shillelagh +shillelaghs +shilling +shillings +shills +shilluk +shilluks +shilly +shim +shimmed +shimmer +shimmered +shimmering +shimmeringly +shimmers +shimmery +shimmied +shimmies +shimming +shimmy +shimmying +shims +shin +shina +shinbone +shinbones +shindies +shindig +shindigs +shindy +shindys +shine +shined +shiner +shiners +shines +shingle +shingled +shingler +shinglers +shingles +shingling +shingly +shingon +shinier +shiniest +shininess +shining +shiningly +shinleaf +shinleafs +shinleaves +shinned +shinneries +shinnery +shinney +shinneys +shinnied +shinnies +shinning +shinny +shinnying +shinplaster +shinplasters +shins +shinsplints +shinto +shintoism +shintoist +shintoistic +shintoists +shiny +ship +shipboard +shipborne +shipbuilder +shipbuilders +shipbuilding +shipfitter +shipfitters +shiplap +shiplapped +shipload +shiploads +shipman +shipmaster +shipmasters +shipmate +shipmates +shipmen +shipment +shipments +shipowner +shipowners +shippable +shipped +shipper +shippers +shipping +ships +shipshape +shipside +shipsides +shipway +shipways +shipworm +shipworms +shipwreck +shipwrecked +shipwrecking +shipwrecks +shipwright +shipwrights +shipyard +shipyards +shire +shires +shirk +shirked +shirker +shirkers +shirking +shirks +shirr +shirred +shirring +shirrs +shirt +shirtdress +shirtdresses +shirted +shirtfront +shirtfronts +shirtier +shirtiest +shirting +shirtless +shirtmaker +shirtmakers +shirts +shirtsleeve +shirtsleeved +shirtsleeves +shirttail +shirttails +shirtwaist +shirtwaists +shirty +shish +shit +shitake +shitfaced +shithead +shitheads +shitless +shitlist +shitlists +shits +shittah +shittahs +shittier +shittiest +shittim +shittimwood +shittimwoods +shitting +shitty +shiv +shiva +shivah +shivaism +shivaist +shivaists +shivaree +shivarees +shiver +shivered +shivering +shivers +shivery +shivs +shkotzim +shlemiehl +shlemiehls +shlemiel +shlemiels +shlep +shlepp +shlepped +shlepper +shleppers +shlepping +shlepps +shleps +shlock +shmear +shmooze +shmoozed +shmoozes +shmoozing +shmuck +shmucks +shoal +shoaled +shoaling +shoals +shoat +shoats +shock +shockable +shocked +shocker +shockers +shocking +shockingly +shockproof +shocks +shod +shodden +shoddier +shoddies +shoddiest +shoddily +shoddiness +shoddy +shoe +shoebill +shoebills +shoeblack +shoeblacks +shoebox +shoeboxes +shoed +shoehorn +shoehorned +shoehorning +shoehorns +shoeing +shoelace +shoelaces +shoeless +shoemaker +shoemakers +shoemaking +shoepac +shoepack +shoepacks +shoepacs +shoes +shoeshine +shoeshines +shoestring +shoestrings +shoetree +shoetrees +shofar +shofars +shofroth +shogi +shogis +shogun +shogunal +shogunate +shogunates +shoguns +shoji +shojis +shona +shonas +shone +shoo +shooed +shooflies +shoofly +shooing +shook +shooks +shoos +shoot +shootdown +shootdowns +shooter +shooters +shooting +shootings +shootout +shootouts +shoots +shop +shopkeeper +shopkeepers +shoplift +shoplifted +shoplifter +shoplifters +shoplifting +shoplifts +shoppe +shopped +shopper +shoppers +shoppes +shopping +shops +shoptalk +shopwindow +shopwindows +shopworn +shoran +shorans +shore +shorebird +shorebirds +shored +shorefront +shorefronts +shoreline +shorelines +shores +shoreside +shoreward +shorewards +shoring +shorings +shorn +short +shortage +shortages +shortbread +shortcake +shortcakes +shortchange +shortchanged +shortchanger +shortchangers +shortchanges +shortchanging +shortcoming +shortcomings +shortcut +shortcuts +shortcutting +shorted +shorten +shortened +shortener +shorteners +shortening +shortenings +shortens +shorter +shortest +shortfall +shortfalls +shorthair +shorthaired +shorthairs +shorthand +shorthanded +shorthands +shorthorn +shorthorns +shortia +shortias +shortie +shorties +shorting +shortish +shortleaf +shortlist +shortlists +shortly +shortness +shorts +shortsighted +shortsightedly +shortsightedness +shortstop +shortstops +shortwave +shorty +shoshone +shoshonean +shoshones +shoshoni +shoshonis +shostakovich +shot +shote +shotes +shotgun +shotgunner +shotgunners +shotguns +shots +shott +shotted +shotten +shotting +shotts +should +should've +shoulder +shouldered +shouldering +shoulders +shouldest +shouldn +shouldn't +shouldst +shout +shouted +shouter +shouters +shouting +shouts +shove +shoved +shovel +shoveled +shoveler +shovelers +shovelful +shovelfuls +shovelhead +shovelheads +shoveling +shovelled +shoveller +shovellers +shovelling +shovelnose +shovelnoses +shovels +shovelsful +shover +shovers +shoves +shoving +show +showable +showbiz +showbizzy +showboat +showboated +showboating +showboats +showbread +showbreads +showcase +showcased +showcases +showcasing +showdown +showdowns +showed +shower +showered +showerer +showerers +showerhead +showerheads +showering +showerless +showers +showery +showgirl +showgirls +showier +showiest +showily +showiness +showing +showings +showman +showmanship +showmen +shown +showoff +showoffs +showpiece +showpieces +showplace +showplaces +showring +showrings +showroom +showrooms +shows +showstopper +showstoppers +showstopping +showtime +showtimes +showy +shoyu +shrank +shrapnel +shred +shredded +shredder +shredders +shredding +shreds +shrew +shrewd +shrewder +shrewdest +shrewdly +shrewdness +shrewish +shrewishly +shrewishness +shrewlike +shrewmice +shrewmouse +shrews +shriek +shrieked +shrieker +shriekers +shrieking +shrieks +shrieval +shrievalty +shrift +shrifts +shrike +shrikes +shrill +shrilled +shriller +shrillest +shrilling +shrillness +shrills +shrilly +shrimp +shrimped +shrimper +shrimpers +shrimpfish +shrimpfishes +shrimping +shrimplike +shrimps +shrimpy +shrine +shrined +shriner +shriners +shrines +shrining +shrink +shrinkable +shrinkage +shrinkages +shrinker +shrinkers +shrinking +shrinks +shrive +shrived +shrivel +shriveled +shriveling +shrivelled +shrivelling +shrivels +shriven +shriver +shrivers +shrives +shriving +shroff +shroffs +shropshire +shroud +shrouded +shrouding +shrouds +shrove +shrovetide +shrub +shrubberies +shrubbery +shrubbier +shrubbiest +shrubbiness +shrubby +shrubs +shrug +shrugged +shrugging +shrugs +shrunk +shrunken +shtetel +shtetels +shtetl +shtetlach +shtetls +shtick +shticks +shtik +shtiks +shuck +shucked +shucker +shuckers +shucking +shucks +shudder +shuddered +shuddering +shudderingly +shudders +shuddery +shuffle +shuffleboard +shuffled +shuffler +shufflers +shuffles +shuffling +shui +shul +shuls +shun +shunned +shunner +shunners +shunning +shunpike +shunpiked +shunpiker +shunpikers +shunpikes +shunpiking +shuns +shunt +shunted +shunter +shunters +shunting +shunts +shush +shushed +shushes +shushing +shut +shutdown +shutdowns +shute +shuteye +shutoff +shutoffs +shutout +shutouts +shuts +shutter +shutterbug +shutterbugs +shuttered +shuttering +shutterless +shutters +shutting +shuttle +shuttlecock +shuttlecocked +shuttlecocking +shuttlecocks +shuttlecraft +shuttlecrafts +shuttled +shuttleless +shuttler +shuttlers +shuttles +shuttling +shy +shyer +shyers +shyest +shying +shylock +shylocked +shylocking +shylocks +shyly +shyness +shyster +shysterism +shysters +si +siabon +siabons +sial +sialadenitis +sialadenitises +sialagogic +sialagogue +sialagogues +sialic +sialomucin +sialomucins +sialorrhea +sialorrheas +sialorrhoea +sialorrhoeas +sials +siam +siamang +siamangs +siamese +sib +sibari +sibelius +siberia +siberian +siberians +sibilance +sibilancy +sibilant +sibilantly +sibilants +sibilate +sibilated +sibilates +sibilating +sibilation +sibilations +sibling +siblings +sibs +sibuyan +sibyl +sibylic +sibyllic +sibylline +sibyls +sic +siccative +siccatives +sicced +siccing +sichuan +sicilian +sicilians +sicily +sick +sickbay +sickbays +sickbed +sickbeds +sicked +sicken +sickened +sickener +sickeners +sickening +sickeningly +sickens +sicker +sickert +sickest +sickie +sickies +sicking +sickish +sickishly +sickishness +sickle +sicklebill +sicklebills +sickled +sicklemia +sicklemias +sickles +sicklied +sicklier +sicklies +sickliest +sicklily +sickliness +sickling +sickly +sicklying +sickness +sicknesses +sicko +sickos +sickout +sickouts +sickroom +sickrooms +sicks +sics +siddons +siddur +siddurim +side +sidearm +sidearms +sideband +sidebands +sidebar +sidebars +sideboard +sideboards +sideburn +sideburned +sideburns +sidecar +sidecars +sided +sidedly +sidedness +sidedress +sidedresses +sidehill +sidehills +sidekick +sidekicks +sidelight +sidelights +sideline +sidelined +sideliner +sideliners +sidelines +sideling +sidelining +sidelong +sideman +sidemen +sidepiece +sidepieces +sider +sidereal +siderite +siderites +sideritic +siderochrome +siderochromes +siderocyte +siderocytes +siderolite +siderolites +siderosis +sides +sidesaddle +sidesaddles +sideshow +sideshows +sideslip +sideslipped +sideslipping +sideslips +sidespin +sidespins +sidesplitting +sidesplittingly +sidestep +sidestepped +sidestepper +sidesteppers +sidestepping +sidesteps +sidestream +sidestroke +sidestroked +sidestroker +sidestrokers +sidestrokes +sidestroking +sideswipe +sideswiped +sideswiper +sideswipers +sideswipes +sideswiping +sidetrack +sidetracked +sidetracking +sidetracks +sidewalk +sidewalks +sidewall +sidewalls +sideward +sidewards +sideway +sideways +sidewinder +sidewinders +sidewise +siding +sidings +sidle +sidled +sidles +sidling +sidlingly +sidney +sidon +siege +sieged +sieges +siegfried +sieging +siemens +siena +sienese +sienna +sierozem +sierozems +sierra +sierran +sierras +siesta +siestas +sieva +sieve +sieved +sievert +sieverts +sieves +sieving +sifaka +sifakas +sift +sifted +sifter +sifters +sifting +siftings +sifts +sigh +sighed +sigher +sighers +sighing +sighs +sight +sighted +sightedly +sightedness +sighting +sightings +sightless +sightlessly +sightlessness +sightlier +sightliest +sightline +sightlines +sightliness +sightly +sights +sightsaw +sightsee +sightseeing +sightseen +sightseer +sightseers +sightsees +sigil +sigils +sigismund +sigma +sigmas +sigmate +sigmoid +sigmoidal +sigmoidally +sigmoidoscope +sigmoidoscopes +sigmoidoscopic +sigmoidoscopy +sign +signage +signal +signaled +signaler +signalers +signaling +signalization +signalizations +signalize +signalized +signalizes +signalizing +signalled +signaller +signallers +signalling +signally +signalman +signalmen +signalment +signalments +signals +signatories +signatory +signature +signatures +signboard +signboards +signed +signee +signees +signer +signers +signet +signeted +signeting +signets +signifiable +significance +significances +significancy +significant +significantly +signification +significations +significative +significativeness +significs +signified +signifier +signifiers +signifies +signify +signifying +signing +signings +signior +signiories +signiors +signiory +signoff +signoffs +signor +signora +signoras +signore +signori +signories +signorina +signorinas +signorine +signors +signory +signpost +signposts +signs +sihasapa +sihasapas +sika +sikas +sikh +sikhism +sikhs +sikkim +sikkimese +silage +silane +silanes +silastic +sild +silds +silence +silenced +silencer +silencers +silences +silencing +sileni +silent +silently +silentness +silents +silenus +silesia +silesian +silesians +silesias +silex +silexes +silhouette +silhouetted +silhouettes +silhouetting +silhouettist +silhouettists +silica +silicate +silicates +siliceous +silicic +silicide +silicides +siliciferous +silicification +silicifications +silicified +silicifies +silicify +silicifying +silicious +silicle +silicles +silicon +silicone +silicones +siliconized +silicoses +silicosis +silicotic +silique +siliques +siliquose +siliquous +silk +silkaline +silked +silken +silkier +silkiest +silkily +silkiness +silking +silklike +silkoline +silks +silkscreen +silkscreened +silkscreening +silkscreens +silkweed +silkweeds +silkworm +silkworms +silky +sill +sillabub +sillabubs +sillier +sillies +silliest +sillily +sillimanite +silliness +sills +silly +silo +siloed +siloing +silos +siloxane +siloxanes +silt +siltation +siltations +silted +silting +silts +siltstone +siltstones +silty +silures +silurian +silurid +silurids +silva +silvae +silvan +silvanus +silvas +silver +silverback +silverbacked +silverbacks +silverbell +silverberries +silverberry +silvered +silverer +silverers +silvereye +silvereyes +silverfish +silverfishes +silveriness +silvering +silverly +silvern +silverpoint +silverpoints +silverrod +silverrods +silvers +silverside +silversides +silversmith +silversmithing +silversmiths +silvertip +silvertips +silverware +silverweed +silverweeds +silverwork +silvery +silvex +silvexes +silvichemical +silvichemicals +silvicolous +silvicultural +silviculturally +silviculture +silviculturist +silviculturists +sima +simas +simazine +simchas +simchat +simeon +simian +simians +similar +similarities +similarity +similarly +simile +similes +similitude +simla +simmental +simmentals +simmenthal +simmenthals +simmer +simmered +simmering +simmers +simnel +simnels +simoleon +simoleons +simon +simoniac +simoniacal +simoniacally +simoniacs +simonist +simonists +simonize +simonized +simonizes +simonizing +simony +simoom +simooms +simoon +simoons +simp +simpatico +simper +simpered +simperer +simperers +simpering +simperingly +simpers +simple +simpleminded +simplemindedly +simplemindedness +simpleness +simpler +simples +simplest +simpleton +simpletons +simplex +simplexes +simplices +simplicia +simplicial +simplicially +simplicities +simplicity +simplification +simplifications +simplified +simplifier +simplifiers +simplifies +simplify +simplifying +simplism +simplistic +simplistically +simplon +simply +simps +simpson +simulacra +simulacre +simulacres +simulacrum +simulacrums +simular +simulars +simulate +simulated +simulates +simulating +simulation +simulations +simulative +simulator +simulators +simulcast +simulcasted +simulcasting +simulcasts +simulium +simuliums +simultaneity +simultaneous +simultaneously +simultaneousness +sin +sinai +sinanthropus +sinanthropuses +sinapism +sinapisms +sinbad +since +sincere +sincerely +sincereness +sincerer +sincerest +sincerity +sincipita +sincipital +sinciput +sinciputs +sind +sindbad +sindhi +sindhis +sine +sinecure +sinecures +sinecurism +sinecurist +sinecurists +sines +sinew +sinewed +sinewing +sinews +sinewy +sinfonia +sinfonias +sinfonietta +sinfoniettas +sinful +sinfully +sinfulness +sing +singable +singapore +singaporean +singaporeans +singe +singed +singeing +singer +singers +singes +singh +singhalese +singing +singings +single +singled +singlehood +singleness +singles +singlestick +singlesticker +singlestickers +singlesticks +singlet +singleton +singletons +singletree +singletrees +singlets +singlewide +singlewides +singling +singly +sings +singsong +singsongs +singsongy +singspiel +singspiels +singular +singularities +singularity +singularize +singularized +singularizes +singularizing +singularly +singularness +singulars +sinhala +sinhalese +sinicism +sinicisms +sinicization +sinicizations +sinicize +sinicized +sinicizes +sinicizing +sinification +sinifications +sinified +sinifies +sinify +sinifying +sinister +sinisterly +sinisterness +sinistral +sinistrally +sinistrorse +sinistrorsely +sinistrous +sinistrously +sinitic +sink +sinkable +sinkage +sinkages +sinker +sinkerball +sinkerballs +sinkers +sinkhole +sinkholes +sinkiang +sinking +sinks +sinless +sinlessly +sinlessness +sinn +sinned +sinner +sinners +sinning +sino +sinoatrial +sinoauricular +sinolog +sinological +sinologist +sinologists +sinologs +sinologue +sinologues +sinology +sinope +sinophile +sinophiles +sinophilia +sinophobe +sinophobes +sinophobia +sinophobic +sinopia +sinopias +sinopie +sins +sinsemilla +sinsemillas +sinter +sinterability +sintered +sintering +sinters +sinuate +sinuated +sinuately +sinuates +sinuating +sinuation +sinuations +sinuosities +sinuosity +sinuous +sinuously +sinuousness +sinus +sinuses +sinusitis +sinusoid +sinusoidal +sinusoidally +sinusoids +siouan +siouans +sioux +sip +siphon +siphonal +siphoned +siphonic +siphoning +siphonophore +siphonophores +siphonostele +siphonosteles +siphonostelic +siphons +siphuncle +siphuncles +siphuncular +siphunculate +sipped +sipper +sippers +sippet +sippets +sipping +sips +sir +sirach +sirdar +sirdars +sire +sired +siree +siren +sirenian +sirenians +sirens +sires +siriases +siriasis +siring +sirius +sirloin +sirloins +sirocco +siroccos +sirrah +sirrahs +sirree +sirs +sirup +sirups +sirupy +sirvente +sirventes +sis +sisal +sisals +siscowet +siscowets +siskin +siskins +sisseton +sissetons +sissies +sissified +sissify +sissifying +sissiness +sissy +sissyish +sissyness +sister +sisterhood +sisterhoods +sisterliness +sisterly +sisters +sistine +sistra +sistrum +sistrums +sisyphean +sisyphian +sisyphus +sit +sita +sitar +sitarist +sitarists +sitars +sitatunga +sitatungas +sitcom +sitcoms +site +sited +sites +sith +siting +sitka +sitkas +sitology +sitomania +sitomanias +sitophobia +sitophobias +sitosterol +sitosterols +sits +sitter +sitters +sitting +sittings +situ +situate +situated +situates +situating +situation +situational +situationally +situations +situs +situtunga +situtungas +sitz +sitzkrieg +sitzkriegs +sitzmark +sitzmarks +siva +sivaism +sivaist +sivaists +sivan +siwalik +siwash +six +sixes +sixfold +sixmo +sixmos +sixpence +sixpences +sixpenny +sixteen +sixteenfold +sixteenmo +sixteenmos +sixteenpenny +sixteens +sixteenth +sixteenths +sixth +sixthly +sixths +sixties +sixtieth +sixtieths +sixtine +sixty +sixtyfold +sixtyish +sizable +sizableness +sizably +sizar +sizars +size +sizeable +sized +sizer +sizers +sizes +sizing +sizings +sizzle +sizzled +sizzler +sizzlers +sizzles +sizzling +sizzlingly +siècle +sjaelland +sjambok +sjamboked +sjamboking +sjamboks +sjögren +ska +skag +skagerak +skagerrak +skags +skald +skaldic +skalds +skamble +skanda +skaneateles +skat +skate +skateboard +skateboarded +skateboarder +skateboarders +skateboarding +skateboards +skated +skater +skaters +skates +skating +skatol +skatole +skatoles +skatols +skean +skeane +skeans +skedaddle +skedaddled +skedaddler +skedaddlers +skedaddles +skedaddling +skeet +skeeter +skeeters +skeg +skegs +skein +skeins +skeletal +skeletally +skeleton +skeletonic +skeletonize +skeletonized +skeletonizer +skeletonizers +skeletonizes +skeletonizing +skeletons +skell +skells +skelter +skeltered +skeltering +skelters +skeltonics +skene +skenes +skep +skeps +skepsis +skeptic +skeptical +skeptically +skepticism +skeptics +skerries +skerry +sketch +sketchbook +sketchbooks +sketched +sketcher +sketchers +sketches +sketchier +sketchiest +sketchily +sketchiness +sketching +sketchpad +sketchpads +sketchy +skew +skewback +skewbacks +skewbald +skewbalds +skewed +skewer +skewered +skewering +skewers +skewing +skewness +skews +ski +skiable +skiagram +skiagrams +skiagraph +skiagraphs +skiagraphy +skiascope +skiascopes +skiascopies +skiascopy +skibob +skibobber +skibobbers +skibobbing +skibobs +skid +skidded +skidder +skidders +skiddier +skiddiest +skidding +skiddoo +skiddy +skidoo +skidoos +skidproof +skids +skied +skier +skiers +skies +skiey +skiff +skiffle +skiffs +skiing +skijoring +skilful +skill +skilled +skilless +skillessness +skillet +skillets +skillful +skillfully +skillfulness +skilling +skillings +skills +skim +skimble +skimmed +skimmer +skimmers +skimming +skimobile +skimobiles +skimp +skimped +skimpier +skimpiest +skimpily +skimpiness +skimping +skimps +skimpy +skims +skin +skinflint +skinflints +skinful +skinfuls +skinhead +skinheads +skink +skinker +skinkers +skinks +skinless +skinned +skinner +skinnerian +skinnerians +skinnerism +skinners +skinnier +skinniest +skinniness +skinning +skinny +skins +skintight +skip +skipjack +skipjacks +skippable +skipped +skipper +skippered +skippering +skippers +skipping +skips +skirl +skirled +skirling +skirls +skirmish +skirmished +skirmisher +skirmishers +skirmishes +skirmishing +skirr +skirred +skirret +skirrets +skirring +skirrs +skirt +skirted +skirter +skirters +skirting +skirts +skis +skit +skits +skitter +skittered +skittering +skitters +skittery +skittish +skittishly +skittishness +skittle +skittles +skive +skived +skiver +skivers +skives +skiving +skivvies +skivvy +skiwear +skoal +skoda +skopje +skosh +skua +skuas +skulduggeries +skulduggery +skulk +skulked +skulker +skulkers +skulking +skulks +skull +skullcap +skullcaps +skullduggeries +skullduggery +skulled +skulls +skunk +skunked +skunking +skunks +skunkweed +skunkweeds +skunkworks +sky +skyborne +skybox +skyboxes +skycap +skycaps +skydive +skydived +skydiver +skydivers +skydives +skydiving +skye +skyey +skyhook +skyhooks +skying +skyjack +skyjacked +skyjacker +skyjackers +skyjacking +skyjacks +skylark +skylarked +skylarker +skylarkers +skylarking +skylarks +skylight +skylighted +skylights +skyline +skylines +skylit +skyrocket +skyrocketed +skyrocketing +skyrockets +skyros +skysail +skysails +skyscraper +skyscrapers +skyscraping +skywalk +skywalks +skyward +skywards +skyway +skyways +skywrite +skywriter +skywriters +skywrites +skywriting +skywritten +skywrote +skíros +slab +slabbed +slabber +slabbered +slabbering +slabbers +slabbing +slablike +slabs +slack +slacked +slacken +slackened +slackening +slackens +slacker +slackers +slackest +slacking +slackly +slackness +slacks +slag +slagged +slagging +slaggy +slags +slain +slake +slaked +slakes +slaking +slalom +slalomed +slalomer +slalomers +slaloming +slalomist +slalomists +slaloms +slam +slammed +slammer +slammers +slamming +slams +slander +slandered +slanderer +slanderers +slandering +slanderous +slanderously +slanderousness +slanders +slang +slanged +slangily +slanginess +slanging +slangs +slanguage +slangy +slant +slanted +slanting +slantingly +slants +slantways +slantwise +slanty +slap +slapdash +slaphappier +slaphappiest +slaphappy +slapjack +slapjacks +slapped +slapper +slappers +slapping +slaps +slapstick +slapsticks +slash +slashed +slasher +slashers +slashes +slashing +slashingly +slat +slate +slated +slatelike +slater +slaters +slates +slatey +slather +slathered +slathering +slathers +slatier +slatiest +slating +slats +slatted +slattern +slatternliness +slatternly +slatterns +slatting +slaty +slaughter +slaughtered +slaughterer +slaughterers +slaughterhouse +slaughterhouses +slaughtering +slaughterous +slaughterously +slaughters +slav +slave +slaved +slaveholder +slaveholders +slaveholding +slaveholdings +slaver +slavered +slaveries +slavering +slavers +slavery +slaves +slavey +slaveys +slavic +slavicist +slavicists +slaving +slavish +slavishly +slavishness +slavism +slavist +slavists +slavocracies +slavocracy +slavocrat +slavocratic +slavocrats +slavonia +slavonian +slavonians +slavonic +slavophil +slavophile +slavophiles +slavophilism +slavophils +slavs +slaw +slaws +slay +slayed +slayer +slayers +slaying +slays +sle +sleave +sleaves +sleaze +sleazebag +sleazebags +sleazeball +sleazeballs +sleazier +sleaziest +sleazily +sleaziness +sleazo +sleazy +sled +sledded +sledder +sledders +sledding +sledge +sledged +sledgehammer +sledgehammered +sledgehammering +sledgehammers +sledges +sledging +sleds +sleek +sleeked +sleeken +sleekened +sleekening +sleekens +sleeker +sleekest +sleeking +sleekly +sleekness +sleeks +sleep +sleeper +sleepers +sleepier +sleepiest +sleepily +sleepiness +sleeping +sleepless +sleeplessly +sleeplessness +sleeplike +sleepover +sleepovers +sleeps +sleepwalk +sleepwalked +sleepwalker +sleepwalkers +sleepwalking +sleepwalks +sleepwear +sleepy +sleepyhead +sleepyheads +sleet +sleeted +sleeting +sleets +sleety +sleeve +sleeved +sleeveless +sleevelet +sleevelets +sleeves +sleeving +sleigh +sleighed +sleigher +sleighers +sleighing +sleighs +sleight +sleights +slender +slenderer +slenderest +slenderize +slenderized +slenderizes +slenderizing +slenderly +slenderness +slept +sles +sleuth +sleuthed +sleuthhound +sleuthhounds +sleuthing +sleuths +slew +slewed +slewing +slews +slice +sliceable +sliced +slicer +slicers +slices +slicing +slick +slicked +slicken +slickened +slickener +slickeners +slickening +slickens +slickenside +slickensides +slicker +slickers +slickest +slicking +slickly +slickness +slickrock +slicks +slid +slidden +slide +slider +sliders +slides +slideway +slideways +sliding +slier +sliest +slight +slighted +slighter +slightest +slighting +slightingly +slightly +slightness +slights +slim +slime +slimeball +slimeballs +slimed +slimes +slimier +slimiest +slimily +sliminess +sliming +slimly +slimmed +slimmer +slimmers +slimmest +slimming +slimnastics +slimness +slimpsy +slims +slimsier +slimsiest +slimsy +slimy +sling +slinger +slingers +slinging +slings +slingshot +slingshots +slink +slinked +slinkier +slinkiest +slinkily +slinkiness +slinking +slinkingly +slinks +slinky +slip +slipcase +slipcased +slipcases +slipcover +slipcovered +slipcovering +slipcovers +slipform +slipformed +slipforming +slipforms +slipknot +slipknots +slipover +slipovers +slippage +slipped +slipper +slippered +slipperier +slipperiest +slipperiness +slippers +slipperwort +slipperworts +slippery +slippier +slippiest +slipping +slippy +slips +slipshod +slipshoddiness +slipshodness +slipslop +slipslops +slipsole +slipsoles +slipstitch +slipstitches +slipstream +slipstreamed +slipstreaming +slipstreams +slipup +slipups +slipware +slipway +slipways +slit +slither +slithered +slithering +slithers +slithery +slitless +slits +slitter +slitters +slitting +slitty +sliver +slivered +slivering +slivers +slivery +slivovitz +slob +slobber +slobbered +slobberer +slobberers +slobbering +slobbers +slobbery +slobbish +slobby +slobs +sloe +sloes +slog +slogan +sloganeer +sloganeered +sloganeering +sloganeers +sloganize +sloganized +sloganizer +sloganizers +sloganizes +sloganizing +slogans +slogged +slogger +sloggers +slogging +slogs +sloop +sloops +slop +slope +sloped +sloper +slopers +slopes +sloping +slopingly +slopped +sloppier +sloppiest +sloppily +sloppiness +slopping +sloppy +slops +slopwork +slosh +sloshed +sloshes +sloshing +sloshy +slot +slotback +slotbacks +sloth +slothful +slothfully +slothfulness +sloths +slots +slotted +slotting +slouch +slouched +sloucher +slouchers +slouches +slouchier +slouchiest +slouchily +slouchiness +slouching +slouchy +slough +sloughed +sloughing +sloughs +sloughy +slovak +slovakia +slovakian +slovakians +slovaks +sloven +slovene +slovenes +slovenia +slovenian +slovenians +slovenlier +slovenliest +slovenliness +slovenly +slovens +slow +slowdown +slowdowns +slowed +slower +slowest +slowing +slowish +slowly +slowness +slowpoke +slowpokes +slows +slowwitted +slowworm +slowworms +sloyd +sloyds +slub +slubbed +slubbing +slubs +sludge +sludged +sludges +sludgiest +sludging +sludgy +slue +slued +slues +slug +slugabed +slugabeds +slugfest +slugfests +sluggard +sluggardly +sluggardness +sluggards +slugged +slugger +sluggers +slugging +sluggish +sluggishly +sluggishness +slugs +sluice +sluiced +sluices +sluiceway +sluiceways +sluicing +sluicy +sluing +slum +slumber +slumbered +slumberer +slumberers +slumbering +slumberingly +slumberous +slumberously +slumberousness +slumbers +slumbery +slumbrous +slumgullion +slumgullions +slumlord +slumlords +slummed +slummer +slummier +slummiest +slumming +slummy +slump +slumped +slumpflation +slumping +slumps +slums +slung +slungshot +slungshots +slunk +slur +slurb +slurbs +slurp +slurped +slurping +slurps +slurred +slurried +slurries +slurring +slurry +slurrying +slurs +slush +slushed +slushes +slushier +slushiest +slushily +slushiness +slushing +slushy +slut +sluts +sluttish +sluttishly +sluttishness +slutty +sly +slyboots +slyer +slyest +slyly +slyness +slype +slypes +smack +smacked +smacker +smackers +smacking +smacks +small +smallclothes +smaller +smallest +smallholder +smallholders +smallholding +smallholdings +smallish +smallmouth +smallness +smallpox +smalls +smallsword +smallswords +smalltime +smalltimer +smalltimers +smalt +smalti +smaltine +smaltines +smaltite +smaltites +smalto +smalts +smaragd +smaragdine +smaragdite +smaragdites +smarm +smarmier +smarmiest +smarmily +smarminess +smarmy +smart +smarted +smarten +smartened +smartening +smartens +smarter +smartest +smartie +smarties +smarting +smartly +smartness +smarts +smartweed +smartweeds +smarty +smash +smashed +smasher +smashers +smashes +smashing +smashingly +smashup +smashups +smatter +smattered +smatterer +smatterers +smattering +smatterings +smatters +smaze +smazes +smear +smearcase +smearcases +smeared +smearer +smearers +smearier +smeariest +smeariness +smearing +smears +smeary +smectic +smectite +smectites +smectitic +smegma +smell +smelled +smeller +smellers +smellier +smelliest +smelling +smells +smelly +smelt +smelted +smelter +smelteries +smelters +smeltery +smelting +smelts +smetana +smew +smews +smidge +smidgen +smidgens +smidgeon +smidgeons +smidgin +smidgins +smiercase +smilax +smilaxes +smile +smiled +smileless +smiler +smilers +smiles +smiley +smiling +smilingly +smilingness +smilodons +smilodonss +smily +smirch +smirched +smirches +smirching +smirk +smirked +smirker +smirkers +smirkily +smirking +smirkingly +smirks +smirky +smite +smiter +smiters +smites +smith +smithereens +smitheries +smithery +smithfield +smithies +smiths +smithsonian +smithsonite +smithsonites +smithy +smiting +smitten +smock +smocked +smocking +smockings +smocks +smog +smoggier +smoggiest +smoggy +smogless +smokable +smoke +smokeable +smoked +smokehouse +smokehouses +smokejack +smokejacks +smokejumper +smokejumpers +smokeless +smokelike +smoker +smokers +smokes +smokescreen +smokescreens +smokestack +smokestacks +smokey +smokier +smokiest +smokily +smokiness +smoking +smoky +smolder +smoldered +smoldering +smolderingly +smolders +smolensk +smollett +smolt +smolts +smooch +smooched +smooches +smooching +smoochy +smooth +smoothbore +smoothbores +smoothed +smoothen +smoothened +smoothening +smoothens +smoother +smoothers +smoothes +smoothest +smoothie +smoothies +smoothing +smoothly +smoothness +smooths +smoothy +smorgasbord +smorgasbords +smote +smother +smothered +smothering +smothers +smothery +smoulder +smouldered +smouldering +smoulders +smudge +smudged +smudges +smudgier +smudgiest +smudgily +smudginess +smudging +smudgy +smug +smugger +smuggest +smuggle +smuggled +smuggler +smugglers +smuggles +smuggling +smugly +smugness +smut +smutch +smutched +smutches +smutching +smutchy +smuts +smutted +smuttier +smuttiest +smuttily +smuttiness +smutting +smutty +smyrna +snack +snacked +snacker +snackers +snacking +snacks +snaffle +snaffled +snaffles +snaffling +snafu +snafued +snafuing +snafus +snag +snagged +snagging +snaggleteeth +snaggletooth +snaggletoothed +snaggy +snags +snail +snaillike +snails +snake +snake's +snakebird +snakebirds +snakebit +snakebite +snakebites +snakebitten +snaked +snakefish +snakefishes +snakehead +snakeheads +snakelike +snakemouth +snakemouths +snakeroot +snakeroots +snakes +snakeskin +snakeskins +snakestone +snakestones +snakeweed +snakeweeds +snakey +snakier +snakiest +snakily +snakiness +snaking +snaky +snap +snapback +snapbacks +snapdragon +snapdragons +snapped +snapper +snappers +snappier +snappiest +snappily +snappiness +snapping +snappish +snappishly +snappishness +snappy +snaps +snapshoot +snapshooter +snapshooters +snapshooting +snapshoots +snapshot +snapshots +snare +snared +snarer +snarers +snares +snaring +snarky +snarl +snarled +snarler +snarlers +snarling +snarlingly +snarls +snarly +snatch +snatched +snatcher +snatchers +snatches +snatchier +snatchiest +snatching +snatchy +snath +snathe +snathes +snaths +snazzier +snazziest +snazziness +snazzy +sneak +sneaked +sneaker +sneakered +sneakers +sneakier +sneakiest +sneakily +sneakiness +sneaking +sneakingly +sneaks +sneaky +sneer +sneered +sneerer +sneerers +sneerful +sneering +sneeringly +sneers +sneery +sneeze +sneezed +sneezer +sneezers +sneezes +sneezeweed +sneezeweeds +sneezewort +sneezeworts +sneezing +sneezy +snell +snellen +snells +snib +snibbed +snibbing +snibs +snick +snicked +snicker +snickered +snickerer +snickerers +snickering +snickeringly +snickers +snickersnee +snickersnees +snickery +snicking +snicks +snide +snidely +snideness +snider +snidest +sniff +sniffable +sniffed +sniffer +sniffers +sniffier +sniffiest +sniffily +sniffiness +sniffing +sniffish +sniffishly +sniffishness +sniffle +sniffled +sniffler +snifflers +sniffles +sniffling +sniffly +sniffs +sniffy +snifter +snifters +snigger +sniggered +sniggerer +sniggerers +sniggering +sniggers +sniggle +sniggled +sniggles +sniggling +snip +snipe +sniped +snipefish +snipefishes +sniper +snipers +sniperscope +sniperscopes +snipes +sniping +snipped +snipper +snippers +snippersnapper +snippersnappers +snippet +snippetier +snippetiest +snippets +snippety +snippier +snippiest +snippily +snippiness +snipping +snippy +snips +snit +snitch +snitched +snitcher +snitchers +snitches +snitching +snits +snivel +sniveled +sniveler +snivelers +sniveling +snivelled +snivelling +snivels +snob +snobberies +snobbery +snobbier +snobbiest +snobbish +snobbishly +snobbishness +snobbism +snobby +snobs +snoek +snoeks +snollygoster +snollygosters +snood +snooded +snooding +snoods +snook +snooker +snookered +snookering +snookers +snooks +snoop +snooped +snooper +snoopers +snoopier +snoopiest +snoopily +snoopiness +snooping +snoops +snoopy +snoot +snooted +snootier +snootiest +snootily +snootiness +snooting +snoots +snooty +snooze +snoozed +snoozer +snoozers +snoozes +snoozing +snoozle +snoozled +snoozles +snoozling +snore +snored +snorer +snorers +snores +snoring +snorkel +snorkeled +snorkeler +snorkelers +snorkeling +snorkels +snort +snorted +snorter +snorters +snorting +snorts +snot +snots +snottier +snottiest +snottily +snottiness +snotty +snout +snouted +snoutish +snouts +snouty +snow +snowball +snowballed +snowballing +snowballs +snowbank +snowbanks +snowbell +snowbells +snowbelt +snowbelts +snowberries +snowberry +snowbird +snowbirds +snowblink +snowblinks +snowblower +snowblowers +snowboard +snowboarded +snowboarder +snowboarders +snowboarding +snowboards +snowbound +snowbrush +snowbrushes +snowbush +snowbushes +snowcap +snowcapped +snowcaps +snowdrift +snowdrifts +snowdrop +snowdrops +snowed +snowfall +snowfalls +snowfield +snowfields +snowflake +snowflakes +snowier +snowiest +snowily +snowiness +snowing +snowless +snowmaker +snowmakers +snowmaking +snowmakings +snowman +snowmelt +snowmelts +snowmen +snowmobile +snowmobiler +snowmobilers +snowmobiles +snowmobiling +snowmobilist +snowmobilists +snowpack +snowpacks +snowplough +snowploughs +snowplow +snowplowed +snowplowing +snowplows +snows +snowscape +snowscapes +snowshed +snowsheds +snowshoe +snowshoed +snowshoeing +snowshoer +snowshoers +snowshoes +snowslide +snowslides +snowstorm +snowstorms +snowsuit +snowsuits +snowy +snub +snubbed +snubber +snubbers +snubbiness +snubbing +snubby +snubness +snubs +snuck +snuff +snuffbox +snuffboxes +snuffed +snuffer +snuffers +snuffing +snuffle +snuffled +snuffler +snufflers +snuffles +snuffling +snuffly +snuffs +snuffy +snug +snugged +snugger +snuggeries +snuggery +snuggest +snugging +snuggle +snuggled +snuggles +snuggling +snuggly +snugly +snugness +snugs +so +soak +soakage +soaked +soaker +soakers +soaking +soaks +soap +soapbark +soapbarks +soapberries +soapberry +soapbox +soapboxed +soapboxes +soapboxing +soaped +soaper +soapers +soapier +soapiest +soapily +soapiness +soaping +soaps +soapstone +soapsuds +soapwort +soapworts +soapy +soar +soared +soarer +soarers +soaring +soaringly +soarings +soars +soave +soaves +sob +sobbed +sobbing +sobbingly +sober +sobered +soberer +soberest +sobering +soberize +soberized +soberizes +soberizing +soberly +soberness +sobers +sobersided +sobersidedness +sobersides +sobriety +sobriquet +sobriquets +sobs +soca +socage +socager +socagers +socages +socas +soccage +soccages +soccer +sociabilities +sociability +sociable +sociableness +sociables +sociably +social +socialism +socialist +socialistic +socialistically +socialists +socialite +socialites +socialities +sociality +socialization +socializations +socialize +socialized +socializer +socializers +socializes +socializing +socially +socials +societal +societally +societies +society +socinian +socinianism +socinians +sociobiological +sociobiologist +sociobiologists +sociobiology +sociocultural +socioculturally +socioeconomic +socioeconomically +sociogram +sociograms +sociohistorical +sociolinguist +sociolinguistic +sociolinguistics +sociolinguists +sociologese +sociologic +sociological +sociologically +sociologist +sociologists +sociology +sociometric +sociometry +sociopath +sociopathic +sociopaths +sociopolitical +sociopsychological +socioreligious +sociosexual +sock +sockdolager +sockdolagers +sockdologer +sockdologers +socked +socket +socketed +socketing +sockets +sockeye +sockeyes +socking +sockless +socko +socks +socle +socles +socotra +socrates +socratic +socratically +sod +soda +sodalist +sodalists +sodalite +sodalites +sodalities +sodality +sodas +sodbuster +sodbusters +sodded +sodden +soddened +soddening +soddenly +soddenness +soddens +sodding +sodic +sodium +sodom +sodomist +sodomists +sodomite +sodomites +sodomitic +sodomitical +sodomize +sodomized +sodomizes +sodomizing +sodomy +sods +soever +sofa +sofar +sofars +sofas +soffit +soffits +sofia +soft +softback +softbacks +softball +softballer +softballers +softballs +softbound +softcover +soften +softened +softener +softeners +softening +softens +softer +softest +softhead +softheaded +softheadedly +softheadedness +softheads +softhearted +softheartedly +softheartedness +softie +softies +softish +softly +softness +softnesses +softshell +softshells +software +softwood +softwoods +softy +sogdian +sogdians +soggier +soggiest +soggily +sogginess +soggy +sognafjord +soho +soigné +soignée +soil +soilage +soilborne +soiled +soiler +soiling +soilism +soilless +soils +soilure +soiree +soirees +soirée +soirées +soixante +sojourn +sojourned +sojourner +sojourners +sojourning +sojourns +soke +sokeman +sokemen +sokes +sol +sola +solace +solaced +solacement +solacer +solacers +solaces +solacing +solan +solanaceous +solanin +solanine +solanines +solanins +solans +solanum +solanums +solar +solaria +solarimeter +solarimeters +solarium +solariums +solarization +solarizations +solarize +solarized +solarizes +solarizing +solatia +solation +solatium +sold +soldan +soldans +solder +solderability +soldered +solderer +solderers +soldering +solders +soldi +soldier +soldiered +soldieries +soldiering +soldierly +soldiers +soldiership +soldiery +soldo +sole +solecism +solecisms +solecist +solecistic +solecists +soled +solei +solely +solemn +solemner +solemnest +solemnified +solemnifies +solemnify +solemnifying +solemnities +solemnity +solemnization +solemnizations +solemnize +solemnized +solemnizes +solemnizing +solemnly +solemnness +soleness +solenodon +solenodons +solenoid +solenoidal +solenoidally +solenoids +soleplate +soleplates +soleprint +soleprints +soles +soleus +solfatara +solfataras +solfataric +solfeggi +solfeggio +solfeggios +solferino +solferinos +solfège +solgel +solicit +solicitant +solicitants +solicitation +solicitations +solicited +soliciting +solicitor +solicitors +solicitorship +solicitous +solicitously +solicitousness +solicits +solicitude +solicitudes +solid +solidago +solidagos +solidarism +solidarist +solidaristic +solidarists +solidarity +solider +solidest +solidi +solidification +solidifications +solidified +solidifier +solidifiers +solidifies +solidify +solidifying +solidity +solidly +solidness +solids +solidus +solifluction +soliloquies +soliloquist +soliloquists +soliloquize +soliloquized +soliloquizer +soliloquizers +soliloquizes +soliloquizing +soliloquy +soliman +soling +solipsism +solipsist +solipsistic +solipsistically +solipsists +solitaire +solitaires +solitarian +solitarians +solitaries +solitarily +solitariness +solitary +soliton +solitons +solitude +solitudinarian +solitudinarians +solleret +sollerets +solmization +solmizations +solo +soloed +soloing +soloist +soloistic +soloists +solomon +solomonic +solomons +solon +solonchak +solonchaks +solonetz +solonetzic +solons +solos +sols +solstice +solstices +solstitial +solubilities +solubility +solubilization +solubilizations +solubilize +solubilized +solubilizes +solubilizing +soluble +solubleness +solubly +solum +solums +solus +solute +solutes +solution +solutions +solutrean +solutrian +solvability +solvable +solvableness +solvate +solvated +solvates +solvating +solvation +solvations +solvay +solve +solved +solvency +solvent +solventless +solvently +solvents +solver +solvers +solves +solving +solvolysis +solvolytic +soma +somali +somalia +somalian +somalians +somaliland +somalis +somas +somata +somatic +somatically +somatogenetic +somatogenic +somatologic +somatological +somatologist +somatologists +somatology +somatomedin +somatomedins +somatoplasm +somatoplasms +somatoplastic +somatopleural +somatopleure +somatopleures +somatopleuric +somatosensory +somatostatin +somatostatins +somatotherapies +somatotherapy +somatotrophin +somatotrophins +somatotropic +somatotropin +somatotropins +somatotype +somatotypes +somatotypic +somber +somberly +somberness +sombre +sombrero +sombreros +sombrous +some +somebodies +somebody +somebody's +someday +somehow +someone +someone's +someplace +somersault +somersaulted +somersaulting +somersaults +somerset +somersets +somersetted +somersetting +somesthetic +something +sometime +sometimes +someway +someways +somewhat +somewhen +somewhere +somewheres +somewhither +somite +somites +somitic +somme +sommelier +sommeliers +somnambulant +somnambular +somnambulate +somnambulated +somnambulates +somnambulating +somnambulation +somnambulations +somnambulism +somnambulist +somnambulistic +somnambulistically +somnambulists +somnifacient +somnifacients +somniferous +somniferously +somnific +somniloquies +somniloquist +somniloquists +somniloquy +somnolence +somnolent +somnolently +son +sonance +sonances +sonant +sonants +sonar +sonata +sonatas +sonatina +sonatinas +sonde +sondes +sone +sones +song +songbird +songbirds +songbook +songbooks +songfest +songfests +songful +songfully +songfulness +songless +songlessly +songlike +songs +songsmith +songsmiths +songster +songsters +songstress +songstresses +songwriter +songwriters +songwriting +sonhood +sonic +sonically +sonicate +sonicated +sonicates +sonicating +sonication +sonications +sonless +sonly +sonnet +sonneteer +sonneteering +sonneteers +sonnets +sonnies +sonny +sonobuoy +sonobuoys +sonogram +sonograms +sonograph +sonographer +sonographers +sonographic +sonographs +sonography +sonometer +sonometers +sonorant +sonorants +sonorities +sonority +sonorous +sonorously +sonorousness +sons +sonship +soochong +soochongs +soon +sooner +sooners +soonest +soot +sooted +sooth +soothe +soothed +soother +soothers +soothes +soothfast +soothing +soothingly +soothingness +soothly +sooths +soothsaid +soothsay +soothsayer +soothsayers +soothsaying +soothsayings +soothsays +sootier +sootiest +sootily +sootiness +sooting +soots +sooty +sop +sopaipilla +sopapilla +sophism +sophisms +sophist +sophistic +sophistical +sophistically +sophisticate +sophisticated +sophisticatedly +sophisticates +sophisticating +sophistication +sophistications +sophisticator +sophisticators +sophistries +sophistry +sophists +sophoclean +sophocles +sophomore +sophomores +sophomoric +sophomorically +sophonias +sopor +soporiferous +soporiferously +soporiferousness +soporific +soporifically +soporifics +sopors +sopped +soppier +soppiest +soppiness +sopping +soppy +sopranino +sopraninos +soprano +sopranos +sops +sora +soras +sorb +sorbability +sorbable +sorbate +sorbates +sorbed +sorbefacient +sorbefacients +sorbent +sorbents +sorbet +sorbets +sorbian +sorbians +sorbic +sorbing +sorbitol +sorbonne +sorbose +sorboses +sorbs +sorcerer +sorcerers +sorceress +sorceresses +sorcerous +sorcerously +sorcery +sordid +sordidly +sordidness +sordini +sordino +sords +sore +sored +soredia +soredial +soredium +sorehead +soreheaded +soreheads +sorely +soreness +sorer +sores +sorest +sorgho +sorghos +sorghum +sorghums +sorgo +sorgos +sori +soricine +soring +sorites +soroptimist +soroptimists +sororal +sororate +sororates +sororicidal +sororicide +sororicides +sororities +sorority +sorption +sorptive +sorrel +sorrels +sorrento +sorrier +sorriest +sorrily +sorriness +sorrow +sorrowed +sorrower +sorrowers +sorrowful +sorrowfully +sorrowfulness +sorrowing +sorrows +sorry +sort +sortable +sortation +sortations +sorted +sorter +sorters +sortie +sortied +sortieing +sorties +sortilege +sortileges +sorting +sortition +sortitions +sorts +sorus +sos +sostenuti +sostenuto +sostenutos +sot +soteriologic +soteriological +soteriology +sothic +sotho +sotol +sotols +sots +sotted +sottedly +sottedness +sottish +sottishly +sottishness +sotto +sou +sou'wester +sou'westers +souari +soubise +soubises +soubrette +soubrettes +soubriquet +soubriquets +souchong +souchongs +souci +soudan +soudans +soufflé +souffléd +soufflés +soufrière +sough +soughed +soughing +soughs +sought +souk +souks +soul +souled +soulful +soulfully +soulfulness +soulless +soullessly +soullessness +soulmate +soulmates +souls +sound +soundable +soundalike +soundboard +soundboards +sounded +sounder +sounders +soundest +sounding +soundingly +soundings +soundless +soundlessly +soundlessness +soundly +soundman +soundmen +soundness +soundproof +soundproofed +soundproofing +soundproofs +sounds +soundstage +soundstages +soundtrack +soundtracks +soup +souped +soupier +soupiest +soups +soupspoon +soupspoons +soupy +soupçon +soupçons +sour +sourball +sourballs +source +sourcebook +sourcebooks +sourced +sourceless +sources +sourcing +sourdine +sourdines +sourdough +sourdoughs +soured +sourer +sourest +souring +sourish +sourly +sourness +sourpuss +sourpusses +sours +soursop +soursops +sourwood +sourwoods +sous +sousa +sousaphone +sousaphones +souse +soused +souses +sousing +souslik +sousliks +soutache +soutaches +soutane +soutanes +south +southampton +southbound +southdown +southeast +southeaster +southeasterly +southeastern +southeasterner +southeasterners +southeasternmost +southeasters +southeastward +southeastwardly +southeastwards +souther +southerlies +southerly +southern +southerner +southerners +southernism +southernisms +southernmost +southernness +southernwood +southernwoods +southers +southey +southing +southings +southland +southlander +southlanders +southlands +southpaw +southpaws +southron +southrons +southward +southwardly +southwards +southwest +southwester +southwesterly +southwestern +southwesterner +southwesterners +southwesternmost +southwesters +southwestward +southwestwardly +southwestwards +souvenir +souvenirs +souvlaki +souvlakia +sovereign +sovereignly +sovereigns +sovereignties +sovereignty +soviet +sovietism +sovietization +sovietizations +sovietize +sovietized +sovietizes +sovietizing +sovietologist +sovietologists +sovietology +soviets +sovkhoz +sovkhozes +sovkhozy +sovran +sovrans +sovranties +sovranty +sow +sowbellies +sowbelly +sowbread +sowbreads +sowed +sowens +sower +sowers +sowetan +sowetans +soweto +sowing +sowings +sown +sows +sox +soxer +soxers +soy +soya +soybean +soybeans +soymilk +sozzled +spa +space +spaceband +spacebands +spacebar +spacebars +spaceborne +spacebridge +spacebridges +spacecraft +spaced +spacefarer +spacefarers +spacefaring +spacefarings +spaceflight +spaceflights +spaceless +spaceman +spacemen +spaceport +spaceports +spacer +spacers +spaces +spaceship +spaceships +spacesick +spacesuit +spacesuits +spacewalk +spacewalked +spacewalker +spacewalkers +spacewalking +spacewalks +spaceward +spacey +spacial +spacier +spaciest +spacing +spacings +spacious +spaciously +spaciousness +spackle +spackled +spackles +spackling +spacy +spade +spaded +spadefish +spadefishes +spadefoot +spadeful +spadefuls +spader +spaders +spades +spadework +spadices +spadille +spading +spadix +spaetzle +spaetzles +spaghetti +spaghettilike +spaghettini +spaghettis +spagyric +spagyrical +spahi +spahis +spain +spall +spallable +spallation +spallations +spalled +spalling +spalls +spalpeen +spalpeens +spam +spammed +spamming +spams +span +spanakopita +spanakopitas +spandau +spandex +spandrel +spandrels +spandril +spandrils +spang +spangle +spangled +spangles +spangling +spanglish +spangly +spaniard +spaniards +spaniel +spaniels +spanish +spanishness +spank +spanked +spanker +spankers +spanking +spankingly +spankings +spanks +spanned +spanner +spanners +spanning +spanokopita +spans +spanworm +spanworms +spar +spare +spareable +spared +sparely +spareness +sparer +sparerib +spareribs +sparers +spares +sparest +sparge +sparged +sparger +spargers +sparges +sparging +sparid +sparids +sparing +sparingly +sparingness +spark +sparked +sparker +sparkers +sparkier +sparkiest +sparkily +sparking +sparkish +sparkle +sparkleberries +sparkleberry +sparkled +sparkler +sparklers +sparkles +sparklier +sparkliest +sparkling +sparklingly +sparkly +sparkplug +sparkplugged +sparkplugging +sparkplugs +sparks +sparky +sparling +sparlings +sparred +sparring +sparrow +sparrowgrass +sparrowlike +sparrows +spars +sparse +sparsely +sparseness +sparser +sparsest +sparsity +sparta +spartacist +spartacists +spartacus +spartan +spartanism +spartanly +spartans +sparteine +sparteines +spas +spasm +spasmodic +spasmodically +spasmolytic +spasmolytics +spasms +spastic +spastically +spasticity +spastics +spat +spatchcock +spatchcocked +spatchcocking +spatchcocks +spate +spates +spathe +spathes +spathic +spathulate +spatial +spatiality +spatially +spatiotemporal +spatiotemporally +spats +spatted +spatter +spatterdock +spatterdocks +spattered +spattering +spatters +spatting +spatula +spatular +spatulas +spatulate +spatzle +spatzles +spavin +spavined +spawn +spawned +spawner +spawners +spawning +spawns +spay +spayed +spaying +spays +spaz +spazzes +speak +speakable +speakeasies +speakeasy +speaker +speakerphone +speakerphones +speakers +speakership +speakerships +speaking +speaks +spear +speared +spearer +spearers +spearfish +spearfished +spearfisher +spearfishers +spearfishes +spearfishing +speargun +spearguns +spearhead +spearheaded +spearheading +spearheads +spearing +spearlike +spearman +spearmen +spearmint +spearmints +spears +spearwort +spearworts +spec +spec'd +spec'er +spec'ers +spec'ing +specced +speccing +special +specialism +specialisms +specialist +specialistic +specialists +specialities +speciality +specialization +specializations +specialize +specialized +specializes +specializing +specially +specialness +specials +specialties +specialty +speciate +speciated +speciates +speciating +speciation +speciational +speciations +specie +species +speciesism +speciesist +speciesists +specifiable +specific +specifically +specification +specifications +specificity +specificness +specifics +specified +specifier +specifiers +specifies +specify +specifying +specimen +specimens +speciosity +specious +speciously +speciousness +speck +specked +specking +speckle +speckled +speckles +speckling +specks +specs +spectacle +spectacled +spectacles +spectacular +spectacularity +spectacularly +spectaculars +spectate +spectated +spectates +spectating +spectator +spectatorial +spectators +spectatorship +spectatorships +specter +specters +spectinomycin +spectinomycins +spectra +spectral +spectrality +spectrally +spectralness +spectre +spectres +spectrin +spectrins +spectrofluorimeter +spectrofluorimeters +spectrofluorometer +spectrofluorometers +spectrofluorometric +spectrofluorometry +spectrogram +spectrograms +spectrograph +spectrographic +spectrographically +spectrographs +spectrography +spectroheliogram +spectroheliograms +spectroheliograph +spectroheliographic +spectroheliographs +spectroheliography +spectrohelioscope +spectrohelioscopes +spectrohelioscopic +spectrometer +spectrometers +spectrometric +spectrometry +spectrophotometer +spectrophotometers +spectrophotometric +spectrophotometrical +spectrophotometrically +spectrophotometry +spectroscope +spectroscopes +spectroscopic +spectroscopical +spectroscopically +spectroscopies +spectroscopist +spectroscopists +spectroscopy +spectrum +spectrums +specula +specular +specularity +specularly +speculate +speculated +speculates +speculating +speculation +speculations +speculative +speculatively +speculativeness +speculator +speculators +speculum +speculums +sped +speech +speeches +speechified +speechifier +speechifiers +speechifies +speechify +speechifying +speechless +speechlessly +speechlessness +speechmaker +speechmakers +speechmaking +speechwriter +speechwriters +speechwriting +speed +speedball +speedballs +speedboat +speedboater +speedboaters +speedboating +speedboatings +speedboats +speeded +speeder +speeders +speedier +speediest +speedily +speediness +speeding +speedings +speedo +speedometer +speedometers +speedos +speeds +speedster +speedsters +speedup +speedups +speedway +speedways +speedwell +speedwells +speedwriter +speedwriters +speedwriting +speedwritings +speedy +speiss +speisses +speleological +speleologist +speleologists +speleology +spell +spellbind +spellbinder +spellbinders +spellbinding +spellbindingly +spellbinds +spellbound +spellchecker +spellcheckers +spelldown +spelldowns +spelled +speller +spellers +spelling +spellings +spells +spelt +spelter +spelters +spelunker +spelunkers +spelunking +spencer +spencerian +spencerianism +spencerians +spencerism +spencers +spend +spendable +spender +spenders +spending +spends +spendthrift +spendthrifts +spenglerian +spenglerians +spenser +spenserian +spent +sperm +spermaceti +spermacetis +spermagonia +spermagonium +spermaries +spermary +spermatheca +spermathecas +spermatia +spermatial +spermatic +spermatid +spermatids +spermatium +spermatocyte +spermatocytes +spermatogenesis +spermatogenetic +spermatogenic +spermatogonia +spermatogonial +spermatogonium +spermatophore +spermatophores +spermatophyte +spermatophytes +spermatophytic +spermatozoa +spermatozoal +spermatozoan +spermatozoid +spermatozoids +spermatozoon +spermicidal +spermicide +spermicides +spermiogenesis +spermogonia +spermogonium +spermophile +spermophiles +spermous +sperms +sperrylite +sperrylites +spessartine +spessartines +spessartite +spessartites +spew +spewed +spewer +spewers +spewing +spews +sphagnous +sphagnum +sphalerite +sphalerites +sphene +sphenes +sphenic +sphenodon +sphenodons +sphenodont +sphenogram +sphenograms +sphenoid +sphenoidal +sphenoids +sphenopsid +sphenopsids +spheral +sphere +sphered +spheres +spheric +spherical +spherically +sphericalness +sphericity +spherics +spherier +spheriest +sphering +spheroid +spheroidal +spheroidally +spheroidic +spheroidicity +spheroids +spherometer +spherometers +spheroplast +spheroplasts +spherular +spherule +spherules +spherulite +spherulites +spherulitic +sphery +sphincter +sphincteral +sphincteric +sphincters +sphinges +sphingid +sphingids +sphingosine +sphingosines +sphinx +sphinxes +sphinxlike +sphragistics +sphygmic +sphygmogram +sphygmograms +sphygmograph +sphygmographic +sphygmographs +sphygmography +sphygmoid +sphygmomanometer +sphygmomanometers +sphygmomanometric +sphygmomanometrically +sphygmomanometry +sphygmometer +sphygmometers +spic +spica +spicae +spicas +spicate +spiccato +spiccatos +spice +spiceberries +spiceberry +spicebush +spicebushes +spiced +spiceless +spiceries +spicery +spices +spicier +spiciest +spicily +spiciness +spicing +spick +spicks +spics +spicula +spiculae +spicular +spiculate +spiculation +spiculations +spicule +spicules +spiculum +spicy +spider +spiderish +spiderlike +spiders +spiderweb +spiderwebs +spiderwort +spiderworts +spidery +spied +spiegel +spiegeleisen +spiegeleisens +spiegels +spiel +spieled +spieler +spielers +spieling +spiels +spier +spiers +spies +spiff +spiffed +spiffied +spiffier +spiffies +spiffiest +spiffily +spiffiness +spiffing +spiffs +spiffy +spiffying +spigot +spigots +spik +spike +spiked +spikelet +spikelets +spikelike +spikenard +spikenards +spiker +spikers +spikes +spikey +spikier +spikiest +spikily +spikiness +spiking +spiks +spiky +spile +spiled +spiles +spiling +spill +spillable +spillage +spillback +spillbacks +spilled +spiller +spillers +spillikin +spillikins +spilling +spillover +spillovers +spills +spillway +spillways +spilt +spilth +spilths +spin +spina +spinach +spinachlike +spinachy +spinal +spinally +spinals +spindle +spindled +spindler +spindlers +spindles +spindlier +spindliest +spindling +spindly +spindrift +spine +spined +spinel +spineless +spinelessly +spinelessness +spinelike +spinelle +spinelles +spinels +spines +spinescence +spinescent +spinet +spinets +spinier +spiniest +spiniferous +spinifex +spinifexes +spininess +spinless +spinnaker +spinnakers +spinner +spinneret +spinnerets +spinnerette +spinnerettes +spinners +spinney +spinneys +spinning +spinnings +spinocerebellar +spinoff +spinoffs +spinor +spinors +spinose +spinosely +spinosity +spinous +spinout +spinouts +spinoza +spinozism +spinozist +spinozistic +spinozists +spins +spinster +spinsterhood +spinsterish +spinsterly +spinsters +spinthariscope +spinthariscopes +spinthariscopic +spinto +spintos +spinule +spinules +spinulose +spinulous +spiny +spiracle +spiracles +spiracular +spiraea +spiraeas +spiral +spiraled +spiraling +spirality +spiralled +spiralling +spirally +spirals +spirant +spirants +spire +spirea +spireas +spired +spirem +spireme +spiremes +spirems +spires +spiriferous +spirilla +spirillum +spiring +spirit +spirited +spiritedly +spiritedness +spiriting +spiritism +spiritist +spiritistic +spiritists +spiritless +spiritlessly +spiritlessness +spiritoso +spiritous +spirits +spiritual +spiritualism +spiritualist +spiritualistic +spiritualists +spiritualities +spirituality +spiritualization +spiritualizations +spiritualize +spiritualized +spiritualizer +spiritualizers +spiritualizes +spiritualizing +spiritually +spiritualness +spirituals +spiritualties +spiritualty +spirituel +spirituelle +spirituosity +spirituous +spirituousness +spirochaete +spirochaetes +spirochetal +spirochete +spirochetes +spirochetoses +spirochetosis +spirograph +spirographic +spirographically +spirographs +spirography +spirogyra +spirogyras +spiroid +spirometer +spirometers +spirometric +spirometry +spironolactone +spironolactones +spiroplasma +spiroplasmas +spirt +spirted +spirting +spirts +spirula +spirulae +spiry +spit +spital +spitals +spitball +spitballs +spite +spited +spiteful +spitefully +spitefulness +spites +spitfire +spitfires +spithead +spiting +spits +spitsbergen +spitted +spitter +spitters +spitting +spittle +spittlebug +spittlebugs +spittoon +spittoons +spitz +spitzes +spiv +spivs +splanchnic +splanchnology +splanchnopleure +splanchnopleures +splanchnopleuric +splash +splashboard +splashboards +splashdown +splashdowns +splashed +splasher +splashers +splashes +splashguard +splashguards +splashier +splashiest +splashily +splashiness +splashing +splashy +splat +splats +splatter +splattered +splattering +splatters +splay +splayed +splayfeet +splayfoot +splayfooted +splaying +splays +spleen +spleenful +spleens +spleenwort +spleenworts +spleeny +splendent +splendid +splendidly +splendidness +splendiferous +splendiferously +splendiferousness +splendor +splendorous +splendors +splendrous +splenectomies +splenectomize +splenectomized +splenectomizes +splenectomizing +splenectomy +splenetic +splenetical +splenetically +spleneticals +splenetics +splenial +splenic +splenii +splenius +splenomegalies +splenomegaly +splice +spliced +splicer +splicers +splices +splicing +spliff +spline +splines +splint +splinted +splinter +splintered +splintering +splinters +splintery +splinting +splints +split +splits +splitter +splitters +splitting +splotch +splotched +splotches +splotchiness +splotching +splotchy +splurge +splurged +splurges +splurging +splurgy +splutter +spluttered +splutterer +spluttering +splutters +spluttery +spock +spode +spodumene +spodumenes +spoil +spoilable +spoilage +spoiled +spoiler +spoilers +spoiling +spoils +spoilsman +spoilsmen +spoilsport +spoilsports +spoilt +spokane +spoke +spoked +spoken +spokes +spokeshave +spokeshaves +spokesman +spokesmanship +spokesmen +spokespeople +spokesperson +spokespersons +spokeswoman +spokeswomen +spoking +spoleto +spoliate +spoliated +spoliates +spoliating +spoliation +spoliator +spoliators +spondaic +spondee +spondees +spondylitis +spondylitises +spondyloses +spondylosis +sponge +sponged +sponger +spongers +sponges +spongeware +spongier +spongiest +spongiform +spongin +sponginess +sponging +spongins +spongioblast +spongioblasts +spongiocyte +spongiocytes +spongocoel +spongocoels +spongy +sponson +sponsons +sponsor +sponsored +sponsorial +sponsoring +sponsors +sponsorship +sponsorships +spontaneities +spontaneity +spontaneous +spontaneously +spontaneousness +spontoon +spontoons +spoof +spoofed +spoofery +spoofing +spoofs +spoofy +spook +spooked +spookeries +spookery +spookier +spookiest +spookily +spookiness +spooking +spookish +spooks +spooky +spool +spooled +spooling +spoolings +spools +spoon +spoonable +spoonbill +spoonbills +spoondrift +spoondrifts +spooned +spoonerism +spoonerisms +spooney +spoonful +spoonfuls +spoonier +spooniest +spooning +spoons +spoonsful +spoony +spoor +spoored +spooring +spoors +sporaceous +sporades +sporadic +sporadical +sporadically +sporadicalness +sporangia +sporangial +sporangiophore +sporangiophores +sporangium +spore +spored +sporeling +sporelings +spores +sporicidal +sporicide +sporicides +sporiferous +sporing +sporocarp +sporocarps +sporocyst +sporocysts +sporocyte +sporocytes +sporogenesis +sporogenic +sporogenous +sporogonia +sporogonic +sporogonium +sporogonous +sporogony +sporont +sporonts +sporophore +sporophores +sporophyll +sporophylls +sporophyte +sporophytes +sporophytic +sporoplasm +sporoplasms +sporopollenin +sporopollenins +sporotrichoses +sporotrichosis +sporozoan +sporozoans +sporozoite +sporozoites +sporran +sporrans +sport +sported +sportfisherman +sportfishermen +sportfishing +sportful +sportfully +sportfulness +sportier +sportiest +sportif +sportily +sportiness +sporting +sportingly +sportive +sportively +sportiveness +sports +sportscast +sportscaster +sportscasters +sportscasts +sportsman +sportsmanlike +sportsmanly +sportsmanship +sportsmen +sportswear +sportswoman +sportswomen +sportswriter +sportswriters +sportswriting +sporty +sporular +sporulate +sporulated +sporulates +sporulating +sporulation +sporulations +sporulative +spot +spotless +spotlessly +spotlessness +spotlight +spotlighted +spotlighting +spotlights +spotlit +spots +spottable +spotted +spotter +spotters +spottier +spottiest +spottily +spottiness +spotting +spotty +spousal +spousals +spouse +spoused +spouseless +spouses +spousing +spout +spouted +spouter +spouters +spouting +spoutings +spouts +sprachgefühl +spraddle +spraddled +spraddles +spraddling +sprag +sprags +sprain +sprained +spraining +sprains +sprang +sprat +sprats +sprawl +sprawled +sprawler +sprawlers +sprawling +sprawls +spray +sprayed +sprayer +sprayers +spraying +sprays +spread +spreadability +spreadable +spreadably +spreader +spreaders +spreading +spreads +spreadsheet +spreadsheets +sprechstimme +sprechstimmes +spree +sprees +sprier +spriest +sprig +sprigged +sprigger +spriggers +sprigging +spright +sprightful +sprightfully +sprightfulness +sprightlier +sprightliest +sprightliness +sprightly +sprights +sprigs +sprigtail +sprigtails +spring +springal +springald +springalds +springals +springboard +springboards +springbok +springboks +springbuck +springbucks +springe +springer +springers +springes +springfield +springform +springhalt +springhalts +springhare +springhares +springhead +springheads +springhouse +springhouses +springier +springiest +springily +springiness +springing +springlet +springlets +springlike +springs +springtail +springtails +springtide +springtides +springtime +springwater +springwood +springwoods +springy +sprinkle +sprinkled +sprinkler +sprinklered +sprinklering +sprinklers +sprinkles +sprinkling +sprinklings +sprint +sprinted +sprinter +sprinters +sprinting +sprints +sprit +sprite +sprites +sprits +spritsail +spritsails +spritz +spritzed +spritzer +spritzers +spritzes +spritzing +sprocket +sprockets +sprout +sprouted +sprouting +sprouts +spruce +spruced +sprucely +spruceness +sprucer +spruces +sprucest +sprucier +spruciest +sprucing +sprucy +sprue +sprues +sprung +spry +spryer +spryest +spryly +spryness +spud +spudded +spudding +spuds +spumante +spume +spumed +spumes +spuming +spumone +spumones +spumoni +spumonis +spumous +spumy +spun +spunbonded +spunk +spunkier +spunkiest +spunkily +spunkiness +spunky +spur +spurge +spurges +spurious +spuriously +spuriousness +spurn +spurned +spurner +spurners +spurning +spurns +spurred +spurrey +spurreys +spurries +spurring +spurry +spurs +spurt +spurted +spurting +spurts +sputa +sputnik +sputniks +sputter +sputtered +sputterer +sputterers +sputtering +sputters +sputtery +sputum +spy +spyglass +spyglasses +spying +spymaster +spymasters +squab +squabble +squabbled +squabbler +squabblers +squabbles +squabbling +squabs +squad +squadded +squadding +squadron +squadrons +squads +squalamine +squalene +squalenes +squalid +squalidity +squalidly +squalidness +squall +squalled +squaller +squallers +squallier +squalliest +squalling +squalls +squally +squalor +squalors +squama +squamae +squamate +squamation +squamations +squamiform +squamosal +squamosals +squamose +squamous +squamously +squamousness +squamule +squamules +squamulose +squander +squandered +squanderer +squanderers +squandering +squanderingly +squanders +square +squared +squarely +squareness +squarer +squarers +squares +squarest +squaretail +squaretails +squaring +squarish +squarishly +squarishness +squarrose +squash +squashed +squasher +squashers +squashes +squashier +squashiest +squashily +squashiness +squashing +squashy +squat +squatly +squatness +squats +squatted +squatter +squatters +squattest +squattier +squattiest +squatting +squatty +squaw +squawfish +squawfishes +squawk +squawked +squawker +squawkers +squawkier +squawkiest +squawkily +squawking +squawks +squawky +squawroot +squawroots +squaws +squeak +squeaked +squeaker +squeakers +squeakier +squeakiest +squeakily +squeakiness +squeaking +squeaks +squeaky +squeal +squealed +squealer +squealers +squealing +squeals +squeamish +squeamishly +squeamishness +squeegee +squeegeed +squeegeeing +squeegees +squeezability +squeezable +squeeze +squeezebox +squeezeboxes +squeezed +squeezer +squeezers +squeezes +squeezing +squelch +squelched +squelcher +squelchers +squelches +squelching +squelchy +squeteague +squib +squibbed +squibbing +squibs +squid +squidded +squidding +squids +squiffed +squiffier +squiffiest +squiffy +squiggle +squiggled +squiggles +squiggling +squiggly +squill +squilla +squillae +squillas +squills +squinch +squinched +squinches +squinching +squinnied +squinnies +squinny +squinnying +squint +squinted +squinter +squinting +squintingly +squints +squinty +squirarchies +squirarchy +squire +squirearchies +squirearchy +squired +squires +squiring +squirish +squirm +squirmed +squirmer +squirmers +squirmier +squirmiest +squirminess +squirming +squirms +squirmy +squirrel +squirreled +squirrelfish +squirrelfishes +squirreling +squirrelled +squirrelling +squirrelly +squirrels +squirt +squirted +squirter +squirters +squirting +squirts +squish +squished +squishes +squishier +squishiest +squishiness +squishing +squishy +squoosh +squooshed +squooshes +squooshing +squush +squushed +squushes +squushing +sranan +sranantongo +srebrenica +sri +srinagar +st +stab +stabat +stabbed +stabber +stabbers +stabbing +stabile +stabiles +stabilities +stability +stabilization +stabilizations +stabilize +stabilized +stabilizer +stabilizers +stabilizes +stabilizing +stable +stabled +stableman +stablemate +stablemates +stablemen +stableness +stabler +stables +stablest +stabling +stablish +stablished +stablishes +stablishing +stably +stabs +staccati +staccato +staccatos +stack +stackable +stacked +stacker +stackers +stacking +stacks +stackup +stackups +stacte +stactes +staddle +staddles +stade +stades +stadholder +stadholders +stadia +stadium +stadiums +stadtholder +stadtholderate +stadtholders +stadtholdership +staff +staffed +staffer +staffers +staffing +staffordshire +staffs +stag +stage +stageable +stagecoach +stagecoaches +stagecraft +stagecrafts +staged +stageful +stagefuls +stagehand +stagehands +stagelike +stager +stagers +stages +stagestruck +stagey +stagflation +stagflationary +staggard +staggards +stagged +stagger +staggerbush +staggerbushes +staggered +staggerer +staggerers +staggering +staggeringly +staggers +staggery +stagging +staggy +staghorn +staghound +staghounds +stagier +stagiest +stagily +staginess +staging +stagings +stagirite +stagirites +stagnancy +stagnant +stagnantly +stagnate +stagnated +stagnates +stagnating +stagnation +stagnations +stags +stagy +staid +staidly +staidness +stain +stainability +stainable +stained +stainer +stainers +staining +stainless +stainlessly +stainproof +stains +stair +staircase +staircases +stairs +stairway +stairways +stairwell +stairwells +stake +staked +stakeholder +stakeholders +stakeout +stakeouts +stakes +stakhanovism +stakhanovite +stakhanovites +staking +stalactiform +stalactite +stalactites +stalactitic +stalag +stalagmite +stalagmites +stalagmitic +stalags +stale +staled +stalely +stalemate +stalemated +stalemates +stalemating +staleness +staler +stales +stalest +stalin +staling +stalingrad +stalinism +stalinist +stalinists +stalinization +stalinize +stalinized +stalinizes +stalinizing +stalinoid +stalk +stalked +stalker +stalkers +stalking +stalkless +stalks +stalky +stall +stalled +stallholder +stallholders +stalling +stallion +stallions +stalls +stalwart +stalwartly +stalwartness +stalwarts +stamen +stamens +stamina +staminal +staminate +staminode +staminodes +staminodia +staminodies +staminodium +staminody +stammel +stammels +stammer +stammered +stammerer +stammerers +stammering +stammeringly +stammers +stamp +stamped +stampede +stampeded +stampeder +stampeders +stampedes +stampeding +stamper +stampers +stamping +stampless +stamps +stance +stances +stanch +stanched +stancher +stanchers +stanches +stanching +stanchion +stanchioned +stanchioning +stanchions +stanchly +stanchness +stand +standalone +standard +standardbred +standardbreds +standardizable +standardization +standardizations +standardize +standardized +standardizer +standardizers +standardizes +standardizing +standardless +standardly +standards +standaway +standby +standbys +standdown +standdowns +standee +standees +stander +standers +standing +standings +standish +standishes +standoff +standoffish +standoffishly +standoffishness +standoffs +standout +standouts +standpat +standpatter +standpatters +standpattism +standpipe +standpipes +standpoint +standpoints +stands +standstill +standstills +standup +stanford +stanhope +stanhopes +stanine +stanines +stanislavski +stanislavskian +stanislavsky +stank +stanley +stannaries +stannary +stannic +stannite +stannites +stannous +stanovoi +stanovoy +stanza +stanzaic +stanzas +stapedectomies +stapedectomy +stapedes +stapedial +stapelia +stapelias +stapes +staph +staphs +staphylinid +staphylinids +staphylococcal +staphylococci +staphylococcic +staphylococcus +staphyloplastic +staphyloplasties +staphyloplasty +staphyloraphies +staphyloraphy +staphylorrhaphies +staphylorrhaphy +staple +stapled +stapler +staplers +staples +stapling +star +starboard +starboards +starburst +starbursts +starch +starched +starches +starchier +starchiest +starchily +starchiness +starching +starchy +stardom +stardoms +stardust +stare +stared +starer +starers +stares +starets +starfish +starfishes +starflower +starflowers +stargaze +stargazed +stargazer +stargazers +stargazes +stargazing +staring +stark +starker +starkers +starkest +starkly +starkness +starless +starlet +starlets +starlight +starlike +starling +starlings +starlit +starred +starrier +starriest +starriness +starring +starry +stars +starship +starships +starstruck +start +started +starter +starters +starting +startle +startled +startlement +startles +startling +startlingly +startlingness +starts +startsy +startup +startups +starvation +starve +starved +starveling +starvelings +starves +starving +starwort +starworts +stases +stash +stashed +stashes +stashing +stasis +stat +statable +statant +state +statecraft +stated +statedly +statehood +statehooder +statehooders +statehouse +statehouses +stateless +statelessness +statelet +statelets +statelier +stateliest +stateliness +stately +statement +statements +staten +stater +stateroom +staterooms +staters +states +stateside +statesman +statesmanlike +statesmanly +statesmanship +statesmen +stateswoman +stateswomen +statewide +static +statical +statically +statice +statices +staticky +statics +stating +station +stational +stationaries +stationary +stationed +stationer +stationers +stationery +stationhouse +stationhouses +stationing +stationmaster +stationmasters +stations +statism +statist +statistic +statistical +statistically +statistician +statisticians +statistics +statists +stative +statives +statoblast +statoblasts +statocyst +statocysts +statolith +statoliths +stator +stators +statoscope +statoscopes +stats +statuaries +statuary +statue +statues +statuesque +statuesquely +statuette +statuettes +stature +statures +status +statuses +statusy +statutable +statute +statutes +statutorily +statutory +staunch +staunched +stauncher +staunchers +staunches +staunching +staunchly +staunchness +staurolite +staurolites +staurolitic +stavanger +stave +staved +staves +stavesacre +stavesacres +staving +stay +stayed +stayer +stayers +staying +stays +staysail +staysails +staël +stead +steaded +steadfast +steadfastly +steadfastness +steadied +steadier +steadiers +steadies +steadiest +steadily +steadiness +steading +steadings +steads +steady +steadying +steak +steakhouse +steakhouses +steaks +steal +stealable +stealer +stealers +stealing +steals +stealth +stealthier +stealthiest +stealthily +stealthiness +stealthy +steam +steamboat +steamboats +steamed +steamer +steamers +steamfitter +steamfitters +steamfitting +steamier +steamiest +steamily +steaminess +steaming +steamroll +steamrolled +steamroller +steamrollered +steamrollering +steamrollers +steamrolling +steamrolls +steams +steamship +steamships +steamy +steapsin +steapsins +stearate +stearates +stearic +stearin +stearine +stearines +stearins +stearoptene +stearoptenes +steatite +steatites +steatitic +steatolysis +steatopygia +steatopygias +steatopygic +steatopygous +steatorrhea +steatorrheas +steatorrhoea +steatorrhoeas +steatoses +steatosis +stedfast +steed +steeds +steel +steele +steeled +steelhead +steelheads +steelie +steelier +steelies +steeliest +steeliness +steeling +steelmaker +steelmakers +steelmaking +steels +steelwork +steelworker +steelworkers +steelworks +steely +steelyard +steelyards +steenbok +steenboks +steep +steeped +steepen +steepened +steepening +steepens +steeper +steepers +steepest +steeping +steepish +steeple +steeplebush +steeplebushes +steeplechase +steeplechaser +steeplechasers +steeplechases +steeplechasing +steepled +steeplejack +steeplejacks +steeples +steeply +steepness +steeps +steer +steerable +steerage +steerageway +steerageways +steered +steerer +steerers +steering +steers +steersman +steersmen +steeve +steeved +steeves +steeving +steganographic +steganography +stegodon +stegodons +stegosaur +stegosaurs +stegosaurus +stegosauruses +stein +steinbeck +steinbok +steinboks +steins +steinway +stela +stelae +stelar +stele +steles +stella +stellar +stellas +stellate +stellated +stellately +stellenbosch +steller +stelliform +stellular +stem +stemless +stemma +stemmas +stemmata +stemmatic +stemmed +stemmer +stemmers +stemmier +stemmiest +stemming +stemmy +stems +stemson +stemsons +stemware +sten +stench +stenches +stenchful +stenchy +stencil +stenciled +stenciler +stencilers +stenciling +stencilled +stenciller +stencillers +stencilling +stencils +stendhal +steno +stenobath +stenobathic +stenobaths +stenograph +stenographer +stenographers +stenographic +stenographical +stenographically +stenographs +stenography +stenohaline +stenophagous +stenos +stenosed +stenoses +stenosis +stenotherm +stenothermal +stenothermic +stenothermous +stenotherms +stenotic +stenotopic +stenotype +stenotyped +stenotypes +stenotypies +stenotyping +stenotypist +stenotypists +stenotypy +stentor +stentorian +stentors +step +stepbrother +stepbrothers +stepchild +stepchildren +stepdaughter +stepdaughters +stepfamilies +stepfamily +stepfather +stepfathers +stephanotis +stephanotises +stephen +stephenson +stepladder +stepladders +steplike +stepmother +stepmothers +stepparent +stepparenting +stepparents +steppe +stepped +stepper +steppers +steppes +stepping +steppingstone +steppingstones +steps +stepsibling +stepsiblings +stepsister +stepsisters +stepson +stepsons +stepwise +steradian +steradians +stercoraceous +stercorous +sterculia +stere +stereo +stereobate +stereobates +stereochemical +stereochemistry +stereochrome +stereochromes +stereochromic +stereochromically +stereochromies +stereochromy +stereogram +stereograms +stereograph +stereographed +stereographic +stereographical +stereographically +stereographing +stereographs +stereography +stereoisomer +stereoisomeric +stereoisomerism +stereoisomerisms +stereoisomers +stereologic +stereological +stereologically +stereologist +stereologists +stereology +stereomicroscope +stereomicroscopes +stereomicroscopic +stereomicroscopically +stereomicroscopy +stereophonic +stereophonically +stereophony +stereophotographic +stereophotography +stereopsis +stereopticon +stereopticons +stereoregular +stereoregularity +stereos +stereoscope +stereoscopes +stereoscopic +stereoscopically +stereoscopist +stereoscopists +stereoscopy +stereospecific +stereospecifically +stereospecificity +stereotactic +stereotactical +stereotactically +stereotaxic +stereotaxical +stereotaxically +stereotaxies +stereotaxis +stereotaxises +stereotaxy +stereotropic +stereotropism +stereotropisms +stereotype +stereotyped +stereotyper +stereotypers +stereotypes +stereotypic +stereotypical +stereotypically +stereotypies +stereotyping +stereotypy +stereovision +stereovisions +steres +steric +sterical +sterically +sterigma +sterigmata +sterigmatic +sterilant +sterilants +sterile +sterilely +sterileness +sterility +sterilization +sterilizations +sterilize +sterilized +sterilizer +sterilizers +sterilizes +sterilizing +sterlet +sterlets +sterling +sterlingly +sterlingness +stern +sterna +sternal +sterner +sternest +sternforemost +sternite +sternites +sternly +sternmost +sternness +sternoclavicular +sternocleidomastoid +sternocleidomastoids +sternocostal +sternpost +sternposts +sterns +sternson +sternsons +sternum +sternums +sternutation +sternutations +sternutator +sternutatories +sternutators +sternutatory +sternward +sternwards +sternway +sternways +sternwheeler +sternwheelers +steroid +steroidal +steroidogenesis +steroidogenic +steroids +sterol +sterols +sterope +steropes +stertor +stertorous +stertorously +stertors +stet +stethoscope +stethoscopes +stethoscopic +stethoscopical +stethoscopically +stethoscopy +stets +stetson +stetsons +stetted +stetting +stevedore +stevedored +stevedores +stevedoring +stevengraph +stevengraphs +stevensgraph +stevensgraphs +stew +steward +stewarded +stewardess +stewardesses +stewarding +stewards +stewardship +stewardships +stewartia +stewartias +stewed +stewing +stewpan +stewpans +stewpot +stewpots +stews +stewy +sthenia +sthenias +sthenic +stibine +stibines +stibnite +stibnites +stich +stiches +stichic +stichometric +stichometry +stichomythia +stichomythias +stichomythic +stichomythies +stichomythy +stick +stickball +stickballer +stickballers +sticked +sticker +stickers +stickful +stickfuls +stickhandle +stickhandled +stickhandler +stickhandlers +stickhandles +stickhandling +stickier +stickiest +stickily +stickiness +sticking +stickle +stickleback +sticklebacks +stickled +stickler +sticklers +stickles +sticklike +stickling +stickman +stickmen +stickpin +stickpins +sticks +stickseed +stickseeds +sticktail +sticktails +sticktight +sticktights +stickum +stickums +stickup +stickups +stickweed +stickweeds +stickwork +sticky +stiction +stied +sties +stiff +stiffed +stiffen +stiffened +stiffener +stiffeners +stiffening +stiffens +stiffer +stiffest +stiffing +stiffish +stiffly +stiffness +stiffs +stifle +stifled +stifler +stiflers +stifles +stifling +stiflingly +stigma +stigmal +stigmas +stigmasterol +stigmasterols +stigmata +stigmatic +stigmatically +stigmatics +stigmatism +stigmatist +stigmatists +stigmatization +stigmatizations +stigmatize +stigmatized +stigmatizer +stigmatizers +stigmatizes +stigmatizing +stilbene +stilbenes +stilbestrol +stilbestrols +stilbite +stilbites +stile +stiles +stiletto +stilettoes +stilettos +still +stillbirth +stillbirths +stillborn +stilled +stiller +stillest +stillier +stilliest +stilliform +stilling +stillman +stillmen +stillness +stillroom +stillrooms +stills +stillson +stillsons +stilly +stilt +stilted +stiltedly +stiltedness +stilting +stilton +stilts +stimulant +stimulants +stimulate +stimulated +stimulater +stimulaters +stimulates +stimulating +stimulatingly +stimulation +stimulations +stimulative +stimulator +stimulators +stimulatory +stimuli +stimulus +sting +stingaree +stingarees +stinger +stingers +stingier +stingiest +stingily +stinginess +stinging +stingingly +stingless +stingray +stingrays +stings +stingy +stink +stinkard +stinkards +stinkaroo +stinkaroos +stinkball +stinkballs +stinkbug +stinkbugs +stinker +stinkeroo +stinkeroos +stinkers +stinkhorn +stinkhorns +stinking +stinkingly +stinkingness +stinko +stinkpot +stinkpots +stinks +stinkstone +stinkstones +stinkweed +stinkweeds +stinkwood +stinkwoods +stinky +stint +stinted +stinter +stinters +stinting +stintingly +stints +stipe +stiped +stipel +stipellate +stipels +stipend +stipendiaries +stipendiary +stipends +stipes +stipiform +stipitate +stipites +stipitiform +stipple +stippled +stippler +stipplers +stipples +stippling +stipular +stipulate +stipulated +stipulates +stipulating +stipulation +stipulations +stipulator +stipulators +stipulatory +stipule +stipuled +stipules +stir +stirabout +stirabouts +stirk +stirks +stirling +stirp +stirpes +stirps +stirred +stirrer +stirrers +stirring +stirringly +stirrings +stirrup +stirrups +stirs +stishovite +stishovites +stitch +stitched +stitcher +stitchers +stitchery +stitches +stitching +stitchwort +stitchworts +stithies +stithy +stiver +stivers +stoa +stoae +stoas +stoat +stoats +stoccado +stoccados +stochastic +stochastically +stock +stockade +stockaded +stockades +stockading +stockage +stockbreeder +stockbreeders +stockbreeding +stockbreedings +stockbroker +stockbrokerage +stockbrokers +stockbroking +stockcar +stockcars +stocked +stocker +stockers +stockfish +stockfishes +stockholder +stockholders +stockholding +stockholdings +stockholm +stockier +stockiest +stockily +stockiness +stockinet +stockinets +stockinette +stockinettes +stocking +stockinged +stockings +stockish +stockist +stockists +stockjobber +stockjobbers +stockjobbery +stockjobbing +stockkeeper +stockkeepers +stockless +stockman +stockmar +stockmen +stockowner +stockowners +stockownership +stockpile +stockpiled +stockpiler +stockpilers +stockpiles +stockpiling +stockpot +stockpots +stockroom +stockrooms +stocks +stocktaking +stocktakings +stocky +stockyard +stockyards +stodgier +stodgiest +stodgily +stodginess +stodgy +stogie +stogies +stogy +stoic +stoical +stoically +stoicalness +stoichiometric +stoichiometrically +stoichiometry +stoicism +stoics +stoke +stoked +stokehold +stokeholds +stokehole +stokeholes +stoker +stokers +stokes +stoking +stole +stolen +stoles +stolid +stolider +stolidest +stolidity +stolidly +stolidness +stollen +stollens +stolon +stolonate +stoloniferous +stoloniferously +stoma +stomach +stomachache +stomachaches +stomached +stomacher +stomachers +stomachic +stomachically +stomachics +stomaching +stomachs +stomachy +stomal +stomas +stomata +stomatal +stomate +stomates +stomatic +stomatitis +stomatitises +stomatologic +stomatological +stomatologist +stomatologists +stomatology +stomatopod +stomatopods +stomatous +stomodaea +stomodaeal +stomodaeum +stomodea +stomodeal +stomodeum +stomp +stomped +stomper +stompers +stomping +stompingly +stomps +stone +stoneboat +stoneboats +stonecat +stonecats +stonechat +stonechats +stonecrop +stonecrops +stonecutter +stonecutters +stonecutting +stoned +stonefish +stonefishes +stoneflies +stonefly +stonehearted +stonehenge +stonemason +stonemasonry +stonemasons +stoner +stoneroller +stonerollers +stoners +stones +stonewall +stonewalled +stonewaller +stonewallers +stonewalling +stonewalls +stoneware +stonewash +stonewashed +stonewashes +stonewashing +stonework +stoneworker +stoneworkers +stonewort +stoneworts +stoney +stonier +stoniest +stonily +stoniness +stoning +stony +stonyhearted +stonyheartedly +stonyheartedness +stood +stooge +stooged +stooges +stooging +stool +stooled +stoolie +stoolies +stooling +stools +stoop +stoopball +stoopballs +stooped +stooper +stoopers +stooping +stoops +stop +stopcock +stopcocks +stope +stoped +stoper +stopers +stopes +stopgap +stopgaps +stoping +stoplight +stoplights +stopover +stopovers +stoppable +stoppage +stoppages +stopped +stopper +stoppered +stoppering +stoppers +stopping +stopple +stoppled +stopples +stoppling +stops +stopwatch +stopwatches +storable +storage +storax +storaxes +store +stored +storefront +storefronts +storehouse +storehouses +storekeeper +storekeepers +storekeeping +storeowner +storeowners +storer +storeroom +storerooms +storers +stores +storeship +storeships +storewide +storey +storeyed +storeys +storied +stories +storing +stork +storks +storksbill +storksbills +storm +stormbound +stormed +stormier +stormiest +stormily +storminess +storming +storms +stormy +story +storyboard +storyboarded +storyboarding +storyboards +storybook +storybooks +storying +storyteller +storytellers +storytelling +storywriter +storywriters +stoss +stotinka +stotinki +stound +stounds +stoup +stoups +stout +stouten +stoutened +stoutening +stoutens +stouter +stoutest +stouthearted +stoutheartedly +stoutheartedness +stoutish +stoutly +stoutness +stouts +stove +stovepipe +stovepipes +stover +stovers +stoves +stovetop +stovetops +stow +stowage +stowaway +stowaways +stowed +stowing +stows +strabismal +strabismic +strabismus +strabo +strabotomies +strabotomy +strachey +strad +straddle +straddled +straddler +straddlers +straddles +straddling +stradivari +stradivarius +strads +strafe +strafed +strafer +strafers +strafes +strafing +straggle +straggled +straggler +stragglers +straggles +stragglier +straggliest +straggling +straggly +straight +straightarrow +straightaway +straightaways +straightbred +straightedge +straightedged +straightedges +straighten +straightened +straightener +straighteners +straightening +straightens +straighter +straightest +straightforward +straightforwardly +straightforwardness +straightforwards +straightish +straightjacket +straightjacketed +straightjacketing +straightjackets +straightlaced +straightly +straightness +straights +straightway +strain +strained +strainer +strainers +straining +strainometer +strainometers +strains +strait +straiten +straitened +straitening +straitens +straitjacket +straitjacketed +straitjacketing +straitjackets +straitlaced +straitlacedly +straitlacedness +straitly +straitness +straits +strake +strakes +stramonium +stramoniums +strand +stranded +strandedness +stranding +strandline +strandlines +strands +strange +strangely +strangeness +stranger +strangers +strangest +strangle +strangled +stranglehold +strangleholds +strangler +stranglers +strangles +strangling +strangulate +strangulated +strangulates +strangulating +strangulation +strangulations +stranguries +strangury +strap +straphang +straphanger +straphangers +straphanging +straphangs +straphung +strapless +straplesses +strappado +strappadoes +strapped +strapper +strappers +strapping +straps +strasbourg +strass +strasses +strata +stratagem +stratagems +stratal +strategic +strategical +strategically +strategics +strategies +strategist +strategists +strategize +strategized +strategizes +strategizing +strategy +stratford +strath +strathclyde +straths +strathspey +strathspeys +strati +straticulate +straticulation +straticulations +stratification +stratificational +stratified +stratifies +stratiform +stratify +stratifying +stratigraphic +stratigraphical +stratigraphically +stratigraphy +stratocracies +stratocracy +stratocratic +stratocumuli +stratocumulus +stratopause +stratopauses +stratosphere +stratospheres +stratospheric +stratospherically +stratovolcano +stratovolcanos +stratum +stratums +stratus +strauss +stravinsky +straw +strawberries +strawberry +strawboard +strawboards +strawflower +strawflowers +strawhat +straws +strawworm +strawworms +strawy +stray +strayed +strayer +strayers +straying +strays +streak +streaked +streaker +streakers +streakier +streakiest +streakily +streakiness +streaking +streaks +streaky +stream +streambed +streambeds +streamed +streamer +streamers +streaming +streamlet +streamlets +streamline +streamlined +streamliner +streamliners +streamlines +streamlining +streams +streamside +streamsides +streamy +street +streetcar +streetcars +streeter +streeters +streetlight +streetlights +streets +streetscape +streetscapes +streetwalker +streetwalkers +streetwalking +streetwise +strength +strengthen +strengthened +strengthener +strengtheners +strengthening +strengthens +strengths +strenuosity +strenuous +strenuously +strenuousness +strep +streps +streptobacilli +streptobacillus +streptocarpus +streptocarpuses +streptococcal +streptococci +streptococcic +streptococcus +streptodornase +streptodornases +streptokinase +streptokinases +streptolysin +streptolysins +streptomyces +streptomycete +streptomycetes +streptomycin +streptomycins +streptonigrin +streptonigrins +streptothricin +streptothricins +streptovaricin +streptovaricins +streptozotocin +streptozotocins +stresa +stress +stressed +stresses +stressful +stressfully +stressfulness +stressing +stressless +stresslessness +stressor +stressors +stretch +stretchability +stretchable +stretched +stretcher +stretchers +stretches +stretchier +stretchiest +stretchiness +stretching +stretchy +stretta +strettas +strette +stretti +stretto +strettos +streusel +streusels +strew +strewed +strewing +strewn +strews +stria +striae +striata +striate +striated +striates +striating +striation +striations +striatum +strick +stricken +strickle +strickled +strickles +strickling +stricks +strict +stricter +strictest +strictly +strictness +stricture +strictures +stridden +stride +stridence +stridency +strident +stridently +strider +striders +strides +striding +stridor +stridors +stridulate +stridulated +stridulates +stridulating +stridulation +stridulations +stridulatory +stridulous +stridulously +strife +strifeless +strigil +strigils +strigose +strike +strikebound +strikebreaker +strikebreakers +strikebreaking +strikeout +strikeouts +strikeover +strikeovers +striker +strikers +strikes +striking +strikingly +strikingness +strindberg +string +stringboard +stringboards +stringcourse +stringcourses +stringed +stringencies +stringency +stringendo +stringent +stringently +stringer +stringers +stringhalt +stringhalted +stringhalts +stringier +stringiest +stringily +stringiness +stringing +stringless +stringpiece +stringpieces +strings +stringy +stringybark +stringybarks +strip +stripe +striped +stripeless +striper +stripers +stripes +stripfilm +stripfilms +stripier +stripiest +striping +stripings +stripling +striplings +strippable +stripped +stripper +strippers +stripping +strips +stript +striptease +stripteaser +stripteasers +stripteases +stripy +strive +strived +striven +striver +strivers +strives +striving +strivingly +strivings +strobe +strobes +strobila +strobilaceous +strobilae +strobilar +strobilation +strobilations +strobile +strobiles +strobili +strobilus +stroboscope +stroboscopes +stroboscopic +stroboscopically +strobotron +strobotrons +strode +stroganoff +stroke +stroked +stroker +strokers +strokes +stroking +stroll +strolled +stroller +strollers +strolling +strolls +stroma +stromal +stromata +stromatic +stromatolite +stromatolites +stromatolitic +stromboli +strong +strongbox +strongboxes +stronger +strongest +stronghold +strongholds +strongish +strongly +strongman +strongmen +strongpoint +strongpoints +strongyl +strongyle +strongyles +strongyloidiasis +strongyloidosis +strongylosis +strongyls +strontianite +strontianites +strontium +strop +strophanthin +strophanthins +strophe +strophes +strophic +strophoid +strophoids +strophuli +strophulus +stropped +stroppier +stroppiest +stropping +stroppy +strops +stroud +strouding +strouds +strove +struck +structural +structuralism +structuralist +structuralists +structuralization +structuralizations +structuralize +structuralized +structuralizes +structuralizing +structurally +structurals +structuration +structure +structured +structureless +structurelessness +structures +structuring +strudel +strudels +struggle +struggled +struggler +strugglers +struggles +struggling +strugglingly +strum +struma +strumae +strumas +strumatic +strummed +strummer +strummers +strumming +strumose +strumous +strumpet +strumpets +strums +strung +strut +struthious +struts +strutted +strutter +strutters +strutting +struttingly +strychnine +strychninism +strychninisms +stuart +stuarts +stub +stubbed +stubbier +stubbiest +stubbily +stubbiness +stubbing +stubble +stubbled +stubbly +stubborn +stubborner +stubbornest +stubbornly +stubbornness +stubbs +stubby +stubs +stucco +stuccoed +stuccoes +stuccoing +stuccos +stuccowork +stuccoworker +stuccoworkers +stuck +stud +studbook +studbooks +studded +studding +studdingsail +studdingsails +student +students +studentship +studentships +studfish +studfishes +studhorse +studhorses +studied +studiedly +studiedness +studier +studiers +studies +studio +studios +studious +studiously +studiousness +studly +studs +studwork +study +studying +stuff +stuffed +stuffer +stuffers +stuffier +stuffiest +stuffily +stuffiness +stuffing +stuffless +stuffs +stuffy +stukeley +stull +stulls +stultification +stultifications +stultified +stultifier +stultifiers +stultifies +stultify +stultifying +stum +stumble +stumblebum +stumblebums +stumbled +stumbler +stumblers +stumbles +stumbling +stumblingly +stummed +stumming +stump +stumpage +stumped +stumper +stumpers +stumpiness +stumping +stumps +stumpy +stums +stun +stung +stunk +stunned +stunner +stunners +stunning +stunningly +stuns +stunt +stunted +stuntedness +stunting +stuntman +stuntmen +stunts +stuntwoman +stuntwomen +stupa +stupas +stupe +stupefacient +stupefacients +stupefaction +stupefactions +stupefactive +stupefactives +stupefied +stupefier +stupefiers +stupefies +stupefy +stupefying +stupefyingly +stupendous +stupendously +stupendousness +stupes +stupid +stupider +stupidest +stupidities +stupidity +stupidly +stupidness +stupids +stupor +stuporous +stupors +sturdier +sturdiest +sturdily +sturdiness +sturdy +sturgeon +sturgeons +sturm +stutter +stuttered +stutterer +stutterers +stuttering +stutteringly +stutters +stuttgart +sty +stye +styes +stygian +stying +stylar +stylate +style +stylebook +stylebooks +styled +styler +stylers +styles +stylet +stylets +styli +styliform +styling +stylings +stylish +stylishly +stylishness +stylist +stylistic +stylistically +stylistics +stylists +stylite +stylites +stylitic +stylitism +stylization +stylizations +stylize +stylized +stylizer +stylizers +stylizes +stylizing +stylobate +stylobates +stylography +styloid +stylolite +stylolites +stylopodia +stylopodium +stylus +styluses +stymie +stymied +stymieing +stymies +stymy +stymying +stypsis +styptic +stypticity +styptics +styrax +styraxes +styrene +styria +styrofoam +styx +suability +suable +suably +suasion +suasions +suasive +suasively +suasiveness +suave +suavely +suaveness +suaver +suavest +suavity +sub +subabdominal +subacid +subacidly +subacidness +subacute +subacutely +subadar +subadars +subaddress +subaddresses +subadolescent +subadult +subadults +subaerial +subaerially +subagencies +subagency +subagent +subagents +subahdar +subahdars +suballocation +suballocations +subalpine +subaltern +subalternate +subalternation +subalternations +subalterns +subantarctic +subapical +subapically +subaquatic +subaqueous +subarachnoid +subarachnoidal +subarctic +subarea +subareas +subarid +subassemblies +subassembly +subatmospheric +subatomic +subaudible +subaudition +subauditions +subaverage +subaxillary +subbase +subbasement +subbasements +subbases +subbasin +subbasins +subbass +subbasses +subbed +subbing +subbituminous +subblock +subblocks +subbranch +subbranches +subcabinet +subcaliber +subcapsular +subcarrier +subcarriers +subcartilaginous +subcaste +subcastes +subcategories +subcategorization +subcategorizations +subcategorize +subcategorized +subcategorizes +subcategorizing +subcategory +subceiling +subceilings +subcelestial +subcellar +subcellars +subcellular +subcenter +subcenters +subcentral +subcentrally +subchannel +subchannels +subchapter +subchapters +subchaser +subchasers +subchief +subchiefs +subclan +subclans +subclass +subclasses +subclassification +subclassifications +subclassified +subclassifies +subclassify +subclassifying +subclavian +subclavians +subclimactic +subclimax +subclimaxes +subclinical +subclinically +subcluster +subclusters +subcode +subcodes +subcollection +subcollections +subcollege +subcolleges +subcollegiate +subcolonies +subcolony +subcommand +subcommands +subcommission +subcommissions +subcommittee +subcommittees +subcommunities +subcommunity +subcompact +subcompacts +subcomponent +subcomponents +subconference +subconferences +subconscious +subconsciously +subconsciousness +subcontinent +subcontinental +subcontinents +subcontract +subcontracted +subcontracting +subcontractor +subcontractors +subcontracts +subcontraoctave +subcontraoctaves +subcontraries +subcontrary +subcool +subcooled +subcooling +subcools +subcordate +subcoriaceous +subcortex +subcortical +subcortically +subcortices +subcounties +subcounty +subcritical +subcrustal +subcult +subcults +subcultural +subculturally +subculture +subcultures +subcurative +subcutaneous +subcutaneously +subcutis +subcutises +subdeacon +subdeacons +subdean +subdeans +subdeb +subdebs +subdebutante +subdebutantes +subdecision +subdecisions +subdepartment +subdepartments +subdermal +subdermally +subdevelopment +subdevelopments +subdiaconal +subdiaconate +subdiaconates +subdialect +subdialects +subdirector +subdirectories +subdirectors +subdirectory +subdiscipline +subdisciplines +subdistrict +subdistricts +subdividable +subdivide +subdivided +subdivider +subdividers +subdivides +subdividing +subdivision +subdivisional +subdivisions +subdominant +subdominants +subduable +subduct +subducted +subducting +subduction +subductions +subducts +subdue +subdued +subduedly +subduer +subduers +subdues +subduing +subdural +subeconomies +subeconomy +subedit +subedited +subediting +subeditor +subeditorial +subeditors +subedits +subemployed +subemployment +subentries +subentry +subepidermal +subequatorial +suberect +suberin +suberins +suberization +suberizations +suberize +suberized +suberizes +suberizing +suberose +suberous +subexpression +subexpressions +subfamilies +subfamily +subfield +subfields +subfigure +subfigures +subfile +subfiles +subfloor +subflooring +subfloorings +subfloors +subfolder +subfolders +subfossil +subfossils +subframe +subframes +subfreezing +subfusc +subfuscs +subgenera +subgeneration +subgenerations +subgeneric +subgenre +subgenres +subgenus +subglacial +subglacially +subgoal +subgoals +subgovernment +subgovernments +subgrade +subgrades +subgraph +subgraphs +subgroup +subgroups +subgum +subgums +subharmonic +subhead +subheading +subheadings +subheads +subhuman +subhumans +subhumid +subindex +subindexes +subindices +subindustries +subindustry +subinfeud +subinfeudate +subinfeudated +subinfeudates +subinfeudating +subinfeudation +subinfeudations +subinfeudatory +subinfeuded +subinfeuding +subinfeuds +subinhibitory +subinterval +subintervals +subirrigate +subirrigated +subirrigates +subirrigating +subirrigation +subirrigations +subito +subjacency +subjacent +subjacently +subject +subjected +subjecting +subjection +subjections +subjective +subjectively +subjectiveness +subjectivism +subjectivist +subjectivistic +subjectivists +subjectivity +subjectivization +subjectivizations +subjectivize +subjectivized +subjectivizes +subjectivizing +subjectless +subjects +subjoin +subjoinder +subjoinders +subjoined +subjoining +subjoins +subjugate +subjugated +subjugates +subjugating +subjugation +subjugations +subjugator +subjugators +subjunction +subjunctions +subjunctive +subjunctives +subkingdom +subkingdoms +sublanguage +sublanguages +sublate +sublated +sublates +sublating +sublation +sublations +sublease +subleased +subleases +subleasing +sublet +sublethal +sublethally +sublets +subletting +sublevel +sublevels +sublibrarian +sublibrarians +sublicense +sublicensed +sublicensee +sublicensees +sublicenses +sublicensing +sublieutenant +sublieutenants +sublimable +sublimate +sublimated +sublimates +sublimating +sublimation +sublimations +sublime +sublimed +sublimely +sublimeness +sublimer +sublimers +sublimes +subliminal +subliminally +subliming +sublimit +sublimities +sublimits +sublimity +subline +sublines +sublingual +sublingually +sublinguals +subliteracy +subliterary +subliterate +subliterature +sublittoral +sublot +sublots +sublunar +sublunary +subluxation +subluxations +submachine +submanager +submanagers +submandibular +submarginal +submarine +submarined +submariner +submariners +submarines +submarining +submarket +submarkets +submaxilla +submaxillae +submaxillaries +submaxillary +submaximal +submediant +submediants +submenu +submenus +submerge +submerged +submergence +submerges +submergibility +submergible +submerging +submerse +submersed +submerses +submersible +submersibles +submersing +submersion +submersions +submetacentric +submetacentrics +submicrogram +submicron +submicroscopic +submicroscopically +submillimeter +subminiature +subminiaturization +subminiaturizations +subminiaturize +subminiaturized +subminiaturizes +subminiaturizing +subminimal +subminimum +subminister +subministered +subministering +subministers +submiss +submission +submissions +submissive +submissively +submissiveness +submit +submitochondrial +submits +submittal +submittals +submitted +submitter +submitters +submitting +submontane +submucosa +submucosal +submucosally +submucosas +submultiple +submultiples +submunition +submunitions +subnational +subnet +subnets +subnetwork +subnetworks +subniche +subniches +subnormal +subnormality +subnormally +subnormals +subnuclear +suboceanic +suboptimal +suboptimization +suboptimizations +suboptimize +suboptimized +suboptimizes +suboptimizing +suboptimum +suboptimums +suborbicular +suborbital +suborbitals +suborder +suborders +subordinate +subordinated +subordinately +subordinateness +subordinates +subordinating +subordination +subordinations +subordinative +subordinator +subordinators +suborganization +suborganizations +suborn +subornation +subornations +suborned +suborner +suborners +suborning +suborns +suboxide +suboxides +subpanel +subpanels +subpar +subparagraph +subparagraphs +subparallel +subpart +subparts +subperiod +subperiods +subperiosteal +subphase +subphases +subphyla +subphylum +subplot +subplots +subpoena +subpoenaed +subpoenaing +subpoenas +subpolar +subpopulation +subpopulations +subpotency +subpotent +subprimate +subprimates +subprincipal +subprincipals +subproblem +subproblems +subprocess +subprocesses +subproduct +subproducts +subprofessional +subprofessionals +subprogram +subprograms +subproject +subprojects +subproletariat +subproletariats +subrational +subregion +subregional +subregions +subreption +subreptions +subreptitious +subreptitiously +subring +subrings +subrogate +subrogated +subrogates +subrogating +subrogation +subrogations +subroutine +subroutines +subs +subsample +subsampled +subsamples +subsampling +subsatellite +subsatellites +subsaturated +subsaturation +subscale +subscales +subscapular +subscapulars +subscience +subsciences +subscribe +subscribed +subscriber +subscribers +subscribes +subscribing +subscript +subscripted +subscripting +subscription +subscriptions +subscriptive +subscriptively +subscripts +subsea +subsecretaries +subsecretary +subsection +subsections +subsector +subsectors +subsegment +subsegments +subseizure +subsense +subsenses +subsentence +subsentences +subsequence +subsequences +subsequent +subsequently +subsequentness +subsere +subseres +subseries +subserve +subserved +subserves +subservience +subserviency +subservient +subserviently +subserving +subset +subsets +subshell +subshells +subshrub +subshrubs +subside +subsided +subsidence +subsides +subsidiaries +subsidiarily +subsidiarity +subsidiary +subsidies +subsiding +subsidization +subsidizations +subsidize +subsidized +subsidizer +subsidizers +subsidizes +subsidizing +subsidy +subsist +subsisted +subsistence +subsistent +subsister +subsisters +subsisting +subsists +subsite +subsites +subskill +subskills +subsocial +subsocieties +subsociety +subsoil +subsoiled +subsoiler +subsoilers +subsoiling +subsoils +subsolar +subsonic +subsonically +subspace +subspaces +subspecialist +subspecialists +subspecialization +subspecializations +subspecialize +subspecialized +subspecializes +subspecializing +subspecialties +subspecialty +subspecies +subspecific +substage +substages +substance +substanceless +substances +substandard +substantia +substantiae +substantial +substantiality +substantially +substantialness +substantials +substantiate +substantiated +substantiates +substantiating +substantiation +substantiations +substantiative +substantival +substantivally +substantive +substantively +substantiveness +substantives +substantivize +substantivized +substantivizes +substantivizing +substate +substates +substation +substations +substituent +substituents +substitutability +substitutable +substitute +substituted +substitutes +substituting +substitution +substitutional +substitutionally +substitutionary +substitutions +substitutive +substitutively +substrata +substrate +substrates +substrative +substratosphere +substratospheres +substratospheric +substratum +substratums +substructural +substructure +substructures +subsumable +subsume +subsumed +subsumes +subsuming +subsumption +subsumptions +subsumptive +subsurface +subsystem +subsystems +subtask +subtasks +subtaxa +subtaxon +subtaxons +subteen +subteens +subtemperate +subtenancy +subtenant +subtenants +subtend +subtended +subtending +subtends +subterfuge +subterfuges +subterminal +subterranean +subterraneanly +subterraneous +subterraneously +subterrestrial +subtest +subtests +subtext +subtexts +subtextual +subtheme +subthemes +subtherapeutic +subtherapeutically +subthreshold +subtile +subtilely +subtileness +subtiler +subtilest +subtilin +subtilins +subtilisin +subtilisins +subtility +subtilization +subtilizations +subtilize +subtilized +subtilizes +subtilizing +subtilty +subtitle +subtitled +subtitles +subtitling +subtle +subtleness +subtler +subtlest +subtleties +subtlety +subtly +subtonic +subtonics +subtopic +subtopics +subtorrid +subtotal +subtotaled +subtotaling +subtotalled +subtotalling +subtotally +subtotals +subtract +subtracted +subtracter +subtracters +subtracting +subtraction +subtractions +subtractive +subtracts +subtrahend +subtrahends +subtreasuries +subtreasury +subtrend +subtrends +subtribe +subtribes +subtropic +subtropical +subtropics +subtype +subtypes +subulate +subumbrella +subumbrellas +subunit +subunits +suburb +suburban +suburbanite +suburbanites +suburbanization +suburbanizations +suburbanize +suburbanized +suburbanizes +suburbanizing +suburbans +suburbia +suburbs +subvarieties +subvariety +subvassal +subvassals +subvention +subventionary +subventions +subversion +subversionary +subversions +subversive +subversively +subversiveness +subversives +subvert +subverted +subverter +subverters +subverting +subverts +subviral +subvirus +subviruses +subvisible +subvisual +subvocal +subvocalization +subvocalizations +subvocalize +subvocalized +subvocalizer +subvocalizers +subvocalizes +subvocalizing +subvocally +subway +subways +subworld +subworlds +subwriter +subwriters +subzero +subzone +subzones +succedanea +succedaneous +succedaneum +succedaneums +succedent +succeed +succeeded +succeeder +succeeders +succeeding +succeeds +success +successes +successful +successfully +successfulness +succession +successional +successionally +successions +successive +successively +successiveness +successor +successors +succi +succinate +succinates +succinct +succincter +succinctest +succinctly +succinctness +succinic +succinyl +succinylcholine +succinylcholines +succinyls +succinylsulfathiazole +succinylsulfathiazoles +succor +succorable +succored +succorer +succorers +succories +succoring +succors +succory +succotash +succoth +succuba +succubae +succubi +succubus +succubuses +succulence +succulency +succulent +succulently +succulents +succumb +succumbed +succumbing +succumbs +succus +succussatory +succussion +succussions +succès +such +suchlike +suck +sucked +sucker +suckered +suckerfish +suckerfishes +suckering +suckers +suckfish +suckfishes +sucking +suckle +suckled +suckler +sucklers +suckles +suckling +sucklings +sucks +sucrase +sucrases +sucre +sucres +sucrose +suction +suctional +suctioned +suctioning +suctions +suctorial +suctorian +suctorians +sudan +sudanese +sudanic +sudatoria +sudatories +sudatorium +sudatory +sudd +sudden +suddenly +suddenness +sudds +sudeten +sudetenland +sudetes +sudoriferous +sudorific +sudorifics +sudra +sudras +suds +sudser +sudsers +sudsier +sudsiest +sudsless +sudsy +sue +sued +suede +sueded +suedes +sueding +suer +suers +sues +suet +suety +suey +sueys +suez +suffer +sufferable +sufferableness +sufferably +sufferance +suffered +sufferer +sufferers +suffering +sufferingly +sufferings +suffers +suffice +sufficed +sufficer +sufficers +suffices +sufficiencies +sufficiency +sufficient +sufficiently +sufficing +sufficingly +sufficingness +suffix +suffixal +suffixation +suffixations +suffixed +suffixes +suffixing +suffixion +suffixions +suffocate +suffocated +suffocates +suffocating +suffocatingly +suffocation +suffocations +suffocative +suffolk +suffragan +suffragans +suffraganship +suffraganships +suffrage +suffrages +suffragette +suffragettes +suffragettism +suffragism +suffragist +suffragists +suffrutescent +suffruticose +suffuse +suffused +suffuses +suffusing +suffusion +suffusions +suffusive +sufi +sufic +sufis +sufism +sufistic +sugar +sugarberries +sugarberry +sugarbird +sugarbirds +sugarcane +sugarcanes +sugarcoat +sugarcoated +sugarcoating +sugarcoats +sugared +sugarer +sugarers +sugarhouse +sugarhouses +sugarier +sugariest +sugariness +sugaring +sugarless +sugarloaf +sugarloaves +sugarplum +sugarplums +sugars +sugary +suggest +suggested +suggester +suggesters +suggestibility +suggestible +suggesting +suggestion +suggestions +suggestive +suggestively +suggestiveness +suggests +sui +suicidal +suicidally +suicide +suicided +suicides +suiciding +suicidologist +suicidologists +suicidology +suing +suint +suints +suit +suitability +suitable +suitableness +suitably +suitcase +suitcases +suite +suited +suiter +suiters +suites +suiting +suitings +suitor +suitors +suits +sukiyaki +sukiyakis +sukkah +sukkot +sukkoth +sulawesi +sulcal +sulcate +sulci +sulcus +suleiman +sulfa +sulfadiazine +sulfadiazines +sulfanilamide +sulfanilamides +sulfanilic +sulfatase +sulfatases +sulfate +sulfated +sulfates +sulfathiazole +sulfathiazoles +sulfating +sulfhydryl +sulfhydryls +sulfide +sulfides +sulfinpyrazone +sulfinpyrazones +sulfinyl +sulfinyls +sulfite +sulfites +sulfitic +sulfonamide +sulfonamides +sulfonate +sulfonated +sulfonates +sulfonating +sulfonation +sulfonations +sulfone +sulfones +sulfonic +sulfonium +sulfoniums +sulfonmethane +sulfonmethanes +sulfonyl +sulfonyls +sulfonylurea +sulfonylureas +sulfoxide +sulfoxides +sulfur +sulfurate +sulfurated +sulfurates +sulfurating +sulfuration +sulfurations +sulfured +sulfureous +sulfuret +sulfureted +sulfureting +sulfurets +sulfuretted +sulfuretting +sulfuric +sulfuring +sulfurization +sulfurizations +sulfurize +sulfurized +sulfurizes +sulfurizing +sulfurous +sulfurously +sulfurousness +sulfurs +sulfury +sulfuryl +sulfuryls +sulk +sulked +sulkers +sulkier +sulkies +sulkiest +sulkily +sulkiness +sulking +sulks +sulky +sulla +sullage +sullen +sullener +sullenest +sullenly +sullenness +sullied +sullies +sullivan +sully +sullying +sulphur +sulphured +sulphureous +sulphuric +sulphuring +sulphurous +sulphurs +sulphury +sulpician +sulpicians +sultan +sultana +sultanas +sultanate +sultanates +sultaness +sultanesses +sultanic +sultans +sultrier +sultriest +sultrily +sultriness +sultry +sulu +sulus +sum +sumac +sumach +sumacs +sumatra +sumatran +sumatrans +sumba +sumbawa +sumer +sumerian +sumerians +sumerologist +sumerologists +sumerology +summa +summability +summable +summae +summand +summands +summaries +summarily +summariness +summarizable +summarization +summarizations +summarize +summarized +summarizer +summarizers +summarizes +summarizing +summary +summate +summated +summates +summating +summation +summational +summations +summative +summed +summer +summercater +summercaters +summered +summerhouse +summerhouses +summering +summerlike +summerlong +summerly +summers +summersault +summersaulted +summersaulting +summersaults +summerset +summersets +summersetted +summersetting +summertime +summerwood +summery +summing +summings +summit +summiteer +summiteers +summitries +summitry +summits +summon +summonable +summoned +summoner +summoners +summoning +summons +summonsed +summonses +summonsing +summum +sumo +sump +sumps +sumpter +sumpters +sumptuary +sumptuous +sumptuously +sumptuousness +sums +sun +sunbaked +sunbath +sunbathe +sunbathed +sunbather +sunbathers +sunbathes +sunbathing +sunbaths +sunbeam +sunbeams +sunbelt +sunbelts +sunbird +sunbirds +sunblind +sunblock +sunbonnet +sunbonnets +sunbow +sunbows +sunburn +sunburned +sunburning +sunburns +sunburnt +sunburst +sunbursts +sunchoke +sunchokes +sundae +sundaes +sunday +sundays +sundeck +sundecks +sunder +sunderance +sundered +sundering +sunders +sundew +sundews +sundial +sundials +sundog +sundogs +sundown +sundowner +sundowners +sundress +sundresses +sundries +sundrops +sundry +sunfish +sunfishes +sunflower +sunflowers +sung +sunglass +sunglasses +sunglow +sunglows +sunk +sunken +sunlamp +sunlamps +sunless +sunlessness +sunlight +sunlike +sunlit +sunn +sunna +sunnah +sunned +sunni +sunnier +sunniest +sunnily +sunniness +sunning +sunnis +sunnism +sunnite +sunnites +sunns +sunny +sunporch +sunporches +sunray +sunrays +sunrise +sunrises +sunroof +sunroofs +sunroom +sunrooms +suns +sunscald +sunscalds +sunscreen +sunscreening +sunscreens +sunseeker +sunseekers +sunset +sunsets +sunshade +sunshades +sunshine +sunshiny +sunspace +sunspaces +sunspot +sunspots +sunstone +sunstones +sunstroke +sunstrokes +sunstruck +sunsuit +sunsuits +suntan +suntanned +suntans +sunup +sunward +sunwards +sunwise +sup +super +superable +superableness +superably +superabound +superabounded +superabounding +superabounds +superabsorbent +superabsorbents +superabundance +superabundant +superabundantly +superachiever +superachievers +superactivities +superactivity +superadd +superadded +superadding +superaddition +superadditions +superadds +superadministrator +superadministrators +superagencies +superagency +superagent +superagents +superalloy +superalloys +superaltern +superalterns +superambitious +superannuate +superannuated +superannuates +superannuating +superannuation +superannuations +superathlete +superb +superbad +superball +superbank +superbillionaire +superbitch +superblock +superblocks +superbly +superbness +superboard +superbomb +superbomber +superbright +superbureaucrat +supercabinet +supercalender +supercalendered +supercalendering +supercalenders +supercar +supercargo +supercargoes +supercargos +supercarrier +supercautious +supercenter +supercharge +supercharged +supercharger +superchargers +supercharges +supercharging +superchic +superchurch +superciliary +supercilious +superciliously +superciliousness +supercities +supercity +supercivilization +supercivilized +superclass +superclasses +superclean +superclub +supercluster +superclusters +supercoil +supercoiled +supercoiling +supercoils +supercollider +supercolliders +supercolossal +supercolumnar +supercomfortable +supercompetitive +supercomputer +supercomputers +supercomputing +superconduct +superconducted +superconducting +superconductive +superconductivity +superconductor +superconductors +superconducts +superconfident +superconglomerate +superconservative +supercontinent +supercontinents +superconvenient +supercool +supercooled +supercooling +supercools +supercop +supercorporation +supercriminal +supercritical +supercurrent +supercurrents +supercute +superdelegate +superdelegates +superdeluxe +superdiplomat +superdominant +superdominants +superduper +supered +supereffective +superefficiency +superefficient +superego +superegoist +superegoists +superegos +superelevate +superelevated +superelevates +superelevating +superelevation +superelevations +superelite +supereminence +supereminent +supereminently +supererogate +supererogated +supererogates +supererogating +supererogation +supererogations +supererogative +supererogatory +superexcellent +superexpensive +superexpress +superfamilies +superfamily +superfan +superfarm +superfast +superfatted +superfecta +superfectas +superfecundation +superfecundations +superfetate +superfetated +superfetates +superfetating +superfetation +superfetations +superficial +superficialities +superficiality +superficially +superficialness +superficies +superfine +superfineness +superfirm +superfix +superfixes +superflack +superfluid +superfluidity +superfluids +superfluities +superfluity +superfluous +superfluously +superfluousness +superfund +supergalactic +supergalaxies +supergalaxy +supergene +supergenes +supergiant +supergiants +superglue +superglues +supergood +supergovernment +supergraphics +supergravity +supergroup +supergroups +supergrowth +superharden +superheat +superheated +superheater +superheaters +superheating +superheats +superheavy +superheavyweight +superheavyweights +superhelical +superhelically +superhelices +superhelix +superhelixes +superhero +superheroes +superheroine +superheterodyne +superheterodynes +superhigh +superhighway +superhighways +superhit +superhot +superhuman +superhumanity +superhumanly +superhumanness +superhype +superimposable +superimpose +superimposed +superimposes +superimposing +superimposition +superimpositions +superincumbence +superincumbency +superincumbent +superincumbently +superindividual +superinduce +superinduced +superinduces +superinducing +superinduction +superinductions +superinfect +superinfected +superinfecting +superinfection +superinfections +superinfects +supering +superinsulated +superintellectual +superintelligence +superintelligent +superintend +superintended +superintendence +superintendences +superintendencies +superintendency +superintendent +superintendents +superintending +superintends +superintensity +superior +superiority +superiorly +superiors +superjacent +superjet +superjets +superjock +superjumbo +superlarge +superlative +superlatively +superlativeness +superlatives +superlawyer +superlight +superlinear +superliner +superliners +superlobbyist +superlobbyists +superloyalist +superloyalists +superlunar +superlunary +superluxurious +superluxury +supermacho +supermagnetic +supermajorities +supermajority +supermale +superman +supermarket +supermarketer +supermarketers +supermarkets +supermasculine +supermassive +supermen +supermicro +supermicros +supermilitant +supermillionaire +supermind +superminicomputer +superminicomputers +superminister +supermodel +supermodels +supermodern +supermolecule +supermolecules +supermom +supermoms +supernal +supernally +supernatant +supernatants +supernation +supernational +supernatural +supernaturalism +supernaturalist +supernaturalistic +supernaturalists +supernaturally +supernaturalness +supernaturals +supernature +supernormal +supernormality +supernormally +supernova +supernovae +supernovas +supernumeraries +supernumerary +supernutrition +superorder +superorders +superordinate +superordinated +superordinates +superordinating +superordination +superordinations +superorganic +superorganism +superorganisms +superorgasm +superovulate +superovulated +superovulates +superovulating +superovulation +superovulations +superoxide +superoxides +superparasitic +superparasitism +superparasitisms +superpatriot +superpatriotic +superpatriotism +superperson +superpersonal +superphenomenon +superphosphate +superphosphates +superphysical +superpimp +superplane +superplastic +superplasticity +superplayer +superpolite +superport +superposable +superpose +superposed +superposes +superposing +superposition +superpower +superpowered +superpowerful +superpowers +superpremium +superpro +superprofit +superquality +superrace +superreal +superrealism +superrealist +superrealistic +superrealists +superregional +superrich +superroad +superromantic +superromanticism +supers +supersafe +supersale +supersalesman +supersaturate +supersaturated +supersaturates +supersaturating +supersaturation +supersaturations +supersaver +supersavers +superscale +superschool +superscout +superscribe +superscribed +superscribes +superscribing +superscript +superscripted +superscripting +superscription +superscripts +supersecrecy +supersecret +supersede +supersedeas +supersedeases +superseded +superseder +superseders +supersedes +superseding +supersedure +supersedures +supersell +superseller +supersensible +supersensibly +supersensitive +supersensitively +supersensitivity +supersensory +superserviceable +supersession +supersessions +superset +supersets +supersexuality +supersharp +supershow +supersinger +supersize +supersized +supersleuth +superslick +supersmart +supersmooth +supersoft +supersonic +supersonically +supersonics +supersophisticated +superspecial +superspecialist +superspecialists +superspecialization +superspecialized +superspectacle +superspectacular +superspeculation +superspy +superstar +superstardom +superstars +superstate +superstates +superstation +superstations +superstimulate +superstition +superstitions +superstitious +superstitiously +superstitiousness +superstock +superstore +superstores +superstrata +superstratum +superstrength +superstrike +superstring +superstrings +superstrong +superstructural +superstructure +superstructures +superstud +supersubstantial +supersubtle +supersubtlety +supersurgeon +supersweet +supersymmetric +supersymmetry +supersystem +supersystems +supertanker +supertankers +supertax +supertaxes +superterrific +superthick +superthin +superthriller +supertight +supertitle +supertitled +supertitles +supertonic +supertonics +supervene +supervened +supervenes +supervenient +supervening +supervention +superventions +supervirile +supervirtuoso +supervise +supervised +supervises +supervising +supervision +supervisions +supervisor +supervisors +supervisory +superwave +superweapon +superwide +superwife +superwoman +superwomen +supinate +supinated +supinates +supinating +supination +supinations +supinator +supinators +supine +supinely +supineness +supped +supper +suppers +suppertime +suppertimes +supping +supplant +supplantation +supplantations +supplanted +supplanter +supplanters +supplanting +supplants +supple +suppled +supplejack +supplejacks +supplely +supplement +supplemental +supplementarity +supplementary +supplementation +supplementations +supplemented +supplementer +supplementers +supplementing +supplements +suppleness +suppler +supples +supplest +suppletion +suppletions +suppletive +suppletory +suppliance +suppliant +suppliantly +suppliants +supplicant +supplicants +supplicate +supplicated +supplicates +supplicating +supplication +supplications +supplicatory +supplied +supplier +suppliers +supplies +suppling +supply +supplying +support +supportability +supportable +supportably +supported +supporter +supporters +supporting +supportive +supportively +supportiveness +supports +supposable +supposably +supposal +supposals +suppose +supposed +supposedly +supposes +supposing +supposition +suppositional +suppositionally +suppositions +suppositious +supposititious +supposititiously +supposititiousness +suppositive +suppositively +suppositives +suppositories +suppository +suppress +suppressant +suppressants +suppressed +suppresser +suppressers +suppresses +suppressibility +suppressible +suppressing +suppression +suppressions +suppressive +suppressiveness +suppressor +suppressors +suppurate +suppurated +suppurates +suppurating +suppuration +suppurations +suppurative +supra +supracellular +supragenic +supraglottal +supraliminal +supramaxilla +supramaxillae +supramaxillary +supramolecular +supranational +supranationalism +supranationalist +supranationalists +supranationality +supraoptic +supraorbital +suprarational +suprarenal +suprarenals +suprascapular +suprasegmental +supraventricular +supravital +supravitally +supremacies +supremacist +supremacists +supremacy +suprematism +suprematist +suprematists +supreme +supremely +supremeness +supremer +supremest +supremo +supremos +suprême +sups +suquamish +suquamishes +sura +surah +surahs +sural +suras +surat +surbase +surbased +surbases +surcease +surceased +surceases +surceasing +surcharge +surcharged +surcharges +surcharging +surcingle +surcingled +surcingles +surcingling +surcoat +surcoats +surculose +surd +surds +sure +surefire +surefooted +surefootedly +surefootedness +surely +sureness +surer +surest +sureties +surety +suretyship +surf +surface +surfaced +surfacer +surfacers +surfaces +surfacing +surfactant +surfactants +surfbird +surfbirds +surfboard +surfboarder +surfboarders +surfboarding +surfboardings +surfboards +surfboat +surfboats +surfcaster +surfcasters +surfcasting +surfcastings +surfed +surfeit +surfeited +surfeiter +surfeiters +surfeiting +surfeits +surfer +surfers +surficial +surfing +surfperch +surfperches +surfs +surfside +surfy +surge +surged +surgeon +surgeonfish +surgeonfishes +surgeons +surgeries +surgery +surges +surgical +surgically +surgicenter +surgicenters +surging +suribachi +suricate +suricates +surimi +surimis +surinam +suriname +surinamer +surinamers +surinamese +surjection +surjections +surjective +surlier +surliest +surlily +surliness +surly +surmise +surmised +surmises +surmising +surmount +surmountable +surmounted +surmounter +surmounters +surmounting +surmounts +surmullet +surmullets +surname +surnamed +surnames +surnaming +surpass +surpassable +surpassed +surpasses +surpassing +surpassingly +surplice +surplices +surplus +surplusage +surplusages +surpluses +surprint +surprinted +surprinting +surprints +surprisal +surprisals +surprise +surprised +surpriser +surprisers +surprises +surprising +surprisingly +surprize +surprized +surprizes +surprizing +surra +surreal +surrealism +surrealist +surrealistic +surrealistically +surrealists +surreally +surrebuttal +surrebuttals +surrebutter +surrebutters +surrejoinder +surrejoinders +surrender +surrendered +surrendering +surrenders +surreptitious +surreptitiously +surreptitiousness +surrey +surreys +surrogacies +surrogacy +surrogate +surrogated +surrogates +surrogating +surround +surrounded +surrounding +surroundings +surrounds +surroyal +surroyals +surtax +surtaxed +surtaxes +surtaxing +surtitle +surtitles +surtout +surtouts +surveil +surveillance +surveillant +surveillants +surveilled +surveilling +surveils +survey +surveyed +surveying +surveyor +surveyors +surveys +survivability +survivable +survival +survivalist +survivalists +survivals +survivance +survive +survived +survives +surviving +survivor +survivors +survivorship +susan +susanna +susceptance +susceptances +susceptibilities +susceptibility +susceptible +susceptibleness +susceptibly +susceptive +susceptiveness +susceptivity +sushi +susiana +suslik +susliks +suspect +suspected +suspecting +suspects +suspend +suspended +suspender +suspendered +suspenders +suspending +suspends +suspense +suspenseful +suspensefully +suspensefulness +suspenseless +suspenser +suspensers +suspension +suspensions +suspensive +suspensively +suspensiveness +suspensor +suspensories +suspensors +suspensory +suspicion +suspicional +suspicioned +suspicioning +suspicions +suspicious +suspiciously +suspiciousness +suspiration +suspirations +suspire +suspired +suspires +suspiring +susquehanna +susquehannas +susquehannock +susquehannocks +suss +sussed +susses +sussex +sussing +sustain +sustainability +sustainable +sustainably +sustained +sustainedly +sustainer +sustainers +sustaining +sustainment +sustainments +sustains +sustenance +sustentacular +sustentation +sustentations +sustentative +susu +susurrant +susurration +susurrations +susurrous +susurrus +susurruses +susus +sutler +sutlers +sutra +sutras +suttee +suttees +sutural +suturally +suture +sutured +sutures +suturing +suzerain +suzerains +suzerainties +suzerainty +suzette +suzettes +suède +svalbard +svedberg +svedbergs +svelte +sveltely +svelteness +svelter +sveltest +svengali +svengalis +sverdlovsk +sverdrup +sw +swab +swabbed +swabber +swabbers +swabbie +swabbies +swabbing +swabby +swabia +swabian +swabians +swabs +swaddle +swaddled +swaddles +swaddling +swag +swage +swaged +swages +swagged +swagger +swaggered +swaggerer +swaggerers +swaggering +swaggeringly +swaggers +swagging +swaging +swagman +swagmen +swags +swahili +swahilian +swahilis +swain +swainish +swainishness +swains +swainson +swale +swales +swallow +swallowable +swallowed +swallower +swallowers +swallowing +swallows +swallowtail +swallowtails +swallowwort +swallowworts +swam +swami +swamis +swamp +swamped +swamper +swampers +swampier +swampiest +swampiness +swamping +swampland +swamplands +swamps +swampy +swan +swank +swanked +swanker +swankest +swankier +swankiest +swankily +swankiness +swanking +swanks +swanky +swanlike +swanned +swanneries +swannery +swanning +swans +swansdown +swanskin +swanskins +swap +swappable +swapped +swapper +swappers +swapping +swaps +swaraj +swarajist +swarajists +sward +swarded +swards +swarf +swarfs +swarm +swarmed +swarmer +swarmers +swarming +swarms +swart +swarth +swarthier +swarthiest +swarthily +swarthiness +swarths +swarthy +swartness +swash +swashbuckle +swashbuckled +swashbuckler +swashbucklers +swashbuckles +swashbuckling +swashed +swasher +swashers +swashes +swashing +swastika +swastikas +swat +swatch +swatches +swath +swathe +swathed +swather +swathers +swathes +swathing +swaths +swats +swatted +swatter +swatters +swatting +sway +swayback +swaybacked +swaybacks +swayed +swayer +swayers +swaying +swayingly +sways +swazi +swaziland +swazis +swear +swearer +swearers +swearing +swears +swearword +swearwords +sweat +sweatband +sweatbands +sweatbox +sweatboxes +sweated +sweater +sweaterdress +sweaterdresses +sweaters +sweathouse +sweathouses +sweatier +sweatiest +sweatily +sweatiness +sweating +sweatpants +sweats +sweatshirt +sweatshirts +sweatshop +sweatshops +sweaty +swede +sweden +swedenborg +swedenborgian +swedenborgianism +swedenborgians +swedes +swedish +sweep +sweepback +sweepbacks +sweeper +sweepers +sweepier +sweepiest +sweeping +sweepingly +sweepingness +sweepings +sweeps +sweepstake +sweepstakes +sweepy +sweet +sweetbread +sweetbreads +sweetbriar +sweetbriars +sweetbrier +sweetbriers +sweeten +sweetened +sweetener +sweeteners +sweetening +sweetenings +sweetens +sweeter +sweetest +sweetheart +sweethearts +sweetie +sweeties +sweeting +sweetings +sweetish +sweetishly +sweetly +sweetmeat +sweetmeats +sweetness +sweets +sweetshop +sweetshops +sweetsop +sweetsops +swell +swelled +sweller +swellest +swellfish +swellfishes +swellhead +swellheaded +swellheadedness +swellheads +swelling +swellings +swells +swelter +sweltered +sweltering +swelteringly +swelters +sweltrier +sweltriest +sweltry +swept +sweptback +sweptwing +sweptwings +swerve +swerved +swerves +swerving +swidden +swiddens +swift +swifter +swiftest +swiftlet +swiftlets +swiftly +swiftness +swifts +swig +swigged +swigger +swiggers +swigging +swigs +swill +swilled +swiller +swillers +swilling +swills +swim +swimmable +swimmer +swimmeret +swimmerets +swimmers +swimmier +swimmiest +swimmily +swimming +swimmingly +swimmy +swims +swimsuit +swimsuits +swimwear +swindle +swindled +swindler +swindlers +swindles +swindling +swine +swineherd +swineherds +swinepox +swinepoxes +swing +swinge +swinged +swingeing +swinger +swingers +swinges +swingier +swingiest +swinging +swingingly +swingletree +swingletrees +swingman +swingmen +swings +swingy +swinish +swinishly +swinishness +swipe +swiped +swipes +swiping +swirl +swirled +swirlier +swirliest +swirling +swirlingly +swirls +swirly +swish +swished +swisher +swishers +swishes +swishier +swishiest +swishing +swishingly +swishy +swiss +swissair +switch +switchable +switchback +switchbacks +switchblade +switchblades +switchboard +switchboards +switched +switcher +switcheroo +switcheroos +switchers +switches +switchgrass +switching +switchman +switchmen +switchover +switchovers +switchyard +switchyards +switzer +switzerland +switzers +swivel +swiveled +swiveling +swivelled +swivelling +swivels +swivet +swivets +swizzle +swizzled +swizzler +swizzlers +swizzles +swizzling +swob +swobbed +swobbing +swobs +swollen +swoon +swooned +swooner +swooners +swooning +swooningly +swoons +swoop +swooped +swooper +swoopers +swooping +swoops +swoosh +swooshed +swooshes +swooshing +swop +swopped +swopping +swops +sword +swordbill +swordbills +swordfish +swordfishes +swordlike +swordplay +swordplayer +swordplayers +swords +swordsman +swordsmanship +swordsmen +swordtail +swordtails +swore +sworn +swum +swung +sybarite +sybarites +sybaritic +sybaritically +sybaritism +sycamine +sycamines +sycamore +sycamores +syce +sycee +sycees +syces +sycomore +sycomores +syconia +syconium +sycophancies +sycophancy +sycophant +sycophantic +sycophantical +sycophantically +sycophantish +sycophantishly +sycophantism +sycophantly +sycophants +sycosis +sydenham +sydney +syenite +syenites +syenitic +syli +sylis +syllabaries +syllabary +syllabi +syllabic +syllabically +syllabicate +syllabicated +syllabicates +syllabicating +syllabication +syllabications +syllabicity +syllabics +syllabification +syllabifications +syllabified +syllabifies +syllabify +syllabifying +syllabism +syllabisms +syllabize +syllabized +syllabizes +syllabizing +syllable +syllabled +syllables +syllabling +syllabub +syllabubs +syllabus +syllabuses +syllepses +syllepsis +sylleptic +syllogism +syllogisms +syllogist +syllogistic +syllogistical +syllogistically +syllogistics +syllogists +syllogization +syllogizations +syllogize +syllogized +syllogizer +syllogizers +syllogizes +syllogizing +sylph +sylphid +sylphids +sylphlike +sylphs +sylva +sylvan +sylvanite +sylvanites +sylvanus +sylvatic +sylviculture +sylvine +sylvines +sylvinite +sylvinites +sylvite +sylvites +symbiont +symbiontic +symbionts +symbioses +symbiosis +symbiote +symbiotes +symbiotic +symbiotical +symbiotically +symbol +symboled +symbolic +symbolical +symbolically +symbolicalness +symboling +symbolism +symbolist +symbolistic +symbolistically +symbolists +symbolization +symbolizations +symbolize +symbolized +symbolizer +symbolizers +symbolizes +symbolizing +symbology +symbols +symmetallism +symmetric +symmetrical +symmetrically +symmetricalness +symmetries +symmetrization +symmetrizations +symmetrize +symmetrized +symmetrizes +symmetrizing +symmetry +sympathectomies +sympathectomized +sympathectomy +sympathetic +sympathetically +sympathies +sympathin +sympathins +sympathize +sympathized +sympathizer +sympathizers +sympathizes +sympathizing +sympathizingly +sympatholytic +sympathomimetic +sympathomimetics +sympathy +sympatric +sympatrically +sympatries +sympatry +sympetalous +sympetaly +symphonic +symphonically +symphonies +symphonious +symphoniously +symphonist +symphonists +symphony +symphyseal +symphyses +symphysial +symphysis +sympodia +sympodial +sympodially +sympodium +symposia +symposiac +symposiacs +symposiarch +symposiarchs +symposiast +symposiasts +symposium +symposiums +symptom +symptomatic +symptomatically +symptomatize +symptomatized +symptomatizes +symptomatizing +symptomatologic +symptomatological +symptomatologically +symptomatology +symptomize +symptomized +symptomizes +symptomizing +symptomless +symptoms +synaeresis +synaesthesia +synaesthesias +synaesthesis +synagog +synagogal +synagogical +synagogs +synagogue +synagogues +synalepha +synalephas +synaloepha +synaloephas +synapse +synapsed +synapses +synapsid +synapsing +synapsis +synaptic +synaptically +synaptinemal +synaptonemal +synaptosomal +synaptosome +synaptosomes +synarthrodia +synarthrodiae +synarthrodial +synarthrodially +synarthroses +synarthrosis +sync +syncarp +syncarpous +syncarps +syncarpy +syncategorematic +syncategorematically +synced +synch +synched +synching +synchondroses +synchondrosis +synchro +synchrocyclotron +synchrocyclotrons +synchroflash +synchroflashes +synchromesh +synchromeshes +synchronal +synchroneity +synchronic +synchronical +synchronically +synchronicities +synchronicity +synchronies +synchronism +synchronistic +synchronistical +synchronistically +synchronization +synchronizations +synchronize +synchronized +synchronizer +synchronizers +synchronizes +synchronizing +synchronous +synchronously +synchronousness +synchrony +synchros +synchroscope +synchroscopes +synchrotron +synchrotrons +synchs +syncing +synclinal +syncline +synclines +syncopal +syncopate +syncopated +syncopates +syncopating +syncopation +syncopations +syncopative +syncopator +syncopators +syncope +syncopes +syncopic +syncretic +syncretism +syncretist +syncretistic +syncretists +syncretize +syncretized +syncretizes +syncretizing +syncs +syncytia +syncytial +syncytium +syndactyl +syndactylism +syndactylous +syndactyls +syndactyly +syndesmoses +syndesmosis +syndesmotic +syndetic +syndetically +syndic +syndical +syndicalism +syndicalist +syndicalistic +syndicalists +syndicate +syndicated +syndicates +syndicating +syndication +syndications +syndicator +syndicators +syndics +syndrome +syndromes +syndromic +syne +synecdoche +synecdoches +synecdochic +synecdochical +synecdochically +synecologic +synecological +synecology +synereses +syneresis +synergetic +synergic +synergically +synergid +synergids +synergies +synergism +synergist +synergistic +synergistically +synergists +synergy +synesis +synesthesia +synesthesias +synesthete +synesthetes +synesthetic +synfuel +synfuels +syngamic +syngamies +syngamous +syngamy +syngas +syngases +syngeneic +syngeneically +syngenesis +syngenetic +synizeses +synizesis +synkaryon +synkaryonic +synkaryons +synkineses +synkinesis +synkinetic +synod +synodal +synodic +synodical +synodically +synods +synonym +synonymic +synonymical +synonymies +synonymist +synonymists +synonymity +synonymize +synonymized +synonymizes +synonymizing +synonymous +synonymously +synonyms +synonymy +synopses +synopsis +synopsize +synopsized +synopsizes +synopsizing +synoptic +synoptical +synoptically +synostoses +synostosis +synostotic +synovia +synovial +synovias +synovitis +synovitises +synsepalous +syntactic +syntactical +syntactically +syntactics +syntagma +syntagmas +syntagmata +syntagmatic +syntax +syntaxes +syntenic +syntenies +synteny +synth +syntheses +synthesis +synthesist +synthesists +synthesize +synthesized +synthesizer +synthesizers +synthesizes +synthesizing +synthetase +synthetases +synthetic +synthetically +synthetics +synths +syntonic +syntrophies +syntrophism +syntrophisms +syntrophy +sypher +syphered +syphering +syphers +syphilis +syphilitic +syphilitics +syphiloid +syphon +syphoned +syphoning +syphons +syracusan +syracuse +syrette +syria +syriac +syrian +syrians +syringa +syringas +syringe +syringeal +syringed +syringes +syringing +syringomyelia +syringomyelias +syringomyelic +syrinx +syrinxes +syros +syrphid +syrphids +syrphus +syrup +syrups +syrupy +sysop +sysops +syssarcoses +syssarcosis +systaltic +system +systematic +systematical +systematically +systematicness +systematics +systematism +systematist +systematists +systematization +systematizations +systematize +systematized +systematizer +systematizers +systematizes +systematizing +systemic +systemically +systemization +systemizations +systemize +systemized +systemizer +systemizers +systemizes +systemizing +systemless +systems +systole +systoles +systolic +syzygial +syzygies +syzygy +szechuan +szechwan +sào +são +séance +séances +sémillon +sémillons +sérac +sèvres +síros +sûreté +süleyman +t +t'other +taal +tab +tabanid +tabanids +tabard +tabards +tabaret +tabarets +tabasco +tabbed +tabbies +tabbing +tabbouleh +tabby +tabernacle +tabernacled +tabernacles +tabernacling +tabernacular +tabes +tabescence +tabescent +tabetic +tabi +tabis +tabla +tablas +tablature +tablatures +table +tableau +tableaus +tableaux +tablecloth +tablecloths +tabled +tableful +tablefuls +tableland +tablelands +tablemat +tablemate +tablemates +tablemats +tables +tableside +tablesides +tablespoon +tablespoonful +tablespoonfuls +tablespoons +tablespoonsful +tablet +tableted +tableting +tabletop +tabletops +tablets +tableware +tabling +tabloid +tabloids +taboo +tabooed +tabooing +tabooli +taboos +tabor +taborer +taborers +taboret +taborets +tabors +tabouli +tabour +tabourer +tabourers +tabouret +tabourets +tabours +tabriz +tabs +tabu +tabued +tabuing +tabula +tabulae +tabular +tabularization +tabularizations +tabularize +tabularized +tabularizes +tabularizing +tabularly +tabulate +tabulated +tabulates +tabulating +tabulation +tabulations +tabulator +tabulators +tabun +tabuns +tabus +tac +tacamahac +tacamahacs +tacan +tacet +tach +tachina +tachinid +tachinids +tachism +tachisme +tachist +tachiste +tachistes +tachistoscope +tachistoscopes +tachistoscopic +tachistoscopically +tachists +tachograph +tachographs +tachometer +tachometers +tachometric +tachometry +tachyarrhythmia +tachyarrhythmias +tachycardia +tachycardiac +tachycardiacs +tachycardias +tachygraphy +tachylite +tachylites +tachylyte +tachylytes +tachylytic +tachymeter +tachymeters +tachymetry +tachyon +tachyonic +tachyons +tachyphylaxes +tachyphylaxis +tachypnea +tachypneas +tachysterol +tachysterols +tacit +tacitly +tacitness +taciturn +taciturnity +taciturnly +tacitus +tack +tackboard +tackboards +tacked +tacker +tackers +tackier +tackies +tackiest +tackified +tackifier +tackifiers +tackifies +tackify +tackifying +tackily +tackiness +tacking +tackle +tackled +tackler +tacklers +tackles +tackless +tackling +tacks +tacky +taco +tacoma +taconite +taconites +tacos +tact +tactful +tactfully +tactfulness +tactic +tactical +tactically +tactician +tacticians +tactics +tactile +tactilely +tactility +taction +tactions +tactless +tactlessly +tactlessness +tactoreceptor +tactoreceptors +tactual +tactually +tad +tadema +tadjik +tadjiks +tadpole +tadpoles +tads +tadzhik +tadzhiki +tadzhikistan +tadzhiks +tael +taels +taenia +taeniacide +taeniacides +taeniae +taeniafuge +taeniafuges +taenias +taeniasis +taeniasises +taffeta +taffetas +taffetized +taffia +taffias +taffies +taffrail +taffrails +taffy +tafia +tafias +tag +tagalog +tagalogs +tagalong +tagalongs +tagboard +tagboards +tagged +tagger +taggers +tagging +taggle +tagliatelle +tagline +taglines +tagma +tagmata +tagore +tagrag +tags +tagus +tahini +tahiti +tahitian +tahitians +tahoe +tahr +tahrs +tahseeldar +tahseeldars +tahsil +tahsildar +tahsildars +tai +taiga +taigas +tail +tailback +tailbacks +tailboard +tailboards +tailbone +tailbones +tailcoat +tailcoated +tailcoats +tailed +tailender +tailenders +tailer +tailers +tailfin +tailfins +tailgate +tailgated +tailgater +tailgaters +tailgates +tailgating +tailing +tailings +taille +tailles +tailless +taillight +taillights +taillike +tailor +tailorbird +tailorbirds +tailored +tailoring +tailors +tailpiece +tailpieces +tailpipe +tailpipes +tailplane +tailplanes +tailrace +tailraces +tails +tailskid +tailskids +tailslide +tailslides +tailspin +tailspins +tailstock +tailstocks +tailwater +tailwind +tailwinds +tain +taino +tainos +tains +taint +tainted +tainting +taintless +taintlessly +taintlessness +taints +taipan +taipans +taipeh +taipei +tais +taiwan +taiwanese +taj +tajik +tajiki +tajikistan +tajiks +tajs +taka +takable +takahe +takahes +takas +take +takeaway +takeaways +takedown +takedowns +taken +takeoff +takeoffs +takeout +takeouts +takeover +takeovers +taker +takers +takes +takin +taking +takings +takins +takkakaw +taklamakan +taklimakan +tala +talapoin +talapoins +talaria +talas +talaud +talaur +talbot +talc +talced +talcing +talcked +talcking +talcky +talcose +talcous +talcs +talcum +tale +talebearer +talebearers +talebearing +talent +talented +talentless +talentlessness +talents +taler +talers +tales +talesman +talesmen +taleteller +taletellers +taletelling +tali +talion +talions +taliped +talipeds +talipes +talipot +talipots +talisman +talismanic +talismanical +talismanically +talismans +talk +talkathon +talkathons +talkative +talkatively +talkativeness +talkback +talkbacks +talked +talker +talkers +talkfest +talkfests +talkie +talkier +talkies +talkiest +talkiness +talking +talks +talky +tall +tallage +tallaged +tallages +tallaging +tallahassee +tallboy +tallboys +taller +tallest +talleyrand +tallgrass +tallied +tallies +tallis +tallish +tallisim +tallith +tallithim +talliths +tallness +tallow +tallowed +tallowing +tallows +tallowy +tally +tallyho +tallyhoed +tallyhoing +tallyhos +tallying +tallyman +tallymen +talmi +talmud +talmudic +talmudical +talmudism +talmudist +talmudists +talon +taloned +talons +talus +taluses +tam +tamable +tamale +tamales +tamandua +tamanduas +tamarack +tamaracks +tamarao +tamaraos +tamarau +tamaraus +tamari +tamarillo +tamarillos +tamarin +tamarind +tamarinds +tamarins +tamarisk +tamarisks +tambac +tambacs +tambak +tambaks +tambala +tambalas +tambour +tamboura +tambouras +tamboured +tambourer +tambourers +tambourin +tambourine +tambourines +tambouring +tambourins +tambours +tambura +tamburas +tamburitza +tamburitzas +tamburlaine +tame +tameable +tamed +tameless +tamely +tameness +tamer +tamerlane +tamers +tames +tamest +tamil +tamils +taming +tammany +tammanyism +tammuz +tammy +tamora +tamoxifen +tamp +tampa +tamped +tamper +tampered +tamperer +tamperers +tampering +tamperproof +tampers +tamping +tampion +tampions +tampon +tamponed +tamponing +tampons +tamps +tams +tamworth +tan +tanager +tanagers +tanagrine +tanbark +tanbarks +tanbur +tanburs +tancred +tandem +tandems +tandoor +tandoori +tandoors +tang +tanganyika +tanganyikan +tanganyikans +tanged +tangelo +tangelos +tangence +tangency +tangent +tangental +tangential +tangentiality +tangentially +tangents +tangerine +tangerines +tangibility +tangible +tangibleness +tangibles +tangibly +tangier +tangiest +tanginess +tanging +tangle +tangled +tanglement +tangles +tangling +tangly +tango +tangoed +tangoing +tangolike +tangoreceptor +tangoreceptors +tangos +tangram +tangrams +tangs +tangy +tanimbar +tanist +tanistry +tanists +tank +tanka +tankage +tankages +tankard +tankards +tankas +tanked +tanker +tankers +tankful +tankfuls +tanking +tankless +tanklike +tanks +tannage +tannate +tannates +tanned +tanner +tanneries +tanners +tannery +tannest +tannhäuser +tannic +tanniferous +tannin +tanning +tannings +tannins +tannish +tanoak +tanoaks +tanoan +tanrec +tanrecs +tans +tansies +tansy +tantalate +tantalic +tantalite +tantalites +tantalization +tantalizations +tantalize +tantalized +tantalizer +tantalizers +tantalizes +tantalizing +tantalizingly +tantalum +tantalums +tantalus +tantaluses +tantamount +tantara +tantaras +tantivies +tantivy +tantra +tantras +tantric +tantrism +tantrist +tantrists +tantrum +tantrums +tanuki +tanyard +tanyards +tanzania +tanzanian +tanzanians +tanzanite +tanzanites +tao +taoiseach +taoism +taoist +taoistic +taoists +taormina +taos +tap +tapa +tapas +tape +tapeable +taped +tapeless +tapeline +tapelines +taper +tapered +taperer +taperers +tapering +taperingly +tapers +taperstick +tapersticks +tapes +tapestried +tapestries +tapestry +tapestrying +tapeta +tapetal +tapetum +tapeworm +tapeworms +taphole +tapholes +taphonomic +taphonomist +taphonomists +taphonomy +taping +tapings +tapioca +tapiocas +tapir +tapirs +tapis +tapped +tapper +tappers +tappet +tappets +tapping +tappings +taproom +taprooms +taproot +taproots +taps +tapster +tapsters +tapénade +tar +taradiddle +taradiddles +tarahumara +tarahumaras +taramasalata +taramasalatas +taramosalata +taramosalatas +tarantella +tarantellas +tarantism +tarantisms +taranto +tarantula +tarantulae +tarantulas +tarascan +tarascans +tarawa +tarboosh +tarbooshes +tarbush +tarbushes +tardenois +tardenoisean +tardier +tardiest +tardigrade +tardigrades +tardily +tardiness +tardive +tardo +tardy +tare +tared +tarentum +tares +targe +targes +target +targetable +targeted +targeting +targets +targum +targums +tarheel +tarheels +tariff +tariffed +tariffing +tariffs +taring +tarlatan +tarlatans +tarletan +tarletans +tarmac +tarmacadam +tarmacadams +tarmacked +tarmacking +tarmacs +tarn +tarnal +tarnally +tarnation +tarnations +tarnish +tarnishable +tarnished +tarnishes +tarnishing +tarns +taro +taroc +tarocs +tarok +taroks +taros +tarot +tarots +tarp +tarpaper +tarpapered +tarpapers +tarpaulin +tarpaulins +tarpon +tarpons +tarps +tarquin +tarquins +tarradiddle +tarradiddles +tarragon +tarragona +tarre +tarred +tarres +tarriance +tarriances +tarried +tarrier +tarriers +tarries +tarriest +tarring +tarry +tarrying +tars +tarsal +tarsi +tarsier +tarsiers +tarsometatarsal +tarsometatarsi +tarsometatarsus +tarsus +tart +tartan +tartans +tartar +tartare +tartarean +tartareous +tartarian +tartaric +tartarization +tartarizations +tartarize +tartarized +tartarizes +tartarizing +tartarous +tartars +tartarus +tartary +tarter +tartest +tartier +tartiest +tartily +tartine +tartines +tartiness +tartish +tartlet +tartlets +tartly +tartness +tartrate +tartrated +tartrates +tarts +tartufe +tartufes +tartuffe +tartuffery +tartuffes +tarty +tarvia +tarweed +tarweeds +tarzan +tarzans +tashkent +task +tasked +tasking +taskmaster +taskmasters +taskmistress +taskmistresses +tasks +tasman +tasmania +tasmanian +tasmanians +tass +tasse +tassel +tasseled +tasseling +tasselled +tasselling +tassels +tasses +tasset +tassets +tasso +tastable +taste +tasted +tasteful +tastefully +tastefulness +tasteless +tastelessly +tastelessness +tastemaker +tastemakers +taster +tasters +tastes +tastier +tastiest +tastily +tastiness +tasting +tastings +tasty +tat +tatami +tatamis +tatar +tatars +tatary +tater +taters +tats +tatted +tatter +tatterdemalion +tatterdemalions +tattered +tattering +tatters +tattersall +tattersalls +tattier +tattiest +tattiness +tatting +tattle +tattled +tattler +tattlers +tattles +tattletale +tattletales +tattling +tattlingly +tattoo +tattooed +tattooer +tattooers +tattooing +tattooist +tattooists +tattoos +tatty +tau +taught +taunt +taunted +taunter +taunters +taunting +tauntingly +taunts +taupe +taurean +taureans +taurine +taurines +taurocholic +taurus +tausug +taut +tautaug +tautaugs +tauten +tautened +tautening +tautens +tauter +tautest +tautly +tautness +tautog +tautogs +tautologic +tautological +tautologically +tautologies +tautologist +tautologists +tautologize +tautologized +tautologizes +tautologizing +tautologous +tautologously +tautology +tautomer +tautomeric +tautomerism +tautomerisms +tautomers +tautonym +tautonymic +tautonymous +tautonyms +tautonymy +tav +tavern +taverna +tavernas +taverner +taverners +taverns +taw +tawdrier +tawdriest +tawdrily +tawdriness +tawdry +tawed +tawer +tawers +tawing +tawnier +tawnies +tawniest +tawniness +tawny +taws +tawse +tax +taxa +taxability +taxable +taxableness +taxables +taxably +taxation +taxed +taxeme +taxemes +taxemic +taxer +taxers +taxes +taxi +taxicab +taxicabs +taxidermal +taxidermic +taxidermist +taxidermists +taxidermy +taxied +taxies +taxiing +taximan +taximen +taximeter +taximeters +taximetrics +taxing +taxingly +taxis +taxiway +taxiways +taxman +taxmen +taxon +taxonomic +taxonomical +taxonomically +taxonomies +taxonomist +taxonomists +taxonomy +taxons +taxpayer +taxpayers +taxpaying +taxus +taxying +taygeta +taylor +tayra +tayras +tayside +tazza +tazzas +tbilisi +tchaikovskian +tchaikovsky +tchaikovskyan +tchotchke +tchotchkes +te +tea +teabag +teabags +teaberry +teacake +teacakes +teacart +teacarts +teach +teachability +teachable +teachableness +teachably +teacher +teacherly +teachers +teaches +teaching +teachings +teacup +teacupful +teacupfuls +teacups +teahouse +teahouses +teak +teakettle +teakettles +teaks +teakwood +teal +tealike +teals +team +teamed +teaming +teammate +teammates +teams +teamster +teamsters +teamwork +teapot +teapots +teapoy +teapoys +tear +tearable +tearaway +tearaways +teardown +teardowns +teardrop +teardrops +teared +tearer +tearers +tearful +tearfully +tearfulness +teargas +teargases +teargassed +teargasses +teargassing +tearier +teariest +tearily +teariness +tearing +tearjerker +tearjerkers +tearless +tearlessly +tearoom +tearooms +tears +tearstain +tearstained +tearstains +teary +teas +tease +teased +teasel +teaseled +teaseling +teaselled +teaselling +teasels +teaser +teasers +teases +teashop +teashops +teasing +teasingly +teaspoon +teaspoonful +teaspoonfuls +teaspoons +teaspoonsful +teat +teated +teatime +teatimes +teats +tebet +tebeth +tech +teched +techie +techies +technetium +technetronic +technic +technical +technicalities +technicality +technicalization +technicalizations +technicalize +technicalized +technicalizes +technicalizing +technically +technicalness +technicals +technician +technicians +technicolor +technics +technique +techniques +technobabble +technocracies +technocracy +technocrat +technocratic +technocrats +technologic +technological +technologically +technologies +technologist +technologists +technologize +technologized +technologizes +technologizing +technology +technophile +technophiles +technophobe +technophobes +technophobia +technophobic +technostructure +technostructures +techy +tecta +tectal +tectonic +tectonically +tectonics +tectonism +tectonisms +tectrices +tectrix +tectum +ted +tedded +tedder +tedders +teddies +tedding +teddy +tedious +tediously +tediousness +tedium +teds +tee +teed +teeing +teem +teemed +teemer +teemers +teeming +teemingly +teemingness +teems +teen +teenage +teenaged +teenager +teenagers +teener +teeners +teenier +teeniest +teens +teensier +teensiest +teensy +teeny +teenybop +teenybopper +teenyboppers +teeoff +teeoffs +teepee +teepees +tees +teeter +teeterboard +teeterboards +teetered +teetering +teeters +teeth +teethe +teethed +teether +teethers +teethes +teething +teethridge +teethridges +teetotal +teetotaler +teetotalers +teetotalism +teetotalist +teetotalists +teetotaller +teetotallers +teetotally +teetotum +teetotums +teff +tefillin +teflon +teg +tegg +teggs +tegmen +tegmental +tegmentum +tegmentums +tegmina +tegs +tegu +tegua +teguas +tegucigalpa +tegular +tegularly +tegulated +tegument +tegumental +tegumentary +teguments +tegus +tehachapi +teheran +tehran +tehuantepec +tehuelche +tehuelchean +tehuelches +teiglach +teiid +teiids +tekkie +tekkies +tektite +tektites +tektitic +tektronix +tel +telaesthesia +telaesthesias +telamon +telamones +telangiectases +telangiectasia +telangiectasias +telangiectasis +telangiectatic +telecamera +telecameras +telecast +telecasted +telecaster +telecasters +telecasting +telecasts +telecom +telecommunicate +telecommunicated +telecommunicates +telecommunicating +telecommunication +telecommunications +telecommunicator +telecommunicators +telecommute +telecommuted +telecommuter +telecommuters +telecommutes +telecommuting +telecoms +teleconference +teleconferenced +teleconferences +teleconferencing +telecopier +telecourse +telecourses +teledrama +teledramas +teledu +teledus +telefacsimile +telefacsimiles +telefilm +telefilms +telegenic +telegenically +telegonic +telegonous +telegony +telegram +telegrammed +telegramming +telegrams +telegraph +telegraphed +telegrapher +telegraphers +telegraphese +telegraphic +telegraphical +telegraphically +telegraphing +telegraphist +telegraphists +telegraphs +telegraphy +telegu +telegus +telekinesis +telekinetic +telekinetically +telemachus +telemark +telemarked +telemarker +telemarkers +telemarketer +telemarketers +telemarketing +telemarking +telemarks +telemedicine +telemeter +telemetered +telemetering +telemeters +telemetric +telemetrical +telemetrically +telemetry +telencephalic +telencephalon +telencephalons +teleologic +teleological +teleologically +teleologies +teleologist +teleologists +teleology +teleonomic +teleonomy +teleost +teleostean +teleosteans +teleosts +telepath +telepathic +telepathically +telepathist +telepathists +telepaths +telepathy +telephone +telephoned +telephoner +telephoners +telephones +telephonic +telephonically +telephoning +telephonist +telephonists +telephony +telephoto +telephotograph +telephotographed +telephotographic +telephotographing +telephotographs +telephotography +telephotos +teleplay +teleplays +teleport +teleportation +teleported +teleporting +teleports +teleprinter +teleprinters +teleprocessing +teleprompter +teleprompters +teleran +telerans +telescope +telescoped +telescopes +telescopic +telescopically +telescoping +telescopist +telescopists +telescopium +telescopy +teleses +teleshopping +teleshoppings +telesis +telestereoscope +telestereoscopes +telesthesia +telesthesias +telesthetic +telesto +teletext +teletexts +teletheater +teletheaters +telethermoscope +telethermoscopes +telethon +telethons +teletranscription +teletranscriptions +teletype +teletyped +teletypes +teletypesetter +teletypewriter +teletypewriters +teletyping +teleutospore +teleutospores +teleutosporic +televangelism +televangelist +televangelists +teleview +televiewed +televiewer +televiewers +televiewing +televiews +televise +televised +televises +televising +television +televisions +televisor +televisors +televisual +telex +telexed +telexes +telexing +telford +telia +telial +telic +telically +teliospore +teliospores +teliosporic +telium +tell +tellable +teller +tellers +tellership +tellies +telling +tellingly +tells +telltale +telltales +tellurian +tellurians +telluric +telluride +tellurion +tellurions +tellurium +tellurometer +tellurometers +tellurous +telly +tellys +telnet +telocentric +telolecithal +telome +telomere +telomeres +telophase +telophases +telophasic +telos +telotaxis +telotaxises +telpher +telphered +telphering +telphers +telson +telsons +telugu +telugus +tem +temblor +temblors +temerarious +temerariously +temerariousness +temerity +temne +temnes +temp +tempeh +tempehs +temper +tempera +temperability +temperable +temperament +temperamental +temperamentally +temperaments +temperance +temperas +temperate +temperately +temperateness +temperature +temperatures +tempered +temperedly +temperedness +temperer +temperers +tempering +tempers +tempest +tempested +tempesting +tempests +tempestuous +tempestuously +tempestuousness +tempi +templar +templars +template +templates +temple +templed +temples +templet +templets +tempo +temporal +temporalities +temporality +temporalize +temporalized +temporalizes +temporalizing +temporally +temporaries +temporarily +temporariness +temporary +tempore +temporization +temporizations +temporize +temporized +temporizer +temporizers +temporizes +temporizing +temporomandibular +tempos +temps +tempt +temptable +temptation +temptations +tempted +tempter +tempters +tempting +temptingly +temptingness +temptress +temptresses +tempts +tempura +tempuras +ten +tenability +tenable +tenableness +tenably +tenace +tenaces +tenacious +tenaciously +tenaciousness +tenacity +tenacula +tenaculum +tenancies +tenancy +tenant +tenantable +tenanted +tenanting +tenantless +tenantry +tenants +tench +tenches +tend +tendance +tended +tendencies +tendencious +tendency +tendentious +tendentiously +tendentiousness +tender +tendered +tenderer +tenderers +tenderest +tenderfeet +tenderfoot +tenderfoots +tenderhearted +tenderheartedly +tenderheartedness +tendering +tenderization +tenderizations +tenderize +tenderized +tenderizer +tenderizers +tenderizes +tenderizing +tenderloin +tenderloins +tenderly +tenderness +tendernesses +tenderometer +tenderometers +tenders +tending +tendinitis +tendinous +tendon +tendonitis +tendons +tendresse +tendril +tendriled +tendrilled +tendrilous +tendrils +tends +tenebrae +tenebrific +tenebrionid +tenebrionids +tenebrious +tenebrism +tenebrist +tenebrists +tenebrosity +tenebrous +tenebrously +tenement +tenemental +tenementary +tenements +tenens +tenerife +tenesmus +tenesmuses +tenet +tenets +tenfold +tenia +teniacide +teniacides +teniae +teniafuge +teniafuges +tenias +teniasis +teniasises +tenner +tenners +tennessean +tennesseans +tennessee +tenniel +tennies +tennis +tennist +tennists +tennyson +tennysonian +tenochtitlán +tenon +tenoned +tenoning +tenonitis +tenons +tenor +tenorist +tenorists +tenorrhaphies +tenorrhaphy +tenors +tenos +tenosynovitis +tenosynovitises +tenotomies +tenotomy +tenpenny +tenpin +tenpins +tenpounder +tenpounders +tenrec +tenrecs +tens +tense +tensed +tensely +tenseness +tenser +tenses +tensest +tensile +tensility +tensimeter +tensimeters +tensing +tensiometer +tensiometers +tensiometric +tensiometry +tension +tensional +tensioned +tensioner +tensioners +tensioning +tensionless +tensions +tensities +tensity +tensive +tensor +tensorial +tensors +tent +tentacle +tentacled +tentacles +tentacular +tentage +tentages +tentative +tentatively +tentativeness +tented +tenter +tentered +tenterhook +tenterhooks +tentering +tenters +tenth +tenthly +tenths +tenting +tentless +tentlike +tentmaker +tentmakers +tents +tenues +tenuis +tenuity +tenuous +tenuously +tenuousness +tenurable +tenure +tenured +tenures +tenurial +tenurially +tenuto +teocalli +teocallis +teosinte +teosintes +teotihuacán +tepa +tepal +tepals +tepary +tepas +tepee +tepees +tephra +tephras +tepid +tepidity +tepidly +tepidness +tequila +tequilas +teraampere +teraamperes +terabecquerel +terabecquerels +terabit +terabits +terabyte +terabytes +teracandela +teracandelas +teracoulomb +teracoulombs +terafarad +terafarads +teraflop +teraflops +teragram +teragrams +terahenries +terahenry +terahenrys +terahertz +terai +terais +terajoule +terajoules +terakelvin +terakelvins +teralumen +teralumens +teralux +terameter +terameters +teramole +teramoles +teranewton +teranewtons +teraohm +teraohms +terapascal +terapascals +teraph +teraphim +teraradian +teraradians +terasecond +teraseconds +terasiemens +terasievert +terasieverts +terasteradian +terasteradians +teratesla +terateslas +teratism +teratisms +teratocarcinoma +teratocarcinomas +teratocarcinomata +teratogen +teratogenesis +teratogenic +teratogenicity +teratogens +teratoid +teratologic +teratological +teratologist +teratologists +teratology +teratoma +teratomas +teratomata +teratomatous +teravolt +teravolts +terawatt +terawatts +teraweber +terawebers +terbium +terce +terceira +tercel +tercels +tercentenaries +tercentenary +tercentennial +tercentennials +tercet +tercets +terebene +terebenes +terebic +terebinth +terebinthic +terebinthine +terebinths +teredines +teredo +teredos +terence +terephthalate +terephthalates +terephthalic +teresa +terete +tereus +terga +tergal +tergite +tergites +tergiversate +tergiversated +tergiversates +tergiversating +tergiversation +tergiversations +tergiversator +tergiversators +tergum +teriyaki +teriyakis +term +termagant +termagants +termed +termer +termers +terminability +terminable +terminableness +terminably +terminal +terminally +terminals +terminate +terminated +terminates +terminating +termination +terminational +terminations +terminative +terminatively +terminator +terminators +terminer +terming +termini +terminological +terminologically +terminologies +terminologist +terminologists +terminology +terminus +terminuses +termitaria +termitaries +termitarium +termitary +termite +termites +termitic +termless +terms +tern +ternaries +ternary +ternate +ternately +terne +terneplate +terneplates +ternes +terns +terpene +terpeneless +terpenes +terpenic +terpenoid +terpenoids +terpin +terpineol +terpineols +terpolymer +terpolymers +terpsichore +terpsichorean +terpsichoreans +terpsichores +terr +terra +terrace +terraced +terraces +terracing +terracotta +terrae +terrain +terrains +terramycin +terran +terrane +terranes +terrapin +terrapins +terraqueous +terraria +terrarium +terrariums +terrazzo +terrene +terrenes +terreplein +terrepleins +terrestrial +terrestrially +terrestrialness +terrestrials +terret +terrets +terrible +terribleness +terribles +terribly +terricolous +terrier +terriers +terries +terrific +terrifically +terrified +terrifier +terrifiers +terrifies +terrify +terrifying +terrifyingly +terrigenous +terrine +terrines +territorial +territorialism +territorialist +territorialists +territorialities +territoriality +territorialization +territorializations +territorialize +territorialized +territorializes +territorializing +territorially +territorials +territories +territory +terror +terrorism +terrorist +terroristic +terrorists +terrorization +terrorizations +terrorize +terrorized +terrorizer +terrorizers +terrorizes +terrorizing +terrorless +terrors +terrs +terry +terse +tersely +terseness +terser +tersest +tertial +tertials +tertian +tertians +tertiaries +tertiary +tertium +tertullian +tervalent +tervuren +terza +terze +tesla +teslas +tessellate +tessellated +tessellates +tessellating +tessellation +tessellations +tessera +tesseract +tesseracts +tesserae +tessitura +tessituras +test +testa +testability +testable +testacean +testaceans +testaceous +testacy +testae +testament +testamentary +testaments +testate +testator +testators +testatrices +testatrix +testatrixes +testcross +testcrossed +testcrosses +testcrossing +tested +testee +testees +tester +testers +testes +testicle +testicles +testicular +testiculate +testier +testiest +testificandum +testification +testifications +testified +testifier +testifiers +testifies +testify +testifying +testily +testimonial +testimonials +testimonies +testimony +testiness +testing +testis +teston +testons +testoon +testoons +testosterone +tests +testudinal +testudinate +testudinates +testudo +testudos +testy +tetanal +tetanic +tetanically +tetanies +tetanization +tetanizations +tetanize +tetanized +tetanizes +tetanizing +tetanus +tetany +tetartohedral +tetched +tetchier +tetchiest +tetchily +tetchiness +tetchy +teth +tether +tetherball +tetherballs +tethered +tethering +tethers +tethys +teton +tetons +tetra +tetrabasic +tetrabasicity +tetrabranchiate +tetrabranchiates +tetracaine +tetracaines +tetrachloride +tetrachlorides +tetrachloroethylene +tetrachord +tetrachordal +tetrachords +tetracid +tetracids +tetracyclic +tetracycline +tetracyclines +tetrad +tetradactylous +tetradic +tetradrachm +tetradrachms +tetrads +tetradymite +tetradymites +tetradynamous +tetraethyl +tetraethyllead +tetraethylleads +tetrafluoride +tetrafluorides +tetragon +tetragonal +tetragonally +tetragons +tetragrammaton +tetragynous +tetrahedra +tetrahedral +tetrahedrally +tetrahedrite +tetrahedrites +tetrahedron +tetrahedrons +tetrahydrocannabinol +tetrahydrocannabinols +tetrahydrofuran +tetrahydrofurans +tetrahydroxy +tetrahymena +tetrahymenas +tetralogies +tetralogy +tetramer +tetrameric +tetramerism +tetramerous +tetramers +tetrameter +tetrameters +tetramethyllead +tetramethylleads +tetrandrous +tetraplegic +tetraploid +tetraploids +tetraploidy +tetrapod +tetrapodous +tetrapods +tetrapterous +tetrapyrrole +tetrapyrroles +tetrarch +tetrarchate +tetrarchates +tetrarchic +tetrarchical +tetrarchies +tetrarchs +tetrarchy +tetras +tetrasporangia +tetrasporangium +tetraspore +tetraspores +tetrasporic +tetrastyle +tetrasyllabic +tetratomic +tetravalent +tetrazolium +tetrazoliums +tetrazzini +tetrode +tetrodes +tetrodotoxin +tetrodotoxins +tetroxide +tetroxides +tetryl +tetryls +tetter +tetterbush +tetterbushes +tetters +teuton +teutonic +teutonically +teutonicism +teutonicisms +teutonism +teutonisms +teutonist +teutonists +teutonization +teutonizations +teutonize +teutonized +teutonizes +teutonizing +teutons +tevet +tewa +tewas +tex +texaco +texan +texans +texas +texel +text +textbook +textbookish +textbooks +textile +textiles +texts +textual +textualism +textualisms +textualist +textualists +textually +textuaries +textuary +textural +texturally +texture +textured +textureless +textures +texturing +texturize +texturized +texturizer +texturizers +texturizes +texturizing +thackeray +thai +thailand +thais +thalamencephalic +thalamencephalon +thalamencephalons +thalami +thalamic +thalamically +thalamus +thalassemia +thalassemias +thalassemic +thalassic +thalassocracies +thalassocracy +thalassocrat +thalassocrats +thaler +thalers +thales +thalesian +thalia +thalidomide +thalli +thallic +thallium +thalloid +thalloidal +thallophyte +thallophytes +thallophytic +thallous +thallus +thalluses +thammuz +than +thanage +thanages +thanatological +thanatologist +thanatologists +thanatology +thanatopsis +thanatos +thanatotic +thane +thanes +thaneship +thanet +thank +thanked +thanker +thankers +thankful +thankfully +thankfulness +thanking +thankless +thanklessly +thanklessness +thanks +thanksgiving +thanksgivings +thankworthier +thankworthiest +thankworthy +that +that'd +that'll +that's +thataway +thatch +thatched +thatcher +thatchers +thatches +thatching +thatchy +thaumatologies +thaumatology +thaumaturge +thaumaturges +thaumaturgic +thaumaturgical +thaumaturgist +thaumaturgists +thaumaturgy +thaw +thawed +thawing +thaws +the +theanthropic +theanthropical +theanthropism +theanthropisms +theanthropist +theanthropists +thearchies +thearchy +theater +theatergoer +theatergoers +theatergoing +theaters +theatine +theatines +theatre +theatres +theatric +theatrical +theatricalism +theatricalisms +theatricality +theatricalization +theatricalizations +theatricalize +theatricalized +theatricalizer +theatricalizers +theatricalizes +theatricalizing +theatrically +theatricalness +theatricals +theatrics +thebaine +thebaines +theban +thebans +thebe +thebes +theca +thecae +thecal +thecate +thecodont +thecodonts +thee +theelin +theelins +theelol +theelols +theft +thefts +thegn +thegnly +their +theirs +theirselves +theism +theist +theistic +theistical +theistically +theists +them +thematic +thematically +theme +themed +themeless +themes +themistocles +themselves +then +thenar +thenars +thence +thenceforth +thenceforward +thenceforwards +theobald +theobromine +theobromines +theocentric +theocentricity +theocentrism +theocracies +theocracy +theocrat +theocratic +theocratical +theocratically +theocrats +theocritus +theodicies +theodicy +theodolite +theodolites +theodolitic +theodora +theodore +theodoric +theodosius +theogonic +theogonies +theogony +theolog +theologian +theologians +theologic +theological +theologically +theologies +theologize +theologized +theologizer +theologizers +theologizes +theologizing +theologs +theologue +theologues +theology +theomachies +theomachy +theomorphic +theomorphism +theomorphisms +theonomous +theonomy +theophanic +theophanies +theophany +theophrastus +theophylline +theophyllines +theorbo +theorbos +theorem +theorematic +theorems +theoretic +theoretical +theoretically +theoretician +theoreticians +theoretics +theories +theorist +theorists +theorization +theorizations +theorize +theorized +theorizer +theorizers +theorizes +theorizing +theory +theosophic +theosophical +theosophically +theosophies +theosophist +theosophists +theosophy +theotokos +therapeusis +therapeutic +therapeutical +therapeutically +therapeutics +therapeutist +therapeutists +therapies +therapist +therapists +therapsid +therapsids +therapy +theravada +there +there'd +there'll +there's +thereabout +thereabouts +thereafter +thereagainst +thereat +thereby +therefor +therefore +therefrom +therein +thereinafter +thereinto +theremin +theremins +thereof +thereon +theresa +thereto +theretofore +thereunder +thereunto +thereupon +therewith +therewithal +theriac +theriaca +theriacal +theriacs +theriomorphic +theriomorphous +therm +thermal +thermalization +thermalizations +thermalize +thermalized +thermalizes +thermalizing +thermally +thermals +thermanesthesia +thermanesthesias +thermesthesia +thermesthesias +thermic +thermically +thermidor +thermion +thermionic +thermionics +thermions +thermistor +thermistors +thermit +thermite +thermocauteries +thermocautery +thermochemical +thermochemist +thermochemistry +thermochemists +thermocline +thermoclines +thermocoagulation +thermocoagulations +thermocouple +thermocouples +thermoduric +thermodynamic +thermodynamical +thermodynamically +thermodynamicist +thermodynamicists +thermodynamics +thermoelectric +thermoelectrical +thermoelectrically +thermoelectricity +thermoelectron +thermoelectrons +thermoelement +thermoelements +thermoform +thermoformable +thermoformed +thermoforming +thermoforms +thermogenesis +thermogenetic +thermogenic +thermogram +thermograms +thermograph +thermographic +thermographically +thermographies +thermographs +thermography +thermohaline +thermojunction +thermojunctions +thermolabile +thermolability +thermoluminescence +thermoluminescences +thermoluminescent +thermolyses +thermolysis +thermolytic +thermomagnetic +thermometer +thermometers +thermometric +thermometrically +thermometry +thermomotor +thermomotors +thermonuclear +thermoperiodicities +thermoperiodicity +thermoperiodism +thermoperiodisms +thermophile +thermophiles +thermophilic +thermophilous +thermopile +thermopiles +thermoplastic +thermoplasticity +thermoplastics +thermoreceptor +thermoreceptors +thermoregulate +thermoregulated +thermoregulates +thermoregulating +thermoregulation +thermoregulations +thermoregulator +thermoregulators +thermoregulatory +thermoremanence +thermoremanent +thermos +thermoscope +thermoscopes +thermoses +thermoset +thermosets +thermosetting +thermosphere +thermospheric +thermostabile +thermostability +thermostable +thermostat +thermostatic +thermostatically +thermostats +thermotactic +thermotaxes +thermotaxic +thermotaxis +thermotherapies +thermotherapy +thermotropic +thermotropism +therms +theropod +theropodan +theropodans +theropods +thersites +thesaural +thesauri +thesaurus +thesauruses +these +these'd +these'll +theses +theseus +thesis +thespian +thespians +thespis +thessalian +thessalians +thessalonian +thessalonians +thessalonica +thessaloniki +thessaloníki +thessaly +theta +thetas +thetic +thetical +thetically +thetis +theurgic +theurgical +theurgically +theurgies +theurgist +theurgists +theurgy +thew +thews +thewy +they +they'd +they'll +they're +they've +thiabendazole +thiabendazoles +thiamin +thiaminase +thiaminases +thiamine +thiamines +thiamins +thiazide +thiazides +thiazine +thiazines +thiazole +thiazoles +thick +thicken +thickened +thickener +thickeners +thickening +thickenings +thickens +thicker +thickest +thicket +thicketed +thickets +thickety +thickhead +thickheaded +thickheads +thickish +thickly +thickness +thicknesses +thickset +thickskulled +thief +thieve +thieved +thieveries +thievery +thieves +thieving +thievish +thievishly +thievishness +thigh +thighbone +thighbones +thighed +thighs +thigmotactic +thigmotactically +thigmotaxis +thigmotaxises +thigmotropic +thigmotropism +thigmotropisms +thill +thills +thimble +thimbleberries +thimbleberry +thimbleful +thimblefuls +thimblerig +thimblerigged +thimblerigger +thimbleriggers +thimblerigging +thimblerigs +thimbles +thimbleweed +thimbleweeds +thimbu +thimerosal +thimerosals +thimphu +thin +thine +thing +thingamabob +thingamabobs +thingamajig +thingamajigs +thingness +things +thingumabob +thingumabobs +thingumajig +thingumajigs +thingumbob +thingumbobs +thingummies +thingummy +think +thinkable +thinkableness +thinkably +thinker +thinkers +thinking +thinkingly +thinkingness +thinkings +thinks +thinly +thinned +thinner +thinners +thinness +thinnest +thinning +thinnish +thins +thio +thiocarbamide +thiocarbamides +thiocyanate +thiocyanates +thiocyanic +thiokol +thiol +thiolic +thiols +thionic +thionyl +thionyls +thiopental +thiophene +thiophenes +thioridazine +thioridazines +thiosulfate +thiosulfates +thiosulfuric +thiotepa +thiotepas +thiouracil +thiouracils +thiourea +thioureas +thiram +thirams +third +thirdhand +thirdly +thirds +thirst +thirsted +thirster +thirsters +thirstier +thirstiest +thirstily +thirstiness +thirsting +thirsts +thirsty +thirteen +thirteenfold +thirteens +thirteenth +thirteenths +thirties +thirtieth +thirtieths +thirty +thirtyfold +thirtyish +this +this'd +this'll +thisaway +thisbe +thistle +thistledown +thistles +thistly +thither +thitherto +thitherward +thitherwards +thixotropic +thixotropy +tho +thohoyandou +thole +tholeiite +tholeiitic +tholepin +tholepins +tholes +thomas +thomism +thomist +thomistic +thomists +thompson +thomson +thong +thonged +thongs +thor +thoraces +thoracic +thoracically +thoracolumbar +thoracoplasties +thoracoplasty +thoracotomies +thoracotomy +thorax +thoraxes +thorazine +thoreau +thoreauvian +thoria +thorianite +thorias +thoric +thorite +thorites +thorium +thorn +thornback +thornbacks +thornbush +thornbushes +thorndike +thorned +thornier +thorniest +thornily +thorniness +thornless +thornlike +thorns +thorny +thoron +thorons +thorough +thoroughbass +thoroughbasses +thoroughbrace +thoroughbraces +thoroughbred +thoroughbreds +thoroughfare +thoroughfares +thoroughgoing +thoroughly +thoroughness +thoroughpaced +thoroughpin +thoroughpins +thoroughwort +thoroughworts +thorp +thorps +those +those'd +those'll +thou +though +thought +thoughtful +thoughtfully +thoughtfulness +thoughtless +thoughtlessly +thoughtlessness +thoughts +thoughtway +thoughtways +thousand +thousandfold +thousands +thousandth +thousandths +thrace +thracian +thracians +thraldom +thrall +thralldom +thralled +thralling +thralls +thrash +thrashed +thrasher +thrashers +thrashes +thrashing +thrashings +thrasonical +thrasonically +thread +threadbare +threadbareness +threaded +threader +threaders +threadfin +threadfins +threadier +threadiest +threadiness +threading +threadless +threadlike +threads +threadworm +threadworms +thready +threat +threated +threaten +threatened +threatener +threateners +threatening +threateningly +threatens +threating +threats +three +threefold +threepence +threepences +threepenny +threes +threescore +threesome +threesomes +thremmatology +threnode +threnodes +threnodial +threnodic +threnodies +threnodist +threnodists +threnody +threonine +threonines +thresh +threshed +thresher +threshers +threshes +threshing +threshold +thresholds +threw +thrice +thrift +thriftier +thriftiest +thriftily +thriftiness +thriftless +thriftlessly +thriftlessness +thrifts +thrifty +thrill +thrilled +thriller +thrillers +thrilling +thrillingly +thrills +thrips +thrive +thrived +thriven +thriver +thrivers +thrives +thriving +thrivingly +throat +throated +throatier +throatiest +throatily +throatiness +throating +throatlatch +throatlatches +throats +throaty +throb +throbbed +throbber +throbbers +throbbing +throbbingly +throbs +throe +throes +thrombi +thrombin +thrombocyte +thrombocytes +thrombocytic +thrombocytopenia +thrombocytopenias +thrombocytopenic +thromboembolic +thromboembolism +thromboembolisms +thrombokinase +thrombokinases +thrombolyses +thrombolysis +thrombolytic +thrombophlebitis +thrombophlebitises +thromboplastic +thromboplastically +thromboplastin +thromboplastins +thromboses +thrombosis +thrombosthenin +thrombosthenins +thrombotic +thromboxane +thromboxanes +thrombus +throne +throned +thrones +throng +thronged +thronging +throngs +throning +throstle +throstles +throttle +throttleable +throttled +throttlehold +throttleholds +throttler +throttlers +throttles +throttling +through +throughly +throughout +throughput +throughway +throughways +throve +throw +throwaway +throwaways +throwback +throwbacks +thrower +throwers +throwing +thrown +throws +throwster +throwsters +thru +thrum +thrummed +thrumming +thrums +thrush +thrushes +thrust +thruster +thrusters +thrustful +thrusting +thrustor +thrustors +thrusts +thruway +thruways +thucydides +thud +thudded +thudding +thuds +thug +thuggery +thuggish +thugs +thuja +thujas +thule +thulium +thumb +thumbed +thumbhole +thumbholes +thumbing +thumbnail +thumbnails +thumbnut +thumbnuts +thumbprint +thumbprints +thumbs +thumbscrew +thumbscrews +thumbtack +thumbtacked +thumbtacking +thumbtacks +thumbwheel +thumbwheels +thummim +thump +thumped +thumper +thumpers +thumping +thumpingly +thumps +thunder +thunderbird +thunderbirds +thunderbolt +thunderbolts +thunderclap +thunderclaps +thundercloud +thunderclouds +thundered +thunderer +thunderers +thunderhead +thunderheads +thundering +thunderingly +thunderous +thunderously +thunders +thundershower +thundershowers +thunderstone +thunderstones +thunderstorm +thunderstorms +thunderstricken +thunderstrike +thunderstrikes +thunderstriking +thunderstroke +thunderstrokes +thunderstruck +thunk +thunked +thunking +thunks +thurber +thurible +thuribles +thurifer +thurifers +thuringer +thuringia +thuringian +thuringians +thurl +thurls +thursday +thursdays +thus +thusly +thwack +thwacked +thwacking +thwacks +thwart +thwarted +thwarter +thwarters +thwarting +thwartly +thwarts +thwartwise +thy +thyestean +thyestes +thylacine +thylacines +thylakoid +thylakoids +thyme +thymectomies +thymectomize +thymectomized +thymectomizes +thymectomizing +thymectomy +thymey +thymic +thymidine +thymidines +thymine +thymines +thymocyte +thymocytes +thymol +thymols +thymoma +thymomas +thymosin +thymosins +thymus +thymuses +thymy +thyratron +thyratrons +thyristor +thyristors +thyroactive +thyrocalcitonin +thyrocalcitonins +thyroglobulin +thyroglobulins +thyroid +thyroidal +thyroidectomies +thyroidectomize +thyroidectomized +thyroidectomizes +thyroidectomizing +thyroidectomy +thyroiditis +thyroiditises +thyroids +thyrotoxicosis +thyrotrophic +thyrotrophin +thyrotrophins +thyrotropic +thyrotropin +thyrotropins +thyroxin +thyroxine +thyroxines +thyroxins +thyrse +thyrses +thyrsi +thyrsoid +thyrsoidal +thyrsus +thysanuran +thysanurans +thyself +thásos +théatre +thíra +ti +tiahuanaco +tiara +tiaras +tiber +tiberian +tiberius +tibet +tibetan +tibetans +tibeto +tibia +tibiae +tibial +tibias +tibiofibula +tibiofibular +tibiofibulas +tibiotarsus +tibiotarsuses +tic +tical +ticals +ticced +ticcing +tick +tickbird +tickbirds +ticked +ticker +tickers +ticket +ticketed +ticketing +ticketless +tickets +ticking +tickle +tickled +tickler +ticklers +tickles +tickling +ticklish +ticklishly +ticklishness +ticks +tickseed +tickseeds +ticktack +ticktacks +ticktacktoe +ticktacktoes +ticktock +ticktocks +ticky +ticqueur +ticqueurs +tics +tictac +tidal +tidally +tidbit +tidbits +tiddledywinks +tiddler +tiddlers +tiddly +tiddlywinks +tide +tided +tideland +tidelands +tideless +tidemark +tidemarks +tiderip +tiderips +tides +tidewaiter +tidewaiters +tidewater +tidewaters +tideway +tideways +tidied +tidier +tidies +tidiest +tidily +tidiness +tiding +tidings +tidy +tidying +tidytips +tie +tieback +tiebacks +tiebreaker +tiebreakers +tiebreaking +tied +tieing +tieless +tiemannite +tiemannites +tientsin +tiepin +tiepins +tiepolo +tier +tierce +tiercel +tiercels +tierces +tiered +tiering +tierra +tiers +ties +tietze +tiff +tiffanies +tiffany +tiffed +tiffin +tiffing +tiffins +tiffs +tiger +tigereye +tigereyes +tigerish +tigerishly +tigerishness +tigerlike +tigers +tight +tighten +tightened +tightener +tighteners +tightening +tightens +tighter +tightest +tightfisted +tightfistedness +tightlipped +tightlippedness +tightly +tightness +tightrope +tightropes +tights +tightwad +tightwads +tightwire +tightwires +tiglic +tiglon +tiglons +tigon +tigons +tigre +tigress +tigresses +tigrinya +tigris +tigré +tike +tikes +tiki +tikis +til +tilapia +tilapias +tilburies +tilbury +tilde +tildes +tile +tiled +tilefish +tilefishes +tiler +tilers +tiles +tiling +till +tillable +tillage +tillamook +tillandsia +tillandsias +tilled +tiller +tillered +tillering +tillerman +tillermen +tillers +tilling +tills +tils +tilsit +tilsiter +tilt +tiltable +tilted +tilter +tilters +tilth +tilting +tiltmeter +tiltmeters +tilts +tiltyard +tiltyards +tim +timbal +timbale +timbales +timbals +timber +timberdoodle +timberdoodles +timbered +timberhead +timberheads +timbering +timberings +timberland +timberlands +timberline +timberlines +timberman +timbermen +timbers +timberwork +timberworks +timbral +timbre +timbrel +timbrelled +timbrels +timbres +timbuktu +time +timecard +timecards +timed +timekeeper +timekeepers +timekeeping +timeless +timelessly +timelessness +timelier +timeliest +timeline +timelines +timeliness +timely +timeous +timeously +timeout +timeouts +timepiece +timepieces +timepleaser +timepleasers +timer +timers +times +timesaver +timesavers +timesaving +timescale +timescales +timeserver +timeservers +timeserving +timeshare +timeshared +timeshares +timesharing +timetable +timetables +timework +timeworker +timeworkers +timeworn +timid +timider +timidest +timidity +timidly +timidness +timing +timings +timocracies +timocracy +timocratic +timocratical +timolol +timolols +timon +timor +timorese +timorous +timorously +timorousness +timothies +timothy +timpani +timpanist +timpanists +timpanogos +timpanum +timucua +timucuas +tin +tinamou +tinamous +tinbergen +tincal +tincals +tinct +tinctorial +tinctorially +tincts +tincture +tinctured +tinctures +tincturing +tinder +tinderbox +tinderboxes +tine +tinea +tineal +tineas +tined +tines +tinfoil +tinful +tinfuls +ting +tinge +tinged +tingeing +tinges +tinging +tingle +tingled +tingler +tinglers +tingles +tingling +tinglingly +tingly +tings +tinhorn +tinhorns +tinian +tinier +tiniest +tinily +tininess +tinker +tinkered +tinkerer +tinkerers +tinkering +tinkers +tinkertoy +tinkle +tinkled +tinkles +tinkling +tinkly +tinned +tinner +tinners +tinnier +tinniest +tinnily +tinniness +tinning +tinnitus +tinnituses +tinny +tinplate +tinplates +tins +tinsel +tinseled +tinseling +tinselled +tinselling +tinselly +tinsels +tinsmith +tinsmithing +tinsmiths +tinstone +tinstones +tint +tinted +tinter +tinters +tinting +tintinnabula +tintinnabular +tintinnabulary +tintinnabulation +tintinnabulations +tintinnabulous +tintinnabulum +tintless +tintoretto +tints +tintype +tintypes +tinware +tinwork +tinworks +tiny +tip +tipcart +tipcarts +tipcat +tipi +tipis +tippecanoe +tipped +tipper +tippers +tippet +tippets +tippier +tippiest +tipping +tipple +tippled +tippler +tipplers +tipples +tippling +tippy +tips +tipsier +tipsiest +tipsily +tipsiness +tipstaff +tipstaffs +tipstaves +tipster +tipsters +tipsy +tiptoe +tiptoed +tiptoeing +tiptoes +tiptop +tiptops +tirade +tirades +tiramisu +tirana +tiranë +tire +tired +tiredly +tiredness +tireless +tirelessly +tirelessness +tires +tiresias +tiresome +tiresomely +tiresomeness +tiring +tiro +tirol +tiros +tirpitz +tiryns +tis +tisane +tisanes +tishri +tisiphone +tissot +tissue +tissues +tissuey +tissular +tit +titan +titanate +titanates +titaness +titanesses +titania +titanic +titanically +titaniferous +titanism +titanisms +titanite +titanites +titanium +titanosaur +titanosaurs +titanothere +titanotheres +titanous +titans +titbit +titbits +titer +titers +titfer +titfers +tithable +tithe +tithed +tither +tithers +tithes +tithing +tithings +tithonia +tithonias +titi +titian +titianesque +titicaca +titillate +titillated +titillater +titillaters +titillates +titillating +titillatingly +titillation +titillations +titillative +titis +titivate +titivated +titivates +titivating +titivation +titivations +titlark +titlarks +title +titled +titleholder +titleholders +titles +titling +titlist +titlists +titmice +titmouse +tito +titoism +titoist +titoists +titrant +titrants +titratable +titrate +titrated +titrates +titrating +titration +titrations +titrator +titrators +titre +titres +titrimetric +titrimetrically +tits +titter +tittered +titterer +titterers +tittering +titteringly +titters +tittivate +tittivated +tittivates +tittivating +tittle +tittles +tittup +tittuped +tittuping +tittupped +tittupping +tittups +titubation +titubations +titular +titularies +titularly +titulars +titulary +titus +tivoli +tiwa +tiwas +tizzies +tizzy +tko +tlingit +tlingits +tmeses +tmesis +tnt +to +toad +toadeater +toadeaters +toadfish +toadfishes +toadflax +toadflaxes +toadied +toadies +toads +toadstone +toadstones +toadstool +toadstools +toady +toadying +toadyish +toadyism +toast +toasted +toaster +toasters +toastier +toastiest +toasting +toastmaster +toastmasters +toastmistress +toastmistresses +toasts +toasty +tobacco +tobaccoes +tobacconist +tobacconists +tobaccos +tobagan +tobagans +tobago +tobagonian +tobagonians +tobias +tobies +tobit +toboggan +tobogganed +tobogganer +tobogganers +tobogganing +tobogganist +tobogganists +toboggans +tobruk +toby +toccata +toccatas +tocharian +tocharians +tocology +tocopherol +tocopherols +tocqueville +tocsin +tocsins +today +todays +toddies +toddle +toddled +toddler +toddlerhood +toddlers +toddles +toddling +toddy +todies +tody +toe +toea +toecap +toecaps +toed +toehold +toeholds +toeing +toeless +toenail +toenailed +toenailing +toenails +toepiece +toepieces +toeplate +toeplates +toes +toffee +toffees +toffies +toffy +tofu +tog +toga +togaed +togas +together +togetherness +togged +toggenburg +toggeries +toggery +togging +toggle +toggled +toggles +toggling +togo +togolese +togs +togue +togues +toheroa +toheroas +toil +toile +toiled +toiler +toilers +toilet +toiletries +toiletry +toilets +toilette +toilettes +toilful +toilfully +toiling +toils +toilsome +toilsomely +toilsomeness +toilworn +toity +tokamak +tokamaks +tokara +tokay +tokays +toke +toked +tokelau +token +tokened +tokening +tokenism +tokenize +tokenized +tokenizes +tokenizing +tokens +tokes +tokharian +tokharians +toking +tokology +tokomak +tokomaks +tokonoma +tokonomas +tokyo +tola +tolas +tolbutamide +tolbutamides +told +tole +toled +toledo +toledos +tolerability +tolerable +tolerableness +tolerably +tolerance +tolerances +tolerant +tolerantly +tolerate +tolerated +tolerates +tolerating +toleration +tolerative +tolerator +tolerators +toles +tolidine +tolidines +toling +toll +tollbooth +tollbooths +tolled +tollgate +tollgates +tollhouse +tollhouses +tolling +tolls +tollway +tollways +tolstoian +tolstoy +tolstoyan +toltec +toltecan +toltecs +tolu +toluate +toluates +toluene +toluenes +toluic +toluidine +toluidines +toluol +toluols +tolus +tolyl +tolyls +tom +tomahawk +tomahawked +tomahawking +tomahawks +tomalley +tomalleys +tomatillo +tomatillos +tomato +tomatoes +tomatoey +tomb +tombac +tombacs +tombless +tomblike +tombolo +tombolos +tomboy +tomboyish +tomboyishness +tomboys +tombs +tombstone +tombstones +tomcat +tomcats +tomcatted +tomcatting +tomcod +tomcods +tome +tomenta +tomentose +tomentum +tomes +tomfool +tomfooleries +tomfoolery +tomfools +tomism +tommed +tommies +tomming +tommy +tommyrot +tomogram +tomograms +tomograph +tomographic +tomographs +tomography +tomorrow +tomorrows +tompion +tompions +toms +tomsk +tomtit +tomtits +tomé +ton +tonal +tonalities +tonality +tonally +tondi +tondo +tondos +tone +tonearm +tonearms +toned +toneless +tonelessly +tonelessness +toneme +tonemes +tonemic +toner +toners +tones +tonetic +tonetically +tonetics +tonette +tonettes +toney +tong +tonga +tongan +tongans +tonged +tonger +tongers +tonging +tongs +tongue +tongued +tonguefish +tonguefishes +tongueless +tonguelike +tongues +tonguing +tonguings +tonic +tonically +tonicities +tonicity +tonics +tonier +toniest +tonight +tonights +toning +tonk +tonka +tonkin +tonkinese +tonks +tonnage +tonnages +tonne +tonneau +tonneaus +tonner +tonners +tonnes +tonometer +tonometers +tonometric +tonometry +tonoplast +tonoplasts +tons +tonsil +tonsillar +tonsillectomies +tonsillectomy +tonsillitic +tonsillitis +tonsillotomies +tonsillotomy +tonsils +tonsorial +tonsure +tonsured +tonsures +tonsuring +tontine +tontines +tonus +tonuses +tony +tonys +too +tooer +tooers +tooism +took +tool +toolbox +toolboxes +tooled +toolholder +toolholders +toolhouse +toolhouses +tooling +toolings +toolkit +toolkits +toolmaker +toolmakers +toolmaking +toolroom +toolrooms +tools +toolshed +toolsheds +toon +toons +toot +tooted +tooter +tooters +tooth +toothache +toothaches +toothbrush +toothbrushes +toothbrushing +toothed +toothier +toothiest +toothily +toothing +toothless +toothlessly +toothlessness +toothlike +toothpaste +toothpick +toothpicks +toothpowder +toothpowders +tooths +toothsome +toothsomely +toothsomeness +toothwort +toothworts +toothy +tooting +tootle +tootled +tootler +tootlers +tootles +tootling +toots +tootsie +tootsies +tootsy +top +topaz +topazes +topcoat +topcoats +topcross +topcrosses +topdressing +topdressings +tope +topectomies +topectomy +toped +topee +topees +topeka +toper +topers +topes +topflight +topful +topfull +topgallant +topgallants +tophet +tophets +tophi +tophus +topi +topiaries +topiary +topic +topical +topicality +topically +topics +toping +topis +topkick +topkicks +topknot +topknots +topless +toplessness +topline +toplines +toploftical +toploftier +toploftiest +toploftily +toploftiness +toplofty +topmast +topmasts +topminnow +topminnows +topmost +topnotch +topnotcher +topnotchers +topocentric +topograph +topographer +topographers +topographic +topographical +topographically +topographies +topographs +topography +topoi +topologic +topological +topologically +topologies +topologist +topologists +topology +toponym +toponymic +toponymical +toponymies +toponymist +toponymists +toponyms +toponymy +topos +topotype +topotypes +topped +topper +toppers +topping +toppings +topple +toppled +topples +toppling +tops +topsail +topsails +topside +topsider +topsiders +topsides +topsoil +topsoiled +topsoiling +topsoils +topspin +topstitch +topstitched +topstitches +topstitching +topsy +topwork +topworked +topworking +topworks +toque +toques +tor +torah +torahs +torbernite +torbernites +torch +torchbearer +torchbearers +torched +torches +torchier +torchiere +torchieres +torchiers +torchiest +torching +torchlight +torchlights +torchon +torchwood +torchwoods +torchy +torchère +torchères +tore +toreador +toreadors +torero +toreros +toreutic +toreutics +tori +toric +tories +torii +torino +torment +tormented +tormenter +tormenters +tormentil +tormentils +tormenting +tormentingly +tormentor +tormentors +torments +torn +tornadic +tornado +tornadoes +tornados +tornillo +tornillos +toroid +toroidal +toroidally +toroids +toronto +torose +torpedo +torpedoed +torpedoes +torpedoing +torpid +torpidity +torpidly +torpor +torporific +torquate +torque +torqued +torquemada +torquer +torquers +torques +torqueses +torquey +torquing +torr +torrefaction +torrefied +torrefies +torrefy +torrefying +torremolinos +torrens +torrent +torrential +torrentially +torrents +torres +torrid +torrider +torridest +torridity +torridly +torridness +tors +torsade +torsades +torsi +torsion +torsional +torsionally +torso +torsos +tort +torte +tortellini +torten +tortes +torticollar +torticollis +torticollises +tortilla +tortillas +tortious +tortiously +tortoise +tortoises +tortoiseshell +tortoiseshells +tortola +tortoni +tortricid +tortricids +tortrix +torts +tortuga +tortuosities +tortuosity +tortuous +tortuously +tortuousness +torture +tortured +torturer +torturers +tortures +torturing +torturous +torturously +torula +torulae +torulas +torus +tory +toryism +tosca +toscanini +tosh +toss +tossed +tosser +tossers +tosses +tossing +tosspot +tosspots +tossup +tossups +tostada +tostadas +tostado +tostados +tot +totable +total +totaled +totaling +totalism +totalistic +totalitarian +totalitarianism +totalitarianize +totalitarianized +totalitarianizes +totalitarianizing +totalitarians +totalities +totality +totalization +totalizations +totalizator +totalizators +totalize +totalized +totalizer +totalizers +totalizes +totalizing +totalled +totalling +totally +totals +tote +toted +totem +totemic +totemism +totemisms +totemist +totemistic +totemists +totems +toter +toters +totes +tother +toting +totipalmate +totipalmation +totipalmations +totipotence +totipotences +totipotencies +totipotency +totipotent +toto +tots +totted +totter +tottered +totterer +totterers +tottering +totteringly +totters +tottery +totting +touareg +toucan +toucanet +toucanets +toucans +touch +touchable +touchableness +touchback +touchbacks +touchdown +touchdowns +touched +toucher +touchers +touches +touchhole +touchholes +touchier +touchiest +touchily +touchiness +touching +touchingly +touchingness +touchline +touchlines +touchmark +touchmarks +touchstone +touchstones +touchtone +touchup +touchups +touchwood +touchwoods +touchy +touché +tough +toughen +toughened +toughener +tougheners +toughening +toughens +tougher +toughest +toughie +toughies +toughly +toughness +toughs +toughy +toulon +toulouse +toupee +toupees +touquet +tour +touraco +touracos +touraine +tourbillion +tourbillions +tourbillon +tourbillons +toured +tourer +tourers +tourette +tourette's +touring +tourings +tourism +tourist +touristic +touristically +tourists +touristy +tourmaline +tourmalines +tournament +tournaments +tournedos +tourney +tourneyed +tourneying +tourneys +tourniquet +tourniquets +tours +touse +toused +touses +tousing +tousle +tousled +tousles +tousling +toussaint +tout +touted +touter +touters +touting +touts +tovarich +tovariches +tovarish +tovarishes +tow +towable +towage +toward +towardliness +towardly +towards +towboat +towboats +towed +towel +toweled +towelette +towelettes +toweling +towelings +towelled +towelling +towellings +towels +tower +towered +towering +toweringly +towerish +towerlike +towers +towhead +towheaded +towheads +towhee +towhees +towing +towline +towlines +town +townhouse +townhouses +townie +townies +townlet +townlets +towns +townscape +townscapes +townsend +townsfolk +townshend +township +townships +townsman +townsmen +townspeople +townswoman +townswomen +towny +towpath +towpaths +towrope +towropes +tows +toxalbumin +toxalbumins +toxaphene +toxaphenes +toxemia +toxemic +toxic +toxically +toxicant +toxicants +toxicities +toxicity +toxicogenic +toxicologic +toxicological +toxicologically +toxicologist +toxicologists +toxicology +toxicoses +toxicosis +toxics +toxigenic +toxigenicity +toxin +toxins +toxoid +toxoids +toxophilite +toxophilites +toxophily +toxoplasma +toxoplasmas +toxoplasmic +toxoplasmoses +toxoplasmosis +toy +toyed +toyer +toyers +toying +toylike +toynbee +toyon +toyons +toyota +toyotas +toys +toyshop +toyshops +trabeate +trabeated +trabeation +trabeations +trabecula +trabeculae +trabecular +trabeculas +trabeculate +trace +traceability +traceable +traceableness +traceably +traced +traceless +tracer +traceried +traceries +tracers +tracery +traces +trachea +tracheae +tracheal +tracheary +tracheas +tracheate +tracheated +tracheates +tracheid +tracheidal +tracheids +tracheitis +tracheitises +tracheobronchial +tracheoesophageal +tracheolar +tracheole +tracheoles +tracheophyte +tracheophytes +tracheoscopic +tracheoscopies +tracheoscopy +tracheostomies +tracheostomy +tracheotomies +tracheotomy +trachoma +trachomatous +trachyte +trachytic +tracing +tracings +track +trackable +trackage +trackages +trackball +trackballs +tracked +tracker +trackers +tracking +tracklayer +tracklayers +tracklaying +trackless +trackman +trackmen +tracks +trackside +tracksides +tracksuit +tracksuits +trackwalker +trackwalkers +trackway +trackways +tract +tractability +tractable +tractableness +tractably +tractarian +tractarianism +tractarians +tractate +tractates +tractile +tractility +traction +tractional +tractive +tractor +tractors +tracts +tracy +tradable +trade +tradeable +tradecraft +tradecrafts +traded +trademark +trademarked +trademarking +trademarks +tradeoff +tradeoffs +trader +traders +trades +tradescantia +tradescantias +tradesman +tradesmen +tradespeople +trading +tradition +traditional +traditionalism +traditionalist +traditionalistic +traditionalists +traditionalize +traditionalized +traditionalizes +traditionalizing +traditionally +traditionary +traditionless +traditions +traditor +traditores +traduce +traduced +traducement +traducements +traducer +traducers +traduces +traducianism +traducianist +traducianistic +traducianists +traducing +traducingly +trafalgar +traffic +trafficability +trafficable +trafficked +trafficker +traffickers +trafficking +traffics +tragacanth +tragacanths +tragedian +tragedians +tragedienne +tragediennes +tragedies +tragedy +tragi +tragic +tragical +tragically +tragicalness +tragicomedies +tragicomedy +tragicomic +tragicomical +tragicomically +tragopan +tragopans +tragus +trail +trailblazer +trailblazers +trailblazing +trailbreaker +trailbreakers +trailed +trailer +trailerable +trailered +trailering +trailerist +trailerists +trailerite +trailerites +trailers +trailhead +trailheads +trailing +trailless +trails +trailside +trailsides +train +trainability +trainable +trainband +trainbands +trainbearer +trainbearers +trained +trainee +trainees +traineeship +trainer +trainers +trainful +trainfuls +training +trainload +trainloads +trainman +trainmaster +trainmasters +trainmen +trains +traipse +traipsed +traipses +traipsing +trait +traitor +traitoress +traitoresses +traitorous +traitorously +traitorousness +traitors +traitress +traitresses +traits +trajan +traject +trajected +trajecting +trajection +trajections +trajectories +trajectory +trajects +trakehner +trakehners +tram +tramcar +tramcars +tramline +tramlines +trammed +trammel +trammeled +trammeler +trammelers +trammeling +trammelled +trammelling +trammels +tramming +tramontane +tramontanes +tramp +tramped +tramper +trampers +tramping +trampish +trample +trampled +trampler +tramplers +tramples +trampling +trampoline +trampoliner +trampoliners +trampolines +trampolining +trampolinist +trampolinists +tramps +trampy +trams +tramway +tramways +trance +tranced +trancelike +trances +tranche +trancing +tranquil +tranquility +tranquilization +tranquilizations +tranquilize +tranquilized +tranquilizer +tranquilizers +tranquilizes +tranquilizing +tranquillity +tranquillize +tranquillized +tranquillizer +tranquillizers +tranquillizes +tranquillizing +tranquilly +tranquilness +trans +transact +transacted +transacting +transactinide +transaction +transactional +transactions +transactivate +transactivated +transactivates +transactivating +transactivation +transactivations +transactivator +transactivators +transactor +transactors +transacts +transalpine +transaminase +transaminases +transamination +transaminations +transatlantic +transaxle +transaxles +transcaucasia +transcaucasian +transcaucasians +transceiver +transceivers +transcend +transcended +transcendence +transcendency +transcendent +transcendental +transcendentalism +transcendentalist +transcendentalists +transcendentally +transcendently +transcending +transcends +transconductance +transcontinental +transcribable +transcribe +transcribed +transcriber +transcribers +transcribes +transcribing +transcript +transcriptase +transcriptases +transcription +transcriptional +transcriptionally +transcriptionist +transcriptionists +transcriptions +transcripts +transcultural +transculturation +transculturations +transcurrent +transcutaneous +transdermal +transdermals +transdisciplinary +transduce +transduced +transducer +transducers +transduces +transducing +transductant +transductants +transduction +transductional +transductions +transect +transected +transecting +transection +transections +transects +transept +transeptal +transepts +transeunt +transfect +transfected +transfecting +transfection +transfections +transfects +transfer +transferability +transferable +transferal +transferals +transferase +transferases +transferee +transferees +transference +transferential +transferor +transferors +transferrable +transferred +transferrer +transferrers +transferrin +transferring +transferrins +transfers +transfiguration +transfigurations +transfigure +transfigured +transfigurement +transfigures +transfiguring +transfinite +transfix +transfixed +transfixes +transfixing +transfixion +transfixions +transform +transformable +transformation +transformational +transformationalist +transformationalists +transformationally +transformations +transformative +transformed +transformer +transformers +transforming +transforms +transfusable +transfuse +transfused +transfuser +transfusers +transfuses +transfusible +transfusing +transfusion +transfusional +transfusions +transfusive +transgenic +transgress +transgressed +transgresses +transgressible +transgressing +transgression +transgressions +transgressive +transgressively +transgressor +transgressors +tranship +transhipped +transhipping +tranships +transhistorical +transhumance +transhumant +transhumants +transience +transiency +transient +transiently +transients +transilluminate +transilluminated +transilluminates +transilluminating +transillumination +transilluminations +transilluminator +transilluminators +transistor +transistorization +transistorizations +transistorize +transistorized +transistorizes +transistorizing +transistors +transit +transited +transiting +transition +transitional +transitionally +transitionary +transitions +transitive +transitively +transitiveness +transitives +transitivity +transitorily +transitoriness +transitory +transits +transjordan +transjordanian +transjordanians +transkei +transkeian +transkeians +translatability +translatable +translatableness +translate +translated +translates +translating +translation +translational +translations +translative +translator +translatorial +translators +translatory +transliterate +transliterated +transliterates +transliterating +transliteration +transliterations +translocate +translocated +translocates +translocating +translocation +translocations +translucence +translucency +translucent +translucently +translunar +transmarine +transmembrane +transmigrant +transmigrants +transmigrate +transmigrated +transmigrates +transmigrating +transmigration +transmigrationism +transmigrations +transmigrator +transmigrators +transmigratory +transmissibility +transmissible +transmission +transmissions +transmissive +transmissivity +transmissometer +transmissometers +transmissometry +transmit +transmits +transmittable +transmittal +transmittals +transmittance +transmittances +transmitted +transmitter +transmitters +transmitting +transmogrification +transmogrifications +transmogrified +transmogrifies +transmogrify +transmogrifying +transmontane +transmountain +transmundane +transmutability +transmutable +transmutableness +transmutably +transmutation +transmutational +transmutations +transmutative +transmute +transmuted +transmuter +transmuters +transmutes +transmuting +transnational +transnationalism +transnatural +transoceanic +transom +transoms +transonic +transpacific +transparence +transparencies +transparency +transparent +transparentize +transparentized +transparentizes +transparentizing +transparently +transparentness +transpersonal +transpicuous +transpierce +transpierced +transpierces +transpiercing +transpiration +transpirational +transpire +transpired +transpires +transpiring +transplacental +transplacentally +transplant +transplantability +transplantable +transplantation +transplantations +transplanted +transplanter +transplanters +transplanting +transplants +transpolar +transponder +transponders +transpontine +transport +transportability +transportable +transportation +transportational +transported +transporter +transporters +transporting +transportive +transports +transposable +transpose +transposed +transposes +transposing +transposition +transpositional +transpositions +transposon +transposons +transsexual +transsexualism +transsexuality +transsexuals +transshape +transshaped +transshapes +transshaping +transship +transshipment +transshipments +transshipped +transshipping +transships +transsonic +transthoracic +transthoracically +transubstantial +transubstantiate +transubstantiated +transubstantiates +transubstantiating +transubstantiation +transubstantiationalist +transubstantiationalists +transubstantiations +transudate +transudates +transudation +transudations +transudatory +transude +transuded +transudes +transuding +transuranic +transuranium +transurethral +transvaal +transvaluate +transvaluated +transvaluates +transvaluating +transvaluation +transvaluations +transvalue +transvalued +transvalues +transvaluing +transversal +transversally +transversals +transverse +transversely +transverseness +transverses +transvestism +transvestite +transvestites +transvestitism +transylvania +transylvanian +transylvanians +trap +trapdoor +trapdoors +trapeze +trapezes +trapezia +trapeziform +trapezist +trapezists +trapezium +trapeziums +trapezius +trapeziuses +trapezohedra +trapezohedron +trapezohedrons +trapezoid +trapezoidal +trapezoids +traplight +traplights +trapline +traplines +trapped +trapper +trappers +trapping +trappings +trappist +trappists +traprock +traprocks +traps +trapshooter +trapshooters +trapshooting +trapunto +trapuntos +trash +trashed +trashes +trashier +trashiest +trashily +trashiness +trashing +trashman +trashmen +trashy +trass +trasses +trattoria +trattorias +trattorie +trauma +traumas +traumata +traumatic +traumatically +traumatism +traumatisms +traumatization +traumatizations +traumatize +traumatized +traumatizes +traumatizing +traumatological +traumatologist +traumatologists +traumatology +travail +travailed +travailing +travails +trave +travel +traveled +traveler +traveler's +travelers +traveling +travelled +traveller +travellers +travelling +travelog +travelogs +travelogue +travelogues +travels +traversable +traversal +traversals +traverse +traversed +traverser +traversers +traverses +traversing +travertine +travertines +traves +travestied +travesties +travesty +travestying +traviata +travois +travoise +travoises +trawl +trawled +trawler +trawlerman +trawlermen +trawlers +trawling +trawls +tray +trayful +trayfuls +trays +trazodone +trazodones +treacheries +treacherous +treacherously +treacherousness +treachery +treacle +treacly +tread +treaded +treader +treaders +treading +treadle +treadled +treadler +treadlers +treadles +treadless +treadling +treadmill +treadmills +treads +treason +treasonable +treasonableness +treasonably +treasonous +treasonously +treasurable +treasure +treasured +treasurer +treasurers +treasurership +treasures +treasuries +treasuring +treasury +treat +treatability +treatable +treated +treater +treaters +treaties +treating +treatise +treatises +treatment +treatments +treats +treaty +trebizond +treble +trebled +trebleness +trebles +trebling +trebly +trebuchet +trebuchets +trebucket +trebuckets +trecento +tredecillion +tredecillions +tree +treed +treehopper +treehoppers +treeing +treeless +treelike +treen +treenail +treenails +treens +trees +treetop +treetops +tref +trefoil +trefoils +trehala +trehalas +trehalase +trehalases +trehalose +trehaloses +treillage +treillages +trek +trekked +trekker +trekkers +trekking +treks +trellis +trellised +trellises +trellising +trelliswork +trematode +trematodes +trematodiasis +tremble +trembled +trembler +tremblers +trembles +trembling +tremblingly +trembly +tremendous +tremendously +tremendousness +tremens +tremolite +tremolites +tremolitic +tremolo +tremolos +tremor +tremors +tremulant +tremulous +tremulously +tremulousness +trenail +trenails +trench +trenchancy +trenchant +trenchantly +trenched +trencher +trencherman +trenchermen +trenchers +trenches +trenching +trend +trended +trendier +trendies +trendiest +trendily +trendiness +trending +trends +trendsetter +trendsetters +trendsetting +trendy +trentino +trenton +trepan +trepanation +trepanations +trepang +trepangs +trepanned +trepanning +trepans +trephination +trephinations +trephine +trephined +trephines +trephining +trepid +trepidant +trepidation +treponema +treponemal +treponemas +treponemata +treponematoses +treponematosis +treponematous +treponeme +treponemes +trespass +trespassed +trespasser +trespassers +trespasses +trespassing +tress +tressed +tressel +tressels +tresses +trestle +trestles +trestletree +trestletrees +trestlework +tretinoin +tretinoins +trevallies +trevally +trevelyan +trevithick +trews +trey +treys +triable +triableness +triacetate +triacetates +triacid +triacids +triad +triadelphous +triadic +triadically +triads +triage +triages +trial +trialogue +trialogues +trials +triamcinolone +triamcinolones +triandrous +triangle +triangles +triangular +triangularity +triangularly +triangulate +triangulated +triangulates +triangulating +triangulation +triangulations +triangulum +triarchies +triarchy +triassic +triathlete +triathletes +triathlon +triathlons +triatomic +triaxial +triaxiality +triazine +triazines +triazole +triazoles +tribade +tribades +tribadism +tribal +tribalism +tribalisms +tribalist +tribalistic +tribalists +tribally +tribasic +tribe +tribes +tribesman +tribesmen +tribespeople +tribeswoman +tribeswomen +triboelectric +triboelectricities +triboelectricity +tribological +tribologist +tribologists +tribology +triboluminescence +triboluminescent +tribrach +tribrachic +tribrachs +tribromoethanol +tribromoethanols +tribulate +tribulated +tribulates +tribulating +tribulation +tribulations +tribunal +tribunals +tribunary +tribunate +tribunates +tribune +tribunes +tribuneship +tributaries +tributary +tribute +tributes +tricameral +tricarboxylic +trice +triced +tricentennial +tricentennials +triceps +tricepses +triceratops +triceratopses +trices +trichiasis +trichina +trichinae +trichinal +trichinas +trichinization +trichinizations +trichinize +trichinized +trichinizes +trichinizing +trichinoses +trichinosis +trichinous +trichite +trichites +trichitic +trichlorethylene +trichlorethylenes +trichlorfon +trichlorfons +trichlorid +trichloride +trichlorides +trichlorids +trichloroacetic +trichloroethane +trichloroethylene +trichloroethylenes +trichlorphon +trichlorphons +trichocyst +trichocystic +trichocysts +trichogyne +trichogynes +trichoid +trichologist +trichologists +trichology +trichome +trichomes +trichomic +trichomonacidal +trichomonacide +trichomonacides +trichomonad +trichomonadal +trichomonads +trichomonal +trichomoniases +trichomoniasis +trichopteran +trichopterans +trichoses +trichosis +trichothecene +trichothecenes +trichotomic +trichotomies +trichotomous +trichotomously +trichotomy +trichroic +trichroism +trichroisms +trichromat +trichromatic +trichromatism +trichromats +trichrome +trichromic +trichuriases +trichuriasis +tricing +trick +tricked +tricker +trickeries +trickers +trickery +trickier +trickiest +trickily +trickiness +tricking +trickish +trickishly +trickishness +trickle +trickled +trickles +trickling +tricks +tricksier +tricksiest +tricksiness +trickster +tricksters +tricksy +tricky +triclad +triclads +triclinia +triclinic +triclinium +tricolette +tricolettes +tricolor +tricolored +tricolors +tricorn +tricorne +tricornered +tricornes +tricorns +tricostate +tricot +tricotine +tricotines +tricots +tricrotic +tricrotism +trictrac +tricuspid +tricuspidal +tricuspidate +tricuspids +tricycle +tricycles +tricyclic +tricyclics +tridactyl +tridactylous +trident +tridentate +tridentine +tridentines +tridents +tridimensional +tridimensionality +triduum +tried +triene +trienes +triennia +triennial +triennially +triennials +triennium +trienniums +trier +trierarch +trierarchies +trierarchs +trierarchy +triers +tries +trieste +triethiodide +triethyl +trifacial +trifecta +trifectas +trifid +trifle +trifled +trifler +triflers +trifles +trifling +triflingly +trifluoperazine +trifluoperazines +trifluralin +trifluralins +trifocal +trifocals +trifoliate +trifoliated +trifoliolate +trifolium +triforia +triforium +triform +triformed +trifurcate +trifurcated +trifurcates +trifurcating +trifurcation +trifurcations +trig +trigamous +trigeminal +trigemini +trigeminus +trigged +trigger +triggered +triggerfish +triggerfishes +triggering +triggerman +triggermen +triggers +trigging +trigly +triglyceride +triglycerides +triglyph +triglyphic +triglyphical +triglyphs +trigness +trigon +trigonal +trigonally +trigonometric +trigonometrical +trigonometrically +trigonometry +trigons +trigram +trigrammatic +trigrammatically +trigrams +trigraph +trigraphic +trigraphically +trigraphs +trigs +trigynous +trihalomethane +trihalomethanes +trihedra +trihedral +trihedrals +trihedron +trihedrons +trihybrid +trihybrids +trihydric +trihydroxy +triiodothyronine +triiodothyronines +trijet +trijets +trike +trikes +trilabiate +trilateral +trilateralism +trilateralisms +trilateralist +trilateralists +trilaterally +trilbies +trilby +trilinear +trilingual +trilingualism +trilingually +trilinguals +triliteral +triliteralism +triliterals +trilith +trilithic +trilithon +trilithons +triliths +trill +trilled +triller +trillers +trilling +trillion +trillions +trillionth +trillionths +trillium +trilliums +trills +trilobate +trilobated +trilobed +trilobite +trilobites +trilobitic +trilocular +trilogies +trilogy +trim +trimaran +trimarans +trimer +trimeric +trimerism +trimerous +trimers +trimester +trimesters +trimestral +trimestrial +trimeter +trimeters +trimethadione +trimethadiones +trimethoprim +trimethoprims +trimetric +trimetrical +trimetrogon +trimetrogons +trimly +trimmed +trimmer +trimmers +trimmest +trimming +trimmings +trimness +trimolecular +trimonthly +trimorph +trimorphic +trimorphically +trimorphism +trimorphous +trimorphs +trimotor +trimotors +trims +trimurti +trinal +trinary +trincomalee +trine +trines +trinidad +trinidadian +trinidadians +trinitarian +trinitarianism +trinitarians +trinities +trinitrobenzene +trinitrobenzenes +trinitrocresol +trinitrocresols +trinitrophenol +trinitrophenols +trinitrotoluene +trinitrotoluenes +trinitrotoluol +trinitrotoluols +trinity +trinitytide +trinket +trinketer +trinketers +trinketry +trinkets +trinocular +trinomial +trinomialism +trinomials +trinucleotide +trinucleotides +trio +triode +triodes +triol +triolet +triolets +triols +trios +triose +trioses +trioxid +trioxide +trioxides +trioxids +trip +tripack +tripacks +tripalmitin +tripalmitins +tripartite +tripartitely +tripartition +tripartitions +tripe +tripedal +tripeptide +tripeptides +tripetalous +triphammer +triphammers +triphenylmethane +triphenylmethanes +triphibian +triphibians +triphibious +triphosphatase +triphosphate +triphosphates +triphosphopyridine +triphthong +triphthongal +triphthongs +tripinnate +tripinnately +triplane +triplanes +triple +tripled +tripleheader +tripleheaders +triples +triplet +tripletail +tripletails +triplets +triplex +triplexes +triplicate +triplicated +triplicately +triplicates +triplicating +triplication +triplications +triplicities +triplicity +tripling +triploblastic +triploid +triploids +triploidy +triply +tripod +tripodal +tripods +tripoli +tripolis +tripolitan +tripolitania +tripolitanian +tripolitanians +tripolitans +tripolyphosphate +tripos +triposes +tripped +tripper +trippers +trippet +trippets +tripping +trippingly +trippy +trips +triptane +triptanes +triptych +triptychs +tripura +tripwire +tripwires +triquetra +triquetral +triquetrous +triquetrum +triradiate +trireme +triremes +trisaccharide +trisaccharides +trisagion +trisect +trisected +trisecting +trisection +trisections +trisector +trisectors +trisects +trisepalous +trishaw +trishaws +triskaidekaphobia +triskaidekaphobias +triskele +triskeles +triskelia +triskelion +trismic +trismus +trisoctahedra +trisoctahedral +trisoctahedron +trisoctahedrons +trisodium +trisome +trisomes +trisomic +trisomies +trisomy +tristan +tristate +triste +tristearin +tristearins +tristeza +tristful +tristfully +tristfulness +tristich +tristichs +tristimulus +tristram +trisubstituted +trisulfide +trisulfides +trisyllabic +trisyllabical +trisyllabically +trisyllable +trisyllables +tritanopia +tritanopias +trite +tritely +triteness +triter +tritest +tritheism +tritheist +tritheistic +tritheistical +tritheists +tritiate +tritiated +tritiates +tritiating +tritiation +triticale +triticales +tritium +tritoma +tritomas +triton +tritone +tritones +tritons +triturable +triturate +triturated +triturates +triturating +trituration +triturations +triturator +triturators +triumph +triumphal +triumphalism +triumphalisms +triumphalist +triumphalists +triumphant +triumphantly +triumphed +triumphing +triumphs +triumvir +triumviral +triumvirate +triumvirates +triumviri +triumvirs +triune +triunes +triunities +triunity +trivalence +trivalency +trivalent +trivalve +trivet +trivets +trivia +trivial +trivialist +trivialists +trivialities +triviality +trivialization +trivializations +trivialize +trivialized +trivializes +trivializing +trivially +trivialness +trivium +triweeklies +triweekly +trobriand +trocar +trocars +trochaic +trochaics +trochal +trochanter +trochanteral +trochanteric +trochanters +trochar +trochars +troche +trochee +trochees +troches +trochlea +trochleae +trochlear +trochoid +trochoidal +trochoidally +trochoids +trochophore +trochophores +trod +trodden +troffer +troffers +troglodyte +troglodytes +troglodytic +troglodytical +trogon +trogons +troika +troikas +troilite +troilites +troilus +trois +trojan +trojans +troll +trolled +troller +trollers +trolley +trolleybus +trolleybuses +trolleyed +trolleying +trolleys +trollied +trollies +trolling +trollop +trollope +trollops +trolls +trolly +trollying +trombe +trombiculiasis +trombiculoses +trombiculosis +trombone +trombones +trombonist +trombonists +trommel +trommels +tromp +trompe +tromped +trompes +tromping +tromps +tromsö +trona +tronas +trondheim +troop +trooped +trooper +troopers +trooping +troops +troopship +troopships +troostite +troostites +trop +trope +tropes +tropez +trophallaxes +trophallaxis +trophic +trophically +trophies +trophoblast +trophoblastic +trophoblasts +trophoderm +trophoderms +trophozoite +trophozoites +trophy +tropic +tropical +tropicalize +tropicalized +tropicalizes +tropicalizing +tropically +tropicals +tropicbird +tropicbirds +tropics +tropin +tropine +tropines +tropins +tropism +tropistic +tropistically +tropocollagen +tropocollagens +tropologic +tropological +tropologically +tropologies +tropology +tropomyosin +tropomyosins +troponin +troponins +tropopause +tropopauses +tropophyte +tropophytes +tropophytic +troposphere +tropospheric +tropotactic +tropotactically +tropotaxis +tropotaxises +troppo +trot +troth +trothed +trothing +trothplight +trothplighted +trothplighting +trothplights +troths +trotline +trotlines +trots +trotsky +trotskyism +trotskyist +trotskyists +trotskyite +trotskyites +trotted +trotter +trotters +trotting +troubadour +troubadours +trouble +troubled +troublemaker +troublemakers +troublemaking +troubler +troublers +troubles +troubleshoot +troubleshooter +troubleshooters +troubleshooting +troubleshoots +troubleshot +troublesome +troublesomely +troublesomeness +troubling +troublingly +troublous +troublously +troublousness +trough +troughs +trounce +trounced +trounces +trouncing +troupe +trouped +trouper +troupers +troupes +troupial +troupials +trouping +trouser +trousers +trousseau +trousseaus +trousseaux +trout +troutier +troutiest +troutperch +troutperches +trouts +trouty +trouvere +trouveres +trouveur +trouveurs +trouville +trouvère +trouvères +trove +trover +trovers +troves +trow +trowed +trowel +troweled +troweler +trowelers +troweling +trowelled +troweller +trowellers +trowelling +trowels +trowing +trows +trowser +trowsers +troy +troôdos +truancies +truancy +truant +truanted +truanting +truantries +truantry +truants +truce +trucebreaker +trucebreakers +truced +truces +trucing +truck +truckage +trucked +trucker +truckers +truckful +truckfuls +trucking +truckle +truckled +truckler +trucklers +truckles +truckline +trucklines +truckling +truckload +truckloads +truckman +truckmaster +truckmasters +truckmen +trucks +truculence +truculences +truculencies +truculency +truculent +truculently +trudge +trudged +trudgen +trudgens +trudgeon +trudgeons +trudger +trudgers +trudges +trudging +true +trueborn +trued +truehearted +trueheartedness +trueing +truelove +trueloves +trueness +truepennies +truepenny +truer +trues +truest +truffle +truffled +truffles +truing +truism +truisms +truistic +truk +trull +trulls +truly +trump +trumped +trumperies +trumpery +trumpet +trumpeted +trumpeter +trumpeters +trumpeting +trumpetlike +trumpets +trumping +trumps +truncate +truncated +truncately +truncates +truncating +truncation +truncations +truncheon +truncheoned +truncheoning +truncheons +trundle +trundled +trundler +trundlers +trundles +trundling +trunk +trunked +trunkfish +trunkfishes +trunkful +trunkfuls +trunks +trunnel +trunnels +trunnion +trunnions +truss +trussed +trusser +trussers +trusses +trussing +trust +trustability +trustable +trustbuster +trustbusters +trustbusting +trustbustings +trusted +trustee +trusteed +trusteeing +trustees +trusteeship +trusteeships +truster +trusters +trustful +trustfully +trustfulness +trustier +trusties +trustiest +trustily +trustiness +trusting +trustingly +trustingness +trustless +trusts +trustworthier +trustworthiest +trustworthily +trustworthiness +trustworthy +trusty +truth +truthful +truthfully +truthfulness +truths +try +trying +tryingly +tryout +tryouts +trypanosomal +trypanosome +trypanosomes +trypanosomiases +trypanosomiasis +trypanosomic +tryparsamide +tryparsamides +trypsin +trypsinogen +trypsinogens +trypsins +tryptamine +tryptamines +tryptic +tryptophan +tryptophane +tryptophanes +tryptophans +trysail +trysails +tryst +trysted +tryster +trysters +trysting +trysts +tryworks +tsade +tsades +tsar +tsars +tsarskoye +tsatske +tsatskes +tsetse +tshiluba +tsimmes +tsimmeses +tsimshian +tsimshians +tsinghai +tsk +tsked +tsking +tsks +tsunami +tsunamic +tsunamis +tsuris +tsurises +tsushima +tsutsugamushi +tswana +tswanas +tu +tuamotu +tuan +tuareg +tuaregs +tuatara +tuataras +tub +tuba +tubaist +tubaists +tubal +tubas +tubate +tubbable +tubbed +tubber +tubbers +tubbier +tubbiest +tubbiness +tubbing +tubby +tube +tubectomies +tubectomy +tubed +tubeless +tubelike +tubenose +tubenoses +tuber +tubercle +tubercles +tubercular +tuberculars +tuberculate +tuberculated +tuberculately +tuberculation +tuberculations +tuberculin +tuberculins +tuberculoid +tuberculoses +tuberculosis +tuberculous +tuberculously +tuberose +tuberoses +tuberosities +tuberosity +tuberous +tubers +tuberworm +tuberworms +tubes +tubeworm +tubeworms +tubful +tubfuls +tubicolous +tubifex +tubifexes +tubificid +tubificids +tubing +tubist +tubists +tublike +tubocurarine +tubocurarines +tuboplasties +tuboplasty +tubs +tubuai +tubular +tubularity +tubularly +tubulate +tubulated +tubulation +tubulations +tubulator +tubulators +tubule +tubules +tubuliferous +tubuliflorous +tubulin +tubulins +tubulous +tubulously +tucana +tuchun +tuchuns +tuck +tuckahoe +tuckahoes +tucked +tucker +tuckered +tuckering +tuckers +tucket +tuckets +tucking +tucks +tuckshop +tuckshops +tucson +tudor +tudors +tuesday +tuesdays +tufa +tufaceous +tufas +tuff +tuffaceous +tuffet +tuffets +tuffs +tuft +tufted +tufter +tufters +tufting +tufts +tufty +tug +tugboat +tugboats +tugged +tugger +tuggers +tugging +tughrik +tughriks +tugrik +tugriks +tugs +tui +tuille +tuilles +tuis +tuition +tuitional +tuitionary +tularemia +tularemic +tule +tules +tulip +tulips +tulipwood +tulipwoods +tulle +tulles +tullibee +tullibees +tulsa +tumble +tumblebug +tumblebugs +tumbled +tumbledown +tumblehome +tumblehomes +tumbler +tumblerful +tumblerfuls +tumblers +tumbles +tumbleset +tumblesets +tumbleweed +tumbleweeds +tumbling +tumblings +tumbrel +tumbrels +tumbril +tumbrils +tumefacient +tumefaction +tumefactions +tumefactive +tumefied +tumefies +tumefy +tumefying +tumescence +tumescences +tumescent +tumid +tumidity +tumidly +tumidness +tummies +tummler +tummlers +tummy +tumor +tumoral +tumorigeneses +tumorigenesis +tumorigenic +tumorigenicity +tumorlike +tumorous +tumors +tump +tumpline +tumplines +tumps +tumular +tumuli +tumulose +tumulosity +tumulous +tumult +tumults +tumultuary +tumultuous +tumultuously +tumultuousness +tumulus +tun +tuna +tunability +tunable +tunableness +tunably +tunas +tundish +tundishes +tundra +tundras +tune +tuneable +tuned +tuneful +tunefully +tunefulness +tuneless +tunelessly +tunelessness +tuner +tuners +tunes +tunesmith +tunesmiths +tung +tungstate +tungstates +tungsten +tungstenic +tungstic +tungstite +tungstites +tungus +tunguses +tungusic +tunic +tunica +tunicae +tunicate +tunicated +tunicates +tunicle +tunicles +tunics +tuning +tunings +tunis +tunisia +tunisian +tunisians +tunnel +tunneled +tunneler +tunnelers +tunneling +tunnelled +tunneller +tunnellers +tunnellike +tunnelling +tunnels +tunnies +tunny +tuns +tup +tupelo +tupelos +tupi +tupian +tupians +tupis +tupped +tuppence +tupperware +tupping +tups +tuque +tuques +turaco +turacos +turanian +turanians +turban +turbaned +turbanned +turbans +turbaries +turbary +turbellarian +turbellarians +turbid +turbidimeter +turbidimeters +turbidimetric +turbidimetrically +turbidimetry +turbidite +turbidites +turbidities +turbidity +turbidly +turbidness +turbinal +turbinals +turbinate +turbinated +turbination +turbinations +turbine +turbines +turbit +turbits +turbo +turbocar +turbocars +turbocharged +turbocharger +turbochargers +turboelectric +turbofan +turbofans +turbogenerator +turbogenerators +turbojet +turbojets +turbomachinery +turboprop +turboprops +turboramjet +turboramjets +turbos +turboshaft +turboshafts +turbosupercharger +turbosuperchargers +turbot +turbots +turbulence +turbulencies +turbulency +turbulent +turbulently +turcoman +turcomans +turd +turds +tureen +tureens +turf +turfed +turfing +turfman +turfmen +turfs +turfski +turfskiing +turfskis +turfy +turgenev +turgescence +turgescent +turgid +turgidity +turgidly +turgidness +turgor +turin +turing +turion +turions +turista +turk +turkana +turkestan +turkey +turkeys +turki +turkic +turkics +turkis +turkish +turkism +turkistan +turkmen +turkmenistan +turkmens +turkoman +turkomans +turks +turmaline +turmalines +turmeric +turmoil +turn +turnable +turnabout +turnabouts +turnaround +turnarounds +turnbuckle +turnbuckles +turncoat +turncoats +turndown +turndowns +turned +turner +turneries +turners +turnery +turning +turnings +turnip +turnips +turnkey +turnkeys +turnoff +turnoffs +turnout +turnouts +turnover +turnovers +turnpike +turnpikes +turns +turnsole +turnsoles +turnspit +turnspits +turnstile +turnstiles +turnstone +turnstones +turntable +turntables +turnup +turnups +turnverein +turnvereins +turophile +turophiles +turpentine +turpentined +turpentines +turpentinic +turpentining +turpentinous +turpin +turpitude +turps +turquois +turquoise +turquoises +turret +turreted +turrets +turtle +turtleback +turtlebacked +turtlebacks +turtled +turtledove +turtledoves +turtlehead +turtleheads +turtleneck +turtlenecked +turtlenecks +turtler +turtlers +turtles +turtling +turves +turvier +turvies +turviest +turvily +turviness +turvy +turvydom +tuscan +tuscans +tuscany +tuscarora +tuscaroras +tusche +tusches +tush +tushes +tushie +tushies +tushy +tusk +tusked +tusker +tuskers +tusking +tusklike +tusks +tussah +tussahs +tussal +tussaud +tusser +tusses +tussie +tussis +tussive +tussle +tussled +tussles +tussling +tussock +tussocks +tussocky +tussore +tussores +tut +tutankhamen +tutankhaten +tutee +tutees +tutelage +tutelar +tutelaries +tutelars +tutelary +tutor +tutorage +tutorages +tutored +tutoress +tutoresses +tutorial +tutorials +tutoring +tutors +tutorship +tutorships +tutoyer +tutoyered +tutoyering +tutoyers +tuts +tutsi +tutsis +tutted +tutti +tutting +tuttis +tutty +tutu +tutuila +tutus +tuvalu +tuvaluan +tuvaluans +tux +tuxedo +tuxedoed +tuxedoes +tuxedos +tuxes +tuyere +tuyeres +tuyère +tuyères +tuzzy +twaddle +twaddled +twaddler +twaddlers +twaddles +twaddling +twain +twains +twang +twanged +twanger +twangers +twanging +twangs +twangy +twas +twat +twats +twayblade +twayblades +tweak +tweaked +tweaking +tweaks +tweaky +twee +tweed +tweeddale +tweedier +tweediest +tweediness +tweedledee +tweedledum +tweeds +tweedy +tween +tweet +tweeted +tweeter +tweeters +tweeting +tweets +tweeze +tweezed +tweezer +tweezers +tweezes +tweezing +twelfth +twelfths +twelve +twelvefold +twelvemo +twelvemonth +twelvemonths +twelvemos +twelvepenny +twelves +twenties +twentieth +twentieths +twenty +twentyfold +twere +twerp +twerps +twi +twibill +twibills +twice +twiddle +twiddled +twiddler +twiddlers +twiddles +twiddling +twig +twigged +twiggier +twiggiest +twigging +twiggy +twigs +twilight +twilit +twill +twilled +twilling +twills +twin +twinberries +twinberry +twinborn +twine +twined +twiner +twiners +twines +twinflower +twinflowers +twinge +twinged +twingeing +twinges +twinging +twinight +twining +twinjet +twinjets +twinkle +twinkled +twinkler +twinklers +twinkles +twinkling +twinkly +twinleaf +twinleaves +twinned +twinning +twinnings +twins +twinset +twinsets +twinship +twiny +twirl +twirled +twirler +twirlers +twirling +twirls +twirly +twirp +twirps +twist +twistability +twistable +twisted +twister +twisters +twisting +twistingly +twists +twisty +twit +twitch +twitched +twitcher +twitchers +twitches +twitchier +twitchiest +twitchily +twitchiness +twitching +twitchingly +twitchy +twite +twites +twits +twitted +twitter +twittered +twitterer +twitterers +twittering +twitters +twittery +twitting +twixt +two +twofaced +twofer +twofers +twofold +twomo +twomos +twopence +twopences +twopenny +twos +twosome +twosomes +tyburn +tycho +tycoon +tycoons +tyer +tyers +tying +tyke +tykes +tylectomies +tylectomy +tylenol +tylose +tyloses +tylosin +tylosins +tylosis +tymbal +tymbals +tympan +tympana +tympanal +tympani +tympanic +tympanies +tympanist +tympanists +tympanites +tympanitic +tympanitis +tympanitises +tympanoplasties +tympanoplasty +tympans +tympanum +tympanums +tympany +tyndale +tyndareus +tyne +tynes +typal +type +typeable +typecast +typecasting +typecasts +typed +typeface +typefaces +typefounder +typefounders +typefounding +types +typescript +typescripts +typeset +typesets +typesetter +typesetters +typesetting +typestyle +typestyles +typewrite +typewriter +typewriters +typewrites +typewriting +typewritings +typewritten +typewrote +typey +typhlitic +typhlitis +typhlology +typhlosole +typhlosoles +typhoean +typhoeus +typhogenic +typhoid +typhoidal +typhoidin +typhoidins +typhon +typhoon +typhoons +typhous +typhus +typic +typical +typicality +typically +typicalness +typier +typiest +typification +typifications +typified +typifier +typifiers +typifies +typify +typifying +typing +typist +typists +typo +typograph +typographed +typographer +typographers +typographic +typographical +typographically +typographies +typographing +typographs +typography +typologic +typological +typologically +typologies +typologist +typologists +typology +typos +typy +tyramine +tyramines +tyrannic +tyrannical +tyrannically +tyrannicalness +tyrannicide +tyrannicides +tyrannies +tyrannize +tyrannized +tyrannizer +tyrannizers +tyrannizes +tyrannizing +tyrannizingly +tyrannosaur +tyrannosaurs +tyrannosaurus +tyrannosauruses +tyrannous +tyrannously +tyranny +tyrant +tyrants +tyrian +tyrians +tyro +tyrocidin +tyrocidine +tyrocidines +tyrocidins +tyrol +tyrolean +tyroleans +tyrolese +tyrolian +tyrollean +tyrone +tyros +tyrosinase +tyrosinases +tyrosine +tyrosines +tyrothricin +tyrothricins +tyrrhenian +tzaddik +tzaddikim +tzar +tzars +tzetze +tzigane +tziganes +tzimmes +tzimmeses +tzitzis +tzitzit +tzuris +tzurises +tène +tête +têtes +tínos +tórshavn +tôle +tôles +u +ubangi +ubiety +ubiquinone +ubiquinones +ubiquitous +ubiquitously +ubiquitousness +ubiquity +uccello +udall +udder +udders +udine +udo +udometer +udometers +udos +udzungwa +uffizi +ufo +ufological +ufologist +ufologists +ufology +ufos +uganda +ugandan +ugandans +ugaritic +ugh +ugli +uglier +uglies +ugliest +uglification +uglifications +uglified +uglifier +uglifiers +uglifies +uglify +uglifying +uglily +ugliness +ugly +ugrian +ugrians +ugric +ugsome +ugsomeness +uh +uhf +uhlan +uhlans +uighur +uighurs +uigur +uigurian +uiguric +uigurs +uilleann +uintahite +uintahites +uintaite +uintaites +uitlander +uitlanders +uk +ukase +ukases +uke +ukelele +ukeleles +ukes +ukraine +ukrainian +ukrainians +ukulele +ukuleles +ulama +ulamas +ulan +ulans +ulcer +ulcerate +ulcerated +ulcerates +ulcerating +ulceration +ulcerations +ulcerative +ulcerogenic +ulcerous +ulcerously +ulcerousness +ulcers +ulema +ulexite +ulexites +ullage +ullages +ulna +ulnae +ulnar +ulnas +ulster +ulsters +ulterior +ulteriorly +ultima +ultimacies +ultimacy +ultimas +ultimata +ultimate +ultimately +ultimateness +ultimatum +ultimatums +ultimo +ultimogeniture +ultra +ultrabasic +ultracareful +ultracasual +ultracautious +ultracentrifugal +ultracentrifugally +ultracentrifugation +ultracentrifugations +ultracentrifuge +ultracentrifuges +ultrachic +ultracivilized +ultraclean +ultracold +ultracommercial +ultracompact +ultracompetent +ultraconservatism +ultraconservative +ultraconservatives +ultracontemporary +ultraconvenient +ultracool +ultracritical +ultrademocratic +ultradense +ultradian +ultradistance +ultradistant +ultradry +ultraefficient +ultraenergetic +ultraexclusive +ultrafamiliar +ultrafashionable +ultrafast +ultrafastidious +ultrafeminine +ultrafiche +ultrafiches +ultrafiltrate +ultrafiltrating +ultrafiltration +ultrafiltrations +ultrafine +ultraglamorous +ultrahazardous +ultraheat +ultraheavy +ultrahigh +ultrahip +ultrahot +ultrahuman +ultraism +ultraist +ultraistic +ultraists +ultraleft +ultraleftism +ultraleftist +ultraleftists +ultraliberal +ultraliberalism +ultraliberals +ultralight +ultralights +ultralightweight +ultralow +ultramafic +ultramarathon +ultramarathoner +ultramarathoners +ultramarathons +ultramarine +ultramarines +ultramasculine +ultramicro +ultramicrofiche +ultramicrofiches +ultramicrometer +ultramicrometers +ultramicroscope +ultramicroscopes +ultramicroscopic +ultramicroscopical +ultramicroscopically +ultramicroscopy +ultramicrotome +ultramicrotomes +ultramicrotomy +ultramilitant +ultramilitants +ultraminiature +ultraminiaturization +ultraminiaturizations +ultraminiaturize +ultraminiaturized +ultraminiaturizes +ultraminiaturizing +ultramodern +ultramodernism +ultramodernist +ultramodernistic +ultramodernists +ultramontane +ultramontanes +ultramontanism +ultramontanist +ultramontanists +ultramundane +ultranational +ultranationalism +ultranationalist +ultranationalistic +ultranationalists +ultraorthodox +ultraparadoxical +ultrapatriotic +ultraphysical +ultrapowerful +ultrapractical +ultraprecise +ultraprecision +ultraprofessional +ultraprogressive +ultrapure +ultraquiet +ultraradical +ultrarapid +ultrarare +ultrararefied +ultrarational +ultrarealism +ultrarealist +ultrarealistic +ultrarealists +ultrarefined +ultrareliable +ultrarespectable +ultrarevolutionary +ultrarich +ultraright +ultrarightist +ultrarightists +ultraromantic +ultraroyalist +ultraroyalists +ultras +ultrasafe +ultrasecret +ultrasegregationist +ultrasegregationists +ultrasensitive +ultraserious +ultrasharp +ultrashort +ultrasimple +ultraslick +ultraslow +ultrasmall +ultrasmart +ultrasmooth +ultrasoft +ultrasonic +ultrasonically +ultrasonics +ultrasonogram +ultrasonograms +ultrasonograph +ultrasonographer +ultrasonographers +ultrasonographic +ultrasonographs +ultrasonography +ultrasophisticated +ultrasound +ultrasounds +ultrastructural +ultrastructurally +ultrastructure +ultrastructures +ultrathin +ultravacuum +ultraviolence +ultraviolent +ultraviolet +ultraviolets +ultravirile +ultravirility +ultravirus +ultraviruses +ultrawide +ululant +ululate +ululated +ululates +ululating +ululation +ululations +ulva +ulysses +um +umatilla +umatillas +umbel +umbellate +umbellated +umbellately +umbellet +umbellets +umbellifer +umbelliferous +umbellifers +umbellule +umbellules +umbels +umber +umbered +umbering +umbers +umbilical +umbilically +umbilicals +umbilicate +umbilicated +umbilication +umbilications +umbilici +umbilicus +umbilicuses +umbles +umbo +umbonal +umbonate +umbones +umbonic +umbos +umbra +umbrae +umbrage +umbrageous +umbrageously +umbrageousness +umbral +umbras +umbrella +umbrellaless +umbrellas +umbrette +umbrettes +umbria +umbrian +umbrians +umbriel +umbundu +umiak +umiaks +umlaut +umlauted +umlauting +umlauts +umm +umnak +ump +umped +umping +umpirage +umpirages +umpire +umpired +umpires +umpiring +umps +umpteen +umpteenth +umtata +un +una +unabashed +unabashedly +unabated +unabatedly +unabbreviated +unable +unabraded +unabridged +unabsorbed +unabsorbent +unacademic +unacademically +unaccented +unacceptability +unacceptable +unacceptably +unaccepted +unacclimated +unacclimatized +unaccommodated +unaccommodating +unaccompanied +unaccomplished +unaccountability +unaccountable +unaccountableness +unaccountably +unaccounted +unaccredited +unacculturated +unaccustomed +unaccustomedly +unaccustomedness +unachievable +unachieved +unacknowledged +unacquainted +unacquaintedness +unactable +unacted +unactorish +unadaptable +unadapted +unaddressed +unadjudicated +unadjusted +unadmired +unadmitted +unadoptable +unadorned +unadult +unadulterated +unadulteratedly +unadventurous +unadvertised +unadvised +unadvisedly +unadvisedness +unaesthetic +unaffected +unaffectedly +unaffectedness +unaffecting +unaffectionate +unaffectionately +unaffiliated +unaffluent +unaffordability +unaffordable +unaffordably +unafraid +unageing +unaggressive +unaging +unai +unaided +unais +unakin +unakite +unakites +unalarmed +unalaska +unalienable +unalienated +unaligned +unalike +unalleviated +unallied +unallocated +unallowable +unalloyed +unalloyedly +unalluring +unalterability +unalterable +unalterableness +unalterably +unaltered +unambiguous +unambiguously +unambitious +unambivalent +unambivalently +unamenable +unamended +unami +unamiable +unamis +unamortized +unamplified +unamusing +unanalyzable +unanalyzably +unanalyzed +unanchored +unaneled +unanesthetized +unanimated +unanimity +unanimous +unanimously +unanimousness +unannotated +unannounced +unanswerability +unanswerable +unanswerableness +unanswerably +unanswered +unanticipated +unanticipatedly +unapologetic +unapologetically +unapologizing +unapparent +unappealable +unappealably +unappealing +unappealingly +unappeasable +unappeasably +unappeased +unappetizing +unappetizingly +unapplied +unappreciable +unappreciated +unappreciation +unappreciative +unappreciatively +unapprised +unapproachability +unapproachable +unapproachableness +unapproachably +unappropriated +unapproved +unapt +unaptly +unaptness +unarguable +unarguably +unarm +unarmed +unarming +unarmored +unarms +unarrogant +unarticulated +unartistic +unary +unascertainable +unascertained +unashamed +unashamedly +unashamedness +unasked +unaspirated +unassailability +unassailable +unassailableness +unassailably +unassailed +unassembled +unasserted +unassertive +unassertively +unassertiveness +unassigned +unassimilable +unassimilated +unassisted +unassociated +unassuageable +unassuaged +unassuming +unassumingly +unassumingness +unathletic +unattached +unattainability +unattainable +unattainableness +unattainably +unattained +unattended +unattenuated +unattested +unattractive +unattractively +unattractiveness +unattributable +unattributed +unattuned +unau +unaudited +unaus +unauthentic +unauthenticated +unauthorized +unautomated +unavailability +unavailable +unavailing +unavailingly +unavailingness +unaverage +unavoidability +unavoidable +unavoidableness +unavoidably +unavowed +unawake +unawakened +unawarded +unaware +unawarely +unawareness +unawares +unawesome +unbacked +unbaked +unbalance +unbalanceable +unbalanced +unbalances +unbalancing +unballasted +unban +unbandage +unbandaged +unbandages +unbandaging +unbanned +unbanning +unbans +unbaptized +unbar +unbarbed +unbarbered +unbarred +unbarricaded +unbarring +unbars +unbated +unbearable +unbearableness +unbearably +unbeatable +unbeatably +unbeaten +unbeautiful +unbeautifully +unbecoming +unbecomingly +unbecomingness +unbefitting +unbegotten +unbeholden +unbeknown +unbeknownst +unbelief +unbelievable +unbelievably +unbeliever +unbelievers +unbelieving +unbelievingly +unbelievingness +unbelligerent +unbeloved +unbelted +unbemused +unbend +unbendable +unbending +unbendingly +unbends +unbent +unbeseeming +unbiased +unbiasedly +unbiasedness +unbiassed +unbiblical +unbid +unbidden +unbigoted +unbilled +unbind +unbinding +unbinds +unbitted +unbitten +unbitter +unbleached +unblemished +unblenched +unblended +unblessed +unblessedness +unblest +unblinded +unblinking +unblinkingly +unblock +unblocked +unblocking +unblocks +unblooded +unblushing +unblushingly +unblushingness +unbodied +unbolt +unbolted +unbolting +unbolts +unbonneted +unbookish +unborn +unbosom +unbosomed +unbosomer +unbosomers +unbosoming +unbosoms +unbought +unbound +unbounded +unboundedly +unboundedness +unbowdlerized +unbowed +unbox +unboxed +unboxes +unboxing +unbrace +unbraced +unbraces +unbracing +unbracketed +unbraid +unbraided +unbraiding +unbraids +unbrake +unbraked +unbrakes +unbraking +unbranched +unbranded +unbreachable +unbreakable +unbreakableness +unbreakables +unbreakably +unbreathable +unbred +unbridgeable +unbridgeably +unbridged +unbridle +unbridled +unbridledly +unbridles +unbridling +unbriefed +unbright +unbrilliant +unbroke +unbroken +unbrokenly +unbrokenness +unbruised +unbrushed +unbuckle +unbuckled +unbuckles +unbuckling +unbudgeable +unbudgeably +unbudgeted +unbudging +unbudgingly +unbuffered +unbuild +unbuildable +unbuilding +unbuilds +unbuilt +unbulky +unbundle +unbundled +unbundles +unbundling +unbundlings +unburden +unburdened +unburdening +unburdens +unbureaucratic +unburied +unburnable +unburned +unburnt +unbusinesslike +unbusy +unbuttered +unbutton +unbuttoned +unbuttoning +unbuttons +uncage +uncaged +uncages +uncaging +uncalcified +uncalcined +uncalculated +uncalculating +uncalibrated +uncalled +uncalloused +uncanceled +uncandid +uncandidly +uncannier +uncanniest +uncannily +uncanniness +uncanny +uncanonical +uncap +uncapitalized +uncapped +uncapping +uncaps +uncaptioned +uncapturable +uncared +uncaring +uncaringly +uncarpeted +uncase +uncased +uncases +uncasing +uncastrated +uncataloged +uncatchable +uncatchy +uncategorizable +uncaught +uncaused +unceasing +unceasingly +unceasingness +uncelebrated +uncensored +uncensorious +uncensured +unceremonious +unceremoniously +unceremoniousness +uncertain +uncertainly +uncertainness +uncertainties +uncertainty +uncertified +unchain +unchainable +unchained +unchaining +unchains +unchallengeable +unchallengeably +unchallenged +unchallenging +unchancy +unchangeability +unchangeable +unchangeableness +unchangeably +unchanged +unchanging +unchangingly +unchangingness +unchanneled +unchaperoned +uncharacteristic +uncharacteristically +uncharacterized +uncharged +uncharismatic +uncharitable +uncharitableness +uncharitably +uncharming +uncharted +unchartered +unchaste +unchastely +unchasteness +unchaster +unchastest +unchastity +unchauvinistic +uncheck +uncheckable +unchecked +unchecking +unchecks +uncheerful +unchewable +unchewed +unchic +unchildlike +unchivalrous +unchivalrously +unchlorinated +unchoke +unchoked +unchokes +unchoking +unchoreographed +unchristened +unchristian +unchronicled +unchronological +unchurch +unchurched +unchurches +unchurching +unchurchly +unci +uncial +uncially +uncials +unciform +unciforms +unciliated +uncinaria +uncinarias +uncinariasis +uncinate +uncinematic +uncirculated +uncircumcised +uncircumcision +uncircumcisions +uncivil +uncivilized +uncivilizedly +uncivilizedness +uncivilly +uncivilness +unclad +unclaimed +unclamp +unclamped +unclamping +unclamps +unclarified +unclarities +unclarity +unclasp +unclasped +unclasping +unclasps +unclassical +unclassifiable +unclassified +uncle +unclean +uncleaned +uncleaner +uncleanest +uncleanlier +uncleanliest +uncleanliness +uncleanly +uncleanness +unclear +unclearer +unclearest +unclearly +unclearness +uncleless +unclench +unclenched +unclenches +unclenching +uncles +unclichéd +unclimbable +unclimbableness +unclinch +unclinched +unclinches +unclinching +unclip +unclipped +unclipping +unclips +uncloak +uncloaked +uncloaking +uncloaks +unclog +unclogged +unclogging +unclogs +unclose +unclosed +uncloses +unclosing +unclothe +unclothed +unclothes +unclothing +unclouded +uncloudedly +uncloying +unclubbable +unclutter +uncluttered +uncluttering +unclutters +uncoalesce +uncoalesced +uncoalesces +uncoalescing +uncoated +uncoating +uncock +uncocked +uncocking +uncocks +uncoded +uncodified +uncoerced +uncoercive +uncoercively +uncoffin +uncoffined +uncoffining +uncoffins +uncoil +uncoiled +uncoiling +uncoils +uncoined +uncollected +uncollectible +uncolored +uncombative +uncombed +uncombined +uncomely +uncomfortable +uncomfortableness +uncomfortably +uncomforted +uncomic +uncomment +uncommented +uncommenting +uncomments +uncommercial +uncommercialized +uncommitted +uncommon +uncommoner +uncommonest +uncommonly +uncommonness +uncommunicable +uncommunicative +uncommunicatively +uncommunicativeness +uncompahgre +uncompassionate +uncompelled +uncompelling +uncompensated +uncompetitive +uncompetitively +uncompetitiveness +uncomplacent +uncomplaining +uncomplainingly +uncompleted +uncomplicated +uncomplimentary +uncompounded +uncomprehended +uncomprehending +uncomprehendingly +uncompress +uncompressed +uncompresses +uncompressing +uncompromisable +uncompromising +uncompromisingly +uncompromisingness +uncomputerized +unconcealed +unconceivable +unconceivableness +unconceivably +unconcern +unconcerned +unconcernedly +unconcernedness +unconcluded +uncondensed +unconditional +unconditionality +unconditionally +unconditionalness +unconditioned +unconditionedness +unconfessed +unconfident +unconfidently +unconfined +unconfirmed +unconformability +unconformable +unconformableness +unconformably +unconformities +unconformity +unconfounded +unconfuse +unconfused +unconfuses +unconfusing +uncongealed +uncongenial +uncongeniality +unconjugated +unconnected +unconnectedly +unconnectedness +unconquerable +unconquerably +unconquered +unconscionability +unconscionable +unconscionableness +unconscionably +unconscious +unconsciously +unconsciousness +unconsecrated +unconsidered +unconsolidated +unconstitutional +unconstitutionality +unconstitutionally +unconstrained +unconstraint +unconstricted +unconstructed +unconstructive +unconsumed +unconsummated +uncontainable +uncontaminated +uncontemplated +uncontemporary +uncontentious +uncontested +uncontracted +uncontradicted +uncontrived +uncontrollability +uncontrollable +uncontrollableness +uncontrollably +uncontrolled +uncontrolledness +uncontroversial +uncontroversially +unconventional +unconventionality +unconventionally +unconverted +unconvertible +unconvinced +unconvincing +unconvincingly +unconvincingness +unconvoyed +uncooked +uncool +uncooled +uncooperative +uncooperatively +uncooperativeness +uncoordinated +uncoordinatedly +uncopyrightable +uncork +uncorked +uncorking +uncorks +uncorrectable +uncorrected +uncorrelated +uncorroborated +uncorrupt +uncorrupted +uncorrupting +uncorseted +uncountable +uncounted +uncouple +uncoupled +uncoupler +uncouplers +uncouples +uncoupling +uncourageous +uncouth +uncouthly +uncouthness +uncovenanted +uncover +uncovered +uncovering +uncovers +uncoy +uncracked +uncrate +uncrated +uncrates +uncrating +uncrazy +uncreated +uncreative +uncredentialed +uncredited +uncrewed +uncrippled +uncritical +uncritically +uncropped +uncross +uncrossable +uncrossed +uncrosses +uncrossing +uncrowded +uncrown +uncrowned +uncrowning +uncrowns +uncrumple +uncrumpled +uncrumples +uncrumpling +uncrushable +uncrushed +uncrystallized +unction +unctuosity +unctuous +unctuously +unctuousness +uncuff +uncuffed +uncuffing +uncuffs +uncultivable +uncultivated +uncultured +uncurbed +uncured +uncurious +uncurl +uncurled +uncurling +uncurls +uncurrent +uncurtained +uncus +uncustomarily +uncustomary +uncut +uncute +uncuttable +uncynical +uncynically +und +undamaged +undamped +undanceable +undated +undauntable +undaunted +undauntedly +undauntedness +undead +undebatable +undebatably +undecadent +undecayed +undeceivable +undeceivably +undeceive +undeceived +undeceives +undeceiving +undecidability +undecidable +undecided +undecidedly +undecidedness +undecideds +undecillion +undecillions +undecipherable +undeciphered +undecked +undeclared +undecomposed +undecorated +undecylenic +undedicated +undefeatable +undefeated +undefended +undefiled +undefinable +undefined +undeflected +undefoliated +undeformed +undelegated +undelete +undeleted +undeliverable +undeliverably +undelivered +undeluded +undemanding +undemocratic +undemocratically +undemonstrated +undemonstrative +undemonstratively +undemonstrativeness +undeniable +undeniableness +undeniably +undenominational +undented +undependability +undependable +under +underachieve +underachieved +underachievement +underachiever +underachievers +underachieves +underachieving +underact +underacted +underacting +underactive +underactivity +underacts +underage +underaged +underappreciated +underarm +underarms +underassessment +underbellies +underbelly +underbid +underbidder +underbidders +underbidding +underbids +underbodies +underbody +underboss +underbosses +underbought +underbracing +underbred +underbrim +underbrims +underbrush +underbudgeted +underbuy +underbuying +underbuys +undercapitalization +undercapitalizations +undercapitalize +undercapitalized +undercapitalizes +undercapitalizing +undercard +undercards +undercarriage +undercarriages +undercharge +undercharged +undercharges +undercharging +underclass +underclasses +underclassman +underclassmen +underclothes +underclothing +undercoat +undercoated +undercoating +undercoats +undercook +undercooked +undercooking +undercooks +undercool +undercooled +undercooling +undercools +undercount +undercounted +undercounting +undercounts +undercover +undercroft +undercrofts +undercurrent +undercurrents +undercut +undercuts +undercutting +underdeveloped +underdevelopment +underdid +underdo +underdoes +underdog +underdogs +underdoing +underdone +underdrawers +underdress +underdressed +underdresses +underdressing +underdrive +underdrives +undereducated +underemphasis +underemphasize +underemphasized +underemphasizes +underemphasizing +underemployed +underemployment +underendow +underendowed +underendowing +underendowment +underendows +underestimate +underestimated +underestimates +underestimating +underestimation +underestimations +underexpose +underexposed +underexposes +underexposing +underexposure +underexposures +underfed +underfeed +underfeeding +underfeeds +underfinanced +underflow +underflows +underfoot +underfund +underfunded +underfunding +underfunds +underfur +underfurs +undergarment +undergarments +undergird +undergirded +undergirding +undergirds +undergirt +underglaze +underglazes +undergo +undergoes +undergoing +undergone +undergrad +undergrads +undergraduate +undergraduates +underground +undergrounded +undergrounder +undergrounders +undergrounding +undergrounds +undergrown +undergrowth +underhair +underhairs +underhand +underhanded +underhandedly +underhandedness +underhung +underinflated +underinflation +underinsurance +underinsure +underinsured +underinsures +underinsuring +underinvestment +underkill +underlaid +underlain +underlay +underlaying +underlayment +underlayments +underlays +underlet +underlets +underletting +underlie +underlies +underline +underlined +underlines +underling +underlings +underlining +underlinings +underlip +underlips +underlying +underlyingly +undermanned +undermine +undermined +undermines +undermining +undermodulate +undermodulated +undermodulates +undermodulating +undermodulation +undermodulations +undermost +underneath +underneaths +undernourish +undernourished +undernourishes +undernourishing +undernourishment +undernutrition +undernutritions +underpaid +underpainting +underpants +underpart +underparts +underpass +underpasses +underpay +underpaying +underpayment +underpayments +underpays +underperform +underperformance +underperformances +underperformed +underperformer +underperformers +underperforming +underperforms +underpin +underpinned +underpinning +underpinnings +underpins +underplay +underplayed +underplaying +underplays +underplot +underplots +underpopulated +underpopulation +underpowered +underprepared +underprice +underpriced +underprices +underpricing +underprivileged +underproduce +underproduced +underproduces +underproducing +underproduction +underproductions +underproductive +underproof +underprop +underpropped +underpropping +underprops +underpublicized +underquote +underquoted +underquotes +underquoting +underran +underrate +underrated +underrates +underrating +underreact +underreacted +underreacting +underreaction +underreactions +underreacts +underreport +underreported +underreporting +underreports +underrepresent +underrepresentation +underrepresentations +underrepresented +underrepresenting +underrepresents +underrun +underrunning +underruns +undersaturated +underscore +underscored +underscores +underscoring +undersea +underseas +undersecretariat +undersecretariats +undersecretaries +undersecretary +undersell +underseller +undersellers +underselling +undersells +underserve +underserved +underserves +underserving +underset +undersets +undersexed +undershirt +undershirted +undershirts +undershoot +undershooting +undershoots +undershorts +undershot +undershrub +undershrubs +underside +undersides +undersign +undersigned +undersigning +undersigns +undersize +undersized +underskirt +underskirts +undersleeve +undersleeves +underslung +undersoil +undersoils +undersold +underspin +underspins +understaff +understaffed +understaffing +understaffs +understand +understandability +understandable +understandably +understanding +understandingly +understandings +understands +understate +understated +understatedly +understatement +understatements +understates +understating +understeer +understeered +understeering +understeers +understood +understories +understory +understrapper +understrappers +understrata +understratum +understratums +understrength +understructure +understructures +understudied +understudies +understudy +understudying +undersubscribe +undersubscribed +undersubscribes +undersubscribing +undersubscription +undersubscriptions +undersupplied +undersupplies +undersupply +undersupplying +undersurface +undersurfaces +undertake +undertaken +undertaker +undertakers +undertakes +undertaking +undertakings +undertenant +undertenants +underthings +underthrust +underthrusting +underthrusts +undertint +undertints +undertone +undertones +undertook +undertow +undertows +undertrick +undertricks +undertrump +undertrumped +undertrumping +undertrumps +underused +underutilization +underutilize +underutilized +underutilizes +underutilizing +undervaluation +undervaluations +undervalue +undervalued +undervalues +undervaluing +undervest +undervests +underwater +underway +underwear +underweight +underwent +underwhelm +underwhelmed +underwhelming +underwhelms +underwing +underwings +underwood +underwoods +underwool +underwools +underworld +underworlds +underwrite +underwriter +underwriters +underwrites +underwriting +underwritten +underwrote +undescended +undescribable +undeserved +undeservedly +undeserving +undeservingly +undesignated +undesigning +undesirability +undesirable +undesirableness +undesirables +undesirably +undesired +undestroyed +undetached +undetectable +undetectably +undetected +undeterminable +undetermined +undeterred +undeveloped +undeviating +undeviatingly +undiagnosable +undiagnosed +undialectical +undid +undidactic +undies +undifferentiated +undiffused +undigested +undigestible +undignified +undiluted +undiminished +undimmed +undimpled +undine +undines +undiplomatic +undiplomatically +undirected +undiscerning +undischarged +undisciplined +undisclosed +undiscouraged +undiscoverable +undiscovered +undiscriminating +undiscussed +undisguised +undisguisedly +undismayed +undisposed +undisputable +undisputed +undisputedly +undisrupted +undissociated +undissolved +undistinguished +undistinguishing +undistorted +undistracted +undistributed +undisturbed +undivided +undividedly +undo +undoable +undocile +undock +undocked +undocking +undocks +undoctored +undoctrinaire +undocumented +undocumenteds +undoer +undoers +undoes +undogmatic +undogmatically +undoing +undomestic +undomesticated +undone +undotted +undouble +undoubled +undoubles +undoubling +undoubtable +undoubted +undoubtedly +undoubting +undrained +undramatic +undramatically +undramatized +undrape +undraped +undrapes +undraping +undraw +undrawing +undrawn +undraws +undreamed +undreamt +undress +undressed +undresses +undressing +undrew +undrilled +undrinkable +undrunk +undubbed +undue +undulant +undulate +undulated +undulates +undulating +undulation +undulations +undulatory +undulled +unduly +unduplicated +undusted +undutiful +undutifully +undutifulness +undyed +undying +undyingly +undynamic +uneager +unearmarked +unearned +unearth +unearthed +unearthing +unearthlier +unearthliest +unearthliness +unearthly +unearths +unease +uneasier +uneasiest +uneasily +uneasiness +uneasy +uneatable +uneaten +uneccentric +unecological +uneconomic +uneconomical +uneconomically +unedifying +unedifyingly +unedited +uneducable +uneducated +unelaborate +unelaborated +unelectable +unelected +unelectrified +unembarrassed +unembellished +unembittered +unemotional +unemotionally +unemphatic +unemphatically +unempirical +unemployability +unemployable +unemployables +unemployed +unemployment +unenchanted +unenclosed +unencouraging +unencumbered +unendearing +unending +unendingly +unendorsed +unendurable +unendurableness +unendurably +unenforceable +unenforced +unengaged +unenlarged +unenlightened +unenlightening +unenriched +unenterprising +unentertaining +unenthusiastic +unenthusiastically +unenviable +unenvied +unenvious +unequal +unequaled +unequalize +unequalized +unequalizes +unequalizing +unequalled +unequally +unequals +unequipped +unequivocably +unequivocal +unequivocally +unerotic +unerring +unerringly +unescapable +unesco +unescorted +unessential +unessentials +unestablished +unethical +unethically +unevaluated +uneven +unevener +unevenest +unevenly +unevenness +uneventful +uneventfully +uneventfulness +unexacting +unexaggerated +unexamined +unexampled +unexcelled +unexceptionable +unexceptionableness +unexceptionably +unexceptional +unexceptionally +unexcitable +unexcited +unexciting +unexcused +unexecuted +unexercised +unexhausted +unexotic +unexpanded +unexpected +unexpectedly +unexpectedness +unexpended +unexpired +unexplainable +unexplainably +unexplained +unexploded +unexploited +unexplored +unexposed +unexpressed +unexpressive +unexpressively +unexpressiveness +unexpurgated +unextraordinary +unfading +unfadingly +unfailing +unfailingly +unfailingness +unfair +unfairer +unfairest +unfairly +unfairness +unfaith +unfaithful +unfaithfully +unfaithfulness +unfaked +unfallen +unfalsifiable +unfaltering +unfalteringly +unfamiliar +unfamiliarity +unfamiliarly +unfamous +unfancy +unfashionable +unfashionableness +unfashionably +unfasten +unfastened +unfastening +unfastens +unfastidious +unfathered +unfathomable +unfathomed +unfavorable +unfavorableness +unfavorably +unfavorite +unfazed +unfeasibility +unfeasible +unfecundated +unfeeling +unfeelingly +unfeelingness +unfeigned +unfeignedly +unfelt +unfeminine +unfenced +unfermented +unfertile +unfertilized +unfetter +unfettered +unfettering +unfetters +unfilial +unfilially +unfilled +unfiltered +unfindable +unfinished +unfired +unfit +unfitly +unfitness +unfits +unfitted +unfitting +unfittingly +unfix +unfixable +unfixed +unfixes +unfixing +unflagging +unflaggingly +unflamboyant +unflappability +unflappable +unflappably +unflapped +unflashy +unflattering +unflatteringly +unflavored +unflawed +unfledged +unflinching +unflinchingly +unflinchingness +unflustered +unflyable +unfocused +unfocussed +unfold +unfolded +unfolding +unfoldment +unfolds +unfond +unforced +unforeseeable +unforeseeably +unforeseen +unforested +unforgettability +unforgettable +unforgettableness +unforgettably +unforgivable +unforgivably +unforgiving +unforgivingness +unforgotten +unforked +unformatted +unformed +unformulated +unforthcoming +unfortified +unfortunate +unfortunately +unfortunateness +unfortunates +unfossiliferous +unfound +unfounded +unfoundedly +unfoundedness +unframed +unfree +unfreedom +unfreeze +unfreezes +unfreezing +unfrequented +unfriended +unfriendlier +unfriendliest +unfriendliness +unfriendly +unfrivolous +unfrock +unfrocked +unfrocking +unfrocks +unfrosted +unfroze +unfrozen +unfruitful +unfruitfully +unfruitfulness +unfulfillable +unfulfilled +unfulfilling +unfunded +unfunny +unfurl +unfurled +unfurling +unfurls +unfurnished +unfused +unfussily +unfussy +ungainlier +ungainliest +ungainliness +ungainly +ungallant +ungallantly +ungarnished +ungava +ungenerosity +ungenerous +ungenerously +ungenial +ungenteel +ungentle +ungentlemanly +ungentrified +ungerminated +ungifted +ungimmicky +ungird +ungirded +ungirding +ungirds +ungirt +unglamorized +unglamorous +unglamorously +unglazed +unglue +unglued +unglues +ungluing +ungodlier +ungodliest +ungodliness +ungodly +ungot +ungotten +ungovernable +ungovernableness +ungovernably +ungoverned +ungraceful +ungracefully +ungracious +ungraciously +ungraciousness +ungraded +ungrammatical +ungrammaticality +ungrammatically +ungraspable +ungrateful +ungratefully +ungratefulness +ungratified +unground +ungrounded +ungrouped +ungrudging +ungrudgingly +ungual +unguard +unguarded +unguardedly +unguardedness +unguarding +unguards +unguent +unguentary +unguents +ungues +unguessable +unguiculate +unguiculated +unguided +unguis +ungula +ungulate +ungulates +unguligrade +unguligrades +unhackneyed +unhallow +unhallowed +unhallowing +unhallows +unhampered +unhand +unhanded +unhandier +unhandiest +unhandily +unhandiness +unhanding +unhands +unhandsome +unhandsomely +unhandsomeness +unhandy +unhappier +unhappiest +unhappily +unhappiness +unhappinesses +unhappy +unhardened +unharmed +unharmonious +unharness +unharnessed +unharnesses +unharnessing +unharvested +unhatched +unhealed +unhealthful +unhealthier +unhealthiest +unhealthily +unhealthiness +unhealthy +unheard +unhearing +unheated +unhedged +unheeded +unheeding +unheedingly +unhelpful +unhelpfully +unheralded +unheroic +unhesitant +unhesitating +unhesitatingly +unhidden +unhighlight +unhighlighted +unhighlighting +unhighlights +unhindered +unhinge +unhinged +unhinges +unhinging +unhip +unhistorical +unhitch +unhitched +unhitches +unhitching +unholier +unholiest +unholily +unholiness +unholy +unhomogenized +unhonored +unhood +unhooded +unhooding +unhoods +unhook +unhooked +unhooking +unhooks +unhoped +unhopeful +unhorse +unhorsed +unhorses +unhorsing +unhoused +unhouseled +unhumorous +unhurried +unhurriedly +unhurt +unhydrolyzed +unhygienic +unhyphenated +unhysterical +unhysterically +unialgal +uniat +uniate +uniaxial +uniaxially +unicameral +unicamerally +unicef +unicellular +unicellularity +unicolor +unicorn +unicorns +unicostate +unicuspid +unicuspids +unicycle +unicycles +unicyclist +unicyclists +unidentifiable +unidentifiably +unidentified +unideological +unidimensional +unidimensionality +unidiomatic +unidirectional +unidirectionally +unifactorial +unifiable +unification +unifications +unified +unifier +unifiers +unifies +unifilar +uniflow +unifoliate +unifoliolate +uniform +uniformed +uniforming +uniformitarian +uniformitarianism +uniformitarians +uniformity +uniformly +uniformness +uniforms +unify +unifying +unignorable +unilateral +unilateralism +unilateralisms +unilateralist +unilateralists +unilaterally +unilineal +unilinear +unilingual +unilingually +uniliteral +unilluminated +unilluminating +unillusioned +unillustrated +unilobar +unilocular +unimaginable +unimaginably +unimaginative +unimaginatively +unimagined +unimak +unimmunized +unimpaired +unimpassioned +unimpeachable +unimpeachably +unimpeded +unimplemented +unimportance +unimportant +unimposing +unimpressed +unimpressionable +unimpressive +unimpressively +unimproved +unincorporated +unindexed +unindicted +unindustrialized +uninfected +uninflammable +uninflated +uninflected +uninfluenced +uninformative +uninformatively +uninformed +uningratiating +uninhabitability +uninhabitable +uninhabited +uninhibited +uninhibitedly +uninhibitedness +uninitialized +uninitiate +uninitiated +uninitiates +uninjured +uninoculated +uninominal +uninspected +uninspired +uninspiring +uninstalled +uninstructed +uninstructive +uninsulated +uninsurability +uninsurable +uninsured +uninsureds +unintegrated +unintellectual +unintelligence +unintelligent +unintelligently +unintelligibility +unintelligible +unintelligibleness +unintelligibly +unintended +unintentional +unintentionally +uninterest +uninterested +uninterestedly +uninterestedness +uninteresting +uninterestingly +uninterrupted +uninterruptedly +unintimidated +unintuitive +uninucleate +uninventive +uninvestigated +uninvited +uninviting +uninvitingly +uninvolved +union +unionism +unionist +unionistic +unionists +unionization +unionizations +unionize +unionized +unionizer +unionizers +unionizes +unionizing +unions +uniparental +uniparentally +uniparous +uniped +unipersonal +uniplanar +unipolar +unipolarity +unipotent +unique +uniquely +uniqueness +unironically +unirradiated +unirrigated +uniserial +uniseriate +unisex +unisexual +unisexuality +unisexually +unison +unisonant +unisonous +unisons +unissued +unit +unitage +unitard +unitards +unitarian +unitarianism +unitarians +unitarily +unitary +unite +united +unitedly +unitedness +uniter +uniters +unites +unities +uniting +unitive +unitization +unitizations +unitize +unitized +unitizes +unitizing +unitrust +unitrusts +units +unity +univalent +univalents +univalve +univalves +univariate +universal +universalism +universalist +universalistic +universalists +universalities +universality +universalizability +universalization +universalizations +universalize +universalized +universalizes +universalizing +universally +universalness +universals +universe +universes +universities +university +univocal +univocally +univocals +unix +unjacketed +unjaded +unjoined +unjoint +unjointed +unjointing +unjoints +unjust +unjustifiable +unjustifiably +unjustified +unjustly +unjustness +unjustnesses +unkempt +unkennel +unkenneled +unkenneling +unkennelled +unkennelling +unkennels +unkept +unkind +unkinder +unkindest +unkindlier +unkindliest +unkindliness +unkindly +unkindness +unkindnesses +unkink +unkinked +unkinking +unkinks +unknit +unknits +unknitted +unknitting +unknot +unknots +unknotted +unknotting +unknowability +unknowable +unknowableness +unknowably +unknowing +unknowingly +unknowingness +unknowledgeable +unknown +unknowns +unkosher +unlabeled +unlabored +unlace +unlaced +unlaces +unlacing +unlade +unladed +unladen +unlades +unlading +unladylike +unlaid +unlamented +unlash +unlashed +unlashes +unlashing +unlatch +unlatched +unlatches +unlatching +unlaundered +unlawful +unlawfully +unlawfulness +unlay +unlaying +unlays +unlead +unleaded +unleading +unleads +unlearn +unlearnable +unlearned +unlearnedly +unlearning +unlearns +unlearnt +unleash +unleashed +unleashes +unleashing +unleavened +unless +unlettered +unleveled +unliberated +unlicensed +unlicked +unlighted +unlikable +unlike +unlikelier +unlikeliest +unlikelihood +unlikeliness +unlikely +unlikeness +unlimber +unlimbered +unlimbering +unlimbers +unlimited +unlimitedly +unlimitedness +unlined +unlink +unlinked +unlinking +unlinks +unliquidated +unlisted +unlistenable +unlit +unliterary +unlivable +unlive +unlived +unlives +unliving +unload +unloaded +unloader +unloaders +unloading +unloads +unlocalized +unlock +unlocked +unlocking +unlocks +unlooked +unloose +unloosed +unloosen +unloosened +unloosening +unloosens +unlooses +unloosing +unlovable +unloved +unlovelier +unloveliest +unloveliness +unlovely +unloving +unluckier +unluckiest +unluckily +unluckiness +unlucky +unlyrical +unmacho +unmade +unmagnified +unmake +unmakes +unmaking +unmalicious +unmaliciously +unman +unmanageability +unmanageable +unmanageably +unmanaged +unmanipulated +unmanlier +unmanliest +unmanliness +unmanly +unmanned +unmannered +unmanneredly +unmannerliness +unmannerly +unmanning +unmans +unmapped +unmarked +unmarketable +unmarred +unmarriageable +unmarried +unmarrieds +unmasculine +unmask +unmasked +unmasking +unmasks +unmatchable +unmatched +unmated +unmeaning +unmeaningly +unmeant +unmeasurable +unmeasured +unmechanical +unmechanically +unmechanized +unmediated +unmedicated +unmeet +unmelodic +unmelodious +unmelodiousness +unmemorable +unmemorably +unmentionable +unmentionableness +unmentionables +unmentionably +unmentioned +unmerciful +unmercifully +unmercifulness +unmerited +unmeritorious +unmerry +unmeshed +unmet +unmetabolized +unmethodical +unmethodically +unmilitary +unmilled +unmindful +unmindfully +unmindfulness +unmined +unmingled +unmissed +unmistakable +unmistakably +unmitigated +unmitigatedly +unmitigatedness +unmix +unmixable +unmixed +unmixedly +unmixes +unmixing +unmodernized +unmodified +unmodish +unmold +unmolded +unmolding +unmolds +unmolested +unmonitored +unmoor +unmoored +unmooring +unmoors +unmoral +unmorality +unmorally +unmortise +unmortised +unmortises +unmortising +unmotivated +unmounted +unmovable +unmoved +unmoving +unmuffle +unmuffled +unmuffles +unmuffling +unmurmuring +unmusical +unmusically +unmusicalness +unmuzzle +unmuzzled +unmuzzles +unmuzzling +unmyelinated +unnail +unnailed +unnailing +unnails +unnamable +unnameable +unnamed +unnatural +unnaturally +unnaturalness +unnecessarily +unnecessary +unneeded +unnegotiable +unnerve +unnerved +unnerves +unnerving +unnervingly +unneurotic +unnewsworthy +unnilhexium +unnilpentium +unnilquadium +unnilquintium +unnormalized +unnoted +unnoticeable +unnoticeably +unnoticed +unnoticing +unnourished +unnourishing +unnumbered +unobjectionable +unobscured +unobservable +unobservant +unobserved +unobserving +unobstructed +unobtainable +unobtrusive +unobtrusively +unobtrusiveness +unoccupied +unoffending +unofficial +unofficially +unopenable +unopened +unopposed +unordered +unordinary +unorganized +unoriginal +unornament +unornamented +unornamenting +unornaments +unorthodox +unorthodoxly +unorthodoxy +unostentatious +unostentatiously +unostentatiousness +unowned +unoxygenated +unpack +unpacked +unpacker +unpackers +unpacking +unpacks +unpadded +unpaged +unpaginated +unpaid +unpainted +unpaired +unpalatability +unpalatable +unpalatably +unparalleled +unparasitized +unpardonable +unparliamentary +unparsed +unparticular +unpartisan +unpassable +unpasteurized +unpastoral +unpatentable +unpatriotic +unpatriotically +unpatronizing +unpaved +unpedantic +unpeeled +unpeg +unpegged +unpegging +unpegs +unpeople +unpeopled +unpeoples +unpeopling +unperceived +unperceiving +unperceptive +unperfect +unperfected +unperforated +unperformable +unperformed +unperson +unpersuaded +unpersuasive +unperturbed +unphysical +unpick +unpicked +unpicking +unpicks +unpicturesque +unpile +unpiled +unpiles +unpiling +unpin +unpinned +unpinning +unpins +unpitying +unpityingly +unplaced +unplanned +unplanted +unplausible +unplayable +unpleasant +unpleasantly +unpleasantness +unpleasantries +unpleasantry +unpleased +unpleasing +unplowed +unplug +unplugged +unplugging +unplugs +unplumbed +unpoetic +unpolarized +unpoliced +unpolished +unpolitical +unpolled +unpolluted +unpopular +unpopularity +unpopulated +unposed +unpractical +unpracticed +unprecedented +unprecedentedly +unpredictability +unpredictable +unpredictables +unpredictably +unpredicted +unpregnant +unprejudiced +unpremeditated +unpremeditatedly +unprepared +unpreparedly +unpreparedness +unprepossessing +unprepossessingly +unpressed +unpressured +unpressurized +unpresuming +unpretending +unpretentious +unpretentiously +unpretentiousness +unpretty +unpriced +unprimed +unprincipled +unprincipledness +unprintable +unprintably +unprivileged +unproblematic +unprocessed +unprocurable +unproduced +unproductive +unproductively +unproductiveness +unprofaned +unprofessed +unprofessional +unprofessionalism +unprofessionally +unprofitability +unprofitable +unprofitableness +unprofitably +unprogrammable +unprogrammed +unprogressive +unprolific +unpromising +unpromisingly +unprompted +unpronounceable +unpronounced +unpropitious +unpropitiously +unprosperous +unprotected +unprovable +unproved +unproven +unprovided +unprovidedly +unprovoked +unpruned +unpublicized +unpublishable +unpublished +unpunctual +unpunctuality +unpunctuated +unpunished +unpurified +unputdownable +unqualified +unqualifiedly +unquantifiable +unquantified +unquenchable +unquenchably +unquenched +unquestionability +unquestionable +unquestionableness +unquestionably +unquestioned +unquestioning +unquestioningly +unquiet +unquieter +unquietest +unquietly +unquietness +unquotable +unquote +unquoted +unraised +unranked +unrated +unravel +unraveled +unraveling +unravelled +unravelling +unravels +unravished +unreachability +unreachable +unreachably +unreached +unread +unreadability +unreadable +unreadier +unreadiest +unreadily +unreadiness +unready +unreal +unrealistic +unrealistically +unrealities +unreality +unrealizable +unrealized +unreason +unreasonable +unreasonableness +unreasonably +unreasoned +unreasoning +unreasoningly +unreassuringly +unrecalled +unreceptive +unreckonable +unreclaimable +unreclaimed +unrecognizable +unrecognizableness +unrecognizably +unrecognized +unrecognizing +unrecompensed +unreconcilable +unreconciled +unreconstructed +unrecorded +unrecoverable +unrecovered +unrectified +unrecyclable +unredeemable +unredeemed +unredressed +unreduced +unreel +unreeled +unreeling +unreels +unreeve +unreeved +unreeves +unreeving +unrefined +unreflecting +unreflectingly +unreflective +unreflectively +unreformed +unrefrigerated +unregenerable +unregeneracy +unregenerate +unregenerately +unregimented +unregistered +unregulated +unrehearsed +unreinforced +unrelated +unrelaxed +unreleased +unrelenting +unrelentingly +unreliability +unreliable +unreliableness +unreliably +unrelieved +unrelievedly +unreligious +unreluctant +unremarkable +unremarkably +unremarked +unremembered +unreminiscent +unremitting +unremittingly +unremittingness +unremovable +unremunerated +unremunerative +unrenowned +unrepaired +unrepeatable +unrepentant +unrepentantly +unreported +unrepresentative +unrepresentativeness +unrepresented +unrepressed +unreproved +unrequited +unrequitedly +unreserve +unreserved +unreservedly +unreservedness +unresistant +unresisting +unresistingly +unresolvable +unresolved +unrespectable +unresponsive +unresponsively +unresponsiveness +unrest +unrestful +unrestored +unrestrained +unrestrainedly +unrestrainedness +unrestraint +unrestraints +unrestricted +unrestrictedly +unretouched +unreturnable +unrevealed +unrevealing +unrevealingly +unreviewable +unreviewed +unrevised +unrevolutionary +unrewarded +unrewarding +unrhetorical +unrhymed +unrhythmic +unridable +unriddle +unriddled +unriddler +unriddlers +unriddles +unriddling +unrifled +unrig +unrigged +unrigging +unrighteous +unrighteously +unrighteousness +unrightfully +unrigs +unrip +unripe +unripened +unripeness +unriper +unripest +unripped +unripping +unrips +unrivaled +unrivalled +unrobed +unroll +unrolled +unrolling +unrolls +unromantic +unromantically +unromanticized +unroof +unroofed +unroofing +unroofs +unroot +unrooted +unrooting +unroots +unround +unrounded +unrounding +unrounds +unrove +unroven +unruffled +unruled +unrulier +unruliest +unruliness +unruly +unrushed +uns +unsacred +unsaddle +unsaddled +unsaddles +unsaddling +unsafe +unsafer +unsafest +unsaid +unsalable +unsalaried +unsalted +unsalvageable +unsanctified +unsanctioned +unsanitary +unsatisfactorily +unsatisfactoriness +unsatisfactory +unsatisfied +unsatisfiedness +unsatisfying +unsatisfyingly +unsaturate +unsaturated +unsaturates +unsaved +unsavorily +unsavoriness +unsavory +unsay +unsayable +unsayables +unsaying +unsays +unscalable +unscarred +unscathed +unscented +unscheduled +unscholarly +unschooled +unscientific +unscientifically +unscramble +unscrambled +unscrambler +unscramblers +unscrambles +unscrambling +unscratched +unscreened +unscrew +unscrewed +unscrewing +unscrews +unscripted +unscriptural +unscrupulous +unscrupulously +unscrupulousness +unseal +unsealed +unsealing +unseals +unseam +unseamed +unseaming +unseams +unsearchable +unsearchably +unseasonable +unseasonableness +unseasonably +unseasoned +unseat +unseated +unseating +unseats +unseaworthy +unsecured +unseeded +unseeing +unseeingly +unseemlier +unseemliest +unseemliness +unseemly +unseen +unsegmented +unsegregated +unselected +unselective +unselectively +unself +unselfconscious +unselfconsciously +unselfconsciousness +unselfish +unselfishly +unselfishness +unsell +unsellable +unselling +unsells +unsensational +unsensitized +unsent +unsentimental +unsentimentally +unseparated +unserious +unseriousness +unserved +unserviceable +unset +unsetting +unsettle +unsettled +unsettledness +unsettlement +unsettles +unsettling +unsettlingly +unsew +unsewed +unsewing +unsewn +unsex +unsexed +unsexes +unsexing +unsexual +unsexy +unshackle +unshackled +unshackles +unshackling +unshaded +unshakable +unshakably +unshaken +unshaped +unshapely +unshapen +unshared +unsharp +unsharpened +unshaved +unshaven +unsheathe +unsheathed +unsheathes +unsheathing +unshed +unshell +unshelled +unshelling +unshells +unsheltered +unshielded +unshift +unshifted +unshifting +unshifts +unship +unshipped +unshipping +unships +unshockable +unshod +unshorn +unshowy +unshrinking +unsight +unsighted +unsighting +unsightlier +unsightliest +unsightliness +unsightly +unsights +unsigned +unsinkable +unsized +unskilled +unskillful +unskillfully +unskillfulness +unslakable +unslaked +unsleeping +unsling +unslinging +unslings +unslung +unsmart +unsmiling +unsmilingly +unsmoothed +unsnag +unsnagged +unsnagging +unsnags +unsnap +unsnapped +unsnapping +unsnaps +unsnarl +unsnarled +unsnarling +unsnarls +unsociability +unsociable +unsociableness +unsociably +unsocial +unsocially +unsoiled +unsold +unsolder +unsoldered +unsoldering +unsolders +unsoldierly +unsolicited +unsolvable +unsolved +unsophisticated +unsophisticatedly +unsophisticatedness +unsophistication +unsorted +unsought +unsound +unsounded +unsounder +unsoundest +unsoundly +unsoundness +unsowed +unsown +unsparing +unsparingly +unsparingness +unspeak +unspeakable +unspeakableness +unspeakably +unspeaking +unspeaks +unspecialized +unspecifiable +unspecific +unspecified +unspectacular +unspectacularly +unspent +unsphere +unsphered +unspheres +unsphering +unspiritual +unsplit +unspoiled +unspoilt +unspoke +unspoken +unsporting +unsportsmanlike +unspotted +unspottedness +unsprayed +unsprung +unstable +unstableness +unstabler +unstablest +unstably +unstained +unstamped +unstandardized +unstapled +unstaring +unstartling +unstated +unstaunched +unstayed +unsteadied +unsteadier +unsteadies +unsteadiest +unsteadily +unsteadiness +unsteady +unsteadying +unsteel +unsteeled +unsteeling +unsteels +unstep +unstepped +unstepping +unsteps +unsterile +unsterilized +unstick +unsticking +unsticks +unstilted +unstinted +unstinting +unstintingly +unstirred +unstitch +unstitched +unstitches +unstitching +unstop +unstoppable +unstoppably +unstopped +unstopper +unstopping +unstops +unstrained +unstrap +unstrapped +unstrapping +unstraps +unstratified +unstressed +unstriated +unstring +unstringing +unstrings +unstructured +unstrung +unstuck +unstudied +unstuffy +unstylish +unsubdued +unsubscribe +unsubscribed +unsubscribes +unsubscribing +unsubsidized +unsubstantial +unsubstantiality +unsubstantially +unsubstantiated +unsubtle +unsubtly +unsuccess +unsuccessful +unsuccessfully +unsuccessfulness +unsuitability +unsuitable +unsuitableness +unsuitably +unsuited +unsullied +unsung +unsupervised +unsupportable +unsupported +unsuppressed +unsure +unsurpassable +unsurpassed +unsurprised +unsurprising +unsurprisingly +unsusceptible +unsuspected +unsuspectedly +unsuspecting +unsuspectingly +unsuspended +unsuspicious +unsustainable +unswathe +unswathed +unswathes +unswathing +unswayable +unswear +unswearing +unswears +unsweetened +unswerving +unswervingly +unswore +unsworn +unsymmetrical +unsymmetrically +unsympathetic +unsympathetically +unsynchronized +unsystematic +unsystematically +unsystematized +untactful +untagged +untainted +untalented +untamable +untamed +untangle +untangled +untangles +untangling +untanned +untapped +untarnished +untaught +untaxed +unteach +unteachable +unteaches +unteaching +untechnical +untellable +untempered +untenability +untenable +untenableness +untenably +untenanted +untended +untented +untenured +untestable +untested +untether +untethered +untethering +untethers +unthankful +unthankfully +unthankfulness +unthawed +unthawing +untheoretical +untheorized +unthink +unthinkability +unthinkable +unthinkableness +unthinkably +unthinking +unthinkingly +unthinkingness +unthinks +unthought +unthread +unthreaded +unthreading +unthreads +unthreatening +unthrift +unthrifty +unthrone +unthroned +unthrones +unthroning +untidier +untidiest +untidily +untidiness +untidy +untie +untied +unties +until +untillable +untilled +untimelier +untimeliest +untimeliness +untimely +untiring +untiringly +untitled +unto +untogether +untold +untouchability +untouchable +untouchables +untouchably +untouched +untoward +untowardly +untowardness +untraceable +untracked +untraditional +untraditionally +untrained +untrammeled +untransformed +untranslatability +untranslatable +untranslated +untraveled +untraversed +untread +untreading +untreads +untreatable +untreatably +untreated +untrendy +untried +untrimmed +untrod +untrodden +untroubled +untroubledness +untrue +untruer +untruest +untruly +untruss +untrussed +untrusses +untrussing +untrusting +untrustworthily +untrustworthiness +untrustworthy +untruth +untruthful +untruthfully +untruthfulness +untruths +untuck +untucked +untucking +untucks +untufted +untune +untuned +untunes +untuning +unturned +untutored +untwine +untwined +untwines +untwining +untwist +untwisted +untwisting +untwists +untying +untypical +untypically +ununderstandable +unusable +unused +unusual +unusually +unusualness +unutilized +unutterable +unutterableness +unutterably +unuttered +unvaccinated +unvalued +unvanquished +unvaried +unvarnished +unvarying +unvaryingly +unveil +unveiled +unveiling +unveilings +unveils +unventilated +unverbalized +unverifiable +unverified +unversed +unvested +unviable +unviewed +unvigilant +unviolated +unvisited +unvocal +unvoice +unvoiced +unvoices +unvoicing +unwanted +unwarier +unwariest +unwarily +unwariness +unwarlike +unwarned +unwarrantable +unwarrantably +unwarranted +unwarrantedly +unwary +unwashed +unwashedness +unwatchable +unwatched +unwatchful +unwavering +unwaveringly +unwaxed +unweakened +unweaned +unwearable +unwearied +unweariedly +unweathered +unweave +unweaves +unweaving +unwed +unwedded +unweeting +unweetingly +unweight +unweighted +unweighting +unweights +unwelcome +unwell +unwept +unwhite +unwholesome +unwholesomely +unwholesomeness +unwieldier +unwieldiest +unwieldily +unwieldiness +unwieldy +unwilled +unwilling +unwillingly +unwillingness +unwind +unwinding +unwinds +unwinnable +unwire +unwired +unwires +unwiring +unwisdom +unwisdoms +unwise +unwisely +unwiser +unwisest +unwish +unwished +unwishes +unwishing +unwitting +unwittingly +unwomanly +unwon +unwonted +unwontedly +unwontedness +unworkability +unworkable +unworkableness +unworkably +unworked +unworldlier +unworldliest +unworldliness +unworldly +unworn +unworried +unworthier +unworthiest +unworthily +unworthiness +unworthy +unwound +unwounded +unwove +unwoven +unwrap +unwrapped +unwrapping +unwraps +unwreathe +unwreathed +unwreathes +unwreathing +unwrinkled +unwritten +unyielding +unyieldingly +unyieldingness +unyoke +unyoked +unyokes +unyoking +unyoung +unzip +unzipped +unzipping +unzips +up +upanishad +upanishadic +upanishads +upas +upbeat +upbeats +upbraid +upbraided +upbraider +upbraiders +upbraiding +upbraidingly +upbraids +upbringing +upbringings +upbuild +upbuilder +upbuilders +upbuilding +upbuilds +upbuilt +upcast +upcasts +upchuck +upchucked +upchucking +upchucks +upcoast +upcoming +upcountry +update +updated +updates +updating +updo +updos +updraft +updrafts +upend +upended +upending +upends +upfield +upfront +upgrade +upgraded +upgrades +upgrading +upgrowth +upgrowths +upheaval +upheavals +upheave +upheaved +upheaver +upheavers +upheaves +upheaving +upheld +uphill +uphills +uphold +upholder +upholders +upholding +upholds +upholster +upholstered +upholsterer +upholsterers +upholsteries +upholstering +upholsters +upholstery +upityness +upkeep +upland +uplander +uplanders +uplands +uplift +uplifted +uplifter +uplifters +uplifting +uplifts +uplink +uplinks +upload +uploaded +uploading +uploads +upmanship +upmanships +upmarket +upmost +upolu +upon +upped +upper +uppercase +uppercased +uppercases +uppercasing +upperclassman +upperclassmen +uppercut +uppercuts +uppermost +upperpart +upperparts +uppers +upping +uppish +uppishly +uppishness +uppitiness +uppity +uppityness +uppsala +upraise +upraised +upraises +upraising +uprate +uprated +uprates +uprating +uprear +upreared +uprearing +uprears +upright +uprightly +uprightness +uprights +uprise +uprisen +upriser +uprisers +uprises +uprising +uprisings +upriver +uproar +uproarious +uproariously +uproariousness +uproars +uproot +uprooted +uprootedness +uprooter +uprooters +uprooting +uproots +uprose +uprush +uprushes +ups +upscale +upscaled +upscales +upscaling +upset +upsets +upsetter +upsetters +upsetting +upsettingly +upshift +upshifted +upshifting +upshifts +upshot +upshots +upside +upsides +upsilon +upsmanship +upsprang +upspring +upspringing +upsprings +upsprung +upstage +upstaged +upstager +upstagers +upstages +upstaging +upstairs +upstanding +upstandingness +upstart +upstarted +upstarting +upstarts +upstate +upstater +upstaters +upstream +upstroke +upstrokes +upsurge +upsurged +upsurges +upsurging +upsweep +upsweeping +upsweeps +upswept +upswing +upswings +uptake +uptakes +uptempo +uptempos +upthrow +upthrows +upthrust +upthrusting +upthrusts +uptick +upticks +uptight +uptightness +uptilt +uptilted +uptilting +uptilts +uptime +uptimes +uptown +uptowner +uptowners +uptowns +uptrend +uptrended +uptrending +uptrends +upturn +upturned +upturning +upturns +upward +upwardly +upwardness +upwards +upwell +upwelled +upwelling +upwells +upwind +uracil +uraei +uraemia +uraemias +uraeus +uraeuses +ural +uralian +uralic +urals +urania +uranian +uranias +uranic +uraninite +uraninites +uranium +uranography +uranous +uranus +uranyl +urase +urases +urate +urates +uratic +urban +urbane +urbanely +urbaner +urbanest +urbanism +urbanist +urbanistic +urbanistically +urbanists +urbanite +urbanites +urbanities +urbanity +urbanization +urbanizations +urbanize +urbanized +urbanizes +urbanizing +urbanologist +urbanologists +urbanology +urbino +urceolate +urchin +urchins +urd +urds +urdu +urea +urease +ureases +uredia +uredinia +uredinial +urediniospore +urediniospores +uredinium +urediospore +urediospores +uredium +uredospore +uredospores +uredostage +uredostages +ureide +ureides +uremia +uremias +uremic +ureotelic +ureotelism +ureter +ureteral +ureteric +ureters +urethan +urethane +urethanes +urethans +urethra +urethrae +urethral +urethras +urethrectomies +urethrectomy +urethritis +urethritises +urethroscope +urethroscopes +urethroscopy +uretic +urge +urged +urgencies +urgency +urgent +urgently +urger +urgers +urges +urging +urgings +urial +uric +uricosuric +uricotelic +uricotelism +uridine +uridines +urim +urinal +urinals +urinalyses +urinalysis +urinary +urinate +urinated +urinates +urinating +urination +urinations +urinative +urinator +urinators +urine +uriniferous +urinogenital +urinometer +urinometers +urinose +urinous +urn +urns +urocanic +urochord +urochordate +urochordates +urochords +urochrome +urochromes +urodele +urodeles +urogenital +urogenous +urogram +urograms +urographic +urographies +urography +urokinase +urokinases +urolith +urolithiasis +urolithic +uroliths +urologic +urological +urologist +urologists +urology +uronic +uropod +uropods +uropygial +uropygium +uropygiums +uroscopies +uroscopy +urostomies +urostomy +urostyle +urostyles +ursa +ursine +ursprache +ursula +ursuline +ursulines +urtext +urtexts +urticant +urticants +urticaria +urticarial +urticate +urticated +urticates +urticating +urtication +urtications +uruguay +uruguayan +uruguayans +urus +uruses +urushiol +urushiols +us +usa +usability +usable +usableness +usably +usage +usages +usance +usances +use +useable +used +useful +usefully +usefulness +useless +uselessly +uselessness +user +users +uses +ushak +ushant +usher +ushered +usherette +usherettes +ushering +ushers +using +usnea +usneas +usnic +usquebaugh +usquebaughs +usual +usually +usualness +usufruct +usufructs +usufructuaries +usufructuary +usurer +usurers +usuries +usurious +usuriously +usuriousness +usurp +usurpation +usurpations +usurped +usurper +usurpers +usurping +usurpingly +usurps +usury +ut +utah +utahan +utahans +ute +utensil +utensils +uteri +uterine +utero +uterus +uteruses +utes +utile +utilitarian +utilitarianism +utilitarians +utilities +utility +utilizable +utilization +utilizations +utilize +utilized +utilizer +utilizers +utilizes +utilizing +utmost +utopia +utopian +utopianism +utopians +utopias +utopism +utopist +utopistic +utopists +utrecht +utricle +utricles +utricular +utriculi +utriculus +utrillo +uttar +utter +utterable +utterance +utterances +uttered +utterer +utterers +uttering +utterly +uttermost +utters +uvarovite +uvarovites +uvea +uveal +uveas +uveitis +uvula +uvulae +uvular +uvulas +uvulitis +uvulitises +uxorial +uxorially +uxoricide +uxoricides +uxorious +uxoriously +uxoriousness +uzbeg +uzbek +uzbekistan +uzbeks +uzès +v +vac +vacancies +vacancy +vacant +vacantly +vacantness +vacatable +vacate +vacated +vacates +vacating +vacation +vacationed +vacationeer +vacationeers +vacationer +vacationers +vacationing +vacationist +vacationists +vacationland +vacationlands +vacationless +vacations +vaccinal +vaccinate +vaccinated +vaccinates +vaccinating +vaccination +vaccinations +vaccinator +vaccinators +vaccine +vaccinee +vaccinees +vaccines +vaccinia +vaccinial +vaccinias +vacillant +vacillate +vacillated +vacillates +vacillating +vacillatingly +vacillation +vacillations +vacillator +vacillators +vacillatory +vacs +vacua +vacuities +vacuity +vacuo +vacuolar +vacuolate +vacuolated +vacuolation +vacuole +vacuoles +vacuolization +vacuous +vacuously +vacuousness +vacuum +vacuumed +vacuumes +vacuuming +vacuums +vade +vadose +vaduz +vagabond +vagabondage +vagabondages +vagabonded +vagabonding +vagabondish +vagabondism +vagabonds +vagal +vagally +vagaries +vagarious +vagariously +vagary +vagi +vagile +vagility +vagina +vaginae +vaginal +vaginally +vaginas +vaginate +vaginated +vaginectomies +vaginectomy +vaginismus +vaginismuses +vaginitis +vaginitises +vagotomies +vagotomy +vagotonia +vagotonic +vagotropic +vagrancies +vagrancy +vagrant +vagrantly +vagrants +vagrom +vague +vaguely +vagueness +vaguer +vaguest +vagus +vahine +vahines +vail +vailed +vailing +vails +vain +vainer +vainest +vainglories +vainglorious +vaingloriously +vaingloriousness +vainglory +vainly +vainness +vair +vairs +vaishnava +vaishnavas +vaishnavism +vaisya +vaisyas +valance +valanced +valances +valancing +vale +valediction +valedictions +valedictorian +valedictorians +valedictories +valedictory +valence +valences +valencia +valenciennes +valency +valentine +valentines +valera +valerate +valerates +valerian +valerians +valeric +vales +valet +valeted +valeting +valets +valetudinarian +valetudinarianism +valetudinarians +valetudinaries +valetudinary +valgoid +valgus +valhalla +valiance +valiancy +valiant +valiantly +valiantness +valiants +valid +validate +validated +validates +validating +validation +validations +validity +validly +validness +valine +valines +valinomycin +valinomycins +valise +valises +valium +valkyrie +valkyries +vallate +vallation +vallations +vallatory +vallecula +valleculae +vallecular +valleculate +vallences +vallencies +valletta +valley +valleyed +valleys +valois +valonia +valonias +valor +valorem +valorization +valorizations +valorize +valorized +valorizes +valorizing +valorous +valorously +valorousness +valors +valparaiso +valpolicella +valproate +valproates +valsalva +valse +valses +valuable +valuableness +valuables +valuably +valuate +valuated +valuates +valuating +valuation +valuational +valuationally +valuations +valuator +valuators +value +valued +valueless +valuelessness +valuer +valuers +values +valuing +valuta +valvar +valvate +valve +valved +valveless +valves +valving +valvula +valvulae +valvular +valvule +valvules +valvulitis +valvulitises +valvuloplasties +valvuloplasty +vambrace +vambraces +vamoose +vamoosed +vamooses +vamoosing +vamp +vamped +vamper +vampers +vamping +vampire +vampires +vampirical +vampirish +vampirism +vampish +vampishly +vamps +vampy +van +vanadate +vanadates +vanadic +vanadinite +vanadinites +vanadium +vanaspati +vanbrugh +vancomycin +vancomycins +vancouver +vanda +vandal +vandalic +vandalism +vandalistic +vandalization +vandalizations +vandalize +vandalized +vandalizes +vandalizing +vandals +vanderbilt +vandyke +vandyked +vandykes +vane +vaned +vanes +vang +vangs +vanguard +vanguardism +vanguardist +vanguardists +vanguards +vanilla +vanillas +vanillic +vanillin +vanir +vanish +vanished +vanisher +vanishers +vanishes +vanishing +vanishingly +vanishment +vanities +vanity +vanload +vanloads +vanned +vanner +vanners +vanning +vanpool +vanpooled +vanpooler +vanpoolers +vanpooling +vanpools +vanquish +vanquishable +vanquished +vanquisher +vanquishers +vanquishes +vanquishing +vanquishment +vans +vansittart +vantage +vantages +vanuatu +vanuatuan +vanuatuans +vanward +vapid +vapidity +vapidly +vapidness +vapor +vapored +vaporer +vaporers +vaporescence +vaporetti +vaporetto +vaporettos +vaporific +vaporing +vaporingly +vaporings +vaporish +vaporishness +vaporizable +vaporization +vaporizations +vaporize +vaporized +vaporizer +vaporizers +vaporizes +vaporizing +vaporosity +vaporous +vaporously +vaporousness +vapors +vaporware +vapory +vaquero +vaqueros +vara +varactor +varactors +varas +varia +variabilities +variability +variable +variableness +variables +variably +variance +variances +variant +variants +varias +variate +variates +variation +variational +variationally +variations +variceal +varicella +varicellas +varicellate +varicelloid +varices +varicocele +varicoceles +varicolored +varicose +varicosed +varicoses +varicosis +varicosities +varicosity +varicotomies +varicotomy +varied +variedly +variegate +variegated +variegates +variegating +variegation +variegations +variegator +variegators +varier +variers +varies +varietal +varietally +varietals +varieties +variety +variform +variola +variolas +variolate +variolated +variolates +variolating +variole +varioles +variolite +variolites +varioloid +varioloids +variolous +variometer +variometers +variorum +variorums +various +variously +variousness +varisized +varistor +varistors +varitype +varityped +varitypes +varityping +varix +varlet +varletry +varlets +varlettries +varmint +varmints +varnish +varnished +varnisher +varnishers +varnishes +varnishing +varnishy +varoom +varoomed +varooming +varooms +varsities +varsity +varsovian +varuna +varus +varve +varved +varves +vary +varying +varyingly +vas +vasa +vasal +vascula +vascular +vascularity +vascularization +vascularizations +vascularize +vascularized +vascularizes +vascularizing +vasculature +vasculatures +vasculitis +vasculitises +vasculum +vase +vasectomies +vasectomize +vasectomized +vasectomizes +vasectomizing +vasectomy +vaselike +vaseline +vases +vashon +vasoactive +vasoactivity +vasoconstriction +vasoconstrictions +vasoconstrictive +vasoconstrictor +vasoconstrictors +vasodilatation +vasodilatations +vasodilation +vasodilations +vasodilator +vasodilators +vasoligate +vasoligated +vasoligates +vasoligating +vasoligation +vasoligations +vasomotor +vasopressin +vasopressins +vasopressor +vasopressors +vasospasm +vasospasms +vasospastic +vasotocin +vasotocins +vasovagal +vassal +vassalage +vassals +vast +vaster +vastest +vastier +vastiest +vastities +vastitude +vastitudes +vastity +vastly +vastness +vasty +vat +vatic +vatical +vatican +vaticanism +vaticinal +vaticinate +vaticinated +vaticinates +vaticinating +vaticination +vaticinations +vaticinator +vaticinators +vats +vatted +vatting +vatu +vatus +vau +vaudeville +vaudevilles +vaudevillian +vaudevillians +vaudois +vaughan +vault +vaulted +vaulter +vaulters +vaulting +vaultingly +vaultings +vaults +vaulty +vaunt +vaunted +vaunter +vaunters +vauntful +vaunting +vauntingly +vaunts +vav +vavasor +vavasors +vavasour +vavasours +vcr +vd +ve +veadar +veal +vealer +vealers +vealy +vector +vectored +vectorial +vectorially +vectoring +vectorization +vectorizations +vectorize +vectorized +vectorizes +vectorizing +vectors +veda +vedalia +vedalias +vedanta +vedantic +vedantism +vedantist +vedantists +vedas +vedda +veddah +veddahs +veddas +veddoid +veddoids +vedette +vedettes +vedic +vee +veejay +veejays +veena +veenas +veep +veeps +veer +veered +veeries +veering +veeringly +veers +veery +vees +vega +vegan +veganism +vegans +vegas +vegetable +vegetables +vegetably +vegetal +vegetarian +vegetarianism +vegetarians +vegetate +vegetated +vegetates +vegetating +vegetation +vegetational +vegetations +vegetative +vegetatively +vegetativeness +vegetive +vegged +veggie +veggies +vegging +vegie +vegies +vehemence +vehemency +vehement +vehemently +vehicle +vehicles +vehicular +veil +veiled +veiling +veilings +veils +vein +veinal +veined +veiner +veiners +veinier +veiniest +veining +veinings +veinlet +veinlets +veins +veinstone +veinstones +veinule +veinules +veiny +vela +velamen +velamentous +velamina +velar +velaria +velarium +velarization +velarizations +velarize +velarized +velarizes +velarizing +velars +velasquez +velate +velcro +veld +velds +veldt +veldts +veliger +veligers +velleities +velleity +vellum +vellums +veloce +velocimeter +velocimeters +velocipede +velocipedes +velocities +velocity +velodrome +velodromes +velour +velours +velouté +velum +velums +velure +velures +velutinous +velvet +velveteen +velveteens +velvetier +velvetiest +velvetleaf +velvetleafs +velvetlike +velvets +velvety +vena +venae +venal +venalities +venality +venally +venatic +venatical +venation +venational +vend +venda +vendable +vendace +vendaces +vended +vendee +vendees +vender +venders +vendetta +vendettas +vendeuse +vendeuses +vendibility +vendible +vending +vendor +vendors +vends +vendue +vendues +vendôme +veneer +veneered +veneerer +veneerers +veneering +veneers +venenation +venenations +venene +venenes +venepuncture +venepunctures +venerability +venerable +venerableness +venerably +venerate +venerated +venerates +venerating +veneration +venerational +venerator +venerators +venereal +venereological +venereologist +venereologists +venereology +venereum +veneries +veneris +venery +venesection +venesections +veneti +venetia +venetian +venetians +venetic +veneto +venezia +venezuela +venezuelan +venezuelans +venge +vengeance +venged +vengeful +vengefully +vengefulness +venges +venging +venial +veniality +venially +venialness +venice +venin +venins +venipuncture +venipunctures +venire +venireman +veniremen +venires +venison +venisons +venite +venites +venn +venogram +venograms +venography +venom +venomous +venomously +venomousness +venose +venosity +venosus +venous +venously +venousness +vent +ventage +ventages +ventail +ventails +vented +venter +venters +ventifact +ventifacts +ventilate +ventilated +ventilates +ventilating +ventilation +ventilations +ventilator +ventilators +ventilatory +venting +ventless +ventrad +ventral +ventrally +ventrals +ventricle +ventricles +ventricose +ventricosity +ventricous +ventricular +ventriculi +ventriculus +ventriloquial +ventriloquially +ventriloquism +ventriloquist +ventriloquistic +ventriloquists +ventriloquize +ventriloquized +ventriloquizes +ventriloquizing +ventriloquy +ventrodorsal +ventrodorsally +ventrolateral +ventrolaterally +ventromedial +ventromedially +vents +venture +ventured +venturer +venturers +ventures +venturesome +venturesomely +venturesomeness +venturi +venturing +venturis +venturous +venturously +venturousness +venue +venues +venular +venule +venules +venus +venusberg +venushair +venusian +venusians +vera +veracious +veraciously +veraciousness +veracities +veracity +veranda +verandaed +verandah +verandahed +verandahs +verandas +verapamil +verapamils +veratridine +veratridines +veratrine +veratrines +veratrum +verb +verba +verbal +verbalism +verbalisms +verbalist +verbalistic +verbalists +verbalizable +verbalization +verbalizations +verbalize +verbalized +verbalizer +verbalizers +verbalizes +verbalizing +verbally +verbals +verbatim +verbaux +verbena +verbenas +verbiage +verbicide +verbicides +verbid +verbified +verbifies +verbify +verbifying +verbigeration +verbigerations +verbless +verbose +verbosely +verboseness +verbosity +verboten +verbs +verbum +verd +verdancy +verdant +verdantly +verde +verdean +verdeans +verderer +verderers +verderor +verderors +verdi +verdict +verdicts +verdigris +verdin +verdins +verditer +verditers +verdun +verdure +verdured +verdurous +verdurousness +verge +verged +verger +vergers +verges +verging +verglas +verglases +veridic +veridical +veridicality +veridically +verier +veriest +verifiability +verifiable +verifiableness +verifiably +verification +verifications +verificative +verified +verifier +verifiers +verifies +verify +verifying +verily +verisimilar +verisimilarly +verisimilitude +verisimilitudes +verisimilitudinous +verism +verismo +verismos +verist +veristic +verists +veritable +veritableness +veritably +verities +verity +verjuice +verjuices +verkhoyansk +verlaine +vermeer +vermeil +vermicelli +vermicidal +vermicide +vermicides +vermicular +vermicularly +vermiculate +vermiculated +vermiculates +vermiculating +vermiculation +vermiculations +vermiculite +vermiculites +vermiform +vermifuge +vermifuges +vermilion +vermilioned +vermilioning +vermilions +vermillion +vermillioned +vermillioning +vermillions +vermin +vermination +verminations +verminous +verminously +vermivorous +vermont +vermonter +vermonters +vermouth +vermouths +vernacle +vernacular +vernacularism +vernacularisms +vernacularize +vernacularized +vernacularizes +vernacularizing +vernacularly +vernaculars +vernal +vernalization +vernalizations +vernalize +vernalized +vernalizes +vernalizing +vernally +vernation +vernations +verner +vernicle +vernier +verniers +vernissage +vernissages +vernix +vernon +verona +veronese +veronica +veronicas +verruca +verrucae +verrucose +verrucous +vers +versa +versailles +versant +versants +versatile +versatilely +versatileness +versatility +verse +versed +verses +verset +versets +versicle +versicles +versicolor +versicolored +versicular +versification +versifications +versified +versifier +versifiers +versifies +versify +versifying +versine +versing +version +versional +versions +verso +versos +verst +versts +versus +vert +verte +vertebra +vertebrae +vertebral +vertebrally +vertebras +vertebrate +vertebrates +vertebration +vertebrations +vertex +vertexes +vertical +verticality +vertically +verticalness +verticals +vertices +verticil +verticillaster +verticillasters +verticillastrate +verticillate +verticillated +verticillately +verticillation +verticillations +verticillium +verticils +vertiginous +vertiginously +vertiginousness +vertigo +vertigoes +vertigos +verts +vertu +vertus +vervain +vervains +verve +vervet +vervets +very +vesalius +vesica +vesicae +vesical +vesicant +vesicants +vesicate +vesicated +vesicates +vesicating +vesication +vesications +vesicatories +vesicatory +vesicle +vesicles +vesicular +vesicularity +vesicularly +vesiculate +vesiculated +vesiculates +vesiculating +vesiculation +vesiculations +vespasian +vesper +vesperal +vesperals +vespers +vespertilian +vespertilionid +vespertilionids +vespertinal +vespertine +vespiaries +vespiary +vespid +vespids +vespine +vespucci +vessel +vessels +vest +vesta +vestal +vestals +vestas +vested +vestee +vestees +vestiaries +vestiary +vestibular +vestibule +vestibuled +vestibules +vestibulocochlear +vestige +vestiges +vestigia +vestigial +vestigially +vestigium +vesting +vestings +vestlike +vestment +vestmental +vestments +vestries +vestry +vestryman +vestrymen +vestrywoman +vestrywomen +vests +vesture +vestured +vestures +vesturing +vesuvian +vesuvianite +vesuvianites +vesuvians +vesuvius +vet +vetch +vetches +vetchling +vetchlings +veteran +veterans +veterinarian +veterinarians +veterinaries +veterinary +vetiver +vetivers +vetivert +vetiverts +veto +vetoed +vetoer +vetoers +vetoes +vetoing +vets +vetted +vetting +vex +vexation +vexations +vexatious +vexatiously +vexatiousness +vexed +vexedly +vexer +vexers +vexes +vexilla +vexillaries +vexillary +vexillate +vexillologic +vexillological +vexillologist +vexillologists +vexillology +vexillum +vexing +vexingly +vext +vhf +via +viability +viable +viably +viaduct +viaducts +vial +vialed +vialing +vialled +vialling +vials +viand +viands +viatic +viatica +viatical +viaticum +viaticums +vibe +vibes +vibist +vibists +vibracula +vibracular +vibraculoid +vibraculum +vibraharp +vibraharpist +vibraharpists +vibraharps +vibrance +vibrancy +vibrant +vibrantly +vibraphone +vibraphones +vibraphonist +vibraphonists +vibrate +vibrated +vibrates +vibratile +vibratility +vibrating +vibration +vibrational +vibrationless +vibrations +vibrative +vibrato +vibratoless +vibrator +vibrators +vibratory +vibratos +vibrio +vibrioid +vibrion +vibrionic +vibrions +vibrios +vibrioses +vibriosis +vibrissa +vibrissae +vibronic +viburnum +vicar +vicarage +vicarages +vicarate +vicarates +vicarial +vicariance +vicariances +vicariant +vicariants +vicariate +vicariates +vicarious +vicariously +vicariousness +vicars +vicarship +vice +viced +vicegeral +vicegerencies +vicegerency +vicegerent +vicegerents +vicenary +vicennial +vicenza +viceregal +viceregally +vicereine +vicereines +viceroy +viceroyalties +viceroyalty +viceroys +viceroyship +viceroyships +vices +vichy +vichyssoise +vichyssoises +vicinage +vicinal +vicing +vicinities +vicinity +vicious +viciously +viciousness +vicissitude +vicissitudes +vicissitudinary +vicissitudinous +victim +victimhood +victimization +victimizations +victimize +victimized +victimizer +victimizers +victimizes +victimizing +victimless +victimologist +victimologists +victimology +victims +victor +victoria +victorian +victoriana +victorianism +victorianisms +victorianization +victorianizations +victorianize +victorianized +victorianizes +victorianizing +victorians +victorias +victories +victorious +victoriously +victoriousness +victors +victory +victrola +victual +victualed +victualer +victualers +victualing +victualled +victualler +victuallers +victualling +victuals +vicuna +vicunas +vicuña +vicuñas +vidalia +vide +videlicet +video +videocassette +videocassettes +videoconference +videoconferences +videoconferencing +videodisc +videodiscs +videodisk +videodisks +videogenic +videographer +videographers +videography +videoland +videophile +videophiles +videophone +videophones +videos +videotape +videotaped +videotapes +videotaping +videotex +videotexs +videotext +videotexts +vidette +videttes +vidicon +vidicons +viduity +vie +vied +vienna +viennese +vientiane +vier +viers +vies +vietcong +vietminh +vietnam +vietnamese +vietnamization +vietnamize +vietnamized +vietnamizes +vietnamizing +view +viewable +viewdata +viewed +viewer +viewers +viewership +viewfinder +viewfinders +viewier +viewiest +viewing +viewings +viewless +viewlessly +viewpoint +viewpoints +views +viewy +vig +viga +vigas +vigesimal +vigil +vigilance +vigilant +vigilante +vigilanteism +vigilantes +vigilantism +vigilantly +vigils +vigintillion +vigneron +vignerons +vignette +vignetted +vignetter +vignetters +vignettes +vignetting +vignettist +vignettists +vigor +vigorish +vigoroso +vigorous +vigorously +vigorousness +viking +vikings +vilayet +vilayets +vile +vilely +vileness +viler +vilest +vilification +vilifications +vilified +vilifier +vilifiers +vilifies +vilify +vilifying +vilipend +vilipended +vilipending +vilipends +vill +villa +villadom +village +villager +villagers +villagery +villages +villain +villainage +villainages +villainess +villainies +villainous +villainously +villainousness +villains +villainy +villanella +villanelle +villanelles +villanueva +villas +villatic +villein +villeinage +villeinages +villeins +villenage +villeneuve +villi +villiers +villiform +villon +villose +villosities +villosity +villous +villously +vills +villus +vim +viminal +vin +vina +vinaceous +vinaigrette +vinaigrettes +vinal +vinas +vinasse +vinasses +vinblastine +vinblastines +vinca +vincent +vincentian +vincentians +vinci +vincibility +vincible +vincibly +vincristine +vincristines +vincula +vinculum +vinculums +vindaloo +vindicable +vindicate +vindicated +vindicates +vindicating +vindication +vindications +vindicator +vindicators +vindicatory +vindictive +vindictively +vindictiveness +vine +vined +vinedresser +vinedressers +vinegar +vinegared +vinegarish +vinegarone +vinegarones +vinegarroon +vinegarroons +vinegars +vinegary +vineries +vinery +vines +vineyard +vineyardist +vineyardists +vineyards +vinic +vinicultural +viniculture +vinicultures +viniculturist +viniculturists +vinier +viniest +vinifera +viniferous +vinification +vinifications +vinified +vinifies +vinify +vinifying +vining +vino +vinogradoff +vinometer +vinometers +vinos +vinosities +vinosity +vinous +vinously +vintage +vintager +vintagers +vintages +vintner +vintners +viny +vinyl +vinylic +vinylidene +vinylidenes +vinyls +viol +viola +violability +violable +violableness +violably +violaceous +violas +violate +violated +violates +violating +violation +violations +violative +violator +violators +viole +violence +violent +violently +violet +violets +violin +violinist +violinistic +violinists +violinmaker +violinmakers +violinmaking +violins +violist +violists +violoncellist +violoncellists +violoncello +violoncellos +violone +violones +viols +viomycin +viomycins +viosterol +viosterols +viper +viperfish +viperfishes +viperine +viperish +viperous +viperously +vipers +viraginous +virago +viragoes +viragos +viral +virally +virelay +virelays +viremia +viremias +viremic +vireo +vireos +vires +virescence +virescent +virga +virgas +virgate +virgates +virgil +virgilia +virgilian +virgin +virginal +virginalist +virginalists +virginally +virginals +virginia +virginiamycin +virginiamycins +virginian +virginians +virginities +virginity +virgins +virgo +virgoan +virgoans +virgos +virgulate +virgule +virgules +viricidal +viricide +viricides +virid +viridescence +viridescent +viridian +viridity +virile +virilely +viriles +virilis +virilism +virilisms +virility +virilization +virilizations +virilize +virilized +virilizes +virilizing +virion +virions +virogene +virogenes +virogeneses +virogenesis +virogenetic +virogenic +viroid +viroids +virologic +virological +virologically +virologist +virologists +virology +viroses +virosis +virtu +virtual +virtuality +virtualizes +virtually +virtue +virtueless +virtues +virtuosa +virtuosas +virtuosi +virtuosic +virtuosically +virtuosities +virtuosity +virtuoso +virtuosos +virtuous +virtuously +virtuousness +virtus +virucidal +virucide +virucides +virulence +virulency +virulent +virulently +viruliferous +virus +viruses +vis +visa +visaed +visage +visaged +visages +visaing +visard +visards +visas +visayan +visayans +viscacha +viscachas +viscera +visceral +viscerally +visceromotor +viscid +viscidity +viscidly +viscidness +viscoelastic +viscoelasticity +viscometer +viscometers +viscometric +viscometry +visconti +viscose +viscosimeter +viscosimeters +viscosimetric +viscosities +viscosity +viscount +viscountcies +viscountcy +viscountess +viscountesses +viscounties +viscounts +viscounty +viscous +viscously +viscousness +viscus +vise +vised +viseed +viseing +viselike +vises +vishnu +visibilities +visibility +visible +visibleness +visibly +visigoth +visigothic +visigoths +vising +vision +visional +visionally +visionaries +visionariness +visionary +visioned +visioning +visionless +visions +visit +visitable +visitant +visitants +visitation +visitational +visitations +visitatorial +visited +visiting +visitor +visitors +visits +visor +visored +visoring +visorless +visors +vista +vistaed +vistas +vistula +visual +visuality +visualizable +visualization +visualizations +visualize +visualized +visualizer +visualizers +visualizes +visualizing +visually +visualness +visuals +visuomotor +visuomotors +visuospatial +vita +vitae +vitaes +vital +vitalism +vitalist +vitalistic +vitalists +vitalities +vitality +vitalization +vitalizations +vitalize +vitalized +vitalizer +vitalizers +vitalizes +vitalizing +vitally +vitalness +vitals +vitamer +vitameric +vitamers +vitamin +vitaminic +vitamins +vitellaria +vitellarium +vitellariums +vitellin +vitelline +vitellines +vitellins +vitellogenesis +vitellogenetic +vitellogenic +vitellus +vitelluses +viterbo +vitiable +vitiate +vitiated +vitiates +vitiating +vitiation +vitiations +vitiator +vitiators +viticultural +viticulturally +viticulture +viticulturist +viticulturists +vitiligo +vitiligos +vitrectomies +vitrectomy +vitreosity +vitreous +vitreousness +vitrescence +vitrescent +vitrifaction +vitrifactions +vitrifiability +vitrifiable +vitrification +vitrifications +vitrified +vitrifies +vitrify +vitrifying +vitrine +vitrines +vitriol +vitrioled +vitriolic +vitrioling +vitriolled +vitriolling +vitriols +vitro +vitruvius +vitta +vittae +vittate +vittle +vittles +vituline +vituperate +vituperated +vituperates +vituperating +vituperation +vituperations +vituperative +vituperatively +vituperativeness +vituperator +vituperators +vituperatory +vitus +viva +vivace +vivacious +vivaciously +vivaciousness +vivacity +vivaldi +vivandière +vivandières +vivant +vivants +vivaria +vivarium +vivariums +vivax +vivaxs +vivendi +viverrid +viverrids +viverrine +viverrines +vivian +vivid +vivider +vividest +vividly +vividness +vivific +vivification +vivifications +vivified +vivifier +vivifiers +vivifies +vivify +vivifying +viviparity +viviparous +viviparously +vivisect +vivisected +vivisecting +vivisection +vivisectional +vivisectionally +vivisectionist +vivisectionists +vivisector +vivisectors +vivisects +vivo +vivos +vivre +vixen +vixenish +vixenishly +vixenishness +vixens +viz +vizard +vizards +vizcacha +vizier +vizierate +vizierial +viziers +viziership +vizor +vizored +vizoring +vizors +vizsla +vizslas +vladivostok +vlaminck +vocable +vocables +vocabular +vocabularies +vocabulary +vocal +vocalic +vocalically +vocalism +vocalist +vocalistic +vocalists +vocality +vocalization +vocalizations +vocalize +vocalized +vocalizer +vocalizers +vocalizes +vocalizing +vocally +vocalness +vocals +vocation +vocational +vocationalism +vocationalisms +vocationalist +vocationalists +vocationally +vocations +vocative +vocatively +vocatives +voce +vociferant +vociferate +vociferated +vociferates +vociferating +vociferation +vociferations +vociferator +vociferators +vociferous +vociferously +vociferousness +vocoder +vocoders +vodka +vodkas +vodoun +vodouns +vodun +voduns +vogue +vogues +voguish +voguishly +voguishness +vogul +voguls +voice +voiced +voicedness +voiceful +voicefulness +voiceless +voicelessly +voicelessness +voiceover +voiceovers +voiceprint +voiceprints +voicer +voicers +voices +voicing +voicings +void +voidable +voidableness +voidance +voidances +voided +voider +voiders +voiding +voidness +voids +voile +voiles +voilà +voir +volans +volant +volante +volapük +volar +volatile +volatileness +volatiles +volatility +volatilizable +volatilization +volatilizations +volatilize +volatilized +volatilizer +volatilizers +volatilizes +volatilizing +volcanic +volcanically +volcanicity +volcanism +volcanisms +volcanization +volcanizations +volcanize +volcanized +volcanizes +volcanizing +volcano +volcanoes +volcanogenic +volcanologic +volcanological +volcanologist +volcanologists +volcanology +volcanos +vole +volens +volente +voles +volga +volgograd +volitant +volitantes +volitation +volitational +volitations +volition +volitional +volitionally +volitive +volkslied +volkslieder +volkswagen +volkswagens +volley +volleyball +volleyballer +volleyballers +volleyballs +volleyed +volleyer +volleyers +volleying +volleys +volplane +volplaned +volplanes +volplaning +volpone +volsci +volscian +volscians +volt +volta +voltage +voltages +voltaic +voltaire +volte +voltes +voltmeter +voltmeters +volts +volubility +voluble +volubleness +volubly +volume +volumed +volumes +volumeter +volumeters +volumetric +volumetrically +voluming +voluminosity +voluminous +voluminously +voluminousness +volumnia +voluntaries +voluntarily +voluntariness +voluntarism +voluntarist +voluntaristic +voluntarists +voluntary +voluntaryism +voluntaryist +voluntaryists +volunteer +volunteered +volunteering +volunteerism +volunteers +voluptuaries +voluptuary +voluptuous +voluptuously +voluptuousness +volute +voluted +volutes +volutin +volutins +volution +volutions +volva +volvas +volvate +volvent +volvents +volvox +volvoxes +volvulus +volvuluses +vomer +vomerine +vomers +vomica +vomicae +vomit +vomited +vomiter +vomiters +vomiting +vomitive +vomitives +vomitories +vomitory +vomits +vomiturition +vomituritions +vomitus +vomituses +von +voodoo +voodooed +voodooing +voodooism +voodooist +voodooistic +voodooists +voodoos +voracious +voraciously +voraciousness +voracity +vorlage +vorlages +vortex +vortexes +vortical +vortically +vorticella +vorticellae +vorticellas +vortices +vorticism +vorticist +vorticists +vorticity +vorticose +vortigern +vortiginous +vosges +votable +votaress +votaresses +votaries +votarist +votarists +votary +vote +voteable +voted +voteless +voter +voters +votes +voting +votive +votively +votiveness +voto +votos +vouch +vouched +vouchee +vouchees +voucher +vouchered +vouchering +vouchers +vouches +vouching +vouchsafe +vouchsafed +vouchsafement +vouchsafes +vouchsafing +voussoir +voussoirs +vouvray +vouvrays +vow +vowed +vowel +vowelization +vowelizations +vowelize +vowelized +vowelizes +vowelizing +vowels +vower +vowers +vowing +vows +vox +voyage +voyaged +voyager +voyagers +voyages +voyageur +voyageurs +voyaging +voyeur +voyeurism +voyeuristic +voyeuristically +voyeurs +vroom +vroomed +vrooming +vrooms +vu +vug +vuggy +vugs +vulcan +vulcanian +vulcanicity +vulcanism +vulcanisms +vulcanite +vulcanizable +vulcanizate +vulcanizates +vulcanization +vulcanizations +vulcanize +vulcanized +vulcanizer +vulcanizers +vulcanizes +vulcanizing +vulcanologist +vulcanologists +vulcanology +vulgar +vulgarian +vulgarians +vulgaris +vulgarism +vulgarisms +vulgarities +vulgarity +vulgarization +vulgarizations +vulgarize +vulgarized +vulgarizer +vulgarizers +vulgarizes +vulgarizing +vulgarly +vulgarness +vulgate +vulgates +vulgus +vulnerabilities +vulnerability +vulnerable +vulnerableness +vulnerably +vulneraries +vulnerary +vulpecula +vulpecular +vulpine +vulture +vultures +vulturine +vulturish +vulturous +vulva +vulvae +vulval +vulvar +vulvas +vulvate +vulvectomies +vulvectomy +vulviform +vulvitis +vulvitises +vulvovaginitis +vulvovaginitises +vying +vänern +vättern +vérité +véronique +w +waals +wabanaki +wabanakis +wabble +wabbled +wabbles +wabbling +wac +wack +wacked +wackier +wackiest +wackily +wackiness +wacko +wackos +wacks +wacky +waco +wacs +wad +wadable +wadded +waddenzee +wadder +wadders +waddied +waddies +wadding +waddle +waddled +waddler +waddlers +waddles +waddling +waddy +waddying +wade +wadeable +waded +wader +waders +wades +wadi +wadies +wading +wadis +wadmal +wadmel +wadmol +wads +wady +waf +wafer +wafered +wafering +wafers +waffle +waffled +waffler +wafflers +waffles +wafflestomper +wafflestompers +waffling +wafflingly +waffly +wafs +waft +waftage +wafted +wafter +wafters +wafting +wafts +wafture +wag +wage +waged +wageless +wager +wagered +wagerer +wagerers +wagering +wagers +wages +wageworker +wageworkers +wagged +wagger +waggeries +waggers +waggery +wagging +waggish +waggishly +waggishness +waggle +waggled +waggles +waggling +waggly +waging +wagner +wagnerian +wagnerians +wagnerite +wagnerites +wagon +wagoned +wagoner +wagoners +wagonette +wagonettes +wagoning +wagonload +wagonloads +wagons +wags +wagtail +wagtails +wahabi +wahabis +wahhabi +wahhabis +wahhabism +wahhabite +wahhabites +wahine +wahines +wahoo +wahoos +wahpekute +wahpekutes +wahpeton +wahpetons +wahwah +waianae +waif +waiflike +waifs +waikiki +wail +wailed +wailer +wailers +wailful +wailfully +wailing +wailingly +wails +wain +wains +wainscot +wainscoted +wainscoting +wainscots +wainscotted +wainscotting +wainwright +wainwrights +waist +waistband +waistbands +waistcloth +waistcloths +waistcoat +waistcoated +waistcoats +waisted +waistless +waistline +waistlines +waists +wait +waited +waiter +waiters +waiting +waitings +waitpeople +waitperson +waitpersons +waitress +waitresses +waitron +waitrons +waits +waive +waived +waiver +waivers +waives +waiving +wakame +wakames +wakashan +wake +waked +wakeful +wakefully +wakefulness +wakeless +waken +wakened +wakener +wakeners +wakening +wakens +waker +wakers +wakes +wakeup +waking +walachia +walapai +walapais +walcheren +walden +waldenses +waldensian +waldensians +waldorf +wale +waled +waler +walers +wales +walhalla +waling +walk +walkability +walkable +walkabout +walkabouts +walkathon +walkathons +walkaway +walkaways +walked +walker +walkers +walkie +walking +walkingstick +walkingsticks +walkman +walkout +walkouts +walkover +walkovers +walks +walkup +walkups +walkway +walkways +walky +walkyrie +wall +walla +wallabies +wallaby +wallace +wallachia +wallachian +wallachians +wallah +wallahs +wallaroo +wallaroos +wallas +wallboard +walled +wallenberg +wallet +wallets +walleye +walleyed +walleyes +wallflower +wallflowers +walling +wallis +wallless +wallonia +walloon +walloons +wallop +walloped +walloper +wallopers +walloping +wallopings +wallops +wallow +wallowa +wallowed +wallower +wallowers +wallowing +wallows +wallpaper +wallpapered +wallpapering +wallpapers +walls +walnut +walnuts +walpole +walpurgis +walpurgisnacht +walrus +walruses +walsingham +walsy +walter +walton +waltz +waltzed +waltzer +waltzers +waltzes +waltzing +wamble +wambled +wambles +wambliness +wambling +wamblingly +wambly +wampanoag +wampanoags +wampum +wampumpeag +wan +wand +wander +wandered +wanderer +wanderers +wandering +wanderingly +wanderings +wanderlust +wanderoo +wanderoos +wanders +wandflower +wandflowers +wands +wane +waned +wanes +wangle +wangled +wangler +wanglers +wangles +wangling +wanigan +wanigans +waning +wanion +wankel +wanly +wanna +wanned +wanner +wanness +wannest +wannigan +wannigans +wanning +wans +want +wanted +wanter +wanters +wanting +wantless +wantlessness +wanton +wantoned +wantoner +wantoners +wantoning +wantonly +wantonness +wantons +wants +wapentake +wapentakes +wapiti +wapitis +wappenschawing +wappinger +wappingers +wapsipinicon +war +warble +warbled +warbler +warblers +warbles +warbling +warbonnet +warbonnets +warburg +ward +warded +warden +wardenries +wardenry +wardens +wardenship +warder +warders +wardership +wardian +warding +wardress +wardresses +wardrobe +wardrobes +wardroom +wardrooms +wards +wardship +wardships +ware +wared +warehouse +warehoused +warehouseman +warehousemen +warehouser +warehousers +warehouses +warehousing +wareroom +warerooms +wares +warfare +warfarin +warfront +warfronts +warhead +warheads +warhorse +warhorses +warier +wariest +warily +wariness +waring +warison +warless +warlike +warlock +warlocks +warlord +warlordism +warlords +warm +warmed +warmer +warmers +warmest +warmhearted +warmheartedly +warmheartedness +warming +warmish +warmly +warmness +warmonger +warmongering +warmongers +warmouth +warmouths +warms +warmth +warmup +warmups +warn +warned +warner +warners +warning +warningly +warnings +warns +warp +warpage +warpath +warpaths +warped +warper +warpers +warping +warplane +warplanes +warps +warrant +warrantability +warrantable +warrantableness +warrantably +warranted +warrantee +warrantees +warranter +warranters +warranties +warranting +warrantless +warrantor +warrantors +warrants +warranty +warred +warren +warrener +warreners +warrens +warring +warrior +warriors +wars +warsaw +warship +warships +wart +warted +warthog +warthogs +wartime +wartless +warts +warty +warwickshire +wary +was +wasabi +wasatch +wash +washability +washable +washbasin +washbasins +washboard +washboards +washbowl +washbowls +washcloth +washcloths +washday +washdays +washed +washer +washerman +washermen +washers +washerwoman +washerwomen +washes +washhouse +washhouses +washier +washiest +washiness +washing +washings +washington +washingtonian +washingtonians +washout +washouts +washrag +washrags +washroom +washrooms +washstand +washstands +washtub +washtubs +washup +washups +washwoman +washwomen +washy +wasn +wasn't +wasp +waspdom +waspier +waspiest +waspish +waspishly +waspishness +wasplike +wasps +waspy +wassail +wassailed +wassailer +wassailers +wassailing +wassails +wassermann +wastage +waste +wastebasket +wastebaskets +wasted +wasteful +wastefully +wastefulness +wasteland +wastelands +wastepaper +waster +wasters +wastes +wastewater +wastewaters +wasting +wastingly +wastrel +wastrels +watap +watape +watapes +wataps +watch +watchable +watchband +watchbands +watchcase +watchcases +watchdog +watchdogged +watchdogging +watchdogs +watched +watcher +watchers +watches +watcheye +watcheyes +watchful +watchfully +watchfulness +watching +watchmaker +watchmakers +watchmaking +watchman +watchmen +watchstrap +watchstraps +watchtower +watchtowers +watchword +watchwords +water +waterbed +waterbeds +waterbird +waterbirds +waterborne +waterbuck +waterbucks +waterbus +waterbuses +waterbusses +watercolor +watercolorist +watercolorists +watercolors +watercooler +watercoolers +watercourse +watercourses +watercraft +watercrafts +watercress +waterdog +waterdogging +waterdogs +watered +waterer +waterers +waterfall +waterfalls +waterfinder +waterfinders +waterflood +waterflooded +waterflooding +waterfloods +waterfowl +waterfowler +waterfowlers +waterfowling +waterfowls +waterfront +waterfronts +watergate +watergates +waterhole +waterholes +waterier +wateriest +waterily +wateriness +watering +waterish +waterishness +waterleaf +waterleafs +waterless +waterlessness +waterline +waterlines +waterlog +waterlogged +waterlogging +waterlogs +waterloo +waterloos +waterman +watermanship +watermark +watermarked +watermarking +watermarks +watermelon +watermelons +watermen +waterpower +waterproof +waterproofed +waterproofer +waterproofers +waterproofing +waterproofness +waterproofs +waters +waterscape +waterscapes +watershed +watersheds +waterside +watersides +waterskiing +waterspout +waterspouts +waterthrush +waterthrushes +watertight +watertightness +waterway +waterways +waterweed +waterweeds +waterwheel +waterwheels +waterworks +waterworn +watery +waterzooi +watlings +watson +watt +wattage +wattages +watteau +wattle +wattlebird +wattlebirds +wattled +wattles +wattling +wattmeter +wattmeters +watts +watusi +watusis +waugh +wave +waveband +wavebands +waved +waveform +waveforms +waveguide +waveguides +wavelength +wavelengths +waveless +wavelessly +wavelet +wavelets +wavelike +wavell +waver +wavered +waverer +waverers +wavering +waveringly +waverley +wavers +wavery +waves +waveshape +waveshapes +wavier +waviest +wavily +waviness +waving +wavy +waw +wax +waxberries +waxberry +waxbill +waxbills +waxed +waxen +waxer +waxers +waxes +waxier +waxiest +waxiness +waxing +waxlike +waxwing +waxwings +waxwork +waxworks +waxy +way +waybill +waybills +wayfarer +wayfarers +wayfaring +waylaid +waylay +waylayer +waylayers +waylaying +waylays +wayless +waypoint +waypoints +ways +wayside +waysides +wayward +waywardly +waywardness +wayworn +waziristan +wazoo +wazoos +we +we'd +we'll +we're +we've +weak +weaken +weakened +weakener +weakeners +weakening +weakens +weaker +weakest +weakfish +weakfishes +weakhearted +weakish +weaklier +weakliest +weakliness +weakling +weaklings +weakly +weakness +weaknesses +weakon +weakons +weakside +weal +weald +wealds +wealth +wealthier +wealthiest +wealthily +wealthiness +wealthy +wean +weaned +weaner +weaners +weaning +weanling +weanlings +weans +weapon +weaponed +weaponeer +weaponeering +weaponeers +weaponing +weaponless +weaponry +weapons +wear +wearability +wearable +wearables +wearer +wearers +wearied +wearier +wearies +weariest +weariful +wearifully +wearifulness +weariless +wearilessly +wearilessness +wearily +weariness +wearing +wearingly +wearisome +wearisomely +wearisomeness +wears +weary +wearying +weasand +weasands +weasel +weaseled +weaseling +weaselled +weaselling +weaselly +weasels +weasely +weather +weatherability +weatherboard +weatherboarded +weatherboarding +weathercast +weathercaster +weathercasters +weathercasts +weathercock +weathercocked +weathercocking +weathercocks +weathered +weatherglass +weatherglasses +weathering +weatherization +weatherizations +weatherize +weatherized +weatherizes +weatherizing +weatherliness +weatherly +weatherman +weathermen +weatherperson +weatherproof +weatherproofed +weatherproofing +weatherproofness +weatherproofs +weathers +weathervane +weathervanes +weatherworn +weave +weaved +weaver +weaverbird +weaverbirds +weavers +weaves +weaving +weavings +web +webbed +webbier +webbiest +webbing +webbings +webby +weber +webers +webfed +webfeet +webfoot +weblike +webs +webster +websters +webworm +webworms +weck +wecks +wed +wedded +weddell +wedder +wedders +wedding +weddings +wedel +wedeled +wedelling +wedeln +wedelns +wedels +wedge +wedged +wedges +wedgie +wedgies +wedging +wedgwood +wedgy +wedlock +wednesday +wednesdays +weds +wee +weed +weeded +weeder +weeders +weedier +weediest +weedily +weediness +weeding +weeds +weedy +week +weekday +weekdays +weekend +weekended +weekender +weekenders +weekending +weekends +weeklies +weeklong +weekly +weeknight +weeknights +weeks +weenie +weenier +weenies +weeniest +weensy +weeny +weep +weeper +weepers +weepie +weepier +weepies +weepiest +weeping +weeps +weepy +weer +weest +weever +weevers +weevil +weevilly +weevils +weevily +weft +wefts +wegener +wehrmacht +weigela +weigelas +weigh +weighable +weighed +weigher +weighers +weighing +weighs +weight +weighted +weightier +weightiest +weightily +weightiness +weighting +weightings +weightless +weightlessly +weightlessness +weightlifter +weightlifters +weightlifting +weights +weighty +weil +weil's +weimar +weimaraner +weimaraners +weinberg +weiner +weiners +weir +weird +weirder +weirdest +weirdie +weirdies +weirdly +weirdness +weirdnesses +weirdo +weirdoes +weirdos +weirdy +weirs +weisenheimer +weisenheimers +weismann +weismannism +wejack +wejacks +weka +wekas +welch +welched +welches +welching +welcome +welcomed +welcomely +welcomeness +welcomer +welcomers +welcomes +welcoming +weld +weldable +welded +welder +welders +welding +weldment +weldments +weldor +weldors +welds +welfare +welfarism +welfarist +welfarists +welkin +welkins +well +welladay +wellaway +wellaways +wellbeing +wellborn +welled +wellerism +wellerisms +wellhead +wellheads +wellie +wellies +welling +wellington +wellingtons +wellness +wells +wellspring +wellsprings +welly +welsbach +welsh +welshed +welsher +welshers +welshes +welshing +welshman +welshmen +welshwoman +welshwomen +welt +weltanschauung +weltanschauungen +weltanschauungs +welted +welter +weltered +weltering +welters +welterweight +welterweights +welting +welts +weltschmerz +wen +wenceslas +wench +wenched +wencher +wenchers +wenches +wenching +wend +wended +wending +wendish +wends +wens +went +wentletrap +wentletraps +wept +were +weregild +weregilds +weren +weren't +werewolf +werewolves +wergeld +wergelds +wergild +wergilds +werner +wernerite +wernerites +wernicke +werwolf +werwolves +weser +weskit +weskits +wesley +wesleyan +wesleyanism +wesleyans +west +westbound +wester +westered +westering +westerlies +westerly +western +westerner +westerners +westernization +westernizations +westernize +westernized +westernizes +westernizing +westernmost +westernness +westerns +westers +westing +westinghouse +westings +westphalia +westphalian +westphalians +westward +westwardly +westwards +wet +wetback +wetbacks +wether +wethers +wetland +wetlands +wetly +wetness +wets +wetsuit +wetsuits +wettability +wettable +wetted +wetter +wetterhorn +wetters +wettest +wetting +wettings +wettish +whack +whacked +whacker +whackers +whackier +whackiest +whacking +whacko +whackos +whacks +whacky +whale +whaleback +whalebacks +whaleboat +whaleboats +whalebone +whalebones +whaled +whalelike +whaler +whalers +whales +whaling +wham +whammed +whammies +whamming +whammo +whammy +whams +whang +whanged +whangee +whangees +whanging +whangs +whap +whapped +whapping +whaps +wharf +wharfage +wharfed +wharfing +wharfinger +wharfingers +wharfmaster +wharfmasters +wharfs +wharves +what +what'd +what're +what's +whatchamacallit +whatchamacallum +whatever +whatness +whatnot +whatnots +whatsis +whatsit +whatsits +whatsoever +wheal +wheals +wheat +wheatear +wheatears +wheaten +wheatgrass +wheatstone +wheatworm +wheatworms +whee +wheedle +wheedled +wheedler +wheedlers +wheedles +wheedling +wheedlingly +wheel +wheelbarrow +wheelbarrows +wheelbase +wheelchair +wheelchairs +wheeled +wheeler +wheelers +wheelhorse +wheelhorses +wheelhouse +wheelhouses +wheelie +wheelies +wheeling +wheelings +wheelless +wheelman +wheelmen +wheels +wheelsman +wheelsmen +wheelwork +wheelworks +wheelwright +wheelwrights +wheeze +wheezed +wheezer +wheezers +wheezes +wheezier +wheeziest +wheezily +wheeziness +wheezing +wheezingly +wheezy +whelk +whelks +whelky +whelm +whelmed +whelming +whelms +whelp +whelped +whelping +whelps +when +whence +whencesoever +whenever +whensoever +where +where'd +where're +where's +whereabout +whereabouts +whereas +whereat +whereby +wherefore +wherefores +wherefrom +wherein +whereinto +whereof +whereon +wheresoever +wherethrough +whereto +whereunto +whereupon +wherever +wherewith +wherewithal +wherries +wherry +whet +whether +whets +whetstone +whetstones +whetted +whetter +whetters +whetting +whew +whey +wheyey +wheylike +which +whichever +whichsoever +whicker +whickered +whickering +whickers +whidah +whidahs +whidbey +whiff +whiffed +whiffer +whiffers +whiffet +whiffets +whiffing +whiffle +whiffled +whiffler +whifflers +whiffles +whiffletree +whiffling +whiffs +whig +whiggery +whiggish +whiggism +whigs +while +whiled +whiles +whiling +whilom +whilst +whim +whimbrel +whimbrels +whimper +whimpered +whimperer +whimperers +whimpering +whimperingly +whimpers +whims +whimsey +whimseys +whimsical +whimsicalities +whimsicality +whimsically +whimsicalness +whimsies +whimsy +whin +whinchat +whinchats +whine +whined +whiner +whiners +whines +whiney +whing +whinge +whinged +whingeing +whinges +whinging +whinier +whiniest +whininess +whining +whiningly +whinnied +whinnies +whinny +whinnying +whins +whinstone +whinstones +whiny +whip +whipcord +whipcords +whiplash +whiplashes +whiplike +whipped +whipper +whippers +whippersnapper +whippersnappers +whippet +whippets +whippier +whippiest +whipping +whippings +whippletree +whippletrees +whippoorwill +whippoorwills +whippy +whips +whipsaw +whipsawed +whipsawing +whipsawn +whipsaws +whipstall +whipstalls +whipstitch +whipstitched +whipstitches +whipstitching +whipstock +whipstocks +whipt +whiptail +whiptails +whipworm +whipworms +whir +whirl +whirled +whirler +whirlers +whirlies +whirligig +whirligigs +whirling +whirlpool +whirlpools +whirls +whirlwind +whirlwinds +whirly +whirlybird +whirlybirds +whirr +whirred +whirring +whirrs +whirs +whish +whished +whishes +whishing +whisk +whiskbroom +whiskbrooms +whisked +whisker +whiskered +whiskerless +whiskers +whiskery +whiskey +whiskeys +whiskies +whisking +whisks +whisky +whisper +whispered +whisperer +whisperers +whispering +whisperingly +whisperings +whispers +whispery +whist +whistle +whistleable +whistleblower +whistleblowers +whistled +whistler +whistlers +whistles +whistling +whit +white +whitebait +whitebark +whitebeard +whitebeards +whitecap +whitecaps +whited +whiteface +whitefaces +whitefish +whitefishes +whiteflies +whitefly +whitefriars +whitehall +whitehead +whiteheads +whitehorse +whitely +whiten +whitened +whitener +whiteners +whiteness +whitening +whitens +whiteout +whiteouts +whiteprint +whiteprints +whiter +whites +whitesmith +whitesmiths +whitest +whitetail +whitetails +whitethroat +whitethroats +whitewall +whitewalls +whitewash +whitewashed +whitewasher +whitewashers +whitewashes +whitewashing +whitewater +whitewing +whitewings +whitewood +whitewoods +whitey +whiteys +whither +whithersoever +whitherward +whiting +whitings +whitish +whitleather +whitlow +whitman +whitmonday +whitney +whitsun +whitsunday +whitsuntide +whittington +whittle +whittled +whittler +whittlers +whittles +whittling +whity +whiz +whizbang +whizbangs +whizz +whizzbang +whizzed +whizzer +whizzers +whizzes +whizzing +who +who'd +who'll +who's +who've +whoa +whodunit +whodunits +whodunnit +whodunnits +whoever +whole +wholehearted +wholeheartedly +wholeheartedness +wholeness +wholes +wholesale +wholesaled +wholesaler +wholesalers +wholesales +wholesaling +wholesome +wholesomely +wholesomeness +wholesomer +wholesomest +wholistic +wholly +whom +whomever +whomp +whomped +whomping +whomps +whomso +whomsoever +whoo +whoop +whooped +whoopee +whoopees +whooper +whoopers +whooping +whoopla +whooplas +whoops +whoos +whoosh +whooshed +whooshes +whooshing +whop +whopped +whopper +whoppers +whopping +whops +whore +whored +whoredom +whoredoms +whorehouse +whorehouses +whoremaster +whoremasters +whoremonger +whoremongers +whores +whoreson +whoresons +whorfian +whoring +whorish +whorishly +whorishness +whorl +whorled +whorls +whort +whortle +whortleberries +whortleberry +whortles +whorts +whose +whosesoever +whoso +whosoever +whump +whumped +whumping +whumps +why +whydah +whydahs +whys +wicca +wiccan +wiccans +wichita +wichitas +wick +wicked +wickeder +wickedest +wickedly +wickedness +wicker +wickerwork +wicket +wicketkeeper +wicketkeepers +wickets +wicking +wickiup +wickiups +wicks +wicopies +wicopy +widal +widdershins +wide +wideawake +wideawakes +wideband +widely +widemouthed +widen +widened +widener +wideners +wideness +widening +widens +wideout +wideouts +wider +widespread +widest +widgeon +widgeons +widget +widgets +widish +widow +widowed +widower +widowerhood +widowers +widowhood +widowing +widows +width +widths +widthwise +wiedersehen +wield +wieldable +wielded +wielder +wielders +wieldier +wieldiest +wielding +wields +wieldy +wien +wiener +wieners +wienerwurst +wienerwursts +wienie +wienies +wiesbaden +wiesel +wife +wifehood +wifeless +wifeliness +wifely +wiffle +wifty +wig +wigan +wigans +wigeon +wigeons +wigged +wigging +wiggle +wiggled +wiggler +wigglers +wiggles +wiggling +wiggly +wight +wights +wiglet +wiglets +wigmaker +wigmakers +wigs +wigwag +wigwagged +wigwagger +wigwaggers +wigwagging +wigwags +wigwam +wigwams +wikiup +wikiups +wilberforce +wilco +wild +wildcard +wildcards +wildcat +wildcats +wildcatted +wildcatter +wildcatters +wildcatting +wildebeest +wildebeests +wilder +wildered +wildering +wilderment +wilderness +wildernesses +wilders +wildest +wildfire +wildfires +wildflower +wildflowers +wildfowl +wildfowler +wildfowlers +wildfowling +wildfowls +wilding +wildings +wildish +wildland +wildlands +wildlife +wildling +wildlings +wildly +wildness +wilds +wildwood +wildwoods +wile +wiled +wiles +wilful +wilhelmshaven +wilier +wiliest +wilily +wiliness +wiling +wilkes +will +willamette +willed +willedly +willedness +willemite +willemites +willemstad +willet +willets +willful +willfully +willfulness +william +willies +willing +willingly +willingness +williwaw +williwaws +willow +willowed +willowier +willowiest +willowing +willowlike +willows +willowware +willowy +willpower +wills +willy +wilmington +wilms +wilson +wilt +wilted +wilting +wilton +wilts +wiltshire +wily +wimble +wimbled +wimbledon +wimbles +wimbling +wimp +wimpiness +wimpish +wimpishness +wimple +wimpled +wimples +wimpling +wimps +wimpy +wimshurst +win +wince +winced +wincer +wincers +winces +winch +winched +wincher +winchers +winches +winchester +winchesters +winching +wincing +wind +windage +windbag +windbags +windblast +windblasts +windblown +windbreak +windbreaker +windbreakers +windbreaks +windburn +windburned +windburns +windcheater +windcheaters +windchill +windchills +winded +windedly +windedness +winder +winders +windfall +windfalls +windflaw +windflaws +windflower +windflowers +windgall +windgalls +windhoek +windhover +windhovers +windier +windiest +windily +windiness +winding +windingly +windings +windjammer +windjammers +windjamming +windlass +windlassed +windlasses +windlassing +windless +windlessly +windlestraw +windlestraws +windmill +windmilled +windmilling +windmills +window +windowed +windowing +windowless +windowpane +windowpanes +windows +windowsill +windowsills +windpipe +windpipes +windproof +windrow +windrowed +windrower +windrowers +windrowing +windrows +winds +windsailing +windscreen +windscreens +windshake +windshakes +windshield +windshields +windsock +windsocks +windsor +windstorm +windstorms +windsucker +windsuckers +windsucking +windsurf +windsurfed +windsurfer +windsurfers +windsurfing +windsurfs +windswept +windthrow +windup +windups +windward +windwards +windway +windways +windy +wine +winebibber +winebibbers +winebibbing +winebibbings +wined +wineglass +wineglasses +winegrower +winegrowers +winemaker +winemakers +winemaking +winepress +winepresses +wineries +winery +wines +winesap +winesaps +wineshop +wineshops +wineskin +wineskins +winetasting +winetastings +winey +wing +wingback +wingbacks +wingbow +wingbows +wingchair +wingchairs +wingding +wingdings +winged +winger +wingers +winging +wingless +winglessness +winglet +winglets +winglike +wingman +wingmen +wingover +wingovers +wings +wingspan +wingspans +wingspread +wingspreads +wingtip +wingtips +wingy +winier +winiest +wining +wink +winked +winker +winkers +winking +winkle +winkled +winkles +winkling +winks +winless +winnability +winnable +winnebago +winnebagoes +winnebagos +winner +winners +winnie +winnies +winning +winningest +winningly +winningness +winnings +winnipeg +winnipegosis +winnipesaukee +winnow +winnowed +winnower +winnowers +winnowing +winnows +wino +winos +wins +winsome +winsomely +winsomeness +winter +winterberries +winterberry +wintered +winterer +winterers +wintergreen +wintergreens +winterier +winteriest +wintering +winterish +winterization +winterizations +winterize +winterized +winterizes +winterizing +winterkill +winterkilled +winterkilling +winterkills +winterly +winters +wintertide +wintertime +wintery +wintrier +wintriest +wintrily +wintriness +wintry +winy +winze +winzes +wipe +wiped +wipeout +wipeouts +wiper +wipers +wipes +wiping +wirable +wire +wired +wiredraw +wiredrawer +wiredrawers +wiredrawing +wiredrawn +wiredraws +wiredrew +wiregrass +wiregrasses +wirehair +wirehaired +wirehairs +wireless +wirelessed +wirelesses +wirelessing +wirelike +wireman +wiremen +wirephoto +wirepuller +wirepullers +wirepulling +wirer +wirers +wires +wiretap +wiretapped +wiretapper +wiretappers +wiretapping +wiretaps +wirewalker +wirewalkers +wirework +wireworks +wireworm +wireworms +wirier +wiriest +wirily +wiriness +wiring +wiry +wisconsin +wisconsinite +wisconsinites +wisdom +wise +wiseacre +wiseacres +wiseass +wiseasses +wisecrack +wisecracked +wisecracker +wisecrackers +wisecracking +wisecracks +wised +wisely +wiseness +wisenheimer +wisenheimers +wisent +wisents +wiser +wises +wisest +wisewoman +wisewomen +wish +wishbone +wishbones +wished +wisher +wishers +wishes +wishful +wishfully +wishfulness +wishing +wishy +wising +wisp +wisped +wispily +wispiness +wisping +wispish +wisps +wispy +wistaria +wistarias +wisteria +wisterias +wistful +wistfully +wistfulness +wit +witan +witch +witchcraft +witched +witcher +witcheries +witchers +witchery +witches +witchgrass +witchgrasses +witching +witchingly +witchlike +witchweed +witchweeds +witchy +witenagemot +witenagemote +with +withal +withdraw +withdrawable +withdrawal +withdrawals +withdrawer +withdrawers +withdrawing +withdrawn +withdrawnness +withdraws +withdrew +withe +wither +withered +withering +witheringly +witherite +witherites +withers +withershins +withes +withheld +withhold +withholder +withholders +withholding +withholdings +withholds +withies +within +withindoors +without +withoutdoors +withstand +withstander +withstanders +withstanding +withstands +withstood +withy +witless +witlessly +witlessness +witling +witlings +witloof +witloofs +witness +witnessed +witnesser +witnessers +witnesses +witnessing +wits +witted +wittedly +wittedness +wittenberg +wittgenstein +wittgensteinian +witticism +witticisms +wittier +wittiest +wittily +wittiness +witting +wittingly +wittings +wittol +wittols +witty +witwatersrand +wive +wived +wivern +wiverns +wives +wiving +wiz +wizard +wizardly +wizardries +wizardry +wizards +wizen +wizened +wizening +wizens +wizes +wkly +woad +woads +woadwaxen +woadwaxens +wobble +wobbled +wobbler +wobblers +wobbles +wobblier +wobblies +wobbliest +wobbliness +wobbling +wobbly +wodehouse +woden +wodge +wodges +woe +woebegone +woebegoneness +woeful +woefully +woefulness +woes +woffington +woful +wok +woke +woken +woks +wold +wolds +wolf +wolfberries +wolfberry +wolfed +wolfer +wolfers +wolffian +wolffish +wolfhound +wolfhounds +wolfing +wolfish +wolfishly +wolfishness +wolflike +wolfram +wolframite +wolframites +wolframs +wolfs +wolfsbane +wolfsbanes +wollastonite +wollastonites +wolof +wolsey +wolverine +wolverines +wolves +woman +womanfully +womanhood +womanish +womanishly +womanishness +womanism +womanist +womanists +womanize +womanized +womanizer +womanizers +womanizes +womanizing +womankind +womanless +womanlier +womanliest +womanlike +womanliness +womanly +womanpower +womb +wombat +wombats +wombed +wombs +women +womenfolk +womenfolks +womenkind +womera +womeras +wommera +wommeras +won +won't +wonder +wondered +wonderer +wonderers +wonderful +wonderfully +wonderfulness +wondering +wonderingly +wonderland +wonderlands +wonderment +wonders +wonderwork +wonderworker +wonderworkers +wonderworking +wonderworks +wondrous +wondrously +wondrousness +wonk +wonkier +wonkiest +wonks +wonky +wont +wonted +wontedly +wontedness +wonting +wonton +wontons +wonts +woo +wood +woodbin +woodbine +woodbines +woodbins +woodblock +woodblocks +woodborer +woodborers +woodboring +woodcarver +woodcarvers +woodcarving +woodcarvings +woodchat +woodchats +woodchopper +woodchoppers +woodchopping +woodchuck +woodchucks +woodcock +woodcocks +woodcraft +woodcrafter +woodcrafters +woodcrafting +woodcrafts +woodcut +woodcuts +woodcutter +woodcutters +woodcutting +woodcuttings +wooded +wooden +woodenhead +woodenheaded +woodenheads +woodenly +woodenness +woodenware +woodie +woodier +woodies +woodiest +woodiness +wooding +woodland +woodlander +woodlanders +woodlands +woodlark +woodlarks +woodlore +woodlot +woodlots +woodman +woodmen +woodnote +woodnotes +woodpecker +woodpeckers +woodpile +woodpiles +woodprint +woodprints +woodruff +woodruffs +woods +woodshed +woodshedded +woodshedding +woodsheds +woodshop +woodshops +woodsia +woodsias +woodsier +woodsiest +woodsman +woodsmen +woodstove +woodstoves +woodsy +woodturner +woodturners +woodturning +woodville +woodwaxen +woodwaxens +woodwind +woodwinds +woodwork +woodworker +woodworkers +woodworking +woodworks +woodworm +woodworms +woody +wooed +wooer +wooers +woof +woofed +woofer +woofers +woofing +woofs +woogie +wooing +wool +wooled +woolen +woolens +woolgather +woolgathered +woolgatherer +woolgatherers +woolgathering +woolgathers +woolgrower +woolgrowers +woolgrowing +woolie +woolier +woolies +wooliest +woolled +woollen +woollens +woollier +woollies +woolliest +woollily +woolliness +woolly +woolpack +woolpacks +wools +woolsack +woolsacks +woolsey +woolshed +woolsheds +woolskin +woolskins +woolsorter +woolworker +woolworkers +woolworth +wooly +woomera +woomeras +woops +woos +woozier +wooziest +woozily +wooziness +woozy +wop +wops +worcester +worcestershire +word +wordage +wordbook +wordbooks +worded +wordier +wordiest +wordily +wordiness +wording +wordings +wordless +wordlessly +wordlessness +wordmonger +wordmongering +wordmongers +wordplay +wordplays +words +wordsmith +wordsmithery +wordsmiths +wordsworth +wordsworthian +wordy +wore +work +workability +workable +workableness +workably +workaday +workaholic +workaholics +workaholism +workaround +workarounds +workbag +workbags +workbasket +workbaskets +workbench +workbenches +workboat +workboats +workbook +workbooks +workbox +workboxes +workday +workdays +worked +worker +workers +workfare +workflow +workflows +workfolk +workfolks +workforce +workforces +workhorse +workhorses +workhouse +workhouses +working +workingman +workingmen +workings +workingwoman +workingwomen +workless +worklessness +workload +workloads +workman +workmanlike +workmanly +workmanship +workmate +workmates +workmen +workout +workouts +workpeople +workpiece +workpieces +workplace +workplaces +workroom +workrooms +works +worksheet +worksheets +workshop +workshops +workspace +workspaces +workstation +workstations +worktable +worktables +workup +workups +workweek +workweeks +workwoman +workwomen +world +worlder +worlders +worldlier +worldliest +worldliness +worldling +worldlings +worldly +worlds +worldview +worldviews +worldwide +worm +wormed +wormer +wormers +wormgrass +wormgrasses +wormhole +wormholes +wormier +wormiest +worminess +worming +wormlike +worms +wormseed +wormseeds +wormwood +wormwoods +wormy +worn +worried +worriedly +worrier +worriers +worries +worriment +worriments +worrisome +worrisomely +worrisomeness +worry +worrying +worryingly +worrywart +worrywarts +worse +worsen +worsened +worsening +worsens +worship +worshiped +worshiper +worshipers +worshipful +worshipfully +worshipfulness +worshiping +worshipless +worshipped +worshipper +worshippers +worshipping +worships +worsleya +worsleyas +worst +worsted +worsteds +worsting +worsts +wort +worth +worthed +worthful +worthier +worthies +worthiest +worthily +worthiness +worthing +worthless +worthlessly +worthlessness +worths +worthwhile +worthwhileness +worthy +wot +wotan +wots +wotted +wotting +would +would've +wouldest +wouldn +wouldn't +wouldst +wound +wounded +woundedly +wounding +woundingly +woundless +wounds +woundwort +woundworts +wove +woven +wow +wowed +wowing +wows +wowser +wowsers +wp +wpm +wrack +wracked +wrackful +wracking +wracks +wraith +wraithlike +wraiths +wrangel +wrangell +wrangle +wrangled +wrangler +wranglers +wrangles +wrangling +wrap +wraparound +wraparounds +wrapped +wrapper +wrappers +wrapping +wrappings +wraps +wrapt +wrasse +wrasses +wrath +wrathful +wrathfully +wrathfulness +wrathy +wreak +wreaked +wreaking +wreaks +wreath +wreathe +wreathed +wreathes +wreathing +wreaths +wreathy +wreck +wreckage +wrecked +wrecker +wreckers +wrecking +wrecks +wren +wrench +wrenched +wrenches +wrenching +wrenchingly +wrens +wrest +wrested +wrester +wresters +wresting +wrestle +wrestled +wrestler +wrestlers +wrestles +wrestling +wrests +wretch +wretched +wretcheder +wretchedest +wretchedly +wretchedness +wretches +wried +wrier +wries +wriest +wriggle +wriggled +wriggler +wrigglers +wriggles +wriggling +wriggly +wright +wrights +wrigley +wring +wringer +wringers +wringing +wrings +wrinkle +wrinkled +wrinkles +wrinkling +wrinkly +wrist +wristband +wristbands +wristed +wristier +wristiest +wristlet +wristlets +wristlock +wristlocks +wrists +wristwatch +wristwatches +wristy +writ +writable +write +writer +writerly +writers +writes +writhe +writhed +writhen +writher +writhers +writhes +writhing +writing +writings +writs +written +wrong +wrongdoer +wrongdoers +wrongdoing +wrongdoings +wronged +wronger +wrongers +wrongest +wrongful +wrongfully +wrongfulness +wrongheaded +wrongheadedly +wrongheadedness +wronging +wrongly +wrongness +wrongs +wrote +wroth +wrought +wrung +wry +wryer +wryest +wrying +wryly +wryneck +wrynecks +wryness +wt +wulfenite +wulfenites +wunderbar +wunderkind +wunderkinder +wurst +wurtemburg +wurzburg +wurzel +wurzels +wushu +wyandot +wyandots +wyandotte +wyandottes +wyatt +wych +wycherley +wyclif +wycliffe +wycliffite +wycliffites +wye +wyes +wyn +wynn +wynns +wyoming +wysiwyg +wyvern +wyverns +württemberg +x +xanadu +xanadus +xanthan +xanthate +xanthates +xanthene +xanthenes +xanthic +xanthine +xanthines +xanthippe +xanthochroic +xanthochroid +xanthochroids +xanthoma +xanthomas +xanthomata +xanthomatoses +xanthomatosis +xanthomatous +xanthone +xanthones +xanthophore +xanthophores +xanthophyll +xanthophyllic +xanthophyllous +xanthophylls +xanthopterin +xanthopterins +xanthous +xantippe +xaverian +xavier +xebec +xebecs +xed +xenia +xenias +xenobiotic +xenobiotics +xenoblast +xenoblasts +xenocryst +xenocrysts +xenodiagnoses +xenodiagnosis +xenodiagnostic +xenogamies +xenogamous +xenogamy +xenogeneic +xenogenesis +xenogenetic +xenogenic +xenograft +xenografts +xenolith +xenolithic +xenoliths +xenon +xenophanes +xenophile +xenophiles +xenophilia +xenophilous +xenophobe +xenophobes +xenophobia +xenophobic +xenophobically +xenophon +xenotropic +xerarch +xeric +xerically +xericity +xeriscape +xeroderma +xerodermas +xerodermia +xerodermias +xerographer +xerographers +xerographic +xerographically +xerography +xerophile +xerophilous +xerophily +xerophthalmia +xerophthalmias +xerophthalmic +xerophyte +xerophytes +xerophytic +xerophytically +xerophytism +xeroradiography +xerosere +xeroseres +xeroses +xerosis +xerothermic +xerox +xeroxed +xeroxes +xeroxing +xerxes +xhosa +xhosas +xi +xinjiang +xiphisterna +xiphisternum +xiphoid +xiphoids +xiphosuran +xiphosurans +xis +xizang +xmas +xmases +xosa +xosas +xray +xs +xu +xylan +xylans +xylem +xylene +xylenes +xylidine +xylidines +xylitol +xylitols +xylograph +xylographed +xylographer +xylographers +xylographic +xylographical +xylographically +xylographing +xylographs +xylography +xyloid +xylol +xylols +xylophage +xylophages +xylophagous +xylophone +xylophones +xylophonist +xylophonists +xylose +xyloses +xylotomies +xylotomist +xylotomists +xylotomy +xyster +xysters +y +y'all +yabber +yabbered +yabbering +yabbers +yablonovy +yacht +yachted +yachter +yachters +yachting +yachts +yachtsman +yachtsmen +yachtswoman +yachtswomen +yack +yacked +yackety +yacking +yacks +yag +yagi +yagis +yahoo +yahooism +yahoos +yahveh +yahvist +yahweh +yahwism +yahwist +yahwistic +yak +yakima +yakimas +yakitori +yakitoris +yakked +yakking +yakow +yakows +yaks +yakut +yakuts +yakuza +yale +yalta +yam +yamasee +yamasees +yamen +yamens +yammer +yammered +yammerer +yammerers +yammering +yammers +yams +yang +yangtze +yank +yanked +yankee +yankeedom +yankeeism +yankeeisms +yankees +yanking +yanks +yankton +yanktonai +yanktonais +yanktons +yanqui +yantra +yantras +yao +yaos +yaoundé +yap +yapok +yapoks +yapped +yapper +yappers +yapping +yaps +yaqui +yaquis +yarborough +yarboroughs +yard +yardage +yardarm +yardarms +yardbird +yardbirds +yarded +yarding +yardman +yardmaster +yardmasters +yardmen +yards +yardstick +yardsticks +yare +yarely +yarmelke +yarmelkes +yarmulke +yarmulkes +yarn +yarned +yarner +yarners +yarning +yarns +yarrow +yarrows +yashmac +yashmacs +yashmak +yashmaks +yasmak +yasmaks +yatagan +yatagans +yataghan +yataghans +yaup +yauped +yauping +yaupon +yaupons +yaups +yautia +yavapai +yavapais +yaw +yawed +yawing +yawl +yawls +yawn +yawned +yawner +yawners +yawning +yawningly +yawns +yawp +yawped +yawper +yawpers +yawping +yawps +yaws +ycleped +yclept +yd +ye +yea +yeah +yean +yeaned +yeaning +yeanling +yeanlings +yeans +year +yearbook +yearbooks +yearend +yearends +yearlies +yearling +yearlings +yearlong +yearly +yearn +yearned +yearner +yearners +yearning +yearningly +yearnings +yearns +years +yeas +yeast +yeasted +yeastier +yeastiest +yeastily +yeastiness +yeasting +yeasts +yeasty +yeats +yeatsian +yecch +yech +yegg +yeggs +yell +yelled +yeller +yellers +yelling +yellow +yellowbellied +yellowbellies +yellowbelly +yellowbird +yellowbirds +yellowcake +yellowcakes +yellowed +yellower +yellowest +yellowfin +yellowhammer +yellowhammers +yellowing +yellowish +yellowishness +yellowknife +yellowlegs +yellowness +yellows +yellowstone +yellowtail +yellowtails +yellowthroat +yellowthroats +yellowware +yellowweed +yellowweeds +yellowwood +yellowwoods +yellowy +yells +yelp +yelped +yelper +yelpers +yelping +yelps +yemen +yemeni +yemenis +yemenite +yemenites +yen +yenned +yenning +yens +yenta +yentas +yeoman +yeomanly +yeomanries +yeomanry +yeomen +yep +yerba +yerkish +yersinia +yersiniae +yersinioses +yersiniosis +yes +yeses +yeshiva +yeshivah +yeshivahs +yeshivas +yeshivot +yessed +yessing +yesterday +yesterdays +yestereve +yestereven +yesterevening +yesterevenings +yesterevens +yestereves +yestermorn +yestermorning +yestermornings +yestermorns +yesternight +yesternights +yesteryear +yesteryears +yet +yeti +yetis +yew +yews +ygdrasil +yggdrasil +yid +yiddish +yiddishism +yiddishist +yiddishists +yids +yield +yielded +yielder +yielders +yielding +yieldingly +yieldingness +yields +yikes +yin +yinglish +yip +yipe +yipes +yipped +yippee +yippie +yippies +yipping +yips +ylang +ylem +ylems +ymca +ymir +yo +yock +yocked +yocking +yocks +yod +yodel +yodeled +yodeler +yodelers +yodeling +yodelled +yodelling +yodels +yodh +yoed +yoga +yogh +yoghourt +yoghourts +yoghurt +yoghurts +yogi +yogic +yogin +yogins +yogis +yogurt +yogurts +yohimbine +yohimbines +yoicks +yoing +yoke +yoked +yokefellow +yokefellows +yokel +yokels +yokes +yoking +yokohama +yokuts +yolk +yolked +yolks +yolky +yom +yon +yonder +yoni +yonic +yonis +yoo +yore +yorick +york +yorker +yorkers +yorkie +yorkies +yorkist +yorkists +yorkshire +yoruba +yoruban +yorubas +yos +yosemite +you +you'd +you'll +you're +you've +young +young'un +young'uns +youngberries +youngberry +younger +youngest +youngish +youngling +younglings +youngness +youngster +youngsters +younker +younkers +your +yours +yourself +yourselfer +yourselfers +yourselves +youth +youthful +youthfully +youthfulness +youthquake +youths +yow +yowl +yowled +yowling +yowls +ypres +yquem +yquems +ytterbia +ytterbias +ytterbic +ytterbium +yttria +yttrias +yttric +yttrium +yuan +yuans +yuca +yucatec +yucatecan +yucatecans +yucatecs +yucatán +yucca +yuccas +yuchi +yuchis +yuck +yuckier +yuckiest +yuckiness +yucky +yuga +yugoslav +yugoslavia +yugoslavian +yugoslavians +yugoslavs +yuk +yukon +yulan +yulans +yule +yuletide +yum +yuma +yuman +yumas +yummier +yummiest +yumminess +yummy +yunnan +yup +yupik +yupiks +yuppie +yuppiedom +yuppies +yurok +yuroks +yurt +yurts +ywis +z +zabaglione +zabagliones +zacharias +zaddik +zaddikim +zaffer +zaffers +zaffre +zaffres +zaftig +zag +zagged +zagging +zagreb +zagreus +zagros +zags +zaibatsu +zaikai +zaire +zairean +zaireans +zaires +zairian +zairians +zambesi +zambezi +zambia +zambian +zambians +zamia +zamias +zamindar +zamindari +zamindaris +zamindars +zanana +zananas +zander +zanders +zanier +zanies +zaniest +zanily +zaniness +zany +zanzibar +zap +zapata +zapateado +zapateados +zapateo +zapotec +zapotecs +zapped +zapper +zappers +zappier +zappiest +zapping +zappy +zaps +zarathustra +zareba +zarebas +zareeba +zareebas +zarf +zarfs +zariba +zaribas +zarzuela +zastruga +zastrugas +zauberflöte +zax +zaxes +zayin +zazen +zaïrean +zaïreans +zeal +zealand +zealander +zealanders +zealot +zealotries +zealotry +zealots +zealous +zealously +zealousness +zeatin +zeatins +zebec +zebeck +zebecks +zebecs +zebedee +zebra +zebras +zebrawood +zebrawoods +zebrine +zebroid +zebroids +zebu +zebulon +zebulun +zebus +zecchin +zecchini +zecchino +zecchinos +zecchins +zechariah +zechin +zechins +zed +zedoaries +zedoary +zedonk +zedonks +zeds +zee +zeebrugge +zeeland +zeeman +zees +zeffirelli +zein +zeins +zeitgeber +zeitgebers +zeitgeist +zeitgeists +zek +zeks +zelkova +zelkovas +zemindar +zemindaries +zemindars +zemindary +zemlya +zemstvo +zemstvos +zen +zenana +zenanas +zend +zener +zenist +zenists +zenith +zenithal +zeniths +zeno +zeolite +zeolites +zeolitic +zephaniah +zephyr +zephyrs +zephyrus +zeppelin +zeppelins +zerk +zerks +zermatt +zero +zeroed +zeroes +zeroing +zeros +zeroth +zest +zested +zester +zesters +zestful +zestfully +zestfulness +zestier +zestiest +zesting +zestless +zests +zesty +zeta +zethos +zethus +zeugma +zeugmas +zeus +zeuxis +zhejiang +zibeline +zibelines +zibelline +zibellines +zibet +zibeth +zibeths +zibets +zidovudine +zidovudines +ziegfeld +zig +zigged +zigging +ziggurat +ziggurats +zigs +zigzag +zigzagged +zigzagger +zigzaggers +zigzagging +zigzags +zilch +zilches +zill +zillion +zillionaire +zillionaires +zillions +zillionth +zillionths +zills +zimbabwe +zimbabwean +zimbabweans +zimmermann +zinc +zincate +zincates +zinced +zincing +zincite +zincites +zincked +zinckenite +zinckenites +zincking +zincks +zincograph +zincographer +zincographers +zincographic +zincographical +zincographs +zincography +zincs +zineb +zinebs +zinfandel +zinfandels +zing +zingari +zingaro +zinged +zinger +zingers +zingier +zingiest +zinging +zings +zingy +zinkenite +zinkenites +zinnia +zinnias +zion +zionism +zionist +zionistic +zionists +zip +zipless +zipped +zipper +zippered +zippering +zippers +zippier +zippiest +zipping +zippy +zips +ziram +zirams +zircaloy +zircaloys +zircon +zirconia +zirconias +zirconium +zircons +zit +zither +zitherist +zitherists +zithern +zitherns +zithers +ziti +zits +zizith +zloty +zlotys +zoa +zoantharian +zoantharians +zoaria +zoarial +zoarium +zoariums +zocalo +zocalos +zodiac +zodiacal +zodiacs +zoea +zoeae +zoeas +zoecia +zoecium +zoffany +zoftig +zoisite +zoisites +zola +zombi +zombie +zombielike +zombies +zombification +zombifications +zombified +zombifies +zombify +zombifying +zombiism +zombis +zona +zonae +zonal +zonally +zonary +zonate +zonated +zonation +zone +zoned +zoner +zoners +zones +zonetime +zonetimes +zonian +zonians +zoning +zonk +zonked +zonking +zonks +zontian +zontians +zonule +zonules +zoo +zoochlorella +zoochlorellae +zoochlorellas +zoochore +zoochores +zooecia +zooecium +zooflagellate +zooflagellates +zoogenic +zoogenous +zoogeographer +zoogeographers +zoogeographic +zoogeographical +zoogeographically +zoogeography +zooglea +zoogleae +zoogleal +zoogleas +zoogloea +zoogloeae +zoogloeas +zoographic +zoographical +zoography +zooid +zooidal +zooids +zookeeper +zookeepers +zooks +zoolater +zoolaters +zoolatrous +zoolatry +zoologic +zoological +zoologically +zoologies +zoologist +zoologists +zoology +zoom +zoomed +zoometric +zoometrical +zoometrically +zoometries +zoometry +zooming +zoomorph +zoomorphic +zoomorphism +zoomorphs +zooms +zoon +zoonoses +zoonosis +zoonotic +zoons +zooparasite +zooparasites +zooparasitic +zoophagous +zoophile +zoophiles +zoophilia +zoophilic +zoophilism +zoophilous +zoophily +zoophobe +zoophobes +zoophobia +zoophyte +zoophytes +zoophytic +zoophytical +zooplankter +zooplankters +zooplankton +zooplanktonic +zooplastic +zooplasties +zooplasty +zoos +zoosperm +zoosperms +zoosporangia +zoosporangium +zoospore +zoospores +zoosporic +zoosporous +zoosterol +zoosterols +zoot +zootechnical +zootechnician +zootechnicians +zootechnics +zootechny +zootomic +zootomical +zootomies +zootomist +zootomists +zootomy +zootoxin +zootoxins +zooty +zooxanthella +zooxanthellae +zori +zoril +zorilla +zorillas +zorille +zorilles +zorils +zoris +zorn +zoroaster +zoroastrian +zoroastrianism +zoroastrians +zoster +zosters +zouave +zouaves +zounds +zowie +zoysia +zucchetto +zucchettos +zucchini +zucchinis +zugspitze +zugunruhe +zugzwang +zugzwangs +zulu +zululand +zulus +zuni +zunian +zunis +zuppa +zurich +zutphen +zuñi +zuñian +zuñis +zwieback +zwiebacks +zwingli +zwinglian +zwinglianism +zwinglians +zwitterion +zwitterionic +zwitterions +zydeco +zygapophyseal +zygapophyses +zygapophysial +zygapophysis +zygodactyl +zygodactylous +zygodactyls +zygogeneses +zygogenesis +zygogenetic +zygoma +zygomas +zygomata +zygomatic +zygomorphic +zygomorphism +zygomorphous +zygomorphy +zygoses +zygosis +zygosity +zygospore +zygospores +zygote +zygotene +zygotenes +zygotes +zygotic +zygotically +zymase +zymases +zymogen +zymogenic +zymogenous +zymogens +zymogram +zymograms +zymologic +zymological +zymologist +zymologists +zymology +zymolysis +zymolytic +zymometer +zymometers +zymosan +zymosans +zymoscope +zymoscopes +zymoses +zymosis +zymotic +zymotically +zymurgy +zyzzyva +zyzzyvas +zákros +zöllner +zöllner's +zürich +à +âge +åland +ångstrom +ångstroms +éclair +éclaircissement +éclairs +éclat +éclats +école +écoles +écorché +écrasez +écu +écus +élan +élans +élite +élites +élitism +élitist +élitists +émigré +émigrés +éminence +éminences +époque +épée +épéeist +épéeists +épées +étagère +étagères +état +étienne +étoile +étoiles +étouffée +étouffées +étui +étuis +évian +évêque +être +öland +öre +øresund +œil +œuvre \ No newline at end of file diff --git a/Trie/Trie/TrieTests/Info.plist b/Trie/Trie/TrieTests/Info.plist new file mode 100644 index 000000000..6c6c23c43 --- /dev/null +++ b/Trie/Trie/TrieTests/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + diff --git a/Trie/Trie/TrieTests/TrieTests.swift b/Trie/Trie/TrieTests/TrieTests.swift new file mode 100644 index 000000000..236908ece --- /dev/null +++ b/Trie/Trie/TrieTests/TrieTests.swift @@ -0,0 +1,162 @@ +// +// TrieTests.swift +// TrieTests +// +// Created by Rick Zaccone on 2016-12-12. +// Copyright © 2016 Rick Zaccone. All rights reserved. +// + +import XCTest +@testable import Trie + +class TrieTests: XCTestCase { + var wordArray: [String]? + var trie = Trie() + + /// Makes sure that the wordArray and trie are initialized before each test. + override func setUp() { + super.setUp() + createWordArray() + insertWordsIntoTrie() + } + + /// Don't need to do anything here because the wordArrayu and trie should + /// stay around. + override func tearDown() { + super.tearDown() + } + + /// Reads words from the dictionary file and inserts them into an array. If + /// the word array already has words, do nothing. This allows running all + /// tests without repeatedly filling the array with the same values. + func createWordArray() { + guard wordArray == nil else { + return + } + let resourcePath = Bundle.main.resourcePath! as NSString + let fileName = "dictionary.txt" + let filePath = resourcePath.appendingPathComponent(fileName) + + var data: String? + do { + data = try String(contentsOfFile: filePath, encoding: String.Encoding.utf8) + } catch let error as NSError { + XCTAssertNil(error) + } + XCTAssertNotNil(data) + let dictionarySize = 162825 + wordArray = data!.components(separatedBy: "\n") + XCTAssertEqual(wordArray!.count, dictionarySize) + } + + /// Inserts words into a trie. If the trie is non-empty, don't do anything. + func insertWordsIntoTrie() { + guard trie.count == 0 else { + return + } + let numberOfWordsToInsert = wordArray!.count + for i in 0.. + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + diff --git a/Trie/Trie/TrieUITests/TrieUITests.swift b/Trie/Trie/TrieUITests/TrieUITests.swift new file mode 100644 index 000000000..f3da2a67f --- /dev/null +++ b/Trie/Trie/TrieUITests/TrieUITests.swift @@ -0,0 +1,36 @@ +// +// TrieUITests.swift +// TrieUITests +// +// Created by Rick Zaccone on 2016-12-12. +// Copyright © 2016 Rick Zaccone. All rights reserved. +// + +import XCTest + +class TrieUITests: XCTestCase { + + override func setUp() { + super.setUp() + + // Put setup code here. This method is called before the invocation of each test method in the class. + + // In UI tests it is usually best to stop immediately when a failure occurs. + continueAfterFailure = false + // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. + XCUIApplication().launch() + + // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. + } + + override func tearDown() { + // Put teardown code here. This method is called after the invocation of each test method in the class. + super.tearDown() + } + + func testExample() { + // Use recording to get started writing UI tests. + // Use XCTAssert and related functions to verify your tests produce the correct results. + } + +} From 1e23b7f859ed83e21dd37941113102af0d8c4d28 Mon Sep 17 00:00:00 2001 From: Richard Date: Tue, 13 Dec 2016 14:30:07 -0800 Subject: [PATCH 0671/1679] Code updates --- Strassen Matrix Multiplication/Matrix.swift | 237 ++++++++++++++++++ .../MatrixSize.swift | 17 ++ Strassen Matrix Multiplication/Number.swift | 41 +++ 3 files changed, 295 insertions(+) diff --git a/Strassen Matrix Multiplication/Matrix.swift b/Strassen Matrix Multiplication/Matrix.swift index 493e27e06..657cf3c80 100644 --- a/Strassen Matrix Multiplication/Matrix.swift +++ b/Strassen Matrix Multiplication/Matrix.swift @@ -7,3 +7,240 @@ // import Foundation + +enum RowOrColumn { + case row, column +} + +struct Matrix { + + // MARK: - Variables + + let rows: Int, columns: Int + var grid: [T] + + var isSquare: Bool { + return rows == columns + } + + var size: MatrixSize { + return MatrixSize(rows: rows, columns: columns) + } + + // MARK: - Init + + init(rows: Int, columns: Int, initialValue: T = T.zero) { + self.rows = rows + self.columns = columns + self.grid = Array(repeating: initialValue, count: rows * columns) + } + + init(size: Int, initialValue: T = T.zero) { + self.rows = size + self.columns = size + self.grid = Array(repeating: initialValue, count: rows * columns) + } + + // MARK: - Subscript + + subscript(row: Int, column: Int) -> T { + get { + assert(indexIsValid(row: row, column: column), "Index out of range") + return grid[(row * columns) + column] + } + set { + assert(indexIsValid(row: row, column: column), "Index out of range") + grid[(row * columns) + column] = newValue + } + } + + subscript(type: RowOrColumn, value: Int) -> [T] { + get { + switch type { + case .row: + assert(indexIsValid(row: value, column: 0), "Index out of range") + return Array(grid[(value * columns)..<(value * columns) + columns]) + case .column: + assert(indexIsValid(row: 0, column: value), "Index out of range") + var columns: [T] = [] + for row in 0.. Bool { + return row >= 0 && row < rows && column >= 0 && column < columns + } + + private func strassenR(by B: Matrix) -> Matrix { + let A = self + assert(A.isSquare && B.isSquare, "This function requires square matricies!") + guard A.rows > 1 && B.rows > 1 else { return A * B } + + let n = A.rows + let nBy2 = n / 2 + + var a11 = Matrix(size: nBy2) + var a12 = Matrix(size: nBy2) + var a21 = Matrix(size: nBy2) + var a22 = Matrix(size: nBy2) + var b11 = Matrix(size: nBy2) + var b12 = Matrix(size: nBy2) + var b21 = Matrix(size: nBy2) + var b22 = Matrix(size: nBy2) + + for i in 0.. Int { + return Int(pow(2, ceil(log2(Double(n))))) + } + + // MARK: - Functions + + func strassenMatrixMultiply(by B: Matrix) -> Matrix { + let A = self + assert(A.columns == B.rows, "Two matricies can only be matrix mulitiplied if one has dimensions mxn & the other has dimensions nxp where m, n, p are in R") + + let n = max(A.rows, A.columns, B.rows, B.columns) + let m = nextPowerOfTwo(of: n) + + var APrep = Matrix(size: m) + var BPrep = Matrix(size: m) + + A.size.forEach { (i, j) in + APrep[i,j] = A[i,j] + } + + B.size.forEach { (i, j) in + BPrep[i,j] = B[i,j] + } + + let CPrep = APrep.strassenR(by: BPrep) + var C = Matrix(rows: A.rows, columns: B.columns) + + for i in 0..) -> Matrix { + let A = self + assert(A.columns == B.rows, "Two matricies can only be matrix mulitiplied if one has dimensions mxn & the other has dimensions nxp where m, n, p are in R") + + var C = Matrix(rows: A.rows, columns: B.columns) + + for i in 0..(lhs: Matrix, rhs: Matrix) -> Matrix { + assert(lhs.size == rhs.size, "To term-by-term multiply matricies they need to be the same size!") + let rows = lhs.rows + let columns = lhs.columns + + var newMatrix = Matrix(rows: rows, columns: columns) + for row in 0..(lhs: Matrix, rhs: Matrix) -> Matrix { + assert(lhs.size == rhs.size, "To term-by-term add matricies they need to be the same size!") + let rows = lhs.rows + let columns = lhs.columns + + var newMatrix = Matrix(rows: rows, columns: columns) + for row in 0..(lhs: Matrix, rhs: Matrix) -> Matrix { + assert(lhs.size == rhs.size, "To term-by-term subtract matricies they need to be the same size!") + let rows = lhs.rows + let columns = lhs.columns + + var newMatrix = Matrix(rows: rows, columns: columns) + for row in 0.. Void) rethrows { + for row in 0.. Bool { + return lhs.columns == rhs.columns && lhs.rows == rhs.rows +} diff --git a/Strassen Matrix Multiplication/Number.swift b/Strassen Matrix Multiplication/Number.swift index 1bd6cf634..34c6d5308 100644 --- a/Strassen Matrix Multiplication/Number.swift +++ b/Strassen Matrix Multiplication/Number.swift @@ -7,3 +7,44 @@ // import Foundation + +protocol Number: Multipliable, Addable { + static var zero: Self { get } +} + +protocol Addable { + static func +(lhs: Self, rhs: Self) -> Self + static func -(lhs: Self, rhs: Self) -> Self +} + +protocol Multipliable { + static func *(lhs: Self, rhs: Self) -> Self +} + +extension Int: Number { + static var zero: Int { + return 0 + } +} + +extension Double: Number { + static var zero: Double { + return 0.0 + } +} + +extension Float: Number { + static var zero: Float { + return 0.0 + } +} + + +extension Array where Element: Number { + func dot(_ b: Array) -> Element { + let a = self + assert(a.count == b.count, "Can only take the dot product of arrays of the same length!") + let c = a.indices.map{ a[$0] * b[$0] } + return c.reduce(Element.zero, { $0 + $1 }) + } +} From 31bc4c3159ea7574ee557ad46dbb65be33987395 Mon Sep 17 00:00:00 2001 From: Nagasawa Hiroki Date: Thu, 15 Dec 2016 08:52:41 +0900 Subject: [PATCH 0672/1679] Use lower camel case in enum case --- .../BinaryTree.playground/Contents.swift | 42 +++++++++---------- Binary Tree/BinaryTree.swift | 24 +++++------ 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/Binary Tree/BinaryTree.playground/Contents.swift b/Binary Tree/BinaryTree.playground/Contents.swift index b35e90c27..b4d65ec1f 100644 --- a/Binary Tree/BinaryTree.playground/Contents.swift +++ b/Binary Tree/BinaryTree.playground/Contents.swift @@ -1,14 +1,14 @@ //: Playground - noun: a place where people can play public indirect enum BinaryTree { - case Node(BinaryTree, T, BinaryTree) - case Empty + case node(BinaryTree, T, BinaryTree) + case empty public var count: Int { switch self { - case let .Node(left, _, right): + case let .node(left, _, right): return left.count + 1 + right.count - case .Empty: + case .empty: return 0 } } @@ -17,9 +17,9 @@ public indirect enum BinaryTree { extension BinaryTree: CustomStringConvertible { public var description: String { switch self { - case let .Node(left, value, right): + case let .node(left, value, right): return "value: \(value), left = [" + left.description + "], right = [" + right.description + "]" - case .Empty: + case .empty: return "" } } @@ -28,24 +28,24 @@ extension BinaryTree: CustomStringConvertible { // leaf nodes -let node5 = BinaryTree.Node(.Empty, "5", .Empty) -let nodeA = BinaryTree.Node(.Empty, "a", .Empty) -let node10 = BinaryTree.Node(.Empty, "10", .Empty) -let node4 = BinaryTree.Node(.Empty, "4", .Empty) -let node3 = BinaryTree.Node(.Empty, "3", .Empty) -let nodeB = BinaryTree.Node(.Empty, "b", .Empty) +let node5 = BinaryTree.node(.empty, "5", .empty) +let nodeA = BinaryTree.node(.empty, "a", .empty) +let node10 = BinaryTree.node(.empty, "10", .empty) +let node4 = BinaryTree.node(.empty, "4", .empty) +let node3 = BinaryTree.node(.empty, "3", .empty) +let nodeB = BinaryTree.node(.empty, "b", .empty) // intermediate nodes on the left -let aMinus10 = BinaryTree.Node(nodeA, "-", node10) -let timesLeft = BinaryTree.Node(node5, "*", aMinus10) +let aMinus10 = BinaryTree.node(nodeA, "-", node10) +let timesLeft = BinaryTree.node(node5, "*", aMinus10) // intermediate nodes on the right -let minus4 = BinaryTree.Node(.Empty, "-", node4) -let divide3andB = BinaryTree.Node(node3, "/", nodeB) -let timesRight = BinaryTree.Node(minus4, "*", divide3andB) +let minus4 = BinaryTree.node(.empty, "-", node4) +let divide3andB = BinaryTree.node(node3, "/", nodeB) +let timesRight = BinaryTree.node(minus4, "*", divide3andB) // root node -let tree = BinaryTree.Node(timesLeft, "+", timesRight) +let tree = BinaryTree.node(timesLeft, "+", timesRight) print(tree) tree.count // 12 @@ -54,7 +54,7 @@ tree.count // 12 extension BinaryTree { public func traverseInOrder(process: (T) -> Void) { - if case let .Node(left, value, right) = self { + if case let .node(left, value, right) = self { left.traverseInOrder(process: process) process(value) right.traverseInOrder(process: process) @@ -62,7 +62,7 @@ extension BinaryTree { } public func traversePreOrder(process: (T) -> Void) { - if case let .Node(left, value, right) = self { + if case let .node(left, value, right) = self { process(value) left.traversePreOrder(process: process) right.traversePreOrder(process: process) @@ -70,7 +70,7 @@ extension BinaryTree { } public func traversePostOrder(process: (T) -> Void) { - if case let .Node(left, value, right) = self { + if case let .node(left, value, right) = self { left.traversePostOrder(process: process) right.traversePostOrder(process: process) process(value) diff --git a/Binary Tree/BinaryTree.swift b/Binary Tree/BinaryTree.swift index 0c55af20e..ad5fcfd13 100644 --- a/Binary Tree/BinaryTree.swift +++ b/Binary Tree/BinaryTree.swift @@ -4,14 +4,14 @@ Nodes don't have a reference to their parent. */ public indirect enum BinaryTree { - case Node(BinaryTree, T, BinaryTree) - case Empty + case node(BinaryTree, T, BinaryTree) + case empty public var count: Int { switch self { - case let .Node(left, _, right): + case let .node(left, _, right): return left.count + 1 + right.count - case .Empty: + case .empty: return 0 } } @@ -20,9 +20,9 @@ public indirect enum BinaryTree { extension BinaryTree: CustomStringConvertible { public var description: String { switch self { - case let .Node(left, value, right): + case let .node(left, value, right): return "value: \(value), left = [" + left.description + "], right = [" + right.description + "]" - case .Empty: + case .empty: return "" } } @@ -30,7 +30,7 @@ extension BinaryTree: CustomStringConvertible { extension BinaryTree { public func traverseInOrder(@noescape process: T -> Void) { - if case let .Node(left, value, right) = self { + if case let .node(left, value, right) = self { left.traverseInOrder(process) process(value) right.traverseInOrder(process) @@ -38,7 +38,7 @@ extension BinaryTree { } public func traversePreOrder(@noescape process: T -> Void) { - if case let .Node(left, value, right) = self { + if case let .node(left, value, right) = self { process(value) left.traversePreOrder(process) right.traversePreOrder(process) @@ -46,7 +46,7 @@ extension BinaryTree { } public func traversePostOrder(@noescape process: T -> Void) { - if case let .Node(left, value, right) = self { + if case let .node(left, value, right) = self { left.traversePostOrder(process) right.traversePostOrder(process) process(value) @@ -56,10 +56,10 @@ extension BinaryTree { extension BinaryTree { func invert() -> BinaryTree { - if case let .Node(left, value, right) = self { - return .Node(right.invert(), value, left.invert()) + if case let .node(left, value, right) = self { + return .node(right.invert(), value, left.invert()) } else { - return .Empty + return .empty } } } From 95cd7732290fd1b9c100adebe2d52dc96ef12f17 Mon Sep 17 00:00:00 2001 From: Nagasawa Hiroki Date: Thu, 15 Dec 2016 08:57:32 +0900 Subject: [PATCH 0673/1679] Update README in Binary Tree --- Binary Tree/README.markdown | 42 ++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/Binary Tree/README.markdown b/Binary Tree/README.markdown index 4b5fe7180..52089b8e7 100644 --- a/Binary Tree/README.markdown +++ b/Binary Tree/README.markdown @@ -20,8 +20,8 @@ Here's how you could implement a general-purpose binary tree in Swift: ```swift public indirect enum BinaryTree { - case Node(BinaryTree, T, BinaryTree) - case Empty + case node(BinaryTree, T, BinaryTree) + case empty } ``` @@ -29,24 +29,24 @@ As an example of how to use this, let's build that tree of arithmetic operations ```swift // leaf nodes -let node5 = BinaryTree.Node(.Empty, "5", .Empty) -let nodeA = BinaryTree.Node(.Empty, "a", .Empty) -let node10 = BinaryTree.Node(.Empty, "10", .Empty) -let node4 = BinaryTree.Node(.Empty, "4", .Empty) -let node3 = BinaryTree.Node(.Empty, "3", .Empty) -let nodeB = BinaryTree.Node(.Empty, "b", .Empty) +let node5 = BinaryTree.node(.empty, "5", .empty) +let nodeA = BinaryTree.node(.empty, "a", .empty) +let node10 = BinaryTree.node(.empty, "10", .empty) +let node4 = BinaryTree.node(.empty, "4", .empty) +let node3 = BinaryTree.node(.empty, "3", .empty) +let nodeB = BinaryTree.node(.empty, "b", .empty) // intermediate nodes on the left -let Aminus10 = BinaryTree.Node(nodeA, "-", node10) -let timesLeft = BinaryTree.Node(node5, "*", Aminus10) +let Aminus10 = BinaryTree.node(nodeA, "-", node10) +let timesLeft = BinaryTree.node(node5, "*", Aminus10) // intermediate nodes on the right -let minus4 = BinaryTree.Node(.Empty, "-", node4) -let divide3andB = BinaryTree.Node(node3, "/", nodeB) -let timesRight = BinaryTree.Node(minus4, "*", divide3andB) +let minus4 = BinaryTree.node(.empty, "-", node4) +let divide3andB = BinaryTree.node(node3, "/", nodeB) +let timesRight = BinaryTree.node(minus4, "*", divide3andB) // root node -let tree = BinaryTree.Node(timesLeft, "+", timesRight) +let tree = BinaryTree.node(timesLeft, "+", timesRight) ``` You need to build up the tree in reverse, starting with the leaf nodes and working your way up to the top. @@ -57,10 +57,10 @@ It will be useful to add a `description` method so you can print the tree: extension BinaryTree: CustomStringConvertible { public var description: String { switch self { - case let .Node(left, value, right): + case let .node(left, value, right): return "value: \(value), left = [" + left.description + "], right = [" + right.description + "]" - case .Empty: + case .empty: return "" } } @@ -92,9 +92,9 @@ Another useful method is counting the number of nodes in the tree: ```swift public var count: Int { switch self { - case let .Node(left, _, right): + case let .node(left, _, right): return left.count + 1 + right.count - case .Empty: + case .empty: return 0 } } @@ -112,7 +112,7 @@ Here is how you'd implement that: ```swift public func traverseInOrder(process: (T) -> Void) { - if case let .Node(left, value, right) = self { + if case let .node(left, value, right) = self { left.traverseInOrder(process: process) process(value) right.traverseInOrder(process: process) @@ -120,7 +120,7 @@ Here is how you'd implement that: } public func traversePreOrder(process: (T) -> Void) { - if case let .Node(left, value, right) = self { + if case let .node(left, value, right) = self { process(value) left.traversePreOrder(process: process) right.traversePreOrder(process: process) @@ -128,7 +128,7 @@ Here is how you'd implement that: } public func traversePostOrder(process: (T) -> Void) { - if case let .Node(left, value, right) = self { + if case let .node(left, value, right) = self { left.traversePostOrder(process: process) right.traversePostOrder(process: process) process(value) From 733487f53eadf59a7c702cb8f4db04297db64a0b Mon Sep 17 00:00:00 2001 From: zaccone Date: Wed, 14 Dec 2016 18:58:09 -0500 Subject: [PATCH 0674/1679] Made improvements suggested by others. These changes cause things to be done in a more Swift-like manner. Also updated the project to Xcode 8.2. --- Trie/Trie/Trie.xcodeproj/project.pbxproj | 7 +++++- Trie/Trie/Trie/Trie.swift | 29 ++++++++---------------- 2 files changed, 16 insertions(+), 20 deletions(-) diff --git a/Trie/Trie/Trie.xcodeproj/project.pbxproj b/Trie/Trie/Trie.xcodeproj/project.pbxproj index 70a0626da..8d3611b6d 100644 --- a/Trie/Trie/Trie.xcodeproj/project.pbxproj +++ b/Trie/Trie/Trie.xcodeproj/project.pbxproj @@ -193,7 +193,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0810; - LastUpgradeCheck = 0810; + LastUpgradeCheck = 0820; ORGANIZATIONNAME = "Rick Zaccone"; TargetAttributes = { EB798DF91DFEF79900F0628D = { @@ -333,6 +333,7 @@ CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; @@ -382,6 +383,7 @@ CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; @@ -508,6 +510,7 @@ EB798E211DFEF79900F0628D /* Release */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; }; EB798E221DFEF79900F0628D /* Build configuration list for PBXNativeTarget "TrieTests" */ = { isa = XCConfigurationList; @@ -516,6 +519,7 @@ EB798E241DFEF79900F0628D /* Release */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; }; EB798E251DFEF79900F0628D /* Build configuration list for PBXNativeTarget "TrieUITests" */ = { isa = XCConfigurationList; @@ -524,6 +528,7 @@ EB798E271DFEF79900F0628D /* Release */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; diff --git a/Trie/Trie/Trie/Trie.swift b/Trie/Trie/Trie/Trie.swift index bd1abc538..ad4e9f2e7 100644 --- a/Trie/Trie/Trie/Trie.swift +++ b/Trie/Trie/Trie/Trie.swift @@ -81,23 +81,19 @@ extension Trie { return } var currentNode = root - let charactersInWord = Array(word.lowercased().characters) - var index = 0 - while index < charactersInWord.count { - let character = charactersInWord[index] + for character in word.lowercased().characters { if let childNode = currentNode.children[character] { currentNode = childNode } else { currentNode.add(value: character) currentNode = currentNode.children[character]! } - index += 1 } // Word already present? guard !currentNode.isTerminating else { return } - self.wordCount += 1 + wordCount += 1 currentNode.isTerminating = true } @@ -110,13 +106,13 @@ extension Trie { return false } var currentNode = root - let charactersInWord = Array(word.lowercased().characters) - var index = 0 - while index < charactersInWord.count, let childNode = currentNode.children[charactersInWord[index]] { - index += 1 + for character in word.lowercased().characters { + guard let childNode = currentNode.children[character] else { + return false + } currentNode = childNode } - return index == charactersInWord.count && currentNode.isTerminating + return currentNode.isTerminating } /// Attempts to walk to the terminating node of a word. The @@ -127,20 +123,15 @@ extension Trie { /// search failed. private func findTerminalNodeOf(word: String) -> Node? { var currentNode = root - var charactersInWord = Array(word.lowercased().characters) - var index = 0 - while index < charactersInWord.count { - let character = charactersInWord[index] + for character in word.lowercased().characters { guard let childNode = currentNode.children[character] else { return nil } currentNode = childNode - index += 1 } return currentNode.isTerminating ? currentNode : nil } - /// Deletes a word from the trie by starting with the last letter /// and moving back, deleting nodes until either a non-leaf or a /// terminating node is found. @@ -180,7 +171,7 @@ extension Trie { } else { terminalNode.isTerminating = false } - self.wordCount -= 1 + wordCount -= 1 } /// Returns an array of words in a subtrie of the trie @@ -198,7 +189,7 @@ extension Trie { if rootNode.isTerminating { subtrieWords.append(previousLetters) } - for (_, childNode) in rootNode.children { + for childNode in rootNode.children.values { let childWords = wordsInSubtrie(rootNode: childNode, partialWord: previousLetters) subtrieWords += childWords } From f27c4aa6073bf35191d651d6d02459c7b38776cc Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Fri, 16 Dec 2016 03:47:34 -0800 Subject: [PATCH 0675/1679] Removes old implementation. Updated README to reflect the new code changes. --- Trie/Old Implementation/trie.swift | 523 ------------------ Trie/ReadMe.md | 86 ++- Trie/Trie.playground/Contents.swift | 16 - Trie/Trie.playground/Sources/Node.swift | 21 - Trie/Trie.playground/Sources/Trie.swift | 83 --- Trie/Trie.playground/contents.xcplayground | 4 - .../contents.xcworkspacedata | 7 - Trie/Trie/Trie/Trie.swift | 334 +++++------ 8 files changed, 201 insertions(+), 873 deletions(-) delete mode 100644 Trie/Old Implementation/trie.swift delete mode 100644 Trie/Trie.playground/Contents.swift delete mode 100644 Trie/Trie.playground/Sources/Node.swift delete mode 100644 Trie/Trie.playground/Sources/Trie.swift delete mode 100644 Trie/Trie.playground/contents.xcplayground delete mode 100644 Trie/Trie.playground/playground.xcworkspace/contents.xcworkspacedata diff --git a/Trie/Old Implementation/trie.swift b/Trie/Old Implementation/trie.swift deleted file mode 100644 index 8227d0243..000000000 --- a/Trie/Old Implementation/trie.swift +++ /dev/null @@ -1,523 +0,0 @@ -/// TODO: - Undergoing refactoring. - -/* - Queue implementation (taken from repository, needed for findPrefix()) -*/ -public struct Queue { - private var array = [T?]() - private var head = 0 - - public var isEmpty: Bool { - return count == 0 - } - - public var count: Int { - return array.count - head - } - - public mutating func enqueue(element: T) { - array.append(element) - } - - public mutating func dequeue() -> T? { - guard head < array.count, let element = array[head] else { return nil } - - array[head] = nil - head += 1 - - let percentage = Double(head)/Double(array.count) - if array.count > 50 && percentage > 0.25 { - array.removeFirst(head) - head = 0 - } - - return element - } -} -/* - A Trie (Pre-fix Tree) - - Some of the functionality of the trie makes use of the Queue implementation for this project. - - - Every node in the Trie stores a bit of information pertainining to what it references: - -Character (letter of an inserted word) - -Parent (Letter that comes before the current letter in some word) - -Children (Words that have more letters than available in the prefix) - -isAWord (Does the current letter mark the end of a known inserted word?) - -visited (Mainly for the findPrefix() function) -*/ -public class Node { - private var character: String? - private var parent: Node? - private var children: [String:Node] - private var isAWord: Bool - private var visited: Bool //only for findPrefix - - init(c: String?, p: Node?) { - self.character = c - self.children = [String:Node]() - self.isAWord = false - self.parent = p - self.visited = false - } - - /* - Function Name: char() - Input: N/A - Output: String - Functionality: Returns the associated value of the node - */ - func char() -> String { - return self.character! - } - - /* - Function Name: update - Input: String - Output: N/A - Functionality: Updates the associated value of the node - */ - func update(c: String?) { - self.character = c - } - - /* - Function Name: isLeaf - Input: N/A - Output: Bool - Functionality: Returns true if the node is a leaf node, false otherwise - */ - func isLeaf() -> Bool { - return self.children.count == 0 - } - - /* - Function Name: getParent - Input: N/A - Output: Node - Functionality: Returns the parent node of the current node - */ - func getParent() -> Node { - return parent! - } - - /* - Function Name: setParent - Input: Node - Output: N/A - Functionality: Changes the parent of the current node to the passed node - */ - - func setParent(node: Node?) { - self.parent = node - } - - /* - Function Name: getChildAt - Input: String - Output: Node - Functionality: returns the child node that holds the specific passed letter - */ - func getChildAt(s: String) -> Node { - return self.children[s]! - } - - /* - Function Name: isValidWord - Input: N/A - Output: Bool - Functionality: Returns whether or not the current node marks the end of a valid word - */ - func isValidWord() -> Bool { - return self.isAWord - } - - /* - Function Name: isWord - Input: N/A - Output: N/A - Functionality: the current node is indeed a word - */ - func isWord() { - self.isAWord = true - } - - /* - Function Name: isNotWord - Input: N/A - Output: N/A - Functionality: marks the current node as not a word - */ - func isNotWord() { - self.isAWord = false - } - - /* - Function Name: isRoot - Input: N/A - Output: Bool - Functionality: Returns whether or not the current node is the root of the trie - */ - func isRoot() -> Bool { - return self.character == "" - } - - /* - Function Name: numChildren - Input: N/A - Output: Int - Functionality: Returns the number of immediate letters that follow the current node - */ - func numChildren() -> Int { - return self.children.count - } - - /* - Function Name: getChildren - Input: N/A - Output: [String: Node] - Functionality: Returns the letters that immediately follow the current node's value for possible word segments that follow - */ - func getChildren() -> [String: Node] { - return self.children - } - - - /* - Function Name: printNode - Input: String, Bool - Output: N/A - Functionality: prints to the console a string representation of the current node in the trie - */ - func printNode(var indent: String, leaf: Bool) { - - print(indent, terminator: "") - if leaf { - print("\\-", terminator: "") - indent += " " - } else { - print("|-", terminator: "") - indent += "| " - } - - print(self.char()) - - var i = 0 - for (_, node) in self.children { - node.printNode(indent, leaf: i == self.getChildren().count-1) - i+=1 - } - - } - -} - - -/* - The Trie class has the following attributes: - -root (the root of the trie) - -wordList (the words that currently exist in the trie) - -wordCount (the number of words in the trie) -*/ -public class Trie { - private var root: Node - private var wordList: [String] - private var wordCount = 0 - - init() { - self.root = Node(c: "", p: nil) - self.wordList = [] - } - - init(wordList: Set) { - - self.root = Node(c: "", p: nil) - self.wordList = [] - - for word in wordList { - self.insert(word) - } - } - - /* - Function Name: merge - Input: Trie - Output: Trie - Functionality: Merges two tries into one and returns the merged trie - */ - func merge(other: Trie) -> Trie { - let newWordList = Set(self.getWords() + other.getWords()) - return Trie(wordList: newWordList) - } - - /* - Function Name: find - Input: String - Output: (Node?, Bool) - Functionality: Looks for a specific key and returns a tuple that - has a reference to the node(if found) and true/false - depending on if it was found - */ - func find(key: String) -> (node: Node?, found: Bool) { - var currentNode = self.root - - for c in key.characters { - if currentNode.children[String(c)] == nil { - return(nil, false) - } - currentNode = currentNode.children[String(c)]! - } - - return(currentNode, currentNode.isValidWord()) - } - - /* - Function Name: isEmpty - Input: N/A - Output: Bool - Functionality: returns true if the trie is empty, false otherwise - */ - func isEmpty() -> Bool { - return wordCount == 0 - } - - /* - Function Name: count - Input: N/A - Output: Int - Functionality: returns the number of words in the trie - */ - func count() -> Int { - return wordCount - } - - /* - Function Name: getWords - Input: N/A - Output: [String] - Functionality: returns the list of words that exist in the trie - */ - func getWords() -> [String] { - return wordList - } - - /* - Function Name: contains - Input: String - Output: Bool - Functionality: returns true if the tries has the word passed, false otherwise - */ - func contains(w: String) -> Bool { - return find(w.lowercaseString).found - } - - /* - Function Name: isPrefix - Input: String - Output: (Node?, Bool) - Functionality: returns a tuple containing a reference to the final - node in the prefix (if it exists) and true/false - depending on whether or not the prefix exists in the trie - */ - func isPrefix(p: String) -> (node: Node?, found: Bool) { - let prefixP = p.lowercaseString - - var currentNode = self.root - - for c in prefixP.characters { - if currentNode.children[String(c)] == nil { - return (nil, false) - } - - currentNode = currentNode.children[String(c)]! - } - - if currentNode.numChildren() > 0 { - return (currentNode, true) - } - - return (nil, false) - } - - /* - Function Name: insert - Input: String - Output: (String, Bool) - Functionality: Inserts a word int othe trie. Returns a tuple containing - the word attempted to be added, and true/false depending on - whether or not the insertion was successful - */ - func insert(w: String) -> (word: String, inserted: Bool) { - - let word = w.lowercaseString - var currentNode = self.root - var length = word.characters.count - - if self.contains(word) { - return (w, false) - } - - var index = 0 - var c = Array(word.characters)[index] - - while let child = currentNode.children[String(c)] { - currentNode = child - length -= 1 - index += 1 - - if length == 0 { - currentNode.isWord() - wordList.append(w) - wordCount += 1 - return (w, true) - } - - c = Array(word.characters)[index] - } - - let remainingChars = String(word.characters.suffix(length)) - for c in remainingChars.characters { - currentNode.children[String(c)] = Node(c: String(c), p: currentNode) - currentNode = currentNode.children[String(c)]! - } - - currentNode.isWord() - wordList.append(w) - wordCount += 1 - return (w, true) - } - - /* - Function Name: insertWords - Input: [String] - Output: ([String], Bool) - Functionality: attempts to insert all words from input array. returns a tuple - containing the input array and true if some of the words were - succesffuly added, false if none were added - */ - - func insertWords(wordList: [String]) -> (wordList: [String], inserted: Bool) { - - var succesful: Bool = false - for word in wordList { - succesful = self.insert(word).inserted || succesful - } - - return(wordList, succesful) - } - - /* - Function Name: remove - Input: String - Output: (String, Bool) - Functionality: Removes the specified key from the trie if it exists, returns - tuple containing the word attempted to be removed and true/false - if the removal was succesful - */ - func remove(w: String) -> (word: String, removed: Bool) { - let word = w.lowercaseString - - if !self.contains(w) { - return (w, false) - } - var currentNode = self.root - - for c in word.characters { - currentNode = currentNode.getChildAt(String(c)) - } - - if currentNode.numChildren() > 0 { - currentNode.isNotWord() - } else { - var character = currentNode.char() - while currentNode.numChildren() == 0 && !currentNode.isRoot() { - currentNode = currentNode.getParent() - currentNode.children[character]!.setParent(nil) - currentNode.children[character]!.update(nil) - currentNode.children[character] = nil - character = currentNode.char() - } - } - - wordCount -= 1 - - var index = 0 - for item in wordList { - if item == w { - wordList.removeAtIndex(index) - } - index += 1 - } - - return (w, true) - } - - /* - Function Name: findPrefix - Input: String - Output: [String] - Functionality: returns a list containing all words in the trie that have the specified prefix - */ - func findPrefix(p: String) -> [String] { - - if !self.isPrefix(p).found { - return [] - } - - var q: Queue = Queue() - var n: Node = self.isPrefix(p).node! - - var wordsWithPrefix: [String] = [] - var word = p - var tmp = "" - q.enqueue(n) - - while let current = q.dequeue() { - for (char, child) in current.getChildren() { - if !child.visited { - q.enqueue(child) - child.visited = true - if child.isValidWord() { - var currentNode = child - while currentNode !== n { - tmp += currentNode.char() - currentNode = currentNode.getParent() - } - tmp = String(tmp.characters.reverse()) - wordsWithPrefix.append(word + tmp) - tmp = "" - } - } - } - } - - - return wordsWithPrefix - } - - - /* - Function Name: removeAll - Input: N/A - Output: N/A - Functionality: removes all nodes in the trie using remove as a subroutine - */ - func removeAll() { - for word in wordList { - self.remove(word) - } - } - - - /* - Function Name: printTrie - Input: N/A - Output: N/A - Functionality: prints all the nodes of the trie to console in a nice and easy to understand format - */ - func printTrie() { - self.root.printNode("", leaf: true) - } - -} diff --git a/Trie/ReadMe.md b/Trie/ReadMe.md index 6b28dd189..172ff4750 100644 --- a/Trie/ReadMe.md +++ b/Trie/ReadMe.md @@ -64,42 +64,38 @@ Insertion into a `Trie` requires you to walk over the nodes until you either hal ```swift func insert(word: String) { - guard !word.isEmpty else { return } + guard !word.isEmpty else { + return + } // 1 var currentNode = root - - // 2 - var characters = Array(word.lowercased().characters) - var currentIndex = 0 - - // 3 - while currentIndex < characters.count { - let character = characters[currentIndex] - // 4 - if let child = currentNode.children[character] { - currentNode = child + // 2 + for character in word.lowercased().characters { + // 3 + if let childNode = currentNode.children[character] { + currentNode = childNode } else { - currentNode.add(child: character) + currentNode.add(value: character) currentNode = currentNode.children[character]! } - - currentIndex += 1 - - // 5 - if currentIndex == characters.count { - currentNode.isTerminating = true - } } + // Word already present? + guard !currentNode.isTerminating else { + return + } + + // 4 + wordCount += 1 + currentNode.isTerminating = true } ``` 1. Once again, you create a reference to the root node. You'll move this reference down a chain of nodes. -2. Keep track of the word you want to insert. -3. Begin walking through your word letter by letter -4. Sometimes, the required node to insert already exists. That is the case for two words inside the `Trie` that shares letters (i.e "Apple", "App"). If a letter already exists, you'll reuse it, and simply traverse deeper down the chain. Otherwise, you'll create a new node representing the letter. -5. Once you get to the end, you mark `isTerminating` to true to mark that specific node as the end of a word. +2. Begin walking through your word letter by letter +3. Sometimes, the required node to insert already exists. That is the case for two words inside the `Trie` that shares letters (i.e "Apple", "App"). If a letter already exists, you'll reuse it, and simply traverse deeper down the chain. Otherwise, you'll create a new node representing the letter. +4. Once you get to the end, you mark `isTerminating` to true to mark that specific node as the end of a word. ### Removal @@ -109,41 +105,27 @@ If you'd like to remove "Apple", you'll need to take care to leave the "App" cha ```swift func remove(word: String) { - guard !word.isEmpty else { return } + guard !word.isEmpty else { + return + } - // 1 - var currentNode = root - - // 2 - var characters = Array(word.lowercased().characters) - var currentIndex = 0 - - // 3 - while currentIndex < characters.count { - let character = characters[currentIndex] - guard let child = currentNode.children[character] else { return } - currentNode = child - currentIndex += 1 + // 1 + guard let terminalNode = findTerminalNodeOf(word: word) else { + return } - - // 4 - if currentNode.children.count > 0 { - currentNode.isTerminating = false + + // 2 + if terminalNode.isLeaf { + deleteNodesForWordEndingWith(terminalNode: terminalNode) } else { - var character = currentNode.value - while currentNode.children.count == 0, let parent = currentNode.parent, !parent.isTerminating { - currentNode = parent - currentNode.children[character!] = nil - character = currentNode.value - } + terminalNode.isTerminating = false } + wordCount -= 1 } ``` -1. Once again, you create a reference to the root node. -2. Keep track of the word you want to remove. -3. Attempt to walk to the terminating node of the word. The `guard` statement will return if it can't find one of the letters; It's possible to call `remove` on a non-existant entry. -4. If you reach the node representing the last letter of the word you want to remove, you'll have 2 cases to deal with. Either it's a leaf node, or it has more children. If it has more children, it means the node is used for other words. In that case, you'll just mark `isTerminating` to false. In the other case, you'll delete the nodes. +1. `findTerminalNodeOf` traverses through the Trie to find the last node that represents the `word`. If it is unable to traverse through the chain of characters, it returns `nil`. +2. `deleteNodesForWordEndingWith` traverse backwords, deleting the nodes represented by the `word`. ### Time Complexity diff --git a/Trie/Trie.playground/Contents.swift b/Trie/Trie.playground/Contents.swift deleted file mode 100644 index 89a160c8d..000000000 --- a/Trie/Trie.playground/Contents.swift +++ /dev/null @@ -1,16 +0,0 @@ -let trie = Trie() - -trie.insert(word: "apple") -trie.insert(word: "ap") -trie.insert(word: "a") - -trie.contains(word: "apple") -trie.contains(word: "ap") -trie.contains(word: "a") - -trie.remove(word: "apple") -trie.contains(word: "a") -trie.contains(word: "apple") - -trie.insert(word: "apple") -trie.contains(word: "apple") diff --git a/Trie/Trie.playground/Sources/Node.swift b/Trie/Trie.playground/Sources/Node.swift deleted file mode 100644 index 56faed3e5..000000000 --- a/Trie/Trie.playground/Sources/Node.swift +++ /dev/null @@ -1,21 +0,0 @@ -public final class TrieNode { - public var value: T? - public weak var parent: TrieNode? - public var children: [T: TrieNode] = [:] - public var isTerminating = false - - init() {} - - init(value: T, parent: TrieNode? = nil) { - self.value = value - self.parent = parent - } -} - -// MARK: - Insertion -public extension TrieNode { - func add(child: T) { - guard children[child] == nil else { return } - children[child] = TrieNode(value: child, parent: self) - } -} diff --git a/Trie/Trie.playground/Sources/Trie.swift b/Trie/Trie.playground/Sources/Trie.swift deleted file mode 100644 index ddce0ba84..000000000 --- a/Trie/Trie.playground/Sources/Trie.swift +++ /dev/null @@ -1,83 +0,0 @@ -/// The Trie class has the following attributes: -/// -root (the root of the trie) -/// -wordList (the words that currently exist in the trie) -/// -wordCount (the number of words in the trie) -public final class Trie { - typealias Node = TrieNode - fileprivate let root: Node - - public init() { - root = TrieNode() - } -} - -// MARK: - Basic Methods -public extension Trie { - func insert(word: String) { - guard !word.isEmpty else { return } - var currentNode = root - - var characters = Array(word.lowercased().characters) - var currentIndex = 0 - - while currentIndex < characters.count { - let character = characters[currentIndex] - if let child = currentNode.children[character] { - currentNode = child - } else { - currentNode.add(child: character) - currentNode = currentNode.children[character]! - } - - currentIndex += 1 - if currentIndex == characters.count { - currentNode.isTerminating = true - } - } - } - - func contains(word: String) -> Bool { - guard !word.isEmpty else { return false } - var currentNode = root - - var characters = Array(word.lowercased().characters) - var currentIndex = 0 - - while currentIndex < characters.count, let child = currentNode.children[characters[currentIndex]] { - currentNode = child - currentIndex += 1 - } - - if currentIndex == characters.count && currentNode.isTerminating { - return true - } else { - return false - } - } - - func remove(word: String) { - guard !word.isEmpty else { return } - var currentNode = root - - var characters = Array(word.lowercased().characters) - var currentIndex = 0 - - while currentIndex < characters.count { - let character = characters[currentIndex] - guard let child = currentNode.children[character] else { return } - currentNode = child - currentIndex += 1 - } - - if currentNode.children.count > 0 { - currentNode.isTerminating = false - } else { - var character = currentNode.value - while currentNode.children.count == 0, let parent = currentNode.parent, !parent.isTerminating { - currentNode = parent - currentNode.children[character!] = nil - character = currentNode.value - } - } - } -} diff --git a/Trie/Trie.playground/contents.xcplayground b/Trie/Trie.playground/contents.xcplayground deleted file mode 100644 index 5da2641c9..000000000 --- a/Trie/Trie.playground/contents.xcplayground +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/Trie/Trie.playground/playground.xcworkspace/contents.xcworkspacedata b/Trie/Trie.playground/playground.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 919434a62..000000000 --- a/Trie/Trie.playground/playground.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/Trie/Trie/Trie/Trie.swift b/Trie/Trie/Trie/Trie.swift index ad4e9f2e7..d9b3bbed9 100644 --- a/Trie/Trie/Trie/Trie.swift +++ b/Trie/Trie/Trie/Trie.swift @@ -11,188 +11,188 @@ import Foundation /// A node in the trie class TrieNode { - var value: T? - weak var parentNode: TrieNode? - var children: [T: TrieNode] = [:] - var isTerminating = false - var isLeaf: Bool { - get { - return children.count == 0 - } + var value: T? + weak var parentNode: TrieNode? + var children: [T: TrieNode] = [:] + var isTerminating = false + var isLeaf: Bool { + get { + return children.count == 0 } - - /// Initializes a node. - /// - /// - Parameters: - /// - value: The value that goes into the node - /// - parentNode: A reference to this node's parent - init(value: T? = nil, parentNode: TrieNode? = nil) { - self.value = value - self.parentNode = parentNode - } - - /// Adds a child node to self. If the child is already present, - /// do nothing. - /// - /// - Parameter value: The item to be added to this node. - func add(value: T) { - guard children[value] == nil else { - return - } - children[value] = TrieNode(value: value, parentNode: self) + } + + /// Initializes a node. + /// + /// - Parameters: + /// - value: The value that goes into the node + /// - parentNode: A reference to this node's parent + init(value: T? = nil, parentNode: TrieNode? = nil) { + self.value = value + self.parentNode = parentNode + } + + /// Adds a child node to self. If the child is already present, + /// do nothing. + /// + /// - Parameter value: The item to be added to this node. + func add(value: T) { + guard children[value] == nil else { + return } + children[value] = TrieNode(value: value, parentNode: self) + } } /// A trie data structure containing words. Each node is a single /// character of a word. class Trie { - typealias Node = TrieNode - /// The number of words in the trie - public var count: Int { - return wordCount - } - /// Is the trie empty? - public var isEmpty: Bool { - return wordCount == 0 - } - /// All words currently in the trie - public var words: [String] { - return wordsInSubtrie(rootNode: root, partialWord: "") - } - fileprivate let root: Node - fileprivate var wordCount: Int - - /// Creats an empty trie. - init() { - root = Node() - wordCount = 0 - } + typealias Node = TrieNode + /// The number of words in the trie + public var count: Int { + return wordCount + } + /// Is the trie empty? + public var isEmpty: Bool { + return wordCount == 0 + } + /// All words currently in the trie + public var words: [String] { + return wordsInSubtrie(rootNode: root, partialWord: "") + } + fileprivate let root: Node + fileprivate var wordCount: Int + + /// Creats an empty trie. + init() { + root = Node() + wordCount = 0 + } } // MARK: - Adds methods: insert, remove, contains extension Trie { - - /// Inserts a word into the trie. If the word is already present, - /// there is no change. - /// - /// - Parameter word: the word to be inserted. - func insert(word: String) { - guard !word.isEmpty else { - return - } - var currentNode = root - for character in word.lowercased().characters { - if let childNode = currentNode.children[character] { - currentNode = childNode - } else { - currentNode.add(value: character) - currentNode = currentNode.children[character]! - } - } - // Word already present? - guard !currentNode.isTerminating else { - return - } - wordCount += 1 - currentNode.isTerminating = true + + /// Inserts a word into the trie. If the word is already present, + /// there is no change. + /// + /// - Parameter word: the word to be inserted. + func insert(word: String) { + guard !word.isEmpty else { + return } - - /// Determines whether a word is in the trie. - /// - /// - Parameter word: the word to check for - /// - Returns: true if the word is present, false otherwise. - func contains(word: String) -> Bool { - guard !word.isEmpty else { - return false - } - var currentNode = root - for character in word.lowercased().characters { - guard let childNode = currentNode.children[character] else { - return false - } - currentNode = childNode - } - return currentNode.isTerminating + var currentNode = root + for character in word.lowercased().characters { + if let childNode = currentNode.children[character] { + currentNode = childNode + } else { + currentNode.add(value: character) + currentNode = currentNode.children[character]! + } } - - /// Attempts to walk to the terminating node of a word. The - /// search will fail if the word is not present. - /// - /// - Parameter word: the word in question - /// - Returns: the node where the search ended, nil if the - /// search failed. - private func findTerminalNodeOf(word: String) -> Node? { - var currentNode = root - for character in word.lowercased().characters { - guard let childNode = currentNode.children[character] else { - return nil - } - currentNode = childNode - } - return currentNode.isTerminating ? currentNode : nil + // Word already present? + guard !currentNode.isTerminating else { + return } - - /// Deletes a word from the trie by starting with the last letter - /// and moving back, deleting nodes until either a non-leaf or a - /// terminating node is found. - /// - /// - Parameter terminalNode: the node representing the last node - /// of a word - private func deleteNodesForWordEndingWith(terminalNode: Node) { - var lastNode = terminalNode - var character = lastNode.value - while lastNode.isLeaf, let parentNode = lastNode.parentNode { - lastNode = parentNode - lastNode.children[character!] = nil - character = lastNode.value - if lastNode.isTerminating { - break - } - } + wordCount += 1 + currentNode.isTerminating = true + } + + /// Determines whether a word is in the trie. + /// + /// - Parameter word: the word to check for + /// - Returns: true if the word is present, false otherwise. + func contains(word: String) -> Bool { + guard !word.isEmpty else { + return false } - - /// Removes a word from the trie. If the word is not present or - /// it is empty, just ignore it. If the last node is a leaf, - /// delete that node and higher nodes that are leaves until a - /// terminating node or non-leaf is found. If the last node of - /// the word has more children, the word is part of other words. - /// Mark the last node as non-terminating. - /// - /// - Parameter word: the word to be removed - func remove(word: String) { - guard !word.isEmpty else { - return - } - guard let terminalNode = findTerminalNodeOf(word: word) else { - return - } - if terminalNode.isLeaf { - deleteNodesForWordEndingWith(terminalNode: terminalNode) - } else { - terminalNode.isTerminating = false - } - wordCount -= 1 + var currentNode = root + for character in word.lowercased().characters { + guard let childNode = currentNode.children[character] else { + return false + } + currentNode = childNode } - - /// Returns an array of words in a subtrie of the trie - /// - /// - Parameters: - /// - rootNode: the root node of the subtrie - /// - partialWord: the letters collected by traversing to this node - /// - Returns: the words in the subtrie - func wordsInSubtrie(rootNode: Node, partialWord: String) -> [String] { - var subtrieWords = [String]() - var previousLetters = partialWord - if let value = rootNode.value { - previousLetters.append(value) - } - if rootNode.isTerminating { - subtrieWords.append(previousLetters) - } - for childNode in rootNode.children.values { - let childWords = wordsInSubtrie(rootNode: childNode, partialWord: previousLetters) - subtrieWords += childWords - } - return subtrieWords + return currentNode.isTerminating + } + + /// Attempts to walk to the terminating node of a word. The + /// search will fail if the word is not present. + /// + /// - Parameter word: the word in question + /// - Returns: the node where the search ended, nil if the + /// search failed. + private func findTerminalNodeOf(word: String) -> Node? { + var currentNode = root + for character in word.lowercased().characters { + guard let childNode = currentNode.children[character] else { + return nil + } + currentNode = childNode + } + return currentNode.isTerminating ? currentNode : nil + } + + /// Deletes a word from the trie by starting with the last letter + /// and moving back, deleting nodes until either a non-leaf or a + /// terminating node is found. + /// + /// - Parameter terminalNode: the node representing the last node + /// of a word + private func deleteNodesForWordEndingWith(terminalNode: Node) { + var lastNode = terminalNode + var character = lastNode.value + while lastNode.isLeaf, let parentNode = lastNode.parentNode { + lastNode = parentNode + lastNode.children[character!] = nil + character = lastNode.value + if lastNode.isTerminating { + break + } + } + } + + /// Removes a word from the trie. If the word is not present or + /// it is empty, just ignore it. If the last node is a leaf, + /// delete that node and higher nodes that are leaves until a + /// terminating node or non-leaf is found. If the last node of + /// the word has more children, the word is part of other words. + /// Mark the last node as non-terminating. + /// + /// - Parameter word: the word to be removed + func remove(word: String) { + guard !word.isEmpty else { + return + } + guard let terminalNode = findTerminalNodeOf(word: word) else { + return + } + if terminalNode.isLeaf { + deleteNodesForWordEndingWith(terminalNode: terminalNode) + } else { + terminalNode.isTerminating = false + } + wordCount -= 1 + } + + /// Returns an array of words in a subtrie of the trie + /// + /// - Parameters: + /// - rootNode: the root node of the subtrie + /// - partialWord: the letters collected by traversing to this node + /// - Returns: the words in the subtrie + func wordsInSubtrie(rootNode: Node, partialWord: String) -> [String] { + var subtrieWords = [String]() + var previousLetters = partialWord + if let value = rootNode.value { + previousLetters.append(value) + } + if rootNode.isTerminating { + subtrieWords.append(previousLetters) + } + for childNode in rootNode.children.values { + let childWords = wordsInSubtrie(rootNode: childNode, partialWord: previousLetters) + subtrieWords += childWords } + return subtrieWords + } } From e7bc36cf645d11539cac9e2c9ffe098457488ad6 Mon Sep 17 00:00:00 2001 From: Anton Date: Sat, 17 Dec 2016 19:41:31 +0100 Subject: [PATCH 0676/1679] Fix Skip-List link in readme --- README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.markdown b/README.markdown index 4c812b0f3..7ac170a65 100644 --- a/README.markdown +++ b/README.markdown @@ -142,7 +142,7 @@ Most of the time using just the built-in `Array`, `Dictionary`, and `Set` types ### Lists - [Linked List](Linked List/). A sequence of data items connected through links. Covers both singly and doubly linked lists. -- Skip List +- [Skip-List](Skip-List/). Skip List is a probablistic data-structure with same logarithmic time bound and efficiency as AVL/ or Red-Black tree and provides a clever compromise to efficiently support search and update operations. ### Trees From a277fed473caf69108eae0aa3276d7a78f01fa90 Mon Sep 17 00:00:00 2001 From: Anton Domashnev Date: Sat, 17 Dec 2016 21:35:42 +0100 Subject: [PATCH 0677/1679] Add AVL tree rotation example image; Update image; Update image; --- AVL Tree/Images/Rotation.jpg | Bin 0 -> 35153 bytes AVL Tree/README.markdown | 5 +++-- 2 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 AVL Tree/Images/Rotation.jpg diff --git a/AVL Tree/Images/Rotation.jpg b/AVL Tree/Images/Rotation.jpg new file mode 100644 index 0000000000000000000000000000000000000000..94a55df4e3268d5e9f8ed5b63a443beb9d6dda6e GIT binary patch literal 35153 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

Fbwd9 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 **Note:** If you're a bit fuzzy on the regular operations of a binary search tree, I suggest you [catch up on those first](../Binary Search Tree/). It will make the rest of the AVL tree easier to understand. -The interesting bits are in the `balance()` method which is called after inserting or deleting a node. +The interesting bits are in the `balance()` method which is called after inserting or deleting a node. ## See also From 7050669ebf695f1f5b029812fffbff38b83540e8 Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Tue, 20 Dec 2016 02:02:10 -0800 Subject: [PATCH 0678/1679] Modified the queue's peek property name to front per naming design guidelines. Computed properties should not imply action. Also checks out on Knuth's Fundamental Algorithms book page 241 where front and rear is the choice for his wording. --- Queue/Queue.playground/Contents.swift | 4 ++-- Queue/Queue.playground/timeline.xctimeline | 6 ------ Queue/README.markdown | 10 +++------- 3 files changed, 5 insertions(+), 15 deletions(-) delete mode 100644 Queue/Queue.playground/timeline.xctimeline diff --git a/Queue/Queue.playground/Contents.swift b/Queue/Queue.playground/Contents.swift index a8be21b08..a90fa647e 100644 --- a/Queue/Queue.playground/Contents.swift +++ b/Queue/Queue.playground/Contents.swift @@ -34,7 +34,7 @@ public struct Queue { } } - public var peek: T? { + public var front: T? { return array.first } } @@ -56,7 +56,7 @@ queueOfNames.dequeue() // Return the first element in the queue. // Returns "Lisa" since "Carl" was dequeued on the previous line. -queueOfNames.peek +queueOfNames.front // Check to see if the queue is empty. // Returns "false" since the queue still has elements in it. diff --git a/Queue/Queue.playground/timeline.xctimeline b/Queue/Queue.playground/timeline.xctimeline deleted file mode 100644 index bf468afec..000000000 --- a/Queue/Queue.playground/timeline.xctimeline +++ /dev/null @@ -1,6 +0,0 @@ - - - - - diff --git a/Queue/README.markdown b/Queue/README.markdown index f7779aa69..25d6205f8 100644 --- a/Queue/README.markdown +++ b/Queue/README.markdown @@ -68,7 +68,7 @@ public struct Queue { } } - public func peek() -> T? { + public var front: T? { return array.first } } @@ -166,12 +166,8 @@ public struct Queue { return element } - public func peek() -> T? { - if isEmpty { - return nil - } else { - return array[head] - } + public var front: T? { + return array.first } } ``` From 6a66252ad17ae92b068d8e27356b54a526bb7865 Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Tue, 20 Dec 2016 02:11:41 -0800 Subject: [PATCH 0679/1679] Updated the peek function of the stack to a computed property instead. This change is inspired by the Swift naming conventions guide and Knuth's fundamental algorithms book page 242 where he states the element at the top of the stack may be denoted by top(A) where A is the stack. --- Stack/README.markdown | 6 +++--- Stack/Stack.playground/Contents.swift | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Stack/README.markdown b/Stack/README.markdown index 9d157f290..a79e2c261 100644 --- a/Stack/README.markdown +++ b/Stack/README.markdown @@ -38,7 +38,7 @@ stack.pop() This returns `3`, and so on. If the stack is empty, popping returns `nil` or in some implementations it gives an error message ("stack underflow"). -A stack is easy to create in Swift. It's just a wrapper around an array that just lets you push, pop, and peek: +A stack is easy to create in Swift. It's just a wrapper around an array that just lets you push, pop, and look at the top element of the stack: ```swift public struct Stack { @@ -60,8 +60,8 @@ public struct Stack { return array.popLast() } - public func peek() -> T? { - return array.last + public var top: T? { + return array.last } } ``` diff --git a/Stack/Stack.playground/Contents.swift b/Stack/Stack.playground/Contents.swift index f086ca817..1eb705f20 100644 --- a/Stack/Stack.playground/Contents.swift +++ b/Stack/Stack.playground/Contents.swift @@ -30,7 +30,7 @@ public struct Stack { return array.popLast() } - public func peek() -> T? { + public var top: T? { return array.last } } @@ -49,7 +49,7 @@ stackOfNames.pop() // Look at the first element from the stack. // Returns "Wade" since "Mike" was popped on the previous line. -stackOfNames.peek() +stackOfNames.top // Check to see if the stack is empty. // Returns "false" since the stack still has elements in it. From bfeac916bedcaba9555f49f982d96a1e84ce157a Mon Sep 17 00:00:00 2001 From: Anton Date: Tue, 20 Dec 2016 23:40:39 +0100 Subject: [PATCH 0680/1679] Add rotation steps description; --- AVL Tree/README.markdown | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/AVL Tree/README.markdown b/AVL Tree/README.markdown index 22ea99f53..bcbbbabbc 100644 --- a/AVL Tree/README.markdown +++ b/AVL Tree/README.markdown @@ -43,13 +43,32 @@ The difference between the heights of the left and right subtrees is called the If after an insertion or deletion the balance factor becomes greater than 1, then we need to re-balance this part of the AVL tree. And that is done with rotations. ## Rotations - Each tree node keeps track of its current balance factor in a variable. After inserting a new node, we need to update the balance factor of its parent node. If that balance factor becomes greater than 1, we "rotate" part of that tree to restore the balance. -Example of balancing the unbalanced tree using rotation: +Example of balancing the unbalanced tree using *Right* (clockwise direction) rotation : ![Rotation](Images/Rotation.jpg) -Insertion never needs more than 2 rotations. Removal might require up to *log(n)* rotations. +Let's dig into rotation algorithm in detail using the terminology: +* *Root* - the parent not of the subtrees that will be rotated; +* *Pivot* - the node that will become parent (basically will be on the *Root*'s position) after rotation; +* *RotationSubtree* - subtree of the *Pivot* upon the side of rotation +* *OppositeSubtree* - subtree of the *Pivot* opposite the side of rotation + +The steps of rotation on the example image could be described by following: +* Select the *Pivot* as `D` and hence the *Root* as `F`; +* Assign the *RotationSubtree* as a new *OppositeSubtree* for the *Root*; +* Assign the *Root* as a new *RotationSubtree* for the *Pivot*; +* Check the final result + +In pseudocode the algorithm above could be written as follows: +``` +Root.OS = Pivot.RS +Pivot.RS = Root +Root = Pivot +``` + +This is a constant time operation - __O(1)__ +Insertion never needs more than 2 rotations. Removal might require up to __log(n)__ rotations. ## The code From 45b5619710d40c5602cc3f70b2e5fdb3300e22ac Mon Sep 17 00:00:00 2001 From: Antonio081014 Date: Tue, 20 Dec 2016 16:40:49 -0800 Subject: [PATCH 0681/1679] Add missing link for Trie in README. --- README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.markdown b/README.markdown index 7ac170a65..5c769688a 100644 --- a/README.markdown +++ b/README.markdown @@ -156,7 +156,7 @@ Most of the time using just the built-in `Array`, `Dictionary`, and `Set` types - kd-Tree - [Heap](Heap/). A binary tree stored in an array, so it doesn't use pointers. Makes a great priority queue. - Fibonacci Heap -- Trie +- [Trie](Trie/). A special type of tree used to store associative data structures. - [B-Tree](B-Tree/). A self-balancing search tree, in which nodes can have more than two children. ### Hashing From 09b74c41364723dbb9b3752765913b13dcb1c6b7 Mon Sep 17 00:00:00 2001 From: BenEmdon Date: Sat, 26 Nov 2016 17:58:21 -0500 Subject: [PATCH 0682/1679] Mathimatical explination --- Rootish Array Stack/README.md | 90 ++++++++++++++++-- .../images/RootishArrayStackExample2.png | Bin 0 -> 81023 bytes 2 files changed, 82 insertions(+), 8 deletions(-) create mode 100644 Rootish Array Stack/images/RootishArrayStackExample2.png diff --git a/Rootish Array Stack/README.md b/Rootish Array Stack/README.md index 842439a0c..285f39b14 100644 --- a/Rootish Array Stack/README.md +++ b/Rootish Array Stack/README.md @@ -2,18 +2,92 @@ A *Rootish Array Stack* is an ordered array based structure that minimizes wasted space (based on [Gauss's summation technique](https://betterexplained.com/articles/techniques-for-adding-the-numbers-1-to-100/)). A *Rootish Array Stack* consists of an array holding many fixed size arrays in ascending size. -![Rootish Array Stack Intro](/images/RootishArrayStackIntro.png) - +![Rootish Array Stack Intro](images/RootishArrayStackIntro.png) A resizable array holds references to blocks (arrays of fixed size). A block's capacity is the same as it's index in the resizable array. Blocks don't grow/shrink like regular Swift arrays. Instead, when their capacity is reached, a new slightly larger block is created. When a block is emptied the last block is freed. This is a great improvement on what a swift array does in terms of wasted space. -![Rootish Array Stack Intro](/images/RootishArrayStackExample.png) +![Rootish Array Stack Intro](images/RootishArrayStackExample.png) Here you can see how insert/remove operations would behave (very similar to how a Swift array handles such operations). -### How indices map: -| Subscript index | Indices of Blocks| -| :------------- | :------------- | -| `[0]` | `blocks[0][0]` | +## The Math +The data structure is based on Gauss's summation technique: +``` +sum from 1...n = n * (n + 1) / 2 +``` +To understand this imagine `n` blocks where `x` represents `1` unit. In this example let `n` be `5`: +``` +blocks: [x] [x x] [x x x] [x x x x] [x x x x x] +# of x's: 1 2 3 4 5 +``` +_Block `1` has 1 `x`, block `2` as 2 `x`s, block `3` has 3 `x`s, etc..._ -## A Mathematical Explanation +If you wanted to take the sum of all the blocks from `1` to `n` you could go through and count them _one by one_. This is okay, but for a large sequence of blocks that could take a long time! Instead you could arrange the blocks to look like a _half pyramid_: +``` +# | blocks +--|------------- +1 | x +2 | x x +3 | x x x +4 | x x x x +5 | x x x x x + +``` +Then we mirror the _half pyramid_ and rearrange the image so that it fits with the original _half pyramid_ in a rectangular shape: +``` +x o x o o o o o +x x o o x x o o o o +x x x o o o => x x x o o o +x x x x o o o o x x x x o o +x x x x x o o o o o x x x x x o +``` +Here we have `n` rows and `n + 1` columns of units. _5 rows and 6 columns_. + +We could calculate sum just as we would an area! Lets also express width and hight in terms of `n`: +``` +area of a rectangle = height * width = n * (n + 1) +``` +But we only want to calculate the amount of `x`s, not the amount of `o`s. Since there's a 1:1 ratio between `x`s and `o`s we and just divide our area by 2! +``` +area of only x = n * (n + 1) / 2 +``` +And voila! We have an interesting new way to arrange our data! + +## Get/Set with Speed +Next we want to find an efficient way to access a random index. For example which block does `rootishArrayStack[12]` point to? To answer this we will need MORE MATH! +Determining the inner block `index` turns out to be easy. If `index` is in some `block` then: +``` +inner block index = index - block * (block + 1) / 2 +``` + +More difficult is determining which `block` an index points to. The number of elements that have indices less than or equal to the the requested `index` is: `index + 1` elements. The number of elements in blocks `0...block` is `(block + 1) * (block + 2) / 2`. Therefore, `block` is the smaller integer such that: +``` +(block + 1) * (block + 2) / 2 >= index + 1 +``` +This can be rewritten as: +``` +(block)^2 + (3 * block) - (2 * index) >= 0 +``` +Using the quadratic formula we can get: +``` +block = (-3 ± √(9 + 8 * index)) / 2 +``` +A negative block doesn't make sense so we take the positive root instead. In general this solution is not an integer but going back to our inequality, we want the smallest block such that `b => (-3 + √(9 + 8 * index)) / 2`. So we take the ceiling of the result: +``` +block = ⌈(-3 + √(9 + 8 * index)) / 2⌉ +``` + +Now we can figure out that `rootishArrayStack[12]` would point to the block at index `4` and at inner block index `2`. +![Rootish Array Stack Intro](images/RootishArrayStackExample2.png) + +# The Code + +To get the `capacity` of the structure we can use the equation we figured out above: +```swift +var capacity: Int { + return blocks.count * (blocks.count + 1) / 2 +} +``` +Since Swift arrays check `count` in `O(1)` time, this capacity lookup is also `O(1)`. + +To solve the problem of which block holds the block holds the element we are looking for we need diff --git a/Rootish Array Stack/images/RootishArrayStackExample2.png b/Rootish Array Stack/images/RootishArrayStackExample2.png new file mode 100644 index 0000000000000000000000000000000000000000..d032833bc99931702053554e2292d5da988ec419 GIT binary patch literal 81023 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

OSm`O{(p!p zynw4^i4kw%*$xOHZ14CrWu$}CEo$dN)S5S=FyZGW89bQG(CN~7S*D3ia>!55P3vvv zsXQLcH`bRFwAnppwG>H1Erzf1iLS;nq{H$GsI@FzK~D^lD9SyID^rB`93lgj&JE9Qm6rgeOCgoWyMU}dr~B z_B=*=t2QwQi)Gnyz2pyeFAz4d9WSNX2?zacL7WxZqZDqeePD=^vXAaUD`BXHC!3TA z5S}BeXx@AvhlP8AgK-$Yg;e{na^g@$>d-uz%$%Fnp6X!e<;WePjNmll=^4LcSk!Wk zf)rW98-!xwiOV&mz)1$N_8=lNVKj)2VmV(WAKtUM8bYv)+YcT;sFSmp2C(8yIt#wP zJh^|_>7yIV{bN$W<6oMwl;)OA$(U>|^cW?&UK>PBqhxC_fq*vH0%o&tnJR@IP&)+`)0w+@Oy zSZVP~ER`H%mD92Va&E@RMwCCf;T*+M;EzI~{YT#>e0{|1OaR4I{RM_WJ)B@n=m+aN z@itO~-k8{`Lj6Me$^M|JRU*24NV)t@o9z$wez$&wQJN22^vKx3**FR7YknJ_$kjYc zsi>%+kQ&QR&up@T83RIl(Bxv;xB{gglu$Q?VfLkJ8Euh(7%Jk{68og6v z>jLOI?*<1kv%5{-M$gK?vK3scF(GeB_S*9GnR_wJ!>Jv_p+W_^o+N=N5^@q!*h=lc z>*BH|Y-mI5@B`kiTW@10zQF;6C?2i)Z5f;ymR);`J~ONn@hcTXN@e~aWyytFq}lvA zCt7(WR+n*Yxpne{Z>{WJ-c>~9?>14@pg&P*I}qw&p`8;c!t#Xe*l~XoCzz)e96eXwyz@r?-NCns zuUS(F4lTKwx}2+PxL4es8Q5Y4F5CKjorgWVB%7B5B145>n`URCgkt+agspf2S9h** z)C@J@C$;rV$FwgP%+D+1HrX%P_Z*B>jI~dnlRYTgT;M?6ELynVruUipt&pnXjo&#H zP6JXvJJ%O{Kc?9V%{GwC(nIZP!cvF4|3YQ0lL_U?AqB7B-Jq*!NPl9?)FZjxV^(Og z^vMv{X)FDvcBxwr9YOtA?X50EMX-E%#JVCTi3;6W0}EK|Yt55S!&1%dooq2-mvk|Q zi_2et~9Q;K;sO;1wR3HLpJ=N^*(JznfNNzir-^~N;=SdL{wq{?@XfCQmDFMH}5G|k` z8s8E+@VdQIX|NnVY7rtIhz7qoC(`gE5(kwEI)1HKrddhu zd$q*EWb0M8mVG{j*Jwd(GdcZ3s~MGrds*8dVr7k2^_}^DUf7OZ@OwPaY^t^Zyr(OI z8x#=;bd_>c@VA|^b;G#T%hSvM&~2}yFt(YET$!0*S?KKU-P7qi^P26$BT!!z}pwZj9|SVh$J+ksB2V+X3Hpz)f9 ztbUyS;IKze;$WqZ*JF_5c=`%OJzoemuVW`FCPuC_-Bc}p&L~QSAa_?%f?mRRVm4{U-?#Zlbo14>EGy_9SLk82> z&&W&GLCc6fK61?qX*UUZ@qrj|S{Ti2_sbfvtu2Ph(KN(mwJ4oqw721=Cdk0Q86CCY z$Lj+nq-jWJ<)%{vL&UuvbU55xxXp3;>^7|`;4HSZsxLAvEv*k*T$nXc_27wfpgm^L^%z09%l` z2;gi2mnTOJhF4{0esrCA{24dlUa>!)3CtmGbenJjCw3M?UBH2XI-x#s>0>8OD?2ti_PwW!D$c#gox88+}6m7+4MtaLV9lt z(0wrEZAdjP1%gge)C3M$7fdRRC#*;<&&Lt z@|Ck=c9nqWs1J{NF4LhhQkj913WY_W*f(o@0c58u&us@?TqhyW;k_&H?aBQw_}lg4 zkfCgRq3OoEn{$_HUr7)(dwn^?Mn74R{~XsPR30!^VP9SHKwj+FGby8~5xsYZ*SC1^l1VGZ zFnMj2gZtaQ;-wJk$8Hwqj_KSN3zA>k?H>q_+vsH_dqwSYcfQ)`5irdnK2N_jcQYk; zs|Bq{B4=Q)#FwX^&Y*Fk&8IjWJG*#a#I2LYWAvF3{s9E&)Rrre1aDJFGB+M{0a{3Q zbN5D*vxB4-M(M70W=B3*Qi_8%pLbfP9uuh{pf#uwrmtZI^9Im_Kv4igPK5%rDP+7O z6}&%v<5d0gHkq0SKb~t#f`#nyX!aVyxrRUWqB$h3w;OrdOHH-0+WM)ngYeH)NzPv*6gW)9j;H9KqW_9}7fEJ#jt= zh@JVSY^&|nB@R|dd}whCq^~>A=vy$$S1{7~xrsfJdxSq`DPiBwz2J{Q+&u$GJ|#!^ z4mE;qr^*p$8TkHF~VulV>$c;q}wsE%Nx6h)&yz&y4oS)TsPJQlHg zzqHxM%*rN1m`~yH{jATWL%&ZLsb1TLK@}UEi|hY>FIQ2;WEHk!>P!T{Y>?{<4#D^x zsSIC6Q7%Z_hj7t88E(O%hAVxkx4>G!We)1@kyAKp>^gD=+TX@lK`Oft8Ta#xx<@=$1W`VhT_5uTh{b@}^o`{Ber}xy`Djktb z>ANCqaj8sU!M@dyDf^I%#IYgTemUHuRktS*%S@s(8?^%H3E2{BPalnDKuz$#869iW zb5o^lj>9E336Cr+K&w^MU33l(ez;Fll=S?n>xy^Hy+fxrk$9C4<#A1t9Q@8f_Ia4f}^7>BKd-L^7G-|`tJMM=^_2BrR@6?>x)GhV)#-?;JX7?ICnZDPuyhN&3f1){N&v^N7`q(X}h68)t3X^gxXAhW)jT;Qi4@l$d`Q48}Yx1RHgs8Kv2yJw&DI2 zvMtuNGgY}p>V~xSS3DPLgI9DAo>aL-N!!P*d4VqchJcEsg-M-IUgj~8zoxVNeg*<5 zyQq0sdZG*1ynq==62r^=I{7J1zrpbOD=jGu67*#8xdR&z@7s zpFIE1{OxB+VF-s6jqC4=pwF)eufq)+U2TJwKc7=}I`|e<5hc#|C<0%ZD_(r{*ZhZ- zBGq;P-2;bPR4;!~_*07FtzL(16ni)mz+Z;l0_W~L0s2%PXo$5Vr( z?1Fv*XXUxGrNly)kCrDzRd)|DXTbjHqY{R&=^2QA1{+6aLI_AkW=e_{09vbYz$Je{ zFAO|YiHSro$_qj=3TD5|yRk4`8_r2YIGuJ8!e5(G zT}y@m>{q)x_by1kHy4mqD;Ll{VU34T+Uo+Cni4+#<1nsmHHIw&SuUEu?sl#FS|M{N^ftO)0P(@dPwF(xTr&Ehd^QTC{TPn40}MJWmw| zNKs?dz0|j1-7`vFfJDhLqaBVIGQpE`F7}W0E#+<@CyV}pn)8_?V!j(ur)S;MY7|?y zFia+$m;I)hw25;@J#=#nmKg}uzxC(+B4=Od;RsQQE%kBeeILqMbXw!?0&#*?)?&{V z`EbgAnRL(qyDde<-u)pW3rQX#v^B@<#_vsYk?2(C<$R1-?B?-UY90!F5smdbpMXX` z9OeFRwF~{h@R46@sULjlcbnOfSPt11L6T_l*bC<0a8bg$O6J#Z0sL*kx2;cY{U3m0 zUk#j<%`Mwu81Sv1RaLjO)ix)T-{g=NE3^tUajLH2h>i8e7Pms9+1YG*dTbm5IN(nf z9o(XnT-H2xzy5smg@rD!2YR8zC9tGlGIl4Gi!C9oA1o4ZcA*OA7q=}xHp>QQ8j|_j z(tolrwDsKEJLXkxocc{VIW_)n&10KAjEVbgl1-`aYazNFdpcYT>ZH}`_(Jx#zA(jA z_@VYhJm9cGeORa&8fZaG-!-<;srFe}`FhV^+2`BA?hQ0L&Vn|fku~|9BL}bs+UlYO z)giUv1Oa<64qblU{<@=m(NQZ3^c*Fbta+j%ONhQuX5?y3o&aWTU)wo&xe1L&Np=#{ zKQ8^z{UH}~iUFd`5PWkANSM0`3N-eV$OeCG5%-nfnjG648bm)wKFTuMSMNtwM-@P! z3flxJkf&|m)=e7#6R=>xQ^iqGXEt~N*Pjnbuh~kGSp(WYqM6Vzh72Z}u%CC7Ant3& zx|@EP1>vt`r|$1ic{-$V$c5I9eOxRUdwm1IJYQuqx$iF`=ybvb9V5iw7jRH2JJKmW z_(%oF8Xf}*(JGy&mUU8FdRCh>IWYD*1VK}?qc)o)U2{sk64+7ROXY!;XQ{lt-4r(X zs~3lNIT?Q0t3YeH^gBLRWz>dZPwwF?f3P=ebQudlhTUQ8E&9&=io6Mo%3#5Epi)VZ zoTEKRM#0P0OcyiHd(XtnIq0!ZsUv*q!=AeAkF5q7*`IM z8@Y&_qnR1?qAiT_WCMLpq0x!Jw}4kGKWvejWPAsQKJp8;t#vu989iL|g-sa-<88t9 zIUOPW_pmBoHd$u6ZCP|8wkjE6RrPVOhUnZAvssgDaIi>uo3lB;kQf+I6*^RuCQ%yw zL8whZVx3pr4>6)L)6G{QAO%J=^-O}7F&}IQkums`!Bgn3E(Q>)!{!_xc5tAY5?l=1 z?e`cKdOqLxA56Py`BPbJf-LYk!`^hLxV%K#ELez?LBPA%;nEC0Iy;w|8IRV?NT?vu*T0-OvwLcd8z_f zWqhC)GuF7DWH@E`9lxnU-MwFB+f$O#)OLft)y-U&e!EW7M6Pym+0Q#CVVp_ZL@uqd zePg1Ry7P1DI3!)%`^=%u6^=f`%*-6-;eChmm}_ePN$OJvxd*E}UZIL|iyY#WJrz(R zUKZUpHu0*d%p@vd48ZIS!)Oe=HGkiBu$VQwQ^iSYEC7c`;On3R^+DRsJ@sNbfzHP9 z`(cXlmvPVlc-z(TR&@Nc^`8jb9Ef8>+Pf4{r{LUZ@4xDZY8aLH2mA1tRFxo=hwt4T zN@w2d~$CSN~*wP z1Bp@#>V28qRK67Nx!LO=Dyee@5eQAEuQBcBJ+f-B*ppjv>h+)l5@Ki)W2R(e{i7pJm&DNM3zO#uT-mrSF$)hv`6 zo8%=F{Ir%Y)$f_>i4bFNcq~<~J9Uw2r1vKCw`P7$m4TOQ=Lft?-)*z40-@jTn{mw< zGOP{k+Vgo~je?coAe^2^v6DG|3~ei7^~lAvY9>O;ZH>WtFU*;VFo`Ax2OE^uJ9dLP zn?n485tL?i9eLaXEo3PxkMrTHyn$)L7}F0TCz-ZBG_9`?{IPi;8k|fcO15(N zQm;@;Qt{8Pt-w}UCF?e)oywvH?ieqR$Q%gMLnJ#0j=!P7J(72Mz1^D9^QFcX{am7B9J!^y$c z1~MyeaEUAnj1A7r=`o~M?oms{wCT;qSojvF<7em8=sVM7g#`Sjs_NdqIO6`%pnZe% zYe5`YTW@xY3IyxrxafoyvQiI}HO@4W30-ey zTVK4-5iw5Z=7v4k#=8h%;fWLM3`mQ&_?ZW=q(JL|WsL!N+6s=9DXk{zXoE+CUr6mj z+_Y{7YE+X~`0Y9EMEPXcIHZVQpr(MGIbF2Q!khv0aI9=iJ|KmbX!{ARhN_c9MZ@_v zbvqKXOP4NfwM)pRW%o2R50E=*p;XAZA!8!r)UY=EUNoYcF<~V~*Q<%e08-;66t@?p z-(i!UW{vnX^0of67N$J$7mhs&B+gz`ZB{G~^rrzxos!ZdqhshCe_8&VW?p3ev#u`) zv`)Ta$K0g_luvkq1qbT@b|Q-8YKQBnX#kj4+ASqKo&vWKb@Y@K!S4Ni@Wc-QCI(cWwJBcpk5gX#N96h`3BjT@QKRxIQMrJ!j<9hLh^nTy*-e`xR{) zkE>s95&-pX_>b6hSh$_6P9Y4RTM zoSe-2`0FaxF&u8`M+!#m{ra_T<;iAz``DynMnB6J_&Br4fU&wvBoBgg4pgu8iS%So zZ2H*7VCY$wRRFt>_%X!vbUgiZdDk>FvC*}n!int@4{c9k6h19o2 z9p3-xi&4(}&Nrt<26``()m_4OZpu#0|As;o(E##3O*8Z6C3Qz5 z4i!EwS`xRuitDe{@c6>UlGlP#k@=kzJ6fpyBb_^v@G+A)be?809KJ$4=&A55jPH)W8SPeq(Q^PSdh96WaRh^2^OIt;$Gyo8 zO=qJkROQhUl|ti{#b6!a4G<{BEOk1vbm7k^m}Q5i#?Q_C$d155(jJ4 zxgo}8yJ{6@z22SsFMSW46(lv7&nlcDTdYu=f9vJR(HN{G=OqkGbk5gU8MWnO-o~R! zWMn-7YQAdD@Dbx7DPHdR+5_lq4m}l!lbU11uLV=tm_R^Y`kU z_jCDgQ*fS=M7xy;)w9JoMWgu!?ewkoB)^{(bql5O#UE`D5X07dYPHtKj*m~^x_Lj$ zp7P%uilKH5w=Tf;a4poriHpk)%l5Cza2RDL=m|v%scL8V`xGx^i*|BPnJuu{c^Xe9 zrg!y-)xQR+&z{opz7bZl{>J}Mf@gV|H}{DS=7!OPgg{&(54L>5Jq@?US5tZ0y?Cbifww!k5P~75 zvxd~K;UAy>GJ35R6?|)9s+ud;`d-ky7DMOTR(^j(qkyZ)hUL&fS9WIxPeUa}rKvnR z%B}#;TqW?t+d5jtc)0%!eNjb)&=NZ4?I&?DvFNw&nEy|lzL-opmblJ^oat-s)2rkD zO5@)BHQ<1)*5)0V3-8}_83@J}G>enB-Rb47h>nz-Tt&DC@&~-<*+kGHm{|-=8Ahjs zh4fur`zDrOCWCmLjO;%Vs6heHNFZn>^U^C26M4w~?AT@u6<8klUBqV}wc!5{4ZawB%+nmD4OY(tER2K& zx07A}u9M?zZ5EVIfPw3$*8*DtN0w?cjhAhKt?KS|r(y^19hGbEjApv3#eDdv{E|7@ zf(3kC=^0=rCRCQbFWkw%mB-<`KvNyGV5q60f;!0Ev!Wv;aQQaGpx`oY&m5O7(U~^X z!!f+-9=ceczul*g-;RqYY=s6dUu-dkz(#*c%3y2bu_ zmShCG>@7GP047}%)3bnOb5Y6^_rkUAW{gp?+8iXtWLAI^D#OubHShHn~$4jaZ=ytax zhRZ&$-T>a!@UJt2N;od?$Gl21_i%19VTV?b;g^*rsd6cq`5hI-|!ds617Kc=Ayz@7kMTXH{Gvd^c$a+H0?Bk$*JGE)uJ2fivU8%Xq6`b<89U04lo z!|#vIMnDRN@?0oEdb<7LS_EW|wZ02#XT7TCk%ZL)(<Y#VH+b(G|ZOIALK~I#}4?zo8h&JlQt7;YU z%>Q(?+>(*HkNO&(OQqk~k3 z+$zXmv(NUiQ@;s0Av=-l-%kl%*)sz>^{b()l1BXSXB`>`8MD{7hDxMx8EHl33i7;A zI_`$4DPLjpfayKIkWor7GJjjHwqQX-{D*F~&AqtTNJIvs9!i>%D?8Y(8M}R7`@L(F zuu2*uZ>Zh}eYTa7)>gupJ;xiq@835tUpg504PV1U!t85hV13akq> z*X8~K5A7EzuM1{McPKQfHMf(>h^B*k_h*g$%Cd7B zw%;;U65TUP?pmJUB$hKj$4aLYf9@37{+d1X{n>gi0FUU6e**Z2CS`-vOUAS(p^(o@?)XV@o5wf z`_pJ7tUllPg6<0WJ4i<0+|Jn58U^t}z{l;-C@bz8kRUa>i`B4?@xv~jqKvNrIHYWoXq70bQ@w@jTTokncK=pLtE(Mg>)Y0UZI3pUWU1mc zQrv$@=>HH-;KH+cthtLqo;j zLs4mTXkiw+eFlDDw|DuH$U*7VfeLuGstTX~QNZ-Dh-|8Xe)(JYQGA^9>YNxPfjU?; zD^N5S$if+j%+#6D8MUBS>W1C?=}t~20A3k)gK{DQ#3Y;%u-oI|1ucO#f%{-vol-Nr zIl4O@34IIL*EJOjP~EjDR=RWMh=4}zcHFRQ$Ef%(aVtig6wPhm4vV2SeBoEc3tKOt8=P#GCf1}W3#}$MQ$p50 zk4>ah35uy7NiIi+q=A{%$NFUz1Idbq=dgW|CduV46|cR_E~(zYFqmf^uv{`*;!Tt2 zJXm3X^eqV1=%4^@7SGrQXRvy7N9xGR^-K&*vzNrs{+H=EJX56x*B<(a9$9&!Ueupbx z6G#f3mE)sCDj)})T}7b%f(QjS&<{*9TlU=094?t&8HdNa@%rm23xtH6*)?_D2HSp8 z4^hcC%ovA4t3>(k7es8;ADF1k%1VbPuCWlv=!}Y1S(M&~5y;eC`8ETG!OB4E75}Zg z#%s?XME>^vUqeYNUw9}^szipaUmQd4zNvrGHOuCUcVbI=_@^Xp(Ky7$Q1gd(N;elf z*`c@Re#C$SrYq-6W_6<@OcwgX!KZrS?(pyl#Su=0b-ql{i32o>WtlceC5>?7+bsj- zcE?5x{fu_BT>^er4zD1{F!27mdICwWU;BjO!LD7%%QrApQ#F5(&h*1&vSR$siffy( zH9%|h_F%1eSKTa=!i^+2V5Po;;PEbLCyvqy34LSY7%MwG5*jwF1<9(_l+ip=ohw=- z)$xBeLPg@5=e3U@6*#t`zayF5&5JWD!~28wp{Wdam}(JmZQCDFZT`t(oP5Stu13L% z#b&0wA-VJEi~PaPKcdTG{B^>(OVR3bbxk*{j5?1_;n}%+B$F*!ZcMUGihXA=ZOwuT z*wpk~b8`T4M22KW+reZ_k|UkNl0vcXSsGYP5G#FWSEDo#TD7u-4p@2A)y%P{)sEfv zvj=wrmn1ty5s2Z`+eIY#|E0HAoJa&11O)_n->Lz9>_jk%l*A;l{l44q(2y*1x6;vy zN>S|a>@bC%5`u1;xJD1xPV=PlNIoPxO`-8~bSAUzR&=pv5F9-^Xl>~DA-TW>WoKxF z<~+lUZDv|x^Gb`A^Mh}7?{;jc`%VDLPagAWv@s+V9#BtIJa_S?ZRj>(e~WbPn#Znw zep-*&(wQk1no7@ceig&>r;}4Tw;eYj)EfnA32=3mS@v5I;_c67wnz~vR{QYP#H~Rr z?n1M>F+4kQqf*ap~)as2<-d&{^ex9<=1h@c|U-6|ptBHb8>C@_R{jDkpa z=Qsu(D%~X@-5rAngGfscB@Er&!`x?3(DS>;SNGlh{NGLPXYaLF?X|vZ?Rzyxq4eva zk@|k4`0lEH=wic%=HQRI~r8-buci&@A3KXAy8#Ci5=fHos>$Elp|lJ zcvo$TT2WPnKN5_tlm)Y1V<%t;Xd8|qy%f_*#bjI=M}ob~$fgZ@VPc&I5*ks~DssY5 zdK9d*HbC2w9X87nRpQ9;vL^;G{P+u|5WN^oTRg?atPGGLs+%yhm14|4y!WGQw{@Up~#t8{}8LIMX(i;`5-Dg$vR?w41*p>(Uw6N8879p zNbjiM(jNJtI2hbAuJ?W(<3**h-r9-bX|!b04=RSM$;z-{ZGGYuf-mIvGShaiwb*`^ zhCE{aqH+f4x~hRS_I~D(dNr`WU&E!xm3e26-&UIGVcuVT_g)%CC6NbyAV9_~4~^dj z`}N_s7|=pmSgJgbW6ven&b$ceB+GNd8zq*=E5B3#Mi($&?W!r3d@*1tC;Xjv-N!Iw zkcsCR*B^T5xelO*hEsqF$)Bo&tg_xbzm`JGX~`FSG)XBVNisqD@M>3u2t}J>1wAOM zl6OFl;hqOto z@N}4}zr~FP<}RpoPno6*D!#DxwSf;vqrcIS)SJ$0{x?7tx&q`dRuw%xPxCRCHGj-X zpV9D0KqNg}bvhw+4N9mta$&M&*nz~4ZRJ=k;cnoLf8$G2QRMoph}hRmH(1BY#GrFs<}!KFhW`Tbmi z$3}~f#&!r5?{#)|_RF`e?hyNKF&t**x_rnV4EaPS#b;GS9}?hms<@Nt0jC2Mw6Z}EN$gd4yv_Sdif`bav2#AF#><3oa) z_dFbpDwkDozC)01)CsS!gio4$y;1dkzVZ0EP*;1Syw>R`&>FzGnhn=6KI0`HtF~&V zWo@AuN0BMrBtAcsKd-7`OOBlS(yWJ*!!IrcgpeE%{Jgo$vkNb}n4x7>ZL#`8U_Cux z7JA>+DvfqSc{gX$3Wd)5e_QWCKJMWT+_|_5Cs7N?&3fZ$2ZI98L^C7+Bk_LMfNYwu(&}p-u&} z9J*7flimfE&WL%s$llId?d+Ghr6pu-aTpDfTQQP*Qyg~RAK;e zY3JgFIay@(P)nVSMGWAWD7&BIhW}y@pjnq}-UztNLW_-r%KidYdv$*!c%(`^=JqGP zjg4W$j;Vz!W`C~m5P*+XLkRBwB;0Kh%_;}e2h#zCYyRXM1U?d$h>|az5-lP1RgR03 zfV{SWjGMPU=tn1xSwjGky|_EFI$XZW%UpA#t4zA5Lx9)N>4hJP7l~(UeQl z4RnITm9YiNIsFiY=Wl1FVr`s;inLq2BvlZ0Gr9&Uo^&E)eRjXL;xX%y2HS zemFk!q>Ya#5tXpbkBPp0H8nM>H^b1#o=W1uO$)s?%`iCw*zLUP#mBtQ9=cj#eP{no zAuAvQxq8!O6tK!yBe57wveyMcC2F5-0c@{UeUQy#*Bw0jrD`EbA|W3A*gG~%$cQw1 zgB-3MzFVqi*WDy(0(%u;l-`IrNPNWde9+V&%c!8OEds2Qj^&oe-dYr&vEmh4!L}fq zkRIElVeFW4cqHGWr3@xdi8}kv<@MYdPFc?%(v8s&I{S1zsyf1VMmp_hXrvpMK0fkk zS5G&QAA2bgOtYyQn7S0I+%=Ed-i4=gx$|X(SF8=^H$s6QFP;7PrF1`zVw+n4&2P^a z@Y>7q_@{+mjXg_y66_~%mNo0j1Dwffam6za<@X`&#K~#Ea8r#4@t-}0&X@#vVFDC8 z!t@we&Nk|lfqwo-dIF;m#^QWW8g%{pyAu^r0`SK;cSz_TW0LvTL+|2FY1o#KX^J=e zKA>{}8uWXNb?RAoWbP)kNWYe3YlP)av(+6BY)m4L0C1 zAdsc!*?#>G**F1L()gV6pMC%S{KeHoKxypv_EVlQ<-cEieFf~w|2_WSG(X$Y|0DkY zH`X)SUy=v^!RyQg22K7J0%`Gzm)2IXW7z-riWMUUyaJ~-@~2M!{rv{eXf~11$n#I$ z{$taioRjkk^!rO;BxQ{3Hu zEfJUv)PSPE4i;q$TKeB_e$qv{te{8`YWNhLDX4zKE;`HCMWR(LJ`615f z^_iml*D8Uh1D0TBh*a#4A^(_2*hgtCxnM*RW{pYBmvtTc)FhlN()bI=In=|x+XS6@ zgulr8oD<+I_;dEZan1@*EV-%=sXaRd{riW|K)`$ByZP4)gF`;Bqq_%-@qco`AG3W9 z&?1pH`tlzi{rP|-cZ?f40ABse_g4)8S_QT|`4@%$pvx%6s?{F5ogOg%92>Ja)OcY= zy7&HQ&pLX;X0>+LNwu?zSvsi~CtV>{eE}Q(%Sw|)y$nCZ5xn->7XHt3=>a3_d}Hc& zc>9m304rd<1st@=2H#vdJG5Pmu2<903(rYX(Ie3;G?2;O-Y@_5Vf*z_v0{w!Ys-D( zUf+gaONY|oYE~vPX}15(L(l~tKKnBo@ITW!8R4odz?CAe`Z)hRr?a1a4F`5A?|JFj z!RQaU!)%`24PdAK@9}5!`qvAnE^gR#*0bf`dxJ@1cvc%W@600i87%^UawuUZSfx-* zOmP3FPjqzWLG*NLeQLHHz9I0n z($^f}ZFqY>x1^_}{90KCqmJNxRDK5`g9z{O9ta}EokKJD2;b+DLt_033!^{8Wu<*? zR1C%owBlo1&s^jQxF)&xji+Ypry+-?05$A9{-z{1PB}w*;&Mr2M^H90p(#5xIpB_< zg%<7Oo{(>whBLVu%@x;BRf8!D*hNfh{T!W*-uQa84PvCNKlb9ynRmsQGJciLbZr8n z>wZi}d)91PIuDzsyy<+v3>>knweob;Thn9Fn@XRLPZBJ~&0aK8Gjr)VyHbBOC|#{c zeT*^pR}>nUW!D$%8qmTsQZwN*J+Mz~g4n-*)VE|*DC9G0nGdELuu7nE9(Pr^vehAB z{++8jF$jk8!GHfegnGE)*O%7RJ{&g>|W2Ttcon{btl%dn>uu!x1TBz8% zU{jINcrf0Ky#I#Bm9pmTLLT+8LQW|iwr%0+75aA}B~@qo7+@6ORIxJRi|M=3f}_3D z+&Wwi@1J#Ue4KxDV{C7C2HeLL0!FX-Ah)i4nas(Wu-&1)muj6j)y{r$a+kftZyiw8 z*AlwUl+hL#%S}s3F3V4>OksrjW~d1}=FM@_m9KQu$GQ`7Z3NG~Vb)hVfRQz7pd)q;mFak>g%q`Mj0AopK{oR*KW{05ZpYwsF!C zA2(_j9vbW1T!DL@G)!%(pgw^GiRV~`6j^$o$|8`tSSR?|F)?*T;8cMEw>G%1M2>{f z0%v!Ldq1Q-(8+IkT^AInnRj{&A-1S*QSM)i4f;JpWDPs(Z(RnQfvG!5Y<1;M_fovP z!IC`6251!go8d@Fr>w&Cp)A6^Y+h_U?o4>nEe3XG?ezVjLZ`iytBr~q@w zz!!eu?n~*GOC>c7<5Algyv|Jr-1z%V2h7Tc(KzchS0IseYB!~m?gLb5N;ofTUC?vz zwYkw4{V8i(b(vwAQDa23bd4g&ub)2kpP?B6@dW%|o?j`-RV2vNMMJ zS`3(tgwKw^6$a2e+@&Dvwj+xik3#cYy1ZKSe3V}GEq$kqsxLPZfSpNFgBD%0ZErYC zU0K|18r`%C$W*-v|N6O^<6aAt_7X3)pMX*zEo@s0#Mb`1ULjsE;nZSox_HtB=YuJ%_p57Bv3OhZCf2J z1?jCXl`{q(E)K&cR*tv9fj&1OeB5HK3QqRIZ({)JUj#~(w*sE^84^mGnN^F{`%|s2 zPY~nFSq~5Q9lJT9^volg7H;gat_)pqrPGtSBEG+8T|CA6kKXA?7dTIsi8BjLUyy$( zZF`v?E;Z%~sZJ)WFwyRnIOwaeJF4XUR0Q5y)S!OdAu1&4h&pm{*{`WEk*@ADY#KmY z55{MBG8qG2;yWGajLUv=HL2souH!}dLqWJ+tB|7-tHIu$A8*AMmCH9ssiW@yJUc>}=1N5@F0Aa3{W93UxZo4B^QdV90ChN2!@52QB!_)xm*~+0^+yH$4wGX5~ zQs2o3zVjvy$QMWl>>U^8^1eb#bMFGaKNL0ka##4l zS+0}%l8adExrh|Nq|7lu>ug(c^3xfJFYXAzVW?r9b+~zcQ=WzwT_;L-a^y~CxSbqC zo1hW)c!{M?1v6n0%E990mc0YL$A+q}mR-Jomam;L$hJpBg^z-c6mk$_@D?V55ZJW$ zLmtF#sBY5yHa-3Lm#cjv3r)^9t@-te3~b`i)i6>@@Yb-h#7D>r$MCbW(ONmw97DLK z8(kUJFkt}{6+i!jc;`F1A57O2tl=O;W>59f077K(gclstk}50NXdnk>7VgjNJ$AeM z3e&z+*VT<9*IH+rK0^CvYIy7#i{Zw|;1gPA@;c_+*dVrRNr>21ROjwdQNS-uu3P!R zbRm(E&$>bsj=vab%JJ>=aP&yM9(<8mZ2N-ZOKG;tHOC|6hM?H=4Sg7&Gx+-$B=jPjxrSLc zx>G3$6F!)0yoA9c4N>eJZ}7m8%S+|xLWG>HS(#WL1JJIJtpL+p5oqCu{1~d}zp$`C zC1Ca>kWS>bqR4bu3LU5%J3icb=u7HO8Exu|t(R8Rca6j4q=lc-RAxw)T+0`)-pjfkUl<9)( zGM5m1HH6-v)T?^n?&jxZ7a9atsH7ILsxg?DV%hnU+EbhugP~l!NuiZQ#y)Z!iWr+y zHxmaFlDJBG?Fz8*Q;(ja@j@Dd@YKtPkDAjJLX|>sXA%>H0)iQfa68o`t#9hHD%PtoNMwT8l=ANTyDqQA8 z1NLXpeuN{LHU06spT3{;7~q0$D(2n8JR6k68$Os{yM4SPCXVv2nEsHw9BCT?Y*h25 z8lZ__p;2qZ>yWKXphNHeTGlZ!(}VjmZ^O2DpHtUb4A!x!r!hYEX?EOv0e{0@PAPG@ zz|@{ozK9+a$0*dN&ZyQG(1t^Bl#}a;VmH`}3Tgfnl0g5Zg9=b4+aX?_?2`lES_!-s zKc-cR#1Qa5KrW(b#Joz_>Nb~4Gu@S+527Qc*LP!^WtL6GYriTf0to;N`I4}KXwl=R zAMk-@(cj5TJdTq;#n-01{+!6LS!a`$ds$S;F6JL-FwU6UVy-643-!4fmnDwqi#NVl zO_mhusF4)3R6)$FO+3he!HeOmTKRQ?1^WdhF20R1Y>!+G3@%6dMcEye@)nS*`P?RT zK{c(yz{z$l@-=(T$QoWIWX`qoDYf+Lt>0Qx!TT@g2CToybACAO1t5JTlZKx3CYaP6 zz`M1sXjACKj9C|@8gD;7<~{y#Y~CQNOD`w#D{>GP19(Z9?G@|5H6J8cEhLBM4d4<1 zle%~lk0xVoJ;d54+neTrQ1jGoegE9d6e4c72d|lr-ALbEPg5y8WO0*Nl9=QYaQ~k$GeNnm2(Hb2U;qG z<{zbgVi+tHA~>IQvoY?lGk}G0&$`gT@FO?wSamjU>FJ)QAzUK@&T?_c1a_V^1DELQD`|6~8Hunt(CY9wsdbx< zvVh16SY)5IHex2-#KIzQz`2$T05|gX=Z}&_FDZR5$>h!hcV(CCGJ>p|i(N*Q^KxNS z3_@VYv&9U$cFiR4_Ec18-)Io~WP|xip#ExGVAJ9Ul*U@GGbHNKN^DOc3+Pw4CP@}( zJF+`BFCYxeQ304^WCqFM^0>HAinaXV#=vCgJ?5Rq%LljgvEE*{nSsevg27w2-D6^uJLVvADVKB#ty5qv~5; zrc`A`^M*Ol8Sz>n(2U5$XyQc@kHR$5FZPA*@V8}J?DOXEA3wv2P(wiKLde%KkUSao zwS%5kWHFv7kZ>xSl*=EC9OU_~MIi`HVCm`yGUptJKpM||FUYmk@ar5d?_xG(Q<(sS z);==-G5_b-2nixFo*2?EkCx((>fQjxeGRC`wvxX7_-&QWQ)ykt#W2l*iH0{0akP{B zdIQb%*Cb2lSG0P5rGb@%v6y#Q?o8ANU=;KanF}iOaIzSjvzpY>gWLq`&{4)MXh1G1 z;XvFDw&rmd4F%7SRM;8{#`dT~@#tI)$L=L#()<^97eM1t<;KThGJPLS3qL~4T1#Z; zQQROr3qQ!wPF|FN>BG(`6U!$GI)=7@R$@1tX^U~P-au$?20JE7%k(wz78*F_C=|G% zgA(Z<;;>hadlsh||6;T*Y(>tJmyIX+;Aq^M7}i3FVw)CsVPbU7cL03jUytbzuUYW) z&QTv2rM5I&p0CvK&5iCnydO?q%0yaPJ>MPF9rfush_#mlbksgtDDhe8LH`&X@_>c) z)5CKB>T1)=+2&jm6WPxPzLZ|aphP=${V*xSX55-8E4h)b34c^b6Fty|q~;OFPRMx& zz-XipJp}N!K<@Bp8;o|`S{*OuEB|7a7qCu_n{Kqqw{G_;yaQL8eee2V0;*cGjP3JN z4i-4RfW-DNJ&u%u-esG)W~s5X1NJlDKutP5nFco0#I|7X6X3r3Bt;gIwM*l6Z z!_)^sq7}1V<8^5}coxz}6GnyxqZ^nZX>ms#KFS^7U;2E6J!hM@Yl}N$d-oZym&NPAgMb^wElJ4Jj86u{HPW!JWa^ zeq~6%imTr6mBC6r($L<-yHdjp){eq2%aMJQ&hU#;RLudfL#wS!I-2u`!x!uBJ@^ed zE&}eSOLSDh2hO*^Ap^KBg-U32_>KWYT4BU~e4F>H_5O&WH;}-X3#*rv+<5<*W3z{2 zt5ak)Zf>;NIRi1D8LmA!njl)D7|1ct(ra$G(=MmJ=Y0LmAZ_bv+~|uYf4}l3)Igxs zW(_GlUYJaNFdo}kEXOA9Wl5*)4FZfEvH>8PWmm%oAyueECeGO!xIg-`FW73Y^hS$Q4JpmJ-4{`)tiKx@DS8XxNMLO6YOR;|Sf6UV|2K5pg#?KWpsmCeMSM1FUCnuG0s=LgUZ7HIh< zjI_Cp#x(pS1&J3@-35^u+9MMN*Bf>xThN=Mn&oK|PvhA(S3+8|ii*)FXyP)6%;zrl z22U4Vb(t5>apxB_#}4GkJBpW$R_K;hFr#EG^JgXY$*qv*v#>(!c(zmA1M6iVo{$oC z6LUM&0#<(d&Y(3uIMW6h3nFZ)2;lKm4PANp&Xp2qa@h46 zM^SQr>dWDbhK7c$j7;aF27%>a@=mF0-taCkX)H}laBNGTBbp?#Bav)q(AD$MJ0sW} zR(hWC;3ar47Xa~kLgAx2$QG75dbBR=TB%%jzE{~%=ch^+#Vd;o;IPAl0LYlvr*5a? z+&z~k_;Y5)%O$HPK0ap0F5%ROu{X$(0%+_smbLx_4HEpS<1rp)_5t|pTZ=RCz#o!}f4v4_<7Dj44D_3m(9Y zQ?0(NGcwSP&#eg~ODsIXY&=?ni2z4kXeD@7P?9)A;tAuhPVJ5IMhT8`cmraA8)|uU zShXv4%OoSsAE*nuP+~vEcB+Zk03#bYnM2D57z!383dXOG+iFKUxp_K7uPNnVoxeyR zULy(vP-XY6-smu(B;yV!?k*0sr>5I2r&RJ9v`kVB%=b05E2G0@{7B+?_eQAL%OPPf z${|vdu^lB{31>$ie8Jw%kb_MagTNP2XI?=|cVUWru_L{gPKSr1cv6TJ*E7688Y|$Z z`WIWBwyJ<)V@Vu5sKAAz_1_om-EW`LtV-s-6I5I10)> z)m|}tmw`7onvHYH`=(K0PDUrdUm$nJKjeK1wt9H|Cx(NiG;*ilnZ&|_3OV?gcJ#(G zN_ZG>9o|8$`)rx|l&|5iVRs-RN_cyx!cN68MPg3}2sMApA0gk?(H=dV@+~8j$PFBa z-J%t`Ezzq#aqPY!+aZq=`3f}t=p-LC?gd-Qk(fU}$6B^p*bm*}FYVV+Cf)3(C}_=H|#<$@f(=7q6bJdY&4=d-8St+A~`%g2L-c2|}g zu5a<$BFR(TYn;a}XsT1l9W$2QK%21Bk_?R8<`v}9j{WSg6jbUMpc>*3-YWp!ACq{! zlb*NVaojt0l+oQZ{KUD;eEaNF#iR6LRTa-m9n;PZYKYx&(0k;vrP@rl^#QX78>~tU zp^^~UqXH+V$?!JWivwitw86tY({tBx_4T}(!Hq<#KS&?4eZYqv8|M4z-1L&7$X%AV zlXPrfT}B8<9c{SA*J)V`!t+l%mq{n%#c9r+^Z#AUFMa3I$DM15rCSkHV+x-Gqun&* z8PpBjzc_@JT8&duxwnI5%??pD=qGUyy|!rG@LjL77ILhZrey{(T!m+WTZepUbRjQ{ zmgLAVy(2&?)Z1Zoa9ckGi(Hw{*i<*685_M86TL3Pck@QoHAg>1|7WLO1p%N!s)5P_AEq;zv}GB{e*z$RFfMvG4(qMs`eR}E#?`}zg$ z^Xp0s$h>IA$Fq8rOdNcfkvSGkUt^-2!Fs*HoA}|+4bB3F*GGa|)qbZGff5@dUW*Z< zLYryk!tIu3gXt{bLOs4+dWo!6e=5H9qP?v&%I1ROu`EUzq|BX5Tlq0W_H}N`OKv;E zg$tjj3o`=-j()r+MQ)%yOatlrVOQZSmrnI6FYaDIa@32*IcMv@VO1jTqtvI^R1JYk zh#}tsv9MjQJ=ETMz_6jUYV(Bp6M~R#WJl1Zl;llGx0!dJ)(C11`I)PJ~Pb-fj(%Gg#Wwq{cobh)1O!uD?NQ%NanpgTW!4G{! zGAHy@GcY#HOJ0&n!`@zX$=bp{{rn+vxqKX@mQ$NDaPi>&xWE70Kt4FkU3M(j-sS3@ zRW96bVP@~W&Sx7mOl=`!Oyu-dgMxy(E6~Q7ixO$->P~CfleKQ1R}Z#wef|CGy7NW3`2nKK3~BKEt#9 z-fB#A4%=T5fTzu+%h&&&%x|Uz)cykSoHQ>Ssxt)ZuSNVCh74#j=+&(d{qpA#>z8gi z85uJSkf{eE1*prIn_~YQ_H+`gq8L9W_V&3`vHACpq%(n&WaI())1&|V_f;haV0JRV zRdZ*{JxhOJUi`X$n*(zN>c77DHO-_s3`EiD8}@I6>DkONFVX-v7rdbHa{Vu}>&8I$ zM#FHU{!Nq9XFbvbNZXtL5Awf34$u?~a9D6HlEI+0 z9aL{V{R?RwF~$yt6^OZd_dm$zub7lGcb($*!=YjI0EAfBA@v`$RiiV?nWydy@QiaE zz@k9q-`qNV_Wz70tpYsjqsq6_B*g#x42nfuzygDK+rpJ!k`33~}p3|GGB+L`+P7tN$QF|byxO;b$W(Vx%# zHM|lQz)j4zTDq>$^;)CB1 z>wj?@^Hn8vEJObLn5D5^gJMuYT_*Vdg9;*IRXfMA``B?N=nu*N^LhU2z$8sF6o33> zjae9Z7TtvZ1p+05K_i!_ve^75fiX`9m@3{C`4@ppA!p@40C4J)g=rI4EM#SCi!3M= z;^t@;rVQSt;Q4c^KygeqfZK7M?mzWu{zVU90dp7;7{D(*RTuxeX&daoIaI?c{%?Gj z2dEF{Q6;?priJv?e1I7L_xOMB$r+9Re@}cP*JXv@Wh&TJS5FXT$z@p>b^*?Lz@0xF z{asBzCB^P0paMHg1pZ&O&6(hQO*=uDwa%2HI55Iq zV)hxhelv%0D$((KAk9=Fu|_{$`E=rTF#k_=NFSNA3H+*y;BG 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 literal 0 HcmV?d00001 From df6e54a0c0eadb4edba616430f247edb54b60d32 Mon Sep 17 00:00:00 2001 From: BenEmdon Date: Sun, 27 Nov 2016 22:32:12 -0500 Subject: [PATCH 0683/1679] Added 'Code' segment --- Rootish Array Stack/README.md | 41 +++++++++++++++++++++++++++++------ 1 file changed, 34 insertions(+), 7 deletions(-) diff --git a/Rootish Array Stack/README.md b/Rootish Array Stack/README.md index 285f39b14..3f154629f 100644 --- a/Rootish Array Stack/README.md +++ b/Rootish Array Stack/README.md @@ -10,8 +10,9 @@ A resizable array holds references to blocks (arrays of fixed size). A block's c Here you can see how insert/remove operations would behave (very similar to how a Swift array handles such operations). -## The Math -The data structure is based on Gauss's summation technique: +## Gauss's Summation Trick + +This data structure is based on Gauss's summation technique: ``` sum from 1...n = n * (n + 1) / 2 ``` @@ -51,10 +52,10 @@ But we only want to calculate the amount of `x`s, not the amount of `o`s. Since ``` area of only x = n * (n + 1) / 2 ``` -And voila! We have an interesting new way to arrange our data! +And voila! A super fast way to take a sum of all the blocks! This equation is useful for deriving fast `block` and `inner block index` equations. ## Get/Set with Speed -Next we want to find an efficient way to access a random index. For example which block does `rootishArrayStack[12]` point to? To answer this we will need MORE MATH! +Next we want to find an efficient and accurate way to access an element at a random index. For example which block does `rootishArrayStack[12]` point to? To answer this we will need more math! Determining the inner block `index` turns out to be easy. If `index` is in some `block` then: ``` inner block index = index - block * (block + 1) / 2 @@ -81,13 +82,39 @@ Now we can figure out that `rootishArrayStack[12]` would point to the block at i ![Rootish Array Stack Intro](images/RootishArrayStackExample2.png) # The Code +Lets start with instance variables and struct declaration: +```swift +import Darwin + +public struct RootishArrayStack { + fileprivate var blocks = [Array]() + fileprivate var internalCount = 0 + + public init() { } -To get the `capacity` of the structure we can use the equation we figured out above: + var count: Int { + return internalCount + } + + +``` +The elements are of generic type `T`, so data of any kind can be stored in the list. `blocks` will be a resizable array to hold fixed sized arrays that take type `T?`. +> The reason for the fixed size arrays taking type `T?` is so that references to elements aren't retained after they've been removed. Eg: if you remove the last element, the last index must be set to `nil` to prevent the last element being held in memory at an inaccessible index. + +`internalCount` is an internal mutable counter that keeps track of the number of elements. `count` is a read only variables that gives the `internalCount` value. `Darwin` is imported here to provide simple math functions such as `ceil()` and `sqrt()`. + +The `capacity` of the structure is simply the Gaussian summation trick: ```swift var capacity: Int { return blocks.count * (blocks.count + 1) / 2 } ``` -Since Swift arrays check `count` in `O(1)` time, this capacity lookup is also `O(1)`. -To solve the problem of which block holds the block holds the element we are looking for we need +To determine which block an index map to: +```swift +fileprivate static func toBlock(index: Int) -> Int { + let block = Int(ceil((-3.0 + sqrt(9.0 + 8.0 * Double(index))) / 2)) + return block +} +``` +This comes straight from the equations derived earlier. As mentioned `sqrt()`, and `ceil()` were imported from `Darwin`. From 1d16285c873b4b7e7d31d6a7de611cdc838ecbc2 Mon Sep 17 00:00:00 2001 From: BenEmdon Date: Mon, 28 Nov 2016 00:32:17 -0500 Subject: [PATCH 0684/1679] Preventing thrashing --- Rootish Array Stack/README.md | 19 ++++++-- Rootish Array Stack/RootishArrayStack.swift | 53 +++++++++++---------- 2 files changed, 45 insertions(+), 27 deletions(-) diff --git a/Rootish Array Stack/README.md b/Rootish Array Stack/README.md index 3f154629f..f6d55b03a 100644 --- a/Rootish Array Stack/README.md +++ b/Rootish Array Stack/README.md @@ -110,11 +110,24 @@ var capacity: Int { } ``` -To determine which block an index map to: +Next lets build what we need to get/set elements: ```swift -fileprivate static func toBlock(index: Int) -> Int { +fileprivate func toBlock(index: Int) -> Int { let block = Int(ceil((-3.0 + sqrt(9.0 + 8.0 * Double(index))) / 2)) return block } + +public subscript(index: Int) -> T { + get { + let block = toBlock(index: index) + let blockIndex = index - block * (block + 1) / 2 + return blocks[block][blockIndex]! + } + set(newValue) { + let block = toBlock(index: index) + let blockIndex = index - block * (block + 1) / 2 + blocks[block][blockIndex] = newValue + } +} ``` -This comes straight from the equations derived earlier. As mentioned `sqrt()`, and `ceil()` were imported from `Darwin`. +`toBlock` is really just wrapping the `block` equation derived earlier. `superscript` lets us have `get/set` access to the structure with the familiar `[index]` syntax. diff --git a/Rootish Array Stack/RootishArrayStack.swift b/Rootish Array Stack/RootishArrayStack.swift index f17f9620e..6cb1cff06 100644 --- a/Rootish Array Stack/RootishArrayStack.swift +++ b/Rootish Array Stack/RootishArrayStack.swift @@ -21,11 +21,24 @@ public struct RootishArrayStack { return blocks.count * (blocks.count + 1) / 2 } - fileprivate static func toBlock(index: Int) -> Int { + fileprivate func toBlock(index: Int) -> Int { let block = Int(ceil((-3.0 + sqrt(9.0 + 8.0 * Double(index))) / 2)) return block } + public subscript(index: Int) -> T { + get { + let block = toBlock(index: index) + let blockIndex = index - block * (block + 1) / 2 + return blocks[block][blockIndex]! + } + set(newValue) { + let block = toBlock(index: index) + let blockIndex = index - block * (block + 1) / 2 + blocks[block][blockIndex] = newValue + } + } + fileprivate mutating func grow() { let newArray = [T?](repeating: nil, count: blocks.count + 1) blocks.append(newArray) @@ -39,21 +52,8 @@ public struct RootishArrayStack { } } - public subscript(index: Int) -> T { - get { - let block = RootishArrayStack.toBlock(index: index) - let blockIndex = index - block * (block + 1) / 2 - return blocks[block][blockIndex]! - } - set(newValue) { - let block = RootishArrayStack.toBlock(index: index) - let blockIndex = index - block * (block + 1) / 2 - blocks[block][blockIndex] = newValue - } - } - public mutating func insert(element: T, atIndex index: Int) { - if capacity < count + 1 { + if capacity - blocks.count < count + 1 { grow() } internalCount += 1 @@ -70,7 +70,7 @@ public struct RootishArrayStack { } fileprivate mutating func makeNil(atIndex index: Int) { - let block = RootishArrayStack.toBlock(index: index) + let block = toBlock(index: index) let blockIndex = index - block * (block + 1) / 2 blocks[block][blockIndex] = nil } @@ -82,22 +82,22 @@ public struct RootishArrayStack { } internalCount -= 1 makeNil(atIndex: count) - if capacity >= count { + if capacity + blocks.count >= count { shrink() } return element } public var memoryDescription: String { - var s = "{\n" - for i in blocks { - s += "\t[" - for j in i { - s += "\(j), " + var description = "{\n" + for block in blocks { + description += "\t[" + for rawElement in block { + description += "\(rawElement), " } - s += "]\n" + description += "]\n" } - return s + "}" + return description + "}" } } @@ -113,3 +113,8 @@ extension RootishArrayStack: CustomStringConvertible { return s + "]" } } + +var list = RootishArrayStack() +for i in 0...10 { + list.append(element: i) +} From c3d03b9b2d56b17bd66eed450e64b58ef2a469c6 Mon Sep 17 00:00:00 2001 From: BenEmdon Date: Mon, 28 Nov 2016 22:04:34 -0500 Subject: [PATCH 0685/1679] Finished implementation explination --- Rootish Array Stack/README.md | 69 ++++++++++++++++++++- Rootish Array Stack/RootishArrayStack.swift | 43 ++++++------- 2 files changed, 86 insertions(+), 26 deletions(-) diff --git a/Rootish Array Stack/README.md b/Rootish Array Stack/README.md index f6d55b03a..790eea6da 100644 --- a/Rootish Array Stack/README.md +++ b/Rootish Array Stack/README.md @@ -96,6 +96,9 @@ public struct RootishArrayStack { return internalCount } + ... + +} ``` The elements are of generic type `T`, so data of any kind can be stored in the list. `blocks` will be a resizable array to hold fixed sized arrays that take type `T?`. @@ -110,7 +113,7 @@ var capacity: Int { } ``` -Next lets build what we need to get/set elements: +Next lets look at we would `get` and `set` elements: ```swift fileprivate func toBlock(index: Int) -> Int { let block = Int(ceil((-3.0 + sqrt(9.0 + 8.0 * Double(index))) / 2)) @@ -130,4 +133,66 @@ public subscript(index: Int) -> T { } } ``` -`toBlock` is really just wrapping the `block` equation derived earlier. `superscript` lets us have `get/set` access to the structure with the familiar `[index]` syntax. +`toBlock(index:)` is really just wrapping the `block` equation derived earlier to return the block that an index maps to. `superscript` lets us have `get` and `set` access to the structure with the familiar `[index:]` syntax. For both `get` and `set` in superscript we use the same logic: + 1. determine the block that the index points to + 2. determine the inner block index + 3. `get`/`set` the value + +Next lets look at how we would `growIfNeeded()` and `shrinkIfNeeded()` the structure. +```swift +fileprivate mutating func growIfNeeded() { + if capacity - blocks.count < count + 1 { + let newArray = [T?](repeating: nil, count: blocks.count + 1) + blocks.append(newArray) + } +} + +fileprivate mutating func shrinkIfNeeded() { + if capacity + blocks.count >= count { + var numberOfBlocks = blocks.count + while numberOfBlocks > 0 && (numberOfBlocks - 2) * (numberOfBlocks - 1) / 2 >= count { + blocks.remove(at: blocks.count - 1) + numberOfBlocks -= 1 + } + } +} +``` +If our data set grows or shrinks in size, we want our data structure to accommodate the change. +Just like a Swift array when a capacity threshold is met we will `grow` or `shrink` the size of our structure. For the Rootish Array Stack we want to `grow` if the second last block is full on an `insert` operation, and `shrink` if the two last blocks are empty. + +Now to the more familiar Swift array behaviour. +```swift +public mutating func insert(element: T, atIndex index: Int) { + growIfNeeded() + internalCount += 1 + var i = count - 1 + while i > index { + self[i] = self[i - 1] + i -= 1 + } + self[index] = element +} + +public mutating func append(element: T) { + insert(element: element, atIndex: count) +} + +public mutating func remove(atIndex index: Int) -> T { + let element = self[index] + for i in index.. Setting a optionals value to `nil` is different than setting it's wrapped value to `nil`. An optionals wrapped value is an embedded type within the optional reference. This means that a `nil` wrapped value is actually `.some(.none)` wheres setting the root reference to `nil` is `.none`. To better understand Swift optionals I recommend checking out @SebastianBoldt's article [Swift! Optionals?](https://medium.com/ios-os-x-development/swift-optionals-78dafaa53f3#.rvjobhuzs). diff --git a/Rootish Array Stack/RootishArrayStack.swift b/Rootish Array Stack/RootishArrayStack.swift index 6cb1cff06..4edc58b2f 100644 --- a/Rootish Array Stack/RootishArrayStack.swift +++ b/Rootish Array Stack/RootishArrayStack.swift @@ -26,6 +26,23 @@ public struct RootishArrayStack { return block } + fileprivate mutating func growIfNeeded() { + if capacity - blocks.count < count + 1 { + let newArray = [T?](repeating: nil, count: blocks.count + 1) + blocks.append(newArray) + } + } + + fileprivate mutating func shrinkIfNeeded() { + if capacity + blocks.count >= count { + var numberOfBlocks = blocks.count + while numberOfBlocks > 0 && (numberOfBlocks - 2) * (numberOfBlocks - 1) / 2 >= count { + blocks.remove(at: blocks.count - 1) + numberOfBlocks -= 1 + } + } + } + public subscript(index: Int) -> T { get { let block = toBlock(index: index) @@ -39,23 +56,8 @@ public struct RootishArrayStack { } } - fileprivate mutating func grow() { - let newArray = [T?](repeating: nil, count: blocks.count + 1) - blocks.append(newArray) - } - - fileprivate mutating func shrink() { - var numberOfBlocks = blocks.count - while numberOfBlocks > 0 && (numberOfBlocks - 2) * (numberOfBlocks - 1) / 2 >= count { - blocks.remove(at: blocks.count - 1) - numberOfBlocks -= 1 - } - } - public mutating func insert(element: T, atIndex index: Int) { - if capacity - blocks.count < count + 1 { - grow() - } + growIfNeeded() internalCount += 1 var i = count - 1 while i > index { @@ -82,9 +84,7 @@ public struct RootishArrayStack { } internalCount -= 1 makeNil(atIndex: count) - if capacity + blocks.count >= count { - shrink() - } + shrinkIfNeeded() return element } @@ -113,8 +113,3 @@ extension RootishArrayStack: CustomStringConvertible { return s + "]" } } - -var list = RootishArrayStack() -for i in 0...10 { - list.append(element: i) -} From 72c12e92485f49b24c30b61522ae9aff9035cdaf Mon Sep 17 00:00:00 2001 From: BenEmdon Date: Mon, 28 Nov 2016 22:32:23 -0500 Subject: [PATCH 0686/1679] Added Gauss' legend Polished example --- Rootish Array Stack/README.md | 36 +++++++++++++++------ Rootish Array Stack/RootishArrayStack.swift | 4 +-- 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/Rootish Array Stack/README.md b/Rootish Array Stack/README.md index 790eea6da..5f62cec2c 100644 --- a/Rootish Array Stack/README.md +++ b/Rootish Array Stack/README.md @@ -10,9 +10,8 @@ A resizable array holds references to blocks (arrays of fixed size). A block's c Here you can see how insert/remove operations would behave (very similar to how a Swift array handles such operations). -## Gauss's Summation Trick - -This data structure is based on Gauss's summation technique: +## Gauss' Summation Trick +One of the most well known legends about famous mathematician [Carl Friedrich Gauss](https://en.wikipedia.org/wiki/Carl_Friedrich_Gauss) goes back to when he was in primary school. One day Gauss' teacher asked his class to add up all the numbers from 1 to 100, hoping that the task would take long enough for the teacher to step out for a smoke break. The teacher was shocked when young Gauss had his hand up with the answer `5050`. So soon? The teacher suspected a cheat, but no. Gauss had found a formula to sidestep the problem of manual adding up all the number 1 by 1. His formula: ``` sum from 1...n = n * (n + 1) / 2 ``` @@ -42,9 +41,9 @@ x x x o o o => x x x o o o x x x x o o o o x x x x o o x x x x x o o o o o x x x x x o ``` -Here we have `n` rows and `n + 1` columns of units. _5 rows and 6 columns_. +Here we have `n` rows and `n + 1` columns. _5 rows and 6 columns_. -We could calculate sum just as we would an area! Lets also express width and hight in terms of `n`: +We could calculate sum just as we would an area! Lets also express the width and hight in terms of `n`: ``` area of a rectangle = height * width = n * (n + 1) ``` @@ -78,10 +77,26 @@ A negative block doesn't make sense so we take the positive root instead. In gen block = ⌈(-3 + √(9 + 8 * index)) / 2⌉ ``` -Now we can figure out that `rootishArrayStack[12]` would point to the block at index `4` and at inner block index `2`. +Now we can figure out that `rootishArrayStack[12]` points to! First lets see which block the `12` points to: +``` +block = ⌈(-3 + √(9 + 8 * (12))) / 2⌉ +block = ⌈(-3 + √105) / 2⌉ +block = ⌈(-3 + (10.246950766)) / 2⌉ +block = ⌈(7.246950766) / 2⌉ +block = ⌈3.623475383⌉ +block = 4 +``` +Next lets see which `innerBlockIndex` `12` points to: +``` +inner block index = (12) - (4) * ((4) + 1) / 2 +inner block index = (12) - (4) * (5) / 2 +inner block index = (12) - 10 +inner block index = 2 +``` +Therefore `rootishArrayStack[12]` points to the block at index `4` and at inner block index `2`. ![Rootish Array Stack Intro](images/RootishArrayStackExample2.png) -# The Code +# Implementation Details Lets start with instance variables and struct declaration: ```swift import Darwin @@ -149,10 +164,8 @@ fileprivate mutating func growIfNeeded() { fileprivate mutating func shrinkIfNeeded() { if capacity + blocks.count >= count { - var numberOfBlocks = blocks.count - while numberOfBlocks > 0 && (numberOfBlocks - 2) * (numberOfBlocks - 1) / 2 >= count { + while blocks.count > 0 && (blocks.count - 2) * (blocks.count - 1) / 2 >= count { blocks.remove(at: blocks.count - 1) - numberOfBlocks -= 1 } } } @@ -196,3 +209,6 @@ fileprivate mutating func makeNil(atIndex index: Int) { ``` To `insert(element:, atIndex:)` we move all elements after the `index` to the right by 1. After space has been made for the element we set the value using the `subscript` convenience. `append(element:)` is just a convenience method to add to the end. To `remove(atIndex:)` we move all the elements after the `index` to the left by 1. After the removed value is covered by it's proceeding value, we set the last value in the structure to `nil`. `makeNil(atIndex:)` uses the same logic as our `subscript` method but is used to set the root optional at a particular index to `nil` (because setting it's wrapped value to `nil` is something only the user of the data structure should do). > Setting a optionals value to `nil` is different than setting it's wrapped value to `nil`. An optionals wrapped value is an embedded type within the optional reference. This means that a `nil` wrapped value is actually `.some(.none)` wheres setting the root reference to `nil` is `.none`. To better understand Swift optionals I recommend checking out @SebastianBoldt's article [Swift! Optionals?](https://medium.com/ios-os-x-development/swift-optionals-78dafaa53f3#.rvjobhuzs). + +# Runtime Analysis + diff --git a/Rootish Array Stack/RootishArrayStack.swift b/Rootish Array Stack/RootishArrayStack.swift index 4edc58b2f..66a681f97 100644 --- a/Rootish Array Stack/RootishArrayStack.swift +++ b/Rootish Array Stack/RootishArrayStack.swift @@ -35,10 +35,8 @@ public struct RootishArrayStack { fileprivate mutating func shrinkIfNeeded() { if capacity + blocks.count >= count { - var numberOfBlocks = blocks.count - while numberOfBlocks > 0 && (numberOfBlocks - 2) * (numberOfBlocks - 1) / 2 >= count { + while blocks.count > 0 && (blocks.count - 2) * (blocks.count - 1) / 2 >= count { blocks.remove(at: blocks.count - 1) - numberOfBlocks -= 1 } } } From cb673314ee570504f655c3d6d992fe90d3c2425e Mon Sep 17 00:00:00 2001 From: BenEmdon Date: Thu, 8 Dec 2016 22:15:14 -0500 Subject: [PATCH 0687/1679] Added performance explination + cleaned up some implementation details --- Rootish Array Stack/README.md | 27 +++++++++++++-------- Rootish Array Stack/RootishArrayStack.swift | 24 ++++++++++-------- 2 files changed, 31 insertions(+), 20 deletions(-) diff --git a/Rootish Array Stack/README.md b/Rootish Array Stack/README.md index 5f62cec2c..ee2351d4d 100644 --- a/Rootish Array Stack/README.md +++ b/Rootish Array Stack/README.md @@ -102,16 +102,17 @@ Lets start with instance variables and struct declaration: import Darwin public struct RootishArrayStack { - fileprivate var blocks = [Array]() - fileprivate var internalCount = 0 - public init() { } + fileprivate var blocks = [Array]() + fileprivate var internalCount = 0 - var count: Int { - return internalCount - } + public init() { } + + var count: Int { + return internalCount + } - ... + ... } @@ -149,7 +150,7 @@ public subscript(index: Int) -> T { } ``` `toBlock(index:)` is really just wrapping the `block` equation derived earlier to return the block that an index maps to. `superscript` lets us have `get` and `set` access to the structure with the familiar `[index:]` syntax. For both `get` and `set` in superscript we use the same logic: - 1. determine the block that the index points to + 1. determine the block that the index points to 2. determine the inner block index 3. `get`/`set` the value @@ -210,5 +211,11 @@ fileprivate mutating func makeNil(atIndex index: Int) { To `insert(element:, atIndex:)` we move all elements after the `index` to the right by 1. After space has been made for the element we set the value using the `subscript` convenience. `append(element:)` is just a convenience method to add to the end. To `remove(atIndex:)` we move all the elements after the `index` to the left by 1. After the removed value is covered by it's proceeding value, we set the last value in the structure to `nil`. `makeNil(atIndex:)` uses the same logic as our `subscript` method but is used to set the root optional at a particular index to `nil` (because setting it's wrapped value to `nil` is something only the user of the data structure should do). > Setting a optionals value to `nil` is different than setting it's wrapped value to `nil`. An optionals wrapped value is an embedded type within the optional reference. This means that a `nil` wrapped value is actually `.some(.none)` wheres setting the root reference to `nil` is `.none`. To better understand Swift optionals I recommend checking out @SebastianBoldt's article [Swift! Optionals?](https://medium.com/ios-os-x-development/swift-optionals-78dafaa53f3#.rvjobhuzs). -# Runtime Analysis - +# Performance +* An internal counter keeps track of the number of elements in the structure. `count` is executed in **O(1)** time. + +* `capacity` can be calculated using Gauss' summation trick in an equation which takes **O(1)** time to execute. + +* Since `subcript[index:]` uses the `block` and `inner block index` equations, which can be executed in **O(1)** time, all get and set operations take **O(1)**. + +* Ignoring the time cost to `grow()` and `shrink()`, `insert()` and `remove()` operations shift all elements right of the specified index resulting in **O(n)** time. diff --git a/Rootish Array Stack/RootishArrayStack.swift b/Rootish Array Stack/RootishArrayStack.swift index 66a681f97..842e34f72 100644 --- a/Rootish Array Stack/RootishArrayStack.swift +++ b/Rootish Array Stack/RootishArrayStack.swift @@ -21,11 +21,15 @@ public struct RootishArrayStack { return blocks.count * (blocks.count + 1) / 2 } - fileprivate func toBlock(index: Int) -> Int { + fileprivate func block(fromIndex index: Int) -> Int { let block = Int(ceil((-3.0 + sqrt(9.0 + 8.0 * Double(index))) / 2)) return block } + fileprivate func innerBlockIndex(fromIndex index: Int, fromBlock block: Int) -> Int { + return index - block * (block + 1) / 2 + } + fileprivate mutating func growIfNeeded() { if capacity - blocks.count < count + 1 { let newArray = [T?](repeating: nil, count: blocks.count + 1) @@ -43,14 +47,14 @@ public struct RootishArrayStack { public subscript(index: Int) -> T { get { - let block = toBlock(index: index) - let blockIndex = index - block * (block + 1) / 2 - return blocks[block][blockIndex]! + let block = self.block(fromIndex: index) + let innerBlockIndex = self.innerBlockIndex(fromIndex: index, fromBlock: block) + return blocks[block][innerBlockIndex]! } set(newValue) { - let block = toBlock(index: index) - let blockIndex = index - block * (block + 1) / 2 - blocks[block][blockIndex] = newValue + let block = self.block(fromIndex: index) + let innerBlockIndex = self.innerBlockIndex(fromIndex: index, fromBlock: block) + blocks[block][innerBlockIndex] = newValue } } @@ -70,9 +74,9 @@ public struct RootishArrayStack { } fileprivate mutating func makeNil(atIndex index: Int) { - let block = toBlock(index: index) - let blockIndex = index - block * (block + 1) / 2 - blocks[block][blockIndex] = nil + let block = self.block(fromIndex: index) + let innerBlockIndex = self.innerBlockIndex(fromIndex: index, fromBlock: block) + blocks[block][innerBlockIndex] = nil } public mutating func remove(atIndex index: Int) -> T { From b8f87bfe07d5268b37ad7e4fb5f2319a94d7d060 Mon Sep 17 00:00:00 2001 From: BenEmdon Date: Sat, 10 Dec 2016 23:14:15 -0500 Subject: [PATCH 0688/1679] Added performance analysis --- Rootish Array Stack/README.md | 68 ++++++++++++++++++++++------------- 1 file changed, 43 insertions(+), 25 deletions(-) diff --git a/Rootish Array Stack/README.md b/Rootish Array Stack/README.md index ee2351d4d..c00061082 100644 --- a/Rootish Array Stack/README.md +++ b/Rootish Array Stack/README.md @@ -11,7 +11,7 @@ A resizable array holds references to blocks (arrays of fixed size). A block's c Here you can see how insert/remove operations would behave (very similar to how a Swift array handles such operations). ## Gauss' Summation Trick -One of the most well known legends about famous mathematician [Carl Friedrich Gauss](https://en.wikipedia.org/wiki/Carl_Friedrich_Gauss) goes back to when he was in primary school. One day Gauss' teacher asked his class to add up all the numbers from 1 to 100, hoping that the task would take long enough for the teacher to step out for a smoke break. The teacher was shocked when young Gauss had his hand up with the answer `5050`. So soon? The teacher suspected a cheat, but no. Gauss had found a formula to sidestep the problem of manual adding up all the number 1 by 1. His formula: +One of the most well known legends about famous mathematician [Carl Friedrich Gauss](https://en.wikipedia.org/wiki/Carl_Friedrich_Gauss) goes back to when he was in primary school. One day Gauss' teacher asked his class to add up all the numbers from 1 to 100, hoping that the task would take long enough for the teacher to step out for a smoke break. The teacher was shocked when young Gauss had his hand up with the answer `5050`. So soon? The teacher suspected a cheat, but no. Gauss had found a formula to sidestep the problem of manually adding up all the numbers 1 by 1. His formula: ``` sum from 1...n = n * (n + 1) / 2 ``` @@ -96,6 +96,9 @@ inner block index = 2 Therefore `rootishArrayStack[12]` points to the block at index `4` and at inner block index `2`. ![Rootish Array Stack Intro](images/RootishArrayStackExample2.png) +### Interesting Discovery +Using the `block` equation we can see that the number of `blocks` is proportional to the square root of the number of elements: **O(blocks) = O(√n)**. + # Implementation Details Lets start with instance variables and struct declaration: ```swift @@ -106,10 +109,10 @@ public struct RootishArrayStack { fileprivate var blocks = [Array]() fileprivate var internalCount = 0 - public init() { } + public init() { } - var count: Int { - return internalCount + var count: Int { + return internalCount } ... @@ -131,25 +134,29 @@ var capacity: Int { Next lets look at we would `get` and `set` elements: ```swift -fileprivate func toBlock(index: Int) -> Int { +fileprivate func block(fromIndex: Int) -> Int { let block = Int(ceil((-3.0 + sqrt(9.0 + 8.0 * Double(index))) / 2)) return block } +fileprivate func innerBlockIndex(fromIndex index: Int, fromBlock block: Int) -> Int { + return index - block * (block + 1) / 2 +} + public subscript(index: Int) -> T { get { - let block = toBlock(index: index) - let blockIndex = index - block * (block + 1) / 2 - return blocks[block][blockIndex]! + let block = self.block(fromIndex: index) + let innerBlockIndex = self.innerBlockIndex(fromIndex: index, fromBlock: block) + return blocks[block][innerBlockIndex]! } set(newValue) { - let block = toBlock(index: index) - let blockIndex = index - block * (block + 1) / 2 - blocks[block][blockIndex] = newValue + let block = self.block(fromIndex: index) + let innerBlockIndex = self.innerBlockIndex(fromIndex: index, fromBlock: block) + blocks[block][innerBlockIndex] = newValue } } ``` -`toBlock(index:)` is really just wrapping the `block` equation derived earlier to return the block that an index maps to. `superscript` lets us have `get` and `set` access to the structure with the familiar `[index:]` syntax. For both `get` and `set` in superscript we use the same logic: +`block(fromIndex:)` and `innerBlockIndex(fromIndex:, fromBlock:)` are wrapping the `block` and `inner block index` equations derived earlier. `superscript` lets us have `get` and `set` access to the structure with the familiar `[index:]` syntax. For both `get` and `set` in superscript we use the same logic: 1. determine the block that the index points to 2. determine the inner block index 3. `get`/`set` the value @@ -157,18 +164,18 @@ public subscript(index: Int) -> T { Next lets look at how we would `growIfNeeded()` and `shrinkIfNeeded()` the structure. ```swift fileprivate mutating func growIfNeeded() { - if capacity - blocks.count < count + 1 { - let newArray = [T?](repeating: nil, count: blocks.count + 1) - blocks.append(newArray) - } + if capacity - blocks.count < count + 1 { + let newArray = [T?](repeating: nil, count: blocks.count + 1) + blocks.append(newArray) + } } fileprivate mutating func shrinkIfNeeded() { - if capacity + blocks.count >= count { - while blocks.count > 0 && (blocks.count - 2) * (blocks.count - 1) / 2 >= count { - blocks.remove(at: blocks.count - 1) - } - } + if capacity + blocks.count >= count { + while blocks.count > 0 && (blocks.count - 2) * (blocks.count - 1) / 2 > count { + blocks.remove(at: blocks.count - 1) + } + } } ``` If our data set grows or shrinks in size, we want our data structure to accommodate the change. @@ -203,9 +210,9 @@ public mutating func remove(atIndex index: Int) -> T { } fileprivate mutating func makeNil(atIndex index: Int) { - let block = toBlock(index: index) - let blockIndex = index - block * (block + 1) / 2 - blocks[block][blockIndex] = nil + let block = self.block(fromIndex: index) + let innerBlockIndex = self.innerBlockIndex(fromIndex: index, fromBlock: block) + blocks[block][innerBlockIndex] = nil } ``` To `insert(element:, atIndex:)` we move all elements after the `index` to the right by 1. After space has been made for the element we set the value using the `subscript` convenience. `append(element:)` is just a convenience method to add to the end. To `remove(atIndex:)` we move all the elements after the `index` to the left by 1. After the removed value is covered by it's proceeding value, we set the last value in the structure to `nil`. `makeNil(atIndex:)` uses the same logic as our `subscript` method but is used to set the root optional at a particular index to `nil` (because setting it's wrapped value to `nil` is something only the user of the data structure should do). @@ -218,4 +225,15 @@ To `insert(element:, atIndex:)` we move all elements after the `index` to the ri * Since `subcript[index:]` uses the `block` and `inner block index` equations, which can be executed in **O(1)** time, all get and set operations take **O(1)**. -* Ignoring the time cost to `grow()` and `shrink()`, `insert()` and `remove()` operations shift all elements right of the specified index resulting in **O(n)** time. +* Ignoring the time cost to `grow` and `shrink`, `insert(atIndex:)` and `remove(atIndex:)` operations shift all elements right of the specified index resulting in **O(n)** time. + +# Analysis of Growing and Shrinking +The performance analysis doesn't account for the cost to `grow` and `shrink`. Unlike a regular Swift array, `grow` and `shrink` operations don't copy all the elements into a backing array. They only allocate or free an array proportional to the number of `blocks`. The number of `blocks` is proportional to the square root of the number of elements. Growing and shrinking only cost **O(√n)**. + +# Wasted Space +Wasted space is how much memory with respect to the number of elements `n` is unused. The Rootish Array Stack never has more than 2 empty blocks and it never has less than 1 empty block. The last two blocks are proportional to the number of blocks which is proportional to the square root of the number of elements. The number of references needed to point to each block is the same as the number of blocks. Therefore, the amount of wasted space with respect to the number of elements is **O(√n)**. + + +_Written for Swift Algorithm Club by @BenEmdon_ + +_With help from [OpenDataStructures.org](http://opendatastructures.org)_ From 0879118bfdffa6ec3d9f426322b3b751e87e6b85 Mon Sep 17 00:00:00 2001 From: BenEmdon Date: Sat, 10 Dec 2016 23:44:08 -0500 Subject: [PATCH 0689/1679] Marks in swift file --- Rootish Array Stack/RootishArrayStack.swift | 40 +++++++++++++-------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/Rootish Array Stack/RootishArrayStack.swift b/Rootish Array Stack/RootishArrayStack.swift index 842e34f72..0d2b15c3c 100644 --- a/Rootish Array Stack/RootishArrayStack.swift +++ b/Rootish Array Stack/RootishArrayStack.swift @@ -1,18 +1,24 @@ // -// main.swift // RootishArrayStack // -// Created by Benjamin Emdon on 2016-11-07. +// Created by @BenEmdon on 2016-11-07. // import Darwin public struct RootishArrayStack { + + // MARK: - Instance variables + fileprivate var blocks = [Array]() fileprivate var internalCount = 0 + // MARK: - Init + public init() { } + // MARK: - Calculated variables + var count: Int { return internalCount } @@ -21,6 +27,8 @@ public struct RootishArrayStack { return blocks.count * (blocks.count + 1) / 2 } + // MARK: - Equations + fileprivate func block(fromIndex index: Int) -> Int { let block = Int(ceil((-3.0 + sqrt(9.0 + 8.0 * Double(index))) / 2)) return block @@ -30,6 +38,8 @@ public struct RootishArrayStack { return index - block * (block + 1) / 2 } + // MARK: - Behavior + fileprivate mutating func growIfNeeded() { if capacity - blocks.count < count + 1 { let newArray = [T?](repeating: nil, count: blocks.count + 1) @@ -89,20 +99,10 @@ public struct RootishArrayStack { shrinkIfNeeded() return element } - - public var memoryDescription: String { - var description = "{\n" - for block in blocks { - description += "\t[" - for rawElement in block { - description += "\(rawElement), " - } - description += "]\n" - } - return description + "}" - } } +// MARK: - Struct to string + extension RootishArrayStack: CustomStringConvertible { public var description: String { var s = "[" @@ -114,4 +114,16 @@ extension RootishArrayStack: CustomStringConvertible { } return s + "]" } + + public var memoryDescription: String { + var description = "{\n" + for block in blocks { + description += "\t[" + for rawElement in block { + description += "\(rawElement), " + } + description += "]\n" + } + return description + "}" + } } From e5dfe6637980b9f425371c0dbe82dedae1100d3e Mon Sep 17 00:00:00 2001 From: BenEmdon Date: Sun, 11 Dec 2016 00:25:58 -0500 Subject: [PATCH 0690/1679] Added isEmpty, first, last --- Rootish Array Stack/RootishArrayStack.swift | 16 ++++++++++++++++ .../contents.xcworkspacedata | 3 +++ 2 files changed, 19 insertions(+) diff --git a/Rootish Array Stack/RootishArrayStack.swift b/Rootish Array Stack/RootishArrayStack.swift index 0d2b15c3c..4033d75f6 100644 --- a/Rootish Array Stack/RootishArrayStack.swift +++ b/Rootish Array Stack/RootishArrayStack.swift @@ -27,6 +27,22 @@ public struct RootishArrayStack { return blocks.count * (blocks.count + 1) / 2 } + var isEmpty: Bool { + return blocks.count == 0 + } + + var first: T? { + guard capacity > 0 else { return nil } + return blocks[0][0] + } + + var last: T? { + guard capacity > 0 else { return nil } + let block = self.block(fromIndex: count - 1) + let innerBlockIndex = self.innerBlockIndex(fromIndex: count - 1, fromBlock: block) + return blocks[block][innerBlockIndex] + } + // MARK: - Equations fileprivate func block(fromIndex index: Int) -> Int { diff --git a/swift-algorithm-club.xcworkspace/contents.xcworkspacedata b/swift-algorithm-club.xcworkspace/contents.xcworkspacedata index ac3a79be9..c2ae29f70 100644 --- a/swift-algorithm-club.xcworkspace/contents.xcworkspacedata +++ b/swift-algorithm-club.xcworkspace/contents.xcworkspacedata @@ -1529,6 +1529,9 @@ + + Date: Sun, 11 Dec 2016 00:32:20 -0500 Subject: [PATCH 0691/1679] Added playground Finished playground --- Rootish Array Stack/README.md | 58 ++--- .../Contents.swift | 219 ++++++++++++++++++ .../contents.xcplayground | 4 + Rootish Array Stack/RootishArrayStack.swift | 35 +-- 4 files changed, 273 insertions(+), 43 deletions(-) create mode 100644 Rootish Array Stack/RootishArrayStack.playground/Contents.swift create mode 100644 Rootish Array Stack/RootishArrayStack.playground/contents.xcplayground diff --git a/Rootish Array Stack/README.md b/Rootish Array Stack/README.md index c00061082..6a45b262a 100644 --- a/Rootish Array Stack/README.md +++ b/Rootish Array Stack/README.md @@ -4,14 +4,14 @@ A *Rootish Array Stack* is an ordered array based structure that minimizes waste ![Rootish Array Stack Intro](images/RootishArrayStackIntro.png) -A resizable array holds references to blocks (arrays of fixed size). A block's capacity is the same as it's index in the resizable array. Blocks don't grow/shrink like regular Swift arrays. Instead, when their capacity is reached, a new slightly larger block is created. When a block is emptied the last block is freed. This is a great improvement on what a swift array does in terms of wasted space. +A resizable array holds references to blocks (arrays of fixed size). A block's capacity is the same as it's index in the resizable array. Blocks don't grow/shrink like regular Swift arrays. Instead, when their capacity is reached, a new slightly larger block is created. When a block is emptied the last block is freed. This is a great improvement on what Swift arrays do in terms of wasted space. ![Rootish Array Stack Intro](images/RootishArrayStackExample.png) Here you can see how insert/remove operations would behave (very similar to how a Swift array handles such operations). ## Gauss' Summation Trick -One of the most well known legends about famous mathematician [Carl Friedrich Gauss](https://en.wikipedia.org/wiki/Carl_Friedrich_Gauss) goes back to when he was in primary school. One day Gauss' teacher asked his class to add up all the numbers from 1 to 100, hoping that the task would take long enough for the teacher to step out for a smoke break. The teacher was shocked when young Gauss had his hand up with the answer `5050`. So soon? The teacher suspected a cheat, but no. Gauss had found a formula to sidestep the problem of manually adding up all the numbers 1 by 1. His formula: +One of the most well known legends about famous mathematician [Carl Friedrich Gauss](https://en.wikipedia.org/wiki/Carl_Friedrich_Gauss) goes back to when he was in primary school. One day, Gauss' teacher asked his class to add up all the numbers from 1 to 100, hoping that the task would take long enough for him to step out for a smoke break. The teacher was shocked when young Gauss had his hand up with the answer `5050`. So soon? The teacher suspected a cheat, but no. Gauss had found a formula to sidestep the problem of manually adding up all the numbers 1 by 1. His formula: ``` sum from 1...n = n * (n + 1) / 2 ``` @@ -22,7 +22,7 @@ blocks: [x] [x x] [x x x] [x x x x] [x x x x x] ``` _Block `1` has 1 `x`, block `2` as 2 `x`s, block `3` has 3 `x`s, etc..._ -If you wanted to take the sum of all the blocks from `1` to `n` you could go through and count them _one by one_. This is okay, but for a large sequence of blocks that could take a long time! Instead you could arrange the blocks to look like a _half pyramid_: +If you wanted to take the sum of all the blocks from `1` to `n`, you could go through and count them _one by one_. This is okay, but for a large sequence of blocks that could take a long time! Instead, you could arrange the blocks to look like a _half pyramid_: ``` # | blocks --|------------- @@ -43,24 +43,24 @@ x x x x x o o o o o x x x x x o ``` Here we have `n` rows and `n + 1` columns. _5 rows and 6 columns_. -We could calculate sum just as we would an area! Lets also express the width and hight in terms of `n`: +We can calculate the sum just as we would an area! Let's also express the width and height in terms of `n`: ``` area of a rectangle = height * width = n * (n + 1) ``` -But we only want to calculate the amount of `x`s, not the amount of `o`s. Since there's a 1:1 ratio between `x`s and `o`s we and just divide our area by 2! +We only want to calculate the amount of `x`s, not the amount of `o`s. Since there's a 1:1 ratio between `x`s and `o`s we can just divide our area by 2! ``` area of only x = n * (n + 1) / 2 ``` -And voila! A super fast way to take a sum of all the blocks! This equation is useful for deriving fast `block` and `inner block index` equations. +Voila! A super fast way to take a sum of all the blocks! This equation is useful for deriving fast `block` and `inner block index` equations. + ## Get/Set with Speed -Next we want to find an efficient and accurate way to access an element at a random index. For example which block does `rootishArrayStack[12]` point to? To answer this we will need more math! +Next, we want to find an efficient and accurate way to access an element at a random index. For example, which block does `rootishArrayStack[12]` point to? To answer this we will need more math! Determining the inner block `index` turns out to be easy. If `index` is in some `block` then: ``` inner block index = index - block * (block + 1) / 2 ``` - -More difficult is determining which `block` an index points to. The number of elements that have indices less than or equal to the the requested `index` is: `index + 1` elements. The number of elements in blocks `0...block` is `(block + 1) * (block + 2) / 2`. Therefore, `block` is the smaller integer such that: +Determining which `block` an index points to is more difficult. The number of elements up to and including the element requested is: `index + 1` elements. The number of elements in blocks `0...block` is `(block + 1) * (block + 2) / 2` (equation derived above). The relationship between the `block` and the `index` is as follows: ``` (block + 1) * (block + 2) / 2 >= index + 1 ``` @@ -68,16 +68,16 @@ This can be rewritten as: ``` (block)^2 + (3 * block) - (2 * index) >= 0 ``` -Using the quadratic formula we can get: +Using the quadratic formula we get: ``` block = (-3 ± √(9 + 8 * index)) / 2 ``` -A negative block doesn't make sense so we take the positive root instead. In general this solution is not an integer but going back to our inequality, we want the smallest block such that `b => (-3 + √(9 + 8 * index)) / 2`. So we take the ceiling of the result: +A negative block doesn't make sense, so we take the positive root instead. In general, this solution is not an integer. However, going back to our inequality, we want the smallest block such that `block => (-3 + √(9 + 8 * index)) / 2`. Next, we take the ceiling of the result: ``` block = ⌈(-3 + √(9 + 8 * index)) / 2⌉ ``` -Now we can figure out that `rootishArrayStack[12]` points to! First lets see which block the `12` points to: +Now we can figure out what `rootishArrayStack[12]` points to! First, let's see which block the `12` points to: ``` block = ⌈(-3 + √(9 + 8 * (12))) / 2⌉ block = ⌈(-3 + √105) / 2⌉ @@ -93,14 +93,14 @@ inner block index = (12) - (4) * (5) / 2 inner block index = (12) - 10 inner block index = 2 ``` -Therefore `rootishArrayStack[12]` points to the block at index `4` and at inner block index `2`. +Therefore, `rootishArrayStack[12]` points to the block at index `4` and at inner block index `2`. ![Rootish Array Stack Intro](images/RootishArrayStackExample2.png) ### Interesting Discovery -Using the `block` equation we can see that the number of `blocks` is proportional to the square root of the number of elements: **O(blocks) = O(√n)**. +Using the `block` equation, we can see that the number of `blocks` is proportional to the square root of the number of elements: **O(blocks) = O(√n)**. # Implementation Details -Lets start with instance variables and struct declaration: +Let's start with instance variables and struct declaration: ```swift import Darwin @@ -123,7 +123,7 @@ public struct RootishArrayStack { The elements are of generic type `T`, so data of any kind can be stored in the list. `blocks` will be a resizable array to hold fixed sized arrays that take type `T?`. > The reason for the fixed size arrays taking type `T?` is so that references to elements aren't retained after they've been removed. Eg: if you remove the last element, the last index must be set to `nil` to prevent the last element being held in memory at an inaccessible index. -`internalCount` is an internal mutable counter that keeps track of the number of elements. `count` is a read only variables that gives the `internalCount` value. `Darwin` is imported here to provide simple math functions such as `ceil()` and `sqrt()`. +`internalCount` is an internal mutable counter that keeps track of the number of elements. `count` is a read only variable that returns the `internalCount` value. `Darwin` is imported here to provide simple math functions such as `ceil()` and `sqrt()`. The `capacity` of the structure is simply the Gaussian summation trick: ```swift @@ -132,7 +132,7 @@ var capacity: Int { } ``` -Next lets look at we would `get` and `set` elements: +Next, let's look at how we would `get` and `set` elements: ```swift fileprivate func block(fromIndex: Int) -> Int { let block = Int(ceil((-3.0 + sqrt(9.0 + 8.0 * Double(index))) / 2)) @@ -156,12 +156,13 @@ public subscript(index: Int) -> T { } } ``` -`block(fromIndex:)` and `innerBlockIndex(fromIndex:, fromBlock:)` are wrapping the `block` and `inner block index` equations derived earlier. `superscript` lets us have `get` and `set` access to the structure with the familiar `[index:]` syntax. For both `get` and `set` in superscript we use the same logic: - 1. determine the block that the index points to - 2. determine the inner block index - 3. `get`/`set` the value +`block(fromIndex:)` and `innerBlockIndex(fromIndex:, fromBlock:)` are wrapping the `block` and `inner block index` equations we derived earlier. `superscript` lets us have `get` and `set` access to the structure with the familiar `[index:]` syntax. For both `get` and `set` in `superscript` we use the same logic: + +1. determine the block that the index points to +2. determine the inner block index +3. `get`/`set` the value -Next lets look at how we would `growIfNeeded()` and `shrinkIfNeeded()` the structure. +Next, let's look at how we would `growIfNeeded()` and `shrinkIfNeeded()`. ```swift fileprivate mutating func growIfNeeded() { if capacity - blocks.count < count + 1 { @@ -179,7 +180,7 @@ fileprivate mutating func shrinkIfNeeded() { } ``` If our data set grows or shrinks in size, we want our data structure to accommodate the change. -Just like a Swift array when a capacity threshold is met we will `grow` or `shrink` the size of our structure. For the Rootish Array Stack we want to `grow` if the second last block is full on an `insert` operation, and `shrink` if the two last blocks are empty. +Just like a Swift array, when a capacity threshold is met we will `grow` or `shrink` the size of our structure. For the Rootish Array Stack we want to `grow` if the second last block is full on an `insert` operation, and `shrink` if the two last blocks are empty. Now to the more familiar Swift array behaviour. ```swift @@ -215,8 +216,11 @@ fileprivate mutating func makeNil(atIndex index: Int) { blocks[block][innerBlockIndex] = nil } ``` -To `insert(element:, atIndex:)` we move all elements after the `index` to the right by 1. After space has been made for the element we set the value using the `subscript` convenience. `append(element:)` is just a convenience method to add to the end. To `remove(atIndex:)` we move all the elements after the `index` to the left by 1. After the removed value is covered by it's proceeding value, we set the last value in the structure to `nil`. `makeNil(atIndex:)` uses the same logic as our `subscript` method but is used to set the root optional at a particular index to `nil` (because setting it's wrapped value to `nil` is something only the user of the data structure should do). -> Setting a optionals value to `nil` is different than setting it's wrapped value to `nil`. An optionals wrapped value is an embedded type within the optional reference. This means that a `nil` wrapped value is actually `.some(.none)` wheres setting the root reference to `nil` is `.none`. To better understand Swift optionals I recommend checking out @SebastianBoldt's article [Swift! Optionals?](https://medium.com/ios-os-x-development/swift-optionals-78dafaa53f3#.rvjobhuzs). +To `insert(element:, atIndex:)` we move all elements after the `index` to the right by 1. After space has been made for the element, we set the value using the `subscript` convenience method. +`append(element:)` is just a convenience method to `insert` to the end. +To `remove(atIndex:)` we move all the elements after the `index` to the left by 1. After the removed value is covered by it's proceeding value, we set the last value in the structure to `nil`. +`makeNil(atIndex:)` uses the same logic as our `subscript` method but is used to set the root optional at a particular index to `nil` (because setting it's wrapped value to `nil` is something only the user of the data structure should do). +> Setting a optionals value to `nil` is different than setting it's wrapped value to `nil`. An optionals wrapped value is an embedded type within the optional reference. This means that a `nil` wrapped value is actually `.some(.none)` whereas setting the root reference to `nil` is `.none`. To better understand Swift optionals I recommend checking out @SebastianBoldt's article [Swift! Optionals?](https://medium.com/ios-os-x-development/swift-optionals-78dafaa53f3#.rvjobhuzs). # Performance * An internal counter keeps track of the number of elements in the structure. `count` is executed in **O(1)** time. @@ -228,10 +232,10 @@ To `insert(element:, atIndex:)` we move all elements after the `index` to the ri * Ignoring the time cost to `grow` and `shrink`, `insert(atIndex:)` and `remove(atIndex:)` operations shift all elements right of the specified index resulting in **O(n)** time. # Analysis of Growing and Shrinking -The performance analysis doesn't account for the cost to `grow` and `shrink`. Unlike a regular Swift array, `grow` and `shrink` operations don't copy all the elements into a backing array. They only allocate or free an array proportional to the number of `blocks`. The number of `blocks` is proportional to the square root of the number of elements. Growing and shrinking only cost **O(√n)**. +The performance analysis doesn't account for the cost to `grow` and `shrink`. Unlike a regular Swift array, `grow` and `shrink` operations don't copy all the elements into a backing array. They only allocate or free an array proportional to the number of `blocks`. The number of `blocks` is proportional to the square root of the number of elements. Growing and shrinking only costs **O(√n)**. # Wasted Space -Wasted space is how much memory with respect to the number of elements `n` is unused. The Rootish Array Stack never has more than 2 empty blocks and it never has less than 1 empty block. The last two blocks are proportional to the number of blocks which is proportional to the square root of the number of elements. The number of references needed to point to each block is the same as the number of blocks. Therefore, the amount of wasted space with respect to the number of elements is **O(√n)**. +Wasted space is how much memory with respect to the number of elements `n` is unused. The Rootish Array Stack never has more than 2 empty blocks and it never has less than 1 empty block. The last two blocks are proportional to the number of blocks, which is proportional to the square root of the number of elements. The number of references needed to point to each block is the same as the number of blocks. Therefore, the amount of wasted space with respect to the number of elements is **O(√n)**. _Written for Swift Algorithm Club by @BenEmdon_ diff --git a/Rootish Array Stack/RootishArrayStack.playground/Contents.swift b/Rootish Array Stack/RootishArrayStack.playground/Contents.swift new file mode 100644 index 000000000..401c773d6 --- /dev/null +++ b/Rootish Array Stack/RootishArrayStack.playground/Contents.swift @@ -0,0 +1,219 @@ +//: Playground - noun: a place where people can play + +import Darwin + +public struct RootishArrayStack { + + // MARK: - Instance variables + + fileprivate var blocks = [Array]() + fileprivate var internalCount = 0 + + // MARK: - Init + + public init() { } + + // MARK: - Calculated variables + + var count: Int { + return internalCount + } + + var capacity: Int { + return blocks.count * (blocks.count + 1) / 2 + } + + var isEmpty: Bool { + return blocks.count == 0 + } + + var first: T? { + guard capacity > 0 else { return nil } + return blocks[0][0] + } + + var last: T? { + guard capacity > 0 else { return nil } + let block = self.block(fromIndex: count - 1) + let innerBlockIndex = self.innerBlockIndex(fromIndex: count - 1, fromBlock: block) + return blocks[block][innerBlockIndex] + } + + // MARK: - Equations + + fileprivate func block(fromIndex index: Int) -> Int { + let block = Int(ceil((-3.0 + sqrt(9.0 + 8.0 * Double(index))) / 2)) + return block + } + + fileprivate func innerBlockIndex(fromIndex index: Int, fromBlock block: Int) -> Int { + return index - block * (block + 1) / 2 + } + + // MARK: - Behavior + + fileprivate mutating func growIfNeeded() { + if capacity - blocks.count < count + 1 { + let newArray = [T?](repeating: nil, count: blocks.count + 1) + blocks.append(newArray) + } + } + + fileprivate mutating func shrinkIfNeeded() { + if capacity + blocks.count >= count { + while blocks.count > 0 && (blocks.count - 2) * (blocks.count - 1) / 2 >= count { + blocks.remove(at: blocks.count - 1) + } + } + } + + public subscript(index: Int) -> T { + get { + let block = self.block(fromIndex: index) + let innerBlockIndex = self.innerBlockIndex(fromIndex: index, fromBlock: block) + return blocks[block][innerBlockIndex]! + } + set(newValue) { + let block = self.block(fromIndex: index) + let innerBlockIndex = self.innerBlockIndex(fromIndex: index, fromBlock: block) + blocks[block][innerBlockIndex] = newValue + } + } + + public mutating func insert(element: T, atIndex index: Int) { + growIfNeeded() + internalCount += 1 + var i = count - 1 + while i > index { + self[i] = self[i - 1] + i -= 1 + } + self[index] = element + } + + public mutating func append(element: T) { + insert(element: element, atIndex: count) + } + + fileprivate mutating func makeNil(atIndex index: Int) { + let block = self.block(fromIndex: index) + let innerBlockIndex = self.innerBlockIndex(fromIndex: index, fromBlock: block) + blocks[block][innerBlockIndex] = nil + } + + public mutating func remove(atIndex index: Int) -> T { + let element = self[index] + for i in index..() +list.isEmpty // true +list.first // nil +list.last // nil +list.count // 0 +list.capacity // 0 + +list.memoryDescription +// { +// } + +list.append(element: "Hello") +list.isEmpty // false +list.first // "Hello" +list.last // "hello" +list.count // 1 +list.capacity // 1 + +list.memoryDescription +// { +// [Optional("Hello")] +// } + +list.append(element: "World") +list.isEmpty // false +list.first // "Hello" +list.last // "World" +list.count // 2 +list.capacity // 3 + +list[0] // "Hello" +list[1] // "World" +//list[2] // crash! + + +list.memoryDescription +// { +// [Optional("Hello")] +// [Optional("World"), nil] +// } + + +list.insert(element: "Swift", atIndex: 1) +list.isEmpty // false +list.first // "Hello" +list.last // "World" +list.count // 3 +list.capacity // 6 + +list[0] // "Hello" +list[1] // "Swift" +list[2] // "World" + +list.memoryDescription +// { +// [Optional("Hello")] +// [Optional("Swift"), Optional("World")] +// [nil, nil, nil] +// } + +list.remove(atIndex: 2) // "World" +list.isEmpty // false +list.first // "Hello" +list.last // "Swift" +list.count // 2 +list.capacity // 3 + +list[0] // "Hello" +list[1] // "Swift" +//list[2] // crash! + +list[0] = list[1] +list[1] = "is awesome" +list // ["Swift", "is awesome"] diff --git a/Rootish Array Stack/RootishArrayStack.playground/contents.xcplayground b/Rootish Array Stack/RootishArrayStack.playground/contents.xcplayground new file mode 100644 index 000000000..63b6dd8df --- /dev/null +++ b/Rootish Array Stack/RootishArrayStack.playground/contents.xcplayground @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Rootish Array Stack/RootishArrayStack.swift b/Rootish Array Stack/RootishArrayStack.swift index 4033d75f6..af95a4316 100644 --- a/Rootish Array Stack/RootishArrayStack.swift +++ b/Rootish Array Stack/RootishArrayStack.swift @@ -115,31 +115,34 @@ public struct RootishArrayStack { shrinkIfNeeded() return element } -} - -// MARK: - Struct to string -extension RootishArrayStack: CustomStringConvertible { - public var description: String { - var s = "[" - for index in 0.. Date: Sun, 18 Dec 2016 16:57:29 -0500 Subject: [PATCH 0692/1679] Added tests template --- Rootish Array Stack/Tests/Info.plist | 24 ++ .../Tests/RootishArrayStack.swift | 148 ++++++++++ .../Tests/RootishArrayStackTests.swift | 251 +++++++++++++++++ .../Tests/Tests.xcodeproj/project.pbxproj | 264 ++++++++++++++++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/xcschemes/Tests.xcscheme | 90 ++++++ 6 files changed, 784 insertions(+) create mode 100644 Rootish Array Stack/Tests/Info.plist create mode 100644 Rootish Array Stack/Tests/RootishArrayStack.swift create mode 100755 Rootish Array Stack/Tests/RootishArrayStackTests.swift create mode 100644 Rootish Array Stack/Tests/Tests.xcodeproj/project.pbxproj create mode 100644 Rootish Array Stack/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 Rootish Array Stack/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme diff --git a/Rootish Array Stack/Tests/Info.plist b/Rootish Array Stack/Tests/Info.plist new file mode 100644 index 000000000..ba72822e8 --- /dev/null +++ b/Rootish Array Stack/Tests/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/Rootish Array Stack/Tests/RootishArrayStack.swift b/Rootish Array Stack/Tests/RootishArrayStack.swift new file mode 100644 index 000000000..af95a4316 --- /dev/null +++ b/Rootish Array Stack/Tests/RootishArrayStack.swift @@ -0,0 +1,148 @@ +// +// RootishArrayStack +// +// Created by @BenEmdon on 2016-11-07. +// + +import Darwin + +public struct RootishArrayStack { + + // MARK: - Instance variables + + fileprivate var blocks = [Array]() + fileprivate var internalCount = 0 + + // MARK: - Init + + public init() { } + + // MARK: - Calculated variables + + var count: Int { + return internalCount + } + + var capacity: Int { + return blocks.count * (blocks.count + 1) / 2 + } + + var isEmpty: Bool { + return blocks.count == 0 + } + + var first: T? { + guard capacity > 0 else { return nil } + return blocks[0][0] + } + + var last: T? { + guard capacity > 0 else { return nil } + let block = self.block(fromIndex: count - 1) + let innerBlockIndex = self.innerBlockIndex(fromIndex: count - 1, fromBlock: block) + return blocks[block][innerBlockIndex] + } + + // MARK: - Equations + + fileprivate func block(fromIndex index: Int) -> Int { + let block = Int(ceil((-3.0 + sqrt(9.0 + 8.0 * Double(index))) / 2)) + return block + } + + fileprivate func innerBlockIndex(fromIndex index: Int, fromBlock block: Int) -> Int { + return index - block * (block + 1) / 2 + } + + // MARK: - Behavior + + fileprivate mutating func growIfNeeded() { + if capacity - blocks.count < count + 1 { + let newArray = [T?](repeating: nil, count: blocks.count + 1) + blocks.append(newArray) + } + } + + fileprivate mutating func shrinkIfNeeded() { + if capacity + blocks.count >= count { + while blocks.count > 0 && (blocks.count - 2) * (blocks.count - 1) / 2 >= count { + blocks.remove(at: blocks.count - 1) + } + } + } + + public subscript(index: Int) -> T { + get { + let block = self.block(fromIndex: index) + let innerBlockIndex = self.innerBlockIndex(fromIndex: index, fromBlock: block) + return blocks[block][innerBlockIndex]! + } + set(newValue) { + let block = self.block(fromIndex: index) + let innerBlockIndex = self.innerBlockIndex(fromIndex: index, fromBlock: block) + blocks[block][innerBlockIndex] = newValue + } + } + + public mutating func insert(element: T, atIndex index: Int) { + growIfNeeded() + internalCount += 1 + var i = count - 1 + while i > index { + self[i] = self[i - 1] + i -= 1 + } + self[index] = element + } + + public mutating func append(element: T) { + insert(element: element, atIndex: count) + } + + fileprivate mutating func makeNil(atIndex index: Int) { + let block = self.block(fromIndex: index) + let innerBlockIndex = self.innerBlockIndex(fromIndex: index, fromBlock: block) + blocks[block][innerBlockIndex] = nil + } + + public mutating func remove(atIndex index: Int) -> T { + let element = self[index] + for i in index.. LinkedList { + let list = LinkedList() + for number in numbers { + list.append(number) + } + return list + } + + func testEmptyList() { + let list = LinkedList() + XCTAssertTrue(list.isEmpty) + XCTAssertEqual(list.count, 0) + XCTAssertNil(list.first) + XCTAssertNil(list.last) + } + + func testListWithOneElement() { + let list = LinkedList() + list.append(123) + + XCTAssertFalse(list.isEmpty) + XCTAssertEqual(list.count, 1) + + XCTAssertNotNil(list.first) + XCTAssertNil(list.first!.previous) + XCTAssertNil(list.first!.next) + XCTAssertEqual(list.first!.value, 123) + + XCTAssertNotNil(list.last) + XCTAssertNil(list.last!.previous) + XCTAssertNil(list.last!.next) + XCTAssertEqual(list.last!.value, 123) + + XCTAssertTrue(list.first === list.last) + } + + func testListWithTwoElements() { + let list = LinkedList() + list.append(123) + list.append(456) + + XCTAssertEqual(list.count, 2) + + XCTAssertNotNil(list.first) + XCTAssertEqual(list.first!.value, 123) + + XCTAssertNotNil(list.last) + XCTAssertEqual(list.last!.value, 456) + + XCTAssertTrue(list.first !== list.last) + + XCTAssertNil(list.first!.previous) + XCTAssertTrue(list.first!.next === list.last) + XCTAssertTrue(list.last!.previous === list.first) + XCTAssertNil(list.last!.next) + } + + func testListWithThreeElements() { + let list = LinkedList() + list.append(123) + list.append(456) + list.append(789) + + XCTAssertEqual(list.count, 3) + + XCTAssertNotNil(list.first) + XCTAssertEqual(list.first!.value, 123) + + let second = list.first!.next + XCTAssertNotNil(second) + XCTAssertEqual(second!.value, 456) + + XCTAssertNotNil(list.last) + XCTAssertEqual(list.last!.value, 789) + + XCTAssertNil(list.first!.previous) + XCTAssertTrue(list.first!.next === second) + XCTAssertTrue(second!.previous === list.first) + XCTAssertTrue(second!.next === list.last) + XCTAssertTrue(list.last!.previous === second) + XCTAssertNil(list.last!.next) + } + + func testNodeAtIndexInEmptyList() { + let list = LinkedList() + let node = list.node(atIndex: 0) + XCTAssertNil(node) + } + + func testNodeAtIndexInListWithOneElement() { + let list = LinkedList() + list.append(123) + + let node = list.node(atIndex: 0) + XCTAssertNotNil(node) + XCTAssertEqual(node!.value, 123) + XCTAssertTrue(node === list.first) + } + + func testNodeAtIndex() { + let list = buildList() + + let nodeCount = list.count + XCTAssertEqual(nodeCount, numbers.count) + + XCTAssertNil(list.node(atIndex: -1)) + XCTAssertNil(list.node(atIndex: nodeCount)) + + let first = list.node(atIndex: 0) + XCTAssertNotNil(first) + XCTAssertTrue(first === list.first) + XCTAssertEqual(first!.value, numbers[0]) + + let last = list.node(atIndex: nodeCount - 1) + XCTAssertNotNil(last) + XCTAssertTrue(last === list.last) + XCTAssertEqual(last!.value, numbers[nodeCount - 1]) + + for i in 0..() + list.insert(123, atIndex: 0) + + XCTAssertFalse(list.isEmpty) + XCTAssertEqual(list.count, 1) + + let node = list.node(atIndex: 0) + XCTAssertNotNil(node) + XCTAssertEqual(node!.value, 123) + } + + func testInsertAtIndex() { + let list = buildList() + let prev = list.node(atIndex: 2) + let next = list.node(atIndex: 3) + let nodeCount = list.count + + list.insert(444, atIndex: 3) + + let node = list.node(atIndex: 3) + XCTAssertNotNil(node) + XCTAssertEqual(node!.value, 444) + XCTAssertEqual(nodeCount + 1, list.count) + + XCTAssertFalse(prev === node) + XCTAssertFalse(next === node) + XCTAssertTrue(prev!.next === node) + XCTAssertTrue(next!.previous === node) + } + + func testRemoveAtIndexOnListWithOneElement() { + let list = LinkedList() + list.append(123) + + let value = list.remove(atIndex: 0) + XCTAssertEqual(value, 123) + + XCTAssertTrue(list.isEmpty) + XCTAssertEqual(list.count, 0) + XCTAssertNil(list.first) + XCTAssertNil(list.last) + } + + func testRemoveAtIndex() { + let list = buildList() + let prev = list.node(atIndex: 2) + let next = list.node(atIndex: 3) + let nodeCount = list.count + + list.insert(444, atIndex: 3) + + let value = list.remove(atIndex: 3) + XCTAssertEqual(value, 444) + + let node = list.node(atIndex: 3) + XCTAssertTrue(next === node) + XCTAssertTrue(prev!.next === node) + XCTAssertTrue(node!.previous === prev) + XCTAssertEqual(nodeCount, list.count) + } + + func testRemoveLastOnListWithOneElement() { + let list = LinkedList() + list.append(123) + + let value = list.removeLast() + XCTAssertEqual(value, 123) + + XCTAssertTrue(list.isEmpty) + XCTAssertEqual(list.count, 0) + XCTAssertNil(list.first) + XCTAssertNil(list.last) + } + + func testRemoveLast() { + let list = buildList() + let last = list.last + let prev = last!.previous + let nodeCount = list.count + + let value = list.removeLast() + XCTAssertEqual(value, 5) + + XCTAssertNil(last!.previous) + XCTAssertNil(last!.next) + + XCTAssertNil(prev!.next) + XCTAssertTrue(list.last === prev) + XCTAssertEqual(nodeCount - 1, list.count) + } + + func testRemoveAll() { + let list = buildList() + list.removeAll() + XCTAssertTrue(list.isEmpty) + XCTAssertEqual(list.count, 0) + XCTAssertNil(list.first) + XCTAssertNil(list.last) + } + + func testReverseLinkedList() { + let list = buildList() + let first = list.first + let last = list.last + let nodeCount = list.count + + list.reverse() + + XCTAssertTrue(first === list.last) + XCTAssertTrue(last === list.first) + XCTAssertEqual(nodeCount, list.count) + } +} diff --git a/Rootish Array Stack/Tests/Tests.xcodeproj/project.pbxproj b/Rootish Array Stack/Tests/Tests.xcodeproj/project.pbxproj new file mode 100644 index 000000000..d6fb62c9d --- /dev/null +++ b/Rootish Array Stack/Tests/Tests.xcodeproj/project.pbxproj @@ -0,0 +1,264 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 1D059BB21E073CED00391DD1 /* RootishArrayStack.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D059BB11E073CED00391DD1 /* RootishArrayStack.swift */; }; + 7B80C3FA1C77A61E003CECC7 /* RootishArrayStackTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C3F91C77A61E003CECC7 /* RootishArrayStackTests.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 1D059BB11E073CED00391DD1 /* RootishArrayStack.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = RootishArrayStack.swift; path = ../RootishArrayStack.swift; sourceTree = ""; }; + 7B2BBC801C779D720067B71D /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 7B2BBC941C779E7B0067B71D /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; + 7B80C3F91C77A61E003CECC7 /* RootishArrayStackTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RootishArrayStackTests.swift; sourceTree = SOURCE_ROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 7B2BBC7D1C779D720067B71D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 7B2BBC681C779D710067B71D = { + isa = PBXGroup; + children = ( + 7B2BBC831C779D720067B71D /* Tests */, + 7B2BBC721C779D710067B71D /* Products */, + ); + sourceTree = ""; + }; + 7B2BBC721C779D710067B71D /* Products */ = { + isa = PBXGroup; + children = ( + 7B2BBC801C779D720067B71D /* Tests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 7B2BBC831C779D720067B71D /* Tests */ = { + isa = PBXGroup; + children = ( + 1D059BB11E073CED00391DD1 /* RootishArrayStack.swift */, + 7B80C3F91C77A61E003CECC7 /* RootishArrayStackTests.swift */, + 7B2BBC941C779E7B0067B71D /* Info.plist */, + ); + name = Tests; + path = TestsTests; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 7B2BBC7F1C779D720067B71D /* Tests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */; + buildPhases = ( + 7B2BBC7C1C779D720067B71D /* Sources */, + 7B2BBC7D1C779D720067B71D /* Frameworks */, + 7B2BBC7E1C779D720067B71D /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Tests; + productName = TestsTests; + productReference = 7B2BBC801C779D720067B71D /* Tests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 7B2BBC691C779D710067B71D /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0720; + LastUpgradeCheck = 0720; + ORGANIZATIONNAME = "Swift Algorithm Club"; + TargetAttributes = { + 7B2BBC7F1C779D720067B71D = { + CreatedOnToolsVersion = 7.2; + LastSwiftMigration = 0800; + }; + }; + }; + buildConfigurationList = 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 7B2BBC681C779D710067B71D; + productRefGroup = 7B2BBC721C779D710067B71D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 7B2BBC7F1C779D720067B71D /* Tests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 7B2BBC7E1C779D720067B71D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 7B2BBC7C1C779D720067B71D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 7B80C3FA1C77A61E003CECC7 /* RootishArrayStackTests.swift in Sources */, + 1D059BB21E073CED00391DD1 /* RootishArrayStack.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 7B2BBC871C779D720067B71D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 7B2BBC881C779D720067B71D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + }; + name = Release; + }; + 7B2BBC8D1C779D720067B71D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; + }; + name = Debug; + }; + 7B2BBC8E1C779D720067B71D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7B2BBC871C779D720067B71D /* Debug */, + 7B2BBC881C779D720067B71D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7B2BBC8D1C779D720067B71D /* Debug */, + 7B2BBC8E1C779D720067B71D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 7B2BBC691C779D710067B71D /* Project object */; +} diff --git a/Rootish Array Stack/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Rootish Array Stack/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..6c0ea8493 --- /dev/null +++ b/Rootish Array Stack/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Rootish Array Stack/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Rootish Array Stack/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme new file mode 100644 index 000000000..8ef8d8581 --- /dev/null +++ b/Rootish Array Stack/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -0,0 +1,90 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From f709ee8d52dbef684e02e6350bd5110c2ffb313b Mon Sep 17 00:00:00 2001 From: BenEmdon Date: Sun, 18 Dec 2016 17:31:52 -0500 Subject: [PATCH 0693/1679] added test scheme to travis --- .travis.yml | 1 + .../contents.xcworkspacedata | 7 + .../Tests/RootishArrayStackTests.swift | 492 +++++++++--------- .../Tests/Tests.xcodeproj/project.pbxproj | 9 +- .../xcshareddata/xcschemes/Tests.xcscheme | 2 +- .../contents.xcworkspacedata | 29 ++ 6 files changed, 293 insertions(+), 247 deletions(-) create mode 100644 Rootish Array Stack/RootishArrayStack.playground/playground.xcworkspace/contents.xcworkspacedata diff --git a/.travis.yml b/.travis.yml index 45f0d4beb..695c702c2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -31,6 +31,7 @@ script: # - xcodebuild test -project ./Priority\ Queue/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Queue/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Quicksort/Tests/Tests.xcodeproj -scheme Tests +- xcodebuild test -project ./Rootish\ Array\ Stack/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Run-Length\ Encoding/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Select\ Minimum\ Maximum/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Selection\ Sort/Tests/Tests.xcodeproj -scheme Tests diff --git a/Rootish Array Stack/RootishArrayStack.playground/playground.xcworkspace/contents.xcworkspacedata b/Rootish Array Stack/RootishArrayStack.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Rootish Array Stack/RootishArrayStack.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Rootish Array Stack/Tests/RootishArrayStackTests.swift b/Rootish Array Stack/Tests/RootishArrayStackTests.swift index 7fa420cb2..8292f3d30 100755 --- a/Rootish Array Stack/Tests/RootishArrayStackTests.swift +++ b/Rootish Array Stack/Tests/RootishArrayStackTests.swift @@ -1,251 +1,255 @@ import XCTest class RootishArrayStackTests: XCTestCase { - let numbers = [8, 2, 10, 9, 7, 5] - - fileprivate func buildList() -> LinkedList { - let list = LinkedList() - for number in numbers { - list.append(number) - } +// let randomNumbers = [8, 2, 10, 9, 7, 5] + + func buildList(withNumbers numbers: [Int]? = nil) -> RootishArrayStack { + var list = RootishArrayStack() + if let numbers = numbers { + for number in numbers { + list.append(element: number) + } + } return list } - func testEmptyList() { - let list = LinkedList() - XCTAssertTrue(list.isEmpty) - XCTAssertEqual(list.count, 0) - XCTAssertNil(list.first) - XCTAssertNil(list.last) - } - - func testListWithOneElement() { - let list = LinkedList() - list.append(123) - - XCTAssertFalse(list.isEmpty) - XCTAssertEqual(list.count, 1) - - XCTAssertNotNil(list.first) - XCTAssertNil(list.first!.previous) - XCTAssertNil(list.first!.next) - XCTAssertEqual(list.first!.value, 123) - - XCTAssertNotNil(list.last) - XCTAssertNil(list.last!.previous) - XCTAssertNil(list.last!.next) - XCTAssertEqual(list.last!.value, 123) - - XCTAssertTrue(list.first === list.last) - } - - func testListWithTwoElements() { - let list = LinkedList() - list.append(123) - list.append(456) - - XCTAssertEqual(list.count, 2) - - XCTAssertNotNil(list.first) - XCTAssertEqual(list.first!.value, 123) - - XCTAssertNotNil(list.last) - XCTAssertEqual(list.last!.value, 456) - - XCTAssertTrue(list.first !== list.last) - - XCTAssertNil(list.first!.previous) - XCTAssertTrue(list.first!.next === list.last) - XCTAssertTrue(list.last!.previous === list.first) - XCTAssertNil(list.last!.next) - } - - func testListWithThreeElements() { - let list = LinkedList() - list.append(123) - list.append(456) - list.append(789) - - XCTAssertEqual(list.count, 3) - - XCTAssertNotNil(list.first) - XCTAssertEqual(list.first!.value, 123) - - let second = list.first!.next - XCTAssertNotNil(second) - XCTAssertEqual(second!.value, 456) - - XCTAssertNotNil(list.last) - XCTAssertEqual(list.last!.value, 789) - - XCTAssertNil(list.first!.previous) - XCTAssertTrue(list.first!.next === second) - XCTAssertTrue(second!.previous === list.first) - XCTAssertTrue(second!.next === list.last) - XCTAssertTrue(list.last!.previous === second) - XCTAssertNil(list.last!.next) - } - - func testNodeAtIndexInEmptyList() { - let list = LinkedList() - let node = list.node(atIndex: 0) - XCTAssertNil(node) - } - - func testNodeAtIndexInListWithOneElement() { - let list = LinkedList() - list.append(123) - - let node = list.node(atIndex: 0) - XCTAssertNotNil(node) - XCTAssertEqual(node!.value, 123) - XCTAssertTrue(node === list.first) - } - - func testNodeAtIndex() { - let list = buildList() - - let nodeCount = list.count - XCTAssertEqual(nodeCount, numbers.count) - - XCTAssertNil(list.node(atIndex: -1)) - XCTAssertNil(list.node(atIndex: nodeCount)) - - let first = list.node(atIndex: 0) - XCTAssertNotNil(first) - XCTAssertTrue(first === list.first) - XCTAssertEqual(first!.value, numbers[0]) - - let last = list.node(atIndex: nodeCount - 1) - XCTAssertNotNil(last) - XCTAssertTrue(last === list.last) - XCTAssertEqual(last!.value, numbers[nodeCount - 1]) - - for i in 0..() - list.insert(123, atIndex: 0) - - XCTAssertFalse(list.isEmpty) - XCTAssertEqual(list.count, 1) - - let node = list.node(atIndex: 0) - XCTAssertNotNil(node) - XCTAssertEqual(node!.value, 123) - } - - func testInsertAtIndex() { - let list = buildList() - let prev = list.node(atIndex: 2) - let next = list.node(atIndex: 3) - let nodeCount = list.count - - list.insert(444, atIndex: 3) - - let node = list.node(atIndex: 3) - XCTAssertNotNil(node) - XCTAssertEqual(node!.value, 444) - XCTAssertEqual(nodeCount + 1, list.count) - - XCTAssertFalse(prev === node) - XCTAssertFalse(next === node) - XCTAssertTrue(prev!.next === node) - XCTAssertTrue(next!.previous === node) - } - - func testRemoveAtIndexOnListWithOneElement() { - let list = LinkedList() - list.append(123) - - let value = list.remove(atIndex: 0) - XCTAssertEqual(value, 123) - - XCTAssertTrue(list.isEmpty) - XCTAssertEqual(list.count, 0) - XCTAssertNil(list.first) - XCTAssertNil(list.last) - } - - func testRemoveAtIndex() { - let list = buildList() - let prev = list.node(atIndex: 2) - let next = list.node(atIndex: 3) - let nodeCount = list.count - - list.insert(444, atIndex: 3) - - let value = list.remove(atIndex: 3) - XCTAssertEqual(value, 444) - - let node = list.node(atIndex: 3) - XCTAssertTrue(next === node) - XCTAssertTrue(prev!.next === node) - XCTAssertTrue(node!.previous === prev) - XCTAssertEqual(nodeCount, list.count) - } - - func testRemoveLastOnListWithOneElement() { - let list = LinkedList() - list.append(123) - - let value = list.removeLast() - XCTAssertEqual(value, 123) - - XCTAssertTrue(list.isEmpty) - XCTAssertEqual(list.count, 0) - XCTAssertNil(list.first) - XCTAssertNil(list.last) - } - - func testRemoveLast() { - let list = buildList() - let last = list.last - let prev = last!.previous - let nodeCount = list.count - - let value = list.removeLast() - XCTAssertEqual(value, 5) - - XCTAssertNil(last!.previous) - XCTAssertNil(last!.next) - - XCTAssertNil(prev!.next) - XCTAssertTrue(list.last === prev) - XCTAssertEqual(nodeCount - 1, list.count) - } - - func testRemoveAll() { - let list = buildList() - list.removeAll() - XCTAssertTrue(list.isEmpty) - XCTAssertEqual(list.count, 0) - XCTAssertNil(list.first) - XCTAssertNil(list.last) - } - - func testReverseLinkedList() { - let list = buildList() - let first = list.first - let last = list.last - let nodeCount = list.count - - list.reverse() - - XCTAssertTrue(first === list.last) - XCTAssertTrue(last === list.first) - XCTAssertEqual(nodeCount, list.count) - } + func testEmptyList() { + let list = buildList() + XCTAssertTrue(list.isEmpty) + XCTAssertEqual(list.count, 0) + XCTAssertEqual(list.capacity, 0) + XCTAssertNil(list.first) + XCTAssertNil(list.last) + } + + func testListWithOneElement() { + let list = buildList(withNumbers: [1]) + XCTAssertFalse(list.isEmpty) + XCTAssertEqual(list.count, 1) + XCTAssertEqual(list.capacity, 1) + XCTAssertEqual(list.first, 1) + XCTAssertEqual(list.last, 1) + XCTAssertEqual(list.first, list.last) + } + + func testListWithTwoElements() { + let list = buildList(withNumbers: [1, 2]) + XCTAssertFalse(list.isEmpty) + XCTAssertEqual(list.count, 2) + XCTAssertEqual(list.capacity, 3) + XCTAssertEqual(list.first, 1) + XCTAssertEqual(list.last, 2) + XCTAssertNotEqual(list.first, list.last) + } + +// +// func testListWithTwoElements() { +// var list = RootishArrayStack() +// list.append(123) +// list.append(456) +// +// XCTAssertEqual(list.count, 2) +// +// XCTAssertNotNil(list.first) +// XCTAssertEqual(list.first!.value, 123) +// +// XCTAssertNotNil(list.last) +// XCTAssertEqual(list.last!.value, 456) +// +// XCTAssertTrue(list.first !== list.last) +// +// XCTAssertNil(list.first!.previous) +// XCTAssertTrue(list.first!.next === list.last) +// XCTAssertTrue(list.last!.previous === list.first) +// XCTAssertNil(list.last!.next) +// } +// +// func testListWithThreeElements() { +// var list = RootishArrayStack() +// list.append(123) +// list.append(456) +// list.append(789) +// +// XCTAssertEqual(list.count, 3) +// +// XCTAssertNotNil(list.first) +// XCTAssertEqual(list.first!.value, 123) +// +// let second = list.first!.next +// XCTAssertNotNil(second) +// XCTAssertEqual(second!.value, 456) +// +// XCTAssertNotNil(list.last) +// XCTAssertEqual(list.last!.value, 789) +// +// XCTAssertNil(list.first!.previous) +// XCTAssertTrue(list.first!.next === second) +// XCTAssertTrue(second!.previous === list.first) +// XCTAssertTrue(second!.next === list.last) +// XCTAssertTrue(list.last!.previous === second) +// XCTAssertNil(list.last!.next) +// } +// +// func testNodeAtIndexInEmptyList() { +// var list = RootishArrayStack() +// let node = list.node(atIndex: 0) +// XCTAssertNil(node) +// } +// +// func testNodeAtIndexInListWithOneElement() { +// let list = RootishArrayStack() +// list.append(123) +// +// let node = list.node(atIndex: 0) +// XCTAssertNotNil(node) +// XCTAssertEqual(node!.value, 123) +// XCTAssertTrue(node === list.first) +// } +// +// func testNodeAtIndex() { +// let list = buildList() +// +// let nodeCount = list.count +// XCTAssertEqual(nodeCount, numbers.count) +// +// XCTAssertNil(list.node(atIndex: -1)) +// XCTAssertNil(list.node(atIndex: nodeCount)) +// +// let first = list.node(atIndex: 0) +// XCTAssertNotNil(first) +// XCTAssertTrue(first === list.first) +// XCTAssertEqual(first!.value, numbers[0]) +// +// let last = list.node(atIndex: nodeCount - 1) +// XCTAssertNotNil(last) +// XCTAssertTrue(last === list.last) +// XCTAssertEqual(last!.value, numbers[nodeCount - 1]) +// +// for i in 0..() +// list.insert(123, atIndex: 0) +// +// XCTAssertFalse(list.isEmpty) +// XCTAssertEqual(list.count, 1) +// +// let node = list.node(atIndex: 0) +// XCTAssertNotNil(node) +// XCTAssertEqual(node!.value, 123) +// } +// +// func testInsertAtIndex() { +// let list = buildList() +// let prev = list.node(atIndex: 2) +// let next = list.node(atIndex: 3) +// let nodeCount = list.count +// +// list.insert(444, atIndex: 3) +// +// let node = list.node(atIndex: 3) +// XCTAssertNotNil(node) +// XCTAssertEqual(node!.value, 444) +// XCTAssertEqual(nodeCount + 1, list.count) +// +// XCTAssertFalse(prev === node) +// XCTAssertFalse(next === node) +// XCTAssertTrue(prev!.next === node) +// XCTAssertTrue(next!.previous === node) +// } +// +// func testRemoveAtIndexOnListWithOneElement() { +// let list = LinkedList() +// list.append(123) +// +// let value = list.remove(atIndex: 0) +// XCTAssertEqual(value, 123) +// +// XCTAssertTrue(list.isEmpty) +// XCTAssertEqual(list.count, 0) +// XCTAssertNil(list.first) +// XCTAssertNil(list.last) +// } +// +// func testRemoveAtIndex() { +// let list = buildList() +// let prev = list.node(atIndex: 2) +// let next = list.node(atIndex: 3) +// let nodeCount = list.count +// +// list.insert(444, atIndex: 3) +// +// let value = list.remove(atIndex: 3) +// XCTAssertEqual(value, 444) +// +// let node = list.node(atIndex: 3) +// XCTAssertTrue(next === node) +// XCTAssertTrue(prev!.next === node) +// XCTAssertTrue(node!.previous === prev) +// XCTAssertEqual(nodeCount, list.count) +// } +// +// func testRemoveLastOnListWithOneElement() { +// let list = LinkedList() +// list.append(123) +// +// let value = list.removeLast() +// XCTAssertEqual(value, 123) +// +// XCTAssertTrue(list.isEmpty) +// XCTAssertEqual(list.count, 0) +// XCTAssertNil(list.first) +// XCTAssertNil(list.last) +// } +// +// func testRemoveLast() { +// let list = buildList() +// let last = list.last +// let prev = last!.previous +// let nodeCount = list.count +// +// let value = list.removeLast() +// XCTAssertEqual(value, 5) +// +// XCTAssertNil(last!.previous) +// XCTAssertNil(last!.next) +// +// XCTAssertNil(prev!.next) +// XCTAssertTrue(list.last === prev) +// XCTAssertEqual(nodeCount - 1, list.count) +// } +// +// func testRemoveAll() { +// let list = buildList() +// list.removeAll() +// XCTAssertTrue(list.isEmpty) +// XCTAssertEqual(list.count, 0) +// XCTAssertNil(list.first) +// XCTAssertNil(list.last) +// } +// +// func testReverseLinkedList() { +// let list = buildList() +// let first = list.first +// let last = list.last +// let nodeCount = list.count +// +// list.reverse() +// +// XCTAssertTrue(first === list.last) +// XCTAssertTrue(last === list.first) +// XCTAssertEqual(nodeCount, list.count) +// } } diff --git a/Rootish Array Stack/Tests/Tests.xcodeproj/project.pbxproj b/Rootish Array Stack/Tests/Tests.xcodeproj/project.pbxproj index d6fb62c9d..cdfd35f71 100644 --- a/Rootish Array Stack/Tests/Tests.xcodeproj/project.pbxproj +++ b/Rootish Array Stack/Tests/Tests.xcodeproj/project.pbxproj @@ -83,12 +83,12 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; - LastUpgradeCheck = 0720; + LastUpgradeCheck = 0820; ORGANIZATIONNAME = "Swift Algorithm Club"; TargetAttributes = { 7B2BBC7F1C779D720067B71D = { CreatedOnToolsVersion = 7.2; - LastSwiftMigration = 0800; + LastSwiftMigration = 0820; }; }; }; @@ -146,8 +146,10 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; @@ -190,8 +192,10 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; @@ -210,6 +214,7 @@ MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; }; name = Release; }; diff --git a/Rootish Array Stack/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Rootish Array Stack/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme index 8ef8d8581..dfcf6de42 100644 --- a/Rootish Array Stack/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme +++ b/Rootish Array Stack/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -1,6 +1,6 @@ + + + + + + + + + + + + + + + + + + From 3a44c0b3c948f43856f0135167934d6ccc6c3077 Mon Sep 17 00:00:00 2001 From: BenEmdon Date: Mon, 19 Dec 2016 11:27:18 -0500 Subject: [PATCH 0694/1679] Added tests --- .../Tests/RootishArrayStackTests.swift | 382 ++++++++---------- .../contents.xcworkspacedata | 4 +- 2 files changed, 170 insertions(+), 216 deletions(-) diff --git a/Rootish Array Stack/Tests/RootishArrayStackTests.swift b/Rootish Array Stack/Tests/RootishArrayStackTests.swift index 8292f3d30..f73857d0f 100755 --- a/Rootish Array Stack/Tests/RootishArrayStackTests.swift +++ b/Rootish Array Stack/Tests/RootishArrayStackTests.swift @@ -1,10 +1,22 @@ import XCTest +fileprivate extension RootishArrayStack { + func equal(toArray array: Array) -> Bool{ + for index in 0.. RootishArrayStack { + private func buildList(withNumbers numbers: [Int]? = nil) -> RootishArrayStack { var list = RootishArrayStack() + if let numbers = numbers { for number in numbers { list.append(element: number) @@ -14,242 +26,184 @@ class RootishArrayStackTests: XCTestCase { } func testEmptyList() { + let emptyArray = [Int]() let list = buildList() + XCTAssertTrue(list.isEmpty) XCTAssertEqual(list.count, 0) XCTAssertEqual(list.capacity, 0) XCTAssertNil(list.first) XCTAssertNil(list.last) + XCTAssertTrue(list.equal(toArray: emptyArray)) } func testListWithOneElement() { - let list = buildList(withNumbers: [1]) + let array = [1] + let list = buildList(withNumbers: array) + XCTAssertFalse(list.isEmpty) XCTAssertEqual(list.count, 1) XCTAssertEqual(list.capacity, 1) XCTAssertEqual(list.first, 1) XCTAssertEqual(list.last, 1) XCTAssertEqual(list.first, list.last) + XCTAssertTrue(list.equal(toArray: array)) } func testListWithTwoElements() { - let list = buildList(withNumbers: [1, 2]) + let array = [1, 2] + let list = buildList(withNumbers: array) + XCTAssertFalse(list.isEmpty) XCTAssertEqual(list.count, 2) XCTAssertEqual(list.capacity, 3) XCTAssertEqual(list.first, 1) XCTAssertEqual(list.last, 2) XCTAssertNotEqual(list.first, list.last) + XCTAssertTrue(list.equal(toArray: array)) + } + + func testListWithThreeElements() { + let array = [1, 2, 3] + let list = buildList(withNumbers: array) + + XCTAssertFalse(list.isEmpty) + XCTAssertEqual(list.count, 3) + XCTAssertEqual(list.capacity, 6) + XCTAssertEqual(list.first, 1) + XCTAssertEqual(list.last, 3) + XCTAssertNotEqual(list.first, list.last) + XCTAssertTrue(list.equal(toArray: array)) + } + + func testFillThenEmpty() { + let array = [Int](0..<100) + let emptyArray = [Int]() + var list = buildList(withNumbers: array) + + XCTAssertTrue(list.equal(toArray: array)) + + for _ in 0..<100 { + list.remove(atIndex: list.count - 1) + } + + XCTAssertEqual(list.count, 0) + XCTAssertEqual(list.capacity, 0) + XCTAssertTrue(list.equal(toArray: emptyArray)) + } + + func testInsertFront() { + var array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] + var list = buildList(withNumbers: array) + + XCTAssertEqual(list.count, 10) + XCTAssertEqual(list.capacity, 15) + XCTAssertEqual(list.first, 1) + XCTAssertTrue(list.equal(toArray: array)) + + let newElement = 0 + list.insert(element: newElement, atIndex: 0) + array.insert(newElement, at: 0) + + XCTAssertEqual(list.count, 11) + XCTAssertEqual(list.capacity, 21) + XCTAssertEqual(list.first, newElement) + XCTAssertTrue(list.equal(toArray: array)) } -// -// func testListWithTwoElements() { -// var list = RootishArrayStack() -// list.append(123) -// list.append(456) -// -// XCTAssertEqual(list.count, 2) -// -// XCTAssertNotNil(list.first) -// XCTAssertEqual(list.first!.value, 123) -// -// XCTAssertNotNil(list.last) -// XCTAssertEqual(list.last!.value, 456) -// -// XCTAssertTrue(list.first !== list.last) -// -// XCTAssertNil(list.first!.previous) -// XCTAssertTrue(list.first!.next === list.last) -// XCTAssertTrue(list.last!.previous === list.first) -// XCTAssertNil(list.last!.next) -// } -// -// func testListWithThreeElements() { -// var list = RootishArrayStack() -// list.append(123) -// list.append(456) -// list.append(789) -// -// XCTAssertEqual(list.count, 3) -// -// XCTAssertNotNil(list.first) -// XCTAssertEqual(list.first!.value, 123) -// -// let second = list.first!.next -// XCTAssertNotNil(second) -// XCTAssertEqual(second!.value, 456) -// -// XCTAssertNotNil(list.last) -// XCTAssertEqual(list.last!.value, 789) -// -// XCTAssertNil(list.first!.previous) -// XCTAssertTrue(list.first!.next === second) -// XCTAssertTrue(second!.previous === list.first) -// XCTAssertTrue(second!.next === list.last) -// XCTAssertTrue(list.last!.previous === second) -// XCTAssertNil(list.last!.next) -// } -// -// func testNodeAtIndexInEmptyList() { -// var list = RootishArrayStack() -// let node = list.node(atIndex: 0) -// XCTAssertNil(node) -// } -// -// func testNodeAtIndexInListWithOneElement() { -// let list = RootishArrayStack() -// list.append(123) -// -// let node = list.node(atIndex: 0) -// XCTAssertNotNil(node) -// XCTAssertEqual(node!.value, 123) -// XCTAssertTrue(node === list.first) -// } -// -// func testNodeAtIndex() { -// let list = buildList() -// -// let nodeCount = list.count -// XCTAssertEqual(nodeCount, numbers.count) -// -// XCTAssertNil(list.node(atIndex: -1)) -// XCTAssertNil(list.node(atIndex: nodeCount)) -// -// let first = list.node(atIndex: 0) -// XCTAssertNotNil(first) -// XCTAssertTrue(first === list.first) -// XCTAssertEqual(first!.value, numbers[0]) -// -// let last = list.node(atIndex: nodeCount - 1) -// XCTAssertNotNil(last) -// XCTAssertTrue(last === list.last) -// XCTAssertEqual(last!.value, numbers[nodeCount - 1]) -// -// for i in 0..() -// list.insert(123, atIndex: 0) -// -// XCTAssertFalse(list.isEmpty) -// XCTAssertEqual(list.count, 1) -// -// let node = list.node(atIndex: 0) -// XCTAssertNotNil(node) -// XCTAssertEqual(node!.value, 123) -// } -// -// func testInsertAtIndex() { -// let list = buildList() -// let prev = list.node(atIndex: 2) -// let next = list.node(atIndex: 3) -// let nodeCount = list.count -// -// list.insert(444, atIndex: 3) -// -// let node = list.node(atIndex: 3) -// XCTAssertNotNil(node) -// XCTAssertEqual(node!.value, 444) -// XCTAssertEqual(nodeCount + 1, list.count) -// -// XCTAssertFalse(prev === node) -// XCTAssertFalse(next === node) -// XCTAssertTrue(prev!.next === node) -// XCTAssertTrue(next!.previous === node) -// } -// -// func testRemoveAtIndexOnListWithOneElement() { -// let list = LinkedList() -// list.append(123) -// -// let value = list.remove(atIndex: 0) -// XCTAssertEqual(value, 123) -// -// XCTAssertTrue(list.isEmpty) -// XCTAssertEqual(list.count, 0) -// XCTAssertNil(list.first) -// XCTAssertNil(list.last) -// } -// -// func testRemoveAtIndex() { -// let list = buildList() -// let prev = list.node(atIndex: 2) -// let next = list.node(atIndex: 3) -// let nodeCount = list.count -// -// list.insert(444, atIndex: 3) -// -// let value = list.remove(atIndex: 3) -// XCTAssertEqual(value, 444) -// -// let node = list.node(atIndex: 3) -// XCTAssertTrue(next === node) -// XCTAssertTrue(prev!.next === node) -// XCTAssertTrue(node!.previous === prev) -// XCTAssertEqual(nodeCount, list.count) -// } -// -// func testRemoveLastOnListWithOneElement() { -// let list = LinkedList() -// list.append(123) -// -// let value = list.removeLast() -// XCTAssertEqual(value, 123) -// -// XCTAssertTrue(list.isEmpty) -// XCTAssertEqual(list.count, 0) -// XCTAssertNil(list.first) -// XCTAssertNil(list.last) -// } -// -// func testRemoveLast() { -// let list = buildList() -// let last = list.last -// let prev = last!.previous -// let nodeCount = list.count -// -// let value = list.removeLast() -// XCTAssertEqual(value, 5) -// -// XCTAssertNil(last!.previous) -// XCTAssertNil(last!.next) -// -// XCTAssertNil(prev!.next) -// XCTAssertTrue(list.last === prev) -// XCTAssertEqual(nodeCount - 1, list.count) -// } -// -// func testRemoveAll() { -// let list = buildList() -// list.removeAll() -// XCTAssertTrue(list.isEmpty) -// XCTAssertEqual(list.count, 0) -// XCTAssertNil(list.first) -// XCTAssertNil(list.last) -// } -// -// func testReverseLinkedList() { -// let list = buildList() -// let first = list.first -// let last = list.last -// let nodeCount = list.count -// -// list.reverse() -// -// XCTAssertTrue(first === list.last) -// XCTAssertTrue(last === list.first) -// XCTAssertEqual(nodeCount, list.count) -// } + func testInsertMiddle() { + var array = [0, 2, 3] + var list = buildList(withNumbers: array) + + XCTAssertEqual(list.count, 3) + XCTAssertEqual(list.capacity, 6) + XCTAssertTrue(list.equal(toArray: array)) + + let newElement = 1 + list.insert(element: newElement, atIndex: 1) + array.insert(newElement, at: 1) + + XCTAssertEqual(list.count, 4) + XCTAssertEqual(list.capacity, 10) + XCTAssertEqual(list[1], newElement) + XCTAssertTrue(list.equal(toArray: array)) + } + + func testSubscriptGet() { + let array = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] + let list = buildList(withNumbers: array) + for index in 0...9 { + XCTAssertEqual(list[index], index) + } + XCTAssertTrue(list.equal(toArray: array)) + } + + func testSubscriptSet() { + var array = [Int](0..<10) + var list = buildList(withNumbers: array) + + list[1] = 100 + list[5] = 500 + list[8] = 800 + array[1] = 100 + array[5] = 500 + array[8] = 800 + + XCTAssertTrue(list.equal(toArray: array)) + } + + func testRemoveFirst() { + var array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] + var list = buildList(withNumbers: array) + + XCTAssertEqual(list.count, 10) + XCTAssertEqual(list.capacity, 15) + XCTAssertEqual(list.first, 1) + XCTAssertTrue(list.equal(toArray: array)) + + list.remove(atIndex: 0) + array.remove(at: 0) + + XCTAssertEqual(list.count, 9) + XCTAssertEqual(list.capacity, 15) + XCTAssertEqual(list.first, 2) + XCTAssertTrue(list.equal(toArray: array)) + } + + + func testRemoveMiddle() { + var array = [0, 1, 2, 3] + var list = buildList(withNumbers: array) + + XCTAssertEqual(list.count, 4) + XCTAssertEqual(list.capacity, 10) + XCTAssertEqual(list.first, 0) + XCTAssertTrue(list.equal(toArray: array)) + + list.remove(atIndex: 2) + array.remove(at: 2) + + XCTAssertEqual(list.count, 3) + XCTAssertEqual(list.capacity, 6) + XCTAssertEqual(list.first, 0) + XCTAssertTrue(list.equal(toArray: array)) + } + + func testRemoveLast() { + var array = [0, 1, 2, 3] + var list = buildList(withNumbers: array) + + XCTAssertEqual(list.count, 4) + XCTAssertEqual(list.capacity, 10) + XCTAssertEqual(list.first, 0) + XCTAssertTrue(list.equal(toArray: array)) + + list.remove(atIndex: 3) + array.remove(at: 3) + + XCTAssertEqual(list.count, 3) + XCTAssertEqual(list.capacity, 6) + XCTAssertEqual(list.first, 0) + XCTAssertTrue(list.equal(toArray: array)) + } } diff --git a/swift-algorithm-club.xcworkspace/contents.xcworkspacedata b/swift-algorithm-club.xcworkspace/contents.xcworkspacedata index 2cea625d1..194c0ae79 100644 --- a/swift-algorithm-club.xcworkspace/contents.xcworkspacedata +++ b/swift-algorithm-club.xcworkspace/contents.xcworkspacedata @@ -1543,10 +1543,10 @@ location = "group:Info.plist"> + location = "group:RootishArrayStackTests.swift"> + location = "group:RootishArrayStack.swift"> From 3b5a508c8d16bbbfbff3ea5b1028b286464d22d5 Mon Sep 17 00:00:00 2001 From: BenEmdon Date: Tue, 20 Dec 2016 20:46:30 -0500 Subject: [PATCH 0695/1679] Added Rootish Array Stack to Readme --- README.markdown | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.markdown b/README.markdown index 4c812b0f3..d4637f7c0 100644 --- a/README.markdown +++ b/README.markdown @@ -130,6 +130,7 @@ Most of the time using just the built-in `Array`, `Dictionary`, and `Set` types - [Bit Set](Bit Set/). A fixed-size sequence of *n* bits. - [Fixed Size Array](Fixed Size Array/). When you know beforehand how large your data will be, it might be more efficient to use an old-fashioned array with a fixed size. - [Ordered Array](Ordered Array/). An array that is always sorted. +- [Rootish Array Stack](Rootish Array Stack/). A space and time efficient variation on Swift arrays. ### Queues @@ -205,6 +206,7 @@ The following books are available for free online: - [Algorithms, Etc.](http://jeffe.cs.illinois.edu/teaching/algorithms/) by Erickson - [Algorithms + Data Structures = Programs](http://www.ethoberon.ethz.ch/WirthPubl/AD.pdf) by Wirth - Algorithms and Data Structures: The Basic Toolbox by Mehlhorn and Sanders +- [Open Data Structures](http://opendatastructures.org) by Pat Morin - [Wikibooks: Algorithms and Implementations](https://en.wikibooks.org/wiki/Algorithm_Implementation) Other algorithm repositories: From 0ffeb21dc6ec1e2a2146a43800b3c058c403a435 Mon Sep 17 00:00:00 2001 From: Stefan Cimander Date: Wed, 21 Dec 2016 18:20:18 +0100 Subject: [PATCH 0696/1679] Fix typo in ReadMe --- Trie/ReadMe.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Trie/ReadMe.md b/Trie/ReadMe.md index 172ff4750..7caa927a7 100644 --- a/Trie/ReadMe.md +++ b/Trie/ReadMe.md @@ -36,7 +36,7 @@ func contains(word: String) -> Bool { // 3 while currentIndex < characters.count, - let child = currentNode.children[character[currentIndex]] { + let child = currentNode.children[characters[currentIndex]] { currentNode = child currentIndex += 1 From 22675cf8d18407a6618909a0d3bb916dbe69762f Mon Sep 17 00:00:00 2001 From: Anton Domashnev Date: Wed, 21 Dec 2016 23:03:18 +0100 Subject: [PATCH 0697/1679] Add new images; --- AVL Tree/Images/Rotation.jpg | Bin 35153 -> 0 bytes AVL Tree/Images/RotationStep0.jpg | Bin 0 -> 22802 bytes AVL Tree/Images/RotationStep1.jpg | Bin 0 -> 18406 bytes AVL Tree/Images/RotationStep2.jpg | Bin 0 -> 18836 bytes AVL Tree/Images/RotationStep3.jpg | Bin 0 -> 18108 bytes 5 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 AVL Tree/Images/Rotation.jpg create mode 100644 AVL Tree/Images/RotationStep0.jpg create mode 100644 AVL Tree/Images/RotationStep1.jpg create mode 100644 AVL Tree/Images/RotationStep2.jpg create mode 100644 AVL Tree/Images/RotationStep3.jpg diff --git a/AVL Tree/Images/Rotation.jpg b/AVL Tree/Images/Rotation.jpg deleted file mode 100644 index 94a55df4e3268d5e9f8ed5b63a443beb9d6dda6e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 35153 zcmd?RcRZZkyDmODL3E;v8quOhkBAmwkmzM1I$G7=QeAskLU5s=YF2G?seVQeXY5kzg`2-KGxFJ0uT@Y z06O>|z%>H!L^HtE2>{U72iye!0OSCIXjcF+zK1^rz=m%C08s$}fC&Ga;IF?G5dP~? zqKE>bf9(^<{&nK@0pPx&3)lzj?E-$qBQ1UpaQ~sMKJi~y!`t6|fxo-7)0_zl$$)y| zoi`L8_Aw7bue$(rkw!i-k|3*MaL`*_TMow{q z5`RJyEr5`Kh=`Dwh=k;?k0A)b9|sWAk*^{PdZLshPQjrM-irle3Gfo41dz zpMOAL(A#&BQPDB6acSxAGcvP2e9SH?E-C$7R$lR?zM-+H8TzfIwWqhQe_-(Y(D3Bc z^vvws`~n<-T;JH-+Wxh(i#|U2eR_6|`E&7?U-$)lUq>WKbFJ4dFVCI)W2%!IR?QhTi zImaUYKY8|Vj{Psc76BUgf%TUW;$K9Bg!o5Agg0Wm3wR?TCHdP(|EH1tZRCF$#lP7# z{vv;0fsl|G|DqrzA^o>w|8(bi89yu)uHgVGA_DwiBBBGR0dTlGMR9=tzqjk3|Bv`N z@&AaQlmCzSIrU%riNFa!v{7L_+yuKY22~y#mCX2}#ip5!iC)=}64&V}xgGvVu5Np+ z7Xg6mbyaTM1c)?L(4`r^9p&2>D}J;wxelE!%6ZZ*KLHqj`SNHT+F}t=56zq)z1#if zuDX1u3YKpQr;O!9({vwL9_vwpY2mUZP}+ncwmRaBUg7au#P|5hdFFcH<5&iUZuxV$ zI@c9}mZV|!y@e7MzoD=I4=}j8i7<6#sckgNOYdc!09ry~;Y_QmQD;5K>+|}N%9E0< zym*bnBYKEGMiRlSiRO-z88N=7V&h`ll6q>?GM?_vV+?5lk=?*3n^l=@$wgiRh~cQM z@G8CPUZiX`a@Az2iCTH6bdff7=OVHnW3_Zo9!k&tkx$;hXy(-ev3A%_>(z>|NdimH zp`s@csZm}O*Z1?k6ZHP<^{F+fbzK8)VC~+nslvWkFJjUV)pSoU6|bsh^{$Y!!m=b# zImr=)#CKjpifyz2V;!P`l`!$F3T>i8cdPFYq%?STt6I2LPM6Kb!w5PF zUBd{r(8_F_NALq>%`evgH{N#g^u7Zyqm*bv#aOpfe1N}UuNTK@ZK24GSfRsxcjkj~ zBTXg}5=Ns3|5ST*4WRGj!>A!>-kgGB^J&HNMl>fp;Je2zi0sWtnO#$MpEOsR=XJ%B z$^d^P)BC$G230Wo)*!-^Kf@Kzs4hfr5ct4WN{(Umt%^XrWgq^EnmuL0{CC&e+s@Uu#-Qu*B5<4tUgl>}lPFx2A09 z5##QL{Ea(BZ~mF4>}+#Yq)Li$9%NCYYFcI7nO)&+gv!6(slIn<81rb#la8v5TbQ-y zjd?jg71dk~``&HZ55wW)WCCwEKGDo2S3|_m_Gh%H=>ApqfW5(1Tnhx+dAH8WLzO8o zbm+5nO^#f)MCfRPs6Ru@cDnt2<2NZK+#dqx`e-mh%sK1AO?&ZRdaa#`-RfXR`!B9N zmj(@und~sd>BT^F;J0>IOJ~%>-4{8->=rLre;Izh_;6xy$z2TBj#XAeQh<4W9zAal zQAAXGX0kGkN`I-8F(wgmk8~6O-sf$u+yX7Y&cIV@&QFmsGCA|7Ue`mvt+R zsSDlid^SrW`HgLjf;OA95&Jg}%XYpDxC#|kSv41GGCoWAzfJz@>Hj?93RCop*$2d1 z)}vO!gOOr7$WdJUXeX#Cw)6^HR!IOz{iLWlWy^sw=tAfz((xTS*+%|$kyiev~Tb?-ld@T^VTV^IRbV}MB-YZt+29<-_si%Gyu;1X) zK{gfZ{;)2OOE)reo;CwDm_pZF49YH50(wnRR~tMZeqUK0Zd*-kt3X<+j~vqiQhtw> zpqO?ESfBm^k#tJxp#?dCy|yA#2I0t~n~yUu2GS-2iv&}cqqgAI68X-r3mO?bj9-1< zO&jEQ9l(9Z@iw5NdwP+HB1p}nes+!4>>_uWRv1qa$7$t_Ydg~1#{KcbZ^L;5Ca^4tq@=q z(C`Ha5S?r`txQvF&3Tr`^7Bx2Bp@Zf?W(Ne;gf;2{Ef z8-EpBPf2L&EdpuX>6SflCy&7t>C>_P6^GOzhM^|+YrA0c&Szz_YA)muPT%z-xVEXP zRWq+7Qn-9Oc5Dp4}lf6!Cc>uvw-OULjaN9G@zdueJ?F1RsMQ}(Qs z;90-wlAYGGbnhZ}(;Z*uV1{ll;xDZHahi934F}vE*5NrN?RZ^2wc~+01d6uac zpG>?9PmX%mfJY?IDNkDwc|YX_*|Ic?SpGWxPuX2RFGAz)6cGNCjaZ23_!`g$jO$cE zbN5k%l0gWQruR%!2j!sEwuRXvno)MG{E~cyEu9}#1FFx9ie6ZJ5Ka`l;On!T$%^_- zxk~4z&3qBko+XvK!29sv;s%O)fu;9c5!|Iu)2|5MwnY1YP-$+H-0kPBwVN`(E?se4;4So_oI@fNfrQx~Z* zC70f1R!-~)9D$*XXyEL9`J^~8EDy>OtJ{LHL)0>Lw#s@KPxj1SIJvW%J2oYnZq4rB zky0S8g1jB#Fq;L{tHo4d?NDDa#g8$m!Dy}F<71GJX=g)ooev#?jU;Y%cEYcc@byF{ zfBuIA`#?jt8{mphZbCv_gN`Vxbw(Jy-85Df*&*|bOB}UP0j_ct6UydwC2;ZdDDC-k z=6{z`U2aB*Dyc&BwN~CbNC^8<2TP5HA)x(?bYCVwi zLFJhb?r}DpMm~38G|~k8SB+^DGd`fojtN2NYYgD-wOWZuJPtqfbcUp)4oDdQLLl@XM0Bf1N|*M;UYFy?}XtqhNu?`NJ204W~Df zJ|HrP9p(=qrWX0Rv?74}L5tEpR<>0COz(u^GWiRr4|4i(ZcA>qmcBPPnSWGDZgAfh z^>Fb@NHf{u?`fyvZ<@5Nw&EH(`y{%B-jnQ`?Cv#y^)v+73nPPA)Vegtb{r%nhItWJ zo)>3|`1^R}NmUUr{h=<|&F8=ogbu1v!93U{Vpjywnk$8_2&H`5U)k7ZXr|>m#l3}Y zpXN)C;%vB&d%hHD(nG02Rtxjl-{sz7+^O$(%Nu?RD_fxX&iv;ZulSIk%Y@<}3}39Z z9l=P7^(2u4@hv9`V#^Pa#=_NGuj@+T+U(l5O+K0{d<<=?0S$!G{8Z%$(0+!JhQU z;QPz(Xz6@!bGE!IO-4h4|4Spgp7}p5mN{+kH=LUCLF+Ot1tdjrcK}st48KhC?x0o* z5xE*_&eI;HO`1g-)85ODm#&*qgwM)A8v9EBF4w4Av0&3f zFQE5s!MBYQ5C`t(3NPvqiXK4-bz3x%^Gu7MRD=bfiexUF# zWTNYOg|p;f`s#55?)@t=Vg| z38PxXg$6)=XLyUg2ok^i;E|T0HX9?`GQF`9PN5j&VD$+Wn2mzQTmTCxj3kOl;p4Z-RJt4lB=Ycq5Gxy-vtZD0=f z*3J%wN5kFETia5s_&kJO#=lIZU_@jbR}m442tAv`@rTZgaYZ9-xK6rPsX5=Sz;^+f zm3!aIc;PxsALi#3SU)=OZuwqKX;V33f4~O92xRkV0@Buzwfn37V8l4x5}jaS*=Uta zh`ZYw<-9#{uh$zUiRU2M2ZWk=vUJZ9F4E#qweMh@KHRZvk*g7>ISN?$b!uUvT}A3Y zM&9%cjX8Goor;h%xw7}@b>*m?D zsEpQ6U&L*ux!wPPH(`KdxE=HSJv?|f#{y4f@raV}(T>PJp7N&>#3({joI>T3m?V5;X z@OoAcFrvYYR=wP2?`c5dTG}HEt~u?d92dECD(F62up|$jWY}x+YN%o~e5)9wl;`^IbbUIit?G`D3r$DRB&8v1$#Z zqM=etO98cAZhqa!l$@jAefzDWMtA7Dijxn>pFQ{XW&=z$CR{4U6@T6h@@y(oul#jR zw+y$@YS54o=TFjEA~n-CHpvM8&Xc13xZ}U38zA|YhHjbp)Q1r6%ZIyZC2XL#vRXDT zEI4@kOLx6wKb_Fevp@fMupJsUGqB;XW>$tZ!OS3%BR`L82RP3{G%G#XY@^G{GcQil z+2bni);;{l<{Ty zi#1*R>>pF^a{Qsw%oHa$!ren{CMPR1eF=DYXsT!9HV`bI$tzEOXzwy|n3A$TLhjQjHS>LZH8fuxP;I^&9Ffd>S?D(tep+EROhi#EA?v=nQS$ zZ4AF-U2$ojWmY=GV^2;kdJ8MJ)DeyA|+CtG53 zam9}4q$`{1Cw?0dy^NXEvZvzw?QQe@B%|fwOdm9i~*yEPV?y{dTQg~ zuTap$RL%7_qG#{=X2?FeZeyZzoj!a5pjL6P8@4l+Afox zKi%+vCZYWOo|f_9Kn|`z?nE(`{!n%_=Srbn!Rq1)uw*GD?d-mTnS0=wXx_5|j^ce^ zkFrm6n$g~cMG0p`DgQ{UabM5=M+_!%OoR;EPrQ5_5RDw~r%A|Tgz0Iuw5R-%6Xt7# zf0A;QGc96|%HChlc4g|(zx(K{2dF@FbYoS1Z>e7Nu|rCv32~YMfT*Q5jR$jr=3D3f zuv&i>>ljib(rDjrxiP8n+2GlM)6~J5={K0B!qt|?!76ua?tsp0h8bBvs-l}!zBJ~f z7lblQmIg%(TmuYqwCiWbN~6#CFP;T89ljq5_GQ`tLtsvclY#qHTe`2tsHQ&| zT?%3N&fcN2VwJtVg#Kjl&w^$zWy@|zoW%%CF&mXEYCtk+KMTGQ+keVp!6+h}n9ko) z(;P+UW#q|V{4JniDp*ra?VCHeE1&DIR@siMCqKcG z52Mtd<;u74@I-7jzoP0vV|AJBmjOYSY0m(GB=$(_mY4zgnGsreQ|jG}+`|xd>+u9- zXM|ex3Trz$Kk<}3MC9?*`iZA_O$l8;+cv9{r^0=JFaH}U1CcSDDApS_*K-*!LDlV{ z3PV=gneSMVequWEJfmgPXs>!@HK23i>EsZ5p9IQeicsc6DfQ)vqgAr{!{EkStLAer z9WJ%9iY+rexHTbmwj{o$t?h=dz(R(-`MmcTzj}H<{dgRDH*|VUc5Paj5{1;jm7Qk> zok6*;WcXgTI_6vhe3;rZLeb5vW*2Qec?_t*aEO94f`)YG?7}poY~XftV^iXbD1J^R zx(5LNb(ri=f;daS6M&=^sidAJK#)X?(U6eI^p;)fWaoovJk7ejW?C#Ce+_UVFV5Hb z2)DWhkN|nR9YqwDPF#(lLw2tXbYrdoMNbB|%x$vWE(uc-ev)Nk?_h@3!VaKv89_9 zz|Y0TUkP$Sn`t6Snz^e^?e9{uG9z2=jhyR>F=z_%-{Pj}RCY@VC|X6Z40fnWP+@vr zt=b1HHD^`D4A|;RAy9hZC%UfU;=HW))9wj8r}0p-)GiUC!i`z?iVw+m}} zWg2AS3xDXuiq4`#L_d#(xCFMDSh^r?DaFL|Rs@R{_$F>)_Fm2S}EQo*IRC{v3ac)h`F*e(|__l>gk9| zJnXZ5_Q0lkJC5}%%2!)cTs7@KP#rYyuK_Ptqd>H(5?DG_VvH+?@vfQTY^-R!7vCU3 zBXs)UbK6OKML}xOF}*&zB<@(;#>~o4C1tDLN<1 znB!bMA>!#4yIwpTUndVYbHxeQg@)Scp*m|$J^6(YlJ!+GED)8OpVUrLu352T8Icu% z6kR)bQBze##2>R(lG<8X98pymPUvQ`Wp$JBPf%_MqmczOD_JQ7RfeNahP!^io~_XT ztlJkqwP?Udb-Srii2RbPCBWPmw8p1KwMfx-@@KdXKVG}3eRv=nj_ zwN=I3N>{6>m%)L?8^yLT$Kei#gKI!Z1^0tHjNdq2xZXES21EeJ9$Vfipy9{VqO7{Z zSoS?wKnx3R*;b8k+uG+it>UuLUQ#{RE&+c4aq3r>Qc&769|2&BOBfr(8Rc)*h$1`C zdamPHV&x&-e>SwS13i|!k+Q0tCbKul52zYgak>UPl<$p^fViTLZ=d|K z$_@c(tFJyu(^?L6E5=!Gf)&V^kMC1}ZO$4lO&~nYsL(`YE%^#8&KWI}Od9{$^@bn} zmUsJOk&aFAaUu-c-qal{cJX8)8*rh)8~4XxA?)S&t@Ls|wa9i#&$V0oD=T}pZGdaQ zxa;IPF#MK}L!zMd@06skOPGeUT8uNy2%QvPg1H80CvRl}sjFK3D%l8z^i_}DV?6!B z)9a7rRp+f~KX%Cs6(d*vFbD(e3ZmSC6zOOcx#e|At4KYIqz2A-QIYT$! zzDQHjujmy_cXYe`&9!FiyWrKBo*Kx$rqMAX%>Ow$m4_is^mYlas)~u1* z7qK2UGaBX~u*>Jcb84R}HyfkmuQoUJ&VVTG0}6x$ej+}*DiA-C0L!+>xPJ#7(CU2_ zE!J(0`XhS#i9Wz;{`bh31AbhZl&t^yE`0VIFs4&&B9uMA3B<6+ ztNV3`x~Y)}a&9J-`*pD^zn?$xO>x0S8Y8`;N|?<=yJXQaCb>^ua$$b{(bN)9ghXdu zJ=0030ALmgQTpi{7K0N?UI!UPwHykatqEfha<$QW+BYF!8aiHTkQk}5=$)?t#wG1N8ZIk z{*a%h*^Gva1?C?Z^nxa_oT&GJ!2vGeDUZ*B-2?011i zgGmG9bS5(un3q|P+S4W|!V`?b^)y|)B5#}6MX_=UyA;qQpK`zLRKPHmkKwt6g@`-b zlY)Mk*MRP)-@jTs{^73-e^z~LZk?X?LhV<&6GeCh%Tm$J|O)pZnoCvSJ@vVsyRGFEH}4E zUgz-0 zfAx_6X4yB{;U$O}8n{1Fsa_m95i}i?^%g9zZHL^;NP^?z|FFgG5Piw*EkJy5d8SMT zno=vR(dju&{TQSPnVe`VgkFuQRlS89``KN-D`(6e^0bfT!BB~-IL$cg{4f}7h6{P| zoc0<}n<NXHg!vCK7lz|HEQJ<&_=+ zd;bG6|2~6)l6&i-d8s7@PP3y2dAIiK!eS5z1Huk~QCr+9Cq;n~E9QD)s)&AW$!3GdQ z-}Bb{yLWcZFwY(a{YbG7zIyv4?ao$W;YSTVLROvcJg3A#Y=EdAhj84i(w;E0i<2Sx zdjhMCxub=-1FiaZz6g;G8o0!n$^^^>%)X;~f7*9%OiG`tZ(-1#A_cw_)!EqL&=Dz^ z=vlpF`3DFVd{&uBVxeB%uDzy4hZ{LFy9Us9QpiXJC{74;%s_;ErMf-9H-yvN6L|w~ z3_1-H_%)@(YpeMz);YUi#hlS*XGN21=)pK}6Nn(-?jQOPC9QhD`q^5ZSFA$QHCgAg zq0bep^qi8O-8%WaG+HT_(8Pv-PT83}~d+71nW9+QM*nzM}s+ z8($Ud11&f*^eL`X2d>jZOWw2kBQc&^>Eb0h2v6)Oci+1+baf5LrXCgk_$2L1eSDta zYwPNCHc5jWZifk@UKukwQPe%3SF9EW>SQVE9JHFc=Gp&y0z3B~6WBk}XVFP}NdH8L z#HIA3ajq=nqqZ4kt%(+`5N?Bel?$6X&m}y?Z^u2MYbB66wX+#NU_q;dInyk_2Dn*% zt4N8=pqwK8EAZU!rLr;Q9kxgBq$&g59!4SzCVrX;myd9zUOMk2hCaY8p?sI*9P;X2 z&rw5)$*;4Fpx;1l>1S{hO?>BF+;?tqh%;@Q3Ys63*pPrhN17x{SPe{&}&Dm(;f1L|XGwQpGb zCB3*3lHIdv(AFNv-;%e?Fq$=NzAhU00&o>zeJb00Tf1z{SrgiVKHq=JtBr6`5;rfV~{4HhYq%r&Ms9BG=1-*4=mzm#V=^$#&;QXkTrHnuDPPgboR2 zT;y1A50yYuALJ>@aKq_)>Lo6vK4cs1a&VoV+IX}77Qhxw zN!viQ<21g`VnZb5swf#}@y_`z`?!}_H7vVCiofQ&Mx^YS2?SrM*5^ALKqa33>9d4I z`c_gpsi;notmMC*pgAjvQA#$V_+3C_gNDZAxUtk2P({FMKYe#0#=fW3d)Zo%N5|vk z0pHR?t+xawEH~m*7;k2vRgw=X(Y^Y06QTTA9gJ|L3pdT_NToT0vCYGklV|mDIL)}( zt!sd8Bvne^7=NgXZfP1oH}!$(APfgrBbFV9Yn+*($Gf?ytOs4cxL-J=TIk6^Y8wYk z%}uSnHydLrg)WIv?#J6_4VdK1N03*TXIW|_SOzq>Cyco<=hlmK{jYiJ`V(S#tR{!0 z!7&@mmdV5XR$i1kC)97<5)KY}jg2j@0lgfjUt~gmKrAp;h~$J$;&zl!oXNYV2WgZa zk{09j%5{Q++g!;c$H8|jc)f<}lM6T1oVjCEZ)4(7HM5rkMUqIdyIV(Ev&0%N@wtJ1 z?tybE3&z+l`A1?ff1Jo7LTs}J_l@jFEyt+mxp6aTT4W7gK%{IxOj0^RqjC*km*%fu)R_?2TOZmsh!zB(1BdMhBkS5ck! z$Y}CN>^a}tEq$V*u=PGevbVTlI0sJbr{LA+b`S+VsftHZxdzf^ZMk#a+Wfspe#u)R zD)>R1Xi1On6ZYE)cPywe>ws&u$+qlL7E6eVj`n?9gz+5glQ#=Gto1GPWP!>v?@{S_ z*ar?@Lw|7bPPSWJs$qosvISK~0t;P_wOBCTo^Q(Po@VgXF`>DWUto4n z$!9n;%^(dWL}Cu&i&zfpwls*R{*mZis<~-vv1+T&`=mAUv^a7>igvh4p&GSgvs#zo zG-;|@arNOE;8LNg>e6}pD_Zcad?dtTZOl@irjJc|O6+@cyH3$J?I;9c)!9k6%u@}) z8PVz}ljoY==ZeWP9XRXLRN}x}D!(68LBbrI9Wh z+EOABcpy}JRopd=1*39$W}W4sToQUSgU=#*fgRa_YRd!j$?XOH6;(y0hZ*{vHoz~x zRPGd@#~duS!CY8bbT+Uvj#rP;S&y zT8GKT%V1a5Aeq#G!o|E$r=ioW_PzCUtifQUD*NC`SdT^x{Hid-LsU9MRr}oPyZQL# z>F;|x))TXpAsMjo-zuZphbYE1=%-KlMd$XIlSoD*8=qeu7x@V#?F)IG>SR_g=-M zWG9^UoL_?m`)~N)2kR|%}ULfxg)$HsJ@z2zSqEyyf zK@|lwYM8-GAf^~!kzu}#AwY?A*9V*r*aK}qhHqB-KhN*@(SQHhEw;H-DNN(Vdq3(H zGLX|~KGJ09Fw8kDnQeT)Nxa8Q|2|9z$MJy&2nW z!9aY^!PnGSWMe#5(K!L;oDXjs47(+PRX}pn1qdOb(Z9!3@v*1pr*2?{3q0yQUT?eD zos&w1vL;IkFlnzyIV5`Bgx7fyV0{#0E+y@pT{03CdBuVym@?SdvEuT(%F}U-6^arDlzsNU@#5wDj5Tix(C6A0012 zc=a>&ODyL)2=3gaD4xHz%4+M{`g%{5W7ZiKBDZbk5chr6a@ibCN0t6PrLj&|aL{+D zEwHv&&7&58mz~t^hoj{YWp6}(6xX<~uuWHqikVDG%l4ferVemvJ+m2oFmjKmg|Jfq z%^e-)8U`=JpNj`$oFIf>844fETWt#qKml21Xp+Os{j&?Iv-5nXuh6NQBQ9NWXXv97 z0ZD$ZL*+WcwmVuJo#)=!RVBGaq3{0%8@QkZ#v_^r|HcN1zyHPtxqo4UZry@(suHe1 z)8Pi9*h@8t)~u=!gl|gO2>GEHI$PwPsAd+YO0S}AfM3eH-W)TGM-IRJZY*s(l{u*F z1e3%Otn8|>zihW!QzIKiVQeo4xOm!UeaX#hE}dYRGGCj06=;0;qz!hxIiv{s(g^c> z-P$Y13lAJyf@|d#8%^s&vi|(mtE^Z3&_H$;gMJn?-RmDNBa(aOj#cc(Qul56xGOnx zx03O?YJWVZqrB3*#q)edMf%B9W1=Fp$m4LaYL8;`!YF|osYTRZz7zvUhyXV;!r-41 z#ZCMx9i0Lrss(PiXVOiIKywaP4zL+%x{&G$&1(Qf)wI7C8a-MeRbZ;qFo zed=|0*%HB$Xmo@3>4P1RNa$E;I}lkL3u1NvrCXw9;J!IrXF-gvpK)4;>}A%kG~TXs zeyJY6_m7f5%-mT$Y9Jk5kDq^_`jrNE&L8>6kqTci>sC^SNgsR02J&%I`8=eRRhX=f zgRV_V^bPl4YU}|p#5JI6HS!`W5o;vM#vP?BQl>J~TSOc+`(sk2kKg4UlhLd4;)w@4 zwwnJ0n5j_n;ErJ1KDd1;f~Vk_DGdgh z)IWuSnK}f5ngmwdZrFbsU|{X9s&IU`32qKmCV}zpFk-9~D!;#4aNt(S)JvgnQ$Bjm zQ6|9^wnzn%%;Mu%=B0;|%DvCw#Y$lTxBmrgRHGTwbocEado(B0UVRGX!9*h^dfKdx z*kT4_8Y^=;*v;vv>vFE-{G0L~fe^ZIHAUI|v^%xFwdt_`3Z;O|=Y+rgPeB0zULcrU z0A#^UtCFA+uK{C@1+Lj;u~g0(!PD-+lv+F}$hX59^B}oN1wgVGUdoZ{esLZNd!8Q) zKaZ?A-1nvQ;Pa85e{yzycfh6lxHK^}HHM#*N;0pgLuB1!Ka4t53?sCjS@6hGnRl<( zvTy%YCdzHx^9(A*@P()y`J^317!WKq7S5>aZ+px#`0AZjjImHC(L?Z%m^nrf^~ z%}9;;9yDSe=`1g*_7k6<{U}8(LhG_X%tl4^q)q|59T~(o(Qdm@v zRm`Z=7_pLl!jlPU?JcPW5~mwl>-h#(CCb6UYoJJZ6bAgVlW(rB*hOx;3ZDB*vP&}M zv1Yn*U&wd+)bShcPxLhfv!x5k7^f7E-m1#9;DuGuJ*%{}srLESlcKeonwMYBY55b# zzB=)kmCo_4(U7}d185)=MHn(&r(m0#J&VA|oFm5O*cZkj-)-G%YP?_l8;A2Rd=AkT zH#~F!qW>AAfiRh+PL6Nab9M|ZE6Mar9jnl%yt$*e@P}S_ZIJKAg+Gys2!2I{zXi@5 zU@6NWx~S7eXjUibj7R$eu|k{UF%MD$*T?R;x$gf(UkpUGsiW)!E%8x9ZmQdQkl zC+46H;BEI_i|#t2hLBD8c2M@r$(tGO!OzN&tl7T`9lp(YvTeCcy(l=InSVznN@gmQ zebgSfo==6Z853# z$fbbtnHo7Tye#!I7wt?Fkmli`zhu)C*fC<9|5&HV{QdSf+23OULi-a4AYFhNg6Vyp zH1txirFv;)FFUbiquaaEMlT4(u++Ux9`OCo{rk1SRn!mvLA^`!f7*42l7KTHwo36- z6qN<0w}+(}4vJIe_P(kuv0b5W9^v<@2ZDV@qL`tEGAX0lcW&trxXd=F;qg&40(!uT zX!FqMt-0{5_b6^@n~;F{hIppEF$RgQjd<`V6}H6tNDEUX1QNw!nkPelUIXZI&O9eS z{k_M64uY;3Rn!XY~3d zKXSyyba5i?F~eg-uT))fft)TxGa;9A{j1EXYU=B&EJK$PxN*z=_D-p3yAN)PpQJ?b z)pf7;dLQSb2(32g%OhrV9sP9$DQHK0pN0{_gW-Sd?>9xE-{mg;DLZqKIX6sRdo@Bh$FWZ&d5bLjc_sUOlDM{7hg+qo^Qpv^Uf6(kQ z;iV^d;S-F$UBcCC?eg32RmK3nV-+inj`xyrBHuNHlb(OD2YWLNf$wvCD0u<9XROj1 z2S5Seg>hl!(Tc7RfvSf%4)o{jH@kTpojxp?qxYq>-!^Z}Bum<8vNnt}R3PkT&L5Xyle>kXq+rYONGqTcB<=M-CMy92yih6nE1 zYV95?j40(<#M%#4cHTspy~S~1f>wJ%i6*OMY{aMOs7n)s!Nh?I_@GI`s+^~woW1kw ze-Y1r2d%YEA*?oPya!0=2BK}ZJ``>I)yo(O8Ty<$uT4ceppfQT>KMn*(Nb!#liq7Txm5W=h=1BI|+wNBs@6#n(Jjr7bz5(AMX5n*7O>8Afz! zL9Q2(N!9i@OF!##jy3gA@Ma6%OiGZdsw#;heocN~_GG(DEy|W}qFNS+NAb+XiCFh_ zJ`Q+^+saE*(+N`MY-{R?!ba`qqX7CJC;H)A&zqC*-p*be}*o@Ys70`s2b#S-WHpN;RqPm>26&UgugpNFd(+J^bqT9f0ac!S52z zJ1TdGwtEKqRvW)2(Eh~esju#m4AiPBoSRquPzt|&T3ay4!}jN7?H+Cc%nZ@C8;tQ? z%ok|O@lY1eXIay4Q(TYWR@wU{`F+gW&No@!KkOJwjOz{Wl zNZ^XP_fGnnBX$FFWsVC&Qor;su0e-6qzy&Z{ejLt@uJdQd;G?HRF!;%cZaok z-bRRIqyJ)Y2_bh;)14BS#7ZldiQOcKs$U?DXu=Kl4HpFD%L|pH09yH zAHTEzG%5}nrb@jEjckuBTScqvr!upaiF5@w+4i^H|r6rkMOcO^e z9y1-)y&~4DD_X$Anwm4MN{T;g;e;*pdUu6peg54Z!T^>73e<@)IxI>QYlom*^pNQ1 zqG`d+O-g_%tQ^zsF9<@EzUdyEV=J*C zmz8@y?+MfXIFnkr5-d}XS`~iOaj^f+tB$UJ7dQOF=6fS82a8XozNR@O2rvTHwh>r#;&@Hrx$< z`+#G$AC?$YmVAoe%IRFY(1}_O$U6$@tgNxD&2>b4lZ z{E8Blg-{FcB!?(YhB9I08<^ST5(yW(Y5#m!KhovPv(;sn;Dd_x)osjaBY@-qpss8Z zXe5N;GyKTiAo)aTm8S3ln^97}m4_LZw1f zCU6Ypq7ZK+wX|ji85$nA`f{4~BC4+Go9UTgv-0}4t88V4Fx1H!%R7j0H4WyY#%Fc$ zg29NnIm+#281^PommOXE`rmy^0h&AM8bFEPGHT1x_ze}Z6a|9a9=Y82T{S6Z54sm+37KXot1vmN1 zWq;GWZD(4;>nA(8ps4&ezbo}w^qPn@T8& ztL%c~W4E5C_A@@VS)NZ}GEwKx127UGVU3`~s&>gW3T4Tg8DONCeSZR6JfmnS@#pH2 z^}u4<+H>UW9gPv6c_lmTF0m%y`v8_M?#A(bG(ttK$Ch>4qf^LbmU*I&cc#ok%{1~o z^$7Ls5TYesflm7sUz$u$$7qRDYjXI7Ts2z0p8+@3DHoyVH(fne79}dqSh;f{T@U;8 zD^RamGehVDhm4o#y%aY28#(e&5F*~UivKm*GwkQ9O{JL09g6)^$l^%1X_#c z9ga$IpE>c1+gyXTU5RVmR||<#%7hrPndD{Sh~w|-bdPHJAm#4c64Bg*p(>%{ogD8V zQgbgMkHlB>maWuhAR~HAoh^RZo4?~f*k|nXNGUA1p~ji-X=nB?UmU${p2EIHk7H%F zI@raNsf;Z!QgD;I#sjuOGx++cUiowK*HW2rAK+6@noj!xkgia1+)oKWQ#3+scR4@H zr*+^%^P7v0#%4KSNc`)0Jm#}yK&t^Ubp-)!z1$pOt{)p0S4mxxIB(uQ9d)*O>w1i6jzt;A}h33X+gGYC>N$VZ_Jk`&bK zdRXIe5q_gue@D)}kxmK-GwkP)1EwDxIAwx~uGXSn9#VBsbdWfqmewcZWj7C!7Ux1f zaD1Qk><+2RRTaYHh8zA(aW7*njNtQa;sX5$0`wIqYVbw#>j<)*uF9#h8?0xlp29bPeA^ z9v*C@9T`tM0f6OhEYzJ_hcCT4Ehv<);^DdfCAD%x>BV}S3pqd zBGP+_^d=zE0t6x;y$J{i2$9};u*QeibG+$*C)&vI3$#A&0HSrxnZjg&$I;5aRKRx`_`|(ZCQ_)(^+`KYgOMN z*e#R%1YBd6=aMT4rWoHj2#=l!9?eu)$Fnm{>{)lku)t!0$sY_h9u#lUcnu&EZ{j)q`Ujr4w zyAJcT9FP={YKu1&o5%y<6^JZE*|pzaDUs%CW^#}{wOUB zLqXCnD^(qJAr|CO>U>gLF>_*6SMhU%g}i)_lcu7;`|bzVt`6#}*}n+t`3A>mw9u4c zR?-s}DrM$fvwG&Hnw#o1URLZglvd&SNt{z#?rPKvheUM4@NV@v{THvfl~?(eU4Uf#d< zxO~%6A72H$UZ@-h!R}8Q;imTridaI>t$gjs2o-dGGO$~#L4_U93gOHt6U+dzE(_0} zTTSe1}+kCH}{Cgb21)s-fgM}FBC5ZR{~gCOX% z=ZI_x&d1RjPP9>@ql#i*)cx@_Td1h2utA2?-5@FxGteE^df1P&L>N_863uIWeu%Zh*#^^5sy47U4mB<|O zuh!^!E^BV)j;b$%(j{>Uroy}3P~kiFR{D~?_wEK9SBEJ!tn8kitFS#24Y?AVfa&t4 z*H{e}FLKwJpJvS2$FXg5kT`RZkPx>8_Oo+@;SF$0)qT~3Va}kmWTn?0Bh2$aSn|Ae zUcNQRY(|0T-aea6M?8TV4Ou9Cerf@$*?6e)c48Ajzc3gz3LaDmVnpA`i{iAqWz&0C zn7Z60myBr1zgOta=4xp~X@&jpp)f#nyfxI2Cg<9j*i z{3!P{Bi;8AJXicYZ)*oS`*ukJ2u=~*iVaoq*nF*a0CKLqQ)3FP?$x5BUX)D|>2#J> z$v#ePurA1P4i(oXBHd%_QKyI1Gr7eF;&p9~tl$@%0dp8ig zhnr-nH)>CENfwa7H!tWrCVljAV{7uBE)eQt=&g}QeM!y?6V?&wMO&PLP=My!*TB-J zX-e_Y>}q`+s6qTAK!43m4UO#6j#}VNs`^bH9cb(MhG=F_$W=fn=Guapj1j>x5&O}! zj4-uMSuPLXWV0jQ5y-`Mz)63BJFSM{-xU{{`OdXum4b$iSz1%3scPA8nvfbSL)0IW z?W5#PAKrG|UR8l=$IIWuR^zh(pJEpqc*BClKxRT@37!(! zTWY8osoG0k5x}0{9HYIL%)2183%odZSk*vw>F{-bT`R5uo`%jC`47>4go1U~mET6& z5S{v$yr(l3km|$mm=%h>~611PJd& zP-nRF+R(5-(}BVqBlUc%{qJ%=3IEeEtD1wOVQ+6jYCjP>J8=;@>p{ z7-Mi87j%MnPHbeX$Hh%dbqqWEq>q~b?&us9nAI1DT2e)^Gnv+uY%fx&cbCO+U(vs{ zmqgmb8H4ARX*wn-!>(uxkQ~&F8Z^V2*yUPRuVSm48zeHu3@6lsGIMSpBqtYDnZ=`Y z*$V7PRusrD1SYO1p$wFy^NR|(zK0rqr7jW#d{a_n5i4GP(hpaJ-e>1;s4T?3H@sfm z4}T9PxzXsT*T+rCWaVD?Y(e81Pd0q^8{_rnx~~Ku-%vi*Q~9o5%_5!?h=&957zD$w zmf|o4o~YUWE6R3Rt14@Vh+s;seN#ucILf9C>HUdUJ8c6qB$lG5dqnZKMUaWk_#1?7 zv=%pu3A-9ykOHFx^F*a}C(dp9^WUPyV%j+`7%dDjjJFbnQMojv(yE29%k66uJBp2v zUZ>+M1O;#%Wr!QdwdW7rRHT^K2qLGcreK}z*nl z<+}nJHo%za7}~~`E5tC&wcA+NWNK$(9slfI3Dc6{6V_ysfVJTNZ2Ty^Ddqisz1nug zn}fUKJK)F+&;W(XW6kG^dfzaL@#;4WfsoIs_(RwMl0Y_*QaC#w&(ib-DU^GBN=4yK-v+U|O8xTLt0TJJHoWI%) zH1O6Tq2GkiciOQOW53h@66GsA?`1&GuL3Q|=@4nqG88VLiPd2ClE*vk69

Fbwd9 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 literal 0 HcmV?d00001 diff --git a/AVL Tree/Images/RotationStep1.jpg b/AVL Tree/Images/RotationStep1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..dbfcc04d60e0e87a37ae6d730d4141103e91bcab GIT binary patch literal 18406 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 literal 0 HcmV?d00001 diff --git a/AVL Tree/Images/RotationStep2.jpg b/AVL Tree/Images/RotationStep2.jpg new file mode 100644 index 0000000000000000000000000000000000000000..df194a73889e33fca6d9d4ccfbb50eb97022864e GIT binary patch literal 18836 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 literal 0 HcmV?d00001 diff --git a/AVL Tree/Images/RotationStep3.jpg b/AVL Tree/Images/RotationStep3.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ae67f4d746250063a37830f3ffafcbc1e00378a9 GIT binary patch literal 18108 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 literal 0 HcmV?d00001 From 5cc12cd45f6a386788d9cb98065953c448130e19 Mon Sep 17 00:00:00 2001 From: Anton Domashnev Date: Wed, 21 Dec 2016 23:08:24 +0100 Subject: [PATCH 0698/1679] Update images; --- AVL Tree/Images/RotationStep0.jpg | Bin 22802 -> 9159 bytes AVL Tree/Images/RotationStep1.jpg | Bin 18406 -> 8046 bytes AVL Tree/Images/RotationStep2.jpg | Bin 18836 -> 8277 bytes AVL Tree/Images/RotationStep3.jpg | Bin 18108 -> 7430 bytes 4 files changed, 0 insertions(+), 0 deletions(-) diff --git a/AVL Tree/Images/RotationStep0.jpg b/AVL Tree/Images/RotationStep0.jpg index 156b18062e84cd5bd05a5557c80404ee6aa9636f..99b69d3e0f58e0faf7d98ecd0a0daf30e2e48640 100644 GIT binary patch delta 8428 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 WpZCcByi4ZzU1G{1urQsc&HWdo$nTl} literal 22802 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 diff --git a/AVL Tree/Images/RotationStep1.jpg b/AVL Tree/Images/RotationStep1.jpg index dbfcc04d60e0e87a37ae6d730d4141103e91bcab..670fa0832039799d8b90d8e530a1de409bef4871 100644 GIT binary patch delta 7288 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 j3+vDQGPS26(E>v?f53Z6M~H?`*?Jbu literal 18406 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 diff --git a/AVL Tree/Images/RotationStep2.jpg b/AVL Tree/Images/RotationStep2.jpg index df194a73889e33fca6d9d4ccfbb50eb97022864e..9d1ab5b8e6e65d0b7fac22c72226242d6e7e2a29 100644 GIT binary patch delta 7538 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 literal 18836 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 diff --git a/AVL Tree/Images/RotationStep3.jpg b/AVL Tree/Images/RotationStep3.jpg index ae67f4d746250063a37830f3ffafcbc1e00378a9..50cedf0c39651abfa38991c499ba5ba136e09c8b 100644 GIT binary patch delta 6740 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 From 2f8f348816ee0b9ef8bf52a23cc60883a7486e79 Mon Sep 17 00:00:00 2001 From: Anton Domashnev Date: Wed, 21 Dec 2016 23:13:05 +0100 Subject: [PATCH 0699/1679] Update readme; --- AVL Tree/README.markdown | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/AVL Tree/README.markdown b/AVL Tree/README.markdown index bcbbbabbc..9deea5649 100644 --- a/AVL Tree/README.markdown +++ b/AVL Tree/README.markdown @@ -45,20 +45,21 @@ If after an insertion or deletion the balance factor becomes greater than 1, the ## Rotations Each tree node keeps track of its current balance factor in a variable. After inserting a new node, we need to update the balance factor of its parent node. If that balance factor becomes greater than 1, we "rotate" part of that tree to restore the balance. -Example of balancing the unbalanced tree using *Right* (clockwise direction) rotation : -![Rotation](Images/Rotation.jpg) +Example of balancing the unbalanced tree using *Right* (clockwise direction) rotation: +![Rotation0](Images/RotationStep0.jpg) -Let's dig into rotation algorithm in detail using the terminology: +For the rotation we're using the terminology: * *Root* - the parent not of the subtrees that will be rotated; * *Pivot* - the node that will become parent (basically will be on the *Root*'s position) after rotation; * *RotationSubtree* - subtree of the *Pivot* upon the side of rotation * *OppositeSubtree* - subtree of the *Pivot* opposite the side of rotation +![Rotation1](Images/RotationStep1.jpg) ![Rotation2](Images/RotationStep2.jpg) ![Rotation3](Images/RotationStep3.jpg) + The steps of rotation on the example image could be described by following: -* Select the *Pivot* as `D` and hence the *Root* as `F`; -* Assign the *RotationSubtree* as a new *OppositeSubtree* for the *Root*; -* Assign the *Root* as a new *RotationSubtree* for the *Pivot*; -* Check the final result +1. Assign the *RotationSubtree* as a new *OppositeSubtree* for the *Root*; +2. Assign the *Root* as a new *RotationSubtree* for the *Pivot*; +3. Check the final result In pseudocode the algorithm above could be written as follows: ``` From 341c504c3508ef0ffd3dd111c06e4eb128106d46 Mon Sep 17 00:00:00 2001 From: Anton Domashnev Date: Wed, 21 Dec 2016 23:14:46 +0100 Subject: [PATCH 0700/1679] Update readme; --- AVL Tree/README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AVL Tree/README.markdown b/AVL Tree/README.markdown index 9deea5649..25073f260 100644 --- a/AVL Tree/README.markdown +++ b/AVL Tree/README.markdown @@ -45,7 +45,7 @@ If after an insertion or deletion the balance factor becomes greater than 1, the ## Rotations Each tree node keeps track of its current balance factor in a variable. After inserting a new node, we need to update the balance factor of its parent node. If that balance factor becomes greater than 1, we "rotate" part of that tree to restore the balance. -Example of balancing the unbalanced tree using *Right* (clockwise direction) rotation: +Example of balancing the unbalanced tree using *Right* (clockwise direction) rotation: ![Rotation0](Images/RotationStep0.jpg) For the rotation we're using the terminology: From 047de8fdfe7221aaca2d0ad3a39be58ed5e11f25 Mon Sep 17 00:00:00 2001 From: Anton Domashnev Date: Wed, 21 Dec 2016 23:20:47 +0100 Subject: [PATCH 0701/1679] Update readme; --- AVL Tree/Images/RotationStep0.jpg | Bin 9159 -> 22246 bytes AVL Tree/Images/RotationStep1.jpg | Bin 8046 -> 18235 bytes AVL Tree/Images/RotationStep2.jpg | Bin 8277 -> 18777 bytes AVL Tree/Images/RotationStep3.jpg | Bin 7430 -> 18265 bytes AVL Tree/README.markdown | 2 +- 5 files changed, 1 insertion(+), 1 deletion(-) diff --git a/AVL Tree/Images/RotationStep0.jpg b/AVL Tree/Images/RotationStep0.jpg index 99b69d3e0f58e0faf7d98ecd0a0daf30e2e48640..f61f8804ad0b12f66f87c45105315436f5ed30a9 100644 GIT binary patch literal 22246 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 CWqJ4j delta 8410 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 W6SwN}G7+K#nPb82RbGfv3o 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 UUi+Wt$^Sf4K8UF|)9;v2$>8 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 diff --git a/AVL Tree/Images/RotationStep2.jpg b/AVL Tree/Images/RotationStep2.jpg index 9d1ab5b8e6e65d0b7fac22c72226242d6e7e2a29..64c0af8622988f3bfbc4967344012eaba5379a12 100644 GIT binary patch literal 18777 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 X%fCkL#lDgaX&ejdN;jaq{QsK(NVo;U delta 7547 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 ZrTz0g{|0}NexITek-JSBdjT@0{|kD3fj|HN diff --git a/AVL Tree/README.markdown b/AVL Tree/README.markdown index 25073f260..9254ffedf 100644 --- a/AVL Tree/README.markdown +++ b/AVL Tree/README.markdown @@ -56,7 +56,7 @@ For the rotation we're using the terminology: ![Rotation1](Images/RotationStep1.jpg) ![Rotation2](Images/RotationStep2.jpg) ![Rotation3](Images/RotationStep3.jpg) -The steps of rotation on the example image could be described by following: +The steps of rotation on the example image could be described by following: 1. Assign the *RotationSubtree* as a new *OppositeSubtree* for the *Root*; 2. Assign the *Root* as a new *RotationSubtree* for the *Pivot*; 3. Check the final result From 3f30747694400904d889588aec00133dcfef45b0 Mon Sep 17 00:00:00 2001 From: Anton Domashnev Date: Wed, 21 Dec 2016 23:25:58 +0100 Subject: [PATCH 0702/1679] Update readme; --- AVL Tree/Images/RotationStep1.jpg | Bin 18235 -> 13059 bytes AVL Tree/Images/RotationStep2.jpg | Bin 18777 -> 13357 bytes AVL Tree/Images/RotationStep3.jpg | Bin 18265 -> 12998 bytes 3 files changed, 0 insertions(+), 0 deletions(-) diff --git a/AVL Tree/Images/RotationStep1.jpg b/AVL Tree/Images/RotationStep1.jpg index 70e314df7cbe8336ae8e8d59533eca8639752f7e..953d35929abff2d5c63ad168710748dffbd4079c 100644 GIT binary patch delta 12153 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 literal 18235 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 G7XA;SX(ZDC literal 18777 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 X%fCkL#lDgaX&ejdN;jaq{QsK(NVo;U diff --git a/AVL Tree/Images/RotationStep3.jpg b/AVL Tree/Images/RotationStep3.jpg index b2045111352b8ba18af53a3841e6368217beae04..921c0c4bac40c5ce1c0367fa2206b3eb3e0e27b1 100644 GIT binary patch delta 12042 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 Date: Wed, 21 Dec 2016 23:27:41 +0100 Subject: [PATCH 0703/1679] Update README.markdown --- AVL Tree/README.markdown | 1 + 1 file changed, 1 insertion(+) diff --git a/AVL Tree/README.markdown b/AVL Tree/README.markdown index 9254ffedf..eaa4aa3c3 100644 --- a/AVL Tree/README.markdown +++ b/AVL Tree/README.markdown @@ -57,6 +57,7 @@ For the rotation we're using the terminology: ![Rotation1](Images/RotationStep1.jpg) ![Rotation2](Images/RotationStep2.jpg) ![Rotation3](Images/RotationStep3.jpg) The steps of rotation on the example image could be described by following: + 1. Assign the *RotationSubtree* as a new *OppositeSubtree* for the *Root*; 2. Assign the *Root* as a new *RotationSubtree* for the *Pivot*; 3. Check the final result From 39ac2ec3c36cf0cdf239d2b9b279258bd0f96dbb Mon Sep 17 00:00:00 2001 From: Anton Date: Wed, 21 Dec 2016 23:30:49 +0100 Subject: [PATCH 0704/1679] Update README.markdown --- AVL Tree/README.markdown | 1 + 1 file changed, 1 insertion(+) diff --git a/AVL Tree/README.markdown b/AVL Tree/README.markdown index eaa4aa3c3..8358fde9c 100644 --- a/AVL Tree/README.markdown +++ b/AVL Tree/README.markdown @@ -62,6 +62,7 @@ The steps of rotation on the example image could be described by following: 2. Assign the *Root* as a new *RotationSubtree* for the *Pivot*; 3. Check the final result + In pseudocode the algorithm above could be written as follows: ``` Root.OS = Pivot.RS From 9ecd211c61cfd4baab2665b10dc7c79547f5ec4b Mon Sep 17 00:00:00 2001 From: Anton Date: Wed, 21 Dec 2016 23:31:44 +0100 Subject: [PATCH 0705/1679] Update README.markdown --- AVL Tree/README.markdown | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/AVL Tree/README.markdown b/AVL Tree/README.markdown index 8358fde9c..86b631ae8 100644 --- a/AVL Tree/README.markdown +++ b/AVL Tree/README.markdown @@ -45,7 +45,8 @@ If after an insertion or deletion the balance factor becomes greater than 1, the ## Rotations Each tree node keeps track of its current balance factor in a variable. After inserting a new node, we need to update the balance factor of its parent node. If that balance factor becomes greater than 1, we "rotate" part of that tree to restore the balance. -Example of balancing the unbalanced tree using *Right* (clockwise direction) rotation: +Example of balancing the unbalanced tree using *Right* (clockwise direction) rotation: + ![Rotation0](Images/RotationStep0.jpg) For the rotation we're using the terminology: From bd645f33bc3640586c992e6b2c54728b4e50bccb Mon Sep 17 00:00:00 2001 From: Anton Date: Wed, 21 Dec 2016 23:33:22 +0100 Subject: [PATCH 0706/1679] Update README.markdown --- AVL Tree/README.markdown | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/AVL Tree/README.markdown b/AVL Tree/README.markdown index 86b631ae8..355204587 100644 --- a/AVL Tree/README.markdown +++ b/AVL Tree/README.markdown @@ -45,8 +45,6 @@ If after an insertion or deletion the balance factor becomes greater than 1, the ## Rotations Each tree node keeps track of its current balance factor in a variable. After inserting a new node, we need to update the balance factor of its parent node. If that balance factor becomes greater than 1, we "rotate" part of that tree to restore the balance. -Example of balancing the unbalanced tree using *Right* (clockwise direction) rotation: - ![Rotation0](Images/RotationStep0.jpg) For the rotation we're using the terminology: @@ -55,9 +53,11 @@ For the rotation we're using the terminology: * *RotationSubtree* - subtree of the *Pivot* upon the side of rotation * *OppositeSubtree* - subtree of the *Pivot* opposite the side of rotation +Let take an example of balancing the unbalanced tree using *Right* (clockwise direction) rotation: + ![Rotation1](Images/RotationStep1.jpg) ![Rotation2](Images/RotationStep2.jpg) ![Rotation3](Images/RotationStep3.jpg) -The steps of rotation on the example image could be described by following: +The steps of rotation could be described by following: 1. Assign the *RotationSubtree* as a new *OppositeSubtree* for the *Root*; 2. Assign the *Root* as a new *RotationSubtree* for the *Pivot*; From b64df56ea624b77b126cbc64d42ab7d687f05e1e Mon Sep 17 00:00:00 2001 From: BenEmdon Date: Thu, 22 Dec 2016 00:35:37 -0500 Subject: [PATCH 0707/1679] Fixed comment spacing in playground --- .../Contents.swift | 72 +++++++++---------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/Rootish Array Stack/RootishArrayStack.playground/Contents.swift b/Rootish Array Stack/RootishArrayStack.playground/Contents.swift index 401c773d6..68ec0a53e 100644 --- a/Rootish Array Stack/RootishArrayStack.playground/Contents.swift +++ b/Rootish Array Stack/RootishArrayStack.playground/Contents.swift @@ -144,22 +144,22 @@ extension RootishArrayStack: CustomStringConvertible { } var list = RootishArrayStack() -list.isEmpty // true -list.first // nil -list.last // nil -list.count // 0 -list.capacity // 0 +list.isEmpty // true +list.first // nil +list.last // nil +list.count // 0 +list.capacity // 0 list.memoryDescription // { // } list.append(element: "Hello") -list.isEmpty // false -list.first // "Hello" -list.last // "hello" -list.count // 1 -list.capacity // 1 +list.isEmpty // false +list.first // "Hello" +list.last // "hello" +list.count // 1 +list.capacity // 1 list.memoryDescription // { @@ -167,15 +167,15 @@ list.memoryDescription // } list.append(element: "World") -list.isEmpty // false -list.first // "Hello" -list.last // "World" -list.count // 2 -list.capacity // 3 +list.isEmpty // false +list.first // "Hello" +list.last // "World" +list.count // 2 +list.capacity // 3 -list[0] // "Hello" -list[1] // "World" -//list[2] // crash! +list[0] // "Hello" +list[1] // "World" +//list[2] // crash! list.memoryDescription @@ -186,15 +186,15 @@ list.memoryDescription list.insert(element: "Swift", atIndex: 1) -list.isEmpty // false -list.first // "Hello" -list.last // "World" -list.count // 3 -list.capacity // 6 +list.isEmpty // false +list.first // "Hello" +list.last // "World" +list.count // 3 +list.capacity // 6 -list[0] // "Hello" -list[1] // "Swift" -list[2] // "World" +list[0] // "Hello" +list[1] // "Swift" +list[2] // "World" list.memoryDescription // { @@ -203,17 +203,17 @@ list.memoryDescription // [nil, nil, nil] // } -list.remove(atIndex: 2) // "World" -list.isEmpty // false -list.first // "Hello" -list.last // "Swift" -list.count // 2 -list.capacity // 3 +list.remove(atIndex: 2) // "World" +list.isEmpty // false +list.first // "Hello" +list.last // "Swift" +list.count // 2 +list.capacity // 3 -list[0] // "Hello" -list[1] // "Swift" -//list[2] // crash! +list[0] // "Hello" +list[1] // "Swift" +//list[2] // crash! list[0] = list[1] list[1] = "is awesome" -list // ["Swift", "is awesome"] +list // ["Swift", "is awesome"] From 3dd067453818046186792746479bdd4986c3ef7b Mon Sep 17 00:00:00 2001 From: Joshua Alvarado Date: Thu, 22 Dec 2016 11:13:39 -0700 Subject: [PATCH 0708/1679] Update palindrome swift file contents --- Palindromes/Palindromes.swift | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/Palindromes/Palindromes.swift b/Palindromes/Palindromes.swift index 889ff357e..2760137ca 100644 --- a/Palindromes/Palindromes.swift +++ b/Palindromes/Palindromes.swift @@ -1,17 +1,26 @@ -import Cocoa +import Foundation -public func palindromeCheck(text: String?) -> Bool { - if let text = text { - let mutableText = text.trimmingCharacters(in: NSCharacterSet.whitespaces).lowercased() - let length: Int = mutableText.characters.count +func isPalindrome(_ str: String) -> Bool { + let strippedString = str.replacingOccurrences(of: "\\W", with: "", options: .regularExpression, range: nil) + let length = strippedString.characters.count - if length == 1 || length == 0 { - return true - } else if mutableText[mutableText.startIndex] == mutableText[mutableText.index(mutableText.endIndex, offsetBy: -1)] { - let range = Range(mutableText.index(mutableText.startIndex, offsetBy: 1).. 1 { + return palindrome(strippedString.lowercased(), left: 0, right: length - 1) } - } - - return false + return false +} + +private func palindrome(_ str: String, left: Int, right: Int) -> Bool { + if left >= right { + return true + } + + let lhs = str[str.index(str.startIndex, offsetBy: left)] + let rhs = str[str.index(str.startIndex, offsetBy: right)] + + if lhs != rhs { + return false + } + + return palindrome(str, left: left + 1, right: right - 1) } From fe93184c3899f0ee6aebc23c453ce14fbddf4db8 Mon Sep 17 00:00:00 2001 From: Joshua Alvarado Date: Thu, 22 Dec 2016 11:13:57 -0700 Subject: [PATCH 0709/1679] Update palindrome playground --- .../Palindromes.playground/Contents.swift | 81 ++++++++++++------- 1 file changed, 54 insertions(+), 27 deletions(-) diff --git a/Palindromes/Palindromes.playground/Contents.swift b/Palindromes/Palindromes.playground/Contents.swift index bb666ee9a..e8562a367 100644 --- a/Palindromes/Palindromes.playground/Contents.swift +++ b/Palindromes/Palindromes.playground/Contents.swift @@ -1,34 +1,61 @@ -import Cocoa +//: Playground - noun: a place where people can play -public func palindromeCheck(text: String?) -> Bool { - if let text = text { - let mutableText = text.trimmingCharacters(in: NSCharacterSet.whitespaces).lowercased() - let length: Int = mutableText.characters.count +import Foundation + +/** + Validate that a string is a plaindrome + - parameter str: The string to validate + - returns: `true` if string is plaindrome, `false` if string is not + */ +func isPalindrome(_ str: String) -> Bool { + let strippedString = str.replacingOccurrences(of: "\\W", with: "", options: .regularExpression, range: nil) + let length = strippedString.characters.count - if length == 1 || length == 0 { - return true - } else if mutableText[mutableText.startIndex] == mutableText[mutableText.index(mutableText.endIndex, offsetBy: -1)] { - let range = Range(mutableText.index(mutableText.startIndex, offsetBy: 1).. 1 { + return palindrome(strippedString.lowercased(), left: 0, right: length - 1) } - } - - return false + return false } -// Test to check that non-palindromes are handled correctly: -palindromeCheck(text: "owls") - -// Test to check that palindromes are accurately found (regardless of case and whitespace: -palindromeCheck(text: "lol") -palindromeCheck(text: "race car") -palindromeCheck(text: "Race fast Safe car") - -// Test to check that palindromes are found regardless of case: -palindromeCheck(text: "HelloLLEH") +/** + Compares a strings left side character against right side character following + - parameter str: The string to compare characters of + - parameter left: Index of left side to compare, must be less than or equal to right + - parameter right: Index of right side to compare, must be greater than or equal to left + - returns: `true` if left side and right side have all been compared and they all match, `false` if a left and right aren't equal + */ +private func palindrome(_ str: String, left: Int, right: Int) -> Bool { + if left >= right { + return true + } + + let lhs = str[str.index(str.startIndex, offsetBy: left)] + let rhs = str[str.index(str.startIndex, offsetBy: right)] + + if lhs != rhs { + return false + } + + return palindrome(str, left: left + 1, right: right - 1) +} -palindromeCheck(text: "moom") +//true +isPalindrome("A man, a plan, a canal, Panama!") +isPalindrome("abbcbba") +isPalindrome("racecar") +isPalindrome("Madam, I'm Adam") +isPalindrome("Madam in Eden, I'm Adam") +isPalindrome("Never odd or even") +isPalindrome("5885") +isPalindrome("5 8 8 5") +isPalindrome("58 85") +isPalindrome("৯৯") +isPalindrome("In girum imus nocte et consumimur igni") -// Test that nil and empty Strings return false: -palindromeCheck(text: "") -palindromeCheck(text: nil) +// false +isPalindrome("\\\\") +isPalindrome("desserts") +isPalindrome("😀😀") +isPalindrome("") +isPalindrome("a") +isPalindrome("power") From 33048487610b59b9c7e09cafb1f33573bda5e252 Mon Sep 17 00:00:00 2001 From: Joshua Alvarado Date: Thu, 22 Dec 2016 11:15:07 -0700 Subject: [PATCH 0710/1679] Update the read for palindromes --- Palindromes/README.markdown | 101 ++++++++++++++++++++++++------------ 1 file changed, 68 insertions(+), 33 deletions(-) diff --git a/Palindromes/README.markdown b/Palindromes/README.markdown index 12f868251..fe31cf297 100644 --- a/Palindromes/README.markdown +++ b/Palindromes/README.markdown @@ -1,64 +1,99 @@ # Palindromes -A palindrome is a word or phrase that is spelled the exact same when read forwards or backwards. -For this example puzzle, palindromes will not take case into account, meaning that uppercase and -lowercase text will be treated the same. In addition, spaces will not be considered, allowing -for multi-word phrases to constitute palindromes too. +A palindrome is a word or phrase that is spelled the exact same when reading it forwards or backward. Palindromes are allowed to be lowercase or uppercase, contain spaces, punctuation, and word dividers. Algorithms that check for palindromes are a common programming interview question. ## Example -The word "radar" is spelled the exact same both forwards and backwards, and as a result is a palindrome. -The phrase "race car" is another common palindrome that is spelled the same forwards and backwards. +The word racecar is a valid palindrome, as it is a word spelled the same when backgrounds and forwards. The examples below shows valid cases of the palindrome `racecar`. +`raceCar` +`r a c e c a r` +`r?a?c?e?c?a?r?` +`RACEcar` ## Algorithm -To check for palindromes, the first and last characters of a String must be compared for equality. -When the first and last characters are the same, they are removed from the String, resulting in a -substring starting with the second character and ending at the second to last character. +To check for palindromes, a strings character are compared starting from the beginning and end and moving inward moving to toward the middle of the string and keep the same distance apart in the comparison index. -In this implementation of a palindrome checker, recursion is used to check each substring of the -original String. +In this implementation of a palindrome algorithm, recursion is used to check each of the characters on the left-hand side and right-hand side moving inward. ## The code Here is a recursive implementation of this in Swift: ```swift -func palindromeCheck (text: String?) -> Bool { - if let text = text { - let mutableText = text.trimmingCharacters(in: NSCharacterSet.whitespaces()).lowercased() - let length: Int = mutableText.characters.count - - guard length >= 1 else { - return false - } - - if length == 1 { - return true - } else if mutableText[mutableText.startIndex] == mutableText[mutableText.index(mutableText.endIndex, offsetBy: -1)] { - let range = Range(mutableText.index(mutableText.startIndex, offsetBy: 1).. Bool { +let strippedString = str.replacingOccurrences(of: "\\W", with: "", options: .regularExpression, range: nil) +let length = strippedString.characters.count + +if length > 1 { +return palindrome(strippedString.lowercased(), left: 0, right: length - 1) +} +return false +} + +private func palindrome(_ str: String, left: Int, right: Int) -> Bool { +if left >= right { +return true +} + +let lhs = str[str.index(str.startIndex, offsetBy: left)] +let rhs = str[str.index(str.startIndex, offsetBy: right)] + +if lhs != rhs { +return false } + +return palindrome(str, left: left + 1, right: right - 1) +} +``` + +This algorithm has a two-step process. +1. The first step is to pass the string to validate as a palindrome into the `isPalindrome` method. This method first removes occurrences of non-word pattern matches `\W` [Regex reference](http://regexr.com). It is written with two \\ to escape the \ in the String literal. + +```swift +let strippedString = str.replacingOccurrences(of: "\\W", with: "", options: .regularExpression, range: nil) ``` +The length of the string is then checked to make sure that the string after being stripped of non-word characters is still in a valid length. It is then passed into the next step after being lowercased. -This code can be tested in a playground using the following: +2. The second step is to pass the string in a recursive method. This method takes a string, a left index, and a right index. The method checks the characters of the string using the indexes to compare each character on both sides. The method checks if the left is greater or equal to the right if so the entire string has been run through without returning false so the string is equal on both sides thus returning true. +```swift +if left >= right { +return true +} +``` +If the check doesn't pass it continues to get the characters at the specified indexes and compare each. If they are not the same the method returns false and exits. +```swift +let lhs = str[str.index(str.startIndex, offsetBy: left)] +let rhs = str[str.index(str.startIndex, offsetBy: right)] +if lhs != rhs { +return false +} +``` +If they are the same the method calls itself again and updates the indexes accordingly to continue to check the rest of the string. ```swift -palindromeCheck(text: "Race car") +return palindrome(str, left: left + 1, right: right - 1) ``` -Since the phrase "Race car" is a palindrome, this will return true. +Step 1: +` race?C ar -> raceCar -> racecar`` + +Step 2: +| | +racecar -> r == r + | | +racecar -> a == a + | | +racecar -> c == c + | +racecar -> left index == right index -> return true ## Additional Resources [Palindrome Wikipedia](https://en.wikipedia.org/wiki/Palindrome) -*Written by [Stephen Rutstein](https://github.com/srutstein21)* +*Written by [Joshua Alvarado](https://github.com/https://github.com/lostatseajoshua)* From 0ffeb1fdd0d4568270b4bef42fef73e89fb108d9 Mon Sep 17 00:00:00 2001 From: Joshua Alvarado Date: Thu, 22 Dec 2016 11:28:44 -0700 Subject: [PATCH 0711/1679] Update README formatting --- Palindromes/README.markdown | 48 ++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/Palindromes/README.markdown b/Palindromes/README.markdown index fe31cf297..48420f323 100644 --- a/Palindromes/README.markdown +++ b/Palindromes/README.markdown @@ -7,6 +7,7 @@ Algorithms that check for palindromes are a common programming interview questio ## Example The word racecar is a valid palindrome, as it is a word spelled the same when backgrounds and forwards. The examples below shows valid cases of the palindrome `racecar`. + `raceCar` `r a c e c a r` `r?a?c?e?c?a?r?` @@ -14,9 +15,7 @@ The word racecar is a valid palindrome, as it is a word spelled the same when ba ## Algorithm -To check for palindromes, a strings character are compared starting from the beginning and end and moving inward moving to toward the middle of the string and keep the same distance apart in the comparison index. - -In this implementation of a palindrome algorithm, recursion is used to check each of the characters on the left-hand side and right-hand side moving inward. +To check for palindromes, a string's characters are compared starting from the beginning and end then moving inward toward the middle of the string while maintaining the same distance apart. In this implementation of a palindrome algorithm, recursion is used to check each of the characters on the left-hand side and right-hand side moving inward. ## The code @@ -24,32 +23,33 @@ Here is a recursive implementation of this in Swift: ```swift func isPalindrome(_ str: String) -> Bool { -let strippedString = str.replacingOccurrences(of: "\\W", with: "", options: .regularExpression, range: nil) -let length = strippedString.characters.count + let strippedString = str.replacingOccurrences(of: "\\W", with: "", options: .regularExpression, range: nil) + let length = strippedString.characters.count -if length > 1 { -return palindrome(strippedString.lowercased(), left: 0, right: length - 1) -} -return false + if length > 1 { + return palindrome(strippedString.lowercased(), left: 0, right: length - 1) + } + return false } private func palindrome(_ str: String, left: Int, right: Int) -> Bool { -if left >= right { -return true -} + if left >= right { + return true + } -let lhs = str[str.index(str.startIndex, offsetBy: left)] -let rhs = str[str.index(str.startIndex, offsetBy: right)] + let lhs = str[str.index(str.startIndex, offsetBy: left)] + let rhs = str[str.index(str.startIndex, offsetBy: right)] -if lhs != rhs { -return false -} + if lhs != rhs { + return false + } -return palindrome(str, left: left + 1, right: right - 1) + return palindrome(str, left: left + 1, right: right - 1) } ``` -This algorithm has a two-step process. +This algorithm has a two-step process. + 1. The first step is to pass the string to validate as a palindrome into the `isPalindrome` method. This method first removes occurrences of non-word pattern matches `\W` [Regex reference](http://regexr.com). It is written with two \\ to escape the \ in the String literal. ```swift @@ -61,7 +61,7 @@ The length of the string is then checked to make sure that the string after bein 2. The second step is to pass the string in a recursive method. This method takes a string, a left index, and a right index. The method checks the characters of the string using the indexes to compare each character on both sides. The method checks if the left is greater or equal to the right if so the entire string has been run through without returning false so the string is equal on both sides thus returning true. ```swift if left >= right { -return true + return true } ``` If the check doesn't pass it continues to get the characters at the specified indexes and compare each. If they are not the same the method returns false and exits. @@ -70,7 +70,7 @@ let lhs = str[str.index(str.startIndex, offsetBy: left)] let rhs = str[str.index(str.startIndex, offsetBy: right)] if lhs != rhs { -return false + return false } ``` If they are the same the method calls itself again and updates the indexes accordingly to continue to check the rest of the string. @@ -82,14 +82,18 @@ Step 1: ` race?C ar -> raceCar -> racecar`` Step 2: +``` | | racecar -> r == r + | | racecar -> a == a + | | racecar -> c == c + | -racecar -> left index == right index -> return true +racecar -> left index == right index -> return true``` ## Additional Resources From e4c2889bc3c8b6ba0f9fa47be0b86bb1f5c663d3 Mon Sep 17 00:00:00 2001 From: Joshua Alvarado Date: Thu, 22 Dec 2016 11:30:15 -0700 Subject: [PATCH 0712/1679] Fix code snippet from running to the bottom of the page --- Palindromes/README.markdown | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Palindromes/README.markdown b/Palindromes/README.markdown index 48420f323..53a48225a 100644 --- a/Palindromes/README.markdown +++ b/Palindromes/README.markdown @@ -93,7 +93,8 @@ racecar -> a == a racecar -> c == c | -racecar -> left index == right index -> return true``` +racecar -> left index == right index -> return true +``` ## Additional Resources From 8c0117dbe7fa5dace9de1492280110f0d6353ea4 Mon Sep 17 00:00:00 2001 From: Joshua Alvarado Date: Thu, 22 Dec 2016 11:34:57 -0700 Subject: [PATCH 0713/1679] Fix spacing on list of palindrome examples --- Palindromes/README.markdown | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Palindromes/README.markdown b/Palindromes/README.markdown index 53a48225a..85bdfc992 100644 --- a/Palindromes/README.markdown +++ b/Palindromes/README.markdown @@ -8,10 +8,12 @@ Algorithms that check for palindromes are a common programming interview questio The word racecar is a valid palindrome, as it is a word spelled the same when backgrounds and forwards. The examples below shows valid cases of the palindrome `racecar`. -`raceCar` -`r a c e c a r` -`r?a?c?e?c?a?r?` -`RACEcar` +``` +raceCar +r a c e c a r +r?a?c?e?c?a?r? +RACEcar +``` ## Algorithm From 13de04998d7f940c5c98bedb947ccee52fa0fe9d Mon Sep 17 00:00:00 2001 From: Joshua Alvarado Date: Thu, 22 Dec 2016 11:35:38 -0700 Subject: [PATCH 0714/1679] Improved formatting in code and markdown --- Palindromes/README.markdown | 47 +++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/Palindromes/README.markdown b/Palindromes/README.markdown index 85bdfc992..ede0af39d 100644 --- a/Palindromes/README.markdown +++ b/Palindromes/README.markdown @@ -25,34 +25,34 @@ Here is a recursive implementation of this in Swift: ```swift func isPalindrome(_ str: String) -> Bool { - let strippedString = str.replacingOccurrences(of: "\\W", with: "", options: .regularExpression, range: nil) - let length = strippedString.characters.count +let strippedString = str.replacingOccurrences(of: "\\W", with: "", options: .regularExpression, range: nil) +let length = strippedString.characters.count - if length > 1 { - return palindrome(strippedString.lowercased(), left: 0, right: length - 1) - } - return false +if length > 1 { +return palindrome(strippedString.lowercased(), left: 0, right: length - 1) +} +return false } private func palindrome(_ str: String, left: Int, right: Int) -> Bool { - if left >= right { - return true - } +if left >= right { +return true +} - let lhs = str[str.index(str.startIndex, offsetBy: left)] - let rhs = str[str.index(str.startIndex, offsetBy: right)] +let lhs = str[str.index(str.startIndex, offsetBy: left)] +let rhs = str[str.index(str.startIndex, offsetBy: right)] - if lhs != rhs { - return false - } +if lhs != rhs { +return false +} - return palindrome(str, left: left + 1, right: right - 1) +return palindrome(str, left: left + 1, right: right - 1) } ``` This algorithm has a two-step process. -1. The first step is to pass the string to validate as a palindrome into the `isPalindrome` method. This method first removes occurrences of non-word pattern matches `\W` [Regex reference](http://regexr.com). It is written with two \\ to escape the \ in the String literal. +1 - The first step is to pass the string to validate as a palindrome into the `isPalindrome` method. This method first removes occurrences of non-word pattern matches `\W` [Regex reference](http://regexr.com). It is written with two \\ to escape the \ in the String literal. ```swift let strippedString = str.replacingOccurrences(of: "\\W", with: "", options: .regularExpression, range: nil) @@ -60,10 +60,10 @@ let strippedString = str.replacingOccurrences(of: "\\W", with: "", options: .reg The length of the string is then checked to make sure that the string after being stripped of non-word characters is still in a valid length. It is then passed into the next step after being lowercased. -2. The second step is to pass the string in a recursive method. This method takes a string, a left index, and a right index. The method checks the characters of the string using the indexes to compare each character on both sides. The method checks if the left is greater or equal to the right if so the entire string has been run through without returning false so the string is equal on both sides thus returning true. +2 - The second step is to pass the string in a recursive method. This method takes a string, a left index, and a right index. The method checks the characters of the string using the indexes to compare each character on both sides. The method checks if the left is greater or equal to the right if so the entire string has been run through without returning false so the string is equal on both sides thus returning true. ```swift if left >= right { - return true +return true } ``` If the check doesn't pass it continues to get the characters at the specified indexes and compare each. If they are not the same the method returns false and exits. @@ -72,7 +72,7 @@ let lhs = str[str.index(str.startIndex, offsetBy: left)] let rhs = str[str.index(str.startIndex, offsetBy: right)] if lhs != rhs { - return false +return false } ``` If they are the same the method calls itself again and updates the indexes accordingly to continue to check the rest of the string. @@ -81,20 +81,21 @@ return palindrome(str, left: left + 1, right: right - 1) ``` Step 1: -` race?C ar -> raceCar -> racecar`` + +`race?C ar -> raceCar -> racecar` Step 2: ``` | | racecar -> r == r - | | +| | racecar -> a == a - | | +| | racecar -> c == c - | +| racecar -> left index == right index -> return true ``` From 6a15d37a61310e7fd05c944f6be947605508b8f1 Mon Sep 17 00:00:00 2001 From: Joshua Alvarado Date: Thu, 22 Dec 2016 11:37:31 -0700 Subject: [PATCH 0715/1679] Revert "Improved formatting in code and markdown" This reverts commit 13de04998d7f940c5c98bedb947ccee52fa0fe9d. --- Palindromes/README.markdown | 47 ++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/Palindromes/README.markdown b/Palindromes/README.markdown index ede0af39d..85bdfc992 100644 --- a/Palindromes/README.markdown +++ b/Palindromes/README.markdown @@ -25,34 +25,34 @@ Here is a recursive implementation of this in Swift: ```swift func isPalindrome(_ str: String) -> Bool { -let strippedString = str.replacingOccurrences(of: "\\W", with: "", options: .regularExpression, range: nil) -let length = strippedString.characters.count + let strippedString = str.replacingOccurrences(of: "\\W", with: "", options: .regularExpression, range: nil) + let length = strippedString.characters.count -if length > 1 { -return palindrome(strippedString.lowercased(), left: 0, right: length - 1) -} -return false + if length > 1 { + return palindrome(strippedString.lowercased(), left: 0, right: length - 1) + } + return false } private func palindrome(_ str: String, left: Int, right: Int) -> Bool { -if left >= right { -return true -} + if left >= right { + return true + } -let lhs = str[str.index(str.startIndex, offsetBy: left)] -let rhs = str[str.index(str.startIndex, offsetBy: right)] + let lhs = str[str.index(str.startIndex, offsetBy: left)] + let rhs = str[str.index(str.startIndex, offsetBy: right)] -if lhs != rhs { -return false -} + if lhs != rhs { + return false + } -return palindrome(str, left: left + 1, right: right - 1) + return palindrome(str, left: left + 1, right: right - 1) } ``` This algorithm has a two-step process. -1 - The first step is to pass the string to validate as a palindrome into the `isPalindrome` method. This method first removes occurrences of non-word pattern matches `\W` [Regex reference](http://regexr.com). It is written with two \\ to escape the \ in the String literal. +1. The first step is to pass the string to validate as a palindrome into the `isPalindrome` method. This method first removes occurrences of non-word pattern matches `\W` [Regex reference](http://regexr.com). It is written with two \\ to escape the \ in the String literal. ```swift let strippedString = str.replacingOccurrences(of: "\\W", with: "", options: .regularExpression, range: nil) @@ -60,10 +60,10 @@ let strippedString = str.replacingOccurrences(of: "\\W", with: "", options: .reg The length of the string is then checked to make sure that the string after being stripped of non-word characters is still in a valid length. It is then passed into the next step after being lowercased. -2 - The second step is to pass the string in a recursive method. This method takes a string, a left index, and a right index. The method checks the characters of the string using the indexes to compare each character on both sides. The method checks if the left is greater or equal to the right if so the entire string has been run through without returning false so the string is equal on both sides thus returning true. +2. The second step is to pass the string in a recursive method. This method takes a string, a left index, and a right index. The method checks the characters of the string using the indexes to compare each character on both sides. The method checks if the left is greater or equal to the right if so the entire string has been run through without returning false so the string is equal on both sides thus returning true. ```swift if left >= right { -return true + return true } ``` If the check doesn't pass it continues to get the characters at the specified indexes and compare each. If they are not the same the method returns false and exits. @@ -72,7 +72,7 @@ let lhs = str[str.index(str.startIndex, offsetBy: left)] let rhs = str[str.index(str.startIndex, offsetBy: right)] if lhs != rhs { -return false + return false } ``` If they are the same the method calls itself again and updates the indexes accordingly to continue to check the rest of the string. @@ -81,21 +81,20 @@ return palindrome(str, left: left + 1, right: right - 1) ``` Step 1: - -`race?C ar -> raceCar -> racecar` +` race?C ar -> raceCar -> racecar`` Step 2: ``` | | racecar -> r == r -| | + | | racecar -> a == a -| | + | | racecar -> c == c -| + | racecar -> left index == right index -> return true ``` From f8888192086c2a542fc9550441a1cb41b7b51e90 Mon Sep 17 00:00:00 2001 From: Joshua Alvarado Date: Thu, 22 Dec 2016 11:37:59 -0700 Subject: [PATCH 0716/1679] Remove extra character --- Palindromes/README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Palindromes/README.markdown b/Palindromes/README.markdown index 85bdfc992..bb52678e0 100644 --- a/Palindromes/README.markdown +++ b/Palindromes/README.markdown @@ -81,7 +81,7 @@ return palindrome(str, left: left + 1, right: right - 1) ``` Step 1: -` race?C ar -> raceCar -> racecar`` +`race?C ar -> raceCar -> racecar` Step 2: ``` From 3da3a75413cf64aca60fc98e4987e9a804c12e48 Mon Sep 17 00:00:00 2001 From: Joshua Alvarado Date: Thu, 22 Dec 2016 11:39:18 -0700 Subject: [PATCH 0717/1679] Improved spacing on code snippet --- Palindromes/README.markdown | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Palindromes/README.markdown b/Palindromes/README.markdown index bb52678e0..18518adbe 100644 --- a/Palindromes/README.markdown +++ b/Palindromes/README.markdown @@ -31,7 +31,8 @@ func isPalindrome(_ str: String) -> Bool { if length > 1 { return palindrome(strippedString.lowercased(), left: 0, right: length - 1) } - return false + + return false } private func palindrome(_ str: String, left: Int, right: Int) -> Bool { From 9d4f6ea1204d2a6aa475cdbb2f6e412771b6b83b Mon Sep 17 00:00:00 2001 From: Joshua Alvarado Date: Thu, 22 Dec 2016 16:48:58 -0700 Subject: [PATCH 0718/1679] Add tests for Travis CI --- .travis.yml | 1 + .../Tests/Tests.xcodeproj/project.pbxproj | 413 ++++++++++++++++++ .../contents.xcworkspacedata | 7 + Palindromes/Tests/Tests/AppDelegate.swift | 46 ++ .../AppIcon.appiconset/Contents.json | 68 +++ .../Tests/Base.lproj/LaunchScreen.storyboard | 27 ++ Palindromes/Tests/Tests/Info.plist | 45 ++ Palindromes/Tests/Tests/Palindromes.swift | 26 ++ Palindromes/Tests/TestsTests/Info.plist | 22 + .../Tests/TestsTests/PalindromeTests.swift | 70 +++ 10 files changed, 725 insertions(+) create mode 100644 Palindromes/Tests/Tests.xcodeproj/project.pbxproj create mode 100644 Palindromes/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 Palindromes/Tests/Tests/AppDelegate.swift create mode 100644 Palindromes/Tests/Tests/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 Palindromes/Tests/Tests/Base.lproj/LaunchScreen.storyboard create mode 100644 Palindromes/Tests/Tests/Info.plist create mode 100644 Palindromes/Tests/Tests/Palindromes.swift create mode 100644 Palindromes/Tests/TestsTests/Info.plist create mode 100644 Palindromes/Tests/TestsTests/PalindromeTests.swift diff --git a/.travis.yml b/.travis.yml index 17655c21e..f7231cdfe 100644 --- a/.travis.yml +++ b/.travis.yml @@ -40,3 +40,4 @@ script: - xcodebuild test -project ./Stack/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Topological\ Sort/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Treap/Treap/Treap.xcodeproj -scheme Tests +- xcodebuild test -project ./Palindromes/Tests/Tests.xcodeproj -scheme Tests diff --git a/Palindromes/Tests/Tests.xcodeproj/project.pbxproj b/Palindromes/Tests/Tests.xcodeproj/project.pbxproj new file mode 100644 index 000000000..63b68d316 --- /dev/null +++ b/Palindromes/Tests/Tests.xcodeproj/project.pbxproj @@ -0,0 +1,413 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 94D8AF0F1E0C9AB4007D8806 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94D8AF0E1E0C9AB4007D8806 /* AppDelegate.swift */; }; + 94D8AF161E0C9AB4007D8806 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 94D8AF151E0C9AB4007D8806 /* Assets.xcassets */; }; + 94D8AF191E0C9AB4007D8806 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 94D8AF171E0C9AB4007D8806 /* LaunchScreen.storyboard */; }; + 94D8AF2F1E0C9AE9007D8806 /* Palindromes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94D8AF2E1E0C9AE9007D8806 /* Palindromes.swift */; }; + 94D8AF331E0C9BB2007D8806 /* PalindromeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94D8AF321E0C9BB2007D8806 /* PalindromeTests.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 94D8AF201E0C9AB4007D8806 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 94D8AF031E0C9AB4007D8806 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 94D8AF0A1E0C9AB4007D8806; + remoteInfo = Tests; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 94D8AF0B1E0C9AB4007D8806 /* Tests.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Tests.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 94D8AF0E1E0C9AB4007D8806 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 94D8AF151E0C9AB4007D8806 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 94D8AF181E0C9AB4007D8806 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 94D8AF1A1E0C9AB4007D8806 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 94D8AF1F1E0C9AB4007D8806 /* TestsTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TestsTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 94D8AF251E0C9AB4007D8806 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 94D8AF2E1E0C9AE9007D8806 /* Palindromes.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Palindromes.swift; sourceTree = ""; }; + 94D8AF321E0C9BB2007D8806 /* PalindromeTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PalindromeTests.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 94D8AF081E0C9AB4007D8806 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 94D8AF1C1E0C9AB4007D8806 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 94D8AF021E0C9AB4007D8806 = { + isa = PBXGroup; + children = ( + 94D8AF0D1E0C9AB4007D8806 /* Tests */, + 94D8AF221E0C9AB4007D8806 /* TestsTests */, + 94D8AF0C1E0C9AB4007D8806 /* Products */, + ); + sourceTree = ""; + }; + 94D8AF0C1E0C9AB4007D8806 /* Products */ = { + isa = PBXGroup; + children = ( + 94D8AF0B1E0C9AB4007D8806 /* Tests.app */, + 94D8AF1F1E0C9AB4007D8806 /* TestsTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 94D8AF0D1E0C9AB4007D8806 /* Tests */ = { + isa = PBXGroup; + children = ( + 94D8AF0E1E0C9AB4007D8806 /* AppDelegate.swift */, + 94D8AF2E1E0C9AE9007D8806 /* Palindromes.swift */, + 94D8AF151E0C9AB4007D8806 /* Assets.xcassets */, + 94D8AF171E0C9AB4007D8806 /* LaunchScreen.storyboard */, + 94D8AF1A1E0C9AB4007D8806 /* Info.plist */, + ); + path = Tests; + sourceTree = ""; + }; + 94D8AF221E0C9AB4007D8806 /* TestsTests */ = { + isa = PBXGroup; + children = ( + 94D8AF321E0C9BB2007D8806 /* PalindromeTests.swift */, + 94D8AF251E0C9AB4007D8806 /* Info.plist */, + ); + path = TestsTests; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 94D8AF0A1E0C9AB4007D8806 /* Tests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 94D8AF281E0C9AB4007D8806 /* Build configuration list for PBXNativeTarget "Tests" */; + buildPhases = ( + 94D8AF071E0C9AB4007D8806 /* Sources */, + 94D8AF081E0C9AB4007D8806 /* Frameworks */, + 94D8AF091E0C9AB4007D8806 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Tests; + productName = Tests; + productReference = 94D8AF0B1E0C9AB4007D8806 /* Tests.app */; + productType = "com.apple.product-type.application"; + }; + 94D8AF1E1E0C9AB4007D8806 /* TestsTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 94D8AF2B1E0C9AB4007D8806 /* Build configuration list for PBXNativeTarget "TestsTests" */; + buildPhases = ( + 94D8AF1B1E0C9AB4007D8806 /* Sources */, + 94D8AF1C1E0C9AB4007D8806 /* Frameworks */, + 94D8AF1D1E0C9AB4007D8806 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 94D8AF211E0C9AB4007D8806 /* PBXTargetDependency */, + ); + name = TestsTests; + productName = TestsTests; + productReference = 94D8AF1F1E0C9AB4007D8806 /* TestsTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 94D8AF031E0C9AB4007D8806 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0820; + LastUpgradeCheck = 0820; + ORGANIZATIONNAME = "Joshua Alvarado"; + TargetAttributes = { + 94D8AF0A1E0C9AB4007D8806 = { + CreatedOnToolsVersion = 8.2; + ProvisioningStyle = Automatic; + }; + 94D8AF1E1E0C9AB4007D8806 = { + CreatedOnToolsVersion = 8.2; + LastSwiftMigration = 0820; + ProvisioningStyle = Automatic; + TestTargetID = 94D8AF0A1E0C9AB4007D8806; + }; + }; + }; + buildConfigurationList = 94D8AF061E0C9AB4007D8806 /* Build configuration list for PBXProject "Tests" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 94D8AF021E0C9AB4007D8806; + productRefGroup = 94D8AF0C1E0C9AB4007D8806 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 94D8AF0A1E0C9AB4007D8806 /* Tests */, + 94D8AF1E1E0C9AB4007D8806 /* TestsTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 94D8AF091E0C9AB4007D8806 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 94D8AF191E0C9AB4007D8806 /* LaunchScreen.storyboard in Resources */, + 94D8AF161E0C9AB4007D8806 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 94D8AF1D1E0C9AB4007D8806 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 94D8AF071E0C9AB4007D8806 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 94D8AF2F1E0C9AE9007D8806 /* Palindromes.swift in Sources */, + 94D8AF0F1E0C9AB4007D8806 /* AppDelegate.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 94D8AF1B1E0C9AB4007D8806 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 94D8AF331E0C9BB2007D8806 /* PalindromeTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 94D8AF211E0C9AB4007D8806 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 94D8AF0A1E0C9AB4007D8806 /* Tests */; + targetProxy = 94D8AF201E0C9AB4007D8806 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 94D8AF171E0C9AB4007D8806 /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 94D8AF181E0C9AB4007D8806 /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 94D8AF261E0C9AB4007D8806 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 10.2; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 94D8AF271E0C9AB4007D8806 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 10.2; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 94D8AF291E0C9AB4007D8806 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = Tests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = self.edu.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; + }; + name = Debug; + }; + 94D8AF2A1E0C9AB4007D8806 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = Tests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = self.edu.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; + }; + name = Release; + }; + 94D8AF2C1E0C9AB4007D8806 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + BUNDLE_LOADER = "$(TEST_HOST)"; + CLANG_ENABLE_MODULES = YES; + INFOPLIST_FILE = TestsTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = self.edu.TestsTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 3.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Tests.app/Tests"; + }; + name = Debug; + }; + 94D8AF2D1E0C9AB4007D8806 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + BUNDLE_LOADER = "$(TEST_HOST)"; + CLANG_ENABLE_MODULES = YES; + INFOPLIST_FILE = TestsTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = self.edu.TestsTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Tests.app/Tests"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 94D8AF061E0C9AB4007D8806 /* Build configuration list for PBXProject "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 94D8AF261E0C9AB4007D8806 /* Debug */, + 94D8AF271E0C9AB4007D8806 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 94D8AF281E0C9AB4007D8806 /* Build configuration list for PBXNativeTarget "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 94D8AF291E0C9AB4007D8806 /* Debug */, + 94D8AF2A1E0C9AB4007D8806 /* Release */, + ); + defaultConfigurationIsVisible = 0; + }; + 94D8AF2B1E0C9AB4007D8806 /* Build configuration list for PBXNativeTarget "TestsTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 94D8AF2C1E0C9AB4007D8806 /* Debug */, + 94D8AF2D1E0C9AB4007D8806 /* Release */, + ); + defaultConfigurationIsVisible = 0; + }; +/* End XCConfigurationList section */ + }; + rootObject = 94D8AF031E0C9AB4007D8806 /* Project object */; +} diff --git a/Palindromes/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Palindromes/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..6c0ea8493 --- /dev/null +++ b/Palindromes/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Palindromes/Tests/Tests/AppDelegate.swift b/Palindromes/Tests/Tests/AppDelegate.swift new file mode 100644 index 000000000..481c72c62 --- /dev/null +++ b/Palindromes/Tests/Tests/AppDelegate.swift @@ -0,0 +1,46 @@ +// +// AppDelegate.swift +// Tests +// +// Created by Joshua Alvarado on 12/22/16. +// Copyright © 2016 Joshua Alvarado. All rights reserved. +// + +import UIKit + +@UIApplicationMain +class AppDelegate: UIResponder, UIApplicationDelegate { + + var window: UIWindow? + + + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { + // Override point for customization after application launch. + return true + } + + func applicationWillResignActive(_ application: UIApplication) { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. + } + + func applicationDidEnterBackground(_ application: UIApplication) { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. + } + + func applicationWillEnterForeground(_ application: UIApplication) { + // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. + } + + func applicationDidBecomeActive(_ application: UIApplication) { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. + } + + func applicationWillTerminate(_ application: UIApplication) { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. + } + + +} + diff --git a/Palindromes/Tests/Tests/Assets.xcassets/AppIcon.appiconset/Contents.json b/Palindromes/Tests/Tests/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 000000000..36d2c80d8 --- /dev/null +++ b/Palindromes/Tests/Tests/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,68 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Palindromes/Tests/Tests/Base.lproj/LaunchScreen.storyboard b/Palindromes/Tests/Tests/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 000000000..fdf3f97d1 --- /dev/null +++ b/Palindromes/Tests/Tests/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Palindromes/Tests/Tests/Info.plist b/Palindromes/Tests/Tests/Info.plist new file mode 100644 index 000000000..f197d509b --- /dev/null +++ b/Palindromes/Tests/Tests/Info.plist @@ -0,0 +1,45 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + LaunchScreen + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/Palindromes/Tests/Tests/Palindromes.swift b/Palindromes/Tests/Tests/Palindromes.swift new file mode 100644 index 000000000..2760137ca --- /dev/null +++ b/Palindromes/Tests/Tests/Palindromes.swift @@ -0,0 +1,26 @@ +import Foundation + +func isPalindrome(_ str: String) -> Bool { + let strippedString = str.replacingOccurrences(of: "\\W", with: "", options: .regularExpression, range: nil) + let length = strippedString.characters.count + + if length > 1 { + return palindrome(strippedString.lowercased(), left: 0, right: length - 1) + } + return false +} + +private func palindrome(_ str: String, left: Int, right: Int) -> Bool { + if left >= right { + return true + } + + let lhs = str[str.index(str.startIndex, offsetBy: left)] + let rhs = str[str.index(str.startIndex, offsetBy: right)] + + if lhs != rhs { + return false + } + + return palindrome(str, left: left + 1, right: right - 1) +} diff --git a/Palindromes/Tests/TestsTests/Info.plist b/Palindromes/Tests/TestsTests/Info.plist new file mode 100644 index 000000000..6c6c23c43 --- /dev/null +++ b/Palindromes/Tests/TestsTests/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + diff --git a/Palindromes/Tests/TestsTests/PalindromeTests.swift b/Palindromes/Tests/TestsTests/PalindromeTests.swift new file mode 100644 index 000000000..27d8f88b0 --- /dev/null +++ b/Palindromes/Tests/TestsTests/PalindromeTests.swift @@ -0,0 +1,70 @@ +// +// PalindromeTests.swift +// Tests +// +// Created by Joshua Alvarado on 12/22/16. +// Copyright © 2016 Joshua Alvarado. All rights reserved. +// + +import XCTest +@testable import Tests + +class PalindromeTests: XCTestCase { + + override func setUp() { + super.setUp() + // Put setup code here. This method is called before the invocation of each test method in the class. + } + + override func tearDown() { + // Put teardown code here. This method is called after the invocation of each test method in the class. + super.tearDown() + } + + func testExample() { + // This is an example of a functional test case. + // Use XCTAssert and related functions to verify your tests produce the correct results. + } + + func testPerformanceExample() { + // This is an example of a performance test case. + self.measure { + // Put the code you want to measure the time of here. + let _ = isPalindrome("abbcbba") + let _ = isPalindrome("asdkfaksjdfasjkdfhaslkjdfakjsdfhakljsdhflkjasdfhkasdjhfklajsdfhkljasdf") + let _ = isPalindrome("abababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababa") + } + } + + func testPalindromeWord() { + XCTAssertTrue(isPalindrome("abbcbba")) + XCTAssertTrue(isPalindrome("racecar")) + } + + func testPalindromeSentence() { + XCTAssertTrue(isPalindrome("A man, a plan, a canal, Panama!")) + XCTAssertTrue(isPalindrome("Madam, I'm Adam")) + XCTAssertTrue(isPalindrome("Madam in Eden, I'm Adam")) + XCTAssertTrue(isPalindrome("In girum imus nocte et consumimur igni")) + XCTAssertTrue(isPalindrome("Never odd or even")) + } + + func testPalindromeNumber() { + XCTAssertTrue(isPalindrome("5885")) + XCTAssertTrue(isPalindrome("5 8 8 5")) + XCTAssertTrue(isPalindrome("58 85")) + } + + func testSpecialCharacters() { + XCTAssertTrue(isPalindrome("৯৯")) + } + + func testNonPalindromes() { + XCTAssertFalse(isPalindrome("\\\\")) + XCTAssertFalse(isPalindrome("desserts")) + XCTAssertFalse(isPalindrome("😀😀")) + XCTAssertFalse(isPalindrome("")) + XCTAssertFalse(isPalindrome("a")) + XCTAssertFalse(isPalindrome("power")) + } +} From 4d4b63d47ca048f58d1c0ddb30bc87648f45956c Mon Sep 17 00:00:00 2001 From: Joshua Alvarado Date: Fri, 23 Dec 2016 10:36:05 -0700 Subject: [PATCH 0719/1679] Update test project to run palindrome tests --- .travis.yml | 2 +- .../{Tests/Tests => Test}/Palindromes.swift | 0 .../Test/Test.xcodeproj/project.pbxproj | 273 ++++++++++++ .../contents.xcworkspacedata | 2 +- .../TestsTests => Test/Test}/Info.plist | 0 .../Test/Test.swift} | 9 +- .../Tests/Tests.xcodeproj/project.pbxproj | 413 ------------------ Palindromes/Tests/Tests/AppDelegate.swift | 46 -- .../AppIcon.appiconset/Contents.json | 68 --- .../Tests/Base.lproj/LaunchScreen.storyboard | 27 -- Palindromes/Tests/Tests/Info.plist | 45 -- 11 files changed, 279 insertions(+), 606 deletions(-) rename Palindromes/{Tests/Tests => Test}/Palindromes.swift (100%) create mode 100644 Palindromes/Test/Test.xcodeproj/project.pbxproj rename Palindromes/{Tests/Tests.xcodeproj => Test/Test.xcodeproj}/project.xcworkspace/contents.xcworkspacedata (72%) rename Palindromes/{Tests/TestsTests => Test/Test}/Info.plist (100%) rename Palindromes/{Tests/TestsTests/PalindromeTests.swift => Test/Test/Test.swift} (96%) delete mode 100644 Palindromes/Tests/Tests.xcodeproj/project.pbxproj delete mode 100644 Palindromes/Tests/Tests/AppDelegate.swift delete mode 100644 Palindromes/Tests/Tests/Assets.xcassets/AppIcon.appiconset/Contents.json delete mode 100644 Palindromes/Tests/Tests/Base.lproj/LaunchScreen.storyboard delete mode 100644 Palindromes/Tests/Tests/Info.plist diff --git a/.travis.yml b/.travis.yml index f7231cdfe..dc681ccd1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -40,4 +40,4 @@ script: - xcodebuild test -project ./Stack/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Topological\ Sort/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Treap/Treap/Treap.xcodeproj -scheme Tests -- xcodebuild test -project ./Palindromes/Tests/Tests.xcodeproj -scheme Tests +- xcodebuild test -project ./Palindromes/Test/Test.xcodeproj -scheme Test diff --git a/Palindromes/Tests/Tests/Palindromes.swift b/Palindromes/Test/Palindromes.swift similarity index 100% rename from Palindromes/Tests/Tests/Palindromes.swift rename to Palindromes/Test/Palindromes.swift diff --git a/Palindromes/Test/Test.xcodeproj/project.pbxproj b/Palindromes/Test/Test.xcodeproj/project.pbxproj new file mode 100644 index 000000000..07aae3e63 --- /dev/null +++ b/Palindromes/Test/Test.xcodeproj/project.pbxproj @@ -0,0 +1,273 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 9437D8841E0D960A00A38FB8 /* Test.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9437D8831E0D960A00A38FB8 /* Test.swift */; }; + 9437D88B1E0D969500A38FB8 /* Palindromes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9437D8791E0D948A00A38FB8 /* Palindromes.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 9437D8791E0D948A00A38FB8 /* Palindromes.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Palindromes.swift; sourceTree = ""; }; + 9437D8811E0D960A00A38FB8 /* Test.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Test.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 9437D8831E0D960A00A38FB8 /* Test.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Test.swift; sourceTree = ""; }; + 9437D8851E0D960A00A38FB8 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 9437D87E1E0D960A00A38FB8 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 9437D8651E0D945200A38FB8 = { + isa = PBXGroup; + children = ( + 9437D8791E0D948A00A38FB8 /* Palindromes.swift */, + 9437D8821E0D960A00A38FB8 /* Test */, + 9437D86F1E0D945200A38FB8 /* Products */, + ); + sourceTree = ""; + }; + 9437D86F1E0D945200A38FB8 /* Products */ = { + isa = PBXGroup; + children = ( + 9437D8811E0D960A00A38FB8 /* Test.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 9437D8821E0D960A00A38FB8 /* Test */ = { + isa = PBXGroup; + children = ( + 9437D8831E0D960A00A38FB8 /* Test.swift */, + 9437D8851E0D960A00A38FB8 /* Info.plist */, + ); + path = Test; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 9437D8801E0D960A00A38FB8 /* Test */ = { + isa = PBXNativeTarget; + buildConfigurationList = 9437D8861E0D960A00A38FB8 /* Build configuration list for PBXNativeTarget "Test" */; + buildPhases = ( + 9437D87D1E0D960A00A38FB8 /* Sources */, + 9437D87E1E0D960A00A38FB8 /* Frameworks */, + 9437D87F1E0D960A00A38FB8 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Test; + productName = Test; + productReference = 9437D8811E0D960A00A38FB8 /* Test.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 9437D8661E0D945200A38FB8 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0820; + LastUpgradeCheck = 0820; + ORGANIZATIONNAME = "Joshua Alvarado"; + TargetAttributes = { + 9437D8801E0D960A00A38FB8 = { + CreatedOnToolsVersion = 8.2; + ProvisioningStyle = Automatic; + }; + }; + }; + buildConfigurationList = 9437D8691E0D945200A38FB8 /* Build configuration list for PBXProject "Test" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 9437D8651E0D945200A38FB8; + productRefGroup = 9437D86F1E0D945200A38FB8 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 9437D8801E0D960A00A38FB8 /* Test */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 9437D87F1E0D960A00A38FB8 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 9437D87D1E0D960A00A38FB8 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 9437D88B1E0D969500A38FB8 /* Palindromes.swift in Sources */, + 9437D8841E0D960A00A38FB8 /* Test.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 9437D8721E0D945200A38FB8 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + }; + name = Debug; + }; + 9437D8731E0D945200A38FB8 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + }; + name = Release; + }; + 9437D8871E0D960A00A38FB8 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Test/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.12; + PRODUCT_BUNDLE_IDENTIFIER = self.edu.Test; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 3.0; + }; + name = Debug; + }; + 9437D8881E0D960A00A38FB8 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Test/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.12; + PRODUCT_BUNDLE_IDENTIFIER = self.edu.Test; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_VERSION = 3.0; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 9437D8691E0D945200A38FB8 /* Build configuration list for PBXProject "Test" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 9437D8721E0D945200A38FB8 /* Debug */, + 9437D8731E0D945200A38FB8 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 9437D8861E0D960A00A38FB8 /* Build configuration list for PBXNativeTarget "Test" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 9437D8871E0D960A00A38FB8 /* Debug */, + 9437D8881E0D960A00A38FB8 /* Release */, + ); + defaultConfigurationIsVisible = 0; + }; +/* End XCConfigurationList section */ + }; + rootObject = 9437D8661E0D945200A38FB8 /* Project object */; +} diff --git a/Palindromes/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Palindromes/Test/Test.xcodeproj/project.xcworkspace/contents.xcworkspacedata similarity index 72% rename from Palindromes/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata rename to Palindromes/Test/Test.xcodeproj/project.xcworkspace/contents.xcworkspacedata index 6c0ea8493..87cc241f8 100644 --- a/Palindromes/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ b/Palindromes/Test/Test.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -2,6 +2,6 @@ + location = "self:Test.xcodeproj"> diff --git a/Palindromes/Tests/TestsTests/Info.plist b/Palindromes/Test/Test/Info.plist similarity index 100% rename from Palindromes/Tests/TestsTests/Info.plist rename to Palindromes/Test/Test/Info.plist diff --git a/Palindromes/Tests/TestsTests/PalindromeTests.swift b/Palindromes/Test/Test/Test.swift similarity index 96% rename from Palindromes/Tests/TestsTests/PalindromeTests.swift rename to Palindromes/Test/Test/Test.swift index 27d8f88b0..e86a40cfb 100644 --- a/Palindromes/Tests/TestsTests/PalindromeTests.swift +++ b/Palindromes/Test/Test/Test.swift @@ -1,13 +1,12 @@ // // PalindromeTests.swift -// Tests +// Test // -// Created by Joshua Alvarado on 12/22/16. +// Created by Joshua Alvarado on 12/23/16. // Copyright © 2016 Joshua Alvarado. All rights reserved. // import XCTest -@testable import Tests class PalindromeTests: XCTestCase { @@ -48,13 +47,13 @@ class PalindromeTests: XCTestCase { XCTAssertTrue(isPalindrome("In girum imus nocte et consumimur igni")) XCTAssertTrue(isPalindrome("Never odd or even")) } - + func testPalindromeNumber() { XCTAssertTrue(isPalindrome("5885")) XCTAssertTrue(isPalindrome("5 8 8 5")) XCTAssertTrue(isPalindrome("58 85")) } - + func testSpecialCharacters() { XCTAssertTrue(isPalindrome("৯৯")) } diff --git a/Palindromes/Tests/Tests.xcodeproj/project.pbxproj b/Palindromes/Tests/Tests.xcodeproj/project.pbxproj deleted file mode 100644 index 63b68d316..000000000 --- a/Palindromes/Tests/Tests.xcodeproj/project.pbxproj +++ /dev/null @@ -1,413 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 94D8AF0F1E0C9AB4007D8806 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94D8AF0E1E0C9AB4007D8806 /* AppDelegate.swift */; }; - 94D8AF161E0C9AB4007D8806 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 94D8AF151E0C9AB4007D8806 /* Assets.xcassets */; }; - 94D8AF191E0C9AB4007D8806 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 94D8AF171E0C9AB4007D8806 /* LaunchScreen.storyboard */; }; - 94D8AF2F1E0C9AE9007D8806 /* Palindromes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94D8AF2E1E0C9AE9007D8806 /* Palindromes.swift */; }; - 94D8AF331E0C9BB2007D8806 /* PalindromeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94D8AF321E0C9BB2007D8806 /* PalindromeTests.swift */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 94D8AF201E0C9AB4007D8806 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 94D8AF031E0C9AB4007D8806 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 94D8AF0A1E0C9AB4007D8806; - remoteInfo = Tests; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXFileReference section */ - 94D8AF0B1E0C9AB4007D8806 /* Tests.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Tests.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 94D8AF0E1E0C9AB4007D8806 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 94D8AF151E0C9AB4007D8806 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - 94D8AF181E0C9AB4007D8806 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; - 94D8AF1A1E0C9AB4007D8806 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 94D8AF1F1E0C9AB4007D8806 /* TestsTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TestsTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 94D8AF251E0C9AB4007D8806 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 94D8AF2E1E0C9AE9007D8806 /* Palindromes.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Palindromes.swift; sourceTree = ""; }; - 94D8AF321E0C9BB2007D8806 /* PalindromeTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PalindromeTests.swift; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 94D8AF081E0C9AB4007D8806 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 94D8AF1C1E0C9AB4007D8806 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 94D8AF021E0C9AB4007D8806 = { - isa = PBXGroup; - children = ( - 94D8AF0D1E0C9AB4007D8806 /* Tests */, - 94D8AF221E0C9AB4007D8806 /* TestsTests */, - 94D8AF0C1E0C9AB4007D8806 /* Products */, - ); - sourceTree = ""; - }; - 94D8AF0C1E0C9AB4007D8806 /* Products */ = { - isa = PBXGroup; - children = ( - 94D8AF0B1E0C9AB4007D8806 /* Tests.app */, - 94D8AF1F1E0C9AB4007D8806 /* TestsTests.xctest */, - ); - name = Products; - sourceTree = ""; - }; - 94D8AF0D1E0C9AB4007D8806 /* Tests */ = { - isa = PBXGroup; - children = ( - 94D8AF0E1E0C9AB4007D8806 /* AppDelegate.swift */, - 94D8AF2E1E0C9AE9007D8806 /* Palindromes.swift */, - 94D8AF151E0C9AB4007D8806 /* Assets.xcassets */, - 94D8AF171E0C9AB4007D8806 /* LaunchScreen.storyboard */, - 94D8AF1A1E0C9AB4007D8806 /* Info.plist */, - ); - path = Tests; - sourceTree = ""; - }; - 94D8AF221E0C9AB4007D8806 /* TestsTests */ = { - isa = PBXGroup; - children = ( - 94D8AF321E0C9BB2007D8806 /* PalindromeTests.swift */, - 94D8AF251E0C9AB4007D8806 /* Info.plist */, - ); - path = TestsTests; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 94D8AF0A1E0C9AB4007D8806 /* Tests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 94D8AF281E0C9AB4007D8806 /* Build configuration list for PBXNativeTarget "Tests" */; - buildPhases = ( - 94D8AF071E0C9AB4007D8806 /* Sources */, - 94D8AF081E0C9AB4007D8806 /* Frameworks */, - 94D8AF091E0C9AB4007D8806 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = Tests; - productName = Tests; - productReference = 94D8AF0B1E0C9AB4007D8806 /* Tests.app */; - productType = "com.apple.product-type.application"; - }; - 94D8AF1E1E0C9AB4007D8806 /* TestsTests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 94D8AF2B1E0C9AB4007D8806 /* Build configuration list for PBXNativeTarget "TestsTests" */; - buildPhases = ( - 94D8AF1B1E0C9AB4007D8806 /* Sources */, - 94D8AF1C1E0C9AB4007D8806 /* Frameworks */, - 94D8AF1D1E0C9AB4007D8806 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - 94D8AF211E0C9AB4007D8806 /* PBXTargetDependency */, - ); - name = TestsTests; - productName = TestsTests; - productReference = 94D8AF1F1E0C9AB4007D8806 /* TestsTests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 94D8AF031E0C9AB4007D8806 /* Project object */ = { - isa = PBXProject; - attributes = { - LastSwiftUpdateCheck = 0820; - LastUpgradeCheck = 0820; - ORGANIZATIONNAME = "Joshua Alvarado"; - TargetAttributes = { - 94D8AF0A1E0C9AB4007D8806 = { - CreatedOnToolsVersion = 8.2; - ProvisioningStyle = Automatic; - }; - 94D8AF1E1E0C9AB4007D8806 = { - CreatedOnToolsVersion = 8.2; - LastSwiftMigration = 0820; - ProvisioningStyle = Automatic; - TestTargetID = 94D8AF0A1E0C9AB4007D8806; - }; - }; - }; - buildConfigurationList = 94D8AF061E0C9AB4007D8806 /* Build configuration list for PBXProject "Tests" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 94D8AF021E0C9AB4007D8806; - productRefGroup = 94D8AF0C1E0C9AB4007D8806 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 94D8AF0A1E0C9AB4007D8806 /* Tests */, - 94D8AF1E1E0C9AB4007D8806 /* TestsTests */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 94D8AF091E0C9AB4007D8806 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 94D8AF191E0C9AB4007D8806 /* LaunchScreen.storyboard in Resources */, - 94D8AF161E0C9AB4007D8806 /* Assets.xcassets in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 94D8AF1D1E0C9AB4007D8806 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 94D8AF071E0C9AB4007D8806 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 94D8AF2F1E0C9AE9007D8806 /* Palindromes.swift in Sources */, - 94D8AF0F1E0C9AB4007D8806 /* AppDelegate.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 94D8AF1B1E0C9AB4007D8806 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 94D8AF331E0C9BB2007D8806 /* PalindromeTests.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 94D8AF211E0C9AB4007D8806 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 94D8AF0A1E0C9AB4007D8806 /* Tests */; - targetProxy = 94D8AF201E0C9AB4007D8806 /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin PBXVariantGroup section */ - 94D8AF171E0C9AB4007D8806 /* LaunchScreen.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 94D8AF181E0C9AB4007D8806 /* Base */, - ); - name = LaunchScreen.storyboard; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 94D8AF261E0C9AB4007D8806 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 10.2; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 94D8AF271E0C9AB4007D8806 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 10.2; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 94D8AF291E0C9AB4007D8806 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = Tests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = self.edu.Tests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 3.0; - }; - name = Debug; - }; - 94D8AF2A1E0C9AB4007D8806 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = Tests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = self.edu.Tests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 3.0; - }; - name = Release; - }; - 94D8AF2C1E0C9AB4007D8806 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; - BUNDLE_LOADER = "$(TEST_HOST)"; - CLANG_ENABLE_MODULES = YES; - INFOPLIST_FILE = TestsTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = self.edu.TestsTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 3.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Tests.app/Tests"; - }; - name = Debug; - }; - 94D8AF2D1E0C9AB4007D8806 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; - BUNDLE_LOADER = "$(TEST_HOST)"; - CLANG_ENABLE_MODULES = YES; - INFOPLIST_FILE = TestsTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = self.edu.TestsTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 3.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Tests.app/Tests"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 94D8AF061E0C9AB4007D8806 /* Build configuration list for PBXProject "Tests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 94D8AF261E0C9AB4007D8806 /* Debug */, - 94D8AF271E0C9AB4007D8806 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 94D8AF281E0C9AB4007D8806 /* Build configuration list for PBXNativeTarget "Tests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 94D8AF291E0C9AB4007D8806 /* Debug */, - 94D8AF2A1E0C9AB4007D8806 /* Release */, - ); - defaultConfigurationIsVisible = 0; - }; - 94D8AF2B1E0C9AB4007D8806 /* Build configuration list for PBXNativeTarget "TestsTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 94D8AF2C1E0C9AB4007D8806 /* Debug */, - 94D8AF2D1E0C9AB4007D8806 /* Release */, - ); - defaultConfigurationIsVisible = 0; - }; -/* End XCConfigurationList section */ - }; - rootObject = 94D8AF031E0C9AB4007D8806 /* Project object */; -} diff --git a/Palindromes/Tests/Tests/AppDelegate.swift b/Palindromes/Tests/Tests/AppDelegate.swift deleted file mode 100644 index 481c72c62..000000000 --- a/Palindromes/Tests/Tests/AppDelegate.swift +++ /dev/null @@ -1,46 +0,0 @@ -// -// AppDelegate.swift -// Tests -// -// Created by Joshua Alvarado on 12/22/16. -// Copyright © 2016 Joshua Alvarado. All rights reserved. -// - -import UIKit - -@UIApplicationMain -class AppDelegate: UIResponder, UIApplicationDelegate { - - var window: UIWindow? - - - func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { - // Override point for customization after application launch. - return true - } - - func applicationWillResignActive(_ application: UIApplication) { - // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. - // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. - } - - func applicationDidEnterBackground(_ application: UIApplication) { - // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. - // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. - } - - func applicationWillEnterForeground(_ application: UIApplication) { - // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. - } - - func applicationDidBecomeActive(_ application: UIApplication) { - // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. - } - - func applicationWillTerminate(_ application: UIApplication) { - // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. - } - - -} - diff --git a/Palindromes/Tests/Tests/Assets.xcassets/AppIcon.appiconset/Contents.json b/Palindromes/Tests/Tests/Assets.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index 36d2c80d8..000000000 --- a/Palindromes/Tests/Tests/Assets.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,68 +0,0 @@ -{ - "images" : [ - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "60x60", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "60x60", - "scale" : "3x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "76x76", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "76x76", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/Palindromes/Tests/Tests/Base.lproj/LaunchScreen.storyboard b/Palindromes/Tests/Tests/Base.lproj/LaunchScreen.storyboard deleted file mode 100644 index fdf3f97d1..000000000 --- a/Palindromes/Tests/Tests/Base.lproj/LaunchScreen.storyboard +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Palindromes/Tests/Tests/Info.plist b/Palindromes/Tests/Tests/Info.plist deleted file mode 100644 index f197d509b..000000000 --- a/Palindromes/Tests/Tests/Info.plist +++ /dev/null @@ -1,45 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleVersion - 1 - LSRequiresIPhoneOS - - UILaunchStoryboardName - LaunchScreen - UIMainStoryboardFile - LaunchScreen - UIRequiredDeviceCapabilities - - armv7 - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - - From 9ac2d762802de647082a7b5977bad4bf9e1db8d6 Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Sat, 24 Dec 2016 03:39:44 -0800 Subject: [PATCH 0720/1679] Fixed up indentation and removed a few self references. --- .../BoyerMoore.playground/Contents.swift | 114 +++++++++--------- 1 file changed, 57 insertions(+), 57 deletions(-) diff --git a/Boyer-Moore/BoyerMoore.playground/Contents.swift b/Boyer-Moore/BoyerMoore.playground/Contents.swift index 362a298f9..9bbc7ec19 100644 --- a/Boyer-Moore/BoyerMoore.playground/Contents.swift +++ b/Boyer-Moore/BoyerMoore.playground/Contents.swift @@ -1,66 +1,66 @@ //: Playground - noun: a place where people can play extension String { - func indexOf(pattern: String) -> String.Index? { - // Cache the length of the search pattern because we're going to - // use it a few times and it's expensive to calculate. - let patternLength = pattern.characters.count - assert(patternLength > 0) - assert(patternLength <= self.characters.count) - - // Make the skip table. This table determines how far we skip ahead - // when a character from the pattern is found. - var skipTable = [Character: Int]() - for (i, c) in pattern.characters.enumerated() { - skipTable[c] = patternLength - i - 1 - } - - // This points at the last character in the pattern. - let p = pattern.index(before: pattern.endIndex) - let lastChar = pattern[p] - - // The pattern is scanned right-to-left, so skip ahead in the string by - // the length of the pattern. (Minus 1 because startIndex already points - // at the first character in the source string.) - var i = self.index(startIndex, offsetBy: patternLength - 1) + func indexOf(pattern: String) -> String.Index? { + // Cache the length of the search pattern because we're going to + // use it a few times and it's expensive to calculate. + let patternLength = pattern.characters.count + assert(patternLength > 0) + assert(patternLength <= characters.count) + + // Make the skip table. This table determines how far we skip ahead + // when a character from the pattern is found. + var skipTable = [Character: Int]() + for (i, c) in pattern.characters.enumerated() { + skipTable[c] = patternLength - i - 1 + } + + // This points at the last character in the pattern. + let p = pattern.index(before: pattern.endIndex) + let lastChar = pattern[p] + + // The pattern is scanned right-to-left, so skip ahead in the string by + // the length of the pattern. (Minus 1 because startIndex already points + // at the first character in the source string.) + var i = index(startIndex, offsetBy: patternLength - 1) + + // This is a helper function that steps backwards through both strings + // until we find a character that doesn’t match, or until we’ve reached + // the beginning of the pattern. + func backwards() -> String.Index? { + var q = p + var j = i + while q > pattern.startIndex { + j = index(before: j) + q = index(before: q) + if self[j] != pattern[q] { return nil } + } + return j + } + + // The main loop. Keep going until the end of the string is reached. + while i < endIndex { + let c = self[i] + + // Does the current character match the last character from the pattern? + if c == lastChar { - // This is a helper function that steps backwards through both strings - // until we find a character that doesn’t match, or until we’ve reached - // the beginning of the pattern. - func backwards() -> String.Index? { - var q = p - var j = i - while q > pattern.startIndex { - j = index(before: j) - q = index(before: q) - if self[j] != pattern[q] { return nil } - } - return j - } + // There is a possible match. Do a brute-force search backwards. + if let k = backwards() { return k } - // The main loop. Keep going until the end of the string is reached. - while i < self.endIndex { - let c = self[i] - - // Does the current character match the last character from the pattern? - if c == lastChar { - - // There is a possible match. Do a brute-force search backwards. - if let k = backwards() { return k } - - // If no match, we can only safely skip one character ahead. - i = index(after: i) - } else { - // The characters are not equal, so skip ahead. The amount to skip is - // determined by the skip table. If the character is not present in the - // pattern, we can skip ahead by the full pattern length. However, if - // the character *is* present in the pattern, there may be a match up - // ahead and we can't skip as far. - i = self.index(i, offsetBy: skipTable[c] ?? patternLength) - } - } - return nil + // If no match, we can only safely skip one character ahead. + i = index(after: i) + } else { + // The characters are not equal, so skip ahead. The amount to skip is + // determined by the skip table. If the character is not present in the + // pattern, we can skip ahead by the full pattern length. However, if + // the character *is* present in the pattern, there may be a match up + // ahead and we can't skip as far. + i = index(i, offsetBy: skipTable[c] ?? patternLength) + } } + return nil + } } // A few simple tests From 7a0417e86553dbe67495deba9f16f2ccdf14b3ea Mon Sep 17 00:00:00 2001 From: mmazzei Date: Sat, 24 Dec 2016 14:18:55 -0300 Subject: [PATCH 0721/1679] Added some tests. There are a failing test in the original code. --- Boyer-Moore/Tests/BoyerMooreTests.swift | 67 +++++ Boyer-Moore/Tests/Info.plist | 24 ++ .../Tests/Tests.xcodeproj/project.pbxproj | 269 ++++++++++++++++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/xcschemes/Tests.xcscheme | 90 ++++++ 5 files changed, 457 insertions(+) create mode 100755 Boyer-Moore/Tests/BoyerMooreTests.swift create mode 100644 Boyer-Moore/Tests/Info.plist create mode 100644 Boyer-Moore/Tests/Tests.xcodeproj/project.pbxproj create mode 100644 Boyer-Moore/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 Boyer-Moore/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme diff --git a/Boyer-Moore/Tests/BoyerMooreTests.swift b/Boyer-Moore/Tests/BoyerMooreTests.swift new file mode 100755 index 000000000..6536d1800 --- /dev/null +++ b/Boyer-Moore/Tests/BoyerMooreTests.swift @@ -0,0 +1,67 @@ +import Foundation +import XCTest + +class BoyerMooreTest: XCTestCase { + override func setUp() { + super.setUp() + } + + func assert(pattern: String, doesNotExistsIn string: String) { + let index = string.indexOf(pattern: pattern) + XCTAssertNil(index) + } + + func assert(pattern: String, existsIn string: String) { + let index = string.indexOf(pattern: pattern) + XCTAssertNotNil(index) + + let startIndex = index! + let endIndex = string.index(index!, offsetBy: pattern.characters.count) + let match = string.substring(with: startIndex.. + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/Boyer-Moore/Tests/Tests.xcodeproj/project.pbxproj b/Boyer-Moore/Tests/Tests.xcodeproj/project.pbxproj new file mode 100644 index 000000000..ff4f401a1 --- /dev/null +++ b/Boyer-Moore/Tests/Tests.xcodeproj/project.pbxproj @@ -0,0 +1,269 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 7B80C3CE1C77A256003CECC7 /* BoyerMooreTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C3CD1C77A256003CECC7 /* BoyerMooreTests.swift */; }; + 9AED567C1E0ED6DE00958DCC /* BoyerMoore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9AED567B1E0ED6DE00958DCC /* BoyerMoore.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 7B2BBC801C779D720067B71D /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 7B2BBC941C779E7B0067B71D /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; + 7B80C3CD1C77A256003CECC7 /* BoyerMooreTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BoyerMooreTests.swift; sourceTree = SOURCE_ROOT; }; + 9AED567B1E0ED6DE00958DCC /* BoyerMoore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BoyerMoore.swift; path = ../../BoyerMoore.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 7B2BBC7D1C779D720067B71D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 7B2BBC681C779D710067B71D = { + isa = PBXGroup; + children = ( + 7B2BBC831C779D720067B71D /* Tests */, + 7B2BBC721C779D710067B71D /* Products */, + ); + sourceTree = ""; + }; + 7B2BBC721C779D710067B71D /* Products */ = { + isa = PBXGroup; + children = ( + 7B2BBC801C779D720067B71D /* Tests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 7B2BBC831C779D720067B71D /* Tests */ = { + isa = PBXGroup; + children = ( + 9AED567B1E0ED6DE00958DCC /* BoyerMoore.swift */, + 7B80C3CD1C77A256003CECC7 /* BoyerMooreTests.swift */, + 7B2BBC941C779E7B0067B71D /* Info.plist */, + ); + name = Tests; + path = TestsTests; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 7B2BBC7F1C779D720067B71D /* Tests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */; + buildPhases = ( + 7B2BBC7C1C779D720067B71D /* Sources */, + 7B2BBC7D1C779D720067B71D /* Frameworks */, + 7B2BBC7E1C779D720067B71D /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Tests; + productName = TestsTests; + productReference = 7B2BBC801C779D720067B71D /* Tests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 7B2BBC691C779D710067B71D /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0720; + LastUpgradeCheck = 0800; + ORGANIZATIONNAME = "Swift Algorithm Club"; + TargetAttributes = { + 7B2BBC7F1C779D720067B71D = { + CreatedOnToolsVersion = 7.2; + LastSwiftMigration = 0800; + }; + }; + }; + buildConfigurationList = 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 7B2BBC681C779D710067B71D; + productRefGroup = 7B2BBC721C779D710067B71D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 7B2BBC7F1C779D720067B71D /* Tests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 7B2BBC7E1C779D720067B71D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 7B2BBC7C1C779D720067B71D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 9AED567C1E0ED6DE00958DCC /* BoyerMoore.swift in Sources */, + 7B80C3CE1C77A256003CECC7 /* BoyerMooreTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 7B2BBC871C779D720067B71D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 7B2BBC881C779D720067B71D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + }; + name = Release; + }; + 7B2BBC8D1C779D720067B71D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; + }; + name = Debug; + }; + 7B2BBC8E1C779D720067B71D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7B2BBC871C779D720067B71D /* Debug */, + 7B2BBC881C779D720067B71D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7B2BBC8D1C779D720067B71D /* Debug */, + 7B2BBC8E1C779D720067B71D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 7B2BBC691C779D710067B71D /* Project object */; +} diff --git a/Boyer-Moore/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Boyer-Moore/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..6c0ea8493 --- /dev/null +++ b/Boyer-Moore/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Boyer-Moore/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Boyer-Moore/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme new file mode 100644 index 000000000..14f27f777 --- /dev/null +++ b/Boyer-Moore/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -0,0 +1,90 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 2be65b442aafa1c96456322c50039dca8184a1e0 Mon Sep 17 00:00:00 2001 From: mmazzei Date: Sat, 24 Dec 2016 14:19:58 -0300 Subject: [PATCH 0722/1679] Fix failing test. --- Boyer-Moore/BoyerMoore.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Boyer-Moore/BoyerMoore.swift b/Boyer-Moore/BoyerMoore.swift index 4d7660ec3..d8ff4e6d2 100644 --- a/Boyer-Moore/BoyerMoore.swift +++ b/Boyer-Moore/BoyerMoore.swift @@ -61,7 +61,7 @@ extension String { // pattern, we can skip ahead by the full pattern length. However, if // the character *is* present in the pattern, there may be a match up // ahead and we can't skip as far. - i = self.index(i, offsetBy: skipTable[c] ?? patternLength) + i = index(i, offsetBy: skipTable[c] ?? patternLength, limitedBy: endIndex) ?? endIndex } } return nil From 4ca7ab9fc784afc018f6dde770fc54afc952664a Mon Sep 17 00:00:00 2001 From: mmazzei Date: Sat, 24 Dec 2016 14:22:59 -0300 Subject: [PATCH 0723/1679] Add Boyer-Moore-Horspool algorithm and tests. --- Boyer-Moore/BoyerMoore.swift | 14 +++++++++++--- Boyer-Moore/Tests/BoyerMooreHorspoolTests.swift | 14 ++++++++++++++ Boyer-Moore/Tests/BoyerMooreTests.swift | 14 ++++++++++++-- Boyer-Moore/Tests/Tests.xcodeproj/project.pbxproj | 4 ++++ 4 files changed, 41 insertions(+), 5 deletions(-) create mode 100644 Boyer-Moore/Tests/BoyerMooreHorspoolTests.swift diff --git a/Boyer-Moore/BoyerMoore.swift b/Boyer-Moore/BoyerMoore.swift index d8ff4e6d2..24842b59e 100644 --- a/Boyer-Moore/BoyerMoore.swift +++ b/Boyer-Moore/BoyerMoore.swift @@ -6,7 +6,7 @@ http://www.drdobbs.com/database/faster-string-searches/184408171 */ extension String { - func indexOf(pattern: String) -> String.Index? { + func indexOf(pattern: String, useHorspoolImprovement: Bool = false) -> String.Index? { // Cache the length of the search pattern because we're going to // use it a few times and it's expensive to calculate. let patternLength = pattern.characters.count @@ -53,8 +53,16 @@ extension String { // There is a possible match. Do a brute-force search backwards. if let k = backwards() { return k } - // If no match, we can only safely skip one character ahead. - i = index(after: i) + if !useHorspoolImprovement { + // If no match, we can only safely skip one character ahead. + i = index(after: i) + } + else { + // Ensure to jump at least one character (this is needed because the first + // character is in the skipTable, and `skipTable[lastChar] = 0`) + let jumpOffset = max(skipTable[c] ?? patternLength, 1) + i = index(i, offsetBy: jumpOffset, limitedBy: endIndex) ?? endIndex + } } else { // The characters are not equal, so skip ahead. The amount to skip is // determined by the skip table. If the character is not present in the diff --git a/Boyer-Moore/Tests/BoyerMooreHorspoolTests.swift b/Boyer-Moore/Tests/BoyerMooreHorspoolTests.swift new file mode 100644 index 000000000..3924494c7 --- /dev/null +++ b/Boyer-Moore/Tests/BoyerMooreHorspoolTests.swift @@ -0,0 +1,14 @@ +// +// BoyerMooreHorspoolTests.swift +// Tests +// +// Created by Matias Mazzei on 12/24/16. +// Copyright © 2016 Swift Algorithm Club. All rights reserved. +// + +class BoyerMooreHorspoolTests: BoyerMooreTest { + override func setUp() { + super.setUp() + useHorspoolImprovement = false + } +} diff --git a/Boyer-Moore/Tests/BoyerMooreTests.swift b/Boyer-Moore/Tests/BoyerMooreTests.swift index 6536d1800..8a2cbdc77 100755 --- a/Boyer-Moore/Tests/BoyerMooreTests.swift +++ b/Boyer-Moore/Tests/BoyerMooreTests.swift @@ -1,18 +1,28 @@ +// +// BoyerMooreHorspoolTests.swift +// Tests +// +// Created by Matias Mazzei on 12/24/16. +// Copyright © 2016 Swift Algorithm Club. All rights reserved. +// + import Foundation import XCTest class BoyerMooreTest: XCTestCase { + var useHorspoolImprovement = false + override func setUp() { super.setUp() } func assert(pattern: String, doesNotExistsIn string: String) { - let index = string.indexOf(pattern: pattern) + let index = string.indexOf(pattern: pattern, useHorspoolImprovement: useHorspoolImprovement) XCTAssertNil(index) } func assert(pattern: String, existsIn string: String) { - let index = string.indexOf(pattern: pattern) + let index = string.indexOf(pattern: pattern, useHorspoolImprovement: useHorspoolImprovement) XCTAssertNotNil(index) let startIndex = index! diff --git a/Boyer-Moore/Tests/Tests.xcodeproj/project.pbxproj b/Boyer-Moore/Tests/Tests.xcodeproj/project.pbxproj index ff4f401a1..f263d846a 100644 --- a/Boyer-Moore/Tests/Tests.xcodeproj/project.pbxproj +++ b/Boyer-Moore/Tests/Tests.xcodeproj/project.pbxproj @@ -9,6 +9,7 @@ /* Begin PBXBuildFile section */ 7B80C3CE1C77A256003CECC7 /* BoyerMooreTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C3CD1C77A256003CECC7 /* BoyerMooreTests.swift */; }; 9AED567C1E0ED6DE00958DCC /* BoyerMoore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9AED567B1E0ED6DE00958DCC /* BoyerMoore.swift */; }; + 9AED56801E0EE60B00958DCC /* BoyerMooreHorspoolTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9AED567F1E0EE60B00958DCC /* BoyerMooreHorspoolTests.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -16,6 +17,7 @@ 7B2BBC941C779E7B0067B71D /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; 7B80C3CD1C77A256003CECC7 /* BoyerMooreTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BoyerMooreTests.swift; sourceTree = SOURCE_ROOT; }; 9AED567B1E0ED6DE00958DCC /* BoyerMoore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BoyerMoore.swift; path = ../../BoyerMoore.swift; sourceTree = ""; }; + 9AED567F1E0EE60B00958DCC /* BoyerMooreHorspoolTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BoyerMooreHorspoolTests.swift; sourceTree = SOURCE_ROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -51,6 +53,7 @@ 9AED567B1E0ED6DE00958DCC /* BoyerMoore.swift */, 7B80C3CD1C77A256003CECC7 /* BoyerMooreTests.swift */, 7B2BBC941C779E7B0067B71D /* Info.plist */, + 9AED567F1E0EE60B00958DCC /* BoyerMooreHorspoolTests.swift */, ); name = Tests; path = TestsTests; @@ -125,6 +128,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 9AED56801E0EE60B00958DCC /* BoyerMooreHorspoolTests.swift in Sources */, 9AED567C1E0ED6DE00958DCC /* BoyerMoore.swift in Sources */, 7B80C3CE1C77A256003CECC7 /* BoyerMooreTests.swift in Sources */, ); From 36fba8ac3f4da6595783f5ebd4e72d19d1621c21 Mon Sep 17 00:00:00 2001 From: mmazzei Date: Sat, 24 Dec 2016 14:25:27 -0300 Subject: [PATCH 0724/1679] Add tests to .travis.yml --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 17655c21e..38099490e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,6 +12,7 @@ script: - xcodebuild test -project ./Array2D/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./AVL\ Tree/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Binary\ Search/Tests/Tests.xcodeproj -scheme Tests +- xcodebuild test -project ./Boyer-Moore/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Binary\ Search\ Tree/Solution\ 1/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Bloom\ Filter/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Bounded\ Priority\ Queue/Tests/Tests.xcodeproj -scheme Tests From c3cad8c13314eda236ca3d98650c5a79c89861e8 Mon Sep 17 00:00:00 2001 From: mmazzei Date: Sat, 24 Dec 2016 14:30:32 -0300 Subject: [PATCH 0725/1679] Updated README: updated algorithms and credits. --- Boyer-Moore/README.markdown | 92 ++++++++++++++++++++++++------------- 1 file changed, 59 insertions(+), 33 deletions(-) diff --git a/Boyer-Moore/README.markdown b/Boyer-Moore/README.markdown index 576f6d17b..08347e3e7 100644 --- a/Boyer-Moore/README.markdown +++ b/Boyer-Moore/README.markdown @@ -87,7 +87,7 @@ extension String { // pattern, we can skip ahead by the full pattern length. However, if // the character *is* present in the pattern, there may be a match up // ahead and we can't skip as far. - i = self.index(i, offsetBy: skipTable[c] ?? patternLength) + i = index(i, offsetBy: skipTable[c] ?? patternLength, limitedBy: endIndex) ?? endIndex } } return nil @@ -158,40 +158,66 @@ Here's an implementation of the Boyer-Moore-Horspool algorithm: ```swift extension String { func indexOf(pattern: String) -> String.Index? { - let patternLength = pattern.characters.count - assert(patternLength > 0) - assert(patternLength <= self.characters.count) + // Cache the length of the search pattern because we're going to + // use it a few times and it's expensive to calculate. + let patternLength = pattern.characters.count + assert(patternLength > 0) + assert(patternLength <= self.characters.count) - var skipTable = [Character: Int]() - for (i, c) in pattern.characters.enumerated() { - skipTable[c] = patternLength - i - 1 - } + // Make the skip table. This table determines how far we skip ahead + // when a character from the pattern is found. + var skipTable = [Character: Int]() + for (i, c) in pattern.characters.enumerated() { + skipTable[c] = patternLength - i - 1 + } - let p = pattern.index(before: pattern.endIndex) - let lastChar = pattern[p] - var i = self.index(startIndex, offsetBy: patternLength - 1) - - func backwards() -> String.Index? { - var q = p - var j = i - while q > pattern.startIndex { - j = index(before: j) - q = index(before: q) - if self[j] != pattern[q] { return nil } - } - return j - } + // This points at the last character in the pattern. + let p = pattern.index(before: pattern.endIndex) + let lastChar = pattern[p] - while i < self.endIndex { - let c = self[i] - if c == lastChar { - if let k = backwards() { return k } - i = index(after: i) - } else { - i = index(i, offsetBy: skipTable[c] ?? patternLength) - } - } - return nil + // The pattern is scanned right-to-left, so skip ahead in the string by + // the length of the pattern. (Minus 1 because startIndex already points + // at the first character in the source string.) + var i = self.index(startIndex, offsetBy: patternLength - 1) + + // This is a helper function that steps backwards through both strings + // until we find a character that doesn’t match, or until we’ve reached + // the beginning of the pattern. + func backwards() -> String.Index? { + var q = p + var j = i + while q > pattern.startIndex { + j = index(before: j) + q = index(before: q) + if self[j] != pattern[q] { return nil } + } + return j + } + + // The main loop. Keep going until the end of the string is reached. + while i < self.endIndex { + let c = self[i] + + // Does the current character match the last character from the pattern? + if c == lastChar { + + // There is a possible match. Do a brute-force search backwards. + if let k = backwards() { return k } + + // Ensure to jump at least one character (this is needed because the first + // character is in the skipTable, and `skipTable[lastChar] = 0`) + let jumpOffset = max(skipTable[c] ?? patternLength, 1) + i = index(i, offsetBy: jumpOffset, limitedBy: endIndex) ?? endIndex + } else { + // The characters are not equal, so skip ahead. The amount to skip is + // determined by the skip table. If the character is not present in the + // pattern, we can skip ahead by the full pattern length. However, if + // the character *is* present in the pattern, there may be a match up + // ahead and we can't skip as far. + i = index(i, offsetBy: skipTable[c] ?? patternLength, limitedBy: endIndex) ?? endIndex + } + } + return nil } } ``` @@ -200,4 +226,4 @@ In practice, the Horspool version of the algorithm tends to perform a little bet Credits: This code is based on the paper: [R. N. Horspool (1980). "Practical fast searching in strings". Software - Practice & Experience 10 (6): 501–506.](http://www.cin.br/~paguso/courses/if767/bib/Horspool_1980.pdf) -_Written for Swift Algorithm Club by Matthijs Hollemans, updated by Andreas Neusüß_ +_Written for Swift Algorithm Club by Matthijs Hollemans, updated by Andreas Neusüß_, [Matías Mazzei](https://github.com/mmazzei). From 78e78a4b9e81b57698d95e68d8abbd86c218ef95 Mon Sep 17 00:00:00 2001 From: mmazzei Date: Sat, 24 Dec 2016 14:42:54 -0300 Subject: [PATCH 0726/1679] Fix swiftlint warnings. --- Boyer-Moore/Tests/BoyerMooreTests.swift | 20 +++++++++---------- .../Tests/Tests.xcodeproj/project.pbxproj | 17 ++++++++++++++++ 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/Boyer-Moore/Tests/BoyerMooreTests.swift b/Boyer-Moore/Tests/BoyerMooreTests.swift index 8a2cbdc77..f1638afcd 100755 --- a/Boyer-Moore/Tests/BoyerMooreTests.swift +++ b/Boyer-Moore/Tests/BoyerMooreTests.swift @@ -30,48 +30,48 @@ class BoyerMooreTest: XCTestCase { let match = string.substring(with: startIndex.. Date: Sat, 24 Dec 2016 14:47:56 -0300 Subject: [PATCH 0727/1679] Xcode option 'Uncheck Autocreate schemes' unchecked. --- .../xcshareddata/WorkspaceSettings.xcsettings | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 Boyer-Moore/Tests/Tests.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings diff --git a/Boyer-Moore/Tests/Tests.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/Boyer-Moore/Tests/Tests.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 000000000..08de0be8d --- /dev/null +++ b/Boyer-Moore/Tests/Tests.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded + + + From cf45ebd0dd84a842a1d032f7545e70c76b2cbb79 Mon Sep 17 00:00:00 2001 From: mmazzei Date: Sun, 25 Dec 2016 15:08:31 -0300 Subject: [PATCH 0728/1679] Update as requested in code review. --- .../BoyerMoore.playground/Contents.swift | 143 ++++++++++-------- Boyer-Moore/BoyerMoore.swift | 35 ++--- Boyer-Moore/README.markdown | 28 ++-- Boyer-Moore/Tests/BoyerMooreTests.swift | 22 ++- 4 files changed, 135 insertions(+), 93 deletions(-) diff --git a/Boyer-Moore/BoyerMoore.playground/Contents.swift b/Boyer-Moore/BoyerMoore.playground/Contents.swift index 9bbc7ec19..f1ae5018e 100644 --- a/Boyer-Moore/BoyerMoore.playground/Contents.swift +++ b/Boyer-Moore/BoyerMoore.playground/Contents.swift @@ -1,72 +1,91 @@ //: Playground - noun: a place where people can play +/* + Boyer-Moore string search + + This code is based on the article "Faster String Searches" by Costas Menico + from Dr Dobb's magazine, July 1989. + http://www.drdobbs.com/database/faster-string-searches/184408171 +*/ extension String { - func indexOf(pattern: String) -> String.Index? { - // Cache the length of the search pattern because we're going to - // use it a few times and it's expensive to calculate. - let patternLength = pattern.characters.count - assert(patternLength > 0) - assert(patternLength <= characters.count) - - // Make the skip table. This table determines how far we skip ahead - // when a character from the pattern is found. - var skipTable = [Character: Int]() - for (i, c) in pattern.characters.enumerated() { - skipTable[c] = patternLength - i - 1 - } - - // This points at the last character in the pattern. - let p = pattern.index(before: pattern.endIndex) - let lastChar = pattern[p] - - // The pattern is scanned right-to-left, so skip ahead in the string by - // the length of the pattern. (Minus 1 because startIndex already points - // at the first character in the source string.) - var i = index(startIndex, offsetBy: patternLength - 1) - - // This is a helper function that steps backwards through both strings - // until we find a character that doesn’t match, or until we’ve reached - // the beginning of the pattern. - func backwards() -> String.Index? { - var q = p - var j = i - while q > pattern.startIndex { - j = index(before: j) - q = index(before: q) - if self[j] != pattern[q] { return nil } - } - return j - } - - // The main loop. Keep going until the end of the string is reached. - while i < endIndex { - let c = self[i] - - // Does the current character match the last character from the pattern? - if c == lastChar { - - // There is a possible match. Do a brute-force search backwards. - if let k = backwards() { return k } - - // If no match, we can only safely skip one character ahead. - i = index(after: i) - } else { - // The characters are not equal, so skip ahead. The amount to skip is - // determined by the skip table. If the character is not present in the - // pattern, we can skip ahead by the full pattern length. However, if - // the character *is* present in the pattern, there may be a match up - // ahead and we can't skip as far. - i = index(i, offsetBy: skipTable[c] ?? patternLength) - } + func index(of pattern: String, usingHorspoolImprovement: Bool = false) -> Index? { + // There are no possible match in an empty string + guard !isEmpty else { return nil } + + // Cache the length of the search pattern because we're going to + // use it a few times and it's expensive to calculate. + let patternLength = pattern.characters.count + guard patternLength > 0, patternLength <= characters.count else { return nil } + + // Make the skip table. This table determines how far we skip ahead + // when a character from the pattern is found. + var skipTable = [Character: Int]() + for (i, c) in pattern.characters.enumerated() { + skipTable[c] = patternLength - i - 1 + } + + // This points at the last character in the pattern. + let p = pattern.index(before: pattern.endIndex) + let lastChar = pattern[p] + + // The pattern is scanned right-to-left, so skip ahead in the string by + // the length of the pattern. (Minus 1 because startIndex already points + // at the first character in the source string.) + var i = index(startIndex, offsetBy: patternLength - 1) + + // This is a helper function that steps backwards through both strings + // until we find a character that doesn’t match, or until we’ve reached + // the beginning of the pattern. + func backwards() -> Index? { + var q = p + var j = i + while q > pattern.startIndex { + j = index(before: j) + q = index(before: q) + if self[j] != pattern[q] { return nil } + } + return j + } + + // The main loop. Keep going until the end of the string is reached. + while i < endIndex { + let c = self[i] + + // Does the current character match the last character from the pattern? + if c == lastChar { + + // There is a possible match. Do a brute-force search backwards. + if let k = backwards() { return k } + + if !usingHorspoolImprovement { + // If no match, we can only safely skip one character ahead. + i = index(after: i) + } else { + // Ensure to jump at least one character (this is needed because the first + // character is in the skipTable, and `skipTable[lastChar] = 0`) + let jumpOffset = max(skipTable[c] ?? patternLength, 1) + i = index(i, offsetBy: jumpOffset, limitedBy: endIndex) ?? endIndex + } + } else { + // The characters are not equal, so skip ahead. The amount to skip is + // determined by the skip table. If the character is not present in the + // pattern, we can skip ahead by the full pattern length. However, if + // the character *is* present in the pattern, there may be a match up + // ahead and we can't skip as far. + i = index(i, offsetBy: skipTable[c] ?? patternLength, limitedBy: endIndex) ?? endIndex + } + } + return nil } - return nil - } } // A few simple tests -let s = "Hello, World" -s.indexOf(pattern: "World") // 7 +let str = "Hello, World" +str.index(of: "World") // 7 let animals = "🐶🐔🐷🐮🐱" -animals.indexOf(pattern: "🐮") // 6 +animals.index(of: "🐮") // 6 + +let lorem = "Lorem ipsum dolor sit amet" +lorem.index(of: "sit", usingHorspoolImprovement: true) // 18 diff --git a/Boyer-Moore/BoyerMoore.swift b/Boyer-Moore/BoyerMoore.swift index 24842b59e..2f6bf1392 100644 --- a/Boyer-Moore/BoyerMoore.swift +++ b/Boyer-Moore/BoyerMoore.swift @@ -6,33 +6,35 @@ http://www.drdobbs.com/database/faster-string-searches/184408171 */ extension String { - func indexOf(pattern: String, useHorspoolImprovement: Bool = false) -> String.Index? { + func index(of pattern: String, usingHorspoolImprovement: Bool = false) -> Index? { + // There are no possible match in an empty string + guard !isEmpty else { return nil } + // Cache the length of the search pattern because we're going to // use it a few times and it's expensive to calculate. let patternLength = pattern.characters.count - assert(patternLength > 0) - assert(patternLength <= self.characters.count) - + guard patternLength > 0, patternLength <= characters.count else { return nil } + // Make the skip table. This table determines how far we skip ahead // when a character from the pattern is found. var skipTable = [Character: Int]() for (i, c) in pattern.characters.enumerated() { skipTable[c] = patternLength - i - 1 } - + // This points at the last character in the pattern. let p = pattern.index(before: pattern.endIndex) let lastChar = pattern[p] - + // The pattern is scanned right-to-left, so skip ahead in the string by // the length of the pattern. (Minus 1 because startIndex already points // at the first character in the source string.) - var i = self.index(startIndex, offsetBy: patternLength - 1) - + var i = index(startIndex, offsetBy: patternLength - 1) + // This is a helper function that steps backwards through both strings // until we find a character that doesn’t match, or until we’ve reached // the beginning of the pattern. - func backwards() -> String.Index? { + func backwards() -> Index? { var q = p var j = i while q > pattern.startIndex { @@ -42,22 +44,21 @@ extension String { } return j } - + // The main loop. Keep going until the end of the string is reached. - while i < self.endIndex { + while i < endIndex { let c = self[i] - + // Does the current character match the last character from the pattern? if c == lastChar { - + // There is a possible match. Do a brute-force search backwards. if let k = backwards() { return k } - - if !useHorspoolImprovement { + + if !usingHorspoolImprovement { // If no match, we can only safely skip one character ahead. i = index(after: i) - } - else { + } else { // Ensure to jump at least one character (this is needed because the first // character is in the skipTable, and `skipTable[lastChar] = 0`) let jumpOffset = max(skipTable[c] ?? patternLength, 1) diff --git a/Boyer-Moore/README.markdown b/Boyer-Moore/README.markdown index 08347e3e7..2cb42b0bd 100644 --- a/Boyer-Moore/README.markdown +++ b/Boyer-Moore/README.markdown @@ -32,12 +32,14 @@ Here's how you could write it in Swift: ```swift extension String { - func indexOf(pattern: String) -> String.Index? { + func index(of pattern: String) -> Index? { + // There are no possible match in an empty string + guard !isEmpty else { return nil } + // Cache the length of the search pattern because we're going to // use it a few times and it's expensive to calculate. let patternLength = pattern.characters.count - assert(patternLength > 0) - assert(patternLength <= self.characters.count) + guard patternLength > 0, patternLength <= characters.count else { return nil } // Make the skip table. This table determines how far we skip ahead // when a character from the pattern is found. @@ -53,12 +55,12 @@ extension String { // The pattern is scanned right-to-left, so skip ahead in the string by // the length of the pattern. (Minus 1 because startIndex already points // at the first character in the source string.) - var i = self.index(startIndex, offsetBy: patternLength - 1) + var i = index(startIndex, offsetBy: patternLength - 1) // This is a helper function that steps backwards through both strings // until we find a character that doesn’t match, or until we’ve reached // the beginning of the pattern. - func backwards() -> String.Index? { + func backwards() -> Index? { var q = p var j = i while q > pattern.startIndex { @@ -70,7 +72,7 @@ extension String { } // The main loop. Keep going until the end of the string is reached. - while i < self.endIndex { + while i < endIndex { let c = self[i] // Does the current character match the last character from the pattern? @@ -157,12 +159,14 @@ Here's an implementation of the Boyer-Moore-Horspool algorithm: ```swift extension String { - func indexOf(pattern: String) -> String.Index? { + func index(of pattern: String) -> Index? { + // There are no possible match in an empty string + guard !isEmpty else { return nil } + // Cache the length of the search pattern because we're going to // use it a few times and it's expensive to calculate. let patternLength = pattern.characters.count - assert(patternLength > 0) - assert(patternLength <= self.characters.count) + guard patternLength > 0, patternLength <= characters.count else { return nil } // Make the skip table. This table determines how far we skip ahead // when a character from the pattern is found. @@ -178,12 +182,12 @@ extension String { // The pattern is scanned right-to-left, so skip ahead in the string by // the length of the pattern. (Minus 1 because startIndex already points // at the first character in the source string.) - var i = self.index(startIndex, offsetBy: patternLength - 1) + var i = index(startIndex, offsetBy: patternLength - 1) // This is a helper function that steps backwards through both strings // until we find a character that doesn’t match, or until we’ve reached // the beginning of the pattern. - func backwards() -> String.Index? { + func backwards() -> Index? { var q = p var j = i while q > pattern.startIndex { @@ -195,7 +199,7 @@ extension String { } // The main loop. Keep going until the end of the string is reached. - while i < self.endIndex { + while i < endIndex { let c = self[i] // Does the current character match the last character from the pattern? diff --git a/Boyer-Moore/Tests/BoyerMooreTests.swift b/Boyer-Moore/Tests/BoyerMooreTests.swift index f1638afcd..9efe60874 100755 --- a/Boyer-Moore/Tests/BoyerMooreTests.swift +++ b/Boyer-Moore/Tests/BoyerMooreTests.swift @@ -17,12 +17,12 @@ class BoyerMooreTest: XCTestCase { } func assert(pattern: String, doesNotExistsIn string: String) { - let index = string.indexOf(pattern: pattern, useHorspoolImprovement: useHorspoolImprovement) + let index = string.index(of: pattern, usingHorspoolImprovement: useHorspoolImprovement) XCTAssertNil(index) } func assert(pattern: String, existsIn string: String) { - let index = string.indexOf(pattern: pattern, useHorspoolImprovement: useHorspoolImprovement) + let index = string.index(of: pattern, usingHorspoolImprovement: useHorspoolImprovement) XCTAssertNotNil(index) let startIndex = index! @@ -31,6 +31,24 @@ class BoyerMooreTest: XCTestCase { XCTAssertEqual(match, pattern) } + func testSearchPatternInEmptyString() { + let string = "" + let pattern = "ABCDEF" + assert(pattern: pattern, doesNotExistsIn: string) + } + + func testSearchEmptyPatternString() { + let string = "ABCDEF" + let pattern = "" + assert(pattern: pattern, doesNotExistsIn: string) + } + + func testSearchPatternLongerThanString() { + let string = "ABC" + let pattern = "ABCDEF" + assert(pattern: pattern, doesNotExistsIn: string) + } + func testSearchTheSameString() { let string = "ABCDEF" let pattern = "ABCDEF" From 960bca13c0207014040b96ba22e586b688279be9 Mon Sep 17 00:00:00 2001 From: mmazzei Date: Sun, 25 Dec 2016 17:58:00 -0300 Subject: [PATCH 0729/1679] Removed redundant validation. --- Boyer-Moore/BoyerMoore.playground/Contents.swift | 3 --- Boyer-Moore/BoyerMoore.swift | 3 --- Boyer-Moore/README.markdown | 6 ------ 3 files changed, 12 deletions(-) diff --git a/Boyer-Moore/BoyerMoore.playground/Contents.swift b/Boyer-Moore/BoyerMoore.playground/Contents.swift index f1ae5018e..f553e1a00 100644 --- a/Boyer-Moore/BoyerMoore.playground/Contents.swift +++ b/Boyer-Moore/BoyerMoore.playground/Contents.swift @@ -9,9 +9,6 @@ */ extension String { func index(of pattern: String, usingHorspoolImprovement: Bool = false) -> Index? { - // There are no possible match in an empty string - guard !isEmpty else { return nil } - // Cache the length of the search pattern because we're going to // use it a few times and it's expensive to calculate. let patternLength = pattern.characters.count diff --git a/Boyer-Moore/BoyerMoore.swift b/Boyer-Moore/BoyerMoore.swift index 2f6bf1392..af8aea9d9 100644 --- a/Boyer-Moore/BoyerMoore.swift +++ b/Boyer-Moore/BoyerMoore.swift @@ -7,9 +7,6 @@ */ extension String { func index(of pattern: String, usingHorspoolImprovement: Bool = false) -> Index? { - // There are no possible match in an empty string - guard !isEmpty else { return nil } - // Cache the length of the search pattern because we're going to // use it a few times and it's expensive to calculate. let patternLength = pattern.characters.count diff --git a/Boyer-Moore/README.markdown b/Boyer-Moore/README.markdown index 2cb42b0bd..e821b812e 100644 --- a/Boyer-Moore/README.markdown +++ b/Boyer-Moore/README.markdown @@ -33,9 +33,6 @@ Here's how you could write it in Swift: ```swift extension String { func index(of pattern: String) -> Index? { - // There are no possible match in an empty string - guard !isEmpty else { return nil } - // Cache the length of the search pattern because we're going to // use it a few times and it's expensive to calculate. let patternLength = pattern.characters.count @@ -160,9 +157,6 @@ Here's an implementation of the Boyer-Moore-Horspool algorithm: ```swift extension String { func index(of pattern: String) -> Index? { - // There are no possible match in an empty string - guard !isEmpty else { return nil } - // Cache the length of the search pattern because we're going to // use it a few times and it's expensive to calculate. let patternLength = pattern.characters.count From f618414c65e8b45f7f11010ad988e733cea23395 Mon Sep 17 00:00:00 2001 From: Joshua Alvarado Date: Mon, 26 Dec 2016 11:31:54 -0700 Subject: [PATCH 0730/1679] Add shared scheme to test Project for tests --- .../xcshareddata/xcschemes/Test.xcscheme | 99 +++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 Palindromes/Test/Test.xcodeproj/xcshareddata/xcschemes/Test.xcscheme diff --git a/Palindromes/Test/Test.xcodeproj/xcshareddata/xcschemes/Test.xcscheme b/Palindromes/Test/Test.xcodeproj/xcshareddata/xcschemes/Test.xcscheme new file mode 100644 index 000000000..9a1b39e69 --- /dev/null +++ b/Palindromes/Test/Test.xcodeproj/xcshareddata/xcschemes/Test.xcscheme @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From d8b96a480aeaefd3ead13c409c6957071ecfc931 Mon Sep 17 00:00:00 2001 From: Nagasawa Hiroki Date: Wed, 28 Dec 2016 08:34:51 +0900 Subject: [PATCH 0731/1679] Fix Access Control position in AVLTree --- AVL Tree/AVLTree.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AVL Tree/AVLTree.swift b/AVL Tree/AVLTree.swift index b4b97f0d6..cfcf114c0 100644 --- a/AVL Tree/AVLTree.swift +++ b/AVL Tree/AVLTree.swift @@ -29,7 +29,7 @@ public class TreeNode { internal var leftChild: Node? internal var rightChild: Node? fileprivate var height: Int - weak fileprivate var parent: Node? + fileprivate weak var parent: Node? public init(key: Key, payload: Payload?, leftChild: Node?, rightChild: Node?, parent: Node?, height: Int) { self.key = key From 03f176083b22b1ba2c40e0fb0f21af8d0451424b Mon Sep 17 00:00:00 2001 From: Nagasawa Hiroki Date: Wed, 28 Dec 2016 10:16:36 +0900 Subject: [PATCH 0732/1679] Make each steps clear --- Red-Black Tree/README.markdown | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/Red-Black Tree/README.markdown b/Red-Black Tree/README.markdown index d4e86a095..05993f016 100644 --- a/Red-Black Tree/README.markdown +++ b/Red-Black Tree/README.markdown @@ -49,16 +49,17 @@ n n n n n b We create a new node with the value to be inserted into the tree. The color of this new node is always red. We perform a standard BST insert with this node. Now the three might not be a valid RBT anymore. -We now go through several insertion steps in order to make the tree valid again. We call the just inserted node n. -1. We check if n is the rootNode, if so we paint it black and we are done. If not we go to step 2. +We now go through several insertion steps in order to make the tree valid again. We call the just inserted node n. + +**Step 1**: We check if n is the rootNode, if so we paint it black and we are done. If not we go to Step 2. We now know that n at least has a parent as it is not the rootNode. -2. We check if the parent of n is black if so we are done. If not we go to step 3. +**Step 2**: We check if the parent of n is black if so we are done. If not we go to Step 3. We now know the parent is also not the root node as the parent is red. Thus n also has a grandparent and thus also an uncle as every node has two children. This uncle may however be a nullLeaf -3. We check if n's uncle is red. If not we go to 4. If n's uncle is indeed red we recolor uncle and parent to black and n's grandparent to red. We now go back to step 1 performing the same logic on n's grandparent. +**Step 3**: We check if n's uncle is red. If not we go to Step 4. If n's uncle is indeed red we recolor uncle and parent to black and n's grandparent to red. We now go back to step 1 performing the same logic on n's grandparent. From here there are four cases: - **The left left case.** n's parent is the left child of its parent and n is the left child of its parent. @@ -66,14 +67,14 @@ From here there are four cases: - **The right right case** n's parent is the right child of its parent and n is the right child of its parent. - **The right left case** n's parent is the right child of its parent and n is the left child of its parent. -4. Step 4 checks if either the **left right** case or the **right left** case applies to the current situation. - - If we find the **left right case**, we left rotate n's parent and go to step 5 while setting n to n's parent. (This transforms the **left right** case into the **left left** case) - - If we find the **right left case**, we right rotate n's parent and go to step 5 while setting n to n's parent. (This transforms the **right left** case into the **right right** case) - - If we find neither of these two we proceed to step 5. +**Step 4**: checks if either the **left right** case or the **right left** case applies to the current situation. + - If we find the **left right case**, we left rotate n's parent and go to Step 5 while setting n to n's parent. (This transforms the **left right** case into the **left left** case) + - If we find the **right left case**, we right rotate n's parent and go to Step 5 while setting n to n's parent. (This transforms the **right left** case into the **right right** case) + - If we find neither of these two we proceed to Step 5. n's parent is now red, while n's grandparent is black. -5. We swap the colors of n's parent and grandparent. +**Step 5**: We swap the colors of n's parent and grandparent. - We either right rotate n's grandparent in case of the **left left** case - Or we left rotate n's grandparent in case of the **right right** case From f8857406b07e0012c96d862e297669a04aba195a Mon Sep 17 00:00:00 2001 From: Mohamed Emad Hegab Date: Wed, 28 Dec 2016 10:55:57 +0100 Subject: [PATCH 0733/1679] swift 3 update --- Select Minimum Maximum/README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Select Minimum Maximum/README.markdown b/Select Minimum Maximum/README.markdown index 5e006f50e..a67f4ec8e 100644 --- a/Select Minimum Maximum/README.markdown +++ b/Select Minimum Maximum/README.markdown @@ -89,7 +89,7 @@ The result is a minimum of `3` and a maximum of `9`. Here is a simple implementation in Swift: ```swift -func minimumMaximum(var array: [T]) -> (minimum: T, maximum: T)? { +func minimumMaximum(_ array: [T]) -> (minimum: T, maximum: T)? { guard !array.isEmpty else { return nil } From 411cbd208df10cb6a9bd9516bba3bae66173d7a6 Mon Sep 17 00:00:00 2001 From: mattthousand Date: Wed, 28 Dec 2016 13:33:29 -0500 Subject: [PATCH 0734/1679] Convert to swift 3.0 syntax. --- Heap Sort/HeapSort.playground/Contents.swift | 21 +++++++++++++++++++ Heap Sort/HeapSort.swift | 6 +++--- .../Tests/Tests.xcodeproj/project.pbxproj | 10 ++++++++- .../xcshareddata/xcschemes/Tests.xcscheme | 2 +- Heap/Heap.swift | 18 ++++++++-------- 5 files changed, 43 insertions(+), 14 deletions(-) create mode 100644 Heap Sort/HeapSort.playground/Contents.swift diff --git a/Heap Sort/HeapSort.playground/Contents.swift b/Heap Sort/HeapSort.playground/Contents.swift new file mode 100644 index 000000000..5dbe2e14f --- /dev/null +++ b/Heap Sort/HeapSort.playground/Contents.swift @@ -0,0 +1,21 @@ +//: Playground - noun: a place where people can play + +extension Heap { + public mutating func sort() -> [T] { + for i in (elements.count - 1).stride(through: 1, by: -1) { + swap(&elements[0], &elements[i]) + shiftDown(index: 0, heapSize: i) + } + return elements + } +} + +/* + Sorts an array using a heap. + Heapsort can be performed in-place, but it is not a stable sort. + */ +public func heapsort(a: [T], _ sort: (T, T) -> Bool) -> [T] { + let reverseOrder = { i1, i2 in sort(i2, i1) } + var h = Heap(array: a, sort: reverseOrder) + return h.sort() +} diff --git a/Heap Sort/HeapSort.swift b/Heap Sort/HeapSort.swift index ec5b4a478..3fbaab14d 100644 --- a/Heap Sort/HeapSort.swift +++ b/Heap Sort/HeapSort.swift @@ -1,8 +1,8 @@ extension Heap { public mutating func sort() -> [T] { - for i in (elements.count - 1).stride(through: 1, by: -1) { + for i in stride(from: (elements.count - 1), through: 1, by: -1) { swap(&elements[0], &elements[i]) - shiftDown(index: 0, heapSize: i) + shiftDown(0, heapSize: i) } return elements } @@ -12,7 +12,7 @@ extension Heap { Sorts an array using a heap. Heapsort can be performed in-place, but it is not a stable sort. */ -public func heapsort(a: [T], _ sort: (T, T) -> Bool) -> [T] { +public func heapsort(_ a: [T], _ sort: @escaping (T, T) -> Bool) -> [T] { let reverseOrder = { i1, i2 in sort(i2, i1) } var h = Heap(array: a, sort: reverseOrder) return h.sort() diff --git a/Heap Sort/Tests/Tests.xcodeproj/project.pbxproj b/Heap Sort/Tests/Tests.xcodeproj/project.pbxproj index 454222c49..f7f101cd6 100644 --- a/Heap Sort/Tests/Tests.xcodeproj/project.pbxproj +++ b/Heap Sort/Tests/Tests.xcodeproj/project.pbxproj @@ -86,11 +86,12 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; - LastUpgradeCheck = 0720; + LastUpgradeCheck = 0820; ORGANIZATIONNAME = "Swift Algorithm Club"; TargetAttributes = { 7B2BBC7F1C779D720067B71D = { CreatedOnToolsVersion = 7.2; + LastSwiftMigration = 0820; }; }; }; @@ -149,8 +150,10 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; @@ -193,8 +196,10 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; @@ -213,6 +218,7 @@ MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; }; name = Release; }; @@ -224,6 +230,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -235,6 +242,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Release; }; diff --git a/Heap Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Heap Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme index 8ef8d8581..dfcf6de42 100644 --- a/Heap Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme +++ b/Heap Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -1,6 +1,6 @@ { fileprivate mutating func buildHeap(fromArray array: [T]) { elements = array for i in stride(from: (elements.count/2 - 1), through: 0, by: -1) { - shiftDown(index: i, heapSize: elements.count) + shiftDown(i, heapSize: elements.count) } } @@ -98,7 +98,7 @@ public struct Heap { */ public mutating func insert(_ value: T) { elements.append(value) - shiftUp(index: elements.count - 1) + shiftUp(elements.count - 1) } public mutating func insert(_ sequence: S) where S.Iterator.Element == T { @@ -116,7 +116,7 @@ public struct Heap { assert(isOrderedBefore(value, elements[i])) elements[i] = value - shiftUp(index: i) + shiftUp(i) } /** @@ -142,14 +142,14 @@ public struct Heap { * Removes an arbitrary node from the heap. Performance: O(log n). You need * to know the node's index, which may actually take O(n) steps to find. */ - public mutating func removeAt(index: Int) -> T? { + public mutating func removeAt(_ index: Int) -> T? { guard index < elements.count else { return nil } let size = elements.count - 1 if index != size { swap(&elements[index], &elements[size]) - shiftDown(index: index, heapSize: size) - shiftUp(index: index) + shiftDown(index, heapSize: size) + shiftUp(index) } return elements.removeLast() } @@ -158,7 +158,7 @@ public struct Heap { * Takes a child node and looks at its parents; if a parent is not larger * (max-heap) or not smaller (min-heap) than the child, we exchange them. */ - mutating func shiftUp(index: Int) { + mutating func shiftUp(_ index: Int) { var childIndex = index let child = elements[childIndex] var parentIndex = self.parentIndex(ofIndex: childIndex) @@ -173,14 +173,14 @@ public struct Heap { } mutating func shiftDown() { - shiftDown(index: 0, heapSize: elements.count) + shiftDown(0, heapSize: elements.count) } /** * Looks at a parent node and makes sure it is still larger (max-heap) or * smaller (min-heap) than its childeren. */ - mutating func shiftDown(index: Int, heapSize: Int) { + mutating func shiftDown(_ index: Int, heapSize: Int) { var parentIndex = index while true { From 75d866a0b9df43a2803bcad6f25f3151f51b73c2 Mon Sep 17 00:00:00 2001 From: mattthousand Date: Wed, 28 Dec 2016 13:35:51 -0500 Subject: [PATCH 0735/1679] Update README. --- Heap Sort/README.markdown | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Heap Sort/README.markdown b/Heap Sort/README.markdown index 3d8b0f394..5f047f82b 100644 --- a/Heap Sort/README.markdown +++ b/Heap Sort/README.markdown @@ -48,13 +48,13 @@ Here's how you can implement heap sort in Swift: ```swift extension Heap { - public mutating func sort() -> [T] { - for i in (elements.count - 1).stride(through: 1, by: -1) { - swap(&elements[0], &elements[i]) - shiftDown(index: 0, heapSize: i) - } + public mutating func sort() -> [T] { + for i in stride(from: (elements.count - 1), through: 1, by: -1) { + swap(&elements[0], &elements[i]) + shiftDown(0, heapSize: i) + } return elements - } + } } ``` @@ -70,10 +70,10 @@ Because we need a max-heap to sort from low-to-high, you need to give `Heap` the We can write a handy helper function for that: ```swift -public func heapsort(a: [T], _ sort: (T, T) -> Bool) -> [T] { - let reverseOrder = { i1, i2 in sort(i2, i1) } - var h = Heap(array: a, sort: reverseOrder) - return h.sort() +public func heapsort(_ a: [T], _ sort: @escaping (T, T) -> Bool) -> [T] { + let reverseOrder = { i1, i2 in sort(i2, i1) } + var h = Heap(array: a, sort: reverseOrder) + return h.sort() } ``` From bb5cbe6e839501edbc6a75d9c99748511b369040 Mon Sep 17 00:00:00 2001 From: mattthousand Date: Wed, 28 Dec 2016 13:39:53 -0500 Subject: [PATCH 0736/1679] Uncomment .travis.yml. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 7b5faffa6..79eb3e051 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,7 +23,7 @@ script: # - xcodebuild test -project ./Depth-First\ Search/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Graph/Graph.xcodeproj -scheme GraphTests # - xcodebuild test -project ./Heap/Tests/Tests.xcodeproj -scheme Tests -# - xcodebuild test -project ./Heap\ Sort/Tests/Tests.xcodeproj -scheme Tests +- xcodebuild test -project ./Heap\ Sort/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Insertion\ Sort/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./K-Means/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Linked\ List/Tests/Tests.xcodeproj -scheme Tests From 6a15e73d72369d44d1b5b118c1e2f45f04b504b7 Mon Sep 17 00:00:00 2001 From: mattthousand Date: Wed, 28 Dec 2016 13:41:50 -0500 Subject: [PATCH 0737/1679] Remove playground. --- Heap Sort/HeapSort.playground/Contents.swift | 21 -------------------- 1 file changed, 21 deletions(-) delete mode 100644 Heap Sort/HeapSort.playground/Contents.swift diff --git a/Heap Sort/HeapSort.playground/Contents.swift b/Heap Sort/HeapSort.playground/Contents.swift deleted file mode 100644 index 5dbe2e14f..000000000 --- a/Heap Sort/HeapSort.playground/Contents.swift +++ /dev/null @@ -1,21 +0,0 @@ -//: Playground - noun: a place where people can play - -extension Heap { - public mutating func sort() -> [T] { - for i in (elements.count - 1).stride(through: 1, by: -1) { - swap(&elements[0], &elements[i]) - shiftDown(index: 0, heapSize: i) - } - return elements - } -} - -/* - Sorts an array using a heap. - Heapsort can be performed in-place, but it is not a stable sort. - */ -public func heapsort(a: [T], _ sort: (T, T) -> Bool) -> [T] { - let reverseOrder = { i1, i2 in sort(i2, i1) } - var h = Heap(array: a, sort: reverseOrder) - return h.sort() -} From 356844c7d61630b4aa09eb9e3d3d785593cf86e2 Mon Sep 17 00:00:00 2001 From: cruisediary Date: Thu, 29 Dec 2016 18:18:14 +0900 Subject: [PATCH 0738/1679] Updating to Swift3 (enum lowercase) - playground - README.md - some.swift file --- .../Contents.swift | 2 +- .../Sources/BinarySearchTree.swift | 54 ++++++------- .../Solution 2/BinarySearchTree.swift | 54 ++++++------- .../CountingSort.playground/Contents.swift | 6 +- Counting Sort/CountingSort.swift | 4 +- Linked List/README.markdown | 4 +- .../ShuntingYard.playground/Contents.swift | 78 +++++++++---------- Shunting Yard/ShuntingYard.swift | 62 +++++++-------- 8 files changed, 132 insertions(+), 132 deletions(-) diff --git a/Binary Search Tree/Solution 2/BinarySearchTree.playground/Contents.swift b/Binary Search Tree/Solution 2/BinarySearchTree.playground/Contents.swift index 12fbba81d..8df69fb6a 100644 --- a/Binary Search Tree/Solution 2/BinarySearchTree.playground/Contents.swift +++ b/Binary Search Tree/Solution 2/BinarySearchTree.playground/Contents.swift @@ -1,7 +1,7 @@ //: Playground - noun: a place where people can play // Each time you insert something, you get back a completely new tree. -var tree = BinarySearchTree.Leaf(7) +var tree = BinarySearchTree.leaf(7) tree = tree.insert(newValue: 2) tree = tree.insert(newValue: 5) tree = tree.insert(newValue: 10) diff --git a/Binary Search Tree/Solution 2/BinarySearchTree.playground/Sources/BinarySearchTree.swift b/Binary Search Tree/Solution 2/BinarySearchTree.playground/Sources/BinarySearchTree.swift index b692efdc4..5128bb348 100644 --- a/Binary Search Tree/Solution 2/BinarySearchTree.playground/Sources/BinarySearchTree.swift +++ b/Binary Search Tree/Solution 2/BinarySearchTree.playground/Sources/BinarySearchTree.swift @@ -4,25 +4,25 @@ The tree is immutable. Any insertions or deletions will create a new tree. */ public enum BinarySearchTree { - case Empty - case Leaf(T) - indirect case Node(BinarySearchTree, T, BinarySearchTree) + case empty + case leaf(T) + indirect case node(BinarySearchTree, T, BinarySearchTree) /* How many nodes are in this subtree. Performance: O(n). */ public var count: Int { switch self { - case .Empty: return 0 - case .Leaf: return 1 - case let .Node(left, _, right): return left.count + 1 + right.count + case .empty: return 0 + case .leaf: return 1 + case let .node(left, _, right): return left.count + 1 + right.count } } /* Distance of this node to its lowest leaf. Performance: O(n). */ public var height: Int { switch self { - case .Empty: return 0 - case .Leaf: return 1 - case let .Node(left, _, right): return 1 + max(left.height, right.height) + case .empty: return 0 + case .leaf: return 1 + case let .node(left, _, right): return 1 + max(left.height, right.height) } } @@ -32,21 +32,21 @@ public enum BinarySearchTree { */ public func insert(newValue: T) -> BinarySearchTree { switch self { - case .Empty: - return .Leaf(newValue) + case .empty: + return .leaf(newValue) - case .Leaf(let value): + case .leaf(let value): if newValue < value { - return .Node(.Leaf(newValue), value, .Empty) + return .node(.leaf(newValue), value, .empty) } else { - return .Node(.Empty, value, .Leaf(newValue)) + return .node(.empty, value, .leaf(newValue)) } - case .Node(let left, let value, let right): + case .node(let left, let value, let right): if newValue < value { - return .Node(left.insert(newValue: newValue), value, right) + return .node(left.insert(newValue: newValue), value, right) } else { - return .Node(left, value, right.insert(newValue: newValue)) + return .node(left, value, right.insert(newValue: newValue)) } } } @@ -57,11 +57,11 @@ public enum BinarySearchTree { */ public func search(x: T) -> BinarySearchTree? { switch self { - case .Empty: + case .empty: return nil - case .Leaf(let y): + case .leaf(let y): return (x == y) ? self : nil - case let .Node(left, y, right): + case let .node(left, y, right): if x < y { return left.search(x: x) } else if y < x { @@ -82,11 +82,11 @@ public enum BinarySearchTree { public func minimum() -> BinarySearchTree { var node = self var prev = node - while case let .Node(next, _, _) = node { + while case let .node(next, _, _) = node { prev = node node = next } - if case .Leaf = node { + if case .leaf = node { return node } return prev @@ -98,11 +98,11 @@ public enum BinarySearchTree { public func maximum() -> BinarySearchTree { var node = self var prev = node - while case let .Node(_, _, next) = node { + while case let .node(_, _, next) = node { prev = node node = next } - if case .Leaf = node { + if case .leaf = node { return node } return prev @@ -112,9 +112,9 @@ public enum BinarySearchTree { extension BinarySearchTree: CustomDebugStringConvertible { public var debugDescription: String { switch self { - case .Empty: return "." - case .Leaf(let value): return "\(value)" - case .Node(let left, let value, let right): + case .empty: return "." + case .leaf(let value): return "\(value)" + case .node(let left, let value, let right): return "(\(left.debugDescription) <- \(value) -> \(right.debugDescription))" } } diff --git a/Binary Search Tree/Solution 2/BinarySearchTree.swift b/Binary Search Tree/Solution 2/BinarySearchTree.swift index ce2868bbf..272b86368 100644 --- a/Binary Search Tree/Solution 2/BinarySearchTree.swift +++ b/Binary Search Tree/Solution 2/BinarySearchTree.swift @@ -4,25 +4,25 @@ The tree is immutable. Any insertions or deletions will create a new tree. */ public enum BinarySearchTree { - case Empty - case Leaf(T) - indirect case Node(BinarySearchTree, T, BinarySearchTree) + case empty + case leaf(T) + indirect case node(BinarySearchTree, T, BinarySearchTree) /* How many nodes are in this subtree. Performance: O(n). */ public var count: Int { switch self { - case .Empty: return 0 - case .Leaf: return 1 - case let .Node(left, _, right): return left.count + 1 + right.count + case .empty: return 0 + case .leaf: return 1 + case let .node(left, _, right): return left.count + 1 + right.count } } /* Distance of this node to its lowest leaf. Performance: O(n). */ public var height: Int { switch self { - case .Empty: return 0 - case .Leaf: return 1 - case let .Node(left, _, right): return 1 + max(left.height, right.height) + case .empty: return 0 + case .leaf: return 1 + case let .node(left, _, right): return 1 + max(left.height, right.height) } } @@ -32,21 +32,21 @@ public enum BinarySearchTree { */ public func insert(newValue: T) -> BinarySearchTree { switch self { - case .Empty: - return .Leaf(newValue) + case .empty: + return .leaf(newValue) - case .Leaf(let value): + case .leaf(let value): if newValue < value { - return .Node(.Leaf(newValue), value, .Empty) + return .node(.leaf(newValue), value, .empty) } else { - return .Node(.Empty, value, .Leaf(newValue)) + return .node(.empty, value, .leaf(newValue)) } - case .Node(let left, let value, let right): + case .node(let left, let value, let right): if newValue < value { - return .Node(left.insert(newValue), value, right) + return .node(left.insert(newValue), value, right) } else { - return .Node(left, value, right.insert(newValue)) + return .node(left, value, right.insert(newValue)) } } } @@ -57,11 +57,11 @@ public enum BinarySearchTree { */ public func search(x: T) -> BinarySearchTree? { switch self { - case .Empty: + case .empty: return nil - case .Leaf(let y): + case .leaf(let y): return (x == y) ? self : nil - case let .Node(left, y, right): + case let .node(left, y, right): if x < y { return left.search(x) } else if y < x { @@ -82,11 +82,11 @@ public enum BinarySearchTree { public func minimum() -> BinarySearchTree { var node = self var prev = node - while case let .Node(next, _, _) = node { + while case let .node(next, _, _) = node { prev = node node = next } - if case .Leaf = node { + if case .leaf = node { return node } return prev @@ -98,11 +98,11 @@ public enum BinarySearchTree { public func maximum() -> BinarySearchTree { var node = self var prev = node - while case let .Node(_, _, next) = node { + while case let .node(_, _, next) = node { prev = node node = next } - if case .Leaf = node { + if case .leaf = node { return node } return prev @@ -112,9 +112,9 @@ public enum BinarySearchTree { extension BinarySearchTree: CustomDebugStringConvertible { public var debugDescription: String { switch self { - case .Empty: return "." - case .Leaf(let value): return "\(value)" - case .Node(let left, let value, let right): + case .empty: return "." + case .leaf(let value): return "\(value)" + case .node(let left, let value, let right): return "(\(left.debugDescription) <- \(value) -> \(right.debugDescription))" } } diff --git a/Counting Sort/CountingSort.playground/Contents.swift b/Counting Sort/CountingSort.playground/Contents.swift index 2d85347ef..1d84f8132 100644 --- a/Counting Sort/CountingSort.playground/Contents.swift +++ b/Counting Sort/CountingSort.playground/Contents.swift @@ -1,12 +1,12 @@ //: Playground - noun: a place where people can play enum CountingSortError: Error { - case ArrayEmpty + case arrayEmpty } func countingSort(array: [Int]) throws -> [Int] { guard array.count > 0 else { - throw CountingSortError.ArrayEmpty + throw CountingSortError.arrayEmpty } // Step 1 @@ -38,4 +38,4 @@ func countingSort(array: [Int]) throws -> [Int] { } -try countingSort(array: [10, 9, 8, 7, 1, 2, 7, 3]) \ No newline at end of file +try countingSort(array: [10, 9, 8, 7, 1, 2, 7, 3]) diff --git a/Counting Sort/CountingSort.swift b/Counting Sort/CountingSort.swift index ec8c5adcb..d37bb2eff 100644 --- a/Counting Sort/CountingSort.swift +++ b/Counting Sort/CountingSort.swift @@ -7,12 +7,12 @@ // enum CountingSortError: ErrorType { - case ArrayEmpty + case arrayEmpty } func countingSort(array: [Int]) throws -> [Int] { guard array.count > 0 else { - throw CountingSortError.ArrayEmpty + throw CountingSortError.arrayEmpty } // Step 1 diff --git a/Linked List/README.markdown b/Linked List/README.markdown index 7b2ec0c0d..1884aeb23 100644 --- a/Linked List/README.markdown +++ b/Linked List/README.markdown @@ -526,8 +526,8 @@ It is possible to implement a linked list with value semantics using an enum. Th ```swift enum ListNode { - indirect case Node(T, next: ListNode) - case End + indirect case node(T, next: ListNode) + case end } ``` diff --git a/Shunting Yard/ShuntingYard.playground/Contents.swift b/Shunting Yard/ShuntingYard.playground/Contents.swift index 04fed7739..707e2a0a3 100644 --- a/Shunting Yard/ShuntingYard.playground/Contents.swift +++ b/Shunting Yard/ShuntingYard.playground/Contents.swift @@ -1,51 +1,51 @@ //: Playground - noun: a place where people can play internal enum OperatorAssociativity { - case LeftAssociative - case RightAssociative + case leftAssociative + case rightAssociative } public enum OperatorType: CustomStringConvertible { - case Add - case Subtract - case Divide - case Multiply - case Percent - case Exponent + case add + case subtract + case divide + case multiply + case percent + case exponent public var description: String { switch self { - case Add: + case add: return "+" - case Subtract: + case subtract: return "-" - case Divide: + case divide: return "/" - case Multiply: + case multiply: return "*" - case Percent: + case percent: return "%" - case Exponent: + case exponent: return "^" } } } public enum TokenType: CustomStringConvertible { - case OpenBracket - case CloseBracket + case openBracket + case closeBracket case Operator(OperatorToken) - case Operand(Double) + case operand(Double) public var description: String { switch self { - case OpenBracket: + case openBracket: return "(" - case CloseBracket: + case closeBracket: return ")" case Operator(let operatorToken): return operatorToken.description - case Operand(let value): + case operand(let value): return "\(value)" } } @@ -60,21 +60,21 @@ public struct OperatorToken: CustomStringConvertible { var precedence: Int { switch operatorType { - case .Add, .Subtract: + case .add, .subtract: return 0 - case .Divide, .Multiply, .Percent: + case .divide, .multiply, .percent: return 5 - case .Exponent: + case .exponent: return 10 } } var associativity: OperatorAssociativity { switch operatorType { - case .Add, .Subtract, .Divide, .Multiply, .Percent: - return .LeftAssociative - case .Exponent: - return .RightAssociative + case .add, .subtract, .divide, .multiply, .percent: + return .leftAssociative + case .exponent: + return .rightAssociative } } @@ -99,7 +99,7 @@ public struct Token: CustomStringConvertible { } init(operand: Double) { - tokenType = .Operand(operand) + tokenType = .operand(operand) } init(operatorType: OperatorType) { @@ -108,7 +108,7 @@ public struct Token: CustomStringConvertible { var isOpenBracket: Bool { switch tokenType { - case .OpenBracket: + case .openBracket: return true default: return false @@ -175,14 +175,14 @@ public func reversePolishNotation(expression: [Token]) -> String { for token in expression { switch token.tokenType { - case .Operand(_): + case .operand(_): reversePolishNotation.append(token) - case .OpenBracket: + case .openBracket: tokenStack.push(token) - case .CloseBracket: - while tokenStack.count > 0, let tempToken = tokenStack.pop() where !tempToken.isOpenBracket { + case .closeBracket: + while tokenStack.count > 0, let tempToken = tokenStack.pop(), !tempToken.isOpenBracket { reversePolishNotation.append(tempToken) } @@ -217,19 +217,19 @@ public func reversePolishNotation(expression: [Token]) -> String { let expr = InfixExpressionBuilder() .addOperand(3) - .addOperator(.Add) + .addOperator(.add) .addOperand(4) - .addOperator(.Multiply) + .addOperator(.multiply) .addOperand(2) - .addOperator(.Divide) + .addOperator(.divide) .addOpenBracket() .addOperand(1) - .addOperator(.Subtract) + .addOperator(.subtract) .addOperand(5) .addCloseBracket() - .addOperator(.Exponent) + .addOperator(.exponent) .addOperand(2) - .addOperator(.Exponent) + .addOperator(.exponent) .addOperand(3) .build() diff --git a/Shunting Yard/ShuntingYard.swift b/Shunting Yard/ShuntingYard.swift index 5159c9172..9d31d5a58 100644 --- a/Shunting Yard/ShuntingYard.swift +++ b/Shunting Yard/ShuntingYard.swift @@ -7,51 +7,51 @@ // internal enum OperatorAssociativity { - case LeftAssociative - case RightAssociative + case leftAssociative + case rightAssociative } public enum OperatorType: CustomStringConvertible { - case Add - case Subtract - case Divide - case Multiply - case Percent - case Exponent + case add + case subtract + case divide + case multiply + case percent + case exponent public var description: String { switch self { - case Add: + case add: return "+" - case Subtract: + case subtract: return "-" - case Divide: + case divide: return "/" - case Multiply: + case multiply: return "*" - case Percent: + case percent: return "%" - case Exponent: + case exponent: return "^" } } } public enum TokenType: CustomStringConvertible { - case OpenBracket - case CloseBracket + case openBracket + case closeBracket case Operator(OperatorToken) - case Operand(Double) + case operand(Double) public var description: String { switch self { - case OpenBracket: + case openBracket: return "(" - case CloseBracket: + case closeBracket: return ")" case Operator(let operatorToken): return operatorToken.description - case Operand(let value): + case operand(let value): return "\(value)" } } @@ -66,20 +66,20 @@ public struct OperatorToken: CustomStringConvertible { var precedence: Int { switch operatorType { - case .Add, .Subtract: + case .add, .subtract: return 0 - case .Divide, .Multiply, .Percent: + case .divide, .multiply, .percent: return 5 - case .Exponent: + case .exponent: return 10 } } var associativity: OperatorAssociativity { switch operatorType { - case .Add, .Subtract, .Divide, .Multiply, .Percent: + case .add, .subtract, .divide, .multiply, .percent: return .LeftAssociative - case .Exponent: + case .exponent: return .RightAssociative } } @@ -105,7 +105,7 @@ public struct Token: CustomStringConvertible { } init(operand: Double) { - tokenType = .Operand(operand) + tokenType = .operand(operand) } init(operatorType: OperatorType) { @@ -114,7 +114,7 @@ public struct Token: CustomStringConvertible { var isOpenBracket: Bool { switch tokenType { - case .OpenBracket: + case .openBracket: return true default: return false @@ -181,14 +181,14 @@ public func reversePolishNotation(expression: [Token]) -> String { for token in expression { switch token.tokenType { - case .Operand(_): + case .operand(_): reversePolishNotation.append(token) - case .OpenBracket: + case .openBracket: tokenStack.push(token) - case .CloseBracket: - while tokenStack.count > 0, let tempToken = tokenStack.pop() where !tempToken.isOpenBracket { + case .closeBracket: + while tokenStack.count > 0, let tempToken = tokenStack.pop(), !tempToken.isOpenBracket { reversePolishNotation.append(tempToken) } From e1517dc458375a589a4cfd49a3f7c0c16caaffd6 Mon Sep 17 00:00:00 2001 From: zaccone Date: Thu, 29 Dec 2016 14:34:48 -0500 Subject: [PATCH 0739/1679] Corrected a spelling error and removed the "get" syntax for a property. --- Trie/Trie/Trie/Trie.swift | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Trie/Trie/Trie/Trie.swift b/Trie/Trie/Trie/Trie.swift index ad4e9f2e7..8f3b46123 100644 --- a/Trie/Trie/Trie/Trie.swift +++ b/Trie/Trie/Trie/Trie.swift @@ -16,9 +16,7 @@ class TrieNode { var children: [T: TrieNode] = [:] var isTerminating = false var isLeaf: Bool { - get { - return children.count == 0 - } + return children.count == 0 } /// Initializes a node. @@ -62,7 +60,7 @@ class Trie { fileprivate let root: Node fileprivate var wordCount: Int - /// Creats an empty trie. + /// Creates an empty trie. init() { root = Node() wordCount = 0 From 5021bc79cd44f1d8ae8f32780984759d2cc57b5a Mon Sep 17 00:00:00 2001 From: zaccone Date: Thu, 29 Dec 2016 16:48:29 -0500 Subject: [PATCH 0740/1679] Added NSCoding conformance. --- ...6ABF2F62-9363-4450-8DE1-D20F57026950.plist | 22 ++++++ .../Info.plist | 33 ++++++++ Trie/Trie/Trie/Trie.swift | 25 ++++++- Trie/Trie/TrieTests/TrieTests.swift | 75 +++++++++++-------- 4 files changed, 121 insertions(+), 34 deletions(-) create mode 100644 Trie/Trie/Trie.xcodeproj/xcshareddata/xcbaselines/EB798E0A1DFEF79900F0628D.xcbaseline/6ABF2F62-9363-4450-8DE1-D20F57026950.plist create mode 100644 Trie/Trie/Trie.xcodeproj/xcshareddata/xcbaselines/EB798E0A1DFEF79900F0628D.xcbaseline/Info.plist diff --git a/Trie/Trie/Trie.xcodeproj/xcshareddata/xcbaselines/EB798E0A1DFEF79900F0628D.xcbaseline/6ABF2F62-9363-4450-8DE1-D20F57026950.plist b/Trie/Trie/Trie.xcodeproj/xcshareddata/xcbaselines/EB798E0A1DFEF79900F0628D.xcbaseline/6ABF2F62-9363-4450-8DE1-D20F57026950.plist new file mode 100644 index 000000000..01ff985c8 --- /dev/null +++ b/Trie/Trie/Trie.xcodeproj/xcshareddata/xcbaselines/EB798E0A1DFEF79900F0628D.xcbaseline/6ABF2F62-9363-4450-8DE1-D20F57026950.plist @@ -0,0 +1,22 @@ + + + + + classNames + + TrieTests + + testInsertPerformance() + + com.apple.XCTPerformanceMetric_WallClockTime + + baselineAverage + 3.0053 + baselineIntegrationDisplayName + Local Baseline + + + + + + diff --git a/Trie/Trie/Trie.xcodeproj/xcshareddata/xcbaselines/EB798E0A1DFEF79900F0628D.xcbaseline/Info.plist b/Trie/Trie/Trie.xcodeproj/xcshareddata/xcbaselines/EB798E0A1DFEF79900F0628D.xcbaseline/Info.plist new file mode 100644 index 000000000..3c07f3d6a --- /dev/null +++ b/Trie/Trie/Trie.xcodeproj/xcshareddata/xcbaselines/EB798E0A1DFEF79900F0628D.xcbaseline/Info.plist @@ -0,0 +1,33 @@ + + + + + runDestinationsByUUID + + 6ABF2F62-9363-4450-8DE1-D20F57026950 + + localComputer + + busSpeedInMHz + 100 + cpuCount + 1 + cpuKind + Intel Core i7 + cpuSpeedInMHz + 3300 + logicalCPUCoresPerPackage + 4 + modelCode + MacBookPro13,2 + physicalCPUCoresPerPackage + 2 + platformIdentifier + com.apple.platform.macosx + + targetArchitecture + x86_64 + + + + diff --git a/Trie/Trie/Trie/Trie.swift b/Trie/Trie/Trie/Trie.swift index 8f3b46123..ec3b1c5cc 100644 --- a/Trie/Trie/Trie/Trie.swift +++ b/Trie/Trie/Trie/Trie.swift @@ -43,7 +43,7 @@ class TrieNode { /// A trie data structure containing words. Each node is a single /// character of a word. -class Trie { +class Trie: NSObject, NSCoding { typealias Node = TrieNode /// The number of words in the trie public var count: Int { @@ -61,10 +61,31 @@ class Trie { fileprivate var wordCount: Int /// Creates an empty trie. - init() { + override init() { root = Node() wordCount = 0 } + + // MARK: NSCoding + + /// Initializes the trie with words from an archive + /// + /// - Parameter decoder: Decodes the archive + required convenience init?(coder decoder: NSCoder) { + self.init() + let words = decoder.decodeObject(forKey: "words") as? [String] + for word in words! { + self.insert(word: word) + } + } + + /// Encodes the words in the trie by putting them in an array then encoding + /// the array. + /// + /// - Parameter coder: The object that will encode the array + func encode(with coder: NSCoder) { + coder.encode(self.words, forKey: "words") + } } // MARK: - Adds methods: insert, remove, contains diff --git a/Trie/Trie/TrieTests/TrieTests.swift b/Trie/Trie/TrieTests/TrieTests.swift index 236908ece..7ef02553f 100644 --- a/Trie/Trie/TrieTests/TrieTests.swift +++ b/Trie/Trie/TrieTests/TrieTests.swift @@ -12,20 +12,20 @@ import XCTest class TrieTests: XCTestCase { var wordArray: [String]? var trie = Trie() - + /// Makes sure that the wordArray and trie are initialized before each test. override func setUp() { super.setUp() createWordArray() insertWordsIntoTrie() } - - /// Don't need to do anything here because the wordArrayu and trie should + + /// Don't need to do anything here because the wordArray and trie should /// stay around. override func tearDown() { super.tearDown() } - + /// Reads words from the dictionary file and inserts them into an array. If /// the word array already has words, do nothing. This allows running all /// tests without repeatedly filling the array with the same values. @@ -36,7 +36,7 @@ class TrieTests: XCTestCase { let resourcePath = Bundle.main.resourcePath! as NSString let fileName = "dictionary.txt" let filePath = resourcePath.appendingPathComponent(fileName) - + var data: String? do { data = try String(contentsOfFile: filePath, encoding: String.Encoding.utf8) @@ -48,24 +48,23 @@ class TrieTests: XCTestCase { wordArray = data!.components(separatedBy: "\n") XCTAssertEqual(wordArray!.count, dictionarySize) } - + /// Inserts words into a trie. If the trie is non-empty, don't do anything. func insertWordsIntoTrie() { guard trie.count == 0 else { return } - let numberOfWordsToInsert = wordArray!.count - for i in 0.. Date: Thu, 29 Dec 2016 17:28:41 -0500 Subject: [PATCH 0741/1679] Added a ReadMe file. --- Trie/Trie/Trie.xcodeproj/project.pbxproj | 4 +++ Trie/Trie/Trie/ReadMe.md | 33 ++++++++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 Trie/Trie/Trie/ReadMe.md diff --git a/Trie/Trie/Trie.xcodeproj/project.pbxproj b/Trie/Trie/Trie.xcodeproj/project.pbxproj index 8d3611b6d..055885ee1 100644 --- a/Trie/Trie/Trie.xcodeproj/project.pbxproj +++ b/Trie/Trie/Trie.xcodeproj/project.pbxproj @@ -17,6 +17,7 @@ EB798E2A1DFEF81400F0628D /* Trie.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB798E281DFEF81400F0628D /* Trie.swift */; }; EB798E2C1DFEF90B00F0628D /* dictionary.txt in Resources */ = {isa = PBXBuildFile; fileRef = EB798E2B1DFEF90B00F0628D /* dictionary.txt */; }; EB798E2D1DFEF90B00F0628D /* dictionary.txt in Resources */ = {isa = PBXBuildFile; fileRef = EB798E2B1DFEF90B00F0628D /* dictionary.txt */; }; + EB8369AD1E15C5710003A7F8 /* ReadMe.md in Sources */ = {isa = PBXBuildFile; fileRef = EB8369AC1E15C5710003A7F8 /* ReadMe.md */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -51,6 +52,7 @@ EB798E1C1DFEF79900F0628D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; EB798E281DFEF81400F0628D /* Trie.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Trie.swift; sourceTree = ""; }; EB798E2B1DFEF90B00F0628D /* dictionary.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = dictionary.txt; sourceTree = ""; }; + EB8369AC1E15C5710003A7F8 /* ReadMe.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = ReadMe.md; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -101,6 +103,7 @@ EB798DFC1DFEF79900F0628D /* Trie */ = { isa = PBXGroup; children = ( + EB8369AC1E15C5710003A7F8 /* ReadMe.md */, EB798DFD1DFEF79900F0628D /* AppDelegate.swift */, EB798DFF1DFEF79900F0628D /* ViewController.swift */, EB798E011DFEF79900F0628D /* Assets.xcassets */, @@ -267,6 +270,7 @@ files = ( EB798E291DFEF81400F0628D /* Trie.swift in Sources */, EB798E001DFEF79900F0628D /* ViewController.swift in Sources */, + EB8369AD1E15C5710003A7F8 /* ReadMe.md in Sources */, EB798DFE1DFEF79900F0628D /* AppDelegate.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/Trie/Trie/Trie/ReadMe.md b/Trie/Trie/Trie/ReadMe.md new file mode 100644 index 000000000..934585a3f --- /dev/null +++ b/Trie/Trie/Trie/ReadMe.md @@ -0,0 +1,33 @@ +# Changes + +- Corrected a spelling error in a comment. + +- Got rid of the `get` syntax for a read only property as the coding guidelines suggest. + +- Changed several tests so that they are more Swift-like. That is, they now feel like they are using the features of the language better. + +- Fixed a problem in the test method `testRemovePerformance`. The `measure` method runs the block of code 10 times. Previously, all words would get removed after the first run and the next 9 runs were very fast because there was nothing to do! That is corrected now. + +- Made the `Trie` class a subclass of `NSObject` and had it conform to `NSCoding`. Added a test to verify that this works. + +--- + +I wasn't able to figure out how to recursively archive the trie. Instead, I tried Kelvin's suggestion to use the `words` property to create an array of words in the trie, then archiving the array. + +There are a couple of nice aspects to this approach. + +- The `TrieNode` class can remain generic since it doesn't need to conform to `NSCoding`. + +- It doesn't require much new code. + +There are several downsides though. + +- The size of the archived words is three times the size of the original file of words! Did I do this right? The tests pass, so it seems correct. I question whether archiving is worth the effort if the resulting archive is so much larger than the original file. + +- I would expect that archiving the trie would result in a file that was smaller than the original since a trie doesn't repeat leading character sequences when they are the same. + +- This requires that the trie get reconstructed when it is unarchived. + +- My gut tells me that it would be faster to archive and unarchive the trie itself, but I don't have any hard data to support this. + +I would like to see code that recursively archives the trie so we can compare the performance. From 02ff5694e848fa5f39ab717b2c418e0fbf014190 Mon Sep 17 00:00:00 2001 From: Yohannes Wijaya Date: Fri, 30 Dec 2016 09:33:55 +0700 Subject: [PATCH 0742/1679] Added a new algorithms book under "Learn More" --- README.markdown | 1 + 1 file changed, 1 insertion(+) diff --git a/README.markdown b/README.markdown index 5c769688a..6766e7025 100644 --- a/README.markdown +++ b/README.markdown @@ -198,6 +198,7 @@ For more information, check out these great books: - [The Algorithm Design Manual](http://www.algorist.com) by Skiena - [Elements of Programming Interviews](http://elementsofprogramminginterviews.com) by Aziz, Lee, Prakash - [Algorithms](http://www.cs.princeton.edu/~rs/) by Sedgewick +- [Grokking Algorithms](https://www.manning.com/books/grokking-algorithms) by Aditya Bhargava The following books are available for free online: From 89fb804a5f006f2bcbe9c55f784a277852484581 Mon Sep 17 00:00:00 2001 From: gonini Date: Mon, 2 Jan 2017 23:24:24 +0900 Subject: [PATCH 0743/1679] Updating to Swift3 I upgraded to swift 3 because it did not run as a grammar problem. --- .../Contents.swift | 24 +++++++++---------- .../timeline.xctimeline | 6 ----- .../Sources/Graph.swift | 8 +++---- .../Sources/Node.swift | 2 +- Shortest Path (Unweighted)/ShortestPath.swift | 2 +- 5 files changed, 18 insertions(+), 24 deletions(-) delete mode 100644 Shortest Path (Unweighted)/ShortestPath.playground/Pages/Shortest path example.xcplaygroundpage/timeline.xctimeline diff --git a/Shortest Path (Unweighted)/ShortestPath.playground/Pages/Shortest path example.xcplaygroundpage/Contents.swift b/Shortest Path (Unweighted)/ShortestPath.playground/Pages/Shortest path example.xcplaygroundpage/Contents.swift index cfc582c49..2380ebb69 100644 --- a/Shortest Path (Unweighted)/ShortestPath.playground/Pages/Shortest path example.xcplaygroundpage/Contents.swift +++ b/Shortest Path (Unweighted)/ShortestPath.playground/Pages/Shortest path example.xcplaygroundpage/Contents.swift @@ -2,15 +2,15 @@ func breadthFirstSearchShortestPath(graph: Graph, source: Node) -> Graph { let shortestPathGraph = graph.duplicate() var queue = Queue() - let sourceInShortestPathsGraph = shortestPathGraph.findNodeWithLabel(source.label) - queue.enqueue(sourceInShortestPathsGraph) + let sourceInShortestPathsGraph = shortestPathGraph.findNodeWithLabel(label: source.label) + queue.enqueue(element: sourceInShortestPathsGraph) sourceInShortestPathsGraph.distance = 0 while let current = queue.dequeue() { for edge in current.neighbors { let neighborNode = edge.neighbor if !neighborNode.hasDistance { - queue.enqueue(neighborNode) + queue.enqueue(element: neighborNode) neighborNode.distance = current.distance! + 1 } } @@ -23,14 +23,14 @@ func breadthFirstSearchShortestPath(graph: Graph, source: Node) -> Graph { let graph = Graph() -let nodeA = graph.addNode("a") -let nodeB = graph.addNode("b") -let nodeC = graph.addNode("c") -let nodeD = graph.addNode("d") -let nodeE = graph.addNode("e") -let nodeF = graph.addNode("f") -let nodeG = graph.addNode("g") -let nodeH = graph.addNode("h") +let nodeA = graph.addNode(label: "a") +let nodeB = graph.addNode(label: "b") +let nodeC = graph.addNode(label: "c") +let nodeD = graph.addNode(label: "d") +let nodeE = graph.addNode(label: "e") +let nodeF = graph.addNode(label: "f") +let nodeG = graph.addNode(label: "g") +let nodeH = graph.addNode(label: "h") graph.addEdge(nodeA, neighbor: nodeB) graph.addEdge(nodeA, neighbor: nodeC) @@ -40,5 +40,5 @@ graph.addEdge(nodeC, neighbor: nodeF) graph.addEdge(nodeC, neighbor: nodeG) graph.addEdge(nodeE, neighbor: nodeH) -let shortestPathGraph = breadthFirstSearchShortestPath(graph, source: nodeA) +let shortestPathGraph = breadthFirstSearchShortestPath(graph: graph, source: nodeA) print(shortestPathGraph.nodes) diff --git a/Shortest Path (Unweighted)/ShortestPath.playground/Pages/Shortest path example.xcplaygroundpage/timeline.xctimeline b/Shortest Path (Unweighted)/ShortestPath.playground/Pages/Shortest path example.xcplaygroundpage/timeline.xctimeline deleted file mode 100644 index bf468afec..000000000 --- a/Shortest Path (Unweighted)/ShortestPath.playground/Pages/Shortest path example.xcplaygroundpage/timeline.xctimeline +++ /dev/null @@ -1,6 +0,0 @@ - - - - - diff --git a/Shortest Path (Unweighted)/ShortestPath.playground/Sources/Graph.swift b/Shortest Path (Unweighted)/ShortestPath.playground/Sources/Graph.swift index 8cfb2a09c..8c3281aa8 100644 --- a/Shortest Path (Unweighted)/ShortestPath.playground/Sources/Graph.swift +++ b/Shortest Path (Unweighted)/ShortestPath.playground/Sources/Graph.swift @@ -11,7 +11,7 @@ public class Graph: CustomStringConvertible, Equatable { return node } - public func addEdge(source: Node, neighbor: Node) { + public func addEdge(_ source: Node, neighbor: Node) { let edge = Edge(neighbor: neighbor) source.neighbors.append(edge) } @@ -35,13 +35,13 @@ public class Graph: CustomStringConvertible, Equatable { let duplicated = Graph() for node in nodes { - duplicated.addNode(node.label) + duplicated.addNode(label: node.label) } for node in nodes { for edge in node.neighbors { - let source = duplicated.findNodeWithLabel(node.label) - let neighbour = duplicated.findNodeWithLabel(edge.neighbor.label) + let source = duplicated.findNodeWithLabel(label: node.label) + let neighbour = duplicated.findNodeWithLabel(label: edge.neighbor.label) duplicated.addEdge(source, neighbor: neighbour) } } diff --git a/Shortest Path (Unweighted)/ShortestPath.playground/Sources/Node.swift b/Shortest Path (Unweighted)/ShortestPath.playground/Sources/Node.swift index 37a3b3fdf..ebdb6f4e3 100644 --- a/Shortest Path (Unweighted)/ShortestPath.playground/Sources/Node.swift +++ b/Shortest Path (Unweighted)/ShortestPath.playground/Sources/Node.swift @@ -23,7 +23,7 @@ public class Node: CustomStringConvertible, Equatable { } public func remove(edge: Edge) { - neighbors.removeAtIndex(neighbors.indexOf { $0 === edge }!) + neighbors.remove(at: neighbors.index { $0 === edge }!) } } diff --git a/Shortest Path (Unweighted)/ShortestPath.swift b/Shortest Path (Unweighted)/ShortestPath.swift index 13ed0c080..6aa082a96 100644 --- a/Shortest Path (Unweighted)/ShortestPath.swift +++ b/Shortest Path (Unweighted)/ShortestPath.swift @@ -10,7 +10,7 @@ func breadthFirstSearchShortestPath(graph: Graph, source: Node) -> Graph { for edge in current.neighbors { let neighborNode = edge.neighbor if !neighborNode.hasDistance { - queue.enqueue(neighborNode) + queue.enqueue(element: neighborNode) neighborNode.distance = current.distance! + 1 } } From 998fc13118dc7d7cefb7f088d3a70719ec5ea5d1 Mon Sep 17 00:00:00 2001 From: Mohamed Emad Hegab Date: Mon, 2 Jan 2017 15:44:58 +0100 Subject: [PATCH 0744/1679] Fix for swift 3 on playground and rest of the classes --- Select Minimum Maximum/Maximum.swift | 23 ++--- Select Minimum Maximum/Minimum.swift | 23 ++--- .../MinimumMaximumPairs.swift | 63 ++++++------ Select Minimum Maximum/README.markdown | 7 +- .../Contents.swift | 99 ++++++++++--------- .../timeline.xctimeline | 6 -- 6 files changed, 112 insertions(+), 109 deletions(-) delete mode 100644 Select Minimum Maximum/SelectMinimumMaximum.playground/timeline.xctimeline diff --git a/Select Minimum Maximum/Maximum.swift b/Select Minimum Maximum/Maximum.swift index 8c78ba478..991a0544e 100644 --- a/Select Minimum Maximum/Maximum.swift +++ b/Select Minimum Maximum/Maximum.swift @@ -1,15 +1,16 @@ /* - Finds the maximum value in an array in O(n) time. -*/ + Finds the maximum value in an array in O(n) time. + */ -func maximum(var array: [T]) -> T? { - guard !array.isEmpty else { - return nil - } +func maximum(_ array: [T]) -> T? { + var array = array + guard !array.isEmpty else { + return nil + } - var maximum = array.removeFirst() - for element in array { - maximum = element > maximum ? element : maximum - } - return maximum + var maximum = array.removeFirst() + for element in array { + maximum = element > maximum ? element : maximum + } + return maximum } diff --git a/Select Minimum Maximum/Minimum.swift b/Select Minimum Maximum/Minimum.swift index 9b08deb4f..90dfbd54b 100644 --- a/Select Minimum Maximum/Minimum.swift +++ b/Select Minimum Maximum/Minimum.swift @@ -1,15 +1,16 @@ /* - Finds the minimum value in an array in O(n) time. -*/ + Finds the minimum value in an array in O(n) time. + */ -func minimum(var array: [T]) -> T? { - guard !array.isEmpty else { - return nil - } +func minimum(_ array: [T]) -> T? { + var array = array + guard !array.isEmpty else { + return nil + } - var minimum = array.removeFirst() - for element in array { - minimum = element < minimum ? element : minimum - } - return minimum + var minimum = array.removeFirst() + for element in array { + minimum = element < minimum ? element : minimum + } + return minimum } diff --git a/Select Minimum Maximum/MinimumMaximumPairs.swift b/Select Minimum Maximum/MinimumMaximumPairs.swift index 5798e1f32..b7deb570a 100644 --- a/Select Minimum Maximum/MinimumMaximumPairs.swift +++ b/Select Minimum Maximum/MinimumMaximumPairs.swift @@ -1,39 +1,40 @@ /* - Finds the maximum and minimum value in an array in O(n) time. -*/ + Finds the maximum and minimum value in an array in O(n) time. + */ -func minimumMaximum(var array: [T]) -> (minimum: T, maximum: T)? { - guard !array.isEmpty else { - return nil - } +func minimumMaximum(_ array: [T]) -> (minimum: T, maximum: T)? { + var array = array + guard !array.isEmpty else { + return nil + } - var minimum = array.first! - var maximum = array.first! + var minimum = array.first! + var maximum = array.first! - let hasOddNumberOfItems = array.count % 2 != 0 - if hasOddNumberOfItems { - array.removeFirst() - } + let hasOddNumberOfItems = array.count % 2 != 0 + if hasOddNumberOfItems { + array.removeFirst() + } - while !array.isEmpty { - let pair = (array.removeFirst(), array.removeFirst()) + while !array.isEmpty { + let pair = (array.removeFirst(), array.removeFirst()) - if pair.0 > pair.1 { - if pair.0 > maximum { - maximum = pair.0 - } - if pair.1 < minimum { - minimum = pair.1 - } - } else { - if pair.1 > maximum { - maximum = pair.1 - } - if pair.0 < minimum { - minimum = pair.0 - } + if pair.0 > pair.1 { + if pair.0 > maximum { + maximum = pair.0 + } + if pair.1 < minimum { + minimum = pair.1 + } + } else { + if pair.1 > maximum { + maximum = pair.1 + } + if pair.0 < minimum { + minimum = pair.0 + } + } } - } - - return (minimum, maximum) + + return (minimum, maximum) } diff --git a/Select Minimum Maximum/README.markdown b/Select Minimum Maximum/README.markdown index a67f4ec8e..09ca97039 100644 --- a/Select Minimum Maximum/README.markdown +++ b/Select Minimum Maximum/README.markdown @@ -23,7 +23,8 @@ Repeat this process until the all elements in the list have been processed. Here is a simple implementation in Swift: ```swift -func minimum(var array: [T]) -> T? { +func minimum(_ array: [T]) -> T? { + var array = array guard !array.isEmpty else { return nil } @@ -35,7 +36,8 @@ func minimum(var array: [T]) -> T? { return minimum } -func maximum(var array: [T]) -> T? { +func maximum(_ array: [T]) -> T? { + var array = array guard !array.isEmpty else { return nil } @@ -90,6 +92,7 @@ Here is a simple implementation in Swift: ```swift func minimumMaximum(_ array: [T]) -> (minimum: T, maximum: T)? { + var array = array guard !array.isEmpty else { return nil } diff --git a/Select Minimum Maximum/SelectMinimumMaximum.playground/Contents.swift b/Select Minimum Maximum/SelectMinimumMaximum.playground/Contents.swift index ef92ac1e6..6076b5246 100644 --- a/Select Minimum Maximum/SelectMinimumMaximum.playground/Contents.swift +++ b/Select Minimum Maximum/SelectMinimumMaximum.playground/Contents.swift @@ -1,64 +1,67 @@ // Compare each item to find minimum -func minimum(var array: [T]) -> T? { - guard !array.isEmpty else { - return nil - } +func minimum(_ array: [T]) -> T? { + var array = array + guard !array.isEmpty else { + return nil + } - var minimum = array.removeFirst() - for element in array { - minimum = element < minimum ? element : minimum - } - return minimum + var minimum = array.removeFirst() + for element in array { + minimum = element < minimum ? element : minimum + } + return minimum } // Compare each item to find maximum -func maximum(var array: [T]) -> T? { - guard !array.isEmpty else { - return nil - } +func maximum(_ array: [T]) -> T? { + var array = array + guard !array.isEmpty else { + return nil + } - var maximum = array.removeFirst() - for element in array { - maximum = element > maximum ? element : maximum - } - return maximum + var maximum = array.removeFirst() + for element in array { + maximum = element > maximum ? element : maximum + } + return maximum } // Compare in pairs to find minimum and maximum -func minimumMaximum(var array: [T]) -> (minimum: T, maximum: T)? { - guard !array.isEmpty else { - return nil - } +func minimumMaximum(_ array: [T]) -> (minimum: T, maximum: T)? { + var array = array + guard !array.isEmpty else { + return nil + } - var minimum = array.first! - var maximum = array.first! + var minimum = array.first! + var maximum = array.first! - let hasOddNumberOfItems = array.count % 2 != 0 - if hasOddNumberOfItems { - array.removeFirst() - } + let hasOddNumberOfItems = array.count % 2 != 0 + if hasOddNumberOfItems { + array.removeFirst() + } - while !array.isEmpty { - let pair = (array.removeFirst(), array.removeFirst()) + while !array.isEmpty { + let pair = (array.removeFirst(), array.removeFirst()) - if pair.0 > pair.1 { - if pair.0 > maximum { - maximum = pair.0 - } - if pair.1 < minimum { - minimum = pair.1 - } - } else { - if pair.1 > maximum { - maximum = pair.1 - } - if pair.0 < minimum { - minimum = pair.0 - } + if pair.0 > pair.1 { + if pair.0 > maximum { + maximum = pair.0 + } + if pair.1 < minimum { + minimum = pair.1 + } + } else { + if pair.1 > maximum { + maximum = pair.1 + } + if pair.0 < minimum { + minimum = pair.0 + } + } } - } - return (minimum, maximum) + return (minimum, maximum) } // Test of minimum and maximum functions @@ -72,5 +75,5 @@ result.minimum result.maximum // Built-in Swift functions -array.minElement() -array.maxElement() +array.min() +array.max() diff --git a/Select Minimum Maximum/SelectMinimumMaximum.playground/timeline.xctimeline b/Select Minimum Maximum/SelectMinimumMaximum.playground/timeline.xctimeline deleted file mode 100644 index bf468afec..000000000 --- a/Select Minimum Maximum/SelectMinimumMaximum.playground/timeline.xctimeline +++ /dev/null @@ -1,6 +0,0 @@ - - - - - From dfc27f868b20b5ad6408238f7d97489ff518cd49 Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Mon, 2 Jan 2017 07:52:15 -0800 Subject: [PATCH 0745/1679] Fixed indentation of the code. --- .../Contents.swift | 106 +++++++++--------- 1 file changed, 53 insertions(+), 53 deletions(-) diff --git a/Select Minimum Maximum/SelectMinimumMaximum.playground/Contents.swift b/Select Minimum Maximum/SelectMinimumMaximum.playground/Contents.swift index 6076b5246..182060805 100644 --- a/Select Minimum Maximum/SelectMinimumMaximum.playground/Contents.swift +++ b/Select Minimum Maximum/SelectMinimumMaximum.playground/Contents.swift @@ -1,67 +1,67 @@ // Compare each item to find minimum func minimum(_ array: [T]) -> T? { - var array = array - guard !array.isEmpty else { - return nil - } - - var minimum = array.removeFirst() - for element in array { - minimum = element < minimum ? element : minimum - } - return minimum + var array = array + guard !array.isEmpty else { + return nil + } + + var minimum = array.removeFirst() + for element in array { + minimum = element < minimum ? element : minimum + } + return minimum } // Compare each item to find maximum func maximum(_ array: [T]) -> T? { - var array = array - guard !array.isEmpty else { - return nil - } - - var maximum = array.removeFirst() - for element in array { - maximum = element > maximum ? element : maximum - } - return maximum + var array = array + guard !array.isEmpty else { + return nil + } + + var maximum = array.removeFirst() + for element in array { + maximum = element > maximum ? element : maximum + } + return maximum } // Compare in pairs to find minimum and maximum func minimumMaximum(_ array: [T]) -> (minimum: T, maximum: T)? { - var array = array - guard !array.isEmpty else { - return nil + var array = array + guard !array.isEmpty else { + return nil + } + + var minimum = array.first! + var maximum = array.first! + + let hasOddNumberOfItems = array.count % 2 != 0 + if hasOddNumberOfItems { + array.removeFirst() + } + + while !array.isEmpty { + let pair = (array.removeFirst(), array.removeFirst()) + + if pair.0 > pair.1 { + if pair.0 > maximum { + maximum = pair.0 + } + if pair.1 < minimum { + minimum = pair.1 + } + } else { + if pair.1 > maximum { + maximum = pair.1 + } + if pair.0 < minimum { + minimum = pair.0 + } } - - var minimum = array.first! - var maximum = array.first! - - let hasOddNumberOfItems = array.count % 2 != 0 - if hasOddNumberOfItems { - array.removeFirst() - } - - while !array.isEmpty { - let pair = (array.removeFirst(), array.removeFirst()) - - if pair.0 > pair.1 { - if pair.0 > maximum { - maximum = pair.0 - } - if pair.1 < minimum { - minimum = pair.1 - } - } else { - if pair.1 > maximum { - maximum = pair.1 - } - if pair.0 < minimum { - minimum = pair.0 - } - } - } - - return (minimum, maximum) + } + + return (minimum, maximum) } // Test of minimum and maximum functions From 728d749d535359788d701296ce338b681fa18b1d Mon Sep 17 00:00:00 2001 From: Zhang Date: Tue, 3 Jan 2017 08:54:29 +0900 Subject: [PATCH 0746/1679] Update README. Convert to swift 3.0 syntax. --- Shortest Path (Unweighted)/README.markdown | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/Shortest Path (Unweighted)/README.markdown b/Shortest Path (Unweighted)/README.markdown index 0107964ae..a16519260 100644 --- a/Shortest Path (Unweighted)/README.markdown +++ b/Shortest Path (Unweighted)/README.markdown @@ -23,7 +23,7 @@ The root of the tree is the node you started the breadth-first search from. To f Let's put breadth-first search into practice and calculate the shortest path from `A` to all the other nodes. We start with the source node `A` and add it to a queue with a distance of `0`. ```swift -queue.enqueue(A) +queue.enqueue(element: A) A.distance = 0 ``` @@ -31,9 +31,9 @@ The queue is now `[ A ]`. We dequeue `A` and enqueue its two immediate neighbor ```swift queue.dequeue() // A -queue.enqueue(B) +queue.enqueue(element: B) B.distance = A.distance + 1 // result: 1 -queue.enqueue(C) +queue.enqueue(element: C) C.distance = A.distance + 1 // result: 1 ``` @@ -41,9 +41,9 @@ The queue is now `[ B, C ]`. Dequeue `B` and enqueue `B`'s neighbor nodes `D` an ```swift queue.dequeue() // B -queue.enqueue(D) +queue.enqueue(element: D) D.distance = B.distance + 1 // result: 2 -queue.enqueue(E) +queue.enqueue(element: E) E.distance = B.distance + 1 // result: 2 ``` @@ -51,9 +51,9 @@ The queue is now `[ C, D, E ]`. Dequeue `C` and enqueue `C`'s neighbor nodes `F` ```swift queue.dequeue() // C -queue.enqueue(F) +queue.enqueue(element: F) F.distance = C.distance + 1 // result: 2 -queue.enqueue(G) +queue.enqueue(element: G) G.distance = C.distance + 1 // result: 2 ``` @@ -66,15 +66,15 @@ func breadthFirstSearchShortestPath(graph: Graph, source: Node) -> Graph { let shortestPathGraph = graph.duplicate() var queue = Queue() - let sourceInShortestPathsGraph = shortestPathGraph.findNodeWithLabel(source.label) - queue.enqueue(sourceInShortestPathsGraph) + let sourceInShortestPathsGraph = shortestPathGraph.findNodeWithLabel(label: source.label) + queue.enqueue(element: sourceInShortestPathsGraph) sourceInShortestPathsGraph.distance = 0 while let current = queue.dequeue() { for edge in current.neighbors { let neighborNode = edge.neighbor if !neighborNode.hasDistance { - queue.enqueue(neighborNode) + queue.enqueue(element: neighborNode) neighborNode.distance = current.distance! + 1 } } @@ -87,7 +87,7 @@ func breadthFirstSearchShortestPath(graph: Graph, source: Node) -> Graph { Put this code in a playground and test it like so: ```swift -let shortestPathGraph = breadthFirstSearchShortestPath(graph, source: nodeA) +let shortestPathGraph = breadthFirstSearchShortestPath(graph: graph, source: nodeA) print(shortestPathGraph.nodes) ``` From b2688ad3cb3a9705aa73aa8fe54773192acd90a2 Mon Sep 17 00:00:00 2001 From: Zhang Date: Tue, 3 Jan 2017 09:26:34 +0900 Subject: [PATCH 0747/1679] Update .travis.yml --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 7b5faffa6..f6c64488d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -36,7 +36,7 @@ script: # - xcodebuild test -project ./Select\ Minimum\ Maximum/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Selection\ Sort/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Shell\ Sort/Tests/Tests.xcodeproj -scheme Tests -# - xcodebuild test -project ./Shortest\ Path\ \(Unweighted\)/Tests/Tests.xcodeproj -scheme Tests +- xcodebuild test -project ./Shortest\ Path\ \(Unweighted\)/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Single-Source\ Shortest\ Paths\ \(Weighted\)/SSSP.xcodeproj -scheme SSSPTests - xcodebuild test -project ./Stack/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Topological\ Sort/Tests/Tests.xcodeproj -scheme Tests From 6aab6200651772d8f6f7c1e7cf641f2242a784fe Mon Sep 17 00:00:00 2001 From: gonini Date: Tue, 3 Jan 2017 09:40:13 +0900 Subject: [PATCH 0748/1679] Updated with XCTest Swift3 syntax for shortest path --- Shortest Path (Unweighted)/Tests/Graph.swift | 159 +++++++++--------- .../Tests/ShortestPathTests.swift | 72 ++++---- 2 files changed, 116 insertions(+), 115 deletions(-) diff --git a/Shortest Path (Unweighted)/Tests/Graph.swift b/Shortest Path (Unweighted)/Tests/Graph.swift index ed71cab7c..0d2a735c2 100644 --- a/Shortest Path (Unweighted)/Tests/Graph.swift +++ b/Shortest Path (Unweighted)/Tests/Graph.swift @@ -1,106 +1,107 @@ // MARK: - Edge public class Edge: Equatable { - public var neighbor: Node - - public init(neighbor: Node) { - self.neighbor = neighbor - } + public var neighbor: Node + + public init(neighbor: Node) { + self.neighbor = neighbor + } } public func == (lhs: Edge, rhs: Edge) -> Bool { - return lhs.neighbor == rhs.neighbor + return lhs.neighbor == rhs.neighbor } + // MARK: - Node public class Node: CustomStringConvertible, Equatable { - public var neighbors: [Edge] - - public private(set) var label: String - public var distance: Int? - public var visited: Bool - - public init(label: String) { - self.label = label - neighbors = [] - visited = false - } - - public var description: String { - if let distance = distance { - return "Node(label: \(label), distance: \(distance))" + public var neighbors: [Edge] + + public private(set) var label: String + public var distance: Int? + public var visited: Bool + + public init(label: String) { + self.label = label + neighbors = [] + visited = false + } + + public var description: String { + if let distance = distance { + return "Node(label: \(label), distance: \(distance))" + } + return "Node(label: \(label), distance: infinity)" + } + + public var hasDistance: Bool { + return distance != nil + } + + public func remove(edge: Edge) { + neighbors.remove(at: neighbors.index { $0 === edge }!) } - return "Node(label: \(label), distance: infinity)" - } - - public var hasDistance: Bool { - return distance != nil - } - - public func remove(edge: Edge) { - neighbors.removeAtIndex(neighbors.indexOf { $0 === edge }!) - } } public func == (lhs: Node, rhs: Node) -> Bool { - return lhs.label == rhs.label && lhs.neighbors == rhs.neighbors + return lhs.label == rhs.label && lhs.neighbors == rhs.neighbors } // MARK: - Graph public class Graph: CustomStringConvertible, Equatable { - public private(set) var nodes: [Node] - - public init() { - self.nodes = [] - } - - public func addNode(label: String) -> Node { - let node = Node(label: label) - nodes.append(node) - return node - } - - public func addEdge(source: Node, neighbor: Node) { - let edge = Edge(neighbor: neighbor) - source.neighbors.append(edge) - } - - public var description: String { - var description = "" - - for node in nodes { - if !node.neighbors.isEmpty { - description += "[node: \(node.label) edges: \(node.neighbors.map { $0.neighbor.label})]" - } + public private(set) var nodes: [Node] + + public init() { + self.nodes = [] } - return description - } - - public func findNodeWithLabel(label: String) -> Node { - return nodes.filter { $0.label == label }.first! - } - - public func duplicate() -> Graph { - let duplicated = Graph() - - for node in nodes { - duplicated.addNode(node.label) + + public func addNode(label: String) -> Node { + let node = Node(label: label) + nodes.append(node) + return node } - - for node in nodes { - for edge in node.neighbors { - let source = duplicated.findNodeWithLabel(node.label) - let neighbour = duplicated.findNodeWithLabel(edge.neighbor.label) - duplicated.addEdge(source, neighbor: neighbour) - } + + public func addEdge(_ source: Node, neighbor: Node) { + let edge = Edge(neighbor: neighbor) + source.neighbors.append(edge) + } + + public var description: String { + var description = "" + + for node in nodes { + if !node.neighbors.isEmpty { + description += "[node: \(node.label) edges: \(node.neighbors.map { $0.neighbor.label})]" + } + } + return description + } + + public func findNodeWithLabel(label: String) -> Node { + return nodes.filter { $0.label == label }.first! + } + + public func duplicate() -> Graph { + let duplicated = Graph() + + for node in nodes { + duplicated.addNode(label: node.label) + } + + for node in nodes { + for edge in node.neighbors { + let source = duplicated.findNodeWithLabel(label: node.label) + let neighbour = duplicated.findNodeWithLabel(label: edge.neighbor.label) + duplicated.addEdge(source, neighbor: neighbour) + } + } + + return duplicated } - - return duplicated - } } public func == (lhs: Graph, rhs: Graph) -> Bool { - return lhs.nodes == rhs.nodes + return lhs.nodes == rhs.nodes } diff --git a/Shortest Path (Unweighted)/Tests/ShortestPathTests.swift b/Shortest Path (Unweighted)/Tests/ShortestPathTests.swift index 003f3cf20..71b9f88ab 100644 --- a/Shortest Path (Unweighted)/Tests/ShortestPathTests.swift +++ b/Shortest Path (Unweighted)/Tests/ShortestPathTests.swift @@ -4,14 +4,14 @@ class ShortestPathTests: XCTestCase { func testShortestPathWhenGivenTree() { let tree = Graph() - let nodeA = tree.addNode("a") - let nodeB = tree.addNode("b") - let nodeC = tree.addNode("c") - let nodeD = tree.addNode("d") - let nodeE = tree.addNode("e") - let nodeF = tree.addNode("f") - let nodeG = tree.addNode("g") - let nodeH = tree.addNode("h") + let nodeA = tree.addNode(label: "a") + let nodeB = tree.addNode(label: "b") + let nodeC = tree.addNode(label: "c") + let nodeD = tree.addNode(label: "d") + let nodeE = tree.addNode(label: "e") + let nodeF = tree.addNode(label: "f") + let nodeG = tree.addNode(label: "g") + let nodeH = tree.addNode(label: "h") tree.addEdge(nodeA, neighbor: nodeB) tree.addEdge(nodeA, neighbor: nodeC) tree.addEdge(nodeB, neighbor: nodeD) @@ -20,30 +20,30 @@ class ShortestPathTests: XCTestCase { tree.addEdge(nodeC, neighbor: nodeG) tree.addEdge(nodeE, neighbor: nodeH) - let shortestPaths = breadthFirstSearchShortestPath(tree, source: nodeA) + let shortestPaths = breadthFirstSearchShortestPath(graph: tree, source: nodeA) - XCTAssertEqual(shortestPaths.findNodeWithLabel(nodeA.label).distance, 0) - XCTAssertEqual(shortestPaths.findNodeWithLabel(nodeB.label).distance, 1) - XCTAssertEqual(shortestPaths.findNodeWithLabel(nodeC.label).distance, 1) - XCTAssertEqual(shortestPaths.findNodeWithLabel(nodeD.label).distance, 2) - XCTAssertEqual(shortestPaths.findNodeWithLabel(nodeE.label).distance, 2) - XCTAssertEqual(shortestPaths.findNodeWithLabel(nodeF.label).distance, 2) - XCTAssertEqual(shortestPaths.findNodeWithLabel(nodeG.label).distance, 2) - XCTAssertEqual(shortestPaths.findNodeWithLabel(nodeH.label).distance, 3) + XCTAssertEqual(shortestPaths.findNodeWithLabel(label: nodeA.label).distance, 0) + XCTAssertEqual(shortestPaths.findNodeWithLabel(label: nodeB.label).distance, 1) + XCTAssertEqual(shortestPaths.findNodeWithLabel(label: nodeC.label).distance, 1) + XCTAssertEqual(shortestPaths.findNodeWithLabel(label: nodeD.label).distance, 2) + XCTAssertEqual(shortestPaths.findNodeWithLabel(label: nodeE.label).distance, 2) + XCTAssertEqual(shortestPaths.findNodeWithLabel(label: nodeF.label).distance, 2) + XCTAssertEqual(shortestPaths.findNodeWithLabel(label: nodeG.label).distance, 2) + XCTAssertEqual(shortestPaths.findNodeWithLabel(label: nodeH.label).distance, 3) } func testShortestPathWhenGivenGraph() { let graph = Graph() - let nodeA = graph.addNode("a") - let nodeB = graph.addNode("b") - let nodeC = graph.addNode("c") - let nodeD = graph.addNode("d") - let nodeE = graph.addNode("e") - let nodeF = graph.addNode("f") - let nodeG = graph.addNode("g") - let nodeH = graph.addNode("h") - let nodeI = graph.addNode("i") + let nodeA = graph.addNode(label:"a") + let nodeB = graph.addNode(label:"b") + let nodeC = graph.addNode(label:"c") + let nodeD = graph.addNode(label:"d") + let nodeE = graph.addNode(label:"e") + let nodeF = graph.addNode(label:"f") + let nodeG = graph.addNode(label:"g") + let nodeH = graph.addNode(label:"h") + let nodeI = graph.addNode(label:"i") graph.addEdge(nodeA, neighbor: nodeB) graph.addEdge(nodeA, neighbor: nodeH) @@ -74,16 +74,16 @@ class ShortestPathTests: XCTestCase { graph.addEdge(nodeI, neighbor: nodeG) graph.addEdge(nodeI, neighbor: nodeH) - let shortestPaths = breadthFirstSearchShortestPath(graph, source: nodeA) + let shortestPaths = breadthFirstSearchShortestPath(graph: graph, source: nodeA) - XCTAssertEqual(shortestPaths.findNodeWithLabel(nodeA.label).distance, 0) - XCTAssertEqual(shortestPaths.findNodeWithLabel(nodeB.label).distance, 1) - XCTAssertEqual(shortestPaths.findNodeWithLabel(nodeC.label).distance, 2) - XCTAssertEqual(shortestPaths.findNodeWithLabel(nodeD.label).distance, 3) - XCTAssertEqual(shortestPaths.findNodeWithLabel(nodeE.label).distance, 4) - XCTAssertEqual(shortestPaths.findNodeWithLabel(nodeF.label).distance, 3) - XCTAssertEqual(shortestPaths.findNodeWithLabel(nodeG.label).distance, 2) - XCTAssertEqual(shortestPaths.findNodeWithLabel(nodeH.label).distance, 1) - XCTAssertEqual(shortestPaths.findNodeWithLabel(nodeI.label).distance, 2) + XCTAssertEqual(shortestPaths.findNodeWithLabel(label: nodeA.label).distance, 0) + XCTAssertEqual(shortestPaths.findNodeWithLabel(label: nodeB.label).distance, 1) + XCTAssertEqual(shortestPaths.findNodeWithLabel(label: nodeC.label).distance, 2) + XCTAssertEqual(shortestPaths.findNodeWithLabel(label: nodeD.label).distance, 3) + XCTAssertEqual(shortestPaths.findNodeWithLabel(label: nodeE.label).distance, 4) + XCTAssertEqual(shortestPaths.findNodeWithLabel(label: nodeF.label).distance, 3) + XCTAssertEqual(shortestPaths.findNodeWithLabel(label: nodeG.label).distance, 2) + XCTAssertEqual(shortestPaths.findNodeWithLabel(label: nodeH.label).distance, 1) + XCTAssertEqual(shortestPaths.findNodeWithLabel(label: nodeI.label).distance, 2) } } From 6eed97951a180899d8887c739bdb493e554e99da Mon Sep 17 00:00:00 2001 From: gonini Date: Tue, 3 Jan 2017 09:51:16 +0900 Subject: [PATCH 0749/1679] Updated with XCTest Swift3 syntax for shortest path XCTest Success --- Shortest Path (Unweighted)/ShortestPath.swift | 4 +-- Shortest Path (Unweighted)/Tests/Graph.swift | 34 +++++++++---------- Shortest Path (Unweighted)/Tests/Queue.swift | 2 +- .../Tests/Tests.xcodeproj/project.pbxproj | 3 ++ 4 files changed, 23 insertions(+), 20 deletions(-) diff --git a/Shortest Path (Unweighted)/ShortestPath.swift b/Shortest Path (Unweighted)/ShortestPath.swift index 6aa082a96..555ad893b 100644 --- a/Shortest Path (Unweighted)/ShortestPath.swift +++ b/Shortest Path (Unweighted)/ShortestPath.swift @@ -2,8 +2,8 @@ func breadthFirstSearchShortestPath(graph: Graph, source: Node) -> Graph { let shortestPathGraph = graph.duplicate() var queue = Queue() - let sourceInShortestPathsGraph = shortestPathGraph.findNodeWithLabel(source.label) - queue.enqueue(sourceInShortestPathsGraph) + let sourceInShortestPathsGraph = shortestPathGraph.findNodeWithLabel(label: source.label) + queue.enqueue(element: sourceInShortestPathsGraph) sourceInShortestPathsGraph.distance = 0 while let current = queue.dequeue() { diff --git a/Shortest Path (Unweighted)/Tests/Graph.swift b/Shortest Path (Unweighted)/Tests/Graph.swift index 0d2a735c2..8322ba0a9 100644 --- a/Shortest Path (Unweighted)/Tests/Graph.swift +++ b/Shortest Path (Unweighted)/Tests/Graph.swift @@ -1,7 +1,7 @@ // MARK: - Edge -public class Edge: Equatable { - public var neighbor: Node +open class Edge: Equatable { + open var neighbor: Node public init(neighbor: Node) { self.neighbor = neighbor @@ -15,12 +15,12 @@ public func == (lhs: Edge, rhs: Edge) -> Bool { // MARK: - Node -public class Node: CustomStringConvertible, Equatable { - public var neighbors: [Edge] +open class Node: CustomStringConvertible, Equatable { + open var neighbors: [Edge] - public private(set) var label: String - public var distance: Int? - public var visited: Bool + open fileprivate(set) var label: String + open var distance: Int? + open var visited: Bool public init(label: String) { self.label = label @@ -28,18 +28,18 @@ public class Node: CustomStringConvertible, Equatable { visited = false } - public var description: String { + open var description: String { if let distance = distance { return "Node(label: \(label), distance: \(distance))" } return "Node(label: \(label), distance: infinity)" } - public var hasDistance: Bool { + open var hasDistance: Bool { return distance != nil } - public func remove(edge: Edge) { + open func remove(_ edge: Edge) { neighbors.remove(at: neighbors.index { $0 === edge }!) } } @@ -50,25 +50,25 @@ public func == (lhs: Node, rhs: Node) -> Bool { // MARK: - Graph -public class Graph: CustomStringConvertible, Equatable { - public private(set) var nodes: [Node] +open class Graph: CustomStringConvertible, Equatable { + open fileprivate(set) var nodes: [Node] public init() { self.nodes = [] } - public func addNode(label: String) -> Node { + open func addNode(label: String) -> Node { let node = Node(label: label) nodes.append(node) return node } - public func addEdge(_ source: Node, neighbor: Node) { + open func addEdge(_ source: Node, neighbor: Node) { let edge = Edge(neighbor: neighbor) source.neighbors.append(edge) } - public var description: String { + open var description: String { var description = "" for node in nodes { @@ -79,11 +79,11 @@ public class Graph: CustomStringConvertible, Equatable { return description } - public func findNodeWithLabel(label: String) -> Node { + open func findNodeWithLabel(label: String) -> Node { return nodes.filter { $0.label == label }.first! } - public func duplicate() -> Graph { + open func duplicate() -> Graph { let duplicated = Graph() for node in nodes { diff --git a/Shortest Path (Unweighted)/Tests/Queue.swift b/Shortest Path (Unweighted)/Tests/Queue.swift index bf462bbdd..0d8752466 100644 --- a/Shortest Path (Unweighted)/Tests/Queue.swift +++ b/Shortest Path (Unweighted)/Tests/Queue.swift @@ -1,5 +1,5 @@ public struct Queue { - private var array: [T] + fileprivate var array: [T] public init() { array = [] diff --git a/Shortest Path (Unweighted)/Tests/Tests.xcodeproj/project.pbxproj b/Shortest Path (Unweighted)/Tests/Tests.xcodeproj/project.pbxproj index 35aeffa54..f1744fcf1 100644 --- a/Shortest Path (Unweighted)/Tests/Tests.xcodeproj/project.pbxproj +++ b/Shortest Path (Unweighted)/Tests/Tests.xcodeproj/project.pbxproj @@ -94,6 +94,7 @@ TargetAttributes = { 7B2BBC7F1C779D720067B71D = { CreatedOnToolsVersion = 7.2; + LastSwiftMigration = 0820; }; }; }; @@ -230,6 +231,7 @@ PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -242,6 +244,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Release; }; From 914441ec8285ae1e8354c22f692a81ae9bb70de7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20B=C3=B8dskov?= Date: Tue, 3 Jan 2017 14:40:59 +0100 Subject: [PATCH 0750/1679] converts Huffman Coding to Swift 3 syntax --- .../Huffman.playground/Contents.swift | 10 +- .../Huffman.playground/Sources/Heap.swift | 34 +- .../Huffman.playground/Sources/Huffman.swift | 30 +- .../Sources/NSData+Bits.swift | 8 +- .../Sources/PriorityQueue.swift | 8 +- .../Huffman.playground/timeline.xctimeline | 10 + Huffman Coding/Huffman.swift | 294 +++++++++--------- Huffman Coding/NSData+Bits.swift | 76 ++--- Huffman Coding/README.markdown | 52 ++-- 9 files changed, 265 insertions(+), 257 deletions(-) diff --git a/Huffman Coding/Huffman.playground/Contents.swift b/Huffman Coding/Huffman.playground/Contents.swift index b67f93a6a..017c5baf2 100644 --- a/Huffman Coding/Huffman.playground/Contents.swift +++ b/Huffman Coding/Huffman.playground/Contents.swift @@ -3,21 +3,21 @@ import Foundation let s1 = "so much words wow many compression" -if let originalData = s1.dataUsingEncoding(NSUTF8StringEncoding) { - print(originalData.length) +if let originalData = s1.data(using: String.Encoding.utf8) { + print(originalData.count) let huffman1 = Huffman() - let compressedData = huffman1.compressData(originalData) + let compressedData = huffman1.compressData(data: originalData as NSData) print(compressedData.length) let frequencyTable = huffman1.frequencyTable() //print(frequencyTable) let huffman2 = Huffman() - let decompressedData = huffman2.decompressData(compressedData, frequencyTable: frequencyTable) + let decompressedData = huffman2.decompressData(data: compressedData, frequencyTable: frequencyTable) print(decompressedData.length) - let s2 = String(data: decompressedData, encoding: NSUTF8StringEncoding)! + let s2 = String(data: decompressedData as Data, encoding: String.Encoding.utf8)! print(s2) assert(s1 == s2) } diff --git a/Huffman Coding/Huffman.playground/Sources/Heap.swift b/Huffman Coding/Huffman.playground/Sources/Heap.swift index 64bd90cd8..5ace98a17 100644 --- a/Huffman Coding/Huffman.playground/Sources/Heap.swift +++ b/Huffman Coding/Huffman.playground/Sources/Heap.swift @@ -8,14 +8,14 @@ public struct Heap { var elements = [T]() /** Determines whether this is a max-heap (>) or min-heap (<). */ - private var isOrderedBefore: (T, T) -> Bool + fileprivate var isOrderedBefore: (T, T) -> Bool /** * Creates an empty heap. * The sort function determines whether this is a min-heap or max-heap. * For integers, > makes a max-heap, < makes a min-heap. */ - public init(sort: (T, T) -> Bool) { + public init(sort: @escaping (T, T) -> Bool) { self.isOrderedBefore = sort } @@ -24,9 +24,9 @@ public struct Heap { * the elements are inserted into the heap in the order determined by the * sort function. */ - public init(array: [T], sort: (T, T) -> Bool) { + public init(array: [T], sort: @escaping (T, T) -> Bool) { self.isOrderedBefore = sort - buildHeap(array) + buildHeap(array: array) } /* @@ -45,7 +45,7 @@ public struct Heap { */ private mutating func buildHeap(array: [T]) { elements = array - for i in (elements.count/2 - 1).stride(through: 0, by: -1) { + for i in stride(from: elements.count/2 - 1, to: 0, by: -1) { shiftDown(index: i, heapSize: elements.count) } } @@ -96,12 +96,12 @@ public struct Heap { * Adds a new value to the heap. This reorders the heap so that the max-heap * or min-heap property still holds. Performance: O(log n). */ - public mutating func insert(value: T) { + public mutating func insert(_ value: T) { elements.append(value) shiftUp(index: elements.count - 1) } - public mutating func insert(sequence: S) { + public mutating func insert(sequence: S) where S.Iterator.Element == T { for value in sequence { insert(value) } @@ -154,15 +154,15 @@ public struct Heap { * Takes a child node and looks at its parents; if a parent is not larger * (max-heap) or not smaller (min-heap) than the child, we exchange them. */ - mutating func shiftUp(index index: Int) { + mutating func shiftUp(index: Int) { var childIndex = index let child = elements[childIndex] - var parentIndex = indexOfParent(childIndex) + var parentIndex = indexOfParent(i: childIndex) while childIndex > 0 && isOrderedBefore(child, elements[parentIndex]) { elements[childIndex] = elements[parentIndex] childIndex = parentIndex - parentIndex = indexOfParent(childIndex) + parentIndex = indexOfParent(i: childIndex) } elements[childIndex] = child @@ -176,11 +176,11 @@ public struct Heap { * Looks at a parent node and makes sure it is still larger (max-heap) or * smaller (min-heap) than its childeren. */ - mutating func shiftDown(index index: Int, heapSize: Int) { + mutating func shiftDown(index: Int, heapSize: Int) { var parentIndex = index while true { - let leftChildIndex = indexOfLeftChild(parentIndex) + let leftChildIndex = indexOfLeftChild(i: parentIndex) let rightChildIndex = leftChildIndex + 1 // Figure out which comes first if we order them by the sort function: @@ -208,16 +208,16 @@ extension Heap where T: Equatable { /** * Searches the heap for the given element. Performance: O(n). */ - public func indexOf(element: T) -> Int? { - return indexOf(element, 0) + public func index(of element: T) -> Int? { + return index(of: element, 0) } - private func indexOf(element: T, _ i: Int) -> Int? { + private func index(of element: T, _ i: Int) -> Int? { if i >= count { return nil } if isOrderedBefore(element, elements[i]) { return nil } if element == elements[i] { return i } - if let j = indexOf(element, indexOfLeftChild(i)) { return j } - if let j = indexOf(element, indexOfRightChild(i)) { return j } + if let j = index(of: element, indexOfLeftChild(i: i)) { return j } + if let j = index(of: element, indexOfRightChild(i: i)) { return j } return nil } } diff --git a/Huffman Coding/Huffman.playground/Sources/Huffman.swift b/Huffman Coding/Huffman.playground/Sources/Huffman.swift index d50b90d82..79b24b09a 100644 --- a/Huffman Coding/Huffman.playground/Sources/Huffman.swift +++ b/Huffman Coding/Huffman.playground/Sources/Huffman.swift @@ -29,7 +29,7 @@ public class Huffman { /* The tree structure. The first 256 entries are for the leaf nodes (not all of those may be used, depending on the input). We add additional nodes as we build the tree. */ - var tree = [Node](count: 256, repeatedValue: Node()) + var tree = [Node](repeating: Node(), count: 256) /* This is the last node we add to the tree. */ var root: NodeIndex = -1 @@ -50,10 +50,10 @@ extension Huffman { occurs. These counts are stored in the first 256 nodes in the tree, i.e. the leaf nodes. The frequency table used by decompression is derived from this. */ - private func countByteFrequency(data: NSData) { - var ptr = UnsafePointer(data.bytes) + fileprivate func countByteFrequency(inData data: NSData) { + var ptr = data.bytes.assumingMemoryBound(to: UInt8.self) for _ in 0..(sort: { $0.count < $1.count }) for node in tree where node.count > 0 { @@ -123,13 +123,13 @@ extension Huffman { extension Huffman { /* Compresses the contents of an NSData object. */ public func compressData(data: NSData) -> NSData { - countByteFrequency(data) + countByteFrequency(inData: data) buildTree() let writer = BitWriter() - var ptr = UnsafePointer(data.bytes) + var ptr = data.bytes.assumingMemoryBound(to: UInt8.self) for _ in 0.. NSData { - restoreTree(frequencyTable) + restoreTree(fromTable: frequencyTable) let reader = BitReader(data: data) let outData = NSMutableData() @@ -167,7 +167,7 @@ extension Huffman { var i = 0 while i < byteCount { var b = findLeafNode(reader: reader, nodeIndex: root) - outData.appendBytes(&b, length: 1) + outData.append(&b, length: 1) i += 1 } return outData @@ -177,7 +177,7 @@ extension Huffman { next bit and use that to determine whether to step to the left or right. When we get to the leaf node, we simply return its index, which is equal to the original byte value. */ - private func findLeafNode(reader reader: BitReader, nodeIndex: Int) -> UInt8 { + private func findLeafNode(reader: BitReader, nodeIndex: Int) -> UInt8 { var h = nodeIndex while tree[h].right != -1 { if reader.readBit() { diff --git a/Huffman Coding/Huffman.playground/Sources/NSData+Bits.swift b/Huffman Coding/Huffman.playground/Sources/NSData+Bits.swift index 0aa821f72..3e5163521 100644 --- a/Huffman Coding/Huffman.playground/Sources/NSData+Bits.swift +++ b/Huffman Coding/Huffman.playground/Sources/NSData+Bits.swift @@ -8,7 +8,7 @@ public class BitWriter { public func writeBit(bit: Bool) { if outCount == 8 { - data.appendBytes(&outByte, length: 1) + data.append(&outByte, length: 1) outCount = 0 } outByte = (outByte << 1) | (bit ? 1 : 0) @@ -21,7 +21,7 @@ public class BitWriter { let diff = UInt8(8 - outCount) outByte <<= diff } - data.appendBytes(&outByte, length: 1) + data.append(&outByte, length: 1) } } } @@ -33,12 +33,12 @@ public class BitReader { var inCount = 8 public init(data: NSData) { - ptr = UnsafePointer(data.bytes) + ptr = data.bytes.assumingMemoryBound(to: UInt8.self) } public func readBit() -> Bool { if inCount == 8 { - inByte = ptr.memory // load the next byte + inByte = ptr.pointee // load the next byte inCount = 0 ptr = ptr.successor() } diff --git a/Huffman Coding/Huffman.playground/Sources/PriorityQueue.swift b/Huffman Coding/Huffman.playground/Sources/PriorityQueue.swift index 757a6c539..4cc9d15ed 100644 --- a/Huffman Coding/Huffman.playground/Sources/PriorityQueue.swift +++ b/Huffman Coding/Huffman.playground/Sources/PriorityQueue.swift @@ -11,13 +11,13 @@ queue (largest element first) or a min-priority queue (smallest element first). */ public struct PriorityQueue { - private var heap: Heap + fileprivate var heap: Heap /* To create a max-priority queue, supply a > sort function. For a min-priority queue, use <. */ - public init(sort: (T, T) -> Bool) { + public init(sort: @escaping (T, T) -> Bool) { heap = Heap(sort: sort) } @@ -33,7 +33,7 @@ public struct PriorityQueue { return heap.peek() } - public mutating func enqueue(element: T) { + public mutating func enqueue(_ element: T) { heap.insert(element) } @@ -53,6 +53,6 @@ public struct PriorityQueue { extension PriorityQueue where T: Equatable { public func indexOf(element: T) -> Int? { - return heap.indexOf(element) + return heap.index(of: element) } } diff --git a/Huffman Coding/Huffman.playground/timeline.xctimeline b/Huffman Coding/Huffman.playground/timeline.xctimeline index bf468afec..2b2555bb1 100644 --- a/Huffman Coding/Huffman.playground/timeline.xctimeline +++ b/Huffman Coding/Huffman.playground/timeline.xctimeline @@ -2,5 +2,15 @@ + + + + diff --git a/Huffman Coding/Huffman.swift b/Huffman Coding/Huffman.swift index d50b90d82..7e2961a2f 100644 --- a/Huffman Coding/Huffman.swift +++ b/Huffman Coding/Huffman.swift @@ -1,191 +1,191 @@ import Foundation /* - Basic implementation of Huffman encoding. It encodes bytes that occur often - with a smaller number of bits than bytes that occur less frequently. - - Based on Al Stevens' C Programming column from Dr.Dobb's Magazine, February - 1991 and October 1992. - - Note: This code is not optimized for speed but explanation. -*/ + Basic implementation of Huffman encoding. It encodes bytes that occur often + with a smaller number of bits than bytes that occur less frequently. + + Based on Al Stevens' C Programming column from Dr.Dobb's Magazine, February + 1991 and October 1992. + + Note: This code is not optimized for speed but explanation. + */ public class Huffman { - /* Tree nodes don't use pointers to refer to each other, but simple integer + /* Tree nodes don't use pointers to refer to each other, but simple integer indices. That allows us to use structs for the nodes. */ - typealias NodeIndex = Int - - /* A node in the compression tree. Leaf nodes represent the actual bytes that + typealias NodeIndex = Int + + /* A node in the compression tree. Leaf nodes represent the actual bytes that are present in the input data. The count of an intermediary node is the sum of the counts of all nodes below it. The root node's count is the number of bytes in the original, uncompressed input data. */ - struct Node { - var count = 0 - var index: NodeIndex = -1 - var parent: NodeIndex = -1 - var left: NodeIndex = -1 - var right: NodeIndex = -1 - } - - /* The tree structure. The first 256 entries are for the leaf nodes (not all + struct Node { + var count = 0 + var index: NodeIndex = -1 + var parent: NodeIndex = -1 + var left: NodeIndex = -1 + var right: NodeIndex = -1 + } + + /* The tree structure. The first 256 entries are for the leaf nodes (not all of those may be used, depending on the input). We add additional nodes as we build the tree. */ - var tree = [Node](count: 256, repeatedValue: Node()) - - /* This is the last node we add to the tree. */ - var root: NodeIndex = -1 - - /* The frequency table describes how often a byte occurs in the input data. + var tree = [Node](repeating: Node(), count: 256) + + /* This is the last node we add to the tree. */ + var root: NodeIndex = -1 + + /* The frequency table describes how often a byte occurs in the input data. You need it to decompress the Huffman-encoded data. The frequency table should be serialized along with the compressed data. */ - public struct Freq { - var byte: UInt8 = 0 - var count = 0 - } - - public init() { } + public struct Freq { + var byte: UInt8 = 0 + var count = 0 + } + + public init() { } } extension Huffman { - /* To compress a block of data, first we need to count how often each byte + /* To compress a block of data, first we need to count how often each byte occurs. These counts are stored in the first 256 nodes in the tree, i.e. the leaf nodes. The frequency table used by decompression is derived from this. */ - private func countByteFrequency(data: NSData) { - var ptr = UnsafePointer(data.bytes) - for _ in 0.. [Freq] { - var a = [Freq]() - for i in 0..<256 where tree[i].count > 0 { - a.append(Freq(byte: UInt8(i), count: tree[i].count)) + public func frequencyTable() -> [Freq] { + var a = [Freq]() + for i in 0..<256 where tree[i].count > 0 { + a.append(Freq(byte: UInt8(i), count: tree[i].count)) + } + return a } - return a - } } extension Huffman { - /* Builds a Huffman tree from a frequency table. */ - private func buildTree() { - // Create a min-priority queue and enqueue all used nodes. - var queue = PriorityQueue(sort: { $0.count < $1.count }) - for node in tree where node.count > 0 { - queue.enqueue(node) + /* Builds a Huffman tree from a frequency table. */ + fileprivate func buildTree() { + // Create a min-priority queue and enqueue all used nodes. + var queue = PriorityQueue(sort: { $0.count < $1.count }) + for node in tree where node.count > 0 { + queue.enqueue(node) + } + + while queue.count > 1 { + // Find the two nodes with the smallest frequencies that do not have + // a parent node yet. + let node1 = queue.dequeue()! + let node2 = queue.dequeue()! + + // Create a new intermediate node. + var parentNode = Node() + parentNode.count = node1.count + node2.count + parentNode.left = node1.index + parentNode.right = node2.index + parentNode.index = tree.count + tree.append(parentNode) + + // Link the two nodes into their new parent node. + tree[node1.index].parent = parentNode.index + tree[node2.index].parent = parentNode.index + + // Put the intermediate node back into the queue. + queue.enqueue(parentNode) + } + + // The final remaining node in the queue becomes the root of the tree. + let rootNode = queue.dequeue()! + root = rootNode.index } - - while queue.count > 1 { - // Find the two nodes with the smallest frequencies that do not have - // a parent node yet. - let node1 = queue.dequeue()! - let node2 = queue.dequeue()! - - // Create a new intermediate node. - var parentNode = Node() - parentNode.count = node1.count + node2.count - parentNode.left = node1.index - parentNode.right = node2.index - parentNode.index = tree.count - tree.append(parentNode) - - // Link the two nodes into their new parent node. - tree[node1.index].parent = parentNode.index - tree[node2.index].parent = parentNode.index - - // Put the intermediate node back into the queue. - queue.enqueue(parentNode) - } - - // The final remaining node in the queue becomes the root of the tree. - let rootNode = queue.dequeue()! - root = rootNode.index - } } extension Huffman { - /* Compresses the contents of an NSData object. */ - public func compressData(data: NSData) -> NSData { - countByteFrequency(data) - buildTree() - - let writer = BitWriter() - var ptr = UnsafePointer(data.bytes) - for _ in 0.. NSData { + countByteFrequency(inData: data) + buildTree() + + let writer = BitWriter() + var ptr = data.bytes.assumingMemoryBound(to: UInt8.self) + for _ in 0.. NSData { - restoreTree(frequencyTable) - - let reader = BitReader(data: data) - let outData = NSMutableData() - let byteCount = tree[root].count - - var i = 0 - while i < byteCount { - var b = findLeafNode(reader: reader, nodeIndex: root) - outData.appendBytes(&b, length: 1) - i += 1 + /* Takes a Huffman-compressed NSData object and outputs the uncompressed data. */ + public func decompressData(data: NSData, frequencyTable: [Freq]) -> NSData { + restoreTree(fromTable: frequencyTable) + + let reader = BitReader(data: data) + let outData = NSMutableData() + let byteCount = tree[root].count + + var i = 0 + while i < byteCount { + var b = findLeafNode(reader: reader, nodeIndex: root) + outData.append(&b, length: 1) + i += 1 + } + return outData } - return outData - } - - /* Walks the tree from the root down to the leaf node. At every node, read the + + /* Walks the tree from the root down to the leaf node. At every node, read the next bit and use that to determine whether to step to the left or right. When we get to the leaf node, we simply return its index, which is equal to the original byte value. */ - private func findLeafNode(reader reader: BitReader, nodeIndex: Int) -> UInt8 { - var h = nodeIndex - while tree[h].right != -1 { - if reader.readBit() { - h = tree[h].left - } else { - h = tree[h].right - } + private func findLeafNode(reader: BitReader, nodeIndex: Int) -> UInt8 { + var h = nodeIndex + while tree[h].right != -1 { + if reader.readBit() { + h = tree[h].left + } else { + h = tree[h].right + } + } + return UInt8(h) } - return UInt8(h) - } } diff --git a/Huffman Coding/NSData+Bits.swift b/Huffman Coding/NSData+Bits.swift index 0aa821f72..4ae3c5c6d 100644 --- a/Huffman Coding/NSData+Bits.swift +++ b/Huffman Coding/NSData+Bits.swift @@ -2,49 +2,49 @@ import Foundation /* Helper class for writing bits to an NSData object. */ public class BitWriter { - public var data = NSMutableData() - var outByte: UInt8 = 0 - var outCount = 0 - - public func writeBit(bit: Bool) { - if outCount == 8 { - data.appendBytes(&outByte, length: 1) - outCount = 0 + public var data = NSMutableData() + var outByte: UInt8 = 0 + var outCount = 0 + + public func writeBit(bit: Bool) { + if outCount == 8 { + data.append(&outByte, length: 1) + outCount = 0 + } + outByte = (outByte << 1) | (bit ? 1 : 0) + outCount += 1 } - outByte = (outByte << 1) | (bit ? 1 : 0) - outCount += 1 - } - - public func flush() { - if outCount > 0 { - if outCount < 8 { - let diff = UInt8(8 - outCount) - outByte <<= diff - } - data.appendBytes(&outByte, length: 1) + + public func flush() { + if outCount > 0 { + if outCount < 8 { + let diff = UInt8(8 - outCount) + outByte <<= diff + } + data.append(&outByte, length: 1) + } } - } } /* Helper class for reading bits from an NSData object. */ public class BitReader { - var ptr: UnsafePointer - var inByte: UInt8 = 0 - var inCount = 8 - - public init(data: NSData) { - ptr = UnsafePointer(data.bytes) - } - - public func readBit() -> Bool { - if inCount == 8 { - inByte = ptr.memory // load the next byte - inCount = 0 - ptr = ptr.successor() + var ptr: UnsafePointer + var inByte: UInt8 = 0 + var inCount = 8 + + public init(data: NSData) { + ptr = data.bytes.assumingMemoryBound(to: UInt8.self) + } + + public func readBit() -> Bool { + if inCount == 8 { + inByte = ptr.pointee // load the next byte + inCount = 0 + ptr = ptr.successor() + } + let bit = inByte & 0x80 // read the next bit + inByte <<= 1 + inCount += 1 + return bit == 0 ? false : true } - let bit = inByte & 0x80 // read the next bit - inByte <<= 1 - inCount += 1 - return bit == 0 ? false : true - } } diff --git a/Huffman Coding/README.markdown b/Huffman Coding/README.markdown index 528ba3a1d..6b2c0d245 100644 --- a/Huffman Coding/README.markdown +++ b/Huffman Coding/README.markdown @@ -70,10 +70,10 @@ public class BitWriter { public var data = NSMutableData() var outByte: UInt8 = 0 var outCount = 0 - + public func writeBit(bit: Bool) { if outCount == 8 { - data.appendBytes(&outByte, length: 1) + data.append(&outByte, length: 1) outCount = 0 } outByte = (outByte << 1) | (bit ? 1 : 0) @@ -86,7 +86,7 @@ public class BitWriter { let diff = UInt8(8 - outCount) outByte <<= diff } - data.appendBytes(&outByte, length: 1) + data.append(&outByte, length: 1) } } } @@ -103,14 +103,14 @@ public class BitReader { var ptr: UnsafePointer var inByte: UInt8 = 0 var inCount = 8 - + public init(data: NSData) { - ptr = UnsafePointer(data.bytes) + ptr = data.bytes.assumingMemoryBound(to: UInt8.self) } - + public func readBit() -> Bool { if inCount == 8 { - inByte = ptr.memory // load the next byte + inByte = ptr.pointee // load the next byte inCount = 0 ptr = ptr.successor() } @@ -145,8 +145,8 @@ class Huffman { var left: NodeIndex = -1 var right: NodeIndex = -1 } - - var tree = [Node](count: 256, repeatedValue: Node()) + + var tree = [Node](repeating: Node(), count: 256) var root: NodeIndex = -1 } @@ -159,10 +159,10 @@ Note that `tree` currently has room for 256 entries. These are for the leaf node We use the following method to count how often each byte occurs in the input data: ```swift - private func countByteFrequency(data: NSData) { - var ptr = UnsafePointer(data.bytes) + fileprivate func countByteFrequency(inData data: NSData) { + var ptr = data.bytes.assumingMemoryBound(to: UInt8.self) for _ in 0..(sort: { $0.count < $1.count }) for node in tree where node.count > 0 { queue.enqueue(node) // 1 @@ -252,7 +252,7 @@ Here is how it works step-by-step: 4. Link the two nodes into their new parent node. Now this new intermediate node has become part of the tree. -5. Put the new intermediate node back into the queue. At this point we're done with `node1` and `node2`, but the `parentNode` stills need to be connected to other nodes in the tree. +5. Put the new intermediate node back into the queue. At this point we're done with `node1` and `node2`, but the `parentNode` still need to be connected to other nodes in the tree. 6. Repeat steps 2-5 until there is only one node left in the queue. This becomes the root node of the tree, and we're done. @@ -269,20 +269,18 @@ The animation shows what the process looks like: Now that we know how to build the compression tree from the frequency table, we can use it to compress the contents of an `NSData` object. Here is the code: ```swift - func compressData(data: NSData) -> NSData { - countByteFrequency(data) + public func compressData(data: NSData) -> NSData { + countByteFrequency(inData: data) buildTree() - - let writer = BitWriter() - var ptr = UnsafePointer(data.bytes) + let writer = BitWriter() + var ptr = data.bytes.assumingMemoryBound(to: UInt8.self) for _ in 0.. NSData { - restoreTree(frequencyTable) + restoreTree(fromTable: frequencyTable) let reader = BitReader(data: data) let outData = NSMutableData() @@ -364,7 +362,7 @@ Here is the code for `decompressData()`, which takes an `NSData` object with Huf var i = 0 while i < byteCount { var b = findLeafNode(reader: reader, nodeIndex: root) - outData.appendBytes(&b, length: 1) + outData.append(&b, length: 1) i += 1 } return outData From 1e9ebe41a2a74c3a7dc4c01a2176ae14e5f63864 Mon Sep 17 00:00:00 2001 From: zaccone Date: Tue, 3 Jan 2017 18:21:23 -0500 Subject: [PATCH 0751/1679] Added super.init() to the initializer. --- Trie/Trie/Trie.xcodeproj/project.pbxproj | 2 -- Trie/Trie/Trie/Trie.swift | 1 + 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/Trie/Trie/Trie.xcodeproj/project.pbxproj b/Trie/Trie/Trie.xcodeproj/project.pbxproj index 055885ee1..90c5734cc 100644 --- a/Trie/Trie/Trie.xcodeproj/project.pbxproj +++ b/Trie/Trie/Trie.xcodeproj/project.pbxproj @@ -17,7 +17,6 @@ EB798E2A1DFEF81400F0628D /* Trie.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB798E281DFEF81400F0628D /* Trie.swift */; }; EB798E2C1DFEF90B00F0628D /* dictionary.txt in Resources */ = {isa = PBXBuildFile; fileRef = EB798E2B1DFEF90B00F0628D /* dictionary.txt */; }; EB798E2D1DFEF90B00F0628D /* dictionary.txt in Resources */ = {isa = PBXBuildFile; fileRef = EB798E2B1DFEF90B00F0628D /* dictionary.txt */; }; - EB8369AD1E15C5710003A7F8 /* ReadMe.md in Sources */ = {isa = PBXBuildFile; fileRef = EB8369AC1E15C5710003A7F8 /* ReadMe.md */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -270,7 +269,6 @@ files = ( EB798E291DFEF81400F0628D /* Trie.swift in Sources */, EB798E001DFEF79900F0628D /* ViewController.swift in Sources */, - EB8369AD1E15C5710003A7F8 /* ReadMe.md in Sources */, EB798DFE1DFEF79900F0628D /* AppDelegate.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/Trie/Trie/Trie/Trie.swift b/Trie/Trie/Trie/Trie.swift index ec3b1c5cc..bf1c7d9c2 100644 --- a/Trie/Trie/Trie/Trie.swift +++ b/Trie/Trie/Trie/Trie.swift @@ -64,6 +64,7 @@ class Trie: NSObject, NSCoding { override init() { root = Node() wordCount = 0 + super.init() } // MARK: NSCoding From b48107ff77ecd007656177914a9bb2860d0f1737 Mon Sep 17 00:00:00 2001 From: zaccone Date: Tue, 3 Jan 2017 18:32:52 -0500 Subject: [PATCH 0752/1679] Added a check for wordArray not nil to the guard statement in insertWordsIntoTrie. --- Trie/Trie/TrieTests/TrieTests.swift | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Trie/Trie/TrieTests/TrieTests.swift b/Trie/Trie/TrieTests/TrieTests.swift index 7ef02553f..f8e934f0d 100644 --- a/Trie/Trie/TrieTests/TrieTests.swift +++ b/Trie/Trie/TrieTests/TrieTests.swift @@ -51,10 +51,8 @@ class TrieTests: XCTestCase { /// Inserts words into a trie. If the trie is non-empty, don't do anything. func insertWordsIntoTrie() { - guard trie.count == 0 else { - return - } - for word in self.wordArray! { + guard let wordArray = wordArray, trie.count == 0 else { return } + for word in wordArray { trie.insert(word: word) } } From 947d4f8052bccdb6f8a104ab1d36892d8152d92e Mon Sep 17 00:00:00 2001 From: gonini Date: Wed, 4 Jan 2017 09:46:09 +0900 Subject: [PATCH 0753/1679] Update Minimum Spanning Tree (Unweighted Graph) to Swift 3 --- .../Contents.swift | 2 +- .../timeline.xctimeline | 6 ------ .../MinimumSpanningTree.playground/Sources/Graph.swift | 6 +++--- .../MinimumSpanningTree.playground/Sources/Node.swift | 4 ++-- .../MinimumSpanningTree.playground/Sources/Queue.swift | 2 +- .../MinimumSpanningTree.swift | 2 +- Minimum Spanning Tree (Unweighted)/Tests/Graph.swift | 10 +++++----- Minimum Spanning Tree (Unweighted)/Tests/Queue.swift | 2 +- .../Tests/Tests.xcodeproj/project.pbxproj | 3 +++ 9 files changed, 17 insertions(+), 20 deletions(-) delete mode 100644 Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Pages/Minimum spanning tree example.xcplaygroundpage/timeline.xctimeline diff --git a/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Pages/Minimum spanning tree example.xcplaygroundpage/Contents.swift b/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Pages/Minimum spanning tree example.xcplaygroundpage/Contents.swift index 088da1d11..86fe27df8 100644 --- a/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Pages/Minimum spanning tree example.xcplaygroundpage/Contents.swift +++ b/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Pages/Minimum spanning tree example.xcplaygroundpage/Contents.swift @@ -1,4 +1,4 @@ -func breadthFirstSearchMinimumSpanningTree(graph: Graph, source: Node) -> Graph { +func breadthFirstSearchMinimumSpanningTree(_ graph: Graph, source: Node) -> Graph { let minimumSpanningTree = graph.duplicate() var queue = Queue() diff --git a/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Pages/Minimum spanning tree example.xcplaygroundpage/timeline.xctimeline b/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Pages/Minimum spanning tree example.xcplaygroundpage/timeline.xctimeline deleted file mode 100644 index bf468afec..000000000 --- a/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Pages/Minimum spanning tree example.xcplaygroundpage/timeline.xctimeline +++ /dev/null @@ -1,6 +0,0 @@ - - - - - diff --git a/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Sources/Graph.swift b/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Sources/Graph.swift index 8cfb2a09c..8f02baf92 100644 --- a/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Sources/Graph.swift +++ b/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Sources/Graph.swift @@ -5,13 +5,13 @@ public class Graph: CustomStringConvertible, Equatable { self.nodes = [] } - public func addNode(label: String) -> Node { + public func addNode(_ label: String) -> Node { let node = Node(label: label) nodes.append(node) return node } - public func addEdge(source: Node, neighbor: Node) { + public func addEdge(_ source: Node, neighbor: Node) { let edge = Edge(neighbor: neighbor) source.neighbors.append(edge) } @@ -27,7 +27,7 @@ public class Graph: CustomStringConvertible, Equatable { return description } - public func findNodeWithLabel(label: String) -> Node { + public func findNodeWithLabel(_ label: String) -> Node { return nodes.filter { $0.label == label }.first! } diff --git a/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Sources/Node.swift b/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Sources/Node.swift index 37a3b3fdf..0aedb6ef9 100644 --- a/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Sources/Node.swift +++ b/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Sources/Node.swift @@ -22,8 +22,8 @@ public class Node: CustomStringConvertible, Equatable { return distance != nil } - public func remove(edge: Edge) { - neighbors.removeAtIndex(neighbors.indexOf { $0 === edge }!) + public func remove(_ edge: Edge) { + neighbors.remove(at: neighbors.index { $0 === edge }!) } } diff --git a/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Sources/Queue.swift b/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Sources/Queue.swift index bf462bbdd..3d98f801c 100644 --- a/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Sources/Queue.swift +++ b/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Sources/Queue.swift @@ -13,7 +13,7 @@ public struct Queue { return array.count } - public mutating func enqueue(element: T) { + public mutating func enqueue(_ element: T) { array.append(element) } diff --git a/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.swift b/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.swift index 92d370878..645a41999 100644 --- a/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.swift +++ b/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.swift @@ -1,4 +1,4 @@ -func breadthFirstSearchMinimumSpanningTree(graph: Graph, source: Node) -> Graph { +func breadthFirstSearchMinimumSpanningTree(_ graph: Graph, source: Node) -> Graph { let minimumSpanningTree = graph.duplicate() var queue = Queue() diff --git a/Minimum Spanning Tree (Unweighted)/Tests/Graph.swift b/Minimum Spanning Tree (Unweighted)/Tests/Graph.swift index ed71cab7c..2d4161245 100644 --- a/Minimum Spanning Tree (Unweighted)/Tests/Graph.swift +++ b/Minimum Spanning Tree (Unweighted)/Tests/Graph.swift @@ -38,8 +38,8 @@ public class Node: CustomStringConvertible, Equatable { return distance != nil } - public func remove(edge: Edge) { - neighbors.removeAtIndex(neighbors.indexOf { $0 === edge }!) + public func remove(_ edge: Edge) { + neighbors.remove(at: neighbors.index { $0 === edge }!) } } @@ -56,13 +56,13 @@ public class Graph: CustomStringConvertible, Equatable { self.nodes = [] } - public func addNode(label: String) -> Node { + public func addNode(_ label: String) -> Node { let node = Node(label: label) nodes.append(node) return node } - public func addEdge(source: Node, neighbor: Node) { + public func addEdge(_ source: Node, neighbor: Node) { let edge = Edge(neighbor: neighbor) source.neighbors.append(edge) } @@ -78,7 +78,7 @@ public class Graph: CustomStringConvertible, Equatable { return description } - public func findNodeWithLabel(label: String) -> Node { + public func findNodeWithLabel(_ label: String) -> Node { return nodes.filter { $0.label == label }.first! } diff --git a/Minimum Spanning Tree (Unweighted)/Tests/Queue.swift b/Minimum Spanning Tree (Unweighted)/Tests/Queue.swift index bf462bbdd..3d98f801c 100644 --- a/Minimum Spanning Tree (Unweighted)/Tests/Queue.swift +++ b/Minimum Spanning Tree (Unweighted)/Tests/Queue.swift @@ -13,7 +13,7 @@ public struct Queue { return array.count } - public mutating func enqueue(element: T) { + public mutating func enqueue(_ element: T) { array.append(element) } diff --git a/Minimum Spanning Tree (Unweighted)/Tests/Tests.xcodeproj/project.pbxproj b/Minimum Spanning Tree (Unweighted)/Tests/Tests.xcodeproj/project.pbxproj index 659c7e9f2..a066b7a71 100644 --- a/Minimum Spanning Tree (Unweighted)/Tests/Tests.xcodeproj/project.pbxproj +++ b/Minimum Spanning Tree (Unweighted)/Tests/Tests.xcodeproj/project.pbxproj @@ -94,6 +94,7 @@ TargetAttributes = { 7B2BBC7F1C779D720067B71D = { CreatedOnToolsVersion = 7.2; + LastSwiftMigration = 0820; }; }; }; @@ -230,6 +231,7 @@ PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -242,6 +244,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Release; }; From fc208c61f96838af6266980bd058f7141b3cac24 Mon Sep 17 00:00:00 2001 From: GongUi Date: Wed, 4 Jan 2017 09:48:04 +0900 Subject: [PATCH 0754/1679] Update .travis.yml --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 4e2918431..4fbf215de 100644 --- a/.travis.yml +++ b/.travis.yml @@ -28,7 +28,7 @@ script: # - xcodebuild test -project ./K-Means/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Linked\ List/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Longest\ Common\ Subsequence/Tests/Tests.xcodeproj -scheme Tests -# - xcodebuild test -project ./Minimum\ Spanning\ Tree\ \(Unweighted\)/Tests/Tests.xcodeproj -scheme Tests +- xcodebuild test -project ./Minimum\ Spanning\ Tree\ \(Unweighted\)/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Priority\ Queue/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Queue/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Quicksort/Tests/Tests.xcodeproj -scheme Tests From 017351f6bb67368ff273d73cba89e1ee42aa45f2 Mon Sep 17 00:00:00 2001 From: gonini Date: Thu, 5 Jan 2017 08:10:11 +0900 Subject: [PATCH 0755/1679] Warning correction for unused return function --- .../MinimumSpanningTree.playground/Sources/Graph.swift | 2 +- Minimum Spanning Tree (Unweighted)/Tests/Graph.swift | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Sources/Graph.swift b/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Sources/Graph.swift index 8f02baf92..e2bb82677 100644 --- a/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Sources/Graph.swift +++ b/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Sources/Graph.swift @@ -35,7 +35,7 @@ public class Graph: CustomStringConvertible, Equatable { let duplicated = Graph() for node in nodes { - duplicated.addNode(node.label) + _ = duplicated.addNode(node.label) } for node in nodes { diff --git a/Minimum Spanning Tree (Unweighted)/Tests/Graph.swift b/Minimum Spanning Tree (Unweighted)/Tests/Graph.swift index 2d4161245..c8cb77ac8 100644 --- a/Minimum Spanning Tree (Unweighted)/Tests/Graph.swift +++ b/Minimum Spanning Tree (Unweighted)/Tests/Graph.swift @@ -86,7 +86,7 @@ public class Graph: CustomStringConvertible, Equatable { let duplicated = Graph() for node in nodes { - duplicated.addNode(node.label) + _ = duplicated.addNode(node.label) } for node in nodes { From 58058cf6e9f6813ffbde7cf89ebefba07950d18b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20B=C3=B8dskov?= Date: Thu, 5 Jan 2017 08:02:06 +0100 Subject: [PATCH 0756/1679] aligning with style guidelines --- Huffman Coding/Huffman.playground/Contents.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Huffman Coding/Huffman.playground/Contents.swift b/Huffman Coding/Huffman.playground/Contents.swift index 017c5baf2..2d59908e9 100644 --- a/Huffman Coding/Huffman.playground/Contents.swift +++ b/Huffman Coding/Huffman.playground/Contents.swift @@ -3,7 +3,7 @@ import Foundation let s1 = "so much words wow many compression" -if let originalData = s1.data(using: String.Encoding.utf8) { +if let originalData = s1.data(using: .utf8) { print(originalData.count) let huffman1 = Huffman() @@ -17,7 +17,7 @@ if let originalData = s1.data(using: String.Encoding.utf8) { let decompressedData = huffman2.decompressData(data: compressedData, frequencyTable: frequencyTable) print(decompressedData.length) - let s2 = String(data: decompressedData as Data, encoding: String.Encoding.utf8)! + let s2 = String(data: decompressedData as Data, encoding: .utf8)! print(s2) assert(s1 == s2) } From 07dc70e66a3a3e42a3cec94a2cfa6b884f1af739 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20B=C3=B8dskov?= Date: Thu, 5 Jan 2017 12:42:42 +0100 Subject: [PATCH 0757/1679] Migrates App-Pairs Shortest Paths to Swift3 syntax --- .travis.yml | 2 +- .../APSP/APSP.xcodeproj/project.pbxproj | 13 +++++++++- .../xcshareddata/xcschemes/APSP.xcscheme | 2 +- .../xcshareddata/xcschemes/APSPTests.xcscheme | 2 +- All-Pairs Shortest Paths/APSP/APSP/APSP.swift | 2 +- .../APSP/APSP/FloydWarshall.swift | 26 +++++++++---------- .../APSP/APSP/Helpers.swift | 11 ++++---- .../APSP/APSPTests/APSPTests.swift | 6 ++--- 8 files changed, 38 insertions(+), 26 deletions(-) diff --git a/.travis.yml b/.travis.yml index 4fbf215de..2417b4b6a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,7 +8,7 @@ install: script: -# - xcodebuild test -project ./All-Pairs\ Shortest\ Paths/APSP/APSP.xcodeproj -scheme APSPTests +- xcodebuild test -project ./All-Pairs\ Shortest\ Paths/APSP/APSP.xcodeproj -scheme APSPTests - xcodebuild test -project ./Array2D/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./AVL\ Tree/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Binary\ Search/Tests/Tests.xcodeproj -scheme Tests diff --git a/All-Pairs Shortest Paths/APSP/APSP.xcodeproj/project.pbxproj b/All-Pairs Shortest Paths/APSP/APSP.xcodeproj/project.pbxproj index e7e95bbb7..b2d93ea35 100644 --- a/All-Pairs Shortest Paths/APSP/APSP.xcodeproj/project.pbxproj +++ b/All-Pairs Shortest Paths/APSP/APSP.xcodeproj/project.pbxproj @@ -187,14 +187,16 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0730; - LastUpgradeCheck = 0730; + LastUpgradeCheck = 0820; ORGANIZATIONNAME = "Swift Algorithm Club"; TargetAttributes = { 493D8DDF1CDD2A1C0089795A = { CreatedOnToolsVersion = 7.3; + LastSwiftMigration = 0820; }; 493D8DF01CDD5B960089795A = { CreatedOnToolsVersion = 7.3; + LastSwiftMigration = 0820; }; }; }; @@ -305,8 +307,10 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; @@ -350,8 +354,10 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; @@ -370,6 +376,7 @@ MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; }; name = Release; }; @@ -381,6 +388,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.swift-algorithm-club.APSPTests"; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -392,6 +400,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.swift-algorithm-club.APSPTests"; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Release; }; @@ -411,6 +420,7 @@ PRODUCT_BUNDLE_IDENTIFIER = "com.swift-algorithm-club.APSP"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; + SWIFT_VERSION = 3.0; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; @@ -432,6 +442,7 @@ PRODUCT_BUNDLE_IDENTIFIER = "com.swift-algorithm-club.APSP"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; + SWIFT_VERSION = 3.0; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; diff --git a/All-Pairs Shortest Paths/APSP/APSP.xcodeproj/xcshareddata/xcschemes/APSP.xcscheme b/All-Pairs Shortest Paths/APSP/APSP.xcodeproj/xcshareddata/xcschemes/APSP.xcscheme index 475997aa9..e313c4b88 100644 --- a/All-Pairs Shortest Paths/APSP/APSP.xcodeproj/xcshareddata/xcschemes/APSP.xcscheme +++ b/All-Pairs Shortest Paths/APSP/APSP.xcodeproj/xcshareddata/xcschemes/APSP.xcscheme @@ -1,6 +1,6 @@ ) -> P + static func apply(_ graph: AbstractGraph) -> P } diff --git a/All-Pairs Shortest Paths/APSP/APSP/FloydWarshall.swift b/All-Pairs Shortest Paths/APSP/APSP/FloydWarshall.swift index 806c8677c..b1a870f2a 100644 --- a/All-Pairs Shortest Paths/APSP/APSP/FloydWarshall.swift +++ b/All-Pairs Shortest Paths/APSP/APSP/FloydWarshall.swift @@ -17,7 +17,7 @@ private typealias StepResult = (distances: Distances, predecessors: Predecessors - note: In all complexity bounds, `V` is the number of vertices in the graph, and `E` is the number of edges. */ -public struct FloydWarshall: APSPAlgorithm { +public struct FloydWarshall: APSPAlgorithm where T: Hashable { public typealias Q = T public typealias P = FloydWarshallResult @@ -29,7 +29,7 @@ public struct FloydWarshall: APSPAlgorithm { - complexity: `Θ(V^3)` time, `Θ(V^2)` space - returns a `FloydWarshallResult` struct which can be queried for shortest paths and their total weights */ - public static func apply(graph: AbstractGraph) -> FloydWarshallResult { + public static func apply(_ graph: AbstractGraph) -> FloydWarshallResult { var previousDistance = constructInitialDistanceMatrix(graph) var previousPredecessor = constructInitialPredecessorMatrix(previousDistance) @@ -59,12 +59,12 @@ public struct FloydWarshall: APSPAlgorithm { - returns: a tuple containing the next distance matrix with weights of currently known shortest paths and the corresponding predecessor matrix */ - static private func nextStep(intermediateIdx: Int, previousDistances: Distances, + static fileprivate func nextStep(_ intermediateIdx: Int, previousDistances: Distances, previousPredecessors: Predecessors, graph: AbstractGraph) -> StepResult { let vertexCount = graph.vertices.count - var nextDistances = Array(count: vertexCount, repeatedValue: Array(count: vertexCount, repeatedValue: Double.infinity)) - var nextPredecessors = Array(count: vertexCount, repeatedValue: Array(count: vertexCount, repeatedValue: nil)) + var nextDistances = Array(repeating: Array(repeating: Double.infinity, count: vertexCount), count: vertexCount) + var nextPredecessors = Array(repeating: Array(repeating: nil, count: vertexCount), count: vertexCount) for fromIdx in 0 ..< vertexCount { for toIndex in 0 ..< vertexCount { @@ -97,12 +97,12 @@ public struct FloydWarshall: APSPAlgorithm { - complexity: `Θ(V^2)` time/space - returns: weighted adjacency matrix in form ready for processing with Floyd-Warshall */ - static private func constructInitialDistanceMatrix(graph: AbstractGraph) -> Distances { + static fileprivate func constructInitialDistanceMatrix(_ graph: AbstractGraph) -> Distances { let vertices = graph.vertices let vertexCount = graph.vertices.count - var distances = Array(count: vertexCount, repeatedValue: Array(count: vertexCount, repeatedValue: Double.infinity)) + var distances = Array(repeating: Array(repeating: Double.infinity, count: vertexCount), count: vertexCount) for row in vertices { for col in vertices { @@ -125,10 +125,10 @@ public struct FloydWarshall: APSPAlgorithm { - complexity: `Θ(V^2)` time/space */ - static private func constructInitialPredecessorMatrix(distances: Distances) -> Predecessors { + static fileprivate func constructInitialPredecessorMatrix(_ distances: Distances) -> Predecessors { let vertexCount = distances.count - var predecessors = Array(count: vertexCount, repeatedValue: Array(count: vertexCount, repeatedValue: nil)) + var predecessors = Array(repeating: Array(repeating: nil, count: vertexCount), count: vertexCount) for fromIdx in 0 ..< vertexCount { for toIdx in 0 ..< vertexCount { @@ -151,10 +151,10 @@ public struct FloydWarshall: APSPAlgorithm { It conforms to the `APSPResult` procotol which provides methods to retrieve distances and paths between given pairs of start and end nodes. */ -public struct FloydWarshallResult: APSPResult { +public struct FloydWarshallResult: APSPResult where T: Hashable { - private var weights: Distances - private var predecessors: Predecessors + fileprivate var weights: Distances + fileprivate var predecessors: Predecessors /** - returns: the total weight of the path from a starting vertex to a destination. @@ -190,7 +190,7 @@ public struct FloydWarshallResult: APSPResult { - returns: the list of predecessors discovered so far */ - private func recursePathFrom(fromVertex from: Vertex, toVertex to: Vertex, path: [Vertex], + fileprivate func recursePathFrom(fromVertex from: Vertex, toVertex to: Vertex, path: [Vertex], inGraph graph: AbstractGraph) -> [Vertex]? { if from.index == to.index { diff --git a/All-Pairs Shortest Paths/APSP/APSP/Helpers.swift b/All-Pairs Shortest Paths/APSP/APSP/Helpers.swift index 644454491..3812b3f58 100644 --- a/All-Pairs Shortest Paths/APSP/APSP/Helpers.swift +++ b/All-Pairs Shortest Paths/APSP/APSP/Helpers.swift @@ -7,10 +7,11 @@ import Foundation + /** Print a matrix, optionally specifying only the cells to display with the triplet (i, j, k) -> matrix[i][j], matrix[i][k], matrix[k][j] */ -func printMatrix(matrix: [[Double]], i: Int = -1, j: Int = -1, k: Int = -1) { +func printMatrix(_ matrix: [[Double]], i: Int = -1, j: Int = -1, k: Int = -1) { if i >= 0 { print(" k: \(k); i: \(i); j: \(j)\n") @@ -31,12 +32,12 @@ func printMatrix(matrix: [[Double]], i: Int = -1, j: Int = -1, k: Int = -1) { } grid.append(row) } - print((grid as NSArray).componentsJoinedByString("\n")) + print((grid as NSArray).componentsJoined(by: "\n")) print(" =======================") } -func printIntMatrix(matrix: [[Int?]]) { +func printIntMatrix(_ matrix: [[Int?]]) { var grid = [String]() @@ -46,14 +47,14 @@ func printIntMatrix(matrix: [[Int?]]) { for y in 0.. { +struct TestCase where T: Hashable { var from: Vertex var to: Vertex @@ -71,7 +71,7 @@ class APSPTests: XCTestCase { for testCase: TestCase in cases { if let computedPath = result.path(fromVertex: testCase.from, toVertex: testCase.to, inGraph: graph), - computedDistance = result.distance(fromVertex: testCase.from, toVertex: testCase.to) { + let computedDistance = result.distance(fromVertex: testCase.from, toVertex: testCase.to) { XCTAssert(computedDistance == testCase.expectedDistance, "expected distance \(testCase.expectedDistance) but got \(computedDistance)") XCTAssert(computedPath == testCase.expectedPath, "expected path \(testCase.expectedPath) but got \(computedPath)") } @@ -111,7 +111,7 @@ class APSPTests: XCTestCase { for testCase: TestCase in cases { if let computedPath = result.path(fromVertex: testCase.from, toVertex: testCase.to, inGraph: graph), - computedDistance = result.distance(fromVertex: testCase.from, toVertex: testCase.to) { + let computedDistance = result.distance(fromVertex: testCase.from, toVertex: testCase.to) { XCTAssert(computedDistance == testCase.expectedDistance, "expected distance \(testCase.expectedDistance) but got \(computedDistance)") XCTAssert(computedPath == testCase.expectedPath, "expected path \(testCase.expectedPath) but got \(computedPath)") } From 797a2e9e2bf70911222cac674e05841b80679310 Mon Sep 17 00:00:00 2001 From: iamsimranjot Date: Fri, 6 Jan 2017 02:56:13 +0530 Subject: [PATCH 0758/1679] Updated Merge Sort (Recursive) to Generic. --- .../MergeSort.playground/Contents.swift | 6 +- Merge Sort/MergeSort.swift | 72 +++++++++---------- 2 files changed, 39 insertions(+), 39 deletions(-) diff --git a/Merge Sort/MergeSort.playground/Contents.swift b/Merge Sort/MergeSort.playground/Contents.swift index ac166131e..e76570481 100644 --- a/Merge Sort/MergeSort.playground/Contents.swift +++ b/Merge Sort/MergeSort.playground/Contents.swift @@ -1,6 +1,6 @@ /* Top-down recursive version */ -func mergeSort(_ array: [Int]) -> [Int] { +func mergeSort(_ array: [T]) -> [T] { guard array.count > 1 else { return array } let middleIndex = array.count / 2 let leftArray = mergeSort(Array(array[0.. [Int] { return merge(leftPile: leftArray, rightPile: rightArray) } -func merge(leftPile: [Int], rightPile: [Int]) -> [Int] { +func merge(leftPile: [T], rightPile: [T]) -> [T] { var leftIndex = 0 var rightIndex = 0 - var orderedPile = [Int]() + var orderedPile = [T]() while leftIndex < leftPile.count && rightIndex < rightPile.count { if leftPile[leftIndex] < rightPile[rightIndex] { diff --git a/Merge Sort/MergeSort.swift b/Merge Sort/MergeSort.swift index 20316663f..bb89ea4d4 100644 --- a/Merge Sort/MergeSort.swift +++ b/Merge Sort/MergeSort.swift @@ -6,45 +6,45 @@ // // -func mergeSort(_ array: [Int]) -> [Int] { - guard array.count > 1 else { return array } - let middleIndex = array.count / 2 - let leftArray = mergeSort(Array(array[0..(_ array: [T]) -> [T] { + guard array.count > 1 else { return array } + let middleIndex = array.count / 2 + let leftArray = mergeSort(Array(array[0.. [Int] { - var leftIndex = 0 - var rightIndex = 0 - var orderedPile = [Int]() - - while leftIndex < leftPile.count && rightIndex < rightPile.count { - if leftPile[leftIndex] < rightPile[rightIndex] { - orderedPile.append(leftPile[leftIndex]) - leftIndex += 1 - } else if leftPile[leftIndex] > rightPile[rightIndex] { - orderedPile.append(rightPile[rightIndex]) - rightIndex += 1 - } else { - orderedPile.append(leftPile[leftIndex]) - leftIndex += 1 - orderedPile.append(rightPile[rightIndex]) - rightIndex += 1 +func merge(leftPile: [T], rightPile: [T]) -> [T] { + var leftIndex = 0 + var rightIndex = 0 + var orderedPile = [T]() + + while leftIndex < leftPile.count && rightIndex < rightPile.count { + if leftPile[leftIndex] < rightPile[rightIndex] { + orderedPile.append(leftPile[leftIndex]) + leftIndex += 1 + } else if leftPile[leftIndex] > rightPile[rightIndex] { + orderedPile.append(rightPile[rightIndex]) + rightIndex += 1 + } else { + orderedPile.append(leftPile[leftIndex]) + leftIndex += 1 + orderedPile.append(rightPile[rightIndex]) + rightIndex += 1 + } } - } - - while leftIndex < leftPile.count { - orderedPile.append(leftPile[leftIndex]) - leftIndex += 1 - } - - while rightIndex < rightPile.count { - orderedPile.append(rightPile[rightIndex]) - rightIndex += 1 - } - - return orderedPile + + while leftIndex < leftPile.count { + orderedPile.append(leftPile[leftIndex]) + leftIndex += 1 + } + + while rightIndex < rightPile.count { + orderedPile.append(rightPile[rightIndex]) + rightIndex += 1 + } + + return orderedPile } /* From e7b54f7bbb1c48be56f0f85ff433f889e1ddd880 Mon Sep 17 00:00:00 2001 From: iamsimranjot Date: Fri, 6 Jan 2017 02:58:50 +0530 Subject: [PATCH 0759/1679] Extra Example Added. --- Merge Sort/MergeSort.playground/Contents.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Merge Sort/MergeSort.playground/Contents.swift b/Merge Sort/MergeSort.playground/Contents.swift index e76570481..2952fc299 100644 --- a/Merge Sort/MergeSort.playground/Contents.swift +++ b/Merge Sort/MergeSort.playground/Contents.swift @@ -43,6 +43,8 @@ func merge(leftPile: [T], rightPile: [T]) -> [T] { let array = [2, 1, 5, 4, 9] let sortedArray = mergeSort(array) +let array2 = ["Tom", "Harry", "Ron", "Chandler", "Monica"] +let sortedArray2 = mergeSort(array2) From 369bff5d3ed3634c140b73c348dbe000ca7df4da Mon Sep 17 00:00:00 2001 From: iamsimranjot Date: Sun, 8 Jan 2017 03:47:54 +0530 Subject: [PATCH 0760/1679] Code Re-Indented With 2 Space Indentation. --- Merge Sort/MergeSort.swift | 70 +++++++++++++++++++------------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/Merge Sort/MergeSort.swift b/Merge Sort/MergeSort.swift index bb89ea4d4..a7677b0bb 100644 --- a/Merge Sort/MergeSort.swift +++ b/Merge Sort/MergeSort.swift @@ -7,44 +7,44 @@ // func mergeSort(_ array: [T]) -> [T] { - guard array.count > 1 else { return array } - let middleIndex = array.count / 2 - let leftArray = mergeSort(Array(array[0.. 1 else { return array } + let middleIndex = array.count / 2 + let leftArray = mergeSort(Array(array[0..(leftPile: [T], rightPile: [T]) -> [T] { - var leftIndex = 0 - var rightIndex = 0 - var orderedPile = [T]() - - while leftIndex < leftPile.count && rightIndex < rightPile.count { - if leftPile[leftIndex] < rightPile[rightIndex] { - orderedPile.append(leftPile[leftIndex]) - leftIndex += 1 - } else if leftPile[leftIndex] > rightPile[rightIndex] { - orderedPile.append(rightPile[rightIndex]) - rightIndex += 1 - } else { - orderedPile.append(leftPile[leftIndex]) - leftIndex += 1 - orderedPile.append(rightPile[rightIndex]) - rightIndex += 1 - } - } - - while leftIndex < leftPile.count { - orderedPile.append(leftPile[leftIndex]) - leftIndex += 1 - } - - while rightIndex < rightPile.count { - orderedPile.append(rightPile[rightIndex]) - rightIndex += 1 - } - - return orderedPile + var leftIndex = 0 + var rightIndex = 0 + var orderedPile = [T]() + + while leftIndex < leftPile.count && rightIndex < rightPile.count { + if leftPile[leftIndex] < rightPile[rightIndex] { + orderedPile.append(leftPile[leftIndex]) + leftIndex += 1 + } else if leftPile[leftIndex] > rightPile[rightIndex] { + orderedPile.append(rightPile[rightIndex]) + rightIndex += 1 + } else { + orderedPile.append(leftPile[leftIndex]) + leftIndex += 1 + orderedPile.append(rightPile[rightIndex]) + rightIndex += 1 + } + } + + while leftIndex < leftPile.count { + orderedPile.append(leftPile[leftIndex]) + leftIndex += 1 + } + + while rightIndex < rightPile.count { + orderedPile.append(rightPile[rightIndex]) + rightIndex += 1 + } + + return orderedPile } /* From f9412936fc0656eebf5f7ad1a79a241a5e05c572 Mon Sep 17 00:00:00 2001 From: iamsimranjot Date: Sun, 8 Jan 2017 03:57:16 +0530 Subject: [PATCH 0761/1679] Code Re Indented with 2 Space Indentation (Part 2) --- Merge Sort/MergeSort.swift | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/Merge Sort/MergeSort.swift b/Merge Sort/MergeSort.swift index a7677b0bb..4332fc44b 100644 --- a/Merge Sort/MergeSort.swift +++ b/Merge Sort/MergeSort.swift @@ -20,28 +20,28 @@ func merge(leftPile: [T], rightPile: [T]) -> [T] { var orderedPile = [T]() while leftIndex < leftPile.count && rightIndex < rightPile.count { - if leftPile[leftIndex] < rightPile[rightIndex] { - orderedPile.append(leftPile[leftIndex]) - leftIndex += 1 - } else if leftPile[leftIndex] > rightPile[rightIndex] { - orderedPile.append(rightPile[rightIndex]) - rightIndex += 1 - } else { - orderedPile.append(leftPile[leftIndex]) - leftIndex += 1 - orderedPile.append(rightPile[rightIndex]) - rightIndex += 1 - } + if leftPile[leftIndex] < rightPile[rightIndex] { + orderedPile.append(leftPile[leftIndex]) + leftIndex += 1 + } else if leftPile[leftIndex] > rightPile[rightIndex] { + orderedPile.append(rightPile[rightIndex]) + rightIndex += 1 + } else { + orderedPile.append(leftPile[leftIndex]) + leftIndex += 1 + orderedPile.append(rightPile[rightIndex]) + rightIndex += 1 + } } while leftIndex < leftPile.count { - orderedPile.append(leftPile[leftIndex]) - leftIndex += 1 + orderedPile.append(leftPile[leftIndex]) + leftIndex += 1 } while rightIndex < rightPile.count { - orderedPile.append(rightPile[rightIndex]) - rightIndex += 1 + orderedPile.append(rightPile[rightIndex]) + rightIndex += 1 } return orderedPile From 0e819963fe321021486aa8247776cb20d65d58cf Mon Sep 17 00:00:00 2001 From: Tai Heng Date: Sun, 8 Jan 2017 15:52:39 -0500 Subject: [PATCH 0762/1679] Updated K-Means Tests.xcodeproj to latest settings. Updated K-Means code to Swift3 syntax and changes to API. --- .travis.yml | 2 +- K-Means/KMeans.swift | 18 ++++----- K-Means/Tests/KMeansTests.swift | 2 +- K-Means/Tests/Tests.xcodeproj/project.pbxproj | 40 ++++++++++++++++++- .../xcshareddata/xcschemes/Tests.xcscheme | 2 +- K-Means/Tests/Vector.swift | 12 +++--- 6 files changed, 57 insertions(+), 19 deletions(-) diff --git a/.travis.yml b/.travis.yml index 727b247a5..b33835565 100644 --- a/.travis.yml +++ b/.travis.yml @@ -25,7 +25,7 @@ script: # - xcodebuild test -project ./Heap/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Heap\ Sort/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Insertion\ Sort/Tests/Tests.xcodeproj -scheme Tests -# - xcodebuild test -project ./K-Means/Tests/Tests.xcodeproj -scheme Tests +- xcodebuild test -project ./K-Means/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Linked\ List/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Longest\ Common\ Subsequence/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Minimum\ Spanning\ Tree\ \(Unweighted\)/Tests/Tests.xcodeproj -scheme Tests diff --git a/K-Means/KMeans.swift b/K-Means/KMeans.swift index 972fd7230..4a89a3fae 100644 --- a/K-Means/KMeans.swift +++ b/K-Means/KMeans.swift @@ -11,11 +11,11 @@ class KMeans { self.numCenters = labels.count } - private func indexOfNearestCenter(x: Vector, centers: [Vector]) -> Int { + private func indexOfNearestCenter(_ x: Vector, centers: [Vector]) -> Int { var nearestDist = DBL_MAX var minIndex = 0 - for (idx, center) in centers.enumerate() { + for (idx, center) in centers.enumerated() { let dist = x.distanceTo(center) if dist < nearestDist { minIndex = idx @@ -25,8 +25,8 @@ class KMeans { return minIndex } - func trainCenters(points: [Vector], convergeDistance: Double) { - let zeroVector = Vector([Double](count: points[0].length, repeatedValue: 0)) + func trainCenters(_ points: [Vector], convergeDistance: Double) { + let zeroVector = Vector([Double](repeating: 0, count: points[0].length)) // Randomly take k objects from the input data to make the initial centroids. var centers = reservoirSample(points, k: numCenters) @@ -34,7 +34,7 @@ class KMeans { var centerMoveDist = 0.0 repeat { // This array keeps track of which data points belong to which centroids. - var classification: [[Vector]] = .init(count: numCenters, repeatedValue: []) + var classification: [[Vector]] = .init(repeating: [], count: numCenters) // For each data point, find the centroid that it is closest to. for p in points { @@ -45,7 +45,7 @@ class KMeans { // Take the average of all the data points that belong to each centroid. // This moves the centroid to a new position. let newCenters = classification.map { assignedPoints in - assignedPoints.reduce(zeroVector, combine: +) / Double(assignedPoints.count) + assignedPoints.reduce(zeroVector, +) / Double(assignedPoints.count) } // Find out how far each centroid moved since the last iteration. If it's @@ -61,14 +61,14 @@ class KMeans { centroids = centers } - func fit(point: Vector) -> Label { + func fit(_ point: Vector) -> Label { assert(!centroids.isEmpty, "Exception: KMeans tried to fit on a non trained model.") let centroidIndex = indexOfNearestCenter(point, centers: centroids) return labels[centroidIndex] } - func fit(points: [Vector]) -> [Label] { + func fit(_ points: [Vector]) -> [Label] { assert(!centroids.isEmpty, "Exception: KMeans tried to fit on a non trained model.") return points.map(fit) @@ -76,7 +76,7 @@ class KMeans { } // Pick k random elements from samples -func reservoirSample(samples: [T], k: Int) -> [T] { +func reservoirSample(_ samples: [T], k: Int) -> [T] { var result = [T]() // Fill the result array with first k elements diff --git a/K-Means/Tests/KMeansTests.swift b/K-Means/Tests/KMeansTests.swift index 179f9d418..7e0c93004 100644 --- a/K-Means/Tests/KMeansTests.swift +++ b/K-Means/Tests/KMeansTests.swift @@ -10,7 +10,7 @@ import Foundation import XCTest class KMeansTests: XCTestCase { - func genPoints(numPoints: Int, numDimensions: Int) -> [Vector] { + func genPoints(_ numPoints: Int, numDimensions: Int) -> [Vector] { var points = [Vector]() for _ in 0.. Double { + func distanceTo(_ other: Vector) -> Double { var result = 0.0 for idx in 0.. Vector { return Vector(results) } -func += (inout left: Vector, right: Vector) { +func += (left: inout Vector, right: Vector) { left = left + right } @@ -51,18 +51,18 @@ func - (left: Vector, right: Vector) -> Vector { return Vector(results) } -func -= (inout left: Vector, right: Vector) { +func -= (left: inout Vector, right: Vector) { left = left - right } func / (left: Vector, right: Double) -> Vector { - var results = [Double](count: left.length, repeatedValue: 0) - for (idx, value) in left.data.enumerate() { + var results = [Double](repeating: 0, count: left.length) + for (idx, value) in left.data.enumerated() { results[idx] = value / right } return Vector(results) } -func /= (inout left: Vector, right: Double) { +func /= (left: inout Vector, right: Double) { left = left / right } From bf46bb528139e05d41a48bed0a54d78030b420b2 Mon Sep 17 00:00:00 2001 From: Tai Heng Date: Sun, 8 Jan 2017 16:29:16 -0500 Subject: [PATCH 0763/1679] Converted playground and combSort code to Swift 3 syntax. Changed combSort to use generic type. --- Comb Sort/Comb Sort.playground/Contents.swift | 24 +------------ .../Sources/Comb Sort.swift | 36 +++++++++++++++++++ Comb Sort/Comb Sort.swift | 6 ++-- 3 files changed, 40 insertions(+), 26 deletions(-) create mode 100644 Comb Sort/Comb Sort.playground/Sources/Comb Sort.swift diff --git a/Comb Sort/Comb Sort.playground/Contents.swift b/Comb Sort/Comb Sort.playground/Contents.swift index 2d6155b50..d6add44f5 100644 --- a/Comb Sort/Comb Sort.playground/Contents.swift +++ b/Comb Sort/Comb Sort.playground/Contents.swift @@ -4,34 +4,12 @@ import Cocoa -func combSort (input: [Int]) -> [Int] { - var copy = input - var gap = copy.count - let shrink = 1.3 - - while gap > 1 { - gap = Int(Double(gap) / shrink) - if gap < 1 { - gap = 1 - } - - var index = 0 - while index + gap < copy.count { - if copy[index] > copy[index + gap] { - swap(©[index], ©[index + gap]) - } - index += 1 - } - } - return copy -} - // Test Comb Sort with small array of ten values let array = [2, 32, 9, -1, 89, 101, 55, -10, -12, 67] combSort(array) // Test Comb Sort with large array of 1000 random values -var bigArray = [Int](count: 1000, repeatedValue: 0) +var bigArray = [Int](repeating: 0, count: 1000) var i = 0 while i < 1000 { bigArray[i] = Int(arc4random_uniform(1000) + 1) diff --git a/Comb Sort/Comb Sort.playground/Sources/Comb Sort.swift b/Comb Sort/Comb Sort.playground/Sources/Comb Sort.swift new file mode 100644 index 000000000..b6e85fa2b --- /dev/null +++ b/Comb Sort/Comb Sort.playground/Sources/Comb Sort.swift @@ -0,0 +1,36 @@ +// Comb Sort.swift +// Comb Sort +// +// Created by Stephen.Rutstein on 7/16/16. +// Copyright © 2016 Stephen.Rutstein. All rights reserved. +// + +import Foundation + +public func combSort(_ input: [T]) -> [T] { + var copy: [T] = input + var gap = copy.count + let shrink = 1.3 + + while gap > 1 { + gap = (Int)(Double(gap) / shrink) + if gap < 1 { + gap = 1 + } + + var index = 0 + while !(index + gap >= copy.count) { + if copy[index] > copy[index + gap] { + swap(©[index], ©[index + gap]) + } + index += 1 + } + } + return copy +} + +fileprivate func swap(a: inout T, b: inout T) { + let temp = a + a = b + b = temp +} diff --git a/Comb Sort/Comb Sort.swift b/Comb Sort/Comb Sort.swift index 7abba8c7f..b6e85fa2b 100644 --- a/Comb Sort/Comb Sort.swift +++ b/Comb Sort/Comb Sort.swift @@ -7,8 +7,8 @@ import Foundation -func combSort (input: [Int]) -> [Int] { - var copy: [Int] = input +public func combSort(_ input: [T]) -> [T] { + var copy: [T] = input var gap = copy.count let shrink = 1.3 @@ -29,7 +29,7 @@ func combSort (input: [Int]) -> [Int] { return copy } -func swap (inout a: Int, inout b: Int) { +fileprivate func swap(a: inout T, b: inout T) { let temp = a a = b b = temp From f1dd6b66c4eca5e01b7b363a329fa4ffa5a46d0e Mon Sep 17 00:00:00 2001 From: iamsimranjot Date: Mon, 9 Jan 2017 03:12:18 +0530 Subject: [PATCH 0764/1679] Removed Extra Spaces. --- Merge Sort/MergeSort.swift | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Merge Sort/MergeSort.swift b/Merge Sort/MergeSort.swift index 4332fc44b..f77d1cd84 100644 --- a/Merge Sort/MergeSort.swift +++ b/Merge Sort/MergeSort.swift @@ -18,7 +18,7 @@ func merge(leftPile: [T], rightPile: [T]) -> [T] { var leftIndex = 0 var rightIndex = 0 var orderedPile = [T]() - + while leftIndex < leftPile.count && rightIndex < rightPile.count { if leftPile[leftIndex] < rightPile[rightIndex] { orderedPile.append(leftPile[leftIndex]) @@ -33,17 +33,17 @@ func merge(leftPile: [T], rightPile: [T]) -> [T] { rightIndex += 1 } } - + while leftIndex < leftPile.count { orderedPile.append(leftPile[leftIndex]) leftIndex += 1 } - + while rightIndex < rightPile.count { orderedPile.append(rightPile[rightIndex]) rightIndex += 1 } - + return orderedPile } From af8b44f97392fb8f8cb5704b0799fb0523ee8e31 Mon Sep 17 00:00:00 2001 From: zaccone Date: Mon, 9 Jan 2017 13:50:28 -0500 Subject: [PATCH 0765/1679] Changed the baseline for one of the tests. --- .../6ABF2F62-9363-4450-8DE1-D20F57026950.plist | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Trie/Trie/Trie.xcodeproj/xcshareddata/xcbaselines/EB798E0A1DFEF79900F0628D.xcbaseline/6ABF2F62-9363-4450-8DE1-D20F57026950.plist b/Trie/Trie/Trie.xcodeproj/xcshareddata/xcbaselines/EB798E0A1DFEF79900F0628D.xcbaseline/6ABF2F62-9363-4450-8DE1-D20F57026950.plist index 01ff985c8..d8e350129 100644 --- a/Trie/Trie/Trie.xcodeproj/xcshareddata/xcbaselines/EB798E0A1DFEF79900F0628D.xcbaseline/6ABF2F62-9363-4450-8DE1-D20F57026950.plist +++ b/Trie/Trie/Trie.xcodeproj/xcshareddata/xcbaselines/EB798E0A1DFEF79900F0628D.xcbaseline/6ABF2F62-9363-4450-8DE1-D20F57026950.plist @@ -11,7 +11,7 @@ com.apple.XCTPerformanceMetric_WallClockTime baselineAverage - 3.0053 + 3.407 baselineIntegrationDisplayName Local Baseline From f0e83bdea4dce34d5a495fcd7dc3b3f3dec8c178 Mon Sep 17 00:00:00 2001 From: Tai Heng Date: Mon, 9 Jan 2017 22:05:24 -0500 Subject: [PATCH 0766/1679] Added Comb Sort test. --- .travis.yml | 1 + Comb Sort/Tests/CombSortTests.swift | 28 ++ Comb Sort/Tests/Info.plist | 22 ++ .../Tests/Tests.xcodeproj/project.pbxproj | 277 ++++++++++++++++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/xcschemes/Tests.xcscheme | 101 +++++++ 6 files changed, 436 insertions(+) create mode 100644 Comb Sort/Tests/CombSortTests.swift create mode 100644 Comb Sort/Tests/Info.plist create mode 100644 Comb Sort/Tests/Tests.xcodeproj/project.pbxproj create mode 100644 Comb Sort/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 Comb Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme diff --git a/.travis.yml b/.travis.yml index 727b247a5..b4691467f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,6 +19,7 @@ script: # - xcodebuild test -project ./Breadth-First\ Search/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Bucket\ Sort/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./B-Tree/Tests/Tests.xcodeproj -scheme Tests +- xcodebuild test -project ./Comb\ Sort/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Counting\ Sort/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Depth-First\ Search/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Graph/Graph.xcodeproj -scheme GraphTests diff --git a/Comb Sort/Tests/CombSortTests.swift b/Comb Sort/Tests/CombSortTests.swift new file mode 100644 index 000000000..1bcc67fd0 --- /dev/null +++ b/Comb Sort/Tests/CombSortTests.swift @@ -0,0 +1,28 @@ +// +// CombSortTests.swift +// Tests +// +// Created by theng on 2017-01-09. +// Copyright © 2017 Swift Algorithm Club. All rights reserved. +// + +import XCTest + +class CombSortTests: XCTestCase { + var sequence: [Int]! + let expectedSequence: [Int] = [-12, -10, -1, 2, 9, 32, 55, 67, 89, 101] + + override func setUp() { + super.setUp() + sequence = [2, 32, 9, -1, 89, 101, 55, -10, -12, 67] + } + + override func tearDown() { + super.tearDown() + } + + func testCombSort() { + let sortedSequence = combSort(sequence) + XCTAssertEqual(sortedSequence, expectedSequence) + } +} diff --git a/Comb Sort/Tests/Info.plist b/Comb Sort/Tests/Info.plist new file mode 100644 index 000000000..6c6c23c43 --- /dev/null +++ b/Comb Sort/Tests/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + diff --git a/Comb Sort/Tests/Tests.xcodeproj/project.pbxproj b/Comb Sort/Tests/Tests.xcodeproj/project.pbxproj new file mode 100644 index 000000000..60039196c --- /dev/null +++ b/Comb Sort/Tests/Tests.xcodeproj/project.pbxproj @@ -0,0 +1,277 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 056E927E1E24852900B30F52 /* CombSortTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 056E927D1E24852900B30F52 /* CombSortTests.swift */; }; + 056E92841E248A4000B30F52 /* Comb Sort.swift in Sources */ = {isa = PBXBuildFile; fileRef = 056E92831E248A4000B30F52 /* Comb Sort.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 056E92751E2483D300B30F52 /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 056E92791E2483D300B30F52 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 056E927D1E24852900B30F52 /* CombSortTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CombSortTests.swift; sourceTree = ""; }; + 056E92831E248A4000B30F52 /* Comb Sort.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "Comb Sort.swift"; path = "../Comb Sort.swift"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 056E92721E2483D300B30F52 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 056E92581E24836C00B30F52 = { + isa = PBXGroup; + children = ( + 056E92761E2483D300B30F52 /* Tests */, + 056E92621E24836C00B30F52 /* Products */, + ); + sourceTree = ""; + }; + 056E92621E24836C00B30F52 /* Products */ = { + isa = PBXGroup; + children = ( + 056E92751E2483D300B30F52 /* Tests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 056E92761E2483D300B30F52 /* Tests */ = { + isa = PBXGroup; + children = ( + 056E92831E248A4000B30F52 /* Comb Sort.swift */, + 056E92791E2483D300B30F52 /* Info.plist */, + 056E927D1E24852900B30F52 /* CombSortTests.swift */, + ); + name = Tests; + sourceTree = SOURCE_ROOT; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 056E92741E2483D300B30F52 /* Tests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 056E927A1E2483D300B30F52 /* Build configuration list for PBXNativeTarget "Tests" */; + buildPhases = ( + 056E92711E2483D300B30F52 /* Sources */, + 056E92721E2483D300B30F52 /* Frameworks */, + 056E92731E2483D300B30F52 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Tests; + productName = Tests; + productReference = 056E92751E2483D300B30F52 /* Tests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 056E92591E24836C00B30F52 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0820; + LastUpgradeCheck = 0820; + ORGANIZATIONNAME = "Swift Algorithm Club"; + TargetAttributes = { + 056E92741E2483D300B30F52 = { + CreatedOnToolsVersion = 8.2; + LastSwiftMigration = 0820; + ProvisioningStyle = Automatic; + }; + }; + }; + buildConfigurationList = 056E925C1E24836C00B30F52 /* Build configuration list for PBXProject "Tests" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 056E92581E24836C00B30F52; + productRefGroup = 056E92621E24836C00B30F52 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 056E92741E2483D300B30F52 /* Tests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 056E92731E2483D300B30F52 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 056E92711E2483D300B30F52 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 056E927E1E24852900B30F52 /* CombSortTests.swift in Sources */, + 056E92841E248A4000B30F52 /* Comb Sort.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 056E926C1E24836C00B30F52 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.12; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 056E926D1E24836C00B30F52 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.12; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + }; + name = Release; + }; + 056E927B1E2483D300B30F52 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "Swift-Algorithm-Club.Tests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 3.0; + }; + name = Debug; + }; + 056E927C1E2483D300B30F52 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "Swift-Algorithm-Club.Tests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 056E925C1E24836C00B30F52 /* Build configuration list for PBXProject "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 056E926C1E24836C00B30F52 /* Debug */, + 056E926D1E24836C00B30F52 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 056E927A1E2483D300B30F52 /* Build configuration list for PBXNativeTarget "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 056E927B1E2483D300B30F52 /* Debug */, + 056E927C1E2483D300B30F52 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 056E92591E24836C00B30F52 /* Project object */; +} diff --git a/Comb Sort/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Comb Sort/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..6c0ea8493 --- /dev/null +++ b/Comb Sort/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Comb Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Comb Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme new file mode 100644 index 000000000..55e697ad3 --- /dev/null +++ b/Comb Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 6ec92d76ccecd3f0083252d406e1fc5b3a59d57b Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Tue, 10 Jan 2017 00:12:50 -0800 Subject: [PATCH 0767/1679] Fixes compile error due to missing brace. --- Trie/Trie/Trie/Trie.swift | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Trie/Trie/Trie/Trie.swift b/Trie/Trie/Trie/Trie.swift index d3c845720..0e11a9c61 100644 --- a/Trie/Trie/Trie/Trie.swift +++ b/Trie/Trie/Trie/Trie.swift @@ -11,15 +11,15 @@ import Foundation /// A node in the trie class TrieNode { - var value: T? - weak var parentNode: TrieNode? - var children: [T: TrieNode] = [:] - var isTerminating = false - var isLeaf: Bool { - return children.count == 0 - } + var value: T? + weak var parentNode: TrieNode? + var children: [T: TrieNode] = [:] + var isTerminating = false + var isLeaf: Bool { + return children.count == 0 } + /// Initializes a node. /// /// - Parameters: From 53b87713a7f3a8083d67053416d4bc633090e68b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20B=C3=B8dskov?= Date: Wed, 11 Jan 2017 02:30:24 +0100 Subject: [PATCH 0768/1679] Migrates Ternary Search Tree to Swift 3 syntax (#352) * migrates Ternary Search Tree to Swift 3 syntax * aligning function names as suggested * adds unit tests to TernarySearchTree * adds guards as suggested --- .travis.yml | 1 + .../TST.playground/Contents.swift | 30 +- .../Sources/TernarySearchTree.swift | 48 ++-- .../TST.playground/Sources/Utils.swift | 30 ++ .../TST.playground/contents.xcplayground | 2 +- Ternary Search Tree/TernarySearchTree.swift | 54 ++-- Ternary Search Tree/Tests/Info.plist | 22 ++ .../Tests/TernarySearchTreeTests.swift | 58 ++++ .../Tests/Tests.xcodeproj/project.pbxproj | 264 ++++++++++++++++++ .../xcshareddata/xcschemes/Tests.xcscheme | 56 ++++ Ternary Search Tree/Utils.swift | 30 ++ .../contents.xcworkspacedata | 10 + 12 files changed, 529 insertions(+), 76 deletions(-) create mode 100644 Ternary Search Tree/TST.playground/Sources/Utils.swift create mode 100644 Ternary Search Tree/Tests/Info.plist create mode 100644 Ternary Search Tree/Tests/TernarySearchTreeTests.swift create mode 100644 Ternary Search Tree/Tests/Tests.xcodeproj/project.pbxproj create mode 100644 Ternary Search Tree/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme create mode 100644 Ternary Search Tree/Utils.swift diff --git a/.travis.yml b/.travis.yml index 6812ac32a..117400d97 100644 --- a/.travis.yml +++ b/.travis.yml @@ -43,3 +43,4 @@ script: - xcodebuild test -project ./Topological\ Sort/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Treap/Treap/Treap.xcodeproj -scheme Tests - xcodebuild test -project ./Palindromes/Test/Test.xcodeproj -scheme Test +- xcodebuild test -project ./Ternary\ Search\ Tree/Tests/Tests.xcodeproj -scheme Tests diff --git a/Ternary Search Tree/TST.playground/Contents.swift b/Ternary Search Tree/TST.playground/Contents.swift index 6b1fe3eaa..bacf56aee 100644 --- a/Ternary Search Tree/TST.playground/Contents.swift +++ b/Ternary Search Tree/TST.playground/Contents.swift @@ -4,39 +4,23 @@ import Cocoa import Foundation let treeOfStrings = TernarySearchTree() -let allowedChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" - -//Random string generator from: -//http://stackoverflow.com/questions/26845307/generate-random-alphanumeric-string-in-swift/26845710 -func randomAlphaNumericString(length: Int) -> String { - let allowedCharsCount = UInt32(allowedChars.characters.count) - var randomString = "" - - for _ in (0..() for _ in (1...testCount) { let randomNum = Int(arc4random_uniform(UInt32.max)) let randomLength = Int(arc4random_uniform(10)) - let key = randomAlphaNumericString(randomLength) + let key = Utils.shared.randomAlphaNumericString(withLength: randomLength) if key != "" { testNums.append((key, randomNum)) - treeOfInts.insert(randomNum, withKey: key) + treeOfInts.insert(data: randomNum, withKey: key) } } for aTest in testNums { - let data = treeOfInts.find(aTest.key) + let data = treeOfInts.find(key: aTest.key) if data == nil { print("TEST FAILED. Key: \(aTest.key) Data: \(aTest.data)") } diff --git a/Ternary Search Tree/TST.playground/Sources/TernarySearchTree.swift b/Ternary Search Tree/TST.playground/Sources/TernarySearchTree.swift index 43c4453e3..fed8f9710 100644 --- a/Ternary Search Tree/TST.playground/Sources/TernarySearchTree.swift +++ b/Ternary Search Tree/TST.playground/Sources/TernarySearchTree.swift @@ -18,11 +18,10 @@ public class TernarySearchTree { //MARK: - Insertion public func insert(data: Element, withKey key: String) -> Bool { - return insertNode(&root, withData: data, andKey: key, atIndex: 0) - + return insert(node: &root, withData: data, andKey: key, atIndex: 0) } - private func insertNode(inout aNode: TSTNode?, withData data: Element, andKey key: String, atIndex charIndex: Int) -> Bool { + private func insert(node: inout TSTNode?, withData data: Element, andKey key: String, atIndex charIndex: Int) -> Bool { //sanity check. if key.characters.count == 0 { @@ -30,30 +29,30 @@ public class TernarySearchTree { } //create a new node if necessary. - if aNode == nil { - let index = key.startIndex.advancedBy(charIndex) - aNode = TSTNode(key: key[index]) + if node == nil { + let index = key.index(key.startIndex, offsetBy: charIndex) + node = TSTNode(key: key[index]) } //if current char is less than the current node's char, go left - let index = key.startIndex.advancedBy(charIndex) - if key[index] < aNode!.key { - return insertNode(&aNode!.left, withData: data, andKey: key, atIndex: charIndex) + let index = key.index(key.startIndex, offsetBy: charIndex) + if key[index] < node!.key { + return insert(node: &node!.left, withData: data, andKey: key, atIndex: charIndex) } //if it's greater, go right. - else if key[index] > aNode!.key { - return insertNode(&aNode!.right, withData: data, andKey: key, atIndex: charIndex) + else if key[index] > node!.key { + return insert(node: &node!.right, withData: data, andKey: key, atIndex: charIndex) } //current char is equal to the current nodes, go middle else { //continue down the middle. if charIndex + 1 < key.characters.count { - return insertNode(&aNode!.middle, withData: data, andKey: key, atIndex: charIndex + 1) + return insert(node: &node!.middle, withData: data, andKey: key, atIndex: charIndex + 1) } //otherwise, all done. else { - aNode!.data = data - aNode?.hasData = true + node!.data = data + node?.hasData = true return true } } @@ -64,32 +63,31 @@ public class TernarySearchTree { public func find(key: String) -> Element? { - return findNode(root, withKey: key, atIndex: 0) + return find(node: root, withKey: key, atIndex: 0) } - - private func findNode(aNode: TSTNode?, withKey key: String, atIndex charIndex: Int) -> Element? { + private func find(node: TSTNode?, withKey key: String, atIndex charIndex: Int) -> Element? { //Given key does not exist in tree. - if aNode == nil { + if node == nil { return nil } - let index = key.startIndex.advancedBy(charIndex) + let index = key.index(key.startIndex, offsetBy: charIndex) //go left - if key[index] < aNode!.key { - return findNode(aNode!.left, withKey: key, atIndex: charIndex) + if key[index] < node!.key { + return find(node: node!.left, withKey: key, atIndex: charIndex) } //go right - else if key[index] > aNode!.key { - return findNode(aNode!.right, withKey: key, atIndex: charIndex) + else if key[index] > node!.key { + return find(node: node!.right, withKey: key, atIndex: charIndex) } //go middle else { if charIndex + 1 < key.characters.count { - return findNode(aNode!.middle, withKey: key, atIndex: charIndex + 1) + return find(node: node!.middle, withKey: key, atIndex: charIndex + 1) } else { - return aNode!.data + return node!.data } } } diff --git a/Ternary Search Tree/TST.playground/Sources/Utils.swift b/Ternary Search Tree/TST.playground/Sources/Utils.swift new file mode 100644 index 000000000..cabfe1b68 --- /dev/null +++ b/Ternary Search Tree/TST.playground/Sources/Utils.swift @@ -0,0 +1,30 @@ +// +// Utils.swift +// +// +// Created by Peter Bødskov on 10/01/17. +// +// + +import Foundation + +public struct Utils { + + public static let shared = Utils() + + let allowedChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" + //Random string generator from: + //http://stackoverflow.com/questions/26845307/generate-random-alphanumeric-string-in-swift/26845710 + public func randomAlphaNumericString(withLength length: Int) -> String { + let allowedCharsCount = UInt32(allowedChars.characters.count) + var randomString = "" + + for _ in (0.. - + \ No newline at end of file diff --git a/Ternary Search Tree/TernarySearchTree.swift b/Ternary Search Tree/TernarySearchTree.swift index 2f143bead..c4b51519a 100644 --- a/Ternary Search Tree/TernarySearchTree.swift +++ b/Ternary Search Tree/TernarySearchTree.swift @@ -33,52 +33,52 @@ public class TernarySearchTree { - returns: Value indicating insertion success/failure. */ - public func insert(data: Element, withKey key: String) -> Bool { - return insertNode(&root, withData: data, andKey: key, atIndex: 0) + @discardableResult public func insert(data: Element, withKey key: String) -> Bool { + return insert(node: &root, withData: data, andKey: key, atIndex: 0) } /** Helper method for insertion that does the actual legwork. Insertion is performed recursively. - - parameter aNode: The current node to insert below. + - parameter node: The current node to insert below. - parameter data: The data being inserted. - parameter key: The key being used to find an insertion location for the given data - parameter charIndex: The index of the character in the key string to use to for the next node. - returns: Value indicating insertion success/failure. */ - private func insertNode(inout aNode: TSTNode?, withData data: Element, andKey key: String, atIndex charIndex: Int) -> Bool { + private func insert(node: inout TSTNode?, withData data: Element, andKey key: String, atIndex charIndex: Int) -> Bool { //sanity check. - if key.characters.count == 0 { + guard key.characters.count > 0 else { return false } //create a new node if necessary. - if aNode == nil { - let index = key.startIndex.advancedBy(charIndex) - aNode = TSTNode(key: key[index]) + if node == nil { + let index = key.index(key.startIndex, offsetBy: charIndex) + node = TSTNode(key: key[index]) } //if current char is less than the current node's char, go left - let index = key.startIndex.advancedBy(charIndex) - if key[index] < aNode!.key { - return insertNode(&aNode!.left, withData: data, andKey: key, atIndex: charIndex) + let index = key.index(key.startIndex, offsetBy: charIndex) + if key[index] < node!.key { + return insert(node: &node!.left, withData: data, andKey: key, atIndex: charIndex) } //if it's greater, go right. - else if key[index] > aNode!.key { - return insertNode(&aNode!.right, withData: data, andKey: key, atIndex: charIndex) + else if key[index] > node!.key { + return insert(node: &node!.right, withData: data, andKey: key, atIndex: charIndex) } //current char is equal to the current nodes, go middle else { //continue down the middle. if charIndex + 1 < key.characters.count { - return insertNode(&aNode!.middle, withData: data, andKey: key, atIndex: charIndex + 1) + return insert(node: &node!.middle, withData: data, andKey: key, atIndex: charIndex + 1) } //otherwise, all done. else { - aNode!.data = data - aNode?.hasData = true + node!.data = data + node?.hasData = true return true } } @@ -95,40 +95,40 @@ public class TernarySearchTree { - returns: The element, if found. Otherwise, nil. */ public func find(key: String) -> Element? { - return findNode(root, withKey: key, atIndex: 0) + return find(node: root, withKey: key, atIndex: 0) } /** Helper method that performs actual legwork of find operation. Implemented recursively. - - parameter aNode: The current node being evaluated. + - parameter node: The current node being evaluated. - parameter key: The key being used for the search. - parameter charIndex: The index of the current char in the search key - returns: The element, if found. Nil otherwise. */ - private func findNode(aNode: TSTNode?, withKey key: String, atIndex charIndex: Int) -> Element? { + private func find(node: TSTNode?, withKey key: String, atIndex charIndex: Int) -> Element? { //Given key does not exist in tree. - if aNode == nil { + guard let node = node else { return nil } - let index = key.startIndex.advancedBy(charIndex) + let index = key.index(key.startIndex, offsetBy: charIndex) //go left - if key[index] < aNode!.key { - return findNode(aNode!.left, withKey: key, atIndex: charIndex) + if key[index] < node.key { + return find(node: node.left, withKey: key, atIndex: charIndex) } //go right - else if key[index] > aNode!.key { - return findNode(aNode!.right, withKey: key, atIndex: charIndex) + else if key[index] > node.key { + return find(node: node.right, withKey: key, atIndex: charIndex) } //go middle else { if charIndex + 1 < key.characters.count { - return findNode(aNode!.middle, withKey: key, atIndex: charIndex + 1) + return find(node: node.middle, withKey: key, atIndex: charIndex + 1) } else { - return aNode!.data + return node.data } } } diff --git a/Ternary Search Tree/Tests/Info.plist b/Ternary Search Tree/Tests/Info.plist new file mode 100644 index 000000000..6c6c23c43 --- /dev/null +++ b/Ternary Search Tree/Tests/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + diff --git a/Ternary Search Tree/Tests/TernarySearchTreeTests.swift b/Ternary Search Tree/Tests/TernarySearchTreeTests.swift new file mode 100644 index 000000000..51e7c808c --- /dev/null +++ b/Ternary Search Tree/Tests/TernarySearchTreeTests.swift @@ -0,0 +1,58 @@ +// +// Tests.swift +// Tests +// +// Created by Peter Bødskov on 10/01/17. +// Copyright © 2017 Swift Algorithm Club. All rights reserved. +// + +import XCTest + +class TernarySearchTreeTests: XCTestCase { + + let treeOfStrings = TernarySearchTree() + let testCount = 30 + + func testCanFindStringInTree() { + var testStrings: [(key: String, data: String)] = [] + for _ in (1...testCount) { + let randomLength = Int(arc4random_uniform(10)) + let key = Utils.shared.randomAlphaNumericString(withLength: randomLength) + let data = Utils.shared.randomAlphaNumericString(withLength: randomLength) + // print("Key: \(key) Data: \(data)") + + if key != "" && data != "" { + testStrings.append((key, data)) + treeOfStrings.insert(data: data, withKey: key) + } + } + + for aTest in testStrings { + let data = treeOfStrings.find(key: aTest.key) + + XCTAssertNotNil(data) + XCTAssertEqual(data, aTest.data) + } + } + + func testCanFindNumberInTree() { + var testNums: [(key: String, data: Int)] = [] + let treeOfInts = TernarySearchTree() + for _ in (1...testCount) { + let randomNum = Int(arc4random_uniform(UInt32.max)) + let randomLength = Int(arc4random_uniform(10)) + let key = Utils.shared.randomAlphaNumericString(withLength: randomLength) + + if key != "" { + testNums.append((key, randomNum)) + treeOfInts.insert(data: randomNum, withKey: key) + } + } + + for aTest in testNums { + let data = treeOfInts.find(key: aTest.key) + XCTAssertNotNil(data) + XCTAssertEqual(data, aTest.data) + } + } +} diff --git a/Ternary Search Tree/Tests/Tests.xcodeproj/project.pbxproj b/Ternary Search Tree/Tests/Tests.xcodeproj/project.pbxproj new file mode 100644 index 000000000..7afaca944 --- /dev/null +++ b/Ternary Search Tree/Tests/Tests.xcodeproj/project.pbxproj @@ -0,0 +1,264 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + D06C22031E24D02800622925 /* TernarySearchTreeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D06C22021E24D02800622925 /* TernarySearchTreeTests.swift */; }; + D0957B8A1E24D92D00417988 /* TernarySearchTree.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0957B891E24D92D00417988 /* TernarySearchTree.swift */; }; + D0957B8C1E24D9A300417988 /* Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0957B8B1E24D9A300417988 /* Utils.swift */; }; + D0957B8E1E24DA0100417988 /* TSTNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0957B8D1E24DA0100417988 /* TSTNode.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + D06C22021E24D02800622925 /* TernarySearchTreeTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TernarySearchTreeTests.swift; sourceTree = ""; }; + D06C22041E24D02800622925 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + D06C22081E24D16800622925 /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + D0957B891E24D92D00417988 /* TernarySearchTree.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = TernarySearchTree.swift; path = ../TernarySearchTree.swift; sourceTree = ""; }; + D0957B8B1E24D9A300417988 /* Utils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Utils.swift; path = ../Utils.swift; sourceTree = ""; }; + D0957B8D1E24DA0100417988 /* TSTNode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = TSTNode.swift; path = ../TSTNode.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + D06C21FD1E24D02800622925 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + D06C21B61E24CC9600622925 = { + isa = PBXGroup; + children = ( + D0957B891E24D92D00417988 /* TernarySearchTree.swift */, + D0957B8B1E24D9A300417988 /* Utils.swift */, + D06C22021E24D02800622925 /* TernarySearchTreeTests.swift */, + D0957B8D1E24DA0100417988 /* TSTNode.swift */, + D06C22041E24D02800622925 /* Info.plist */, + D06C22081E24D16800622925 /* Tests.xctest */, + ); + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + D06C21FF1E24D02800622925 /* Tests */ = { + isa = PBXNativeTarget; + buildConfigurationList = D06C22051E24D02800622925 /* Build configuration list for PBXNativeTarget "Tests" */; + buildPhases = ( + D06C21FC1E24D02800622925 /* Sources */, + D06C21FD1E24D02800622925 /* Frameworks */, + D06C21FE1E24D02800622925 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Tests; + productName = Tests; + productReference = D06C22081E24D16800622925 /* Tests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + D06C21B71E24CC9600622925 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0810; + LastUpgradeCheck = 0810; + ORGANIZATIONNAME = "Swift Algorithm Club"; + TargetAttributes = { + D06C21FF1E24D02800622925 = { + CreatedOnToolsVersion = 8.1; + ProvisioningStyle = Automatic; + }; + }; + }; + buildConfigurationList = D06C21BA1E24CC9600622925 /* Build configuration list for PBXProject "Tests" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = D06C21B61E24CC9600622925; + productRefGroup = D06C21B61E24CC9600622925; + projectDirPath = ""; + projectRoot = ""; + targets = ( + D06C21FF1E24D02800622925 /* Tests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + D06C21FE1E24D02800622925 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + D06C21FC1E24D02800622925 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D06C22031E24D02800622925 /* TernarySearchTreeTests.swift in Sources */, + D0957B8E1E24DA0100417988 /* TSTNode.swift in Sources */, + D0957B8A1E24D92D00417988 /* TernarySearchTree.swift in Sources */, + D0957B8C1E24D9A300417988 /* Utils.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + D06C21C31E24CC9600622925 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVES = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + }; + name = Debug; + }; + D06C21C41E24CC9600622925 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVES = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + }; + name = Release; + }; + D06C22061E24D02800622925 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 3.0; + }; + name = Debug; + }; + D06C22071E24D02800622925 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_VERSION = 3.0; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + D06C21BA1E24CC9600622925 /* Build configuration list for PBXProject "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D06C21C31E24CC9600622925 /* Debug */, + D06C21C41E24CC9600622925 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + D06C22051E24D02800622925 /* Build configuration list for PBXNativeTarget "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D06C22061E24D02800622925 /* Debug */, + D06C22071E24D02800622925 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = D06C21B71E24CC9600622925 /* Project object */; +} diff --git a/Ternary Search Tree/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Ternary Search Tree/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme new file mode 100644 index 000000000..752b0c7fc --- /dev/null +++ b/Ternary Search Tree/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Ternary Search Tree/Utils.swift b/Ternary Search Tree/Utils.swift new file mode 100644 index 000000000..cabfe1b68 --- /dev/null +++ b/Ternary Search Tree/Utils.swift @@ -0,0 +1,30 @@ +// +// Utils.swift +// +// +// Created by Peter Bødskov on 10/01/17. +// +// + +import Foundation + +public struct Utils { + + public static let shared = Utils() + + let allowedChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" + //Random string generator from: + //http://stackoverflow.com/questions/26845307/generate-random-alphanumeric-string-in-swift/26845710 + public func randomAlphaNumericString(withLength length: Int) -> String { + let allowedCharsCount = UInt32(allowedChars.characters.count) + var randomString = "" + + for _ in (0.. + + + + + + From b9b491d98c50a270184204a98e982e1ccc3b07ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20B=C3=B8dskov?= Date: Wed, 11 Jan 2017 16:05:37 +0100 Subject: [PATCH 0769/1679] fixing failing test (#355) the problem was that the testdata generator could generate keys that was not unique...which caused the `find` method to return the wrong values for keys when the keys were the same. --- Ternary Search Tree/TernarySearchTree.swift | 2 +- .../Tests/TernarySearchTreeTests.swift | 25 ++++++++++++++----- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/Ternary Search Tree/TernarySearchTree.swift b/Ternary Search Tree/TernarySearchTree.swift index c4b51519a..2e2ca2917 100644 --- a/Ternary Search Tree/TernarySearchTree.swift +++ b/Ternary Search Tree/TernarySearchTree.swift @@ -75,7 +75,7 @@ public class TernarySearchTree { if charIndex + 1 < key.characters.count { return insert(node: &node!.middle, withData: data, andKey: key, atIndex: charIndex + 1) } - //otherwise, all done. + //otherwise, all done. else { node!.data = data node?.hasData = true diff --git a/Ternary Search Tree/Tests/TernarySearchTreeTests.swift b/Ternary Search Tree/Tests/TernarySearchTreeTests.swift index 51e7c808c..40739c888 100644 --- a/Ternary Search Tree/Tests/TernarySearchTreeTests.swift +++ b/Ternary Search Tree/Tests/TernarySearchTreeTests.swift @@ -10,14 +10,23 @@ import XCTest class TernarySearchTreeTests: XCTestCase { - let treeOfStrings = TernarySearchTree() + let testCount = 30 func testCanFindStringInTree() { var testStrings: [(key: String, data: String)] = [] + let treeOfStrings = TernarySearchTree() + for _ in (1...testCount) { - let randomLength = Int(arc4random_uniform(10)) - let key = Utils.shared.randomAlphaNumericString(withLength: randomLength) + var randomLength = Int(arc4random_uniform(10)) + + var key = Utils.shared.randomAlphaNumericString(withLength: randomLength) + + while testStrings.contains(where: { $0.key == key}) { + //That key is taken, so we generate a new one with another length + randomLength = Int(arc4random_uniform(10)) + key = Utils.shared.randomAlphaNumericString(withLength: randomLength) + } let data = Utils.shared.randomAlphaNumericString(withLength: randomLength) // print("Key: \(key) Data: \(data)") @@ -29,7 +38,6 @@ class TernarySearchTreeTests: XCTestCase { for aTest in testStrings { let data = treeOfStrings.find(key: aTest.key) - XCTAssertNotNil(data) XCTAssertEqual(data, aTest.data) } @@ -40,8 +48,13 @@ class TernarySearchTreeTests: XCTestCase { let treeOfInts = TernarySearchTree() for _ in (1...testCount) { let randomNum = Int(arc4random_uniform(UInt32.max)) - let randomLength = Int(arc4random_uniform(10)) - let key = Utils.shared.randomAlphaNumericString(withLength: randomLength) + var randomLength = Int(arc4random_uniform(10)) + var key = Utils.shared.randomAlphaNumericString(withLength: randomLength) + while testNums.contains(where: { $0.key == key}) { + //That key is taken, so we generate a new one with another length + randomLength = Int(arc4random_uniform(10)) + key = Utils.shared.randomAlphaNumericString(withLength: randomLength) + } if key != "" { testNums.append((key, randomNum)) From bc73299363a92f07b95bd831942985c2daba1d4b Mon Sep 17 00:00:00 2001 From: Keita Date: Wed, 11 Jan 2017 16:58:11 -0800 Subject: [PATCH 0770/1679] Update Stack and Queue files to use top and front properties (#351) * Update Stack.swift and StackTests.swift to use top property - peek() method was replaced with top property. Update Stack.swift and StackTests.swift to use top property instead of peek() method. - Fix indentation in Stack/README.markdown. * Update Queue-Optimized.swift and QueueTests.swift to use front property - peek() method was replaced with front property. Update Queue-Optimized.swift and QueueTests.swift to use front property instead of peek() method. - Fix front property implementation of Queue-Optimized in Queue/README.markdown. * Update Queue-Simple.swift to use front property instead of peek() method --- Queue/Queue-Optimized.swift | 2 +- Queue/Queue-Simple.swift | 2 +- Queue/README.markdown | 6 +++++- Queue/Tests/QueueTests.swift | 16 ++++++++-------- Stack/README.markdown | 2 +- Stack/Stack.swift | 2 +- Stack/Tests/StackTests.swift | 16 ++++++++-------- 7 files changed, 25 insertions(+), 21 deletions(-) diff --git a/Queue/Queue-Optimized.swift b/Queue/Queue-Optimized.swift index ad6999295..7dff91698 100644 --- a/Queue/Queue-Optimized.swift +++ b/Queue/Queue-Optimized.swift @@ -37,7 +37,7 @@ public struct Queue { return element } - public func peek() -> T? { + public var front: T? { if isEmpty { return nil } else { diff --git a/Queue/Queue-Simple.swift b/Queue/Queue-Simple.swift index 27fbdee4d..c5e8067c8 100644 --- a/Queue/Queue-Simple.swift +++ b/Queue/Queue-Simple.swift @@ -30,7 +30,7 @@ public struct Queue { } } - public func peek() -> T? { + public var front: T? { return array.first } } diff --git a/Queue/README.markdown b/Queue/README.markdown index 25d6205f8..f8259c31c 100644 --- a/Queue/README.markdown +++ b/Queue/README.markdown @@ -167,7 +167,11 @@ public struct Queue { } public var front: T? { - return array.first + if isEmpty { + return nil + } else { + return array[head] + } } } ``` diff --git a/Queue/Tests/QueueTests.swift b/Queue/Tests/QueueTests.swift index 7406f8d35..b820ac0d3 100755 --- a/Queue/Tests/QueueTests.swift +++ b/Queue/Tests/QueueTests.swift @@ -6,7 +6,7 @@ class QueueTest: XCTestCase { var queue = Queue() XCTAssertTrue(queue.isEmpty) XCTAssertEqual(queue.count, 0) - XCTAssertEqual(queue.peek(), nil) + XCTAssertEqual(queue.front, nil) XCTAssertNil(queue.dequeue()) } @@ -16,13 +16,13 @@ class QueueTest: XCTestCase { queue.enqueue(123) XCTAssertFalse(queue.isEmpty) XCTAssertEqual(queue.count, 1) - XCTAssertEqual(queue.peek(), 123) + XCTAssertEqual(queue.front, 123) let result = queue.dequeue() XCTAssertEqual(result, 123) XCTAssertTrue(queue.isEmpty) XCTAssertEqual(queue.count, 0) - XCTAssertEqual(queue.peek(), nil) + XCTAssertEqual(queue.front, nil) } func testTwoElements() { @@ -32,19 +32,19 @@ class QueueTest: XCTestCase { queue.enqueue(456) XCTAssertFalse(queue.isEmpty) XCTAssertEqual(queue.count, 2) - XCTAssertEqual(queue.peek(), 123) + XCTAssertEqual(queue.front, 123) let result1 = queue.dequeue() XCTAssertEqual(result1, 123) XCTAssertFalse(queue.isEmpty) XCTAssertEqual(queue.count, 1) - XCTAssertEqual(queue.peek(), 456) + XCTAssertEqual(queue.front, 456) let result2 = queue.dequeue() XCTAssertEqual(result2, 456) XCTAssertTrue(queue.isEmpty) XCTAssertEqual(queue.count, 0) - XCTAssertEqual(queue.peek(), nil) + XCTAssertEqual(queue.front, nil) } func testMakeEmpty() { @@ -58,12 +58,12 @@ class QueueTest: XCTestCase { queue.enqueue(789) XCTAssertEqual(queue.count, 1) - XCTAssertEqual(queue.peek(), 789) + XCTAssertEqual(queue.front, 789) let result = queue.dequeue() XCTAssertEqual(result, 789) XCTAssertTrue(queue.isEmpty) XCTAssertEqual(queue.count, 0) - XCTAssertEqual(queue.peek(), nil) + XCTAssertEqual(queue.front, nil) } } diff --git a/Stack/README.markdown b/Stack/README.markdown index a79e2c261..1a3ca2638 100644 --- a/Stack/README.markdown +++ b/Stack/README.markdown @@ -61,7 +61,7 @@ public struct Stack { } public var top: T? { - return array.last + return array.last } } ``` diff --git a/Stack/Stack.swift b/Stack/Stack.swift index 49edaf4cb..974d5a443 100644 --- a/Stack/Stack.swift +++ b/Stack/Stack.swift @@ -22,7 +22,7 @@ public struct Stack { return array.popLast() } - public func peek() -> T? { + public var top: T? { return array.last } } diff --git a/Stack/Tests/StackTests.swift b/Stack/Tests/StackTests.swift index 62e26b0fa..f4df09a67 100755 --- a/Stack/Tests/StackTests.swift +++ b/Stack/Tests/StackTests.swift @@ -6,7 +6,7 @@ class StackTest: XCTestCase { var stack = Stack() XCTAssertTrue(stack.isEmpty) XCTAssertEqual(stack.count, 0) - XCTAssertEqual(stack.peek(), nil) + XCTAssertEqual(stack.top, nil) XCTAssertNil(stack.pop()) } @@ -16,13 +16,13 @@ class StackTest: XCTestCase { stack.push(123) XCTAssertFalse(stack.isEmpty) XCTAssertEqual(stack.count, 1) - XCTAssertEqual(stack.peek(), 123) + XCTAssertEqual(stack.top, 123) let result = stack.pop() XCTAssertEqual(result, 123) XCTAssertTrue(stack.isEmpty) XCTAssertEqual(stack.count, 0) - XCTAssertEqual(stack.peek(), nil) + XCTAssertEqual(stack.top, nil) XCTAssertNil(stack.pop()) } @@ -33,19 +33,19 @@ class StackTest: XCTestCase { stack.push(456) XCTAssertFalse(stack.isEmpty) XCTAssertEqual(stack.count, 2) - XCTAssertEqual(stack.peek(), 456) + XCTAssertEqual(stack.top, 456) let result1 = stack.pop() XCTAssertEqual(result1, 456) XCTAssertFalse(stack.isEmpty) XCTAssertEqual(stack.count, 1) - XCTAssertEqual(stack.peek(), 123) + XCTAssertEqual(stack.top, 123) let result2 = stack.pop() XCTAssertEqual(result2, 123) XCTAssertTrue(stack.isEmpty) XCTAssertEqual(stack.count, 0) - XCTAssertEqual(stack.peek(), nil) + XCTAssertEqual(stack.top, nil) XCTAssertNil(stack.pop()) } @@ -60,13 +60,13 @@ class StackTest: XCTestCase { stack.push(789) XCTAssertEqual(stack.count, 1) - XCTAssertEqual(stack.peek(), 789) + XCTAssertEqual(stack.top, 789) let result = stack.pop() XCTAssertEqual(result, 789) XCTAssertTrue(stack.isEmpty) XCTAssertEqual(stack.count, 0) - XCTAssertEqual(stack.peek(), nil) + XCTAssertEqual(stack.top, nil) XCTAssertNil(stack.pop()) } } From d3b2496c3b5a3eca4f80fdc8d33159ccd2fa6c2a Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Thu, 12 Jan 2017 01:43:41 -0800 Subject: [PATCH 0771/1679] Update README.markdown --- README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.markdown b/README.markdown index 9e0ae00fa..e5c8f8dae 100644 --- a/README.markdown +++ b/README.markdown @@ -8,7 +8,7 @@ If you're a computer science student who needs to learn this stuff for exams -- The goal of this project is to **explain how algorithms work**. The focus is on clarity and readability of the code, not on making a reusable library that you can drop into your own projects. That said, most of the code should be ready for production use but you may need to tweak it to fit into your own codebase. -All code is compatible with **Xcode 7.3** and **Swift 2.2**. We'll keep this updated with the latest version of Swift. +Most code is compatible with **Xcode 8.2** and **Swift 3**. We'll keep this updated with the latest version of Swift. This is a work in progress. More algorithms will be added soon. :-) From d44abb819f182abc44f86026d211ed1a132ccc88 Mon Sep 17 00:00:00 2001 From: Tai Heng Date: Tue, 10 Jan 2017 21:47:58 -0500 Subject: [PATCH 0772/1679] Updated radixSort argument to swift3 syntax. --- Radix Sort/radixSort.swift | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/Radix Sort/radixSort.swift b/Radix Sort/radixSort.swift index 31a783db7..24d4155d7 100644 --- a/Radix Sort/radixSort.swift +++ b/Radix Sort/radixSort.swift @@ -5,43 +5,42 @@ */ -func radixSort(inout arr: [Int] ) { - - +// NOTE: This implementation does not handle negative numbers +func radixSort(_ array: inout [Int] ) { let radix = 10 //Here we define our radix to be 10 var done = false var index: Int var digit = 1 //Which digit are we on? - - + + while !done { //While our sorting is not completed done = true //Assume it is done for now - + var buckets: [[Int]] = [] //Our sorting subroutine is bucket sort, so let us predefine our buckets - + for _ in 1...radix { buckets.append([]) } - - - for number in arr { + + + for number in array { index = number / digit //Which bucket will we access? buckets[index % radix].append(number) if done && index > 0 { //If we arent done, continue to finish, otherwise we are done done = false } } - + var i = 0 - + for j in 0.. Date: Tue, 10 Jan 2017 21:48:55 -0500 Subject: [PATCH 0773/1679] Added playground demonstrating radixSort. --- .../RadixSort.playground/Contents.swift | 16 +++++++ .../Sources/radixSort.swift | 46 +++++++++++++++++++ .../contents.xcplayground | 4 ++ 3 files changed, 66 insertions(+) create mode 100644 Radix Sort/RadixSort.playground/Contents.swift create mode 100644 Radix Sort/RadixSort.playground/Sources/radixSort.swift create mode 100644 Radix Sort/RadixSort.playground/contents.xcplayground diff --git a/Radix Sort/RadixSort.playground/Contents.swift b/Radix Sort/RadixSort.playground/Contents.swift new file mode 100644 index 000000000..a4f7e3527 --- /dev/null +++ b/Radix Sort/RadixSort.playground/Contents.swift @@ -0,0 +1,16 @@ +//: Playground - noun: a place where people can play + +import Cocoa + +// Test Radix Sort with small array of ten values +var array: [Int] = [19, 4242, 2, 9, 912, 101, 55, 67, 89, 32] +radixSort(&array) + +// Test Radix Sort with large array of 1000 random values +var bigArray = [Int](repeating: 0, count: 1000) +var i = 0 +while i < 1000 { + bigArray[i] = Int(arc4random_uniform(1000) + 1) + i += 1 +} +radixSort(&bigArray) diff --git a/Radix Sort/RadixSort.playground/Sources/radixSort.swift b/Radix Sort/RadixSort.playground/Sources/radixSort.swift new file mode 100644 index 000000000..136ede4fd --- /dev/null +++ b/Radix Sort/RadixSort.playground/Sources/radixSort.swift @@ -0,0 +1,46 @@ +/* + + Sorting Algorithm that sorts an input array of integers digit by digit. + + */ +import Foundation + +// NOTE: This implementation does not handle negative numbers +public func radixSort(_ array: inout [Int] ) { + let radix = 10 //Here we define our radix to be 10 + var done = false + var index: Int + var digit = 1 //Which digit are we on? + + + while !done { //While our sorting is not completed + done = true //Assume it is done for now + + var buckets: [[Int]] = [] //Our sorting subroutine is bucket sort, so let us predefine our buckets + + for _ in 1...radix { + buckets.append([]) + } + + + for number in array { + index = number / digit //Which bucket will we access? + buckets[index % radix].append(number) + if done && index > 0 { //If we arent done, continue to finish, otherwise we are done + done = false + } + } + + var i = 0 + + for j in 0.. + + + \ No newline at end of file From 021772eee7c6b8da4598fa7d0ecffb817388aa94 Mon Sep 17 00:00:00 2001 From: Tai Heng Date: Tue, 10 Jan 2017 21:49:55 -0500 Subject: [PATCH 0774/1679] Added tests for RadixSort. --- .travis.yml | 1 + .../contents.xcworkspacedata | 7 + Radix Sort/Tests/Info.plist | 22 ++ Radix Sort/Tests/RadixSortTests.swift | 18 ++ .../Tests/Tests.xcodeproj/project.pbxproj | 277 ++++++++++++++++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/xcschemes/Tests.xcscheme | 101 +++++++ 7 files changed, 433 insertions(+) create mode 100644 Radix Sort/RadixSort.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 Radix Sort/Tests/Info.plist create mode 100644 Radix Sort/Tests/RadixSortTests.swift create mode 100644 Radix Sort/Tests/Tests.xcodeproj/project.pbxproj create mode 100644 Radix Sort/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 Radix Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme diff --git a/.travis.yml b/.travis.yml index 9d8c6e346..64c23eb56 100644 --- a/.travis.yml +++ b/.travis.yml @@ -33,6 +33,7 @@ script: # - xcodebuild test -project ./Priority\ Queue/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Queue/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Quicksort/Tests/Tests.xcodeproj -scheme Tests +- xcodebuild test -project ./Radix\ Sort/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Rootish\ Array\ Stack/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Run-Length\ Encoding/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Select\ Minimum\ Maximum/Tests/Tests.xcodeproj -scheme Tests diff --git a/Radix Sort/RadixSort.playground/playground.xcworkspace/contents.xcworkspacedata b/Radix Sort/RadixSort.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Radix Sort/RadixSort.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Radix Sort/Tests/Info.plist b/Radix Sort/Tests/Info.plist new file mode 100644 index 000000000..6c6c23c43 --- /dev/null +++ b/Radix Sort/Tests/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + diff --git a/Radix Sort/Tests/RadixSortTests.swift b/Radix Sort/Tests/RadixSortTests.swift new file mode 100644 index 000000000..688bcdcb8 --- /dev/null +++ b/Radix Sort/Tests/RadixSortTests.swift @@ -0,0 +1,18 @@ +// +// RadixSortTests.swift +// Tests +// +// Created by theng on 2017-01-10. +// Copyright © 2017 Swift Algorithm Club. All rights reserved. +// + +import XCTest + +class RadixSortTests: XCTestCase { + func testCombSort() { + let expectedSequence: [Int] = [2, 9, 19, 32, 55, 67, 89, 101, 912, 4242] + var sequence = [19, 4242, 2, 9, 912, 101, 55, 67, 89, 32] + radixSort(&sequence) + XCTAssertEqual(sequence, expectedSequence) + } +} diff --git a/Radix Sort/Tests/Tests.xcodeproj/project.pbxproj b/Radix Sort/Tests/Tests.xcodeproj/project.pbxproj new file mode 100644 index 000000000..4b32f71b5 --- /dev/null +++ b/Radix Sort/Tests/Tests.xcodeproj/project.pbxproj @@ -0,0 +1,277 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 056E92AB1E25D0C700B30F52 /* RadixSortTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 056E92AA1E25D0C700B30F52 /* RadixSortTests.swift */; }; + 056E92AF1E25D3D700B30F52 /* radixSort.swift in Sources */ = {isa = PBXBuildFile; fileRef = 056E92AE1E25D3D700B30F52 /* radixSort.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 056E92A21E25D04D00B30F52 /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 056E92A61E25D04D00B30F52 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 056E92AA1E25D0C700B30F52 /* RadixSortTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RadixSortTests.swift; sourceTree = ""; }; + 056E92AE1E25D3D700B30F52 /* radixSort.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = radixSort.swift; path = ../radixSort.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 056E929F1E25D04D00B30F52 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 056E92851E25D03300B30F52 = { + isa = PBXGroup; + children = ( + 056E92A31E25D04D00B30F52 /* Tests */, + 056E928F1E25D03300B30F52 /* Products */, + ); + sourceTree = ""; + }; + 056E928F1E25D03300B30F52 /* Products */ = { + isa = PBXGroup; + children = ( + 056E92A21E25D04D00B30F52 /* Tests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 056E92A31E25D04D00B30F52 /* Tests */ = { + isa = PBXGroup; + children = ( + 056E92AE1E25D3D700B30F52 /* radixSort.swift */, + 056E92A61E25D04D00B30F52 /* Info.plist */, + 056E92AA1E25D0C700B30F52 /* RadixSortTests.swift */, + ); + name = Tests; + sourceTree = SOURCE_ROOT; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 056E92A11E25D04D00B30F52 /* Tests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 056E92A71E25D04D00B30F52 /* Build configuration list for PBXNativeTarget "Tests" */; + buildPhases = ( + 056E929E1E25D04D00B30F52 /* Sources */, + 056E929F1E25D04D00B30F52 /* Frameworks */, + 056E92A01E25D04D00B30F52 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Tests; + productName = Tests; + productReference = 056E92A21E25D04D00B30F52 /* Tests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 056E92861E25D03300B30F52 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0820; + LastUpgradeCheck = 0820; + ORGANIZATIONNAME = "Swift Algorithm Club"; + TargetAttributes = { + 056E92A11E25D04D00B30F52 = { + CreatedOnToolsVersion = 8.2; + LastSwiftMigration = 0820; + ProvisioningStyle = Automatic; + }; + }; + }; + buildConfigurationList = 056E92891E25D03300B30F52 /* Build configuration list for PBXProject "Tests" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 056E92851E25D03300B30F52; + productRefGroup = 056E928F1E25D03300B30F52 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 056E92A11E25D04D00B30F52 /* Tests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 056E92A01E25D04D00B30F52 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 056E929E1E25D04D00B30F52 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 056E92AF1E25D3D700B30F52 /* radixSort.swift in Sources */, + 056E92AB1E25D0C700B30F52 /* RadixSortTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 056E92991E25D03300B30F52 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.12; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 056E929A1E25D03300B30F52 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.12; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + }; + name = Release; + }; + 056E92A81E25D04D00B30F52 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = Swift.Algorithm.Club.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 3.0; + }; + name = Debug; + }; + 056E92A91E25D04D00B30F52 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = Swift.Algorithm.Club.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 056E92891E25D03300B30F52 /* Build configuration list for PBXProject "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 056E92991E25D03300B30F52 /* Debug */, + 056E929A1E25D03300B30F52 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 056E92A71E25D04D00B30F52 /* Build configuration list for PBXNativeTarget "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 056E92A81E25D04D00B30F52 /* Debug */, + 056E92A91E25D04D00B30F52 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 056E92861E25D03300B30F52 /* Project object */; +} diff --git a/Radix Sort/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Radix Sort/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..6c0ea8493 --- /dev/null +++ b/Radix Sort/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Radix Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Radix Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme new file mode 100644 index 000000000..b3f6d696a --- /dev/null +++ b/Radix Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 548f11791666bb2df3cae77183efda861171a0d0 Mon Sep 17 00:00:00 2001 From: Richard Date: Thu, 12 Jan 2017 20:17:41 -0800 Subject: [PATCH 0775/1679] Code restructuring - Moved source files Matrix.swift, MatrixSize.swift & Number.swift to the Sources foler in the PLayground - Restrucutred the code into extensions to make it more organized and readable - Deleted all the objects from the playground and moved them to the Sources folder --- .../MatrixSize.swift | 26 -- .../Contents.swift | 297 +----------------- .../Sources}/Matrix.swift | 183 +++++------ .../Sources/MatrixSize.swift | 33 ++ .../Sources}/Number.swift | 15 +- 5 files changed, 136 insertions(+), 418 deletions(-) delete mode 100644 Strassen Matrix Multiplication/MatrixSize.swift rename Strassen Matrix Multiplication/{ => StrassensMatrixMultiplication.playground/Sources}/Matrix.swift (72%) create mode 100644 Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/MatrixSize.swift rename Strassen Matrix Multiplication/{ => StrassensMatrixMultiplication.playground/Sources}/Number.swift (71%) diff --git a/Strassen Matrix Multiplication/MatrixSize.swift b/Strassen Matrix Multiplication/MatrixSize.swift deleted file mode 100644 index f1eada931..000000000 --- a/Strassen Matrix Multiplication/MatrixSize.swift +++ /dev/null @@ -1,26 +0,0 @@ -// -// MatrixSize.swift -// -// -// Created by Richard Ash on 10/28/16. -// -// - -import Foundation - -struct MatrixSize: Equatable { - let rows: Int - let columns: Int - - func forEach(_ body: (Int, Int) throws -> Void) rethrows { - for row in 0.. Bool { - return lhs.columns == rhs.columns && lhs.rows == rhs.rows -} diff --git a/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Contents.swift b/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Contents.swift index d4b4d8330..50af60a6f 100644 --- a/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Contents.swift +++ b/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Contents.swift @@ -1,302 +1,7 @@ //: Playground - noun: a place where people can play // Reference - http://mathworld.wolfram.com/StrassenFormulas.html - -import UIKit - -enum RowOrColumn { - case row, column -} - -protocol Number: Multipliable, Addable { - static var zero: Self { get } -} - -protocol Addable { - static func +(lhs: Self, rhs: Self) -> Self - static func -(lhs: Self, rhs: Self) -> Self -} - -protocol Multipliable { - static func *(lhs: Self, rhs: Self) -> Self -} - -extension Int: Number { - static var zero: Int { - return 0 - } -} - -extension Double: Number { - static var zero: Double { - return 0.0 - } -} - -extension Float: Number { - static var zero: Float { - return 0.0 - } -} - - -extension Array where Element: Number { - func dot(_ b: Array) -> Element { - let a = self - assert(a.count == b.count, "Can only take the dot product of arrays of the same length!") - let c = a.indices.map{ a[$0] * b[$0] } - return c.reduce(Element.zero, { $0 + $1 }) - } -} - -struct MatrixSize: Equatable { - let rows: Int - let columns: Int - - func forEach(_ body: (Int, Int) throws -> Void) rethrows { - for row in 0.. Bool { - return lhs.columns == rhs.columns && lhs.rows == rhs.rows -} - - -struct Matrix { - - // MARK: - Variables - - let rows: Int, columns: Int - var grid: [T] - - var isSquare: Bool { - return rows == columns - } - - var size: MatrixSize { - return MatrixSize(rows: rows, columns: columns) - } - - // MARK: - Init - - init(rows: Int, columns: Int, initialValue: T = T.zero) { - self.rows = rows - self.columns = columns - self.grid = Array(repeating: initialValue, count: rows * columns) - } - - init(size: Int, initialValue: T = T.zero) { - self.rows = size - self.columns = size - self.grid = Array(repeating: initialValue, count: rows * columns) - } - - // MARK: - Subscript - - subscript(row: Int, column: Int) -> T { - get { - assert(indexIsValid(row: row, column: column), "Index out of range") - return grid[(row * columns) + column] - } - set { - assert(indexIsValid(row: row, column: column), "Index out of range") - grid[(row * columns) + column] = newValue - } - } - - subscript(type: RowOrColumn, value: Int) -> [T] { - get { - switch type { - case .row: - assert(indexIsValid(row: value, column: 0), "Index out of range") - return Array(grid[(value * columns)..<(value * columns) + columns]) - case .column: - assert(indexIsValid(row: 0, column: value), "Index out of range") - var columns: [T] = [] - for row in 0.. Bool { - return row >= 0 && row < rows && column >= 0 && column < columns - } - - private func strassenR(by B: Matrix) -> Matrix { - let A = self - assert(A.isSquare && B.isSquare, "This function requires square matricies!") - guard A.rows > 1 && B.rows > 1 else { return A * B } - - let n = A.rows - let nBy2 = n / 2 - - var a11 = Matrix(size: nBy2) - var a12 = Matrix(size: nBy2) - var a21 = Matrix(size: nBy2) - var a22 = Matrix(size: nBy2) - var b11 = Matrix(size: nBy2) - var b12 = Matrix(size: nBy2) - var b21 = Matrix(size: nBy2) - var b22 = Matrix(size: nBy2) - - for i in 0.. Int { - return Int(pow(2, ceil(log2(Double(n))))) - } - - // MARK: - Functions - - func strassenMatrixMultiply(by B: Matrix) -> Matrix { - let A = self - assert(A.columns == B.rows, "Two matricies can only be matrix mulitiplied if one has dimensions mxn & the other has dimensions nxp where m, n, p are in R") - - let n = max(A.rows, A.columns, B.rows, B.columns) - let m = nextPowerOfTwo(of: n) - - var APrep = Matrix(size: m) - var BPrep = Matrix(size: m) - - A.size.forEach { (i, j) in - APrep[i,j] = A[i,j] - } - - B.size.forEach { (i, j) in - BPrep[i,j] = B[i,j] - } - - let CPrep = APrep.strassenR(by: BPrep) - var C = Matrix(rows: A.rows, columns: B.columns) - - for i in 0..) -> Matrix { - let A = self - assert(A.columns == B.rows, "Two matricies can only be matrix mulitiplied if one has dimensions mxn & the other has dimensions nxp where m, n, p are in R") - - var C = Matrix(rows: A.rows, columns: B.columns) - - for i in 0..(lhs: Matrix, rhs: Matrix) -> Matrix { - assert(lhs.size == rhs.size, "To term-by-term multiply matricies they need to be the same size!") - let rows = lhs.rows - let columns = lhs.columns - - var newMatrix = Matrix(rows: rows, columns: columns) - for row in 0..(lhs: Matrix, rhs: Matrix) -> Matrix { - assert(lhs.size == rhs.size, "To term-by-term add matricies they need to be the same size!") - let rows = lhs.rows - let columns = lhs.columns - - var newMatrix = Matrix(rows: rows, columns: columns) - for row in 0..(lhs: Matrix, rhs: Matrix) -> Matrix { - assert(lhs.size == rhs.size, "To term-by-term subtract matricies they need to be the same size!") - let rows = lhs.rows - let columns = lhs.columns - - var newMatrix = Matrix(rows: rows, columns: columns) - for row in 0.. { +public struct Matrix { // MARK: - Variables @@ -29,20 +29,22 @@ struct Matrix { // MARK: - Init - init(rows: Int, columns: Int, initialValue: T = T.zero) { + public init(rows: Int, columns: Int, initialValue: T = T.zero) { self.rows = rows self.columns = columns self.grid = Array(repeating: initialValue, count: rows * columns) } - init(size: Int, initialValue: T = T.zero) { + public init(size: Int, initialValue: T = T.zero) { self.rows = size self.columns = size self.grid = Array(repeating: initialValue, count: rows * columns) } - - // MARK: - Subscript - +} + +// MARK: - Public Functions + +public extension Matrix { subscript(row: Int, column: Int) -> T { get { assert(indexIsValid(row: row, column: column), "Index out of range") @@ -88,13 +90,59 @@ struct Matrix { } } - // MARK: - Private Functions + func strassenMatrixMultiply(by B: Matrix) -> Matrix { + let A = self + assert(A.columns == B.rows, "Two matricies can only be matrix mulitiplied if one has dimensions mxn & the other has dimensions nxp where m, n, p are in R") + + let n = max(A.rows, A.columns, B.rows, B.columns) + let m = nextPowerOfTwo(of: n) + + var APrep = Matrix(size: m) + var BPrep = Matrix(size: m) + + A.size.forEach { (i, j) in + APrep[i,j] = A[i,j] + } + + B.size.forEach { (i, j) in + BPrep[i,j] = B[i,j] + } + + let CPrep = APrep.strassenR(by: BPrep) + var C = Matrix(rows: A.rows, columns: B.columns) + + for i in 0.. Bool { + func matrixMultiply(by B: Matrix) -> Matrix { + let A = self + assert(A.columns == B.rows, "Two matricies can only be matrix mulitiplied if one has dimensions mxn & the other has dimensions nxp where m, n, p are in R") + + var C = Matrix(rows: A.rows, columns: B.columns) + + for i in 0.. Bool { return row >= 0 && row < rows && column >= 0 && column < columns } - private func strassenR(by B: Matrix) -> Matrix { + func strassenR(by B: Matrix) -> Matrix { let A = self assert(A.isSquare && B.isSquare, "This function requires square matricies!") guard A.rows > 1 && B.rows > 1 else { return A * B } @@ -150,97 +198,56 @@ struct Matrix { return C } - private func nextPowerOfTwo(of n: Int) -> Int { + func nextPowerOfTwo(of n: Int) -> Int { return Int(pow(2, ceil(log2(Double(n))))) } - - // MARK: - Functions - - func strassenMatrixMultiply(by B: Matrix) -> Matrix { - let A = self - assert(A.columns == B.rows, "Two matricies can only be matrix mulitiplied if one has dimensions mxn & the other has dimensions nxp where m, n, p are in R") - - let n = max(A.rows, A.columns, B.rows, B.columns) - let m = nextPowerOfTwo(of: n) - - var APrep = Matrix(size: m) - var BPrep = Matrix(size: m) - - A.size.forEach { (i, j) in - APrep[i,j] = A[i,j] - } - - B.size.forEach { (i, j) in - BPrep[i,j] = B[i,j] - } - - let CPrep = APrep.strassenR(by: BPrep) - var C = Matrix(rows: A.rows, columns: B.columns) - - for i in 0..) -> Matrix { - let A = self - assert(A.columns == B.rows, "Two matricies can only be matrix mulitiplied if one has dimensions mxn & the other has dimensions nxp where m, n, p are in R") - - var C = Matrix(rows: A.rows, columns: B.columns) - - for i in 0..(lhs: Matrix, rhs: Matrix) -> Matrix { - assert(lhs.size == rhs.size, "To term-by-term multiply matricies they need to be the same size!") - let rows = lhs.rows - let columns = lhs.columns - - var newMatrix = Matrix(rows: rows, columns: columns) - for row in 0..(lhs: Matrix, rhs: Matrix) -> Matrix { + assert(lhs.size == rhs.size, "To term-by-term add matricies they need to be the same size!") + let rows = lhs.rows + let columns = lhs.columns + + var newMatrix = Matrix(rows: rows, columns: columns) + for row in 0..(lhs: Matrix, rhs: Matrix) -> Matrix { - assert(lhs.size == rhs.size, "To term-by-term add matricies they need to be the same size!") - let rows = lhs.rows - let columns = lhs.columns - var newMatrix = Matrix(rows: rows, columns: columns) - for row in 0..(lhs: Matrix, rhs: Matrix) -> Matrix { + assert(lhs.size == rhs.size, "To term-by-term subtract matricies they need to be the same size!") + let rows = lhs.rows + let columns = lhs.columns + + var newMatrix = Matrix(rows: rows, columns: columns) + for row in 0..(lhs: Matrix, rhs: Matrix) -> Matrix { - assert(lhs.size == rhs.size, "To term-by-term subtract matricies they need to be the same size!") - let rows = lhs.rows - let columns = lhs.columns - - var newMatrix = Matrix(rows: rows, columns: columns) - for row in 0..(lhs: Matrix, rhs: Matrix) -> Matrix { + assert(lhs.size == rhs.size, "To term-by-term multiply matricies they need to be the same size!") + let rows = lhs.rows + let columns = lhs.columns + + var newMatrix = Matrix(rows: rows, columns: columns) + for row in 0.. Void) rethrows { + for row in 0.. Bool { + return lhs.columns == rhs.columns && lhs.rows == rhs.rows + } +} diff --git a/Strassen Matrix Multiplication/Number.swift b/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/Number.swift similarity index 71% rename from Strassen Matrix Multiplication/Number.swift rename to Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/Number.swift index 34c6d5308..9f4c7f4ab 100644 --- a/Strassen Matrix Multiplication/Number.swift +++ b/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/Number.swift @@ -8,40 +8,39 @@ import Foundation -protocol Number: Multipliable, Addable { +public protocol Number: Multipliable, Addable { static var zero: Self { get } } -protocol Addable { +public protocol Addable { static func +(lhs: Self, rhs: Self) -> Self static func -(lhs: Self, rhs: Self) -> Self } -protocol Multipliable { +public protocol Multipliable { static func *(lhs: Self, rhs: Self) -> Self } extension Int: Number { - static var zero: Int { + public static var zero: Int { return 0 } } extension Double: Number { - static var zero: Double { + public static var zero: Double { return 0.0 } } extension Float: Number { - static var zero: Float { + public static var zero: Float { return 0.0 } } - extension Array where Element: Number { - func dot(_ b: Array) -> Element { + public func dot(_ b: Array) -> Element { let a = self assert(a.count == b.count, "Can only take the dot product of arrays of the same length!") let c = a.indices.map{ a[$0] * b[$0] } From c260a3438c5e7103654d3b576b528065089c6972 Mon Sep 17 00:00:00 2001 From: pbodsk Date: Fri, 13 Jan 2017 13:31:37 +0100 Subject: [PATCH 0776/1679] migrates Single-Source Shortest Paths to Swift 3 syntax --- .travis.yml | 2 +- .../SSSP.playground/Contents.swift | 2 +- .../SSSP.xcodeproj/project.pbxproj | 13 +++++++++++- .../xcshareddata/xcschemes/SSSP.xcscheme | 2 +- .../xcshareddata/xcschemes/SSSPTests.xcscheme | 2 +- .../SSSP/BellmanFord.swift | 20 +++++++++---------- .../SSSP/SSSP.swift | 2 +- .../SSSPTests/SSSPTests.swift | 20 +++++++++---------- 8 files changed, 37 insertions(+), 26 deletions(-) diff --git a/.travis.yml b/.travis.yml index 9d8c6e346..765f07786 100644 --- a/.travis.yml +++ b/.travis.yml @@ -39,7 +39,7 @@ script: - xcodebuild test -project ./Selection\ Sort/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Shell\ Sort/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Shortest\ Path\ \(Unweighted\)/Tests/Tests.xcodeproj -scheme Tests -# - xcodebuild test -project ./Single-Source\ Shortest\ Paths\ \(Weighted\)/SSSP.xcodeproj -scheme SSSPTests +- xcodebuild test -project ./Single-Source\ Shortest\ Paths\ \(Weighted\)/SSSP.xcodeproj -scheme SSSPTests - xcodebuild test -project ./Stack/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Topological\ Sort/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Treap/Treap/Treap.xcodeproj -scheme Tests diff --git a/Single-Source Shortest Paths (Weighted)/SSSP.playground/Contents.swift b/Single-Source Shortest Paths (Weighted)/SSSP.playground/Contents.swift index ece36a663..652b558b1 100644 --- a/Single-Source Shortest Paths (Weighted)/SSSP.playground/Contents.swift +++ b/Single-Source Shortest Paths (Weighted)/SSSP.playground/Contents.swift @@ -25,4 +25,4 @@ graph.addDirectedEdge(z, to: x, withWeight: 7) let result = BellmanFord.apply(graph, source: s)! -let path = result.path(z, inGraph: graph) +let path = result.path(to: z, inGraph: graph) diff --git a/Single-Source Shortest Paths (Weighted)/SSSP.xcodeproj/project.pbxproj b/Single-Source Shortest Paths (Weighted)/SSSP.xcodeproj/project.pbxproj index 55893acfd..0dd67f69c 100644 --- a/Single-Source Shortest Paths (Weighted)/SSSP.xcodeproj/project.pbxproj +++ b/Single-Source Shortest Paths (Weighted)/SSSP.xcodeproj/project.pbxproj @@ -184,14 +184,16 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0730; - LastUpgradeCheck = 0730; + LastUpgradeCheck = 0810; ORGANIZATIONNAME = "Swift Algorithm Club"; TargetAttributes = { 49BFA2921CDF86E100522D66 = { CreatedOnToolsVersion = 7.3; + LastSwiftMigration = 0810; }; 49BFA29C1CDF86E100522D66 = { CreatedOnToolsVersion = 7.3; + LastSwiftMigration = 0810; }; }; }; @@ -301,8 +303,10 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; @@ -349,8 +353,10 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; @@ -370,6 +376,7 @@ MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; @@ -392,6 +399,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -411,6 +419,7 @@ PRODUCT_BUNDLE_IDENTIFIER = "com.swift-algorithm-club.SSSP"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; + SWIFT_VERSION = 3.0; }; name = Release; }; @@ -422,6 +431,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.swift-algorithm-club.SSSPTests"; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -433,6 +443,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.swift-algorithm-club.SSSPTests"; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Release; }; diff --git a/Single-Source Shortest Paths (Weighted)/SSSP.xcodeproj/xcshareddata/xcschemes/SSSP.xcscheme b/Single-Source Shortest Paths (Weighted)/SSSP.xcodeproj/xcshareddata/xcschemes/SSSP.xcscheme index 9d28c18c4..469159bd8 100644 --- a/Single-Source Shortest Paths (Weighted)/SSSP.xcodeproj/xcshareddata/xcschemes/SSSP.xcscheme +++ b/Single-Source Shortest Paths (Weighted)/SSSP.xcodeproj/xcshareddata/xcschemes/SSSP.xcscheme @@ -1,6 +1,6 @@ { +public struct BellmanFord where T: Hashable { public typealias Q = T } @@ -30,12 +30,12 @@ extension BellmanFord: SSSPAlgorithm { - returns a `BellmanFordResult` struct which can be queried for shortest paths and their total weights, or `nil` if a negative weight cycle exists */ - public static func apply(graph: AbstractGraph, source: Vertex) -> BellmanFordResult? { + public static func apply(_ graph: AbstractGraph, source: Vertex) -> BellmanFordResult? { let vertices = graph.vertices let edges = graph.edges - var predecessors = Array(count: vertices.count, repeatedValue: nil) - var weights = Array(count: vertices.count, repeatedValue: Double.infinity) + var predecessors = Array(repeating: nil, count: vertices.count) + var weights = Array(repeating: Double.infinity, count: vertices.count) predecessors[source.index] = source.index weights[source.index] = 0 @@ -78,10 +78,10 @@ extension BellmanFord: SSSPAlgorithm { It conforms to the `SSSPResult` procotol which provides methods to retrieve distances and paths between given pairs of start and end nodes. */ -public struct BellmanFordResult { +public struct BellmanFordResult where T: Hashable { - private var predecessors: [Int?] - private var weights: [Double] + fileprivate var predecessors: [Int?] + fileprivate var weights: [Double] } @@ -112,7 +112,7 @@ extension BellmanFordResult: SSSPResult { return nil } - guard let path = recursePath(to, inGraph: graph, path: [to]) else { + guard let path = recursePath(to: to, inGraph: graph, path: [to]) else { return nil } @@ -126,7 +126,7 @@ extension BellmanFordResult: SSSPResult { - returns: the list of predecessors discovered so far, or `nil` if the next vertex has no predecessor */ - private func recursePath(to: Vertex, inGraph graph: AbstractGraph, path: [Vertex]) -> [Vertex]? { + fileprivate func recursePath(to: Vertex, inGraph graph: AbstractGraph, path: [Vertex]) -> [Vertex]? { guard let predecessorIdx = predecessors[to.index] else { return nil } @@ -136,7 +136,7 @@ extension BellmanFordResult: SSSPResult { return [ to ] } - guard let buildPath = recursePath(predecessor, inGraph: graph, path: path) else { + guard let buildPath = recursePath(to: predecessor, inGraph: graph, path: path) else { return nil } diff --git a/Single-Source Shortest Paths (Weighted)/SSSP/SSSP.swift b/Single-Source Shortest Paths (Weighted)/SSSP/SSSP.swift index 8e3afc40a..3066f6516 100644 --- a/Single-Source Shortest Paths (Weighted)/SSSP/SSSP.swift +++ b/Single-Source Shortest Paths (Weighted)/SSSP/SSSP.swift @@ -18,7 +18,7 @@ protocol SSSPAlgorithm { associatedtype Q: Equatable, Hashable associatedtype P: SSSPResult - static func apply(graph: AbstractGraph, source: Vertex) -> P? + static func apply(_ graph: AbstractGraph, source: Vertex) -> P? } diff --git a/Single-Source Shortest Paths (Weighted)/SSSPTests/SSSPTests.swift b/Single-Source Shortest Paths (Weighted)/SSSPTests/SSSPTests.swift index 1bb862b74..04584dfeb 100644 --- a/Single-Source Shortest Paths (Weighted)/SSSPTests/SSSPTests.swift +++ b/Single-Source Shortest Paths (Weighted)/SSSPTests/SSSPTests.swift @@ -40,11 +40,11 @@ class SSSPTests: XCTestCase { let result = BellmanFord.apply(graph, source: s)! let expectedPath = ["s", "y", "x", "t", "z"] - let computedPath = result.path(z, inGraph: graph)! + let computedPath = result.path(to: z, inGraph: graph)! XCTAssertEqual(expectedPath, computedPath, "expected path of \(expectedPath) but got \(computedPath)") let expectedWeight = -2.0 - let computedWeight = result.distance(z) + let computedWeight = result.distance(to: z) XCTAssertEqual(expectedWeight, computedWeight, "expected weight of \(expectedWeight) but got \(computedWeight)") } @@ -71,11 +71,11 @@ class SSSPTests: XCTestCase { let result = BellmanFord.apply(graph, source: a)! let expectedPath = ["a", "b", "c", "e", "d"] - let computedPath = result.path(d, inGraph: graph)! + let computedPath = result.path(to: d, inGraph: graph)! XCTAssertEqual(expectedPath, computedPath, "expected path of \(expectedPath) but got \(computedPath)") let expectedWeight = 7.0 - let computedWeight = result.distance(d) + let computedWeight = result.distance(to: d) XCTAssertEqual(expectedWeight, computedWeight, "expected weight of \(expectedWeight) but got \(computedWeight)") } @@ -104,12 +104,12 @@ class SSSPTests: XCTestCase { let result = BellmanFord.apply(graph, source: a)! - XCTAssertNil(result.path(b, inGraph: graph), "a path should not be defined from a ~> b") - XCTAssertNil(result.distance(b), "a path should not be defined from a ~> b") - XCTAssertNotNil(result.path(s, inGraph: graph), "a path should be defined from a ~> s") - XCTAssertNotNil(result.distance(s), "a path should be defined from a ~> s") - XCTAssertNotNil(result.path(t, inGraph: graph), "a path should be defined from a ~> t") - XCTAssertNotNil(result.distance(t), "a path should be defined from a ~> t") + XCTAssertNil(result.path(to: b, inGraph: graph), "a path should not be defined from a ~> b") + XCTAssertNil(result.distance(to: b), "a path should not be defined from a ~> b") + XCTAssertNotNil(result.path(to: s, inGraph: graph), "a path should be defined from a ~> s") + XCTAssertNotNil(result.distance(to: s), "a path should be defined from a ~> s") + XCTAssertNotNil(result.path(to: t, inGraph: graph), "a path should be defined from a ~> t") + XCTAssertNotNil(result.distance(to: t), "a path should be defined from a ~> t") } func testNegativeWeightCycle() { From 2e5a4a60471ba9d215bfe52975bd563524908637 Mon Sep 17 00:00:00 2001 From: Jacopo Mangiavacchi Date: Sat, 14 Jan 2017 12:50:59 +0000 Subject: [PATCH 0777/1679] Update README.md --- DiningPhilosophers/README.md | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/DiningPhilosophers/README.md b/DiningPhilosophers/README.md index 06302cf2a..5f5d5383d 100755 --- a/DiningPhilosophers/README.md +++ b/DiningPhilosophers/README.md @@ -1,13 +1,35 @@ # SwiftDiningPhilosophers Dining philosophers problem Algorithm implemented in Swift (concurrent algorithm design to illustrate synchronization issues and techniques for resolving them using GCD and Semaphore in Swift) -Written by Jacopo Mangiavacchi +Written for Swift Algorithm Club by Jacopo Mangiavacchi -# from https://en.wikipedia.org/wiki/Dining_philosophers_problem +# Introduction In computer science, the dining philosophers problem is an example problem often used in concurrent algorithm design to illustrate synchronization issues and techniques for resolving them. It was originally formulated in 1965 by Edsger Dijkstra as a student exam exercise, presented in terms of computers competing for access to tape drive peripherals. Soon after, Tony Hoare gave the problem its present formulation. This Swift implementation is based on the Chandy/Misra solution and it use GCD Dispatch and Semaphone on Swift cross platform + +# Problem statement + +Five silent philosophers sit at a round table with bowls of spaghetti. Forks are placed between each pair of adjacent philosophers. + +Each philosopher must alternately think and eat. However, a philosopher can only eat spaghetti when they have both left and right forks. Each fork can be held by only one philosopher and so a philosopher can use the fork only if it is not being used by another philosopher. After an individual philosopher finishes eating, they need to put down both forks so that the forks become available to others. A philosopher can take the fork on their right or the one on their left as they become available, but cannot start eating before getting both forks. + +Eating is not limited by the remaining amounts of spaghetti or stomach space; an infinite supply and an infinite demand are assumed. + +The problem is how to design a discipline of behavior (a concurrent algorithm) such that no philosopher will starve; i.e., each can forever continue to alternate between eating and thinking, assuming that no philosopher can know when others may want to eat or think. + +This is an illustration of an dinining table: + +![Dining Philosophers table](https://upload.wikimedia.org/wikipedia/commons/7/7b/An_illustration_of_the_dining_philosophers_problem.png) + + + +# See also + +Dining Philosophers on Wikipedia https://en.wikipedia.org/wiki/Dining_philosophers_problem + +Written for Swift Algorithm Club by Jacopo Mangiavacchi From 13d1827d697b030de86dcb042a2068b9f26f3f52 Mon Sep 17 00:00:00 2001 From: Jacopo Mangiavacchi Date: Sat, 14 Jan 2017 13:00:23 +0000 Subject: [PATCH 0778/1679] Update README.md --- DiningPhilosophers/README.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/DiningPhilosophers/README.md b/DiningPhilosophers/README.md index 5f5d5383d..22687d2fd 100755 --- a/DiningPhilosophers/README.md +++ b/DiningPhilosophers/README.md @@ -27,6 +27,27 @@ This is an illustration of an dinining table: ![Dining Philosophers table](https://upload.wikimedia.org/wikipedia/commons/7/7b/An_illustration_of_the_dining_philosophers_problem.png) +# Solution +There are different solutions for this classic algorithm and this Swift implementation is based on the on the Chandy/Misra solution that more generally allows for arbitrary agents to contend for an arbitrary number of resources in a completely distributed scenario with no needs for a central authority to control the locking and serialization of resources. + +However, it is very important to note here that this solution violates the requirement that "the philosophers do not speak to each other" (due to the request messages). + + +# Description +For every pair of philosophers contending for a resource, create a fork and give it to the philosopher with the lower ID (n for agent Pn). Each fork can either be dirty or clean. Initially, all forks are dirty. +When a philosopher wants to use a set of resources (i.e. eat), said philosopher must obtain the forks from their contending neighbors. For all such forks the philosopher does not have, they send a request message. +When a philosopher with a fork receives a request message, they keep the fork if it is clean, but give it up when it is dirty. If the philosopher sends the fork over, they clean the fork before doing so. +After a philosopher is done eating, all their forks become dirty. If another philosopher had previously requested one of the forks, the philosopher that has just finished eating cleans the fork and sends it. +This solution also allows for a large degree of concurrency, and will solve an arbitrarily large problem. + +It also solves the starvation problem. The clean / dirty labels act as a way of giving preference to the most "starved" processes, and a disadvantage to processes that have just "eaten". One could compare their solution to one where philosophers are not allowed to eat twice in a row without letting others use the forks in between. Chandy and Misra's solution is more flexible than that, but has an element tending in that direction. + +In their analysis they derive a system of preference levels from the distribution of the forks and their clean/dirty states. They show that this system may describe an acyclic graph, and if so, the operations in their protocol cannot turn that graph into a cyclic one. This guarantees that deadlock cannot occur. However, if the system is initialized to a perfectly symmetric state, like all philosophers holding their left side forks, then the graph is cyclic at the outset, and their solution cannot prevent a deadlock. Initializing the system so that philosophers with lower IDs have dirty forks ensures the graph is initially acyclic. + + +# Swift implementation + + # See also From 4daf0d07dedf6f638a494a535b69d63e17bdf53c Mon Sep 17 00:00:00 2001 From: Jacopo Mangiavacchi Date: Sat, 14 Jan 2017 13:01:02 +0000 Subject: [PATCH 0779/1679] Update README.md --- DiningPhilosophers/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DiningPhilosophers/README.md b/DiningPhilosophers/README.md index 22687d2fd..3ac5b1343 100755 --- a/DiningPhilosophers/README.md +++ b/DiningPhilosophers/README.md @@ -1,4 +1,4 @@ -# SwiftDiningPhilosophers +# Dining Philosophers Dining philosophers problem Algorithm implemented in Swift (concurrent algorithm design to illustrate synchronization issues and techniques for resolving them using GCD and Semaphore in Swift) Written for Swift Algorithm Club by Jacopo Mangiavacchi From 5b3f3c4570b17be37d4f19344e3755523a9bcd21 Mon Sep 17 00:00:00 2001 From: Jacopo Mangiavacchi Date: Sat, 14 Jan 2017 13:08:16 +0000 Subject: [PATCH 0780/1679] Update main.swift --- DiningPhilosophers/Sources/main.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/DiningPhilosophers/Sources/main.swift b/DiningPhilosophers/Sources/main.swift index dfde40773..deff344b9 100755 --- a/DiningPhilosophers/Sources/main.swift +++ b/DiningPhilosophers/Sources/main.swift @@ -12,7 +12,7 @@ import Dispatch let numberOfPhilosophers = 4 -class ForkPair { +struct ForkPair { static let forksSemaphore:[DispatchSemaphore] = Array(repeating: DispatchSemaphore(value: 1), count: numberOfPhilosophers) let leftFork: DispatchSemaphore @@ -44,7 +44,7 @@ class ForkPair { } -class Philosophers { +struct Philosophers { let forkPair: ForkPair let philosopherIndex: Int From dca7bf14870e3007247344415b9d00e7d5cd8471 Mon Sep 17 00:00:00 2001 From: Jacopo Mangiavacchi Date: Sat, 14 Jan 2017 13:23:28 +0000 Subject: [PATCH 0781/1679] Update README.md --- DiningPhilosophers/README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/DiningPhilosophers/README.md b/DiningPhilosophers/README.md index 3ac5b1343..29b5916e9 100755 --- a/DiningPhilosophers/README.md +++ b/DiningPhilosophers/README.md @@ -47,7 +47,13 @@ In their analysis they derive a system of preference levels from the distributio # Swift implementation +This Swift 3.0 implementation of the Chandy/Misra solution is based on GCD and Semaphore tecnique and it could be built on both macOS and Linux. +The code is based on a ForkPair struct used for holding an array of DispatchSemaphore and a Philosopher struct for associate a couple of forks to each Philosopher. + +The ForkPair DispatchSemaphore static array is used for waking the neighbour Philosophers any time a fork pair is put down on the table. + +A background DispatchQueue is then used to let any Philosopher run asyncrounosly on the background and a global DispatchSemaphore is simply used in order to keep the main thread on wait forever and let the Philosophers contienue forever in their alternate think and eat cycle. # See also From 671aa3b26f8ec5ea16c2bfdbc567c1f7a2f5819a Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Sat, 14 Jan 2017 14:57:45 -0800 Subject: [PATCH 0782/1679] Update README.markdown Added Dining Philosophers link. --- README.markdown | 1 + 1 file changed, 1 insertion(+) diff --git a/README.markdown b/README.markdown index e5c8f8dae..ad5f910b4 100644 --- a/README.markdown +++ b/README.markdown @@ -190,6 +190,7 @@ A lot of software developer interview questions consist of algorithmic puzzles. - [Fizz Buzz](Fizz Buzz/) - [Monty Hall Problem](Monty Hall Problem/) - [Finding Palindromes](Palindromes/) +- [Dining Philosophers](DiningPhilosophers/) ## Learn more! From 71d8a43149fe3b125ce21b4ae3f0ec8eeb50220c Mon Sep 17 00:00:00 2001 From: vincentngo Date: Sun, 15 Jan 2017 11:23:42 -0500 Subject: [PATCH 0783/1679] Update Target to Swift 3.0 --- .../SSSP.xcodeproj/project.pbxproj | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Single-Source Shortest Paths (Weighted)/SSSP.xcodeproj/project.pbxproj b/Single-Source Shortest Paths (Weighted)/SSSP.xcodeproj/project.pbxproj index 0dd67f69c..fb425a73e 100644 --- a/Single-Source Shortest Paths (Weighted)/SSSP.xcodeproj/project.pbxproj +++ b/Single-Source Shortest Paths (Weighted)/SSSP.xcodeproj/project.pbxproj @@ -334,6 +334,7 @@ ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 3.0; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; @@ -377,6 +378,7 @@ MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_VERSION = 3.0; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; From cf0d1b539b2bf628a76e37b33332bab02c9bcc1a Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Mon, 16 Jan 2017 10:59:20 -0800 Subject: [PATCH 0784/1679] Modified Z-Algorithm to conform to our style guide. --- Z-Algorithm/ZAlgorithm.swift | 116 +++++++------- .../ZetaAlgorithm.playground/Contents.swift | 150 +++++++++--------- Z-Algorithm/ZetaAlgorithm.swift | 56 +++---- 3 files changed, 161 insertions(+), 161 deletions(-) diff --git a/Z-Algorithm/ZAlgorithm.swift b/Z-Algorithm/ZAlgorithm.swift index c9d7de876..9bef69687 100644 --- a/Z-Algorithm/ZAlgorithm.swift +++ b/Z-Algorithm/ZAlgorithm.swift @@ -1,66 +1,66 @@ /* Z-Algorithm for pattern/string pre-processing - - The code is based on the book: - "Algorithms on String, Trees and Sequences: Computer Science and Computational Biology" - by Dan Gusfield - Cambridge University Press, 1997 -*/ + + The code is based on the book: + "Algorithms on String, Trees and Sequences: Computer Science and Computational Biology" + by Dan Gusfield + Cambridge University Press, 1997 + */ import Foundation func ZetaAlgorithm(ptrn: String) -> [Int]? { - - let pattern = Array(ptrn.characters) - let patternLength: Int = pattern.count - - guard patternLength > 0 else { - return nil - } - - var zeta: [Int] = [Int](repeating: 0, count: patternLength) - - var left: Int = 0 - var right: Int = 0 - var k_1: Int = 0 - var betaLength: Int = 0 - var textIndex: Int = 0 - var patternIndex: Int = 0 - - for k in 1 ..< patternLength { - if k > right { - patternIndex = 0 - - while k + patternIndex < patternLength && - pattern[k + patternIndex] == pattern[patternIndex] { - patternIndex = patternIndex + 1 - } - - zeta[k] = patternIndex - - if zeta[k] > 0 { - left = k - right = k + zeta[k] - 1 - } - } else { - k_1 = k - left + 1 - betaLength = right - k + 1 - - if zeta[k_1 - 1] < betaLength { - zeta[k] = zeta[k_1 - 1] - } else if zeta[k_1 - 1] >= betaLength { - textIndex = betaLength - patternIndex = right + 1 - - while patternIndex < patternLength && pattern[textIndex] == pattern[patternIndex] { - textIndex = textIndex + 1 - patternIndex = patternIndex + 1 - } - - zeta[k] = patternIndex - k - left = k - right = patternIndex - 1 - } + + let pattern = Array(ptrn.characters) + let patternLength = pattern.count + + guard patternLength > 0 else { + return nil + } + + var zeta = [Int](repeating: 0, count: patternLength) + + var left = 0 + var right = 0 + var k_1 = 0 + var betaLength = 0 + var textIndex = 0 + var patternIndex = 0 + + for k in 1 ..< patternLength { + if k > right { + patternIndex = 0 + + while k + patternIndex < patternLength && + pattern[k + patternIndex] == pattern[patternIndex] { + patternIndex = patternIndex + 1 + } + + zeta[k] = patternIndex + + if zeta[k] > 0 { + left = k + right = k + zeta[k] - 1 + } + } else { + k_1 = k - left + 1 + betaLength = right - k + 1 + + if zeta[k_1 - 1] < betaLength { + zeta[k] = zeta[k_1 - 1] + } else if zeta[k_1 - 1] >= betaLength { + textIndex = betaLength + patternIndex = right + 1 + + while patternIndex < patternLength && pattern[textIndex] == pattern[patternIndex] { + textIndex = textIndex + 1 + patternIndex = patternIndex + 1 } + + zeta[k] = patternIndex - k + left = k + right = patternIndex - 1 + } } - return zeta + } + return zeta } diff --git a/Z-Algorithm/ZetaAlgorithm.playground/Contents.swift b/Z-Algorithm/ZetaAlgorithm.playground/Contents.swift index c9d942149..395122af0 100644 --- a/Z-Algorithm/ZetaAlgorithm.playground/Contents.swift +++ b/Z-Algorithm/ZetaAlgorithm.playground/Contents.swift @@ -2,88 +2,88 @@ func ZetaAlgorithm(ptrn: String) -> [Int]? { - - let pattern = Array(ptrn.characters) - let patternLength: Int = pattern.count - - guard patternLength > 0 else { - return nil - } - - var zeta: [Int] = [Int](repeating: 0, count: patternLength) - - var left: Int = 0 - var right: Int = 0 - var k_1: Int = 0 - var betaLength: Int = 0 - var textIndex: Int = 0 - var patternIndex: Int = 0 - - for k in 1 ..< patternLength { - if k > right { - patternIndex = 0 - - while k + patternIndex < patternLength && - pattern[k + patternIndex] == pattern[patternIndex] { - patternIndex = patternIndex + 1 - } - - zeta[k] = patternIndex - - if zeta[k] > 0 { - left = k - right = k + zeta[k] - 1 - } - } else { - k_1 = k - left + 1 - betaLength = right - k + 1 - - if zeta[k_1 - 1] < betaLength { - zeta[k] = zeta[k_1 - 1] - } else if zeta[k_1 - 1] >= betaLength { - textIndex = betaLength - patternIndex = right + 1 - - while patternIndex < patternLength && pattern[textIndex] == pattern[patternIndex] { - textIndex = textIndex + 1 - patternIndex = patternIndex + 1 - } - - zeta[k] = patternIndex - k - left = k - right = patternIndex - 1 - } + + let pattern = Array(ptrn.characters) + let patternLength = pattern.count + + guard patternLength > 0 else { + return nil + } + + var zeta = [Int](repeating: 0, count: patternLength) + + var left = 0 + var right = 0 + var k_1 = 0 + var betaLength = 0 + var textIndex = 0 + var patternIndex = 0 + + for k in 1 ..< patternLength { + if k > right { + patternIndex = 0 + + while k + patternIndex < patternLength && + pattern[k + patternIndex] == pattern[patternIndex] { + patternIndex = patternIndex + 1 + } + + zeta[k] = patternIndex + + if zeta[k] > 0 { + left = k + right = k + zeta[k] - 1 + } + } else { + k_1 = k - left + 1 + betaLength = right - k + 1 + + if zeta[k_1 - 1] < betaLength { + zeta[k] = zeta[k_1 - 1] + } else if zeta[k_1 - 1] >= betaLength { + textIndex = betaLength + patternIndex = right + 1 + + while patternIndex < patternLength && pattern[textIndex] == pattern[patternIndex] { + textIndex = textIndex + 1 + patternIndex = patternIndex + 1 } + + zeta[k] = patternIndex - k + left = k + right = patternIndex - 1 + } } - return zeta + } + return zeta } extension String { - - func indexesOf(pattern: String) -> [Int]? { - let patternLength: Int = pattern.characters.count - let zeta = ZetaAlgorithm(ptrn: pattern + "💲" + self) - - guard zeta != nil else { - return nil - } - - var indexes: [Int] = [Int]() - - /* Scan the zeta array to find matched patterns */ - for i in 0 ..< zeta!.count { - if zeta![i] == patternLength { - indexes.append(i - patternLength - 1) - } - } - - guard !indexes.isEmpty else { - return nil - } - - return indexes + + func indexesOf(pattern: String) -> [Int]? { + let patternLength = pattern.characters.count + let zeta = ZetaAlgorithm(ptrn: pattern + "💲" + self) + + guard zeta != nil else { + return nil + } + + var indexes: [Int] = [] + + /* Scan the zeta array to find matched patterns */ + for i in 0 ..< zeta!.count { + if zeta![i] == patternLength { + indexes.append(i - patternLength - 1) + } + } + + guard !indexes.isEmpty else { + return nil } + + return indexes + } } /* Examples */ diff --git a/Z-Algorithm/ZetaAlgorithm.swift b/Z-Algorithm/ZetaAlgorithm.swift index 4d80aa665..c35703272 100644 --- a/Z-Algorithm/ZetaAlgorithm.swift +++ b/Z-Algorithm/ZetaAlgorithm.swift @@ -1,36 +1,36 @@ /* Z-Algorithm based algorithm for pattern/string matching - - The code is based on the book: - "Algorithms on String, Trees and Sequences: Computer Science and Computational Biology" - by Dan Gusfield - Cambridge University Press, 1997 -*/ + + The code is based on the book: + "Algorithms on String, Trees and Sequences: Computer Science and Computational Biology" + by Dan Gusfield + Cambridge University Press, 1997 + */ import Foundation extension String { + + func indexesOf(pattern: String) -> [Int]? { + let patternLength = pattern.characters.count + let zeta = ZetaAlgorithm(ptrn: pattern + "💲" + self) + + guard zeta != nil else { + return nil + } + + var indexes: [Int] = [Int]() - func indexesOf(pattern: String) -> [Int]? { - let patternLength: Int = pattern.characters.count - let zeta = ZetaAlgorithm(ptrn: pattern + "💲" + self) - - guard zeta != nil else { - return nil - } - - var indexes: [Int] = [Int]() - - /* Scan the zeta array to find matched patterns */ - for i in 0 ..< zeta!.count { - if zeta![i] == patternLength { - indexes.append(i - patternLength - 1) - } - } - - guard !indexes.isEmpty else { - return nil - } - - return indexes + /* Scan the zeta array to find matched patterns */ + for i in 0 ..< zeta!.count { + if zeta![i] == patternLength { + indexes.append(i - patternLength - 1) + } } + + guard !indexes.isEmpty else { + return nil + } + + return indexes + } } From e5fb825ffa5fb4604ac0dd40782c372b5a5aef20 Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Mon, 16 Jan 2017 11:01:46 -0800 Subject: [PATCH 0785/1679] Update README.markdown Added Z-algorithm link. --- README.markdown | 1 + 1 file changed, 1 insertion(+) diff --git a/README.markdown b/README.markdown index ad5f910b4..2d7522b1e 100644 --- a/README.markdown +++ b/README.markdown @@ -50,6 +50,7 @@ If you're new to algorithms and data structures, here are a few good ones to sta - [k-th Largest Element](Kth Largest Element/). Find the *k*-th largest element in an array, such as the median. - [Selection Sampling](Selection Sampling/). Randomly choose a bunch of items from a collection. - [Union-Find](Union-Find/). Keeps track of disjoint sets and lets you quickly merge them. +- [Z-Algorithm](Z-Algorithm/). Finds all instances of a pattern in a String, and returns the indexes of where the pattern starts within the String. ### String Search From 10abdbc8efa765f6b9700498e9a08ab8de0ffbe1 Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Mon, 16 Jan 2017 11:02:39 -0800 Subject: [PATCH 0786/1679] Update README.markdown Updated the Z-algorithm link to the String Search section. --- README.markdown | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.markdown b/README.markdown index 2d7522b1e..97b84057b 100644 --- a/README.markdown +++ b/README.markdown @@ -50,7 +50,7 @@ If you're new to algorithms and data structures, here are a few good ones to sta - [k-th Largest Element](Kth Largest Element/). Find the *k*-th largest element in an array, such as the median. - [Selection Sampling](Selection Sampling/). Randomly choose a bunch of items from a collection. - [Union-Find](Union-Find/). Keeps track of disjoint sets and lets you quickly merge them. -- [Z-Algorithm](Z-Algorithm/). Finds all instances of a pattern in a String, and returns the indexes of where the pattern starts within the String. + ### String Search @@ -59,6 +59,7 @@ If you're new to algorithms and data structures, here are a few good ones to sta - Knuth-Morris-Pratt - Rabin-Karp - [Longest Common Subsequence](Longest Common Subsequence/). Find the longest sequence of characters that appear in the same order in both strings. +- [Z-Algorithm](Z-Algorithm/). Finds all instances of a pattern in a String, and returns the indexes of where the pattern starts within the String. ### Sorting From ca35d57d14073ac99f6a74c5a2057f1ab7f28c60 Mon Sep 17 00:00:00 2001 From: Bo Qian Date: Wed, 18 Jan 2017 17:25:53 -0800 Subject: [PATCH 0787/1679] Simplify the insert method by removing the fileprivate method. Delete duplicated BinarySearchTree.swift, so that there is only one single file. --- .../Sources/BinarySearchTree.swift | 14 +- .../Solution 1/BinarySearchTree.swift | 377 ------------------ .../Tests/Tests.xcodeproj/project.pbxproj | 8 +- .../contents.xcworkspacedata | 3 - 4 files changed, 9 insertions(+), 393 deletions(-) delete mode 100644 Binary Search Tree/Solution 1/BinarySearchTree.swift diff --git a/Binary Search Tree/Solution 1/BinarySearchTree.playground/Sources/BinarySearchTree.swift b/Binary Search Tree/Solution 1/BinarySearchTree.playground/Sources/BinarySearchTree.swift index f4960380e..5edbfc48a 100644 --- a/Binary Search Tree/Solution 1/BinarySearchTree.playground/Sources/BinarySearchTree.swift +++ b/Binary Search Tree/Solution 1/BinarySearchTree.playground/Sources/BinarySearchTree.swift @@ -23,7 +23,7 @@ public class BinarySearchTree { precondition(array.count > 0) self.init(value: array.first!) for v in array.dropFirst() { - insert(value: v, parent: self) + insert(value: v) } } @@ -74,23 +74,19 @@ extension BinarySearchTree { Performance: runs in O(h) time, where h is the height of the tree. */ public func insert(value: T) { - insert(value: value, parent: self) - } - - fileprivate func insert(value: T, parent: BinarySearchTree) { if value < self.value { if let left = left { - left.insert(value: value, parent: left) + left.insert(value: value) } else { left = BinarySearchTree(value: value) - left?.parent = parent + left?.parent = self } } else { if let right = right { - right.insert(value: value, parent: right) + right.insert(value: value) } else { right = BinarySearchTree(value: value) - right?.parent = parent + right?.parent = self } } } diff --git a/Binary Search Tree/Solution 1/BinarySearchTree.swift b/Binary Search Tree/Solution 1/BinarySearchTree.swift deleted file mode 100644 index a58ac075a..000000000 --- a/Binary Search Tree/Solution 1/BinarySearchTree.swift +++ /dev/null @@ -1,377 +0,0 @@ -/* - A binary search tree. - - Each node stores a value and two children. The left child contains a smaller - value; the right a larger (or equal) value. - - This tree allows duplicate elements. - - This tree does not automatically balance itself. To make sure it is balanced, - you should insert new values in randomized order, not in sorted order. -*/ -public class BinarySearchTree { - private(set) public var value: T - private(set) public var parent: BinarySearchTree? - private(set) public var left: BinarySearchTree? - private(set) public var right: BinarySearchTree? - - public init(value: T) { - self.value = value - } - - public convenience init(array: [T]) { - precondition(array.count > 0) - self.init(value: array.first!) - for v in array.dropFirst() { - insert(v, parent: self) - } - } - - public var isRoot: Bool { - return parent == nil - } - - public var isLeaf: Bool { - return left == nil && right == nil - } - - public var isLeftChild: Bool { - return parent?.left === self - } - - public var isRightChild: Bool { - return parent?.right === self - } - - public var hasLeftChild: Bool { - return left != nil - } - - public var hasRightChild: Bool { - return right != nil - } - - public var hasAnyChild: Bool { - return hasLeftChild || hasRightChild - } - - public var hasBothChildren: Bool { - return hasLeftChild && hasRightChild - } - - /* How many nodes are in this subtree. Performance: O(n). */ - public var count: Int { - return (left?.count ?? 0) + 1 + (right?.count ?? 0) - } -} - -// MARK: - Adding items - -extension BinarySearchTree { - /* - Inserts a new element into the tree. You should only insert elements - at the root, to make to sure this remains a valid binary tree! - Performance: runs in O(h) time, where h is the height of the tree. - */ - public func insert(value: T) { - insert(value, parent: self) - } - - private func insert(value: T, parent: BinarySearchTree) { - if value < self.value { - if let left = left { - left.insert(value, parent: left) - } else { - left = BinarySearchTree(value: value) - left?.parent = parent - } - } else { - if let right = right { - right.insert(value, parent: right) - } else { - right = BinarySearchTree(value: value) - right?.parent = parent - } - } - } -} - -// MARK: - Deleting items - -extension BinarySearchTree { - /* - Deletes a node from the tree. - - Returns the node that has replaced this removed one (or nil if this was a - leaf node). That is primarily useful for when you delete the root node, in - which case the tree gets a new root. - - Performance: runs in O(h) time, where h is the height of the tree. - */ - public func remove() -> BinarySearchTree? { - let replacement: BinarySearchTree? - - if let left = left { - if let right = right { - replacement = removeNodeWithTwoChildren(left, right) - } else { - // This node only has a left child. The left child replaces the node. - replacement = left - } - } else if let right = right { - // This node only has a right child. The right child replaces the node. - replacement = right - } else { - // This node has no children. We just disconnect it from its parent. - replacement = nil - } - - reconnectParentToNode(replacement) - - // The current node is no longer part of the tree, so clean it up. - parent = nil - left = nil - right = nil - - return replacement - } - - private func removeNodeWithTwoChildren(left: BinarySearchTree, _ right: BinarySearchTree) -> BinarySearchTree { - // This node has two children. It must be replaced by the smallest - // child that is larger than this node's value, which is the leftmost - // descendent of the right child. - let successor = right.minimum() - - // If this in-order successor has a right child of its own (it cannot - // have a left child by definition), then that must take its place. - successor.remove() - - // Connect our left child with the new node. - successor.left = left - left.parent = successor - - // Connect our right child with the new node. If the right child does - // not have any left children of its own, then the in-order successor - // *is* the right child. - if right !== successor { - successor.right = right - right.parent = successor - } else { - successor.right = nil - } - - // And finally, connect the successor node to our parent. - return successor - } - - private func reconnectParentToNode(node: BinarySearchTree?) { - if let parent = parent { - if isLeftChild { - parent.left = node - } else { - parent.right = node - } - } - node?.parent = parent - } -} - -// MARK: - Searching - -extension BinarySearchTree { - /* - Finds the "highest" node with the specified value. - Performance: runs in O(h) time, where h is the height of the tree. - */ - public func search(value: T) -> BinarySearchTree? { - var node: BinarySearchTree? = self - while case let n? = node { - if value < n.value { - node = n.left - } else if value > n.value { - node = n.right - } else { - return node - } - } - return nil - } - - /* - // Recursive version of search - public func search(value: T) -> BinarySearchTree? { - if value < self.value { - return left?.search(value) - } else if value > self.value { - return right?.search(value) - } else { - return self // found it! - } - } - */ - - public func contains(value: T) -> Bool { - return search(value) != nil - } - - /* - Returns the leftmost descendent. O(h) time. - */ - public func minimum() -> BinarySearchTree { - var node = self - while case let next? = node.left { - node = next - } - return node - } - - /* - Returns the rightmost descendent. O(h) time. - */ - public func maximum() -> BinarySearchTree { - var node = self - while case let next? = node.right { - node = next - } - return node - } - - /* - Calculates the depth of this node, i.e. the distance to the root. - Takes O(h) time. - */ - public func depth() -> Int { - var node = self - var edges = 0 - while case let parent? = node.parent { - node = parent - edges += 1 - } - return edges - } - - /* - Calculates the height of this node, i.e. the distance to the lowest leaf. - Since this looks at all children of this node, performance is O(n). - */ - public func height() -> Int { - if isLeaf { - return 0 - } else { - return 1 + max(left?.height() ?? 0, right?.height() ?? 0) - } - } - - /* - Finds the node whose value precedes our value in sorted order. - */ - public func predecessor() -> BinarySearchTree? { - if let left = left { - return left.maximum() - } else { - var node = self - while case let parent? = node.parent { - if parent.value < value { return parent } - node = parent - } - return nil - } - } - - /* - Finds the node whose value succeeds our value in sorted order. - */ - public func successor() -> BinarySearchTree? { - if let right = right { - return right.minimum() - } else { - var node = self - while case let parent? = node.parent { - if parent.value > value { return parent } - node = parent - } - return nil - } - } -} - -// MARK: - Traversal - -extension BinarySearchTree { - public func traverseInOrder(@noescape process: T -> Void) { - left?.traverseInOrder(process) - process(value) - right?.traverseInOrder(process) - } - - public func traversePreOrder(@noescape process: T -> Void) { - process(value) - left?.traversePreOrder(process) - right?.traversePreOrder(process) - } - - public func traversePostOrder(@noescape process: T -> Void) { - left?.traversePostOrder(process) - right?.traversePostOrder(process) - process(value) - } - - /* - Performs an in-order traversal and collects the results in an array. - */ - public func map(@noescape formula: T -> T) -> [T] { - var a = [T]() - if let left = left { a += left.map(formula) } - a.append(formula(value)) - if let right = right { a += right.map(formula) } - return a - } -} - -/* - Is this binary tree a valid binary search tree? -*/ -extension BinarySearchTree { - public func isBST(minValue minValue: T, maxValue: T) -> Bool { - if value < minValue || value > maxValue { return false } - let leftBST = left?.isBST(minValue: minValue, maxValue: value) ?? true - let rightBST = right?.isBST(minValue: value, maxValue: maxValue) ?? true - return leftBST && rightBST - } -} - -// MARK: - Debugging - -extension BinarySearchTree: CustomStringConvertible { - public var description: String { - var s = "" - if let left = left { - s += "(\(left.description)) <- " - } - s += "\(value)" - if let right = right { - s += " -> (\(right.description))" - } - return s - } -} - -extension BinarySearchTree: CustomDebugStringConvertible { - public var debugDescription: String { - var s = "value: \(value)" - if let parent = parent { - s += ", parent: \(parent.value)" - } - if let left = left { - s += ", left = [" + left.debugDescription + "]" - } - if let right = right { - s += ", right = [" + right.debugDescription + "]" - } - return s - } - - public func toArray() -> [T] { - return map { $0 } - } -} diff --git a/Binary Search Tree/Solution 1/Tests/Tests.xcodeproj/project.pbxproj b/Binary Search Tree/Solution 1/Tests/Tests.xcodeproj/project.pbxproj index c1d6c8029..7ecfe593f 100644 --- a/Binary Search Tree/Solution 1/Tests/Tests.xcodeproj/project.pbxproj +++ b/Binary Search Tree/Solution 1/Tests/Tests.xcodeproj/project.pbxproj @@ -7,15 +7,15 @@ objects = { /* Begin PBXBuildFile section */ - 7B80C3D81C77A313003CECC7 /* BinarySearchTree.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C3D71C77A313003CECC7 /* BinarySearchTree.swift */; }; 7B80C3DA1C77A323003CECC7 /* BinarySearchTreeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C3D91C77A323003CECC7 /* BinarySearchTreeTests.swift */; }; + 9E5A58B91E304C3100DAB3BB /* BinarySearchTree.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E5A58B81E304C3100DAB3BB /* BinarySearchTree.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ 7B2BBC801C779D720067B71D /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 7B2BBC941C779E7B0067B71D /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; - 7B80C3D71C77A313003CECC7 /* BinarySearchTree.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BinarySearchTree.swift; path = ../BinarySearchTree.swift; sourceTree = SOURCE_ROOT; }; 7B80C3D91C77A323003CECC7 /* BinarySearchTreeTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BinarySearchTreeTests.swift; sourceTree = SOURCE_ROOT; }; + 9E5A58B81E304C3100DAB3BB /* BinarySearchTree.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BinarySearchTree.swift; path = ../BinarySearchTree.playground/Sources/BinarySearchTree.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -48,7 +48,7 @@ 7B2BBC831C779D720067B71D /* Tests */ = { isa = PBXGroup; children = ( - 7B80C3D71C77A313003CECC7 /* BinarySearchTree.swift */, + 9E5A58B81E304C3100DAB3BB /* BinarySearchTree.swift */, 7B80C3D91C77A323003CECC7 /* BinarySearchTreeTests.swift */, 7B2BBC941C779E7B0067B71D /* Info.plist */, ); @@ -125,7 +125,7 @@ buildActionMask = 2147483647; files = ( 7B80C3DA1C77A323003CECC7 /* BinarySearchTreeTests.swift in Sources */, - 7B80C3D81C77A313003CECC7 /* BinarySearchTree.swift in Sources */, + 9E5A58B91E304C3100DAB3BB /* BinarySearchTree.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/swift-algorithm-club.xcworkspace/contents.xcworkspacedata b/swift-algorithm-club.xcworkspace/contents.xcworkspacedata index 4231528aa..b2ffce836 100644 --- a/swift-algorithm-club.xcworkspace/contents.xcworkspacedata +++ b/swift-algorithm-club.xcworkspace/contents.xcworkspacedata @@ -310,9 +310,6 @@ - - From 942e3b1738d95645e4dc49c483d84e9e094b1ea5 Mon Sep 17 00:00:00 2001 From: Bo Qian Date: Thu, 19 Jan 2017 18:33:43 -0800 Subject: [PATCH 0788/1679] Simplified the remove(). I feel the new implementation is more elegant and conceptually more straightforward. --- .../Sources/BinarySearchTree.swift | 97 +++++++------------ 1 file changed, 34 insertions(+), 63 deletions(-) diff --git a/Binary Search Tree/Solution 1/BinarySearchTree.playground/Sources/BinarySearchTree.swift b/Binary Search Tree/Solution 1/BinarySearchTree.playground/Sources/BinarySearchTree.swift index 5edbfc48a..31ae99a2f 100644 --- a/Binary Search Tree/Solution 1/BinarySearchTree.playground/Sources/BinarySearchTree.swift +++ b/Binary Search Tree/Solution 1/BinarySearchTree.playground/Sources/BinarySearchTree.swift @@ -106,58 +106,30 @@ extension BinarySearchTree { */ @discardableResult public func remove() -> BinarySearchTree? { let replacement: BinarySearchTree? - + + // Replacement for current node can be either biggest one on the left or + // smallest one on the right, whichever is not nil if let left = left { - if let right = right { - replacement = removeNodeWithTwoChildren(left, right) - } else { - // This node only has a left child. The left child replaces the node. - replacement = left - } + replacement = left.maximum() } else if let right = right { - // This node only has a right child. The right child replaces the node. - replacement = right + replacement = right.minimum() } else { - // This node has no children. We just disconnect it from its parent. - replacement = nil + replacement = nil; } - - reconnectParentTo(node: replacement) - + + replacement?.remove(); + + // Place the replacement on current node's position + replacement?.right = right; + replacement?.left = left; + reconnectParentTo(node:replacement); + // The current node is no longer part of the tree, so clean it up. parent = nil left = nil right = nil - - return replacement - } - - private func removeNodeWithTwoChildren(_ left: BinarySearchTree, _ right: BinarySearchTree) -> BinarySearchTree { - // This node has two children. It must be replaced by the smallest - // child that is larger than this node's value, which is the leftmost - // descendent of the right child. - let successor = right.minimum() - - // If this in-order successor has a right child of its own (it cannot - // have a left child by definition), then that must take its place. - successor.remove() - - // Connect our left child with the new node. - successor.left = left - left.parent = successor - - // Connect our right child with the new node. If the right child does - // not have any left children of its own, then the in-order successor - // *is* the right child. - if right !== successor { - successor.right = right - right.parent = successor - } else { - successor.right = nil - } - - // And finally, connect the successor node to our parent. - return successor + + return replacement; } private func reconnectParentTo(node: BinarySearchTree?) { @@ -350,24 +322,23 @@ extension BinarySearchTree: CustomStringConvertible { } return s } -} - -extension BinarySearchTree: CustomDebugStringConvertible { - public var debugDescription: String { - var s = "value: \(value)" - if let parent = parent { - s += ", parent: \(parent.value)" - } - if let left = left { - s += ", left = [" + left.debugDescription + "]" - } - if let right = right { - s += ", right = [" + right.debugDescription + "]" - } - return s - } + + public func toArray() -> [T] { + return map { $0 } + } - public func toArray() -> [T] { - return map { $0 } - } } + +//extension BinarySearchTree: CustomDebugStringConvertible { +// public var debugDescription: String { +// var s = "" +// if let left = left { +// s += "(\(left.description)) <- " +// } +// s += "\(value)" +// if let right = right { +// s += " -> (\(right.description))" +// } +// return s +// } +//} From c3ea705cb7623f9d6a9df3babcfcb01c61abcf4e Mon Sep 17 00:00:00 2001 From: Ray Wenderlich Date: Wed, 25 Jan 2017 11:46:55 -0500 Subject: [PATCH 0789/1679] Added license clarification. --- How to Contribute.markdown | 2 +- README.markdown | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/How to Contribute.markdown b/How to Contribute.markdown index 9e83b5ed6..258357e8b 100644 --- a/How to Contribute.markdown +++ b/How to Contribute.markdown @@ -21,7 +21,7 @@ To keep this a high quality repo, please follow this process when submitting you 1. Create a pull request to "claim" an algorithm or data structure. Just so multiple people don't work on the same thing. 2. Use this [style guide](https://github.com/raywenderlich/swift-style-guide) for writing code (more or less). 3. Write an explanation of how the algorithm works. Include **plenty of examples** for readers to follow along. Pictures are good. Take a look at [the explanation of quicksort](Quicksort/) to get an idea. -4. Include your name in the explanation, something like *Written by Your Name* at the end of the document. If you wrote it, you deserve the credit and fame. +4. Include your name in the explanation, something like *Written by Your Name* at the end of the document. 5. Add a playground and/or unit tests. 6. Run [SwiftLint](https://github.com/realm/SwiftLint) - [Install](https://github.com/realm/SwiftLint#installation) diff --git a/README.markdown b/README.markdown index c6d2e0149..b33a8f8ae 100644 --- a/README.markdown +++ b/README.markdown @@ -233,4 +233,6 @@ The Swift Algorithm Club is a collaborative effort from the [most algorithmic me All content is licensed under the terms of the MIT open source license. +By posting here, or by submitting any pull request through this forum, you agree that all content you submit or create, both code and text, is subject to this license. Razeware, LLC, and others will have all the rights described in the license regarding this content. The precise terms of this license may be found [here](https://github.com/raywenderlich/swift-algorithm-club/blob/master/LICENSE.txt). + [![Build Status](https://travis-ci.org/raywenderlich/swift-algorithm-club.svg?branch=master)](https://travis-ci.org/raywenderlich/swift-algorithm-club) From 40f667cfbb57e51ed5f639c9bfff5bdcc45fa867 Mon Sep 17 00:00:00 2001 From: Ray Wenderlich Date: Wed, 25 Jan 2017 11:47:48 -0500 Subject: [PATCH 0790/1679] Added Vincent as maintainer. --- README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.markdown b/README.markdown index b33a8f8ae..e2d99e2bc 100644 --- a/README.markdown +++ b/README.markdown @@ -225,7 +225,7 @@ Other algorithm repositories: The Swift Algorithm Club was originally created by [Matthijs Hollemans](https://github.com/hollance). -It is now maintained by [Chris Pilcher](https://github.com/chris-pilcher) and [Kelvin Lau](https://github.com/kelvinlauKL). +It is now maintained by [Vincent Ngo](https://www.raywenderlich.com/u/jomoka) and [Kelvin Lau](https://github.com/kelvinlauKL). The Swift Algorithm Club is a collaborative effort from the [most algorithmic members](https://github.com/rwenderlich/swift-algorithm-club/graphs/contributors) of the [raywenderlich.com](https://www.raywenderlich.com) community. We're always looking for help - why not [join the club](How to Contribute.markdown)? :] From 1504e605537c2c2b881c8bdbdadac8eabc209bfd Mon Sep 17 00:00:00 2001 From: Jaap Date: Sat, 28 Jan 2017 01:10:46 +0100 Subject: [PATCH 0791/1679] migrated to swift 3 --- Run-Length Encoding/README.markdown | 121 ++++---- .../RLE.playground/Contents.swift | 162 ++++++----- .../RLE.playground/Sources/RLE.swift | 68 +++++ Run-Length Encoding/RLE.swift | 70 ----- Run-Length Encoding/Tests/Info.plist | 24 -- Run-Length Encoding/Tests/RLETests.swift | 110 -------- .../Tests/Tests.xcodeproj/project.pbxproj | 261 ------------------ .../contents.xcworkspacedata | 7 - .../xcshareddata/xcschemes/Tests.xcscheme | 90 ------ 9 files changed, 228 insertions(+), 685 deletions(-) create mode 100644 Run-Length Encoding/RLE.playground/Sources/RLE.swift delete mode 100644 Run-Length Encoding/RLE.swift delete mode 100644 Run-Length Encoding/Tests/Info.plist delete mode 100644 Run-Length Encoding/Tests/RLETests.swift delete mode 100644 Run-Length Encoding/Tests/Tests.xcodeproj/project.pbxproj delete mode 100644 Run-Length Encoding/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata delete mode 100644 Run-Length Encoding/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme diff --git a/Run-Length Encoding/README.markdown b/Run-Length Encoding/README.markdown index 8371b1227..f7d196161 100644 --- a/Run-Length Encoding/README.markdown +++ b/Run-Length Encoding/README.markdown @@ -3,14 +3,14 @@ RLE is probably the simplest way to do compression. Let's say you have data that looks like this: aaaaabbbcdeeeeeeef... - + then RLE encodes it as follows: 5a3b1c1d7e1f... Instead of repeating bytes, you first write how often that byte occurs and then the byte's actual value. So `5a` means `aaaaa`. If the data has a lot of "byte runs", that is lots of repeating bytes, then RLE can save quite a bit of space. It works quite well on images. -There are many different ways you can implement RLE. Here's an extension of `NSData` that does a version of RLE inspired by the old [PCX image file format](https://en.wikipedia.org/wiki/PCX). +There are many different ways you can implement RLE. Here's an extension of `Data` that does a version of RLE inspired by the old [PCX image file format](https://en.wikipedia.org/wiki/PCX). The rules are these: @@ -20,44 +20,42 @@ The rules are these: - A single byte in the range 192 - 255 is represented by two bytes: first the byte 192 (meaning a run of 1 byte), followed by the actual value. -Here is the compression code. It returns a new `NSData` object containing the run-length encoded bytes: +Here is the compression code. It returns a new `Data` object containing the run-length encoded bytes: ```swift -extension NSData { - public func compressRLE() -> NSData { - let data = NSMutableData() - if length > 0 { - var ptr = UnsafePointer(bytes) - let end = ptr + length - - while ptr < end { // 1 - var count = 0 - var byte = ptr.memory - var next = byte - - while next == byte && ptr < end && count < 64 { // 2 - ptr = ptr.advancedBy(1) - next = ptr.memory - count += 1 - } - - if count > 1 || byte >= 192 { // 3 - var size = 191 + UInt8(count) - data.appendBytes(&size, length: 1) - data.appendBytes(&byte, length: 1) - } else { // 4 - data.appendBytes(&byte, length: 1) +extension Data { + public func compressRLE() -> Data { + var data = Data() + self.withUnsafeBytes { (uPtr: UnsafePointer) in + var ptr = uPtr + let end = ptr + count + while ptr < end { //1 + var count = 0 + var byte = ptr.pointee + var next = byte + + while next == byte && ptr < end && count < 64 { //2 + ptr = ptr.advanced(by: 1) + next = ptr.pointee + count += 1 + } + + if count > 1 || byte >= 192 { // 3 + var size = 191 + UInt8(count) + data.append(&size, count: 1) + data.append(&byte, count: 1) + } else { // 4 + data.append(&byte, count: 1) + } + } } - } + return data } - return data - } -} ``` How it works: -1. We use an `UnsafePointer` to step through the bytes of the original `NSData` object. +1. We use an `UnsafePointer` to step through the bytes of the original `Data` object. 2. At this point we've read the current byte value into the `byte` variable. If the next byte is the same, then we keep reading until we find a byte value that is different, or we reach the end of the data. We also stop if the run is 64 bytes because that's the maximum we can encode. @@ -69,11 +67,11 @@ You can test it like this in a playground: ```swift let originalString = "aaaaabbbcdeeeeeeef" -let utf8 = originalString.dataUsingEncoding(NSUTF8StringEncoding)! +let utf8 = originalString.data(using: String.Encoding.utf8)! let compressed = utf8.compressRLE() ``` -The compressed `NSData` object should be ``. Let's decode that by hand to see what has happened: +The compressed `Data` object should be ``. Let's decode that by hand to see what has happened: c4 This is 196 in decimal. It means the next byte appears 5 times. 61 The data byte "a". @@ -90,34 +88,38 @@ So that's 9 bytes encoded versus 18 original. That's a savings of 50%. Of course Here is the decompression code: ```swift - public func decompressRLE() -> NSData { - let data = NSMutableData() - if length > 0 { - var ptr = UnsafePointer(bytes) - let end = ptr + length - - while ptr < end { - var byte = ptr.memory // 1 - ptr = ptr.advancedBy(1) - - if byte < 192 { // 2 - data.appendBytes(&byte, length: 1) - - } else if ptr < end { // 3 - var value = ptr.memory - ptr = ptr.advancedBy(1) - - for _ in 0 ..< byte - 191 { - data.appendBytes(&value, length: 1) - } +public func decompressRLE() -> Data { + var data = Data() + self.withUnsafeBytes { (uPtr: UnsafePointer) in + var ptr = uPtr + let end = ptr + count + + while ptr < end { + // Read the next byte. This is either a single value less than 192, + // or the start of a byte run. + var byte = ptr.pointee // 1 + ptr = ptr.advanced(by: 1) + + if byte < 192 { // 2 + data.append(&byte, count: 1) + } else if ptr < end { // 3 + // Read the actual data value. + var value = ptr.pointee + ptr = ptr.advanced(by: 1) + + // And write it out repeatedly. + for _ in 0 ..< byte - 191 { + data.append(&value, count: 1) + } + } + } } - } + return data } - return data - } + ``` -1. Again this uses an `UnsafePointer` to read the `NSData`. Here we read the next byte; this is either a single value less than 192, or the start of a byte run. +1. Again this uses an `UnsafePointer` to read the `Data`. Here we read the next byte; this is either a single value less than 192, or the start of a byte run. 2. If it's a single value, then it's just a matter of copying it to the output. @@ -134,6 +136,7 @@ And now `originalString == restoredString` must be true! Footnote: The original PCX implementation is slightly different. There, a byte value of 192 (0xC0) means that the following byte will be repeated 0 times. This also limits the maximum run size to 63 bytes. Because it makes no sense to store bytes that don't occur, in my implementation 192 means the next byte appears once, and the maximum run length is 64 bytes. -This was probably a trade-off when they designed the PCX format way back when. If you look at it in binary, the upper two bits indicate whether a byte is compressed. (If both bits are set then the byte value is 192 or more.) To get the run length you can simply do `byte & 0x3F`, giving you a value in the range 0 to 63. +This was probably a trade-off when they designed the PCX format way back when. If you look at it in binary, the upper two bits indicate whether a byte is compressed. (If both bits are set then the byte value is 192 or more.) To get the run length you can simply do `byte & 0x3F`, giving you a value in the range 0 to 63. *Written for Swift Algorithm Club by Matthijs Hollemans* +*Migrated to Swift3 by Jaap Wijnen* diff --git a/Run-Length Encoding/RLE.playground/Contents.swift b/Run-Length Encoding/RLE.playground/Contents.swift index 41dcae3b1..62b4ef437 100644 --- a/Run-Length Encoding/RLE.playground/Contents.swift +++ b/Run-Length Encoding/RLE.playground/Contents.swift @@ -2,81 +2,115 @@ import Foundation -extension NSData { - /* - Compresses the NSData using run-length encoding. - */ - public func compressRLE() -> NSData { - let data = NSMutableData() - if length > 0 { - var ptr = UnsafePointer(bytes) - let end = ptr + length +let originalString = "aaaaabbbcdeeeeeeef" +let utf8 = originalString.data(using: String.Encoding.utf8)! +let compressed = utf8.compressRLE() - while ptr < end { - var count = 0 - var byte = ptr.memory - var next = byte +let decompressed = compressed.decompressRLE() +let restoredString = String(data: decompressed, encoding: String.Encoding.utf8) +originalString == restoredString - // Is the next byte the same? Keep reading until we find a different - // value, or we reach the end of the data, or the run is 64 bytes. - while next == byte && ptr < end && count < 64 { - ptr = ptr.advancedBy(1) - next = ptr.memory - count += 1 - } +func encodeAndDecode(_ bytes: [UInt8]) -> Bool { + var bytes = bytes + + var data1 = Data(bytes: &bytes, count: bytes.count) + print("data1 is \(data1.count) bytes") + + var rleData = data1.compressRLE() + print("encoded data is \(rleData.count) bytes") + + var data2 = rleData.decompressRLE() + print("data2 is \(data2.count) bytes") + + return data1 == data2 +} - if count > 1 || byte >= 192 { // byte run of up to 64 repeats - var size = 191 + UInt8(count) - data.appendBytes(&size, length: 1) - data.appendBytes(&byte, length: 1) - } else { // single byte between 0 and 192 - data.appendBytes(&byte, length: 1) - } - } - } - return data - } +func testEmpty() -> Bool { + let bytes: [UInt8] = [] + return encodeAndDecode(bytes) +} - /* - Converts a run-length encoded NSData back to the original. - */ - public func decompressRLE() -> NSData { - let data = NSMutableData() - if length > 0 { - var ptr = UnsafePointer(bytes) - let end = ptr + length +func testOneByteWithLowValue() -> Bool { + let bytes: [UInt8] = [0x80] + return encodeAndDecode(bytes) +} - while ptr < end { - // Read the next byte. This is either a single value less than 192, - // or the start of a byte run. - var byte = ptr.memory - ptr = ptr.advancedBy(1) +func testOneByteWithHighValue() -> Bool { + let bytes: [UInt8] = [0xD0] + return encodeAndDecode(bytes) +} - if byte < 192 { // single value - data.appendBytes(&byte, length: 1) +func testSimpleCases() -> Bool { + let bytes: [UInt8] = [ + 0x00, + 0x20, 0x20, 0x20, 0x20, 0x20, + 0x30, + 0x00, 0x00, + 0xC0, + 0xC1, + 0xC0, 0xC0, 0xC0, + 0xFF, 0xFF, 0xFF, 0xFF + ] + return encodeAndDecode(bytes) +} - } else if ptr < end { // byte run - // Read the actual data value. - var value = ptr.memory - ptr = ptr.advancedBy(1) +func testBufferWithoutSpans() -> Bool { + // There is nothing that can be encoded in this buffer, so the encoded + // data ends up being longer. + var bytes: [UInt8] = [] + for i in 0..<1024 { + bytes.append(UInt8(i%256)) + } + return encodeAndDecode(bytes) +} - // And write it out repeatedly. - for _ in 0 ..< byte - 191 { - data.appendBytes(&value, length: 1) - } +func testBufferWithSpans(_ spanSize: Int) -> Bool { + print("span size \(spanSize)") + + let length = spanSize * 32 + var bytes: [UInt8] = Array(repeating: 0, count: length) + + for t in stride(from: 0, to: length, by: spanSize) { + for i in 0.. Bool { + let length = 1 + Int(arc4random_uniform(2048)) + var bytes: [UInt8] = [] + for _ in 0.. Bool { + var tests: [Bool] = [ + testEmpty(), + testOneByteWithLowValue(), + testOneByteWithHighValue(), + testSimpleCases(), + testBufferWithoutSpans(), + testBufferWithSpans(4), + testBufferWithSpans(63), + testBufferWithSpans(64), + testBufferWithSpans(65), + testBufferWithSpans(66), + testBufferWithSpans(80) + ] + for _ in 0..<10 { + let result = testRandomByte() + tests.append(result) + } + var result = true + for bool in tests { + result = result && bool + } + + return result +} -let originalString = "aaaaabbbcdeeeeeeef" -let utf8 = originalString.dataUsingEncoding(NSUTF8StringEncoding)! -let compressed = utf8.compressRLE() - -let decompressed = compressed.decompressRLE() -let restoredString = String(data: decompressed, encoding: NSUTF8StringEncoding) -originalString == restoredString +runTests() \ No newline at end of file diff --git a/Run-Length Encoding/RLE.playground/Sources/RLE.swift b/Run-Length Encoding/RLE.playground/Sources/RLE.swift new file mode 100644 index 000000000..5707e3d9d --- /dev/null +++ b/Run-Length Encoding/RLE.playground/Sources/RLE.swift @@ -0,0 +1,68 @@ +import Foundation + +extension Data { + /* + Compresses the NSData using run-length encoding. + */ + public func compressRLE() -> Data { + var data = Data() + self.withUnsafeBytes { (uPtr: UnsafePointer) in + var ptr = uPtr + let end = ptr + count + while ptr < end { + var count = 0 + var byte = ptr.pointee + var next = byte + + // Is the next byte the same? Keep reading until we find a different + // value, or we reach the end of the data, or the run is 64 bytes. + while next == byte && ptr < end && count < 64 { + ptr = ptr.advanced(by: 1) + next = ptr.pointee + count += 1 + } + + if count > 1 || byte >= 192 { // byte run of up to 64 repeats + var size = 191 + UInt8(count) + data.append(&size, count: 1) + data.append(&byte, count: 1) + } else { // single byte between 0 and 192 + data.append(&byte, count: 1) + } + } + } + return data + } + + /* + Converts a run-length encoded NSData back to the original. + */ + public func decompressRLE() -> Data { + var data = Data() + self.withUnsafeBytes { (uPtr: UnsafePointer) in + var ptr = uPtr + let end = ptr + count + + while ptr < end { + // Read the next byte. This is either a single value less than 192, + // or the start of a byte run. + var byte = ptr.pointee + ptr = ptr.advanced(by: 1) + + if byte < 192 { // single value + data.append(&byte, count: 1) + } else if ptr < end { // byte run + // Read the actual data value. + var value = ptr.pointee + ptr = ptr.advanced(by: 1) + + // And write it out repeatedly. + for _ in 0 ..< byte - 191 { + data.append(&value, count: 1) + } + } + } + } + return data + } +} diff --git a/Run-Length Encoding/RLE.swift b/Run-Length Encoding/RLE.swift deleted file mode 100644 index b62c59c63..000000000 --- a/Run-Length Encoding/RLE.swift +++ /dev/null @@ -1,70 +0,0 @@ -import Foundation - -extension NSData { - /* - Compresses the NSData using run-length encoding. - */ - public func compressRLE() -> NSData { - let data = NSMutableData() - if length > 0 { - var ptr = UnsafePointer(bytes) - let end = ptr + length - - while ptr < end { - var count = 0 - var byte = ptr.memory - var next = byte - - // Is the next byte the same? Keep reading until we find a different - // value, or we reach the end of the data, or the run is 64 bytes. - while next == byte && ptr < end && count < 64 { - ptr = ptr.advancedBy(1) - next = ptr.memory - count += 1 - } - - if count > 1 || byte >= 192 { // byte run of up to 64 repeats - var size = 191 + UInt8(count) - data.appendBytes(&size, length: 1) - data.appendBytes(&byte, length: 1) - } else { // single byte between 0 and 192 - data.appendBytes(&byte, length: 1) - } - } - } - return data - } - - /* - Converts a run-length encoded NSData back to the original. - */ - public func decompressRLE() -> NSData { - let data = NSMutableData() - if length > 0 { - var ptr = UnsafePointer(bytes) - let end = ptr + length - - while ptr < end { - // Read the next byte. This is either a single value less than 192, - // or the start of a byte run. - var byte = ptr.memory - ptr = ptr.advancedBy(1) - - if byte < 192 { // single value - data.appendBytes(&byte, length: 1) - - } else if ptr < end { // byte run - // Read the actual data value. - var value = ptr.memory - ptr = ptr.advancedBy(1) - - // And write it out repeatedly. - for _ in 0 ..< byte - 191 { - data.appendBytes(&value, length: 1) - } - } - } - } - return data - } -} diff --git a/Run-Length Encoding/Tests/Info.plist b/Run-Length Encoding/Tests/Info.plist deleted file mode 100644 index ba72822e8..000000000 --- a/Run-Length Encoding/Tests/Info.plist +++ /dev/null @@ -1,24 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - BNDL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - - diff --git a/Run-Length Encoding/Tests/RLETests.swift b/Run-Length Encoding/Tests/RLETests.swift deleted file mode 100644 index f4b2f8d7d..000000000 --- a/Run-Length Encoding/Tests/RLETests.swift +++ /dev/null @@ -1,110 +0,0 @@ -import XCTest - -class RLETests: XCTestCase { - private var showExtraOutput = false - - private func dumpData(data: NSData) { - if showExtraOutput { - var ptr = UnsafePointer(data.bytes) - for _ in 0.. - - - - diff --git a/Run-Length Encoding/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Run-Length Encoding/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme deleted file mode 100644 index 8ef8d8581..000000000 --- a/Run-Length Encoding/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme +++ /dev/null @@ -1,90 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From 2accb9907f434968e8806afe5637eeab69d4a0a9 Mon Sep 17 00:00:00 2001 From: Jaap Date: Sat, 28 Jan 2017 01:39:29 +0100 Subject: [PATCH 0792/1679] Migrate Shunting Yard to Swift 3 --- Shunting Yard/README.markdown | 5 +- .../ShuntingYard.playground/Contents.swift | 38 +- .../Sources/Stack.swift | 32 +- Shunting Yard/ShuntingYard.swift | 364 +++++++++--------- 4 files changed, 218 insertions(+), 221 deletions(-) diff --git a/Shunting Yard/README.markdown b/Shunting Yard/README.markdown index d2e568d39..72df4d346 100644 --- a/Shunting Yard/README.markdown +++ b/Shunting Yard/README.markdown @@ -6,7 +6,7 @@ Any mathematics we write is expressed in a notation known as *infix notation*. F The operator is placed in between the operands, hence the expression is said to be in *infix* form. If you think about it, any expression that you write on a piece of paper will always be in infix form. This is what we humans understand. -Multiplication has higher precedence than addition, so when the above expression is evaluated you would first multiply **B** and **C**, and then add the result to **A**. We humans can easily understand the precedence of operators, but a machine needs to be given instructions about each operator. +Multiplication has higher precedence than addition, so when the above expression is evaluated you would first multiply **B** and **C**, and then add the result to **A**. We humans can easily understand the precedence of operators, but a machine needs to be given instructions about each operator. To change the order of evaluation, we can use parentheses: @@ -108,4 +108,5 @@ We end up with the postfix expression: [Shunting yard algorithm on Wikipedia](https://en.wikipedia.org/wiki/Shunting-yard_algorithm) -*Written for the Swift Algorithm Club by [Ali Hafizji](http://www.github.com/aliHafizji)* \ No newline at end of file +*Written for the Swift Algorithm Club by [Ali Hafizji](http://www.github.com/aliHafizji)* +*Migrated to Swift 3 by Jaap Wijnen* diff --git a/Shunting Yard/ShuntingYard.playground/Contents.swift b/Shunting Yard/ShuntingYard.playground/Contents.swift index 707e2a0a3..b341c673b 100644 --- a/Shunting Yard/ShuntingYard.playground/Contents.swift +++ b/Shunting Yard/ShuntingYard.playground/Contents.swift @@ -15,17 +15,17 @@ public enum OperatorType: CustomStringConvertible { public var description: String { switch self { - case add: + case .add: return "+" - case subtract: + case .subtract: return "-" - case divide: + case .divide: return "/" - case multiply: + case .multiply: return "*" - case percent: + case .percent: return "%" - case exponent: + case .exponent: return "^" } } @@ -39,13 +39,13 @@ public enum TokenType: CustomStringConvertible { public var description: String { switch self { - case openBracket: + case .openBracket: return "(" - case closeBracket: + case .closeBracket: return ")" - case Operator(let operatorToken): + case .Operator(let operatorToken): return operatorToken.description - case operand(let value): + case .operand(let value): return "\(value)" } } @@ -141,23 +141,23 @@ public struct Token: CustomStringConvertible { public class InfixExpressionBuilder { private var expression = [Token]() - public func addOperator(operatorType: OperatorType) -> InfixExpressionBuilder { + public func addOperator(_ operatorType: OperatorType) -> InfixExpressionBuilder { expression.append(Token(operatorType: operatorType)) return self } - public func addOperand(operand: Double) -> InfixExpressionBuilder { + public func addOperand(_ operand: Double) -> InfixExpressionBuilder { expression.append(Token(operand: operand)) return self } public func addOpenBracket() -> InfixExpressionBuilder { - expression.append(Token(tokenType: .OpenBracket)) + expression.append(Token(tokenType: .openBracket)) return self } public func addCloseBracket() -> InfixExpressionBuilder { - expression.append(Token(tokenType: .CloseBracket)) + expression.append(Token(tokenType: .closeBracket)) return self } @@ -168,7 +168,7 @@ public class InfixExpressionBuilder { } // This returns the result of the shunting yard algorithm -public func reversePolishNotation(expression: [Token]) -> String { +public func reversePolishNotation(_ expression: [Token]) -> String { var tokenStack = Stack() var reversePolishNotation = [Token]() @@ -187,14 +187,14 @@ public func reversePolishNotation(expression: [Token]) -> String { } case .Operator(let operatorToken): - for tempToken in tokenStack.generate() { + for tempToken in tokenStack.makeIterator() { if !tempToken.isOperator { break } if let tempOperatorToken = tempToken.operatorToken { - if operatorToken.associativity == .LeftAssociative && operatorToken <= tempOperatorToken - || operatorToken.associativity == .RightAssociative && operatorToken < tempOperatorToken { + if operatorToken.associativity == .leftAssociative && operatorToken <= tempOperatorToken + || operatorToken.associativity == .rightAssociative && operatorToken < tempOperatorToken { reversePolishNotation.append(tokenStack.pop()!) } else { break @@ -209,7 +209,7 @@ public func reversePolishNotation(expression: [Token]) -> String { reversePolishNotation.append(tokenStack.pop()!) } - return reversePolishNotation.map({token in token.description}).joinWithSeparator(" ") + return reversePolishNotation.map({token in token.description}).joined(separator: " ") } diff --git a/Shunting Yard/ShuntingYard.playground/Sources/Stack.swift b/Shunting Yard/ShuntingYard.playground/Sources/Stack.swift index 0df342af5..a67bb9d64 100644 --- a/Shunting Yard/ShuntingYard.playground/Sources/Stack.swift +++ b/Shunting Yard/ShuntingYard.playground/Sources/Stack.swift @@ -1,41 +1,37 @@ import Foundation public struct Stack { - private var array = [T]() - + fileprivate var array = [T]() + public init() { - array = [] + } - + public var isEmpty: Bool { return array.isEmpty } - + public var count: Int { return array.count } - - public mutating func push(element: T) { + + public mutating func push(_ element: T) { array.append(element) } - + public mutating func pop() -> T? { - if isEmpty { - return nil - } else { - return array.removeLast() - } + return array.popLast() } - - public func peek() -> T? { + + public var top: T? { return array.last } } -extension Stack: SequenceType { - public func generate() -> AnyGenerator { +extension Stack: Sequence { + public func makeIterator() -> AnyIterator { var curr = self - return anyGenerator { + return AnyIterator { _ -> T? in return curr.pop() } diff --git a/Shunting Yard/ShuntingYard.swift b/Shunting Yard/ShuntingYard.swift index 9d31d5a58..b8f5f8e6b 100644 --- a/Shunting Yard/ShuntingYard.swift +++ b/Shunting Yard/ShuntingYard.swift @@ -7,213 +7,213 @@ // internal enum OperatorAssociativity { - case leftAssociative - case rightAssociative + case leftAssociative + case rightAssociative } public enum OperatorType: CustomStringConvertible { - case add - case subtract - case divide - case multiply - case percent - case exponent - - public var description: String { - switch self { - case add: - return "+" - case subtract: - return "-" - case divide: - return "/" - case multiply: - return "*" - case percent: - return "%" - case exponent: - return "^" - } - } + case add + case subtract + case divide + case multiply + case percent + case exponent + + public var description: String { + switch self { + case .add: + return "+" + case .subtract: + return "-" + case .divide: + return "/" + case .multiply: + return "*" + case .percent: + return "%" + case .exponent: + return "^" + } + } } public enum TokenType: CustomStringConvertible { - case openBracket - case closeBracket - case Operator(OperatorToken) - case operand(Double) - - public var description: String { - switch self { - case openBracket: - return "(" - case closeBracket: - return ")" - case Operator(let operatorToken): - return operatorToken.description - case operand(let value): - return "\(value)" - } - } + case openBracket + case closeBracket + case Operator(OperatorToken) + case operand(Double) + + public var description: String { + switch self { + case .openBracket: + return "(" + case .closeBracket: + return ")" + case .Operator(let operatorToken): + return operatorToken.description + case .operand(let value): + return "\(value)" + } + } } public struct OperatorToken: CustomStringConvertible { - let operatorType: OperatorType - - init(operatorType: OperatorType) { - self.operatorType = operatorType - } - - var precedence: Int { - switch operatorType { - case .add, .subtract: - return 0 - case .divide, .multiply, .percent: - return 5 - case .exponent: - return 10 - } - } - - var associativity: OperatorAssociativity { - switch operatorType { - case .add, .subtract, .divide, .multiply, .percent: - return .LeftAssociative - case .exponent: - return .RightAssociative - } - } - - public var description: String { - return operatorType.description - } + let operatorType: OperatorType + + init(operatorType: OperatorType) { + self.operatorType = operatorType + } + + var precedence: Int { + switch operatorType { + case .add, .subtract: + return 0 + case .divide, .multiply, .percent: + return 5 + case .exponent: + return 10 + } + } + + var associativity: OperatorAssociativity { + switch operatorType { + case .add, .subtract, .divide, .multiply, .percent: + return .leftAssociative + case .exponent: + return .rightAssociative + } + } + + public var description: String { + return operatorType.description + } } func <= (left: OperatorToken, right: OperatorToken) -> Bool { - return left.precedence <= right.precedence + return left.precedence <= right.precedence } func < (left: OperatorToken, right: OperatorToken) -> Bool { - return left.precedence < right.precedence + return left.precedence < right.precedence } public struct Token: CustomStringConvertible { - let tokenType: TokenType - - init(tokenType: TokenType) { - self.tokenType = tokenType - } - - init(operand: Double) { - tokenType = .operand(operand) - } - - init(operatorType: OperatorType) { - tokenType = .Operator(OperatorToken(operatorType: operatorType)) - } - - var isOpenBracket: Bool { - switch tokenType { - case .openBracket: - return true - default: - return false - } - } - - var isOperator: Bool { - switch tokenType { - case .Operator(_): - return true - default: - return false - } - } - - var operatorToken: OperatorToken? { - switch tokenType { - case .Operator(let operatorToken): - return operatorToken - default: - return nil - } - } - - public var description: String { - return tokenType.description - } + let tokenType: TokenType + + init(tokenType: TokenType) { + self.tokenType = tokenType + } + + init(operand: Double) { + tokenType = .operand(operand) + } + + init(operatorType: OperatorType) { + tokenType = .Operator(OperatorToken(operatorType: operatorType)) + } + + var isOpenBracket: Bool { + switch tokenType { + case .openBracket: + return true + default: + return false + } + } + + var isOperator: Bool { + switch tokenType { + case .Operator(_): + return true + default: + return false + } + } + + var operatorToken: OperatorToken? { + switch tokenType { + case .Operator(let operatorToken): + return operatorToken + default: + return nil + } + } + + public var description: String { + return tokenType.description + } } public class InfixExpressionBuilder { - private var expression = [Token]() - - public func addOperator(operatorType: OperatorType) -> InfixExpressionBuilder { - expression.append(Token(operatorType: operatorType)) - return self - } - - public func addOperand(operand: Double) -> InfixExpressionBuilder { - expression.append(Token(operand: operand)) - return self - } - - public func addOpenBracket() -> InfixExpressionBuilder { - expression.append(Token(tokenType: .OpenBracket)) - return self - } - - public func addCloseBracket() -> InfixExpressionBuilder { - expression.append(Token(tokenType: .CloseBracket)) - return self - } - - public func build() -> [Token] { - // Maybe do some validation here - return expression - } + private var expression = [Token]() + + public func addOperator(_ operatorType: OperatorType) -> InfixExpressionBuilder { + expression.append(Token(operatorType: operatorType)) + return self + } + + public func addOperand(_ operand: Double) -> InfixExpressionBuilder { + expression.append(Token(operand: operand)) + return self + } + + public func addOpenBracket() -> InfixExpressionBuilder { + expression.append(Token(tokenType: .openBracket)) + return self + } + + public func addCloseBracket() -> InfixExpressionBuilder { + expression.append(Token(tokenType: .closeBracket)) + return self + } + + public func build() -> [Token] { + // Maybe do some validation here + return expression + } } // This returns the result of the shunting yard algorithm -public func reversePolishNotation(expression: [Token]) -> String { - - var tokenStack = Stack() - var reversePolishNotation = [Token]() - - for token in expression { - switch token.tokenType { - case .operand(_): - reversePolishNotation.append(token) - - case .openBracket: - tokenStack.push(token) - - case .closeBracket: - while tokenStack.count > 0, let tempToken = tokenStack.pop(), !tempToken.isOpenBracket { - reversePolishNotation.append(tempToken) - } - - case .Operator(let operatorToken): - for tempToken in tokenStack.generate() { - if !tempToken.isOperator { - break - } - - if let tempOperatorToken = tempToken.operatorToken { - if operatorToken.associativity == .LeftAssociative && operatorToken <= tempOperatorToken - || operatorToken.associativity == .RightAssociative && operatorToken < tempOperatorToken { - reversePolishNotation.append(tokenStack.pop()!) - } else { - break +public func reversePolishNotation(_ expression: [Token]) -> String { + + var tokenStack = Stack() + var reversePolishNotation = [Token]() + + for token in expression { + switch token.tokenType { + case .operand(_): + reversePolishNotation.append(token) + + case .openBracket: + tokenStack.push(token) + + case .closeBracket: + while tokenStack.count > 0, let tempToken = tokenStack.pop(), !tempToken.isOpenBracket { + reversePolishNotation.append(tempToken) + } + + case .Operator(let operatorToken): + for tempToken in tokenStack.makeIterator() { + if !tempToken.isOperator { + break + } + + if let tempOperatorToken = tempToken.operatorToken { + if operatorToken.associativity == .leftAssociative && operatorToken <= tempOperatorToken + || operatorToken.associativity == .rightAssociative && operatorToken < tempOperatorToken { + reversePolishNotation.append(tokenStack.pop()!) + } else { + break + } + } } - } + tokenStack.push(token) } - tokenStack.push(token) } - } - - while tokenStack.count > 0 { - reversePolishNotation.append(tokenStack.pop()!) - } - - return reversePolishNotation.map({token in token.description}).joinWithSeparator(" ") + + while tokenStack.count > 0 { + reversePolishNotation.append(tokenStack.pop()!) + } + + return reversePolishNotation.map({token in token.description}).joined(separator: " ") } From 9d5c990ea69bd6f0fce8747630358a8391be48c5 Mon Sep 17 00:00:00 2001 From: Jaap Date: Sat, 28 Jan 2017 01:55:24 +0100 Subject: [PATCH 0793/1679] Set Cover migrated to swift 3 --- Set Cover (Unweighted)/README.markdown | 3 ++- .../SetCover.playground/Sources/RandomArrayOfSets.swift | 2 +- .../SetCover.playground/Sources/SetCover.swift | 4 ++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Set Cover (Unweighted)/README.markdown b/Set Cover (Unweighted)/README.markdown index fde032438..0b4ddfefe 100644 --- a/Set Cover (Unweighted)/README.markdown +++ b/Set Cover (Unweighted)/README.markdown @@ -30,4 +30,5 @@ If there is no cover within the group of sets, `cover` returns `nil`. [Set cover problem on Wikipedia](https://en.wikipedia.org/wiki/Set_cover_problem) -*Written for Swift Algorithm Club by [Michael C. Rael](https://github.com/mrael2)* \ No newline at end of file +*Written for Swift Algorithm Club by [Michael C. Rael](https://github.com/mrael2)* +*Migrated to Swift 3 by Jaap Wijnen* diff --git a/Set Cover (Unweighted)/SetCover.playground/Sources/RandomArrayOfSets.swift b/Set Cover (Unweighted)/SetCover.playground/Sources/RandomArrayOfSets.swift index b64d8d70e..9454c6383 100644 --- a/Set Cover (Unweighted)/SetCover.playground/Sources/RandomArrayOfSets.swift +++ b/Set Cover (Unweighted)/SetCover.playground/Sources/RandomArrayOfSets.swift @@ -18,7 +18,7 @@ public func randomArrayOfSets(covering universe: Set, while true { let randomUniverseIndex = Int(arc4random_uniform(UInt32(universe.count))) - for (setIndex, value) in universe.enumerate() { + for (setIndex, value) in universe.enumerated() { if setIndex == randomUniverseIndex { generatedSet.insert(value) break diff --git a/Set Cover (Unweighted)/SetCover.playground/Sources/SetCover.swift b/Set Cover (Unweighted)/SetCover.playground/Sources/SetCover.swift index 8d40e1fda..043cf46a0 100644 --- a/Set Cover (Unweighted)/SetCover.playground/Sources/SetCover.swift +++ b/Set Cover (Unweighted)/SetCover.playground/Sources/SetCover.swift @@ -8,7 +8,7 @@ public extension Set { var largestSet: Set? for set in array { - let intersectionLength = remainingSet.intersect(set).count + let intersectionLength = remainingSet.intersection(set).count if intersectionLength > largestIntersectionLength { largestIntersectionLength = intersectionLength largestSet = set @@ -21,7 +21,7 @@ public extension Set { while !remainingSet.isEmpty { guard let largestSet = largestIntersectingSet() else { break } result!.append(largestSet) - remainingSet = remainingSet.subtract(largestSet) + remainingSet = remainingSet.subtracting(largestSet) } if !remainingSet.isEmpty || isEmpty { From 83dea87c62a44e8d180811e4d1b5c9da211dddeb Mon Sep 17 00:00:00 2001 From: barbara Date: Sat, 28 Jan 2017 19:29:21 +0100 Subject: [PATCH 0794/1679] Splay Tree Initial Commit --- Splay Tree/readme.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 Splay Tree/readme.md diff --git a/Splay Tree/readme.md b/Splay Tree/readme.md new file mode 100644 index 000000000..2282502fa --- /dev/null +++ b/Splay Tree/readme.md @@ -0,0 +1 @@ +In progress From dcd1a0a877d72a5285b56401866ea9a9a97e8017 Mon Sep 17 00:00:00 2001 From: Bo Qian Date: Sat, 28 Jan 2017 18:11:26 -0800 Subject: [PATCH 0795/1679] Updated README.markdown for the new implementation of insert and remove. Added a remove example in BinarySearchTree.playground. --- .../Images/DeleteTwoChildren.graffle | Bin 2912 -> 11233 bytes .../Images/DeleteTwoChildren.png | Bin 13760 -> 33187 bytes Binary Search Tree/README.markdown | 132 ++++-------------- .../Contents.swift | 3 +- 4 files changed, 31 insertions(+), 104 deletions(-) diff --git a/Binary Search Tree/Images/DeleteTwoChildren.graffle b/Binary Search Tree/Images/DeleteTwoChildren.graffle index a03748077e6c23fec83e473e86fd9d71ef5fe97e..a6a09877a55b170f3d9f0938099d6841e93f1af7 100644 GIT binary patch literal 11233 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 literal 2912 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 diff --git a/Binary Search Tree/Images/DeleteTwoChildren.png b/Binary Search Tree/Images/DeleteTwoChildren.png index c0a77aab1f93d9026e523e2d2439d04ef5b943a5..1d941fe3c16265e73797fa9fc8ea5b621b9d5272 100644 GIT binary patch literal 33187 zcmeFZg?h_*ZAS0!wlY$$j9Q2LdjWyIot(_e? zEp42wAe`QgFTmYMNaEh2;73P@yCsdcBh<-F)LVk?&mE%RXT)VLI+{PXxIdSmGuF_i zk#ly1&pxIX(AUJ3mVR$7@->JBbH$mC2V=Y#Up`t9?=4Sn76}=4w!A{rt0yQ!KQX9u zth)+y&)D2Sa`YR^SonLz--QPh(;vbE9v^@hJE@U&}~^ncC=8QmD~X%`eZlFJ5Sxtz>Zh_v?zv8P2srpL(EQ7lZ* zl%ZKe)2>g(4NCUv$Sy5qT|@uXeuKu!#!WC)1r|P=6pSI5@N9<7`L15!ByVNn`C&4THD~MZE;0e{CF#>E0&28e zO{D0Emv_UdQSka1f@&bVISiv9Aoqz}HlO;RAFN7U!pEL{D;IH^Yjm1#e)PuF&`|K% z*W&pWFR9<3P< z4Kp%7D>EGy4N`DFun=7mFA7c=n9K{|$p}=Gj*F?v6`d8KMZd!zuW>!KIlA?kW-B{x zE@;Cj=tDoDcThy<{4g4P%oOcV065ky${o;5RoyA?DJ=6h3YAEV^q#_ zjpNHukqyIiD7>b?ti|)=^J!a0Pl2y~AxLOX@TBveNataKZxI3Ca)^d+9)R&1%Pru1 z@O7hvX@gTVnLymB zvu}8OGhUFiI7UdGPBghtBIWUtO0u~e63S0PbR~G>1*TMO-7hZWg}5Cqt=1+6Zs0Cd z5-*GOsd#OaeSCZbhJd4Blkpcnwp>&4$xG({TBMaVtOr9NdlfBSjN+?pizcY%;XCx;J21z(Zv za!m`@0mcKg(ReLM2akzd^@Zf??b@+=`|++Nia*q)9PD&MeU{fqXt}^pk)AhiCFN1r z2XOEOH6XM!YUOGC4sombX8YHtiydHdc`f=+kJ>M~9pu;X_l5Xau=;^@-3IUQbQcC@ zmybspBpzwS_n-pwWfavtwOlbfH#fJjvGK9xXsl^HwCU#?^4;dG52!f8G(|3h(hK6W zfwa2RA_%tkE*^<2fe`;L_`((RZ0LKnhsf)ZNMqdVk>Wc6TGF;vys_6ewcp2g8Wznf z&D+$t+Vn@R#Mn|&hAhyP47lGQp;;k<$T?E>B_4Mi(x9!);|+a05Jc|D5M>1uo&h)C zYuRhZr&s)1z5z{;mq8xextB>v2FCuvf*_DjsgPkKt?3i=M1YtYuvikZBa;l}ulAS$ zuNJ?(I?Pa9+r88;s(6ZvjGinHg5RUGqdOq@5lF*HG4Qk*K82XzKd?n6cu}qX*gSH+ zP$R7yM{L-^SUov|pqmN>_#r7^!9hO2jSpQ_V^QdU8`D%ZdPqyRFF)xBXnPq7!WoxY za~;@}n+Cdx=9 zQ)jBJ@A;~lWFx3;Kd{i?=o>y@V||QlsLlw5OPFR5hTE@xhc6M*4h|c@>&r)tVHJ-* zs;b6{?FvV_)hpE6je+prP=Ub=umsR>={)v7tX)1GtoA+{L4Yzaau`~w?KXz{-h%%^ ztIvsGN$vH;aan2Uv-xI^Qu+O-qv;|O?{ax;5p-D>?Mv|kOdJqrt-(6?=EudLse(CV zd%Jv4&9)oMJaFF!*rm@V+`z`h7B3WVyg4=GWAF^Pk_&T?Vvj%Cmq7GnW#HC4Wk&;n zV6Cq0B9utbFz?^*i=h;AT~Q|SAS#O@6L>b9%mW6M_`eLg8}uoZ#GIwFBU8k!@U`e* z;gVsx8sVS-H*heTDqLj#XVesaVA@d#XM3+Giq8&EuJfR$MKl%E zzLx0qMUyjg)!cwh>Nc%Yd$ttG^%%IzV!);2V!K(zT|>mHN(rU&N(q1Rq0!*^qp+AB zxhdmzfiy$}Yp~8z>qmyyg2*aNZ$)erk>4eCTotG%&(=B66PjHmI-Sj#NG zgMlMb#VAtR(-5Od^9=J}N5-W>&%bS#mVHn)eA3{Qp+0mEm#WoqRi`buhaiX(j-u@feKYr>}_ZJ4Uk~rUkan*|38P7c!iv zNheRSW@@rwF(56v|6p~<^y9OsW{>AQqqgxToV~gVtg6SuwYqeRrGn6z7yC;+iFS_= zi%bIoz#HU$1%Ny}5WW!MbX!i^w!dc4b-6d1gyV7D7)BW`K%dD%jrfGA3{ejYoq5T4|x|@|Rlo#n|hM-@|HqBh7$_ zZpwr*n=0ATU6{){4&Q@51!9z&wVdQea>j)v76DMdWz~HT-K*UrE5T#xEdHqAA=fL6->Pt&1H=hU4GD5Tk!!(PF8g<)sZ+Ry-G+StdcR^I2qw?J*KGi{3Mky~E424* zQztvKLuy?%Nwy~a^Eq;1+i%i=rwua%DW;?ty}T3b4d}{JM&QdmX5?M&OBF(k6ttC_ z9S{=t073?%-m}e|Dq=WSt}WlXIn25prXRUj300=S;|Kf9zUvHZ<1WA=L&wsIv6-~H zf3%N(ydpRQb6&YN)sj44*{baLa1J$*9;nzevhe?yo&6(k*-}c<+1q{ z(9%}L=(qlly6Hz)O?vO5j57u)DhPSW;~=Bk&;x2sFDHW5O8DcU?H<W@gCrdvEq24)o65{r(-kXq~kpBUzLut^&}R4`{^QX zo70ul8`?Rq3yO`?($go{^}U1sWpcfA1b@uCBUS?!v;i(|3DrFK$#GQC5`a$jO-^iVAT^< z?)u|+@@t8kv*q_Qws7lI-B|vtfQyaoiEVtQDOx-nu&xxNbtqt6RlsQRf{rpYDxfk$ z--#XkRWT6kbyan$U5(ud_A$O8&XGtGE>F2=QLv82;IpcfCvm{u0Azzh{97GbFh7cT zclzDea(7U47Jq5wM0zrbPe7Hz-0;2xA(0`%mw8Ker!oT?`WYBY4t_^xZWS2~d z64}tiLw@a}P9Mwfi>B;>js{4H>MMmj6tbs{q0;8S%~iHpOwHd=M`I!<+VElNV6))CJO<@{`{<=uTatDGmr)o2WbWqWjkg1(Tw9Ld4DSlGLv6pQ%lZO zIVMWj(lx0aj%J93VLj~P9HFw*r9`1ZU>nkSu{sk>n&vTBsA0bxC;&SQ#4g99QECZa zQ4Bn&SO5;Yx@hm!yZ1{kmVdffCr>U6C!nQ|8j!v;K=r%Pqice@AEEyOPEtF7GiZw% zrYD2<cxJ zo*^|@IEtwj3#g1Qn!W8YsS|kYeT~{7K%YVIxjf)=BLGe)Xg}in%U<>%O1Y(y!A2hO zY|rBZfAX4(svtUyz7by&IM*J@mU-=+52sftm7^gC+lBmLf-ApjD1jgzdKS{)TBr#4 zL*-$B{u`?nv!HRNYCMZ8*9E;kA9^6(`O8{3Gi(j{7GYmj0uGvts8yA72D>fayYrq1OS^3K)JTJxOAR4O1>zXAIPQ8?+`)` zBN+mCF{&8E;#Ia)XMT;H!iFS+4;G;Cg7cao&UmxbSkXf5ke0=QJjBtF7^w(AJUt`GS+UoI_XuE(O^uMDm zN_WL<;SZC|P&@)Le;%*UN`Rj(drCb?IV-#{ab-~hqdk=U9mCuI-wOF#_1*1LZxps%i6AkhPXHMk@{Ka}5G8uQVxA=umvaL%S zKHDKU!eAoq=DG7^UQGr3;>O%$w)(WAZP3u&zB~6WozuuxF7#Z>2@fC8w^ya5V}pZ( zB5rHLSyF)~+wg6^5qL($d^q*}^f9UjZVZw71X(0Cb_us1lS96s7@EL6Xc) z04_--=6gWikd3um?{=EIQV(UjbLbv**r6&*Z^j)eJ~GR z&ARW?voLU2h#hVwMqqcM>HaHIxYkJ4XJ*BTEHW8iI?pQc#n!IqRPmrh0wjymJ}DRBNh|G#V}D`P|Rb5_?L@@!P%*CUO{9 zl(0|3{9ffyg9ONGWRiYsW0hZJjX>#Sm5dH*3bPSoso>5`t3zMm!H#djPP(GmDCh1> zg-%iz3T!0%J$>M(GmNaDw;x;YEhSsWY|K2m2GR)6Os}V z1f1r)zZUBt5|Pq(s3REtu0e0G$yIl^mtfmm$%a#V$)!VLh8mgL$1>k6YfoXMZ&OIs zh(ax`r#aV`z;24L7-p{6+g^_7mbOxEWScMy?MTr%C$JOrmqN$53IQh*Ec)||Da&9chGgekDyPbNyivxLl=>RxnX ztV8k_T7egOFKPR97^?g)J$-Jj034Zv6wPaY(dT#}Vd}XAc3Rt1&%op*RvOCz?V2>e zr{E=lZl6NM`KvX@nwpF2O3B|7G9Y=Q^53g8PuC_vNdzmZ#{Qs?uwTDEZQ(qlygVRq zt7CE`ol4Eag?IIJi6)y>B@vj|&jRbuZ}F8tmxF)7Tx(3(Y$FTnnB;smCoz)V-u$t(A%fxy&v5NvIc99Td6sl!@ zSSx`2GBD+vSqd*?5EWOv%4NA1QB(2FUa}cV)8%Tops{2`u4tN zLR-OY6|cORjJ)^3>A=UTv-fkbBvx9RCUIaU=>(@vnP;whF_Q!%mIeTxR0cX$O9p|> z+??0XV$M5TNLpRAE1DPRNtoHV{92~3ZazNyO6GkOx>obom&xrw}B< z!4o7c2#AItFKiYs`D1|72${ebo5*x;@9`rS#Pics#mQVKcU-B(EgbuD<^kvcnyR@l zIt5a=pbIurP79yagfhblKtHjHG3MTAWY_Szbh?C-GckR?D*z>^OknJ_Nb!DY@XC_V z)ARTlZuA5jHGX)ZtJbPXZL@~G&|3Kt9}4Dq&q0z>o6BKj8wv5ZA6ll;Q5v3+H7V)y zpDqkd419VI&Gv*nwoR~6_3ER!EN)LUxV*U7*rnkpYBoqQP2ChoU-^^V)<-!WJ;HFR zXV>u9`c?tTB>)~(o+oy{CG>_k<;ti8)j~QaKbYnQPeD9W!nc0? zsY~|#V1+EsM++U6pnSez*QaPFSU&mm=bN79qZDB}1yJD9Z+6G1FZWZ)6Yc37Ni4{s zB+rCb70Z~23>K-7tFwJxDUlq*CyFAims6g zrVW{2oKg~YTyJh2QB|}B4vKYu5c#!2%n=~fT

);B7r3#*}9BpI{$Wf55>S;J&iM@o#BLQPFmBaWL5Z8v)z=aYji`m7NnA{xyw zmoO82V%tkll|EVRWM)LUFKOoPwCr?J$d%afa&fT3ukCqOS)~n8n%;)wn8Q~OTCe2E zaQUCf{>iAr6N3qC&!<1k=PKM!5VY}PX{r|Yzc_mJ3Z)v+W~*#F`QEbItOi-Mb;vC) zR!-G}sxeYQ4-|iNCxl-=V~!aVg|74-C=pW6R=3mfb)EJuOs>@2*KA%F6fxk2tmf{u`HxeOg>jolP9x1fy1q>;)ZNOQ3Ox-~0M zlhQh;`Nubai!X;|9UU!~Th6+SQ@ATC4h}I{jezklrTS=HFEsk=f{=7^ z&czdl($6>23zt2R0tvcNTd)IpQ?%paKNV)A;eIrzpTv-8w~V{2 zoHocOI`=4!xBJEl1*`l#=lOK2ty)UA`;WH@cd|Lc1QcCca|yTM_#Ner#?d zQ9B=XnT#1R7uOcD0j@81H?yTFh0iY2rS~Cdl!AWJrK{=fn5>gh(Ff%lquyITL+)~n*E1^#?8Dy`M_&#$z*Gq`N`p6VG@`B27!;%$yBAq@kDPD zPO*=)j^%s0=(fP`HW^q_c<7lRDHXSVd=?`ug93@1dHS@A;%QepXZ!*niGZq29*#*_ z>~bI)MxZ6W*(q`%X)w=`=tJ|vGsQhRw{1E*Vb&|(N|S23IR5(k*PZ!oeL@QPRA7^h zqgA%EyB;eaDmSgV?x&icJq-(6v0Rh-(C9XuX%?G#JX1gDc>HWy56hhFnX!_?c|)$; z@RBqL?sAF#dwJqW1mAfb99ZgF;O(y?isV4+k$W#DQDq2v-g-EC`71Bhrqu77iJb^` zBu1^C)y4M~GbS_rn$v-GN9q8-A1)(tZSmG3@2(4KJQFe84Ed{tgB5$|MgqKC_d?(U zR$Y=|rwO-lI_1|dcQQ*QqEESWuvCdvSUGPE-QSvkGB(tuzh=)Ls(txoL=!fmhLi?M zHl0ba&Faah`J9U`A1pe|tAjzguV1V>iOYg>uf?!D&Z*wA`>q3LTgY-T0oZ2b24Na6 zsd2^IO@0PT&D8w}eIwDrFtqA@n}<_rb{n=~dr9H^{l~7)hJX5R+8R*U=r82V3Lf%L zK5#6>rM1}K)LIQV*eQxuQxx~Qra1S0+&1|@OuO1KkH5%1>LFSjV7-d3?xP&c&lL?; z8ol@_)uwuW675Hnj3a+*%`}X>rtGP((BxJ$c+w9V3a4{!V}RtY^q6hz?TT*X$AeaO z0-wBt73gO{yV42u`LS$_R-C<>XQ-Nb11>2&;i1$Lzh^p&K8n}PresM<6kTmJ_00$P ze={G#8E)~c0#=peL0FY$;KoY_3}w)y=Hk0zjVo$MY@K!0ZD>aBaecY&eB-j3(VcqT zSf!YwYCI9r8j+}xY+!5||2IFT11%L37)Qv?`vMFdK|xEy;YcQ11pLYW)hTq_JN`l=P{tkqn^A1AQkj{7bO*@_%LgUMzry%Km4-+u9Vwo{O0ITL&DIv zyol4pc&AG)3gN4>EO+M#jW!~7+IOJ-#zXJ~FZtF1{`r(DpuQFr;x?|@QGgogxxG41 zp0%9IX>g#Bt=LW$qtXI;IIyBf&}n+`ByebOa3$IT2yQSxV2Fol{D{iL@M%8tNa`-E zD*km(iSoU5{ncX=*@ZI?rf#O~xy^4>WCf;*bog4+y>>&BJzNH@xm1pM*W@Cp9393t zHPExUihcN|##4;o2LLKTz1IU}o-D(xy=|!=8V9B^?=x}G6U{ZmR@34V27lD(H_K;< zBZwLr8VVX$lp?M+FGfH|Rn?r73H#18T4pyB4WMu{pCyoS(muE45g5g&a6`K^D?E2{ zbiNlbU?LBE^|C2@-q(J8`QugFb%xjnsdF+Vx9uOVI^F(i?x)}&lMp|M5#9gJbDN6y zgxmV|`0_pT6Z$`|e~svBqL*Ht0gcdoz@sDpOZ8Xvzo2pIY2yDGFEwW`m%SAlJ~$s< z5DZc*#MMq*Gy)9%2%R6Vr1!dg^$m9dZsJ2ZH`mJP5WjstNr3u~?ne`L@C1{D*B<=( z>dhTN!4F#DrY@WsjVIDQt@y=D%-$$9Ci=kchLz?!&U#B#KuiI$zQbvb1$WxtW2**c zn+6rfJ|K0N`4}+Of<U}HaT_B4+>|s^oW_N~J~}Cze!LX!28T&Srsjn- zSh&}0y<-?IwWRwm?Y)KH*<8U3as+nAnoqvl?#WMI#;Uh+Jx^h&e=$jyULTHs&K`%?pT6o%&aD4j)m_Rg&!C* zOm8YiIvN6g6^QA!%~#l^w+FV&KEC}1-Xxn%h77A9!;>tob`EMbhz8W%D{p6At)Kn9V@e{dblio5dD~|`t;jM z+ZZ30iwN|@a9ejT)Fp2v=hUFgP=N@=B@9qu%saIX(dw5!9DFi;7W(ebd8mWF^`hjy z82=!p^s`kEQdZ?dWSD}Pr!|w-Q`Rf8vV2qvO3f}UWVADdEUh&(7rYi| zoDw-;QEKdBvzY8k8G?+4`~l_nY)w>`T9Bz|hzTY+m(3V7ZKX4ri3y3Stxbgrd||osIr&Tm33B+_ zD#~v=?@z&6Ez!x(rL)L4p~59&NiGt{(YVeCF1R~W=hL^Q)v#w!??&#mGgp--e*45Y zs3wI^Kbd=-Imy-6glQPGiZukdyyD{HZO)A_A>Y%}#fuhwz+O7}HJ-Q1#CMqfph1|T z+_*XylsaxNraM-mU8XMC{(d092JwJh%i-1H#Q}$U5~tbcb`C+NzYxm+Y9~bX-T{BAI%zu>r*|#oJXP%i*AfhhZ_yI?Iv0ayX$;wz6xA<*s7v0dRwH_z7j`J#|$53tEStmS27NTk*W zgO`J99r`TiQ2JVkj-!_*WZx5j!|L>mna4AQm`{j8CFrHo@N!n;32Vv5<~moXPnQm*^H=dbwS@bygJT~JcSSxU5Cc}hn887JF{b;M>ay$0C9lfx`rYGQVoP zJf5N^$gnl#N%KK2@#q0XKKk#(?FSLuIJ_2PzdjiF#GMzWIla8xX?Sg1vc<{p>|E_f zOLWp+hlS^Z!|B=rA;Hv|&jj7Fh{BB5Gz0`?p=Yb1pfN?Vtpj}kiM0AA`!+>vm{$7c z1BONW5A};BCO2<~Aw9K*dCxRx3*{)(q*)jUA%K8HJ~L@l&&$E^KIldhJG@oKv)7j= zP)NprMayIZ4z6cM#5MFxt?rzZ0(oz2EWeLQi+5QU9@J$f331|kdfeeV-mm!vi z+T*JZl%I&nZT`D#p8L?-`u%L3?}cwZ0reT8AzuwZ186g}5$4O^Q}Vld#rKd$C`E4Y z$*+`rC)0se zt@ewjTA*3KPIy|&D|vvdZW^e*$X?=+}i^a?Sx2X>}lrKSyAGH}faqRd}t6|f;# z`r)Y9nAlz`KnnF9D)PUbBLp}Ht#lzq2Ux>^_xuaEgSLJV5}xlGY<$s*_2(<6`D_K5 zDu)tD1g@8n;H_nrx8ZAASo@5U;Is-)G618OCX5~byVc$w#--d#m*5}{pl zK*~y%pmfH+^9t-Kl*d?Q*-#$!<}FUQF!p=5B zF790wRh=Q`RXSr$hygnJ3=^Us|A(E~O+Y|5kD1 z-5o1!pl>Ltji_ZDBwpWc`6cF+Y$iQq#<;>I9FKgwFumz_M4uJ8gfbmxp8uXeSuZy~hKqdr2^yP?iK&{OH0g*5C2q?Zb zQb^`=5g`YCe+Fpnw$EP(0-2IELnG}ENWF%c8p`WAZAnlZ{2(Wc ziq(|AjMO@h7PMTu^M4T&Akx>j%*-G;1t%u71$)84fjLXhLyp%P8GoX^suS(lLF&b)`-)#}|!j~fDo6S~7yr!rF(4PVYq?OI9dQAQHl9Bpx zeF$U~sOr{$;u91Pfo}efT*0JNUthof$OjxRK!gV%5kK9X_dVV;FgCWILV?@>P4Jc7 zvvehX%;<=@Y(;R&q~Y z?Dctb?Da$L3JwzI*sQYY!>}QTye9&io&taNdU=ATKd*e38?v_0QJo+2YS9*8MwugrV*npNG`lll+0Z;`67@V zRg+=X|N7~(%@ZSrWOK#dEg)6{oH(~XWQ*Yo(16Hh>Yg-?!}OC@;h=HuKEYdG3f##+ zm#1DXZ#zC#5q>x@1WIOHGkH@igSJ^*u#rry19n1NBGo3xqx4kQcoDC)u9~+;-vUqG z0Wq};LSVGtLvmuvYS$Cq8W${5i^*0bXb;n~a;a6y)8~y*EYZfCybCmjo)2ba;rcai zYF6_eZ{IrKJ_m z8Xz)OHi&;%!sN?UBwOnFu8Fx;wWCzzr?mjeCRQ~3qLK_bUnM!7k)B#ysQdd<;BR-|w>ixLu9Z56$rXvVe>rCj{yRM@8e4Ey$q5|#(jT@hk!uQJmQgLqOhH3S0bgvfZJKX@~t{X#>2v^LV^t)c?w&@PH6k05AJ z6zhFN9M6co$EnCQxc1&hzqEyvoF%PqB^R2An#jw*=I z|9ax1rgsTRi3!4N;}&0eCl@tmde*d_xdl!(NPp6ET4kd$p?-fsdWg!kj2F%8``h~= zxjihYnwFPkmds~g+KelY1j6Tg1unCsB~^D$88JyP4g03_!xYVVS1!gf^E-qENIh~f|qVHatU4};@yPni~x?3hVoN-h; z6$7E{11H2xD!4PLH7LUhPuPZaFy+*~gWR2X9#ey|4RK{36%^FN-d z3Fux<3jnH}@n^TjdY439&I+X%q=nl0V#46if@7wMGTG2Y9+ETo7@q`L7tL5v`lCD42py#Ws3N>03kqaR{EpB$(88wc0*H*oRsRkm{l4pv zZl^s7&E1Q6P?!K>LtIMHuPt)ZRO&lP&uKVWyT05_ZDo@bpswfN`u?%3yfIM^^fa`Z zI}xD=!01;&{ThSWlA=sj=X|Y(5>NKZlBBf>A=fh7rzc8!eK`md@OOQABS;28RSMJl zdp^m*IoOT>yfuFm$tJ_L;Gh2`ZLys`Xy0lmxgM0Ke1d_s1J?w3!k28B6TyL6sf+R0 zi9PNiRxF>eKEz3oQeTj-4xKdX0#WX01A^Nhs~}s^{OXoGc^74{w3yYVdg*FNYo@DCyMP`fOVJ;i&($6W?QW zr`L@ar@uXbJl*^y@X^9DhLChEKN=MI9;C~tGY^Avv~^ED7A3y97&4lRaC7LgXkc9c zhF4v@t_jYuU~s(Z@7mt_(4yIH)C|g8mq#1c){lnjSJ~vqQT4P^L~%5BjFOk}-q3zg z%tLtv{WAtKHmX_!cirbDXWGHFOuOvU%47F-aEb(^{h%Lphs506^IGtuMQ6dINj@yT z6r03G^9L|@M&}A)pov@!M)%S2EIfS1xc?;1aZ{N8qs7!+$82iL;#VZmx;YQpqf7Fp z5nD|5X|XIhL@(#TI}M6G?y(FpqXhMr;`-GI=c^`V@`rAW5kkSkTSa4 zCiaQFK7dRTc4IsyJd*3U-|5fv&#osDbDl>>hypAa<|$c7ynhEAqV~?aF-_TgyBeHV z{qr$6cDl4VW zi}ch_ls1dFf34IL#K+U%)d0>@hD>${o ziSZm%uKl#UftrrVFutf_KG;b7`bb(*ZJO)lHNZi&lzD^-Z}E<88iyK(&;1~NSSeLJ zsuBRh8VVwv+v}Qb*aJ~Aa{C8l363 zqtC2kG6VEU2a`a&+{3zIt7~>6oB!7&33`F{uCjTv6k%L}XTnsdmM3h&Rw)nMnh!oqX0qR*)c$g_ zO7P?X^Do1=o3_@`QHK!COGcr@Fl=(qrEq3ZN9FDA?WD-xPmEkX|2|ueO{yffL4Ktk zxB7AHpsgE}FpC%5zdj@;CI-hjJy-hQZ<={Ndjtj2YkF*v3Q`YWrR6WycHIEEOFvpWn_ZcrLk)jdg^U> zPC$Ri7o2uu{cglJS#L45gmsiRcZ)c>zfxckcs^v|)Ny?>CUtuSI`h|SY0eMG1%h(? zhS;>6hVy+}o6c6j*#}mLte#qxR5hriFw#_dX z8E~kCTCnb) zLGnhmA0zUxM@8v$V)q8AZO^?&Mb`U=%80ql=Zdtb6TGpWvY^^7eGad&xd6Sv=L@Y( zs+B~J-^xwgfGBO~ImZ)muI!nRQQMf_oW7V45u7Q6xzx%;<@SUA%^za%bD>noZ=TGL z&q%|y>)-X+)ilk_TYmG&iAloGUZ?~I$+bM=<9uRT$4mlNs7mT)LERPsH#|t^dJLO| z_7t>y9&aWd`8b(4Jz};SI;aN9LS27&4J6`P;I$>t5AT9n$zR>fl9~N<+yCrmuJa2{ zd>R)%Ql=SpDPG{>XEl91^)TWdzbZ|(4!l?QY&Ax)vhTOHU@Vf{hh2MUHZ+bB#<4=n zI?}U`a|jO0bR%<&t%eC!!`?i&^ytE1ZUskYAE5xDzSIikkNd>z!kfi;x}hicfX7M_ z1df&R!9076zulRC(TzPoYSYV7Rx@Ss$qB2QR_+ZDuZRs)w0{O4e(+C9xp=-IWZ0A*LOXm^@Zvx*bfkZB2mXq+wv zb|}SCA*d8|vVb7p2TLi6v>FKV2Vz!P=f`a6r_uzTGjTbO+2Uon9=jx4y#gnIl20!a zHd85zW3l;JGswvjH0dq+HuHptXujnl>rZDiYR~&fT zd|6Z<&Xh1sEWJCg+8n5NnXu589Xs`K0hGJ|7FM*DY3~kGgCc>euZ19mVQV+V%?x_# z?7Y_^#~xNvLugCDy<|Yu59pdfy2JL%{`j;~5~uBm@d`nFTWvZW%sk%M>x-I#Nh!9+ zOes|+q3eKRaKUmrg5n1?z1DY?zFZU-}>%7$)Aba>yJ@9RW_a1t4g8MC?>20wx z)M5}8XICIhuVC->d|-TL-L2#OAsV6dac+w5Yl2iaHxvG&q`*5nu_5fPME_^}xqUCA zp+^83GWZY%xw0Gt!NfUEAuUK_QjDP-Te0PdI013~T*rX`UCdCRmUi_48+F}8r z=U30d*8m^Or8-Wm41zLS3lkF&$M5{-*KvFKy|L6>YW<}T^CbuWQ83~0h(P_DWPa}Y zLcar39H_(mKka>0RF&w3c1@V_{Co_PIk$ri#} zA{z=iDD(!LFDhPA`S4-VP=^zUkbK_6tBfwSwXPB6R%xSE^qQQP{-%&<4)2uui($W}NoNeOIOz zmNbsJD|@$K0!ckQNkt6o;yzvBevfv`F1QzgR>8+-^x3MB@wd9H8wKUu*jQicY9DS@ zHN@?Ab;X|*O-4JQ2{sg1{DGNXrS`F2!7I{TByal_3B~K&Pi%vd(XC!{0UG-6Atf*=>+NDga|4#!5Jr*#UWsGzzEs0J^0$> z$001x3pcqLg~w7_wu=4=ada&gqa+yS$TJd9Cn3cg*O2ydV-KIG*OsYY%~zUMyF~p& zZk=?&&pLbe>gpjoa{Y~?R05;r=#lKY#qM3Q>`W)Hhz5+k%VtrXe0A4!5^>_4_xRmylNP0L5*&mn zU0k_LvTV{%H#CELtVR)B?9dsS0VJtc1_6*awu!0?wQ;`n*CahWtvCdeG_-i|%KpS> z_n$LsAtf^8^{)5^Z+~B{lNgjx@XkMFR5(v@JWPhjtViE;IdS6vl3oj;vTiIsg0aB7PG+ci67W71eg27us66UdVQQgp9%qusDi^l^V%FQ%n>x;mf0Y^(_3N zm`BB+Xp+1!E$3L(_U%JO`IeURm&_EN8~u%+GRmt>1H#Pb?Hx?K#~%`r@!a^A~$VDp>qZqkc%%t^zN@;BM3* zxH%>j_M-QGe)V3TANg)8BojS!{t!6l&Z89te0-a)SwpQjx`|kQzL%jn6Kl^OaV##p z2&k_$^Z{mHgk#I#HCLuAJyE7Jxe>&y`XMU2_+KoHU|AQ}*G5vdl#wqK3VS`T*}Jmv zF>oYe0C3!$C!m2@i!vwRZ@Idb9SDf&ymP#s9^*p-A-Uhr4|rTs`~GIYP2l3-&eGY7sIw;v9s=6Iehg9XetsmLbiEvG1DrIzD~QKDNPI)WLb@ zGH&=9x$T`|O|&!EFw^Ysdvh7UB)G1jg z7tOJL9@MK8S!elNC_EGh9ac3`oS^DlqrU5*37;_8JS&1dK! z)odIwHjtp&X6na>384skK7LBOKo|&rWXqbw7k7kxlJZ#m*(LT_sd{XeMCLY;&Fh&F zyB9xz0#b9+Ot&7-S$0e{dreJF;#Rg^nc5p6X62E!=#XkNKkvY_8y|ZE!7u5bwX>afvseoY zg;&u_(y}eunOdE^GRlbNg-4$nvifa)ew*HfyDQ^-Q+;*&EAQ4OtyHN+waK57Dn^2V zX}(4q%OF`M1#HQ<6<<%9@DAGD;mR=NoapASn!Pogb4C{Ybc8N7b2QYKoY~dC9__Ct z;3e*Fuda&wd+Tkz^;|~#O%Oaty$M)=Zo?7yvanUV$cns7mhVPU*8zMih`9bgIj z{8F5-2fRU6T**_FFcoES*Ir^qAo8wEyKl}B!Wu9TL2{Y|T?xE3YcsUgi11>*p%r%N z_R^c1jXnFd0EkMxv?TE>2QmNh+Au1tls= zELFx+wp%ejzMo6Fcs2w}(Rg{Mkx)1`K3*y)#$gH^dRI8jENs%VnlD2EE6QQuwZ47q zZF*5zme{kad=X6p36U_C9Rx81?%GP^5_h&6LpDg(sm-K_y;?ttZS1U!c)Y58Et;mn z6w#Xx3KOe-O4)1akE(G%bnCh6Oi8^j%%_odV(o?iPgXud_3$Z?^1`*sQc4|Zy-BkV z!Cgsrs5GA0@mgq-FkSo^ts$g`ebZ$N%$6Kfk|DE!yf9OQ0ksaSXu1#~P@}jUBPyTe zoSf6QQz#rD>Aq?6Ip$K=mM^>SU<>Ypq`ElTV4y#(z*74ptsKIRQBJ>CJt*29<0&6H z({V~nyyF2UY6?eO{g{cK=1fPfn!>00y)|Z-*{#b-B4g_zKaE!f9!00wX@zae-w_{;ndLXpe)aF}~AH?xo>Qf%yn3On|nCQTWM^Y^cS2FtVsuoJV!C z@M$1_>?&;*Efb#-yVP~}ZjxqdJY84M)SC#k(jr1PsrOm-kt)ifPI}Mi!$WTlW-*F& zo(*4g(VNzV0^IR3Cf96@n5VVF>csa8Gngx zZ*~ZYBJ#6XPR!|e%a)fd5V~b=Kvhmt110vhmx3saY@luTwEgjTe)?K9`f=c6oOkTM zR_Sa!&!=)M^jewK3H*_z#SWr&cckDQ26LbLvYmhiV>K8z+hTsRoj;ymTGRgEgX_o8d{ zSx~Dd*E02JQW@FkO0zVwc&IRs5@0kp--`>^H0bmjf%UYGOq&4V8C`Spl}`8Gq@x+# zn{-X!-*jkw1^mqSo89?q0S%(` zpc^SlaJUJ;JG@>D;~c24xqzC_#mEpHD>~ebm5~k0J6|8--CgSAs^*$ny5-6Qv|@ho zeo+^Ev^p7n%|5S5+xs*LJ80LJh7kl!^WI}6XR^X!FS;+N5Ar4 z!Dos*HLt*uv3ucHDZW5;ZtFhm%#E%vZ@o;t`8k6HmP}_UJ09v33?qwzdThVy$1B~t z{TV+B`YUs~IIyt9(b+iKjQFyF9Bu_Ph~#&JIQxhcP5!a7G)#QN)yMkjXz0)gAR>k#wlI5J2(o_s0 zZLr=0RzNL2nTnb^sOL!!4O>u8g70~9z2Gw?o|?8i!r}8yHxfsM(AYcAWh3)hcHwZ8 zifsBXkeKT9Q7WllYoxc)Xf?mrdA2GiVE$q#_DaLCzp-5(h^gFpR00A#P|ZQ3On|Qw z^d-ytwNh;6_*--i*;k&?R>gW>$s4bL%n7nNi9h<{BVj67EvGwz0m%&-E%gBS@Kt4~ zXnJbyhZEk?Cud}_bnRMnnl{I)));Or1_|eDiM{2yEth`qo+Ao)Z51uH{HQjv>fk;i zd#zJW_I0-2ul6@2GRmNW@#qU(*1gTSib($vuuSajfs#S&ukg+|!(`-w^L{1KS!!L7 ziyxc4RhMQ#5GYSNFJ$@a)`wIW;&Qo81x!qzWdd7rG1UPl{3g+FQJ%`kTgoe_&er-% zo-G4Lq1Qh3ljDt2T&r=j***3LfNN-27~|n~o^lusg?plK>Sa~V?TWc~134?hs)^=d zGai@>=PJ}}+E&xG@C+ew3ea4QQ;+dTD?>!;PPbZ8l~3+lEk*Sym$N8=Tj5>%G)Q7JTR)Ry^yv&)No`d ze)zMAl(Ys5ExQIvegW-V31|sI3G%IfRbnNQR5(oe5|}xCBSvr=)WCp+N-7se@s0Sx zINLj~wnV#9hjXRWPly4&SI^EIJbgnkn?21&>yZ(YGj9s_t{ZJIw~@ulBhqpjBa5jo z@dR{o*U6vvLQ-nfn%By1Dp&rT?O*lZz65k2bhWq3cFDz?U%}xzW@)7E zTQ+6_NrixY#=r|&bh(YX^v>RDFOSG^MWw~Jmw5T?W9LWurKMFL6NmRnrzAgFurJMY zPPP*>xmO_Qj*~*Hhm^)qA6r)3-|>@6`8mNsQb&e9)qcl{b&z`Tl)EWt2r36gC3D?Z zj`1fp1-h;$i}Z66F|O^Y+EdmR1XVP62kl|zU69;(o0VhyTEbrokp z9-%pevhHI0Rik74a^+&38g8QV1Wnw+f4i+C2vN&!74H5u5UOMXF9Xu0LEBebLZmZS z_EU|I@$0e)M<1WOG`RAJd=%RS#djE!6%Ytv;ne<1bPId7a}rUy#|9|Y%p)tT;801- zSYlr8E{Qt|Qe2lPze7zFlsJDC%D8fEC)sEPS&+aZCF!^es+7UWftF41jlVepEHDB- zvJYRxg|Gf4Iba(*t($HapSLBZBY74EFi+<6l=<)1TKwJD^7BArCCPE@*@SN;7@0sI zo#1DELdD;*-LiwW%K9^RJ2vXZh&Z2veoK5vxvzelv&foRVAZtkzw|==kYhuJFITD` zJ#YEP!w)iVMx1(y`Re2LrE~67QV;W9_`iiZCs-BYESnPozi>CaRb#cWppZaOtFhFw z_;0@zTixbrxE2{UkliMVjLVToBwH$vU&m3`nn=0$Y%#$hhsRKfh?B!fYulDtGqrx^ zruWJ5!D>Ja|E#mv%Y!BDrxRL0vZ(``1|=tPBR`P?!S`sIq`YtFv^?FXv`bYvIXMup z%U{&l`wpqDY?bi&uB4g&;oYZs_y7?Cc=*ao!LVwJEkuh>)`UoK(?_#}O&yzyo~1TDWS?3#z*Fcu|OIkVO&C4S12or|DTkGHwZ1o97dsjeSi93R+in$KG2(|rVh zy>Q*emCn1jv|oOA4~{~1N#9}4l=czxKiB~YUxEvnRrh{PYc3Q}2$ScgHZLGV`PA5o z&%XkN6v*G-Q610=EI!|%5xBBP-E=*)pn{w|MV~L-{K}G)f-1utSEIoN$x@z-#Eu-w z$8n#&%RSXDXX+V9IMnU`R>YpK`Oq`RnVU$W&F^JqWFT@g zAiEK0x(+y=2#||;nKgWw5+p-i&x>v1Z-Zhl$Y+?kwotDz#vOQrPxs2ZbE{V)aKsm- zU)+5Md~EhKxx*!$7oc2+u81I|ZM*1NBB0k4!Gd4q7Be1$Mt~S2u+ML&iaqm~acnK- zIG7U-K)>qfXuBZ*)TyMrRs=u)XxJKc8c5BPy&obn$0>`)ucp=q)NwI>OjJR~jdFC4 zmoR+vP7Q(6vBcN&?HX5H`$ato=CwH?+)Y8e`8Z9 zH}FVT6;mYw8qgvDmU6Nn8x`OK*&=kdwSZzDi!oTT>3LGkv;5f$X#-$Z@&sqf2%7q2 zjTfa9zHx}n_Q%hlOFV$c@IPF(7^|2QQeb?No8FNWyAhEMf@T-*s}gL~wjiF@=1aM<)C?qnGf`YP*T}9h*%|lFekv|IY=A*tgtJiJ z7HJ&27wufYg=WqdphEE?*bm_B;Z@*`T{IdpKA+Gg2+Ai3~65^RGDE=VsMTJu9ry~emb|?%T1)QZ=Jb}5AG3Ry~jdRF0e9^U3F*3OvgD%e3hDQo68)$kQPy0|&0U zWGX1$G#nqg?6)>dC?`6y%i>AKL`PtTtAkjMKBgpIN;ug_Dw3!v4YN7|D%V{KEQId4 z=VT;e&!(vaMhuiQEe<3cHM>3P;4T$4kXR8}u#@g2x_ab%$_Cx>rv!hvUPOwCE(>)T-Xwp73G?)(hyx)xn0GjdPH=RTI|p zF|#1gloKcXoTmu(gfQ*nPo9@osNVYo+Q%-(?wa%}^Xo|j=##;zkKRhu3OX_pnI!xs ziof)r3wDfHqj8`_aHlbl!0n0gWb|3DL^Q8xFh6s{@5%UEO|2$OR9x+_K23PuV0dTI z(S?TH@Y-|d~w%wtKpgWZ9Ay~E2$Y1@fGb}w`9RVf@>w9<3QOvf`OD<)c==_pWY#{^Y~0^lF44DaqoCcTvAAlVr~aLET-knA|4BKD zD5kf=1Zi=9=_OEVtWo_1P;-uMO+>3AwnPkzcrXOt42!pwu)H?PLujUY(dy$fDE8(E zXFN}PFSobILBL_+zQW!$|LLpSW=@74F6rYtZ*ygbYg=cuF-%pTs(9-pHL&#Shah(~ zWHnt-#@Z^>Jp)FGW_O3;^>qub-pqFfWsDKhO+=!~t!I&N`&5_&S-~bWTxhHz2k!OEZ!(4E9i|gC*%A0%iDkBTb_(vhd zp#lZqWtuA|7K%B@a!S3sT*7j=-;){5fJCby(!202pu>7dN_|T6_9D+cXk9?a@Yx&q zswg953|XBgvHmhcwRv3@q^JU=kpnK)Tv+8A1|Q7)f<|n-Zb@RsO)4?PX>m&&%mzK^ zF#p#6UI@-=@|8;~)ryl7T#=QPpooI%I5deXwTV10dbO;pLN8L+ypq!?-nKiHPat$| zcMKpWow&*XS#RG+GM?sY)O2|pmoHWeN;o#(-p{tj0F#uHll0=(Q{GHQWtSxB`Ge0m z(ZBl9lzRI8yg>)I9UWh17nT=!$H&gK!~6r4wrxW2Potht2c}4qKVOnVztUNjSjb2- z6r{(ASa832Xt|b-;75HbFrcmFeee#yH=oMakAzB}4>D$Z)}I_WQN|=2s7{CBZ({ug3cE?>2=+v^hiMPZqHVM4v1eiDELP#H%{3WKUP+vmVe z^%=0qX6TNhZBy1u<8Bc_CoaMXWnPOfZI@$8Y^}c^{(K@wWxqBNURy3|qG%3_@5{d} zzUCQajB#aHeCsJ1Zo10$yd8^}b$HN4C!-IvPk9>+DR|ip@ zR^K8TyW4w|=^`*MGb|7_eavgcxB1ZWgw=lsl=er(&*arA*{_bYm21a5QlXb5YFvu_ z@?lEcEn#^m4I;h zxtboB7Hf{wuMB2@`v1PN?6DOWs(OsCpXun6apHHY#r*Afh8;qL&D=6*0+Y22?6g+}j@uyjWz>;P2+c10pMtJyv*%`Nbz) z$N1YJM;s-U2GX7V^f=-!Mf8)TIqDz&Z#egt`(GJ40S4G#65`*6`wXe9T6B&S!Nhil z92EqU{rY=6%E$Ox%#8Kh8Ygk#s+#CP=1H)8*osR;?T*ds1A)Mg-9V2m&~uNLEZ6j? ztKxxr_4%94_^ZWzGK;L1_bcwRIGqGCZaIH9K(fIKMJK&=b=s-C08zDGEn)Ji)7e2H_Sn(<`VGuXYR>jI8*d{c=_XEp@!vHtT(FiJ6a@?n2MSfVZ^`%j5c@N@(UX+ zd#qR2*-y`w_igFZ1!*8uQ2&i$d^M=NQ7FS5CCbVz0GRSx88^OueH45Vh!O!~7tDAA zavqAf(^-`gq0?eHj7Va{xC({J!MvfjPG0 zA~i|xzyA)G`+!1-F=&(H{PREme$F0*=gVyg&M^J^HE}(ULA_XJ4MFwC7vP}`dXS$? z<_f&?|33Ry3lO9rda>DtrT6cje_#tL(N6JXjUYAu=R-1Zaljx4sS+r@|M^fdISAhw zE8zcsH|_nWBmYNdgpOGm++o6V{yDl*W>>DP0o6!0vW^u_RUnrqx1O?Rfa_E)VGy4O zIbjs&%P)fm0J0g!0Y2L-?1m$)7^(f76=4o9a|HyI&3U89e9j&yR=B;X<-8K#Pm!~w z!=FfFX^D@MM6MD_`%@vHC^UiSe9UD&EoHNyTBXxhtZnZa3hH|Y)UMY*vGki9y*rdP zGV=N8j2+xkGB5qYdq;9gazT3GAs)*PBsB<&t?}^5c!cW{8Yf8MS;_23Yor+(5*po0ulrKqXN#7^+Mya5+GE#P2P zU$D)N$iT-5eXSw`;WkuX{eV}0f9t!kq2YP!w&$d>J8Y+I$@@mQFtL-f5M|VLeEPY9 z#zzKJ=f)Fmdm^c9zR;HO^f(tSzX}1~Z9tZU z3(ow2uB$z~DR3Vy&vKfb4I-qydi5&q4&ZlvmtR+bz(_f;wQSY)mJMPk@2KC6*>6*K zeDZ{Z`7MYCnianuNcB8zo%(Q{kX~2V@TB(nE#Ac9ZS`Pm@FC+0#5=0C)hR z?ikPpdWJ6VepK3{@7l=KPGevUiK#;;>RlQRC8~lLj!78A7eUuDtm@~C4KY0_0a+U@ z@8xi*`x}e9>kICNLU*}~?P~z`5XpQgzQHPEK}oXD$}wa#4yv2 zv4B8cSNG_VAn2EW&o|(o6^nYATq1{PGixpl+3qJMfI|boHEq zd=Zm_WO_K^!CSa%1LR?atK3ps>GVu*X!kjABG@Q-yBVl?Y+GwBKm|8~{{jGqon6k7 zu^}?jF}GV`nX*^Ls$7mbfM#NMq}T~PtTxTScj^b~2`hjH z^TP$M7SREPd~Uxe=oAK~Ck=077Oh_h7SFHkW=fq3#{m>D;K&n~4|eZcHl4=rB3^cI z@}zn?LhhvLKuODg+;A&R#z*3~08po*+oe$Yf%@yUH;#r!<-0uo3solEhzE!tI1Du^ zEzQKDuN70H=qSa<0d)ChO2>%;`YDgiP`=pG{s0L6A!F(`d8{7~7tl&(7C26(Jwt3} z<>Z*h2JZz&jt#o@jFi~A(;|eQ^5~>@-8ux91^7H&lLa7sy$d3?<27PF`~hbqC|a#= z&Y2u-Zv%O%*t||EfEnHE{Kp8Z!TdyQ*YRps*VQ>NEgGGkJEgUOrylMRire;vx%jz$ zj!pb7GWJ6lZdOTlD%LwCMn)J!O_oTwygG3#fW|^Kn+}Q&8Fh_PQ;W?nhdLCCrCpTc z$<;hKSpVDr`@1^GO=L4J@XY&cLwLTX75Mz4ByYivqSyzgC85n7OZE7~wC_8Kr7X3IHY=92eE(eh0Vd zcx;DmE!2e~{y7`fa68&fhT;5Yt{nOKDX#i+iJXG|rd_v$R!mthTw9rH2ryl!1(p_I zDY&QRN1aLzp@`4U4~c5A!Do-&-T3gRTAil`se=Brd4{Ny!3t+`HK}`7+w;Sk_>wKw z`11s0`3(pwnz}^P`P=K>fO|m80zf4M*s8!jx9LhWJ2oH2e27b4&CgAL`#JFl{=+@| z=8=nVScJH{Ov`S%4!8mXo&}5uZ<>Hnan~&gTt`iR$^-#b{-d!Ap;|4tY3=J(x>sRE z#A7-doXsp!d4O=hr^;D81bn6IyB;L+Tx-0B6;+(3Fq5TFQY6yBi&MKQVmYGf*4SOh zFsojlgey-{Y9^Sw{NJGq!?kA{S;z8+P8Z=vx{Y8MS&?xRSepN>Hc^-VbsN%um-5 z;f{l>4c(OX{+OZW>-$}s7tgSX@aT$@vmqY9u7mY?@{b`AMy!AQ`}dD*|Ly;KI70X5 zgO~&u4<#RFh5XCA;CcM6kAMC^b{T#npwjyD8;BbcxPLX^ua+Pb5I3|l?AiZl942PD z=$}7eQ($7cV=7brvjgbo$r8i={DJK`{6@)}{O30wymu!0-Rr+Tdg@`|gZHV3UZsB> z5ln1sTdO~Rz~{uqp2rU5{>Nj#KgRZ-q5IF!{jsk9v+Dk{VgFZc-7)Um3U}vZ>#Wx) P_@kz*tyHXV*)&wu)y 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 diff --git a/Binary Search Tree/README.markdown b/Binary Search Tree/README.markdown index bacb1ffe1..e8d2f58e2 100644 --- a/Binary Search Tree/README.markdown +++ b/Binary Search Tree/README.markdown @@ -69,21 +69,14 @@ If you traverse a binary search tree in-order, it looks at all the nodes as if t ## Deleting nodes -Removing nodes is kinda tricky. It is easy to remove a leaf node, you just disconnect it from its parent: - -![Deleting a leaf node](Images/DeleteLeaf.png) - -If the node to remove has only one child, we can link that child to the parent node. So we just pull the node out: - -![Deleting a node with one child](Images/DeleteOneChild.png) - -The gnarly part is when the node to remove has two children. To keep the tree properly sorted, we must replace this node by the smallest child that is larger than the node: +Removing nodes is also easy. After removing a node, we replace the node with either its biggest child on the left or its smallest child on the right. That way the tree is still sorted after the removal. In following example, 10 is removed and replaced with either 9 (Figure 2), or 11 (Figure 3). ![Deleting a node with two children](Images/DeleteTwoChildren.png) -This is always the leftmost descendant in the right subtree. It requires an additional search of at most **O(h)** to find this child. +Note the replacement needs to happen when the node has at least one child. If it has no child, you just disconnect it from its parent: + +![Deleting a leaf node](Images/DeleteLeaf.png) -Most of the other code involving binary search trees is fairly straightforward (if you understand recursion) but deleting nodes is a bit of a headscratcher. ## The code (solution 1) @@ -158,23 +151,19 @@ A tree node by itself is pretty useless, so here is how you would add new nodes ```swift public func insert(value: T) { - insert(value, parent: self) - } - - private func insert(value: T, parent: BinarySearchTree) { if value < self.value { if let left = left { - left.insert(value, parent: left) + left.insert(value: value) } else { left = BinarySearchTree(value: value) - left?.parent = parent + left?.parent = self } } else { if let right = right { - right.insert(value, parent: right) + right.insert(value: value) } else { right = BinarySearchTree(value: value) - right?.parent = parent + right?.parent = self } } } @@ -379,7 +368,7 @@ As an exercise for yourself, see if you can implement filter and reduce. ### Deleting nodes -You've seen that deleting nodes can be tricky. We can make the code much more readable by defining some helper functions. +We can make the code much more readable by defining some helper functions. ```swift private func reconnectParentToNode(node: BinarySearchTree?) { @@ -396,7 +385,7 @@ You've seen that deleting nodes can be tricky. We can make the code much more re Making changes to the tree involves changing a bunch of `parent` and `left` and `right` pointers. This function helps with that. It takes the parent of the current node -- that is `self` -- and connects it to another node. Usually that other node will be one of the children of `self`. -We also need a function that returns the leftmost descendent of a node: +We also need a function that returns the minimum and maximum of a node: ```swift public func minimum() -> BinarySearchTree { @@ -406,17 +395,7 @@ We also need a function that returns the leftmost descendent of a node: } return node } -``` - -To see how this works, take the following tree: - -![Example](Images/MinimumMaximum.png) - -For example, if we look at node `10`, its leftmost descendent is `7`. We get there by following all the `left` pointers until there are no more left children to look at. The leftmost descendent of the root node `6` is `1`. Therefore, `1` is the minimum value in the entire tree. - -We won't need it for deleting, but for completeness' sake, here is the opposite of `minimum()`: - -```swift + public func maximum() -> BinarySearchTree { var node = self while case let next? = node.right { @@ -424,94 +403,41 @@ We won't need it for deleting, but for completeness' sake, here is the opposite } return node } -``` -It returns the rightmost descendent of the node. We find it by following `right` pointers until we get to the end. In the above example, the rightmost descendent of node `2` is `5`. The maximum value in the entire tree is `11`, because that is the rightmost descendent of the root node `6`. +``` -Finally, we can write the code that removes a node from the tree: +The rest of the code is pretty self-explanatory: ```swift - public func remove() -> BinarySearchTree? { + @discardableResult public func remove() -> BinarySearchTree? { let replacement: BinarySearchTree? - + + // Replacement for current node can be either biggest one on the left or + // smallest one on the right, whichever is not nil if let left = left { - if let right = right { - replacement = removeNodeWithTwoChildren(left, right) // 1 - } else { - replacement = left // 2 - } - } else if let right = right { // 3 - replacement = right + replacement = left.maximum() + } else if let right = right { + replacement = right.minimum() } else { - replacement = nil // 4 + replacement = nil; } - reconnectParentToNode(replacement) + replacement?.remove(); + // Place the replacement on current node's position + replacement?.right = right; + replacement?.left = left; + reconnectParentTo(node:replacement); + + // The current node is no longer part of the tree, so clean it up. parent = nil left = nil right = nil - - return replacement - } -``` - -It doesn't look so scary after all. ;-) There are four situations to handle: - -1. This node has two children. -2. This node only has a left child. The left child replaces the node. -3. This node only has a right child. The right child replaces the node. -4. This node has no children. We just disconnect it from its parent. - -First, we determine which node will replace the one we're removing and then we call `reconnectParentToNode()` to change the `left`, `right`, and `parent` pointers to make that happen. Since the current node is no longer part of the tree, we clean it up by setting its pointers to `nil`. Finally, we return the node that has replaced the removed one (or `nil` if this was a leaf node). - -The only tricky situation here is `// 1` and that logic has its own helper method: - -```swift - private func removeNodeWithTwoChildren(left: BinarySearchTree, _ right: BinarySearchTree) -> BinarySearchTree { - let successor = right.minimum() - successor.remove() - - successor.left = left - left.parent = successor - - if right !== successor { - successor.right = right - right.parent = successor - } else { - successor.right = nil - } - return successor + return replacement; } ``` -If the node to remove has two children, it must be replaced by the smallest child that is larger than this node's value. That always happens to be the leftmost descendent of the right child, i.e. `right.minimum()`. We take that node out of its original position in the tree and put it into the place of the node we're removing. - -Try it out: - -```swift -if let node2 = tree.search(2) { - print(tree) // before - node2.remove() - print(tree) // after -} -``` - -First you find the node that you want to remove with `search()` and then you call `remove()` on that object. Before the removal, the tree printed like this: - - ((1) <- 2 -> (5)) <- 6 -> ((9) <- 10) - -But after `remove()` you get: - - ((1) <- 5) <- 6 -> ((9) <- 10) - -As you can see, node `5` has taken the place of `2`. - -> **Note:** What would happen if you deleted the root node? In that case, `remove()` tells you which node has become the new root. Try it out: call `tree.remove()` and see what happens. - -Like most binary search tree operations, removing a node runs in **O(h)** time, where **h** is the height of the tree. - ### Depth and height Recall that the height of a node is the distance to its lowest leaf. We can calculate that with the following function: diff --git a/Binary Search Tree/Solution 1/BinarySearchTree.playground/Contents.swift b/Binary Search Tree/Solution 1/BinarySearchTree.playground/Contents.swift index 6d73585b5..ec9902283 100644 --- a/Binary Search Tree/Solution 1/BinarySearchTree.playground/Contents.swift +++ b/Binary Search Tree/Solution 1/BinarySearchTree.playground/Contents.swift @@ -7,8 +7,9 @@ tree.insert(value: 10) tree.insert(value: 9) tree.insert(value: 1) +let toDelete = tree.search(value: 1) +toDelete?.remove() tree -tree.debugDescription let tree2 = BinarySearchTree(array: [7, 2, 5, 10, 9, 1]) From eb54bc8544f0d482336878e211269ea43da9a7a7 Mon Sep 17 00:00:00 2001 From: Mike Taghavi Date: Mon, 30 Jan 2017 11:38:32 +0100 Subject: [PATCH 0796/1679] Add Simulated annealing --- Simulated annealing/README.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 Simulated annealing/README.md diff --git a/Simulated annealing/README.md b/Simulated annealing/README.md new file mode 100644 index 000000000..bee8ffe94 --- /dev/null +++ b/Simulated annealing/README.md @@ -0,0 +1 @@ +# Simulated annealing From a6afbc107e25b96bdb86b9186f4a5794046b004b Mon Sep 17 00:00:00 2001 From: Mike Taghavi Date: Mon, 30 Jan 2017 18:18:50 +0100 Subject: [PATCH 0797/1679] Initial --- Simulated annealing/README.md | 32 ++++ Simulated annealing/simann.swift | 105 +++++++++++ Simulated annealing/simann_example.swift | 222 +++++++++++++++++++++++ 3 files changed, 359 insertions(+) create mode 100644 Simulated annealing/simann.swift create mode 100644 Simulated annealing/simann_example.swift diff --git a/Simulated annealing/README.md b/Simulated annealing/README.md index bee8ffe94..e7fe75778 100644 --- a/Simulated annealing/README.md +++ b/Simulated annealing/README.md @@ -1 +1,33 @@ # Simulated annealing + +Simulated Annealing is a nature inspired global optimization technique and a metaheuristic to approximate global maxima in a (often discrete)large search space. The name comes from the process of annealing in metallurgy where a material is heated and cooled down under controlled conditions in order to improve its strength and durabilility. The objective is to find a minimum cost solution in the search space by exploiting properties of a thermodynamic system. +Unlike hill climbing techniques which usually gets stuck in a local maxima ( downward moves are not allowed ), simulated annealing can escape local maxima. The interesting property of simulated annealing is that probability of allowing downward moves is high at the high temperatures and gradually reduced as it cools down. In other words, high temperature relaxes the acceptance criteria for the search space and triggers chaotic behavior of acceptance function in the algorithm (e.x initial/high temperature stages) which should make it possible to escape from local maxima and cooler temperatures narrows it and focuses on improvements. + +Pseucocode + + Input: initial, temperature, coolingRate, acceptance + Output: Sbest + Scurrent <- CreateInitialSolution(initial) + Sbest <- Scurrent + while temperature is not minimum: + Snew <- FindNewSolution(Scurrent) + if acceptance(Energy(Scurrent), Energy(Snew), temperature) > Rand(): + Scurrent = Snew + if Energy(Scurrent) < Energy(Sbest): + Sbest = Scurrent + temperature = temperature * (1-coolingRate) + +Common acceptance criteria : P(accept) <- exp((e-ne)/T) where + e is the current energy ( current solution ), + ne is new energy ( new solution ), + T is current temperature. + + +We use this algorithm to solve a Travelling salesman problem instance with 20 cities. The code is in `simann_example.swift` + +#See also + +[Simulated annealing on Wikipedia](https://en.wikipedia.org/wiki/Simulated_annealing) +[Travelling salesman problem](https://en.wikipedia.org/wiki/Travelling_salesman_problem) + +Written for Swift Algorithm Club by [Mike Taghavi](https://github.com/mitghi) diff --git a/Simulated annealing/simann.swift b/Simulated annealing/simann.swift new file mode 100644 index 000000000..8adfbf817 --- /dev/null +++ b/Simulated annealing/simann.swift @@ -0,0 +1,105 @@ +// The MIT License (MIT) +// Copyright (c) 2017 Mike Taghavi (mitghi[at]me.com) +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +#if os(OSX) + import Foundation +#elseif os(Linux) + import Glibc +#endif + +public extension Double { + public static func random(_ lower: Double, _ upper: Double) -> Double { + #if os(OSX) + return (Double(arc4random()) / 0xFFFFFFFF) * (upper - lower) + lower + #elseif os(Linux) + return (Double(random()) / 0xFFFFFFFF) * (upper - lower) + lower + #endif + } +} + +protocol Clonable { + init(current: Self) +} + +// MARK: - create a clone from instance + +extension Clonable { + func clone() -> Self { + return Self.init(current: self) + } +} + +protocol SAObject: Clonable { + var count: Int { get } + func randSwap(a: Int, b: Int) + func currentEnergy() -> Double + func shuffle() +} + +// MARK: - create a new copy of elements + +extension Array where Element: Clonable { + func clone() -> Array { + var newArray = Array() + for elem in self { + newArray.append(elem.clone()) + } + + return newArray + } +} + +typealias AcceptanceFunc = (Double, Double, Double) -> Double + +func SimulatedAnnealing(initial: T, temperature: Double, coolingRate: Double, acceptance: AcceptanceFunc) -> T { + // Step 1: + // Calculate the initial feasible solution based on a random permutation. + // Set best and current solutions to initial solution + + var temp: Double = temperature + var currentSolution = initial.clone() + currentSolution.shuffle() + var bestSolution = currentSolution.clone() + + // Step 2: + // Repeat while the system is still hot + // Randomly modify the current solution by swapping its elements + // Randomly decide if the new solution ( neighbor ) is acceptable and set current solution accordingly + // Update the best solution *iff* it had improved ( lower energy = improvement ) + // Reduce temperature + + while temp > 1 { + let newSolution: T = currentSolution.clone() + let pos1: Int = Int(arc4random_uniform(UInt32(newSolution.count))) + let pos2: Int = Int(arc4random_uniform(UInt32(newSolution.count))) + newSolution.randSwap(a: pos1, b: pos2) + let currentEnergy: Double = currentSolution.currentEnergy() + let newEnergy: Double = newSolution.currentEnergy() + + if acceptance(currentEnergy, newEnergy, temp) > Double.random(0, 1) { + currentSolution = newSolution.clone() + } + if currentSolution.currentEnergy() < bestSolution.currentEnergy() { + bestSolution = currentSolution.clone() + } + + temp *= 1-coolingRate + } + + return bestSolution +} diff --git a/Simulated annealing/simann_example.swift b/Simulated annealing/simann_example.swift new file mode 100644 index 000000000..a0dfaa19a --- /dev/null +++ b/Simulated annealing/simann_example.swift @@ -0,0 +1,222 @@ +// The MIT License (MIT) +// Copyright (c) 2017 Mike Taghavi (mitghi[at]me.com) +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +#if os(OSX) + import Foundation +#elseif os(Linux) + import Glibc +#endif + +public extension Double { + + public static func random(_ lower: Double, _ upper: Double) -> Double { + #if os(OSX) + return (Double(arc4random()) / 0xFFFFFFFF) * (upper - lower) + lower + #elseif os(Linux) + return (Double(random()) / 0xFFFFFFFF) * (upper - lower) + lower + #endif + } +} + +protocol Clonable { + init(current: Self) +} + +extension Clonable { + func clone() -> Self { + return Self.init(current: self) + } +} + +protocol SAObject: Clonable { + var count: Int { get } + func randSwap(a: Int, b: Int) + func currentEnergy() -> Double + func shuffle() +} + +// MARK: - create a new copy of elements + +extension Array where Element: Clonable { + func clone() -> Array { + var newArray = Array() + for elem in self { + newArray.append(elem.clone()) + } + + return newArray + } +} + +typealias Points = [Point] +typealias AcceptanceFunc = (Double, Double, Double) -> Double + +class Point: Clonable { + var x: Int + var y: Int + + init(x: Int, y: Int) { + self.x = x + self.y = y + } + + required init(current: Point){ + self.x = current.x + self.y = current.y + } +} + +// MARK: - string representation + +extension Point: CustomStringConvertible { + public var description: String { + return "Point(\(x), \(y))" + } +} + +// MARK: - return distance between two points using operator '<->' + +infix operator <->: AdditionPrecedence +extension Point { + static func <-> (left: Point, right: Point) -> Double { + let xDistance = (left.x - right.x) + let yDistance = (left.y - right.y) + + return Double(sqrt(Double((xDistance * xDistance) + (yDistance * yDistance)))) + } +} + + +class Tour: SAObject { + var tour: Points + var energy: Double = 0.0 + var count: Int { + get { + return self.tour.count + } + } + + init(points: Points){ + self.tour = points.clone() + } + + required init(current: Tour) { + self.tour = current.tour.clone() + } +} + +// MARK: - calculate current tour distance ( energy ). + +extension Tour { + func randSwap(a: Int, b: Int) -> Void { + let (cpos1, cpos2) = (self[a], self[b]) + self[a] = cpos2 + self[b] = cpos1 + } + + func shuffle() { + for i in stride(from: self.count - 1, through: 1, by: -1) { + let j = Int(arc4random()) % (i + 1) + if i != j { + swap(&self.tour[i], &self.tour[j]) + } + } + } + + func currentEnergy() -> Double { + if self.energy == 0 { + var tourEnergy: Double = 0.0 + for i in 0..destCity + tourEnergy = tourEnergy + e + + } + self.energy = tourEnergy + } + return self.energy + } + +} + +// MARK: - subscript to manipulate elements of Tour. + +extension Tour { + subscript(index: Int) -> Point { + get { + return self.tour[index] + } + set(newValue) { + self.tour[index] = newValue + } + } +} + +func SimulatedAnnealing(initial: T, temperature: Double, coolingRate: Double, acceptance: AcceptanceFunc) -> T { + var temp: Double = temperature + var currentSolution = initial.clone() + currentSolution.shuffle() + var bestSolution = currentSolution.clone() + print("Initial solution: ", bestSolution.currentEnergy()) + + while temp > 1 { + let newSolution: T = currentSolution.clone() + let pos1: Int = Int(arc4random_uniform(UInt32(newSolution.count))) + let pos2: Int = Int(arc4random_uniform(UInt32(newSolution.count))) + newSolution.randSwap(a: pos1, b: pos2) + let currentEnergy: Double = currentSolution.currentEnergy() + let newEnergy: Double = newSolution.currentEnergy() + + if acceptance(currentEnergy, newEnergy, temp) > Double.random(0, 1) { + currentSolution = newSolution.clone() + } + if currentSolution.currentEnergy() < bestSolution.currentEnergy() { + bestSolution = currentSolution.clone() + } + + temp *= 1-coolingRate + } + + print("Best solution: ", bestSolution.currentEnergy()) + return bestSolution +} + +let points: [Point] = [ + (60 , 200), (180, 200), (80 , 180), (140, 180), + (20 , 160), (100, 160), (200, 160), (140, 140), + (40 , 120), (100, 120), (180, 100), (60 , 80) , + (120, 80) , (180, 60) , (20 , 40) , (100, 40) , + (200, 40) , (20 , 20) , (60 , 20) , (160, 20) , + ].map{ Point(x: $0.0, y: $0.1) } + +let acceptance : AcceptanceFunc = { + (e: Double, ne: Double, te: Double) -> Double in + if ne < e { + return 1.0 + } + return exp((e - ne) / te) +} + +let result: Tour = SimulatedAnnealing(initial : Tour(points: points), + temperature : 100000.0, + coolingRate : 0.003, + acceptance : acceptance) From a794dec1522cd0df09b96a2d8744b261b8185f2a Mon Sep 17 00:00:00 2001 From: Mike Date: Mon, 30 Jan 2017 18:23:23 +0100 Subject: [PATCH 0798/1679] Update README.md --- Simulated annealing/README.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/Simulated annealing/README.md b/Simulated annealing/README.md index e7fe75778..3a36464d7 100644 --- a/Simulated annealing/README.md +++ b/Simulated annealing/README.md @@ -17,10 +17,12 @@ Pseucocode Sbest = Scurrent temperature = temperature * (1-coolingRate) -Common acceptance criteria : P(accept) <- exp((e-ne)/T) where - e is the current energy ( current solution ), - ne is new energy ( new solution ), - T is current temperature. +Common acceptance criteria : + + P(accept) <- exp((e-ne)/T) where + e is the current energy ( current solution ), + ne is new energy ( new solution ), + T is current temperature. We use this algorithm to solve a Travelling salesman problem instance with 20 cities. The code is in `simann_example.swift` @@ -28,6 +30,7 @@ We use this algorithm to solve a Travelling salesman problem instance with 20 ci #See also [Simulated annealing on Wikipedia](https://en.wikipedia.org/wiki/Simulated_annealing) + [Travelling salesman problem](https://en.wikipedia.org/wiki/Travelling_salesman_problem) Written for Swift Algorithm Club by [Mike Taghavi](https://github.com/mitghi) From 717794dcb7cfaba84bc5f2dbbe3f316e5b7f57f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Azevedo?= Date: Wed, 1 Feb 2017 16:05:06 +0100 Subject: [PATCH 0799/1679] Fixed the trimming of deques --- Deque/Deque-Optimized.swift | 6 ++++-- Deque/README.markdown | 12 ++++++++---- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/Deque/Deque-Optimized.swift b/Deque/Deque-Optimized.swift index 6326b457b..f565458c7 100644 --- a/Deque/Deque-Optimized.swift +++ b/Deque/Deque-Optimized.swift @@ -7,9 +7,11 @@ public struct Deque { private var array: [T?] private var head: Int private var capacity: Int + private let originalCapacity:Int public init(_ capacity: Int = 10) { self.capacity = max(capacity, 1) + originalCapacity = self.capacity array = [T?](repeating: nil, count: capacity) head = capacity } @@ -30,7 +32,7 @@ public struct Deque { if head == 0 { capacity *= 2 let emptySpace = [T?](repeating: nil, count: capacity) - array.insertContentsOf(emptySpace, at: 0) + array.insert(contentsOf: emptySpace, at: 0) head = capacity } @@ -44,7 +46,7 @@ public struct Deque { array[head] = nil head += 1 - if capacity > 10 && head >= capacity*2 { + if capacity >= originalCapacity && head >= capacity*2 { let amountToRemove = capacity + capacity/2 array.removeFirst(amountToRemove) head -= amountToRemove diff --git a/Deque/README.markdown b/Deque/README.markdown index 5858f3e6d..d156f9d97 100644 --- a/Deque/README.markdown +++ b/Deque/README.markdown @@ -119,9 +119,11 @@ public struct Deque { private var array: [T?] private var head: Int private var capacity: Int + private let originalCapacity:Int public init(_ capacity: Int = 10) { self.capacity = max(capacity, 1) + originalCapacity = self.capacity array = [T?](repeating: nil, count: capacity) head = capacity } @@ -267,7 +269,7 @@ Those empty spots at the front only get used when you call `enqueueFront()`. But array[head] = nil head += 1 - if capacity > 10 && head >= capacity*2 { + if capacity >= originalCapacity && head >= capacity*2 { let amountToRemove = capacity + capacity/2 array.removeFirst(amountToRemove) head -= amountToRemove @@ -279,6 +281,8 @@ Those empty spots at the front only get used when you call `enqueueFront()`. But Recall that `capacity` is the original number of empty places at the front of the queue. If the `head` has advanced more to the right than twice the capacity, then it's time to trim off a bunch of these empty spots. We reduce it to about 25%. +> **Note:** he deque will keep at least its original capacity by comparing `capacity` to `originalCapacity`. + For example, this: [ x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, 1, 2, 3 ] @@ -288,9 +292,9 @@ For example, this: becomes after trimming: [ x, x, x, x, x, 1, 2, 3 ] - | - head - capacity + | + head + capacity This way we can strike a balance between fast enqueuing and dequeuing at the front and keeping the memory requirements reasonable. From 096eca30aa4a686f4d0839321dd99089d63c6c5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Azevedo?= Date: Wed, 1 Feb 2017 16:07:50 +0100 Subject: [PATCH 0800/1679] Typo fixed --- Deque/README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Deque/README.markdown b/Deque/README.markdown index d156f9d97..67a734576 100644 --- a/Deque/README.markdown +++ b/Deque/README.markdown @@ -281,7 +281,7 @@ Those empty spots at the front only get used when you call `enqueueFront()`. But Recall that `capacity` is the original number of empty places at the front of the queue. If the `head` has advanced more to the right than twice the capacity, then it's time to trim off a bunch of these empty spots. We reduce it to about 25%. -> **Note:** he deque will keep at least its original capacity by comparing `capacity` to `originalCapacity`. +> **Note:** The deque will keep at least its original capacity by comparing `capacity` to `originalCapacity`. For example, this: From 74bbb2105111797bad57ddc795b2b44cb494bb22 Mon Sep 17 00:00:00 2001 From: Parva9eh Date: Wed, 1 Feb 2017 19:09:34 -0800 Subject: [PATCH 0801/1679] Update README.markdown Hello, My name is Parvaneh. I am taking a writing course in the field of Computer Science. For an assignment, I need to edit some relevant documents and share the result. I hope you like my revisions. --- Merge Sort/README.markdown | 72 +++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/Merge Sort/README.markdown b/Merge Sort/README.markdown index 3ff69fdd5..05b90f166 100644 --- a/Merge Sort/README.markdown +++ b/Merge Sort/README.markdown @@ -2,40 +2,40 @@ Goal: Sort an array from low to high (or high to low) -Invented in 1945 by John von Neumann, merge sort is a fairly efficient sorting algorithm with a best, worst, and average time complexity of **O(n log n)**. +Invented in 1945 by John von Neumann, merge-sort is an efficient algorithm with a best, worst, and average time complexity of **O(n log n)**. -The idea behind merge sort is to **divide and conquer**: to divide a big problem into smaller problems and solving many small problems instead of solving a big one. I think of merge sort as **split first** and **merge after**. +The merge-sort algorithm uses the **divide and conquer** approach which is to divide a big problem into smaller problems and solve them. I think of the merge-sort algorithm as **split first** and **merge after**. -Assume you're given an array of *n* numbers and you need to put them in the right order. The merge sort algorithm works as follows: +Assume you need to sort an array of *n* numbers in the right order. The merge-sort algorithm works as follows: -- Put the numbers in a pile. The pile is unsorted. -- Split the pile into 2. Now you have **two unsorted piles** of numbers. -- Keep splitting the resulting piles until you can't split anymore. In the end, you will have *n* piles with 1 number in each pile. -- Begin to **merge** the piles together by sequentially pairing a pile with another pile. During each merge, you put the contents in sorted order. This is fairly easy because each individual pile is already sorted. +- Put the numbers in an unsorted pile. +- Split the pile into two. Now, you have **two unsorted piles** of numbers. +- Keep splitting the resulting piles until you cannot split anymore. In the end, you will have *n* piles with one number in each pile. +- Begin to **merge** the piles together by pairing them sequentially. During each merge, put the contents in sorted order. This is fairly easy because each individual pile is already sorted. ## An example ### Splitting -Let's say the numbers to sort are `[2, 1, 5, 4, 9]`. This is your unsorted pile. The goal is to keep splitting the pile until you can't split anymore. +Assume you are given an array of *n* numbers as`[2, 1, 5, 4, 9]`. This is an unsorted pile. The goal is to keep splitting the pile until you cannot split anymore. -First, split the array into two halves: `[2, 1]` and `[5, 4, 9]`. Can you keep splitting them? Yes you can! +First, split the array into two halves: `[2, 1]` and `[5, 4, 9]`. Can you keep splitting them? Yes, you can! -Focus on the left pile. `[2, 1]` will split into `[2]` and `[1]`. Can you keep splitting them? No. Time to check the other pile. +Focus on the left pile. Split`[2, 1]` into `[2]` and `[1]`. Can you keep splitting them? No. Time to check the other pile. -`[5, 4, 9]` splits to `[5]` and `[4, 9]`. Unsurprisingly, `[5]` can't be split anymore, but `[4, 9]` splits into `[4]` and `[9]`. +Split `[5, 4, 9]` into `[5]` and `[4, 9]`. Unsurprisingly, `[5]` cannot be split anymore, but `[4, 9]` can be split into `[4]` and `[9]`. The splitting process ends with the following piles: `[2]` `[1]` `[5]` `[4]` `[9]`. Notice that each pile consists of just one element. ### Merging -Now that you've split the array, you'll **merge** the piles together **while sorting them**. Remember, the idea is to solve many small problems rather than a big one. For each merge iteration you'll only be concerned at merging one pile with another. +Now that you have split the array, you should **merge** the piles together **while sorting them**. Remember, the idea is to solve many small problems rather than a big one. For each merge iteration, you must be concerned at merging one pile with another. -Given the piles `[2]` `[1]` `[5]` `[4]` `[9]`, the first pass will result in `[1, 2]` and `[4, 5]` and `[9]`. Since `[9]` is the odd one out, you can't merge it with anything during this pass. +Given the piles `[2]` `[1]` `[5]` `[4]` `[9]`, the first pass will result in `[1, 2]` and `[4, 5]` and `[9]`. Since `[9]` is the odd one out, you cannot merge it with anything during this pass. -The next pass will merge `[1, 2]` and `[4, 5]` together. This results in `[1, 2, 4, 5]`, with the `[9]` left out again since it's the odd one out. +The next pass will merge `[1, 2]` and `[4, 5]` together. This results in `[1, 2, 4, 5]`, with the `[9]` left out again because it is the odd one out. -You're left with only two piles and `[9]` finally gets its chance to merge, resulting in the sorted array `[1, 2, 4, 5, 9]`. +You are left with only two piles and `[9]`, finally gets its chance to merge, resulting in the sorted array as `[1, 2, 4, 5, 9]`. ## Top-down implementation @@ -57,15 +57,15 @@ func mergeSort(_ array: [Int]) -> [Int] { A step-by-step explanation of how the code works: -1. If the array is empty or only contains a single element, there's no way to split it into smaller pieces. You'll just return the array. +1. If the array is empty or contains a single element, there is no way to split it into smaller pieces. You must just return the array. 2. Find the middle index. 3. Using the middle index from the previous step, recursively split the left side of the array. -4. Also recursively split the right side of the array. +4. Also, recursively split the right side of the array. -5. Finally, merge all the values together, making sure that it's always sorted. +5. Finally, merge all the values together, making sure that it is always sorted. Here's the merging algorithm: @@ -109,15 +109,15 @@ func merge(leftPile: [Int], rightPile: [Int]) -> [Int] { } ``` -This method may look scary but it is quite straightforward: +This method may look scary, but it is quite straightforward: 1. You need two indexes to keep track of your progress for the two arrays while merging. -2. This is the merged array. It's empty right now, but you'll build it up in subsequent steps by appending elements from the other arrays. +2. This is the merged array. It is empty right now, but you will build it up in subsequent steps by appending elements from the other arrays. -3. This while loop will compare the elements from the left and right sides, and append them to the `orderedPile` while making sure that the result stays in order. +3. This while-loop will compare the elements from the left and right sides and append them into the `orderedPile` while making sure that the result stays in order. -4. If control exits from the previous while loop, it means that either `leftPile` or `rightPile` has its contents completely merged into the `orderedPile`. At this point, you no longer need to do comparisons. Just append the rest of the contents of the other array until there's no more to append. +4. If control exits from the previous while-loop, it means that either the `leftPile` or the `rightPile` has its contents completely merged into the `orderedPile`. At this point, you no longer need to do comparisons. Just append the rest of the contents of the other array until there is no more to append. As an example of how `merge()` works, suppose that we have the following piles: `leftPile = [1, 7, 8]` and `rightPile = [3, 6, 9]`. Note that each of these piles is individually sorted already -- that is always true with merge sort. These are merged into one larger sorted pile in the following steps: @@ -131,13 +131,13 @@ The left index, here represented as `l`, points at the first item from the left [ 1, 7, 8 ] [ 3, 6, 9 ] [ 1 ] -->l r -Now `l` points at `7` but `r` is still at `3`. We add the smallest item to the ordered pile, so that's `3`. The situation is now: +Now `l` points at `7` but `r` is still at `3`. We add the smallest item to the ordered pile, so that is `3`. The situation is now: leftPile rightPile orderedPile [ 1, 7, 8 ] [ 3, 6, 9 ] [ 1, 3 ] l -->r -This process repeats. At each step we pick the smallest item from either `leftPile` or `rightPile` and add it to `orderedPile`: +This process repeats. At each step, we pick the smallest item from either the `leftPile` or the `rightPile` and add the item into the `orderedPile`: leftPile rightPile orderedPile [ 1, 7, 8 ] [ 3, 6, 9 ] [ 1, 3, 6 ] @@ -151,13 +151,13 @@ This process repeats. At each step we pick the smallest item from either `leftPi [ 1, 7, 8 ] [ 3, 6, 9 ] [ 1, 3, 6, 7, 8 ] -->l r -Now there are no more items in the left pile. We simply add the remaining items from the right pile, and we're done. The merged pile is `[ 1, 3, 6, 7, 8, 9 ]`. +Now, there are no more items in the left pile. We simply add the remaining items from the right pile, and we are done. The merged pile is `[ 1, 3, 6, 7, 8, 9 ]`. -Notice that this algorithm is very simple: it moves from left-to-right through the two piles and at every step picks the smallest item. This works because we guarantee that each of the piles is already sorted. +Notice that, this algorithm is very simple: it moves from left-to-right through the two piles and at every step picks the smallest item. This works because we guarantee that each of the piles is already sorted. ## Bottom-up implementation -The implementation of merge sort you've seen so far is called "top-down" because it first splits the array into smaller piles and then merges them. When sorting an array (as opposed to, say, a linked list) you can actually skip the splitting step and immediately start merging the individual array elements. This is called the "bottom-up" approach. +The implementation of the merge-sort algorithm you have seen so far is called the "top-down" approach because it first splits the array into smaller piles and then merges them. When sorting an array (as opposed to, say, a linked list) you can actually skip the splitting step and immediately start merging the individual array elements. This is called the "bottom-up" approach. Time to step up the game a little. :-) Here is a complete bottom-up implementation in Swift: @@ -212,19 +212,19 @@ func mergeSortBottomUp(_ a: [T], _ isOrderedBefore: (T, T) -> Bool) -> [T] { } ``` -It looks a lot more intimidating than the top-down version but notice that the main body includes the same three `while` loops from `merge()`. +It looks a lot more intimidating than the top-down version, but notice that the main body includes the same three `while` loops from `merge()`. Notable points: -1. Merge sort needs a temporary working array because you can't merge the left and right piles and at the same time overwrite their contents. But allocating a new array for each merge is wasteful. Therefore, we're using two working arrays and we'll switch between them using the value of `d`, which is either 0 or 1. The array `z[d]` is used for reading, `z[1 - d]` is used for writing. This is called *double-buffering*. +1. The Merge-sort algorithm needs a temporary working array because you cannot merge the left and right piles and at the same time overwrite their contents. Because allocating a new array for each merge is wasteful, we are using two working arrays, and we will switch between them using the value of `d`, which is either 0 or 1. The array `z[d]` is used for reading, and `z[1 - d]` is used for writing. This is called *double-buffering*. -2. Conceptually, the bottom-up version works the same way as the top-down version. First, it merges small piles of 1 element each, then it merges piles of 2 elements each, then piles of 4 elements each, and so on. The size of the pile is given by `width`. Initially, `width` is `1` but at the end of each loop iteration we multiply it by 2. So this outer loop determines the size of the piles being merged. And in each step, the subarrays to merge become larger. +2. Conceptually, the bottom-up version works the same way as the top-down version. First, it merges small piles of one element each, then it merges piles of two elements each, then piles of four elements each, and so on. The size of the pile is given by `width`. Initially, `width` is `1` but at the end of each loop iteration, we multiply it by two, so this outer loop determines the size of the piles being merged, and the subarrays to merge become larger in each step. 3. The inner loop steps through the piles and merges each pair of piles into a larger one. The result is written in the array given by `z[1 - d]`. -4. This is the same logic as in the top-down version. The main difference is that we're using double-buffering, so values are read from `z[d]` and written into `z[1 - d]`. It also uses an `isOrderedBefore` function to compare the elements rather than just `<`, so this merge sort is generic and you can use it to sort any kind of object you want. +4. This is the same logic as in the top-down version. The main difference is that we're using double-buffering, so values are read from `z[d]` and written into `z[1 - d]`. It also uses an `isOrderedBefore` function to compare the elements rather than just `<`, so this merge-sort algorithm is generic, and you can use it to sort any kind of object you want. -5. At this point, the piles of size `width` from array `z[d]` have been merged into larger piles of size `width * 2` in array `z[1 - d]`. Here we swap the active array, so that in the next step we'll read from the new piles we've just created. +5. At this point, the piles of size `width` from array `z[d]` have been merged into larger piles of size `width * 2` in array `z[1 - d]`. Here, we swap the active array, so that in the next step we'll read from the new piles we have just created. This function is generic, so you can use it to sort any type you desire, as long as you provide a proper `isOrderedBefore` closure to compare the elements. @@ -237,15 +237,15 @@ mergeSortBottomUp(array, <) // [1, 2, 4, 5, 9] ## Performance -The speed of merge sort is dependent on the size of the array it needs to sort. The larger the array, the more work it needs to do. +The speed of the merge-sort algorithm is dependent on the size of the array it needs to sort. The larger the array, the more work it needs to do. -Whether or not the initial array is sorted already doesn't affect the speed of merge sort since you'll be doing the same amount splits and comparisons regardless of the initial order of the elements. +Whether or not the initial array is sorted already doesnot affect the speed of the merge-sort algorithm since you will be doing the same amount splits and comparisons regardless of the initial order of the elements. Therefore, the time complexity for the best, worst, and average case will always be **O(n log n)**. -A disadvantage of merge sort is that it needs a temporary "working" array equal in size to the array being sorted. It is not an **in-place** sort, unlike for example [quicksort](../Quicksort/). +A disadvantage of the merge-sort algorithm is that it needs a temporary "working" array equal in size to the array being sorted. It is not an **in-place** sort, unlike for example [quicksort](../Quicksort/). -Most implementations of merge sort produce a **stable** sort. This means that array elements that have identical sort keys will stay in the same order relative to each other after sorting. This is not important for simple values such as numbers or strings, but it can be an issue when sorting more complex objects. +Most implementations of the merge-sort algorithm produce a **stable** sort. This means that array elements that have identical sort keys will stay in the same order relative to each other after sorting. This is not important for simple values such as numbers or strings, but it can be an issue when sorting more complex objects. ## See also From b99c037c861f295f63470d394a66b2dcaed40303 Mon Sep 17 00:00:00 2001 From: Keizar Date: Fri, 3 Feb 2017 13:20:07 -0800 Subject: [PATCH 0802/1679] update README.markdown --- Bubble Sort/README.markdown | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Bubble Sort/README.markdown b/Bubble Sort/README.markdown index ceb2a98cb..93d370827 100644 --- a/Bubble Sort/README.markdown +++ b/Bubble Sort/README.markdown @@ -1,14 +1,14 @@ # Bubble Sort -Bubble sort is a sorting algorithm that is implemented by starting in the beginning of the array and swapping the first two elements only if the first element is greater than the second element. This comparison is then moved onto the next pair and so on and so forth. This is done until the the array is completely sorted. The smaller items slowly “bubble” up to the beginning of the array. +Bubble sort is a sorting algorithm that is implemented by starting in the beginning of the array and swapping the first two elements only if the first element is greater than the second element. This comparison is then moved onto the next pair and so on and so forth. This is done until the array is completely sorted. The smaller items slowly “bubble” up to the beginning of the array. ##### Runtime: -- Average: O(N^2) +- Average: O(N^2) - Worst: O(N^2) -##### Memory: +##### Memory: - O(1) ### Implementation: -The implementation will not be shown because as you can see from the average and worst runtimes this is a very inefficient algorithm but having a grasp of the concept will help in getting to know the basics of simple sorting algorithms. +The implementation will not be shown as the average and worst runtimes show that this is a very inefficient algorithm. However, having a grasp of the concept will help you understand the basics of simple sorting algorithms. From c22799378133820468783a1699be31d13c0f9d29 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Sat, 4 Feb 2017 18:22:06 +0800 Subject: [PATCH 0803/1679] left/right tree should reconnect to new node --- .../Sources/BinarySearchTree.swift | 8 +- .../Tests/BinarySearchTreeTests.swift | 87 ++++++++++--------- .../Tests/Tests.xcodeproj/project.pbxproj | 5 +- .../xcshareddata/WorkspaceSettings.xcsettings | 8 ++ 4 files changed, 61 insertions(+), 47 deletions(-) create mode 100644 Binary Search Tree/Solution 1/Tests/Tests.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings diff --git a/Binary Search Tree/Solution 1/BinarySearchTree.playground/Sources/BinarySearchTree.swift b/Binary Search Tree/Solution 1/BinarySearchTree.playground/Sources/BinarySearchTree.swift index 31ae99a2f..74399efef 100644 --- a/Binary Search Tree/Solution 1/BinarySearchTree.playground/Sources/BinarySearchTree.swift +++ b/Binary Search Tree/Solution 1/BinarySearchTree.playground/Sources/BinarySearchTree.swift @@ -109,10 +109,10 @@ extension BinarySearchTree { // Replacement for current node can be either biggest one on the left or // smallest one on the right, whichever is not nil - if let left = left { - replacement = left.maximum() - } else if let right = right { + if let right = right { replacement = right.minimum() + } else if let left = left { + replacement = left.maximum() } else { replacement = nil; } @@ -122,6 +122,8 @@ extension BinarySearchTree { // Place the replacement on current node's position replacement?.right = right; replacement?.left = left; + right?.parent = replacement + left?.parent = replacement reconnectParentTo(node:replacement); // The current node is no longer part of the tree, so clean it up. diff --git a/Binary Search Tree/Solution 1/Tests/BinarySearchTreeTests.swift b/Binary Search Tree/Solution 1/Tests/BinarySearchTreeTests.swift index 7c7fd069b..30749d8e4 100755 --- a/Binary Search Tree/Solution 1/Tests/BinarySearchTreeTests.swift +++ b/Binary Search Tree/Solution 1/Tests/BinarySearchTreeTests.swift @@ -17,8 +17,8 @@ class BinarySearchTreeTest: XCTestCase { XCTAssertEqual(tree.count, 8) XCTAssertEqual(tree.toArray(), [3, 5, 6, 8, 9, 10, 12, 16]) - XCTAssertEqual(tree.search(9)!.value, 9) - XCTAssertNil(tree.search(99)) + XCTAssertEqual(tree.search(value: 9)!.value, 9) + XCTAssertNil(tree.search(value: 99)) XCTAssertEqual(tree.minimum().value, 3) XCTAssertEqual(tree.maximum().value, 16) @@ -26,17 +26,17 @@ class BinarySearchTreeTest: XCTestCase { XCTAssertEqual(tree.height(), 3) XCTAssertEqual(tree.depth(), 0) - let node1 = tree.search(16) + let node1 = tree.search(value: 16) XCTAssertNotNil(node1) XCTAssertEqual(node1!.height(), 0) XCTAssertEqual(node1!.depth(), 3) - let node2 = tree.search(12) + let node2 = tree.search(value: 12) XCTAssertNotNil(node2) XCTAssertEqual(node2!.height(), 1) XCTAssertEqual(node2!.depth(), 2) - let node3 = tree.search(10) + let node3 = tree.search(value: 10) XCTAssertNotNil(node3) XCTAssertEqual(node3!.height(), 2) XCTAssertEqual(node3!.depth(), 1) @@ -45,32 +45,32 @@ class BinarySearchTreeTest: XCTestCase { func testInsert() { let tree = BinarySearchTree(value: 8) - tree.insert(5) + tree.insert(value: 5) XCTAssertEqual(tree.count, 2) XCTAssertEqual(tree.height(), 1) XCTAssertEqual(tree.depth(), 0) - let node1 = tree.search(5) + let node1 = tree.search(value: 5) XCTAssertNotNil(node1) XCTAssertEqual(node1!.height(), 0) XCTAssertEqual(node1!.depth(), 1) - tree.insert(10) + tree.insert(value: 10) XCTAssertEqual(tree.count, 3) XCTAssertEqual(tree.height(), 1) XCTAssertEqual(tree.depth(), 0) - let node2 = tree.search(10) + let node2 = tree.search(value: 10) XCTAssertNotNil(node2) XCTAssertEqual(node2!.height(), 0) XCTAssertEqual(node2!.depth(), 1) - tree.insert(3) + tree.insert(value: 3) XCTAssertEqual(tree.count, 4) XCTAssertEqual(tree.height(), 2) XCTAssertEqual(tree.depth(), 0) - let node3 = tree.search(3) + let node3 = tree.search(value: 3) XCTAssertNotNil(node3) XCTAssertEqual(node3!.height(), 0) XCTAssertEqual(node3!.depth(), 2) @@ -84,9 +84,9 @@ class BinarySearchTreeTest: XCTestCase { func testInsertDuplicates() { let tree = BinarySearchTree(array: [8, 5, 10]) - tree.insert(8) - tree.insert(5) - tree.insert(10) + tree.insert(value: 8) + tree.insert(value: 5) + tree.insert(value: 10) XCTAssertEqual(tree.count, 6) XCTAssertEqual(tree.toArray(), [5, 5, 8, 8, 10, 10]) } @@ -108,7 +108,7 @@ class BinarySearchTreeTest: XCTestCase { } func testInsertSorted() { - let tree = BinarySearchTree(array: [8, 5, 10, 3, 12, 9, 6, 16].sort(<)) + let tree = BinarySearchTree(array: [8, 5, 10, 3, 12, 9, 6, 16].sorted(by: <)) XCTAssertEqual(tree.count, 8) XCTAssertEqual(tree.toArray(), [3, 5, 6, 8, 9, 10, 12, 16]) @@ -118,7 +118,7 @@ class BinarySearchTreeTest: XCTestCase { XCTAssertEqual(tree.height(), 7) XCTAssertEqual(tree.depth(), 0) - let node1 = tree.search(16) + let node1 = tree.search(value: 16) XCTAssertNotNil(node1) XCTAssertEqual(node1!.height(), 0) XCTAssertEqual(node1!.depth(), 7) @@ -127,15 +127,15 @@ class BinarySearchTreeTest: XCTestCase { func testRemoveLeaf() { let tree = BinarySearchTree(array: [8, 5, 10, 4]) - let node10 = tree.search(10)! + let node10 = tree.search(value: 10)! XCTAssertNil(node10.left) XCTAssertNil(node10.right) XCTAssertTrue(tree.right === node10) - let node5 = tree.search(5)! + let node5 = tree.search(value: 5)! XCTAssertTrue(tree.left === node5) - let node4 = tree.search(4)! + let node4 = tree.search(value: 4)! XCTAssertTrue(node5.left === node4) XCTAssertNil(node5.right) @@ -158,8 +158,8 @@ class BinarySearchTreeTest: XCTestCase { func testRemoveOneChildLeft() { let tree = BinarySearchTree(array: [8, 5, 10, 4, 9]) - let node4 = tree.search(4)! - let node5 = tree.search(5)! + let node4 = tree.search(value: 4)! + let node5 = tree.search(value: 5)! XCTAssertTrue(node5.left === node4) XCTAssertTrue(node5 === node4.parent) @@ -171,8 +171,8 @@ class BinarySearchTreeTest: XCTestCase { XCTAssertEqual(tree.count, 4) XCTAssertEqual(tree.toArray(), [4, 8, 9, 10]) - let node9 = tree.search(9)! - let node10 = tree.search(10)! + let node9 = tree.search(value: 9)! + let node10 = tree.search(value: 10)! XCTAssertTrue(node10.left === node9) XCTAssertTrue(node10 === node9.parent) @@ -188,8 +188,8 @@ class BinarySearchTreeTest: XCTestCase { func testRemoveOneChildRight() { let tree = BinarySearchTree(array: [8, 5, 10, 6, 11]) - let node6 = tree.search(6)! - let node5 = tree.search(5)! + let node6 = tree.search(value: 6)! + let node5 = tree.search(value: 5)! XCTAssertTrue(node5.right === node6) XCTAssertTrue(node5 === node6.parent) @@ -201,8 +201,8 @@ class BinarySearchTreeTest: XCTestCase { XCTAssertEqual(tree.count, 4) XCTAssertEqual(tree.toArray(), [6, 8, 10, 11]) - let node11 = tree.search(11)! - let node10 = tree.search(10)! + let node11 = tree.search(value: 11)! + let node10 = tree.search(value: 10)! XCTAssertTrue(node10.right === node11) XCTAssertTrue(node10 === node11.parent) @@ -218,9 +218,9 @@ class BinarySearchTreeTest: XCTestCase { func testRemoveTwoChildrenSimple() { let tree = BinarySearchTree(array: [8, 5, 10, 4, 6, 9, 11]) - let node4 = tree.search(4)! - let node5 = tree.search(5)! - let node6 = tree.search(6)! + let node4 = tree.search(value: 4)! + let node5 = tree.search(value: 5)! + let node6 = tree.search(value: 6)! XCTAssertTrue(node5.left === node4) XCTAssertTrue(node5.right === node6) XCTAssertTrue(node5 === node4.parent) @@ -241,9 +241,9 @@ class BinarySearchTreeTest: XCTestCase { XCTAssertEqual(tree.count, 6) XCTAssertEqual(tree.toArray(), [4, 6, 8, 9, 10, 11]) - let node9 = tree.search(9)! - let node10 = tree.search(10)! - let node11 = tree.search(11)! + let node9 = tree.search(value: 9)! + let node10 = tree.search(value: 10)! + let node11 = tree.search(value: 11)! XCTAssertTrue(node10.left === node9) XCTAssertTrue(node10.right === node11) XCTAssertTrue(node10 === node9.parent) @@ -268,11 +268,12 @@ class BinarySearchTreeTest: XCTestCase { func testRemoveTwoChildrenComplex() { let tree = BinarySearchTree(array: [8, 5, 10, 4, 9, 20, 11, 15, 13]) - let node9 = tree.search(9)! - let node10 = tree.search(10)! - let node11 = tree.search(11)! - let node15 = tree.search(15)! - let node20 = tree.search(20)! + let node9 = tree.search(value: 9)! + let node10 = tree.search(value: 10)! + let node11 = tree.search(value: 11)! + let node13 = tree.search(value: 13)! + let node15 = tree.search(value: 15)! + let node20 = tree.search(value: 20)! XCTAssertTrue(node10.left === node9) XCTAssertTrue(node10 === node9.parent) XCTAssertTrue(node10.right === node20) @@ -290,8 +291,8 @@ class BinarySearchTreeTest: XCTestCase { XCTAssertTrue(node11 === node9.parent) XCTAssertTrue(node11.right === node20) XCTAssertTrue(node11 === node20.parent) - XCTAssertTrue(node20.left === node15) - XCTAssertTrue(node20 === node15.parent) + XCTAssertTrue(node20.left === node13) + XCTAssertTrue(node20 === node13.parent) XCTAssertNil(node20.right) XCTAssertNil(node10.left) XCTAssertNil(node10.right) @@ -303,7 +304,7 @@ class BinarySearchTreeTest: XCTestCase { func testRemoveRoot() { let tree = BinarySearchTree(array: [8, 5, 10, 4, 9, 20, 11, 15, 13]) - let node9 = tree.search(9)! + let node9 = tree.search(value: 9)! let newRoot = tree.remove() XCTAssertTrue(newRoot === node9) @@ -319,7 +320,7 @@ class BinarySearchTreeTest: XCTestCase { func testPredecessor() { let tree = BinarySearchTree(array: [3, 1, 2, 5, 4]) - let node = tree.search(5) + let node = tree.search(value: 5) XCTAssertEqual(node!.value, 5) XCTAssertEqual(node!.predecessor()!.value, 4) @@ -331,7 +332,7 @@ class BinarySearchTreeTest: XCTestCase { func testSuccessor() { let tree = BinarySearchTree(array: [3, 1, 2, 5, 4]) - let node = tree.search(1) + let node = tree.search(value: 1) XCTAssertEqual(node!.value, 1) XCTAssertEqual(node!.successor()!.value, 2) diff --git a/Binary Search Tree/Solution 1/Tests/Tests.xcodeproj/project.pbxproj b/Binary Search Tree/Solution 1/Tests/Tests.xcodeproj/project.pbxproj index 7ecfe593f..f4c3f65c7 100644 --- a/Binary Search Tree/Solution 1/Tests/Tests.xcodeproj/project.pbxproj +++ b/Binary Search Tree/Solution 1/Tests/Tests.xcodeproj/project.pbxproj @@ -15,7 +15,7 @@ 7B2BBC801C779D720067B71D /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 7B2BBC941C779E7B0067B71D /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; 7B80C3D91C77A323003CECC7 /* BinarySearchTreeTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BinarySearchTreeTests.swift; sourceTree = SOURCE_ROOT; }; - 9E5A58B81E304C3100DAB3BB /* BinarySearchTree.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BinarySearchTree.swift; path = ../BinarySearchTree.playground/Sources/BinarySearchTree.swift; sourceTree = ""; }; + 9E5A58B81E304C3100DAB3BB /* BinarySearchTree.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BinarySearchTree.swift; path = ../BinarySearchTree.playground/Sources/BinarySearchTree.swift; sourceTree = SOURCE_ROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -88,6 +88,7 @@ TargetAttributes = { 7B2BBC7F1C779D720067B71D = { CreatedOnToolsVersion = 7.2; + LastSwiftMigration = 0820; }; }; }; @@ -220,6 +221,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -231,6 +233,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Release; }; diff --git a/Binary Search Tree/Solution 1/Tests/Tests.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/Binary Search Tree/Solution 1/Tests/Tests.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 000000000..08de0be8d --- /dev/null +++ b/Binary Search Tree/Solution 1/Tests/Tests.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded + + + From eef96f6431477e31598e884a72d3178c9b06e8f6 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Sat, 4 Feb 2017 17:59:53 +0800 Subject: [PATCH 0804/1679] unmark .travis.yml test for BinarySearchTree --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 80ced8b6c..2b2bafd14 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,7 +13,7 @@ script: - xcodebuild test -project ./AVL\ Tree/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Binary\ Search/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Boyer-Moore/Tests/Tests.xcodeproj -scheme Tests -# - xcodebuild test -project ./Binary\ Search\ Tree/Solution\ 1/Tests/Tests.xcodeproj -scheme Tests +- xcodebuild test -project ./Binary\ Search\ Tree/Solution\ 1/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Bloom\ Filter/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Bounded\ Priority\ Queue/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Breadth-First\ Search/Tests/Tests.xcodeproj -scheme Tests From 78da2c7b4719f55faaa69f2ae0c0324eb3423db0 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Sat, 4 Feb 2017 17:36:46 +0800 Subject: [PATCH 0805/1679] lint files --- .../Sources/BinarySearchTree.swift | 24 +++++++++---------- .../Contents.swift | 2 -- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/Binary Search Tree/Solution 1/BinarySearchTree.playground/Sources/BinarySearchTree.swift b/Binary Search Tree/Solution 1/BinarySearchTree.playground/Sources/BinarySearchTree.swift index 74399efef..8a126e950 100644 --- a/Binary Search Tree/Solution 1/BinarySearchTree.playground/Sources/BinarySearchTree.swift +++ b/Binary Search Tree/Solution 1/BinarySearchTree.playground/Sources/BinarySearchTree.swift @@ -22,7 +22,7 @@ public class BinarySearchTree { public convenience init(array: [T]) { precondition(array.count > 0) self.init(value: array.first!) - for v in array.dropFirst() { + for v in array.dropFirst() { insert(value: v) } } @@ -106,7 +106,7 @@ extension BinarySearchTree { */ @discardableResult public func remove() -> BinarySearchTree? { let replacement: BinarySearchTree? - + // Replacement for current node can be either biggest one on the left or // smallest one on the right, whichever is not nil if let right = right { @@ -114,24 +114,24 @@ extension BinarySearchTree { } else if let left = left { replacement = left.maximum() } else { - replacement = nil; + replacement = nil } - - replacement?.remove(); + + replacement?.remove() // Place the replacement on current node's position - replacement?.right = right; - replacement?.left = left; + replacement?.right = right + replacement?.left = left right?.parent = replacement left?.parent = replacement - reconnectParentTo(node:replacement); - + reconnectParentTo(node:replacement) + // The current node is no longer part of the tree, so clean it up. parent = nil left = nil right = nil - - return replacement; + + return replacement } private func reconnectParentTo(node: BinarySearchTree?) { @@ -324,7 +324,7 @@ extension BinarySearchTree: CustomStringConvertible { } return s } - + public func toArray() -> [T] { return map { $0 } } diff --git a/Binary Search Tree/Solution 2/BinarySearchTree.playground/Contents.swift b/Binary Search Tree/Solution 2/BinarySearchTree.playground/Contents.swift index 8df69fb6a..2b5dcc341 100644 --- a/Binary Search Tree/Solution 2/BinarySearchTree.playground/Contents.swift +++ b/Binary Search Tree/Solution 2/BinarySearchTree.playground/Contents.swift @@ -12,5 +12,3 @@ print(tree) tree.search(x: 10) tree.search(x: 1) tree.search(x: 11) - - From f47a45e967ec651b6091f1d81a352f15420fd564 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Sat, 4 Feb 2017 17:56:24 +0800 Subject: [PATCH 0806/1679] Update README.markdown --- Binary Search Tree/README.markdown | 75 ++++++++++++++++-------------- 1 file changed, 39 insertions(+), 36 deletions(-) diff --git a/Binary Search Tree/README.markdown b/Binary Search Tree/README.markdown index e8d2f58e2..bd2a00c9e 100644 --- a/Binary Search Tree/README.markdown +++ b/Binary Search Tree/README.markdown @@ -58,7 +58,7 @@ Sometimes you don't want to look at just a single node, but at all of them. There are three ways to traverse a binary tree: 1. *In-order* (or *depth-first*): first look at the left child of a node, then at the node itself, and finally at its right child. -2. *Pre-order*: first look at a node, then its left and right children. +2. *Pre-order*: first look at a node, then its left and right children. 3. *Post-order*: first look at the left and right children and process the node itself last. Once again, this happens recursively. @@ -133,7 +133,7 @@ public class BinarySearchTree { } ``` -This class describes just a single node, not the entire tree. It's a generic type, so the node can store any kind of data. It also has references to its `left` and `right` child nodes and a `parent` node. +This class describes just a single node, not the entire tree. It's a generic type, so the node can store any kind of data. It also has references to its `left` and `right` child nodes and a `parent` node. Here's how you'd use it: @@ -258,7 +258,7 @@ Here is the implementation of `search()`: I hope the logic is clear: this starts at the current node (usually the root) and compares the values. If the search value is less than the node's value, we continue searching in the left branch; if the search value is greater, we dive into the right branch. -Of course, if there are no more nodes to look at -- when `left` or `right` is nil -- then we return `nil` to indicate the search value is not in the tree. +Of course, if there are no more nodes to look at -- when `left` or `right` is nil -- then we return `nil` to indicate the search value is not in the tree. > **Note:** In Swift that's very conveniently done with optional chaining; when you write `left?.search(value)` it automatically returns nil if `left` is nil. There's no need to explicitly check for this with an `if` statement. @@ -300,21 +300,21 @@ The first three lines all return the corresponding `BinaryTreeNode` object. The Remember there are 3 different ways to look at all nodes in the tree? Here they are: ```swift - public func traverseInOrder(@noescape process: T -> Void) { - left?.traverseInOrder(process) + public func traverseInOrder(process: (T) -> Void) { + left?.traverseInOrder(process: process) process(value) - right?.traverseInOrder(process) + right?.traverseInOrder(process: process) } - - public func traversePreOrder(@noescape process: T -> Void) { + + public func traversePreOrder(process: (T) -> Void) { process(value) - left?.traversePreOrder(process) - right?.traversePreOrder(process) + left?.traversePreOrder(process: process) + right?.traversePreOrder(process: process) } - - public func traversePostOrder(@noescape process: T -> Void) { - left?.traversePostOrder(process) - right?.traversePostOrder(process) + + public func traversePostOrder(process: (T) -> Void) { + left?.traversePostOrder(process: process) + right?.traversePostOrder(process: process) process(value) } ``` @@ -339,11 +339,12 @@ This prints the following: You can also add things like `map()` and `filter()` to the tree. For example, here's an implementation of map: ```swift - public func map(@noescape formula: T -> T) -> [T] { + + public func map(formula: (T) -> T) -> [T] { var a = [T]() - if let left = left { a += left.map(formula) } + if let left = left { a += left.map(formula: formula) } a.append(formula(value)) - if let right = right { a += right.map(formula) } + if let right = right { a += right.map(formula: formula) } return a } ``` @@ -365,7 +366,7 @@ tree.toArray() // [1, 2, 5, 7, 9, 10] ``` As an exercise for yourself, see if you can implement filter and reduce. - + ### Deleting nodes We can make the code much more readable by defining some helper functions. @@ -395,7 +396,7 @@ We also need a function that returns the minimum and maximum of a node: } return node } - + public func maximum() -> BinarySearchTree { var node = self while case let next? = node.right { @@ -411,30 +412,32 @@ The rest of the code is pretty self-explanatory: ```swift @discardableResult public func remove() -> BinarySearchTree? { let replacement: BinarySearchTree? - + // Replacement for current node can be either biggest one on the left or // smallest one on the right, whichever is not nil - if let left = left { - replacement = left.maximum() - } else if let right = right { + if let right = right { replacement = right.minimum() + } else if let left = left { + replacement = left.maximum() } else { - replacement = nil; + replacement = nil } - - replacement?.remove(); + + replacement?.remove() // Place the replacement on current node's position - replacement?.right = right; - replacement?.left = left; - reconnectParentTo(node:replacement); - + replacement?.right = right + replacement?.left = left + right?.parent = replacement + left?.parent = replacement + reconnectParentTo(node:replacement) + // The current node is no longer part of the tree, so clean it up. parent = nil left = nil right = nil - - return replacement; + + return replacement } ``` @@ -574,7 +577,7 @@ if let node1 = tree.search(1) { ## The code (solution 2) -We've implemented the binary tree node as a class but you can also use an enum. +We've implemented the binary tree node as a class but you can also use an enum. The difference is reference semantics versus value semantics. Making a change to the class-based tree will update that same instance in memory. But the enum-based tree is immutable -- any insertions or deletions will give you an entirely new copy of the tree. Which one is best totally depends on what you want to use it for. @@ -588,7 +591,7 @@ public enum BinarySearchTree { } ``` -The enum has three cases: +The enum has three cases: - `Empty` to mark the end of a branch (the class-based version used `nil` references for this). - `Leaf` for a leaf node that has no children. @@ -606,7 +609,7 @@ As usual, we'll implement most functionality recursively. We'll treat each case case let .Node(left, _, right): return left.count + 1 + right.count } } - + public var height: Int { switch self { case .Empty: return 0 @@ -623,7 +626,7 @@ Inserting new nodes looks like this: switch self { case .Empty: return .Leaf(newValue) - + case .Leaf(let value): if newValue < value { return .Node(.Leaf(newValue), value, .Empty) From 257e973125884983b42193d7e67d1a6155081b4c Mon Sep 17 00:00:00 2001 From: Julio Guzman Date: Mon, 6 Feb 2017 16:32:26 -0600 Subject: [PATCH 0807/1679] Change last upgrade version --- .../Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Breadth-First Search/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Breadth-First Search/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme index 8ef8d8581..dfcf6de42 100644 --- a/Breadth-First Search/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme +++ b/Breadth-First Search/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -1,6 +1,6 @@ Date: Mon, 6 Feb 2017 16:32:42 -0600 Subject: [PATCH 0808/1679] Change last upgrade check --- Breadth-First Search/Tests/Tests.xcodeproj/project.pbxproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Breadth-First Search/Tests/Tests.xcodeproj/project.pbxproj b/Breadth-First Search/Tests/Tests.xcodeproj/project.pbxproj index 33be43391..a04c95170 100644 --- a/Breadth-First Search/Tests/Tests.xcodeproj/project.pbxproj +++ b/Breadth-First Search/Tests/Tests.xcodeproj/project.pbxproj @@ -89,7 +89,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; - LastUpgradeCheck = 0720; + LastUpgradeCheck = 0820; ORGANIZATIONNAME = "Swift Algorithm Club"; TargetAttributes = { 7B2BBC7F1C779D720067B71D = { From c8ce274329483d25f8e3ddfb3917419dad7eb9b0 Mon Sep 17 00:00:00 2001 From: Julio Guzman Date: Mon, 6 Feb 2017 16:40:38 -0600 Subject: [PATCH 0809/1679] Add assignation to remove warning --- Breadth-First Search/Tests/Graph.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Breadth-First Search/Tests/Graph.swift b/Breadth-First Search/Tests/Graph.swift index ed71cab7c..09684da5b 100644 --- a/Breadth-First Search/Tests/Graph.swift +++ b/Breadth-First Search/Tests/Graph.swift @@ -86,7 +86,7 @@ public class Graph: CustomStringConvertible, Equatable { let duplicated = Graph() for node in nodes { - duplicated.addNode(node.label) + let _ = duplicated.addNode(node.label) } for node in nodes { From e0a3b634d087a3376ba2f2478effd872cbe800f1 Mon Sep 17 00:00:00 2001 From: Julio Guzman Date: Mon, 6 Feb 2017 16:51:01 -0600 Subject: [PATCH 0810/1679] Migrates Breadth First Search tests project to Swift 3 syntax --- Breadth-First Search/Tests/Graph.swift | 8 ++++---- Breadth-First Search/Tests/Queue.swift | 2 +- .../Tests/Tests.xcodeproj/project.pbxproj | 3 +++ 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/Breadth-First Search/Tests/Graph.swift b/Breadth-First Search/Tests/Graph.swift index 09684da5b..5e0837160 100644 --- a/Breadth-First Search/Tests/Graph.swift +++ b/Breadth-First Search/Tests/Graph.swift @@ -39,7 +39,7 @@ public class Node: CustomStringConvertible, Equatable { } public func remove(edge: Edge) { - neighbors.removeAtIndex(neighbors.indexOf { $0 === edge }!) + neighbors.remove(at: neighbors.index { $0 === edge }!) } } @@ -56,13 +56,13 @@ public class Graph: CustomStringConvertible, Equatable { self.nodes = [] } - public func addNode(label: String) -> Node { + public func addNode(_ label: String) -> Node { let node = Node(label: label) nodes.append(node) return node } - public func addEdge(source: Node, neighbor: Node) { + public func addEdge(_ source: Node, neighbor: Node) { let edge = Edge(neighbor: neighbor) source.neighbors.append(edge) } @@ -78,7 +78,7 @@ public class Graph: CustomStringConvertible, Equatable { return description } - public func findNodeWithLabel(label: String) -> Node { + public func findNodeWithLabel(_ label: String) -> Node { return nodes.filter { $0.label == label }.first! } diff --git a/Breadth-First Search/Tests/Queue.swift b/Breadth-First Search/Tests/Queue.swift index bf462bbdd..3d98f801c 100644 --- a/Breadth-First Search/Tests/Queue.swift +++ b/Breadth-First Search/Tests/Queue.swift @@ -13,7 +13,7 @@ public struct Queue { return array.count } - public mutating func enqueue(element: T) { + public mutating func enqueue(_ element: T) { array.append(element) } diff --git a/Breadth-First Search/Tests/Tests.xcodeproj/project.pbxproj b/Breadth-First Search/Tests/Tests.xcodeproj/project.pbxproj index a04c95170..f86abf86e 100644 --- a/Breadth-First Search/Tests/Tests.xcodeproj/project.pbxproj +++ b/Breadth-First Search/Tests/Tests.xcodeproj/project.pbxproj @@ -94,6 +94,7 @@ TargetAttributes = { 7B2BBC7F1C779D720067B71D = { CreatedOnToolsVersion = 7.2; + LastSwiftMigration = 0820; }; }; }; @@ -230,6 +231,7 @@ PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -242,6 +244,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Release; }; From ca8e7ff4be86d94c8f5fea31d50a74896362b0dc Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Mon, 6 Feb 2017 17:26:07 -0800 Subject: [PATCH 0811/1679] Fixed spacing. --- .../ShuntingYard.playground/Contents.swift | 174 ++++----- Shunting Yard/ShuntingYard.swift | 366 +++++++++--------- 2 files changed, 270 insertions(+), 270 deletions(-) diff --git a/Shunting Yard/ShuntingYard.playground/Contents.swift b/Shunting Yard/ShuntingYard.playground/Contents.swift index b341c673b..fa9f5745b 100644 --- a/Shunting Yard/ShuntingYard.playground/Contents.swift +++ b/Shunting Yard/ShuntingYard.playground/Contents.swift @@ -12,21 +12,21 @@ public enum OperatorType: CustomStringConvertible { case multiply case percent case exponent - + public var description: String { switch self { - case .add: - return "+" - case .subtract: - return "-" - case .divide: - return "/" - case .multiply: - return "*" - case .percent: - return "%" - case .exponent: - return "^" + case .add: + return "+" + case .subtract: + return "-" + case .divide: + return "/" + case .multiply: + return "*" + case .percent: + return "%" + case .exponent: + return "^" } } } @@ -36,48 +36,48 @@ public enum TokenType: CustomStringConvertible { case closeBracket case Operator(OperatorToken) case operand(Double) - + public var description: String { switch self { - case .openBracket: - return "(" - case .closeBracket: - return ")" - case .Operator(let operatorToken): - return operatorToken.description - case .operand(let value): - return "\(value)" + case .openBracket: + return "(" + case .closeBracket: + return ")" + case .Operator(let operatorToken): + return operatorToken.description + case .operand(let value): + return "\(value)" } } } public struct OperatorToken: CustomStringConvertible { let operatorType: OperatorType - + init(operatorType: OperatorType) { self.operatorType = operatorType } - + var precedence: Int { switch operatorType { - case .add, .subtract: - return 0 - case .divide, .multiply, .percent: - return 5 - case .exponent: - return 10 + case .add, .subtract: + return 0 + case .divide, .multiply, .percent: + return 5 + case .exponent: + return 10 } } - + var associativity: OperatorAssociativity { switch operatorType { - case .add, .subtract, .divide, .multiply, .percent: - return .leftAssociative - case .exponent: - return .rightAssociative + case .add, .subtract, .divide, .multiply, .percent: + return .leftAssociative + case .exponent: + return .rightAssociative } } - + public var description: String { return operatorType.description } @@ -93,46 +93,46 @@ func < (left: OperatorToken, right: OperatorToken) -> Bool { public struct Token: CustomStringConvertible { let tokenType: TokenType - + init(tokenType: TokenType) { self.tokenType = tokenType } - + init(operand: Double) { tokenType = .operand(operand) } - + init(operatorType: OperatorType) { tokenType = .Operator(OperatorToken(operatorType: operatorType)) } - + var isOpenBracket: Bool { switch tokenType { - case .openBracket: - return true - default: - return false + case .openBracket: + return true + default: + return false } } - + var isOperator: Bool { switch tokenType { - case .Operator(_): - return true - default: - return false + case .Operator(_): + return true + default: + return false } } - + var operatorToken: OperatorToken? { switch tokenType { - case .Operator(let operatorToken): - return operatorToken - default: - return nil + case .Operator(let operatorToken): + return operatorToken + default: + return nil } } - + public var description: String { return tokenType.description } @@ -140,27 +140,27 @@ public struct Token: CustomStringConvertible { public class InfixExpressionBuilder { private var expression = [Token]() - + public func addOperator(_ operatorType: OperatorType) -> InfixExpressionBuilder { expression.append(Token(operatorType: operatorType)) return self } - + public func addOperand(_ operand: Double) -> InfixExpressionBuilder { expression.append(Token(operand: operand)) return self } - + public func addOpenBracket() -> InfixExpressionBuilder { expression.append(Token(tokenType: .openBracket)) return self } - + public func addCloseBracket() -> InfixExpressionBuilder { expression.append(Token(tokenType: .closeBracket)) return self } - + public func build() -> [Token] { // Maybe do some validation here return expression @@ -169,46 +169,46 @@ public class InfixExpressionBuilder { // This returns the result of the shunting yard algorithm public func reversePolishNotation(_ expression: [Token]) -> String { - + var tokenStack = Stack() var reversePolishNotation = [Token]() - + for token in expression { switch token.tokenType { - case .operand(_): - reversePolishNotation.append(token) - - case .openBracket: - tokenStack.push(token) - - case .closeBracket: - while tokenStack.count > 0, let tempToken = tokenStack.pop(), !tempToken.isOpenBracket { - reversePolishNotation.append(tempToken) + case .operand(_): + reversePolishNotation.append(token) + + case .openBracket: + tokenStack.push(token) + + case .closeBracket: + while tokenStack.count > 0, let tempToken = tokenStack.pop(), !tempToken.isOpenBracket { + reversePolishNotation.append(tempToken) + } + + case .Operator(let operatorToken): + for tempToken in tokenStack.makeIterator() { + if !tempToken.isOperator { + break } - - case .Operator(let operatorToken): - for tempToken in tokenStack.makeIterator() { - if !tempToken.isOperator { + + if let tempOperatorToken = tempToken.operatorToken { + if operatorToken.associativity == .leftAssociative && operatorToken <= tempOperatorToken + || operatorToken.associativity == .rightAssociative && operatorToken < tempOperatorToken { + reversePolishNotation.append(tokenStack.pop()!) + } else { break } - - if let tempOperatorToken = tempToken.operatorToken { - if operatorToken.associativity == .leftAssociative && operatorToken <= tempOperatorToken - || operatorToken.associativity == .rightAssociative && operatorToken < tempOperatorToken { - reversePolishNotation.append(tokenStack.pop()!) - } else { - break - } - } } - tokenStack.push(token) + } + tokenStack.push(token) } } - + while tokenStack.count > 0 { reversePolishNotation.append(tokenStack.pop()!) } - + return reversePolishNotation.map({token in token.description}).joined(separator: " ") } diff --git a/Shunting Yard/ShuntingYard.swift b/Shunting Yard/ShuntingYard.swift index b8f5f8e6b..97a72249d 100644 --- a/Shunting Yard/ShuntingYard.swift +++ b/Shunting Yard/ShuntingYard.swift @@ -7,213 +7,213 @@ // internal enum OperatorAssociativity { - case leftAssociative - case rightAssociative + case leftAssociative + case rightAssociative } public enum OperatorType: CustomStringConvertible { - case add - case subtract - case divide - case multiply - case percent - case exponent - - public var description: String { - switch self { - case .add: - return "+" - case .subtract: - return "-" - case .divide: - return "/" - case .multiply: - return "*" - case .percent: - return "%" - case .exponent: - return "^" - } - } + case add + case subtract + case divide + case multiply + case percent + case exponent + + public var description: String { + switch self { + case .add: + return "+" + case .subtract: + return "-" + case .divide: + return "/" + case .multiply: + return "*" + case .percent: + return "%" + case .exponent: + return "^" + } + } } public enum TokenType: CustomStringConvertible { - case openBracket - case closeBracket - case Operator(OperatorToken) - case operand(Double) - - public var description: String { - switch self { - case .openBracket: - return "(" - case .closeBracket: - return ")" - case .Operator(let operatorToken): - return operatorToken.description - case .operand(let value): - return "\(value)" - } - } + case openBracket + case closeBracket + case Operator(OperatorToken) + case operand(Double) + + public var description: String { + switch self { + case .openBracket: + return "(" + case .closeBracket: + return ")" + case .Operator(let operatorToken): + return operatorToken.description + case .operand(let value): + return "\(value)" + } + } } public struct OperatorToken: CustomStringConvertible { - let operatorType: OperatorType - - init(operatorType: OperatorType) { - self.operatorType = operatorType - } - - var precedence: Int { - switch operatorType { - case .add, .subtract: - return 0 - case .divide, .multiply, .percent: - return 5 - case .exponent: - return 10 - } - } - - var associativity: OperatorAssociativity { - switch operatorType { - case .add, .subtract, .divide, .multiply, .percent: - return .leftAssociative - case .exponent: - return .rightAssociative - } - } - - public var description: String { - return operatorType.description - } + let operatorType: OperatorType + + init(operatorType: OperatorType) { + self.operatorType = operatorType + } + + var precedence: Int { + switch operatorType { + case .add, .subtract: + return 0 + case .divide, .multiply, .percent: + return 5 + case .exponent: + return 10 + } + } + + var associativity: OperatorAssociativity { + switch operatorType { + case .add, .subtract, .divide, .multiply, .percent: + return .leftAssociative + case .exponent: + return .rightAssociative + } + } + + public var description: String { + return operatorType.description + } } func <= (left: OperatorToken, right: OperatorToken) -> Bool { - return left.precedence <= right.precedence + return left.precedence <= right.precedence } func < (left: OperatorToken, right: OperatorToken) -> Bool { - return left.precedence < right.precedence + return left.precedence < right.precedence } public struct Token: CustomStringConvertible { - let tokenType: TokenType - - init(tokenType: TokenType) { - self.tokenType = tokenType - } - - init(operand: Double) { - tokenType = .operand(operand) - } - - init(operatorType: OperatorType) { - tokenType = .Operator(OperatorToken(operatorType: operatorType)) - } - - var isOpenBracket: Bool { - switch tokenType { - case .openBracket: - return true - default: - return false - } - } - - var isOperator: Bool { - switch tokenType { - case .Operator(_): - return true - default: - return false - } - } - - var operatorToken: OperatorToken? { - switch tokenType { - case .Operator(let operatorToken): - return operatorToken - default: - return nil - } - } - - public var description: String { - return tokenType.description - } + let tokenType: TokenType + + init(tokenType: TokenType) { + self.tokenType = tokenType + } + + init(operand: Double) { + tokenType = .operand(operand) + } + + init(operatorType: OperatorType) { + tokenType = .Operator(OperatorToken(operatorType: operatorType)) + } + + var isOpenBracket: Bool { + switch tokenType { + case .openBracket: + return true + default: + return false + } + } + + var isOperator: Bool { + switch tokenType { + case .Operator(_): + return true + default: + return false + } + } + + var operatorToken: OperatorToken? { + switch tokenType { + case .Operator(let operatorToken): + return operatorToken + default: + return nil + } + } + + public var description: String { + return tokenType.description + } } public class InfixExpressionBuilder { - private var expression = [Token]() - - public func addOperator(_ operatorType: OperatorType) -> InfixExpressionBuilder { - expression.append(Token(operatorType: operatorType)) - return self - } - - public func addOperand(_ operand: Double) -> InfixExpressionBuilder { - expression.append(Token(operand: operand)) - return self - } - - public func addOpenBracket() -> InfixExpressionBuilder { - expression.append(Token(tokenType: .openBracket)) - return self - } - - public func addCloseBracket() -> InfixExpressionBuilder { - expression.append(Token(tokenType: .closeBracket)) - return self - } - - public func build() -> [Token] { - // Maybe do some validation here - return expression - } + private var expression = [Token]() + + public func addOperator(_ operatorType: OperatorType) -> InfixExpressionBuilder { + expression.append(Token(operatorType: operatorType)) + return self + } + + public func addOperand(_ operand: Double) -> InfixExpressionBuilder { + expression.append(Token(operand: operand)) + return self + } + + public func addOpenBracket() -> InfixExpressionBuilder { + expression.append(Token(tokenType: .openBracket)) + return self + } + + public func addCloseBracket() -> InfixExpressionBuilder { + expression.append(Token(tokenType: .closeBracket)) + return self + } + + public func build() -> [Token] { + // Maybe do some validation here + return expression + } } // This returns the result of the shunting yard algorithm public func reversePolishNotation(_ expression: [Token]) -> String { - - var tokenStack = Stack() - var reversePolishNotation = [Token]() - - for token in expression { - switch token.tokenType { - case .operand(_): - reversePolishNotation.append(token) - - case .openBracket: - tokenStack.push(token) - - case .closeBracket: - while tokenStack.count > 0, let tempToken = tokenStack.pop(), !tempToken.isOpenBracket { - reversePolishNotation.append(tempToken) - } - - case .Operator(let operatorToken): - for tempToken in tokenStack.makeIterator() { - if !tempToken.isOperator { - break - } - - if let tempOperatorToken = tempToken.operatorToken { - if operatorToken.associativity == .leftAssociative && operatorToken <= tempOperatorToken - || operatorToken.associativity == .rightAssociative && operatorToken < tempOperatorToken { - reversePolishNotation.append(tokenStack.pop()!) - } else { - break - } - } - } - tokenStack.push(token) + + var tokenStack = Stack() + var reversePolishNotation = [Token]() + + for token in expression { + switch token.tokenType { + case .operand(_): + reversePolishNotation.append(token) + + case .openBracket: + tokenStack.push(token) + + case .closeBracket: + while tokenStack.count > 0, let tempToken = tokenStack.pop(), !tempToken.isOpenBracket { + reversePolishNotation.append(tempToken) + } + + case .Operator(let operatorToken): + for tempToken in tokenStack.makeIterator() { + if !tempToken.isOperator { + break } - } - - while tokenStack.count > 0 { - reversePolishNotation.append(tokenStack.pop()!) - } - - return reversePolishNotation.map({token in token.description}).joined(separator: " ") + + if let tempOperatorToken = tempToken.operatorToken { + if operatorToken.associativity == .leftAssociative && operatorToken <= tempOperatorToken + || operatorToken.associativity == .rightAssociative && operatorToken < tempOperatorToken { + reversePolishNotation.append(tokenStack.pop()!) + } else { + break + } + } + } + tokenStack.push(token) + } + } + + while tokenStack.count > 0 { + reversePolishNotation.append(tokenStack.pop()!) + } + + return reversePolishNotation.map({token in token.description}).joined(separator: " ") } From 6eb7d9a172e3cded2c5be3e52c7193c9168def81 Mon Sep 17 00:00:00 2001 From: Jaap Date: Tue, 7 Feb 2017 18:43:38 +0100 Subject: [PATCH 0812/1679] old version with error --- Threaded Binary Tree/README.markdown | 49 +- .../Contents.swift} | 52 +- .../Sources/ThreadedBinaryTree.swift | 459 ++++++++++++++++++ .../contents.xcplayground | 4 + .../contents.xcworkspacedata | 7 + Threaded Binary Tree/ThreadedBinaryTree.swift | 459 ------------------ 6 files changed, 519 insertions(+), 511 deletions(-) rename Threaded Binary Tree/{ThreadedBinaryTreeTests.swift => ThreadedBinaryTree.playground/Contents.swift} (53%) create mode 100644 Threaded Binary Tree/ThreadedBinaryTree.playground/Sources/ThreadedBinaryTree.swift create mode 100644 Threaded Binary Tree/ThreadedBinaryTree.playground/contents.xcplayground create mode 100644 Threaded Binary Tree/ThreadedBinaryTree.playground/playground.xcworkspace/contents.xcworkspacedata delete mode 100644 Threaded Binary Tree/ThreadedBinaryTree.swift diff --git a/Threaded Binary Tree/README.markdown b/Threaded Binary Tree/README.markdown index 0c533ad63..fd05113d8 100644 --- a/Threaded Binary Tree/README.markdown +++ b/Threaded Binary Tree/README.markdown @@ -158,31 +158,31 @@ outlined above. We use these predecessor/successor attributes to great effect in this new algorithm for both forward and backward traversals: ```swift -func traverseInOrderForward(visit: T -> Void) { - var n: ThreadedBinaryTree - n = minimum() - while true { - visit(n.value) - if let successor = n.successor() { - n = successor - } else { - break + public func traverseInOrderForward(_ visit: (T) -> Void) { + var n: ThreadedBinaryTree + n = minimum() + while true { + visit(n.value) + if let successor = n.successor() { + n = successor + } else { + break + } + } } - } -} -func traverseInOrderBackward(visit: T -> Void) { - var n: ThreadedBinaryTree - n = maximum() - while true { - visit(n.value) - if let predecessor = n.predecessor() { - n = predecessor - } else { - break + public func traverseInOrderBackward(_ visit: (T) -> Void) { + var n: ThreadedBinaryTree + n = maximum() + while true { + visit(n.value) + if let predecessor = n.predecessor() { + n = predecessor + } else { + break + } + } } - } -} ``` Again, this a method of `ThreadedBinaryTree`, so we'd call it via `node.traverseInorderForward(visitFunction)`. Note that we are able to specify @@ -221,7 +221,7 @@ continuously manage the `leftThread` and `rightThread` variables. Rather than walking through some boring code, it is best to explain this with an example (although you can read through [the implementation](ThreadedBinaryTree.swift) if you want to know the finer details). Please note that this requires -knowledge of binary search trees, so make sure you have +knowledge of binary search trees, so make sure you have [read this first](../Binary Search Tree/). > Note: we do allow duplicate nodes in this implementation of a threaded binary @@ -342,11 +342,12 @@ Many of these methods are inherent to binary search trees as well, so you can find [further documentation here](../Binary Search Tree/). -## See also +## See also [Threaded Binary Tree on Wikipedia](https://en.wikipedia.org/wiki/Threaded_binary_tree) *Written for the Swift Algorithm Club by [Jayson Tung](https://github.com/JFTung)* +*Migrated to Swift 3 by Jaap Wijnen* *Images made using www.draw.io* diff --git a/Threaded Binary Tree/ThreadedBinaryTreeTests.swift b/Threaded Binary Tree/ThreadedBinaryTree.playground/Contents.swift similarity index 53% rename from Threaded Binary Tree/ThreadedBinaryTreeTests.swift rename to Threaded Binary Tree/ThreadedBinaryTree.playground/Contents.swift index 514c0db63..ff59f81d1 100644 --- a/Threaded Binary Tree/ThreadedBinaryTreeTests.swift +++ b/Threaded Binary Tree/ThreadedBinaryTree.playground/Contents.swift @@ -1,35 +1,31 @@ -/* - TESTS - I don't have access to an Apple computer, so I can't make a Playground or any - of that fancy stuff. Here's a simple demonstration of the ThreadedBinaryTree - class. It follows the examples in the README. -*/ +//: Playground - noun: a place where people can play + // Simple little debug function to make testing output pretty -func check(tree: ThreadedBinaryTree?) { - if let tree = tree { - print("\(tree.count) Total Nodes:") - print(tree) - print("Debug Info:") - print(tree.debugDescription) - print("In-Order Traversal:") - let myArray = tree.toArray() - for node in myArray { - print(node) - } - if tree.isBST(minValue: Int.min, maxValue: Int.max) { - print("This is a VALID binary search tree.") - } else { - print("This is an INVALID binary search tree.") - } - if tree.isThreaded() { - print("This is a VALID threaded binary tree.") +func check(_ tree: ThreadedBinaryTree?) { + if let tree = tree { + print("\(tree.count) Total Nodes:") + print(tree) + print("Debug Info:") + print(tree.debugDescription) + print("In-Order Traversal:") + let myArray = tree.toArray() + for node in myArray { + print(node) + } + if tree.isBST(minValue: Int.min, maxValue: Int.max) { + print("This is a VALID binary search tree.") + } else { + print("This is an INVALID binary search tree.") + } + if tree.isThreaded() { + print("This is a VALID threaded binary tree.") + } else { + print("This is an INVALID threaded binary tree.") + } } else { - print("This is an INVALID threaded binary tree.") + print("This tree is nil.") } - } else { - print("This tree is nil.") - } } diff --git a/Threaded Binary Tree/ThreadedBinaryTree.playground/Sources/ThreadedBinaryTree.swift b/Threaded Binary Tree/ThreadedBinaryTree.playground/Sources/ThreadedBinaryTree.swift new file mode 100644 index 000000000..4ae03238d --- /dev/null +++ b/Threaded Binary Tree/ThreadedBinaryTree.playground/Sources/ThreadedBinaryTree.swift @@ -0,0 +1,459 @@ +/* + A Threaded Binary Tree. + Based on this club's Binary Search Tree implementation. + + Each node stores a value and two children. The left child contains a smaller + value; the right a larger (or equal) value. + + Any nodes that lack either a left or right child instead keep track of their + in-order predecessor and/or successor. + + This tree allows duplicate elements (we break ties by defaulting right). + + This tree does not automatically balance itself. To make sure it is balanced, + you should insert new values in randomized order, not in sorted order. + */ +public class ThreadedBinaryTree { + fileprivate(set) public var value: T + fileprivate(set) public var parent: ThreadedBinaryTree? + fileprivate(set) public var left: ThreadedBinaryTree? + fileprivate(set) public var right: ThreadedBinaryTree? + fileprivate(set) public var leftThread: ThreadedBinaryTree? + fileprivate(set) public var rightThread: ThreadedBinaryTree? + + public init(value: T) { + self.value = value + } + + public convenience init(array: [T]) { + precondition(array.count > 0) + self.init(value: array.first!) + for v in array.dropFirst() { + insert(v, parent: self) + } + } + + public var isRoot: Bool { + return parent == nil + } + + public var isLeaf: Bool { + return left == nil && right == nil + } + + public var isLeftChild: Bool { + return parent?.left === self + } + + public var isRightChild: Bool { + return parent?.right === self + } + + public var hasLeftChild: Bool { + return left != nil + } + + public var hasRightChild: Bool { + return right != nil + } + + public var hasAnyChild: Bool { + return hasLeftChild || hasRightChild + } + + public var hasBothChildren: Bool { + return hasLeftChild && hasRightChild + } + + /* How many nodes are in this subtree. Performance: O(n). */ + public var count: Int { + return (left?.count ?? 0) + 1 + (right?.count ?? 0) + } +} + +// MARK: - Adding items + +extension ThreadedBinaryTree { + /* + Inserts a new element into the tree. You should only insert elements + at the root, to make to sure this remains a valid binary tree! + Performance: runs in O(h) time, where h is the height of the tree. + */ + public func insert(_ value: T) { + insert(value, parent: self) + } + + fileprivate func insert(_ value: T, parent: ThreadedBinaryTree) { + if value < self.value { + if let left = left { + left.insert(value, parent: left) + } else { + left = ThreadedBinaryTree(value: value) + left?.parent = parent + left?.rightThread = parent + left?.leftThread = leftThread + leftThread = nil + } + } else { + if let right = right { + right.insert(value, parent: right) + } else { + right = ThreadedBinaryTree(value: value) + right?.parent = parent + right?.leftThread = parent + right?.rightThread = rightThread + rightThread = nil + } + } + } +} + +// MARK: - Deleting items + +extension ThreadedBinaryTree { + /* + Deletes the "highest" node with the specified value. + + Returns the node that has replaced this removed one (or nil if this was a + leaf node). That is primarily useful for when you delete the root node, in + which case the tree gets a new root. + + Performance: runs in O(h) time, where h is the height of the tree. + */ + public func remove(_ value: T) -> ThreadedBinaryTree? { + return search(value)?.remove() + } + + /* + Deletes "this" node from the tree. + */ + public func remove() -> ThreadedBinaryTree? { + let replacement: ThreadedBinaryTree? + + if let left = left { + if let right = right { + replacement = removeNodeWithTwoChildren(left, right) + replacement?.leftThread = leftThread + replacement?.rightThread = rightThread + left.maximum().rightThread = replacement + right.minimum().leftThread = replacement + } else { + // This node only has a left child. The left child replaces the node. + replacement = left + left.maximum().rightThread = rightThread + } + } else if let right = right { + // This node only has a right child. The right child replaces the node. + replacement = right + right.minimum().leftThread = leftThread + } else { + // This node has no children. We just disconnect it from its parent. + replacement = nil + if isLeftChild { + parent?.leftThread = leftThread + } else { + parent?.rightThread = rightThread + } + } + + reconnectParentToNode(replacement) + + // The current node is no longer part of the tree, so clean it up. + parent = nil + left = nil + right = nil + leftThread = nil + rightThread = nil + + return replacement + } + + private func removeNodeWithTwoChildren(_ left: ThreadedBinaryTree, _ right: ThreadedBinaryTree) -> ThreadedBinaryTree { + // This node has two children. It must be replaced by the smallest + // child that is larger than this node's value, which is the leftmost + // descendent of the right child. + let successor = right.minimum() + + // If this in-order successor has a right child of its own (it cannot + // have a left child by definition), then that must take its place. + successor.remove() + + // Connect our left child with the new node. + successor.left = left + left.parent = successor + + // Connect our right child with the new node. If the right child does + // not have any left children of its own, then the in-order successor + // *is* the right child. + if right !== successor { + successor.right = right + right.parent = successor + } else { + successor.right = nil + } + + // And finally, connect the successor node to our parent. + return successor + } + + private func reconnectParentToNode(_ node: ThreadedBinaryTree?) { + if let parent = parent { + if isLeftChild { + parent.left = node + } else { + parent.right = node + } + } + node?.parent = parent + } +} + +// MARK: - Searching + +extension ThreadedBinaryTree { + /* + Finds the "highest" node with the specified value. + Performance: runs in O(h) time, where h is the height of the tree. + */ + public func search(_ value: T) -> ThreadedBinaryTree? { + var node: ThreadedBinaryTree? = self + while case let n? = node { + if value < n.value { + node = n.left + } else if value > n.value { + node = n.right + } else { + return node + } + } + return nil + } + + /* + // Recursive version of search + // Educational but undesirable due to the overhead cost of recursion + public func search(value: T) -> ThreadedBinaryTree? { + if value < self.value { + return left?.search(value) + } else if value > self.value { + return right?.search(value) + } else { + return self + } + } + */ + + public func contains(value: T) -> Bool { + return search(value) != nil + } + + /* + Returns the leftmost descendent. O(h) time. + */ + public func minimum() -> ThreadedBinaryTree { + var node = self + while case let next? = node.left { + node = next + } + return node + } + + /* + Returns the rightmost descendent. O(h) time. + */ + public func maximum() -> ThreadedBinaryTree { + var node = self + while case let next? = node.right { + node = next + } + return node + } + + /* + Calculates the depth of this node, i.e. the distance to the root. + Takes O(h) time. + */ + public func depth() -> Int { + var node = self + var edges = 0 + while case let parent? = node.parent { + node = parent + edges += 1 + } + return edges + } + + /* + Calculates the height of this node, i.e. the distance to the lowest leaf. + Since this looks at all children of this node, performance is O(n). + */ + public func height() -> Int { + if isLeaf { + return 0 + } else { + return 1 + max(left?.height() ?? 0, right?.height() ?? 0) + } + } + + /* + Finds the node whose value precedes our value in sorted order. + */ + public func predecessor() -> ThreadedBinaryTree? { + if let left = left { + return left.maximum() + } else { + return leftThread + } + } + + /* + Finds the node whose value succeeds our value in sorted order. + */ + public func successor() -> ThreadedBinaryTree? { + if let right = right { + return right.minimum() + } else { + return rightThread + } + } +} + +// MARK: - Traversal + +extension ThreadedBinaryTree { + public func traverseInOrderForward(_ visit: (T) -> Void) { + var n: ThreadedBinaryTree + n = minimum() + while true { + visit(n.value) + if let successor = n.successor() { + n = successor + } else { + break + } + } + } + + public func traverseInOrderBackward(_ visit: (T) -> Void) { + var n: ThreadedBinaryTree + n = maximum() + while true { + visit(n.value) + if let predecessor = n.predecessor() { + n = predecessor + } else { + break + } + } + } + + public func traversePreOrder(_ visit: (T) -> Void) { + visit(value) + left?.traversePreOrder(visit) + right?.traversePreOrder(visit) + } + + public func traversePostOrder(_ visit: (T) -> Void) { + left?.traversePostOrder(visit) + right?.traversePostOrder(visit) + visit(value) + } + + /* + Performs an in-order traversal and collects the results in an array. + */ + public func map(formula: (T) -> T) -> [T] { + var a = [T]() + var n: ThreadedBinaryTree + n = minimum() + while true { + a.append(formula(n.value)) + if let successor = n.successor() { + n = successor + } else { + break + } + } + return a + } +} + +// MARK: - Verification + +extension ThreadedBinaryTree { + /* + Is this threaded binary tree a valid binary search tree? + */ + public func isBST(minValue: T, maxValue: T) -> Bool { + if value < minValue || value > maxValue { return false } + let leftBST = left?.isBST(minValue: minValue, maxValue: value) ?? true + let rightBST = right?.isBST(minValue: value, maxValue: maxValue) ?? true + return leftBST && rightBST + } + + /* + Is this binary tree properly threaded? + Either left or leftThread (but not both) must be nil (likewise for right). + The first and last nodes in the in-order traversal are exempt from this, + as the first has leftThread = nil, and the last has rightThread = nil. + */ + public func isThreaded() -> Bool { + if left == nil && leftThread == nil { + if self !== minimum() { return false } + } + if left != nil && leftThread != nil { + return false + } + if right == nil && rightThread == nil { + if self !== maximum() { return false } + } + if right != nil && rightThread != nil { + return false + } + let leftThreaded = left?.isThreaded() ?? true + let rightThreaded = right?.isThreaded() ?? true + return leftThreaded && rightThreaded + } +} + +// MARK: - Debugging + +extension ThreadedBinaryTree: CustomStringConvertible { + public var description: String { + var s = "" + if let left = left { + s += "(\(left.description)) <- " + } + s += "\(value)" + if let right = right { + s += " -> (\(right.description))" + } + return s + } +} + +extension ThreadedBinaryTree: CustomDebugStringConvertible { + public var debugDescription: String { + var s = "value: \(value)" + if let parent = parent { + s += ", parent: \(parent.value)" + } + if let leftThread = leftThread { + s += ", leftThread: \(leftThread.value)" + } + if let rightThread = rightThread { + s += ", rightThread: \(rightThread.value)" + } + if let left = left { + s += ", left = [" + left.debugDescription + "]" + } + if let right = right { + s += ", right = [" + right.debugDescription + "]" + } + return s + } + + public func toArray() -> [T] { + return map { $0 } + } +} diff --git a/Threaded Binary Tree/ThreadedBinaryTree.playground/contents.xcplayground b/Threaded Binary Tree/ThreadedBinaryTree.playground/contents.xcplayground new file mode 100644 index 000000000..5da2641c9 --- /dev/null +++ b/Threaded Binary Tree/ThreadedBinaryTree.playground/contents.xcplayground @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Threaded Binary Tree/ThreadedBinaryTree.playground/playground.xcworkspace/contents.xcworkspacedata b/Threaded Binary Tree/ThreadedBinaryTree.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Threaded Binary Tree/ThreadedBinaryTree.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Threaded Binary Tree/ThreadedBinaryTree.swift b/Threaded Binary Tree/ThreadedBinaryTree.swift deleted file mode 100644 index 98a23d013..000000000 --- a/Threaded Binary Tree/ThreadedBinaryTree.swift +++ /dev/null @@ -1,459 +0,0 @@ -/* - A Threaded Binary Tree. - Based on this club's Binary Search Tree implementation. - - Each node stores a value and two children. The left child contains a smaller - value; the right a larger (or equal) value. - - Any nodes that lack either a left or right child instead keep track of their - in-order predecessor and/or successor. - - This tree allows duplicate elements (we break ties by defaulting right). - - This tree does not automatically balance itself. To make sure it is balanced, - you should insert new values in randomized order, not in sorted order. -*/ -public class ThreadedBinaryTree { - private(set) public var value: T - private(set) public var parent: ThreadedBinaryTree? - private(set) public var left: ThreadedBinaryTree? - private(set) public var right: ThreadedBinaryTree? - private(set) public var leftThread: ThreadedBinaryTree? - private(set) public var rightThread: ThreadedBinaryTree? - - public init(value: T) { - self.value = value - } - - public convenience init(array: [T]) { - precondition(array.count > 0) - self.init(value: array.first!) - for v in array.dropFirst() { - insert(v, parent: self) - } - } - - public var isRoot: Bool { - return parent == nil - } - - public var isLeaf: Bool { - return left == nil && right == nil - } - - public var isLeftChild: Bool { - return parent?.left === self - } - - public var isRightChild: Bool { - return parent?.right === self - } - - public var hasLeftChild: Bool { - return left != nil - } - - public var hasRightChild: Bool { - return right != nil - } - - public var hasAnyChild: Bool { - return hasLeftChild || hasRightChild - } - - public var hasBothChildren: Bool { - return hasLeftChild && hasRightChild - } - - /* How many nodes are in this subtree. Performance: O(n). */ - public var count: Int { - return (left?.count ?? 0) + 1 + (right?.count ?? 0) - } -} - -// MARK: - Adding items - -extension ThreadedBinaryTree { - /* - Inserts a new element into the tree. You should only insert elements - at the root, to make to sure this remains a valid binary tree! - Performance: runs in O(h) time, where h is the height of the tree. - */ - public func insert(value: T) { - insert(value, parent: self) - } - - private func insert(value: T, parent: ThreadedBinaryTree) { - if value < self.value { - if let left = left { - left.insert(value, parent: left) - } else { - left = ThreadedBinaryTree(value: value) - left?.parent = parent - left?.rightThread = parent - left?.leftThread = leftThread - leftThread = nil - } - } else { - if let right = right { - right.insert(value, parent: right) - } else { - right = ThreadedBinaryTree(value: value) - right?.parent = parent - right?.leftThread = parent - right?.rightThread = rightThread - rightThread = nil - } - } - } -} - -// MARK: - Deleting items - -extension ThreadedBinaryTree { - /* - Deletes the "highest" node with the specified value. - - Returns the node that has replaced this removed one (or nil if this was a - leaf node). That is primarily useful for when you delete the root node, in - which case the tree gets a new root. - - Performance: runs in O(h) time, where h is the height of the tree. - */ - public func remove(value: T) -> ThreadedBinaryTree? { - return search(value)?.remove() - } - - /* - Deletes "this" node from the tree. - */ - public func remove() -> ThreadedBinaryTree? { - let replacement: ThreadedBinaryTree? - - if let left = left { - if let right = right { - replacement = removeNodeWithTwoChildren(left, right) - replacement?.leftThread = leftThread - replacement?.rightThread = rightThread - left.maximum().rightThread = replacement - right.minimum().leftThread = replacement - } else { - // This node only has a left child. The left child replaces the node. - replacement = left - left.maximum().rightThread = rightThread - } - } else if let right = right { - // This node only has a right child. The right child replaces the node. - replacement = right - right.minimum().leftThread = leftThread - } else { - // This node has no children. We just disconnect it from its parent. - replacement = nil - if isLeftChild { - parent?.leftThread = leftThread - } else { - parent?.rightThread = rightThread - } - } - - reconnectParentToNode(replacement) - - // The current node is no longer part of the tree, so clean it up. - parent = nil - left = nil - right = nil - leftThread = nil - rightThread = nil - - return replacement - } - - private func removeNodeWithTwoChildren(left: ThreadedBinaryTree, _ right: ThreadedBinaryTree) -> ThreadedBinaryTree { - // This node has two children. It must be replaced by the smallest - // child that is larger than this node's value, which is the leftmost - // descendent of the right child. - let successor = right.minimum() - - // If this in-order successor has a right child of its own (it cannot - // have a left child by definition), then that must take its place. - successor.remove() - - // Connect our left child with the new node. - successor.left = left - left.parent = successor - - // Connect our right child with the new node. If the right child does - // not have any left children of its own, then the in-order successor - // *is* the right child. - if right !== successor { - successor.right = right - right.parent = successor - } else { - successor.right = nil - } - - // And finally, connect the successor node to our parent. - return successor - } - - private func reconnectParentToNode(node: ThreadedBinaryTree?) { - if let parent = parent { - if isLeftChild { - parent.left = node - } else { - parent.right = node - } - } - node?.parent = parent - } -} - -// MARK: - Searching - -extension ThreadedBinaryTree { - /* - Finds the "highest" node with the specified value. - Performance: runs in O(h) time, where h is the height of the tree. - */ - public func search(value: T) -> ThreadedBinaryTree? { - var node: ThreadedBinaryTree? = self - while case let n? = node { - if value < n.value { - node = n.left - } else if value > n.value { - node = n.right - } else { - return node - } - } - return nil - } - - /* - // Recursive version of search - // Educational but undesirable due to the overhead cost of recursion - public func search(value: T) -> ThreadedBinaryTree? { - if value < self.value { - return left?.search(value) - } else if value > self.value { - return right?.search(value) - } else { - return self - } - } - */ - - public func contains(value: T) -> Bool { - return search(value) != nil - } - - /* - Returns the leftmost descendent. O(h) time. - */ - public func minimum() -> ThreadedBinaryTree { - var node = self - while case let next? = node.left { - node = next - } - return node - } - - /* - Returns the rightmost descendent. O(h) time. - */ - public func maximum() -> ThreadedBinaryTree { - var node = self - while case let next? = node.right { - node = next - } - return node - } - - /* - Calculates the depth of this node, i.e. the distance to the root. - Takes O(h) time. - */ - public func depth() -> Int { - var node = self - var edges = 0 - while case let parent? = node.parent { - node = parent - edges += 1 - } - return edges - } - - /* - Calculates the height of this node, i.e. the distance to the lowest leaf. - Since this looks at all children of this node, performance is O(n). - */ - public func height() -> Int { - if isLeaf { - return 0 - } else { - return 1 + max(left?.height() ?? 0, right?.height() ?? 0) - } - } - - /* - Finds the node whose value precedes our value in sorted order. - */ - public func predecessor() -> ThreadedBinaryTree? { - if let left = left { - return left.maximum() - } else { - return leftThread - } - } - - /* - Finds the node whose value succeeds our value in sorted order. - */ - public func successor() -> ThreadedBinaryTree? { - if let right = right { - return right.minimum() - } else { - return rightThread - } - } -} - -// MARK: - Traversal - -extension ThreadedBinaryTree { - public func traverseInOrderForward(@noescape visit: T -> Void) { - var n: ThreadedBinaryTree - n = minimum() - while true { - visit(n.value) - if let successor = n.successor() { - n = successor - } else { - break - } - } - } - - public func traverseInOrderBackward(@noescape visit: T -> Void) { - var n: ThreadedBinaryTree - n = maximum() - while true { - visit(n.value) - if let predecessor = n.predecessor() { - n = predecessor - } else { - break - } - } - } - - public func traversePreOrder(@noescape visit: T -> Void) { - visit(value) - left?.traversePreOrder(visit) - right?.traversePreOrder(visit) - } - - public func traversePostOrder(@noescape visit: T -> Void) { - left?.traversePostOrder(visit) - right?.traversePostOrder(visit) - visit(value) - } - - /* - Performs an in-order traversal and collects the results in an array. - */ - public func map(@noescape formula: T -> T) -> [T] { - var a = [T]() - var n: ThreadedBinaryTree - n = minimum() - while true { - a.append(formula(n.value)) - if let successor = n.successor() { - n = successor - } else { - break - } - } - return a - } -} - -// MARK: - Verification - -extension ThreadedBinaryTree { - /* - Is this threaded binary tree a valid binary search tree? - */ - public func isBST(minValue minValue: T, maxValue: T) -> Bool { - if value < minValue || value > maxValue { return false } - let leftBST = left?.isBST(minValue: minValue, maxValue: value) ?? true - let rightBST = right?.isBST(minValue: value, maxValue: maxValue) ?? true - return leftBST && rightBST - } - - /* - Is this binary tree properly threaded? - Either left or leftThread (but not both) must be nil (likewise for right). - The first and last nodes in the in-order traversal are exempt from this, - as the first has leftThread = nil, and the last has rightThread = nil. - */ - public func isThreaded() -> Bool { - if left == nil && leftThread == nil { - if self !== minimum() { return false } - } - if left != nil && leftThread != nil { - return false - } - if right == nil && rightThread == nil { - if self !== maximum() { return false } - } - if right != nil && rightThread != nil { - return false - } - let leftThreaded = left?.isThreaded() ?? true - let rightThreaded = right?.isThreaded() ?? true - return leftThreaded && rightThreaded - } -} - -// MARK: - Debugging - -extension ThreadedBinaryTree: CustomStringConvertible { - public var description: String { - var s = "" - if let left = left { - s += "(\(left.description)) <- " - } - s += "\(value)" - if let right = right { - s += " -> (\(right.description))" - } - return s - } -} - -extension ThreadedBinaryTree: CustomDebugStringConvertible { - public var debugDescription: String { - var s = "value: \(value)" - if let parent = parent { - s += ", parent: \(parent.value)" - } - if let leftThread = leftThread { - s += ", leftThread: \(leftThread.value)" - } - if let rightThread = rightThread { - s += ", rightThread: \(rightThread.value)" - } - if let left = left { - s += ", left = [" + left.debugDescription + "]" - } - if let right = right { - s += ", right = [" + right.debugDescription + "]" - } - return s - } - - public func toArray() -> [T] { - return map { $0 } - } -} From 3fc54e61b6c727323e97cc026021141966aec193 Mon Sep 17 00:00:00 2001 From: Jaap Date: Tue, 7 Feb 2017 18:46:27 +0100 Subject: [PATCH 0813/1679] fix --- .../Sources/ThreadedBinaryTree.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Threaded Binary Tree/ThreadedBinaryTree.playground/Sources/ThreadedBinaryTree.swift b/Threaded Binary Tree/ThreadedBinaryTree.playground/Sources/ThreadedBinaryTree.swift index 4ae03238d..e703d793a 100644 --- a/Threaded Binary Tree/ThreadedBinaryTree.playground/Sources/ThreadedBinaryTree.swift +++ b/Threaded Binary Tree/ThreadedBinaryTree.playground/Sources/ThreadedBinaryTree.swift @@ -120,7 +120,7 @@ extension ThreadedBinaryTree { Performance: runs in O(h) time, where h is the height of the tree. */ - public func remove(_ value: T) -> ThreadedBinaryTree? { + @discardableResult public func remove(_ value: T) -> ThreadedBinaryTree? { return search(value)?.remove() } From 92363b88477de2595c69924fb51c65679f9d0d85 Mon Sep 17 00:00:00 2001 From: Jaap Date: Tue, 7 Feb 2017 19:01:31 +0100 Subject: [PATCH 0814/1679] fix spaces --- .../Contents.swift | 42 +- .../Sources/ThreadedBinaryTree.swift | 752 +++++++++--------- 2 files changed, 397 insertions(+), 397 deletions(-) diff --git a/Threaded Binary Tree/ThreadedBinaryTree.playground/Contents.swift b/Threaded Binary Tree/ThreadedBinaryTree.playground/Contents.swift index ff59f81d1..e4b527664 100644 --- a/Threaded Binary Tree/ThreadedBinaryTree.playground/Contents.swift +++ b/Threaded Binary Tree/ThreadedBinaryTree.playground/Contents.swift @@ -3,28 +3,28 @@ // Simple little debug function to make testing output pretty func check(_ tree: ThreadedBinaryTree?) { - if let tree = tree { - print("\(tree.count) Total Nodes:") - print(tree) - print("Debug Info:") - print(tree.debugDescription) - print("In-Order Traversal:") - let myArray = tree.toArray() - for node in myArray { - print(node) - } - if tree.isBST(minValue: Int.min, maxValue: Int.max) { - print("This is a VALID binary search tree.") - } else { - print("This is an INVALID binary search tree.") - } - if tree.isThreaded() { - print("This is a VALID threaded binary tree.") - } else { - print("This is an INVALID threaded binary tree.") - } + if let tree = tree { + print("\(tree.count) Total Nodes:") + print(tree) + print("Debug Info:") + print(tree.debugDescription) + print("In-Order Traversal:") + let myArray = tree.toArray() + for node in myArray { + print(node) + } + if tree.isBST(minValue: Int.min, maxValue: Int.max) { + print("This is a VALID binary search tree.") + } else { + print("This is an INVALID binary search tree.") + } + if tree.isThreaded() { + print("This is a VALID threaded binary tree.") + } else { + print("This is an INVALID threaded binary tree.") + } } else { - print("This tree is nil.") + print("This tree is nil.") } } diff --git a/Threaded Binary Tree/ThreadedBinaryTree.playground/Sources/ThreadedBinaryTree.swift b/Threaded Binary Tree/ThreadedBinaryTree.playground/Sources/ThreadedBinaryTree.swift index e703d793a..a4d308e77 100644 --- a/Threaded Binary Tree/ThreadedBinaryTree.playground/Sources/ThreadedBinaryTree.swift +++ b/Threaded Binary Tree/ThreadedBinaryTree.playground/Sources/ThreadedBinaryTree.swift @@ -14,446 +14,446 @@ you should insert new values in randomized order, not in sorted order. */ public class ThreadedBinaryTree { - fileprivate(set) public var value: T - fileprivate(set) public var parent: ThreadedBinaryTree? - fileprivate(set) public var left: ThreadedBinaryTree? - fileprivate(set) public var right: ThreadedBinaryTree? - fileprivate(set) public var leftThread: ThreadedBinaryTree? - fileprivate(set) public var rightThread: ThreadedBinaryTree? - - public init(value: T) { - self.value = value - } - - public convenience init(array: [T]) { - precondition(array.count > 0) - self.init(value: array.first!) - for v in array.dropFirst() { - insert(v, parent: self) - } - } - - public var isRoot: Bool { - return parent == nil - } - - public var isLeaf: Bool { - return left == nil && right == nil - } - - public var isLeftChild: Bool { - return parent?.left === self - } - - public var isRightChild: Bool { - return parent?.right === self - } - - public var hasLeftChild: Bool { - return left != nil - } - - public var hasRightChild: Bool { - return right != nil - } - - public var hasAnyChild: Bool { - return hasLeftChild || hasRightChild - } - - public var hasBothChildren: Bool { - return hasLeftChild && hasRightChild - } - - /* How many nodes are in this subtree. Performance: O(n). */ - public var count: Int { - return (left?.count ?? 0) + 1 + (right?.count ?? 0) + fileprivate(set) public var value: T + fileprivate(set) public var parent: ThreadedBinaryTree? + fileprivate(set) public var left: ThreadedBinaryTree? + fileprivate(set) public var right: ThreadedBinaryTree? + fileprivate(set) public var leftThread: ThreadedBinaryTree? + fileprivate(set) public var rightThread: ThreadedBinaryTree? + + public init(value: T) { + self.value = value + } + + public convenience init(array: [T]) { + precondition(array.count > 0) + self.init(value: array.first!) + for v in array.dropFirst() { + insert(v, parent: self) } + } + + public var isRoot: Bool { + return parent == nil + } + + public var isLeaf: Bool { + return left == nil && right == nil + } + + public var isLeftChild: Bool { + return parent?.left === self + } + + public var isRightChild: Bool { + return parent?.right === self + } + + public var hasLeftChild: Bool { + return left != nil + } + + public var hasRightChild: Bool { + return right != nil + } + + public var hasAnyChild: Bool { + return hasLeftChild || hasRightChild + } + + public var hasBothChildren: Bool { + return hasLeftChild && hasRightChild + } + + /* How many nodes are in this subtree. Performance: O(n). */ + public var count: Int { + return (left?.count ?? 0) + 1 + (right?.count ?? 0) + } } // MARK: - Adding items extension ThreadedBinaryTree { - /* - Inserts a new element into the tree. You should only insert elements - at the root, to make to sure this remains a valid binary tree! - Performance: runs in O(h) time, where h is the height of the tree. - */ - public func insert(_ value: T) { - insert(value, parent: self) - } + /* + Inserts a new element into the tree. You should only insert elements + at the root, to make to sure this remains a valid binary tree! + Performance: runs in O(h) time, where h is the height of the tree. + */ + public func insert(_ value: T) { + insert(value, parent: self) + } - fileprivate func insert(_ value: T, parent: ThreadedBinaryTree) { - if value < self.value { - if let left = left { - left.insert(value, parent: left) - } else { - left = ThreadedBinaryTree(value: value) - left?.parent = parent - left?.rightThread = parent - left?.leftThread = leftThread - leftThread = nil - } - } else { - if let right = right { - right.insert(value, parent: right) - } else { - right = ThreadedBinaryTree(value: value) - right?.parent = parent - right?.leftThread = parent - right?.rightThread = rightThread - rightThread = nil - } - } + fileprivate func insert(_ value: T, parent: ThreadedBinaryTree) { + if value < self.value { + if let left = left { + left.insert(value, parent: left) + } else { + left = ThreadedBinaryTree(value: value) + left?.parent = parent + left?.rightThread = parent + left?.leftThread = leftThread + leftThread = nil + } + } else { + if let right = right { + right.insert(value, parent: right) + } else { + right = ThreadedBinaryTree(value: value) + right?.parent = parent + right?.leftThread = parent + right?.rightThread = rightThread + rightThread = nil + } } + } } // MARK: - Deleting items extension ThreadedBinaryTree { - /* - Deletes the "highest" node with the specified value. + /* + Deletes the "highest" node with the specified value. - Returns the node that has replaced this removed one (or nil if this was a - leaf node). That is primarily useful for when you delete the root node, in - which case the tree gets a new root. + Returns the node that has replaced this removed one (or nil if this was a + leaf node). That is primarily useful for when you delete the root node, in + which case the tree gets a new root. - Performance: runs in O(h) time, where h is the height of the tree. - */ - @discardableResult public func remove(_ value: T) -> ThreadedBinaryTree? { - return search(value)?.remove() - } + Performance: runs in O(h) time, where h is the height of the tree. + */ + @discardableResult public func remove(_ value: T) -> ThreadedBinaryTree? { + return search(value)?.remove() + } - /* - Deletes "this" node from the tree. - */ - public func remove() -> ThreadedBinaryTree? { - let replacement: ThreadedBinaryTree? + /* + Deletes "this" node from the tree. + */ + public func remove() -> ThreadedBinaryTree? { + let replacement: ThreadedBinaryTree? - if let left = left { - if let right = right { - replacement = removeNodeWithTwoChildren(left, right) - replacement?.leftThread = leftThread - replacement?.rightThread = rightThread - left.maximum().rightThread = replacement - right.minimum().leftThread = replacement - } else { - // This node only has a left child. The left child replaces the node. - replacement = left - left.maximum().rightThread = rightThread - } - } else if let right = right { - // This node only has a right child. The right child replaces the node. - replacement = right - right.minimum().leftThread = leftThread - } else { - // This node has no children. We just disconnect it from its parent. - replacement = nil - if isLeftChild { - parent?.leftThread = leftThread - } else { - parent?.rightThread = rightThread - } - } + if let left = left { + if let right = right { + replacement = removeNodeWithTwoChildren(left, right) + replacement?.leftThread = leftThread + replacement?.rightThread = rightThread + left.maximum().rightThread = replacement + right.minimum().leftThread = replacement + } else { + // This node only has a left child. The left child replaces the node. + replacement = left + left.maximum().rightThread = rightThread + } + } else if let right = right { + // This node only has a right child. The right child replaces the node. + replacement = right + right.minimum().leftThread = leftThread + } else { + // This node has no children. We just disconnect it from its parent. + replacement = nil + if isLeftChild { + parent?.leftThread = leftThread + } else { + parent?.rightThread = rightThread + } + } - reconnectParentToNode(replacement) + reconnectParentToNode(replacement) - // The current node is no longer part of the tree, so clean it up. - parent = nil - left = nil - right = nil - leftThread = nil - rightThread = nil + // The current node is no longer part of the tree, so clean it up. + parent = nil + left = nil + right = nil + leftThread = nil + rightThread = nil - return replacement - } + return replacement + } - private func removeNodeWithTwoChildren(_ left: ThreadedBinaryTree, _ right: ThreadedBinaryTree) -> ThreadedBinaryTree { - // This node has two children. It must be replaced by the smallest - // child that is larger than this node's value, which is the leftmost - // descendent of the right child. - let successor = right.minimum() + private func removeNodeWithTwoChildren(_ left: ThreadedBinaryTree, _ right: ThreadedBinaryTree) -> ThreadedBinaryTree { + // This node has two children. It must be replaced by the smallest + // child that is larger than this node's value, which is the leftmost + // descendent of the right child. + let successor = right.minimum() - // If this in-order successor has a right child of its own (it cannot - // have a left child by definition), then that must take its place. - successor.remove() + // If this in-order successor has a right child of its own (it cannot + // have a left child by definition), then that must take its place. + successor.remove() - // Connect our left child with the new node. - successor.left = left - left.parent = successor + // Connect our left child with the new node. + successor.left = left + left.parent = successor - // Connect our right child with the new node. If the right child does - // not have any left children of its own, then the in-order successor - // *is* the right child. - if right !== successor { - successor.right = right - right.parent = successor - } else { - successor.right = nil - } - - // And finally, connect the successor node to our parent. - return successor + // Connect our right child with the new node. If the right child does + // not have any left children of its own, then the in-order successor + // *is* the right child. + if right !== successor { + successor.right = right + right.parent = successor + } else { + successor.right = nil } + + // And finally, connect the successor node to our parent. + return successor + } - private func reconnectParentToNode(_ node: ThreadedBinaryTree?) { - if let parent = parent { - if isLeftChild { - parent.left = node - } else { - parent.right = node - } - } - node?.parent = parent - } + private func reconnectParentToNode(_ node: ThreadedBinaryTree?) { + if let parent = parent { + if isLeftChild { + parent.left = node + } else { + parent.right = node + } + } + node?.parent = parent + } } // MARK: - Searching extension ThreadedBinaryTree { - /* - Finds the "highest" node with the specified value. - Performance: runs in O(h) time, where h is the height of the tree. - */ - public func search(_ value: T) -> ThreadedBinaryTree? { - var node: ThreadedBinaryTree? = self - while case let n? = node { - if value < n.value { - node = n.left - } else if value > n.value { - node = n.right - } else { - return node - } - } - return nil + /* + Finds the "highest" node with the specified value. + Performance: runs in O(h) time, where h is the height of the tree. + */ + public func search(_ value: T) -> ThreadedBinaryTree? { + var node: ThreadedBinaryTree? = self + while case let n? = node { + if value < n.value { + node = n.left + } else if value > n.value { + node = n.right + } else { + return node + } } + return nil + } - /* - // Recursive version of search - // Educational but undesirable due to the overhead cost of recursion - public func search(value: T) -> ThreadedBinaryTree? { - if value < self.value { - return left?.search(value) - } else if value > self.value { - return right?.search(value) - } else { - return self - } - } - */ + /* + // Recursive version of search + // Educational but undesirable due to the overhead cost of recursion + public func search(value: T) -> ThreadedBinaryTree? { + if value < self.value { + return left?.search(value) + } else if value > self.value { + return right?.search(value) + } else { + return self + } + } + */ - public func contains(value: T) -> Bool { - return search(value) != nil - } + public func contains(value: T) -> Bool { + return search(value) != nil + } - /* - Returns the leftmost descendent. O(h) time. - */ - public func minimum() -> ThreadedBinaryTree { - var node = self - while case let next? = node.left { - node = next - } - return node - } + /* + Returns the leftmost descendent. O(h) time. + */ + public func minimum() -> ThreadedBinaryTree { + var node = self + while case let next? = node.left { + node = next + } + return node + } - /* - Returns the rightmost descendent. O(h) time. - */ - public func maximum() -> ThreadedBinaryTree { - var node = self - while case let next? = node.right { - node = next - } - return node - } + /* + Returns the rightmost descendent. O(h) time. + */ + public func maximum() -> ThreadedBinaryTree { + var node = self + while case let next? = node.right { + node = next + } + return node + } - /* - Calculates the depth of this node, i.e. the distance to the root. - Takes O(h) time. - */ - public func depth() -> Int { - var node = self - var edges = 0 - while case let parent? = node.parent { - node = parent - edges += 1 - } - return edges - } + /* + Calculates the depth of this node, i.e. the distance to the root. + Takes O(h) time. + */ + public func depth() -> Int { + var node = self + var edges = 0 + while case let parent? = node.parent { + node = parent + edges += 1 + } + return edges + } - /* - Calculates the height of this node, i.e. the distance to the lowest leaf. - Since this looks at all children of this node, performance is O(n). - */ - public func height() -> Int { - if isLeaf { - return 0 - } else { - return 1 + max(left?.height() ?? 0, right?.height() ?? 0) - } - } + /* + Calculates the height of this node, i.e. the distance to the lowest leaf. + Since this looks at all children of this node, performance is O(n). + */ + public func height() -> Int { + if isLeaf { + return 0 + } else { + return 1 + max(left?.height() ?? 0, right?.height() ?? 0) + } + } - /* - Finds the node whose value precedes our value in sorted order. - */ - public func predecessor() -> ThreadedBinaryTree? { - if let left = left { - return left.maximum() - } else { - return leftThread - } - } + /* + Finds the node whose value precedes our value in sorted order. + */ + public func predecessor() -> ThreadedBinaryTree? { + if let left = left { + return left.maximum() + } else { + return leftThread + } + } - /* - Finds the node whose value succeeds our value in sorted order. - */ - public func successor() -> ThreadedBinaryTree? { - if let right = right { - return right.minimum() - } else { - return rightThread - } - } + /* + Finds the node whose value succeeds our value in sorted order. + */ + public func successor() -> ThreadedBinaryTree? { + if let right = right { + return right.minimum() + } else { + return rightThread + } + } } // MARK: - Traversal extension ThreadedBinaryTree { - public func traverseInOrderForward(_ visit: (T) -> Void) { - var n: ThreadedBinaryTree - n = minimum() - while true { - visit(n.value) - if let successor = n.successor() { - n = successor - } else { - break - } - } - } + public func traverseInOrderForward(_ visit: (T) -> Void) { + var n: ThreadedBinaryTree + n = minimum() + while true { + visit(n.value) + if let successor = n.successor() { + n = successor + } else { + break + } + } + } - public func traverseInOrderBackward(_ visit: (T) -> Void) { - var n: ThreadedBinaryTree - n = maximum() - while true { - visit(n.value) - if let predecessor = n.predecessor() { - n = predecessor - } else { - break - } - } - } + public func traverseInOrderBackward(_ visit: (T) -> Void) { + var n: ThreadedBinaryTree + n = maximum() + while true { + visit(n.value) + if let predecessor = n.predecessor() { + n = predecessor + } else { + break + } + } + } - public func traversePreOrder(_ visit: (T) -> Void) { - visit(value) - left?.traversePreOrder(visit) - right?.traversePreOrder(visit) - } + public func traversePreOrder(_ visit: (T) -> Void) { + visit(value) + left?.traversePreOrder(visit) + right?.traversePreOrder(visit) + } - public func traversePostOrder(_ visit: (T) -> Void) { - left?.traversePostOrder(visit) - right?.traversePostOrder(visit) - visit(value) - } + public func traversePostOrder(_ visit: (T) -> Void) { + left?.traversePostOrder(visit) + right?.traversePostOrder(visit) + visit(value) + } - /* - Performs an in-order traversal and collects the results in an array. - */ - public func map(formula: (T) -> T) -> [T] { - var a = [T]() - var n: ThreadedBinaryTree - n = minimum() - while true { - a.append(formula(n.value)) - if let successor = n.successor() { - n = successor - } else { - break - } - } - return a - } + /* + Performs an in-order traversal and collects the results in an array. + */ + public func map(formula: (T) -> T) -> [T] { + var a = [T]() + var n: ThreadedBinaryTree + n = minimum() + while true { + a.append(formula(n.value)) + if let successor = n.successor() { + n = successor + } else { + break + } + } + return a + } } // MARK: - Verification extension ThreadedBinaryTree { - /* - Is this threaded binary tree a valid binary search tree? - */ - public func isBST(minValue: T, maxValue: T) -> Bool { - if value < minValue || value > maxValue { return false } - let leftBST = left?.isBST(minValue: minValue, maxValue: value) ?? true - let rightBST = right?.isBST(minValue: value, maxValue: maxValue) ?? true - return leftBST && rightBST - } + /* + Is this threaded binary tree a valid binary search tree? + */ + public func isBST(minValue: T, maxValue: T) -> Bool { + if value < minValue || value > maxValue { return false } + let leftBST = left?.isBST(minValue: minValue, maxValue: value) ?? true + let rightBST = right?.isBST(minValue: value, maxValue: maxValue) ?? true + return leftBST && rightBST + } - /* - Is this binary tree properly threaded? - Either left or leftThread (but not both) must be nil (likewise for right). - The first and last nodes in the in-order traversal are exempt from this, - as the first has leftThread = nil, and the last has rightThread = nil. - */ - public func isThreaded() -> Bool { - if left == nil && leftThread == nil { - if self !== minimum() { return false } - } - if left != nil && leftThread != nil { - return false - } - if right == nil && rightThread == nil { - if self !== maximum() { return false } - } - if right != nil && rightThread != nil { - return false - } - let leftThreaded = left?.isThreaded() ?? true - let rightThreaded = right?.isThreaded() ?? true - return leftThreaded && rightThreaded - } + /* + Is this binary tree properly threaded? + Either left or leftThread (but not both) must be nil (likewise for right). + The first and last nodes in the in-order traversal are exempt from this, + as the first has leftThread = nil, and the last has rightThread = nil. + */ + public func isThreaded() -> Bool { + if left == nil && leftThread == nil { + if self !== minimum() { return false } + } + if left != nil && leftThread != nil { + return false + } + if right == nil && rightThread == nil { + if self !== maximum() { return false } + } + if right != nil && rightThread != nil { + return false + } + let leftThreaded = left?.isThreaded() ?? true + let rightThreaded = right?.isThreaded() ?? true + return leftThreaded && rightThreaded + } } // MARK: - Debugging extension ThreadedBinaryTree: CustomStringConvertible { - public var description: String { - var s = "" - if let left = left { - s += "(\(left.description)) <- " - } - s += "\(value)" - if let right = right { - s += " -> (\(right.description))" - } - return s + public var description: String { + var s = "" + if let left = left { + s += "(\(left.description)) <- " } + s += "\(value)" + if let right = right { + s += " -> (\(right.description))" + } + return s + } } extension ThreadedBinaryTree: CustomDebugStringConvertible { - public var debugDescription: String { - var s = "value: \(value)" - if let parent = parent { - s += ", parent: \(parent.value)" - } - if let leftThread = leftThread { - s += ", leftThread: \(leftThread.value)" - } - if let rightThread = rightThread { - s += ", rightThread: \(rightThread.value)" - } - if let left = left { - s += ", left = [" + left.debugDescription + "]" - } - if let right = right { - s += ", right = [" + right.debugDescription + "]" - } - return s + public var debugDescription: String { + var s = "value: \(value)" + if let parent = parent { + s += ", parent: \(parent.value)" } - - public func toArray() -> [T] { - return map { $0 } + if let leftThread = leftThread { + s += ", leftThread: \(leftThread.value)" } + if let rightThread = rightThread { + s += ", rightThread: \(rightThread.value)" + } + if let left = left { + s += ", left = [" + left.debugDescription + "]" + } + if let right = right { + s += ", right = [" + right.debugDescription + "]" + } + return s + } + + public func toArray() -> [T] { + return map { $0 } + } } From c1c1a55904bf2f02c426ddcda33633443fe82656 Mon Sep 17 00:00:00 2001 From: vincentngo Date: Wed, 8 Feb 2017 00:29:35 -0500 Subject: [PATCH 0815/1679] fix warning --- .../Sources/ThreadedBinaryTree.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Threaded Binary Tree/ThreadedBinaryTree.playground/Sources/ThreadedBinaryTree.swift b/Threaded Binary Tree/ThreadedBinaryTree.playground/Sources/ThreadedBinaryTree.swift index a4d308e77..6f438c0cf 100644 --- a/Threaded Binary Tree/ThreadedBinaryTree.playground/Sources/ThreadedBinaryTree.swift +++ b/Threaded Binary Tree/ThreadedBinaryTree.playground/Sources/ThreadedBinaryTree.swift @@ -176,7 +176,7 @@ extension ThreadedBinaryTree { // If this in-order successor has a right child of its own (it cannot // have a left child by definition), then that must take its place. - successor.remove() + _ = successor.remove() // Connect our left child with the new node. successor.left = left From e149dac200ddd46d110fa94a39c539fde919adf4 Mon Sep 17 00:00:00 2001 From: Yurii Samsoniuk Date: Sat, 11 Feb 2017 16:31:04 +0100 Subject: [PATCH 0816/1679] Create big enough array for merge results --- Merge Sort/MergeSort.swift | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Merge Sort/MergeSort.swift b/Merge Sort/MergeSort.swift index f77d1cd84..990c432fa 100644 --- a/Merge Sort/MergeSort.swift +++ b/Merge Sort/MergeSort.swift @@ -18,6 +18,9 @@ func merge(leftPile: [T], rightPile: [T]) -> [T] { var leftIndex = 0 var rightIndex = 0 var orderedPile = [T]() + if orderedPile.capacity < leftPile.count + rightPile.count { + orderedPile.reserveCapacity(leftPile.count + rightPile.count) + } while leftIndex < leftPile.count && rightIndex < rightPile.count { if leftPile[leftIndex] < rightPile[rightIndex] { From bfef1ee575456b66f1cb483750f2f6164dcea7a5 Mon Sep 17 00:00:00 2001 From: Yurii Samsoniuk Date: Sat, 11 Feb 2017 16:32:34 +0100 Subject: [PATCH 0817/1679] Also update workspace content --- Merge Sort/MergeSort.playground/Contents.swift | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Merge Sort/MergeSort.playground/Contents.swift b/Merge Sort/MergeSort.playground/Contents.swift index 2952fc299..137dd19e2 100644 --- a/Merge Sort/MergeSort.playground/Contents.swift +++ b/Merge Sort/MergeSort.playground/Contents.swift @@ -12,6 +12,9 @@ func merge(leftPile: [T], rightPile: [T]) -> [T] { var leftIndex = 0 var rightIndex = 0 var orderedPile = [T]() + if orderedPile.capacity < leftPile.count + rightPile.count { + orderedPile.reserveCapacity(leftPile.count + rightPile.count) + } while leftIndex < leftPile.count && rightIndex < rightPile.count { if leftPile[leftIndex] < rightPile[rightIndex] { From 8f57fbb8635df485a125cad192c9685999b71b22 Mon Sep 17 00:00:00 2001 From: Yurii Samsoniuk Date: Mon, 13 Feb 2017 09:49:30 +0100 Subject: [PATCH 0818/1679] Use string interpolation for the whole description string --- Binary Tree/BinaryTree.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Binary Tree/BinaryTree.swift b/Binary Tree/BinaryTree.swift index ad5fcfd13..61ae696c7 100644 --- a/Binary Tree/BinaryTree.swift +++ b/Binary Tree/BinaryTree.swift @@ -21,7 +21,7 @@ extension BinaryTree: CustomStringConvertible { public var description: String { switch self { case let .node(left, value, right): - return "value: \(value), left = [" + left.description + "], right = [" + right.description + "]" + return "value: \(value), left = [\(left.description)], right = [\(right.description)]" case .empty: return "" } From b68b3b9309ecea1d56e8c5bf40779156abfafbe1 Mon Sep 17 00:00:00 2001 From: Yurii Samsoniuk Date: Mon, 13 Feb 2017 09:50:24 +0100 Subject: [PATCH 0819/1679] Updated playground content --- Binary Tree/BinaryTree.playground/Contents.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Binary Tree/BinaryTree.playground/Contents.swift b/Binary Tree/BinaryTree.playground/Contents.swift index b4d65ec1f..aa084e44d 100644 --- a/Binary Tree/BinaryTree.playground/Contents.swift +++ b/Binary Tree/BinaryTree.playground/Contents.swift @@ -18,7 +18,7 @@ extension BinaryTree: CustomStringConvertible { public var description: String { switch self { case let .node(left, value, right): - return "value: \(value), left = [" + left.description + "], right = [" + right.description + "]" + return "value: \(value), left = [\(left.description)], right = [\(right.description)]" case .empty: return "" } From 0155784b6cb0860d66f877439ebfe0acfa8ff29f Mon Sep 17 00:00:00 2001 From: Yurii Samsoniuk Date: Mon, 13 Feb 2017 09:51:23 +0100 Subject: [PATCH 0820/1679] Updated README content --- Binary Tree/README.markdown | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Binary Tree/README.markdown b/Binary Tree/README.markdown index 52089b8e7..896116dda 100644 --- a/Binary Tree/README.markdown +++ b/Binary Tree/README.markdown @@ -58,8 +58,7 @@ extension BinaryTree: CustomStringConvertible { public var description: String { switch self { case let .node(left, value, right): - return "value: \(value), left = [" + left.description + "], right = [" - + right.description + "]" + return "value: \(value), left = [\(left.description)], right = [\(right.description)]" case .empty: return "" } From cb64ed6034f91f5a300d0f728f08a4c09cd3e8f0 Mon Sep 17 00:00:00 2001 From: abhisood Date: Mon, 13 Feb 2017 03:13:53 -0800 Subject: [PATCH 0821/1679] Trie - Support prefix matching Solves issue #378 --- Trie/Trie/Trie/Trie.swift | 54 ++++++++++++++++++++++++----- Trie/Trie/TrieTests/TrieTests.swift | 16 +++++++++ 2 files changed, 61 insertions(+), 9 deletions(-) diff --git a/Trie/Trie/Trie/Trie.swift b/Trie/Trie/Trie/Trie.swift index 0e11a9c61..cc310b9ee 100644 --- a/Trie/Trie/Trie/Trie.swift +++ b/Trie/Trie/Trie/Trie.swift @@ -135,7 +135,26 @@ extension Trie { } return currentNode.isTerminating } - + + + /// Attempts to walk to the last node of a word. The + /// search will fail if the word is not present. Doesn't + /// check if the node is terminating + /// + /// - Parameter word: the word in question + /// - Returns: the node where the search ended, nil if the + /// search failed. + private func findLastNodeOf(word: String) -> Node? { + var currentNode = root + for character in word.lowercased().characters { + guard let childNode = currentNode.children[character] else { + return nil + } + currentNode = childNode + } + return currentNode + } + /// Attempts to walk to the terminating node of a word. The /// search will fail if the word is not present. /// @@ -143,14 +162,11 @@ extension Trie { /// - Returns: the node where the search ended, nil if the /// search failed. private func findTerminalNodeOf(word: String) -> Node? { - var currentNode = root - for character in word.lowercased().characters { - guard let childNode = currentNode.children[character] else { - return nil - } - currentNode = childNode + if let lastNode = findLastNodeOf(word: word) { + return lastNode.isTerminating ? lastNode : nil } - return currentNode.isTerminating ? currentNode : nil + return nil + } /// Deletes a word from the trie by starting with the last letter @@ -201,7 +217,7 @@ extension Trie { /// - rootNode: the root node of the subtrie /// - partialWord: the letters collected by traversing to this node /// - Returns: the words in the subtrie - func wordsInSubtrie(rootNode: Node, partialWord: String) -> [String] { + fileprivate func wordsInSubtrie(rootNode: Node, partialWord: String) -> [String] { var subtrieWords = [String]() var previousLetters = partialWord if let value = rootNode.value { @@ -216,4 +232,24 @@ extension Trie { } return subtrieWords } + + /// Returns an array of words in a subtrie of the trie that start + /// with given prefix + /// + /// - Parameters: + /// - prefix: the letters for word prefix + /// - Returns: the words in the subtrie that start with prefix + func findWordsWithPrefix(prefix: String) -> [String] { + var words = [String]() + if let lastNode = findLastNodeOf(word: prefix) { + if lastNode.isTerminating { + words.append(prefix) + } + for childNode in lastNode.children.values { + let childWords = wordsInSubtrie(rootNode: childNode, partialWord: prefix) + words += childWords + } + } + return words + } } diff --git a/Trie/Trie/TrieTests/TrieTests.swift b/Trie/Trie/TrieTests/TrieTests.swift index f8e934f0d..de41663a9 100644 --- a/Trie/Trie/TrieTests/TrieTests.swift +++ b/Trie/Trie/TrieTests/TrieTests.swift @@ -168,4 +168,20 @@ class TrieTests: XCTestCase { XCTAssertEqual(trieCopy.count, trie.count) } + + func testFindWordsWithPrefix() { + let trie = Trie() + trie.insert(word: "test") + trie.insert(word: "another") + trie.insert(word: "exam") + let wordsAll = trie.findWordsWithPrefix(prefix: "") + XCTAssertEqual(wordsAll.sorted(), ["another", "exam", "test"]); + let words = trie.findWordsWithPrefix(prefix: "ex") + XCTAssertEqual(words, ["exam"]); + trie.insert(word: "examination") + let words2 = trie.findWordsWithPrefix(prefix: "exam") + XCTAssertEqual(words2, ["exam", "examination"]); + let noWords = trie.findWordsWithPrefix(prefix: "tee") + XCTAssertEqual(noWords, []); + } } From 9c5a98dc5f64b941f38596088fd867f601a97af7 Mon Sep 17 00:00:00 2001 From: abhisood Date: Mon, 13 Feb 2017 03:58:25 -0800 Subject: [PATCH 0822/1679] Handle uppercase prefix --- Trie/Trie/Trie/Trie.swift | 7 ++++--- Trie/Trie/TrieTests/TrieTests.swift | 8 ++++++++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/Trie/Trie/Trie/Trie.swift b/Trie/Trie/Trie/Trie.swift index cc310b9ee..4321479c3 100644 --- a/Trie/Trie/Trie/Trie.swift +++ b/Trie/Trie/Trie/Trie.swift @@ -241,12 +241,13 @@ extension Trie { /// - Returns: the words in the subtrie that start with prefix func findWordsWithPrefix(prefix: String) -> [String] { var words = [String]() - if let lastNode = findLastNodeOf(word: prefix) { + let prefixLowerCased = prefix.lowercased() + if let lastNode = findLastNodeOf(word: prefixLowerCased) { if lastNode.isTerminating { - words.append(prefix) + words.append(prefixLowerCased) } for childNode in lastNode.children.values { - let childWords = wordsInSubtrie(rootNode: childNode, partialWord: prefix) + let childWords = wordsInSubtrie(rootNode: childNode, partialWord: prefixLowerCased) words += childWords } } diff --git a/Trie/Trie/TrieTests/TrieTests.swift b/Trie/Trie/TrieTests/TrieTests.swift index de41663a9..a75c35c62 100644 --- a/Trie/Trie/TrieTests/TrieTests.swift +++ b/Trie/Trie/TrieTests/TrieTests.swift @@ -183,5 +183,13 @@ class TrieTests: XCTestCase { XCTAssertEqual(words2, ["exam", "examination"]); let noWords = trie.findWordsWithPrefix(prefix: "tee") XCTAssertEqual(noWords, []); + let unicodeWord = "😬😎" + trie.insert(word: unicodeWord) + let wordsUnicode = trie.findWordsWithPrefix(prefix: "😬") + XCTAssertEqual(wordsUnicode, [unicodeWord]); + trie.insert(word: "Team") + let wordsUpperCase = trie.findWordsWithPrefix(prefix: "Te") + XCTAssertEqual(wordsUpperCase.sorted(), ["team", "test"]); + } } From ba3975281965852471a40f7a58514fa1d98d1578 Mon Sep 17 00:00:00 2001 From: Adrian Date: Wed, 15 Feb 2017 18:11:12 -0500 Subject: [PATCH 0823/1679] Update CountingSort.swift to Swift 3.0 syntax Updated to Swift 3.0 syntax --- Counting Sort/CountingSort.swift | 66 ++++++++++++++++---------------- 1 file changed, 34 insertions(+), 32 deletions(-) diff --git a/Counting Sort/CountingSort.swift b/Counting Sort/CountingSort.swift index d37bb2eff..9a1ffb373 100644 --- a/Counting Sort/CountingSort.swift +++ b/Counting Sort/CountingSort.swift @@ -6,39 +6,41 @@ // Copyright © 2016 Ali Hafizji. All rights reserved. // -enum CountingSortError: ErrorType { - case arrayEmpty +import Foundation + +enum CountingSortError: Error { + case arrayEmpty } func countingSort(array: [Int]) throws -> [Int] { - guard array.count > 0 else { - throw CountingSortError.arrayEmpty - } - - // Step 1 - // Create an array to store the count of each element - let maxElement = array.maxElement() ?? 0 - - var countArray = [Int](count: Int(maxElement + 1), repeatedValue: 0) - for element in array { - countArray[element] += 1 - } - - // Step 2 - // Set each value to be the sum of the previous two values - for index in 1 ..< countArray.count { - let sum = countArray[index] + countArray[index - 1] - countArray[index] = sum - } - - print(countArray) - - // Step 3 - // Place the element in the final array as per the number of elements before it - var sortedArray = [Int](count: array.count, repeatedValue: 0) - for element in array { - countArray[element] -= 1 - sortedArray[countArray[element]] = element - } - return sortedArray + guard array.count > 0 else { + throw CountingSortError.arrayEmpty + } + + // Step 1 + // Create an array to store the count of each element + let maxElement = array.max() ?? 0 + + var countArray = [Int](repeating: 0, count: Int(maxElement + 1)) + for element in array { + countArray[element] += 1 + } + + // Step 2 + // Set each value to be the sum of the previous two values + for index in 1 ..< countArray.count { + let sum = countArray[index] + countArray[index - 1] + countArray[index] = sum + } + + print(countArray) + + // Step 3 + // Place the element in the final array as per the number of elements before it + var sortedArray = [Int](repeating: 0, count: array.count) + for element in array { + countArray[element] -= 1 + sortedArray[countArray[element]] = element + } + return sortedArray } From 0b93a48f4dd66111fb9033e187cb4176d51d6dc0 Mon Sep 17 00:00:00 2001 From: Timur Galimov Date: Sat, 18 Feb 2017 02:20:13 +0300 Subject: [PATCH 0824/1679] Quadtree --- QuadTree/QuadTree.playground/Contents.swift | 14 + .../Sources/QuadTree.swift | 290 ++++++++++++++++++ .../QuadTree.playground/contents.xcplayground | 4 + .../contents.xcworkspacedata | 7 + QuadTree/README.md | 158 ++++++++++ .../Tests/Tests.xcodeproj/project.pbxproj | 274 +++++++++++++++++ .../contents.xcworkspacedata | 7 + QuadTree/Tests/Tests/Info.plist | 22 ++ QuadTree/Tests/Tests/Tests.swift | 85 +++++ 9 files changed, 861 insertions(+) create mode 100644 QuadTree/QuadTree.playground/Contents.swift create mode 100644 QuadTree/QuadTree.playground/Sources/QuadTree.swift create mode 100644 QuadTree/QuadTree.playground/contents.xcplayground create mode 100644 QuadTree/QuadTree.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 QuadTree/README.md create mode 100644 QuadTree/Tests/Tests.xcodeproj/project.pbxproj create mode 100644 QuadTree/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 QuadTree/Tests/Tests/Info.plist create mode 100644 QuadTree/Tests/Tests/Tests.swift diff --git a/QuadTree/QuadTree.playground/Contents.swift b/QuadTree/QuadTree.playground/Contents.swift new file mode 100644 index 000000000..41e73147f --- /dev/null +++ b/QuadTree/QuadTree.playground/Contents.swift @@ -0,0 +1,14 @@ + +import Foundation + +let tree = QuadTree(rect: Rect(origin: Point(0, 0), size: Size(xLength: 10, yLength: 10))) + +for _ in 0..<40 { + let randomX = Double(arc4random_uniform(100)) / 10 + let randomY = Double(arc4random_uniform(100)) / 10 + let point = Point(randomX, randomY) + tree.add(point: point) +} + +print(tree) +print(tree.points(inRect: Rect(origin: Point(1, 1), size: Size(xLength: 5, yLength: 5)))) diff --git a/QuadTree/QuadTree.playground/Sources/QuadTree.swift b/QuadTree/QuadTree.playground/Sources/QuadTree.swift new file mode 100644 index 000000000..beec4a7b7 --- /dev/null +++ b/QuadTree/QuadTree.playground/Sources/QuadTree.swift @@ -0,0 +1,290 @@ + +public struct Point { + let x: Double + let y: Double + + public init(_ x: Double, _ y: Double) { + self.x = x + self.y = y + } +} + +extension Point: CustomStringConvertible { + public var description: String { + return "Point(\(x), \(y))" + } +} + +public struct Size: CustomStringConvertible { + var xLength: Double + var yLength: Double + + public init(xLength: Double, yLength: Double) { + precondition(xLength >= 0, "xLength can not be negative") + precondition(yLength >= 0, "yLength can not be negative") + self.xLength = xLength + self.yLength = yLength + } + + var half: Size { + return Size(xLength: xLength / 2, yLength: yLength / 2) + } + + public var description: String { + return "Size(\(xLength), \(yLength))" + } +} + +public struct Rect { + // left top vertice + var origin: Point + var size: Size + + public init(origin: Point, size: Size) { + self.origin = origin + self.size = size + } + + var minX: Double { + return origin.x + } + + var minY: Double { + return origin.y + } + + var maxX: Double { + return origin.x + size.xLength + } + + var maxY: Double { + return origin.y + size.yLength + } + + func containts(point: Point) -> Bool { + return (minX <= point.x && point.x <= maxX) && + (minY <= point.y && point.y <= maxY) + } + + var leftTopRect: Rect { + return Rect(origin: origin, size: size.half) + } + + var leftBottomRect: Rect { + return Rect(origin: Point(origin.x, origin.y + size.half.yLength), size: size.half) + } + + var rightTopRect: Rect { + return Rect(origin: Point(origin.x + size.half.xLength, origin.y), size: size.half) + } + + var rightBottomRect: Rect { + return Rect(origin: Point(origin.x + size.half.xLength, origin.y + size.half.yLength), size: size.half) + } + + func intersects(rect: Rect) -> Bool { + + func lineSegmentsIntersect(lStart: Double, lEnd: Double, rStart: Double, rEnd: Double) -> Bool { + return max(lStart, rStart) <= min(lEnd, rEnd) + } + // to intersect, both horizontal and vertical projections need to intersect + // horizontal + if !lineSegmentsIntersect(lStart: minX, lEnd: maxX, rStart: rect.minX, rEnd: rect.maxX) { + return false + } + + // vertical + return lineSegmentsIntersect(lStart: minY, lEnd: maxY, rStart: rect.minY, rEnd: rect.maxY) + } +} + +extension Rect: CustomStringConvertible { + public var description: String { + return "Rect(\(origin), \(size))" + } +} + +protocol PointsContainter { + func add(point: Point) -> Bool + func points(inRect rect: Rect) -> [Point] +} + +class QuadTreeNode { + + enum NodeType { + case leaf + case `internal`(children: Children) + } + + struct Children: Sequence { + let leftTop: QuadTreeNode + let leftBottom: QuadTreeNode + let rightTop: QuadTreeNode + let rightBottom: QuadTreeNode + + init(parentNode: QuadTreeNode) { + leftTop = QuadTreeNode(rect: parentNode.rect.leftTopRect) + leftBottom = QuadTreeNode(rect: parentNode.rect.leftBottomRect) + rightTop = QuadTreeNode(rect: parentNode.rect.rightTopRect) + rightBottom = QuadTreeNode(rect: parentNode.rect.rightBottomRect) + } + + struct ChildrenIterator: IteratorProtocol { + private var index = 0 + private let children: Children + + init(children: Children) { + self.children = children + } + + mutating func next() -> QuadTreeNode? { + + defer { index += 1 } + + switch index { + case 0: return children.leftTop + case 1: return children.leftBottom + case 2: return children.rightTop + case 3: return children.rightBottom + default: return nil + } + } + } + + public func makeIterator() -> ChildrenIterator { + return ChildrenIterator(children: self) + } + } + + var points: [Point] = [] + let rect: Rect + var type: NodeType = .leaf + + static let maxPointCapacity = 3 + + init(rect: Rect) { + self.rect = rect + } + + var recursiveDescription: String { + return recursiveDescription(withTabCount: 0) + } + + private func recursiveDescription(withTabCount count: Int) -> String { + let indent = String(repeating: "\t", count: count) + var result = "\(indent)" + description + "\n" + switch type { + case .internal(let children): + for child in children { + result += child.recursiveDescription(withTabCount: count + 1) + } + default: + break + } + return result + } +} + +extension QuadTreeNode: PointsContainter { + + @discardableResult + func add(point: Point) -> Bool { + if !rect.containts(point: point) { + return false + } + + switch type { + case .internal(let children): + // pass the point to one of the children + for child in children { + if child.add(point: point) { + return true + } + } + + fatalError("rect.containts evaluted to true, but none of the children added the point") + case .leaf: + points.append(point) + // if the max capacity was reached, become an internal node + if points.count == QuadTreeNode.maxPointCapacity { + subdivide() + } + } + return true + } + + private func subdivide() { + switch type { + case .leaf: + type = .internal(children: Children(parentNode: self)) + case .internal: + preconditionFailure("Calling subdivide on an internal node") + } + } + + func points(inRect rect: Rect) -> [Point] { + + // if the node's rect and the given rect don't intersect, return an empty array, + // because there can't be any points that lie the node's (or its children's) rect and + // in the given rect + if !self.rect.intersects(rect: rect) { + return [] + } + + var result: [Point] = [] + + // collect the node's points that lie in the rect + for point in points { + if rect.containts(point: point) { + result.append(point) + } + } + + switch type { + case .leaf: + break + case .internal(let children): + // recursively add children's points that lie in the rect + for childNode in children { + result.append(contentsOf: childNode.points(inRect: rect)) + } + } + + return result + } +} + +extension QuadTreeNode: CustomStringConvertible { + var description: String { + switch type { + case .leaf: + return "leaf \(rect) Points: \(points)" + case .internal: + return "parent \(rect) Points: \(points)" + } + } +} + +public class QuadTree: PointsContainter { + + let root: QuadTreeNode + + public init(rect: Rect) { + self.root = QuadTreeNode(rect: rect) + } + + @discardableResult + public func add(point: Point) -> Bool { + return root.add(point: point) + } + + public func points(inRect rect: Rect) -> [Point] { + return root.points(inRect: rect) + } +} + +extension QuadTree: CustomStringConvertible { + public var description: String { + return "Quad tree\n" + root.recursiveDescription + } +} diff --git a/QuadTree/QuadTree.playground/contents.xcplayground b/QuadTree/QuadTree.playground/contents.xcplayground new file mode 100644 index 000000000..5da2641c9 --- /dev/null +++ b/QuadTree/QuadTree.playground/contents.xcplayground @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/QuadTree/QuadTree.playground/playground.xcworkspace/contents.xcworkspacedata b/QuadTree/QuadTree.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/QuadTree/QuadTree.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/QuadTree/README.md b/QuadTree/README.md new file mode 100644 index 000000000..77ac8b8fa --- /dev/null +++ b/QuadTree/README.md @@ -0,0 +1,158 @@ +# QuadTree + +A quadtree is a [tree](https://github.com/raywenderlich/swift-algorithm-club/tree/master/Tree) in which each internal (not leaf) node has four children. + +### Problem + +Consider the following problem: your need to store a number of points (each point is a pair of `X` and `Y` coordinates) and then you need to answer which points lie in a certain rectangular region. A naive solution would be to store the points inside an array and then iterate over the points and check each one individually. This solution runs in O(n) though. + +### A Better Approach + +Quadrees are most commonly used to partition a two-dimensional space by recursively subdividing it into four regions(quadrants). Let's see how we can use a Quadtree to store the points. + +Each node in the tree represents a rectangular region and stores a limited number(`maxPointCapacity`) of points that all lie in its region. + +```swift +class QuadTreeNode { + + enum NodeType { + case leaf + case `internal`(children: Children) + } + + struct Children { + let leftTop: QuadTreeNode + let leftBottom: QuadTreeNode + let rightTop: QuadTreeNode + let rightBottom: QuadTreeNode + + ... + } + + var points: [Point] = [] + let rect: Rect + var type: NodeType = .leaf + + static let maxPointCapacity = 3 + + init(rect: Rect) { + self.rect = rect + } + + ... +} + +``` +Once the limit in a leaf node is reached, four child nodes are added to the node and they represent `topLeft`, `topRight`, `bottomLeft`, `bottomRight` quadrants of the node's rect; each of the consequent points in the rect will be passed to one of the children. Thus, new points are always added to leaf nodes. + +```swift +extension QuadTreeNode { + + @discardableResult + func add(point: Point) -> Bool { + + if !rect.containts(point: point) { + return false + } + + switch type { + case .internal(let children): + // pass the point to one of the children + for child in children { + if child.add(point: point) { + return true + } + } + return false // should never happen + case .leaf: + points.append(point) + // if the max capacity was reached, become an internal node + if points.count == QuadTreeNode.maxPointCapacity { + subdivide() + } + } + return true + } + + private func subdivide() { + switch type { + case .leaf: + type = .internal(children: Children(parentNode: self)) + case .internal: + preconditionFailure("Calling subdivide on an internal node") + } + } +} + +extension Children { + + init(parentNode: QuadTreeNode) { + leftTop = QuadTreeNode(rect: parentNode.rect.leftTopRect) + leftBottom = QuadTreeNode(rect: parentNode.rect.leftBottomRect) + rightTop = QuadTreeNode(rect: parentNode.rect.rightTopRect) + rightBottom = QuadTreeNode(rect: parentNode.rect.rightBottomRect) + } +} + +``` + +To find the points that lie in a given region we can now traverse the tree from top to bottom and collect the suitable points from nodes. + +```swift + +class QuadTree { + + ... + + let root: QuadTreeNode + + public func points(inRect rect: Rect) -> [Point] { + return root.points(inRect: rect) + } +} + +extension QuadTreeNode { + func points(inRect rect: Rect) -> [Point] { + + // if the node's rect and the given rect don't intersect, return an empty array, + // because there can't be any points that lie the node's (or its children's) rect and + // in the given rect + if !self.rect.intersects(rect: rect) { + return [] + } + + var result: [Point] = [] + + // collect the node's points that lie in the rect + for point in points { + if rect.containts(point: point) { + result.append(point) + } + } + + switch type { + case .leaf: + break + case .internal(children: let children): + // recursively add children's points that lie in the rect + for childNode in children { + result.append(contentsOf: childNode.points(inRect: rect)) + } + } + + return result + } +} + +``` + +Both adding a point and searching can still take up to O(n) in the worst case, since the tree isn't balanced in any way. However, on average it runs significantly faster (something comparable to O(log n)). + +### See also + +Displaying a large amount of objects in a MapView - a great use case for a Quadtree ([Thoughtbot Atricle](https://robots.thoughtbot.com/how-to-handle-large-amounts-of-data-on-maps)) + +More info on [Wiki](https://en.wikipedia.org/wiki/Quadtree) + +*Written for Swift Algorithm Club by Timur Galimov* + diff --git a/QuadTree/Tests/Tests.xcodeproj/project.pbxproj b/QuadTree/Tests/Tests.xcodeproj/project.pbxproj new file mode 100644 index 000000000..a972bf534 --- /dev/null +++ b/QuadTree/Tests/Tests.xcodeproj/project.pbxproj @@ -0,0 +1,274 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 82EF3AAE1E50E77800013ECB /* Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82EF3AAD1E50E77800013ECB /* Tests.swift */; }; + 82EF3AB51E50E82400013ECB /* QuadTree.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82EF3AB41E50E82400013ECB /* QuadTree.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 82EF3AAA1E50E77800013ECB /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 82EF3AAD1E50E77800013ECB /* Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tests.swift; sourceTree = ""; }; + 82EF3AAF1E50E77800013ECB /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 82EF3AB41E50E82400013ECB /* QuadTree.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = QuadTree.swift; path = ../QuadTree.playground/Sources/QuadTree.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 82EF3AA71E50E77800013ECB /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 82EF3A9F1E50E74900013ECB = { + isa = PBXGroup; + children = ( + 82EF3AB41E50E82400013ECB /* QuadTree.swift */, + 82EF3AAC1E50E77800013ECB /* Tests */, + 82EF3AAB1E50E77800013ECB /* Products */, + ); + sourceTree = ""; + }; + 82EF3AAB1E50E77800013ECB /* Products */ = { + isa = PBXGroup; + children = ( + 82EF3AAA1E50E77800013ECB /* Tests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 82EF3AAC1E50E77800013ECB /* Tests */ = { + isa = PBXGroup; + children = ( + 82EF3AAD1E50E77800013ECB /* Tests.swift */, + 82EF3AAF1E50E77800013ECB /* Info.plist */, + ); + path = Tests; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 82EF3AA91E50E77800013ECB /* Tests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 82EF3AB01E50E77800013ECB /* Build configuration list for PBXNativeTarget "Tests" */; + buildPhases = ( + 82EF3AA61E50E77800013ECB /* Sources */, + 82EF3AA71E50E77800013ECB /* Frameworks */, + 82EF3AA81E50E77800013ECB /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Tests; + productName = Tests; + productReference = 82EF3AAA1E50E77800013ECB /* Tests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 82EF3AA01E50E74900013ECB /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0820; + LastUpgradeCheck = 0820; + TargetAttributes = { + 82EF3AA91E50E77800013ECB = { + CreatedOnToolsVersion = 8.2.1; + DevelopmentTeam = 34BUG46ZSN; + ProvisioningStyle = Automatic; + }; + }; + }; + buildConfigurationList = 82EF3AA31E50E74900013ECB /* Build configuration list for PBXProject "Tests" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 82EF3A9F1E50E74900013ECB; + productRefGroup = 82EF3AAB1E50E77800013ECB /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 82EF3AA91E50E77800013ECB /* Tests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 82EF3AA81E50E77800013ECB /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 82EF3AA61E50E77800013ECB /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 82EF3AB51E50E82400013ECB /* QuadTree.swift in Sources */, + 82EF3AAE1E50E77800013ECB /* Tests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 82EF3AA41E50E74900013ECB /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + }; + name = Debug; + }; + 82EF3AA51E50E74900013ECB /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + }; + name = Release; + }; + 82EF3AB11E50E77800013ECB /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + DEVELOPMENT_TEAM = 34BUG46ZSN; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + INFOPLIST_FILE = Tests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.12; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_BUNDLE_IDENTIFIER = com.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 3.0; + }; + name = Debug; + }; + 82EF3AB21E50E77800013ECB /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEVELOPMENT_TEAM = 34BUG46ZSN; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + INFOPLIST_FILE = Tests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.12; + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_BUNDLE_IDENTIFIER = com.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_VERSION = 3.0; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 82EF3AA31E50E74900013ECB /* Build configuration list for PBXProject "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 82EF3AA41E50E74900013ECB /* Debug */, + 82EF3AA51E50E74900013ECB /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 82EF3AB01E50E77800013ECB /* Build configuration list for PBXNativeTarget "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 82EF3AB11E50E77800013ECB /* Debug */, + 82EF3AB21E50E77800013ECB /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 82EF3AA01E50E74900013ECB /* Project object */; +} diff --git a/QuadTree/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/QuadTree/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..6c0ea8493 --- /dev/null +++ b/QuadTree/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/QuadTree/Tests/Tests/Info.plist b/QuadTree/Tests/Tests/Info.plist new file mode 100644 index 000000000..6c6c23c43 --- /dev/null +++ b/QuadTree/Tests/Tests/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + diff --git a/QuadTree/Tests/Tests/Tests.swift b/QuadTree/Tests/Tests/Tests.swift new file mode 100644 index 000000000..b7bcda4e6 --- /dev/null +++ b/QuadTree/Tests/Tests/Tests.swift @@ -0,0 +1,85 @@ +// +// Tests.swift +// Tests +// +// Created by Timur Galimov on 12/02/2017. +// +// + +import XCTest + +extension Point: Equatable { + +} + +public func ==(lhs: Point, rhs: Point) -> Bool { + return lhs.x == rhs.x && lhs.y == rhs.y +} + +class Tests: XCTestCase { + + func testRectContains() { + let rect = Rect(origin: Point(0, 0), size: Size(xLength: 3, yLength: 3)) + + XCTAssertTrue(rect.containts(point: Point(1, 1))) + XCTAssertTrue(rect.containts(point: Point(0, 0))) + XCTAssertTrue(rect.containts(point: Point(0, 3))) + XCTAssertTrue(rect.containts(point: Point(3, 3))) + + XCTAssertFalse(rect.containts(point: Point(-1, 1))) + XCTAssertFalse(rect.containts(point: Point(-0.1, 0.1))) + XCTAssertFalse(rect.containts(point: Point(0, 3.1))) + XCTAssertFalse(rect.containts(point: Point(-4, 1))) + } + + func testIntersects() { + let rect = Rect(origin: Point(0, 0), size: Size(xLength: 5, yLength: 5)) + let rect2 = Rect(origin: Point(1, 1), size: Size(xLength: 1, yLength: 1)) + XCTAssertTrue(rect.intersects(rect: rect2)) + + let rect3 = Rect(origin: Point(1, 0), size: Size(xLength: 1, yLength: 10)) + let rect4 = Rect(origin: Point(0, 1), size: Size(xLength: 10, yLength: 1)) + XCTAssertTrue(rect3.intersects(rect: rect4)) + + let rect5 = Rect(origin: Point(0, 0), size: Size(xLength: 4, yLength: 4)) + let rect6 = Rect(origin: Point(2, 2), size: Size(xLength: 4, yLength: 4)) + XCTAssertTrue(rect5.intersects(rect: rect6)) + + let rect7 = Rect(origin: Point(0, 0), size: Size(xLength: 4, yLength: 4)) + let rect8 = Rect(origin: Point(4, 4), size: Size(xLength: 1, yLength: 1)) + XCTAssertTrue(rect7.intersects(rect: rect8)) + + let rect9 = Rect(origin: Point(-1, -1), size: Size(xLength: 0.5, yLength: 0.5)) + let rect10 = Rect(origin: Point(0, 0), size: Size(xLength: 1, yLength: 1)) + XCTAssertFalse(rect9.intersects(rect: rect10)) + + let rect11 = Rect(origin: Point(0, 0), size: Size(xLength: 2, yLength: 1)) + let rect12 = Rect(origin: Point(3, 0), size: Size(xLength: 1, yLength: 1)) + XCTAssertFalse(rect11.intersects(rect: rect12)) + } + + func testQuadTree() { + let rect = Rect(origin: Point(0, 0), size: Size(xLength: 5, yLength: 5)) + let qt = QuadTree(rect: rect) + + XCTAssertTrue(qt.points(inRect: rect) == [Point]()) + + XCTAssertFalse(qt.add(point: Point(-0.1, 0.1))) + + XCTAssertTrue(qt.points(inRect: rect) == [Point]()) + + XCTAssertTrue(qt.add(point: Point(1, 1))) + XCTAssertTrue(qt.add(point: Point(3, 3))) + XCTAssertTrue(qt.add(point: Point(4, 4))) + XCTAssertTrue(qt.add(point: Point(0.5, 0.5))) + + XCTAssertFalse(qt.add(point: Point(5.5, 0))) + XCTAssertFalse(qt.add(point: Point(5.5, 1))) + XCTAssertFalse(qt.add(point: Point(5.5, 2))) + + XCTAssertTrue(qt.add(point: Point(1.5, 1.5))) + + let rect2 = Rect(origin: Point(0, 0), size: Size(xLength: 2, yLength: 2)) + XCTAssertTrue(qt.points(inRect: rect2) == [Point(1, 1), Point(0.5, 0.5), Point(1.5, 1.5)]) + } +} From c1952ec2f66b4ce98d82d3e948e43af4be77809d Mon Sep 17 00:00:00 2001 From: Jaap Wijnen Date: Sat, 18 Feb 2017 02:18:53 +0100 Subject: [PATCH 0825/1679] finalize migration tests (#381) * finalize migration tests * fix * fixes * test fixes * fix bounded priority queue --- .travis.yml | 23 ++++--- .../Sources/BoundedPriorityQueue.swift | 2 +- .../BoundedPriorityQueue.swift | 30 ++++----- .../Tests/Tests.xcodeproj/project.pbxproj | 42 +++++++++++- .../xcshareddata/xcschemes/Tests.xcscheme | 2 +- Counting Sort/CountingSort.swift | 66 +++++++++---------- .../Tests/Tests.xcodeproj/project.pbxproj | 10 ++- .../xcshareddata/xcschemes/Tests.xcscheme | 2 +- Depth-First Search/Tests/Graph.swift | 38 +++++------ .../Tests/Tests.xcodeproj/project.pbxproj | 10 ++- .../xcshareddata/xcschemes/Tests.xcscheme | 2 +- Graph/Graph.xcodeproj/project.pbxproj | 5 +- Graph/GraphTests/GraphTests.swift | 24 +++---- Heap/Tests/HeapTests.swift | 12 ++-- Heap/Tests/Tests.xcodeproj/project.pbxproj | 2 +- .../Tests/Tests.xcodeproj/project.pbxproj | 2 +- Quicksort/Quicksort.swift | 20 +++--- Quicksort/Tests/QuicksortTests.swift | 6 +- .../Tests/Tests.xcodeproj/project.pbxproj | 10 ++- .../xcshareddata/xcschemes/Tests.xcscheme | 2 +- .../Tests/MaximumTests.swift | 2 +- .../Tests/MinimumMaximumPairsTests.swift | 4 +- .../Tests/MinimumTests.swift | 2 +- Select Minimum Maximum/Tests/TestHelper.swift | 2 +- .../Tests/Tests.xcodeproj/project.pbxproj | 10 ++- .../xcshareddata/xcschemes/Tests.xcscheme | 2 +- 26 files changed, 202 insertions(+), 130 deletions(-) diff --git a/.travis.yml b/.travis.yml index 2b2bafd14..b6ff6190c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,30 +15,29 @@ script: - xcodebuild test -project ./Boyer-Moore/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Binary\ Search\ Tree/Solution\ 1/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Bloom\ Filter/Tests/Tests.xcodeproj -scheme Tests -# - xcodebuild test -project ./Bounded\ Priority\ Queue/Tests/Tests.xcodeproj -scheme Tests -# - xcodebuild test -project ./Breadth-First\ Search/Tests/Tests.xcodeproj -scheme Tests +- xcodebuild test -project ./Bounded\ Priority\ Queue/Tests/Tests.xcodeproj -scheme Tests +- xcodebuild test -project ./Breadth-First\ Search/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Bucket\ Sort/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./B-Tree/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Comb\ Sort/Tests/Tests.xcodeproj -scheme Tests -# - xcodebuild test -project ./Counting\ Sort/Tests/Tests.xcodeproj -scheme Tests -# - xcodebuild test -project ./Depth-First\ Search/Tests/Tests.xcodeproj -scheme Tests -# - xcodebuild test -project ./Graph/Graph.xcodeproj -scheme GraphTests -# - xcodebuild test -project ./Heap/Tests/Tests.xcodeproj -scheme Tests +- xcodebuild test -project ./Counting\ Sort/Tests/Tests.xcodeproj -scheme Tests +- xcodebuild test -project ./Depth-First\ Search/Tests/Tests.xcodeproj -scheme Tests +- xcodebuild test -project ./Graph/Graph.xcodeproj -scheme GraphTests +- xcodebuild test -project ./Heap/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Heap\ Sort/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Insertion\ Sort/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./K-Means/Tests/Tests.xcodeproj -scheme Tests -# - xcodebuild test -project ./Linked\ List/Tests/Tests.xcodeproj -scheme Tests +- xcodebuild test -project ./Linked\ List/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Longest\ Common\ Subsequence/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Minimum\ Spanning\ Tree\ \(Unweighted\)/Tests/Tests.xcodeproj -scheme Tests -# - xcodebuild test -project ./Priority\ Queue/Tests/Tests.xcodeproj -scheme Tests +- xcodebuild test -project ./Priority\ Queue/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Queue/Tests/Tests.xcodeproj -scheme Tests -# - xcodebuild test -project ./Quicksort/Tests/Tests.xcodeproj -scheme Tests +- xcodebuild test -project ./Quicksort/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Radix\ Sort/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Rootish\ Array\ Stack/Tests/Tests.xcodeproj -scheme Tests -# - xcodebuild test -project ./Run-Length\ Encoding/Tests/Tests.xcodeproj -scheme Tests -# - xcodebuild test -project ./Select\ Minimum\ Maximum/Tests/Tests.xcodeproj -scheme Tests +- xcodebuild test -project ./Select\ Minimum\ Maximum/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Selection\ Sort/Tests/Tests.xcodeproj -scheme Tests -# - xcodebuild test -project ./Shell\ Sort/Tests/Tests.xcodeproj -scheme Tests +- xcodebuild test -project ./Shell\ Sort/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Shortest\ Path\ \(Unweighted\)/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Single-Source\ Shortest\ Paths\ \(Weighted\)/SSSP.xcodeproj -scheme SSSPTests - xcodebuild test -project ./Stack/Tests/Tests.xcodeproj -scheme Tests diff --git a/Bounded Priority Queue/BoundedPriorityQueue.playground/Sources/BoundedPriorityQueue.swift b/Bounded Priority Queue/BoundedPriorityQueue.playground/Sources/BoundedPriorityQueue.swift index fc399811d..b94863afc 100644 --- a/Bounded Priority Queue/BoundedPriorityQueue.playground/Sources/BoundedPriorityQueue.swift +++ b/Bounded Priority Queue/BoundedPriorityQueue.playground/Sources/BoundedPriorityQueue.swift @@ -9,7 +9,7 @@ public class LinkedListNode { } public class BoundedPriorityQueue { - private typealias Node = LinkedListNode + fileprivate typealias Node = LinkedListNode private(set) public var count = 0 fileprivate var head: Node? diff --git a/Bounded Priority Queue/BoundedPriorityQueue.swift b/Bounded Priority Queue/BoundedPriorityQueue.swift index fbd8d5450..d882a7698 100644 --- a/Bounded Priority Queue/BoundedPriorityQueue.swift +++ b/Bounded Priority Queue/BoundedPriorityQueue.swift @@ -1,4 +1,4 @@ -public class LinkedListNode { +open class LinkedListNode { var value: T var next: LinkedListNode? var previous: LinkedListNode? @@ -8,27 +8,27 @@ public class LinkedListNode { } } -public class BoundedPriorityQueue { - private typealias Node = LinkedListNode +open class BoundedPriorityQueue { + fileprivate typealias Node = LinkedListNode - private(set) public var count = 0 - private var head: Node? - private var tail: Node? - private var maxElements: Int + fileprivate(set) open var count = 0 + fileprivate var head: Node? + fileprivate var tail: Node? + fileprivate var maxElements: Int public init(maxElements: Int) { self.maxElements = maxElements } - public var isEmpty: Bool { + open var isEmpty: Bool { return count == 0 } - public func peek() -> T? { + open func peek() -> T? { return head?.value } - public func enqueue(value: T) { + open func enqueue(_ value: T) { if let node = insert(value, after: findInsertionPoint(value)) { // If the newly inserted node is the last one in the list, then update // the tail pointer. @@ -44,7 +44,7 @@ public class BoundedPriorityQueue { } } - private func insert(value: T, after: Node?) -> Node? { + fileprivate func insert(_ value: T, after: Node?) -> Node? { if let previous = after { // If the queue is full and we have to insert at the end of the list, @@ -78,18 +78,18 @@ public class BoundedPriorityQueue { /* Find the node after which to insert the new value. If this returns nil, the new value should be inserted at the head of the list. */ - private func findInsertionPoint(value: T) -> Node? { + fileprivate func findInsertionPoint(_ value: T) -> Node? { var node = head var prev: Node? = nil - while let current = node where value < current.value { + while let current = node, value < current.value { prev = node node = current.next } return prev } - private func removeLeastImportantElement() { + fileprivate func removeLeastImportantElement() { if let last = tail { tail = last.previous tail?.next = nil @@ -101,7 +101,7 @@ public class BoundedPriorityQueue { // this is much slower on large lists. } - public func dequeue() -> T? { + open func dequeue() -> T? { if let first = head { count -= 1 if count == 0 { diff --git a/Bounded Priority Queue/Tests/Tests.xcodeproj/project.pbxproj b/Bounded Priority Queue/Tests/Tests.xcodeproj/project.pbxproj index 6fd5c0b46..842c51695 100644 --- a/Bounded Priority Queue/Tests/Tests.xcodeproj/project.pbxproj +++ b/Bounded Priority Queue/Tests/Tests.xcodeproj/project.pbxproj @@ -82,10 +82,11 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; - LastUpgradeCheck = 0720; + LastUpgradeCheck = 0820; TargetAttributes = { B80004B21C83E342001FE2D7 = { CreatedOnToolsVersion = 7.2.1; + LastSwiftMigration = 0820; }; }; }; @@ -132,12 +133,49 @@ B80004AD1C83E324001FE2D7 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + ONLY_ACTIVE_ARCH = YES; }; name = Debug; }; B80004AE1C83E324001FE2D7 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; }; name = Release; }; @@ -188,6 +226,7 @@ SDKROOT = macosx; SWIFT_OBJC_BRIDGING_HEADER = ""; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -230,6 +269,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = macosx; SWIFT_OBJC_BRIDGING_HEADER = ""; + SWIFT_VERSION = 3.0; }; name = Release; }; diff --git a/Bounded Priority Queue/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Bounded Priority Queue/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme index 0416248f1..8bb763edd 100644 --- a/Bounded Priority Queue/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme +++ b/Bounded Priority Queue/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -1,6 +1,6 @@ [Int] { - guard array.count > 0 else { - throw CountingSortError.arrayEmpty - } - - // Step 1 - // Create an array to store the count of each element - let maxElement = array.max() ?? 0 - - var countArray = [Int](repeating: 0, count: Int(maxElement + 1)) - for element in array { - countArray[element] += 1 - } - - // Step 2 - // Set each value to be the sum of the previous two values - for index in 1 ..< countArray.count { - let sum = countArray[index] + countArray[index - 1] - countArray[index] = sum - } - - print(countArray) - - // Step 3 - // Place the element in the final array as per the number of elements before it - var sortedArray = [Int](repeating: 0, count: array.count) - for element in array { - countArray[element] -= 1 - sortedArray[countArray[element]] = element - } - return sortedArray +func countingSort(_ array: [Int]) throws -> [Int] { + guard array.count > 0 else { + throw CountingSortError.arrayEmpty + } + + // Step 1 + // Create an array to store the count of each element + let maxElement = array.max() ?? 0 + + var countArray = [Int](repeating: 0, count: Int(maxElement + 1)) + for element in array { + countArray[element] += 1 + } + + // Step 2 + // Set each value to be the sum of the previous two values + for index in 1 ..< countArray.count { + let sum = countArray[index] + countArray[index - 1] + countArray[index] = sum + } + + print(countArray) + + // Step 3 + // Place the element in the final array as per the number of elements before it + var sortedArray = [Int](repeating: 0, count: array.count) + for element in array { + countArray[element] -= 1 + sortedArray[countArray[element]] = element + } + return sortedArray } diff --git a/Counting Sort/Tests/Tests.xcodeproj/project.pbxproj b/Counting Sort/Tests/Tests.xcodeproj/project.pbxproj index 6801bb587..5cbb0d4aa 100644 --- a/Counting Sort/Tests/Tests.xcodeproj/project.pbxproj +++ b/Counting Sort/Tests/Tests.xcodeproj/project.pbxproj @@ -83,11 +83,12 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; - LastUpgradeCheck = 0720; + LastUpgradeCheck = 0820; ORGANIZATIONNAME = "Swift Algorithm Club"; TargetAttributes = { 7B2BBC7F1C779D720067B71D = { CreatedOnToolsVersion = 7.2; + LastSwiftMigration = 0820; }; }; }; @@ -145,8 +146,10 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; @@ -189,8 +192,10 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; @@ -209,6 +214,7 @@ MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; }; name = Release; }; @@ -220,6 +226,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -231,6 +238,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Release; }; diff --git a/Counting Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Counting Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme index 8ef8d8581..dfcf6de42 100644 --- a/Counting Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme +++ b/Counting Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -1,6 +1,6 @@ Bool { // MARK: - Node -public class Node: CustomStringConvertible, Equatable { - public var neighbors: [Edge] +open class Node: CustomStringConvertible, Equatable { + open var neighbors: [Edge] - public private(set) var label: String - public var distance: Int? - public var visited: Bool + open fileprivate(set) var label: String + open var distance: Int? + open var visited: Bool public init(label: String) { self.label = label @@ -27,19 +27,19 @@ public class Node: CustomStringConvertible, Equatable { visited = false } - public var description: String { + open var description: String { if let distance = distance { return "Node(label: \(label), distance: \(distance))" } return "Node(label: \(label), distance: infinity)" } - public var hasDistance: Bool { + open var hasDistance: Bool { return distance != nil } - public func remove(edge: Edge) { - neighbors.removeAtIndex(neighbors.indexOf { $0 === edge }!) + open func remove(_ edge: Edge) { + neighbors.remove(at: neighbors.index { $0 === edge }!) } } @@ -49,25 +49,25 @@ public func == (lhs: Node, rhs: Node) -> Bool { // MARK: - Graph -public class Graph: CustomStringConvertible, Equatable { - public private(set) var nodes: [Node] +open class Graph: CustomStringConvertible, Equatable { + open fileprivate(set) var nodes: [Node] public init() { self.nodes = [] } - public func addNode(label: String) -> Node { + open func addNode(_ label: String) -> Node { let node = Node(label: label) nodes.append(node) return node } - public func addEdge(source: Node, neighbor: Node) { + open func addEdge(_ source: Node, neighbor: Node) { let edge = Edge(neighbor: neighbor) source.neighbors.append(edge) } - public var description: String { + open var description: String { var description = "" for node in nodes { @@ -78,15 +78,15 @@ public class Graph: CustomStringConvertible, Equatable { return description } - public func findNodeWithLabel(label: String) -> Node { + open func findNodeWithLabel(_ label: String) -> Node { return nodes.filter { $0.label == label }.first! } - public func duplicate() -> Graph { + open func duplicate() -> Graph { let duplicated = Graph() for node in nodes { - duplicated.addNode(node.label) + _ = duplicated.addNode(node.label) } for node in nodes { diff --git a/Depth-First Search/Tests/Tests.xcodeproj/project.pbxproj b/Depth-First Search/Tests/Tests.xcodeproj/project.pbxproj index 9e2872f88..dbc44ecd4 100644 --- a/Depth-First Search/Tests/Tests.xcodeproj/project.pbxproj +++ b/Depth-First Search/Tests/Tests.xcodeproj/project.pbxproj @@ -86,11 +86,12 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; - LastUpgradeCheck = 0720; + LastUpgradeCheck = 0820; ORGANIZATIONNAME = "Swift Algorithm Club"; TargetAttributes = { 7B2BBC7F1C779D720067B71D = { CreatedOnToolsVersion = 7.2; + LastSwiftMigration = 0820; }; }; }; @@ -149,8 +150,10 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; @@ -193,8 +196,10 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; @@ -213,6 +218,7 @@ MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; }; name = Release; }; @@ -226,6 +232,7 @@ PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -238,6 +245,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Release; }; diff --git a/Depth-First Search/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Depth-First Search/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme index e5bd10d97..4462aede0 100644 --- a/Depth-First Search/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme +++ b/Depth-First Search/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -1,6 +1,6 @@ .Type) { + func testEdgesFromReturnsCorrectEdgeInSingleEdgeDirecedGraphWithType(_ graphType: AbstractGraph.Type) { let graph = graphType.init() let a = graph.createVertex(1) @@ -71,7 +71,7 @@ class GraphTests: XCTestCase { XCTAssertEqual(edgesFromA.first?.to, b) } - func testEdgesFromReturnsCorrectEdgeInSingleEdgeUndirectedGraphWithType(graphType: AbstractGraph.Type) { + func testEdgesFromReturnsCorrectEdgeInSingleEdgeUndirectedGraphWithType(_ graphType: AbstractGraph.Type) { let graph = graphType.init() let a = graph.createVertex(1) @@ -89,7 +89,7 @@ class GraphTests: XCTestCase { XCTAssertEqual(edgesFromB.first?.to, a) } - func testEdgesFromReturnsNoEdgesInNoEdgeGraphWithType(graphType: AbstractGraph.Type) { + func testEdgesFromReturnsNoEdgesInNoEdgeGraphWithType(_ graphType: AbstractGraph.Type) { let graph = graphType.init() let a = graph.createVertex(1) @@ -99,7 +99,7 @@ class GraphTests: XCTestCase { XCTAssertEqual(graph.edgesFrom(b).count, 0) } - func testEdgesFromReturnsCorrectEdgesInBiggerGraphInDirectedGraphWithType(graphType: AbstractGraph.Type) { + func testEdgesFromReturnsCorrectEdgesInBiggerGraphInDirectedGraphWithType(_ graphType: AbstractGraph.Type) { let graph = graphType.init() let verticesCount = 100 var vertices: [Vertex] = [] @@ -125,34 +125,34 @@ class GraphTests: XCTestCase { } func testEdgesFromReturnsCorrectEdgeInSingleEdgeDirecedMatrixGraph() { - testEdgesFromReturnsCorrectEdgeInSingleEdgeDirecedGraphWithType(AdjacencyMatrixGraph) + testEdgesFromReturnsCorrectEdgeInSingleEdgeDirecedGraphWithType(AdjacencyMatrixGraph.self) } func testEdgesFromReturnsCorrectEdgeInSingleEdgeUndirectedMatrixGraph() { - testEdgesFromReturnsCorrectEdgeInSingleEdgeUndirectedGraphWithType(AdjacencyMatrixGraph) + testEdgesFromReturnsCorrectEdgeInSingleEdgeUndirectedGraphWithType(AdjacencyMatrixGraph.self) } func testEdgesFromReturnsNoInNoEdgeMatrixGraph() { - testEdgesFromReturnsNoEdgesInNoEdgeGraphWithType(AdjacencyMatrixGraph) + testEdgesFromReturnsNoEdgesInNoEdgeGraphWithType(AdjacencyMatrixGraph.self) } func testEdgesFromReturnsCorrectEdgesInBiggerGraphInDirectedMatrixGraph() { - testEdgesFromReturnsCorrectEdgesInBiggerGraphInDirectedGraphWithType(AdjacencyMatrixGraph) + testEdgesFromReturnsCorrectEdgesInBiggerGraphInDirectedGraphWithType(AdjacencyMatrixGraph.self) } func testEdgesFromReturnsCorrectEdgeInSingleEdgeDirecedListGraph() { - testEdgesFromReturnsCorrectEdgeInSingleEdgeDirecedGraphWithType(AdjacencyListGraph) + testEdgesFromReturnsCorrectEdgeInSingleEdgeDirecedGraphWithType(AdjacencyListGraph.self) } func testEdgesFromReturnsCorrectEdgeInSingleEdgeUndirectedListGraph() { - testEdgesFromReturnsCorrectEdgeInSingleEdgeUndirectedGraphWithType(AdjacencyListGraph) + testEdgesFromReturnsCorrectEdgeInSingleEdgeUndirectedGraphWithType(AdjacencyListGraph.self) } func testEdgesFromReturnsNoInNoEdgeListGraph() { - testEdgesFromReturnsNoEdgesInNoEdgeGraphWithType(AdjacencyListGraph) + testEdgesFromReturnsNoEdgesInNoEdgeGraphWithType(AdjacencyListGraph.self) } func testEdgesFromReturnsCorrectEdgesInBiggerGraphInDirectedListGraph() { - testEdgesFromReturnsCorrectEdgesInBiggerGraphInDirectedGraphWithType(AdjacencyListGraph) + testEdgesFromReturnsCorrectEdgesInBiggerGraphInDirectedGraphWithType(AdjacencyListGraph.self) } } diff --git a/Heap/Tests/HeapTests.swift b/Heap/Tests/HeapTests.swift index c5b479f14..0e6c504f3 100644 --- a/Heap/Tests/HeapTests.swift +++ b/Heap/Tests/HeapTests.swift @@ -197,27 +197,27 @@ class HeapTests: XCTestCase { XCTAssertEqual(h.elements, [100, 50, 70, 10, 20, 60, 65]) //test index out of bounds - let v = h.removeAt(index: 10) + let v = h.removeAt(10) XCTAssertEqual(v, nil) XCTAssertTrue(verifyMaxHeap(h)) XCTAssertEqual(h.elements, [100, 50, 70, 10, 20, 60, 65]) - let v1 = h.removeAt(index: 5) + let v1 = h.removeAt(5) XCTAssertEqual(v1, 60) XCTAssertTrue(verifyMaxHeap(h)) XCTAssertEqual(h.elements, [100, 50, 70, 10, 20, 65]) - let v2 = h.removeAt(index: 4) + let v2 = h.removeAt(4) XCTAssertEqual(v2, 20) XCTAssertTrue(verifyMaxHeap(h)) XCTAssertEqual(h.elements, [100, 65, 70, 10, 50]) - let v3 = h.removeAt(index: 4) + let v3 = h.removeAt(4) XCTAssertEqual(v3, 50) XCTAssertTrue(verifyMaxHeap(h)) XCTAssertEqual(h.elements, [100, 65, 70, 10]) - let v4 = h.removeAt(index: 0) + let v4 = h.removeAt(0) XCTAssertEqual(v4, 100) XCTAssertTrue(verifyMaxHeap(h)) XCTAssertEqual(h.elements, [70, 65, 10]) @@ -270,7 +270,7 @@ class HeapTests: XCTestCase { let m = (n + 1)/2 for k in 1...m { let i = Int(arc4random_uniform(UInt32(n - k + 1))) - let v = h.removeAt(index: i)! + let v = h.removeAt(i)! let j = a.index(of: v)! a.remove(at: j) diff --git a/Heap/Tests/Tests.xcodeproj/project.pbxproj b/Heap/Tests/Tests.xcodeproj/project.pbxproj index 9319e2089..22112fa60 100644 --- a/Heap/Tests/Tests.xcodeproj/project.pbxproj +++ b/Heap/Tests/Tests.xcodeproj/project.pbxproj @@ -88,7 +88,7 @@ TargetAttributes = { 7B2BBC7F1C779D720067B71D = { CreatedOnToolsVersion = 7.2; - LastSwiftMigration = 0800; + LastSwiftMigration = 0820; }; }; }; diff --git a/Priority Queue/Tests/Tests.xcodeproj/project.pbxproj b/Priority Queue/Tests/Tests.xcodeproj/project.pbxproj index 77423c57a..0f7d84be9 100644 --- a/Priority Queue/Tests/Tests.xcodeproj/project.pbxproj +++ b/Priority Queue/Tests/Tests.xcodeproj/project.pbxproj @@ -91,7 +91,7 @@ TargetAttributes = { 7B2BBC7F1C779D720067B71D = { CreatedOnToolsVersion = 7.2; - LastSwiftMigration = 0800; + LastSwiftMigration = 0820; }; }; }; diff --git a/Quicksort/Quicksort.swift b/Quicksort/Quicksort.swift index 6448dd815..39fa27b66 100644 --- a/Quicksort/Quicksort.swift +++ b/Quicksort/Quicksort.swift @@ -3,7 +3,7 @@ import Foundation /* Easy to understand but not very efficient. */ -func quicksort(a: [T]) -> [T] { +func quicksort(_ a: [T]) -> [T] { guard a.count > 1 else { return a } let pivot = a[a.count/2] @@ -29,7 +29,7 @@ func quicksort(a: [T]) -> [T] { if the pivot value occurs more than once, its duplicates will be found in the left partition. */ -func partitionLomuto(inout a: [T], low: Int, high: Int) -> Int { +func partitionLomuto(_ a: inout [T], low: Int, high: Int) -> Int { // We always use the highest item as the pivot. let pivot = a[high] @@ -56,7 +56,7 @@ func partitionLomuto(inout a: [T], low: Int, high: Int) -> Int { /* Recursive, in-place version that uses Lomuto's partioning scheme. */ -func quicksortLomuto(inout a: [T], low: Int, high: Int) { +func quicksortLomuto(_ a: inout [T], low: Int, high: Int) { if low < high { let p = partitionLomuto(&a, low: low, high: high) quicksortLomuto(&a, low: low, high: p - 1) @@ -80,7 +80,7 @@ func quicksortLomuto(inout a: [T], low: Int, high: Int) { Hoare scheme is more efficient than Lomuto's partition scheme; it performs fewer swaps. */ -func partitionHoare(inout a: [T], low: Int, high: Int) -> Int { +func partitionHoare(_ a: inout [T], low: Int, high: Int) -> Int { let pivot = a[low] var i = low - 1 var j = high + 1 @@ -101,7 +101,7 @@ func partitionHoare(inout a: [T], low: Int, high: Int) -> Int { Recursive, in-place version that uses Hoare's partioning scheme. Because of the choice of pivot, this performs badly if the array is already sorted. */ -func quicksortHoare(inout a: [T], low: Int, high: Int) { +func quicksortHoare(_ a: inout [T], low: Int, high: Int) { if low < high { let p = partitionHoare(&a, low: low, high: high) quicksortHoare(&a, low: low, high: p) @@ -112,7 +112,7 @@ func quicksortHoare(inout a: [T], low: Int, high: Int) { // MARK: - Randomized sort /* Returns a random integer in the range min...max, inclusive. */ -public func random(min min: Int, max: Int) -> Int { +public func random(min: Int, max: Int) -> Int { assert(min < max) return min + Int(arc4random_uniform(UInt32(max - min + 1))) } @@ -121,7 +121,7 @@ public func random(min min: Int, max: Int) -> Int { Uses a random pivot index. On average, this results in a well-balanced split of the input array. */ -func quicksortRandom(inout a: [T], low: Int, high: Int) { +func quicksortRandom(_ a: inout [T], low: Int, high: Int) { if low < high { // Create a random pivot index in the range [low...high]. let pivotIndex = random(min: low, max: high) @@ -142,7 +142,7 @@ func quicksortRandom(inout a: [T], low: Int, high: Int) { Swift's swap() doesn't like it if the items you're trying to swap refer to the same memory location. This little wrapper simply ignores such swaps. */ -public func swap(inout a: [T], _ i: Int, _ j: Int) { +public func swap(_ a: inout [T], _ i: Int, _ j: Int) { if i != j { swap(&a[i], &a[j]) } @@ -165,7 +165,7 @@ public func swap(inout a: [T], _ i: Int, _ j: Int) { Time complexity is O(n), space complexity is O(1). */ -func partitionDutchFlag(inout a: [T], low: Int, high: Int, pivotIndex: Int) -> (Int, Int) { +func partitionDutchFlag(_ a: inout [T], low: Int, high: Int, pivotIndex: Int) -> (Int, Int) { let pivot = a[pivotIndex] var smaller = low @@ -195,7 +195,7 @@ func partitionDutchFlag(inout a: [T], low: Int, high: Int, pivotI /* Uses Dutch national flag partitioning and a random pivot index. */ -func quicksortDutchFlag(inout a: [T], low: Int, high: Int) { +func quicksortDutchFlag(_ a: inout [T], low: Int, high: Int) { if low < high { let pivotIndex = random(min: low, max: high) let (p, q) = partitionDutchFlag(&a, low: low, high: high, pivotIndex: pivotIndex) diff --git a/Quicksort/Tests/QuicksortTests.swift b/Quicksort/Tests/QuicksortTests.swift index 00135b31f..c8d9a62e6 100644 --- a/Quicksort/Tests/QuicksortTests.swift +++ b/Quicksort/Tests/QuicksortTests.swift @@ -5,12 +5,12 @@ class QuicksortTests: XCTestCase { checkSortAlgorithm(quicksort) } - private typealias QuicksortFunction = (inout [Int], low: Int, high: Int) -> Void + fileprivate typealias QuicksortFunction = (inout [Int], _ low: Int, _ high: Int) -> Void - private func checkQuicksort(function: QuicksortFunction) { + fileprivate func checkQuicksort(_ function: QuicksortFunction) { checkSortAlgorithm { (a: [Int]) -> [Int] in var b = a - function(&b, low: 0, high: b.count - 1) + function(&b, 0, b.count - 1) return b } } diff --git a/Quicksort/Tests/Tests.xcodeproj/project.pbxproj b/Quicksort/Tests/Tests.xcodeproj/project.pbxproj index 8aecb59f8..2d8ee18ff 100644 --- a/Quicksort/Tests/Tests.xcodeproj/project.pbxproj +++ b/Quicksort/Tests/Tests.xcodeproj/project.pbxproj @@ -86,11 +86,12 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; - LastUpgradeCheck = 0720; + LastUpgradeCheck = 0820; ORGANIZATIONNAME = "Swift Algorithm Club"; TargetAttributes = { 7B2BBC7F1C779D720067B71D = { CreatedOnToolsVersion = 7.2; + LastSwiftMigration = 0820; }; }; }; @@ -149,8 +150,10 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; @@ -193,8 +196,10 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; @@ -213,6 +218,7 @@ MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; }; name = Release; }; @@ -224,6 +230,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -235,6 +242,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Release; }; diff --git a/Quicksort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Quicksort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme index 8ef8d8581..dfcf6de42 100644 --- a/Quicksort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme +++ b/Quicksort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -1,6 +1,6 @@ [UInt32] { +func createRandomList(_ numberOfElements: Int) -> [UInt32] { return (1...numberOfElements).map {_ in arc4random()} } diff --git a/Select Minimum Maximum/Tests/Tests.xcodeproj/project.pbxproj b/Select Minimum Maximum/Tests/Tests.xcodeproj/project.pbxproj index e2857d2b7..fb70d6970 100644 --- a/Select Minimum Maximum/Tests/Tests.xcodeproj/project.pbxproj +++ b/Select Minimum Maximum/Tests/Tests.xcodeproj/project.pbxproj @@ -98,11 +98,12 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; - LastUpgradeCheck = 0720; + LastUpgradeCheck = 0820; ORGANIZATIONNAME = "Swift Algorithm Club"; TargetAttributes = { 7B2BBC7F1C779D720067B71D = { CreatedOnToolsVersion = 7.2; + LastSwiftMigration = 0820; }; }; }; @@ -165,8 +166,10 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; @@ -209,8 +212,10 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; @@ -229,6 +234,7 @@ MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; }; name = Release; }; @@ -240,6 +246,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -251,6 +258,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Release; }; diff --git a/Select Minimum Maximum/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Select Minimum Maximum/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme index 8ef8d8581..dfcf6de42 100644 --- a/Select Minimum Maximum/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme +++ b/Select Minimum Maximum/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -1,6 +1,6 @@ Date: Sun, 19 Feb 2017 14:58:50 +0100 Subject: [PATCH 0826/1679] Convex Hull algorithm --- .../Convex Hull.xcodeproj/project.pbxproj | 297 ++++++++++++++++++ .../contents.xcworkspacedata | 7 + Convex Hull/Convex Hull/AppDelegate.swift | 57 ++++ .../AppIcon.appiconset/Contents.json | 93 ++++++ .../Base.lproj/LaunchScreen.storyboard | 27 ++ Convex Hull/Convex Hull/Info.plist | 47 +++ Convex Hull/Convex Hull/View.swift | 177 +++++++++++ Convex Hull/README.md | 41 +++ 8 files changed, 746 insertions(+) create mode 100644 Convex Hull/Convex Hull.xcodeproj/project.pbxproj create mode 100644 Convex Hull/Convex Hull.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 Convex Hull/Convex Hull/AppDelegate.swift create mode 100644 Convex Hull/Convex Hull/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 Convex Hull/Convex Hull/Base.lproj/LaunchScreen.storyboard create mode 100644 Convex Hull/Convex Hull/Info.plist create mode 100644 Convex Hull/Convex Hull/View.swift create mode 100644 Convex Hull/README.md diff --git a/Convex Hull/Convex Hull.xcodeproj/project.pbxproj b/Convex Hull/Convex Hull.xcodeproj/project.pbxproj new file mode 100644 index 000000000..2f236b013 --- /dev/null +++ b/Convex Hull/Convex Hull.xcodeproj/project.pbxproj @@ -0,0 +1,297 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 8E6D68BA1E59989400161780 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8E6D68B91E59989400161780 /* AppDelegate.swift */; }; + 8E6D68C11E59989400161780 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 8E6D68C01E59989400161780 /* Assets.xcassets */; }; + 8E6D68C41E59989400161780 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8E6D68C21E59989400161780 /* LaunchScreen.storyboard */; }; + 8E6D68CC1E599CF100161780 /* View.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8E6D68CB1E599CF100161780 /* View.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 8E6D68B61E59989400161780 /* Convex Hull.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Convex Hull.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 8E6D68B91E59989400161780 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 8E6D68C01E59989400161780 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 8E6D68C31E59989400161780 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 8E6D68C51E59989400161780 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 8E6D68CB1E599CF100161780 /* View.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = View.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 8E6D68B31E59989400161780 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 8E6D68AD1E59989400161780 = { + isa = PBXGroup; + children = ( + 8E6D68B81E59989400161780 /* Convex Hull */, + 8E6D68B71E59989400161780 /* Products */, + ); + sourceTree = ""; + }; + 8E6D68B71E59989400161780 /* Products */ = { + isa = PBXGroup; + children = ( + 8E6D68B61E59989400161780 /* Convex Hull.app */, + ); + name = Products; + sourceTree = ""; + }; + 8E6D68B81E59989400161780 /* Convex Hull */ = { + isa = PBXGroup; + children = ( + 8E6D68B91E59989400161780 /* AppDelegate.swift */, + 8E6D68CB1E599CF100161780 /* View.swift */, + 8E6D68C01E59989400161780 /* Assets.xcassets */, + 8E6D68C21E59989400161780 /* LaunchScreen.storyboard */, + 8E6D68C51E59989400161780 /* Info.plist */, + ); + path = "Convex Hull"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 8E6D68B51E59989400161780 /* Convex Hull */ = { + isa = PBXNativeTarget; + buildConfigurationList = 8E6D68C81E59989400161780 /* Build configuration list for PBXNativeTarget "Convex Hull" */; + buildPhases = ( + 8E6D68B21E59989400161780 /* Sources */, + 8E6D68B31E59989400161780 /* Frameworks */, + 8E6D68B41E59989400161780 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "Convex Hull"; + productName = "Convex Hull"; + productReference = 8E6D68B61E59989400161780 /* Convex Hull.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 8E6D68AE1E59989400161780 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0820; + LastUpgradeCheck = 0820; + ORGANIZATIONNAME = Workmoose; + TargetAttributes = { + 8E6D68B51E59989400161780 = { + CreatedOnToolsVersion = 8.2.1; + DevelopmentTeam = 7C4LVS3ZVC; + ProvisioningStyle = Automatic; + }; + }; + }; + buildConfigurationList = 8E6D68B11E59989400161780 /* Build configuration list for PBXProject "Convex Hull" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 8E6D68AD1E59989400161780; + productRefGroup = 8E6D68B71E59989400161780 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 8E6D68B51E59989400161780 /* Convex Hull */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 8E6D68B41E59989400161780 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 8E6D68C41E59989400161780 /* LaunchScreen.storyboard in Resources */, + 8E6D68C11E59989400161780 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 8E6D68B21E59989400161780 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 8E6D68BA1E59989400161780 /* AppDelegate.swift in Sources */, + 8E6D68CC1E599CF100161780 /* View.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 8E6D68C21E59989400161780 /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 8E6D68C31E59989400161780 /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 8E6D68C61E59989400161780 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 10.2; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 8E6D68C71E59989400161780 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 10.2; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 8E6D68C91E59989400161780 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + DEVELOPMENT_TEAM = 7C4LVS3ZVC; + INFOPLIST_FILE = "Convex Hull/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "workmoose.Convex-Hull"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; + }; + name = Debug; + }; + 8E6D68CA1E59989400161780 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + DEVELOPMENT_TEAM = 7C4LVS3ZVC; + INFOPLIST_FILE = "Convex Hull/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "workmoose.Convex-Hull"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 8E6D68B11E59989400161780 /* Build configuration list for PBXProject "Convex Hull" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 8E6D68C61E59989400161780 /* Debug */, + 8E6D68C71E59989400161780 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 8E6D68C81E59989400161780 /* Build configuration list for PBXNativeTarget "Convex Hull" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 8E6D68C91E59989400161780 /* Debug */, + 8E6D68CA1E59989400161780 /* Release */, + ); + defaultConfigurationIsVisible = 0; + }; +/* End XCConfigurationList section */ + }; + rootObject = 8E6D68AE1E59989400161780 /* Project object */; +} diff --git a/Convex Hull/Convex Hull.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Convex Hull/Convex Hull.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..dfcd4bc52 --- /dev/null +++ b/Convex Hull/Convex Hull.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Convex Hull/Convex Hull/AppDelegate.swift b/Convex Hull/Convex Hull/AppDelegate.swift new file mode 100644 index 000000000..1901083a8 --- /dev/null +++ b/Convex Hull/Convex Hull/AppDelegate.swift @@ -0,0 +1,57 @@ +// +// AppDelegate.swift +// Convex Hull +// +// Created by Jaap Wijnen on 19/02/2017. +// Copyright © 2017 Workmoose. All rights reserved. +// + +import UIKit + +@UIApplicationMain +class AppDelegate: UIResponder, UIApplicationDelegate { + + var window: UIWindow? + + + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { + + let screenBounds = UIScreen.main.bounds + + window = UIWindow(frame: screenBounds) + + let viewController = UIViewController() + viewController.view = View(frame: (window?.frame)!) + viewController.view.backgroundColor = .white + + window?.rootViewController = viewController + window?.makeKeyAndVisible() + + return true + } + + func applicationWillResignActive(_ application: UIApplication) { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. + } + + func applicationDidEnterBackground(_ application: UIApplication) { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. + } + + func applicationWillEnterForeground(_ application: UIApplication) { + // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. + } + + func applicationDidBecomeActive(_ application: UIApplication) { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. + } + + func applicationWillTerminate(_ application: UIApplication) { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. + } + + +} + diff --git a/Convex Hull/Convex Hull/Assets.xcassets/AppIcon.appiconset/Contents.json b/Convex Hull/Convex Hull/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 000000000..1d060ed28 --- /dev/null +++ b/Convex Hull/Convex Hull/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,93 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Convex Hull/Convex Hull/Base.lproj/LaunchScreen.storyboard b/Convex Hull/Convex Hull/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 000000000..fdf3f97d1 --- /dev/null +++ b/Convex Hull/Convex Hull/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Convex Hull/Convex Hull/Info.plist b/Convex Hull/Convex Hull/Info.plist new file mode 100644 index 000000000..390c5347e --- /dev/null +++ b/Convex Hull/Convex Hull/Info.plist @@ -0,0 +1,47 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIRequiredDeviceCapabilities + + armv7 + + UIRequiresFullScreen + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/Convex Hull/Convex Hull/View.swift b/Convex Hull/Convex Hull/View.swift new file mode 100644 index 000000000..2d7157e6f --- /dev/null +++ b/Convex Hull/Convex Hull/View.swift @@ -0,0 +1,177 @@ +// +// View.swift +// Convex Hull +// +// Created by Jaap Wijnen on 19/02/2017. +// Copyright © 2017 Workmoose. All rights reserved. +// + +import UIKit + +class View: UIView { + + let MAX_POINTS = 100 + + var points = [CGPoint]() + + var convexHull = [CGPoint]() + + override init(frame: CGRect) { + super.init(frame: frame) + + generatePoints() + quickHull(points: points) + } + + required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func generatePoints() { + for _ in 0.. Bool in + return a.x < b.x + } + } + + func quickHull(points: [CGPoint]) { + var pts = points + + // Assume points has at least 2 points + // Assume list is ordered on x + + // left most point + let p1 = pts.removeFirst() + // right most point + let p2 = pts.removeLast() + + // p1 and p2 are outer most points and thus are part of the hull + convexHull.append(p1) + convexHull.append(p2) + + // points to the right of oriented line from p1 to p2 + var s1 = [CGPoint]() + + // points to the right of oriented line from p2 to p1 + var s2 = [CGPoint]() + + // p1 to p2 line + let lineVec1 = CGPoint(x: p2.x - p1.x, y: p2.y - p1.y) + + for p in pts { // per point check if point is to right or left of p1 to p2 line + let pVec1 = CGPoint(x: p.x - p1.x, y: p.y - p1.y) + let sign1 = lineVec1.x * pVec1.y - pVec1.x * lineVec1.y // cross product to check on which side of the line point p is. + + if sign1 > 0 { // right of p1 p2 line (in a normal xy coordinate system this would be < 0 but due to the weird iPhone screen coordinates this is > 0 + s1.append(p) + } else { // right of p2 p1 line + s2.append(p) + } + } + + // find new hull points + findHull(s1, p1, p2) + findHull(s2, p2, p1) + } + + func findHull(_ points: [CGPoint], _ p1: CGPoint, _ p2: CGPoint) { + // if set of points is empty there are no points to the right of this line so this line is part of the hull. + if points.isEmpty { + return + } + + var pts = points + + // calculate parameters of general line equation y = a * x + b + let a = (p1.y - p2.y) / (p1.x - p2.x) + let b = p1.y - a * p1.x + + // calculate normal line's growth factor + let a1 = -1 / a + + var maxDist: CGFloat = -1 + var maxPoint: CGPoint = pts.first! + + for p in pts { // for every point check the distance from our line + let b1 = p.y - a1 * p.x // calculate offset to line equation for given point p + let x = -(b - b1)/(a - a1) // calculate x where the two lines intersect + let y = a * x + b // calculate y value of this intersect point + + let dist = pow(x - p.x, 2) + pow(y - p.y, 2) // calculate distance squared between intersection point and point p + if dist > maxDist { // if distance is larger than current maxDist remember new point p + maxDist = dist + maxPoint = p + } + } + + convexHull.insert(maxPoint, at: convexHull.index(of: p1)! + 1) // insert point with max distance from line in the convexHull after p1 + + pts.remove(at: pts.index(of: maxPoint)!) // remove maxPoint from points array as we are going to split this array in points left and right of the line + + // points to the right of oriented line from p1 to maxPoint + var s1 = [CGPoint]() + + // points to the right of oriented line from maxPoint to p2 + var s2 = [CGPoint]() + + // p1 to maxPoint line + let lineVec1 = CGPoint(x: maxPoint.x - p1.x, y: maxPoint.y - p1.y) + // maxPoint to p2 line + let lineVec2 = CGPoint(x: p2.x - maxPoint.x, y: p2.y - maxPoint.y) + + for p in pts { + let pVec1 = CGPoint(x: p.x - p1.x, y: p.y - p1.y) // vector from p1 to p + let sign1 = lineVec1.x * pVec1.y - pVec1.x * lineVec1.y // sign to check is p is to the right or left of lineVec1 + + let pVec2 = CGPoint(x: p.x - maxPoint.x, y: p.y - maxPoint.y) // vector from p2 to p + let sign2 = lineVec2.x * pVec2.y - pVec2.x * lineVec2.y // sign to check is p is to the right or left of lineVec2 + + if sign1 > 0 { // right of p1 maxPoint line + s1.append(p) + } else if sign2 > 0 { // right of maxPoint p2 line + s2.append(p) + } + } + + // find new hull points + findHull(s1, p1, maxPoint) + findHull(s2, maxPoint, p2) + } + + override func draw(_ rect: CGRect) { + + let context = UIGraphicsGetCurrentContext() + + // Draw hull + let lineWidth:CGFloat = 2.0 + + context!.setFillColor(UIColor.black.cgColor) + context!.setLineWidth(lineWidth) + context!.setStrokeColor(UIColor.red.cgColor) + context!.setFillColor(UIColor.black.cgColor) + + let firstPoint = convexHull.first! + context!.move(to: firstPoint) + + for p in convexHull.dropFirst() { + context!.addLine(to: p) + } + context!.addLine(to: firstPoint) + + context!.strokePath() + + // Draw points + for p in points { + let radius: CGFloat = 5 + let circleRect = CGRect(x: p.x - radius, y: p.y - radius, width: 2 * radius, height: 2 * radius) + context!.fillEllipse(in: circleRect) + } + } +} diff --git a/Convex Hull/README.md b/Convex Hull/README.md new file mode 100644 index 000000000..b73f66176 --- /dev/null +++ b/Convex Hull/README.md @@ -0,0 +1,41 @@ +# Convex Hull + +There are multiple Convex Hull algorithms. This particular implementation uses the Quickhull algorithm. + +Given a group of points on a plane. The Convex Hull algorithm calculates the shape (made up from the points itself) containing all these points. It can also be used on a collection of points of different dimention. This implementation however covers points on a plane. It essentially calculates the lines between points which together contain all points. + +## Quickhull + +The quickhull algorithm works as follows. +The algorithm takes an input of a collection of points. These points should be ordered on their x coordinate value. We pick the two points A and B with the smallest(A) and the largest(B) x coordinate. These of course have to be part of the hull. Imagine a line from point A to point B. All points to the right of this line are grouped in an array S1. Imagine now a line from point B to point A. (this is of course the same line as before just with opposite direction) Again all points to the right of this line are grouped in an array, S2 this time. +We now define the following recursive function: + +`findHull(points: [CGPoint], p1: CGPoint, p2: CGPoint)` + +``` +findHull(S1, A, B) +findHull(S2, B, A) +``` + +What this function does is the following: +1. If `points` is empty we return as there are no points to the right of our line to add to our hull. +2. Draw a line from `p1` to `p2`. +3. Find the point in `points` that is furthest away from this line. (`maxPoint`) +4. Add `maxPoint` to the hull right after `p1`. +5. Draw a line (`line1`) from `p1` to `maxPoint`. +6. Draw a line (`line2`) from `maxPoint` to `p2`. (These lines now form a triangle) +7. All points within this triangle are of course not part of the hull and thus can be ignored. We check which points in `points` are to the right of `line1` these are grouped in an array `s1`. +8. All points that are to the right of `line2` are grouped in an array `s2`. Note that there are no points that are both to the right of `line1` and `line2` as then `maxPoint` wouldn't be the point furthest away from our initial line between `p1` and `p2`. +9. We call `findHull(_, _, _)` again on our new groups of points to find more hull points. +``` +findHull(s1, p1, maxPoint) +findHull(s2, maxPoint, p2) +``` + +This eventually leaves us with an array of points describing the convex hull. + +## See also + +[Convex Hull on Wikipedia](https://en.wikipedia.org/wiki/Convex_hull_algorithms) + +*Written for the Swift Algorithm Club by Jaap Wijnen.* From 94c9b5f2b0306e9924c01486889b69934f34575a Mon Sep 17 00:00:00 2001 From: barbara Date: Sun, 19 Feb 2017 16:46:31 +0100 Subject: [PATCH 0827/1679] initial implementation fro Splay Trees Test in progress Debug in progress Playground in progress Documentation not started --- .../SplayTree.playground/Contents.swift | 7 + .../Sources/SplayTree.swift | 509 ++++++++++++++++ .../contents.xcplayground | 4 + .../contents.xcworkspacedata | 7 + Splay Tree/SplayTree.swift | 552 ++++++++++++++++++ Splay Tree/Tests/Info.plist | 22 + Splay Tree/Tests/SplayTreeTests.swift | 19 + Splay Tree/Tests/Tests-Bridging-Header.h | 4 + .../Tests/Tests.xcodeproj/project.pbxproj | 279 +++++++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/xcschemes/Tests.xcscheme | 101 ++++ 11 files changed, 1511 insertions(+) create mode 100644 Splay Tree/SplayTree.playground/Contents.swift create mode 100644 Splay Tree/SplayTree.playground/Sources/SplayTree.swift create mode 100644 Splay Tree/SplayTree.playground/contents.xcplayground create mode 100644 Splay Tree/SplayTree.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 Splay Tree/SplayTree.swift create mode 100644 Splay Tree/Tests/Info.plist create mode 100644 Splay Tree/Tests/SplayTreeTests.swift create mode 100644 Splay Tree/Tests/Tests-Bridging-Header.h create mode 100644 Splay Tree/Tests/Tests.xcodeproj/project.pbxproj create mode 100644 Splay Tree/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 Splay Tree/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme diff --git a/Splay Tree/SplayTree.playground/Contents.swift b/Splay Tree/SplayTree.playground/Contents.swift new file mode 100644 index 000000000..951ad4c5c --- /dev/null +++ b/Splay Tree/SplayTree.playground/Contents.swift @@ -0,0 +1,7 @@ +//: Playground - Splay Tree Implementation + + +let splayTree = SplayTree(array: [1]) +splayTree.insert(value: 2) +splayTree.insert(value: 10) +splayTree.insert(value: 6) diff --git a/Splay Tree/SplayTree.playground/Sources/SplayTree.swift b/Splay Tree/SplayTree.playground/Sources/SplayTree.swift new file mode 100644 index 000000000..f0c45e831 --- /dev/null +++ b/Splay Tree/SplayTree.playground/Sources/SplayTree.swift @@ -0,0 +1,509 @@ +/* + * Splay Tree + * + * Based on Binary Search Tree Implementation written by Nicolas Ameghino and Matthijs Hollemans for Swift Algorithms Club + * https://github.com/raywenderlich/swift-algorithm-club/blob/master/Binary%20Search%20Tree + * And extended for the specifics of a Splay Tree by Barbara Martina Rodeker + * + */ + +/** + Represent the 3 possible operations (combinations of rotations) that + could be performed during the Splay phase in Splay Trees + + - zigZag Left child of a right child OR right child of a left child + - zigZig Left child of a left child OR right child of a right child + - zig Only 1 parent and that parent is the root + + */ +public enum SplayOperation { + case zigZag + case zigZig + case zig + + + /** + Splay the given node up to the root of the tree + + - Parameters: + - node SplayTree node to move up to the root + */ + public static func splay(node: SplayTree) { + + while (node.parent != nil) { + operation(forNode: node).apply(onNode: node) + } + } + + /** + Compares the node and its parent and determine + if the rotations should be performed in a zigZag, zigZig or zig case. + + - Parmeters: + - forNode SplayTree node to be checked + - Returns + - Operation Case zigZag - zigZig - zig + */ + private static func operation(forNode node: SplayTree) -> SplayOperation { + + if let parent = node.parent, let grandParent = parent.parent { + if (node.isLeftChild && grandParent.isRightChild) || (node.isRightChild && grandParent.isLeftChild) { + return .zigZag + } + return .zigZig + } + return .zig + } + + /** + Applies the rotation associated to the case + Modifying the splay tree and briging the received node further to the top of the tree + + - Parameters: + - onNode Node to splay up. Should be alwayas the node that needs to be splayed, neither its parent neither it's grandparent + */ + private func apply(onNode node: SplayTree) { + switch self { + case .zigZag: + assert(node.parent != nil && node.parent!.parent != nil, "Should be at least 2 nodes up in the tree") + rotate(child: node, parent: node.parent!) + rotate(child: node, parent: node.parent!) + + case .zigZig: + assert(node.parent != nil && node.parent!.parent != nil, "Should be at least 2 nodes up in the tree") + rotate(child: node.parent!, parent: node.parent!.parent!) + rotate(child: node, parent: node.parent!) + + case .zig: + assert(node.parent != nil && node.parent!.parent == nil, "There should be a parent which is the root") + rotate(child: node, parent: node.parent!) + } + } + + /** + Performs a single rotation from a node to its parent + re-arranging the children properly + */ + private func rotate(child: SplayTree, parent: SplayTree) { + + assert(child.parent != nil && child.parent!.value == parent.value, "Parent and child.parent should match here") + + var grandchildToMode: SplayTree? + if child.isLeftChild { + + grandchildToMode = child.right + child.right = parent + parent.left = grandchildToMode + + } else { + + grandchildToMode = child.left + child.left = parent + parent.right = grandchildToMode + } + + let grandParent = parent.parent + parent.parent = child + child.parent = grandParent + } +} + +public class SplayTree { + + fileprivate(set) public var value: T + fileprivate(set) public var parent: SplayTree? + fileprivate(set) public var left: SplayTree? + fileprivate(set) public var right: SplayTree? + + public init(value: T) { + self.value = value + } + + public convenience init(array: [T]) { + precondition(array.count > 0) + self.init(value: array.first!) + for v in array.dropFirst() { + insert(value: v) + } + } + + public var isRoot: Bool { + return parent == nil + } + + public var isLeaf: Bool { + return left == nil && right == nil + } + + public var isLeftChild: Bool { + return parent?.left === self + } + + public var isRightChild: Bool { + return parent?.right === self + } + + public var hasLeftChild: Bool { + return left != nil + } + + public var hasRightChild: Bool { + return right != nil + } + + public var hasAnyChild: Bool { + return hasLeftChild || hasRightChild + } + + public var hasBothChildren: Bool { + return hasLeftChild && hasRightChild + } + + /* How many nodes are in this subtree. Performance: O(n). */ + public var count: Int { + return (left?.count ?? 0) + 1 + (right?.count ?? 0) + } +} + +// MARK: - Adding items + +extension SplayTree { + + /* + Inserts a new element into the tree. You should only insert elements + at the root, to make to sure this remains a valid binary tree! + Performance: runs in O(h) time, where h is the height of the tree. + */ + public func insert(value: T) { + if value < self.value { + if let left = left { + left.insert(value: value) + } else { + + left = SplayTree(value: value) + left?.parent = self + + if let left = left { + SplayOperation.splay(node: left) + self.parent = nil + self.value = left.value + self.left = left.left + self.right = left.right + } + } + } else { + + if let right = right { + right.insert(value: value) + } else { + + right = SplayTree(value: value) + right?.parent = self + + if let right = right { + SplayOperation.splay(node: right) + self.parent = nil + self.value = right.value + self.left = right.left + self.right = right.right + } + } + } + } +} + +// MARK: - Deleting items + +extension SplayTree { + /* + Deletes a node from the tree. + Returns the node that has replaced this removed one (or nil if this was a + leaf node). That is primarily useful for when you delete the root node, in + which case the tree gets a new root. + Performance: runs in O(h) time, where h is the height of the tree. + */ + @discardableResult public func remove() -> SplayTree? { + let replacement: SplayTree? + + if let left = left { + if let right = right { + replacement = removeNodeWithTwoChildren(left, right) + } else { + // This node only has a left child. The left child replaces the node. + replacement = left + } + } else if let right = right { + // This node only has a right child. The right child replaces the node. + replacement = right + } else { + // This node has no children. We just disconnect it from its parent. + replacement = nil + } + + // Save the parent to splay before reconnecting + var parentToSplay: SplayTree? + if let replacement = replacement { + parentToSplay = replacement.parent + } else { + parentToSplay = self.parent + } + + reconnectParentTo(node: replacement) + + // performs the splay operation + if let parentToSplay = parentToSplay { + SplayOperation.splay(node: parentToSplay) + } + + // The current node is no longer part of the tree, so clean it up. + parent = nil + left = nil + right = nil + + return replacement + } + + private func removeNodeWithTwoChildren(_ left: SplayTree, _ right: SplayTree) -> SplayTree { + // This node has two children. It must be replaced by the smallest + // child that is larger than this node's value, which is the leftmost + // descendent of the right child. + let successor = right.minimum() + + // If this in-order successor has a right child of its own (it cannot + // have a left child by definition), then that must take its place. + successor.remove() + + // Connect our left child with the new node. + successor.left = left + left.parent = successor + + // Connect our right child with the new node. If the right child does + // not have any left children of its own, then the in-order successor + // *is* the right child. + if right !== successor { + successor.right = right + right.parent = successor + } else { + successor.right = nil + } + + // And finally, connect the successor node to our parent. + return successor + } + + private func reconnectParentTo(node: SplayTree?) { + if let parent = parent { + if isLeftChild { + parent.left = node + } else { + parent.right = node + } + } + node?.parent = parent + } +} + +// MARK: - Searching + +extension SplayTree { + + /* + Finds the "highest" node with the specified value. + Performance: runs in O(h) time, where h is the height of the tree. + */ + public func search(value: T) -> SplayTree? { + var node: SplayTree? = self + while case let n? = node { + if value < n.value { + node = n.left + } else if value > n.value { + node = n.right + } else { + + if let node = node { + SplayOperation.splay(node: node) + } + + return node + } + } + + if let node = node { + SplayOperation.splay(node: node) + } + + return nil + } + + public func contains(value: T) -> Bool { + return search(value: value) != nil + } + + /* + Returns the leftmost descendent. O(h) time. + */ + public func minimum() -> SplayTree { + var node = self + while case let next? = node.left { + node = next + } + + SplayOperation.splay(node: node) + + return node + } + + /* + Returns the rightmost descendent. O(h) time. + */ + public func maximum() -> SplayTree { + var node = self + while case let next? = node.right { + node = next + } + + SplayOperation.splay(node: node) + + return node + } + + /* + Calculates the depth of this node, i.e. the distance to the root. + Takes O(h) time. + */ + public func depth() -> Int { + var node = self + var edges = 0 + while case let parent? = node.parent { + node = parent + edges += 1 + } + return edges + } + + /* + Calculates the height of this node, i.e. the distance to the lowest leaf. + Since this looks at all children of this node, performance is O(n). + */ + public func height() -> Int { + if isLeaf { + return 0 + } else { + return 1 + max(left?.height() ?? 0, right?.height() ?? 0) + } + } + + /* + Finds the node whose value precedes our value in sorted order. + */ + public func predecessor() -> SplayTree? { + if let left = left { + return left.maximum() + } else { + var node = self + while case let parent? = node.parent { + if parent.value < value { return parent } + node = parent + } + return nil + } + } + + /* + Finds the node whose value succeeds our value in sorted order. + */ + public func successor() -> SplayTree? { + if let right = right { + return right.minimum() + } else { + var node = self + while case let parent? = node.parent { + if parent.value > value { return parent } + node = parent + } + return nil + } + } +} + +// MARK: - Traversal +extension SplayTree { + + public func traverseInOrder(process: (T) -> Void) { + left?.traverseInOrder(process: process) + process(value) + right?.traverseInOrder(process: process) + } + + public func traversePreOrder(process: (T) -> Void) { + process(value) + left?.traversePreOrder(process: process) + right?.traversePreOrder(process: process) + } + + public func traversePostOrder(process: (T) -> Void) { + left?.traversePostOrder(process: process) + right?.traversePostOrder(process: process) + process(value) + } + + /* + Performs an in-order traversal and collects the results in an array. + */ + public func map(formula: (T) -> T) -> [T] { + var a = [T]() + if let left = left { a += left.map(formula: formula) } + a.append(formula(value)) + if let right = right { a += right.map(formula: formula) } + return a + } +} + +/* + Is this binary tree a valid binary search tree? + */ +extension SplayTree { + + public func isBST(minValue: T, maxValue: T) -> Bool { + if value < minValue || value > maxValue { return false } + let leftBST = left?.isBST(minValue: minValue, maxValue: value) ?? true + let rightBST = right?.isBST(minValue: value, maxValue: maxValue) ?? true + return leftBST && rightBST + } +} + +// MARK: - Debugging + +extension SplayTree: CustomStringConvertible { + public var description: String { + var s = "" + if let left = left { + s += "(\(left.description)) <- " + } + s += "\(value)" + if let right = right { + s += " -> (\(right.description))" + } + return s + } +} + +extension SplayTree: CustomDebugStringConvertible { + public var debugDescription: String { + var s = "value: \(value)" + if let parent = parent { + s += ", parent: \(parent.value)" + } + if let left = left { + s += ", left = [" + left.debugDescription + "]" + } + if let right = right { + s += ", right = [" + right.debugDescription + "]" + } + return s + } + + public func toArray() -> [T] { + return map { $0 } + } +} diff --git a/Splay Tree/SplayTree.playground/contents.xcplayground b/Splay Tree/SplayTree.playground/contents.xcplayground new file mode 100644 index 000000000..5da2641c9 --- /dev/null +++ b/Splay Tree/SplayTree.playground/contents.xcplayground @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Splay Tree/SplayTree.playground/playground.xcworkspace/contents.xcworkspacedata b/Splay Tree/SplayTree.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Splay Tree/SplayTree.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Splay Tree/SplayTree.swift b/Splay Tree/SplayTree.swift new file mode 100644 index 000000000..727ff8f50 --- /dev/null +++ b/Splay Tree/SplayTree.swift @@ -0,0 +1,552 @@ +/* + * Splay Tree + * + * Based on Binary Search Tree Implementation written by Nicolas Ameghino and Matthijs Hollemans for Swift Algorithms Club + * https://github.com/raywenderlich/swift-algorithm-club/blob/master/Binary%20Search%20Tree + * And extended for the specifics of a Splay Tree by Barbara Martina Rodeker + * + */ + +/** + Represent the 3 possible operations (combinations of rotations) that + could be performed during the Splay phase in Splay Trees + + - zigZag Left child of a right child OR right child of a left child + - zigZig Left child of a left child OR right child of a right child + - zig Only 1 parent and that parent is the root + + */ +public enum SplayOperation { + case zigZag + case zigZig + case zig + + + /** + Splay the given node up to the root of the tree + + - Parameters: + - node SplayTree node to move up to the root + */ + public static func splay(node: SplayTree) { + + while (node.parent != nil) { + operation(forNode: node).apply(onNode: node) + } + } + + /** + Compares the node and its parent and determine + if the rotations should be performed in a zigZag, zigZig or zig case. + + - Parmeters: + - forNode SplayTree node to be checked + - Returns + - Operation Case zigZag - zigZig - zig + */ + private static func operation(forNode node: SplayTree) -> SplayOperation { + + if let parent = node.parent, let _ = parent.parent { + if (node.isLeftChild && parent.isRightChild) || (node.isRightChild && parent.isLeftChild) { + return .zigZag + } + return .zigZig + } + return .zig + } + + /** + Applies the rotation associated to the case + Modifying the splay tree and briging the received node further to the top of the tree + + - Parameters: + - onNode Node to splay up. Should be alwayas the node that needs to be splayed, neither its parent neither it's grandparent + */ + private func apply(onNode node: SplayTree) { + switch self { + case .zigZag: + assert(node.parent != nil && node.parent!.parent != nil, "Should be at least 2 nodes up in the tree") + rotate(child: node, parent: node.parent!) + rotate(child: node, parent: node.parent!) + + case .zigZig: + assert(node.parent != nil && node.parent!.parent != nil, "Should be at least 2 nodes up in the tree") + rotate(child: node.parent!, parent: node.parent!.parent!) + rotate(child: node, parent: node.parent!) + + case .zig: + assert(node.parent != nil && node.parent!.parent == nil, "There should be a parent which is the root") + rotate(child: node, parent: node.parent!) + } + } + + /** + Performs a single rotation from a node to its parent + re-arranging the children properly + */ + private func rotate(child: SplayTree, parent: SplayTree) { + + assert(child.parent != nil && child.parent!.value == parent.value, "Parent and child.parent should match here") + + var grandchildToMode: SplayTree? + if child.isLeftChild { + + grandchildToMode = child.right + child.right = parent + parent.left = grandchildToMode + + } else { + + grandchildToMode = child.left + child.left = parent + parent.right = grandchildToMode + } + + let grandParent = parent.parent + parent.parent = child + child.parent = grandParent + } +} + +public class Node { + + fileprivate(set) public var value: T + fileprivate(set) public var parent: SplayTree? + fileprivate(set) public var left: SplayTree? + fileprivate(set) public var right: SplayTree? + + init(value: T){ + self.value = value + } +} + +public class SplayTree { + + + fileprivate(set) public var root: Node? + public var value: T? { + get { + return root?.value + } + set { + if let value = newValue { + root?.value = value + } + } + } + + fileprivate(set) public var parent: SplayTree? { + get { + return root?.parent + } + set { + root?.parent = newValue + } + } + + fileprivate(set) public var left: SplayTree? { + get { + return root?.left + } + set { + root?.left = newValue + } + } + fileprivate(set) public var right: SplayTree? { + get { + return root?.right + } + set { + root?.right = newValue + } + } + + //MARK: - Initializer + + public init(value: T) { + self.root = Node(value:value) + } + + public var isRoot: Bool { + return parent == nil + } + + public var isLeaf: Bool { + return left == nil && right == nil + } + + public var isLeftChild: Bool { + return parent?.left === self + } + + public var isRightChild: Bool { + return parent?.right === self + } + + public var hasLeftChild: Bool { + return left != nil + } + + public var hasRightChild: Bool { + return right != nil + } + + public var hasAnyChild: Bool { + return hasLeftChild || hasRightChild + } + + public var hasBothChildren: Bool { + return hasLeftChild && hasRightChild + } + + /* How many nodes are in this subtree. Performance: O(n). */ + public var count: Int { + return (left?.count ?? 0) + 1 + (right?.count ?? 0) + } +} + +// MARK: - Adding items + +extension SplayTree { + + /* + Inserts a new element into the tree. You should only insert elements + at the root, to make to sure this remains a valid binary tree! + Performance: runs in O(h) time, where h is the height of the tree. + */ + public func insert(value: T) -> SplayTree? { + if let selfValue = self.value { + if value < selfValue { + if let left = left { + return left.insert(value: value) + } else { + + left = SplayTree(value: value) + left?.parent = self + + if let left = left { + SplayOperation.splay(node: left) + return left + } + } + } else { + + if let right = right { + return right.insert(value: value) + } else { + + right = SplayTree(value: value) + right?.parent = self + + if let right = right { + SplayOperation.splay(node: right) + return right + } + } + } + } else { + self.root = Node(value: value) + return self + } + return nil + } +} + +// MARK: - Deleting items + +extension SplayTree { + /* + Deletes a node from the tree. + Returns the node that has replaced this removed one (or nil if this was a + leaf node). That is primarily useful for when you delete the root node, in + which case the tree gets a new root. + Performance: runs in O(h) time, where h is the height of the tree. + */ + @discardableResult public func remove() -> SplayTree? { + let replacement: SplayTree? + + if let left = left { + if let right = right { + replacement = removeNodeWithTwoChildren(left, right) + } else { + // This node only has a left child. The left child replaces the node. + replacement = left + } + } else if let right = right { + // This node only has a right child. The right child replaces the node. + replacement = right + } else { + // This node has no children. We just disconnect it from its parent. + replacement = nil + } + + // Save the parent to splay before reconnecting + var parentToSplay: SplayTree? + if let replacement = replacement { + parentToSplay = replacement.parent + } else { + parentToSplay = self.parent + } + + reconnectParentTo(node: replacement) + + // performs the splay operation + if let parentToSplay = parentToSplay { + SplayOperation.splay(node: parentToSplay) + } + + // The current node is no longer part of the tree, so clean it up. + parent = nil + left = nil + right = nil + + return replacement + } + + private func removeNodeWithTwoChildren(_ left: SplayTree, _ right: SplayTree) -> SplayTree { + // This node has two children. It must be replaced by the smallest + // child that is larger than this node's value, which is the leftmost + // descendent of the right child. + let successor = right.minimum() + + // If this in-order successor has a right child of its own (it cannot + // have a left child by definition), then that must take its place. + successor.remove() + + // Connect our left child with the new node. + successor.left = left + left.parent = successor + + // Connect our right child with the new node. If the right child does + // not have any left children of its own, then the in-order successor + // *is* the right child. + if right !== successor { + successor.right = right + right.parent = successor + } else { + successor.right = nil + } + + // And finally, connect the successor node to our parent. + return successor + } + + private func reconnectParentTo(node: SplayTree?) { + if let parent = parent { + if isLeftChild { + parent.left = node + } else { + parent.right = node + } + } + node?.parent = parent + } +} + +// MARK: - Searching + +extension SplayTree { + + /* + Finds the "highest" node with the specified value. + Performance: runs in O(h) time, where h is the height of the tree. + */ + public func search(value: T) -> SplayTree? { + var node: SplayTree? = self + while case let n? = node, n.value != nil { + if value < n.value! { + node = n.left + } else if value > n.value! { + node = n.right + } else { + + if let node = node { + SplayOperation.splay(node: node) + } + + return node + } + } + + if let node = node { + SplayOperation.splay(node: node) + } + + return nil + } + + public func contains(value: T) -> Bool { + return search(value: value) != nil + } + + /* + Returns the leftmost descendent. O(h) time. + */ + public func minimum() -> SplayTree { + var node = self + while case let next? = node.left { + node = next + } + + SplayOperation.splay(node: node) + + return node + } + + /* + Returns the rightmost descendent. O(h) time. + */ + public func maximum() -> SplayTree { + var node = self + while case let next? = node.right { + node = next + } + + SplayOperation.splay(node: node) + + return node + } + + /* + Calculates the depth of this node, i.e. the distance to the root. + Takes O(h) time. + */ + public func depth() -> Int { + var node = self + var edges = 0 + while case let parent? = node.parent { + node = parent + edges += 1 + } + return edges + } + + /* + Calculates the height of this node, i.e. the distance to the lowest leaf. + Since this looks at all children of this node, performance is O(n). + */ + public func height() -> Int { + if isLeaf { + return 0 + } else { + return 1 + max(left?.height() ?? 0, right?.height() ?? 0) + } + } + + /* + Finds the node whose value precedes our value in sorted order. + */ + public func predecessor() -> SplayTree? { + if let left = left { + return left.maximum() + } else { + var node = self + while case let parent? = node.parent, parent.value != nil, value != nil { + if parent.value! < value! { return parent } + node = parent + } + return nil + } + } + + /* + Finds the node whose value succeeds our value in sorted order. + */ + public func successor() -> SplayTree? { + if let right = right { + return right.minimum() + } else { + var node = self + while case let parent? = node.parent, parent.value != nil , value != nil { + if parent.value! > value! { return parent } + node = parent + } + return nil + } + } +} + +// MARK: - Traversal +extension SplayTree { + + public func traverseInOrder(process: (T) -> Void) { + left?.traverseInOrder(process: process) + process(value!) + right?.traverseInOrder(process: process) + } + + public func traversePreOrder(process: (T) -> Void) { + process(value!) + left?.traversePreOrder(process: process) + right?.traversePreOrder(process: process) + } + + public func traversePostOrder(process: (T) -> Void) { + left?.traversePostOrder(process: process) + right?.traversePostOrder(process: process) + process(value!) + } + + /* + Performs an in-order traversal and collects the results in an array. + */ + public func map(formula: (T) -> T) -> [T] { + var a = [T]() + if let left = left { a += left.map(formula: formula) } + a.append(formula(value!)) + if let right = right { a += right.map(formula: formula) } + return a + } +} + +/* + Is this binary tree a valid binary search tree? + */ +extension SplayTree { + + public func isBST(minValue: T, maxValue: T) -> Bool { + if let value = value { + if value < minValue || value > maxValue { return false } + let leftBST = left?.isBST(minValue: minValue, maxValue: value) ?? true + let rightBST = right?.isBST(minValue: value, maxValue: maxValue) ?? true + return leftBST && rightBST + } + return false + } +} + +// MARK: - Debugging + +extension SplayTree: CustomStringConvertible { + public var description: String { + var s = "" + if let left = left { + s += "(\(left.description)) <- " + } + s += "\(value)" + if let right = right { + s += " -> (\(right.description))" + } + return s + } +} + +extension SplayTree: CustomDebugStringConvertible { + public var debugDescription: String { + var s = "value: \(value)" + if let parent = parent { + s += ", parent: \(parent.value)" + } + if let left = left { + s += ", left = [" + left.debugDescription + "]" + } + if let right = right { + s += ", right = [" + right.debugDescription + "]" + } + return s + } + + public func toArray() -> [T] { + return map { $0 } + } +} diff --git a/Splay Tree/Tests/Info.plist b/Splay Tree/Tests/Info.plist new file mode 100644 index 000000000..6c6c23c43 --- /dev/null +++ b/Splay Tree/Tests/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + diff --git a/Splay Tree/Tests/SplayTreeTests.swift b/Splay Tree/Tests/SplayTreeTests.swift new file mode 100644 index 000000000..35bdedb71 --- /dev/null +++ b/Splay Tree/Tests/SplayTreeTests.swift @@ -0,0 +1,19 @@ +import XCTest + +class SplayTreeTests: XCTestCase { + var tree: SplayTree! + + override func setUp() { + super.setUp() + tree = SplayTree(value: 1) + } + + func testElements() { + print(tree) + let tree1 = tree.insert(value: 10) + print(tree1!) + let tree2 = tree1!.insert(value: 2) + print(tree2!) + } + +} diff --git a/Splay Tree/Tests/Tests-Bridging-Header.h b/Splay Tree/Tests/Tests-Bridging-Header.h new file mode 100644 index 000000000..1b2cb5d6d --- /dev/null +++ b/Splay Tree/Tests/Tests-Bridging-Header.h @@ -0,0 +1,4 @@ +// +// Use this file to import your target's public headers that you would like to expose to Swift. +// + diff --git a/Splay Tree/Tests/Tests.xcodeproj/project.pbxproj b/Splay Tree/Tests/Tests.xcodeproj/project.pbxproj new file mode 100644 index 000000000..8a900fcd3 --- /dev/null +++ b/Splay Tree/Tests/Tests.xcodeproj/project.pbxproj @@ -0,0 +1,279 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 763F9E771E59DAEF00AC5031 /* SplayTree.swift in Sources */ = {isa = PBXBuildFile; fileRef = 763F9E761E59DAEF00AC5031 /* SplayTree.swift */; }; + 763F9E791E59DAFE00AC5031 /* SplayTreeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 763F9E781E59DAFE00AC5031 /* SplayTreeTests.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 056E92A21E25D04D00B30F52 /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 056E92A61E25D04D00B30F52 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 763F9E761E59DAEF00AC5031 /* SplayTree.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SplayTree.swift; path = ../SplayTree.swift; sourceTree = ""; }; + 763F9E781E59DAFE00AC5031 /* SplayTreeTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SplayTreeTests.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 056E929F1E25D04D00B30F52 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 056E92851E25D03300B30F52 = { + isa = PBXGroup; + children = ( + 056E92A31E25D04D00B30F52 /* Tests */, + 056E928F1E25D03300B30F52 /* Products */, + ); + sourceTree = ""; + }; + 056E928F1E25D03300B30F52 /* Products */ = { + isa = PBXGroup; + children = ( + 056E92A21E25D04D00B30F52 /* Tests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 056E92A31E25D04D00B30F52 /* Tests */ = { + isa = PBXGroup; + children = ( + 056E92A61E25D04D00B30F52 /* Info.plist */, + 763F9E781E59DAFE00AC5031 /* SplayTreeTests.swift */, + 763F9E761E59DAEF00AC5031 /* SplayTree.swift */, + ); + name = Tests; + sourceTree = SOURCE_ROOT; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 056E92A11E25D04D00B30F52 /* Tests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 056E92A71E25D04D00B30F52 /* Build configuration list for PBXNativeTarget "Tests" */; + buildPhases = ( + 056E929E1E25D04D00B30F52 /* Sources */, + 056E929F1E25D04D00B30F52 /* Frameworks */, + 056E92A01E25D04D00B30F52 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Tests; + productName = Tests; + productReference = 056E92A21E25D04D00B30F52 /* Tests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 056E92861E25D03300B30F52 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0820; + LastUpgradeCheck = 0820; + ORGANIZATIONNAME = "Swift Algorithm Club"; + TargetAttributes = { + 056E92A11E25D04D00B30F52 = { + CreatedOnToolsVersion = 8.2; + LastSwiftMigration = 0820; + ProvisioningStyle = Automatic; + }; + }; + }; + buildConfigurationList = 056E92891E25D03300B30F52 /* Build configuration list for PBXProject "Tests" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 056E92851E25D03300B30F52; + productRefGroup = 056E928F1E25D03300B30F52 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 056E92A11E25D04D00B30F52 /* Tests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 056E92A01E25D04D00B30F52 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 056E929E1E25D04D00B30F52 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 763F9E771E59DAEF00AC5031 /* SplayTree.swift in Sources */, + 763F9E791E59DAFE00AC5031 /* SplayTreeTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 056E92991E25D03300B30F52 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.12; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 056E929A1E25D03300B30F52 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.12; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + }; + name = Release; + }; + 056E92A81E25D04D00B30F52 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = Swift.Algorithm.Club.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Tests-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 3.0; + }; + name = Debug; + }; + 056E92A91E25D04D00B30F52 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = Swift.Algorithm.Club.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Tests-Bridging-Header.h"; + SWIFT_VERSION = 3.0; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 056E92891E25D03300B30F52 /* Build configuration list for PBXProject "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 056E92991E25D03300B30F52 /* Debug */, + 056E929A1E25D03300B30F52 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 056E92A71E25D04D00B30F52 /* Build configuration list for PBXNativeTarget "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 056E92A81E25D04D00B30F52 /* Debug */, + 056E92A91E25D04D00B30F52 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 056E92861E25D03300B30F52 /* Project object */; +} diff --git a/Splay Tree/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Splay Tree/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..6c0ea8493 --- /dev/null +++ b/Splay Tree/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Splay Tree/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Splay Tree/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme new file mode 100644 index 000000000..b3f6d696a --- /dev/null +++ b/Splay Tree/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 217cad58d2501c10d040fd72cbcaea96d366fc72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=A9=98=E5=AD=90?= <726451484@qq.com> Date: Mon, 20 Feb 2017 10:25:31 +0800 Subject: [PATCH 0828/1679] Update README.markdown add swift version --- Shell Sort/README.markdown | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/Shell Sort/README.markdown b/Shell Sort/README.markdown index 6cb682035..a2ac843c7 100644 --- a/Shell Sort/README.markdown +++ b/Shell Sort/README.markdown @@ -111,6 +111,28 @@ This is an old Commodore 64 BASIC version of shell sort that Matthijs used a lon 61300 GOTO 61220 61310 RETURN +## The Code: +Here is an implementation of Shell Sort in Swift: +``` +var arr = [64, 20, 50, 33, 72, 10, 23, -1, 4, 5] + +var n = arr.count / 2 + +repeat +{ + for index in 0.. arr[index + n]{ + + swap(&arr[index], &arr[index + n]) + } + } + + n = n / 2 + +}while n > 0 +``` + ## See also [Shellsort on Wikipedia](https://en.wikipedia.org/wiki/Shellsort) From 31b89968878506cadb76ae2a650edbe651d5f58c Mon Sep 17 00:00:00 2001 From: Timur Galimov Date: Tue, 21 Feb 2017 22:04:11 +0300 Subject: [PATCH 0829/1679] fix typo in PointsContainer protocol --- QuadTree/QuadTree.playground/Sources/QuadTree.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/QuadTree/QuadTree.playground/Sources/QuadTree.swift b/QuadTree/QuadTree.playground/Sources/QuadTree.swift index beec4a7b7..65c55d49e 100644 --- a/QuadTree/QuadTree.playground/Sources/QuadTree.swift +++ b/QuadTree/QuadTree.playground/Sources/QuadTree.swift @@ -104,7 +104,7 @@ extension Rect: CustomStringConvertible { } } -protocol PointsContainter { +protocol PointsContainer { func add(point: Point) -> Bool func points(inRect rect: Rect) -> [Point] } @@ -185,7 +185,7 @@ class QuadTreeNode { } } -extension QuadTreeNode: PointsContainter { +extension QuadTreeNode: PointsContainer { @discardableResult func add(point: Point) -> Bool { @@ -265,7 +265,7 @@ extension QuadTreeNode: CustomStringConvertible { } } -public class QuadTree: PointsContainter { +public class QuadTree: PointsContainer { let root: QuadTreeNode From 2e5a5748fdbf92bb1f7c191af7a1c7a0e8b64de6 Mon Sep 17 00:00:00 2001 From: Timur Galimov Date: Tue, 21 Feb 2017 22:28:50 +0300 Subject: [PATCH 0830/1679] Add quadtree diagram --- QuadTree/Images/quadtree.png | Bin 0 -> 110070 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 QuadTree/Images/quadtree.png diff --git a/QuadTree/Images/quadtree.png b/QuadTree/Images/quadtree.png new file mode 100644 index 0000000000000000000000000000000000000000..53af6fb082a3e6172090bd167e4178a4b8e99e36 GIT binary patch literal 110070 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 z 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 T^->+Urc~-GI?7qcEdBl;I+hf* literal 0 HcmV?d00001 From 42032b4bec864013c7e51fff3443ec602b295741 Mon Sep 17 00:00:00 2001 From: Timur Galimov Date: Wed, 22 Feb 2017 01:04:55 +0300 Subject: [PATCH 0831/1679] Update README.md --- QuadTree/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/QuadTree/README.md b/QuadTree/README.md index 77ac8b8fa..3fc682547 100644 --- a/QuadTree/README.md +++ b/QuadTree/README.md @@ -2,6 +2,8 @@ A quadtree is a [tree](https://github.com/raywenderlich/swift-algorithm-club/tree/master/Tree) in which each internal (not leaf) node has four children. + + ### Problem Consider the following problem: your need to store a number of points (each point is a pair of `X` and `Y` coordinates) and then you need to answer which points lie in a certain rectangular region. A naive solution would be to store the points inside an array and then iterate over the points and check each one individually. This solution runs in O(n) though. From 71bfd719ce6024944e7c17847952d77094be6cc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=A9=98=E5=AD=90?= <726451484@qq.com> Date: Sun, 26 Feb 2017 12:41:50 +0800 Subject: [PATCH 0832/1679] add file ShellSortExample.swift update code --- Shell Sort/ShellSortExample.swift | 33 +++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 Shell Sort/ShellSortExample.swift diff --git a/Shell Sort/ShellSortExample.swift b/Shell Sort/ShellSortExample.swift new file mode 100644 index 000000000..eea80e539 --- /dev/null +++ b/Shell Sort/ShellSortExample.swift @@ -0,0 +1,33 @@ +// +// ShellSortExample.swift +// +// +// Created by Cheer on 2017/2/26. +// +// + +import Foundation + +public func shellSort(_ list : inout [Int]) +{ + var sublistCount = list.count / 2 + + while sublistCount > 0 + { + for index in 0.. arr[index + sublistCount]{ + swap(&arr[index], &arr[index + sublistCount]) + } + + guard sublistCount == 1 && index > 0 else { continue } + + if arr[index - 1] > arr[index]{ + swap(&arr[index - 1], &arr[index]) + } + } + sublistCount = sublistCount / 2 + } +} From 8202cf1668a535b61fbac12962ebc5a639631ee1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=A9=98=E5=AD=90?= <726451484@qq.com> Date: Mon, 27 Feb 2017 10:52:37 +0800 Subject: [PATCH 0833/1679] Update ShellSortExample.swift Fix my code mistakes --- Shell Sort/ShellSortExample.swift | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Shell Sort/ShellSortExample.swift b/Shell Sort/ShellSortExample.swift index eea80e539..68cd9ead1 100644 --- a/Shell Sort/ShellSortExample.swift +++ b/Shell Sort/ShellSortExample.swift @@ -14,18 +14,18 @@ public func shellSort(_ list : inout [Int]) while sublistCount > 0 { - for index in 0.. arr[index + sublistCount]{ - swap(&arr[index], &arr[index + sublistCount]) + if list[index] > list[index + sublistCount]{ + swap(&list[index], &list[index + sublistCount]) } guard sublistCount == 1 && index > 0 else { continue } - if arr[index - 1] > arr[index]{ - swap(&arr[index - 1], &arr[index]) + if list[index - 1] > list[index]{ + swap(&list[index - 1], &list[index]) } } sublistCount = sublistCount / 2 From 69cb42eef48c610f2f42e6c5d51781fdb3482e6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=A9=98=E5=AD=90?= <726451484@qq.com> Date: Wed, 1 Mar 2017 12:13:54 +0800 Subject: [PATCH 0834/1679] Update ShellSortExample.swift let code to suit style guide --- Shell Sort/ShellSortExample.swift | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Shell Sort/ShellSortExample.swift b/Shell Sort/ShellSortExample.swift index 68cd9ead1..efa035da3 100644 --- a/Shell Sort/ShellSortExample.swift +++ b/Shell Sort/ShellSortExample.swift @@ -8,23 +8,23 @@ import Foundation -public func shellSort(_ list : inout [Int]) -{ - var sublistCount = list.count / 2 +public func shellSort(_ list: inout [Int]) { - while sublistCount > 0 - { - for index in 0.. 0 { + + for index in 0.. list[index + sublistCount]{ + if list[index] > list[index + sublistCount] { swap(&list[index], &list[index + sublistCount]) } guard sublistCount == 1 && index > 0 else { continue } - if list[index - 1] > list[index]{ + if list[index - 1] > list[index] { swap(&list[index - 1], &list[index]) } } From a69e3d84fcdc3bb8ab1d9e788f8826e5e9ab4254 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=A9=98=E5=AD=90?= <726451484@qq.com> Date: Thu, 2 Mar 2017 10:47:14 +0800 Subject: [PATCH 0835/1679] Update README.markdown update sample code --- Shell Sort/README.markdown | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/Shell Sort/README.markdown b/Shell Sort/README.markdown index a2ac843c7..9c4bdf076 100644 --- a/Shell Sort/README.markdown +++ b/Shell Sort/README.markdown @@ -116,21 +116,31 @@ Here is an implementation of Shell Sort in Swift: ``` var arr = [64, 20, 50, 33, 72, 10, 23, -1, 4, 5] -var n = arr.count / 2 - -repeat -{ - for index in 0.. arr[index + n]{ +public func shellSort(_ list: inout [Int]) { + + var sublistCount = list.count / 2 + + while sublistCount > 0 { - swap(&arr[index], &arr[index + n]) + for index in 0.. list[index + sublistCount] { + swap(&list[index], &list[index + sublistCount]) + } + + guard sublistCount == 1 && index > 0 else { continue } + + if list[index - 1] > list[index] { + swap(&list[index - 1], &list[index]) + } } + sublistCount = sublistCount / 2 } - - n = n / 2 - -}while n > 0 +} + +shellSort(&arr) ``` ## See also From b4e4ef1c8095405c21e69284807095f548fea537 Mon Sep 17 00:00:00 2001 From: John Pham Date: Thu, 2 Mar 2017 17:10:59 +0700 Subject: [PATCH 0836/1679] Update dim func follow syntax change of swift 3 --- Array2D/README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Array2D/README.markdown b/Array2D/README.markdown index 51e77435e..b98a09593 100644 --- a/Array2D/README.markdown +++ b/Array2D/README.markdown @@ -36,7 +36,7 @@ var cookies = [[Int]](repeating: [Int](repeating: 0, count: 7), count: 9) but that's just ugly. To be fair, you can hide the ugliness in a helper function: ```swift -func dim(count: Int, _ value: T) -> [T] { +func dim(_ count: Int, _ value: T) -> [T] { return [T](repeating: value, count: count) } ``` From 0837113e9e8a0fa69d2e8deb8302bb0a72c5d5b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=A9=98=E5=AD=90?= <726451484@qq.com> Date: Thu, 2 Mar 2017 19:19:18 +0800 Subject: [PATCH 0837/1679] Add files via upload upload a radix sort implement,faster than original code --- Radix Sort/RadixSortExample.swift | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 Radix Sort/RadixSortExample.swift diff --git a/Radix Sort/RadixSortExample.swift b/Radix Sort/RadixSortExample.swift new file mode 100644 index 000000000..7d9461c5c --- /dev/null +++ b/Radix Sort/RadixSortExample.swift @@ -0,0 +1,29 @@ +// +// RadixSortExample.swift +// +// +// Created by Cheer on 2017/3/2. +// +// + +import Foundation + +func radixSort1(_ arr: inout [Int]) { + + var temp = [[Int]](repeating: [], count: 10) + + for num in arr { temp[num % 10].append(num) } + + for i in 1...Int(arr.max()!.description.characters.count) { + + for index in 0.. Date: Fri, 3 Mar 2017 11:13:22 +0800 Subject: [PATCH 0838/1679] Update LinearSearch.swift more swift --- Linear Search/LinearSearch.swift | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Linear Search/LinearSearch.swift b/Linear Search/LinearSearch.swift index 882795180..c5374d0a4 100644 --- a/Linear Search/LinearSearch.swift +++ b/Linear Search/LinearSearch.swift @@ -4,3 +4,7 @@ func linearSearch(_ array: [T], _ object: T) -> Int? { } return nil } + +func linearSearch1(_ array: [T], _ object: T) -> Array.Index? { + return array.index { $0 == object } +} From 12b0bdbb8488f7746edac33623b2f86c57564a31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=A9=98=E5=AD=90?= <726451484@qq.com> Date: Fri, 3 Mar 2017 11:34:04 +0800 Subject: [PATCH 0839/1679] Update README.markdown update some details --- Select Minimum Maximum/README.markdown | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Select Minimum Maximum/README.markdown b/Select Minimum Maximum/README.markdown index 09ca97039..fa0f8fed8 100644 --- a/Select Minimum Maximum/README.markdown +++ b/Select Minimum Maximum/README.markdown @@ -68,6 +68,13 @@ array.minElement() // This will return 3 array.maxElement() // This will return 9 ``` +``` +let array = [ 8, 3, 9, 4, 6 ] +//swift3 +array.min() // This will return 3 +array.max() // This will return 9 +``` + ## Maximum and minimum To find both the maximum and minimum values contained in array while minimizing the number of comparisons we can compare the items in pairs. From cc973dcb62d310f1af0d08d408c782a57e3523cb Mon Sep 17 00:00:00 2001 From: barbara Date: Fri, 3 Mar 2017 21:01:11 +0100 Subject: [PATCH 0840/1679] Fixes for connecting nodes during rotations --- Splay Tree/SplayTree.swift | 53 ++++++++++++++++++--------- Splay Tree/Tests/SplayTreeTests.swift | 41 +++++++++++++-------- 2 files changed, 61 insertions(+), 33 deletions(-) diff --git a/Splay Tree/SplayTree.swift b/Splay Tree/SplayTree.swift index 727ff8f50..2e008ba50 100644 --- a/Splay Tree/SplayTree.swift +++ b/Splay Tree/SplayTree.swift @@ -44,7 +44,7 @@ public enum SplayOperation { - Returns - Operation Case zigZag - zigZig - zig */ - private static func operation(forNode node: SplayTree) -> SplayOperation { + public static func operation(forNode node: SplayTree) -> SplayOperation { if let parent = node.parent, let _ = parent.parent { if (node.isLeftChild && parent.isRightChild) || (node.isRightChild && parent.isLeftChild) { @@ -62,7 +62,7 @@ public enum SplayOperation { - Parameters: - onNode Node to splay up. Should be alwayas the node that needs to be splayed, neither its parent neither it's grandparent */ - private func apply(onNode node: SplayTree) { + public func apply(onNode node: SplayTree) { switch self { case .zigZag: assert(node.parent != nil && node.parent!.parent != nil, "Should be at least 2 nodes up in the tree") @@ -84,7 +84,7 @@ public enum SplayOperation { Performs a single rotation from a node to its parent re-arranging the children properly */ - private func rotate(child: SplayTree, parent: SplayTree) { + public func rotate(child: SplayTree, parent: SplayTree) { assert(child.parent != nil && child.parent!.value == parent.value, "Parent and child.parent should match here") @@ -95,16 +95,22 @@ public enum SplayOperation { child.right = parent parent.left = grandchildToMode + + } else { grandchildToMode = child.left child.left = parent parent.right = grandchildToMode - } + } + let grandParent = parent.parent parent.parent = child child.parent = grandParent + + grandParent?.left = child + } } @@ -210,9 +216,15 @@ public class SplayTree { extension SplayTree { /* - Inserts a new element into the tree. You should only insert elements - at the root, to make to sure this remains a valid binary tree! - Performance: runs in O(h) time, where h is the height of the tree. + Inserts a new element into the tree. + Returns the new Tree generated by the insertion. + + - Parameters: + - value T value to be inserted. Will be splayed to the root position + + - Returns + - SplayTree Containing the inserted value in the root node + */ public func insert(value: T) -> SplayTree? { if let selfValue = self.value { @@ -255,14 +267,17 @@ extension SplayTree { // MARK: - Deleting items extension SplayTree { + /* - Deletes a node from the tree. - Returns the node that has replaced this removed one (or nil if this was a - leaf node). That is primarily useful for when you delete the root node, in - which case the tree gets a new root. - Performance: runs in O(h) time, where h is the height of the tree. + Deletes the given node from the tree. + Return the new tree generated by the removal. + The removed node (not necessarily the one containing the value), will be splayed to the root. + + - Returns: + - SplayTree Resulting from the deletion and the splaying of the removed node + */ - @discardableResult public func remove() -> SplayTree? { + public func remove() -> SplayTree? { let replacement: SplayTree? if let left = left { @@ -521,11 +536,13 @@ extension SplayTree: CustomStringConvertible { public var description: String { var s = "" if let left = left { - s += "(\(left.description)) <- " + s += "left: (\(left.description)) <- " + } + if let v = value { + s += "\(v)" } - s += "\(value)" if let right = right { - s += " -> (\(right.description))" + s += " -> (right: \(right.description))" } return s } @@ -534,8 +551,8 @@ extension SplayTree: CustomStringConvertible { extension SplayTree: CustomDebugStringConvertible { public var debugDescription: String { var s = "value: \(value)" - if let parent = parent { - s += ", parent: \(parent.value)" + if let parent = parent, let v = parent.value { + s += ", parent: \(v)" } if let left = left { s += ", left = [" + left.debugDescription + "]" diff --git a/Splay Tree/Tests/SplayTreeTests.swift b/Splay Tree/Tests/SplayTreeTests.swift index 35bdedb71..998c6d3c4 100644 --- a/Splay Tree/Tests/SplayTreeTests.swift +++ b/Splay Tree/Tests/SplayTreeTests.swift @@ -1,19 +1,30 @@ import XCTest class SplayTreeTests: XCTestCase { - var tree: SplayTree! - - override func setUp() { - super.setUp() - tree = SplayTree(value: 1) - } - - func testElements() { - print(tree) - let tree1 = tree.insert(value: 10) - print(tree1!) - let tree2 = tree1!.insert(value: 2) - print(tree2!) - } - + + var tree: SplayTree! + var tree1: SplayTree! + + override func setUp() { + super.setUp() + tree = SplayTree(value: 1) + tree1 = tree.insert(value: 10)?.insert(value: 20)?.insert(value: 3)//?.insert(value: 6)?.insert(value: 100)?.insert(value: 44) + } + + func testInsertion() { + let tree1 = tree.insert(value: 10) + assert(tree1?.root?.value == 10) + + let tree2 = tree1!.insert(value: 2) + assert(tree2?.root?.value == 2) + } + + + func testDeleteExisting() { + print(tree1) + let tree2 = tree1.search(value: 6)?.remove() + + } + + } From 72740a17e7bd9b74716e32f1ef9ef4a92534b302 Mon Sep 17 00:00:00 2001 From: barbara Date: Sat, 4 Mar 2017 09:20:25 +0100 Subject: [PATCH 0841/1679] Test for search function + fixes for rotations --- Splay Tree/SplayTree.swift | 17 +++++++++-------- Splay Tree/Tests/SplayTreeTests.swift | 7 ++++--- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/Splay Tree/SplayTree.swift b/Splay Tree/SplayTree.swift index 2e008ba50..bbe8491e2 100644 --- a/Splay Tree/SplayTree.swift +++ b/Splay Tree/SplayTree.swift @@ -94,7 +94,7 @@ public enum SplayOperation { grandchildToMode = child.right child.right = parent parent.left = grandchildToMode - + grandchildToMode?.parent = parent } else { @@ -102,6 +102,7 @@ public enum SplayOperation { grandchildToMode = child.left child.left = parent parent.right = grandchildToMode + grandchildToMode?.parent = parent } @@ -368,23 +369,23 @@ extension SplayTree { */ public func search(value: T) -> SplayTree? { var node: SplayTree? = self + var nodeParent: SplayTree? = self while case let n? = node, n.value != nil { if value < n.value! { + if n.left != nil { nodeParent = n.left } node = n.left } else if value > n.value! { node = n.right - } else { - - if let node = node { - SplayOperation.splay(node: node) - } - - return node + if n.right != nil { nodeParent = n.right } } } if let node = node { SplayOperation.splay(node: node) + return node + } else if let nodeParent = nodeParent { + SplayOperation.splay(node: nodeParent) + return nodeParent } return nil diff --git a/Splay Tree/Tests/SplayTreeTests.swift b/Splay Tree/Tests/SplayTreeTests.swift index 998c6d3c4..042344193 100644 --- a/Splay Tree/Tests/SplayTreeTests.swift +++ b/Splay Tree/Tests/SplayTreeTests.swift @@ -8,7 +8,7 @@ class SplayTreeTests: XCTestCase { override func setUp() { super.setUp() tree = SplayTree(value: 1) - tree1 = tree.insert(value: 10)?.insert(value: 20)?.insert(value: 3)//?.insert(value: 6)?.insert(value: 100)?.insert(value: 44) + tree1 = tree.insert(value: 10)?.insert(value: 20)?.insert(value: 3)?.insert(value: 6)?.insert(value: 100)?.insert(value: 44) } func testInsertion() { @@ -20,9 +20,10 @@ class SplayTreeTests: XCTestCase { } - func testDeleteExisting() { + func testSearchNonExisting() { print(tree1) - let tree2 = tree1.search(value: 6)?.remove() + let tree2 = tree1.search(value: 5) + assert(tree2?.root?.value == 10) } From 84e75b73e246e76fe8a22c97ef49c9d5277ea35b Mon Sep 17 00:00:00 2001 From: barbara Date: Sun, 5 Mar 2017 19:23:31 +0100 Subject: [PATCH 0842/1679] Completing implementation + debug fixes of Splay Tree --- Splay Tree/SplayTree.swift | 321 +++++++++++++++++++++---------------- 1 file changed, 186 insertions(+), 135 deletions(-) diff --git a/Splay Tree/SplayTree.swift b/Splay Tree/SplayTree.swift index bbe8491e2..f50af7349 100644 --- a/Splay Tree/SplayTree.swift +++ b/Splay Tree/SplayTree.swift @@ -28,7 +28,7 @@ public enum SplayOperation { - Parameters: - node SplayTree node to move up to the root */ - public static func splay(node: SplayTree) { + public static func splay(node: Node) { while (node.parent != nil) { operation(forNode: node).apply(onNode: node) @@ -44,7 +44,7 @@ public enum SplayOperation { - Returns - Operation Case zigZag - zigZig - zig */ - public static func operation(forNode node: SplayTree) -> SplayOperation { + public static func operation(forNode node: Node) -> SplayOperation { if let parent = node.parent, let _ = parent.parent { if (node.isLeftChild && parent.isRightChild) || (node.isRightChild && parent.isLeftChild) { @@ -62,7 +62,7 @@ public enum SplayOperation { - Parameters: - onNode Node to splay up. Should be alwayas the node that needs to be splayed, neither its parent neither it's grandparent */ - public func apply(onNode node: SplayTree) { + public func apply(onNode node: Node) { switch self { case .zigZag: assert(node.parent != nil && node.parent!.parent != nil, "Should be at least 2 nodes up in the tree") @@ -84,95 +84,65 @@ public enum SplayOperation { Performs a single rotation from a node to its parent re-arranging the children properly */ - public func rotate(child: SplayTree, parent: SplayTree) { + public func rotate(child: Node, parent: Node) { assert(child.parent != nil && child.parent!.value == parent.value, "Parent and child.parent should match here") - var grandchildToMode: SplayTree? + var grandchildToMode: Node? + if child.isLeftChild { grandchildToMode = child.right - child.right = parent parent.left = grandchildToMode grandchildToMode?.parent = parent + + let grandParent = parent.parent + child.parent = grandParent + + if parent.isLeftChild { + grandParent?.left = child + } else { + grandParent?.right = child + } + + child.right = parent + parent.parent = child } else { grandchildToMode = child.left - child.left = parent parent.right = grandchildToMode grandchildToMode?.parent = parent + let grandParent = parent.parent + child.parent = grandParent + + if parent.isLeftChild { + grandParent?.left = child + } else { + grandParent?.right = child + } + + child.left = parent + parent.parent = child + } - let grandParent = parent.parent - parent.parent = child - child.parent = grandParent - - grandParent?.left = child } } public class Node { - fileprivate(set) public var value: T - fileprivate(set) public var parent: SplayTree? - fileprivate(set) public var left: SplayTree? - fileprivate(set) public var right: SplayTree? + fileprivate(set) public var value: T? + fileprivate(set) public var parent: Node? + fileprivate(set) public var left: Node? + fileprivate(set) public var right: Node? - init(value: T){ + init(value: T) { self.value = value } -} - -public class SplayTree { - - - fileprivate(set) public var root: Node? - public var value: T? { - get { - return root?.value - } - set { - if let value = newValue { - root?.value = value - } - } - } - - fileprivate(set) public var parent: SplayTree? { - get { - return root?.parent - } - set { - root?.parent = newValue - } - } - - fileprivate(set) public var left: SplayTree? { - get { - return root?.left - } - set { - root?.left = newValue - } - } - fileprivate(set) public var right: SplayTree? { - get { - return root?.right - } - set { - root?.right = newValue - } - } - - //MARK: - Initializer - - public init(value: T) { - self.root = Node(value:value) - } public var isRoot: Bool { return parent == nil @@ -212,29 +182,66 @@ public class SplayTree { } } +public class SplayTree { + + internal var root: Node? + + var value: T? { + return root?.value + } + + //MARK: - Initializer + + public init(value: T) { + self.root = Node(value:value) + } + + public func insert(value: T) { + root = root?.insert(value: value) + } + + public func remove(value: T) { + root = root?.remove(value: value) + } + + public func search(value: T) -> Node? { + root = root?.search(value: value) + return root + } + + public func minimum() -> Node? { + root = root?.minimum(splayed: true) + return root + } + + public func maximum() -> Node? { + root = root?.maximum(splayed: true) + return root + } + +} + // MARK: - Adding items -extension SplayTree { +extension Node { /* - Inserts a new element into the tree. - Returns the new Tree generated by the insertion. + Inserts a new element into the node tree. - Parameters: - value T value to be inserted. Will be splayed to the root position - - Returns - - SplayTree Containing the inserted value in the root node - + - Returns: + - Node inserted */ - public func insert(value: T) -> SplayTree? { + public func insert(value: T) -> Node { if let selfValue = self.value { if value < selfValue { if let left = left { return left.insert(value: value) } else { - left = SplayTree(value: value) + left = Node(value: value) left?.parent = self if let left = left { @@ -248,7 +255,7 @@ extension SplayTree { return right.insert(value: value) } else { - right = SplayTree(value: value) + right = Node(value: value) right?.parent = self if let right = right { @@ -257,78 +264,104 @@ extension SplayTree { } } } - } else { - self.root = Node(value: value) - return self } - return nil + return self } } // MARK: - Deleting items -extension SplayTree { +extension Node { /* - Deletes the given node from the tree. + Deletes the given node from the nodes tree. Return the new tree generated by the removal. The removed node (not necessarily the one containing the value), will be splayed to the root. + - Parameters: + - value To be removed + - Returns: - - SplayTree Resulting from the deletion and the splaying of the removed node + - Node Resulting from the deletion and the splaying of the removed node */ - public func remove() -> SplayTree? { - let replacement: SplayTree? + public func remove(value: T) -> Node? { + let replacement: Node? - if let left = left { - if let right = right { - replacement = removeNodeWithTwoChildren(left, right) + if let v = self.value, v == value { + + var parentToSplay: Node? + if let left = left { + if let right = right { + + replacement = removeNodeWithTwoChildren(left, right) + + if let replacement = replacement, + let replacementParent = replacement.parent, + replacementParent.value != self.value { + + parentToSplay = replacement.parent + + } else { + parentToSplay = self.parent + } + + } else { + // This node only has a left child. The left child replaces the node. + replacement = left + parentToSplay = parent + } + } else if let right = right { + // This node only has a right child. The right child replaces the node. + replacement = right + parentToSplay = parent } else { - // This node only has a left child. The left child replaces the node. - replacement = left + // This node has no children. We just disconnect it from its parent. + replacement = nil + parentToSplay = parent } - } else if let right = right { - // This node only has a right child. The right child replaces the node. - replacement = right - } else { - // This node has no children. We just disconnect it from its parent. - replacement = nil - } + + reconnectParentTo(node: replacement) + + // performs the splay operation + if let parentToSplay = parentToSplay { + SplayOperation.splay(node: parentToSplay) + } + + // The current node is no longer part of the tree, so clean it up. + parent = nil + left = nil + right = nil - // Save the parent to splay before reconnecting - var parentToSplay: SplayTree? - if let replacement = replacement { - parentToSplay = replacement.parent + return parentToSplay + + } else if let v = self.value, value < v { + if left != nil { + return left!.remove(value: value) + } else { + let node = self + SplayOperation.splay(node: node) + return node + + } } else { - parentToSplay = self.parent - } - - reconnectParentTo(node: replacement) - - // performs the splay operation - if let parentToSplay = parentToSplay { - SplayOperation.splay(node: parentToSplay) + if right != nil { + return right?.remove(value: value) + } else { + let node = self + SplayOperation.splay(node: node) + return node + + } } - - // The current node is no longer part of the tree, so clean it up. - parent = nil - left = nil - right = nil - - return replacement } - private func removeNodeWithTwoChildren(_ left: SplayTree, _ right: SplayTree) -> SplayTree { + private func removeNodeWithTwoChildren(_ left: Node, _ right: Node) -> Node { // This node has two children. It must be replaced by the smallest // child that is larger than this node's value, which is the leftmost // descendent of the right child. let successor = right.minimum() - // If this in-order successor has a right child of its own (it cannot - // have a left child by definition), then that must take its place. - successor.remove() - // Connect our left child with the new node. successor.left = left left.parent = successor @@ -347,7 +380,7 @@ extension SplayTree { return successor } - private func reconnectParentTo(node: SplayTree?) { + private func reconnectParentTo(node: Node?) { if let parent = parent { if isLeftChild { parent.left = node @@ -361,15 +394,15 @@ extension SplayTree { // MARK: - Searching -extension SplayTree { +extension Node { /* Finds the "highest" node with the specified value. Performance: runs in O(h) time, where h is the height of the tree. */ - public func search(value: T) -> SplayTree? { - var node: SplayTree? = self - var nodeParent: SplayTree? = self + public func search(value: T) -> Node? { + var node: Node? = self + var nodeParent: Node? = self while case let n? = node, n.value != nil { if value < n.value! { if n.left != nil { nodeParent = n.left } @@ -377,6 +410,8 @@ extension SplayTree { } else if value > n.value! { node = n.right if n.right != nil { nodeParent = n.right } + } else { + break } } @@ -398,27 +433,31 @@ extension SplayTree { /* Returns the leftmost descendent. O(h) time. */ - public func minimum() -> SplayTree { + public func minimum(splayed: Bool = false) -> Node { var node = self while case let next? = node.left { node = next } - SplayOperation.splay(node: node) - + if splayed == true { + SplayOperation.splay(node: node) + } + return node } /* Returns the rightmost descendent. O(h) time. */ - public func maximum() -> SplayTree { + public func maximum(splayed: Bool = false) -> Node { var node = self while case let next? = node.right { node = next } - SplayOperation.splay(node: node) + if splayed == true { + SplayOperation.splay(node: node) + } return node } @@ -452,7 +491,7 @@ extension SplayTree { /* Finds the node whose value precedes our value in sorted order. */ - public func predecessor() -> SplayTree? { + public func predecessor() -> Node? { if let left = left { return left.maximum() } else { @@ -468,7 +507,7 @@ extension SplayTree { /* Finds the node whose value succeeds our value in sorted order. */ - public func successor() -> SplayTree? { + public func successor() -> Node? { if let right = right { return right.minimum() } else { @@ -483,7 +522,7 @@ extension SplayTree { } // MARK: - Traversal -extension SplayTree { +extension Node { public func traverseInOrder(process: (T) -> Void) { left?.traverseInOrder(process: process) @@ -518,7 +557,7 @@ extension SplayTree { /* Is this binary tree a valid binary search tree? */ -extension SplayTree { +extension Node { public func isBST(minValue: T, maxValue: T) -> Bool { if let value = value { @@ -533,7 +572,7 @@ extension SplayTree { // MARK: - Debugging -extension SplayTree: CustomStringConvertible { +extension Node: CustomStringConvertible { public var description: String { var s = "" if let left = left { @@ -549,7 +588,13 @@ extension SplayTree: CustomStringConvertible { } } -extension SplayTree: CustomDebugStringConvertible { +extension SplayTree: CustomStringConvertible { + public var description: String { + return root?.description ?? "Empty tree" + } +} + +extension Node: CustomDebugStringConvertible { public var debugDescription: String { var s = "value: \(value)" if let parent = parent, let v = parent.value { @@ -568,3 +613,9 @@ extension SplayTree: CustomDebugStringConvertible { return map { $0 } } } + +extension SplayTree: CustomDebugStringConvertible { + public var debugDescription: String { + return root?.debugDescription ?? "Empty tree" + } +} From efa2f4856c6e80ccd36e8de11f3fb279974d9e3e Mon Sep 17 00:00:00 2001 From: barbara Date: Sun, 5 Mar 2017 19:23:43 +0100 Subject: [PATCH 0843/1679] Tests for max, min, search, insert and remove --- Splay Tree/Tests/SplayTreeTests.swift | 52 ++++++++++++++++++++------- 1 file changed, 40 insertions(+), 12 deletions(-) diff --git a/Splay Tree/Tests/SplayTreeTests.swift b/Splay Tree/Tests/SplayTreeTests.swift index 042344193..0209f8afe 100644 --- a/Splay Tree/Tests/SplayTreeTests.swift +++ b/Splay Tree/Tests/SplayTreeTests.swift @@ -2,30 +2,58 @@ import XCTest class SplayTreeTests: XCTestCase { - var tree: SplayTree! var tree1: SplayTree! + var tree2: SplayTree! override func setUp() { super.setUp() - tree = SplayTree(value: 1) - tree1 = tree.insert(value: 10)?.insert(value: 20)?.insert(value: 3)?.insert(value: 6)?.insert(value: 100)?.insert(value: 44) + tree1 = SplayTree(value: 1) + + tree2 = SplayTree(value: 1) + tree2.insert(value: 10) + tree2.insert(value: 20) + tree2.insert(value: 3) + tree2.insert(value: 6) + tree2.insert(value: 100) + tree2.insert(value: 44) } func testInsertion() { - let tree1 = tree.insert(value: 10) - assert(tree1?.root?.value == 10) + tree1.insert(value: 10) + assert(tree1.value == 10) - let tree2 = tree1!.insert(value: 2) - assert(tree2?.root?.value == 2) + tree2.insert(value: 2) + assert(tree2.root?.value == 2) } - func testSearchNonExisting() { - print(tree1) - let tree2 = tree1.search(value: 5) - assert(tree2?.root?.value == 10) - + let t = tree2.search(value: 5) + assert(t?.value == 10) + } + + func testSearchExisting() { + let t = tree2.search(value: 6) + assert(t?.value == 6) + } + + func testDeleteExistingOnlyLeftChild() { + tree2.remove(value: 3) + assert(tree2.value == 6) + } + + func testDeleteExistingOnly2Children() { + tree2.remove(value: 6) + assert(tree2.value == 20) } + func testMinimum() { + let v = tree2.minimum() + assert(v?.value == 1) + } + + func testMaximum() { + let v = tree2.maximum() + assert(v?.value == 100) + } } From c27fdde75dc064f55ea7dfdcd5c7d0d4a44aaea6 Mon Sep 17 00:00:00 2001 From: barbara Date: Sun, 5 Mar 2017 19:24:22 +0100 Subject: [PATCH 0844/1679] Replacing SplayTree implementation inside Playground --- .../Sources/SplayTree.swift | 398 +++++++++++------- 1 file changed, 255 insertions(+), 143 deletions(-) diff --git a/Splay Tree/SplayTree.playground/Sources/SplayTree.swift b/Splay Tree/SplayTree.playground/Sources/SplayTree.swift index f0c45e831..f50af7349 100644 --- a/Splay Tree/SplayTree.playground/Sources/SplayTree.swift +++ b/Splay Tree/SplayTree.playground/Sources/SplayTree.swift @@ -28,7 +28,7 @@ public enum SplayOperation { - Parameters: - node SplayTree node to move up to the root */ - public static func splay(node: SplayTree) { + public static func splay(node: Node) { while (node.parent != nil) { operation(forNode: node).apply(onNode: node) @@ -44,10 +44,10 @@ public enum SplayOperation { - Returns - Operation Case zigZag - zigZig - zig */ - private static func operation(forNode node: SplayTree) -> SplayOperation { + public static func operation(forNode node: Node) -> SplayOperation { - if let parent = node.parent, let grandParent = parent.parent { - if (node.isLeftChild && grandParent.isRightChild) || (node.isRightChild && grandParent.isLeftChild) { + if let parent = node.parent, let _ = parent.parent { + if (node.isLeftChild && parent.isRightChild) || (node.isRightChild && parent.isLeftChild) { return .zigZag } return .zigZig @@ -62,7 +62,7 @@ public enum SplayOperation { - Parameters: - onNode Node to splay up. Should be alwayas the node that needs to be splayed, neither its parent neither it's grandparent */ - private func apply(onNode node: SplayTree) { + public func apply(onNode node: Node) { switch self { case .zigZag: assert(node.parent != nil && node.parent!.parent != nil, "Should be at least 2 nodes up in the tree") @@ -84,49 +84,66 @@ public enum SplayOperation { Performs a single rotation from a node to its parent re-arranging the children properly */ - private func rotate(child: SplayTree, parent: SplayTree) { + public func rotate(child: Node, parent: Node) { assert(child.parent != nil && child.parent!.value == parent.value, "Parent and child.parent should match here") - var grandchildToMode: SplayTree? + var grandchildToMode: Node? + if child.isLeftChild { grandchildToMode = child.right - child.right = parent parent.left = grandchildToMode - + grandchildToMode?.parent = parent + + let grandParent = parent.parent + child.parent = grandParent + + if parent.isLeftChild { + grandParent?.left = child + } else { + grandParent?.right = child + } + + child.right = parent + parent.parent = child + + } else { grandchildToMode = child.left - child.left = parent parent.right = grandchildToMode + grandchildToMode?.parent = parent + + let grandParent = parent.parent + child.parent = grandParent + + if parent.isLeftChild { + grandParent?.left = child + } else { + grandParent?.right = child + } + + child.left = parent + parent.parent = child + } + - let grandParent = parent.parent - parent.parent = child - child.parent = grandParent } } -public class SplayTree { +public class Node { - fileprivate(set) public var value: T - fileprivate(set) public var parent: SplayTree? - fileprivate(set) public var left: SplayTree? - fileprivate(set) public var right: SplayTree? + fileprivate(set) public var value: T? + fileprivate(set) public var parent: Node? + fileprivate(set) public var left: Node? + fileprivate(set) public var right: Node? - public init(value: T) { + init(value: T) { self.value = value } - public convenience init(array: [T]) { - precondition(array.count > 0) - self.init(value: array.first!) - for v in array.dropFirst() { - insert(value: v) - } - } - public var isRoot: Bool { return parent == nil } @@ -165,114 +182,186 @@ public class SplayTree { } } +public class SplayTree { + + internal var root: Node? + + var value: T? { + return root?.value + } + + //MARK: - Initializer + + public init(value: T) { + self.root = Node(value:value) + } + + public func insert(value: T) { + root = root?.insert(value: value) + } + + public func remove(value: T) { + root = root?.remove(value: value) + } + + public func search(value: T) -> Node? { + root = root?.search(value: value) + return root + } + + public func minimum() -> Node? { + root = root?.minimum(splayed: true) + return root + } + + public func maximum() -> Node? { + root = root?.maximum(splayed: true) + return root + } + +} + // MARK: - Adding items -extension SplayTree { +extension Node { /* - Inserts a new element into the tree. You should only insert elements - at the root, to make to sure this remains a valid binary tree! - Performance: runs in O(h) time, where h is the height of the tree. + Inserts a new element into the node tree. + + - Parameters: + - value T value to be inserted. Will be splayed to the root position + + - Returns: + - Node inserted */ - public func insert(value: T) { - if value < self.value { - if let left = left { - left.insert(value: value) - } else { - - left = SplayTree(value: value) - left?.parent = self - + public func insert(value: T) -> Node { + if let selfValue = self.value { + if value < selfValue { if let left = left { - SplayOperation.splay(node: left) - self.parent = nil - self.value = left.value - self.left = left.left - self.right = left.right + return left.insert(value: value) + } else { + + left = Node(value: value) + left?.parent = self + + if let left = left { + SplayOperation.splay(node: left) + return left + } } - } - } else { - - if let right = right { - right.insert(value: value) } else { - right = SplayTree(value: value) - right?.parent = self - if let right = right { - SplayOperation.splay(node: right) - self.parent = nil - self.value = right.value - self.left = right.left - self.right = right.right + return right.insert(value: value) + } else { + + right = Node(value: value) + right?.parent = self + + if let right = right { + SplayOperation.splay(node: right) + return right + } } } } + return self } } // MARK: - Deleting items -extension SplayTree { +extension Node { + /* - Deletes a node from the tree. - Returns the node that has replaced this removed one (or nil if this was a - leaf node). That is primarily useful for when you delete the root node, in - which case the tree gets a new root. - Performance: runs in O(h) time, where h is the height of the tree. + Deletes the given node from the nodes tree. + Return the new tree generated by the removal. + The removed node (not necessarily the one containing the value), will be splayed to the root. + + - Parameters: + - value To be removed + + - Returns: + - Node Resulting from the deletion and the splaying of the removed node + */ - @discardableResult public func remove() -> SplayTree? { - let replacement: SplayTree? + public func remove(value: T) -> Node? { + let replacement: Node? - if let left = left { - if let right = right { - replacement = removeNodeWithTwoChildren(left, right) + if let v = self.value, v == value { + + var parentToSplay: Node? + if let left = left { + if let right = right { + + replacement = removeNodeWithTwoChildren(left, right) + + if let replacement = replacement, + let replacementParent = replacement.parent, + replacementParent.value != self.value { + + parentToSplay = replacement.parent + + } else { + parentToSplay = self.parent + } + + } else { + // This node only has a left child. The left child replaces the node. + replacement = left + parentToSplay = parent + } + } else if let right = right { + // This node only has a right child. The right child replaces the node. + replacement = right + parentToSplay = parent } else { - // This node only has a left child. The left child replaces the node. - replacement = left + // This node has no children. We just disconnect it from its parent. + replacement = nil + parentToSplay = parent } - } else if let right = right { - // This node only has a right child. The right child replaces the node. - replacement = right - } else { - // This node has no children. We just disconnect it from its parent. - replacement = nil - } + + reconnectParentTo(node: replacement) + + // performs the splay operation + if let parentToSplay = parentToSplay { + SplayOperation.splay(node: parentToSplay) + } + + // The current node is no longer part of the tree, so clean it up. + parent = nil + left = nil + right = nil - // Save the parent to splay before reconnecting - var parentToSplay: SplayTree? - if let replacement = replacement { - parentToSplay = replacement.parent + return parentToSplay + + } else if let v = self.value, value < v { + if left != nil { + return left!.remove(value: value) + } else { + let node = self + SplayOperation.splay(node: node) + return node + + } } else { - parentToSplay = self.parent - } - - reconnectParentTo(node: replacement) - - // performs the splay operation - if let parentToSplay = parentToSplay { - SplayOperation.splay(node: parentToSplay) + if right != nil { + return right?.remove(value: value) + } else { + let node = self + SplayOperation.splay(node: node) + return node + + } } - - // The current node is no longer part of the tree, so clean it up. - parent = nil - left = nil - right = nil - - return replacement } - private func removeNodeWithTwoChildren(_ left: SplayTree, _ right: SplayTree) -> SplayTree { + private func removeNodeWithTwoChildren(_ left: Node, _ right: Node) -> Node { // This node has two children. It must be replaced by the smallest // child that is larger than this node's value, which is the leftmost // descendent of the right child. let successor = right.minimum() - // If this in-order successor has a right child of its own (it cannot - // have a left child by definition), then that must take its place. - successor.remove() - // Connect our left child with the new node. successor.left = left left.parent = successor @@ -291,7 +380,7 @@ extension SplayTree { return successor } - private func reconnectParentTo(node: SplayTree?) { + private func reconnectParentTo(node: Node?) { if let parent = parent { if isLeftChild { parent.left = node @@ -305,31 +394,33 @@ extension SplayTree { // MARK: - Searching -extension SplayTree { +extension Node { /* Finds the "highest" node with the specified value. Performance: runs in O(h) time, where h is the height of the tree. */ - public func search(value: T) -> SplayTree? { - var node: SplayTree? = self - while case let n? = node { - if value < n.value { + public func search(value: T) -> Node? { + var node: Node? = self + var nodeParent: Node? = self + while case let n? = node, n.value != nil { + if value < n.value! { + if n.left != nil { nodeParent = n.left } node = n.left - } else if value > n.value { + } else if value > n.value! { node = n.right + if n.right != nil { nodeParent = n.right } } else { - - if let node = node { - SplayOperation.splay(node: node) - } - - return node + break } } if let node = node { SplayOperation.splay(node: node) + return node + } else if let nodeParent = nodeParent { + SplayOperation.splay(node: nodeParent) + return nodeParent } return nil @@ -342,27 +433,31 @@ extension SplayTree { /* Returns the leftmost descendent. O(h) time. */ - public func minimum() -> SplayTree { + public func minimum(splayed: Bool = false) -> Node { var node = self while case let next? = node.left { node = next } - SplayOperation.splay(node: node) - + if splayed == true { + SplayOperation.splay(node: node) + } + return node } /* Returns the rightmost descendent. O(h) time. */ - public func maximum() -> SplayTree { + public func maximum(splayed: Bool = false) -> Node { var node = self while case let next? = node.right { node = next } - SplayOperation.splay(node: node) + if splayed == true { + SplayOperation.splay(node: node) + } return node } @@ -396,13 +491,13 @@ extension SplayTree { /* Finds the node whose value precedes our value in sorted order. */ - public func predecessor() -> SplayTree? { + public func predecessor() -> Node? { if let left = left { return left.maximum() } else { var node = self - while case let parent? = node.parent { - if parent.value < value { return parent } + while case let parent? = node.parent, parent.value != nil, value != nil { + if parent.value! < value! { return parent } node = parent } return nil @@ -412,13 +507,13 @@ extension SplayTree { /* Finds the node whose value succeeds our value in sorted order. */ - public func successor() -> SplayTree? { + public func successor() -> Node? { if let right = right { return right.minimum() } else { var node = self - while case let parent? = node.parent { - if parent.value > value { return parent } + while case let parent? = node.parent, parent.value != nil , value != nil { + if parent.value! > value! { return parent } node = parent } return nil @@ -427,16 +522,16 @@ extension SplayTree { } // MARK: - Traversal -extension SplayTree { +extension Node { public func traverseInOrder(process: (T) -> Void) { left?.traverseInOrder(process: process) - process(value) + process(value!) right?.traverseInOrder(process: process) } public func traversePreOrder(process: (T) -> Void) { - process(value) + process(value!) left?.traversePreOrder(process: process) right?.traversePreOrder(process: process) } @@ -444,7 +539,7 @@ extension SplayTree { public func traversePostOrder(process: (T) -> Void) { left?.traversePostOrder(process: process) right?.traversePostOrder(process: process) - process(value) + process(value!) } /* @@ -453,7 +548,7 @@ extension SplayTree { public func map(formula: (T) -> T) -> [T] { var a = [T]() if let left = left { a += left.map(formula: formula) } - a.append(formula(value)) + a.append(formula(value!)) if let right = right { a += right.map(formula: formula) } return a } @@ -462,37 +557,48 @@ extension SplayTree { /* Is this binary tree a valid binary search tree? */ -extension SplayTree { +extension Node { public func isBST(minValue: T, maxValue: T) -> Bool { - if value < minValue || value > maxValue { return false } - let leftBST = left?.isBST(minValue: minValue, maxValue: value) ?? true - let rightBST = right?.isBST(minValue: value, maxValue: maxValue) ?? true - return leftBST && rightBST + if let value = value { + if value < minValue || value > maxValue { return false } + let leftBST = left?.isBST(minValue: minValue, maxValue: value) ?? true + let rightBST = right?.isBST(minValue: value, maxValue: maxValue) ?? true + return leftBST && rightBST + } + return false } } // MARK: - Debugging -extension SplayTree: CustomStringConvertible { +extension Node: CustomStringConvertible { public var description: String { var s = "" if let left = left { - s += "(\(left.description)) <- " + s += "left: (\(left.description)) <- " + } + if let v = value { + s += "\(v)" } - s += "\(value)" if let right = right { - s += " -> (\(right.description))" + s += " -> (right: \(right.description))" } return s } } -extension SplayTree: CustomDebugStringConvertible { +extension SplayTree: CustomStringConvertible { + public var description: String { + return root?.description ?? "Empty tree" + } +} + +extension Node: CustomDebugStringConvertible { public var debugDescription: String { var s = "value: \(value)" - if let parent = parent { - s += ", parent: \(parent.value)" + if let parent = parent, let v = parent.value { + s += ", parent: \(v)" } if let left = left { s += ", left = [" + left.debugDescription + "]" @@ -507,3 +613,9 @@ extension SplayTree: CustomDebugStringConvertible { return map { $0 } } } + +extension SplayTree: CustomDebugStringConvertible { + public var debugDescription: String { + return root?.debugDescription ?? "Empty tree" + } +} From 4aaec9d94b5b6a5c75b07c35fd0e4def6830ac44 Mon Sep 17 00:00:00 2001 From: barbara Date: Sun, 5 Mar 2017 19:38:15 +0100 Subject: [PATCH 0845/1679] Test for root removal and multiple operations executed --- Splay Tree/Tests/SplayTreeTests.swift | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/Splay Tree/Tests/SplayTreeTests.swift b/Splay Tree/Tests/SplayTreeTests.swift index 0209f8afe..01201a108 100644 --- a/Splay Tree/Tests/SplayTreeTests.swift +++ b/Splay Tree/Tests/SplayTreeTests.swift @@ -46,6 +46,11 @@ class SplayTreeTests: XCTestCase { assert(tree2.value == 20) } + func testDeleteRoot() { + tree2.remove(value: 44) + assert(tree2.value == 100) + } + func testMinimum() { let v = tree2.minimum() assert(v?.value == 1) @@ -56,4 +61,16 @@ class SplayTreeTests: XCTestCase { assert(v?.value == 100) } + func testInsertionRemovals() { + let splayTree = SplayTree(value: 1) + splayTree.insert(value: 2) + splayTree.insert(value: 10) + splayTree.insert(value: 6) + + splayTree.remove(value: 10) + splayTree.remove(value: 6) + + assert(splayTree.value == 2) + } + } From 9da711ddf62bdc9b77d73ad64da8285a94f2b4cc Mon Sep 17 00:00:00 2001 From: barbara Date: Sun, 5 Mar 2017 19:38:47 +0100 Subject: [PATCH 0846/1679] Fixes for root removal & insertions with nil root --- .../Sources/SplayTree.swift | 106 ++++++++++-------- Splay Tree/SplayTree.swift | 22 +++- 2 files changed, 78 insertions(+), 50 deletions(-) diff --git a/Splay Tree/SplayTree.playground/Sources/SplayTree.swift b/Splay Tree/SplayTree.playground/Sources/SplayTree.swift index f50af7349..a4feda7ef 100644 --- a/Splay Tree/SplayTree.playground/Sources/SplayTree.swift +++ b/Splay Tree/SplayTree.playground/Sources/SplayTree.swift @@ -1,5 +1,5 @@ /* - * Splay Tree + * Splay Tree * * Based on Binary Search Tree Implementation written by Nicolas Ameghino and Matthijs Hollemans for Swift Algorithms Club * https://github.com/raywenderlich/swift-algorithm-club/blob/master/Binary%20Search%20Tree @@ -8,12 +8,12 @@ */ /** - Represent the 3 possible operations (combinations of rotations) that - could be performed during the Splay phase in Splay Trees + Represent the 3 possible operations (combinations of rotations) that + could be performed during the Splay phase in Splay Trees - - zigZag Left child of a right child OR right child of a left child - - zigZig Left child of a left child OR right child of a right child - - zig Only 1 parent and that parent is the root + - zigZag Left child of a right child OR right child of a left child + - zigZig Left child of a left child OR right child of a right child + - zig Only 1 parent and that parent is the root */ public enum SplayOperation { @@ -23,10 +23,10 @@ public enum SplayOperation { /** - Splay the given node up to the root of the tree + Splay the given node up to the root of the tree - - Parameters: - - node SplayTree node to move up to the root + - Parameters: + - node SplayTree node to move up to the root */ public static func splay(node: Node) { @@ -36,13 +36,13 @@ public enum SplayOperation { } /** - Compares the node and its parent and determine - if the rotations should be performed in a zigZag, zigZig or zig case. + Compares the node and its parent and determine + if the rotations should be performed in a zigZag, zigZig or zig case. - - Parmeters: - - forNode SplayTree node to be checked - - Returns - - Operation Case zigZag - zigZig - zig + - Parmeters: + - forNode SplayTree node to be checked + - Returns + - Operation Case zigZag - zigZig - zig */ public static func operation(forNode node: Node) -> SplayOperation { @@ -56,11 +56,11 @@ public enum SplayOperation { } /** - Applies the rotation associated to the case - Modifying the splay tree and briging the received node further to the top of the tree + Applies the rotation associated to the case + Modifying the splay tree and briging the received node further to the top of the tree - - Parameters: - - onNode Node to splay up. Should be alwayas the node that needs to be splayed, neither its parent neither it's grandparent + - Parameters: + - onNode Node to splay up. Should be alwayas the node that needs to be splayed, neither its parent neither it's grandparent */ public func apply(onNode node: Node) { switch self { @@ -68,12 +68,12 @@ public enum SplayOperation { assert(node.parent != nil && node.parent!.parent != nil, "Should be at least 2 nodes up in the tree") rotate(child: node, parent: node.parent!) rotate(child: node, parent: node.parent!) - + case .zigZig: assert(node.parent != nil && node.parent!.parent != nil, "Should be at least 2 nodes up in the tree") rotate(child: node.parent!, parent: node.parent!.parent!) rotate(child: node, parent: node.parent!) - + case .zig: assert(node.parent != nil && node.parent!.parent == nil, "There should be a parent which is the root") rotate(child: node, parent: node.parent!) @@ -81,8 +81,8 @@ public enum SplayOperation { } /** - Performs a single rotation from a node to its parent - re-arranging the children properly + Performs a single rotation from a node to its parent + re-arranging the children properly */ public func rotate(child: Node, parent: Node) { @@ -95,41 +95,41 @@ public enum SplayOperation { grandchildToMode = child.right parent.left = grandchildToMode grandchildToMode?.parent = parent - + let grandParent = parent.parent child.parent = grandParent - + if parent.isLeftChild { grandParent?.left = child } else { grandParent?.right = child } - + child.right = parent parent.parent = child - - + + } else { grandchildToMode = child.left parent.right = grandchildToMode grandchildToMode?.parent = parent - + let grandParent = parent.parent child.parent = grandParent - + if parent.isLeftChild { grandParent?.left = child } else { grandParent?.right = child } - + child.left = parent parent.parent = child - + } - + } } @@ -183,13 +183,13 @@ public class Node { } public class SplayTree { - + internal var root: Node? var value: T? { return root?.value } - + //MARK: - Initializer public init(value: T) { @@ -197,13 +197,17 @@ public class SplayTree { } public func insert(value: T) { - root = root?.insert(value: value) + if let root = root { + self.root = root.insert(value: value) + } else { + root = Node(value: value) + } } public func remove(value: T) { root = root?.remove(value: value) } - + public func search(value: T) -> Node? { root = root?.search(value: value) return root @@ -229,10 +233,10 @@ extension Node { Inserts a new element into the node tree. - Parameters: - - value T value to be inserted. Will be splayed to the root position + - value T value to be inserted. Will be splayed to the root position - Returns: - - Node inserted + - Node inserted */ public func insert(value: T) -> Node { if let selfValue = self.value { @@ -275,14 +279,14 @@ extension Node { /* Deletes the given node from the nodes tree. - Return the new tree generated by the removal. + Return the new tree generated by the removal. The removed node (not necessarily the one containing the value), will be splayed to the root. - Parameters: - - value To be removed + - value To be removed - Returns: - - Node Resulting from the deletion and the splaying of the removed node + - Node Resulting from the deletion and the splaying of the removed node */ public func remove(value: T) -> Node? { @@ -302,19 +306,29 @@ extension Node { parentToSplay = replacement.parent - } else { + } else if self.parent != nil { parentToSplay = self.parent + } else { + parentToSplay = replacement } } else { // This node only has a left child. The left child replaces the node. replacement = left - parentToSplay = parent + if self.parent != nil { + parentToSplay = self.parent + } else { + parentToSplay = replacement + } } } else if let right = right { // This node only has a right child. The right child replaces the node. replacement = right - parentToSplay = parent + if self.parent != nil { + parentToSplay = self.parent + } else { + parentToSplay = replacement + } } else { // This node has no children. We just disconnect it from its parent. replacement = nil @@ -332,7 +346,7 @@ extension Node { parent = nil left = nil right = nil - + return parentToSplay } else if let v = self.value, value < v { diff --git a/Splay Tree/SplayTree.swift b/Splay Tree/SplayTree.swift index f50af7349..a7b20743d 100644 --- a/Splay Tree/SplayTree.swift +++ b/Splay Tree/SplayTree.swift @@ -197,7 +197,11 @@ public class SplayTree { } public func insert(value: T) { - root = root?.insert(value: value) + if let root = root { + self.root = root.insert(value: value) + } else { + root = Node(value: value) + } } public func remove(value: T) { @@ -302,19 +306,29 @@ extension Node { parentToSplay = replacement.parent - } else { + } else if self.parent != nil { parentToSplay = self.parent + } else { + parentToSplay = replacement } } else { // This node only has a left child. The left child replaces the node. replacement = left - parentToSplay = parent + if self.parent != nil { + parentToSplay = self.parent + } else { + parentToSplay = replacement + } } } else if let right = right { // This node only has a right child. The right child replaces the node. replacement = right - parentToSplay = parent + if self.parent != nil { + parentToSplay = self.parent + } else { + parentToSplay = replacement + } } else { // This node has no children. We just disconnect it from its parent. replacement = nil From ecba738935641768526277d908153adc3f9d8ca6 Mon Sep 17 00:00:00 2001 From: barbara Date: Sun, 5 Mar 2017 19:38:55 +0100 Subject: [PATCH 0847/1679] Playground Splay Tree --- .../SplayTree.playground/Contents.swift | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/Splay Tree/SplayTree.playground/Contents.swift b/Splay Tree/SplayTree.playground/Contents.swift index 951ad4c5c..4406a759d 100644 --- a/Splay Tree/SplayTree.playground/Contents.swift +++ b/Splay Tree/SplayTree.playground/Contents.swift @@ -1,7 +1,29 @@ //: Playground - Splay Tree Implementation -let splayTree = SplayTree(array: [1]) +let splayTree = SplayTree(value: 1) splayTree.insert(value: 2) splayTree.insert(value: 10) splayTree.insert(value: 6) + +splayTree.remove(value: 10) +splayTree.remove(value: 6) + +splayTree.insert(value: 55) +splayTree.insert(value: 559) +splayTree.remove(value: 2) +splayTree.remove(value: 1) +splayTree.remove(value: 55) +splayTree.remove(value: 559) + +splayTree.insert(value: 1843000) +splayTree.insert(value: 1238) +splayTree.insert(value: -1) +splayTree.insert(value: 87) + +splayTree.minimum() +splayTree.maximum() + + + + From cae6d08a8c1ea02fdf37c6481e965b74457b0eaa Mon Sep 17 00:00:00 2001 From: vincentngo Date: Mon, 6 Mar 2017 15:15:06 -0500 Subject: [PATCH 0848/1679] Update link for radix sort --- README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.markdown b/README.markdown index e2d99e2bc..dfe451478 100644 --- a/README.markdown +++ b/README.markdown @@ -80,7 +80,7 @@ Fast sorts: Special-purpose sorts: - [Counting Sort](Counting Sort/) -- Radix Sort +- [Radix Sort](Radix Sort/) - [Topological Sort](Topological Sort/) Bad sorting algorithms (don't use these!): From ce1ec8842561fb69c02f835278539f4bab287a8e Mon Sep 17 00:00:00 2001 From: "JUNYEONG.YOO" Date: Tue, 7 Mar 2017 19:31:50 +0900 Subject: [PATCH 0849/1679] Modified typo in README.md of QuickSort --- Quicksort/README.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Quicksort/README.markdown b/Quicksort/README.markdown index e3d284333..d359ecb5c 100644 --- a/Quicksort/README.markdown +++ b/Quicksort/README.markdown @@ -30,7 +30,7 @@ Here's how it works. When given an array, `quicksort()` splits it up into three All the elements less than the pivot go into a new array called `less`. All the elements equal to the pivot go into the `equal` array. And you guessed it, all elements greater than the pivot go into the third array, `greater`. This is why the generic type `T` must be `Comparable`, so we can compare the elements with `<`, `==`, and `>`. -Once we have these three arrays, `quicksort()` recursively sorts the `less` array and the `right` array, then glues those sorted subarrays back together with the `equal` array to get the final result. +Once we have these three arrays, `quicksort()` recursively sorts the `less` array and the `greater` array, then glues those sorted subarrays back together with the `equal` array to get the final result. ## An example @@ -44,7 +44,7 @@ First, we pick the pivot element. That is `8` because it's in the middle of the equal: [ 8, 8 ] greater: [ 10, 9, 14, 27, 26 ] -This is a good split because `less` and `equal` roughly contain the same number of elements. So we've picked a good pivot that chopped the array right down the middle. +This is a good split because `less` and `greater` roughly contain the same number of elements. So we've picked a good pivot that chopped the array right down the middle. Note that the `less` and `greater` arrays aren't sorted yet, so we call `quicksort()` again to sort those two subarrays. That does the exact same thing: pick a pivot and split the subarray into three even smaller parts. From 7a5700dbae300b075195842482cb74981ae5fc9e Mon Sep 17 00:00:00 2001 From: Daniel Santos Date: Wed, 8 Mar 2017 19:44:06 -0500 Subject: [PATCH 0850/1679] added ExpressibleByArrayLiteral to the Linked List and wrote test for the new initializer. --- .../LinkedList.playground/Contents.swift | 22 +++++++++++++++++-- Linked List/LinkedList.swift | 10 ++++++++- Linked List/Tests/LinkedListTests.swift | 22 +++++++++++++++++++ 3 files changed, 51 insertions(+), 3 deletions(-) diff --git a/Linked List/LinkedList.playground/Contents.swift b/Linked List/LinkedList.playground/Contents.swift index a90b7180c..1f7aa7dae 100644 --- a/Linked List/LinkedList.playground/Contents.swift +++ b/Linked List/LinkedList.playground/Contents.swift @@ -10,7 +10,7 @@ public class LinkedListNode { } } -public class LinkedList { +public final class LinkedList { public typealias Node = LinkedListNode fileprivate var head: Node? @@ -187,7 +187,7 @@ extension LinkedList { } } -extension LinkedList { +extension LinkedList: ExpressibleByArrayLiteral { convenience init(array: Array) { self.init() @@ -195,6 +195,14 @@ extension LinkedList { self.append(element) } } + + public convenience init(arrayLiteral elements: T...) { + self.init() + + for element in elements { + self.append(element) + } + } } let list = LinkedList() @@ -255,3 +263,13 @@ list[0] // "Swift" list.remove(atIndex: 0) // "Swift" list.count // 0 + +let linkedList: LinkedList = [1, 2, 3, 4] // [1, 2, 3, 4] +linkedList.count // 4 +linkedList[0] // 1 + +// Infer the type from the array +let listArrayLiteral2: LinkedList = ["Swift", "Algorithm", "Club"] +listArrayLiteral2.count // 3 +listArrayLiteral2[0] // "Swift" +listArrayLiteral2.removeLast() // "Club" diff --git a/Linked List/LinkedList.swift b/Linked List/LinkedList.swift index 83f898f6c..792215a72 100755 --- a/Linked List/LinkedList.swift +++ b/Linked List/LinkedList.swift @@ -8,7 +8,7 @@ public class LinkedListNode { } } -public class LinkedList { +public final class LinkedList: ExpressibleByArrayLiteral { public typealias Node = LinkedListNode fileprivate var head: Node? @@ -203,4 +203,12 @@ extension LinkedList { self.append(element) } } + + public convenience init(arrayLiteral elements: T...) { + self.init() + + for element in elements { + self.append(element) + } + } } diff --git a/Linked List/Tests/LinkedListTests.swift b/Linked List/Tests/LinkedListTests.swift index 367ec8c6b..6f58d9775 100755 --- a/Linked List/Tests/LinkedListTests.swift +++ b/Linked List/Tests/LinkedListTests.swift @@ -248,4 +248,26 @@ class LinkedListTest: XCTestCase { XCTAssertTrue(last === list.first) XCTAssertEqual(nodeCount, list.count) } + + func testArrayLiteralInitTypeInfer() { + let arrayLiteralInitInfer: LinkedList = [1.0, 2.0, 3.0] + + XCTAssertEqual(arrayLiteralInitInfer.count, 3) + XCTAssertEqual(arrayLiteralInitInfer.first?.value, 1.0) + XCTAssertEqual(arrayLiteralInitInfer.last?.value, 3.0) + XCTAssertEqual(arrayLiteralInitInfer[1], 2.0) + XCTAssertEqual(arrayLiteralInitInfer.removeLast(), 3.0) + XCTAssertEqual(arrayLiteralInitInfer.count, 2) + } + + func testArrayLiteralInitExplicit() { + let arrayLiteralInitExplicit: LinkedList = [1, 2, 3] + + XCTAssertEqual(arrayLiteralInitExplicit.count, 3) + XCTAssertEqual(arrayLiteralInitExplicit.first?.value, 1) + XCTAssertEqual(arrayLiteralInitExplicit.last?.value, 3) + XCTAssertEqual(arrayLiteralInitExplicit[1], 2) + XCTAssertEqual(arrayLiteralInitExplicit.removeLast(), 3) + XCTAssertEqual(arrayLiteralInitExplicit.count, 2) + } } From 6863590f96aa24a004af813f6c82272267c5b742 Mon Sep 17 00:00:00 2001 From: Daniel Santos Date: Wed, 8 Mar 2017 19:53:20 -0500 Subject: [PATCH 0851/1679] implemented the ExpressibleByArrayLiteral for the Linked List in a new extension instead of the class declaration for readability --- .../LinkedList.playground/Contents.swift | 80 +++++++++++-------- Linked List/LinkedList.swift | 16 ++-- 2 files changed, 55 insertions(+), 41 deletions(-) diff --git a/Linked List/LinkedList.playground/Contents.swift b/Linked List/LinkedList.playground/Contents.swift index 1f7aa7dae..ed46331d8 100644 --- a/Linked List/LinkedList.playground/Contents.swift +++ b/Linked List/LinkedList.playground/Contents.swift @@ -4,7 +4,7 @@ public class LinkedListNode { var value: T var next: LinkedListNode? weak var previous: LinkedListNode? - + public init(value: T) { self.value = value } @@ -12,17 +12,19 @@ public class LinkedListNode { public final class LinkedList { public typealias Node = LinkedListNode - + fileprivate var head: Node? - + + public init() {} + public var isEmpty: Bool { return head == nil } - + public var first: Node? { return head } - + public var last: Node? { if var node = head { while case let next? = node.next { @@ -33,7 +35,7 @@ public final class LinkedList { return nil } } - + public var count: Int { if var node = head { var c = 1 @@ -46,7 +48,7 @@ public final class LinkedList { return 0 } } - + public func node(atIndex index: Int) -> Node? { if index >= 0 { var node = head @@ -59,15 +61,19 @@ public final class LinkedList { } return nil } - + public subscript(index: Int) -> T { let node = self.node(atIndex: index) assert(node != nil) return node!.value } - + public func append(_ value: T) { let newNode = Node(value: value) + self.append(newNode) + } + + public func append(_ newNode: Node) { if let lastNode = last { newNode.previous = lastNode lastNode.next = newNode @@ -75,64 +81,68 @@ public final class LinkedList { head = newNode } } - + private func nodesBeforeAndAfter(index: Int) -> (Node?, Node?) { assert(index >= 0) - + var i = index var next = head var prev: Node? - + while next != nil && i > 0 { i -= 1 prev = next next = next!.next } assert(i == 0) // if > 0, then specified index was too large - + return (prev, next) } - + public func insert(_ value: T, atIndex index: Int) { - let (prev, next) = nodesBeforeAndAfter(index: index) - let newNode = Node(value: value) + self.insert(newNode, atIndex: index) + } + + public func insert(_ newNode: Node, atIndex index: Int) { + let (prev, next) = nodesBeforeAndAfter(index: index) + newNode.previous = prev newNode.next = next prev?.next = newNode next?.previous = newNode - + if prev == nil { head = newNode } } - + public func removeAll() { head = nil } - - public func remove(node: Node) -> T { + + @discardableResult public func remove(node: Node) -> T { let prev = node.previous let next = node.next - + if let prev = prev { prev.next = next } else { head = next } next?.previous = prev - + node.previous = nil node.next = nil return node.value } - - public func removeLast() -> T { + + @discardableResult public func removeLast() -> T { assert(!isEmpty) return remove(node: last!) } - - public func remove(atIndex index: Int) -> T { + + @discardableResult public func remove(atIndex index: Int) -> T { let node = self.node(atIndex: index) assert(node != nil) return remove(node: node!) @@ -173,7 +183,7 @@ extension LinkedList { } return result } - + public func filter(predicate: (T) -> Bool) -> LinkedList { let result = LinkedList() var node = head @@ -187,21 +197,23 @@ extension LinkedList { } } -extension LinkedList: ExpressibleByArrayLiteral { +extension LinkedList { convenience init(array: Array) { self.init() - + for element in array { self.append(element) } } - +} + +extension LinkedList: ExpressibleByArrayLiteral { public convenience init(arrayLiteral elements: T...) { - self.init() + self.init() - for element in elements { - self.append(element) - } + for element in elements { + self.append(element) + } } } diff --git a/Linked List/LinkedList.swift b/Linked List/LinkedList.swift index 792215a72..53dc77a06 100755 --- a/Linked List/LinkedList.swift +++ b/Linked List/LinkedList.swift @@ -8,7 +8,7 @@ public class LinkedListNode { } } -public final class LinkedList: ExpressibleByArrayLiteral { +public final class LinkedList { public typealias Node = LinkedListNode fileprivate var head: Node? @@ -203,12 +203,14 @@ extension LinkedList { self.append(element) } } - - public convenience init(arrayLiteral elements: T...) { - self.init() +} + +extension LinkedList: ExpressibleByArrayLiteral { + public convenience init(arrayLiteral elements: T...) { + self.init() - for element in elements { - self.append(element) - } + for element in elements { + self.append(element) } + } } From 345f8441b64003258779cd3fed692c5549a4cbd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=A9=98=E5=AD=90?= <726451484@qq.com> Date: Thu, 9 Mar 2017 18:35:26 +0800 Subject: [PATCH 0852/1679] add SelectionSamplingExample.swift --- .../SelectionSamplingExample.swift | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 Selection Sampling/SelectionSamplingExample.swift diff --git a/Selection Sampling/SelectionSamplingExample.swift b/Selection Sampling/SelectionSamplingExample.swift new file mode 100644 index 000000000..66648a934 --- /dev/null +++ b/Selection Sampling/SelectionSamplingExample.swift @@ -0,0 +1,32 @@ +// +// Select.swift +// +// +// Created by Cheer on 2017/3/9. +// +// + +import Foundation + +func select(from a: [T], count requested: Int) -> [T] { + + // if requested > a.count, will throw ==> fatal error: Index out of range + + if requested < a.count { + var arr = a + for i in 0.. the range is [0...n-1] + //So: arc4random_uniform(UInt32(arr.count - i - 2)) + (i + 1) ==> [0...arr.count - (i + 1) - 1] + (i + 1) ==> the range is [(i + 1)...arr.count - 1] + //Why start index is "(i + 1)"? Because in "swap(&A,&B)", if A's index == B's index, will throw a error: "swapping a location with itself is not supported" + + let nextIndex = Int(arc4random_uniform(UInt32(arr.count - i - 2))) + (i + 1) + swap(&arr[nextIndex], &arr[i]) + } + return Array(arr[0.. Date: Mon, 13 Mar 2017 17:00:42 +0600 Subject: [PATCH 0853/1679] Egg Drop Dynamic Problem Added --- Egg Drop Problem/EggDrop.swift | 31 +++++++++++++++++++ .../contents.xcworkspacedata | 7 +++++ 2 files changed, 38 insertions(+) create mode 100644 Egg Drop Problem/EggDrop.swift diff --git a/Egg Drop Problem/EggDrop.swift b/Egg Drop Problem/EggDrop.swift new file mode 100644 index 000000000..6d0aab2a1 --- /dev/null +++ b/Egg Drop Problem/EggDrop.swift @@ -0,0 +1,31 @@ +func eggDrop(_ numberOfEggs: Int, numberOfFloors: Int) -> Int { + var eggFloor: [[Int]] = [] //egg(rows) floor(cols) array to store the solutions + var attempts: Int = 0 + + for var i in (0.. k-1 + //case 2: egg doesn't break. meaning we'll still have 'i' number of eggs, and we'll go upstairs -> j-k + attempts = 1 + max(eggFloor[i-1][k-1], eggFloor[i][j-k])//we add one taking into account the attempt we're taking at the moment + + if attempts < eggFloor[i][j]{ //finding the min + eggFloor[i][j] = attempts; + } + } + } + } + + return eggFloor[numberOfEggs][numberOfFloors] +} + +func max(_ x1: Int, _ x2: Int){ + return x1 > x2 ? x1 : x2 +} diff --git a/swift-algorithm-club.xcworkspace/contents.xcworkspacedata b/swift-algorithm-club.xcworkspace/contents.xcworkspacedata index b2ffce836..5ac8577f5 100644 --- a/swift-algorithm-club.xcworkspace/contents.xcworkspacedata +++ b/swift-algorithm-club.xcworkspace/contents.xcworkspacedata @@ -1,6 +1,13 @@ + + + + From 5205fc8cf7ac1091448aecd9e7680b25779c9a88 Mon Sep 17 00:00:00 2001 From: Deep Parekh Date: Thu, 23 Feb 2017 00:08:21 -0500 Subject: [PATCH 0854/1679] Added checks for subscript and fixed initializer compile error --- Array2D/Array2D.playground/Contents.swift | 69 +++++++++++++---------- 1 file changed, 40 insertions(+), 29 deletions(-) diff --git a/Array2D/Array2D.playground/Contents.swift b/Array2D/Array2D.playground/Contents.swift index 7064de59c..38d4eff23 100644 --- a/Array2D/Array2D.playground/Contents.swift +++ b/Array2D/Array2D.playground/Contents.swift @@ -1,31 +1,42 @@ /* - Two-dimensional array with a fixed number of rows and columns. - This is mostly handy for games that are played on a grid, such as chess. - Performance is always O(1). -*/ + Two-dimensional array with a fixed number of rows and columns. + This is mostly handy for games that are played on a grid, such as chess. + Performance is always O(1). + */ public struct Array2D { - public let columns: Int - public let rows: Int - fileprivate var array: [T] - - public init(columns: Int, rows: Int, initialValue: T) { - self.columns = columns - self.rows = rows - array = .init(repeatElement(initialValue, count: rows*columns)) - } - - public subscript(column: Int, row: Int) -> T { - get { - return array[row*columns + column] + public let columns: Int + public let rows: Int + public var array: [T] + + public init(columns: Int, rows: Int, initialValue: T) { + self.columns = columns + self.rows = rows + array = [T](repeating: initialValue, count: rows*columns) } - set { - array[row*columns + column] = newValue + + public subscript(column: Int, row: Int) -> T { + get { + if isValidSubscript(column: column, row: row) { + return array[row*columns + column] + } else { + fatalError("Not a valid subscript") + } + } + set { + if isValidSubscript(column: column, row: row) { + array[row*columns + column] = newValue + } else { + fatalError("Not a valid subscript") + } + } + } + + private func isValidSubscript(column: Int, row: Int) -> Bool { + return column < columns && row < rows } - } } - // initialization var matrix = Array2D(columns: 3, rows: 5, initialValue: 0) @@ -51,13 +62,13 @@ print(matrix.array) // print out the 2D array with a reference around the grid for i in 0.. Date: Wed, 15 Mar 2017 19:48:51 -0700 Subject: [PATCH 0855/1679] availability check, native array loop for signal --- DiningPhilosophers/Sources/main.swift | 46 +++++++++++++-------------- 1 file changed, 22 insertions(+), 24 deletions(-) diff --git a/DiningPhilosophers/Sources/main.swift b/DiningPhilosophers/Sources/main.swift index deff344b9..285402d53 100755 --- a/DiningPhilosophers/Sources/main.swift +++ b/DiningPhilosophers/Sources/main.swift @@ -7,17 +7,16 @@ // -import Foundation import Dispatch let numberOfPhilosophers = 4 struct ForkPair { - static let forksSemaphore:[DispatchSemaphore] = Array(repeating: DispatchSemaphore(value: 1), count: numberOfPhilosophers) - + static let forksSemaphore: [DispatchSemaphore] = Array(repeating: DispatchSemaphore(value: 1), count: numberOfPhilosophers) + let leftFork: DispatchSemaphore let rightFork: DispatchSemaphore - + init(leftIndex: Int, rightIndex: Int) { //Order forks by index to prevent deadlock if leftIndex > rightIndex { @@ -35,7 +34,7 @@ struct ForkPair { leftFork.wait() rightFork.wait() } - + func putDown() { //The order does not matter here leftFork.signal() @@ -47,61 +46,60 @@ struct ForkPair { struct Philosophers { let forkPair: ForkPair let philosopherIndex: Int - + var leftIndex = -1 var rightIndex = -1 - + init(philosopherIndex: Int) { leftIndex = philosopherIndex rightIndex = philosopherIndex - 1 - + if rightIndex < 0 { rightIndex += numberOfPhilosophers } self.forkPair = ForkPair(leftIndex: leftIndex, rightIndex: rightIndex) self.philosopherIndex = philosopherIndex - + print("Philosopher: \(philosopherIndex) left: \(leftIndex) right: \(rightIndex)") } - + func run() { while true { - print("Acquiring lock for Philosofer: \(philosopherIndex) Left:\(leftIndex) Right:\(rightIndex)") + print("Acquiring lock for Philosopher: \(philosopherIndex) Left:\(leftIndex) Right:\(rightIndex)") forkPair.pickUp() print("Start Eating Philosopher: \(philosopherIndex)") //sleep(1000) - print("Releasing lock for Philosofer: \(philosopherIndex) Left:\(leftIndex) Right:\(rightIndex)") + print("Releasing lock for Philosopher: \(philosopherIndex) Left:\(leftIndex) Right:\(rightIndex)") forkPair.putDown() } } } -// Layout of the table (P = philosopher, f = fork) for 4 Philosopher +// Layout of the table (P = philosopher, f = fork) for 4 Philosophers // P0 // f3 f0 // P3 P1 // f2 f1 // P2 - let globalSem = DispatchSemaphore(value: 0) for i in 0.. Date: Wed, 15 Mar 2017 19:53:29 -0700 Subject: [PATCH 0856/1679] links --- DiningPhilosophers/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DiningPhilosophers/README.md b/DiningPhilosophers/README.md index 29b5916e9..ec1611c65 100755 --- a/DiningPhilosophers/README.md +++ b/DiningPhilosophers/README.md @@ -1,5 +1,5 @@ # Dining Philosophers -Dining philosophers problem Algorithm implemented in Swift (concurrent algorithm design to illustrate synchronization issues and techniques for resolving them using GCD and Semaphore in Swift) +Dining philosophers problem Algorithm implemented in Swift (concurrent algorithm design to illustrate synchronization issues and techniques for resolving them using [GCD](https://apple.github.io/swift-corelibs-libdispatch/) and [Semaphore](https://developer.apple.com/reference/dispatch/dispatchsemaphore) in Swift) Written for Swift Algorithm Club by Jacopo Mangiavacchi From a9655534e55620364e975cabb78242dca9db0c11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=A9=98=E5=AD=90?= <726451484@qq.com> Date: Fri, 17 Mar 2017 11:06:13 +0800 Subject: [PATCH 0857/1679] Update ShellSortExample.swift Fix bug. Origin code probally get wrong answer.My fault. --- Shell Sort/ShellSortExample.swift | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/Shell Sort/ShellSortExample.swift b/Shell Sort/ShellSortExample.swift index efa035da3..c41eb8889 100644 --- a/Shell Sort/ShellSortExample.swift +++ b/Shell Sort/ShellSortExample.swift @@ -8,24 +8,25 @@ import Foundation -public func shellSort(_ list: inout [Int]) { - +public func shellSort(_ list : inout [Int]) +{ var sublistCount = list.count / 2 - - while sublistCount > 0 { - - for index in 0.. 0 + { + for var index in 0.. list[index + sublistCount] { - swap(&list[index], &list[index + sublistCount]) + if arr[index] > arr[index + sublistCount]{ + swap(&arr[index], &arr[index + sublistCount]) } guard sublistCount == 1 && index > 0 else { continue } - - if list[index - 1] > list[index] { - swap(&list[index - 1], &list[index]) + + while arr[index - 1] > arr[index] && index - 1 > 0 { + swap(&arr[index - 1], &arr[index]) + index -= 1 } } sublistCount = sublistCount / 2 From beddc9a7f4dd96b9122e849ace3c7dba57caaea7 Mon Sep 17 00:00:00 2001 From: Brandon05 Date: Fri, 17 Mar 2017 13:41:49 -0400 Subject: [PATCH 0858/1679] Updated syntax for Swift 3 Hello, I was recreating this file in playground and I noticed you still had the explicit @noescape . Thought I can lend a hand by removing it. Thanks for this awesome repository! --- Binary Tree/BinaryTree.swift | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Binary Tree/BinaryTree.swift b/Binary Tree/BinaryTree.swift index 61ae696c7..102f23e06 100644 --- a/Binary Tree/BinaryTree.swift +++ b/Binary Tree/BinaryTree.swift @@ -29,26 +29,26 @@ extension BinaryTree: CustomStringConvertible { } extension BinaryTree { - public func traverseInOrder(@noescape process: T -> Void) { + public func traverseInOrder(process: T -> Void) { if case let .node(left, value, right) = self { - left.traverseInOrder(process) + left.traverseInOrder(process: process) process(value) - right.traverseInOrder(process) + right.traverseInOrder(process: process) } } - public func traversePreOrder(@noescape process: T -> Void) { + public func traversePreOrder(process: T -> Void) { if case let .node(left, value, right) = self { process(value) - left.traversePreOrder(process) - right.traversePreOrder(process) + left.traversePreOrder(process: process) + right.traversePreOrder(process: process) } } - public func traversePostOrder(@noescape process: T -> Void) { + public func traversePostOrder(process: T -> Void) { if case let .node(left, value, right) = self { - left.traversePostOrder(process) - right.traversePostOrder(process) + left.traversePostOrder(process: process) + right.traversePostOrder(process: process) process(value) } } From 9677b8c0e6bbd32831b6eca6c69c6f09d64f9f37 Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Fri, 17 Mar 2017 20:10:53 -0700 Subject: [PATCH 0859/1679] Fixed indenting, and changed a scope modifier on the array property from public to fileprivate. --- Array2D/Array2D.playground/Contents.swift | 72 +++++++++++------------ Array2D/README.markdown | 24 ++++++-- 2 files changed, 54 insertions(+), 42 deletions(-) diff --git a/Array2D/Array2D.playground/Contents.swift b/Array2D/Array2D.playground/Contents.swift index 38d4eff23..8b18a333f 100644 --- a/Array2D/Array2D.playground/Contents.swift +++ b/Array2D/Array2D.playground/Contents.swift @@ -4,36 +4,36 @@ Performance is always O(1). */ public struct Array2D { - public let columns: Int - public let rows: Int - public var array: [T] - - public init(columns: Int, rows: Int, initialValue: T) { - self.columns = columns - self.rows = rows - array = [T](repeating: initialValue, count: rows*columns) + public let columns: Int + public let rows: Int + fileprivate var array: [T] + + public init(columns: Int, rows: Int, initialValue: T) { + self.columns = columns + self.rows = rows + array = [T](repeating: initialValue, count: rows*columns) + } + + public subscript(column: Int, row: Int) -> T { + get { + if isValidSubscript(column: column, row: row) { + return array[row*columns + column] + } else { + fatalError("Not a valid subscript") + } } - - public subscript(column: Int, row: Int) -> T { - get { - if isValidSubscript(column: column, row: row) { - return array[row*columns + column] - } else { - fatalError("Not a valid subscript") - } - } - set { - if isValidSubscript(column: column, row: row) { - array[row*columns + column] = newValue - } else { - fatalError("Not a valid subscript") - } - } - } - - private func isValidSubscript(column: Int, row: Int) -> Bool { - return column < columns && row < rows + set { + if isValidSubscript(column: column, row: row) { + array[row*columns + column] = newValue + } else { + fatalError("Not a valid subscript") + } } + } + + private func isValidSubscript(column: Int, row: Int) -> Bool { + return column < columns && row < rows + } } @@ -62,13 +62,13 @@ print(matrix.array) // print out the 2D array with a reference around the grid for i in 0.. { public let columns: Int public let rows: Int - private var array: [T] - + fileprivate var array: [T] + public init(columns: Int, rows: Int, initialValue: T) { self.columns = columns self.rows = rows - array = .init(repeating: initialValue, count: rows*columns) + array = [T](repeating: initialValue, count: rows*columns) } - + public subscript(column: Int, row: Int) -> T { get { - return array[row*columns + column] + if isValidSubscript(column: column, row: row) { + return array[row*columns + column] + } else { + fatalError("Not a valid subscript") + } } set { - array[row*columns + column] = newValue + if isValidSubscript(column: column, row: row) { + array[row*columns + column] = newValue + } else { + fatalError("Not a valid subscript") + } } } + + private func isValidSubscript(column: Int, row: Int) -> Bool { + return column < columns && row < rows + } } ``` From c4d39ec0dc41060f2ff5b5532e9fa69489c9bbef Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Fri, 17 Mar 2017 20:16:01 -0700 Subject: [PATCH 0860/1679] Updated the subscript check to use preconditions instead of a custom function. --- Array2D/Array2D.playground/Contents.swift | 22 +++++++--------------- Array2D/Array2D.swift | 9 +++++---- Array2D/README.markdown | 22 +++++++--------------- 3 files changed, 19 insertions(+), 34 deletions(-) diff --git a/Array2D/Array2D.playground/Contents.swift b/Array2D/Array2D.playground/Contents.swift index 8b18a333f..d088c99af 100644 --- a/Array2D/Array2D.playground/Contents.swift +++ b/Array2D/Array2D.playground/Contents.swift @@ -11,29 +11,21 @@ public struct Array2D { public init(columns: Int, rows: Int, initialValue: T) { self.columns = columns self.rows = rows - array = [T](repeating: initialValue, count: rows*columns) + array = .init(repeating: initialValue, count: rows*columns) } public subscript(column: Int, row: Int) -> T { get { - if isValidSubscript(column: column, row: row) { - return array[row*columns + column] - } else { - fatalError("Not a valid subscript") - } + precondition(column < columns, "Column \(column) Index is out of range. Array(columns: \(columns), rows:\(rows))") + precondition(row < rows, "Row \(row) Index is out of range. Array(columns: \(columns), rows:\(rows))") + return array[row*columns + column] } set { - if isValidSubscript(column: column, row: row) { - array[row*columns + column] = newValue - } else { - fatalError("Not a valid subscript") - } + precondition(column < columns, "Column \(column) Index is out of range. Array(columns: \(columns), rows:\(rows))") + precondition(row < rows, "Row \(row) Index is out of range. Array(columns: \(columns), rows:\(rows))") + array[row*columns + column] = newValue } } - - private func isValidSubscript(column: Int, row: Int) -> Bool { - return column < columns && row < rows - } } diff --git a/Array2D/Array2D.swift b/Array2D/Array2D.swift index 6d6c01902..df4822916 100644 --- a/Array2D/Array2D.swift +++ b/Array2D/Array2D.swift @@ -7,21 +7,22 @@ public struct Array2D { public let columns: Int public let rows: Int fileprivate var array: [T] - + public init(columns: Int, rows: Int, initialValue: T) { self.columns = columns self.rows = rows array = .init(repeating: initialValue, count: rows*columns) } - + public subscript(column: Int, row: Int) -> T { get { + precondition(column < columns, "Column \(column) Index is out of range. Array(columns: \(columns), rows:\(rows))") + precondition(row < rows, "Row \(row) Index is out of range. Array(columns: \(columns), rows:\(rows))") return array[row*columns + column] } set { - precondition(row < rows, "Row \(row) Index is out of range. Array(columns: \(columns), rows:\(rows))") precondition(column < columns, "Column \(column) Index is out of range. Array(columns: \(columns), rows:\(rows))") - + precondition(row < rows, "Row \(row) Index is out of range. Array(columns: \(columns), rows:\(rows))") array[row*columns + column] = newValue } } diff --git a/Array2D/README.markdown b/Array2D/README.markdown index 6550dc943..04afb9510 100644 --- a/Array2D/README.markdown +++ b/Array2D/README.markdown @@ -72,29 +72,21 @@ public struct Array2D { public init(columns: Int, rows: Int, initialValue: T) { self.columns = columns self.rows = rows - array = [T](repeating: initialValue, count: rows*columns) + array = .init(repeating: initialValue, count: rows*columns) } public subscript(column: Int, row: Int) -> T { get { - if isValidSubscript(column: column, row: row) { - return array[row*columns + column] - } else { - fatalError("Not a valid subscript") - } + precondition(column < columns, "Column \(column) Index is out of range. Array(columns: \(columns), rows:\(rows))") + precondition(row < rows, "Row \(row) Index is out of range. Array(columns: \(columns), rows:\(rows))") + return array[row*columns + column] } set { - if isValidSubscript(column: column, row: row) { - array[row*columns + column] = newValue - } else { - fatalError("Not a valid subscript") - } + precondition(column < columns, "Column \(column) Index is out of range. Array(columns: \(columns), rows:\(rows))") + precondition(row < rows, "Row \(row) Index is out of range. Array(columns: \(columns), rows:\(rows))") + array[row*columns + column] = newValue } } - - private func isValidSubscript(column: Int, row: Int) -> Bool { - return column < columns && row < rows - } } ``` From 162c3453bab7fa216cd3f11a9a45488ce9515c5c Mon Sep 17 00:00:00 2001 From: Ute Schiehlen Date: Tue, 21 Mar 2017 11:21:59 +0100 Subject: [PATCH 0861/1679] Exchanged old red-black tree implementation with new one, also updated redmea --- Red-Black Tree/README.markdown | 259 +++--- .../RedBlackTree.playground/Contents.swift | 22 + .../Sources/RedBlackTree.swift | 740 ++++++++++++++++++ .../contents.xcplayground | 4 + 4 files changed, 930 insertions(+), 95 deletions(-) create mode 100644 Red-Black Tree/RedBlackTree.playground/Contents.swift create mode 100644 Red-Black Tree/RedBlackTree.playground/Sources/RedBlackTree.swift create mode 100644 Red-Black Tree/RedBlackTree.playground/contents.xcplayground diff --git a/Red-Black Tree/README.markdown b/Red-Black Tree/README.markdown index 05993f016..74fffa415 100644 --- a/Red-Black Tree/README.markdown +++ b/Red-Black Tree/README.markdown @@ -1,120 +1,189 @@ # Red-Black Tree -A Red-Black tree is a special version of a [Binary Search Tree](https://github.com/raywenderlich/swift-algorithm-club/tree/master/Binary%20Search%20Tree). Binary search trees(BSTs) can become unbalanced after a lot of insertions/deletions. The only difference between a node from a BST and a Red-Black Tree(RBT) is that RBT nodes have a color property added to them which can either be red or black. A RBT rebalances itself by making sure the following properties hold: +A red-black tree (RBT) is a balanced version of a [Binary Search Tree](https://github.com/raywenderlich/swift-algorithm-club/tree/master/Binary%20Search%20Tree) guaranteeing that the basic operations (search, predecessor, successor, minimum, maximum, insert and delete) have a logarithmic worst case performance. -## Properties -1. A node is either red or black -2. The root is always black -3. All leaves are black -4. If a node is red, both of its children are black -5. Every path to a leaf contains the same number of black nodes (The amount of black nodes met when going down a RBT is called the black-depth of the tree.) - -## Methods -* `insert(_ value: T)` inserts the value into the tree -* `insert(_ values: [T])` inserts an array of values into the tree -* `delete(_ value: T)` deletes the value from the tree -* `find(_ value: T) -> RBTNode` looks for a node in the tree with given value and returns it -* `minimum(n: RBTNode) -> RBTNode` looks for the maximum value of a subtree starting at the given node -* `maximum(n: RBTNode) -> RBTNode` looks for the minimum value of a subtree starting at the given node -* `func verify()` verifies if the tree is still valid. Prints warning messages if this is not the case - -## Rotation +Binary search trees (BSTs) have the disadvantage that they can become unbalanced after some insert or delete operations. In the worst case, this could lead to a tree where the nodes build a linked list as shown in the following example: -In order to rebalance their nodes RBTs use an operation known as rotation. You can either left or right rotate a node and its child. Rotating a node and its child swaps the nodes and interchanges their subtrees. Left rotation swaps the parent node with its right child. while right rotation swaps the parent node with its left child. - -Left rotation: -``` -before left rotating p after left rotating p - p b - / \ / \ - a b -> p n - / \ / \ / \ -n n n n a n - / \ - n n -``` -Right rotation: ``` -before right rotating p after right rotating p - p a - / \ / \ - a b -> n p - / \ / \ / \ -n n n n n b - / \ - n n +a + \ + b + \ + c + \ + d ``` +To prevent this issue, RBTs perform rebalancing operations after an insert or delete and store an additional color property at each node which can either be red or black. After each operation a RBT satisfies the following properties: -## Insertion - -We create a new node with the value to be inserted into the tree. The color of this new node is always red. -We perform a standard BST insert with this node. Now the three might not be a valid RBT anymore. -We now go through several insertion steps in order to make the tree valid again. We call the just inserted node n. - -**Step 1**: We check if n is the rootNode, if so we paint it black and we are done. If not we go to Step 2. - -We now know that n at least has a parent as it is not the rootNode. - -**Step 2**: We check if the parent of n is black if so we are done. If not we go to Step 3. - -We now know the parent is also not the root node as the parent is red. Thus n also has a grandparent and thus also an uncle as every node has two children. This uncle may however be a nullLeaf - -**Step 3**: We check if n's uncle is red. If not we go to Step 4. If n's uncle is indeed red we recolor uncle and parent to black and n's grandparent to red. We now go back to step 1 performing the same logic on n's grandparent. - -From here there are four cases: -- **The left left case.** n's parent is the left child of its parent and n is the left child of its parent. -- **The left right case** n's parent is the left child of its parent and n is the right child of its parent. -- **The right right case** n's parent is the right child of its parent and n is the right child of its parent. -- **The right left case** n's parent is the right child of its parent and n is the left child of its parent. - -**Step 4**: checks if either the **left right** case or the **right left** case applies to the current situation. - - If we find the **left right case**, we left rotate n's parent and go to Step 5 while setting n to n's parent. (This transforms the **left right** case into the **left left** case) - - If we find the **right left case**, we right rotate n's parent and go to Step 5 while setting n to n's parent. (This transforms the **right left** case into the **right right** case) - - If we find neither of these two we proceed to Step 5. +## Properties -n's parent is now red, while n's grandparent is black. +1. Every node is either red or black +2. The root is black +3. Every leaf (nullLeaf) is black +4. If a node is red, then both its children are black +5. For each node, all paths from the node to descendant leaves contain the same number of black nodes -**Step 5**: We swap the colors of n's parent and grandparent. - - We either right rotate n's grandparent in case of the **left left** case - - Or we left rotate n's grandparent in case of the **right right** case +Property 5 includes the definition of the black-height of a node x, bh(x), which is the number of black nodes on a path from this node down to a leaf not counting the node itself. +From [CLRS] -Reaching the end we have successfully made the tree valid again. +## Methods -# Deletion +Nodes: +* `nodeX.getSuccessor()` Returns the inorder successor of nodeX +* `nodeX.minimum()` Returns the node with the minimum key of the subtree of nodeX +* `nodeX.maximum()` Returns the node with the maximum key of the subtree of nodeX +Tree: +* `search(input:)` Returns the node with the given key value +* `minValue()` Returns the minimum key value of the whole tree +* `maxValue()` Returns the maximum key value of the whole tree +* `insert(key:)` Inserts the key value into the tree +* `delete(key:)` Delete the node with the respective key value from the tree +* `verify()` Verifies that the given tree fulfills the red-black tree properties -Deletion is a little more complicated than insertion. In the following we call del the node to be deleted. -First we try and find the node to be deleted using find() -we send the result of find to del. -We now go through the following steps in order to delete the node del. +The rotation, insertion and deletion algorithms are implemented based on the pseudo-code provided in [CLRS] -First we do a few checks: -- Is del the rootNode if so set the root to a nullLeaf and we are done. -- If del has 2 nullLeaf children and is red. We check if del is either a left or a right child and set del's parent left or right to a nullLeaf. -- If del has two non nullLeaf children we look for the maximum value in del's left subtree. We set del's value to this maximum value and continue to instead delete this maximum node. Which we will now call del. +## Implementation Details -Because of these checks we now know that del has at most 1 non nullLeaf child. It has either two nullLeaf children or one nullLeaf and one regular red child. (The child is red otherwise the black-depth wouldn't be the same for every leaf) +For convenience, all nil-pointers to children or the parent (except the parent of the root) of a node are exchanged with a nullLeaf. This is an ordinary node object, like all other nodes in the tree, but with a black color, and in this case a nil value for its children, parent and key. Therefore, an empty tree consists of exactly one nullLeaf at the root. -We now call the non nullLeaf child of del, child. If del has two nullLeaf children child will be a nullLeaf. This means child can either be a nullLeaf or a red node. +## Rotation -We now have three options +Left rotation (around x): +Assumes that x.rightChild y is not a nullLeaf, rotates around the link from x to y, makes y the new root of the subtree with x as y's left child and y's left child as x's right child, where n = a node, [n] = a subtree +``` + | | + x y + / \ ~> / \ + [A] y x [C] + / \ / \ + [B] [C] [A] [B] +``` +Right rotation (around y): +Assumes that y.leftChild x is not a nullLeaf, rotates around the link from y to x, makes x the new root of the subtree with y as x's right child and x's right child as y's left child, where n = a node, [n] = a subtree +``` + | | + x y + / \ <~ / \ + [A] y x [C] + / \ / \ + [B] [C] [A] [B] +``` +As rotation is a local operation only exchanging pointers it's runtime is O(1). -- If del is red its child is a nullLeaf and we can just delete it as it doesn't change the black-depth of the tree. We are done +## Insertion -- If child is red we recolor it black and child's parent to del's parent. del is now deleted and we are done. +We create a node with the given key and set its color to red. Then we insert it into the the tree by performing a standard insert into a BST. After this, the tree might not be a valid RBT anymore, so we fix the red-black properties by calling the insertFixup algorithm. +The only violation of the red-black properties occurs at the inserted node z and its parent. Either both are red, or the parent does not exist (so there is a violation since the root must be black). +We have three distinct cases: +**Case 1:** The uncle of z is red. If z.parent is left child, z's uncle is z.grandparent's right child. If this is the case, we recolor and move z to z.grandparent, then we check again for this new z. In the following cases, we denote a red node with (x) and a black node with {x}, p = parent, gp = grandparent and u = uncle +``` + | | + {gp} (newZ) + / \ ~> / \ + (p) (u) {p} {u} + / \ / \ / \ / \ + (z) [C] [D] [E] (z) [C] [D] [E] + / \ / \ +[A] [B] [A] [B] -- Both del and child are black we go through +``` +**Case 2a:** The uncle of z is black and z is right child. Here, we move z upwards, so z's parent is the newZ and then we rotate around this newZ. After this, we have Case 2b. +``` + | | + {gp} {gp} + / \ ~> / \ + (p) {u} (z) {u} + / \ / \ / \ / \ + [A] (z) [D] [E] (newZ) [C] [D] [E] + / \ / \ + [B] [C] [A] [B] -If both del and child are black we introduce a new variable sibling. Which is del's sibling. We also replace del with child and recolor it doubleBlack. del is now deleted and child and sibling are siblings. +``` +**Case 2b:** The uncle of z is black and z is left child. In this case, we recolor z.parent to black and z.grandparent to red. Then we rotate around z's grandparent. Afterwards we have valid red-black tree. +``` + | | + {gp} {p} + / \ ~> / \ + (p) {u} (z) (gp) + / \ / \ / \ / \ + (z) [C] [D] [E] [A] [B] [C] {u} + / \ / \ +[A] [B] [D] [E] -We now have to go through a lot of steps in order to remove this doubleBlack color. Which are hard to explain in text without just writing the full code in text. This is due the many possible combination of nodes and colors. The code is commented, but if you don't quite understand please leave me a message. Also part of the deletion is described by the final link in the Also See section. +``` +Running time of this algorithm: +* Only case 1 may repeat, but this only h/2 steps, where h is the height of the tree +* Case 2a -> Case 2b -> red-black tree +* Case 2b -> red-black tree +As we perform case 1 at most O(log n) times and all other cases at most once, we have O(log n) recolorings and at most 2 rotations. +The overall runtime of insert is O(log n). + +## Deletion + +We search for the node with the given key, and if it exists we delete it by performing a standard delete from a BST. If the deleted nodes' color was red everything is fine, otherwise red-black properties may be violated so we call the fixup procedure deleteFixup. +Violations can be that the parent and child of the deleted node x where red, so we now have two adjacent red nodes, or if we deleted the root, the root could now be red, or the black height property is violated. +We have 4 cases: We call deleteFixup on node x +**Case 1:** The sibling of x is red. The sibling is the other child of x's parent, which is not x itself. In this case, we recolor the parent of x and x.sibling then we left rotate around x's parent. In the following cases s = sibling of x, (x) = red, {x} = black, |x| = red/black. +``` + | | + {p} {s} + / \ ~> / \ + {x} (s) (p) [D] + / \ / \ / \ + [A] [B] [C] [D] {x} [C] + / \ + [A] [B] -## Also see +``` +**Case 2:** The sibling of x is black and has two black children. Here, we recolor x.sibling to red, move x upwards to x.parent and check again for this newX. +``` + | | + |p| |newX| + / \ ~> / \ + {x} {s} {x} (s) + / \ / \ / \ / \ + [A] [B] {l} {r} [A] [B] {l} {r} + / \ / \ / \ / \ + [C][D][E][F] [C][D][E][F] -* [Wikipedia](https://en.wikipedia.org/wiki/Red–black_tree) -* [GeeksforGeeks - introduction](http://www.geeksforgeeks.org/red-black-tree-set-1-introduction-2/) -* [GeeksforGeeks - insertion](http://www.geeksforgeeks.org/red-black-tree-set-2-insert/) -* [GeeksforGeeks - deletion](http://www.geeksforgeeks.org/red-black-tree-set-3-delete-2/) +``` +**Case 3:** The sibling of x is black with one black child to the right. In this case, we recolor the sibling to red and sibling.leftChild to black, then we right rotate around the sibling. After this we have case 4. +``` + | | + |p| |p| + / \ ~> / \ + {x} {s} {x} {l} + / \ / \ / \ / \ + [A] [B] (l) {r} [A] [B] [C] (s) + / \ / \ / \ + [C][D][E][F] [D]{e} + / \ + [E] [F] -Important to note is that GeeksforGeeks doesn't mention a few deletion cases that do occur. The code however does implement these. +``` +**Case 4:** The sibling of x is black with one red child to the right. Here, we recolor the sibling to the color of x.parent and x.parent and sibling.rightChild to black. Then we left rotate around x.parent. After this operation we have a valid red-black tree. Here, ||x|| denotes that x can have either color red or black, but that this can be different to |x| color. This is important, as s gets the same color as p. +``` + | | + ||p|| ||s|| + / \ ~> / \ + {x} {s} {p} {r} + / \ / \ / \ / \ + [A] [B] |l| (r) {x} |l| [E] [F] + / \ / \ / \ / \ + [C][D][E][F] [A][B][C][D] -*Written for Swift Algorithm Club by Jaap Wijnen. Updated from Ashwin Raghuraman's contribution.* +``` +Running time of this algorithm: +* Only case 2 can repeat, but this only h many times, where h is the height of the tree +* Case 1 -> case 2 -> red-black tree + Case 1 -> case 3 -> case 4 -> red-black tree + Case 1 -> case 4 -> red-black tree +* Case 3 -> case 4 -> red-black tree +* Case 4 -> red-black tree +As we perform case 2 at most O(log n) times and all other steps at most once, we have O(log n) recolorings and at most 3 rotations. +The overall runtime of delete is O(log n). + +## Resources: +[CLRS] T. Cormen, C. Leiserson, R. Rivest, and C. Stein. "Introduction to Algorithms", Third Edition. 2009 + +*Written for Swift Algorithm Club by Ute Schiehlen. Updated from Jaap Wijnen and Ashwin Raghuraman's contributions.* diff --git a/Red-Black Tree/RedBlackTree.playground/Contents.swift b/Red-Black Tree/RedBlackTree.playground/Contents.swift new file mode 100644 index 000000000..5b19f9bd1 --- /dev/null +++ b/Red-Black Tree/RedBlackTree.playground/Contents.swift @@ -0,0 +1,22 @@ +//: Playground - noun: a place where people can play +// Test for the RedBlackTree implementation provided in the Source folder of this Playground +import Foundation + +let redBlackTree = RedBlackTree() + +let randomMax = Double(0x10000000) +var values = [Double]() +for _ in 0..<1000 { + let value = Double(arc4random()) / randomMax + values.append(value) + redBlackTree.insert(key: value) +} +redBlackTree.verify() + +for _ in 0..<1000 { + let rand = arc4random_uniform(UInt32(values.count)) + let index = Int(rand) + let value = values.remove(at: index) + redBlackTree.delete(key: value) +} +redBlackTree.verify() diff --git a/Red-Black Tree/RedBlackTree.playground/Sources/RedBlackTree.swift b/Red-Black Tree/RedBlackTree.playground/Sources/RedBlackTree.swift new file mode 100644 index 000000000..057909b07 --- /dev/null +++ b/Red-Black Tree/RedBlackTree.playground/Sources/RedBlackTree.swift @@ -0,0 +1,740 @@ +// +// RedBlackTree.swift +// +// Created by Ute Schiehlen on 14.03.17. +// Copyright © 2017 Ute Schiehlen. All rights reserved. +// + +import Foundation + +private enum RBTreeColor { + case red + case black +} + +private enum rotationDirection { + case left + case right +} + +// MARK: - RBNode + +public class RBTreeNode: Equatable { + public typealias RBNode = RBTreeNode + + fileprivate var color: RBTreeColor = .black + fileprivate var key: Key? + fileprivate var isNullLeaf = true + var leftChild: RBNode? + var rightChild: RBNode? + fileprivate weak var parent: RBNode? + + public init(key: Key?, leftChild: RBNode?, rightChild: RBNode?, parent: RBNode?) { + self.key = key + self.leftChild = leftChild + self.rightChild = rightChild + self.parent = parent + + self.leftChild?.parent = self + self.rightChild?.parent = self + } + + public convenience init(key: Key?) { + self.init(key: key, leftChild: RBNode(), rightChild: RBNode(), parent: RBNode()) + self.isNullLeaf = false + } + + // For initialising the nullLeaf + public convenience init() { + self.init(key: nil, leftChild: nil, rightChild: nil, parent: nil) + self.color = .black + self.isNullLeaf = true + } + + var isRoot: Bool { + return parent == nil + } + + var isLeaf: Bool { + return rightChild == nil && leftChild == nil + } + + var isLeftCild: Bool { + return parent?.leftChild === self + } + + var isRightChild: Bool { + return parent?.rightChild === self + } + + var grandparent: RBNode? { + return parent?.parent + } + + var sibling: RBNode? { + if isLeftCild { + return parent?.rightChild + } else { + return parent?.leftChild + } + } + + var uncle: RBNode? { + return parent?.sibling + } +} + +// MARK: - RedBlackTree + +public class RedBlackTree { + public typealias RBNode = RBTreeNode + + fileprivate(set) var root: RBNode + fileprivate(set) var size = 0 + fileprivate let nullLeaf = RBNode() + + public init() { + root = nullLeaf + } +} + +// MARK: - Equatable protocol + +extension RBTreeNode { + static public func ==(lhs: RBTreeNode, rhs: RBTreeNode) -> Bool { + return lhs.key == rhs.key + } +} + +// MARK: - Finding a nodes successor + +extension RBTreeNode { + /* + * Returns the inorder successor node of a node + * The successor is a node with the next larger key value of the current node + */ + public func getSuccessor() -> RBNode? { + // If node has right child: successor min of this right tree + if let rightChild = self.rightChild { + if !rightChild.isNullLeaf { + return rightChild.minimum() + } + } + // Else go upward until node left child + var currentNode = self + var parent = currentNode.parent + while currentNode.isRightChild { + if let parent = parent { + currentNode = parent + } + parent = currentNode.parent + } + return parent + } +} + +// MARK: - Searching + +extension RBTreeNode { + /* + * Returns the node with the minimum key of the current subtree + */ + public func minimum() -> RBNode? { + if let leftChild = leftChild { + if !leftChild.isNullLeaf { + return leftChild.minimum() + } + return self + } + return self + } + + /* + * Returns the node with the maximum key of the current subtree + */ + public func maximum() -> RBNode? { + if let rightChild = rightChild { + if !rightChild.isNullLeaf { + return rightChild.maximum() + } + return self + } + return self + } +} + +extension RedBlackTree { + /* + * Returns the node with the given key |input| if existing + */ + public func search(input: Key) -> RBNode? { + return search(key: input, node: root) + } + + /* + * Returns the node with given |key| in subtree of |node| + */ + fileprivate func search(key: Key, node: RBNode?) -> RBNode? { + // If node nil -> key not found + guard let node = node else { + return nil + } + // If node is nullLeaf == semantically same as if nil + if !node.isNullLeaf { + if let nodeKey = node.key { + // Node found + if key == nodeKey { + return node + } else if key < nodeKey { + return search(key: key, node: node.leftChild) + } else { + return search(key: key, node: node.rightChild) + } + } + } + return nil + } +} + +// MARK: - Finding maximum and minimum value + +extension RedBlackTree { + /* + * Returns the minimum key value of the whole tree + */ + public func minValue() -> Key? { + if let minNode = root.minimum() { + return minNode.key + } else { + return nil + } + } + + /* + * Returns the maximum key value of the whole tree + */ + public func maxValue() -> Key? { + if let maxNode = root.maximum() { + return maxNode.key + } else { + return nil + } + } +} + +// MARK: - Inserting new nodes + +extension RedBlackTree { + /* + * Insert a node with key |key| into the tree + * 1. Perform normal insert operation as in a binary search tree + * 2. Fix red-black properties + * Runntime: O(log n) + */ + public func insert(key: Key) { + if root.isNullLeaf { + root = RBNode(key: key) + } else { + insert(input: RBNode(key: key), node: root) + } + + size += 1 + } + + /* + * Nearly identical insert operation as in a binary search tree + * Differences: All nil pointers are replaced by the nullLeaf, we color the inserted node red, + * after inserting we call insertFixup to maintain the red-black properties + */ + private func insert(input: RBNode, node: RBNode) { + guard let inputKey = input.key, let nodeKey = node.key else { + return + } + if inputKey < nodeKey { + guard let child = node.leftChild else { + addAsLeftChild(child: input, parent: node) + return + } + if child.isNullLeaf { + addAsLeftChild(child: input, parent: node) + } else { + insert(input: input, node: child) + } + } else { + guard let child = node.rightChild else { + addAsRightChild(child: input, parent: node) + return + } + if child.isNullLeaf { + addAsRightChild(child: input, parent: node) + } else { + insert(input: input, node: child) + } + } + } + + private func addAsLeftChild(child: RBNode, parent: RBNode) { + parent.leftChild = child + child.parent = parent + child.color = .red + insertFixup(node: child) + } + + private func addAsRightChild(child: RBNode, parent: RBNode) { + parent.rightChild = child + child.parent = parent + child.color = .red + insertFixup(node: child) + } + + /* + * Fixes possible violations of the red-black property after insertion + * Only violation of red-black properties occurs at inserted node |z| and z.parent + * We have 3 distinct cases: case 1, 2a and 2b + * - case 1: may repeat, but only h/2 steps, where h is the height of the tree + * - case 2a -> case 2b -> red-black tree + * - case 2b -> red-black tree + */ + private func insertFixup(node z: RBNode) { + if(!z.isNullLeaf) { + guard let parentZ = z.parent else{ + return + } + // If both |z| and his parent are red -> violation of red-black property -> need to fix it + if parentZ.color == .red { + guard let uncle = z.uncle else { + return + } + // Case 1: Uncle red -> recolor + move z + if uncle.color == .red { + parentZ.color = .black + uncle.color = .black + if let grandparentZ = parentZ.parent { + grandparentZ.color = .red + // Move z to grandparent and check again + insertFixup(node: grandparentZ) + } + } + // Case 2: Uncle black + else { + var zNew = z + // Case 2.a: z right child -> rotate + if parentZ.isLeftCild && z.isRightChild { + zNew = parentZ + leftRotate(node: zNew) + } else if parentZ.isRightChild && z.isLeftCild { + zNew = parentZ + rightRotate(node: zNew) + } + // Case 2.b: z left child -> recolor + rotate + zNew.parent?.color = .black + if let grandparentZnew = zNew.grandparent { + grandparentZnew.color = .red + if z.isLeftCild { + rightRotate(node: grandparentZnew) + } else { + leftRotate(node: grandparentZnew) + } + // We have a valid red-black-tree + } + } + } + } + root.color = .black + } +} + +// MARK: - Deleting a node +extension RedBlackTree { + /* + * Delete a node with key |key| from the tree + * 1. Perform standard delete operation as in a binary search tree + * 2. Fix red-black properties + * Runntime: O(log n) + */ + public func delete(key: Key) { + if size == 1 { + root = nullLeaf + size -= 1 + } else if let node = search(key: key, node: root) { + if !node.isNullLeaf { + delete(node: node) + size -= 1 + } + } + } + + /* + * Nearly identical delete operation as in a binary search tree + * Differences: All nil pointers are replaced by the nullLeaf, + * after deleting we call insertFixup to maintain the red-black properties if the delted node was + * black (as if it was red -> no violation of red-black properties) + */ + private func delete(node z: RBNode) { + var nodeY = RBNode() + var nodeX = RBNode() + if let leftChild = z.leftChild, let rightChild = z.rightChild { + if leftChild.isNullLeaf || rightChild.isNullLeaf { + nodeY = z + } else { + if let successor = z.getSuccessor() { + nodeY = successor + } + } + } + if let leftChild = nodeY.leftChild { + if !leftChild.isNullLeaf { + nodeX = leftChild + } else if let rightChild = nodeY.rightChild { + nodeX = rightChild + } + } + nodeX.parent = nodeY.parent + if let parentY = nodeY.parent { + // Should never be the case, as parent of root = nil + if parentY.isNullLeaf { + root = nodeX + } else { + if nodeY.isLeftCild { + parentY.leftChild = nodeX + } else { + parentY.rightChild = nodeX + } + } + } else { + root = nodeX + } + if nodeY != z { + z.key = nodeY.key + } + // If sliced out node was red -> nothing to do as red-black-property holds + // If it was black -> fix red-black-property + if nodeY.color == .black { + deleteFixup(node: nodeX) + } + } + + /* + * Fixes possible violations of the red-black property after deletion + * We have w distinct cases: only case 2 may repeat, but only h many steps, where h is the height + * of the tree + * - case 1 -> case 2 -> red-black tree + * case 1 -> case 3 -> case 4 -> red-black tree + * case 1 -> case 4 -> red-black tree + * - case 3 -> case 4 -> red-black tree + * - case 4 -> red-black tree + */ + private func deleteFixup(node x: RBNode) { + var xTmp = x + if !x.isRoot && x.color == .black { + guard var sibling = x.sibling else { + return + } + // Case 1: Sibling of x is red + if sibling.color == .red { + // Recolor + sibling.color = .black + if let parentX = x.parent { + parentX.color = .red + // Rotation + if x.isLeftCild { + leftRotate(node: parentX) + } else { + rightRotate(node: parentX) + } + // Update sibling + if let sibl = x.sibling { + sibling = sibl + } + } + } + // Case 2: Sibling is black with two black children + if sibling.leftChild?.color == .black && sibling.rightChild?.color == .black { + // Recolor + sibling.color = .red + // Move fake black unit upwards + if let parentX = x.parent { + deleteFixup(node: parentX) + } + // We have a valid red-black-tree + } else { + // Case 3: a. Sibling black with one black child to the right + if x.isLeftCild && sibling.rightChild?.color == .black { + // Recolor + sibling.leftChild?.color = .black + sibling.color = .red + // Rotate + rightRotate(node: sibling) + // Update sibling of x + if let sibl = x.sibling { + sibling = sibl + } + } + // Still case 3: b. One black child to the left + else if x.isRightChild && sibling.leftChild?.color == .black { + // Recolor + sibling.rightChild?.color = .black + sibling.color = .red + // Rotate + leftRotate(node: sibling) + // Update sibling of x + if let sibl = x.sibling { + sibling = sibl + } + } + // Case 4: Sibling is black with red right child + // Recolor + if let parentX = x.parent { + sibling.color = parentX.color + parentX.color = .black + // a. x left and sibling with red right child + if x.isLeftCild { + sibling.rightChild?.color = .black + // Rotate + leftRotate(node: parentX) + } + // b. x right and sibling with red left child + else { + sibling.leftChild?.color = .black + //Rotate + rightRotate(node: parentX) + } + // We have a valid red-black-tree + xTmp = root + } + } + } + xTmp.color = .black + } +} + +// MARK: - Rotation +extension RedBlackTree { + /* + * Left rotation around node x + * Assumes that x.rightChild y is not a nullLeaf, rotates around the link from x to y, + * makes y the new root of the subtree with x as y's left child and y's left child as x's right + * child, where n = a node, [n] = a subtree + * | | + * x y + * / \ ~> / \ + * [A] y x [C] + * / \ / \ + * [B] [C] [A] [B] + */ + fileprivate func leftRotate(node x: RBNode) { + rotate(node: x, direction: .left) + } + + + /* + * Right rotation around node y + * Assumes that y.leftChild x is not a nullLeaf, rotates around the link from y to x, + * makes x the new root of the subtree with y as x's right child and x's right child as y's left + * child, where n = a node, [n] = a subtree + * | | + * x y + * / \ <~ / \ + * [A] y x [C] + * / \ / \ + * [B] [C] [A] [B] + */ + fileprivate func rightRotate(node x: RBNode) { + rotate(node: x, direction: .right) + } + + /* + * Rotation around a node x + * Is a local operation preserving the binary-search-tree property that only exchanges pointers. + * Runntime: O(1) + */ + private func rotate(node x: RBNode, direction: rotationDirection) { + var nodeY: RBNode? = RBNode() + + // Set |nodeY| and turn |nodeY|'s left/right subtree into |x|'s right/left subtree + switch direction { + case .left: + nodeY = x.rightChild + x.rightChild = nodeY?.leftChild + x.rightChild?.parent = x + case .right: + nodeY = x.leftChild + x.leftChild = nodeY?.rightChild + x.leftChild?.parent = x + } + + // Link |x|'s parent to nodeY + nodeY?.parent = x.parent + if x.isRoot { + if let node = nodeY { + root = node + } + } else if x.isLeftCild { + x.parent?.leftChild = nodeY + } else if x.isRightChild { + x.parent?.rightChild = nodeY + } + + // Put |x| on |nodeY|'s left + switch direction { + case .left: + nodeY?.leftChild = x + case .right: + nodeY?.rightChild = x + } + x.parent = nodeY + } +} + +// MARK: - Verify +extension RedBlackTree { + /* + * Verifies that the existing tree fulfills all red-black properties + * Returns true if the tree is a valid red-black tree, false otherwise + */ + public func verify() -> Bool { + if root.isNullLeaf { + print("The tree is empty") + return true + } + return property2() && property4() && property5() + } + + // Property 1: Every node is either red or black -> fullfilled through setting node.color of type + // RBTreeColor + + + // Property 2: The root is black + private func property2() -> Bool { + if root.color == .red { + print("Property-Error: Root is red") + return false + } + return true + } + + // Property 3: Every nullLeaf is black -> fullfilled through initialising nullLeafs with color = black + + // Property 4: If a node is red, then both its children are black + private func property4() -> Bool { + return property4(node: root) + } + + private func property4(node: RBNode) -> Bool { + if node.isNullLeaf { + return true + } + if let leftChild = node.leftChild, let rightChild = node.rightChild { + if node.color == .red { + if !leftChild.isNullLeaf && leftChild.color == .red { + print("Property-Error: Red node with key \(node.key ?? nil) has red left child") + return false + } + if !rightChild.isNullLeaf && rightChild.color == .red { + print("Property-Error: Red node with key \(node.key ?? nil) has red right child") + return false + } + } + return property4(node: leftChild) && property4(node: rightChild) + } + return false + } + + // Property 5: For each node, all paths from the node to descendant leaves contain the same number + // of black nodes (same blackheight) + private func property5() -> Bool { + if property5(node: root) == -1 { + return false + } else { + return true + } + } + + private func property5(node: RBNode) -> Int { + if node.isNullLeaf { + return 0 + } + guard let leftChild = node.leftChild, let rightChild = node.rightChild else { + return -1 + } + let left = property5(node: leftChild) + let right = property5(node: rightChild) + + if left == -1 || right == -1 { + return -1 + } else if left == right { + let addedHeight = node.color == .black ? 1 : 0 + return left + addedHeight + } else { + print("Property-Error: Black height violated at node with key \(node.key ?? nil)") + return -1 + } + } +} + +// MARK: - Debugging + +extension RBTreeNode: CustomDebugStringConvertible { + public var debugDescription: String { + var s = "" + if isNullLeaf { + s = "nullLeaf" + } else { + if let key = key { + s = "key: \(key)" + } else { + s = "key: nil" + } + if let parent = parent { + s += ", parent: \(parent.key)" + } + if let left = leftChild { + s += ", left = [" + left.debugDescription + "]" + } + if let right = rightChild { + s += ", right = [" + right.debugDescription + "]" + } + s += ", color = \(color)" + } + return s + } +} + +extension RedBlackTree: CustomDebugStringConvertible { + public var debugDescription: String { + return root.debugDescription + } +} + +extension RBTreeNode: CustomStringConvertible { + public var description: String { + var s = "" + if isNullLeaf { + s += "nullLeaf" + } else { + if let left = leftChild { + s += "(\(left.description)) <- " + } + if let key = key { + s += "\(key)" + } else { + s += "nil" + } + s += ", \(color)" + if let right = rightChild { + s += " -> (\(right.description))" + } + } + return s + } +} + +extension RedBlackTree: CustomStringConvertible { + public var description: String { + if root.isNullLeaf { + return "[]" + } else{ + return root.description + } + } +} diff --git a/Red-Black Tree/RedBlackTree.playground/contents.xcplayground b/Red-Black Tree/RedBlackTree.playground/contents.xcplayground new file mode 100644 index 000000000..5da2641c9 --- /dev/null +++ b/Red-Black Tree/RedBlackTree.playground/contents.xcplayground @@ -0,0 +1,4 @@ + + + + \ No newline at end of file From cf91833f5688398045bb7b76150bc988df747580 Mon Sep 17 00:00:00 2001 From: Ute Schiehlen Date: Tue, 21 Mar 2017 11:23:37 +0100 Subject: [PATCH 0862/1679] Deleted old version --- .../Contents.swift | 20 - .../Sources/RBTree.swift | 521 ------------------ .../contents.xcplayground | 4 - .../contents.xcworkspacedata | 0 4 files changed, 545 deletions(-) delete mode 100644 Red-Black Tree/Red-Black Tree 2.playground/Contents.swift delete mode 100644 Red-Black Tree/Red-Black Tree 2.playground/Sources/RBTree.swift delete mode 100644 Red-Black Tree/Red-Black Tree 2.playground/contents.xcplayground rename Red-Black Tree/{Red-Black Tree 2.playground => RedBlackTree.playground}/playground.xcworkspace/contents.xcworkspacedata (100%) diff --git a/Red-Black Tree/Red-Black Tree 2.playground/Contents.swift b/Red-Black Tree/Red-Black Tree 2.playground/Contents.swift deleted file mode 100644 index d55c153d5..000000000 --- a/Red-Black Tree/Red-Black Tree 2.playground/Contents.swift +++ /dev/null @@ -1,20 +0,0 @@ -//: Playground - noun: a place where people can play -import Foundation - -let tree = RBTree() -let randomMax = Double(0x100000000) -var values = [Double]() -for _ in 0..<1000 { - let value = Double(arc4random()) / randomMax - values.append(value) - tree.insert(value) -} -tree.verify() - -for _ in 0..<1000 { - let rand = arc4random_uniform(UInt32(values.count)) - let index = Int(rand) - let value = values.remove(at: index) - tree.delete(value) -} -tree.verify() diff --git a/Red-Black Tree/Red-Black Tree 2.playground/Sources/RBTree.swift b/Red-Black Tree/Red-Black Tree 2.playground/Sources/RBTree.swift deleted file mode 100644 index 1735798d5..000000000 --- a/Red-Black Tree/Red-Black Tree 2.playground/Sources/RBTree.swift +++ /dev/null @@ -1,521 +0,0 @@ - -private enum RBTColor { - case red - case black - case doubleBlack -} - -public class RBTNode: CustomStringConvertible { - fileprivate var color: RBTColor = .red - public var value: T! = nil - public var right: RBTNode! - public var left: RBTNode! - public var parent: RBTNode! - - public var description: String { - if self.value == nil { - return "null" - } else { - var nodeValue: String - - // If the value is encapsulated by parentheses it is red - // If the value is encapsulated by pipes it is black - // If the value is encapsulated by double pipes it is double black (This should not occur in a verified RBTree) - if self.isRed { - nodeValue = "(\(self.value!))" - } else if self.isBlack{ - nodeValue = "|\(self.value!)|" - } else { - nodeValue = "||\(self.value!)||" - } - - return "(\(self.left.description)<-\(nodeValue)->\(self.right.description))" - } - } - - init(tree: RBTree) { - right = tree.nullLeaf - left = tree.nullLeaf - parent = tree.nullLeaf - } - - init() { - //This method is here to support the creation of a nullLeaf - } - - public var isLeftChild: Bool { - return self.parent.left === self - } - - public var isRightChild: Bool { - return self.parent.right === self - } - - public var grandparent: RBTNode { - return parent.parent - } - - public var sibling: RBTNode { - if isLeftChild { - return self.parent.right - } else { - return self.parent.left - } - } - - public var uncle: RBTNode { - return parent.sibling - } - - fileprivate var isRed: Bool { - return color == .red - } - - fileprivate var isBlack: Bool { - return color == .black - } - - fileprivate var isDoubleBlack: Bool { - return color == .doubleBlack - } -} - -public class RBTree: CustomStringConvertible { - public var root: RBTNode - fileprivate let nullLeaf: RBTNode - - public var description: String { - return root.description - } - - public init() { - nullLeaf = RBTNode() - nullLeaf.color = .black - root = nullLeaf - } - - public convenience init(withValue value: T) { - self.init() - insert(value) - } - - public convenience init(withArray array: [T]) { - self.init() - insert(array) - } - - public func insert(_ value: T) { - let newNode = RBTNode(tree: self) - newNode.value = value - insertNode(n: newNode) - } - - public func insert(_ values: [T]) { - for value in values { - print(value) - insert(value) - } - } - - public func delete(_ value: T) { - let nodeToDelete = find(value) - if nodeToDelete !== nullLeaf { - deleteNode(n: nodeToDelete) - } - } - - public func find(_ value: T) -> RBTNode { - let foundNode = findNode(rootNode: root, value: value) - return foundNode - } - - public func minimum(n: RBTNode) -> RBTNode { - var min = n - if n.left !== nullLeaf { - min = minimum(n: n.left) - } - - return min - } - - public func maximum(n: RBTNode) -> RBTNode { - var max = n - if n.right !== nullLeaf { - max = maximum(n: n.right) - } - - return max - } - - public func verify() { - if self.root === nullLeaf { - print("The tree is empty") - return - } - property1() - property2(n: self.root) - property3() - } - - private func findNode(rootNode: RBTNode, value: T) -> RBTNode { - var nextNode = rootNode - if rootNode !== nullLeaf && value != rootNode.value { - if value < rootNode.value { - nextNode = findNode(rootNode: rootNode.left, value: value) - } else { - nextNode = findNode(rootNode: rootNode.right, value: value) - } - } - - return nextNode - } - - private func insertNode(n: RBTNode) { - BSTInsertNode(n: n, parent: root) - insertCase1(n: n) - } - - private func BSTInsertNode(n: RBTNode, parent: RBTNode) { - if parent === nullLeaf { - self.root = n - } else if n.value < parent.value { - if parent.left !== nullLeaf { - BSTInsertNode(n: n, parent: parent.left) - } else { - parent.left = n - parent.left.parent = parent - } - } else { - if parent.right !== nullLeaf { - BSTInsertNode(n: n, parent: parent.right) - } else { - parent.right = n - parent.right.parent = parent - } - } - } - - // if node is root change color to black, else move on - private func insertCase1(n: RBTNode) { - if n === root { - n.color = .black - } else { - insertCase2(n: n) - } - } - - // if parent of node is not black, and node is not root move on - private func insertCase2(n: RBTNode) { - if !n.parent.isBlack { - insertCase3(n: n) - } - } - - // if uncle is red do stuff otherwise move to 4 - private func insertCase3(n: RBTNode) { - if n.uncle.isRed { // node must have grandparent as children of root have a black parent - // both parent and uncle are red, so grandparent must be black. - n.parent.color = .black - n.uncle.color = .black - n.grandparent.color = .red - // now both parent and uncle are black and grandparent is red. - // we repeat for the grandparent - insertCase1(n: n.grandparent) - } else { - insertCase4(n: n) - } - } - - // parent is red, grandparent is black, uncle is black - // There are 4 cases left: - // - left left - // - left right - // - right right - // - right left - - // the cases "left right" and "right left" can be rotated into the other two - // so if either of the two is detected we apply a rotation and then move on to - // deal with the final two cases, if neither is detected we move on to those cases anyway - private func insertCase4(n: RBTNode) { - if n.parent.isLeftChild && n.isRightChild { // left right case - leftRotate(n: n.parent) - insertCase5(n: n.left) - } else if n.parent.isRightChild && n.isLeftChild { // right left case - rightRotate(n: n.parent) - insertCase5(n: n.right) - } else { - insertCase5(n: n) - } - } - - private func insertCase5(n: RBTNode) { - // swap color of parent and grandparent - // parent is red grandparent is black - n.parent.color = .black - n.grandparent.color = .red - - if n.isLeftChild { // left left case - rightRotate(n: n.grandparent) - } else { // right right case - leftRotate(n: n.grandparent) - } - } - - private func deleteNode(n: RBTNode) { - var toDel = n - - if toDel.left === nullLeaf && toDel.right === nullLeaf && toDel.parent === nullLeaf { - self.root = nullLeaf - return - } - - if toDel.left === nullLeaf && toDel.right === nullLeaf && toDel.isRed { - if toDel.isLeftChild { - toDel.parent.left = nullLeaf - } else { - toDel.parent.right = nullLeaf - } - return - } - - if toDel.left !== nullLeaf && toDel.right !== nullLeaf { - let pred = maximum(n: toDel.left) - toDel.value = pred.value - toDel = pred - } - - // from here toDel has at most 1 non nullLeaf child - - var child: RBTNode - if toDel.left !== nullLeaf { - child = toDel.left - } else { - child = toDel.right - } - - if toDel.isRed || child.isRed { - child.color = .black - - if toDel.isLeftChild { - toDel.parent.left = child - } else { - toDel.parent.right = child - } - - if child !== nullLeaf { - child.parent = toDel.parent - } - } else { // both toDel and child are black - - var sibling = toDel.sibling - - if toDel.isLeftChild { - toDel.parent.left = child - } else { - toDel.parent.right = child - } - if child !== nullLeaf { - child.parent = toDel.parent - } - child.color = .doubleBlack - - while child.isDoubleBlack || (child.parent !== nullLeaf && child.parent != nil) { - if sibling.isBlack { - - var leftRedChild: RBTNode! = nil - if sibling.left.isRed { - leftRedChild = sibling.left - } - var rightRedChild: RBTNode! = nil - if sibling.right.isRed { - rightRedChild = sibling.right - } - - if leftRedChild != nil || rightRedChild != nil { // at least one of sibling's children are red - child.color = .black - if sibling.isLeftChild { - if leftRedChild != nil { // left left case - sibling.left.color = .black - let tempColor = sibling.parent.color - sibling.parent.color = sibling.color - sibling.color = tempColor - rightRotate(n: sibling.parent) - } else { // left right case - if sibling.parent.isRed { - sibling.parent.color = .black - } else { - sibling.right.color = .black - } - leftRotate(n: sibling) - rightRotate(n: sibling.grandparent) - } - } else { - if rightRedChild != nil { // right right case - sibling.right.color = .black - let tempColor = sibling.parent.color - sibling.parent.color = sibling.color - sibling.color = tempColor - leftRotate(n: sibling.parent) - } else { // right left case - if sibling.parent.isRed { - sibling.parent.color = .black - } else { - sibling.left.color = .black - } - rightRotate(n: sibling) - leftRotate(n: sibling.grandparent) - } - } - break - } else { // both sibling's children are black - child.color = .black - sibling.color = .red - if sibling.parent.isRed { - sibling.parent.color = .black - break - } - /* - sibling.parent.color = .doubleBlack - child = sibling.parent - sibling = child.sibling - */ - if sibling.parent.parent === nullLeaf { // parent of child is root - break - } else { - sibling.parent.color = .doubleBlack - child = sibling.parent - sibling = child.sibling // can become nill if child is root as parent is nullLeaf - } - //--------------- - } - } else { // sibling is red - sibling.color = .black - - if sibling.isLeftChild { // left case - rightRotate(n: sibling.parent) - sibling = sibling.right.left - sibling.parent.color = .red - } else { // right case - leftRotate(n: sibling.parent) - sibling = sibling.left.right - sibling.parent.color = .red - } - } - - // sibling check is here for when child is a nullLeaf and thus does not have a parent. - // child is here as sibling can become nil when child is the root - if (sibling.parent === nullLeaf) || (child !== nullLeaf && child.parent === nullLeaf) { - child.color = .black - } - } - } - } - - private func property1() { - - if self.root.isRed { - print("Root is not black") - } - } - - private func property2(n: RBTNode) { - if n === nullLeaf { - return - } - if n.isRed { - if n.left !== nullLeaf && n.left.isRed { - print("Red node: \(n.value), has red left child") - } else if n.right !== nullLeaf && n.right.isRed { - print("Red node: \(n.value), has red right child") - } - } - property2(n: n.left) - property2(n: n.right) - } - - private func property3() { - let bDepth = blackDepth(root: self.root) - - let leaves:[RBTNode] = getLeaves(n: self.root) - - for leaflet in leaves { - var leaf = leaflet - var i = 0 - - while leaf !== nullLeaf { - if leaf.isBlack { - i = i + 1 - } - leaf = leaf.parent - } - - if i != bDepth { - print("black depth: \(bDepth), is not equal (depth: \(i)) for leaf with value: \(leaflet.value)") - } - } - - } - - private func getLeaves(n: RBTNode) -> [RBTNode] { - var leaves = [RBTNode]() - - if n !== nullLeaf { - if n.left === nullLeaf && n.right === nullLeaf { - leaves.append(n) - } else { - let leftLeaves = getLeaves(n: n.left) - let rightLeaves = getLeaves(n: n.right) - - leaves.append(contentsOf: leftLeaves) - leaves.append(contentsOf: rightLeaves) - } - } - - return leaves - } - - private func blackDepth(root: RBTNode) -> Int { - if root === nullLeaf { - return 0 - } else { - let returnValue = root.isBlack ? 1 : 0 - return returnValue + (max(blackDepth(root: root.left), blackDepth(root: root.right))) - } - } - - private func leftRotate(n: RBTNode) { - let newRoot = n.right! - n.right = newRoot.left! - if newRoot.left !== nullLeaf { - newRoot.left.parent = n - } - newRoot.parent = n.parent - if n.parent === nullLeaf { - self.root = newRoot - } else if n.isLeftChild { - n.parent.left = newRoot - } else { - n.parent.right = newRoot - } - newRoot.left = n - n.parent = newRoot - } - - private func rightRotate(n: RBTNode) { - let newRoot = n.left! - n.left = newRoot.right! - if newRoot.right !== nullLeaf { - newRoot.right.parent = n - } - newRoot.parent = n.parent - if n.parent === nullLeaf { - self.root = newRoot - } else if n.isRightChild { - n.parent.right = newRoot - } else { - n.parent.left = newRoot - } - newRoot.right = n - n.parent = newRoot - } -} diff --git a/Red-Black Tree/Red-Black Tree 2.playground/contents.xcplayground b/Red-Black Tree/Red-Black Tree 2.playground/contents.xcplayground deleted file mode 100644 index 5da2641c9..000000000 --- a/Red-Black Tree/Red-Black Tree 2.playground/contents.xcplayground +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/Red-Black Tree/Red-Black Tree 2.playground/playground.xcworkspace/contents.xcworkspacedata b/Red-Black Tree/RedBlackTree.playground/playground.xcworkspace/contents.xcworkspacedata similarity index 100% rename from Red-Black Tree/Red-Black Tree 2.playground/playground.xcworkspace/contents.xcworkspacedata rename to Red-Black Tree/RedBlackTree.playground/playground.xcworkspace/contents.xcworkspacedata From dc460542ffe226bbb0175fec35a9195eac87d9a3 Mon Sep 17 00:00:00 2001 From: Ute Schiehlen Date: Tue, 21 Mar 2017 11:30:51 +0100 Subject: [PATCH 0863/1679] Added licence to file --- .../Sources/RedBlackTree.swift | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/Red-Black Tree/RedBlackTree.playground/Sources/RedBlackTree.swift b/Red-Black Tree/RedBlackTree.playground/Sources/RedBlackTree.swift index 057909b07..a588ea6bc 100644 --- a/Red-Black Tree/RedBlackTree.playground/Sources/RedBlackTree.swift +++ b/Red-Black Tree/RedBlackTree.playground/Sources/RedBlackTree.swift @@ -1,9 +1,22 @@ +//Copyright (c) 2016 Matthijs Hollemans and contributors // -// RedBlackTree.swift +//Permission is hereby granted, free of charge, to any person obtaining a copy +//of this software and associated documentation files (the "Software"), to deal +//in the Software without restriction, including without limitation the rights +//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +//copies of the Software, and to permit persons to whom the Software is +//furnished to do so, subject to the following conditions: // -// Created by Ute Schiehlen on 14.03.17. -// Copyright © 2017 Ute Schiehlen. All rights reserved. +//The above copyright notice and this permission notice shall be included in +//all copies or substantial portions of the Software. // +//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +//THE SOFTWARE. import Foundation From 37d7300627bda5538381127db68571bf7b38f57e Mon Sep 17 00:00:00 2001 From: Ute Schiehlen Date: Tue, 21 Mar 2017 11:51:08 +0100 Subject: [PATCH 0864/1679] Incorporated major swiftlint warnings --- .../Sources/RedBlackTree.swift | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/Red-Black Tree/RedBlackTree.playground/Sources/RedBlackTree.swift b/Red-Black Tree/RedBlackTree.playground/Sources/RedBlackTree.swift index a588ea6bc..6f3b16b86 100644 --- a/Red-Black Tree/RedBlackTree.playground/Sources/RedBlackTree.swift +++ b/Red-Black Tree/RedBlackTree.playground/Sources/RedBlackTree.swift @@ -25,7 +25,7 @@ private enum RBTreeColor { case black } -private enum rotationDirection { +private enum RotationDirection { case left case right } @@ -114,7 +114,7 @@ public class RedBlackTree { // MARK: - Equatable protocol extension RBTreeNode { - static public func ==(lhs: RBTreeNode, rhs: RBTreeNode) -> Bool { + static public func == (lhs: RBTreeNode, rhs: RBTreeNode) -> Bool { return lhs.key == rhs.key } } @@ -309,8 +309,8 @@ extension RedBlackTree { * - case 2b -> red-black tree */ private func insertFixup(node z: RBNode) { - if(!z.isNullLeaf) { - guard let parentZ = z.parent else{ + if !z.isNullLeaf { + guard let parentZ = z.parent else { return } // If both |z| and his parent are red -> violation of red-black property -> need to fix it @@ -539,7 +539,6 @@ extension RedBlackTree { rotate(node: x, direction: .left) } - /* * Right rotation around node y * Assumes that y.leftChild x is not a nullLeaf, rotates around the link from y to x, @@ -561,7 +560,7 @@ extension RedBlackTree { * Is a local operation preserving the binary-search-tree property that only exchanges pointers. * Runntime: O(1) */ - private func rotate(node x: RBNode, direction: rotationDirection) { + private func rotate(node x: RBNode, direction: RotationDirection) { var nodeY: RBNode? = RBNode() // Set |nodeY| and turn |nodeY|'s left/right subtree into |x|'s right/left subtree @@ -616,7 +615,6 @@ extension RedBlackTree { // Property 1: Every node is either red or black -> fullfilled through setting node.color of type // RBTreeColor - // Property 2: The root is black private func property2() -> Bool { if root.color == .red { @@ -746,7 +744,7 @@ extension RedBlackTree: CustomStringConvertible { public var description: String { if root.isNullLeaf { return "[]" - } else{ + } else { return root.description } } From 306ef65bd3ef8b652b1120bc8a5b6770583c3e35 Mon Sep 17 00:00:00 2001 From: kyungkoo Date: Fri, 24 Mar 2017 17:29:41 +0900 Subject: [PATCH 0865/1679] fixed broken link --- README.markdown | 100 ++++++++++++++++++++++++------------------------ 1 file changed, 50 insertions(+), 50 deletions(-) diff --git a/README.markdown b/README.markdown index dfe451478..fc034f71b 100644 --- a/README.markdown +++ b/README.markdown @@ -34,31 +34,31 @@ If you're new to algorithms and data structures, here are a few good ones to sta - [Stack](Stack/) - [Queue](Queue/) -- [Insertion Sort](Insertion Sort/) -- [Binary Search](Binary Search/) and [Binary Search Tree](Binary Search Tree/) -- [Merge Sort](Merge Sort/) +- [Insertion Sort](Insertion%20Sort/) +- [Binary Search](Binary%20Search/) and [Binary Search Tree](Binary%20Search%20Tree/) +- [Merge Sort](Merge%20Sort/) - [Boyer-Moore string search](Boyer-Moore/) ## The algorithms ### Searching -- [Linear Search](Linear Search/). Find an element in an array. -- [Binary Search](Binary Search/). Quickly find elements in a sorted array. -- [Count Occurrences](Count Occurrences/). Count how often a value appears in an array. -- [Select Minimum / Maximum](Select Minimum Maximum). Find the minimum/maximum value in an array. -- [k-th Largest Element](Kth Largest Element/). Find the *k*-th largest element in an array, such as the median. -- [Selection Sampling](Selection Sampling/). Randomly choose a bunch of items from a collection. +- [Linear Search](Linear%20Search/). Find an element in an array. +- [Binary Search](Binary%20Search/). Quickly find elements in a sorted array. +- [Count Occurrences](Count%20Occurrences/). Count how often a value appears in an array. +- [Select Minimum / Maximum](Select%20Minimum%20Maximum). Find the minimum/maximum value in an array. +- [k-th Largest Element](Kth%20Largest%20Element/). Find the *k*-th largest element in an array, such as the median. +- [Selection Sampling](Selection%20Sampling/). Randomly choose a bunch of items from a collection. - [Union-Find](Union-Find/). Keeps track of disjoint sets and lets you quickly merge them. ### String Search -- [Brute-Force String Search](Brute-Force String Search/). A naive method. +- [Brute-Force String Search](Brute-Force%20String%20Search/). A naive method. - [Boyer-Moore](Boyer-Moore/). A fast method to search for substrings. It skips ahead based on a look-up table, to avoid looking at every character in the text. - Knuth-Morris-Pratt - [Rabin-Karp](Rabin-Karp/) Faster search by using hashing. -- [Longest Common Subsequence](Longest Common Subsequence/). Find the longest sequence of characters that appear in the same order in both strings. +- [Longest Common Subsequence](Longest%20Common%20Subsequence/). Find the longest sequence of characters that appear in the same order in both strings. - [Z-Algorithm](Z-Algorithm/). Finds all instances of a pattern in a String, and returns the indexes of where the pattern starts within the String. ### Sorting @@ -67,51 +67,51 @@ It's fun to see how sorting algorithms work, but in practice you'll almost never Basic sorts: -- [Insertion Sort](Insertion Sort/) -- [Selection Sort](Selection Sort/) -- [Shell Sort](Shell Sort/) +- [Insertion Sort](Insertion%20Sort/) +- [Selection Sort](Selection%20Sort/) +- [Shell Sort](Shell%20Sort/) Fast sorts: - [Quicksort](Quicksort/) -- [Merge Sort](Merge Sort/) -- [Heap Sort](Heap Sort/) +- [Merge Sort](Merge%20Sort/) +- [Heap Sort](Heap%20Sort/) Special-purpose sorts: -- [Counting Sort](Counting Sort/) -- [Radix Sort](Radix Sort/) -- [Topological Sort](Topological Sort/) +- [Counting Sort](Counting%20Sort/) +- [Radix Sort](Radix%20Sort/) +- [Topological Sort](Topological%20Sort/) Bad sorting algorithms (don't use these!): -- [Bubble Sort](Bubble Sort/) -- [Slow Sort](Slow Sort/) +- [Bubble Sort](Bubble%20Sort/) +- [Slow Sort](Slow%20Sort/) ### Compression -- [Run-Length Encoding (RLE)](Run-Length Encoding/). Store repeated values as a single byte and a count. -- [Huffman Coding](Huffman Coding/). Store more common elements using a smaller number of bits. +- [Run-Length Encoding (RLE)](Run-Length%20Encoding/). Store repeated values as a single byte and a count. +- [Huffman Coding](Huffman%20Coding/). Store more common elements using a smaller number of bits. ### Miscellaneous - [Shuffle](Shuffle/). Randomly rearranges the contents of an array. -- [Comb Sort](Comb Sort/). An improve upon the Bubble Sort algorithm. +- [Comb Sort](Comb%20Sort/). An improve upon the Bubble Sort algorithm. ### Mathematics - [Greatest Common Divisor (GCD)](GCD/). Special bonus: the least common multiple. - [Permutations and Combinations](Combinatorics/). Get your combinatorics on! -- [Shunting Yard Algorithm](Shunting Yard/). Convert infix expressions to postfix. +- [Shunting Yard Algorithm](Shunting%20Yard/). Convert infix expressions to postfix. - Statistics -- [Karatsuba Multiplication](Karatsuba Multiplication/). Another take on elementary multiplication. +- [Karatsuba Multiplication](Karatsuba%20Multiplication/). Another take on elementary multiplication. - [Haversine Distance](HaversineDistance/). Calculating the distance between 2 points from a sphere. ### Machine learning - [k-Means Clustering](K-Means/). Unsupervised classifier that partitions data into *k* clusters. - k-Nearest Neighbors -- [Linear Regression](Linear Regression/) +- [Linear Regression](Linear%20Regression/) - Logistic Regression - Neural Networks - PageRank @@ -129,33 +129,33 @@ Most of the time using just the built-in `Array`, `Dictionary`, and `Set` types ### Variations on arrays - [Array2D](Array2D/). A two-dimensional array with fixed dimensions. Useful for board games. -- [Bit Set](Bit Set/). A fixed-size sequence of *n* bits. -- [Fixed Size Array](Fixed Size Array/). When you know beforehand how large your data will be, it might be more efficient to use an old-fashioned array with a fixed size. -- [Ordered Array](Ordered Array/). An array that is always sorted. -- [Rootish Array Stack](Rootish Array Stack/). A space and time efficient variation on Swift arrays. +- [Bit Set](Bit%20Set/). A fixed-size sequence of *n* bits. +- [Fixed Size Array](Fixed%20Size%20Array/). When you know beforehand how large your data will be, it might be more efficient to use an old-fashioned array with a fixed size. +- [Ordered Array](Ordered%20Array/). An array that is always sorted. +- [Rootish Array Stack](Rootish%20Array%20Stack/). A space and time efficient variation on Swift arrays. ### Queues - [Stack](Stack/). Last-in, first-out! - [Queue](Queue/). First-in, first-out! - [Deque](Deque/). A double-ended queue. -- [Priority Queue](Priority Queue). A queue where the most important element is always at the front. -- [Ring Buffer](Ring Buffer/). Also known as a circular buffer. An array of a certain size that conceptually wraps around back to the beginning. +- [Priority Queue](Priority%20Queue). A queue where the most important element is always at the front. +- [Ring Buffer](Ring%20Buffer/). Also known as a circular buffer. An array of a certain size that conceptually wraps around back to the beginning. ### Lists -- [Linked List](Linked List/). A sequence of data items connected through links. Covers both singly and doubly linked lists. +- [Linked List](Linked%20List/). A sequence of data items connected through links. Covers both singly and doubly linked lists. - [Skip-List](Skip-List/). Skip List is a probablistic data-structure with same logarithmic time bound and efficiency as AVL/ or Red-Black tree and provides a clever compromise to efficiently support search and update operations. ### Trees - [Tree](Tree/). A general-purpose tree structure. -- [Binary Tree](Binary Tree/). A tree where each node has at most two children. -- [Binary Search Tree (BST)](Binary Search Tree/). A binary tree that orders its nodes in a way that allows for fast queries. +- [Binary Tree](Binary%20Tree/). A tree where each node has at most two children. +- [Binary Search Tree (BST)](Binary%20Search%20Tree/). A binary tree that orders its nodes in a way that allows for fast queries. - Red-Black Tree - Splay Tree - Threaded Binary Tree -- [Segment Tree](Segment Tree/). Can quickly compute a function over a portion of an array. +- [Segment Tree](Segment%20Tree/). Can quickly compute a function over a portion of an array. - kd-Tree - [Heap](Heap/). A binary tree stored in an array, so it doesn't use pointers. Makes a great priority queue. - Fibonacci Heap @@ -164,33 +164,33 @@ Most of the time using just the built-in `Array`, `Dictionary`, and `Set` types ### Hashing -- [Hash Table](Hash Table/). Allows you to store and retrieve objects by a key. This is how the dictionary type is usually implemented. +- [Hash Table](Hash%20Table/). Allows you to store and retrieve objects by a key. This is how the dictionary type is usually implemented. - Hash Functions ### Sets -- [Bloom Filter](Bloom Filter/). A constant-memory data structure that probabilistically tests whether an element is in a set. -- [Hash Set](Hash Set/). A set implemented using a hash table. +- [Bloom Filter](Bloom%20Filter/). A constant-memory data structure that probabilistically tests whether an element is in a set. +- [Hash Set](Hash%20Set/). A set implemented using a hash table. - Multiset -- [Ordered Set](Ordered Set/). A set where the order of items matters. +- [Ordered Set](Ordered%20Set/). A set where the order of items matters. ### Graphs - [Graph](Graph/) -- [Breadth-First Search (BFS)](Breadth-First Search/) -- [Depth-First Search (DFS)](Depth-First Search/) -- [Shortest Path](Shortest Path %28Unweighted%29/) on an unweighted tree -- [Single-Source Shortest Paths](Single-Source Shortest Paths (Weighted)/) -- [Minimum Spanning Tree](Minimum Spanning Tree %28Unweighted%29/) on an unweighted tree -- [All-Pairs Shortest Paths](All-Pairs Shortest Paths/) +- [Breadth-First Search (BFS)](Breadth-First%20Search/) +- [Depth-First Search (DFS)](Depth-First%20Search/) +- [Shortest Path](Shortest%20Path%20%28Unweighted%29/) on an unweighted tree +- [Single-Source Shortest Paths](Single-Source%20Shortest%20Paths%20(Weighted)/) +- [Minimum Spanning Tree](Minimum%20Spanning%20Tree%20%28Unweighted%29/) on an unweighted tree +- [All-Pairs Shortest Paths](All-Pairs%20Shortest%20Paths/) ## Puzzles A lot of software developer interview questions consist of algorithmic puzzles. Here is a small selection of fun ones. For more puzzles (with answers), see [here](http://elementsofprogramminginterviews.com/) and [here](http://www.crackingthecodinginterview.com). -- [Two-Sum Problem](Two-Sum Problem/) -- [Fizz Buzz](Fizz Buzz/) -- [Monty Hall Problem](Monty Hall Problem/) +- [Two-Sum Problem](Two-Sum%20Problem/) +- [Fizz Buzz](Fizz%20Buzz/) +- [Monty Hall Problem](Monty%20Hall%20Problem/) - [Finding Palindromes](Palindromes/) - [Dining Philosophers](DiningPhilosophers/) From 943ad7e48fe966f7679c4addfafa7baa5fb81fb2 Mon Sep 17 00:00:00 2001 From: kyungkoo Date: Fri, 24 Mar 2017 18:25:24 +0900 Subject: [PATCH 0866/1679] fixed important links section link --- README.markdown | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.markdown b/README.markdown index fc034f71b..023f151fb 100644 --- a/README.markdown +++ b/README.markdown @@ -16,17 +16,17 @@ This is a work in progress. More algorithms will be added soon. :-) ## Important links -[What are algorithms and data structures?](What are Algorithms.markdown) Pancakes! +[What are algorithms and data structures?](What%20are%20Algorithms.markdown) Pancakes! -[Why learn algorithms?](Why Algorithms.markdown) Worried this isn't your cup of tea? Then read this. +[Why learn algorithms?](Why%20Algorithms.markdown) Worried this isn't your cup of tea? Then read this. -[Big-O notation](Big-O Notation.markdown). We often say things like, "This algorithm is **O(n)**." If you don't know what that means, read this first. +[Big-O notation](Big-O%20Notation.markdown). We often say things like, "This algorithm is **O(n)**." If you don't know what that means, read this first. -[Algorithm design techniques](Algorithm Design.markdown). How do you create your own algorithms? +[Algorithm design techniques](Algorithm%20Design.markdown). How do you create your own algorithms? -[How to contribute](How to Contribute.markdown). Report an issue to leave feedback, or submit a pull request. +[How to contribute](How%20to%20Contribute.markdown). Report an issue to leave feedback, or submit a pull request. -[Under construction](Under Construction.markdown). Algorithms that are under construction. +[Under construction](Under%20Construction.markdown). Algorithms that are under construction. ## Where to start? From a54e722b035ffc5eeba63fcd5b1648e56f732ec0 Mon Sep 17 00:00:00 2001 From: Jake Romer Date: Fri, 24 Mar 2017 07:58:19 -0700 Subject: [PATCH 0867/1679] Fix links to related articles Fixes links to Linked List, Ring Buffer, and Priority Queue directories. --- Queue/README.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Queue/README.markdown b/Queue/README.markdown index f8259c31c..9efce66b9 100644 --- a/Queue/README.markdown +++ b/Queue/README.markdown @@ -255,8 +255,8 @@ The `nil` objects at the front have been removed and the array is no longer wast ## See also -There are many other ways to create a queue. Alternative implementations use a [linked list](../Linked List/), a [circular buffer](../Ring Buffer/), or a [heap](../Heap/). +There are many other ways to create a queue. Alternative implementations use a [linked list](../Linked%20List/), a [circular buffer](../Ring%20Buffer/), or a [heap](../Heap/). -Variations on this theme are [deque](../Deque/), a double-ended queue where you can enqueue and dequeue at both ends, and [priority queue](../Priority Queue/), a sorted queue where the "most important" item is always at the front. +Variations on this theme are [deque](../Deque/), a double-ended queue where you can enqueue and dequeue at both ends, and [priority queue](../Priority%20Queue/), a sorted queue where the "most important" item is always at the front. *Written for Swift Algorithm Club by Matthijs Hollemans* From 3d033740b0d3b727d488a14121da68f822b578a2 Mon Sep 17 00:00:00 2001 From: Jake Romer Date: Sat, 25 Mar 2017 07:47:49 -0700 Subject: [PATCH 0868/1679] URL encode links in Markdown files There are a ton of broken markdown links in the READMEs throughout this repo because the files and directories they refer to have spaces in their names but these aren't HTML encoded in their links. This commit just replaces spaces with %20 to fix these. --- AVL Tree/README.markdown | 8 ++++---- Big-O Notation.markdown | 2 +- Binary Search Tree/README.markdown | 10 +++++----- Binary Search/README.markdown | 2 +- Binary Tree/README.markdown | 2 +- Bloom Filter/README.markdown | 2 +- Bounded Priority Queue/README.markdown | 2 +- Boyer-Moore/README.markdown | 2 +- Breadth-First Search/README.markdown | 4 ++-- Count Occurrences/README.markdown | 4 ++-- Hash Set/README.markdown | 2 +- How to Contribute.markdown | 2 +- Ordered Array/README.markdown | 2 +- Ordered Set/README.markdown | 2 +- Selection Sort/README.markdown | 6 +++--- Shell Sort/README.markdown | 2 +- Shortest Path (Unweighted)/README.markdown | 8 ++++---- Threaded Binary Tree/README.markdown | 10 +++++----- Topological Sort/README.markdown | 2 +- Tree/README.markdown | 4 ++-- Under Construction.markdown | 20 ++++++++++---------- 21 files changed, 49 insertions(+), 49 deletions(-) diff --git a/AVL Tree/README.markdown b/AVL Tree/README.markdown index 355204587..a9218203a 100644 --- a/AVL Tree/README.markdown +++ b/AVL Tree/README.markdown @@ -1,6 +1,6 @@ # AVL Tree -An AVL tree is a self-balancing form of a [binary search tree](../Binary Search Tree/), in which the height of subtrees differ at most by only 1. +An AVL tree is a self-balancing form of a [binary search tree](../Binary%20Search%20Tree/), in which the height of subtrees differ at most by only 1. A binary tree is *balanced* when its left and right subtrees contain roughly the same number of nodes. That is what makes searching the tree really fast. But if a binary search tree is unbalanced, searching can become really slow. @@ -8,7 +8,7 @@ This is an example of an unbalanced tree: ![Unbalanced tree](Images/Unbalanced.png) -All the children are in the left branch and none are in the right. This is essentially the same as a [linked list](../Linked List/). As a result, searching takes **O(n)** time instead of the much faster **O(log n)** that you'd expect from a binary search tree. +All the children are in the left branch and none are in the right. This is essentially the same as a [linked list](../Linked%20List/). As a result, searching takes **O(n)** time instead of the much faster **O(log n)** that you'd expect from a binary search tree. A balanced version of that tree would look like this: @@ -78,7 +78,7 @@ Insertion never needs more than 2 rotations. Removal might require up to __log(n Most of the code in [AVLTree.swift](AVLTree.swift) is just regular [binary search tree](../Binary Search Tree/) stuff. You'll find this in any implementation of a binary search tree. For example, searching the tree is exactly the same. The only things that an AVL tree does slightly differently are inserting and deleting the nodes. -> **Note:** If you're a bit fuzzy on the regular operations of a binary search tree, I suggest you [catch up on those first](../Binary Search Tree/). It will make the rest of the AVL tree easier to understand. +> **Note:** If you're a bit fuzzy on the regular operations of a binary search tree, I suggest you [catch up on those first](../Binary%20Search%20Tree/). It will make the rest of the AVL tree easier to understand. The interesting bits are in the `balance()` method which is called after inserting or deleting a node. @@ -86,6 +86,6 @@ The interesting bits are in the `balance()` method which is called after inserti [AVL tree on Wikipedia](https://en.wikipedia.org/wiki/AVL_tree) -AVL tree was the first self-balancing binary tree. These days, the [red-black tree](../Red-Black Tree/) seems to be more popular. +AVL tree was the first self-balancing binary tree. These days, the [red-black tree](../Red-Black%20Tree/) seems to be more popular. *Written for Swift Algorithm Club by Mike Taghavi and Matthijs Hollemans* diff --git a/Big-O Notation.markdown b/Big-O Notation.markdown index 8cb988168..09fbb04aa 100644 --- a/Big-O Notation.markdown +++ b/Big-O Notation.markdown @@ -19,6 +19,6 @@ Big-O | Name | Description Often you don't need math to figure out what the Big-O of an algorithm is but you can simply use your intuition. If your code uses a single loop that looks at all **n** elements of your input, the algorithm is **O(n)**. If the code has two nested loops, it is **O(n^2)**. Three nested loops gives **O(n^3)**, and so on. -Note that Big-O notation is an estimate and is only really useful for large values of **n**. For example, the worst-case running time for the [insertion sort](Insertion Sort/) algorithm is **O(n^2)**. In theory that is worse than the running time for [merge sort](Merge Sort/), which is **O(n log n)**. But for small amounts of data, insertion sort is actually faster, especially if the array is partially sorted already! +Note that Big-O notation is an estimate and is only really useful for large values of **n**. For example, the worst-case running time for the [insertion sort](Insertion%20Sort/) algorithm is **O(n^2)**. In theory that is worse than the running time for [merge sort](Merge Sort/), which is **O(n log n)**. But for small amounts of data, insertion sort is actually faster, especially if the array is partially sorted already! If you find this confusing, don't let this Big-O stuff bother you too much. It's mostly useful when comparing two algorithms to figure out which one is better. But in the end you still want to test in practice which one really is the best. And if the amount of data is relatively small, then even a slow algorithm will be fast enough for practical use. diff --git a/Binary Search Tree/README.markdown b/Binary Search Tree/README.markdown index bd2a00c9e..a3a84c03d 100644 --- a/Binary Search Tree/README.markdown +++ b/Binary Search Tree/README.markdown @@ -1,6 +1,6 @@ # Binary Search Tree (BST) -A binary search tree is a special kind of [binary tree](../Binary Tree/) (a tree in which each node has at most two children) that performs insertions and deletions such that the tree is always sorted. +A binary search tree is a special kind of [binary tree](../Binary%20Tree/) (a tree in which each node has at most two children) that performs insertions and deletions such that the tree is always sorted. If you don't know what a tree is or what it is for, then [read this first](../Tree/). @@ -49,7 +49,7 @@ If we were looking for the value `5` in the example, it would go as follows: ![Searching the tree](Images/Searching.png) -Thanks to the structure of the tree, searching is really fast. It runs in **O(h)** time. If you have a well-balanced tree with a million nodes, it only takes about 20 steps to find anything in this tree. (The idea is very similar to [binary search](../Binary Search) in an array.) +Thanks to the structure of the tree, searching is really fast. It runs in **O(h)** time. If you have a well-balanced tree with a million nodes, it only takes about 20 steps to find anything in this tree. (The idea is very similar to [binary search](../Binary%20Search) in an array.) ## Traversing the tree @@ -535,7 +535,7 @@ The code for `successor()` works the exact same way but mirrored: Both these methods run in **O(h)** time. -> **Note:** There is a cool variation called a ["threaded" binary tree](../Threaded Binary Tree) where "unused" left and right pointers are repurposed to make direct links between predecessor and successor nodes. Very clever! +> **Note:** There is a cool variation called a ["threaded" binary tree](../Threaded%20Binary%20Tree) where "unused" left and right pointers are repurposed to make direct links between predecessor and successor nodes. Very clever! ### Is the search tree valid? @@ -713,11 +713,11 @@ The root node is in the middle; a dot means there is no child at that position. A binary search tree is *balanced* when its left and right subtrees contain roughly the same number of nodes. In that case, the height of the tree is *log(n)*, where *n* is the number of nodes. That's the ideal situation. -However, if one branch is significantly longer than the other, searching becomes very slow. We end up checking way more values than we'd ideally have to. In the worst case, the height of the tree can become *n*. Such a tree acts more like a [linked list](../Linked List/) than a binary search tree, with performance degrading to **O(n)**. Not good! +However, if one branch is significantly longer than the other, searching becomes very slow. We end up checking way more values than we'd ideally have to. In the worst case, the height of the tree can become *n*. Such a tree acts more like a [linked list](../Linked%20List/) than a binary search tree, with performance degrading to **O(n)**. Not good! One way to make the binary search tree balanced is to insert the nodes in a totally random order. On average that should balance out the tree quite nicely. But it doesn't guarantee success, nor is it always practical. -The other solution is to use a *self-balancing* binary tree. This type of data structure adjusts the tree to keep it balanced after you insert or delete nodes. See [AVL tree](../AVL Tree) and [red-black tree](../Red-Black Tree) for examples. +The other solution is to use a *self-balancing* binary tree. This type of data structure adjusts the tree to keep it balanced after you insert or delete nodes. See [AVL tree](../AVL%20Tree) and [red-black tree](../Red-Black%20Tree) for examples. ## See also diff --git a/Binary Search/README.markdown b/Binary Search/README.markdown index c65d0b5fd..09b141e04 100644 --- a/Binary Search/README.markdown +++ b/Binary Search/README.markdown @@ -12,7 +12,7 @@ let numbers = [11, 59, 3, 2, 53, 17, 31, 7, 19, 67, 47, 13, 37, 61, 29, 43, 5, 4 numbers.indexOf(43) // returns 15 ``` -The built-in `indexOf()` function performs a [linear search](../Linear Search/). In code that looks something like this: +The built-in `indexOf()` function performs a [linear search](../Linear%20Search/). In code that looks something like this: ```swift func linearSearch(_ a: [T], _ key: T) -> Int? { diff --git a/Binary Tree/README.markdown b/Binary Tree/README.markdown index 896116dda..8ce398804 100644 --- a/Binary Tree/README.markdown +++ b/Binary Tree/README.markdown @@ -8,7 +8,7 @@ The child nodes are usually called the *left* child and the *right* child. If a Often nodes will have a link back to their parent but this is not strictly necessary. -Binary trees are often used as [binary search trees](../Binary Search Tree/). In that case, the nodes must be in a specific order (smaller values on the left, larger values on the right). But this is not a requirement for all binary trees. +Binary trees are often used as [binary search trees](../Binary%20Search%20Tree/). In that case, the nodes must be in a specific order (smaller values on the left, larger values on the right). But this is not a requirement for all binary trees. For example, here is a binary tree that represents a sequence of arithmetical operations, `(5 * (a - 10)) + (-4 * (3 / b))`: diff --git a/Bloom Filter/README.markdown b/Bloom Filter/README.markdown index a85d71be4..3fff0a379 100644 --- a/Bloom Filter/README.markdown +++ b/Bloom Filter/README.markdown @@ -18,7 +18,7 @@ An advantage of the Bloom Filter over a hash table is that the former maintains ## Inserting objects into the set -A Bloom Filter is essentially a fixed-length [bit vector](../Bit Set/), an array of bits. When we insert objects, we set some of these bits to `1`, and when we query for objects we check if certain bits are `0` or `1`. Both operations use hash functions. +A Bloom Filter is essentially a fixed-length [bit vector](../Bit%20Set/), an array of bits. When we insert objects, we set some of these bits to `1`, and when we query for objects we check if certain bits are `0` or `1`. Both operations use hash functions. To insert an element in the filter, the element is hashed with several different hash functions. Each hash function returns a value that we map to an index in the array. We then set the bits at these indices to `1` or true. diff --git a/Bounded Priority Queue/README.markdown b/Bounded Priority Queue/README.markdown index 8d47adefb..4e4c89272 100644 --- a/Bounded Priority Queue/README.markdown +++ b/Bounded Priority Queue/README.markdown @@ -1,6 +1,6 @@ # Bounded Priority queue -A bounded priority queue is similar to a regular [priority queue](../Priority Queue/), except that there is a fixed upper bound on the number of elements that can be stored. When a new element is added to the queue while the queue is at capacity, the element with the highest priority value is ejected from the queue. +A bounded priority queue is similar to a regular [priority queue](../Priority%20Queue/), except that there is a fixed upper bound on the number of elements that can be stored. When a new element is added to the queue while the queue is at capacity, the element with the highest priority value is ejected from the queue. ## Example diff --git a/Boyer-Moore/README.markdown b/Boyer-Moore/README.markdown index e821b812e..5b3841eca 100644 --- a/Boyer-Moore/README.markdown +++ b/Boyer-Moore/README.markdown @@ -24,7 +24,7 @@ animals.indexOf(pattern: "🐮") > **Note:** The index of the cow is 6, not 3 as you might expect, because the string uses more storage per character for emoji. The actual value of the `String.Index` is not so important, just that it points at the right character in the string. -The [brute-force approach](../Brute-Force String Search/) works OK, but it's not very efficient, especially on large chunks of text. As it turns out, you don't need to look at _every_ character from the source string -- you can often skip ahead multiple characters. +The [brute-force approach](../Brute-Force%20String%20Search/) works OK, but it's not very efficient, especially on large chunks of text. As it turns out, you don't need to look at _every_ character from the source string -- you can often skip ahead multiple characters. The skip-ahead algorithm is called [Boyer-Moore](https://en.wikipedia.org/wiki/Boyer–Moore_string_search_algorithm) and it has been around for a long time. It is considered the benchmark for all string search algorithms. diff --git a/Breadth-First Search/README.markdown b/Breadth-First Search/README.markdown index 084f4611a..2ef92fd73 100644 --- a/Breadth-First Search/README.markdown +++ b/Breadth-First Search/README.markdown @@ -148,7 +148,7 @@ This will output: `["a", "b", "c", "d", "e", "f", "g", "h"]` Breadth-first search can be used to solve many problems. A small selection: -* Computing the [shortest path](../Shortest Path/) between a source node and each of the other nodes (only for unweighted graphs). -* Calculating the [minimum spanning tree](../Minimum Spanning Tree (Unweighted)/) on an unweighted graph. +* Computing the [shortest path](../Shortest%20Path/) between a source node and each of the other nodes (only for unweighted graphs). +* Calculating the [minimum spanning tree](../Minimum%20Spanning%20Tree%20(Unweighted)/) on an unweighted graph. *Written by [Chris Pilcher](https://github.com/chris-pilcher) and Matthijs Hollemans* diff --git a/Count Occurrences/README.markdown b/Count Occurrences/README.markdown index 90a9ec2f3..4c65c4219 100644 --- a/Count Occurrences/README.markdown +++ b/Count Occurrences/README.markdown @@ -2,9 +2,9 @@ Goal: Count how often a certain value appears in an array. -The obvious way to do this is with a [linear search](../Linear Search/) from the beginning of the array until the end, keeping count of how often you come across the value. That is an **O(n)** algorithm. +The obvious way to do this is with a [linear search](../Linear%20Search/) from the beginning of the array until the end, keeping count of how often you come across the value. That is an **O(n)** algorithm. -However, if the array is sorted you can do it much faster, in **O(log n)** time, by using a modification of [binary search](../Binary Search/). +However, if the array is sorted you can do it much faster, in **O(log n)** time, by using a modification of [binary search](../Binary%20Search/). Let's say we have the following array: diff --git a/Hash Set/README.markdown b/Hash Set/README.markdown index 368920a1c..fb829c313 100644 --- a/Hash Set/README.markdown +++ b/Hash Set/README.markdown @@ -196,7 +196,7 @@ difference2.allElements() // [5, 6] If you look at the [documentation](http://swiftdoc.org/v2.1/type/Set/) for Swift's own `Set`, you'll notice it has tons more functionality. An obvious extension would be to make `HashSet` conform to `SequenceType` so that you can iterate it with a `for`...`in` loop. -Another thing you could do is replace the `Dictionary` with an actual [hash table](../Hash Table), but one that just stores the keys and doesn't associate them with anything. So you wouldn't need the `Bool` values anymore. +Another thing you could do is replace the `Dictionary` with an actual [hash table](../Hash%20Table), but one that just stores the keys and doesn't associate them with anything. So you wouldn't need the `Bool` values anymore. If you often need to look up whether an element belongs to a set and perform unions, then the [union-find](../Union-Find/) data structure may be more suitable. It uses a tree structure instead of a dictionary to make the find and union operations very efficient. diff --git a/How to Contribute.markdown b/How to Contribute.markdown index 258357e8b..1235f07ff 100644 --- a/How to Contribute.markdown +++ b/How to Contribute.markdown @@ -6,7 +6,7 @@ Want to help out with the Swift Algorithm Club? Great! Take a look at the [list](README.markdown). Any algorithms or data structures that don't have a link yet are up for grabs. -Algorithms in the [Under construction](Under Construction.markdown) area are being worked on. Suggestions and feedback is welcome! +Algorithms in the [Under construction](Under%20Construction.markdown) area are being worked on. Suggestions and feedback is welcome! New algorithms and data structures are always welcome (even if they aren't on the list). diff --git a/Ordered Array/README.markdown b/Ordered Array/README.markdown index ca088c325..974a42cae 100644 --- a/Ordered Array/README.markdown +++ b/Ordered Array/README.markdown @@ -83,7 +83,7 @@ a // [-2, -1, 1, 3, 4, 5, 7, 9, 10] The array's contents will always be sorted from low to high, now matter what. -Unfortunately, the current `findInsertionPoint()` function is a bit slow. In the worst case, it needs to scan through the entire array. We can speed this up by using a [binary search](../Binary Search) to find the insertion point. +Unfortunately, the current `findInsertionPoint()` function is a bit slow. In the worst case, it needs to scan through the entire array. We can speed this up by using a [binary search](../Binary%20Search) to find the insertion point. Here is the new version: diff --git a/Ordered Set/README.markdown b/Ordered Set/README.markdown index 0525a31ed..1c0d5a8ac 100644 --- a/Ordered Set/README.markdown +++ b/Ordered Set/README.markdown @@ -115,7 +115,7 @@ The next function is `indexOf()`, which takes in an object of type `T` and retur } ``` -> **Note:** If you are not familiar with the concept of binary search, we have an [article that explains all about it](../Binary Search). +> **Note:** If you are not familiar with the concept of binary search, we have an [article that explains all about it](../Binary%20Search). However, there is an important issue to deal with here. Recall that two objects can be unequal yet still have the same "value" for the purposes of comparing them. Since a set can contain multiple items with the same value, it is important to check that the binary search has landed on the correct item. diff --git a/Selection Sort/README.markdown b/Selection Sort/README.markdown index c583b47ea..e95749d14 100644 --- a/Selection Sort/README.markdown +++ b/Selection Sort/README.markdown @@ -6,7 +6,7 @@ You are given an array of numbers and need to put them in the right order. The s [ ...sorted numbers... | ...unsorted numbers... ] -This is similar to [insertion sort](../Insertion Sort/), but the difference is in how new numbers are added to the sorted portion. +This is similar to [insertion sort](../Insertion%20Sort/), but the difference is in how new numbers are added to the sorted portion. It works as follows: @@ -108,9 +108,9 @@ The source file [SelectionSort.swift](SelectionSort.swift) has a version of this ## Performance -Selection sort is easy to understand but it performs quite badly, **O(n^2)**. It's worse than [insertion sort](../Insertion Sort/) but better than [bubble sort](../Bubble Sort/). The killer is finding the lowest element in the rest of the array. This takes up a lot of time, especially since the inner loop will be performed over and over. +Selection sort is easy to understand but it performs quite badly, **O(n^2)**. It's worse than [insertion sort](../Insertion%20Sort/) but better than [bubble sort](../Bubble Sort/). The killer is finding the lowest element in the rest of the array. This takes up a lot of time, especially since the inner loop will be performed over and over. -[Heap sort](../Heap Sort/) uses the same principle as selection sort but has a really fast method for finding the minimum value in the rest of the array. Its performance is **O(n log n)**. +[Heap sort](../Heap%20Sort/) uses the same principle as selection sort but has a really fast method for finding the minimum value in the rest of the array. Its performance is **O(n log n)**. ## See also diff --git a/Shell Sort/README.markdown b/Shell Sort/README.markdown index 9c4bdf076..c21c29685 100644 --- a/Shell Sort/README.markdown +++ b/Shell Sort/README.markdown @@ -39,7 +39,7 @@ As you can see, each sublist contains only every 4th item from the original arra We now call `insertionSort()` once on each sublist. -This particular version of [insertion sort](../Insertion Sort/) sorts from the back to the front. Each item in the sublist is compared against the others. If they're in the wrong order, the value is swapped and travels all the way down until we reach the start of the sublist. +This particular version of [insertion sort](../Insertion%20Sort/) sorts from the back to the front. Each item in the sublist is compared against the others. If they're in the wrong order, the value is swapped and travels all the way down until we reach the start of the sublist. So for sublist 0, we swap `4` with `72`, then swap `4` with `64`. After sorting, this sublist looks like: diff --git a/Shortest Path (Unweighted)/README.markdown b/Shortest Path (Unweighted)/README.markdown index a16519260..4c3c34d9c 100644 --- a/Shortest Path (Unweighted)/README.markdown +++ b/Shortest Path (Unweighted)/README.markdown @@ -12,11 +12,11 @@ If the [graph is unweighed](../Graph/), then finding the shortest path is easy: ## Unweighted graph: breadth-first search -[Breadth-first search](../Breadth-First Search/) is a method for traversing a tree or graph data structure. It starts at a source node and explores the immediate neighbor nodes first, before moving to the next level neighbors. As a convenient side effect, it automatically computes the shortest path between a source node and each of the other nodes in the tree or graph. +[Breadth-first search](../Breadth-First%20Search/) is a method for traversing a tree or graph data structure. It starts at a source node and explores the immediate neighbor nodes first, before moving to the next level neighbors. As a convenient side effect, it automatically computes the shortest path between a source node and each of the other nodes in the tree or graph. The result of the breadth-first search can be represented with a tree: -![The BFS tree](../Breadth-First Search/Images/TraversalTree.png) +![The BFS tree](../Breadth-First%20Search/Images/TraversalTree.png) The root of the tree is the node you started the breadth-first search from. To find the distance from node `A` to any other node, we simply count the number of edges in the tree. And so we find that the shortest path between `A` and `F` is 2. The tree not only tells you how long that path is, but also how to actually get from `A` to `F` (or any of the other nodes). @@ -57,7 +57,7 @@ queue.enqueue(element: G) G.distance = C.distance + 1 // result: 2 ``` -This continues until the queue is empty and we've visited all the nodes. Each time we discover a new node, it gets the `distance` of its parent plus 1. As you can see, this is exactly what the [breadth-first search](../Breadth-First Search/) algorithm does, except that we now also keep track of the distance travelled. +This continues until the queue is empty and we've visited all the nodes. Each time we discover a new node, it gets the `distance` of its parent plus 1. As you can see, this is exactly what the [breadth-first search](../Breadth-First%20Search/) algorithm does, except that we now also keep track of the distance travelled. Here's the code: @@ -97,6 +97,6 @@ This will output: Node(label: d, distance: 2), Node(label: e, distance: 2), Node(label: f, distance: 2), Node(label: g, distance: 2), Node(label: h, distance: 3) -> **Note:** This version of `breadthFirstSearchShortestPath()` does not actually produce the tree, it only computes the distances. See [minimum spanning tree](../Minimum Spanning Tree (Unweighted)/) on how you can convert the graph into a tree by removing edges. +> **Note:** This version of `breadthFirstSearchShortestPath()` does not actually produce the tree, it only computes the distances. See [minimum spanning tree](../Minimum%20Spanning%20Tree%20(Unweighted)/) on how you can convert the graph into a tree by removing edges. *Written by [Chris Pilcher](https://github.com/chris-pilcher) and Matthijs Hollemans* diff --git a/Threaded Binary Tree/README.markdown b/Threaded Binary Tree/README.markdown index fd05113d8..8a1c518f1 100644 --- a/Threaded Binary Tree/README.markdown +++ b/Threaded Binary Tree/README.markdown @@ -1,6 +1,6 @@ # Threaded Binary Tree -A threaded binary tree is a special kind of [binary tree](../Binary Tree/) (a +A threaded binary tree is a special kind of [binary tree](../Binary%20Tree/) (a tree in which each node has at most two children) that maintains a few extra variables to allow cheap and fast **in-order traversal** of the tree. We will explore the general structure of threaded binary trees, as well as @@ -17,7 +17,7 @@ The main motivation behind using a threaded binary tree over a simpler and smaller standard binary tree is to increase the speed of an in-order traversal of the tree. An in-order traversal of a binary tree visits the nodes in the order in which they are stored, which matches the underlying ordering of a -[binary search tree](../Binary Search Tree/). This means most threaded binary +[binary search tree](../Binary%20Search%20Tree/). This means most threaded binary trees are also binary search trees. The idea is to visit all the left children of a node first, then visit the node itself, and then visit the right children last. @@ -47,7 +47,7 @@ tree, to **O(n)** to a very unbalanced tree. A threaded binary tree fixes this problem. -> For more information about in-order traversals [see here](../Binary Tree/). +> For more information about in-order traversals [see here](../Binary%20Tree/). ## Predecessors and successors @@ -222,7 +222,7 @@ walking through some boring code, it is best to explain this with an example (although you can read through [the implementation](ThreadedBinaryTree.swift) if you want to know the finer details). Please note that this requires knowledge of binary search trees, so make sure you have -[read this first](../Binary Search Tree/). +[read this first](../Binary%20Search%20Tree/). > Note: we do allow duplicate nodes in this implementation of a threaded binary > tree. We break ties by defaulting insertion to the right. @@ -339,7 +339,7 @@ such as `searching()` for a node in the tree, finding the `depth()` or `height()` of a node, etc. You can check [the implementation](ThreadedBinaryTree.swift) for the full technical details. Many of these methods are inherent to binary search trees as well, so you can -find [further documentation here](../Binary Search Tree/). +find [further documentation here](../Binary%20Search%20Tree/). ## See also diff --git a/Topological Sort/README.markdown b/Topological Sort/README.markdown index 4429a0754..5659dc3fd 100644 --- a/Topological Sort/README.markdown +++ b/Topological Sort/README.markdown @@ -22,7 +22,7 @@ The following is not a valid topological sort for this graph, since **X** and ** Let's consider that you want to learn all the algorithms and data structures from the Swift Algorithm Club. This might seem daunting at first but we can use topological sort to get things organized. -Since you're learning about topological sort, let's take this topic as an example. What else do you need to learn first before you can fully understand topological sort? Well, topological sort uses [depth-first search](../Depth-First Search/) as well as a [stack](../Stack/). But before you can learn about the depth-first search algorithm, you need to know what a [graph](../Graph/) is, and it helps to know what a [tree](../Tree/) is. In turn, graphs and trees use the idea of linking objects together, so you may need to read up on that first. And so on... +Since you're learning about topological sort, let's take this topic as an example. What else do you need to learn first before you can fully understand topological sort? Well, topological sort uses [depth-first search](../Depth-First%20Search/) as well as a [stack](../Stack/). But before you can learn about the depth-first search algorithm, you need to know what a [graph](../Graph/) is, and it helps to know what a [tree](../Tree/) is. In turn, graphs and trees use the idea of linking objects together, so you may need to read up on that first. And so on... If we were to represent these objectives in the form of a graph it would look as follows: diff --git a/Tree/README.markdown b/Tree/README.markdown index 529a68cf1..440d9c9a4 100644 --- a/Tree/README.markdown +++ b/Tree/README.markdown @@ -16,7 +16,7 @@ The pointers in a tree do not form cycles. This is not a tree: ![Not a tree](Images/Cycles.png) -Such a structure is called a [graph](../Graph/). A tree is really a very simple form of a graph. (In a similar vein, a [linked list](../Linked List/) is a simple version of a tree. Think about it!) +Such a structure is called a [graph](../Graph/). A tree is really a very simple form of a graph. (In a similar vein, a [linked list](../Linked%20List/) is a simple version of a tree. Think about it!) This article talks about a general-purpose tree. That's a tree without any kind of restrictions on how many children each node may have, or on the order of the nodes in the tree. @@ -119,7 +119,7 @@ We often use the following definitions when talking about trees: - **Depth of a node.** The number of links between this node and the root node. For example, the depth of `tea` is 2 because it takes two jumps to reach the root. (The root itself has depth 0.) -There are many different ways to construct trees. For example, sometimes you don't need to have a `parent` property at all. Or maybe you only need to give each node a maximum of two children -- such a tree is called a [binary tree](../Binary Tree/). A very common type of tree is the [binary search tree](../Binary Search Tree/) (or BST), a stricter version of a binary tree where the nodes are ordered in a particular way to speed up searches. +There are many different ways to construct trees. For example, sometimes you don't need to have a `parent` property at all. Or maybe you only need to give each node a maximum of two children -- such a tree is called a [binary tree](../Binary%20Tree/). A very common type of tree is the [binary search tree](../Binary%20Search%20Tree/) (or BST), a stricter version of a binary tree where the nodes are ordered in a particular way to speed up searches. The general purpose tree I've shown here is great for describing hierarchical data, but it really depends on your application what kind of extra functionality it needs to have. diff --git a/Under Construction.markdown b/Under Construction.markdown index 0c59d90c1..be53e01b0 100644 --- a/Under Construction.markdown +++ b/Under Construction.markdown @@ -5,27 +5,27 @@ Here you'll find algorithms that are currently under construction. Suggestions a ### Sorting Special-purpose sorts: - - [Radix Sort](Radix Sort/) + - [Radix Sort](Radix%20Sort/) ### Special-purpose sorts: -- [Bucket Sort](Bucket Sort/) +- [Bucket Sort](Bucket%20Sort/) ### Queues -- [Bounded Priority Queue](Bounded Priority Queue). A queue that is bounded to have a limited number of elements. +- [Bounded Priority Queue](Bounded%20Priority%20Queue). A queue that is bounded to have a limited number of elements. ### Trees -- [AVL Tree](AVL Tree/). A binary search tree that balances itself using rotations. -- [Red-Black Tree](Red-Black Tree/) -- [Threaded Binary Tree](Threaded Binary Tree/) -- [Ternary Search Tree](Ternary Search Tree/) +- [AVL Tree](AVL%20Tree/). A binary search tree that balances itself using rotations. +- [Red-Black Tree](Red-Black%20Tree/) +- [Threaded Binary Tree](Threaded%20Binary%20Tree/) +- [Ternary Search Tree](Ternary%20Search%20Tree/) - [Trie](Trie/) -- [Radix Tree](Radix Tree/) +- [Radix Tree](Radix%20Tree/) ### Miscellaneous -- [Minimum Edit Distance](Minimum Edit Distance/). Measure the similarity of two strings by counting the number of operations required to transform one string into the other. +- [Minimum Edit Distance](Minimum%20Edit%20Distance/). Measure the similarity of two strings by counting the number of operations required to transform one string into the other. - [Treap](Treap/) -- [Set Cover (Unweighted)](Set Cover (Unweighted)/) +- [Set Cover (Unweighted)](Set%20Cover%20(Unweighted)/) From bd35ff8f1bb984bf5cf5eeb8375539dfcdd248ad Mon Sep 17 00:00:00 2001 From: Hunter Maximillion Monk Date: Sat, 25 Mar 2017 21:57:12 -0500 Subject: [PATCH 0869/1679] Fix binary search tree link Just need to convert spaces into %20 for relative URLs with spaces to work. --- Binary Tree/README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Binary Tree/README.markdown b/Binary Tree/README.markdown index 896116dda..8ce398804 100644 --- a/Binary Tree/README.markdown +++ b/Binary Tree/README.markdown @@ -8,7 +8,7 @@ The child nodes are usually called the *left* child and the *right* child. If a Often nodes will have a link back to their parent but this is not strictly necessary. -Binary trees are often used as [binary search trees](../Binary Search Tree/). In that case, the nodes must be in a specific order (smaller values on the left, larger values on the right). But this is not a requirement for all binary trees. +Binary trees are often used as [binary search trees](../Binary%20Search%20Tree/). In that case, the nodes must be in a specific order (smaller values on the left, larger values on the right). But this is not a requirement for all binary trees. For example, here is a binary tree that represents a sequence of arithmetical operations, `(5 * (a - 10)) + (-4 * (3 / b))`: From eb68b1d69836d3d2d1bb1cba269466a94f837aea Mon Sep 17 00:00:00 2001 From: Richard Date: Sun, 26 Mar 2017 15:38:26 -0700 Subject: [PATCH 0870/1679] updated readme --- .../README.markdown | 459 +++++++++++++++++- .../Contents.swift | 2 + .../Sources/Matrix.swift | 180 ++++--- .../Sources/MatrixSize.swift | 19 +- .../Sources/Number.swift | 12 +- 5 files changed, 571 insertions(+), 101 deletions(-) diff --git a/Strassen Matrix Multiplication/README.markdown b/Strassen Matrix Multiplication/README.markdown index d07004bad..e4222b4f4 100644 --- a/Strassen Matrix Multiplication/README.markdown +++ b/Strassen Matrix Multiplication/README.markdown @@ -1 +1,458 @@ -## TODO: Examples & Explanation +# Strassen Matrix Multiplication + +## Goal ++ To quickly perform a matrix multiplication operation on two matricies + +## What is Matrix Multiplication?? + +> Note: If you are already familiar with Linear Algebra/Matrix Multiplication, feel free to skip this section + +Before we begin, you may ask what is matrix multiplication? Great question! It is **NOT** multiplying two matricies term-by-term. Matrix multiplication is a mathematical operation that combines two matricies into a single one. Sounds like multiplying term-by-term huh? It's not... our lives would be much easier if it were. To see how matrix multiplcation works, let's look at an example. + +### Example: Matrix Multiplication + + matrix A = |1 2| + |3 4| + + matrix B = |5 6| + |7 8| + + A * B = C + + |1 2| * |5 6| = |1*5+2*7 1*6+2*8| = |19 22| + |3 4| |7 8| |3*5+4*7 3*6+4*8| |43 48| + +What's going on here? To start, we're multiplying matricies A & B. Our new matrix, C's, elements `[i, j]` are determined by the dot product of the first matrix's ith row and the second matrix's jth column. See [here](https://www.khanacademy.org/math/linear-algebra/vectors-and-spaces/dot-cross-products/v/vector-dot-product-and-vector-length) for a refresher on the dot product. + +So the upper left element `[i=1, j=1]` of our new matrix is a combination of A's 1st row and B's 1st column. + + A's first row = [1, 2] + B's first column = [5, 7] + + [1, 2] dot [5, 7] = [1*5 + 2*7] = [19] = C[1, 1] + +Now let's try this for `[i=1, j=2]`. Because `i=1` and `j=2`, this will represent the upper right element in our new matrix, C. + + A's first row = [1, 2] + B's second column = [6, 8] + + [1, 2] dot [6, 8] = [1*6 + 2*8] = [22] = C[1, 2] + +If we do this for each row & column of A & B we'll get our result matrix C! + +Here's a great graphic that visually shows you what's going on. + +![](https://upload.wikimedia.org/wikipedia/commons/thumb/e/e1/Matrix_multiplication_principle.svg/1024px-Matrix_multiplication_principle.svg.png) + +[Source](https://upload.wikimedia.org/wikipedia/commons/thumb/e/e1/Matrix_multiplication_principle.svg/1024px-Matrix_multiplication_principle.svg.png) + + +## Matix Multiplication Algorithm + +So how do we implement matrix multiplication in an algoirthm? We'll start with the basic version and from there move on to Strassen's Algorithm. + ++ [Basic Version](#basic-version) ++ [Strassen's Algorithm](#strassens-algorithm) + +### Basic Version + +Remember the method we used to solve matrix multiplication [above](#what-is-matrix-multiplication??)? Let's try to implement that first! We first assert that the two matricies are the right size. + +`assert(A.columns == B.rows, "Two matricies can only be matrix mulitiplied if one has dimensions mxn & the other has dimensions nxp where m, n, p are in R")` + +> **NOTE:** A's # of columns HAS to equal B's # of rows for matrix multiplication to work + +Next, we loop over A's columns and B's rows. Because we know both A's columns & B's rows are the same length, we set that length equal to `n`. + +```swift +for i in 0..) -> Matrix { + let A = self + assert(A.columns == B.rows, "Two matricies can only be matrix mulitiplied if one has dimensions mxn & the other has dimensions nxp where m, n, p are in R") + let n = A.columns + var C = Matrix(rows: A.rows, columns: B.columns) + + for i in 0..) -> Matrix { + let A = self + assert(A.columns == B.rows, "Two matricies can only be matrix mulitiplied if one has dimensions mxn & the other has dimensions nxp where m, n, p are in R") + + let n = max(A.rows, A.columns, B.rows, B.columns) + let m = nextPowerOfTwo(after: n) + + var APrep = Matrix(size: m) + var BPrep = Matrix(size: m) + + A.forEach { (i, j) in + APrep[i,j] = A[i,j] + } + + B.forEach { (i, j) in + BPrep[i,j] = B[i,j] + } + + let CPrep = APrep.strassenR(by: BPrep) + var C = Matrix(rows: A.rows, columns: B.columns) + for i in 0..) -> Matrix { + let A = self + assert(A.isSquare && B.isSquare, "This function requires square matricies!") + guard A.rows > 1 && B.rows > 1 else { return A * B } + + let n = A.rows + let nBy2 = n / 2 + + /* + Assume submatricies are allocated as follows + + matrix A = |a b|, matrix B = |e f| + |c d| |g h| + */ + + var a = Matrix(size: nBy2) + var b = Matrix(size: nBy2) + var c = Matrix(size: nBy2) + var d = Matrix(size: nBy2) + var e = Matrix(size: nBy2) + var f = Matrix(size: nBy2) + var g = Matrix(size: nBy2) + var h = Matrix(size: nBy2) + + for i in 0.. Int { + return Int(pow(2, ceil(log2(Double(n))))) + } +} +``` + + +## Appendix + +### Number Protocol + +I use a number protocol to enable by Matrix to be generic. + +The Number protocol ensures three things: + +1. Everything that is a number can be multiplied +2. Everything that is a number can be added/subtracted +3. Everything that is a number has a zero value + +Extending `Int`, `Float`, and `Double` to conform to this protocol is now very straightforward. All you need to do is implement the `static var zero`! + +```swift +public protocol Number: Multipliable, Addable { + static var zero: Self { get } +} + +public protocol Addable { + static func +(lhs: Self, rhs: Self) -> Self + static func -(lhs: Self, rhs: Self) -> Self +} + +public protocol Multipliable { + static func *(lhs: Self, rhs: Self) -> Self +} +``` + +### Dot Product + +I extend `Array` to include a dot product function for when the Array's element conform to the `Number` protocol. + +```swift +extension Array where Element: Number { + public func dot(_ b: Array) -> Element { + let a = self + assert(a.count == b.count, "Can only take the dot product of arrays of the same length!") + let c = a.indices.map{ a[$0] * b[$0] } + return c.reduce(Element.zero, { $0 + $1 }) + } +} +``` + +##Resources ++ [Intro to Matrix Multiplication | Khan Academy](https://www.khanacademy.org/math/precalculus/precalc-matrices/multiplying-matrices-by-matrices/v/matrix-multiplication-intro) ++ [Matrix Multiplication | Wikipedia](https://en.wikipedia.org/wiki/Matrix_multiplication) ++ [Strassen Algorithm | Wikipedia](https://en.wikipedia.org/wiki/Strassen_algorithm) ++ [Strassen Algorithm | Wolfram MathWorld](http://mathworld.wolfram.com/StrassenFormulas.html) ++ [Strassens Algorithm | Geeks for Geeks](http://www.geeksforgeeks.org/strassens-matrix-multiplication/) \ No newline at end of file diff --git a/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Contents.swift b/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Contents.swift index 50af60a6f..5d82244a3 100644 --- a/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Contents.swift +++ b/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Contents.swift @@ -8,9 +8,11 @@ A[.row, 0] = [2, 3, -1, 0] A[.row, 1] = [-7, 2, 1, 10] var B = Matrix(rows: 4, columns: 2, initialValue: 0) +print(B) B[.column, 0] = [3, 2, -1, 2] B[.column, 1] = [4, 1, 2, 7] + let C = A.matrixMultiply(by: B) let D = A.strassenMatrixMultiply(by: B) let E = B.matrixMultiply(by: A) diff --git a/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/Matrix.swift b/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/Matrix.swift index eba49ce9a..77ced4632 100644 --- a/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/Matrix.swift +++ b/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/Matrix.swift @@ -40,23 +40,26 @@ public struct Matrix { self.columns = size self.grid = Array(repeating: initialValue, count: rows * columns) } -} - -// MARK: - Public Functions - -public extension Matrix { - subscript(row: Int, column: Int) -> T { + + // MARK: - Private Functions + + fileprivate func indexIsValid(row: Int, column: Int) -> Bool { + return row >= 0 && row < rows && column >= 0 && column < columns + } + + // MARK: - Subscript + + public subscript(row: Int, column: Int) -> T { get { assert(indexIsValid(row: row, column: column), "Index out of range") return grid[(row * columns) + column] - } - set { + } set { assert(indexIsValid(row: row, column: column), "Index out of range") grid[(row * columns) + column] = newValue } } - subscript(type: RowOrColumn, value: Int) -> [T] { + public subscript(type: RowOrColumn, value: Int) -> [T] { get { switch type { case .row: @@ -64,15 +67,11 @@ public extension Matrix { return Array(grid[(value * columns)..<(value * columns) + columns]) case .column: assert(indexIsValid(row: 0, column: value), "Index out of range") - var columns: [T] = [] - for row in 0.. T in + let currentColumnIndex = currentRow * columns + value + return grid[currentColumnIndex] } - return columns + return column } } set { switch type { @@ -90,59 +89,84 @@ public extension Matrix { } } - func strassenMatrixMultiply(by B: Matrix) -> Matrix { + // MARK: - Public Functions + + public func row(for columnIndex: Int) -> [T] { + assert(indexIsValid(row: columnIndex, column: 0), "Index out of range") + return Array(grid[(columnIndex * columns)..<(columnIndex * columns) + columns]) + } + + public func column(for rowIndex: Int) -> [T] { + assert(indexIsValid(row: 0, column: rowIndex), "Index out of range") + + let column = (0.. T in + let currentColumnIndex = currentRow * columns + rowIndex + return grid[currentColumnIndex] + } + return column + } + + public func forEach(_ body: (Int, Int) throws -> Void) rethrows { + for row in 0..) -> Matrix { + let A = self + assert(A.columns == B.rows, "Two matricies can only be matrix mulitiplied if one has dimensions mxn & the other has dimensions nxp where m, n, p are in R") + + var C = Matrix(rows: A.rows, columns: B.columns) + + for i in 0..) -> Matrix { let A = self assert(A.columns == B.rows, "Two matricies can only be matrix mulitiplied if one has dimensions mxn & the other has dimensions nxp where m, n, p are in R") let n = max(A.rows, A.columns, B.rows, B.columns) - let m = nextPowerOfTwo(of: n) + let m = nextPowerOfTwo(after: n) var APrep = Matrix(size: m) var BPrep = Matrix(size: m) - A.size.forEach { (i, j) in + A.forEach { (i, j) in APrep[i,j] = A[i,j] } - B.size.forEach { (i, j) in + B.forEach { (i, j) in BPrep[i,j] = B[i,j] } let CPrep = APrep.strassenR(by: BPrep) var C = Matrix(rows: A.rows, columns: B.columns) - for i in 0..) -> Matrix { - let A = self - assert(A.columns == B.rows, "Two matricies can only be matrix mulitiplied if one has dimensions mxn & the other has dimensions nxp where m, n, p are in R") - - var C = Matrix(rows: A.rows, columns: B.columns) - - for i in 0.. Bool { - return row >= 0 && row < rows && column >= 0 && column < columns - } - func strassenR(by B: Matrix) -> Matrix { + private func strassenR(by B: Matrix) -> Matrix { let A = self assert(A.isSquare && B.isSquare, "This function requires square matricies!") guard A.rows > 1 && B.rows > 1 else { return A * B } @@ -150,42 +174,49 @@ fileprivate extension Matrix { let n = A.rows let nBy2 = n / 2 - var a11 = Matrix(size: nBy2) - var a12 = Matrix(size: nBy2) - var a21 = Matrix(size: nBy2) - var a22 = Matrix(size: nBy2) - var b11 = Matrix(size: nBy2) - var b12 = Matrix(size: nBy2) - var b21 = Matrix(size: nBy2) - var b22 = Matrix(size: nBy2) + /* + Assume submatricies are allocated as follows + + matrix A = |a b|, matrix B = |e f| + |c d| |g h| + */ + + var a = Matrix(size: nBy2) + var b = Matrix(size: nBy2) + var c = Matrix(size: nBy2) + var d = Matrix(size: nBy2) + var e = Matrix(size: nBy2) + var f = Matrix(size: nBy2) + var g = Matrix(size: nBy2) + var h = Matrix(size: nBy2) for i in 0.. Int { + private func nextPowerOfTwo(after n: Int) -> Int { return Int(pow(2, ceil(log2(Double(n))))) } } - // Term-by-term Matrix Math extension Matrix: Addable { diff --git a/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/MatrixSize.swift b/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/MatrixSize.swift index f4a604ade..e0d957607 100644 --- a/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/MatrixSize.swift +++ b/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/MatrixSize.swift @@ -8,26 +8,13 @@ import Foundation -public struct MatrixSize: Equatable { +public struct MatrixSize { let rows: Int let columns: Int - - public init(rows: Int, columns: Int) { - self.rows = rows - self.columns = columns - } - - public func forEach(_ body: (Int, Int) throws -> Void) rethrows { - for row in 0.. Bool { +extension MatrixSize: Equatable { + public static func ==(lhs: MatrixSize, rhs: MatrixSize) -> Bool { return lhs.columns == rhs.columns && lhs.rows == rhs.rows } } diff --git a/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/Number.swift b/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/Number.swift index 9f4c7f4ab..7da1eee60 100644 --- a/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/Number.swift +++ b/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/Number.swift @@ -22,21 +22,15 @@ public protocol Multipliable { } extension Int: Number { - public static var zero: Int { - return 0 - } + public static var zero: Int { return 0 } } extension Double: Number { - public static var zero: Double { - return 0.0 - } + public static var zero: Double { return 0.0 } } extension Float: Number { - public static var zero: Float { - return 0.0 - } + public static var zero: Float { return 0.0 } } extension Array where Element: Number { From c94fbab56dcd0b3f483ec8a1fec718de7ef97ba2 Mon Sep 17 00:00:00 2001 From: Richard Date: Sun, 26 Mar 2017 15:53:58 -0700 Subject: [PATCH 0871/1679] added authorship to readme --- Strassen Matrix Multiplication/README.markdown | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Strassen Matrix Multiplication/README.markdown b/Strassen Matrix Multiplication/README.markdown index e4222b4f4..6949f906c 100644 --- a/Strassen Matrix Multiplication/README.markdown +++ b/Strassen Matrix Multiplication/README.markdown @@ -405,7 +405,6 @@ extension Matrix { } ``` - ## Appendix ### Number Protocol @@ -455,4 +454,6 @@ extension Array where Element: Number { + [Matrix Multiplication | Wikipedia](https://en.wikipedia.org/wiki/Matrix_multiplication) + [Strassen Algorithm | Wikipedia](https://en.wikipedia.org/wiki/Strassen_algorithm) + [Strassen Algorithm | Wolfram MathWorld](http://mathworld.wolfram.com/StrassenFormulas.html) -+ [Strassens Algorithm | Geeks for Geeks](http://www.geeksforgeeks.org/strassens-matrix-multiplication/) \ No newline at end of file ++ [Strassens Algorithm | Geeks for Geeks](http://www.geeksforgeeks.org/strassens-matrix-multiplication/) + +*Written for Swift Algorithm Club by Richard Ash* \ No newline at end of file From 09848a79e92c266b3e33006781732c1e288d7f6f Mon Sep 17 00:00:00 2001 From: Richard Date: Sun, 26 Mar 2017 15:55:13 -0700 Subject: [PATCH 0872/1679] fixed the display of the resources header --- Strassen Matrix Multiplication/README.markdown | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Strassen Matrix Multiplication/README.markdown b/Strassen Matrix Multiplication/README.markdown index 6949f906c..713ab1801 100644 --- a/Strassen Matrix Multiplication/README.markdown +++ b/Strassen Matrix Multiplication/README.markdown @@ -449,7 +449,8 @@ extension Array where Element: Number { } ``` -##Resources +## Resources + + [Intro to Matrix Multiplication | Khan Academy](https://www.khanacademy.org/math/precalculus/precalc-matrices/multiplying-matrices-by-matrices/v/matrix-multiplication-intro) + [Matrix Multiplication | Wikipedia](https://en.wikipedia.org/wiki/Matrix_multiplication) + [Strassen Algorithm | Wikipedia](https://en.wikipedia.org/wiki/Strassen_algorithm) From ab37359616c210f84363b885ef0308b17cadc202 Mon Sep 17 00:00:00 2001 From: Richard Date: Sun, 26 Mar 2017 16:05:27 -0700 Subject: [PATCH 0873/1679] fixed layout of code in readme --- .../README.markdown | 142 +++++++++--------- 1 file changed, 75 insertions(+), 67 deletions(-) diff --git a/Strassen Matrix Multiplication/README.markdown b/Strassen Matrix Multiplication/README.markdown index 713ab1801..fa822d310 100644 --- a/Strassen Matrix Multiplication/README.markdown +++ b/Strassen Matrix Multiplication/README.markdown @@ -11,17 +11,16 @@ Before we begin, you may ask what is matrix multiplication? Great question! It i ### Example: Matrix Multiplication - matrix A = |1 2| - |3 4| - - matrix B = |5 6| - |7 8| - - A * B = C +``` +matrix A = |1 2|, matrix B = |5 6| + |3 4| |7 8| - |1 2| * |5 6| = |1*5+2*7 1*6+2*8| = |19 22| - |3 4| |7 8| |3*5+4*7 3*6+4*8| |43 48| +A * B = C +|1 2| * |5 6| = |1*5+2*7 1*6+2*8| = |19 22| +|3 4| |7 8| |3*5+4*7 3*6+4*8| |43 48| +``` + What's going on here? To start, we're multiplying matricies A & B. Our new matrix, C's, elements `[i, j]` are determined by the dot product of the first matrix's ith row and the second matrix's jth column. See [here](https://www.khanacademy.org/math/linear-algebra/vectors-and-spaces/dot-cross-products/v/vector-dot-product-and-vector-length) for a refresher on the dot product. So the upper left element `[i=1, j=1]` of our new matrix is a combination of A's 1st row and B's 1st column. @@ -66,14 +65,14 @@ Next, we loop over A's columns and B's rows. Because we know both A's columns & ```swift for i in 0..) -> Matrix { - let A = self - assert(A.columns == B.rows, "Two matricies can only be matrix mulitiplied if one has dimensions mxn & the other has dimensions nxp where m, n, p are in R") - let n = A.columns - var C = Matrix(rows: A.rows, columns: B.columns) + let A = self + assert(A.columns == B.rows, "Two matricies can only be matrix mulitiplied if one has dimensions mxn & the other has dimensions nxp where m, n, p are in R") + let n = A.columns + var C = Matrix(rows: A.rows, columns: B.columns) - for i in 0.. Date: Mon, 27 Mar 2017 16:33:26 +0800 Subject: [PATCH 0874/1679] Delete SelectionSamplingExample.swift --- .../SelectionSamplingExample.swift | 32 ------------------- 1 file changed, 32 deletions(-) delete mode 100644 Selection Sampling/SelectionSamplingExample.swift diff --git a/Selection Sampling/SelectionSamplingExample.swift b/Selection Sampling/SelectionSamplingExample.swift deleted file mode 100644 index 66648a934..000000000 --- a/Selection Sampling/SelectionSamplingExample.swift +++ /dev/null @@ -1,32 +0,0 @@ -// -// Select.swift -// -// -// Created by Cheer on 2017/3/9. -// -// - -import Foundation - -func select(from a: [T], count requested: Int) -> [T] { - - // if requested > a.count, will throw ==> fatal error: Index out of range - - if requested < a.count { - var arr = a - for i in 0.. the range is [0...n-1] - //So: arc4random_uniform(UInt32(arr.count - i - 2)) + (i + 1) ==> [0...arr.count - (i + 1) - 1] + (i + 1) ==> the range is [(i + 1)...arr.count - 1] - //Why start index is "(i + 1)"? Because in "swap(&A,&B)", if A's index == B's index, will throw a error: "swapping a location with itself is not supported" - - let nextIndex = Int(arc4random_uniform(UInt32(arr.count - i - 2))) + (i + 1) - swap(&arr[nextIndex], &arr[i]) - } - return Array(arr[0.. Date: Tue, 28 Mar 2017 15:54:51 +0800 Subject: [PATCH 0875/1679] Update ShellSortExample.swift fix code. And apologize for my carelessness. --- Shell Sort/ShellSortExample.swift | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Shell Sort/ShellSortExample.swift b/Shell Sort/ShellSortExample.swift index c41eb8889..0beac00a3 100644 --- a/Shell Sort/ShellSortExample.swift +++ b/Shell Sort/ShellSortExample.swift @@ -14,18 +14,18 @@ public func shellSort(_ list : inout [Int]) while sublistCount > 0 { - for var index in 0.. arr[index + sublistCount]{ - swap(&arr[index], &arr[index + sublistCount]) + if list[index] > list[index + sublistCount]{ + swap(&list[index], &list[index + sublistCount]) } guard sublistCount == 1 && index > 0 else { continue } - - while arr[index - 1] > arr[index] && index - 1 > 0 { - swap(&arr[index - 1], &arr[index]) + + while list[index - 1] > list[index] && index - 1 > 0 { + swap(&list[index - 1], &list[index]) index -= 1 } } From 14fe78745ccceb2de88ed2a3dc05835d99317e90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=A9=98=E5=AD=90?= <726451484@qq.com> Date: Tue, 28 Mar 2017 15:55:45 +0800 Subject: [PATCH 0876/1679] Update ShellSortExample.swift --- Shell Sort/ShellSortExample.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Shell Sort/ShellSortExample.swift b/Shell Sort/ShellSortExample.swift index 0beac00a3..05ab2518b 100644 --- a/Shell Sort/ShellSortExample.swift +++ b/Shell Sort/ShellSortExample.swift @@ -14,11 +14,11 @@ public func shellSort(_ list : inout [Int]) while sublistCount > 0 { - for var index in 0.. list[index + sublistCount]{ + if list[index] > list[index + sublistCount] { swap(&list[index], &list[index + sublistCount]) } From cf1561f885c414d8c4bb260cd21720c109468b9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=A9=98=E5=AD=90?= <726451484@qq.com> Date: Tue, 28 Mar 2017 15:56:26 +0800 Subject: [PATCH 0877/1679] Update ShellSortExample.swift --- Shell Sort/ShellSortExample.swift | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Shell Sort/ShellSortExample.swift b/Shell Sort/ShellSortExample.swift index 05ab2518b..9174b935b 100644 --- a/Shell Sort/ShellSortExample.swift +++ b/Shell Sort/ShellSortExample.swift @@ -8,12 +8,10 @@ import Foundation -public func shellSort(_ list : inout [Int]) -{ +public func shellSort(_ list : inout [Int]) { var sublistCount = list.count / 2 - while sublistCount > 0 - { + while sublistCount > 0 { for var index in 0.. Date: Tue, 28 Mar 2017 20:01:36 -0700 Subject: [PATCH 0878/1679] Update How to Contribute link Super simple but just something I noticed while getting started. Cheers! --- README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.markdown b/README.markdown index 023f151fb..5e6cfbfe4 100644 --- a/README.markdown +++ b/README.markdown @@ -227,7 +227,7 @@ The Swift Algorithm Club was originally created by [Matthijs Hollemans](https:// It is now maintained by [Vincent Ngo](https://www.raywenderlich.com/u/jomoka) and [Kelvin Lau](https://github.com/kelvinlauKL). -The Swift Algorithm Club is a collaborative effort from the [most algorithmic members](https://github.com/rwenderlich/swift-algorithm-club/graphs/contributors) of the [raywenderlich.com](https://www.raywenderlich.com) community. We're always looking for help - why not [join the club](How to Contribute.markdown)? :] +The Swift Algorithm Club is a collaborative effort from the [most algorithmic members](https://github.com/rwenderlich/swift-algorithm-club/graphs/contributors) of the [raywenderlich.com](https://www.raywenderlich.com) community. We're always looking for help - why not [join the club](How%20to%20Contribute.markdown)? :] ## License From edee6981d7e77ff88186439b2536b8cc212354c5 Mon Sep 17 00:00:00 2001 From: Richard Date: Tue, 28 Mar 2017 21:31:33 -0700 Subject: [PATCH 0879/1679] =?UTF-8?q?updated=20syntax=20for=20Swift=203.1!?= =?UTF-8?q?=20=F0=9F=98=81=F0=9F=94=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Contents.swift | 1 - .../Sources/Matrix.swift | 31 ++++++++++++------- .../Sources/MatrixSize.swift | 20 ------------ 3 files changed, 19 insertions(+), 33 deletions(-) delete mode 100644 Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/MatrixSize.swift diff --git a/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Contents.swift b/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Contents.swift index 5d82244a3..9e11cb6a1 100644 --- a/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Contents.swift +++ b/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Contents.swift @@ -1,5 +1,4 @@ //: Playground - noun: a place where people can play -// Reference - http://mathworld.wolfram.com/StrassenFormulas.html import Foundation diff --git a/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/Matrix.swift b/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/Matrix.swift index 77ced4632..c13b3eeee 100644 --- a/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/Matrix.swift +++ b/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/Matrix.swift @@ -8,37 +8,44 @@ import Foundation -public enum RowOrColumn { - case row, column -} - public struct Matrix { + // MARK: - Martix Objects + + public enum Index { + case row, column + } + + public struct Size: Equatable { + let rows: Int, columns: Int + + public static func ==(lhs: Size, rhs: Size) -> Bool { + return lhs.columns == rhs.columns && lhs.rows == rhs.rows + } + } + // MARK: - Variables let rows: Int, columns: Int + let size: Size + var grid: [T] var isSquare: Bool { return rows == columns } - var size: MatrixSize { - return MatrixSize(rows: rows, columns: columns) - } - // MARK: - Init public init(rows: Int, columns: Int, initialValue: T = T.zero) { self.rows = rows self.columns = columns + self.size = Size(rows: rows, columns: columns) self.grid = Array(repeating: initialValue, count: rows * columns) } public init(size: Int, initialValue: T = T.zero) { - self.rows = size - self.columns = size - self.grid = Array(repeating: initialValue, count: rows * columns) + self.init(rows: size, columns: size, initialValue: initialValue) } // MARK: - Private Functions @@ -59,7 +66,7 @@ public struct Matrix { } } - public subscript(type: RowOrColumn, value: Int) -> [T] { + public subscript(type: Matrix.Index, value: Int) -> [T] { get { switch type { case .row: diff --git a/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/MatrixSize.swift b/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/MatrixSize.swift deleted file mode 100644 index e0d957607..000000000 --- a/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/MatrixSize.swift +++ /dev/null @@ -1,20 +0,0 @@ -// -// MatrixSize.swift -// -// -// Created by Richard Ash on 10/28/16. -// -// - -import Foundation - -public struct MatrixSize { - let rows: Int - let columns: Int -} - -extension MatrixSize: Equatable { - public static func ==(lhs: MatrixSize, rhs: MatrixSize) -> Bool { - return lhs.columns == rhs.columns && lhs.rows == rhs.rows - } -} From 4d1b9ff02cb46640b55f8b462be8d4536ca182bf Mon Sep 17 00:00:00 2001 From: Jim Rhoades Date: Wed, 29 Mar 2017 18:02:32 -0400 Subject: [PATCH 0880/1679] Update Big-O Notation.markdown Fixed the link to "merge sort". --- Big-O Notation.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Big-O Notation.markdown b/Big-O Notation.markdown index 09fbb04aa..746cba8a3 100644 --- a/Big-O Notation.markdown +++ b/Big-O Notation.markdown @@ -19,6 +19,6 @@ Big-O | Name | Description Often you don't need math to figure out what the Big-O of an algorithm is but you can simply use your intuition. If your code uses a single loop that looks at all **n** elements of your input, the algorithm is **O(n)**. If the code has two nested loops, it is **O(n^2)**. Three nested loops gives **O(n^3)**, and so on. -Note that Big-O notation is an estimate and is only really useful for large values of **n**. For example, the worst-case running time for the [insertion sort](Insertion%20Sort/) algorithm is **O(n^2)**. In theory that is worse than the running time for [merge sort](Merge Sort/), which is **O(n log n)**. But for small amounts of data, insertion sort is actually faster, especially if the array is partially sorted already! +Note that Big-O notation is an estimate and is only really useful for large values of **n**. For example, the worst-case running time for the [insertion sort](Insertion%20Sort/) algorithm is **O(n^2)**. In theory that is worse than the running time for [merge sort](Merge%20Sort/), which is **O(n log n)**. But for small amounts of data, insertion sort is actually faster, especially if the array is partially sorted already! If you find this confusing, don't let this Big-O stuff bother you too much. It's mostly useful when comparing two algorithms to figure out which one is better. But in the end you still want to test in practice which one really is the best. And if the amount of data is relatively small, then even a slow algorithm will be fast enough for practical use. From 6d4a1eec73c92713e2e4e880b486694da545dbf9 Mon Sep 17 00:00:00 2001 From: darrellhz Date: Thu, 30 Mar 2017 14:30:01 +0900 Subject: [PATCH 0881/1679] Update README.markdown updated to swift 3 syntax --- Binary Search Tree/README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Binary Search Tree/README.markdown b/Binary Search Tree/README.markdown index a3a84c03d..b3b955c61 100644 --- a/Binary Search Tree/README.markdown +++ b/Binary Search Tree/README.markdown @@ -195,7 +195,7 @@ For convenience, let's add an init method that calls `insert()` for all the elem precondition(array.count > 0) self.init(value: array.first!) for v in array.dropFirst() { - insert(v, parent: self) + insert(value: v) } } ``` From da0be01444b4dfc2cdbd2259a3e5c524e9d37434 Mon Sep 17 00:00:00 2001 From: Parva9eh Date: Sat, 1 Apr 2017 14:29:56 -0700 Subject: [PATCH 0882/1679] Update README.markdown Hello, I have revised one of your documents for my assignment. I still need to revise more documents (10 in total). I hope it will be fine if I choose some documents from your account. Thanks, Parvaneh --- Heap/README.markdown | 116 +++++++++++++++++++++---------------------- 1 file changed, 58 insertions(+), 58 deletions(-) diff --git a/Heap/README.markdown b/Heap/README.markdown index 88ea25eeb..3935950a6 100644 --- a/Heap/README.markdown +++ b/Heap/README.markdown @@ -1,19 +1,19 @@ # Heap -A heap is a [binary tree](../Binary Tree/) that lives inside an array, so it doesn't use parent/child pointers. The tree is partially sorted according to something called the "heap property" that determines the order of the nodes in the tree. +A heap is a [binary tree](../Binary Tree/) inside an array, so it doesn't use parent/child pointers. A heap is sorted based on the "heap property" that determines the order of the nodes in the tree. Common uses for heap: -- For building [priority queues](../Priority Queue/). -- The heap is the data structure supporting [heap sort](../Heap Sort/). -- Heaps are fast for when you often need to compute the minimum (or maximum) element of a collection. -- Impressing your non-programmer friends. +- To build [priority queues](../Priority Queue/). +- To support [heap sorts](../Heap Sort/). +- To compute the minimum (or maximum) element of a collection quickly. +- To impress your non-programmer friends. ## The heap property -There are two kinds of heaps: a *max-heap* and a *min-heap*. They are identical, except that the order in which they store the tree nodes is opposite. +There are two kinds of heaps: a *max-heap* and a *min-heap* which are different by the order in which they store the tree nodes. -In a max-heap, parent nodes must always have a greater value than each of their children. For a min-heap it's the other way around: every parent node has a smaller value than its child nodes. This is called the "heap property" and it is true for every single node in the tree. +In a max-heap, parent nodes have a greater value than each of their children. In a min-heap, every parent node has a smaller value than its child nodes. This is called the "heap property", and it is true for every single node in the tree. An example: @@ -21,33 +21,33 @@ An example: This is a max-heap because every parent node is greater than its children. `(10)` is greater than `(7)` and `(2)`. `(7)` is greater than `(5)` and `(1)`. -As a result of this heap property, a max-heap always stores its largest item at the root of the tree. For a min-heap, the root is always the smallest item in the tree. That is very useful because heaps are often used as a [priority queue](../Priority Queue/) where you want to quickly access the "most important" element. +As a result of this heap property, a max-heap always stores its largest item at the root of the tree. For a min-heap, the root is always the smallest item in the tree. The heap property is useful because heaps are often used as a [priority queue](../Priority Queue/)to access the "most important" element quickly. -> **Note:** You can't really say anything else about the sort order of the heap. For example, in a max-heap the maximum element is always at index 0 but the minimum element isn’t necessarily the last one -- the only guarantee you have is that it is one of the leaf nodes, but not which one. +> **Note:** The root of the heap has the maximum or minimum element, but the sort order of other elements are not predictable. For example, the maximum element is always at index 0 in a max-heap, but the minimum element isn’t necessarily the last one. -- the only guarantee you have is that it is one of the leaf nodes, but not which one. -## How does heap compare to regular trees? +## How does a heap can be compared to regular trees? -A heap isn't intended to be a replacement for a binary search tree. But there are many similarities between the two and also some differences. Here are some of the bigger differences: +A heap is not a replacement for a binary search tree, and there are similarities and differnces between them. Here are some main differences: -**Order of the nodes.** In a [binary search tree (BST)](../Binary Search Tree/), the left child must always be smaller than its parent and the right child must be greater. This is not true for a heap. In max-heap both children must be smaller; in a min-heap they both must be greater. +**Order of the nodes.** In a [binary search tree (BST)](../Binary Search Tree/), the left child must be smaller than its parent and the right child must be greater. This is not true for a heap. In a max-heap both children must be smaller than the parent; in a min-heap they both must be greater. **Memory.** Traditional trees take up more memory than just the data they store. You need to allocate additional storage for the node objects and pointers to the left/right child nodes. A heap only uses a plain array for storage and uses no pointers. -**Balancing.** A binary search tree must be "balanced" so that most operations have **O(log n)** performance. You can either insert and delete your data in a random order or use something like an [AVL tree](../AVL Tree/) or [red-black tree](../Red-Black Tree/). But with heaps we don't actually need the entire tree to be sorted. We just want the heap property to be fulfilled, and so balancing isn't an issue. Because of the way the heap is structured, heaps can guarantee **O(log n)** performance. +**Balancing.** A binary search tree must be "balanced" so that most operations have **O(log n)** performance. You can either insert and delete your data in a random order or use something like an [AVL tree](../AVL Tree/) or [red-black tree](../Red-Black Tree/), but with heaps we don't actually need the entire tree to be sorted. We just want the heap property to be fulfilled, so balancing isn't an issue. Because of the way the heap is structured, heaps can guarantee **O(log n)** performance. -**Searching.** Searching a binary tree is really fast -- that's its whole purpose. In a heap, searching is slow. The purpose of a heap is to always put the largest (or smallest) node at the front, and to allow relatively fast inserts and deletes. Searching isn't a top priority. +**Searching.** Whereas searching is fast in a binary tree, it is slow in a heap. Searching isn't a top priority in a heap since the purpose of a heap is to put the largest (or smallest) node at the front and to allow relatively fast inserts and deletes. -## The tree that lived in an array +## The tree inside an array -An array may seem like an odd way to implement a tree-like structure but it is very efficient in both time and space. +An array may seem like an odd way to implement a tree-like structure, but it is efficient in both time and space. -This is how we're going to store the tree from the above example: +This is how we are going to store the tree from the above example: [ 10, 7, 2, 5, 1 ] That's all there is to it! We don't need any more storage than just this simple array. -So how do we know which nodes are the parents and which are the children if we're not allowed to use any pointers? Good question! There is a well-defined relationship between the array index of a tree node and the array indices of its parent and children. +So how do we know which nodes are the parents and which are the children if we are not allowed to use any pointers? Good question! There is a well-defined relationship between the array index of a tree node and the array indices of its parent and children. If `i` is the index of a node, then the following formulas give the array indices of its parent and child nodes: @@ -69,7 +69,7 @@ Let's use these formulas on the example. Fill in the array index and we should g Verify for yourself that these array indices indeed correspond to the picture of the tree. -> **Note:** The root node `(10)` doesn't have a parent because `-1` is not a valid array index. Likewise, nodes `(2)`, `(5)`, and `(1)` don't have children because those indices are greater than the array size. So we always have to make sure the indices we calculate are actually valid before we use them. +> **Note:** The root node `(10)` does not have a parent because `-1` is not a valid array index. Likewise, nodes `(2)`, `(5)`, and `(1)` do not have children because those indices are greater than the array size, so we always have to make sure the indices we calculate are actually valid before we use them. Recall that in a max-heap, the parent's value is always greater than (or equal to) the values of its children. This means the following must be true for all array indices `i`: @@ -79,27 +79,27 @@ array[parent(i)] >= array[i] Verify that this heap property holds for the array from the example heap. -As you can see, these equations let us find the parent or child index for any node without the need for pointers. True, it's slightly more complicated than just dereferencing a pointer but that's the tradeoff: we save memory space but pay with extra computations. Fortunately, the computations are fast and only take **O(1)** time. +As you can see, these equations allow us to find the parent or child index for any node without the need for pointers. It is complicated than just dereferencing a pointer, but that is the tradeoff: we save memory space but pay with extra computations. Fortunately, the computations are fast and only take **O(1)** time. -It's important to understand this relationship between array index and position in the tree. Here's a slightly larger heap, this tree has 15 nodes divided over four levels: +It is important to understand this relationship between array index and position in the tree. Here is a larger heap which has 15 nodes divided over four levels: ![Large heap](Images/LargeHeap.png) -The numbers in this picture aren't the values of the nodes but the array indices that store the nodes! Those array indices correspond to the different levels of the tree like this: +The numbers in this picture are not the values of the nodes but the array indices that store the nodes! Here is the array indices correspond to the different levels of the tree: ![The heap array](Images/Array.png) -For the formulas to work, parent nodes must always appear before child nodes in the array. You can see that in the above picture. +For the formulas to work, parent nodes must appear before child nodes in the array. You can see that in the above picture. Note that this scheme has limitations. You can do the following with a regular binary tree but not with a heap: ![Impossible with a heap](Images/RegularTree.png) -You can’t start a new level unless the current lowest level is completely full. So heaps always have this kind of shape: +You can not start a new level unless the current lowest level is completely full, so heaps always have this kind of shape: ![The shape of a heap](Images/HeapShape.png) -> **Note:** Technically speaking you *could* emulate a regular binary tree with a heap, but it would waste a lot of space and you’d need some way to mark array indices as being empty. +> **Note:** You *could* emulate a regular binary tree with a heap, but it would be a waste of space, and you would need to mark array indices as being empty. Pop quiz! Let's say we have the array: @@ -111,15 +111,15 @@ Is this a valid heap? The answer is yes! A sorted array from low-to-high is a va The heap property holds for each node because a parent is always smaller than its children. (Verify for yourself that an array sorted from high-to-low is always a valid max-heap.) -> **Note:** But not every min-heap is necessarily a sorted array! It only works one way... To turn a heap back into a sorted array, you need to use [heap sort](../Heap Sort/). +> **Note:** But not every min-heap is necessarily a sorted array! It only works one way. To turn a heap back into a sorted array, you need to use [heap sort](../Heap Sort/). ## More math! -In case you are curious, here are a few more formulas that describe certain properties of a heap. You don't need to know these by heart but they come in handy sometimes. Feel free to skip this section! +In case you are curious, here are a few more formulas that describe certain properties of a heap. You do not need to know these by heart, but they come in handy sometimes. Feel free to skip this section! -The *height* of a tree is defined as the number of steps it takes to go from the root node to the lowest leaf node. Or more formally: the height is the maximum number of edges between the nodes. A heap of height *h* has *h + 1* levels. +The *height* of a tree is defined as the number of steps it takes to go from the root node to the lowest leaf node, or more formally: the height is the maximum number of edges between the nodes. A heap of height *h* has *h + 1* levels. -This heap has height 3 and therefore has 4 levels: +This heap has height 3, so it has 4 levels: ![Large heap](Images/LargeHeap.png) @@ -145,31 +145,31 @@ There are two primitive operations necessary to make sure the heap is a valid ma Shifting up or down is a recursive procedure that takes **O(log n)** time. -The other operations are built on these primitives. They are: +Here are other operations that are built on primitive operations: - `insert(value)`: Adds the new element to the end of the heap and then uses `shiftUp()` to fix the heap. -- `remove()`: Removes and returns the maximum value (max-heap) or the minimum value (min-heap). To fill up the hole that's left by removing the element, the very last element is moved to the root position and then `shiftDown()` fixes up the heap. (This is sometimes called "extract min" or "extract max".) +- `remove()`: Removes and returns the maximum value (max-heap) or the minimum value (min-heap). To fill up the hole left by removing the element, the very last element is moved to the root position and then `shiftDown()` fixes up the heap. (This is sometimes called "extract min" or "extract max".) -- `removeAtIndex(index)`: Just like `remove()` except it lets you remove any item from the heap, not just the root. This calls both `shiftDown()`, in case the new element is out-of-order with its children, and `shiftUp()`, in case the element is out-of-order with its parents. +- `removeAtIndex(index)`: Just like `remove()` with the exception that it allows you to remove any item from the heap, not just the root. This calls both `shiftDown()`, in case the new element is out-of-order with its children, and `shiftUp()`, in case the element is out-of-order with its parents. -- `replace(index, value)`: Assigns a smaller (min-heap) or larger (max-heap) value to a node. Because this invalidates the heap property, it uses `shiftUp()` to patch things up. (Also called "decrease key" and "increase key".) +- `replace(index, value)`: Assigns a smaller (min-heap) or larger (max-heap) value to a node. Because this invalidates the heap property, it uses `shiftUp()` to patch things up. (Also called "decrease key" and "increase key".) -All of the above take time **O(log n)** because shifting up or down is the most expensive thing they do. There are also a few operations that take more time: +All of the above take time **O(log n)** because shifting up or down is expensive. There are also a few operations that take more time: -- `search(value)`. Heaps aren't built for efficient searches but the `replace()` and `removeAtIndex()` operations require the array index of the node, so you need to find that index somehow. Time: **O(n)**. +- `search(value)`. Heaps are not built for efficient searches, but the `replace()` and `removeAtIndex()` operations require the array index of the node, so you need to find that index. Time: **O(n)**. -- `buildHeap(array)`: Converts an (unsorted) array into a heap by repeatedly calling `insert()`. If you’re smart about this, it can be done in **O(n)** time. +- `buildHeap(array)`: Converts an (unsorted) array into a heap by repeatedly calling `insert()`. If you are smart about this, it can be done in **O(n)** time. -- [Heap sort](../Heap Sort/). Since the heap is really an array, we can use its unique properties to sort the array from low to high. Time: **O(n lg n).** +- [Heap sort](../Heap Sort/). Since the heap is an array, we can use its unique properties to sort the array from low to high. Time: **O(n lg n).** The heap also has a `peek()` function that returns the maximum (max-heap) or minimum (min-heap) element, without removing it from the heap. Time: **O(1)**. -> **Note:** By far the most common things you'll do with a heap are inserting new values with `insert()` and removing the maximum or minimum value with `remove()`. Both take **O(log n)** time. The other operations exist to support more advanced usage, such as building a priority queue where the "importance" of items can change after they've been added to the queue. +> **Note:** By far the most common things you will do with a heap are inserting new values with `insert()` and removing the maximum or minimum value with `remove()`. Both take **O(log n)** time. The other operations exist to support more advanced usage, such as building a priority queue where the "importance" of items can change after they have been added to the queue. ## Inserting into the heap -Let's go through an example insertion to see in more detail how this works. We'll insert the value `16` into this heap: +Let's go through an example of insertion to see in details how this works. We will insert the value `16` into this heap: ![The heap before insertion](Images/Heap1.png) @@ -185,13 +185,13 @@ This corresponds to the following tree: The `(16)` was added to the first available space on the last row. -Unfortunately, the heap property is no longer satisfied because `(2)` is above `(16)` and we want higher numbers above lower numbers. (This is a max-heap.) +Unfortunately, the heap property is no longer satisfied because `(2)` is above `(16)`, and we want higher numbers above lower numbers. (This is a max-heap.) -To restore the heap property, we're going to swap `(16)` and `(2)`. +To restore the heap property, we are going to swap `(16)` and `(2)`. ![The heap before insertion](Images/Insert2.png) -We're not done yet because `(10)` is also smaller than `(16)`. We keep swapping our inserted value with its parent, until the parent is larger or we reach the top of the tree. This is called **shift-up** or **sifting** and is done after every insertion. It makes a number that is too large or too small "float up" the tree. +We are not done yet because `(10)` is also smaller than `(16)`. We keep swapping our inserted value with its parent, until the parent is larger or we reach the top of the tree. This is called **shift-up** or **sifting** and is done after every insertion. It makes a number that is too large or too small "float up" the tree. Finally, we get: @@ -199,7 +199,7 @@ Finally, we get: And now every parent is greater than its children again. -The time required for shifting up is proportional to the height of the tree so it takes **O(log n)** time. (The time it takes to append the node to the end of the array is only **O(1)**, so that doesn't slow it down.) +The time required for shifting up is proportional to the height of the tree, so it takes **O(log n)** time. (The time it takes to append the node to the end of the array is only **O(1)**, so that does not slow it down.) ## Removing the root @@ -211,7 +211,7 @@ What happens to the empty spot at the top? ![The root is gone](Images/Remove1.png) -When inserting, we put the new value at the end of the array. Here, we'll do the opposite: we're going to take the last object we have, stick it up on top of the tree, and restore the heap property. +When inserting, we put the new value at the end of the array. Here, we will do the opposite: we are going to take the last object we have, stick it up on top of the tree, and restore the heap property. ![The last node goes to the root](Images/Remove2.png) @@ -219,19 +219,19 @@ Let's look at how to **shift-down** `(1)`. To maintain the heap property for thi ![The last node goes to the root](Images/Remove3.png) -Keep shifting down until the node doesn't have any children or it is larger than both its children. For our heap we only need one more swap to restore the heap property: +Keep shifting down until the node does not have any children or it is larger than both its children. For our heap, we only need one more swap to restore the heap property: ![The last node goes to the root](Images/Remove4.png) -The time required for shifting all the way down is proportional to the height of the tree so it takes **O(log n)** time. +The time required for shifting all the way down is proportional to the height of the tree, so it takes **O(log n)** time. > **Note:** `shiftUp()` and `shiftDown()` can only fix one out-of-place element at a time. If there are multiple elements in the wrong place, you need to call these functions once for each of those elements. ## Removing any node -The vast majority of the time you'll be removing the object at the root of the heap because that's what heaps are designed for. +The vast majority of the time you will be removing the object at the root of the heap because that is what heaps are designed for. -However, it can be useful to remove an arbitrary element. This is a more general version of `remove()` and may involve either `shiftDown()` or `shiftUp()`. +However, it can be useful to remove an arbitrary element. This is a general version of `remove()` and may involve either `shiftDown()` or `shiftUp()`. Let's take the example tree again and remove `(7)`: @@ -241,13 +241,13 @@ As a reminder, the array is: [ 10, 7, 2, 5, 1 ] -As you know, removing an element could potentially invalidate the max-heap or min-heap property. To fix this, we swap the node that we're removing with the last element: +As you know, removing an element could potentially invalidate the max-heap or min-heap property. To fix this, we swap the node that we are removing with the last element: [ 10, 1, 2, 5, 7 ] -The last element is the one that we'll return; we'll call `removeLast()` to remove it from the heap. The `(1)` is now out-of-order because it's smaller than its child, `(5)`, but sits higher in the tree. We call `shiftDown()` to repair this. +The last element is the one that we will return; we will call `removeLast()` to remove it from the heap. The `(1)` is now out-of-order because it is smaller than its child, `(5)` but sits higher in the tree. We call `shiftDown()` to repair this. -However, shifting down is not the only situation we need to handle -- it may also happen that the new element must be shifted up. Consider what happens if you remove `(5)` from the following heap: +However, shifting down is not the only situation we need to handle. It may also happen that the new element must be shifted up. Consider what happens if you remove `(5)` from the following heap: ![We need to shift up](Images/Remove5.png) @@ -267,7 +267,7 @@ In code it would look like this: } ``` -We simply call `insert()` for each of the values in the array. Simple enough, but not very efficient. This takes **O(n log n)** time in total because there are **n** elements and each insertion takes **log n** time. +We simply call `insert()` for each of the values in the array. Simple enough but not very efficient. This takes **O(n log n)** time in total because there are **n** elements and each insertion takes **log n** time. If you didn't gloss over the math section, you'd have seen that for any heap the elements at array indices *n/2* to *n-1* are the leaves of the tree. We can simply skip those leaves. We only have to process the other nodes, since they are parents with one or more children and therefore may be in the wrong order. @@ -286,9 +286,9 @@ Here, `elements` is the heap's own array. We walk backwards through this array, ## Searching the heap -Heaps aren't made for fast searches, but if you want to remove an arbitrary element using `removeAtIndex()` or change the value of an element with `replace()`, then you need to obtain the index of that element somehow. Searching is one way to do this but it's kind of slow. +Heaps are not made for fast searches, but if you want to remove an arbitrary element using `removeAtIndex()` or change the value of an element with `replace()`, then you need to obtain the index of that element. Searching is one way to do this, but it is slow. -In a [binary search tree](../Binary Search Tree/) you can depend on the order of the nodes to guarantee a fast search. A heap orders its nodes differently and so a binary search won't work. You'll potentially have to look at every node in the tree. +In a [binary search tree](../Binary Search Tree/) you can depend on the order of the nodes to guarantee a fast search. A heap orders its nodes differently, so a binary search will not work. You need to look at every node in the tree. Let's take our example heap again: @@ -296,9 +296,9 @@ Let's take our example heap again: If we want to search for the index of node `(1)`, we could just step through the array `[ 10, 7, 2, 5, 1 ]` with a linear search. -But even though the heap property wasn't conceived with searching in mind, we can still take advantage of it. We know that in a max-heap a parent node is always larger than its children, so we can ignore those children (and their children, and so on...) if the parent is already smaller than the value we're looking for. +Even though the heap property was not conceived with searching in mind, we can still take advantage of it. We know that in a max-heap a parent node is always larger than its children, so we can ignore those children (and their children, and so on...) if the parent is already smaller than the value we are looking for. -Let's say we want to see if the heap contains the value `8` (it doesn't). We start at the root `(10)`. This is obviously not what we're looking for, so we recursively look at its left and right child. The left child is `(7)`. That is also not what we want, but since this is a max-heap, we know there's no point in looking at the children of `(7)`. They will always be smaller than `7` and are therefore never equal to `8`. Likewise for the right child, `(2)`. +Let's say we want to see if the heap contains the value `8` (it doesn't). We start at the root `(10)`. This is not what we are looking for, so we recursively look at its left and right child. The left child is `(7)`. That is also not what we want, but since this is a max-heap, we know there is no point in looking at the children of `(7)`. They will always be smaller than `7` and are therefore never equal to `8`; likewise, for the right child, `(2)`. Despite this small optimization, searching is still an **O(n)** operation. @@ -308,9 +308,9 @@ Despite this small optimization, searching is still an **O(n)** operation. See [Heap.swift](Heap.swift) for the implementation of these concepts in Swift. Most of the code is quite straightforward. The only tricky bits are in `shiftUp()` and `shiftDown()`. -You've seen that there are two types of heaps: a max-heap and a min-heap. The only difference between them is in how they order their nodes: largest value first or smallest value first. +You have seen that there are two types of heaps: a max-heap and a min-heap. The only difference between them is in how they order their nodes: largest value first or smallest value first. -Rather than create two different versions, `MaxHeap` and `MinHeap`, there is just one `Heap` object and it takes an `isOrderedBefore` closure. This closure contains the logic that determines the order of two values. You've probably seen this before because it's also how Swift's `sort()` works. +Rather than create two different versions, `MaxHeap` and `MinHeap`, there is just one `Heap` object and it takes an `isOrderedBefore` closure. This closure contains the logic that determines the order of two values. You have probably seen this before because it is also how Swift's `sort()` works. To make a max-heap of integers, you write: From 52855ccbd3fb95704cd6375d44f1fa22512d04e1 Mon Sep 17 00:00:00 2001 From: Parva9eh Date: Sat, 1 Apr 2017 19:38:22 -0700 Subject: [PATCH 0883/1679] Update README.markdown For an assignment in technical writings, I have revised this document. Thanks, Parvaneh --- Hash Table/README.markdown | 69 +++++++++++++++++++------------------- 1 file changed, 34 insertions(+), 35 deletions(-) diff --git a/Hash Table/README.markdown b/Hash Table/README.markdown index 4399b0f86..958c3595a 100644 --- a/Hash Table/README.markdown +++ b/Hash Table/README.markdown @@ -2,13 +2,13 @@ A hash table allows you to store and retrieve objects by a "key". -Also called dictionary, map, associative array. There are other ways to implement these, such as with a tree or even a plain array, but hash table is the most common. +A hash table is used to implement structures, such as a dictionary, a map, and an associative array. These structures can be implemented by a tree or a plain array, but it is efficient to use a hash table. -This should explain why Swift's built-in `Dictionary` type requires that keys conform to the `Hashable` protocol: internally it uses a hash table, just like the one you'll learn about here. +This should explain why Swift's built-in `Dictionary` type requires that keys conform to the `Hashable` protocol: internally it uses a hash table, like the one you will learn about here. ## How it works -At its most basic, a hash table is nothing more than an array. Initially, this array is empty. When you put a value into the hash table under a certain key, it uses that key to calculate an index in the array, like so: +A hash table is nothing more than an array. Initially, this array is empty. When you put a value into the hash table under a certain key, it uses that key to calculate an index in the array. Here is an example: ```swift hashTable["firstName"] = "Steve" @@ -48,33 +48,33 @@ hashTable["hobbies"] = "Programming Swift" +--------------+ ``` -The trick is in how the hash table calculates those array indices. That's where the hashing comes in. When you write, +The trick is how the hash table calculates those array indices. That is where the hashing comes in. When you write the following statement, ```swift hashTable["firstName"] = "Steve" ``` -the hash table takes the key `"firstName"` and asks it for its `hashValue` property. That's why keys must be `Hashable`. +the hash table takes the key `"firstName"` and asks it for its `hashValue` property. Hence, keys must be `Hashable`. -When you do `"firstName".hashValue`, it returns a big integer: -4799450059917011053. Likewise, `"hobbies".hashValue` has the hash value 4799450060928805186. (The values you see may vary.) +When you write `"firstName".hashValue`, it returns a big integer: -4799450059917011053. Likewise, `"hobbies".hashValue` has the hash value 4799450060928805186. (The values you see may vary.) -Of course, these numbers are way too big to be used as indices into our array. One of them is even negative! A common way to make these big numbers more suitable is to first make the hash positive and then take the modulo with the array size. +These numbers are big to be used as indices into our array, and one of them is even negative! A common way to make these big numbers suitable is to first make the hash positive and then take the modulo with the array size. -Our array has size 5, so the index for the `"firstName"` key becomes `abs(-4799450059917011053) % 5 = 3`. You can calculate for yourself that the array index for `"hobbies"` is 1. +Our array has size 5, so the index for the `"firstName"` key becomes `abs(-4799450059917011053) % 5 = 3`. You can calculate that the array index for `"hobbies"` is 1. -Using hashes in this manner is what makes the dictionary so efficient: to find an element in the hash table you only have to hash the key to get an array index and then look up the element in the underlying array. All these operations take a constant amount of time, so inserting, retrieving, and removing are all **O(1)**. +Using hashes in this manner is what makes the dictionary efficient: to find an element in the hash table, you must hash the key to get an array index and then look up the element in the underlying array. All these operations take a constant amount of time, so inserting, retrieving, and removing are all **O(1)**. -> **Note:** As you can see, it's hard to predict where in the array your objects end up. That's why dictionaries do not guarantee any particular order of the elements in the hash table. +> **Note:** It is difficult to predict where in the array your objects end up. Hence, dictionaries do not guarantee any particular order of the elements in the hash table. ## Avoiding collisions There is one problem: because we take the modulo of the hash value with the size of the array, it can happen that two or more keys get assigned the same array index. This is called a collision. -One way to avoid collisions is to have a very large array. That reduces the likelihood of two keys mapping to the same index. Another trick is to use a prime number for the array size. However, collisions are bound to occur so you need some way to handle them. +One way to avoid collisions is to have a large array which reduces the likelihood of two keys mapping to the same index. Another trick is to use a prime number for the array size. However, collisions are bound to occur, so you need to find a way to handle them. -Because our table is so small it's easy to show a collision. For example, the array index for the key `"lastName"` is also 3. That's a problem, as we don't want to overwrite the value that's already at this array index. +Because our table is small, it is easy to show a collision. For example, the array index for the key `"lastName"` is also 3, but we do not want to overwrite the value that is already at this array index. -There are a few ways to handle collisions. A common one is to use chaining. The array now looks as follows: +A common way to handle collisions is to use chaining. The array looks as follows: ```swift buckets: @@ -91,25 +91,25 @@ There are a few ways to handle collisions. A common one is to use chaining. The +-----+ ``` -With chaining, keys and their values are not stored directly in the array. Instead, each array element is really a list of zero or more key/value pairs. The array elements are usually called the *buckets* and the lists are called the *chains*. So here we have 5 buckets and two of these buckets have chains. The other three buckets are empty. +With chaining, keys and their values are not stored directly in the array. Instead, each array element is a list of zero or more key/value pairs. The array elements are usually called the *buckets* and the lists are called the *chains*. Here we have 5 buckets, and two of these buckets have chains. The other three buckets are empty. -If we now write the following to retrieve an item from the hash table, +If we write the following statement to retrieve an item from the hash table, ```swift let x = hashTable["lastName"] ``` -then this first hashes the key `"lastName"` to calculate the array index, which is 3. Bucket 3 has a chain, so we step through that list to find the value with the key `"lastName"`. That is done by comparing the keys, so here that involves a string comparison. The hash table sees that this key belongs to the last item in the chain and returns the corresponding value, `"Jobs"`. +it first hashes the key `"lastName"` to calculate the array index, which is 3. Since bucket 3 has a chain, we step through the list to find the value with the key `"lastName"`. This is done by comparing the keys using a string comparison. The hash table checks that the key belongs to the last item in the chain and returns the corresponding value, `"Jobs"`. -Common ways to implement this chaining mechanism are to use a linked list or another array. Technically speaking the order of the items in the chain doesn't matter, so you also can think of it as a set instead of a list. (Now you can also imagine where the term "bucket" comes from; we just dump all the objects together into the bucket.) +Common ways to implement this chaining mechanism are to use a linked list or another array. Since the order of the items in the chain does not matter, you can think of it as a set instead of a list. (Now you can also imagine where the term "bucket" comes from; we just dump all the objects together into the bucket.) -It's important that chains do not become too long or looking up items in the hash table becomes really slow. Ideally, we would have no chains at all but in practice it is impossible to avoid collisions. You can improve the odds by giving the hash table enough buckets and by using high-quality hash functions. +Chains should not become long becasuse the slow process of looking up items in the hash table. Ideally, we would have no chains at all, but in practice it is impossible to avoid collisions. You can improve the odds by giving the hash table enough buckets using high-quality hash functions. -> **Note:** An alternative to chaining is "open addressing". The idea is this: if an array index is already taken, we put the element in the next unused bucket. Of course, this approach has its own upsides and downsides. +> **Note:** An alternative to chaining is "open addressing". The idea is this: if an array index is already taken, we put the element in the next unused bucket. This approach has its own upsides and downsides. ## The code -Let's look at a basic implementation of a hash table in Swift. We'll build it up step-by-step. +Let's look at a basic implementation of a hash table in Swift. We will build it up step-by-step. ```swift public struct HashTable { @@ -127,9 +127,9 @@ public struct HashTable { } ``` -The `HashTable` is a generic container and the two generic types are named `Key` (which must be `Hashable`) and `Value`. We also define two other types: `Element` is a key/value pair for use in a chain and `Bucket` is an array of such `Elements`. +The `HashTable` is a generic container, and the two generic types are named `Key` (which must be `Hashable`) and `Value`. We also define two other types: `Element` is a key/value pair for useing in a chain, and `Bucket` is an array of such `Elements`. -The main array is named `buckets`. It has a fixed size, the so-called capacity, provided by the `init(capacity)` method. We're also keeping track of how many items have been added to the hash table using the `count` variable. +The main array is named `buckets`. It has a fixed size, the so-called capacity, provided by the `init(capacity)` method. We are also keeping track of how many items have been added to the hash table using the `count` variable. An example of how to create a new hash table object: @@ -137,7 +137,7 @@ An example of how to create a new hash table object: var hashTable = HashTable(capacity: 5) ``` -Currently the hash table doesn't do anything yet, so let's add the remaining functionality. First, add a helper method that calculates the array index for a given key: +The hash table does not do anything yet, so let's add the remaining functionality. First, add a helper method that calculates the array index for a given key: ```swift private func index(forKey key: Key) -> Int { @@ -145,9 +145,9 @@ Currently the hash table doesn't do anything yet, so let's add the remaining fun } ``` -This performs the calculation you saw earlier: it takes the absolute value of the key's `hashValue` modulo the size of the buckets array. We've put this in a function of its own because it gets used in a few different places. +This performs the calculation you saw earlier: it takes the absolute value of the key's `hashValue` modulo the size of the buckets array. We have put this in a function of its own because it gets used in a few different places. -There are four common things you'll do with a hash table or dictionary: +There are four common things you will do with a hash table or dictionary: - insert a new element - look up an element @@ -180,7 +180,7 @@ We can do all these things with a `subscript` function: } ``` -This calls three helper functions to do the actual work. Let's take a look at `value(forKey:)` first, which retrieves an object from the hash table. +This calls three helper functions to do the actual work. Let's take a look at `value(forKey:)`which retrieves an object from the hash table. ```swift public func value(forKey key: Key) -> Value? { @@ -193,10 +193,9 @@ This calls three helper functions to do the actual work. Let's take a look at `v return nil // key not in hash table } ``` +First it calls `index(forKey:)` to convert the key into an array index. That gives us the bucket number, but this bucket may be used by more than one key if there were collisions. The `value(forKey:)` loops through the chain from that bucket and compares the keys one-by-one. If found, it returns the corresponding value, otherwise it returns `nil`. -First it calls `index(forKey:)` to convert the key into an array index. That gives us the bucket number, but if there were collisions this bucket may be used by more than one key. So `value(forKey:)` loops through the chain from that bucket and compares the keys one-by-one. If found, it returns the corresponding value, otherwise it returns `nil`. - -The code to insert a new element or update an existing element lives in `updateValue(_:forKey:)`. It's a little bit more complicated: +The code to insert a new element or update an existing element lives in `updateValue(_:forKey:)`. This is more complicated: ```swift public mutating func updateValue(_ value: Value, forKey key: Key) -> Value? { @@ -218,9 +217,9 @@ The code to insert a new element or update an existing element lives in `updateV } ``` -Again, the first thing we do is convert the key into an array index to find the bucket. Then we loop through the chain for that bucket. If we find the key in the chain, it means we must update it with the new value. If the key is not in the chain, we insert the new key/value pair to the end of the chain. +Again, the first step is to convert the key into an array index to find the bucket. Then we loop through the chain for that bucket. If we find the key in the chain, we must update it with the new value. If the key is not in the chain, we insert the new key/value pair to the end of the chain. -As you can see, it's important that chains are kept short (by making the hash table large enough). Otherwise, you spend a lot of time in these `for`...`in` loops and the performance of the hash table will no longer be **O(1)** but more like **O(n)**. +As you can see, it is important to keep the chains short (by making the hash table large enough). Otherwise, you spend excessive time in these `for`...`in` loops and the performance of the hash table will no longer be **O(1)** but more like **O(n)**. Removing is similar in that again it loops through the chain: @@ -246,16 +245,16 @@ Try this stuff out in a playground. It should work just like a standard Swift `D ## Resizing the hash table -This version of `HashTable` always uses an array of a fixed size or capacity. That's fine if you've got a good idea of many items you'll be storing in the hash table. For the capacity, choose a prime number that is greater than the maximum number of items you expect to store and you're good to go. +This version of `HashTable` always uses an array of a fixed size or capacity. If you have many items to store in the hash table, for the capacity, choose a prime number greater than the maximum number of items. The *load factor* of a hash table is the percentage of the capacity that is currently used. If there are 3 items in a hash table with 5 buckets, then the load factor is `3/5 = 60%`. -If the hash table is too small and the chains are long, the load factor can become greater than 1. That's not a good idea. +If the hash table is small, and the chains are long, the load factor can become greater than 1, that is not a good idea. -If the load factor becomes too high, say > 75%, you can resize the hash table. Adding the code for this is left as an exercise for the reader. Keep in mind that making the buckets array larger will change the array indices that the keys map to! To account for this, you'll have to insert all the elements again after resizing the array. +If the load factor becomes high, greater than 75%, you can resize the hash table. Adding the code for this condition is left as an exercise for the reader. Keep in mind that making the buckets array larger will change the array indices that the keys map to! This requires you to insert all the elements again after resizing the array. ## Where to go from here? -`HashTable` is quite basic. It might be fun to integrate it better with the Swift standard library by making it a `SequenceType`, for example. +`HashTable` is quite basic. It might be efficient to integrate it with the Swift standard library by making it a `SequenceType`. *Written for Swift Algorithm Club by Matthijs Hollemans* From 7010d4ff4e28871cd06067aad15dcde031e745c8 Mon Sep 17 00:00:00 2001 From: Marwan Alani Date: Sun, 2 Apr 2017 18:28:48 -0400 Subject: [PATCH 0884/1679] Fixed an issue with links that has spaces in the address --- Graph/README.markdown | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Graph/README.markdown b/Graph/README.markdown index 1ff1a82ac..a2531e808 100644 --- a/Graph/README.markdown +++ b/Graph/README.markdown @@ -28,7 +28,7 @@ The following are also graphs: ![Tree and linked list](Images/TreeAndList.png) -On the left is a [tree](../Tree/) structure, on the right a [linked list](../Linked List/). Both can be considered graphs, but in a simpler form. After all, they have vertices (nodes) and edges (links). +On the left is a [tree](../Tree/) structure, on the right a [linked list](../Linked%20List/). Both can be considered graphs, but in a simpler form. After all, they have vertices (nodes) and edges (links). The very first graph I showed you contained *cycles*, where you can start off at a vertex, follow a path, and come back to the original vertex. A tree is a graph without such cycles. @@ -42,7 +42,7 @@ Like a tree this does not have any cycles in it (no matter where you start, ther Maybe you're shrugging your shoulders and thinking, what's the big deal? Well, it turns out that graphs are an extremely useful data structure. -If you have some programming problem where you can represent some of your data as vertices and some of it as edges between those vertices, then you can draw your problem as a graph and use well-known graph algorithms such as [breadth-first search](../Breadth-First Search/) or [depth-first search](../Depth-First Search) to find a solution. +If you have some programming problem where you can represent some of your data as vertices and some of it as edges between those vertices, then you can draw your problem as a graph and use well-known graph algorithms such as [breadth-first search](../Breadth-First%20Search/) or [depth-first search](../Depth-First%20Search) to find a solution. For example, let's say you have a list of tasks where some tasks have to wait on others before they can begin. You can model this using an acyclic directed graph: @@ -50,7 +50,7 @@ For example, let's say you have a list of tasks where some tasks have to wait on Each vertex represents a task. Here, an edge between two vertices means that the source task must be completed before the destination task can start. So task C cannot start before B and D are finished, and B nor D can start before A is finished. -Now that the problem is expressed using a graph, you can use a depth-first search to perform a [topological sort](../Topological Sort/). This will put the tasks in an optimal order so that you minimize the time spent waiting for tasks to complete. (One possible order here is A, B, D, E, C, F, G, H, I, J, K.) +Now that the problem is expressed using a graph, you can use a depth-first search to perform a [topological sort](../Topological%20Sort/). This will put the tasks in an optimal order so that you minimize the time spent waiting for tasks to complete. (One possible order here is A, B, D, E, C, F, G, H, I, J, K.) Whenever you're faced with a tough programming problem, ask yourself, "how can I express this problem using a graph?" Graphs are all about representing relationships between your data. The trick is in how you define "relationship". From 79255d2bb83cfbbcab0fb3f983bdc96e25c0bd4b Mon Sep 17 00:00:00 2001 From: Marwan Alani Date: Sun, 2 Apr 2017 19:43:48 -0400 Subject: [PATCH 0885/1679] Fixed white-space encoding in markdown links --- Heap/README.markdown | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/Heap/README.markdown b/Heap/README.markdown index 88ea25eeb..1bcb05e1b 100644 --- a/Heap/README.markdown +++ b/Heap/README.markdown @@ -1,11 +1,11 @@ # Heap -A heap is a [binary tree](../Binary Tree/) that lives inside an array, so it doesn't use parent/child pointers. The tree is partially sorted according to something called the "heap property" that determines the order of the nodes in the tree. +A heap is a [binary tree](../Binary%20Tree/) that lives inside an array, so it doesn't use parent/child pointers. The tree is partially sorted according to something called the "heap property" that determines the order of the nodes in the tree. Common uses for heap: -- For building [priority queues](../Priority Queue/). -- The heap is the data structure supporting [heap sort](../Heap Sort/). +- For building [priority queues](../Priority%20Queue/). +- The heap is the data structure supporting [heap sort](../Heap%20Sort/). - Heaps are fast for when you often need to compute the minimum (or maximum) element of a collection. - Impressing your non-programmer friends. @@ -21,7 +21,7 @@ An example: This is a max-heap because every parent node is greater than its children. `(10)` is greater than `(7)` and `(2)`. `(7)` is greater than `(5)` and `(1)`. -As a result of this heap property, a max-heap always stores its largest item at the root of the tree. For a min-heap, the root is always the smallest item in the tree. That is very useful because heaps are often used as a [priority queue](../Priority Queue/) where you want to quickly access the "most important" element. +As a result of this heap property, a max-heap always stores its largest item at the root of the tree. For a min-heap, the root is always the smallest item in the tree. That is very useful because heaps are often used as a [priority queue](../Priority%20Queue/) where you want to quickly access the "most important" element. > **Note:** You can't really say anything else about the sort order of the heap. For example, in a max-heap the maximum element is always at index 0 but the minimum element isn’t necessarily the last one -- the only guarantee you have is that it is one of the leaf nodes, but not which one. @@ -29,11 +29,11 @@ As a result of this heap property, a max-heap always stores its largest item at A heap isn't intended to be a replacement for a binary search tree. But there are many similarities between the two and also some differences. Here are some of the bigger differences: -**Order of the nodes.** In a [binary search tree (BST)](../Binary Search Tree/), the left child must always be smaller than its parent and the right child must be greater. This is not true for a heap. In max-heap both children must be smaller; in a min-heap they both must be greater. +**Order of the nodes.** In a [binary search tree (BST)](../Binary%20Search%20Tree/), the left child must always be smaller than its parent and the right child must be greater. This is not true for a heap. In max-heap both children must be smaller; in a min-heap they both must be greater. **Memory.** Traditional trees take up more memory than just the data they store. You need to allocate additional storage for the node objects and pointers to the left/right child nodes. A heap only uses a plain array for storage and uses no pointers. -**Balancing.** A binary search tree must be "balanced" so that most operations have **O(log n)** performance. You can either insert and delete your data in a random order or use something like an [AVL tree](../AVL Tree/) or [red-black tree](../Red-Black Tree/). But with heaps we don't actually need the entire tree to be sorted. We just want the heap property to be fulfilled, and so balancing isn't an issue. Because of the way the heap is structured, heaps can guarantee **O(log n)** performance. +**Balancing.** A binary search tree must be "balanced" so that most operations have **O(log n)** performance. You can either insert and delete your data in a random order or use something like an [AVL tree](../AVL%20Tree/) or [red-black tree](../Red-Black%20Tree/). But with heaps we don't actually need the entire tree to be sorted. We just want the heap property to be fulfilled, and so balancing isn't an issue. Because of the way the heap is structured, heaps can guarantee **O(log n)** performance. **Searching.** Searching a binary tree is really fast -- that's its whole purpose. In a heap, searching is slow. The purpose of a heap is to always put the largest (or smallest) node at the front, and to allow relatively fast inserts and deletes. Searching isn't a top priority. @@ -54,7 +54,7 @@ If `i` is the index of a node, then the following formulas give the array indice parent(i) = floor((i - 1)/2) left(i) = 2i + 1 right(i) = 2i + 2 - + Note that `right(i)` is simply `left(i) + 1`. The left and right nodes are always stored right next to each other. Let's use these formulas on the example. Fill in the array index and we should get the positions of the parent and child nodes in the array: @@ -63,7 +63,7 @@ Let's use these formulas on the example. Fill in the array index and we should g |------|-------------|--------------|------------|-------------| | 10 | 0 | -1 | 1 | 2 | | 7 | 1 | 0 | 3 | 4 | -| 2 | 2 | 0 | 5 | 6 | +| 2 | 2 | 0 | 5 | 6 | | 5 | 3 | 1 | 7 | 8 | | 1 | 4 | 1 | 9 | 10 | @@ -76,7 +76,7 @@ Recall that in a max-heap, the parent's value is always greater than (or equal t ```swift array[parent(i)] >= array[i] ``` - + Verify that this heap property holds for the array from the example heap. As you can see, these equations let us find the parent or child index for any node without the need for pointers. True, it's slightly more complicated than just dereferencing a pointer but that's the tradeoff: we save memory space but pay with extra computations. Fortunately, the computations are fast and only take **O(1)** time. @@ -104,14 +104,14 @@ You can’t start a new level unless the current lowest level is completely full Pop quiz! Let's say we have the array: [ 10, 14, 25, 33, 81, 82, 99 ] - + Is this a valid heap? The answer is yes! A sorted array from low-to-high is a valid min-heap. We can draw this heap as follows: ![A sorted array is a valid heap](Images/SortedArray.png) The heap property holds for each node because a parent is always smaller than its children. (Verify for yourself that an array sorted from high-to-low is always a valid max-heap.) -> **Note:** But not every min-heap is necessarily a sorted array! It only works one way... To turn a heap back into a sorted array, you need to use [heap sort](../Heap Sort/). +> **Note:** But not every min-heap is necessarily a sorted array! It only works one way... To turn a heap back into a sorted array, you need to use [heap sort](../Heap%20Sort/). ## More math! @@ -129,7 +129,7 @@ If the lowest level is completely full, then that level contains *2^h* nodes. Th The total number of nodes *n* in the entire heap is therefore *2^(h+1) - 1*. In the example, `2^4 - 1 = 16 - 1 = 15`. -There are at most *ceil(n/2^(h+1))* nodes of height *h* in an *n*-element heap. +There are at most *ceil(n/2^(h+1))* nodes of height *h* in an *n*-element heap. The leaf nodes are always located at array indices *floor(n/2)* to *n-1*. We will make use of this fact to quickly build up the heap from an array. Verify this for the example if you don't believe it. ;-) @@ -141,7 +141,7 @@ There are two primitive operations necessary to make sure the heap is a valid ma - `shiftUp()`: If the element is greater (max-heap) or smaller (min-heap) than its parent, it needs to be swapped with the parent. This makes it move up the tree. -- `shiftDown()`. If the element is smaller (max-heap) or greater (min-heap) than its children, it needs to move down the tree. This operation is also called "heapify". +- `shiftDown()`. If the element is smaller (max-heap) or greater (min-heap) than its children, it needs to move down the tree. This operation is also called "heapify". Shifting up or down is a recursive procedure that takes **O(log n)** time. @@ -161,7 +161,7 @@ All of the above take time **O(log n)** because shifting up or down is the most - `buildHeap(array)`: Converts an (unsorted) array into a heap by repeatedly calling `insert()`. If you’re smart about this, it can be done in **O(n)** time. -- [Heap sort](../Heap Sort/). Since the heap is really an array, we can use its unique properties to sort the array from low to high. Time: **O(n lg n).** +- [Heap sort](../Heap%20Sort/). Since the heap is really an array, we can use its unique properties to sort the array from low to high. Time: **O(n lg n).** The heap also has a `peek()` function that returns the maximum (max-heap) or minimum (min-heap) element, without removing it from the heap. Time: **O(1)**. @@ -187,7 +187,7 @@ The `(16)` was added to the first available space on the last row. Unfortunately, the heap property is no longer satisfied because `(2)` is above `(16)` and we want higher numbers above lower numbers. (This is a max-heap.) -To restore the heap property, we're going to swap `(16)` and `(2)`. +To restore the heap property, we're going to swap `(16)` and `(2)`. ![The heap before insertion](Images/Insert2.png) @@ -211,7 +211,7 @@ What happens to the empty spot at the top? ![The root is gone](Images/Remove1.png) -When inserting, we put the new value at the end of the array. Here, we'll do the opposite: we're going to take the last object we have, stick it up on top of the tree, and restore the heap property. +When inserting, we put the new value at the end of the array. Here, we'll do the opposite: we're going to take the last object we have, stick it up on top of the tree, and restore the heap property. ![The last node goes to the root](Images/Remove2.png) @@ -223,7 +223,7 @@ Keep shifting down until the node doesn't have any children or it is larger than ![The last node goes to the root](Images/Remove4.png) -The time required for shifting all the way down is proportional to the height of the tree so it takes **O(log n)** time. +The time required for shifting all the way down is proportional to the height of the tree so it takes **O(log n)** time. > **Note:** `shiftUp()` and `shiftDown()` can only fix one out-of-place element at a time. If there are multiple elements in the wrong place, you need to call these functions once for each of those elements. @@ -269,7 +269,7 @@ In code it would look like this: We simply call `insert()` for each of the values in the array. Simple enough, but not very efficient. This takes **O(n log n)** time in total because there are **n** elements and each insertion takes **log n** time. -If you didn't gloss over the math section, you'd have seen that for any heap the elements at array indices *n/2* to *n-1* are the leaves of the tree. We can simply skip those leaves. We only have to process the other nodes, since they are parents with one or more children and therefore may be in the wrong order. +If you didn't gloss over the math section, you'd have seen that for any heap the elements at array indices *n/2* to *n-1* are the leaves of the tree. We can simply skip those leaves. We only have to process the other nodes, since they are parents with one or more children and therefore may be in the wrong order. In code: @@ -288,7 +288,7 @@ Here, `elements` is the heap's own array. We walk backwards through this array, Heaps aren't made for fast searches, but if you want to remove an arbitrary element using `removeAtIndex()` or change the value of an element with `replace()`, then you need to obtain the index of that element somehow. Searching is one way to do this but it's kind of slow. -In a [binary search tree](../Binary Search Tree/) you can depend on the order of the nodes to guarantee a fast search. A heap orders its nodes differently and so a binary search won't work. You'll potentially have to look at every node in the tree. +In a [binary search tree](../Binary%20Search%20Tree/) you can depend on the order of the nodes to guarantee a fast search. A heap orders its nodes differently and so a binary search won't work. You'll potentially have to look at every node in the tree. Let's take our example heap again: @@ -302,7 +302,7 @@ Let's say we want to see if the heap contains the value `8` (it doesn't). We sta Despite this small optimization, searching is still an **O(n)** operation. -> **Note:** There is away to turn lookups into a **O(1)** operation by keeping an additional dictionary that maps node values to indices. This may be worth doing if you often need to call `replace()` to change the "priority" of objects in a [priority queue](../Priority Queue/) that's built on a heap. +> **Note:** There is away to turn lookups into a **O(1)** operation by keeping an additional dictionary that maps node values to indices. This may be worth doing if you often need to call `replace()` to change the "priority" of objects in a [priority queue](../Priority%20Queue/) that's built on a heap. ## The code From bdb1b157cc2698b3e211069475399ef19958261e Mon Sep 17 00:00:00 2001 From: Jacopo Date: Mon, 3 Apr 2017 21:26:14 +0100 Subject: [PATCH 0886/1679] Minimum Coin Change Problem - Dynamic Programming in Swift --- MinimumCoinChange/LICENSE | 201 ++++++++++++++++++ MinimumCoinChange/Package.swift | 7 + MinimumCoinChange/README.md | 41 ++++ .../Sources/MinimumCoinChange.swift | 76 +++++++ MinimumCoinChange/Tests/LinuxMain.swift | 6 + .../MinimumCoinChangeTests.swift | 21 ++ MinimumCoinChange/eurocoins.gif | Bin 0 -> 90051 bytes 7 files changed, 352 insertions(+) create mode 100755 MinimumCoinChange/LICENSE create mode 100644 MinimumCoinChange/Package.swift create mode 100755 MinimumCoinChange/README.md create mode 100644 MinimumCoinChange/Sources/MinimumCoinChange.swift create mode 100644 MinimumCoinChange/Tests/LinuxMain.swift create mode 100644 MinimumCoinChange/Tests/MinimumCoinChangeTests/MinimumCoinChangeTests.swift create mode 100644 MinimumCoinChange/eurocoins.gif diff --git a/MinimumCoinChange/LICENSE b/MinimumCoinChange/LICENSE new file mode 100755 index 000000000..8dada3eda --- /dev/null +++ b/MinimumCoinChange/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/MinimumCoinChange/Package.swift b/MinimumCoinChange/Package.swift new file mode 100644 index 000000000..749073782 --- /dev/null +++ b/MinimumCoinChange/Package.swift @@ -0,0 +1,7 @@ +// swift-tools-version:3.1 + +import PackageDescription + +let package = Package( + name: "MinimumCoinChange" +) diff --git a/MinimumCoinChange/README.md b/MinimumCoinChange/README.md new file mode 100755 index 000000000..c9cd71cd1 --- /dev/null +++ b/MinimumCoinChange/README.md @@ -0,0 +1,41 @@ +# Minimum Coin Change +Minimum Coin Change problem algorithm implemented in Swift comparing dynamic programming algorithm design to traditional greedy approach. + +Written for Swift Algorithm Club by Jacopo Mangiavacchi + +![Coins](eurocoins.gif) + +# Introduction + +In the traditional coin change problem you have to find all the different ways to change some given money in a particular amount of coins using a given amount of set of coins (i.e. 1 cent, 2 cents, 5 cents, 10 cents etc.). + +For example using Euro cents the total of 4 cents value of money can be changed in these possible ways: + +- Four 1 cent coins +- Two 2 cent coins +- One 2 cent coin and two 1 cent coins + +The minimum coin change problem is a variation of the generic coin change problem where you need to find the best option for changing the money returning the less number of coins. + +For example using Euro cents the best possible change for 4 cents are two 2 cent coins with a total of two coins. + + +# Greedy Solution + +A simple approach for implementing the Minimum Coin Change algorithm in a very efficient way is to start subtracting from the input value the greater possible coin value from the given amount of set of coins available and iterate subtracting the next greater possible coin value on the resulting difference. + +For example from the total of 4 Euro cents of the example above you can subtract initially 2 cents as the other biggest coins value (from 5 cents to above) are to bigger for the current 4 Euro cent value. Once used the first 2 cents coin you iterate again with the same logic for the rest of 2 cents and select another 2 cents coin and finally return the two 2 cents coins as the best change. + +Most of the time the result for this greedy approach is optimal but for some set of coins the result will not be the optimal. + +Indeed, if we use the a set of these three different coins set with values 1, 3 and 4 and execute this greedy algorithm for asking the best change for the value 6 we will get one coin of 4 and two coins of 1 instead of two coins of 3. + + +# Dynamic Programming Solution + +A classic dynamic programming strategy will iterate selecting in order a possible coin from the given amount of set of coins and finding using recursive calls the minimum coin change on the difference from the passed value and the selected coin. For any interaction the algorithm select from all possible combinations the one with the less number of coins used. + +The dynamic programming approach will always select the optimal change but it will require a number of steps that is at least quadratic in the goal amount to change. + +In this Swift implementation in order to optimize the overall performance we use an internal data structure for caching the result for best minimum coin change for previous values. + diff --git a/MinimumCoinChange/Sources/MinimumCoinChange.swift b/MinimumCoinChange/Sources/MinimumCoinChange.swift new file mode 100644 index 000000000..db7edecbe --- /dev/null +++ b/MinimumCoinChange/Sources/MinimumCoinChange.swift @@ -0,0 +1,76 @@ +// +// Minimum Coin Change Problem +// Compare Greedy Algorithm and Dynamic Programming Algorithm in Swift +// +// Created by Jacopo Mangiavacchi on 04/03/17. +// + +import Foundation + +public struct MinimumCoinChange { + private let sortedCoinSet: [Int] + private var cache: [Int : [Int]] + + public init(coinSet: [Int]) { + self.sortedCoinSet = coinSet.sorted(by: { $0 > $1} ) + self.cache = [:] + } + + //Greedy Algorithm + public func changeGreedy(_ value: Int) -> [Int] { + var change: [Int] = [] + var newValue = value + + for coin in sortedCoinSet { + while newValue - coin >= 0 { + change.append(coin) + newValue -= coin + } + + if newValue == 0 { + break + } + } + + return change + } + + //Dynamic Programming Algorithm + public mutating func changeDynamic(_ value: Int) -> [Int] { + if value <= 0 { + return [] + } + + if let cached = cache[value] { + return cached + } + + var change: [Int] = [] + + var potentialChangeArray: [[Int]] = [] + + for coin in sortedCoinSet { + if value - coin >= 0 { + var potentialChange: [Int] = [] + potentialChange.append(coin) + let newPotentialValue = value - coin + + if value > 0 { + potentialChange.append(contentsOf: changeDynamic(newPotentialValue)) + } + + //print("value: \(value) coin: \(coin) potentialChange: \(potentialChange)") + potentialChangeArray.append(potentialChange) + } + } + + if potentialChangeArray.count > 0 { + let sortedPotentialChangeArray = potentialChangeArray.sorted(by: { $0.count < $1.count }) + change = sortedPotentialChangeArray[0] + } + + cache[value] = change + return change + } +} + diff --git a/MinimumCoinChange/Tests/LinuxMain.swift b/MinimumCoinChange/Tests/LinuxMain.swift new file mode 100644 index 000000000..db61c6011 --- /dev/null +++ b/MinimumCoinChange/Tests/LinuxMain.swift @@ -0,0 +1,6 @@ +import XCTest +@testable import MinimumCoinChangeTests + +XCTMain([ + testCase(MinimumCoinChangeTests.allTests), +]) diff --git a/MinimumCoinChange/Tests/MinimumCoinChangeTests/MinimumCoinChangeTests.swift b/MinimumCoinChange/Tests/MinimumCoinChangeTests/MinimumCoinChangeTests.swift new file mode 100644 index 000000000..86c9007ba --- /dev/null +++ b/MinimumCoinChange/Tests/MinimumCoinChangeTests/MinimumCoinChangeTests.swift @@ -0,0 +1,21 @@ +import XCTest +@testable import MinimumCoinChange + +class MinimumCoinChangeTests: XCTestCase { + func testExample() { + var mcc = MinimumCoinChange(coinSet: [1, 2, 5, 10, 20, 25]) + + for i in 0..<100 { + let greedy = mcc.changeGreedy(i) + let dynamic = mcc.changeDynamic(i) + + if greedy.count != dynamic.count { + print("\(i): greedy = \(greedy) dynamic = \(dynamic)") + } + } + } + + static var allTests = [ + ("testExample", testExample), + ] +} diff --git a/MinimumCoinChange/eurocoins.gif b/MinimumCoinChange/eurocoins.gif new file mode 100644 index 0000000000000000000000000000000000000000..2d9e81e559071eb0b63dc82d35801e5809447612 GIT binary patch literal 90051 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

CP-d(QUGY&)`KEg`5L-~O% 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 UYwfkzW~=SC+;;2joq+%VJHCEf)Bpeg literal 0 HcmV?d00001 From 3f7aaa2799db7c94076bb3155a83811a7c596708 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Tue, 4 Apr 2017 09:19:14 +0800 Subject: [PATCH 0887/1679] fix: broken links --- AVL Tree/README.markdown | 4 +- Bounded Priority Queue/README.markdown | 2 +- Count Occurrences/README.markdown | 6 +-- Depth-First Search/README.markdown | 6 +-- Deque/README.markdown | 42 +++++++++---------- Heap Sort/README.markdown | 2 +- Huffman Coding/README.markdown | 28 ++++++------- Knuth-Morris-Pratt/README.markdown | 32 +++++++------- Kth Largest Element/README.markdown | 6 +-- .../README.markdown | 4 +- Priority Queue/README.markdown | 6 +-- Quicksort/README.markdown | 24 +++++------ Segment Tree/README.markdown | 12 +++--- Selection Sort/README.markdown | 10 ++--- 14 files changed, 92 insertions(+), 92 deletions(-) diff --git a/AVL Tree/README.markdown b/AVL Tree/README.markdown index a9218203a..c8d8d4628 100644 --- a/AVL Tree/README.markdown +++ b/AVL Tree/README.markdown @@ -53,7 +53,7 @@ For the rotation we're using the terminology: * *RotationSubtree* - subtree of the *Pivot* upon the side of rotation * *OppositeSubtree* - subtree of the *Pivot* opposite the side of rotation -Let take an example of balancing the unbalanced tree using *Right* (clockwise direction) rotation: +Let take an example of balancing the unbalanced tree using *Right* (clockwise direction) rotation: ![Rotation1](Images/RotationStep1.jpg) ![Rotation2](Images/RotationStep2.jpg) ![Rotation3](Images/RotationStep3.jpg) @@ -76,7 +76,7 @@ Insertion never needs more than 2 rotations. Removal might require up to __log(n ## The code -Most of the code in [AVLTree.swift](AVLTree.swift) is just regular [binary search tree](../Binary Search Tree/) stuff. You'll find this in any implementation of a binary search tree. For example, searching the tree is exactly the same. The only things that an AVL tree does slightly differently are inserting and deleting the nodes. +Most of the code in [AVLTree.swift](AVLTree.swift) is just regular [binary search tree](../Binary%20Search%20Tree/) stuff. You'll find this in any implementation of a binary search tree. For example, searching the tree is exactly the same. The only things that an AVL tree does slightly differently are inserting and deleting the nodes. > **Note:** If you're a bit fuzzy on the regular operations of a binary search tree, I suggest you [catch up on those first](../Binary%20Search%20Tree/). It will make the rest of the AVL tree easier to understand. diff --git a/Bounded Priority Queue/README.markdown b/Bounded Priority Queue/README.markdown index 4e4c89272..8cbaa85b2 100644 --- a/Bounded Priority Queue/README.markdown +++ b/Bounded Priority Queue/README.markdown @@ -26,7 +26,7 @@ Suppose that we wish to insert the element `G` with priority 0.1 into this BPQ. ## Implementation -While a [heap](../Heap/) may be a really simple implementation for a priority queue, a sorted [linked list](../Linked List/) allows for **O(k)** insertion and **O(1)** deletion, where **k** is the bounding number of elements. +While a [heap](../Heap/) may be a really simple implementation for a priority queue, a sorted [linked list](../Linked%20List/) allows for **O(k)** insertion and **O(1)** deletion, where **k** is the bounding number of elements. Here's how you could implement it in Swift: diff --git a/Count Occurrences/README.markdown b/Count Occurrences/README.markdown index 4c65c4219..85b77d2d0 100644 --- a/Count Occurrences/README.markdown +++ b/Count Occurrences/README.markdown @@ -36,7 +36,7 @@ func countOccurrencesOfKey(_ key: Int, inArray a: [Int]) -> Int { } return low } - + func rightBoundary() -> Int { var low = 0 var high = a.count @@ -50,12 +50,12 @@ func countOccurrencesOfKey(_ key: Int, inArray a: [Int]) -> Int { } return low } - + return rightBoundary() - leftBoundary() } ``` -Notice that the helper functions `leftBoundary()` and `rightBoundary()` are very similar to the [binary search](../Binary Search/) algorithm. The big difference is that they don't stop when they find the search key, but keep going. +Notice that the helper functions `leftBoundary()` and `rightBoundary()` are very similar to the [binary search](../Binary%20Search/) algorithm. The big difference is that they don't stop when they find the search key, but keep going. To test this algorithm, copy the code to a playground and then do: diff --git a/Depth-First Search/README.markdown b/Depth-First Search/README.markdown index 9e1a5112d..98a19e0cb 100644 --- a/Depth-First Search/README.markdown +++ b/Depth-First Search/README.markdown @@ -40,7 +40,7 @@ func depthFirstSearch(_ graph: Graph, source: Node) -> [String] { } ``` -Where a [breadth-first search](../Breadth-First Search/) visits all immediate neighbors first, a depth-first search tries to go as deep down the tree or graph as it can. +Where a [breadth-first search](../Breadth-First%20Search/) visits all immediate neighbors first, a depth-first search tries to go as deep down the tree or graph as it can. Put this code in a playground and test it like so: @@ -71,13 +71,13 @@ print(nodesExplored) ``` This will output: `["a", "b", "d", "e", "h", "f", "g", "c"]` - + ## What is DFS good for? Depth-first search can be used to solve many problems, for example: * Finding connected components of a sparse graph -* [Topological sorting](../Topological Sort/) of nodes in a graph +* [Topological sorting](../Topological%20Sort/) of nodes in a graph * Finding bridges of a graph (see: [Bridges](https://en.wikipedia.org/wiki/Bridge_(graph_theory)#Bridge-finding_algorithm)) * And lots of others! diff --git a/Deque/README.markdown b/Deque/README.markdown index 67a734576..fda1de5f8 100644 --- a/Deque/README.markdown +++ b/Deque/README.markdown @@ -9,23 +9,23 @@ Here is a very basic implementation of a deque in Swift: ```swift public struct Deque { private var array = [T]() - + public var isEmpty: Bool { return array.isEmpty } - + public var count: Int { return array.count } - + public mutating func enqueue(_ element: T) { array.append(element) } - + public mutating func enqueueFront(_ element: T) { array.insert(element, atIndex: 0) } - + public mutating func dequeue() -> T? { if isEmpty { return nil @@ -33,7 +33,7 @@ public struct Deque { return array.removeFirst() } } - + public mutating func dequeueBack() -> T? { if isEmpty { return nil @@ -41,11 +41,11 @@ public struct Deque { return array.removeLast() } } - + public func peekFront() -> T? { return array.first } - + public func peekBack() -> T? { return array.last } @@ -73,7 +73,7 @@ deque.dequeue() // 5 This particular implementation of `Deque` is simple but not very efficient. Several operations are **O(n)**, notably `enqueueFront()` and `dequeue()`. I've included it only to show the principle of what a deque does. ## A more efficient version - + The reason that `dequeue()` and `enqueueFront()` are **O(n)** is that they work on the front of the array. If you remove an element at the front of an array, what happens is that all the remaining elements need to be shifted in memory. Let's say the deque's array contains the following items: @@ -92,7 +92,7 @@ Likewise, inserting an element at the front of the array is expensive because it First, the elements `2`, `3`, and `4` are moved up by one position in the computer's memory, and then the new element `5` is inserted at the position where `2` used to be. -Why is this not an issue at for `enqueue()` and `dequeueBack()`? Well, these operations are performed at the end of the array. The way resizable arrays are implemented in Swift is by reserving a certain amount of free space at the back. +Why is this not an issue at for `enqueue()` and `dequeueBack()`? Well, these operations are performed at the end of the array. The way resizable arrays are implemented in Swift is by reserving a certain amount of free space at the back. Our initial array `[ 1, 2, 3, 4]` actually looks like this in memory: @@ -120,26 +120,26 @@ public struct Deque { private var head: Int private var capacity: Int private let originalCapacity:Int - + public init(_ capacity: Int = 10) { self.capacity = max(capacity, 1) originalCapacity = self.capacity array = [T?](repeating: nil, count: capacity) head = capacity } - + public var isEmpty: Bool { return count == 0 } - + public var count: Int { return array.count - head } - + public mutating func enqueue(_ element: T) { array.append(element) } - + public mutating func enqueueFront(_ element: T) { // this is explained below } @@ -155,7 +155,7 @@ public struct Deque { return array.removeLast() } } - + public func peekFront() -> T? { if isEmpty { return nil @@ -163,7 +163,7 @@ public struct Deque { return array[head] } } - + public func peekBack() -> T? { if isEmpty { return nil @@ -176,7 +176,7 @@ public struct Deque { It still largely looks the same -- `enqueue()` and `dequeueBack()` haven't changed -- but there are also a few important differences. The array now stores objects of type `T?` instead of just `T` because we need some way to mark array elements as being empty. -The `init` method allocates a new array that contains a certain number of `nil` values. This is the free room we have to work with at the beginning of the array. By default this creates 10 empty spots. +The `init` method allocates a new array that contains a certain number of `nil` values. This is the free room we have to work with at the beginning of the array. By default this creates 10 empty spots. The `head` variable is the index in the array of the front-most object. Since the queue is currently empty, `head` points at an index beyond the end of the array. @@ -219,7 +219,7 @@ Notice how the array has resized itself. There was no room to add the `1`, so Sw | head -> **Note:** You won't see those empty spots at the back of the array when you `print(deque.array)`. This is because Swift hides them from you. Only the ones at the front of the array show up. +> **Note:** You won't see those empty spots at the back of the array when you `print(deque.array)`. This is because Swift hides them from you. Only the ones at the front of the array show up. The `dequeue()` method does the opposite of `enqueueFront()`, it reads the value at `head`, sets the array element back to `nil`, and then moves `head` one position to the right: @@ -250,7 +250,7 @@ There is one tiny problem... If you enqueue a lot of objects at the front, you'r } ``` -If `head` equals 0, there is no room left at the front. When that happens, we add a whole bunch of new `nil` elements to the array. This is an **O(n)** operation but since this cost gets divided over all the `enqueueFront()`s, each individual call to `enqueueFront()` is still **O(1)** on average. +If `head` equals 0, there is no room left at the front. When that happens, we add a whole bunch of new `nil` elements to the array. This is an **O(n)** operation but since this cost gets divided over all the `enqueueFront()`s, each individual call to `enqueueFront()` is still **O(1)** on average. > **Note:** We also multiply the capacity by 2 each time this happens, so if your queue grows bigger and bigger, the resizing happens less often. This is also what Swift arrays automatically do at the back. @@ -302,7 +302,7 @@ This way we can strike a balance between fast enqueuing and dequeuing at the fro ## See also -Other ways to implement deque are by using a [doubly linked list](../Linked List/), a [circular buffer](../Ring Buffer/), or two [stacks](../Stack/) facing opposite directions. +Other ways to implement deque are by using a [doubly linked list](../Linked%20List/), a [circular buffer](../Ring%20Buffer/), or two [stacks](../Stack/) facing opposite directions. [A fully-featured deque implementation in Swift](https://github.com/lorentey/Deque) diff --git a/Heap Sort/README.markdown b/Heap Sort/README.markdown index 5f047f82b..7fdd8d2ca 100644 --- a/Heap Sort/README.markdown +++ b/Heap Sort/README.markdown @@ -40,7 +40,7 @@ And fix up the heap to make it valid max-heap again: As you can see, the largest items are making their way to the back. We repeat this process until we arrive at the root node and then the whole array is sorted. -> **Note:** This process is very similar to [selection sort](../Selection Sort/), which repeatedly looks for the minimum item in the remainder of the array. Extracting the minimum or maximum value is what heaps are good at. +> **Note:** This process is very similar to [selection sort](../Selection%20Sort/), which repeatedly looks for the minimum item in the remainder of the array. Extracting the minimum or maximum value is what heaps are good at. Performance of heap sort is **O(n lg n)** in best, worst, and average case. Because we modify the array directly, heap sort can be performed in-place. But it is not a stable sort: the relative order of identical elements is not preserved. diff --git a/Huffman Coding/README.markdown b/Huffman Coding/README.markdown index 6b2c0d245..4e6f75514 100644 --- a/Huffman Coding/README.markdown +++ b/Huffman Coding/README.markdown @@ -16,7 +16,7 @@ If you count how often each byte appears, you can clearly see that some bytes oc c: 2 p: 1 r: 2 e: 1 n: 2 i: 1 - + We can assign bit strings to each of these bytes. The more common a byte is, the fewer bits we assign to it. We might get something like this: space: 5 010 u: 1 11001 @@ -30,12 +30,12 @@ We can assign bit strings to each of these bytes. The more common a byte is, the Now if we replace the original bytes with these bit strings, the compressed output becomes: - 101 000 010 111 11001 0011 10001 010 0010 000 1001 11010 101 + 101 000 010 111 11001 0011 10001 010 0010 000 1001 11010 101 s o _ m u c h _ w o r d s - + 010 0010 000 0010 010 111 11011 0110 01111 010 0011 000 111 _ w o w _ m a n y _ c o m - + 11000 1001 01110 101 101 10000 000 0110 0 p r e s s i o n @@ -57,7 +57,7 @@ The edges between the nodes either say "1" or "0". These correspond to the bit-e Compression is then a matter of looping through the input bytes, and for each byte traverse the tree from the root node to that byte's leaf node. Every time we take a left branch, we emit a 1-bit. When we take a right branch, we emit a 0-bit. -For example, to go from the root node to `c`, we go right (`0`), right again (`0`), left (`1`), and left again (`1`). So the Huffman code for `c` is `0011`. +For example, to go from the root node to `c`, we go right (`0`), right again (`0`), left (`1`), and left again (`1`). So the Huffman code for `c` is `0011`. Decompression works in exactly the opposite way. It reads the compressed bits one-by-one and traverses the tree until we get to a leaf node. The value of that leaf node is the uncompressed byte. For example, if the bits are `11010`, we start at the root and go left, left again, right, left, and a final right to end up at `d`. @@ -137,7 +137,7 @@ Here are the definitions we need: ```swift class Huffman { typealias NodeIndex = Int - + struct Node { var count = 0 var index: NodeIndex = -1 @@ -152,7 +152,7 @@ class Huffman { } ``` -The tree structure is stored in the `tree` array and will be made up of `Node` objects. Since this is a [binary tree](../Binary Tree/), each node needs two children, `left` and `right`, and a reference back to its `parent` node. Unlike a typical binary tree, however, these nodes don't to use pointers to refer to each other but simple integer indices in the `tree` array. (We also store the array `index` of the node itself; the reason for this will become clear later.) +The tree structure is stored in the `tree` array and will be made up of `Node` objects. Since this is a [binary tree](../Binary%20Tree/), each node needs two children, `left` and `right`, and a reference back to its `parent` node. Unlike a typical binary tree, however, these nodes don't to use pointers to refer to each other but simple integer indices in the `tree` array. (We also store the array `index` of the node itself; the reason for this will become clear later.) Note that `tree` currently has room for 256 entries. These are for the leaf nodes because there are 256 possible byte values. Of course, not all of those may end up being used, depending on the input data. Later, we'll add more nodes as we build up the actual tree. For the moment there isn't a tree yet, just 256 separate leaf nodes with no connections between them. All the node counts are 0. @@ -183,7 +183,7 @@ Instead, we'll add a method to export the frequency table without all the pieces var byte: UInt8 = 0 var count = 0 } - + func frequencyTable() -> [Freq] { var a = [Freq]() for i in 0..<256 where tree[i].count > 0 { @@ -209,7 +209,7 @@ To build the tree, we do the following: 2. Create a new parent node that links these two nodes together. 3. This repeats over and over until only one node with no parent remains. This becomes the root node of the tree. -This is an ideal place to use a [priority queue](../Priority Queue/). A priority queue is a data structure that is optimized so that finding the minimum value is always very fast. Here, we repeatedly need to find the node with the smallest count. +This is an ideal place to use a [priority queue](../Priority%20Queue/). A priority queue is a data structure that is optimized so that finding the minimum value is always very fast. Here, we repeatedly need to find the node with the smallest count. The function `buildTree()` then becomes: @@ -233,7 +233,7 @@ The function `buildTree()` then becomes: tree[node1.index].parent = parentNode.index // 4 tree[node2.index].parent = parentNode.index - + queue.enqueue(parentNode) // 5 } @@ -286,7 +286,7 @@ Now that we know how to build the compression tree from the frequency table, we } ``` -This first calls `countByteFrequency()` to build the frequency table, then `buildTree()` to put together the compression tree. It also creates a `BitWriter` object for writing individual bits. +This first calls `countByteFrequency()` to build the frequency table, then `buildTree()` to put together the compression tree. It also creates a `BitWriter` object for writing individual bits. Then it loops through the entire input and for each byte calls `traverseTree()`. That method will step through the tree nodes and for each node write a 1 or 0 bit. Finally, we return the `BitWriter`'s data object. @@ -309,7 +309,7 @@ The interesting stuff happens in `traverseTree()`. This is a recursive method: } ``` -When we call this method from `compressData()`, the `nodeIndex` parameter is the array index of the leaf node for the byte that we're about to encode. This method recursively walks the tree from a leaf node up to the root, and then back again. +When we call this method from `compressData()`, the `nodeIndex` parameter is the array index of the leaf node for the byte that we're about to encode. This method recursively walks the tree from a leaf node up to the root, and then back again. As we're going back from the root to the leaf node, we write a 1 bit or a 0 bit for every node we encounter. If a child is the left node, we emit a 1; if it's the right node, we emit a 0. @@ -395,10 +395,10 @@ Here's how you would use the decompression method: ```swift let frequencyTable = huffman1.frequencyTable() - + let huffman2 = Huffman() let decompressedData = huffman2.decompressData(compressedData, frequencyTable: frequencyTable) - + let s2 = String(data: decompressedData, encoding: NSUTF8StringEncoding)! ``` diff --git a/Knuth-Morris-Pratt/README.markdown b/Knuth-Morris-Pratt/README.markdown index f01b87b3d..95fdea9e9 100644 --- a/Knuth-Morris-Pratt/README.markdown +++ b/Knuth-Morris-Pratt/README.markdown @@ -1,9 +1,9 @@ # Knuth-Morris-Pratt String Search -Goal: Write a linear-time string matching algorithm in Swift that returns the indexes of all the occurrencies of a given pattern. - +Goal: Write a linear-time string matching algorithm in Swift that returns the indexes of all the occurrencies of a given pattern. + In other words, we want to implement an `indexesOf(pattern: String)` extension on `String` that returns an array `[Int]` of integers, representing all occurrences' indexes of the search pattern, or `nil` if the pattern could not be found inside the string. - + For example: ```swift @@ -16,7 +16,7 @@ concert.indexesOf(ptnr: "🎻🎷") // Output: [6] The [Knuth-Morris-Pratt algorithm](https://en.wikipedia.org/wiki/Knuth–Morris–Pratt_algorithm) is considered one of the best algorithms for solving the pattern matching problem. Although in practice [Boyer-Moore](../Boyer-Moore/) is usually preferred, the algorithm that we will introduce is simpler, and has the same (linear) running time. -The idea behind the algorithm is not too different from the [naive string search](../Brute-Force String Search/) procedure. As it, Knuth-Morris-Pratt aligns the text with the pattern and goes with character comparisons from left to right. But, instead of making a shift of one character when a mismatch occurs, it uses a more intelligent way to move the pattern along the text. In fact, the algorithm features a pattern pre-processing stage where it acquires all the informations that will make the algorithm skip redundant comparisons, resulting in larger shifts. +The idea behind the algorithm is not too different from the [naive string search](../Brute-Force%20String%20Search/) procedure. As it, Knuth-Morris-Pratt aligns the text with the pattern and goes with character comparisons from left to right. But, instead of making a shift of one character when a mismatch occurs, it uses a more intelligent way to move the pattern along the text. In fact, the algorithm features a pattern pre-processing stage where it acquires all the informations that will make the algorithm skip redundant comparisons, resulting in larger shifts. The pre-processing stage produces an array (called `suffixPrefix` in the code) of integers in which every element `suffixPrefix[i]` records the length of the longest proper suffix of `P[0...i]` (where `P` is the pattern) that matches a prefix of `P`. In other words, `suffixPrefix[i]` is the longest proper substring of `P` that ends at position `i` and that is a prefix of `P`. Just a quick example. Consider `P = "abadfryaabsabadffg"`, then `suffixPrefix[4] = 0`, `suffixPrefix[9] = 2`, `suffixPrefix[14] = 4`. There are different ways to obtain the values of `SuffixPrefix` array. We will use the method based on the [Z-Algorithm](../Z-Algorithm/). This function takes in input the pattern and produces an array of integers. Each element represents the length of the longest substring starting at position `i` of `P` and that matches a prefix of `P`. You can notice that the two arrays are similar, they record the same informations but on the different places. We only have to find a method to map `Z[i]` to `suffixPrefix[j]`. It is not that difficult and this is the code that will do for us: @@ -93,10 +93,10 @@ extension String { ``` Let's make an example reasoning with the code above. Let's consider the string `P = ACTGACTA"`, the consequentially obtained `suffixPrefix` array equal to `[0, 0, 0, 0, 0, 0, 3, 1]`, and the text `T = "GCACTGACTGACTGACTAG"`. The algorithm begins with the text and the pattern aligned like below. We have to compare `T[0]` with `P[0]`. - + 1 0123456789012345678 - text: GCACTGACTGACTGACTAG + text: GCACTGACTGACTGACTAG textIndex: ^ pattern: ACTGACTA patternIndex: ^ @@ -104,54 +104,54 @@ Let's make an example reasoning with the code above. Let's consider the string ` suffixPrefix: 00000031 We have a mismatch and we move on comparing `T[1]` and `P[0]`. We have to check if a pattern occurrence is present but there is not. So, we have to shift the pattern right and by doing so we have to check `suffixPrefix[1 - 1]`. Its value is `0` and we restart by comparing `T[1]` with `P[0]`. Again a mismath occurs, so we go on with `T[2]` and `P[0]`. - + 1 0123456789012345678 text: GCACTGACTGACTGACTAG - textIndex: ^ + textIndex: ^ pattern: ACTGACTA patternIndex: ^ suffixPrefix: 00000031 This time we have a match. And it continues until position `8`. Unfortunately the length of the match is not equal to the pattern length, we cannot report an occurrence. But we are still lucky because we can use the values computed in the `suffixPrefix` array now. In fact, the length of the match is `7`, and if we look at the element `suffixPrefix[7 - 1]` we discover that is `3`. This information tell us that that the prefix of `P` matches the suffix of the susbtring `T[0...8]`. So the `suffixPrefix` array guarantees us that the two substring match and that we do not have to compare their characters, so we can shift right the pattern for more than one character! The comparisons restart from `T[9]` and `P[3]`. - + 1 0123456789012345678 - text: GCACTGACTGACTGACTAG + text: GCACTGACTGACTGACTAG textIndex: ^ pattern: ACTGACTA patternIndex: ^ suffixPrefix: 00000031 They match so we continue the compares until position `13` where a misatch occurs beetwen charcter `G` and `A`. Just like before, we are lucky and we can use the `suffixPrefix` array to shift right the pattern. - + 1 0123456789012345678 - text: GCACTGACTGACTGACTAG + text: GCACTGACTGACTGACTAG textIndex: ^ pattern: ACTGACTA patternIndex: ^ suffixPrefix: 00000031 Again, we have to compare. But this time the comparisons finally take us to an occurrence, at position `17 - 7 = 10`. - + 1 0123456789012345678 - text: GCACTGACTGACTGACTAG + text: GCACTGACTGACTGACTAG textIndex: ^ pattern: ACTGACTA patternIndex: ^ suffixPrefix: 00000031 The algorithm than tries to compare `T[18]` with `P[1]` (because we used the element `suffixPrefix[8 - 1] = 1`) but it fails and at the next iteration it ends its work. - + The pre-processing stage involves only the pattern. The running time of the Z-Algorithm is linear and takes `O(n)`, where `n` is the length of the pattern `P`. After that, the search stage does not "overshoot" the length of the text `T` (call it `m`). It can be be proved that number of comparisons of the search stage is bounded by `2 * m`. The final running time of the Knuth-Morris-Pratt algorithm is `O(n + m)`. > **Note:** To execute the code in the [KnuthMorrisPratt.swift](./KnuthMorrisPratt.swift) you have to copy the [ZAlgorithm.swift](../Z-Algorithm/ZAlgorithm.swift) file contained in the [Z-Algorithm](../Z-Algorithm/) folder. The [KnuthMorrisPratt.playground](./KnuthMorrisPratt.playground) already includes the definition of the `Zeta` function. -Credits: This code is based on the handbook ["Algorithm on String, Trees and Sequences: Computer Science and Computational Biology"](https://books.google.it/books/about/Algorithms_on_Strings_Trees_and_Sequence.html?id=Ofw5w1yuD8kC&redir_esc=y) by Dan Gusfield, Cambridge University Press, 1997. +Credits: This code is based on the handbook ["Algorithm on String, Trees and Sequences: Computer Science and Computational Biology"](https://books.google.it/books/about/Algorithms_on_Strings_Trees_and_Sequence.html?id=Ofw5w1yuD8kC&redir_esc=y) by Dan Gusfield, Cambridge University Press, 1997. *Written for Swift Algorithm Club by Matteo Dunnhofer* diff --git a/Kth Largest Element/README.markdown b/Kth Largest Element/README.markdown index d50d691a1..53bec1c1c 100644 --- a/Kth Largest Element/README.markdown +++ b/Kth Largest Element/README.markdown @@ -44,7 +44,7 @@ Of course, if you were looking for the k-th *smallest* element, you'd use `a[k]` ## A faster solution -There is a clever algorithm that combines the ideas of [binary search](../Binary Search/) and [quicksort](../Quicksort/) to arrive at an **O(n)** solution. +There is a clever algorithm that combines the ideas of [binary search](../Binary%20Search/) and [quicksort](../Quicksort/) to arrive at an **O(n)** solution. Recall that binary search splits the array in half over and over again, to quickly narrow in on the value you're searching for. That's what we'll do here too. @@ -86,7 +86,7 @@ The following function implements these ideas: ```swift public func randomizedSelect(array: [T], order k: Int) -> T { var a = array - + func randomPivot(inout a: [T], _ low: Int, _ high: Int) -> T { let pivotIndex = random(min: low, max: high) swap(&a, pivotIndex, high) @@ -120,7 +120,7 @@ public func randomizedSelect(array: [T], order k: Int) -> T { return a[low] } } - + precondition(a.count > 0) return randomizedSelect(&a, 0, a.count - 1, k) } diff --git a/Minimum Spanning Tree (Unweighted)/README.markdown b/Minimum Spanning Tree (Unweighted)/README.markdown index cfd29c987..23f18c335 100644 --- a/Minimum Spanning Tree (Unweighted)/README.markdown +++ b/Minimum Spanning Tree (Unweighted)/README.markdown @@ -16,7 +16,7 @@ Drawn as a more conventional tree it looks like this: ![An actual tree](Images/Tree.png) -To calculate the minimum spanning tree on an unweighted graph, we can use the [breadth-first search](../Breadth-First Search/) algorithm. Breadth-first search starts at a source node and traverses the graph by exploring the immediate neighbor nodes first, before moving to the next level neighbors. If we tweak this algorithm by selectively removing edges, then it can convert the graph into the minimum spanning tree. +To calculate the minimum spanning tree on an unweighted graph, we can use the [breadth-first search](../Breadth-First%20Search/) algorithm. Breadth-first search starts at a source node and traverses the graph by exploring the immediate neighbor nodes first, before moving to the next level neighbors. If we tweak this algorithm by selectively removing edges, then it can convert the graph into the minimum spanning tree. Let's step through the example. We start with the source node `a`, add it to a queue and mark it as visited. @@ -185,6 +185,6 @@ print(minimumSpanningTree) // [node: a edges: ["b", "h"]] // [node: h edges: ["g", "i"]] ``` -> **Note:** On an unweighed graph, any spanning tree is always a minimal spanning tree. This means you can also use a [depth-first search](../Depth-First Search) to find the minimum spanning tree. +> **Note:** On an unweighed graph, any spanning tree is always a minimal spanning tree. This means you can also use a [depth-first search](../Depth-First%20Search) to find the minimum spanning tree. *Written by [Chris Pilcher](https://github.com/chris-pilcher) and Matthijs Hollemans* diff --git a/Priority Queue/README.markdown b/Priority Queue/README.markdown index 8308ec16f..fbbcaa0f3 100644 --- a/Priority Queue/README.markdown +++ b/Priority Queue/README.markdown @@ -12,7 +12,7 @@ Examples of algorithms that can benefit from a priority queue: - Event-driven simulations. Each event is given a timestamp and you want events to be performed in order of their timestamps. The priority queue makes it easy to find the next event that needs to be simulated. - Dijkstra's algorithm for graph searching uses a priority queue to calculate the minimum cost. -- [Huffman coding](../Huffman Coding/) for data compression. This algorithm builds up a compression tree. It repeatedly needs to find the two nodes with the smallest frequencies that do not have a parent node yet. +- [Huffman coding](../Huffman%20Coding/) for data compression. This algorithm builds up a compression tree. It repeatedly needs to find the two nodes with the smallest frequencies that do not have a parent node yet. - A* pathfinding for artificial intelligence. - Lots of other places! @@ -31,8 +31,8 @@ Common operations on a priority queue: There are different ways to implement priority queues: -- As a [sorted array](../Ordered Array/). The most important item is at the end of the array. Downside: inserting new items is slow because they must be inserted in sorted order. -- As a balanced [binary search tree](../Binary Search Tree/). This is great for making a double-ended priority queue because it implements both "find minimum" and "find maximum" efficiently. +- As a [sorted array](../Ordered%20Array/). The most important item is at the end of the array. Downside: inserting new items is slow because they must be inserted in sorted order. +- As a balanced [binary search tree](../Binary%20Search%20Tree/). This is great for making a double-ended priority queue because it implements both "find minimum" and "find maximum" efficiently. - As a [heap](../Heap/). The heap is a natural data structure for a priority queue. In fact, the two terms are often used as synonyms. A heap is more efficient than a sorted array because a heap only has to be partially sorted. All heap operations are **O(log n)**. Here's a Swift priority queue based on a heap: diff --git a/Quicksort/README.markdown b/Quicksort/README.markdown index d359ecb5c..e0bd8e604 100644 --- a/Quicksort/README.markdown +++ b/Quicksort/README.markdown @@ -14,7 +14,7 @@ func quicksort(_ a: [T]) -> [T] { let less = a.filter { $0 < pivot } let equal = a.filter { $0 == pivot } let greater = a.filter { $0 > pivot } - + return quicksort(less) + equal + quicksort(greater) } ``` @@ -30,7 +30,7 @@ Here's how it works. When given an array, `quicksort()` splits it up into three All the elements less than the pivot go into a new array called `less`. All the elements equal to the pivot go into the `equal` array. And you guessed it, all elements greater than the pivot go into the third array, `greater`. This is why the generic type `T` must be `Comparable`, so we can compare the elements with `<`, `==`, and `>`. -Once we have these three arrays, `quicksort()` recursively sorts the `less` array and the `greater` array, then glues those sorted subarrays back together with the `equal` array to get the final result. +Once we have these three arrays, `quicksort()` recursively sorts the `less` array and the `greater` array, then glues those sorted subarrays back together with the `equal` array to get the final result. ## An example @@ -73,7 +73,7 @@ The `less` array is empty because there was no value smaller than `-1`; the othe That `greater` array was: [ 3, 2, 5 ] - + This works just the same way as before: we pick the middle element `2` as the pivot and fill up the subarrays: less: [ ] @@ -122,7 +122,7 @@ There is no guarantee that partitioning keeps the elements in the same relative [ 3, 0, 5, 2, -1, 1, 8, 8, 14, 26, 10, 27, 9 ] -The only guarantee is that to the left of the pivot are all the smaller elements and to the right are all the larger elements. Because partitioning can change the original order of equal elements, quicksort does not produce a "stable" sort (unlike [merge sort](../Merge Sort/), for example). Most of the time that's not a big deal. +The only guarantee is that to the left of the pivot are all the smaller elements and to the right are all the larger elements. Because partitioning can change the original order of equal elements, quicksort does not produce a "stable" sort (unlike [merge sort](../Merge%20Sort/), for example). Most of the time that's not a big deal. ## Lomuto's partitioning scheme @@ -133,7 +133,7 @@ Here's an implementation of Lomuto's partitioning scheme in Swift: ```swift func partitionLomuto(_ a: inout [T], low: Int, high: Int) -> Int { let pivot = a[high] - + var i = low for j in low..(_ a: inout [T], low: Int, high: Int) -> Int i += 1 } } - + (a[i], a[high]) = (a[high], a[i]) return i } @@ -168,7 +168,7 @@ After partitioning, the array looks like this: The variable `p` contains the return value of the call to `partitionLomuto()` and is 7. This is the index of the pivot element in the new array (marked with a star). -The left partition goes from 0 to `p-1` and is `[ 0, 3, 2, 1, 5, 8, -1 ]`. The right partition goes from `p+1` to the end, and is `[ 9, 10, 14, 26, 27 ]` (the fact that the right partition is already sorted is a coincidence). +The left partition goes from 0 to `p-1` and is `[ 0, 3, 2, 1, 5, 8, -1 ]`. The right partition goes from `p+1` to the end, and is `[ 9, 10, 14, 26, 27 ]` (the fact that the right partition is already sorted is a coincidence). You may notice something interesting... The value `8` occurs more than once in the array. One of those `8`s did not end up neatly in the middle but somewhere in the left partition. That's a small downside of the Lomuto algorithm as it makes quicksort slower if there are a lot of duplicate elements. @@ -281,11 +281,11 @@ func partitionHoare(_ a: inout [T], low: Int, high: Int) -> Int { let pivot = a[low] var i = low - 1 var j = high + 1 - + while true { repeat { j -= 1 } while a[j] > pivot repeat { i += 1 } while a[i] < pivot - + if i < j { swap(&a[i], &a[j]) } else { @@ -309,9 +309,9 @@ The result is: [ -1, 0, 3, 8, 2, 5, 1, 27, 10, 14, 9, 8, 26 ] -Note that this time the pivot isn't in the middle at all. Unlike with Lomuto's scheme, the return value is not necessarily the index of the pivot element in the new array. +Note that this time the pivot isn't in the middle at all. Unlike with Lomuto's scheme, the return value is not necessarily the index of the pivot element in the new array. -Instead, the array is partitioned into the regions `[low...p]` and `[p+1...high]`. Here, the return value `p` is 6, so the two partitions are `[ -1, 0, 3, 8, 2, 5, 1 ]` and `[ 27, 10, 14, 9, 8, 26 ]`. +Instead, the array is partitioned into the regions `[low...p]` and `[p+1...high]`. Here, the return value `p` is 6, so the two partitions are `[ -1, 0, 3, 8, 2, 5, 1 ]` and `[ 27, 10, 14, 9, 8, 26 ]`. The pivot is placed somewhere inside one of the two partitions, but the algorithm doesn't tell you which one or where. If the pivot value occurs more than once, then some instances may appear in the left partition and others may appear in the right partition. @@ -357,7 +357,7 @@ And again: And so on... -That's no good, because this pretty much reduces quicksort to the much slower insertion sort. For quicksort to be efficient, it needs to split the array into roughly two halves. +That's no good, because this pretty much reduces quicksort to the much slower insertion sort. For quicksort to be efficient, it needs to split the array into roughly two halves. The optimal pivot for this example would have been `4`, so we'd get: diff --git a/Segment Tree/README.markdown b/Segment Tree/README.markdown index 15b1a3227..9897c9c3b 100644 --- a/Segment Tree/README.markdown +++ b/Segment Tree/README.markdown @@ -18,7 +18,7 @@ var a = [ 20, 3, -1, 101, 14, 29, 5, 61, 99 ] We want to query this array on the interval from 3 to 7 for the function "sum". That means we do the following: 101 + 14 + 29 + 5 + 61 = 210 - + because `101` is at index 3 in the array and `61` is at index 7. So we pass all the numbers between `101` and `61` to the sum function, which adds them all up. If we had used the "min" function, the result would have been `5` because that's the smallest number in the interval from 3 to 7. Here's naive approach if our array's type is `Int` and **f** is just the sum of two integers: @@ -43,7 +43,7 @@ The main idea of segment trees is simple: we precalculate some segments in our a ## Structure of segment tree -A segment tree is just a [binary tree](../Binary Tree/) where each node is an instance of the `SegmentTree` class: +A segment tree is just a [binary tree](../Binary%20Tree/) where each node is an instance of the `SegmentTree` class: ```swift public class SegmentTree { @@ -116,18 +116,18 @@ Here's the code: if self.leftBound == leftBound && self.rightBound == rightBound { return self.value } - + guard let leftChild = leftChild else { fatalError("leftChild should not be nil") } guard let rightChild = rightChild else { fatalError("rightChild should not be nil") } - + // 2 if leftChild.rightBound < leftBound { return rightChild.query(withLeftBound: leftBound, rightBound: rightBound) - + // 3 } else if rightChild.leftBound > rightBound { return leftChild.query(withLeftBound: leftBound, rightBound: rightBound) - + // 4 } else { let leftResult = leftChild.query(withLeftBound: leftBound, rightBound: leftChild.rightBound) diff --git a/Selection Sort/README.markdown b/Selection Sort/README.markdown index e95749d14..cb8ed59c2 100644 --- a/Selection Sort/README.markdown +++ b/Selection Sort/README.markdown @@ -2,7 +2,7 @@ Goal: Sort an array from low to high (or high to low). -You are given an array of numbers and need to put them in the right order. The selection sort algorithm divides the array into two parts: the beginning of the array is sorted, while the rest of the array consists of the numbers that still remain to be sorted. +You are given an array of numbers and need to put them in the right order. The selection sort algorithm divides the array into two parts: the beginning of the array is sorted, while the rest of the array consists of the numbers that still remain to be sorted. [ ...sorted numbers... | ...unsorted numbers... ] @@ -23,7 +23,7 @@ It's called a "selection" sort, because at every step you search through the res ## An example -Let's say the numbers to sort are `[ 5, 8, 3, 4, 6 ]`. We also keep track of where the sorted portion of the array ends, denoted by the `|` symbol. +Let's say the numbers to sort are `[ 5, 8, 3, 4, 6 ]`. We also keep track of where the sorted portion of the array ends, denoted by the `|` symbol. Initially, the sorted portion is empty: @@ -65,14 +65,14 @@ func selectionSort(_ array: [Int]) -> [Int] { var a = array // 2 for x in 0 ..< a.count - 1 { // 3 - + var lowest = x for y in x + 1 ..< a.count { // 4 if a[y] < a[lowest] { lowest = y } } - + if x != lowest { // 5 swap(&a[x], &a[lowest]) } @@ -108,7 +108,7 @@ The source file [SelectionSort.swift](SelectionSort.swift) has a version of this ## Performance -Selection sort is easy to understand but it performs quite badly, **O(n^2)**. It's worse than [insertion sort](../Insertion%20Sort/) but better than [bubble sort](../Bubble Sort/). The killer is finding the lowest element in the rest of the array. This takes up a lot of time, especially since the inner loop will be performed over and over. +Selection sort is easy to understand but it performs quite badly, **O(n^2)**. It's worse than [insertion sort](../Insertion%20Sort/) but better than [bubble sort](../Bubble%20Sort/). The killer is finding the lowest element in the rest of the array. This takes up a lot of time, especially since the inner loop will be performed over and over. [Heap sort](../Heap%20Sort/) uses the same principle as selection sort but has a really fast method for finding the minimum value in the rest of the array. Its performance is **O(n log n)**. From 93cbde7ae9f22d800bb30050b504e13a652ce5a2 Mon Sep 17 00:00:00 2001 From: Marwan Alani Date: Tue, 4 Apr 2017 02:46:04 -0400 Subject: [PATCH 0888/1679] Fixed a bug when appending or inserting a node --- .../LinkedList.playground/Contents.swift | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/Linked List/LinkedList.playground/Contents.swift b/Linked List/LinkedList.playground/Contents.swift index ed46331d8..6e743ba89 100644 --- a/Linked List/LinkedList.playground/Contents.swift +++ b/Linked List/LinkedList.playground/Contents.swift @@ -73,7 +73,8 @@ public final class LinkedList { self.append(newNode) } - public func append(_ newNode: Node) { + public func append(_ node: Node) { + let newNode = LinkedListNode(value: node.value) if let lastNode = last { newNode.previous = lastNode lastNode.next = newNode @@ -104,9 +105,9 @@ public final class LinkedList { self.insert(newNode, atIndex: index) } - public func insert(_ newNode: Node, atIndex index: Int) { + public func insert(_ node: Node, atIndex index: Int) { let (prev, next) = nodesBeforeAndAfter(index: index) - + let newNode = LinkedListNode(value: node.value) newNode.previous = prev newNode.next = next prev?.next = newNode @@ -264,16 +265,16 @@ f // [Universe, Swifty] //list.removeAll() //list.isEmpty -list.remove(node: list.first!) // "Hello" +list.remove(node: list.first!) // "Universe" list.count // 2 -list[0] // "Swift" -list[1] // "World" +list[0] // "Swifty" +list[1] // "Hello" -list.removeLast() // "World" +list.removeLast() // "Hello" list.count // 1 -list[0] // "Swift" +list[0] // "Swifty" -list.remove(atIndex: 0) // "Swift" +list.remove(atIndex: 0) // "Swifty" list.count // 0 let linkedList: LinkedList = [1, 2, 3, 4] // [1, 2, 3, 4] @@ -281,7 +282,7 @@ linkedList.count // 4 linkedList[0] // 1 // Infer the type from the array -let listArrayLiteral2: LinkedList = ["Swift", "Algorithm", "Club"] -listArrayLiteral2.count // 3 -listArrayLiteral2[0] // "Swift" -listArrayLiteral2.removeLast() // "Club" +let listArrayLiteral2: LinkedList? = ["Swift", "Algorithm", "Club"] +listArrayLiteral2?.count // 3 +listArrayLiteral2?[0] // "Swift" +listArrayLiteral2?.removeLast() // "Club" From 3028c6500f4b2bf8ac4fe899f238b32f946fa879 Mon Sep 17 00:00:00 2001 From: Marwan Alani Date: Tue, 4 Apr 2017 03:07:05 -0400 Subject: [PATCH 0889/1679] Corrected comments in playground. Fixed a logic bug when inserting/appending a node --- Linked List/LinkedList.playground/Contents.swift | 8 ++++---- Linked List/LinkedList.swift | 7 ++++--- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/Linked List/LinkedList.playground/Contents.swift b/Linked List/LinkedList.playground/Contents.swift index 6e743ba89..abbb90467 100644 --- a/Linked List/LinkedList.playground/Contents.swift +++ b/Linked List/LinkedList.playground/Contents.swift @@ -282,7 +282,7 @@ linkedList.count // 4 linkedList[0] // 1 // Infer the type from the array -let listArrayLiteral2: LinkedList? = ["Swift", "Algorithm", "Club"] -listArrayLiteral2?.count // 3 -listArrayLiteral2?[0] // "Swift" -listArrayLiteral2?.removeLast() // "Club" +let listArrayLiteral2: LinkedList = ["Swift", "Algorithm", "Club"] +listArrayLiteral2.count // 3 +listArrayLiteral2[0] // "Swift" +listArrayLiteral2.removeLast() // "Club" diff --git a/Linked List/LinkedList.swift b/Linked List/LinkedList.swift index 53dc77a06..55593cdc9 100755 --- a/Linked List/LinkedList.swift +++ b/Linked List/LinkedList.swift @@ -71,7 +71,8 @@ public final class LinkedList { self.append(newNode) } - public func append(_ newNode: Node) { + public func append(_ node: Node) { + let newNode = Node(value: node.value) if let lastNode = last { newNode.previous = lastNode lastNode.next = newNode @@ -102,9 +103,9 @@ public final class LinkedList { self.insert(newNode, atIndex: index) } - public func insert(_ newNode: Node, atIndex index: Int) { + public func insert(_ node: Node, atIndex index: Int) { let (prev, next) = nodesBeforeAndAfter(index: index) - + let newNode = Node(value: node.value) newNode.previous = prev newNode.next = next prev?.next = newNode From b0204d3e0a9a84c8ddb4fdce3fa9dc8276e755ed Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Tue, 4 Apr 2017 10:08:48 +0300 Subject: [PATCH 0890/1679] Dijkstra's algorithm --- .../Dijkstra.playground/Contents.swift | 122 +++++++ .../Dijkstra.playground/contents.xcplayground | 4 + .../contents.xcworkspacedata | 7 + Dijkstra Algorithm/README.md | 23 ++ .../Screenshots/screenshot1.jpg | Bin 0 -> 214771 bytes .../Screenshots/screenshot2.jpg | Bin 0 -> 225916 bytes .../Screenshots/screenshot3.jpg | Bin 0 -> 224243 bytes .../Contents.swift | 57 ++++ .../Resources/Pause.png | Bin 0 -> 712 bytes .../Resources/Start.png | Bin 0 -> 1044 bytes .../Resources/Stop.png | Bin 0 -> 498 bytes .../Sources/CustomUI/EdgeRepresentation.swift | 109 ++++++ .../Sources/CustomUI/ErrorView.swift | 30 ++ .../Sources/CustomUI/MyShapeLayer.swift | 7 + .../Sources/CustomUI/RoundedButton.swift | 20 ++ .../Sources/CustomUI/VertexView.swift | 63 ++++ .../Sources/Graph.swift | 308 +++++++++++++++++ .../Sources/GraphColors.swift | 15 + .../Sources/GraphView.swift | 246 ++++++++++++++ .../Sources/SimpleObjects/Edge.swift | 12 + .../Sources/SimpleObjects/Vertex.swift | 62 ++++ .../Sources/Window.swift | 319 ++++++++++++++++++ .../contents.xcplayground | 4 + .../contents.xcworkspacedata | 7 + .../timeline.xctimeline | 6 + README.markdown | 1 + 26 files changed, 1422 insertions(+) create mode 100644 Dijkstra Algorithm/Dijkstra.playground/Contents.swift create mode 100644 Dijkstra Algorithm/Dijkstra.playground/contents.xcplayground create mode 100644 Dijkstra Algorithm/Dijkstra.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 Dijkstra Algorithm/README.md create mode 100644 Dijkstra Algorithm/Screenshots/screenshot1.jpg create mode 100644 Dijkstra Algorithm/Screenshots/screenshot2.jpg create mode 100644 Dijkstra Algorithm/Screenshots/screenshot3.jpg create mode 100644 Dijkstra Algorithm/VisualizedDijkstra.playground/Contents.swift create mode 100644 Dijkstra Algorithm/VisualizedDijkstra.playground/Resources/Pause.png create mode 100644 Dijkstra Algorithm/VisualizedDijkstra.playground/Resources/Start.png create mode 100644 Dijkstra Algorithm/VisualizedDijkstra.playground/Resources/Stop.png create mode 100644 Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/EdgeRepresentation.swift create mode 100644 Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/ErrorView.swift create mode 100644 Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/MyShapeLayer.swift create mode 100644 Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/RoundedButton.swift create mode 100644 Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/VertexView.swift create mode 100644 Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/Graph.swift create mode 100644 Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/GraphColors.swift create mode 100644 Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/GraphView.swift create mode 100644 Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/SimpleObjects/Edge.swift create mode 100644 Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/SimpleObjects/Vertex.swift create mode 100644 Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/Window.swift create mode 100644 Dijkstra Algorithm/VisualizedDijkstra.playground/contents.xcplayground create mode 100644 Dijkstra Algorithm/VisualizedDijkstra.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 Dijkstra Algorithm/VisualizedDijkstra.playground/timeline.xctimeline diff --git a/Dijkstra Algorithm/Dijkstra.playground/Contents.swift b/Dijkstra Algorithm/Dijkstra.playground/Contents.swift new file mode 100644 index 000000000..8d600d577 --- /dev/null +++ b/Dijkstra Algorithm/Dijkstra.playground/Contents.swift @@ -0,0 +1,122 @@ +//: Playground - noun: a place where people can play + +import Foundation +import UIKit + +open class ProductVertex: Vertex {} + +open class Vertex: Hashable, Equatable { + + open var identifier: String! + open var neighbors: [(Vertex, Double)] = [] + open var pathLengthFromStart: Double = Double.infinity + open var pathVerticesFromStart: [Vertex] = [] +// open var point: CGPoint! + + public init(identifier: String/*, point: CGPoint*/) { + self.identifier = identifier +// self.point = point + } + + open var hashValue: Int { + return self.identifier.hashValue + } + + public static func ==(lhs: Vertex, rhs: Vertex) -> Bool { + if lhs.hashValue == rhs.hashValue { + return true + } + return false + } + + open func clearCache() { + self.pathLengthFromStart = Double.infinity + self.pathVerticesFromStart = [] + } +} + +public class Dijkstra { + private var totalVertices: Set + + public init(vertices: Set) { + self.totalVertices = vertices + } + + private func clearCache() { + self.totalVertices.forEach { $0.clearCache() } + } + + public func findShortestPaths(from startVertex: Vertex) { + self.clearCache() + startVertex.pathLengthFromStart = 0 + startVertex.pathVerticesFromStart.append(startVertex) + var currentVertex: Vertex! = startVertex + while currentVertex != nil { + totalVertices.remove(currentVertex) + let filteredNeighbors = currentVertex.neighbors.filter { totalVertices.contains($0.0) } + for neighbor in filteredNeighbors { + let neighborVertex = neighbor.0 + let weight = neighbor.1 + + let theoreticNewWeight = currentVertex.pathLengthFromStart + weight + if theoreticNewWeight < neighborVertex.pathLengthFromStart { + neighborVertex.pathLengthFromStart = theoreticNewWeight + neighborVertex.pathVerticesFromStart = currentVertex.pathVerticesFromStart + neighborVertex.pathVerticesFromStart.append(neighborVertex) + } + } + if totalVertices.isEmpty { + currentVertex = nil + break + } + currentVertex = totalVertices.min { $0.pathLengthFromStart < $1.pathLengthFromStart } + } + } +} + +var _vertices: Set = Set() + +func createNotConnectedVertices() { + for i in 0..<15 { + let vertex = Vertex(identifier: "\(i)") + _vertices.insert(vertex) + } +} + +func setupConnections() { + for vertex in _vertices { + let randomEdgesCount = arc4random_uniform(4) + 1 + for _ in 0.. Vertex { + var newSet = _vertices + newSet.remove(vertex) + let offset = Int(arc4random_uniform(UInt32(newSet.count))) + let index = newSet.index(newSet.startIndex, offsetBy: offset) + return newSet[index] +} + +createNotConnectedVertices() +setupConnections() +let dijkstra = Dijkstra(vertices: _vertices) +let offset = Int(arc4random_uniform(UInt32(_vertices.count))) +let index = _vertices.index(_vertices.startIndex, offsetBy: offset) +let startVertex = _vertices[index] +dijkstra.findShortestPaths(from: startVertex) +let destinationVertex = randomVertex(except: startVertex) +destinationVertex.pathLengthFromStart +destinationVertex.pathVerticesFromStart + + diff --git a/Dijkstra Algorithm/Dijkstra.playground/contents.xcplayground b/Dijkstra Algorithm/Dijkstra.playground/contents.xcplayground new file mode 100644 index 000000000..5da2641c9 --- /dev/null +++ b/Dijkstra Algorithm/Dijkstra.playground/contents.xcplayground @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Dijkstra Algorithm/Dijkstra.playground/playground.xcworkspace/contents.xcworkspacedata b/Dijkstra Algorithm/Dijkstra.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Dijkstra Algorithm/Dijkstra.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Dijkstra Algorithm/README.md b/Dijkstra Algorithm/README.md new file mode 100644 index 000000000..872e9f851 --- /dev/null +++ b/Dijkstra Algorithm/README.md @@ -0,0 +1,23 @@ +# Dijkstra-algorithm +WWDC 2017 Scholarship Project +Created by [Taras Nikulin](https://github.com/crabman448) + +## About +Dijkstra's algorithm is used for finding shortest paths from start vertex in graph(with weighted vertices) to all other vertices. +More algorithm's description can be found in playground or on wikipedia: +[Wikipedia](https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm) + +To understand how does this algorithm works, I have created **VisualizedDijkstra.playground.** It works in auto and interactive modes. Moreover there are play/pause/stop buttons. + +If you need only realization of the algorithm without visualization then run **Dijkstra.playground.** It contains necessary classes and couple functions to create random graph for algorithm testing. + +## Demo video +Click the link: [YouTube](https://youtu.be/PPESI7et0cQ) + +## Screenshots + + + + + + diff --git a/Dijkstra Algorithm/Screenshots/screenshot1.jpg b/Dijkstra Algorithm/Screenshots/screenshot1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..390bc658224310c7720678cffd68bf1654b5c045 GIT binary patch literal 214771 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

@lrF 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 Ag8%>k literal 0 HcmV?d00001 diff --git a/Dijkstra Algorithm/Screenshots/screenshot2.jpg b/Dijkstra Algorithm/Screenshots/screenshot2.jpg new file mode 100644 index 0000000000000000000000000000000000000000..bc51046fb36bd2c77b11cf8f6bc28afd0a2faff8 GIT binary patch literal 225916 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 literal 0 HcmV?d00001 diff --git a/Dijkstra Algorithm/Screenshots/screenshot3.jpg b/Dijkstra Algorithm/Screenshots/screenshot3.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e9f7a1207f315e8f5aa20c72f3264c65edafd3a8 GIT binary patch literal 224243 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 literal 0 HcmV?d00001 diff --git a/Dijkstra Algorithm/VisualizedDijkstra.playground/Contents.swift b/Dijkstra Algorithm/VisualizedDijkstra.playground/Contents.swift new file mode 100644 index 000000000..e4b3e6732 --- /dev/null +++ b/Dijkstra Algorithm/VisualizedDijkstra.playground/Contents.swift @@ -0,0 +1,57 @@ +/*: + ## Dijkstra's algorithm visualization + This playground is about the [Dijkstra's algorithm](https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm). + Plyground works in 2 modes: + * Auto visualization + * Interactive visualization + + */ +import UIKit +import PlaygroundSupport +/*: + First of all, let's set up colors for our window and graph. The visited color will be applied to visited vertices. The checking color will be applied to an edge and an edge neighbor every time the algorithm is checking some vertex neighbors. And default colors are just initial colors for elements. + */ +GraphColors.sharedInstance.visitedColor = #colorLiteral(red: 0, green: 0.5898008943, blue: 1, alpha: 1) +GraphColors.sharedInstance.checkingColor = #colorLiteral(red: 0.9411764741, green: 0.4980392158, blue: 0.3529411852, alpha: 1) +GraphColors.sharedInstance.defaultEdgeColor = #colorLiteral(red: 0.721568644, green: 0.8862745166, blue: 0.5921568871, alpha: 1) +GraphColors.sharedInstance.defaultVertexColor = #colorLiteral(red: 0.721568644, green: 0.8862745166, blue: 0.5921568871, alpha: 1) + +GraphColors.sharedInstance.mainWindowBackgroundColor = #colorLiteral(red: 0.921431005, green: 0.9214526415, blue: 0.9214410186, alpha: 1) +GraphColors.sharedInstance.topViewBackgroundColor = #colorLiteral(red: 1, green: 0.4932718873, blue: 0.4739984274, alpha: 1) +GraphColors.sharedInstance.buttonsBackgroundColor = #colorLiteral(red: 0, green: 0.3285208941, blue: 0.5748849511, alpha: 1) +GraphColors.sharedInstance.graphBackgroundColor = #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1) +/*: + Now, we need to create some graph. You can create graph with any vertices amount but I aware you from setting up too many, otherwise it will be hard to place all of them nicely on the screen. Also, you can change the animations' duration: slow down or speed up. + */ +let graph = Graph(verticesCount: 6) +graph.interactiveNeighborCheckAnimationDuration = 1.2 +graph.visualizationNeighborCheckAnimationDuration = 1.2 +/*: + Now, let's configure the graph's visual representation by passing the virtual graph to our window. For better perception open live view in full screen. + */ +let screenBounds = UIScreen.main.bounds +let frame = CGRect(x: 0, y: 0, width: screenBounds.width * 0.8, height: screenBounds.height * 0.8) +let window = Window(frame: frame) +window.configure(graph: graph) +PlaygroundPage.current.liveView = window +/*: + **Great!** + + Now we have graph on the screen. It is beautiful, isn't it? ;) Before the visualization starts, I recommend you to move vertices around the screen using you finger to be sure that all vertices and edges are properly visible. + + And a final step! Before you will see the visualization **(by pressing "Visualization" button),** please, read explanation of how the Dijkstra's algorithm works. + + Algorithm's flow: + First of all, this program randomly decides which vertex will be the start one, then the program assigns a zero value to the start vertex path length from the start. + + Then the algorithm repeats following cycle until all vertices are marked as visited. + Cycle: + 1) From the non-visited vertices the algorithm picks a vertex with the shortest path length from the start (if there are more than one vertex with the same shortest path value, then algorithm picks any of them) + 2) The algorithm marks picked vertex as visited. + 3) The algorithm check all of its neighbors. If the current vertex path length from the start plus an edge weight to a neighbor less than the neighbor current path length from the start, than it assigns new path length from the start to the neihgbor. + When all vertices are marked as visited, the algorithm's job is done. Now, you can see the shortest path from the start for every vertex by pressing the one you are interested in. + + Now, try yourself at the Dijkstra's algorithm. Press **"Interactive" button.** The program will mark the start vertex as visited and calculate new paths for its neighbors. You have to pick next vertex for the algorithm to check. If you are wrong, you will see a message on the screen. + + Good luck and have fun! ;) + */ diff --git a/Dijkstra Algorithm/VisualizedDijkstra.playground/Resources/Pause.png b/Dijkstra Algorithm/VisualizedDijkstra.playground/Resources/Pause.png new file mode 100644 index 0000000000000000000000000000000000000000..12a5d49228a5ed6708e3478435ea0c60885c958f GIT binary patch literal 712 zcmeAS@N?(olHy`uVBq!ia0vp^6(G#P1|%(0%q{^b#^NA%Cx&(BWL`2bFg1C)IEGX( zzP)&mmqCH&utUQCxs8f{HfWVMXq*p literal 0 HcmV?d00001 diff --git a/Dijkstra Algorithm/VisualizedDijkstra.playground/Resources/Start.png b/Dijkstra Algorithm/VisualizedDijkstra.playground/Resources/Start.png new file mode 100644 index 0000000000000000000000000000000000000000..3ab9556297d800bdd36cdbc8f1a256467230cab9 GIT binary patch literal 1044 zcmeAS@N?(olHy`uVBq!ia0vp^6(G#P1|%(0%q{^b#^NA%Cx&(BWL`2bFrV{uaSW+o ze0w)L@3sR^YvAq|hc<1|I~zH3wb+gh-PeZvlV%-HS6HBXw%|~;(9`t1^UptTtf{?Q z(L3`%(`xYx%0k}XmonK3ec^udOZS4Z!}?HjJLbE_U)WyUQ(aKqa__Ru4!#oq3+xlp zw>P|F{N-c#(C&h+vpT~vJ;q(GFGBYAlsar@naenRx5x{z1;tmnt})lDmM})V6kD*q zLGS9S8|)=2C9END!xktn$ezmcjrlD{?SJ+sH|&>x{l4kP`M-7bPjZsp7BcBFzP4tK z@|3tD)@Ukr!E4c?Z9Ho>HiQYWZe>sCW!*CA#0p!+Y@G#DU7X$uMkF(?RpHAze?W>m zLv>@IJHxdI2kp-3Rze$&F-3Xml)5DJvVVDSz`>u%#`MdH{)~g`UWfF*lWb(QWBqdG zK(GU|&a>OOC+=r7)Hi(1)5vHz`YW=%f$fKIS?$v7jE3uTe$U_C!d4+)^4>4}0>gX5 zdGYU=q#hKX*evSn%v^J9dfk4{jE2jM!Qp1Cyaig(|8}V@U_94;`fj17$$_0QPhaad zvh9#rQa$u>?*WXSH7}vG0di#Kjw?Mc5Zk>2W!`p^6Rx_QLbB-q6Kh7eRP%ZJg zFZ2RKbn%a`+D&XX_>ZhE7Be{z$Mdgt@&d+h?H}wO3P>fq|MB=&z7w+yyFlqBX_Eti z8;{TbEdML~&(1j#GY`B!ao9pzrE$Bv$pOWg?J}R(RtqzR3H`n18_~}+gYklMfDfR@_i+Q?DS1lN{JHKU#t~tgS;khN)H^G$efY+m6SzN0N z8N!6Fhl+!Z=vcoFtV1x|8LZ&Y{x-0YE%AF|ub!8sJynnC^dFi9Xc+d^gn1J4@gcZs_E z4UN3P1vVMX5)sGu9FE@4z$`tl?m#2A!3IXl_|hZsa-!ywxqaHDf!UnF)78&qol`;+ E0JOlxT>t<8 literal 0 HcmV?d00001 diff --git a/Dijkstra Algorithm/VisualizedDijkstra.playground/Resources/Stop.png b/Dijkstra Algorithm/VisualizedDijkstra.playground/Resources/Stop.png new file mode 100644 index 0000000000000000000000000000000000000000..b74585cbe2b300ac7126e7bc63c0968843432f8b GIT binary patch literal 498 zcmeAS@N?(olHy`uVBq!ia0vp^6(G#P1|%(0%q{^b#^NA%Cx&(BWL^TXLn;{G zUS{NFP~bV@aA5y)#|anj$ZWa$zH)oawF4(7G5%&_>9cP-z;vAV$VZ)s2Rj-q=CN|i zm ULH=xDyfH9%y85}Sb4q9e0I4;^asU7T literal 0 HcmV?d00001 diff --git a/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/EdgeRepresentation.swift b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/EdgeRepresentation.swift new file mode 100644 index 000000000..5ff656dab --- /dev/null +++ b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/EdgeRepresentation.swift @@ -0,0 +1,109 @@ +import UIKit + +public class EdgeRepresentation: Equatable { + private var graphColors: GraphColors = GraphColors.sharedInstance + + public private(set)var label: UILabel! + public private(set)var layer: MyShapeLayer! + + public init(from vertex1: Vertex, to vertex2: Vertex, weight: Double) { + guard let vertex1View = vertex1.view, let vertex2View = vertex2.view else { + assertionFailure("passed vertices without configured views") + return + } + let x1 = vertex1View.frame.origin.x + let y1 = vertex1View.frame.origin.y + let width1 = vertex1View.frame.width + let height1 = vertex1View.frame.height + + let x2 = vertex2View.frame.origin.x + let y2 = vertex2View.frame.origin.y + let width2 = vertex2View.frame.width + let height2 = vertex2View.frame.height + + var startPoint: CGPoint + var endPoint: CGPoint + + if y1 == y2 { + if x1 < x2 { + startPoint = CGPoint(x: x1 + width1, y: y1 + height1 / 2) + endPoint = CGPoint(x: x2, y: y2 + height2 / 2) + } else { + startPoint = CGPoint(x: x1, y: y1 + height1 / 2) + endPoint = CGPoint(x: x2 + width2, y: y2 + height2 / 2) + } + } else { + startPoint = CGPoint(x: x1 + width1 / 2, y: y1 + height1) + endPoint = CGPoint(x: x2 + width2 / 2, y: y2) + } + + let arcDiameter: CGFloat = 20 + var circleOrigin: CGPoint! + + if endPoint.x == startPoint.x { + startPoint.y -= 1 + endPoint.y += 1 + let x = startPoint.x - arcDiameter / 2 + let y = startPoint.y + ((endPoint.y - startPoint.y) / 2 * 1.25 - arcDiameter / 2) + circleOrigin = CGPoint(x: x, y: y) + } else if endPoint.y == startPoint.y { + let x = startPoint.x + ((endPoint.x - startPoint.x) / 2 * 1.25 - arcDiameter / 2) + let y = startPoint.y + ((endPoint.y - startPoint.y) / 2 * 1.25 - arcDiameter / 2) + circleOrigin = CGPoint(x: x, y: y) + } else { + startPoint.x -= 1 + endPoint.x += 1 + startPoint.y -= 1 + endPoint.y += 1 + let x = startPoint.x + ((endPoint.x - startPoint.x) / 2 * 1.25 - arcDiameter / 2) + let y = startPoint.y + ((endPoint.y - startPoint.y) / 2 * 1.25 - arcDiameter / 2) + circleOrigin = CGPoint(x: x, y: y) + } + + + let path = UIBezierPath() + path.move(to: startPoint) + path.addLine(to: endPoint) + + let label = UILabel(frame: CGRect(origin: circleOrigin, size: CGSize(width: arcDiameter, height: arcDiameter))) + label.textAlignment = .center + label.backgroundColor = self.graphColors.defaultEdgeColor + label.clipsToBounds = true + label.adjustsFontSizeToFitWidth = true + label.layer.cornerRadius = arcDiameter / 2 + label.text = "" + + let shapeLayer = MyShapeLayer() + shapeLayer.path = path.cgPath + shapeLayer.strokeColor = self.graphColors.defaultEdgeColor.cgColor + shapeLayer.fillColor = UIColor.clear.cgColor + shapeLayer.lineWidth = 2.0 + shapeLayer.startPoint = startPoint + shapeLayer.endPoint = endPoint + shapeLayer.actions = ["position" : NSNull(), "bounds" : NSNull(), "path" : NSNull()] + self.layer = shapeLayer + self.label = label + self.label.text = "\(weight)" + } + + public func setCheckingColor() { + self.layer.strokeColor = self.graphColors.checkingColor.cgColor + self.label.backgroundColor = self.graphColors.checkingColor + } + + public func setDefaultColor() { + self.layer.strokeColor = self.graphColors.defaultEdgeColor.cgColor + self.label.backgroundColor = self.graphColors.defaultEdgeColor + } + + public func setText(text: String) { + self.label.text = text + } + + public static func ==(lhs: EdgeRepresentation, rhs: EdgeRepresentation) -> Bool { + if lhs.label.hashValue == rhs.label.hashValue && lhs.layer.hashValue == rhs.layer.hashValue { + return true + } + return false + } +} diff --git a/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/ErrorView.swift b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/ErrorView.swift new file mode 100644 index 000000000..69874e5d7 --- /dev/null +++ b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/ErrorView.swift @@ -0,0 +1,30 @@ +import UIKit + +public class ErrorView: UIView { + private var label: UILabel! + public override init(frame: CGRect) { + super.init(frame: frame) + self.commonInit() + } + + public required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + private func commonInit() { + self.backgroundColor = UIColor(red: 242/255, green: 156/255, blue: 84/255, alpha: 1) + self.layer.cornerRadius = 10 + + let labelFrame = CGRect(x: 10, y: 10, width: self.frame.width - 20, height: self.frame.height - 20) + self.label = UILabel(frame: labelFrame) + self.label.numberOfLines = 0 + self.label.adjustsFontSizeToFitWidth = true + self.label.textAlignment = .center + self.label.textColor = UIColor.white + self.addSubview(self.label) + } + + public func setText(text: String) { + self.label.text = text + } +} diff --git a/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/MyShapeLayer.swift b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/MyShapeLayer.swift new file mode 100644 index 000000000..54147f5e1 --- /dev/null +++ b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/MyShapeLayer.swift @@ -0,0 +1,7 @@ +import Foundation +import UIKit + +public class MyShapeLayer: CAShapeLayer { + public var startPoint: CGPoint? + public var endPoint: CGPoint? +} diff --git a/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/RoundedButton.swift b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/RoundedButton.swift new file mode 100644 index 000000000..2647c4525 --- /dev/null +++ b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/RoundedButton.swift @@ -0,0 +1,20 @@ +import UIKit + +public class RoundedButton: UIButton { + private var graphColors: GraphColors = GraphColors.sharedInstance + + public override init(frame: CGRect) { + super.init(frame: frame) + self.commonInit() + } + + public required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + private func commonInit() { + self.backgroundColor = self.graphColors.buttonsBackgroundColor + self.titleLabel?.adjustsFontSizeToFitWidth = true + self.layer.cornerRadius = 7 + } +} diff --git a/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/VertexView.swift b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/VertexView.swift new file mode 100644 index 000000000..29c971411 --- /dev/null +++ b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/VertexView.swift @@ -0,0 +1,63 @@ +import UIKit + +public class VertexView: UIButton { + + public var vertex: Vertex? + private var idLabel: UILabel! + private var pathLengthLabel: UILabel! + private var graphColors: GraphColors = GraphColors.sharedInstance + + public required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + public override init(frame: CGRect) { + precondition(frame.height == frame.width) + precondition(frame.height >= 30) + super.init(frame: frame) + self.backgroundColor = self.graphColors.defaultVertexColor + self.layer.cornerRadius = frame.width / 2 + self.clipsToBounds = true + self.setupIdLabel() + self.setupPathLengthFromStartLabel() + } + + private func setupIdLabel() { + let x: CGFloat = self.frame.width * 0.2 + let y: CGFloat = 0 + let width: CGFloat = self.frame.width * 0.6 + let height: CGFloat = self.frame.height / 2 + let idLabelFrame = CGRect(x: x, y: y, width: width, height: height) + + self.idLabel = UILabel(frame: idLabelFrame) + self.idLabel.textAlignment = .center + self.idLabel.adjustsFontSizeToFitWidth = true + self.addSubview(self.idLabel) + } + + private func setupPathLengthFromStartLabel() { + let x: CGFloat = self.frame.width * 0.2 + let y: CGFloat = self.frame.height / 2 + let width: CGFloat = self.frame.width * 0.6 + let height: CGFloat = self.frame.height / 2 + let pathLengthLabelFrame = CGRect(x: x, y: y, width: width, height: height) + + self.pathLengthLabel = UILabel(frame: pathLengthLabelFrame) + self.pathLengthLabel.textAlignment = .center + self.pathLengthLabel.adjustsFontSizeToFitWidth = true + self.addSubview(self.pathLengthLabel) + } + + public func setIdLabel(text: String) { + self.idLabel.text = text + } + + public func setPathLengthLabel(text: String) { + self.pathLengthLabel.text = text + } + + public func setLabelsTextColor(color: UIColor) { + self.idLabel.textColor = color + self.pathLengthLabel.textColor = color + } +} diff --git a/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/Graph.swift b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/Graph.swift new file mode 100644 index 000000000..0b0b97b92 --- /dev/null +++ b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/Graph.swift @@ -0,0 +1,308 @@ +import Foundation +import UIKit + +public enum GraphState { + case initial + case autoVisualization + case interactiveVisualization + case parsing + case completed +} + +public class Graph { + private init() { } + + private var verticesCount: UInt! + private var _vertices: Set = Set() + public weak var delegate: GraphDelegate? + public var nextVertices: [Vertex] = [] + public var state: GraphState = .initial + public var pauseVisualization: Bool = false + public var stopVisualization: Bool = false + public var startVertex: Vertex! + public var interactiveNeighborCheckAnimationDuration: Double = 1.8 { + didSet { + self._interactiveOneSleepDuration = UInt32(self.interactiveNeighborCheckAnimationDuration * 1000000.0 / 3.0) + } + } + private var _interactiveOneSleepDuration: UInt32 = 600000 + + public var visualizationNeighborCheckAnimationDuration: Double = 2.25 { + didSet { + self._visualizationOneSleepDuration = UInt32(self.visualizationNeighborCheckAnimationDuration * 1000000.0 / 3.0) + } + } + private var _visualizationOneSleepDuration: UInt32 = 750000 + + public var vertices: Set { + return self._vertices + } + + public init(verticesCount: UInt) { + self.verticesCount = verticesCount + } + + public func removeGraph() { + self._vertices.removeAll() + self.startVertex = nil + } + + public func createNewGraph() { + guard self._vertices.isEmpty, self.startVertex == nil else { + assertionFailure("Clear graph before creating new one") + return + } + self.createNotConnectedVertices() + self.setupConnections() + let offset = Int(arc4random_uniform(UInt32(self._vertices.count))) + let index = self._vertices.index(self._vertices.startIndex, offsetBy: offset) + self.startVertex = self._vertices[index] + self.setVertexLevels() + } + + private func clearCache() { + self._vertices.forEach { $0.clearCache() } + } + + public func reset() { + for vertex in self._vertices { + vertex.clearCache() + } + } + + private func createNotConnectedVertices() { + for i in 0.. Vertex { + var newSet = self._vertices + newSet.remove(vertex) + let offset = Int(arc4random_uniform(UInt32(newSet.count))) + let index = newSet.index(newSet.startIndex, offsetBy: offset) + return newSet[index] + } + + private func setVertexLevels() { + self._vertices.forEach { $0.clearLevelInfo() } + guard let startVertex = self.startVertex else { + assertionFailure() + return + } + var queue: [Vertex] = [startVertex] + startVertex.levelChecked = true + + //BFS + while !queue.isEmpty { + let currentVertex = queue.first! + for edge in currentVertex.edges { + let neighbor = edge.neighbor + if !neighbor.levelChecked { + neighbor.levelChecked = true + neighbor.level = currentVertex.level + 1 + queue.append(neighbor) + } + } + queue.removeFirst() + } + } + + public func findShortestPathsWithVisualization(completion: () -> Void) { + self.clearCache() + startVertex.pathLengthFromStart = 0 + startVertex.pathVerticesFromStart.append(self.startVertex) + var currentVertex: Vertex! = self.startVertex + + var totalVertices = self._vertices + + breakableLoop: while currentVertex != nil { + totalVertices.remove(currentVertex) + while self.pauseVisualization == true { + if self.stopVisualization == true { + break breakableLoop + } + } + if self.stopVisualization == true { + break breakableLoop + } + DispatchQueue.main.async { + currentVertex.setVisitedColor() + } + usleep(750000) + currentVertex.visited = true + let filteredEdges = currentVertex.edges.filter { !$0.neighbor.visited } + for edge in filteredEdges { + let neighbor = edge.neighbor + let weight = edge.weight + let edgeRepresentation = edge.edgeRepresentation + + while self.pauseVisualization == true { + if self.stopVisualization == true { + break breakableLoop + } + } + if self.stopVisualization == true { + break breakableLoop + } + DispatchQueue.main.async { + edgeRepresentation?.setCheckingColor() + neighbor.setCheckingPathColor() + self.delegate?.willCompareVertices(startVertexPathLength: currentVertex.pathLengthFromStart, + edgePathLength: weight, + endVertexPathLength: neighbor.pathLengthFromStart) + } + usleep(self._visualizationOneSleepDuration) + + + let theoreticNewWeight = currentVertex.pathLengthFromStart + weight + + if theoreticNewWeight < neighbor.pathLengthFromStart { + while self.pauseVisualization == true { + if self.stopVisualization == true { + break breakableLoop + } + } + if self.stopVisualization == true { + break breakableLoop + } + neighbor.pathLengthFromStart = theoreticNewWeight + neighbor.pathVerticesFromStart = currentVertex.pathVerticesFromStart + neighbor.pathVerticesFromStart.append(neighbor) + } + usleep(self._visualizationOneSleepDuration) + + DispatchQueue.main.async { + self.delegate?.didFinishCompare() + edge.edgeRepresentation?.setDefaultColor() + edge.neighbor.setDefaultColor() + } + usleep(self._visualizationOneSleepDuration) + } + if totalVertices.isEmpty { + currentVertex = nil + break + } + currentVertex = totalVertices.min { $0.pathLengthFromStart < $1.pathLengthFromStart } + } + if self.stopVisualization == true { + DispatchQueue.main.async { + self.delegate?.didStop() + } + } else { + completion() + } + } + + public func parseNeighborsFor(vertex: Vertex, completion: @escaping () -> ()) { + DispatchQueue.main.async { + vertex.setVisitedColor() + } + DispatchQueue.global(qos: .background).async { + vertex.visited = true + + let nonVisitedVertices = self._vertices.filter { $0.visited == false } + if nonVisitedVertices.isEmpty { + self.state = .completed + DispatchQueue.main.async { + self.delegate?.didCompleteGraphParsing() + } + return + } + + let filteredEdges = vertex.edges.filter { !$0.neighbor.visited } + breakableLoop: for edge in filteredEdges { + while self.pauseVisualization == true { + if self.stopVisualization == true { + break breakableLoop + } + } + if self.stopVisualization == true { + break breakableLoop + } + let weight = edge.weight + let neighbor = edge.neighbor + + DispatchQueue.main.async { + edge.neighbor.setCheckingPathColor() + edge.edgeRepresentation?.setCheckingColor() + self.delegate?.willCompareVertices(startVertexPathLength: vertex.pathLengthFromStart, + edgePathLength: weight, + endVertexPathLength: neighbor.pathLengthFromStart) + } + usleep(self._interactiveOneSleepDuration) + + let theoreticNewWeight = vertex.pathLengthFromStart + weight + if theoreticNewWeight < neighbor.pathLengthFromStart { + while self.pauseVisualization == true { + if self.stopVisualization == true { + break breakableLoop + } + } + if self.stopVisualization == true { + break breakableLoop + } + neighbor.pathLengthFromStart = theoreticNewWeight + neighbor.pathVerticesFromStart = vertex.pathVerticesFromStart + neighbor.pathVerticesFromStart.append(neighbor) + } + + usleep(self._interactiveOneSleepDuration) + while self.pauseVisualization == true { + if self.stopVisualization == true { + break breakableLoop + } + } + if self.stopVisualization == true { + break breakableLoop + } + DispatchQueue.main.async { + self.delegate?.didFinishCompare() + edge.neighbor.setDefaultColor() + edge.edgeRepresentation?.setDefaultColor() + } + usleep(self._interactiveOneSleepDuration) + } + if self.stopVisualization == true { + DispatchQueue.main.async { + self.delegate?.didStop() + } + } else { + let nextVertexPathLength = nonVisitedVertices.sorted { $0.pathLengthFromStart < $1.pathLengthFromStart }.first!.pathLengthFromStart + self.nextVertices = nonVisitedVertices.filter { $0.pathLengthFromStart == nextVertexPathLength } + completion() + } + } + } + + public func didTapVertex(vertex: Vertex) { + if self.nextVertices.contains(vertex) { + self.delegate?.willStartVertexNeighborsChecking() + self.state = .parsing + self.parseNeighborsFor(vertex: vertex) { + self.state = .interactiveVisualization + self.delegate?.didFinishVertexNeighborsChecking() + } + } else { + self.delegate?.didTapWrongVertex() + } + } +} diff --git a/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/GraphColors.swift b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/GraphColors.swift new file mode 100644 index 000000000..95e9b8d74 --- /dev/null +++ b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/GraphColors.swift @@ -0,0 +1,15 @@ +import UIKit + +public class GraphColors { + public static let sharedInstance: GraphColors = GraphColors() + private init() { } + + public var mainWindowBackgroundColor: UIColor = #colorLiteral(red: 0.921431005, green: 0.9214526415, blue: 0.9214410186, alpha: 1) + public var topViewBackgroundColor: UIColor = #colorLiteral(red: 1, green: 0.4932718873, blue: 0.4739984274, alpha: 1) + public var graphBackgroundColor: UIColor = #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1) + public var defaultVertexColor: UIColor = #colorLiteral(red: 0.721568644, green: 0.8862745166, blue: 0.5921568871, alpha: 1) + public var defaultEdgeColor: UIColor = #colorLiteral(red: 0.721568644, green: 0.8862745166, blue: 0.5921568871, alpha: 1) + public var checkingColor: UIColor = #colorLiteral(red: 0.9411764741, green: 0.4980392158, blue: 0.3529411852, alpha: 1) + public var visitedColor: UIColor = #colorLiteral(red: 0, green: 0.5898008943, blue: 1, alpha: 1) + public var buttonsBackgroundColor: UIColor = #colorLiteral(red: 0, green: 0.3285208941, blue: 0.5748849511, alpha: 1) +} diff --git a/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/GraphView.swift b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/GraphView.swift new file mode 100644 index 000000000..49bc6853f --- /dev/null +++ b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/GraphView.swift @@ -0,0 +1,246 @@ +import UIKit + +public class GraphView: UIView { + private var graph: Graph! + private var panningView: VertexView? = nil + private var graphColors: GraphColors = GraphColors.sharedInstance + + public override init(frame: CGRect) { + super.init(frame: frame) + self.backgroundColor = self.graphColors.graphBackgroundColor + } + + public required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + + } + + public func configure(graph: Graph) { + self.graph = graph + } + + public func removeGraph() { + for vertex in self.graph.vertices { + if let view = vertex.view { + view.removeFromSuperview() + vertex.view = nil + } + } + for vertex in self.graph.vertices { + for edge in vertex.edges { + if let edgeRepresentation = edge.edgeRepresentation { + edgeRepresentation.layer.removeFromSuperlayer() + edgeRepresentation.label.removeFromSuperview() + edge.edgeRepresentation = nil + } + } + } + } + + public func createNewGraph() { + self.setupVertexViews() + self.setupEdgeRepresentations() + self.addGraph() + } + + public func reset() { + for vertex in self.graph.vertices { + vertex.edges.forEach { $0.edgeRepresentation?.setDefaultColor() } + vertex.setDefaultColor() + } + } + + private func addGraph() { + for vertex in self.graph.vertices { + for edge in vertex.edges { + if let edgeRepresentation = edge.edgeRepresentation { + self.layer.addSublayer(edgeRepresentation.layer) + self.addSubview(edgeRepresentation.label) + } + } + } + for vertex in self.graph.vertices { + if let view = vertex.view { + self.addSubview(view) + } + } + } + + private func setupVertexViews() { + var level = 0 + var buildViewQueue = [self.graph.startVertex!] + let itemWidth: CGFloat = 40 + while !buildViewQueue.isEmpty { + let levelItemsCount = CGFloat(buildViewQueue.count) + let xStep = (self.frame.width - levelItemsCount * itemWidth) / (levelItemsCount + 1) + var previousVertexMaxX: CGFloat = 0.0 + for vertex in buildViewQueue { + let x: CGFloat = previousVertexMaxX + xStep + let y: CGFloat = CGFloat(level * 100) + previousVertexMaxX = x + itemWidth + let frame = CGRect(x: x, y: y, width: itemWidth, height: itemWidth) + let vertexView = VertexView(frame: frame) + vertex.view = vertexView + vertexView.vertex = vertex + vertex.view?.setIdLabel(text: vertex.identifier) + vertex.view?.setPathLengthLabel(text: "\(vertex.pathLengthFromStart)") + vertex.view?.addTarget(self, action: #selector(self.didTapVertex(sender:)), for: .touchUpInside) + let panGesture = UIPanGestureRecognizer(target: self, action: #selector(self.handlePan(recognizer:))) + vertex.view?.addGestureRecognizer(panGesture) + } + level += 1 + buildViewQueue = self.graph.vertices.filter { $0.level == level } + } + } + + private var movingVertexInputEdges: [EdgeRepresentation] = [] + private var movingVertexOutputEdges: [EdgeRepresentation] = [] + + @objc private func handlePan(recognizer: UIPanGestureRecognizer) { + guard let vertexView = recognizer.view as? VertexView, let vertex = vertexView.vertex else { + return + } + if self.panningView != nil { + if self.panningView != vertexView { + return + } + } + + switch recognizer.state { + case .began: + let movingVertexViewFrame = vertexView.frame + let sizedVertexView = CGRect(x: movingVertexViewFrame.origin.x - 10, + y: movingVertexViewFrame.origin.y - 10, + width: movingVertexViewFrame.width + 20, + height: movingVertexViewFrame.height + 20) + vertex.edges.forEach { edge in + if let edgeRepresentation = edge.edgeRepresentation{ + if sizedVertexView.contains(edgeRepresentation.layer.startPoint!) { + movingVertexOutputEdges.append(edgeRepresentation) + } else { + movingVertexInputEdges.append(edgeRepresentation) + } + } + } + self.panningView = vertexView + case .changed: + if self.movingVertexOutputEdges.isEmpty && self.movingVertexInputEdges.isEmpty { + return + } + let translation = recognizer.translation(in: self) + if vertexView.frame.origin.x + translation.x <= 0 + || vertexView.frame.origin.y + translation.y <= 0 + || (vertexView.frame.origin.x + vertexView.frame.width + translation.x) >= self.frame.width + || (vertexView.frame.origin.y + vertexView.frame.height + translation.y) >= self.frame.height { + break + } + self.movingVertexInputEdges.forEach { edgeRepresentation in + let originalLabelCenter = edgeRepresentation.label.center + edgeRepresentation.label.center = CGPoint(x: originalLabelCenter.x + translation.x * 0.625, + y: originalLabelCenter.y + translation.y * 0.625) + + CATransaction.begin() + CATransaction.setValue(kCFBooleanTrue, forKey: kCATransactionDisableActions) + let newPath = self.path(fromEdgeRepresentation: edgeRepresentation, movingVertex: vertex, translation: translation, outPath: false) + edgeRepresentation.layer.path = newPath + CATransaction.commit() + + } + + self.movingVertexOutputEdges.forEach { edgeRepresentation in + let originalLabelCenter = edgeRepresentation.label.center + edgeRepresentation.label.center = CGPoint(x: originalLabelCenter.x + translation.x * 0.375, + y: originalLabelCenter.y + translation.y * 0.375) + + CATransaction.begin() + CATransaction.setValue(kCFBooleanTrue, forKey: kCATransactionDisableActions) + let newPath = self.path(fromEdgeRepresentation: edgeRepresentation, movingVertex: vertex, translation: translation, outPath: true) + edgeRepresentation.layer.path = newPath + CATransaction.commit() + } + + vertexView.center = CGPoint(x: vertexView.center.x + translation.x, + y: vertexView.center.y + translation.y) + recognizer.setTranslation(CGPoint.zero, in: self) + case .ended: + self.movingVertexInputEdges = [] + self.movingVertexOutputEdges = [] + self.panningView = nil + default: + break + } + } + + private func path(fromEdgeRepresentation edgeRepresentation: EdgeRepresentation, movingVertex: Vertex, translation: CGPoint, outPath: Bool) -> CGPath { + let bezier = UIBezierPath() + + if outPath == true { + bezier.move(to: edgeRepresentation.layer.endPoint!) + let startPoint = CGPoint(x: edgeRepresentation.layer.startPoint!.x + translation.x, + y: edgeRepresentation.layer.startPoint!.y + translation.y) + edgeRepresentation.layer.startPoint = startPoint + bezier.addLine(to: startPoint) + } else { + bezier.move(to: edgeRepresentation.layer.startPoint!) + let endPoint = CGPoint(x: edgeRepresentation.layer.endPoint!.x + translation.x, + y: edgeRepresentation.layer.endPoint!.y + translation.y) + edgeRepresentation.layer.endPoint = endPoint + bezier.addLine(to: endPoint) + } + return bezier.cgPath + } + + @objc private func didTapVertex(sender: AnyObject) { + DispatchQueue.main.async { + if self.graph.state == .completed { + for vertex in self.graph.vertices { + vertex.edges.forEach { $0.edgeRepresentation?.setDefaultColor() } + vertex.setVisitedColor() + } + if let vertexView = sender as? VertexView, let vertex = vertexView.vertex { + for (index, pathVertex) in vertex.pathVerticesFromStart.enumerated() { + pathVertex.setCheckingPathColor() + if vertex.pathVerticesFromStart.count > index + 1 { + let nextVertex = vertex.pathVerticesFromStart[index + 1] + + if let edge = pathVertex.edges.filter({ $0.neighbor == nextVertex }).first { + edge.edgeRepresentation?.setCheckingColor() + } + } + + } + } + } else if self.graph.state == .interactiveVisualization { + if let vertexView = sender as? VertexView, let vertex = vertexView.vertex { + if vertex.visited { + return + } else { + self.graph.didTapVertex(vertex: vertex) + } + } + } + } + } + + private func setupEdgeRepresentations() { + var edgeQueue: [Vertex] = [self.graph.startVertex!] + + //BFS + while !edgeQueue.isEmpty { + let currentVertex = edgeQueue.first! + currentVertex.haveAllEdges = true + for edge in currentVertex.edges { + let neighbor = edge.neighbor + let weight = edge.weight + if !neighbor.haveAllEdges { + let edgeRepresentation = EdgeRepresentation(from: currentVertex, to: neighbor, weight: weight) + edge.edgeRepresentation = edgeRepresentation + let index = neighbor.edges.index(where: { $0.neighbor == currentVertex })! + neighbor.edges[index].edgeRepresentation = edgeRepresentation + edgeQueue.append(neighbor) + } + } + edgeQueue.removeFirst() + } + } +} diff --git a/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/SimpleObjects/Edge.swift b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/SimpleObjects/Edge.swift new file mode 100644 index 000000000..6f4493bbe --- /dev/null +++ b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/SimpleObjects/Edge.swift @@ -0,0 +1,12 @@ +import Foundation + +public class Edge { + public var neighbor: Vertex + public var weight: Double + public var edgeRepresentation: EdgeRepresentation? + + public init(vertex: Vertex, weight: Double) { + self.neighbor = vertex + self.weight = weight + } +} diff --git a/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/SimpleObjects/Vertex.swift b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/SimpleObjects/Vertex.swift new file mode 100644 index 000000000..c9270b0df --- /dev/null +++ b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/SimpleObjects/Vertex.swift @@ -0,0 +1,62 @@ +import UIKit + +public class Vertex: Hashable, Equatable { + private var graphColors: GraphColors = GraphColors.sharedInstance + + public var identifier: String + public var edges: [Edge] = [] + public var pathLengthFromStart: Double = Double.infinity { + didSet { + DispatchQueue.main.async { + self.view?.setPathLengthLabel(text: "\(self.pathLengthFromStart)") + } + } + } + public var pathVerticesFromStart: [Vertex] = [] + public var level: Int = 0 + public var levelChecked: Bool = false + public var haveAllEdges: Bool = false + public var visited: Bool = false + + public var view: VertexView? + + public init(identifier: String) { + self.identifier = identifier + } + + public var hashValue: Int { + return self.identifier.hashValue + } + + public static func ==(lhs: Vertex, rhs: Vertex) -> Bool { + if lhs.hashValue == rhs.hashValue { + return true + } + return false + } + + public func clearCache() { + self.pathLengthFromStart = Double.infinity + self.pathVerticesFromStart = [] + self.visited = false + } + + public func clearLevelInfo() { + self.level = 0 + self.levelChecked = false + } + + public func setVisitedColor() { + self.view?.backgroundColor = self.graphColors.visitedColor + self.view?.setLabelsTextColor(color: UIColor.white) + } + + public func setCheckingPathColor() { + self.view?.backgroundColor = self.graphColors.checkingColor + } + + public func setDefaultColor() { + self.view?.backgroundColor = self.graphColors.defaultVertexColor + self.view?.setLabelsTextColor(color: UIColor.black) + } +} diff --git a/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/Window.swift b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/Window.swift new file mode 100644 index 000000000..e8aabad27 --- /dev/null +++ b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/Window.swift @@ -0,0 +1,319 @@ +import Foundation +import UIKit + +public protocol GraphDelegate: class { + func willCompareVertices(startVertexPathLength: Double, edgePathLength: Double, endVertexPathLength: Double) + func didFinishCompare() + func didCompleteGraphParsing() + func didTapWrongVertex() + func didStop() + func willStartVertexNeighborsChecking() + func didFinishVertexNeighborsChecking() +} + +public class Window: UIView, GraphDelegate { + public var graphView: GraphView! + + private var topView: UIView! + private var createGraphButton: RoundedButton! + private var startVisualizationButton: RoundedButton! + private var startInteractiveVisualizationButton: RoundedButton! + private var startButton: UIButton! + private var pauseButton: UIButton! + private var stopButton: UIButton! + private var comparisonLabel: UILabel! + private var activityIndicator: UIActivityIndicatorView! + private var graph: Graph! + private var numberOfVertices: UInt! + private var graphColors: GraphColors = GraphColors.sharedInstance + + public override init(frame: CGRect) { + super.init(frame: frame) + self.frame = frame + self.backgroundColor = self.graphColors.mainWindowBackgroundColor + } + + public required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + public func configure(graph: Graph) { + self.graph = graph + self.graph.createNewGraph() + self.graph.delegate = self + let frame = CGRect(x: 10, y: 170, width: self.frame.width - 20, height: self.frame.height - 180) + self.graphView = GraphView(frame: frame) + self.graphView.layer.cornerRadius = 15 + + self.graphView.configure(graph: self.graph) + self.graphView.createNewGraph() + self.addSubview(self.graphView) + + self.configureCreateGraphButton() + self.configureStartVisualizationButton() + self.configureStartInteractiveVisualizationButton() + self.configureStartButton() + self.configurePauseButton() + self.configureStopButton() + self.configureComparisonLabel() + self.configureActivityIndicator() + + self.topView = UIView(frame: CGRect(x: 10, y: 10, width: self.frame.width - 20, height: 150)) + self.topView.backgroundColor = self.graphColors.topViewBackgroundColor + self.topView.layer.cornerRadius = 15 + self.addSubview(self.topView) + + self.topView.addSubview(self.createGraphButton) + self.topView.addSubview(self.startVisualizationButton) + self.topView.addSubview(self.startInteractiveVisualizationButton) + self.topView.addSubview(self.startButton) + self.topView.addSubview(self.pauseButton) + self.topView.addSubview(self.stopButton) + self.topView.addSubview(self.comparisonLabel) + self.topView.addSubview(self.activityIndicator) + } + + private func configureCreateGraphButton() { + let frame = CGRect(x: self.center.x - 200, y: 12, width: 100, height: 34) + self.createGraphButton = RoundedButton(frame: frame) + self.createGraphButton.setTitle("New graph", for: .normal) + self.createGraphButton.addTarget(self, action: #selector(self.createGraphButtonTap), for: .touchUpInside) + } + + private func configureStartVisualizationButton() { + let frame = CGRect(x: self.center.x - 50, y: 12, width: 100, height: 34) + self.startVisualizationButton = RoundedButton(frame: frame) + self.startVisualizationButton.setTitle("Auto", for: .normal) + self.startVisualizationButton.addTarget(self, action: #selector(self.startVisualizationButtonDidTap), for: .touchUpInside) + } + + private func configureStartInteractiveVisualizationButton() { + let frame = CGRect(x: self.center.x + 100, y: 12, width: 100, height: 34) + self.startInteractiveVisualizationButton = RoundedButton(frame: frame) + self.startInteractiveVisualizationButton.setTitle("Interactive", for: .normal) + self.startInteractiveVisualizationButton.addTarget(self, action: #selector(self.startInteractiveVisualizationButtonDidTap), for: .touchUpInside) + } + + private func configureStartButton() { + let frame = CGRect(x: self.center.x - 65, y: 56, width: 30, height: 30) + self.startButton = UIButton(frame: frame) + let playImage = UIImage(named: "Start.png") + self.startButton.setImage(playImage, for: .normal) + self.startButton.isEnabled = false + self.startButton.addTarget(self, action: #selector(self.didTapStartButton), for: .touchUpInside) + } + + private func configurePauseButton() { + let frame = CGRect(x: self.center.x - 15, y: 56, width: 30, height: 30) + self.pauseButton = UIButton(frame: frame) + let pauseImage = UIImage(named: "Pause.png") + self.pauseButton.setImage(pauseImage, for: .normal) + self.pauseButton.isEnabled = false + self.pauseButton.addTarget(self, action: #selector(self.didTapPauseButton), for: .touchUpInside) + } + + private func configureStopButton() { + let frame = CGRect(x: self.center.x + 35, y: 56, width: 30, height: 30) + self.stopButton = UIButton(frame: frame) + let stopImage = UIImage(named: "Stop.png") + self.stopButton.setImage(stopImage, for: .normal) + self.stopButton.isEnabled = false + self.stopButton.addTarget(self, action: #selector(self.didTapStopButton), for: .touchUpInside) + } + + private func configureComparisonLabel() { + let size = CGSize(width: 250, height: 42) + let origin = CGPoint(x: self.center.x - 125, y: 96) + let frame = CGRect(origin: origin, size: size) + self.comparisonLabel = UILabel(frame: frame) + self.comparisonLabel.textAlignment = .center + self.comparisonLabel.text = "Have fun!" + } + + private func configureActivityIndicator() { + let size = CGSize(width: 50, height: 42) + let origin = CGPoint(x: self.center.x - 25, y: 100) + let activityIndicatorFrame = CGRect(origin: origin, size: size) + self.activityIndicator = UIActivityIndicatorView(frame: activityIndicatorFrame) + self.activityIndicator.activityIndicatorViewStyle = .whiteLarge + } + + @objc private func createGraphButtonTap() { + self.comparisonLabel.text = "" + self.graphView.removeGraph() + self.graph.removeGraph() + self.graph.createNewGraph() + self.graphView.createNewGraph() + self.graph.state = .initial + } + + @objc private func startVisualizationButtonDidTap() { + self.comparisonLabel.text = "" + self.pauseButton.isEnabled = true + self.stopButton.isEnabled = true + self.createGraphButton.isEnabled = false + self.startVisualizationButton.isEnabled = false + self.startInteractiveVisualizationButton.isEnabled = false + self.createGraphButton.alpha = 0.5 + self.startVisualizationButton.alpha = 0.5 + self.startInteractiveVisualizationButton.alpha = 0.5 + + if self.graph.state == .completed { + self.graphView.reset() + self.graph.reset() + } + self.graph.state = .autoVisualization + DispatchQueue.global(qos: .background).async { + self.graph.findShortestPathsWithVisualization { + self.graph.state = .completed + + DispatchQueue.main.async { + self.startButton.isEnabled = false + self.pauseButton.isEnabled = false + self.stopButton.isEnabled = false + self.createGraphButton.isEnabled = true + self.startVisualizationButton.isEnabled = true + self.startInteractiveVisualizationButton.isEnabled = true + self.createGraphButton.alpha = 1 + self.startVisualizationButton.alpha = 1 + self.startInteractiveVisualizationButton.alpha = 1 + self.comparisonLabel.text = "Completed!" + } + } + } + } + + @objc private func startInteractiveVisualizationButtonDidTap() { + self.comparisonLabel.text = "" + self.pauseButton.isEnabled = true + self.stopButton.isEnabled = true + self.createGraphButton.isEnabled = false + self.startVisualizationButton.isEnabled = false + self.startInteractiveVisualizationButton.isEnabled = false + self.createGraphButton.alpha = 0.5 + self.startVisualizationButton.alpha = 0.5 + self.startInteractiveVisualizationButton.alpha = 0.5 + + if self.graph.state == .completed { + self.graphView.reset() + self.graph.reset() + } + + self.graph.startVertex.pathLengthFromStart = 0 + self.graph.startVertex.pathVerticesFromStart.append(self.graph.startVertex) + self.graph.state = .parsing + self.graph.parseNeighborsFor(vertex: self.graph.startVertex) { + self.graph.state = .interactiveVisualization + DispatchQueue.main.async { + self.comparisonLabel.text = "Pick next vertex" + } + } + } + + @objc private func didTapStartButton() { + self.startButton.isEnabled = false + self.pauseButton.isEnabled = true + DispatchQueue.global(qos: .utility).async { + self.graph.pauseVisualization = false + } + } + + @objc private func didTapPauseButton() { + self.startButton.isEnabled = true + self.pauseButton.isEnabled = false + DispatchQueue.global(qos: .utility).async { + self.graph.pauseVisualization = true + } + } + + @objc private func didTapStopButton() { + self.startButton.isEnabled = false + self.pauseButton.isEnabled = false + self.comparisonLabel.text = "" + self.activityIndicator.startAnimating() + if self.graph.state == .parsing || self.graph.state == .autoVisualization { + self.graph.stopVisualization = true + } else if self.graph.state == .interactiveVisualization { + self.didStop() + } + } + + private func setButtonsToInitialState() { + self.createGraphButton.isEnabled = true + self.startVisualizationButton.isEnabled = true + self.startInteractiveVisualizationButton.isEnabled = true + self.startButton.isEnabled = false + self.pauseButton.isEnabled = false + self.stopButton.isEnabled = false + self.createGraphButton.alpha = 1 + self.startVisualizationButton.alpha = 1 + self.startInteractiveVisualizationButton.alpha = 1 + } + + private func showError(error: String) { + DispatchQueue.main.async { + let size = CGSize(width: 250, height: 42) + let origin = CGPoint(x: self.topView.center.x - 125, y: 96) + let frame = CGRect(origin: origin, size: size) + let errorView = ErrorView(frame: frame) + errorView.setText(text: error) + self.topView.addSubview(errorView) + UIView.animate(withDuration: 2, animations: { + errorView.alpha = 0 + }, completion: { _ in + errorView.removeFromSuperview() + }) + } + } + + // MARK: GraphDelegate + public func didCompleteGraphParsing() { + self.graph.state = .completed + self.setButtonsToInitialState() + self.comparisonLabel.text = "Completed!" + } + + public func didTapWrongVertex() { + if !self.subviews.contains { $0 is ErrorView } { + self.showError(error: "You have picked wrong next vertex") + } + } + + public func willCompareVertices(startVertexPathLength: Double, edgePathLength: Double, endVertexPathLength: Double) { + DispatchQueue.main.async { + if startVertexPathLength + edgePathLength < endVertexPathLength { + self.comparisonLabel.text = "\(startVertexPathLength) + \(edgePathLength) < \(endVertexPathLength) 👍" + } else { + self.comparisonLabel.text = "\(startVertexPathLength) + \(edgePathLength) >= \(endVertexPathLength) 👎" + } + } + } + + public func didFinishCompare() { + DispatchQueue.main.async { + self.comparisonLabel.text = "" + } + } + + public func didStop() { + self.graph.state = .initial + self.graph.stopVisualization = false + self.graph.pauseVisualization = false + self.graphView.reset() + self.graph.reset() + self.setButtonsToInitialState() + self.activityIndicator.stopAnimating() + } + + public func willStartVertexNeighborsChecking() { + DispatchQueue.main.async { + self.comparisonLabel.text = "" + } + } + + public func didFinishVertexNeighborsChecking() { + DispatchQueue.main.async { + self.comparisonLabel.text = "Pick next vertex" + } + } +} diff --git a/Dijkstra Algorithm/VisualizedDijkstra.playground/contents.xcplayground b/Dijkstra Algorithm/VisualizedDijkstra.playground/contents.xcplayground new file mode 100644 index 000000000..35968656f --- /dev/null +++ b/Dijkstra Algorithm/VisualizedDijkstra.playground/contents.xcplayground @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Dijkstra Algorithm/VisualizedDijkstra.playground/playground.xcworkspace/contents.xcworkspacedata b/Dijkstra Algorithm/VisualizedDijkstra.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Dijkstra Algorithm/VisualizedDijkstra.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Dijkstra Algorithm/VisualizedDijkstra.playground/timeline.xctimeline b/Dijkstra Algorithm/VisualizedDijkstra.playground/timeline.xctimeline new file mode 100644 index 000000000..bf468afec --- /dev/null +++ b/Dijkstra Algorithm/VisualizedDijkstra.playground/timeline.xctimeline @@ -0,0 +1,6 @@ + + + + + diff --git a/README.markdown b/README.markdown index 5e6cfbfe4..eee5cbb46 100644 --- a/README.markdown +++ b/README.markdown @@ -183,6 +183,7 @@ Most of the time using just the built-in `Array`, `Dictionary`, and `Set` types - [Single-Source Shortest Paths](Single-Source%20Shortest%20Paths%20(Weighted)/) - [Minimum Spanning Tree](Minimum%20Spanning%20Tree%20%28Unweighted%29/) on an unweighted tree - [All-Pairs Shortest Paths](All-Pairs%20Shortest%20Paths/) +- [Dijkstra's shortest path algorithm](Dijkstra%20Algorithm/) ## Puzzles From 8efb7354645763fce0823ec74c2fe3ffb904f4df Mon Sep 17 00:00:00 2001 From: Jacopo Mangiavacchi Date: Tue, 4 Apr 2017 10:25:36 +0100 Subject: [PATCH 0891/1679] MIT License --- MinimumCoinChange/LICENSE | 222 ++++---------------------------------- 1 file changed, 21 insertions(+), 201 deletions(-) diff --git a/MinimumCoinChange/LICENSE b/MinimumCoinChange/LICENSE index 8dada3eda..fda6e6146 100755 --- a/MinimumCoinChange/LICENSE +++ b/MinimumCoinChange/LICENSE @@ -1,201 +1,21 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright {yyyy} {name of copyright owner} - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. +MIT License + +Copyright (c) 2017 Jacopo Mangiavacchi + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. From 63257f629f99ba76a7997a1e0b18b8236cefa57b Mon Sep 17 00:00:00 2001 From: Richard Date: Tue, 4 Apr 2017 13:37:53 -0700 Subject: [PATCH 0892/1679] fixed typos in readme --- Strassen Matrix Multiplication/README.markdown | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Strassen Matrix Multiplication/README.markdown b/Strassen Matrix Multiplication/README.markdown index fa822d310..07ce534b2 100644 --- a/Strassen Matrix Multiplication/README.markdown +++ b/Strassen Matrix Multiplication/README.markdown @@ -18,7 +18,7 @@ matrix A = |1 2|, matrix B = |5 6| A * B = C |1 2| * |5 6| = |1*5+2*7 1*6+2*8| = |19 22| -|3 4| |7 8| |3*5+4*7 3*6+4*8| |43 48| +|3 4| |7 8| |3*5+4*7 3*6+4*8| |43 50| ``` What's going on here? To start, we're multiplying matricies A & B. Our new matrix, C's, elements `[i, j]` are determined by the dot product of the first matrix's ith row and the second matrix's jth column. See [here](https://www.khanacademy.org/math/linear-algebra/vectors-and-spaces/dot-cross-products/v/vector-dot-product-and-vector-length) for a refresher on the dot product. @@ -72,7 +72,7 @@ Then, for each row in A and column in B, we take the dot product of the ith row ```swift for k in 0..) -> Matrix { for i in 0.. Date: Tue, 4 Apr 2017 14:07:19 -0700 Subject: [PATCH 0893/1679] Update README.markdown --- README.markdown | 1 + 1 file changed, 1 insertion(+) diff --git a/README.markdown b/README.markdown index 5e6cfbfe4..067de2418 100644 --- a/README.markdown +++ b/README.markdown @@ -106,6 +106,7 @@ Bad sorting algorithms (don't use these!): - Statistics - [Karatsuba Multiplication](Karatsuba%20Multiplication/). Another take on elementary multiplication. - [Haversine Distance](HaversineDistance/). Calculating the distance between 2 points from a sphere. +- [Strassen's Multiplication Matrix](Strassen%20Multiplication%20Matrix). Efficient way to handle matrix multiplication. ### Machine learning From bbba068205500a62943a601540d4dfba205586f2 Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Tue, 4 Apr 2017 14:09:02 -0700 Subject: [PATCH 0894/1679] Updated a link to Strassen Multiplication Matrix. --- README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.markdown b/README.markdown index 067de2418..29fc9d748 100644 --- a/README.markdown +++ b/README.markdown @@ -106,7 +106,7 @@ Bad sorting algorithms (don't use these!): - Statistics - [Karatsuba Multiplication](Karatsuba%20Multiplication/). Another take on elementary multiplication. - [Haversine Distance](HaversineDistance/). Calculating the distance between 2 points from a sphere. -- [Strassen's Multiplication Matrix](Strassen%20Multiplication%20Matrix). Efficient way to handle matrix multiplication. +- [Strassen's Multiplication Matrix](Strassen%20Matrix%20Multiplication/). Efficient way to handle matrix multiplication. ### Machine learning From 20d7c1fd66b93c2a3933abe5d048169cea888ced Mon Sep 17 00:00:00 2001 From: Parva9eh Date: Tue, 4 Apr 2017 17:46:46 -0700 Subject: [PATCH 0895/1679] Revisions in README.md # Coherence & Sentence structures # Grammar and spelling --- DiningPhilosophers/README.md | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/DiningPhilosophers/README.md b/DiningPhilosophers/README.md index ec1611c65..0bf4f28ce 100755 --- a/DiningPhilosophers/README.md +++ b/DiningPhilosophers/README.md @@ -1,22 +1,22 @@ # Dining Philosophers -Dining philosophers problem Algorithm implemented in Swift (concurrent algorithm design to illustrate synchronization issues and techniques for resolving them using [GCD](https://apple.github.io/swift-corelibs-libdispatch/) and [Semaphore](https://developer.apple.com/reference/dispatch/dispatchsemaphore) in Swift) +The dining philosophers problem Algorithm implemented in Swift (concurrent algorithm design to illustrate synchronization issues and techniques for resolving them using [GCD](https://apple.github.io/swift-corelibs-libdispatch/) and [Semaphore](https://developer.apple.com/reference/dispatch/dispatchsemaphore) in Swift) Written for Swift Algorithm Club by Jacopo Mangiavacchi # Introduction -In computer science, the dining philosophers problem is an example problem often used in concurrent algorithm design to illustrate synchronization issues and techniques for resolving them. +In computer science, the dining philosophers problem is often used in the concurrent algorithm design to illustrate synchronization issues and techniques for resolving them. It was originally formulated in 1965 by Edsger Dijkstra as a student exam exercise, presented in terms of computers competing for access to tape drive peripherals. Soon after, Tony Hoare gave the problem its present formulation. -This Swift implementation is based on the Chandy/Misra solution and it use GCD Dispatch and Semaphone on Swift cross platform +This Swift implementation is based on the Chandy/Misra solution, and it uses the GCD Dispatch and Semaphone on the Swift cross platform. # Problem statement Five silent philosophers sit at a round table with bowls of spaghetti. Forks are placed between each pair of adjacent philosophers. -Each philosopher must alternately think and eat. However, a philosopher can only eat spaghetti when they have both left and right forks. Each fork can be held by only one philosopher and so a philosopher can use the fork only if it is not being used by another philosopher. After an individual philosopher finishes eating, they need to put down both forks so that the forks become available to others. A philosopher can take the fork on their right or the one on their left as they become available, but cannot start eating before getting both forks. +Each philosopher must alternately think and eat. A philosopher can only eat spaghetti when they have both left and right forks. Since each fork can be held by only one philosopher, a philosopher can use the fork only if it is not being used by another philosopher. When a philosopher finishes eating, they need to put down both forks so that the forks become available to others. A philosopher can take the fork on their right or the one on their left as they become available, but they cannot start eating before getting both forks. Eating is not limited by the remaining amounts of spaghetti or stomach space; an infinite supply and an infinite demand are assumed. @@ -26,35 +26,32 @@ This is an illustration of an dinining table: ![Dining Philosophers table](https://upload.wikimedia.org/wikipedia/commons/7/7b/An_illustration_of_the_dining_philosophers_problem.png) - # Solution -There are different solutions for this classic algorithm and this Swift implementation is based on the on the Chandy/Misra solution that more generally allows for arbitrary agents to contend for an arbitrary number of resources in a completely distributed scenario with no needs for a central authority to control the locking and serialization of resources. - -However, it is very important to note here that this solution violates the requirement that "the philosophers do not speak to each other" (due to the request messages). +There are different solutions for this classic algorithm, and this Swift implementation is based on the Chandy/Misra solution. This implementation allows agents to contend for an arbitrary number of resources in a completely distributed scenario with no needs for a central authority to control the locking and serialization of resources. +However, this solution violates the requirement that "the philosophers do not speak to each other" (due to the request messages). # Description For every pair of philosophers contending for a resource, create a fork and give it to the philosopher with the lower ID (n for agent Pn). Each fork can either be dirty or clean. Initially, all forks are dirty. -When a philosopher wants to use a set of resources (i.e. eat), said philosopher must obtain the forks from their contending neighbors. For all such forks the philosopher does not have, they send a request message. -When a philosopher with a fork receives a request message, they keep the fork if it is clean, but give it up when it is dirty. If the philosopher sends the fork over, they clean the fork before doing so. +When a philosopher wants to use a set of resources (i.e. eat), said philosopher must obtain the forks from their contending neighbors. The philospher send a message for all such forks needed. When a philosopher with a fork receives a request message, they keep the fork if it is clean, but give it up when it is dirty. If the philosopher sends the fork over, they clean the fork before doing so. After a philosopher is done eating, all their forks become dirty. If another philosopher had previously requested one of the forks, the philosopher that has just finished eating cleans the fork and sends it. -This solution also allows for a large degree of concurrency, and will solve an arbitrarily large problem. +This solution also allows for a large degree of concurrency, and it will solve an arbitrarily large problem. -It also solves the starvation problem. The clean / dirty labels act as a way of giving preference to the most "starved" processes, and a disadvantage to processes that have just "eaten". One could compare their solution to one where philosophers are not allowed to eat twice in a row without letting others use the forks in between. Chandy and Misra's solution is more flexible than that, but has an element tending in that direction. +In addition, it solves the starvation problem. The clean / dirty labels give a preference to the most "starved" processes and a disadvantage to processes that have just "eaten". One could compare their solution to one where philosophers are not allowed to eat twice in a row without letting others use the forks in between. The Chandy and Misra's solution is more flexible but has an element tending in that direction. -In their analysis they derive a system of preference levels from the distribution of the forks and their clean/dirty states. They show that this system may describe an acyclic graph, and if so, the operations in their protocol cannot turn that graph into a cyclic one. This guarantees that deadlock cannot occur. However, if the system is initialized to a perfectly symmetric state, like all philosophers holding their left side forks, then the graph is cyclic at the outset, and their solution cannot prevent a deadlock. Initializing the system so that philosophers with lower IDs have dirty forks ensures the graph is initially acyclic. +Based on the Chandy and Misra's analysis, a system of preference levels is derived from the distribution of the forks and their clean/dirty states. This system may describe an acyclic graph, and if so, the solution's protocol cannot turn that graph into a cyclic one. This guarantees that deadlock cannot occur. However, if the system is initialized to a perfectly symmetric state, such as all philosophers holding their left side forks, then the graph is cyclic at the outset, and the solution cannot prevent a deadlock. Initializing the system so that philosophers with lower IDs have dirty forks ensures the graph is initially acyclic. # Swift implementation -This Swift 3.0 implementation of the Chandy/Misra solution is based on GCD and Semaphore tecnique and it could be built on both macOS and Linux. +This Swift 3.0 implementation of the Chandy/Misra solution is based on the GCD and Semaphore tecnique that can be built on both macOS and Linux. The code is based on a ForkPair struct used for holding an array of DispatchSemaphore and a Philosopher struct for associate a couple of forks to each Philosopher. The ForkPair DispatchSemaphore static array is used for waking the neighbour Philosophers any time a fork pair is put down on the table. -A background DispatchQueue is then used to let any Philosopher run asyncrounosly on the background and a global DispatchSemaphore is simply used in order to keep the main thread on wait forever and let the Philosophers contienue forever in their alternate think and eat cycle. - +A background DispatchQueue is then used to let any Philosopher run asyncrounosly on the background, and a global DispatchSemaphore is used to keep the main thread on wait forever and let the Philosophers continue forever in their alternate think and eat cycle. + # See also Dining Philosophers on Wikipedia https://en.wikipedia.org/wiki/Dining_philosophers_problem From 56c5ecf2c5c6baf4b7442dbf46db5c9d13fda523 Mon Sep 17 00:00:00 2001 From: Parva9eh Date: Tue, 4 Apr 2017 19:31:26 -0700 Subject: [PATCH 0896/1679] Revisions in README.markdown 1- Coherence, Sentence structure, & Consistency 2- Grammar, Word choice, & Spelling --- Huffman Coding/README.markdown | 82 +++++++++++++++++----------------- 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/Huffman Coding/README.markdown b/Huffman Coding/README.markdown index 4e6f75514..69e105c87 100644 --- a/Huffman Coding/README.markdown +++ b/Huffman Coding/README.markdown @@ -1,12 +1,12 @@ # Huffman Coding -The idea: Encode objects that occur often with a smaller number of bits than objects that occur less frequently. +The idea: To encode objects that occur with a smaller number of bits than objects that occur less frequently. -Although you can encode any type of objects with this scheme, it's most common to compress a stream of bytes. Let's say you have the following text, where each character is one byte: +Although any type of objects can be encoded with this scheme, it is common to compress a stream of bytes. Suppose you have the following text, where each character is one byte: so much words wow many compression -If you count how often each byte appears, you can clearly see that some bytes occur more than others: +If you count how often each byte appears, you can see some bytes occur more than others: space: 5 u: 1 o: 5 h: 1 @@ -41,11 +41,11 @@ Now if we replace the original bytes with these bit strings, the compressed outp The extra 0-bit at the end is there to make a full number of bytes. We were able to compress the original 34 bytes into merely 16 bytes, a space savings of over 50%! -But hold on... to be able to decode these bits we need to have the original frequency table. That table needs to be transmitted or saved along with the compressed data, otherwise the decoder doesn't know how to interpret the bits. Because of the overhead of this frequency table (about 1 kilobyte), it doesn't really pay to use Huffman encoding on very small inputs. +To be able to decode these bits, we need to have the original frequency table. That table needs to be transmitted or saved along with the compressed data. Otherwise, the decoder does not know how to interpret the bits. Because of the overhead of this frequency table (about 1 kilobyte), it is not beneficial to use Huffman encoding on small inputs. ## How it works -When compressing a stream of bytes, the algorithm first creates a frequency table that counts how often each byte occurs. Based on this table it creates a binary tree that describes the bit strings for each of the input bytes. +When compressing a stream of bytes, the algorithm first creates a frequency table that counts how often each byte occurs. Based on this table, the algorithm creates a binary tree that describes the bit strings for each of the input bytes. For our example, the tree looks like this: @@ -53,17 +53,17 @@ For our example, the tree looks like this: Note that the tree has 16 leaf nodes (the grey ones), one for each byte value from the input. Each leaf node also shows the count of how often it occurs. The other nodes are "intermediate" nodes. The number shown in these nodes is the sum of the counts of their child nodes. The count of the root node is therefore the total number of bytes in the input. -The edges between the nodes either say "1" or "0". These correspond to the bit-encodings of the leaf nodes. Notice how each left branch is always 1 and each right branch is always 0. +The edges between the nodes are either "1" or "0". These correspond to the bit-encodings of the leaf nodes. Notice how each left branch is always 1 and each right branch is always 0. -Compression is then a matter of looping through the input bytes, and for each byte traverse the tree from the root node to that byte's leaf node. Every time we take a left branch, we emit a 1-bit. When we take a right branch, we emit a 0-bit. +Compression is then a matter of looping through the input bytes and for each byte traversing the tree from the root node to that byte's leaf node. Every time we take a left branch, we emit a 1-bit. When we take a right branch, we emit a 0-bit. -For example, to go from the root node to `c`, we go right (`0`), right again (`0`), left (`1`), and left again (`1`). So the Huffman code for `c` is `0011`. +For example, to go from the root node to `c`, we go right (`0`), right again (`0`), left (`1`), and left again (`1`). This gives the Huffman code as `0011` for `c`. -Decompression works in exactly the opposite way. It reads the compressed bits one-by-one and traverses the tree until we get to a leaf node. The value of that leaf node is the uncompressed byte. For example, if the bits are `11010`, we start at the root and go left, left again, right, left, and a final right to end up at `d`. +Decompression works in exactly the opposite way. It reads the compressed bits one-by-one and traverses the tree until it reaches to a leaf node. The value of that leaf node is the uncompressed byte. For example, if the bits are `11010`, we start at the root and go left, left again, right, left, and a final right to end up at `d`. ## The code -Before we get to the actual Huffman coding scheme, it's useful to have some helper code that can write individual bits to an `NSData` object. The smallest piece of data that `NSData` understands is the byte, but we're dealing in bits, so we need to translate between the two. +Before we get to the actual Huffman coding scheme, it is useful to have some helper code that can write individual bits to an `NSData` object. The smallest piece of data that `NSData` understands is the byte, but we are dealing in bits, so we need to translate between the two. ```swift public class BitWriter { @@ -92,11 +92,11 @@ public class BitWriter { } ``` -To add a bit to the `NSData` you call `writeBit()`. This stuffs each new bit into the `outByte` variable. Once you've written 8 bits, `outByte` gets added to the `NSData` object for real. +To add a bit to the `NSData`, you can call `writeBit()`. This helper object stuffs each new bit into the `outByte` variable. Once you have written 8 bits, `outByte` gets added to the `NSData` object for real. The `flush()` method is used for outputting the very last byte. There is no guarantee that the number of compressed bits is a nice round multiple of 8, in which case there may be some spare bits at the end. If so, `flush()` adds a few 0-bits to make sure that we write a full byte. -We'll use a similar helper object for reading individual bits from `NSData`: +Here is a similar helper object for reading individual bits from `NSData`: ```swift public class BitReader { @@ -122,15 +122,15 @@ public class BitReader { } ``` -This works in a similar fashion. We read one whole byte from the `NSData` object and put it in `inByte`. Then `readBit()` returns the individual bits from that byte. Once `readBit()` has been called 8 times, we read the next byte from the `NSData`. +By using this helper object, we can read one whole byte from the `NSData` object and put it in `inByte`. Then, `readBit()` returns the individual bits from that byte. Once `readBit()` has been called 8 times, we read the next byte from the `NSData`. -> **Note:** It's no big deal if you're unfamiliar with this sort of bit manipulation. Just know that these two helper objects make it simple for us to write and read bits and not worry about all the messy stuff of making sure they end up in the right place. +> **Note:** If you are unfamiliar with this type of bit manipulation, just know that these two helper objects make it simple for us to write and read bits. ## The frequency table -The first step in Huffman compression is to read the entire input stream and build a frequency table. This table contains a list of all 256 possible byte values and how often each of these bytes occurs in the input data. +The first step in the Huffman compression is to read the entire input stream and build a frequency table. This table contains a list of all 256 possible byte values and shows how often each of these bytes occurs in the input data. -We could store this frequency information in a dictionary or an array, but since we're going to need to build a tree anyway, we might as well store the frequency table as the leaves of the tree. +We could store this frequency information in a dictionary or an array, but since we need to build a tree, we might store the frequency table as the leaves of the tree. Here are the definitions we need: @@ -152,9 +152,9 @@ class Huffman { } ``` -The tree structure is stored in the `tree` array and will be made up of `Node` objects. Since this is a [binary tree](../Binary%20Tree/), each node needs two children, `left` and `right`, and a reference back to its `parent` node. Unlike a typical binary tree, however, these nodes don't to use pointers to refer to each other but simple integer indices in the `tree` array. (We also store the array `index` of the node itself; the reason for this will become clear later.) +The tree structure is stored in the `tree` array and will be made up of `Node` objects. Since this is a [binary tree](../Binary%20Tree/), each node needs two children, `left` and `right`, and a reference back to its `parent` node. Unlike a typical binary tree, these nodes do not use pointers to refer to each other but use simple integer indices in the `tree` array. (We also store the array `index` of the node itself; the reason for this will become clear later.) -Note that `tree` currently has room for 256 entries. These are for the leaf nodes because there are 256 possible byte values. Of course, not all of those may end up being used, depending on the input data. Later, we'll add more nodes as we build up the actual tree. For the moment there isn't a tree yet, just 256 separate leaf nodes with no connections between them. All the node counts are 0. +Note that the `tree` currently has room for 256 entries. These are for the leaf nodes because there are 256 possible byte values. Of course, not all of those may end up being used, depending on the input data. Later, we will add more nodes as we build up the actual tree. For the moment, there is not a tree yet. It includes 256 separate leaf nodes with no connections between them. All the node counts are 0. We use the following method to count how often each byte occurs in the input data: @@ -170,13 +170,13 @@ We use the following method to count how often each byte occurs in the input dat } ``` -This steps through the `NSData` object from beginning to end and for each byte increments the `count` of the corresponding leaf node. That's all there is to it. After `countByteFrequency()` completes, the first 256 `Node` objects in the `tree` array represent the frequency table. +This steps through the `NSData` object from beginning to end and for each byte increments the `count` of the corresponding leaf node. After `countByteFrequency()` completes, the first 256 `Node` objects in the `tree` array represent the frequency table. -Now, I mentioned that in order to decompress a Huffman-encoded block of data, you also need to have the original frequency table. If you were writing the compressed data to a file, then somewhere in the file you'd include the frequency table. +To decompress a Huffman-encoded block of data, we need to have the original frequency table. If we were writing the compressed data to a file, then somewhere in the file we should include the frequency table. -You could simply dump the first 256 elements from the `tree` array but that's not very efficient. It's likely that not all of these 256 elements will be used, plus you don't need to serialize the `parent`, `right`, and `left` pointers. All we need is the frequency information, not the entire tree. +We could dump the first 256 elements from the `tree` array, but that is not efficient. Not all of these 256 elements will be used, and we do not need to serialize the `parent`, `right`, and `left` pointers. All we need is the frequency information and not the entire tree. -Instead, we'll add a method to export the frequency table without all the pieces we don't need: +Instead, we will add a method to export the frequency table without all the pieces we do not need: ```swift struct Freq { @@ -193,7 +193,7 @@ Instead, we'll add a method to export the frequency table without all the pieces } ``` -The `frequencyTable()` method looks at those first 256 nodes from the tree but keeps only those that are actually used, without the `parent`, `left`, and `right` pointers. It returns an array of `Freq` objects. You have to serialize this array along with the compressed data so that it can be properly decompressed later. +The `frequencyTable()` method looks at those first 256 nodes from the tree but keeps only those that are used, without the `parent`, `left`, and `right` pointers. It returns an array of `Freq` objects. You have to serialize this array along with the compressed data, so that it can be properly decompressed later. ## The tree @@ -201,7 +201,7 @@ As a reminder, there is the compression tree for the example: ![The compression tree](Images/Tree.png) -The leaf nodes represent the actual bytes that are present in the input data. The intermediary nodes connect the leaves in such a way that the path from the root to a frequently-used byte value is shorter than the path to a less common byte value. As you can see, `m`, `s`, space, and `o` are the most common letters in our input data and therefore they are highest up in the tree. +The leaf nodes represent the actual bytes that are present in the input data. The intermediary nodes connect the leaves in such a way that the path from the root to a frequently-used byte value is shorter than the path to a less common byte value. As you can see, `m`, `s`, space, and `o` are the most common letters in our input data and the highest up in the tree. To build the tree, we do the following: @@ -209,7 +209,7 @@ To build the tree, we do the following: 2. Create a new parent node that links these two nodes together. 3. This repeats over and over until only one node with no parent remains. This becomes the root node of the tree. -This is an ideal place to use a [priority queue](../Priority%20Queue/). A priority queue is a data structure that is optimized so that finding the minimum value is always very fast. Here, we repeatedly need to find the node with the smallest count. +This is an ideal place to use a [priority queue](../Priority%20Queue/). A priority queue is a data structure that is optimized, so that finding the minimum value is always fast. Here, we repeatedly need to find the node with the smallest count. The function `buildTree()` then becomes: @@ -252,15 +252,15 @@ Here is how it works step-by-step: 4. Link the two nodes into their new parent node. Now this new intermediate node has become part of the tree. -5. Put the new intermediate node back into the queue. At this point we're done with `node1` and `node2`, but the `parentNode` still need to be connected to other nodes in the tree. +5. Put the new intermediate node back into the queue. At this point we are done with `node1` and `node2`, but the `parentNode` still needs to be connected to other nodes in the tree. -6. Repeat steps 2-5 until there is only one node left in the queue. This becomes the root node of the tree, and we're done. +6. Repeat steps 2-5 until there is only one node left in the queue. This becomes the root node of the tree, and we are done. The animation shows what the process looks like: ![Building the tree](Images/BuildTree.gif) -> **Note:** Instead of using a priority queue, you can repeatedly iterate through the `tree` array to find the next two smallest nodes, but that makes the compressor quite slow, **O(n^2)**. Using the priority queue, the running time is only **O(n log n)** where **n** is the number of nodes. +> **Note:** Instead of using a priority queue, you can repeatedly iterate through the `tree` array to find the next two smallest nodes, but that makes the compressor slow as **O(n^2)**. Using the priority queue, the running time is only **O(n log n)** where **n** is the number of nodes. > **Fun fact:** Due to the nature of binary trees, if we have *x* leaf nodes we can at most add *x - 1* additional nodes to the tree. Given that at most there will be 256 leaf nodes, the tree will never contain more than 511 nodes total. @@ -286,11 +286,11 @@ Now that we know how to build the compression tree from the frequency table, we } ``` -This first calls `countByteFrequency()` to build the frequency table, then `buildTree()` to put together the compression tree. It also creates a `BitWriter` object for writing individual bits. +This first calls `countByteFrequency()` to build the frequency table and then calls `buildTree()` to put together the compression tree. It also creates a `BitWriter` object for writing individual bits. -Then it loops through the entire input and for each byte calls `traverseTree()`. That method will step through the tree nodes and for each node write a 1 or 0 bit. Finally, we return the `BitWriter`'s data object. +Then, it loops through the entire input and calls `traverseTree()`for each byte. This method will step through the tree nodes and for each node write a 1 or 0 bit. Finally, we return the `BitWriter`'s data object. -> **Note:** Compression always requires two passes through the entire input data: first to build the frequency table, second to convert the bytes to their compressed bit sequences. +> **Note:** Compression always requires two passes through the entire input data: first to build the frequency table, and second to convert the bytes to their compressed bit sequences. The interesting stuff happens in `traverseTree()`. This is a recursive method: @@ -309,15 +309,15 @@ The interesting stuff happens in `traverseTree()`. This is a recursive method: } ``` -When we call this method from `compressData()`, the `nodeIndex` parameter is the array index of the leaf node for the byte that we're about to encode. This method recursively walks the tree from a leaf node up to the root, and then back again. +When we call this method from `compressData()`, the `nodeIndex` parameter is the array index of the leaf node for the byte that we need to encode. This method recursively walks the tree from a leaf node up to the root and then back again. -As we're going back from the root to the leaf node, we write a 1 bit or a 0 bit for every node we encounter. If a child is the left node, we emit a 1; if it's the right node, we emit a 0. +As we are going back from the root to the leaf node, we write a 1 bit or a 0 bit for every node we encounter. If a child is the left node, we emit a 1; if it is the right node, we emit a 0. In a picture: ![How compression works](Images/Compression.png) -Even though the illustration of the tree shows a 0 or 1 for each edge between the nodes, the bit values 0 and 1 aren't actually stored in the tree! The rule is that we write a 1 bit if we take the left branch and a 0 bit if we take the right branch, so just knowing the direction we're going in is enough to determine what bit value to write. +Even though the illustration of the tree shows a 0 or 1 for each edge between the nodes, the bit values 0 and 1 are not actually stored in the tree! The rule is that we write a 1 bit if we take the left branch and a 0 bit if we take the right branch, so just knowing the direction we are going in is enough to determine what bit value to write. You use the `compressData()` method as follows: @@ -332,9 +332,9 @@ if let originalData = s1.dataUsingEncoding(NSUTF8StringEncoding) { ## Decompression -Decompression is pretty much compression in reverse. However, the compressed bits are useless to us without the frequency table. Earlier you saw the `frequencyTable()` method that returns an array of `Freq` objects. The idea is that if you were saving the compressed data into a file or sending it across the network, you'd also save that `[Freq]` array along with it. +Decompression is the compression in reverse. However, the compressed bits are useless without the frequency table. As mentioned, the `frequencyTable()` method returns an array of `Freq` objects. If we were saving the compressed data into a file or sending it across the network, we'd also save that `[Freq]` array along with it. -We first need some way to turn the `[Freq]` array back into a compression tree. Fortunately, this is pretty easy: +We first need some way to turn the `[Freq]` array back into a compression tree: ```swift fileprivate func restoreTree(fromTable frequencyTable: [Freq]) { @@ -349,7 +349,7 @@ We first need some way to turn the `[Freq]` array back into a compression tree. We convert the `Freq` objects into leaf nodes and then call `buildTree()` to do the rest. -Here is the code for `decompressData()`, which takes an `NSData` object with Huffman-encoded bits and a frequency table, and returns the original data: +Here is the code for `decompressData()`, which takes an `NSData` object with Huffman-encoded bits and a frequency table, and it returns the original data: ```swift func decompressData(data: NSData, frequencyTable: [Freq]) -> NSData { @@ -385,13 +385,13 @@ This also uses a helper method to traverse the tree: } ``` -`findLeafNode()` walks the tree from the root down to the leaf node given by `nodeIndex`. At each intermediate node we read a new bit and then step to the left (bit is 1) or the right (bit is 0). When we get to the leaf node, we simply return its index, which is equal to the original byte value. +`findLeafNode()` walks the tree from the root down to the leaf node given by `nodeIndex`. At each intermediate node, we read a new bit and then step to the left (bit is 1) or the right (bit is 0). When we get to the leaf node, we simply return its index, which is equal to the original byte value. In a picture: ![How decompression works](Images/Decompression.png) -Here's how you would use the decompression method: +Here is how we use the decompression method: ```swift let frequencyTable = huffman1.frequencyTable() @@ -402,9 +402,9 @@ Here's how you would use the decompression method: let s2 = String(data: decompressedData, encoding: NSUTF8StringEncoding)! ``` -First you get the frequency table from somewhere (in this case the `Huffman` object we used to encode the data) and then call `decompressData()`. The string that results should be equal to the one you compressed in the first place. +First we get the frequency table from somewhere (in this case the `Huffman` object we used to encode the data) and then call `decompressData()`. The string that results should be equal to the one we compressed in the first place. -You can see how this works in more detail in the Playground. +we can see how this works in more detail in the Playground. ## See also From d70f40ed8668e60584dc1bd9d5b859b7ad2e91de Mon Sep 17 00:00:00 2001 From: Parva9eh Date: Wed, 5 Apr 2017 10:34:21 -0700 Subject: [PATCH 0897/1679] Revisions in README.markdown I have revised your document to be simplified and concise. --- Array2D/README.markdown | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/Array2D/README.markdown b/Array2D/README.markdown index d67079691..88f25c99a 100644 --- a/Array2D/README.markdown +++ b/Array2D/README.markdown @@ -1,14 +1,14 @@ # Array2D -In C and Objective-C you can write the following line, +In C and Objective-C, you can write the following line, int cookies[9][7]; -to make a 9x7 grid of cookies. This would create a two-dimensional array of 63 elements. To find the cookie at column 3, row 6, you'd write: +to make a 9x7 grid of cookies. This creates a two-dimensional array of 63 elements. To find the cookie at column 3 and row 6, you can write: myCookie = cookies[3][6]; -Unfortunately, you can't write the above in Swift. To create a multi-dimensional array in Swift you'd have to do something like this: +This statement is not acceptable in Swift. To create a multi-dimensional array in Swift, you can write: ```swift var cookies = [[Int]]() @@ -21,19 +21,19 @@ for _ in 1...9 { } ``` -And then to find a cookie: +Then, to find a cookie, you can write: ```swift let myCookie = cookies[3][6] ``` -Actually, you could create the array in a single line of code, like so: +You can also create the array in a single line of code: ```swift var cookies = [[Int]](repeating: [Int](repeating: 0, count: 7), count: 9) ``` -but that's just ugly. To be fair, you can hide the ugliness in a helper function: +This looks complicated, but can simplfy it in a helper function: ```swift func dim(_ count: Int, _ value: T) -> [T] { @@ -41,13 +41,13 @@ func dim(_ count: Int, _ value: T) -> [T] { } ``` -And then creating the array looks like this: +Then, you can create the array: ```swift var cookies = dim(9, dim(7, 0)) ``` -Swift infers that the datatype of the array should be `Int` because you specified `0` as the default value of the array elements. To use a string instead, you'd write: +Swift infers that the datatype of the array must be `Int` because you specified `0` as the default value of the array elements. To use a string instead, you can write: ```swift var cookies = dim(9, dim(7, "yum")) @@ -59,9 +59,9 @@ The `dim()` function makes it easy to go into even more dimensions: var threeDimensions = dim(2, dim(3, dim(4, 0))) ``` -The downside of using multi-dimensional arrays in this fashion -- actually, multiple nested arrays -- is that it's easy to lose track of what dimension represents what. +The downside of using multi-dimensional arrays or multiple nested arrays in this way is to lose track of what dimension represents what. -So instead let's create our own type that acts like a 2-D array and that is more convenient to use. Here it is, short and sweet: +Instead, you can create your own type that acts like a 2-D array which is more convenient to use: ```swift public struct Array2D { @@ -92,26 +92,24 @@ public struct Array2D { `Array2D` is a generic type, so it can hold any kind of object, not just numbers. -To create an instance of `Array2D` you'd write: +To create an instance of `Array2D`, you can write: ```swift var cookies = Array2D(columns: 9, rows: 7, initialValue: 0) ``` -Thanks to the `subscript` function, you can do the following to retrieve an object from the array: +By using the `subscript` function, you can retrieve an object from the array: ```swift let myCookie = cookies[column, row] ``` -Or change it: +Or, you can change it: ```swift cookies[column, row] = newCookie ``` -Internally, `Array2D` uses a single one-dimensional array to store the data. The index of an object in that array is given by `(row x numberOfColumns) + column`. But as a user of `Array2D` you don't have to worry about that; you only have to think in terms of "column" and "row", and let `Array2D` figure out the details for you. That's the advantage of wrapping primitive types into a wrapper class or struct. - -And that's all there is to it. +Internally, `Array2D` uses a single one-dimensional array to store the data. The index of an object in that array is given by `(row x numberOfColumns) + column`, but as a user of `Array2D`, you only need to think in terms of "column" and "row", and the details will be done by `Array2D`. This is the advantage of wrapping primitive types into a wrapper class or struct. *Written for Swift Algorithm Club by Matthijs Hollemans* From 777bf7b948e75d77bbac8cbba5dc40716c6b5d61 Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Thu, 6 Apr 2017 16:34:58 +0300 Subject: [PATCH 0898/1679] Deleted unnecessary code and added comments --- .../Dijkstra.playground/Contents.swift | 37 +++++++++++++------ 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/Dijkstra Algorithm/Dijkstra.playground/Contents.swift b/Dijkstra Algorithm/Dijkstra.playground/Contents.swift index 8d600d577..13087a8f9 100644 --- a/Dijkstra Algorithm/Dijkstra.playground/Contents.swift +++ b/Dijkstra Algorithm/Dijkstra.playground/Contents.swift @@ -3,19 +3,15 @@ import Foundation import UIKit -open class ProductVertex: Vertex {} - open class Vertex: Hashable, Equatable { open var identifier: String! open var neighbors: [(Vertex, Double)] = [] open var pathLengthFromStart: Double = Double.infinity open var pathVerticesFromStart: [Vertex] = [] -// open var point: CGPoint! - public init(identifier: String/*, point: CGPoint*/) { + public init(identifier: String) { self.identifier = identifier -// self.point = point } open var hashValue: Int { @@ -77,7 +73,9 @@ public class Dijkstra { var _vertices: Set = Set() func createNotConnectedVertices() { - for i in 0..<15 { + //change this value to increase or decrease amount of vertices in the graph + let numberOfVerticesInGraph = 15 + for i in 0.. Vertex { return newSet[index] } +func randomVertex() -> Vertex { + let offset = Int(arc4random_uniform(UInt32(_vertices.count))) + let index = _vertices.index(_vertices.startIndex, offsetBy: offset) + return _vertices[index] +} + +//initialize random graph createNotConnectedVertices() setupConnections() + +//initialize Dijkstra algorithm with graph vertices let dijkstra = Dijkstra(vertices: _vertices) -let offset = Int(arc4random_uniform(UInt32(_vertices.count))) -let index = _vertices.index(_vertices.startIndex, offsetBy: offset) -let startVertex = _vertices[index] + +//decide which vertex will be the starting one +let startVertex = randomVertex() + +//ask algorithm to find shortest paths from start vertex to all others dijkstra.findShortestPaths(from: startVertex) + +//printing results let destinationVertex = randomVertex(except: startVertex) -destinationVertex.pathLengthFromStart -destinationVertex.pathVerticesFromStart +print(destinationVertex.pathLengthFromStart) +var pathVerticesFromStartString: [String] = [] +for vertex in destinationVertex.pathVerticesFromStart { + pathVerticesFromStartString.append(vertex.identifier) +} +print(pathVerticesFromStartString.joined(separator: "->")) From 11fdc6ca756b4d402e807a0f9b6063fd6f38dab1 Mon Sep 17 00:00:00 2001 From: Parva9eh Date: Thu, 6 Apr 2017 11:57:03 -0700 Subject: [PATCH 0899/1679] Revisions in README.markdown I have revised your document to be more concise. --- Graph/README.markdown | 62 +++++++++++++++++++++---------------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/Graph/README.markdown b/Graph/README.markdown index a2531e808..bc33b044a 100644 --- a/Graph/README.markdown +++ b/Graph/README.markdown @@ -1,26 +1,26 @@ # Graph -A graph is something that looks like this: +A graph looks like the following picture: ![A graph](Images/Graph.png) -In computer-science lingo, a graph is a set of *vertices* paired with a set of *edges*. The vertices are the round things and the edges are the lines between them. Edges connect a vertex to other vertices. +In computer science, a graph is defined as a set of *vertices* paired with a set of *edges*. The vertices are represented by circles, and the edges are the lines between them. Edges connect a vertex to other vertices. -> **Note:** Vertices are sometimes also called "nodes" and edges are also called "links". +> **Note:** Vertices are sometimes called "nodes", and edges are called "links". -For example, a graph can represent a social network. Each person is a vertex, and people who know each other are connected by edges. A somewhat historically inaccurate example: +A graph can represent a social network. Each person is a vertex, and people who know each other are connected by edges. Here is a somewhat historically inaccurate example: ![Social network](Images/SocialNetwork.png) -Graphs come in all kinds of shapes and sizes. The edges can have a *weight*, where a positive or negative numeric value is assigned to each edge. Consider an example of a graph representing airplane flights. Cities can be vertices, and flights can be edges. Then an edge weight could describe flight time or the price of a ticket. +Graphs have various shapes and sizes. The edges can have a *weight*, where a positive or negative numeric value is assigned to each edge. Consider an example of a graph representing airplane flights. Cities can be vertices, and flights can be edges. Then, an edge weight could describe flight time or the price of a ticket. ![Airplane flights](Images/Flights.png) With this hypothetical airline, flying from San Francisco to Moscow is cheapest by going through New York. -Edges can also be *directed*. So far the edges you've seen have been undirected, so if Ada knows Charles, then Charles also knows Ada. A directed edge, on the other hand, implies a one-way relationship. A directed edge from vertex X to vertex Y connects X to Y, but *not* Y to X. +Edges can also be *directed*. In examples mentioned above, the edges are undirected. For instance, if Ada knows Charles, then Charles also knows Ada. A directed edge, on the other hand, implies a one-way relationship. A directed edge from vertex X to vertex Y connects X to Y, but *not* Y to X. -Continuing from the flights example, a directed edge from San Francisco to Juneau in Alaska would indicate that there is a flight from San Francisco to Juneau, but not from Juneau to San Francisco (I suppose that means you're walking back). +Continuing from the flights example, a directed edge from San Francisco to Juneau in Alaska indicates that there is a flight from San Francisco to Juneau, but not from Juneau to San Francisco (I suppose that means you're walking back). ![One-way flights](Images/FlightsDirected.png) @@ -28,51 +28,51 @@ The following are also graphs: ![Tree and linked list](Images/TreeAndList.png) -On the left is a [tree](../Tree/) structure, on the right a [linked list](../Linked%20List/). Both can be considered graphs, but in a simpler form. After all, they have vertices (nodes) and edges (links). +On the left is a [tree](../Tree/) structure, on the right a [linked list](../Linked%20List/). They can be considered graphs but in a simpler form. They both have vertices (nodes) and edges (links). -The very first graph I showed you contained *cycles*, where you can start off at a vertex, follow a path, and come back to the original vertex. A tree is a graph without such cycles. +The first graph includes *cycles*, where you can start off at a vertex, follow a path, and come back to the original vertex. A tree is a graph without such cycles. -Another very common type of graph is the *directed acyclic graph* or DAG: +Another common type of graph is the *directed acyclic graph* or DAG: ![DAG](Images/DAG.png) -Like a tree this does not have any cycles in it (no matter where you start, there is no path back to the starting vertex), but unlike a tree the edges are directional and the shape doesn't necessarily form a hierarchy. +Like a tree, this graph does not have any cycles (no matter where you start, there is no path back to the starting vertex), but this graph has directional edges with the shape that does not necessarily form a hierarchy. ## Why use graphs? -Maybe you're shrugging your shoulders and thinking, what's the big deal? Well, it turns out that graphs are an extremely useful data structure. +Maybe you're shrugging your shoulders and thinking, what's the big deal? Well, it turns out that a graph is a useful data structure. -If you have some programming problem where you can represent some of your data as vertices and some of it as edges between those vertices, then you can draw your problem as a graph and use well-known graph algorithms such as [breadth-first search](../Breadth-First%20Search/) or [depth-first search](../Depth-First%20Search) to find a solution. +If you have a programming problem where you can represent your data as vertices and edges, then you can draw your problem as a graph and use well-known graph algorithms such as [breadth-first search](../Breadth-First%20Search/) or [depth-first search](../Depth-First%20Search) to find a solution. -For example, let's say you have a list of tasks where some tasks have to wait on others before they can begin. You can model this using an acyclic directed graph: +For example, suppose you have a list of tasks where some tasks have to wait on others before they can begin. You can model this using an acyclic directed graph: ![Tasks as a graph](Images/Tasks.png) -Each vertex represents a task. Here, an edge between two vertices means that the source task must be completed before the destination task can start. So task C cannot start before B and D are finished, and B nor D can start before A is finished. +Each vertex represents a task. An edge between two vertices means the source task must be completed before the destination task can start. As an example, task C cannot start before B and D are finished, and B nor D can start before A is finished. Now that the problem is expressed using a graph, you can use a depth-first search to perform a [topological sort](../Topological%20Sort/). This will put the tasks in an optimal order so that you minimize the time spent waiting for tasks to complete. (One possible order here is A, B, D, E, C, F, G, H, I, J, K.) -Whenever you're faced with a tough programming problem, ask yourself, "how can I express this problem using a graph?" Graphs are all about representing relationships between your data. The trick is in how you define "relationship". +Whenever you are faced with a tough programming problem, ask yourself, "how can I express this problem using a graph?" Graphs are all about representing relationships between your data. The trick is in how you define "relationships". -If you're a musician you might appreciate this graph: +If you are a musician you might appreciate this graph: ![Chord map](Images/ChordMap.png) -The vertices are chords from the C major scale. The edges -- the relationships between the chords -- represent how [likely one chord is to follow another](http://mugglinworks.com/chordmaps/genmap.htm). This is a directed graph, so the direction of the arrows shows how you can go from one chord to the next. It's also a weighted graph, where the weight of the edges -- portrayed here by line thickness -- shows a strong relationship between two chords. As you can see, a G7-chord is very likely to be followed by a C chord, and much less likely by a Am chord. +The vertices are chords from the C major scale. The edges -- the relationships between the chords -- represent how [likely one chord is to follow another](http://mugglinworks.com/chordmaps/genmap.htm). This is a directed graph, so the direction of the arrows shows how you can go from one chord to the next. It is also a weighted graph, where the weight of the edges -- portrayed here by line thickness -- shows a strong relationship between two chords. As you can see, a G7-chord is very likely to be followed by a C chord, and much less likely by a Am chord. -You're probably already using graphs without even knowing it. Your data model is also a graph (from Apple's Core Data documentation): +You are probably already using graphs without even knowing it. Your data model is also a graph (from Apple's Core Data documentation): ![Core Data model](https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/CoreDataVersioning/Art/recipe_version2.0.jpg) -Another common graph that's used by programmers is the state machine, where edges depict the conditions for transitioning between states. Here is a state machine that models my cat: +Another common graph used by programmers is the state machine, where edges depict the conditions for transitioning between states. Here is a state machine that models my cat: ![State machine](Images/StateMachine.png) -Graphs are awesome. Facebook made a fortune from their social graph. If you're going to learn any data structure, it should be the graph and the vast collection of standard graph algorithms. +Graphs are awesome. Facebook made a fortune from their social graph. If you are going to learn any data structure, you must choose the graph and the vast collection of standard graph algorithms. ## Vertices and edges, oh my! -In theory, a graph is just a bunch of vertex objects and a bunch of edge objects. But how do you describe these in code? +In theory, a graph is just a bunch of vertex and edge objects, but how do you describe this in code? There are two main strategies: adjacency list and adjacency matrix. @@ -80,9 +80,9 @@ There are two main strategies: adjacency list and adjacency matrix. ![Adjacency list](Images/AdjacencyList.png) -The adjacency list describes outgoing edges. A has an edge to B but B does not have an edge back to A, so A does not appear in B's adjacency list. Finding an edge or weight between two vertices can be expensive because there is no random access to edges–you must traverse the adjacency lists until it is found. +The adjacency list describes outgoing edges. A has an edge to B, but B does not have an edge back to A, so A does not appear in B's adjacency list. Finding an edge or weight between two vertices can be expensive because there is no random access to edges. You must traverse the adjacency lists until it is found. -**Adjacency Matrix.** In an adjacency matrix implementation, a matrix with rows and columns representing vertices stores a weight to indicate if vertices are connected, and by what weight. For example, if there is a directed edge of weight 5.6 from vertex A to vertex B, then the entry with row for vertex A, column for vertex B would have value 5.6: +**Adjacency Matrix.** In an adjacency matrix implementation, a matrix with rows and columns representing vertices stores a weight to indicate if vertices are connected and by what weight. For example, if there is a directed edge of weight 5.6 from vertex A to vertex B, then the entry with row for vertex A and column for vertex B would have the value 5.6: ![Adjacency matrix](Images/AdjacencyMatrix.png) @@ -103,7 +103,7 @@ Let *V* be the number of vertices in the graph, and *E* the number of edges. Th In the case of a *sparse* graph, where each vertex is connected to only a handful of other vertices, an adjacency list is the best way to store the edges. If the graph is *dense*, where each vertex is connected to most of the other vertices, then a matrix is preferred. -We'll show you sample implementations of both adjacency list and adjacency matrix. +Here are sample implementations of both adjacency list and adjacency matrix: ## The code: edges and vertices @@ -137,9 +137,9 @@ It stores arbitrary data with a generic type `T`, which is `Hashable` to enforce ## The code: graphs -> **Note:** There are many, many ways to implement graphs. The code given here is just one possible implementation. You probably want to tailor the graph code to each individual problem you're trying to solve. For instance, your edges may not need a `weight` property, or you may not have the need to distinguish between directed and undirected edges. +> **Note:** There are many ways to implement graphs. The code given here is just one possible implementation. You probably want to tailor the graph code to each individual problem you are trying to solve. For instance, your edges may not need a `weight` property, or you may not have the need to distinguish between directed and undirected edges. -Here's an example of a very simple graph: +Here is an example of a simple graph: ![Demo](Images/Demo1.png) @@ -165,7 +165,7 @@ for graph in [AdjacencyMatrixGraph(), AdjacencyListGraph()] { } ``` -As mentioned earlier, to create an undirected edge you need to make two directed edges. If we wanted undirected graphs, we'd call this method instead, which takes care of that work for us: +As mentioned earlier, to create an undirected edge you need to make two directed edges. For undirected graphs, we call the following method instead: ```swift graph.addUndirectedEdge(v1, to: v2, withWeight: 1.0) @@ -198,7 +198,7 @@ private class EdgeList where T: Equatable, T: Hashable { } ``` -They are implemented as a class as opposed to structs so we can modify them by reference, in place, like when adding an edge to a new vertex, where the source vertex already has an edge list: +They are implemented as a class as opposed to structs, so we can modify them by reference, in place, like when adding an edge to a new vertex, where the source vertex already has an edge list: ```swift open override func createVertex(_ data: T) -> Vertex { @@ -231,7 +231,7 @@ where the general form `a -> [(b: w), ...]` means an edge exists from `a` to `b` ## The code: adjacency matrix -We'll keep track of the adjacency matrix in a two-dimensional `[[Double?]]` array. An entry of `nil` indicates no edge, while any other value indicates an edge of the given weight. If `adjacencyMatrix[i][j]` is not nil, then there is an edge from vertex `i` to vertex `j`. +We will keep track of the adjacency matrix in a two-dimensional `[[Double?]]` array. An entry of `nil` indicates no edge, while any other value indicates an edge of the given weight. If `adjacencyMatrix[i][j]` is not nil, then there is an edge from vertex `i` to vertex `j`. To index into the matrix using vertices, we use the `index` property in `Vertex`, which is assigned when creating the vertex through the graph object. When creating a new vertex, the graph must resize the matrix: @@ -277,6 +277,6 @@ Then the adjacency matrix looks like this: ## See also -This article described what a graph is and how you can implement the basic data structure. But we have many more articles on practical uses for graphs, so check those out too! +This article described what a graph is, and how you can implement the basic data structure. We have other articles on practical uses of graphs, so check those out too! *Written by Donald Pinckney and Matthijs Hollemans* From 0a77b0685a7c26512377ba57ed02d2ee4644a880 Mon Sep 17 00:00:00 2001 From: Parva9eh Date: Thu, 6 Apr 2017 13:57:39 -0700 Subject: [PATCH 0900/1679] Revisions in README.markdown I have revised your document to be more concise. --- Binary Search Tree/README.markdown | 138 ++++++++++++++--------------- 1 file changed, 69 insertions(+), 69 deletions(-) diff --git a/Binary Search Tree/README.markdown b/Binary Search Tree/README.markdown index b3b955c61..14ef931b9 100644 --- a/Binary Search Tree/README.markdown +++ b/Binary Search Tree/README.markdown @@ -2,7 +2,7 @@ A binary search tree is a special kind of [binary tree](../Binary%20Tree/) (a tree in which each node has at most two children) that performs insertions and deletions such that the tree is always sorted. -If you don't know what a tree is or what it is for, then [read this first](../Tree/). +For more iformation about a tree, [read this first](../Tree/). ## "Always sorted" property @@ -12,56 +12,56 @@ Here is an example of a valid binary search tree: Notice how each left child is smaller than its parent node, and each right child is greater than its parent node. This is the key feature of a binary search tree. -For example, `2` is smaller than `7` so it goes on the left; `5` is greater than `2` so it goes on the right. +For example, `2` is smaller than `7`, so it goes on the left; `5` is greater than `2`, so it goes on the right. ## Inserting new nodes When performing an insertion, we first compare the new value to the root node. If the new value is smaller, we take the *left* branch; if greater, we take the *right* branch. We work our way down the tree this way until we find an empty spot where we can insert the new value. -Say we want to insert the new value `9`: +Suppose we want to insert the new value `9`: - We start at the root of the tree (the node with the value `7`) and compare it to the new value `9`. - `9 > 7`, so we go down the right branch and repeat the same procedure but this time on node `10`. - Because `9 < 10`, we go down the left branch. -- We've now arrived at a point where there are no more values to compare with. A new node for `9` is inserted at that location. +- We now arrived at a point where there are no more values to compare with. A new node for `9` is inserted at that location. -The tree now looks like this: +Here is the tree after inserting the new value `9`: ![After adding 9](Images/Tree2.png) -There is always only one possible place where the new element can be inserted in the tree. Finding this place is usually pretty quick. It takes **O(h)** time, where **h** is the height of the tree. +There is only one possible place where the new element can be inserted in the tree. Finding this place is usually quick. It takes **O(h)** time, where **h** is the height of the tree. > **Note:** The *height* of a node is the number of steps it takes to go from that node to its lowest leaf. The height of the entire tree is the distance from the root to the lowest leaf. Many of the operations on a binary search tree are expressed in terms of the tree's height. -By following this simple rule -- smaller values on the left, larger values on the right -- we keep the tree sorted in a way such that whenever we query it, we can quickly check if a value is in the tree. +By following this simple rule -- smaller values on the left, larger values on the right -- we keep the tree sorted, so whenever we query it, we can check if a value is in the tree. ## Searching the tree -To find a value in the tree, we essentially perform the same steps as with insertion: +To find a value in the tree, we perform the same steps as with insertion: - If the value is less than the current node, then take the left branch. - If the value is greater than the current node, take the right branch. -- And if the value is equal to the current node, we've found it! +- If the value is equal to the current node, we've found it! -Like most tree operations, this is performed recursively until either we find what we're looking for, or run out of nodes to look at. +Like most tree operations, this is performed recursively until either we find what we are looking for or run out of nodes to look at. -If we were looking for the value `5` in the example, it would go as follows: +Here is an example for searching the value `5`: ![Searching the tree](Images/Searching.png) -Thanks to the structure of the tree, searching is really fast. It runs in **O(h)** time. If you have a well-balanced tree with a million nodes, it only takes about 20 steps to find anything in this tree. (The idea is very similar to [binary search](../Binary%20Search) in an array.) +Searching is fast using the structure of the tree. It runs in **O(h)** time. If you have a well-balanced tree with a million nodes, it only takes about 20 steps to find anything in this tree. (The idea is very similar to [binary search](../Binary%20Search) in an array.) ## Traversing the tree -Sometimes you don't want to look at just a single node, but at all of them. +Sometimes you need to look at all nodes rather than only one. There are three ways to traverse a binary tree: -1. *In-order* (or *depth-first*): first look at the left child of a node, then at the node itself, and finally at its right child. -2. *Pre-order*: first look at a node, then its left and right children. +1. *In-order* (or *depth-first*): first look at the left child of a node then at the node itself and finally at its right child. +2. *Pre-order*: first look at a node then its left and right children. 3. *Post-order*: first look at the left and right children and process the node itself last. -Once again, this happens recursively. +Traversing the tree also happens recursively. If you traverse a binary search tree in-order, it looks at all the nodes as if they were sorted from low to high. For the example tree, it would print `1, 2, 5, 7, 9, 10`: @@ -69,7 +69,7 @@ If you traverse a binary search tree in-order, it looks at all the nodes as if t ## Deleting nodes -Removing nodes is also easy. After removing a node, we replace the node with either its biggest child on the left or its smallest child on the right. That way the tree is still sorted after the removal. In following example, 10 is removed and replaced with either 9 (Figure 2), or 11 (Figure 3). +Removing nodes is easy. After removing a node, we replace the node with either its biggest child on the left or its smallest child on the right. That way the tree is still sorted after the removal. In the following example, 10 is removed and replaced with either 9 (Figure 2) or 11 (Figure 3). ![Deleting a node with two children](Images/DeleteTwoChildren.png) @@ -80,9 +80,9 @@ Note the replacement needs to happen when the node has at least one child. If it ## The code (solution 1) -So much for the theory. Let's see how we can implement a binary search tree in Swift. There are different approaches you can take. First, I'll show you how to make a class-based version but we'll also look at how to make one using enums. +So much for the theory. Let's see how we can implement a binary search tree in Swift. There are different approaches you can take. First, I will show you how to make a class-based version, but we will also look at how to make one using enums. -Here's a first stab at a `BinarySearchTree` class: +Here is an example for a `BinarySearchTree` class: ```swift public class BinarySearchTree { @@ -133,21 +133,21 @@ public class BinarySearchTree { } ``` -This class describes just a single node, not the entire tree. It's a generic type, so the node can store any kind of data. It also has references to its `left` and `right` child nodes and a `parent` node. +This class describes just a single node not the entire tree. It is a generic type, so the node can store any kind of data. It also has references to its `left` and `right` child nodes and a `parent` node. -Here's how you'd use it: +Here is how you can use it: ```swift let tree = BinarySearchTree(value: 7) ``` -The `count` property determines how many nodes are in the subtree described by this node. This doesn't just count the node's immediate children but also their children and their children's children, and so on. If this particular object is the root node, then it counts how many nodes are in the entire tree. Initially, `count = 0`. +The `count` property determines how many nodes are in the subtree described by this node. This does not just count the node's immediate children but also their children and their children's children, and so on. If this particular object is the root node, then it counts how many nodes are in the entire tree. Initially, `count = 0`. -> **Note:** Because `left`, `right`, and `parent` are optionals, we can make good use of Swift's optional chaining (`?`) and nil-coalescing operators (`??`). You could also write this sort of thing with `if let` but that is less concise. +> **Note:** Because `left`, `right`, and `parent` are optional, we can make good use of Swift's optional chaining (`?`) and nil-coalescing operators (`??`). You could also write this sort of thing with `if let`, but that is less concise. ### Inserting nodes -A tree node by itself is pretty useless, so here is how you would add new nodes to the tree: +A tree node by itself is useless, so here is how you would add new nodes to the tree: ```swift public func insert(value: T) { @@ -173,9 +173,9 @@ Like so many other tree operations, insertion is easiest to implement with recur If there is no more left or right child to look at, we create a `BinarySearchTree` object for the new node and connect it to the tree by setting its `parent` property. -> **Note:** Because the whole point of a binary search tree is to have smaller nodes on the left and larger ones on the right, you should always insert elements at the root, to make to sure this remains a valid binary tree! +> **Note:** Because the whole point of a binary search tree is to have smaller nodes on the left and larger ones on the right, you should always insert elements at the root to make sure this remains a valid binary tree! -To build the complete tree from the example you'd do: +To build the complete tree from the example you can do: ```swift let tree = BinarySearchTree(value: 7) @@ -186,7 +186,7 @@ tree.insert(9) tree.insert(1) ``` -> **Note:** For reasons that will become clear later, you should insert the numbers in a somewhat random order. If you insert them in sorted order, the tree won't have the right shape. +> **Note:** For reasons that will become clear later, you should insert the numbers in a random order. If you insert them in a sorted order, the tree will not have the right shape. For convenience, let's add an init method that calls `insert()` for all the elements in an array: @@ -210,7 +210,7 @@ The first value in the array becomes the root of the tree. ### Debug output -When working with somewhat complicated data structures such as this, it's useful to have human-readable debug output. +When working with complicated data structures, it is useful to have human-readable debug output. ```swift extension BinarySearchTree: CustomStringConvertible { @@ -236,11 +236,11 @@ The root node is in the middle. With some imagination, you should see that this ![The tree](Images/Tree2.png) -By the way, you may be wondering what happens when you insert duplicate items? We always insert those in the right branch. Try it out! +You may be wondering what happens when you insert duplicate items? We always insert those in the right branch. Try it out! ### Searching -What do we do now that we have some values in our tree? Search for them, of course! Being able to find items quickly is the entire purpose of a binary search tree. :-) +What do we do now that we have some values in our tree? Search for them, of course! To find items quickly is the main purpose of a binary search tree. :-) Here is the implementation of `search()`: @@ -258,11 +258,11 @@ Here is the implementation of `search()`: I hope the logic is clear: this starts at the current node (usually the root) and compares the values. If the search value is less than the node's value, we continue searching in the left branch; if the search value is greater, we dive into the right branch. -Of course, if there are no more nodes to look at -- when `left` or `right` is nil -- then we return `nil` to indicate the search value is not in the tree. +If there are no more nodes to look at -- when `left` or `right` is nil -- then we return `nil` to indicate the search value is not in the tree. -> **Note:** In Swift that's very conveniently done with optional chaining; when you write `left?.search(value)` it automatically returns nil if `left` is nil. There's no need to explicitly check for this with an `if` statement. +> **Note:** In Swift, that is conveniently done with optional chaining; when you write `left?.search(value)` it automatically returns nil if `left` is nil. There is no need to explicitly check for this with an `if` statement. -Searching is a recursive process but you can also implement it with a simple loop instead: +Searching is a recursive process, but you can also implement it with a simple loop instead: ```swift public func search(value: T) -> BinarySearchTree? { @@ -280,9 +280,9 @@ Searching is a recursive process but you can also implement it with a simple loo } ``` -Verify for yourself that you understand that these two implementations are equivalent. Personally, I prefer to use iterative code over recursive code but your opinion may differ. ;-) +Verify that you understand these two implementations are equivalent. Personally, I prefer to use iterative code over recursive code, but your opinion may differ. ;-) -Here's how to test searching: +Here is how to test searching: ```swift tree.search(5) @@ -291,9 +291,9 @@ tree.search(7) tree.search(6) // nil ``` -The first three lines all return the corresponding `BinaryTreeNode` object. The last line returns `nil` because there is no node with value `6`. +The first three lines return the corresponding `BinaryTreeNode` object. The last line returns `nil` because there is no node with value `6`. -> **Note:** If there are duplicate items in the tree, `search()` always returns the "highest" node. That makes sense, because we start searching from the root downwards. +> **Note:** If there are duplicate items in the tree, `search()` returns the "highest" node. That makes sense, because we start searching from the root downwards. ### Traversal @@ -319,9 +319,9 @@ Remember there are 3 different ways to look at all nodes in the tree? Here they } ``` -They all do pretty much the same thing but in different orders. Notice once again that all the work is done recursively. Thanks to Swift's optional chaining, the calls to `traverseInOrder()` etc are ignored when there is no left or right child. +They all work the same but in different orders. Notice that all the work is done recursively. The Swift's optional chaining makes it clear that the calls to `traverseInOrder()` etc are ignored when there is no left or right child. -To print out all the values from the tree sorted from low to high you can write: +To print out all the values of the tree sorted from low to high you can write: ```swift tree.traverseInOrder { value in print(value) } @@ -336,7 +336,7 @@ This prints the following: 9 10 -You can also add things like `map()` and `filter()` to the tree. For example, here's an implementation of map: +You can also add things like `map()` and `filter()` to the tree. For example, here is an implementation of map: ```swift @@ -365,11 +365,11 @@ This turns the contents of the tree back into a sorted array. Try it out in the tree.toArray() // [1, 2, 5, 7, 9, 10] ``` -As an exercise for yourself, see if you can implement filter and reduce. +As an exercise, see if you can implement filter and reduce. ### Deleting nodes -We can make the code much more readable by defining some helper functions. +We can make the code more readable by defining some helper functions. ```swift private func reconnectParentToNode(node: BinarySearchTree?) { @@ -384,7 +384,7 @@ We can make the code much more readable by defining some helper functions. } ``` -Making changes to the tree involves changing a bunch of `parent` and `left` and `right` pointers. This function helps with that. It takes the parent of the current node -- that is `self` -- and connects it to another node. Usually that other node will be one of the children of `self`. +Making changes to the tree involves changing a bunch of `parent` and `left` and `right` pointers. This function helps with this implementation. It takes the parent of the current node -- that is `self` -- and connects it to another node which will be one of the children of `self`. We also need a function that returns the minimum and maximum of a node: @@ -407,7 +407,7 @@ We also need a function that returns the minimum and maximum of a node: ``` -The rest of the code is pretty self-explanatory: +The rest of the code is self-explanatory: ```swift @discardableResult public func remove() -> BinarySearchTree? { @@ -457,7 +457,7 @@ Recall that the height of a node is the distance to its lowest leaf. We can calc We look at the heights of the left and right branches and take the highest one. Again, this is a recursive procedure. Since this looks at all children of this node, performance is **O(n)**. -> **Note:** Swift's null-coalescing operator is used as shorthand to deal with `left` or `right` pointers that are nil. You could write this with `if let` but this is a lot more concise. +> **Note:** Swift's null-coalescing operator is used as shorthand to deal with `left` or `right` pointers that are nil. You could write this with `if let`, but this is more concise. Try it out: @@ -479,7 +479,7 @@ You can also calculate the *depth* of a node, which is the distance to the root. } ``` -It steps upwards through the tree, following the `parent` pointers until we reach the root node (whose `parent` is nil). This takes **O(h)** time. Example: +It steps upwards through the tree, following the `parent` pointers until we reach the root node (whose `parent` is nil). This takes **O(h)** time. Here is an example: ```swift if let node9 = tree.search(9) { @@ -489,11 +489,11 @@ if let node9 = tree.search(9) { ### Predecessor and successor -The binary search tree is always "sorted" but that doesn't mean that consecutive numbers are actually next to each other in the tree. +The binary search tree is always "sorted" but that does not mean that consecutive numbers are actually next to each other in the tree. ![Example](Images/Tree2.png) -Note that you can't find the number that comes before `7` by just looking at its left child node. The left child is `2`, not `5`. Likewise for the number that comes after `7`. +Note that you cannot find the number that comes before `7` by just looking at its left child node. The left child is `2`, not `5`. Likewise for the number that comes after `7`. The `predecessor()` function returns the node whose value precedes the current value in sorted order: @@ -512,11 +512,11 @@ The `predecessor()` function returns the node whose value precedes the current v } ``` -It's easy if we have a left subtree. In that case, the immediate predecessor is the maximum value in that subtree. You can verify in the above picture that `5` is indeed the maximum value in `7`'s left branch. +It is easy if we have a left subtree. In that case, the immediate predecessor is the maximum value in that subtree. You can verify in the above picture that `5` is indeed the maximum value in `7`'s left branch. -However, if there is no left subtree then we have to look at our parent nodes until we find a smaller value. So if we want to know what the predecessor is of node `9`, we keep going up until we find the first parent with a smaller value, which is `7`. +If there is no left subtree, then we have to look at our parent nodes until we find a smaller value. If we want to know what the predecessor is of node `9`, we keep going up until we find the first parent with a smaller value, which is `7`. -The code for `successor()` works the exact same way but mirrored: +The code for `successor()` works the same way but mirrored: ```swift public func successor() -> BinarySearchTree? { @@ -535,11 +535,11 @@ The code for `successor()` works the exact same way but mirrored: Both these methods run in **O(h)** time. -> **Note:** There is a cool variation called a ["threaded" binary tree](../Threaded%20Binary%20Tree) where "unused" left and right pointers are repurposed to make direct links between predecessor and successor nodes. Very clever! +> **Note:** There is a variation called a ["threaded" binary tree](../Threaded%20Binary%20Tree) where "unused" left and right pointers are repurposed to make direct links between predecessor and successor nodes. Very clever! ### Is the search tree valid? -If you were intent on sabotage you could turn the binary search tree into an invalid tree by calling `insert()` on a node that is not the root, like so: +If you were intent on sabotage you could turn the binary search tree into an invalid tree by calling `insert()` on a node that is not the root. Here is an example: ```swift if let node1 = tree.search(1) { @@ -547,7 +547,7 @@ if let node1 = tree.search(1) { } ``` -The value of the root node is `7`, so a node with value `100` is supposed to be in the tree's right branch. However, you're not inserting at the root but at a leaf node in the tree's left branch. So the new `100` node is in the wrong place in the tree! +The value of the root node is `7`, so a node with value `100`must be in the tree's right branch. However, you are not inserting at the root but at a leaf node in the tree's left branch. So the new `100` node is in the wrong place in the tree! As a result, doing `tree.search(100)` gives nil. @@ -562,7 +562,7 @@ You can check whether a tree is a valid binary search tree with the following me } ``` -This verifies that the left branch does indeed contain values that are less than the current node's value, and that the right branch only contains values that are larger. +This verifies the left branch contains values that are less than the current node's value, and that the right branch only contains values that are larger. Call it as follows: @@ -577,11 +577,11 @@ if let node1 = tree.search(1) { ## The code (solution 2) -We've implemented the binary tree node as a class but you can also use an enum. +We have implemented the binary tree node as a class, but you can also use an enum. -The difference is reference semantics versus value semantics. Making a change to the class-based tree will update that same instance in memory. But the enum-based tree is immutable -- any insertions or deletions will give you an entirely new copy of the tree. Which one is best totally depends on what you want to use it for. +The difference is reference semantics versus value semantics. Making a change to the class-based tree will update that same instance in memory, but the enum-based tree is immutable -- any insertions or deletions will give you an entirely new copy of the tree. Which one is best, totally depends on what you want to use it for. -Here's how you'd make a binary search tree using an enum: +Here is how you can make a binary search tree using an enum: ```swift public enum BinarySearchTree { @@ -597,9 +597,9 @@ The enum has three cases: - `Leaf` for a leaf node that has no children. - `Node` for a node that has one or two children. This is marked `indirect` so that it can hold `BinarySearchTree` values. Without `indirect` you can't make recursive enums. -> **Note:** The nodes in this binary tree don't have a reference to their parent node. It's not a major impediment but it will make certain operations slightly more cumbersome to implement. +> **Note:** The nodes in this binary tree do not have a reference to their parent node. It is not a major impediment, but it will make certain operations more cumbersome to implement. -As usual, we'll implement most functionality recursively. We'll treat each case of the enum slightly differently. For example, this is how you could calculate the number of nodes in the tree and the height of the tree: +This implementation is recursive, and each case of the enum will be treated differently. For example, this is how you can calculate the number of nodes in the tree and the height of the tree: ```swift public var count: Int { @@ -655,7 +655,7 @@ tree = tree.insert(9) tree = tree.insert(1) ``` -Notice that each time you insert something, you get back a completely new tree object. That's why you need to assign the result back to the `tree` variable. +Notice that for each insertion, you get back a new tree object, so you need to assign the result back to the `tree` variable. Here is the all-important search function: @@ -678,7 +678,7 @@ Here is the all-important search function: } ``` -As you can see, most of these functions have the same structure. +Most of these functions have the same structure. Try it out in a playground: @@ -688,7 +688,7 @@ tree.search(1) tree.search(11) // nil ``` -To print the tree for debug purposes you can use this method: +To print the tree for debug purposes, you can use this method: ```swift extension BinarySearchTree: CustomDebugStringConvertible { @@ -703,21 +703,21 @@ extension BinarySearchTree: CustomDebugStringConvertible { } ``` -When you do `print(tree)` it will look something like this: +When you do `print(tree)`, it will look like this: ((1 <- 2 -> 5) <- 7 -> (9 <- 10 -> .)) -The root node is in the middle; a dot means there is no child at that position. +The root node is in the middle, and a dot means there is no child at that position. ## When the tree becomes unbalanced... -A binary search tree is *balanced* when its left and right subtrees contain roughly the same number of nodes. In that case, the height of the tree is *log(n)*, where *n* is the number of nodes. That's the ideal situation. +A binary search tree is *balanced* when its left and right subtrees contain the same number of nodes. In that case, the height of the tree is *log(n)*, where *n* is the number of nodes. That is the ideal situation. -However, if one branch is significantly longer than the other, searching becomes very slow. We end up checking way more values than we'd ideally have to. In the worst case, the height of the tree can become *n*. Such a tree acts more like a [linked list](../Linked%20List/) than a binary search tree, with performance degrading to **O(n)**. Not good! +If one branch is significantly longer than the other, searching becomes very slow. We end up checking more values than we need. In the worst case, the height of the tree can become *n*. Such a tree acts like a [linked list](../Linked%20List/) than a binary search tree, with performance degrading to **O(n)**. Not good! -One way to make the binary search tree balanced is to insert the nodes in a totally random order. On average that should balance out the tree quite nicely. But it doesn't guarantee success, nor is it always practical. +One way to make the binary search tree balanced is to insert the nodes in a totally random order. On average that should balance out the tree well, but it not guaranteed, nor is it always practical. -The other solution is to use a *self-balancing* binary tree. This type of data structure adjusts the tree to keep it balanced after you insert or delete nodes. See [AVL tree](../AVL%20Tree) and [red-black tree](../Red-Black%20Tree) for examples. +The other solution is to use a *self-balancing* binary tree. This type of data structure adjusts the tree to keep it balanced after you insert or delete nodes. To see examples, check [AVL tree](../AVL%20Tree) and [red-black tree](../Red-Black%20Tree). ## See also From 499bd86cd7ffab858dac481735b532f1789c0ab9 Mon Sep 17 00:00:00 2001 From: Parva9eh Date: Thu, 6 Apr 2017 17:07:38 -0700 Subject: [PATCH 0901/1679] Revisions in README.markdown I have revised your document to be more concise. Some words and phrases are removed or replaced due to redundancy. --- Queue/README.markdown | 52 +++++++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/Queue/README.markdown b/Queue/README.markdown index 9efce66b9..8938e0cf1 100644 --- a/Queue/README.markdown +++ b/Queue/README.markdown @@ -2,11 +2,11 @@ A queue is a list where you can only insert new items at the back and remove items from the front. This ensures that the first item you enqueue is also the first item you dequeue. First come, first serve! -Why would you need this? Well, in many algorithms you want to add objects to a temporary list at some point and then pull them off this list again at a later time. Often the order in which you add and remove these objects matters. +Why would you need this? Well, in many algorithms you want to add objects to a temporary list and pull them off this list later. Often the order in which you add and remove these objects matters. -A queue gives you a FIFO or first-in, first-out order. The element you inserted first is also the first one to come out again. It's only fair! (A very similar data structure, the [stack](../Stack/), is LIFO or last-in first-out.) +A queue gives you a FIFO or first-in, first-out order. The element you inserted first is the first one to come out. It is only fair! (A similar data structure, the [stack](../Stack/), is LIFO or last-in first-out.) -For example, let's enqueue a number: +Here is an example to enqueue a number: ```swift queue.enqueue(10) @@ -38,11 +38,11 @@ queue.dequeue() This returns `3`, the next dequeue returns `57`, and so on. If the queue is empty, dequeuing returns `nil` or in some implementations it gives an error message. -> **Note:** A queue is not always the best choice. If the order in which the items are added and removed from the list isn't important, you might as well use a [stack](../Stack/) instead of a queue. Stacks are simpler and faster. +> **Note:** A queue is not always the best choice. If the order in which the items are added and removed from the list is not important, you can use a [stack](../Stack/) instead of a queue. Stacks are simpler and faster. ## The code -Here is a very simplistic implementation of a queue in Swift. It's just a wrapper around an array that lets you enqueue, dequeue, and peek at the front-most item: +Here is a simplistic implementation of a queue in Swift. It is a wrapper around an array to enqueue, dequeue, and peek at the front-most item: ```swift public struct Queue { @@ -74,11 +74,11 @@ public struct Queue { } ``` -This queue works just fine but it is not optimal. +This queue works well, but it is not optimal. -Enqueuing is an **O(1)** operation because adding to the end of an array always takes the same amount of time, regardless of the size of the array. So that's great. +Enqueuing is an **O(1)** operation because adding to the end of an array always takes the same amount of time regardless of the size of the array. -You might be wondering why appending items to an array is **O(1)**, or a constant-time operation. That is so because an array in Swift always has some empty space at the end. If we do the following: +You might be wondering why appending items to an array is **O(1)** or a constant-time operation. That is because an array in Swift always has some empty space at the end. If we do the following: ```swift var queue = Queue() @@ -95,13 +95,13 @@ where `xxx` is memory that is reserved but not filled in yet. Adding a new eleme [ "Ada", "Steve", "Tim", "Grace", xxx, xxx ] -This is simply matter of copying memory from one place to another, a constant-time operation. +This results by copying memory from one place to another which is a constant-time operation. -Of course, there are only a limited number of such unused spots at the end of the array. When the last `xxx` gets used and you want to add another item, the array needs to resize to make more room. +There are only a limited number of unused spots at the end of the array. When the last `xxx` gets used, and you want to add another item, the array needs to resize to make more room. -Resizing includes allocating new memory and copying all the existing data over to the new array. This is an **O(n)** process, so it's relatively slow. But since it happens only every so often, the time for appending a new element to the end of the array is still **O(1)** on average, or **O(1)** "amortized". +Resizing includes allocating new memory and copying all the existing data over to the new array. This is an **O(n)** process which is relatively slow. Since it happens occasionally, the time for appending a new element to the end of the array is still **O(1)** on average or **O(1)** "amortized". -The story for dequeueing is slightly different. To dequeue we remove the element from the *beginning* of the array, not the end. This is always an **O(n)** operation because it requires all remaining array elements to be shifted in memory. +The story for dequeueing is different. To dequeue, we remove the element from the *beginning* of the array. This is always an **O(n)** operation because it requires all remaining array elements to be shifted in memory. In our example, dequeuing the first element `"Ada"` copies `"Steve"` in the place of `"Ada"`, `"Tim"` in the place of `"Steve"`, and `"Grace"` in the place of `"Tim"`: @@ -112,13 +112,13 @@ In our example, dequeuing the first element `"Ada"` copies `"Steve"` in the plac / / / after [ "Steve", "Tim", "Grace", xxx, xxx, xxx ] -Moving all these elements in memory is always an **O(n)** operation. So with our simple implementation of a queue, enqueuing is efficient but dequeueing leaves something to be desired... +Moving all these elements in memory is always an **O(n)** operation. So with our simple implementation of a queue, enqueuing is efficient, but dequeueing leaves something to be desired... ## A more efficient queue -To make dequeuing more efficient, we can use the same trick of reserving some extra free space, but this time do it at the front of the array. We're going to have to write this code ourselves as the built-in Swift array doesn't support this out of the box. +To make dequeuing efficient, we can also reserve some extra free space but this time at the front of the array. We must write this code ourselves because the built-in Swift array does not support it. -The idea is as follows: whenever we dequeue an item, we don't shift the contents of the array to the front (slow) but mark the item's position in the array as empty (fast). After dequeuing `"Ada"`, the array is: +The main idea is whenever we dequeue an item, we do not shift the contents of the array to the front (slow) but mark the item's position in the array as empty (fast). After dequeuing `"Ada"`, the array is: [ xxx, "Steve", "Tim", "Grace", xxx, xxx ] @@ -126,13 +126,13 @@ After dequeuing `"Steve"`, the array is: [ xxx, xxx, "Tim", "Grace", xxx, xxx ] -These empty spots at the front never get reused for anything, so they're wasting space. Every so often you can trim the array by moving the remaining elements to the front again: +Because these empty spots at the front never get reused, you can periodically trim the array by moving the remaining elements to the front: [ "Tim", "Grace", xxx, xxx, xxx, xxx ] -This trimming procedure involves shifting memory so it's an **O(n)** operation. But because it only happens once in a while, dequeuing is now **O(1)** on average. +This trimming procedure involves shifting memory which is an **O(n)** operation. Because this only happens once in a while, dequeuing is **O(1)** on average. -Here is how you could implement this version of `Queue`: +Here is how you can implement this version of `Queue`: ```swift public struct Queue { @@ -176,9 +176,9 @@ public struct Queue { } ``` -The array now stores objects of type `T?` instead of just `T` because we need some way to mark array elements as being empty. The `head` variable is the index in the array of the front-most object. +The array now stores objects of type `T?` instead of just `T` because we need to mark array elements as being empty. The `head` variable is the index in the array of the front-most object. -Most of the new functionality sits in `dequeue()`. When we dequeue an item, we first set `array[head]` to `nil` to remove the object from the array. Then we increment `head` because now the next item has become the front one. +Most of the new functionality sits in `dequeue()`. When we dequeue an item, we first set `array[head]` to `nil` to remove the object from the array. Then, we increment `head` because the next item has become the front one. We go from this: @@ -190,9 +190,9 @@ to this: [ xxx, "Steve", "Tim", "Grace", xxx, xxx ] head -It's like some weird supermarket where the people in the checkout lane don't shuffle forward towards the cash register, but the cash register moves up the queue. +It is like if in a supermarket the people in the checkout lane do not shuffle forward towards the cash register, but the cash register moves up the queue. -Of course, if we never remove those empty spots at the front then the array will keep growing as we enqueue and dequeue elements. To periodically trim down the array, we do the following: +If we never remove those empty spots at the front then the array will keep growing as we enqueue and dequeue elements. To periodically trim down the array, we do the following: ```swift let percentage = Double(head)/Double(array.count) @@ -202,11 +202,11 @@ Of course, if we never remove those empty spots at the front then the array will } ``` -This calculates the percentage of empty spots at the beginning as a ratio of the total array size. If more than 25% of the array is unused, we chop off that wasted space. However, if the array is small we don't want to resize it all the time, so there must be at least 50 elements in the array before we try to trim it. +This calculates the percentage of empty spots at the beginning as a ratio of the total array size. If more than 25% of the array is unused, we chop off that wasted space. However, if the array is small we do not resize it all the time, so there must be at least 50 elements in the array before we try to trim it. > **Note:** I just pulled these numbers out of thin air -- you may need to tweak them based on the behavior of your app in a production environment. -To test this in a playground, do: +To test this in a playground, do the following: ```swift var q = Queue() @@ -251,11 +251,11 @@ q.array // [{Some "Grace"}] q.count // 1 ``` -The `nil` objects at the front have been removed and the array is no longer wasting space. This new version of `Queue` isn't much more complicated than the first one but dequeuing is now also an **O(1)** operation, just because we were a bit smarter about how we used the array. +The `nil` objects at the front have been removed, and the array is no longer wasting space. This new version of `Queue` is not more complicated than the first one but dequeuing is now also an **O(1)** operation, just because we were aware about how we used the array. ## See also -There are many other ways to create a queue. Alternative implementations use a [linked list](../Linked%20List/), a [circular buffer](../Ring%20Buffer/), or a [heap](../Heap/). +There are many ways to create a queue. Alternative implementations use a [linked list](../Linked%20List/), a [circular buffer](../Ring%20Buffer/), or a [heap](../Heap/). Variations on this theme are [deque](../Deque/), a double-ended queue where you can enqueue and dequeue at both ends, and [priority queue](../Priority%20Queue/), a sorted queue where the "most important" item is always at the front. From 0f4baf57b3485af6391de0bc06f626e8efc88c82 Mon Sep 17 00:00:00 2001 From: Parva9eh Date: Thu, 6 Apr 2017 17:38:53 -0700 Subject: [PATCH 0902/1679] Revisions in README.markdown I have revised your document to be more concise. --- Selection Sort/README.markdown | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/Selection Sort/README.markdown b/Selection Sort/README.markdown index cb8ed59c2..daebc64f4 100644 --- a/Selection Sort/README.markdown +++ b/Selection Sort/README.markdown @@ -1,6 +1,6 @@ # Selection Sort -Goal: Sort an array from low to high (or high to low). +Goal: To sort an array from low to high (or high to low). You are given an array of numbers and need to put them in the right order. The selection sort algorithm divides the array into two parts: the beginning of the array is sorted, while the rest of the array consists of the numbers that still remain to be sorted. @@ -10,20 +10,20 @@ This is similar to [insertion sort](../Insertion%20Sort/), but the difference is It works as follows: -- Find the lowest number in the array. You start at index 0, loop through all the numbers in the array, and keep track of what the lowest number is. -- Swap the lowest number you've found with the number at index 0. Now the sorted portion consists of just the number at index 0. +- Find the lowest number in the array. You must start at index 0, loop through all the numbers in the array, and keep track of what the lowest number is. +- Swap the lowest number with the number at index 0. Now, the sorted portion consists of just the number at index 0. - Go to index 1. - Find the lowest number in the rest of the array. This time you start looking from index 1. Again you loop until the end of the array and keep track of the lowest number you come across. -- Swap it with the number at index 1. Now the sorted portion contains two numbers and extends from index 0 to index 1. +- Swap the lowest number with the number at index 1. Now, the sorted portion contains two numbers and extends from index 0 to index 1. - Go to index 2. -- Find the lowest number in the rest of the array, starting from index 2, and swap it with the one at index 2. Now the array is sorted from index 0 to 2; this range contains the three lowest numbers in the array. -- And so on... until no numbers remain to be sorted. +- Find the lowest number in the rest of the array, starting from index 2, and swap it with the one at index 2. Now, the array is sorted from index 0 to 2; this range contains the three lowest numbers in the array. +- And continue until no numbers remain to be sorted. -It's called a "selection" sort, because at every step you search through the rest of the array to select the next lowest number. +It nis called a "selection" sort because at every step you search through the rest of the array to select the next lowest number. ## An example -Let's say the numbers to sort are `[ 5, 8, 3, 4, 6 ]`. We also keep track of where the sorted portion of the array ends, denoted by the `|` symbol. +Suppose the numbers to sort are `[ 5, 8, 3, 4, 6 ]`. We also keep track of where the sorted portion of the array ends, denoted by the `|` symbol. Initially, the sorted portion is empty: @@ -43,7 +43,7 @@ Again, we look for the lowest number, starting from the `|` bar. We find `4` and [ 3, 4 | 5, 8, 6 ] * * -With every step, the `|` bar moves one position to the right. We again look through the rest of the array and find `5` as the lowest number. There's no need to swap `5` with itself and we simply move forward: +With every step, the `|` bar moves one position to the right. We again look through the rest of the array and find `5` as the lowest number. There is no need to swap `5` with itself, and we simply move forward: [ 3, 4, 5 | 8, 6 ] * @@ -52,7 +52,7 @@ This process repeats until the array is sorted. Note that everything to the left [ 3, 4, 5, 6, 8 |] -As you can see, selection sort is an *in-place* sort because everything happens in the same array; no additional memory is necessary. You can also implement this as a *stable* sort so that identical elements do not get swapped around relative to each other (note that the version given below isn't stable). +The selection sort is an *in-place* sort because everything happens in the same array without using additional memory. You can also implement this as a *stable* sort so that identical elements do not get swapped around relative to each other (note that the version given below is not stable). ## The code @@ -90,9 +90,9 @@ selectionSort(list) A step-by-step explanation of how the code works: -1. If the array is empty or only contains a single element, then there's not much point to sorting it. +1. If the array is empty or only contains a single element, then there is no need to sort. -2. Make a copy of the array. This is necessary because we cannot modify the contents of the `array` parameter directly in Swift. Like Swift's own `sort()`, the `selectionSort()` function will return a sorted *copy* of the original array. +2. Make a copy of the array. This is necessary because we cannot modify the contents of the `array` parameter directly in Swift. Like the Swift's `sort()` function, the `selectionSort()` function will return a sorted *copy* of the original array. 3. There are two loops inside this function. The outer loop looks at each of the elements in the array in turn; this is what moves the `|` bar forward. @@ -100,17 +100,17 @@ A step-by-step explanation of how the code works: 5. Swap the lowest number with the current array index. The `if` check is necessary because you can't `swap()` an element with itself in Swift. -In summary: For each element of the array, selection sort swaps positions with the lowest value from the rest of the array. As a result, the array gets sorted from the left to the right. (You can also do it right-to-left, in which case you always look for the largest number in the array. Give that a try!) +In summary: For each element of the array, the selection sort swaps positions with the lowest value from the rest of the array. As a result, the array gets sorted from the left to the right. (You can also do it right-to-left, in which case you always look for the largest number in the array. Give that a try!) -> **Note:** The outer loop ends at index `a.count - 2`. The very last element will automatically always be in the correct position because at that point there are no other smaller elements left. +> **Note:** The outer loop ends at index `a.count - 2`. The very last element will automatically be in the correct position because at that point there are no other smaller elements left. -The source file [SelectionSort.swift](SelectionSort.swift) has a version of this function that uses generics, so you can also use it to sort strings and other types. +The source file [SelectionSort.swift](SelectionSort.swift) has a version of this function that uses generics, so you can also use it to sort strings and other data types. ## Performance -Selection sort is easy to understand but it performs quite badly, **O(n^2)**. It's worse than [insertion sort](../Insertion%20Sort/) but better than [bubble sort](../Bubble%20Sort/). The killer is finding the lowest element in the rest of the array. This takes up a lot of time, especially since the inner loop will be performed over and over. +The selection sort is easy to understand but it performs slow as **O(n^2)**. It is worse than [insertion sort](../Insertion%20Sort/) but better than [bubble sort](../Bubble%20Sort/). Finding the lowest element in the rest of the array is slow, especially since the inner loop will be performed repeatedly . -[Heap sort](../Heap%20Sort/) uses the same principle as selection sort but has a really fast method for finding the minimum value in the rest of the array. Its performance is **O(n log n)**. +The [Heap sort](../Heap%20Sort/) uses the same principle as selection sort but has a fast method for finding the minimum value in the rest of the array. The heap sort' performance is **O(n log n)**. ## See also From 8d84f6fdb9996e0a8b84360fd54eeb9892965e04 Mon Sep 17 00:00:00 2001 From: vincentngo Date: Thu, 6 Apr 2017 22:25:17 -0400 Subject: [PATCH 0903/1679] Spelling error --- Binary Search Tree/README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Binary Search Tree/README.markdown b/Binary Search Tree/README.markdown index 14ef931b9..80c2df7df 100644 --- a/Binary Search Tree/README.markdown +++ b/Binary Search Tree/README.markdown @@ -2,7 +2,7 @@ A binary search tree is a special kind of [binary tree](../Binary%20Tree/) (a tree in which each node has at most two children) that performs insertions and deletions such that the tree is always sorted. -For more iformation about a tree, [read this first](../Tree/). +For more information about a tree, [read this first](../Tree/). ## "Always sorted" property From 8080f271109d494eed485137392363bed2d462f4 Mon Sep 17 00:00:00 2001 From: Jacopo Mangiavacchi Date: Fri, 7 Apr 2017 19:18:26 +0200 Subject: [PATCH 0904/1679] Fix and optimizations --- .../Sources/MinimumCoinChange.swift | 89 +++++++++++-------- .../MinimumCoinChangeTests.swift | 20 +++-- 2 files changed, 66 insertions(+), 43 deletions(-) diff --git a/MinimumCoinChange/Sources/MinimumCoinChange.swift b/MinimumCoinChange/Sources/MinimumCoinChange.swift index db7edecbe..c995063ab 100644 --- a/MinimumCoinChange/Sources/MinimumCoinChange.swift +++ b/MinimumCoinChange/Sources/MinimumCoinChange.swift @@ -1,5 +1,5 @@ // -// Minimum Coin Change Problem +// Minimum Coin Change Problem Playground // Compare Greedy Algorithm and Dynamic Programming Algorithm in Swift // // Created by Jacopo Mangiavacchi on 04/03/17. @@ -7,70 +7,85 @@ import Foundation +public enum MinimumCoinChangeError: Error { + case noRestPossibleForTheGivenValue +} + public struct MinimumCoinChange { - private let sortedCoinSet: [Int] - private var cache: [Int : [Int]] + internal let sortedCoinSet: [Int] public init(coinSet: [Int]) { self.sortedCoinSet = coinSet.sorted(by: { $0 > $1} ) - self.cache = [:] } //Greedy Algorithm - public func changeGreedy(_ value: Int) -> [Int] { + public func changeGreedy(_ value: Int) throws -> [Int] { + guard value > 0 else { return [] } + var change: [Int] = [] var newValue = value - + for coin in sortedCoinSet { while newValue - coin >= 0 { change.append(coin) newValue -= coin } - if newValue == 0 { + if newValue == 0 { break } } + if newValue > 0 { + throw MinimumCoinChangeError.noRestPossibleForTheGivenValue + } + return change } //Dynamic Programming Algorithm - public mutating func changeDynamic(_ value: Int) -> [Int] { - if value <= 0 { - return [] - } + public func changeDynamic(_ value: Int) throws -> [Int] { + guard value > 0 else { return [] } - if let cached = cache[value] { - return cached - } - - var change: [Int] = [] - - var potentialChangeArray: [[Int]] = [] - - for coin in sortedCoinSet { - if value - coin >= 0 { - var potentialChange: [Int] = [] - potentialChange.append(coin) - let newPotentialValue = value - coin + var cache: [Int : [Int]] = [:] - if value > 0 { - potentialChange.append(contentsOf: changeDynamic(newPotentialValue)) - } + func _changeDynamic(_ value: Int) -> [Int] { + guard value > 0 else { return [] } - //print("value: \(value) coin: \(coin) potentialChange: \(potentialChange)") - potentialChangeArray.append(potentialChange) + if let cached = cache[value] { + return cached } + + var change: [Int] = [] + + var potentialChangeArray: [[Int]] = [] + + for coin in sortedCoinSet { + if value - coin >= 0 { + var potentialChange: [Int] = [coin] + potentialChange.append(contentsOf: _changeDynamic(value - coin)) + potentialChangeArray.append(potentialChange) + } + } + + if potentialChangeArray.count > 0 { + let sortedPotentialChangeArray = potentialChangeArray.sorted(by: { $0.count < $1.count }) + change = sortedPotentialChangeArray[0] + } + + if change.reduce(0, +) == value { + cache[value] = change + } + + return change } - - if potentialChangeArray.count > 0 { - let sortedPotentialChangeArray = potentialChangeArray.sorted(by: { $0.count < $1.count }) - change = sortedPotentialChangeArray[0] - } - - cache[value] = change + + let change: [Int] = _changeDynamic(value) + + if change.reduce(0, +) != value { + throw MinimumCoinChangeError.noRestPossibleForTheGivenValue + } + return change } } - diff --git a/MinimumCoinChange/Tests/MinimumCoinChangeTests/MinimumCoinChangeTests.swift b/MinimumCoinChange/Tests/MinimumCoinChangeTests/MinimumCoinChangeTests.swift index 86c9007ba..705113e92 100644 --- a/MinimumCoinChange/Tests/MinimumCoinChangeTests/MinimumCoinChangeTests.swift +++ b/MinimumCoinChange/Tests/MinimumCoinChangeTests/MinimumCoinChangeTests.swift @@ -3,16 +3,24 @@ import XCTest class MinimumCoinChangeTests: XCTestCase { func testExample() { - var mcc = MinimumCoinChange(coinSet: [1, 2, 5, 10, 20, 25]) + let mcc = MinimumCoinChange(coinSet: [1, 2, 5, 10, 20, 25]) + print("Coin set: \(mcc.sortedCoinSet)") - for i in 0..<100 { - let greedy = mcc.changeGreedy(i) - let dynamic = mcc.changeDynamic(i) + do { + for i in 0..<100 { + let greedy = try mcc.changeGreedy(i) + let dynamic = try mcc.changeDynamic(i) - if greedy.count != dynamic.count { - print("\(i): greedy = \(greedy) dynamic = \(dynamic)") + XCTAssertEqual(greedy.reduce(0, +), dynamic.reduce(0, +), "Greedy and Dynamic return two different changes") + + if greedy.count != dynamic.count { + print("\(i): greedy = \(greedy) dynamic = \(dynamic)") + } } } + catch { + XCTFail("Test Failed: impossible to change with the given coin set") + } } static var allTests = [ From 7abd8765deff7437e591730ea5c4cbf263ec9fc6 Mon Sep 17 00:00:00 2001 From: Ievgen Pavliuk Date: Sat, 8 Apr 2017 14:30:42 +0200 Subject: [PATCH 0905/1679] Fixed typo in AVL --- AVL Tree/README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AVL Tree/README.markdown b/AVL Tree/README.markdown index c8d8d4628..e7515d99f 100644 --- a/AVL Tree/README.markdown +++ b/AVL Tree/README.markdown @@ -48,7 +48,7 @@ Each tree node keeps track of its current balance factor in a variable. After in ![Rotation0](Images/RotationStep0.jpg) For the rotation we're using the terminology: -* *Root* - the parent not of the subtrees that will be rotated; +* *Root* - the parent node of the subtrees that will be rotated; * *Pivot* - the node that will become parent (basically will be on the *Root*'s position) after rotation; * *RotationSubtree* - subtree of the *Pivot* upon the side of rotation * *OppositeSubtree* - subtree of the *Pivot* opposite the side of rotation From 3e62df6cff7e3408647b8da016ca4230fb2a191c Mon Sep 17 00:00:00 2001 From: Ute Schiehlen Date: Mon, 10 Apr 2017 11:18:34 +0200 Subject: [PATCH 0906/1679] Silenced warnings in print statements --- .../RedBlackTree.playground/Sources/RedBlackTree.swift | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Red-Black Tree/RedBlackTree.playground/Sources/RedBlackTree.swift b/Red-Black Tree/RedBlackTree.playground/Sources/RedBlackTree.swift index 6f3b16b86..351f89a9d 100644 --- a/Red-Black Tree/RedBlackTree.playground/Sources/RedBlackTree.swift +++ b/Red-Black Tree/RedBlackTree.playground/Sources/RedBlackTree.swift @@ -638,11 +638,11 @@ extension RedBlackTree { if let leftChild = node.leftChild, let rightChild = node.rightChild { if node.color == .red { if !leftChild.isNullLeaf && leftChild.color == .red { - print("Property-Error: Red node with key \(node.key ?? nil) has red left child") + print("Property-Error: Red node with key \(String(describing: node.key)) has red left child") return false } if !rightChild.isNullLeaf && rightChild.color == .red { - print("Property-Error: Red node with key \(node.key ?? nil) has red right child") + print("Property-Error: Red node with key \(String(describing: node.key)) has red right child") return false } } @@ -677,7 +677,7 @@ extension RedBlackTree { let addedHeight = node.color == .black ? 1 : 0 return left + addedHeight } else { - print("Property-Error: Black height violated at node with key \(node.key ?? nil)") + print("Property-Error: Black height violated at node with key \(String(describing: node.key))") return -1 } } @@ -697,7 +697,7 @@ extension RBTreeNode: CustomDebugStringConvertible { s = "key: nil" } if let parent = parent { - s += ", parent: \(parent.key)" + s += ", parent: \(String(describing: parent.key))" } if let left = leftChild { s += ", left = [" + left.debugDescription + "]" From 51d36815aaf49d23cc0630ed36459141acbdab9e Mon Sep 17 00:00:00 2001 From: Marwan Alani Date: Mon, 10 Apr 2017 15:38:52 -0400 Subject: [PATCH 0907/1679] Updated a comment about nested class declarations for Swift 3. Formatted the signature at the bottom --- Linked List/README.markdown | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/Linked List/README.markdown b/Linked List/README.markdown index 1884aeb23..c5a752e13 100644 --- a/Linked List/README.markdown +++ b/Linked List/README.markdown @@ -79,18 +79,18 @@ public class LinkedList { public typealias Node = LinkedListNode private var head: Node? - + public var isEmpty: Bool { return head == nil } - + public var first: Node? { return head } } ``` -Ideally, I'd like to put the `LinkedListNode` class inside `LinkedList` but Swift currently doesn't allow generic types to have nested types. Instead we're using a typealias so inside `LinkedList` we can write the shorter `Node` instead of `LinkedListNode`. +Ideally, we would want a class name to be as descriptive as possible, yet, we don't want to type a long name every time we want to use the class, therefore, we're using a typealias so inside `LinkedList` we can write the shorter `Node` instead of `LinkedListNode`. This linked list only has a `head` pointer, not a tail. Adding a tail pointer is left as an exercise for the reader. (I'll point out which functions would be different if we also had a tail pointer.) @@ -267,7 +267,7 @@ Let's write a method that lets you insert a new node at any index in the list. F ```swift private func nodesBeforeAndAfter(index: Int) -> (Node?, Node?) { assert(index >= 0) - + var i = index var next = head var prev: Node? @@ -283,13 +283,13 @@ Let's write a method that lets you insert a new node at any index in the list. F } ``` -This returns a tuple containing the node currently at the specified index and the node that immediately precedes it, if any. The loop is very similar to `nodeAtIndex()`, except that here we also keep track of what the previous node is as we iterate through the list. +This returns a tuple containing the node currently at the specified index and the node that immediately precedes it, if any. The loop is very similar to `nodeAtIndex()`, except that here we also keep track of what the previous node is as we iterate through the list. Let's look at an example. Suppose we have the following list: head --> A --> B --> C --> D --> E --> nil -We want to find the nodes before and after index 3. As we start the loop, `i = 3`, `next` points at `"A"`, and `prev` is nil. +We want to find the nodes before and after index 3. As we start the loop, `i = 3`, `next` points at `"A"`, and `prev` is nil. head --> A --> B --> C --> D --> E --> nil next @@ -320,7 +320,7 @@ Now that we have this helper function, we can write the method for inserting nod ```swift public func insert(value: T, atIndex index: Int) { let (prev, next) = nodesBeforeAndAfter(index) // 1 - + let newNode = Node(value: value) // 2 newNode.previous = prev newNode.next = next @@ -364,20 +364,20 @@ What else do we need? Removing nodes, of course! First we'll do `removeAll()`, w If you had a tail pointer, you'd set it to `nil` here too. -Next we'll add some functions that let you remove individual nodes. If you already have a reference to the node, then using `removeNode()` is the most optimal because you don't need to iterate through the list to find the node first. +Next we'll add some functions that let you remove individual nodes. If you already have a reference to the node, then using `removeNode()` is the most optimal because you don't need to iterate through the list to find the node first. ```swift public func remove(node: Node) -> T { let prev = node.previous let next = node.next - + if let prev = prev { prev.next = next } else { head = next } next?.previous = prev - + node.previous = nil node.next = nil return node.value @@ -412,7 +412,7 @@ If you don't have a reference to the node, you can use `removeLast()` or `remove } ``` -All these removal functions also return the value from the removed element. +All these removal functions also return the value from the removed element. ```swift list.removeLast() // "World" @@ -543,4 +543,4 @@ When performing operations on a linked list, you always need to be careful to up When processing lists, you can often use recursion: process the first element and then recursively call the function again on the rest of the list. You’re done when there is no next element. This is why linked lists are the foundation of functional programming languages such as LISP. -*Written for Swift Algorithm Club by Matthijs Hollemans* +*Originally written by Matthijs Hollemans for Ray Wenderlich's Swift Algorithm Club* From a613ca599c03a98e588e32982d57097d5b388909 Mon Sep 17 00:00:00 2001 From: Marwan Alani Date: Mon, 10 Apr 2017 16:39:50 -0400 Subject: [PATCH 0908/1679] Updated the Playground file with more comments and added an overloadded implementations of 'insert' & 'append' to accept a whole list as an argument --- .../LinkedList.playground/Contents.swift | 96 +++++++++++++++---- .../contents.xcplayground | 2 +- 2 files changed, 81 insertions(+), 17 deletions(-) diff --git a/Linked List/LinkedList.playground/Contents.swift b/Linked List/LinkedList.playground/Contents.swift index abbb90467..93ed4246d 100644 --- a/Linked List/LinkedList.playground/Contents.swift +++ b/Linked List/LinkedList.playground/Contents.swift @@ -1,30 +1,41 @@ -//: Playground - noun: a place where people can play +//: # Linked Lists -public class LinkedListNode { - var value: T - var next: LinkedListNode? - weak var previous: LinkedListNode? - - public init(value: T) { - self.value = value - } -} +// For best results, don't forget to select "Show Rendered Markup" from XCode's "Editor" menu +//: Linked List Class Declaration: public final class LinkedList { + + // Linked List's Node Class Declaration + public class LinkedListNode { + var value: T + var next: LinkedListNode? + weak var previous: LinkedListNode? + + public init(value: T) { + self.value = value + } + } + + // Typealiasing the node class to increase readability of code public typealias Node = LinkedListNode + // The head of the Linked List fileprivate var head: Node? + // Default initializer public init() {} + // Computed property to check if the linked list is empty public var isEmpty: Bool { return head == nil } + // Computed property to get the first node in the linked list (if any) public var first: Node? { return head } + // Computed property to iterate through the linked list and return the last node in the list (if any) public var last: Node? { if var node = head { while case let next? = node.next { @@ -36,6 +47,7 @@ public final class LinkedList { } } + // Computed property to iterate through the linked list and return the total number of nodes public var count: Int { if var node = head { var c = 1 @@ -49,6 +61,7 @@ public final class LinkedList { } } + // Function to return the node at a specific index public func node(atIndex index: Int) -> Node? { if index >= 0 { var node = head @@ -62,17 +75,20 @@ public final class LinkedList { return nil } + // Subscript function to return the node at a specific index public subscript(index: Int) -> T { let node = self.node(atIndex: index) assert(node != nil) return node!.value } + // Append a value public func append(_ value: T) { let newNode = Node(value: value) self.append(newNode) } + // Append a node without taking ownership (appends a copy) public func append(_ node: Node) { let newNode = LinkedListNode(value: node.value) if let lastNode = last { @@ -83,6 +99,16 @@ public final class LinkedList { } } + // Append a whole linked list without taking ownership (appends a copy) + public func append(_ list: LinkedList) { + var nodeToCopy = list.head + while let node = nodeToCopy { + self.append(node.value) + nodeToCopy = node.next + } + } + + // Private helper function to return the nodes (in a tuple) before and after a specific index private func nodesBeforeAndAfter(index: Int) -> (Node?, Node?) { assert(index >= 0) @@ -100,11 +126,13 @@ public final class LinkedList { return (prev, next) } + // Insert a value at a specific index public func insert(_ value: T, atIndex index: Int) { let newNode = Node(value: value) self.insert(newNode, atIndex: index) } + // Insert a node at a specific index without taking ownership (inserts a copy) public func insert(_ node: Node, atIndex index: Int) { let (prev, next) = nodesBeforeAndAfter(index: index) let newNode = LinkedListNode(value: node.value) @@ -118,10 +146,33 @@ public final class LinkedList { } } + // Insert a whole linked list at a specific index without taking ownership (inserts a copy) + public func insert(_ list: LinkedList, atIndex index: Int) { + if list.isEmpty { return } + var (prev, next) = nodesBeforeAndAfter(index: index) + var nodeToCopy = list.head + var newNode:Node? + while let node = nodeToCopy { + newNode = Node(value: node.value) + newNode?.previous = prev + if let previous = prev { + previous.next = newNode + } else { + self.head = newNode + } + nodeToCopy = nodeToCopy?.next + prev = newNode + } + prev?.next = next + next?.previous = prev + } + + // Function to remove all nodes from the list public func removeAll() { head = nil } + // Function to remove a specific node from the list and return its value @discardableResult public func remove(node: Node) -> T { let prev = node.previous let next = node.next @@ -138,11 +189,13 @@ public final class LinkedList { return node.value } + // Function to remove the last node in the list @discardableResult public func removeLast() -> T { assert(!isEmpty) return remove(node: last!) } + // Function to remove the node at a specific index from the list @discardableResult public func remove(atIndex index: Int) -> T { let node = self.node(atIndex: index) assert(node != nil) @@ -150,6 +203,7 @@ public final class LinkedList { } } +//: End of the base class declarations & beginning of extensions' declarations: extension LinkedList: CustomStringConvertible { public var description: String { var s = "[" @@ -218,6 +272,8 @@ extension LinkedList: ExpressibleByArrayLiteral { } } + +//: Ok, now that the declarations are done, let's see our Linked List in action: let list = LinkedList() list.isEmpty // true list.first // nil @@ -247,10 +303,20 @@ list[0] // "Hello" list[1] // "World" //list[2] // crash! +let list2 = LinkedList() +list2.append("Goodbye") +list2.append("World") +list.append(list2) // [Hello, World, Goodbye, World] +list2.removeAll() // [ ] +list2.isEmpty // true +list.removeLast() // "World" +list.remove(atIndex: 2) // "Goodbye" + + list.insert("Swift", atIndex: 1) -list[0] -list[1] -list[2] +list[0] // "Hello" +list[1] // "Swift" +list[2] // "World" print(list) list.reverse() // [World, Swift, Hello] @@ -262,9 +328,6 @@ m // [8, 6, 5] let f = list.filter { s in s.characters.count > 5 } f // [Universe, Swifty] -//list.removeAll() -//list.isEmpty - list.remove(node: list.first!) // "Universe" list.count // 2 list[0] // "Swifty" @@ -286,3 +349,4 @@ let listArrayLiteral2: LinkedList = ["Swift", "Algorithm", "Club"] listArrayLiteral2.count // 3 listArrayLiteral2[0] // "Swift" listArrayLiteral2.removeLast() // "Club" + diff --git a/Linked List/LinkedList.playground/contents.xcplayground b/Linked List/LinkedList.playground/contents.xcplayground index 06828af92..3de2b51ba 100644 --- a/Linked List/LinkedList.playground/contents.xcplayground +++ b/Linked List/LinkedList.playground/contents.xcplayground @@ -1,4 +1,4 @@ - + \ No newline at end of file From 45ef5cc2e0fb0f340744812a43b0fa329b20f867 Mon Sep 17 00:00:00 2001 From: Marwan Alani Date: Mon, 10 Apr 2017 16:57:12 -0400 Subject: [PATCH 0909/1679] Added 2 overloaded 'insert' & 'append' funcs that take a List as an argument to LinkedList.swift. Added 5 tests to LinkedListTests.swift to check the added 2 functions --- Linked List/LinkedList.swift | 51 ++++++++++++++++----- Linked List/Tests/LinkedListTests.swift | 60 +++++++++++++++++++++++++ 2 files changed, 100 insertions(+), 11 deletions(-) diff --git a/Linked List/LinkedList.swift b/Linked List/LinkedList.swift index 55593cdc9..a7ef9bf5e 100755 --- a/Linked List/LinkedList.swift +++ b/Linked List/LinkedList.swift @@ -1,14 +1,15 @@ -public class LinkedListNode { - var value: T - var next: LinkedListNode? - weak var previous: LinkedListNode? +public final class LinkedList { - public init(value: T) { - self.value = value + public class LinkedListNode { + var value: T + var next: LinkedListNode? + weak var previous: LinkedListNode? + + public init(value: T) { + self.value = value + } } -} - -public final class LinkedList { + public typealias Node = LinkedListNode fileprivate var head: Node? @@ -72,7 +73,7 @@ public final class LinkedList { } public func append(_ node: Node) { - let newNode = Node(value: node.value) + let newNode = LinkedListNode(value: node.value) if let lastNode = last { newNode.previous = lastNode lastNode.next = newNode @@ -81,6 +82,14 @@ public final class LinkedList { } } + public func append(_ list: LinkedList) { + var nodeToCopy = list.head + while let node = nodeToCopy { + self.append(node.value) + nodeToCopy = node.next + } + } + private func nodesBeforeAndAfter(index: Int) -> (Node?, Node?) { assert(index >= 0) @@ -105,7 +114,7 @@ public final class LinkedList { public func insert(_ node: Node, atIndex index: Int) { let (prev, next) = nodesBeforeAndAfter(index: index) - let newNode = Node(value: node.value) + let newNode = LinkedListNode(value: node.value) newNode.previous = prev newNode.next = next prev?.next = newNode @@ -116,6 +125,26 @@ public final class LinkedList { } } + public func insert(_ list: LinkedList, atIndex index: Int) { + if list.isEmpty { return } + var (prev, next) = nodesBeforeAndAfter(index: index) + var nodeToCopy = list.head + var newNode:Node? + while let node = nodeToCopy { + newNode = Node(value: node.value) + newNode?.previous = prev + if let previous = prev { + previous.next = newNode + } else { + self.head = newNode + } + nodeToCopy = nodeToCopy?.next + prev = newNode + } + prev?.next = next + next?.previous = prev + } + public func removeAll() { head = nil } diff --git a/Linked List/Tests/LinkedListTests.swift b/Linked List/Tests/LinkedListTests.swift index 6f58d9775..ea063cacb 100755 --- a/Linked List/Tests/LinkedListTests.swift +++ b/Linked List/Tests/LinkedListTests.swift @@ -165,7 +165,67 @@ class LinkedListTest: XCTestCase { XCTAssertTrue(prev!.next === node) XCTAssertTrue(next!.previous === node) } + + func testInsertListAtIndex() { + let list = buildList() + let list2 = LinkedList() + list2.append(99) + list2.append(102) + list.insert(list2, atIndex: 2) + XCTAssertTrue(list.count == 8) + XCTAssertEqual(list.node(atIndex: 1)?.value, 2) + XCTAssertEqual(list.node(atIndex: 2)?.value, 99) + XCTAssertEqual(list.node(atIndex: 3)?.value, 102) + XCTAssertEqual(list.node(atIndex: 4)?.value, 10) + } + func testInsertListAtFirstIndex() { + let list = buildList() + let list2 = LinkedList() + list2.append(99) + list2.append(102) + list.insert(list2, atIndex: 0) + XCTAssertTrue(list.count == 8) + XCTAssertEqual(list.node(atIndex: 0)?.value, 99) + XCTAssertEqual(list.node(atIndex: 1)?.value, 102) + XCTAssertEqual(list.node(atIndex: 2)?.value, 8) + } + + func testInsertListAtLastIndex() { + let list = buildList() + let list2 = LinkedList() + list2.append(99) + list2.append(102) + list.insert(list2, atIndex: list.count) + XCTAssertTrue(list.count == 8) + XCTAssertEqual(list.node(atIndex: 5)?.value, 5) + XCTAssertEqual(list.node(atIndex: 6)?.value, 99) + XCTAssertEqual(list.node(atIndex: 7)?.value, 102) + } + + func testAppendList() { + let list = buildList() + let list2 = LinkedList() + list2.append(99) + list2.append(102) + list.append(list2) + XCTAssertTrue(list.count == 8) + XCTAssertEqual(list.node(atIndex: 5)?.value, 5) + XCTAssertEqual(list.node(atIndex: 6)?.value, 99) + XCTAssertEqual(list.node(atIndex: 7)?.value, 102) + } + + func testAppendListToEmptyList() { + let list = LinkedList() + let list2 = LinkedList() + list2.append(5) + list2.append(10) + list.append(list2) + XCTAssertTrue(list.count == 2) + XCTAssertEqual(list.node(atIndex: 0)?.value, 5) + XCTAssertEqual(list.node(atIndex: 1)?.value, 10) + } + func testRemoveAtIndexOnListWithOneElement() { let list = LinkedList() list.append(123) From c74bec1667b6be79b6a8dd56dd09b9c0076c1ef7 Mon Sep 17 00:00:00 2001 From: Marwan Alani Date: Mon, 10 Apr 2017 19:24:50 -0400 Subject: [PATCH 0910/1679] Updated the xcode version in .travis.yml --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index b6ff6190c..d413140fc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,5 @@ language: objective-c -osx_image: xcode8 +osx_image: xcode8.3 # sudo: false install: From 84009ae732937157fd3f071b78430895968d500b Mon Sep 17 00:00:00 2001 From: Marwan Alani Date: Tue, 11 Apr 2017 19:33:40 -0400 Subject: [PATCH 0911/1679] Added proper annotation to the Linked List playground files --- .../LinkedList.playground/Contents.swift | 82 ++++++++++++++----- 1 file changed, 61 insertions(+), 21 deletions(-) diff --git a/Linked List/LinkedList.playground/Contents.swift b/Linked List/LinkedList.playground/Contents.swift index 93ed4246d..b86fbf0b4 100644 --- a/Linked List/LinkedList.playground/Contents.swift +++ b/Linked List/LinkedList.playground/Contents.swift @@ -5,7 +5,7 @@ //: Linked List Class Declaration: public final class LinkedList { - // Linked List's Node Class Declaration + /// Linked List's Node Class Declaration public class LinkedListNode { var value: T var next: LinkedListNode? @@ -16,26 +16,26 @@ public final class LinkedList { } } - // Typealiasing the node class to increase readability of code + /// Typealiasing the node class to increase readability of code public typealias Node = LinkedListNode - // The head of the Linked List + /// The head of the Linked List fileprivate var head: Node? - // Default initializer + /// Default initializer public init() {} - // Computed property to check if the linked list is empty + /// Computed property to check if the linked list is empty public var isEmpty: Bool { return head == nil } - // Computed property to get the first node in the linked list (if any) + /// Computed property to get the first node in the linked list (if any) public var first: Node? { return head } - // Computed property to iterate through the linked list and return the last node in the list (if any) + /// Computed property to iterate through the linked list and return the last node in the list (if any) public var last: Node? { if var node = head { while case let next? = node.next { @@ -47,7 +47,7 @@ public final class LinkedList { } } - // Computed property to iterate through the linked list and return the total number of nodes + /// Computed property to iterate through the linked list and return the total number of nodes public var count: Int { if var node = head { var c = 1 @@ -61,7 +61,10 @@ public final class LinkedList { } } - // Function to return the node at a specific index + /// Function to return the node at a specific index. Crashes if index is out of bounds (0...self.count) + /// + /// - Parameter index: Integer value of the node's index to be returned + /// - Returns: Optional LinkedListNode public func node(atIndex index: Int) -> Node? { if index >= 0 { var node = head @@ -75,20 +78,26 @@ public final class LinkedList { return nil } - // Subscript function to return the node at a specific index + /// Subscript function to return the node at a specific index + /// + /// - Parameter index: Integer value of the requested value's index public subscript(index: Int) -> T { let node = self.node(atIndex: index) assert(node != nil) return node!.value } - // Append a value + /// Append a value to the end of the list + /// + /// - Parameter value: The data value to be appended public func append(_ value: T) { let newNode = Node(value: value) self.append(newNode) } - // Append a node without taking ownership (appends a copy) + /// Append a copy of a LinkedListNode to the end of the list. + /// + /// - Parameter node: The node containing the value to be appended public func append(_ node: Node) { let newNode = LinkedListNode(value: node.value) if let lastNode = last { @@ -99,7 +108,9 @@ public final class LinkedList { } } - // Append a whole linked list without taking ownership (appends a copy) + /// Append a copy of a LinkedList to the end of the list. + /// + /// - Parameter list: The list to be copied and appended. public func append(_ list: LinkedList) { var nodeToCopy = list.head while let node = nodeToCopy { @@ -108,7 +119,10 @@ public final class LinkedList { } } - // Private helper function to return the nodes (in a tuple) before and after a specific index + /// A private helper funciton to find the nodes before and after a specified index. Crashes if index is out of bounds (0...self.count) + /// + /// - Parameter index: Integer value of the index between the nodes. + /// - Returns: A tuple of 2 nodes before & after the specified index respectively. private func nodesBeforeAndAfter(index: Int) -> (Node?, Node?) { assert(index >= 0) @@ -126,13 +140,21 @@ public final class LinkedList { return (prev, next) } - // Insert a value at a specific index + /// Insert a value at a specific index. Crashes if index is out of bounds (0...self.count) + /// + /// - Parameters: + /// - value: The data value to be inserted + /// - index: Integer value of the index to be insterted at public func insert(_ value: T, atIndex index: Int) { let newNode = Node(value: value) self.insert(newNode, atIndex: index) } - // Insert a node at a specific index without taking ownership (inserts a copy) + /// Insert a copy of a node at a specific index. Crashes if index is out of bounds (0...self.count) + /// + /// - Parameters: + /// - node: The node containing the value to be inserted + /// - index: Integer value of the index to be inserted at public func insert(_ node: Node, atIndex index: Int) { let (prev, next) = nodesBeforeAndAfter(index: index) let newNode = LinkedListNode(value: node.value) @@ -146,7 +168,11 @@ public final class LinkedList { } } - // Insert a whole linked list at a specific index without taking ownership (inserts a copy) + /// Insert a copy of a LinkedList at a specific index. Crashes if index is out of bounds (0...self.count) + /// + /// - Parameters: + /// - list: The LinkedList to be copied and inserted + /// - index: Integer value of the index to be inserted at public func insert(_ list: LinkedList, atIndex index: Int) { if list.isEmpty { return } var (prev, next) = nodesBeforeAndAfter(index: index) @@ -167,12 +193,15 @@ public final class LinkedList { next?.previous = prev } - // Function to remove all nodes from the list + /// Function to remove all nodes/value from the list public func removeAll() { head = nil } - // Function to remove a specific node from the list and return its value + /// Function to remove a specific node. + /// + /// - Parameter node: The node to be deleted + /// - Returns: The data value contained in the deleted node. @discardableResult public func remove(node: Node) -> T { let prev = node.previous let next = node.next @@ -189,13 +218,18 @@ public final class LinkedList { return node.value } - // Function to remove the last node in the list + /// Function to remove the last node/value in the list. Crashes if the list is empty + /// + /// - Returns: The data value contained in the deleted node. @discardableResult public func removeLast() -> T { assert(!isEmpty) return remove(node: last!) } - // Function to remove the node at a specific index from the list + /// Function to remove a node/value at a specific index. Crashes if index is out of bounds (0...self.count) + /// + /// - Parameter index: Integer value of the index of the node to be removed + /// - Returns: The data value contained in the deleted node @discardableResult public func remove(atIndex index: Int) -> T { let node = self.node(atIndex: index) assert(node != nil) @@ -204,6 +238,8 @@ public final class LinkedList { } //: End of the base class declarations & beginning of extensions' declarations: + +// MARK: - Extension to enable the standard conversion of a list to String extension LinkedList: CustomStringConvertible { public var description: String { var s = "[" @@ -217,6 +253,7 @@ extension LinkedList: CustomStringConvertible { } } +// MARK: - Extension to add a 'reverse' function to the list extension LinkedList { public func reverse() { var node = head @@ -228,6 +265,7 @@ extension LinkedList { } } +// MARK: - An extension with an implementation of 'map' & 'filter' functions extension LinkedList { public func map(transform: (T) -> U) -> LinkedList { let result = LinkedList() @@ -252,6 +290,7 @@ extension LinkedList { } } +// MARK: - Extension to enable initialization from an Array extension LinkedList { convenience init(array: Array) { self.init() @@ -262,6 +301,7 @@ extension LinkedList { } } +// MARK: - Extension to enable initialization from an Array Literal extension LinkedList: ExpressibleByArrayLiteral { public convenience init(arrayLiteral elements: T...) { self.init() From 621a28da46cebf8bcd003ef6e80afb7e63b01136 Mon Sep 17 00:00:00 2001 From: vincentngo Date: Thu, 13 Apr 2017 21:07:51 -0400 Subject: [PATCH 0912/1679] Update README.markdown --- Hash Table/README.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Hash Table/README.markdown b/Hash Table/README.markdown index 958c3595a..bc9636195 100644 --- a/Hash Table/README.markdown +++ b/Hash Table/README.markdown @@ -103,7 +103,7 @@ it first hashes the key `"lastName"` to calculate the array index, which is 3. S Common ways to implement this chaining mechanism are to use a linked list or another array. Since the order of the items in the chain does not matter, you can think of it as a set instead of a list. (Now you can also imagine where the term "bucket" comes from; we just dump all the objects together into the bucket.) -Chains should not become long becasuse the slow process of looking up items in the hash table. Ideally, we would have no chains at all, but in practice it is impossible to avoid collisions. You can improve the odds by giving the hash table enough buckets using high-quality hash functions. +Chains should not become long because the slow process of looking up items in the hash table. Ideally, we would have no chains at all, but in practice it is impossible to avoid collisions. You can improve the odds by giving the hash table enough buckets using high-quality hash functions. > **Note:** An alternative to chaining is "open addressing". The idea is this: if an array index is already taken, we put the element in the next unused bucket. This approach has its own upsides and downsides. @@ -127,7 +127,7 @@ public struct HashTable { } ``` -The `HashTable` is a generic container, and the two generic types are named `Key` (which must be `Hashable`) and `Value`. We also define two other types: `Element` is a key/value pair for useing in a chain, and `Bucket` is an array of such `Elements`. +The `HashTable` is a generic container, and the two generic types are named `Key` (which must be `Hashable`) and `Value`. We also define two other types: `Element` is a key/value pair for using in a chain, and `Bucket` is an array of such `Elements`. The main array is named `buckets`. It has a fixed size, the so-called capacity, provided by the `init(capacity)` method. We are also keeping track of how many items have been added to the hash table using the `count` variable. From 55c11cadd38ee59e89a3128860b53f63e8b0457d Mon Sep 17 00:00:00 2001 From: ph1ps Date: Fri, 14 Apr 2017 21:37:24 +0200 Subject: [PATCH 0913/1679] Claim Naive Bayes Classifier --- Naive Bayes Classifier/README.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 Naive Bayes Classifier/README.md diff --git a/Naive Bayes Classifier/README.md b/Naive Bayes Classifier/README.md new file mode 100644 index 000000000..e69de29bb From 85f8085de5131657a9f8f5e7ab8f8d3e42f39edf Mon Sep 17 00:00:00 2001 From: ph1ps Date: Fri, 14 Apr 2017 21:38:44 +0200 Subject: [PATCH 0914/1679] Add initial version of NB --- Naive Bayes Classifier/NaiveBayes.swift | 141 ++++++++++++++++++++++++ 1 file changed, 141 insertions(+) create mode 100644 Naive Bayes Classifier/NaiveBayes.swift diff --git a/Naive Bayes Classifier/NaiveBayes.swift b/Naive Bayes Classifier/NaiveBayes.swift new file mode 100644 index 000000000..c988cacbe --- /dev/null +++ b/Naive Bayes Classifier/NaiveBayes.swift @@ -0,0 +1,141 @@ +// +// main.swift +// NaiveBayes +// +// Created by Philipp Gabriel on 14.04.17. +// Copyright © 2017 ph1ps. All rights reserved. +// + +//TODO naming +import Foundation + +extension Array where Element == Double { + + func mean() -> Double { + return self.reduce(0, +) / Double(count) + } + + func standardDeviation() -> Double { + let calculatedMean = mean() + + let sum = self.reduce(0.0) { (previous, next) in + return previous + pow(next - calculatedMean, 2) + } + + return sqrt(sum / Double(count - 1)) + } +} + +extension Array where Element == Int { + + //Is this the best way?! + func uniques() -> [Int] { + return Array(Set(self)) + } + +} + +class NaiveBayes { + + var data: [[Double]] + var classes: [Int] + var variables: [Int: [(feature: Int, mean: Double, stDev: Double)]] + + init(data: [[Double]], classes: [Int]) { + self.data = data + self.classes = classes + self.variables = [Int: [(feature: Int, mean: Double, stDev: Double)]]() + } + + //TODO + //init(dataAndClasses: [[Double]], index ofClassRow: Int) {} + + //TODO: Does it really need to be n^2 runtime? + func train() { + + for `class` in 0.. Int { + let likelihoods = predictLikelihood(input: input).max { (first, second) -> Bool in + return first.1 < second.1 + } + + guard let `class` = likelihoods?.0 else { + return -1 + } + + return `class` + } + + func predictLikelihood(input: [Double]) -> [(Int, Double)] { + + var probabilityOfClasses = [Int: Double]() + let amount = classes.uniques().count + + classes.forEach { `class` in + let individual = classes.filter { $0 == `class` }.count + probabilityOfClasses[`class`] = Double(amount) / Double(individual) + } + + let probaClass = variables.map { (key, value) -> (Int, [Double]) in + let probaFeature = value.map { (feature, mean, stDev) -> Double in + let featureValue = input[feature] + let eulerPart = pow(M_E, -1 * pow(featureValue - mean, 2) / (2 * pow(stDev, 2))) + let distribution = eulerPart / sqrt(2 * .pi) / stDev + return distribution + } + return (key, probaFeature) + } + + let likelihoods = probaClass.map { (key, probaFeature) in + return (key, probaFeature.reduce(1, *) * (probabilityOfClasses[key] ?? 1.0)) + } + + let sum = likelihoods.map { $0.1 }.reduce(0, +) + let normalized = likelihoods.map { (`class`, likelihood) in + return (`class`, likelihood / sum) + } + + return normalized + } +} + +let data: [[Double]] = [ + [6,180,12], + [5.92,190,11], + [5.58,170,12], + [5.92,165,10], + [5,100,6], + [5.5,150,8], + [5.42,130,7], + [5.75,150,9] +] + +let classes = [0,0,0,0,1,1,1,1] + +let naive = NaiveBayes(data: data, classes: classes) +naive.train() +let result = naive.predictLikelihood(input: [6,130,8]) +print(result) + + + + + + + + From be4ac46a126d4f1b744bb84216ab0ef68686e2e7 Mon Sep 17 00:00:00 2001 From: Philipp Gabriel Date: Fri, 14 Apr 2017 21:40:52 +0200 Subject: [PATCH 0915/1679] Add NB to README --- README.markdown | 1 + 1 file changed, 1 insertion(+) diff --git a/README.markdown b/README.markdown index 29fc9d748..7df847960 100644 --- a/README.markdown +++ b/README.markdown @@ -116,6 +116,7 @@ Bad sorting algorithms (don't use these!): - Logistic Regression - Neural Networks - PageRank +- [Naive Bayes Classifier](Naive%20Bayes%20Classifier/) ## Data structures From f536ff10804f32066a5fdea1becfc6b80ebbf25f Mon Sep 17 00:00:00 2001 From: ARKALYK AKASH Date: Sat, 15 Apr 2017 02:06:55 +0600 Subject: [PATCH 0916/1679] Bugs fied. Readme added. --- .../EggDrop.playground/Contents.swift | 5 +++ .../EggDrop.playground/Sources/EggDrop.swift | 41 +++++++++++++++++ .../EggDrop.playground/contents.xcplayground | 4 ++ Egg Drop Problem/EggDrop.swift | 36 +++++++++------ Egg Drop Problem/README.markdown | 44 +++++++++++++++++++ .../contents.xcworkspacedata | 6 +++ 6 files changed, 123 insertions(+), 13 deletions(-) create mode 100644 Egg Drop Problem/EggDrop.playground/Contents.swift create mode 100644 Egg Drop Problem/EggDrop.playground/Sources/EggDrop.swift create mode 100644 Egg Drop Problem/EggDrop.playground/contents.xcplayground create mode 100644 Egg Drop Problem/README.markdown diff --git a/Egg Drop Problem/EggDrop.playground/Contents.swift b/Egg Drop Problem/EggDrop.playground/Contents.swift new file mode 100644 index 000000000..4ddb936b3 --- /dev/null +++ b/Egg Drop Problem/EggDrop.playground/Contents.swift @@ -0,0 +1,5 @@ + //: Playground - noun: a place where people can play + +import Cocoa + +eggDrop(numberOfEggs: 2, numberOfFloors: 4) diff --git a/Egg Drop Problem/EggDrop.playground/Sources/EggDrop.swift b/Egg Drop Problem/EggDrop.playground/Sources/EggDrop.swift new file mode 100644 index 000000000..f69284491 --- /dev/null +++ b/Egg Drop Problem/EggDrop.playground/Sources/EggDrop.swift @@ -0,0 +1,41 @@ +public func eggDrop(numberOfEggs: Int, numberOfFloors: Int) -> Int { + if numberOfEggs == 0 || numberOfFloors == 0{ + return 0 + } + if numberOfEggs == 1 || numberOfFloors == 1{ + return 1 + } + + var eggFloor = [[Int]](repeating: [Int](repeating: 0, count: numberOfFloors+1), count: numberOfEggs+1) //egg(rows) floor(cols) array to store the solutions + var attempts: Int = 0 + + for var floorNumber in (0..<(numberOfFloors+1)){ + eggFloor[1][floorNumber] = floorNumber //base case: if there's only one egg, it takes 'numberOfFloors' attempts + for var eggNumber in (2..<(numberOfEggs+1)){ + eggFloor[eggNumber][floorNumber] = 0 + } + } + eggFloor[2][1] = 1 //base case: if there's are two eggs and one floor, it takes one attempt + + for var eggNumber in (2..<(numberOfEggs+1)){ + for var floorNumber in (2..<(numberOfFloors+1)){ + eggFloor[eggNumber][floorNumber] = 1000000 + for var visitingFloor in (1..<(floorNumber+1)){ + //there are two cases + //case 1: egg breaks. meaning we'll have one less egg, and we'll have to go downstairs -> visitingFloor-1 + //case 2: egg doesn't break. meaning we'll still have 'eggs' number of eggs, and we'll go upstairs -> floorNumber-visitingFloor + attempts = 1 + max(eggFloor[eggNumber-1][visitingFloor-1], eggFloor[eggNumber][floorNumber-visitingFloor])//we add one taking into account the attempt we're taking at the moment + + if attempts < eggFloor[eggNumber][floorNumber]{ //finding the min + eggFloor[eggNumber][floorNumber] = attempts; + } + } + } + } + + return eggFloor[numberOfEggs][numberOfFloors] +} + +public func max(_ x1: Int, _ x2: Int) -> Int{ + return x1 > x2 ? x1 : x2 +} diff --git a/Egg Drop Problem/EggDrop.playground/contents.xcplayground b/Egg Drop Problem/EggDrop.playground/contents.xcplayground new file mode 100644 index 000000000..63b6dd8df --- /dev/null +++ b/Egg Drop Problem/EggDrop.playground/contents.xcplayground @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Egg Drop Problem/EggDrop.swift b/Egg Drop Problem/EggDrop.swift index 6d0aab2a1..a525793db 100644 --- a/Egg Drop Problem/EggDrop.swift +++ b/Egg Drop Problem/EggDrop.swift @@ -1,23 +1,33 @@ -func eggDrop(_ numberOfEggs: Int, numberOfFloors: Int) -> Int { - var eggFloor: [[Int]] = [] //egg(rows) floor(cols) array to store the solutions +public func eggDrop(numberOfEggs: Int, numberOfFloors: Int) -> Int { + if numberOfEggs == 0 || numberOfFloors == 0{ + return 0 + } + if numberOfEggs == 1 || numberOfFloors == 1{ + return 1 + } + + var eggFloor = [[Int]](repeating: [Int](repeating: 0, count: numberOfFloors+1), count: numberOfEggs+1) //egg(rows) floor(cols) array to store the solutions var attempts: Int = 0 - for var i in (0.. k-1 - //case 2: egg doesn't break. meaning we'll still have 'i' number of eggs, and we'll go upstairs -> j-k - attempts = 1 + max(eggFloor[i-1][k-1], eggFloor[i][j-k])//we add one taking into account the attempt we're taking at the moment + //case 2: egg doesn't break. meaning we'll still have 'eggs' number of eggs, and we'll go upstairs -> floors-k + attempts = 1 + max(eggFloor[eggNumber-1][floors-1], eggFloor[eggNumber][floorNumber-floors])//we add one taking into account the attempt we're taking at the moment - if attempts < eggFloor[i][j]{ //finding the min - eggFloor[i][j] = attempts; + if attempts < eggFloor[eggNumber][floorNumber]{ //finding the min + eggFloor[eggNumber][floorNumber] = attempts; } } } @@ -26,6 +36,6 @@ func eggDrop(_ numberOfEggs: Int, numberOfFloors: Int) -> Int { return eggFloor[numberOfEggs][numberOfFloors] } -func max(_ x1: Int, _ x2: Int){ +public func max(_ x1: Int, _ x2: Int) -> Int{ return x1 > x2 ? x1 : x2 } diff --git a/Egg Drop Problem/README.markdown b/Egg Drop Problem/README.markdown new file mode 100644 index 000000000..a58827ba3 --- /dev/null +++ b/Egg Drop Problem/README.markdown @@ -0,0 +1,44 @@ +#Egg Drop Dynamic Problem + +#Problem Description + +Given some number of floors and some number of eggs, what is the minimum number of attempts it will take to find out from which floor egg will break. + +Suppose that we wish to know which stories in a 36-story building are safe to drop eggs from, and which will cause the eggs to break on landing. We make a few assumptions: + +- An egg that survives a fall can be used again. +- A broken egg must be discarded. +- The effect of a fall is the same for all eggs. +- If an egg breaks when dropped, then it would break if dropped from a higher floor. +- If an egg survives a fall then it would survive a shorter fall. + +If only one egg is available and we wish to be sure of obtaining the right result, the experiment can be carried out in only one way. Drop the egg from the first-floor window; if it survives, drop it from the second floor window. Continue upward until it breaks. In the worst case, this method may require 36 droppings. Suppose 2 eggs are available. What is the least number of egg-droppings that is guaranteed to work in all cases? +The problem is not actually to find the critical floor, but merely to decide floors from which eggs should be dropped so that total number of trials are minimized. + +#Solution +We store all the solutions in a 2D array. Where rows represents number of eggs and columns represent number of floors. + +First, we set base cases: +1) If there's only one egg, it takes as many attempts as number of floors +2) If there's are two eggs and one floor, it takes one attempt + +eggNumber ==> Number of eggs at the moment +floorNumber ==> Floor number at the moment +visitingFloor ==> Floor being visited at the moment +attempts ==> Minimum number of attempts it will take to find out from which floor egg will break + +When we drop an egg from a floor 'floorNumber', there can be two cases (1) The egg breaks (2) The egg doesn’t break. + +1) If the egg breaks after dropping from 'floorNumberth' floor, then we only need to check for floors lower than 'floorNumber' with remaining eggs; so the problem reduces to 'floorNumber'-1 floors and 'eggNumber'-1 eggs +2) If the egg doesn’t break after dropping from the xth floor, then we only need to check for floors higher than 'floorNumber'; so the problem reduces to floors-'floorNumber' floors and 'eggNumber' eggs. + +Since we need to minimize the number of trials in worst case, we take the maximum of two cases. We consider the max of above two cases for every floor and choose the floor which yields minimum number of trials. + +```swift + +attempts = 1 + max(eggFloor[eggNumber-1][floors-1], eggFloor[eggNumber][floorNumber-floors])//we add one taking into account the attempt we're taking at the moment + +if attempts < eggFloor[eggNumber][floorNumber]{ //finding the min + eggFloor[eggNumber][floorNumber] = attempts; +} +``` diff --git a/swift-algorithm-club.xcworkspace/contents.xcworkspacedata b/swift-algorithm-club.xcworkspace/contents.xcworkspacedata index 5ac8577f5..1c6b407c3 100644 --- a/swift-algorithm-club.xcworkspace/contents.xcworkspacedata +++ b/swift-algorithm-club.xcworkspace/contents.xcworkspacedata @@ -7,6 +7,12 @@ + + + + From 75d3b5b59977a1cc54bcac2ce42e2c884eab5e69 Mon Sep 17 00:00:00 2001 From: ARKALYK AKASH Date: Sat, 15 Apr 2017 02:12:30 +0600 Subject: [PATCH 0917/1679] Bugs fixed --- Egg Drop Problem/README.markdown | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Egg Drop Problem/README.markdown b/Egg Drop Problem/README.markdown index a58827ba3..44af8174a 100644 --- a/Egg Drop Problem/README.markdown +++ b/Egg Drop Problem/README.markdown @@ -23,19 +23,21 @@ First, we set base cases: 2) If there's are two eggs and one floor, it takes one attempt eggNumber ==> Number of eggs at the moment + floorNumber ==> Floor number at the moment + visitingFloor ==> Floor being visited at the moment + attempts ==> Minimum number of attempts it will take to find out from which floor egg will break When we drop an egg from a floor 'floorNumber', there can be two cases (1) The egg breaks (2) The egg doesn’t break. -1) If the egg breaks after dropping from 'floorNumberth' floor, then we only need to check for floors lower than 'floorNumber' with remaining eggs; so the problem reduces to 'floorNumber'-1 floors and 'eggNumber'-1 eggs -2) If the egg doesn’t break after dropping from the xth floor, then we only need to check for floors higher than 'floorNumber'; so the problem reduces to floors-'floorNumber' floors and 'eggNumber' eggs. +1) If the egg breaks after dropping from 'visitingFloorth' floor, then we only need to check for floors lower than 'visitingFloor' with remaining eggs; so the problem reduces to 'visitingFloor'-1 floors and 'eggNumber'-1 eggs. +2) If the egg doesn’t break after dropping from the 'visitingFloorth' floor, then we only need to check for floors higher than 'visitingFloor'; so the problem reduces to floors-'visitingFloor' floors and 'eggNumber' eggs. Since we need to minimize the number of trials in worst case, we take the maximum of two cases. We consider the max of above two cases for every floor and choose the floor which yields minimum number of trials. ```swift - attempts = 1 + max(eggFloor[eggNumber-1][floors-1], eggFloor[eggNumber][floorNumber-floors])//we add one taking into account the attempt we're taking at the moment if attempts < eggFloor[eggNumber][floorNumber]{ //finding the min From 61949ab24314ee060f888642c59d6d20bcfa4841 Mon Sep 17 00:00:00 2001 From: ARKALYK AKASH Date: Sat, 15 Apr 2017 11:09:53 +0600 Subject: [PATCH 0918/1679] Minor changes in README --- .../EggDrop.playground/Sources/EggDrop.swift | 9 +++------ Egg Drop Problem/EggDrop.swift | 16 ++++++++-------- Egg Drop Problem/README.markdown | 19 ++++++++++++------- 3 files changed, 23 insertions(+), 21 deletions(-) diff --git a/Egg Drop Problem/EggDrop.playground/Sources/EggDrop.swift b/Egg Drop Problem/EggDrop.playground/Sources/EggDrop.swift index f69284491..897ba2dee 100644 --- a/Egg Drop Problem/EggDrop.playground/Sources/EggDrop.swift +++ b/Egg Drop Problem/EggDrop.playground/Sources/EggDrop.swift @@ -1,5 +1,5 @@ public func eggDrop(numberOfEggs: Int, numberOfFloors: Int) -> Int { - if numberOfEggs == 0 || numberOfFloors == 0{ + if numberOfEggs == 0 || numberOfFloors == 0{ //edge case: When either number of eggs or number of floors is 0, answer is 0 return 0 } if numberOfEggs == 1 || numberOfFloors == 1{ @@ -11,15 +11,12 @@ public func eggDrop(numberOfEggs: Int, numberOfFloors: Int) -> Int { for var floorNumber in (0..<(numberOfFloors+1)){ eggFloor[1][floorNumber] = floorNumber //base case: if there's only one egg, it takes 'numberOfFloors' attempts - for var eggNumber in (2..<(numberOfEggs+1)){ - eggFloor[eggNumber][floorNumber] = 0 - } } - eggFloor[2][1] = 1 //base case: if there's are two eggs and one floor, it takes one attempt + eggFloor[2][1] = 1 //base case: if there are two eggs and one floor, it takes one attempt for var eggNumber in (2..<(numberOfEggs+1)){ for var floorNumber in (2..<(numberOfFloors+1)){ - eggFloor[eggNumber][floorNumber] = 1000000 + eggFloor[eggNumber][floorNumber] = Int.max //setting the final result a high number to find out minimum for var visitingFloor in (1..<(floorNumber+1)){ //there are two cases //case 1: egg breaks. meaning we'll have one less egg, and we'll have to go downstairs -> visitingFloor-1 diff --git a/Egg Drop Problem/EggDrop.swift b/Egg Drop Problem/EggDrop.swift index a525793db..7be691f57 100644 --- a/Egg Drop Problem/EggDrop.swift +++ b/Egg Drop Problem/EggDrop.swift @@ -1,5 +1,5 @@ public func eggDrop(numberOfEggs: Int, numberOfFloors: Int) -> Int { - if numberOfEggs == 0 || numberOfFloors == 0{ + if numberOfEggs == 0 || numberOfFloors == 0{ //edge case: When either number of eggs or number of floors is 0, answer is 0 return 0 } if numberOfEggs == 1 || numberOfFloors == 1{ @@ -10,21 +10,21 @@ public func eggDrop(numberOfEggs: Int, numberOfFloors: Int) -> Int { var attempts: Int = 0 for var floorNumber in (0..<(numberOfFloors+1)){ - eggFloor[1][floorNumber] = floorNumber + eggFloor[1][floorNumber] = floorNumber //base case: if there's only one egg, it takes 'numberOfFloors' attempts for var eggNumber in (2..<(numberOfEggs+1)){ eggFloor[eggNumber][floorNumber] = 0 } } - eggFloor[2][1] = 1 + eggFloor[2][1] = 1 //base case: if there are two eggs and one floor, it takes one attempt for var eggNumber in (2..<(numberOfEggs+1)){ for var floorNumber in (2..<(numberOfFloors+1)){ - eggFloor[eggNumber][floorNumber] = 1000000 - for var floors in (1..<(floorNumber+1)){ + eggFloor[eggNumber][floorNumber] = Int.max //setting the final result a high number to find out minimum + for var visitingFloor in (1..<(floorNumber+1)){ //there are two cases - //case 1: egg breaks. meaning we'll have one less egg, and we'll have to go downstairs -> k-1 - //case 2: egg doesn't break. meaning we'll still have 'eggs' number of eggs, and we'll go upstairs -> floors-k - attempts = 1 + max(eggFloor[eggNumber-1][floors-1], eggFloor[eggNumber][floorNumber-floors])//we add one taking into account the attempt we're taking at the moment + //case 1: egg breaks. meaning we'll have one less egg, and we'll have to go downstairs -> visitingFloor-1 + //case 2: egg doesn't break. meaning we'll still have 'eggs' number of eggs, and we'll go upstairs -> floorNumber-visitingFloor + attempts = 1 + max(eggFloor[eggNumber-1][visitingFloor-1], eggFloor[eggNumber][floorNumber-visitingFloor])//we add one taking into account the attempt we're taking at the moment if attempts < eggFloor[eggNumber][floorNumber]{ //finding the min eggFloor[eggNumber][floorNumber] = attempts; diff --git a/Egg Drop Problem/README.markdown b/Egg Drop Problem/README.markdown index 44af8174a..2df3088b5 100644 --- a/Egg Drop Problem/README.markdown +++ b/Egg Drop Problem/README.markdown @@ -22,19 +22,24 @@ First, we set base cases: 1) If there's only one egg, it takes as many attempts as number of floors 2) If there's are two eggs and one floor, it takes one attempt -eggNumber ==> Number of eggs at the moment - -floorNumber ==> Floor number at the moment - -visitingFloor ==> Floor being visited at the moment - -attempts ==> Minimum number of attempts it will take to find out from which floor egg will break +- eggNumber ==> Number of eggs at the moment +- floorNumber ==> Floor number at the moment +- visitingFloor ==> Floor being visited at the moment +- attempts ==> Minimum number of attempts it will take to find out from which floor egg will break When we drop an egg from a floor 'floorNumber', there can be two cases (1) The egg breaks (2) The egg doesn’t break. 1) If the egg breaks after dropping from 'visitingFloorth' floor, then we only need to check for floors lower than 'visitingFloor' with remaining eggs; so the problem reduces to 'visitingFloor'-1 floors and 'eggNumber'-1 eggs. 2) If the egg doesn’t break after dropping from the 'visitingFloorth' floor, then we only need to check for floors higher than 'visitingFloor'; so the problem reduces to floors-'visitingFloor' floors and 'eggNumber' eggs. +```swift +for var floorNumber in (0..<(numberOfFloors+1)){ + eggFloor[1][floorNumber] = floorNumber //base case: if there's only one egg, it takes 'numberOfFloors' attempts +} + +eggFloor[2][1] = 1 //base case: if there are two eggs and one floor, it takes one attempt +``` + Since we need to minimize the number of trials in worst case, we take the maximum of two cases. We consider the max of above two cases for every floor and choose the floor which yields minimum number of trials. ```swift From 4ab987c592763cd13719411b829d8d513a64707b Mon Sep 17 00:00:00 2001 From: ARKALYK AKASH Date: Sat, 15 Apr 2017 11:14:18 +0600 Subject: [PATCH 0919/1679] Minor changes in README --- Egg Drop Problem/README.markdown | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/Egg Drop Problem/README.markdown b/Egg Drop Problem/README.markdown index 2df3088b5..eda28fa6f 100644 --- a/Egg Drop Problem/README.markdown +++ b/Egg Drop Problem/README.markdown @@ -16,32 +16,33 @@ If only one egg is available and we wish to be sure of obtaining the right resul The problem is not actually to find the critical floor, but merely to decide floors from which eggs should be dropped so that total number of trials are minimized. #Solution +- eggNumber -> Number of eggs at the moment +- floorNumber -> Floor number at the moment +- visitingFloor -> Floor being visited at the moment +- attempts -> Minimum number of attempts it will take to find out from which floor egg will break + We store all the solutions in a 2D array. Where rows represents number of eggs and columns represent number of floors. First, we set base cases: 1) If there's only one egg, it takes as many attempts as number of floors 2) If there's are two eggs and one floor, it takes one attempt -- eggNumber ==> Number of eggs at the moment -- floorNumber ==> Floor number at the moment -- visitingFloor ==> Floor being visited at the moment -- attempts ==> Minimum number of attempts it will take to find out from which floor egg will break - -When we drop an egg from a floor 'floorNumber', there can be two cases (1) The egg breaks (2) The egg doesn’t break. - -1) If the egg breaks after dropping from 'visitingFloorth' floor, then we only need to check for floors lower than 'visitingFloor' with remaining eggs; so the problem reduces to 'visitingFloor'-1 floors and 'eggNumber'-1 eggs. -2) If the egg doesn’t break after dropping from the 'visitingFloorth' floor, then we only need to check for floors higher than 'visitingFloor'; so the problem reduces to floors-'visitingFloor' floors and 'eggNumber' eggs. - ```swift for var floorNumber in (0..<(numberOfFloors+1)){ - eggFloor[1][floorNumber] = floorNumber //base case: if there's only one egg, it takes 'numberOfFloors' attempts +eggFloor[1][floorNumber] = floorNumber //base case 1: if there's only one egg, it takes 'numberOfFloors' attempts } -eggFloor[2][1] = 1 //base case: if there are two eggs and one floor, it takes one attempt +eggFloor[2][1] = 1 //base case 2: if there are two eggs and one floor, it takes one attempt ``` +When we drop an egg from a floor 'floorNumber', there can be two cases (1) The egg breaks (2) The egg doesn’t break. + +1) If the egg breaks after dropping from 'visitingFloorth' floor, then we only need to check for floors lower than 'visitingFloor' with remaining eggs; so the problem reduces to 'visitingFloor'-1 floors and 'eggNumber'-1 eggs. +2) If the egg doesn’t break after dropping from the 'visitingFloorth' floor, then we only need to check for floors higher than 'visitingFloor'; so the problem reduces to floors-'visitingFloor' floors and 'eggNumber' eggs. + Since we need to minimize the number of trials in worst case, we take the maximum of two cases. We consider the max of above two cases for every floor and choose the floor which yields minimum number of trials. +We find the answer based on the base cases and previously found answers as follows. ```swift attempts = 1 + max(eggFloor[eggNumber-1][floors-1], eggFloor[eggNumber][floorNumber-floors])//we add one taking into account the attempt we're taking at the moment From 1fbb40efe14b80d6187a9ebd698960ba3520fe3b Mon Sep 17 00:00:00 2001 From: ARKALYK AKASH Date: Sat, 15 Apr 2017 11:35:40 +0600 Subject: [PATCH 0920/1679] Example added --- Egg Drop Problem/EggDrop.playground/Contents.swift | 6 +++++- Egg Drop Problem/EggDrop.swift | 3 --- Egg Drop Problem/README.markdown | 14 +++++++++++++- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/Egg Drop Problem/EggDrop.playground/Contents.swift b/Egg Drop Problem/EggDrop.playground/Contents.swift index 4ddb936b3..d452e7f9f 100644 --- a/Egg Drop Problem/EggDrop.playground/Contents.swift +++ b/Egg Drop Problem/EggDrop.playground/Contents.swift @@ -2,4 +2,8 @@ import Cocoa -eggDrop(numberOfEggs: 2, numberOfFloors: 4) +eggDrop(numberOfEggs: 2, numberOfFloors: 2) //expected answer: 2 +eggDrop(numberOfEggs: 2, numberOfFloors: 4) //expected answer: 3 +eggDrop(numberOfEggs: 2, numberOfFloors: 6) //expected answer: 3 +eggDrop(numberOfEggs: 5, numberOfFloors: 5) //expected answer: 2 +eggDrop(numberOfEggs: 5, numberOfFloors: 20) //expected answer: 4 \ No newline at end of file diff --git a/Egg Drop Problem/EggDrop.swift b/Egg Drop Problem/EggDrop.swift index 7be691f57..897ba2dee 100644 --- a/Egg Drop Problem/EggDrop.swift +++ b/Egg Drop Problem/EggDrop.swift @@ -11,9 +11,6 @@ public func eggDrop(numberOfEggs: Int, numberOfFloors: Int) -> Int { for var floorNumber in (0..<(numberOfFloors+1)){ eggFloor[1][floorNumber] = floorNumber //base case: if there's only one egg, it takes 'numberOfFloors' attempts - for var eggNumber in (2..<(numberOfEggs+1)){ - eggFloor[eggNumber][floorNumber] = 0 - } } eggFloor[2][1] = 1 //base case: if there are two eggs and one floor, it takes one attempt diff --git a/Egg Drop Problem/README.markdown b/Egg Drop Problem/README.markdown index eda28fa6f..1a436c374 100644 --- a/Egg Drop Problem/README.markdown +++ b/Egg Drop Problem/README.markdown @@ -25,7 +25,7 @@ We store all the solutions in a 2D array. Where rows represents number of eggs a First, we set base cases: 1) If there's only one egg, it takes as many attempts as number of floors -2) If there's are two eggs and one floor, it takes one attempt +2) If there are two eggs and one floor, it takes one attempt ```swift for var floorNumber in (0..<(numberOfFloors+1)){ @@ -50,3 +50,15 @@ if attempts < eggFloor[eggNumber][floorNumber]{ //finding the min eggFloor[eggNumber][floorNumber] = attempts; } ``` +Example: +Let's assume we have 2 eggs and 2 floors. +1) We drop one egg from the first floor. If it breaks, then we get the answer. If it doesn't we'll have 2 eggs and 1 floors to work with. + attempts = 1 + maximum of 0(got the answer) and eggFloor[2][1] (base case 2 which gives us 1) + attempts = 1 + 1 = 2 +2) We drop one egg from the second floor. If it breaks, we'll have 1 egg and 1 floors to work with. If it doesn't, we'll get the answer. + attempts = 1 + maximum of eggFloor[1][1](base case 1 which gives us 1) and 0(got the answer) + attempts = 1 + 1 = 2 +3) Finding the minimum of 2 and 2 gives us 2, so the answer is 2. + 2 is the minimum number of attempts it will take to find out from which floor egg will break. + + From 082385a5ac58967b8eaf565654f1620444383ebf Mon Sep 17 00:00:00 2001 From: Arkalyk Akash Date: Sat, 15 Apr 2017 11:37:09 +0600 Subject: [PATCH 0921/1679] Update README.markdown --- Egg Drop Problem/README.markdown | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Egg Drop Problem/README.markdown b/Egg Drop Problem/README.markdown index 1a436c374..5ff6ebb1d 100644 --- a/Egg Drop Problem/README.markdown +++ b/Egg Drop Problem/README.markdown @@ -1,6 +1,6 @@ -#Egg Drop Dynamic Problem +# Egg Drop Dynamic Problem -#Problem Description +# Problem Description Given some number of floors and some number of eggs, what is the minimum number of attempts it will take to find out from which floor egg will break. @@ -15,7 +15,7 @@ Suppose that we wish to know which stories in a 36-story building are safe to dr If only one egg is available and we wish to be sure of obtaining the right result, the experiment can be carried out in only one way. Drop the egg from the first-floor window; if it survives, drop it from the second floor window. Continue upward until it breaks. In the worst case, this method may require 36 droppings. Suppose 2 eggs are available. What is the least number of egg-droppings that is guaranteed to work in all cases? The problem is not actually to find the critical floor, but merely to decide floors from which eggs should be dropped so that total number of trials are minimized. -#Solution +# Solution - eggNumber -> Number of eggs at the moment - floorNumber -> Floor number at the moment - visitingFloor -> Floor being visited at the moment From ffea424eec7b80d010d731f6f1b44c442c26cab8 Mon Sep 17 00:00:00 2001 From: Arkalyk Akash Date: Sat, 15 Apr 2017 11:37:55 +0600 Subject: [PATCH 0922/1679] Update README.markdown --- Egg Drop Problem/README.markdown | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Egg Drop Problem/README.markdown b/Egg Drop Problem/README.markdown index 5ff6ebb1d..82543502d 100644 --- a/Egg Drop Problem/README.markdown +++ b/Egg Drop Problem/README.markdown @@ -1,6 +1,6 @@ # Egg Drop Dynamic Problem -# Problem Description +## Problem Description Given some number of floors and some number of eggs, what is the minimum number of attempts it will take to find out from which floor egg will break. @@ -15,7 +15,7 @@ Suppose that we wish to know which stories in a 36-story building are safe to dr If only one egg is available and we wish to be sure of obtaining the right result, the experiment can be carried out in only one way. Drop the egg from the first-floor window; if it survives, drop it from the second floor window. Continue upward until it breaks. In the worst case, this method may require 36 droppings. Suppose 2 eggs are available. What is the least number of egg-droppings that is guaranteed to work in all cases? The problem is not actually to find the critical floor, but merely to decide floors from which eggs should be dropped so that total number of trials are minimized. -# Solution +## Solution - eggNumber -> Number of eggs at the moment - floorNumber -> Floor number at the moment - visitingFloor -> Floor being visited at the moment @@ -50,7 +50,7 @@ if attempts < eggFloor[eggNumber][floorNumber]{ //finding the min eggFloor[eggNumber][floorNumber] = attempts; } ``` -Example: +## Example Let's assume we have 2 eggs and 2 floors. 1) We drop one egg from the first floor. If it breaks, then we get the answer. If it doesn't we'll have 2 eggs and 1 floors to work with. attempts = 1 + maximum of 0(got the answer) and eggFloor[2][1] (base case 2 which gives us 1) From 260948a2b7af625ea0fe6590e3cf966975c420dd Mon Sep 17 00:00:00 2001 From: ARKALYK AKASH Date: Sat, 15 Apr 2017 11:41:32 +0600 Subject: [PATCH 0923/1679] Comments added --- Egg Drop Problem/EggDrop.playground/Sources/EggDrop.swift | 3 ++- Egg Drop Problem/EggDrop.swift | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Egg Drop Problem/EggDrop.playground/Sources/EggDrop.swift b/Egg Drop Problem/EggDrop.playground/Sources/EggDrop.swift index 897ba2dee..db1e48b95 100644 --- a/Egg Drop Problem/EggDrop.playground/Sources/EggDrop.swift +++ b/Egg Drop Problem/EggDrop.playground/Sources/EggDrop.swift @@ -2,7 +2,7 @@ public func eggDrop(numberOfEggs: Int, numberOfFloors: Int) -> Int { if numberOfEggs == 0 || numberOfFloors == 0{ //edge case: When either number of eggs or number of floors is 0, answer is 0 return 0 } - if numberOfEggs == 1 || numberOfFloors == 1{ + if numberOfEggs == 1 || numberOfFloors == 1{ //edge case: When either number of eggs or number of floors is 1, answer is 1 return 1 } @@ -33,6 +33,7 @@ public func eggDrop(numberOfEggs: Int, numberOfFloors: Int) -> Int { return eggFloor[numberOfEggs][numberOfFloors] } +//Helper function to find max of two integers public func max(_ x1: Int, _ x2: Int) -> Int{ return x1 > x2 ? x1 : x2 } diff --git a/Egg Drop Problem/EggDrop.swift b/Egg Drop Problem/EggDrop.swift index 897ba2dee..db1e48b95 100644 --- a/Egg Drop Problem/EggDrop.swift +++ b/Egg Drop Problem/EggDrop.swift @@ -2,7 +2,7 @@ public func eggDrop(numberOfEggs: Int, numberOfFloors: Int) -> Int { if numberOfEggs == 0 || numberOfFloors == 0{ //edge case: When either number of eggs or number of floors is 0, answer is 0 return 0 } - if numberOfEggs == 1 || numberOfFloors == 1{ + if numberOfEggs == 1 || numberOfFloors == 1{ //edge case: When either number of eggs or number of floors is 1, answer is 1 return 1 } @@ -33,6 +33,7 @@ public func eggDrop(numberOfEggs: Int, numberOfFloors: Int) -> Int { return eggFloor[numberOfEggs][numberOfFloors] } +//Helper function to find max of two integers public func max(_ x1: Int, _ x2: Int) -> Int{ return x1 > x2 ? x1 : x2 } From 903ce26995d275e858dc535726df8a649260a4cd Mon Sep 17 00:00:00 2001 From: ph1ps Date: Sun, 16 Apr 2017 14:37:34 +0200 Subject: [PATCH 0924/1679] Add fully functional gaussian NB & examples --- Naive Bayes Classifier/NaiveBayes.swift | 122 ++++++++++++++---------- 1 file changed, 74 insertions(+), 48 deletions(-) diff --git a/Naive Bayes Classifier/NaiveBayes.swift b/Naive Bayes Classifier/NaiveBayes.swift index c988cacbe..63edd9981 100644 --- a/Naive Bayes Classifier/NaiveBayes.swift +++ b/Naive Bayes Classifier/NaiveBayes.swift @@ -1,16 +1,15 @@ // -// main.swift +// NaiveBayes.swift // NaiveBayes // // Created by Philipp Gabriel on 14.04.17. // Copyright © 2017 ph1ps. All rights reserved. // -//TODO naming import Foundation extension Array where Element == Double { - + func mean() -> Double { return self.reduce(0, +) / Double(count) } @@ -28,18 +27,17 @@ extension Array where Element == Double { extension Array where Element == Int { - //Is this the best way?! - func uniques() -> [Int] { - return Array(Set(self)) + func uniques() -> Set { + return Set(self) } } class NaiveBayes { - - var data: [[Double]] - var classes: [Int] - var variables: [Int: [(feature: Int, mean: Double, stDev: Double)]] + + private var data: [[Double]] + private var classes: [Int] + private var variables: [Int: [(feature: Int, mean: Double, stDev: Double)]] init(data: [[Double]], classes: [Int]) { self.data = data @@ -47,30 +45,37 @@ class NaiveBayes { self.variables = [Int: [(feature: Int, mean: Double, stDev: Double)]]() } - //TODO - //init(dataAndClasses: [[Double]], index ofClassRow: Int) {} - - //TODO: Does it really need to be n^2 runtime? + convenience init(dataAndClasses: [[Double]], rowOfClass: Int) { + let classes = dataAndClasses.map { Int($0[rowOfClass]) } + let data = dataAndClasses.map { row in + return row.enumerated().filter { $0.offset != rowOfClass }.map { $0.element } + } + + self.init(data: data, classes: classes) + } + func train() { - - for `class` in 0.. Int { - let likelihoods = predictLikelihood(input: input).max { (first, second) -> Bool in + func classify(with input: [Double]) -> Int { + let likelihoods = calcLikelihoods(with: input).max { (first, second) -> Bool in return first.1 < second.1 } @@ -81,30 +86,30 @@ class NaiveBayes { return `class` } - func predictLikelihood(input: [Double]) -> [(Int, Double)] { - - var probabilityOfClasses = [Int: Double]() - let amount = classes.uniques().count + func calcLikelihoods(with input: [Double]) -> [(Int, Double)] { + + var probaClass = [Int: Double]() + let amount = classes.count classes.forEach { `class` in let individual = classes.filter { $0 == `class` }.count - probabilityOfClasses[`class`] = Double(amount) / Double(individual) + probaClass[`class`] = Double(individual) / Double(amount) } - let probaClass = variables.map { (key, value) -> (Int, [Double]) in - let probaFeature = value.map { (feature, mean, stDev) -> Double in + let classesAndFeatures = variables.map { (key, value) -> (Int, [Double]) in + let distributions = value.map { (feature, mean, stDev) -> Double in let featureValue = input[feature] let eulerPart = pow(M_E, -1 * pow(featureValue - mean, 2) / (2 * pow(stDev, 2))) let distribution = eulerPart / sqrt(2 * .pi) / stDev return distribution } - return (key, probaFeature) + return (key, distributions) } - let likelihoods = probaClass.map { (key, probaFeature) in - return (key, probaFeature.reduce(1, *) * (probabilityOfClasses[key] ?? 1.0)) + let likelihoods = classesAndFeatures.map { (key, probaFeature) in + return (key, probaFeature.reduce(1, *) * (probaClass[key] ?? 1.0)) } - + let sum = likelihoods.map { $0.1 }.reduce(0, +) let normalized = likelihoods.map { (`class`, likelihood) in return (`class`, likelihood / sum) @@ -115,27 +120,48 @@ class NaiveBayes { } let data: [[Double]] = [ - [6,180,12], - [5.92,190,11], - [5.58,170,12], - [5.92,165,10], - [5,100,6], - [5.5,150,8], - [5.42,130,7], - [5.75,150,9] + [6, 180, 12], + [5.92, 190, 11], + [5.58, 170, 12], + [5.92, 165, 10], + [5, 100, 6], + [5.5, 150, 8], + [5.42, 130, 7], + [5.75, 150, 9] ] -let classes = [0,0,0,0,1,1,1,1] +let classes = [0, 0, 0, 0, 1, 1, 1, 1] let naive = NaiveBayes(data: data, classes: classes) naive.train() -let result = naive.predictLikelihood(input: [6,130,8]) -print(result) - - - - +print(naive.classify(with: [6, 130, 8])) + +let otherData: [[Double]] = [ + [6, 180, 12, 0], + [5.92, 190, 11, 0], + [5.58, 170, 12, 0], + [5.92, 165, 10, 0], + [5, 100, 6, 1], + [5.5, 150, 8, 1], + [5.42, 130, 7, 1], + [5.75, 150, 9, 1] +] +let otherNaive = NaiveBayes(dataAndClasses: otherData, rowOfClass: 3) +otherNaive.train() +print(otherNaive.calcLikelihoods(with: [6, 130, 8])) +guard let csv = try? String(contentsOfFile: "/Users/ph1ps/Desktop/wine.csv") else { + print("file not found") + exit(0) +} +let rows = csv.characters.split(separator: "\r\n").map { String($0) } +let wineData = rows.map { row -> [Double] in + let split = row.characters.split(separator: ";") + return split.map { Double(String($0))! } +} +let wineNaive = NaiveBayes(dataAndClasses: wineData, rowOfClass: 0) +wineNaive.train() +print(wineNaive.calcLikelihoods(with: [12.85, 1.6, 2.52, 17.8, 95, 2.48, 2.37, 0.26, 1.46, 3.93, 1.09, 3.63, 1015])) From b6d40144c5ac91bd3155036fbcefca231a6dba0d Mon Sep 17 00:00:00 2001 From: ph1ps Date: Sun, 16 Apr 2017 23:52:57 +0200 Subject: [PATCH 0925/1679] Split into seperate types of NB classifier, implement strategy pattern --- Naive Bayes Classifier/NaiveBayes.swift | 209 +++++++++++++++++------- 1 file changed, 146 insertions(+), 63 deletions(-) diff --git a/Naive Bayes Classifier/NaiveBayes.swift b/Naive Bayes Classifier/NaiveBayes.swift index 63edd9981..dbbf3cd9f 100644 --- a/Naive Bayes Classifier/NaiveBayes.swift +++ b/Naive Bayes Classifier/NaiveBayes.swift @@ -33,49 +33,143 @@ extension Array where Element == Int { } +enum NBType { + + case gaussian(data: [[Double]], classes: [Int]) + case multinomial(data: [[Int]], classes: [Int]) + //case bernoulli(data: [[Bool]], classes: [Int]) --> TODO + + var classes: [Int] { + if case .gaussian(_, let classes) = self { + return classes + } else if case .multinomial(_, let classes) = self { + return classes + } + + return [] + } + + var data: [[Any]] { + if case .gaussian(let data, _) = self { + return data + } else if case .multinomial(let data, _) = self { + return data + } + + return [] + } + + func calcLikelihood(variables: [Any], input: Any) -> Double? { + + if case .gaussian = self { + + guard let input = input as? Double else { + return nil + } + + guard let mean = variables[0] as? Double else { + return nil + } + + guard let stDev = variables[1] as? Double else { + return nil + } + + let eulerPart = pow(M_E, -1 * pow(input - mean, 2) / (2 * pow(stDev, 2))) + let distribution = eulerPart / sqrt(2 * .pi) / stDev + + return distribution + + } else if case .multinomial = self { + + guard let variables = variables as? [(category: Int, probability: Double)] else { + return nil + } + + guard let input = input as? Double else { + return nil + } + + return variables.first { variable in + return variable.category == Int(input) + }?.probability + + } + + return nil + } + + func train(values: [Any]) -> [Any]? { + + if case .gaussian = self { + + guard let values = values as? [Double] else { + return nil + } + + return [values.mean(), values.standardDeviation()] + + } else if case .multinomial = self { + + guard let values = values as? [Int] else { + return nil + } + + let count = values.count + let categoryProba = values.uniques().map { value -> (Int, Double) in + return (value, Double(values.filter { $0 == value }.count) / Double(count)) + } + return categoryProba + } + + return nil + } +} + class NaiveBayes { - private var data: [[Double]] - private var classes: [Int] - private var variables: [Int: [(feature: Int, mean: Double, stDev: Double)]] + private var variables: [Int: [(feature: Int, variables: [Any])]] + private var type: NBType - init(data: [[Double]], classes: [Int]) { - self.data = data - self.classes = classes - self.variables = [Int: [(feature: Int, mean: Double, stDev: Double)]]() + init(type: NBType) { + self.type = type + self.variables = [Int: [(Int, [Any])]]() } - convenience init(dataAndClasses: [[Double]], rowOfClass: Int) { - let classes = dataAndClasses.map { Int($0[rowOfClass]) } + static func convert(dataAndClasses: [[T]], rowOfClasses: Int) -> (data: [[T]], classes: [Int]) { + let classes = dataAndClasses.map { Int($0[rowOfClasses] as! Double) } //TODO + let data = dataAndClasses.map { row in - return row.enumerated().filter { $0.offset != rowOfClass }.map { $0.element } + return row.enumerated().filter { $0.offset != rowOfClasses }.map { $0.element } } - self.init(data: data, classes: classes) + return (data, classes) } + //TODO remake pliss, i dont like this at all func train() { + var classes = type.classes + for `class` in classes.uniques() { - variables[`class`] = [(feature: Int, mean: Double, stDev: Double)]() + variables[`class`] = [(Int, [Any])]() - for feature in 0.. Int { - let likelihoods = calcLikelihoods(with: input).max { (first, second) -> Bool in + let likelihoods = classifyProba(with: input).max { (first, second) -> Bool in return first.1 < second.1 } @@ -86,8 +180,10 @@ class NaiveBayes { return `class` } - func calcLikelihoods(with input: [Double]) -> [(Int, Double)] { + //TODO fix this doesnt have to be a double + func classifyProba(with input: [Double]) -> [(Int, Double)] { + let classes = type.classes var probaClass = [Int: Double]() let amount = classes.count @@ -96,18 +192,15 @@ class NaiveBayes { probaClass[`class`] = Double(individual) / Double(amount) } - let classesAndFeatures = variables.map { (key, value) -> (Int, [Double]) in - let distributions = value.map { (feature, mean, stDev) -> Double in - let featureValue = input[feature] - let eulerPart = pow(M_E, -1 * pow(featureValue - mean, 2) / (2 * pow(stDev, 2))) - let distribution = eulerPart / sqrt(2 * .pi) / stDev - return distribution + let classesAndFeatures = variables.map { (`class`, value) -> (Int, [Double]) in + let distribution = value.map { (feature, variables) -> Double in + return type.calcLikelihood(variables: variables, input: input[feature]) ?? 0.0 } - return (key, distributions) + return (`class`, distribution) } - let likelihoods = classesAndFeatures.map { (key, probaFeature) in - return (key, probaFeature.reduce(1, *) * (probaClass[key] ?? 1.0)) + let likelihoods = classesAndFeatures.map { (`class`, distribution) in + return (`class`, distribution.reduce(1, *) * (probaClass[`class`] ?? 1.0)) } let sum = likelihoods.map { $0.1 }.reduce(0, +) @@ -119,38 +212,6 @@ class NaiveBayes { } } -let data: [[Double]] = [ - [6, 180, 12], - [5.92, 190, 11], - [5.58, 170, 12], - [5.92, 165, 10], - [5, 100, 6], - [5.5, 150, 8], - [5.42, 130, 7], - [5.75, 150, 9] -] - -let classes = [0, 0, 0, 0, 1, 1, 1, 1] - -let naive = NaiveBayes(data: data, classes: classes) -naive.train() -print(naive.classify(with: [6, 130, 8])) - -let otherData: [[Double]] = [ - [6, 180, 12, 0], - [5.92, 190, 11, 0], - [5.58, 170, 12, 0], - [5.92, 165, 10, 0], - [5, 100, 6, 1], - [5.5, 150, 8, 1], - [5.42, 130, 7, 1], - [5.75, 150, 9, 1] -] - -let otherNaive = NaiveBayes(dataAndClasses: otherData, rowOfClass: 3) -otherNaive.train() -print(otherNaive.calcLikelihoods(with: [6, 130, 8])) - guard let csv = try? String(contentsOfFile: "/Users/ph1ps/Desktop/wine.csv") else { print("file not found") exit(0) @@ -162,6 +223,28 @@ let wineData = rows.map { row -> [Double] in return split.map { Double(String($0))! } } -let wineNaive = NaiveBayes(dataAndClasses: wineData, rowOfClass: 0) +let convertedWine = NaiveBayes.convert(dataAndClasses: wineData, rowOfClasses: 0) +let wineNaive = NaiveBayes(type: .gaussian(data: convertedWine.data, classes: convertedWine.classes)) wineNaive.train() -print(wineNaive.calcLikelihoods(with: [12.85, 1.6, 2.52, 17.8, 95, 2.48, 2.37, 0.26, 1.46, 3.93, 1.09, 3.63, 1015])) +print(wineNaive.classifyProba(with: [12.85, 1.6, 2.52, 17.8, 95, 2.48, 2.37, 0.26, 1.46, 3.93, 1.09, 3.63, 1015])) + +let golfData = [ + [0, 0, 0, 0], + [0, 0, 0, 1], + [1, 0, 0, 0], + [2, 1, 0, 0], + [2, 2, 1, 0], + [2, 2, 1, 1], + [1, 2, 1, 1], + [0, 1, 0, 0], + [0, 2, 1, 0], + [2, 1, 1, 0], + [0, 1, 1, 1], + [1, 1, 0, 1], + [1, 0, 1, 0], + [2, 1, 0, 1] +] +let golfClasses = [0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0] +let golfNaive = NaiveBayes(type: .multinomial(data: golfData, classes: golfClasses)) +golfNaive.train() +print(golfNaive.classifyProba(with: [0, 2, 0, 1])) From 42db9a9d9a823a5bd0f2acf5f629881265ba7a83 Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Mon, 17 Apr 2017 12:12:10 +0300 Subject: [PATCH 0926/1679] Removed extra screenshots --- Dijkstra Algorithm/README.md | 4 ---- .../Screenshots/screenshot1.jpg | Bin 214771 -> 224243 bytes .../Screenshots/screenshot2.jpg | Bin 225916 -> 0 bytes .../Screenshots/screenshot3.jpg | Bin 224243 -> 0 bytes 4 files changed, 4 deletions(-) delete mode 100644 Dijkstra Algorithm/Screenshots/screenshot2.jpg delete mode 100644 Dijkstra Algorithm/Screenshots/screenshot3.jpg diff --git a/Dijkstra Algorithm/README.md b/Dijkstra Algorithm/README.md index 872e9f851..10166a63f 100644 --- a/Dijkstra Algorithm/README.md +++ b/Dijkstra Algorithm/README.md @@ -17,7 +17,3 @@ Click the link: [YouTube](https://youtu.be/PPESI7et0cQ) ## Screenshots - - - - diff --git a/Dijkstra Algorithm/Screenshots/screenshot1.jpg b/Dijkstra Algorithm/Screenshots/screenshot1.jpg index 390bc658224310c7720678cffd68bf1654b5c045..e9f7a1207f315e8f5aa20c72f3264c65edafd3a8 100644 GIT binary patch literal 224243 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 literal 214771 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

@lrF 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 Ag8%>k diff --git a/Dijkstra Algorithm/Screenshots/screenshot2.jpg b/Dijkstra Algorithm/Screenshots/screenshot2.jpg deleted file mode 100644 index bc51046fb36bd2c77b11cf8f6bc28afd0a2faff8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 225916 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 diff --git a/Dijkstra Algorithm/Screenshots/screenshot3.jpg b/Dijkstra Algorithm/Screenshots/screenshot3.jpg deleted file mode 100644 index e9f7a1207f315e8f5aa20c72f3264c65edafd3a8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 224243 zcmeFa2Ut|wk~X{%5yXH9h-4&4XaPwQ1o|if0s#=RYLZvIH#DHteB*% zxF~Q#M^RN3{7%Qr$=uw|`H8&?33Jl#iHnPatcZx6v#{x7`$y)&X7;us9;OZ=qQX~2 z06D0KgQ=N~xeMnbb4x2bd9IBrG#97UV|gx^q{dYZ2SxKIR=2&J%yqmpbLE3)?$ciipa{$cS7O6A=>=0` z^$@ai=Kk#ox6GZ*oU9yNtnBSLe>~Cjk-e*nJQw)OzrKmOjpIM?AXt9g=lyl} zTpwHLa0KxA_|mhJZ&z_QeMw&cTB;LTMxPW7{WaPADq(*=PM28e)zm{Kb13$=) zksqfxK}mIz`V@FU$vNN{89Di}SblRqrT#oc&&m%ul zao;SgW4PD7$s_*A$?qif1;&d^%)FQR_yq(dB(F(H%g8F;Qc_mAt*WM@tEUe$xNm6o z*xbVMiIugpi>sTvho{$zm;M2PL9c?NqTj^C#=U(PpOTuE{wX6fEBkX%aY<=ec|~P? zLt|5OOKaQLp5DIxfx)5S5zO?=?A-jq;?gp9YkOyRZy$GX_=7GG`TiSO;OD#E(KnP4#P` z{!2OiYdQO)(EPQKz=x25&p3YkI3@V++^LhN&i&JcG!7aNuSg@nX>u}9n8;}XC_utbg+0Kal})()VBGgbdU!qF>ln8mcX^vF)mnI~!+HCdN=_AjoW;wQvKX;>73L ztGGQQ3wvrSv8PUC6|Qp6yf_tRqT!OTHcOe+k9^AEEAB*<4HGt;sb&rT%r>vfZm4(u z#$d`(CrTgN61-bxf$p0Zoct1Mrgb#u0F|A4H{QAMsB!=DdnJUw+UNJx<6VoVFQ4$I z+Pdo(ycz|6T_N$fNBe%_&Dri~RV6@JgGu7e-D7_q{K0^37qlq)JBnTjrF*<} zR~AHynmqr2*Tn_|EVE-#AK1*wujBTdw`scA`xof-cN`@Js_He^?aZPvjt&luJ@-tk zNx){yXzgiSV5&zwRFH1Zrl08v>-MhB7z_zdjCGGQ^yzaiy(b}lvo7Y%lpkab8CWY8 z(k#na5q;9z_GS4E!umJLRHR&Z|2~tj^BM_o*O|t5%}3By%igyBoFxHM zY;*M5@SDE3>9v&rB&nN_n@cdd8=}^;zAIBZm#ZbPPj#~C2`m|*`|iW$+1y13wPy5- zufa$~gGbg|I&Y3HcWLp~w!Z} zi-gLVJ8jz-hUU?ozeUw_Nqg}et1lnl1p4+A>Wt{SZ)~o-)Ha$HDEHaoni_4KWpI+* zT!N^!DKDjd6>L_6Cweqq-wk~$+Q&s7s`~`h;sx2!!ad{IWg!7?NWhUZRs@%TK8zs& zbN0kp-$reC_>MLSI7d!QMQ$aN06Pw>400Dj0=`ZXS_wfZXtu>vA}1w58N2~X9D`0f zk$`0w35Y=-MIO;A`Cji^4a95032G!@tBeFVK_Bsh)bo>o zATko5jXuyK0cAA*B<)MsR;+Z?W&ZY7&Z&szz^T9T!DcBImH!(XPAU1i;AL@h(-Bk? z4K}&PZP`{l&#+&cX2X2U%(~cL&Md({difAOWtrJ$8Qi{HS{Y^@HkisC`r?2Y|31`% zgE6W<)Mn&vY>yFCgl}%2qr3K^M@cMJlil^|tNJvdj+1t%A`QE0;!cQ*wi3eh@by0m zIh%|Gpbe+PKg3~kRI|oBZ0g)k^o$ILI*s!kwy`?g_^3V zLgqcL4uv+?p0Jf}7OA{G^?b-r8M6+VfNYL!@HU#`-kFMO7pD>~SHC0J)Fe|rCwn^1OZc+26RHrV2TJ*!QpDLtFffw;h0nQz>(4SAQ;ViJVhUt`Q3nw;Y z<$pty88H}M^rEevU5%W#lxb!Wsqbr^;cM5VUaJi`9Cr0$4^;AndHlyZtvr}8N;$=5 zrK4FZp#0#CXWV25M=SB>H{#nN1N}D+o`{UI;d=Be2mG3op8uw79>9O6Efzq1^@may ze`smzbCT2Kc@-?SMJ3IRMcLzAvF%Olv^4>P1{Kk|J*s3gF(GZths`ZX@+Vt*s&gm5 zz{8#oOHygVr!dGl`i--*gj3brgrOQ7E)w>n5d3h z(ASwBt81H_ENkP5o1%x6l7I#|ye{%(4z~1+kmcsb&ZX2Cc3nMZCW|08jN(~MY1Ske z)Ol1v>Z^=<#7@=W;nCDp-v{tB_hM?&3@a$CQ>};i@IC@Yg@6 z&W(TVw+HUR1R8DCeewwzGa^<@OCFdi_tAl<4o0{kxT6 z16j2HMZ;|GIrahyGtQ{{LM`rg@8n(gaurt>m0SGBoTK1Sf79S5om7qf>@|ie*{kJ- zG0TFwF|&Ire%flvC)wY`RCF>NvK&b*OEHpwGh6{q1_t9A$LI)MvA;l%&B7L9d_cS= zifofjCf3s-7t2?+I9LRlX3K1>T6Ur7wZVGn>;iKk-93r;-4J~Djs^(1TQd%Ie_-z4 zSB4H;=iURUy2JHUvc}j_#(P;Lz>3R)BQrm$d?P4%OAD_-0v=XP63*>T#@tY6P!k(& z^L>KF1?PT@o93gm_;?w;dBImV${^M(%9E!@TM7A*510S@U!d3D_s5Ip;@TSx-Tmd{ zDMw1=4L#QKrjMWLxqUOUZOX|jeoa9L!GhhW6QNbaAcL-{TKYI18*7>STBM9EVrX^Y zdCVZgrovwGvQVO5Nwv*c{@#k22gX{~E<0q-P^yQR5!d~KX=#4d3@yq-2$^$>ZY!#8t@1n29QoLt=D!`;=1+ig)9oHlA5Q;gsO_|$XZVaQYL3+_h(z!8vT+IJXx`c3cgYdv8OkA zvj6(YV7Qszp}OaV0T|QQv?e#v11(@rAx11-zl!zY_-ZJqv@>7-thD>PU4)z)<3kOh zfi5dy`b692>)r+?p2<(f+|nKvemS0SmO?<4*G;;q?6J8vOxWdUl;uF8<0fNqrJo{w z;hj%XVSSjG{%3+Wru@Vpi}3KtqLQwRgU95X!b;xbh_#>k)?z%7VP@Ge+%-fSZkxPP_97--;X-@5l>2Hb4kGde zROAPAJ0E@~{*U97%o(x7zs!TKV08|SoRx#$XN zi2UR)KeQSpsrO%IRD!Lkk^o+E(Eckhh94?;9en?dZM(60^Uo+l(^>38vQDC4$?+8tBKqtj4gcv3#G zD@g#fq^u@iN+o|@XtYU>Xk<3laK?ljc)C7$6L~?4?_n3)%oXVoNLzcwW^_(OK*3(L zjtQ(s9WRdvN3=vUQcIs)f?85iF4#UI0ZqN%(l>R8cOcU(1YhK8;ovt8GNc6wU_`i; z_lZ2+5GtlQvzUXv+rM$!K&bBc)am@aFMOGR&paz^kOa`+Me;rP_JnY~80h&?$)t>Q zYmMVrsm;nQgc$hXlxeWKmYmT+BjeCa#~_SZh}swy3d6Gb%8LXDRa*4d$u{5<5`jx6C*WR zlo5LZo6yiTkt@WL2(uo9hJb)Am2 z$UgLkilOA3)dw6 zim^yUwUy(Ms_!=wDeReslFqCtBwcAbAXm9mw%YotOIqoQ)_1*JV(yCR0_9O@YS)T9 z_mTzrJhK1rZfcOf(oy4F+tL~H6&DgfK2Jk~CnNR|k|j4HDnC_Atk?=-pW5d7cFaqT z<=%DVi?0I2&bmn{F2QACiy~_*4hrnP?UPgr=We<^ur5@n@uED9_-@EKGo~g=ob&a8 zRYgr_!(J|TjLWFU;RS|$HImM{`)AyANT;w!Ww*ylx*w$Zh#V;pznKW(_Ah_Tszcgi zCQm zJ8gv{Bmejtmno%}i2d#+5|zpIlbf2z6Qdrk_;S2Pj&xtBqTQ;xXhTwl!kveQ;j*wV za2mvoT%1vhEKLvs3Q^1)ny9;SCDA=6lm@ZGUE?VsI3uc=XYJ~#`*=F_aqnF3g#81! zMQ(&)4J$jty;S`;@i)2&`Mt&?M_E=W>xsjwP!^o=ixeriUMNPS$DkcAMuT}SNb1=UhnR!#y5@QbxR44Z5TIm6{SoV)7c z!F=)6b=pr+4^}CEF|wZB|B`?DvRPPT?iFrWOy_wgH!U06^vXj|_5cy#I@2U!r}S?h zr89F%YW4>R@`x_V&4tyOOuQPdHya^@Q^_4&IW$Q;>dlimX)Sa!%j&(UFZs3aj6BJ` zlbnQ5;>l&hU=Kwl@KsVLJU%JTwLBGyZj18uZl4An_OK8K3Lgv!D(ULr<*G> zm*A&MtmL5P$1jzrZ@UWR72l=n(GQ91lD@+_l?3p3+Xk)zDZ0>;?6n*)48G z)Ic@8Bj+KfDPm=Y*uB^CtJ|5RbzNe4Gw6#$WfG6RcDtd?%_4;AZo0(4b1tV%d`=cD zdorFgT2--y3RgIf%fX-<-zi+gHC^b{4)&N9Q;B=kbMKlu({=Ytl-wVe&r)&KmSH(o zS)hJ+b8qt*IQ#G-`>9@xe=;0hcA;Hj+YYo<%ARK^m}MF#sD4o>r_3OrQ(hshq10;6 z?BXEU7{2)eOzy>#k!sIQEF6%joAmu5oDc2s;94jM<;(@5jtQ2IGgr9 z=qlugaJa0*CuX#$BBV|g_PTalTfbg@*nI2uW95h50mkI(DmQKVNq}hxi!J$HEUx6! zlDGb(X7BFp55x5@1Bj9uwL|0#?FrL1EoVaNVaZZg9`%0K>{wm<6vp;WnE7R)^c{05 zCucQn>$RM8@0^uv%Ww~~y<0dRhP=GECK3=b0{4^C@y%{f@#yhfLv(7}z3sXf)>_B! zpzNUOfjUF@fVMZ?sfeYBb6NX{=jkJLS_STdOu zTG27yI$6OD(@&1ns=G5stlRDnm)O|!=2!+&d)(1vF3M1k)$OqwugXc=@R6Oo712?7 z1lp(I@EPR_CA_>$0=gXszcB2RfK`wjo@L|_6=*1>%%H-sImBBLct?WPh(a)WOAmFp z5B+|4IhY?c%S{jlLGrVo>P#&cvJHxrBKU0}cN7QBjNKcx4)}=R^9vqq5QDsSJ|p)l zq0fx>7Lkq0+8EjgNskn6Rm z5^jL(y`%MWow-C_u)_)afbbo#B&4IweNN33N9K40)-#7S#eU)jZ2d6JV`QE562?cO zyD0Nb=<4naBO&-H{v<}7Af+@|?Ja06wYBU{W2eyCD8?nG!hLPAUm6m6-FXFlBtdLf zxQ0VwP;B^XxaawchGl_x%ZHB)Tvpon5`}dcPM^PR2H0A(QOcZZaXiqJl5VKJg&kW- zqEmyQ1bg5G35up0W%QNBgHMf~rX&PTgMt?uvsK}5hzr(! zlPzgIR>_MWcp&R5Z|7qISEmWck#3H1PwmJ-w!06aFg-1;COkMDGF%2@gNVQ3tgnJp zlp;g=T<*=|Nvgl_PzYmgM*FExnej2~+IFpKY|hlppP`%XYF=Y$VCPGcFw4k=Tz#JW zn#V0kJi;lP=8=j4dg}e*gRsG7TYFdn_k$;gY#mMcQ>RWc^@zdb&kjQU5#rMXXI-pR za0&9mgWDmVFwd$X{8(j6-PGhq2v!RR1i;JdD zFsZ>=D)0K<#wd))ZAZ9=73skFyYD3h0*%uWdkl}9@_Qp8i~IZK0*F4G%D=H zYq1-wS<=!6(`a=G$h&ILU3MIUJ%;ng_hNiN$8oH7vJj$`(ns<^)7m;(pfyaB^$23m3eZ0V4r=0J@yxm_t_0h zApQ;f407n^BneQaCTO7AMFKdsv=Ne^nmmOhT!idiL&sHnk^tWZ67Zb(lmz@z8;IT# z0Ih{VP)DSJ_90~R#Ubv8+wb=kGKCt6CaRqP{nZc4(L0FU{X7K2(LH3_FCaW!Wn?5q zB%uv9&4?@c53t|7>*&PzV zKmuAT%RUm_Hk0w8PY#o0Hr@BUD+wR)?lWOr?FO=U4q0Ka)(d^(k_}gmj{kC!dqmZ) zngHoVNFA{wq;Ka*Xo2d7$tC$Dt{Dq+i=0buFjT!v-QsvD>FVc)p;^r|&L(k3$Bf%7 zv6j<$V^Ci8j)vF$wr&m{Z!Ywlv0`~^>3Nh9?s3qt_dQ-iYYO(o=g~oESyme<2b=pHdguCAY#~G8#cTt$s4Oeztt#HidE=3cQQMNCy{kI~IK%R< zju{?X0+6zzIYg!8q|eUS0Szb@CrZ#92-tg!ef>%%{?6o+C~1*5R1c%54y4Y++P*5b z%#sh#r0_9DKAL=4I+B6EWEj|z$INljo|fg()6?ouEuOD-lpRSjWa!}zH|VC8t%w?& z67c{l*_<7JX8cnkL*=qEH{^bUpxVZ@@45v#%uyc$9Q$Bz%2rp7#3h{^!_R;J!Hu@k{`IvBQCs@b4)>LK12Tg4wBIL=C-mJ@ z9r?PYftGTf*9t*WAn%|$qt=I>Wvkd6{AMmuVpTnTUyO|8KzOwb1GPYMV}kTkD&F*L;H8J z$mcrK8I7Q!JcO6o468dfvWz>)TQM7&W^w!3aX&_(iYfut!D` zx5>lLOOk(QmyMsVUyx4FxFRX79;-87o!4`AgfD&K{o2rS)8q1|LdF{RTjC`SY*}{W zYx8W(^GElkkxazqYds!(cX7`*AuR(O=Zn`k8EeW)BigF`fzDetJXPUj($`Ot&z<(j zUm>2{n4+OD!7F#;k?u3zHd^QJYk41MXMZB@=tx`2-FY8T_l&%-CDs?SkfgwgbH^G@ z)71MYZ|LE?bK6qKCV#Qbczk>IKG&m@`l@<;Ta?nRsE?phUShT%d0)S+ASF9l_=Q@` z)?AM4nZk?U#g2mV@+r}CIr>XV#jE-KiM{$|9oEj~7jtyxwV zHR_Wk$ohzY2_`JxD>*aF#;aHpu0csQyVq$gcGb+}C85em5{j_!=k+^U;f{*}z(%6&Ik-NI;Q$h=T06 zwN$B8=^;%(v33>c#tJgvG(Ha)hjl#D6azRs1DW>ANx-9Ia$IN6R@YQqvpiq3FIVBK zG+C>cMiQek3OcXST6eCiE##2(PRK!~(B#(80(*ZKI4y3SBXGn%sN|$&P0h717h!YN zv}26A9-X&eX{vIc3UxM7-0a1`R_8XmTH-k(Bv2#QI@TqOGS`pWq-k)(XF7GqGE!2{ z2ztn|2b9|^#4Ky(e!QnWXR9puKFV$Vz+|IH|N7!%U4i;gOEs~1)vuZgKk*h+6roOn||d3OLxpweTm`Gjm$>m^pUkbsZW<%ruYw0IdW z@f}$Z@C|BBodf;&>l6E$Hs)A5*d&Kc-|ke)ECvS|0GtAn`HpB5;$l z5#OQAxURZ=c!Ac7YBrnvAq~{Xavsl!*MnPwks0qr$2L!F(?5I>RXz)=pJ2nDEyQTJ zH8jRkv=1-KK5dhuyVSrFncxRyZc3?*CXa1?$#-g8O{0ngcz--thl<5`*1Hvj>gu7Z z`Ut5w|07j|2(IRc6Zig}Z0x%+0;o6z z0Dl*Ee`fN9Y{Y6C77fm?zx3)+k0^OEQpLZO_leK({>9hyCuT2vx%Bpe31piXjNQcZ z-Hc(g~5xv6LGm+#&V@BIlvOM5#)pT7YCO=Bc`|!XOs=UK7thML8$+qQDG`-Pm zd&+2Y?vwci<~w!k_IGJwRH7lRAChVf3tN;;QZdOvUdb<9wV0RVNWj^hjPH2aUgU?7 zwky%MBl!VFPqtBK+VZf*(^D?_g2B5E($vNC%lf(V6N%^Hyy^HZ2;19xSrnRK4982B zM-OUjXML+|;A{#k>PLJT;X=FZ+}O(t4K^6dBBRW(t$GWCkhkuhFQ`&9hMEvXNAw=O zb%)S!*9|hfa^Hs@ywJ=8!Rh*Co2;k_s-ZKB9Xv0&qR5o^s$fk!FbZMjbZUkt0#Kg` zLX}bP$4R4C*_}1a>yR=1GT;5(WgnfR$M~DwL{7Xz-{Z}uF{#QEfws1vthPp5Ki}N^ zOH9<;KnQ&9HOn{EzQdFMBD%38iQGL%cHrVJlWm}jiQa@;e{FZ`aC#BA?HZS z_q&dU8K!+$qd77AR(i*q#(=t!-1hBfU)>_36cHI=@=|pipOe2NI<>U8O`bzztgHu$ zS}w<>8XEZ|aVua7^V84p4+Tb{1*DsMTNU7&lwf}@`o0-ZxLGx`5U3CFxu(GeT0DU9kjLmEo!E%3>?Edud~OZ_?KIZHi#V z152r(EjaaIkXG^Nu7}AqW`HL`y?1;#=l^y zS&yyRk&=I-``wNEyu9v>->RN*bIZ)a{E6Q=m?SyEC+SK=I3|rw@mrjt$g6d~n3vMo zWHuhIF7-4z9MY6C(DqqHEs5QgEuE^w-pE&9E_6js&-&3N4HNMw_nn&Bqhy3{^CVp@ zt5p&+h@gz7HS^^pEoWAg{MfV$3hOaEp*a;8C!Vjdmz1ga;tSA48FeBrykgMd3fu_& z9y!=2gKtrzR)*YZWnRzqDHvKKU*1NBRRBmvFFfe&D$9vd9Y|EuGuB=E7G*eWq`Yf* z@m?2KW_^sInkM6%ZH@3owq}>kj?~@&Hp5@e{YcqE#RzO4^V|`n<ZRKTztBi=br5DgHiuWQzLe={ZM&wU_)5WYZ6!i%h?ssbNhftViHd4^kVZkp~y1k#$f4 zZ*mL>ACMmwaHZh(*YFgEML4ybe5yyzv{YcR2(7i-h(e63=eeq?s&_(|0N_h&2amrl z;=>GIbd%>AL!yDqji&2TeLbOl7HR!GOJhgkdo#GK6ub)VOQq#Y5zgw(LI2$8f$2D<{ zo$gclC#K|cxcAJkTJ>Gb#4dITLZY0{bUXaS#PVQ>x1}edo%QrkXhh;L-JD09;C)rf zxh`q^TuPq9*abFB-(*u~vhD`*9nC8XEQFR{Brq~R%y5!>1)Q6h5Gf)=LZ1ZXUnyya zGA+g~3T@=Ol&YGRmsDuaQ?))i)lx_9K5k`>cNg<2XniY2~^}Ry>)AQ74 z{nZ3@*GFJBv4nW{GVf$xVmI`H0;7i(=0wbqDB^6NW<~mlrf^A^(G%M7&NOM-0!*z# zTFexM-s!P;9Ca`RE!2()$Y{GTYFj$7Rx>K?e5KhVJE=#NCrVW)%7_OPN%tg=zW`gZ zar{-VAB12~M^r{6V6hIKRdQgq*+5hi2|%x2vInQTD10+uTl*2vjUnVFv?F$j< z8G-6{uBME#WGr+!F^G~<{pX2*U!_ug*lv>LbAx!gk9_95X84hI(T!6<0bGLX!V8NTt41@(6CSW>k;bD9x|KuUNZU*+ z_sCIoPgjOY%{7PI9G2T(StDDiRk_fziz%t6;*?{oW18sw{fQLHG;-m92Mif5IRd6a0~=`fw0Mw zzH-F2L+BS0K#SYZ+Jpw-g?#tVm3~^HzZc;C@J3{}!PS^J>d`l$G0ox!AxfTIfvKyP zlo^;Eqocg+M!jwOQ@f3oMC@gIKgGY%H5_~#HR-+hZm(<=i-k8pi%?AwbRLkV!AOt5 zI@yu-bZbVpUo_~0PM&mR?{VkjVWr!O`i1XU)e358V=6p7yFDL=oaqX*#dC8Xge-KN ztO*cr4SW6VSpnAn3NO2qHm2%r=zoQNR-&#v7oeV?v0H(?#!aXs;-uh?=_DFci$=GJM|FC!;>iuU@k z5ib#Xn1~m#L`INbuUybHL3TZz^N@hDxUXd_ytGC1PqQvQWv59;&??!VP7!pmm>db;#!{N+vtgMHRYKd*1WnRZ zJ7PFq>L6tMgm_+P_Ri~=Q}n^ahc1sg(!-8jdlY_b=FAv}+VTbnnfxY8wHoZtSP`YL zVHwX9cyRZ|ZO?S3e!i|gR1UBG_PorNlH~>DLVb+nfsc~2VgQDkeyR8Uy%%<3D>?3( zM|qm>uvZpL($!vTimR&0OQ>}iS$;g!%0S2v-XSd_&f1t=dX>Nxqkce zNoU*B8Lzh(tge9*p>%8Y3)GFFh?*l2gxYr^Bf@iYGQ3)I(z2H`Ubn*KPEcw^Sc>IP z^_s@;7p5;$ur3MMgDda%T}@3=-^UkuTiHB`4LPi6gUJx)1ipXzkX4mdGO%A|4OtJ0z--r38u?^p{|FRtl#>D?0}W2iWKf@`T) z5ZHv*8NpB6#L8BWzycekURgRbG#IJRj)X;14TsvsmxO*F%d27t>U@)GD6y289b20>oZ%xfb`-dG72EaVQZ*J?xAE#QuQn0`XI<)|8yo-j zTJg*`&Nt3HXz%^-NMG?715~%Ny=A}l&NG$;FfZWGTOB&aT)Ga zmw)l{0#~RdKjiZ0Xo}T!iSXX(%c)ZxM$Peg`wbnuJ6dPu((W7n&FUH|GIL}J`q7?@ zN(>u1fmd{4nuqA>O~JnT=;)PErG1Wn^oF?poi{`edFF54kh1^H-jM!(6>rE^+?v!> zPKRc5d-Da_cbZ9`Se~Ww+-h+u`+nYe7xfCVcflYv=~{p}4T~R>!Q*pYevkz?1F^$| zW>DBpTWpXUqw&^xaHIk|iu9Xa|A0kdF`GB)+r{9wR9T*Xum)<*sVxp1D zV47wd2XPV(PDVA}2M3nJli&$HaAGgH3yKwHwE|}yp$GRsSHl&B>nXLMZ$AKxOUTLr z9d*bfACAp7^sXdwHi87$rxLlkXu!#3Eut!vcndmhEZs|dhTKXQAsQgu|I^=A!7C+k zkbn=#_$VYk2-#Tfm_Y#3?B>+q_yXK|@DUx6Ns9Ohg$GTCwH;&w7|YPt4}vBrp*8{+ zA_oQIq@f2qUpIeeE$zIgB zKu}Qw7_LDFlCMPqB581OXC*++ap1GmNkA+ITQ~gC-!bSX5@;<0L68ZyE)O_4%*FA4 zuzkIJ+ge$f(iP^zg6jmcU4D}-Xh}&$O+|QT&$W1~w_IGI zMWRyxWS1Oc|B|JS{bcWsz^0wwJ3FeS`LFI*_ebj&Y9Sn7l225#P03KKy|MSsB#S6E zHhqU2y9>bE6?Ru7arUn!xO+R^IJ~{p&tFx#OMdXS(~I;b(}Eff)&`5(*B z$|CY-+0_CATmS4fe~@nTbI88rEBDPM)9qyI; zFswJ{OXJiBZF|}=B;aB?E>T)5RqJA3=0`a$Kc5F`ZYI^AqmQEHlJ{IUB_}GT7xCJT zOb?(c?E&1c__(Q331jODZ`n)scP*A=72bU`P)c9Auw-LHRiAR2jL0`poO2KoF8$fF zQ)W88_+ByWan(WTI&tP`r5=7(z@b^2^|*P*wXqE0EjL3?o+vo-E*LN~)75+Pr<_wT z2etMd;S-+0GizwrqrP5TptrBVf&OvO+jafJW17AtyS8F~KSWPrd^xjXX0m3ia<*mpstx#_cNk>`$YIbLtM~+9wvv#1=ods`3Z( z2J&^EyazqeQsVggAr!Toz!56Lpl0nVSgz11W{aE>K!GE!oHI0)kMVn+po;@GhoLxC znunuR-W8TG01X`#hdwy6(xZ2J}QJqsv&-nHr}M8>0nB@O9ITGXE|F>_fK_lF#De^4s|BMt%1;qxSvF$W+g3I*Md3 z)1Nm$ZYJo$QuKdh$T2PbmXY-jezD(W=KVkU&ZHMQ%L_v42WB8p_SgP>B2`XcW2hrX zLtH9UF*7BY;6fz(5!VYP4g8B(N`I*7{Xc5h!T-d2{qvynx7Y~w0UM|og} zO@5tgYvI~=;vO`nc4}paD7g?n_*^nf#HF--Z-^4Btl%Kui<*ny3nM4~VrWnBRs_vB z>H$(8naQeIG##E7WYmJ`8;iuX4^h2{C}(|S55AJ}kwos2NU z4Mwe)93POV=^3Rd{RJ8`VQ z*EYU`p~`zSU0rWWK#TqCGJJPiiWp$SRkHijVXaz5W7ovhvK zicetdb20P~K)tnDTKhfccAZecDh=3{&8$Oo>i`J!Mxj!_B}T|?Ps8!gK7b+4APW7? zUM*YG@^>d{y~T(Ehb>gd3K4y9PQ`)aF8KLVUi<&1V}_qoc9l_9$y?`(NkD!f=p4A2 z&v9O~5qZ`mlyDYg<8CkR_>bW7AB+C|OROvLKQRuG?d&}#0h~fo#F~$w#8KGjYyNx; z8|cMp;}k@2MZ3tiVB(FXOvj1>eRoNL$+Uh4tc3^~EMKW(au=x_-99L;%y4U(Q zow2_RiK?Zh8?^AQu%~_GFrYdipS(15aK-QJ8HSyJB8&!$5ycPf1Kk>c#-Q0-uqYbr zSw9IDbkV8Ib!S5FHtMK-bQ{G&`yxi(q-F7)7Oi$utx{SQvQFlZKc&12@uR_av;va1 z*pi7gpup)!hT4#=#~yK6MWXOMa3L+@X} zeDn+8Tbq0b#rar`an5w)Cf*S*=!@Et1fkVlS4aI{EI=AL9O&5O3k~W1ZD^`_je?g0!>gEMTXDh-dz(ApW8-{!|cuSqJ1l zGGG5ymZSPV0UNXj5U|uI?|$yu&2|X0+z!(d@9g=8ANuh`>?6dV-W4-KNiT{TXUWVC zqIATH@A)a5I#oBe%Xa5ZvF#!nM(|23Et;t@(;a6hJff$>nL%aPHwL$w9C@Ogo}^TN zjWL(<6kpve7u4l$Q@aNGQ1mVD{!XcpEhe9V&R&NSyg{fQv(B(>9{_@RoQnNy&6YxU ztvLJmsA#NC!qg$mkp!GlCw@#mU;$(PQI-_J8PsmkQ2A-O2!^1>$~PZf&HH_Gce7`! z!TY)LHVB`=NTd+sIJ}U^VE}U0o>>3cb&{O~*jniF3o94R0eZbAb}!{H(AG44>hlR z&6)N|E(lxmUXI;c?_SY`MS&|I{OwA965tQcyWQ==hk+|3!P0jRp&bXw9K;;ZL$feB zjsCXX@e=^a@$w%WMXlSrtsdQqxIDJNGL&E$IwN_n*3E9MXg61m)v8&<qV}Na1a34H_4?#WMf3ZkkNglrTvkd75m0@rlAj(EN8`ocf<~{FYN9dmRQ49h;g5!=3&pmR7I%*r{~ z$Dy|6t%JAVI79gEX>js(lHkwryIU2|DhKGRBtQ>D_}d#;_`FyDfB0lMZXEuw z_-5s&erI$3W_$jx+5X;<_vea8|7B;%|Af-~^BI3xhx(uQ>;0>wB>gEO|Cg33|K~;U zUnLIge^>;$#j<0~p2_g+&;!M=Z|qkHg$jU&qF%Ie6_&QP!arDj?;=lm7}eAZuCPG1 zy}~9hWJ7W&7{NrmQpYnvK4{vP_R``u)sy^lUd8t)e9&uV?7O{kYz8e!cdfkGl{td0 zGGrf7>&*!4-P0fp%HIs;&o>+V&71n`Rxq6~Yv}W4fBRVXXmih16IE(4#{_5GU=p4e zmxq}Qtv#p3?D1$~d7x=N3Wy7OCA^4@4w_JEkwf%bCnOk0b+h(1^@JIGciNA)6<#tV z0j}Lk#o9_Ydg%2|B^s$0Rr)orZ(S6&3%~SgR?m})I2|3kGJ@(Y6jWUV{blsQ)chzu zTopE?0ZOq05jp4aX=H18g1C02`)QAqBhRyfD?Cx6WzI?TL8`v7f9_HiH?=B8Kqym>`f99jachV?+gppN4O1tNtaodBO<>=v2Z^p%x;OK|{ zo1xC{Y5Q-$ooP7&LMm8+`dE-6R!WO*!>ckVXrO8X3v?B3(g!isg zcxNzgK~v$)C5Tl+vY!ndPA7S)}gKez(Y+h>LV@zvm}XlMjF;bAW7mS?ZsvX4&zcRllt z$Idw43HUZqpGk!Mf9$EgD4yQA7m$kqO_FDVyefD$rIp=xqUdunw#D_?Jym{vw zbIviwd>>FYnP)H?5YsAfz^3{z0RiShhN_nIK~DKf6DUt^jtCKAPqX*Rf-ru&~- zPrng9WMFyDQh{l9HPF*j->(6E{K=1Jv3<>x3{hL*b1g;JKJx`>K*LcrdsiL|_WK?p zKe-l}cW3LS8pu*?ju$Ka?s_W3uL${2?$8L$C0gSR75PKgPF zZo;_yjrE>&Hqosn^6KkqQH0AlKsFvjSV&h!PBkQcHD5Yoz)MvU~x@*29m*n5mzj=FqGO z!x%|JuIJNYQA$#@2m4VA#O0eISiahW!ykqux0*W|3c6)ZgEhMzIPmv=*BP%TMdo^Kek8gcB3OL*QT`3(wFNdv z-P4Z|$wtjrPtAcIx_$2OQp4|=AouQ+qdA9t`T98O8fMRgMJ>g(D!)!(7hKj;_(8!; z7C3E%b;;zrZKY9fWiDPS8f;xLK5K23mt}Zo0sv39YRSn8m5JSlKYGN~l zqjK+l659TXUIQXcUTWdd;`t)98f!iv&9~4u^XdU=S#y1g< z8C%&aTI9ONS_)?A3F()Bw{%6h$N5vx8Ga3;Vm0@EIxYiR5RDN?ac58|1Ia@$0QBE1hIhzeN=#Gk$_vzRycM zuB?rK7Y)AVOlpg;M2*NR+h!ebMRAPJE;FanjCxAJtP5vUNrBbI>HA40hI91sdoOCh z4lAbx6m-0p54gcEGrmDC(o+EY7xb-SAgZ+A?=7*v-IcMp;Cw@GRNz3V%V)S>dPM_)#TOjt(t z@+3#Vqp0z^iS1MlF}GAsN@qez;+B>~P!6AxqBh zZJ%uXtwAME6|JmX4;&!B6!e(-#Gdv^CZB^P+|I-^!)((zJNFw=Yp&PxL?^NpUF`+?`eIh8 z$;q(9skD%c!)+ONG-<;S9iS`foDZ{xB}lO$*a+M&FVQZv?oeaSdhP1!2PSy`YG zZXG?fbc{7_ZTeex14kfpSo9mnLwc5T^LT?Vsn!_Gc>{+#}7T#7feC#DJ(ZV=@U}CTyOt*JM zs@Lr>M$8jiZs5b%ZvkEz9l(Aw1ozcOQEigp4H#D8ZTG|zJJ(~Te}YQ2 zpH~}F1jaW3!+BmydRoq17yAphX4Fp^Da5>AiHSt&Xu~snYy(R6l7#COFUEK$8#X0{ zmt4JgW02CA(;#qeJmSM-bwUhBeY0HO>YDn@U*6KP}zh@6Yz%q8|L_AN_YQV?51*`Y6rUg3O;b9&TM7^GWCXH*U8Zif3ESopo1H z^E%D9*nKG%r`xQlJHqq$W65Gy%$XcYRIzzCR7F`5&*&!{bf;FcqsOz9(HZ^h7u$A6 z$HkI0!!8tlTh6)ioZ`>S`)Ys56F&}LXDWTlT%ZXG&UdVqn?N0Mf(+d%d!r%Pbu8#+ z-V}4%$@`rH+STj1v+HuZd>1}p{c}i zIQ7QHDhs^^LiEh#otriYr#^dq3ic>6`9&;>VR&C207iMiQcHW$@c zE9b5bgAVzS@_kQ|XNo7lf&4sV(yM&Nmu&k!1SiEwPgX_tUQOuv+@<~ zxrDE)^;QqOxzbFc%EdTO&bKAeoz@}RR4#IN^C%m&m~yLeRIuBxC6gMmrtm~)Jtg{^ zs)WW6Z?UBAc6|aI17}lqoYD?Kvnp#$B*`r&cm|b1OB_z_d~caMoyYD4og$sDe$`OE5^p5@ zhU>9Ho&Hi%?y#>T*#OxxNqh+bCMi!)(To!}&g}^g(1=hkX1de6PggK2vOXCe+F-8x z?+py{s`8V@QYOAnm=rfXUervVU;knngZEZ0G&ji4-!wwMSSQsH{SoAV30Y#m!*~xq z8~VkBwFxALSzASY+^jXY_w)ie*T}qOn zmz_B&GFdudw;*IH`C9th=shiH#V+evg}@BOtC@M(O?48nF?hfH`LP<}b6@cZ^q}pQ zGj}aJ862GNcOI#b>6LfHT&T1o>&;J4?!%SCOcncHK&3>ZM0;yF?Vu&2%(q_5!NbkbzO_A?TVz=UD0e>lqUYq@RV7p};+2tQJ3cC%O~tJh&Us-Y?HQ5u}Wfv6fSmQ2{1YaAR< zbKA>O1Ffzfzw((${>!$=rTp;OP|d?|AGC>YfaJv3BRyGR3%4Ienp(!FFXlUKv$HfX z8w29^ZB&Nj0rnqM!G|gHO`Z<#o-eu=yEdq)A%AnFM*2DI8EjwNIl$}VD(yTygP~x5 z#x|r{E5mfaVxAP4pZvn!?NI;2r`8q8URErtpILK;kCGLL^Wj{bM+aS^up%?7q;=&y z_5F_)^pa2aCZumpYq{cl<}&B;*`>of*q<-~e4byb1Jb{jL+y;wJu&#xwX&r>wN3)BpGD0xTIGDRC@!^v4^els z{eF#h7Vi0v#&!;(usZ-md!J@|q8{N{8#&Zz)FZahfUC=2Y^WSyn(}3{7=w% zQSIFYEU>BO9|ac3zX~h>3LC&=PHP<4yWttGm!i8}}1J_IL0~Vmj@G0 z?(kF0%GYwKjL?*$THMGl<^X%pm@nmD?V9{P?|*(zn#%>qZ1*bbXBuBv8B;t3%t7vJ z&;s3LH=I5LKBjlhIGwV%*jpDeB!J%@_Cd4I5CpOMs@|!C>l+Z$aOn!`9Y=>X?}3b2 z;nbfX=xr1jkUuR5Q_cY+l6}860Rqi>rWlInOTep}dtM7S8eTw<(c8B!;7wOi^|hZw zA4WhptFKkP7d#IY{9q%;-$EM7M=csUJ$bUp`>d4kLgKt1t6~r{S$4`MUgiq_S{LBW z`IXM$?|ZA!ntedStqX0Nv#z}{fK4iakrd18Bw68~?mk?%U-A)P23EEgp#{u}{fKkg zUkcu+EEfY6wW@E%eZD5u0f3|kaHWL?7Qsf zX*}>xX^hiU^miX%rxJS4(U$%ql%d^(j_(DWeYDR5k_ikg7EOD-9>}$Urbz?+*bmzb zO~Bh=5ITVkrZW@PV1Qbo^UqhkLpSQTqUQvF|Ld3h-FHG21qOy@1 zptpTvl@;qOTJI}-kmguf%r_wK#1||(Ixgj>7MFyn9u+ykg=9^8e()Yhhf58Vf&bWE)P}ShRIJTope9$Y zHrZ^xU9>+)ZhAuK*a6IREMBke117`FKfC`JQ~uLP!T(+#_51PPZ07!VukRlV6o36b z3;bJdML7#qU6fG)EuiZ&J7vbFmZOhi#=(76IUw9ItnE{%=gHZgFznafkDzgvyZ;)* z>i?Krb}#DAM0jS5|AqZu8^=Kkf(eJ-#Ya1 z_X5s2md%Yo$Ui7^70i3Rlkn4i*UYI!lTOEwHZ}pOVKH8uF^E*9Z-zU` z=;kgxcV`rYw1bY{BQPTk58sr3-{DjOED`@)MXP1BTxX-KBHuAGi$w<^Cy;lwYbvTJgbAV0LCjFVSA$&B=si-l>kGEywaY7q7KHzuoYpVk^>T@1w(Ftui8f(rG_ZA8z;Z z(9VzOhl~@gOpDK@;g?}HBDDhh;8B4#z0tKpxy#uz<5KUGrw%W>AnkBo7fT#v2B}fn zxLX@jpP{E{!jydn6n!&EI!xk-YfO}$?74<{Viwl|7nSbl=4S1}H zD~rGz#45W#{B%obr?TXv@&3gt*=rf{`+pb!25?MF(Gh70d*9AZ9efp)^12HJR%hI! zp(B)~V_Dg`UpzJFTg>yNktVCRA(4P1(+aWG|KGb>|BF07R3s2~HHd#oHqj-mfA|sXB)| z{xnzv{{-ad+2_MLL~hrZz1ZpT$Vkg_R6CB+puLdUH_~#Z=}dC~>xX?*{khcV|Dc8j zjC%j2p6|f7qNxEA(YS{3aEY67XZ&}{@73HsU5}$3_1FHmA-kz?Zof7N_5;=kJ_!v~ zw#-?~2vv8HW-0eLA=wr{))AemAW6GR)qZ0)o?lyJz@;}6GbNmv9n%@ZH;L6Y|{SVomhqO8KLd2mQ25bkiW_1?>j&tBtJGgqaa@L))XRw?ho3MK8}GXKDZ&X1g)Y zJ2M(Gd|dGn8rQl`YOH7{!f(VGHmI}7-%kshUK+u#Y>hnK-he16HcZ)uXBZ`MDLTXM z#;cEco6oIUmnT*tCegGg@V=j*s-K{~S{Hn|uO~$x*5$`XMVJQM>zJ5#KVb1;S**^F^cBQx5qML!uJGXH<`%CAP87T55^% z%(SS>deHWL*i`WgZ+4xL{u@=p)LNHoNu66=AyM}E>^+2_TAARMN*b$enFqUJ_ z?qPk_4@hmvj*=P(MXRqyNsWq_AS1eAg_$Sg$qE;p0CBtxTynNM8XD#u}3yQ!)w(9Q@I)bc1+d(;_#0tnc^{J zKg!uxdO#jwDjI)d`%XL|!|z_9kJMSfEnlx9>3wMO?bHz0T%`lojWM8O8nQcI_M8VrdOKo%L>gB6 z-#OxXAOt2bbk5MkQ8ta!Dxr$?Qm*|Ylu+fTh(Wa%-mND>*mEs8FO`4H5G=RWyp$TL zo=xNGNxVl*Owl~1JYOBK@s5*Gx{H9v!wF&c`bW*0DKll@r;g>*KOa`x` zj68=DH`LcX!>X}^ocV-{1fTK+;7&nJ?ED|L`1qe=qGaHP&OvW$uVsrU5PG3|xE&ql z_|Cs5*7p4bw0pmAk^i&`+Q)L>xYr?qNbNbQBTaaU4|Y?;NXhG6)2Hm$wN}uONO(@~ z8ev(OylZZ%9o)QYX1yY_xmFP4{Z2XtP2DF5ww(KwO2s_LwOvOZAb?bg764M|I(2-V zSuMB3A=kHWEN2JHPU;>#=_3iKCyqu>9x-lmn`Cp)=X(A2=?S%~a+XE-E}njRGWp20SZ+3c6E|E(TbZ6-Y1h2_=IUcKpkXSaIE8vHvViY( zO(JpwEuYsx7O;=|iDigF0zHieJ63@%JXaQQ>&2F;{g0zEqMzHHZwPdQ+?ymnzem?Y zr!b-n2)g(iF_RZsAUd<#y%;0)PEnFw0(NZ(k)IT`v9^B2*zst?)y6z4&M7UmE85l` z&z48F$8L@K$x_|abdA*0^`L%0jQ= zdftm@F1*L_)^ z5HXq*<}(x#GS+zJY^JHu+vRmj1tqth&2v-oZ~SAGfU@t~6g+P1v!V6s}th zu1fE6sO9UO=#=Gu&>TKa_rE>jgx#Ft)frF~%?NNuMiPyE1Zs z^qT8Ea9muM(tGqscgj`^3Rc%t;wIEzi}^B5E!GGdSA=i06Ry=yKKhDe3w(nvextA< zOF-|*BWtysGhd6BHit^DhOB-w6BBQ3TWfqV|HgZ!nsrR0SK=pVs;|o!J#rJB;Y|u) z@KCW9;f_wFStUx$(5u>44g`=+?B54z45>bd?DKChNS}^=dhJ>1HVolZ(W27yy{<1- zgr{HsZIqs#CakPORc0r)rhDm$@8do(NulqxXQ(%Rf=a|o6S~1VhPJ<>lw(3sxsc^d9lWXpw?F5xjkmqIMAMIsy5_Z;-`Y8w8fsVuJrLETG&HF96u3mj}dXd z{8qP^Xa1#?Rk|IF?4O_!Xj^*L%ukR3uv!uO<2t|XpW-X#pMcEmchvebYDLED-o3)g ztmkbcPI@hKL^(A4=0Smv&ZcXpWs@|&`&SQIq_^2W?WhtBsG>$r`1tO)esNZ(tpg5v zOM8gq3TpmgB{7-VH_3^^l5;79B(E5^rL%HbwI&R88OnxbHO4%(8o@X@26lk2v3Joj zRCsQ;`~>m4m2ado+NdeOWoqddC}n0Oh@p2caXdgfHN)#OF8h{9@9v@xnC|emu0&>g zKFm>!auz+g*f`2xOdOPD*~fR?xn<2PVI9!yXPbYFHtH=e_dWE6@kD(s{}ViL@PNGB zNut7r7#I4S^lsFJ2&9O9+{a|?s93 zw#n$q28`A)Fey|WwE>^;Vy6kgk9$Z`$=%8^Dm*vGb~)bb(lHbz{huIA?pRU4PmtD4 z^xOx;KvvowTRXKho$(Crj8Y{;I5LO~rN}yLW1$K;n;Ol>a*lz{6 z2$Gmb{4q3lrd?7R={<6&nfV^LfAGdwmezC4HA}W`@G^fxIb5^lM9jFC=8%(kq-fogDrWDlF7M{yAg|dr<}!4(5B9Ss@k5XGfU?bq@9mRL zc0;!bU-S6SbZvEOKtfX?9OTiIyb)^Z;^(TbhfkH-bzK;ru(8`Ye`89>&w8l=_Yeis z#x!VO?xv|bLJ}2|GVk<{gSR>xPEh@B7NYI&hb`>OP0&q}>@&Qd4h!6kz5gMb{uMXp zcWYDEqH|&oe~e~G4v!#+9jQf%v@DSicD3p) zd@^C61QpEX{Ot_VL7@zOkVjiXJ>91KZjlfEdjt4r{%p9Dj3fNgaGK*$_RhDMAL_IV zKS9SgMxV$+Rn%2EuFwT}a@MInP02^%@$QEcR=O3en3U1wV06yfQDf3*B+kBiOWls-pWmJXWLLf)K4hSjN7tvZbMnQCaM} zR)FkI^@O%|2zOteK(9=G_}EdPg)%0_zK*v%a3b;^awf~!JpbQVve=7B+hDF;81tn^AEzW|0R z$rjm7I|R!+(ks&^2Ds zVMy@N5*}^lKb z{5wG2EG1eN;TV`r?tyz%UvbYUiR|vwx#8jH{%JW=1J=tUMHlhj;EaZ;-+ZLXssFz_ ze)}Ks`hQD&dVlRnd|;RUvkS-cOAq@mmjU0rIi&HKE81g{?O6MT83s%1l9l<`8-=_D z!!WLyrF)sNOQh5a1pZa+sq$8h(ea4R=CO{CqREw1yxp-Oafrs@`5Afb?}zZ$%6tNX zHo4p3tux7rVV;qIk3NtM>usmP?}kfj^yAW4k_eQ^n~b-p;K>Laqjr1{$a0Q=(zesf zVTLjGk`Q=bZ^Ps?9R>9lr(vuGFNw8)JY_K+lj4Vn7iM){uq;=fq6KMrrP5^joL)J? zVZ%OCzJy$^{7`sc)!7Gf(m-l!%V7jS^PvS(II_;&K6om-lLh>!_(BIS{uP6}oERq) zcK}V4Co(!pU{Du|#gNhy_djzq6IyXe-1o!;;vVNmb%E-@bUII@Ia^J5%)6$HYG?M_ z*9mQy+!<+VPBR2phWyS)`PQh0x8%AqhQYzkw_s*J2#WRJwZ=$Fxe&c&M85NM&0ntx~t zaFbcbYSqEkn4tOI=3E&N{<@~IsMT*vSwA*l0}2TEL8L`DzXg^z5@^dy3o~BcDexct z*7e=7)L&jb^%DGtksbbi?5P;&M3dxg_xiV%7qn&>ME)hj>V>48`A03Kh~A+;j2lvDydFMs@rL znzsj$tQ|1=6wT4sdrXYJ&VJGWuq$qv zZ`{j6{LEO3qGk-C(^<%BBD~g>SKxi~@ZSEGQs1%T6SG`r9l2J!Nqs81+h$zhI0b_? zisZIO44ziJC%M|a0*NnBYUF3>++6PF+>-@V*|CKYIC{q17;&`7kBd49<)fzECw9$CPGurGh^8brvBNq)VAzxPyshB?{|&C0T|nv{ zdSphK>e6o+_XsjL{=yjS&g)p$e#Na z!c(EGg|$HdwbFdj`FqGN)yo%x^!vj?P@FP{*oc8NC9h~m(qZAM5BfU=Y;Ghdo9`8f zZ+h$)bodRH&hFv40b_eo%&tF`iEXV%I=GHrT070)%#n-7EohzQlgrfpBR>L?eHMHp zpIjoF_BY+m+rSd94;4*5vRt33Zfri?_a(m+Gso%e$ytO^u*;a&gMUQ?Ho)tE{D^C$ z-|T(qT@X|FX(B;-M+*9_CL&=j>aqss)#MLhA@BkDSLh=rB$Lu5a}3~Y>VR8mB0Pj2 zoVb5dVO-^lPQ!)*T{NYPf(=}u{BXEZfS%2?1op3e&V^a53<{^^RYrkq%WZ z;)7~=un@hwPCr3r)4~AG9Z{FCK2{hvirqO_cx4F~!I%3l^v!z?evOvQk$SXiusJPF zyR7QCbtYO(U28siCmY=M0dNO`O&&|^2+E$lG?!`v{46uav^{Mu_Q{E{FE}c5p94Mw zJG=sH@|c1T{seJs5UD%Gdph8a4)`wwbYJ`RZg?8Yrn#`CXM>FG+Cy{_c<~e;noAP` zgwHzm>>;9?|6=G5{F(RKI(kkOVMLm+2&pufNO zi}^leU*!>Z>RI6p%*qA)8Yex-5*m_jIfvf~E^fT*B{WC)x`w7|RU@(}8S_d&kL394 zF`zJ)hj(F$eD!*O5&l<4pb#mEoMKRSatG|v_D;Dn#J!;E)>P)6bcRAXm0t$Jizsj8 zvxJQ-w*T5t$d&H{4@?kyAP1AakJ@Jdjy+6AbZ6z_8v5^isxaRvYl|>feOlo9to9JO zw1D-2*h|kh#f-2!1wljFAB%a4%OdtM>O}yPBBMF{{fLu5Qm>P|9q~@@r61QrAY*>` zwL1s&pMQPyRh>KnJ=V|rDY|m#)f97_6Pb_b)K;8tA~QKFXZ8AhkN(>-Q6#Q$tCqKD z9e&d6OC+Zs4mfC$62q{bs@@=H(mO$cy_P=zX7x1>YHHvWV~%lxuGmNJd*L%VqFSvr z2~8Nrjx;0LBc8Lbu=g-zm(PJfOduF>BCDNO_pzwx4c{xPK*LFUfq}ZD*ah%HjM_IJ z1E!`M!Rfz33>RBdHTSc%!Ql_Fr(+^JgKmi)J+7X@CCiym8=!@A_q{tI`kKK)dss=% z*o#bA6f%;tY;F;5eS^X7er6VPwBf-VZ;roig9+i}_BC z6l>q7Ef?IvdlR2SwO%*z9^h{Wd~Z^(Nq4mCq!CO_-xSRzyH^U5yPbUpMp4_YIRrZ3yt4+Aj z{Xo~!t=r`%$Vj_qjez0boM&xYIDJRN>wqf@9?l$*VWHfU;Z_umG=K%10+u-x18D3Y z8~B-3f+2dUM{!vK7m`##kIa#l4W#%zHSA&GY!*%iBEW2u*x+>3%(gAU)b}TdsBjoa zb=xqMs&ikv)FwpHo)#t?gcF~{oX1Ywa~N8Z6%LC?>=s_vgT?>`JTJ8;4<&xX=6K~O zUWzAdaPy)~wj4zL%@l%a=5gH90|D*Xs3eusQ_#V&KQd&A+;w!fEYN#WJ#ODlQPL}U zm{1U1_-VZ4j|}M}B-<&d7m@N7Xb;3~-M;{?Z@fEee`FzsyFr(>sXR%VjCdh&uu=ar zN;3%l^(-Ui`yjQuejB;A$@2XtsQVt!ic8rClkkF4r^+%=(xa6_iSe?Dl5b1pq-V z0E~sF=yFL=gLMOUxWZo!3oW5IGcE${0rYc}O%64i{%y9X(?Xh_OSyFqXpkk|a%ZMX z8$&mA54|UFlqy|2oNKSd?t3bXagTjHjsExpAtVF*fIvM@Pt)?%z#I4oam|#Cak?LN zmN=ixv{)iVt0T^vbCrktN_t`>b;31%b?z`fK{xk*vYVlrVA)i+6C1cSO*QybxlBga zx|W`nCSByusw2c0<8NNoGUvsi0Pny_=$lUo-D z(bSz;uZdgm;#xL*1P(*dmNhReF_Gzu# z3u+>3&p4t?iq%4rqLOrK!NyuJdddaU5eE=kFQVtV&p=v{@(pCI2H_HGZa-r{OO zh)C!U{Ir`kucp!${%lnwktWO#=|OhMM6jbUk_*>D%zX8GcB37F8I>)VncjBB$F4YX z%4MJszsmR?O1&`Fx@FQ))#n~6Mlaanx$_seV*%J}vFh5U$d?J#a!pbwtOmEg0xBR^5-Y#uN@T9Omni)!%ucUij6P za{tPP7UR*E*RgANJI&UxRBdJREK2%3`10zH>UT6X=J~rnX!<>jbzTDqr3KSIgSSq_ zEICB|0v1|K3wmfi^&Ng`;1uhP3BiiZc%aQt0>C8GUogoilAmp4xcdZsBnui1?yFG? zsc>F7q4ZZ^;m}LJ4ZTEZf}DP#piWc!1jjg<*P!YlXhjI2)o?+yE6qPm zd)(jRHJ?-(3+?hb;NqtL7trEAf*r-1TK9?SMNy2MEma)uT2`}CzZ8G`KDeV!b@g; z^<$s*F@#qu*yCYj?W4`W9loupz22>5FUe-7eHcFKH6Nb`+YUyjD@p~jt-&&A!1Zo1 zV6dA1+~;rkLPi+Mxt+9KeEil~-bDSBSFvCY+L_!~3)moBn3P(%$g+4L_~z*cRwr7| zZF4T{%x)nm6BOY8!bjYI3OAa%DC2IM{g?RJjPh1xt&wOnIGhh78bbw0tof zN^K4gT@0m4Jwx|M>gy)JAJp|^V z?hC!`H<53Q&}{#(!Luf3~(_qS}Mxn>0bOO!)A zIQIp+P2kx_t%mK%S5)c`Lf_RDcrQ+r2d+r}P#3C%u7A6U-cacs?KCqi8dlMcNI(l( zD$6Q3ae8sJ)W5qi_9&~`%6;?&!BCWzQ%<{J0qI6hga3j_S{RB`PKy>Ds$OdoU&U7s zOwtk+M$PXc=jVv089mgLOms^}N);0$J`cNlDd0Z*byY^m&{IP>+zq^bTmvphsH#8ziaw1xZE$ND=@*66w#VXMckvq(33apWXa(2Q4beqc6OoU2vZp zw*ky$3G^tiK@9E+VjO2Iu#AAHz|J66MVPhm%D1m-)BOA2ZEBO1lziHi3ak2%Gk@mu z3l&sdkkXO|H-Nvs%Pp|}1d06W$Y3z;qwdSF4&6>)5}3NkM#u*bA}i1w#~51B&yZq6 zUjxRh+khSZ45Ryx(>7)Q?X;Q%4iD46K$1c`%=G6@MxhRdVvx4T{S$NmT4IlXExUlR zO0Di1nv4Yw`Sl+TIaE(Vo>*W3m}kW6zdA9`xrWr`>U*dTlGTGeZF+-u7P4~sw#z&% zJ<=&(RdfT;0!E1MVZVkJp8Y`Tv1GlJHIpEUO!n#*bn*Y%@*I>tQuT+;HcbW8sGn-ZNc zNMma4tr9}*$2VHmO7&A!g_cqlLyX%lLnr7L*3EkTpu=^x zk2pF+ORJt|1qf~w~ z1GVD4G?>Q(b|AX$YGgig&128){0y7yF>9Na>kXJp#Ioces{S3aT%bFi#ZH&yiA*AL zc~a*}{ZXsE=r7x{WNO~M+Ps=nSakR8yf~ca4nLm>X255NAQ9Y(Eh%pTmT!eqm>S^4 zEp?{vmZ}XWtq`HPTfE_c2_DYS>g$4Fhc)e2*T5y7ONo}Y6chL>Zs_r9Stpk>i`V4l za`Y7L_r+dFdrru3ujT0=(l{*}yBq{g4k4d%l@YfOpPM3Itc{@OO_XA{9I3D3-mL{i zI=lKDmzOOOKBJ$Zswyjp&)i;Ln}6K%_Uw5_KKwdlit0)6X@Hy~OJMM&1CdVoQwb_L zUrpq6+FTDw2M|>d4vUio(fq0z@4LZUZ6D}zXpx<}44{xqF&(I&=7Im@=x)y6eyFRB=haGK7BpEJZXSrkB*~=dT^8pk9gP?qyG6=4vlbDh z;U^pm)L!)zNXk#pxp0AV8%h@N-e)0lzaS;kUmzt>+@f6-xKS((<0vjC{gUT#Ju?hN z%#V~QDET?HSQi)rm*Llvho`W)uSL?88Pu?$$t{T%Ug}z~^4sC#Q@e-wyuLfH`7LFW?f9m=m0>s$!E@Ye- zT9;i)ut~H{H&%c2IPpT5pWwFO_QhKJN*j)%E?_wJ1-pZ`NVcrK03U{9X!}h?Ma?07 zN}}?OI*n2}P$FF4C@Zx#_KJq_6K@UE+W>&M0zjF6P>_H*sf=&41$~mn&5Th#@0B98 zf0o~|7(1S{Z_uru-(Zi!LUvD{+U1q^l);a<-GWY+E@7p~#e8BvO+=2Br?lLFUk>~U zdfcMOPWAA>ysg3~&(6gM(?ot;X%+e z$5c&`iKU1+_(^e`i}fT6qsbX(@5=|I-4b>Y^p%y%o!=_0vL8=$}2I%591^a$&b!VdOEja&k!xCZE7Hq_8D6dEEmZHQ?*9v?@wL>4`mPlASX@4&)=KAODW6qKx6p1!aAH0?{y#qJMsy&05&HmL= zDY@({@epXK1X|ONp*1PkL8YxgGIs-e&^APzBsr*Z_0WEuSEEm&uI!h$)Z1tCOobWO zR~uJJp7|?o>)%IfX7e*Z*WIHX@v;S0T^&N=8cc2{#Kr)RkJ}H9;vSuvKicmtV*MG7A;Y zTk;_`6T|&ZQTZkw(9|a{{ivy|Npchu6AxNU9Lk0)>Eg3ngg@Z9$*aq@x%LdHPUS0< z(9eo-4bv2{dcLc>^Idm6lM0JYpO!AVl}xj#)DA7g0R`bxrvM0VFLNSp{)|O#P7?>J zxpHk-VBg4_<~)@v=CI}MbQ1??5wMcd>BqjOC0=4qj@EOXT6{gXT$3AfuQFtjzAA$A z`tP64l1hg(#}fGzoy{T<#vV{JU(uYh!W5IyR=4xKaQcsN1`3gif9J{f1sNi%X-3ZBhQCcoxa z&97cRF&ubfXByj8y*to+3e2UtJ+`JW8oPHV|K#o%Qg=nJ_yjCGEuVg%Mo+RKfThq0IQ6C`bM z7pSvf;idc@Dy9y}Io6&)u)2O^w|B@X@YLOoWm?qkjswTeO4^<}H*{iRd7+EOv?z;h z&|bAQcALTj?_74RRo$)^yU7I3cPoc;$=I!lJ7&JyTmIv%mo5X6Qj?*B%Y&{;t;@7H zrj3FS(v40r%9bgMfIvmKrysI|pLjKSEeyrsL^)=5uiV~G_#OBa;~YW0b0d6UzTwv- zJ}`YxyGccxZl>1DzIUYsv$r^dw*l>Yp$hKb#L>)dV>430`iay9Xl(E=b`SfMih7bh ztR6dYRcVSm?pNwPG@J_ENC)d_~iCo%E26)aPm_9vQySvv|w6_HgdT}U{@A* z^zZ9X;G2F1{cz4NCXmA1V1mL2N^J6p)ESw}@{gyVV63UC3cWpe+A<;_O3OQmt5^S0 zgW}T!e~m4*qI!K7mmh^xr#)e$ej`5=un&+NbZgm?HXcLh*J9I5&C=9`N?!_}?jPq8 zr)&A(nzX}5FHlhwr8)>x7wx=ffiX4HNMkkSK#RjZruRoZzkHL&6O;|f^G-sjTemJK zz=bB2FGF&CIOe;m%bZxL5rm>njDNTj1tufGH%| zGNQeeO&*3aK@K6EU~&+lSou=X_8|@NN2O&)kLKJBJE_jK+v_wTdD8sO1+8lyM6cr? zXm=mNa;VZ1rNP0|X99;^5>q`7hF@28(*NA2m9>A3q~SvYm4plr_ZWrjk< zsFDYxoR_RW(Tl6c2JwT*LhtJ5jUsQi^u}BlWXJ*~D?Cj%J%#Jw_uWgXs>Z;bZ^HSj zuk?TJ>&_h=4SA*-&^3*dg7(%AUphac=nJ6%a0+_{G1Z3 z!zf$KcjU~|p18)n9Z5jV&`TTmLW&dgX9>LTAEEg1) zqRUHz$9a)+YL`WUj;Bc5f2h%?lBVv5qsg-^gSJiZW10O0)?ho``knDdF@=M6>saTO zYi(InLz`KJ4A}*)+`d1E$rk>abM_WWq72uDcIvI~*D6UF6JX zALW}ALpFY_ba;l2t&C0E+nID=UX}Q$xZOiv?b{NHVfU4qL$N5I=Vf$F{ghbrJ;_%zjrxLp=)#cHSdK> zF!kUsnbd~Qt}?q%u#Vkz?VuwP(82q;o6HM{3NkR5l0i8=;gIWJ!SJ4?<)H_j2G2Po zDhfCn`9WQ>Nu*N^OEC4MR)`vOSyH?4Astcg^-SPM!ATfqjnKIv?}yimEiotA?(&Ur zO;8*dl4O}s$K2aaV$y++HO$aOboEZcJ_~FLHBFszz^gFv&_I)H9RenkZSezUe$D72Qn33(ia9lB zPwkFnRatlQ&Y77leZi$;?5z>gOcBpv^H6|**;uZ(;Kv&x;}v0r*{1>N7@I>7GsrEk z(jH?n%}%OZumQh20Gp|dIFo-_g-wR+**XPPP3B7=>J z#!;;j2lV8sT{SL!5Q*-==&vAf!gWUZm)!KrCAz##O_%$KPL18nYHkjcA^c{gWdoX> zrj&}b)%wogeEC!}%f!((xkraUBcvBi;-m)5kzuQrqknC8c2vMTRZ(Ay@}xt;vT;rV z!$=cH<0gI$7jo*5Ql1C%zx6l)wiJtJM9GT#2<$7sIx8Uj(c=VYXH61k>qp4|?X2YS z+Jb45X=k!DJ%yqUj9uYRp1wtYj6%;Y2)E~^v355 ze1L0$CU(2_*_+yIS+W6IMO&tnnvv4}!tMWI@4dsCT(@oUAR;O%qVyIO6{Lt#q!Y^m zM8pUPp+`l!fboW1w`-E-Id z-RJQS9(}>&BcJd0&N1g0bIij;@I$uv4aUDn&t-_EgNNWB&yL<~-7BEq$`iqynwLqC zkw=_@`n;5xJz|?uNp>dKhVH&ls!*DW0NO~#{CE>$Zp4@`0riNJhyGg2W%6F)se7jp zI0s&qb(ppp@VwMrAENE9zjy`^oXzuWF`!}}0c5&Ni=jKk*VS%OUMP0x0K_L?2Oib` zTP@cBsO8QApL`1LKu-UJ!j{Y2gAA)fHsMmKlX|63-4^#$`|v!IR8DE|65CNgCn|x? zg;P$`dR~+JOf$FdiFD*4ugp757>{++ZP6K^uH6D8b)}>hzx;wT)YE%+xgdHVm^tqh zlMW%Xb{}c+tyvq8ni;4(D#I04bCrA!cceA=(^T_@K5$*mPxzMT4Mdzre=4{9PdMTK zs~zcBM^9@j8IuPQXxL+1R}6q&&$@jtRB;+Il_u7FLUi7i5uka_LaB$j=kjZX=C409 zYEYaTveKnKK;7F|vLG9x0QmYA%JGvzjaBg&Lud|&bAF0WTU9DDyt6CBieG^Qb7Lsp zqwgM~77_ueL#n!T6Hu{7)oaJ6!722Bq|kw&xhF7^o!7Jy`+gh%(gFkD#W$p*m2PiE5W2af-XwJc~1`zL!+6-raJsJUPI>60uDgt zVe01}VU&0)0C6{rvZW|@J~_mKZ`Z~r%$5mZRl`kgW9l@;qvX#AWPtsJZh|=J zLE1ekZajZ_PUo=}g3xr&H)Uq>aFFl}c$SZASp*cSE&$)Uxn$dn6#4uaLt{ZRTWAD9 z<3%!zF%vpV)TyzIJXd}eVmi)$MMgbH+yY#Uf^Nfxkr~96uBS`g99o1-1r>xgm1EI! zz(&5;C96gr_pOwGIx*^D-_nXcW328g`gXtN8>&bF>DmW)#*_%%j$xCxY31u*$V}(_ zneIOSM?srz9kOza;5|+c>qCl=op)gDz0L8WscC^I*YjJ9JUo!)@U2a>FG98YBgQf^iucmAj zjOMRmbb;~%&Cpf3?JsJGuKNF^Dt2@x_{x-(#jT6>*V-D+p>Ln`3t{h?}k93VW_7ETYaY`D7~0p<#&rKFO~5Gw-qM z0WH`aV{i0ejgjVn3)S?yiFIEtDdqDb^9R0Ldwp9cZ?rrrzft*yNl~r%RLaB_<9Arh zqAC4AiH2_$S#@T;diNRO%O+zgv)SHI>~qtz4nOW3fG)#losfI+JE>%#yrUEzyq?T4 zDIbI?rf423O+M9kPWuRI%ruAWxQW$z?P34aU}f6C%rVyd+-s#ktPaE5o<@=0`1b5A zHC^7{ghiU70D0ec`~SWK;_s4?H%A!spYb=x1%sL^h}(Xi(asrPrgzr+{}Mzi{w|0{ z;-c-@#s69NXsJaRQ-n$cUE@AneCD!o8uAwg6i{UywG5Y9b?G$n3J<>I z3S{PYMfQdO4VKGiXD07DS={BGu78II+iSswmV5Ijd(qox0GNQU=GG#K7!{s(^%1aM z+xZzcy~WPc`Ex$|2@XC0;2=IPO+2d;!3OTu=~$_~G9UHW#Hjn&7M(Hb+F#nX90|6$ zhjEXTqmDoaUV`&%Ogy}ASGQIaylP#W$#m#&HeTs&z%UsJMS$|G0}$Rd*N%}ifRAQESE)s-2h?Kk5&g_T@-sn9ISV{c6pn-T zh8w*V9Eu9zQX3S7lsvAL8p>9R3*O*?2YX$7%b~YX?{gCd?f~~z^1yk?hD&q~gOUs9 zo>A}8Z{@eiHM64t#o5@#4S$K4vMBjc;pDOpPdp^8omqjNWcl)SX{VZ_t1(1=@mar@7Wdsc!n%CEux(Uius*q#SMO9^C5EI0jJ*J6rtgNEv1upCJ*M@S zz^`Ig%M#P{nqd(U1y zlN@ageK{5}MQTEHLQlsJr)InZ)FgWtpaZ2%rZ=H8pC?SYeW>+NuAuk_BioHInZ8v_+vE+is0sA$!g=uCkc?Bo44wD{P<*Ewbi#Y?=<2cxgWkK)zk2X7c;&`_T6XxeEdw{i zc|2-0RB3fR$GjH`@>^Rq@%5j7c650ek+7jh!ob_6Z`~Kqo^b4rW4?o4<8L5sb|8-t zJ$vK#&GdjK=%SnU_n!b#q%UY^05KqF3LNrV{AW*W?Q1Vrc^!aEQ+&LNl4@ch?^Xa= zNcjZrsM`Bm+wI@L58onMuyM>p-=#%Vy1R>(Y3Yv3D zw)GvL@hfYtpoHxA(U)&KT-Wj$p*n9w{fI&{Kp=PDf&bK6Dz_Kqn%6rxMMkP zbpV=3DlLe7H#@SUh9RRS*`ssp%4?g#dZteNTTAwm=__N)Kt<-%rK(R%+eWDeATcvO z=)ML3ogiKldTY(fhaCBOspXoCplP6QZT#Urzfzc^4~oUFkAok0e+jBqz@V^pZ+7J> z?vZyGTZfhM)gH>t4|Zwm`3en!%w#u#1@aKobmqiw!YwK9DiyN&Lt`gbfzO;5@~3S3 z+jN`)=XwFkaYq^aZB4@d`8g-=T^r_ExqPoV!jNCSg!cG^V6~IX`g3$|Ria3EnaS;p z7EMUh^%VZ3TA|dx#nG<|v*%F#Y}pv1p9lWI-2H)aq4`={EKU9vd=TjF+(>VDYxLt- z)9#IM_jv7jfN$j5w`>xVq`F*QP}{$98MPKFEkusaAC8dr5pcjV|BRtEamB7aMjGEX zcU{FSW)+O?s+vs8f}u{{bgh|jx_XJT89`ARyScz!&YBRe5bAwrw_Gl(;1HZB3dGpH zdgyx?IOVU&H}F9U*mup8qeKK3Z-Vm>=~HXyy-WQ?2IM<;%HJMR8(mH1a&S?pYk6T% zn**1_lZzX^yvEstfB?+ramv&FB% zb0B(orF_bp7G1MfHmEInG}V0A)Xu2AVx3IlSl!p>Npnjk773)YE%I{EDyfG^{#EFjO?xXE3%z<{zHL{r!S<)1doZLz*D&t zH;g-WI3%QszG_HTh;~4=)u*Giv{aC)Bh-trC2BoLFv;Q-v4zl?l1GRusV2E$1%i^d z+b^Zvj5yNs^($y%OEBprgDd7F1(iuLuBjk0H;P!fDtKpJjJh&-DO{hA@!_M#j^AD$ zRenENs}U}DIr530MpZ<1wuHJ8h`z>0!Hf;}1$A5_^G7U-d+A$@|0(9-3Hw~yE|+rd zp>TTcJxYc|-j&OEF-~z$7u!x(Ct4Zg#-t+p}K8jbD+gVb9!^z<7bad;*9jVb>E@^kO&A`haV^T8uz(!6(Q?gipN}&tFLBG8|4hqCVZS2ni_Xg^jnhE%F^Te-fc~&KHiB-f>u-A|2QC zR*SFOOMAB_m3ET;`pn8kIhaWQYEz&WcWA>JUbcBaQm8P3i}P3 zOEqn1mrCvaH2*P}dX2*S_r?1En|~JxB*lk(ByN?D!JO`rDWCP#h8 zeL;tY*-vK#NasGrR2JODU)igt@b9C3U}HK^!=%V&@z=;@s+Y#5<$Qu5Mc6#L{Sw6x zmJE^J2Grq@J1e7C=nfw`bt@g415x-7AyCAZ6yJzFN@f>bDu4N)!RZz!UXs~-W$WT` zqBnlD{C>DeB`P321+u38q7eKQC~(QIU$59^X1;1TaK@*clJ9d>w{AD(27lklTc3A& z#G~zu_j-eOs~Yen-M+5sy?BFCjJl=lk4BBtdj)miolc*VPf+IBhH9vc2l4D1CtEL^ zZu_#wV#3MW#~cLvAawxBA4@VQXP$Z?CTb$cvop44$PR4KHN_V{`@yvOB?{^eKRfMX z-48f=F5yp!+7JJ*a@gjHaN@v-VxBwU0{92~ET@=R$cCf`4tjOZz>2nmOF?FQp- zW!mN(Z@2fCUVr$$PHy^)ZQpw`KHa+bYI3@Vq=pI0DZH?LdDlF%UPKfV%VNe7pn~E= z2oUy}d<2?n&x9oCaJg~+@w>zkovD(Du)h)4T51eH$YRcLVxe`6qD?^RBL}t(>ndj?iGJ|Eqd2Lam>h zTIE-a&+plx$*#@KqON$ns)vktq%EM1d$qJz?z*gt0-4a}+?W6DddNSkef&8#IP?VO zQTN6SEs|YEzy-4z>udgw!|m5jV)o}8mf(`GG=ynCk2X1WlI!hUdsP&;{_G6Eij~f8 zQT9_NO`e+@)UK@>3hXPqdBM_P{?8&g_0FA=*A1s1l>1S zM?b8m8h?EL_M6NqwURvd0h~Lk6?~STx21&*#&P12XZnxi75+%my}p^8fkeaRSl17W zLy6L>_!9j#Vr#*S`}xrq9$&xajtXH@qBX0Y`y@+WVoh7EuUhlxzu>^+v37T0BQWj> zZ!M{PU1r|d_@w&Tw=?RDy60%RpSY{iwWS3rt*OnN%c8bD$y_TJ`*w4{1u?Kd;IsoP zbLROKEy@qYx?Q*>;gd)xYb~+o(*G(8JUGI06mk3;%qAZo#5Kauq~SQxwIc)65)|YG`X!oLp_Zuv;FY^W5Tr7q*7X2JCk&7{|8A{A8wHHty61sJQiIY8 zWSGT}J%+3U&`S*p&;VHNPUBdshwhy^08Qt0AAq=1|G3__WdssQAgg>OzQMd@1T?X| zH^h(+JqY>C0qEMVOaHpzzqZ-$AGTi) z*RLbx*FpL#eEdF${?|b>-?_2&VhM3P=<~a|g!Kz(#bVS=g~W|_*ik0JqZ{iQ4!Jx* zkIc>3caH0Cb6I_1o4ElwOQFNsVspqiLzc$3BBx&yeCc{rhr3waSAj`2?H%OsH`*Bi zSsYhfD~mQ9Hsu@@rQeCDrkqK~?_4q`^Oq9fr%XMf$mER1gh<}i@Eg3!^1N=hhTZpE zw+%^6xHG4!l58B`X(f`q}oBZ!v zs@h=+^%9`z0jr`sOMWU;W8Bg1)laLUNc2uW(6Y&(@JD?8hjqTOJ%r9QCbK_}N7^9> zm4J_(-fd=PIiblb{lKbGn1ns)B({fvEYQvMlEs3XwDvM3Hhje~S@t|?*)`VAcJn7#y9tq-)zwqGw_)mT&M-#`IxLYWf439Ha z1yoge5^#5SV=cmJjqO_b8-@=1*b(=e%4iD22O*RD=EI4lxiB86?$!5^WNwN#*PDCC zYveXAFOTQ0k=J@KeR3A&R~~s7_SYmuX}syTOdNokfYX|8No(ZC zyd?yP+wHjeLP?i;xpYM}*Y?MSZF}SQ$({NyyWlQYo$~^U=_+EU}9}GQwli zh#qj~eTFtAH#zd(AQ~TlijSneN8BWyD$HyrEQQQJcMX$YpUMB|F(-Q#u!^aic&*My zrMpnWi)E76$hNm&P%lNTxqjY zJi9vt2!Vc=4#SpWB$qD|xGD=Z(=#Oc+MRdHIqG&}<%=_T6{n+Z7S9wHk6Rc2^Vm@O z_i?2Q_1~Bn=lZ~J^==I#l2z$0D=&rfA;X6DV2OX+nE&C)O*S5)ll|P4%Z>U0pS}MX zDiKv&4=68yDuIeEmdOKCf3_58Db28bhs=FxUP$Y8ambuoFu4qvi)r@X8(sXO|9umv z4(PQkBGNjJH1Nw9zJr@>ikP{ImQSTF@$FZ!txtM+3@;!}?b@-)iC&kI}sWFjQbeoBqhs1+zqxL)UYUbsM$BKqJaXmc)jJzFI8Sm3s< zfKIG}i??LR^*ZX)H<=r<`0O66ls5%e9MA|}ffSE1SwH70Do=3=q!jlAQ)x*P^joP@ zSF1i6EqHM>;F!n7Hsz0laO=MGH z+l9niIoB{mOa`5L^Khv)tfF`$7MjaZlr|TQ|&A&$@&w>Fm!~!dW{e-f{pX5_$DoYUvg2v|D zX6t?;dhRM@Eg6@G=!ADyta9}<>-w(J=CUEhpVh#;4-5iwIJUKsIcnthAA|SB2^M~- z2xau`q9Hqh3KB=i^kEfY{~LqBOowjG8xiNw1ZlYkdL&&r&k7i9>Emu0{PbMU7p?82 z>R$H}n2|{NbkqQDLs{x$6*|bVg`<)Aw91(`Dm8Bzv|b*W`gVLyO6)z`9nbVgr7xs+6y&xXm+;9FSrX@>+(Q#i zy-ztrb~Lj)+SkJ{-ch&~Wvzc?`n6=;Zcw)%JxC86_Mx}-G6iTN@_Uz|uks|%+Bwkm z;!8Vq)~UG`)7-SPT{4Fr&|#mJsWWsRcXiM{zG9>)Q(RlNsn+qtBRjVy*04m*s^41G zxU~k!Z#AZJHL+%(JJFhSKI*qn*Qbng_w)A&0Rcu$$_l+wp%$0ls*9I6B3AZJz(V}r zFZPGYu8zVzw`7+eS!pF(udt5oiePSf7){{cxO(qyYMLH-y~o-`T=RF4MdTBPGMhzg zA5xQ+?TQBVB7cZKz8uT5Zqc%2ik>V$$W3|kxgHs|zfn9jHXVV&Uj%1it$;x_U#0i* z;SC=5veS=8?z~@dtx3sgCqja*I4WCfbxAZ0Xe!5EDjv%sRZ8|GkW3OYX!V!xpjRQvfkOds6^wkrDSQA&1vEJ^0(ey9Th z?sx;GsIFF&4y8^Vt})}p^#MHwCXzrK&6yf#3}8m5?LdAA2TFN>*gP5rp}3)czf3D7 ze-NuqQLXq?@<5q{K8GgL0}P<P+K7wiEI0s-NV|ldM|NF7 zS`A`&re?|{P-I?Q$0Uky3-OacP>y#dkNr z6b4k}03h#1ZL;YA9{%yWDL?{yoCzR7LAZ4rfCLQ(GXLMLhYGdSwy!eN5G_Ea3!err zJ+K6d9=Z^s94Y}QL%gpA$`DLI3r#+XyaN9H(wmJH^%O{w=Q>bCHrg#($?UJo{<_Ja z@LyZ%*8}wHxcGHA{udEw&;m;|n`jO)yF}d%Dn0w21E!ErCB*M=aj3*b-tSYa<)y97 z*RoH!1c$ycYkMCjg?LCqg1CDsE5?t+KYsyQhEytP8KJC&n`;XFsD(YHPrS)q*~k{ukyp)e;~r`X|UhScum2Q`z(uP&SEBe1Bc` z*G&d?*#G~w)Lb_^vRj$HlDM*I%F%~x%HB24o8FjpoE1NRH*(~~@aO~CF5Bi>1`jpD zP^ekIqSE9z7+L-f_k->u#dZXjepxwy5a4b=?{yYs42S3NWW9X~JX7PY+%5{@$N zpXpfZsO?+CE0ipK$rDD9?Ktyb7?;uDQlX5z%!h4T6;$-q9`R6SDrgtbZ@J9*_~q0KPUV+F$MTRJ81^moNuo@% zc;FCsx&LN`PG?^V+jQ&VAYaBwdXbR7A zl^f9S4}Y9$v&#+OT!>Q3PNW3qTJ@zB)b`kllv|pcn^!)dZbH&Bp=S-NTC&A1ozidm z{6n*<+-0;ZcyuXi>S}u$ZKQ3d<>?YX--Y3FP>KEfY^qx{S@!@mCTxYDAosG)uIcvY zuH^MQ&8nJ(r4H7BCvkOE4ncZ*n$$R~vhO6E83#;?D-iO$@D%iz6!lTXe(^3Ph_Qgo zu+NRSNzNb%sFLPd#5p0so2cXMvtve07I8N|K33%n1pL8>P_TH`1S})AnKO7(@R)ax zy3@$`n60&~dzD^4@$+lf7y9>2gd?cqs(7V=sM!2O`yIoPi))`o$2M&Vf?u$QOej*s z8GNvm^NkFpB&Ykco>PMEBC+bMC$7-H-=n<qk< zz@{S=3)uQz+cBS4tE8#c=(W+hwE&-9F2JWZ^-A}I4|5^FOWqM{6nBcTFMn`FdcCmk zPUr?V=G4{nedo3VP{Pa~>Ii>W0{VyfzpE>#sqOXs6i4VnDW~AGfUM$opzV)mauZ(b>%TGWuA>Ii_p{Q}!% z{B_;GmCSzK=U@Bk*K_p$?zv%lhtxo@^i>p?kjx?*Y3}pZuQN+mFQm2Exi(*PqmSbg zSw2pvy+n2)=X|Mb4h%Lmcr1P<{F8oQBxtYb6?y2Cb>x$D|I94y;MnBc*tH%0+FMP- z^JbatEP?L=Br2Vv^=ivCF>$Oq$p)OMp%O_ft5-_Nx2SHcuul{*;yn+XiKLC@^!(^k z>c?%JFDzIE=f!c6QKYy{rA%Ng+rsE7`UzWd6`u3s(O3FSoWd1f)S^w)Yv%pld3i0(s7j-=_G2xlwU_uC3P%>uFMcu# z-fBO|bkw{~M_hAQdD?j_WveBABH1e`zDT`n|5BBb;+(X;ymDWBLRpOVc=<>8;Md*Z zoU1a2BzvQ3vxphZ))Z833xPQ>(KUJSUA9b2Xk?5P-)HS(f@oywP^kxV7)4tAjiOE_ z8F@d__R3KxN!3$lm)~azVF5p?tvlbHC{s3Qy=SrpxMqrW+4N&YuL{Rs`mG{1y(4i< z&AfPAe@0}fd*ne=*ifLf=!>iqayw5usUp+z)Kk=CMY*d1#9i@x*z?NjZs*t6elt6o zu;=$(Da@Of&ENGpDgG{?7GpwYbb4fkhw*-V;b2e_k9Q{v{K))sXvIHgtQ>upvM~9) zqW8p79v_G!5=k3CTSxGoa%?yR899aztppfx+Ox(F?f8BD2si zJj1&te#;O=vD35xT`GkhUBUqNM2*phqE7ED5tGasdK*=qTIICbS7A5QmH=g8?lm0` z-bZ;49xQAlkx(KscXw)H=glTn?O_!uKIo+heS`IOP{^rEF;0=M@R3mpL`ZNcf@8At zPBWf&6L)%1@T8;DZ`MhHlaC$;D*IxyTG#YbPLsolg^=q*v-5wmxy~v)w(#i~7?fj|4645Z_R^gmFPx{@{2G{G$moJsAV&MVTAnTT~g^ z8(a89<{QexZ-);+?p?A6Aa64}s-p?I33~R2$5_kB2~WG{F7qo}l7~!$S)D7YYx=G~ zJ<8QO0TY;1I=(b9*T}?LhC^$|eQ9vZ4=E-G4KKyj$!^Wx%0FJB6el)mmMb9bURGX{ zSF!Y@@IkE+?};HXgI+hIg?8H?gNr5CX+jCmMmP&s?ar75rQC7vX^jTKl!qYLsPY-$ z&(4Kn_xCThER~fb&rz<{kYls3Xc~|DsZ`6HY^fg45S|91hj|f=r!XF_jEcO2sF05( zWF2BfEk8A11bup`Sac|dWqi8vnp-qLT7fLN+F49PuSs7cCk`iud@sq}(@2oY`>~^F zSW$Drg7M_b_Xi-aajB_6#W1-Wm4@T)^N1F>8?6h%{Op^HC*n!ATG58?%>t2A+IWRx zfHjka+*Gn{t382WsU-0=Dqkjf0T^hzcp^9U5=T4rT%AYQ1Cx z(V4a|5SL@(Br40-u|t&FjafzQDgArQqV)jY?HY<70r~{1D!x$e_9>4Ord)g_3}mD6 z*1P)1_cS)_L=ALbry(x-dPk&q%mHXktp%dxOCC~jbzqw*DT_YQA|Y{Y`-!iqI`PM> ziNd4)YB`q|ZA~$#Qm)bAy-;v{Z4qwOk%&>xf#?EG>;k(#khAAC(n@wynt)**-}qkw zmcev}i)~$d5aIR1$x3{8ma>iP@RJ&O;7app&@wMF5oN=Ej8wQFrW<5vC!ATzOuy#aqv5j9Z5b4Gj6m4})2xPPw#qmp0b0Dz8GmN2A*?;6@X74M*lcscQZN zx{qdS{$C;fLI#xcpDvsU$gbS~=HnwKtdcrnmCpku2NB*ai$+VQru61BQa3BW3Hi;V ztAp#18@v~t^c=K3aU7cpR zbNYLS7oE1IlpaZO<8!!dorQ%g=v3NJ;G&^_I*D1I`$7EMlHpSZfm2|-18Nlu7!L4T zn7_?txhK5gef0oDJoWs6;7E>`(a4E76X>LB$+-a6+ISmh%&kQqld4nr6rT)eK}nyO zKw(j++KD?L=2;*0RU1A*_2QoAW(9?sg&8{I@2bvzPwdTXmzcY^WmDB3x3+2e8=>HP zd`xNdcRsEnG_#!<JX^HwIn$Z^z43Tpl}BD{~pX zIYX;jb+q_?E38F|ErzTjLgVYG{13xKV-T5&gR5E%+7R>hvPws=fb`Dm2^ExSjcBBgT3&a zjD>4F$+yk@l}8q#@A))62k=cM@|Q)-%`Z;4TO6Zu7c|Yj_2Sk|gzn9&JlB;+@hIs9 zujfF6D_wHgx7+U0t>%LF#JsL1XD{rP9GZhBSfFd=edpD*RL@E^4E4tJp@wdz250C@ zSOCrjCbI+;)`xWeO<#<2s1{s6FIlb0$(CJfN@HNSor~{`PDh}R+-^W&i zl`T1&>vHnz3*qV(vWIXmiVh)6u$lW(vu~cttkL&VscQnvm5bijlpysuCBz*9&=to{ z3QNhj$mGhFTW_R3qTg_%FM{XrX&;!}=2RlZH`v2@7`9Dx;V4nX_Tw`5j0CYcfpz0s%Ud%seOm8y!tSrQgCW`^X9Oe2IqFXd6CYEqx6v6LqL z?dHS0>p4~DNK1yjDeT3$1lah)B4g}ti5o+d5kC(zVmlM}XVgpZUz?uTHSR{5~}NT z$DLSp!Si`AYms%cOj@iF&p5cfTfbN?>Oi!&T!lHW3k4itCzv><=Sv!hcOlBg34qW^|52HR{X>4|wyaWra-Z1Pwn=g;iQ z)~g+-WOt$7m_?_|@p)v3vKh)ko@k3baMCkzff^xN{jCEUXKguDKe}Y;#7kjUe`qSe z?aov!Kcn0rs?4Dgy0)n|(~Nv)jlVLo)Mv~>biR2fQg4@(loyovH+NlUWuGr>4(ZW4 z0s`L@c}=z@E@_ZmKb%zVJM#ltnxD}kA-K=H*TAQwhC(q#GBgtxk zye8DF;CsOI;xxoQ4g>wEqg?2I^?zFJIPj-UyQXhLpopk?B;=&CJ6BP^<15#rbm8)h zrlAnH*RDV#(CC9jmk3;}d~Tg zCl#Yz-j3@)@C%PXeyaIYy+8RNVH?lRQfUFcG!vK#=Yn=6AiiCY8r9JBZmD+V6e zXla|={tu3h&mvnSIA?CokKZ`~)ZKkpr5Mj=dT=zz`)e2;MS7>bB%n%Pqr58ZV7{KN-?Qp#;gIcP`E*0P=Wl-8^X@H?tydV7(` z1Qc{#DJ7VMBHypJ{eY-kO`cP&G5!G9Dt{TevIo19L3!})YC(C(rFZV4GT7N_T5O&u zFzP|D{fbj{S3mj7GcV$a8Z4~4ZX&UDX zR?h)+z{39jil5=X^lt`%3G>s!nXQ5^K^ZR7L!llSjj$9!96tvU-+h)>{oFixsrwmU zH!1@Tx!xfV5Fj~Fb7pa*JFrpMu?qk3+)ydtrp>b$LRevhnCZkLUlBb4yZ&cxeBHIz z7c1EV%nADpg~eQ}tH_OVC)E2DU5X5$9db&a$x7K1e#Ahb3TR4aUP_#|eJ9pF!=f4T079@KD_|dd=_+R=Y|6qvGQ!@Hi0ZBQ)`@M~A<>=mxuo{>Wr*~Ez z|77hWpi>P_=4kfHs7JAsb*>kd3$E@iO0Lh5&F@Q48J*!zhuXj;Xg|Ym)&P_4$xuUm z6WJtkh@SVxd>VglSc~&(h2y&^=Tn6dZ}&8QWZ;s#u>Jc#jyKlhN?J+G-}8vLnM5+Y z+Y*0gaZhC0jhelDp}3S~UgG<>r^ei@x&QU6%61r$sEUP%lWKPRu+fs>s}u=ROUgZy zfOFpTXXZA56xOI{X>63nObG>aj0~l+>I5&DifiNYsWmcFSsb=8lP() zYrAnjb>XYPxH{Xs^x6{=>tfx5qXPAZ?Jw>%Iq;YzW2G|Fwi%^267r3>9X&!JRZ2G&$4V2& zoV%Ky#OP!})jeGW2DhqK+_u&n;Bxyp6rtLedP+!p4~K0Vl0zeuaRI4BZY7}`Mr);N(wHdV%Ax8@XSyeSp01AF?dj>4r}rhe?y1WBG zkbm7=@z6grVJvpF6SzP0{8H~$$g`@_w@*?do`F$M6fT$6CF0&F zDou>bTBq=r7+F;oySgjqw?v`7=Enu^e=on#@I*SD&$|W=*w>;`NNx((cWk?QXu4_0 zRh$Bl1ew-tod560fV4Vk0E0dbX-oUt#G9M^mjCwFj0b=2{6_j2)MyroP;&;dW>P^( zg-pR!J)S7yPA&jkvRg0Ru4?Iq+KM5$7oh~+$w;Ez!%e}ptQKY#*nj@~Xu$NxT1)XE z$;Q1q>&hE)edoXAuV?Lkv>jtox;LKZ@WEixKDz-DxT!o@o%4u{%3OefN0BTQ&s^u) z#Qgc&#*c10bPN?}nU*Ptqz0Pq4LlzVLv(j75uWHw8ty2*QzeI8Jd3jQ$UXvy0#3ZT z3upuFRZTNq|*`AucLRFE6}@u>iKD(X&?r+JG% zMR%e#ai^iLbRgg9>yZbLQ8aGAa}V}zrO*R9iM2kpG-;ZX)!D5V-?XNN(;2g=883mA z6&rL&^3H$7t8z-$d!QyS$7kD>^%t5sdF-NBhxe~9Y(f&ScmC2zvP3A1aXdYnA%b0U zE{e5!6gIi)vDRRl;6l~VCeE}rq;k+xGrL+SWJ=C(PE)le0I~4l%Uh+pk1GKjh;oAV z0b|=nZ9Bdiy%F^Ht}9*lN{t6Cr>j%r$u7WCUo%zxkIsI1qHRjQq99=$dU>%~sf8Tz z+@aGE(_G0dB3yD_%c<)MR>JaVtKq%57&t<-L~M2eR&=u=;v${DPhcH5&k|)xx%Uk+ zHR|kheEY;D&dmk_PIx<5qy@wL4JR!E+-=w4sW|w99lySHMKAoM9W~}P9^QAtUOuKx zh6*IlQzrhHDf|f=PI#$LayPN#25Ra%cFDwedvHhVZT?5~h%MN|hIQ$dMKCi$(kJfj z$($5o8J^-YgSv;wnPsg#9&Eec*1dLn+ar)70qtM@n8@`_gFZLVOCsVHMMd3IPQ1a# zOw$<>uys3cUgI~sW_twcycWt1q4rI-UrcjagQ5bEBQ;94x&i{zbV; z2xxgZi4+8iI|ffkP|cV({dpJ5?B9GiBMwYm{yOB4L4J2@;F>7b%uR_kIqv|3C_Cx? zr1-hC1ECXANA36#cQuK|#S;Tet`ofZUlf}Dg*o7!mSG5!Yw1SVeXfG*CPvGlwnJgE8+Ws&z^vaF-QmO#4`+$iD)S091Vc|28c84{_yq`B2%YUDBT4^lKrpo-{W_ z23@X;LsO^~rhQ{F2koq_k9d>ew{n>?fw{R)kEn(jl;zyb>3N%?zUPANaTpC>(+ioX zt;(>1!Jps;qL&{6YGTF2hcEE{BD+oGHKIlXjtOuRwYy~ztw%cb0c*%Jes3m3QH?Pb^V=IeVTdVVo`cEaVu48=}{Yy z`%|uw?7!{j(t+6lW~N`Ep`q|dLPIpbCObSWS`UEwQ(eq^v$(ceIci?M zed*E~2q6-DJ1#|NfN>0Tk=>s!!+|f{XcOBmLE*-lXxq1AKMv3sH!r&;C|+jQ?XA*N zcehK!vAb7ttfUg-+8f!sKiLe$i56x0lgBjpYAI7xYaYi{j|(_QBs1b}F*#vk-^ZSd zW%c1>wccIV-H0$MX=-$nA}4)gL3 z*#ZL_(4@G$Y!4%2BJzXeJt?qqKl{a~vc7X@$ZGBz*!YVS;UpV4vnzYAb=8`;^vA)) z?tV&0<8ubjZ)GyEohoe-!L}9^AGh4~+@W8o3BbPC+#mwmLkRS*eqlQu$imwJSvI)B zxgh(J8Eb|&gA(_%CGKBXKl0Qk-hOIXWb;!6n%m>fO%gEEYs-PbWp*9jb7s4jzO%<_#Gf~NIo|OFn09(?&f~hU_?Lr)}bcmw@8Cw z?%tTs5khadc(*|lmelNhfflbk|DXwn(@S3OvJLdDhur@MasM6GiyA|kzHBOBO=fPfNeq5>iyO?pdIq?ZUt5rjySPDFZ*5Fm7<7wMtbgc{QPJ?t}k zzVq&xIaAJD^Zwx#f(dZtc|LbpYu)QUF9mw1e&PC>*3MVyMKnQEo5=dLwVsiBZ_u&U z!a?Ybho?^<_Cj@K%q>3QaqYKDD+O8MA9BXcK9FP*D4c%&#Ek@df^Rd7=SCSU_~wDW zp2Nii7VbBD`fTCeXtk2{BR`LOaxArLFf;}#xWBu$ZGVxhY`Ff3UM`i**`>iTN?Ys$ z6YkcX0D5Rz6jj(IN9=OF{ivl8XOoVv^OA<|t;$FKt2;jRKE1VU1=P#EYi>@*KGMJT zeGD5r^{hdJ_w1!#?!1W&ynkZa^;H{M6UZA)d;-Sbojl;pZeC-HK#$UaP(!xV0}N(T ze?(oNb(>g4QTKWs|AZbqNK|A?$K)Vo7pT98lmFNL@-N@d4&Bfb9kNAKMohi!GA=0e z(Gyb}5Tei5W^bvP456;`)?9hImaH^2bK9$YAd9};g4u7iq}dPKcdD>!MxI-NZJM(k z04!gmkH5E)GS8!2w8Y?t_bIVe^R?| zv&Dvp^mnjJwI~HjLH7&rJN0*H`CxC?8DmBS;7fyVVWWwy-97k#Hpg8A)|dTY$V7Rg zmZRtM>A;m2^WXtJBAg7!GH}Ny|?ymO(uDMHq1GX{Fkp69Hs%Ns6q>TqL+%(br z?)J@VrIoRGC3uHCT-kRkKi7yMcRHZ;O06GMhpA(%&o6cZ^Kby49}t1M?Uvx?l^wP_ z0cx)2Hw)L;LO)NG4qCJKD5t@41IGaHic$T79=jDE&%?Cv8WbW*;)3!tpGD%bqE-)bg86 zrz(jbL0s8s7YjZg|9BN~j){(dFR(igEE0bKKri)L-;diFFj~6w(kmb$M`>;KC*UT9 zdq*^9PfIy3*VzA}hi^xHg_IbYJRHb)+3pk2D!qt!+>WA@nP_&n?@OUpZh*1LurN7s z@T_LA#LWtpy(q+D`n>C|IlZ!|uaDkBQ|jOe+29!Dl-(-eQ)_^854`9bz3zwzlbArY zIkV1+h1ZZwpCG{M15jaDwIF~wPT5AlANZO#CNv+Ho?8P3K8~W;PWL5z3NGq}O8j8p zkj2ug--zubgWK;`*b;wfq-#`UE8S2bMr;Fxo61S*N=DNK!}+2Qpd^~=)3c^Ja^%z+ z^%vEMNI&VEX?34yc{&%u10nMj{HiF;#6m5NB|D8b09wbZ1MGU9L#2%}N5|A!-~b!% z;>Z8ggTh96Q`_S?2kc35RycU{gMp2|K7dHxenNCxGISSJ6tpodeavsmuH=9} z(GQF%zXf(QJ=TH(tC)_^N7t8!`wG0o8dlTQX<0du^Sf_W4q`aoL zw^4d(sw@5>{GM-hED8_K9;&-h8*$=XmR&eUs3|RR&w_?P>ndExlJ_-534N!ZJTxI^ z{P=$fG=KSCuVGx>MGO0xPwAI=Qrlvdjx2K>V1xvRrxEKJz;1{NKx@1PwgomgL3YxV z*vzp)wM+c+5AsF0j`0Iprb`HW^ynQO4-19C&8sEf)^<5J*R#VUg(W|PShaB~zuEx& z=m@piulKyFjrR$KLi2T~S$NIYs=UI4C%4>*9mW=86bt)d?e}l>PS?FTr+1|#`K)z_ zek)&>pA*Fp$R5Es7&8@dE7~&KF6dM!B1lr^TPB4U)n2zfyV#hha@|Wo;$&C;`0}X> zz4wI6DY*7yk0K%hP|&jCSwv7O4>92tD;8)FGNz0<4a7GPKHQRlZ)Nv`&4(A|J+8zt zzb%;9bQ`Rewx%&y>xfr^RX%GooSu{-EVz1J8fKY0RVW+P!5eEREKRZH&R5jmT$d=!S8 zV3jI##SCvXvrd1)t!jtStgN-NRZq_`+&sVFqC2ku_s)S(dtYQfd>i5eZ4eqSlg^r%D5of6IO%Bs7JIcS9%(!=b#%>`(ym;9Y+KN#|c^LouW zYtgJQ)6YO_YjIEPvF!k;@$q8#N*{CW-Q3hU3eh% zQ|Yw~rns3U`@2lw)g1lC{%pdfBC#g^=pJz@|kZd%Z9d zK!S_5ELE3gNZX2~@+VB*B%CjhZQGlW<2@SF%199(WG%*z)k)kTK1I$RKV^HPjo2xH zMP}!aAsS0D8JbsujW{nwyjE`ZPOT$McF#vHy#B%Pq>|BD7hv~`+v&W%knr7mMjYmf zi@{rU!x?gbkp&FvX@Oem(M_*~cC zM3kFKVLLbF3q|QGecEn2HtHoPRJ z9EM%m^U`hIcNIX)X%zK+X~RDk7orUwumu=pfew-9UWGeFl#EC-{0;=HiR@6FTTeu!)9sGDE9| z97ZH>&&S|B)SDu1k@L}P&)L?{G@k8jTM*lg=h^hGLouJIvo*6S{|0IhA-Ybz44{a1 zB%kj2D65BCQ^PO(s=!c8By?~`T*5rKb>PuC%Z&<6ScW^Oz3Op%8GFcA?RfI{HO$rl z7w&X=uId;~fn(iq-RYxQvb@nVRE9`vKKpC}l${8EW8*iXwajBT zS+Xx}oyMZ-G^tZN0_k7^Mg%|)*19eByNA#3$vVCP!`IpRAL@4J?YO@~ni*0^J;m!0g zkwb;$A7HE(bP=L5I%utSs43yroH{6X7g*%{gCWi`r0LE(zPnLvYzFCJFXEeF9HcL- zXH30ao@g%zZ}d|#C|zrcK6Ljkl0>6xn=Dmu@=|BQtrTL$E+FIO@g<*`GJk@8qa^8G z06lj`*k%NkI6UwG60E}Y^{)9w z3}(0Aa#h4-!R4f{+^n@zEW#H;)eG8HJWn_}+m)JS1){S}=y<%49+Wv+rk= zH2@0JS^c_UQ*7hxuX9J@-p$=gRb~7(oaARt5cS$`s8Ddbb|%f9LQ$LQQr(wY!iz1( zu-a{Jj`ra63Q0bCj4O_a(%Y&bSm!Q>4@UwfrM6J2<(0Q~cduK0PQC-*@k2c%XN-1R zZJU4LirTd`Wml}Ey@w;|M|OaI6=n>7@t5`Azw`Bjy5f=nhp{0td+ODd0x1$wZ9}ZR zOfQ%mlyDf-94+|dw|?6Mbw@dQTYBvR1QpeBZI+|H%uG51CY4%$kzGXy?b_ys2 zsw0(6e@DPd5cpw1#9hj{dPPzXWh$zkxnh^XNLTj4|4-_^T3KL5-=ZRGXX|cJtHI+5 z_(SM>85!{BY*grL&%XO%&(QUMsGj`W2JZ}wp4gG4aCB}9ZEN2glE-RrWcVw3A0Lt? zHX_#SrwY(F!^m}am#qemhadK^elZB*!}W(VR_C1G5c(!hqvMxmzACEsBdmWgV2{55 zAjkkW2fy2~nserGiiKI<_lOw2N{piQhJDYJP`O=^s+@Hdk>81 zZeH21*((t%1`(w(Rrp~L3wkY6mixpfOP6md`j|}s^<@rN2l}`jR?@+nsXKM;pX(nKI(l>+OeWa$MT;=&;?1eJ;C2w_Pv*MjeqkL;Y7P+gpIBmvx*~r88*`yL| zb?WiL9p4^8)yUL687Y!c++OS_JMD7%kUVWdRba^{Y}TDM$n^M-X;)^6V}qFwT_={@ zH`i(FaBTqU1Kv7g{)>zqEI^r)ck3FO0|2_ET9QCrX?7~l?R$^D>!BX`f-1a5tcY+^ zD}na=HSw9}BEbZqcK99S`jicQ`|kbivf;^qRVt<_92N$sleX)?vo^sSpDUhd%lu%l z^^{ns0w=PMjoKwSX4Vwk$fyLZ-4yiK)Q6_>NT!*Q4E4xsZv9Pn5T~l(Vb_YVkJ7_h zhj#PDPc&?9n!Rewp>$8YL!^p|4n|yAl(h z`DdF$nj{#$;5vQGr+aQmh!AYQg zm9mZ7Z%!OHw&Fi2ji24Jb4@7AJP@9M=jY-ej9e;S%Qu$hZ?kee8zULdBCgEs2B`)0 zP=qt!ycCED)CEnI?{_~pY^rrpR@oUmSWIR;3`4F)^&&*gH^OGD=YAfRp|Q7hSke-f zrqp`+sxp#{u=VE8-RRa8J;h1Qx~XvqUC({3*^wEmW6&Dblx$r=+@u;7J?KMM7JE`R z_Rvx;S9LI4oEUgn$lwD|yn;SK2rnUAWE*&@h$il)bHWu+bM$zCifVips z$L`^O;D`F(+5PuB?FTf-VW@gq8ub!toZdsbVUfRfm$W&{xQVfqIGw$(f+I^w`-j4$ z-rB=100JE{$h$@1@h#F1hJJL{=Rc%a;IJw!&OQa2U?!)x)@vVRsYmEWG-m|!5>*K3 zU+ukox|gG@nC3A>a|gQc${xI#>`?U7sGha#cnTM5Z;)7fJ(op?t@~jr4!!bZ+UHgZ zkcz+NQ$G0F^rcsHIgp-tZ|_So?Zi}c@ne9pr{3oX0OB6wkSQMq945xK4;?1B7zxtz zJ~(V{;U{_@A#?p$TWd)1F+?S;K6o2#mR>12>cD%aOdYK`=+`MWlcw+6x^-G?_VnI+ z@SaV$!N)RbEf1nuu0M3Q;J7#Rk)o3IQ+r0* zQpZLCunHcM%1Q(UW;7^p3 zQ~TAuQv-$1_g%3CLjS>&eNSSk!EUx5I8b9vtZc!JHDu zdRMD&f5pEQ9xg}ez{tXME+q>;#QX*8fSxtq+C^IgksqJ37K9=s#HbGw8p zeIV?mawr^r>2tPIWL;d@O<5zXxu2?@wvu>Jwzw6Sz6cQcQ{n++qe0&bd5!i-XI5L+ zA_n66f!I=d?f07LKmADB#1{o1rV*UWh>J>cHK*ENPqS8E)qiOQ!ixS>xT8D<%#u%H z9?wQHcQkQZI#$$2{92!<$C5pvtGdt55#}dvIXlHV<>hI>^?L8t`mlPWOluQvk@Wlgx!zU~zJ^}Px?7u>jV6z#~mpFht*xu`O=wNWtxrhnfCt0M^c zu~R-H*4u8tI1Q}92lWVuth+XgK%D>2OdLJjD0DzSvbV2{e})2luD~hA>F?5$O3p*Z zw{$FL2KGu2wq6D^ALHcNE?z?JgUF!njK2EI(B%@q3EHcCG$R`5Lb0qKQ2Yc!0E#j3 zDGL8&f8QTv@XGoqaMt@xgO};$k7ky^^gXVZI zE_Mh{DWUPWx`!;w8qf}Qel0j_Z&a#GPfXrC;??pyL;XJWGZ9?IR%c(FRC%|uuRHyB z>VV$^`(Hhxd5HU)REzYn-JS&C&*(rdL))OTv#=dxDE9+@Ka9Z6i`{AB#Zm$OtuU%C z3vODwM)M1Bc{cfG{!>@y@aOy)6#hGk$p4NV`0t+%kp9@|l)aSRehSKlCh!zpEQYUx z?N61d#~@rgXyT_1fng=Z0-^*xReMKeJF+zEC6XqO#5@0W?qeoe_|iqtAs4H24j$Et zcKbfA*QD0(`abl=HBCsZ`<#OvBE!No95BQY0KI`wuT{)t4LhynhneOzCdul(cPvxp z4_ovT`7Kw%yVs+vMvG~l+3l{oEeP(V{J}Jn2XE{&pBA|rCcS%*a3A;!3>yE0tDmui z5~2ViM8Xvm=Mr@l8BFzM+og(inGUz`A8{2b@dsK>!ADv{MevJ|>`v|2pA8z76`0dy!vr58DW=vK zxcAcj4}qagFp6``#Q4f3p~Mdij0QTVUv`9th+pzePGD<3d%e?(ftkqDQK&a7^X2;U z3e`_$yfHpUXbZcRRDp^GTXIWo4vAu9abBa{mdIQ3;pNYCnLYXvy-wLxqqm?`?AYgG zbJ49%V1U9ycwo4*+n`gpjqh6F)V4}T>$c$J74!UQ7?S#vgRD+T-}8*m#dC*V0fXIuyxoE`_zJi zoRX59{bzxOnPDy-rc;B{ob&4QQzi1pG)kOZ_H&ykOBV)4T(Rr}%K$7}E9)DWq*>}Z z_7J~qj_hHdP!J3=P-iI|V0&vHH=x8elcFgul+?ILN~eudgF%S}^z5iCs%V~eX~IhA zo;04&PR~}i_qFi{C0i@#rsgyRFB|2zI@WV&A4`P?=K%iVOR=xP)3yMcI|!4Sbqc1F zlSz;f9aP6TeHt2yqBNhV#cxWGj_g(es#b)!-ZQiU5fL@p%T-E~V?u*NP&J_80SZJ> zxLNB`X{z!a+}i%h$nA~BT%6JA*9_$0g{OrSXOaQMXrSjMm1ow8e|gNRJ0Ynk?um8j zWGyCsP4z7r&Y07>P)qGliM#8U$OnUz)zb?WoABcqc06>=2?+htkh_eyuctr&RWSti z^^9mrc^blsvVKD_u$FycD);v~A+h*k^dUvq$iPkN>69T%L` z_KI}t1JWm^q-&zaGY&P|;_J}EPL3s5w)l94*Gir4j`K>`yVcCsoYnN4PpBf%`fl`q zkH7uq3l+z6GaZN^vhR%s`jMS3% zUT#!YJ^g^mYBC8sb2ZnOP%>+jLBK)Z(qic5KQ9K}!b{5iU?|EB1g|^rMf#&mth~dU z?$_>oaEsa2gj}49Zg?_otJt5k5U|NnF>%=Ht$}X-JD~XAdk=f3{Ulp2_2;ajCtDkm zO>J1ZatN8u-rs9HjBPCN78OeuHH?VMEJB{K*W)A|?<_AoWVxeXw=!1ms%^;aOHX+r za0)6lSdqBpLg9J_$oip#HL&#FW zE4w20S`!|K3`Me7)8pYm_$u`o$hBeZX6n?-73hr!pQCErS<83G(amd~zN zdBq{J-6ZC4&#!zx(4_7rV8}w(TtM5RSue##%0Hg3<$;O!VqbcMf1-CB9*94bfckpJ zIP`CGNCGezR*XTFe|n(Qz*hR{X@31eKe?@W`Zq%D!jPNd8|x4*K&(qfrcs+8^eg%2 zJ=;HekLX?!1XcQ0>8$+g5_TM3w)QY3cUi%s*wLYk^P<&yYM#F;Z@>rQ7zL#WuSvd?}C zcMQoMJ8J)&zNPxr&t32bgEKsvkk2npl%A~fQ4*i2Z531$a;Hm8r~-wCz|`_^9RU|q zs3iO3GV+|cR>1X?5i;xJ5lGjpm^P38%u_W|f#4s6?Y~Wa%BIhUONxsq(ymLx| z)mS_wXB_ulP+-AhS7kDw3^=j=$GIi5*-wfI`kZ|oHXqgSw}3T}418$pYQ-$;OXy7i zluRxQUzgdM{QiumGv@oc`ivY^4oa5y&^4+f7 zv!vNp38H^~Q86=6Ya1k<>iWUG6+JS=vz!!EIHP0G@vHHa{!K;G&``Gb1Lrwk$TOQU z;6Fg7<0@K^qadRJcX7yG65(pf^bdy6YNah)&WOb_QYlu8hh0O%I8nRu$m_*`Z|e*7 zvLVhdKA@_{El@RegF_RwWPTY-^@A#@VXfBOAq$qmYJ8Oar`jki$+8f zav>h{?3YWA9WMkMMnO*01<;v~6s&MNt87OS8Q@5G6)QX=Td6;C67gnP{%Y=8%GSUx+(f&J+xtd) zCr#6wiAz~8n{9vkIcQHP$fmkKYyAG{&TKE1JT*%}8_p~BK85u)-0}NQW|P;}FdYP? zgYVx(+>EMr>w;hTNrA8gWe+)R)Sv122M*O>22GJ_7+)a;rbB+ZCCh@^e5IUING;}&cF!SDqx_>6aCJb5JHv&$tM z_FZjoHlO6#cgjX6ALWOM>IgQuRGhkt zDWZv$WokyJq0E&kbz_R^WsNXhovwVnASqrNF3KPA29PuORQg$q<^ej+429*PH*}5{ zb^tl6^V7epRQg?$1PG>{Z60mQUHa^W*D|OM3P;|~W^velJIcEtGw1UYuFMD7i00MA zPcfR>ZD7}n;j`dixeRr$IY;w$Korl2?bdL9&Z46cT(V67zy3z+Cxyo zAMXi7e<%trh%=r*^6;Xr-0|1{5`mahiQ7t?+PnVTMQl2EqoZvHkpcdt9k7uy6iq$8 zY81J6W&>;o79Sq>F9UGSK~xGr-2dw!_&<0Lo6a#=$=e)ke~#nB3HGov7qn?xH+OkW^S*zitO1}fgpQA`+`LXqeZRt*qpV7X#KA}) zGXkw)fGYH2gYl};OVSQ~75M~w6#9_prAPK=rM^eJ@1U%}CXsmH{@*hd14^IJv$d$l zL|%>V8QuO%$F3sA4BJut%g~ey#d_Rbr$Pl>;;iM5`MeezY4~AjBY>3=jL)Y z2Ypcs_%v;Sl=i=q;gCp@-u@4Uv%8@+!ef#@7!VINe*;ShoBNZ3Lypypp5V!;=%?OgiPkob@Po|(vD z=>lLSEC5#WaS%pHMJ%5*JtX4^5&%&EJB!&@878wIe#ZtF;|(_1&lT7Nitf9lXL}iX zTaSScy&rVqkM*&4MbkO}iwJry-P+S-`oZ8rHzcnYWi(c!_Ud2Rc;Rkc7y*ptvfB|# zHpD`UJKf3}Ewe4KD(8sc@6Ig<=B=q9*%&jO9549de9Xn|pU7uDcwuHN3 zQ_>YPX$=ytXHi-b&HQzTY=P(BJVdTZn}KeKvzKL~9g;cEWuF1_<41-y)vZn6h^jZH zS6^|%3)zaZvc~EXgI`W$_oLRUz2qMq5kv09=Fv1~?W+J39Pn~-dVa2AWCO`>mdXi4 z!wJ@J)5A{Ypb(`anf8iB;+i8xNX55)5r{D;STbN2%`{JnxKXJE1p`N3^VCfPrRs@t+u!u7~Z#}1^+g@ze79UG^T;!UuDAhoG=wWu!3PL_qo`= zzwQ<>N+^M^QGi*%>16#D4X3yziquB{9U4?<{D+}YtU*NpASCMpyd{D@4i`8`JekG& zcWMb*A!}ZL4Om?^_gZ^?b7w*eP#+`?7v$oSG|?+6g5OHxM-g7p;C=6>)P$>Ff|1lK zx++tE)m;|ghG0Ku?B_7UL&*f@M~f>fQ(or@4d`yHc`=-56CBoroidAXVTP`qgL?j8 zxb0=wEeiWJV>S7-q3!^F+l}%j#dlpE2e@l2)JqX9n!9k+D|G(Ogmb7H5Zx+eeLeac zU%30WLr)WuiDdaeM`g3A+~;Z9)%(Bf>o-dX$X)s@fHWmb%{(v_Z~jmnR}zXg%eOi! z;P@boPt9l8op+^3F@YsPz!xJSA>+jIe040TkAm4!01W;}22)s%WYjrmC)is!nbEDV{UY@&M zd|41^#Y7P)zNgtcA{q?QjJoOH+RHcxkk^qh5~VuY+Lp)HGa5OfAoIB5C3S<6{<+w* z#%A$5#>2xSkdb$g){fU1U0Dz(JrX!=PALwiWxM3JI)e%D;4m$KUm7l5y8K?_sJH#% z=hfFEt)M9TC9jMq&Y^4Xu3TbZxXHl(jx4skwN?~=QK^)^U$yf1b8%+j*_=Po$zf+1~+ks+7CSRLI)HJ6WefuPS0 zy%n^b_dRoBBROa>w&=%pij^k&rf^N6d#6S0JNBP>VfM0{QjUgqxcV~hiwbfAb2(iA zjcyc&Y}V#bf#%u>)tq6v!)r6nmkBRh8BF%iur*D*LhqCB$-gE}0{mexC6c!R-xUk8 zHVo$q&KpD$7WY>S`T;vIn%+-+B#%!=4VuAO!fhPue#S);&AwF zgY&R{*&Mu!As3i%IS%}?C_#@DH}kz#yf>z+XMgww-5xc-JQjrrjGcd11+xV}EQU(U zW!a~I;8K}6EXyX>mK^5vxhiTJ@wuUR7k9S?T6;AU&Ee+$DfLh_llC`b&i|H}y(HF; zOiPfo{jQAFMfjG9pS|7ossoFh%&un`S8ic6-OoFD?9tX~7d+v9lYSi6+VBotGdp&n z%-J~4D^Ia`YPkBKkd=$XhwmZj)bd>LjBy&+DJt-YU0vfnoT&OeMf*FOIAZ@lJ=uQ{P5diEsI z|BTSlQ=-mz;)ZgRx_3l1IGlP~z0bQWE0C^g0 z4ddWgw%vwRBvBM;6#03T6lQ{Be42Q?D+1dtR#!?H3LdZ;w|%#8YrbLDQg)0?>+T^a z0_Af3GcrJ3{B`gGzIUXk;X>6?1~|?OQ0)fZ7%RlOU%h;=d9}{aFt)wlah^VROLi`E zIGK74$?dR%nT&(b4}hhQrUaKU{O8p#vD7onKI zMFWos0@c&fYmEWChJsjD5C;Sjd{jQ#CJw{h^__kdTsZq1Z6re9l%0G*?WrZQ-gA)K z%Vz!KJi+fDQLP#9qr&WG`RdbE%zXO_CKF@l5Utd~b?F7n`JJA!XT>WgZ|&*zP-2`B z=8#ZSpA+l)Wuj`XL<03_IOxRkw)jwXmcB7R#{l3Iw!@=1B>&I)mj0&Aej~bS4H!f`+6T*1(eAYQw5Tv5~7;)>fIdUIoM>|Q&RuM7x<0f&~U61V!B#L})p`}11#(k|ES%;!GTFmJxZG8Y6vKUpjpGinJ- z9Z!k(Omh43YC>g@+jZ^KQ4*wkFfSi3(idB6sE_e?r%X+I_a~)1YpBVxdI36td7>8t zzecjiCS~A-3MK`KsIc`|{d!F0`-pFC9_ja^&%zB}zS`~b(WIWox73ReK+R|nyn}vY z;OQWEhN(JYIpKUtpGvaFk(Vd=lD%Pnds*4!dzKWqUMG ziy(+a9ePAukUPt zvyR}+_*QDM;hHNm?AX9?QVA8T|KiEz(sy-kiXn4R56=D4Fj#%|1uI?;&5a07z1(Ns z0f=a(98ItIR|@{-t^F(g(h}gU4YT{Rx3(L?p&Lc%;?nH0tKR`xxX=Z;srrE5b|O$Q zT__DDR0r0^7x+X|nrSx?ch}dHRMP=b3`g-@9Le)BW-}I;b4d&8y19!91`0rM5=s~IsA@7g8sH9U^M_$sZ`F7rln9l{4{4= zX9_j$ttfD^MNWCI_nZV&EY4(x`m!BmKSSbA-HX%1&Bo>de>zzA z1)r}CZS25&Ug_!;t~YQ{5FBZ*!H`hml@lSJ4W z6}kY|uQouaxq>)KtOzj)@;2#V6Enor94DZ+;ZF0`Y2W=+2#g^rLSCuEjrBZ{rVDtX zls2|z?yc^*qk%`i3x8awk3_sg94nLnKsNgI22jXR@8|h;I$yNErNzQ0S$Qi}GL#_Q z@ROwASxhj*)02L#+DtKgiF*tpDHz=Ggz2bHN_JF6(uSWfMcL1S7&B^T3J)PJ?~lBN zc3rnU8#s0f-QB)a8Gcm+ugs;@Kn`eC z84(WbFB4b$wJzMCugI#T`sGHH@rR7GU6#zV_RBqE!7cT?!)U7H42Tu_DNjlG(e(`p z%Xy&$I}zpyVu@fxL~1SffoWaT#g-?M-VUObBV#X2^G(U6DXHV_-IF%R=F00TtWt%V zN5vW?G=0DSGFCkmHvwyG=~+v}wo(yqkwW(=dv_NL@j(ZNTA&*wgtu__6|&^Zpl-##O`fC) z2oKTt_j{KsmZdM~!#Wms0ZrIn!E;A~XKj_xXI7kkFz9X}yM8Uwo^kV4QkMF`0H5iZ z%M<%ZEKP+3x?kM=8MEJigk~>0)8wlpeiYH8CFn%;1@+Z(S1;VR_&9~Pd~G@lNt*yD z%s-G?|74K)yTRxm>6-q_?j3l{D?}X$i&sR#4*fZXe+JOFL%@!fit#1#v~cj(+t8Ke z!F}~j==U=c`-=PTFf#s&fTD6s%4MAsv3#gT{F7zJ|4&t(YbT?>BExa<9PN9^C~LWf z6zSoZsLgS~*}W$K1?bIzJvDmCU+w3r1FOK=ui3?nmdLNKpfymjydMnBQp9toh+E&M z&UP(_s%ZA~*4ypn5w@7*`s4Y{05h~D=V`w5Wz3f~AnN<#y#B^r@R#$8M|xIMxd6&~ zZ%U2w?dF$k!0l_?mp5#i$<2wwi(8|*cV0GLzT?`l2t;X$<{&~6I;HMyJf0qB>#M%e zQ$0mzYBOWxs<+PAh+@Uk!F|#x<@=gz5Y5OUxCUUxz9R=V-4qKUGQI?$JvX8R0PU$f zIRg|Vz=-<5qv6y1S$NhX)eSkgy$K~=5y3cMu4YiLn0nmhI+iW4pMwW?kg!tCNqdqd zE+$sAx~tq6ws>2D{Tcm|>YltuSJV?YuRo*9hFAvLBhu?ZSc;$_pguX3#_wkh>$2TsPXRGx=&bS;CV33$jRciZ{ijmCb1 zuoNZ)9pQaLCTZ>gd2*H7!!@0co6tW%MZ;OYfgPq^ z)$_sL)SvBhLvk*a3r+V)+vmr!d^SULNXIK#&haw91Hve{z4Nq0Y1k_|{}9y{-_e`z zHPup~@q@vz8h1joZ6uhIXY$!M#-&AUmG9I{R^Xd_*F3GgHjZPLI3qytMF2Za%KIN9 zXV~M|`Lfu(%8;Cj!ua)lL`s6;NW)Av+%8mNHK$Zx-CutB-zgUVcwsrmf`dzS46l;g z<&Ae8DiOa)znbhor*6OhGUneIUpOKo2wOrJLetc}NgwiA%}8(cwkiAaD>Jq|vxip9 z1SD1Mn|I%)&VY8W+6HiUzR(4W`XSh)X(CN3m-`4lRwqJ{n69@77RZ-=!6^CrIMHB@ z6;3N)5{q%~`tlEk8l!i9sregEK?W{#-Z83v6Hu(N`APc+#v2{V!M+~uHxbyrQX^(x zqdh|XE+6AY-@5tuAZ)>%^{AK4{SM{CSHK*XALg4MCd;J)%yPrQYI{dqD+3tXdT{9V zLciea*O-7iw0fa0k{MO5@HA`ptBnAIQxv_X9@ZZWg%N+@BMk+7q?s#X^GB3!)Sl<+ z0dE}oNI#GZdhJ&h8$jRU?!4@)OWakq3tK4t!NBR|YVft9Ufq>?3%*{myln{%bbA@Z z5b)N1I3pxmANnB{s%b8&0UWA}f8~q)`&5w#6N44uxL*koycb&9o0+UeQ0b^?YS;3> zy6LATM!3CDhHnl5nz7qyZ?f0L?sgF2!DZ0|x|n3)n)BzH6|#g(&nNfOhB|!?U6Z-) z?3rSN^UmQ1F=7i-;RrVR1+S7uNIl5GaGgVKKfddN?swsP>++Xa_#aH~T&=%3tfXG# z6~9|{+GEdb^gAi@$q0X#!jUz(Le`TcSs1ZCuUa#Box1E&H5xU7*Iip5foFe~KIjHV ziq4{g)6}KKr3Y)shz77zyOKC|THd9yR@)%B&fO}mc4CtRy5q+~TFvw_#AaYs#J5Mq z&1vz*-{jb2g?O&BwvV-?1^AP$4e>FaNBu!HyO_) zURsCH#tftx^w{#^I`N-dfd!W@*{8`-DgK!-y-#-c%jyP8F2u-kiejm|n{nU%aCurq6~}x zCV;VLJ*)GPdTvO)Hb}%>_;s%_FRx;d3n~4xN(+W-m0Ys4AKfTtcMy?KC)`@co=o`; zbD>7=MD=7}Hv)-=??0)U%6E{c65a~#ku~8 zKnTv==u*YEhbgSH!%e{KTVbuKL|B>PGx3{OURvCJbRYcYmrg_e?=JU94n*N5)F~xx zP^h2GiWReEJeR7Z-g$RTh6v=GH~Z$cpEHRG;o+y2>n9jm7VofjZmqDSZJ;>fny#Ll zB+75N+2$cJ8h!0y1I0)D1{A8DJ*cItWwK-cDH7x!Jwq@^V}4iM!)hYi)z$N~LiYxn z<7%F7ogpx3|IEul2|@_|in%Cl|LYo6FaP}U-pFH5XBhkxukoVZp7nLS&pEsYIIHHtibA&+!FoLPT)M9FRXNVB)HJK?Dz?D)$_7LBMaJCO-> znXxec2Zj~%X*e8LJ%}&yZawJXv+Sz{3j+qO_8GB|&8hqO7lD92q3&(BApgh z{l!UXXc+lDptkjUXVqT~_JE%z5#fSV*zAw~6ArxM1{*>H+*j?yjGHGp>A;Ky01dGXc{o7Nyj`#K9M#cT(_DLp zrbGVka?}5HpO?|>{dzH?JFcjQ>I3<$um!vAOe2=0Vc`-de;wcriCpZn5pVeR$0G2w? z#!uJctr(CcF=Frx>9pJtT(0fD%x|@^)N*tKl~sBHd}=c@WNJwkbp35b;)PvMBc5;x z($ljq|N1wQ8h~)76RJY=G81Nz<^XWMbcT@rx8eEU)q}r1e$wK7k)aM`b0GF!Lf$#8 z62^VBV|OZOufM8}Kt(;NG_1U;+lUwyhyy3?u}43~TliuM8sOf12*J)6wRu~u%m}qfP~*txEjgRlB@3Acuxa&Ac4L52 z?}pp*kkw{Xp8rXufZalF;)LE;g-=Llcks#aN^8LDIr!)|{s?8{s?iQCgl>)*rC)nF z)*Wp7R^%vnJzJjyzY}+TzCR{A0x7V$2kXi1yx;Po-n6|3qc*sd^D*^QPQ0(}MdR^9 zr)T67QPX`x9Sgq0a_io2eMqr1&8Gu9blTVBg&x~SuvEoIdUly!f!&@dU-;CN%z!Qf z$UFJVs}=j!(iB;J(yRRPlKcf_h4XwHJ%)3Gr3CVIqxnPdA z(^fwi@?%K8YW2j_Pm=<~6FNEID{ib&VHsb}(6fnX`-czj=iOvvIP=o*Ntm3a@#Fg; zFGX`Wf#=NrPVw`-*v8@7)WZFziO&^2)l>kqaeCePkAFPW|EcGqksI%`?Zm#&#}r@D z$6jlGOI3%ae{wc3im3)nb9$5pRJgr-HpOihOseR3M_5}4nazBZ01n@|1N(WPwh8o= zvqg`3Y#uBH?NRq;|H5(|b=$I?0<6Ge!?v1YB!K$y@NAo(Ck=t`w;0e* zJ6exv@0!N0iD^!!&=8&9iU)Vk*CGI5?E0{wv^hpOVnR9k=(wWKPo=*;@C^M zo?=dc-Ga@v%}`TDnUdrs$mhor{E2?D^O}2~t|kzdz{aa2N04bQXjW}w;LyMN5$S!7 zajW<)?Pd$DeF2!EuLn`pJ-87_KS{)^J#-1+2pH5u^^K$1XS1dPl(op8O>?qkr_x6C z_0?|6vV}g1wo>bT_nLK9)O6RdK4%rUgo(#5K!CZ<=G2QE37qA|RbuHXta3B1CBs z5h;=0ArKV->C&Y}={-o58tJ_^se#Z-AfY8d62IlX=X`I!bN4>?-23i3e?USAVI^y> zIe&AE@f+j%AT&DR(J)G$)(2)2c&COqJ)5(~(!A5=u|#{C10w&VTUdi}4vn&1n3_~` zak(06^{Kj=EB2KvA4Fvq{|wp+~J zpS|7gZ?5>@brfB=!RBlkk7sdI*%!e~n(KC1uV5HI*gW9Fso6!VF--^GP+5^+UHt%*r=A)wHV&e)P>th z<}WliT34RbDB?7n?vFknajvf9t$D^8?9W#Rxw^mqc7xeqk9l0KWq_Fjuvz1%cgTLG zd}CQ|v;DFXd5(~wFPZy%NdYYR#GuBo%B?n`-&&u?WqI+*%ABl)P>WG<~AVldPb zo>sTi8{?)qWLFxzEG2s9RYhgRb7EBztLZ?FHcaudH$%b=kHH>qdqJ|!qB5(Px+?)O4aAjb&s@cfQ)OE=K5vy}^^)IRxzS}$ zx2lHD1NKm36Ag7-efd)85Zax9hA8U~d=+2AE`6)q`tefYZO36~I@5dKW}l2C3$hVI z_z2&o=y|mc$bh&;waegxt=Dk@U!Ri1@|q3g+RM{ez0pFFF$ZwBzI~;j15TXVcQpj( zY$uY33^oE@gZ0~U6#T8L!VUMMznyq6mJNa z;JsmQe_K)QXl<_8Sj8+RICAYV(6PhAXa_4*u`AYKjxDjdEYHQ0vdZOoFdC8IkZJ6j zzYI;RvFWyK&&Jxmiqgg;!W{7CMvU=hmZ~iG6Bc6j?XEX>Ol)Ni#?(aND~ScHZaRZ# zXYcz<>O)`PUe#(GLT0wP%l6-?j5_G-_d}7<#)C?l_71kU^(_G;;@qJsg}+Xq^&q^c zwVDbjoy>N+eG*6O!9`*3`rIv=>i8q<#crmShaBEbOx*qGqem)3o^@{x3N^Xf5V0IL{Q;dMi{ zvnO6x#q|Pcs>OtRjL4FE_#vQUQ~U6%ehg^*$5ZqB&+g@bDh}wkcxtEGX@|IH_xRCP zxliaev~)Bcp*83;nAVtcWq%!e7WpH}7g%Rs)I6p|IVf zWx1yI{<)r$my~Bmmyus^71#4u`~4n%>o&e1BP626!wU|eJe$ce*uM8^YHaDo8;kJ0 zIa*%tKoypmavx|1EhmwIc2Lt_VHwhPUx48U4SrZ3AN8^3}eEmZ`MX1T~cU854f>qv94)FC2jAvU~3&ND50^-h9b zQXHv=H|T1l7wRs(qt}xPH`kF%11838*Zi+me%d)&qoXDT4wM^>xwPgjJhY_bJG6Im zD!`PySfbGSBZI+uJGOJz=Rp$=Xt-PxEIwl?1^#f*UtKkIGVZlK;D%eJXhc%PTs4`n zv9YtT<1WZOh5K+qkDHE_)z7am-ikXk`i0C3b~>cQD#QsYv=Hz1Rny5WsREhx*|dlf zSP2*Wy+Zt-yDI%pDoKAYFR$z_sQ8UG&%A8YeU743Kya`1x1bJucHwIk zrWifz2*~i|p|sN!^`$Tk!US|MsdtvDmF6i9xF}RQq1v9nCO|AZOk()oV>yodf;Lrq zskXD$n3G(zvLz1ETLiCVrY@5D38L)A1U_N+ ziRO~D5dOJv;W8TR0%%Ut*9M2n_({m`inevi)LfSwv(kPA@CBS~f?*(ZD3g_Wb-1W% zI^)YEd#UlWrMI5v*Z~#X8=2M>lhef3XCp4Cb1Q@J(`AwE_qqL~g(CJ_AMA2LyOt=A z7=Fk_KQV}^cvZ0x-d7_~a8}bz{kB1~8p(jS88`)$8d@F0F2oqCQSQIIs_%R7Ftm_sG9 zH4$+y-D*4~&4UGdqO2Y!Ak9^%rg&smY)5KNNs{Q3H5Yzv(mg=$irO7k7EOJb(T&ul zBC4i_V<}W$OfpBGr>8@Fx?g{^T7gm>uspk3wV{)Qhqq5-IU-5sY`<+~#=6%o7ZYq#hCFho|(Ovl2f? zys}?dFe+N=S@kkzV@mOaPv=Z8$AcTKos5AoIeNtyW&RQ$h{cu{FA>c7jUy8t*UIV_ zy4qh|0cEQ)u^xp<(qS5?*?1WzmW7SVYWGD$qOFVr?<)XaFTS6lE* zwp}!JTus@nSWS9(Dw)eTNxNw{eDB(~ABqQK$u*$r^xzFJS51-)%QcOZK}Q(hEr?4{4s-+&=5Ot_oDi={5jq@niQ( zk&;WRUm57OWh>B_*t70w8c1P8RL_VW-EQWQ=y&EkE~dCJ^e}C;k?)Xcv4)9#4+ib> z`3mSltevoBG3bR(xCiJ#vnG1Pu{RIdn`;!i>E`9JJx#Nyq>YYqXND4EH@sw;ta1(N zT_-%*Y}z1mMbNI1*b=O$N1*RsiHT$%5%=QBRvVk1__Mwz)xb-Y^kgVm5dva`jEdVRF2Javmoii-e&oIfiNl?+)@|m7r6pp zL?74x@w!v6!$CK9Yk5XTf6`glgEPGN-LWAUSnD7Y?~ws? ztDGq?2=4}}g8%K9jlcD%u* z!!kTi+uZ|SkD|a=If(9hhGH2j2PLaD_hYt`RC6gGe-(Z7Eq_{FX${}d)g3H!-j_2{ zX-C~xr6(v1AGD81)q?MrN_)Ofgr;UMd^$Mt3~I0CGdR1dtWpWP)0&JBtBVvzelbE6 z-=#g*9YUS~*z^6-g3-=x_gHs@2To|q&OQC4ujBSucf=UJeX;ZfIT)9Xb(+ivHnto` z4(Q-G$2$Hm0qNOKs!Ob-#t&RngZ;X41_SsC*S$f?9&Q0NegjxrY(mqE5&fBm%o~91 z6z@JX`{=3Tj*Q+uXF!iwcsz9~*ZQ08r`E6oOs6a7pT4_)*n#~0IgHNFE&@RkjmKF& zDtm+nDuJxRxe`+1t`DYvV7ro}+$y^ZX$-gCS#k+|RLPKgTWy9;K7pv{^$bI7$*u$S zIo|lVfc^ZM#~3rl9pJPX;{I$W+l!y$>tYlcYPioOLxRK(K<&)@YKWH#a_di`a*b=s ziz@iee&xx^#L+)aIACrlwxm}NV`gqcpEX+qwSL>ZDI*J}6$%|7{Yt$U`79StqzEkD zpE-}G&MkY34}24a&hF9x=P$sA`!YA+3Dn4JZaX)IkucG}a3r`MW56AmtpdhsVzu|7ITOZ)Cig2YMdtT|uSU;< znxOqNCBia(o^~dAx%)gZXCDiTxkLftlWE(F|0EjqfAx2|&tfiCf6SHTBLE(y;b96= znF}WCnsa2+{oX|-Sl0+E@yW_f>qs?^2%Y>FXhE}r)Ed`0oPJjJLz^1;Og5*!qTABc ztz@u-7V9cX#h&`mz@YwTqLec;8I2*}Vb# z*ZFBsP)p;l!_$a@3Hl6sni^8+pPq@hq4OP*6jy> zGPX;5x1K$|QWCJ>&(D7BSY@jd`MCp3z#6l45fEM#4j`9RYP)*r1N?cCjpS|dnOH-^ zEREjiwh{#!BXdvora0kXHMlK&84JxkxY;a|8fkTj{Yf=&rJht1{Cu=_uXE3fc+BA5 z&Dwmc1JU8WF8$H-INg*tZ^Tii39aPQX@=GSTladtT7$T6O#*c|i*kI?rxKm7S)=AA2MQLdV zMQ7MrxQ?p{;QPy4+&k-)t`G$Bs8Q$!mLIlZzsaY?cxx9)Y@9mo#@Y@Y7@zN*1C1SY z8V#w%k{U-*ug-t%lzgpcuZ9l*_?;uH+Zs-Cwv?46>T*^8~@4+n8P>wxRZ4oD^f&=tN{V*_imeX zWIv=`?Coj=hA~xS*R`bwt6BW6q2Kj^4M$6myztp0`wWL*<|3P+oDW|7b{NIL@f|2yty!0XVrfjBVc-JC6+#pJn$bIm7HJmime+RJ`_exHtFu0p2Cz`HBcn5P{IMl+tJG4#R_!O;dwd&Q*K+<}^Myq5$)0ePH= z9PuvTKP@j~!jPmJQffU}WI!q#RY7bMkaGfMgs3M~u_Ggjy6Qt8RlUr_8y@?9p{GB4 z+umN4kHusy4dF#N8SKV~IzeMAKn0btTH>PHMtKZn>bKIg)DCWT(PDOP1|FWHh!t7R zkBDvV3f@1>Ilw-_{XtLEcYS!L;=K}=JLh+;PYB-B39ITjxPn#uQ%}jzIJ>41E@K>o zaU>~E>x*1eZ1{AHjQWIAI(5yX)rPrnX7j8}f}e~Q`hy>k2OeI{5fw_BxACgjiapps z0KEGiWVkH(B|u2b8D6%%X)X;On}0X(aLIM;oy;-tR+l#uJ^jw5Q&-FV<>8hi*Hg8! zKOD`?4FPycIyr{eAj*RvnQG3&5j_V$-pXFU%Q_~uf~vMh(?56gWC}YkS8FbqpMF?z z@ETae5be8H|72{_hpvHEKo{2200$T!=yJx|m`F<$l^0j9_?rg+v_Eg%Mw_GQd51^i zNZ463-($6^)J5Rc{%cL(e+zj3J0AI`PUrtd7rH{#*3AVnb5kVJO``@JEo$sy|C8!qIv0vUp&G9mhfv#>eXqtPB@ z$x$1!n==+W^a{Msbd@Ty+_CL$Wq3rjkL11q?IwyH)&rdm-w;6E`kw{1T*Z9i3Ikli zN1G0r;IqBKSS}imy9(JF%!1I(B70sg7B#D_3}bVqzx?8>XS9Y8s>Gjkdl6ew*mGpGPK~efpkPUqzL$+$$AeQ(ZQiM$ zJ9$>2h2hpMCMOtwQ$&nP4!onx%66hQZf0zLQLUqYWnqYFLWm2k0nJVEOKl!s)A!s+ zn$J$@a86Nd%#D0M6E?FYl7;p|zJf6O^d7V}F`uL8QIiqsHl^L_7kzaIlefHMPu;vo zDe+Do=HYELJ5w}|mthCN$eT?T4Lqla^g#`I<)K+qCc+g*5>6%D&019v*{0}UzK<>m zrCIm(qrmzJIt#GCE#f4KJg)+nyIayu_L?Vt$Pa4`MC9Pg8X+L3G#i^g*t)dJ0>DT zvG8g5;Y6+G)Xn*=EJw4@v-Ls3nMxb7i?wWfC%jMrFdiR%TJN2~nglk#%@d2!k@Dj2 z1`ebhj&9Icg-|)@^!8Z}nM9qaDyv5&8WRwe-beJT4CTJVmVl$r9uJ@`8Gxk!<6iME ze?HwR5VQqicTZi?s{(w@4IATQ7UcPzX}tdtOv@Bs$khlstEl8*eQ>j2?^e?bR+*`o z8f~0N??qVn8M4z-U>M&=XN1erp>O5pzD0kH^y~zf>FF6mWD2xC_OTPKQBy3~GJ8`X1E&*+)$QAF>B4|&<-^}_%vIzK^w>dG)&CDHoX(_ zk8RBE4wU^sB&*QPGsmqDp(zedgyF5 zznG_l^oPGHwGe&HC$L$v5iZxKbZsRe!q7(R3};Hb*zwoqUAQh_A9#T7QF-1ZR4~1J-^d-Tai%4O)cd z-rCz0veGklgXJo=1pVDTdp4@AQqeTZAAlQELdi~eV`HyR2o1TfOIadmRml(AO>WKt zaDB7iUu>uTzODKn-LfVl^Hw|!HimAd`Hp=$>f@V3IbrV^-pt4`A(Yj~KgaZ*h6hXZ zt{BPW_cA{qmps}&thkjIn8h5VnmNQKtzYgCU%2?t4AiuK(dSi-+o2N<^x@l}s74Ya z<(}(VBt{TMW(53xt+HVcZvq-I$uQ6NKsMc>4=MsJfA}f`MzX$XVy8?_`blRLjqy84 zbyii&rl=4W!u09A+UYIh7J3i6-|oMv)F)zs%SOb>UYc8d#2TTG;dxwFD9Uc0ZtsAd zifLNuvvg3a^d|GXk2aZMby)ABFx_W+y5;K!v3JnK-0Z@BSRS*P36iT|g=P_gep>@A zycO4E5FVSA>=*Lh`=TlR3_O3Zj@#X~l~K~heXgdU1vzEJ+$%NJZ`jvn--qZ?=&dQc z$jR&&^Tr4jw4lKA<-I@tsR@G9yG73m) zFVK#|QFCw-A%)Wi)*H|0{r=C zzV+$AtT77aLRf(T*$Ce1by{7@^x}|?V@R5pF|4F)^vQ$Q1?fKBZb-|0PUz6RU~p4z zdlC}M2)pw}?fZPf9_Ry)OcaiPI(`;?+R6@|zS7uPQhKjS)vRUlOo~I_QLji%_!NzW z);p(`z9$d73XNTDwpNmiF$#Er&1rHGq0y& zj5-|;+zrIjAm-$KRCncui{Y(i2rJBOuy{G{Gk`5kdmQgm7#*bD1A-hO92L9MDM zK5a@CU;;}NRisBuiPzdQsim`F?`)5!{7q78;qZ*N+O?X=S9SrP_bo)dL}8Oo`ptv> zp=&>O$CloW3nVNm2T85=+<&_(P;&?+$EE(*2!`m_MZ3Xb6@Zjj703+pNaeD^8Jw|? zUKLT17~(RPysq>H5lr^cTb5IOFUidYAD^I)2Pi?5{L+xcTk;Vj@YB{8U_X!r&(<&% zyJ(6R86rc4x3L=vOI>7N04?5qzOrXG`HG)+t+Qgb+1Ws~QS{p2`PE3N^;!oKZ*QL? z@&Xx}p>5FLX658GV(Yjmw)NxN^Q%5qhrM0z#z)3`uAWGLbQa#Peg7?)VT)Up#*evZ zleK&^2s!`T7U25^RGJ**XvWyGbn6aT;L6%Ttz`0 z_>Q)bY+^Y_9&L>hZg@46IK)Pp+fNIkCS0&04-L2|j4^d>E(5)E!HFA#e1=l-e2L)|(Bkw_eD+)gO8{92j5;5ER(7m&3}Sb$vgL>}mKuK$l=2^?1l; z>P_Sn{%Q8@W26Vy&z{B`!iv1J$>E2ODRA;iIu6OK*jyK3?#!g`TB4$F+3RxEpSfJ5 zfCyQaC&_=ThMgpUxnIYQxJ__t0G)j5 z&i1|PwVX*zR_2gD>v-jcrlXo*4qwzzqzAg7?N(8q{?iXx7E@NW>&d&rt_D1HMI|F4hn=l!gl+;sQE;4J_c&>^7PSb4{aH2 z9CQ&@1cUj^4N9$A6O#nR8Pm*DhN3owb3lXxv-Bv9Yi0bcw81?f zh{ZL0_a&8niUJm15=H3Y>`wJmAp;A>7qO|83twrSJ9b}|CZT1+UU`oUf$rBW{sh6* z{M#apO)qmEjnA65i;1FgWvrja?B^&!$==P3yv75&Z3@&o4gyMBJ1z%kZAzX=O*oY7 z=41}ui+jJpaas5OhE}Ez_*|X(0ih=1I$eXF%yh7wRU8B7()2EF2kJy-g@%g&D&KuX zGnbj~LVm$g-|o0@S;j&E<&2ZLaQB5Bb6M6`waY*@wws{07O*dE0V*xJ|M{1O+ry!n z5LQ*bs5jS-3_-8vxUV%D*ycWQ;*O;Ipo7wxM7 zveB;=+16V}&bR=MNc~Z>;eJx{ws(vpWKr0^H_(UouxW)LO)WaM-)>T7ma$Ux;`Jat zt%7^+`f(~mmpps`E`|d*xJN#f7f^uS0X@kP!$Iat6;c~#Z3;K#pVoQ>C`5odBsN<4 zXfabO(;R)JNt~QA{jJ0Zz!+mQvz-ce4BBW|kg=8+3N_CDQZOwiU;WF1 zLu;r^Ltdpg3dlh;D=qtAJ|FY$It8*UvarcU>xZ(Dkc4o=%_8snTV`KvP42u#9hfug zACxN&1#LTVP5ZN&)v4TBbw(k-8^`RaVZ&SgEZdi&aYy+ko2tS5`U@tcAY?+=`* z7e%xJ9kqh&A}2wDDkm3Lp5&&cbo13gOWdRpqBG#rO43swbP)k0n|W@gz&_Lezh6225tn9-$yrO#3`^VslGm(smAAUHB$dnaQh8=I+8$5EZ_xaMAD&#H|mQ@hJLp= z5qNM7XvQS#$xyBWmE8roUYvZR-6h9!$xYrY_G$Zv&_IPf3B;$TvKUde=^nN)jq%7u zWWcnG0j9}@UZcx3#4dw7ZB}AqDZEpv9ce{AY@W0ta&iJST^GjJZ#-&T^@10V}Q7JhW-4h)|Xmo#8!g}WzVMy<$fm)vnRF>dlF6t|VH6cfP=SnE((e{{;*_{2sc8)(ZJLi6`7CG$H^BEr zDhi4ZrU(3FNsqR~n3b#@;(oEuKYpRCe==Qa8MQAMJ`y9bByL?!pNgpmyr3IN2PtTm zHNX=M^y>E#G+dEm<%vZAk^=mYnJ_=poRY} zp!JV`|4%{Jf1{lx`Z^g$gEbU**P4Csak_$rqIt*%he{XVby@3;+m%5zlM55{&w$8H zSd?N9d+7F!+cXMzCta7CqHEVsD~`eNxBsMT>jIP(HttK`FOCrs9{|csyx>ndftP5r zoVMYjC&)%nJBPzdbixZ130Ma*ZUG?HkP_nWOZh+Ewqg35Z60r6O2YKPO)8w*>{7l? zGt6ge^NHhQA2K4?c{iQPKFrK~<>J6w7OH<^VC7yqj!hL$;WEs$Hy~-&jSgTaSu>pHuna- znt!<({!5uMa|))o9}2SYg$IFRnV@RT4sgx%v@d4Kh@AiAI#4Ic^I7QUo3aVLenLct zT(}>we(AWt52$7$__PHMH>>3b@o<73~-!QpqxNkPmy`SW4rJi0}0Exsetpb;T z_vz(71<78njtj&W)X!UM-T3T1@*e>{aBXd!Bn!67d8t6mbUd!Y=R8sD{SuIZ&Bp9N zuOH$_=8l(>9scv(5It(fIxZVlD8$(RQ3CAvd_!a$` zlK;jlEE@?a@MI34*rdTHOreKT{lJ{1!=v{1@K2e?ix=XGb1MbMXyG{-H(tNoe_3#| zYaKXSdraT|WSjGQbJ!mr&wO;lzGa}Jp5+LC;CDJV0TfJ#)`#S#@ld3{mG&XvxJO{- zR>w2UW$L`!pPt8DUcGn@GV;xd%eryEsSK+;_34F(m&~@oQZ^iQ0ryU&qW|gz8=38w zJ%c;kNVz!>PAn)vW6d!aT*dp?Ckra^#C_t4Og}quk;|1)@Q12=*Upxh{ovSCqDMFo zKp`w;u;b)+6Gr{X?=(kxF&&P#Got);*YEN{%OZ)4?xkPl>Q}la7F}mbE@#GQRHMwb zP0X?>+Wq*g1n2X{6)%vks6xY?d(-N5g+{W26HtxApQZJyHGyD85ion;bDaaigGGaW1UCkPWevvH& zy#dQnAP25TLsPPjPD>H}YaaXX4A!J8*qvEq*>!DTZqmtmL(wfL0!n{nvH#Agx8(jYJAd!wQy(B5mp)D^TMwtq(MJ*QwAi zGP-^=oEUGpS{`T`;`~JGv(M4Y)LNrE456&n+7DN=RL+t0-T}FzXv2d{S zs5_A`3%&|EMLyF|M_+m<7VujCq-mgl zU4j*O+Nu5E?2#V~>z3$8H`|s?v85(E(_5YxGQDrIgRK}Rt8y8`BTLnX=s4IXU`<~~ z-C|wjktL*8(9_OyU%XiB%Xls8M8l3LAoIv3t*z`pdE`%=RhHI75_&5`Jy~*io^e5a z5m2@d`IMYC!)3Z{w#->7aoy_x)KG0e#ITV)*Y09qm)yNbrku{%X?}t^tt7*5_??yI z6iy-|Kw0fp`_9MM^M@;>A>Xbe3*o(;;w3unMyf64$S%NDExy+uEpjM~I#1E=1CDQl zyZ$dX34g2?|M9-XDo0^rhVqiN^y#B}lOEuELp0XK160%UIHZ{D*p#)X|Nj({|3*Jh^abh{m|a7GHWI^M1f1?R zWQLcyI|R>h=)*RJCT)ne(!hXIye0zwu7Jk24^nMlse}9dGA5R^r7&us7)npP2S>w?|+#G zz++5Q)sV1?J;*m(D)r7+CBZN=-+f#r$w(cJx?qcJ3(*^9ZijRJ)O$H)p^7fXH`g?g z`*xhy1xt{pDNKwWy$$$#b-f;`y-l&3i`NzJ+Oqo`_bHnJPcEL`$;Pn%r28%ds{F7O zNzq;dPOR6`e__?+MB^ngq5^I(4!3smzEoycs7AiofC~?&X)-yvK8){HmVNZ1BB%xe zpRE=X|H?n~`9s>SQWiDhC*4RPZvzi|)iB@_H!Do!F}Knr1CM^#djYNjzehfPh4EKV z^uiU~C8L^<3Ve$)y{fI6@>g~?_m{?jd}{j>?(EjLTZWznb@ai`0y;kr8futwpyiT* z7X$*TR~rDZI9(ComjBcZ_wSX|k>A~xJvKimaj$rOfhS8}k`_co|B7D^Luv1G?8u44 zvAxSMQHU{fHrEfa7SZ70x5GhL-EW(JC7xw;fhUPX0hIL1%^d}*$k2}6IV*!5CEMg% zuE%ctN9wwEv$c_-;Z(y2Njv|m%&$Bh3ZuuX62js`0a`yHA8&V?yWv{X^PhA@R8@ec zo;&0+xj=@DKPVx`rL8(_>17ZO`|(4&2_mgKm=7HOF%Hyt+?s{zuZ$gsjn2Ms7fPsS zK@2q|&9*{c;s#M#MHlt`0AywoOD~c3!DMdOHYF4hmcX9Dep?8R-nxG3NDp4hf@hT%g|^N-@$Cr9DCRmcwqEg4rU2pgZC z)&32a!)YK`i27@@my!>)+|AU;d9xUiR?m#+I0MZb*RRy**+ggUNb>om&tpjuz6twA zgLkqFdV-=OYsdAcq^cG2^>0d$FId6s9(4GyA|6tM0beLXjbjZ;T!YS#3nHgqr`7Zi zGdr-fKKeLUWNZRX> z$JH&u*vQt5o}={@R*9!A&OhHN(PXni+zCCix*5pYW{_FSi#R_(84_z>3 zEojbW4Vdn%*!w!p{yGJpLCgi(74p`AsL9~>?fNvUOBH7p>zSUEM!tVtNO>m_Huo(@ z!D^N&IHQX9B9LGN(R@$+cp|$-#%ioRv+(Ix?Bb8U`WSytN|F7Z_mi%~8;@@69oL-$ zH59mv43JD}d<_Tneu#}t)v1EaDv~p4tacApgzA-_0b4V}OMebj{1Ln` zLI+W7X2VZB^R8%eYqvfn&wDt~ruy>UHVA!hGN`A(Qa3nhDsr{Eh-@8`nKKX^oziaI zlUp;_3Sw0N&9KM2c%ko*E*n0y-v&JnnZ36QAYw2DYb+a$7Xhh@0?3;)r7N!s!kJ}S zlS@e+O7pzSZl2QCcm(sItQCiIULJWBi7&Vpwih7ScGg2aa6esk_q*cIX!j%ef_{ZC&a+$L?O}b~q-uRp&AmhAqvPWE`>bC{77kH6h*?7bC+cyAjx)U{*iZaUb;b+C^ ze#!0L_R+~4%`6N7G3$m<%LPmZvfPSy40!`2=F|t%3E$X-CB0PLXhOEXrm!zcH-KgR zcY5I0Ej;yMC|A(sr|0egzU{sySM#k#r|Cwb3?aVHY$9Y*a!MC1t+b`7J!UH zIDhi^>8sH;=8DZ8l_@59%`(**)+h^_>K#F5{G|k`5+DI7BeTSe=gZ5(w2wZ*UO6Pz zG!wRq2?34X&W$%$N~=qf4$#>@>1@0X!W(&}>>N%^vP@3ML<-$CH|_J)j#*?Xw$Cn* z*}&+{H~Td?WnH%7uLO)9O>&0*>k;v5bm)oMt(Pu8CT*v)gl&BHG0Du-(T3XHyAzvV zq3mIsM^tJNxO2c?ZKCeZ^gY+&hxgopzStfl9AUg|t&<2~gD1PpK)YRtR@#aE(O{@j z=0bZwaE_R0ot;_GQ!+L-VbKS+=vIXZQ&3E|RYl=1Fz;J1_c(3%EK|0Pc*zwlN`g-G z0k6Aj_-3j?B6cH+(g=%HQ@pbyZ!>X^GNcEYwy0f)SLU|6-PAaKdnYq=E&Ds&^CRmb z;9N8KPdW}n1fCl(57-hM)6XGx#<;>3J?@|gJ%;fkgotHF!fQ#lzoXY!p+Z(l0VM3}IL% z4U7FbU-OB9Ql8Z#xiy!+T#rQ$7KN=U_Pk`CZ~3L#ec{ z&S3?Gi3sq>Cd-T%5yx1sTPF^x?~o=-@P-}PQ0+|}TOFV>{u*n4eKa`p9} zbPCXDOHV~0bEiyybayiNqRem0oZKwPG45Wc%_LR8%m~IJ<(p$I8=z4k!@$hG_SL(W z2%;6CZQq@;`SQrinWdGTAvcZgNFT#~m3^#|b^36QXxz5aX503Qlxs!<ArdvPr8Zk}GIUC|lU_HddDj0yn3w0{LZ^K`cG z9CZ?nqE=}B9{fxj_&rM$4PJB47x?7Y%e-iae&Td!P>T6bSdAX$nNxP~0TFw`3-NC! z*5g!Z&)VDtsjy=iMO9pE)Ja{9ib#C*CF;0OrQN_c@nZqK%M4aY{EtyQ2Y_A>wPeaW61Yy%|mfeD2*Gy|bD)q8=_~ zKduImIRV`VAQqos1$s`Zwe7l>F*8Y6qyJDE$}y_qAOWw7%ezQn;H89FC)zgPzTvpk z;&Xen9m2dqdu);BH?2B6aryv?%yJiN^nAs^DHYL5>^yATT>?}|#&?h0rF+hxlopyt zv98H0g|6;0n;Iaw@PNoLRParWM!~H_0BGwUwVe|J1u%da)=IGfDV#-(YG;hwCW`1gH>>%|>fxuy-hgo8@Y0Jf##8K)=3T3jy?gtRnFU%8KvU)>IHV z$>IzyLt5Cy&RfcM4?jc{F?TUSU#2br#6~l0taCQJ)vXxDv0UJh{p>tYAErl6uZm8^ zK8$}FzNe|;1?@wYz}7Pet$Xez)is2$Fi|N*$Vr@sxmR!;;NWca?9);o7gIxB{NRp_ z$RqYayxE(S4Am~5^zDO@WUtFg$~WXpMr`%RoK;^jA6=p7VB+rnvP$dy?T>}ef4={@ zvZ}neB64Hv$-7f;Eh1GIa_M!{W*9Uk^d%Erf7^}8UrPW7ZxIxCi4h zGeq+RV=CGt@Zg3V(pAt~rMwjQB9ZHUmbB_Ikkw7VhRzeSrL;s}Z<{O?*lq2_;eBDm zaVP92opgoSqh?SkPZ^GLldM9!uu?o}^eBc+lxLs$P`kNJ3tU63%3gyIvevhA)}R^9HMXaxg!!##lh2d29f(aJ1~*URhpq0mUqNgs-)6g z^}l-mz-i^}&gCe!&yxy-ucI?Up6I3KhriF!(T$2u{-vzR{Kk)e`Y##iYXoSZt@A|M ztRhmp{laTM)YtX*2SCqIK!zvYWr0k7A++79I_&BlTC_X-a0;jpj9Y-}<}bRfpul)3 z`Oxbo{D5QE;(6M()RHHrX-Z&F+)BG_z4n-Q+xD&ks*_l#U}CEBuJ#%KKD9;4;an#A zj;Fa32PQ<4k{T-gr9U9L+h9X1Mg0!xHTyY%JnffFg)v74Z zb~or@sXQ>+{-A>T%+$JI$?@8|x%An=`sIRz98*w?sSO*6SD6ycP+^kEqfk1>)6Ok9 zocfDk&oTYW(ehWL=$}0PUwOp;8$C182^eeD);Fc|w7rbWlrM=C_=>^4?_M^-9jq39 zIJ!?sMH12Ufm21Swan-lcC1VzGI+=08$t;p_T7XNvawQb_LJ^PhRbfZySM^|epwsf z${U7!v_+lE)=XJ*?s(gcn8$SuK+P2A%7h3|Jwa{zKAA& zwWrs_bXw_r1pL3xQ0@^9)rLt%&t7yaZ%2c8L3?or;Ukr&T(FnO*Yrw9uS&;0YxpWV zM-2q0`TQT|-aD+RHSHcoQBhH1LqJMYKvb#)DFU$^Ku`!pIwS`HY0^PLOH>4u76kzX zA<{%@q)8`IBVB6ffzW$GC?U;nd*+>aXXZCE=gfS+YrgLfu8_h-va|Q|tb5(-UMp_g z38qRONRDGbhi$OQ-3dz5=0xQ^f+mPOACy zDmkHiE$Er4QzR??w#4`OveGEdo(=dh$5Tv;<#T(#wrPwivotpacttWvzz~8NpKo?G zYPawTCT$KJh3LRFV2+PzY=eZ1+dXexnRvgo%aeRZlFJPxyx62^OuLb6 zaiBH@OrKK@JUoaIvzf0zb=E*`v+DwGUVHNSg<$m!P+isBQiqF4_Mw7&pAJ}+<3@A@ z`#|64;=~%QF+T_N#a{Nw!F0dM(y7sk>72vCYSYu0o~n-P4a4VRgRSj_?m^Ik7&cuA zlK-e17R`6Dp_?sqENB}QpnTyk@;c#N|L$sX^Yoz<4y+_)t{KdQI1C$KpIWI5kCvAH z=C}*Ubl$kRskE`L_A$V1N1{Z;nkp9#_Kkyjo(`)S=PYKW5q`1m_;b9!){Y67I)^U{w;Y!^~XP%+m7iH7}wT2I?d&OxDxDC(Be8hb3d zZ4T@0xAshpk9Pa39D3Q}#c@u8aojZyy`U4jmS7=3AyytJudJt+c_L;W9nw6N z`{1H->FkU|e^m%TF$$&r&e7%KnsPfJQ{%EVa{45D*Lq6I1N5XCJ2aan*p#20wI!3I zO{{yx?QY9WP-34U60rIH>VEdofs$7sOtH#y2CKV8)OERC*z$mbweO|~3yG3z&<%kW zSQBUoKE!?$42e9O^t`4Nk_gB|_iQRlMw3zDsTAS(A@_vOyJoZQ{owdgi^ruhB@40k zhhK&`Ib|w%ceWbYC}wN^3gB5U0M!1u6%p>3S{C)O{Plw?iFyCCJ zR=1Rb=C7yd`Yd8Rgfahv}eh zUC0oBQ_VD>>)S?$Mbjyf7yD}~^#Mg%ydxDdt&CK}UazDD=PzAOf^eJ4Nzhu?+*RGx zjF_I10OM|#Y5w|Jt|Y9j4?Bv6gh^1DlHJlS(vMP)nAN}1sNp?vo*81Z>@kRr)_xC+ zj1YULHO2ig$7f&`thv_~fe?aEw)$MS?BH?cuCns2t}%Fn{CuKjNQvr^eTAj)tEe{3 z9Sl_!a>(Si`eW?}d8^RX=zBf8QvrmEcl4ltwh4I(J8mbE#x% zv*7roRoA=pG4t5iLnAmYeb!B^-sz*kFnRI>D-7Ph5zJJYVwYFIS&7v`z7^4_YRoor zrK02l?0wakNZUW>!w|$K1H1AbmoURwV4k{(18a*F1n9Okrb)UveFsHjzGcTvP=Kgk z&8oW;&3$&vb5$c$)kuzgTsQCjUyq>qdHVkz#OP+_EBpLH^IdK$*qN}>ph!(C?05DdAmXJ&`WL5R z)sJaB_qv}E*P{86zxI~aDEYXYThnzdZoV~F>|;n1Iz?Rz8IF)o9!D#H9x?hvQZ1fA zc0U3^&SX?(+_SU0%>XHu zj~L;_BK>3f6wAz8NAN;cqi3h*E>7CW2qT^OvRbo%h`<}b57PpY^iYVYC$vRi4%Yqg zCM3ik6}G_*0hvlCe;UQV6BC_%ys0)GTpHN#6oc>R`M9DL2;HepNI)&JZKs#oVju^{ zw$~-PO9G^Mnxv#m_E#5!t5?R*75V1pv1wVla^aCiF{b1vSGu`f`l+N@9sgf)nIKNx2sK-j|q#sw>D9R5oib zfEgW`niTL!JwblKa`<^0f)^9d=7h=Xo=!!Yn{nUf!i&4f@wxavoA<|ydv{eVaHWp%tdev9mxtZ|vZU$(R*yNvxP6m*miwfM&8 zbsJS7ndKlWGA2_Q!hwi2^H6wED#cUfX=l9>83GP<9s+0~_r22GXAB9)^}E{awolWa zB~WaM(;laM8;FM;X^y8AJVB(ltKjW#_3U2>c889PG@mVtdZ0d^vl|#dix1!YOjEvZ zl&vm%yC9kW_N4K_uD+6dh)LPC%1CaNpyEETo`3L0{y|B<`pdePP1IX2dXLxV-SARg8b$S!-Oaaw zq|CmfP%J1`n}T{O<{Tw+JK$Fyvl~+7z?Y|t?T7Xe+$I6`a-KdgC;_plRC(mJUI_3I zmEhDm;33P!V+lnCfM9W%CDLAL+D8;4NM26_R`K+bKL%ZaR#qP52qNJoIX~D5dAcUL zbrYt_%_MDNj75J(*eh`Y}>Ojx)NjOQgGr2N0$~|LTCk=^u@dq!-ed8NLpf` zNG{Yx-=gFd*P<)CQ44ulvtG;PBGV?lbY!x1#t=ShA)Yd9aZB!XW9m`O&q5}#n}LrN zXk9~w%e4}Vbg<^;Xx7Ev!{9t)xYONHXe-3IpZ+lr&;vq;2o3(6=Q2rUr)JZWoA|-S zqNqy0R}35%Bds?4mpiX*Ufw#(vHR&0j(LtOeb_3ebZTgr`2Haz5}Um)Q0o_g@7pTR ziH4G45q9gq9$JMK`@=^cXd+TDCmr~Zr}|8qU?MxBhu`V(97(B0c~nIc+j;_3vBQW6 zsKtm|9R8SQihhk+N?47HmXMc5w{~iG-JuNIBmU1M8|AM96m3}L@Z#{VmmSNv_8yoL z)>bHA1R60|xI7HRX*BSR)mJM%v<=5@x?M~27ViRwtj){@#PQy~*OxEvd>*@u2{edA z>jebQYx?8hng_DQ&sTl)zwoi(S-5khMyMA5MJzDp!&OnhXF_}V!Lcg+i&v1`3g2i~ zRSHCEfIrXf;-%SKvB<@N=e)DazHw1Gv@p$X6XmELjj>mOoyc${cH9hRn5|0jZOg2G zIPq(_n=9Fm^^s^*jRLJwM6F{3*An_(nC&H+pKqyJcBWfBGSf*Q+6 zZ^#=KX~dml0R2Yi4Uk3utO+eRJCKnh{?s>h9JS9uB_yADtKR7b((CK3;<)Uat4%hTWCqTh;hi1IG3LLFV z|B_(&NwOe-WjfrRq>BWm0Z@l@*vCMvH6N>UNzw1S>>TrMH;kw?ixv>3!C%n>)hg_y zt&1hT!3MxEWf+*RrL!!eVzI>7IP6nFeulY|XddO+;BrGK`02h<=bIxji8Gn`U^JnLMU7fNhMw3hftI+UkMmgAaAj9?#y3nRj239_|a$9*&&0d>O5 zb+)a^E9!jLJ$VI4T*7!K6q}7YC<9Lz_rI1-BJwQwS>*P~K%PO8ix)yVA*UwY)Xrb+ z3Bug!9d;C4eWxVB=6EMT&5u%;OnK@UR^upZi9#$xTl|HT%~=XcF`V@J2|tv%ZeKT-Q*Q!$IcED^c}hYL~_P zU8gI&TJG=g{YG)r7=%{_LT)kplakm}+=SxH#+u(av>o4D4M|%#jj|uY9|w_|;eTR2 z0Qh@iL4!N~VB5E4pkELJ9Pg5!Ns@n2r~Ld~G6aZK^p0}&X)0$3chC8Q;?Rt{y%c`= zF@4LyJn@U&)477_$|W}PZQ@=Hr2cC7gxSdvqsVbn&X5OpWgtVy^m$^OKQfFICE9p& zw)v6vK68ml{N!jrWcXP8`K+kacY9t;?KQPMI)4*;iJ&G}Cx&q)FMsTu)SY<#>K%Yo z!hQlI1kSk0TK>b%Bopg1-zjTnobYug!5;T*^P*%kAQcdDMuN*v*+;k}f1S{ZR8vJ& zPK|;a3Av8LA2GQj5&6nKiB||*uY&e3f(B}&c$_tAUq6l+Q$4jKeBzQ`b{etF@D`xW z`DFn(0#E+o&xL}8Q&(f;jP$g`0AsBf=Q*?pvRmX7c}Xp4(&y)7oJUGhIdQ zsA|aw;kVx#Zl_e|;qns<`&%!o7%OKL)%SX$o^1xmzFRA!heRhhinB94g!4;8WySK2 zo(PD23YVj`ZAF^7qCO)}nW<$5To^1nEO;3h%=@Shde@bzDAH(h!J14YWi<xI^ws2+8Q=iWj-nzrUJx_8Mm6bWAEx1BK;FA zd*P^_@U8m{+)KI)rXP)^M;pdDhbIh3$`U0RoHfETP$%Lm_n!$ zPYvDvfRzBEc9>nsowO_gbcs{zcMA<=^*~(bB(MeL1Zi-FtY;cqs(3=Sc zCGpLaJ+E5jz5?cC>4gO*CX}_XlKk#GqVrqS9*A65RS>Zc<3zG(ti47tRVb^4p8k#Ea65Y}W>|J;ZL7jlA+BSpC{EoGT@A;`@V#~zSnSUDpf_&by1HUM!_b2q73ivCaTOMYWZj$n!x2yJyyV^`SZ zJ*fF}HJ;_NFHer6LS|wG7%Hz@c9Jm+c|UFESSgXvZkY*yUg-LrSQ2Z zVAbL1Pn@ad_1eO6FRa^(+W`CJ+K?nmG8=oF+ho`vl9AD|08PAT1yr{A9lQU&tgUu! z0Bq+n+cDHG)B-dR~2ERkXjfM?;k&)##eKP@d&Ua|b{!wWzV zpC7z_<(Ha}f!DGiCxCRRf`4M}XF2yvHkq(5U|xy?ASUfM5OZ)Vhf;J9Jy>~p{4kyw zEmaGReZ9u_lTaPK{w#baj6_(`pMZqMw52b6U848-9p1xp^8DM!@s>wGMWHH3Jm7l~ z_^r=0JgM1XWmEq9%FAzPsNqqt*#Q}pN`T3t(4|Qck9T#(diNJ<-f!U2h~&HN%-ry5 zn-$xZ-wYqZ35&5^I0&zA?Mdu_CbG zJH4sH> zEKY@QxG)3M85mOXYQuN7SkL;>wyRfvlVMnsXkSj|7%T2M(q&^|w|~`Mw$C(V7;;QS zvnk_T{k~PcR{qV=9~_r{N`6q!G{~Od}?B zqw18{6-p=`&|GR+cHmtyE5)EUXbHV~7*J6MU4z_kPE?bj;9l^I?Q8hQ@oPcIM^oe`@2?zk=jqXx0XMSsf^I<4@hRY7FKx~ZN>zC% z8#aEXe-uhmy%Wv&$su)~KnfHz=+aP=`H({cvkQ32Jzo%G+8U(|1aCyDsfT{tsc>b~ zz)8+fPHma3Dr#T!dFyAFPV6sC+c4tTMLQT1E;*n*Ec$Z+{`HR(Ncw$OM}!SVhZm1X zQAFC61A_a&9x%gCG?2;nRi3O#!31%?^_GUIKjrnoTGagpmkXjr&2qIK4MYWY`qNDB z6OkT=J3ciRB@HG?lh_eI4Xh%(liJ>J? zNa+MJTJDfkZezrTDm(0Kb)^fasdj%{!G@X6OuT37J`KnS`Ul5Dcu)0O-UBkG8P+2_ zu+;CPRFi2AKQ(JbPa&$itAPO})RLgf+Ww+S6&J5{;LEkcrQ)ZoHUktb?JiR0G9}ZC z;v71D^UyQV`t-m1J|GK=s+B<8{;GGp0Jg7E^n&wA5#Nm+&uhVpjUa#g(HB|TJU(JE zR%ZRdb;gbN?|-`43QaRn-Cga4#|c&oPoOTh-(_WIf7Bex9~91C5M9q+RdU;Mt}m!| zp?FPMH742zyI5#;YmJEIH1UBq1_Esv88%sZ{)BuQ_f`-Y6QWYZ0_2+pmcl*Q)uXt< z$Y~+}FF`kWscs65B%;jjlW1z2Tg+lmAHtb4z95j435clFKCJ%WSXp?4Q){PemeBAN z(oON+9~=*89-TKDG&yC9SUc#79j`IxdAD6mA+p<(ei;`R_E@&8Mb#65Isnf(cSCr9 zQAT494i5g^@l|q4doLPp^;;xEXA|ZtMU35=O(WGIxz?m?efFIN6h)PY(fn=Z8~y4Z zqSJqdT7P@I;I0X!ENmmFMH-Kh1G-4=%sI8W4@@0v_;KAgemPp=v+CNf!>f~{zkDJt z`Xdwgl0R9B9T@Sb`)%fLItGDn8W(>IRCuqS$%K3z1%!A9A($G=&opN*U)d2Aoxt8Z zqj4Hi(EbrRsJYtyedm|A%C0cCJAhe}Vr|uh1q}u2&~Yc!@ejl;tKIztnKmK5doHN8 zs@c$uP04^VG|<#{$z)&WP{kloR-_xt?g)nEesu8HjZC^aa{u|%-Y0FCToD~-eb#H^ zFXfd9@HSz-ozL`)Ii_P^{ENvAbQl}lv(+L6fAki0Vl$^cW ztXA-VcBG%9y4YjGbbd*7Q^`0AJXD&gWj#Yq(6?=pNM$cr^PthE8oxe}2>bNeXN)iuM6jR5Vb!Em zHFaUlSuO0aG(dK-A@O(Ji2sm02_XfzmC^$Ag9XlUi7uwQv(#OCtxo>pFluLd1Q}YC z4^251yqI@ysy$I!MWO=@9RFt{nKmu^=({2JlR{M7I8&hWVf63S4iP`n~V+R^;Cz0_+DH zeHuKo$fBFrTirf;`@NH_)KN3l*3s7$G{8^4eRLjn?=K0cQHgw)eg;Jp!Y=N0M{$>m z%3!=QTHUv>H8+<^>FBzr%%!jJiguM8*=7hC1es{`(?Xu#RAx@GfXM~Nw)o0wniqL? zxj{%g4TpRAxxFDY{G`wm)@(R0XUD66 zi4c*MSDuoTmAAzwZDRby2%GlLYK3|mu`7YzZYNlcTP|)A<6Y`=zTMzXwh|)2vDt zrX+6&Gi&ytiqw@$i_l&C)D#}i{j5XSIXi*Z!Kpvft{3-XhoD1Yq(00EmEE5gi*^#n zLk-5~W8+`nVfAIPCibf>LjBoLN>)P-0!lOf+Wg(MH+)E;B*AtZ-8t5^w8mMjof`?b z1P2CUuVN3V4qG&BJ33Wk2kF`X?J?&?zw@VSCq3Tu!)>X~!nDnYr+3j3bw=F9(#rES z@$6H*>$&c(?@@{5Iig}d=o@mm$8k6@if0n-3V2%s!#X|yjlcS}fID3oCB6ybI#{Mg=Ev-`L z`eatvGMNyv1~6qSaK?-~>asItiPnnyn%-K~#*F`n94}$-w;(VhopIsEEVZ_RxO5$p zYZqe0Ftpva>{9457(knVcaA~Qe!)UDJ^aW1ovtZZjlH!^7JkNb1n-*iBGqfN$s(O` zwiLdd*s&wc$2=OO>&X@)w%u;K3aHg9AN``0V+G(`?W}J&v;pdp)ok*I`C&aEyvd`! zf%XKrh>4mKfcuXmjyuj85O(k!P-7vtybbDm!y1kN<;-{G|D%BY`-1jg+~<*O6xrLo z+0mQEikYX*o}L6qx9=>3+Gf4@cBIOlrNiq%z^DMnbkQz$n~&i#VuN?}1mTysQ%Wb4 z9$l4eZnFLUrY4`SMQsV2v*^)ZcW!55MOO6v_iD3r+S41rxj~!do5c6_1%xj+ zxBCEL)Cp2<-U4b(?mQFk)XdZxJ+l_@pYtqaPa%RE6o4@5f}t58jG9JS6kIK5daYSf zI&!`Tz8xH4w7Fqy#z z;|qO+lk?#ITBaA#uKuxuJW!`?BL_w5$9!Vyd{4xup3t)4F`ZMh)zB%>VVZK|qKIg1 zbmx`i9K7rq;n(}j(BD1AYuzdKE1*wK+c*8li-Z?dU_@$j&^Clrvj{qb z>>6HsDI4}uP0GojL#5p2QIXrL=r*zH5Kcz+NGdNi4)M$=W5JF*hw3OX>B4?vj4JGF zIK1~or&GZBnzYhvS@qujmA=&cKu5}2qw_X-tv>&HpYjDO$fCh0MES!rh)@@lgqh&OFsSs_g7_`UCWQ-Eqc?U(XB z^w_@G(f6_D{iaBfxy1bFgpvfeq8h%P*O612+DQ#|S6NXCRpyPfS2Q=rt33j&N{pvSpMeE1kGJskM+v_YwXe6-+YfPVo~xou zItlRdx20sx$*dE|gOvz=i4JM_+iz3RCrs1yUZn534-Eb7RSTCKzO(W-M{XS>gn%Jt zfR!@+R=clU@_LSsBKy+nb$WD=*J7W^NeJg}Rvr>V+n2C6@1rG^WcSn3K*vl0B>C!z zIF$7+2))qTtLlO%3-^}nI_Ts~!hoV)xw1&0%8<%uka8j*C+jUa{J6LAlt0}3y-3U% zm2_V&x(KPfsNH)fMerySfX&lwl`K@Qb!frb@?zj!3iTQQShk|S{}GzzcU}XS-9l;c zOr6@&d6~d*2yr)j0oDeSC;fa-qu0%!8!aKRc+Y<0w?Kz&D<`Xu?770ar@bk{Nx)(H z2b%88Y^@nb0?>8xlyGa&!phV1MXoOGplU8+S?d+-(s4vQU`sI!v}k)v(kU0!Jt5pS zBa;gl##byAk0iNW)*}|ASWIf78V*nth(l*m^+@M|mxSGaE{S zUc!ZG+uOtvOqd}9W5W_itaT1Y1?%{}|B3%pdwI>RvZ3p0jlgcQ01f_|6ZKzJd=yjM z&ndxf)=1C|%EHSE@S9-X6{8vO3GZ!&d`c-7=n>oEXy3jW=!E7H>?CU6ryR=oVF*>x zgAy3-jHtpS;7Uy*M}Y1nzmI9U=RoDTtF))f)?!-dyd>NqlTO}JlBzLao!?iQ9c_y% zkAJMTe#wTpbQ0IwDbi*W{8g{M&g|9&$cu=cr) zq9}5gVZs%#@@-^zc%0Q=T@PRv?;SGs6Ur9O-!h4cyk;KoMcRip-gNHXLAcFr45Vl<5#&=GT+8* z;f+uF04$EliU#?eL^bq%1=?$+@D2JGdn`CqzTYr$3Yuc*9>ser7@s1C*v|7A5}lG z|7^$}hZlU_2rKY^QKBW(z!h&41)6>+<6+%7t0%B-(fwDoCNJka6Q5uXORSE!X^PX;%j z_|=r!6Kc=CpReRR@+~q`RB{l{<9jDapi@<_G;sC0T4p*O6tO8-JnJx4()w>(6^)_x^8bHB|TC`_BIN`MUmUoiv9J5sXYTE@mJ0hCDt!WsM#ewM$hfSWbzIFfwSnbLp9jChidNFX@|>uG5bnWiQ_M$I zM3E}ZR@}?8Np2J1BhE1qxD)WA?LnSxkp`LxxvQsI%RZ%heeyy@Ekm~EJyf_O^E`3= z+9v8{qH4;6-lN#eh1ctvnCxjbC#AsGtr5(}A^}rf^u`Qi0kO44;tu&^NZMrH%9~cm zOgeLICj}EKnV!jd_YzxhF*9KuuTBjp3^LF7!4V-FqcU}e=9o6PlA!;v_RV966u?+| z|7K+Wq0Vh@-rc<=&L^DzG#e_p?98U1ci5EFy{OmJ8>kRx8-%oW8O(}io z@rKJ`(Kn3VL_P!QIXB9#$g+iw5n%xlIsY&BM&69JiY?du4QQ@2V44KyQUTLHS>7vfAFPrl|E7F(mx?GGD(HZY|3O#!a{a12otp(T6FJt+hp;zW?j_ zRzC^xe`&Y+-*m}}W*Rcqh6CG6iscP6T6r@v?T2y?nd*Jh|>+GqiwrH zC>8JpQ=bjgiqS+fIjmXO*z|jTL0QzTvjOj3Uba~{x7NT*4MAlHslLMtK1~gesC;k8 z7{I+`+fqbKqIKoenGw)-){7jYww%gH#uh&zwr-tLmnLtuoxiqs);)c+pRrc9aQ&v6rZspm!fd` zp-Ypd;_0~$csEQF#aPBD*RYLTJ8(5QW9LoKl2!A?u6G&zt0Zjd2155}U318(chRy# z+BwxGqH*Z~7j(uvKlYZsNiHp zD;A5!g};jV-iFBOKe=r5R8e3@_p&b1W>*vKozaKFa=6{W;airix?7b7#+LaREB4af z_Wci41Vf`Pu5pHMm7ZTxTvyD6b<~Yf#m39@d+!HES-Cwac}(GoDv>_CPiJ%a2*9zp z?)5a<1T9BQEU4&HLfiCwItrc&j(-bq1B=~Wswm#rSF^Dgb7WV zw9GMGZUa3J$ElENO$e(d5Xw6R}7_I5PtWCmZKEM`ILz5Mo%rAZee9c8q z#QmHgwfVy+`(GjOzkW{g6~!%@DLoMZDW!$)NVgrzxILQ)-9F-ptl{#MoEd|XaE)Ez zgdzv{p^Y7HhSZ8*A4xB(IyPvq#y!h7RaFw-?$yfg`;D~#@DeDpntku|d+~_orhctk zG2@;+l5>RVpaWCb2pA9f*j4jn!m#Yu*5R9B2_wF?BFmbe<*Cmr*P6l6MKuLs2f72* z8gu0y-U;6Z$tY+C8SPWm^xwejW_JQvfJ-^F9{v2qJ!_ZVvyx5MJwY93x*mU39jHZz z^5>K8oK}xk{Ay&xaq%~^qw20tQdqu;(kx zy-RalDrN~R+&2jyMpQMXoJjUwJ7G~x-Y^3Z@i{n6rf$$uzjw0Ry@3gaMv`(X*ElQ^ zXQUFo_I0)|x7H{leqp{doWC5ZgR!s31wP(K@4u)o|E$9N^DQqr$C<7XnN%v6@nY)C zl>~^o03c{?+HOp0TR`F`llH}E%y(ucEgnU^gM|2%w~v5sYqi1JOtyvk3%w^ZQnK>f zr1Ug;+LunriobmVIJ}n&!$}$;S*y`)3O(pm_jlVitX%~UW%tssjh@n7FR}M7ZSL2d z1^;4s5ztae*7m3fOtJ)>>s-$P2|yXR>-Hm`nH&Y+yeVfO-c#r`;KR8_mD?)K3FMCR z4PfC@SY;%x2wKT)>xY0a`R804WoLxVi7$0?gdFm2dvLCQ)_F)dPT-fWS~Z&;bf&)# zZ>Cge0+59`DV`8i%&D)|#e zUHYd7?9T@dxaF^8huD)2t1i1XgYJ9u3l@U=d;ynMK7y=@L^dvjdE;?i)wU~g@%Z;( zRx=AU1?#m;h^Ut3dMWj|;Mn?+dr-jY0AoY<*~Ic)`P$L)z#aHVX!gA-NH4wY zgCXzhE0^C<{bg<2&iM9*bvWQRZg?5xxUla2?Hg@-#$x9n*#kCftqpHaWRxmiTzC<@ zn#h8}0bn5yp%rF z#9G)!5ie?PVsCV(ua^Yy<0|&t-8s)YF}d09RNH-bQ}M#mi-feRpZ*a%`@M0n-+lhm z><|b&Y~8l$@%O-6obAjr`#7YG+B+ z6WS@~u!nF9(?5X|pL%oxOEH@ce(>P2H0I}GW|7rzdY+WVGg{az_>J;-#^#r7IrPvVOCn2 z_55zUu}aD3Pt(EuZ#+Sw!6ED@vPq*8!jAPiIxdY^KHgG8VpuI!uU4k-VDPesFOo1@ zox2rcU`*o`>5Qt95~OjEfPKSB7xBVV2RjQk)5d{Ciu0`Ys71jf_{tf^O*2|R z!|)sb$MJ=S)rME~-`G7-iClbVx%$9ppT?@PeY9+S;xl#^M5Kp1cYae+Rb+a247z{E zw(K3ptB{tRHwu!mq5K^|(oUO{ibF-MD=gRhO7G2mgLpSeN4oP@1Dg)1fjJv5b+|7` z2|2H4pUbPPat;vBd0bkV!kaG;U5Ipr47{5mvbU(1f!eZ?gTz9Yohn9Kf$VEQK&6gh zC1RO3S#eAY5{Azbku~`!-X9;jxnsU6&_lXv8b~sG^UP0At9kUj`;D{3YO0I=vQKNl zH0KGfP`C8H)smsZ1G!Q{!JdsIl}Kv5iq9?+RS&Z%L>PC{-CbdI&_t&Ud$F=-&s?Y| zNnDk^b6F}vM6hY*X!|9_dC$7u_h-j@-wf+dv+dmcmuySbuB+Ss`hxq4&`*u^mf@B) z?XCnc_{NbpoCkxI6`Uxq++&@t2k|)yl;FppRY!-b`L=9WZ&x3=x**RoHA*h&95s6+ zB@Vv)dFJ6e=q<(bS?||9o`B}HL^^y_D5 z(FXXZ@XIv9R&+_US1MDv#05sbU1)D>BQn)28X33_)(!4GTg_~cPYprKJ6aSivW~9U zR;xy~OSFW9tW*ujniMg+(l)z}IMkl{90Y|`N4E|^qBWYKY0-H>9D4|DYT`5&NtPE5 zKFmDVYZv2qd2gF0khyd6&dz=CiW*{ZuhDn*0mK~XFdcy=)n;AYKbl`VVL$9Q%&~I@ z{_BBF4l3Lb;am?BCWpM}t-fv}{NB>_;^kGquPEMTRR{5Ykm=UI$U*H~|G^>KPOrU} zevy{{GOrTwV#l$n){&Z>BF9+CfY((Q?GEz7;xV{Y`|Z-AJEpMTRzt(^uLEU;Qr!?EYv4Rz!d~pJ6@fWY0lflEdot~{($SL* zAUos_4h`lK;Zwn($7Y&GaEQ|Rfu&h5Lc^`BMzm;;+F47p4j?J3>TxKLly%}6ga}>4 z#rbFE_m?hndpZ6L#IjZ5TF*IE8=SfHYDf9a?t4K5A!U{zcCx3sV5xpwg8Y01HJJ?r zd*z-Mc!VlR7F<-Ko4i}`KtM^djyy{wSZ;PlhjBvFnkGfHAev5&CLy&h4j zkKmgpKD*HEz{DKn$*1HyOzn$J7D01|3KyyjEW5~z z&IS`&$Rz8ExBDHphu{W2NsRBp&cpKFeA-%5*2CAkib~z4;BRc$l?oDU&K(n<48-w< zVcj7Wbm=`vv|AF!4v?>R)jYnzA*Z-IYf%wM=~&}cGI3z%!Rkw)B<;2$V3w)11Q&V| z03QwnSMycFmS4p0V;(~;u_Sw>yhjdSmOWcPb{hH%e^=ioB+4qSMoPr&Rv0Dy{F8cU)vPMPi<@*T!#zN9*}yb*vIm@E_EFsUd*yYPjUX>xFt-d6S{23)P_Dp z>%ku!?NtTrTsoCXIWeXb;1Eby^zY|wr9m6F*kYflig!PK7Ds>o!GQ<>_h$MStxQsm z{stPA6FxexO7S#TY#c$bJBr9!r+9ZsKz#?Bw108KJbYJIsFeI=O5t@|K)4` z;u@;;7kh;#DxLoWY(YQ%o3>5SOj&?PLz$pfgVHx%8vi8Hn0tXopp8&g*B4}DE?mCx zRDV5|j=-G@n%lc@8!Surl5I-=ccl6M19N|ZWX@S|1iT3Uge|TkQ z!o4Ev_pauzH)6(7WMLiT>sN@nM7yhR?BxyK`$H{cB`PLT)OwKK~aAKy=(~syg9vHm*)>~A@ z7v(R4!?$OR+$qZ9x>akyRWcGt> z#zi-jeK8Q3MyoX`drgOMBdp@=E=QU5#A)FjwW#9rC3jcd+P4xV+cwt1mG4h$W{CVJ!9u_`Ko41_v&swROE~SY#14UE0IJ3gm6XcYF^sSTUpCJ$Q~?{5!{W6wo*M=n-x5a z0FemI5pOr)f@5D^XV?dNTz&%#iGMWS5ynMzdW_{RVD|>flhIE;97r`ommCeNNB~`@ z&lG;$(&H-iEip+=n7-<8cNpi70^}lXg`_zZcz9F8phn+?8skGR$P#`eWV@4|QI#J1UBy1#dGbLNyUW|Z;S7*)AKQ)N3ChjK zN>O}+Ra8V>G$h|{WLHMM*O(jf4`#1TJHPBF(f`}cCYa!& zNud(qY3g}8=D7N(1YfqM$oP3mR=8=?B;&U8t||W?9A<(XNPhX$tia1uTL%0E)|_NK z6L&yKZFLm$Ey#I*m-ob3j+|-^MGnJUQ(OJmxhAbXWI#}pCPz|@N&62DP_V>-n@0%K{SphQ=%_gB*Iv}m3CqAIqQ1DuebtpA`ec-LRQ4yHhn zH}AUN<8xoAKyylPAGot7rn;9DSC*7|)00cC^U8+ZX?8i5?}cN7y>#yvzFS!Hh`nm_5b1Dc2tj+;Nk%Qj<&Uu{J zHHEy&0z?HH7OuqdF6Kc)Ob_rMoy~u6+@U2~gPGKI+zr@IgL91e;7gQ0(Nj^*zcc+e zfd9Xdx_`pDe>aU_*QIDS9}>_6QM>?#Xa&d}te5_&3SypOt>H1Jx&X5n z5YwL`Ia@sD!EXc{z3+_9qrH3I-eo7VA2E&rkStT}(7*fnpUuv4-}RFzu+%)EZT5D9 z!{p`gZ6C_<#wcG;fvat|pVX+q+SpVdx0^I0qJT3WOswCA9RI@iL!fp;y5bUM%P@PJ zesJ^fam~{2CG#aq`t^s3eIKiuvQP=UR3p?#E<>JqUKLf%@Rz}n@ktP3-wga9u_N)t z%TrPwpN#Z4H~|}!y~;l|O~1*GoBIM)(-wgNUI#P0BzUSBi2bY$1ua>gOeKHmNb2m7 z6&b>xfzNUnCOE_$WoMGfUNIXf zDTU8QqjK(tk>}R^-)s<%&6|JO8#V1ZM>{b5gJZkx*MS+o_)IcRqoQr0SL@-}Qx*xS zi5d6|DAH@sBHWUdr^mnI>ID&a1{&xnJ?Um;hG()V8cWqaOa<_OQv>Z4F7XG4=&%D8 zTuMvwag-RUzWK34SNY9e3pNc!DVWotpu^Zf-hk*sZFY625DXtv)RE52iBwHG^RZC_$J;lWPY|h3__+bPwI^RKUFZwj8eZ zQ0?of@Ho-^6*@zr=2s;QoRSs4j02e+&&u5dfVlO9Co9!s$PKCG%kkYzDz2OB=IWrx zCN;i>f^SYy!MPn~O7x0HLiSC3a@Dp&^OUbqCnm*Aw=CuTwYf%vtxjKV`45)FVkC+n))b zaFcM&7TH(PyN1+aGwmP6O7bcKJA0XsP4r_4)mo=b@Gf?j2p_o{txq{~YBo*n(H%&4 zcg-u{n#r9bIA8;c3X6JOYzlinL<7uAsVHE`gT9f@VU$DUZumZDROq=COC9o;j<#%w zate?LY5VZWUP5&dxtgEt?9!kDmFkwq$orM z1*y`cCn5p@LPQ0mMnt4UM0yK}ibxTNfbRNMPF;4>NGP(Otf4ek#Hi??G#-5mI$ml5!6%0hd*i)MKf#y_+iZEbqalYy=b3jEegmT?ar3c@#psXw7cr$;W0RT?9Ke-T2e`5e$$=*a1#~S`rvSke z&v$*4elwmXyvIAD09?9X&_e9v8ANvB74ojn#w${y9hgnbzTH0zKX`LdVa)n-ktWV5_4F?g<@ejH3q7E(wX3{tUHD8 zcA;vp-KUO1A$i(@jxM(xXT59N_MG=P+D;JmGONJjXY}1lV?Ug6v6Sdyb+(iP(QvjU zWU7!kpOqJsb71EdE+$^>8~Hgu>(K6K@x>mN0fgDWr_6`P@B96K z>3CMr!48o4!@hC~yjKR$+h;9XYy$&IcSlzv*>C${!2HmI#rt^(Q;?0O^Fca}UcP(I z2kjI}c5>Q5pScs$`tBE?Rhcx#g&Vk-X%Um>ZyWgn5MHDs?+lfwPHQtOF_B|4LvYK? z+E+ol8|cBd;y?vtkmK^#n;{-4NH178kpQ6rS+)S5`4WJs^n!0Jokw*+WVY%L(TLB> zT!rg$mpK>#5z`-J(!Yf_{-uxm->}F3@}3a;Z76M#rg!~6Q%&eL0jb*`XeH!#@4v_2 z5z9l)Cb?;movcNYl|8b@M4$V}o>oxw%imc-8EsK59{H&CVx{5X{y78>J50kccehG&}p7N@1l~c$KZUApsU>CQo{>p^;@D z3;RnLZv*Dz-tCcnK%?>gShnZ(Wqc4qgxoN_9{6Tb*}~o-&36AmqUlb8dz`4qXzBF0 zj;!>u@Sk^{6!@jb=f2@yPfDzHEm8_28K?0Byr7o{*X@^Ux>6L69H@}v?o?i#u!G zNZF_2j%#Wm>ko_cp0b6npWJ=%L;Y(LG8EYe;g%BfAMr9=kg)^DA<P4}FNv`1XU5nsYw?VMeg z1{1ovmjse=>JX;?au@xhJ8VkPjeuU!63aJ~*>~yw-tt7H&OU1a0v_mx$9ClTq_<^` zU;Z#{P*t&zvb@g(Z%1&Zn7V&@65cd2*;%!DJ~3z}3DCrJdr^fNItrZZ%&j3vQ!i00 zCFHWH{zw|*~dy%&6~Vxx_ZGN!>9hPue4_3kEIli zyMp4tc~@%x_g&QKGJSowo;{g-zQu(l4&)&Lnh^o?s~TmD(*DR>*LF+%B0i3uVxd(BFwKOW_K8+XCc(;lrT zon?;f+p%FLw%>{P%F+8Y&)wY}Yy?)#5i zUw3t>R3|5uRg_f*X~P9OI2V2ZDoj;vvwEBCl!9A;&G_5DUxG+zSbV%4Yjuk2XnXq` zI&KaAuU~DLzsW~tWLWPw+H&Q#yGC{gRfpxP0<>EU!tFp6NQ!goQ@qN7mpbeCalnD&e;- zGmsA%zE*^gBeFKq#Be;<4;_bkHGFm~-)yq<3qgdq06NB7(zv!a_cSvd+2H#i<|T18 zuzp3HuVb@=|De-@a)NHR=(!I%$wxXR+d-*k|e9$1jT)YQU@;+ojuj%8iS z4mz1~)|8c_?}3PDZ^P3=TrlwmpbphBgby8!U$%;meIwt@I`e8fQP(`<|l%J9SEc? zYoUQK7~X=b++W%3bxR6fE}L9*x5u$8>I%R_jz=lbR5E4)H|-{Y9Ev`9?>Or7M-T)1 zSyP@+VwZYRV`W^)R!Tf54D#a-0&)~JBLJIzF(L}^H{38T0zxSGDFTb*Kq{`E!^|YW znvR2>8IstUP}}91CmWEu1`}+En@c3%+p8? zeDc@R3{!%h4nL?Vb4?u`JHy^T;Pf52hOmuW&X}_cu~$yi59kBSy2zzDVAFb35nW%F znOsx(#9T))U*Amq)s^I2wr2pcfA=pXQiZoyy}XS7g_?GxUbAd0_!4QQVVP{8t7-vb zK3(uDGtWOuM?ycWQc*6q+G2`b?DeEwpK>dQ@LMnJ6Yvb$$rLDoDE2AKqvqo~aKM;Y zI8_OHAku@wl(^or@-g!!F#E;oXIIWZn}U1hXF*jKYc;hg8`9HM6&7Fo>Ae&RcFT%6 zKTFF<=a9U$AZ6fRM*y*rMJ)^Q)9|VX((Ew#l;& zVAIRki>s54EH6QRkP0ae7M|=UUIhfNyQVb;+w(1cSpr%^{d?fwbVQvU0AKj3^iSD0 z$$#q~MBiM^0<@HXNIlzq^J(J_fd4`lj_!`#F(LuDF2R_jBeM{74+(zZh1wF_F(SI7 z#xov8ZM3HNi1kXKU)KLkuSpSJ2f>j#OPu7;$+3ZhDi>)NODH34Xyjfbs0zkvEpaK$EQHuv!s(Z9R=d4A zdCA2q;mkCD;I{GYn^N+KIz!L*GcVQqq^B@v*ZIgDq@{zI8!^XPr%jo@FUDFn7DP9V zR=p1GzJ1C1%G6A)JU&xp2F65j?LoK^cQwkYisPV$#e1n0pW0M-Z=U|)=t%GM{z!{0 z`GM(;Z@o^iqiC7PDo8}={+g+OQ08+sIpdL^$gVDJe7Fs+vF1Q_A<~n-4svRADB{sEq~`N+_1B`j#lig zFnEr=c6|o`3RoX_fbzF=0XG2@_#aL!f1ZLQG|uzcSU$^q8_EBcZb=(l{i!9E+C=Sj z*HUW_`&su=Xe==RGk~MIG(^v&_@yo>!Boe0ZZ#S_nQ3p23lK$KBY!czV<=Sxju|6BIe<{x>RNEu;(U%vw*PU8K!IzdQoj=Yu#D=P^a72$T zR=7j_*_bJOiAuzIt`5vdl389`B4jxgf%L%IBv<==zRN_mDTnX_+3Uem=Lh5CQM{c} zlL3`%6X*B%3Z2G3Zc*?+en^$l-3DEBM?rbWw70I0#d1hQc$Pb~VL#7ktyKmyqg+t5 z9MO#8nid1ISD*JzQSRsBWM2!A1v-b(yc=n&lBXdT^i*eo6-=yLuHfAGO|go^DpmKg z9lu5tBgyR)?wwcYT#)A)EE@Ga+d_w&mezjHGp#xj-Cal{0k8#x*8u7-0E^6>I?ymC z4LP*moaozy#Vkqbn_+Tofp!z+`n_U7w;0nactc1_WMgqr!VZaxinO0m8d;lUPoLm_~_ zc^>=?Kq-ufq`hq}iJgbLODJI%6u4#Z#TY1{>G6J(T2_y7r;%6`Dr&;Z4_zxqhSY&A zBdReYBgrqk6Hi>yt>Fv*Tsvi1lik4Eixfw=hQ5|IL=_<9e@SF9UcT;i0j)3x4r;Ma z;uadNrYADggU@ZOm#A_Lrk8_X{8an`SyBBlGf?OiWKe}?*fA60%#%0CrvXUWDj?zC z0iCnlv#N@CJP#}}ke9fv=&fzf{Y29#=m#*sjpy6)Y-`Lk30keYFQ0ee+S`P^jl9lHN4H-d5XPe6b1?r)X{+_`nm{JO- zaWQ>lVKwb_LfBJ5 zba#IhknM*W89^Jk<&W|YTESbHuNw%&>_XgW5etK^w>=TpCIH@&I7J{yeevmmqATD> z0>pk;?yl6{bHry=&BDACLzs`cqs<~-Q*;pzU4|3Zl-`1_(Kz=FzAo~d?{+rLwRyz_ zII%?*BGxevq4a=*TCsr{>y3sUM620h@JA#N{ITjb4iw4%BqLZwsha&^NliOkSm)Ny z@8{IZrDrR<8hkF`M!@XxqdICm?gQrNp8HxI^X7=QAG(dIX`QYq8wi>CU2=-)%fS4&YdA@Mu%PhQC*Yi=C;fl`~ z*EZ38|Ed4xqln*h(n}$gvi?sDK7mx(0Q&Q-ZYfuBQV06)%x&PO1YVC6f5rVP(`KPC%PB~pX*0T@NUGYNd_2C2D z{qENgb#fAUyZ!brm2yLT-CR^?t*Z;D)7#$chDG>Sy#2y)f@2bindAKjXj+Y|L@*stzU_XqZmlwtON9pH9s zcZ@c=0!v4?vK8{>0-s}ivLFW{o=m|`I~~`4uFFX@Tmoh3Vg{=(GgJg)p*SImw5))Q zQK~m*8ZhktDo$C&fj`1t7&oSG|KnxY+|o!VtI}BZ1vua}ZIB3uuqZ0+XvJyihq;Bx zsJ?h0N;nB}_X#>MxF`wI3_^ME#RS_D-|r>_VL$W`7&T$*Qd)Z_AcHl?YRT#K0B5_4 zgI?NdkI#l{a@_7U;GlbfM%nI+dijec8?L4rTD%TQJ%?g3vtrawCw~6$A`k1bX(ehX zd%)48qyb!~efsWy86^5g0McJS_fO!;f0JPr_7u5;DAVwpjx8sW@YGye|HucAhw}Fs zuD&=1`W~WQ<5j}e5meWQ)$aY47c&_-=aL^0fl$o7PBqNSq-2p88ekX65-K)Xi|36S zKpMQ--JvVX8~E#1868gIf%W5Q5nb1$+E~d3%ZWKOvj`9VUGvX0P53NsSVKIG{1LjY z{Tgx|$kS^VALG{H`1#cRi7V#zG911M@&1X>&V4L`4a!z^dNgaKz~8<)JTeIhoiRI2 zjdekBP8!=Hh5Mp(3Icrm60h#OhYaa+nuN@6W4lGpsPs}~(u@}>70=k)*e0>Ck5+8+ zSF9Ut8BD&|V?2Ao4ywOj14K#ik|u5tC}uVagN1=3LiPsZd$>c{$SO$i@2^CEZtp#j zR?@`ZFNk_rZC7wt!dqj7p+fO=OoytR#_-kKVO4UIoa6*Wg$$NcCw8XT{5?G@cDQSx zGf!*jh;2jlF5~wvR#$PFj(t&^=Z7?oQ*m7L2$}S8cf4s-V=O?zPQE*I58@ngkO>(! z%jl2D_8t=$PbHF^mrM_&4 zG-$*!0^L4~%sVwWJU#ic#-2fO4-i%ZNX&xGx#29JvWro5=gCntChoVE2nFkl zXEfE>T)*V~*6@v^H#>iCb+|D#6#@Nr&lz>{>6I!ZxG%rRV&Iw_{n9XKC2%gc>5270 zd31SO2^OWY=Zj+krliYUmUjF2)a@uLEq@5^_*3*Zz_(n`bN8G$#}nH{7?9 z@QVtAw(k!;-*{C-zSuZu3L_FIQ6rS9r+f3jdQ}t|p7FD?1uY6GEn!d?IcNOitcOCt zUaH*o_w5t4U&_kLir*koS9sZt8Sw;J)w)1C=v8M&f02RKtzoPSjyM zO7yo7(QV7CEWbs0P6E`l*ZIX{mMI@U=V=`i>IFxX;6@6TJm2K^GWhkY)wtm0 z4bnOd+kv zfx7?%l4pPY0QB*dk>RDcooUfj7E~5RFcrx}atkmqaSz+7<8eHf(CE$bCYwS9Vn(Do zAX=Y(^sV+DTQ7cw$y!2j)!c2(FgCGN7rUN{n)2(PRf22MjCsR*6#;f92;O8r-;Uep zwU3`4at6K4D-0AGPWqUksaQ-1+fcCS`%}!w>;Fy6$dQia+6#bO^23B`A>!GCc-j5L znW4GrjxE3s#+`8l&T#NLp6Nbap#?Q{DPzoG2|gxxDd674jm~jieGBqgd}zqen@^B~ zVv+DwF?>ZUjDZtunX-mv#@F(7WiGbD)71vUen1eztvo-}v3W@!=D-#|D9% zpX{A4ZX`qK&ROD-igHPj;V%qKgimMe|ujMgLHslUY^66nGD$S^I`2p4vcmN zQsxU-64X63*G5rBAh-U{9U|4Aq?jz6<<4dt1LZ0Uhc;a55IT16cyuBieV8`V%^jvs zUO&)>Ctf2#-&4H!8?Z+gb_<7W-gkBiWv!={J;zGrir%U!A7N6ksPTCEN-|--<7bos zDiUvXUC;#YR;a$R{toeUWV^_4B6O$CAEUvb;WD@`DH{HrRk{{s$hP9;YJ&Ik_ zyoQAO@cOE*_vw>S4+|>yETWs~PEUM2>qfvm71|d5#QMlNUa;z?l2^8=v~D5HbpQJ{UyA%yt$&PG6N>`Aw((tJ6dul;EVUAri2%E>d#l z>H4cNjk76^`M`|>GAc6TPPLVppc}-f4g`3Eog$FmdFZhl<}_$oN~(XMT3y83D?UII zTUFmMT99O`*=Hm@{G0AGaR_Z)(vy4G6swU;1@MCZ5>4@sj%O56b~~8U<5QN&!&fLA zR$DiszOzGYh`EV6Mj|8(`OIZxbS~9)bTw9WHBZ9wqblf81}OIp=yaajqD|*%iI)Leek?+dFs?SK(d)c5snpS) zefIvT(=rO5Q-tquDux|*)|-M9tNS9vXC@g`rZAi~i{EUxf|50I(}d4MuY5Eez0Y^z z%1r<1nRanoUrxO!mCLG@I!yLSn;3tbE$)5d)oPnOFt4@HNl2Byt?R)PR~i_al?y#Z z22ufOih*DdadLhor^$(|N<$r=hFj#4dP|)g}b< z!M%|#()><3(O_jXvrEd1r7tJWWbk?5-S_Lqt1~f|Kc5BmfbZrr*-{P+knK1oiX<`Y zfM8XxeUbSjIs3aquuku~Ht3~m2!1|-Z+Lg(?Gz?XcAoPD@d>ZylhL@xk>5szR#C7Y zl^6Oi8%M;^N+8a;qF-xE0yl=snj}6xUa{>!v>aSRXoVBXzOOTq>!<7zX}z3jy5091 zUcL452prnMW(aMcWpmU2@^W{1sTdWowPow1dK;*BT)6(%<<37UkN%S|5cU^A1D!|0 zpWXuc{qHj_qi1hK&ywBr!VgM|Fh3<>GPIvrXr|>bl;@K89)M8bu}O%RG?>r!Fr>=d z86^-~&AMaoz+J^4`~Xj;BtwC;ixzmSIhD_Q?s2+uu=gx<)9R48=6&;Dvb3f9gPq*4 zT{Vj3asQ~q{NUA70E)Rs>=G-vM{#FE4%iy+j(*I z;7jO+SnGiA@T~m4TiYus!>Il3&FEo8OZ#sPQ)s}$WM^_yaj9z*IxG?ike!?_Uc5bG z8LxlarjWzH7QN)%^;mx)x%Q*Du7(I&nePvS2$lcao{Rr-EYY5af+C_nRJSo+{aBJE zs`kTpSG?@NaYJ^?B(a69CAg)hpUl8xXYC(NO~A zUYq{>ta46xZH4U#Q)>8kwoQXzfH%1++H8?RJ~6Z`v*s$?1Qc2BM=l_GFYiC|WHn(d z`v4Y0yiQb7Z;BF0v3~LK{;=i^1&*oCr~3*Rz+Ga|{un}(h*0-%3)?sCt|+F}swWf!5i_6B-!XdYFdb_iIwI<0@#IP_zvg>c<4bJ!eE{atyrjsk}(*iNT@aggMX&zrk8%uORhCVT48JfzJL{?KD0^mUzB5C~VLZxLDrB#RA0PRC= zfZv?ZK!b(#pg|g6=Qo#Wi0@b;pnXeu_#a4$yrVT;ayb>&0_N$J;f3zR_z_h$FCSnk zA&U6ZG+|OyAV{`ONxS>-*9ou37ZG3>1a68WAXUpkMrc*nrzi1YV5Bg}Ftqx)%6b;Y5 zpJRnde3493&;kLi88sVSrX z+;$)2=ZSfTl%;i{I1#2Zs1LPVpIVS?q}-MfY;jXnNblOutvBs)WJ{%6k}W0%A1Ov? zfCKRf7_O-IwY+3>M%}bmRj&Ti94T4R^BYe^2-@q4oBTfwJD&&!(aFhSt030)!=p1@ z?`dL7kjpqL#@9``6s^nfZ0pLNm>kO1Ovi_o-80*YAx{0zm>8z5zGDK|A*@|3%p>$h z1p^3eyVrxUmLZWLrCbQHwg`#f)vHPePOTkCr$CrqCN<@gjnV$5l5p|p{LtPAt}=YC zWOb8P-IYNxy}aoTH44NBB>tRzOr2ppvX5__%;y_iKajWSZd8tBRMFM==y5(^)D@Xt zg8?F-$SqbRR3pzd5<|eMJ>rzdF`En<8>ZphS&&D}4l|XpXhCSci>!MXby|nLNcMS1 zjW1C;zuaKPUk-0|&VBO$_q;NEy_%6p!Y}LC{HP*6K<$=unresXa7JHVVrBd-t%!Om zhC**Ooob(ns?%`6tjtu1NQppJjXn0>ovqmVegbC&-*nn}L5;4xN)hrgCTA0J^_84j zCWOn`Wp;1fy!S+RL-lpu5pef{de7TLBAy8%fLer3K`F67GANLPxIPGHDQfLs*IeqL?n(3X4WS}Hb2XFo9? z=&OAHN5$yhdv2bhF})0BSzNV&vlP+o=Kg=RufoI^-XsF9Lf-#*20mE(e!C*!-|(DsJZ$<*Kz6VfejS63#F}W@3L&{ zd0Yu#RMNOAfE6Rk1kT3)rmI)TJs*{CX(3kkrbe%bq5|Zid*7`h$_^d+l>Daq=p7Qs zHuFfa2N)|=jPL)|4Fv#1OztxTNC#gbmAQeoTX%px&A>{@jQ(#rk_b72&-?sB+02}J z6`+O1GRW@2&6jo}a74a07E%dvd!y@rEiK)Ed^)FKw1~fgD5&;_R{8S&rc=h6NvPQ;xNG`SyS?s||d0J^C}N~|52e@Rw{G0N+X(_-U?Dn-*|jv+zFZW&2r52RSe z7xyywh8l{A>=15DQb^jlc&ieR*7TLO0Q>mu7gB4C+r*t%|2=|s2x#sl4ZmU?z6d|UJ!-0!k+>@*(0 zCEC7`nI1mLgs=knIdh+%O&wSny8U`aIF;^bKI)6a>hqNNc_oNgvp_|Td_)Rc)jEFN zQ!I3oEzI%B`U{-o{H-3c8}0P{6JJNw{V5`)1DGWDwjx2$LtZ{K%5xvSlQk$@3>oet zaBpvZyV_%a?cq3=hJ^qyn;d;kmuImPN=Go0>Nu!NiHxj0njiYC)O1t&Vfu?Mj+fAn{mZ#!b z!)|#D-9K8H*__~^i;=E)6}z1AdRO{=(AafvoKDLaim1cPJYfwfM8EIdlBgbh*G%#$ znT^z=h+kAub8@}* z%JDvXW}31s2{UXbJ|&_G#I0xDhX|MhTp563*Htt<8DNZuR)FGP7(~+AZMKN&n|MAfZ^2fqxQlE*j6z=x{^- z0;F*wW5@*(mdi)ZkrOB9?8poaMOwV>*-zV}*pC$(S5n4J4iYCObApV0;8T4JYwzu_ z({YbUMC6Cfk>7N$wv=hRvI~re-*lN29dZiEbwitVy5mFa%Y=kNoea3I(l1Q1Ludb9 z%^8Cfch(&j;@tbzEOJS6MdrMN8pFzu$+g56;MF?XDx$wAmYmTV)c~E31hU1f#v6Qz z9-exVv5C8yZw6sInS2;tS`e_=^Cw@G|H>%vKc@LebTc&hp*=%)6 z?A-(t5gO$sj2fwoeMU`oImYYR0=nuQ(B_3NRKM(?R&Xzgh3-(3!c9kC0@A2tva4d z{TsbTCtpBXnAf^~fgh6t39rGIY&{VGk)kqGjhmkJ5^7QlzrnWh#2_M|_11vtnD9X^ zXv(p_?oni}t$P`T4+#eN6-|HUS4^VOot4}&1Xo|T549S?@w>d9NO;$xS*RJD5L11G zXM2D*L@SXnhTH|uzLBJnu;5w{i!WMA=%6Np<`v(U@hGg?)@Gh&Ez=9}yD_j$J+PaqRxBkOQv$Hf4%k4o zB;m((cB7JFyhTtsN@`~8{e21?2zoZ`a}2&n8Cc!p5bk{~^ALwo>2ZMt>^PJSZz;G| zeThHuOiywJ2ei_Ispy$WcEm_(b8`>wU9B>De@+fU6zhy?0H)jY$Yap-OQ$?J4R$jo zg^{R+*lll!aj&#)0(ecXYgYx)u#^$Hr(gcG#&(D)b$JsYg8|o zdx7iau;|0d2MTSwk}E#wF6r@WeAc|dcfS$oIOx1@_8at>=R0TS8R_2NTGai(_VqA2 z+Bx?B1=_&UcHwbzcl-N$4)1d$PVTbJ$(Pkr!AmN)qvT5X$tTA!ehy}7sty(sOR~PU zJr%*P6a|H}O^6ZX$2lI+UgbwUgBxkas9aYg{)S-w2cfUUo=*I%e%o-8`2gr;acyY| z`7kz=Yd)HL2!x}}XGH0Ks=Px-f3$+?)WD_g&)c*m`{k@~*2WJA&&<#-17%gu?aaHW zCO7gzTI)27?vqYAqu9w@Y8AbfGLdp^0>^>?2Nm@J6su{59|e^PSFl@y4&|XQnNWgI z!}berkR{`IW&-HQBG<&?G^}8p$L;IhQ=sguVeWs1|FE${w)bKXYT1J=>|X}y18h)H zfDOt-2qcoXA?)Pysy>f`CKjirHLgd2R&aXzxAsqOjh|_fhxniK4m2&Y5Md?G5Z9EN zT%Q#Mx>&Bvu5}en&W??QNJt{E>ca`#04i882>fII*JeQ;86gP1-I)Wo`^Uwm8gA*F zedo!7CYVj65Oc+jyO$^`+w2$@UZfq_42i?16Cu$n$dWNUn%vb8C9gC^vhv%!q&7OI z2Xfwh1F1y$Bb6j!3L!~~BI=*M=3yGE_OQ}a7sVx_bJ}WBncjY4ovIU(gT##ukRmx< zJnv4tj;<`r+))a4j#%r)p3c|1vKBLbnBBetd=%S%sc&Eq>^@4nPLuAH7OyY+VoW>2 z-?7gE#0qGU%tmi}dIPG(NJn`qD)A(sUWL~aWO3hq!rhB$b8qH^cD3^&t#Wnsqz*zo z%+Oiw@)#+aB^@@BfH= zEmn*^N>3mb67)1&&J3tNV;ZXCXBZ>YKvjvfsIPa;`v@b(>vFTBOQV$h3$} zX_t=a-*je^bKY|xolD;i24VXeYyAM~_s@c?*yfQ+B;{T^wTNfKwN)HHx9=%hEqO9` z^;S5P|9F_X)b+yBsMx0Ir@AzuLw~s`w%v@aM`r=pU%Jn%6^T89?mpgz_(%6xhSB=qxe6>j*~FR)g>l3I8w^g!kl7Ci7T0ayVCMSRCt>0Su0^cQ88+uM zEzo9EM8-^29S6qr@ZUt7{m*0E%#y@Q2=OJ(HJNQulWA`r-2QnI3&u+05=vk;Rvjf^FrQ3m&NfM|9>tDIGHn=;l^_Du6i_}h`0vHc;#-s$( z1oa<$d@7m5y%{=UI05jmYE436?2pmJZ~8%ecyCBMRnyPM<3m!1d?>UOODfn8S4G$n zcXz&2z@wdUJZkAOS5<#$y-(c@W#HHaI@fr~r4iG-c$ZIc<;evn`6R1+(dNHy6C8YC z+L2bW2veCyUrHwqu#cyT*4Ue82lOsKkQvT>40LcrI!-s@DH=)cMs+2Sb7n1;uW?OR zXVJ--v*`R|_)aqkYKnyyW(D-IRQnrD(^aHFtw{^jC*apU-yP5VTSZ6Mn$%(&=eCuCczPxr zx6n|7vgc41ga^qW2;23smenR~J)C#-?7MW{^jWh<(!iB&1vJ;O{Y2Et!ma@fKm%FV zF^{Uhtizo{qgjEB085A@$nsES9=Na2P|Mz}$p1`glKE+iC0+Af=9nLAD~|2ntvAXR zQX1BBB1{m})GF_Yg-S|G;EZf{I&n`4V!=>d7GGo8*JIc7rFc~a+ABQMw^e1mDw4!; zp8$l)3^54;a;V-ztI}zHnH#hGuJwTe>G%K4xzu;f{$^x7C;^+O9hw1s;`#0s+k<_7 zxD_*KKrvvqYEEyA%o`25@NX2a-e__g8-L(X{;peao>S2Ut02{^87yjRyWx3#9tcQv zieodZXAi_Dtr+cwxFoz(yZ-`i{Q4cQEFY@4A)JyO^zx-bbeOj`!fJYQq;qYwsnXyB zO^nR^gm?u1>)hh5TawX;q48Q{XX>ic`efjNz&SNlq;9mL<8-e zKE*RB)={-$q>%iN#@<3Y4}1O9)Z?zoo{r((OCt*%=&AxJ*rhQtvspKma%#pKELJS? z@oRRaJM)SAPc2Q=JlK|hkyrG&2Dn~h^k&D!7P+J4w{5&e8>!lrRV9V~T^@j-da1Kc zeGcAPVjobcmvw7VTzaL39u%fXQ^d59aydoO$VG?t7IJ~#pF9tk z0MCP_uDI0knxc@qxXy|l-eUm0vDn~*kYK|gjgQrPpSm!g?VAA!;1T(S&>&9kXUKmz zGX#=Fsxv`O<19#OQYc>I0(U+$j+Rd5%F>gR4$pyywY^*8+KM%IN90=UmQI0G`jKpP z)Nr$?gA%LPy#uK4aElnP2Qgljfa!rsdhu((^x)DTrUx_HBn)7BAT0Cg@}Eo(5}Bv8U8ak2qz$Y)yNY^f zH~I^TGmsujH`1_-qVZ7 zrZ*XH9wfy4rh5_cgoe@F<`P0*it1@pkIb>(!>U;rGoKFZRS$aVK50svtzS$OF7>$Z zhVT2P_%fz)W>Rh!tKa8hr|`6lUEUc;LTh>GeR7F;FcsIA63*5DF9?X;&R7|UFKdJ`QLOTWQzP?!FSn9Q? z7=pWY&Vp;q(a(~!5f@m)2HVm@C}X>pQuQa{*Ah9Y=hO?>mYx-H$@+Re+H*0>TuKS> zRb4AI0>HgsU~c+bvzx#7SZIW)X8tjj_sn;1T7P9ehj-3iKe~JhyYMxR)A(#cl#(uP z7*g+rG~Dh0859k!9CAGcsLD&Z;3O-KH(CFLX(0Ep1eiK|uLHx2q{wlQvMZUF_zX$M;dU;;HkM zfx!Kztl7sC4T{-lIgx!Q3#1z+>U6})88TBr@(=S2_>js0r zzCb3I7jc>OF+bw&qXaqJn#&N_xEuih`T3*=CX4EuZfE z8CNCtM3l)L4w5;dZozn7G9du8BelX9XQaEdTiR^^yW6FBe8kt zOtl^3yUojP*e>__$^>ikcuNt{LKf7pLr}pOW9)HKPy+@N2(`^z~0+&vvxc2NTF%LVo&prOGXz4=SRLH&X#ke@k z>*jTrr8g5-s5xL3Yp$lXu%b!ZfONT#jkWqtfWQ5c8_{au6Y?Q%I`+V6>RZ!+vU0kS zP3_H1iUM~*Md^!|5nM_`*Q8{R)XCb7VeiT|Az}`|WQF_0j5^3^>%qt$*&gY2F3zXX z6J2f`VUK>(O|;ro11LQG*IYFDMq?NmHnZCZ@vZa_N?nj|YK-i0{di{RhD#8t@T}Im zMDBQEYrUCu0dgLsPm4qi*UG=9rR1*riu6EYq@$Yv2VVlSTCOvs4!ZsI>^c% zhW}c@*(hEjF4vnKE8RdqUSvt0Rcgd2ZlJ2?%ksbPe+}lk3jOav7@!lxP*1v_88jp&Rhz+cI zIe@&5959LpokrPpokF}IZ2=w*ClRqOgAqHuzRCHO9)<&xAZNB`GN@v2q3uVzgxhIZ z4_;M^J?orLDU3p8s!n-pNE7j^P6S8*=In`gKoxj_tSQD$rhgnUMLMQMS6NXa+x}?p z4x6CoGbZsRRYaaebPKDsIpJ5t+K#^M=i|!j zSy}+0m2C{Q%ZzyijV)!lJLR!{W%|@hJ+oi2)C**{EK@iSJ#i-sA@1N}ZqFA(+f+M+ z?SOET!@pySc|KVYFYVY8gGw**T&*k%H|tl6e|4=a|D!T*mYbgFuNnGymXPgTu}?_B z5sEO$>KzhjmanQjhOz*t-Kxd-@l4-4CmxSxOvz!tG^JbF0upTDUiGM!8jZ5C^CBb`q>oRypCO3kR+^3*-NiFnqHIrI z>N#SUcS^1WWnoY)Q0`Olp0;B`Rvm};JE(nb{M>vi z^XR(;hNG$2-i3z9(@N;H_l1WpUfus42{~FakdU^5)c$o-9yIN87Q$-+P9u&s;48cy z?&zTAV}AYziNlkTtu^4gZceWLsTjTgaD2d=bRTW_Rr?M#-&k|*_GAa>=6)Z6?2BDI z{|9&D54#7-EOa_>$0+1!a-!sgg+g8zeL5d97htAPa2;wQVgM4sk9ESbfMw#eHd5f1 z)Fj9qu3I06F8qP|XkG+ND6=S|l|S(`)E1un0yP?NW+5QN!KBFhjDY!8l7c#Q!x5L} zu;EVM7%Le=k;}Ts?Ybr|zSAOzx~#jM;{qb|JvJq5A7B=E2CKmWlYM_!KA5=oHOn7i zA^Sl$KRZCbVn6GB zdu1Gx=;y7fZ0};{!4cd0Bv!H~)Q7qK$@a>P*h=}na$v>y2V%5;9dfa17ML6q~I8SU-g| zvh=(pVidfv35+_*-Ch^F(%qrLN=0+@+R%ZFeG(PkEfhpzc(>*4=KK?9Sqa$~6z~57 zgWcTCJ1$BwpJHb*#g006zhTn4!qYLpTre|IUW@auU;KoYLd7668l-n*-IWm@j_;nj^ro6b?HKKY>^^FWk9T&A*a?SCu~rnRPR94 zQ~m%%;0A0rYYa_QlFkA{{ z>C73F^2#@k47Kdqg%UA~L5MZ3)O=}uo)qd>E&J#Jc8iuf|0q03%u37`pwOxeS^sOE zOK`!;FXo>cj(KspST4m5#-yms+e+r#*M1G`T9qU#&uT@RKrEMHdMbi zexn=`^yO8`tjwv4^ju42v!(RlM8vqe@Zy1L4WGUCEJ8^Q(UKP=@K7F4xhCJEc> zdC|aa`dz4b9oGvM9Bsk34e#GG16&?ow@`Trxs3@3pe>N9EL7L!vcs}2OUpQ+up+k3 zI}A)9yCKB?*I4S|@B1fs>c7wFk-iaUZ8b{7K8CHgzJhE>U>1!g>BFt+bB}mie4#nX z<)L;$ym4nmqYid&&j2%2*H&KkRIdl>tfFFV=^kY`7||}>c^v>$@w6}Av!=4PXKJi~ zYsnJ_)RTRn6MygKXPcRj!;89nB2##iX{3bj(O6g7nm2nkYCG5kZ~(naMnO01;;6TO zv2f6)*5(&SCl_qdZxNy+rdb2q$2(SsevA*C+eBvrZQ@+Sj-~$7K+L05APwh0bRuVy zBQ!u`7XRc*PU!eafiyONC&QKm z2sj=d`KMn_$QvX#KSl26F3c>G>Q?LuDwnH5htF9?QyB(pjRtAb9n( zfR73JQj;MTP~YEl7t_#9EbfoBss>gqp0+!Vsww`MIrx@GC#Zg>V#GUpR?-B^6719X z{H9Ucy@X#;81+Tm^1c|e!-+G3S(h)KVd-$)OS^7sH+JGJr;QM3unCu!X%Mn$hF9Nm%@ z%ERu$&iSKg4y}@7%@Wg&Im>Swc;BmfQOn-0(zx#^id!V9Pm@Igt_^Zr9KVp5D)?4z zd);tE-OpKxF)ze7eRN2glB?7*oOC~^Pi7)a`|WF|@emE{ho%|AQr1R^z((fe0j>jZ zS35Lc_@X1lEhAh0#L2O+Z(@Yo}ucG2 zsyV+JlI`!58N-G6SpGli-aD+xbzS#G9g0##K{`=T5hEZ9QUoF@T|htxJt`ngdT)t} zfS?cs0jW_CLyz=Mq(*x0HS|sb1VRXLe~dZT++(ga=9>GQwf0=+{EmI`iZ-5Ys_y6S=vrEmA?aG z8$h1`djaC=NKXxyQA1sz6CQI(K1R>r<~p2s0Pf4k6|s^WD<_`uytGi-{QQv%8&*oS zjS5g5GHsq%qwk*2e|i3$m-4YK($~IgqEec&&z;lG)L$QIsXyP}0v_IRotrI5j_fdS z@KE&bui+eDOpkndwB1(y@rMjmGfKt}i0&Sg`*M87eVSQG0XVXe1rZbItsIa74qEIm z>zkdKE1xrH#tZvYg2b05=m(`R<5J&#fJd$(; z_TxyGKNPC$XAEQQs;lwLsl;|I*3A*Vt`|Q6me30Ce>P4(dFQb~h|)5%TSeTf0O`!R z^dh6bDkWqfZ>0LWjiB}VS>^W1QuFthnlyT#@?JCeymWMnQ^4)a8#0T(Qz+zUcY&VK z>(FWXP?`QU<}t?pVK)gHH2^VbuqFw8zj;z=l3AL5cD-iawdyy+qS3HQz}Os;SeLw)I?0s0_Bl#TR&I$=EM0H~^A0J7IjmooagvGGEp?V|Hny z?ibxvog!Q42GiS?u-k$BE~;~yBhT33SF+x=s?wC&--Ilw2ey$~z>PJdM4|csvj*oW zi&@`#fyy`*2+v?|jfh>r2Z3zIOWE7kuyQnolhg=v#q(d_Ce5|K=zM=CP+aiW8Hd|s z>KdDPm4CIbmkS(o2dxK%P#ZyIuNqWW9b#L)2atu=>0p!@1+$PI#7Zdh;x#Hd&dGK#6gS^N2J)*5f= z1z-sK;UgA>-&P(5rfDTVvzT&e0d^H-yFuhKiWRe64ivQ1OKv}xIzO5+Da2H;txm>g z79rmBjJ6*nPiOESkX-9Nj5Ly73uGelr@NCP&5>QLP0 zxdu{~=@Xj?##U&X()NI)L7&owm3E$bXyoRIuA}#9X8FWdSLB~xB!=u#powq4_$dxt z-fF%Kf!!yzVDbQ;+X-VI48X!g-=r zYR;ebwWq@x;V0({vg}KO_ap``n=yMWBZ!}LvaVxajO5AfJhi#*~u>C^*-$ zR@zF6e1c&G_T4j0EyZE)2TO~y9*QppfA-Y27?=yEL9sEV@^5sV0zwx-ud58)@hgq0 zPj~eA)KcPU7uF#r6ho0SwgX0QtXxhCeK~>A)a|yXx2sv#EK{_DY%1 zpvRiFr7M4Xb^V(WgU)dmHF+1g!8LSUGJLe5=0vZjgY=f;e1yqmNF#5C2V}REVZVk8 zbA`5&n830Vm@p2PR#+`?^e?Sg^b-a8v{wE{EC6oOHuB9#RdoQi2p)BHumI?kD;{>r zJrgnJzv#%+cv{TV{K)imB5e!dCL`h3_pPea3a~l;$ArS8f7i(Re=yYerwlFzjzC*n=dayr4zlZ}cECIqg;`q`~&Vd%8y?28NwB8Ls5}Ngk4x#%R zF)ORHjd?_VmIABCGK=RW+aqN92HWtY_AJCpxXpy6B))~Q+8D0t`i~C@9EsV>B^9?& zVrf3EeD}~^mffo5x#z46uHoq1)EAHYcx8He66qW4(v2j{<@%z`JbvJl_EW+k6w=&$ z+3wv_N)|u{Z720ZYj}g3O85Ax5#d{m=k&NejD1D(lMrJ3%YII4x9YwK1=UoYm2Esc zI%LvlZTm{*$-}I)@1TW*LTK#ca{|eURVlf@ylDyTe z(AWUzw_mlb-_3g27v*!b#);Uu#+zz)<5u+4CqxP9#O>dzfIM5mt(p1v3k6dGZ4N=8 z_^vu!N>T0}_P#&2;=Mz6xsQpH`K0plj%ruMx7=^GUV8Q>jeTBT`AkJo-wgzY6*`~v z4Yt-?J4h8THti&K7nIF$fA9tF%5U_=E1QMfTe!}wVolVhyb=7(Vm z?Yl1z`a1c664^tGUWG9J$}WK;$;&XaTgc3c65Wr?yci9zCNObULjhN-r8X2s`?2v` z#*=4fZk~woH38e^3RZLO{Vo#yvNgxMCa%>tv*`&|bDE*8cIO0bK6bb~SX*;CKdv*s zYt?a+!nlrfwd$bc%sd;s;-pLyIRQtebORJamm`*${7DONX)o z0XbjSe7tc2U_mXX+2K*?+q{tqX=aF-A*ty{onM5TL*8akOZE!GjmV|;4)J@4_>pCr zB4H<{LNabGnsq94o_p81k`ldUrtgDnqJb?1LZAO`=En(a-hvRjn7tBIUjTdn$0)U$ z;p;S!a_$`qREkcuSId_>23)`#N3}0M1|S6KfA9iAJ*8>)_j&puVPLUVYUh<+MXsiv z!0ZN2M|ZH>&(~8Z@846&BoDyaJ*k@>D;_WX*Z6+-?{}qE^9ewKSh5)m9P8Vy%BcO9 zShB6p|7>&rXODx0bh|tpjX-ORGV{XZH$WSF@*X`Y*YE1pzp*mx+XbK*RMGG6_bRkT zM`dQg)Rn)mGGNch(ReIL%=0AYcSRRm7aoVV=vDUVmw^ZGWt7q%3_AaqiG?vvaK7D? zkHt-gtI$-+9~0E7B#=oUkLPTA3G3UF?6y25$75EXFOa!b5&LuBb?_#fBNoY-!f^;k z{vT`ANI}j4)8P_{|s2xB_0I&?2f-XSIAe&@VZ6juN!~}VzF74jz$-tbW z)d7KW9UhfwzDKtW9P2^r5FIkJQ3*K?VF}0vl>ZezLh^|wkF4DC&Eh5+%Mc-2qK>~zjOYD(od8~CSz|JO@V(qD!w)V__M(fQcN_Pob2m2GFUBjW8>cm_2i%-SooE}J z;7`uWb&tJs!i;5PFfiGiMEC;6hPhEOW4+!l~`$sO&AHROJ>{(orFh^Ux(g6>@sXyR_VKlRoE?L@5f29mE z)C0@qW|Wj()@~l60jN%UBqOa0#Vvmm2uwzuCP@>JujH?lZZ4Tw*6aFRr-<$PXO{XfLQehAYILb z1zPQC#8oPqBP_;@f225_0unLIPUfuv#dLjH-7j@ zs8HD%x#(5q0AGUp4q!%XK!of-PQz~(Z@i&8Oz(U2If>1cdHCOR`|Zt#xlzJhP>JJ9pK?T#mbC zlj+N~AuCFT3hc+=+5tTDLvxw*MCbf8hK9Jg=pwGViSPs7&FcEHKU+$uz}ogIZM66W z88STz3@e}6)m-ZxSwxj(q{8BnPG&%|!&Z|?Ok^~k*~XyHT(4)O!`JE=HCiBtAq)3M z%*Czd;|(j1E4RhDtK>+$XI2e!G}ASo$iZ460Bsjf;Aocrk@O@QO*Jv-`Rha}tWJgSHl`sh0<54Z(>0rvW# zYzH4l(V61Xhac{LdBpO9<#-^1>2dj!cK;E|_P{8tm#7d>5S-?J==sIuDYycgs=%u% zZ@k(Kt*kKtbPFin&7q&fEuX764_m*#wkIMrk6;jLLLtO=(+vQT7Zd_;(7ei4<<{DO z5yq>U;w6m!0PvalpXtf}Yxuc`>g;3lsF4`rl-4cChP^JTg&WaSorb6Q!jBQg5aYei zadQlVA@F`y}JrQB!_k|FNt8H@COnA_i3>9s={%!Ee7;1>*?xsB~<9K(o28A8z*sw8E@`7qPif5GP; z7S_KvX#iUS{2KZ84~Zg^^uZBvVoXsGtHk#BFnuN4D)SQn_nAhomlI`S^Njuo?5wVC zeQk?Qs)AS*1cwy}08LHaXliWA&-|tueT-F>@y2|=>@uP=Ljke2^t}39b)vjBh&A9bdFiT!&nx%T zMW%a#93pHMO)~Bk_ZB-`7yY3jwaiOTF(nuW@`B z=lYrhyf%Np&i)s=fB*i&YT%!!X*$#<{r)Qv^}D{n@JjlXZ#fP9oshm7Ub5e=_;ZZS z1puFF14iwdLcW3H6j_Mq(2j$nK*Gp7k2|9X$pG|0^E{9+q2u_2>(l;L3?u}c-y49y=c+O|DYjmqafftL{bLRszQ3mKtAJPd+724$$obw1~+KSSG3f!x{p$ zK+JpTw(|YF7+jwQ1QyW~*(t<$MGzUO;tmOw67*jiduq8ht}_#EON@J0rFhpTNM|bz z$ddRAFX9oxNzU(Srp(@Y%{Iuwm3Ga9stYL4kNib$aAq#$P;L;@x!;N!puxb)U zc1KS}d#8QRFJCD_WD76K0;*JudTP1ECmw^DRzv9a6;FEX?OM8l!`-o-@Sz0Bnz^RLZ|3Mq4;wz zr$$)?mgHO=0(qeheWjagp_JkTp^nooH=r+0=;%|rP|Q@l&f+ikVH@0>pfAGPdDsVJ z=+UMH!*a3JuUFo__`2J?629f~iRt-R>SCVZ#b56>SeFND==&$@D*)Zc zy$=OQDmWz)yP7hSPjwho`fDQkTET+{HtM-wYc2tOkvM0e(b`9P5f!9!Kp|xH=fsZ% z5|(L+hw_vnKEV8+D)l>rHNjHa<$5)9tL0zA~KCV&h8C?^e%$Z17abU>bfz? zO+3;zSc5OK&|1AgXe0=qr#pX~O3K63f@i|)Vw{*gN(3$d%S znfY(R;)nF{-G5o+kNo-C z2A&rmDJOpO@q%nv{g_Bkb9ESNdz_Cs99W4Q{6R`0tgoZhYl)s@;D&~ zXHsaZ$V!Zi%U%Yfw*CDxCJY&yuY8{Su?`ii*1$^O7Rs7CC!y|hzXQbbZxv6q6X z7C9~J?s7$vh%3k~%>e)}sHcu}&TO!?W-s46XZZE0JQ0c4S;kR)2mlb199Lg+re|(Y zUO#ixj>m&*OH6EDP0%cf&ip60@Qd3C-gSrwf#XDl8G96KmAWP7-VsK(SnpF3k1UbN z?CWMzYZsYj!gIvz48MNP*J?@d`$bn97)Ywd? zU2tx@&7~cL=fZEN?xt)=kH1|+d#4G+jFWkH+`6{o%%M$%2*+h6?@#6Xa{03h5Xn%5 zQMz3d3a4g|NBfx;1!=Y7$c}*v!I76vrcE9zU-wJs%Dp}&pDty}D{cn?{ER|;-aHzT z6TD#bsvW5mCr;EvRBl+g)H7G9AFsHkt8z3eZ0I2h)+$1_-e?y}SpmUk#neUB3eAFALN!hd^fS)!$sK+zqpF#_gU9>2#JeXjlO zT=%tG-8s4#Z>3|Ux-$^|=3((R>Q!Bswst5$lzxG@wA$+U(F3H%( zRs$~!Ms4Xo+s^;nANxzh_d`3|&n!?q0yKmqUsUpzJ(N6sFiZ`lCvr5HQKkBxUy@ej z?~CX2V9}61*hxlQu&7t|HA;$RHkf!=xL$;K*$O?b;a8kFJxO>Egpw@q6o09F=~pR+ zNA3cGvEl5`y>Q`0ZzE0eY=Qe&#L^xHlJ2MFPKgUHVm1}^wF>SeW(@tJOPE46l_Ls? z9@v*AD@DarZwX4ZErP{+6ESaRZ0`sEnqnQ?=FK>1c?_Ac4B@G^Q1>U4sQ|Xgu8oOP zoH1v-6g$dkh#0Anj}FolcCzu268nI=HFVl0;V$1zyfGmiIS@W zBBiOsmTX})F-{2~hpwheXvuJ?b zXl#27(H~8c$IR>veg%WC0QLHN)w|%BK`MV5`31KyvblUsGC-Po(!&{t^4p3Ay$hfl zO@jbYR=ZZm#ysy)0v&=@%96xB#dNaHn^L}hM9F1bN>X0rvZtj~JEsTmWdC%o{cj?QBW>igdc%o}y=|$)mLpuYizfJ`3nl^H*O}KzK-Kx*y2}ev1&bvNQR-@L?%|_2c#y zJL1&twiN!Ekw}vRXDE4KWiQUz0>^UsUGz@TE-d_Z3%H%iJU!4Cz0YZQ$$4#)z4XML zYNbvh3#~fPp$FVkYkA?#w=Df(nt-YnLwBZtEg=6efA;0ibbl67xrm0+X~&2`CHFaZ z8d(CN0mMXg0;#m66vIrey=a%titA6P?LP9V-}nt^#=>M^&yl&wFS6xjmx5E4;3(Jp=R}gFI~EPb>?tmy-6OH2E&%66`6oZO(6Arj*8daB;um zeDB3p=s_S5uG$5hAh&U~f74OHr4Y4uj{2+sNM~7sX=9wY^AzT^g;_h|G(uGTQc<|@ ztMQ@7_~e!u`8clGqY!I{t$RR4+f~D0{}%7aI`bgT#2g#u9K|dQEopOnlBrUrvbD!{ z1})@r^^Pn^)Msz-2AccgcA&J06e8MNhFChMg)q4}_ls`y*c7@Bay)>!k9NUFRVAN* zcoV>PzOo0iy%^PDl_LA-qG=jqne1(^q)j(j4$?+#Cr>L8gx7gp<>_{G%)!q(x2;x% zE`CP9R$z1sX;0lb_zGtud*hvJlP%535kyvVa&YF@Nb3{)IK;5hICbA~n(Jx86%N(J zYf7!5vOl=#_@JYc4Ep!THwpgu-B(qPS;mWl#35s&-^!B(x18VIsnXpL@^>D8AuF{v zFD8Od+mKbXv6*vp?Au#z*^VvsRip7sahO7Ak_ENwyUF@09Syag<>3_~5vp1L2abFYZM#LYP< zIycRKcTQnjawfa)IMm*(#swGcU0lhJBN$$VD4AQ4BOp}9eHm9*!L7)hj04p91Acd_qq#Y z&X|_;NV<9B&WZpiAL|oJOH?QK$k&4%)8r5aIF1oyr+64-sXA&s#%a)Flv8IPA+||I zku57}rMI1VXx#%3J3Mqky+Wbb_p8RkT#aSKH(ddnAnl-D!SaZ+Q|QQ=3zO(KG_bu} zEw5Y2-ibhT@)y-+hJ8AntRR>&8H`804meI{&d|mib$wS4zkq-xeg}A~J9(7vA*#?b z{SWE_CdW+x8jg**g=qcM)5Y1MazDAK0q5SYQ1n!Xd%YqXVIgQ$B^f`;wK_fHsvGBa zyE3T|l$jR^)P9*g?*!A1TUCNi!Pw*qJ+C&G1H=A9_1#nUM{e!RRgRMD`At=^Pw7B< z4lnv?7Z?5Di>ux+4M_RsH^c;_i)XgcGNTKceeqq^;A@WgRX_g6_7lS0l6RC3dcx?b zg|PTvbQ>RfiH*K-BQ@uJuy3tzopT<0c1h@9W~&sBD|TLjFnLryz1*MfFzgot60{*4 z(m*YsJKqFrKAHF(GV;AvXDR*a!0ZNc%gQ|9?m%%^1S&X(SC~8;fWzg{w_qccFO|Lk zP87P{(}_E(_r4nFmQGjUBv?pRu1+n2Ui@06@-wRTzvK!2>VB4b{|WX47bMrk1X(w(c-Oio?`yH^Pw3vDBJLH$gd_*< zY_#?P&Rq?!oUt&hdrIE9B-)h}(H&TrBJVFc-3xu^Eq?6P3w(MmL%m9hYvhQab>hUeI~iq@M%Bu+w9~mylFJe~a@Yh? zSaRr>1K!BLy4l+jO}cYOts4)j92a|1QGNZ14lCf=M9nt~$Mz$6_juY3gS@oNVx;`d zij~<7gOC3s1os8HcLIlCH2DqSS#7sJDDL>A9MSxjbkQ_)A6%u}0da1995UWL42AS;mdNEi@Dc2)is&NQD-fIRUa!6V7WOhK_-)3qRlFb3uO3#!9}I zPQBA72`EqtcrS*YtnM#~ai=F>0DniJYPN2m&D zZEf|JM<^L12wl^dTB>yU7FC?xw{v(l3NnbGwVTh`#rE%f@^fF0n>FMK=$objpSZkU z%hsB!%@I63;u~g8z~@&tl$5u7AKB9VT#zqDp{LJNtXxgSGA6NmHayxp3zSbA{DddW*!C_`q9^`1pB@hqOczB9aFG1_NK-CT>R;8j|p zoZQ=*?4SHj`q;~u=b1Rc8d6Wy?Qcs7ckKl9+PS!+{er4H4bRh3US()b!5AKlPU<{F z414SDfseq1p&=5{u9<6rE1u3e7fJH*b1}*3otcErM%Ew{D_qJ}m+UZoF0vxGNbl5> z3n{W+-Xqxcnhd&jZma#ABASP;j_;qN3X{RPtuwhGmG=(NQ~6F9bnN55yASF`oI#!PsQdi%Kxr-tH1ug!Z_z7r{`pJ-Sj_s?0Op}f1%g74^&RPh)4{vMLX@E4fY!|eX z{eoqH6d`+xG>09*00k@M+GUoQlm2oNK#C;Cr}NN@AH zfrYv-9mA3gy{_4143YItue7SuJmtxVcqPhvY42ItOb&UgaZ)ViR6&vR4D3B%!V%D+ z(r;pT*;2Y*my1let??tK_&onDCz1p^ZA-bjpj)Aq$bBlQoN{HpYI=8CnM9p@N@xsH zTkB5NEbSBArbNMG+%?Hhp1l*3YK^V@xT$-}ptCY?h64R+Y&RhH+(P;FsiS`9k3nFt zrth=3X~oN#xK`u9eWBaXOl(EXjxV1D15xMAS5wqk7?*y=UGMLdD|O;~)0GE8wG}5K zir3a&7m8Dh;ufA$BI^l9D-yujj8XU{MSpj|=a$e@tN*q-Zy%7_fd}ON(KhpEThG7x zK8D>}v85kAIpNi3Aa%=JaFwzMO*}T#xnQSd$4!8kl!q99PWzNc3!iP6vK=tY{;e&m z>ox6?dt+x10NUDw)l))~xn|Eh##7SfASS@ZF0Y(c7S!Npr%?L10XJEJs^?hkYZi>O zl4yI`U6IZ77sLAZaRrxRvw%{VyDU6)hAJXOPK)^Kka_ULz&+|s<}@1R(60V8R^+`V zV;Eb-jiexQ_zX#$4)C5;;?estDRyzQDvo-iZrdMDd}~*R9zYP;rz8@8O*HauHf2jwN5>H0TPjh z-q(P4gIKS9CYCk=6+>9M&kYrwqA{ao5pVA&yh-#4r$4{Hx#fWy4Bw+JTyJ=q%OKLE zkR0t?oabUG!Etr}d$;f6@NS9wz_(Y^{>Fw5zC0qF?^|4yEp0105~ukEJI%WnOcQy@ zQMOk4?|;smrx^f~K>@h@D3u>L&?O70BsS1QiPt7=dWsUghI-4EJ7!P6sU8Y~ajU$W zlj3sn`Tja7r&N(hfFUnd$4DkyhbD}vifiHab2k?K2Xmn_;-LsT=dc=f;za1wip&nv1X%M~a$-GH8RhQgnSg8nx>GN)Z%rPnh14E|x zI2T%lCxJF4uG-JhooDxT5#qFnLq=8QJJ%a7!0wtsp>a&LUd;{-Ad46yz@u|RQ$EJ} z18?^fB4hY3J|up(e)3-F=Xr{Lc6~}`lfV&o(X@k7ZTgFk3y#owNcYxdcJp@YX|mm< z@$ZF!v5UkxH9ypj=@*JiV0PN6q&l}9gSdU`OiJfxAmX*2xnm7&Q;E=uaxEXE6$1eO%Ktp;<|4<2M*((LsvS_lUxPhI%<1lT1MR4pw;9i@KJ)kk=YjKwBu0(n*ah$_ga z#Y`C$Ja6I~Xo{HvV1ZNOR1|4p9L5|Kz=_ETiQIij z58&%LR$^u>n10cPAtF5;B?*}MV9YH`x;J_Jmo*zL2%o|&nD7gPg8=A^x{Jyw$dS`n}U05&>!AEB{-rsg)eaeopCX9z8&YGO@szZZ}Su12K?bHG%$ zF~NGz15pOpnt%h}|0YFQJD61Gg`zbx#!;~n!4~VdR3rvCfTgCZ)rskOsU0E|+y&%_ zce--mINQmk!8^gYM;5^~)uGs)Gy*8NEpHy|8+=3ay2caI;D!KA}L=AUT$Ew!x@JF4uCS(iJsPL>7_bbho$YC z?Yn<>220OaHi3Vzx%?%|3}@$fvb7ofo3g;{U@PtVLF#N}1+c~<@WDaL(oxB8UAha8 zB9=Z1%{ym5MieOfmPb0?W5Af0Y@5SU6~^L1CE{NvxpY;SmVSk1kCGH4iJaj95d7_9 znLZ(u+gDDwm{B`at#o58SC3#~0SQ?o{06aq-v^kV#$R=w8slIFG|=UHg0P)Ws0=CL zQ1~$)bd&T<1NNM!tY&l2jRj9gc?C*D zdF`idbryR}OFUY{CFDe@zSPS(42LYtY1cIF*?vQ9*O)uce@A#8qRfZ-0gWyVt8$qB zCSiN)+rSvH8j%wLtUCcO95l7aRu`k!;DS{S@uso&g`?NknyH}!Rfx6l;-Wfz=lxD) z+VdI8ESkzS*}fRE3^^;{3vb4^UM`C%Gj!1g+~BANWcouL2A|GGrprX;;gT1dY~_&G z4#A+X6V*1_J(BI0Az^*zEW#)wHD}v%)k7I}YC`AVKEjgO2RH zbcr@w+En429QsAqYLq7YH7JV)(V%t_5jap7h>HsHC1CM7b>@hAxFC_|Ao?M;FDJI6 zrO|5InCG$f*1MVWR{lg7bK(^nX&@Zn=pPtuecq7O+`~KpQhnEQ%gG$) zvK|Fu9t?O4uc64XO4so^PaR0msX5AIfOMCDu|b|mzlFgVW45g57E4+#T$+s5B?s@@ z`=IJjOjL;}bN4zLTS4FBKB>e5r_oh^TH9#sNvLR9$o?2{dmame;pL2#PIh5N=wEUe zn7Q0~=hFI<8sR@IDzAJ}vk8I9s zic5~R&o8>CI*XI(evxmd6@+1L;i&6kCroZlD^rlmH^5JQE|iCTE{m{^XyP_HdUE$f zRiz2p-=FGv`+UTCUbE0V0@ZvZ=Q(*sOe@{`QM*QJAoeNvSi4Wyz{H@D3uwoY%3v zlv0$2_PgqjHJpV9tfoMvxx{)1B>ThYD4dR%-ARt6>V;Um^?(w$gaE1F7Y1O)jCr&7 zop|CycI2%Y6lEHJ7#eR;6;8N;@G23Evx5QQI;tmF)%%diGy?E8gLmkwokuwyErfm#!p_^oh-tH zM(?An4j83?dv3mWFlGNmhoyjgo8+Fjk$=(krjtv67vZls_+#chl6Ds#XMK*+p*zx- zKv-$cgA4k6c%G|yIo{UI^dM!8w&ej+A`f&T1C(67<$QEh+M*xaZ7;XM*j*HrUI`{0?#v5YCerxe!sEZ_#P?Dhp=;>X!Maj_c;YlL!g$+f z&GEe|y9UQ2ucK(7ha(wfsQMM?*8E$VR}~C5$ydccg}Twg4Jj_Z|8rlS=~kMby6}a- zAFcjSF>zjv*9z%&7m@cwTk>UEvLes1=xrYOi{J9U7NyGMcrAzR^qDps@PwlL81{N` zh$2|1$K}AAbrKQox*c81I>Rv)f%vx2VIRl@<~s5Lxsf=bjM4)%74>;a5AUfmia*Uv z-U8jlIr*{m)Vw7K*Rj(3oYM2>MHDZeclVZIzU;rse;QG7GxFXQZL3{)zrz>z{RjVxypHhgg4OU40gK-0 z#0j0l4j!Q}Ppom~X~q(Rrmd`H*AwiLHx(>AtlEaqz&s%gEbqWdd=mE3Ka^j6XN>G0r2rN- zA%yO8pSC(lt0+f&!kS~o3pS*k z*i%tRv%nIr@vLqmLnlBzJI#{McAil6Hp_RkQ7I1PsipN+9v8%X_cu30wM3@u&}}5R zrGWvvAYGOW&{jkPiV@+*e>^V!|LyB{UtSt=18j?nMB#da@|X?D%SOZH*Gm~uJ37wk zesdi4$kvSMC(Q=1Efo#|AtP5Zpwt!5dS+A+*Za+VIou5HkkHjjJvObmYrZr2>|THR zo-5h&0KB9DUiea5<_RvpRRf##UAc@7G?j%gkyYyJKb+H?ei&oEe4T8o z_X@3LEYyeAzHXLpa@^XUN8m%&D=9{`dB}tiGx>TgDA~T-9&_gNaD zRQqGRWOlqLECU#r6667=a`Qf@0mTfQqN_q^$5&aCB$kT5&k!(xD$PC#a+lg?8bn(u z#pmO$)o@lR49@!U$2EdPfRU-)#&2)yx%U5Jcixbkw}?6g;<5UqCFy7D#}~s#Lm*?($o&N=h0=yxjXEXAX;G;UIK3B5le_gKYNN~o zA!x3lwstQYQ+*WIXs0Wa(x~i~;2cpUor!;11%QZZr2&|>59Fm(|52_J`tSYNEE<`# zK2X!Pul$jd>ZUV5=|Li6(TXCDfebkn-PM_Vo%T3QpLZQ@rqY z70TchS38W_c{!)Ew2je@RGW{m4hu?S3ekVBnj!dIYLd~GcK+VZP)Yl{Ynk;(T-lB+ zMk4wF5%Kb(L&S}H{^+1sx--Cu-A)eEk5KGiIB?*2-BYm;x+OZ8C3}!-0^^xCANWOg zbL>hUsGcU@BUSzV0UYPyGqf;gNo)0h+zT>q^fxjym+M|g2d9<97y%@rF`zJ5l>ECF zVM^W^e<9Blm_Qkcjo&@eBm+p_So^#np}pAD^88O~PynH0a`S4RrA*n+Eg(RoY`Gg@ zwQS?`h3s`jsyRUHsPYEN zhdV&S;`f^XjHox-*1hKRqB+D78d$Zed#o`vu4eD2ZTPf=YuWq;Ud>ca-^8;qcLZ^2`gvsX3tQuqdZ;(pQTTso|7 zDEdECX-W0OvcJmV+yo?uH+;OcE(3cj|YpzbI% zPeGAB2%QRI6IT3S}I=Xt95Aotl>19ReA}zuSKo-R(&fRTzc$Ph(J_23+nB<^WAVX2Rrb7 zdGQ`+hl)?5xXBK+u`nkh|E9?W`ln~(FA5c$-%BKL@vq1gTb?X$9~PS*3Q*AKeYB+f zdw5qin zbG8-lN!?JxXy@#=1PF)xXf)`^+N}9FlQW4?!>p*dNGpnwtBEzfl7M{3l%MzB#q6Is zx)NjRiZ^imr#+TgO?JfTsB}Qic0lEtu?mp0&9e8=_X=X@?FU@8)h-vtt)!&1@YQWo zwWyO%kLa=i*qAOlnWNu55$6`=#0=MGCDUlexGn57y-q`Tma!Cr_zKtXR%ca-#ak=i zJq+KY9UUMT^^0neH)1+=gEF=x=W;c7d@cF)<>?)(R}xh1TGbT`Ro9tLHiv>@bnq$z zOCqrvS57-lbth$tD)KLn(9b{z)>Q!r5h2~f%P37d`>7APOW!sLgwa() z)Cm)BQ(qpS>@#L)Cem#SwBLNGWw|4;VS|;Gx0&coobv8^{c^D|)i~h8!iZ{p1f%xo zr77tiC&4DNR!?|OH`yti*%($K?p^ND4jr%Dor|}_g)if zfF$1KKKq=xd+xn+X3n$snYlCm#l!Q!3Vds=?|a|h`zuvhwsY@h#DLZZu#^r1$jpfx z(oSMxd!2%CTEmCgr0anFbg+E~U_br%q6&Fi99!V+uEPG+D&bb97wr#WDWVTU4Tw*L zgeiddlwY%xscz@)OgMQ5+ z{|5OjhkT1HJ*^drc1==VorP?5*?3Sk7j_zb&f^l3iuMOQcnHYpJG2lni|mV_JD;ir zvb}WCCrKi6;rtnu9lwXQ|3WpQV{G6&(j%4DJ3?P%{RtzlW8dm|H}Sb{57niUvRsgz4iPk%D1@He544IJp~_mat*j0@PF z0AJmPFfMU&A+AY0(iZQAv~iK-5pFT&$9x}G;Ky0w)+p@pL!$zt+&saZhr<0@^GXRR zDB^+%o(#YwrcYK`o?W?01hPmFZU+NbJMy#xUJs5O{vcJ|Y;2|L@5dZ)wkd1(mS{i> z%2-T1R}^e3({F5Z=O{Iyan(P<^Qtmy#5K%;=lIv`x*t{pRA?50X0Y#+xoUvk6yX!c zPz=p&z8vnur~^T`Ti9RK0r}Wt+I9K86E0I+ z@{D(H1Dl_vNvgE!*&UU2`fbHVCtQfbc^@EZVyCgM7;n=nqIoK=Np97}tsn5`x2R6h z>=TwUl|io}+rxEU`6GY~nhhfx-xqlnQ8o@S6P+Et5(*-hTJgvRY<`j*kZAV}z=waG zNm4@$OAj9>_}WLlc^5;|AOFn43!l9Jd*g49+|dKZS~WP(p|D>86ju+}wIvbr4SW2K zV5un;s?QFjpt7MAQT2eG9?{PAkz|3UMb54Xe-0|H^|>m%{5|Dn^}t&0cqfQxdq}o2 ztlVj)C;>;=kAedjXmn2tYg%qds_!3%3{*eIC|$H%bq(Cu{~RPtIkiuD2$V&C->UN; z+CWsK4}ggT@UjZV{>=@J$~Wz|{R#B_pXdQMQ$pTbv(~bvBzr^Be!wY9pc-7qC|MD7bGL<{C&r*FmWb;;DdbaQFKt1dGa;`I=^|E$xFY-E zz``UO=HTSjaOPT$&RnJ0O-Cdi9+HWlPd;~@Z9PD;UD2O^7u1=&;usZ884902YZejF>2*L50VGRUuK$siHA{Ko%x-kg2VObI)3xtZK&`N99Ol9$Hu;Or)?JUK zXNwwcl`3B*!r+W9nFRVqVKq~EkJjsM3r>oOkctxrkq2nMeT>T4T#fE8D#KcBQx<3v zqT-9IDN5s!he>)9@-{`*PX(SbQdBUF9%eMaxxlB`iFzniFAouYXA|-Dz?lddDz8z% zk1)D8{X98+C(v(?at;!H5Sb)>ZYp_*M`U4G)&EGZgXd~pb({J}A{^gTJ7^zMZ+-V- z9c6R+rhLU5q7=$eWMl|uka9AxvYqljE(DKC@+W&o(@ft*3zl*w$)(#E4r{$X-!_Mv zw~3w^RXRmaAJ@BUzc^Q|8bImH*f-ivgJ^UGfU||u(|%#IiGy%RK=KD);kXBLen zNZk3Zsl3=0W;tW~ zgbhF?g?aWT@O&sBK;e?!MPv8w=P1q%cXQ#s>F{#>F-qL zN*$CU0Z@L~W?|f2qJ5^ZQm!XO?0zECwXbYd`SW2S6qIAC5}>|N3`c96iC!)zf{Q zy)RKO=3WiBMobt4zz+ML6#AWd0%qytM`bgn*P1 zx_3wSxWBO;L_!u+c1!$#E!<=)I-f!n=eIPf(oZM8VB%y?^WDVnV=^P@XQCA@yY6_er@4MMjKhx#? za20OS)vd(cJRca;@G(U_SpMF#yFfWtT>Wdtn_BGvN$R~LVGSF)_w=C+kdM)f?V2?V zQpm_UzwkT(TS;M|s8H9b(I-cgCEaqqkWv2f@w0)uqc+BxH#i&aCrmTir3>Q~3Vbrv zT!cIlwZ+9Kqk%Q~`{An?2!ZAd21@H~b=-H2f?Je2Z5MZK zdYZEL1w{;eih;&j#qKxY@Q9Z7$CAF)xuWVDJmQfIq_A!7A~fr#N-WW@Qrtf6^j}{v*K(La@MQgJHqxNK3lFy20Z?IQF)StzH<&<}cnS$TRE5R>jEmjQ?gYn`k^CH?g7;OGZtOY& zkF5qz?MJi5-ggAlI0^_1;n;8uhj*6N=3`K}!Y!Im$>yp6$|?)@nqqf*cM(&j@Yl<7?v8C3AAgq_blwJSu+O}e+FUQ15q*hdQNR5O9ZFKX#1+*Zwvu|*h+f=kF!-WJA6-edZNuvT z`CYd?)DR499k{Ds$Gp;WFmPEdf%9{E#B3SNV4`9pU6Dwh0-e}Tl+!!osAq-{IZtkt zK6Kxd*)~gWW}aanT214ce(3dCkb^J~jo*i-&79*+GOEX_({F9_WjPXW)s0`k7Z-h} zdSD+_usoC1-{UeoUUa?U^r}%2XLUX<18*Clpn7=}nz;Q1r2S(3;kI%edI9OMZ*SOO zHI`?gzHjv&aH;azw;xIqpAkB4eu#-qD$e~*1$m6!j^DOa^nYyuDkj?Cn}pNZO61bt zA7@*_f761GGX&FgA6N7+wR9l>Co}QWt%r|+R#Jj(2Isq3(CkY2Ty!M;_%HH zWtRgVJ+6-5yl=y(1Y8*|wvARU{`C3d3)7*SukJvCf9S3Hnb#g{E;BLbDvNe*FtaNN zkWK*a&)T)$VXA)=xl21VZ7Ua2bfeW@DamF^^5f}`#5UAhqc${iiXI%y5TZ& zjTcGoDv-^Z!2Bh=6~6$Tp z#RgFYu)6x@8PQpCvzozF0baoeO0=VNHTF;xFBTGTfJL5B0sZt%iX#aD%u>83rZrKh zufl*!YrI=uj#wFaa||wK4mh&H&n!cY)*Hk@lPP<)TMz-#8Lx+*F;a#$@=Bd5#ALmu zp2U|c^Iq|~U@%pyJ3Uvp$&MyK7XJ$|wvexZ^Ox?Oj@~A$b)~|7n2Z&rXB%QcU+vvz zsKj?tv)EU#X%X}`by1+8x|?=plB7s(Id7Z zErht!_?blj3^1pSd7snW`mQ?!sLFx{!?zTDrWyNDn}-P*J8e6SON1tW3WD*SydpEyS`q zJT$i1VM=7`mxcv^JgU^Zy<&!X20RlI@H*kbdHFESuWt?rB$|msRQXI#wFPFYnUjGs z7<#CuVP5%yT88}sllONj!09G5TYa`(^+Y;Scb$w*lD!$vdw_KIkwTM>2 zLn5%HZz&yprob>`LBTg%9!MRRM>JI*ufE4A&b*XYJRZ56X(Dww>ny;2$ms*OP{1S3 zA3tK64|0tqC1Wogn4J!z{PFmM?e}!zkMQvZfeArA%!;NrQR$TIRa04kU)JEDaUB5Z(ghZNYnhw_9 z4wp$xmhF(~IPIE7Oe*?Hv=P2C7nZWdC4EUy4(gpVKR9RoKI<0{$pbfUQV$m0s z3H@yjCQlC)dQ)2z>n{{qDz-c_#q$J$2PF|li2kZ0mqOP(=x0*q7lvSqq|X}`tGSO^ zzvg-3KB0&sTcm0&QJU1=dfpwulWqIU;1SZ*kp(`{+X1L4(I6);u1a;4K5MHu#byTU z9WG9Kih|=}6yKEBd;iA+>u2f-uV-3OU1j5d|6l)8st2yeg#BdUCm-60`g%YVYc{qj z>R(U0u@0x>IQ09HQo8+wlQQ@RmrB{JE$$$lU-4zo+AjMco6rE)MUpF{fZ5vmH=D2E z|7zIxf3d&kteMG(dDFwHmscWp47KYwr5ctk=>lW}lgd;+zuF5U0o{SuCy0=tzq0$Z ztE3}X|M_Em{+sY~71L{zSXMip79geb+l_CvBPS0sZRi&?5zXVg-DbC@6{TI5s_b7P z$`x`+Viq0uVrAxTvFCA^=5TXSj$_cP(mx_3>3@xo%mD__KO!V&Bqzd@*!r%bWq)`& z($)j5cuk1mmei24q+S#6vw_>rk?+sK8O%bmCPmLU$hrW+h+8D>G$e5Yd|-G{w0;b( z>f!b~;9Y&i=m64?on6(evIpt1_%%ebYu5za*c<^^2u`zDeB7G0C^U4LT>?OUR4t z>s7K~hd)EC!{UnO!P_5k*{DF&kb}Y6uleKf)3g-st{?g1TD5HHF>Ykk)WswNi-3$l zS4C>iAC2-Z8@RLC#?y_h!=cpiPK~W%fRJE-x&>er)eYm8)csCn3(cl>lHILQ%k+BR>C*1KtOyNh_nYt`M*xBEkT) z`y&5FyGNZ*Yc38k1LzTNavU7s%mF)~5n^n;Z=HD^RifAmd1@7|nb5y8i3^9O+{WNx zIq6rrj*mQ=z}(o=F4O-Nudl0dVNo-ZLo=#c&`(<)x|8AgzWt9D+lHHME6G}p8AaQ| z&YhOMJ(R8)1v$=~u`fVp6+Vc5n`Iyop32cHKf}xG$&8pj?NVyzvs-J8IcK%Z6mu}p zcN5$;G^f_LIoA&+5t@iI!w>ip}T@_cp)rgU-OYs~P-JZIi zSK}L_?S>C0Qg7 zb}jK*{ZMed$(t7j;Pa#QidAi-B&0=JXLf+bA#fr;zN-L6H9tIm*VvZ4TE6N{{<6Ja zQ!;yiXo9~?e$zg@O@QN$Uiwbe{m`*(W%=}JOWFVsUg^!Wu$4-v5#dU?!dI(`Bbgy0 zZzmUuXt=Cnk1Gf83N>GhjL*`oihNW!o+}!=GD!Adh@CUG7N`qh&~*0>|KwC+bQsJ5@PpH~S<2=@5&+&z_SLMnv| zXP#{a#8@XrFc z@p`nA^VLGFLmGKgyzDOXatU#V>C>&t9jD_xx$*_R{Nl+KekeUz)~s4`@-03o%Jz)> zlyKole)=;WCDdo1jZUe(07z4KaRR$RtiKWhSG1pWfoLiu#2el=5`Vr>)N5%Bri8)) z1z_Ml5fEGbW5$>NlYj5U(W}14E27lD)Ufx9_YQq<2hBw6IUy}%fEc_!9V1+QZ_fW7 zg9lrgN?S`s+T(ZMcb6}+$GaS^LF)41PNZ9agM+C{{SAoU} zdLRUE`|wQ@p24KoneWXKmPyhy^-3mFqO)JB@5}vYxZ1`OFLP-< zm6`iqqO^-9r5Zb_&I`o8C-B21SFIT{j=j3Y1QPk&{^Sq)e%HV^t}3(k9`j5-Y8ji| z->F`qe@nqj1~+0hURnSaDn=;nXZ|q@w1IbcKv53%fQR!3b4-Cn_gbo}v65G3xeWJC zKB|GqrOj9dvH^zis$30TlW*Kl&sVlu8m2_$A0Z=s*+0NTW#EUilaz!ai$=Mk;ER-ziAB*Ua@Ma2A7p0*t4WrVu2{e_u2xp)slW7npnWay zkCI9-SCgUraP`J4gN1?Ul^1hs_DZUImU+wW{a+eupz?siF^#72020Q;Tb!=nBpaf6 z5x-i$M8xS>*rNkviZE6_8PbE!H^#~+#(&Mo6CznoYn}R5=@afW4)qfX-I(+-SOjp0 z&T5ZlDL@hCj;=o< z@@%L#MDJMc#czTQss}YC5R&G-@|nE6UPV(r-h04w+N;~&j?G+raT1-gQVd}2*gAiJ zC2@^qpfcgT;eazwh)x3cKFDoUPfA#>*WgoP-Hvo4|Cb$_BF-1y=!?BBE)-5jr>te3 zmh4gX5b8)zy39ULK%6pwPBUy<9-)}E{8i4m0IzC0MBw4G{s~N9XQS-~>|VaaBv!EJ@*-Y!M5wwfQx)3^Szb>diPh4rc6%|lc0xceKe;< zV~xn{`S6)y>{%>)+KCN^v!y_;K(Ycj`NrxW*}>s>Cy6ilS%UH3sjBzWoAQ`%Mn8R& z7!KZ`hyLs1?vMKZ-#j)4{#*@aAr%fTJZ(VuV`{>-=Op3pnxWx87t7XUfX`zm(tFif@2pb?3Bp+$~MfOy?2b(7! zzQAS?+o`;z~vu@E$TVE%sTdveRs;Nq(>`ntnYm&G^RCG#eEIduYOIEkGCrigf zqt#%=iDl-Yjnuoa4mZ|t5xmX|=Tdh~jg{GC!Jg+gesNXiW!_pCL}nn5DqU8cv7}9d z=*7YE-v>wEQM8G~Bi5ny{#)bKJy?mFQ^YqUQ39iSYN_xBay5>21}uFVnYjiDhP}qE zk+_pF1`HlpKRHM@vW3Ef-*&wa;hFGGsvT2>#^QgFEBcVgpKa;CkZylBZv6MO$2QAs zSK{&te_+3mahv_n?ojTn0yRNFy+|A|lgwi3e=|1>*m{XSvhG>8E`hx>U9harq;DU9 z3@Y(JT_}pY(s02i4e-fo%B|lP?NGx9POlN4xT%Yx{OiYHDlx_+Z970^ zUyUjj7abSFtB{W1RTj+0e}#9;P1S$EyOcYf*%vR6BusG0ULl#F1h@-F-GN+4bFU)! zMPJPYyWarc2R^9TQA!DC=haMn%Y6$!$R^8gkzC!&1#=16@2E}2>ptHe(+^PrO2ctX z5QPB?f_kKJZmnsfZyR)icD`vsg!*;?2**o9?gw*SGBY~sMpR9eY0!SSG;APl>;V;Ndj2@q|DVdu*2W`DT%*AJPN@4B@2B|{pF*RD`H2uS@X=0tZvB5U1`#kL83x^*dWc|pi z42Jnh_to2=*v-q5EX|=wZ734;oq^@y-D4HS2|$1V;GeN?U>PQPQS0o|nvMIlkMq*a z{Nq?HopDUfLLG%4AFu|Wsu-Rh$>+N81YVqWaTzE>d+k6Bo@2KQ3iFOdb>53REQRRp z!9uqRGL!Yv@Wij~WfQiGZALk5dtM31Ns6uFl!o6%-9ZG@uz|+rvZty<)Wa3r_Cy=Oyz(X2EN|LnF32?9qLtDpoPTbDRHGbD9Lrb zx2$Y&_)hiA9Z=!pObLP`o%s4T1aU7>nnckeCu4f+%OJxRLfu-HS9r7zcP;=p2jMf^ zhjr;Ym3$Du3>SKwkP3g(a3Bac3Sbl`{|dQ591^(;Mn%mHC{&lHF(s$ZMU=LuywaA%W8} z!Ugr?CnU!vUgu~B^XKS=t9t&L3=pK-_V>8+0?8~sw1jtjSm6h*QN1&MVV)uE*wXxorpa2rS$7Bs#e!c}q<~9Y_UAuIQ)Ecf3m0--H8~!Rp0rZ zbUjf2#-(%4s)Ezx(3wd89S)(CFsch8RQp~2pSC%^ zGH<2oCt@_|bi(%%^8rT`szU_5#Mem)8O_XMn{{k@=SIh0?iD7_mi)nEEt#ZsGC0j4FJ2msn}q8>HV#%0KKV%S36`_P zw=4sg(;C)qoLn-HGpms+QeV?**ocs~zY~zd8Z><(wm&u7<%}W$KK4-ER7&KH+YSwf;qe{lTO9x4>51y;QVb^O)vI zPcaRGyz;r!W8M!bo4MROg^tq-J)JWheyX3V*4(25nLk2qn3c<+>4TtQyqy9jYkbxT zW9ab(XPX;V9=t($6Q3hxlQr^7SJ98t64KL#mf&YG5>w{>UlOs5q%$_;wA1RdmL{SC zwCVYS?$;-&ZqQK2SVC|B@IZ&{Q92EsANL5GIn?s_-nw^U)6dr}U;{}!l}y$` z$HN~ZsA`Z8A<!d*n-dy z3>Bh9#damfW;9F}aNCw#z`S`?tNrHB!|4C&$@-5Uz~HT<-7NC^b!8w`Nt9~z^-P4= zvUHJjdk0DTPW@XB_Gr}HA{{LA1yr3mb$Wo27Bk|n>;unO?u?(|yjo}dS~{{3!k>jf z+8oq`?SdjLOVBTBKpoeDr|ts6gg)#1gaDJ;dRe-a*j0LcGdSi%Bg~&Tvip=+G_#N> zY-OH!QT63_D&-P#0~cpRiR=S;XP!e`q%P3mdNGsJ>S`|77~g04oQ=}kpDo;&>w$@X zkW_#JC)Buw3MwgXc0-LK$S8Aj)Y>INY16<(uqCq=`}xJ9rVM`9oFFO>&;#%?;)Nv( zjAtl7hM>~85q7Xz8S=*FLUC__&E0NiQ4l*R?89|l!)RG6l2m89t?~F#L`j06@U={) zEcr4%>)5#xO5nHD(92)lcBHuRGZj~bPSzp97pDcKrB$xX=DSE%KR#Rx55YY zNsRuqm|dIbFA7=-Uzfh3%VCU^;nK<%U3OTeHQjG2b!To4g80+lByz{rWW~>rUxBxt zug^P<49fJUcU~YG~hrgTx zOCQ^{`CziWwETh8x#-t=(5YJ-s@=Pwp5hox&tCM=+Uwyf{m@_7N-U$XpF7viW>fHC_DqJHMSUbFmQD^&nVnj(kc{lH`KjSru8Ft z4tEy(B4Odkw7Za6mj0GrQoRU8>$ABIxo8Rqv1B#-PIY?C-oJ#Kpi-8+j=W<6yw_9o z*gyRI{5$97pDz}ro}rJ%9?K5#N3apqj^b-9Hiu~V{l7kipQKzG-0GFta-k*}cPofa z?vpNkfI4|WMIPH*Te;2A(6AaDIVsaz0E;yI_MM6WZd*;=sH>hwbi>{4OI^1)O+g6k z>9od;7Q)`l*U(E(RrW2nF((bFjxVqWm6PMxo?PSG%R+$`Q+ z!~wR-NLq|P9ze4Rg=wfo3Qee5Rl;lD)=?L+SML{`zaYP1wx*rtV`fCz;B|l_J$+;L zatL|KA0Z8~^Okq7w;SnH)Nns&u6KEvPE|$ey5@6jel#s9@kyh~lhDX@v%^VTT8Bq& zUW8DfXFL5WQ9+`~*RZ<9R`Q z#gpoN^>Lh`uY7?wJV=pKQQC+oOSq^>8D(e@j%$?gy=TmJMMj2)dT@t%lw?dapXN|$ z*o30$&I1RpL0Ktuyzj!b&qrR>x*t(kK+Rb~#wQ$18hb4qq!}$nYot}d#nEoPLPJtZ z6l%l_Ptiqs>Y8^PMG7w-y%JE|{7!WliINIoWKhdUzc|$LrK)MT1yThB#E5;F=5I}x zAGvWq($}WrJx|$&mu*?@A{#jpdAf#9Iz&n%w-6fpkmprMoARldjU$W4l~BVK@Sq8r zjR2p3rbR5C(9x9ocPoTqU_#K4vEsAI#(0!|5f5sEl zc7)vhY+X4J;^O3D`-^vJ(TA%I?{olPTAf-dIx6PfK~7e$<+{Qv3LnGO#Kx9L<7fj! z>t`4wnlAXB((!;DhieNuV4m^BaKFV^RTBBMKUA0tutJjxXT5*&!K>7D%I9-buV8w64mtsj8?E=znNOtTFeP&LBFSJWm0YMqib9)uWkV=+cq^KSiWq z%P|~NIS<4gyiE3%57+h~!GXgErSRj>{zk@jiOP6A@)*cXREhvGU0VD>WjiR^XTVNb z(m7a&63(YhrCo+x+t7V;Dbl+w)jGY_i|->k3u2FDu&?CrqRu4Tg0YK9gE0 zG)`f+KF)Jk!I1|UTDXsg*QcFsK%U{G3otjm| z->|JRG1E7HnMJNJQy_hL(=gfiV!rAnp$4)lIy6dPW-HnkJ@#9_(QLbVFrA0T}5vj z=RH~StTAMaM;vi;EEwis_#Q~`wjMu0Oq$v_cYDNOcwH)K`~uvEi=-bFU>T+$O^XvO z2yq-&Pgc@3L1S%aJ1g)DFBjtHx7`E|3v$}NiK^^5W4aHq%2cz~I+hDVl!!kZ=Ke1t zApDTBMt!sIJJl>N%G4b2OtsV1BA;Lz$jH{#HHfY7TyCYqdp|yt6pRte{un5K_jAd^ zaWJ$CkO}31J*ke<98C<@MzQ8A8|9Utq*=Ep;*(KL z5Y|yO_eXu}Z$Wo?#OS*nTk?mob_JJ;Eu$=iN**HQcGlsiQ#Alx1uh(SAX_i~;?t-E z3cq=0JQZMpOF*+3qiw^Zv?7KzDVTQt+_eH{7iaF`&o39!AD@b8%1V2UKbkWew+Qaq z5e-5z7YB-!L}}IeC6pu!*v72A-)Hg?5lf)%e~MONc&(kuUss@fepe$4uD#}sJfYMNh zNAmo$La3v5AYa2Z#-*~N&92cq-7+-q>Zx4)IYTN0=9&2PyMu4fm#OBX^(%(-L>g|! zqUGGR{ja4VGY7xsUh-hd;o~WpC?KRg=eqmzTL0%-Qg6}k zPUGe6#|3*ZzK(QU{TYW+_0O7zxj-UXxdNeH?A`XNe_i;{RixtjIms`1) zJWnCdaR`q?Y)Ga1A`3uaAC2KwpmQK}A=XzMVLgZH3k2V>UB!(_!v@h~B++gKz3G%D zL&D3lvx{Hxn6Tg=mq)eC>}$(6YPsL#!q{P5*b6MvbcuUxI|Cn+gGaU7Y~@`-^b_h5 z?jPo8Livv?r5d(Ro^u5Q0CC7TQ@7GDPy^8@%X1ITIVP#WKT4ve@3_mPU-x^!{#>P1 z_OMYoke=Db*XzUp+9av8z;Z0oM5D}+zgf#0JnfQQP>o2P5*iV2PzyfA92i9lsTNQ! zj;$WeLRa(Q8@+l2oPC?u)TavQ>i~ylDO1IxlFv`ahtEwTf}@S^m>n76n{PhUp99g8 zg!!T{ju}KX={iYOmzk02h4zC~dwOGiXCx9KEdUPsbWrb=g68K36RchsgwOsYI+@9ZG~{vAXx< z>)Q{DCrxE8`m?MZBa}5zm3uvUoA#?;#Bx+RXvf;XGPsz*bd+GXn&Sl4|RQ~SwU zM#vdJce9kcLbENf4`oDM#}Jr7NL= zvck~@Xdzb)tNxAW|kL8LNj|(Lxs8N*Wj-ndMF6tpDBu9R@#%IZ3$FU`(viG@iW? zR%k^YYcPkc2BmuJX&MgKoF$a4N=-YSPh6?>YcNTb8 zb_HGoEuVquITJ}12t8Er$%I-HTboUKTq1=%at6g!IVx2zseHq^Ror)O^5abKpB6z* zi3WohKR7Ef5udJjSGtx}MbE0TSMeF}px&Il|KtHDO#o*+*=pB`IFxZtL_yfgZNuSM zCna3?z9e?&a7L+sD|(_%?gh_Yd2m7Vf=IVzaaTKDS3BQSEOIhqh8N1;N;WV3)T=>X zpFam(tmw{6Y-M!UjhM@sJMC#WCS5R&>PeTwg8+YcyTcLqOU~nj$7vZ3xR^VYX(5@S z@k^Ka&FewZR8}&AwX_T!9v}uOEDh-@QCsOaNwL4T!DOJsmABt{?J8lH+#|lglW@A2 zv1xU(R8aH;<%fW1=jAP8_A>5z8O}SBaDY(XbCpfon$CFyR z4C-UB6Loz!b(_n1tsFOdq4T_r>=XO$XmO)3UHiIJ-A|5F^SJ|Ji;0!s@#fVbz7w_= zQuA<$r(_%w;`9Yus){KhCO&&MA_YSZYmP`6SO@Y`|2L$E)6B-p#CKOBKa`pTq<$*X zPjnlMen$@(Z&o9p$_OWc!ik?*QXi#*&y!+JmAx(dhsek36fOm|xJH}|icTrri(3a6 z`C&l$xF5Itk3;eU+tjFJZqW)w;&3}g#{P{op{;l{sPt>13YW_nz zte^00GV?k>Yggfg+Cwms(5xqGZJF4 zqxe6|Oz(f1dEh_r|1uxz4O^S@7}C%(@>}Z)$9<)lPuiy|KGN9z7t!mHAI4Q@1Rk1PGfC@6YDIa%#}px_s5TZq@OvFfgR0M5IIxB# z*d96p1F7^0;tD*N%0b5%K4RiR0#qQ)rX+sKa4&qJj3PHNb)7BVz;bsW1+a0!5(WT~ z0i?8eVjuAIj4mT;AJ1Y=B9~+XX*w<>FKiuRtw5UM51%QZFdfNN1}xB>?6F%T->EoU z@R>h9?B_E6d_aD_XFqq4pL^raBj)Gf`LiteSzZ0C8-JGHKO2ibw`Gd=DvWwFbkhmRmN_5Cu@>v-fm})nsshDAU3z}7aw*UYD From a6020a54187ff8f473b1bccae3229846b7716258 Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Mon, 17 Apr 2017 12:13:19 +0300 Subject: [PATCH 0927/1679] Credits to the bottom --- Dijkstra Algorithm/README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Dijkstra Algorithm/README.md b/Dijkstra Algorithm/README.md index 10166a63f..bf158def9 100644 --- a/Dijkstra Algorithm/README.md +++ b/Dijkstra Algorithm/README.md @@ -1,6 +1,4 @@ # Dijkstra-algorithm -WWDC 2017 Scholarship Project -Created by [Taras Nikulin](https://github.com/crabman448) ## About Dijkstra's algorithm is used for finding shortest paths from start vertex in graph(with weighted vertices) to all other vertices. @@ -17,3 +15,7 @@ Click the link: [YouTube](https://youtu.be/PPESI7et0cQ) ## Screenshots + +## Credits +WWDC 2017 Scholarship Project +Created by [Taras Nikulin](https://github.com/crabman448) From a76764eaa0907a8ec455f911af14a0ad27087a95 Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Mon, 17 Apr 2017 12:16:05 +0300 Subject: [PATCH 0928/1679] Moved Vertex and Dijkstra classes to sources --- .../Dijkstra.playground/Contents.swift | 69 ------------------- .../Sources/Dijkstra.swift | 40 +++++++++++ .../Dijkstra.playground/Sources/Vertex.swift | 29 ++++++++ 3 files changed, 69 insertions(+), 69 deletions(-) create mode 100644 Dijkstra Algorithm/Dijkstra.playground/Sources/Dijkstra.swift create mode 100644 Dijkstra Algorithm/Dijkstra.playground/Sources/Vertex.swift diff --git a/Dijkstra Algorithm/Dijkstra.playground/Contents.swift b/Dijkstra Algorithm/Dijkstra.playground/Contents.swift index 13087a8f9..cd08e26fb 100644 --- a/Dijkstra Algorithm/Dijkstra.playground/Contents.swift +++ b/Dijkstra Algorithm/Dijkstra.playground/Contents.swift @@ -1,74 +1,5 @@ //: Playground - noun: a place where people can play - import Foundation -import UIKit - -open class Vertex: Hashable, Equatable { - - open var identifier: String! - open var neighbors: [(Vertex, Double)] = [] - open var pathLengthFromStart: Double = Double.infinity - open var pathVerticesFromStart: [Vertex] = [] - - public init(identifier: String) { - self.identifier = identifier - } - - open var hashValue: Int { - return self.identifier.hashValue - } - - public static func ==(lhs: Vertex, rhs: Vertex) -> Bool { - if lhs.hashValue == rhs.hashValue { - return true - } - return false - } - - open func clearCache() { - self.pathLengthFromStart = Double.infinity - self.pathVerticesFromStart = [] - } -} - -public class Dijkstra { - private var totalVertices: Set - - public init(vertices: Set) { - self.totalVertices = vertices - } - - private func clearCache() { - self.totalVertices.forEach { $0.clearCache() } - } - - public func findShortestPaths(from startVertex: Vertex) { - self.clearCache() - startVertex.pathLengthFromStart = 0 - startVertex.pathVerticesFromStart.append(startVertex) - var currentVertex: Vertex! = startVertex - while currentVertex != nil { - totalVertices.remove(currentVertex) - let filteredNeighbors = currentVertex.neighbors.filter { totalVertices.contains($0.0) } - for neighbor in filteredNeighbors { - let neighborVertex = neighbor.0 - let weight = neighbor.1 - - let theoreticNewWeight = currentVertex.pathLengthFromStart + weight - if theoreticNewWeight < neighborVertex.pathLengthFromStart { - neighborVertex.pathLengthFromStart = theoreticNewWeight - neighborVertex.pathVerticesFromStart = currentVertex.pathVerticesFromStart - neighborVertex.pathVerticesFromStart.append(neighborVertex) - } - } - if totalVertices.isEmpty { - currentVertex = nil - break - } - currentVertex = totalVertices.min { $0.pathLengthFromStart < $1.pathLengthFromStart } - } - } -} var _vertices: Set = Set() diff --git a/Dijkstra Algorithm/Dijkstra.playground/Sources/Dijkstra.swift b/Dijkstra Algorithm/Dijkstra.playground/Sources/Dijkstra.swift new file mode 100644 index 000000000..0ae83589e --- /dev/null +++ b/Dijkstra Algorithm/Dijkstra.playground/Sources/Dijkstra.swift @@ -0,0 +1,40 @@ +import Foundation + +public class Dijkstra { + private var totalVertices: Set + + public init(vertices: Set) { + self.totalVertices = vertices + } + + private func clearCache() { + self.totalVertices.forEach { $0.clearCache() } + } + + public func findShortestPaths(from startVertex: Vertex) { + self.clearCache() + startVertex.pathLengthFromStart = 0 + startVertex.pathVerticesFromStart.append(startVertex) + var currentVertex: Vertex! = startVertex + while currentVertex != nil { + totalVertices.remove(currentVertex) + let filteredNeighbors = currentVertex.neighbors.filter { totalVertices.contains($0.0) } + for neighbor in filteredNeighbors { + let neighborVertex = neighbor.0 + let weight = neighbor.1 + + let theoreticNewWeight = currentVertex.pathLengthFromStart + weight + if theoreticNewWeight < neighborVertex.pathLengthFromStart { + neighborVertex.pathLengthFromStart = theoreticNewWeight + neighborVertex.pathVerticesFromStart = currentVertex.pathVerticesFromStart + neighborVertex.pathVerticesFromStart.append(neighborVertex) + } + } + if totalVertices.isEmpty { + currentVertex = nil + break + } + currentVertex = totalVertices.min { $0.pathLengthFromStart < $1.pathLengthFromStart } + } + } +} diff --git a/Dijkstra Algorithm/Dijkstra.playground/Sources/Vertex.swift b/Dijkstra Algorithm/Dijkstra.playground/Sources/Vertex.swift new file mode 100644 index 000000000..035db2713 --- /dev/null +++ b/Dijkstra Algorithm/Dijkstra.playground/Sources/Vertex.swift @@ -0,0 +1,29 @@ +import Foundation + +open class Vertex: Hashable, Equatable { + + open var identifier: String! + open var neighbors: [(Vertex, Double)] = [] + open var pathLengthFromStart: Double = Double.infinity + open var pathVerticesFromStart: [Vertex] = [] + + public init(identifier: String) { + self.identifier = identifier + } + + open var hashValue: Int { + return self.identifier.hashValue + } + + public static func ==(lhs: Vertex, rhs: Vertex) -> Bool { + if lhs.hashValue == rhs.hashValue { + return true + } + return false + } + + open func clearCache() { + self.pathLengthFromStart = Double.infinity + self.pathVerticesFromStart = [] + } +} From 3bdb63de34cba4abcc581980c83da650bc8d3ba4 Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Mon, 17 Apr 2017 12:17:45 +0300 Subject: [PATCH 0929/1679] Hashable, Equatable to Extensions --- .../Dijkstra.playground/Sources/Vertex.swift | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/Dijkstra Algorithm/Dijkstra.playground/Sources/Vertex.swift b/Dijkstra Algorithm/Dijkstra.playground/Sources/Vertex.swift index 035db2713..67ba3791e 100644 --- a/Dijkstra Algorithm/Dijkstra.playground/Sources/Vertex.swift +++ b/Dijkstra Algorithm/Dijkstra.playground/Sources/Vertex.swift @@ -1,6 +1,6 @@ import Foundation -open class Vertex: Hashable, Equatable { +open class Vertex { open var identifier: String! open var neighbors: [(Vertex, Double)] = [] @@ -11,19 +11,23 @@ open class Vertex: Hashable, Equatable { self.identifier = identifier } + open func clearCache() { + self.pathLengthFromStart = Double.infinity + self.pathVerticesFromStart = [] + } +} + +extension Vertex: Hashable { open var hashValue: Int { return self.identifier.hashValue } +} +extension Vertex: Equatable { public static func ==(lhs: Vertex, rhs: Vertex) -> Bool { if lhs.hashValue == rhs.hashValue { return true } return false } - - open func clearCache() { - self.pathLengthFromStart = Double.infinity - self.pathVerticesFromStart = [] - } } From b2c5674b0c7d818cf061309e1cb7988e808d294b Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Mon, 17 Apr 2017 12:18:44 +0300 Subject: [PATCH 0930/1679] Removed simplicity unwrapped for initialized variable --- Dijkstra Algorithm/Dijkstra.playground/Sources/Vertex.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dijkstra Algorithm/Dijkstra.playground/Sources/Vertex.swift b/Dijkstra Algorithm/Dijkstra.playground/Sources/Vertex.swift index 67ba3791e..22c04a0e1 100644 --- a/Dijkstra Algorithm/Dijkstra.playground/Sources/Vertex.swift +++ b/Dijkstra Algorithm/Dijkstra.playground/Sources/Vertex.swift @@ -2,7 +2,7 @@ import Foundation open class Vertex { - open var identifier: String! + open var identifier: String open var neighbors: [(Vertex, Double)] = [] open var pathLengthFromStart: Double = Double.infinity open var pathVerticesFromStart: [Vertex] = [] From f0d057b89058c10cfe749990d5bdc3c669696610 Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Mon, 17 Apr 2017 12:19:34 +0300 Subject: [PATCH 0931/1679] Removed unnecessary explicit typing --- Dijkstra Algorithm/Dijkstra.playground/Sources/Vertex.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dijkstra Algorithm/Dijkstra.playground/Sources/Vertex.swift b/Dijkstra Algorithm/Dijkstra.playground/Sources/Vertex.swift index 22c04a0e1..dcdc64691 100644 --- a/Dijkstra Algorithm/Dijkstra.playground/Sources/Vertex.swift +++ b/Dijkstra Algorithm/Dijkstra.playground/Sources/Vertex.swift @@ -4,7 +4,7 @@ open class Vertex { open var identifier: String open var neighbors: [(Vertex, Double)] = [] - open var pathLengthFromStart: Double = Double.infinity + open var pathLengthFromStart = Double.infinity open var pathVerticesFromStart: [Vertex] = [] public init(identifier: String) { From d0c68887780424e343f6663391eb5d70998fe166 Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Mon, 17 Apr 2017 12:20:05 +0300 Subject: [PATCH 0932/1679] Refactor Equatable extension --- Dijkstra Algorithm/Dijkstra.playground/Sources/Vertex.swift | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Dijkstra Algorithm/Dijkstra.playground/Sources/Vertex.swift b/Dijkstra Algorithm/Dijkstra.playground/Sources/Vertex.swift index dcdc64691..89e66c68d 100644 --- a/Dijkstra Algorithm/Dijkstra.playground/Sources/Vertex.swift +++ b/Dijkstra Algorithm/Dijkstra.playground/Sources/Vertex.swift @@ -25,9 +25,6 @@ extension Vertex: Hashable { extension Vertex: Equatable { public static func ==(lhs: Vertex, rhs: Vertex) -> Bool { - if lhs.hashValue == rhs.hashValue { - return true - } - return false + return lhs.hashValue == rhs.hashValue } } From 222e96d2f221c2f0549b5292be8b60adee93e1de Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Mon, 17 Apr 2017 12:23:14 +0300 Subject: [PATCH 0933/1679] Made vertex optional --- .../Dijkstra.playground/Sources/Dijkstra.swift | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Dijkstra Algorithm/Dijkstra.playground/Sources/Dijkstra.swift b/Dijkstra Algorithm/Dijkstra.playground/Sources/Dijkstra.swift index 0ae83589e..f0a9386b4 100644 --- a/Dijkstra Algorithm/Dijkstra.playground/Sources/Dijkstra.swift +++ b/Dijkstra Algorithm/Dijkstra.playground/Sources/Dijkstra.swift @@ -15,18 +15,18 @@ public class Dijkstra { self.clearCache() startVertex.pathLengthFromStart = 0 startVertex.pathVerticesFromStart.append(startVertex) - var currentVertex: Vertex! = startVertex - while currentVertex != nil { - totalVertices.remove(currentVertex) - let filteredNeighbors = currentVertex.neighbors.filter { totalVertices.contains($0.0) } + var currentVertex: Vertex? = startVertex + while let vertex = currentVertex { + totalVertices.remove(vertex) + let filteredNeighbors = vertex.neighbors.filter { totalVertices.contains($0.0) } for neighbor in filteredNeighbors { let neighborVertex = neighbor.0 let weight = neighbor.1 - let theoreticNewWeight = currentVertex.pathLengthFromStart + weight + let theoreticNewWeight = vertex.pathLengthFromStart + weight if theoreticNewWeight < neighborVertex.pathLengthFromStart { neighborVertex.pathLengthFromStart = theoreticNewWeight - neighborVertex.pathVerticesFromStart = currentVertex.pathVerticesFromStart + neighborVertex.pathVerticesFromStart = vertex.pathVerticesFromStart neighborVertex.pathVerticesFromStart.append(neighborVertex) } } From e2561032e31912df5dab472f7d63a3900d05ac70 Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Mon, 17 Apr 2017 12:26:57 +0300 Subject: [PATCH 0934/1679] Removed unnecessary self --- .../Dijkstra.playground/Sources/Dijkstra.swift | 6 +++--- Dijkstra Algorithm/Dijkstra.playground/Sources/Vertex.swift | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Dijkstra Algorithm/Dijkstra.playground/Sources/Dijkstra.swift b/Dijkstra Algorithm/Dijkstra.playground/Sources/Dijkstra.swift index f0a9386b4..f4cd8503a 100644 --- a/Dijkstra Algorithm/Dijkstra.playground/Sources/Dijkstra.swift +++ b/Dijkstra Algorithm/Dijkstra.playground/Sources/Dijkstra.swift @@ -4,15 +4,15 @@ public class Dijkstra { private var totalVertices: Set public init(vertices: Set) { - self.totalVertices = vertices + totalVertices = vertices } private func clearCache() { - self.totalVertices.forEach { $0.clearCache() } + totalVertices.forEach { $0.clearCache() } } public func findShortestPaths(from startVertex: Vertex) { - self.clearCache() + clearCache() startVertex.pathLengthFromStart = 0 startVertex.pathVerticesFromStart.append(startVertex) var currentVertex: Vertex? = startVertex diff --git a/Dijkstra Algorithm/Dijkstra.playground/Sources/Vertex.swift b/Dijkstra Algorithm/Dijkstra.playground/Sources/Vertex.swift index 89e66c68d..a3587e04e 100644 --- a/Dijkstra Algorithm/Dijkstra.playground/Sources/Vertex.swift +++ b/Dijkstra Algorithm/Dijkstra.playground/Sources/Vertex.swift @@ -12,14 +12,14 @@ open class Vertex { } open func clearCache() { - self.pathLengthFromStart = Double.infinity - self.pathVerticesFromStart = [] + pathLengthFromStart = Double.infinity + pathVerticesFromStart = [] } } extension Vertex: Hashable { open var hashValue: Int { - return self.identifier.hashValue + return identifier.hashValue } } From 5060d788da63363809c93996aa9851751131e2d2 Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Mon, 17 Apr 2017 12:53:05 +0300 Subject: [PATCH 0935/1679] Removed self, unnecessary imports --- .../Sources/CustomUI/EdgeRepresentation.swift | 24 +- .../Sources/CustomUI/ErrorView.swift | 23 +- .../Sources/CustomUI/MyShapeLayer.swift | 1 - .../Sources/CustomUI/RoundedButton.swift | 8 +- .../Sources/CustomUI/VertexView.swift | 48 ++-- .../Sources/Graph.swift | 84 +++--- .../Sources/GraphView.swift | 62 ++-- .../Sources/SimpleObjects/Vertex.swift | 59 ++-- .../Sources/Window.swift | 272 +++++++++--------- 9 files changed, 291 insertions(+), 290 deletions(-) diff --git a/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/EdgeRepresentation.swift b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/EdgeRepresentation.swift index 5ff656dab..d827d3924 100644 --- a/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/EdgeRepresentation.swift +++ b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/EdgeRepresentation.swift @@ -1,6 +1,6 @@ import UIKit -public class EdgeRepresentation: Equatable { +public class EdgeRepresentation { private var graphColors: GraphColors = GraphColors.sharedInstance public private(set)var label: UILabel! @@ -67,7 +67,7 @@ public class EdgeRepresentation: Equatable { let label = UILabel(frame: CGRect(origin: circleOrigin, size: CGSize(width: arcDiameter, height: arcDiameter))) label.textAlignment = .center - label.backgroundColor = self.graphColors.defaultEdgeColor + label.backgroundColor = graphColors.defaultEdgeColor label.clipsToBounds = true label.adjustsFontSizeToFitWidth = true label.layer.cornerRadius = arcDiameter / 2 @@ -75,35 +75,35 @@ public class EdgeRepresentation: Equatable { let shapeLayer = MyShapeLayer() shapeLayer.path = path.cgPath - shapeLayer.strokeColor = self.graphColors.defaultEdgeColor.cgColor + shapeLayer.strokeColor = graphColors.defaultEdgeColor.cgColor shapeLayer.fillColor = UIColor.clear.cgColor shapeLayer.lineWidth = 2.0 shapeLayer.startPoint = startPoint shapeLayer.endPoint = endPoint shapeLayer.actions = ["position" : NSNull(), "bounds" : NSNull(), "path" : NSNull()] + self.layer = shapeLayer self.label = label self.label.text = "\(weight)" } public func setCheckingColor() { - self.layer.strokeColor = self.graphColors.checkingColor.cgColor - self.label.backgroundColor = self.graphColors.checkingColor + layer.strokeColor = graphColors.checkingColor.cgColor + label.backgroundColor = graphColors.checkingColor } public func setDefaultColor() { - self.layer.strokeColor = self.graphColors.defaultEdgeColor.cgColor - self.label.backgroundColor = self.graphColors.defaultEdgeColor + layer.strokeColor = graphColors.defaultEdgeColor.cgColor + label.backgroundColor = graphColors.defaultEdgeColor } public func setText(text: String) { - self.label.text = text + label.text = text } +} +extension EdgeRepresentation: Equatable { public static func ==(lhs: EdgeRepresentation, rhs: EdgeRepresentation) -> Bool { - if lhs.label.hashValue == rhs.label.hashValue && lhs.layer.hashValue == rhs.layer.hashValue { - return true - } - return false + return lhs.label.hashValue == rhs.label.hashValue && lhs.layer.hashValue == rhs.layer.hashValue } } diff --git a/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/ErrorView.swift b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/ErrorView.swift index 69874e5d7..a63655dd9 100644 --- a/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/ErrorView.swift +++ b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/ErrorView.swift @@ -2,9 +2,10 @@ import UIKit public class ErrorView: UIView { private var label: UILabel! + public override init(frame: CGRect) { super.init(frame: frame) - self.commonInit() + commonInit() } public required init?(coder aDecoder: NSCoder) { @@ -12,19 +13,19 @@ public class ErrorView: UIView { } private func commonInit() { - self.backgroundColor = UIColor(red: 242/255, green: 156/255, blue: 84/255, alpha: 1) - self.layer.cornerRadius = 10 + backgroundColor = UIColor(red: 242/255, green: 156/255, blue: 84/255, alpha: 1) + layer.cornerRadius = 10 - let labelFrame = CGRect(x: 10, y: 10, width: self.frame.width - 20, height: self.frame.height - 20) - self.label = UILabel(frame: labelFrame) - self.label.numberOfLines = 0 - self.label.adjustsFontSizeToFitWidth = true - self.label.textAlignment = .center - self.label.textColor = UIColor.white - self.addSubview(self.label) + let labelFrame = CGRect(x: 10, y: 10, width: frame.width - 20, height: frame.height - 20) + label = UILabel(frame: labelFrame) + label.numberOfLines = 0 + label.adjustsFontSizeToFitWidth = true + label.textAlignment = .center + label.textColor = UIColor.white + addSubview(label) } public func setText(text: String) { - self.label.text = text + label.text = text } } diff --git a/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/MyShapeLayer.swift b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/MyShapeLayer.swift index 54147f5e1..33bf4a515 100644 --- a/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/MyShapeLayer.swift +++ b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/MyShapeLayer.swift @@ -1,4 +1,3 @@ -import Foundation import UIKit public class MyShapeLayer: CAShapeLayer { diff --git a/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/RoundedButton.swift b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/RoundedButton.swift index 2647c4525..819fcfc5c 100644 --- a/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/RoundedButton.swift +++ b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/RoundedButton.swift @@ -5,7 +5,7 @@ public class RoundedButton: UIButton { public override init(frame: CGRect) { super.init(frame: frame) - self.commonInit() + commonInit() } public required init?(coder aDecoder: NSCoder) { @@ -13,8 +13,8 @@ public class RoundedButton: UIButton { } private func commonInit() { - self.backgroundColor = self.graphColors.buttonsBackgroundColor - self.titleLabel?.adjustsFontSizeToFitWidth = true - self.layer.cornerRadius = 7 + backgroundColor = graphColors.buttonsBackgroundColor + titleLabel?.adjustsFontSizeToFitWidth = true + layer.cornerRadius = 7 } } diff --git a/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/VertexView.swift b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/VertexView.swift index 29c971411..e785e120b 100644 --- a/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/VertexView.swift +++ b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/VertexView.swift @@ -15,49 +15,49 @@ public class VertexView: UIButton { precondition(frame.height == frame.width) precondition(frame.height >= 30) super.init(frame: frame) - self.backgroundColor = self.graphColors.defaultVertexColor - self.layer.cornerRadius = frame.width / 2 - self.clipsToBounds = true - self.setupIdLabel() - self.setupPathLengthFromStartLabel() + backgroundColor = graphColors.defaultVertexColor + layer.cornerRadius = frame.width / 2 + clipsToBounds = true + setupIdLabel() + setupPathLengthFromStartLabel() } private func setupIdLabel() { - let x: CGFloat = self.frame.width * 0.2 + let x: CGFloat = frame.width * 0.2 let y: CGFloat = 0 - let width: CGFloat = self.frame.width * 0.6 - let height: CGFloat = self.frame.height / 2 + let width: CGFloat = frame.width * 0.6 + let height: CGFloat = frame.height / 2 let idLabelFrame = CGRect(x: x, y: y, width: width, height: height) - self.idLabel = UILabel(frame: idLabelFrame) - self.idLabel.textAlignment = .center - self.idLabel.adjustsFontSizeToFitWidth = true - self.addSubview(self.idLabel) + idLabel = UILabel(frame: idLabelFrame) + idLabel.textAlignment = .center + idLabel.adjustsFontSizeToFitWidth = true + addSubview(idLabel) } private func setupPathLengthFromStartLabel() { - let x: CGFloat = self.frame.width * 0.2 - let y: CGFloat = self.frame.height / 2 - let width: CGFloat = self.frame.width * 0.6 - let height: CGFloat = self.frame.height / 2 + let x: CGFloat = frame.width * 0.2 + let y: CGFloat = frame.height / 2 + let width: CGFloat = frame.width * 0.6 + let height: CGFloat = frame.height / 2 let pathLengthLabelFrame = CGRect(x: x, y: y, width: width, height: height) - self.pathLengthLabel = UILabel(frame: pathLengthLabelFrame) - self.pathLengthLabel.textAlignment = .center - self.pathLengthLabel.adjustsFontSizeToFitWidth = true - self.addSubview(self.pathLengthLabel) + pathLengthLabel = UILabel(frame: pathLengthLabelFrame) + pathLengthLabel.textAlignment = .center + pathLengthLabel.adjustsFontSizeToFitWidth = true + addSubview(pathLengthLabel) } public func setIdLabel(text: String) { - self.idLabel.text = text + idLabel.text = text } public func setPathLengthLabel(text: String) { - self.pathLengthLabel.text = text + pathLengthLabel.text = text } public func setLabelsTextColor(color: UIColor) { - self.idLabel.textColor = color - self.pathLengthLabel.textColor = color + idLabel.textColor = color + pathLengthLabel.textColor = color } } diff --git a/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/Graph.swift b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/Graph.swift index 0b0b97b92..7c4a8e373 100644 --- a/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/Graph.swift +++ b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/Graph.swift @@ -22,20 +22,20 @@ public class Graph { public var startVertex: Vertex! public var interactiveNeighborCheckAnimationDuration: Double = 1.8 { didSet { - self._interactiveOneSleepDuration = UInt32(self.interactiveNeighborCheckAnimationDuration * 1000000.0 / 3.0) + _interactiveOneSleepDuration = UInt32(interactiveNeighborCheckAnimationDuration * 1000000.0 / 3.0) } } private var _interactiveOneSleepDuration: UInt32 = 600000 public var visualizationNeighborCheckAnimationDuration: Double = 2.25 { didSet { - self._visualizationOneSleepDuration = UInt32(self.visualizationNeighborCheckAnimationDuration * 1000000.0 / 3.0) + _visualizationOneSleepDuration = UInt32(visualizationNeighborCheckAnimationDuration * 1000000.0 / 3.0) } } private var _visualizationOneSleepDuration: UInt32 = 750000 public var vertices: Set { - return self._vertices + return _vertices } public init(verticesCount: UInt) { @@ -43,46 +43,46 @@ public class Graph { } public func removeGraph() { - self._vertices.removeAll() - self.startVertex = nil + _vertices.removeAll() + startVertex = nil } public func createNewGraph() { - guard self._vertices.isEmpty, self.startVertex == nil else { + guard _vertices.isEmpty, startVertex == nil else { assertionFailure("Clear graph before creating new one") return } - self.createNotConnectedVertices() - self.setupConnections() - let offset = Int(arc4random_uniform(UInt32(self._vertices.count))) - let index = self._vertices.index(self._vertices.startIndex, offsetBy: offset) - self.startVertex = self._vertices[index] - self.setVertexLevels() + createNotConnectedVertices() + setupConnections() + let offset = Int(arc4random_uniform(UInt32(_vertices.count))) + let index = _vertices.index(_vertices.startIndex, offsetBy: offset) + startVertex = _vertices[index] + setVertexLevels() } private func clearCache() { - self._vertices.forEach { $0.clearCache() } + _vertices.forEach { $0.clearCache() } } public func reset() { - for vertex in self._vertices { + for vertex in _vertices { vertex.clearCache() } } private func createNotConnectedVertices() { - for i in 0.. Vertex { - var newSet = self._vertices + var newSet = _vertices newSet.remove(vertex) let offset = Int(arc4random_uniform(UInt32(newSet.count))) let index = newSet.index(newSet.startIndex, offsetBy: offset) @@ -103,8 +103,8 @@ public class Graph { } private func setVertexLevels() { - self._vertices.forEach { $0.clearLevelInfo() } - guard let startVertex = self.startVertex else { + _vertices.forEach { $0.clearLevelInfo() } + guard let startVertex = startVertex else { assertionFailure() return } @@ -127,21 +127,21 @@ public class Graph { } public func findShortestPathsWithVisualization(completion: () -> Void) { - self.clearCache() + clearCache() startVertex.pathLengthFromStart = 0 - startVertex.pathVerticesFromStart.append(self.startVertex) - var currentVertex: Vertex! = self.startVertex + startVertex.pathVerticesFromStart.append(startVertex) + var currentVertex: Vertex! = startVertex - var totalVertices = self._vertices + var totalVertices = _vertices breakableLoop: while currentVertex != nil { totalVertices.remove(currentVertex) - while self.pauseVisualization == true { - if self.stopVisualization == true { + while pauseVisualization == true { + if stopVisualization == true { break breakableLoop } } - if self.stopVisualization == true { + if stopVisualization == true { break breakableLoop } DispatchQueue.main.async { @@ -155,12 +155,12 @@ public class Graph { let weight = edge.weight let edgeRepresentation = edge.edgeRepresentation - while self.pauseVisualization == true { - if self.stopVisualization == true { + while pauseVisualization == true { + if stopVisualization == true { break breakableLoop } } - if self.stopVisualization == true { + if stopVisualization == true { break breakableLoop } DispatchQueue.main.async { @@ -170,32 +170,32 @@ public class Graph { edgePathLength: weight, endVertexPathLength: neighbor.pathLengthFromStart) } - usleep(self._visualizationOneSleepDuration) + usleep(_visualizationOneSleepDuration) let theoreticNewWeight = currentVertex.pathLengthFromStart + weight if theoreticNewWeight < neighbor.pathLengthFromStart { - while self.pauseVisualization == true { - if self.stopVisualization == true { + while pauseVisualization == true { + if stopVisualization == true { break breakableLoop } } - if self.stopVisualization == true { + if stopVisualization == true { break breakableLoop } neighbor.pathLengthFromStart = theoreticNewWeight neighbor.pathVerticesFromStart = currentVertex.pathVerticesFromStart neighbor.pathVerticesFromStart.append(neighbor) } - usleep(self._visualizationOneSleepDuration) + usleep(_visualizationOneSleepDuration) DispatchQueue.main.async { self.delegate?.didFinishCompare() edge.edgeRepresentation?.setDefaultColor() edge.neighbor.setDefaultColor() } - usleep(self._visualizationOneSleepDuration) + usleep(_visualizationOneSleepDuration) } if totalVertices.isEmpty { currentVertex = nil @@ -203,7 +203,7 @@ public class Graph { } currentVertex = totalVertices.min { $0.pathLengthFromStart < $1.pathLengthFromStart } } - if self.stopVisualization == true { + if stopVisualization == true { DispatchQueue.main.async { self.delegate?.didStop() } @@ -294,10 +294,10 @@ public class Graph { } public func didTapVertex(vertex: Vertex) { - if self.nextVertices.contains(vertex) { - self.delegate?.willStartVertexNeighborsChecking() - self.state = .parsing - self.parseNeighborsFor(vertex: vertex) { + if nextVertices.contains(vertex) { + delegate?.willStartVertexNeighborsChecking() + state = .parsing + parseNeighborsFor(vertex: vertex) { self.state = .interactiveVisualization self.delegate?.didFinishVertexNeighborsChecking() } diff --git a/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/GraphView.swift b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/GraphView.swift index 49bc6853f..bdeab7669 100644 --- a/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/GraphView.swift +++ b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/GraphView.swift @@ -7,7 +7,7 @@ public class GraphView: UIView { public override init(frame: CGRect) { super.init(frame: frame) - self.backgroundColor = self.graphColors.graphBackgroundColor + backgroundColor = graphColors.graphBackgroundColor } public required init?(coder aDecoder: NSCoder) { @@ -20,13 +20,13 @@ public class GraphView: UIView { } public func removeGraph() { - for vertex in self.graph.vertices { + for vertex in graph.vertices { if let view = vertex.view { view.removeFromSuperview() vertex.view = nil } } - for vertex in self.graph.vertices { + for vertex in graph.vertices { for edge in vertex.edges { if let edgeRepresentation = edge.edgeRepresentation { edgeRepresentation.layer.removeFromSuperlayer() @@ -38,41 +38,41 @@ public class GraphView: UIView { } public func createNewGraph() { - self.setupVertexViews() - self.setupEdgeRepresentations() - self.addGraph() + setupVertexViews() + setupEdgeRepresentations() + addGraph() } public func reset() { - for vertex in self.graph.vertices { + for vertex in graph.vertices { vertex.edges.forEach { $0.edgeRepresentation?.setDefaultColor() } vertex.setDefaultColor() } } private func addGraph() { - for vertex in self.graph.vertices { + for vertex in graph.vertices { for edge in vertex.edges { if let edgeRepresentation = edge.edgeRepresentation { - self.layer.addSublayer(edgeRepresentation.layer) - self.addSubview(edgeRepresentation.label) + layer.addSublayer(edgeRepresentation.layer) + addSubview(edgeRepresentation.label) } } } - for vertex in self.graph.vertices { + for vertex in graph.vertices { if let view = vertex.view { - self.addSubview(view) + addSubview(view) } } } private func setupVertexViews() { var level = 0 - var buildViewQueue = [self.graph.startVertex!] + var buildViewQueue = [graph.startVertex!] let itemWidth: CGFloat = 40 while !buildViewQueue.isEmpty { let levelItemsCount = CGFloat(buildViewQueue.count) - let xStep = (self.frame.width - levelItemsCount * itemWidth) / (levelItemsCount + 1) + let xStep = (frame.width - levelItemsCount * itemWidth) / (levelItemsCount + 1) var previousVertexMaxX: CGFloat = 0.0 for vertex in buildViewQueue { let x: CGFloat = previousVertexMaxX + xStep @@ -84,12 +84,12 @@ public class GraphView: UIView { vertexView.vertex = vertex vertex.view?.setIdLabel(text: vertex.identifier) vertex.view?.setPathLengthLabel(text: "\(vertex.pathLengthFromStart)") - vertex.view?.addTarget(self, action: #selector(self.didTapVertex(sender:)), for: .touchUpInside) - let panGesture = UIPanGestureRecognizer(target: self, action: #selector(self.handlePan(recognizer:))) + vertex.view?.addTarget(self, action: #selector(didTapVertex(sender:)), for: .touchUpInside) + let panGesture = UIPanGestureRecognizer(target: self, action: #selector(handlePan(recognizer:))) vertex.view?.addGestureRecognizer(panGesture) } level += 1 - buildViewQueue = self.graph.vertices.filter { $0.level == level } + buildViewQueue = graph.vertices.filter { $0.level == level } } } @@ -100,8 +100,8 @@ public class GraphView: UIView { guard let vertexView = recognizer.view as? VertexView, let vertex = vertexView.vertex else { return } - if self.panningView != nil { - if self.panningView != vertexView { + if panningView != nil { + if panningView != vertexView { return } } @@ -122,39 +122,39 @@ public class GraphView: UIView { } } } - self.panningView = vertexView + panningView = vertexView case .changed: - if self.movingVertexOutputEdges.isEmpty && self.movingVertexInputEdges.isEmpty { + if movingVertexOutputEdges.isEmpty && movingVertexInputEdges.isEmpty { return } let translation = recognizer.translation(in: self) if vertexView.frame.origin.x + translation.x <= 0 || vertexView.frame.origin.y + translation.y <= 0 - || (vertexView.frame.origin.x + vertexView.frame.width + translation.x) >= self.frame.width - || (vertexView.frame.origin.y + vertexView.frame.height + translation.y) >= self.frame.height { + || (vertexView.frame.origin.x + vertexView.frame.width + translation.x) >= frame.width + || (vertexView.frame.origin.y + vertexView.frame.height + translation.y) >= frame.height { break } - self.movingVertexInputEdges.forEach { edgeRepresentation in + movingVertexInputEdges.forEach { edgeRepresentation in let originalLabelCenter = edgeRepresentation.label.center edgeRepresentation.label.center = CGPoint(x: originalLabelCenter.x + translation.x * 0.625, y: originalLabelCenter.y + translation.y * 0.625) CATransaction.begin() CATransaction.setValue(kCFBooleanTrue, forKey: kCATransactionDisableActions) - let newPath = self.path(fromEdgeRepresentation: edgeRepresentation, movingVertex: vertex, translation: translation, outPath: false) + let newPath = path(fromEdgeRepresentation: edgeRepresentation, movingVertex: vertex, translation: translation, outPath: false) edgeRepresentation.layer.path = newPath CATransaction.commit() } - self.movingVertexOutputEdges.forEach { edgeRepresentation in + movingVertexOutputEdges.forEach { edgeRepresentation in let originalLabelCenter = edgeRepresentation.label.center edgeRepresentation.label.center = CGPoint(x: originalLabelCenter.x + translation.x * 0.375, y: originalLabelCenter.y + translation.y * 0.375) CATransaction.begin() CATransaction.setValue(kCFBooleanTrue, forKey: kCATransactionDisableActions) - let newPath = self.path(fromEdgeRepresentation: edgeRepresentation, movingVertex: vertex, translation: translation, outPath: true) + let newPath = path(fromEdgeRepresentation: edgeRepresentation, movingVertex: vertex, translation: translation, outPath: true) edgeRepresentation.layer.path = newPath CATransaction.commit() } @@ -163,9 +163,9 @@ public class GraphView: UIView { y: vertexView.center.y + translation.y) recognizer.setTranslation(CGPoint.zero, in: self) case .ended: - self.movingVertexInputEdges = [] - self.movingVertexOutputEdges = [] - self.panningView = nil + movingVertexInputEdges = [] + movingVertexOutputEdges = [] + panningView = nil default: break } @@ -223,7 +223,7 @@ public class GraphView: UIView { } private func setupEdgeRepresentations() { - var edgeQueue: [Vertex] = [self.graph.startVertex!] + var edgeQueue: [Vertex] = [graph.startVertex!] //BFS while !edgeQueue.isEmpty { diff --git a/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/SimpleObjects/Vertex.swift b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/SimpleObjects/Vertex.swift index c9270b0df..f18ec3114 100644 --- a/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/SimpleObjects/Vertex.swift +++ b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/SimpleObjects/Vertex.swift @@ -1,10 +1,17 @@ import UIKit -public class Vertex: Hashable, Equatable { +public class Vertex { private var graphColors: GraphColors = GraphColors.sharedInstance + public var view: VertexView? + public var identifier: String public var edges: [Edge] = [] + public var pathVerticesFromStart: [Vertex] = [] + public var level: Int = 0 + public var levelChecked: Bool = false + public var haveAllEdges: Bool = false + public var visited: Bool = false public var pathLengthFromStart: Double = Double.infinity { didSet { DispatchQueue.main.async { @@ -12,51 +19,45 @@ public class Vertex: Hashable, Equatable { } } } - public var pathVerticesFromStart: [Vertex] = [] - public var level: Int = 0 - public var levelChecked: Bool = false - public var haveAllEdges: Bool = false - public var visited: Bool = false - - public var view: VertexView? public init(identifier: String) { self.identifier = identifier } - public var hashValue: Int { - return self.identifier.hashValue - } - - public static func ==(lhs: Vertex, rhs: Vertex) -> Bool { - if lhs.hashValue == rhs.hashValue { - return true - } - return false - } - public func clearCache() { - self.pathLengthFromStart = Double.infinity - self.pathVerticesFromStart = [] - self.visited = false + pathLengthFromStart = Double.infinity + pathVerticesFromStart = [] + visited = false } public func clearLevelInfo() { - self.level = 0 - self.levelChecked = false + level = 0 + levelChecked = false } public func setVisitedColor() { - self.view?.backgroundColor = self.graphColors.visitedColor - self.view?.setLabelsTextColor(color: UIColor.white) + view?.backgroundColor = graphColors.visitedColor + view?.setLabelsTextColor(color: UIColor.white) } public func setCheckingPathColor() { - self.view?.backgroundColor = self.graphColors.checkingColor + view?.backgroundColor = graphColors.checkingColor } public func setDefaultColor() { - self.view?.backgroundColor = self.graphColors.defaultVertexColor - self.view?.setLabelsTextColor(color: UIColor.black) + view?.backgroundColor = graphColors.defaultVertexColor + view?.setLabelsTextColor(color: UIColor.black) + } +} + +extension Vertex: Hashable { + public var hashValue: Int { + return identifier.hashValue + } +} + +extension Vertex: Equatable { + public static func ==(lhs: Vertex, rhs: Vertex) -> Bool { + return lhs.hashValue == rhs.hashValue } } diff --git a/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/Window.swift b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/Window.swift index e8aabad27..054b804c9 100644 --- a/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/Window.swift +++ b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/Window.swift @@ -30,7 +30,7 @@ public class Window: UIView, GraphDelegate { public override init(frame: CGRect) { super.init(frame: frame) self.frame = frame - self.backgroundColor = self.graphColors.mainWindowBackgroundColor + backgroundColor = graphColors.mainWindowBackgroundColor } public required init?(coder aDecoder: NSCoder) { @@ -39,130 +39,130 @@ public class Window: UIView, GraphDelegate { public func configure(graph: Graph) { self.graph = graph - self.graph.createNewGraph() - self.graph.delegate = self + graph.createNewGraph() + graph.delegate = self let frame = CGRect(x: 10, y: 170, width: self.frame.width - 20, height: self.frame.height - 180) - self.graphView = GraphView(frame: frame) - self.graphView.layer.cornerRadius = 15 - - self.graphView.configure(graph: self.graph) - self.graphView.createNewGraph() - self.addSubview(self.graphView) - - self.configureCreateGraphButton() - self.configureStartVisualizationButton() - self.configureStartInteractiveVisualizationButton() - self.configureStartButton() - self.configurePauseButton() - self.configureStopButton() - self.configureComparisonLabel() - self.configureActivityIndicator() - - self.topView = UIView(frame: CGRect(x: 10, y: 10, width: self.frame.width - 20, height: 150)) - self.topView.backgroundColor = self.graphColors.topViewBackgroundColor - self.topView.layer.cornerRadius = 15 - self.addSubview(self.topView) - - self.topView.addSubview(self.createGraphButton) - self.topView.addSubview(self.startVisualizationButton) - self.topView.addSubview(self.startInteractiveVisualizationButton) - self.topView.addSubview(self.startButton) - self.topView.addSubview(self.pauseButton) - self.topView.addSubview(self.stopButton) - self.topView.addSubview(self.comparisonLabel) - self.topView.addSubview(self.activityIndicator) + graphView = GraphView(frame: frame) + graphView.layer.cornerRadius = 15 + + graphView.configure(graph: graph) + graphView.createNewGraph() + addSubview(graphView) + + configureCreateGraphButton() + configureStartVisualizationButton() + configureStartInteractiveVisualizationButton() + configureStartButton() + configurePauseButton() + configureStopButton() + configureComparisonLabel() + configureActivityIndicator() + + topView = UIView(frame: CGRect(x: 10, y: 10, width: frame.width - 20, height: 150)) + topView.backgroundColor = graphColors.topViewBackgroundColor + topView.layer.cornerRadius = 15 + addSubview(topView) + + topView.addSubview(createGraphButton) + topView.addSubview(startVisualizationButton) + topView.addSubview(startInteractiveVisualizationButton) + topView.addSubview(startButton) + topView.addSubview(pauseButton) + topView.addSubview(stopButton) + topView.addSubview(comparisonLabel) + topView.addSubview(activityIndicator) } private func configureCreateGraphButton() { - let frame = CGRect(x: self.center.x - 200, y: 12, width: 100, height: 34) - self.createGraphButton = RoundedButton(frame: frame) - self.createGraphButton.setTitle("New graph", for: .normal) - self.createGraphButton.addTarget(self, action: #selector(self.createGraphButtonTap), for: .touchUpInside) + let frame = CGRect(x: center.x - 200, y: 12, width: 100, height: 34) + createGraphButton = RoundedButton(frame: frame) + createGraphButton.setTitle("New graph", for: .normal) + createGraphButton.addTarget(self, action: #selector(createGraphButtonTap), for: .touchUpInside) } private func configureStartVisualizationButton() { - let frame = CGRect(x: self.center.x - 50, y: 12, width: 100, height: 34) - self.startVisualizationButton = RoundedButton(frame: frame) - self.startVisualizationButton.setTitle("Auto", for: .normal) - self.startVisualizationButton.addTarget(self, action: #selector(self.startVisualizationButtonDidTap), for: .touchUpInside) + let frame = CGRect(x: center.x - 50, y: 12, width: 100, height: 34) + startVisualizationButton = RoundedButton(frame: frame) + startVisualizationButton.setTitle("Auto", for: .normal) + startVisualizationButton.addTarget(self, action: #selector(startVisualizationButtonDidTap), for: .touchUpInside) } private func configureStartInteractiveVisualizationButton() { - let frame = CGRect(x: self.center.x + 100, y: 12, width: 100, height: 34) - self.startInteractiveVisualizationButton = RoundedButton(frame: frame) - self.startInteractiveVisualizationButton.setTitle("Interactive", for: .normal) - self.startInteractiveVisualizationButton.addTarget(self, action: #selector(self.startInteractiveVisualizationButtonDidTap), for: .touchUpInside) + let frame = CGRect(x: center.x + 100, y: 12, width: 100, height: 34) + startInteractiveVisualizationButton = RoundedButton(frame: frame) + startInteractiveVisualizationButton.setTitle("Interactive", for: .normal) + startInteractiveVisualizationButton.addTarget(self, action: #selector(startInteractiveVisualizationButtonDidTap), for: .touchUpInside) } private func configureStartButton() { - let frame = CGRect(x: self.center.x - 65, y: 56, width: 30, height: 30) - self.startButton = UIButton(frame: frame) + let frame = CGRect(x: center.x - 65, y: 56, width: 30, height: 30) + startButton = UIButton(frame: frame) let playImage = UIImage(named: "Start.png") - self.startButton.setImage(playImage, for: .normal) - self.startButton.isEnabled = false - self.startButton.addTarget(self, action: #selector(self.didTapStartButton), for: .touchUpInside) + startButton.setImage(playImage, for: .normal) + startButton.isEnabled = false + startButton.addTarget(self, action: #selector(didTapStartButton), for: .touchUpInside) } private func configurePauseButton() { - let frame = CGRect(x: self.center.x - 15, y: 56, width: 30, height: 30) - self.pauseButton = UIButton(frame: frame) + let frame = CGRect(x: center.x - 15, y: 56, width: 30, height: 30) + pauseButton = UIButton(frame: frame) let pauseImage = UIImage(named: "Pause.png") - self.pauseButton.setImage(pauseImage, for: .normal) - self.pauseButton.isEnabled = false - self.pauseButton.addTarget(self, action: #selector(self.didTapPauseButton), for: .touchUpInside) + pauseButton.setImage(pauseImage, for: .normal) + pauseButton.isEnabled = false + pauseButton.addTarget(self, action: #selector(didTapPauseButton), for: .touchUpInside) } private func configureStopButton() { - let frame = CGRect(x: self.center.x + 35, y: 56, width: 30, height: 30) - self.stopButton = UIButton(frame: frame) + let frame = CGRect(x: center.x + 35, y: 56, width: 30, height: 30) + stopButton = UIButton(frame: frame) let stopImage = UIImage(named: "Stop.png") - self.stopButton.setImage(stopImage, for: .normal) - self.stopButton.isEnabled = false - self.stopButton.addTarget(self, action: #selector(self.didTapStopButton), for: .touchUpInside) + stopButton.setImage(stopImage, for: .normal) + stopButton.isEnabled = false + stopButton.addTarget(self, action: #selector(didTapStopButton), for: .touchUpInside) } private func configureComparisonLabel() { let size = CGSize(width: 250, height: 42) - let origin = CGPoint(x: self.center.x - 125, y: 96) + let origin = CGPoint(x: center.x - 125, y: 96) let frame = CGRect(origin: origin, size: size) - self.comparisonLabel = UILabel(frame: frame) - self.comparisonLabel.textAlignment = .center - self.comparisonLabel.text = "Have fun!" + comparisonLabel = UILabel(frame: frame) + comparisonLabel.textAlignment = .center + comparisonLabel.text = "Have fun!" } private func configureActivityIndicator() { let size = CGSize(width: 50, height: 42) - let origin = CGPoint(x: self.center.x - 25, y: 100) + let origin = CGPoint(x: center.x - 25, y: 100) let activityIndicatorFrame = CGRect(origin: origin, size: size) - self.activityIndicator = UIActivityIndicatorView(frame: activityIndicatorFrame) - self.activityIndicator.activityIndicatorViewStyle = .whiteLarge + activityIndicator = UIActivityIndicatorView(frame: activityIndicatorFrame) + activityIndicator.activityIndicatorViewStyle = .whiteLarge } @objc private func createGraphButtonTap() { - self.comparisonLabel.text = "" - self.graphView.removeGraph() - self.graph.removeGraph() - self.graph.createNewGraph() - self.graphView.createNewGraph() - self.graph.state = .initial + comparisonLabel.text = "" + graphView.removeGraph() + graph.removeGraph() + graph.createNewGraph() + graphView.createNewGraph() + graph.state = .initial } @objc private func startVisualizationButtonDidTap() { - self.comparisonLabel.text = "" - self.pauseButton.isEnabled = true - self.stopButton.isEnabled = true - self.createGraphButton.isEnabled = false - self.startVisualizationButton.isEnabled = false - self.startInteractiveVisualizationButton.isEnabled = false - self.createGraphButton.alpha = 0.5 - self.startVisualizationButton.alpha = 0.5 - self.startInteractiveVisualizationButton.alpha = 0.5 - - if self.graph.state == .completed { - self.graphView.reset() - self.graph.reset() + comparisonLabel.text = "" + pauseButton.isEnabled = true + stopButton.isEnabled = true + createGraphButton.isEnabled = false + startVisualizationButton.isEnabled = false + startInteractiveVisualizationButton.isEnabled = false + createGraphButton.alpha = 0.5 + startVisualizationButton.alpha = 0.5 + startInteractiveVisualizationButton.alpha = 0.5 + + if graph.state == .completed { + graphView.reset() + graph.reset() } - self.graph.state = .autoVisualization + graph.state = .autoVisualization DispatchQueue.global(qos: .background).async { self.graph.findShortestPathsWithVisualization { self.graph.state = .completed @@ -184,25 +184,25 @@ public class Window: UIView, GraphDelegate { } @objc private func startInteractiveVisualizationButtonDidTap() { - self.comparisonLabel.text = "" - self.pauseButton.isEnabled = true - self.stopButton.isEnabled = true - self.createGraphButton.isEnabled = false - self.startVisualizationButton.isEnabled = false - self.startInteractiveVisualizationButton.isEnabled = false - self.createGraphButton.alpha = 0.5 - self.startVisualizationButton.alpha = 0.5 - self.startInteractiveVisualizationButton.alpha = 0.5 - - if self.graph.state == .completed { - self.graphView.reset() - self.graph.reset() + comparisonLabel.text = "" + pauseButton.isEnabled = true + stopButton.isEnabled = true + createGraphButton.isEnabled = false + startVisualizationButton.isEnabled = false + startInteractiveVisualizationButton.isEnabled = false + createGraphButton.alpha = 0.5 + startVisualizationButton.alpha = 0.5 + startInteractiveVisualizationButton.alpha = 0.5 + + if graph.state == .completed { + graphView.reset() + graph.reset() } - self.graph.startVertex.pathLengthFromStart = 0 - self.graph.startVertex.pathVerticesFromStart.append(self.graph.startVertex) - self.graph.state = .parsing - self.graph.parseNeighborsFor(vertex: self.graph.startVertex) { + graph.startVertex.pathLengthFromStart = 0 + graph.startVertex.pathVerticesFromStart.append(graph.startVertex) + graph.state = .parsing + graph.parseNeighborsFor(vertex: graph.startVertex) { self.graph.state = .interactiveVisualization DispatchQueue.main.async { self.comparisonLabel.text = "Pick next vertex" @@ -211,43 +211,43 @@ public class Window: UIView, GraphDelegate { } @objc private func didTapStartButton() { - self.startButton.isEnabled = false - self.pauseButton.isEnabled = true + startButton.isEnabled = false + pauseButton.isEnabled = true DispatchQueue.global(qos: .utility).async { self.graph.pauseVisualization = false } } @objc private func didTapPauseButton() { - self.startButton.isEnabled = true - self.pauseButton.isEnabled = false + startButton.isEnabled = true + pauseButton.isEnabled = false DispatchQueue.global(qos: .utility).async { self.graph.pauseVisualization = true } } @objc private func didTapStopButton() { - self.startButton.isEnabled = false - self.pauseButton.isEnabled = false - self.comparisonLabel.text = "" - self.activityIndicator.startAnimating() - if self.graph.state == .parsing || self.graph.state == .autoVisualization { - self.graph.stopVisualization = true - } else if self.graph.state == .interactiveVisualization { - self.didStop() + startButton.isEnabled = false + pauseButton.isEnabled = false + comparisonLabel.text = "" + activityIndicator.startAnimating() + if graph.state == .parsing || graph.state == .autoVisualization { + graph.stopVisualization = true + } else if graph.state == .interactiveVisualization { + didStop() } } private func setButtonsToInitialState() { - self.createGraphButton.isEnabled = true - self.startVisualizationButton.isEnabled = true - self.startInteractiveVisualizationButton.isEnabled = true - self.startButton.isEnabled = false - self.pauseButton.isEnabled = false - self.stopButton.isEnabled = false - self.createGraphButton.alpha = 1 - self.startVisualizationButton.alpha = 1 - self.startInteractiveVisualizationButton.alpha = 1 + createGraphButton.isEnabled = true + startVisualizationButton.isEnabled = true + startInteractiveVisualizationButton.isEnabled = true + startButton.isEnabled = false + pauseButton.isEnabled = false + stopButton.isEnabled = false + createGraphButton.alpha = 1 + startVisualizationButton.alpha = 1 + startInteractiveVisualizationButton.alpha = 1 } private func showError(error: String) { @@ -268,14 +268,14 @@ public class Window: UIView, GraphDelegate { // MARK: GraphDelegate public func didCompleteGraphParsing() { - self.graph.state = .completed - self.setButtonsToInitialState() - self.comparisonLabel.text = "Completed!" + graph.state = .completed + setButtonsToInitialState() + comparisonLabel.text = "Completed!" } public func didTapWrongVertex() { - if !self.subviews.contains { $0 is ErrorView } { - self.showError(error: "You have picked wrong next vertex") + if !subviews.contains { $0 is ErrorView } { + showError(error: "You have picked wrong next vertex") } } @@ -296,13 +296,13 @@ public class Window: UIView, GraphDelegate { } public func didStop() { - self.graph.state = .initial - self.graph.stopVisualization = false - self.graph.pauseVisualization = false - self.graphView.reset() - self.graph.reset() - self.setButtonsToInitialState() - self.activityIndicator.stopAnimating() + graph.state = .initial + graph.stopVisualization = false + graph.pauseVisualization = false + graphView.reset() + graph.reset() + setButtonsToInitialState() + activityIndicator.stopAnimating() } public func willStartVertexNeighborsChecking() { From 900b7caf229697f5666627bd7cdc34c6f1143702 Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Mon, 17 Apr 2017 12:56:12 +0300 Subject: [PATCH 0936/1679] Replaced with optional --- .../Sources/Graph.swift | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/Graph.swift b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/Graph.swift index 7c4a8e373..8bf2452cc 100644 --- a/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/Graph.swift +++ b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/Graph.swift @@ -130,12 +130,12 @@ public class Graph { clearCache() startVertex.pathLengthFromStart = 0 startVertex.pathVerticesFromStart.append(startVertex) - var currentVertex: Vertex! = startVertex + var currentVertex: Vertex? = startVertex var totalVertices = _vertices - breakableLoop: while currentVertex != nil { - totalVertices.remove(currentVertex) + breakableLoop: while let vertex = currentVertex { + totalVertices.remove(vertex) while pauseVisualization == true { if stopVisualization == true { break breakableLoop @@ -145,11 +145,11 @@ public class Graph { break breakableLoop } DispatchQueue.main.async { - currentVertex.setVisitedColor() + vertex.setVisitedColor() } usleep(750000) - currentVertex.visited = true - let filteredEdges = currentVertex.edges.filter { !$0.neighbor.visited } + vertex.visited = true + let filteredEdges = vertex.edges.filter { !$0.neighbor.visited } for edge in filteredEdges { let neighbor = edge.neighbor let weight = edge.weight @@ -166,14 +166,14 @@ public class Graph { DispatchQueue.main.async { edgeRepresentation?.setCheckingColor() neighbor.setCheckingPathColor() - self.delegate?.willCompareVertices(startVertexPathLength: currentVertex.pathLengthFromStart, + self.delegate?.willCompareVertices(startVertexPathLength: vertex.pathLengthFromStart, edgePathLength: weight, endVertexPathLength: neighbor.pathLengthFromStart) } usleep(_visualizationOneSleepDuration) - let theoreticNewWeight = currentVertex.pathLengthFromStart + weight + let theoreticNewWeight = vertex.pathLengthFromStart + weight if theoreticNewWeight < neighbor.pathLengthFromStart { while pauseVisualization == true { @@ -185,7 +185,7 @@ public class Graph { break breakableLoop } neighbor.pathLengthFromStart = theoreticNewWeight - neighbor.pathVerticesFromStart = currentVertex.pathVerticesFromStart + neighbor.pathVerticesFromStart = vertex.pathVerticesFromStart neighbor.pathVerticesFromStart.append(neighbor) } usleep(_visualizationOneSleepDuration) From 2a1a2a1a7bbdf738b8643d49775ccf7895d476b6 Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Mon, 17 Apr 2017 13:27:18 +0300 Subject: [PATCH 0937/1679] Refactored a bit --- .../Sources/Graph.swift | 14 ++++++++------ .../Sources/GraphView.swift | 12 +++++------- .../Sources/Window.swift | 19 +++++++++++-------- 3 files changed, 24 insertions(+), 21 deletions(-) diff --git a/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/Graph.swift b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/Graph.swift index 8bf2452cc..447b3dbe1 100644 --- a/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/Graph.swift +++ b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/Graph.swift @@ -10,16 +10,14 @@ public enum GraphState { } public class Graph { - private init() { } - - private var verticesCount: UInt! + private var verticesCount: UInt private var _vertices: Set = Set() public weak var delegate: GraphDelegate? public var nextVertices: [Vertex] = [] public var state: GraphState = .initial - public var pauseVisualization: Bool = false - public var stopVisualization: Bool = false - public var startVertex: Vertex! + public var pauseVisualization = false + public var stopVisualization = false + public var startVertex: Vertex? public var interactiveNeighborCheckAnimationDuration: Double = 1.8 { didSet { _interactiveOneSleepDuration = UInt32(interactiveNeighborCheckAnimationDuration * 1000000.0 / 3.0) @@ -127,6 +125,10 @@ public class Graph { } public func findShortestPathsWithVisualization(completion: () -> Void) { + guard let startVertex = self.startVertex else { + assertionFailure("start vertex is nil") + return + } clearCache() startVertex.pathLengthFromStart = 0 startVertex.pathVerticesFromStart.append(startVertex) diff --git a/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/GraphView.swift b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/GraphView.swift index bdeab7669..ec4f74705 100644 --- a/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/GraphView.swift +++ b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/GraphView.swift @@ -1,13 +1,15 @@ import UIKit public class GraphView: UIView { - private var graph: Graph! + private var graph: Graph private var panningView: VertexView? = nil - private var graphColors: GraphColors = GraphColors.sharedInstance + private var graphColors = GraphColors.sharedInstance - public override init(frame: CGRect) { + public init(frame: CGRect, graph: Graph) { + self.graph = graph super.init(frame: frame) backgroundColor = graphColors.graphBackgroundColor + layer.cornerRadius = 15 } public required init?(coder aDecoder: NSCoder) { @@ -15,10 +17,6 @@ public class GraphView: UIView { } - public func configure(graph: Graph) { - self.graph = graph - } - public func removeGraph() { for vertex in graph.vertices { if let view = vertex.view { diff --git a/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/Window.swift b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/Window.swift index 054b804c9..73c512e6b 100644 --- a/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/Window.swift +++ b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/Window.swift @@ -25,7 +25,7 @@ public class Window: UIView, GraphDelegate { private var activityIndicator: UIActivityIndicatorView! private var graph: Graph! private var numberOfVertices: UInt! - private var graphColors: GraphColors = GraphColors.sharedInstance + private var graphColors = GraphColors.sharedInstance public override init(frame: CGRect) { super.init(frame: frame) @@ -42,10 +42,9 @@ public class Window: UIView, GraphDelegate { graph.createNewGraph() graph.delegate = self let frame = CGRect(x: 10, y: 170, width: self.frame.width - 20, height: self.frame.height - 180) - graphView = GraphView(frame: frame) - graphView.layer.cornerRadius = 15 + graphView = GraphView(frame: frame, graph: graph) + - graphView.configure(graph: graph) graphView.createNewGraph() addSubview(graphView) @@ -198,11 +197,15 @@ public class Window: UIView, GraphDelegate { graphView.reset() graph.reset() } - - graph.startVertex.pathLengthFromStart = 0 - graph.startVertex.pathVerticesFromStart.append(graph.startVertex) + + guard let startVertex = graph.startVertex else { + assertionFailure("startVertex is nil") + return + } + startVertex.pathLengthFromStart = 0 + startVertex.pathVerticesFromStart.append(startVertex) graph.state = .parsing - graph.parseNeighborsFor(vertex: graph.startVertex) { + graph.parseNeighborsFor(vertex: startVertex) { self.graph.state = .interactiveVisualization DispatchQueue.main.async { self.comparisonLabel.text = "Pick next vertex" From 846101720981de86abf8fe8f372715fa50f12dcb Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Mon, 17 Apr 2017 14:02:43 +0300 Subject: [PATCH 0938/1679] Updated description --- Dijkstra Algorithm/README.md | 38 ++++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/Dijkstra Algorithm/README.md b/Dijkstra Algorithm/README.md index bf158def9..2bbf74b87 100644 --- a/Dijkstra Algorithm/README.md +++ b/Dijkstra Algorithm/README.md @@ -1,21 +1,39 @@ # Dijkstra-algorithm -## About -Dijkstra's algorithm is used for finding shortest paths from start vertex in graph(with weighted vertices) to all other vertices. -More algorithm's description can be found in playground or on wikipedia: -[Wikipedia](https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm) - -To understand how does this algorithm works, I have created **VisualizedDijkstra.playground.** It works in auto and interactive modes. Moreover there are play/pause/stop buttons. - -If you need only realization of the algorithm without visualization then run **Dijkstra.playground.** It contains necessary classes and couple functions to create random graph for algorithm testing. +## About this repository +This repository contains to playgrounds: +* To understand how does this algorithm works, I have created **VisualizedDijkstra.playground.** It works in auto and interactive modes. Moreover there are play/pause/stop buttons. +* If you need only realization of the algorithm without visualization then run **Dijkstra.playground.** It contains necessary classes and couple functions to create random graph for algorithm testing. ## Demo video Click the link: [YouTube](https://youtu.be/PPESI7et0cQ) ## Screenshots - +## Dijkstra's algorithm explanation + +Wikipedia's explanation: +Let the node at which we are starting be called the initial node. Let the distance of node Y be the distance from the initial node to Y. Dijkstra's algorithm will assign some initial distance values and will try to improve them step by step. + +1. Assign to every node a tentative distance value: set it to zero for our initial node and to infinity for all other nodes. +2. Set the initial node as current. Mark all other nodes unvisited. Create a set of all the unvisited nodes called the unvisited set. +3. For the current node, consider all of its unvisited neighbors and calculate their tentative distances. Compare the newly calculated tentative distance to the current assigned value and assign the smaller one. For example, if the current node A is marked with a distance of 6, and the edge connecting it with a neighbor B has length 2, then the distance to B (through A) will be 6 + 2 = 8. If B was previously marked with a distance greater than 8 then change it to 8. Otherwise, keep the current value. +4. When we are done considering all of the neighbors of the current node, mark the current node as visited and remove it from the unvisited set. A visited node will never be checked again. +5. If the destination node has been marked visited (when planning a route between two specific nodes) or if the smallest tentative distance among the nodes in the unvisited set is infinity (when planning a complete traversal; occurs when there is no connection between the initial node and remaining unvisited nodes), then stop. The algorithm has finished. +6. Otherwise, select the unvisited node that is marked with the smallest tentative distance, set it as the new "current node", and go back to step 3. + +Explanation, that can be found in the **VisualizedDijkstra.playground** +Algorithm's flow: +First of all, this program randomly decides which vertex will be the start one, then the program assigns a zero value to the start vertex path length from the start. + +Then the algorithm repeats following cycle until all vertices are marked as visited. +Cycle: +1. From the non-visited vertices the algorithm picks a vertex with the shortest path length from the start (if there are more than one vertex with the same shortest path value, then algorithm picks any of them) +2. The algorithm marks picked vertex as visited. +3. The algorithm check all of its neighbors. If the current vertex path length from the start plus an edge weight to a neighbor less than the neighbor current path length from the start, than it assigns new path length from the start to the neihgbor. +When all vertices are marked as visited, the algorithm's job is done. Now, you can see the shortest path from the start for every vertex by pressing the one you are interested in. + ## Credits -WWDC 2017 Scholarship Project +WWDC 2017 Scholarship Project Created by [Taras Nikulin](https://github.com/crabman448) From f7793cc6b6692000e4fd878afce62fd67d5b5f00 Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Mon, 17 Apr 2017 14:38:47 +0300 Subject: [PATCH 0939/1679] Added gif --- Dijkstra Algorithm/Images/Dijkstra_Animation.gif | Bin 0 -> 8561 bytes .../{Screenshots => Images}/screenshot1.jpg | Bin Dijkstra Algorithm/README.md | 8 +++++++- 3 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 Dijkstra Algorithm/Images/Dijkstra_Animation.gif rename Dijkstra Algorithm/{Screenshots => Images}/screenshot1.jpg (100%) diff --git a/Dijkstra Algorithm/Images/Dijkstra_Animation.gif b/Dijkstra Algorithm/Images/Dijkstra_Animation.gif new file mode 100644 index 0000000000000000000000000000000000000000..3b1a2ef434107efb104a9bc1a6a714af37367529 GIT binary patch literal 8561 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 literal 0 HcmV?d00001 diff --git a/Dijkstra Algorithm/Screenshots/screenshot1.jpg b/Dijkstra Algorithm/Images/screenshot1.jpg similarity index 100% rename from Dijkstra Algorithm/Screenshots/screenshot1.jpg rename to Dijkstra Algorithm/Images/screenshot1.jpg diff --git a/Dijkstra Algorithm/README.md b/Dijkstra Algorithm/README.md index 2bbf74b87..0ac4bc17e 100644 --- a/Dijkstra Algorithm/README.md +++ b/Dijkstra Algorithm/README.md @@ -9,10 +9,12 @@ This repository contains to playgrounds: Click the link: [YouTube](https://youtu.be/PPESI7et0cQ) ## Screenshots - + ## Dijkstra's algorithm explanation + + Wikipedia's explanation: Let the node at which we are starting be called the initial node. Let the distance of node Y be the distance from the initial node to Y. Dijkstra's algorithm will assign some initial distance values and will try to improve them step by step. @@ -34,6 +36,10 @@ Cycle: 3. The algorithm check all of its neighbors. If the current vertex path length from the start plus an edge weight to a neighbor less than the neighbor current path length from the start, than it assigns new path length from the start to the neihgbor. When all vertices are marked as visited, the algorithm's job is done. Now, you can see the shortest path from the start for every vertex by pressing the one you are interested in. +## Usage + + + ## Credits WWDC 2017 Scholarship Project Created by [Taras Nikulin](https://github.com/crabman448) From 3f6be33a1750d6f9122ca8ab38b70c3a9e4d123b Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Mon, 17 Apr 2017 14:40:34 +0300 Subject: [PATCH 0940/1679] Added link --- Dijkstra Algorithm/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Dijkstra Algorithm/README.md b/Dijkstra Algorithm/README.md index 0ac4bc17e..b2606f0f9 100644 --- a/Dijkstra Algorithm/README.md +++ b/Dijkstra Algorithm/README.md @@ -13,7 +13,8 @@ Click the link: [YouTube](https://youtu.be/PPESI7et0cQ) ## Dijkstra's algorithm explanation - +GIF from Wikipedia + Wikipedia's explanation: Let the node at which we are starting be called the initial node. Let the distance of node Y be the distance from the initial node to Y. Dijkstra's algorithm will assign some initial distance values and will try to improve them step by step. From a153067e60fcd90d8a8b6448fbc5d9e0c5753076 Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Mon, 17 Apr 2017 14:41:35 +0300 Subject: [PATCH 0941/1679] Updated link --- Dijkstra Algorithm/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dijkstra Algorithm/README.md b/Dijkstra Algorithm/README.md index b2606f0f9..cf939c7cc 100644 --- a/Dijkstra Algorithm/README.md +++ b/Dijkstra Algorithm/README.md @@ -14,7 +14,7 @@ Click the link: [YouTube](https://youtu.be/PPESI7et0cQ) ## Dijkstra's algorithm explanation GIF from Wikipedia - + Wikipedia's explanation: Let the node at which we are starting be called the initial node. Let the distance of node Y be the distance from the initial node to Y. Dijkstra's algorithm will assign some initial distance values and will try to improve them step by step. From b59ffa53930e3021a22bee31923965a12f7031a3 Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Mon, 17 Apr 2017 14:42:10 +0300 Subject: [PATCH 0942/1679] Revert "Updated link" This reverts commit a153067e60fcd90d8a8b6448fbc5d9e0c5753076. --- Dijkstra Algorithm/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dijkstra Algorithm/README.md b/Dijkstra Algorithm/README.md index cf939c7cc..b2606f0f9 100644 --- a/Dijkstra Algorithm/README.md +++ b/Dijkstra Algorithm/README.md @@ -14,7 +14,7 @@ Click the link: [YouTube](https://youtu.be/PPESI7et0cQ) ## Dijkstra's algorithm explanation GIF from Wikipedia - + Wikipedia's explanation: Let the node at which we are starting be called the initial node. Let the distance of node Y be the distance from the initial node to Y. Dijkstra's algorithm will assign some initial distance values and will try to improve them step by step. From ef13b5076e1741023c6d014e32266044d8d63d7b Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Mon, 17 Apr 2017 14:42:40 +0300 Subject: [PATCH 0943/1679] Revert "Added link" This reverts commit 3f6be33a1750d6f9122ca8ab38b70c3a9e4d123b. --- Dijkstra Algorithm/README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Dijkstra Algorithm/README.md b/Dijkstra Algorithm/README.md index b2606f0f9..0ac4bc17e 100644 --- a/Dijkstra Algorithm/README.md +++ b/Dijkstra Algorithm/README.md @@ -13,8 +13,7 @@ Click the link: [YouTube](https://youtu.be/PPESI7et0cQ) ## Dijkstra's algorithm explanation -GIF from Wikipedia - + Wikipedia's explanation: Let the node at which we are starting be called the initial node. Let the distance of node Y be the distance from the initial node to Y. Dijkstra's algorithm will assign some initial distance values and will try to improve them step by step. From aea01e8b68d7fefd06ccae2d3afeb253a43abba0 Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Mon, 17 Apr 2017 14:44:39 +0300 Subject: [PATCH 0944/1679] Added link to Wikipedia This reverts commit a153067e60fcd90d8a8b6448fbc5d9e0c5753076. --- Dijkstra Algorithm/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dijkstra Algorithm/README.md b/Dijkstra Algorithm/README.md index 0ac4bc17e..325bab40f 100644 --- a/Dijkstra Algorithm/README.md +++ b/Dijkstra Algorithm/README.md @@ -15,7 +15,7 @@ Click the link: [YouTube](https://youtu.be/PPESI7et0cQ) -Wikipedia's explanation: +[Wikipedia](https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm)'s explanation: Let the node at which we are starting be called the initial node. Let the distance of node Y be the distance from the initial node to Y. Dijkstra's algorithm will assign some initial distance values and will try to improve them step by step. 1. Assign to every node a tentative distance value: set it to zero for our initial node and to infinity for all other nodes. From edafd431fab46087ff805f6ad419b076a076bf82 Mon Sep 17 00:00:00 2001 From: ph1ps Date: Mon, 17 Apr 2017 21:15:01 +0200 Subject: [PATCH 0945/1679] Add playground --- .../NaiveBayes.playground/Contents.swift | 60 ++++++ .../NaiveBayes.playground/Resources/wine.csv | 177 ++++++++++++++++ .../Sources/NaiveBayes.swift | 196 ++++++++++++++++++ .../contents.xcplayground | 4 + .../contents.xcworkspacedata | 7 + Naive Bayes Classifier/NaiveBayes.swift | 124 ++++------- 6 files changed, 479 insertions(+), 89 deletions(-) create mode 100644 Naive Bayes Classifier/NaiveBayes.playground/Contents.swift create mode 100644 Naive Bayes Classifier/NaiveBayes.playground/Resources/wine.csv create mode 100644 Naive Bayes Classifier/NaiveBayes.playground/Sources/NaiveBayes.swift create mode 100644 Naive Bayes Classifier/NaiveBayes.playground/contents.xcplayground create mode 100644 Naive Bayes Classifier/NaiveBayes.playground/playground.xcworkspace/contents.xcworkspacedata diff --git a/Naive Bayes Classifier/NaiveBayes.playground/Contents.swift b/Naive Bayes Classifier/NaiveBayes.playground/Contents.swift new file mode 100644 index 000000000..cb820272e --- /dev/null +++ b/Naive Bayes Classifier/NaiveBayes.playground/Contents.swift @@ -0,0 +1,60 @@ +import Foundation + +/*: + ## Naive Bayes Classifier + + This playground uses the given algorithm and utilizes its features with some example datasets + + ### Gaussian Naive Bayes + - Note: + When using Gaussian NB you have to have continuous features (Double). + + For this example we are going to use a famous dataset with different types of wine. The labels of the features can be viewed [here](https://gist.github.com/tijptjik/9408623) + */ +guard let wineCSV = Bundle.main.path(forResource: "wine", ofType: "csv") else { + print("Resource could not be found!") + exit(0) +} + +guard let csv = try? String(contentsOfFile: wineCSV) else { + print("File could not be read!") + exit(0) +} + +/*: + Reading the .csv file line per line + */ +let rows = csv.characters.split(separator: "\r\n").map { String($0) } +/*: + Splitting on the ; sign and converting the value to a Double + + - Important: + Do not force unwrap the mapped values in your real application. Carefully convert them! This is just for the sake of showing how the algorithm works. + */ +let wineData = rows.map { row -> [Double] in + let split = row.characters.split(separator: ";") + return split.map { Double(String($0))! } +} + +/*: + The algorithm wants the classes and the data seperated since this gives a huge performance boost. Also I haven't implemented this in the NB class itself since it is not in the scope of it. + */ +let rowOfClasses = 0 +let classes = wineData.map { Int($0[rowOfClasses]) } +let data = wineData.map { row in + return row.enumerated().filter { $0.offset != rowOfClasses }.map { $0.element } +} + +/*: + Again use `guard` on the result of a `try?` or simply `do-try-catch` because this would crash your application if an error occured. + + The array in the `classifyProba` method I passed is a former entry in the .csv file which I removed in order to classify it. + */ +let wineBayes = try! NaiveBayes(type: .gaussian, data: data, classes: classes).train() +let result = wineBayes.classifyProba(with: [12.85, 1.6, 2.52, 17.8, 95, 2.48, 2.37, 0.26, 1.46, 3.93, 1.09, 3.63, 1015]) +print(result) +/*: + I can assure you that this is the correct result and as you can see the classifier thinks that its ***99.99%*** correct too. + + ### Multinomial Naive Bayes + */ diff --git a/Naive Bayes Classifier/NaiveBayes.playground/Resources/wine.csv b/Naive Bayes Classifier/NaiveBayes.playground/Resources/wine.csv new file mode 100644 index 000000000..89e14fd02 --- /dev/null +++ b/Naive Bayes Classifier/NaiveBayes.playground/Resources/wine.csv @@ -0,0 +1,177 @@ +1;14.23;1.71;2.43;15.6;127;2.8;3.06;.28;2.29;5.64;1.04;3.92;1065 +1;13.2;1.78;2.14;11.2;100;2.65;2.76;.26;1.28;4.38;1.05;3.4;1050 +1;13.16;2.36;2.67;18.6;101;2.8;3.24;.3;2.81;5.68;1.03;3.17;1185 +1;14.37;1.95;2.5;16.8;113;3.85;3.49;.24;2.18;7.8;.86;3.45;1480 +1;13.24;2.59;2.87;21;118;2.8;2.69;.39;1.82;4.32;1.04;2.93;735 +1;14.2;1.76;2.45;15.2;112;3.27;3.39;.34;1.97;6.75;1.05;2.85;1450 +1;14.39;1.87;2.45;14.6;96;2.5;2.52;.3;1.98;5.25;1.02;3.58;1290 +1;14.06;2.15;2.61;17.6;121;2.6;2.51;.31;1.25;5.05;1.06;3.58;1295 +1;14.83;1.64;2.17;14;97;2.8;2.98;.29;1.98;5.2;1.08;2.85;1045 +1;13.86;1.35;2.27;16;98;2.98;3.15;.22;1.85;7.22;1.01;3.55;1045 +1;14.1;2.16;2.3;18;105;2.95;3.32;.22;2.38;5.75;1.25;3.17;1510 +1;14.12;1.48;2.32;16.8;95;2.2;2.43;.26;1.57;5;1.17;2.82;1280 +1;13.75;1.73;2.41;16;89;2.6;2.76;.29;1.81;5.6;1.15;2.9;1320 +1;14.75;1.73;2.39;11.4;91;3.1;3.69;.43;2.81;5.4;1.25;2.73;1150 +1;14.38;1.87;2.38;12;102;3.3;3.64;.29;2.96;7.5;1.2;3;1547 +1;13.63;1.81;2.7;17.2;112;2.85;2.91;.3;1.46;7.3;1.28;2.88;1310 +1;14.3;1.92;2.72;20;120;2.8;3.14;.33;1.97;6.2;1.07;2.65;1280 +1;13.83;1.57;2.62;20;115;2.95;3.4;.4;1.72;6.6;1.13;2.57;1130 +1;14.19;1.59;2.48;16.5;108;3.3;3.93;.32;1.86;8.7;1.23;2.82;1680 +1;13.64;3.1;2.56;15.2;116;2.7;3.03;.17;1.66;5.1;.96;3.36;845 +1;14.06;1.63;2.28;16;126;3;3.17;.24;2.1;5.65;1.09;3.71;780 +1;12.93;3.8;2.65;18.6;102;2.41;2.41;.25;1.98;4.5;1.03;3.52;770 +1;13.71;1.86;2.36;16.6;101;2.61;2.88;.27;1.69;3.8;1.11;4;1035 +1;13.5;1.81;2.61;20;96;2.53;2.61;.28;1.66;3.52;1.12;3.82;845 +1;13.05;2.05;3.22;25;124;2.63;2.68;.47;1.92;3.58;1.13;3.2;830 +1;13.39;1.77;2.62;16.1;93;2.85;2.94;.34;1.45;4.8;.92;3.22;1195 +1;13.3;1.72;2.14;17;94;2.4;2.19;.27;1.35;3.95;1.02;2.77;1285 +1;13.87;1.9;2.8;19.4;107;2.95;2.97;.37;1.76;4.5;1.25;3.4;915 +1;14.02;1.68;2.21;16;96;2.65;2.33;.26;1.98;4.7;1.04;3.59;1035 +1;13.73;1.5;2.7;22.5;101;3;3.25;.29;2.38;5.7;1.19;2.71;1285 +1;13.58;1.66;2.36;19.1;106;2.86;3.19;.22;1.95;6.9;1.09;2.88;1515 +1;13.68;1.83;2.36;17.2;104;2.42;2.69;.42;1.97;3.84;1.23;2.87;990 +1;13.76;1.53;2.7;19.5;132;2.95;2.74;.5;1.35;5.4;1.25;3;1235 +1;13.51;1.8;2.65;19;110;2.35;2.53;.29;1.54;4.2;1.1;2.87;1095 +1;13.48;1.81;2.41;20.5;100;2.7;2.98;.26;1.86;5.1;1.04;3.47;920 +1;13.28;1.64;2.84;15.5;110;2.6;2.68;.34;1.36;4.6;1.09;2.78;880 +1;13.05;1.65;2.55;18;98;2.45;2.43;.29;1.44;4.25;1.12;2.51;1105 +1;13.07;1.5;2.1;15.5;98;2.4;2.64;.28;1.37;3.7;1.18;2.69;1020 +1;14.22;3.99;2.51;13.2;128;3;3.04;.2;2.08;5.1;.89;3.53;760 +1;13.56;1.71;2.31;16.2;117;3.15;3.29;.34;2.34;6.13;.95;3.38;795 +1;13.41;3.84;2.12;18.8;90;2.45;2.68;.27;1.48;4.28;.91;3;1035 +1;13.88;1.89;2.59;15;101;3.25;3.56;.17;1.7;5.43;.88;3.56;1095 +1;13.24;3.98;2.29;17.5;103;2.64;2.63;.32;1.66;4.36;.82;3;680 +1;13.05;1.77;2.1;17;107;3;3;.28;2.03;5.04;.88;3.35;885 +1;14.21;4.04;2.44;18.9;111;2.85;2.65;.3;1.25;5.24;.87;3.33;1080 +1;14.38;3.59;2.28;16;102;3.25;3.17;.27;2.19;4.9;1.04;3.44;1065 +1;13.9;1.68;2.12;16;101;3.1;3.39;.21;2.14;6.1;.91;3.33;985 +1;14.1;2.02;2.4;18.8;103;2.75;2.92;.32;2.38;6.2;1.07;2.75;1060 +1;13.94;1.73;2.27;17.4;108;2.88;3.54;.32;2.08;8.90;1.12;3.1;1260 +1;13.05;1.73;2.04;12.4;92;2.72;3.27;.17;2.91;7.2;1.12;2.91;1150 +1;13.83;1.65;2.6;17.2;94;2.45;2.99;.22;2.29;5.6;1.24;3.37;1265 +1;13.82;1.75;2.42;14;111;3.88;3.74;.32;1.87;7.05;1.01;3.26;1190 +1;13.77;1.9;2.68;17.1;115;3;2.79;.39;1.68;6.3;1.13;2.93;1375 +1;13.74;1.67;2.25;16.4;118;2.6;2.9;.21;1.62;5.85;.92;3.2;1060 +1;13.56;1.73;2.46;20.5;116;2.96;2.78;.2;2.45;6.25;.98;3.03;1120 +1;14.22;1.7;2.3;16.3;118;3.2;3;.26;2.03;6.38;.94;3.31;970 +1;13.29;1.97;2.68;16.8;102;3;3.23;.31;1.66;6;1.07;2.84;1270 +1;13.72;1.43;2.5;16.7;108;3.4;3.67;.19;2.04;6.8;.89;2.87;1285 +2;12.37;.94;1.36;10.6;88;1.98;.57;.28;.42;1.95;1.05;1.82;520 +2;12.33;1.1;2.28;16;101;2.05;1.09;.63;.41;3.27;1.25;1.67;680 +2;12.64;1.36;2.02;16.8;100;2.02;1.41;.53;.62;5.75;.98;1.59;450 +2;13.67;1.25;1.92;18;94;2.1;1.79;.32;.73;3.8;1.23;2.46;630 +2;12.37;1.13;2.16;19;87;3.5;3.1;.19;1.87;4.45;1.22;2.87;420 +2;12.17;1.45;2.53;19;104;1.89;1.75;.45;1.03;2.95;1.45;2.23;355 +2;12.37;1.21;2.56;18.1;98;2.42;2.65;.37;2.08;4.6;1.19;2.3;678 +2;13.11;1.01;1.7;15;78;2.98;3.18;.26;2.28;5.3;1.12;3.18;502 +2;12.37;1.17;1.92;19.6;78;2.11;2;.27;1.04;4.68;1.12;3.48;510 +2;13.34;.94;2.36;17;110;2.53;1.3;.55;.42;3.17;1.02;1.93;750 +2;12.21;1.19;1.75;16.8;151;1.85;1.28;.14;2.5;2.85;1.28;3.07;718 +2;12.29;1.61;2.21;20.4;103;1.1;1.02;.37;1.46;3.05;906;1.82;870 +2;13.86;1.51;2.67;25;86;2.95;2.86;.21;1.87;3.38;1.36;3.16;410 +2;13.49;1.66;2.24;24;87;1.88;1.84;.27;1.03;3.74;.98;2.78;472 +2;12.99;1.67;2.6;30;139;3.3;2.89;.21;1.96;3.35;1.31;3.5;985 +2;11.96;1.09;2.3;21;101;3.38;2.14;.13;1.65;3.21;.99;3.13;886 +2;11.66;1.88;1.92;16;97;1.61;1.57;.34;1.15;3.8;1.23;2.14;428 +2;13.03;.9;1.71;16;86;1.95;2.03;.24;1.46;4.6;1.19;2.48;392 +2;11.84;2.89;2.23;18;112;1.72;1.32;.43;.95;2.65;.96;2.52;500 +2;12.33;.99;1.95;14.8;136;1.9;1.85;.35;2.76;3.4;1.06;2.31;750 +2;12.7;3.87;2.4;23;101;2.83;2.55;.43;1.95;2.57;1.19;3.13;463 +2;12;.92;2;19;86;2.42;2.26;.3;1.43;2.5;1.38;3.12;278 +2;12.72;1.81;2.2;18.8;86;2.2;2.53;.26;1.77;3.9;1.16;3.14;714 +2;12.08;1.13;2.51;24;78;2;1.58;.4;1.4;2.2;1.31;2.72;630 +2;13.05;3.86;2.32;22.5;85;1.65;1.59;.61;1.62;4.8;.84;2.01;515 +2;11.84;.89;2.58;18;94;2.2;2.21;.22;2.35;3.05;.79;3.08;520 +2;12.67;.98;2.24;18;99;2.2;1.94;.3;1.46;2.62;1.23;3.16;450 +2;12.16;1.61;2.31;22.8;90;1.78;1.69;.43;1.56;2.45;1.33;2.26;495 +2;11.65;1.67;2.62;26;88;1.92;1.61;.4;1.34;2.6;1.36;3.21;562 +2;11.64;2.06;2.46;21.6;84;1.95;1.69;.48;1.35;2.8;1;2.75;680 +2;12.08;1.33;2.3;23.6;70;2.2;1.59;.42;1.38;1.74;1.07;3.21;625 +2;12.08;1.83;2.32;18.5;81;1.6;1.5;.52;1.64;2.4;1.08;2.27;480 +2;12;1.51;2.42;22;86;1.45;1.25;.5;1.63;3.6;1.05;2.65;450 +2;12.69;1.53;2.26;20.7;80;1.38;1.46;.58;1.62;3.05;.96;2.06;495 +2;12.29;2.83;2.22;18;88;2.45;2.25;.25;1.99;2.15;1.15;3.3;290 +2;11.62;1.99;2.28;18;98;3.02;2.26;.17;1.35;3.25;1.16;2.96;345 +2;12.47;1.52;2.2;19;162;2.5;2.27;.32;3.28;2.6;1.16;2.63;937 +2;11.81;2.12;2.74;21.5;134;1.6;.99;.14;1.56;2.5;.95;2.26;625 +2;12.29;1.41;1.98;16;85;2.55;2.5;.29;1.77;2.9;1.23;2.74;428 +2;12.37;1.07;2.1;18.5;88;3.52;3.75;.24;1.95;4.5;1.04;2.77;660 +2;12.29;3.17;2.21;18;88;2.85;2.99;.45;2.81;2.3;1.42;2.83;406 +2;12.08;2.08;1.7;17.5;97;2.23;2.17;.26;1.4;3.3;1.27;2.96;710 +2;12.6;1.34;1.9;18.5;88;1.45;1.36;.29;1.35;2.45;1.04;2.77;562 +2;12.34;2.45;2.46;21;98;2.56;2.11;.34;1.31;2.8;.8;3.38;438 +2;11.82;1.72;1.88;19.5;86;2.5;1.64;.37;1.42;2.06;.94;2.44;415 +2;12.51;1.73;1.98;20.5;85;2.2;1.92;.32;1.48;2.94;1.04;3.57;672 +2;12.42;2.55;2.27;22;90;1.68;1.84;.66;1.42;2.7;.86;3.3;315 +2;12.25;1.73;2.12;19;80;1.65;2.03;.37;1.63;3.4;1;3.17;510 +2;12.72;1.75;2.28;22.5;84;1.38;1.76;.48;1.63;3.3;.88;2.42;488 +2;12.22;1.29;1.94;19;92;2.36;2.04;.39;2.08;2.7;.86;3.02;312 +2;11.61;1.35;2.7;20;94;2.74;2.92;.29;2.49;2.65;.96;3.26;680 +2;11.46;3.74;1.82;19.5;107;3.18;2.58;.24;3.58;2.9;.75;2.81;562 +2;12.52;2.43;2.17;21;88;2.55;2.27;.26;1.22;2;.9;2.78;325 +2;11.76;2.68;2.92;20;103;1.75;2.03;.6;1.05;3.8;1.23;2.5;607 +2;11.41;.74;2.5;21;88;2.48;2.01;.42;1.44;3.08;1.1;2.31;434 +2;12.08;1.39;2.5;22.5;84;2.56;2.29;.43;1.04;2.9;.93;3.19;385 +2;11.03;1.51;2.2;21.5;85;2.46;2.17;.52;2.01;1.9;1.71;2.87;407 +2;11.82;1.47;1.99;20.8;86;1.98;1.6;.3;1.53;1.95;.95;3.33;495 +2;12.42;1.61;2.19;22.5;108;2;2.09;.34;1.61;2.06;1.06;2.96;345 +2;12.77;3.43;1.98;16;80;1.63;1.25;.43;.83;3.4;.7;2.12;372 +2;12;3.43;2;19;87;2;1.64;.37;1.87;1.28;.93;3.05;564 +2;11.45;2.4;2.42;20;96;2.9;2.79;.32;1.83;3.25;.8;3.39;625 +2;11.56;2.05;3.23;28.5;119;3.18;5.08;.47;1.87;6;.93;3.69;465 +2;12.42;4.43;2.73;26.5;102;2.2;2.13;.43;1.71;2.08;.92;3.12;365 +2;13.05;5.8;2.13;21.5;86;2.62;2.65;.3;2.01;2.6;.73;3.1;380 +2;11.87;4.31;2.39;21;82;2.86;3.03;.21;2.91;2.8;.75;3.64;380 +2;12.07;2.16;2.17;21;85;2.6;2.65;.37;1.35;2.76;.86;3.28;378 +2;12.43;1.53;2.29;21.5;86;2.74;3.15;.39;1.77;3.94;.69;2.84;352 +2;11.79;2.13;2.78;28.5;92;2.13;2.24;.58;1.76;3;.97;2.44;466 +2;12.37;1.63;2.3;24.5;88;2.22;2.45;.4;1.9;2.12;.89;2.78;342 +2;12.04;4.3;2.38;22;80;2.1;1.75;.42;1.35;2.6;.79;2.57;580 +3;12.86;1.35;2.32;18;122;1.51;1.25;.21;.94;4.1;.76;1.29;630 +3;12.88;2.99;2.4;20;104;1.3;1.22;.24;.83;5.4;.74;1.42;530 +3;12.81;2.31;2.4;24;98;1.15;1.09;.27;.83;5.7;.66;1.36;560 +3;12.7;3.55;2.36;21.5;106;1.7;1.2;.17;.84;5;.78;1.29;600 +3;12.51;1.24;2.25;17.5;85;2;.58;.6;1.25;5.45;.75;1.51;650 +3;12.6;2.46;2.2;18.5;94;1.62;.66;.63;.94;7.1;.73;1.58;695 +3;12.25;4.72;2.54;21;89;1.38;.47;.53;.8;3.85;.75;1.27;720 +3;12.53;5.51;2.64;25;96;1.79;.6;.63;1.1;5;.82;1.69;515 +3;13.49;3.59;2.19;19.5;88;1.62;.48;.58;.88;5.7;.81;1.82;580 +3;12.84;2.96;2.61;24;101;2.32;.6;.53;.81;4.92;.89;2.15;590 +3;12.93;2.81;2.7;21;96;1.54;.5;.53;.75;4.6;.77;2.31;600 +3;13.36;2.56;2.35;20;89;1.4;.5;.37;.64;5.6;.7;2.47;780 +3;13.52;3.17;2.72;23.5;97;1.55;.52;.5;.55;4.35;.89;2.06;520 +3;13.62;4.95;2.35;20;92;2;.8;.47;1.02;4.4;.91;2.05;550 +3;12.25;3.88;2.2;18.5;112;1.38;.78;.29;1.14;8.21;.65;2;855 +3;13.16;3.57;2.15;21;102;1.5;.55;.43;1.3;4;.6;1.68;830 +3;13.88;5.04;2.23;20;80;.98;.34;.4;.68;4.9;.58;1.33;415 +3;12.87;4.61;2.48;21.5;86;1.7;.65;.47;.86;7.65;.54;1.86;625 +3;13.32;3.24;2.38;21.5;92;1.93;.76;.45;1.25;8.42;.55;1.62;650 +3;13.08;3.9;2.36;21.5;113;1.41;1.39;.34;1.14;9.40;.57;1.33;550 +3;13.5;3.12;2.62;24;123;1.4;1.57;.22;1.25;8.60;.59;1.3;500 +3;12.79;2.67;2.48;22;112;1.48;1.36;.24;1.26;10.8;.48;1.47;480 +3;13.11;1.9;2.75;25.5;116;2.2;1.28;.26;1.56;7.1;.61;1.33;425 +3;13.23;3.3;2.28;18.5;98;1.8;.83;.61;1.87;10.52;.56;1.51;675 +3;12.58;1.29;2.1;20;103;1.48;.58;.53;1.4;7.6;.58;1.55;640 +3;13.17;5.19;2.32;22;93;1.74;.63;.61;1.55;7.9;.6;1.48;725 +3;13.84;4.12;2.38;19.5;89;1.8;.83;.48;1.56;9.01;.57;1.64;480 +3;12.45;3.03;2.64;27;97;1.9;.58;.63;1.14;7.5;.67;1.73;880 +3;14.34;1.68;2.7;25;98;2.8;1.31;.53;2.7;13;.57;1.96;660 +3;13.48;1.67;2.64;22.5;89;2.6;1.1;.52;2.29;11.75;.57;1.78;620 +3;12.36;3.83;2.38;21;88;2.3;.92;.5;1.04;7.65;.56;1.58;520 +3;13.69;3.26;2.54;20;107;1.83;.56;.5;.8;5.88;.96;1.82;680 +3;12.85;3.27;2.58;22;106;1.65;.6;.6;.96;5.58;.87;2.11;570 +3;12.96;3.45;2.35;18.5;106;1.39;.7;.4;.94;5.28;.68;1.75;675 +3;13.78;2.76;2.3;22;90;1.35;.68;.41;1.03;9.58;.7;1.68;615 +3;13.73;4.36;2.26;22.5;88;1.28;.47;.52;1.15;6.62;.78;1.75;520 +3;13.45;3.7;2.6;23;111;1.7;.92;.43;1.46;10.68;.85;1.56;695 +3;12.82;3.37;2.3;19.5;88;1.48;.66;.4;.97;10.26;.72;1.75;685 +3;13.58;2.58;2.69;24.5;105;1.55;.84;.39;1.54;8.66;.74;1.8;750 +3;13.4;4.6;2.86;25;112;1.98;.96;.27;1.11;8.5;.67;1.92;630 +3;12.2;3.03;2.32;19;96;1.25;.49;.4;.73;5.5;.66;1.83;510 +3;12.77;2.39;2.28;19.5;86;1.39;.51;.48;.64;9.899999;.57;1.63;470 +3;14.16;2.51;2.48;20;91;1.68;.7;.44;1.24;9.7;.62;1.71;660 +3;13.71;5.65;2.45;20.5;95;1.68;.61;.52;1.06;7.7;.64;1.74;740 +3;13.4;3.91;2.48;23;102;1.8;.75;.43;1.41;7.3;.7;1.56;750 +3;13.27;4.28;2.26;20;120;1.59;.69;.43;1.35;10.2;.59;1.56;835 +3;13.17;2.59;2.37;20;120;1.65;.68;.53;1.46;9.3;.6;1.62;840 +3;14.13;4.1;2.74;24.5;96;2.05;.76;.56;1.35;9.2;.61;1.6;560 \ No newline at end of file diff --git a/Naive Bayes Classifier/NaiveBayes.playground/Sources/NaiveBayes.swift b/Naive Bayes Classifier/NaiveBayes.playground/Sources/NaiveBayes.swift new file mode 100644 index 000000000..3af8102c7 --- /dev/null +++ b/Naive Bayes Classifier/NaiveBayes.playground/Sources/NaiveBayes.swift @@ -0,0 +1,196 @@ +// +// NaiveBayes.swift +// NaiveBayes +// +// Created by Philipp Gabriel on 14.04.17. +// Copyright © 2017 ph1ps. All rights reserved. +// + +import Foundation + +extension String: Error {} + +extension Array where Element == Double { + + func mean() -> Double { + return self.reduce(0, +) / Double(count) + } + + func standardDeviation() -> Double { + let calculatedMean = mean() + + let sum = self.reduce(0.0) { (previous, next) in + return previous + pow(next - calculatedMean, 2) + } + + return sqrt(sum / Double(count - 1)) + } +} + +extension Array where Element == Int { + + func uniques() -> Set { + return Set(self) + } + +} + +public enum NBType { + + case gaussian + case multinomial + //case bernoulli --> TODO + + func calcLikelihood(variables: [Any], input: Any) -> Double? { + + if case .gaussian = self { + + guard let input = input as? Double else { + return nil + } + + guard let mean = variables[0] as? Double else { + return nil + } + + guard let stDev = variables[1] as? Double else { + return nil + } + + let eulerPart = pow(M_E, -1 * pow(input - mean, 2) / (2 * pow(stDev, 2))) + let distribution = eulerPart / sqrt(2 * .pi) / stDev + + return distribution + + } else if case .multinomial = self { + + guard let variables = variables as? [(category: Int, probability: Double)] else { + return nil + } + + guard let input = input as? Int else { + return nil + } + + return variables.first { variable in + return variable.category == input + }?.probability + + } + + return nil + } + + func train(values: [Any]) -> [Any]? { + + if case .gaussian = self { + + guard let values = values as? [Double] else { + return nil + } + + return [values.mean(), values.standardDeviation()] + + } else if case .multinomial = self { + + guard let values = values as? [Int] else { + return nil + } + + let count = values.count + let categoryProba = values.uniques().map { value -> (Int, Double) in + return (value, Double(values.filter { $0 == value }.count) / Double(count)) + } + return categoryProba + } + + return nil + } +} + +public class NaiveBayes { + + var variables: [Int: [(feature: Int, variables: [Any])]] + var type: NBType + + var data: [[T]] + var classes: [Int] + + public init(type: NBType, data: [[T]], classes: [Int]) throws { + self.type = type + self.data = data + self.classes = classes + self.variables = [Int: [(Int, [Any])]]() + + if case .gaussian = type, T.self != Double.self { + throw "When using Gaussian NB you have to have continuous features (Double)" + } else if case .multinomial = type, T.self != Int.self { + throw "When using Multinomial NB you have to have categorical features (Int)" + } + } + + public func train() throws -> Self { + + for `class` in classes.uniques() { + variables[`class`] = [(Int, [Any])]() + + let classDependent = data.enumerated().filter { (offset, _) in + return classes[offset] == `class` + } + + for feature in 0.. Int { + let likelihoods = classifyProba(with: input).max { (first, second) -> Bool in + return first.1 < second.1 + } + + guard let `class` = likelihoods?.0 else { + return -1 + } + + return `class` + } + + public func classifyProba(with input: [T]) -> [(Int, Double)] { + + var probaClass = [Int: Double]() + let amount = classes.count + + classes.forEach { `class` in + let individual = classes.filter { $0 == `class` }.count + probaClass[`class`] = Double(individual) / Double(amount) + } + + let classesAndFeatures = variables.map { (`class`, value) -> (Int, [Double]) in + let distribution = value.map { (feature, variables) -> Double in + return type.calcLikelihood(variables: variables, input: input[feature]) ?? 0.0 + } + return (`class`, distribution) + } + + let likelihoods = classesAndFeatures.map { (`class`, distribution) in + return (`class`, distribution.reduce(1, *) * (probaClass[`class`] ?? 0.0)) + } + + let sum = likelihoods.map { $0.1 }.reduce(0, +) + let normalized = likelihoods.map { (`class`, likelihood) in + return (`class`, likelihood / sum) + } + + return normalized + } +} diff --git a/Naive Bayes Classifier/NaiveBayes.playground/contents.xcplayground b/Naive Bayes Classifier/NaiveBayes.playground/contents.xcplayground new file mode 100644 index 000000000..b1148fc50 --- /dev/null +++ b/Naive Bayes Classifier/NaiveBayes.playground/contents.xcplayground @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Naive Bayes Classifier/NaiveBayes.playground/playground.xcworkspace/contents.xcworkspacedata b/Naive Bayes Classifier/NaiveBayes.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Naive Bayes Classifier/NaiveBayes.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Naive Bayes Classifier/NaiveBayes.swift b/Naive Bayes Classifier/NaiveBayes.swift index dbbf3cd9f..9b9ace86d 100644 --- a/Naive Bayes Classifier/NaiveBayes.swift +++ b/Naive Bayes Classifier/NaiveBayes.swift @@ -8,6 +8,8 @@ import Foundation +extension String: Error {} + extension Array where Element == Double { func mean() -> Double { @@ -35,29 +37,9 @@ extension Array where Element == Int { enum NBType { - case gaussian(data: [[Double]], classes: [Int]) - case multinomial(data: [[Int]], classes: [Int]) - //case bernoulli(data: [[Bool]], classes: [Int]) --> TODO - - var classes: [Int] { - if case .gaussian(_, let classes) = self { - return classes - } else if case .multinomial(_, let classes) = self { - return classes - } - - return [] - } - - var data: [[Any]] { - if case .gaussian(let data, _) = self { - return data - } else if case .multinomial(let data, _) = self { - return data - } - - return [] - } + case gaussian + case multinomial + //case bernoulli --> TODO func calcLikelihood(variables: [Any], input: Any) -> Double? { @@ -86,12 +68,12 @@ enum NBType { return nil } - guard let input = input as? Double else { + guard let input = input as? Int else { return nil } return variables.first { variable in - return variable.category == Int(input) + return variable.category == input }?.probability } @@ -126,49 +108,52 @@ enum NBType { } } -class NaiveBayes { +class NaiveBayes { - private var variables: [Int: [(feature: Int, variables: [Any])]] - private var type: NBType + var variables: [Int: [(feature: Int, variables: [Any])]] + var type: NBType - init(type: NBType) { + var data: [[T]] + var classes: [Int] + + init(type: NBType, data: [[T]], classes: [Int]) throws { self.type = type + self.data = data + self.classes = classes self.variables = [Int: [(Int, [Any])]]() - } - - static func convert(dataAndClasses: [[T]], rowOfClasses: Int) -> (data: [[T]], classes: [Int]) { - let classes = dataAndClasses.map { Int($0[rowOfClasses] as! Double) } //TODO - let data = dataAndClasses.map { row in - return row.enumerated().filter { $0.offset != rowOfClasses }.map { $0.element } + if case .gaussian = type, T.self != Double.self { + throw "When using Gaussian NB you have to have continuous features (Double)" + } else if case .multinomial = type, T.self != Int.self { + throw "When using Multinomial NB you have to have categorical features (Int)" } - - return (data, classes) } - //TODO remake pliss, i dont like this at all - func train() { - - var classes = type.classes + func train() throws -> Self { for `class` in classes.uniques() { - variables[`class`] = [(Int, [Any])]() - for feature in 0.. Int { + func classify(with input: [T]) -> Int { let likelihoods = classifyProba(with: input).max { (first, second) -> Bool in return first.1 < second.1 } @@ -180,10 +165,8 @@ class NaiveBayes { return `class` } - //TODO fix this doesnt have to be a double - func classifyProba(with input: [Double]) -> [(Int, Double)] { + func classifyProba(with input: [T]) -> [(Int, Double)] { - let classes = type.classes var probaClass = [Int: Double]() let amount = classes.count @@ -200,7 +183,7 @@ class NaiveBayes { } let likelihoods = classesAndFeatures.map { (`class`, distribution) in - return (`class`, distribution.reduce(1, *) * (probaClass[`class`] ?? 1.0)) + return (`class`, distribution.reduce(1, *) * (probaClass[`class`] ?? 0.0)) } let sum = likelihoods.map { $0.1 }.reduce(0, +) @@ -211,40 +194,3 @@ class NaiveBayes { return normalized } } - -guard let csv = try? String(contentsOfFile: "/Users/ph1ps/Desktop/wine.csv") else { - print("file not found") - exit(0) -} - -let rows = csv.characters.split(separator: "\r\n").map { String($0) } -let wineData = rows.map { row -> [Double] in - let split = row.characters.split(separator: ";") - return split.map { Double(String($0))! } -} - -let convertedWine = NaiveBayes.convert(dataAndClasses: wineData, rowOfClasses: 0) -let wineNaive = NaiveBayes(type: .gaussian(data: convertedWine.data, classes: convertedWine.classes)) -wineNaive.train() -print(wineNaive.classifyProba(with: [12.85, 1.6, 2.52, 17.8, 95, 2.48, 2.37, 0.26, 1.46, 3.93, 1.09, 3.63, 1015])) - -let golfData = [ - [0, 0, 0, 0], - [0, 0, 0, 1], - [1, 0, 0, 0], - [2, 1, 0, 0], - [2, 2, 1, 0], - [2, 2, 1, 1], - [1, 2, 1, 1], - [0, 1, 0, 0], - [0, 2, 1, 0], - [2, 1, 1, 0], - [0, 1, 1, 1], - [1, 1, 0, 1], - [1, 0, 1, 0], - [2, 1, 0, 1] -] -let golfClasses = [0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0] -let golfNaive = NaiveBayes(type: .multinomial(data: golfData, classes: golfClasses)) -golfNaive.train() -print(golfNaive.classifyProba(with: [0, 2, 0, 1])) From 8ac88ae7fe6134885956502bd9551e7b6cd0a083 Mon Sep 17 00:00:00 2001 From: ph1ps Date: Mon, 17 Apr 2017 21:29:43 +0200 Subject: [PATCH 0946/1679] Change macOS playground to iOS --- .../NaiveBayes.playground/Contents.swift | 51 +++++++++++++++++-- .../contents.xcplayground | 2 +- .../NaiveBayes.playground/timeline.xctimeline | 21 ++++++++ 3 files changed, 70 insertions(+), 4 deletions(-) create mode 100644 Naive Bayes Classifier/NaiveBayes.playground/timeline.xctimeline diff --git a/Naive Bayes Classifier/NaiveBayes.playground/Contents.swift b/Naive Bayes Classifier/NaiveBayes.playground/Contents.swift index cb820272e..321e7a04a 100644 --- a/Naive Bayes Classifier/NaiveBayes.playground/Contents.swift +++ b/Naive Bayes Classifier/NaiveBayes.playground/Contents.swift @@ -7,7 +7,7 @@ import Foundation ### Gaussian Naive Bayes - Note: - When using Gaussian NB you have to have continuous features (Double). + When using Gaussian NB you have to have continuous features (Double). For this example we are going to use a famous dataset with different types of wine. The labels of the features can be viewed [here](https://gist.github.com/tijptjik/9408623) */ @@ -52,9 +52,54 @@ let data = wineData.map { row in */ let wineBayes = try! NaiveBayes(type: .gaussian, data: data, classes: classes).train() let result = wineBayes.classifyProba(with: [12.85, 1.6, 2.52, 17.8, 95, 2.48, 2.37, 0.26, 1.46, 3.93, 1.09, 3.63, 1015]) -print(result) /*: - I can assure you that this is the correct result and as you can see the classifier thinks that its ***99.99%*** correct too. + I can assure you that ***class 1*** is the correct result and as you can see the classifier thinks that its ***99.99%*** likely too. ### Multinomial Naive Bayes + + - Note: + When using Multinomial NB you have to have categorical features (Int). + + Now this dataset is commonly used to describe the classification problem and it is categorical which means you don't have real values you just have categorical data as stated before. The structure of this dataset is as follows. + + Outlook,Temperature,Humidity,Windy + + ***Outlook***: 0 = rainy, 1 = overcast, 2 = sunny + + ***Temperature***: 0 = hot, 1 = mild, 2 = cool + + ***Humidity***: 0 = high, 1 = normal + + ***Windy***: 0 = false, 1 = true + + The classes are either he will play golf or not depending on the weather conditions. (0 = won't play, 1 = will play) + */ + +let golfData = [ + [0, 0, 0, 0], + [0, 0, 0, 1], + [1, 0, 0, 0], + [2, 1, 0, 0], + [2, 2, 1, 0], + [2, 2, 1, 1], + [1, 2, 1, 1], + [0, 1, 0, 0], + [0, 2, 1, 0], + [2, 1, 1, 0], + [0, 1, 1, 1], + [1, 1, 0, 1], + [1, 0, 1, 0], + [2, 1, 0, 1] +] +let golfClasses = [0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0] + +let golfNaive = try! NaiveBayes(type: .multinomial, data: golfData, classes: golfClasses).train() + +/*: + The weather conditions is as follows now: Outlook=rainy, Temperature=cool, Humidity=high, Windy=true + */ +let golfResult = golfNaive.classifyProba(with: [0, 2, 0, 1]) + +/*: + Naive Bayes tells us that the golf player will ***not*** play with a likelihood of almost ***80%***. Which is true of course. */ diff --git a/Naive Bayes Classifier/NaiveBayes.playground/contents.xcplayground b/Naive Bayes Classifier/NaiveBayes.playground/contents.xcplayground index b1148fc50..35968656f 100644 --- a/Naive Bayes Classifier/NaiveBayes.playground/contents.xcplayground +++ b/Naive Bayes Classifier/NaiveBayes.playground/contents.xcplayground @@ -1,4 +1,4 @@ - + \ No newline at end of file diff --git a/Naive Bayes Classifier/NaiveBayes.playground/timeline.xctimeline b/Naive Bayes Classifier/NaiveBayes.playground/timeline.xctimeline new file mode 100644 index 000000000..b15fdda55 --- /dev/null +++ b/Naive Bayes Classifier/NaiveBayes.playground/timeline.xctimeline @@ -0,0 +1,21 @@ + + + + + + + + + + + From d9e36fa2800c2c67e07df17048424903ab5a7eb6 Mon Sep 17 00:00:00 2001 From: Matthijs Hollemans Date: Tue, 18 Apr 2017 13:43:41 +0200 Subject: [PATCH 0947/1679] Missing word --- Huffman Coding/README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Huffman Coding/README.markdown b/Huffman Coding/README.markdown index 69e105c87..7058096d0 100644 --- a/Huffman Coding/README.markdown +++ b/Huffman Coding/README.markdown @@ -1,6 +1,6 @@ # Huffman Coding -The idea: To encode objects that occur with a smaller number of bits than objects that occur less frequently. +The idea: To encode objects that occur often with a smaller number of bits than objects that occur less frequently. Although any type of objects can be encoded with this scheme, it is common to compress a stream of bytes. Suppose you have the following text, where each character is one byte: From 6c7e9de65cb84da86bb0a5de554f5d13fa6412e6 Mon Sep 17 00:00:00 2001 From: Matthijs Hollemans Date: Tue, 18 Apr 2017 13:45:16 +0200 Subject: [PATCH 0948/1679] Fix alignment --- Huffman Coding/README.markdown | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/Huffman Coding/README.markdown b/Huffman Coding/README.markdown index 7058096d0..d1181d215 100644 --- a/Huffman Coding/README.markdown +++ b/Huffman Coding/README.markdown @@ -9,13 +9,13 @@ Although any type of objects can be encoded with this scheme, it is common to co If you count how often each byte appears, you can see some bytes occur more than others: space: 5 u: 1 - o: 5 h: 1 - s: 4 d: 1 - m: 3 a: 1 - w: 3 y: 1 - c: 2 p: 1 - r: 2 e: 1 - n: 2 i: 1 + o: 5 h: 1 + s: 4 d: 1 + m: 3 a: 1 + w: 3 y: 1 + c: 2 p: 1 + r: 2 e: 1 + n: 2 i: 1 We can assign bit strings to each of these bytes. The more common a byte is, the fewer bits we assign to it. We might get something like this: @@ -23,10 +23,10 @@ We can assign bit strings to each of these bytes. The more common a byte is, the o: 5 000 h: 1 10001 s: 4 101 d: 1 11010 m: 3 111 a: 1 11011 - w: 3 0010 y: 1 01111 - c: 2 0011 p: 1 11000 - r: 2 1001 e: 1 01110 - n: 2 0110 i: 1 10000 + w: 3 0010 y: 1 01111 + c: 2 0011 p: 1 11000 + r: 2 1001 e: 1 01110 + n: 2 0110 i: 1 10000 Now if we replace the original bytes with these bit strings, the compressed output becomes: From 9fafc9278d72240fda1117d010b1544ff106dccb Mon Sep 17 00:00:00 2001 From: ph1ps Date: Tue, 18 Apr 2017 13:47:17 +0200 Subject: [PATCH 0949/1679] Add README with explanation --- .../NaiveBayes.playground/Contents.swift | 28 ++--- .../Sources/NaiveBayes.swift | 100 +++++++++--------- .../contents.xcplayground | 2 +- .../NaiveBayes.playground/timeline.xctimeline | 10 ++ Naive Bayes Classifier/NaiveBayes.swift | 100 +++++++++--------- Naive Bayes Classifier/README.md | 99 +++++++++++++++++ Naive Bayes Classifier/images/bayes.gif | Bin 0 -> 1095 bytes .../images/code_example.png | Bin 0 -> 122044 bytes Naive Bayes Classifier/images/mean.gif | Bin 0 -> 590 bytes Naive Bayes Classifier/images/multinomial.gif | Bin 0 -> 703 bytes .../images/normal_distribution.gif | Bin 0 -> 925 bytes .../images/standard_deviation.gif | Bin 0 -> 1125 bytes .../images/tennis_dataset.png | Bin 0 -> 61477 bytes 13 files changed, 224 insertions(+), 115 deletions(-) create mode 100644 Naive Bayes Classifier/images/bayes.gif create mode 100644 Naive Bayes Classifier/images/code_example.png create mode 100644 Naive Bayes Classifier/images/mean.gif create mode 100644 Naive Bayes Classifier/images/multinomial.gif create mode 100644 Naive Bayes Classifier/images/normal_distribution.gif create mode 100644 Naive Bayes Classifier/images/standard_deviation.gif create mode 100644 Naive Bayes Classifier/images/tennis_dataset.png diff --git a/Naive Bayes Classifier/NaiveBayes.playground/Contents.swift b/Naive Bayes Classifier/NaiveBayes.playground/Contents.swift index 321e7a04a..66aefaa32 100644 --- a/Naive Bayes Classifier/NaiveBayes.playground/Contents.swift +++ b/Naive Bayes Classifier/NaiveBayes.playground/Contents.swift @@ -2,13 +2,13 @@ import Foundation /*: ## Naive Bayes Classifier - + This playground uses the given algorithm and utilizes its features with some example datasets - + ### Gaussian Naive Bayes - Note: When using Gaussian NB you have to have continuous features (Double). - + For this example we are going to use a famous dataset with different types of wine. The labels of the features can be viewed [here](https://gist.github.com/tijptjik/9408623) */ guard let wineCSV = Bundle.main.path(forResource: "wine", ofType: "csv") else { @@ -27,7 +27,7 @@ guard let csv = try? String(contentsOfFile: wineCSV) else { let rows = csv.characters.split(separator: "\r\n").map { String($0) } /*: Splitting on the ; sign and converting the value to a Double - + - Important: Do not force unwrap the mapped values in your real application. Carefully convert them! This is just for the sake of showing how the algorithm works. */ @@ -47,31 +47,31 @@ let data = wineData.map { row in /*: Again use `guard` on the result of a `try?` or simply `do-try-catch` because this would crash your application if an error occured. - + The array in the `classifyProba` method I passed is a former entry in the .csv file which I removed in order to classify it. */ let wineBayes = try! NaiveBayes(type: .gaussian, data: data, classes: classes).train() let result = wineBayes.classifyProba(with: [12.85, 1.6, 2.52, 17.8, 95, 2.48, 2.37, 0.26, 1.46, 3.93, 1.09, 3.63, 1015]) /*: I can assure you that ***class 1*** is the correct result and as you can see the classifier thinks that its ***99.99%*** likely too. - + ### Multinomial Naive Bayes - + - Note: When using Multinomial NB you have to have categorical features (Int). - + Now this dataset is commonly used to describe the classification problem and it is categorical which means you don't have real values you just have categorical data as stated before. The structure of this dataset is as follows. - + Outlook,Temperature,Humidity,Windy - + ***Outlook***: 0 = rainy, 1 = overcast, 2 = sunny - + ***Temperature***: 0 = hot, 1 = mild, 2 = cool - + ***Humidity***: 0 = high, 1 = normal - + ***Windy***: 0 = false, 1 = true - + The classes are either he will play golf or not depending on the weather conditions. (0 = won't play, 1 = will play) */ diff --git a/Naive Bayes Classifier/NaiveBayes.playground/Sources/NaiveBayes.swift b/Naive Bayes Classifier/NaiveBayes.playground/Sources/NaiveBayes.swift index 3af8102c7..6e6d7b4c0 100644 --- a/Naive Bayes Classifier/NaiveBayes.playground/Sources/NaiveBayes.swift +++ b/Naive Bayes Classifier/NaiveBayes.playground/Sources/NaiveBayes.swift @@ -11,186 +11,186 @@ import Foundation extension String: Error {} extension Array where Element == Double { - + func mean() -> Double { return self.reduce(0, +) / Double(count) } - + func standardDeviation() -> Double { let calculatedMean = mean() - + let sum = self.reduce(0.0) { (previous, next) in return previous + pow(next - calculatedMean, 2) } - + return sqrt(sum / Double(count - 1)) } } extension Array where Element == Int { - + func uniques() -> Set { return Set(self) } - + } public enum NBType { - + case gaussian case multinomial //case bernoulli --> TODO - + func calcLikelihood(variables: [Any], input: Any) -> Double? { - + if case .gaussian = self { - + guard let input = input as? Double else { return nil } - + guard let mean = variables[0] as? Double else { return nil } - + guard let stDev = variables[1] as? Double else { return nil } - + let eulerPart = pow(M_E, -1 * pow(input - mean, 2) / (2 * pow(stDev, 2))) let distribution = eulerPart / sqrt(2 * .pi) / stDev - + return distribution - + } else if case .multinomial = self { - + guard let variables = variables as? [(category: Int, probability: Double)] else { return nil } - + guard let input = input as? Int else { return nil } - + return variables.first { variable in return variable.category == input }?.probability - + } - + return nil } - + func train(values: [Any]) -> [Any]? { - + if case .gaussian = self { - + guard let values = values as? [Double] else { return nil } - + return [values.mean(), values.standardDeviation()] - + } else if case .multinomial = self { - + guard let values = values as? [Int] else { return nil } - + let count = values.count let categoryProba = values.uniques().map { value -> (Int, Double) in return (value, Double(values.filter { $0 == value }.count) / Double(count)) } return categoryProba } - + return nil } } public class NaiveBayes { - + var variables: [Int: [(feature: Int, variables: [Any])]] var type: NBType - + var data: [[T]] var classes: [Int] - + public init(type: NBType, data: [[T]], classes: [Int]) throws { self.type = type self.data = data self.classes = classes self.variables = [Int: [(Int, [Any])]]() - + if case .gaussian = type, T.self != Double.self { throw "When using Gaussian NB you have to have continuous features (Double)" } else if case .multinomial = type, T.self != Int.self { throw "When using Multinomial NB you have to have categorical features (Int)" } } - + public func train() throws -> Self { - + for `class` in classes.uniques() { variables[`class`] = [(Int, [Any])]() - + let classDependent = data.enumerated().filter { (offset, _) in return classes[offset] == `class` } - + for feature in 0.. Int { let likelihoods = classifyProba(with: input).max { (first, second) -> Bool in return first.1 < second.1 } - + guard let `class` = likelihoods?.0 else { return -1 } - + return `class` } - + public func classifyProba(with input: [T]) -> [(Int, Double)] { - + var probaClass = [Int: Double]() let amount = classes.count - + classes.forEach { `class` in let individual = classes.filter { $0 == `class` }.count probaClass[`class`] = Double(individual) / Double(amount) } - + let classesAndFeatures = variables.map { (`class`, value) -> (Int, [Double]) in let distribution = value.map { (feature, variables) -> Double in return type.calcLikelihood(variables: variables, input: input[feature]) ?? 0.0 } return (`class`, distribution) } - + let likelihoods = classesAndFeatures.map { (`class`, distribution) in return (`class`, distribution.reduce(1, *) * (probaClass[`class`] ?? 0.0)) } - + let sum = likelihoods.map { $0.1 }.reduce(0, +) let normalized = likelihoods.map { (`class`, likelihood) in return (`class`, likelihood / sum) } - + return normalized } } diff --git a/Naive Bayes Classifier/NaiveBayes.playground/contents.xcplayground b/Naive Bayes Classifier/NaiveBayes.playground/contents.xcplayground index 35968656f..89da2d470 100644 --- a/Naive Bayes Classifier/NaiveBayes.playground/contents.xcplayground +++ b/Naive Bayes Classifier/NaiveBayes.playground/contents.xcplayground @@ -1,4 +1,4 @@ - + \ No newline at end of file diff --git a/Naive Bayes Classifier/NaiveBayes.playground/timeline.xctimeline b/Naive Bayes Classifier/NaiveBayes.playground/timeline.xctimeline index b15fdda55..7bc414f58 100644 --- a/Naive Bayes Classifier/NaiveBayes.playground/timeline.xctimeline +++ b/Naive Bayes Classifier/NaiveBayes.playground/timeline.xctimeline @@ -17,5 +17,15 @@ selectedRepresentationIndex = "0" shouldTrackSuperviewWidth = "NO"> + + + + diff --git a/Naive Bayes Classifier/NaiveBayes.swift b/Naive Bayes Classifier/NaiveBayes.swift index 9b9ace86d..46a0bb4f5 100644 --- a/Naive Bayes Classifier/NaiveBayes.swift +++ b/Naive Bayes Classifier/NaiveBayes.swift @@ -11,186 +11,186 @@ import Foundation extension String: Error {} extension Array where Element == Double { - + func mean() -> Double { return self.reduce(0, +) / Double(count) } - + func standardDeviation() -> Double { let calculatedMean = mean() - + let sum = self.reduce(0.0) { (previous, next) in return previous + pow(next - calculatedMean, 2) } - + return sqrt(sum / Double(count - 1)) } } extension Array where Element == Int { - + func uniques() -> Set { return Set(self) } - + } enum NBType { - + case gaussian case multinomial //case bernoulli --> TODO - + func calcLikelihood(variables: [Any], input: Any) -> Double? { - + if case .gaussian = self { - + guard let input = input as? Double else { return nil } - + guard let mean = variables[0] as? Double else { return nil } - + guard let stDev = variables[1] as? Double else { return nil } - + let eulerPart = pow(M_E, -1 * pow(input - mean, 2) / (2 * pow(stDev, 2))) let distribution = eulerPart / sqrt(2 * .pi) / stDev - + return distribution - + } else if case .multinomial = self { - + guard let variables = variables as? [(category: Int, probability: Double)] else { return nil } - + guard let input = input as? Int else { return nil } - + return variables.first { variable in return variable.category == input }?.probability - + } - + return nil } - + func train(values: [Any]) -> [Any]? { - + if case .gaussian = self { - + guard let values = values as? [Double] else { return nil } - + return [values.mean(), values.standardDeviation()] - + } else if case .multinomial = self { - + guard let values = values as? [Int] else { return nil } - + let count = values.count let categoryProba = values.uniques().map { value -> (Int, Double) in return (value, Double(values.filter { $0 == value }.count) / Double(count)) } return categoryProba } - + return nil } } class NaiveBayes { - + var variables: [Int: [(feature: Int, variables: [Any])]] var type: NBType - + var data: [[T]] var classes: [Int] - + init(type: NBType, data: [[T]], classes: [Int]) throws { self.type = type self.data = data self.classes = classes self.variables = [Int: [(Int, [Any])]]() - + if case .gaussian = type, T.self != Double.self { throw "When using Gaussian NB you have to have continuous features (Double)" } else if case .multinomial = type, T.self != Int.self { throw "When using Multinomial NB you have to have categorical features (Int)" } } - + func train() throws -> Self { - + for `class` in classes.uniques() { variables[`class`] = [(Int, [Any])]() - + let classDependent = data.enumerated().filter { (offset, _) in return classes[offset] == `class` } - + for feature in 0.. Int { let likelihoods = classifyProba(with: input).max { (first, second) -> Bool in return first.1 < second.1 } - + guard let `class` = likelihoods?.0 else { return -1 } - + return `class` } - + func classifyProba(with input: [T]) -> [(Int, Double)] { - + var probaClass = [Int: Double]() let amount = classes.count - + classes.forEach { `class` in let individual = classes.filter { $0 == `class` }.count probaClass[`class`] = Double(individual) / Double(amount) } - + let classesAndFeatures = variables.map { (`class`, value) -> (Int, [Double]) in let distribution = value.map { (feature, variables) -> Double in return type.calcLikelihood(variables: variables, input: input[feature]) ?? 0.0 } return (`class`, distribution) } - + let likelihoods = classesAndFeatures.map { (`class`, distribution) in return (`class`, distribution.reduce(1, *) * (probaClass[`class`] ?? 0.0)) } - + let sum = likelihoods.map { $0.1 }.reduce(0, +) let normalized = likelihoods.map { (`class`, likelihood) in return (`class`, likelihood / sum) } - + return normalized } } diff --git a/Naive Bayes Classifier/README.md b/Naive Bayes Classifier/README.md index e69de29bb..9c0f0082a 100644 --- a/Naive Bayes Classifier/README.md +++ b/Naive Bayes Classifier/README.md @@ -0,0 +1,99 @@ +# Naive Bayes Classifier + +> ***Disclaimer:*** Do not get scared of complicated formulas or terms, I will describe them right after I use them. Also the math skills you need to understand this are very basic. + +The goal of a classifier is to predict the class of a given data entry based on previously fed data and its features. + +Now what is a class or a feature? The best I can do is to describe it with a table. +This is a dataset that uses height, weight and foot size of a person to illustrate the relationship between those values and the sex. + +| Sex | height (feet) | weight(lbs) | foot size (inches) | +| ------------- |:-------------:|:-----:|:---:| +| male | 6 | 180 | 12 | +| male | 5.92 | 190 | 11 | +| male | 5.58 | 170 | 12 | +| male | 5.92 | 165 | 10 | +| female | 5 | 100 | 6 | +| female | 5.5 | 150 | 8 | +| female | 5.42 | 130 | 7 | +| female | 5.75 | 150 | 9 | + +The ***classes*** of this table is the data in the sex column (male/female). You "classify" the rest of the data and bind them to a sex. + +The ***features*** of this table are the labels of the other columns (height, weight, foot size) and the numbers right under the labels. + +Now that I've told you what a classifier is I will tell you what exactly a ***Naive Bayes classifier*** is. There are a lot of other classifiers out there but what's so special about this specific is that it only needs a very small dataset to get good results. The others like Random Forests normally need a very large dataset. + +Why isn't this algorithm used more you might ask (or not). Because it is normally ***outperformed*** in accuracy by ***Random Forests*** or ***Boosted Trees***. + +## Theory + +The Naive Bayes classifier utilizes the ***Bayes Theorem*** (as its name suggests) which looks like this. + +![](images/bayes.gif) + +***P*** always means the probability of something. + +***A*** is the class, ***B*** is the data depending on a feature and the ***pipe*** symbol means given. + +P(A | B) therefore is: probability of the class given the data (which is dependent on the feature). + +This is all you have to know about the Bayes Theorem. The important thing for us is now how to calculate all those variables, plug them into this formula and you are ready to classify data. + +### **P(A)** +This is the probability of the class. To get back to the example I gave before: Let's say we want to classify this data entry: + +| height (feet) | weight(lbs) | foot size (inches) | +|:-------------:|:-----:|:---:| +| 6 | 130 | 8 | + +What Naive Bayes classifier now does: it checks the probability for every class possible which is in our case either male or female. Look back at the original table and count the male and the female entries. Then divide them by the overall count of data entries. + +P(male) = 4 / 8 = 0.5 + +P(female) = 4 / 8 = 0.5 + +This should be a very easy task to do. Basically just the probability of all classes. + +### **P(B)** +This variable is not needed in a Naive Bayes classifier. It is the probability of the data. It does not change, therefore it is a constant. And what can you do with a constant? Exactly! Discard it. This saves time and code. + +### **P(B | A)** +This is the probability of the data given the class. To calculate this I have to introduce you to the subtypes of NB. You have to decide which you use depending on your data which you want to classify. + +### **Gaussian Naive Bayes** +If you have a dataset like the one I showed you before (continuous features -> `Double`s) you have to use this subtype. There are 3 formulas you need for Gaussian NB to calculate P(B | A). + +![mean](images/mean.gif) + +![standard deviation](images/standard_deviation.gif) + +![normal distribution](images/normal_distribution.gif) + +and **P(x | y) = P(B | A)** + +Again, very complicated looking formulas but they are very easy. The first formula with µ is just the mean of the data (adding all data points and dividing them by the count). The second with σ is the standard deviation. You might have heard of it somewhen in school. It is just the sum of all values minus the mean, squared and that divided by the count of the data minus 1 and a sqaure root around it. The third equation is the Gaussian or normal distribution if you want to read more about it I suggest reading [this](https://en.wikipedia.org/wiki/Normal_distribution). + +Why the Gaussian distribution? Because we assume that the continuous values associated with each class are distributed according to the Gaussian distribution. Simple as that. + +### **Multinomial Naive Bayes** + +What do we do if we have this for examples: + +![tennis or golf](images/tennis_dataset.png) + +We can't just calculate the mean of sunny, overcast and rainy. This is why we need the categorical model which is the multinomial NB. This is the last formula, I promise! + +![multinomial](images/multinomial.gif) + +Now this is the number of times feature **i** appears in a sample **N** of class **y** in the data set divided by the count of the sample just depending on the class **y**. That θ is also just a fancy way of writing P(B | A). + +You might have noticed that there is still the α in this formula. This solves a problem called "zero-frequency-problem". Because what happens if there is no sample with feature **i** and class **y**? The whole equation would result in 0 (because 0 / something is always 0). This is a huge problem but there is a simple solution to this. Just add 1 to any count of the sample (α = 1). + +## Those formulas in action + +Enough talking! This is the code. If you want a deeper explanation of how the code works just look at the Playground I provided. + +![code example](images/code_example.png) + +*Written for Swift Algorithm Club by Philipp Gabriel* \ No newline at end of file diff --git a/Naive Bayes Classifier/images/bayes.gif b/Naive Bayes Classifier/images/bayes.gif new file mode 100644 index 0000000000000000000000000000000000000000..363ff3425836342c4e354a74454b4828c1fab6d3 GIT binary patch literal 1095 zcmV-N1i1T0Nk%w1Vb1_70OJ4v|Ns90004G&b|NAoW@ctYL`2NY%v4lVy1KgD+}xO$ znC|ZGh=_;~5D+plGODVoA^8LW00000EC2ui0M7s`000F35XecZy*TU5yI+boEg}$> z=mm;r>b`KC5oB4E3n8PlnD4+KOfU!tj)a1N!a!JvMr5IN(-54KM=J(B3X;o7b91F= zh3GV=aG)RpiHQSK&`lD7hop*mZvk^aY;JIJ8-5jmYKx2j0b2_J3=(G-c@;)`8VZsX z41X_=6p@nvl^L9+VxWz!FmG`a1_4+Fu@$p5l!X9%79j(6vc4Ar9IzC#wYL|*!V(6= zuG1+34HX26*B14m3J zr&6dow5$Yn85Xz%Ab=QCO%+xGKt^HhHvn@6oh{f}N{a#~oxTwKL7l82;k1`DtadXy zH#FNEdWZmy;fERl4mzfGy#;vys9z2UZz>_dfdCOHT_2!|!SYcVoEP{mK|u@a*mXVF z-hFu&DMmxifc>P1mn2(G30**(P6}_0@cvg%27^p67=RWaLY->Q;2{@+8VSHv2mNVf z+Hn&ea-k?AbYjYd<#`AfCY@!nN@34H&HgXjZ=;<(sbh*I2MFv7(!Rh^AJAzXi(8b3sPW@KMcL-NS0`( zDM3dd$+uHaas5PrG?R%z)?r0jG}E4ZCZy({L2Q+QS4TnDmROJ(h$sMWjg@C80Yob4 zq?A@_>7|%vs_CYjcG~F#XccFdV2=^g7Hg_B3FxZyAhrQ#l9faZV-z@cBLH?0&}W}~ zvFfW2zR_``Y^<&1OC&nIX2FlY_cptTc;uOI-gViT!rq9^L8t3$tbi!2 zXaR)ZrogReW~wP+xh@c!Zg}>=#{_0<)%(R1S%jNqyZ)gNWsL0Z8nS-t9B!@uGKiq*>E?O+<2Qbmz=iJ73p2veB)qlB7Fz$!MjWQE4bhQtC0BN Nhc~=Il0roQ06YAH(zpNs literal 0 HcmV?d00001 diff --git a/Naive Bayes Classifier/images/code_example.png b/Naive Bayes Classifier/images/code_example.png new file mode 100644 index 0000000000000000000000000000000000000000..a147ecdd6d5a9b542ac02cc1b778e279e183b229 GIT binary patch literal 122044 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%0AqlP%v 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 literal 0 HcmV?d00001 diff --git a/Naive Bayes Classifier/images/mean.gif b/Naive Bayes Classifier/images/mean.gif new file mode 100644 index 0000000000000000000000000000000000000000..7518c9995f8b5d2a33b4268aebfe9d8c9d90868f GIT binary patch literal 590 zcmV-U0hZ;sgm(P!LiW?r0MiU?!oEECS8T_EArNc1 zo1rg}gaRXCD4?~V0RsmPtT>=_swa&C3-P7X@Kx6@D%(%=F0vZiyQX43783hUy3kL~<76Sx%d?-p21_23@D-Q&n z1PThC1auS(k_rQC7F|7)DVhupY>-z)v~Z3VX*UyqycbY)u7wo?OcGWLKnj@v%D5T= z0Tm6T!#e_+2x=jT0Cx%A8ip7PzXsL9*EtUi3z{=dO#*=c4w@I_7YX+V1qcZU3 z)t+@Y9GGxGM;X2f2M!(?U?Lns9SI&3SRh5#uZ#W$Vn~>F5yzN2B`qu%lO|=01Pkz3 za|ytJxB@6?rU0W#X9EQc9V`&1vnUM)dtzm9gMpK%r!$Qr*)~BM!3tN61lY>8tJkk! z!-^eC_5(^zQq!(L5VH;gUbh_B5_!StQ%_OV?zlrhO0s3mp6N~dWq>0D-oOzZ%oxBI z0Q9arY@Al1y@m)T@8IBJj|dWeC|Ah1vEzV`WM0sf5RZioohM87_z{GLK7=r3f?UGp ziS1k$d6qnbMGKDG7rum%SU7WmzLd|TS#un?g*g)JAgf~_&6xv>)%pP>s5%^?iyGB* z+!nxqdV?!TxYSIA-A|$LS};Wcl`8BK2yWCEEV5`Jl3dVaunPsglrjh=0~T`(9?k%k zpdKXkVoggt#AF?8+HjLyVugG-fjO3>0|g=zVAoSo?Ytuc1&>8`AqM;u;156oL2*x2 l_hcp71eP&`LPSHlL>fm)iWXawjpbHAUQkLUoL&(C06Px_310vJ literal 0 HcmV?d00001 diff --git a/Naive Bayes Classifier/images/normal_distribution.gif b/Naive Bayes Classifier/images/normal_distribution.gif new file mode 100644 index 0000000000000000000000000000000000000000..b2f35e8ebf9e6e92c985176a946e5dbcce14a9a4 GIT binary patch literal 925 zcmV;O17iF~Nk%w1VZHz=0OJ4v|Ns90004G&b|NAoW@ctYL`2NY%v4lVy1KgD+}xO$ znC|ZGh=_;~5D+plGODVoA^8LW00000EC2ui0KNb!000F35XecZy*TU5yI+Ojjbzy= z4}q9$>%LYZD8UNfIAAb9GUUKuuqG^;5C@}j*&#AF29ax_pezWBr*;c)axFX<;vq>? zZQt||tp+d>I6|*67$n*L8VdqFVE_VId5brDYIh3@336Ev440QSC~jyB zQjDN1j%j@WRAg`&2XFU2JWK9g`LY zWI0$S1szwhgarW(0-tJ8BM;LP#T^0z0RrpViaR5+5j(@N*`MKMG*IC@GHu5)uxUGH}4F=|VUO z8jxuKZUVhxWF;IZdu8gdRAJi$Ro3oi#u+iHQiTMdd^!Wg{*0S{;`>};^EF_jGlOJ4?1 zRKPM*3LfGU;xk%8yr>CMw~xcD8@`o*J1UE0;e&8 znO*=|AV_QkJRpq#51^4iPlr(uRaCRVli?PM={68HGyE3e1;e3pk4zFUfFp@t98lqm zTzu2PW64O=7*ot3@SGM2;0Pos=-9HLDSZeq43&5g@Z*zPoa532f6SmEeoNF?AOr4H z#icCBDI=60iYT_?nsk0)<^Z1@kXoI528l)k$q0~QpM;jlBL#Yv;lMy%DWDEO))iW3 zHWe^1rzrtULjW8+JkZhsSb*T3qqNNyIqFNSL zrbU>OwAN`_a~N1+)Rbj-MZl=RP4YPaJsVb_xPtpKKss^Zlz!;@C zU_$`lq;|li+|t=VApJ2V5G1J;z=o*`c+xJd40N;azd2|WFTezspk~1rL;wIghTUnw literal 0 HcmV?d00001 diff --git a/Naive Bayes Classifier/images/standard_deviation.gif b/Naive Bayes Classifier/images/standard_deviation.gif new file mode 100644 index 0000000000000000000000000000000000000000..b917d9922e589300b796ba8cd32d2b6251d26089 GIT binary patch literal 1125 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
PPPq>4m!%z#o!=8IENk;buccYO#mSK|v> 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

D73NrvdrmS(1$?q|n9 z4rCl6jf%Mf5$S@?nEU9XKl)PZI6t^yo}-(#pJ(3v=akb2379{tW5?Ms_oc;cY0Z@z zisPFvdicgqI>gk}4ew*R)Xe;wIGa>$rLZRXJ+YYh{kRX^Z#K_|eWDzgXjZ$+GKKx@ zP#u2PW|%#e>2z8r6PnrD9d>@f%i<1V%=O+BBw*|QVrIsd(<_yMXY5_zp*CQQ5hV!e z!>V6*p{aNGcG$Sn<4C{G@4s;soiagXpkaJBh+ z6jln>Q4#XN?20zCnx=G@X~R`Yx%aG5kmm;n%YJ4ij<1%CM9Mzlx|QTojoQp|EUUejj8U&1S!SguhEw z`#EEu<=3Z?<#omBG3|X|1yTcfLbG-Lay44234BSu%FA^-`|CccSfYyS_sfv9nQDUW z{>QLmKwiqlxaP>;&ELk#_CbKm)L*TH#XZ3(T*yE_rx{n4<=- zUvs~MuF;CEO6J0Oauntd6H6q}*#6w|@2Bx=7$}i;b;k$?fe5pB&8aq=e}{7>^oMrE zN37E54JlWEd=G+NsInET41I_ugNhp1aAl(5kfr^b{FFO?v}ncx)mT`Pfl5%&XZNQOx%uaU`#u_T`*)RGf)Xa zWkEC*zD>zEYG_%aM}MGXc~SA19auZ#+uJ_-3J+2w?P^x@Sqr>7#qtOu$YVX6^g(dR6Ub0;U73tGo!Rg`n5bmYWWcpQI*(q1zH)Ipg~E0ezOx_-{k` zAfG){0zvjfNB^ylS#>5*JkxnH*ucNl+q{230ZPF*n4-%c1=V3qO@HV*$U=8^`FI+3 zzkk5%m&ZEH$a!Mr;%S`w@P100&rEG}d84$fw1iM8PzL8E$N8M7{j84R0~cQ|E^2pq zhvKC$LRc8!i(gCzsH$NGF0pD-WMp(Ewb*F}-Oja^-Xa|gxS4Sjdn^*Q&+`@1_V_`2 z$JOc{y4AbuwVj`x|$DBSWMr#R)blie1*1f+#yqhwwL%7YbEaa z{?O+L$u;zHqMD{}_6I~&WjC)K)5V=XS2i5VH*0t`#A}3}F#|5g-WybLMw7gZqqpPe zFz&#tioBg_DmAlMbmfJ+ZwS3tvGgaOoDe7+4%hIfmZxxGjII@au>@il-{FZZ9=bmkCsR6$5&!@>_u385MUrGDQX&>OaA|+k)Z~ zTVlQ0+lx9&MK^9m3hVauSL&8k^pqLp6lGF^$1gsdhYzD01gcYpG9TaMPtTrgS6Uh` zZwim{ej6RWl#UzEqWWz|gXZ9Htqk1n7~8K$E7F4hsJ4}O>ArUYH&Y`-TTyBfbs~0v zh#YJyv}`{qvpaqmY|u;&P`2_IhE<-qiyurKD;Q^~^iCbjz($PFRvx(2r2}?wkYFVz zwxs~+nygMBpH8NKt31Bvo;pho(?aCJMHw&Noyw7v{>E>(@7Johw?Eiz74A`#JU8@s1NiV0F6@*}~E7+}0!pxW4$9 znK=g59yQW6=;h3BVWOZcS)Uw7W|GJ;HC-56N6zdVQ9U&;VI9JcK&|S5mKpkY!#;#v z&}0dztIYQfRnPonqsLeH#?u~S2B%d@mi3R~>NNAMad`~19ogs?K#v?o*~D7JA<9W^=P?oyo-cz6DC9j ze3+j;IkP0C_mCQt@2RhUXs2uKXs^n{i%h#F@XSCWtnzd0&d*xp_k)DatwOhI%uT4U z)J1dE2{Iz7@cnX-^?W(8+?i2dwdmJU)BCY6*bjsW>)u1_i^^hmJ~&y zG^Wkzq(W_4f_%5sKdGbckYQi(O1|9fOW*loXBzEkV^_3}7dhpeUf1BwMJw5yUgf$~ z5q+_SEW{Ds4}F}W22bG=`dV?rN}3> z89b%k>Iib6@<%gqzl*A&OKU{G?wE;|~i`bWpNp5FF!=I&>iX)kBu2eU!&)%OE2WWiQS@HC-npz*VJRuPwhYd-ScIYg(aR@2^?yxOJOY z`LEReh`Kg^-g+sYRJQt#VHB)}X!8|gUTwTgy ze37H?#9u)=zFASM8$|ahG#}vB&7V%c&L36Qh_`uCL~Rf5TlG9pNoF-?)er#5?~U$> zH(Wq5w(v4Qfcyj@zYMgGeTvXF(O8+&y*&)uP}5itjQ>$9{YYHTI5m>pc3VBNO!g#p zo5MlFaF;8C{l3lA z9FOT}*5LB)7W2^1up*a!P$RW1CgnezSQOQJCKe7k!{Ft>f*PLW_*HdrMcG^UK$g?fwWBPd)z_(2);~`izzi6ksZno`ONjm zp0?@KA^zdZRl66-`}Ki5OG|r3Frxylr;0=U3Z6A>wC#{H-kl*mFB&Wew-J>Sj$rknGLLwql#><9V*R~Ils-II8Kdj!J<>uq-JMZTN zVF(`lW;HMBcGPaWq-Pzd!9_VP;Ly$DepWzCdS?)qI=(>PHOyRpZSrzhl8v3F@|im469wr5q0Si zNu|%~?!G=+4bhhHxEgdiK5=OoLiYEC*JSKXJp(bspJ!4SXtSO5Ktf#4qHYI>3fWWi zT;d)S92!jj)IA%7)HsGvOZ-up8*!Aa4&s;9C8<*aBk)D@byzbnGF<3K@LZYQn(?G= z7+cW9pAjJ+{k^Bo&8pca5)Q}i)0HM%@LI7!xyMlLZ^>&aQc6(dd1T{h3huvm?QukC z_e{9}@EKKRz`dB)=*fvdop>-OPE?u^=e}(`57u>?fbnJjVp;kaYln_w;1-{c)G;SN zu7TEyL0#}cDjVFm$NqElWs?Es9>^>wmgiKYYe3wb#2@c0ioA1dgF0Jn2--psKh(9_ zj=wHGj(}o9MR_PY7P+8h)5*3_4AuOO4!-tHfiaZg#TVqWCE@bn^{lcP_%#(wzYi`e zoA5{MRb<&qz9z=`S?jdwx{R0=;|z8wRM=gGbMz^_uG1#FER$)0kKL0wE@h?Jjk!5a zmL>LZHGx}8FxJQX4RW3mQ=Xo_IoR13bG4_nDkqNCn|cMciIMLb1QIO2llFhAO6_E+ zvYu^+?i@cmG@S>kn2g&5)eqf3_S|c|^{Q+26Wo~H+Of^lMlD#Vn|`G_2vPlp&oY`W zXG8&?|2Jvt`|BmL0%I((_X-0I4bUS}+6LP;9R0LpeYKw9Y7=ZlPSCE5bTg4?70mx4oo-@ zM{xX~1Q$ndt?zTfa_VwdD7`G)BY0@XGdM;eo*<(cnAFwJs;W-1 zoz>4)d&FPL|sJN?ydZK4;`VMvUthPx87Dq$sTkBR1Jl_Bj4r$f zj;A}@d?P!lsP7POmk99GF?==J+FWbqr1%z#yH^N1e`Odxe@DE7+B3$e7Bh8BY9!Gr z%0QhbrC-7zi})LD$})(R(p9{;V5BEeYnkirwIorSr|jA9a%cN54lSkZ6o}2FYFI$M zT)yl6hykc>y`oH=KPs0NbcF&H^4X^7@ybrp!2*{MQZ>7xt)EWD@sGE#@v<}_cN+v> zn533tZDHZ1agJ)afs=Ma`G;L-pVKd398gu>wi~|w7?6fTxaIubyv8Y-G0B3L-&?op?e=k;Z+TzXY_)k;i_(kfs zu(N=4#PCgBg)KKd`n~8~G6WTFpB4FVM8QlTC(huG-h>o|o9+J@;CmVoK;5BzopHbL zq_8cv!GY**O_f8VB~B~?a_Y)zORte;l6Mt95D})qyeXws-*vsyiqtzX55itQOT)%Oe-BD4p`3@})?Y zU6->YZO-v7#$L!8a=!}DzD~ReJBP2rY}sRh?hzW0qbOUH5uns%YDsYQVy@P?w?C84 zgnsW6mS!@pyelZ~$YkJ9Pf`*7YB)XUiKCeyobcnVHA0jADq%U?cy@7c9rBfoKM#!@ zbAzwvfGcA!V&=-e1waO22tVqbAzpd|lx((L84hQ=s$Kazv3fo4%GW@KKsxk79M9IE z49`W4DZ_i+_FlTPV~B$mkM8)kHy!pY{?=-SSGiWrgVzqaYO(HlRKYQNJWFz`YW*KNUOdnnd;I8OZK z-tNr~-*7!7kuK#de)HoIRmnjUenRcLO4O;Wc8(=Jf6TQlM6%26&Ol58qOf6n=V#!5 zx*jdcaWjJxK~Kr}pqZlC82Sf2yK-5h7Y3#_vM+jshMyFVo}n)vy3cV2G#Cbqoc+=7 z9Q@H~TK&;k;)ivpAypbIw6sk1fy*`U5Msay^K(v4fF~q-*2s3NlyaCX;4;5pFWh`(d}}x#Zz}srx}VMQ9s+aoj>uv2XqG? zAX#MvPYdBw-^igplC+YpGR^_C8j0i9zqdpAp)N;UT8Ve3GvQ|0oSFnnQ}tJEh$B!7 zL&)-H?$0@50=j(q2(nU2qLTekp!yDAljEcxl{U)v+)5no3iKE7tbwswW7F0L-k5vH zt~m+$!{3$0SyxR?Tr@5as4g%rB(Z(7=`*3qfB$5#O7lhM+OR1qaBJ#P^y9t{_W>de zQtKZ)o*dFch==M3Kn=zJA?YNgo3SH*3sd3ZT}pP8_YWv|&)iZo97V@g&Ht0GP!$e~ zfmyUN=eZKUU?W&t=69r^n>ulp~RQcBVg`B3jR zdPsB(A-1FZK(Z8->bRSxMr#b4Mu^r3;ReGh->pO&jct$s2I?3;*?=ZmY=bis3RXk2 z{I<9OoD@Uo$6o=LO<~Q6c!UHXhP*QtIXlU`a58TaR2Eegf+avX{vCHO)~eXCftl>k z<~30@K?Xf%RmK@(gF>VPb0BeGBA}YHNZd#eB1){>u%bkf@3T!Fq57a#mSN;UWYWZGBBBp% z!k6t0UZqFD8*MeF7hFZ1^)MB}oBi>l9lC)VY=Y%!z~(E~sxc(9?oeT%00anKpF(OvcgGu~_7-cxCp`iMbMp z&-K+KxS@H==hsJ=j4h8BI{=#lf2T@oO|RUFuC19d?6}{k#S~=p+K6`r;NBEXp5Z_K zx1=BC1tB$hKg2>?AAB^uih0XjM7%ij&PfuaD0tJe0r0$Q9JcD&uYyD0>x)``7+S{)OQ{-1k;Q$Ov%>5-5xY zvR8!kw$ggEQfu87GaHRn7($raNNI-vfLvT?g`s{_CHlLAgA;@RI6NzXX;;Y|FGo|T z{=wVAK)gtAIOTR!!*GLZ0l*1SfP<-B-j96ox6@w&uDIdad+N#&CbcP2ssVBsufJ2$>a?}* zYePhFx{{7fPWFY@%&e3jX}AY}|02eCs2av3H0YJjdB1)EKbRQrXZ8?0CHVS3sAGxO zo)-1Bh2I}YN3UX->F~+>e<&vtC%*kuY~hdIG>Vm+)CLX)Gf+?u`a&QWhLrB}ONiY3 z`t4!b&+)+vGqoCuUp2@=ZOPA)9t6I6P3#QQ2PVY3Sv6{WyR2VXRf?WB1y`PiUTYd# z(qA}`+o4Wtdgv$wd5-~3_Wjop;XO4TH$7xjlvdgz&bu44bm+5(X3w~ zx@Fe(O~RD#*ZNwzCW6?|8rG}AqwvsK>@z#Ik;(&$-y+`IR{(}%AbgO5GW>+Am6b$7 zK!0HoLNnL1TB-_!z5iB0RC7_BG>6=Ku?$;of{)ED`` zrFl#cOvw#_FDsn}g1wz6N$MhDU`~H9oU;0}K9GhA!TUi-4+~e0AjyuwR=U|Y{iD>a zFz<#j>4bvtT+9g;AFtT=YaFiSLbt zaY-ri-(3#k(h|iR1HR|{p5W2=dS70!^{evRQE&}*oP{JJINfALu{tpET84MIB?W=w zL^YYx2eh6SsNQ7wx-z{w`}gI z=_#=xGIc@%oEoORxyVZ9|Lq9LFOrKgQd>@^JI&fVIMB>4E>dhO;31J|tIJa)q>E`y z5!&1wa%DT}w|=i)Dn{GgZ``k`3qx36joZ_gf=ONh#7Hvi;zPDnw~XQL6HZ(9&3ePkW*vSeN^Wa_BsUG5~oCcE$g|m^~%Fxu3%ZO4ct^<;W@QF)W+kI|7|On>M7Wf!#df1%HdQr}?XBC zvf6Vg;?+5hm#cb~8ij8*JvlAyI1^!9J3qbT+M3R%XX-G`gt~v$3WQa~`C)2)l%?&};xok`Tm|GKKX`~w>NpTiI& zqJcw6-OgxMce0`5* z<6d8a^UWnrs3W_M5e9{ta6nKZ)dvAPzg=H+tG-*}MVS6QyyOP*XHHtTyBex3+5U!x zH>`HgNRNXm8dJd+ej;|Vn^;)s%YFR5 z`Ci0P`8!2)$1It#rKgk{RL19cr26Sd5hMk04GYdPMl>r`_lc^?s%0prURN2-CfokR ze|c$Vw9PFZ-G`*`a3)=tfW`~&$1M|>0qZHBz>%7I0}n}j2v1xPem<#~VR3?0PX5^g zbP&lBm9rwn%H#eH>z+T=UoL}mv98E1W{d*=rzkn@4vI7R`P)I7 zfst{2+0bvU_as31V{31Lo2YOO*M%%Vtyqt6s9S|EnDQsSgj8Tn)F_W4MVM=M@yw*8 zb`ihPVDLF>{q5X&%%8{I+UA3{vzN&BEvMvG6XuuWg%r*_0vwI9Jxm4~14g+)ZUU0x zbbUZ60(kSsC~wyKRpr*y6m5-w=Wh_~E%%aSm@ZRAX%26-?HY0+fsyo?0&izNQ31GV zlr)zTDpd;W7$Tqdw38ojX8<2M%Aw&gv{~@f?IiTV)RI$WdzHL$y?ZrmvUP~h8Z6^( z?RG4!R)<^nX*+~`!qeiBmux8rm3bG)V0`#U_(jtaUX z{@4I(|Yb&8u zyPv93Q0F7?_%5I|8=?i2aTu&ho`aMB)f%*_mjxzb=_of1?>oFy07Xn(nvSh zYMSjAsrYhXSbT+eiSScc6w4CS;xCKTlT1 zF2Ci!33s}Bcxkh{C0~mXd4W9attHoHw5Cq?wcssFfD)%*WErgriaGgU|MmsG+yZw_ng)Qm{h}c;maY7@K&BH zeibO)l5O-knUz@o?S7&;SSoi?{9#JR@l7uKAzwD1#)^;BxV6%io59Eec4U+%MNFO4 zX#d867GP=~aX)&&G4L!D)Rl(29mH2_v<5EHjufE=0+N8L4>5YwB5<^=^mX0$((7Js z7T&#N#pBXi?)>DH#Jfj;CV-~!wHfqYNK9x)z5N6?dtOv-nv?JK=&aRxtSvnztJH2D zhB1b)WEz3R$ZGPtbP^uABgssih*aje(w^n?D z)~)wcmP?8`4lVR88^%qSx7E7&@Jm%>%#relYXX@S_?#4bPXq4^}KdZza z-ca`?w2SzY^*)iqpH@eR3=WjL;Q|ys>2$jQCh{3PI-zpJfz3Q3t7f;1UCU|vE@F-I zlF;eeA9=*r8)#O~$KVQrJI=@fxEV=NibJ?^3i^qcrfY#?BUoCC^)rrPjqYJbP;syH zntNM3LGuZenWa^>P`BOwpoW($m!EJx=&VU#?uXRR)I=}--iz3Gr9%fY1W>1niB*|Z z7FE+BUok18zdP8N};V>BjU0f4i)EA>kpf2d969+r@~g7x9cFJsJ_ z9>O#1MEobz^$?At)905Ad zSX-&Q{V6oxbg%wt;18Mt;`0MVvg0z@UX8&EPbB(DP@X)(5kDgr3>+&2A2tZc|2t%w zvdq{P3|N?deJCWyWsbjK3tn=^zFzeL0}LCUTMtFt*=#*tNMX1l83k7Num$r}@{acY z9>-fiwefLktd8VZ%bS&e8I&&~3o#9_PJ8N=;zWihgyql<5Kzp1-rxSOpDLC8u& zJ~$v0!8h$Jn zKz|Y_@Yp7othz2&d7WT`KVpoKn!zzNnwHUdg)K3N?tVUaR)#bL7uE@xJ57*syomLV z$0~;p#nb3rN=7{QOe~iXyYF;Hb0Z!@Lkf#^Or008#81(`R>DchB&J7l1r`%QQ!1#6 zF_u-Kz6()iy#!)&9?PZIa(>F__8?5^b<4CpjnH1UZnj$Qx3-sO8e%*otmR&{d6DRP z9wiZ5V@{(68&Ij3TJ$Zat7D&Mh(&DtsHz#q4AKj^hq?g5C}n6wvC}vY1H*fDlXT)H zncbT9<=MJEhM3=uuh`Jh*1=)}JsG7m>^|`m51t|B||* z6_S#ui2ziOgSjxS`E)vQ#0Gtm2zu}g%_HLQB@1fGs`7d*?djcN+66fcsfLZt=l9s8 z`=|Ns3N9j=XuQ56UB?oLhTrqPA#jLCY^bg3$gZh*p>&o98EF7fX4`D#d7XUdj~yRU zVFjz>J~+fPaX<>ql7W~;Ms^!bYrF5y$r5I=pVVD)bRQq}R4?SXCMMl3Nh5bEruWj${0OWV7B zd2yV^0;N!k!GraBT$+K9)Ebi@RJQSvizruz!O|~zsSrS)OE6NHM@2DrROJf<9(-Mp z3$ZTzN#Ug>@H8$> ztSxowUh=tg%}>39AvON2$O*z&KpJo}=H3xWJtZI^u?3AuS8A^l2-%}|I&X*bPv~QX zbdw)=Vxg3)FDEr6m}4mj*h2Fz&y=a(h#mf6vrzE}=wdtC zrkXG;ir+gguBaWfpM~KK_6_B}+ay2Ar* ze$wsjIn~K(vA++UinO?~G6IKl;(K`c)@ZWWFI`7GbQ`fGa66!-kqH>wa$kX(J)(r{ ziCWWcZ_B_N>EI4;blJ1N&~P|>pN-nqT^VZAMW%{2wU=!ZN@Khcsc_V%!HIQ7L7-z4 zAR02QJ-k|Ev+U?GjCu3i^}6n)(JMmp!Lf2GU-X312YXySU_8#T5Kcx$^s>I}+p_+e zK$ABcr9j2C=V_C{DdZA7^PezLt`UY8F?gUdnqAL$;%iQlT?n;-`NfsV@_)EW$9o`J)8h?dt7pm#7ig5^P&f?@u?v6Q8n|zxdBt*h4zam1cXur!=KHFZfVD9x<$C z-sk}u-|tH%r&3e<0sXHsJnZOCmS9WW_Mmiw?qcwq!R&Lh=1r%Jae&R7t&KG{-_2Aa z7us-rey%C9IVpf$Z&?30N>?mf-qM2Cn7xmUN{aqbBMwyo93xkYWen=`!FJFzU`>HUWC-E!kjN=r01g?92Md0Uo7dt4V=3kON>no{bnDx{WY3ZY$Xr| z8|ZR2_IQC?yr0qTma!=Jv*}Gi#^mytwA8Q5q392L4`etKmAkbi+(pS^5628>4e6UZ2m8RIAE;2|O+^ViF9;FD}K4-rAtM zX&TI9k;h1iTqdZpV1d8R`n=b)rjN8~Z$7>9+5jnYX$X>-M|zGbFMt(Q(Nc${YkU)a zM-q=5dnY$Mc0OW*;AsqWfo_S)(b;$rm;5#RY9 zIcvt%kl~hLYia1+<9l2FPTfEM{DqT~+{A5Sucu10yUv9njMmr6Y8rHK;&|E5zf_RJ zh<@>@+HF-er&jw#T7|HALJeq`%9>7SxevM?N>0;q_`gn{bN^c{?zi?53i#%A9Y(Y7 zZ@;H#SmkEeiuyxJ37gNhKTLY>D6+piYYTHM4_idu&NICIleZusVrJLyV*e0X<3(VY zZc8RN!d2--pc5s5jvhFNNnUO3&+{^8f z?s2=6jn!xa-1Iow%j)1D^s9hDvAg(KA6+VP?iOCmVK_T+B4lqQo9uU}_}&HHyvHBU zo2^96Idj65L8<$GhIE-<5zPw^Os@z?5E*!2pJJTm!!G!!?z5?Gyky>hz8|AUQ${dz zqrk*y>AilO`GXJ?rldN?L*j@N@#=M3#=~DkZ7D#ObiGO=1OZ7x)dfo?EGU>PiWH!R zsieph{PexzFQM--tbnta?hg$lXF8Z-h~}_>nM}!OgvlI#6k(!|$`q~j9&4ySnf=L( ze_D0@8{zWWUL8zz8?rxJzDlikMNquK+u0_AuoNO{ro|7k<1obS-QWD98^03|c3(Ay zwOLHuv|yvC;)n;wW5gT0W_$H+tmHGk1caa^lOUghMkq=7ZHeH$TwKsc@pyh~B$69# z&;P}mRO`Di8}_Kl;a;k4i_62KSdEe#13NgLnQzV{cqCB=YnZ*t8>79MEl6tb?_1px zP^(2?xLR*laAWukB{P=@RKUq#mUNxUwHyAkMrAbZlZ+mf*uH6GPA#$L(iGkx)5Kxh z8=H!<>8Go3o(#_EE+xm>^#?wtcWcEJI>;iiaf(g4j=H{ZOvcspaw$;KDHcjxcYanK z&AMwP`as66t?@c#hs>GU{3UUCRP*!$9oX2mEqh~cdB#`5lw|8e>UMcV7*h0I&wDqlxZJi#>4XJqsxjjG*0ZZJ`h@)Yx6RMG}Lz^`z z@j@ZIEnQ=I+5Agw8#zV`-7Ji%$Q|)M=sx&4bSr<7A}_^jIQ#GI8u*sfVyS}gQ;>ww z;}t6MB45SAqh9%P_}JSm{`|mOd@jpH$GovLZqDd6)d)mpj8{4hw{I*|Gg=0`+rZ_b z>UWSB)2i_JHMUwyH}1H;`+BQQ?OoGHzIw03A|jBOTI0OO!CGjRnud1RrzHjbmwti2 z$-dtZGBL@|6nU~3H+WK#Lu$4#6?5o>pbB|;TUI(4oN{Fh2R_+USTf?MH(4&Ei*_U< zAxTvsT6S$WpHYtW;$;UCARR^|u6e+DJWABKt}LQcY1VH-Uq;q+ezhJG)Vqw^CYuio zz?^CS_X4Ngwi>oC)Ovp0CBaDbYCFHgZXIk5F6FJKg{(pUKA-VYn&nrNH*fXyEvzfh z%Swa~`Rbl$^IQ3^en}DYB6CyAChzKg79~|h;lWLF|7oY|I7qR*fe84oX`dtHvP1PQ z5Ulk5fJdEijGuSkP!TiOPU~^IQYZZ}f-pZG#+1`6u)4;Gc#D7|_GG$=Znc=pYgEkhS(%K@ z>1a6S#SHJtJ4B2W>h96`?90|Sy$BXGX+w&DO7L?fB@$|C0mmsv3C$QCF0k>HEk?9T z_laCsUhAPUjHVv>gePZMxbbA#{(O?-DVHOU%fDWl(Y9UR+Zq_1^v$?PKID#B{JehR z$ncF@;uZ!UD-EcV0h{=6(AqyXTAgZtK~oHJe~Vnt-~^hgqPAAZ_*f2n zHOxg4so=K4Q1@}6@gnM8X$M4|nP!6tj=Hck5hcRIJFd8|{)KjutQKBk7AHnRg#6(T z*p@508THrK@{xst?)|QXVa?0u{B=!j`&D-sKZ)3g#B6a|-xjH@55;R}?zY5jJRv8X9Uwy;+X)k_X-`FMKv{$F|0#7+-bU`mWH#H^bUrF_+o}VA}Pq|LMkr zL!bVE$Bf7)12y65i}g1>YFTij_cd~vVL$xk0%({LibUA+wv?QWbLMg#L%|Ue_2OdeeG{}mu^YJ zED!40wY~+8a>@lbPn6eN| zQM@k46pbVNq(4yvCYf>^YSLHlPXu+Bqk5-aeb6Uj?U_psOz05BBb0PPg*GR%C*|8+m`S zX%RGmz|+7qgH+yfDf=8#Eu?gRFQ${K7Yb|m4D+}GsRiC_H;QJm5CN0HJNIu=HFZ1&UXBIT8pf)K6!bgzIfC|L zGQM>?`ujT1HlS7PhHBP+4jc|H%JT=jlWB9e5}ZvnT^T1(($Jy{HZSyv=MaO(t#T5-1;IQy zAAMWmW|3I8)cg{sk>r5KWZN(jn#*b-G9wwtg2R>B3zI$}t?6?tN@%~M$uH{pSsHqN zWs69-)*-MEZ_^oCsL9kUO<>MWTC%-ZF!2jQV!f*9GBO{)kY z_a06#&*!73#2y*M0JSvL*#ragUFu?->J9ycg|MwbzNDJq>7+X0Cl;><+HUI5^yWnu z1I2MN6o-PTwy;iR_>0X!ynzRV#+|)~>p;x9oo{s1m}H^O)pKs9vwAMbl)t}!3%7-i z2=6RDxwi>w?#)b`>%fhS#q$>JP(}hChBvS3P&k!#S?(;3!i2Mg`u(vM% zxw(Gh46c1IRAaG#d=RRgGW4rVz*Zy=_5lx1Q&#@m2mhwq364R^IkzAkweOx4SdjNz z^Ue>rXsV#54WrFpErBi9T%st}7&?5Z+NQ@aUl>mIZp(ypSv6t*qBq(~KH2;jLBet2LyANAd4=9vw~fo?#L~!0 z=yw6*Mqt}ff48JSl9=Iwv{1`(2>2lg9E)t3TCp=8@!JbBVEb>C)5D!`u976req1e2 zz=oj>hk${@u;aqYat54bY##iSuGuXU|2{#3S<8r(1UnJ3;#UZ{5X`YKk(nIy6An)i z=K#$w7RfR6A{}r?6K`znkudpUK~jln5v>LzNAyt|Y6*n2updW16{)U@tE=U!H2lpN zC{_}ownC7a6sVj~PqgfiCy?roJVS`mC?!P^?eg*0z#gb4MS-|I03MyaPKY%VX; zMh^}LS*D-HDcB#c+>47WU`O zdq8zsv*F2iLy;m95S!!7ybu*m+`!TRZH5SU%WIF_Uka?dW@7MmuhgU4K&4ZiXEowk zOAQLbD1u}<2b7Yr{{3%`*9bkSktpXzMZH8q^;`My!!>-;!TAI)7@d2uF(;zx{ud?p zvg|Q6^qI}nnTT7_{f2WFGVJxX%E#{)3(ErOaahe>f+#0FGc-eNn4~Tqdm@=!o4wx{ zABMj1`^uc)`J`f|lv#ODDVm8^UxelK47+9w7A?YB4C}~!$2A{G7e(*ASWL2u;x!lW zL3J6X;Nyf-p^9!UvneVje5-~Y20cNXu9kr4S}r0Lt74O zL9wO~d5Dhv9R1g`#v~BxYyQBO?T4oXR(Fcq-WR*d+G^zQIQOaWM@ECRKVPATwvlga z;d<#_v(<3LeVMkhs5g62rD=G*SpuH!r%Sqe%*PZYL_-ms7Fx|0Pe`m&%9JQTEnD|2 zVp%^gj;7ym86>BF#&|nMz>sLzFmQ4%ipU_kEM8n0!+g)9RK(+C@+Z|nof!ICfhp;I4b*jb7qk9&+iEH&qxgGXYjM&$0tYpPO?tXxvPEjG*^ z*3u^yJNK*-mIphCDbvC{_A_jpvW1;(o-Q4E5i3Iwaq^Tk=dzL*1w+X8IFCOq=WH!C z*3;8yeGBcUJgT~F>0z)26jaF**HMP=z#n_)aAJ^bc$3QF=h+lQnI`ng?Zx3b9Gpe? zbCD6ljT^EmIfaodB4?*R=i@g2+;>1sysyY618frVJY;vkWhCyRn#fLbZnK}9|C>b!0q)P`36i^mtVb}4%IQz6a1+kbcQLB z7M}TJ(sWX3-jLZ=I3KHLPDmqa9s7ti@8W#8nyL!^h2gYHZ5(U!wnnv;H&ag-&t~v# zECIfhl%qtjw_RYG{dwbv-U+&?;5_^v#{0@8h~Ypo2=(xeo8Uw%Gx8ZNWr1C!hapj76mw*ytBT87M}zd3KUchGO-0h&q7YEN~1de8$ags?~1NeqFFr4@2IX*p8efuTYS zI@MRvXLQ}2NFtCG4q;`sqWLQge!}H9WJV~TIur)06ig*`fdno)8$#czpU8k8ia3cBbg z^`yZX;S49=QhE9#yK++K8De1mcz-}Gm5y<({K%G34O^A2+{?(drDI>Gd)(vOwH=14 zYp*X^yPL`Ku}$9bivVi=*ISa-{iwk!_CRpu%SBY>i>UBz0yizu-;Rs{b(gh-Y?6%| zbHdTQd;5*YLwuo@$A<{gr7|Rs3^M^Gx{IQ`#C3yEjFQrS%m)NGA}ySpoBlyT(JQmt z7*9nc9uJcb8C%T^o_T^Hk!aa8*e^k%2S@cB7qDash2JtnD`EC|;we!+hIoq#l8pa_ zsZhPvcY+NqvX?!a!`j^0+zk$ylGyyqWn4caOf|&N`Lz9UFl4P&YLe})Rbo(uNm;MC zHAExWoXpj2Wwy}Qr8oh6p^{xX(Diz3eS;XqLIpSm6_T4UY+OaUS=f=_CdJ?EbkLuJ4J4e}eMQbCGf z#Zb?}xZQ9<3kBAK51vt`X}y)i7X|K@9GKv4aNcU zvFU+uVveftVLx&bQ56K#DjB&)}sN#?I4l=H_VcjtiwD(vS%3b@%9e)I?rOI8IE{`*z%4ZcU z_EZBu#9sr1fz4hG9*jEBMjhwGsO4$DkqDGuIJIpmV_D%l&QlGB^@=C+62 z&OA<+?mSMT_xxEmA=30s{l&i(@WDL|&HA<}?OjH~yOLTwn^W@Ib}wbZsdY4JCvUF)aNP&tB1l)ubDaXIb=TQ?V0H>IfZf;Ll&H*SZ)o%KdF>VF|p>FtA(> zKMY$%^oeseF+l&!c!2wcW{2hcs0cn@Sx7jsd_XD;_T#tRA|mE(r3<=f3;#gc0mBHv zFP>RB0n^C#WMKV(Q$JcV#olq)tG(XKMJOU_jFswjg4VFRdPUbiYhF|F`~=TWW(KzIo;CIC9!ytzx|YEFuaWAuz^s$wd5~i(DioseCL%JLPuw)mrhK1q;$)4 zsOCOC4-N_`Gcn}bMHgT!U^CJ@3>GeYlx{07f|`XWs*k<4qy#xgw8^zM(ihAQBbZMD zy3Uut=WV|w!Yf>cy$Qq#@`}KZ1}pWS60oF7C3fcz;bMIh_eO@1g@lW69VlFdmME?h z^iw)IC*dKv2vx}y`n|s)+0?Y|Q7M!;h0Jg`V*Efoi|4mB!}C{J!?@nhnRPQBEB(v& zXg?wZ9(L`fV}51O;Ja~xf~10hA7MlOHWudn{dZdH1pFh)Dt?pr#`5&wO4ux7wF(LY zg!jM39mj_#?Pf$+)}T@*f&*F?LljfQr^~ZwMQ>O_d@ZC*`_4`g<#cw-| zhFu>dWy8!@;qCE?7zb=eV(5rs2Z^{yLB~@qB1a0+Nw8H}pGAtAF#Tz=w9Y!r|C>pD zNNzHSnI>gcSUg`NH6AS;ff4ctN@@M4CJ)ZUZ<*R_^y9xIIfnT^%RUcrX+bu>@qI(- zc18H-Pw>J*yJRWAs$cQiW+}1JvjKt3D`4R+ASoGAdn|5m;39=?p;?K){pUVDAqhsL zj~#kV+o|Rei9$nUZonrBXW{EU3j-bU{&i2-x(Va-*J6!I3S8-0E;?k`acko?x&KGk zTSis6Mf<~a*CsdJ-AGAyBi-Ey2uP=NcO!^&NC`-Hhe&q{8X;ENTY`>YN3 zAuztSN{4QP>*-owMoN#uKi6_gfx@;qM29-@imCR; zDfc^hF{rA9Co*&E>2Ub&-{SmHxS(z!csI*c)8CBN)I(fIhO%wk=7&HZU39~lQk-mH zJ?+0D#pp7GYEI^@x?8s)KJOd~56gq4ZI3QFrygU$BP%FCo^?MQZT$XcnNPG#v4n>` z989h74&k-iNaU-o80oB`9INrkJcbXH)@ zM0bqJm<;VkpWsktPR`;S`!EEcJUh)ia@a0kXDL?jga)tPfxWXsPL{`YZuc(?Aslyg zJoCZ^6wq){|92L|hf&&TPcQ?dsXt@J9*1g{pwD_-nLIuwYea%S6m}u%*GzAhZ1gSR}ORQ8jyw}U!{j{%UL-yQ87G4P0f?^IhFKD zRH5)2+^3>U-r($^1D>@{<1gZuOD zg{Efco{z&C%Bn!cRN9$aYRU3BTMChd9~84ExjxsleBQ#M3jR5US<$7(y?` zWRC0$t8vrlRT9G4&}azWX8+9&4rjws9jG=xMG-Ka`X_k6(BR~=n?4+)s&vxzeQt6t^zbL0J*7JRf$A7f_hvifV z%a9+B?|KK7i|nQeAvS@i+7zJ;8VYnt;ZOzfYC@A#d{W({Zr_n+u3&YHRNkS;PuvpX ztN5gm9EuH*^*MEXU+>>Pd-%y1fNziDfC=D=hF#)vu8kM+fMj~3qcxoLF^3`wl~dU) zky5K%>(u#Uhv;J#IcdyF2;?rv$CQTApA|7)Voy3aChIZ(CBUVRAuZ8a7e9zKn)_Ay zfj!1h@Icaz;NiHJMhamOq32^Xw)K(JAT3raL7Qb_*Up4z8mOe6HlSp9-T;4a{8H0X ze{vK!0qgx`Kk!X1H#L$z^Nx-m!foUeZ!H+w(9*OKhoT~i9K<;P%^~{!IfmZTG2qQ` zIDaWKw$OgsU*c<{SB1UZ&16Ha(Xi@rjGLm<1Fc$PIug3jXIXcuv)V!z30@(SFE<^vxOsymi?!WMl)zlk@CQVY$V}w#9Wx zkcTcZWmeT8=JdRHPAj$mC-?gi-V#DT^8$qq5NaF)R5yWM!K|1Os;gB-_gAu=adXx9 zYcvnNLFWRA#lyGfkiSLKJ2?J06&aHyGexBylXZNYGi3CONvwJTQd7nwhhN}=>r$GN z3Z?N+9Wr{8^7HhW+-u5bVv(MSC6Dki`2J2As_UU>DWbnNWTaRNXEnej_??VW4zb_Y z;vc0u6MyCp#xs9}XrK)dMG-!%?bH)C@y2m2sm6$}BQ;*qqD_};%CT)a#Bm1MJ+13q zdO8*#q-JVlu!@ht)Bq1-aGV5%db3go}6}$F* z-m|SMg3KZG%$?4BlY`^z*{j`Jbs$b71mJw1>I4i2xU^D3|Cq$Ju;j8?{DcYo;^QcC z7!$GbG4daV_M-TJfJ2%he92SghB`31)?%T10c?Gw+jQVKG)aQJ<@?#csW9xpF=(W^ z$VFq}fbS&Rh6W-XhSV%x|F(Npip~hYK3u3*9=x)Bnka?K<-HgnHkjdxodiEva@JE9 zAvO5bYHoyygt7`18GPU9Hd%IAlH-|e*ftOU$LNDQo}w2K^TDMRgdWtKm*KP0|C)WX zvhSJ;*M*?nVn35Eo{XK^{8>yasZ~^t*(lR?P+j?KsNXXU#?*j>38ZFS?11&dDxHS# zYiyfJu(wU>agdrO{rTKzFecJTY>TFm>#x_Mvbm_sx^Hc^{MI zXpTzDj?2YjHxFzeQ%$C@yf8z9o?`G7tl^Yx(3ugPjb_89-?;#Cdv>-$!cP+a4*x81 z;QW~S{*W5mEV>jPJLL+tbzIU#U>msF`d&!QWb)1%K(VG*fOg!EN5;t~&je8Y!d$Vl zX;M9ou-?H#TDMpw;w67I8B^Ts42^t7K!cwKF>Nfi6>wCA=cDe&KbwFSaL$<*z&@hp zMsY2;r~{Po*j4gwKb`6cT@ut~j4TIe0JHpgq`o=)Yys0x{CP}Df3g6;lgRX1ez65C z#sW}$z9FE4SLKoIJ`NCvL-xGAyY)ZY(}U{xC-~!9G=s$mE^E06E`dd)CD*LaZjFj( zbm=F1qXa1N!h^BI%=TuIvPAxAbMOmjDvCbiL^GjF4R0HrEHkb5pb;}iJY=9qy|Q2X zs{&wluW1M(~qkg9Uzq-$;M)vkEJ%Xc;51byL)ArW2)a*Ec z1L4kV)Quo9dFSGZ*8OK%@t(Z_U<9DLW2a`|nq&x{$s;wv1?YN0t+uuDti-NnXA`rs z=BQ3~jm5PQwN~?a>^0Z3+5|j>#P3$l{&G)Y%;x|IW1O(e8ZZ6?e2eH(WQ=d1bDY7| z4Xd}fm9vA?xTOhert@eDjOoyAoeC1VWb7Nf{Q?lOC5n*k83V z9t>yijtw;Wi<1Na>Ie#l6*G+w`xFPMVc3=Lo+@3UA;LjG4Qw*>}iK8~2N zEsH2n-8eps8q1UD7EN}=3>=rzR<8R#n7~=Qorq_{526J``dtm?iR1ss^tN>+6H-%A zpte}Yu)%dTXf#6-c|iv_!V&C5wGluMyZ~QeLqwQg3y2rA4k$d_;^zr|%iwoib>Z*P z{9E)o`Mzp?jb2Yx^366oja8cj*5n~Sd%?wLFZi^CKRD+N`;(JZu&Z|WDW%4tF;3D} zPIXX{W3ps(Bd{h$N8Q$x!|L0?d}0jl$%hw~F$=!PlQ(rn_AmL*3Zy>JR}dD_AX;O-6BRk+*=VuOtDQf&$O zfr&5dOv*lF#LXWc>la742dUvn4nec(S3$c?DbO7ZB^fdrqbCNO6nTsES;h-E*wE(? zj`AG)fFIa3*j(Tc4rtSiJaS>?YlB9))fU<8%y!U4tYy;cRASi2r;yQeJ-71yDbxYh zjo^gCs~lKd>f`u6!^bgfKsY^u7ch*n62q9%_;er)#S;807`-Q77LojC4Okk^{iM^F z4YsQPL>kJn*X2Hr;XEXYV1ofjO7c)Jn+(WW0eTGFOoIiU90Ml4sAE`6mfiJBk(`(; zX?veAJOmFWJ&Q_41Nbscxw8Jv-AoVqO@~DEFVQXh&lbrTe9jEpb&6|AR$HgA-z8gJ1|8w2GeM;d*#bnPwg!8NsRi z&7xdq6D$xyDg++pi##Gg7+5JOQA`?Tpln zGS3+b>;D?^4_ibyq~gupRNiD|Ty+05ZCNd5+Ll41l<1UTN5DAY-X&T>bx+LVC6b>s z`4Kz&e<^qSQiD^+xM|4FX7NK|be+H@0biGUJJl%`(+aw%tA36qS1|CrCMo$pYdApD zq@F-3(?lcj{RMQaZqA91! zF(#A+sj&cZ5SCkO%;Nq{w#`+BGhaJ7Dj2|Wemq9?|KqcjY0TRUl5h&%tvm;rvSqG@ z*aOlvnoSZrYD*xj&CqU#5yR#`sZhD=nkX?IXGfh+cWO-59@q_imPW#jKzq8w)WuEF zVU&b{hkiUFZgyow+GaZwxaB`(7E&kwI_`H*Or`8|5#sv~<@C}Lb`_4Z7>>-FO1j)u z#hcr{KPpmP*f*7U2oBX_G2^1teOm{1eBc2Gb4>wQZ}-UhWxPtK69_sBB(bJ&sku;e zI3O&S6sVQPR{}Opy9jF!`U`OYXplK4ou?$_6K_rd}Ar} z?>;Bi2*aUugBVY_8r76$SY{sJ93SrF3)0Dkf6z=TCL3yn?C19hJ>f?ytP8SoM zV#7v9H@IEj83H)H&M?4?Pq+3JSplaaIW<-fgzn&h+)yM~T$hC+;|ON0)M^VI2}q4K zXs#8P~@q&c`WH@HmC13hL`;CJjfbm@s>k z^w|ESR3vk=CuDPH>iJK*;Seyq(z*hDx1kzn31Bh)0K;8L*9hOpjvmhrPpE$*9ZYR* z*0~@vxNkE!BNc>K$uPk+i=|~Hs`$lOpDMPc*)zU?=apr=1n>Zmdo5w*=T8iA1uUSV zjF?(4m!`atXx(Ilq1fh2VbO;Po!NC6PO0oBl{i?$Omtp(HXn5}Wt}Vh?>2%&Gv6r; zimas4-kPjcPp_Y{)d~Ftq=F@K;^nL~#91>H!Sm*$&s_O6k>8znQ?@Y&I5@s2eb-qL zMLEjnUgN8FEf&FAn|lW$-s!F#0vn`;X%&nG$Bv83xJ(ztbu!F@n^nMs(%YSU?38EB?Bb*AAmJ+!HL2550wCx2n;6JT{3A zp8LTJNxcf6Er<2TbM?L>SD;>tmoJ40kw z-B|mi&YlF?loG95eY<$7a7h385+;2g$0bgv};H&NjMT6wH+iQczW@+XTCrefDY0c|S0x}t9%E~$A9|4O){uF-I8u!?{V zAN+mwP6_^C`|AXReQ}c7)I>I982@~M)hpdqa+QBFZ;cT2K%s&Hu1MF=GS(-508-0T zqwhKxHo(P7$(*|l%KV-l0nfOzX_=HZ_E+M7MgTW$T-H3g0q_^G?Lf&FBvmwU86YCJ zOoL1I{rIATCw@mrvx#`@UE!{PBBu~O*4&GqbfA1Ef2kAi=IG@|;7)|a(VW*|sE2mP zx)|4@FWjNr%)(vG`X_;O>F_vIxWzizeE>EpxXFi=Wxv=M(O_VdUD1s|?tahyHK7aN zr~O<-@L%1p17zes7yZ__i!johuymbeJRdb%60e3|@uH@V*Lxq?s|eZ?-+!|T7r?>l zP?>M@RsEIN20)#fK_SUK(uKjbV>d87G)3r3C zT(54Yj+M^WXfffeD)ks1xtbxP9gWVW(u+}w!Jpir!x5sTRa9o~qnplR2J%0$Z%5Q5 z+G2jj+f&d6z;#Wj0cZArz!Q*Cb@*jjFG=h<@bXKUyb;~MKvI{F3X_^)`yrLe`FEO0 zLh|Zo#9baS>R!*2mXEBrv2vNewL385*iky--Cocsx!|LFTS>neC)}d94LlN#5CYsr z8Y2t&dXG{|z8~Yc05{Wl(3h(#TMAkBY;s4v*65@M2Gy#0G4_;O1AzZlz>AekBr4QraEPgZ8{qp0ez_WX$1}ze$)_ zD-rT^u~9$O7fs0A=Viw9f7ge^tzSyxseK6_aP4u&c4IL0a^>+pIi~L^b_x$Nj&IJA zB~}T99)}X1tT*qUdCL{h!=-E3bJ)m0QkuZnwj4*QZUmDx7QjuL*EcGsmkb?I99HT^x^+Gt+a>cMyyA_;(1dqR$HIRsjY_an- zPhIO1tf#i%hoA|3FmJneF6W3nmz1L9%WAWF^5&W~?9%JD<}wQVz*Zp)h?Zrc-Xn(K z#fOyX8W*8aYo2`yQ5A%>xiP>eBLf90VL^>O2FIn$qEdAYUDQ=SffCx}za!hEku;4f z_>ScVx>fted^#inUn+*ga|~ztXszaP2&y8p1^L3wN6I1^8)@#gn3F3pb z5J)hXHe(Uu-$na0nRR9~(4|B(LkciTX}$0tF`EQe4jM6EO{tOoK%3u=O_K3eT~i7t zo}RFxpygd)xPU5Er-4b^h@75(X44zm*3V&~TTqJqkuCGjd^M*3Yo&Tjw6wP>=d!-@Vw#WJ#EmNNl^ zo^VH#zAX89W8AP*fSXg?#bmd-{FJC6%G%;-RR0If0C#5iz%bar z5BT@%GTrU+*dqdQDIyg@@EI-Ka2z=HfRkyX`}8~fQ=RvF^+j(l!Gj|WWAKp9%-gnz zm9x{YCh9)@p8Qr$miQ`y?g)c}9j9=!uRUD@g2awiJy2rZlnNTN505Q$i4#F4?evo3 zWVG!U2bRRNNc1YW1YACF9+&vSC;U0N&4lb>1HS&|Q$MBayjJ*^Z>C^9_#7k&D9~iv zY?gaywkP*&W4aeJg%=8J91oVNw)bvW3+Z~`ZZUo#?UZ3gaO~@rG{-C-Z+d|FAKJ76 zD7{zJuct)!ite}#5mwT=iLQjNaO{8!8e>g2AwT{-j1FJM*=^W)eHdkA9SXr{E=qEq z^x$QOSvv`jf9cBFx&wJiZSkGE#n2V0`Hq?J3}+HwL%&YHN0l^sZgV%Rq8{M~&mrdN zAQ?4iriybC^b^sJ*c*Qv<4;On6D5Ux{M&&R zN1`~5p`0^`S0Jq|e2Jt)auYZepkHrKUTx4$oJjdiK2DnsL+}$a?>@%a2sY`eY^S}L z(AyFi(>6N_veiJi_N!lTFYMH!`ik!)WURCIjhgn~j{$8o@xb56)qew7>AYj2aw*zm za6~HGd4zrhoOnBX0dNkl;G*Caa{3?%_MD5;yc-@e;bdg1GK|R9L9noYt}e3EH8e5LAFt4zB=G7nOt7uWutNVhGZ$zwQ}5}6ZkMiNTCzZRw|&(w zUr<$f6TQ6#AFa<+(z$Eh=RRf6(ZMx7RqE3tTLJQrny9M}!FDc>Ff7nh-{rBtgLM1* zZn$%n+uz0+T5Sl*0X}IHb$8%(tgH^28u zp)TlbMKkSkp>VqOPog?Y>JcZcF(s}kC<_VE@ksjS?BT`t z*zBCNDKOU3xd-{j> z2Jn}1XcPD6OQK2L&U0&JdD82qvU&IW-NruqUza4q$g_oxZ2yF{{=A7FID+Nm$PUXy zo>BtMyxE`5`*LtS zOdGk#DiW**tvDuUnPBXhyf8rE(d1uXKG4%Y{hAN7gnLI&aG*s3k2-Mz1C9#GkqM{B zQXQV((^Ppx&gRV}hT<`fk8LCzVOJLQ8`(+z_+C5C$9e{84`>gcp8dzrM|#153? z7T~bvh|brJ+JCHVt*nWKJ9o`(jbXclZDe=n26ZAdbyW@~Lcvb?=@i(1BR!+yPnci5 z$oW=I-IY%%W&oStc}+`ap>$o&nlG7F`!^f=*2?c8F-fLfsPsbY;ej12QWdIb@|j;? zr00n>*eKIr$#(zoZUgjubBXg&E#zL$D>In8WR#Rf866wUVaKo3V$39(DZCf52HE&3 zo!rU;f*re>7%#4W{P8Et#wb6YKu!dDne*B|6Ja9C^8L>RA4bBi6 zSYh@tLY57_&FdP%gUF6NJZ$*+knS`q*qtOkn!=XTymxEH|B=~GzSl#Qetb~6(>8S) z?)vg;X^Gj-Bd*QGaG(eyY!V{m9aalVXjKOhRtrEpP^f(M(x1-Bph^BnHOJ&nX2Ak4 ziojMKG;kY#evjBk^Rw;=%-T<8+54TWcfqpf51|wlF!v{r5hw5ZfF%g&MaNVCymGfG z?dS%nxMe3$F+&%-4*{JK!STwa7t7{o{_44NZM!z2;A$vO{zwfxjw8ij97%^+Jp7Hz z4K`6Ykm-*UdM0a4G2HyGoU7k7`U#7T_1X1ugq-rqKrKq#@4&3*`-jWg$)$C>FOK^Q_vU*1#&=JJGA4p7%NIyix?ji5HmtnG4L?bz@>71v zVG8DFX9bBFU6A$Y2+G6>aKUv;2Qx^pEd2hlZWhuoR#dktvt;^7>J?MGW}sVPH1vbu4qfYB>7!sLw^1AGwSKr zbI+2{%o5bEdyw^_{SOytM89`-Xpai1OIm*AArx(er)#l5dLM3m@!H9Y zUE>AOUrG0A*`cEvbYCp%)nS_*GUN-O{WM?vQXIk1i|F!zrrcwIJTQC_K}5KYNSyMw zAn2Ys5o`N`930Z~>KlBZ)vw>$6m2ALU)}y)^Xy+xsJwdIE31M&PWqb;zQ7uKcXfaN zG8zA41f;9n+uS42`v3?Z=3Q;B-1rM*Be0&rWGiX39v;K5$Y~H>Nn5MJCV+M9C7R55 zno@<6*ORq3_ZD1EJuBy=PX=1@Z%M4A7bSZNH?|V;DH_}n%XIqLZ;Hm)S8CKqIv?-S zk^v|gJnkz`9}Jf#Jjnq_KcfRCRykJolKRt<7SufUTWE}X5qCES%-2>XKK7m^AM%GLc))2KBc16htAmt2Y-0UGR zo7ALw;ZVSIR5N^=Kn>oVQg)@PqkfcUbJ3YSv=ss1f1zhnvE*mpYEFww`Qd7Z^oQJQ zJw6a9$C%wL%ex5uRRnDXu|#gKKdyQv6YwG24koBPZ`TJ+SzM*lg zGcCq*4!x!$>-`2_c>_KQ7HSM&e{kR%4h>|Fjp>f_GfV&Z%f2uhyP;%8&9BA!diS#( z*>FIz=TQ*$#7I$TE|(+PciWy;^zYV;TcmG-x!isvqXhyS)<`=gj8=~I^vS>%m!`(TZx#PNA9D7Mu|=4S*6m;jdtvyK z>Gxgt8KKMmg=|%3A}GIwTQ&2iXk6JY;D%PhLy_)w^@Ww(l*;9d6wY6HN#fPd9#CK7*UW@hW%h&DK6<2Cr&!%?3KQ$=|Z%3?EE(({#8K`@(|1Ht0)54u7+7(r{2I zIfBsONsNdlN?Xu=cZs_l8w=JQXR9~&TxB?JTeBhK7J7)-3kz|6eu5XAQoD9KFdng* zFd{HA>wm;`#@D|c-;{zD1aYjQxQKPagq_U+`Jzi`ttk1DM-5XAE^)#iw?#_$%lw;b zFVG9yHU0#U{MC=%ad5i?)Rq_4)ZIn-FFnS&{BHsaW%wn)e{5 zAt4fy$Dn0{TluOuXt+-b+gQv1qU+KS=k|y4Fb(^*Km& zO)+d+StSK}LZs0je|ry3!aRdv>c;v3DVk(Ps? z!=Gu+UH4nX6gr&=7T*GY^likPnfA3io3DE`wj0|~;^8#prU>WvOFh-_ap#v>^VYoI zX~~r@F5cxtxe-#bMRkKY{fOF$852a%8?PbyRRRQ;i=>`Er49cwgy<2V@#IG9moT|H zc`42c=`|45kn9qq(n?GPs;#h$R*6nSj8AYlSvpM(wIdWQboSrGM9Nf?I=ma^P0~m? zYRSJRk*d$!r~jfBb^h=|mM%71O=gb)1f6ia>?g&3N9{nY*6XJ0ZrX|_XZ?YJg&}+G z1?51`@l)Rsi(|geq0xqGZzgy9i@>{np;$$(yBKBjtx;2&>5o{2fuj+1c5@cjTWzNy za8BhWf{XZ8A@$}++7;!g;v+NRxig}~kx8d6B>GT6wAQ~MS#5Fu3nF}-_$X3}ZiW4_ zg-Z4yHZP7mJ#IjCv2hA|=J0Hg zEiR9j1}FtBQlft^cu({qqjjj_ zDLI=c{7 zmI?k#ob@VLn6evHt~4K0rnwPGduk+qH4^Qfc_8@6tzt7{82MwU-zgxaZcROeT=XD#S}+@?o^+aw& zHkN-BPx^vn>`kE073%2W8X_yT%7||jr_8pP+k1>k7Kg3t5Rq$8L?AO*oWe$Ndd2;JlLlpAceDYONJXL z@DMcDd}mz8_(Iu*(A0Jt9a3MW3D5cMM&CN9q_8769CIS?1Jdq}{#GWW6RS`*0qOYQ z#YkL1K$|gAiE)?L0Y6!tw-iZgch%`f*e@L2ut1RyZ)wPd01oLP2?T@*UO8T>zMG@+ zwzKtt&&BkGQqd)eA9?hd=Cv?Iam(n)KR1mx_icAEnxE}&x)P*(>DvhByWf8h(U@<= zNGi<|@`H_&sn;=NLbV$ihCgGjgb)?rJ|x!%o*_DwD8gezF``wLdtEudWb3Em=()hi z_MCi^j5}jO=0ZWscReyme21jU{31&ET=CSu zPK81!5h}j((fn97xfQ^-$1>vRCx8}ddg9|eLh>jrda9$e=Sw;-K8=U(x7Z`Bm1_DZ zr)2-V9b#dUvAGos`=T!Qy23S1>$d`I?1iT4$VAX-U$)#!m25HNKYMQjCkMkn!xj;{ z_k1x12i3(r-5~0+WAt=Pn7{o!LcBgKrj(U0kxW6*q^)y(qZ%QHQ{q6UPb`{h0g2ae zB^lPMP(P1L22Sh$~#*N)p5nAXN8;{1L(+*~x_-8Gqo|rgWHAqAEX27i6AKOZ1XHShiw7GUgn2fvWU| zLqsZKmOgAo-<2nxgc~W6PL*Jh!(r64=gWs+aed%|YZFp*6V~QFmlKA#wl$tF9vP%} zjB_G0djhm-imD_Sc;3&pGsJHBG#Cys$mNoNT(AwVFS|-zQ5-8gPqSe4*573+bn)d! zOiH>83O|aX0MOBp)P6U6i9T&(c8Cl_-RbRMIIQc}#u=`{(>5H+MY8?TytQ~50IGW* z7VH~ObvIB354O8l%d)@Om;s{$@!9WWCvm z{kKd^p12`b_awAt`IJT3F?q|ePFNsTPzG1OR3`PQni+U|8EL^hM}_br6YWB{k_QPu!jDZ%IUl9$sajuVU z-w3It(*DqS1c! zFoPuMSiSwW+GNfy_az_Hq-7aOH!B9M{do@LKBYJ=bN5tziYU!<)H$tAC8 zu&$>tv{%t-qE*_PN0%6-f0+FZ_pIU1=ixP z(RF=AILb%O-X{qAE&tjiwNR~Je}8q?l9%%P;yXLB+An`?0nWw%oLyDZKF1vU1vWrn!^fc~kY5E7&VqkZ>$%aY&{DSsP1*mUj}x<{^8k zaEmC8FFEa&FoM$v3Jo*zR{^PaLm)QB#oz|+1XZi>*^*Nm>56Z9O2^aK2Ge=$jY$-Y z;tfvIQknHMEHRkTI~Nu80MuG>sgGLh2+=y@gLwPNWjh#gv`uD?&jf zFnq-j2UM9I;bL2I)(fz(ek?dsnXjGl-YR{_<(Dq}8BHp`!?B#So|86M3m%CMOyr?B z$mYT*MjhJ4icm=$4yMkw5Chd^c#pJIV)|slNTqdAVNH=XcOU@|sznW3m${ z3-PFISCdMk#|(^ZhwEOmY&ehycgyx}f;CE6Bdv7S3Mx)ocZsCA_2}5=WH(wCcI6qb zeu6Ey_|47Vsiw(dSPe|0=_b&{!~G$RzrZ?eD)nJS+!rt!=>Jji`!qOS$SGL>CDj=n z9{BSJoi!tbwY8I-np1q~Wdhc6YZ)vVW?U_rXwS8Km6{pXdjNJz?sSA%*+|-Dvb%5+ z)tMvxYU0!@$HSlC{oZRXRjn&r65&g%e?Sc*DA!o90EEF)nt6BrDCB;108F$a=s2Cm znxM-dW&4Lp0pnNfVpJv}vU`VS0w`TWp626E6-5%f2tI&lrdRRRHi?-)=NQ2L(GYSz z1I0m>HA}*W-qzsJnice$9BGBfrW))&{Um;`w1Y+IJLOq9fyetk-R8CZHNTk{9G^_{ zm~VTn$J3YPcwV1&8U~1=0ln7IvH4S)`tRH8bR+Nf?V&n7 z?j8?`4Ig8&@)&yQvngVWaAXo4BX%gO0kCY#A43Z5f@0+qdnD8m` zR}j?Wlqv-SHBU0miZaViE!Heg{}3)Y0JW(b=U>)zR67`8-T&x+XOc5YYXN$h(k*0Lur0;tyh zxq=oWH_qg?JS0OEauAgKZd{dw)dS7X@fWFp?gv$bJWVwI?v)fU^@7SXLNt^J)=!bP zUv?I+88PvAgD-)|0_b}T1$zCFjczG21sn7m#y(-|YOE&-0Wf(<5oI3$9yiBZW8w}) zA=-A%$yFalP+Xz@HY>oX#73~ddPxV>iIjsSz}<9JIYg5W7^5ACyLtjF2CB%$@lMx% zyIG$VvI$d}yiWQd9P~VrRPcpnnr$=IjX(jz0hke}=BXVr%FuNq08oKY@EQ4{!M4*} zAl|0qIiX=di*@xM!Dd+DACP<2*x1dMU9eCw@zoG4V+ zO|dd1o;lY+Ur4C=MU5SRx-6gg59$&q^X&7YWCQqK8aeJp0AjV9S;Dyj? zbo4WL4v!!;DxG8(B;SGM^q?o?^1t7F6(docTt)R{`=1Gjcbl?xoF|t7Z2eU`A|B_J zYpNU2lEp0?2Y|2uzVjI%jsr_#)uhl{@j(N?bm4NxW6lZWI2f+N$2N@W*rUE!NYh3) z;RWy;&Wfp3C|-&P45pWU5iU#I007?Q31>V$!Sgh@Vjd=e{&ch)W#U5R*$ihxU^F0= z`3XG=j0Q+DZ+;ydFFU{9ege-*JkeaY&IWWIxd4CwRZXSPJn~$TSI)5J*HP`|+y*9c zb~q#6b4yIfL;6%6$ zd_$m9w3%LaTr_=oND$R5zZ`{GjtOpwI1@o1a zDBWk86oMsy2BA`#GJvOdlkd!c^fQUE0jS~~E-?)FKN_7GUxyH9`=5>jK%xIdx4S(- z?Eyq946G<&Hb2n?KR}yt>Kl+tDb-&TSvK4{L25lvq$lVvyI$YmI6&kObGA<#Ohs4j zd!Htvmtu)esQHjyDFCMTG#J2ifS2-?d2=RGIxEZwc ze{&4~N*^{p7-0CJVvZ6q>I4_4zzho*28aamE+vu_0+oC7;BJ8--~%^3=fJSwJ~8lv zqVJsf&!<8ql%b0bY&PNlHw#dvZWY`OOa=V^tca1IwXaW4$z-!As%rrd_1eou%-D{2 zBr2V&2w8N(z)S~%F3f*)8V3QT5g4T5uqk=5__A{Vm^=Um$7n4F6a?bgtf;9cm5I5b zZYVWV{7-Z_{CA=Cll>}ks>BU-@nHhGN$~0i3qEzBs%+PSd1{r!wr(u8JJqx1_MZ92Cj;E!kkO#-vkU=1I)yFf+C3mK2PIg6qc*Y%h9WBm_?~wx@L^` z=R#pfjsXk((8|1PT??TQ40wtTSxf?ACKiKmF664+?Sk}(FcF#Ut6LL_{@$qPsW(99 z!LVsQtgj;%;D(}JE7TT^(K8Pkk=Afjyyht46MVBhFY_1?jIo#hZ4{Q~)i)7=h}bsf z_&o;J>&}~$7(LP%x}s8n!|QZ976#R6MN?|o)o<5MeX zd@`lhqTbfz3)C&rGsV&(gZO{jC)^8pPcijWyoy_P%zA-<`)suIyhvH?U7`E5b<3sLd-hEK}9RfJs}f7;N-vgYH+y7*@V1yTyBbTcC9s#$RxP(G=VdK|xiHk>O=2R}XKv*v$&x~D{CYdmi#z@!)a{?~h~H{W-( zKj9E%A_3Fz+zMtt^3k`y{JZ-#8SGbU5sfa=%K9xYgTPuXVpKCzvWStvN=+)s3|Qtv z3L3AKti99dJxj>KpLr(X5*c?gv_mXu0}~2fUI+N!zNtx~gsA#No@UY5zxr2_VQ#5)L23NG$Jj!Lj}G9 zSb;|yMNy4y3YFzoBP0K6J}|R9%6^RFfF1!?YTtHG#Ai}S3 zXv?uk3y+gVfnXJGw009w)^kMUU3-FDF_qD;$7QUM%RR~0l8Ez52L+PlQFUkP0P0j) zyPBlIue|U2V1T;Is6l?OL_!|T`G`b+1bb&1Z%9mzsJgLt=f;w@ zi3Yma0@2T5XK#pF2EkgiDmun`%c= zf4-#JT{wzD!%+X@@p_uS_p6yeA26P|)jMgWt{Y!U7GIMPL*0NAtsEWsK-)f`h=<%a z=>95n6g<@+HMk}_FQI@jZoO1oj-8tH&$MU~iu$ths|!=6X)^r!;g7~j7O$AsJ#Nzq z=9(u&ne|2szSmKleeL%bc_})nXhQwMfh%fgxnP+&hUn&7lFo7P{i<|!lm2UX#kHPP z*0*DNRohuNK?6XGCiFhMSeU!U2)CP$PRi1Ot)0SCT~`}5%F9mrWhxIbF4rpm%{{m4 z%^N$Z3Z<1xJR@>R=5FGBqf^|Ktg$Qtj{B77*pnCvgX%*0X+4zNM4rpBet2h`;~R6x zuX2%)!75mMrI#f(4BPix?FR3Su|)6edf{D+PyOtO{MGeU7)X#bY5ab#&xh-j)0*OE z`&8VUjV_V(^RD|5nG9dp7WcvA>K;e5C2_#`bx=uVtaPA%@V}r_7*`5iMo15nxS}x_ zbf`R}y0WLf?{E{SHtZz+vmY9-mKgHBMJ4LI_9F&Q+qVnUyd%lJ1Y-T$5FuZboY?=F z-Q5SHsLQ7R{qc*PW@EF}!4V?MJ?t$OL@>JX-Y)rrtgO7mV~S|kTjG7^_<;tQuw}04 za9iLV6YB$^=n~czulyw*X(peCwl(ok)u2;2o+&Jn4N{KwZC)^UVUG!G=8So`Q)4W< zQ7a+g#2sEdm}n8vs_Wz()ZuM)dDjO`|1U+6R5v7pE<_(g$Ntg&EqH{{*{06{?0yzl zeiu%QgRJZ?Kw=NSh}D^PO+}+R5>hOJ4+*~LmEqa&X{sz)@NV1co&F&?;4$xo{4(EC>u~~NZuLf)3=ILt%dRjK zZC)H;5{%?cQQ}SGKR91sh5P@Q(Lz4O6UIuV;pv*C5cu~cnJp6pdy28zRn({|e*Xz7 z^T3D@xz7F7(c@(S=T4N?mhQ#LKW$n#pBvhZmyNpR(jTFV1N4wa|2b-(t*?);2Hm)G zkgb~=ZzlpFTxVikV_Hf$wDdF4EhTxh*ygnYP|Z+{>irL|^Hqtz$i>dhx+o zI81Ug&Tia`RzvvAnG$rS9{Ji~J`(*h>a12Jt;fMGFZN^f^14a9GVWtiL9(WS;9Dfo z`-fwp>+jNL=1y5;!>XikN!`M0pW)%msaT0dQ*=9x*%S`w`iH*-)zNZJZE%Hf)#)nPkLwG zhd?Thi3;4qMQxbhL4STeTQE{aFvxl7FJv5e)t2aW^~(>f5n$&cJ5hxhXZrIfCy=~I z^qS8PB&HImYX(Wpc3@fql6(a<-OzyP{E|V0<^ahsbI0+@s7Wuea{SeJwhDi~{aKb& zGNSTNi>N2@hqng^ijzNH7o%ynQs(#w4MurG8=1xa=gkRegoY}wfrnU6ie|{ID_}ns zYy#q5sD3ua%9x)3gteHhy~?<>FJ2%5cvySuwugbnA3I^=jP^ngNfH0-H&jPwZg!7XA_|~#pv-ndTW-+K8L+Y6C1xS z*4`v7|L3^QLXNk*ea%)60}>YkDk6wbN+NlH_RJ*%eX>0q%6h26NUkXlxYF@YHGKzA zlo@(at=vp%<_Mzx&nFzZbUY-5uosX z2rsbNInhOn)zFA-%XkxJeSvGlND)ZT44%)$`93o+fS5aPdKYJ`om}ULtXA?iO9T-v za+@0dr4e{wdz#*~HG^|gEYj3r+A4cZwCtQS-&f8tm{4=OeKr;f1He@Q0#5@kl2q2q zo6A>&%)M1`tF84({_5VnE863eyU88ex*pQ|=z$M8f zxe{4ifY+}U23R{9K#bwH%LmwsLalJkYn~DaBvOGGL#8qwA@@#IC){vY0$*u|4gKXN zK46$G#D+m81=X6~_>@zzeMOqp@wR-H5IoQ$Ez%|iUAkdi^=!^Q3@sB6Ddy`EBNw?naMt%i{)X_1h=Gv_nNlW-&($1PV(Eh)V9mQT=UpL)4q5@#MuU3<)?Lj zsAmLy9A6hwp*E>r`10I|E+R^Y?TFm+sU7+a(RZg>$br)ch_G!0(qswO`F#m|>^oOP z9z3feWCT=UqaL5oZ*>$}q9j{g`MBlH_eEL5b#)y(C4`(E!j@Dg^!OsDc3;g+6AANt z&+4PYbL}ffRCDFu@eeb9zG=l+IWbM1yPFgGv=R04gsPAtk&FU5eMVamUU7K*!o9sP zi$;UL-u|ll1I^*}aJV9eS-Q9S8PXZ_S5;7DGUbHzOMXe=AD$GJdW$=IxEGH>jTuzs zZik9#!d}r3(fdDwl@V!OpAcI?PF^G=S7Cm3~Qb`~yp&ZpvpW(l%C(KEVJ&H8Dg4*`#AyP`pA* z1&1puk8*z37Y-xFj{j-dOLNuiT0Lf(uK`Rm$M-sr<&OeHu|$L)gB`xk;o2AGkJr-x+R^m z>Yh^d2V>w4QBA)vQ0w$N(ovcNQAib2ju7do=dP%I1ellBNyv?w3YySKm+MjcZAaVV zaC@1Whp~qVqAY$>OT04jil&l|T_fABa9Afz(P6D$s%)5;{~KT}g+;?|MTQBrE12S- zX~3phClaew*NF`$6;rX$(*iK?^Gg7-HaC~JWV_|$iuN5{s=@i#8~LoDLtcB`F0Aa% z1K|=$@wvM`%a+~YPn*g0GJ*^Su9fPn`$=j3-}()zWNgx4KMQ-qe?0Fx%A(vGi%o|X zCXVnb-k2w?5YkQN;nXky2$m!S0+I@o8T5}~7zf#hqM^nZ%7BhrP(+$=1FSy{CKDhSDlR9aHnn9RyAV&nf z?!hgvA(|cvMuuSL3#Xo{(L2@ATH~?}vv4sXj%Cd}LU!Hr4?nmB}t@hBr%u}X9R4umdq6G0N` z`CF`9%a=S1LE%^2K6W1qmg8kNb<3P@Mo%)TFEL8tp_cenHr;Q0RNJ`5*@CzJI@e;& zjb}K`(F@!j%41UyEk2`J?j@+_HpoW%Ki4dI4*L+(QIo)$Z)udW5h6r4hUyHD@7niT zSzeG5J4_>)ZtZef2i8+vm&PDO<(B0wa1og)wKE5@y=911_tocgeoy^}e1U+{ch5ZS zQK44yr3ED(XU-t92=3=tE;V3B(%}0$sy{J;U4aVUV}zz68~ys-?)Kucda^7jhbp-u z;SY@CO=B|NBY(~icoUknV$l9o`)s>>;*X55$O&#vf6Dz~=iSF>F>h?{myT1;C$dXk zq~)1!kT@DE6joZr2yVspcFgJ>4AN+?J2s2#9Z+JdeP4#hho!+auT}}fr?A^^kj}P= zHS=Lee@GEnzI0E{kJ3MjnmIfTip5s$+;vVAntH`YN|slUOOAQ`5wlemjb={{XV&<) zNrwy?&X-N>U_#D1XW&69d9pgLTDVU4S9ASMr|HdgN6&D zU*PRBwN$XVeu?~CiiWA*cms&T#W54mo^eoZ#gc~PlSWzL!9<0lyN^tqMm>HH5RX>x zO(2rVt)~;~i`oJ)cSaGSqEKgb1mDqWd{O0Kd`l}$e?RT5!Z^@{9{k6CxH3FZNFdd4 z*(TLKM6#{EUm$PLF=S`~Sxzw~7{wwwpi{CfLe+FulNoU-sR`#L3lwZ?cp~XcuN#$y zFfR>^FaMq{!e+@<0grHTX>o3hbkK{*Xg64B;V)MQnhdT-|lgRYgJiBTZrhqz;wNP=RiKi_B~ z)PgXt47>6wwHd>$y)UQT;6v#ZgYkj4O;igovB;=fjkOyVCCM$BvPd4OC!oI367flX zd%d>U-C*KCLka4xoA}97o%d(TcfUK#dO*P8;~AsFdlMQKj?Z%alTVr&v)!U>Zry1P z9HEzqtSzUVXokP;O;*YTYY)y=&!7FfLTICpKpP+{#~T8?$qr(!y3EpV3$YlFn^zD* zqfARaJ=bk3M{uJWw~!#=CuC_b%Rw3f-b&UMKy%jzMJNBI-b9FYp~FN*vYGg$FI_$c zDxuXWOd_}PzA~j$p`uI5s1rd(^2Lwavp%0?sB^Iev@f{GSr_47I!@pg?)E+tzq3Qu zb2;;jUu3IH;f)H~67||dy0e**shC)zu=jIiG`)5@t%Dq4oUhHScT+Jpt)Q9o*?a96 zC)9Bz@j?pokM~2)I74!#2;{5A+5qhe+RLUi&grS1zG9pGMBAi+1dCMn9Qjk%a|kz- zB!@7QqMJM2okMN_eJG>5i&RZlH}^HnX0%Zy&isb(*ny~aFyumh@Yx+ta0~VK$SZ&L z8Mu9adxS??>DOeud3;)KJcpJ<8PA(ge0&eh$%NX({jBC#lbLh~=ZC&Iz1bXLo1(Xw zNEQa3W$~%CtL|I_X&v|Hu&>|b_Wln%>ECz_>A2rA3D@PERQ(kWz{xEL&(~Ony+eh2 zoKEa*15Xyrz&_G0djg^EY81U1azf6yP(ewJnib4-q*oN0*92C!Ti;M8&B4u6qH3Ax zcfX9JBY-2#;K2!BET&leo|6eZOf@cIHsc<0{Wl1QKUSl$x`24m83NclsGjAk@~|6S z&3Z@^BI-z!>3I(yrooWvTTe)s+h0yyj6dR+ zg|heMBcVC7ppK>wv}Wn$j3`%uD6ZWX5B+0lTE6~fVVg*x2Jwn0Nu|El^ZM8LjPE;+ z25Z>quYgF$t$n2`QoIZT((2zmJm>iZ|4tPEs;9Kv?jARwc!ceNZw{=4y&uEQCvt=g zk$*|AM4!sA`Z%xwbkx40oe5u64*67+&qdZ5ymR;fm)O=P)E-SGqJz2a*FvtJhT}Lf z0zt0ilojf_+JV%NzoR-JwfESU*pGBFZ+B&X#X-7h-|C$q36bv`Ob#6Ag_P;n2_FR zN0jI(_$}awTc}o1z38<#x8<)}gCY>9=lWa^@e4KBtHvi_dp`Tl#$6*aL*ty&`4{hR z(}n}ig0lT6K7PLipKq)ETDzMT~N^9o`57Ti8wzJZ3zZk z>)J_QKEw{SuQfP$h`FCGv7s6NaPMj+pP-G-I8B+zVdMkvME!4wKp1!%u@)BMTugmO zCZp+kf9I_CW9OTev)j?VZYF|Cze7G)XF!mcVcF_L2P$Mt0s#7k2AbwOhWliqd^KEk zSz1I;9$hvaREoxInBcP>Yfh&m^R$ll$1z~nh3Nv2@vUOPH;KEjQFPueH3O?%%tRMl z_$E&pthdsvm-M-;TFi#*3QABZV>!RLTJLQFK7I>l{W>5A+cR~EcM#msrfAB%_ISuE z!Pqm^=|c5{`+VmVtWsU9UGMkwU?Tn)MR78I1cx8k=(+C5EGv|ww7%dJPa<5BC5v=p zBre{5lU5yee5fB7;~D^1?Y@gRwnm?{=uO+zg>Ue}s2F}EJ;6hK!%ijj&1QW*-*HPN z@GiOtO>R6qEcp+-8b^P)ipOaa)~lCjG6;weSrSW7@M}sViB-6jtWmq`ddl5CR6L&? z3EC}hP_~B9=ELV!!}oelkBi)O>+rq8~qTj7r#P|Dgi9nb;Nq1r^FB4(pd4zrlgv^P6phyfw}2 zAysmIATx93tS!A~_-!@-*>f;*Gmqcl4J*HC^?(Ubx)R%IH8!>3dwp?~?eH)hCn74^ zMxn{S#C-CSg^lYd#1_AV4@Gcp&_oqTkDL=d^^iJn%uV($OfMt#^5(^gt^> z!QOy+dU?-vY| z(zo1u_g^R7<@nj3W-27sjs5?sLR;zZ;9MCFiXv^O(yQ+o2x(;Yx^;0t6Q;eDIlir! zNIOE%w7^#H7<)=rp+4e|D{flPlpDy&b9><5KiAv6QZSYf7aFYN!eMOth=QGpG4PDr z|M6Z@F*o(}!O_*BiaD#W9D)|}0hjdVhKFU_TIHAenmr%&5*q5(oZ)N_6uGnmmAONH z)c5#PLaP*m@U%C5Z(9^quu95w`ChG^V$@sut}Vk(t2uk-Uo3D+b`&ZWagx5dSbqLJ zZtihi$|qhFDj#qG#DU|nZ*Z!;W*Z*QR**LLs{M%quM6^c4dDsPnrclcR@2xj^xNLH zJlE+?h<%6{#!e%~C=sGDq{mSYUPCsrPU%;*7h^+cB_;B2B~^WgyP=7mamL^7jn?R$ zrHPc&@$ilv>gff!D$DFXj2JE5x#TLZENCVYW<7ZVzdb?@ZHzS5(f}RmUL;Jd38J-n z1Ybd3SmQxjL~C#g5qm|X4G+&ZyQ~Y5T!_-1W@5g2>xSQ=DOt`RZg0J>DOu=TRUzfn z@Z?=X9@pPQ?Ae*awdfw+ln|GWM}3dMmlDE4>OK>>qu6mK8E|zC)9P$R!dD0}jSENo zeLd0~C0dpkg!)B*pOF)n$Ezqvp)g>tt7W8okCBM3mGqxC9Q8=TfR^*qydP41b*rRy zCgYfZ{E++~%4CE*BL&O%d_6eo%`X>8qJ~dr%U|>~Fx)@77fvqo#9=_87YrBqnRx?~ zW=bt$0`j&Wz8iPdJPB)KhQsbDlXC{hzmoxv{wR)$_!Me_{*~vsNAcI$+6zUU)1!vV zcwp4C3!~zJH;WXr$#)N6_h)O{_uV;6zdd>D6QFR9)to`n=`^3J4)aVNduDQ07!OvY z5Ci9;n!9Dw6(!~kd1U$+WyI4e=>Jk+#C7p6mn$BB&Rs)mm{85tR*0>F>~y=R;@AjH#wvuyLrYC8#B%Q5!kX*iKn#0C($CCn zrg)f3CvKKF5|MU@L64eTi$O-*h{VF4*yv>I6E-KyHsSP|*kMpM9gcsfrh3Dn6u3-vUcj>-oP8RD%2crrfG<6;hBBM$UG89uYWASa{19%qZJyF( z6=Mapc7%RAU$h&^ ze?|m4M@aFXS4wee7yJIV z+E+DOA{aTmty3kW5MTus;!3ee1tChU4&h(j>K@-42T@iz{pSeWNuy=_(VR@mI41+) zT-k|J?vFsyz7XCtRH)4>UL)xXO>?VZbr%lrGOT5ph!R5UkgmKE^UZ_aq;s96f*{2;qddMY!?>>2(hHH439oi54Q?Y$t$Wz zabVHnBS(;veC~x4ijceJEH?TAZ!7m-OhN-_#QhDjHXav!0^%gI`yWlT`dfVQ+9Vfe-=C*Mc$VxfsFt*%ob>V8S0{7BhW3%CIu%G_ ze-7kR)75oZj{nWs_4!Tkw@s2-?8#7VvsxvOpK zd&Om#Ef*Dwz$xms!!677c3Q{{-8G7m_UmKdq$AYbNvki_*ox%Pb}w~s|nMJ9;h zo_V4{3goU`-u@)dRWUN+v5XP%b;=U7s^a5R`lqsrv*htp|gLr?8g$&H#I8s)S3db2sw2R zQF3Dh+Z|v95|Zw-VD2>4KeKg`U9?qoiu*A35H2P6e9n2qJVE60^K4%Dec)fKP3&#@ z3*83~3!qk2Onh;Xg$3i?7o|ddnWEo;hf1$WT|CVA&KeuF@TQ^M01BtNeIpNbYHRNK zS(Qa@Y(ilY6hP0ncCR+0xWE9#c#AdeDCmm(Q@IYkhX3D&FP7khjk6dmefY1$NpenM zuMh~ATScuX7`3SMs`%8R*yYTMZI0}ShggIs@kX1}^K>0&by`a63BFUFRtapTw2TQN zYKBiL=uw_q!MX?KgP$a{5z&>iDI0ij%>#lWJ*Jc>N>?HsN`8#qLQdDE+WDRv@v>Vs z?Goxf2?|5QT@i)C(B2jU7niF!s8>f&g^fcWiF#yyqu47DFQ5_xDqDQ zLJ=Xh`tksbU*q_mPLxVp8qmz$kvTd=sy?(;oYFm^2qJakOP_5&TE4dsbQ?OHGHLC)#up@p>9WjBgF& zS)yIg8qdOw@WroZHh4aFbv(w!v{h{jJOjMlpMZ7{1Ks9Y`(q>%I7D?dv0YMlI6q}1-^1fkZ#Qqq@HBzIf=!JTtDvT%>LdN? z&h_<^2b0H!wxesc)4{7B?>l@SPxekJ*Bx#>SNE>&{Y3VTDm(bPCN6|h5QEK)ez+7? zHtI9Aq7BD1`)YRHcV8eloWxn?xP8)@kn&!p@!SzoM&vLh;{vd`A2JavAB(Oy+iBEC z9M-L}N;Wz>T`3j2nwaWxcEyQxqK)FWA9ut=V;%@(NiJPB%EqEo#ZT2r%{zP`txA%q zw9H`DRH$r{nrOgjH=iDU%E1`$-c5-WwRnG2L5Vx5l;P;_T&mIC1RnGnD zna!qn+-()@q^COcD&X_G_+-$f(0TL3g%|_dD;Uu-#%}>FqP^Hi6ZK$C7xS6o z#DMCU!UF(|Fj??}++PwCmP zu|DcfvJ%(1eOB9^NC#Wrfa_uwy>9l4759t6;le#KU~V&X15Y}y%0H!UM+mkaM~>g) z>!N0a&h55gyYd6x>O+fcDBfUS5oXPcd*Tvl(X}?WCPP8a2A!Z~=f?sx+am$aw$efc z-E2F)hq~!s4F;@WHoLM+VMj6D4#1HIV~d~pBP~=C=E+R>eTDDZ+JdcAKKp%c`@P)w z=^}8MD#|mGM*hFCvUJnX(Kd3<+Tg z8;q9@&EQH-YJuXh2dZxg$89THrxEgUC2G&j(Dax4;zK})tL%4?hg!!O3o}=#4cB%# z*N@}$9*cjl()|6@xT`!sOvh6)fjLLoyD#kxblT?+c}!;s^{%m?Sw1STjoJ)Qu*v4@ zAq(2GHyE+H<(cWOYMgL|!X{@70}9jIFQi>F*RMRH3YXkRhEBfDI|wILp+Kk%M?=vI-4Sl zFl0n6_1@*Kt(wy5o4f=H=Q>|}vn%EcYZZtTSHwT`E_0Sp5%`?f)z67ebDROY*gL$? zJV3fM@YO|;1a(!XJRM1_8K=v?1)wYQCeRaiKMFV;OUHGPRVzE=Hz0uw;QM`70s6!P zD(AP${U}hw9F&$7Mkk3Bbe?jWDRfWSZcV2oXy{Zwo6P$gY&P^s3d&WaTCPhC2eLs# zZ9>DFOJR@2S)8Lot{E$hNcT~vDR{277ziQj>fBRgflJ_?%Xwtz;h&klLTRA4z0Qk? z6E-X|b-W3zi6G&jQw~pp@!gm@1Fq&S@7cjH7kH!q2o4*5WI}y3i^le-f zwR~~LAiS%d>}4Bf$Zmn|=*O6ZGnAAkIpfloZ#@=6e9ccnB=$3I8ZP0WvqQ~; zb%kXD!IVqkXD(YEP-by*7F6cMKBH;(24Fih6(O$baQ4|Z#@k&g13E80Txn_k-Ggwa8FxtJC55wq1uTFh`FyrSirhD zOB~N@QUkb)AXF1#=#7-kAMC7N7q`b5uYG9%vjL~=@|H25zSTCLb(QLa-G9h;)_3Tx z`FVy_%>roI<~g(Knv7Nb*J`WPn!4sm|N1m?N`Y?LBd#lp@QYsLVj0c$gs6r(S5I(J z(|#3=krg-%7qkhw)=rCLiF+K0t|ufW;(m3N@pT*>-c@{V=5Vuf$$NhU?@Ev-Up}rZ z5lSw`_d}Zm9^B#%FZ6uPvi7ApO zXp1%S}G3Fa|wCCA@4;nhS&mI8eiAX4EYVI@G`FAebOt8&l zJ(z#G+?TAFejgz$NkGOl%7eX1n`~=2VWij~2gfLY8RUK$Bw*8HFi-scy!jd*iNYTx zmxA@xe}||Pu;2^3tF*$%lL$>A-M_6=(e3zCR6D|qdMY0{gOqq`&F=CPYE2gvblSHK zoH4F_J7{}=g5Cak+tl~icWG1z`wV5?>zI7WJ7az5c`y&b2t${xkJGY^tblQac~h11 z@Ysw626`qiqr=#c??+H1f<3A+lMZHusBb;}O$e)EAxhVv9p&IP`E_aTvzpa_j>$?PXO&>>IKXjm#M=8$>Gw5=Ruzy!zLFo-4fbWIMI5YH(jg!gAR^Dp=ks4H zipLUhF_@P8ra65Li~M=-Fb9()A3RiUsa{B@MBfN;vgCu`CCioi@gUo18HGqGuoiw) z2W~mF-b92I(&|;_mCM{}Ov{Qyx%5=OZqt6wc)2;HB~)`@@|-xGCV$}}!;?KQiGshV zG0BbrcN)Zki*CX)11e=NFwnsY`BY(#3e^U9vr0{IHN5;<#9%g?!M7xHi=lYK2^%9i zy|_1p!Iw!(3aR8>EuVm5?S35L@JjVKcG-r6rTzd6A%5<+}P#ThYmQWRF{KI%?*H75?FbbHJ=SB%|I+)2jNSe* zSC#&MZl~VBrS@o5UkLjzJr8VZ4^Oc|x&J&JTdbQw?A*Du2J64{&Z))DF9Q@3{_}L| zfPhZ{8@sATRR2p)96E+cp~ZP+{*~dhH{g-N9+Cg07YrT4u}ahan-}PX6DBC_Q;6^X p(nErd|8D~RPXhjbw!kyit-KW~<64p=v_I+_dFjtmRT73l{}27fbNT=P literal 0 HcmV?d00001 diff --git a/Dijkstra Algorithm/Images/image3.png b/Dijkstra Algorithm/Images/image3.png new file mode 100644 index 0000000000000000000000000000000000000000..493048ab7b37f907f7b1a89aeee868a543d00e91 GIT binary patch literal 65232 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�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 literal 0 HcmV?d00001 diff --git a/Dijkstra Algorithm/Images/image4.png b/Dijkstra Algorithm/Images/image4.png new file mode 100644 index 0000000000000000000000000000000000000000..9c47aaaaffabcd49f10fe5cda5aedf33431ce1a3 GIT binary patch literal 65286 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 )oiImBH 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 DI2Sh? literal 0 HcmV?d00001 diff --git a/Dijkstra Algorithm/Images/image5.png b/Dijkstra Algorithm/Images/image5.png new file mode 100644 index 0000000000000000000000000000000000000000..2494654449417fd46572395eafcdc21a10c1c812 GIT binary patch literal 66333 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 literal 0 HcmV?d00001 diff --git a/Dijkstra Algorithm/Images/image7.png b/Dijkstra Algorithm/Images/image7.png new file mode 100644 index 0000000000000000000000000000000000000000..dd91cab0b84515792f0002c8c9fb360a78098357 GIT binary patch literal 66716 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 - ## Credits WWDC 2017 Scholarship Project Created by [Taras Nikulin](https://github.com/crabman448) From fb4c63bc92ac909159528e2e1c3f16d99eb9665a Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Thu, 20 Apr 2017 15:32:05 +0300 Subject: [PATCH 0961/1679] Tables fix --- Dijkstra Algorithm/README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Dijkstra Algorithm/README.md b/Dijkstra Algorithm/README.md index 9a48bbeb3..132f4e5bd 100644 --- a/Dijkstra Algorithm/README.md +++ b/Dijkstra Algorithm/README.md @@ -12,6 +12,7 @@ When the algorithm starts to work initial graph looks like this: [image1.png] The table below will represent graph state + | | A | B | C | D | E | | ------------------------- | --- | --- | --- | --- | --- | | Visited | F | F | F | F | F | @@ -61,6 +62,7 @@ If neighbor's path length from start is bigger than checking vertex path length | Path Vertices From Start | [A] | [A, B] | [ ] | [A, D] | [ ] | [image4.jpg] + | | A | B | C | D | E | | ------------------------- | ---------- | ---------- | ---------- | ---------- | ---------- | | Visited | T | F | F | T | F | @@ -68,6 +70,7 @@ If neighbor's path length from start is bigger than checking vertex path length | Path Vertices From Start | [A] | [A, B] | [ ] | [A, D] | [A, D, E] | [image5.jpg] + | | A | B | C | D | E | | ------------------------- | ---------- | ---------- | ---------- | ---------- | ---------- | | Visited | T | F | F | T | T | @@ -75,6 +78,7 @@ If neighbor's path length from start is bigger than checking vertex path length | Path Vertices From Start | [A] | [A, B] |[A, D, E, C]| [A, D] | [A, D, E ] | [image6.jpg] + | | A | B | C | D | E | | ------------------------- | ---------- | ---------- | ---------- | ---------- | ---------- | | Visited | T | T | F | T | T | @@ -82,6 +86,7 @@ If neighbor's path length from start is bigger than checking vertex path length | Path Vertices From Start | [A] | [A, B] | [A, B, C]| [A, D] | [A, D, E ] | [image7.jpg] + | | A | B | C | D | E | | ------------------------- | ---------- | ---------- | ---------- | ---------- | ---------- | | Visited | T | T | T | T | T | From cce96e2694e71e473f30817a535a97a6d59591f3 Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Thu, 20 Apr 2017 15:34:16 +0300 Subject: [PATCH 0962/1679] Updating --- Dijkstra Algorithm/README.md | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/Dijkstra Algorithm/README.md b/Dijkstra Algorithm/README.md index 132f4e5bd..cb0683e5d 100644 --- a/Dijkstra Algorithm/README.md +++ b/Dijkstra Algorithm/README.md @@ -9,12 +9,12 @@ The best example is road network. If you wnat to find the shortest path from you I have a gif example, which will show you how algorithm works. If this is not enough, then you can play with my **VisualizedDijkstra.playground**. So let's image, that your house is "A" vertex and your job is "B" vertex. And you are lucky, you have graph with all possible routes. When the algorithm starts to work initial graph looks like this: -[image1.png] +[images/image1.png] The table below will represent graph state | | A | B | C | D | E | -| ------------------------- | --- | --- | --- | --- | --- | +|:------------------------- |:---:|:---:|:---:|:---:|:---:| | Visited | F | F | F | F | F | | Path Length From Start | inf | inf | inf | inf | inf | | Path Vertices From Start | [ ] | [ ] | [ ] | [ ] | [ ] | @@ -44,51 +44,51 @@ var checkingVertex = nonVisitedVertices.smallestPathLengthFromStartVertex() Then we set this vertex as visited | | A | B | C | D | E | -| ------------------------- | --- | --- | --- | --- | --- | +|:------------------------- |:---:|:---:|:---:|:---:|:---:| | Visited | T | F | F | F | F | | Path Length From Start | 0 | inf | inf | inf | inf | | Path Vertices From Start | [A] | [ ] | [ ] | [ ] | [ ] | checkingVertex.visited = true -[image2.jpg] +[images/image2.jpg] Then we check all of its neighbors. If neighbor's path length from start is bigger than checking vertex path length from start + edge weigth, then we set neighbor's path length from start new value and append to its pathVerticesFromStart array new vertex: checkingVertex. Repeat this action for every vertex. -[image3.jpg] +[images/image3.jpg] | | A | B | C | D | E | -| ------------------------- | ---------- | ---------- | ---------- | ---------- | ---------- | +|:------------------------- |:----------:|:----------:|:----------:|:----------:|:----------:| | Visited | T | F | F | F | F | | Path Length From Start | 0 | 3 | inf | 1 | inf | | Path Vertices From Start | [A] | [A, B] | [ ] | [A, D] | [ ] | -[image4.jpg] +[images/image4.jpg] | | A | B | C | D | E | -| ------------------------- | ---------- | ---------- | ---------- | ---------- | ---------- | +|:------------------------- |:----------:|:----------:|:----------:|:----------:|:----------:| | Visited | T | F | F | T | F | | Path Length From Start | 0 | 3 | inf | 1 | 2 | | Path Vertices From Start | [A] | [A, B] | [ ] | [A, D] | [A, D, E] | -[image5.jpg] +[images/image5.jpg] | | A | B | C | D | E | -| ------------------------- | ---------- | ---------- | ---------- | ---------- | ---------- | +|:------------------------- |:----------:|:----------:|:----------:|:----------:|:----------:| | Visited | T | F | F | T | T | | Path Length From Start | 0 | 3 | 11 | 1 | 2 | | Path Vertices From Start | [A] | [A, B] |[A, D, E, C]| [A, D] | [A, D, E ] | -[image6.jpg] +[images/image6.jpg] | | A | B | C | D | E | -| ------------------------- | ---------- | ---------- | ---------- | ---------- | ---------- | +|:------------------------- |:----------:|:----------:|:----------:|:----------:|:----------:| | Visited | T | T | F | T | T | | Path Length From Start | 0 | 3 | 8 | 1 | 2 | | Path Vertices From Start | [A] | [A, B] | [A, B, C]| [A, D] | [A, D, E ] | -[image7.jpg] +[images/image7.jpg] | | A | B | C | D | E | -| ------------------------- | ---------- | ---------- | ---------- | ---------- | ---------- | +|:------------------------- |:----------:|:----------:|:----------:|:----------:|:----------:| | Visited | T | T | T | T | T | | Path Length From Start | 0 | 3 | 8 | 1 | 2 | | Path Vertices From Start | [A] | [A, B] | [A, B, C]| [A, D] | [A, D, E ] | From 142ff2e866c89259c576b03b025b500e655cf028 Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Thu, 20 Apr 2017 15:35:00 +0300 Subject: [PATCH 0963/1679] Fix folder references --- Dijkstra Algorithm/README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Dijkstra Algorithm/README.md b/Dijkstra Algorithm/README.md index cb0683e5d..677c97447 100644 --- a/Dijkstra Algorithm/README.md +++ b/Dijkstra Algorithm/README.md @@ -9,7 +9,7 @@ The best example is road network. If you wnat to find the shortest path from you I have a gif example, which will show you how algorithm works. If this is not enough, then you can play with my **VisualizedDijkstra.playground**. So let's image, that your house is "A" vertex and your job is "B" vertex. And you are lucky, you have graph with all possible routes. When the algorithm starts to work initial graph looks like this: -[images/image1.png] +[Images/image1.png] The table below will represent graph state @@ -50,10 +50,10 @@ Then we set this vertex as visited | Path Vertices From Start | [A] | [ ] | [ ] | [ ] | [ ] | checkingVertex.visited = true -[images/image2.jpg] +[Images/image2.jpg] Then we check all of its neighbors. If neighbor's path length from start is bigger than checking vertex path length from start + edge weigth, then we set neighbor's path length from start new value and append to its pathVerticesFromStart array new vertex: checkingVertex. Repeat this action for every vertex. -[images/image3.jpg] +[Images/image3.jpg] | | A | B | C | D | E | |:------------------------- |:----------:|:----------:|:----------:|:----------:|:----------:| @@ -61,7 +61,7 @@ If neighbor's path length from start is bigger than checking vertex path length | Path Length From Start | 0 | 3 | inf | 1 | inf | | Path Vertices From Start | [A] | [A, B] | [ ] | [A, D] | [ ] | -[images/image4.jpg] +[Images/image4.jpg] | | A | B | C | D | E | |:------------------------- |:----------:|:----------:|:----------:|:----------:|:----------:| @@ -69,7 +69,7 @@ If neighbor's path length from start is bigger than checking vertex path length | Path Length From Start | 0 | 3 | inf | 1 | 2 | | Path Vertices From Start | [A] | [A, B] | [ ] | [A, D] | [A, D, E] | -[images/image5.jpg] +[Images/image5.jpg] | | A | B | C | D | E | |:------------------------- |:----------:|:----------:|:----------:|:----------:|:----------:| @@ -77,7 +77,7 @@ If neighbor's path length from start is bigger than checking vertex path length | Path Length From Start | 0 | 3 | 11 | 1 | 2 | | Path Vertices From Start | [A] | [A, B] |[A, D, E, C]| [A, D] | [A, D, E ] | -[images/image6.jpg] +[Images/image6.jpg] | | A | B | C | D | E | |:------------------------- |:----------:|:----------:|:----------:|:----------:|:----------:| @@ -85,7 +85,7 @@ If neighbor's path length from start is bigger than checking vertex path length | Path Length From Start | 0 | 3 | 8 | 1 | 2 | | Path Vertices From Start | [A] | [A, B] | [A, B, C]| [A, D] | [A, D, E ] | -[images/image7.jpg] +[Images/image7.jpg] | | A | B | C | D | E | |:------------------------- |:----------:|:----------:|:----------:|:----------:|:----------:| From 8e0d77ff9f99812bb8de307b66f1d211ef4ea785 Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Thu, 20 Apr 2017 15:37:15 +0300 Subject: [PATCH 0964/1679] Images --- Dijkstra Algorithm/README.md | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/Dijkstra Algorithm/README.md b/Dijkstra Algorithm/README.md index 677c97447..490b4de1d 100644 --- a/Dijkstra Algorithm/README.md +++ b/Dijkstra Algorithm/README.md @@ -9,7 +9,8 @@ The best example is road network. If you wnat to find the shortest path from you I have a gif example, which will show you how algorithm works. If this is not enough, then you can play with my **VisualizedDijkstra.playground**. So let's image, that your house is "A" vertex and your job is "B" vertex. And you are lucky, you have graph with all possible routes. When the algorithm starts to work initial graph looks like this: -[Images/image1.png] + + The table below will represent graph state @@ -50,10 +51,13 @@ Then we set this vertex as visited | Path Vertices From Start | [A] | [ ] | [ ] | [ ] | [ ] | checkingVertex.visited = true -[Images/image2.jpg] + + + Then we check all of its neighbors. If neighbor's path length from start is bigger than checking vertex path length from start + edge weigth, then we set neighbor's path length from start new value and append to its pathVerticesFromStart array new vertex: checkingVertex. Repeat this action for every vertex. -[Images/image3.jpg] + + | | A | B | C | D | E | |:------------------------- |:----------:|:----------:|:----------:|:----------:|:----------:| @@ -61,7 +65,7 @@ If neighbor's path length from start is bigger than checking vertex path length | Path Length From Start | 0 | 3 | inf | 1 | inf | | Path Vertices From Start | [A] | [A, B] | [ ] | [A, D] | [ ] | -[Images/image4.jpg] + | | A | B | C | D | E | |:------------------------- |:----------:|:----------:|:----------:|:----------:|:----------:| @@ -69,7 +73,7 @@ If neighbor's path length from start is bigger than checking vertex path length | Path Length From Start | 0 | 3 | inf | 1 | 2 | | Path Vertices From Start | [A] | [A, B] | [ ] | [A, D] | [A, D, E] | -[Images/image5.jpg] + | | A | B | C | D | E | |:------------------------- |:----------:|:----------:|:----------:|:----------:|:----------:| @@ -77,7 +81,7 @@ If neighbor's path length from start is bigger than checking vertex path length | Path Length From Start | 0 | 3 | 11 | 1 | 2 | | Path Vertices From Start | [A] | [A, B] |[A, D, E, C]| [A, D] | [A, D, E ] | -[Images/image6.jpg] + | | A | B | C | D | E | |:------------------------- |:----------:|:----------:|:----------:|:----------:|:----------:| @@ -85,7 +89,7 @@ If neighbor's path length from start is bigger than checking vertex path length | Path Length From Start | 0 | 3 | 8 | 1 | 2 | | Path Vertices From Start | [A] | [A, B] | [A, B, C]| [A, D] | [A, D, E ] | -[Images/image7.jpg] + | | A | B | C | D | E | |:------------------------- |:----------:|:----------:|:----------:|:----------:|:----------:| From 37550365f6db8b980cfe1792a3122efe24a1ed91 Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Thu, 20 Apr 2017 15:55:29 +0300 Subject: [PATCH 0965/1679] Still improving description --- Dijkstra Algorithm/README.md | 73 ++++++++++++++++++++++++++---------- 1 file changed, 54 insertions(+), 19 deletions(-) diff --git a/Dijkstra Algorithm/README.md b/Dijkstra Algorithm/README.md index 490b4de1d..5541276fc 100644 --- a/Dijkstra Algorithm/README.md +++ b/Dijkstra Algorithm/README.md @@ -1,4 +1,4 @@ -# Dijkstra-algorithm +# Dijkstra's algorithm This algorithm was invented in 1956 by Edsger W. Dijkstra. @@ -6,13 +6,17 @@ This algorithm can be used, when you have one source vertex and want to find the The best example is road network. If you wnat to find the shortest path from your house to your job, then it is time for the Dijkstra's algorithm. -I have a gif example, which will show you how algorithm works. If this is not enough, then you can play with my **VisualizedDijkstra.playground**. -So let's image, that your house is "A" vertex and your job is "B" vertex. And you are lucky, you have graph with all possible routes. +I have created **VisualizedDijkstra.playground** to help you to understand, how this algorithm works. Besides, I have described below step by step how does it works. + +So let's imagine, that your house is "A" vertex and your job is "B" vertex. And you are lucky, you have graph with all possible routes. + +> Initialization + When the algorithm starts to work initial graph looks like this: -The table below will represent graph state +The table below represents graph state: | | A | B | C | D | E | |:------------------------- |:---:|:---:|:---:|:---:|:---:| @@ -20,11 +24,17 @@ The table below will represent graph state | Path Length From Start | inf | inf | inf | inf | inf | | Path Vertices From Start | [ ] | [ ] | [ ] | [ ] | [ ] | -Graph's array contains 5 vertices [A, B, C, D, E]. -Let's assume, that edge weight it is path length in kilometers between vertices. -A vertex has neighbors: B(path from A: 5.0), C(path from A: 0.0), D(path from A: 0.0) -And because algorithm has done nothing, then all vertices' path length from source vertex values are infinity (think about infinity as "I don't know, how long will it takes to get this vertex from source one") -Finally we have to set source vertex path length from source vertex to 0. +_inf is equal infinity, which basically means, that algorithm doesn't know how far away is this vertex from start one._ +_F states for False_ +_T states for True_ + +To initialize out graph we have to set source vertex path length from source vertex to 0. + +| | A | B | C | D | E | +|:------------------------- |:---:|:---:|:---:|:---:|:---:| +| Visited | F | F | F | F | F | +| Path Length From Start | 0 | inf | inf | inf | inf | +| Path Vertices From Start | [ ] | [ ] | [ ] | [ ] | [ ] | Great, now our graph is initialized and we can pass it to the Dijkstra's algorithm. @@ -37,12 +47,15 @@ Cycle: When all vertices are marked as visited, the algorithm's job is done. Now, you can see the shortest path from the start for every vertex by pressing the one you are interested in. Okay, let's start! -From now we will keep array which contains non visited vertices. Here they are: -var nonVisitedVertices = [A, B, C, D, E] -Let's follow the algorithm and pick the first vertex, which neighbors we want to check. -Imagine that we have function, that returns vertex with smallest path length from start. -var checkingVertex = nonVisitedVertices.smallestPathLengthFromStartVertex() -Then we set this vertex as visited +Let's follow the algorithm's cycle and pick the first vertex, which neighbors we want to check. +All our vertices are not visited, but there is only one have the smallest path length from start - A. This vertex is th first one, which neighbors we will check. +First of all, set this vertex as visited + +A.visited = true + + + +After this step graph has this state: | | A | B | C | D | E | |:------------------------- |:---:|:---:|:---:|:---:|:---:| @@ -50,21 +63,35 @@ Then we set this vertex as visited | Path Length From Start | 0 | inf | inf | inf | inf | | Path Vertices From Start | [A] | [ ] | [ ] | [ ] | [ ] | -checkingVertex.visited = true - - +> Step 1 Then we check all of its neighbors. -If neighbor's path length from start is bigger than checking vertex path length from start + edge weigth, then we set neighbor's path length from start new value and append to its pathVerticesFromStart array new vertex: checkingVertex. Repeat this action for every vertex. +If checking vertex path length from start + edge weigth is smaller than neighbor's path length from start, then we set neighbor's path length from start new value and append to its pathVerticesFromStart array new vertex: checkingVertex. Repeat this action for every vertex. + +for clarity: +```swift +if (A.pathLengthFromStart + AB.weight) < B.pathLengthFromStart { + B.pathLengthFromStart = A.pathLengthFromStart + AB.weight + B.pathVerticesFromStart = A.pathVerticesFromStart + B.pathVerticesFromStart.append(B) +} +``` +And now our graph looks like this one: +And its state is here: + | | A | B | C | D | E | |:------------------------- |:----------:|:----------:|:----------:|:----------:|:----------:| | Visited | T | F | F | F | F | | Path Length From Start | 0 | 3 | inf | 1 | inf | | Path Vertices From Start | [A] | [A, B] | [ ] | [A, D] | [ ] | +> Step 2 + +From now we repeat all actions again and fill our table with new info! + | | A | B | C | D | E | @@ -73,6 +100,8 @@ If neighbor's path length from start is bigger than checking vertex path length | Path Length From Start | 0 | 3 | inf | 1 | 2 | | Path Vertices From Start | [A] | [A, B] | [ ] | [A, D] | [A, D, E] | +> Step 3 + | | A | B | C | D | E | @@ -81,6 +110,8 @@ If neighbor's path length from start is bigger than checking vertex path length | Path Length From Start | 0 | 3 | 11 | 1 | 2 | | Path Vertices From Start | [A] | [A, B] |[A, D, E, C]| [A, D] | [A, D, E ] | +> Step 4 + | | A | B | C | D | E | @@ -89,8 +120,12 @@ If neighbor's path length from start is bigger than checking vertex path length | Path Length From Start | 0 | 3 | 8 | 1 | 2 | | Path Vertices From Start | [A] | [A, B] | [A, B, C]| [A, D] | [A, D, E ] | +> Step 5 + +> Step 6 + | | A | B | C | D | E | |:------------------------- |:----------:|:----------:|:----------:|:----------:|:----------:| | Visited | T | T | T | T | T | From 5e5e7a93188b79ee6693b19fd03d387635b87dbf Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Thu, 20 Apr 2017 15:57:33 +0300 Subject: [PATCH 0966/1679] Description --- Dijkstra Algorithm/README.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Dijkstra Algorithm/README.md b/Dijkstra Algorithm/README.md index 5541276fc..206507b7b 100644 --- a/Dijkstra Algorithm/README.md +++ b/Dijkstra Algorithm/README.md @@ -63,7 +63,7 @@ After this step graph has this state: | Path Length From Start | 0 | inf | inf | inf | inf | | Path Vertices From Start | [A] | [ ] | [ ] | [ ] | [ ] | -> Step 1 +## Step 1 Then we check all of its neighbors. If checking vertex path length from start + edge weigth is smaller than neighbor's path length from start, then we set neighbor's path length from start new value and append to its pathVerticesFromStart array new vertex: checkingVertex. Repeat this action for every vertex. @@ -88,7 +88,7 @@ And its state is here: | Path Length From Start | 0 | 3 | inf | 1 | inf | | Path Vertices From Start | [A] | [A, B] | [ ] | [A, D] | [ ] | -> Step 2 +## Step 2 From now we repeat all actions again and fill our table with new info! @@ -100,7 +100,7 @@ From now we repeat all actions again and fill our table with new info! | Path Length From Start | 0 | 3 | inf | 1 | 2 | | Path Vertices From Start | [A] | [A, B] | [ ] | [A, D] | [A, D, E] | -> Step 3 +## Step 3 @@ -110,7 +110,7 @@ From now we repeat all actions again and fill our table with new info! | Path Length From Start | 0 | 3 | 11 | 1 | 2 | | Path Vertices From Start | [A] | [A, B] |[A, D, E, C]| [A, D] | [A, D, E ] | -> Step 4 +## Step 4 @@ -120,23 +120,23 @@ From now we repeat all actions again and fill our table with new info! | Path Length From Start | 0 | 3 | 8 | 1 | 2 | | Path Vertices From Start | [A] | [A, B] | [A, B, C]| [A, D] | [A, D, E ] | -> Step 5 +## Step 5 -> Step 6 - | | A | B | C | D | E | |:------------------------- |:----------:|:----------:|:----------:|:----------:|:----------:| | Visited | T | T | T | T | T | | Path Length From Start | 0 | 3 | 8 | 1 | 2 | | Path Vertices From Start | [A] | [A, B] | [A, B, C]| [A, D] | [A, D, E ] | +## About + This repository contains to playgrounds: * To understand how does this algorithm works, I have created **VisualizedDijkstra.playground.** It works in auto and interactive modes. Moreover there are play/pause/stop buttons. * If you need only realization of the algorithm without visualization then run **Dijkstra.playground.** It contains necessary classes and couple functions to create random graph for algorithm testing. -## Dijkstra's algorithm explanation + From 2e7c34c8d59c003dffe5f51a5f035a8c9b1141ba Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Thu, 20 Apr 2017 15:58:50 +0300 Subject: [PATCH 0967/1679] Probably final updates --- Dijkstra Algorithm/README.md | 34 ++++------------------------------ 1 file changed, 4 insertions(+), 30 deletions(-) diff --git a/Dijkstra Algorithm/README.md b/Dijkstra Algorithm/README.md index 206507b7b..e73f95393 100644 --- a/Dijkstra Algorithm/README.md +++ b/Dijkstra Algorithm/README.md @@ -10,7 +10,7 @@ I have created **VisualizedDijkstra.playground** to help you to understand, how So let's imagine, that your house is "A" vertex and your job is "B" vertex. And you are lucky, you have graph with all possible routes. -> Initialization +## Initialization When the algorithm starts to work initial graph looks like this: @@ -130,43 +130,17 @@ From now we repeat all actions again and fill our table with new info! | Path Length From Start | 0 | 3 | 8 | 1 | 2 | | Path Vertices From Start | [A] | [A, B] | [A, B, C]| [A, D] | [A, D, E ] | -## About +## About this repository This repository contains to playgrounds: * To understand how does this algorithm works, I have created **VisualizedDijkstra.playground.** It works in auto and interactive modes. Moreover there are play/pause/stop buttons. * If you need only realization of the algorithm without visualization then run **Dijkstra.playground.** It contains necessary classes and couple functions to create random graph for algorithm testing. - - - - -[Wikipedia](https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm)'s explanation: -Let the node at which we are starting be called the initial node. Let the distance of node Y be the distance from the initial node to Y. Dijkstra's algorithm will assign some initial distance values and will try to improve them step by step. - -1. Assign to every node a tentative distance value: set it to zero for our initial node and to infinity for all other nodes. -2. Set the initial node as current. Mark all other nodes unvisited. Create a set of all the unvisited nodes called the unvisited set. -3. For the current node, consider all of its unvisited neighbors and calculate their tentative distances. Compare the newly calculated tentative distance to the current assigned value and assign the smaller one. For example, if the current node A is marked with a distance of 6, and the edge connecting it with a neighbor B has length 2, then the distance to B (through A) will be 6 + 2 = 8. If B was previously marked with a distance greater than 8 then change it to 8. Otherwise, keep the current value. -4. When we are done considering all of the neighbors of the current node, mark the current node as visited and remove it from the unvisited set. A visited node will never be checked again. -5. If the destination node has been marked visited (when planning a route between two specific nodes) or if the smallest tentative distance among the nodes in the unvisited set is infinity (when planning a complete traversal; occurs when there is no connection between the initial node and remaining unvisited nodes), then stop. The algorithm has finished. -6. Otherwise, select the unvisited node that is marked with the smallest tentative distance, set it as the new "current node", and go back to step 3. - -Explanation, that can be found in the **VisualizedDijkstra.playground** -Algorithm's flow: -First of all, this program randomly decides which vertex will be the start one, then the program assigns a zero value to the start vertex path length from the start. - -Then the algorithm repeats following cycle until all vertices are marked as visited. -Cycle: -1. From the non-visited vertices the algorithm picks a vertex with the shortest path length from the start (if there are more than one vertex with the same shortest path value, then algorithm picks any of them) -2. The algorithm marks picked vertex as visited. -3. The algorithm check all of its neighbors. If the current vertex path length from the start plus an edge weight to a neighbor less than the neighbor current path length from the start, than it assigns new path length from the start to the neihgbor. -When all vertices are marked as visited, the algorithm's job is done. Now, you can see the shortest path from the start for every vertex by pressing the one you are interested in. - -## Usage -This algorithm is popular in routing. For example, biggest Russian IT company Yandex uses it in [Яндекс.Карты](https://yandex.ru/company/technologies/routes/) - ## Demo video + Click the link: [YouTube](https://youtu.be/PPESI7et0cQ) ## Credits + WWDC 2017 Scholarship Project Created by [Taras Nikulin](https://github.com/crabman448) From dd9e998e4482ff9665e3964829569a0c5489daf4 Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Thu, 20 Apr 2017 16:01:01 +0300 Subject: [PATCH 0968/1679] Added reference to wikipedia --- Dijkstra Algorithm/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dijkstra Algorithm/README.md b/Dijkstra Algorithm/README.md index e73f95393..76cc4ca1d 100644 --- a/Dijkstra Algorithm/README.md +++ b/Dijkstra Algorithm/README.md @@ -1,6 +1,6 @@ # Dijkstra's algorithm -This algorithm was invented in 1956 by Edsger W. Dijkstra. +This [algorithm](https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm) was invented in 1956 by Edsger W. Dijkstra. This algorithm can be used, when you have one source vertex and want to find the shortest paths to all other vertices in the graph. From e2282045c04aeab0ff7eeb2c1df8edc33c92c76c Mon Sep 17 00:00:00 2001 From: Taras Date: Thu, 20 Apr 2017 16:07:33 +0300 Subject: [PATCH 0969/1679] Update README.md --- Dijkstra Algorithm/README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Dijkstra Algorithm/README.md b/Dijkstra Algorithm/README.md index 76cc4ca1d..61b47e97f 100644 --- a/Dijkstra Algorithm/README.md +++ b/Dijkstra Algorithm/README.md @@ -24,9 +24,11 @@ The table below represents graph state: | Path Length From Start | inf | inf | inf | inf | inf | | Path Vertices From Start | [ ] | [ ] | [ ] | [ ] | [ ] | -_inf is equal infinity, which basically means, that algorithm doesn't know how far away is this vertex from start one._ -_F states for False_ -_T states for True_ +>inf is equal infinity, which basically means, that algorithm doesn't know how far away is this vertex from start one. + +>F states for False + +>T states for True To initialize out graph we have to set source vertex path length from source vertex to 0. From b95331012e6fa880928b38a7606384e6b7a0db9a Mon Sep 17 00:00:00 2001 From: Taras Date: Thu, 20 Apr 2017 16:09:14 +0300 Subject: [PATCH 0970/1679] Update README.md --- Dijkstra Algorithm/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dijkstra Algorithm/README.md b/Dijkstra Algorithm/README.md index 61b47e97f..9999e224e 100644 --- a/Dijkstra Algorithm/README.md +++ b/Dijkstra Algorithm/README.md @@ -30,13 +30,13 @@ The table below represents graph state: >T states for True -To initialize out graph we have to set source vertex path length from source vertex to 0. +To initialize out graph we have to set source vertex path length from source vertex to 0, and append itself to path vertices ffrom start. | | A | B | C | D | E | |:------------------------- |:---:|:---:|:---:|:---:|:---:| | Visited | F | F | F | F | F | | Path Length From Start | 0 | inf | inf | inf | inf | -| Path Vertices From Start | [ ] | [ ] | [ ] | [ ] | [ ] | +| Path Vertices From Start | [A] | [ ] | [ ] | [ ] | [ ] | Great, now our graph is initialized and we can pass it to the Dijkstra's algorithm. From a44f84ecad941273df7472ef1c7de7aa93b1d1c8 Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Thu, 20 Apr 2017 16:26:33 +0300 Subject: [PATCH 0971/1679] Removed unnecessary images --- .../Images/Dijkstra_Animation.gif | Bin 8561 -> 0 bytes Dijkstra Algorithm/Images/screenshot1.jpg | Bin 224243 -> 0 bytes 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 Dijkstra Algorithm/Images/Dijkstra_Animation.gif delete mode 100644 Dijkstra Algorithm/Images/screenshot1.jpg diff --git a/Dijkstra Algorithm/Images/Dijkstra_Animation.gif b/Dijkstra Algorithm/Images/Dijkstra_Animation.gif deleted file mode 100644 index 3b1a2ef434107efb104a9bc1a6a714af37367529..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8561 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 diff --git a/Dijkstra Algorithm/Images/screenshot1.jpg b/Dijkstra Algorithm/Images/screenshot1.jpg deleted file mode 100644 index e9f7a1207f315e8f5aa20c72f3264c65edafd3a8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 224243 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 From 3395c01c00c80554be30f91310f2878d7faedcce Mon Sep 17 00:00:00 2001 From: darrellhz Date: Fri, 21 Apr 2017 16:04:19 +0900 Subject: [PATCH 0972/1679] Update README.markdown updated to Swift 3 syntax --- Linked List/README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Linked List/README.markdown b/Linked List/README.markdown index c5a752e13..c03023c42 100644 --- a/Linked List/README.markdown +++ b/Linked List/README.markdown @@ -364,7 +364,7 @@ What else do we need? Removing nodes, of course! First we'll do `removeAll()`, w If you had a tail pointer, you'd set it to `nil` here too. -Next we'll add some functions that let you remove individual nodes. If you already have a reference to the node, then using `removeNode()` is the most optimal because you don't need to iterate through the list to find the node first. +Next we'll add some functions that let you remove individual nodes. If you already have a reference to the node, then using `remove()` is the most optimal because you don't need to iterate through the list to find the node first. ```swift public func remove(node: Node) -> T { From b66e31825d9025916d9617073830f50284ebd488 Mon Sep 17 00:00:00 2001 From: Jacopo Date: Fri, 21 Apr 2017 19:25:23 +0100 Subject: [PATCH 0973/1679] Filters the potential change arrays for only the ones which add up to the exact value --- MinimumCoinChange/Sources/MinimumCoinChange.swift | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/MinimumCoinChange/Sources/MinimumCoinChange.swift b/MinimumCoinChange/Sources/MinimumCoinChange.swift index c995063ab..8b0da80ac 100644 --- a/MinimumCoinChange/Sources/MinimumCoinChange.swift +++ b/MinimumCoinChange/Sources/MinimumCoinChange.swift @@ -64,7 +64,10 @@ public struct MinimumCoinChange { if value - coin >= 0 { var potentialChange: [Int] = [coin] potentialChange.append(contentsOf: _changeDynamic(value - coin)) - potentialChangeArray.append(potentialChange) + + if potentialChange.reduce(0, +) == value { + potentialChangeArray.append(potentialChange) + } } } From d5c9d179f63767cfad7dda48faad914f808ca68b Mon Sep 17 00:00:00 2001 From: Jacopo Date: Fri, 21 Apr 2017 19:38:45 +0100 Subject: [PATCH 0974/1679] Optimisation: removed double check if the winner change is valid --- MinimumCoinChange/Sources/MinimumCoinChange.swift | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/MinimumCoinChange/Sources/MinimumCoinChange.swift b/MinimumCoinChange/Sources/MinimumCoinChange.swift index 8b0da80ac..55629d020 100644 --- a/MinimumCoinChange/Sources/MinimumCoinChange.swift +++ b/MinimumCoinChange/Sources/MinimumCoinChange.swift @@ -56,8 +56,6 @@ public struct MinimumCoinChange { return cached } - var change: [Int] = [] - var potentialChangeArray: [[Int]] = [] for coin in sortedCoinSet { @@ -73,14 +71,11 @@ public struct MinimumCoinChange { if potentialChangeArray.count > 0 { let sortedPotentialChangeArray = potentialChangeArray.sorted(by: { $0.count < $1.count }) - change = sortedPotentialChangeArray[0] + cache[value] = sortedPotentialChangeArray[0] + return sortedPotentialChangeArray[0] } - if change.reduce(0, +) == value { - cache[value] = change - } - - return change + return [] } let change: [Int] = _changeDynamic(value) From 2ff26a1365cce2d47e7cf8cc341eadf3134cfdac Mon Sep 17 00:00:00 2001 From: TheIronBorn Date: Fri, 21 Apr 2017 23:07:00 -0700 Subject: [PATCH 0975/1679] prettify some syntax around optionals --- AVL Tree/AVLTree.swift | 28 +++++----------------------- 1 file changed, 5 insertions(+), 23 deletions(-) diff --git a/AVL Tree/AVLTree.swift b/AVL Tree/AVLTree.swift index cfcf114c0..4feb691e4 100644 --- a/AVL Tree/AVLTree.swift +++ b/AVL Tree/AVLTree.swift @@ -99,17 +99,11 @@ open class AVLTree { extension TreeNode { public func minimum() -> TreeNode? { - if let leftChild = self.leftChild { - return leftChild.minimum() - } - return self + return leftChild?.minimum() ?? self } public func maximum() -> TreeNode? { - if let rightChild = self.rightChild { - return rightChild.maximum() - } - return self + return rightChild?.maximum() ?? self } } @@ -120,11 +114,7 @@ extension AVLTree { } public func search(input: Key) -> Payload? { - if let result = search(key: input, node: root) { - return result.payload - } else { - return nil - } + return search(key: input, node: root)?.payload } fileprivate func search(key: Key, node: Node?) -> Node? { @@ -385,11 +375,7 @@ extension TreeNode: CustomDebugStringConvertible { extension AVLTree: CustomDebugStringConvertible { public var debugDescription: String { - if let root = root { - return root.debugDescription - } else { - return "[]" - } + return root?.debugDescription ?? "[]" } } @@ -409,10 +395,6 @@ extension TreeNode: CustomStringConvertible { extension AVLTree: CustomStringConvertible { public var description: String { - if let root = root { - return root.description - } else { - return "[]" - } + return root?.description ?? "[]" } } From 7ecbb716fb9bd16f5f89bd491edc1fe81d3c85be Mon Sep 17 00:00:00 2001 From: TheIronBorn Date: Fri, 21 Apr 2017 23:15:30 -0700 Subject: [PATCH 0976/1679] prettify some syntax around optionals --- .../AVLTree.playground/Sources/AVLTree.swift | 28 ++++--------------- 1 file changed, 5 insertions(+), 23 deletions(-) diff --git a/AVL Tree/AVLTree.playground/Sources/AVLTree.swift b/AVL Tree/AVLTree.playground/Sources/AVLTree.swift index b4b97f0d6..56ba81608 100644 --- a/AVL Tree/AVLTree.playground/Sources/AVLTree.swift +++ b/AVL Tree/AVLTree.playground/Sources/AVLTree.swift @@ -99,17 +99,11 @@ open class AVLTree { extension TreeNode { public func minimum() -> TreeNode? { - if let leftChild = self.leftChild { - return leftChild.minimum() - } - return self + return leftChild?.minimum() ?? self } public func maximum() -> TreeNode? { - if let rightChild = self.rightChild { - return rightChild.maximum() - } - return self + return rightChild?.maximum() ?? self } } @@ -120,11 +114,7 @@ extension AVLTree { } public func search(input: Key) -> Payload? { - if let result = search(key: input, node: root) { - return result.payload - } else { - return nil - } + return search(key: input, node: root)?.payload } fileprivate func search(key: Key, node: Node?) -> Node? { @@ -385,11 +375,7 @@ extension TreeNode: CustomDebugStringConvertible { extension AVLTree: CustomDebugStringConvertible { public var debugDescription: String { - if let root = root { - return root.debugDescription - } else { - return "[]" - } + return root?.debugDescription ?? "[]" } } @@ -409,10 +395,6 @@ extension TreeNode: CustomStringConvertible { extension AVLTree: CustomStringConvertible { public var description: String { - if let root = root { - return root.description - } else { - return "[]" - } + return root?.description ?? "[]" } } From 3d48ed411d872b5b3f03c114e6b1c074bb4293e8 Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Sun, 23 Apr 2017 23:36:55 +0300 Subject: [PATCH 0977/1679] Credits --- Dijkstra Algorithm/README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Dijkstra Algorithm/README.md b/Dijkstra Algorithm/README.md index 9999e224e..086e60c55 100644 --- a/Dijkstra Algorithm/README.md +++ b/Dijkstra Algorithm/README.md @@ -144,5 +144,4 @@ Click the link: [YouTube](https://youtu.be/PPESI7et0cQ) ## Credits -WWDC 2017 Scholarship Project -Created by [Taras Nikulin](https://github.com/crabman448) +WWDC 2017 Scholarship Project (Rejected) created by [Taras Nikulin](https://github.com/crabman448) From 83f7a32ccf0a2fe4b6223305bf89a7724b666a65 Mon Sep 17 00:00:00 2001 From: Antonio081014 Date: Mon, 24 Apr 2017 11:23:09 -0700 Subject: [PATCH 0978/1679] Add variety implementation with complexity analysis. --- Union-Find/README.markdown | 63 ++++++++++---- .../UnionFind.playground/Contents.swift | 82 ++++--------------- .../Sources/UnionFindQuickFind.swift | 50 +++++++++++ .../Sources/UnionFindQuickUnion.swift | 51 ++++++++++++ .../Sources/UnionFindWeightedQuickFind.swift | 59 +++++++++++++ .../Sources/UnionFindWeightedQuickUnion.swift | 56 +++++++++++++ ...indWeightedQuickUnionPathCompression.swift | 53 ++++++++++++ .../UnionFind.playground/timeline.xctimeline | 6 -- Union-Find/UnionFind.swift | 59 ------------- 9 files changed, 330 insertions(+), 149 deletions(-) create mode 100644 Union-Find/UnionFind.playground/Sources/UnionFindQuickFind.swift create mode 100644 Union-Find/UnionFind.playground/Sources/UnionFindQuickUnion.swift create mode 100644 Union-Find/UnionFind.playground/Sources/UnionFindWeightedQuickFind.swift create mode 100644 Union-Find/UnionFind.playground/Sources/UnionFindWeightedQuickUnion.swift create mode 100644 Union-Find/UnionFind.playground/Sources/UnionFindWeightedQuickUnionPathCompression.swift delete mode 100644 Union-Find/UnionFind.playground/timeline.xctimeline delete mode 100644 Union-Find/UnionFind.swift diff --git a/Union-Find/README.markdown b/Union-Find/README.markdown index 5102f6b89..03e082507 100644 --- a/Union-Find/README.markdown +++ b/Union-Find/README.markdown @@ -23,7 +23,8 @@ The most common application of this data structure is keeping track of the conne ## Implementation -Union-Find can be implemented in many ways but we'll look at the most efficient. +Union-Find can be implemented in many ways but we'll look at an efficient and easy to understand implementation: Weighted Quick Union. +> __PS: Variety implementation of Union-Find has been included in playground.__ ```swift public struct UnionFind { @@ -141,24 +142,24 @@ public mutating func inSameSet(_ firstElement: T, and secondElement: T) -> Bool Since this calls `setOf()` it also optimizes the tree. -## Union +## Union (Weighted) The final operation is **Union**, which combines two sets into one larger set. ```swift -public mutating func unionSetsContaining(_ firstElement: T, and secondElement: T) { - if let firstSet = setOf(firstElement), let secondSet = setOf(secondElement) { // 1 - if firstSet != secondSet { // 2 - if size[firstSet] < size[secondSet] { // 3 - parent[firstSet] = secondSet // 4 - size[secondSet] += size[firstSet] // 5 - } else { - parent[secondSet] = firstSet - size[firstSet] += size[secondSet] - } + public mutating func unionSetsContaining(_ firstElement: T, and secondElement: T) { + if let firstSet = setOf(firstElement), let secondSet = setOf(secondElement) { // 1 + if firstSet != secondSet { // 2 + if size[firstSet] < size[secondSet] { // 3 + parent[firstSet] = secondSet // 4 + size[secondSet] += size[firstSet] // 5 + } else { + parent[secondSet] = firstSet + size[firstSet] += size[secondSet] + } + } + } } - } -} ``` Here is how it works: @@ -167,7 +168,7 @@ Here is how it works: 2. Check that the sets are not equal because if they are it makes no sense to union them. -3. This is where the size optimization comes in. We want to keep the trees as shallow as possible so we always attach the smaller tree to the root of the larger tree. To determine which is the smaller tree we compare trees by their sizes. +3. This is where the size optimization comes in (Weighting). We want to keep the trees as shallow as possible so we always attach the smaller tree to the root of the larger tree. To determine which is the smaller tree we compare trees by their sizes. 4. Here we attach the smaller tree to the root of the larger tree. @@ -185,10 +186,40 @@ Note that, because we call `setOf()` at the start of the method, the larger tree Union with optimizations also takes almost **O(1)** time. +## Path Compression +```swift +private mutating func setByIndex(_ index: Int) -> Int { + if index != parent[index] { + // Updating parent index while looking up the index of parent. + parent[index] = setByIndex(parent[index]) + } + return parent[index] +} +``` +Path Compression helps keep trees very flat, thus find operation could take __ALMOST__ in __O(1)__ + +## Complexity Summary of Variety Implementation + +##### To process N objects +| Data Structure | Union | Find | +|---|---|---| +|Quick Find|N|1| +|Quick Union|Tree height|Tree height| +|Weighted Quick Union|lgN|lgN| +|Weighted Quick Union + Path Compression| very close, but not O(1)| very close, but not O(1) | + +##### To process M union commands on N objects +| Algorithm | Worst-case time| +|---|---| +|Quick Find| M N | +|Quick Union| M N | +|Weighted Quick Union| N + M lgN | +|Weighted Quick Union + Path Compression| (M + N) lgN | + ## See also See the playground for more examples of how to use this handy data structure. [Union-Find at Wikipedia](https://en.wikipedia.org/wiki/Disjoint-set_data_structure) -*Written for Swift Algorithm Club by [Artur Antonov](https://github.com/goingreen)* +*Written for Swift Algorithm Club by [Artur Antonov](https://github.com/goingreen)*, *modified by [Yi Ding](https://github.com/antonio081014).* \ No newline at end of file diff --git a/Union-Find/UnionFind.playground/Contents.swift b/Union-Find/UnionFind.playground/Contents.swift index 09649b938..9ad5215b3 100644 --- a/Union-Find/UnionFind.playground/Contents.swift +++ b/Union-Find/UnionFind.playground/Contents.swift @@ -1,73 +1,19 @@ //: Playground - noun: a place where people can play -public struct UnionFind { - private var index = [T: Int]() - private var parent = [Int]() - private var size = [Int]() - - public mutating func addSetWith(_ element: T) { - index[element] = parent.count - parent.append(parent.count) - size.append(1) - } - - private mutating func setByIndex(_ index: Int) -> Int { - if parent[index] == index { - return index - } else { - parent[index] = setByIndex(parent[index]) - return parent[index] - } - } - - public mutating func setOf(_ element: T) -> Int? { - if let indexOfElement = index[element] { - return setByIndex(indexOfElement) - } else { - return nil - } - } - - public mutating func unionSetsContaining(_ firstElement: T, and secondElement: T) { - if let firstSet = setOf(firstElement), let secondSet = setOf(secondElement) { - if firstSet != secondSet { - if size[firstSet] < size[secondSet] { - parent[firstSet] = secondSet - size[secondSet] += size[firstSet] - } else { - parent[secondSet] = firstSet - size[firstSet] += size[secondSet] - } - } - } - } - - public mutating func inSameSet(_ firstElement: T, and secondElement: T) -> Bool { - if let firstSet = setOf(firstElement), let secondSet = setOf(secondElement) { - return firstSet == secondSet - } else { - return false - } - } -} - - - - -var dsu = UnionFind() +var dsu = UnionFindQuickUnion() for i in 1...10 { - dsu.addSetWith(i) + dsu.addSetWith(i) } // now our dsu contains 10 independent sets // let's divide our numbers into two sets by divisibility by 2 for i in 3...10 { - if i % 2 == 0 { - dsu.unionSetsContaining(2, and: i) - } else { - dsu.unionSetsContaining(1, and: i) - } + if i % 2 == 0 { + dsu.unionSetsContaining(2, and: i) + } else { + dsu.unionSetsContaining(1, and: i) + } } // check our division @@ -88,7 +34,7 @@ print(dsu.inSameSet(3, and: 6)) -var dsuForStrings = UnionFind() +var dsuForStrings = UnionFindQuickUnion() let words = ["all", "border", "boy", "afternoon", "amazing", "awesome", "best"] dsuForStrings.addSetWith("a") @@ -96,12 +42,12 @@ dsuForStrings.addSetWith("b") // In that example we divide strings by its first letter for word in words { - dsuForStrings.addSetWith(word) - if word.hasPrefix("a") { - dsuForStrings.unionSetsContaining("a", and: word) - } else if word.hasPrefix("b") { - dsuForStrings.unionSetsContaining("b", and: word) - } + dsuForStrings.addSetWith(word) + if word.hasPrefix("a") { + dsuForStrings.unionSetsContaining("a", and: word) + } else if word.hasPrefix("b") { + dsuForStrings.unionSetsContaining("b", and: word) + } } print(dsuForStrings.inSameSet("a", and: "all")) diff --git a/Union-Find/UnionFind.playground/Sources/UnionFindQuickFind.swift b/Union-Find/UnionFind.playground/Sources/UnionFindQuickFind.swift new file mode 100644 index 000000000..25d7f5b5d --- /dev/null +++ b/Union-Find/UnionFind.playground/Sources/UnionFindQuickFind.swift @@ -0,0 +1,50 @@ +import Foundation + +/// Quick-find algorithm may take ~MN steps +/// to process M union commands on N objects +public struct UnionFindQuickFind { + private var index = [T: Int]() + private var parent = [Int]() + private var size = [Int]() + + public init() {} + + public mutating func addSetWith(_ element: T) { + index[element] = parent.count + parent.append(parent.count) + size.append(1) + } + + private mutating func setByIndex(_ index: Int) -> Int { + return parent[index] + } + + public mutating func setOf(_ element: T) -> Int? { + if let indexOfElement = index[element] { + return setByIndex(indexOfElement) + } else { + return nil + } + } + + public mutating func unionSetsContaining(_ firstElement: T, and secondElement: T) { + if let firstSet = setOf(firstElement), let secondSet = setOf(secondElement) { + if firstSet != secondSet { + for index in 0.. Bool { + if let firstSet = setOf(firstElement), let secondSet = setOf(secondElement) { + return firstSet == secondSet + } else { + return false + } + } +} diff --git a/Union-Find/UnionFind.playground/Sources/UnionFindQuickUnion.swift b/Union-Find/UnionFind.playground/Sources/UnionFindQuickUnion.swift new file mode 100644 index 000000000..4c848e61d --- /dev/null +++ b/Union-Find/UnionFind.playground/Sources/UnionFindQuickUnion.swift @@ -0,0 +1,51 @@ +import Foundation + +/// Quick-Union algorithm may take ~MN steps +/// to process M union commands on N objects +public struct UnionFindQuickUnion { + private var index = [T: Int]() + private var parent = [Int]() + private var size = [Int]() + + public init() {} + + public mutating func addSetWith(_ element: T) { + index[element] = parent.count + parent.append(parent.count) + size.append(1) + } + + private mutating func setByIndex(_ index: Int) -> Int { + if parent[index] == index { + return index + } else { + parent[index] = setByIndex(parent[index]) + return parent[index] + } + } + + public mutating func setOf(_ element: T) -> Int? { + if let indexOfElement = index[element] { + return setByIndex(indexOfElement) + } else { + return nil + } + } + + public mutating func unionSetsContaining(_ firstElement: T, and secondElement: T) { + if let firstSet = setOf(firstElement), let secondSet = setOf(secondElement) { + if firstSet != secondSet { + parent[firstSet] = secondSet + size[secondSet] += size[firstSet] + } + } + } + + public mutating func inSameSet(_ firstElement: T, and secondElement: T) -> Bool { + if let firstSet = setOf(firstElement), let secondSet = setOf(secondElement) { + return firstSet == secondSet + } else { + return false + } + } +} diff --git a/Union-Find/UnionFind.playground/Sources/UnionFindWeightedQuickFind.swift b/Union-Find/UnionFind.playground/Sources/UnionFindWeightedQuickFind.swift new file mode 100644 index 000000000..02bec94a8 --- /dev/null +++ b/Union-Find/UnionFind.playground/Sources/UnionFindWeightedQuickFind.swift @@ -0,0 +1,59 @@ +import Foundation + +/// Quick-find algorithm may take ~MN steps +/// to process M union commands on N objects +public struct UnionFindWeightedQuickFind { + private var index = [T: Int]() + private var parent = [Int]() + private var size = [Int]() + + public init() {} + + public mutating func addSetWith(_ element: T) { + index[element] = parent.count + parent.append(parent.count) + size.append(1) + } + + private mutating func setByIndex(_ index: Int) -> Int { + return parent[index] + } + + public mutating func setOf(_ element: T) -> Int? { + if let indexOfElement = index[element] { + return setByIndex(indexOfElement) + } else { + return nil + } + } + + public mutating func unionSetsContaining(_ firstElement: T, and secondElement: T) { + if let firstSet = setOf(firstElement), let secondSet = setOf(secondElement) { + if firstSet != secondSet { + if size[firstSet] < size[secondSet] { + for index in 0.. Bool { + if let firstSet = setOf(firstElement), let secondSet = setOf(secondElement) { + return firstSet == secondSet + } else { + return false + } + } +} diff --git a/Union-Find/UnionFind.playground/Sources/UnionFindWeightedQuickUnion.swift b/Union-Find/UnionFind.playground/Sources/UnionFindWeightedQuickUnion.swift new file mode 100644 index 000000000..b3ac7445e --- /dev/null +++ b/Union-Find/UnionFind.playground/Sources/UnionFindWeightedQuickUnion.swift @@ -0,0 +1,56 @@ +import Foundation + +public struct UnionFindWeightedQuickUnion { + private var index = [T: Int]() + private var parent = [Int]() + private var size = [Int]() + + public init() {} + + public mutating func addSetWith(_ element: T) { + index[element] = parent.count + parent.append(parent.count) + size.append(1) + } + + private mutating func setByIndex(_ index: Int) -> Int { + if parent[index] == index { + return index + } else { + parent[index] = setByIndex(parent[index]) + return parent[index] + } + } + + public mutating func setOf(_ element: T) -> Int? { + if let indexOfElement = index[element] { + return setByIndex(indexOfElement) + } else { + return nil + } + } + + /// Weighted, by comparing set size. + /// Merge small set into the large one. + public mutating func unionSetsContaining(_ firstElement: T, and secondElement: T) { + if let firstSet = setOf(firstElement), let secondSet = setOf(secondElement) { + if firstSet != secondSet { + if size[firstSet] < size[secondSet] { + parent[firstSet] = secondSet + size[secondSet] += size[firstSet] + } else { + parent[secondSet] = firstSet + size[firstSet] += size[secondSet] + } + } + } + } + + public mutating func inSameSet(_ firstElement: T, and secondElement: T) -> Bool { + if let firstSet = setOf(firstElement), let secondSet = setOf(secondElement) { + return firstSet == secondSet + } else { + return false + } + } +} diff --git a/Union-Find/UnionFind.playground/Sources/UnionFindWeightedQuickUnionPathCompression.swift b/Union-Find/UnionFind.playground/Sources/UnionFindWeightedQuickUnionPathCompression.swift new file mode 100644 index 000000000..892f46a3c --- /dev/null +++ b/Union-Find/UnionFind.playground/Sources/UnionFindWeightedQuickUnionPathCompression.swift @@ -0,0 +1,53 @@ +import Foundation + +public struct UnionFindWeightedQuickUnionPathCompression { + private var index = [T: Int]() + private var parent = [Int]() + private var size = [Int]() + + public init() {} + + public mutating func addSetWith(_ element: T) { + index[element] = parent.count + parent.append(parent.count) + size.append(1) + } + + /// Path Compression. + private mutating func setByIndex(_ index: Int) -> Int { + if index != parent[index] { + parent[index] = setByIndex(parent[index]) + } + return parent[index] + } + + public mutating func setOf(_ element: T) -> Int? { + if let indexOfElement = index[element] { + return setByIndex(indexOfElement) + } else { + return nil + } + } + + public mutating func unionSetsContaining(_ firstElement: T, and secondElement: T) { + if let firstSet = setOf(firstElement), let secondSet = setOf(secondElement) { + if firstSet != secondSet { + if size[firstSet] < size[secondSet] { + parent[firstSet] = secondSet + size[secondSet] += size[firstSet] + } else { + parent[secondSet] = firstSet + size[firstSet] += size[secondSet] + } + } + } + } + + public mutating func inSameSet(_ firstElement: T, and secondElement: T) -> Bool { + if let firstSet = setOf(firstElement), let secondSet = setOf(secondElement) { + return firstSet == secondSet + } else { + return false + } + } +} diff --git a/Union-Find/UnionFind.playground/timeline.xctimeline b/Union-Find/UnionFind.playground/timeline.xctimeline deleted file mode 100644 index bf468afec..000000000 --- a/Union-Find/UnionFind.playground/timeline.xctimeline +++ /dev/null @@ -1,6 +0,0 @@ - - - - - diff --git a/Union-Find/UnionFind.swift b/Union-Find/UnionFind.swift deleted file mode 100644 index 506cdc1fe..000000000 --- a/Union-Find/UnionFind.swift +++ /dev/null @@ -1,59 +0,0 @@ -/* - Union-Find Data Structure - - Performance: - adding new set is almost O(1) - finding set of element is almost O(1) - union sets is almost O(1) -*/ - -public struct UnionFind { - private var index = [T: Int]() - private var parent = [Int]() - private var size = [Int]() - - public mutating func addSetWith(_ element: T) { - index[element] = parent.count - parent.append(parent.count) - size.append(1) - } - - private mutating func setByIndex(_ index: Int) -> Int { - if parent[index] == index { - return index - } else { - parent[index] = setByIndex(parent[index]) - return parent[index] - } - } - - public mutating func setOf(_ element: T) -> Int? { - if let indexOfElement = index[element] { - return setByIndex(indexOfElement) - } else { - return nil - } - } - - public mutating func unionSetsContaining(_ firstElement: T, and secondElement: T) { - if let firstSet = setOf(firstElement), let secondSet = setOf(secondElement) { - if firstSet != secondSet { - if size[firstSet] < size[secondSet] { - parent[firstSet] = secondSet - size[secondSet] += size[firstSet] - } else { - parent[secondSet] = firstSet - size[firstSet] += size[secondSet] - } - } - } - } - - public mutating func inSameSet(_ firstElement: T, and secondElement: T) -> Bool { - if let firstSet = setOf(firstElement), let secondSet = setOf(secondElement) { - return firstSet == secondSet - } else { - return false - } - } -} From 0de6055763a91902d3a52ef4857930aec6dbd0d7 Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Tue, 25 Apr 2017 17:36:09 +0300 Subject: [PATCH 0979/1679] Added code description --- Dijkstra Algorithm/README.md | 138 +++++++++++++++++++++++++++++++++++ 1 file changed, 138 insertions(+) diff --git a/Dijkstra Algorithm/README.md b/Dijkstra Algorithm/README.md index 086e60c55..a72843e69 100644 --- a/Dijkstra Algorithm/README.md +++ b/Dijkstra Algorithm/README.md @@ -132,6 +132,144 @@ From now we repeat all actions again and fill our table with new info! | Path Length From Start | 0 | 3 | 8 | 1 | 2 | | Path Vertices From Start | [A] | [A, B] | [A, B, C]| [A, D] | [A, D, E ] | + +## Code implementation +First of all, lets create class, that will describe any Vertex in the graph. +It is pretty simple +```swift +open class Vertex { + + //Every vertex should be unique, that's why we set up identifier + open var identifier: String + + //For dijkstra every vertex in the graph should be connected with at least one other vertex. But there can be some use cases, + //when you firstly initialize all vertices without neighbors. And then on next interation set up thei neighbors. So, initially neighbors is an empty array. + //Array contains tuples (Vertex, Double). Vertex is a neighbor and Double is as edge weight to that neighbor. + open var neighbors: [(Vertex, Double)] = [] + + //As it was mentioned in algorithm description, default path length from start for all vertices should be as much as possible. + //It is var, because we will update it during algorithm execution. + open var pathLengthFromStart = Double.infinity + + //This array containt vertices, which we need to go through to reach this vertex from starting one + //As with path length from start, we will change this array during algorithm execution. + open var pathVerticesFromStart: [Vertex] = [] + + public init(identifier: String) { + self.identifier = identifier + } + + //This function let us use the same array of vertices again and again to calculate paths with different starting vertex. + //When we will need to set new starting vertex andd recalculate paths, then we will simply clear graph vertices' cashes. + open func clearCache() { + pathLengthFromStart = Double.infinity + pathVerticesFromStart = [] + } +} +``` + +Because every vertex should be unique it is usefull to make them Hashable and according Equatable. We use identifier for this purposes. +```swift +extension Vertex: Hashable { + open var hashValue: Int { + return identifier.hashValue + } +} + +extension Vertex: Equatable { + public static func ==(lhs: Vertex, rhs: Vertex) -> Bool { + return lhs.hashValue == rhs.hashValue + } +} +``` + +We've created a base for our algorithm. Now let's create a house :) +Dijkstra's realization is really straightforward. +```swift +public class Dijkstra { + //It is a storage for vertices in the graph. + //Assuming, that our vertices are unique, we can use Set instead of array. This approach will bring some benefits later. + private var totalVertices: Set + + public init(vertices: Set) { + totalVertices = vertices + } + + //Remember clearCache function in the Vertex class implementation? + //This is just a wrapper that cleans cache for all stored vertices. + private func clearCache() { + totalVertices.forEach { $0.clearCache() } + } + + public func findShortestPaths(from startVertex: Vertex) { + //Before we start searching shortes path from startVertex, + //we need to clear vertices cache just to be sure, that out graph is as clean as a baby. + //Remember that every Vertex is a class and classes are passed by reference. + //So whenever you change vertex outside of this class, it will affect this vertex inside totalVertices Set + clearCache() + //Now all our vertices have Double.infinity pathLengthFromStart and empty pathVerticesFromStart array. + + //The next step in the algorithm is to set startVertex pathLengthFromStart and pathVerticesFromStart + startVertex.pathLengthFromStart = 0 + startVertex.pathVerticesFromStart.append(startVertex) + + //Here starts the main part. We will use while loop to iterate through all vertices in the graph. + //For this purpose we define currentVertex variable, which we will change in the end of each while cycle. + var currentVertex: Vertex? = startVertex + + while let vertex = currentVertex { + + //Nex line of code is an implementation of setting vertex as visited. + //As it has been said, we should check only unvisited vertices in the graph, + //So why don't just delete it from the set? This approach let us skip checking for *"if !vertex.visited then"* + totalVertices.remove(vertex) + + //filteredNeighbors is and arrray, that contains current vertex neighbors, which aren't yet visited + let filteredNeighbors = vertex.neighbors.filter { totalVertices.contains($0.0) } + + //Let's iterate through them + for neighbor in filteredNeighbors { + //These variable are more representative, than neighbor.0 or neighbor.1 + let neighborVertex = neighbor.0 + let weight = neighbor.1 + + //Here we calculate new weight, that we can offer to neighbor. + let theoreticNewWeight = vertex.pathLengthFromStart + weight + + //If it is smaller than neighbor's current pathLengthFromStart + //Then we perform this code + if theoreticNewWeight < neighborVertex.pathLengthFromStart { + + //set new pathLengthFromStart + neighborVertex.pathLengthFromStart = theoreticNewWeight + + //set new pathVerticesFromStart + neighborVertex.pathVerticesFromStart = vertex.pathVerticesFromStart + + //append current vertex to neighbor's pathVerticesFromStart + neighborVertex.pathVerticesFromStart.append(neighborVertex) + } + } + + //If totalVertices is empty, i.e. all vertices are visited + //Than break the loop + if totalVertices.isEmpty { + currentVertex = nil + break + } + + //If loop is not broken, than pick next vertex for checkin from not visited. + //Next vertex pathLengthFromStart should be the smallest one. + currentVertex = totalVertices.min { $0.pathLengthFromStart < $1.pathLengthFromStart } + } + } +} +``` + +That's all! Now you can check this algorithm in the playground. On the main page there is a code for creating random graph. + +Also there is a **VisualizedDijkstra.playground**. Use it to figure out algorithm flow in real (slowed :)) time. + ## About this repository This repository contains to playgrounds: From aac4f8fbf24f6996b70ea5c1f792ba7b81cd9e98 Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Tue, 25 Apr 2017 17:54:34 +0300 Subject: [PATCH 0980/1679] Fixed code comments --- Dijkstra Algorithm/README.md | 76 ++++++++++++++++++------------------ 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/Dijkstra Algorithm/README.md b/Dijkstra Algorithm/README.md index a72843e69..2b6bc3875 100644 --- a/Dijkstra Algorithm/README.md +++ b/Dijkstra Algorithm/README.md @@ -139,28 +139,28 @@ It is pretty simple ```swift open class Vertex { - //Every vertex should be unique, that's why we set up identifier +//Every vertex should be unique, that's why we set up identifier open var identifier: String - //For dijkstra every vertex in the graph should be connected with at least one other vertex. But there can be some use cases, - //when you firstly initialize all vertices without neighbors. And then on next interation set up thei neighbors. So, initially neighbors is an empty array. - //Array contains tuples (Vertex, Double). Vertex is a neighbor and Double is as edge weight to that neighbor. +//For dijkstra every vertex in the graph should be connected with at least one other vertex. But there can be some use cases, +//when you firstly initialize all vertices without neighbors. And then on next interation set up thei neighbors. So, initially neighbors is an empty array. +//Array contains tuples (Vertex, Double). Vertex is a neighbor and Double is as edge weight to that neighbor. open var neighbors: [(Vertex, Double)] = [] - //As it was mentioned in algorithm description, default path length from start for all vertices should be as much as possible. - //It is var, because we will update it during algorithm execution. +//As it was mentioned in algorithm description, default path length from start for all vertices should be as much as possible. +//It is var, because we will update it during algorithm execution. open var pathLengthFromStart = Double.infinity - //This array containt vertices, which we need to go through to reach this vertex from starting one - //As with path length from start, we will change this array during algorithm execution. +//This array containt vertices, which we need to go through to reach this vertex from starting one +//As with path length from start, we will change this array during algorithm execution. open var pathVerticesFromStart: [Vertex] = [] public init(identifier: String) { self.identifier = identifier } - //This function let us use the same array of vertices again and again to calculate paths with different starting vertex. - //When we will need to set new starting vertex andd recalculate paths, then we will simply clear graph vertices' cashes. +//This function let us use the same array of vertices again and again to calculate paths with different starting vertex. +//When we will need to set new starting vertex andd recalculate paths, then we will simply clear graph vertices' cashes. open func clearCache() { pathLengthFromStart = Double.infinity pathVerticesFromStart = [] @@ -187,79 +187,79 @@ We've created a base for our algorithm. Now let's create a house :) Dijkstra's realization is really straightforward. ```swift public class Dijkstra { - //It is a storage for vertices in the graph. - //Assuming, that our vertices are unique, we can use Set instead of array. This approach will bring some benefits later. +//It is a storage for vertices in the graph. +//Assuming, that our vertices are unique, we can use Set instead of array. This approach will bring some benefits later. private var totalVertices: Set public init(vertices: Set) { totalVertices = vertices } - //Remember clearCache function in the Vertex class implementation? - //This is just a wrapper that cleans cache for all stored vertices. +//Remember clearCache function in the Vertex class implementation? +//This is just a wrapper that cleans cache for all stored vertices. private func clearCache() { totalVertices.forEach { $0.clearCache() } } public func findShortestPaths(from startVertex: Vertex) { - //Before we start searching shortes path from startVertex, - //we need to clear vertices cache just to be sure, that out graph is as clean as a baby. - //Remember that every Vertex is a class and classes are passed by reference. - //So whenever you change vertex outside of this class, it will affect this vertex inside totalVertices Set +//Before we start searching shortes path from startVertex, +//we need to clear vertices cache just to be sure, that out graph is as clean as a baby. +//Remember that every Vertex is a class and classes are passed by reference. +//So whenever you change vertex outside of this class, it will affect this vertex inside totalVertices Set clearCache() - //Now all our vertices have Double.infinity pathLengthFromStart and empty pathVerticesFromStart array. +//Now all our vertices have Double.infinity pathLengthFromStart and empty pathVerticesFromStart array. - //The next step in the algorithm is to set startVertex pathLengthFromStart and pathVerticesFromStart +//The next step in the algorithm is to set startVertex pathLengthFromStart and pathVerticesFromStart startVertex.pathLengthFromStart = 0 startVertex.pathVerticesFromStart.append(startVertex) - //Here starts the main part. We will use while loop to iterate through all vertices in the graph. - //For this purpose we define currentVertex variable, which we will change in the end of each while cycle. +//Here starts the main part. We will use while loop to iterate through all vertices in the graph. +//For this purpose we define currentVertex variable, which we will change in the end of each while cycle. var currentVertex: Vertex? = startVertex while let vertex = currentVertex { - //Nex line of code is an implementation of setting vertex as visited. - //As it has been said, we should check only unvisited vertices in the graph, - //So why don't just delete it from the set? This approach let us skip checking for *"if !vertex.visited then"* +//Nex line of code is an implementation of setting vertex as visited. +//As it has been said, we should check only unvisited vertices in the graph, +//So why don't just delete it from the set? This approach let us skip checking for *"if !vertex.visited then"* totalVertices.remove(vertex) - //filteredNeighbors is and arrray, that contains current vertex neighbors, which aren't yet visited +//filteredNeighbors is and arrray, that contains current vertex neighbors, which aren't yet visited let filteredNeighbors = vertex.neighbors.filter { totalVertices.contains($0.0) } - //Let's iterate through them +//Let's iterate through them for neighbor in filteredNeighbors { - //These variable are more representative, than neighbor.0 or neighbor.1 +//These variable are more representative, than neighbor.0 or neighbor.1 let neighborVertex = neighbor.0 let weight = neighbor.1 - //Here we calculate new weight, that we can offer to neighbor. +//Here we calculate new weight, that we can offer to neighbor. let theoreticNewWeight = vertex.pathLengthFromStart + weight - //If it is smaller than neighbor's current pathLengthFromStart - //Then we perform this code +//If it is smaller than neighbor's current pathLengthFromStart +//Then we perform this code if theoreticNewWeight < neighborVertex.pathLengthFromStart { - //set new pathLengthFromStart +//set new pathLengthFromStart neighborVertex.pathLengthFromStart = theoreticNewWeight - //set new pathVerticesFromStart +//set new pathVerticesFromStart neighborVertex.pathVerticesFromStart = vertex.pathVerticesFromStart - //append current vertex to neighbor's pathVerticesFromStart +//append current vertex to neighbor's pathVerticesFromStart neighborVertex.pathVerticesFromStart.append(neighborVertex) } } - //If totalVertices is empty, i.e. all vertices are visited - //Than break the loop +//If totalVertices is empty, i.e. all vertices are visited +//Than break the loop if totalVertices.isEmpty { currentVertex = nil break } - //If loop is not broken, than pick next vertex for checkin from not visited. - //Next vertex pathLengthFromStart should be the smallest one. +//If loop is not broken, than pick next vertex for checkin from not visited. +//Next vertex pathLengthFromStart should be the smallest one. currentVertex = totalVertices.min { $0.pathLengthFromStart < $1.pathLengthFromStart } } } From edbccd3b4fee79fe55ce2d741833dbef431bf466 Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Tue, 25 Apr 2017 17:57:12 +0300 Subject: [PATCH 0981/1679] Fixed comments again --- Dijkstra Algorithm/README.md | 76 ++++++++++++++++++------------------ 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/Dijkstra Algorithm/README.md b/Dijkstra Algorithm/README.md index 2b6bc3875..a8ed3c827 100644 --- a/Dijkstra Algorithm/README.md +++ b/Dijkstra Algorithm/README.md @@ -139,28 +139,28 @@ It is pretty simple ```swift open class Vertex { -//Every vertex should be unique, that's why we set up identifier + //Every vertex should be unique, that's why we set up identifier open var identifier: String -//For dijkstra every vertex in the graph should be connected with at least one other vertex. But there can be some use cases, -//when you firstly initialize all vertices without neighbors. And then on next interation set up thei neighbors. So, initially neighbors is an empty array. -//Array contains tuples (Vertex, Double). Vertex is a neighbor and Double is as edge weight to that neighbor. + //For dijkstra every vertex in the graph should be connected with at least one other vertex. But there can be some use cases, + //when you firstly initialize all vertices without neighbors. And then on next interation set up thei neighbors. So, initially neighbors is an empty array. + //Array contains tuples (Vertex, Double). Vertex is a neighbor and Double is as edge weight to that neighbor. open var neighbors: [(Vertex, Double)] = [] -//As it was mentioned in algorithm description, default path length from start for all vertices should be as much as possible. -//It is var, because we will update it during algorithm execution. + //As it was mentioned in algorithm description, default path length from start for all vertices should be as much as possible. + //It is var, because we will update it during algorithm execution. open var pathLengthFromStart = Double.infinity -//This array containt vertices, which we need to go through to reach this vertex from starting one -//As with path length from start, we will change this array during algorithm execution. + //This array containt vertices, which we need to go through to reach this vertex from starting one + //As with path length from start, we will change this array during algorithm execution. open var pathVerticesFromStart: [Vertex] = [] public init(identifier: String) { self.identifier = identifier } -//This function let us use the same array of vertices again and again to calculate paths with different starting vertex. -//When we will need to set new starting vertex andd recalculate paths, then we will simply clear graph vertices' cashes. + //This function let us use the same array of vertices again and again to calculate paths with different starting vertex. + //When we will need to set new starting vertex andd recalculate paths, then we will simply clear graph vertices' cashes. open func clearCache() { pathLengthFromStart = Double.infinity pathVerticesFromStart = [] @@ -187,79 +187,79 @@ We've created a base for our algorithm. Now let's create a house :) Dijkstra's realization is really straightforward. ```swift public class Dijkstra { -//It is a storage for vertices in the graph. -//Assuming, that our vertices are unique, we can use Set instead of array. This approach will bring some benefits later. + //This is a storage for vertices in the graph. + //Assuming, that our vertices are unique, we can use Set instead of array. This approach will bring some benefits later. private var totalVertices: Set public init(vertices: Set) { totalVertices = vertices } -//Remember clearCache function in the Vertex class implementation? -//This is just a wrapper that cleans cache for all stored vertices. + //Remember clearCache function in the Vertex class implementation? + //This is just a wrapper that cleans cache for all stored vertices. private func clearCache() { totalVertices.forEach { $0.clearCache() } } public func findShortestPaths(from startVertex: Vertex) { -//Before we start searching shortes path from startVertex, -//we need to clear vertices cache just to be sure, that out graph is as clean as a baby. -//Remember that every Vertex is a class and classes are passed by reference. -//So whenever you change vertex outside of this class, it will affect this vertex inside totalVertices Set + //Before we start searching shortes path from startVertex, + //we need to clear vertices cache just to be sure, that out graph is as clean as a baby. + //Remember that every Vertex is a class and classes are passed by reference. + //So whenever you change vertex outside of this class, it will affect this vertex inside totalVertices Set clearCache() -//Now all our vertices have Double.infinity pathLengthFromStart and empty pathVerticesFromStart array. + //Now all our vertices have Double.infinity pathLengthFromStart and empty pathVerticesFromStart array. -//The next step in the algorithm is to set startVertex pathLengthFromStart and pathVerticesFromStart + //The next step in the algorithm is to set startVertex pathLengthFromStart and pathVerticesFromStart startVertex.pathLengthFromStart = 0 startVertex.pathVerticesFromStart.append(startVertex) -//Here starts the main part. We will use while loop to iterate through all vertices in the graph. -//For this purpose we define currentVertex variable, which we will change in the end of each while cycle. + //Here starts the main part. We will use while loop to iterate through all vertices in the graph. + //For this purpose we define currentVertex variable, which we will change in the end of each while cycle. var currentVertex: Vertex? = startVertex while let vertex = currentVertex { -//Nex line of code is an implementation of setting vertex as visited. -//As it has been said, we should check only unvisited vertices in the graph, -//So why don't just delete it from the set? This approach let us skip checking for *"if !vertex.visited then"* + //Nex line of code is an implementation of setting vertex as visited. + //As it has been said, we should check only unvisited vertices in the graph, + //So why don't just delete it from the set? This approach let us skip checking for *"if !vertex.visited then"* totalVertices.remove(vertex) -//filteredNeighbors is and arrray, that contains current vertex neighbors, which aren't yet visited + //filteredNeighbors is and arrray, that contains current vertex neighbors, which aren't yet visited let filteredNeighbors = vertex.neighbors.filter { totalVertices.contains($0.0) } -//Let's iterate through them + //Let's iterate through them for neighbor in filteredNeighbors { -//These variable are more representative, than neighbor.0 or neighbor.1 + //These variable are more representative, than neighbor.0 or neighbor.1 let neighborVertex = neighbor.0 let weight = neighbor.1 -//Here we calculate new weight, that we can offer to neighbor. + //Here we calculate new weight, that we can offer to neighbor. let theoreticNewWeight = vertex.pathLengthFromStart + weight -//If it is smaller than neighbor's current pathLengthFromStart -//Then we perform this code + //If it is smaller than neighbor's current pathLengthFromStart + //Then we perform this code if theoreticNewWeight < neighborVertex.pathLengthFromStart { -//set new pathLengthFromStart + //set new pathLengthFromStart neighborVertex.pathLengthFromStart = theoreticNewWeight -//set new pathVerticesFromStart + //set new pathVerticesFromStart neighborVertex.pathVerticesFromStart = vertex.pathVerticesFromStart -//append current vertex to neighbor's pathVerticesFromStart + //append current vertex to neighbor's pathVerticesFromStart neighborVertex.pathVerticesFromStart.append(neighborVertex) } } -//If totalVertices is empty, i.e. all vertices are visited -//Than break the loop + //If totalVertices is empty, i.e. all vertices are visited + //Than break the loop if totalVertices.isEmpty { currentVertex = nil break } -//If loop is not broken, than pick next vertex for checkin from not visited. -//Next vertex pathLengthFromStart should be the smallest one. + //If loop is not broken, than pick next vertex for checkin from not visited. + //Next vertex pathLengthFromStart should be the smallest one. currentVertex = totalVertices.min { $0.pathLengthFromStart < $1.pathLengthFromStart } } } From b6c5b820be7506bbbfec04b230bbedcda1b6f5d0 Mon Sep 17 00:00:00 2001 From: Taras Date: Tue, 25 Apr 2017 18:02:52 +0300 Subject: [PATCH 0982/1679] Update README.md --- Dijkstra Algorithm/README.md | 80 ++++++++++++++++++------------------ 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/Dijkstra Algorithm/README.md b/Dijkstra Algorithm/README.md index a8ed3c827..f8ac37cf0 100644 --- a/Dijkstra Algorithm/README.md +++ b/Dijkstra Algorithm/README.md @@ -139,28 +139,28 @@ It is pretty simple ```swift open class Vertex { - //Every vertex should be unique, that's why we set up identifier + //Every vertex should be unique, that's why we set up identifier open var identifier: String - //For dijkstra every vertex in the graph should be connected with at least one other vertex. But there can be some use cases, - //when you firstly initialize all vertices without neighbors. And then on next interation set up thei neighbors. So, initially neighbors is an empty array. - //Array contains tuples (Vertex, Double). Vertex is a neighbor and Double is as edge weight to that neighbor. + //For dijkstra every vertex in the graph should be connected with at least one other vertex. But there can be some use cases, + //when you firstly initialize all vertices without neighbors. And then on next interation set up thei neighbors. So, initially neighbors is an empty array. + //Array contains tuples (Vertex, Double). Vertex is a neighbor and Double is as edge weight to that neighbor. open var neighbors: [(Vertex, Double)] = [] - //As it was mentioned in algorithm description, default path length from start for all vertices should be as much as possible. - //It is var, because we will update it during algorithm execution. + //As it was mentioned in algorithm description, default path length from start for all vertices should be as much as possible. + //It is var, because we will update it during algorithm execution. open var pathLengthFromStart = Double.infinity - - //This array containt vertices, which we need to go through to reach this vertex from starting one - //As with path length from start, we will change this array during algorithm execution. + + //This array containt vertices, which we need to go through to reach this vertex from starting one + //As with path length from start, we will change this array during algorithm execution. open var pathVerticesFromStart: [Vertex] = [] public init(identifier: String) { self.identifier = identifier } - //This function let us use the same array of vertices again and again to calculate paths with different starting vertex. - //When we will need to set new starting vertex andd recalculate paths, then we will simply clear graph vertices' cashes. + //This function let us use the same array of vertices again and again to calculate paths with different starting vertex. + //When we will need to set new starting vertex andd recalculate paths, then we will simply clear graph vertices' cashes. open func clearCache() { pathLengthFromStart = Double.infinity pathVerticesFromStart = [] @@ -187,79 +187,79 @@ We've created a base for our algorithm. Now let's create a house :) Dijkstra's realization is really straightforward. ```swift public class Dijkstra { - //This is a storage for vertices in the graph. - //Assuming, that our vertices are unique, we can use Set instead of array. This approach will bring some benefits later. + //This is a storage for vertices in the graph. + //Assuming, that our vertices are unique, we can use Set instead of array. This approach will bring some benefits later. private var totalVertices: Set public init(vertices: Set) { totalVertices = vertices } - //Remember clearCache function in the Vertex class implementation? - //This is just a wrapper that cleans cache for all stored vertices. + //Remember clearCache function in the Vertex class implementation? + //This is just a wrapper that cleans cache for all stored vertices. private func clearCache() { totalVertices.forEach { $0.clearCache() } } public func findShortestPaths(from startVertex: Vertex) { - //Before we start searching shortes path from startVertex, - //we need to clear vertices cache just to be sure, that out graph is as clean as a baby. - //Remember that every Vertex is a class and classes are passed by reference. - //So whenever you change vertex outside of this class, it will affect this vertex inside totalVertices Set + //Before we start searching shortes path from startVertex, + //we need to clear vertices cache just to be sure, that out graph is as clean as a baby. + //Remember that every Vertex is a class and classes are passed by reference. + //So whenever you change vertex outside of this class, it will affect this vertex inside totalVertices Set clearCache() - //Now all our vertices have Double.infinity pathLengthFromStart and empty pathVerticesFromStart array. + //Now all our vertices have Double.infinity pathLengthFromStart and empty pathVerticesFromStart array. - //The next step in the algorithm is to set startVertex pathLengthFromStart and pathVerticesFromStart + //The next step in the algorithm is to set startVertex pathLengthFromStart and pathVerticesFromStart startVertex.pathLengthFromStart = 0 startVertex.pathVerticesFromStart.append(startVertex) - //Here starts the main part. We will use while loop to iterate through all vertices in the graph. - //For this purpose we define currentVertex variable, which we will change in the end of each while cycle. + //Here starts the main part. We will use while loop to iterate through all vertices in the graph. + //For this purpose we define currentVertex variable, which we will change in the end of each while cycle. var currentVertex: Vertex? = startVertex while let vertex = currentVertex { - - //Nex line of code is an implementation of setting vertex as visited. - //As it has been said, we should check only unvisited vertices in the graph, - //So why don't just delete it from the set? This approach let us skip checking for *"if !vertex.visited then"* + + //Nex line of code is an implementation of setting vertex as visited. + //As it has been said, we should check only unvisited vertices in the graph, + //So why don't just delete it from the set? This approach let us skip checking for *"if !vertex.visited then"* totalVertices.remove(vertex) - //filteredNeighbors is and arrray, that contains current vertex neighbors, which aren't yet visited + //filteredNeighbors is and arrray, that contains current vertex neighbors, which aren't yet visited let filteredNeighbors = vertex.neighbors.filter { totalVertices.contains($0.0) } - //Let's iterate through them + //Let's iterate through them for neighbor in filteredNeighbors { - //These variable are more representative, than neighbor.0 or neighbor.1 + //These variable are more representative, than neighbor.0 or neighbor.1 let neighborVertex = neighbor.0 let weight = neighbor.1 - //Here we calculate new weight, that we can offer to neighbor. + //Here we calculate new weight, that we can offer to neighbor. let theoreticNewWeight = vertex.pathLengthFromStart + weight - //If it is smaller than neighbor's current pathLengthFromStart - //Then we perform this code + //If it is smaller than neighbor's current pathLengthFromStart + //Then we perform this code if theoreticNewWeight < neighborVertex.pathLengthFromStart { - //set new pathLengthFromStart + //set new pathLengthFromStart neighborVertex.pathLengthFromStart = theoreticNewWeight - //set new pathVerticesFromStart + //set new pathVerticesFromStart neighborVertex.pathVerticesFromStart = vertex.pathVerticesFromStart - //append current vertex to neighbor's pathVerticesFromStart + //append current vertex to neighbor's pathVerticesFromStart neighborVertex.pathVerticesFromStart.append(neighborVertex) } } - //If totalVertices is empty, i.e. all vertices are visited - //Than break the loop + //If totalVertices is empty, i.e. all vertices are visited + //Than break the loop if totalVertices.isEmpty { currentVertex = nil break } - //If loop is not broken, than pick next vertex for checkin from not visited. - //Next vertex pathLengthFromStart should be the smallest one. + //If loop is not broken, than pick next vertex for checkin from not visited. + //Next vertex pathLengthFromStart should be the smallest one. currentVertex = totalVertices.min { $0.pathLengthFromStart < $1.pathLengthFromStart } } } From 9575a6745caa33bc5d864d6e406682af2f5f9515 Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Tue, 25 Apr 2017 18:22:00 +0300 Subject: [PATCH 0983/1679] Added some comments to playground --- Dijkstra Algorithm/Dijkstra.playground/Contents.swift | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Dijkstra Algorithm/Dijkstra.playground/Contents.swift b/Dijkstra Algorithm/Dijkstra.playground/Contents.swift index 1c12245bd..7c7f1a4b0 100644 --- a/Dijkstra Algorithm/Dijkstra.playground/Contents.swift +++ b/Dijkstra Algorithm/Dijkstra.playground/Contents.swift @@ -14,13 +14,18 @@ func createNotConnectedVertices() { func setupConnections() { for vertex in vertices { + //the amount of edges each vertex can have let randomEdgesCount = arc4random_uniform(4) + 1 for _ in 0.. Date: Wed, 26 Apr 2017 10:31:44 +0300 Subject: [PATCH 0984/1679] Final edits --- Dijkstra Algorithm/README.md | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/Dijkstra Algorithm/README.md b/Dijkstra Algorithm/README.md index f8ac37cf0..db1726b1f 100644 --- a/Dijkstra Algorithm/README.md +++ b/Dijkstra Algorithm/README.md @@ -2,13 +2,13 @@ This [algorithm](https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm) was invented in 1956 by Edsger W. Dijkstra. -This algorithm can be used, when you have one source vertex and want to find the shortest paths to all other vertices in the graph. +It can be used, when you have one source vertex and want to find the shortest paths to all other vertices in the graph. The best example is road network. If you wnat to find the shortest path from your house to your job, then it is time for the Dijkstra's algorithm. -I have created **VisualizedDijkstra.playground** to help you to understand, how this algorithm works. Besides, I have described below step by step how does it works. +I have created **VisualizedDijkstra.playground** to improve your understanding of the algorithm's flow. Besides, below is step by step algorithm's description. -So let's imagine, that your house is "A" vertex and your job is "B" vertex. And you are lucky, you have graph with all possible routes. +Let's imagine, you want to go to the shop. Your house is A vertex and there are 4 possible stores around your house. How to find the closest one/ones? Luckily, you have graph, that connects your house with all these stores. So, you know what to do :) ## Initialization @@ -30,7 +30,7 @@ The table below represents graph state: >T states for True -To initialize out graph we have to set source vertex path length from source vertex to 0, and append itself to path vertices ffrom start. +To initialize our graph we have to set source vertex path length from source vertex to 0, and append itself to path vertices from start. | | A | B | C | D | E | |:------------------------- |:---:|:---:|:---:|:---:|:---:| @@ -40,7 +40,7 @@ To initialize out graph we have to set source vertex path length from source ver Great, now our graph is initialized and we can pass it to the Dijkstra's algorithm. -But before we will go through all process side by side let me explain how algorithm works. +But before we will go through all process side by side read this explanation. The algorithm repeats following cycle until all vertices are marked as visited. Cycle: 1. From the non-visited vertices the algorithm picks a vertex with the shortest path length from the start (if there are more than one vertex with the same shortest path value, then algorithm picks any of them) @@ -50,7 +50,7 @@ When all vertices are marked as visited, the algorithm's job is done. Now, you c Okay, let's start! Let's follow the algorithm's cycle and pick the first vertex, which neighbors we want to check. -All our vertices are not visited, but there is only one have the smallest path length from start - A. This vertex is th first one, which neighbors we will check. +All our vertices are not visited, but there is only one has the smallest path length from start - A. This vertex is the first one, which neighbors we will check. First of all, set this vertex as visited A.visited = true @@ -268,7 +268,9 @@ public class Dijkstra { That's all! Now you can check this algorithm in the playground. On the main page there is a code for creating random graph. -Also there is a **VisualizedDijkstra.playground**. Use it to figure out algorithm flow in real (slowed :)) time. +Also there is a **VisualizedDijkstra.playground**. Use it to figure out algorithm's flow in real (slowed :)) time. + +It is up to you how to implement some specific parts of algorithm, you can use Array instead of Set, add _visited_ property to Vertex or you can create some local totalVertices Array/Set inside _func findShortestPaths(from startVertex: Vertex)_ to keep totalVertices Array/Set unchanged. This is a general explanation with one possible implementation :) ## About this repository From d79a076ea901657161392a4fc3b53b0e2df65cdd Mon Sep 17 00:00:00 2001 From: Lucy Jeong Date: Thu, 27 Apr 2017 11:31:57 +0900 Subject: [PATCH 0985/1679] Update README.markdown changed enumerate() -> enumerated() --- Hash Table/README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Hash Table/README.markdown b/Hash Table/README.markdown index bc9636195..8f1eaaf70 100644 --- a/Hash Table/README.markdown +++ b/Hash Table/README.markdown @@ -202,7 +202,7 @@ The code to insert a new element or update an existing element lives in `updateV let index = self.index(forKey: key) // Do we already have this key in the bucket? - for (i, element) in buckets[index].enumerate() { + for (i, element) in buckets[index].enumerated() { if element.key == key { let oldValue = element.value buckets[index][i].value = value From 03393a86a3864221ff1f0b7137eefb619bf19698 Mon Sep 17 00:00:00 2001 From: Jawwad Ahmad Date: Fri, 28 Apr 2017 06:17:13 +0500 Subject: [PATCH 0986/1679] Fix "found unknown escape character" while trying to run swiftlint 0.18.1 Also update the smiley face regex check to have a space before the colon so that it doesn't match: fatalError("init(coder:) has not been implemented") --- .swiftlint.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.swiftlint.yml b/.swiftlint.yml index 1434bf637..6cb714110 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -17,8 +17,8 @@ disabled_rules: custom_rules: smiley_face: name: "Smiley Face" - regex: "(\:\))" - match_kinds: + regex: '( :\))' + match_kinds: - comment - string message: "A closing parenthesis smiley :) creates a half-hearted smile, and thus is not preferred. Use :]" From 018ddaccfc0276ac8740c093731b92aeae122a9d Mon Sep 17 00:00:00 2001 From: Jawwad Ahmad Date: Fri, 28 Apr 2017 09:42:15 +0500 Subject: [PATCH 0987/1679] [swiftlint] Fix: MARK comment should be in valid format. --- .../TST.playground/Sources/TernarySearchTree.swift | 4 ++-- Ternary Search Tree/TernarySearchTree.swift | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Ternary Search Tree/TST.playground/Sources/TernarySearchTree.swift b/Ternary Search Tree/TST.playground/Sources/TernarySearchTree.swift index fed8f9710..21b8f0dc3 100644 --- a/Ternary Search Tree/TST.playground/Sources/TernarySearchTree.swift +++ b/Ternary Search Tree/TST.playground/Sources/TernarySearchTree.swift @@ -15,7 +15,7 @@ public class TernarySearchTree { public init() {} - //MARK: - Insertion + // MARK: - Insertion public func insert(data: Element, withKey key: String) -> Bool { return insert(node: &root, withData: data, andKey: key, atIndex: 0) @@ -59,7 +59,7 @@ public class TernarySearchTree { } - //MARK: - Finding + // MARK: - Finding public func find(key: String) -> Element? { diff --git a/Ternary Search Tree/TernarySearchTree.swift b/Ternary Search Tree/TernarySearchTree.swift index 2e2ca2917..0fa6d9634 100644 --- a/Ternary Search Tree/TernarySearchTree.swift +++ b/Ternary Search Tree/TernarySearchTree.swift @@ -23,7 +23,7 @@ public class TernarySearchTree { */ public init() {} - //MARK: - Insertion + // MARK: - Insertion /** Public insertion method. @@ -85,7 +85,7 @@ public class TernarySearchTree { } - //MARK: - Finding + // MARK: - Finding /** Public find method. From 29c5952fadf80e8ac3f0c717d7d7ae08620b0dcb Mon Sep 17 00:00:00 2001 From: Felipe Naranjo Date: Fri, 28 Apr 2017 10:57:48 -0400 Subject: [PATCH 0988/1679] Update README.markdown Though "indexes" is grammatically correct, the word "indices" is used in Apple documentation. --- Union-Find/README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Union-Find/README.markdown b/Union-Find/README.markdown index 5102f6b89..68698f39e 100644 --- a/Union-Find/README.markdown +++ b/Union-Find/README.markdown @@ -119,7 +119,7 @@ Here's illustration of what I mean. Let's say the tree looks like this: ![BeforeFind](Images/BeforeFind.png) -We call `setOf(4)`. To find the root node we have to first go to node `2` and then to node `7`. (The indexes of the elements are marked in red.) +We call `setOf(4)`. To find the root node we have to first go to node `2` and then to node `7`. (The indices of the elements are marked in red.) During the call to `setOf(4)`, the tree is reorganized to look like this: From 137c36051dff6a1e3965dad4959ad0a742fc01b4 Mon Sep 17 00:00:00 2001 From: Jawwad Ahmad Date: Fri, 28 Apr 2017 09:46:49 +0500 Subject: [PATCH 0989/1679] [swiftlint] Fix: Else and catch should be on the same line warning: Statement Position Violation: Else and catch should be on the same line, one space after the previous declaration. --- DiningPhilosophers/Sources/main.swift | 3 +-- Skip-List/SkipList.swift | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/DiningPhilosophers/Sources/main.swift b/DiningPhilosophers/Sources/main.swift index 285402d53..338a9074d 100755 --- a/DiningPhilosophers/Sources/main.swift +++ b/DiningPhilosophers/Sources/main.swift @@ -22,8 +22,7 @@ struct ForkPair { if leftIndex > rightIndex { leftFork = ForkPair.forksSemaphore[leftIndex] rightFork = ForkPair.forksSemaphore[rightIndex] - } - else { + } else { leftFork = ForkPair.forksSemaphore[rightIndex] rightFork = ForkPair.forksSemaphore[leftIndex] } diff --git a/Skip-List/SkipList.swift b/Skip-List/SkipList.swift index 5fc61bf8e..c5fe2b821 100644 --- a/Skip-List/SkipList.swift +++ b/Skip-List/SkipList.swift @@ -118,8 +118,7 @@ extension SkipList { if value.key == key { isFound = true break - } - else { + } else { if key < value.key! { currentNode = node.down } else { From c3a05c6bfe865554261fbb0b641651f7dcfffff4 Mon Sep 17 00:00:00 2001 From: Jawwad Ahmad Date: Fri, 28 Apr 2017 09:49:54 +0500 Subject: [PATCH 0990/1679] [swiftlint] Fix: trailing_semicolon warning: Trailing Semicolon Violation: Lines should not have trailing semicolons. --- Trie/Trie/TrieTests/TrieTests.swift | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Trie/Trie/TrieTests/TrieTests.swift b/Trie/Trie/TrieTests/TrieTests.swift index a75c35c62..50a30a552 100644 --- a/Trie/Trie/TrieTests/TrieTests.swift +++ b/Trie/Trie/TrieTests/TrieTests.swift @@ -175,21 +175,21 @@ class TrieTests: XCTestCase { trie.insert(word: "another") trie.insert(word: "exam") let wordsAll = trie.findWordsWithPrefix(prefix: "") - XCTAssertEqual(wordsAll.sorted(), ["another", "exam", "test"]); + XCTAssertEqual(wordsAll.sorted(), ["another", "exam", "test"]) let words = trie.findWordsWithPrefix(prefix: "ex") - XCTAssertEqual(words, ["exam"]); + XCTAssertEqual(words, ["exam"]) trie.insert(word: "examination") let words2 = trie.findWordsWithPrefix(prefix: "exam") - XCTAssertEqual(words2, ["exam", "examination"]); + XCTAssertEqual(words2, ["exam", "examination"]) let noWords = trie.findWordsWithPrefix(prefix: "tee") - XCTAssertEqual(noWords, []); + XCTAssertEqual(noWords, []) let unicodeWord = "😬😎" trie.insert(word: unicodeWord) let wordsUnicode = trie.findWordsWithPrefix(prefix: "😬") - XCTAssertEqual(wordsUnicode, [unicodeWord]); + XCTAssertEqual(wordsUnicode, [unicodeWord]) trie.insert(word: "Team") let wordsUpperCase = trie.findWordsWithPrefix(prefix: "Te") - XCTAssertEqual(wordsUpperCase.sorted(), ["team", "test"]); + XCTAssertEqual(wordsUpperCase.sorted(), ["team", "test"]) } } From 4eb7ac1975dfbd2f3d9059d649af3ab6f90d97a2 Mon Sep 17 00:00:00 2001 From: Jawwad Ahmad Date: Fri, 28 Apr 2017 09:52:12 +0500 Subject: [PATCH 0991/1679] [swiftlint] Fix control_statement (i.e. parens around if statement) warning: Control Statement Violation: if,for,while,do statements shouldn't wrap their conditionals in parentheses. --- Rootish Array Stack/Tests/RootishArrayStackTests.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Rootish Array Stack/Tests/RootishArrayStackTests.swift b/Rootish Array Stack/Tests/RootishArrayStackTests.swift index f73857d0f..9ffc4ebb9 100755 --- a/Rootish Array Stack/Tests/RootishArrayStackTests.swift +++ b/Rootish Array Stack/Tests/RootishArrayStackTests.swift @@ -4,7 +4,7 @@ fileprivate extension RootishArrayStack { func equal(toArray array: Array) -> Bool{ for index in 0.. Date: Fri, 28 Apr 2017 09:53:16 +0500 Subject: [PATCH 0992/1679] [swiftlint] Fix redundant_optional_initialization (i.e. don't need "= nil") warning: Redundant Optional Initialization Violation: Initializing an optional variable with nil is redundant. --- Graph/Graph/AdjacencyListGraph.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Graph/Graph/AdjacencyListGraph.swift b/Graph/Graph/AdjacencyListGraph.swift index e5e9fc2db..edb754c97 100644 --- a/Graph/Graph/AdjacencyListGraph.swift +++ b/Graph/Graph/AdjacencyListGraph.swift @@ -12,7 +12,7 @@ import Foundation private class EdgeList where T: Equatable, T: Hashable { var vertex: Vertex - var edges: [Edge]? = nil + var edges: [Edge]? init(vertex: Vertex) { self.vertex = vertex From 55eba6e7d86e468b1cb0f114c25f5439cf2d4702 Mon Sep 17 00:00:00 2001 From: Jawwad Ahmad Date: Fri, 28 Apr 2017 09:55:51 +0500 Subject: [PATCH 0993/1679] [swiftlint] Fix: closure_parameter_position warning: Closure Parameter Position Violation: Closure parameters should be on the same line as opening brace. --- B-Tree/BTree.playground/Contents.swift | 3 +-- Shunting Yard/ShuntingYard.playground/Sources/Stack.swift | 3 +-- Skip-List/SkipList.swift | 7 +++---- Stack/Stack.swift | 3 +-- 4 files changed, 6 insertions(+), 10 deletions(-) diff --git a/B-Tree/BTree.playground/Contents.swift b/B-Tree/BTree.playground/Contents.swift index 8238fe5a5..710ace701 100644 --- a/B-Tree/BTree.playground/Contents.swift +++ b/B-Tree/BTree.playground/Contents.swift @@ -14,8 +14,7 @@ bTree[3] bTree.remove(2) -bTree.traverseKeysInOrder { - key in +bTree.traverseKeysInOrder { key in print(key) } diff --git a/Shunting Yard/ShuntingYard.playground/Sources/Stack.swift b/Shunting Yard/ShuntingYard.playground/Sources/Stack.swift index a67bb9d64..27286fdbd 100644 --- a/Shunting Yard/ShuntingYard.playground/Sources/Stack.swift +++ b/Shunting Yard/ShuntingYard.playground/Sources/Stack.swift @@ -31,8 +31,7 @@ public struct Stack { extension Stack: Sequence { public func makeIterator() -> AnyIterator { var curr = self - return AnyIterator { - _ -> T? in + return AnyIterator { _ -> T? in return curr.pop() } } diff --git a/Skip-List/SkipList.swift b/Skip-List/SkipList.swift index c5fe2b821..1418656f3 100644 --- a/Skip-List/SkipList.swift +++ b/Skip-List/SkipList.swift @@ -52,10 +52,9 @@ public struct Stack { extension Stack: Sequence { public func makeIterator() -> AnyIterator { var curr = self - return AnyIterator { - _ -> T? in - return curr.pop() - } + return AnyIterator { _ -> T? in + return curr.pop() + } } } diff --git a/Stack/Stack.swift b/Stack/Stack.swift index 974d5a443..c3f42ea44 100644 --- a/Stack/Stack.swift +++ b/Stack/Stack.swift @@ -30,8 +30,7 @@ public struct Stack { extension Stack: Sequence { public func makeIterator() -> AnyIterator { var curr = self - return AnyIterator { - _ -> T? in + return AnyIterator { _ -> T? in return curr.pop() } } From 6c3dcd4be40058e09875d4bcd3f6086e021380e4 Mon Sep 17 00:00:00 2001 From: Jawwad Ahmad Date: Fri, 28 Apr 2017 09:57:19 +0500 Subject: [PATCH 0994/1679] [swiftlint] Fix: leading_whitespace warning: Leading Whitespace Violation: File shouldn't start with whitespace. --- HaversineDistance/HaversineDistance.playground/Contents.swift | 1 - QuadTree/QuadTree.playground/Contents.swift | 1 - QuadTree/QuadTree.playground/Sources/QuadTree.swift | 1 - Red-Black Tree/Red-Black Tree 2.playground/Sources/RBTree.swift | 1 - 4 files changed, 4 deletions(-) diff --git a/HaversineDistance/HaversineDistance.playground/Contents.swift b/HaversineDistance/HaversineDistance.playground/Contents.swift index f46d7c394..a6effb7b0 100644 --- a/HaversineDistance/HaversineDistance.playground/Contents.swift +++ b/HaversineDistance/HaversineDistance.playground/Contents.swift @@ -1,4 +1,3 @@ - import UIKit func haversineDinstance(la1: Double, lo1: Double, la2: Double, lo2: Double, radius: Double = 6367444.7) -> Double { diff --git a/QuadTree/QuadTree.playground/Contents.swift b/QuadTree/QuadTree.playground/Contents.swift index 41e73147f..ad8ee31f8 100644 --- a/QuadTree/QuadTree.playground/Contents.swift +++ b/QuadTree/QuadTree.playground/Contents.swift @@ -1,4 +1,3 @@ - import Foundation let tree = QuadTree(rect: Rect(origin: Point(0, 0), size: Size(xLength: 10, yLength: 10))) diff --git a/QuadTree/QuadTree.playground/Sources/QuadTree.swift b/QuadTree/QuadTree.playground/Sources/QuadTree.swift index 65c55d49e..14d0dbba7 100644 --- a/QuadTree/QuadTree.playground/Sources/QuadTree.swift +++ b/QuadTree/QuadTree.playground/Sources/QuadTree.swift @@ -1,4 +1,3 @@ - public struct Point { let x: Double let y: Double diff --git a/Red-Black Tree/Red-Black Tree 2.playground/Sources/RBTree.swift b/Red-Black Tree/Red-Black Tree 2.playground/Sources/RBTree.swift index 1735798d5..b0f440809 100644 --- a/Red-Black Tree/Red-Black Tree 2.playground/Sources/RBTree.swift +++ b/Red-Black Tree/Red-Black Tree 2.playground/Sources/RBTree.swift @@ -1,4 +1,3 @@ - private enum RBTColor { case red case black From 932b453d5b0ce1b5ad058323bed79728f92dfd52 Mon Sep 17 00:00:00 2001 From: Jawwad Ahmad Date: Fri, 28 Apr 2017 09:58:51 +0500 Subject: [PATCH 0995/1679] [swiftlint] Fix rule: trailing_newline warning: Trailing Newline Violation: Files should have a single trailing newline. --- B-Tree/Tests/Tests/BTreeNodeTests.swift | 1 - Comb Sort/Comb Sort.playground/Contents.swift | 2 -- Convex Hull/Convex Hull/AppDelegate.swift | 1 - Fixed Size Array/FixedSizeArray.playground/Contents.swift | 1 - Insertion Sort/InsertionSort.playground/Contents.swift | 2 +- Linked List/LinkedList.playground/Contents.swift | 1 - .../MRPrimality.playground/Contents.swift | 2 +- Run-Length Encoding/RLE.playground/Contents.swift | 2 +- Trie/Trie/Trie/AppDelegate.swift | 1 - Trie/Trie/Trie/ViewController.swift | 1 - 10 files changed, 3 insertions(+), 11 deletions(-) diff --git a/B-Tree/Tests/Tests/BTreeNodeTests.swift b/B-Tree/Tests/Tests/BTreeNodeTests.swift index da6ebe9f6..fd3ba10e8 100644 --- a/B-Tree/Tests/Tests/BTreeNodeTests.swift +++ b/B-Tree/Tests/Tests/BTreeNodeTests.swift @@ -51,4 +51,3 @@ class BTreeNodeTests: XCTestCase { XCTAssertEqual(root.children!.count, 2) } } - diff --git a/Comb Sort/Comb Sort.playground/Contents.swift b/Comb Sort/Comb Sort.playground/Contents.swift index d6add44f5..40176be9f 100644 --- a/Comb Sort/Comb Sort.playground/Contents.swift +++ b/Comb Sort/Comb Sort.playground/Contents.swift @@ -16,5 +16,3 @@ while i < 1000 { i += 1 } combSort(bigArray) - - diff --git a/Convex Hull/Convex Hull/AppDelegate.swift b/Convex Hull/Convex Hull/AppDelegate.swift index 1901083a8..4f8496cd5 100644 --- a/Convex Hull/Convex Hull/AppDelegate.swift +++ b/Convex Hull/Convex Hull/AppDelegate.swift @@ -54,4 +54,3 @@ class AppDelegate: UIResponder, UIApplicationDelegate { } - diff --git a/Fixed Size Array/FixedSizeArray.playground/Contents.swift b/Fixed Size Array/FixedSizeArray.playground/Contents.swift index f1bc63315..4bc5d66df 100644 --- a/Fixed Size Array/FixedSizeArray.playground/Contents.swift +++ b/Fixed Size Array/FixedSizeArray.playground/Contents.swift @@ -53,4 +53,3 @@ array.append(2) array[1] array.removeAt(index: 0) array.removeAll() - diff --git a/Insertion Sort/InsertionSort.playground/Contents.swift b/Insertion Sort/InsertionSort.playground/Contents.swift index b25916b23..df1822b8f 100644 --- a/Insertion Sort/InsertionSort.playground/Contents.swift +++ b/Insertion Sort/InsertionSort.playground/Contents.swift @@ -16,4 +16,4 @@ func insertionSort(_ array: [T], _ isOrderedBefore: (T, T) -> Bool) -> [T] { let list = [ 10, -1, 3, 9, 2, 27, 8, 5, 1, 3, 0, 26 ] insertionSort(list, <) -insertionSort(list, >) \ No newline at end of file +insertionSort(list, >) diff --git a/Linked List/LinkedList.playground/Contents.swift b/Linked List/LinkedList.playground/Contents.swift index b86fbf0b4..10677935a 100644 --- a/Linked List/LinkedList.playground/Contents.swift +++ b/Linked List/LinkedList.playground/Contents.swift @@ -389,4 +389,3 @@ let listArrayLiteral2: LinkedList = ["Swift", "Algorithm", "Club"] listArrayLiteral2.count // 3 listArrayLiteral2[0] // "Swift" listArrayLiteral2.removeLast() // "Club" - diff --git a/Miller-Rabin Primality Test/MRPrimality.playground/Contents.swift b/Miller-Rabin Primality Test/MRPrimality.playground/Contents.swift index 8d97dc409..98032bd59 100644 --- a/Miller-Rabin Primality Test/MRPrimality.playground/Contents.swift +++ b/Miller-Rabin Primality Test/MRPrimality.playground/Contents.swift @@ -21,4 +21,4 @@ mrPrimalityTest(178426363) mrPrimalityTest(32415187747) // With iteration -mrPrimalityTest(32416190071, iteration: 10) \ No newline at end of file +mrPrimalityTest(32416190071, iteration: 10) diff --git a/Run-Length Encoding/RLE.playground/Contents.swift b/Run-Length Encoding/RLE.playground/Contents.swift index 62b4ef437..11e177d0d 100644 --- a/Run-Length Encoding/RLE.playground/Contents.swift +++ b/Run-Length Encoding/RLE.playground/Contents.swift @@ -113,4 +113,4 @@ func runTests() -> Bool { return result } -runTests() \ No newline at end of file +runTests() diff --git a/Trie/Trie/Trie/AppDelegate.swift b/Trie/Trie/Trie/AppDelegate.swift index 4da9dc345..b2b4c0c5f 100644 --- a/Trie/Trie/Trie/AppDelegate.swift +++ b/Trie/Trie/Trie/AppDelegate.swift @@ -23,4 +23,3 @@ class AppDelegate: NSObject, NSApplicationDelegate { } - diff --git a/Trie/Trie/Trie/ViewController.swift b/Trie/Trie/Trie/ViewController.swift index b2e9d9105..e24a812cb 100644 --- a/Trie/Trie/Trie/ViewController.swift +++ b/Trie/Trie/Trie/ViewController.swift @@ -24,4 +24,3 @@ class ViewController: NSViewController { } - From a025c0cc27b3fa4b8bfa2255f59eceb8447ad9b3 Mon Sep 17 00:00:00 2001 From: Jawwad Ahmad Date: Fri, 28 Apr 2017 10:00:27 +0500 Subject: [PATCH 0996/1679] [swiftlint] Fix rule: opening_brace warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration. --- .../BruteForceStringSearch.playground/Contents.swift | 2 +- Brute-Force String Search/BruteForceStringSearch.swift | 2 +- .../KaratsubaMultiplication.playground/Contents.swift | 6 +++--- .../Red-Black Tree 2.playground/Sources/RBTree.swift | 2 +- Rootish Array Stack/Tests/RootishArrayStackTests.swift | 2 +- Shell Sort/ShellSortExample.swift | 2 +- Skip-List/SkipList.swift | 2 +- .../Sources/Number.swift | 2 +- 8 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Brute-Force String Search/BruteForceStringSearch.playground/Contents.swift b/Brute-Force String Search/BruteForceStringSearch.playground/Contents.swift index 61064c698..00ac6da97 100644 --- a/Brute-Force String Search/BruteForceStringSearch.playground/Contents.swift +++ b/Brute-Force String Search/BruteForceStringSearch.playground/Contents.swift @@ -6,7 +6,7 @@ extension String { for i in self.characters.indices { var j = i var found = true - for p in pattern.characters.indices{ + for p in pattern.characters.indices { if j == self.characters.endIndex || self[j] != pattern[p] { found = false break diff --git a/Brute-Force String Search/BruteForceStringSearch.swift b/Brute-Force String Search/BruteForceStringSearch.swift index 03a2dff13..016292304 100644 --- a/Brute-Force String Search/BruteForceStringSearch.swift +++ b/Brute-Force String Search/BruteForceStringSearch.swift @@ -6,7 +6,7 @@ extension String { for i in self.characters.indices { var j = i var found = true - for p in pattern.characters.indices{ + for p in pattern.characters.indices { if j == self.characters.endIndex || self[j] != pattern[p] { found = false break diff --git a/Karatsuba Multiplication/KaratsubaMultiplication.playground/Contents.swift b/Karatsuba Multiplication/KaratsubaMultiplication.playground/Contents.swift index bde8fd9f9..3ac29301a 100644 --- a/Karatsuba Multiplication/KaratsubaMultiplication.playground/Contents.swift +++ b/Karatsuba Multiplication/KaratsubaMultiplication.playground/Contents.swift @@ -15,8 +15,8 @@ func ^^ (radix: Int, power: Int) -> Int { // Long Multiplication - O(n^2) func multiply(_ num1: Int, by num2: Int, base: Int = 10) -> Int { - let num1Array = String(num1).characters.reversed().map{ Int(String($0))! } - let num2Array = String(num2).characters.reversed().map{ Int(String($0))! } + let num1Array = String(num1).characters.reversed().map { Int(String($0))! } + let num2Array = String(num2).characters.reversed().map { Int(String($0))! } var product = Array(repeating: 0, count: num1Array.count + num2Array.count) @@ -30,7 +30,7 @@ func multiply(_ num1: Int, by num2: Int, base: Int = 10) -> Int { product[i + num2Array.count] += carry } - return Int(product.reversed().map{ String($0) }.reduce("", +))! + return Int(product.reversed().map { String($0) }.reduce("", +))! } // Karatsuba Multiplication - O(n^log2(3)) diff --git a/Red-Black Tree/Red-Black Tree 2.playground/Sources/RBTree.swift b/Red-Black Tree/Red-Black Tree 2.playground/Sources/RBTree.swift index b0f440809..0038494d3 100644 --- a/Red-Black Tree/Red-Black Tree 2.playground/Sources/RBTree.swift +++ b/Red-Black Tree/Red-Black Tree 2.playground/Sources/RBTree.swift @@ -22,7 +22,7 @@ public class RBTNode: CustomStringConvertible { // If the value is encapsulated by double pipes it is double black (This should not occur in a verified RBTree) if self.isRed { nodeValue = "(\(self.value!))" - } else if self.isBlack{ + } else if self.isBlack { nodeValue = "|\(self.value!)|" } else { nodeValue = "||\(self.value!)||" diff --git a/Rootish Array Stack/Tests/RootishArrayStackTests.swift b/Rootish Array Stack/Tests/RootishArrayStackTests.swift index 9ffc4ebb9..f0aaa8bca 100755 --- a/Rootish Array Stack/Tests/RootishArrayStackTests.swift +++ b/Rootish Array Stack/Tests/RootishArrayStackTests.swift @@ -1,7 +1,7 @@ import XCTest fileprivate extension RootishArrayStack { - func equal(toArray array: Array) -> Bool{ + func equal(toArray array: Array) -> Bool { for index in 0.. 0 else { continue } - while list[index - 1] > list[index] && index - 1 > 0 { + while list[index - 1] > list[index] && index - 1 > 0 { swap(&list[index - 1], &list[index]) index -= 1 } diff --git a/Skip-List/SkipList.swift b/Skip-List/SkipList.swift index 1418656f3..52de1412e 100644 --- a/Skip-List/SkipList.swift +++ b/Skip-List/SkipList.swift @@ -283,7 +283,7 @@ extension SkipList { extension SkipList { - public func get(key:Key) -> Payload?{ + public func get(key:Key) -> Payload? { return search(key: key) } } diff --git a/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/Number.swift b/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/Number.swift index 7da1eee60..69afe76e4 100644 --- a/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/Number.swift +++ b/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/Number.swift @@ -37,7 +37,7 @@ extension Array where Element: Number { public func dot(_ b: Array) -> Element { let a = self assert(a.count == b.count, "Can only take the dot product of arrays of the same length!") - let c = a.indices.map{ a[$0] * b[$0] } + let c = a.indices.map { a[$0] * b[$0] } return c.reduce(Element.zero, { $0 + $1 }) } } From 44adf5a8f6ac5e14ca74b761fbdd01083100ccf8 Mon Sep 17 00:00:00 2001 From: Jawwad Ahmad Date: Fri, 28 Apr 2017 10:01:33 +0500 Subject: [PATCH 0997/1679] [swiftlint] Fix rule: empty_parentheses_with_trailing_closure warning: Empty Parentheses with Trailing Closure Violation: When using trailing closures, empty parentheses should be avoided after the method call. --- All-Pairs Shortest Paths/APSP/APSP/FloydWarshall.swift | 2 +- Bloom Filter/BloomFilter.playground/Contents.swift | 4 ++-- Bloom Filter/BloomFilter.swift | 4 ++-- Graph/Graph/AdjacencyListGraph.swift | 2 +- Graph/Graph/AdjacencyMatrixGraph.swift | 2 +- .../SSSP/BellmanFord.swift | 4 ++-- Trie/Trie/TrieTests/TrieTests.swift | 8 ++++---- 7 files changed, 13 insertions(+), 13 deletions(-) diff --git a/All-Pairs Shortest Paths/APSP/APSP/FloydWarshall.swift b/All-Pairs Shortest Paths/APSP/APSP/FloydWarshall.swift index b1a870f2a..7bc78f326 100644 --- a/All-Pairs Shortest Paths/APSP/APSP/FloydWarshall.swift +++ b/All-Pairs Shortest Paths/APSP/APSP/FloydWarshall.swift @@ -175,7 +175,7 @@ public struct FloydWarshallResult: APSPResult where T: Hashable { public func path(fromVertex from: Vertex, toVertex to: Vertex, inGraph graph: AbstractGraph) -> [T]? { if let path = recursePathFrom(fromVertex: from, toVertex: to, path: [ to ], inGraph: graph) { - let pathValues = path.map() { vertex in + let pathValues = path.map { vertex in vertex.data } return pathValues diff --git a/Bloom Filter/BloomFilter.playground/Contents.swift b/Bloom Filter/BloomFilter.playground/Contents.swift index d5e7d2dc6..06022c9b3 100644 --- a/Bloom Filter/BloomFilter.playground/Contents.swift +++ b/Bloom Filter/BloomFilter.playground/Contents.swift @@ -10,7 +10,7 @@ public class BloomFilter { } private func computeHashes(_ value: T) -> [Int] { - return hashFunctions.map() { hashFunc in abs(hashFunc(value) % array.count) } + return hashFunctions.map { hashFunc in abs(hashFunc(value) % array.count) } } public func insert(_ element: T) { @@ -29,7 +29,7 @@ public class BloomFilter { let hashValues = computeHashes(value) // Map hashes to indices in the Bloom Filter - let results = hashValues.map() { hashValue in array[hashValue] } + let results = hashValues.map { hashValue in array[hashValue] } // All values must be 'true' for the query to return true diff --git a/Bloom Filter/BloomFilter.swift b/Bloom Filter/BloomFilter.swift index 03b5333f1..56c3be328 100644 --- a/Bloom Filter/BloomFilter.swift +++ b/Bloom Filter/BloomFilter.swift @@ -8,7 +8,7 @@ public class BloomFilter { } private func computeHashes(_ value: T) -> [Int] { - return hashFunctions.map() { hashFunc in abs(hashFunc(value) % array.count) } + return hashFunctions.map { hashFunc in abs(hashFunc(value) % array.count) } } public func insert(_ element: T) { @@ -27,7 +27,7 @@ public class BloomFilter { let hashValues = computeHashes(value) // Map hashes to indices in the Bloom Filter - let results = hashValues.map() { hashValue in array[hashValue] } + let results = hashValues.map { hashValue in array[hashValue] } // All values must be 'true' for the query to return true diff --git a/Graph/Graph/AdjacencyListGraph.swift b/Graph/Graph/AdjacencyListGraph.swift index edb754c97..3d86c78f7 100644 --- a/Graph/Graph/AdjacencyListGraph.swift +++ b/Graph/Graph/AdjacencyListGraph.swift @@ -64,7 +64,7 @@ open class AdjacencyListGraph: AbstractGraph where T: Equatable, T: Hashab open override func createVertex(_ data: T) -> Vertex { // check if the vertex already exists - let matchingVertices = vertices.filter() { vertex in + let matchingVertices = vertices.filter { vertex in return vertex.data == data } diff --git a/Graph/Graph/AdjacencyMatrixGraph.swift b/Graph/Graph/AdjacencyMatrixGraph.swift index 8f357bc8c..a9b43fb6d 100644 --- a/Graph/Graph/AdjacencyMatrixGraph.swift +++ b/Graph/Graph/AdjacencyMatrixGraph.swift @@ -46,7 +46,7 @@ open class AdjacencyMatrixGraph: AbstractGraph where T: Equatable, T: Hash // Performance: possibly O(n^2) because of the resizing of the matrix. open override func createVertex(_ data: T) -> Vertex { // check if the vertex already exists - let matchingVertices = vertices.filter() { vertex in + let matchingVertices = vertices.filter { vertex in return vertex.data == data } diff --git a/Single-Source Shortest Paths (Weighted)/SSSP/BellmanFord.swift b/Single-Source Shortest Paths (Weighted)/SSSP/BellmanFord.swift index 5b6670806..41be9759b 100644 --- a/Single-Source Shortest Paths (Weighted)/SSSP/BellmanFord.swift +++ b/Single-Source Shortest Paths (Weighted)/SSSP/BellmanFord.swift @@ -41,7 +41,7 @@ extension BellmanFord: SSSPAlgorithm { for _ in 0 ..< vertices.count - 1 { var weightsUpdated = false - edges.forEach() { edge in + edges.forEach { edge in let weight = edge.weight! let relaxedDistance = weights[edge.from.index] + weight let nextVertexIdx = edge.to.index @@ -116,7 +116,7 @@ extension BellmanFordResult: SSSPResult { return nil } - return path.map() { vertex in + return path.map { vertex in return vertex.data } } diff --git a/Trie/Trie/TrieTests/TrieTests.swift b/Trie/Trie/TrieTests/TrieTests.swift index 50a30a552..960b65791 100644 --- a/Trie/Trie/TrieTests/TrieTests.swift +++ b/Trie/Trie/TrieTests/TrieTests.swift @@ -101,7 +101,7 @@ class TrieTests: XCTestCase { /// Tests the performance of the insert method. func testInsertPerformance() { - self.measure() { + self.measure { let trie = Trie() for word in self.wordArray! { trie.insert(word: word) @@ -114,7 +114,7 @@ class TrieTests: XCTestCase { /// Tests the performance of the insert method when the words are already /// present. func testInsertAgainPerformance() { - self.measure() { + self.measure { for word in self.wordArray! { self.trie.insert(word: word) } @@ -123,7 +123,7 @@ class TrieTests: XCTestCase { /// Tests the performance of the contains method. func testContainsPerformance() { - self.measure() { + self.measure { for word in self.wordArray! { XCTAssertTrue(self.trie.contains(word: word)) } @@ -136,7 +136,7 @@ class TrieTests: XCTestCase { for word in self.wordArray! { self.trie.remove(word: word) } - self.measure() { + self.measure { self.insertWordsIntoTrie() for word in self.wordArray! { self.trie.remove(word: word) From 71c0e32fbc9794289199c3a8bbe0e1719a9b2ece Mon Sep 17 00:00:00 2001 From: Jawwad Ahmad Date: Fri, 28 Apr 2017 10:05:34 +0500 Subject: [PATCH 0998/1679] [swiftlint] Fix rule: colon (i.e. should be next to identifier) warning: Colon Violation: Colons should be next to the identifier when specifying a type and next to the key in dictionary literals. --- .../BucketSort.playground/Sources/BucketSort.swift | 2 +- Bucket Sort/BucketSort.swift | 2 +- Convex Hull/Convex Hull/View.swift | 2 +- Deque/Deque-Optimized.swift | 2 +- Linked List/LinkedList.playground/Contents.swift | 2 +- Linked List/LinkedList.swift | 2 +- .../Red-Black Tree 2.playground/Sources/RBTree.swift | 8 ++++---- Skip-List/SkipList.swift | 2 +- Topological Sort/Graph.swift | 4 ++-- .../Topological Sort.playground/Sources/Graph.swift | 4 ++-- .../Sources/TopologicalSort1.swift | 2 +- Topological Sort/TopologicalSort1.swift | 2 +- 12 files changed, 17 insertions(+), 17 deletions(-) diff --git a/Bucket Sort/BucketSort.playground/Sources/BucketSort.swift b/Bucket Sort/BucketSort.playground/Sources/BucketSort.swift index e510e51b4..08962c0e1 100644 --- a/Bucket Sort/BucketSort.playground/Sources/BucketSort.swift +++ b/Bucket Sort/BucketSort.playground/Sources/BucketSort.swift @@ -122,7 +122,7 @@ public struct InsertionSorter: Sorter { // MARK: Bucket ////////////////////////////////////// -public struct Bucket { +public struct Bucket { var elements: [T] let capacity: Int diff --git a/Bucket Sort/BucketSort.swift b/Bucket Sort/BucketSort.swift index ef72c67dc..ff36b372a 100644 --- a/Bucket Sort/BucketSort.swift +++ b/Bucket Sort/BucketSort.swift @@ -173,7 +173,7 @@ public struct InsertionSorter: Sorter { // MARK: Bucket ////////////////////////////////////// -public struct Bucket { +public struct Bucket { var elements: [T] let capacity: Int diff --git a/Convex Hull/Convex Hull/View.swift b/Convex Hull/Convex Hull/View.swift index 2d7157e6f..f9f9f6ef4 100644 --- a/Convex Hull/Convex Hull/View.swift +++ b/Convex Hull/Convex Hull/View.swift @@ -150,7 +150,7 @@ class View: UIView { let context = UIGraphicsGetCurrentContext() // Draw hull - let lineWidth:CGFloat = 2.0 + let lineWidth: CGFloat = 2.0 context!.setFillColor(UIColor.black.cgColor) context!.setLineWidth(lineWidth) diff --git a/Deque/Deque-Optimized.swift b/Deque/Deque-Optimized.swift index f565458c7..4eea01f1a 100644 --- a/Deque/Deque-Optimized.swift +++ b/Deque/Deque-Optimized.swift @@ -7,7 +7,7 @@ public struct Deque { private var array: [T?] private var head: Int private var capacity: Int - private let originalCapacity:Int + private let originalCapacity: Int public init(_ capacity: Int = 10) { self.capacity = max(capacity, 1) diff --git a/Linked List/LinkedList.playground/Contents.swift b/Linked List/LinkedList.playground/Contents.swift index 10677935a..08e14ef70 100644 --- a/Linked List/LinkedList.playground/Contents.swift +++ b/Linked List/LinkedList.playground/Contents.swift @@ -177,7 +177,7 @@ public final class LinkedList { if list.isEmpty { return } var (prev, next) = nodesBeforeAndAfter(index: index) var nodeToCopy = list.head - var newNode:Node? + var newNode: Node? while let node = nodeToCopy { newNode = Node(value: node.value) newNode?.previous = prev diff --git a/Linked List/LinkedList.swift b/Linked List/LinkedList.swift index a7ef9bf5e..783e650e8 100755 --- a/Linked List/LinkedList.swift +++ b/Linked List/LinkedList.swift @@ -129,7 +129,7 @@ public final class LinkedList { if list.isEmpty { return } var (prev, next) = nodesBeforeAndAfter(index: index) var nodeToCopy = list.head - var newNode:Node? + var newNode: Node? while let node = nodeToCopy { newNode = Node(value: node.value) newNode?.previous = prev diff --git a/Red-Black Tree/Red-Black Tree 2.playground/Sources/RBTree.swift b/Red-Black Tree/Red-Black Tree 2.playground/Sources/RBTree.swift index 0038494d3..42a68237e 100644 --- a/Red-Black Tree/Red-Black Tree 2.playground/Sources/RBTree.swift +++ b/Red-Black Tree/Red-Black Tree 2.playground/Sources/RBTree.swift @@ -7,9 +7,9 @@ private enum RBTColor { public class RBTNode: CustomStringConvertible { fileprivate var color: RBTColor = .red public var value: T! = nil - public var right: RBTNode! - public var left: RBTNode! - public var parent: RBTNode! + public var right: RBTNode! + public var left: RBTNode! + public var parent: RBTNode! public var description: String { if self.value == nil { @@ -435,7 +435,7 @@ public class RBTree: CustomStringConvertible { private func property3() { let bDepth = blackDepth(root: self.root) - let leaves:[RBTNode] = getLeaves(n: self.root) + let leaves: [RBTNode] = getLeaves(n: self.root) for leaflet in leaves { var leaf = leaflet diff --git a/Skip-List/SkipList.swift b/Skip-List/SkipList.swift index 52de1412e..14b5a4076 100644 --- a/Skip-List/SkipList.swift +++ b/Skip-List/SkipList.swift @@ -283,7 +283,7 @@ extension SkipList { extension SkipList { - public func get(key:Key) -> Payload? { + public func get(key: Key) -> Payload? { return search(key: key) } } diff --git a/Topological Sort/Graph.swift b/Topological Sort/Graph.swift index 1e1be6919..5032ba1d1 100644 --- a/Topological Sort/Graph.swift +++ b/Topological Sort/Graph.swift @@ -4,7 +4,7 @@ public class Graph: CustomStringConvertible { private(set) public var adjacencyLists: [Node : [Node]] public init() { - adjacencyLists = [Node : [Node]]() + adjacencyLists = [Node: [Node]]() } public func addNode(_ value: Node) -> Node { @@ -35,7 +35,7 @@ extension Graph { typealias InDegree = Int func calculateInDegreeOfNodes() -> [Node : InDegree] { - var inDegrees = [Node : InDegree]() + var inDegrees = [Node: InDegree]() for (node, _) in adjacencyLists { inDegrees[node] = 0 diff --git a/Topological Sort/Topological Sort.playground/Sources/Graph.swift b/Topological Sort/Topological Sort.playground/Sources/Graph.swift index 1e1be6919..5032ba1d1 100644 --- a/Topological Sort/Topological Sort.playground/Sources/Graph.swift +++ b/Topological Sort/Topological Sort.playground/Sources/Graph.swift @@ -4,7 +4,7 @@ public class Graph: CustomStringConvertible { private(set) public var adjacencyLists: [Node : [Node]] public init() { - adjacencyLists = [Node : [Node]]() + adjacencyLists = [Node: [Node]]() } public func addNode(_ value: Node) -> Node { @@ -35,7 +35,7 @@ extension Graph { typealias InDegree = Int func calculateInDegreeOfNodes() -> [Node : InDegree] { - var inDegrees = [Node : InDegree]() + var inDegrees = [Node: InDegree]() for (node, _) in adjacencyLists { inDegrees[node] = 0 diff --git a/Topological Sort/Topological Sort.playground/Sources/TopologicalSort1.swift b/Topological Sort/Topological Sort.playground/Sources/TopologicalSort1.swift index 0f9566f6a..4d3717fe6 100644 --- a/Topological Sort/Topological Sort.playground/Sources/TopologicalSort1.swift +++ b/Topological Sort/Topological Sort.playground/Sources/TopologicalSort1.swift @@ -23,7 +23,7 @@ extension Graph { return node }) - var visited = [Node : Bool]() + var visited = [Node: Bool]() for (node, _) in adjacencyLists { visited[node] = false } diff --git a/Topological Sort/TopologicalSort1.swift b/Topological Sort/TopologicalSort1.swift index 0f9566f6a..4d3717fe6 100644 --- a/Topological Sort/TopologicalSort1.swift +++ b/Topological Sort/TopologicalSort1.swift @@ -23,7 +23,7 @@ extension Graph { return node }) - var visited = [Node : Bool]() + var visited = [Node: Bool]() for (node, _) in adjacencyLists { visited[node] = false } From c4fdd035df77487756eee2389d18c89f9dc652cd Mon Sep 17 00:00:00 2001 From: TheIronBorn Date: Sat, 29 Apr 2017 00:52:39 -0700 Subject: [PATCH 0999/1679] switch removeFirst to dropFirst we don't need a mutable copy of `array` to alter it, instead we can just drop the first element --- Select Minimum Maximum/Maximum.swift | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Select Minimum Maximum/Maximum.swift b/Select Minimum Maximum/Maximum.swift index 991a0544e..c999504fb 100644 --- a/Select Minimum Maximum/Maximum.swift +++ b/Select Minimum Maximum/Maximum.swift @@ -3,13 +3,12 @@ */ func maximum(_ array: [T]) -> T? { - var array = array guard !array.isEmpty else { return nil } - var maximum = array.removeFirst() - for element in array { + var maximum = array.first! + for element in array.dropFirst() { maximum = element > maximum ? element : maximum } return maximum From 5e7fc5487f833fd96852d21d7f856c300956a62b Mon Sep 17 00:00:00 2001 From: TheIronBorn Date: Sat, 29 Apr 2017 00:56:51 -0700 Subject: [PATCH 1000/1679] switch removeFirst to dropFirst we don't need to alter a mutable copy of `array`, instead we can just drop the first element. --- Select Minimum Maximum/Minimum.swift | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Select Minimum Maximum/Minimum.swift b/Select Minimum Maximum/Minimum.swift index 90dfbd54b..88a562170 100644 --- a/Select Minimum Maximum/Minimum.swift +++ b/Select Minimum Maximum/Minimum.swift @@ -3,13 +3,12 @@ */ func minimum(_ array: [T]) -> T? { - var array = array guard !array.isEmpty else { return nil } - var minimum = array.removeFirst() - for element in array { + var minimum = array.first! + for element in array.dropFirst() { minimum = element < minimum ? element : minimum } return minimum From e15e1330417dcbe2222d2606a35dd5462eac6b2c Mon Sep 17 00:00:00 2001 From: TheIronBorn Date: Sat, 29 Apr 2017 18:14:37 -0700 Subject: [PATCH 1001/1679] switch from removeFirst to stride for pairing We don't need to alter a local copy of `array` to generate each pair, instead use stride(from:to:by). In my simple [tests](https://gist.github.com/TheIronBorn/cc0507b36fddad291aa34674eb52ad8f), this can be up to an order of magnitude faster. --- Select Minimum Maximum/MinimumMaximumPairs.swift | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/Select Minimum Maximum/MinimumMaximumPairs.swift b/Select Minimum Maximum/MinimumMaximumPairs.swift index b7deb570a..2c7b5bb5f 100644 --- a/Select Minimum Maximum/MinimumMaximumPairs.swift +++ b/Select Minimum Maximum/MinimumMaximumPairs.swift @@ -3,7 +3,6 @@ */ func minimumMaximum(_ array: [T]) -> (minimum: T, maximum: T)? { - var array = array guard !array.isEmpty else { return nil } @@ -11,13 +10,11 @@ func minimumMaximum(_ array: [T]) -> (minimum: T, maximum: T)? { var minimum = array.first! var maximum = array.first! + // if 'array' has an odd number of items, let 'minimum' or 'maximum' deal with the leftover let hasOddNumberOfItems = array.count % 2 != 0 - if hasOddNumberOfItems { - array.removeFirst() - } - - while !array.isEmpty { - let pair = (array.removeFirst(), array.removeFirst()) + let start = hasOddNumberOfItems ? 1 : 0 + for i in stride(from: start, to: array.count, by: 2) { + let pair = (array[i], array[i+1]) if pair.0 > pair.1 { if pair.0 > maximum { @@ -35,6 +32,6 @@ func minimumMaximum(_ array: [T]) -> (minimum: T, maximum: T)? { } } } - + return (minimum, maximum) } From b8d668d3883f79754aa83f5944a3e3d97e13d3a6 Mon Sep 17 00:00:00 2001 From: TheIronBorn Date: Sat, 29 Apr 2017 18:19:43 -0700 Subject: [PATCH 1002/1679] update to match source --- Select Minimum Maximum/README.markdown | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/Select Minimum Maximum/README.markdown b/Select Minimum Maximum/README.markdown index fa0f8fed8..3c29b5764 100644 --- a/Select Minimum Maximum/README.markdown +++ b/Select Minimum Maximum/README.markdown @@ -24,26 +24,24 @@ Here is a simple implementation in Swift: ```swift func minimum(_ array: [T]) -> T? { - var array = array guard !array.isEmpty else { return nil } - var minimum = array.removeFirst() - for element in array { + var minimum = array.first! + for element in array.dropFirst() { minimum = element < minimum ? element : minimum } return minimum } func maximum(_ array: [T]) -> T? { - var array = array guard !array.isEmpty else { return nil } - var maximum = array.removeFirst() - for element in array { + var maximum = array.first! + for element in array.dropFirst() { maximum = element > maximum ? element : maximum } return maximum @@ -99,7 +97,6 @@ Here is a simple implementation in Swift: ```swift func minimumMaximum(_ array: [T]) -> (minimum: T, maximum: T)? { - var array = array guard !array.isEmpty else { return nil } @@ -107,13 +104,12 @@ func minimumMaximum(_ array: [T]) -> (minimum: T, maximum: T)? { var minimum = array.first! var maximum = array.first! + // if 'array' has an odd number of items, let 'minimum' or 'maximum' deal with the leftover let hasOddNumberOfItems = array.count % 2 != 0 - if hasOddNumberOfItems { - array.removeFirst() - } + let start = hasOddNumberOfItems ? 1 : 0 + for i in stride(from: start, to: array.count, by: 2) { + let pair = (array[i], array[i+1]) - while !array.isEmpty { - let pair = (array.removeFirst(), array.removeFirst()) if pair.0 > pair.1 { if pair.0 > maximum { maximum = pair.0 From 5ddf933c48da612a9489c77b095496b0c80c1b66 Mon Sep 17 00:00:00 2001 From: TheIronBorn Date: Sat, 29 Apr 2017 18:21:35 -0700 Subject: [PATCH 1003/1679] update to match source --- .../Contents.swift | 33 ++++++++----------- 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/Select Minimum Maximum/SelectMinimumMaximum.playground/Contents.swift b/Select Minimum Maximum/SelectMinimumMaximum.playground/Contents.swift index 182060805..427ccdb9e 100644 --- a/Select Minimum Maximum/SelectMinimumMaximum.playground/Contents.swift +++ b/Select Minimum Maximum/SelectMinimumMaximum.playground/Contents.swift @@ -1,12 +1,11 @@ // Compare each item to find minimum func minimum(_ array: [T]) -> T? { - var array = array guard !array.isEmpty else { return nil } - - var minimum = array.removeFirst() - for element in array { + + var minimum = array.first! + for element in array.dropFirst() { minimum = element < minimum ? element : minimum } return minimum @@ -14,13 +13,12 @@ func minimum(_ array: [T]) -> T? { // Compare each item to find maximum func maximum(_ array: [T]) -> T? { - var array = array guard !array.isEmpty else { return nil } - - var maximum = array.removeFirst() - for element in array { + + var maximum = array.first! + for element in array.dropFirst() { maximum = element > maximum ? element : maximum } return maximum @@ -28,22 +26,19 @@ func maximum(_ array: [T]) -> T? { // Compare in pairs to find minimum and maximum func minimumMaximum(_ array: [T]) -> (minimum: T, maximum: T)? { - var array = array guard !array.isEmpty else { return nil } - + var minimum = array.first! var maximum = array.first! - + + // if 'array' has an odd number of items, let 'minimum' or 'maximum' deal with the leftover let hasOddNumberOfItems = array.count % 2 != 0 - if hasOddNumberOfItems { - array.removeFirst() - } - - while !array.isEmpty { - let pair = (array.removeFirst(), array.removeFirst()) - + let start = hasOddNumberOfItems ? 1 : 0 + for i in stride(from: start, to: array.count, by: 2) { + let pair = (array[i], array[i+1]) + if pair.0 > pair.1 { if pair.0 > maximum { maximum = pair.0 @@ -60,7 +55,7 @@ func minimumMaximum(_ array: [T]) -> (minimum: T, maximum: T)? { } } } - + return (minimum, maximum) } From 3f156498b0cb043f103eef22216f2e4e9df6edd6 Mon Sep 17 00:00:00 2001 From: Jawwad Ahmad Date: Mon, 1 May 2017 01:03:09 +0500 Subject: [PATCH 1004/1679] Fix alignment by adding an additional tab --- Tree/README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tree/README.markdown b/Tree/README.markdown index 440d9c9a4..566864a8f 100644 --- a/Tree/README.markdown +++ b/Tree/README.markdown @@ -153,7 +153,7 @@ tree.search("bubbly") // nil It's also possible to describe a tree using nothing more than an array. The indices in the array then create the links between the different nodes. For example, if we have: - 0 = beverage 5 = cocoa 9 = green + 0 = beverage 5 = cocoa 9 = green 1 = hot 6 = soda 10 = chai 2 = cold 7 = milk 11 = ginger ale 3 = tea 8 = black 12 = bitter lemon From 32457ce5aca5bcdee4acc1f8d6f6c0c6a075daba Mon Sep 17 00:00:00 2001 From: Jawwad Ahmad Date: Mon, 1 May 2017 02:03:34 +0500 Subject: [PATCH 1005/1679] Fix misindented return statement --- Trie/ReadMe.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Trie/ReadMe.md b/Trie/ReadMe.md index 7caa927a7..356f6887e 100644 --- a/Trie/ReadMe.md +++ b/Trie/ReadMe.md @@ -46,7 +46,7 @@ func contains(word: String) -> Bool { if currentIndex == characters.count && currentNode.isTerminating { return true } else { - return false + return false } } ``` From 09f2c8fb8564bd956beb1a067b6ad21255bad97c Mon Sep 17 00:00:00 2001 From: Jawwad Ahmad Date: Mon, 1 May 2017 05:25:13 +0500 Subject: [PATCH 1006/1679] [swiftlint] Fix rule: force_cast (Force casts should be avoided) --- Trie/Trie/TrieTests/TrieTests.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Trie/Trie/TrieTests/TrieTests.swift b/Trie/Trie/TrieTests/TrieTests.swift index 960b65791..b69c5666e 100644 --- a/Trie/Trie/TrieTests/TrieTests.swift +++ b/Trie/Trie/TrieTests/TrieTests.swift @@ -164,8 +164,8 @@ class TrieTests: XCTestCase { let fileName = "dictionary-archive" let filePath = resourcePath.appendingPathComponent(fileName) NSKeyedArchiver.archiveRootObject(trie, toFile: filePath) - let trieCopy = NSKeyedUnarchiver.unarchiveObject(withFile: filePath) as! Trie - XCTAssertEqual(trieCopy.count, trie.count) + let trieCopy = NSKeyedUnarchiver.unarchiveObject(withFile: filePath) as? Trie + XCTAssertEqual(trieCopy?.count, trie.count) } From b1319ce90d5288e20ee02b56390c61895d1d7765 Mon Sep 17 00:00:00 2001 From: Jawwad Ahmad Date: Thu, 4 May 2017 03:23:06 +0500 Subject: [PATCH 1007/1679] [swiftlint] Fix violation: unused_closure_parameter warning: Unused Closure Parameter Violation: Unused parameters in a closure should be replaced with _. --- B-Tree/Tests/Tests/BTreeTests.swift | 2 +- .../Topological Sort.playground/Sources/TopologicalSort1.swift | 2 +- .../Topological Sort.playground/Sources/TopologicalSort2.swift | 2 +- Topological Sort/TopologicalSort1.swift | 2 +- Topological Sort/TopologicalSort2.swift | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/B-Tree/Tests/Tests/BTreeTests.swift b/B-Tree/Tests/Tests/BTreeTests.swift index c8db17fa3..f2dac7511 100644 --- a/B-Tree/Tests/Tests/BTreeTests.swift +++ b/B-Tree/Tests/Tests/BTreeTests.swift @@ -31,7 +31,7 @@ class BTreeTests: XCTestCase { } func testInorderTraversalOfEmptyTree() { - bTree.traverseKeysInOrder { i in + bTree.traverseKeysInOrder { _ in XCTFail("Inorder travelsal fail.") } } diff --git a/Topological Sort/Topological Sort.playground/Sources/TopologicalSort1.swift b/Topological Sort/Topological Sort.playground/Sources/TopologicalSort1.swift index 4d3717fe6..2ad9b51a0 100644 --- a/Topological Sort/Topological Sort.playground/Sources/TopologicalSort1.swift +++ b/Topological Sort/Topological Sort.playground/Sources/TopologicalSort1.swift @@ -19,7 +19,7 @@ extension Graph { let startNodes = calculateInDegreeOfNodes().filter({ _, indegree in return indegree == 0 - }).map({ node, indegree in + }).map({ node, _ in return node }) diff --git a/Topological Sort/Topological Sort.playground/Sources/TopologicalSort2.swift b/Topological Sort/Topological Sort.playground/Sources/TopologicalSort2.swift index f4c1cdd6f..589801d33 100644 --- a/Topological Sort/Topological Sort.playground/Sources/TopologicalSort2.swift +++ b/Topological Sort/Topological Sort.playground/Sources/TopologicalSort2.swift @@ -8,7 +8,7 @@ extension Graph { // topologically sorted list. var leaders = nodes.filter({ _, indegree in return indegree == 0 - }).map({ node, indegree in + }).map({ node, _ in return node }) diff --git a/Topological Sort/TopologicalSort1.swift b/Topological Sort/TopologicalSort1.swift index 4d3717fe6..2ad9b51a0 100644 --- a/Topological Sort/TopologicalSort1.swift +++ b/Topological Sort/TopologicalSort1.swift @@ -19,7 +19,7 @@ extension Graph { let startNodes = calculateInDegreeOfNodes().filter({ _, indegree in return indegree == 0 - }).map({ node, indegree in + }).map({ node, _ in return node }) diff --git a/Topological Sort/TopologicalSort2.swift b/Topological Sort/TopologicalSort2.swift index f4c1cdd6f..589801d33 100644 --- a/Topological Sort/TopologicalSort2.swift +++ b/Topological Sort/TopologicalSort2.swift @@ -8,7 +8,7 @@ extension Graph { // topologically sorted list. var leaders = nodes.filter({ _, indegree in return indegree == 0 - }).map({ node, indegree in + }).map({ node, _ in return node }) From 9107542b7753210cef8eaf982373db377f6a8a62 Mon Sep 17 00:00:00 2001 From: Jawwad Ahmad Date: Thu, 4 May 2017 03:25:35 +0500 Subject: [PATCH 1008/1679] [swiftlint] Fix violation: redundant_discardable_let warning: Redundant Discardable Let Violation: Prefer `_ = foo()` over `let _ = foo()` when discarding a result from a function. --- Breadth-First Search/Tests/Graph.swift | 2 +- Palindromes/Test/Test/Test.swift | 6 +++--- Treap/TreapCollectionType.swift | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Breadth-First Search/Tests/Graph.swift b/Breadth-First Search/Tests/Graph.swift index 5e0837160..a8c34b3f6 100644 --- a/Breadth-First Search/Tests/Graph.swift +++ b/Breadth-First Search/Tests/Graph.swift @@ -86,7 +86,7 @@ public class Graph: CustomStringConvertible, Equatable { let duplicated = Graph() for node in nodes { - let _ = duplicated.addNode(node.label) + _ = duplicated.addNode(node.label) } for node in nodes { diff --git a/Palindromes/Test/Test/Test.swift b/Palindromes/Test/Test/Test.swift index e86a40cfb..1dd79ea97 100644 --- a/Palindromes/Test/Test/Test.swift +++ b/Palindromes/Test/Test/Test.swift @@ -29,9 +29,9 @@ class PalindromeTests: XCTestCase { // This is an example of a performance test case. self.measure { // Put the code you want to measure the time of here. - let _ = isPalindrome("abbcbba") - let _ = isPalindrome("asdkfaksjdfasjkdfhaslkjdfakjsdfhakljsdhflkjasdfhkasdjhfklajsdfhkljasdf") - let _ = isPalindrome("abababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababa") + _ = isPalindrome("abbcbba") + _ = isPalindrome("asdkfaksjdfasjkdfhaslkjdfakjsdfhakljsdhflkjasdfhkasdjhfklajsdfhkljasdf") + _ = isPalindrome("abababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababa") } } diff --git a/Treap/TreapCollectionType.swift b/Treap/TreapCollectionType.swift index de40464d1..9f7f81905 100644 --- a/Treap/TreapCollectionType.swift +++ b/Treap/TreapCollectionType.swift @@ -50,7 +50,7 @@ extension Treap: MutableCollection { mutating set { guard let value = newValue else { - let _ = try? self.delete(key: key) + _ = try? self.delete(key: key) return } From c67a277487e3611ad51b0c88855540d3f56f58bb Mon Sep 17 00:00:00 2001 From: Jawwad Ahmad Date: Thu, 4 May 2017 03:34:24 +0500 Subject: [PATCH 1009/1679] [swiftlint] Fix violation: operator_whitespace warning: Operator Function Whitespace Violation: Operators should be surrounded by a single whitespace when defining them. Apple has also used spacing in The Swift Programming Language book https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/AdvancedOperators.html#//apple_ref/doc/uid/TP40014097-CH27-ID42 --- QuadTree/Tests/Tests/Tests.swift | 2 +- .../Sources/Matrix.swift | 2 +- .../Sources/Number.swift | 6 +++--- Treap/TreapCollectionType.swift | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/QuadTree/Tests/Tests/Tests.swift b/QuadTree/Tests/Tests/Tests.swift index b7bcda4e6..b408c4f7e 100644 --- a/QuadTree/Tests/Tests/Tests.swift +++ b/QuadTree/Tests/Tests/Tests.swift @@ -12,7 +12,7 @@ extension Point: Equatable { } -public func ==(lhs: Point, rhs: Point) -> Bool { +public func == (lhs: Point, rhs: Point) -> Bool { return lhs.x == rhs.x && lhs.y == rhs.y } diff --git a/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/Matrix.swift b/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/Matrix.swift index c13b3eeee..ccfa58b09 100644 --- a/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/Matrix.swift +++ b/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/Matrix.swift @@ -19,7 +19,7 @@ public struct Matrix { public struct Size: Equatable { let rows: Int, columns: Int - public static func ==(lhs: Size, rhs: Size) -> Bool { + public static func == (lhs: Size, rhs: Size) -> Bool { return lhs.columns == rhs.columns && lhs.rows == rhs.rows } } diff --git a/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/Number.swift b/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/Number.swift index 69afe76e4..d53ef75bd 100644 --- a/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/Number.swift +++ b/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/Number.swift @@ -13,12 +13,12 @@ public protocol Number: Multipliable, Addable { } public protocol Addable { - static func +(lhs: Self, rhs: Self) -> Self - static func -(lhs: Self, rhs: Self) -> Self + static func + (lhs: Self, rhs: Self) -> Self + static func - (lhs: Self, rhs: Self) -> Self } public protocol Multipliable { - static func *(lhs: Self, rhs: Self) -> Self + static func * (lhs: Self, rhs: Self) -> Self } extension Int: Number { diff --git a/Treap/TreapCollectionType.swift b/Treap/TreapCollectionType.swift index 9f7f81905..7292c5f0a 100644 --- a/Treap/TreapCollectionType.swift +++ b/Treap/TreapCollectionType.swift @@ -85,7 +85,7 @@ extension Treap: MutableCollection { public struct TreapIndex: Comparable { - public static func <(lhs: TreapIndex, rhs: TreapIndex) -> Bool { + public static func < (lhs: TreapIndex, rhs: TreapIndex) -> Bool { return lhs.keyIndex < rhs.keyIndex } From 18c7b435cec0eafb657f28f7c80345d8a7aa513a Mon Sep 17 00:00:00 2001 From: Jawwad Ahmad Date: Thu, 4 May 2017 03:41:07 +0500 Subject: [PATCH 1010/1679] [swiftlint] Fix violation: Colons should be next to the identifier warning: Colon Violation: Colons should be next to the identifier when specifying a type and next to the key in dictionary literals. --- Bucket Sort/BucketSort.swift | 4 ++-- Skip-List/SkipList.swift | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Bucket Sort/BucketSort.swift b/Bucket Sort/BucketSort.swift index ff36b372a..5845819f2 100644 --- a/Bucket Sort/BucketSort.swift +++ b/Bucket Sort/BucketSort.swift @@ -23,7 +23,7 @@ import Foundation // FIXME: comparison operators with optionals were removed from the Swift Standard Libary. // Consider refactoring the code to use the non-optional operators. -fileprivate func < (lhs: T?, rhs: T?) -> Bool { +fileprivate func < (lhs: T?, rhs: T?) -> Bool { switch (lhs, rhs) { case let (l?, r?): return l < r @@ -36,7 +36,7 @@ fileprivate func < (lhs: T?, rhs: T?) -> Bool { // FIXME: comparison operators with optionals were removed from the Swift Standard Libary. // Consider refactoring the code to use the non-optional operators. -fileprivate func >= (lhs: T?, rhs: T?) -> Bool { +fileprivate func >= (lhs: T?, rhs: T?) -> Bool { switch (lhs, rhs) { case let (l?, r?): return l >= r diff --git a/Skip-List/SkipList.swift b/Skip-List/SkipList.swift index 14b5a4076..e844f9959 100644 --- a/Skip-List/SkipList.swift +++ b/Skip-List/SkipList.swift @@ -71,10 +71,10 @@ private func coinFlip() -> Bool { public class DataNode { public typealias Node = DataNode - var data : Payload? - fileprivate var key : Key? - var next : Node? - var down : Node? + var data: Payload? + fileprivate var key: Key? + var next: Node? + var down: Node? public init(key: Key, data: Payload) { self.key = key @@ -102,8 +102,8 @@ open class SkipList { extension SkipList { func findNode(key: Key) -> Node? { - var currentNode : Node? = head - var isFound : Bool = false + var currentNode: Node? = head + var isFound: Bool = false while !isFound { if let node = currentNode { From e3a4494138ca4776aab23bed0428b3e4063395ca Mon Sep 17 00:00:00 2001 From: Jawwad Ahmad Date: Thu, 4 May 2017 03:47:57 +0500 Subject: [PATCH 1011/1679] [swiftlint] Fix violation: Computed properties should avoid using get Rule: implicit_getter warning: Implicit Getter Violation: Computed read-only properties should avoid using the get keyword. --- Graph/Graph/AdjacencyListGraph.swift | 58 ++++++++++++-------------- Graph/Graph/AdjacencyMatrixGraph.swift | 44 +++++++++---------- Graph/Graph/Edge.swift | 19 ++++----- Graph/Graph/Graph.swift | 12 ++---- Graph/Graph/Vertex.swift | 8 +--- Treap/Treap.swift | 31 ++++++-------- Treap/TreapMergeSplit.swift | 4 +- 7 files changed, 71 insertions(+), 105 deletions(-) diff --git a/Graph/Graph/AdjacencyListGraph.swift b/Graph/Graph/AdjacencyListGraph.swift index 3d86c78f7..57fd75fed 100644 --- a/Graph/Graph/AdjacencyListGraph.swift +++ b/Graph/Graph/AdjacencyListGraph.swift @@ -37,29 +37,25 @@ open class AdjacencyListGraph: AbstractGraph where T: Equatable, T: Hashab } open override var vertices: [Vertex] { - get { - var vertices = [Vertex]() - for edgeList in adjacencyList { - vertices.append(edgeList.vertex) - } - return vertices + var vertices = [Vertex]() + for edgeList in adjacencyList { + vertices.append(edgeList.vertex) } + return vertices } open override var edges: [Edge] { - get { - var allEdges = Set>() - for edgeList in adjacencyList { - guard let edges = edgeList.edges else { - continue - } + var allEdges = Set>() + for edgeList in adjacencyList { + guard let edges = edgeList.edges else { + continue + } - for edge in edges { - allEdges.insert(edge) - } + for edge in edges { + allEdges.insert(edge) } - return Array(allEdges) } + return Array(allEdges) } open override func createVertex(_ data: T) -> Vertex { @@ -114,27 +110,25 @@ open class AdjacencyListGraph: AbstractGraph where T: Equatable, T: Hashab } open override var description: String { - get { - var rows = [String]() - for edgeList in adjacencyList { + var rows = [String]() + for edgeList in adjacencyList { - guard let edges = edgeList.edges else { - continue - } + guard let edges = edgeList.edges else { + continue + } - var row = [String]() - for edge in edges { - var value = "\(edge.to.data)" - if edge.weight != nil { - value = "(\(value): \(edge.weight!))" - } - row.append(value) + var row = [String]() + for edge in edges { + var value = "\(edge.to.data)" + if edge.weight != nil { + value = "(\(value): \(edge.weight!))" } - - rows.append("\(edgeList.vertex.data) -> [\(row.joined(separator: ", "))]") + row.append(value) } - return rows.joined(separator: "\n") + rows.append("\(edgeList.vertex.data) -> [\(row.joined(separator: ", "))]") } + + return rows.joined(separator: "\n") } } diff --git a/Graph/Graph/AdjacencyMatrixGraph.swift b/Graph/Graph/AdjacencyMatrixGraph.swift index a9b43fb6d..1b12790d8 100644 --- a/Graph/Graph/AdjacencyMatrixGraph.swift +++ b/Graph/Graph/AdjacencyMatrixGraph.swift @@ -23,23 +23,19 @@ open class AdjacencyMatrixGraph: AbstractGraph where T: Equatable, T: Hash } open override var vertices: [Vertex] { - get { - return _vertices - } + return _vertices } open override var edges: [Edge] { - get { - var edges = [Edge]() - for row in 0 ..< adjacencyMatrix.count { - for column in 0 ..< adjacencyMatrix.count { - if let weight = adjacencyMatrix[row][column] { - edges.append(Edge(from: vertices[row], to: vertices[column], weight: weight)) - } + var edges = [Edge]() + for row in 0 ..< adjacencyMatrix.count { + for column in 0 ..< adjacencyMatrix.count { + if let weight = adjacencyMatrix[row][column] { + edges.append(Edge(from: vertices[row], to: vertices[column], weight: weight)) } } - return edges } + return edges } // Adds a new vertex to the matrix. @@ -96,23 +92,21 @@ open class AdjacencyMatrixGraph: AbstractGraph where T: Equatable, T: Hash } open override var description: String { - get { - var grid = [String]() - let n = self.adjacencyMatrix.count - for i in 0..: Equatable where T: Equatable, T: Hashable { extension Edge: CustomStringConvertible { public var description: String { - get { - guard let unwrappedWeight = weight else { - return "\(from.description) -> \(to.description)" - } - return "\(from.description) -(\(unwrappedWeight))-> \(to.description)" + guard let unwrappedWeight = weight else { + return "\(from.description) -> \(to.description)" } + return "\(from.description) -(\(unwrappedWeight))-> \(to.description)" } } @@ -32,15 +30,12 @@ extension Edge: CustomStringConvertible { extension Edge: Hashable { public var hashValue: Int { - get { - var string = "\(from.description)\(to.description)" - if weight != nil { - string.append("\(weight!)") - } - return string.hashValue + var string = "\(from.description)\(to.description)" + if weight != nil { + string.append("\(weight!)") } + return string.hashValue } - } public func == (lhs: Edge, rhs: Edge) -> Bool { diff --git a/Graph/Graph/Graph.swift b/Graph/Graph/Graph.swift index 2ad91608b..13d6802b9 100644 --- a/Graph/Graph/Graph.swift +++ b/Graph/Graph/Graph.swift @@ -21,21 +21,15 @@ open class AbstractGraph: CustomStringConvertible where T: Equatable, T: Hash } open var description: String { - get { - fatalError("abstract property accessed") - } + fatalError("abstract property accessed") } open var vertices: [Vertex] { - get { - fatalError("abstract property accessed") - } + fatalError("abstract property accessed") } open var edges: [Edge] { - get { - fatalError("abstract property accessed") - } + fatalError("abstract property accessed") } // Adds a new vertex to the matrix. diff --git a/Graph/Graph/Vertex.swift b/Graph/Graph/Vertex.swift index 43cabcd1f..42a7dad7b 100644 --- a/Graph/Graph/Vertex.swift +++ b/Graph/Graph/Vertex.swift @@ -17,9 +17,7 @@ public struct Vertex: Equatable where T: Equatable, T: Hashable { extension Vertex: CustomStringConvertible { public var description: String { - get { - return "\(index): \(data)" - } + return "\(index): \(data)" } } @@ -27,9 +25,7 @@ extension Vertex: CustomStringConvertible { extension Vertex: Hashable { public var hashValue: Int { - get { - return "\(data)\(index)".hashValue - } + return "\(data)\(index)".hashValue } } diff --git a/Treap/Treap.swift b/Treap/Treap.swift index 478f248df..6e80abfb2 100644 --- a/Treap/Treap.swift +++ b/Treap/Treap.swift @@ -63,27 +63,22 @@ public indirect enum Treap { } public var depth: Int { - get { - switch self { - case .empty: - return 0 - case let .node(_, _, _, left, .empty): - return 1 + left.depth - case let .node(_, _, _, .empty, right): - return 1 + right.depth - case let .node(_, _, _, left, right): - let leftDepth = left.depth - let rightDepth = right.depth - return 1 + leftDepth > rightDepth ? leftDepth : rightDepth - } - + switch self { + case .empty: + return 0 + case let .node(_, _, _, left, .empty): + return 1 + left.depth + case let .node(_, _, _, .empty, right): + return 1 + right.depth + case let .node(_, _, _, left, right): + let leftDepth = left.depth + let rightDepth = right.depth + return 1 + leftDepth > rightDepth ? leftDepth : rightDepth } } - + public var count: Int { - get { - return Treap.countHelper(self) - } + return Treap.countHelper(self) } fileprivate static func countHelper(_ treap: Treap) -> Int { diff --git a/Treap/TreapMergeSplit.swift b/Treap/TreapMergeSplit.swift index 660bd4932..34cfec3d2 100644 --- a/Treap/TreapMergeSplit.swift +++ b/Treap/TreapMergeSplit.swift @@ -94,9 +94,7 @@ internal func merge(_ left: Treap, right extension Treap: CustomStringConvertible { public var description: String { - get { - return Treap.descHelper(self, indent: 0) - } + return Treap.descHelper(self, indent: 0) } fileprivate static func descHelper(_ treap: Treap, indent: Int) -> String { From 9af41f20ed8318739bd4f1d582a6789fe650e9b5 Mon Sep 17 00:00:00 2001 From: Jawwad Ahmad Date: Thu, 4 May 2017 03:49:49 +0500 Subject: [PATCH 1012/1679] [swiftlint] Fix violation: trailing_whitespace --- Array2D/Array2D.playground/Contents.swift | 4 +- Array2D/Array2D.swift | 4 +- B-Tree/BTree.playground/Sources/BTree.swift | 108 +++++++------- B-Tree/BTree.swift | 108 +++++++------- B-Tree/Tests/Tests/BTreeNodeTests.swift | 18 +-- B-Tree/Tests/Tests/BTreeTests.swift | 112 +++++++------- .../Contents.swift | 2 +- .../Sources/Comb Sort.swift | 4 +- Comb Sort/Comb Sort.swift | 4 +- Comb Sort/Tests/CombSortTests.swift | 2 +- Convex Hull/Convex Hull/AppDelegate.swift | 8 +- Convex Hull/Convex Hull/View.swift | 80 +++++----- .../FixedSizeArray.playground/Contents.swift | 10 +- Graph/Graph.playground/Contents.swift | 2 +- .../HashSet.playground/Sources/HashSet.swift | 16 +- .../Sources/HashTable.swift | 28 ++-- .../Contents.swift | 10 +- Heap/Heap.swift | 4 +- Heap/Tests/HeapTests.swift | 4 +- Huffman Coding/Huffman.swift | 34 ++--- Huffman Coding/NSData+Bits.swift | 8 +- .../Contents.swift | 16 +- .../KaratsubaMultiplication.swift | 12 +- Knuth-Morris-Pratt/KnuthMorrisPratt.swift | 26 ++-- .../LinkedList.playground/Contents.swift | 62 ++++---- Linked List/LinkedList.swift | 62 ++++---- Linked List/Tests/LinkedListTests.swift | 18 +-- .../Sources/MRPrimality.swift | 28 ++-- Miller-Rabin Primality Test/MRPrimality.swift | 28 ++-- .../Contents.swift | 8 +- .../OrderedArray.playground/Contents.swift | 2 +- .../Palindromes.playground/Contents.swift | 8 +- Palindromes/Palindromes.swift | 8 +- Palindromes/Test/Palindromes.swift | 8 +- Palindromes/Test/Test/Test.swift | 18 +-- .../Sources/QuadTree.swift | 88 +++++------ QuadTree/Tests/Tests/Tests.swift | 34 ++--- .../Sources/radixSort.swift | 18 +-- Radix Sort/RadixSortExample.swift | 12 +- Radix Sort/radixSort.swift | 18 +-- .../Contents.swift | 2 +- .../Sources/RBTree.swift | 138 +++++++++--------- .../RLE.playground/Contents.swift | 14 +- .../RLE.playground/Sources/RLE.swift | 12 +- .../SegmentTree.playground/Contents.swift | 18 +-- Segment Tree/SegmentTree.swift | 16 +- .../MinimumMaximumPairs.swift | 2 +- .../Contents.swift | 14 +- Shell Sort/ShellSortExample.swift | 10 +- Shortest Path (Unweighted)/Tests/Graph.swift | 32 ++-- .../ShuntingYard.playground/Contents.swift | 52 +++---- .../Sources/Stack.swift | 14 +- Shunting Yard/ShuntingYard.swift | 52 +++---- Skip-List/SkipList.swift | 84 +++++------ .../Sources/Matrix.swift | 88 +++++------ .../TST.playground/Sources/Utils.swift | 8 +- .../Tests/TernarySearchTreeTests.swift | 18 +-- Ternary Search Tree/Utils.swift | 8 +- .../Sources/ThreadedBinaryTree.swift | 52 +++---- Treap/Treap.swift | 18 +-- Treap/Treap/TreapTests/TreapTests.swift | 12 +- Treap/TreapCollectionType.swift | 34 ++--- Treap/TreapMergeSplit.swift | 14 +- Trie/Trie/Trie/Trie.swift | 16 +- Trie/Trie/TrieUITests/TrieUITests.swift | 12 +- Z-Algorithm/ZAlgorithm.swift | 22 +-- .../ZetaAlgorithm.playground/Contents.swift | 34 ++--- Z-Algorithm/ZetaAlgorithm.swift | 12 +- 68 files changed, 926 insertions(+), 926 deletions(-) diff --git a/Array2D/Array2D.playground/Contents.swift b/Array2D/Array2D.playground/Contents.swift index d088c99af..1a6a439bd 100644 --- a/Array2D/Array2D.playground/Contents.swift +++ b/Array2D/Array2D.playground/Contents.swift @@ -7,13 +7,13 @@ public struct Array2D { public let columns: Int public let rows: Int fileprivate var array: [T] - + public init(columns: Int, rows: Int, initialValue: T) { self.columns = columns self.rows = rows array = .init(repeating: initialValue, count: rows*columns) } - + public subscript(column: Int, row: Int) -> T { get { precondition(column < columns, "Column \(column) Index is out of range. Array(columns: \(columns), rows:\(rows))") diff --git a/Array2D/Array2D.swift b/Array2D/Array2D.swift index df4822916..caff8373c 100644 --- a/Array2D/Array2D.swift +++ b/Array2D/Array2D.swift @@ -7,13 +7,13 @@ public struct Array2D { public let columns: Int public let rows: Int fileprivate var array: [T] - + public init(columns: Int, rows: Int, initialValue: T) { self.columns = columns self.rows = rows array = .init(repeating: initialValue, count: rows*columns) } - + public subscript(column: Int, row: Int) -> T { get { precondition(column < columns, "Column \(column) Index is out of range. Array(columns: \(columns), rows:\(rows))") diff --git a/B-Tree/BTree.playground/Sources/BTree.swift b/B-Tree/BTree.playground/Sources/BTree.swift index 52cda4e43..2693eb308 100644 --- a/B-Tree/BTree.playground/Sources/BTree.swift +++ b/B-Tree/BTree.playground/Sources/BTree.swift @@ -33,23 +33,23 @@ class BTreeNode { * The tree that owns the node. */ unowned var owner: BTree - + fileprivate var keys = [Key]() fileprivate var values = [Value]() var children: [BTreeNode]? - + var isLeaf: Bool { return children == nil } - + var numberOfKeys: Int { return keys.count } - + init(owner: BTree) { self.owner = owner } - + convenience init(owner: BTree, keys: [Key], values: [Value], children: [BTreeNode]? = nil) { self.init(owner: owner) @@ -62,7 +62,7 @@ class BTreeNode { // MARK: BTreeNode extesnion: Searching extension BTreeNode { - + /** * Returns the value for a given `key`, returns nil if the `key` is not found. * @@ -71,11 +71,11 @@ extension BTreeNode { */ func value(for key: Key) -> Value? { var index = keys.startIndex - + while (index + 1) < keys.endIndex && keys[index] < key { index = (index + 1) } - + if key == keys[index] { return values[index] } else if key < keys[index] { @@ -89,7 +89,7 @@ extension BTreeNode { // MARK: BTreeNode extension: Travelsals extension BTreeNode { - + /** * Traverses the keys in order, executes `process` for every key. * @@ -101,7 +101,7 @@ extension BTreeNode { children?[i].traverseKeysInOrder(process) process(keys[i]) } - + children?.last?.traverseKeysInOrder(process) } } @@ -109,7 +109,7 @@ extension BTreeNode { // MARK: BTreeNode extension: Insertion extension BTreeNode { - + /** * Inserts `value` for `key` to the node, or to one if its descendants. * @@ -119,16 +119,16 @@ extension BTreeNode { */ func insert(_ value: Value, for key: Key) { var index = keys.startIndex - + while index < keys.endIndex && keys[index] < key { index = (index + 1) } - + if index < keys.endIndex && keys[index] == key { values[index] = value return } - + if isLeaf { keys.insert(key, at: index) values.insert(value, at: index) @@ -140,7 +140,7 @@ extension BTreeNode { } } } - + /** * Splits `child` at `index`. * The key-value pair at `index` gets moved up to the parent node, @@ -156,7 +156,7 @@ extension BTreeNode { values.insert(child.values[middleIndex], at: index) child.keys.remove(at: middleIndex) child.values.remove(at: middleIndex) - + let rightSibling = BTreeNode( owner: owner, keys: Array(child.keys[child.keys.indices.suffix(from: middleIndex)]), @@ -164,9 +164,9 @@ extension BTreeNode { ) child.keys.removeSubrange(child.keys.indices.suffix(from: middleIndex)) child.values.removeSubrange(child.values.indices.suffix(from: middleIndex)) - + children!.insert(rightSibling, at: (index + 1)) - + if child.children != nil { rightSibling.children = Array( child.children![child.children!.indices.suffix(from: (middleIndex + 1))] @@ -198,7 +198,7 @@ extension BTreeNode { return children!.last!.inorderPredecessor } } - + /** * Removes `key` and the value associated with it from the node * or one of its descendants. @@ -208,11 +208,11 @@ extension BTreeNode { */ func remove(_ key: Key) { var index = keys.startIndex - + while (index + 1) < keys.endIndex && keys[index] < key { index = (index + 1) } - + if keys[index] == key { if isLeaf { keys.remove(at: index) @@ -229,7 +229,7 @@ extension BTreeNode { } } else if key < keys[index] { // We should go to left child... - + if let leftChild = children?[index] { leftChild.remove(key) if leftChild.numberOfKeys < owner.order { @@ -240,7 +240,7 @@ extension BTreeNode { } } else { // We should go to right child... - + if let rightChild = children?[(index + 1)] { rightChild.remove(key) if rightChild.numberOfKeys < owner.order { @@ -251,7 +251,7 @@ extension BTreeNode { } } } - + /** * Fixes `childWithTooFewKeys` by either moving a key to it from * one of its neighbouring nodes, or by merging. @@ -264,7 +264,7 @@ extension BTreeNode { * - index: the index of the child to be fixed in the current node */ private func fix(childWithTooFewKeys child: BTreeNode, atIndex index: Int) { - + if (index - 1) >= 0 && children![(index - 1)].numberOfKeys > owner.order { move(keyAtIndex: (index - 1), to: child, from: children![(index - 1)], at: .left) } else if (index + 1) < children!.count && children![(index + 1)].numberOfKeys > owner.order { @@ -275,7 +275,7 @@ extension BTreeNode { merge(child: child, atIndex: index, to: .right) } } - + /** * Moves the key at the specified `index` from `node` to * the `targetNode` at `position` @@ -301,7 +301,7 @@ extension BTreeNode { at: targetNode.children!.startIndex) node.children!.removeLast() } - + case .right: targetNode.keys.insert(keys[index], at: targetNode.keys.endIndex) targetNode.values.insert(values[index], at: targetNode.values.endIndex) @@ -316,7 +316,7 @@ extension BTreeNode { } } } - + /** * Merges `child` at `position` to the node at the `position`. * @@ -329,33 +329,33 @@ extension BTreeNode { switch position { case .left: // We can merge to the left sibling - + children![(index - 1)].keys = children![(index - 1)].keys + [keys[(index - 1)]] + child.keys - + children![(index - 1)].values = children![(index - 1)].values + [values[(index - 1)]] + child.values - + keys.remove(at: (index - 1)) values.remove(at: (index - 1)) - + if !child.isLeaf { children![(index - 1)].children = children![(index - 1)].children! + child.children! } - + case .right: // We should merge to the right sibling - + children![(index + 1)].keys = child.keys + [keys[index]] + children![(index + 1)].keys - + children![(index + 1)].values = child.values + [values[index]] + children![(index + 1)].values - + keys.remove(at: index) values.remove(at: index) - + if !child.isLeaf { children![(index + 1)].children = child.children! + children![(index + 1)].children! @@ -374,18 +374,18 @@ extension BTreeNode { */ var inorderArrayFromKeys: [Key] { var array = [Key] () - + for i in 0.. { * except the root node which is allowed to contain less keys than the value of order. */ public let order: Int - + /** * The root node of the tree */ var rootNode: BTreeNode! - + fileprivate(set) public var numberOfKeys = 0 - + /** * Designated initializer for the tree * @@ -484,7 +484,7 @@ extension BTree { guard rootNode.numberOfKeys > 0 else { return nil } - + return rootNode.value(for: key) } } @@ -501,12 +501,12 @@ extension BTree { */ public func insert(_ value: Value, for key: Key) { rootNode.insert(value, for: key) - + if rootNode.numberOfKeys > order * 2 { splitRoot() } } - + /** * Splits the root node of the tree. * @@ -515,7 +515,7 @@ extension BTree { */ private func splitRoot() { let middleIndexOfOldRoot = rootNode.numberOfKeys / 2 - + let newRoot = BTreeNode( owner: self, keys: [rootNode.keys[middleIndexOfOldRoot]], @@ -524,7 +524,7 @@ extension BTree { ) rootNode.keys.remove(at: middleIndexOfOldRoot) rootNode.values.remove(at: middleIndexOfOldRoot) - + let newRightChild = BTreeNode( owner: self, keys: Array(rootNode.keys[rootNode.keys.indices.suffix(from: middleIndexOfOldRoot)]), @@ -532,7 +532,7 @@ extension BTree { ) rootNode.keys.removeSubrange(rootNode.keys.indices.suffix(from: middleIndexOfOldRoot)) rootNode.values.removeSubrange(rootNode.values.indices.suffix(from: middleIndexOfOldRoot)) - + if rootNode.children != nil { newRightChild.children = Array( rootNode.children![rootNode.children!.indices.suffix(from: (middleIndexOfOldRoot + 1))] @@ -541,7 +541,7 @@ extension BTree { rootNode.children!.indices.suffix(from: (middleIndexOfOldRoot + 1)) ) } - + newRoot.children!.append(newRightChild) rootNode = newRoot } @@ -560,9 +560,9 @@ extension BTree { guard rootNode.numberOfKeys > 0 else { return } - + rootNode.remove(key) - + if rootNode.numberOfKeys == 0 && !rootNode.isLeaf { rootNode = rootNode.children!.first! } diff --git a/B-Tree/BTree.swift b/B-Tree/BTree.swift index 52cda4e43..2693eb308 100644 --- a/B-Tree/BTree.swift +++ b/B-Tree/BTree.swift @@ -33,23 +33,23 @@ class BTreeNode { * The tree that owns the node. */ unowned var owner: BTree - + fileprivate var keys = [Key]() fileprivate var values = [Value]() var children: [BTreeNode]? - + var isLeaf: Bool { return children == nil } - + var numberOfKeys: Int { return keys.count } - + init(owner: BTree) { self.owner = owner } - + convenience init(owner: BTree, keys: [Key], values: [Value], children: [BTreeNode]? = nil) { self.init(owner: owner) @@ -62,7 +62,7 @@ class BTreeNode { // MARK: BTreeNode extesnion: Searching extension BTreeNode { - + /** * Returns the value for a given `key`, returns nil if the `key` is not found. * @@ -71,11 +71,11 @@ extension BTreeNode { */ func value(for key: Key) -> Value? { var index = keys.startIndex - + while (index + 1) < keys.endIndex && keys[index] < key { index = (index + 1) } - + if key == keys[index] { return values[index] } else if key < keys[index] { @@ -89,7 +89,7 @@ extension BTreeNode { // MARK: BTreeNode extension: Travelsals extension BTreeNode { - + /** * Traverses the keys in order, executes `process` for every key. * @@ -101,7 +101,7 @@ extension BTreeNode { children?[i].traverseKeysInOrder(process) process(keys[i]) } - + children?.last?.traverseKeysInOrder(process) } } @@ -109,7 +109,7 @@ extension BTreeNode { // MARK: BTreeNode extension: Insertion extension BTreeNode { - + /** * Inserts `value` for `key` to the node, or to one if its descendants. * @@ -119,16 +119,16 @@ extension BTreeNode { */ func insert(_ value: Value, for key: Key) { var index = keys.startIndex - + while index < keys.endIndex && keys[index] < key { index = (index + 1) } - + if index < keys.endIndex && keys[index] == key { values[index] = value return } - + if isLeaf { keys.insert(key, at: index) values.insert(value, at: index) @@ -140,7 +140,7 @@ extension BTreeNode { } } } - + /** * Splits `child` at `index`. * The key-value pair at `index` gets moved up to the parent node, @@ -156,7 +156,7 @@ extension BTreeNode { values.insert(child.values[middleIndex], at: index) child.keys.remove(at: middleIndex) child.values.remove(at: middleIndex) - + let rightSibling = BTreeNode( owner: owner, keys: Array(child.keys[child.keys.indices.suffix(from: middleIndex)]), @@ -164,9 +164,9 @@ extension BTreeNode { ) child.keys.removeSubrange(child.keys.indices.suffix(from: middleIndex)) child.values.removeSubrange(child.values.indices.suffix(from: middleIndex)) - + children!.insert(rightSibling, at: (index + 1)) - + if child.children != nil { rightSibling.children = Array( child.children![child.children!.indices.suffix(from: (middleIndex + 1))] @@ -198,7 +198,7 @@ extension BTreeNode { return children!.last!.inorderPredecessor } } - + /** * Removes `key` and the value associated with it from the node * or one of its descendants. @@ -208,11 +208,11 @@ extension BTreeNode { */ func remove(_ key: Key) { var index = keys.startIndex - + while (index + 1) < keys.endIndex && keys[index] < key { index = (index + 1) } - + if keys[index] == key { if isLeaf { keys.remove(at: index) @@ -229,7 +229,7 @@ extension BTreeNode { } } else if key < keys[index] { // We should go to left child... - + if let leftChild = children?[index] { leftChild.remove(key) if leftChild.numberOfKeys < owner.order { @@ -240,7 +240,7 @@ extension BTreeNode { } } else { // We should go to right child... - + if let rightChild = children?[(index + 1)] { rightChild.remove(key) if rightChild.numberOfKeys < owner.order { @@ -251,7 +251,7 @@ extension BTreeNode { } } } - + /** * Fixes `childWithTooFewKeys` by either moving a key to it from * one of its neighbouring nodes, or by merging. @@ -264,7 +264,7 @@ extension BTreeNode { * - index: the index of the child to be fixed in the current node */ private func fix(childWithTooFewKeys child: BTreeNode, atIndex index: Int) { - + if (index - 1) >= 0 && children![(index - 1)].numberOfKeys > owner.order { move(keyAtIndex: (index - 1), to: child, from: children![(index - 1)], at: .left) } else if (index + 1) < children!.count && children![(index + 1)].numberOfKeys > owner.order { @@ -275,7 +275,7 @@ extension BTreeNode { merge(child: child, atIndex: index, to: .right) } } - + /** * Moves the key at the specified `index` from `node` to * the `targetNode` at `position` @@ -301,7 +301,7 @@ extension BTreeNode { at: targetNode.children!.startIndex) node.children!.removeLast() } - + case .right: targetNode.keys.insert(keys[index], at: targetNode.keys.endIndex) targetNode.values.insert(values[index], at: targetNode.values.endIndex) @@ -316,7 +316,7 @@ extension BTreeNode { } } } - + /** * Merges `child` at `position` to the node at the `position`. * @@ -329,33 +329,33 @@ extension BTreeNode { switch position { case .left: // We can merge to the left sibling - + children![(index - 1)].keys = children![(index - 1)].keys + [keys[(index - 1)]] + child.keys - + children![(index - 1)].values = children![(index - 1)].values + [values[(index - 1)]] + child.values - + keys.remove(at: (index - 1)) values.remove(at: (index - 1)) - + if !child.isLeaf { children![(index - 1)].children = children![(index - 1)].children! + child.children! } - + case .right: // We should merge to the right sibling - + children![(index + 1)].keys = child.keys + [keys[index]] + children![(index + 1)].keys - + children![(index + 1)].values = child.values + [values[index]] + children![(index + 1)].values - + keys.remove(at: index) values.remove(at: index) - + if !child.isLeaf { children![(index + 1)].children = child.children! + children![(index + 1)].children! @@ -374,18 +374,18 @@ extension BTreeNode { */ var inorderArrayFromKeys: [Key] { var array = [Key] () - + for i in 0.. { * except the root node which is allowed to contain less keys than the value of order. */ public let order: Int - + /** * The root node of the tree */ var rootNode: BTreeNode! - + fileprivate(set) public var numberOfKeys = 0 - + /** * Designated initializer for the tree * @@ -484,7 +484,7 @@ extension BTree { guard rootNode.numberOfKeys > 0 else { return nil } - + return rootNode.value(for: key) } } @@ -501,12 +501,12 @@ extension BTree { */ public func insert(_ value: Value, for key: Key) { rootNode.insert(value, for: key) - + if rootNode.numberOfKeys > order * 2 { splitRoot() } } - + /** * Splits the root node of the tree. * @@ -515,7 +515,7 @@ extension BTree { */ private func splitRoot() { let middleIndexOfOldRoot = rootNode.numberOfKeys / 2 - + let newRoot = BTreeNode( owner: self, keys: [rootNode.keys[middleIndexOfOldRoot]], @@ -524,7 +524,7 @@ extension BTree { ) rootNode.keys.remove(at: middleIndexOfOldRoot) rootNode.values.remove(at: middleIndexOfOldRoot) - + let newRightChild = BTreeNode( owner: self, keys: Array(rootNode.keys[rootNode.keys.indices.suffix(from: middleIndexOfOldRoot)]), @@ -532,7 +532,7 @@ extension BTree { ) rootNode.keys.removeSubrange(rootNode.keys.indices.suffix(from: middleIndexOfOldRoot)) rootNode.values.removeSubrange(rootNode.values.indices.suffix(from: middleIndexOfOldRoot)) - + if rootNode.children != nil { newRightChild.children = Array( rootNode.children![rootNode.children!.indices.suffix(from: (middleIndexOfOldRoot + 1))] @@ -541,7 +541,7 @@ extension BTree { rootNode.children!.indices.suffix(from: (middleIndexOfOldRoot + 1)) ) } - + newRoot.children!.append(newRightChild) rootNode = newRoot } @@ -560,9 +560,9 @@ extension BTree { guard rootNode.numberOfKeys > 0 else { return } - + rootNode.remove(key) - + if rootNode.numberOfKeys == 0 && !rootNode.isLeaf { rootNode = rootNode.children!.first! } diff --git a/B-Tree/Tests/Tests/BTreeNodeTests.swift b/B-Tree/Tests/Tests/BTreeNodeTests.swift index fd3ba10e8..8eff926b5 100644 --- a/B-Tree/Tests/Tests/BTreeNodeTests.swift +++ b/B-Tree/Tests/Tests/BTreeNodeTests.swift @@ -9,44 +9,44 @@ import XCTest class BTreeNodeTests: XCTestCase { - + let owner = BTree(order: 2)! var root: BTreeNode! var leftChild: BTreeNode! var rightChild: BTreeNode! - + override func setUp() { super.setUp() - + root = BTreeNode(owner: owner) leftChild = BTreeNode(owner: owner) rightChild = BTreeNode(owner: owner) - + root.insert(1, for: 1) root.children = [leftChild, rightChild] } - + func testIsLeafRoot() { XCTAssertFalse(root.isLeaf) } - + func testIsLeafLeaf() { XCTAssertTrue(leftChild.isLeaf) XCTAssertTrue(rightChild.isLeaf) } - + func testOwner() { XCTAssert(root.owner === owner) XCTAssert(leftChild.owner === owner) XCTAssert(rightChild.owner === owner) } - + func testNumberOfKeys() { XCTAssertEqual(root.numberOfKeys, 1) XCTAssertEqual(leftChild.numberOfKeys, 0) XCTAssertEqual(rightChild.numberOfKeys, 0) } - + func testChildren() { XCTAssertEqual(root.children!.count, 2) } diff --git a/B-Tree/Tests/Tests/BTreeTests.swift b/B-Tree/Tests/Tests/BTreeTests.swift index f2dac7511..1e94bfd7d 100644 --- a/B-Tree/Tests/Tests/BTreeTests.swift +++ b/B-Tree/Tests/Tests/BTreeTests.swift @@ -10,201 +10,201 @@ import XCTest class BTreeTests: XCTestCase { var bTree: BTree! - + override func setUp() { super.setUp() bTree = BTree(order: 3)! } - + // MARK: - Tests on empty tree - + func testOrder() { XCTAssertEqual(bTree.order, 3) } - + func testRootNode() { XCTAssertNotNil(bTree.rootNode) } - + func testNumberOfNodesOnEmptyTree() { XCTAssertEqual(bTree.numberOfKeys, 0) } - + func testInorderTraversalOfEmptyTree() { bTree.traverseKeysInOrder { _ in XCTFail("Inorder travelsal fail.") } } - + func testSubscriptOnEmptyTree() { XCTAssertEqual(bTree[1], nil) } - + func testSearchEmptyTree() { XCTAssertEqual(bTree.value(for: 1), nil) } - + func testInsertToEmptyTree() { bTree.insert(1, for: 1) - + XCTAssertEqual(bTree[1]!, 1) } - + func testRemoveFromEmptyTree() { bTree.remove(1) XCTAssertEqual(bTree.description, "[]") } - + func testInorderArrayFromEmptyTree() { XCTAssertEqual(bTree.inorderArrayFromKeys, [Int]()) } - + func testDescriptionOfEmptyTree() { XCTAssertEqual(bTree.description, "[]") } - + // MARK: - Travelsal - + func testInorderTravelsal() { for i in 1...20 { bTree.insert(i, for: i) } - + var j = 1 - + bTree.traverseKeysInOrder { i in XCTAssertEqual(i, j) j += 1 } } - + // MARK: - Searching - + func testSearchForMaximum() { for i in 1...20 { bTree.insert(i, for: i) } - + XCTAssertEqual(bTree.value(for: 20)!, 20) } - + func testSearchForMinimum() { for i in 1...20 { bTree.insert(i, for: i) } - + XCTAssertEqual(bTree.value(for: 1)!, 1) } - + // MARK: - Insertion - + func testInsertion() { bTree.insertKeysUpTo(20) - + XCTAssertEqual(bTree.numberOfKeys, 20) - + for i in 1...20 { XCTAssertNotNil(bTree[i]) } - + do { try bTree.checkBalance() } catch { XCTFail("BTree is not balanced") } } - + // MARK: - Removal - + func testRemoveMaximum() { for i in 1...20 { bTree.insert(i, for: i) } - + bTree.remove(20) - + XCTAssertNil(bTree[20]) - + do { try bTree.checkBalance() } catch { XCTFail("BTree is not balanced") } } - + func testRemoveMinimum() { bTree.insertKeysUpTo(20) - + bTree.remove(1) - + XCTAssertNil(bTree[1]) - + do { try bTree.checkBalance() } catch { XCTFail("BTree is not balanced") } } - + func testRemoveSome() { bTree.insertKeysUpTo(20) - + bTree.remove(6) bTree.remove(9) - + XCTAssertNil(bTree[6]) XCTAssertNil(bTree[9]) - + do { try bTree.checkBalance() } catch { XCTFail("BTree is not balanced") } } - + func testRemoveSomeFrom2ndOrder() { bTree = BTree(order: 2)! bTree.insertKeysUpTo(20) - + bTree.remove(6) bTree.remove(9) - + XCTAssertNil(bTree[6]) XCTAssertNil(bTree[9]) - + do { try bTree.checkBalance() } catch { XCTFail("BTree is not balanced") } } - + func testRemoveAll() { bTree.insertKeysUpTo(20) - + XCTAssertEqual(bTree.numberOfKeys, 20) - + for i in (1...20).reversed() { bTree.remove(i) } - + do { try bTree.checkBalance() } catch { XCTFail("BTree is not balanced") } - + XCTAssertEqual(bTree.numberOfKeys, 0) } - + // MARK: - InorderArray - + func testInorderArray() { bTree.insertKeysUpTo(20) - + let returnedArray = bTree.inorderArrayFromKeys let targetArray = Array(1...20) - + XCTAssertEqual(returnedArray, targetArray) } } @@ -221,7 +221,7 @@ extension BTreeNode { } else if !root && numberOfKeys < owner.order { throw BTreeError.tooFewNodes } - + if !isLeaf { for child in children! { try child.checkBalance(isRoot: false) @@ -234,14 +234,14 @@ extension BTree where Key: SignedInteger, Value: SignedInteger { func insertKeysUpTo(_ to: Int) { var k: Key = 1 var v: Value = 1 - + for _ in 1...to { insert(v, for: k) k = k + 1 v = v + 1 } } - + func checkBalance() throws { try rootNode.checkBalance(isRoot: true) } diff --git a/Brute-Force String Search/BruteForceStringSearch.playground/Contents.swift b/Brute-Force String Search/BruteForceStringSearch.playground/Contents.swift index 00ac6da97..b9f2b1432 100644 --- a/Brute-Force String Search/BruteForceStringSearch.playground/Contents.swift +++ b/Brute-Force String Search/BruteForceStringSearch.playground/Contents.swift @@ -2,7 +2,7 @@ extension String { func indexOf(_ pattern: String) -> String.Index? { - + for i in self.characters.indices { var j = i var found = true diff --git a/Comb Sort/Comb Sort.playground/Sources/Comb Sort.swift b/Comb Sort/Comb Sort.playground/Sources/Comb Sort.swift index b6e85fa2b..f7c4eec61 100644 --- a/Comb Sort/Comb Sort.playground/Sources/Comb Sort.swift +++ b/Comb Sort/Comb Sort.playground/Sources/Comb Sort.swift @@ -11,13 +11,13 @@ public func combSort(_ input: [T]) -> [T] { var copy: [T] = input var gap = copy.count let shrink = 1.3 - + while gap > 1 { gap = (Int)(Double(gap) / shrink) if gap < 1 { gap = 1 } - + var index = 0 while !(index + gap >= copy.count) { if copy[index] > copy[index + gap] { diff --git a/Comb Sort/Comb Sort.swift b/Comb Sort/Comb Sort.swift index b6e85fa2b..f7c4eec61 100644 --- a/Comb Sort/Comb Sort.swift +++ b/Comb Sort/Comb Sort.swift @@ -11,13 +11,13 @@ public func combSort(_ input: [T]) -> [T] { var copy: [T] = input var gap = copy.count let shrink = 1.3 - + while gap > 1 { gap = (Int)(Double(gap) / shrink) if gap < 1 { gap = 1 } - + var index = 0 while !(index + gap >= copy.count) { if copy[index] > copy[index + gap] { diff --git a/Comb Sort/Tests/CombSortTests.swift b/Comb Sort/Tests/CombSortTests.swift index 1bcc67fd0..b9287f84a 100644 --- a/Comb Sort/Tests/CombSortTests.swift +++ b/Comb Sort/Tests/CombSortTests.swift @@ -16,7 +16,7 @@ class CombSortTests: XCTestCase { super.setUp() sequence = [2, 32, 9, -1, 89, 101, 55, -10, -12, 67] } - + override func tearDown() { super.tearDown() } diff --git a/Convex Hull/Convex Hull/AppDelegate.swift b/Convex Hull/Convex Hull/AppDelegate.swift index 4f8496cd5..bfe15e1a7 100644 --- a/Convex Hull/Convex Hull/AppDelegate.swift +++ b/Convex Hull/Convex Hull/AppDelegate.swift @@ -17,16 +17,16 @@ class AppDelegate: UIResponder, UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { let screenBounds = UIScreen.main.bounds - + window = UIWindow(frame: screenBounds) - + let viewController = UIViewController() viewController.view = View(frame: (window?.frame)!) viewController.view.backgroundColor = .white - + window?.rootViewController = viewController window?.makeKeyAndVisible() - + return true } diff --git a/Convex Hull/Convex Hull/View.swift b/Convex Hull/Convex Hull/View.swift index f9f9f6ef4..2f2c3e046 100644 --- a/Convex Hull/Convex Hull/View.swift +++ b/Convex Hull/Convex Hull/View.swift @@ -9,24 +9,24 @@ import UIKit class View: UIView { - + let MAX_POINTS = 100 - + var points = [CGPoint]() - + var convexHull = [CGPoint]() - + override init(frame: CGRect) { super.init(frame: frame) - + generatePoints() quickHull(points: points) } - + required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } - + func generatePoints() { for _ in 0.. Bool in return a.x < b.x } } - + func quickHull(points: [CGPoint]) { var pts = points - + // Assume points has at least 2 points // Assume list is ordered on x - + // left most point let p1 = pts.removeFirst() // right most point let p2 = pts.removeLast() - + // p1 and p2 are outer most points and thus are part of the hull convexHull.append(p1) convexHull.append(p2) - + // points to the right of oriented line from p1 to p2 var s1 = [CGPoint]() - + // points to the right of oriented line from p2 to p1 var s2 = [CGPoint]() - + // p1 to p2 line let lineVec1 = CGPoint(x: p2.x - p1.x, y: p2.y - p1.y) - + for p in pts { // per point check if point is to right or left of p1 to p2 line let pVec1 = CGPoint(x: p.x - p1.x, y: p.y - p1.y) let sign1 = lineVec1.x * pVec1.y - pVec1.x * lineVec1.y // cross product to check on which side of the line point p is. - + if sign1 > 0 { // right of p1 p2 line (in a normal xy coordinate system this would be < 0 but due to the weird iPhone screen coordinates this is > 0 s1.append(p) } else { // right of p2 p1 line s2.append(p) } } - + // find new hull points findHull(s1, p1, p2) findHull(s2, p2, p1) } - + func findHull(_ points: [CGPoint], _ p1: CGPoint, _ p2: CGPoint) { // if set of points is empty there are no points to the right of this line so this line is part of the hull. if points.isEmpty { return } - + var pts = points - + // calculate parameters of general line equation y = a * x + b let a = (p1.y - p2.y) / (p1.x - p2.x) let b = p1.y - a * p1.x - + // calculate normal line's growth factor let a1 = -1 / a - + var maxDist: CGFloat = -1 var maxPoint: CGPoint = pts.first! - + for p in pts { // for every point check the distance from our line let b1 = p.y - a1 * p.x // calculate offset to line equation for given point p let x = -(b - b1)/(a - a1) // calculate x where the two lines intersect let y = a * x + b // calculate y value of this intersect point - + let dist = pow(x - p.x, 2) + pow(y - p.y, 2) // calculate distance squared between intersection point and point p if dist > maxDist { // if distance is larger than current maxDist remember new point p maxDist = dist maxPoint = p } } - + convexHull.insert(maxPoint, at: convexHull.index(of: p1)! + 1) // insert point with max distance from line in the convexHull after p1 - + pts.remove(at: pts.index(of: maxPoint)!) // remove maxPoint from points array as we are going to split this array in points left and right of the line - + // points to the right of oriented line from p1 to maxPoint var s1 = [CGPoint]() - + // points to the right of oriented line from maxPoint to p2 var s2 = [CGPoint]() - + // p1 to maxPoint line let lineVec1 = CGPoint(x: maxPoint.x - p1.x, y: maxPoint.y - p1.y) // maxPoint to p2 line let lineVec2 = CGPoint(x: p2.x - maxPoint.x, y: p2.y - maxPoint.y) - + for p in pts { let pVec1 = CGPoint(x: p.x - p1.x, y: p.y - p1.y) // vector from p1 to p let sign1 = lineVec1.x * pVec1.y - pVec1.x * lineVec1.y // sign to check is p is to the right or left of lineVec1 - + let pVec2 = CGPoint(x: p.x - maxPoint.x, y: p.y - maxPoint.y) // vector from p2 to p let sign2 = lineVec2.x * pVec2.y - pVec2.x * lineVec2.y // sign to check is p is to the right or left of lineVec2 @@ -139,34 +139,34 @@ class View: UIView { s2.append(p) } } - + // find new hull points findHull(s1, p1, maxPoint) findHull(s2, maxPoint, p2) } override func draw(_ rect: CGRect) { - + let context = UIGraphicsGetCurrentContext() - + // Draw hull let lineWidth: CGFloat = 2.0 - + context!.setFillColor(UIColor.black.cgColor) context!.setLineWidth(lineWidth) context!.setStrokeColor(UIColor.red.cgColor) context!.setFillColor(UIColor.black.cgColor) - + let firstPoint = convexHull.first! context!.move(to: firstPoint) - + for p in convexHull.dropFirst() { context!.addLine(to: p) } context!.addLine(to: firstPoint) - + context!.strokePath() - + // Draw points for p in points { let radius: CGFloat = 5 diff --git a/Fixed Size Array/FixedSizeArray.playground/Contents.swift b/Fixed Size Array/FixedSizeArray.playground/Contents.swift index 4bc5d66df..8ef545e45 100644 --- a/Fixed Size Array/FixedSizeArray.playground/Contents.swift +++ b/Fixed Size Array/FixedSizeArray.playground/Contents.swift @@ -10,25 +10,25 @@ struct FixedSizeArray { private var defaultValue: T private var array: [T] private (set) var count = 0 - + init(maxSize: Int, defaultValue: T) { self.maxSize = maxSize self.defaultValue = defaultValue self.array = [T](repeating: defaultValue, count: maxSize) } - + subscript(index: Int) -> T { assert(index >= 0) assert(index < count) return array[index] } - + mutating func append(_ newElement: T) { assert(count < maxSize) array[count] = newElement count += 1 } - + mutating func removeAt(index: Int) -> T { assert(index >= 0) assert(index < count) @@ -38,7 +38,7 @@ struct FixedSizeArray { array[count] = defaultValue return result } - + mutating func removeAll() { for i in 0..(), AdjacencyListGraph()] { - + let v1 = graph.createVertex(1) let v2 = graph.createVertex(2) let v3 = graph.createVertex(3) diff --git a/Hash Set/HashSet.playground/Sources/HashSet.swift b/Hash Set/HashSet.playground/Sources/HashSet.swift index c3365110b..3ccaa94ea 100644 --- a/Hash Set/HashSet.playground/Sources/HashSet.swift +++ b/Hash Set/HashSet.playground/Sources/HashSet.swift @@ -2,31 +2,31 @@ public struct HashSet { fileprivate var dictionary = Dictionary() - + public init() { - + } - + public mutating func insert(_ element: T) { dictionary[element] = true } - + public mutating func remove(_ element: T) { dictionary[element] = nil } - + public func contains(_ element: T) -> Bool { return dictionary[element] != nil } - + public func allElements() -> [T] { return Array(dictionary.keys) } - + public var count: Int { return dictionary.count } - + public var isEmpty: Bool { return dictionary.isEmpty } diff --git a/Hash Table/HashTable.playground/Sources/HashTable.swift b/Hash Table/HashTable.playground/Sources/HashTable.swift index 947737c32..2383b8192 100644 --- a/Hash Table/HashTable.playground/Sources/HashTable.swift +++ b/Hash Table/HashTable.playground/Sources/HashTable.swift @@ -34,19 +34,19 @@ public struct HashTable: CustomStringConvertible { private typealias Element = (key: Key, value: Value) private typealias Bucket = [Element] private var buckets: [Bucket] - + /// The number of key-value pairs in the hash table. private(set) public var count = 0 - + /// A Boolean value that indicates whether the hash table is empty. public var isEmpty: Bool { return count == 0 } - + /// A string that represents the contents of the hash table. public var description: String { let pairs = buckets.flatMap { b in b.map { e in "\(e.key) = \(e.value)" } } return pairs.joined(separator: ", ") } - + /// A string that represents the contents of /// the hash table, suitable for debugging. public var debugDescription: String { @@ -57,7 +57,7 @@ public struct HashTable: CustomStringConvertible { } return str } - + /** Create a hash table with the given capacity. */ @@ -65,7 +65,7 @@ public struct HashTable: CustomStringConvertible { assert(capacity > 0) buckets = Array(repeatElement([], count: capacity)) } - + /** Accesses the value associated with the given key for reading and writing. @@ -82,7 +82,7 @@ public struct HashTable: CustomStringConvertible { } } } - + /** Returns the value for the given key. */ @@ -95,14 +95,14 @@ public struct HashTable: CustomStringConvertible { } return nil // key not in hash table } - + /** Updates the value stored in the hash table for the given key, or adds a new key-value pair if the key does not exist. */ @discardableResult public mutating func updateValue(_ value: Value, forKey key: Key) -> Value? { let index = self.index(forKey: key) - + // Do we already have this key in the bucket? for (i, element) in buckets[index].enumerated() { if element.key == key { @@ -111,20 +111,20 @@ public struct HashTable: CustomStringConvertible { return oldValue } } - + // This key isn't in the bucket yet; add it to the chain. buckets[index].append((key: key, value: value)) count += 1 return nil } - + /** Removes the given key and its associated value from the hash table. */ @discardableResult public mutating func removeValue(forKey key: Key) -> Value? { let index = self.index(forKey: key) - + // Find the element in the bucket's chain and remove it. for (i, element) in buckets[index].enumerated() { if element.key == key { @@ -135,7 +135,7 @@ public struct HashTable: CustomStringConvertible { } return nil // key not in hash table } - + /** Removes all key-value pairs from the hash table. */ @@ -143,7 +143,7 @@ public struct HashTable: CustomStringConvertible { buckets = Array(repeatElement([], count: buckets.count)) count = 0 } - + /** Returns the given key's array index. */ diff --git a/HaversineDistance/HaversineDistance.playground/Contents.swift b/HaversineDistance/HaversineDistance.playground/Contents.swift index a6effb7b0..449fa366d 100644 --- a/HaversineDistance/HaversineDistance.playground/Contents.swift +++ b/HaversineDistance/HaversineDistance.playground/Contents.swift @@ -1,25 +1,25 @@ import UIKit func haversineDinstance(la1: Double, lo1: Double, la2: Double, lo2: Double, radius: Double = 6367444.7) -> Double { - + let haversin = { (angle: Double) -> Double in return (1 - cos(angle))/2 } - + let ahaversin = { (angle: Double) -> Double in return 2*asin(sqrt(angle)) } - + // Converts from degrees to radians let dToR = { (angle: Double) -> Double in return (angle / 360) * 2 * M_PI } - + let lat1 = dToR(la1) let lon1 = dToR(lo1) let lat2 = dToR(la2) let lon2 = dToR(lo2) - + return radius * ahaversin(haversin(lat2 - lat1) + cos(lat1) * cos(lat2) * haversin(lon2 - lon1)) } diff --git a/Heap/Heap.swift b/Heap/Heap.swift index fa30df362..80b40c65f 100644 --- a/Heap/Heap.swift +++ b/Heap/Heap.swift @@ -113,7 +113,7 @@ public struct Heap { */ public mutating func replace(index i: Int, value: T) { guard i < elements.count else { return } - + assert(isOrderedBefore(value, elements[i])) elements[i] = value shiftUp(i) @@ -144,7 +144,7 @@ public struct Heap { */ public mutating func removeAt(_ index: Int) -> T? { guard index < elements.count else { return nil } - + let size = elements.count - 1 if index != size { swap(&elements[index], &elements[size]) diff --git a/Heap/Tests/HeapTests.swift b/Heap/Tests/HeapTests.swift index 0e6c504f3..cac934406 100644 --- a/Heap/Tests/HeapTests.swift +++ b/Heap/Tests/HeapTests.swift @@ -201,7 +201,7 @@ class HeapTests: XCTestCase { XCTAssertEqual(v, nil) XCTAssertTrue(verifyMaxHeap(h)) XCTAssertEqual(h.elements, [100, 50, 70, 10, 20, 60, 65]) - + let v1 = h.removeAt(5) XCTAssertEqual(v1, 60) XCTAssertTrue(verifyMaxHeap(h)) @@ -314,7 +314,7 @@ class HeapTests: XCTestCase { h.replace(index: 5, value: 13) XCTAssertTrue(verifyMaxHeap(h)) XCTAssertEqual(h.elements, [16, 14, 13, 8, 7, 10, 3, 2, 4, 1]) - + //test index out of bounds h.replace(index: 20, value: 2) XCTAssertTrue(verifyMaxHeap(h)) diff --git a/Huffman Coding/Huffman.swift b/Huffman Coding/Huffman.swift index 7e2961a2f..cad80327d 100644 --- a/Huffman Coding/Huffman.swift +++ b/Huffman Coding/Huffman.swift @@ -13,7 +13,7 @@ public class Huffman { /* Tree nodes don't use pointers to refer to each other, but simple integer indices. That allows us to use structs for the nodes. */ typealias NodeIndex = Int - + /* A node in the compression tree. Leaf nodes represent the actual bytes that are present in the input data. The count of an intermediary node is the sum of the counts of all nodes below it. The root node's count is the number of @@ -25,15 +25,15 @@ public class Huffman { var left: NodeIndex = -1 var right: NodeIndex = -1 } - + /* The tree structure. The first 256 entries are for the leaf nodes (not all of those may be used, depending on the input). We add additional nodes as we build the tree. */ var tree = [Node](repeating: Node(), count: 256) - + /* This is the last node we add to the tree. */ var root: NodeIndex = -1 - + /* The frequency table describes how often a byte occurs in the input data. You need it to decompress the Huffman-encoded data. The frequency table should be serialized along with the compressed data. */ @@ -41,7 +41,7 @@ public class Huffman { var byte: UInt8 = 0 var count = 0 } - + public init() { } } @@ -59,7 +59,7 @@ extension Huffman { ptr = ptr.successor() } } - + /* Takes a frequency table and rebuilds the tree. This is the first step of decompression. */ fileprivate func restoreTree(fromTable frequencyTable: [Freq]) { @@ -70,7 +70,7 @@ extension Huffman { } buildTree() } - + /* Returns the frequency table. This is the first 256 nodes from the tree but only those that are actually used, without the parent/left/right pointers. You would serialize this along with the compressed file. */ @@ -91,13 +91,13 @@ extension Huffman { for node in tree where node.count > 0 { queue.enqueue(node) } - + while queue.count > 1 { // Find the two nodes with the smallest frequencies that do not have // a parent node yet. let node1 = queue.dequeue()! let node2 = queue.dequeue()! - + // Create a new intermediate node. var parentNode = Node() parentNode.count = node1.count + node2.count @@ -105,15 +105,15 @@ extension Huffman { parentNode.right = node2.index parentNode.index = tree.count tree.append(parentNode) - + // Link the two nodes into their new parent node. tree[node1.index].parent = parentNode.index tree[node2.index].parent = parentNode.index - + // Put the intermediate node back into the queue. queue.enqueue(parentNode) } - + // The final remaining node in the queue becomes the root of the tree. let rootNode = queue.dequeue()! root = rootNode.index @@ -125,7 +125,7 @@ extension Huffman { public func compressData(data: NSData) -> NSData { countByteFrequency(inData: data) buildTree() - + let writer = BitWriter() var ptr = data.bytes.assumingMemoryBound(to: UInt8.self) for _ in 0.. NSData { restoreTree(fromTable: frequencyTable) - + let reader = BitReader(data: data) let outData = NSMutableData() let byteCount = tree[root].count - + var i = 0 while i < byteCount { var b = findLeafNode(reader: reader, nodeIndex: root) @@ -172,7 +172,7 @@ extension Huffman { } return outData } - + /* Walks the tree from the root down to the leaf node. At every node, read the next bit and use that to determine whether to step to the left or right. When we get to the leaf node, we simply return its index, which is equal to diff --git a/Huffman Coding/NSData+Bits.swift b/Huffman Coding/NSData+Bits.swift index 4ae3c5c6d..1f5333296 100644 --- a/Huffman Coding/NSData+Bits.swift +++ b/Huffman Coding/NSData+Bits.swift @@ -5,7 +5,7 @@ public class BitWriter { public var data = NSMutableData() var outByte: UInt8 = 0 var outCount = 0 - + public func writeBit(bit: Bool) { if outCount == 8 { data.append(&outByte, length: 1) @@ -14,7 +14,7 @@ public class BitWriter { outByte = (outByte << 1) | (bit ? 1 : 0) outCount += 1 } - + public func flush() { if outCount > 0 { if outCount < 8 { @@ -31,11 +31,11 @@ public class BitReader { var ptr: UnsafePointer var inByte: UInt8 = 0 var inCount = 8 - + public init(data: NSData) { ptr = data.bytes.assumingMemoryBound(to: UInt8.self) } - + public func readBit() -> Bool { if inCount == 8 { inByte = ptr.pointee // load the next byte diff --git a/Karatsuba Multiplication/KaratsubaMultiplication.playground/Contents.swift b/Karatsuba Multiplication/KaratsubaMultiplication.playground/Contents.swift index 3ac29301a..2d327fbac 100644 --- a/Karatsuba Multiplication/KaratsubaMultiplication.playground/Contents.swift +++ b/Karatsuba Multiplication/KaratsubaMultiplication.playground/Contents.swift @@ -17,7 +17,7 @@ func ^^ (radix: Int, power: Int) -> Int { func multiply(_ num1: Int, by num2: Int, base: Int = 10) -> Int { let num1Array = String(num1).characters.reversed().map { Int(String($0))! } let num2Array = String(num2).characters.reversed().map { Int(String($0))! } - + var product = Array(repeating: 0, count: num1Array.count + num2Array.count) for i in num1Array.indices { @@ -29,7 +29,7 @@ func multiply(_ num1: Int, by num2: Int, base: Int = 10) -> Int { } product[i + num2Array.count] += carry } - + return Int(product.reversed().map { String($0) }.reduce("", +))! } @@ -37,24 +37,24 @@ func multiply(_ num1: Int, by num2: Int, base: Int = 10) -> Int { func karatsuba(_ num1: Int, by num2: Int) -> Int { let num1Array = String(num1).characters let num2Array = String(num2).characters - + guard num1Array.count > 1 && num2Array.count > 1 else { return multiply(num1, by: num2) } - + let n = max(num1Array.count, num2Array.count) let nBy2 = n / 2 - + let a = num1 / 10^^nBy2 let b = num1 % 10^^nBy2 let c = num2 / 10^^nBy2 let d = num2 % 10^^nBy2 - + let ac = karatsuba(a, by: c) let bd = karatsuba(b, by: d) let adPlusbc = karatsuba(a+b, by: c+d) - ac - bd - + let product = ac * 10^^(2 * nBy2) + adPlusbc * 10^^nBy2 + bd - + return product } diff --git a/Karatsuba Multiplication/KaratsubaMultiplication.swift b/Karatsuba Multiplication/KaratsubaMultiplication.swift index fb20a667d..0f0e8ed12 100644 --- a/Karatsuba Multiplication/KaratsubaMultiplication.swift +++ b/Karatsuba Multiplication/KaratsubaMultiplication.swift @@ -22,24 +22,24 @@ func ^^ (radix: Int, power: Int) -> Int { func karatsuba(_ num1: Int, by num2: Int) -> Int { let num1Array = String(num1).characters let num2Array = String(num2).characters - + guard num1Array.count > 1 && num2Array.count > 1 else { return num1 * num2 } - + let n = max(num1Array.count, num2Array.count) let nBy2 = n / 2 - + let a = num1 / 10^^nBy2 let b = num1 % 10^^nBy2 let c = num2 / 10^^nBy2 let d = num2 % 10^^nBy2 - + let ac = karatsuba(a, by: c) let bd = karatsuba(b, by: d) let adPlusbc = karatsuba(a+b, by: c+d) - ac - bd - + let product = ac * 10^^(2 * nBy2) + adPlusbc * 10^^nBy2 + bd - + return product } diff --git a/Knuth-Morris-Pratt/KnuthMorrisPratt.swift b/Knuth-Morris-Pratt/KnuthMorrisPratt.swift index 46a88c134..45d9812b7 100644 --- a/Knuth-Morris-Pratt/KnuthMorrisPratt.swift +++ b/Knuth-Morris-Pratt/KnuthMorrisPratt.swift @@ -9,54 +9,54 @@ import Foundation extension String { - + func indexesOf(ptnr: String) -> [Int]? { - + let text = Array(self.characters) let pattern = Array(ptnr.characters) - + let textLength: Int = text.count let patternLength: Int = pattern.count - + guard patternLength > 0 else { return nil } - + var suffixPrefix: [Int] = [Int](repeating: 0, count: patternLength) var textIndex: Int = 0 var patternIndex: Int = 0 var indexes: [Int] = [Int]() - + /* Pre-processing stage: computing the table for the shifts (through Z-Algorithm) */ let zeta = ZetaAlgorithm(ptnr: ptnr) - + for patternIndex in (1 ..< patternLength).reversed() { textIndex = patternIndex + zeta![patternIndex] - 1 suffixPrefix[textIndex] = zeta![patternIndex] } - + /* Search stage: scanning the text for pattern matching */ textIndex = 0 patternIndex = 0 - + while textIndex + (patternLength - patternIndex - 1) < textLength { - + while patternIndex < patternLength && text[textIndex] == pattern[patternIndex] { textIndex = textIndex + 1 patternIndex = patternIndex + 1 } - + if patternIndex == patternLength { indexes.append(textIndex - patternIndex) } - + if patternIndex == 0 { textIndex = textIndex + 1 } else { patternIndex = suffixPrefix[patternIndex - 1] } } - + guard !indexes.isEmpty else { return nil } diff --git a/Linked List/LinkedList.playground/Contents.swift b/Linked List/LinkedList.playground/Contents.swift index 08e14ef70..9ee4cc4c4 100644 --- a/Linked List/LinkedList.playground/Contents.swift +++ b/Linked List/LinkedList.playground/Contents.swift @@ -4,37 +4,37 @@ //: Linked List Class Declaration: public final class LinkedList { - + /// Linked List's Node Class Declaration public class LinkedListNode { var value: T var next: LinkedListNode? weak var previous: LinkedListNode? - + public init(value: T) { self.value = value } } - + /// Typealiasing the node class to increase readability of code public typealias Node = LinkedListNode - + /// The head of the Linked List fileprivate var head: Node? - + /// Default initializer public init() {} - + /// Computed property to check if the linked list is empty public var isEmpty: Bool { return head == nil } - + /// Computed property to get the first node in the linked list (if any) public var first: Node? { return head } - + /// Computed property to iterate through the linked list and return the last node in the list (if any) public var last: Node? { if var node = head { @@ -46,7 +46,7 @@ public final class LinkedList { return nil } } - + /// Computed property to iterate through the linked list and return the total number of nodes public var count: Int { if var node = head { @@ -60,7 +60,7 @@ public final class LinkedList { return 0 } } - + /// Function to return the node at a specific index. Crashes if index is out of bounds (0...self.count) /// /// - Parameter index: Integer value of the node's index to be returned @@ -77,7 +77,7 @@ public final class LinkedList { } return nil } - + /// Subscript function to return the node at a specific index /// /// - Parameter index: Integer value of the requested value's index @@ -86,7 +86,7 @@ public final class LinkedList { assert(node != nil) return node!.value } - + /// Append a value to the end of the list /// /// - Parameter value: The data value to be appended @@ -94,7 +94,7 @@ public final class LinkedList { let newNode = Node(value: value) self.append(newNode) } - + /// Append a copy of a LinkedListNode to the end of the list. /// /// - Parameter node: The node containing the value to be appended @@ -107,7 +107,7 @@ public final class LinkedList { head = newNode } } - + /// Append a copy of a LinkedList to the end of the list. /// /// - Parameter list: The list to be copied and appended. @@ -118,28 +118,28 @@ public final class LinkedList { nodeToCopy = node.next } } - + /// A private helper funciton to find the nodes before and after a specified index. Crashes if index is out of bounds (0...self.count) /// /// - Parameter index: Integer value of the index between the nodes. /// - Returns: A tuple of 2 nodes before & after the specified index respectively. private func nodesBeforeAndAfter(index: Int) -> (Node?, Node?) { assert(index >= 0) - + var i = index var next = head var prev: Node? - + while next != nil && i > 0 { i -= 1 prev = next next = next!.next } assert(i == 0) // if > 0, then specified index was too large - + return (prev, next) } - + /// Insert a value at a specific index. Crashes if index is out of bounds (0...self.count) /// /// - Parameters: @@ -149,7 +149,7 @@ public final class LinkedList { let newNode = Node(value: value) self.insert(newNode, atIndex: index) } - + /// Insert a copy of a node at a specific index. Crashes if index is out of bounds (0...self.count) /// /// - Parameters: @@ -162,12 +162,12 @@ public final class LinkedList { newNode.next = next prev?.next = newNode next?.previous = newNode - + if prev == nil { head = newNode } } - + /// Insert a copy of a LinkedList at a specific index. Crashes if index is out of bounds (0...self.count) /// /// - Parameters: @@ -192,12 +192,12 @@ public final class LinkedList { prev?.next = next next?.previous = prev } - + /// Function to remove all nodes/value from the list public func removeAll() { head = nil } - + /// Function to remove a specific node. /// /// - Parameter node: The node to be deleted @@ -205,19 +205,19 @@ public final class LinkedList { @discardableResult public func remove(node: Node) -> T { let prev = node.previous let next = node.next - + if let prev = prev { prev.next = next } else { head = next } next?.previous = prev - + node.previous = nil node.next = nil return node.value } - + /// Function to remove the last node/value in the list. Crashes if the list is empty /// /// - Returns: The data value contained in the deleted node. @@ -225,7 +225,7 @@ public final class LinkedList { assert(!isEmpty) return remove(node: last!) } - + /// Function to remove a node/value at a specific index. Crashes if index is out of bounds (0...self.count) /// /// - Parameter index: Integer value of the index of the node to be removed @@ -276,7 +276,7 @@ extension LinkedList { } return result } - + public func filter(predicate: (T) -> Bool) -> LinkedList { let result = LinkedList() var node = head @@ -294,7 +294,7 @@ extension LinkedList { extension LinkedList { convenience init(array: Array) { self.init() - + for element in array { self.append(element) } @@ -305,7 +305,7 @@ extension LinkedList { extension LinkedList: ExpressibleByArrayLiteral { public convenience init(arrayLiteral elements: T...) { self.init() - + for element in elements { self.append(element) } diff --git a/Linked List/LinkedList.swift b/Linked List/LinkedList.swift index 783e650e8..94e978c07 100755 --- a/Linked List/LinkedList.swift +++ b/Linked List/LinkedList.swift @@ -1,29 +1,29 @@ public final class LinkedList { - + public class LinkedListNode { var value: T var next: LinkedListNode? weak var previous: LinkedListNode? - + public init(value: T) { self.value = value } } - + public typealias Node = LinkedListNode - + fileprivate var head: Node? - + public init() {} - + public var isEmpty: Bool { return head == nil } - + public var first: Node? { return head } - + public var last: Node? { if var node = head { while case let next? = node.next { @@ -34,7 +34,7 @@ public final class LinkedList { return nil } } - + public var count: Int { if var node = head { var c = 1 @@ -47,7 +47,7 @@ public final class LinkedList { return 0 } } - + public func node(atIndex index: Int) -> Node? { if index >= 0 { var node = head @@ -60,18 +60,18 @@ public final class LinkedList { } return nil } - + public subscript(index: Int) -> T { let node = self.node(atIndex: index) assert(node != nil) return node!.value } - + public func append(_ value: T) { let newNode = Node(value: value) self.append(newNode) } - + public func append(_ node: Node) { let newNode = LinkedListNode(value: node.value) if let lastNode = last { @@ -81,7 +81,7 @@ public final class LinkedList { head = newNode } } - + public func append(_ list: LinkedList) { var nodeToCopy = list.head while let node = nodeToCopy { @@ -89,29 +89,29 @@ public final class LinkedList { nodeToCopy = node.next } } - + private func nodesBeforeAndAfter(index: Int) -> (Node?, Node?) { assert(index >= 0) - + var i = index var next = head var prev: Node? - + while next != nil && i > 0 { i -= 1 prev = next next = next!.next } assert(i == 0) // if > 0, then specified index was too large - + return (prev, next) } - + public func insert(_ value: T, atIndex index: Int) { let newNode = Node(value: value) self.insert(newNode, atIndex: index) } - + public func insert(_ node: Node, atIndex index: Int) { let (prev, next) = nodesBeforeAndAfter(index: index) let newNode = LinkedListNode(value: node.value) @@ -119,12 +119,12 @@ public final class LinkedList { newNode.next = next prev?.next = newNode next?.previous = newNode - + if prev == nil { head = newNode } } - + public func insert(_ list: LinkedList, atIndex index: Int) { if list.isEmpty { return } var (prev, next) = nodesBeforeAndAfter(index: index) @@ -144,32 +144,32 @@ public final class LinkedList { prev?.next = next next?.previous = prev } - + public func removeAll() { head = nil } - + @discardableResult public func remove(node: Node) -> T { let prev = node.previous let next = node.next - + if let prev = prev { prev.next = next } else { head = next } next?.previous = prev - + node.previous = nil node.next = nil return node.value } - + @discardableResult public func removeLast() -> T { assert(!isEmpty) return remove(node: last!) } - + @discardableResult public func remove(atIndex index: Int) -> T { let node = self.node(atIndex: index) assert(node != nil) @@ -211,7 +211,7 @@ extension LinkedList { } return result } - + public func filter(predicate: (T) -> Bool) -> LinkedList { let result = LinkedList() var node = head @@ -228,7 +228,7 @@ extension LinkedList { extension LinkedList { convenience init(array: Array) { self.init() - + for element in array { self.append(element) } @@ -238,7 +238,7 @@ extension LinkedList { extension LinkedList: ExpressibleByArrayLiteral { public convenience init(arrayLiteral elements: T...) { self.init() - + for element in elements { self.append(element) } diff --git a/Linked List/Tests/LinkedListTests.swift b/Linked List/Tests/LinkedListTests.swift index ea063cacb..7fd31c2c7 100755 --- a/Linked List/Tests/LinkedListTests.swift +++ b/Linked List/Tests/LinkedListTests.swift @@ -165,7 +165,7 @@ class LinkedListTest: XCTestCase { XCTAssertTrue(prev!.next === node) XCTAssertTrue(next!.previous === node) } - + func testInsertListAtIndex() { let list = buildList() let list2 = LinkedList() @@ -190,7 +190,7 @@ class LinkedListTest: XCTestCase { XCTAssertEqual(list.node(atIndex: 1)?.value, 102) XCTAssertEqual(list.node(atIndex: 2)?.value, 8) } - + func testInsertListAtLastIndex() { let list = buildList() let list2 = LinkedList() @@ -202,7 +202,7 @@ class LinkedListTest: XCTestCase { XCTAssertEqual(list.node(atIndex: 6)?.value, 99) XCTAssertEqual(list.node(atIndex: 7)?.value, 102) } - + func testAppendList() { let list = buildList() let list2 = LinkedList() @@ -214,7 +214,7 @@ class LinkedListTest: XCTestCase { XCTAssertEqual(list.node(atIndex: 6)?.value, 99) XCTAssertEqual(list.node(atIndex: 7)?.value, 102) } - + func testAppendListToEmptyList() { let list = LinkedList() let list2 = LinkedList() @@ -225,7 +225,7 @@ class LinkedListTest: XCTestCase { XCTAssertEqual(list.node(atIndex: 0)?.value, 5) XCTAssertEqual(list.node(atIndex: 1)?.value, 10) } - + func testRemoveAtIndexOnListWithOneElement() { let list = LinkedList() list.append(123) @@ -308,10 +308,10 @@ class LinkedListTest: XCTestCase { XCTAssertTrue(last === list.first) XCTAssertEqual(nodeCount, list.count) } - + func testArrayLiteralInitTypeInfer() { let arrayLiteralInitInfer: LinkedList = [1.0, 2.0, 3.0] - + XCTAssertEqual(arrayLiteralInitInfer.count, 3) XCTAssertEqual(arrayLiteralInitInfer.first?.value, 1.0) XCTAssertEqual(arrayLiteralInitInfer.last?.value, 3.0) @@ -319,10 +319,10 @@ class LinkedListTest: XCTestCase { XCTAssertEqual(arrayLiteralInitInfer.removeLast(), 3.0) XCTAssertEqual(arrayLiteralInitInfer.count, 2) } - + func testArrayLiteralInitExplicit() { let arrayLiteralInitExplicit: LinkedList = [1, 2, 3] - + XCTAssertEqual(arrayLiteralInitExplicit.count, 3) XCTAssertEqual(arrayLiteralInitExplicit.first?.value, 1) XCTAssertEqual(arrayLiteralInitExplicit.last?.value, 3) diff --git a/Miller-Rabin Primality Test/MRPrimality.playground/Sources/MRPrimality.swift b/Miller-Rabin Primality Test/MRPrimality.playground/Sources/MRPrimality.swift index 9dca23996..ee2ace8b9 100644 --- a/Miller-Rabin Primality Test/MRPrimality.playground/Sources/MRPrimality.swift +++ b/Miller-Rabin Primality Test/MRPrimality.playground/Sources/MRPrimality.swift @@ -23,38 +23,38 @@ import Foundation */ public func mrPrimalityTest(_ n: UInt64, iteration k: Int = 1) -> Bool { guard n > 2 && n % 2 == 1 else { return false } - + var d = n - 1 var s = 0 - + while d % 2 == 0 { d /= 2 s += 1 } - + let range = UInt64.max - UInt64.max % (n - 2) var r: UInt64 = 0 repeat { arc4random_buf(&r, MemoryLayout.size(ofValue: r)) } while r >= range - + r = r % (n - 2) + 2 - + for _ in 1 ... k { var x = powmod64(r, d, n) if x == 1 || x == n - 1 { continue } - + if s == 1 { s = 2 } - + for _ in 1 ... s - 1 { x = powmod64(x, 2, n) if x == 1 { return false } if x == n - 1 { break } } - + if x != n - 1 { return false } } - + return true } @@ -71,17 +71,17 @@ public func mrPrimalityTest(_ n: UInt64, iteration k: Int = 1) -> Bool { */ private func powmod64(_ base: UInt64, _ exp: UInt64, _ m: UInt64) -> UInt64 { if m == 1 { return 0 } - + var result: UInt64 = 1 var b = base % m var e = exp - + while e > 0 { if e % 2 == 1 { result = mulmod64(result, b, m) } b = mulmod64(b, b, m) e >>= 1 } - + return result } @@ -100,12 +100,12 @@ private func mulmod64(_ first: UInt64, _ second: UInt64, _ m: UInt64) -> UInt64 var result: UInt64 = 0 var a = first var b = second - + while a != 0 { if a % 2 == 1 { result = ((result % m) + (b % m)) % m } // This may overflow if 'm' is a 64bit number && both 'result' and 'b' are very close to but smaller than 'm'. a >>= 1 b = (b << 1) % m } - + return result } diff --git a/Miller-Rabin Primality Test/MRPrimality.swift b/Miller-Rabin Primality Test/MRPrimality.swift index 9dca23996..ee2ace8b9 100644 --- a/Miller-Rabin Primality Test/MRPrimality.swift +++ b/Miller-Rabin Primality Test/MRPrimality.swift @@ -23,38 +23,38 @@ import Foundation */ public func mrPrimalityTest(_ n: UInt64, iteration k: Int = 1) -> Bool { guard n > 2 && n % 2 == 1 else { return false } - + var d = n - 1 var s = 0 - + while d % 2 == 0 { d /= 2 s += 1 } - + let range = UInt64.max - UInt64.max % (n - 2) var r: UInt64 = 0 repeat { arc4random_buf(&r, MemoryLayout.size(ofValue: r)) } while r >= range - + r = r % (n - 2) + 2 - + for _ in 1 ... k { var x = powmod64(r, d, n) if x == 1 || x == n - 1 { continue } - + if s == 1 { s = 2 } - + for _ in 1 ... s - 1 { x = powmod64(x, 2, n) if x == 1 { return false } if x == n - 1 { break } } - + if x != n - 1 { return false } } - + return true } @@ -71,17 +71,17 @@ public func mrPrimalityTest(_ n: UInt64, iteration k: Int = 1) -> Bool { */ private func powmod64(_ base: UInt64, _ exp: UInt64, _ m: UInt64) -> UInt64 { if m == 1 { return 0 } - + var result: UInt64 = 1 var b = base % m var e = exp - + while e > 0 { if e % 2 == 1 { result = mulmod64(result, b, m) } b = mulmod64(b, b, m) e >>= 1 } - + return result } @@ -100,12 +100,12 @@ private func mulmod64(_ first: UInt64, _ second: UInt64, _ m: UInt64) -> UInt64 var result: UInt64 = 0 var a = first var b = second - + while a != 0 { if a % 2 == 1 { result = ((result % m) + (b % m)) % m } // This may overflow if 'm' is a 64bit number && both 'result' and 'b' are very close to but smaller than 'm'. a >>= 1 b = (b << 1) % m } - + return result } diff --git a/Minimum Edit Distance/MinimumEditDistance.playground/Contents.swift b/Minimum Edit Distance/MinimumEditDistance.playground/Contents.swift index d651ddf2e..238afeb9b 100755 --- a/Minimum Edit Distance/MinimumEditDistance.playground/Contents.swift +++ b/Minimum Edit Distance/MinimumEditDistance.playground/Contents.swift @@ -1,21 +1,21 @@ extension String { - + public func minimumEditDistance(other: String) -> Int { let m = self.characters.count let n = other.characters.count var matrix = [[Int]](repeating: [Int](repeating: 0, count: n + 1), count: m + 1) - + // initialize matrix for index in 1...m { // the distance of any first string to an empty second string matrix[index][0] = index } - + for index in 1...n { // the distance of any second string to an empty first string matrix[0][index] = index } - + // compute Levenshtein distance for (i, selfChar) in self.characters.enumerated() { for (j, otherChar) in other.characters.enumerated() { diff --git a/Ordered Array/OrderedArray.playground/Contents.swift b/Ordered Array/OrderedArray.playground/Contents.swift index 1a0320a65..5ca0d7d31 100644 --- a/Ordered Array/OrderedArray.playground/Contents.swift +++ b/Ordered Array/OrderedArray.playground/Contents.swift @@ -49,7 +49,7 @@ public struct OrderedArray { private func findInsertionPoint(_ newElement: T) -> Int { var startIndex = 0 var endIndex = array.count - + while startIndex < endIndex { let midIndex = startIndex + (endIndex - startIndex) / 2 if array[midIndex] == newElement { diff --git a/Palindromes/Palindromes.playground/Contents.swift b/Palindromes/Palindromes.playground/Contents.swift index e8562a367..b9e857dd0 100644 --- a/Palindromes/Palindromes.playground/Contents.swift +++ b/Palindromes/Palindromes.playground/Contents.swift @@ -10,7 +10,7 @@ import Foundation func isPalindrome(_ str: String) -> Bool { let strippedString = str.replacingOccurrences(of: "\\W", with: "", options: .regularExpression, range: nil) let length = strippedString.characters.count - + if length > 1 { return palindrome(strippedString.lowercased(), left: 0, right: length - 1) } @@ -28,14 +28,14 @@ private func palindrome(_ str: String, left: Int, right: Int) -> Bool { if left >= right { return true } - + let lhs = str[str.index(str.startIndex, offsetBy: left)] let rhs = str[str.index(str.startIndex, offsetBy: right)] - + if lhs != rhs { return false } - + return palindrome(str, left: left + 1, right: right - 1) } diff --git a/Palindromes/Palindromes.swift b/Palindromes/Palindromes.swift index 2760137ca..9ddd04c80 100644 --- a/Palindromes/Palindromes.swift +++ b/Palindromes/Palindromes.swift @@ -3,7 +3,7 @@ import Foundation func isPalindrome(_ str: String) -> Bool { let strippedString = str.replacingOccurrences(of: "\\W", with: "", options: .regularExpression, range: nil) let length = strippedString.characters.count - + if length > 1 { return palindrome(strippedString.lowercased(), left: 0, right: length - 1) } @@ -14,13 +14,13 @@ private func palindrome(_ str: String, left: Int, right: Int) -> Bool { if left >= right { return true } - + let lhs = str[str.index(str.startIndex, offsetBy: left)] let rhs = str[str.index(str.startIndex, offsetBy: right)] - + if lhs != rhs { return false } - + return palindrome(str, left: left + 1, right: right - 1) } diff --git a/Palindromes/Test/Palindromes.swift b/Palindromes/Test/Palindromes.swift index 2760137ca..9ddd04c80 100644 --- a/Palindromes/Test/Palindromes.swift +++ b/Palindromes/Test/Palindromes.swift @@ -3,7 +3,7 @@ import Foundation func isPalindrome(_ str: String) -> Bool { let strippedString = str.replacingOccurrences(of: "\\W", with: "", options: .regularExpression, range: nil) let length = strippedString.characters.count - + if length > 1 { return palindrome(strippedString.lowercased(), left: 0, right: length - 1) } @@ -14,13 +14,13 @@ private func palindrome(_ str: String, left: Int, right: Int) -> Bool { if left >= right { return true } - + let lhs = str[str.index(str.startIndex, offsetBy: left)] let rhs = str[str.index(str.startIndex, offsetBy: right)] - + if lhs != rhs { return false } - + return palindrome(str, left: left + 1, right: right - 1) } diff --git a/Palindromes/Test/Test/Test.swift b/Palindromes/Test/Test/Test.swift index 1dd79ea97..ddf970300 100644 --- a/Palindromes/Test/Test/Test.swift +++ b/Palindromes/Test/Test/Test.swift @@ -9,22 +9,22 @@ import XCTest class PalindromeTests: XCTestCase { - + override func setUp() { super.setUp() // Put setup code here. This method is called before the invocation of each test method in the class. } - + override func tearDown() { // Put teardown code here. This method is called after the invocation of each test method in the class. super.tearDown() } - + func testExample() { // This is an example of a functional test case. // Use XCTAssert and related functions to verify your tests produce the correct results. } - + func testPerformanceExample() { // This is an example of a performance test case. self.measure { @@ -34,12 +34,12 @@ class PalindromeTests: XCTestCase { _ = isPalindrome("abababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababa") } } - + func testPalindromeWord() { XCTAssertTrue(isPalindrome("abbcbba")) XCTAssertTrue(isPalindrome("racecar")) } - + func testPalindromeSentence() { XCTAssertTrue(isPalindrome("A man, a plan, a canal, Panama!")) XCTAssertTrue(isPalindrome("Madam, I'm Adam")) @@ -47,17 +47,17 @@ class PalindromeTests: XCTestCase { XCTAssertTrue(isPalindrome("In girum imus nocte et consumimur igni")) XCTAssertTrue(isPalindrome("Never odd or even")) } - + func testPalindromeNumber() { XCTAssertTrue(isPalindrome("5885")) XCTAssertTrue(isPalindrome("5 8 8 5")) XCTAssertTrue(isPalindrome("58 85")) } - + func testSpecialCharacters() { XCTAssertTrue(isPalindrome("৯৯")) } - + func testNonPalindromes() { XCTAssertFalse(isPalindrome("\\\\")) XCTAssertFalse(isPalindrome("desserts")) diff --git a/QuadTree/QuadTree.playground/Sources/QuadTree.swift b/QuadTree/QuadTree.playground/Sources/QuadTree.swift index 14d0dbba7..7fd459e97 100644 --- a/QuadTree/QuadTree.playground/Sources/QuadTree.swift +++ b/QuadTree/QuadTree.playground/Sources/QuadTree.swift @@ -1,7 +1,7 @@ public struct Point { let x: Double let y: Double - + public init(_ x: Double, _ y: Double) { self.x = x self.y = y @@ -17,18 +17,18 @@ extension Point: CustomStringConvertible { public struct Size: CustomStringConvertible { var xLength: Double var yLength: Double - + public init(xLength: Double, yLength: Double) { precondition(xLength >= 0, "xLength can not be negative") precondition(yLength >= 0, "yLength can not be negative") self.xLength = xLength self.yLength = yLength } - + var half: Size { return Size(xLength: xLength / 2, yLength: yLength / 2) } - + public var description: String { return "Size(\(xLength), \(yLength))" } @@ -38,49 +38,49 @@ public struct Rect { // left top vertice var origin: Point var size: Size - + public init(origin: Point, size: Size) { self.origin = origin self.size = size } - + var minX: Double { return origin.x } - + var minY: Double { return origin.y } - + var maxX: Double { return origin.x + size.xLength } - + var maxY: Double { return origin.y + size.yLength } - + func containts(point: Point) -> Bool { return (minX <= point.x && point.x <= maxX) && (minY <= point.y && point.y <= maxY) } - + var leftTopRect: Rect { return Rect(origin: origin, size: size.half) } - + var leftBottomRect: Rect { return Rect(origin: Point(origin.x, origin.y + size.half.yLength), size: size.half) } - + var rightTopRect: Rect { return Rect(origin: Point(origin.x + size.half.xLength, origin.y), size: size.half) } - + var rightBottomRect: Rect { return Rect(origin: Point(origin.x + size.half.xLength, origin.y + size.half.yLength), size: size.half) } - + func intersects(rect: Rect) -> Bool { func lineSegmentsIntersect(lStart: Double, lEnd: Double, rStart: Double, rEnd: Double) -> Bool { @@ -91,7 +91,7 @@ public struct Rect { if !lineSegmentsIntersect(lStart: minX, lEnd: maxX, rStart: rect.minX, rEnd: rect.maxX) { return false } - + // vertical return lineSegmentsIntersect(lStart: minY, lEnd: maxY, rStart: rect.minY, rEnd: rect.maxY) } @@ -109,37 +109,37 @@ protocol PointsContainer { } class QuadTreeNode { - + enum NodeType { case leaf case `internal`(children: Children) } - + struct Children: Sequence { let leftTop: QuadTreeNode let leftBottom: QuadTreeNode let rightTop: QuadTreeNode let rightBottom: QuadTreeNode - + init(parentNode: QuadTreeNode) { leftTop = QuadTreeNode(rect: parentNode.rect.leftTopRect) leftBottom = QuadTreeNode(rect: parentNode.rect.leftBottomRect) rightTop = QuadTreeNode(rect: parentNode.rect.rightTopRect) rightBottom = QuadTreeNode(rect: parentNode.rect.rightBottomRect) } - + struct ChildrenIterator: IteratorProtocol { private var index = 0 private let children: Children - + init(children: Children) { self.children = children } - + mutating func next() -> QuadTreeNode? { - + defer { index += 1 } - + switch index { case 0: return children.leftTop case 1: return children.leftBottom @@ -149,26 +149,26 @@ class QuadTreeNode { } } } - + public func makeIterator() -> ChildrenIterator { return ChildrenIterator(children: self) } } - + var points: [Point] = [] let rect: Rect var type: NodeType = .leaf - + static let maxPointCapacity = 3 - + init(rect: Rect) { self.rect = rect } - + var recursiveDescription: String { return recursiveDescription(withTabCount: 0) } - + private func recursiveDescription(withTabCount count: Int) -> String { let indent = String(repeating: "\t", count: count) var result = "\(indent)" + description + "\n" @@ -185,13 +185,13 @@ class QuadTreeNode { } extension QuadTreeNode: PointsContainer { - + @discardableResult func add(point: Point) -> Bool { if !rect.containts(point: point) { return false } - + switch type { case .internal(let children): // pass the point to one of the children @@ -200,7 +200,7 @@ extension QuadTreeNode: PointsContainer { return true } } - + fatalError("rect.containts evaluted to true, but none of the children added the point") case .leaf: points.append(point) @@ -211,7 +211,7 @@ extension QuadTreeNode: PointsContainer { } return true } - + private func subdivide() { switch type { case .leaf: @@ -220,25 +220,25 @@ extension QuadTreeNode: PointsContainer { preconditionFailure("Calling subdivide on an internal node") } } - + func points(inRect rect: Rect) -> [Point] { - + // if the node's rect and the given rect don't intersect, return an empty array, // because there can't be any points that lie the node's (or its children's) rect and // in the given rect if !self.rect.intersects(rect: rect) { return [] } - + var result: [Point] = [] - + // collect the node's points that lie in the rect for point in points { if rect.containts(point: point) { result.append(point) } } - + switch type { case .leaf: break @@ -248,7 +248,7 @@ extension QuadTreeNode: PointsContainer { result.append(contentsOf: childNode.points(inRect: rect)) } } - + return result } } @@ -265,18 +265,18 @@ extension QuadTreeNode: CustomStringConvertible { } public class QuadTree: PointsContainer { - + let root: QuadTreeNode - + public init(rect: Rect) { self.root = QuadTreeNode(rect: rect) } - + @discardableResult public func add(point: Point) -> Bool { return root.add(point: point) } - + public func points(inRect rect: Rect) -> [Point] { return root.points(inRect: rect) } diff --git a/QuadTree/Tests/Tests/Tests.swift b/QuadTree/Tests/Tests/Tests.swift index b408c4f7e..9bd8ad28f 100644 --- a/QuadTree/Tests/Tests/Tests.swift +++ b/QuadTree/Tests/Tests/Tests.swift @@ -17,68 +17,68 @@ public func == (lhs: Point, rhs: Point) -> Bool { } class Tests: XCTestCase { - + func testRectContains() { let rect = Rect(origin: Point(0, 0), size: Size(xLength: 3, yLength: 3)) - + XCTAssertTrue(rect.containts(point: Point(1, 1))) XCTAssertTrue(rect.containts(point: Point(0, 0))) XCTAssertTrue(rect.containts(point: Point(0, 3))) XCTAssertTrue(rect.containts(point: Point(3, 3))) - + XCTAssertFalse(rect.containts(point: Point(-1, 1))) XCTAssertFalse(rect.containts(point: Point(-0.1, 0.1))) XCTAssertFalse(rect.containts(point: Point(0, 3.1))) XCTAssertFalse(rect.containts(point: Point(-4, 1))) } - + func testIntersects() { let rect = Rect(origin: Point(0, 0), size: Size(xLength: 5, yLength: 5)) let rect2 = Rect(origin: Point(1, 1), size: Size(xLength: 1, yLength: 1)) XCTAssertTrue(rect.intersects(rect: rect2)) - + let rect3 = Rect(origin: Point(1, 0), size: Size(xLength: 1, yLength: 10)) let rect4 = Rect(origin: Point(0, 1), size: Size(xLength: 10, yLength: 1)) XCTAssertTrue(rect3.intersects(rect: rect4)) - + let rect5 = Rect(origin: Point(0, 0), size: Size(xLength: 4, yLength: 4)) let rect6 = Rect(origin: Point(2, 2), size: Size(xLength: 4, yLength: 4)) XCTAssertTrue(rect5.intersects(rect: rect6)) - + let rect7 = Rect(origin: Point(0, 0), size: Size(xLength: 4, yLength: 4)) let rect8 = Rect(origin: Point(4, 4), size: Size(xLength: 1, yLength: 1)) XCTAssertTrue(rect7.intersects(rect: rect8)) - + let rect9 = Rect(origin: Point(-1, -1), size: Size(xLength: 0.5, yLength: 0.5)) let rect10 = Rect(origin: Point(0, 0), size: Size(xLength: 1, yLength: 1)) XCTAssertFalse(rect9.intersects(rect: rect10)) - + let rect11 = Rect(origin: Point(0, 0), size: Size(xLength: 2, yLength: 1)) let rect12 = Rect(origin: Point(3, 0), size: Size(xLength: 1, yLength: 1)) XCTAssertFalse(rect11.intersects(rect: rect12)) } - + func testQuadTree() { let rect = Rect(origin: Point(0, 0), size: Size(xLength: 5, yLength: 5)) let qt = QuadTree(rect: rect) - + XCTAssertTrue(qt.points(inRect: rect) == [Point]()) - + XCTAssertFalse(qt.add(point: Point(-0.1, 0.1))) - + XCTAssertTrue(qt.points(inRect: rect) == [Point]()) - + XCTAssertTrue(qt.add(point: Point(1, 1))) XCTAssertTrue(qt.add(point: Point(3, 3))) XCTAssertTrue(qt.add(point: Point(4, 4))) XCTAssertTrue(qt.add(point: Point(0.5, 0.5))) - + XCTAssertFalse(qt.add(point: Point(5.5, 0))) XCTAssertFalse(qt.add(point: Point(5.5, 1))) XCTAssertFalse(qt.add(point: Point(5.5, 2))) - + XCTAssertTrue(qt.add(point: Point(1.5, 1.5))) - + let rect2 = Rect(origin: Point(0, 0), size: Size(xLength: 2, yLength: 2)) XCTAssertTrue(qt.points(inRect: rect2) == [Point(1, 1), Point(0.5, 0.5), Point(1.5, 1.5)]) } diff --git a/Radix Sort/RadixSort.playground/Sources/radixSort.swift b/Radix Sort/RadixSort.playground/Sources/radixSort.swift index 136ede4fd..81c2479e8 100644 --- a/Radix Sort/RadixSort.playground/Sources/radixSort.swift +++ b/Radix Sort/RadixSort.playground/Sources/radixSort.swift @@ -11,18 +11,18 @@ public func radixSort(_ array: inout [Int] ) { var done = false var index: Int var digit = 1 //Which digit are we on? - - + + while !done { //While our sorting is not completed done = true //Assume it is done for now - + var buckets: [[Int]] = [] //Our sorting subroutine is bucket sort, so let us predefine our buckets - + for _ in 1...radix { buckets.append([]) } - - + + for number in array { index = number / digit //Which bucket will we access? buckets[index % radix].append(number) @@ -30,9 +30,9 @@ public func radixSort(_ array: inout [Int] ) { done = false } } - + var i = 0 - + for j in 0..: CustomStringConvertible { public var right: RBTNode! public var left: RBTNode! public var parent: RBTNode! - + public var description: String { if self.value == nil { return "null" } else { var nodeValue: String - + // If the value is encapsulated by parentheses it is red // If the value is encapsulated by pipes it is black // If the value is encapsulated by double pipes it is double black (This should not occur in a verified RBTree) @@ -27,33 +27,33 @@ public class RBTNode: CustomStringConvertible { } else { nodeValue = "||\(self.value!)||" } - + return "(\(self.left.description)<-\(nodeValue)->\(self.right.description))" } } - + init(tree: RBTree) { right = tree.nullLeaf left = tree.nullLeaf parent = tree.nullLeaf } - + init() { //This method is here to support the creation of a nullLeaf } - + public var isLeftChild: Bool { return self.parent.left === self } - + public var isRightChild: Bool { return self.parent.right === self } - + public var grandparent: RBTNode { return parent.parent } - + public var sibling: RBTNode { if isLeftChild { return self.parent.right @@ -61,19 +61,19 @@ public class RBTNode: CustomStringConvertible { return self.parent.left } } - + public var uncle: RBTNode { return parent.sibling } - + fileprivate var isRed: Bool { return color == .red } - + fileprivate var isBlack: Bool { return color == .black } - + fileprivate var isDoubleBlack: Bool { return color == .doubleBlack } @@ -82,70 +82,70 @@ public class RBTNode: CustomStringConvertible { public class RBTree: CustomStringConvertible { public var root: RBTNode fileprivate let nullLeaf: RBTNode - + public var description: String { return root.description } - + public init() { nullLeaf = RBTNode() nullLeaf.color = .black root = nullLeaf } - + public convenience init(withValue value: T) { self.init() insert(value) } - + public convenience init(withArray array: [T]) { self.init() insert(array) } - + public func insert(_ value: T) { let newNode = RBTNode(tree: self) newNode.value = value insertNode(n: newNode) } - + public func insert(_ values: [T]) { for value in values { print(value) insert(value) } } - + public func delete(_ value: T) { let nodeToDelete = find(value) if nodeToDelete !== nullLeaf { deleteNode(n: nodeToDelete) } } - + public func find(_ value: T) -> RBTNode { let foundNode = findNode(rootNode: root, value: value) return foundNode } - + public func minimum(n: RBTNode) -> RBTNode { var min = n if n.left !== nullLeaf { min = minimum(n: n.left) } - + return min } - + public func maximum(n: RBTNode) -> RBTNode { var max = n if n.right !== nullLeaf { max = maximum(n: n.right) } - + return max } - + public func verify() { if self.root === nullLeaf { print("The tree is empty") @@ -155,7 +155,7 @@ public class RBTree: CustomStringConvertible { property2(n: self.root) property3() } - + private func findNode(rootNode: RBTNode, value: T) -> RBTNode { var nextNode = rootNode if rootNode !== nullLeaf && value != rootNode.value { @@ -165,15 +165,15 @@ public class RBTree: CustomStringConvertible { nextNode = findNode(rootNode: rootNode.right, value: value) } } - + return nextNode } - + private func insertNode(n: RBTNode) { BSTInsertNode(n: n, parent: root) insertCase1(n: n) } - + private func BSTInsertNode(n: RBTNode, parent: RBTNode) { if parent === nullLeaf { self.root = n @@ -193,7 +193,7 @@ public class RBTree: CustomStringConvertible { } } } - + // if node is root change color to black, else move on private func insertCase1(n: RBTNode) { if n === root { @@ -202,14 +202,14 @@ public class RBTree: CustomStringConvertible { insertCase2(n: n) } } - + // if parent of node is not black, and node is not root move on private func insertCase2(n: RBTNode) { if !n.parent.isBlack { insertCase3(n: n) } } - + // if uncle is red do stuff otherwise move to 4 private func insertCase3(n: RBTNode) { if n.uncle.isRed { // node must have grandparent as children of root have a black parent @@ -224,14 +224,14 @@ public class RBTree: CustomStringConvertible { insertCase4(n: n) } } - + // parent is red, grandparent is black, uncle is black // There are 4 cases left: // - left left // - left right // - right right // - right left - + // the cases "left right" and "right left" can be rotated into the other two // so if either of the two is detected we apply a rotation and then move on to // deal with the final two cases, if neither is detected we move on to those cases anyway @@ -246,28 +246,28 @@ public class RBTree: CustomStringConvertible { insertCase5(n: n) } } - + private func insertCase5(n: RBTNode) { // swap color of parent and grandparent // parent is red grandparent is black n.parent.color = .black n.grandparent.color = .red - + if n.isLeftChild { // left left case rightRotate(n: n.grandparent) } else { // right right case leftRotate(n: n.grandparent) } } - + private func deleteNode(n: RBTNode) { var toDel = n - + if toDel.left === nullLeaf && toDel.right === nullLeaf && toDel.parent === nullLeaf { self.root = nullLeaf return } - + if toDel.left === nullLeaf && toDel.right === nullLeaf && toDel.isRed { if toDel.isLeftChild { toDel.parent.left = nullLeaf @@ -276,38 +276,38 @@ public class RBTree: CustomStringConvertible { } return } - + if toDel.left !== nullLeaf && toDel.right !== nullLeaf { let pred = maximum(n: toDel.left) toDel.value = pred.value toDel = pred } - + // from here toDel has at most 1 non nullLeaf child - + var child: RBTNode if toDel.left !== nullLeaf { child = toDel.left } else { child = toDel.right } - + if toDel.isRed || child.isRed { child.color = .black - + if toDel.isLeftChild { toDel.parent.left = child } else { toDel.parent.right = child } - + if child !== nullLeaf { child.parent = toDel.parent } } else { // both toDel and child are black - + var sibling = toDel.sibling - + if toDel.isLeftChild { toDel.parent.left = child } else { @@ -317,10 +317,10 @@ public class RBTree: CustomStringConvertible { child.parent = toDel.parent } child.color = .doubleBlack - + while child.isDoubleBlack || (child.parent !== nullLeaf && child.parent != nil) { if sibling.isBlack { - + var leftRedChild: RBTNode! = nil if sibling.left.isRed { leftRedChild = sibling.left @@ -329,7 +329,7 @@ public class RBTree: CustomStringConvertible { if sibling.right.isRed { rightRedChild = sibling.right } - + if leftRedChild != nil || rightRedChild != nil { // at least one of sibling's children are red child.color = .black if sibling.isLeftChild { @@ -389,7 +389,7 @@ public class RBTree: CustomStringConvertible { } } else { // sibling is red sibling.color = .black - + if sibling.isLeftChild { // left case rightRotate(n: sibling.parent) sibling = sibling.right.left @@ -400,7 +400,7 @@ public class RBTree: CustomStringConvertible { sibling.parent.color = .red } } - + // sibling check is here for when child is a nullLeaf and thus does not have a parent. // child is here as sibling can become nil when child is the root if (sibling.parent === nullLeaf) || (child !== nullLeaf && child.parent === nullLeaf) { @@ -409,14 +409,14 @@ public class RBTree: CustomStringConvertible { } } } - + private func property1() { - + if self.root.isRed { print("Root is not black") } } - + private func property2(n: RBTNode) { if n === nullLeaf { return @@ -431,48 +431,48 @@ public class RBTree: CustomStringConvertible { property2(n: n.left) property2(n: n.right) } - + private func property3() { let bDepth = blackDepth(root: self.root) - + let leaves: [RBTNode] = getLeaves(n: self.root) - + for leaflet in leaves { var leaf = leaflet var i = 0 - + while leaf !== nullLeaf { if leaf.isBlack { i = i + 1 } leaf = leaf.parent } - + if i != bDepth { print("black depth: \(bDepth), is not equal (depth: \(i)) for leaf with value: \(leaflet.value)") } } - + } - + private func getLeaves(n: RBTNode) -> [RBTNode] { var leaves = [RBTNode]() - + if n !== nullLeaf { if n.left === nullLeaf && n.right === nullLeaf { leaves.append(n) } else { let leftLeaves = getLeaves(n: n.left) let rightLeaves = getLeaves(n: n.right) - + leaves.append(contentsOf: leftLeaves) leaves.append(contentsOf: rightLeaves) } } - + return leaves } - + private func blackDepth(root: RBTNode) -> Int { if root === nullLeaf { return 0 @@ -481,7 +481,7 @@ public class RBTree: CustomStringConvertible { return returnValue + (max(blackDepth(root: root.left), blackDepth(root: root.right))) } } - + private func leftRotate(n: RBTNode) { let newRoot = n.right! n.right = newRoot.left! @@ -499,7 +499,7 @@ public class RBTree: CustomStringConvertible { newRoot.left = n n.parent = newRoot } - + private func rightRotate(n: RBTNode) { let newRoot = n.left! n.left = newRoot.right! diff --git a/Run-Length Encoding/RLE.playground/Contents.swift b/Run-Length Encoding/RLE.playground/Contents.swift index 11e177d0d..26f7dca48 100644 --- a/Run-Length Encoding/RLE.playground/Contents.swift +++ b/Run-Length Encoding/RLE.playground/Contents.swift @@ -12,16 +12,16 @@ originalString == restoredString func encodeAndDecode(_ bytes: [UInt8]) -> Bool { var bytes = bytes - + var data1 = Data(bytes: &bytes, count: bytes.count) print("data1 is \(data1.count) bytes") - + var rleData = data1.compressRLE() print("encoded data is \(rleData.count) bytes") - + var data2 = rleData.decompressRLE() print("data2 is \(data2.count) bytes") - + return data1 == data2 } @@ -66,10 +66,10 @@ func testBufferWithoutSpans() -> Bool { func testBufferWithSpans(_ spanSize: Int) -> Bool { print("span size \(spanSize)") - + let length = spanSize * 32 var bytes: [UInt8] = Array(repeating: 0, count: length) - + for t in stride(from: 0, to: length, by: spanSize) { for i in 0.. Bool { for bool in tests { result = result && bool } - + return result } diff --git a/Run-Length Encoding/RLE.playground/Sources/RLE.swift b/Run-Length Encoding/RLE.playground/Sources/RLE.swift index 5707e3d9d..0bb6fa00d 100644 --- a/Run-Length Encoding/RLE.playground/Sources/RLE.swift +++ b/Run-Length Encoding/RLE.playground/Sources/RLE.swift @@ -13,7 +13,7 @@ extension Data { var count = 0 var byte = ptr.pointee var next = byte - + // Is the next byte the same? Keep reading until we find a different // value, or we reach the end of the data, or the run is 64 bytes. while next == byte && ptr < end && count < 64 { @@ -21,7 +21,7 @@ extension Data { next = ptr.pointee count += 1 } - + if count > 1 || byte >= 192 { // byte run of up to 64 repeats var size = 191 + UInt8(count) data.append(&size, count: 1) @@ -33,7 +33,7 @@ extension Data { } return data } - + /* Converts a run-length encoded NSData back to the original. */ @@ -42,20 +42,20 @@ extension Data { self.withUnsafeBytes { (uPtr: UnsafePointer) in var ptr = uPtr let end = ptr + count - + while ptr < end { // Read the next byte. This is either a single value less than 192, // or the start of a byte run. var byte = ptr.pointee ptr = ptr.advanced(by: 1) - + if byte < 192 { // single value data.append(&byte, count: 1) } else if ptr < end { // byte run // Read the actual data value. var value = ptr.pointee ptr = ptr.advanced(by: 1) - + // And write it out repeatedly. for _ in 0 ..< byte - 191 { data.append(&value, count: 1) diff --git a/Segment Tree/SegmentTree.playground/Contents.swift b/Segment Tree/SegmentTree.playground/Contents.swift index 5bba56cc0..08474aee2 100644 --- a/Segment Tree/SegmentTree.playground/Contents.swift +++ b/Segment Tree/SegmentTree.playground/Contents.swift @@ -1,19 +1,19 @@ //: Playground - noun: a place where people can play public class SegmentTree { - + private var value: T private var function: (T, T) -> T private var leftBound: Int private var rightBound: Int private var leftChild: SegmentTree? private var rightChild: SegmentTree? - + public init(array: [T], leftBound: Int, rightBound: Int, function: @escaping (T, T) -> T) { self.leftBound = leftBound self.rightBound = rightBound self.function = function - + if leftBound == rightBound { value = array[leftBound] } else { @@ -23,19 +23,19 @@ public class SegmentTree { value = function(leftChild!.value, rightChild!.value) } } - + public convenience init(array: [T], function: @escaping (T, T) -> T) { self.init(array: array, leftBound: 0, rightBound: array.count-1, function: function) } - + public func query(leftBound: Int, rightBound: Int) -> T { if self.leftBound == leftBound && self.rightBound == rightBound { return self.value } - + guard let leftChild = leftChild else { fatalError("leftChild should not be nil") } guard let rightChild = rightChild else { fatalError("rightChild should not be nil") } - + if leftChild.rightBound < leftBound { return rightChild.query(leftBound: leftBound, rightBound: rightBound) } else if rightChild.leftBound > rightBound { @@ -46,7 +46,7 @@ public class SegmentTree { return function(leftResult, rightResult) } } - + public func replaceItem(at index: Int, withItem item: T) { if leftBound == rightBound { value = item @@ -83,7 +83,7 @@ func gcd(_ m: Int, _ n: Int) -> Int { var a = 0 var b = max(m, n) var r = min(m, n) - + while r != 0 { a = b b = r diff --git a/Segment Tree/SegmentTree.swift b/Segment Tree/SegmentTree.swift index a3ec8b1bf..6f4edd306 100644 --- a/Segment Tree/SegmentTree.swift +++ b/Segment Tree/SegmentTree.swift @@ -8,19 +8,19 @@ */ public class SegmentTree { - + private var value: T private var function: (T, T) -> T private var leftBound: Int private var rightBound: Int private var leftChild: SegmentTree? private var rightChild: SegmentTree? - + public init(array: [T], leftBound: Int, rightBound: Int, function: @escaping (T, T) -> T) { self.leftBound = leftBound self.rightBound = rightBound self.function = function - + if leftBound == rightBound { value = array[leftBound] } else { @@ -30,19 +30,19 @@ public class SegmentTree { value = function(leftChild!.value, rightChild!.value) } } - + public convenience init(array: [T], function: @escaping (T, T) -> T) { self.init(array: array, leftBound: 0, rightBound: array.count-1, function: function) } - + public func query(leftBound: Int, rightBound: Int) -> T { if self.leftBound == leftBound && self.rightBound == rightBound { return self.value } - + guard let leftChild = leftChild else { fatalError("leftChild should not be nil") } guard let rightChild = rightChild else { fatalError("rightChild should not be nil") } - + if leftChild.rightBound < leftBound { return rightChild.query(leftBound: leftBound, rightBound: rightBound) } else if rightChild.leftBound > rightBound { @@ -53,7 +53,7 @@ public class SegmentTree { return function(leftResult, rightResult) } } - + public func replaceItem(at index: Int, withItem item: T) { if leftBound == rightBound { value = item diff --git a/Select Minimum Maximum/MinimumMaximumPairs.swift b/Select Minimum Maximum/MinimumMaximumPairs.swift index b7deb570a..81942b303 100644 --- a/Select Minimum Maximum/MinimumMaximumPairs.swift +++ b/Select Minimum Maximum/MinimumMaximumPairs.swift @@ -35,6 +35,6 @@ func minimumMaximum(_ array: [T]) -> (minimum: T, maximum: T)? { } } } - + return (minimum, maximum) } diff --git a/Select Minimum Maximum/SelectMinimumMaximum.playground/Contents.swift b/Select Minimum Maximum/SelectMinimumMaximum.playground/Contents.swift index 182060805..dbf3a7468 100644 --- a/Select Minimum Maximum/SelectMinimumMaximum.playground/Contents.swift +++ b/Select Minimum Maximum/SelectMinimumMaximum.playground/Contents.swift @@ -4,7 +4,7 @@ func minimum(_ array: [T]) -> T? { guard !array.isEmpty else { return nil } - + var minimum = array.removeFirst() for element in array { minimum = element < minimum ? element : minimum @@ -18,7 +18,7 @@ func maximum(_ array: [T]) -> T? { guard !array.isEmpty else { return nil } - + var maximum = array.removeFirst() for element in array { maximum = element > maximum ? element : maximum @@ -32,18 +32,18 @@ func minimumMaximum(_ array: [T]) -> (minimum: T, maximum: T)? { guard !array.isEmpty else { return nil } - + var minimum = array.first! var maximum = array.first! - + let hasOddNumberOfItems = array.count % 2 != 0 if hasOddNumberOfItems { array.removeFirst() } - + while !array.isEmpty { let pair = (array.removeFirst(), array.removeFirst()) - + if pair.0 > pair.1 { if pair.0 > maximum { maximum = pair.0 @@ -60,7 +60,7 @@ func minimumMaximum(_ array: [T]) -> (minimum: T, maximum: T)? { } } } - + return (minimum, maximum) } diff --git a/Shell Sort/ShellSortExample.swift b/Shell Sort/ShellSortExample.swift index aaf58cf4d..e9cee7543 100644 --- a/Shell Sort/ShellSortExample.swift +++ b/Shell Sort/ShellSortExample.swift @@ -10,18 +10,18 @@ import Foundation public func shellSort(_ list : inout [Int]) { var sublistCount = list.count / 2 - + while sublistCount > 0 { for var index in 0.. list[index + sublistCount] { swap(&list[index], &list[index + sublistCount]) } - + guard sublistCount == 1 && index > 0 else { continue } - + while list[index - 1] > list[index] && index - 1 > 0 { swap(&list[index - 1], &list[index]) index -= 1 diff --git a/Shortest Path (Unweighted)/Tests/Graph.swift b/Shortest Path (Unweighted)/Tests/Graph.swift index 8322ba0a9..4d2e59eab 100644 --- a/Shortest Path (Unweighted)/Tests/Graph.swift +++ b/Shortest Path (Unweighted)/Tests/Graph.swift @@ -2,7 +2,7 @@ open class Edge: Equatable { open var neighbor: Node - + public init(neighbor: Node) { self.neighbor = neighbor } @@ -17,28 +17,28 @@ public func == (lhs: Edge, rhs: Edge) -> Bool { open class Node: CustomStringConvertible, Equatable { open var neighbors: [Edge] - + open fileprivate(set) var label: String open var distance: Int? open var visited: Bool - + public init(label: String) { self.label = label neighbors = [] visited = false } - + open var description: String { if let distance = distance { return "Node(label: \(label), distance: \(distance))" } return "Node(label: \(label), distance: infinity)" } - + open var hasDistance: Bool { return distance != nil } - + open func remove(_ edge: Edge) { neighbors.remove(at: neighbors.index { $0 === edge }!) } @@ -52,25 +52,25 @@ public func == (lhs: Node, rhs: Node) -> Bool { open class Graph: CustomStringConvertible, Equatable { open fileprivate(set) var nodes: [Node] - + public init() { self.nodes = [] } - + open func addNode(label: String) -> Node { let node = Node(label: label) nodes.append(node) return node } - + open func addEdge(_ source: Node, neighbor: Node) { let edge = Edge(neighbor: neighbor) source.neighbors.append(edge) } - + open var description: String { var description = "" - + for node in nodes { if !node.neighbors.isEmpty { description += "[node: \(node.label) edges: \(node.neighbors.map { $0.neighbor.label})]" @@ -78,18 +78,18 @@ open class Graph: CustomStringConvertible, Equatable { } return description } - + open func findNodeWithLabel(label: String) -> Node { return nodes.filter { $0.label == label }.first! } - + open func duplicate() -> Graph { let duplicated = Graph() - + for node in nodes { duplicated.addNode(label: node.label) } - + for node in nodes { for edge in node.neighbors { let source = duplicated.findNodeWithLabel(label: node.label) @@ -97,7 +97,7 @@ open class Graph: CustomStringConvertible, Equatable { duplicated.addEdge(source, neighbor: neighbour) } } - + return duplicated } } diff --git a/Shunting Yard/ShuntingYard.playground/Contents.swift b/Shunting Yard/ShuntingYard.playground/Contents.swift index fa9f5745b..bd4d15515 100644 --- a/Shunting Yard/ShuntingYard.playground/Contents.swift +++ b/Shunting Yard/ShuntingYard.playground/Contents.swift @@ -12,7 +12,7 @@ public enum OperatorType: CustomStringConvertible { case multiply case percent case exponent - + public var description: String { switch self { case .add: @@ -36,7 +36,7 @@ public enum TokenType: CustomStringConvertible { case closeBracket case Operator(OperatorToken) case operand(Double) - + public var description: String { switch self { case .openBracket: @@ -53,11 +53,11 @@ public enum TokenType: CustomStringConvertible { public struct OperatorToken: CustomStringConvertible { let operatorType: OperatorType - + init(operatorType: OperatorType) { self.operatorType = operatorType } - + var precedence: Int { switch operatorType { case .add, .subtract: @@ -68,7 +68,7 @@ public struct OperatorToken: CustomStringConvertible { return 10 } } - + var associativity: OperatorAssociativity { switch operatorType { case .add, .subtract, .divide, .multiply, .percent: @@ -77,7 +77,7 @@ public struct OperatorToken: CustomStringConvertible { return .rightAssociative } } - + public var description: String { return operatorType.description } @@ -93,19 +93,19 @@ func < (left: OperatorToken, right: OperatorToken) -> Bool { public struct Token: CustomStringConvertible { let tokenType: TokenType - + init(tokenType: TokenType) { self.tokenType = tokenType } - + init(operand: Double) { tokenType = .operand(operand) } - + init(operatorType: OperatorType) { tokenType = .Operator(OperatorToken(operatorType: operatorType)) } - + var isOpenBracket: Bool { switch tokenType { case .openBracket: @@ -114,7 +114,7 @@ public struct Token: CustomStringConvertible { return false } } - + var isOperator: Bool { switch tokenType { case .Operator(_): @@ -123,7 +123,7 @@ public struct Token: CustomStringConvertible { return false } } - + var operatorToken: OperatorToken? { switch tokenType { case .Operator(let operatorToken): @@ -132,7 +132,7 @@ public struct Token: CustomStringConvertible { return nil } } - + public var description: String { return tokenType.description } @@ -140,27 +140,27 @@ public struct Token: CustomStringConvertible { public class InfixExpressionBuilder { private var expression = [Token]() - + public func addOperator(_ operatorType: OperatorType) -> InfixExpressionBuilder { expression.append(Token(operatorType: operatorType)) return self } - + public func addOperand(_ operand: Double) -> InfixExpressionBuilder { expression.append(Token(operand: operand)) return self } - + public func addOpenBracket() -> InfixExpressionBuilder { expression.append(Token(tokenType: .openBracket)) return self } - + public func addCloseBracket() -> InfixExpressionBuilder { expression.append(Token(tokenType: .closeBracket)) return self } - + public func build() -> [Token] { // Maybe do some validation here return expression @@ -169,29 +169,29 @@ public class InfixExpressionBuilder { // This returns the result of the shunting yard algorithm public func reversePolishNotation(_ expression: [Token]) -> String { - + var tokenStack = Stack() var reversePolishNotation = [Token]() - + for token in expression { switch token.tokenType { case .operand(_): reversePolishNotation.append(token) - + case .openBracket: tokenStack.push(token) - + case .closeBracket: while tokenStack.count > 0, let tempToken = tokenStack.pop(), !tempToken.isOpenBracket { reversePolishNotation.append(tempToken) } - + case .Operator(let operatorToken): for tempToken in tokenStack.makeIterator() { if !tempToken.isOperator { break } - + if let tempOperatorToken = tempToken.operatorToken { if operatorToken.associativity == .leftAssociative && operatorToken <= tempOperatorToken || operatorToken.associativity == .rightAssociative && operatorToken < tempOperatorToken { @@ -204,11 +204,11 @@ public func reversePolishNotation(_ expression: [Token]) -> String { tokenStack.push(token) } } - + while tokenStack.count > 0 { reversePolishNotation.append(tokenStack.pop()!) } - + return reversePolishNotation.map({token in token.description}).joined(separator: " ") } diff --git a/Shunting Yard/ShuntingYard.playground/Sources/Stack.swift b/Shunting Yard/ShuntingYard.playground/Sources/Stack.swift index 27286fdbd..c54c5a600 100644 --- a/Shunting Yard/ShuntingYard.playground/Sources/Stack.swift +++ b/Shunting Yard/ShuntingYard.playground/Sources/Stack.swift @@ -2,27 +2,27 @@ import Foundation public struct Stack { fileprivate var array = [T]() - + public init() { - + } - + public var isEmpty: Bool { return array.isEmpty } - + public var count: Int { return array.count } - + public mutating func push(_ element: T) { array.append(element) } - + public mutating func pop() -> T? { return array.popLast() } - + public var top: T? { return array.last } diff --git a/Shunting Yard/ShuntingYard.swift b/Shunting Yard/ShuntingYard.swift index 97a72249d..201264650 100644 --- a/Shunting Yard/ShuntingYard.swift +++ b/Shunting Yard/ShuntingYard.swift @@ -18,7 +18,7 @@ public enum OperatorType: CustomStringConvertible { case multiply case percent case exponent - + public var description: String { switch self { case .add: @@ -42,7 +42,7 @@ public enum TokenType: CustomStringConvertible { case closeBracket case Operator(OperatorToken) case operand(Double) - + public var description: String { switch self { case .openBracket: @@ -59,11 +59,11 @@ public enum TokenType: CustomStringConvertible { public struct OperatorToken: CustomStringConvertible { let operatorType: OperatorType - + init(operatorType: OperatorType) { self.operatorType = operatorType } - + var precedence: Int { switch operatorType { case .add, .subtract: @@ -74,7 +74,7 @@ public struct OperatorToken: CustomStringConvertible { return 10 } } - + var associativity: OperatorAssociativity { switch operatorType { case .add, .subtract, .divide, .multiply, .percent: @@ -83,7 +83,7 @@ public struct OperatorToken: CustomStringConvertible { return .rightAssociative } } - + public var description: String { return operatorType.description } @@ -99,19 +99,19 @@ func < (left: OperatorToken, right: OperatorToken) -> Bool { public struct Token: CustomStringConvertible { let tokenType: TokenType - + init(tokenType: TokenType) { self.tokenType = tokenType } - + init(operand: Double) { tokenType = .operand(operand) } - + init(operatorType: OperatorType) { tokenType = .Operator(OperatorToken(operatorType: operatorType)) } - + var isOpenBracket: Bool { switch tokenType { case .openBracket: @@ -120,7 +120,7 @@ public struct Token: CustomStringConvertible { return false } } - + var isOperator: Bool { switch tokenType { case .Operator(_): @@ -129,7 +129,7 @@ public struct Token: CustomStringConvertible { return false } } - + var operatorToken: OperatorToken? { switch tokenType { case .Operator(let operatorToken): @@ -138,7 +138,7 @@ public struct Token: CustomStringConvertible { return nil } } - + public var description: String { return tokenType.description } @@ -146,27 +146,27 @@ public struct Token: CustomStringConvertible { public class InfixExpressionBuilder { private var expression = [Token]() - + public func addOperator(_ operatorType: OperatorType) -> InfixExpressionBuilder { expression.append(Token(operatorType: operatorType)) return self } - + public func addOperand(_ operand: Double) -> InfixExpressionBuilder { expression.append(Token(operand: operand)) return self } - + public func addOpenBracket() -> InfixExpressionBuilder { expression.append(Token(tokenType: .openBracket)) return self } - + public func addCloseBracket() -> InfixExpressionBuilder { expression.append(Token(tokenType: .closeBracket)) return self } - + public func build() -> [Token] { // Maybe do some validation here return expression @@ -175,29 +175,29 @@ public class InfixExpressionBuilder { // This returns the result of the shunting yard algorithm public func reversePolishNotation(_ expression: [Token]) -> String { - + var tokenStack = Stack() var reversePolishNotation = [Token]() - + for token in expression { switch token.tokenType { case .operand(_): reversePolishNotation.append(token) - + case .openBracket: tokenStack.push(token) - + case .closeBracket: while tokenStack.count > 0, let tempToken = tokenStack.pop(), !tempToken.isOpenBracket { reversePolishNotation.append(tempToken) } - + case .Operator(let operatorToken): for tempToken in tokenStack.makeIterator() { if !tempToken.isOperator { break } - + if let tempOperatorToken = tempToken.operatorToken { if operatorToken.associativity == .leftAssociative && operatorToken <= tempOperatorToken || operatorToken.associativity == .rightAssociative && operatorToken < tempOperatorToken { @@ -210,10 +210,10 @@ public func reversePolishNotation(_ expression: [Token]) -> String { tokenStack.push(token) } } - + while tokenStack.count > 0 { reversePolishNotation.append(tokenStack.pop()!) } - + return reversePolishNotation.map({token in token.description}).joined(separator: " ") } diff --git a/Skip-List/SkipList.swift b/Skip-List/SkipList.swift index e844f9959..cd832eef9 100644 --- a/Skip-List/SkipList.swift +++ b/Skip-List/SkipList.swift @@ -70,29 +70,29 @@ private func coinFlip() -> Bool { public class DataNode { public typealias Node = DataNode - - var data: Payload? + + var data: Payload? fileprivate var key: Key? var next: Node? var down: Node? - + public init(key: Key, data: Payload) { self.key = key self.data = data } public init(asHead head: Bool){} - + } open class SkipList { public typealias Node = DataNode - + fileprivate(set) var head: Node? public init() {} - + } @@ -100,18 +100,18 @@ open class SkipList { // MARK: - Search lanes for a node with a given key extension SkipList { - + func findNode(key: Key) -> Node? { var currentNode: Node? = head var isFound: Bool = false while !isFound { if let node = currentNode { - + switch node.next { case .none: - - currentNode = node.down + + currentNode = node.down case .some(let value) where value.key != nil: if value.key == key { @@ -122,14 +122,14 @@ extension SkipList { currentNode = node.down } else { currentNode = node.next - } + } } - + default: continue } - - } else { + + } else { break } } @@ -139,7 +139,7 @@ extension SkipList { } else { return nil } - + } func search(key: Key) -> Payload? { @@ -147,9 +147,9 @@ extension SkipList { return nil } - return node.next!.data - } - + return node.next!.data + } + } @@ -157,12 +157,12 @@ extension SkipList { // MARK: - Insert a node into lanes depending on skip list status ( bootstrap base-layer if head is empty / start insertion from current head ). extension SkipList { - private func bootstrapBaseLayer(key: Key, data: Payload) { - head = Node(asHead: true) + private func bootstrapBaseLayer(key: Key, data: Payload) { + head = Node(asHead: true) var node = Node(key: key, data: data) head!.next = node - + var currentTopNode = node while coinFlip() { @@ -174,7 +174,7 @@ extension SkipList { head = newHead currentTopNode = node } - + } @@ -191,13 +191,13 @@ extension SkipList { } else { currentNode = nextNode } - + } else { stack.push(currentNode!) - currentNode = currentNode!.down + currentNode = currentNode!.down } - - } + + } let itemAtLayer = stack.pop() var node = Node(key: key, data: data) @@ -208,24 +208,24 @@ extension SkipList { while coinFlip() { if stack.isEmpty { let newHead = Node(asHead: true) - + node = Node(key: key, data: data) node.down = currentTopNode newHead.next = node newHead.down = head head = newHead currentTopNode = node - - } else { + + } else { let nextNode = stack.pop() - + node = Node(key: key, data: data) node.down = currentTopNode node.next = nextNode!.next nextNode!.next = node currentTopNode = node } - } + } } @@ -233,7 +233,7 @@ extension SkipList { if head != nil { if let node = findNode(key: key) { // replace, in case of key already exists. - var currentNode = node.next + var currentNode = node.next while currentNode != nil && currentNode!.key == key { currentNode!.data = data currentNode = currentNode!.down @@ -241,12 +241,12 @@ extension SkipList { } else { insertItem(key: key, data: data) } - + } else { bootstrapBaseLayer(key: key, data: data) } } - + } @@ -257,32 +257,32 @@ extension SkipList { guard let item = findNode(key: key) else { return } - + var currentNode = Optional(item) - + while currentNode != nil { let node = currentNode!.next - + if node!.key != key { currentNode = node continue } let nextNode = node!.next - + currentNode!.next = nextNode currentNode = currentNode!.down - + } - - } + + } } // MARK: - Get associated payload from a node with a given key. extension SkipList { - + public func get(key: Key) -> Payload? { return search(key: key) } diff --git a/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/Matrix.swift b/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/Matrix.swift index ccfa58b09..324e906ee 100644 --- a/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/Matrix.swift +++ b/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/Matrix.swift @@ -9,53 +9,53 @@ import Foundation public struct Matrix { - + // MARK: - Martix Objects - + public enum Index { case row, column } - + public struct Size: Equatable { let rows: Int, columns: Int - + public static func == (lhs: Size, rhs: Size) -> Bool { return lhs.columns == rhs.columns && lhs.rows == rhs.rows } } - + // MARK: - Variables - + let rows: Int, columns: Int let size: Size - + var grid: [T] - + var isSquare: Bool { return rows == columns } - + // MARK: - Init - + public init(rows: Int, columns: Int, initialValue: T = T.zero) { self.rows = rows self.columns = columns self.size = Size(rows: rows, columns: columns) self.grid = Array(repeating: initialValue, count: rows * columns) } - + public init(size: Int, initialValue: T = T.zero) { self.init(rows: size, columns: size, initialValue: initialValue) } - + // MARK: - Private Functions - + fileprivate func indexIsValid(row: Int, column: Int) -> Bool { return row >= 0 && row < rows && column >= 0 && column < columns } - + // MARK: - Subscript - + public subscript(row: Int, column: Int) -> T { get { assert(indexIsValid(row: row, column: column), "Index out of range") @@ -65,7 +65,7 @@ public struct Matrix { grid[(row * columns) + column] = newValue } } - + public subscript(type: Matrix.Index, value: Int) -> [T] { get { switch type { @@ -95,24 +95,24 @@ public struct Matrix { } } } - + // MARK: - Public Functions - + public func row(for columnIndex: Int) -> [T] { assert(indexIsValid(row: columnIndex, column: 0), "Index out of range") return Array(grid[(columnIndex * columns)..<(columnIndex * columns) + columns]) } - + public func column(for rowIndex: Int) -> [T] { assert(indexIsValid(row: 0, column: rowIndex), "Index out of range") - + let column = (0.. T in let currentColumnIndex = currentRow * columns + rowIndex return grid[currentColumnIndex] } return column } - + public func forEach(_ body: (Int, Int) throws -> Void) rethrows { for row in 0..) -> Matrix { let A = self assert(A.columns == B.rows, "Two matricies can only be matrix mulitiplied if one has dimensions mxn & the other has dimensions nxp where m, n, p are in R") - + var C = Matrix(rows: A.rows, columns: B.columns) - + for i in 0..) -> Matrix { let A = self assert(A.columns == B.rows, "Two matricies can only be matrix mulitiplied if one has dimensions mxn & the other has dimensions nxp where m, n, p are in R") - + let n = max(A.rows, A.columns, B.rows, B.columns) let m = nextPowerOfTwo(after: n) - + var APrep = Matrix(size: m) var BPrep = Matrix(size: m) - + A.forEach { (i, j) in APrep[i,j] = A[i,j] } - + B.forEach { (i, j) in BPrep[i,j] = B[i,j] } - + let CPrep = APrep.strassenR(by: BPrep) var C = Matrix(rows: A.rows, columns: B.columns) for i in 0..) -> Matrix { let A = self assert(A.isSquare && B.isSquare, "This function requires square matricies!") guard A.rows > 1 && B.rows > 1 else { return A * B } - + let n = A.rows let nBy2 = n / 2 - + /* Assume submatricies are allocated as follows matrix A = |a b|, matrix B = |e f| |c d| |g h| */ - + var a = Matrix(size: nBy2) var b = Matrix(size: nBy2) var c = Matrix(size: nBy2) @@ -196,7 +196,7 @@ extension Matrix { var f = Matrix(size: nBy2) var g = Matrix(size: nBy2) var h = Matrix(size: nBy2) - + for i in 0.. Int { return Int(pow(2, ceil(log2(Double(n))))) } @@ -248,7 +248,7 @@ extension Matrix: Addable { assert(lhs.size == rhs.size, "To term-by-term add matricies they need to be the same size!") let rows = lhs.rows let columns = lhs.columns - + var newMatrix = Matrix(rows: rows, columns: columns) for row in 0..(lhs: Matrix, rhs: Matrix) -> Matrix { assert(lhs.size == rhs.size, "To term-by-term subtract matricies they need to be the same size!") let rows = lhs.rows let columns = lhs.columns - + var newMatrix = Matrix(rows: rows, columns: columns) for row in 0..(rows: rows, columns: columns) for row in 0.. String { let allowedCharsCount = UInt32(allowedChars.characters.count) var randomString = "" - + for _ in (0..() for _ in (1...testCount) { var randomLength = Int(arc4random_uniform(10)) - + var key = Utils.shared.randomAlphaNumericString(withLength: randomLength) - + while testStrings.contains(where: { $0.key == key}) { //That key is taken, so we generate a new one with another length randomLength = Int(arc4random_uniform(10)) @@ -29,20 +29,20 @@ class TernarySearchTreeTests: XCTestCase { } let data = Utils.shared.randomAlphaNumericString(withLength: randomLength) // print("Key: \(key) Data: \(data)") - + if key != "" && data != "" { testStrings.append((key, data)) treeOfStrings.insert(data: data, withKey: key) } } - + for aTest in testStrings { let data = treeOfStrings.find(key: aTest.key) XCTAssertNotNil(data) XCTAssertEqual(data, aTest.data) } } - + func testCanFindNumberInTree() { var testNums: [(key: String, data: Int)] = [] let treeOfInts = TernarySearchTree() @@ -55,13 +55,13 @@ class TernarySearchTreeTests: XCTestCase { randomLength = Int(arc4random_uniform(10)) key = Utils.shared.randomAlphaNumericString(withLength: randomLength) } - + if key != "" { testNums.append((key, randomNum)) treeOfInts.insert(data: randomNum, withKey: key) } } - + for aTest in testNums { let data = treeOfInts.find(key: aTest.key) XCTAssertNotNil(data) diff --git a/Ternary Search Tree/Utils.swift b/Ternary Search Tree/Utils.swift index cabfe1b68..97f09fdd2 100644 --- a/Ternary Search Tree/Utils.swift +++ b/Ternary Search Tree/Utils.swift @@ -9,22 +9,22 @@ import Foundation public struct Utils { - + public static let shared = Utils() - + let allowedChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" //Random string generator from: //http://stackoverflow.com/questions/26845307/generate-random-alphanumeric-string-in-swift/26845710 public func randomAlphaNumericString(withLength length: Int) -> String { let allowedCharsCount = UInt32(allowedChars.characters.count) var randomString = "" - + for _ in (0.. ThreadedBinaryTree? { return search(value)?.remove() } - + /* Deletes "this" node from the tree. */ public func remove() -> ThreadedBinaryTree? { let replacement: ThreadedBinaryTree? - + if let left = left { if let right = right { replacement = removeNodeWithTwoChildren(left, right) @@ -155,33 +155,33 @@ extension ThreadedBinaryTree { parent?.rightThread = rightThread } } - + reconnectParentToNode(replacement) - + // The current node is no longer part of the tree, so clean it up. parent = nil left = nil right = nil leftThread = nil rightThread = nil - + return replacement } - + private func removeNodeWithTwoChildren(_ left: ThreadedBinaryTree, _ right: ThreadedBinaryTree) -> ThreadedBinaryTree { // This node has two children. It must be replaced by the smallest // child that is larger than this node's value, which is the leftmost // descendent of the right child. let successor = right.minimum() - + // If this in-order successor has a right child of its own (it cannot // have a left child by definition), then that must take its place. _ = successor.remove() - + // Connect our left child with the new node. successor.left = left left.parent = successor - + // Connect our right child with the new node. If the right child does // not have any left children of its own, then the in-order successor // *is* the right child. @@ -191,11 +191,11 @@ extension ThreadedBinaryTree { } else { successor.right = nil } - + // And finally, connect the successor node to our parent. return successor } - + private func reconnectParentToNode(_ node: ThreadedBinaryTree?) { if let parent = parent { if isLeftChild { @@ -228,7 +228,7 @@ extension ThreadedBinaryTree { } return nil } - + /* // Recursive version of search // Educational but undesirable due to the overhead cost of recursion @@ -242,11 +242,11 @@ extension ThreadedBinaryTree { } } */ - + public func contains(value: T) -> Bool { return search(value) != nil } - + /* Returns the leftmost descendent. O(h) time. */ @@ -257,7 +257,7 @@ extension ThreadedBinaryTree { } return node } - + /* Returns the rightmost descendent. O(h) time. */ @@ -268,7 +268,7 @@ extension ThreadedBinaryTree { } return node } - + /* Calculates the depth of this node, i.e. the distance to the root. Takes O(h) time. @@ -282,7 +282,7 @@ extension ThreadedBinaryTree { } return edges } - + /* Calculates the height of this node, i.e. the distance to the lowest leaf. Since this looks at all children of this node, performance is O(n). @@ -294,7 +294,7 @@ extension ThreadedBinaryTree { return 1 + max(left?.height() ?? 0, right?.height() ?? 0) } } - + /* Finds the node whose value precedes our value in sorted order. */ @@ -305,7 +305,7 @@ extension ThreadedBinaryTree { return leftThread } } - + /* Finds the node whose value succeeds our value in sorted order. */ @@ -333,7 +333,7 @@ extension ThreadedBinaryTree { } } } - + public func traverseInOrderBackward(_ visit: (T) -> Void) { var n: ThreadedBinaryTree n = maximum() @@ -346,19 +346,19 @@ extension ThreadedBinaryTree { } } } - + public func traversePreOrder(_ visit: (T) -> Void) { visit(value) left?.traversePreOrder(visit) right?.traversePreOrder(visit) } - + public func traversePostOrder(_ visit: (T) -> Void) { left?.traversePostOrder(visit) right?.traversePostOrder(visit) visit(value) } - + /* Performs an in-order traversal and collects the results in an array. */ @@ -390,7 +390,7 @@ extension ThreadedBinaryTree { let rightBST = right?.isBST(minValue: value, maxValue: maxValue) ?? true return leftBST && rightBST } - + /* Is this binary tree properly threaded? Either left or leftThread (but not both) must be nil (likewise for right). @@ -452,7 +452,7 @@ extension ThreadedBinaryTree: CustomDebugStringConvertible { } return s } - + public func toArray() -> [T] { return map { $0 } } diff --git a/Treap/Treap.swift b/Treap/Treap.swift index 6e80abfb2..7038e843e 100644 --- a/Treap/Treap.swift +++ b/Treap/Treap.swift @@ -27,11 +27,11 @@ import Foundation public indirect enum Treap { case empty case node(key: Key, val: Element, p: Int, left: Treap, right: Treap) - + public init() { self = .empty } - + internal func get(_ key: Key) -> Element? { switch self { case .empty: @@ -46,7 +46,7 @@ public indirect enum Treap { return nil } } - + public func contains(_ key: Key) -> Bool { switch self { case .empty: @@ -61,7 +61,7 @@ public indirect enum Treap { return false } } - + public var depth: Int { switch self { case .empty: @@ -80,12 +80,12 @@ public indirect enum Treap { public var count: Int { return Treap.countHelper(self) } - + fileprivate static func countHelper(_ treap: Treap) -> Int { if case let .node(_, _, _, left, right) = treap { return countHelper(left) + 1 + countHelper(right) } - + return 0 } } @@ -121,7 +121,7 @@ public extension Treap { return .empty } } - + fileprivate func insertAndBalance(_ nodeKey: Key, _ nodeVal: Element, _ nodeP: Int, _ left: Treap, _ right: Treap, _ key: Key, _ val: Element, _ p: Int) -> Treap { let newChild: Treap @@ -141,14 +141,14 @@ public extension Treap { newNode = .empty return newNode } - + if case let .node(_, _, newChildP, _, _) = newChild , newChildP < nodeP { return rotate(newNode) } else { return newNode } } - + internal func delete(key: Key) throws -> Treap { switch self { case .empty: diff --git a/Treap/Treap/TreapTests/TreapTests.swift b/Treap/Treap/TreapTests/TreapTests.swift index f349e6ab8..d4fc4cfdb 100644 --- a/Treap/Treap/TreapTests/TreapTests.swift +++ b/Treap/Treap/TreapTests/TreapTests.swift @@ -27,17 +27,17 @@ THE SOFTWARE.*/ import XCTest class TreapTests: XCTestCase { - + override func setUp() { super.setUp() // Put setup code here. This method is called before the invocation of each test method in the class. } - + override func tearDown() { // Put teardown code here. This method is called after the invocation of each test method in the class. super.tearDown() } - + func testSanity() { var treap = Treap.empty treap = treap.set(key: 5, val: "a").set(key: 7, val: "b") @@ -51,7 +51,7 @@ class TreapTests: XCTestCase { XCTAssert(!treap.contains(5)) XCTAssert(treap.contains(7)) } - + func testFairlyBalanced() { var treap = Treap.empty for i in 0..<1000 { @@ -60,7 +60,7 @@ class TreapTests: XCTestCase { let depth = treap.depth XCTAssert(depth < 30, "treap.depth was \(depth)") } - + func testFairlyBalancedCollection() { var treap = Treap() for i in 0..<1000 { @@ -69,5 +69,5 @@ class TreapTests: XCTestCase { let depth = treap.depth XCTAssert(depth > 0 && depth < 30) } - + } diff --git a/Treap/TreapCollectionType.swift b/Treap/TreapCollectionType.swift index 7292c5f0a..eeee065fe 100644 --- a/Treap/TreapCollectionType.swift +++ b/Treap/TreapCollectionType.swift @@ -25,52 +25,52 @@ THE SOFTWARE.*/ import Foundation extension Treap: MutableCollection { - + public typealias Index = TreapIndex - + public subscript(index: TreapIndex) -> Element { get { guard let result = self.get(index.keys[index.keyIndex]) else { fatalError("Invalid index!") } - + return result } - + mutating set { let key = index.keys[index.keyIndex] self = self.set(key: key, val: newValue) } } - + public subscript(key: Key) -> Element? { get { return self.get(key) } - + mutating set { guard let value = newValue else { _ = try? self.delete(key: key) return } - + self = self.set(key: key, val: value) } } - + public var startIndex: TreapIndex { return TreapIndex(keys: keys, keyIndex: 0) } - + public var endIndex: TreapIndex { let keys = self.keys return TreapIndex(keys: keys, keyIndex: keys.count) } - + public func index(after i: TreapIndex) -> TreapIndex { return i.successor() } - + fileprivate var keys: [Key] { var results: [Key] = [] if case let .node(key, _, _, left, right) = self { @@ -78,28 +78,28 @@ extension Treap: MutableCollection { results.append(key) results.append(contentsOf: right.keys) } - + return results } } public struct TreapIndex: Comparable { - + public static func < (lhs: TreapIndex, rhs: TreapIndex) -> Bool { return lhs.keyIndex < rhs.keyIndex } - + fileprivate let keys: [Key] fileprivate let keyIndex: Int - + public func successor() -> TreapIndex { return TreapIndex(keys: keys, keyIndex: keyIndex + 1) } - + public func predecessor() -> TreapIndex { return TreapIndex(keys: keys, keyIndex: keyIndex - 1) } - + fileprivate init(keys: [Key] = [], keyIndex: Int = 0) { self.keys = keys self.keyIndex = keyIndex diff --git a/Treap/TreapMergeSplit.swift b/Treap/TreapMergeSplit.swift index 34cfec3d2..62d18d16f 100644 --- a/Treap/TreapMergeSplit.swift +++ b/Treap/TreapMergeSplit.swift @@ -37,7 +37,7 @@ public extension Treap { } else { fatalError("No values in treap") } - + switch self { case .node: if case let .node(_, _, _, left, right) = current.set(key: key, val: val, p: -1) { @@ -49,7 +49,7 @@ public extension Treap { return (left: .empty, right: .empty) } } - + internal var leastKey: Key? { switch self { case .empty: @@ -60,7 +60,7 @@ public extension Treap { return left.leastKey } } - + internal var mostKey: Key? { switch self { case .empty: @@ -79,7 +79,7 @@ internal func merge(_ left: Treap, right return right case (_, .empty): return left - + case let (.node(leftKey, leftVal, leftP, leftLeft, leftRight), .node(rightKey, rightVal, rightP, rightLeft, rightRight)): if leftP < rightP { return .node(key: leftKey, val: leftVal, p: leftP, left: leftLeft, right: merge(leftRight, right: right)) @@ -96,16 +96,16 @@ extension Treap: CustomStringConvertible { public var description: String { return Treap.descHelper(self, indent: 0) } - + fileprivate static func descHelper(_ treap: Treap, indent: Int) -> String { if case let .node(key, value, priority, left, right) = treap { var result = "" let tabs = String(repeating: "\t", count: indent) - + result += descHelper(left, indent: indent + 1) result += "\n" + tabs + "\(key), \(value), \(priority)\n" result += descHelper(right, indent: indent + 1) - + return result } else { return "" diff --git a/Trie/Trie/Trie/Trie.swift b/Trie/Trie/Trie/Trie.swift index 4321479c3..7ff9638d7 100644 --- a/Trie/Trie/Trie/Trie.swift +++ b/Trie/Trie/Trie/Trie.swift @@ -18,8 +18,8 @@ class TrieNode { var isLeaf: Bool { return children.count == 0 } - - + + /// Initializes a node. /// /// - Parameters: @@ -29,7 +29,7 @@ class TrieNode { self.value = value self.parentNode = parentNode } - + /// Adds a child node to self. If the child is already present, /// do nothing. /// @@ -92,7 +92,7 @@ class Trie: NSObject, NSCoding { // MARK: - Adds methods: insert, remove, contains extension Trie { - + /// Inserts a word into the trie. If the word is already present, /// there is no change. /// @@ -117,7 +117,7 @@ extension Trie { wordCount += 1 currentNode.isTerminating = true } - + /// Determines whether a word is in the trie. /// /// - Parameter word: the word to check for @@ -168,7 +168,7 @@ extension Trie { return nil } - + /// Deletes a word from the trie by starting with the last letter /// and moving back, deleting nodes until either a non-leaf or a /// terminating node is found. @@ -187,7 +187,7 @@ extension Trie { } } } - + /// Removes a word from the trie. If the word is not present or /// it is empty, just ignore it. If the last node is a leaf, /// delete that node and higher nodes that are leaves until a @@ -210,7 +210,7 @@ extension Trie { } wordCount -= 1 } - + /// Returns an array of words in a subtrie of the trie /// /// - Parameters: diff --git a/Trie/Trie/TrieUITests/TrieUITests.swift b/Trie/Trie/TrieUITests/TrieUITests.swift index f3da2a67f..acb3b1756 100644 --- a/Trie/Trie/TrieUITests/TrieUITests.swift +++ b/Trie/Trie/TrieUITests/TrieUITests.swift @@ -9,12 +9,12 @@ import XCTest class TrieUITests: XCTestCase { - + override func setUp() { super.setUp() - + // Put setup code here. This method is called before the invocation of each test method in the class. - + // In UI tests it is usually best to stop immediately when a failure occurs. continueAfterFailure = false // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. @@ -22,15 +22,15 @@ class TrieUITests: XCTestCase { // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. } - + override func tearDown() { // Put teardown code here. This method is called after the invocation of each test method in the class. super.tearDown() } - + func testExample() { // Use recording to get started writing UI tests. // Use XCTAssert and related functions to verify your tests produce the correct results. } - + } diff --git a/Z-Algorithm/ZAlgorithm.swift b/Z-Algorithm/ZAlgorithm.swift index 9bef69687..969a3599b 100644 --- a/Z-Algorithm/ZAlgorithm.swift +++ b/Z-Algorithm/ZAlgorithm.swift @@ -9,34 +9,34 @@ import Foundation func ZetaAlgorithm(ptrn: String) -> [Int]? { - + let pattern = Array(ptrn.characters) let patternLength = pattern.count - + guard patternLength > 0 else { return nil } - + var zeta = [Int](repeating: 0, count: patternLength) - + var left = 0 var right = 0 var k_1 = 0 var betaLength = 0 var textIndex = 0 var patternIndex = 0 - + for k in 1 ..< patternLength { if k > right { patternIndex = 0 - + while k + patternIndex < patternLength && pattern[k + patternIndex] == pattern[patternIndex] { patternIndex = patternIndex + 1 } - + zeta[k] = patternIndex - + if zeta[k] > 0 { left = k right = k + zeta[k] - 1 @@ -44,18 +44,18 @@ func ZetaAlgorithm(ptrn: String) -> [Int]? { } else { k_1 = k - left + 1 betaLength = right - k + 1 - + if zeta[k_1 - 1] < betaLength { zeta[k] = zeta[k_1 - 1] } else if zeta[k_1 - 1] >= betaLength { textIndex = betaLength patternIndex = right + 1 - + while patternIndex < patternLength && pattern[textIndex] == pattern[patternIndex] { textIndex = textIndex + 1 patternIndex = patternIndex + 1 } - + zeta[k] = patternIndex - k left = k right = patternIndex - 1 diff --git a/Z-Algorithm/ZetaAlgorithm.playground/Contents.swift b/Z-Algorithm/ZetaAlgorithm.playground/Contents.swift index 395122af0..44faf6790 100644 --- a/Z-Algorithm/ZetaAlgorithm.playground/Contents.swift +++ b/Z-Algorithm/ZetaAlgorithm.playground/Contents.swift @@ -2,34 +2,34 @@ func ZetaAlgorithm(ptrn: String) -> [Int]? { - + let pattern = Array(ptrn.characters) let patternLength = pattern.count - + guard patternLength > 0 else { return nil } - + var zeta = [Int](repeating: 0, count: patternLength) - + var left = 0 var right = 0 var k_1 = 0 var betaLength = 0 var textIndex = 0 var patternIndex = 0 - + for k in 1 ..< patternLength { if k > right { patternIndex = 0 - + while k + patternIndex < patternLength && pattern[k + patternIndex] == pattern[patternIndex] { patternIndex = patternIndex + 1 } - + zeta[k] = patternIndex - + if zeta[k] > 0 { left = k right = k + zeta[k] - 1 @@ -37,18 +37,18 @@ func ZetaAlgorithm(ptrn: String) -> [Int]? { } else { k_1 = k - left + 1 betaLength = right - k + 1 - + if zeta[k_1 - 1] < betaLength { zeta[k] = zeta[k_1 - 1] } else if zeta[k_1 - 1] >= betaLength { textIndex = betaLength patternIndex = right + 1 - + while patternIndex < patternLength && pattern[textIndex] == pattern[patternIndex] { textIndex = textIndex + 1 patternIndex = patternIndex + 1 } - + zeta[k] = patternIndex - k left = k right = patternIndex - 1 @@ -60,28 +60,28 @@ func ZetaAlgorithm(ptrn: String) -> [Int]? { extension String { - + func indexesOf(pattern: String) -> [Int]? { let patternLength = pattern.characters.count let zeta = ZetaAlgorithm(ptrn: pattern + "💲" + self) - + guard zeta != nil else { return nil } - + var indexes: [Int] = [] - + /* Scan the zeta array to find matched patterns */ for i in 0 ..< zeta!.count { if zeta![i] == patternLength { indexes.append(i - patternLength - 1) } } - + guard !indexes.isEmpty else { return nil } - + return indexes } } diff --git a/Z-Algorithm/ZetaAlgorithm.swift b/Z-Algorithm/ZetaAlgorithm.swift index c35703272..e60c1617f 100644 --- a/Z-Algorithm/ZetaAlgorithm.swift +++ b/Z-Algorithm/ZetaAlgorithm.swift @@ -9,28 +9,28 @@ import Foundation extension String { - + func indexesOf(pattern: String) -> [Int]? { let patternLength = pattern.characters.count let zeta = ZetaAlgorithm(ptrn: pattern + "💲" + self) - + guard zeta != nil else { return nil } - + var indexes: [Int] = [Int]() - + /* Scan the zeta array to find matched patterns */ for i in 0 ..< zeta!.count { if zeta![i] == patternLength { indexes.append(i - patternLength - 1) } } - + guard !indexes.isEmpty else { return nil } - + return indexes } } From b718f04b4be46ebe9d82cc1d18264d92b12be0a9 Mon Sep 17 00:00:00 2001 From: Jawwad Ahmad Date: Thu, 4 May 2017 03:53:31 +0500 Subject: [PATCH 1013/1679] Fix violation: unused_optional_binding warning: Unused Optional Binding Violation: Prefer `!= nil` over `let _ =` () --- Graph/Graph/AdjacencyListGraph.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Graph/Graph/AdjacencyListGraph.swift b/Graph/Graph/AdjacencyListGraph.swift index 57fd75fed..b58ef6417 100644 --- a/Graph/Graph/AdjacencyListGraph.swift +++ b/Graph/Graph/AdjacencyListGraph.swift @@ -78,7 +78,7 @@ open class AdjacencyListGraph: AbstractGraph where T: Equatable, T: Hashab // works let edge = Edge(from: from, to: to, weight: weight) let edgeList = adjacencyList[from.index] - if let _ = edgeList.edges { + if edgeList.edges != nil { edgeList.addEdge(edge) } else { edgeList.edges = [edge] From 9a363c7082c2acbc6984864b67ac6c20ac911cdb Mon Sep 17 00:00:00 2001 From: Xiangxin Date: Fri, 17 Mar 2017 00:19:36 +0800 Subject: [PATCH 1014/1679] Minimum Spanning Tree (Kruskal's and Prim's) --- Minimum Spanning Tree/Images/kruskal.png | Bin 0 -> 22083 bytes Minimum Spanning Tree/Images/prim.png | Bin 0 -> 19053 bytes Minimum Spanning Tree/Kruskal.swift | 31 +++ .../Contents.swift | 93 +++++++ .../Resources/mst.png | Bin 0 -> 19209 bytes .../Sources/Graph.swift | 55 +++++ .../Sources/Heap.swift | 227 ++++++++++++++++++ .../Sources/PriorityQueue.swift | 58 +++++ .../Sources/UnionFind.swift | 61 +++++ .../contents.xcplayground | 4 + Minimum Spanning Tree/Prim.swift | 45 ++++ Minimum Spanning Tree/README.markdown | 102 ++++++++ README.markdown | 1 + .../contents.xcworkspacedata | 26 ++ 14 files changed, 703 insertions(+) create mode 100644 Minimum Spanning Tree/Images/kruskal.png create mode 100644 Minimum Spanning Tree/Images/prim.png create mode 100644 Minimum Spanning Tree/Kruskal.swift create mode 100644 Minimum Spanning Tree/MinimumSpanningTree.playground/Contents.swift create mode 100644 Minimum Spanning Tree/MinimumSpanningTree.playground/Resources/mst.png create mode 100644 Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/Graph.swift create mode 100644 Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/Heap.swift create mode 100644 Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/PriorityQueue.swift create mode 100644 Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/UnionFind.swift create mode 100644 Minimum Spanning Tree/MinimumSpanningTree.playground/contents.xcplayground create mode 100644 Minimum Spanning Tree/Prim.swift create mode 100644 Minimum Spanning Tree/README.markdown diff --git a/Minimum Spanning Tree/Images/kruskal.png b/Minimum Spanning Tree/Images/kruskal.png new file mode 100644 index 0000000000000000000000000000000000000000..5172f180fda8dff8666a4a38f08e675311c515dd GIT binary patch literal 22083 zcmb?igbz4h8}O!szbqoV1j5cXxwGcY`!Y=RjJd1f)R)1qp$D^Y=G= z=el;iJMVMOeeQFgXS?3*-4vAMMMSL>&{I%vQ2trye~-}r4xvad^q&n54kD1}5h#fN z4#*?&8PbsF{(lBRL4l#5C&FBJ|!fx}SXc_?r=3j7~a6a)kX0YgFLp&;N$+W&z6K_jt{ z$;fELzdHX627%;3AaDo-@vkh>gTWxMJO~U9fg%2}KrZINAbEL^JUAo|@sAWT77l~J z^B{0I1dc#*M5aOzFbE{5Am;EBn#vsJP!tk!{7*H_efI6SQsJ?hJeEm$o7zWAZa4A zk#ZpWN0LBxh-8ffLy|_aM1~@HAPXb0kOsi4;becv_{_@~I3C zom$hW){2=Nu+4O#Qd{M0fr#hn=2TnNr}t73Ksx32>V-1J3@)?j_L`+C%`)Y8${%W1 z>I~Z)x416pP;H4*J`HBAg!GY$77TKIn-rkGkPWb zz0o-OPj2Mc(1(_96R9i#qZC{`cpm}ZgY-~we@{B|VI7>?Y=QiTx&`at`rY*yNM6^-d`(ek`gFZ|`RU zT(rs&gZRBvcVQkXSQeiK`u~=jFOV~c;C~9tY5ic+NAd2(^>ox=$*>;{YV@!n@X{dP zlT*!R!WV1Hb4%)pv~44R5>~w%4R*iLW5MK?!C-;hp?`{^@l(u!x~okRK^7`dtflAQ zPLPD4lLLT;iSEbWQlu~)v;y~LDW>sPmNOX?WbYL;B~>?L(j<#(a#F+F_$f2O`JQx` z;-#ZG4|AngZ?hbqHizWWg&fH9vx)Lf=%D$dQkL>hn~*WO)uHs%c+p)JlVq=7iiah! z>^=0^4me&KwAwK8)wh{+imPsoK@N1V$PZ(AFD7o;3JC2m#vQoywu|GThA&SJ(wvDA z`-EKaE~p8TY3#bHEZ}ev?Ej_fWZ5$f{Cu($Fss1&-=FKM1S0@ z#H>t>H!h~zv-c(OKW0uo;?Ibww)C%wV^Rotn!zna+Q>2MS&P`m`aonVtL*wG{=v)y^fnhUO{_ z_owv+w(K49+_oDt=Id5fQV9qZ^Z6sKzZX*Dw`8ssc4NgqB=aHqA}PUBUs5H7t1R!k z%a_&6X!q|_d!ZbJ`<>g%z@Q&<{wZ@CzY6ZCOn|K31@w{0`X->`j2Iu0w|^L5J6mW| zF!wVQyke9v@-kj~4e^inxW~k?BF!flp6F1+c6~Bt@D@6ukH22~)m|q8qmik&j7s*r zgl@iO(6b(xy#*2h3AgYB^OURm%N}=%2Jx9B$E)WEVhB)`vV|F)Z4n|&Ci_sSFJrYM za{9noP~ZU})6;xOe>kiuTTVfIDlH2j$AT}e%g=OcXh?*C#u0t1BJSsheHAam`b0MB zhlZN8smw;d?d+6%r2HvzJ|?`5^Wrsld27C2u=lUuRPc8hdShP}8XD%yv{YJ>mE~cX z@kcFjHRn8Z&n_zXEq=^nZz{)+^eN9MYjHZ+O-c%nhUN!8VZBiNNAur9A&M6Ue58ek z!FG(Hcf7W@=oM=MF{SmWmqB*F$%rUOr(iEh6r02n=MK^2WSPquEH~agU=zo4TYKbj z%!gA7$AWA)#zBEz#I!U5_!VQJ)c9J|=Rb7DUBAPvi>FH0_hk@Fw%SKI(?clv9wQ#)v{qD94m=G-tbU!)V**RQ>QL}mr(L8?9a`|u+Z_88dgRK z-Cl~VXkDh1SOL`I**nt4cDpPs)HqsMT6pSV)L+tlpq5mv3L0KG>0+V%A0Jhzr*BnV zrU$ZB$}1BbX^j1Q&z$S;DCitXG67+$e>!{>+ucg|9`?(y&+b5hS3{b(R^vuSx@8%=OxuzTm&93hDPnJzX+#B$CH-oCDq$j2~33t5@Y%RnRm`( zhU=4)q{>^?(qG;;$x?e((`PzL%QMwYqmaeBOEKLv9xG%aU^s8s`fX3A+204 zb7-q`7^SD?7F}tOJ`zh?A|{R>bfkEl7ndCL;ln0?bKH89-(0)E6BPFHZOIcT%ABCb zFv{ba!NaRMsa$0jNP}VK%5qrFV=U0&a>N5J&e9R`L=SMN>;MHr*!XkTqqyL!I2rP04DfP5}gxPHsaWV|}Uo-uf_4Am3jXWp6D=`X5eLyn$X zQHDQT!j@*D{-M_3kytK*va&w;L;Y*sa?ufjvG%zSjXvM$xn?_IxDfKD7`1b2u}Xn% ze744<*>jkf80QQLlQ8c6xueP7b+Np|)@qp~8k@fxI|MhD)nW1J6~&9h z|889*clI5r{q*1XyL~&?IdC)kGx+b{uPB6FgIMYp;WQ6B*cx5K6mu8RVh_8Zl&(<& ztloH&hds(qUE{)Ym&pMS-xvwICl%Cxr58Nxb09Rjrw!(QW%oWDfK$5RuhoC&`_Qs* z5RT&08hk7X2kWRnNHDheV`)MK!h%YsvDBu7tmKVh%76{R+K zZk^$xihYiF^`|nY|4bxiPry6yPc$v^5`fz4OC0@pQ{?V~E``{7nB4acNaQgWE?#{W z-_@1z>6ydxSi>(re4;>f@;Tl5exLZfmQBZ@iO+ksi9Ed8oJ)iv-aJUrf0a4B_xrJO zF19Fa@iu}IoxEbM?-*a;`T!Mj_C^>NPm}KL>e4HwV$H|%5JHiNDD&S~{Dm>@?|plw zgKx{8KUr)LTr2Z_yqOhN_1SEmN zWuUyDg|+yOLAN`QMFHT36fc1y@p7xPBP&G{8_Dc1C*m-|+F}7GZF0i&2!Y-3wpK7W z6_7+!&m;pIIr#Mo^UK(0K3#FFX_N^Z zB!7y7GbtkyZyA?l=t#X-JcNmEG@lh=OZiuWQjaK}nz`ne*jU^NPuqf8a%G$*L5C&s zb-6TZ)$;IE=X#<lA|lOsL478Z zEHBK8sT2Eg%#eK{CCA!;1Cqja8-14376 zit%|sAAep`Gq`gEPdyYCzrY4A6{^#w^dbWGOl1fD0*98MtvBOX&vQefdECGXW1QKX z>@~2P<-V9nNEM|Zb{+7JU%|)z_ z@3TMifJ7<$i56YT@>q?rSI>q8HWUO@_Ng)NIg}vu`5gEm^YOE+Ss18no7e^GD7aOE z=H6~X_x8L@J@_p5X>?^2rIy$g@`Zawc=LC_jTmX}_0kS(tT*n2T~;|zY^)`BLJ{l& zTU0_WP0BE#_@Kes~$ z8OHM+uYw^Ku$OlT3#GsVx1x#s__qA<%{zFow3m7>`Gg!at=)jJWR>ChRYGy4*{5vp z9cg`|%l|4-fa7T{tH@iZ!5-5^9BD;FVaeZwR3?~SqDh0xH1ThC02_mNK9(=*tADOC${J-<{7xVhCLa4D z`(VW#qey;tlln%h$>|xUGrz^yAO_mHMYl+dDr1vdDC6UO6JVGc#fCges$N2{i8q|4 zq!>fA4a41C42v85O`tB}OXQe8?xf?(kN3JmUosujn&@OOn!)%YjtLw0QpsN=H?c|V zlwsQl9UJs@fs(su+3q%++xSRpNHj>kb4dfz;q8&zCau!$Lkt8D3W+k~bD2;Ek21W; zkm>4Z`a?{ifomn5(Y8Zm__7S6r5ToOuOZ_k#tN};`0`FCq3lixtXA6$Xu~1SPt;um zyj3Lb0TQ7eQ{;mcr2Q4cq6mZ2>0gse8hj)B9hTy(Wfr6;fK6;n3Sf(20!M|4C+*?= zzSo_h0-B_%g6FZ0@?uy}*=n%}Lr=Tkl=Muamv!#+tb0hu2-?h+qDAdcWvj@mN>L#4 z%8Jr^>ldkCR2GYRC^HUIhc6HoFvcVkV-5a&KKz$!uLfrk#u&$4P9{KC=8NkUz#D+b zD(SDI2t54&>`o;`rEkZjaf+dF^1+QlXL5E&U!Na{xw0K~Qb|9gN(b8&tFI0cfKu-o^<(P6`Y!KvZtbGh5YyrTrVOAmG-*a+$a@@MYTFa ze1{CU7dmOF>XUylicJH8SvASdpLrXBHjbVNI~ygTl|^K?iHdb?vk0EG$)111qg(3b z)ft?lZr-3MKBpFz4c}8T&nb}5RgBd zLNI<>-p%E$Y(YaU`#!=zFHiMG=F?w1NtgV16QVHy6Mj%N#ftAofKKy;U_RZvrc}Ty7jYTv!w;PxxK9-O*Fm0l6px=piIh5vOfI&|l;ZhI2`^#SA z@0Fa7$PM-!=a_BRzW+jZS5w5zbzW8o!PQp=w*S@SN#P z%xcQPi3ZG3-_to#>UBxl@VYS)%Lpms6bvpAXwhZjg;te(He_TdO*B-wJl^A;gX!6LI;O=Xg9{ zR&3Q%hLbN9N7EYP=S&c9Ck>A;Ir8-{HruwFUdHb&ws75Ae#>M9ORO2#ojfBLUZ=HT zM~}!^tou@s1b;?JwECzBZ*FZ@N-;cGc1O+Pbw5~mOK5Ssdo~kYXm(&#C#=&~d;g zt??L8HJtXtH>W5Jtay+&aG0Zhg8usCoqAx#z)A3{(~z8#Vm`Oh}yLAu2*&H8fA72vF zujjRIsq2Cg32ReE)y4QSSwFn!?^H4%LU)W)+G}r0eNV;*3&0aBn9uQ192xqE|FfYW z##h|MWW<{AWSsBNs>i$AWJNbzy*XUmq!{?P3~gQ<@5yJSM6qg8Dse#@d-zQ;tvO7y@+1*? zJI_EXL-a_dgQ~J2K-T%RCF73GltHs06@R7RVG|!u_*3-Di|=#Uu|h7}qedih>P39t zH*YDAiY3+XxdO zhs)LvufHHy(;mB;tqOgEpW7Y2KYwA+8aB@j5&aaRGIl;68-r^WhoYXH^yg_v4nxzz zEoaMYA4RvVsrDq&5z;M!4dLe}@y0gJHu4n*h>vzDR@JRaJ$s{+E$rFlN%?sshKSrO zSajE+gqr2|641A%Kf`u5NgLUP88+^*eL*9fCtD)cms5m$xKY-fl@nH76xnClUlv1@ zr^5HGiC;>qfhQgPXTj{h3XT~Uu_M0~-{rQx=|-(U(-gdAFK?Cx9{JBmcRu*mkLU^l zh()x^>ebt-8Hx;gps8z^it{e2VF4sl(R|u3k74Y`qxb&D_RR3rh&Oa35!iJG2?i z3oy?3Ch?@~KL>Kj*E`@aB!B?MA6Ok5=N)v3Txxqsf2;8uR_AdD%opzBk594|R<>(0 z(`Z1`f2@zbG_~6lVqSg9lV@?GqPdZBIqZEi7)Ie#*=489%p2X8PeeYT7qB>8t9kft zJoz(MWo15km1t60AFFmf5$s%Zw-G}_JuhF4r>JuyrzXs9z@4JdnS_#O<1@qJs2hi9 zK4@_b;#R?l?@+95*V7#L$v=Nl9iejFd;)xA{IJZa+TP<-SeksM+A5NtSTS`jwHv(` zTT4=Ur9H`4ddgKQui%THaW(aK&tBE}v^TjG0HH=pw z>^6QLFLKOzP6s3s7~U|k*M6v$jM6GFDSa>a?3T%a*~j5-YWo8oi#&ng3AAY<<;=SX zPRQ?6%RrMCI3R8&se98e9}@hRw;zkp?&s^e;3otYTr&@0yCtR&HYEbjJU$rH_ABOW>7aH+sqA->-6-uY>A~9(N-|q3*_V_u z)T`iEUU?-;isb|7>mX*@J*ybSw-hAPpJD>0c8Rhkhgta+;!xpMB@UX?ql7*n{BYg+#T4($C?yHJrusG3)>)pw5t-aM5L;_h=dZOs>MKB90^m zQ-;skU2^F6LrKfv5~jbmALL#LLZFu0V^1lS zU}1dT!z0lQt^5Edz;Iatxw1}88m%rmX4bRDy%1F-RaMLJ9?F0ADZPat4w{M2dJxCa z78Rhon|mvIXha#of`5l7qgrl1z;EkTQ`uc~@;kA9_OVM&y`PWQM0el#;gV~qTrF}6 zprt2!LipM?j?*1A!z4c~J0Nw8K75^Byjyf$Z0{mC_;#Ll<9JjTTSt~H9#=838yaRD zD;S@EJvsNg)xIc7&E;}}F4rLY6ChTO?yapHPLDPf!9_5Blp;}1tY*LJY>BASq@qx@ zcHqN4X)Wp$cgDnX7`Pg^7O1GP^oP{I7>jvv5bmT+Og9lrz*KFC#w{5U&RZT{V*@43 z&zuIsW38xtV=)}`9r9pnVXw-=pj@?9%J*v{IEoDw%0|=LZ<3pIh+0mFM!LrMeznQG z{7@_vv>GYjK2wfx^Nbc;F4MP>2NvilIXOHGY0d2;KaYvX0iy-*xtv-2K`n$5Or%tf zf)n;qyt7t7ttR=d69aoYov`+WPdn$8{+r8Z<~Zx0-)t+DyeJ>1SM%j+zeTT8_GgV^ zPk+xBm+VeYFUr9*^`Zwbzk7MCNXc=IRWWMj z$N5Lk*ct`VB*a*hGn{)xmQf74u)OnCzUOQfFcRy&UAE-%?xw)1TH=XkdJe##?%yS? zvUXTm(^)(qw99&?Ki#5uJ$+4A(;8FvH(*jg@NeORAg+9`K#D`hMbY>9@fWT86w~Z& z;&EV{iX=P)UwE66={@w8X~?!D3X4U(ZF7W^^j&H}{S^_ZRP79_PS}f3(`^wd<;+C? z>C8$1M-gk4=9gK%;&z^|%vx+*-7V-TSASA32@Iw}>YY~>V)Kw;T()=?r53;LMznhRul^yJ=O za#F)|ZJwAWnZM@JDXz2S{l3RtdaWRTioZ-gEmCH*1ZN36#d;9g`-b@wwKCQb>RZ3X z5=_ruCl5Sv&NC9&Os5_rM;na!)MYI^wX^r1-9)<;a=$g7QEq=D40!Bb{5`qfDEi0~ zrj{W2G+59S6FbjQ+D)$&MfeV9i(PR>afRrZFmP~f&{5$*ZOv84qZZ?xaY`)5cI2D- zDhcM9hLQu4uL`qoo)Qw?tapDN_G|;&2-lJKS#I(P70J-Y7sd4N*?jbyFI(V!XUw5) zwuxZkC{aAjWY(LV5((Htl>Hw2+zY+)x#^&!enxUf>c#!jA7AwT-DJw+WedZ|I)wMe zy+mMbSL%mST#>^`<-p(ek3mDN9}l)PR#v`AugO&HAJ@NB4|8h0uS_dC_@U5ujXtQP zGY~;M&=~+Gb+6DH=DxELCs6v>NHmCQ%M5&g+{$EqL`%GA1BDDG1*}CrUy8%#k>qA zEu75tr1a-d`~c|z>zBW9qzA!J+?pisIvgx<4o#y0jy@^yRU29#!yygcQ5i^cSQG(y zU^pvact$G2kT^2(tpjm4FznV$;+259REbF~eO(~48$Ke{E+Np)z(?POja{Df>G0smk}`QMjsP~s6&J@nb(v&n+l}gLNQe`~%9(`AGre>b zdV41z9^r+`S#Sr2T3a+}7 zA7&;$oyj-3EB2{K^>E06n3A>w6zic(%+lq-!3w6XKlD%H`? zP*$9g(rZp+a^@6k+AKhDr4L?2sruD()8vP3$fpI?@eLB}bzRy|tNXZrGCxh2&dJ?>`V~2s{7`vx zo^O>|vhF3mc%?>vS~>vuG$=9)0?z*~FGV|GsgGj;Cw`iaC|>=Yu(Lk*^-3wySPA<> zoH~EnW#FemkS0iJPWy8HLs==+bsrILA}k&B=ZcMZcLCEx>BlnL)0N693F~e5C%9L6 z5uk*2tZa`|3uB8^!eKPVP!Ky^`@Lzxw%{y}_9ENZr_)gdgzNp{Rk^m9zbZwL8qbH! zbxXEGQ=NlAEu1Vcy)=hR&-`ELGt!!cX%&r2p2eGQWn#Q!m|L$H@bO?AfaQePl=e}& zck^`jbCTEEg4ZllwmJ$COJUTyX@RPjf!Ziux&x^*4#ho6_Wl4-(L5AJkpJUFyaAl~5ytF-4$P$}9aDPphY4^p%TRLdf|lm%o;|nTDtY(J>2= zVAwcK;1Wx%M#N^{D)%ctA>7z{oR44~b?Aus%4ZN$JmR>lGK7wyUUYs!q;%i$^Gnq} z@yJi^;qad7sZtUKOc^Isc?pVd^ig@%@VMSI?$j4vN4dlGc>7rI15M#W=jGe!lh&Lr_k)w?a~geO)=PtX>GWSx7nXt!VdS$yXf-^@cAQbPVmYQrL;OQH~oVsGHKG z1HEhcLk-&d%=+QF8%+ns54OuO&g=QiCMW_-U1O>@z5256CMGICSbFP|a#@@0`8Lji zFBeTO(6`DkqxMl z-(>80i!%;yws+n-!?4gQS^WhuKRGX7nZ>z%i!(K!G2XYr;k7*=sBd$%{ev=!85;Ii zMi@oEwYr}gage!Qv3b9e`ZcoetFZ-mRAOwl4_n8a4hobD*apjPcNCZo*;`l%8Y+LW zD9n#$&)pV$`!RB|w(E=JO2r5!GfxV0>+8T>Jud@EQmfHrv#%pN_E%=HZi#y9>4Y#z z?-{(0BwNmj#bGWGuIkAHJq>7|1tZ=!Am=0k%hVERwOw?PC+54eT%de&Mo~&sD@~$- z%Qr%7W*v*XsS2V6iBetP_K1&uJ2ti&R}sMC-fzR+K6JKvYF448AN<*x5aTk2GQC&C z_!-oKrRR@FNxk~4gAJ%IhmT|Z6t*=qZ{jcv6gey=J?EEKw|Uj7%2$~?Kn3wVYrHD% zi;*&8!JO7g*Eb>0O5`snINlsIv@1d(rlp!hqaRE#q;5wsvXDKX%4UZve&t+E#@jw!z|Boe?5{g8}05Unf%AqwGuu48OH9vPag5DS3Yk;Nbm^XFhPXK@?oW4zp=L z0U<=vyz{nCA)tc|mVAak+GC^XrXe%&4!~0PZCGgN8)q(H3`U^8=7r5;cPR;W_ z$ItB6#>`IU1NJ*dsMCQ>YH^tn@-Uo3oMa)}84XX63#w*aH1kgE9U;;x0x?1qe=~ zyv;&*PVSHG;_!P8M-IQXpKJP^3(G2^Jv!Axo;9@T;VuHVA*YySWi(`;I_6GTFs(VM zPfL0u7AsS&L245asNBl(%Bu-PD4TMP9m^*C{BpN9_`Bos6B|GCfp%j;?<-uJ>hIy% zY$4$Ds+swgjw6@-^X;P4_vEDlJj`hHz9{&}wK0@MD1@8_+j!k%2h4QxHL_hIi|3# z#j7_EW1XY=X%q!A<%2lpj=0^!{zg}7#2>w0x-zCQEu7AmTmt1+-mD1vpUsCC&4C(q zFIY%?E&^GZ#{P%`r!;l$e#(dIo5{J3>$g|Rf8>~T?Hf=aQ*bW;RU>a13C+$+G!9Z@ z4c||hDlJ|%B+RA}C{VnvLC}o-;t}3ht%T8j);6W z{*!RbZxMt$kl*#bvZU|g_c#HJQGem9_<3SBtDMBuB*5!OTPh9PRk5n8;iF5T;<0n9 zrflhz65(6OAAPMR_q9m$nb-K`zeV%i zb2hKrY5ydhU*CMu0%2WQcPhgSCT)D2xnBMT`}{HVdHYNKH(%jTrz$O1EYCLxY2Ih1 zFR^@vIc|K!ZlEKcI_w$^m+r1j-l`fm;^a3m%Rl|zybb(pA2hM$-+7~UbmM#UHn?;2 zZH!gDl~=g%t0+RBXkk;ts<-b}vM)}d@9!74@m1!DRlZ3+#R*5Zkq@^qgm;NCw`m4G z8H5&@SVZ;)cj<5Z(nIdv^1RosxXbUnE10+|{CxNB=&tDI?mgChF~xn!v-?uv`!a?5 za)bMd*Y}k^_f^mRQ&R3E-}~n_-49vb)qOQ>XnNE5p0(!YUY0N*k0GFz;%}>hS3BbV zhdrj=OVJM$s?9NfyZYmfC@;GWX8c)*u*U;9e~u?;rVLp8&2Qe*6A&MIqqGPHcB0vh zS{UVg5`Odyto$}IRrQy$jBqAr*5ZnWX!*feBj?k{he*XRU8#aMIiNYur22@*|Q2Mz_| zB+gFb?KF{&*G%4G)!e;#^BWKwf`&!RW3R~wjCc~yHZm6@NNwF@lA5_X{(OLg*#4W29Tda*vvtyqE`+;N8+wU;^+;HJCT^ZJ<_Pl3SC zv9zv>=-DVPTCVHklrPKis%*i5#vg1In?>@9Ih3{RykMDhSn zmviD=kwKg5_k0@%vG9_CMwh>THp1bP)ajr2(DCWC>RduK8E-rq5b&3mnzed9O>U|;BiwsG80w87e`8nzF8)JsJ zJBoN<oU%QVJ6`PO>-|u(!Pj?L)Vm-MSD{#zqwGkd z5~XMswHP6MwOqlj%a>_Cr0|qcQ?I57q~!@A?lh_}Yvm|6B^hDXmC+s=Hk|N2R|1tx z@H^`w9912FU`QhJ-I->0sMsdsgNv2) zZ&mhe?vUH4vYBatw7upALgZUT8|B=sMhmY)f@hl&{ttWYKgAfPEKk*~%|!(yVwbfT zOw%^0 zRJ^B2l>hmo%}<(st6(P`&#`2gt)&=JNOV)k-xnh~wdB;l7`2y*e^qcA=P=Yo*N85b zZ==-0&)Ss{TECBwAvNUkxZ^d7^`M4QViLySyBiUOui#N(vDdI-Fc@8>kok}_%!zQl zi6vIYt1iJubFhh(90I9?DsnL0rx+o6nF+R+Xqfj1*r{nJ8ALf0y+6cI*D&JZY4ZbJ z0P=oLMzP^NkVz#1LY7L-8C~-V<`8FTxdbRFSH4?ONUkD=gP5h6CM9m5b9fL8VIyr; z-%g2BtFEuAsM{ZG&&J_65%|Qf99-m?LNg|<48Bk^4TW?RKZ4v%*6=|50EwkY6`?^t zcAm5v+2t*amoP$H^4U1+NdwU5`Vp71>h-#K8?uFy!goGx5J7zJXB>D@5e|!n+ z>xYc8V54d!9p$P;L3t}K_X_PsH0j*ht8n@ibxTs+7Z>)p_r<(qwauxa z>)Id7(cTuh@h=48Wi;<;jWJa3;OnVgRc}@AkQKF^YEf(D(YySLqy3GK(CQ9_SB{@m zItSIsMf#`pR)=!m45EuV)RIeglQzDv)7uN*6Q=3;BL(w|TB( z|K07p6-s)e8JNdpyGr%o-UxCHROLS{<&7LzRV#AgGd)mF>jfw@ldH`L`bL#oKn;A| zhDh45DTto)b3fCZTH|$$6KLDj@puQpE*ii{%LHM|(Z00vIl9_>K-23XX_#@5Adjw6S!h7Y^N!Q$;PUbK?(4d(ld2h)|6<@rXOHlvrJ8TT21qMDz zZApgK^Dsd~r*~#93*=ew1GU)%+ywc7d@J?vFIKMr&eF;c{PBYyY>mtwtOaa#2!+wu z`nBRD>h(=r5lJxa1+KCVAq|MgBcM;3;yN~#W8{GI9r zM`Mp)d}0oUDS$G~4!J6G7>~l8vi#!g+^+{A?|0wT5-o z6-!5}f+HV>%o9S$_DBvZ74a$)iZ6@UqhVs@17QgSMWk0wh>^%)@7ZV;&DM9}E(|8~ z2d{3L4QvYE7ZtEivC~F9qDs|Zq}r56F7OKQCYcb7Ds4<&K^Z68O_lI>zPsx55dK(h zzGF>mZcg>n97dBgu^YPeuxDVoeHWiqA&!>!?L6Vi!)={3MCN3Y;;p)br zIO7^+pxsVh;uL2XAdlh7qAlY}8Ym5=d9LG6(;;N~+WbMukxrFHo-kcXQTg`;Yv5^k zph1iFB3{@9S%~C>=W;u0!jPFt(tt;-tsa|qU&+rv-@lulf=tmm#XAP@+X$Rzu+~9i zGnSwFFPOitON~1ZIT#pSaHs(y`Yhx5q?WmYM<~*I$+QP1rBn7{gL>IVG|nZ>s5 zV5Gw6SnXhBdzfIYKE-xP@gU+6pA@$fPssylajZv@TMs1~DnVXH-m zce5!W7jxVni)dQr1J73pWjQaHLN<;`+2pF>{ae#^kS1~ld0u|65=xwlThtq5?ab(w6TefwK3PAlqEreZ-dHKngl@Yc%T3Q zneQCb9*v-woWM95usbp_7%!tLBScwn{Y+L#b%!qN6aLn7qE{NGh7CvEecklg`X)K*k{Rk6%ogb7p)qph`8 z&?z}3R<&5^4k`$gf99btV(vPhn< zwM?uLL+BP&n%PzmM_ZbGU%HVQ+@X=}JknxH{z_1$B&tvrgcDv&TfD+De1f@LnD~_z zAS*tu6U&TQ^X+9ehP3*S%%2=%O&P)Q@(a9j!F5~Z3hOUgBd%7l9D~y3w3-ARAk8j% zQ`9tVZ%R{;^7gqVA*xl9Dms}nI&fY2RkiA?>hgx;xpSP&$ zhpZ+Qd#CTQ9gK(YK=~fJ%5>0_t4INZ@EHRC3{S!GF&=& zG$d8O`XpDI118vEb5Rd7YPUoFVF_4S{2e1o_8`$b?a;BPl1+UJ+Ocm#9_jd^N{>-5 zJC|H|wbFHu{o{g#8T+CajKUy{!;jJuGcX|4A2}o2*LadljEYm2&?#)`fDH#Up4n zySG1}ShGsP_{b5);e5g#$wwRNPakl~7W>D}v64fc=O{KAiymHC$XaOJQKj;y%7MTn zmNlB8GDe)fFapTxA)m8yhX{*u1qi8z8G4MG_7(QA7TPv`Q>H&k@Q92n#%zwVjdL|m z1%`>@U&Fc1uQCA%hrC;u@xQ@!gwy53}!y5YH(cGqz{dx@N}R)kh= z4A&+w%1$kPeYAtxIol62YVq8E)LEV~J)OW={(Qr3wz|u)l1yvoP{D=~+IVsL-4oZr3|yWZH) z$+aW8+xpDgA2AAFtzu`ir@!D`!Eb=J>v&-{$XPPK&TEj*l?MjSWMD?o*^b>L&c2bS z8CgRo+n4iPqgdBn34Aon_f~tPYxvzgUhSWh7A>0|?y$zV(lyoKQqG)KF2&RgdeUXp z%QS9ZO=zQ3Xil~YoGgrUhH~jf@GiQ@G;po=D8Qkvv(&P)flNx$7^R0vDB~D;T}-jy zxVx#i@RgM)^E1`S)AZn^NcGW<;Zd-AwFTa(V)gU6Ki@Zcup&iV$`uouMMmodjVeY5 zx$)#80jm<{bS#?@9~IxBhOJ&M&QKQB9*O{?Fd98Q7lBpNnhJ)2P6(0^zHn8RE zz%SyvM|5#kN6(t?&?}h)-T1{lu52MJbTK!JY8XrJjL%?;-ffs~<9O|&EZXa%`C;|b z-PFH4@0L(v{@9KuC>7Ia%<6>lnRHjHXXiISfBMk6eFn=UQp@sh@DysF`AE5W#G~k7UD-|(O7a$qtG~fe%xl2>gUeahlD>d`P34vR%4kh%mH#MW`l!m02s~syq5j) z{Xs6fuvbipgWYnS6X;EFX-u0nfJzL&(bZ` zrb7EShKQJlp?RcNwjA!ysJYfL;`gTtw%3PjLIOXH((z?G*2fJ^-2I(@$O_h2w!0WB zHkx!*4w_#(f}M3VB8};Vm_*w}?<4qW<4C{Cmk>J@@Cf=idRZI`8m90XWsF-SAVyhf zzzUf$WWam z!aRRKl1DrFCwRFc|0e!1&xAO>hnV)_XmGD6Tc)?e1@@lgCcMLw;>TmGVr^ zt<$Gn$ak=ncWH{{>mTUO$RU8cc%kFKwbb%CkB)_pT;H|jM9W{}s9r~aw*SQay1ZwM zYcJrB`S}khE2n=zr1`VkJi{9~Uzku+!wC6k(qm4Mph4)37u3|&W{oUl6WZQgXf!W> ziJM-tp+f1mZ2G3OtMk~(c3Uwg zKiUI2;)4FR_6dqc5XRSBuY?3(`W@Y-CPZ@0M(#z=l3W@TJih@?9VB+mW*xi5i>Jy) zmHnvU@97~FicJ4ztG-k8THEc@gjd0v`PKQ%ITzNBg6g(FC$-`cfV$Z0cN_IK-4{@vYm=M%Gvq@Jg|e0W^`79o3e$SQq#~vK%p7%P&JlX?70A z`9ltpO>nL#j>MtvRH}GkQ>OLSZBe(GI0-B>k_LPUtePE+rGw6^P#L zl``7#{O#xB58CzD4tjy|vG>9W+B5e1g!;7=?r0&oniGp{~ zzw)s+J)5Hc3w9KV>uY$tO~~_0EJI;8V?ktlT(7XOiEA-L%W|Cx7^epLQ57pKh@6fV@axRGygjRNMG^l)7iY;n|oH({mFXq*?7}OiDa=HF2AB zNJW$6)!1~O0j&+XHc*PVE{*NDfWz${th-N`szZT2OgQ##HzY^9g!D%{^QHyYH?}%z z{YDsJ;B(!0u}(7t$hO4Ka7&fJ6buhVP{*WvNrE@3&D;CsSdhDI*ucSj^hAVH5;) zo^(00U`LiV6*5a9=AS=m)ZnFvHO-C+YTB0FsAkY#D4{)79rRbs|4`3RDq<0|*M#R* zG5P)lg+SKS!5dxTNIi9z|c*j+pUw%hWJeggpMDb-LNT zR~Dbjyh~~l)6*62r~P&G8}DzNrivQvw($WB5HW%967Zn>3{23W_v%w{CO;k{52FI- zLeN2)NTP2pk}h=VuJ|l$C`5+t*`zpvG~pty4q0qbp~WaP|8PVX6XcLango(CvcYD& z@gvV@GRa4fVCrtW9uq<`p=taoO_ddgjM70M9aK`v>->oEO8j)3kjE`IjHp46U;=Za z_cXLGG&9+36QT9SJaVvQN^8U*W-d~3p%P<&@=77yv} zBvb$4Rn}iQ`;eiZQYlu`nS52KDNhUXXBidzOvoN)?}3iSV(&VZ(f7KXg0N%_t!UMR zhz0Mbe-;In+?X8eQdf|81y|j9^IEJyZXtUY*}?i@|H4kD;NVHr-3Xcn58hn#16Pc+ z4Oi97zN8mc6cROvr19ueNn(VG%(2Uc9g3H;dze7s27pn3mZ4B!uy$iMX|4Dle8WJ<`1>t>64i%mcr+_~DmrkD^|+1LJM+f4{%3cKcr37QIpKFhjcn|oBa z<(^PZUM2-Q?|}mcx7u=6Wq<700;$A%3iv3qqWz~|yIEBDW4762?`xFGw$xsNF4l2v zz1tmhb&l5L>{*xpVdm+E?!hBef>H^cb{`!b|Fpb9nQ{u2RP5;U9#XV%Di(k6tjeC? z{vo-lvcyn}<<=OF%l9p&<|-k_17p!`31>h4TlqH%4^r}OxAgwM_r003Wu@{g<28#J zTnJn!+DE@A(dvB?%HKowvX+*Wg>bN7PF${%m12-e6QtToRU&t?d)%QpjK!Ch(>icR;~&dWRgyJ+6CoBZ$zL zpamvyK^w0z4d!5w6@N72dnA+E3$GMA+cB>o_}B!r@X4QM8dFOFBO(`r){xR3OgPJ@Q~(RvuqbS4i(ew)hE0c9goY>p6#crkFhofzcMNfy z7^rcT)`%i~JRzC%=4eJcLdzdPv6DUc2#4nsE_5W@nv|?bJLPGNRZMx3ajeys+O$s^ zO+a5m(Pu_dMQ#h!*hFlm@|(I%GjQ2srGOTRk!xzxe>x;V@g%k14Cxgkc2c>QYEKV z5rR^Js??BI-Jv8+^AGkF)1PXw11{CsmuU7*eIazC`Z9XGJ0e7$AMH>#FEUbK;dNZ+ z!Kz{u7E+o0H6$^VA;sQCF{p;?C+G63OBZ4ftKriSaf#gIGO0zj%O2fghErLMEI>N=}uK4fU6{zCM<)g`pVi;K#1o?rOIJSxF%!bGF@nByJ30#)_Cx z*@6s>wLLj&5TEOsu&Ol{ZS);a%orPlOoIt9u&aZ#3S0d_h`fu1;Benm9gC5dZ^WyP zd8KOD*h@5&X28&*X{}flhAPH}O3k%?X5C~T46)^7ps<72D@WA^mXM-Q2RruCc zzP~Ec0|heM23Ockh*nOG0E|IjotGGZ7EU^+MWbs*{Wq!Gf5I6y5Fc7lfrxEq7(9qh8b8+N~h z>bOv04{AVViXEuvlvHkK#*4E zf+6m)1%KRu5lr&#G|Vy^^`()X%(wy568Mh}UeDUF*0aNJOW1H<2+Gpw_Fs1`7=s~f zTY;WQqql4jdvLB?TOQAoQ(9@EUmZRO1T=z)GZ7l<6*71E|hG2bb z3ZFY6oGzIdxQha$AFL;+HrWAH&}yD&EiThQMQwP8k5Q*$wJj3QyEFXmDmRNQ9N%7G znxeA6l^t`@|6XewRj3m@&duWG4iJp2I`JCCSm*gAX~qMWxoQ}^dvPd)^{B0I!eP65 zDTvD^d-sQG=+Yp(R5+JV`-xPdes<(2hs*;)7~}qvi?% zwJn20+kaQU%Lk>1EW=LHxlPs-Y>qXjX`@%{0;DSV&B;N%#(_ z0}tXJmO>iffbP`e4tH;3>T4m0!ZfrGG5Y1SA}r$crVgcp?|cNrz(^He2+bT~Eimsh z|MoBMBnJ4B2qS3FJMKY!086phMi@E67+VV%=?57(&=f_bQ?w%o|88D5ujrfsg9c|8 z2Lo~75naG>Ubs;`Oi)VNaO_Z!q&CqZ`XLS)VIJk;Cm!yQ?r|_!(IH4isJvs}IL;&f z5m*wEFfb5IVx|&VL>y749vvdN03_^EQ7(3hiSlBSEU-~L5_k$QJ(wXSeeDvZ%v{*R zO)63|4$VOp=ZGRwAr5k5I8tJiP$Q%P5D1bbn!(eAgCZ~k6I%sbD(NVf@r*$0(I5?N z{H_T}ZabLapzwhV&m>#uk&(dUCiU;f1Vj=qA_l-x4%6&cf>IqdP$Tf6cwk2=|2^Uj zFCq@T3@w3jE;PX*>jHeh3{@l}*FM4@HlZh_LoHK=F$-+TYKTqDaxTUVcw&(+IpZsP zCl(>|C34ap_i!e>$ZF`qAGYV|a0CFC@ii`DCn}>8mm&}cC?msBF0S#_=E8RjVWoa+ zB{hO7(!-1(L+w0dP@FPADpSoavk5VRXdbeIc&8z}Q8Wc`E{g9nU4rr+MA9}Q-1OsW@LmRIoHy>gm|1Y!^S1X+g zVG{-i`=I6;PXmGefkW{@6spbsnuYPKr+bdc8Kyz$Q0{5U;sun)FM-F?{z5#jWS}&1 zemd?g2M~_%awaNJBobTEghC8jh=Ms63SkxHck4iYG%Qs^G8M@*R_OR?u< zP{9d?ryy95;e;xaq9TLHPlPT?d6;w|KoKL1(@+MAK^+Fm`UR)FV;MB_Oth?AYBEq% z(dd*;8w^G*IwdY3HGE|7i9&%1{-S(74Akx>w(qbNs zQTAeY4nm#&Au4FKAn*xtW^O41$(caSor>ac=4g-fNGG&FPccq;|B@7u*yJKLf*GdI zJEQ@9W+GMYCpi;D_%NrU>|qNq%}xr)tds*DimC~QC*O?eO$j2iZmM(8NmPZ(@@_CB z_VG$y5+!EseORhZa3U%Xg5}a8?fm2hK}8{0PL#@&r*g_rfod&oK&w`@2$e@r+k^x` z!XF4`JMQ72ps*!ys99kML#=`>n`H{2;vYc4WCKTly2lA_p@>doxqgRM&!?SwBXOKX zLbI_^&7>>45J445OmN6iYZWkNqnN}hIab6es$v>op?X3U7Vso|{J}2a)HIUm6}G`v zouUvvag|a}V*d)S#KvOJEHob?@wTH+OG7t*WQ-`2WC`%q|43;X4yPppCt%#-A_{?b z2zDwe$Ap$Pg(wgX4Ame~2RvS)Bm%`To6%kerC-ZZDm;xw!y;8N$7q}jmq0Q8nzRtT zYc2jm1=$MUR;v({M_VPPB%TUwlS)YU1nq7kIu7wUjdWN7b#AYdfKrtpNCpR{;S=-d zPSl6H=<`=qM36d%aQ-L}ZE&p&f`$%4Cf$TM{S+^$%A5T4ArSRRX~K~vR)J_pc3WgQ zJ%T`&v1G!tO?AwF%f$X(Pu5c*6;MqL@bR7RbVxs*aMEXAk3Cx%$I()7k#mVPjy1MK#DB)%teft zIzwWnQ>Ox!{jm8BDzcudHKB|BG2UN%ltGqnkE(nL*e}vsC2JwIT3U zn(3tuohqELQk$!!nH}OiEs&gNc${*%_}Iucd=qZ8QbSv?vuzn*S_V&Uz!`oSwt;Din8Y-!BY01b5~-mma+kFMqz*&spn)4d==SCukZ{{N zX_#oaTk+-ux40QOiKihBPK2_m`w2biSrRUU#0M(~R=UqOJv?S%h+Dj)N~`y1?yiR_ z>q;@v2vh?)2D=WuPsP4RlDwH1zdgB;7ee-uDQek*8md;9D6zm%TbZ&@np}{-$J@c- z4Z>YntD8u4@hCX5TP?CD!z*tS|6njUv>|&W{J}^3JWD*KKl#L$P{sd}#f_T6UEIWD ze4A(7m_xe8ZxhE+T*qzlr+NIvf854{oR9--$o0_3)f&l(JdKq+7@J&HpZvaIJj$V* z%JbUFH`2$ke2%wV%Ddc&wfxIlTg)|^%(HyT&AiOh{6;8Q%x`(k?-|b7T+S8b&FOqw z@0`T*ysFWB&*R+B+ZoWk!_EbL&U4_!M5J<&az(V5xN`#Q`aUC}2!J=*-s<7J>U zebYI;(>?vuK|Rz(ebh<4)J^@=Q9adFebrgL)m{D7VLjGmeb#Bc)@>csD?QhBeb;%t z*M0rhfj!uTeb|Y;*p26Q*P7(xtnb1woO9rE%$QK~e#cZg!XMT)Im@Is_D?VL=+Cq)R|b35EUE z-{0`fIeYHT&b-e&^US?_&VBDyRR>EwwFP6RVqRnXv#|d@VgDV%&|cU->+S7Dp?^nV zp#D3ckLYh`L;v>wGY|%bBL)Tn0|WW5650cSFhGtNAOr>oi2*|W3p#=@933$n5g3k0 z3`f+zTm%RM;fR4iU?7kf2-Lr&NDv0n5d(?9Kq4`a|CnN+Ko}@T3={$bg+$Z-2mB8j zjfGx}&PM&K^UoYXAOr}61c6Zh%A!3-N01`|Gq|muY zM-UPLLLxy(6q+M?DG22VLLopXBnXABie`-lLz70cMAJgY(1p?1XlOJRdNJx>L;rlV zAsii%j*h5*{h`aEJp{rLfpkQm{dr=oeF3!|~o&}b~wKjr>~(LUOc2n6b%km&xSi9fAjtq{BMN+Wd3g| z|8oBm`k(6mY4>mGe{%dA!haq9L;8>OznT2U;~(&U(CE_vJteew=$_D}SZ{GKF)+w6 z1pb}X|E>uP0(3n>2DOHwzDNQpK8ult;{GUdc8xr>#*)D}AjoBPq_K23iA5=vLA|ML zG>u2U#$vRod^}6Uek@PDxnd$$>h00$XmjP)LitDlqee^Bbg5bzpXFFf^=u`iR3l%b zwPyakNwdq^SnK=64>tX=jGAq=-Q>r4w#V|{&oDDk`&}NvQflZ11B)TR z<=-i^Y1B0Ykpf)cVma-AHzVEns<2}Cb@qX~R(tdQ*CK1I$@gpvazV(8*XKmj){WhH zPlZ-$JGNz{`COQ%rT-VWW$|x zzlAW|Mlt|C^QJRfNdc=ULD-~51Ht$V`DH)@dtA9&dCWIxv4=W+iGNsqbhvAeADQtITElPUoXZ0pJITH;0ur z;BYs~MiFKgg&K%5CYFTR<*QyprtzI6=)CQ9y8BF%5j-2@dj&ziX{l2NN#>ZduoS?% za=;23H3?-e^`%U|T{xYU$iT&c_z15?f&$hMd1X|wQyZ?p0|uooPdqR)FTvl?1OoCs zK>f;pJrSL1%u0OWYaEcE4Zvncb!Qp_de`l%Y6l)JZN0Eu+N(0xN$81WC!8t{N(r_k zY6@3kp09bF(pB;SM54XE6 zBl}t4X2Yh0=f|UJjGHHb1cCuA2K%fozEJ;P?~m)Lh+aB25ew#aHpM*MdBG6to>v); z&;HE+jr5V(&esoQbElKYjeB511o)b_K&pPCGYTF;x;1-pq<(Wgl11QDUke^-tjpBfxq4^*-z&laaDh=A&72l>Z8^Y9;+f-eKK+ zPv2+X2k*KXy$d`w`3`6tEB9? z=E?DFcCR8-ebQDSC>#gwh${lW!*A=@=GSCz!yBIAB8y26DM2`Fhk;CHEXOE493{5b z+QFoKs_9ovbWy9NfRD7)(qRa=SNroXHVHMA@E&f{4QrCA3YsLFJ#5m{OWux#H% zNgtfNV403c#_&}ee&)j&PT9n)2whUaPbH7Y%`H+C@o9zSX&JqFxj~qbkuL(^4{|MK zjoqqzrg-8A`#ZgsFI8157oroynV#1S=}?o-xk$G*Eg++B%RQK{h~Jnlq@_iSz|ZiU z9x2%{WnYu^>o&#JQ;vw+IUquN-^Zx9S!3X1fuT2vA#d2J9&p$+`x;X06_oAnc*Io= z0xokk`s@|CoLOamH-*RgZvb346k@dAvYwqyQ_Pn3X=ToM_VeM8!#Gjuu8sV##etQl zN>7s?M|h>1iBXfdo3#4KkmQjkIOzwdF>%m3xnz3hGLZoaP!cbxTm5Zhd}pEitN^FY zA8egE{lpc!6uB$ZP7PAL;5I@RV~g}$&Uup;rpxuOe#F^}aB9qzQ0}^msfI zj)qIs>9V++#-Hd8dl3>23KKQ82k7W&4yql!*1ME`t38#6DWPY8!ql4>9ahRtD^_&9 z>Vt1hRryWuzaUUA0@_j+ z7EYI12L$3<@eZ2pLVVjtc==y0i0?(N?q-RV6v<=rZnp-QnhK$$9$AWPlw0|ZuVmDc zq?pfFr&HfD&Thnjt4LA~O%8#t+_3FCyome70-mD(S`tQ0^J-(UmE+6h3+Z#}eZV;u z_&Q3U_2zxw2TuMvPGjQncUezJ)%(|%uRp!>PJYKbe=E zsCdNZ(TQsq1{{)_Y)te;ZZrM48I~t)N{-UnVWYntQPXKk%|h;QN#Bk_5}VR1wRZW; zZ^uj~n=;#xyFzIWpKVB+vxl|z#By(uPCCswi^#nvUAL$SkHqG@eXadxE4Pz=lg$O! z$bH#Aw_jg>A^>y~rz%jfR*c|y34)ajvg$J!st7-bTAuja?Ae10jEVd6Ko<;+s&&ey89nF$x% z%}_T#iV1ZmSJfYG9tUg}Q(0DWsJneLnUqjuyQibCT`ogDM3ue*6{h39UVcIcS#7C3 zQF#+hn`JA|)-Ra+0-vkjyyD6&D0tULas^?FE7>eP@guKfh25dm>jCB)a#$;1Gk)O-=64N3`t`2z-?{A{f4UT= z#}ZZq0wC!px4nOvO}@MU38f1?`>11qDg(%cav`f^Q7Xrt*E{DStngch6S;w)q79`DuA?qr zqa(6mvEmB`1bE;ylp^rpx%`X`9bdnt;y~HHV9FHQ(qZP2Ow<~+jjq9iOf{NMSJ@nR57CNs0Y zB`d)odbI?610?$66KR4Km_Px@5Q|2krpUB0h~hKCJ;<@!J;+8{{MbD?6sw>Ky&)1< zUNliWJr%4h#tg035#hSQt$5f~HXcJ+_(>gvhO@-jGXyVbh>#7qt#HUUFYH-)*7!N^ ziDIAk?eqd|B-vYfC$wzG z;K0jQfC zz@39gCv3Aocr)5rY1^+^;bBo9i_^{qadcI+lXX*zJ)-!5MEjhy<3(7YOnMDJ+8Y~U za~4=x1bu@%$xL$0B&*MUhNhQS@N;!w{{Y(?-bA}IV7cvMlqXps4F88(Fe_)q{s8W5 za%PApED51!te!}uE-)eT7OOA1A(@uu0%-0L52MX`TTR&63L7IxOg1I&0%kngrn}h6 z;Lb?it<3Qrl@lZ6REoi}kS8&Z&eSRj^65GME!KtG1fMNzJm~R10f~i4cMLumI0HcMEdGq-2&9w0cY6oF%)DgU#RO z4kK##MsV)EIAItJsfVEg>_IKYO6jSwrI!NxS5*rofWiPBl`00lWmf_FT*++lxoM8$ zS7PeTA`}t4OSANyxC|0J5(U{+xUmJHw>2G&Bocu7??+_otl@zs&;A-SMW0tEiHbrl zG$AF7+5^HB=cVk=gzIxapXq7^l;0YNh;W4UtQxft&yFTMe|3YWW*&<2HUDG7k;ZK&!;@Sz~>of=X zOtrT56GX%?h+rh9Ow=8(thfzUrcTIKz*h18S&A-pG^m9R(Ga zrpusNS8~Fy-c3LDkf6h5chyVG_FCiJlsaJNrpJjon;ZPT*eVcq&SVQI=8B(8)+682@-peO|s*8xS6(o(xhn!bl*sey_o9^|qLRV2it93w8d4aqQ$ z#*a>mUhI8IJ8We+@)F8+ur!)8{QRb2c&lIBRlTQtgf75| zqZTnT;7R-7p+}+E-c&=ofg6j2XoZ!sj_YaRhIdqI+7ScaCpNR^Z19bfC)9L#y63q# zwSVGL6r7Z{pL8ZKK~TFfOi)TrNMDWp^~A?JkTMj}>gT3jJD%9Wn|!7$*dIPRnNG{w z*)oNke2w&)%X=C4jN*^LyE`|Z*HK?r_9jDpzvA3ayuALZ+BUh4oYEc&ECA_^i@+52 zrlyIfwR}P*eT92!Tj=4_?zPjJLwcYcAWp_Ju(AEGv?PGR z%dE*D7lJe)e)6#wr_Xi3Pou$|vf9S7&5~wLel5RmQ4P|JFP9Y?c?fL*U1!nc>;2{C{jPWK+LMj%Kv+haX1NV7%MxwiaB$DPtaP?VsTvK-C;d@ehJ1m~t91pv8 zTsyNT`0mAff}eIDf~dGjw{<^JW0N}KhOZc{?;mw-7c6`iMV;?AdF_~B?gdP5qeS*X z27-`QuJS$(XIx-Lp-n(s4xUpUXmW_dahx4 zK51Jg?>IROZ8WQ|J9>8S+C=IiBYGGSvTMk?@K}Pi{rM^J#DPbX!Jr zFI;wQeVtlnBaSr%; zM*qBnFXfEYb4@l>m|YEchIhj8-J!3*M|S$0MB(W1Ih}VH&!aeaoLWc-WWc9+}sdPs;y zs_^hS(Mi_x7e&gilDEW{5x>9IQZC8TM26a>3EO(fQ7V#A{9NDf)@={^d{|yjNzY7^ zVSW19=awzymICu^wb@dz@Ypr!R^s$GP13i@50~QS7gU(%c1f1xS9vX8DN>pKuHaw0 zzPjKJr2sSC5vBxwu%@W_PFefrtJP;`?XTqJ)>mC0Zl0j@XulScQ)dkWfs*=K~U7(E6+Z~JJc>3`rVQR6uOEm-%=bvmE zYl3IH*X=Y*2FZ|%VN%I4IGl+ABV=K8hDYE^!AgxXqj~mL-VhJ0Uy_2PweGn3+MNLn zT(MEkbsu5$#`OkuZ%@_-a~taidS3tWq6VbX0;u_3BNzj+-Y<5`(#ydaI;&rfWt=}4 zM*AOWXApne8+e7U65oVf88r9yT3EG-rEi&}C4sRY`#}bKOabC^-Mz$Vo)B1r zzUAe9S4vq;+Etsz8T#b#XW98hx}c6i@r4&e3B5OdT8@Fq2>^qIw?wP$^lWgtK&5)l{SczSOgE|6I+Jo(6xjPW(9rEM3pp%2Ev07wMeN znZz=-3s(6g=$PgDED*Af- zdwKdVjr?pK&l(VBpkip+#jtInM-JtWqPkql%4a=zi-#hM5AALi+*UbfF0QSHC!GW4 zf-kI?ACvv4jZ^va`P17+%Rkzw#4OI~JX=Oxr~6;881?PiiAq-geV{!lVy;zxo+4!I z|1Mrp&hqJcvBtL_1A$S9^P%3fTBYx06)(DTrcR%qEX#c+a0hWO1p98~-rw`~Cairb zLd<^TPMUeJWookcb#h$D+rIusZl(H~zM4d; ztq#qtKBiKWx->`tm26MlqO0cmc9}xLA~6X|_y>7B><-@NW4C5@0*&w-#8-!%i^z|S?AwrekzJTy{AZ4btxqx!eZYV73IB| zf__5Z<|@k02$laS;Mi9j)iCpdgewD-W`2*bhBtadr2{;azp0tzsKnPmiHzM4sa78^ z_y)yST$K0KE9M$gOfmN~aMIO-5hy*itcwCsTo}@(#xY6VeowFCU@%-_FXmvJ6<}JO zS4#{sTDEvpdj|y3B)V!%KaWX&^0cv-hpf<}pR0I-_Jyg!gwv+hIMk%_Jx2&t@PJpP z#jNU35SJV#bwAV>&h>CO7t0ADmG6tn=V4zXx&BaH6SRS_x4_ zyM=RA?I?AUk#ml8>Y->z>xeV-3L6YC2i;efju+eqM0|s94rAZ{_1kB z8vp^cxibFt5p$ghb79fjnD0Mi0Kw0drM7jojJ|&%Nv`E-xp9f)&xAz zQad!AR~k2}=l?B^4PCXTLh(o`qpm)d^}>hC$29ot*v(Sm#8241oeO*^b4j+_ph-v@ z)OFz0*F?7c67qYw{dAKneFDzWNMSp~7~o?zSHbU$pH|{}LRnX4VZ_%75LBGht8pO5 z!&`CDd804=B)NyLSs!6u`ix#{dHu%+JOr2rJUeorvDogKTUlKH=i^(!J)sfpXW z=AT=vK9W0hy;jdKCD9v66Yyh0hGFtvW3Mr&NPR|KM1jT>#k@|bYTZ+XR|G(2X==Qk zw4JJrdcC-t&*1pav*=%(wc#Sbp&#<7 zh7#X(dr7<8d;Mj-w0aZ%a&}2(iv_Q?th3^2FtJnmhq#yTj#_AxDtQV-lg?QUOAPOYV>vE$!Mb zw2M<-DS@19ub#Q;Quo8>Y#*n#-+EpxRLyTk;4H)&5)3et!P8}{wSnfwLo>bf6x^I* zMt}GmYS(1Nl~IGUiuM%Ot7+Pj0eK`@BHw9NlkXO;j|35cRAbQSf@nD@OjiR0l9?Fk^z=S$8wL|;t5|87GdTM@PDH8mSgZ1rEN)Xj8vfh+ow$Q<>>M= zhA10-i!7sn9Or;AQ<;1=z2bSy7m^%B1EpTRGDQL6XM#a#{5xL+|0;IbC|-Jf5fKmu zQOk)#V^LJzj1oKYlJRk(>GfjJ{*2^)`r3Y@Ktj>2e%Y&jIh+A`>H!6g0Y&ivCFKES zg8`M717Pm~Rp@|P`ha@bfJV!JrrQ81vY&Kip!#TlV|w64keKeAk{%A=nYc>w4dFT8 zBL-l%0kMh+LmpfDpb#}d8+I13O2v*Z8nA+uyrS|pX3(ZZDdGU1%R|L(XE2-vVb>_; zutV@9UD4@E+0h9rtaK=rmcZEti=Vy7a1?yf+4fOAJdbGDmomEV44VrQ?j)^htEK7@ zG;I1Z=T@(Yx_8K5fH3O}AA*rZG_6{JnMln8m6i{;CRW?-m$2j;hPtI{^Vc;&#AdzJ zP_SD1VE>_5Hw6n5b1m#E2B`SZMQ3Meue;0nF_i$<+ZCi6V#Azhejs6v7^oEEk zVpYux+1b~DnddEUQA1DD01FsZEo68s^kq1d<$We->^_(J83-ig#KCFbnUNl6rzUD? zr;%(kk_#m|UD9yWYD}0KGcHs06CmIO;pDq%wEV>nyixt&HjYUwhEG3Ia)s{`k1JH7 z2B2aS;?qb0ayJLXI`|2}Y~T&6l2Qc7q~xJO0fNwmNZ?3vK;u~FfV^)mJYN&DsTb)y zM`q+*k7DDW>4<{3XeD>x+jJA?XpXxY#PD^c1cpugHRY|D%X;xg3${A(do~Hx*FjF~ zT0f$w(Yd4HI5n8q8wKIf_$w8k-hiLVL9wq)_>QnCrt#zY>gNb2ymPjZN_t}I19cnr z`15$hMT|t2gu6>_*G(cKHww*!(e>;ByDlwcM-Uu@-Vq7 zIN`+8Ao7+ZZ%N8JVH0c}C5Tvc_q00;M2Iimy(+n&RzzqDK8!V;?*wg(9c{FW5NW{f zn!~|g8*a1HJW6f z@)IH;QJ#qz;CuQdGVbgwLrzYi{4BeT2I&@n7F;f}n=t<(gV`H!jGYmME3 ztRJJYIS3#lNsiIDu4TidAryNDZzfEJm0CN>+j&9mb->4m!XlmjFxk z>T-2xZQQ7I5M#R}FHUtEmAgemb1nsEs3n);c{otU2N$(9!x{mz^NHHl6k!U#O1S(IcYZW~S$*K$l`THT#Er z`KeFZ1e*B<0>8`#@AXttmqSI&!>7!Jnlvr$rJy|BAwL5q z5cU|rZ?gLuYO>a}jCF6*MWhRBA|Q(7;5Hh-bQhUH1%{1ocC3M1KO`0c zh%H+zI)}9MO^V6 zd|Hs+otFq1T!Z=vOOuy~yZlOM@<$d|92XO-yt8HXbK%$hQBsDO?k2j~5(KppP+~$e z)mEc6K|v=&s}2$|Yew$%-SrO##weF;LsJ3N>@2>A2Bimqh>3+zQc$;YzjUreiCZmDZF(D58W%-WPsfqrI1D=P( zl+zz8u7+@U>-wAW57-k6?ki8fbQskL4DVj4yS@`@SH7Q*)? zoQL!l1)F8>A@14s533g8PWs;2Kguw{sV_#6+7H7nTX1zCJ%7~%g~CQN zkkNz7Jr;(HjERu2*}EK#;PMY#aNO)5orm9>^N)HrxRg3YwA#3O$-k%+!Ir274KoCn z#3v8Spz2}#a6yQ%_3sU6fd}U485x-(ZejnyS(FQ-`zG61WW%;h`SvLdTZbDI==*I- zoWG{k?4>rCq3}FNFrG=y^MdPi8RLkg~I>)8om(DdE6 z{^8K2vWAmt;EsynP;&vo$lqZxXSg{&dZN((T9eK>^En~<32J6G-W8aCal_V^s#WD9 zCKulP4zU;mY{gu5@h`!02kbVF2-g@oo{(k1HPT7?GYMj*Ps5HN^86)E_gakkvh;zV zi0d|$2hQhrSDcejFlp{4JGGl(lBRpuF0DPAZm{3ue1*Hh9D5pL_3AY@>!5>?TK-+@ zpyz|aF;(jQmQ1xX*1Jhj>BS4SJbd)+S$9|@1(8N>ELL(Wbn zV6Qd7#c!yyn7{-mVcX?9{Gll64eQ`tuw}c~v)My)H$4}EnGYTXo?4+RWn z;0|3M+@CZwf36A$9^cdC!3+Z5wFf-07%A9m99Xek(Dhq@_f|MM{sw7yx;cDWOqbA4 z@;-Gi5rYP4B;rShV&PK?I6+uqBLR=a+z!rI2cjvt^=h5Y*@oij@VOZLgki-l*AVf$ z{WtpTLB%$1R8{J*;_wH>YA5wG`;ipR7ZnzrCk6TRsMA3Td#|)Y7o^>UxcDVlBGkiX zfUb%cK9OM7?san1YNs0eyXNKnM{;XElR3p=HQfb))ef(HSz^~|p|$RS>x+}|#n(K^ zC?}MWB^*nI*iZ~n9L;;iL{*B5Jho3xA_f<96rI z(=$!uz}YunL;=Esf}1${jIUp4%LGBs_h&yaH(m$-xx2pn%s*8q!xLSs9cIy6k`IXg z3z`u36;VuhA}ks~CSmM+xgLs1YO)bdDWoDGjT_tV4TEzet zh59xZzS@Z8F>;8WV%uS8Rm-7Cq(~7~jxDc9Np!)?@Ii_aI})HIFo$-& zGA3wkQ$ZBhW}&(d)b^2lvlxmKT=0!qRbu@5--VgPaX~H09PEtK1JqevR|*<(Euw>r zg?FNZtV%KrT|_kOCRw?RK9P<@DElP9;ceOn?K1`+GnYw!-fs)E7zhW%Vr^1pROt6$Un6tG;_VC%GZAK;V>z#ESox3H|Hkt*+B^?X{v)q zYx?eTQdqpEBXLhXxYEz-@6}9YXjihsjCkLBmx|)wUl-wSOf(D@FD0~5xgtDZTV`G< z-tC;PQKz558ot@Q(H{c5O!G@SR67=nF@n_67%|vyct1Re&pcmt395cAda+PB{72TMD_WTL-7eMs%>Dsj1pupzQ4s~1QBGqEiY+# z&B)C=!eZM7B53pY6MD2F09;k_^txuG&oeIz`Cmtds9p_=XVXw+w3Krwh_RB(Nj+w0 zi-Kn?7n88#_KD9l^4r>KHCOefLx76(iRNJ93KOak0+@I%pT5>7F1W8}iH_dp7xAji zyv)^Y(shL$2OO%hxAUTj_zD{Y(kdi4&pe#p*0S?S*gbBa7f5-5vX~X~@JY(fK4H>X z0)tL_VcepaZ*jv_sQ`V_}1p@b=1YX=NQXcef?MRtAd?tPa^vYiQ zg(qdv(j1qfDmXb<@F(b9Q`9cgc1{4JatdBbtgpzCussQ`O0I2c@>KRv*wIO0K~9AF ziIIG4vUoAxl^VoNufkF zz2b4ABe6feW|ns2RYNK}7!q9=zad#D0a`b@QDD^j(pp1MU+wiUG>g!*W5uB@^3q=SLI76mB zTs0*T&8hLpoJb}ZXAWd)cVlO>%q~V4==2QKzKU>0wGayKNq&^qI8K)n=dIr;Ti<0>{m)*nQ{7`sd0pWHj8&6P&&LV?SkKxv6r2GODB%PK4S zB@Tj_6tK2p)P2EbH}MzKR+uoteNLwtMMvyDDxPz$@8TrRj1yj^8}N!JYMq@LCNQL5 z8nAzB@{^bP+hfn9IpXKfjajNE_6l3OD}Rh-x7OV&`8?UQxEX!JV*OSx;+JuPb6%3P z7cBiO`{EOjwqHE)9N*ep#^ok`nbd+@LK!^ciejbNc27`=u0=%cjs<8;MHZa5yf;q) z*bOjGvVc;pDmH4Ta%zHEeT{_8f5h25U0aGUArhTA%t^@Bmr13FIhUFFG?%Lva?l($ zy#EFY$Bp;fNTk4L`^nA375lR3M2*^Q&j`e>A=)wc32y*6c&9{dAl?xWpPljEg=(B6 ztF*^m#xoX$pCqbar0-{xCc@;|-i4jqn8QkfnV}+WuE-&w6Yi9zwOyGV|5eOJ1gv{} z%UlL)wZ2+oe-)0iNA~sUXWs%y7mgEmtmzQ{`z;7gX-04W3BCVuIm4X5a;D`RXYfo^ zgrZH?_sXO8rQ7Y={$7xg=)-1~XoXL~W7Is)cP(pxx0@3?QH7KD36+{xvq zTEI_h>@eYO;iR8mWgyrm)!#)fvQ@5kuH92dwE7{Am(i|6AM;WeN_-rAMw9qoQEU0m zZG*+GGwv^3I1(OMKFGCCPOz2kYvG7hPu|;)&MqQ`Mrg@&!p&ZP!NGqM$yHk%U-fFi ziab=iQftGx*hZ&tpuM086HW${z)Y$e{&h=x>Hzg|%TQ^k81J759T1<$!JBy9}1#bhxPLJSu^-*c7MB652J0XnDHvu%`TU zn&QW=?^ee}Ax=8XEJNn2d6K75U!QU}Gj~L}JzO~~&sH?g)B={~?WVIYfKWfn%ztY8T7DBx&lV7D zIdKbP2E@o==$Yc!J#I2k@-tSKn)Z!fWa$gPWc+#-4hK!?D7Xzf0*NHjV_udm{xqOv z+GADJU1WymCl^h4cW2oYvtWEHP;4aCm{8t=i5=9e&-D8O8zCft}vB9aoESMD(f>N72J5JO4~6iWR`y29#hL*uzPBmXT5X*GvIQp&3@tn2~?y$&yC` zUqIk6c@}AI;q`{wDUGO2bJ{Df7hJ9Fgfsw`Xp3KLEgM)-sVGMgofw(xDrOCF-^eb>V#Uy0>{z!{1h8<`ip=)Q%6nVHJi zRT2Rx%s03ISIe3N+8-!5xG(JWIWx}Eanj{s26=d32}iuaJ&P}R-oNp)B;qkP)k7+D zUR-b+vo2}RZz+f|`>iWF(ak!*RW)tcxI~#RZw;|TIo!0ELyr@xmtK9Mne=)+8^UBO z<*=(LpNkcN;;Ft@1vS7a-jO;P=z;xpAjKm!@{>Og($v%r&E{|v9=P=7*VyMdJQ`Ar z>5Pnj<4bH3!oUCqMsQS3iiy>LYHhieUrx#vLjE}rpym(}Zo~D9i&z=<;-y{Aacr@- zSwUOcQz63Fu_J*)`1FiJ*)w~t@iPep&VkBDg|)l@H-|X}7G-5s8<#xCxkKzbyr!jL z_@omr)|RUVw8HDCpu5J%qEcDPP${f9FZDa4AxcWxv4Ad2dDi zKK|2W*KbJoX;e?mcq!>rPf6~CI9L-xt6$3?1LKZWR?+%(2w`}zpLDt;_y!Q)}#B2MuLa12ShJBW%sXc1vaQ;#xG!@IQHIrk|1macB7 zrt+D9Mqi#Sdq%Zp=Gf<3Ey1pUMHSxHA^Ttpx7L?gi<{gv3`H7qI9wCo-n#M5NAPP5qh0xJ@+kfn zDyw*8^~+qAeBLnFZY~{9JHPKsMvhwMh0dpJXy8MI*$#UshEVRuxpEu4J}=lxUNJ($ zXy}RSL=H@jp`TKv`FNLIb z_K^Pi25=<9(WCS9l2gI2Gx$BRbxIJhvA{t{!`PJK*pb^*Rm+%I2u!XwlGSNM;h3ZA z^-+F7^GizoMa7A7n<%4=e(xKHVCeX-o+!LDQcT(prboi@B6wd( z_uPRci}`0Lov+w`@B(W+l%Bg*ew@3jcWJ@f2XD9t9}V9d4e-#o5A={zoCq`0p>PHi z^<7WTisNI6#<{Msi1Jf4G3Jn3jfl4hKIi+dyUzIcga>$??A84#|DIy;3y z)%+?IJiz{$ZV3Y!!B4{@mau6y=(zvttkzLn`lv9pi%pKg2>781d*EFk6bwMGPV^#K z7&TR8F~6O2Y42qZ*vR?A2bQGZ*h`qTA%Op3HQ^aZZo3~y^|v}Qb$`IC_iKuyj>-@-Hg1w{i&86onp#+FEDAc&D(dU#7CTFmofTa(Q52LEBHo5 zMyWN0hhzIlMRyoiVB#>gRjTKgVJ-YVS#C&s5?`83Cda%N}?MUbCAJ! zZW>e2G#DEG$|sqoH2@~q+@icAW_L|s(Z-im?V}{pc6a*AVznvc0it3Kwc36MW18q> zX?6bf>!;3}9wgfC9LxJM0=yx*$+!o-hyr|-bJ zqWvb&*Z0-_;N0aKw|KWdqpq*61qvmNfgXWxl>OqapGPM0ef3rAzfPe(FZ=Y?V@eWd z5gv5e>haxNe|so+yWOsIQuk8y_sunJHBqp>pHjm$_B>cMcQ9fFFZ``lvPQn>T#$A6ZkeEvn2N<#R*NxFv(Pz_#W*di$qu`f81fZl}5LehPiYhPMN|A+L zzv&e_nJYKvL>?CX3l5cb550Nazo@x*tJA{+^|XOyW8krb)pqaG)W7Ln^l`8+0y=!mArxC1|jv{dl_*1`wPAnirSN^x< zt*U_IRQI#l1+ZTou%iA_q+n6izaQ4Z5AD|enVcNp-E^b0fg)vD|5@<|JXozy+z5-Y zF%K10U^RJ?OJFPdE@fv#*v==kfPVG*47#DOftvuECqt>2f<$|m3 z&L}9rRiYRxaB~6LRl@AupLVGc>Op$BCl{|cE2^~2;I!vQYNH4Tim1gvDD{Kwv}|Vd z8gbb1EafKKs=rQh%;U*=d_kx}F}eM~N#fMQ=P6RpjGelb!j?zmenzSy3)_tt81Bx8 zZi^fK7oG@V_nk22DUN(bNq}xa%pEsn-Zq%%*VMFk_PZFC1>BwAT0%WU?6hq#gQ!0Q zp_2{@|F><__cY9J_l;D{qCNs+7K8h|Jl1L4$lra@Q{Kyidd*ZmQqTsyDkH#|p$t%b% zK{~Il2GP_hNSKa{lc6)sY%Iw-Ap%p(51IM%qbVG+kTE+k!gC@;5!ETgLmQ>Y9`2%i zkL3*UHH}>N?wlVS=0FP|1Ec z>`q_wn=`Z*YkZ=6>`+{9o!OQ=N@_sw9P7bz4RKu0L84qS%YF7Y$kS1ebxzhJ>W2wI ze{@lI(PQsDqbx<`C`sQnoV{+x^_~A4zI=)QNO|~Zhv>NGsqfuvz=E%+Cg!U*)Of+M zgjn^UyT@sKnEGCqHGi79ZY$5=p2m(C2EqrG@tU(AfAvt<;w|&00f)SmkAVNV-cC+M zC2SRNBhRy1^d2)Y2hxgxg9;MwfLEP6z+fB9;6gR5!-Z)~g9$e{NmtHO6|QI{g=;|( zKAN$TY2bkoA&grEak!HM>O^QZdRYz`!mI~Eup>MCki7PmHXw#(Z;8QR2F+6pIQb+6 zh1iBYv|=>+c_szhz}yy{a>Wul#}J+|;S$lP!y@tRhgC}BL~g{dCuS*q5ro(T$@fNz zByo;bf{bK5Cd(*<&cS7iA!$4Km6TLkCpsgjVOm9iCHotp#z=Y z%0@DcZH$v})Lkn2=*NLDk|0xw&{SBYi3SxTZ?aqoEvb_gqS&&Oy{w24--V;m7|xf~ z3nj^t2$NzG5Hf73hFdzA#ja388)%8<`>fd&uB7N5O(^7N{(+D3ER&q}I^vx6vZr!V z@0g<0**c9WmG!izM3lP6cUE!_-fW>c`s`nG%#xNo?@zwMI7o;e~DC{&a@(g;!jbP>M)!}m8t?^YE>(ERf>#~ zf>>=D^1P~4t%kLGW1UD6$@(dlrd6kS>Sl@vVmtOwlC5R65-RapSE=q)uQtV#G@9V9 zf3StFeI=e*4SQ3*Cbp%yO3)(*$XI4dwwP_|(cPi$)LvhnOJCoTKgiv|cEyt%lC!Ym2&re{hWKfCu zuwW(g8;yMCF{>GMNoKQM-`u=3$GJ7VO%$EcIA=T)N6&kXjGO%&yFLdRHG?MfNvC>f zI4innhGw*O6aDBiOPYw3&TghG&CX1NZ_{eUS*SoAYEh4x)TK7{sZpJ3Rj-=Wt#j@0!=8?)0yL9c*C_o7lxR_OX$jY-KN-+0AzLv!NYrX-}Kl i)wcGvv7K#gZ=2iQ_V%~I9d2=to809#_qiz&5CA)6hq%=M literal 0 HcmV?d00001 diff --git a/Minimum Spanning Tree/Kruskal.swift b/Minimum Spanning Tree/Kruskal.swift new file mode 100644 index 000000000..bebd32602 --- /dev/null +++ b/Minimum Spanning Tree/Kruskal.swift @@ -0,0 +1,31 @@ +// +// Kruskal.swift +// +// +// Created by xiang xin on 16/3/17. +// +// + + +func minimumSpanningTreeKruskal(graph: Graph) -> (cost: Int, tree: Graph) { + var cost: Int = 0 + var tree = Graph() + let sortedEdgeListByWeight = graph.edgeList.sorted(by: { $0.weight < $1.weight }) + + var unionFind = UnionFind() + for vertex in graph.vertices { + unionFind.addSetWith(vertex) + } + + for edge in sortedEdgeListByWeight { + let v1 = edge.vertex1 + let v2 = edge.vertex2 + if !unionFind.inSameSet(v1, and: v2) { + cost += edge.weight + tree.addEdge(edge) + unionFind.unionSetsContaining(v1, and: v2) + } + } + + return (cost: cost, tree: tree) +} diff --git a/Minimum Spanning Tree/MinimumSpanningTree.playground/Contents.swift b/Minimum Spanning Tree/MinimumSpanningTree.playground/Contents.swift new file mode 100644 index 000000000..99b5e859f --- /dev/null +++ b/Minimum Spanning Tree/MinimumSpanningTree.playground/Contents.swift @@ -0,0 +1,93 @@ +/** + The following code demonstrates getting MST of the graph below by both + Kruskal's and Prim's algorithms. + */ + +func minimumSpanningTreeKruskal(graph: Graph) -> (cost: Int, tree: Graph) { + var cost: Int = 0 + var tree = Graph() + let sortedEdgeListByWeight = graph.edgeList.sorted(by: { $0.weight < $1.weight }) + + var unionFind = UnionFind() + for vertex in graph.vertices { + unionFind.addSetWith(vertex) + } + + for edge in sortedEdgeListByWeight { + let v1 = edge.vertex1 + let v2 = edge.vertex2 + if !unionFind.inSameSet(v1, and: v2) { + cost += edge.weight + tree.addEdge(edge) + unionFind.unionSetsContaining(v1, and: v2) + } + } + + return (cost: cost, tree: tree) +} + +func minimumSpanningTreePrim(graph: Graph) -> (cost: Int, tree: Graph) { + var cost: Int = 0 + var tree = Graph() + + if graph.vertices.isEmpty { + return (cost: cost, tree: tree) + } + + var visited = Set() + var priorityQueue = PriorityQueue<(vertex: T, weight: Int, parent: T?)>( + sort: { $0.weight < $1.weight }) + + priorityQueue.enqueue((vertex: graph.vertices.first!, weight: 0, parent: nil)) + while let head = priorityQueue.dequeue() { + let vertex = head.vertex + if visited.contains(vertex) { + continue + } + visited.insert(vertex) + + cost += head.weight + if let prev = head.parent { + tree.addEdge(vertex1: prev, vertex2: vertex, weight: head.weight) + } + + if let neighbours = graph.adjList[vertex] { + for neighbour in neighbours { + let nextVertex = neighbour.vertex + if !visited.contains(nextVertex) { + priorityQueue.enqueue((vertex: nextVertex, weight: neighbour.weight, parent: vertex)) + } + } + } + } + + return (cost: cost, tree: tree) +} + +/*: + ![Graph](mst.png) + */ + +var graph = Graph() +graph.addEdge(vertex1: 1, vertex2: 2, weight: 6) +graph.addEdge(vertex1: 1, vertex2: 3, weight: 1) +graph.addEdge(vertex1: 1, vertex2: 4, weight: 5) +graph.addEdge(vertex1: 2, vertex2: 3, weight: 5) +graph.addEdge(vertex1: 2, vertex2: 5, weight: 3) +graph.addEdge(vertex1: 3, vertex2: 4, weight: 5) +graph.addEdge(vertex1: 3, vertex2: 5, weight: 6) +graph.addEdge(vertex1: 3, vertex2: 6, weight: 4) +graph.addEdge(vertex1: 4, vertex2: 6, weight: 2) +graph.addEdge(vertex1: 5, vertex2: 6, weight: 6) + +print("===== Kruskal's =====") +let result1 = minimumSpanningTreeKruskal(graph: graph) +print("Minimum spanning tree total weight: \(result1.cost)") +print("Minimum spanning tree:") +print(result1.tree) + +print("===== Prim's =====") +let result2 = minimumSpanningTreePrim(graph: graph) +print("Minimum spanning tree total weight: \(result2.cost)") +print("Minimum spanning tree:") +print(result2.tree) diff --git a/Minimum Spanning Tree/MinimumSpanningTree.playground/Resources/mst.png b/Minimum Spanning Tree/MinimumSpanningTree.playground/Resources/mst.png new file mode 100644 index 0000000000000000000000000000000000000000..2138fd535de977e68e4a08878f6e8782eab9ca2e GIT binary patch literal 19209 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 LpB?Rl2?zi?V2Grt literal 0 HcmV?d00001 diff --git a/Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/Graph.swift b/Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/Graph.swift new file mode 100644 index 000000000..0ae996646 --- /dev/null +++ b/Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/Graph.swift @@ -0,0 +1,55 @@ + +// Undirected edge +public struct Edge: CustomStringConvertible { + public let vertex1: T + public let vertex2: T + public let weight: Int + + public var description: String { + return "[\(vertex1)-\(vertex2), \(weight)]" + } +} + + +// Undirected weighted graph +public struct Graph: CustomStringConvertible { + + public private(set) var edgeList: [Edge] + public private(set) var vertices: Set + public private(set) var adjList: [T: [(vertex: T, weight: Int)]] + + public init() { + edgeList = [Edge]() + vertices = Set() + adjList = [T: [(vertex: T, weight: Int)]]() + } + + public var description: String { + var description = "" + for edge in edgeList { + description += edge.description + "\n" + } + return description + } + + public mutating func addEdge(vertex1 v1: T, vertex2 v2: T, weight w: Int) { + edgeList.append(Edge(vertex1: v1, vertex2: v2, weight: w)) + vertices.insert(v1) + vertices.insert(v2) + if adjList[v1] == nil { + adjList[v1] = [(vertex: v2, weight: w)] + } else { + adjList[v1]!.append((vertex: v2, weight: w)) + } + + if adjList[v2] == nil { + adjList[v2] = [(vertex: v1, weight: w)] + } else { + adjList[v2]!.append((vertex: v1, weight: w)) + } + } + + public mutating func addEdge(_ edge: Edge) { + addEdge(vertex1: edge.vertex1, vertex2: edge.vertex2, weight: edge.weight) + } +} diff --git a/Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/Heap.swift b/Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/Heap.swift new file mode 100644 index 000000000..fa30df362 --- /dev/null +++ b/Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/Heap.swift @@ -0,0 +1,227 @@ +// +// Heap.swift +// Written for the Swift Algorithm Club by Kevin Randrup and Matthijs Hollemans +// + +public struct Heap { + /** The array that stores the heap's nodes. */ + var elements = [T]() + + /** Determines whether this is a max-heap (>) or min-heap (<). */ + fileprivate var isOrderedBefore: (T, T) -> Bool + + /** + * Creates an empty heap. + * The sort function determines whether this is a min-heap or max-heap. + * For integers, > makes a max-heap, < makes a min-heap. + */ + public init(sort: @escaping (T, T) -> Bool) { + self.isOrderedBefore = sort + } + + /** + * Creates a heap from an array. The order of the array does not matter; + * the elements are inserted into the heap in the order determined by the + * sort function. + */ + public init(array: [T], sort: @escaping (T, T) -> Bool) { + self.isOrderedBefore = sort + buildHeap(fromArray: array) + } + + /* + // This version has O(n log n) performance. + private mutating func buildHeap(array: [T]) { + elements.reserveCapacity(array.count) + for value in array { + insert(value) + } + } + */ + + /** + * Converts an array to a max-heap or min-heap in a bottom-up manner. + * Performance: This runs pretty much in O(n). + */ + fileprivate mutating func buildHeap(fromArray array: [T]) { + elements = array + for i in stride(from: (elements.count/2 - 1), through: 0, by: -1) { + shiftDown(i, heapSize: elements.count) + } + } + + public var isEmpty: Bool { + return elements.isEmpty + } + + public var count: Int { + return elements.count + } + + /** + * Returns the index of the parent of the element at index i. + * The element at index 0 is the root of the tree and has no parent. + */ + @inline(__always) func parentIndex(ofIndex i: Int) -> Int { + return (i - 1) / 2 + } + + /** + * Returns the index of the left child of the element at index i. + * Note that this index can be greater than the heap size, in which case + * there is no left child. + */ + @inline(__always) func leftChildIndex(ofIndex i: Int) -> Int { + return 2*i + 1 + } + + /** + * Returns the index of the right child of the element at index i. + * Note that this index can be greater than the heap size, in which case + * there is no right child. + */ + @inline(__always) func rightChildIndex(ofIndex i: Int) -> Int { + return 2*i + 2 + } + + /** + * Returns the maximum value in the heap (for a max-heap) or the minimum + * value (for a min-heap). + */ + public func peek() -> T? { + return elements.first + } + + /** + * Adds a new value to the heap. This reorders the heap so that the max-heap + * or min-heap property still holds. Performance: O(log n). + */ + public mutating func insert(_ value: T) { + elements.append(value) + shiftUp(elements.count - 1) + } + + public mutating func insert(_ sequence: S) where S.Iterator.Element == T { + for value in sequence { + insert(value) + } + } + + /** + * Allows you to change an element. In a max-heap, the new element should be + * larger than the old one; in a min-heap it should be smaller. + */ + public mutating func replace(index i: Int, value: T) { + guard i < elements.count else { return } + + assert(isOrderedBefore(value, elements[i])) + elements[i] = value + shiftUp(i) + } + + /** + * Removes the root node from the heap. For a max-heap, this is the maximum + * value; for a min-heap it is the minimum value. Performance: O(log n). + */ + @discardableResult public mutating func remove() -> T? { + if elements.isEmpty { + return nil + } else if elements.count == 1 { + return elements.removeLast() + } else { + // Use the last node to replace the first one, then fix the heap by + // shifting this new first node into its proper position. + let value = elements[0] + elements[0] = elements.removeLast() + shiftDown() + return value + } + } + + /** + * Removes an arbitrary node from the heap. Performance: O(log n). You need + * to know the node's index, which may actually take O(n) steps to find. + */ + public mutating func removeAt(_ index: Int) -> T? { + guard index < elements.count else { return nil } + + let size = elements.count - 1 + if index != size { + swap(&elements[index], &elements[size]) + shiftDown(index, heapSize: size) + shiftUp(index) + } + return elements.removeLast() + } + + /** + * Takes a child node and looks at its parents; if a parent is not larger + * (max-heap) or not smaller (min-heap) than the child, we exchange them. + */ + mutating func shiftUp(_ index: Int) { + var childIndex = index + let child = elements[childIndex] + var parentIndex = self.parentIndex(ofIndex: childIndex) + + while childIndex > 0 && isOrderedBefore(child, elements[parentIndex]) { + elements[childIndex] = elements[parentIndex] + childIndex = parentIndex + parentIndex = self.parentIndex(ofIndex: childIndex) + } + + elements[childIndex] = child + } + + mutating func shiftDown() { + shiftDown(0, heapSize: elements.count) + } + + /** + * Looks at a parent node and makes sure it is still larger (max-heap) or + * smaller (min-heap) than its childeren. + */ + mutating func shiftDown(_ index: Int, heapSize: Int) { + var parentIndex = index + + while true { + let leftChildIndex = self.leftChildIndex(ofIndex: parentIndex) + let rightChildIndex = leftChildIndex + 1 + + // Figure out which comes first if we order them by the sort function: + // the parent, the left child, or the right child. If the parent comes + // first, we're done. If not, that element is out-of-place and we make + // it "float down" the tree until the heap property is restored. + var first = parentIndex + if leftChildIndex < heapSize && isOrderedBefore(elements[leftChildIndex], elements[first]) { + first = leftChildIndex + } + if rightChildIndex < heapSize && isOrderedBefore(elements[rightChildIndex], elements[first]) { + first = rightChildIndex + } + if first == parentIndex { return } + + swap(&elements[parentIndex], &elements[first]) + parentIndex = first + } + } +} + +// MARK: - Searching + +extension Heap where T: Equatable { + /** + * Searches the heap for the given element. Performance: O(n). + */ + public func index(of element: T) -> Int? { + return index(of: element, 0) + } + + fileprivate func index(of element: T, _ i: Int) -> Int? { + if i >= count { return nil } + if isOrderedBefore(element, elements[i]) { return nil } + if element == elements[i] { return i } + if let j = index(of: element, self.leftChildIndex(ofIndex: i)) { return j } + if let j = index(of: element, self.rightChildIndex(ofIndex: i)) { return j } + return nil + } +} diff --git a/Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/PriorityQueue.swift b/Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/PriorityQueue.swift new file mode 100644 index 000000000..92f7b6d3f --- /dev/null +++ b/Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/PriorityQueue.swift @@ -0,0 +1,58 @@ +/* + Priority Queue, a queue where the most "important" items are at the front of + the queue. + + The heap is a natural data structure for a priority queue, so this object + simply wraps the Heap struct. + + All operations are O(lg n). + + Just like a heap can be a max-heap or min-heap, the queue can be a max-priority + queue (largest element first) or a min-priority queue (smallest element first). +*/ +public struct PriorityQueue { + fileprivate var heap: Heap + + /* + To create a max-priority queue, supply a > sort function. For a min-priority + queue, use <. + */ + public init(sort: @escaping (T, T) -> Bool) { + heap = Heap(sort: sort) + } + + public var isEmpty: Bool { + return heap.isEmpty + } + + public var count: Int { + return heap.count + } + + public func peek() -> T? { + return heap.peek() + } + + public mutating func enqueue(_ element: T) { + heap.insert(element) + } + + public mutating func dequeue() -> T? { + return heap.remove() + } + + /* + Allows you to change the priority of an element. In a max-priority queue, + the new priority should be larger than the old one; in a min-priority queue + it should be smaller. + */ + public mutating func changePriority(index i: Int, value: T) { + return heap.replace(index: i, value: value) + } +} + +extension PriorityQueue where T: Equatable { + public func index(of element: T) -> Int? { + return heap.index(of: element) + } +} diff --git a/Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/UnionFind.swift b/Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/UnionFind.swift new file mode 100644 index 000000000..29ea0a373 --- /dev/null +++ b/Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/UnionFind.swift @@ -0,0 +1,61 @@ +/* + Union-Find Data Structure + + Performance: + adding new set is almost O(1) + finding set of element is almost O(1) + union sets is almost O(1) + */ + +public struct UnionFind { + private var index = [T: Int]() + private var parent = [Int]() + private var size = [Int]() + + public init() {} + + public mutating func addSetWith(_ element: T) { + index[element] = parent.count + parent.append(parent.count) + size.append(1) + } + + private mutating func setByIndex(_ index: Int) -> Int { + if parent[index] == index { + return index + } else { + parent[index] = setByIndex(parent[index]) + return parent[index] + } + } + + public mutating func setOf(_ element: T) -> Int? { + if let indexOfElement = index[element] { + return setByIndex(indexOfElement) + } else { + return nil + } + } + + public mutating func unionSetsContaining(_ firstElement: T, and secondElement: T) { + if let firstSet = setOf(firstElement), let secondSet = setOf(secondElement) { + if firstSet != secondSet { + if size[firstSet] < size[secondSet] { + parent[firstSet] = secondSet + size[secondSet] += size[firstSet] + } else { + parent[secondSet] = firstSet + size[firstSet] += size[secondSet] + } + } + } + } + + public mutating func inSameSet(_ firstElement: T, and secondElement: T) -> Bool { + if let firstSet = setOf(firstElement), let secondSet = setOf(secondElement) { + return firstSet == secondSet + } else { + return false + } + } +} diff --git a/Minimum Spanning Tree/MinimumSpanningTree.playground/contents.xcplayground b/Minimum Spanning Tree/MinimumSpanningTree.playground/contents.xcplayground new file mode 100644 index 000000000..89da2d470 --- /dev/null +++ b/Minimum Spanning Tree/MinimumSpanningTree.playground/contents.xcplayground @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Minimum Spanning Tree/Prim.swift b/Minimum Spanning Tree/Prim.swift new file mode 100644 index 000000000..89c26cff0 --- /dev/null +++ b/Minimum Spanning Tree/Prim.swift @@ -0,0 +1,45 @@ +// +// Prim.swift +// +// +// Created by xiang xin on 16/3/17. +// +// + +func minimumSpanningTreePrim(graph: Graph) -> (cost: Int, tree: Graph) { + var cost: Int = 0 + var tree = Graph() + + if graph.vertices.isEmpty { + return (cost: cost, tree: tree) + } + + var visited = Set() + var priorityQueue = PriorityQueue<(vertex: T, weight: Int, parent: T?)>( + sort: { $0.weight < $1.weight }) + + priorityQueue.enqueue((vertex: graph.vertices.first!, weight: 0, parent: nil)) + while let head = priorityQueue.dequeue() { + let vertex = head.vertex + if visited.contains(vertex) { + continue + } + visited.insert(vertex) + + cost += head.weight + if let prev = head.parent { + tree.addEdge(vertex1: prev, vertex2: vertex, weight: head.weight) + } + + if let neighbours = graph.adjList[vertex] { + for neighbour in neighbours { + let nextVertex = neighbour.vertex + if !visited.contains(nextVertex) { + priorityQueue.enqueue((vertex: nextVertex, weight: neighbour.weight, parent: vertex)) + } + } + } + } + + return (cost: cost, tree: tree) +} diff --git a/Minimum Spanning Tree/README.markdown b/Minimum Spanning Tree/README.markdown new file mode 100644 index 000000000..c47713701 --- /dev/null +++ b/Minimum Spanning Tree/README.markdown @@ -0,0 +1,102 @@ +# Minimum Spanning Tree (Weighted Graph) + +A [minimum spanning tree](https://en.wikipedia.org/wiki/Minimum_spanning_tree) (MST) of a connected undirected weighted graph has a subset of the edges from the original graph that connects all the vertices together, without any cycles and with the minimum possible total edge weight. There can be more than one MSTs of a graph. + +There are two popular algorithms to calculate MST of a graph - [Kruskal's algorithm](https://en.wikipedia.org/wiki/Kruskal's_algorithm) and [Prim's algorithm](https://en.wikipedia.org/wiki/Prim's_algorithm). Both algorithms have a total time complexity of `O(ElogE)` where `E` is the number of edges from the original graph. + +### Kruskal's Algorithm +Sort the edges base on weight. Greedily select the smallest one each time and add into the MST as long as it doesn't form a cycle. +Kruskal's algoritm uses [Union Find](https://github.com/raywenderlich/swift-algorithm-club/tree/master/Union-Find) data structure to check whether any additional edge causes a cycle. The logic is to put all connected vertices into the same set (in Union Find's concept). If the two vertices from a new edge do not belong to the same set, then it's safe to add that edge into the MST. + +The following graph demonstrates the steps: + +![Graph](Images/kruskal.png) + +Preparation +```swift +// Initialize the values to be returned and Union Find data structure. +var cost: Int = 0 +var tree = Graph() +var unionFind = UnionFind() +for vertex in graph.vertices { + +// Initially all vertices are disconnected. +// Each of them belongs to it's individual set. + unionFind.addSetWith(vertex) +} +``` + +Sort the edges +```swift +let sortedEdgeListByWeight = graph.edgeList.sorted(by: { $0.weight < $1.weight }) +``` + +Take one edge at a time and try to insert it into the MST. +```swift +for edge in sortedEdgeListByWeight { + let v1 = edge.vertex1 + let v2 = edge.vertex2 + + // Same set means the two vertices of this edge were already connected in the MST. + // Adding this one will cause a cycle. + if !unionFind.inSameSet(v1, and: v2) { + // Add the edge into the MST and update the final cost. + cost += edge.weight + tree.addEdge(edge) + + // Put the two vertices into the same set. + unionFind.unionSetsContaining(v1, and: v2) + } +} +``` +### Prim's Algorithm +Prim's algorithm doesn't pre-sort all edges. Instead, it uses a [Priority Queue](https://github.com/raywenderlich/swift-algorithm-club/tree/master/Priority%20Queue) to maintain a running sorted next-possile vertices. +Starting from one vertex, loop through all unvisited neighbours and enqueue a pair of values for each neighbour - the vertex and the weight of edge connecting current vertex to the neighbour. Each time it greedily select the top of the priority queue (the one with least weight value) and add the edge into the final MST if the enqueued neighbour hasn't been already visited. + +The following graph demonstrates the steps: + +![Graph](Images/prim.png) + +Preparation +```swift +// Initialize the values to be returned and Priority Queue data structure. +var cost: Int = 0 +var tree = Graph() +var visited = Set() + +// In addition to the (neighbour vertex, weight) pair, parent is added for the purpose of printing out the MST later. +// parent is basically current vertex. aka. the previous vertex before neigbour vertex gets visited. +var priorityQueue = PriorityQueue<(vertex: T, weight: Int, parent: T?)>(sort: { $0.weight < $1.weight }) +``` + +Start from any vertex +```swift +priorityQueue.enqueue((vertex: graph.vertices.first!, weight: 0, parent: nil)) +``` + +```swift +// Take from the top of the priority queue ensures getting the least weight edge. +while let head = priorityQueue.dequeue() { + let vertex = head.vertex + if visited.contains(vertex) { + continue + } + + // If the vertex hasn't been visited before, its edge (parent-vertex) is selected for MST. + visited.insert(vertex) + cost += head.weight + if let prev = head.parent { // The first vertex doesn't have a parent. + tree.addEdge(vertex1: prev, vertex2: vertex, weight: head.weight) + } + + // Add all unvisted neighbours into the priority queue. + if let neighbours = graph.adjList[vertex] { + for neighbour in neighbours { + let nextVertex = neighbour.vertex + if !visited.contains(nextVertex) { + priorityQueue.enqueue((vertex: nextVertex, weight: neighbour.weight, parent: vertex)) + } + } + } +} +``` diff --git a/README.markdown b/README.markdown index e0983f22e..579ca0b4e 100644 --- a/README.markdown +++ b/README.markdown @@ -178,6 +178,7 @@ Most of the time using just the built-in `Array`, `Dictionary`, and `Set` types - [Shortest Path](Shortest%20Path%20%28Unweighted%29/) on an unweighted tree - [Single-Source Shortest Paths](Single-Source%20Shortest%20Paths%20(Weighted)/) - [Minimum Spanning Tree](Minimum%20Spanning%20Tree%20%28Unweighted%29/) on an unweighted tree +- [Minimum Spanning Tree](Minimum%20Spanning%20Tree/) - [All-Pairs Shortest Paths](All-Pairs%20Shortest%20Paths/) ## Puzzles diff --git a/swift-algorithm-club.xcworkspace/contents.xcworkspacedata b/swift-algorithm-club.xcworkspace/contents.xcworkspacedata index b2ffce836..c89ac0dfe 100644 --- a/swift-algorithm-club.xcworkspace/contents.xcworkspacedata +++ b/swift-algorithm-club.xcworkspace/contents.xcworkspacedata @@ -1267,6 +1267,32 @@ location = "group:README.markdown"> + + + + + + + + + + + + + + + + From 6bc50e5f9a966738b8331d68de8ed421067d4f4e Mon Sep 17 00:00:00 2001 From: Xiangxin Date: Tue, 25 Apr 2017 15:29:45 +0800 Subject: [PATCH 1015/1679] Address comments and refactor --- .../MinimumSpanningTree.playground/Contents.swift | 4 ++-- .../Sources/Graph.swift | 13 +++++++------ .../playground.xcworkspace/contents.xcworkspacedata | 7 +++++++ Minimum Spanning Tree/Prim.swift | 5 +++-- 4 files changed, 19 insertions(+), 10 deletions(-) create mode 100644 Minimum Spanning Tree/MinimumSpanningTree.playground/playground.xcworkspace/contents.xcworkspacedata diff --git a/Minimum Spanning Tree/MinimumSpanningTree.playground/Contents.swift b/Minimum Spanning Tree/MinimumSpanningTree.playground/Contents.swift index 99b5e859f..2981d30ea 100644 --- a/Minimum Spanning Tree/MinimumSpanningTree.playground/Contents.swift +++ b/Minimum Spanning Tree/MinimumSpanningTree.playground/Contents.swift @@ -30,7 +30,7 @@ func minimumSpanningTreePrim(graph: Graph) -> (cost: Int, tree: Graph) var cost: Int = 0 var tree = Graph() - if graph.vertices.isEmpty { + guard let start = graph.vertices.first else { return (cost: cost, tree: tree) } @@ -38,7 +38,7 @@ func minimumSpanningTreePrim(graph: Graph) -> (cost: Int, tree: Graph) var priorityQueue = PriorityQueue<(vertex: T, weight: Int, parent: T?)>( sort: { $0.weight < $1.weight }) - priorityQueue.enqueue((vertex: graph.vertices.first!, weight: 0, parent: nil)) + priorityQueue.enqueue((vertex: start, weight: 0, parent: nil)) while let head = priorityQueue.dequeue() { let vertex = head.vertex if visited.contains(vertex) { diff --git a/Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/Graph.swift b/Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/Graph.swift index 0ae996646..a2f243202 100644 --- a/Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/Graph.swift +++ b/Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/Graph.swift @@ -36,16 +36,17 @@ public struct Graph: CustomStringConvertible { edgeList.append(Edge(vertex1: v1, vertex2: v2, weight: w)) vertices.insert(v1) vertices.insert(v2) - if adjList[v1] == nil { - adjList[v1] = [(vertex: v2, weight: w)] + + if let _ = adjList[v1] { + adjList[v1]?.append((vertex: v2, weight: w)) } else { - adjList[v1]!.append((vertex: v2, weight: w)) + adjList[v1] = [(vertex: v2, weight: w)] } - if adjList[v2] == nil { - adjList[v2] = [(vertex: v1, weight: w)] + if let _ = adjList[v2] { + adjList[v2]?.append((vertex: v1, weight: w)) } else { - adjList[v2]!.append((vertex: v1, weight: w)) + adjList[v2] = [(vertex: v1, weight: w)] } } diff --git a/Minimum Spanning Tree/MinimumSpanningTree.playground/playground.xcworkspace/contents.xcworkspacedata b/Minimum Spanning Tree/MinimumSpanningTree.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Minimum Spanning Tree/MinimumSpanningTree.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Minimum Spanning Tree/Prim.swift b/Minimum Spanning Tree/Prim.swift index 89c26cff0..d975fc430 100644 --- a/Minimum Spanning Tree/Prim.swift +++ b/Minimum Spanning Tree/Prim.swift @@ -10,7 +10,7 @@ func minimumSpanningTreePrim(graph: Graph) -> (cost: Int, tree: Graph) var cost: Int = 0 var tree = Graph() - if graph.vertices.isEmpty { + guard let start = graph.vertices.first else { return (cost: cost, tree: tree) } @@ -18,7 +18,7 @@ func minimumSpanningTreePrim(graph: Graph) -> (cost: Int, tree: Graph) var priorityQueue = PriorityQueue<(vertex: T, weight: Int, parent: T?)>( sort: { $0.weight < $1.weight }) - priorityQueue.enqueue((vertex: graph.vertices.first!, weight: 0, parent: nil)) + priorityQueue.enqueue((vertex: start, weight: 0, parent: nil)) while let head = priorityQueue.dequeue() { let vertex = head.vertex if visited.contains(vertex) { @@ -43,3 +43,4 @@ func minimumSpanningTreePrim(graph: Graph) -> (cost: Int, tree: Graph) return (cost: cost, tree: tree) } + From ea777fb3bc861e4818c414a97eb72fb8b9e3b644 Mon Sep 17 00:00:00 2001 From: Xiangxin Date: Sat, 6 May 2017 13:08:41 +0800 Subject: [PATCH 1016/1679] refactor --- .../Sources/Graph.swift | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/Graph.swift b/Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/Graph.swift index a2f243202..5e74e14cb 100644 --- a/Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/Graph.swift +++ b/Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/Graph.swift @@ -37,17 +37,11 @@ public struct Graph: CustomStringConvertible { vertices.insert(v1) vertices.insert(v2) - if let _ = adjList[v1] { - adjList[v1]?.append((vertex: v2, weight: w)) - } else { - adjList[v1] = [(vertex: v2, weight: w)] - } + adjList[v1] = adjList[v1] ?? [] + adjList[v1]?.append((vertex: v2, weight: w)) - if let _ = adjList[v2] { - adjList[v2]?.append((vertex: v1, weight: w)) - } else { - adjList[v2] = [(vertex: v1, weight: w)] - } + adjList[v2] = adjList[v2] ?? [] + adjList[v2]?.append((vertex: v1, weight: w)) } public mutating func addEdge(_ edge: Edge) { From 12fac48235b369612be3a96b807e4e4ba2ad237c Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Sun, 7 May 2017 04:45:19 -0700 Subject: [PATCH 1017/1679] Fixed spacing, and fixes some English. --- .../UnionFind.playground/Contents.swift | 24 ++--- .../Sources/UnionFindQuickFind.swift | 80 ++++++++-------- .../Sources/UnionFindQuickUnion.swift | 82 ++++++++-------- .../Sources/UnionFindWeightedQuickFind.swift | 94 +++++++++---------- .../Sources/UnionFindWeightedQuickUnion.swift | 92 +++++++++--------- ...indWeightedQuickUnionPathCompression.swift | 86 ++++++++--------- 6 files changed, 229 insertions(+), 229 deletions(-) diff --git a/Union-Find/UnionFind.playground/Contents.swift b/Union-Find/UnionFind.playground/Contents.swift index 9ad5215b3..0a50d1ba6 100644 --- a/Union-Find/UnionFind.playground/Contents.swift +++ b/Union-Find/UnionFind.playground/Contents.swift @@ -3,17 +3,17 @@ var dsu = UnionFindQuickUnion() for i in 1...10 { - dsu.addSetWith(i) + dsu.addSetWith(i) } // now our dsu contains 10 independent sets // let's divide our numbers into two sets by divisibility by 2 for i in 3...10 { - if i % 2 == 0 { - dsu.unionSetsContaining(2, and: i) - } else { - dsu.unionSetsContaining(1, and: i) - } + if i % 2 == 0 { + dsu.unionSetsContaining(2, and: i) + } else { + dsu.unionSetsContaining(1, and: i) + } } // check our division @@ -42,12 +42,12 @@ dsuForStrings.addSetWith("b") // In that example we divide strings by its first letter for word in words { - dsuForStrings.addSetWith(word) - if word.hasPrefix("a") { - dsuForStrings.unionSetsContaining("a", and: word) - } else if word.hasPrefix("b") { - dsuForStrings.unionSetsContaining("b", and: word) - } + dsuForStrings.addSetWith(word) + if word.hasPrefix("a") { + dsuForStrings.unionSetsContaining("a", and: word) + } else if word.hasPrefix("b") { + dsuForStrings.unionSetsContaining("b", and: word) + } } print(dsuForStrings.inSameSet("a", and: "all")) diff --git a/Union-Find/UnionFind.playground/Sources/UnionFindQuickFind.swift b/Union-Find/UnionFind.playground/Sources/UnionFindQuickFind.swift index 25d7f5b5d..33e81832d 100644 --- a/Union-Find/UnionFind.playground/Sources/UnionFindQuickFind.swift +++ b/Union-Find/UnionFind.playground/Sources/UnionFindQuickFind.swift @@ -3,48 +3,48 @@ import Foundation /// Quick-find algorithm may take ~MN steps /// to process M union commands on N objects public struct UnionFindQuickFind { - private var index = [T: Int]() - private var parent = [Int]() - private var size = [Int]() - - public init() {} - - public mutating func addSetWith(_ element: T) { - index[element] = parent.count - parent.append(parent.count) - size.append(1) + private var index = [T: Int]() + private var parent = [Int]() + private var size = [Int]() + + public init() {} + + public mutating func addSetWith(_ element: T) { + index[element] = parent.count + parent.append(parent.count) + size.append(1) + } + + private mutating func setByIndex(_ index: Int) -> Int { + return parent[index] + } + + public mutating func setOf(_ element: T) -> Int? { + if let indexOfElement = index[element] { + return setByIndex(indexOfElement) + } else { + return nil } - - private mutating func setByIndex(_ index: Int) -> Int { - return parent[index] - } - - public mutating func setOf(_ element: T) -> Int? { - if let indexOfElement = index[element] { - return setByIndex(indexOfElement) - } else { - return nil - } - } - - public mutating func unionSetsContaining(_ firstElement: T, and secondElement: T) { - if let firstSet = setOf(firstElement), let secondSet = setOf(secondElement) { - if firstSet != secondSet { - for index in 0.. Bool { - if let firstSet = setOf(firstElement), let secondSet = setOf(secondElement) { - return firstSet == secondSet - } else { - return false - } + } + + public mutating func inSameSet(_ firstElement: T, and secondElement: T) -> Bool { + if let firstSet = setOf(firstElement), let secondSet = setOf(secondElement) { + return firstSet == secondSet + } else { + return false } + } } diff --git a/Union-Find/UnionFind.playground/Sources/UnionFindQuickUnion.swift b/Union-Find/UnionFind.playground/Sources/UnionFindQuickUnion.swift index 4c848e61d..9bff31616 100644 --- a/Union-Find/UnionFind.playground/Sources/UnionFindQuickUnion.swift +++ b/Union-Find/UnionFind.playground/Sources/UnionFindQuickUnion.swift @@ -3,49 +3,49 @@ import Foundation /// Quick-Union algorithm may take ~MN steps /// to process M union commands on N objects public struct UnionFindQuickUnion { - private var index = [T: Int]() - private var parent = [Int]() - private var size = [Int]() - - public init() {} - - public mutating func addSetWith(_ element: T) { - index[element] = parent.count - parent.append(parent.count) - size.append(1) + private var index = [T: Int]() + private var parent = [Int]() + private var size = [Int]() + + public init() {} + + public mutating func addSetWith(_ element: T) { + index[element] = parent.count + parent.append(parent.count) + size.append(1) + } + + private mutating func setByIndex(_ index: Int) -> Int { + if parent[index] == index { + return index + } else { + parent[index] = setByIndex(parent[index]) + return parent[index] } - - private mutating func setByIndex(_ index: Int) -> Int { - if parent[index] == index { - return index - } else { - parent[index] = setByIndex(parent[index]) - return parent[index] - } + } + + public mutating func setOf(_ element: T) -> Int? { + if let indexOfElement = index[element] { + return setByIndex(indexOfElement) + } else { + return nil } - - public mutating func setOf(_ element: T) -> Int? { - if let indexOfElement = index[element] { - return setByIndex(indexOfElement) - } else { - return nil - } + } + + public mutating func unionSetsContaining(_ firstElement: T, and secondElement: T) { + if let firstSet = setOf(firstElement), let secondSet = setOf(secondElement) { + if firstSet != secondSet { + parent[firstSet] = secondSet + size[secondSet] += size[firstSet] + } } - - public mutating func unionSetsContaining(_ firstElement: T, and secondElement: T) { - if let firstSet = setOf(firstElement), let secondSet = setOf(secondElement) { - if firstSet != secondSet { - parent[firstSet] = secondSet - size[secondSet] += size[firstSet] - } - } - } - - public mutating func inSameSet(_ firstElement: T, and secondElement: T) -> Bool { - if let firstSet = setOf(firstElement), let secondSet = setOf(secondElement) { - return firstSet == secondSet - } else { - return false - } + } + + public mutating func inSameSet(_ firstElement: T, and secondElement: T) -> Bool { + if let firstSet = setOf(firstElement), let secondSet = setOf(secondElement) { + return firstSet == secondSet + } else { + return false } + } } diff --git a/Union-Find/UnionFind.playground/Sources/UnionFindWeightedQuickFind.swift b/Union-Find/UnionFind.playground/Sources/UnionFindWeightedQuickFind.swift index 02bec94a8..c89f2a457 100644 --- a/Union-Find/UnionFind.playground/Sources/UnionFindWeightedQuickFind.swift +++ b/Union-Find/UnionFind.playground/Sources/UnionFindWeightedQuickFind.swift @@ -3,57 +3,57 @@ import Foundation /// Quick-find algorithm may take ~MN steps /// to process M union commands on N objects public struct UnionFindWeightedQuickFind { - private var index = [T: Int]() - private var parent = [Int]() - private var size = [Int]() - - public init() {} - - public mutating func addSetWith(_ element: T) { - index[element] = parent.count - parent.append(parent.count) - size.append(1) + private var index = [T: Int]() + private var parent = [Int]() + private var size = [Int]() + + public init() {} + + public mutating func addSetWith(_ element: T) { + index[element] = parent.count + parent.append(parent.count) + size.append(1) + } + + private mutating func setByIndex(_ index: Int) -> Int { + return parent[index] + } + + public mutating func setOf(_ element: T) -> Int? { + if let indexOfElement = index[element] { + return setByIndex(indexOfElement) + } else { + return nil } - - private mutating func setByIndex(_ index: Int) -> Int { - return parent[index] - } - - public mutating func setOf(_ element: T) -> Int? { - if let indexOfElement = index[element] { - return setByIndex(indexOfElement) + } + + public mutating func unionSetsContaining(_ firstElement: T, and secondElement: T) { + if let firstSet = setOf(firstElement), let secondSet = setOf(secondElement) { + if firstSet != secondSet { + if size[firstSet] < size[secondSet] { + for index in 0.. Bool { - if let firstSet = setOf(firstElement), let secondSet = setOf(secondElement) { - return firstSet == secondSet - } else { - return false - } + } + + public mutating func inSameSet(_ firstElement: T, and secondElement: T) -> Bool { + if let firstSet = setOf(firstElement), let secondSet = setOf(secondElement) { + return firstSet == secondSet + } else { + return false } + } } diff --git a/Union-Find/UnionFind.playground/Sources/UnionFindWeightedQuickUnion.swift b/Union-Find/UnionFind.playground/Sources/UnionFindWeightedQuickUnion.swift index b3ac7445e..cd33007bc 100644 --- a/Union-Find/UnionFind.playground/Sources/UnionFindWeightedQuickUnion.swift +++ b/Union-Find/UnionFind.playground/Sources/UnionFindWeightedQuickUnion.swift @@ -1,56 +1,56 @@ import Foundation public struct UnionFindWeightedQuickUnion { - private var index = [T: Int]() - private var parent = [Int]() - private var size = [Int]() - - public init() {} - - public mutating func addSetWith(_ element: T) { - index[element] = parent.count - parent.append(parent.count) - size.append(1) + private var index = [T: Int]() + private var parent = [Int]() + private var size = [Int]() + + public init() {} + + public mutating func addSetWith(_ element: T) { + index[element] = parent.count + parent.append(parent.count) + size.append(1) + } + + private mutating func setByIndex(_ index: Int) -> Int { + if parent[index] == index { + return index + } else { + parent[index] = setByIndex(parent[index]) + return parent[index] } - - private mutating func setByIndex(_ index: Int) -> Int { - if parent[index] == index { - return index - } else { - parent[index] = setByIndex(parent[index]) - return parent[index] - } + } + + public mutating func setOf(_ element: T) -> Int? { + if let indexOfElement = index[element] { + return setByIndex(indexOfElement) + } else { + return nil } - - public mutating func setOf(_ element: T) -> Int? { - if let indexOfElement = index[element] { - return setByIndex(indexOfElement) + } + + /// Weighted, by comparing set size. + /// Merge small set into the large one. + public mutating func unionSetsContaining(_ firstElement: T, and secondElement: T) { + if let firstSet = setOf(firstElement), let secondSet = setOf(secondElement) { + if firstSet != secondSet { + if size[firstSet] < size[secondSet] { + parent[firstSet] = secondSet + size[secondSet] += size[firstSet] } else { - return nil - } - } - - /// Weighted, by comparing set size. - /// Merge small set into the large one. - public mutating func unionSetsContaining(_ firstElement: T, and secondElement: T) { - if let firstSet = setOf(firstElement), let secondSet = setOf(secondElement) { - if firstSet != secondSet { - if size[firstSet] < size[secondSet] { - parent[firstSet] = secondSet - size[secondSet] += size[firstSet] - } else { - parent[secondSet] = firstSet - size[firstSet] += size[secondSet] - } - } + parent[secondSet] = firstSet + size[firstSet] += size[secondSet] } + } } - - public mutating func inSameSet(_ firstElement: T, and secondElement: T) -> Bool { - if let firstSet = setOf(firstElement), let secondSet = setOf(secondElement) { - return firstSet == secondSet - } else { - return false - } + } + + public mutating func inSameSet(_ firstElement: T, and secondElement: T) -> Bool { + if let firstSet = setOf(firstElement), let secondSet = setOf(secondElement) { + return firstSet == secondSet + } else { + return false } + } } diff --git a/Union-Find/UnionFind.playground/Sources/UnionFindWeightedQuickUnionPathCompression.swift b/Union-Find/UnionFind.playground/Sources/UnionFindWeightedQuickUnionPathCompression.swift index 892f46a3c..7eb8fe209 100644 --- a/Union-Find/UnionFind.playground/Sources/UnionFindWeightedQuickUnionPathCompression.swift +++ b/Union-Find/UnionFind.playground/Sources/UnionFindWeightedQuickUnionPathCompression.swift @@ -1,53 +1,53 @@ import Foundation public struct UnionFindWeightedQuickUnionPathCompression { - private var index = [T: Int]() - private var parent = [Int]() - private var size = [Int]() - - public init() {} - - public mutating func addSetWith(_ element: T) { - index[element] = parent.count - parent.append(parent.count) - size.append(1) + private var index = [T: Int]() + private var parent = [Int]() + private var size = [Int]() + + public init() {} + + public mutating func addSetWith(_ element: T) { + index[element] = parent.count + parent.append(parent.count) + size.append(1) + } + + /// Path Compression. + private mutating func setByIndex(_ index: Int) -> Int { + if index != parent[index] { + parent[index] = setByIndex(parent[index]) } - - /// Path Compression. - private mutating func setByIndex(_ index: Int) -> Int { - if index != parent[index] { - parent[index] = setByIndex(parent[index]) - } - return parent[index] + return parent[index] + } + + public mutating func setOf(_ element: T) -> Int? { + if let indexOfElement = index[element] { + return setByIndex(indexOfElement) + } else { + return nil } - - public mutating func setOf(_ element: T) -> Int? { - if let indexOfElement = index[element] { - return setByIndex(indexOfElement) + } + + public mutating func unionSetsContaining(_ firstElement: T, and secondElement: T) { + if let firstSet = setOf(firstElement), let secondSet = setOf(secondElement) { + if firstSet != secondSet { + if size[firstSet] < size[secondSet] { + parent[firstSet] = secondSet + size[secondSet] += size[firstSet] } else { - return nil - } - } - - public mutating func unionSetsContaining(_ firstElement: T, and secondElement: T) { - if let firstSet = setOf(firstElement), let secondSet = setOf(secondElement) { - if firstSet != secondSet { - if size[firstSet] < size[secondSet] { - parent[firstSet] = secondSet - size[secondSet] += size[firstSet] - } else { - parent[secondSet] = firstSet - size[firstSet] += size[secondSet] - } - } + parent[secondSet] = firstSet + size[firstSet] += size[secondSet] } + } } - - public mutating func inSameSet(_ firstElement: T, and secondElement: T) -> Bool { - if let firstSet = setOf(firstElement), let secondSet = setOf(secondElement) { - return firstSet == secondSet - } else { - return false - } + } + + public mutating func inSameSet(_ firstElement: T, and secondElement: T) -> Bool { + if let firstSet = setOf(firstElement), let secondSet = setOf(secondElement) { + return firstSet == secondSet + } else { + return false } + } } From e560f60fc35889fefba95389ea53c6d02a9e22e9 Mon Sep 17 00:00:00 2001 From: Jawwad Ahmad Date: Mon, 8 May 2017 01:09:02 +0500 Subject: [PATCH 1018/1679] Fix a few typos in DiningPhilosophers Readme an -> a dinining -> dining "no needs" -> "no need" --- DiningPhilosophers/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/DiningPhilosophers/README.md b/DiningPhilosophers/README.md index 0bf4f28ce..bc622e559 100755 --- a/DiningPhilosophers/README.md +++ b/DiningPhilosophers/README.md @@ -22,12 +22,12 @@ Eating is not limited by the remaining amounts of spaghetti or stomach space; an The problem is how to design a discipline of behavior (a concurrent algorithm) such that no philosopher will starve; i.e., each can forever continue to alternate between eating and thinking, assuming that no philosopher can know when others may want to eat or think. -This is an illustration of an dinining table: +This is an illustration of a dining table: ![Dining Philosophers table](https://upload.wikimedia.org/wikipedia/commons/7/7b/An_illustration_of_the_dining_philosophers_problem.png) # Solution -There are different solutions for this classic algorithm, and this Swift implementation is based on the Chandy/Misra solution. This implementation allows agents to contend for an arbitrary number of resources in a completely distributed scenario with no needs for a central authority to control the locking and serialization of resources. +There are different solutions for this classic algorithm, and this Swift implementation is based on the Chandy/Misra solution. This implementation allows agents to contend for an arbitrary number of resources in a completely distributed scenario with no need for a central authority to control the locking and serialization of resources. However, this solution violates the requirement that "the philosophers do not speak to each other" (due to the request messages). From 297b0d4679fbd8607edb5b59b87d273962354e84 Mon Sep 17 00:00:00 2001 From: Jawwad Ahmad Date: Mon, 8 May 2017 01:26:16 +0500 Subject: [PATCH 1019/1679] Fix minor grammar typo --- Graph/README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Graph/README.markdown b/Graph/README.markdown index bc33b044a..d3c8b89e5 100644 --- a/Graph/README.markdown +++ b/Graph/README.markdown @@ -143,7 +143,7 @@ Here is an example of a simple graph: ![Demo](Images/Demo1.png) -We can represent it as an adjacency matrix or adjacency list. The classes implementing those concept both inherit a common API from `AbstractGraph`, so they can be created in an identical fashion, with different optimized data structures behind the scenes. +We can represent it as an adjacency matrix or adjacency list. The classes implementing those concepts both inherit a common API from `AbstractGraph`, so they can be created in an identical fashion, with different optimized data structures behind the scenes. Let's create some directed, weighted graphs, using each representation, to store the example: From 24d5adeba873dc184e2fc28dcaf942b15c60b95e Mon Sep 17 00:00:00 2001 From: Jawwad Ahmad Date: Mon, 8 May 2017 01:32:34 +0500 Subject: [PATCH 1020/1679] Fix broken links by replacing spaces with %20 --- Heap/README.markdown | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Heap/README.markdown b/Heap/README.markdown index 7beea4f34..a3b0038ab 100644 --- a/Heap/README.markdown +++ b/Heap/README.markdown @@ -1,11 +1,11 @@ # Heap -A heap is a [binary tree](../Binary Tree/) inside an array, so it does not use parent/child pointers. A heap is sorted based on the "heap property" that determines the order of the nodes in the tree. +A heap is a [binary tree](../Binary%20Tree/) inside an array, so it does not use parent/child pointers. A heap is sorted based on the "heap property" that determines the order of the nodes in the tree. Common uses for heap: -- To build [priority queues](../Priority Queue/). -- To support [heap sorts](../Heap Sort/). +- To build [priority queues](../Priority%20Queue/). +- To support [heap sorts](../Heap%20Sort/). - To compute the minimum (or maximum) element of a collection quickly. - To impress your non-programmer friends. @@ -21,7 +21,7 @@ An example: This is a max-heap because every parent node is greater than its children. `(10)` is greater than `(7)` and `(2)`. `(7)` is greater than `(5)` and `(1)`. -As a result of this heap property, a max-heap always stores its largest item at the root of the tree. For a min-heap, the root is always the smallest item in the tree. The heap property is useful because heaps are often used as a [priority queue](../Priority Queue/)to access the "most important" element quickly. +As a result of this heap property, a max-heap always stores its largest item at the root of the tree. For a min-heap, the root is always the smallest item in the tree. The heap property is useful because heaps are often used as a [priority queue](../Priority%20Queue/)to access the "most important" element quickly. > **Note:** The root of the heap has the maximum or minimum element, but the sort order of other elements are not predictable. For example, the maximum element is always at index 0 in a max-heap, but the minimum element isn’t necessarily the last one. -- the only guarantee you have is that it is one of the leaf nodes, but not which one. @@ -30,11 +30,11 @@ As a result of this heap property, a max-heap always stores its largest item at A heap is not a replacement for a binary search tree, and there are similarities and differnces between them. Here are some main differences: -**Order of the nodes.** In a [binary search tree (BST)](../Binary Search Tree/), the left child must be smaller than its parent, and the right child must be greater. This is not true for a heap. In a max-heap both children must be smaller than the parent, while in a min-heap they both must be greater. +**Order of the nodes.** In a [binary search tree (BST)](../Binary%20Search%20Tree/), the left child must be smaller than its parent, and the right child must be greater. This is not true for a heap. In a max-heap both children must be smaller than the parent, while in a min-heap they both must be greater. **Memory.** Traditional trees take up more memory than just the data they store. You need to allocate additional storage for the node objects and pointers to the left/right child nodes. A heap only uses a plain array for storage and uses no pointers. -**Balancing.** A binary search tree must be "balanced" so that most operations have **O(log n)** performance. You can either insert and delete your data in a random order or use something like an [AVL tree](../AVL Tree/) or [red-black tree](../Red-Black Tree/), but with heaps we don't actually need the entire tree to be sorted. We just want the heap property to be fulfilled, so balancing isn't an issue. Because of the way the heap is structured, heaps can guarantee **O(log n)** performance. +**Balancing.** A binary search tree must be "balanced" so that most operations have **O(log n)** performance. You can either insert and delete your data in a random order or use something like an [AVL tree](../AVL%20Tree/) or [red-black tree](../Red-Black%20Tree/), but with heaps we don't actually need the entire tree to be sorted. We just want the heap property to be fulfilled, so balancing isn't an issue. Because of the way the heap is structured, heaps can guarantee **O(log n)** performance. **Searching.** Whereas searching is fast in a binary tree, it is slow in a heap. Searching isn't a top priority in a heap since the purpose of a heap is to put the largest (or smallest) node at the front and to allow relatively fast inserts and deletes. @@ -112,7 +112,7 @@ Is this a valid heap? The answer is yes! A sorted array from low-to-high is a va The heap property holds for each node because a parent is always smaller than its children. (Verify for yourself that an array sorted from high-to-low is always a valid max-heap.) -> **Note:** But not every min-heap is necessarily a sorted array! It only works one way. To turn a heap back into a sorted array, you need to use [heap sort](../Heap Sort/). +> **Note:** But not every min-heap is necessarily a sorted array! It only works one way. To turn a heap back into a sorted array, you need to use [heap sort](../Heap%20Sort/). ## More math! @@ -162,7 +162,7 @@ All of the above take time **O(log n)** because shifting up or down is expensive - `buildHeap(array)`: Converts an (unsorted) array into a heap by repeatedly calling `insert()`. If you are smart about this, it can be done in **O(n)** time. -- [Heap sort](../Heap Sort/). Since the heap is an array, we can use its unique properties to sort the array from low to high. Time: **O(n lg n).** +- [Heap sort](../Heap%20Sort/). Since the heap is an array, we can use its unique properties to sort the array from low to high. Time: **O(n lg n).** The heap also has a `peek()` function that returns the maximum (max-heap) or minimum (min-heap) element, without removing it from the heap. Time: **O(1)**. @@ -289,7 +289,7 @@ Here, `elements` is the heap's own array. We walk backwards through this array, Heaps are not made for fast searches, but if you want to remove an arbitrary element using `removeAtIndex()` or change the value of an element with `replace()`, then you need to obtain the index of that element. Searching is one way to do this, but it is slow. -In a [binary search tree](../Binary Search Tree/), depending on the order of the nodes, a fast search can be guaranteed. Since a heap orders its nodes differently, a binary search will not work, and you need to check every node in the tree. +In a [binary search tree](../Binary%20Search%20Tree/), depending on the order of the nodes, a fast search can be guaranteed. Since a heap orders its nodes differently, a binary search will not work, and you need to check every node in the tree. Let's take our example heap again: From 1eb61c97a7949a0088834759bd9b1f40d884a9e9 Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Mon, 8 May 2017 05:16:23 -0700 Subject: [PATCH 1021/1679] Improves the wording for a few sentences. --- Union-Find/README.markdown | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Union-Find/README.markdown b/Union-Find/README.markdown index dfec7dbe6..a268f1d70 100644 --- a/Union-Find/README.markdown +++ b/Union-Find/README.markdown @@ -9,7 +9,7 @@ What do we mean by this? For example, the Union-Find data structure could be kee [ g, d, c ] [ i, j ] -These sets are disjoint because they have no members in common. +These sets are **disjoint** because they have no members in common. Union-Find supports three basic operations: @@ -24,7 +24,7 @@ The most common application of this data structure is keeping track of the conne ## Implementation Union-Find can be implemented in many ways but we'll look at an efficient and easy to understand implementation: Weighted Quick Union. -> __PS: Variety implementation of Union-Find has been included in playground.__ +> __PS: Multiple implementations of Union-Find has been included in playground.__ ```swift public struct UnionFind { @@ -198,7 +198,7 @@ private mutating func setByIndex(_ index: Int) -> Int { ``` Path Compression helps keep trees very flat, thus find operation could take __ALMOST__ in __O(1)__ -## Complexity Summary of Variety Implementation +## Complexity Summary ##### To process N objects | Data Structure | Union | Find | From a087b19f146e32ac731fac5c4c989b1eff3c7401 Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Mon, 8 May 2017 05:17:49 -0700 Subject: [PATCH 1022/1679] Fixes spelling. --- DiningPhilosophers/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DiningPhilosophers/README.md b/DiningPhilosophers/README.md index 0bf4f28ce..e4db0d7e0 100755 --- a/DiningPhilosophers/README.md +++ b/DiningPhilosophers/README.md @@ -10,7 +10,7 @@ In computer science, the dining philosophers problem is often used in the concur It was originally formulated in 1965 by Edsger Dijkstra as a student exam exercise, presented in terms of computers competing for access to tape drive peripherals. Soon after, Tony Hoare gave the problem its present formulation. -This Swift implementation is based on the Chandy/Misra solution, and it uses the GCD Dispatch and Semaphone on the Swift cross platform. +This Swift implementation is based on the Chandy/Misra solution, and it uses the GCD Dispatch and Semaphores on the Swift cross platform. # Problem statement From 988e354fed9122acb0b7b7ec8098b0a29c374070 Mon Sep 17 00:00:00 2001 From: Mike Date: Mon, 8 May 2017 18:54:43 -0400 Subject: [PATCH 1023/1679] Formatted headers in readme Github seems to require spaces between "#" and headings . --- Radix Sort/ReadMe.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Radix Sort/ReadMe.md b/Radix Sort/ReadMe.md index 5bdb931ca..ceb4459d7 100644 --- a/Radix Sort/ReadMe.md +++ b/Radix Sort/ReadMe.md @@ -2,19 +2,19 @@ Radix sort is a sorting algorithm that takes as input an array of integers and uses a sorting subroutine( that is often another efficient sorting algorith) to sort the integers by their radix, or rather their digit. Counting Sort, and Bucket Sort are often times used as the subroutine for Radix Sort. -##Example +## Example * Input Array: [170, 45, 75, 90, 802, 24, 2, 66] * Output Array (Sorted): [2, 24, 45, 66, 75, 90, 170, 802] -###Step 1: +### Step 1: The first step in this algorithm is to define the digit or rather the "base" or radix that we will use to sort. For this example we will let radix = 10, since the integers we are working with in the example are of base 10. -###Step 2: +### Step 2: The next step is to simply iterate n times (where n is the number of digits in the largest integer in the input array), and upon each iteration perform a sorting subroutine on the current digit in question. -###Algorithm in Action +### Algorithm in Action Let's take a look at our example input array. From 90730ade45d11947529e51acf15e09f1ef622596 Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Tue, 16 May 2017 09:56:13 -0700 Subject: [PATCH 1024/1679] Fixes #464. --- Threaded Binary Tree/README.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Threaded Binary Tree/README.markdown b/Threaded Binary Tree/README.markdown index 8a1c518f1..f631b86f9 100644 --- a/Threaded Binary Tree/README.markdown +++ b/Threaded Binary Tree/README.markdown @@ -267,9 +267,9 @@ something simple, like removing **7**, which has no children: Before we can just throw **7** away, we have to perform some clean-up. In this case, because **7** is a `right` child and has no children itself, we can simply set the `rightThread` of **7**'s `parent`(**5**) to **7**'s (now -outdated) `rightThread`. Then we can just set **7**'s `parent`, `left`, +outdated) `rightThread`. Then we can just set **7**'s `parent`, `left`, `right`, `leftThread`, and `rightThread` to `nil`, effectively removing it from -the tree. +the tree. We also set the parent's `rightChild` to `nil`, which completes the deletion of this right child. Let's try something a little harder. Say we remove **5** from the tree: From cde6f854865d19c4cefb187894a4da09a0be4fee Mon Sep 17 00:00:00 2001 From: Jawwad Ahmad Date: Wed, 17 May 2017 05:16:52 +0500 Subject: [PATCH 1025/1679] Fix a few typos in Heap/README --- Heap/README.markdown | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Heap/README.markdown b/Heap/README.markdown index a3b0038ab..bb7a785a5 100644 --- a/Heap/README.markdown +++ b/Heap/README.markdown @@ -21,7 +21,7 @@ An example: This is a max-heap because every parent node is greater than its children. `(10)` is greater than `(7)` and `(2)`. `(7)` is greater than `(5)` and `(1)`. -As a result of this heap property, a max-heap always stores its largest item at the root of the tree. For a min-heap, the root is always the smallest item in the tree. The heap property is useful because heaps are often used as a [priority queue](../Priority%20Queue/)to access the "most important" element quickly. +As a result of this heap property, a max-heap always stores its largest item at the root of the tree. For a min-heap, the root is always the smallest item in the tree. The heap property is useful because heaps are often used as a [priority queue](../Priority%20Queue/) to access the "most important" element quickly. > **Note:** The root of the heap has the maximum or minimum element, but the sort order of other elements are not predictable. For example, the maximum element is always at index 0 in a max-heap, but the minimum element isn’t necessarily the last one. -- the only guarantee you have is that it is one of the leaf nodes, but not which one. @@ -124,7 +124,7 @@ This heap has height 3, so it has 4 levels: ![Large heap](Images/LargeHeap.png) -A heap with *n* nodes has height *h = floor(log_2(n))*. This is because we always fill up the lowest level completely before we add a new level. The example has 15 nodes, so the height is `floor(log_2(15)) = floor(3.91) = 3`. +A heap with *n* nodes has height *h = floor(log2(n))*. This is because we always fill up the lowest level completely before we add a new level. The example has 15 nodes, so the height is `floor(log2(15)) = floor(3.91) = 3`. If the lowest level is completely full, then that level contains *2^h* nodes. The rest of the tree above it contains *2^h - 1* nodes. Fill in the numbers from the example: the lowest level has 8 nodes, which indeed is `2^3 = 8`. The first three levels contain a total of 7 nodes, i.e. `2^3 - 1 = 8 - 1 = 7`. @@ -303,7 +303,7 @@ Let's say we want to see if the heap contains the value `8` (it doesn't). We sta Despite this small optimization, searching is still an **O(n)** operation. -> **Note:** There is away to turn lookups into a **O(1)** operation by keeping an additional dictionary that maps node values to indices. This may be worth doing if you often need to call `replace()` to change the "priority" of objects in a [priority queue](../Priority%20Queue/) that's built on a heap. +> **Note:** There is a way to turn lookups into a **O(1)** operation by keeping an additional dictionary that maps node values to indices. This may be worth doing if you often need to call `replace()` to change the "priority" of objects in a [priority queue](../Priority%20Queue/) that's built on a heap. ## The code From c014bd9a0823d6206fa18e915f6e4f01d5852beb Mon Sep 17 00:00:00 2001 From: Artur Date: Wed, 17 May 2017 03:19:47 +0300 Subject: [PATCH 1026/1679] remove "countingSort" func throws if you received empty array, just return empty array --- Counting Sort/CountingSort.swift | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/Counting Sort/CountingSort.swift b/Counting Sort/CountingSort.swift index abece0213..725a634a4 100644 --- a/Counting Sort/CountingSort.swift +++ b/Counting Sort/CountingSort.swift @@ -6,14 +6,8 @@ // Copyright © 2016 Ali Hafizji. All rights reserved. // -enum CountingSortError: Error { - case arrayEmpty -} - -func countingSort(_ array: [Int]) throws -> [Int] { - guard array.count > 0 else { - throw CountingSortError.arrayEmpty - } +func countingSort(_ array: [Int])-> [Int] { + guard array.count > 0 else {return []} // Step 1 // Create an array to store the count of each element From d705414bbcf2eb62232d5c456befc193e397b208 Mon Sep 17 00:00:00 2001 From: Jawwad Ahmad Date: Wed, 17 May 2017 05:20:54 +0500 Subject: [PATCH 1027/1679] Update displayed code to use 2 space indentation --- Heap Sort/README.markdown | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Heap Sort/README.markdown b/Heap Sort/README.markdown index 7fdd8d2ca..a45dad6f9 100644 --- a/Heap Sort/README.markdown +++ b/Heap Sort/README.markdown @@ -48,13 +48,13 @@ Here's how you can implement heap sort in Swift: ```swift extension Heap { - public mutating func sort() -> [T] { - for i in stride(from: (elements.count - 1), through: 1, by: -1) { - swap(&elements[0], &elements[i]) - shiftDown(0, heapSize: i) - } - return elements + public mutating func sort() -> [T] { + for i in stride(from: (elements.count - 1), through: 1, by: -1) { + swap(&elements[0], &elements[i]) + shiftDown(0, heapSize: i) } + return elements + } } ``` @@ -71,9 +71,9 @@ We can write a handy helper function for that: ```swift public func heapsort(_ a: [T], _ sort: @escaping (T, T) -> Bool) -> [T] { - let reverseOrder = { i1, i2 in sort(i2, i1) } - var h = Heap(array: a, sort: reverseOrder) - return h.sort() + let reverseOrder = { i1, i2 in sort(i2, i1) } + var h = Heap(array: a, sort: reverseOrder) + return h.sort() } ``` From e311ee9b88a16d9dfaeacc7f2e7ea7825169fe8b Mon Sep 17 00:00:00 2001 From: Tobias Helmrich Date: Thu, 18 May 2017 21:52:38 +0900 Subject: [PATCH 1028/1679] Fix typos and markdown formatting --- Linear Regression/README.markdown | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Linear Regression/README.markdown b/Linear Regression/README.markdown index 1a1a1eb8b..29ac2e321 100644 --- a/Linear Regression/README.markdown +++ b/Linear Regression/README.markdown @@ -75,7 +75,7 @@ for n in 1...numberOfIterations { The program loops through each data point (each car age and car price). For each data point it adjusts the intercept and the slope to bring them closer to the correct values. The equations used in the code to adjust the intercept and the slope are based on moving in the direction of the maximal reduction of these variables. This is a *gradient descent*. -We want to minimse the square of the distance between the line and the points. We define a function `J` which represents this distance - for simplicity we consider only one point here. This function `J` is proprotional to `((slope.carAge + intercept) - carPrice)) ^ 2`. +We want to minimise the square of the distance between the line and the points. We define a function `J` which represents this distance - for simplicity we consider only one point here. This function `J` is proportional to `((slope.carAge + intercept) - carPrice)) ^ 2`. In order to move in the direction of maximal reduction, we take the partial derivative of this function with respect to the slope, and similarly for the intercept. We multiply these derivatives by our factor alpha and then use them to adjust the values of slope and intercept on each iteration. @@ -98,7 +98,7 @@ Here is the same data shown as a graph. Each of the blue lines on the graph repr After 18,000 iterations it looks as if the line is getting closer to what we would expect (just by looking) to be the correct line of best fit. Also, each additional 2,000 iterations has less and less effect on the final result - the values of the intercept and the slope are converging on the correct values. -##A closed form solution +## A closed form solution There is another way we can calculate the line of best fit, without having to do multiple iterations. We can solve the equations describing the least squares minimisation and just work out the intercept and slope directly. @@ -139,7 +139,7 @@ This function takes as arguments two arrays of Doubles, and returns a function w Using this line, we would predict a price for our 4 year old car of £6952. -##Summary +## Summary We've seen two different ways to implement a simple linear regression in Swift. An obvious question is: why bother with the iterative approach at all? Well, the line we've found doesn't fit the data perfectly. For one thing, the graph includes some negative values at high car ages! Possibly we would have to pay someone to tow away a very old car... but really these negative values just show that we have not modelled the real life situation very accurately. The relationship between the car age and the car price is not linear but instead is some other function. We also know that a car's price is not just related to its age but also other factors such as the make, model and engine size of the car. We would need to use additional variables to describe these other factors. From d2f02efd49d2367382c7a6fffc5fa1e3b74c8eff Mon Sep 17 00:00:00 2001 From: Barbara Martina Rodeker Date: Sun, 21 May 2017 21:46:01 +0200 Subject: [PATCH 1029/1679] Initial Docs template and text --- Splay Tree/readme.md | 61 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) diff --git a/Splay Tree/readme.md b/Splay Tree/readme.md index 2282502fa..aa6bdd4db 100644 --- a/Splay Tree/readme.md +++ b/Splay Tree/readme.md @@ -1 +1,60 @@ -In progress +# Splay Tree +Splay tree is a data structure, structurally identitical to a Balanced Binary Search Tree. Every operation performed on a Splay Tree causes a readjustment in order to provide fast access to recently operated values. On every access, the tree is rearranged and the node accessed is moved to the root of the tree using a set of specific rotations, which together are referred to as **Splaying**. + + +## Rotations + +### Zig-Zig + +Given a node *a* if *a* is not the root, and *a* has a child *b*, and both *a* and *b* are left children or right children, a **Zig-Zig** is performed. + +### Zig-Zag + +Given a node *a* if *a* is not the root, and *a* has a child *b*, and *b* is the left child of *a* being the right child (or the opporsite), a **Zig-Zag** is performed. + +### Zig + +A **Zig** is performed when the node *a* to be rotated has the root as parent. + +## Splaying + +## Operations + +### Insertion + +### Deletion + +### Search + +## Examples + +### Example 1 + +### Example 2 + +### Example 3 + +## Advantages + +Splay trees provide an efficient way to quickly access elements that are frequently requested. This characteristic makes then a good choice to implement, for exmaple, caches or garbage collection algorithms, or in any other problem involving frequent access to a certain numbers of elements from a data set. + +## Disadvantages + +Splay tree are not perfectly balanced always, so in case of accessing all the elements in the tree in an increasing order, the height of the tree becomes *n*. + +## Time complexity + +| Case | Performance | +| ------------- |:-------------:| +| Average | O(log n) | +| Worst | n | + +With *n* being the number of items in the tree. + + +## See also + +[Splay Tree on Wikipedia](https://en.wikipedia.org/wiki/Splay_tree) +[Splay Tree by University of California in Berkeley - CS 61B Lecture 34](https://www.youtube.com/watch?v=G5QIXywcJlY) + +*Written for Swift Algorithm Club by Mike Taghavi and Matthijs Hollemans* From 7f751918b92881d93aabce634a891b95f46a90f0 Mon Sep 17 00:00:00 2001 From: barbara Date: Sun, 21 May 2017 22:03:23 +0200 Subject: [PATCH 1030/1679] images for documentation --- Splay Tree/Images /zig.png | Bin 0 -> 7793 bytes Splay Tree/Images /zigzag1.png | Bin 0 -> 13964 bytes Splay Tree/Images /zigzag2.png | Bin 0 -> 13877 bytes Splay Tree/Images /zigzig1.png | Bin 0 -> 13855 bytes Splay Tree/Images /zigzig2.png | Bin 0 -> 15179 bytes 5 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 Splay Tree/Images /zig.png create mode 100644 Splay Tree/Images /zigzag1.png create mode 100644 Splay Tree/Images /zigzag2.png create mode 100644 Splay Tree/Images /zigzig1.png create mode 100644 Splay Tree/Images /zigzig2.png diff --git a/Splay Tree/Images /zig.png b/Splay Tree/Images /zig.png new file mode 100644 index 0000000000000000000000000000000000000000..e21522b6fe55f9529b2f818a4e108cd47964908b GIT binary patch literal 7793 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 YUzYE4d4Gxltz?jjlBQyfyhZr`0hMWjJpcdz literal 0 HcmV?d00001 diff --git a/Splay Tree/Images /zigzag1.png b/Splay Tree/Images /zigzag1.png new file mode 100644 index 0000000000000000000000000000000000000000..1bd40624802f9bbafa93472c6d3b8ec37711d0bc GIT binary patch literal 13964 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 W8y_a@5`1NbBL7lJrbNov@BaW;q?*+L literal 0 HcmV?d00001 diff --git a/Splay Tree/Images /zigzag2.png b/Splay Tree/Images /zigzag2.png new file mode 100644 index 0000000000000000000000000000000000000000..5f8e4c63f9763560028d3088396d3e24b5787b4a GIT binary patch literal 13877 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 literal 0 HcmV?d00001 diff --git a/Splay Tree/Images /zigzig1.png b/Splay Tree/Images /zigzig1.png new file mode 100644 index 0000000000000000000000000000000000000000..11ec330f2a33a56b5cb2aa983f05d7b9ed7b97c1 GIT binary patch literal 13855 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 LH5H2GUikfg>;GAg literal 0 HcmV?d00001 From 6c1c12651247ed73e3e727c0e7dc28e2a0b1e518 Mon Sep 17 00:00:00 2001 From: barbara Date: Sun, 21 May 2017 22:17:44 +0200 Subject: [PATCH 1031/1679] Images for examples documentation --- Splay Tree/Images /example1-1.png | Bin 0 -> 13964 bytes Splay Tree/Images /example1-2.png | Bin 0 -> 15451 bytes Splay Tree/Images /example1-3.png | Bin 0 -> 14778 bytes Splay Tree/Images /examplezig.svg | 2 ++ Splay Tree/Images /examplezig1.png | Bin 0 -> 6583 bytes Splay Tree/Images /examplezig2.png | Bin 0 -> 9317 bytes Splay Tree/Images /examplezigzig.svg | 2 ++ Splay Tree/Images /examplezigzig1.png | Bin 0 -> 13855 bytes Splay Tree/Images /examplezigzig2.png | Bin 0 -> 15247 bytes Splay Tree/Images /examplezigzig3.png | Bin 0 -> 18128 bytes 10 files changed, 4 insertions(+) create mode 100644 Splay Tree/Images /example1-1.png create mode 100644 Splay Tree/Images /example1-2.png create mode 100644 Splay Tree/Images /example1-3.png create mode 100644 Splay Tree/Images /examplezig.svg create mode 100644 Splay Tree/Images /examplezig1.png create mode 100644 Splay Tree/Images /examplezig2.png create mode 100644 Splay Tree/Images /examplezigzig.svg create mode 100644 Splay Tree/Images /examplezigzig1.png create mode 100644 Splay Tree/Images /examplezigzig2.png create mode 100644 Splay Tree/Images /examplezigzig3.png diff --git a/Splay Tree/Images /example1-1.png b/Splay Tree/Images /example1-1.png new file mode 100644 index 0000000000000000000000000000000000000000..1bd40624802f9bbafa93472c6d3b8ec37711d0bc GIT binary patch literal 13964 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 W8y_a@5`1NbBL7lJrbNov@BaW;q?*+L literal 0 HcmV?d00001 diff --git a/Splay Tree/Images /example1-2.png b/Splay Tree/Images /example1-2.png new file mode 100644 index 0000000000000000000000000000000000000000..46dd35bcd131dc43f7edb45a9efe7c6c585950f0 GIT binary patch literal 15451 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 TFbIB=iK8U1CRZY38t{JrK7T3H literal 0 HcmV?d00001 diff --git a/Splay Tree/Images /examplezig.svg b/Splay Tree/Images /examplezig.svg new file mode 100644 index 000000000..800ef1886 --- /dev/null +++ b/Splay Tree/Images /examplezig.svg @@ -0,0 +1,2 @@ + +
2
2
6
6
10
10
2
2
6
6
10
10
\ No newline at end of file diff --git a/Splay Tree/Images /examplezig1.png b/Splay Tree/Images /examplezig1.png new file mode 100644 index 0000000000000000000000000000000000000000..dda9d6de91d4dcd011fcc9356ee305a8c0eb68e1 GIT binary patch literal 6583 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 U21jw=A2I}Y(05T)YIYI-53Dwf-2eap literal 0 HcmV?d00001 diff --git a/Splay Tree/Images /examplezig2.png b/Splay Tree/Images /examplezig2.png new file mode 100644 index 0000000000000000000000000000000000000000..ba8a48867103c53ac775bd74046d239deaf747eb GIT binary patch literal 9317 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 literal 0 HcmV?d00001 diff --git a/Splay Tree/Images /examplezigzig.svg b/Splay Tree/Images /examplezigzig.svg new file mode 100644 index 000000000..7bd4dcf6f --- /dev/null +++ b/Splay Tree/Images /examplezigzig.svg @@ -0,0 +1,2 @@ + +
4
4
3
3
9
9
2
2
7
7
20
20
2 - ZIG
2 - ZIG
1 - ZIG
1 - ZIG
9
9
7
7
20
20
4
4
2
2
3
3
9
9
7
7
20
20
4
4
2
2
3
3
\ No newline at end of file diff --git a/Splay Tree/Images /examplezigzig1.png b/Splay Tree/Images /examplezigzig1.png new file mode 100644 index 0000000000000000000000000000000000000000..11ec330f2a33a56b5cb2aa983f05d7b9ed7b97c1 GIT binary patch literal 13855 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 OF;o-~@>Q~yVgCoGitcv+ literal 0 HcmV?d00001 diff --git a/Splay Tree/Images /examplezigzig3.png b/Splay Tree/Images /examplezigzig3.png new file mode 100644 index 0000000000000000000000000000000000000000..dbc40a3ba39fe01e44846dba5b16bd6cfed5a351 GIT binary patch literal 18128 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≻M%oM94;*+% zs-#srY}8qlCdTmMuu~$m?z*-&DSe>R`a6nmM!c4&<})trz~NJPh?j*%z!^v}X$~0W zDy3fgkzxE*fqo8(Awf-A1QXyKa(ZoiTx9(5)=nHA5*L6lh3*2b@F=Ll@679{@8Y!2 zX&>KK34&lT#vrqZ5k80k#nRSL>azz-l8{*j<9HAstR`f8zinjK(If5cyB&(9>D(YU9A0bcDCuSkc|IF4C3{LKCz`sXA8I_x?_@t*9ACN-f4z`G@uyClnqzYDC zFCB`i$_S3CWDL}U%SdDTjSmNUySh|4nT`j3MS*WZkx=qMyp9LHJK~g~nN%g|ADV`s zhoS@tB!Kb;3J-_L1T^Z3faX2yVo{!KVij<7&tayPRHN%~tPTJ+oT9tD$pe z2xMk9mP`%@Xo2`$+lrPLe@EUASf9m6+58!-O<5;Cq1AiH4UNYPjzf~-*OEQ z8WpdD4KDkMs=ZG}SR3^3snk4Pg+7UkdR;#3tx3)TJR;xS0lA%V+mg?qs#zRv&E7Ka zif-z_saNC%VmSv8OMs;sCr9VYUs}7>&h#3Ei)x33E@5X`K=mJw?R*@|4bKdRrN+m{ zzqt!-+WHC}b$Zh@q*MqP3PIhr{1Oc~kL^S!7KHpg2C-ZvGht}jZmQ6PqmW5

~t9TomnK zsmVR6O4QK&fW4Jf8*JhLtEUbaDFG#f#^pak$o>WWhx%-AP^g_=e*pL$l6lYMM}vom z^dA`n_Ex5vNtyjt<_1)n0UfqG-spd!N^7-igVUtl2quTdKDy>=$(G$9?T-l9HwEE& z;Bs|S$PJU}XZ{sB&K4&jv~T=w8ZvR9P0?&c6Iy5K7li0=Cy^DxMWDYR|^P ztT@r1KYw0fX;6+FaHCYLdGVb39B`k3w~B=X@EVraZ~qlDT&E<}uUP#_2@K>`y%)Rj z$=w=^-~ByL`h@PXHs!2(Viju2J7TX~QBssoS||%-WMn#F8$DGRP zV(fqvz6PxzMNLYr4&_FPIDa*NiKA=|rXo^2z8B8UsZ){lD`G5r)7TgLG8b7>Ug8F; zRDuf9^F|@g?&n+%(`!21qQ5i<(~3u{c$fYS6}Pb}NZy0!hN}U~VwhVu{*>Y)4cY%> ziX)B`=v5)(VF(`zA{vo+0vZ}Zf*S$)6;?4jo}h1q?yr7vtY2hs>U4K~M- zZ&WA;;=2_JZPtNNLr9PW#RVzh;NbgX-wUvj{FxRv z53m{%0t8Ltlali6(6yd!*r7%d8=UHD5buqNk0Y0G z_Cbh~jE>H+4&i4h`NccUyM_4t1y6%&?~iv6lCzpdHw*?Y2J`c4e-B;0#tFXE8-@v`k01P z3oWt>S)EA)-}@%#>k`0{9I@-7oAs`@`AP0xrZ2Bjv^JtaFOr zN3ccEtxxPAuP0ACaK`-TVt0B8jQ1p>upvQS3|FX{YDjzc(W>62B&_f9zY z$}o@}aGRFc*>Xq$vzzaUv74&*(}^#GAVF`W@E!xWZ3g~lnlo1%ySx9&5QxF8nEx|F zki`ma;Q!1J>@vMh_^%8>2KM>*uMEL4S-H?#5tyaXYOU`-2erUNQ!jb+lS6yR+MrizmH|0_pu`G0Z* z4+sd2&=5aF|3ggw=$|}sP^#9u2{<-KApCTq%;L&GbO0Z;f&%3eWcF z5Ha(yj5%4pi5%1~wZL_lAqA+(_Lm(;)|2iyX6!U8>BZQ_-;}%!(S0!xh)3|o_hi4j zy}$v4h?nG^x&fIy3k0!#zoVX{UupJ;4WNToTto3c1tDTc;}9$xxd**oBjhXwGDdkh z#wSEr^c^UyDF<>YS`2A9DI~|b&zzj z_#ck@CnCH}K+O)!FhFhv55cTTQ3M5NXv4fQptpAq+2(R}mg?e&N)_mbO*M>%JGd@D z(m2HHze2#m5l1x$s5B3H>5|>ae5k*dmlqo`x@BMB&uAtH{-RHdM_~k5fL}pPfco1@ z;h1zqZj{Xy1CMw#t*%WJMMBno}WAgIpn?|~^R-wC?v&D;mcj9{K| z!Qi&5pNd`h6-Y-oLVKo4LWW&bRFCCB((8m^LFB~WuhLKq0r81n*(XT}&@WhwPvJ)V z{}S4D^^>s+#|CS1ATp!&!7)!k-fabXN8h=^e&RcI5Oe(hP7$0$rt`qq1Leciq^9W! zNyX!U;Kb?a={fkx+hcjWvY_dobgm)t_U+pi0D6(q(eVJRw{kmXHbnaPib Date: Sun, 21 May 2017 22:20:42 +0200 Subject: [PATCH 1032/1679] delete blank images space --- Splay Tree/{Images => Images}/example1-1.png | Bin Splay Tree/{Images => Images}/example1-2.png | Bin Splay Tree/{Images => Images}/example1-3.png | Bin Splay Tree/{Images => Images}/examplezig.svg | 0 Splay Tree/{Images => Images}/examplezig1.png | Bin Splay Tree/{Images => Images}/examplezig2.png | Bin Splay Tree/{Images => Images}/examplezigzig.svg | 0 Splay Tree/{Images => Images}/examplezigzig1.png | Bin Splay Tree/{Images => Images}/examplezigzig2.png | Bin Splay Tree/{Images => Images}/examplezigzig3.png | Bin Splay Tree/{Images => Images}/zig.png | Bin Splay Tree/{Images => Images}/zigzag1.png | Bin Splay Tree/{Images => Images}/zigzag2.png | Bin Splay Tree/{Images => Images}/zigzig1.png | Bin Splay Tree/{Images => Images}/zigzig2.png | Bin 15 files changed, 0 insertions(+), 0 deletions(-) rename Splay Tree/{Images => Images}/example1-1.png (100%) rename Splay Tree/{Images => Images}/example1-2.png (100%) rename Splay Tree/{Images => Images}/example1-3.png (100%) rename Splay Tree/{Images => Images}/examplezig.svg (100%) rename Splay Tree/{Images => Images}/examplezig1.png (100%) rename Splay Tree/{Images => Images}/examplezig2.png (100%) rename Splay Tree/{Images => Images}/examplezigzig.svg (100%) rename Splay Tree/{Images => Images}/examplezigzig1.png (100%) rename Splay Tree/{Images => Images}/examplezigzig2.png (100%) rename Splay Tree/{Images => Images}/examplezigzig3.png (100%) rename Splay Tree/{Images => Images}/zig.png (100%) rename Splay Tree/{Images => Images}/zigzag1.png (100%) rename Splay Tree/{Images => Images}/zigzag2.png (100%) rename Splay Tree/{Images => Images}/zigzig1.png (100%) rename Splay Tree/{Images => Images}/zigzig2.png (100%) diff --git a/Splay Tree/Images /example1-1.png b/Splay Tree/Images/example1-1.png similarity index 100% rename from Splay Tree/Images /example1-1.png rename to Splay Tree/Images/example1-1.png diff --git a/Splay Tree/Images /example1-2.png b/Splay Tree/Images/example1-2.png similarity index 100% rename from Splay Tree/Images /example1-2.png rename to Splay Tree/Images/example1-2.png diff --git a/Splay Tree/Images /example1-3.png b/Splay Tree/Images/example1-3.png similarity index 100% rename from Splay Tree/Images /example1-3.png rename to Splay Tree/Images/example1-3.png diff --git a/Splay Tree/Images /examplezig.svg b/Splay Tree/Images/examplezig.svg similarity index 100% rename from Splay Tree/Images /examplezig.svg rename to Splay Tree/Images/examplezig.svg diff --git a/Splay Tree/Images /examplezig1.png b/Splay Tree/Images/examplezig1.png similarity index 100% rename from Splay Tree/Images /examplezig1.png rename to Splay Tree/Images/examplezig1.png diff --git a/Splay Tree/Images /examplezig2.png b/Splay Tree/Images/examplezig2.png similarity index 100% rename from Splay Tree/Images /examplezig2.png rename to Splay Tree/Images/examplezig2.png diff --git a/Splay Tree/Images /examplezigzig.svg b/Splay Tree/Images/examplezigzig.svg similarity index 100% rename from Splay Tree/Images /examplezigzig.svg rename to Splay Tree/Images/examplezigzig.svg diff --git a/Splay Tree/Images /examplezigzig1.png b/Splay Tree/Images/examplezigzig1.png similarity index 100% rename from Splay Tree/Images /examplezigzig1.png rename to Splay Tree/Images/examplezigzig1.png diff --git a/Splay Tree/Images /examplezigzig2.png b/Splay Tree/Images/examplezigzig2.png similarity index 100% rename from Splay Tree/Images /examplezigzig2.png rename to Splay Tree/Images/examplezigzig2.png diff --git a/Splay Tree/Images /examplezigzig3.png b/Splay Tree/Images/examplezigzig3.png similarity index 100% rename from Splay Tree/Images /examplezigzig3.png rename to Splay Tree/Images/examplezigzig3.png diff --git a/Splay Tree/Images /zig.png b/Splay Tree/Images/zig.png similarity index 100% rename from Splay Tree/Images /zig.png rename to Splay Tree/Images/zig.png diff --git a/Splay Tree/Images /zigzag1.png b/Splay Tree/Images/zigzag1.png similarity index 100% rename from Splay Tree/Images /zigzag1.png rename to Splay Tree/Images/zigzag1.png diff --git a/Splay Tree/Images /zigzag2.png b/Splay Tree/Images/zigzag2.png similarity index 100% rename from Splay Tree/Images /zigzag2.png rename to Splay Tree/Images/zigzag2.png diff --git a/Splay Tree/Images /zigzig1.png b/Splay Tree/Images/zigzig1.png similarity index 100% rename from Splay Tree/Images /zigzig1.png rename to Splay Tree/Images/zigzig1.png diff --git a/Splay Tree/Images /zigzig2.png b/Splay Tree/Images/zigzig2.png similarity index 100% rename from Splay Tree/Images /zigzig2.png rename to Splay Tree/Images/zigzig2.png From 5d15f553817310785fc0d5539c01508c86892250 Mon Sep 17 00:00:00 2001 From: Barbara Martina Rodeker Date: Sun, 21 May 2017 22:27:24 +0200 Subject: [PATCH 1033/1679] Adding images for examples and rotation cases --- Splay Tree/readme.md | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/Splay Tree/readme.md b/Splay Tree/readme.md index aa6bdd4db..89444b2cc 100644 --- a/Splay Tree/readme.md +++ b/Splay Tree/readme.md @@ -8,14 +8,25 @@ Splay tree is a data structure, structurally identitical to a Balanced Binary Se Given a node *a* if *a* is not the root, and *a* has a child *b*, and both *a* and *b* are left children or right children, a **Zig-Zig** is performed. +![ZigZigCase1](Images/zigzig1.png) + +![ZigZigCase2](Images/zigzig2.png) + ### Zig-Zag Given a node *a* if *a* is not the root, and *a* has a child *b*, and *b* is the left child of *a* being the right child (or the opporsite), a **Zig-Zag** is performed. +![ZigZagCase1](Images/zigzag1.png) + +![ZigZagCase2](Images/zigzag2.png) + ### Zig A **Zig** is performed when the node *a* to be rotated has the root as parent. +![ZigCase](Images/zig.png) + + ## Splaying ## Operations @@ -30,9 +41,20 @@ A **Zig** is performed when the node *a* to be rotated has the root as parent. ### Example 1 +![ZigEx1](Images/examplezigzig1.png) + +![ZigEx2](Images/examplezigzig2.png) + +![ZigEx3](Images/examplezigzig3.png) + + ### Example 2 -### Example 3 +![ZigEx21](Images/example1-1.png) + +![ZigEx22](Images/example1-2.png) + +![ZigEx23](Images/example1-3.png) ## Advantages @@ -57,4 +79,4 @@ With *n* being the number of items in the tree. [Splay Tree on Wikipedia](https://en.wikipedia.org/wiki/Splay_tree) [Splay Tree by University of California in Berkeley - CS 61B Lecture 34](https://www.youtube.com/watch?v=G5QIXywcJlY) -*Written for Swift Algorithm Club by Mike Taghavi and Matthijs Hollemans* +*Written for Swift Algorithm Club by Barbara Martina Rodeker* From c4268801a9340b1776c6b4e0c452fe8a6388031b Mon Sep 17 00:00:00 2001 From: Barbara Martina Rodeker Date: Tue, 23 May 2017 22:08:14 +0200 Subject: [PATCH 1034/1679] Update readme.md --- Splay Tree/readme.md | 64 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 63 insertions(+), 1 deletion(-) diff --git a/Splay Tree/readme.md b/Splay Tree/readme.md index 89444b2cc..29f9dede5 100644 --- a/Splay Tree/readme.md +++ b/Splay Tree/readme.md @@ -4,22 +4,36 @@ Splay tree is a data structure, structurally identitical to a Balanced Binary Se ## Rotations +There are 3 types of rotations that can form an **Splaying**: + +- ZigZig +- ZigZag +- Zig + ### Zig-Zig Given a node *a* if *a* is not the root, and *a* has a child *b*, and both *a* and *b* are left children or right children, a **Zig-Zig** is performed. +### Case both nodes right children ![ZigZigCase1](Images/zigzig1.png) +### Case both nodes left children ![ZigZigCase2](Images/zigzig2.png) +**IMPORTANT** is to note that a *ZigZig* performs first the rotation of the middle node with its parent (call it the grandparent) and later the rotation of the remaining node (grandchild). Doing that helps to keep the trees balanced even if it was first created by inserted a sequence of increasing values (see below worst case scenario). + ### Zig-Zag Given a node *a* if *a* is not the root, and *a* has a child *b*, and *b* is the left child of *a* being the right child (or the opporsite), a **Zig-Zag** is performed. +### Case right - left ![ZigZagCase1](Images/zigzag1.png) +### Case left - right ![ZigZagCase2](Images/zigzag2.png) +**IMPORTANT** A *ZigZag* performs first the rotation of the grandchild node and later the same node with its new parent again. + ### Zig A **Zig** is performed when the node *a* to be rotated has the root as parent. @@ -29,7 +43,53 @@ A **Zig** is performed when the node *a* to be rotated has the root as parent. ## Splaying -## Operations +A splaying consists in making so many rotations as needed until the node affected by the operation is at the top and becomes the root of the tree. + +``` +while (node.parent != nil) { + operation(forNode: node).apply(onNode: node) +} +``` + +Where operation returns the required rotation to be applied. + +``` + public static func operation(forNode node: Node) -> SplayOperation { + + if let parent = node.parent, let _ = parent.parent { + if (node.isLeftChild && parent.isRightChild) || (node.isRightChild && parent.isLeftChild) { + return .zigZag + } + return .zigZig + } + return .zig + } +``` + +During the applying phase, the algorithms determines which nodes are involved depending on the rotation to be applied and proceeding to re-arrange the node with its parent. + +``` + public func apply(onNode node: Node) { + switch self { + case .zigZag: + assert(node.parent != nil && node.parent!.parent != nil, "Should be at least 2 nodes up in the tree") + rotate(child: node, parent: node.parent!) + rotate(child: node, parent: node.parent!) + + case .zigZig: + assert(node.parent != nil && node.parent!.parent != nil, "Should be at least 2 nodes up in the tree") + rotate(child: node.parent!, parent: node.parent!.parent!) + rotate(child: node, parent: node.parent!) + + case .zig: + assert(node.parent != nil && node.parent!.parent == nil, "There should be a parent which is the root") + rotate(child: node, parent: node.parent!) + } + } +``` + + +## Operations on an Splay Tree ### Insertion @@ -73,6 +133,8 @@ Splay tree are not perfectly balanced always, so in case of accessing all the el With *n* being the number of items in the tree. +# An example of the Worst Case Performance + ## See also From 0a813ba0f16865323529e7de03ff9cb69eea378d Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Wed, 24 May 2017 16:05:34 +0300 Subject: [PATCH 1035/1679] Code improvements --- Dijkstra Algorithm/Dijkstra.playground/Sources/Dijkstra.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Dijkstra Algorithm/Dijkstra.playground/Sources/Dijkstra.swift b/Dijkstra Algorithm/Dijkstra.playground/Sources/Dijkstra.swift index f4cd8503a..9c5961c71 100644 --- a/Dijkstra Algorithm/Dijkstra.playground/Sources/Dijkstra.swift +++ b/Dijkstra Algorithm/Dijkstra.playground/Sources/Dijkstra.swift @@ -13,11 +13,12 @@ public class Dijkstra { public func findShortestPaths(from startVertex: Vertex) { clearCache() + var currentVertices = self.totalVertices startVertex.pathLengthFromStart = 0 startVertex.pathVerticesFromStart.append(startVertex) var currentVertex: Vertex? = startVertex while let vertex = currentVertex { - totalVertices.remove(vertex) + currentVertices.remove(vertex) let filteredNeighbors = vertex.neighbors.filter { totalVertices.contains($0.0) } for neighbor in filteredNeighbors { let neighborVertex = neighbor.0 From 35db21bb212b56ab13a1ecf67b251727ca3718a9 Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Wed, 24 May 2017 17:54:49 +0300 Subject: [PATCH 1036/1679] Updated description --- Dijkstra Algorithm/Images/DirectedGraph.png | Bin 0 -> 68702 bytes Dijkstra Algorithm/Images/Vertices.png | Bin 0 -> 35896 bytes .../Images/WeightedDirectedGraph.png | Bin 0 -> 70820 bytes .../Images/WeightedDirectedGraphFinal.png | Bin 0 -> 76503 bytes .../Images/WeightedUndirectedGraph.png | Bin 0 -> 78079 bytes Dijkstra Algorithm/README.md | 56 +++++++++++++----- 6 files changed, 42 insertions(+), 14 deletions(-) create mode 100644 Dijkstra Algorithm/Images/DirectedGraph.png create mode 100644 Dijkstra Algorithm/Images/Vertices.png create mode 100644 Dijkstra Algorithm/Images/WeightedDirectedGraph.png create mode 100644 Dijkstra Algorithm/Images/WeightedDirectedGraphFinal.png create mode 100644 Dijkstra Algorithm/Images/WeightedUndirectedGraph.png diff --git a/Dijkstra Algorithm/Images/DirectedGraph.png b/Dijkstra Algorithm/Images/DirectedGraph.png new file mode 100644 index 0000000000000000000000000000000000000000..67db4995811de13dbf289b45f4cb0b8125bfe317 GIT binary patch literal 68702 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 literal 0 HcmV?d00001 diff --git a/Dijkstra Algorithm/Images/Vertices.png b/Dijkstra Algorithm/Images/Vertices.png new file mode 100644 index 0000000000000000000000000000000000000000..09b2ad2c0190c1145627afc85f24157302a4abfb GIT binary patch literal 35896 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 literal 0 HcmV?d00001 diff --git a/Dijkstra Algorithm/Images/WeightedDirectedGraph.png b/Dijkstra Algorithm/Images/WeightedDirectedGraph.png new file mode 100644 index 0000000000000000000000000000000000000000..542c698e1aa006df61c1dc62bfe950bda1ab1c4c GIT binary patch literal 70820 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 aOX&wc5htqAPn9shkCK9#e7UUov;PC-y<_D7 literal 0 HcmV?d00001 diff --git a/Dijkstra Algorithm/Images/WeightedDirectedGraphFinal.png b/Dijkstra Algorithm/Images/WeightedDirectedGraphFinal.png new file mode 100644 index 0000000000000000000000000000000000000000..b2bb3e8e2b9990ff598b7be178547fa3d0171691 GIT binary patch literal 76503 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 literal 0 HcmV?d00001 diff --git a/Dijkstra Algorithm/Images/WeightedUndirectedGraph.png b/Dijkstra Algorithm/Images/WeightedUndirectedGraph.png new file mode 100644 index 0000000000000000000000000000000000000000..2f26b74d4dcd457fd32d619744dd5cdbd340a0c0 GIT binary patch literal 78079 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ñx&@q?ReE3{3Qd)#J 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 literal 0 HcmV?d00001 diff --git a/Dijkstra Algorithm/README.md b/Dijkstra Algorithm/README.md index db1726b1f..ddce51525 100644 --- a/Dijkstra Algorithm/README.md +++ b/Dijkstra Algorithm/README.md @@ -1,13 +1,50 @@ +#Weighted graph general cocepts + +Every weighted graph should contain: +1. Vertices/Nodes (I will use "vertex" in this readme). + + + +2. Edges connecting vertices. Let's add some edges to our graph. For simplicity let's create directed graph for now. Directed means, that edge have a direction, i.e. vertex, where it starts and vertex, where it ends. But remember VERY IMPORTANT thing: + * All undirected graphs can be viewed as a directed graph. + * A directed graph is undirected if and only if every edge is paired with an edge going in the opposite direction. + + + +3. Weights for every edge. + + + +Final result. +Directed weighted graph: + + + +Undirected weighted graph: + + + +And once again: An undireceted graph - it is a directed graph with every edge paired with an edge going in the opposite direction. This statement is clear on the image above. + +Great! Now we are familiar with general concepts about graphs. + # Dijkstra's algorithm +This [algorithm](https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm) was invented in 1956 by Edsger W. Dijkstra. -This [algorithm](https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm) was invented in 1956 by Edsger W. Dijkstra. +It can be used, when you have one source vertex and want to find the shortest paths to ALL other vertices in the graph. -It can be used, when you have one source vertex and want to find the shortest paths to all other vertices in the graph. +The best example is road network. If you wnat to find the shortest path from your house to your job, or if you want to find the closest store to your house, then it is time for the Dijkstra's algorithm. -The best example is road network. If you wnat to find the shortest path from your house to your job, then it is time for the Dijkstra's algorithm. +The algorithm repeats following cycle until all vertices are marked as visited. +Cycle: +1. From the non-visited vertices the algorithm picks a vertex with the shortest path length from the start (if there are more than one vertex with the same shortest path value, then algorithm picks any of them) +2. The algorithm marks picked vertex as visited. +3. The algorithm check all of its neighbors. If the current vertex path length from the start plus an edge weight to a neighbor less than the neighbor current path length from the start, than it assigns new path length from the start to the neihgbor. +When all vertices are marked as visited, the algorithm's job is done. Now, you can see the shortest path from the start for every vertex by pressing the one you are interested in. -I have created **VisualizedDijkstra.playground** to improve your understanding of the algorithm's flow. Besides, below is step by step algorithm's description. +I have created **VisualizedDijkstra.playground** game/tutorial to improve your understanding of the algorithm's flow. Besides, below is step by step algorithm's description. +#Example Let's imagine, you want to go to the shop. Your house is A vertex and there are 4 possible stores around your house. How to find the closest one/ones? Luckily, you have graph, that connects your house with all these stores. So, you know what to do :) ## Initialization @@ -38,17 +75,8 @@ To initialize our graph we have to set source vertex path length from source ver | Path Length From Start | 0 | inf | inf | inf | inf | | Path Vertices From Start | [A] | [ ] | [ ] | [ ] | [ ] | -Great, now our graph is initialized and we can pass it to the Dijkstra's algorithm. - -But before we will go through all process side by side read this explanation. -The algorithm repeats following cycle until all vertices are marked as visited. -Cycle: -1. From the non-visited vertices the algorithm picks a vertex with the shortest path length from the start (if there are more than one vertex with the same shortest path value, then algorithm picks any of them) -2. The algorithm marks picked vertex as visited. -3. The algorithm check all of its neighbors. If the current vertex path length from the start plus an edge weight to a neighbor less than the neighbor current path length from the start, than it assigns new path length from the start to the neihgbor. -When all vertices are marked as visited, the algorithm's job is done. Now, you can see the shortest path from the start for every vertex by pressing the one you are interested in. +Great, now our graph is initialized and we can pass it to the Dijkstra's algorithm, let's start! -Okay, let's start! Let's follow the algorithm's cycle and pick the first vertex, which neighbors we want to check. All our vertices are not visited, but there is only one has the smallest path length from start - A. This vertex is the first one, which neighbors we will check. First of all, set this vertex as visited From e9017365a47a93a977dc0f26c42045d6fccd4b76 Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Wed, 24 May 2017 18:01:53 +0300 Subject: [PATCH 1037/1679] Fix --- Dijkstra Algorithm/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dijkstra Algorithm/README.md b/Dijkstra Algorithm/README.md index ddce51525..5cf312acc 100644 --- a/Dijkstra Algorithm/README.md +++ b/Dijkstra Algorithm/README.md @@ -1,4 +1,4 @@ -#Weighted graph general cocepts +# Weighted graph general cocepts Every weighted graph should contain: 1. Vertices/Nodes (I will use "vertex" in this readme). From b1a50b492373dba7490e603975f9bec8e98c4725 Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Wed, 24 May 2017 18:04:09 +0300 Subject: [PATCH 1038/1679] fix --- Dijkstra Algorithm/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dijkstra Algorithm/README.md b/Dijkstra Algorithm/README.md index 5cf312acc..a9a898d80 100644 --- a/Dijkstra Algorithm/README.md +++ b/Dijkstra Algorithm/README.md @@ -44,7 +44,7 @@ When all vertices are marked as visited, the algorithm's job is done. Now, you c I have created **VisualizedDijkstra.playground** game/tutorial to improve your understanding of the algorithm's flow. Besides, below is step by step algorithm's description. -#Example +# Example Let's imagine, you want to go to the shop. Your house is A vertex and there are 4 possible stores around your house. How to find the closest one/ones? Luckily, you have graph, that connects your house with all these stores. So, you know what to do :) ## Initialization From bb8b2a7d480b6e9f3d5eeee87eaf4a7e01e2ba36 Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Wed, 24 May 2017 18:07:47 +0300 Subject: [PATCH 1039/1679] Fixes --- Dijkstra Algorithm/README.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Dijkstra Algorithm/README.md b/Dijkstra Algorithm/README.md index a9a898d80..7afc34094 100644 --- a/Dijkstra Algorithm/README.md +++ b/Dijkstra Algorithm/README.md @@ -44,10 +44,10 @@ When all vertices are marked as visited, the algorithm's job is done. Now, you c I have created **VisualizedDijkstra.playground** game/tutorial to improve your understanding of the algorithm's flow. Besides, below is step by step algorithm's description. -# Example +## Example Let's imagine, you want to go to the shop. Your house is A vertex and there are 4 possible stores around your house. How to find the closest one/ones? Luckily, you have graph, that connects your house with all these stores. So, you know what to do :) -## Initialization +### Initialization When the algorithm starts to work initial graph looks like this: @@ -93,7 +93,7 @@ After this step graph has this state: | Path Length From Start | 0 | inf | inf | inf | inf | | Path Vertices From Start | [A] | [ ] | [ ] | [ ] | [ ] | -## Step 1 +### Step 1 Then we check all of its neighbors. If checking vertex path length from start + edge weigth is smaller than neighbor's path length from start, then we set neighbor's path length from start new value and append to its pathVerticesFromStart array new vertex: checkingVertex. Repeat this action for every vertex. @@ -118,7 +118,7 @@ And its state is here: | Path Length From Start | 0 | 3 | inf | 1 | inf | | Path Vertices From Start | [A] | [A, B] | [ ] | [A, D] | [ ] | -## Step 2 +### Step 2 From now we repeat all actions again and fill our table with new info! @@ -130,7 +130,7 @@ From now we repeat all actions again and fill our table with new info! | Path Length From Start | 0 | 3 | inf | 1 | 2 | | Path Vertices From Start | [A] | [A, B] | [ ] | [A, D] | [A, D, E] | -## Step 3 +### Step 3 @@ -140,7 +140,7 @@ From now we repeat all actions again and fill our table with new info! | Path Length From Start | 0 | 3 | 11 | 1 | 2 | | Path Vertices From Start | [A] | [A, B] |[A, D, E, C]| [A, D] | [A, D, E ] | -## Step 4 +### Step 4 @@ -150,7 +150,7 @@ From now we repeat all actions again and fill our table with new info! | Path Length From Start | 0 | 3 | 8 | 1 | 2 | | Path Vertices From Start | [A] | [A, B] | [A, B, C]| [A, D] | [A, D, E ] | -## Step 5 +### Step 5 @@ -300,16 +300,16 @@ Also there is a **VisualizedDijkstra.playground**. Use it to figure out algorith It is up to you how to implement some specific parts of algorithm, you can use Array instead of Set, add _visited_ property to Vertex or you can create some local totalVertices Array/Set inside _func findShortestPaths(from startVertex: Vertex)_ to keep totalVertices Array/Set unchanged. This is a general explanation with one possible implementation :) -## About this repository +# About this repository This repository contains to playgrounds: * To understand how does this algorithm works, I have created **VisualizedDijkstra.playground.** It works in auto and interactive modes. Moreover there are play/pause/stop buttons. * If you need only realization of the algorithm without visualization then run **Dijkstra.playground.** It contains necessary classes and couple functions to create random graph for algorithm testing. -## Demo video +# Demo video Click the link: [YouTube](https://youtu.be/PPESI7et0cQ) -## Credits +# Credits WWDC 2017 Scholarship Project (Rejected) created by [Taras Nikulin](https://github.com/crabman448) From fbd5d6ea149cccd61c93530a772bad148e3a45e1 Mon Sep 17 00:00:00 2001 From: barbara Date: Thu, 25 May 2017 14:04:49 +0200 Subject: [PATCH 1040/1679] Examples for documentation --- .../Images/SplayTreesWorstCaseExamples.svg | 2 ++ Splay Tree/Images/example-zigzig-1.png | Bin 0 -> 32202 bytes Splay Tree/Images/example-zigzig-2.png | Bin 0 -> 34485 bytes Splay Tree/Images/example-zigzig-3.png | Bin 0 -> 29732 bytes Splay Tree/Images/example-zigzig-4.png | Bin 0 -> 28709 bytes Splay Tree/Images/example-zigzig-5.png | Bin 0 -> 25735 bytes Splay Tree/Images/worst-case-1.png | Bin 0 -> 6795 bytes Splay Tree/Images/worst-case-2.png | Bin 0 -> 7076 bytes Splay Tree/Images/worst-case-3.png | Bin 0 -> 9049 bytes Splay Tree/Images/worst-case-4.png | Bin 0 -> 10813 bytes Splay Tree/Images/worst-case-5.png | Bin 0 -> 11827 bytes Splay Tree/Images/worst-case-6.png | Bin 0 -> 35177 bytes Splay Tree/Images/zigzig-wrongrotated.png | Bin 0 -> 38831 bytes 13 files changed, 2 insertions(+) create mode 100644 Splay Tree/Images/SplayTreesWorstCaseExamples.svg create mode 100644 Splay Tree/Images/example-zigzig-1.png create mode 100644 Splay Tree/Images/example-zigzig-2.png create mode 100644 Splay Tree/Images/example-zigzig-3.png create mode 100644 Splay Tree/Images/example-zigzig-4.png create mode 100644 Splay Tree/Images/example-zigzig-5.png create mode 100644 Splay Tree/Images/worst-case-1.png create mode 100644 Splay Tree/Images/worst-case-2.png create mode 100644 Splay Tree/Images/worst-case-3.png create mode 100644 Splay Tree/Images/worst-case-4.png create mode 100644 Splay Tree/Images/worst-case-5.png create mode 100644 Splay Tree/Images/worst-case-6.png create mode 100644 Splay Tree/Images/zigzig-wrongrotated.png diff --git a/Splay Tree/Images/SplayTreesWorstCaseExamples.svg b/Splay Tree/Images/SplayTreesWorstCaseExamples.svg new file mode 100644 index 000000000..c07312af2 --- /dev/null +++ b/Splay Tree/Images/SplayTreesWorstCaseExamples.svg @@ -0,0 +1,2 @@ + +
1
1
2
2
1
1
2
2
1
1
2
2
3
3
1
1
2
2
3
3
1
1
2
2
3
3
4
4
1
1
2
2
3
3
4
4
1
1
2
2
3
3
4
4
1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
5
5
6
6
7
7
8
8
5
5
6
6
7
7
8
8
1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
\ No newline at end of file diff --git a/Splay Tree/Images/example-zigzig-1.png b/Splay Tree/Images/example-zigzig-1.png new file mode 100644 index 0000000000000000000000000000000000000000..48a08c17cf8cdbbf4de565b1ae4339a533f8b562 GIT binary patch literal 32202 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

^3u@V70z)B9iJxD+Z%NK(r?LStzHVG-% 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 G@c#kXNwKB? literal 0 HcmV?d00001 diff --git a/Splay Tree/Images/example-zigzig-3.png b/Splay Tree/Images/example-zigzig-3.png new file mode 100644 index 0000000000000000000000000000000000000000..905b4d4bd2d9638e902358172764e23e29c03da6 GIT binary patch literal 29732 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

350Y9 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 Date: Wed, 19 Apr 2017 16:44:55 +0300 Subject: [PATCH 0950/1679] Replaced _vertices with vertices --- .../Dijkstra.playground/Contents.swift | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/Dijkstra Algorithm/Dijkstra.playground/Contents.swift b/Dijkstra Algorithm/Dijkstra.playground/Contents.swift index cd08e26fb..1c12245bd 100644 --- a/Dijkstra Algorithm/Dijkstra.playground/Contents.swift +++ b/Dijkstra Algorithm/Dijkstra.playground/Contents.swift @@ -1,19 +1,19 @@ //: Playground - noun: a place where people can play import Foundation -var _vertices: Set = Set() +var vertices: Set = Set() func createNotConnectedVertices() { //change this value to increase or decrease amount of vertices in the graph let numberOfVerticesInGraph = 15 for i in 0.. Vertex { - var newSet = _vertices + var newSet = vertices newSet.remove(vertex) let offset = Int(arc4random_uniform(UInt32(newSet.count))) let index = newSet.index(newSet.startIndex, offsetBy: offset) @@ -38,9 +38,9 @@ func randomVertex(except vertex: Vertex) -> Vertex { } func randomVertex() -> Vertex { - let offset = Int(arc4random_uniform(UInt32(_vertices.count))) - let index = _vertices.index(_vertices.startIndex, offsetBy: offset) - return _vertices[index] + let offset = Int(arc4random_uniform(UInt32(vertices.count))) + let index = vertices.index(vertices.startIndex, offsetBy: offset) + return vertices[index] } //initialize random graph @@ -48,7 +48,7 @@ createNotConnectedVertices() setupConnections() //initialize Dijkstra algorithm with graph vertices -let dijkstra = Dijkstra(vertices: _vertices) +let dijkstra = Dijkstra(vertices: vertices) //decide which vertex will be the starting one let startVertex = randomVertex() @@ -63,6 +63,7 @@ var pathVerticesFromStartString: [String] = [] for vertex in destinationVertex.pathVerticesFromStart { pathVerticesFromStartString.append(vertex.identifier) } + print(pathVerticesFromStartString.joined(separator: "->")) From 93aad5ea36a1f09d62c8c877675877097e9b29fc Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Thu, 20 Apr 2017 03:39:21 -0700 Subject: [PATCH 0951/1679] Added templates for the repository. --- .github/CONTRIBUTING.md | 0 .github/ISSUE_TEMPLATE.md | 19 +++++++++++++++++++ .github/PULL_REQUEST_TEMPLATE.md | 0 3 files changed, 19 insertions(+) create mode 100644 .github/CONTRIBUTING.md create mode 100644 .github/ISSUE_TEMPLATE.md create mode 100644 .github/PULL_REQUEST_TEMPLATE.md diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md new file mode 100644 index 000000000..e69de29bb diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 000000000..27a857ef5 --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,19 @@ +### Category + +- [ ] Bug +- [ ] Feature Request +- [ ] Question + +### Brief Intro + +> Describe this issue below in 1 sentence. + +### More Details + +> If necessary, start off with the code snippet. Put the code in between ``` to format them into code blocks. + +[INSERT CODE HERE] + +> Describe the problem in more detail. + +[INSERT DETAILS HERE] \ No newline at end of file diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 000000000..e69de29bb From 5128bfa4dca199beeda930dacf0623d7f6e0e926 Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Thu, 20 Apr 2017 04:32:41 -0700 Subject: [PATCH 0952/1679] Updated contribution guidelines. --- .github/CONTRIBUTING.md | 57 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index e69de29bb..a1393a2e0 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -0,0 +1,57 @@ +# Contributing Guidelines + +Want to help out with the Swift Algorithm Club? Great! While we don't have strict templates on the format of each contribution, we do have a few guidelines that should be kept in mind: + +**Readability** + +The `README` file is the cake, and the sample code is the cherry on top. Readablity is really important for us. A good contribution has succinct explanations supported by diagrams. Code is best introduced in chunks, weaved into the explanations where relevant. + +**API Design Guidelines** + +A good contribution abides to the [Swift API Guidelines](https://swift.org/documentation/api-design-guidelines/). We review the pull requests with this in mind. + +**Swift Language Guidelines** + +We follow the following Swift [style guide](https://github.com/raywenderlich/swift-style-guide). + +### Contribution Categories + +### Refinement + +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. + +### New Contributions + +Before writing about something new, you should do 2 things: + +1. Check the main page for existing implementations +2. Check the [pull requests](https://github.com/raywenderlich/swift-algorithm-club/pulls) for "claimed" topics. More info on that below. + +If what you have in mind is a new addition, please follow this process when submitting your contribution: + +1. Create a pull request to "claim" an algorithm or data structure. This is to avoid having multiple people working on the same thing. +2. Use this [style guide](https://github.com/raywenderlich/swift-style-guide) for writing code (more or less). +3. Write an explanation of how the algorithm works. Include **plenty of examples** for readers to follow along. Pictures are good. Take a look at [the explanation of quicksort](Quicksort/) to get an idea. +4. Include your name in the explanation, something like *Written by Your Name* at the end of the document. +5. Add a playground and/or unit tests. + +For the unit tests: + +- Add the unit test project to `.travis.yml` so they will be run on [Travis-CI](https://travis-ci.org/raywenderlich/swift-algorithm-club). Add a line to `.travis.yml` like this: + +``` +- xctool test -project ./Algorithm/Tests/Tests.xcodeproj -scheme Tests +``` + +- Configure the Test project's scheme to run on Travis-CI: + - Open **Product -> Scheme -> Manage Schemes...** + - Uncheck **Autocreate schemes** + - Check **Shared** + +![Screenshot of scheme settings](Images/scheme-settings-for-travis.png) + +## Want to chat? + +This isn't just a repo with a bunch of code... If you want to learn more about how an algorithm works or want to discuss better ways of solving problems, then open a [Github issue](https://github.com/raywenderlich/swift-algorithm-club/issues) and we'll talk! \ No newline at end of file From 1e149dc959731e16eb303396293e1e719f86d2ef Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Thu, 20 Apr 2017 04:33:33 -0700 Subject: [PATCH 0953/1679] Fixed broken link. --- .github/CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index a1393a2e0..fe8a23278 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -50,7 +50,7 @@ For the unit tests: - Uncheck **Autocreate schemes** - Check **Shared** -![Screenshot of scheme settings](Images/scheme-settings-for-travis.png) +![Screenshot of scheme settings](../Images/scheme-settings-for-travis.png) ## Want to chat? From 1620a9cb811ecac68528c8f330f45762ec1beb6a Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Thu, 20 Apr 2017 04:34:11 -0700 Subject: [PATCH 0954/1679] Fixes another broken link in the readme. --- .github/CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index fe8a23278..5b6f5d4dd 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -33,7 +33,7 @@ If what you have in mind is a new addition, please follow this process when subm 1. Create a pull request to "claim" an algorithm or data structure. This is to avoid having multiple people working on the same thing. 2. Use this [style guide](https://github.com/raywenderlich/swift-style-guide) for writing code (more or less). -3. Write an explanation of how the algorithm works. Include **plenty of examples** for readers to follow along. Pictures are good. Take a look at [the explanation of quicksort](Quicksort/) to get an idea. +3. Write an explanation of how the algorithm works. Include **plenty of examples** for readers to follow along. Pictures are good. Take a look at [the explanation of quicksort](../Quicksort/) to get an idea. 4. Include your name in the explanation, something like *Written by Your Name* at the end of the document. 5. Add a playground and/or unit tests. From d83263cd7e2dcd13e7e2e8ad7c9f624fab337a00 Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Thu, 20 Apr 2017 04:43:55 -0700 Subject: [PATCH 0955/1679] Updated issue and pr template. --- .github/ISSUE_TEMPLATE.md | 10 ++-------- .github/PULL_REQUEST_TEMPLATE.md | 11 +++++++++++ 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 27a857ef5..416641261 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -6,14 +6,8 @@ ### Brief Intro -> Describe this issue below in 1 sentence. + ### More Details -> If necessary, start off with the code snippet. Put the code in between ``` to format them into code blocks. - -[INSERT CODE HERE] - -> Describe the problem in more detail. - -[INSERT DETAILS HERE] \ No newline at end of file + \ No newline at end of file diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index e69de29bb..c52564721 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,11 @@ + + +### Checklist + +- [ ] I've looked at the [contribution guidelines](https://github.com/raywenderlich/swift-algorithm-club/blob/master/.github/CONTRIBUTING.md). +- [ ] This pull request is complete and ready for review. + +### Description + + + From bb6c29fee3cf3549c56cf5fb351bf01b15301177 Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Thu, 20 Apr 2017 04:45:44 -0700 Subject: [PATCH 0956/1679] Fixes formatting. --- .github/CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 5b6f5d4dd..2b08e2633 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -14,7 +14,7 @@ A good contribution abides to the [Swift API Guidelines](https://swift.org/docum We follow the following Swift [style guide](https://github.com/raywenderlich/swift-style-guide). -### Contribution Categories +## Contribution Categories ### Refinement From aadae31ed56f8317eae20e94196b2c242994d1fb Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Thu, 20 Apr 2017 04:54:06 -0700 Subject: [PATCH 0957/1679] Updated readme with links to updated/new contributions. --- README.markdown | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/README.markdown b/README.markdown index 29fc9d748..e0983f22e 100644 --- a/README.markdown +++ b/README.markdown @@ -8,9 +8,7 @@ If you're a computer science student who needs to learn this stuff for exams -- The goal of this project is to **explain how algorithms work**. The focus is on clarity and readability of the code, not on making a reusable library that you can drop into your own projects. That said, most of the code should be ready for production use but you may need to tweak it to fit into your own codebase. -Most code is compatible with **Xcode 8.2** and **Swift 3**. We'll keep this updated with the latest version of Swift. - -This is a work in progress. More algorithms will be added soon. :-) +Most code is compatible with **Xcode 8.3** and **Swift 3**. We'll keep this updated with the latest version of Swift. :heart_eyes: **Suggestions and contributions are welcome!** :heart_eyes: @@ -24,9 +22,7 @@ This is a work in progress. More algorithms will be added soon. :-) [Algorithm design techniques](Algorithm%20Design.markdown). How do you create your own algorithms? -[How to contribute](How%20to%20Contribute.markdown). Report an issue to leave feedback, or submit a pull request. - -[Under construction](Under%20Construction.markdown). Algorithms that are under construction. +[How to contribute](https://github.com/raywenderlich/swift-algorithm-club/blob/master/.github/CONTRIBUTING.md). Report an issue to leave feedback, or submit a pull request. ## Where to start? @@ -56,7 +52,7 @@ If you're new to algorithms and data structures, here are a few good ones to sta - [Brute-Force String Search](Brute-Force%20String%20Search/). A naive method. - [Boyer-Moore](Boyer-Moore/). A fast method to search for substrings. It skips ahead based on a look-up table, to avoid looking at every character in the text. -- Knuth-Morris-Pratt +- [Knuth-Morris-Pratt](Knuth-Morris-Pratt/). A linear-time string algorithm that returns indexes of all occurrencies of a given pattern. - [Rabin-Karp](Rabin-Karp/) Faster search by using hashing. - [Longest Common Subsequence](Longest%20Common%20Subsequence/). Find the longest sequence of characters that appear in the same order in both strings. - [Z-Algorithm](Z-Algorithm/). Finds all instances of a pattern in a String, and returns the indexes of where the pattern starts within the String. @@ -103,7 +99,6 @@ Bad sorting algorithms (don't use these!): - [Greatest Common Divisor (GCD)](GCD/). Special bonus: the least common multiple. - [Permutations and Combinations](Combinatorics/). Get your combinatorics on! - [Shunting Yard Algorithm](Shunting%20Yard/). Convert infix expressions to postfix. -- Statistics - [Karatsuba Multiplication](Karatsuba%20Multiplication/). Another take on elementary multiplication. - [Haversine Distance](HaversineDistance/). Calculating the distance between 2 points from a sphere. - [Strassen's Multiplication Matrix](Strassen%20Matrix%20Multiplication/). Efficient way to handle matrix multiplication. @@ -112,7 +107,7 @@ Bad sorting algorithms (don't use these!): - [k-Means Clustering](K-Means/). Unsupervised classifier that partitions data into *k* clusters. - k-Nearest Neighbors -- [Linear Regression](Linear%20Regression/) +- [Linear Regression](Linear%20Regression/). A technique for creating a model of the relationship between two (or more) variable quantities. - Logistic Regression - Neural Networks - PageRank @@ -153,9 +148,9 @@ Most of the time using just the built-in `Array`, `Dictionary`, and `Set` types - [Tree](Tree/). A general-purpose tree structure. - [Binary Tree](Binary%20Tree/). A tree where each node has at most two children. - [Binary Search Tree (BST)](Binary%20Search%20Tree/). A binary tree that orders its nodes in a way that allows for fast queries. -- Red-Black Tree +- [Red-Black Tree](Red-Black%20Tree/). A self balancing binary search tree. - Splay Tree -- Threaded Binary Tree +- [Threaded Binary Tree](Threaded%20Binary%20Tree/). A binary tree that maintains a few extra variables for cheap and fast in-order traversals. - [Segment Tree](Segment%20Tree/). Can quickly compute a function over a portion of an array. - kd-Tree - [Heap](Heap/). A binary tree stored in an array, so it doesn't use pointers. Makes a great priority queue. @@ -226,7 +221,7 @@ Other algorithm repositories: The Swift Algorithm Club was originally created by [Matthijs Hollemans](https://github.com/hollance). -It is now maintained by [Vincent Ngo](https://www.raywenderlich.com/u/jomoka) and [Kelvin Lau](https://github.com/kelvinlauKL). +It is now maintained by [Vincent Ngo](https://www.raywenderlich.com/u/jomoka), [Kelvin Lau](https://github.com/kelvinlauKL) and [Ross O'brien](https://www.raywenderlich.com/u/narrativium). The Swift Algorithm Club is a collaborative effort from the [most algorithmic members](https://github.com/rwenderlich/swift-algorithm-club/graphs/contributors) of the [raywenderlich.com](https://www.raywenderlich.com) community. We're always looking for help - why not [join the club](How%20to%20Contribute.markdown)? :] From 2ce23ca2b1059050be7c87cf45df184dd5090008 Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Thu, 20 Apr 2017 04:55:50 -0700 Subject: [PATCH 0958/1679] Removed old contribution guidelines. --- How to Contribute.markdown | 55 -------------------------------------- 1 file changed, 55 deletions(-) delete mode 100644 How to Contribute.markdown diff --git a/How to Contribute.markdown b/How to Contribute.markdown deleted file mode 100644 index 1235f07ff..000000000 --- a/How to Contribute.markdown +++ /dev/null @@ -1,55 +0,0 @@ -# How to contribute - -Want to help out with the Swift Algorithm Club? Great! - -## What sort of things can you contribute? - -Take a look at the [list](README.markdown). Any algorithms or data structures that don't have a link yet are up for grabs. - -Algorithms in the [Under construction](Under%20Construction.markdown) area are being worked on. Suggestions and feedback is welcome! - -New algorithms and data structures are always welcome (even if they aren't on the list). - -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. - -Unit tests. Fixes for typos. No contribution is too small. :-) - -## Please follow this process - -To keep this a high quality repo, please follow this process when submitting your contribution: - -1. Create a pull request to "claim" an algorithm or data structure. Just so multiple people don't work on the same thing. -2. Use this [style guide](https://github.com/raywenderlich/swift-style-guide) for writing code (more or less). -3. Write an explanation of how the algorithm works. Include **plenty of examples** for readers to follow along. Pictures are good. Take a look at [the explanation of quicksort](Quicksort/) to get an idea. -4. Include your name in the explanation, something like *Written by Your Name* at the end of the document. -5. Add a playground and/or unit tests. -6. Run [SwiftLint](https://github.com/realm/SwiftLint) - - [Install](https://github.com/realm/SwiftLint#installation) - - Open terminal and run the `swiftlint` command: - -``` -cd path/to/swift-algorithm-club -swiftlint -``` - - -Just so you know, I will probably edit your text and code for grammar etc, just to ensure a certain level of polish. - -For the unit tests: - -- Add the unit test project to `.travis.yml` so they will be run on [Travis-CI](https://travis-ci.org/raywenderlich/swift-algorithm-club). Add a line to `.travis.yml` like this: - -``` -- xctool test -project ./Algorithm/Tests/Tests.xcodeproj -scheme Tests -``` - -- Configure the Test project's scheme to run on Travis-CI: - - Open **Product -> Scheme -> Manage Schemes...** - - Uncheck **Autocreate schemes** - - Check **Shared** - -![Screenshot of scheme settings](Images/scheme-settings-for-travis.png) - -## Want to chat? - -This isn't just a repo with a bunch of code... If you want to learn more about how an algorithm works or want to discuss better ways of solving problems, then open a [Github issue](https://github.com/raywenderlich/swift-algorithm-club/issues) and we'll talk! From 37de447879960291131d97aecb3d56c89da77429 Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Thu, 20 Apr 2017 15:07:29 +0300 Subject: [PATCH 0959/1679] Updating --- Dijkstra Algorithm/README.md | 61 +++++++++++++++++++++++++++++++----- 1 file changed, 53 insertions(+), 8 deletions(-) diff --git a/Dijkstra Algorithm/README.md b/Dijkstra Algorithm/README.md index 325bab40f..7ec9d352e 100644 --- a/Dijkstra Algorithm/README.md +++ b/Dijkstra Algorithm/README.md @@ -1,19 +1,59 @@ # Dijkstra-algorithm -## About this repository +This algorithm was invented in 1956 by Edsger W. Dijkstra. + +This algorithm can be used, when you have one source vertex and want to find the shortest paths to all other vertices in the graph. + +The best example is road network. If you wnat to find the shortest path from your house to your job, then it is time for the Dijkstra's algorithm. + +I have a gif example, which will show you how algorithm works. If this is not enough, then you can play with my **VisualizedDijkstra.playground**. +So let's image, that your house is "A" vertex and your job is "B" vertex. And you are lucky, you have graph with all possible routes. +When the algorithm starts to work initial graph looks like this: +[image1.png all are non visited] +Graph's array contains 5 vertices [A, B, C, D, E]. +Let's assume, that edge weight it is path length in kilometers between vertices. +A vertex has neighbors: B(path from A: 5.0), C(path from A: 0.0), D(path from A: 0.0) +And because algorithm has done nothing, then all vertices' path length from source vertex values are infinity (think about infinity as "I don't know, how long will it takes to get this vertex from source one") +Finally we have to set source vertex path length from source vertex to 0. + +Great, now our graph is initialized and we can pass it to the Dijkstra's algorithm. + +| | A | B | C | D | E | +| ------------------------- | --- | --- | --- | --- | --- | +| Visited | F | F | F | F | F | +| Path Length From Start | inf | inf | inf | inf | inf | +| Path Vertices From Start | [ ] | [ ] | [ ] | [ ] | [ ] | + +But before we will go through all process side by side let me explain how algorithm works. +The algorithm repeats following cycle until all vertices are marked as visited. +Cycle: +1. From the non-visited vertices the algorithm picks a vertex with the shortest path length from the start (if there are more than one vertex with the same shortest path value, then algorithm picks any of them) +2. The algorithm marks picked vertex as visited. +3. The algorithm check all of its neighbors. If the current vertex path length from the start plus an edge weight to a neighbor less than the neighbor current path length from the start, than it assigns new path length from the start to the neihgbor. +When all vertices are marked as visited, the algorithm's job is done. Now, you can see the shortest path from the start for every vertex by pressing the one you are interested in. + +Okay, let's start! +From now we will keep array which contains non visited vertices. Here they are: +var nonVisitedVertices = [A, B, C, D, E] +Let's follow the algorithm and pick the first vertex, which neighbors we want to check. +Imagine that we have function, that returns vertex with smallest path length from start. +var checkingVertex = nonVisitedVertices.smallestPathLengthFromStartVertex() +Then we set this vertex as visited +checkingVertex.visited = true +[image2.jpg visited first] +Then we check all of its neighbors. +If neighbor's path length from start is bigger than checking vertex path length from start + edge weigth, then we set neighbor's path length from start new value and append to its pathVerticesFromStart array new vertex: checkingVertex. Repeat this action for every vertex. +[image3.jpg visited first with checked neighbors] + + + This repository contains to playgrounds: * To understand how does this algorithm works, I have created **VisualizedDijkstra.playground.** It works in auto and interactive modes. Moreover there are play/pause/stop buttons. * If you need only realization of the algorithm without visualization then run **Dijkstra.playground.** It contains necessary classes and couple functions to create random graph for algorithm testing. -## Demo video -Click the link: [YouTube](https://youtu.be/PPESI7et0cQ) - -## Screenshots - - ## Dijkstra's algorithm explanation - + [Wikipedia](https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm)'s explanation: Let the node at which we are starting be called the initial node. Let the distance of node Y be the distance from the initial node to Y. Dijkstra's algorithm will assign some initial distance values and will try to improve them step by step. @@ -37,8 +77,13 @@ Cycle: When all vertices are marked as visited, the algorithm's job is done. Now, you can see the shortest path from the start for every vertex by pressing the one you are interested in. ## Usage +This algorithm is popular in routing. For example, biggest Russian IT company Yandex uses it in [Яндекс.Карты](https://yandex.ru/company/technologies/routes/) +## Demo video +Click the link: [YouTube](https://youtu.be/PPESI7et0cQ) +## VisualizedDijkstra.playground Screenshots + ## Credits WWDC 2017 Scholarship Project From f24ecc22436be2b71f6c840464d6826ddf9e258c Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Thu, 20 Apr 2017 15:30:59 +0300 Subject: [PATCH 0960/1679] Still updating --- Dijkstra Algorithm/Images/image1.png | Bin 0 -> 61926 bytes Dijkstra Algorithm/Images/image2.png | Bin 0 -> 63758 bytes Dijkstra Algorithm/Images/image3.png | Bin 0 -> 65232 bytes Dijkstra Algorithm/Images/image4.png | Bin 0 -> 65286 bytes Dijkstra Algorithm/Images/image5.png | Bin 0 -> 66333 bytes Dijkstra Algorithm/Images/image6.png | Bin 0 -> 67070 bytes Dijkstra Algorithm/Images/image7.png | Bin 0 -> 66716 bytes Dijkstra Algorithm/README.md | 66 +++++++++++++++++++++------ 8 files changed, 52 insertions(+), 14 deletions(-) create mode 100644 Dijkstra Algorithm/Images/image1.png create mode 100644 Dijkstra Algorithm/Images/image2.png create mode 100644 Dijkstra Algorithm/Images/image3.png create mode 100644 Dijkstra Algorithm/Images/image4.png create mode 100644 Dijkstra Algorithm/Images/image5.png create mode 100644 Dijkstra Algorithm/Images/image6.png create mode 100644 Dijkstra Algorithm/Images/image7.png diff --git a/Dijkstra Algorithm/Images/image1.png b/Dijkstra Algorithm/Images/image1.png new file mode 100644 index 0000000000000000000000000000000000000000..aabe0969e2cf86efc9a5e2e3e313d8fa3e02818e GIT binary patch literal 61926 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 y9tz2t8pe1{?q0s@KBMqFG) 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

B7$oICoc!tXhtlK^rOAI7+;Y?9 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 iDv{4^gN(v|mI{h!ExBpa`i&JzP*gDMm#Nip(|y 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 diff --git a/Trie/sources/main.swift b/Trie/sources/main.swift index e88bbc713..8f95afdf7 100644 --- a/Trie/sources/main.swift +++ b/Trie/sources/main.swift @@ -8,6 +8,7 @@ T.insert("Hi") T.insert("Hey") T.insert("Hallo") T.insert("Henry") +T.insert("YELLO") var U: Trie = Trie(wordList: Set(["Hey", "HO", "hello", "yolo"])) var V: Trie = T.merge(U) //T.printTrie() @@ -31,4 +32,4 @@ assert(T.wordList.count == 3)*/ //T.printTrie() //print(T.find("")) -//print(T.findPrefix("H")) +print(T.findPrefix("H")) diff --git a/Trie/sources/trie.swift b/Trie/sources/trie.swift index bf1b44156..9088d2b70 100644 --- a/Trie/sources/trie.swift +++ b/Trie/sources/trie.swift @@ -3,13 +3,14 @@ public class Node { private var parent: Node? private var children: [String:Node] private var isAWord: Bool - + private var visited: Bool //only for findPrefix init(c: String?, p: Node?){ self.character = c self.children = [String:Node]() self.isAWord = false self.parent = p + self.visited = false } //Easier getter function, probably will make it more swift like @@ -233,8 +234,39 @@ public class Trie { func findPrefix(p: String) -> [String] { - var q: Queue = Queue() - return [] + if !self.isPrefix(p).found { + return [] + } + + var q: Queue = Queue() + var n: Node = self.isPrefix(p).node! + + var wordsWithPrefix: [String] = [] + var word = p + var tmp = "" + q.enqueue(n) + + while let current = q.dequeue() { + for (char, child) in current.getChildren() { + if(!child.visited) { + q.enqueue(child) + child.visited = true + if(child.isValidWord()) { + var currentNode = child + while currentNode !== n { + tmp += currentNode.char() + currentNode = currentNode.getParent() + } + tmp = String(tmp.characters.reverse()) + wordsWithPrefix.append(word + tmp) + } + } + tmp = "" + } + } + + + return wordsWithPrefix } From 002c70b07ec33e17128277be09b7a20481adfc4e Mon Sep 17 00:00:00 2001 From: Thukor Date: Tue, 3 May 2016 16:18:03 -0400 Subject: [PATCH 0316/1679] Fixed commit message.... --- Trie/sources/trie.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Trie/sources/trie.swift b/Trie/sources/trie.swift index 9088d2b70..092b497dc 100644 --- a/Trie/sources/trie.swift +++ b/Trie/sources/trie.swift @@ -259,9 +259,9 @@ public class Trie { } tmp = String(tmp.characters.reverse()) wordsWithPrefix.append(word + tmp) + tmp = "" } } - tmp = "" } } From 6f886298c9fd1cab41776684a8e477d0d72d2d46 Mon Sep 17 00:00:00 2001 From: Ashwin Date: Tue, 3 May 2016 17:23:49 -0400 Subject: [PATCH 0317/1679] fixed insertion and rotations --- Red Black Trees/RBTree.swift | 145 +++++++++++++++++++++++++---- Red Black Trees/RBTree.swift~ | 167 ++++++++++++++++++++++++++++++++++ 2 files changed, 294 insertions(+), 18 deletions(-) create mode 100644 Red Black Trees/RBTree.swift~ diff --git a/Red Black Trees/RBTree.swift b/Red Black Trees/RBTree.swift index 33c165b4e..cd43b8255 100644 --- a/Red Black Trees/RBTree.swift +++ b/Red Black Trees/RBTree.swift @@ -1,4 +1,3 @@ - public class RBTNode{ private(set) public var color: Bool private(set) public var left: RBTNode! @@ -14,17 +13,37 @@ public class RBTNode{ } init(rootData: Int){ self.data = rootData - self.color = true + self.color = true //0is black 1 is red self.left = nil self.right = nil self.parent = nil } + public func grandparent()->RBTNode?{ + if(self.parent === nil || self.parent.parent === nil){ + return nil + } + else{ + return self.parent.parent + } + } + public func sibling()->RBTNode?{ + if(self.parent === nil || self.parent.right === nil || self.parent.left === nil){ + return nil + } + if(self === self.parent!.left!){ + return self.parent!.right! + } + else{ + return self.parent!.left! + } + } } public class RBTree { private(set) public var root: RBTNode? init(rootData: Int) { root = RBTNode(rootData: rootData) + root!.color = false } init(){ root = nil @@ -47,7 +66,6 @@ public class RBTree { } private func inOrder(root: RBTNode?){ if(root == nil){ - print("nil") return } inOrder(root!.left) @@ -74,7 +92,7 @@ public class RBTree { } private func rightRotate(x: RBTNode) { let newRoot = x.left - x.left = newRoot.right + x.left = newRoot.right if newRoot.right !== nil { newRoot.right.parent = x } @@ -90,14 +108,94 @@ public class RBTree { x.parent = newRoot } +public func insertFixup(value: Int){ + let inserted = find(value) + + if(inserted == nil){ + print("INSERTEDNILLLLLLLL") + } + print("inserted: ") + print(inserted!.data) + insertCase1(inserted) +} +public func insertCase1(inserted: RBTNode?){ + let myroot = self.root! + if myroot === inserted!{ + self.root!.color = false + print("ITS THE ROOT") + print("insert case 1: The root was nil and we inserted a black node at root") + } + insertCase2(inserted!) +} +public func insertCase2(inserted: RBTNode?){ + if inserted!.parent!.color == false{ + print("Insert case 2: parent is black so nothing to change") + return + } + insertCase3(inserted!) +} +public func insertCase3(inserted: RBTNode?){ + if(inserted!.parent!.sibling() != nil && inserted!.parent!.sibling()!.color == true){ + print("insert case3: If both the parent P and the uncle U are red, then both of them can be repainted black and the grandparent G ") + inserted!.parent!.color = false + inserted!.parent!.sibling()!.color = false + let g = inserted!.grandparent + g()!.color = true + if(g()!.parent == nil){ + g()!.color = false + } + } + insertCase4(inserted) +} +//THIS ONE MAY BE BROKEN!?!?!?!? +public func insertCase4(var inserted: RBTNode?){ + if((inserted! === inserted!.parent!.right) && (inserted!.grandparent()!.left === inserted!.parent!)){ + print("case 4") + rightRotate(inserted!.parent) + inserted! = inserted!.left + } + else if((inserted! === inserted!.parent!.left) && (inserted!.grandparent()!.right === inserted!.parent!)){ + print("case 4") + leftRotate(inserted!.parent) + inserted! = inserted!.right + } + insertCase5(inserted) +} +public func insertCase5(inserted: RBTNode?){ + if((inserted!.parent!.color == true && (inserted!.parent!.sibling()?.color == false || inserted!.parent!.sibling() == nil ))){ + if(inserted! === inserted!.parent!.left && inserted!.grandparent()!.left === inserted!.parent!){ + print("insert case 5: The parent P is red but the uncle U is black/nil, the current node N is the left child of P, and P is the left child of its parent G") + inserted!.parent.color = false + inserted!.grandparent()?.color = true + if(inserted! === inserted!.parent!.left){ + print("its on the left") + rightRotate(inserted!.grandparent()!) + } + } + else if(inserted! === inserted!.parent!.right && inserted!.grandparent()!.right === inserted!.parent!){ + print("insert case 5: RIGHT RIGHT") + inserted!.parent.color = false + inserted!.grandparent()?.color = true + + print("Its on the right") + leftRotate(inserted!.grandparent()!) + + } + } + + print("weve reached the end boys") +} - private func insertFixup(){} public func insert(value: Int) { insert(value, parent: root!) - //insertFixUp() + insertFixup(value) } private func insert(value: Int, parent: RBTNode) { - if value < parent.data { + if self.root == nil{ + self.root = RBTNode(rootData: value) + return + } + else if value < parent.data { if let left = parent.left { insert(value, parent: left) } else { @@ -116,6 +214,7 @@ public class RBTree { public func find(data: Int)->RBTNode?{ return find(root!,data: data) } + private func find(root: RBTNode, data: Int)->RBTNode?{ if data == root.data{ return root @@ -140,19 +239,28 @@ tree.insert(9) tree.insert(6) tree.insert(5) tree.insert(4) -tree.insert(3) -tree.inOrder() -print("_________________________") -let x = tree.root! -print("root: \(tree.root!.data)") -tree.rightRotate(x) -print("root: \(tree.root!.data)") +tree.insert(40) +tree.insert(400) +tree.insert(430) + tree.inOrder() -let t = tree.find(234) -if t == nil{ - print("ASDASD") -} +//print("_________________________") +//let x = tree.root! +//print("sibling: \(tree.root!.left!.sibling()!.data)") +//print("root: \(tree.root!.data)") +//tree.rightRotate(x) +//print("root: \(tree.root!.data)") +//tree.inOrder() + +//let l = tree.root!.left! +//let r = tree.root!.right! +//print(l.data) +//print(r.data) +//if tree.root!.parent == nil{ +// print("ASDASD") +//} + //how you access certain elements //let root = tree.root!.left! //if(root.parent === nil){ @@ -165,3 +273,4 @@ if t == nil{ //print(tree.root!.data) //print(tree.root!.right!.data) //print(tree.root!.left!.data) + diff --git a/Red Black Trees/RBTree.swift~ b/Red Black Trees/RBTree.swift~ new file mode 100644 index 000000000..33c165b4e --- /dev/null +++ b/Red Black Trees/RBTree.swift~ @@ -0,0 +1,167 @@ + +public class RBTNode{ + private(set) public var color: Bool + private(set) public var left: RBTNode! + private(set) public var right: RBTNode! + private(set) public var parent: RBTNode! + private(set) public var data: Int + init(){ + self.data = -1 + self.color = true + self.left = nil + self.right = nil + self.parent = nil + } + init(rootData: Int){ + self.data = rootData + self.color = true + self.left = nil + self.right = nil + self.parent = nil + } +} +public class RBTree { + + private(set) public var root: RBTNode? + init(rootData: Int) { + root = RBTNode(rootData: rootData) + } + init(){ + root = nil + } + public func depth()->Int{ + let n = depth(root!) + return n + } + private func depth(rooty:RBTNode?)->Int{ + if(rooty == nil){ + return 0 + } + else{ + return 1+(max(depth(root!.left),depth(root!.right))) + } + } + + public func inOrder(){ + inOrder(root) + } + private func inOrder(root: RBTNode?){ + if(root == nil){ + print("nil") + return + } + inOrder(root!.left) + print("Data: \(root!.data) Color: \(root!.color)") + inOrder(root!.right) + } + + private func leftRotate(x: RBTNode) { + let newRoot = x.right + x.right = newRoot.left + if (newRoot.left !== nil) { + newRoot.left.parent = x + } + newRoot.parent = x.parent + if(x.parent === nil) { + root = newRoot + } else if (x === x.parent.left) { + x.parent.left = newRoot + } else { + x.parent.right = newRoot + } + newRoot.left = x + x.parent = newRoot + } + private func rightRotate(x: RBTNode) { + let newRoot = x.left + x.left = newRoot.right + if newRoot.right !== nil { + newRoot.right.parent = x + } + newRoot.parent = x.parent + if x.parent === nil { + root = newRoot + } else if x === x.parent.right { + x.parent.right = newRoot + } else { + x.parent.left = newRoot + } + newRoot.right = x + x.parent = newRoot +} + + + private func insertFixup(){} + public func insert(value: Int) { + insert(value, parent: root!) + //insertFixUp() + } + private func insert(value: Int, parent: RBTNode) { + if value < parent.data { + if let left = parent.left { + insert(value, parent: left) + } else { + parent.left = RBTNode(rootData: value) + parent.left?.parent = parent + } + } else { + if let right = parent.right { + insert(value, parent: right) + } else { + parent.right = RBTNode(rootData: value) + parent.right?.parent = parent + } + } + } + public func find(data: Int)->RBTNode?{ + return find(root!,data: data) + } + private func find(root: RBTNode, data: Int)->RBTNode?{ + if data == root.data{ + return root + } + if root.data != data && root.right == nil && root.left == nil { + return nil + } + else if data > root.data{ + return find(root.right, data: data) + } + else if data < root.data{ + return find(root.left, data: data) + } + else{ + return nil + } + } +} + +var tree = RBTree(rootData: 8) +tree.insert(9) +tree.insert(6) +tree.insert(5) +tree.insert(4) +tree.insert(3) +tree.inOrder() +print("_________________________") +let x = tree.root! +print("root: \(tree.root!.data)") +tree.rightRotate(x) +print("root: \(tree.root!.data)") +tree.inOrder() + +let t = tree.find(234) +if t == nil{ + print("ASDASD") +} +//how you access certain elements +//let root = tree.root!.left! +//if(root.parent === nil){ +// print("niggs") +//} +//else{ +// print(root.parent.data) +//} + +//print(tree.root!.data) +//print(tree.root!.right!.data) +//print(tree.root!.left!.data) From c6d34032b824957aa410f2279e25132afc396f7b Mon Sep 17 00:00:00 2001 From: Jayson Tung Date: Tue, 3 May 2016 17:36:10 -0400 Subject: [PATCH 0318/1679] Finalize ThreadedBinaryTree implementation --- Threaded Binary Tree/README.markdown | 52 ++++++- Threaded Binary Tree/ThreadedBinaryTree.swift | 136 +++--------------- .../ThreadedBinaryTreeTests.swift | 89 ++++++++++++ 3 files changed, 151 insertions(+), 126 deletions(-) create mode 100644 Threaded Binary Tree/ThreadedBinaryTreeTests.swift diff --git a/Threaded Binary Tree/README.markdown b/Threaded Binary Tree/README.markdown index 155404b66..1b35f39e2 100644 --- a/Threaded Binary Tree/README.markdown +++ b/Threaded Binary Tree/README.markdown @@ -185,25 +185,56 @@ a function that executes on each node as they are visited. This function can be anything you want, as long as it accepts `T` (the type of the values of the nodes of the tree) and has no return value. +Let's walk through a forward traversal of a tree by hand to get a better idea +of how a computer would do it. For example, take this simple threaded tree: + +![Base](Images/Base.png) + +We start at the root of the tree, **9**. Note that we don't `visit(9)` yet. +From there we want to go to the `minimum()` node in the tree, which is **2** in +this case. We then `visit(2)` and see that it has a `rightThread`, and thus +we immediately know what its `successor()` is. We follow the thread to **5**, +which does not have any leaving threads. Therefore, after we `visit(5)`, we go +to the `minimum()` node in its `right` subtree, which is **7**. We then +`visit(7)` and see that it has a `rightThread`, which we follow to get back to +**9**. *Now* we `visit(9)`, and after noticing that it has no `rightThread`, +we go to the `minimum()` node in its `right` subtree, which is **12**. This +node has a `rightThread` that leads to `nil`, which signals that we have +completed the traversal! We visited the nodes in order **2, 5, 7, 9, 12**, +which intuitively makes sense, as that is their natural increasing order. + +A backward traversal would be very similar, but you would replace `right`, +`rightThread`, `minimum()`, and `successor()` with `left`, `leftThread`, +`maximum()`, and `predecessor()`. + + ## Insertion and deletion The quick in-order traversal that a threaded binary trees gives us comes at a small cost. Inserting/deleting nodes becomes more complicated, as we have to -continuously manage the `leftThread` and `rightThread` variables. It is best -to explain this with an example. Please note that this requires knowledge of -binary search trees, so make sure you have +continuously manage the `leftThread` and `rightThread` variables. Rather than +walking through some boring code, it is best to explain this with an example +(although you can read through [the implementation](ThreadedBinaryTree.swift) +if you want to know the finer details). Please note that this requires +knowledge of binary search trees, so make sure you have [read this first](../Binary Search Tree/). -Base: +> Note: we do allow duplicate nodes in this implementation of a threaded binary +> tree. We break ties by defaulting insertion to the right. + +Let's start with the same tree that we used for the above traversal example: ![Base](Images/Base.png) -Insert1: +Suppose we `insert(10)` into this tree. The resulting graph would look like +this, with the changes highlighted in red: ![Insert1](Images/Insert1.png) -Insert2: +If you've done your homework and are familiar with binary search trees, the +placement of the node should not surprise you. What's new is how we maintain +the threads between nodes. ![Insert2](Images/Insert2.png) @@ -228,8 +259,15 @@ Remove4: ![Remove4](Images/Remove4.png) +## Miscellaneous methods + +There are many other smaller operations that a threaded binary tree can do, +such as `searching()` for a node in the tree, finding the `depth()` or +`height()` of a node, etc. You can check +[the implementation](ThreadedBinaryTree.swift) for the full technical details. +Many of these methods are inherent to binary search trees as well, so you can +find [further documentation here](../Binary Search Tree/). -### Still under construction. ## See also diff --git a/Threaded Binary Tree/ThreadedBinaryTree.swift b/Threaded Binary Tree/ThreadedBinaryTree.swift index c4fd2f4de..a046d4378 100644 --- a/Threaded Binary Tree/ThreadedBinaryTree.swift +++ b/Threaded Binary Tree/ThreadedBinaryTree.swift @@ -8,7 +8,7 @@ Any nodes that lack either a left or right child instead keep track of their in-order predecessor and/or successor. - This tree allows duplicate elements. + This tree allows duplicate elements (we break ties by defaulting right). This tree does not automatically balance itself. To make sure it is balanced, you should insert new values in randomized order, not in sorted order. @@ -18,8 +18,6 @@ public class ThreadedBinaryTree { private(set) public var parent: ThreadedBinaryTree? private(set) public var left: ThreadedBinaryTree? private(set) public var right: ThreadedBinaryTree? - - //THREADED private(set) public var leftThread: ThreadedBinaryTree? private(set) public var rightThread: ThreadedBinaryTree? @@ -92,9 +90,8 @@ extension ThreadedBinaryTree { } else { left = ThreadedBinaryTree(value: value) left?.parent = parent - //THREADED - left?.leftThread = leftThread left?.rightThread = parent + left?.leftThread = leftThread leftThread = nil } } else { @@ -103,9 +100,8 @@ extension ThreadedBinaryTree { } else { right = ThreadedBinaryTree(value: value) right?.parent = parent - //THREADED - right?.rightThread = rightThread right?.leftThread = parent + right?.rightThread = rightThread rightThread = nil } } @@ -124,7 +120,6 @@ extension ThreadedBinaryTree { Performance: runs in O(h) time, where h is the height of the tree. */ - //THREADED public func remove(value: T) -> ThreadedBinaryTree? { return search(value)?.remove() } @@ -138,7 +133,6 @@ extension ThreadedBinaryTree { if let left = left { if let right = right { replacement = removeNodeWithTwoChildren(left, right) - //THREADED replacement?.leftThread = leftThread replacement?.rightThread = rightThread left.maximum().rightThread = replacement @@ -146,18 +140,15 @@ extension ThreadedBinaryTree { } else { // This node only has a left child. The left child replaces the node. replacement = left - //THREADED left.maximum().rightThread = rightThread } } else if let right = right { // This node only has a right child. The right child replaces the node. replacement = right - //THREADED right.minimum().leftThread = leftThread } else { // This node has no children. We just disconnect it from its parent. replacement = nil - //THREADED if isLeftChild { parent?.leftThread = leftThread } else { @@ -171,7 +162,6 @@ extension ThreadedBinaryTree { parent = nil left = nil right = nil - //THREADED leftThread = nil rightThread = nil @@ -312,7 +302,6 @@ extension ThreadedBinaryTree { if let left = left { return left.maximum() } else { - //THREADED return leftThread } } @@ -324,7 +313,6 @@ extension ThreadedBinaryTree { if let right = right { return right.minimum() } else { - //THREADED return rightThread } } @@ -333,7 +321,6 @@ extension ThreadedBinaryTree { // MARK: - Traversal extension ThreadedBinaryTree { - //THREADED public func traverseInOrderForward(@noescape visit: T -> Void) { var n: ThreadedBinaryTree n = minimum() @@ -347,7 +334,6 @@ extension ThreadedBinaryTree { } } - //THREADED public func traverseInOrderBackward(@noescape visit: T -> Void) { var n: ThreadedBinaryTree n = maximum() @@ -378,7 +364,6 @@ extension ThreadedBinaryTree { */ public func map(@noescape formula: T -> T) -> [T] { var a = [T]() - //THREADED var n: ThreadedBinaryTree n = minimum() while true { @@ -412,20 +397,17 @@ extension ThreadedBinaryTree { The first and last nodes in the in-order traversal are exempt from this, as the first has leftThread = nil, and the last has rightThread = nil. */ - //THREADED public func isThreaded() -> Bool { - if self === minimum() { - if left != nil && leftThread != nil { - return false - } - } else if (left == nil && leftThread == nil) || (left != nil && leftThread != nil) { + if left == nil && leftThread == nil { + if self !== minimum() { return false } + } + if left != nil && leftThread != nil { return false } - if self === maximum() { - if right != nil && rightThread != nil { - return false - } - } else if (right == nil && rightThread == nil) || (right != nil && rightThread != nil) { + if right == nil && rightThread == nil { + if self !== maximum() { return false } + } + if right != nil && rightThread != nil { return false } let leftThreaded = left?.isThreaded() ?? true @@ -456,19 +438,18 @@ extension ThreadedBinaryTree: CustomDebugStringConvertible { if let parent = parent { s += ", parent: \(parent.value)" } - if let left = left { - s += ", left = [" + left.debugDescription + "]" - } - if let right = right { - s += ", right = [" + right.debugDescription + "]" - } - //THREADED if let leftThread = leftThread { s += ", leftThread: \(leftThread.value)" } if let rightThread = rightThread { s += ", rightThread: \(rightThread.value)" } + if let left = left { + s += ", left = [" + left.debugDescription + "]" + } + if let right = right { + s += ", right = [" + right.debugDescription + "]" + } return s } @@ -476,86 +457,3 @@ extension ThreadedBinaryTree: CustomDebugStringConvertible { return map { $0 } } } - -/* - TESTS - I don't have an Apple computer, so I can't make a Playground or any of that - fancy stuff. Here's a simple demonstration of the ThreadedBinaryTree class. - It follows the examples in the README. -*/ - -// Simple little debug function to make testing output pretty -private func check(tree: ThreadedBinaryTree?) { - if let tree = tree { - print("\(tree.count) Total Nodes:"); - print(tree) - print("Debug Info:") - print(tree.debugDescription) - print("In-Order Traversal:") - let myArray = tree.toArray() - for node in myArray { - print(node) - } - if tree.isThreaded() { - print("This threaded binary tree is VALID.") - } else { - print("This threaded binary tree is INVALID.") - } - } else { - print("This tree is nil.") - } -} - - -print("\nTree with Single Node") -let emptyTree = ThreadedBinaryTree(value: 1) -check(emptyTree) - -print("\nFull Balanced Binary Tree with 7 Nodes") -let fullTree = ThreadedBinaryTree(value: 4) -fullTree.insert(2) -fullTree.insert(6) -fullTree.insert(1) -fullTree.insert(3) -fullTree.insert(5) -fullTree.insert(7) -check(fullTree) - - -print("\n\nUnbalanced Binary Tree with 5 Nodes") -let tree = ThreadedBinaryTree(array: [9, 5, 12, 2, 7]) -check(tree) - -print("\nInsert 10") -tree.insert(10) -check(tree) - -print("\nInsert 4") -tree.insert(4) -check(tree) - -print("\nInsert 15") -tree.insert(15) -check(tree) - -print("\nRemove 13 (Not in the Tree)") -tree.remove(13) -check(tree) - -print("\nRemove 7") -tree.remove(7) -check(tree) - -print("\nRemove 5") -tree.remove(5) -check(tree) - -print("\nRemove 9 (root)") -let newRoot = tree.remove(9) -check(newRoot) - -print("\nRemove 12") -newRoot?.remove(12) -check(newRoot) - -print("\n\nDone with Tests!\n") diff --git a/Threaded Binary Tree/ThreadedBinaryTreeTests.swift b/Threaded Binary Tree/ThreadedBinaryTreeTests.swift new file mode 100644 index 000000000..550df424d --- /dev/null +++ b/Threaded Binary Tree/ThreadedBinaryTreeTests.swift @@ -0,0 +1,89 @@ +/* + TESTS + I don't have access to an Apple computer, so I can't make a Playground or any + of that fancy stuff. Here's a simple demonstration of the ThreadedBinaryTree + class. It follows the examples in the README. +*/ + +// Simple little debug function to make testing output pretty +func check(tree: ThreadedBinaryTree?) { + if let tree = tree { + print("\(tree.count) Total Nodes:"); + print(tree) + print("Debug Info:") + print(tree.debugDescription) + print("In-Order Traversal:") + let myArray = tree.toArray() + for node in myArray { + print(node) + } + if tree.isBST(minValue: Int.min, maxValue: Int.max) { + print("This is a VALID binary search tree.") + } else { + print("This is an INVALID binary search tree.") + } + if tree.isThreaded() { + print("This is a VALID threaded binary tree.") + } else { + print("This is an INVALID threaded binary tree.") + } + } else { + print("This tree is nil.") + } +} + + +print("\nTree with Single Node") +let emptyTree = ThreadedBinaryTree(value: 1) +check(emptyTree) + + +print("\nFull Balanced Binary Tree with 7 Nodes") +let fullTree = ThreadedBinaryTree(value: 4) +fullTree.insert(2) +fullTree.insert(1) +fullTree.insert(6) +fullTree.insert(5) +fullTree.insert(3) +fullTree.insert(7) +check(fullTree) + + +print("\n\nBase Binary Tree with 5 Nodes") +let tree = ThreadedBinaryTree(array: [9, 5, 12, 2, 7]) +check(tree) + +print("\nInsert 10") +tree.insert(10) +check(tree) + +print("\nInsert 4") +tree.insert(4) +check(tree) + +print("\nInsert 15") +tree.insert(15) +check(tree) + +print("\nRemove 13 (Not in the Tree)") +tree.remove(13) +check(tree) + +print("\nRemove 7") +tree.remove(7) +check(tree) + +print("\nRemove 5") +tree.remove(5) +check(tree) + +print("\nRemove 9 (root)") +let newRoot = tree.remove(9) +check(newRoot) + +print("\nRemove 12") +newRoot?.remove(12) +check(newRoot) + + +print("\n\nDone with Tests!\n") From ba9b1bb2fa6e49f9eb9f733cf5312508bf99d517 Mon Sep 17 00:00:00 2001 From: Ashwin Date: Tue, 3 May 2016 20:01:16 -0400 Subject: [PATCH 0319/1679] added delete helpers --- Red Black Trees/RBTree.swift | 63 ++++++++++++--- Red Black Trees/RBTree.swift~ | 145 +++++++++++++++++++++++++++++----- 2 files changed, 181 insertions(+), 27 deletions(-) diff --git a/Red Black Trees/RBTree.swift b/Red Black Trees/RBTree.swift index cd43b8255..69d49b230 100644 --- a/Red Black Trees/RBTree.swift +++ b/Red Black Trees/RBTree.swift @@ -37,6 +37,37 @@ public class RBTNode{ return self.parent!.left! } } + public func replaceNode(n1: RBTNode, n2: RBTNode){ + var temp = n1.data + var temp_color = n1.color + n1.data = n2.data + n1.color = n2.color + n2.data = temp + n2.color = temp_color + } + public func minimum(var node: RBTNode)->RBTNode { + while node.left !== nil{ + node = node.left + } + return node + } + public func successorOfNode(var node: RBTNode) -> RBTNode? { + if node.right !== nil { + return minimum(node.right) + } + var successor = node.parent + while successor !== nil && node === successor.right { + node = successor + successor = successor.parent + } + return successor + } + public func maximum(var rootNode: RBTNode) -> RBTNode{ + while rootNode.right !== nil { + rootNode = rootNode.right + } + return rootNode + } } public class RBTree { @@ -118,7 +149,7 @@ public func insertFixup(value: Int){ print(inserted!.data) insertCase1(inserted) } -public func insertCase1(inserted: RBTNode?){ +private func insertCase1(inserted: RBTNode?){ let myroot = self.root! if myroot === inserted!{ self.root!.color = false @@ -127,14 +158,14 @@ public func insertCase1(inserted: RBTNode?){ } insertCase2(inserted!) } -public func insertCase2(inserted: RBTNode?){ +private func insertCase2(inserted: RBTNode?){ if inserted!.parent!.color == false{ print("Insert case 2: parent is black so nothing to change") return } insertCase3(inserted!) } -public func insertCase3(inserted: RBTNode?){ +private func insertCase3(inserted: RBTNode?){ if(inserted!.parent!.sibling() != nil && inserted!.parent!.sibling()!.color == true){ print("insert case3: If both the parent P and the uncle U are red, then both of them can be repainted black and the grandparent G ") inserted!.parent!.color = false @@ -148,7 +179,7 @@ public func insertCase3(inserted: RBTNode?){ insertCase4(inserted) } //THIS ONE MAY BE BROKEN!?!?!?!? -public func insertCase4(var inserted: RBTNode?){ +private func insertCase4(var inserted: RBTNode?){ if((inserted! === inserted!.parent!.right) && (inserted!.grandparent()!.left === inserted!.parent!)){ print("case 4") rightRotate(inserted!.parent) @@ -161,7 +192,7 @@ public func insertCase4(var inserted: RBTNode?){ } insertCase5(inserted) } -public func insertCase5(inserted: RBTNode?){ +private func insertCase5(inserted: RBTNode?){ if((inserted!.parent!.color == true && (inserted!.parent!.sibling()?.color == false || inserted!.parent!.sibling() == nil ))){ if(inserted! === inserted!.parent!.left && inserted!.grandparent()!.left === inserted!.parent!){ print("insert case 5: The parent P is red but the uncle U is black/nil, the current node N is the left child of P, and P is the left child of its parent G") @@ -179,10 +210,8 @@ public func insertCase5(inserted: RBTNode?){ print("Its on the right") leftRotate(inserted!.grandparent()!) - } } - print("weve reached the end boys") } @@ -232,6 +261,17 @@ public func insertCase5(inserted: RBTNode?){ return nil } } + + //DELETION HELPER FUNCTIONS + public func remove(value: Int){ + let toRemove = find(value) + if(toRemove == nil){ + return + } + } + + + } var tree = RBTree(rootData: 8) @@ -242,7 +282,12 @@ tree.insert(4) tree.insert(40) tree.insert(400) tree.insert(430) - +var t = tree.root! +var min = t.minimum(t) +print("MIN: \(min.data)") +var x = tree.root!.left +tree.inOrder() +t.replaceNode(t,n2:x) tree.inOrder() //print("_________________________") @@ -264,7 +309,7 @@ tree.inOrder() //how you access certain elements //let root = tree.root!.left! //if(root.parent === nil){ -// print("niggs") +// print("nil") //} //else{ // print(root.parent.data) diff --git a/Red Black Trees/RBTree.swift~ b/Red Black Trees/RBTree.swift~ index 33c165b4e..cd43b8255 100644 --- a/Red Black Trees/RBTree.swift~ +++ b/Red Black Trees/RBTree.swift~ @@ -1,4 +1,3 @@ - public class RBTNode{ private(set) public var color: Bool private(set) public var left: RBTNode! @@ -14,17 +13,37 @@ public class RBTNode{ } init(rootData: Int){ self.data = rootData - self.color = true + self.color = true //0is black 1 is red self.left = nil self.right = nil self.parent = nil } + public func grandparent()->RBTNode?{ + if(self.parent === nil || self.parent.parent === nil){ + return nil + } + else{ + return self.parent.parent + } + } + public func sibling()->RBTNode?{ + if(self.parent === nil || self.parent.right === nil || self.parent.left === nil){ + return nil + } + if(self === self.parent!.left!){ + return self.parent!.right! + } + else{ + return self.parent!.left! + } + } } public class RBTree { private(set) public var root: RBTNode? init(rootData: Int) { root = RBTNode(rootData: rootData) + root!.color = false } init(){ root = nil @@ -47,7 +66,6 @@ public class RBTree { } private func inOrder(root: RBTNode?){ if(root == nil){ - print("nil") return } inOrder(root!.left) @@ -74,7 +92,7 @@ public class RBTree { } private func rightRotate(x: RBTNode) { let newRoot = x.left - x.left = newRoot.right + x.left = newRoot.right if newRoot.right !== nil { newRoot.right.parent = x } @@ -90,14 +108,94 @@ public class RBTree { x.parent = newRoot } +public func insertFixup(value: Int){ + let inserted = find(value) + + if(inserted == nil){ + print("INSERTEDNILLLLLLLL") + } + print("inserted: ") + print(inserted!.data) + insertCase1(inserted) +} +public func insertCase1(inserted: RBTNode?){ + let myroot = self.root! + if myroot === inserted!{ + self.root!.color = false + print("ITS THE ROOT") + print("insert case 1: The root was nil and we inserted a black node at root") + } + insertCase2(inserted!) +} +public func insertCase2(inserted: RBTNode?){ + if inserted!.parent!.color == false{ + print("Insert case 2: parent is black so nothing to change") + return + } + insertCase3(inserted!) +} +public func insertCase3(inserted: RBTNode?){ + if(inserted!.parent!.sibling() != nil && inserted!.parent!.sibling()!.color == true){ + print("insert case3: If both the parent P and the uncle U are red, then both of them can be repainted black and the grandparent G ") + inserted!.parent!.color = false + inserted!.parent!.sibling()!.color = false + let g = inserted!.grandparent + g()!.color = true + if(g()!.parent == nil){ + g()!.color = false + } + } + insertCase4(inserted) +} +//THIS ONE MAY BE BROKEN!?!?!?!? +public func insertCase4(var inserted: RBTNode?){ + if((inserted! === inserted!.parent!.right) && (inserted!.grandparent()!.left === inserted!.parent!)){ + print("case 4") + rightRotate(inserted!.parent) + inserted! = inserted!.left + } + else if((inserted! === inserted!.parent!.left) && (inserted!.grandparent()!.right === inserted!.parent!)){ + print("case 4") + leftRotate(inserted!.parent) + inserted! = inserted!.right + } + insertCase5(inserted) +} +public func insertCase5(inserted: RBTNode?){ + if((inserted!.parent!.color == true && (inserted!.parent!.sibling()?.color == false || inserted!.parent!.sibling() == nil ))){ + if(inserted! === inserted!.parent!.left && inserted!.grandparent()!.left === inserted!.parent!){ + print("insert case 5: The parent P is red but the uncle U is black/nil, the current node N is the left child of P, and P is the left child of its parent G") + inserted!.parent.color = false + inserted!.grandparent()?.color = true + if(inserted! === inserted!.parent!.left){ + print("its on the left") + rightRotate(inserted!.grandparent()!) + } + } + else if(inserted! === inserted!.parent!.right && inserted!.grandparent()!.right === inserted!.parent!){ + print("insert case 5: RIGHT RIGHT") + inserted!.parent.color = false + inserted!.grandparent()?.color = true + + print("Its on the right") + leftRotate(inserted!.grandparent()!) + + } + } + + print("weve reached the end boys") +} - private func insertFixup(){} public func insert(value: Int) { insert(value, parent: root!) - //insertFixUp() + insertFixup(value) } private func insert(value: Int, parent: RBTNode) { - if value < parent.data { + if self.root == nil{ + self.root = RBTNode(rootData: value) + return + } + else if value < parent.data { if let left = parent.left { insert(value, parent: left) } else { @@ -116,6 +214,7 @@ public class RBTree { public func find(data: Int)->RBTNode?{ return find(root!,data: data) } + private func find(root: RBTNode, data: Int)->RBTNode?{ if data == root.data{ return root @@ -140,19 +239,28 @@ tree.insert(9) tree.insert(6) tree.insert(5) tree.insert(4) -tree.insert(3) -tree.inOrder() -print("_________________________") -let x = tree.root! -print("root: \(tree.root!.data)") -tree.rightRotate(x) -print("root: \(tree.root!.data)") +tree.insert(40) +tree.insert(400) +tree.insert(430) + tree.inOrder() -let t = tree.find(234) -if t == nil{ - print("ASDASD") -} +//print("_________________________") +//let x = tree.root! +//print("sibling: \(tree.root!.left!.sibling()!.data)") +//print("root: \(tree.root!.data)") +//tree.rightRotate(x) +//print("root: \(tree.root!.data)") +//tree.inOrder() + +//let l = tree.root!.left! +//let r = tree.root!.right! +//print(l.data) +//print(r.data) +//if tree.root!.parent == nil{ +// print("ASDASD") +//} + //how you access certain elements //let root = tree.root!.left! //if(root.parent === nil){ @@ -165,3 +273,4 @@ if t == nil{ //print(tree.root!.data) //print(tree.root!.right!.data) //print(tree.root!.left!.data) + From df9e4f6887fe0933ca589b8d832b10482c038a5e Mon Sep 17 00:00:00 2001 From: Ashwin Date: Tue, 3 May 2016 20:07:12 -0400 Subject: [PATCH 0320/1679] added predecessor --- Red Black Trees/RBTree.swift | 13 +++++- Red Black Trees/RBTree.swift~ | 74 ++++++++++++++++++++++++++++++----- 2 files changed, 77 insertions(+), 10 deletions(-) diff --git a/Red Black Trees/RBTree.swift b/Red Black Trees/RBTree.swift index 69d49b230..4cb0c2fcb 100644 --- a/Red Black Trees/RBTree.swift +++ b/Red Black Trees/RBTree.swift @@ -51,7 +51,7 @@ public class RBTNode{ } return node } - public func successorOfNode(var node: RBTNode) -> RBTNode? { + public func successor(var node: RBTNode) -> RBTNode? { if node.right !== nil { return minimum(node.right) } @@ -62,6 +62,17 @@ public class RBTNode{ } return successor } + public func predecessor(var node: RBTNode) -> RBTNode{ + if node.left !== nil { + return minimum(node.left) + } + var successor = node.parent + while successor !== nil && node === successor.left { + node = successor + successor = successor.parent + } + return successor + } public func maximum(var rootNode: RBTNode) -> RBTNode{ while rootNode.right !== nil { rootNode = rootNode.right diff --git a/Red Black Trees/RBTree.swift~ b/Red Black Trees/RBTree.swift~ index cd43b8255..4cb0c2fcb 100644 --- a/Red Black Trees/RBTree.swift~ +++ b/Red Black Trees/RBTree.swift~ @@ -37,6 +37,48 @@ public class RBTNode{ return self.parent!.left! } } + public func replaceNode(n1: RBTNode, n2: RBTNode){ + var temp = n1.data + var temp_color = n1.color + n1.data = n2.data + n1.color = n2.color + n2.data = temp + n2.color = temp_color + } + public func minimum(var node: RBTNode)->RBTNode { + while node.left !== nil{ + node = node.left + } + return node + } + public func successor(var node: RBTNode) -> RBTNode? { + if node.right !== nil { + return minimum(node.right) + } + var successor = node.parent + while successor !== nil && node === successor.right { + node = successor + successor = successor.parent + } + return successor + } + public func predecessor(var node: RBTNode) -> RBTNode{ + if node.left !== nil { + return minimum(node.left) + } + var successor = node.parent + while successor !== nil && node === successor.left { + node = successor + successor = successor.parent + } + return successor + } + public func maximum(var rootNode: RBTNode) -> RBTNode{ + while rootNode.right !== nil { + rootNode = rootNode.right + } + return rootNode + } } public class RBTree { @@ -118,7 +160,7 @@ public func insertFixup(value: Int){ print(inserted!.data) insertCase1(inserted) } -public func insertCase1(inserted: RBTNode?){ +private func insertCase1(inserted: RBTNode?){ let myroot = self.root! if myroot === inserted!{ self.root!.color = false @@ -127,14 +169,14 @@ public func insertCase1(inserted: RBTNode?){ } insertCase2(inserted!) } -public func insertCase2(inserted: RBTNode?){ +private func insertCase2(inserted: RBTNode?){ if inserted!.parent!.color == false{ print("Insert case 2: parent is black so nothing to change") return } insertCase3(inserted!) } -public func insertCase3(inserted: RBTNode?){ +private func insertCase3(inserted: RBTNode?){ if(inserted!.parent!.sibling() != nil && inserted!.parent!.sibling()!.color == true){ print("insert case3: If both the parent P and the uncle U are red, then both of them can be repainted black and the grandparent G ") inserted!.parent!.color = false @@ -148,7 +190,7 @@ public func insertCase3(inserted: RBTNode?){ insertCase4(inserted) } //THIS ONE MAY BE BROKEN!?!?!?!? -public func insertCase4(var inserted: RBTNode?){ +private func insertCase4(var inserted: RBTNode?){ if((inserted! === inserted!.parent!.right) && (inserted!.grandparent()!.left === inserted!.parent!)){ print("case 4") rightRotate(inserted!.parent) @@ -161,7 +203,7 @@ public func insertCase4(var inserted: RBTNode?){ } insertCase5(inserted) } -public func insertCase5(inserted: RBTNode?){ +private func insertCase5(inserted: RBTNode?){ if((inserted!.parent!.color == true && (inserted!.parent!.sibling()?.color == false || inserted!.parent!.sibling() == nil ))){ if(inserted! === inserted!.parent!.left && inserted!.grandparent()!.left === inserted!.parent!){ print("insert case 5: The parent P is red but the uncle U is black/nil, the current node N is the left child of P, and P is the left child of its parent G") @@ -179,10 +221,8 @@ public func insertCase5(inserted: RBTNode?){ print("Its on the right") leftRotate(inserted!.grandparent()!) - } } - print("weve reached the end boys") } @@ -232,6 +272,17 @@ public func insertCase5(inserted: RBTNode?){ return nil } } + + //DELETION HELPER FUNCTIONS + public func remove(value: Int){ + let toRemove = find(value) + if(toRemove == nil){ + return + } + } + + + } var tree = RBTree(rootData: 8) @@ -242,7 +293,12 @@ tree.insert(4) tree.insert(40) tree.insert(400) tree.insert(430) - +var t = tree.root! +var min = t.minimum(t) +print("MIN: \(min.data)") +var x = tree.root!.left +tree.inOrder() +t.replaceNode(t,n2:x) tree.inOrder() //print("_________________________") @@ -264,7 +320,7 @@ tree.inOrder() //how you access certain elements //let root = tree.root!.left! //if(root.parent === nil){ -// print("niggs") +// print("nil") //} //else{ // print(root.parent.data) From 8fdc1aff72210bc093c6e80b01af10e53df412cc Mon Sep 17 00:00:00 2001 From: Jayson Tung Date: Tue, 3 May 2016 22:36:59 -0400 Subject: [PATCH 0321/1679] Complete rough draft of Thread. Bin. Tree README --- Threaded Binary Tree/README.markdown | 116 ++++++++++++++++++++++----- 1 file changed, 95 insertions(+), 21 deletions(-) diff --git a/Threaded Binary Tree/README.markdown b/Threaded Binary Tree/README.markdown index 1b35f39e2..e3a27eb4b 100644 --- a/Threaded Binary Tree/README.markdown +++ b/Threaded Binary Tree/README.markdown @@ -2,7 +2,10 @@ A threaded binary tree is a special kind of [binary tree](../Binary Tree/) (a tree in which each node has at most two children) that maintains a few extra -variables to allow cheap and fast **in-order traversal** of the tree. +variables to allow cheap and fast **in-order traversal** of the tree. We will +explore the general structure of threaded binary trees, as well as +[the Swift implementation](ThreadedBinaryTree.swift) of a fully functioning +threaded binary tree. If you don't know what a tree is or what it is for, then [read this first](../Tree/). @@ -11,14 +14,15 @@ If you don't know what a tree is or what it is for, then ## In-order traversal The main motivation behind using a threaded binary tree over a simpler and -smaller standard binary tree is to increase the speed of **in-order traversal** +smaller standard binary tree is to increase the speed of in-order traversal of the tree. An in-order traversal of a binary tree visits the nodes in the order in which they are stored, which matches the underlying ordering of a [binary search tree](../Binary Search Tree/). The idea is to visit all the left children of a node first, then visit the node itself, and visit the left children last. -In-order traversal of any binary tree generally goes as follows: +In-order traversal of any binary tree generally goes as follows (using Swift +syntax): ```swift func traverse(n: Node?) { @@ -48,15 +52,15 @@ A threaded binary tree fixes this problem. ## Predecessors and successors An in-order traversal of a tree yields a linear ordering of the nodes. Thus -each node has both a predecessor and a successor (except for the first and last -nodes, which only have a successor or a predecessor respectively). In a -threaded binary tree, each left child that would normally be `nil` instead +each node has both a **predecessor** and a **successor** (except for the first +and last nodes, which only have a successor or a predecessor respectively). In +a threaded binary tree, each left child that would normally be `nil` instead stores the node's predecessor (if it exists), and each right child that would normally be `nil` instead stores the node's successor (if it exists). This is what separates threaded binary trees from standard binary trees. -There are two types of threaded binary trees: single threaded and double -threaded: +There are two types of threaded binary trees: **single threaded** and **double +threaded**: - A single threaded tree keeps track of **either** the in-order predecessor **or** successor (left **or** right). - A double threaded tree keeps track of **both** the in-order predecessor @@ -110,7 +114,8 @@ Swift *optionals*. - `leftThread: ThreadedBinaryTree?` is the in-order predecessor of this node - `rightThread: ThreadedBinaryTree?` is the in-order successor of this node -Now we are ready to go over some of the member functions in our +As we are storing both `leftThread` and `rightThread`, this is a double +threaded tree. Now we are ready to go over some of the member functions in our `ThreadedBinaryTree` class. @@ -118,9 +123,9 @@ Now we are ready to go over some of the member functions in our Let's start with the main reason we're using a threaded binary tree. It is now very easy to find the in-order predecessor and the in-order successor of any -node in the tree. If the node has no left/right child, we can simply return -the node's leftThread/rightThread. Otherwise, it is trivial to move down the -tree and find the correct node. +node in the tree. If the node has no `left`/`right` child, we can simply +return the node's `leftThread`/`rightThread`. Otherwise, it is trivial to move +down the tree and find the correct node. ```swift func predecessor() -> ThreadedBinaryTree? { @@ -227,37 +232,104 @@ Let's start with the same tree that we used for the above traversal example: ![Base](Images/Base.png) -Suppose we `insert(10)` into this tree. The resulting graph would look like +Suppose we insert **10** into this tree. The resulting graph would look like this, with the changes highlighted in red: ![Insert1](Images/Insert1.png) If you've done your homework and are familiar with binary search trees, the -placement of the node should not surprise you. What's new is how we maintain -the threads between nodes. +placement of this node should not surprise you. What's new is how we maintain +the threads between nodes. So we know that we want to insert **10** as +**12**'s `left` child. The first thing we do is set **12**'s `left` child to +**10**, and set **10**'s `parent` to **12**. Because **10** is being inserted +on the `left`, and **10** has no children of its own, we can safely set +**10**'s `rightThread` to its `parent` **12**. What about **10**'s +`leftThread`? Because we know that **10** < **12**, and **10** is the only +`left` child of **12**, we can safely set **10**'s `leftThread` to **12**'s +(now outdated) `leftThread`. Finally we set **12**'s `leftThread = nil`, as it +now has a `left` child. + +Let's now insert another node, **4**, into the tree: ![Insert2](Images/Insert2.png) -Insert3: +While we are inserting **4** as a `right` child, it follows the exact same +process as above, but mirrored (swap `left` and `right`). For the sake of +completeness, we'll insert one final node, **15**: ![Insert3](Images/Insert3.png) -Remove1: +Now that we have a fairly crowded tree, let's try removing some nodes. +Compared to insertion, deletion is a little more complicated. Let's start with +something simple, like removing **7**, which has no children: ![Remove1](Images/Remove1.png) -Remove2: +Before we can just throw **7** away, we have to perform some clean-up. In this +case, because **7** is a `right` child and has no children itself, we can +simply set the `rightThread` of **7**'s `parent`(**5**) to **7**'s (now +outdated) `rightThread`. Then we can just set **7**'s `parent`, `left`, +`right`, `leftThread`, and `rightThread` to `nil`, effectively removing it from +the tree. + +Let's try something a little harder. Say we remove **5** from the tree: ![Remove2](Images/Remove2.png) -Remove3: +This is a little trickier, as **5** has some children that we have to deal +with. The core idea is to replace **5** with its first child, **2**. To +accomplish this, we of course set **2**'s `parent` to **9** and set **9**'s +`left` child to **2**. Note that **4**'s `rightThread` used to be **5**, but +we are removing **5**, so it needs to change. It is now important to +understand two important properties of threaded binary trees: + +1. For the rightmost node **m** in the `left` subtree of any node **n**, +**m**'s `rightThread` is **n**. +2. For the leftmost node **m** in the `right` subtree of any node **n**, +**m**'s `leftThread` is **n**. + +Note how this property held true before the removal of **5**, as **4** was the +rightmost node in **5**'s `left` subtree. In order to maintain this property, +we must set **4**'s `rightThread` to **9**, as **4** is now the rightmost node +in **9**'s `left` subtree. To completely remove **5**, all we now have to do +is set **5**'s `parent`, `left`, `right`, `leftThread`, and `rightThread` to +`nil`. + +How about we do something crazy? What would happen if we tried to remove +**9**, the root node? This is the resulting tree: ![Remove3](Images/Remove3.png) -Remove4: +Whenever we want to remove a node that has two children, we take a slightly +different approach than the above examples. The basic idea is to replace the +node that we want to remove with the leftmost node in its `right` subtree, +which we call the replacement node. + +> Note: we could also replace the node with the rightmost node in its `left` +> subtree. Choosing left or right is mostly an arbitrary decision. + +Once we find the replacement node, **10** in this case, we remove it from the +tree using the algorithms outlined above. This ensures that the edges in the +`right` subtree remain correct. From there it is easy to replace **9** with +**10**, as we just have to update the edges leaving **10**. Now all we have to +do is fiddle with the threads in order to maintain the two properties outlined +above. In this case, **12**'s `leftThread` is now **10**. Node **9** is no +longer needed, so we can finish teh removal process by setting all of its +variables to `nil`. + +In order to illustrate how to remove a node that has only a `right` child, +we'll remove one final node, **12** from the tree: ![Remove4](Images/Remove4.png) +The process to remove **12** is identical to the process we used to remove +**5**, but mirrored. **5** had a `left` child, while **12** has a `right` +child, but the core algorithm is the same. + +That is a quick overview of how insertion and deletion work in threaded binary +trees. More detail can of course be found in +[the implementation](ThreadedBinaryTree.swift). + ## Miscellaneous methods @@ -271,7 +343,9 @@ find [further documentation here](../Binary Search Tree/). ## See also -[Threaded Binary Tree on Wikipedia](https://en.wikipedia.org/wiki/Threaded_binary_tree). +[Threaded Binary Tree on Wikipedia](https://en.wikipedia.org/wiki/Threaded_binary_tree) *Written for the Swift Algorithm Club by [Jayson Tung](https://github.com/JFTung)* + +*Images made using www.draw.io* From 6ab41aad8ac66675af43e7690854371624355597 Mon Sep 17 00:00:00 2001 From: Thukor Date: Tue, 3 May 2016 22:55:08 -0400 Subject: [PATCH 0322/1679] Finished Radix Sort Implementation --- Radix-Sort/radixSort | Bin 0 -> 20310 bytes Radix-Sort/radixSort.swift | 42 +++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100755 Radix-Sort/radixSort create mode 100644 Radix-Sort/radixSort.swift diff --git a/Radix-Sort/radixSort b/Radix-Sort/radixSort new file mode 100755 index 0000000000000000000000000000000000000000..6ebfbe215703f5c207e9c454062125f9e1fc466d GIT binary patch literal 20310 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 QqHj!kR$tua|5y(DADjR>DF6Tf literal 0 HcmV?d00001 diff --git a/Radix-Sort/radixSort.swift b/Radix-Sort/radixSort.swift new file mode 100644 index 000000000..47bdb0fd1 --- /dev/null +++ b/Radix-Sort/radixSort.swift @@ -0,0 +1,42 @@ +func radixSort(inout arr: [Int] ) { + + let radix = 10 + var done = false + var index: Int + var digit = 1 + + while !done { + done = true + + var buckets: [[Int]] = [] + + for _ in 1...radix { + buckets.append([]) + } + + + for number in arr { + index = number / digit + buckets[index % radix].append(number) + if done && index > 0 { + done = false + } + } + + var i = 0 + + for j in 0.. Date: Tue, 3 May 2016 23:28:23 -0400 Subject: [PATCH 0323/1679] Finalize Threaded Binary Tree README --- Threaded Binary Tree/README.markdown | 44 +++++++++++++++------------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/Threaded Binary Tree/README.markdown b/Threaded Binary Tree/README.markdown index e3a27eb4b..048a1f23d 100644 --- a/Threaded Binary Tree/README.markdown +++ b/Threaded Binary Tree/README.markdown @@ -14,14 +14,15 @@ If you don't know what a tree is or what it is for, then ## In-order traversal The main motivation behind using a threaded binary tree over a simpler and -smaller standard binary tree is to increase the speed of in-order traversal +smaller standard binary tree is to increase the speed of an in-order traversal of the tree. An in-order traversal of a binary tree visits the nodes in the order in which they are stored, which matches the underlying ordering of a -[binary search tree](../Binary Search Tree/). The idea is to visit all the -left children of a node first, then visit the node itself, and visit the left +[binary search tree](../Binary Search Tree/). Thus threaded binary trees are +almost always binary search trees too. The idea is to visit all the left +children of a node first, then visit the node itself, and visit the left children last. -In-order traversal of any binary tree generally goes as follows (using Swift +An in-order traversal of any binary tree generally goes as follows (using Swift syntax): ```swift @@ -68,8 +69,8 @@ threaded**: Using a single or double threaded tree depends on what we want to accomplish. If we only need to traverse the tree in one direction (either forward or -backward), use a single threaded tree. If we want to traverse in both -directions, use a double threaded tree. +backward), then we use a single threaded tree. If we want to traverse in both +directions, then we use a double threaded tree. It is important to note that each node stores either its predecessor or its left child, and either its successor or its right child. The nodes do not @@ -77,7 +78,7 @@ need to keep track of both. For example, in a double threaded tree, if a node has a right child but no left child, it will track its predecessor in place of its left child. -Here is a valid "full" threaded binary tree: +Here is an example valid "full" threaded binary tree: ![Full](Images/Full.png) @@ -106,11 +107,11 @@ The core of this data structure is the `ThreadedBinaryTree` class. Each instance of this class represents a node with six member variables: `value`, `parent`, `left`, `right`, `leftThread`, and `rightThread`. Of all of these, only `value` is required. The other five are -Swift *optionals*. +Swift *optionals* (they may be `nil`). - `value: T` is the value of this node (e.g. 1, 2, A, B, etc.) -- `parent: ThreadedBinaryTree?` is the parent of this node (if it exists) -- `left: ThreadedBinaryTree?` is the left child of this node (if it exists) -- `right: ThreadedBinaryTree?` is the right child of this node (if it exists) +- `parent: ThreadedBinaryTree?` is the parent of this node +- `left: ThreadedBinaryTree?` is the left child of this node +- `right: ThreadedBinaryTree?` is the right child of this node - `leftThread: ThreadedBinaryTree?` is the in-order predecessor of this node - `rightThread: ThreadedBinaryTree?` is the in-order successor of this node @@ -213,7 +214,6 @@ A backward traversal would be very similar, but you would replace `right`, `maximum()`, and `predecessor()`. - ## Insertion and deletion The quick in-order traversal that a threaded binary trees gives us comes at a @@ -288,12 +288,12 @@ understand two important properties of threaded binary trees: 2. For the leftmost node **m** in the `right` subtree of any node **n**, **m**'s `leftThread` is **n**. -Note how this property held true before the removal of **5**, as **4** was the -rightmost node in **5**'s `left` subtree. In order to maintain this property, -we must set **4**'s `rightThread` to **9**, as **4** is now the rightmost node -in **9**'s `left` subtree. To completely remove **5**, all we now have to do -is set **5**'s `parent`, `left`, `right`, `leftThread`, and `rightThread` to -`nil`. +Note how these properties held true before the removal of **5**, as **4** was +the rightmost node in **5**'s `left` subtree. In order to maintain this +property, we must set **4**'s `rightThread` to **9**, as **4** is now the +rightmost node in **9**'s `left` subtree. To completely remove **5**, all we +now have to do is set **5**'s `parent`, `left`, `right`, `leftThread`, and +`rightThread` to `nil`. How about we do something crazy? What would happen if we tried to remove **9**, the root node? This is the resulting tree: @@ -314,7 +314,7 @@ tree using the algorithms outlined above. This ensures that the edges in the **10**, as we just have to update the edges leaving **10**. Now all we have to do is fiddle with the threads in order to maintain the two properties outlined above. In this case, **12**'s `leftThread` is now **10**. Node **9** is no -longer needed, so we can finish teh removal process by setting all of its +longer needed, so we can finish the removal process by setting all of its variables to `nil`. In order to illustrate how to remove a node that has only a `right` child, @@ -326,8 +326,10 @@ The process to remove **12** is identical to the process we used to remove **5**, but mirrored. **5** had a `left` child, while **12** has a `right` child, but the core algorithm is the same. -That is a quick overview of how insertion and deletion work in threaded binary -trees. More detail can of course be found in +And that's it! This was just a quick overview of how insertion and deletion +work in threaded binary trees, but if you understood these examples, you should +be able to insert or remove any node from any tree you want. More detail can +of course be found in [the implementation](ThreadedBinaryTree.swift). From d13f9d078d9dec034d7b9f5abfbb426078cacfab Mon Sep 17 00:00:00 2001 From: Jayson Tung Date: Wed, 4 May 2016 16:39:36 -0400 Subject: [PATCH 0324/1679] Fix various typos in Threaded README --- Threaded Binary Tree/README.markdown | 39 ++++++++++++++-------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/Threaded Binary Tree/README.markdown b/Threaded Binary Tree/README.markdown index 048a1f23d..0c533ad63 100644 --- a/Threaded Binary Tree/README.markdown +++ b/Threaded Binary Tree/README.markdown @@ -17,10 +17,10 @@ The main motivation behind using a threaded binary tree over a simpler and smaller standard binary tree is to increase the speed of an in-order traversal of the tree. An in-order traversal of a binary tree visits the nodes in the order in which they are stored, which matches the underlying ordering of a -[binary search tree](../Binary Search Tree/). Thus threaded binary trees are -almost always binary search trees too. The idea is to visit all the left -children of a node first, then visit the node itself, and visit the left -children last. +[binary search tree](../Binary Search Tree/). This means most threaded binary +trees are also binary search trees. The idea is to visit all the left children +of a node first, then visit the node itself, and then visit the right children +last. An in-order traversal of any binary tree generally goes as follows (using Swift syntax): @@ -89,25 +89,24 @@ binary search tree: ![Partial](Images/Partial.png) The solid lines denote the links between parents and children, while the dotted -lines denote the "threads." The important thing to note here is how the -children and thread edges interact with each other. Every node besides the -root has one entering edge (from its parent), and two leaving edges: one to the -left and one to the right. The left leaving edge goes to the node's left child -if it exists, and to its in-order predecessor if it does not. The right -leaving edge goes to the node's right child if it exists, and to its in-order -successor if it does not. The exceptions are the left-most node and the -right-most node, which do not have a predecessor or successor, respectively. +lines denote the "threads." It is important to note how the children and +thread edges interact with each other. Every node besides the root has one +entering edge (from its parent), and two leaving edges: one to the left and one +to the right. The left leaving edge goes to the node's left child if it +exists, and to its in-order predecessor if it does not. The right leaving edge +goes to the node's right child if it exists, and to its in-order successor if +it does not. The exceptions are the left-most node and the right-most node, +which do not have a predecessor or successor, respectively. ## Representation -Before we go into detail about the methods that we can apply to threaded binary -trees, it might be a good idea to explain how we will be representing the tree. -The core of this data structure is the `ThreadedBinaryTree` -class. Each instance of this class represents a node with six member -variables: `value`, `parent`, `left`, `right`, `leftThread`, and -`rightThread`. Of all of these, only `value` is required. The other five are -Swift *optionals* (they may be `nil`). +Before we go into detail about the methods of a threaded binary tree, we should +first explain how the tree itself is represented. The core of this data +structure is the `ThreadedBinaryTree` class. Each instance of +this class represents a node with six member variables: `value`, `parent`, +`left`, `right`, `leftThread`, and `rightThread`. Of all of these, only +`value` is required. The other five are Swift *optionals* (they may be `nil`). - `value: T` is the value of this node (e.g. 1, 2, A, B, etc.) - `parent: ThreadedBinaryTree?` is the parent of this node - `left: ThreadedBinaryTree?` is the left child of this node @@ -185,7 +184,7 @@ func traverseInOrderBackward(visit: T -> Void) { } } ``` -Again, this a method of `ThreadedBinaryTree`, so we'd call it like +Again, this a method of `ThreadedBinaryTree`, so we'd call it via `node.traverseInorderForward(visitFunction)`. Note that we are able to specify a function that executes on each node as they are visited. This function can be anything you want, as long as it accepts `T` (the type of the values of the From 6644f8b4011617af2ec0188275f038634e4d68e3 Mon Sep 17 00:00:00 2001 From: Ashwin Date: Wed, 4 May 2016 17:05:00 -0400 Subject: [PATCH 0325/1679] added delete --- Red Black Trees/RBTree.swift | 228 ++++++++++++++++++++++++++--------- 1 file changed, 170 insertions(+), 58 deletions(-) diff --git a/Red Black Trees/RBTree.swift b/Red Black Trees/RBTree.swift index 4cb0c2fcb..dab7e1fd8 100644 --- a/Red Black Trees/RBTree.swift +++ b/Red Black Trees/RBTree.swift @@ -13,11 +13,14 @@ public class RBTNode{ } init(rootData: Int){ self.data = rootData - self.color = true //0is black 1 is red + self.color = true //0 is black 1 is red self.left = nil self.right = nil self.parent = nil } + deinit{ + print("Node: \(self.data) is bein deinitialized") + } public func grandparent()->RBTNode?{ if(self.parent === nil || self.parent.parent === nil){ return nil @@ -37,48 +40,9 @@ public class RBTNode{ return self.parent!.left! } } - public func replaceNode(n1: RBTNode, n2: RBTNode){ - var temp = n1.data - var temp_color = n1.color - n1.data = n2.data - n1.color = n2.color - n2.data = temp - n2.color = temp_color - } - public func minimum(var node: RBTNode)->RBTNode { - while node.left !== nil{ - node = node.left - } - return node - } - public func successor(var node: RBTNode) -> RBTNode? { - if node.right !== nil { - return minimum(node.right) - } - var successor = node.parent - while successor !== nil && node === successor.right { - node = successor - successor = successor.parent - } - return successor - } - public func predecessor(var node: RBTNode) -> RBTNode{ - if node.left !== nil { - return minimum(node.left) - } - var successor = node.parent - while successor !== nil && node === successor.left { - node = successor - successor = successor.parent - } - return successor - } - public func maximum(var rootNode: RBTNode) -> RBTNode{ - while rootNode.right !== nil { - rootNode = rootNode.right - } - return rootNode - } + + + } public class RBTree { @@ -189,16 +153,16 @@ private func insertCase3(inserted: RBTNode?){ } insertCase4(inserted) } -//THIS ONE MAY BE BROKEN!?!?!?!? + private func insertCase4(var inserted: RBTNode?){ if((inserted! === inserted!.parent!.right) && (inserted!.grandparent()!.left === inserted!.parent!)){ print("case 4") - rightRotate(inserted!.parent) + leftRotate(inserted!.parent) inserted! = inserted!.left } else if((inserted! === inserted!.parent!.left) && (inserted!.grandparent()!.right === inserted!.parent!)){ print("case 4") - leftRotate(inserted!.parent) + rightRotate(inserted!.parent) inserted! = inserted!.right } insertCase5(inserted) @@ -280,26 +244,174 @@ private func insertCase5(inserted: RBTNode?){ return } } + public func replaceNode(n1: RBTNode, n2: RBTNode){ + var temp = n1.data + var temp_color = n1.color + n1.data = n2.data + n1.color = n2.color + n2.data = temp + n2.color = temp_color + } + public func minimum(var node: RBTNode)->RBTNode { + while node.left !== nil{ + node = node.left + } + return node + } + public func successor(var node: RBTNode) -> RBTNode? { + if node.right !== nil { + return minimum(node.right) + } + var successor = node.parent + while successor !== nil && node === successor.right { + node = successor + successor = successor.parent + } + return successor + } + public func predecessor(var node: RBTNode) -> RBTNode{ + if node.left !== nil { + return minimum(node.left) + } + var successor = node.parent + while successor !== nil && node === successor.left { + node = successor + successor = successor.parent + } + return successor + } + public func maximum(var rootNode: RBTNode) -> RBTNode{ + while rootNode.right !== nil { + rootNode = rootNode.right + } + return rootNode + } + private func deletionFixup(x: RBTNode) {} + + public func delete(x: Int){ + let toDel = find(x) + deleteNode(toDel!) + } + private func deleteNode(var toDel: RBTNode?){ + print("DELETE CASE 0") + if(toDel!.left == nil && toDel!.right == nil && toDel!.color == true){ + print("IM IN HERE") + //DEINIT NOT BEING CALLED AGAIN? + toDel = nil + return + } + if(toDel!.left !== nil && toDel!.right !== nil){ + var pred = maximum(toDel!.left!) + toDel!.data = pred.data + toDel! = pred + } + var child: RBTNode? = nil + if(toDel!.right === nil){ + child = toDel!.left + } + else{ + child = toDel!.right + } + + if(toDel!.color == false){ + toDel!.color = child!.color + deleteCase1(toDel!) + } + if(child !== nil){ + replaceNode(toDel!, n2: child!) + if(toDel!.parent === nil && child !== nil){ + child!.color = false + } + } + print("This statement isnt actually deleting the object??? V") + toDel = nil + } + private func deleteCase1(var toDel: RBTNode?){ + print("DELETE CASE 1") + if(toDel?.parent === nil){ + return + } + else{ + deleteCase2(toDel) + } + } + private func deleteCase2(var toDel: RBTNode?){ + print("DELETE CASE 2") + var sibling = toDel!.sibling() + if(sibling?.color == true){ + toDel!.parent.color = true; + sibling?.color = false + if(toDel! === toDel!.parent.left){ + leftRotate(toDel!.parent) + } + else{ + rightRotate(toDel!.parent) + } + deleteCase3(toDel!) + } + } + private func deleteCase3(var toDel: RBTNode?){ + print("DELETE CASE 3") + if(toDel!.parent?.color == false && toDel!.sibling()?.color == false && toDel!.sibling()?.left!.color == false && toDel!.sibling()?.right!.color == false){ + toDel!.sibling()?.color = true + toDel!.parent?.color = false + } + else{ + deleteCase4(toDel) + } + } + private func deleteCase4(var toDel: RBTNode?){ + print("DELETE CASE 4") + if(toDel!.parent?.color == true && toDel!.sibling()?.color == false && toDel!.sibling()?.left!.color == false && toDel!.sibling()?.right!.color == false){ + toDel!.sibling()?.color = true + toDel!.parent.color = false + } + else{ + deleteCase5(toDel) + } + } + private func deleteCase5(var toDel:RBTNode?){ + print("DELETE CASE 5") + if(toDel! === toDel!.parent?.left && toDel!.sibling()?.color == false && toDel!.sibling()?.left.color == true && toDel!.sibling()?.right.color == false){ + toDel!.sibling()?.color = true + toDel!.sibling()?.left?.color = false + rightRotate(toDel!.sibling()!) + } + else if(toDel! === toDel!.parent?.right && toDel!.sibling()?.color == false && toDel!.sibling()?.left.color == false && toDel!.sibling()?.right.color == true){ + toDel!.sibling()?.color = true + toDel!.sibling()?.right?.color = false + leftRotate(toDel!.sibling()!) + } + } + private func deleteCase6(var toDel: RBTNode?){ + print("DELETE CASE 6") + let color = toDel!.sibling()?.color + toDel!.parent?.color = color! + toDel!.parent?.color = false + if(toDel! === toDel!.parent.left){ + toDel!.sibling()?.right?.color = false + leftRotate(toDel!.parent!) + } + else{ + toDel!.sibling()?.left?.color = false + rightRotate(toDel!.parent!) + } + } } + + var tree = RBTree(rootData: 8) -tree.insert(9) + tree.insert(6) -tree.insert(5) -tree.insert(4) -tree.insert(40) -tree.insert(400) -tree.insert(430) -var t = tree.root! -var min = t.minimum(t) -print("MIN: \(min.data)") -var x = tree.root!.left -tree.inOrder() -t.replaceNode(t,n2:x) +tree.delete(6) tree.inOrder() +print("_______") + + //print("_________________________") //let x = tree.root! From ead1fc37b587c7b2021750c6fcc4bf1e8e55b8fa Mon Sep 17 00:00:00 2001 From: Christian Encarnacion Date: Wed, 4 May 2016 20:36:43 -0400 Subject: [PATCH 0326/1679] Update ReadMe.md --- Radix-Sort/ReadMe.md | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/Radix-Sort/ReadMe.md b/Radix-Sort/ReadMe.md index 27dcf6eb3..5bdb931ca 100644 --- a/Radix-Sort/ReadMe.md +++ b/Radix-Sort/ReadMe.md @@ -1,6 +1,30 @@ # Radix Sort -Under Construction. +Radix sort is a sorting algorithm that takes as input an array of integers and uses a sorting subroutine( that is often another efficient sorting algorith) to sort the integers by their radix, or rather their digit. Counting Sort, and Bucket Sort are often times used as the subroutine for Radix Sort. + +##Example + +* Input Array: [170, 45, 75, 90, 802, 24, 2, 66] +* Output Array (Sorted): [2, 24, 45, 66, 75, 90, 170, 802] + +###Step 1: +The first step in this algorithm is to define the digit or rather the "base" or radix that we will use to sort. +For this example we will let radix = 10, since the integers we are working with in the example are of base 10. + +###Step 2: +The next step is to simply iterate n times (where n is the number of digits in the largest integer in the input array), and upon each iteration perform a sorting subroutine on the current digit in question. + +###Algorithm in Action + +Let's take a look at our example input array. + +The largest integer in our array is 802, and it has three digits (ones, tens, hundreds). So our algorithm will iterate three times whilst performing some sorting algorithm on the digits of each integer. + +* Iteration 1: 170, 90, 802, 2, 24, 45, 75, 66 +* Iteration 2: 802, 2, 24, 45, 66, 170, 75, 90 +* Iteration 3: 2, 24, 45, 66, 75, 90, 170, 802 + + See also [Wikipedia](https://en.wikipedia.org/wiki/Radix_Sort). From 1a07781dfe4a40fa0523202fd5dac0171ac81e48 Mon Sep 17 00:00:00 2001 From: Thukor Date: Thu, 5 May 2016 11:00:15 -0400 Subject: [PATCH 0327/1679] Provided a temporary fix for insert function, finished radix sort readme, commented Trie and Node classes. --- Radix-Sort/radixSort.swift | 29 +-- Trie/.build/debug/Trie.a | Bin 125236 -> 139282 bytes Trie/.build/debug/Trie.o/Trie/Queue.d | 6 +- Trie/.build/debug/Trie.o/Trie/Queue.swiftdeps | 16 +- .../Trie.o/Trie/Queue~partial.swiftmodule | Bin 11788 -> 11608 bytes .../.build/debug/Trie.o/Trie/master.swiftdeps | 7 +- .../debug/Trie.o/Trie/output-file-map.json | 6 - Trie/.build/debug/Trie.o/Trie/trie.d | 6 +- Trie/.build/debug/Trie.o/Trie/trie.swiftdeps | 34 ++-- .../Trie.o/Trie/trie~partial.swiftmodule | Bin 66240 -> 66060 bytes Trie/.build/debug/Trie.o/build.db | Bin 15360 -> 15360 bytes Trie/.build/debug/Trie.o/llbuild.yaml | 20 +- .../.build/debug/Trie.o/sources/Queue.swift.o | Bin 23440 -> 23408 bytes Trie/.build/debug/Trie.o/sources/trie.swift.o | Bin 107904 -> 107872 bytes Trie/.build/debug/Trie.swiftmodule | Bin 21236 -> 20828 bytes Trie/sources/main.swift | 35 ---- Trie/sources/trie.swift | 190 +++++++++++++++++- Trie/tests/LinuxMain.swift | 8 + Trie/tests/Trie/TrieTest.swift | 26 +++ 19 files changed, 276 insertions(+), 107 deletions(-) delete mode 100644 Trie/sources/main.swift create mode 100644 Trie/tests/LinuxMain.swift create mode 100644 Trie/tests/Trie/TrieTest.swift diff --git a/Radix-Sort/radixSort.swift b/Radix-Sort/radixSort.swift index 47bdb0fd1..64166e88a 100644 --- a/Radix-Sort/radixSort.swift +++ b/Radix-Sort/radixSort.swift @@ -1,14 +1,23 @@ +/* + + Sorting Algorithm that sorts an input array of integers digit by digit. + +*/ + + func radixSort(inout arr: [Int] ) { - let radix = 10 + + let radix = 10 //Here we define our radix to be 10 var done = false var index: Int - var digit = 1 + var digit = 1 //Which digit are we on? + - while !done { - done = true + while !done { //While our sorting is not completed + done = true //Assume it is done for now - var buckets: [[Int]] = [] + var buckets: [[Int]] = [] //Our sorting subroutine is bucket sort, so let us predefine our buckets for _ in 1...radix { buckets.append([]) @@ -16,9 +25,9 @@ func radixSort(inout arr: [Int] ) { for number in arr { - index = number / digit + index = number / digit //Which bucket will we access? buckets[index % radix].append(number) - if done && index > 0 { + if done && index > 0 { //If we arent done, continue to finish, otherwise we are done done = false } } @@ -33,10 +42,6 @@ func radixSort(inout arr: [Int] ) { } } - digit *= radix + digit *= radix //Move to the next digit } } - -var a: [Int] = [0, 69, 28, 14, 32, 1, 1, 1111, 1111111, 55, 123, 236626456256, 9393, 23, 66] -radixSort(&a) -print(a) diff --git a/Trie/.build/debug/Trie.a b/Trie/.build/debug/Trie.a index 6683c390836e5dea9352d1ab823aa4057f36435f..8a6855460ced86d852718c4d574c11b94b8e9168 100644 GIT binary patch literal 139282 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 literal 125236 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 z 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" -- !private "Double" -- !private "&&" - !private "+=" +- !private ">" +- !private "/" +- "FloatLiteralType" depends-member: - !private ["Ps16AbsoluteValuable", "init"] - ["Sa", "Generator"] diff --git a/Trie/.build/debug/Trie.o/Trie/Queue~partial.swiftmodule b/Trie/.build/debug/Trie.o/Trie/Queue~partial.swiftmodule index 267c48a56b4a095c3a6463ff17bcb74be262f696..1594ec4d238b3a285e3e18a9dbfd52390d125f0e 100644 GIT binary patch delta 404 zcmWmAO-Per0KoD8^Z3a2zFVoAABTarS%muLqA58^csib5WOE>RTGK-Am+^gH|)$M!}`QvqvELDUN^g_%IQ zNdi7sWU2Szc|lt}cnWR7P)*dP{5qJI@@BGp?b3gH!5UJ0k4X-j1-~DouiRxk5T;aY z!2Q)tDyIk~C95HUYYD=AIK2@{-9Gjb7O7{7i&@F9cERup#0NOK-%90%AKqDTpwKzV zbW*Um4myqb9OLJ)A7{4a`6JB2&K?eeIwG8=w_z{J_J|4_l zbbnFgCMD*&FmKl|_8`vFR*uH~Y?m!I4;3F~CA&R>Z|i7pn##u*nFBxde=I6h#m2nk z%`IW7FEFkQo#sLu$J2;*+ia;?PR^DUZwsmpJjtN%#W9_Y{A;mU^%jOZ27)1*VqGnf Xyd;?tbiKq}&7zmjoWb&^jB{Yk;Sh1kcL7XhQWfY3WbY6|6 z3bRFXPA$wESBlZ;Y}&MpVkQ?&W=k{bS<6Vdtbd8LL3j0Qu=CQ`O?UfmlzL#MWMp+! zPtBCl5Em|^RIt>nnVin5M&5Pmt}iClcY;eoJU?Dv==|edT-Ig6hXsor5+BQG%fnp$ z(nC%7Xq6Q_V9B!2r%&OMV4=@yIaR`yRUX`WY!JtbdZp>Vkzsl3jQJ+oSNf z4-$UPy-|4kLuM^6=o*mhYmcz4ah#L=G~W67+)x;3%IsVh" -- !private "Array" +- !private "!==" +- !private "-=" +- "Bool" +- !private "+" +- "String" depends-member: - !private ["Vs12AnyGenerator", "Element"] - !private ["Ps9AnyObject", "Array"] diff --git a/Trie/.build/debug/Trie.o/Trie/trie~partial.swiftmodule b/Trie/.build/debug/Trie.o/Trie/trie~partial.swiftmodule index f9e33b421a684ed26ac2066848785167312f0845..e7406d6766930d93bf2df20bf71744e783feb822 100644 GIT binary patch delta 2355 zcmWmEdstL;9>?+bZ+>z{Wo9IAfQ&gym}sty#AR@;PKKqetEAS0w&G~0n1CZ$k*&_J zyc=6%Xlh7J+T)tf)>0t4F49TVP*KNnjg)LOylnNf(`9$P;qGt$JI{GN-}61c%javY z>{hj+TU~KVkN5ImumcjS%TgxwvjM&BX`wMM|NjYwCO~}kQ1_j3a8K%YxC^(;UNs8U z`vJ^TgD|%yFubTccaJj|KSWZqQ84Kkp22eo-=9rjTN;%Mdh^D8J-EKB8}2nWHF>Ns zU)+xO+GA|KolceN%Vo1CEuJ{FHe|C3#|eKaE=~@f5<=zHoK^tSU+!X;ppI) zuj1(X!Dj7#UZ{Wnjc8gCW?}}uEr~>q$Mf=)IHvw$Qw2*zbm4wNpA@lqP6k=K6KOgh zPtnhD>SULV>Y%VPE!5L~OrMttgOb>(cc8qF!H}Mk{FTDocYxUHS(vB2cvdD+@Q{O& zUmHO>`%Ct`BGhw-F&})2!jmIu|2Bzj%N)2(L*;s;@`gk>wH4LBn099-ojsD-ywbs- zhYbGuD{1~15-e|}?%`r$gEML9pA1zFraWxmNt0IE>%wv$Ayi$Ae?lgI7?Mo!1_vu2 zH7Fe%l-5!03y+YnznD;QChfV&%zfLzhyp{I>5}XXBARxTaN-}OXl*s4h~N? z@ZTfV$&JDqcns@}IYiqtDJf58!#)SCGYpzCr0UuvtgJSDbaUaJd$DShX*=cM_fH$- zXNuI|t_T1~*1ab@?sf-*Xa-61)jnY)u%zW~Y;iHHI2L zRx)wBu+E(#)@weV+APu^AHbOrPKw?%SoJ%pF76QKpFT&On~!-ji)+gU&@slzvTX)^ zCre&^PY~?!ccL{<6P}jM&W{GLc!rasbp~bAq#E_UFuy(ns~6xsnT_{{0Zf0<$z;pm zmS392hr;@z9dlJF=~HuvW~XrbEhl?U8A{EU)^`oUzws=A>19OgHP1-lYMqn7mxf9$ zlV+q*s8`Mr3`ffF#&U=(N#S6#{`aWC`vIvo?iDQVAevuJ!LVGCw&?QXPGVOKY8Oju z`99&F^%ViDoSk!WsoI@FYKN1Le=t~1HvLaOZtgt_PfswF^pzK=DzZkh(VsOn`We~o0; zLE-uBMGCSPkrWR4I5^o&^Dq}r_P4Y76{-GnNT@r$AzZx(^Q4c^0yh=8F6O!IYTc{S z3VbR&C%%DyE+Xp6p1$vY}VtI!t^zvJVhk9 zGiZ1%k-4q$Oz(_S=1)Nz!(I?pZ4(8L712H{gFrZugOPYT{t?IMf7v*sli#!-^3G;AXI~Ow=O?H?`k~Ov=@CgRNp#?M8d!E|I#&pD-~kHy>9O;= z7vG~vB&0hi?Qf_P@zQjy5}x2)EqFefMd4X5`Q=G;&vW1!Xs9<`(kfalJbPQ<_AJ8P zM&enczdqK%@HB(G-qISsR+udZiIvXA${k6=TYBbAar;Ytv8M?msD98@HWomnYN*y?1`2}4bsC)J1bLS6h4Pgf~dgE_dz zq_FE9C$}PoT3;f~=?x-0;VhA{WkFhZ5(p-K>crIMT|K1`(9X=dO-K0L?V&5P;-9l3JYZa<*C!Ssv&@&I;DmO*> zE|#X+)tvRxJlraxrJWS~rh+6-9{IubZertfeA4W!dtIu+BZ9_GLNhAxjm*PS<7W6o z7sW&Dd|55wsIYom!dhEF!6SM4+PZN}adCR6ojW#4wjLFfTq4j|LEY>;TI=1opL8*7 zgk4o_l0=S)==YZ>xT%|~JlYPraUCvpu`biDrfrd`v9138Tgfu$Xmj(#To+UBwX6MG zq;<7T_+Pk;_km|<59i@H<>pL@i|Q=9n(?Nze8+|V9nDiT@6vomS1)k!dA413XZkj zNtajX=6QDYmF7y#4{F}7`7_Pm>gLbt=A-OtX|1$cHP6?)M{`FW5nJbhn0~e5%I;BO GmF<5$NBQ;u delta 2535 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 RzQ>+>Qfv+hV{=H1{|k-3N}m7# diff --git a/Trie/.build/debug/Trie.o/llbuild.yaml b/Trie/.build/debug/Trie.o/llbuild.yaml index 8607eca74..7f699a487 100644 --- a/Trie/.build/debug/Trie.o/llbuild.yaml +++ b/Trie/.build/debug/Trie.o/llbuild.yaml @@ -11,19 +11,19 @@ commands: : tool: swift-compiler executable: "/home/christian/swiftv2/usr/bin/swiftc" - inputs: ["/home/christian/Desktop/swift-algorithm-club/Trie/sources/main.swift","/home/christian/Desktop/swift-algorithm-club/Trie/sources/trie.swift","/home/christian/Desktop/swift-algorithm-club/Trie/sources/Queue.swift"] - outputs: ["","/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.swiftmodule","/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/sources/main.swift.o","/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/sources/trie.swift.o","/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/sources/Queue.swift.o"] + inputs: ["/home/christian/Desktop/swift-algorithm-club/Trie/sources/trie.swift","/home/christian/Desktop/swift-algorithm-club/Trie/sources/Queue.swift"] + outputs: ["","/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.swiftmodule","/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/sources/trie.swift.o","/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/sources/Queue.swift.o"] module-name: "Trie" module-output-path: "/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.swiftmodule" - is-library: false - sources: ["/home/christian/Desktop/swift-algorithm-club/Trie/sources/main.swift","/home/christian/Desktop/swift-algorithm-club/Trie/sources/trie.swift","/home/christian/Desktop/swift-algorithm-club/Trie/sources/Queue.swift"] - objects: ["/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/sources/main.swift.o","/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/sources/trie.swift.o","/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/sources/Queue.swift.o"] + is-library: true + sources: ["/home/christian/Desktop/swift-algorithm-club/Trie/sources/trie.swift","/home/christian/Desktop/swift-algorithm-club/Trie/sources/Queue.swift"] + objects: ["/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/sources/trie.swift.o","/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/sources/Queue.swift.o"] import-paths: ["/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug"] temps-path: "/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/Trie" - other-args: ["-j8","-Onone","-g","-I","/usr/local/include"] + other-args: ["-j8","-Onone","-g","-enable-testing","-I","/usr/local/include"] : tool: shell - inputs: ["","/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/sources/main.swift.o","/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/sources/trie.swift.o","/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/sources/Queue.swift.o"] - outputs: ["","/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie"] - args: ["/home/christian/swiftv2/usr/bin/swiftc","-o","/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie","/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/sources/main.swift.o","/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/sources/trie.swift.o","/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/sources/Queue.swift.o","-g","-L/usr/local/lib"] - description: "Linking Executable: .build/debug/Trie" + inputs: ["","/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/sources/trie.swift.o","/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/sources/Queue.swift.o"] + outputs: ["","/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.a"] + args: ["/bin/sh","-c","rm -f '/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.a'; ar cr '/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.a' '/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/sources/trie.swift.o' '/home/christian/Desktop/swift-algorithm-club/Trie/.build/debug/Trie.o/sources/Queue.swift.o'"] + description: "Linking Library: .build/debug/Trie.a" diff --git a/Trie/.build/debug/Trie.o/sources/Queue.swift.o b/Trie/.build/debug/Trie.o/sources/Queue.swift.o index efac8c7a3782cff0aaa917c7375533ce4bf89c97..068c988f70a207bd47b06b045f22a76272695d32 100644 GIT binary patch delta 1714 zcmZ{kZAepL6vy}6Y})(G*6oTxmZ4iH6oFZ}>niVc`%*z=E=X=5bwkAIiXvhfg%$+K zzYl!~MS@T%Fom)ROu}9$f~XG>6dFN|=w(o#Mc9)&H}O=1oy&f||8t&acjxZh4e{l= zI9DKgulep}VeO*N^K0s?eYG`(v6{x1UAG^(-jkkstD&)`&}uBKwf8kx4M+Pgc@Hh< z_pWSp3s-;ps#_kdGtD*mTARAKX3MKvzAq!XQB_9LaAspse1t;VS!kU2PR3(1Q(!OS zNy^)dJALZ^&DXeMOtjDj#~F7vXhk%vqN%h%bEl^w?JSv#p;A=~&r0Fj%=(cmHMK%o z`-)iu+XGW;e=zGubHLQL(b^o5($0OY#i(3+fc7n6HjGSN6@K`1Q^XL}RqZ_WIr3Ms zb252TChH-}OzkoyAF||KSY=bEeaEaHZDnTY0jjflb?Lo;FQ`|bWNz`}Av`JRDDxgqAFvs{fkBlBp+^b=3eh&^ZAnT)rLJAFPdzJMm|GvnSAN3oHq z*_0V$nL1d8szu1oqZ2t3(1kW>uaI5BYy?Aw8vj5xpV_a(ix_`Fd;{aJh#QQ%e?Q{# z6=r;1ilfrZ{BwSbWh^wCs%BB=!_0QznzS8cPcYkuQEB_go@I6rnH6eikn9C!onNqv z@d3(TWqcUX3U$^n*#U?ORZf+x!TT)vlQNJ0!=Evp1rbuUEV_rUne}0{v_7)mn7s%~ zTIaiXXlG|O0%((V9sN6GGrJW-AyrAH;bo{Odp&KinT0;O`Kr6Ji*cv2KvW}9sVkqB!oNEpnqcqNMG)PxZbL%W zD124A=!IRSD`P9rQx%Y{6Y@hcZ?Z*Mq(B+V!@)>E8405&^1DYOqKgdp_UQ7#w)f=! E0{u+*EC2ui delta 1703 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 delta 6335 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 diff --git a/Trie/.build/debug/Trie.swiftmodule b/Trie/.build/debug/Trie.swiftmodule index e387c6b3e3b7fafc2d6e5435918866b17cfd6302..078d7a6e1f4157ce427046619f65d62ae669b16e 100644 GIT binary patch delta 7588 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 delta 8357 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 JOR_iq{0F_>A6ozb diff --git a/Trie/sources/main.swift b/Trie/sources/main.swift deleted file mode 100644 index 8f95afdf7..000000000 --- a/Trie/sources/main.swift +++ /dev/null @@ -1,35 +0,0 @@ - -print("tests") - - -var T: Trie = Trie() -T.insert("Hello") -T.insert("Hi") -T.insert("Hey") -T.insert("Hallo") -T.insert("Henry") -T.insert("YELLO") -var U: Trie = Trie(wordList: Set(["Hey", "HO", "hello", "yolo"])) -var V: Trie = T.merge(U) -//T.printTrie() -//U.printTrie() -//V.printTrie() -print(V.getWords()) -V.removeAll() -//V.printTrie() -/*T.insert("Hello") -T.insert("Hey") -T.insert("YOLO") -T.insert("Him") -assert(T.count() == 4, "Count function failed") -assert(T.contains("Hey") == true) -assert(T.contains("Hello") == true) -print("trying remove") -T.remove("Him") -assert(T.count() == 3) -assert(T.contains("Him") == false, "Test failed") -assert(T.wordList.count == 3)*/ - -//T.printTrie() -//print(T.find("")) -print(T.findPrefix("H")) diff --git a/Trie/sources/trie.swift b/Trie/sources/trie.swift index 092b497dc..b3a8fb4f5 100644 --- a/Trie/sources/trie.swift +++ b/Trie/sources/trie.swift @@ -1,3 +1,16 @@ +/* + A Trie (Pre-fix Tree) + + Some of the functionality of the trie makes use of the Queue implementation for this project. + + + Every node in the Trie stores a bit of information pertainining to what it references: + -Character (letter of an inserted word) + -Parent (Letter that comes before the current letter in some word) + -Children (Words that have more letters than available in the prefix) + -isAWord (Does the current letter mark the end of a known inserted word?) + -visited (Mainly for the findPrefix() function) +*/ public class Node { private var character: String? private var parent: Node? @@ -13,58 +26,135 @@ public class Node { self.visited = false } - //Easier getter function, probably will make it more swift like + /* + Function Name: char() + Input: N/A + Output: String + Functionality: Returns the associated value of the node + */ func char() -> String { return self.character! } - func update(c: String?) -> Void { + /* + Function Name: update + Input: String + Output: N/A + Functionality: Updates the associated value of the node + */ + func update(c: String?) { self.character = c } + /* + Function Name: isLeaf + Input: N/A + Output: Bool + Functionality: Returns true if the node is a leaf node, false otherwise + */ func isLeaf() -> Bool{ return self.children.count == 0 } - //For Testing purposes + + /* + Function Name: getParent + Input: N/A + Output: Node + Functionality: Returns the parent node of the current node + */ func getParent() -> Node { return parent! } - func setParent(node: Node?) -> Void { + /* + Function Name: setParent + Input: Node + Output: N/A + Functionality: Changes the parent of the current node to the passed node + */ + + func setParent(node: Node?) { self.parent = node } + /* + Function Name: getChildAt + Input: String + Output: Node + Functionality: returns the child node that holds the specific passed letter + */ func getChildAt(s: String) -> Node { return self.children[s]! } - //Is this node marked as the end of a word? + + /* + Function Name: isValidWord + Input: N/A + Output: Bool + Functionality: Returns whether or not the current node marks the end of a valid word + */ func isValidWord() -> Bool{ return self.isAWord } - //Setters - func isWord() -> Void { + /* + Function Name: isWord + Input: N/A + Output: N/A + Functionality: the current node is indeed a word + */ + func isWord() { self.isAWord = true } - func isNotWord() -> Void { + /* + Function Name: isNotWord + Input: N/A + Output: N/A + Functionality: marks the current node as not a word + */ + func isNotWord() { self.isAWord = false } + /* + Function Name: isRoot + Input: N/A + Output: Bool + Functionality: Returns whether or not the current node is the root of the trie + */ func isRoot() -> Bool { return self.character == "" } + /* + Function Name: numChildren + Input: N/A + Output: Int + Functionality: Returns the number of immediate letters that follow the current node + */ func numChildren() -> Int { return self.children.count } + /* + Function Name: getChildren + Input: N/A + Output: [String: Node] + Functionality: Returns the letters that immediately follow the current node's value for possible word segments that follow + */ func getChildren() -> [String: Node] { return self.children } - func printNode(var indent: String, leaf: Bool) -> Void { + /* + Function Name: printNode + Input: String, Bool + Output: N/A + Functionality: prints to the console a string representation of the current node in the trie + */ + func printNode(var indent: String, leaf: Bool) { print(indent, terminator: "") if(leaf) { @@ -88,6 +178,13 @@ public class Node { } + +/* + The Trie class has the following attributes: + -root (the root of the trie) + -wordList (the words that currently exist in the trie) + -wordCount (the number of words in the trie) +*/ public class Trie { private var root: Node private var wordList: [String] @@ -108,11 +205,23 @@ public class Trie { } } + /* + Function Name: merge + Input: Trie + Output: Trie + Functionality: Merges two tries into one and returns the merged trie + */ func merge(other: Trie) -> Trie{ let newWordList = Set(self.getWords() + other.getWords()) return Trie(wordList: newWordList) } + /* + Function Name: find + Input: String + Output: (Node?, Bool) + Functionality: Looks for a specific key and returns a tuple that has a reference to the node(if found) and true/false depending on if it was found + */ func find(key: String) -> (node: Node?, found: Bool) { var currentNode = self.root @@ -126,22 +235,52 @@ public class Trie { return(currentNode, currentNode.isValidWord()) } + /* + Function Name: isEmpty + Input: N/A + Output: Bool + Functionality: returns true if the trie is empty, false otherwise + */ func isEmpty() -> Bool { return wordCount == 0 } + /* + Function Name: count + Input: N/A + Output: Int + Functionality: returns the number of words in the trie + */ func count() -> Int { return wordCount } + /* + Function Name: getWords + Input: N/A + Output: [String] + Functionality: returns the list of words that exist in the trie + */ func getWords() -> [String] { return wordList } + /* + Function Name: contains + Input: String + Output: Bool + Functionality: returns true if the tries has the word passed, false otherwise + */ func contains(w: String) -> Bool { return find(w.lowercaseString).found } + /* + Function Name: isPrefix + Input: String + Output: (Node?, Bool) + Functionality: returns a tuple containing a reference to the final node in the prefix (if it exists) and true/false depending on whether or not the prefix exists in the trie + */ func isPrefix(p: String) -> (node: Node?, found: Bool) { let prefixP = p.lowercaseString @@ -162,8 +301,15 @@ public class Trie { return (nil, false) } + /* + Function Name: insert + Input: String + Output: (String, Bool) + Functionality: Inserts a word int othe trie. Returns a tuple containing the word attempted to be added, and true/false depending on whether or not the insertion was successful + */ func insert(w: String) -> (word: String, inserted: Bool) { + print(w) let word = w.lowercaseString var currentNode = self.root var length = word.characters.count @@ -182,6 +328,7 @@ public class Trie { c = Array(word.characters)[index] } + print(length) let remainingChars = String(word.characters.suffix(length)) for c in remainingChars.characters { currentNode.children[String(c)] = Node(c: String(c), p: currentNode) @@ -194,6 +341,12 @@ public class Trie { return (w, true) } + /* + Function Name: remove + Input: String + Output: (String, Bool) + Functionality: Removes the specified key from the trie if it exists, returns tuple containing the word attempted to be removed and true/false if the removal was succesful + */ func remove(w: String) -> (word: String, removed: Bool){ let word = w.lowercaseString @@ -211,6 +364,7 @@ public class Trie { } else { var character = currentNode.char() while(currentNode.numChildren() == 0 && !currentNode.isRoot()) { + print("I make it here") currentNode = currentNode.getParent() currentNode.children[character]!.setParent(nil) currentNode.children[character]!.update(nil) @@ -232,6 +386,12 @@ public class Trie { return (w, true) } + /* + Function Name: findPrefix + Input: String + Output: [String] + Functionality: returns a list containing all words in the trie that have the specified prefix + */ func findPrefix(p: String) -> [String] { if !self.isPrefix(p).found { @@ -270,6 +430,12 @@ public class Trie { } + /* + Function Name: removeAll + Input: N/A + Output: N/A + Functionality: removes all nodes in the trie using remove as a subroutine + */ func removeAll() { for word in wordList { self.remove(word) @@ -278,6 +444,12 @@ public class Trie { } + /* + Function Name: printTrie + Input: N/A + Output: N/A + Functionality: prints all the nodes of the trie to console in a nice and easy to understand format + */ func printTrie() { self.root.printNode("", leaf: true) } diff --git a/Trie/tests/LinuxMain.swift b/Trie/tests/LinuxMain.swift new file mode 100644 index 000000000..83504f1dd --- /dev/null +++ b/Trie/tests/LinuxMain.swift @@ -0,0 +1,8 @@ + + +import XCTest +@testable import TrieTestSuite + +XCTMain([ + testCase(TrieTests.allTests) +]) diff --git a/Trie/tests/Trie/TrieTest.swift b/Trie/tests/Trie/TrieTest.swift new file mode 100644 index 000000000..8f49d1196 --- /dev/null +++ b/Trie/tests/Trie/TrieTest.swift @@ -0,0 +1,26 @@ +import XCTest +@testable import Trie + +class TrieTests: XCTestCase { + var trie : Trie! + + override func setUp() { + super.setUp() + trie = Trie() + } + + func testInsert() { + + var T: Trie = Trie() + var result = T.insert("Test").inserted + XCTAssertEqual(result, true) + } +} + +extension CalculatorTests { + static var allTests : [(String, CalculatorTests -> () throws -> Void)] { + return [ + ("Testing Insert...", testInsert) + ] + } +} From 7926986b5618bff7b6b289bb858e019cfe96009d Mon Sep 17 00:00:00 2001 From: Thukor Date: Thu, 5 May 2016 11:04:58 -0400 Subject: [PATCH 0328/1679] I realized that I didnt actually push my changes...... --- Trie/sources/trie.swift | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/Trie/sources/trie.swift b/Trie/sources/trie.swift index b3a8fb4f5..8e836fa1a 100644 --- a/Trie/sources/trie.swift +++ b/Trie/sources/trie.swift @@ -1,3 +1,4 @@ + /* A Trie (Pre-fix Tree) @@ -325,10 +326,17 @@ public class Trie { currentNode = child length -= 1 index += 1 + + if(length == 0) { + currentNode.isWord() + wordList.append(w) + wordCount += 1 + return (w, true) + } + c = Array(word.characters)[index] } - print(length) let remainingChars = String(word.characters.suffix(length)) for c in remainingChars.characters { currentNode.children[String(c)] = Node(c: String(c), p: currentNode) @@ -341,6 +349,23 @@ public class Trie { return (w, true) } + /* + Function Name: insertWords + Input: [String] + Output: ([String], Bool) + Functionality: attempts to insert all words from input array. returns a tuple containing the input array and true if some of the words were succesffuly added, false if none were added + */ + + func insertWords(wordList: [String]) -> (wordList: [String], bool: inserted){ + + var successful: Bool = false + for word in wordList { + succesful |= self.insert(word).inserted + } + + return(wordList, succesful) + } + /* Function Name: remove Input: String @@ -364,7 +389,6 @@ public class Trie { } else { var character = currentNode.char() while(currentNode.numChildren() == 0 && !currentNode.isRoot()) { - print("I make it here") currentNode = currentNode.getParent() currentNode.children[character]!.setParent(nil) currentNode.children[character]!.update(nil) @@ -440,7 +464,6 @@ public class Trie { for word in wordList { self.remove(word) } - self.root.update(nil) } From 9416c9091d1b8883078e5efc5b2b100a377340cc Mon Sep 17 00:00:00 2001 From: Christian Encarnacion Date: Thu, 5 May 2016 11:20:41 -0400 Subject: [PATCH 0329/1679] Update README.markdown --- README.markdown | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/README.markdown b/README.markdown index a6b492154..bbc10fb8d 100644 --- a/README.markdown +++ b/README.markdown @@ -72,9 +72,9 @@ Fast sorts: Special-purpose sorts: -- Bucket Sort -- [Counting Sort](Counting-Sort/) :construction: -- [Radix Sort](Radix-Sort/) :construction: +- [Bucket Sort](Bucket Sort/) :construction: +- [Counting Sort](Counting Sort/) +- Radix Sort - [Topological Sort](Topological Sort/) Bad sorting algorithms (don't use these!): @@ -143,14 +143,14 @@ Most of the time using just the built-in `Array`, `Dictionary`, and `Set` types - [Binary Tree](Binary Tree/). A tree where each node has at most two children. - [Binary Search Tree (BST)](Binary Search Tree/). A binary tree that orders its nodes in a way that allows for fast queries. - [AVL Tree](AVL Tree/). A binary search tree that balances itself using rotations. :construction: -- [Red-Black Tree](Red Black Trees/) :construction: +- Red-Black Tree - Splay Tree -- [Threaded Binary Tree](Threaded\ Binary\ Tree/) :construction: +- Threaded Binary Tree - [Segment Tree](Segment Tree/). Can quickly compute a function over a portion of an array. - kd-Tree - [Heap](Heap/). A binary tree stored in an array, so it doesn't use pointers. Makes a great priority queue. - Fibonacci Heap -- [Trie](Trie/) :construction: +- Trie - [B-Tree](B Tree/) :construction: ### Hashing @@ -163,7 +163,7 @@ Most of the time using just the built-in `Array`, `Dictionary`, and `Set` types - [Bloom Filter](Bloom Filter/). A constant-memory data structure that probabilistically tests whether an element is in a set. - [Hash Set](Hash Set/). A set implemented using a hash table. - Multiset -- Ordered Set +- [Ordered Set](Ordered Set/). A set where the order of items matters. ### Graphs @@ -197,6 +197,7 @@ The following books are available for free online: - [Algorithms, Etc.](http://jeffe.cs.illinois.edu/teaching/algorithms/) by Erickson - [Algorithms + Data Structures = Programs](http://www.ethoberon.ethz.ch/WirthPubl/AD.pdf) by Wirth - Algorithms and Data Structures: The Basic Toolbox by Mehlhorn and Sanders +- [Wikibooks: Algorithms and Implementations](https://en.wikibooks.org/wiki/Algorithm_Implementation) Other algorithm repositories: From 1fb66f8dfa334c8b50599bda46a7420146b47e80 Mon Sep 17 00:00:00 2001 From: Christian Encarnacion Date: Thu, 5 May 2016 11:36:39 -0400 Subject: [PATCH 0330/1679] Update README.markdown --- README.markdown | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.markdown b/README.markdown index bbc10fb8d..4bfe4e562 100644 --- a/README.markdown +++ b/README.markdown @@ -74,7 +74,7 @@ Special-purpose sorts: - [Bucket Sort](Bucket Sort/) :construction: - [Counting Sort](Counting Sort/) -- Radix Sort +- Radix Sort :construction - [Topological Sort](Topological Sort/) Bad sorting algorithms (don't use these!): @@ -143,15 +143,16 @@ Most of the time using just the built-in `Array`, `Dictionary`, and `Set` types - [Binary Tree](Binary Tree/). A tree where each node has at most two children. - [Binary Search Tree (BST)](Binary Search Tree/). A binary tree that orders its nodes in a way that allows for fast queries. - [AVL Tree](AVL Tree/). A binary search tree that balances itself using rotations. :construction: -- Red-Black Tree +- Red-Black Tree :construction: - Splay Tree - Threaded Binary Tree - [Segment Tree](Segment Tree/). Can quickly compute a function over a portion of an array. - kd-Tree - [Heap](Heap/). A binary tree stored in an array, so it doesn't use pointers. Makes a great priority queue. - Fibonacci Heap -- Trie +- Trie :construction: - [B-Tree](B Tree/) :construction: +- Radix Tree :construction: ### Hashing From d0a7b1971f57b371afb9cba50e5c6f1f4c6b3d41 Mon Sep 17 00:00:00 2001 From: Christian Encarnacion Date: Thu, 5 May 2016 11:37:38 -0400 Subject: [PATCH 0331/1679] Update README.markdown --- README.markdown | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/README.markdown b/README.markdown index 4bfe4e562..bbc10fb8d 100644 --- a/README.markdown +++ b/README.markdown @@ -74,7 +74,7 @@ Special-purpose sorts: - [Bucket Sort](Bucket Sort/) :construction: - [Counting Sort](Counting Sort/) -- Radix Sort :construction +- Radix Sort - [Topological Sort](Topological Sort/) Bad sorting algorithms (don't use these!): @@ -143,16 +143,15 @@ Most of the time using just the built-in `Array`, `Dictionary`, and `Set` types - [Binary Tree](Binary Tree/). A tree where each node has at most two children. - [Binary Search Tree (BST)](Binary Search Tree/). A binary tree that orders its nodes in a way that allows for fast queries. - [AVL Tree](AVL Tree/). A binary search tree that balances itself using rotations. :construction: -- Red-Black Tree :construction: +- Red-Black Tree - Splay Tree - Threaded Binary Tree - [Segment Tree](Segment Tree/). Can quickly compute a function over a portion of an array. - kd-Tree - [Heap](Heap/). A binary tree stored in an array, so it doesn't use pointers. Makes a great priority queue. - Fibonacci Heap -- Trie :construction: +- Trie - [B-Tree](B Tree/) :construction: -- Radix Tree :construction: ### Hashing From 764db2777501ca9490ef32d8d1ba0d4e5d92f751 Mon Sep 17 00:00:00 2001 From: Christian Encarnacion Date: Thu, 5 May 2016 14:29:45 -0400 Subject: [PATCH 0332/1679] deleted a print statement --- Trie/sources/trie.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/Trie/sources/trie.swift b/Trie/sources/trie.swift index 8e836fa1a..f2b339024 100644 --- a/Trie/sources/trie.swift +++ b/Trie/sources/trie.swift @@ -310,7 +310,6 @@ public class Trie { */ func insert(w: String) -> (word: String, inserted: Bool) { - print(w) let word = w.lowercaseString var currentNode = self.root var length = word.characters.count From 6cbc877c19129f6ec2bfd96f68bffab597cfaf71 Mon Sep 17 00:00:00 2001 From: Christian Encarnacion Date: Thu, 5 May 2016 14:54:24 -0400 Subject: [PATCH 0333/1679] Update ReadMe.md --- Trie/ReadMe.md | 72 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 71 insertions(+), 1 deletion(-) diff --git a/Trie/ReadMe.md b/Trie/ReadMe.md index edabbb994..3f7fbfa55 100644 --- a/Trie/ReadMe.md +++ b/Trie/ReadMe.md @@ -1,6 +1,76 @@ # Trie -Under Construction. +##What is a Trie? +A trie (also known as a prefix tree, or radix tree in some other (but different) implementations) is a special type of tree used to store associative data structures where the key item is normally of type String. Each node in the trie is typically not associated with a value containing strictly itself, but more so is linked to some common prefix that precedes it in levels above it. Oftentimes, true key-value pairs are associated with the leaves of the trie, but they are not limited to this. + +##Why a Trie? +Tries are very useful simply for the fact that it has some advantages over other data structures, like the binary tree or a hash map. These advantages include: +* Looking up keys is typically faster in the worst case when compared to other data structures. +* Unlike a hash map, a trie need not worry about key collisions +* No need for hasing, as each key will have a unique path in the trie +* Tries, by implementation, can be by default alphabetically ordered. + + +##Common Algorithms + +###Find (or any general lookup function) +Tries make looking up keys a trivial task, as all one has to do is walk over the nodes until we either hit a null reference or we find the key in question. + +The algorithm would be as follows: +``` + let node be the root of the trie + + for each character in the key + if the child of node with value character is null + return false (key doesn't exist in trie) + else + node = child of node with value character (move to the next node) + return true (key exists in trie and was found +``` + +And in swift: +```swift +func find(key: String) -> (node: Node?, found: Bool) { + var currentNode = self.root + + for c in key.characters { + if currentNode.children[String(c)] == nil { + return(nil, false) + } + currentNode = currentNode.children[String(c)]! + } + + return(currentNode, currentNode.isValidWord()) + } +``` + +###Insertion +Insertion is also a trivial task with a Trie, as all one needs to do is walk over the nodes until we either halt on a node that we must mark as a key, or we reach a point where we need to add extra nodes to represent it. + +Let's walk through the algorithm: + +``` + let S be the root node of our tree + let word be an array of characters of the input key + let length be the length of the key + + + find(key) + if the key was found + return false + else + + for each character in key + + + +``` + + + + + +` See also [Wikipedia](https://en.wikipedia.org/wiki/Trie). From 79555bbce692671ff55433c213282522b7474a89 Mon Sep 17 00:00:00 2001 From: Christian Encarnacion Date: Thu, 5 May 2016 16:03:23 -0400 Subject: [PATCH 0334/1679] Update ReadMe.md --- Trie/ReadMe.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/Trie/ReadMe.md b/Trie/ReadMe.md index 3f7fbfa55..63b0f3ca8 100644 --- a/Trie/ReadMe.md +++ b/Trie/ReadMe.md @@ -61,7 +61,24 @@ Let's walk through the algorithm: else for each character in key + if child node with value character does not exist + break + else + node = child node with value character + decrement length + if length != 0 + let suffix be the remaining characters in the key defined by the shortened length + + for each character in suffix + create a new node with value character and let it be the child of node + node = newly created child now + mark node as a valid key + else + mark node as valid key + + + ``` From 6dd90026d9e3db7331670bc3d6227f70c8e4d2f9 Mon Sep 17 00:00:00 2001 From: Christian Encarnacion Date: Thu, 5 May 2016 16:05:24 -0400 Subject: [PATCH 0335/1679] Update ReadMe.md --- Trie/ReadMe.md | 50 +++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 45 insertions(+), 5 deletions(-) diff --git a/Trie/ReadMe.md b/Trie/ReadMe.md index 63b0f3ca8..8181fd015 100644 --- a/Trie/ReadMe.md +++ b/Trie/ReadMe.md @@ -76,11 +76,51 @@ Let's walk through the algorithm: mark node as a valid key else mark node as valid key - - - - - +``` + +And the corresponding swift code: + +```swift + func insert(w: String) -> (word: String, inserted: Bool) { + + let word = w.lowercaseString + var currentNode = self.root + var length = word.characters.count + + if self.contains(word) { + return (w, false) + } + + var index = 0 + var c = Array(word.characters)[index] + + while let child = currentNode.children[String(c)] { + currentNode = child + length -= 1 + index += 1 + + if(length == 0) { + currentNode.isWord() + wordList.append(w) + wordCount += 1 + return (w, true) + } + + c = Array(word.characters)[index] + } + + let remainingChars = String(word.characters.suffix(length)) + for c in remainingChars.characters { + currentNode.children[String(c)] = Node(c: String(c), p: currentNode) + currentNode = currentNode.children[String(c)]! + } + + currentNode.isWord() + wordList.append(w) + wordCount += 1 + return (w, true) + } + ``` From d0a7a6df15bda32ed1771220bb8b5059621b9727 Mon Sep 17 00:00:00 2001 From: Christian Encarnacion Date: Thu, 5 May 2016 16:12:27 -0400 Subject: [PATCH 0336/1679] Update ReadMe.md --- Trie/ReadMe.md | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/Trie/ReadMe.md b/Trie/ReadMe.md index 8181fd015..33653da1a 100644 --- a/Trie/ReadMe.md +++ b/Trie/ReadMe.md @@ -123,7 +123,78 @@ And the corresponding swift code: ``` +###Removal +Removing keys from the trie is a little more tricky, as there a few more cases that we have to take into account the fact that keys may exist that are actually sub-strings of other valid keys. That being said, it isn't as simple a process to just delete the nodes for a specific key, as we could be deleting references/nodes necessary for already exisitng keys! +The algorithm would be as follows: + +``` + + let word be the key to remove + let node be the root of the trie + + find(word) + if word was not found + return false + else + + for each character in word + node = child node with value character + + if node has more than just 1 child node + Mark node as an invalid key, since removing it would remove nodes still in use + else + while node has no valid children and node is not the root node + let character = node's value + node = the parent of node + delete node's child node with value character + return true +``` + + + +and the corresponding swift code: + +```swift + func remove(w: String) -> (word: String, removed: Bool){ + let word = w.lowercaseString + + if(!self.contains(w)) { + return (w, false) + } + var currentNode = self.root + + for c in word.characters { + currentNode = currentNode.getChildAt(String(c)) + } + + if currentNode.numChildren() > 0 { + currentNode.isNotWord() + } else { + var character = currentNode.char() + while(currentNode.numChildren() == 0 && !currentNode.isRoot()) { + currentNode = currentNode.getParent() + currentNode.children[character]!.setParent(nil) + currentNode.children[character]!.update(nil) + currentNode.children[character] = nil + character = currentNode.char() + } + } + + wordCount -= 1 + + var index = 0 + for item in wordList{ + if item == w { + wordList.removeAtIndex(index) + } + index += 1 + } + + return (w, true) + } + +``` From 80f2611465dd7d65b2cb60e475d22ce2a391f73c Mon Sep 17 00:00:00 2001 From: Christian Encarnacion Date: Thu, 5 May 2016 16:18:47 -0400 Subject: [PATCH 0337/1679] Update ReadMe.md --- Trie/ReadMe.md | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/Trie/ReadMe.md b/Trie/ReadMe.md index 33653da1a..a6dd3d32f 100644 --- a/Trie/ReadMe.md +++ b/Trie/ReadMe.md @@ -51,16 +51,16 @@ Let's walk through the algorithm: ``` let S be the root node of our tree - let word be an array of characters of the input key + let word be the input key let length be the length of the key - find(key) - if the key was found + find(word) + if the word was found return false else - for each character in key + for each character in word if child node with value character does not exist break else @@ -197,10 +197,25 @@ and the corresponding swift code: ``` +###Running Times + +Let n be the length of some key in the trie + +* Find(...) : In the Worst case O(n) +* Insert(...) : O(n) +* Remove(...) : O(n) +* + +###Other Notable Operations + +* Count: Returns the number of keys in the trie ( O(1) ) +* getWords: Returns a list containing all keys in the trie ( *O(1) ) +* isEmpty: Returns true f the trie is empty, false otherwise ( *O(1) ) +* contains: Returns true if the trie has a given key, false otherwise ( O(n) ) ` -See also [Wikipedia](https://en.wikipedia.org/wiki/Trie). +See also [Wikipedia entry for Trie](https://en.wikipedia.org/wiki/Trie). *Written for the Swift Algorithm Club by Christian Encarnacion* From 285a1e932d417406cb7c6aa638efc1a7953d0ab0 Mon Sep 17 00:00:00 2001 From: Christian Encarnacion Date: Thu, 5 May 2016 16:19:22 -0400 Subject: [PATCH 0338/1679] Update ReadMe.md --- Trie/ReadMe.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Trie/ReadMe.md b/Trie/ReadMe.md index a6dd3d32f..844eb1df0 100644 --- a/Trie/ReadMe.md +++ b/Trie/ReadMe.md @@ -204,7 +204,6 @@ Let n be the length of some key in the trie * Find(...) : In the Worst case O(n) * Insert(...) : O(n) * Remove(...) : O(n) -* ###Other Notable Operations @@ -213,7 +212,7 @@ Let n be the length of some key in the trie * isEmpty: Returns true f the trie is empty, false otherwise ( *O(1) ) * contains: Returns true if the trie has a given key, false otherwise ( O(n) ) -` +`* denotes that running time may vary depending on implementation See also [Wikipedia entry for Trie](https://en.wikipedia.org/wiki/Trie). From 833bae6bb889389461adc2a254205010d8abccce Mon Sep 17 00:00:00 2001 From: axptwig Date: Thu, 5 May 2016 19:40:51 -0400 Subject: [PATCH 0339/1679] Readme Update --- Red Black Trees/README.md | 65 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 63 insertions(+), 2 deletions(-) diff --git a/Red Black Trees/README.md b/Red Black Trees/README.md index 6747154b8..85d111fa1 100644 --- a/Red Black Trees/README.md +++ b/Red Black Trees/README.md @@ -1,8 +1,69 @@ # Red Black Tree -Under Construction. +Red-black trees are an evolution of binary search trees that aim to keep the tree balanced without affecting the complexity of the primitive operations. This is done by coloring each node in the tree with either red or black and preserving a set of properties that guarantee that the deepest path in the tree is not longer than twice the shortest one. +## Motivation: +* We want a balanced binary search tree +* Height of the tree is O(log n) +* Red-Black Tree is an implementation of a balanced binary search tree -See also [Wikipedia](https://en.wikipedia.org/wiki/Red%E2%80%93black_tree). + +## Invariants: +1. Every node is colored either red or black +2. All leaf (nil) nodes are colored with black; if a node’s child is missing then we will assume that it has a nil child in that place and this nil child is always colored black. +3. Both children of a red node must be black nodes. +4. Every path from a node n to a descendent leaf has the same number of black nodes (not counting node n). + +## Methods: + +Since the red-black tree is a balanced BST, it supports the functions: + * find(key) + * Predecessor(key) + * Successor(key) + * Minimum(key) + * maximum(key) + * insert(key) + * delete(key) + +Since an insertion or deletion may violate one of the invariant's of the red-black tree we must either change colors, or perform rotation actions. + +#Rotation +To ensure that its color scheme and properties don’t get thrown off, red-black trees employ a key operation known as rotation. Rotation is a binary operation, between a parent node and one of its children, that swaps nodes and modifys their pointers while preserving the inorder traversal of the tree (so that elements are still sorted). There are two types of rotations: left rotation and right rotation. Left rotation swaps the parent node with its right child, while right rotation swaps the parent node with its left child. + +###Left-Rotation +```c++ +y ← x->right +x->right ← y->left +y->left->p ← x +y->p ← x->p +if x->p = Null + then T->root ← y + else if x = x->p->left + then x->p->left ← y + else x->p->right ← y +y->left ← x +x->p ← y +``` +###Right-Rotation +```c++ +y ← x->left +x->left ← y->right +y->right->p ← x +y->p ← x->p +if x->p = Null + then T->root ← y + else if x = x->p->right + then x->p->right ← y + else x->p->left ← y +y->right ← x +x->p ← y +``` +###Insertion +When adding a new node to a binary search tree, note that the new node will always be a leaf in the tree. To insert a new node, all we will do is navigate the BST starting from the root. If the new node value is smaller than the current node value, we go left – if it is larger, we go right. When we reach a leaf node, the last step is to attach the new node as a child to this leaf node in a way that preserves the BST constraint. We must recheck the RBTree invariants to see if any were violated + +###Deletion +The same concept behind red-black tree insertions applies here. Removing a node from a red-black tree makes use of the BST deletion procedure and then restores the red-black tree properties in O(log n). The total running time for the deletion process takes O(log n) time, then, which meets the complexity requirements for the primitive operations. + +See also [Wikipedia](https://en.wikipedia.org/wiki/Red%E2%80%93black_tree). *Written for the Swift Algorithm Club by Ashwin Raghuraman* From 9c436cc042327bef3abc7fb726334c180d0c56b6 Mon Sep 17 00:00:00 2001 From: Ashwin Date: Thu, 5 May 2016 19:51:52 -0400 Subject: [PATCH 0340/1679] bug fixes + added figures to readme --- Red Black Trees/RBTree.swift | 552 ++++++++++++++++----------------- Red Black Trees/README.md | 12 +- Red Black Trees/files/fig1.png | Bin 0 -> 24455 bytes Red Black Trees/files/fig2.png | Bin 0 -> 40534 bytes 4 files changed, 281 insertions(+), 283 deletions(-) create mode 100644 Red Black Trees/files/fig1.png create mode 100644 Red Black Trees/files/fig2.png diff --git a/Red Black Trees/RBTree.swift b/Red Black Trees/RBTree.swift index dab7e1fd8..50d1d00d4 100644 --- a/Red Black Trees/RBTree.swift +++ b/Red Black Trees/RBTree.swift @@ -21,6 +21,7 @@ public class RBTNode{ deinit{ print("Node: \(self.data) is bein deinitialized") } + public func grandparent()->RBTNode?{ if(self.parent === nil || self.parent.parent === nil){ return nil @@ -30,7 +31,7 @@ public class RBTNode{ } } public func sibling()->RBTNode?{ - if(self.parent === nil || self.parent.right === nil || self.parent.left === nil){ + if(self.parent === nil || self.parent.right === nil || self.parent.left === nil){ return nil } if(self === self.parent!.left!){ @@ -40,61 +41,60 @@ public class RBTNode{ return self.parent!.left! } } - - - } public class RBTree { - - private(set) public var root: RBTNode? - init(rootData: Int) { - root = RBTNode(rootData: rootData) - root!.color = false - } - init(){ - root = nil - } - public func depth()->Int{ - let n = depth(root!) - return n + private(set) public var root: RBTNode? + init(rootData: Int) { + root = RBTNode(rootData: rootData) + root!.color = false + } + init(){ + root = nil + } + public func depth()->Int{ + let n = depth(root!) + return n + } + private func depth(rooty:RBTNode?)->Int{ + if(rooty == nil){ + return 0 } - private func depth(rooty:RBTNode?)->Int{ - if(rooty == nil){ - return 0 - } - else{ - return 1+(max(depth(root!.left),depth(root!.right))) - } + else{ + return 1+(max(depth(root!.left),depth(root!.right))) } + } - public func inOrder(){ - inOrder(root) + public func inOrder(){ + inOrder(root) + } + private func inOrder(root: RBTNode?){ + if(self.root == nil ){ + print("The tree is empty.") } - private func inOrder(root: RBTNode?){ - if(root == nil){ - return - } - inOrder(root!.left) - print("Data: \(root!.data) Color: \(root!.color)") - inOrder(root!.right) + if(root == nil){ + return } + inOrder(root!.left) + print("Data: \(root!.data) Color: \(root!.color)") + inOrder(root!.right) + } - private func leftRotate(x: RBTNode) { - let newRoot = x.right - x.right = newRoot.left - if (newRoot.left !== nil) { - newRoot.left.parent = x - } - newRoot.parent = x.parent - if(x.parent === nil) { - root = newRoot - } else if (x === x.parent.left) { - x.parent.left = newRoot - } else { - x.parent.right = newRoot - } - newRoot.left = x - x.parent = newRoot + private func leftRotate(x: RBTNode) { + let newRoot = x.right + x.right = newRoot.left + if (newRoot.left !== nil) { + newRoot.left.parent = x + } + newRoot.parent = x.parent + if(x.parent === nil) { + root = newRoot + } else if (x === x.parent.left) { + x.parent.left = newRoot + } else { + x.parent.right = newRoot + } + newRoot.left = x + x.parent = newRoot } private func rightRotate(x: RBTNode) { let newRoot = x.left @@ -112,225 +112,241 @@ public class RBTree { } newRoot.right = x x.parent = newRoot -} - -public func insertFixup(value: Int){ - let inserted = find(value) - - if(inserted == nil){ - print("INSERTEDNILLLLLLLL") - } - print("inserted: ") - print(inserted!.data) - insertCase1(inserted) -} -private func insertCase1(inserted: RBTNode?){ - let myroot = self.root! - if myroot === inserted!{ - self.root!.color = false - print("ITS THE ROOT") - print("insert case 1: The root was nil and we inserted a black node at root") - } - insertCase2(inserted!) -} -private func insertCase2(inserted: RBTNode?){ - if inserted!.parent!.color == false{ - print("Insert case 2: parent is black so nothing to change") - return } - insertCase3(inserted!) -} -private func insertCase3(inserted: RBTNode?){ - if(inserted!.parent!.sibling() != nil && inserted!.parent!.sibling()!.color == true){ - print("insert case3: If both the parent P and the uncle U are red, then both of them can be repainted black and the grandparent G ") - inserted!.parent!.color = false - inserted!.parent!.sibling()!.color = false - let g = inserted!.grandparent - g()!.color = true - if(g()!.parent == nil){ - g()!.color = false + public func insertFixup(value: Int){ + let inserted = find(value) + print("Inserted Node: \(inserted!.data)") + insertCase1(inserted) + } + private func insertCase1(inserted: RBTNode?){ + let myroot = self.root! + if myroot === inserted!{ + self.root!.color = false + } + insertCase2(inserted!) + } + private func insertCase2(inserted: RBTNode?){ + if inserted!.parent!.color == false{ + return + } + insertCase3(inserted!) + } + private func insertCase3(inserted: RBTNode?){ + if(inserted!.parent!.sibling() != nil && + inserted!.parent!.sibling()!.color == true){ + inserted!.parent!.color = false + inserted!.parent!.sibling()!.color = false + let g = inserted!.grandparent + g()!.color = true + if(g()!.parent == nil){ + g()!.color = false + } } - } insertCase4(inserted) -} - -private func insertCase4(var inserted: RBTNode?){ - if((inserted! === inserted!.parent!.right) && (inserted!.grandparent()!.left === inserted!.parent!)){ - print("case 4") - leftRotate(inserted!.parent) - inserted! = inserted!.left } - else if((inserted! === inserted!.parent!.left) && (inserted!.grandparent()!.right === inserted!.parent!)){ - print("case 4") - rightRotate(inserted!.parent) - inserted! = inserted!.right + + private func insertCase4( insert: RBTNode?){ + var inserted = insert + if((inserted! === inserted!.parent!.right) && + (inserted!.grandparent()!.left === inserted!.parent!)){ + + leftRotate(inserted!.parent) + inserted! = inserted!.left + } + else if((inserted! === inserted!.parent!.left) && + (inserted!.grandparent()!.right === inserted!.parent!)){ + + rightRotate(inserted!.parent) + inserted! = inserted!.right + } + insertCase5(inserted) } - insertCase5(inserted) -} -private func insertCase5(inserted: RBTNode?){ - if((inserted!.parent!.color == true && (inserted!.parent!.sibling()?.color == false || inserted!.parent!.sibling() == nil ))){ - if(inserted! === inserted!.parent!.left && inserted!.grandparent()!.left === inserted!.parent!){ - print("insert case 5: The parent P is red but the uncle U is black/nil, the current node N is the left child of P, and P is the left child of its parent G") - inserted!.parent.color = false - inserted!.grandparent()?.color = true - if(inserted! === inserted!.parent!.left){ - print("its on the left") - rightRotate(inserted!.grandparent()!) - } - } - else if(inserted! === inserted!.parent!.right && inserted!.grandparent()!.right === inserted!.parent!){ - print("insert case 5: RIGHT RIGHT") - inserted!.parent.color = false - inserted!.grandparent()?.color = true + private func insertCase5(inserted: RBTNode?){ + if((inserted!.parent!.color == true && + (inserted!.parent!.sibling()?.color == false || + inserted!.parent!.sibling() == nil ))){ - print("Its on the right") + if(inserted! === inserted!.parent!.left && inserted!.grandparent()!.left === inserted!.parent!){ + inserted!.parent.color = false + inserted!.grandparent()?.color = true + if(inserted! === inserted!.parent!.left){ + rightRotate(inserted!.grandparent()!) + } + } + else if(inserted! === inserted!.parent!.right && inserted!.grandparent()!.right === inserted!.parent!){ + inserted!.parent.color = false + inserted!.grandparent()?.color = true leftRotate(inserted!.grandparent()!) - } + } + } } - print("weve reached the end boys") -} - public func insert(value: Int) { - insert(value, parent: root!) - insertFixup(value) - } - private func insert(value: Int, parent: RBTNode) { - if self.root == nil{ - self.root = RBTNode(rootData: value) - return + public func insert(value: Int) { + insert(value, parent: root!) + insertFixup(value) + } + private func insert(value: Int, parent: RBTNode) { + if self.root == nil{ + self.root = RBTNode(rootData: value) + return + } + else if value < parent.data { + if let left = parent.left { + insert(value, parent: left) + } else { + parent.left = RBTNode(rootData: value) + parent.left?.parent = parent } - else if value < parent.data { - if let left = parent.left { - insert(value, parent: left) - } else { - parent.left = RBTNode(rootData: value) - parent.left?.parent = parent - } + } else { + if let right = parent.right { + insert(value, parent: right) } else { - if let right = parent.right { - insert(value, parent: right) - } else { - parent.right = RBTNode(rootData: value) - parent.right?.parent = parent - } + parent.right = RBTNode(rootData: value) + parent.right?.parent = parent } } - public func find(data: Int)->RBTNode?{ - return find(root!,data: data) - } - - private func find(root: RBTNode, data: Int)->RBTNode?{ - if data == root.data{ - return root - } - if root.data != data && root.right == nil && root.left == nil { - return nil - } - else if data > root.data{ - return find(root.right, data: data) - } - else if data < root.data{ - return find(root.left, data: data) - } - else{ - return nil - } - } + } + public func find(data: Int)->RBTNode?{ + return find(root!,data: data) + } - //DELETION HELPER FUNCTIONS - public func remove(value: Int){ - let toRemove = find(value) - if(toRemove == nil){ - return - } - } - public func replaceNode(n1: RBTNode, n2: RBTNode){ - var temp = n1.data - var temp_color = n1.color - n1.data = n2.data - n1.color = n2.color - n2.data = temp - n2.color = temp_color - } - public func minimum(var node: RBTNode)->RBTNode { - while node.left !== nil{ - node = node.left + private func find(root: RBTNode, data: Int)->RBTNode?{ + if data == root.data{ + return root } - return node - } - public func successor(var node: RBTNode) -> RBTNode? { - if node.right !== nil { - return minimum(node.right) + if root.data != data && root.right == nil && root.left == nil { + return nil } - var successor = node.parent - while successor !== nil && node === successor.right { - node = successor - successor = successor.parent + else if data > root.data{ + return find(root.right, data: data) } - return successor - } - public func predecessor(var node: RBTNode) -> RBTNode{ - if node.left !== nil { - return minimum(node.left) + else if data < root.data{ + return find(root.left, data: data) } - var successor = node.parent - while successor !== nil && node === successor.left { - node = successor - successor = successor.parent + else{ + return nil } - return successor - } - public func maximum(var rootNode: RBTNode) -> RBTNode{ - while rootNode.right !== nil { - rootNode = rootNode.right + } + + //DELETION HELPER FUNCTIONS + public func remove(value: Int){ + let toRemove = find(value) + if(toRemove == nil){ + return } - return rootNode + } + public func replaceNode(n1: RBTNode, n2: RBTNode){ + let temp = n1.data + let temp_color = n1.color + n1.data = n2.data + n1.color = n2.color + n2.data = temp + n2.color = temp_color + } + public func minimum(Node: RBTNode)->RBTNode { + var node = Node + while node.left !== nil{ + node = node.left + } + return node + } + public func successor(Node: RBTNode) -> RBTNode? { + var node = Node + if node.right !== nil { + return minimum(node.right) + } + var successor = node.parent + while successor !== nil && node === successor.right { + node = successor + successor = successor.parent + } + return successor + } + public func predecessor(Node: RBTNode) -> RBTNode{ + var node = Node + if node.left !== nil { + return minimum(node.left) } - private func deletionFixup(x: RBTNode) {} + var successor = node.parent + while successor !== nil && node === successor.left { + node = successor + successor = successor.parent + } + return successor + } + public func maximum(rootnode: RBTNode) -> RBTNode{ + var rootNode = rootnode + while rootNode.right !== nil { + rootNode = rootNode.right + } + return rootNode + } public func delete(x: Int){ let toDel = find(x) deleteNode(toDel!) } - private func deleteNode(var toDel: RBTNode?){ - print("DELETE CASE 0") - if(toDel!.left == nil && toDel!.right == nil && toDel!.color == true){ - print("IM IN HERE") - //DEINIT NOT BEING CALLED AGAIN? + private func deleteNode(todel: RBTNode?){ + var toDel = todel + if(toDel!.left === nil && toDel!.right === nil && toDel!.parent === nil){ toDel = nil + self.root = nil + return + } + if(toDel!.left === nil && toDel!.right === nil && toDel!.color == true){ + if(toDel!.parent.left === toDel!){ + toDel!.parent.left = nil + toDel = nil + } + else if(toDel!.parent === nil){ + toDel = nil + } + else{ + toDel?.parent.right = nil + toDel = nil + } return } if(toDel!.left !== nil && toDel!.right !== nil){ - var pred = maximum(toDel!.left!) + let pred = maximum(toDel!.left!) toDel!.data = pred.data toDel! = pred } - var child: RBTNode? = nil + var child: RBTNode? = nil if(toDel!.right === nil){ child = toDel!.left } else{ child = toDel!.right } - - if(toDel!.color == false){ + if(toDel!.color == false && child !== nil){ toDel!.color = child!.color deleteCase1(toDel!) } if(child !== nil){ replaceNode(toDel!, n2: child!) - if(toDel!.parent === nil && child !== nil){ child!.color = false } } - print("This statement isnt actually deleting the object??? V") - toDel = nil + if(toDel!.parent.left === toDel!){ + toDel!.parent.left = nil + toDel = nil + return + } + else if(toDel!.parent === nil){ + toDel = nil + return + } + else{ + toDel?.parent.right = nil + toDel = nil + return + } } - private func deleteCase1(var toDel: RBTNode?){ - print("DELETE CASE 1") + private func deleteCase1( toDel: RBTNode?){ if(toDel?.parent === nil){ return } @@ -338,9 +354,8 @@ private func insertCase5(inserted: RBTNode?){ deleteCase2(toDel) } } - private func deleteCase2(var toDel: RBTNode?){ - print("DELETE CASE 2") - var sibling = toDel!.sibling() + private func deleteCase2(toDel: RBTNode?){ + let sibling = toDel!.sibling() if(sibling?.color == true){ toDel!.parent.color = true; sibling?.color = false @@ -353,9 +368,12 @@ private func insertCase5(inserted: RBTNode?){ deleteCase3(toDel!) } } - private func deleteCase3(var toDel: RBTNode?){ - print("DELETE CASE 3") - if(toDel!.parent?.color == false && toDel!.sibling()?.color == false && toDel!.sibling()?.left!.color == false && toDel!.sibling()?.right!.color == false){ + private func deleteCase3(toDel: RBTNode?){ + if(toDel!.parent?.color == false && + toDel!.sibling()?.color == false && + toDel!.sibling()?.left!.color == false && + toDel!.sibling()?.right!.color == false){ + toDel!.sibling()?.color = true toDel!.parent?.color = false } @@ -363,31 +381,41 @@ private func insertCase5(inserted: RBTNode?){ deleteCase4(toDel) } } - private func deleteCase4(var toDel: RBTNode?){ - print("DELETE CASE 4") - if(toDel!.parent?.color == true && toDel!.sibling()?.color == false && toDel!.sibling()?.left!.color == false && toDel!.sibling()?.right!.color == false){ - toDel!.sibling()?.color = true - toDel!.parent.color = false + private func deleteCase4(toDel: RBTNode?){ + if(toDel!.parent?.color == true && + toDel!.sibling()?.color == false && + toDel!.sibling()?.left!.color == false && + toDel!.sibling()?.right!.color == false){ + + toDel!.sibling()?.color = true + toDel!.parent.color = false } else{ deleteCase5(toDel) } } - private func deleteCase5(var toDel:RBTNode?){ - print("DELETE CASE 5") - if(toDel! === toDel!.parent?.left && toDel!.sibling()?.color == false && toDel!.sibling()?.left.color == true && toDel!.sibling()?.right.color == false){ - toDel!.sibling()?.color = true - toDel!.sibling()?.left?.color = false - rightRotate(toDel!.sibling()!) + private func deleteCase5(toDel:RBTNode?){ + if(toDel! === toDel!.parent?.left && + toDel!.sibling()?.color == false && + toDel!.sibling()?.left.color == true && + toDel!.sibling()?.right.color == false){ + + toDel!.sibling()?.color = true + toDel!.sibling()?.left?.color = false + rightRotate(toDel!.sibling()!) } - else if(toDel! === toDel!.parent?.right && toDel!.sibling()?.color == false && toDel!.sibling()?.left.color == false && toDel!.sibling()?.right.color == true){ - toDel!.sibling()?.color = true - toDel!.sibling()?.right?.color = false - leftRotate(toDel!.sibling()!) + + else if(toDel! === toDel!.parent?.right && + toDel!.sibling()?.color == false && + toDel!.sibling()?.left.color == false && + toDel!.sibling()?.right.color == true){ + + toDel!.sibling()?.color = true + toDel!.sibling()?.right?.color = false + leftRotate(toDel!.sibling()!) } } - private func deleteCase6(var toDel: RBTNode?){ - print("DELETE CASE 6") + private func deleteCase6(toDel: RBTNode?){ let color = toDel!.sibling()?.color toDel!.parent?.color = color! toDel!.parent?.color = false @@ -402,43 +430,13 @@ private func insertCase5(inserted: RBTNode?){ } } - - var tree = RBTree(rootData: 8) - -tree.insert(6) -tree.delete(6) +tree.insert(5) +tree.insert(4) +tree.insert(9) +tree.delete(9) +tree.insert(3) +tree.insert(10) +tree.delete(3) +var x = tree.find(5) tree.inOrder() -print("_______") - - - -//print("_________________________") -//let x = tree.root! -//print("sibling: \(tree.root!.left!.sibling()!.data)") -//print("root: \(tree.root!.data)") -//tree.rightRotate(x) -//print("root: \(tree.root!.data)") -//tree.inOrder() - -//let l = tree.root!.left! -//let r = tree.root!.right! -//print(l.data) -//print(r.data) -//if tree.root!.parent == nil{ -// print("ASDASD") -//} - -//how you access certain elements -//let root = tree.root!.left! -//if(root.parent === nil){ -// print("nil") -//} -//else{ -// print(root.parent.data) -//} - -//print(tree.root!.data) -//print(tree.root!.right!.data) -//print(tree.root!.left!.data) - diff --git a/Red Black Trees/README.md b/Red Black Trees/README.md index 85d111fa1..dae7c4d62 100644 --- a/Red Black Trees/README.md +++ b/Red Black Trees/README.md @@ -1,5 +1,5 @@ # Red Black Tree - +![fig1](Images/fig1.png) Red-black trees are an evolution of binary search trees that aim to keep the tree balanced without affecting the complexity of the primitive operations. This is done by coloring each node in the tree with either red or black and preserving a set of properties that guarantee that the deepest path in the tree is not longer than twice the shortest one. ## Motivation: * We want a balanced binary search tree @@ -28,8 +28,8 @@ Since an insertion or deletion may violate one of the invariant's of the red-bla #Rotation To ensure that its color scheme and properties don’t get thrown off, red-black trees employ a key operation known as rotation. Rotation is a binary operation, between a parent node and one of its children, that swaps nodes and modifys their pointers while preserving the inorder traversal of the tree (so that elements are still sorted). There are two types of rotations: left rotation and right rotation. Left rotation swaps the parent node with its right child, while right rotation swaps the parent node with its left child. - -###Left-Rotation +![fig2](Images/fig2.png) +###Left-Rotation: ```c++ y ← x->right x->right ← y->left @@ -43,7 +43,7 @@ if x->p = Null y->left ← x x->p ← y ``` -###Right-Rotation +###Right-Rotation: ```c++ y ← x->left x->left ← y->right @@ -57,10 +57,10 @@ if x->p = Null y->right ← x x->p ← y ``` -###Insertion +###Insertion: When adding a new node to a binary search tree, note that the new node will always be a leaf in the tree. To insert a new node, all we will do is navigate the BST starting from the root. If the new node value is smaller than the current node value, we go left – if it is larger, we go right. When we reach a leaf node, the last step is to attach the new node as a child to this leaf node in a way that preserves the BST constraint. We must recheck the RBTree invariants to see if any were violated -###Deletion +###Deletion: The same concept behind red-black tree insertions applies here. Removing a node from a red-black tree makes use of the BST deletion procedure and then restores the red-black tree properties in O(log n). The total running time for the deletion process takes O(log n) time, then, which meets the complexity requirements for the primitive operations. See also [Wikipedia](https://en.wikipedia.org/wiki/Red%E2%80%93black_tree). diff --git a/Red Black Trees/files/fig1.png b/Red Black Trees/files/fig1.png new file mode 100644 index 0000000000000000000000000000000000000000..7a91eb6932feddfc00890e16aeec6e1a079a75b9 GIT binary patch literal 24455 zcmagGcRbeb8$Nu8kgSTxULkullo1h1N=B)WJ<7}`AuB~lM)pV~WMw9+j3}WZdyhg$ z**u5O@Av)VdH#94KCkb$yKe9M{l2dAI?v-c&f~m;H7=@9Q7};u2n4Egs!Ey!0?}Rk z`4>46{`an9Unl;L*zwFcZE|w*-r-9_cuDJYR@X_(&fLk>=#Cjd%hK7&$?T5F{V#h6 z1P;PEB?WD_o|!~fJ+0>DWxgc?qCLJ}9%-MAcya#$2ZuTd18s{45rwX+&F!u?GuOKe zYDDf+9kk-g^GV}MMfG^y2zr{!{zk>YPJwZ*G~CNxDjuyMAtcCYkJ) z-fl@C@|EYHC0`%*)hGP-r=u0L^70$n+v$F+e1j$LL>FiT{_lfy z?0g_4DaF;RSO2@>A=P{Lwu&s;7^NSPYFxYK{%_`5w=*p{3qPZVj*j!zhI_X&mUF9q zVYKn~ty>!ORyH;PJL^dN;Q{f7XOb3%T?*-YS82l7Pd8{}7Zem^XH)!R+qqxTqeqX{ z_!2ScH+fsy*)?ipzk0RTNM<()(W(*I!@0RR(VOpT2K#_t5>grWOlbTHuCZDxh_pz z7QK9#mVUR$&A@(A-w?Z=-d=VYH(Gjnoom-lT6|`qp$Xe_fOl+cjDv~)?c3`&Zs6${ z+1YRE>RQ^`&W(&nc&#}Z7#MUHe3{znzPn1av8iCpMN9WwgP-qG((^V8Y!faSupN}1 zKI%(Mw)MNIf9#k&ELCN>ltmKu~b`hVwefw2b z))X!AhwT*2m)QT1&`|YDm#$v9;^N{`Qd$~xLmM9%?&L}=EltZrvE{jynUj-~pPye* zaa~hWQ%6TfMa9DKWw~SRGfBgmNi0}vM|U?P0|Ns+{kNW;pLnF<;nb|GrZQD4tLe{) z(l@K`3G?#0tSwEy)XIG97L%5i*4^EWy(1#b%+BiT>3#kB)o@ZVeZ4;4oGSJ>m5|

q7zm>s!5PTkV3Z-KO*PT7hR9fqhuf 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 ZtP#NR0LKFy4_MKF=La|*{Qrdq{|k=tr6~Xa literal 0 HcmV?d00001 diff --git a/Huffman Coding/Images/Compression.graffle b/Huffman Coding/Images/Compression.graffle new file mode 100644 index 0000000000000000000000000000000000000000..81920ac70587bc3bac22df5ec0451d6afe321f02 GIT binary patch literal 4299 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 literal 0 HcmV?d00001 diff --git a/Huffman Coding/Images/Compression.png b/Huffman Coding/Images/Compression.png new file mode 100644 index 0000000000000000000000000000000000000000..924e899aa17161d5991d9936ac75468db9668d2a GIT binary patch literal 54972 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